From ad8bec40bbab560775bb8019c70b5b5da112a170 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Wed, 10 Apr 2024 05:04:36 -0400 Subject: [PATCH 1/7] Add creating particle systems from particle emitters. --- .../Content/Proxy/ParticleEmitterProxy.cs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/Source/Editor/Content/Proxy/ParticleEmitterProxy.cs b/Source/Editor/Content/Proxy/ParticleEmitterProxy.cs index 8c1204128..9ac4d698c 100644 --- a/Source/Editor/Content/Proxy/ParticleEmitterProxy.cs +++ b/Source/Editor/Content/Proxy/ParticleEmitterProxy.cs @@ -3,6 +3,9 @@ using System; using FlaxEditor.Content.Create; using FlaxEditor.Content.Thumbnails; +using FlaxEditor.GUI.ContextMenu; +using FlaxEditor.GUI.Timeline; +using FlaxEditor.GUI.Timeline.Tracks; using FlaxEditor.Viewport.Previews; using FlaxEditor.Windows; using FlaxEditor.Windows.Assets; @@ -48,6 +51,59 @@ namespace FlaxEditor.Content Editor.Instance.ContentImporting.Create(new ParticleEmitterCreateEntry(outputPath)); } + /// + public override void OnContentWindowContextMenu(ContextMenu menu, ContentItem item) + { + base.OnContentWindowContextMenu(menu, item); + + if (item is BinaryAssetItem binaryAssetItem) + { + var button = menu.AddButton("Create Particle System", CreateParticleSystemClicked); + button.Tag = binaryAssetItem; + } + } + + private void CreateParticleSystemClicked(ContextMenuButton obj) + { + var binaryAssetItem = (BinaryAssetItem)obj.Tag; + CreateParticleSystem(binaryAssetItem); + } + + /// + /// Creates the particle system from the given particle emitter. + /// + /// The particle emitter item to use as a base for the particle system. + public static void CreateParticleSystem(BinaryAssetItem emitterItem) + { + var particleSystemName = emitterItem.ShortName + " Particle System"; + var particleSystemProxy = Editor.Instance.ContentDatabase.GetProxy(); + Editor.Instance.Windows.ContentWin.NewItem(particleSystemProxy, null, item => OnParticleSystemCreated(item, emitterItem), particleSystemName); + } + + private static void OnParticleSystemCreated(ContentItem item, BinaryAssetItem particleItem) + { + var assetItem = (AssetItem)item; + var particleSystem = FlaxEngine.Content.LoadAsync(assetItem.ID); + if (particleSystem == null || particleSystem.WaitForLoaded()) + { + Editor.LogError("Failed to load created particle system."); + return; + } + + ParticleEmitter emitter = FlaxEngine.Content.LoadAsync(particleItem.ID); + + ParticleSystemPreview tempPreview = new ParticleSystemPreview(false); + ParticleSystemTimeline timeline = new ParticleSystemTimeline(tempPreview); + timeline.Load(particleSystem); + + var track = (ParticleEmitterTrack)timeline.NewTrack(ParticleEmitterTrack.GetArchetype()); + track.Asset = emitter; + track.TrackMedia.DurationFrames = timeline.DurationFrames; + track.Rename(particleItem.ShortName); + timeline.AddTrack(track); + timeline.Save(particleSystem); + } + /// public override void OnThumbnailDrawPrepare(ThumbnailRequest request) { From 48400ff5cea79ae637e602508def16e2830594b2 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Wed, 10 Apr 2024 16:26:29 -0400 Subject: [PATCH 2/7] Add better error handling to particle system creation. Add skinned model -> animation graph workflow, though a bit hacky. --- .../Content/Proxy/ParticleEmitterProxy.cs | 4 ++ .../Editor/Content/Proxy/SkinnedModelProxy.cs | 55 +++++++++++++++++++ .../Windows/Assets/AnimationGraphWindow.cs | 9 +++ 3 files changed, 68 insertions(+) diff --git a/Source/Editor/Content/Proxy/ParticleEmitterProxy.cs b/Source/Editor/Content/Proxy/ParticleEmitterProxy.cs index 9ac4d698c..be2530efa 100644 --- a/Source/Editor/Content/Proxy/ParticleEmitterProxy.cs +++ b/Source/Editor/Content/Proxy/ParticleEmitterProxy.cs @@ -91,6 +91,10 @@ namespace FlaxEditor.Content } ParticleEmitter emitter = FlaxEngine.Content.LoadAsync(particleItem.ID); + if (emitter == null || emitter.WaitForLoaded()) + { + Editor.LogError("Failed to load base particle emitter."); + } ParticleSystemPreview tempPreview = new ParticleSystemPreview(false); ParticleSystemTimeline timeline = new ParticleSystemTimeline(tempPreview); diff --git a/Source/Editor/Content/Proxy/SkinnedModelProxy.cs b/Source/Editor/Content/Proxy/SkinnedModelProxy.cs index e05ca80d9..97e423a2d 100644 --- a/Source/Editor/Content/Proxy/SkinnedModelProxy.cs +++ b/Source/Editor/Content/Proxy/SkinnedModelProxy.cs @@ -2,6 +2,10 @@ using System; using FlaxEditor.Content.Thumbnails; +using FlaxEditor.GUI.ContextMenu; +using FlaxEditor.GUI.Docking; +using FlaxEditor.Options; +using FlaxEditor.Surface; using FlaxEditor.Viewport.Previews; using FlaxEditor.Windows; using FlaxEditor.Windows.Assets; @@ -39,6 +43,57 @@ namespace FlaxEditor.Content /// public override Type AssetType => typeof(SkinnedModel); + /// + public override void OnContentWindowContextMenu(ContextMenu menu, ContentItem item) + { + base.OnContentWindowContextMenu(menu, item); + + if (item is BinaryAssetItem binaryAssetItem) + { + var button = menu.AddButton("Create Animation Graph", CreateAnimationGraphClicked); + button.Tag = binaryAssetItem; + } + } + + private void CreateAnimationGraphClicked(ContextMenuButton obj) + { + var binaryAssetItem = (BinaryAssetItem)obj.Tag; + CreateAnimationGraph(binaryAssetItem); + } + + /// + /// Creates the animation graph from the given particle emitter. + /// + /// The skinned model item to use as the base model for the animation graph. + public static void CreateAnimationGraph(BinaryAssetItem skinnedModelItem) + { + var animationGraphName = skinnedModelItem.ShortName + " Graph"; + var animationGraphProxy = Editor.Instance.ContentDatabase.GetProxy(); + Editor.Instance.Windows.ContentWin.NewItem(animationGraphProxy, null, item => OnAnimationGraphCreated(item, skinnedModelItem), animationGraphName); + } + + private static void OnAnimationGraphCreated(ContentItem item, BinaryAssetItem skinnedModelItem) + { + var skinnedModel = FlaxEngine.Content.LoadAsync(skinnedModelItem.ID); + if (skinnedModel == null || skinnedModel.WaitForLoaded()) + { + Editor.LogError("Failed to load base skinned model."); + } + + // Hack the animation graph window to modify the base model of the animation graph. + AnimationGraphWindow win = new AnimationGraphWindow(Editor.Instance, item as AssetItem); + win.Show(); + + // Ensure the window knows the asset is loaded so we can save it later. + win.Asset.WaitForLoaded(); + win.Update(0); // Call Update() to refresh the loaded flag. + + win.SetBaseModel(skinnedModel); + win.Surface.MarkAsEdited(); + win.Save(); + win.Close(); + } + /// public override void OnThumbnailDrawPrepare(ThumbnailRequest request) { diff --git a/Source/Editor/Windows/Assets/AnimationGraphWindow.cs b/Source/Editor/Windows/Assets/AnimationGraphWindow.cs index 9d65e5f7b..e75becf72 100644 --- a/Source/Editor/Windows/Assets/AnimationGraphWindow.cs +++ b/Source/Editor/Windows/Assets/AnimationGraphWindow.cs @@ -295,6 +295,15 @@ namespace FlaxEditor.Windows.Assets base.SetParameter(index, value); } + /// + /// Sets the base model of the animation graph this window is editing. + /// + /// The new base model. + public void SetBaseModel(SkinnedModel baseModel) + { + _properties.BaseModel = baseModel; + } + /// protected override void UnlinkItem() { From 873ac347d4b81fa1a65e7daeaf7dbe3588558ad5 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Wed, 10 Apr 2024 16:30:39 -0400 Subject: [PATCH 3/7] Remove extra usings. --- Source/Editor/Content/Proxy/SkinnedModelProxy.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Source/Editor/Content/Proxy/SkinnedModelProxy.cs b/Source/Editor/Content/Proxy/SkinnedModelProxy.cs index 97e423a2d..163df87da 100644 --- a/Source/Editor/Content/Proxy/SkinnedModelProxy.cs +++ b/Source/Editor/Content/Proxy/SkinnedModelProxy.cs @@ -3,9 +3,6 @@ using System; using FlaxEditor.Content.Thumbnails; using FlaxEditor.GUI.ContextMenu; -using FlaxEditor.GUI.Docking; -using FlaxEditor.Options; -using FlaxEditor.Surface; using FlaxEditor.Viewport.Previews; using FlaxEditor.Windows; using FlaxEditor.Windows.Assets; From 8ef38178e6e16e52c823275fd048c4bbd838752f Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Wed, 10 Apr 2024 18:13:27 -0400 Subject: [PATCH 4/7] Allow the user to pick prefab type upon creation of a prefab. --- .../Content/Create/PrefabCreateEntry.cs | 72 +++++++++++++++++++ Source/Editor/Content/Proxy/PrefabProxy.cs | 16 ++--- 2 files changed, 76 insertions(+), 12 deletions(-) create mode 100644 Source/Editor/Content/Create/PrefabCreateEntry.cs diff --git a/Source/Editor/Content/Create/PrefabCreateEntry.cs b/Source/Editor/Content/Create/PrefabCreateEntry.cs new file mode 100644 index 000000000..b307f09dd --- /dev/null +++ b/Source/Editor/Content/Create/PrefabCreateEntry.cs @@ -0,0 +1,72 @@ +// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. + +using System; +using FlaxEditor.Scripting; +using FlaxEngine; +using Object = FlaxEngine.Object; + +namespace FlaxEditor.Content.Create +{ + /// + /// Visual Script asset creating handler. Allows to specify base class to inherit from. + /// + /// + public class PrefabCreateEntry : CreateFileEntry + { + /// + /// The create options. + /// + public class Options + { + /// + /// The root actor. + /// + [TypeReference(typeof(FlaxEngine.Actor), nameof(IsValid))] + [Tooltip("The actor type of the root of the new Prefab.")] + public Type RootActorType = typeof(EmptyActor); + + private static bool IsValid(Type type) + { + return (type.IsPublic || type.IsNestedPublic) && !type.IsAbstract && !type.IsGenericType; + } + } + + private readonly Options _options = new Options(); + + /// + public override object Settings => _options; + + /// + /// Initializes a new instance of the class. + /// + /// The result file url. + public PrefabCreateEntry(string resultUrl) + : base("Settings", resultUrl) + { + } + + /// + public override bool Create() + { + if (_options.RootActorType == null) + _options.RootActorType = typeof(EmptyActor); + + ScriptType actorType = new ScriptType(_options.RootActorType); + + Actor actor = null; + try + { + actor = actorType.CreateInstance() as Actor; + Object.Destroy(actor, 20.0f); + } + catch (Exception ex) + { + Editor.LogError("Failed to create prefab with root actor type: " + actorType.Name); + Editor.LogWarning(ex); + return true; + } + + return PrefabManager.CreatePrefab(actor, ResultUrl, true); + } + } +} diff --git a/Source/Editor/Content/Proxy/PrefabProxy.cs b/Source/Editor/Content/Proxy/PrefabProxy.cs index 18860995e..a97b6232f 100644 --- a/Source/Editor/Content/Proxy/PrefabProxy.cs +++ b/Source/Editor/Content/Proxy/PrefabProxy.cs @@ -2,6 +2,7 @@ using System; using System.IO; +using FlaxEditor.Content.Create; using FlaxEditor.Content.Thumbnails; using FlaxEditor.Viewport.Previews; using FlaxEditor.Windows; @@ -76,30 +77,21 @@ namespace FlaxEditor.Content /// public override void Create(string outputPath, object arg) { - bool resetTransform = false; var transform = Transform.Identity; if (!(arg is Actor actor)) { - // Create default prefab root object - actor = new EmptyActor - { - Name = "Root" - }; - - // Cleanup it after usage - Object.Destroy(actor, 20.0f); + Editor.Instance.ContentImporting.Create(new PrefabCreateEntry(outputPath)); + return; } else if (actor.Scene != null) { // Create prefab with identity transform so the actor instance on a level will have it customized - resetTransform = true; transform = actor.LocalTransform; actor.LocalTransform = Transform.Identity; } PrefabManager.CreatePrefab(actor, outputPath, true); - if (resetTransform) - actor.LocalTransform = transform; + actor.LocalTransform = transform; } /// From fe6c254a2496889fce842e42cdcab864ba3e9600 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Wed, 10 Apr 2024 18:47:01 -0400 Subject: [PATCH 5/7] Support displaying "Widget" instead of "Prefab" in the type description. --- Source/Editor/Content/Items/PrefabItem.cs | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Source/Editor/Content/Items/PrefabItem.cs b/Source/Editor/Content/Items/PrefabItem.cs index a61e07e7c..6394ed52c 100644 --- a/Source/Editor/Content/Items/PrefabItem.cs +++ b/Source/Editor/Content/Items/PrefabItem.cs @@ -42,6 +42,32 @@ namespace FlaxEditor.Content /// public override SpriteHandle DefaultThumbnail => SpriteHandle.Invalid; + private string _cachedTypeDescription = null; + + /// + public override string TypeDescription + { + get + { + if (_cachedTypeDescription != null) + return _cachedTypeDescription; + + Prefab prefab = FlaxEngine.Content.LoadAsync(ID); + if (prefab.WaitForLoaded(5000)) + { + _cachedTypeDescription = "Prefab"; + } + + Actor root = prefab.GetDefaultInstance(); + if (root is UIControl or UICanvas) + _cachedTypeDescription = "Widget"; + else + _cachedTypeDescription = "Prefab"; + + return _cachedTypeDescription; + } + } + /// public override bool IsOfType(Type type) { From 019230f6d9077ec025a5c6a84cc5bf4d8a9013f3 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Thu, 11 Apr 2024 00:03:04 -0400 Subject: [PATCH 6/7] Allow users to choose what type of widget they want to create. --- .../Content/Create/PrefabCreateEntry.cs | 111 +++++++++++++++++- Source/Editor/Content/Proxy/PrefabProxy.cs | 14 +-- 2 files changed, 112 insertions(+), 13 deletions(-) diff --git a/Source/Editor/Content/Create/PrefabCreateEntry.cs b/Source/Editor/Content/Create/PrefabCreateEntry.cs index b307f09dd..e207343a5 100644 --- a/Source/Editor/Content/Create/PrefabCreateEntry.cs +++ b/Source/Editor/Content/Create/PrefabCreateEntry.cs @@ -3,12 +3,13 @@ using System; using FlaxEditor.Scripting; using FlaxEngine; +using FlaxEngine.GUI; using Object = FlaxEngine.Object; namespace FlaxEditor.Content.Create { /// - /// Visual Script asset creating handler. Allows to specify base class to inherit from. + /// Prefab asset creating handler. Allows to specify base actor to use as the root. /// /// public class PrefabCreateEntry : CreateFileEntry @@ -69,4 +70,112 @@ namespace FlaxEditor.Content.Create return PrefabManager.CreatePrefab(actor, ResultUrl, true); } } + + /// + /// Widget asset creating handler. Allows to specify base UIControl to use as the root. + /// + /// + public class WidgetCreateEntry : CreateFileEntry + { + /// + /// The create options. + /// + public class Options + { + /// + /// Which mode is used to initialize this widget. + /// + public enum WidgetMode + { + /// + /// Initialize the widget with a UICanvas. + /// + Canvas, + + /// + /// Initialize the widget with a UIControl. + /// + Control + } + + /// + /// The mode used to initialize the widget. + /// + [Tooltip("Whether to initialize the widget with a canvas or a control.")] + public WidgetMode WidgetInitializationMode = WidgetMode.Canvas; + + bool ShowRoot => WidgetInitializationMode == WidgetMode.Control; + + /// + /// The root control. + /// + [TypeReference(typeof(Control), nameof(IsValid))] + [Tooltip("The control type of the root of the new Widget's root control."), VisibleIf(nameof(ShowRoot))] + public Type RootControlType = typeof(Panel); + + private static bool IsValid(Type type) + { + return (type.IsPublic || type.IsNestedPublic) && !type.IsAbstract && !type.IsGenericType; + } + } + + private readonly Options _options = new Options(); + + /// + public override object Settings => _options; + + /// + /// Initializes a new instance of the class. + /// + /// The result file url. + public WidgetCreateEntry(string resultUrl) + : base("Settings", resultUrl) + { + } + + /// + public override bool Create() + { + Actor actor = null; + + if (_options.WidgetInitializationMode == Options.WidgetMode.Control) + { + if (_options.RootControlType == null) + _options.RootControlType = typeof(Control); + + ScriptType controlType = new ScriptType(_options.RootControlType); + + Control control = null; + try + { + control = controlType.CreateInstance() as Control; + } + catch (Exception ex) + { + Editor.LogError("Failed to create widget with root control type: " + controlType.Name); + Editor.LogWarning(ex); + return true; + } + + UIControl newControl = new UIControl(); + newControl.Control = control; + + actor = newControl; + } + else if (_options.WidgetInitializationMode == Options.WidgetMode.Canvas) + { + actor = new UICanvas(); + } + + if (actor == null) + { + Editor.LogError("Failed to create widget. Final actor was null."); + return true; + } + + Object.Destroy(actor, 20.0f); + + return PrefabManager.CreatePrefab(actor, ResultUrl, true); + } + } } diff --git a/Source/Editor/Content/Proxy/PrefabProxy.cs b/Source/Editor/Content/Proxy/PrefabProxy.cs index a97b6232f..fd4eefdf2 100644 --- a/Source/Editor/Content/Proxy/PrefabProxy.cs +++ b/Source/Editor/Content/Proxy/PrefabProxy.cs @@ -233,18 +233,8 @@ namespace FlaxEditor.Content /// public override void Create(string outputPath, object arg) { - // Create prefab with UI Control - var actor = new UIControl - { - Name = Path.GetFileNameWithoutExtension(outputPath), - StaticFlags = StaticFlags.None, - }; - actor.Control = new Button - { - Text = "Button", - }; - PrefabManager.CreatePrefab(actor, outputPath, false); - Object.Destroy(actor, 20.0f); + Editor.Instance.ContentImporting.Create(new WidgetCreateEntry(outputPath)); + return; } } } From 4683262cf307f7f3459efa5324805eba8104d11f Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 11 Sep 2024 13:38:31 +0200 Subject: [PATCH 7/7] Small codestyle tweaks #2415 --- .../Content/Create/PrefabCreateEntry.cs | 30 +++++++------------ Source/Editor/Content/Items/PrefabItem.cs | 24 +++++++-------- Source/Editor/Content/Proxy/PrefabProxy.cs | 7 +++-- .../Editor/Content/Proxy/SkinnedModelProxy.cs | 6 ++-- 4 files changed, 29 insertions(+), 38 deletions(-) diff --git a/Source/Editor/Content/Create/PrefabCreateEntry.cs b/Source/Editor/Content/Create/PrefabCreateEntry.cs index e207343a5..06d0c94d4 100644 --- a/Source/Editor/Content/Create/PrefabCreateEntry.cs +++ b/Source/Editor/Content/Create/PrefabCreateEntry.cs @@ -49,12 +49,8 @@ namespace FlaxEditor.Content.Create /// public override bool Create() { - if (_options.RootActorType == null) - _options.RootActorType = typeof(EmptyActor); - - ScriptType actorType = new ScriptType(_options.RootActorType); - - Actor actor = null; + var actorType = new ScriptType(_options.RootActorType ?? typeof(EmptyActor)); + Actor actor; try { actor = actorType.CreateInstance() as Actor; @@ -102,7 +98,7 @@ namespace FlaxEditor.Content.Create /// The mode used to initialize the widget. /// [Tooltip("Whether to initialize the widget with a canvas or a control.")] - public WidgetMode WidgetInitializationMode = WidgetMode.Canvas; + public WidgetMode WidgetInitializationMode = WidgetMode.Control; bool ShowRoot => WidgetInitializationMode == WidgetMode.Control; @@ -111,7 +107,7 @@ namespace FlaxEditor.Content.Create /// [TypeReference(typeof(Control), nameof(IsValid))] [Tooltip("The control type of the root of the new Widget's root control."), VisibleIf(nameof(ShowRoot))] - public Type RootControlType = typeof(Panel); + public Type RootControlType = typeof(Button); private static bool IsValid(Type type) { @@ -140,12 +136,8 @@ namespace FlaxEditor.Content.Create if (_options.WidgetInitializationMode == Options.WidgetMode.Control) { - if (_options.RootControlType == null) - _options.RootControlType = typeof(Control); - - ScriptType controlType = new ScriptType(_options.RootControlType); - - Control control = null; + var controlType = new ScriptType(_options.RootControlType ?? typeof(Control)); + Control control; try { control = controlType.CreateInstance() as Control; @@ -157,10 +149,11 @@ namespace FlaxEditor.Content.Create return true; } - UIControl newControl = new UIControl(); - newControl.Control = control; - - actor = newControl; + actor = new UIControl + { + Control = control, + Name = controlType.Name + }; } else if (_options.WidgetInitializationMode == Options.WidgetMode.Canvas) { @@ -172,7 +165,6 @@ namespace FlaxEditor.Content.Create Editor.LogError("Failed to create widget. Final actor was null."); return true; } - Object.Destroy(actor, 20.0f); return PrefabManager.CreatePrefab(actor, ResultUrl, true); diff --git a/Source/Editor/Content/Items/PrefabItem.cs b/Source/Editor/Content/Items/PrefabItem.cs index 6394ed52c..3638f274f 100644 --- a/Source/Editor/Content/Items/PrefabItem.cs +++ b/Source/Editor/Content/Items/PrefabItem.cs @@ -11,6 +11,8 @@ namespace FlaxEditor.Content /// public sealed class PrefabItem : JsonAssetItem { + private string _cachedTypeDescription = null; + /// /// Initializes a new instance of the class. /// @@ -42,28 +44,22 @@ namespace FlaxEditor.Content /// public override SpriteHandle DefaultThumbnail => SpriteHandle.Invalid; - private string _cachedTypeDescription = null; - /// public override string TypeDescription { get { - if (_cachedTypeDescription != null) - return _cachedTypeDescription; - - Prefab prefab = FlaxEngine.Content.LoadAsync(ID); - if (prefab.WaitForLoaded(5000)) + if (_cachedTypeDescription == null) { _cachedTypeDescription = "Prefab"; + var prefab = FlaxEngine.Content.Load(ID); + if (prefab) + { + Actor root = prefab.GetDefaultInstance(); + if (root is UIControl or UICanvas) + _cachedTypeDescription = "Widget"; + } } - - Actor root = prefab.GetDefaultInstance(); - if (root is UIControl or UICanvas) - _cachedTypeDescription = "Widget"; - else - _cachedTypeDescription = "Prefab"; - return _cachedTypeDescription; } } diff --git a/Source/Editor/Content/Proxy/PrefabProxy.cs b/Source/Editor/Content/Proxy/PrefabProxy.cs index 5f5a782b8..27bece29c 100644 --- a/Source/Editor/Content/Proxy/PrefabProxy.cs +++ b/Source/Editor/Content/Proxy/PrefabProxy.cs @@ -1,7 +1,6 @@ // Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. using System; -using System.IO; using FlaxEditor.Content.Create; using FlaxEditor.Content.Thumbnails; using FlaxEditor.Viewport.Previews; @@ -9,7 +8,6 @@ using FlaxEditor.Windows; using FlaxEditor.Windows.Assets; using FlaxEngine; using FlaxEngine.GUI; -using Object = FlaxEngine.Object; namespace FlaxEditor.Content { @@ -87,6 +85,7 @@ namespace FlaxEditor.Content /// public override void Create(string outputPath, object arg) { + bool resetTransform = false; var transform = Transform.Identity; if (!(arg is Actor actor)) { @@ -96,12 +95,14 @@ namespace FlaxEditor.Content else if (actor.HasScene) { // Create prefab with identity transform so the actor instance on a level will have it customized + resetTransform = true; transform = actor.LocalTransform; actor.LocalTransform = Transform.Identity; } PrefabManager.CreatePrefab(actor, outputPath, true); - actor.LocalTransform = transform; + if (resetTransform) + actor.LocalTransform = transform; } /// diff --git a/Source/Editor/Content/Proxy/SkinnedModelProxy.cs b/Source/Editor/Content/Proxy/SkinnedModelProxy.cs index 163df87da..551dd1beb 100644 --- a/Source/Editor/Content/Proxy/SkinnedModelProxy.cs +++ b/Source/Editor/Content/Proxy/SkinnedModelProxy.cs @@ -71,13 +71,15 @@ namespace FlaxEditor.Content private static void OnAnimationGraphCreated(ContentItem item, BinaryAssetItem skinnedModelItem) { - var skinnedModel = FlaxEngine.Content.LoadAsync(skinnedModelItem.ID); - if (skinnedModel == null || skinnedModel.WaitForLoaded()) + var skinnedModel = FlaxEngine.Content.Load(skinnedModelItem.ID); + if (skinnedModel == null) { Editor.LogError("Failed to load base skinned model."); + return; } // Hack the animation graph window to modify the base model of the animation graph. + // TODO: implement it without window logic (load AnimGraphSurface and set AnimationGraphWindow.BaseModelId to model) AnimationGraphWindow win = new AnimationGraphWindow(Editor.Instance, item as AssetItem); win.Show();