Add ModelPrefab to imported model prefab for reimporting functionality
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using FlaxEditor.Content;
|
||||
using FlaxEditor.CustomEditors.Editors;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
using FlaxEngine.Tools;
|
||||
|
||||
namespace FlaxEditor.CustomEditors.Dedicated;
|
||||
|
||||
/// <summary>
|
||||
/// The missing script editor.
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(ModelPrefab)), DefaultEditor]
|
||||
public class ModelPrefabEditor : GenericEditor
|
||||
{
|
||||
private Guid _prefabId;
|
||||
private Button _reimportButton;
|
||||
private string _importPath;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Initialize(LayoutElementsContainer layout)
|
||||
{
|
||||
base.Initialize(layout);
|
||||
|
||||
var modelPrefab = Values[0] as ModelPrefab;
|
||||
if (modelPrefab == null)
|
||||
return;
|
||||
_prefabId = modelPrefab.PrefabID;
|
||||
while (true)
|
||||
{
|
||||
var prefab = FlaxEngine.Content.Load<Prefab>(_prefabId);
|
||||
if (prefab)
|
||||
{
|
||||
var prefabObjectId = modelPrefab.PrefabObjectID;
|
||||
var prefabObject = prefab.GetDefaultInstance(ref prefabObjectId);
|
||||
if (prefabObject.PrefabID == _prefabId)
|
||||
break;
|
||||
_prefabId = prefabObject.PrefabID;
|
||||
}
|
||||
}
|
||||
|
||||
var button = layout.Button("Reimport", "Reimports the source asset as prefab.");
|
||||
_reimportButton = button.Button;
|
||||
_reimportButton.Clicked += OnReimport;
|
||||
}
|
||||
|
||||
private void OnReimport()
|
||||
{
|
||||
var prefab = FlaxEngine.Content.Load<Prefab>(_prefabId);
|
||||
var modelPrefab = (ModelPrefab)Values[0];
|
||||
var importPath = modelPrefab.ImportPath;
|
||||
var editor = Editor.Instance;
|
||||
if (editor.ContentImporting.GetReimportPath("Model Prefab", ref importPath))
|
||||
return;
|
||||
var folder = editor.ContentDatabase.Find(Path.GetDirectoryName(prefab.Path)) as ContentFolder;
|
||||
if (folder == null)
|
||||
return;
|
||||
var importOptions = modelPrefab.ImportOptions;
|
||||
importOptions.Type = ModelTool.ModelType.Prefab;
|
||||
_importPath = importPath;
|
||||
_reimportButton.Enabled = false;
|
||||
editor.ContentImporting.ImportFileEnd += OnImportFileEnd;
|
||||
editor.ContentImporting.Import(importPath, folder, true, importOptions);
|
||||
}
|
||||
|
||||
private void OnImportFileEnd(IFileEntryAction entry, bool failed)
|
||||
{
|
||||
if (entry.SourceUrl == _importPath)
|
||||
{
|
||||
// Restore button
|
||||
_importPath = null;
|
||||
_reimportButton.Enabled = true;
|
||||
Editor.Instance.ContentImporting.ImportFileEnd -= OnImportFileEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,6 @@ namespace FlaxEditor.CustomEditors
|
||||
{
|
||||
if (instanceValues == null || instanceValues.Count != Count)
|
||||
throw new ArgumentException();
|
||||
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
var v = instanceValues[i];
|
||||
|
||||
@@ -126,29 +126,35 @@ namespace FlaxEditor.Modules
|
||||
{
|
||||
if (item != null && !item.GetImportPath(out string importPath))
|
||||
{
|
||||
// Check if input file is missing
|
||||
if (!System.IO.File.Exists(importPath))
|
||||
{
|
||||
Editor.LogWarning(string.Format("Cannot reimport asset \'{0}\'. File \'{1}\' does not exist.", item.Path, importPath));
|
||||
if (skipSettingsDialog)
|
||||
return;
|
||||
|
||||
// Ask user to select new file location
|
||||
var title = string.Format("Please find missing \'{0}\' file for asset \'{1}\'", importPath, item.ShortName);
|
||||
if (FileSystem.ShowOpenFileDialog(Editor.Windows.MainWindow, null, "All files (*.*)\0*.*\0", false, title, out var files))
|
||||
return;
|
||||
if (files != null && files.Length > 0)
|
||||
importPath = files[0];
|
||||
|
||||
// Validate file path again
|
||||
if (!System.IO.File.Exists(importPath))
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetReimportPath(item.ShortName, ref importPath, skipSettingsDialog))
|
||||
return;
|
||||
Import(importPath, item.Path, true, skipSettingsDialog, settings);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool GetReimportPath(string contextName, ref string importPath, bool skipSettingsDialog = false)
|
||||
{
|
||||
// Check if input file is missing
|
||||
if (!System.IO.File.Exists(importPath))
|
||||
{
|
||||
Editor.LogWarning(string.Format("Cannot reimport asset \'{0}\'. File \'{1}\' does not exist.", contextName, importPath));
|
||||
if (skipSettingsDialog)
|
||||
return true;
|
||||
|
||||
// Ask user to select new file location
|
||||
var title = string.Format("Please find missing \'{0}\' file for asset \'{1}\'", importPath, contextName);
|
||||
if (FileSystem.ShowOpenFileDialog(Editor.Windows.MainWindow, null, "All files (*.*)\0*.*\0", false, title, out var files))
|
||||
return true;
|
||||
if (files != null && files.Length > 0)
|
||||
importPath = files[0];
|
||||
|
||||
// Validate file path again
|
||||
if (!System.IO.File.Exists(importPath))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imports the specified files.
|
||||
/// </summary>
|
||||
|
||||
@@ -165,20 +165,7 @@ bool CreateAssetContext::AllocateChunk(int32 index)
|
||||
void CreateAssetContext::AddMeta(JsonWriter& writer) const
|
||||
{
|
||||
writer.JKEY("ImportPath");
|
||||
if (AssetsImportingManager::UseImportPathRelative && !FileSystem::IsRelative(InputPath)
|
||||
#if PLATFORM_WINDOWS
|
||||
// Import path from other drive should be stored as absolute on Windows to prevent issues
|
||||
&& InputPath.Length() > 2 && Globals::ProjectFolder.Length() > 2 && InputPath[0] == Globals::ProjectFolder[0]
|
||||
#endif
|
||||
)
|
||||
{
|
||||
const String relativePath = FileSystem::ConvertAbsolutePathToRelative(Globals::ProjectFolder, InputPath);
|
||||
writer.String(relativePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.String(InputPath);
|
||||
}
|
||||
writer.String(AssetsImportingManager::GetImportPath(InputPath));
|
||||
writer.JKEY("ImportUsername");
|
||||
writer.String(Platform::GetUserName());
|
||||
}
|
||||
@@ -304,6 +291,20 @@ bool AssetsImportingManager::ImportIfEdited(const StringView& inputPath, const S
|
||||
return false;
|
||||
}
|
||||
|
||||
String AssetsImportingManager::GetImportPath(const String& path)
|
||||
{
|
||||
if (UseImportPathRelative && !FileSystem::IsRelative(path)
|
||||
#if PLATFORM_WINDOWS
|
||||
// Import path from other drive should be stored as absolute on Windows to prevent issues
|
||||
&& path.Length() > 2 && Globals::ProjectFolder.Length() > 2 && path[0] == Globals::ProjectFolder[0]
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return FileSystem::ConvertAbsolutePathToRelative(Globals::ProjectFolder, path);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
bool AssetsImportingManager::Create(const Function<CreateAssetResult(CreateAssetContext&)>& callback, const StringView& inputPath, const StringView& outputPath, Guid& assetId, void* arg)
|
||||
{
|
||||
PROFILE_CPU();
|
||||
|
||||
@@ -236,6 +236,9 @@ public:
|
||||
return ImportIfEdited(inputPath, outputPath, id, arg);
|
||||
}
|
||||
|
||||
// Converts source files path into the relative format if enabled by the project settings. Result path can be stored in asset for reimports.
|
||||
static String GetImportPath(const String& path);
|
||||
|
||||
private:
|
||||
static bool Create(const CreateAssetFunction& callback, const StringView& inputPath, const StringView& outputPath, Guid& assetId, void* arg);
|
||||
};
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "Engine/Level/Actors/StaticModel.h"
|
||||
#include "Engine/Level/Prefabs/Prefab.h"
|
||||
#include "Engine/Level/Prefabs/PrefabManager.h"
|
||||
#include "Engine/Level/Scripts/ModelPrefab.h"
|
||||
#include "Engine/Platform/FileSystem.h"
|
||||
#include "Engine/Utilities/RectPack.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
@@ -699,7 +700,26 @@ CreateAssetResult ImportModel::CreatePrefab(CreateAssetContext& context, ModelDa
|
||||
}
|
||||
}
|
||||
ASSERT_LOW_LAYER(rootActor);
|
||||
// TODO: add PrefabModel script for asset reimporting
|
||||
{
|
||||
// Add script with import options
|
||||
auto* modelPrefabScript = New<ModelPrefab>();
|
||||
modelPrefabScript->SetParent(rootActor);
|
||||
modelPrefabScript->ImportPath = AssetsImportingManager::GetImportPath(context.InputPath);
|
||||
modelPrefabScript->ImportOptions = options;
|
||||
|
||||
// Link with existing prefab instance
|
||||
if (prefab)
|
||||
{
|
||||
for (const auto& i : prefab->ObjectsCache)
|
||||
{
|
||||
if (i.Value->GetTypeHandle() == modelPrefabScript->GetTypeHandle())
|
||||
{
|
||||
modelPrefabScript->LinkPrefab(i.Value->GetPrefabID(), i.Value->GetPrefabObjectID());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create prefab instead of native asset
|
||||
bool failed;
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
#if !BUILD_RELEASE || USE_EDITOR
|
||||
#include "Engine/Level/Level.h"
|
||||
#include "Engine/Threading/Threading.h"
|
||||
#include "Engine/Level/Components/MissingScript.h"
|
||||
#include "Engine/Level/Scripts/MissingScript.h"
|
||||
#endif
|
||||
#include "Engine/Level/Scripts/ModelPrefab.h"
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
@@ -46,6 +47,11 @@ void MissingScript::SetReferenceScript(const ScriptingObjectReference<Script>& v
|
||||
|
||||
#endif
|
||||
|
||||
ModelPrefab::ModelPrefab(const SpawnParams& params)
|
||||
: Script(params)
|
||||
{
|
||||
}
|
||||
|
||||
SceneObjectsFactory::Context::Context(ISerializeModifier* modifier)
|
||||
: Modifier(modifier)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Scripting/Script.h"
|
||||
#if USE_EDITOR
|
||||
#include "Engine/Tools/ModelTool/ModelTool.h"
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Actor script component that handled model prefabs importing and setup.
|
||||
/// </summary>
|
||||
API_CLASS(Attributes="HideInEditor") class FLAXENGINE_API ModelPrefab : public Script
|
||||
{
|
||||
API_AUTO_SERIALIZATION();
|
||||
DECLARE_SCRIPTING_TYPE(ModelPrefab);
|
||||
|
||||
#if USE_EDITOR
|
||||
/// <summary>
|
||||
/// Source model file path (absolute or relative to the project).
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="ReadOnly") String ImportPath;
|
||||
|
||||
/// <summary>
|
||||
/// Model file import settings.
|
||||
/// </summary>
|
||||
API_FIELD() ModelTool::Options ImportOptions;
|
||||
#endif
|
||||
};
|
||||
Reference in New Issue
Block a user