From 41b92c16b2ba37e3af37ac454a1773dfa8421ca2 Mon Sep 17 00:00:00 2001 From: bonnibel Date: Wed, 13 Dec 2023 01:28:59 -0800 Subject: [PATCH] Started to work on prefab asset editors... --- .../CustomEditors/CharacterEditor.cs | 3 - .../CustomEditors/LocalizationAssetEditor.cs | 3 - .../CustomEditors/SpriteEditor.cs | 128 ++++++++++++++++++ src/Murder.Editor/Stage/Stage.cs | 17 +-- src/Murder/Core/Geometry/Rectangle.cs | 15 +- 5 files changed, 145 insertions(+), 21 deletions(-) create mode 100644 src/Murder.Editor/CustomEditors/SpriteEditor.cs diff --git a/src/Murder.Editor/CustomEditors/CharacterEditor.cs b/src/Murder.Editor/CustomEditors/CharacterEditor.cs index 12d2a78a4..091b399e5 100644 --- a/src/Murder.Editor/CustomEditors/CharacterEditor.cs +++ b/src/Murder.Editor/CustomEditors/CharacterEditor.cs @@ -10,10 +10,7 @@ using Murder.Editor.Reflection; using Murder.Editor.Stages; using Murder.Editor.Systems; -using Murder.Editor.Utilities; using Murder.Editor.Utilities.Attributes; -using Newtonsoft.Json.Linq; -using System; namespace Murder.Editor.CustomEditors { diff --git a/src/Murder.Editor/CustomEditors/LocalizationAssetEditor.cs b/src/Murder.Editor/CustomEditors/LocalizationAssetEditor.cs index 9168e32c2..95cee6e72 100644 --- a/src/Murder.Editor/CustomEditors/LocalizationAssetEditor.cs +++ b/src/Murder.Editor/CustomEditors/LocalizationAssetEditor.cs @@ -1,5 +1,4 @@ using ImGuiNET; -using Murder.Assets; using Murder.Assets.Localization; using Murder.Core.Graphics; using Murder.Diagnostics; @@ -8,8 +7,6 @@ using Murder.Editor.Reflection; using Murder.Editor.Utilities; using Murder.Editor.Utilities.Serialization; -using System; -using System.Collections.Immutable; using System.Numerics; namespace Murder.Editor.CustomEditors diff --git a/src/Murder.Editor/CustomEditors/SpriteEditor.cs b/src/Murder.Editor/CustomEditors/SpriteEditor.cs new file mode 100644 index 000000000..2e2b818a3 --- /dev/null +++ b/src/Murder.Editor/CustomEditors/SpriteEditor.cs @@ -0,0 +1,128 @@ +using ImGuiNET; +using Murder.Assets.Graphics; +using Murder.Components; +using Murder.Core; +using Murder.Core.Geometry; +using Murder.Core.Graphics; +using Murder.Diagnostics; +using Murder.Editor.Attributes; +using Murder.Editor.ImGuiExtended; +using Murder.Editor.Stages; +using Murder.Editor.Systems; +using Murder.Utilities; +using System.Numerics; + +namespace Murder.Editor.CustomEditors +{ + [CustomEditorOf(typeof(SpriteAsset))] + internal class SpriteEditor : CustomEditor + { + /// + /// Tracks the dialog system editors across different guids. + /// + protected Dictionary ActiveEditors { get; private set; } = new(); + + private SpriteAsset? _sprite = null; + + public override object Target => _sprite!; + + public override void OpenEditor(ImGuiRenderer imGuiRenderer, RenderContext renderContext, object target, bool overwrite) + { + _sprite = (SpriteAsset)target; + + if (!ActiveEditors.ContainsKey(_sprite.Guid)) + { + Stage stage = new(imGuiRenderer, renderContext); + + SpriteInformation info = new(stage); + ActiveEditors[_sprite.Guid] = info; + + InitializeStage(stage, info); + } + } + + private void InitializeStage(Stage stage, SpriteInformation info) + { + GameLogger.Verify(_sprite is not null); + + stage.ToggleSystem(typeof(EntitiesSelectorSystem), false); + + Portrait portrait = new(_sprite.Guid, _sprite.Animations.Count == 0 ? string.Empty : _sprite.Animations.First().Key); + info.HelperId = stage.AddEntityWithoutAsset(new PositionComponent(), new SpriteComponent(portrait)); + + stage.ShowInfo = false; + stage.EditorHook.DrawSelection = false; + stage.EditorHook.CurrentZoomLevel = 5; + } + + public override void DrawEditor() + { + GameLogger.Verify(_sprite is not null); + + if (!ActiveEditors.TryGetValue(_sprite.Guid, out var info)) + { + GameLogger.Warning("Unitialized stage for particle editor?"); + return; + } + + Vector2 windowSize = ImGui.GetContentRegionAvail(); + + using TableMultipleColumns table = new( + $"sprite_stage_{_sprite.Guid}", ImGuiTableFlags.Resizable, Calculator.RoundToInt(windowSize.X / 5), -1, Calculator.RoundToInt(windowSize.X / 5)); + + ImGui.TableNextColumn(); + + DrawFistColumn(); + + ImGui.TableNextColumn(); + + Stage stage = info.Stage; + + if (ActiveEditors.ContainsKey(_sprite.Guid)) + { + windowSize = ImGui.GetContentRegionAvail(); + Vector2 origin = ImGui.GetItemRectMin(); + float length = windowSize.X / 3f; + + stage.Draw(); + } + + ImGui.TableNextRow(); + ImGui.TableNextColumn(); + } + + private void DrawFistColumn() + { + GameLogger.Verify(_sprite is not null); + + + Vector2 windowSize = ImGui.GetContentRegionAvail(); + ImGui.PushID("somed"); + ImGui.PushItemWidth(20); + ImGui.TextColored(Game.Profile.Theme.Accent, $"\uf520 {_sprite.Name}"); + ImGuiHelpers.PrettySelectableWithIcon( + label: _sprite.Name, + selectable: true); + ImGui.PopItemWidth(); + ImGui.PopID(); + } + + public override void CloseEditor(Guid target) + { + if (ActiveEditors.TryGetValue(target, out SpriteInformation? info)) + { + info.Stage.Dispose(); + } + + ActiveEditors.Remove(target); + } + + protected record SpriteInformation(Stage Stage) + { + /// + /// This is the entity id in the world. + /// + public int HelperId = 0; + } + } +} diff --git a/src/Murder.Editor/Stage/Stage.cs b/src/Murder.Editor/Stage/Stage.cs index 2259064b2..303e09036 100644 --- a/src/Murder.Editor/Stage/Stage.cs +++ b/src/Murder.Editor/Stage/Stage.cs @@ -71,7 +71,7 @@ private void InitializeDrawAndWorld() _world.Start(); } - public void Draw() + public void Draw(Rectangle? rectToDrawStage = null) { if (!_calledStart) { @@ -84,7 +84,11 @@ public void Draw() Architect.Input.MouseConsumed = false; } - Vector2 size = ImGui.GetItemRectSize() - new Vector2(0, 5); + Vector2 topLeft = rectToDrawStage?.TopLeft ?? ImGui.GetItemRectMin(); + Vector2 bottomRight = rectToDrawStage?.BottomRight ?? ImGui.GetItemRectMax(); + + Vector2 size = rectToDrawStage?.Size ?? Rectangle.FromCoordinates(topLeft, bottomRight).Size; + if (size.X <= 0 || size.Y <= 0) { // Empty. @@ -118,16 +122,13 @@ public void Draw() } } - var topLeft = ImGui.GetItemRectMin(); if (_world.GetUnique() is EditorComponent editorComponent) { - editorComponent.EditorHook.Offset = ImGui.GetItemRectMin().Point(); - Vector2 rectSize = ImGui.GetItemRectSize(); - editorComponent.EditorHook.StageSize = rectSize; + editorComponent.EditorHook.Offset = topLeft.Point(); + editorComponent.EditorHook.StageSize = rectToDrawStage?.Size ?? + Rectangle.FromCoordinates(topLeft, bottomRight).Size; } - Vector2 bottomRight = ImGui.GetItemRectMax(); - ImDrawListPtr drawList = ImGui.GetWindowDrawList(); drawList.PushClipRect(topLeft, bottomRight); diff --git a/src/Murder/Core/Geometry/Rectangle.cs b/src/Murder/Core/Geometry/Rectangle.cs index 77dd0d215..f410f4a51 100644 --- a/src/Murder/Core/Geometry/Rectangle.cs +++ b/src/Murder/Core/Geometry/Rectangle.cs @@ -71,14 +71,9 @@ public Vector2 Size public static implicit operator Microsoft.Xna.Framework.Rectangle(Rectangle p) => new(Calculator.RoundToInt(p.X), Calculator.RoundToInt(p.Y), Calculator.RoundToInt(p.Width), Calculator.RoundToInt(p.Height)); /// - /// Constructor for a rectangle + /// Constructor for a rectangle from a set of coordinates. /// - /// - /// - /// - /// - /// - internal static Rectangle FromCoordinates(float top, float bottom, float left, float right) + public static Rectangle FromCoordinates(float top, float bottom, float left, float right) { return new Rectangle( left, @@ -88,6 +83,12 @@ internal static Rectangle FromCoordinates(float top, float bottom, float left, f ); } + /// + /// Constructor for a rectangle from a set of coordinates. + /// + public static Rectangle FromCoordinates(Vector2 topLeft, Vector2 bottomRight) => + FromCoordinates(top: topLeft.Y, bottom: bottomRight.Y, left: topLeft.X, right: bottomRight.X); + public static implicit operator Rectangle(IntRectangle p) => new(p.X, p.Y, p.Width, p.Height); public Rectangle AddPosition(Vector2 position) => new Rectangle(X + Calculator.RoundToInt(position.X), Y + Calculator.RoundToInt(position.Y), Width, Height);