From 7a5714da51ce08e693b61f64597a2c7d168364dd Mon Sep 17 00:00:00 2001 From: Donavin Draws <51259260+DonavinDraws@users.noreply.github.com> Date: Tue, 21 Nov 2023 02:34:50 -0600 Subject: [PATCH 1/6] Full-On Pack Parsing Pipes and Actor Selection Shapes now parse their pack file to draw themselves --- Fushigi/actor_pack/ActorPack.cs | 29 +++++ Fushigi/actor_pack/components/DrainPipe.cs | 17 +++ Fushigi/actor_pack/components/GamePhysics.cs | 95 +++++++++++++++ Fushigi/actor_pack/components/ModelInfo.cs | 4 + Fushigi/ui/widgets/LevelViewport.cs | 116 ++++++++++++------- 5 files changed, 218 insertions(+), 43 deletions(-) create mode 100644 Fushigi/actor_pack/components/DrainPipe.cs create mode 100644 Fushigi/actor_pack/components/GamePhysics.cs diff --git a/Fushigi/actor_pack/ActorPack.cs b/Fushigi/actor_pack/ActorPack.cs index 109cb978..2275ea1c 100644 --- a/Fushigi/actor_pack/ActorPack.cs +++ b/Fushigi/actor_pack/ActorPack.cs @@ -1,11 +1,14 @@ using Fushigi.actor_pack.components; +using Fushigi.Bfres; using Fushigi.Byml.Serializer; using Fushigi.gl.Bfres; using Fushigi.SARC; using Fushigi.util; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; +using System.Numerics; using System.Text; using System.Threading.Tasks; @@ -33,6 +36,10 @@ public class ActorPack public ModelInfo DrawArrayModelInfoRef; public ModelInfo ModelInfoRef; public ModelExpandParam ModelExpandParamRef; + public DrainPipe DrainPipeRef; + public GamePhysics GamePhysicsRef; + public ControllerSetParam ControllerPath; + public ShapeParam ShapeParams; public string Category = ""; @@ -110,6 +117,28 @@ private void LoadComponents(SARC.SARC sarc, ActorParam param) case "ModelExpandRef": this.ModelExpandParamRef = BymlSerialize.Deserialize(data); break; + case "DrainPipeRef": + this.DrainPipeRef = BymlSerialize.Deserialize(data); + break; + case "GamePhysicsRef": + this.GamePhysicsRef = BymlSerialize.Deserialize(data); + filePath = GetPathGyml(GamePhysicsRef.ControllerSetPath); + data = sarc.OpenFile(filePath); + this.ControllerPath = BymlSerialize.Deserialize(data); + if(this.ControllerPath.ShapeNamePathAry != null) + { + foreach(var shape in this.ControllerPath.ShapeNamePathAry) + { + if(shape.Name == "Body" || shape.Name.Trim() == "BodyShape") + { + filePath = GetPathGyml(shape.FilePath); + data = sarc.OpenFile(filePath); + if(shape.FilePath != null) + this.ShapeParams = BymlSerialize.Deserialize(data); + } + } + } + break; } } } diff --git a/Fushigi/actor_pack/components/DrainPipe.cs b/Fushigi/actor_pack/components/DrainPipe.cs new file mode 100644 index 00000000..7d822a5e --- /dev/null +++ b/Fushigi/actor_pack/components/DrainPipe.cs @@ -0,0 +1,17 @@ +using Fushigi.Byml.Serializer; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Threading.Tasks; + +namespace Fushigi.actor_pack.components +{ + [Serializable] + public class DrainPipe + { + public string ModelKeyMiddle { get; set; } + public string ModelKeyTop { get; set; } + } +} diff --git a/Fushigi/actor_pack/components/GamePhysics.cs b/Fushigi/actor_pack/components/GamePhysics.cs new file mode 100644 index 00000000..3f3f8351 --- /dev/null +++ b/Fushigi/actor_pack/components/GamePhysics.cs @@ -0,0 +1,95 @@ +using Fushigi.Byml.Serializer; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Threading.Tasks; + +namespace Fushigi.actor_pack.components +{ + [Serializable] + public class GamePhysics + { + public string ControllerSetPath { get; set; } + } + + [Serializable] + public class ControllerSetParam + { + public List ShapeNamePathAry { get; set; } + } + + [Serializable] + public class ShapeName + { + public string FilePath { get; set; } + public string Name { get; set; } + } + + [Serializable] + public class ShapeParam + { + [BymlProperty("AutoCalc")] + public AutoCalc mCalc { get; set; } + + [BymlProperty("Box")] + public List mBox { get; set; } + + [BymlProperty("Sphere")] + public List mSphere { get; set; } + + [BymlProperty("Capsule")] + public List mCapsule { get; set; } + } + + [Serializable] + public class AutoCalc + { + [BymlProperty("Axis")] + public Vector3 mAxis { get; set; } + + [BymlProperty("Center")] + public Vector3 mCenter { get; set; } + + [BymlProperty("Min")] + public Vector3 mMin { get; set; } + + [BymlProperty("Max")] + public Vector3 mMax { get; set; } + } + + [Serializable] + public class Box + { + [BymlProperty("Center")] + public Vector3 mCenter { get; set; } + + [BymlProperty("HalfExtents")] + public Vector3 mExtents { get; set; } + + } + + [Serializable] + public class Sphere + { + public float Radius { get; set; } + + [BymlProperty("Center")] + public Vector3 mCenter { get; set; } + + + } + + [Serializable] + public class Capsule + { + public float Radius { get; set; } + + [BymlProperty("CenterA")] + public Vector3 mCenterA { get; set; } + + [BymlProperty("CenterB")] + public Vector3 mCenterB { get; set; } + } +} \ No newline at end of file diff --git a/Fushigi/actor_pack/components/ModelInfo.cs b/Fushigi/actor_pack/components/ModelInfo.cs index 9633cb03..fcaec0b1 100644 --- a/Fushigi/actor_pack/components/ModelInfo.cs +++ b/Fushigi/actor_pack/components/ModelInfo.cs @@ -24,6 +24,10 @@ public class ModelInfo public class SubModel { public string FmdbName { get; set; } + + public string ModelProjectName { get; set; } + + public string SearchModelKey { get; set; } } [Serializable] diff --git a/Fushigi/ui/widgets/LevelViewport.cs b/Fushigi/ui/widgets/LevelViewport.cs index 52e714bc..b28d7b98 100644 --- a/Fushigi/ui/widgets/LevelViewport.cs +++ b/Fushigi/ui/widgets/LevelViewport.cs @@ -25,6 +25,7 @@ using System.Runtime.InteropServices; using static Fushigi.ui.SceneObjects.bgunit.BGUnitRailSceneObj; using Fushigi.ui.SceneObjects.bgunit; +using System.Diagnostics; namespace Fushigi.ui.widgets { @@ -268,20 +269,25 @@ private void RenderActor(CourseActor actor, ModelInfo modelInfo) var model = render.Models[modelName]; //switch for drawing models with different methods easier switch (modelName){ + case "DokanJunction": case "DokanTop": - var matPTop = - Matrix4x4.CreateScale(actor.mScale.X, actor.mScale.X, actor.mScale.Z) * - Matrix4x4.CreateTranslation(0, (actor.mScale.Y-actor.mScale.X)*2, 0) * - rotMat * - transMat; - - var matPMid = - Matrix4x4.CreateScale(actor.mScale.X, actor.mScale.Y*2, actor.mScale.Z) * - rotMat * - transMat; - - model.Render(gl, render, matPTop, this.Camera); - render.Models["DokanMiddle"].Render(gl, render, matPMid, this.Camera); + var drainRef = actor.mActorPack.DrainPipeRef; + + var KeyMats = new Dictionary{ + {drainRef.ModelKeyTop, + Matrix4x4.CreateScale(actor.mScale.X, actor.mScale.X, actor.mScale.Z) * + Matrix4x4.CreateTranslation(0, (actor.mScale.Y-actor.mScale.X)*2, 0) * + rotMat * + transMat}, + + {drainRef.ModelKeyMiddle, + Matrix4x4.CreateScale(actor.mScale.X, actor.mScale.Y*2, actor.mScale.Z) * + rotMat * + transMat}}; + + render.Models[modelName].Render(gl, render, KeyMats[modelInfo.SearchModelKey], this.Camera); + if(modelInfo.SubModels.Any()) + render.Models[modelInfo.SubModels[0].FmdbName].Render(gl, render, KeyMats[modelInfo.SubModels[0].SearchModelKey], this.Camera); break; default: model.Render(gl, render, mat, this.Camera); @@ -956,6 +962,29 @@ Vector2[] GetPoints() foreach (CourseActor actor in mEditContext.GetActorHolder().GetActors()) { + Vector3 min = new(-.5f); + Vector3 max = new(.5f); + Vector3 off = new(0f); + Vector3 center = new(0f); + var drawing = "box"; + + if (actor.mActorPack.ShapeParams != null) + { + var calc = actor.mActorPack.ShapeParams.mCalc; + min = calc.mMin; + max = calc.mMax; + center = calc.mCenter; + + if(actor.mActorPack.ShapeParams.mSphere != null) + { + drawing = "sphere"; + } + else if(actor.mActorPack.ShapeParams.mCapsule != null) + { + drawing = "cap"; + } + } + string layer = actor.mLayer; if (mLayersVisibility!.TryGetValue(layer, out bool isVisible) && isVisible) @@ -978,27 +1007,17 @@ Vector2[] GetPoints() { if (actor.mActorName.Contains("CameraArea")) color = ImGui.ColorConvertFloat4ToU32(new(1, 0, 0, 1)); - - //topLeft - s_actorRectPolygon[0] = WorldToScreen(Vector3.Transform(new(-0.5f, 1f, 0), transform)); - //topRight - s_actorRectPolygon[1] = WorldToScreen(Vector3.Transform(new(0.5f, 1f, 0), transform)); - //bottomRight - s_actorRectPolygon[2] = WorldToScreen(Vector3.Transform(new(0.5f, 0, 0), transform)); - //bottomLeft - s_actorRectPolygon[3] = WorldToScreen(Vector3.Transform(new(-0.5f, 0, 0), transform)); - } - else - { - //topLeft - s_actorRectPolygon[0] = WorldToScreen(Vector3.Transform(new(-0.5f, 0.5f, 0), transform)); - //topRight - s_actorRectPolygon[1] = WorldToScreen(Vector3.Transform(new(0.5f, 0.5f, 0), transform)); - //bottomRight - s_actorRectPolygon[2] = WorldToScreen(Vector3.Transform(new(0.5f, -0.5f, 0), transform)); - //bottomLeft - s_actorRectPolygon[3] = WorldToScreen(Vector3.Transform(new(-0.5f, -0.5f, 0), transform)); + + off = new(0, .5f, 0); } + //topLeft + s_actorRectPolygon[0] = WorldToScreen(Vector3.Transform(new(min.X, off.Y+max.Y, 0), transform)); + //topRight + s_actorRectPolygon[1] = WorldToScreen(Vector3.Transform(new(max.X, off.Y+max.Y, 0), transform)); + //bottomRight + s_actorRectPolygon[2] = WorldToScreen(Vector3.Transform(new(max.X, off.Y+min.Y, 0), transform)); + //bottomLeft + s_actorRectPolygon[3] = WorldToScreen(Vector3.Transform(new(min.X, off.Y+min.Y, 0), transform)); if (mEditContext.IsSelected(actor)) { @@ -1007,17 +1026,28 @@ Vector2[] GetPoints() bool isHovered = HoveredObject == actor; - for (int i = 0; i < 4; i++) + switch(drawing) { - if (mEditContext.IsSelected(actor)) - { - mDrawList.AddCircleFilled(s_actorRectPolygon[i], - pointSize, color); - } - mDrawList.AddLine( - s_actorRectPolygon[i], - s_actorRectPolygon[(i + 1) % 4], - color, isHovered ? 2.5f : 1.5f); + default: + for (int i = 0; i < 4; i++) + { + if (mEditContext.IsSelected(actor)) + { + mDrawList.AddCircleFilled(s_actorRectPolygon[i], + pointSize, color); + } + mDrawList.AddLine( + s_actorRectPolygon[i], + s_actorRectPolygon[(i+1) % 4 ], + color, isHovered ? 2.5f : 1.5f); + } + break; + case "sphere": + var pos = WorldToScreen(Vector3.Transform(center, transform)); + var rad = WorldToScreen(Vector3.Transform(max, transform)).X- + WorldToScreen(Vector3.Transform(center, transform)).X; + mDrawList.AddCircle(pos, Math.Abs(rad), color, 0, isHovered ? 2.5f : 1.5f); + break; } string name = actor.mActorName; From 74ca024f7d2ffe876ec9b30c29c6fe112b291550 Mon Sep 17 00:00:00 2001 From: Donavin Draws <51259260+DonavinDraws@users.noreply.github.com> Date: Thu, 23 Nov 2023 16:27:12 -0600 Subject: [PATCH 2/6] Better Packs, Shapes, and Selections -Pack Parsing now yields the appropriate shape for each actor -Shape parsing consolidated into it's own function to avoid clutter -Actors without a shape will still draw their models -Updated ImGui.Net -Ported the updated input method -We can draw ellipses now -Drawing actor bounds with better shapes -Actors now show their translation point and square bounding box when selected -Moving actors will account for the mouse's relative position to avoid jumping with bigger actors -Revamp of the multi-select to allow moving multiple actors at once --- Fushigi/Fushigi.csproj | 2 +- Fushigi/Program.cs | 1 + Fushigi/actor_pack/ActorPack.cs | 64 ++++++-- Fushigi/actor_pack/components/GamePhysics.cs | 55 ++++--- Fushigi/course/CourseActor.cs | 1 + Fushigi/ui/widgets/LevelViewport.cs | 113 +++++++++---- Fushigi/windowing/ImGuiController.cs | 162 ++++++++++++------- 7 files changed, 273 insertions(+), 125 deletions(-) diff --git a/Fushigi/Fushigi.csproj b/Fushigi/Fushigi.csproj index 7f8ea1c8..d2f536bb 100644 --- a/Fushigi/Fushigi.csproj +++ b/Fushigi/Fushigi.csproj @@ -10,7 +10,7 @@ - + diff --git a/Fushigi/Program.cs b/Fushigi/Program.cs index 8173b34f..12659b4f 100644 --- a/Fushigi/Program.cs +++ b/Fushigi/Program.cs @@ -3,6 +3,7 @@ using Fushigi.ui; using System.Runtime.InteropServices; + FileStream outputStream = new FileStream("output.log", FileMode.Create); var consoleWriter = new StreamWriter(outputStream); consoleWriter.AutoFlush = true; diff --git a/Fushigi/actor_pack/ActorPack.cs b/Fushigi/actor_pack/ActorPack.cs index 2275ea1c..dfb17cc7 100644 --- a/Fushigi/actor_pack/ActorPack.cs +++ b/Fushigi/actor_pack/ActorPack.cs @@ -39,7 +39,7 @@ public class ActorPack public DrainPipe DrainPipeRef; public GamePhysics GamePhysicsRef; public ControllerSetParam ControllerPath; - public ShapeParam ShapeParams; + public ShapeParamList ShapeParams; public string Category = ""; @@ -122,23 +122,57 @@ private void LoadComponents(SARC.SARC sarc, ActorParam param) break; case "GamePhysicsRef": this.GamePhysicsRef = BymlSerialize.Deserialize(data); - filePath = GetPathGyml(GamePhysicsRef.ControllerSetPath); - data = sarc.OpenFile(filePath); - this.ControllerPath = BymlSerialize.Deserialize(data); - if(this.ControllerPath.ShapeNamePathAry != null) + if(!string.IsNullOrEmpty(GamePhysicsRef.mPath)) + GetActorShape(sarc, data, filePath); + + break; + } + } + } + + private void GetActorShape(SARC.SARC sarc, byte[] data, string filePath) + { + filePath = GetPathGyml(GamePhysicsRef.mPath); + data = sarc.OpenFile(filePath); + ControllerPath = BymlSerialize.Deserialize(data); + if(ControllerPath.ShapeNamePathAry != null) + { + var shapes = ControllerPath.ShapeNamePathAry; + if (!string.IsNullOrEmpty(ControllerPath.parent)) + { + filePath = GetPathGyml(ControllerPath.parent); + data = sarc.OpenFile(filePath); + ControllerPath = BymlSerialize.Deserialize(data); + } + var rigidBodies = ControllerPath.mRigids != null && ControllerPath.mRigids.Count > 0 ? ControllerPath.mRigids : ControllerPath.mEntity; + + foreach(var rigid in rigidBodies) + { + filePath = GetPathGyml(rigid.FilePath); + data = sarc.OpenFile(filePath); + var body = BymlSerialize.Deserialize(data); + + foreach(var shape in shapes) + { + if(body.ShapeName != null) { - foreach(var shape in this.ControllerPath.ShapeNamePathAry) + if(body.ShapeName == shape.Name && shape.FilePath != null) { - if(shape.Name == "Body" || shape.Name.Trim() == "BodyShape") - { - filePath = GetPathGyml(shape.FilePath); - data = sarc.OpenFile(filePath); - if(shape.FilePath != null) - this.ShapeParams = BymlSerialize.Deserialize(data); - } - } + filePath = GetPathGyml(shape.FilePath); + data = sarc.OpenFile(filePath); + ShapeParams = BymlSerialize.Deserialize(data); + } } - break; + else if(body.ShapeNames != null) + { + if(body.ShapeNames.Cast().Contains(shape.Name) && shape.FilePath != null) + { + filePath = GetPathGyml(shape.FilePath); + data = sarc.OpenFile(filePath); + ShapeParams = BymlSerialize.Deserialize(data); + } + } + } } } } diff --git a/Fushigi/actor_pack/components/GamePhysics.cs b/Fushigi/actor_pack/components/GamePhysics.cs index 3f3f8351..5a6d77f1 100644 --- a/Fushigi/actor_pack/components/GamePhysics.cs +++ b/Fushigi/actor_pack/components/GamePhysics.cs @@ -11,13 +11,23 @@ namespace Fushigi.actor_pack.components [Serializable] public class GamePhysics { - public string ControllerSetPath { get; set; } + [BymlProperty("ControllerSetPath", DefaultValue = "")] + public string mPath { get; set; } } [Serializable] public class ControllerSetParam { + [BymlProperty("$parent")] + public string parent { get; set; } + public List ShapeNamePathAry { get; set; } + + [BymlProperty("MatterRigidBodyNamePathAry", DefaultValue = "")] + public List mRigids { get; set; } + + [BymlProperty("RigidBodyEntityNamePathAry", DefaultValue = "")] + public List mEntity { get; set; } } [Serializable] @@ -28,19 +38,30 @@ public class ShapeName } [Serializable] - public class ShapeParam + public class ShapeParamList { [BymlProperty("AutoCalc")] public AutoCalc mCalc { get; set; } - [BymlProperty("Box")] - public List mBox { get; set; } + [BymlProperty("Box", DefaultValue = "")] + public List mBox { get; set; } - [BymlProperty("Sphere")] - public List mSphere { get; set; } + [BymlProperty("Sphere", DefaultValue = "")] + public List mSphere { get; set; } - [BymlProperty("Capsule")] - public List mCapsule { get; set; } + [BymlProperty("Capsule", DefaultValue = "")] + public List mCapsule { get; set; } + + [BymlProperty("Polytope", DefaultValue = "")] + public List mPoly { get; set; } + } + + [Serializable] + public class RigidParam + { + public string ShapeName { get; set; } + + public List ShapeNames { get; set; } } [Serializable] @@ -60,25 +81,19 @@ public class AutoCalc } [Serializable] - public class Box + public class ShapeParam { - [BymlProperty("Center")] - public Vector3 mCenter { get; set; } - - [BymlProperty("HalfExtents")] - public Vector3 mExtents { get; set; } - - } + [BymlProperty("AutoCalc", DefaultValue = "")] + public AutoCalc mCalc { get; set; } - [Serializable] - public class Sphere - { public float Radius { get; set; } [BymlProperty("Center")] public Vector3 mCenter { get; set; } - + [BymlProperty("HalfExtents")] + public Vector3 mExtents { get; set; } + } [Serializable] diff --git a/Fushigi/course/CourseActor.cs b/Fushigi/course/CourseActor.cs index e856e647..0fbf69e0 100644 --- a/Fushigi/course/CourseActor.cs +++ b/Fushigi/course/CourseActor.cs @@ -256,6 +256,7 @@ public BymlHashTable BuildNode(CourseLinkHolder linkHolder) public string mActorName; public string mName; public string mLayer; + public System.Numerics.Vector3 mStartingTrans; public System.Numerics.Vector3 mTranslation; public System.Numerics.Vector3 mRotation; public System.Numerics.Vector3 mScale; diff --git a/Fushigi/ui/widgets/LevelViewport.cs b/Fushigi/ui/widgets/LevelViewport.cs index 284fd143..7d494b5a 100644 --- a/Fushigi/ui/widgets/LevelViewport.cs +++ b/Fushigi/ui/widgets/LevelViewport.cs @@ -26,6 +26,8 @@ using static Fushigi.ui.SceneObjects.bgunit.BGUnitRailSceneObj; using Fushigi.ui.SceneObjects.bgunit; using System.Diagnostics; +using Silk.NET.Maths; +using ZstdSharp.Unsafe; namespace Fushigi.ui.widgets { @@ -58,6 +60,7 @@ internal class LevelViewport(CourseArea area, GL gl, CourseAreaScene areaScene) Vector2 mSize = Vector2.Zero; + private ulong prevSelect; private Vector3? mSelectedPoint; private int mWallIdx = -1; private int mUnitIdx = -1; @@ -156,7 +159,7 @@ public void SelectedActor(CourseActor actor) public void HandleCameraControls(double deltaSeconds, bool mouseHover, bool mouseActive) { bool isPanGesture = (ImGui.IsMouseDragging(ImGuiMouseButton.Middle)) || - (ImGui.IsMouseDragging(ImGuiMouseButton.Left) && ImGui.GetIO().KeyShift); + (ImGui.IsMouseDragging(ImGuiMouseButton.Left) && ImGui.GetIO().KeyShift && !mEditContext.IsAnySelected()); if (mouseActive && isPanGesture) { @@ -370,20 +373,24 @@ public void Draw(Vector2 size, double deltaSeconds, IDictionary la { if (ImGui.IsMouseDragging(ImGuiMouseButton.Left)) { - if (mEditContext.IsSingleObjectSelected(out CourseActor? actor)) + if (mEditContext.IsAnySelected()) { - Vector3 posVec = ScreenToWorld(ImGui.GetMousePos()); - - if (ImGui.GetIO().KeyShift) - { - actor.mTranslation = posVec; - } - else + foreach(CourseActor actor in mEditContext.GetSelectedObjects()) { - posVec.X = MathF.Round(posVec.X * 2, MidpointRounding.AwayFromZero) / 2; - posVec.Y = MathF.Round(posVec.Y * 2, MidpointRounding.AwayFromZero) / 2; - posVec.Z = actor.mTranslation.Z; - actor.mTranslation = posVec; + Vector3 posVec = ScreenToWorld(ImGui.GetMousePos()); + posVec -= ScreenToWorld(ImGui.GetIO().MouseClickedPos[0]) - actor.mStartingTrans; + + if (ImGui.GetIO().KeyShift) + { + actor.mTranslation = posVec; + } + else + { + posVec.X = MathF.Round(posVec.X * 2, MidpointRounding.AwayFromZero) / 2; + posVec.Y = MathF.Round(posVec.Y * 2, MidpointRounding.AwayFromZero) / 2; + posVec.Z = actor.mTranslation.Z; + actor.mTranslation = posVec; + } } } if (mEditContext.IsSingleObjectSelected(out CourseRail.CourseRailPoint? rail)) @@ -430,13 +437,18 @@ public void Draw(Vector2 size, double deltaSeconds, IDictionary la { if (ImGui.IsKeyDown(ImGuiKey.LeftShift)) { + prevSelect = mEditContext.SelectionVersion; mEditContext.Select(HoveredObject!); } - else + else if(!mEditContext.IsSelected(HoveredObject)) { mEditContext.DeselectAll(); mEditContext.Select(HoveredObject!); } + foreach(CourseActor actor in mEditContext.GetSelectedObjects()) + { + actor.mStartingTrans = actor.mTranslation; + } } if (HoveredPoint == null) @@ -449,6 +461,24 @@ public void Draw(Vector2 size, double deltaSeconds, IDictionary la } } + if(HoveredObject != null && ImGui.IsMouseReleased(ImGuiMouseButton.Left) && + HoveredObject is not BGUnitRailSceneObj && HoveredObject is not BGUnitRailSceneObj.RailPoint) + { + if (ImGui.GetIO().MouseDragMaxDistanceSqr[0] <= ImGui.GetIO().MouseDragThreshold) + { + if(ImGui.IsKeyDown(ImGuiKey.LeftShift) && + (mEditContext.SelectionVersion == prevSelect)) + { + mEditContext.Deselect(HoveredObject!); + } + else if(!ImGui.IsKeyDown(ImGuiKey.LeftShift)) + { + mEditContext.DeselectAll(); + mEditContext.Select(HoveredObject!); + } + } + } + if (ImGui.IsKeyPressed(ImGuiKey.Delete)) { mEditorState = EditorState.DeleteActorLinkCheck; @@ -847,7 +877,7 @@ Vector2[] GetPoints() //Delete selected if (selectedPoint != null && ImGui.IsKeyPressed(ImGuiKey.Delete)) { - rail.mPoints.Remove(selectedPoint); + rail.mPoints.Remove(selectedPoint); } if (selectedPoint != null && ImGui.IsMouseReleased(0)) { @@ -856,7 +886,7 @@ Vector2[] GetPoints() if (matching.Count > 1) rail.mPoints.Remove(selectedPoint); } - + bool add_point = ImGui.IsMouseClicked(0) && ImGui.IsMouseDown(0) && ImGui.GetIO().KeyAlt; //Insert point to selected @@ -867,9 +897,9 @@ Vector2[] GetPoints() var index = rail.mPoints.IndexOf(selectedPoint); var newPoint = new CourseRail.CourseRailPoint(selectedPoint); newPoint.mTranslate = new( - MathF.Round(posVec.X, MidpointRounding.AwayFromZero), - MathF.Round(posVec.Y, MidpointRounding.AwayFromZero), - selectedPoint.mTranslate.Z); + MathF.Round(posVec.X, MidpointRounding.AwayFromZero), + MathF.Round(posVec.Y, MidpointRounding.AwayFromZero), + selectedPoint.mTranslate.Z); if (rail.mPoints.Count - 1 == index) rail.mPoints.Add(newPoint); @@ -886,9 +916,9 @@ Vector2[] GetPoints() var newPoint = new CourseRail.CourseRailPoint(); newPoint.mTranslate = new( - MathF.Round(posVec.X, MidpointRounding.AwayFromZero), - MathF.Round(posVec.Y, MidpointRounding.AwayFromZero), - 0); + MathF.Round(posVec.X, MidpointRounding.AwayFromZero), + MathF.Round(posVec.Y, MidpointRounding.AwayFromZero), + 0); rail.mPoints.Add(newPoint); @@ -971,18 +1001,23 @@ Vector2[] GetPoints() if (actor.mActorPack.ShapeParams != null) { var calc = actor.mActorPack.ShapeParams.mCalc; - min = calc.mMin; - max = calc.mMax; - center = calc.mCenter; if(actor.mActorPack.ShapeParams.mSphere != null) { drawing = "sphere"; } - else if(actor.mActorPack.ShapeParams.mCapsule != null) + if(actor.mActorPack.ShapeParams.mCapsule != null) + { + drawing = "sphere"; + } + if(actor.mActorPack.ShapeParams.mPoly != null && actor.mActorPack.ShapeParams.mPoly.Count > 0) { - drawing = "cap"; + calc = actor.mActorPack.ShapeParams.mPoly[0].mCalc; } + + min = calc.mMin; + max = calc.mMax; + center = calc.mCenter; } string layer = actor.mLayer; @@ -1031,11 +1066,6 @@ Vector2[] GetPoints() default: for (int i = 0; i < 4; i++) { - if (mEditContext.IsSelected(actor)) - { - mDrawList.AddCircleFilled(s_actorRectPolygon[i], - pointSize, color); - } mDrawList.AddLine( s_actorRectPolygon[i], s_actorRectPolygon[(i+1) % 4 ], @@ -1044,11 +1074,24 @@ Vector2[] GetPoints() break; case "sphere": var pos = WorldToScreen(Vector3.Transform(center, transform)); - var rad = WorldToScreen(Vector3.Transform(max, transform)).X- - WorldToScreen(Vector3.Transform(center, transform)).X; - mDrawList.AddCircle(pos, Math.Abs(rad), color, 0, isHovered ? 2.5f : 1.5f); + var scale = Matrix4x4.CreateScale(actor.mScale); + Vector2 rad = (WorldToScreen(Vector3.Transform(max, scale))-WorldToScreen(Vector3.Transform(min, scale)))/2; + mDrawList.AddEllipse(pos, Math.Abs(rad.X), Math.Abs(rad.Y), color, -actor.mRotation.Z, 0, isHovered ? 2.5f : 1.5f); break; } + if (mEditContext.IsSelected(actor)) + { + for (int i = 0; i < 4; i++) + { + mDrawList.AddCircleFilled(s_actorRectPolygon[i], + pointSize, color); + mDrawList.AddLine( + s_actorRectPolygon[i], + s_actorRectPolygon[(i+1) % 4 ], + color, isHovered ? 2.5f : 1.5f); + } + mDrawList.AddEllipse(WorldToScreen(Vector3.Transform(new(0), transform)), pointSize*3, pointSize*3, color, -actor.mRotation.Z, 4, 2); + } string name = actor.mActorName; diff --git a/Fushigi/windowing/ImGuiController.cs b/Fushigi/windowing/ImGuiController.cs index 77cabd59..20b49a71 100644 --- a/Fushigi/windowing/ImGuiController.cs +++ b/Fushigi/windowing/ImGuiController.cs @@ -16,6 +16,9 @@ using Silk.NET.Windowing.Glfw; using Sdl = Silk.NET.SDL.Sdl; using Silk.NET.Windowing.Sdl; +using Silk.NET.SDL; +using PixelFormat = Silk.NET.OpenGL.PixelFormat; +using PixelType = Silk.NET.OpenGL.PixelType; namespace Fushigi.windowing; @@ -109,7 +112,13 @@ public ImGuiController(GL gl, IWindow window, IInputContext input, Action? onCon CreateDeviceResources(); - SetKeyMappings(); + foreach (var key in input.Keyboards[0].SupportedKeys) + { + if (TryMapKey(key, out ImGuiKey imguikey)) + { + io.AddKeyEvent(imguikey, input.Keyboards[0].IsKeyPressed(key)); + } + } SetPerFrameImGuiData(1f / 60f); @@ -157,9 +166,10 @@ private void OnKeyDown(IKeyboard keyboard, Key key, int scanCode) if (key == Key.Unknown) return; - key = TranslateKeyFunc?.Invoke(key, scanCode) ?? key; - - ImGui.GetIO().KeysDown[(int)key] = true; + if (TryMapKey(key, out ImGuiKey imguikey)) + { + ImGui.GetIO().AddKeyEvent(imguikey, true); + } } private void OnKeyUp(IKeyboard keyboard, Key key, int scanCode) @@ -167,9 +177,10 @@ private void OnKeyUp(IKeyboard keyboard, Key key, int scanCode) if (key == Key.Unknown) return; - key = TranslateKeyFunc?.Invoke(key, scanCode) ?? key; - - ImGui.GetIO().KeysDown[(int)key] = false; + if (TryMapKey(key, out ImGuiKey imguikey)) + { + ImGui.GetIO().AddKeyEvent(imguikey, false); + } } private void WindowResized(Vector2D size) @@ -224,6 +235,7 @@ public void Update(float deltaSeconds) } SetPerFrameImGuiData(deltaSeconds); + UpdateImGuiInput(); _frameBegun = true; @@ -252,62 +264,104 @@ private void SetPerFrameImGuiData(float deltaSeconds) io.DeltaTime = deltaSeconds; // DeltaTime is in seconds. } - private void UpdateImGuiInput() - { - var io = ImGuiNET.ImGui.GetIO(); - - var mouseState = _input.Mice[0].CaptureState(); - var keyboardState = _input.Keyboards[0]; - - io.MouseDown[0] = mouseState.IsButtonPressed(MouseButton.Left); - io.MouseDown[1] = mouseState.IsButtonPressed(MouseButton.Right); - io.MouseDown[2] = mouseState.IsButtonPressed(MouseButton.Middle); + private bool TryMapKey(Key key, out ImGuiKey result) + { + ImGuiKey KeyToImGuiKeyShortcut(Key keyToConvert, Key startKey1, ImGuiKey startKey2) + { + int changeFromStart1 = (int)keyToConvert - (int)startKey1; + return startKey2 + changeFromStart1; + } - io.MousePos = new Vector2((int)mouseState.Position.X, (int)mouseState.Position.Y); + result = key switch + { + >= Key.F1 and <= Key.F24 => KeyToImGuiKeyShortcut(key, Key.F1, ImGuiKey.F1), + >= Key.Keypad0 and <= Key.Keypad9 => KeyToImGuiKeyShortcut(key, Key.Keypad0, ImGuiKey.Keypad0), + >= Key.A and <= Key.Z => KeyToImGuiKeyShortcut(key, Key.A, ImGuiKey.A), + >= Key.Number0 and <= Key.Number9 => KeyToImGuiKeyShortcut(key, Key.Number0, ImGuiKey._0), + Key.ShiftLeft => ImGuiKey.LeftShift, + Key.ShiftRight => ImGuiKey.RightShift, + Key.ControlLeft => ImGuiKey.LeftCtrl, + Key.ControlRight => ImGuiKey.RightCtrl, + Key.AltLeft => ImGuiKey.LeftAlt, + Key.AltRight => ImGuiKey.RightAlt, + Key.SuperLeft => ImGuiKey.LeftSuper, + Key.SuperRight => ImGuiKey.RightSuper, + Key.Menu => ImGuiKey.Menu, + Key.Up => ImGuiKey.UpArrow, + Key.Down => ImGuiKey.DownArrow, + Key.Left => ImGuiKey.LeftArrow, + Key.Right => ImGuiKey.RightArrow, + Key.Enter => ImGuiKey.Enter, + Key.Escape => ImGuiKey.Escape, + Key.Space => ImGuiKey.Space, + Key.Tab => ImGuiKey.Tab, + Key.Backspace => ImGuiKey.Backspace, + Key.Insert => ImGuiKey.Insert, + Key.Delete => ImGuiKey.Delete, + Key.PageUp => ImGuiKey.PageUp, + Key.PageDown => ImGuiKey.PageDown, + Key.Home => ImGuiKey.Home, + Key.End => ImGuiKey.End, + Key.CapsLock => ImGuiKey.CapsLock, + Key.ScrollLock => ImGuiKey.ScrollLock, + Key.PrintScreen => ImGuiKey.PrintScreen, + Key.Pause => ImGuiKey.Pause, + Key.NumLock => ImGuiKey.NumLock, + Key.KeypadDivide => ImGuiKey.KeypadDivide, + Key.KeypadMultiply => ImGuiKey.KeypadMultiply, + Key.KeypadSubtract => ImGuiKey.KeypadSubtract, + Key.KeypadAdd => ImGuiKey.KeypadAdd, + Key.KeypadDecimal => ImGuiKey.KeypadDecimal, + Key.KeypadEnter => ImGuiKey.KeypadEnter, + Key.GraveAccent => ImGuiKey.GraveAccent, + Key.Minus => ImGuiKey.Minus, + Key.Equal => ImGuiKey.Equal, + Key.LeftBracket => ImGuiKey.LeftBracket, + Key.RightBracket => ImGuiKey.RightBracket, + Key.Semicolon => ImGuiKey.Semicolon, + Key.Apostrophe => ImGuiKey.Apostrophe, + Key.Comma => ImGuiKey.Comma, + Key.Period => ImGuiKey.Period, + Key.Slash => ImGuiKey.Slash, + Key.BackSlash => ImGuiKey.Backslash, + _ => ImGuiKey.None + }; - var wheel = mouseState.GetScrollWheels()[0]; - io.MouseWheel = wheel.Y; - io.MouseWheelH = wheel.X; + return result != ImGuiKey.None; + } - foreach (var c in _pressedChars) + internal void PressChar(char keyChar) { - io.AddInputCharacter(c); + _pressedChars.Add(keyChar); } - _pressedChars.Clear(); + private void UpdateImGuiInput() + { + ImGuiIOPtr io = ImGui.GetIO(); - io.KeyCtrl = keyboardState.IsKeyPressed(Key.ControlLeft) || keyboardState.IsKeyPressed(Key.ControlRight); - io.KeyAlt = keyboardState.IsKeyPressed(Key.AltLeft) || keyboardState.IsKeyPressed(Key.AltRight); - io.KeyShift = keyboardState.IsKeyPressed(Key.ShiftLeft) || keyboardState.IsKeyPressed(Key.ShiftRight); - io.KeySuper = keyboardState.IsKeyPressed(Key.SuperLeft) || keyboardState.IsKeyPressed(Key.SuperRight); - } + var mouseState = _input.Mice[0].CaptureState(); + var keyboardState = _input.Keyboards[0]; - internal void PressChar(char keyChar) - { - _pressedChars.Add(keyChar); - } - private static void SetKeyMappings() - { - var io = ImGuiNET.ImGui.GetIO(); - io.KeyMap[(int)ImGuiKey.Tab] = (int)Key.Tab; - io.KeyMap[(int)ImGuiKey.LeftArrow] = (int)Key.Left; - io.KeyMap[(int)ImGuiKey.RightArrow] = (int)Key.Right; - io.KeyMap[(int)ImGuiKey.UpArrow] = (int)Key.Up; - io.KeyMap[(int)ImGuiKey.DownArrow] = (int)Key.Down; - io.KeyMap[(int)ImGuiKey.PageUp] = (int)Key.PageUp; - io.KeyMap[(int)ImGuiKey.PageDown] = (int)Key.PageDown; - io.KeyMap[(int)ImGuiKey.Home] = (int)Key.Home; - io.KeyMap[(int)ImGuiKey.End] = (int)Key.End; - io.KeyMap[(int)ImGuiKey.Delete] = (int)Key.Delete; - io.KeyMap[(int)ImGuiKey.Backspace] = (int)Key.Backspace; - io.KeyMap[(int)ImGuiKey.Enter] = (int)Key.Enter; - io.KeyMap[(int)ImGuiKey.Escape] = (int)Key.Escape; - - for (int i = 0; i < (Key.Z - Key.A)+1; i++) - { - io.KeyMap[(int)ImGuiKey.A+i] = (int)Key.A+i; + io.AddMousePosEvent(mouseState.Position.X, mouseState.Position.Y); + io.AddMouseButtonEvent(0, mouseState.IsButtonPressed(MouseButton.Left)); + io.AddMouseButtonEvent(1, mouseState.IsButtonPressed(MouseButton.Right)); + io.AddMouseButtonEvent(2, mouseState.IsButtonPressed(MouseButton.Middle)); + io.AddMouseButtonEvent(3, mouseState.IsButtonPressed(MouseButton.Button4)); + io.AddMouseButtonEvent(4, mouseState.IsButtonPressed(MouseButton.Button5)); + + io.AddMouseWheelEvent(mouseState.GetScrollWheels()[0].X, mouseState.GetScrollWheels()[0].Y); + foreach (var c in _pressedChars) + { + io.AddInputCharacter(c); + } + + _pressedChars.Clear(); + + ImGui.GetIO().AddKeyEvent(ImGuiKey.ModCtrl, ImGui.IsKeyDown(ImGuiKey.LeftCtrl) || ImGui.IsKeyDown(ImGuiKey.RightCtrl)); + ImGui.GetIO().AddKeyEvent(ImGuiKey.ModAlt, ImGui.IsKeyDown(ImGuiKey.LeftAlt) || ImGui.IsKeyDown(ImGuiKey.RightAlt)); + ImGui.GetIO().AddKeyEvent(ImGuiKey.ModShift, ImGui.IsKeyDown(ImGuiKey.LeftShift) || ImGui.IsKeyDown(ImGuiKey.RightShift)); + ImGui.GetIO().AddKeyEvent(ImGuiKey.ModSuper, ImGui.IsKeyDown(ImGuiKey.LeftSuper) || ImGui.IsKeyDown(ImGuiKey.RightSuper)); } - } private unsafe void SetupRenderState(ImDrawDataPtr drawDataPtr, int framebufferWidth, int framebufferHeight) { From 0fd4654da2342d8f9e79dd29736f785c654dbf46 Mon Sep 17 00:00:00 2001 From: Donavin Draws <51259260+DonavinDraws@users.noreply.github.com> Date: Thu, 23 Nov 2023 20:27:36 -0600 Subject: [PATCH 3/6] Fixed It is --- Fushigi/ui/widgets/CourseScene.cs | 3 +- Fushigi/ui/widgets/LevelViewport.cs | 46 +++++++++++------------------ 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/Fushigi/ui/widgets/CourseScene.cs b/Fushigi/ui/widgets/CourseScene.cs index 4457f732..eca6b4fe 100644 --- a/Fushigi/ui/widgets/CourseScene.cs +++ b/Fushigi/ui/widgets/CourseScene.cs @@ -7,6 +7,7 @@ using ImGuiNET; using Silk.NET.OpenGL; using System.Collections.Immutable; +using System.Drawing; using System.Numerics; using System.Runtime.CompilerServices; @@ -221,7 +222,7 @@ public void DrawUI(GL gl, double deltaSeconds) ImGui.OpenPopup("AreaParams"); //Display Mouse Position - if (ImGui.IsWindowHovered()) + if (new RectangleF((PointF)topLeft, (SizeF)size).Contains((PointF)ImGui.GetMousePos())) { var _mousePos = activeViewport.ScreenToWorld(ImGui.GetMousePos()); ImGui.Text("X: " + Math.Round(_mousePos.X, 3) + "\nY: " + Math.Round(_mousePos.Y, 3)); diff --git a/Fushigi/ui/widgets/LevelViewport.cs b/Fushigi/ui/widgets/LevelViewport.cs index d630af0e..4bd5ece6 100644 --- a/Fushigi/ui/widgets/LevelViewport.cs +++ b/Fushigi/ui/widgets/LevelViewport.cs @@ -8,11 +8,8 @@ using System.Drawing; using System.Numerics; using System.Runtime.InteropServices; -using static Fushigi.ui.SceneObjects.bgunit.BGUnitRailSceneObj; -using Fushigi.ui.SceneObjects.bgunit; -using System.Diagnostics; -using Silk.NET.Maths; -using ZstdSharp.Unsafe; +using static Fushigi.course.CourseUnit; +using Vector3 = System.Numerics.Vector3; namespace Fushigi.ui.widgets { @@ -30,14 +27,17 @@ public static void DefaultSelect(CourseAreaEditContext ctx, object selectable) { ctx.Select(selectable); } - else + else if(!ctx.IsSelected(selectable)) { ctx.WithSuspendUpdateDo(() => { ctx.DeselectAll(); ctx.Select(selectable); }); - + } + foreach(CourseActor act in ctx.GetSelectedObjects()) + { + act.mStartingTrans = act.mTranslation; } } } @@ -63,7 +63,7 @@ internal class LevelViewport(CourseArea area, GL gl, CourseAreaScene areaScene) Vector2 mSize = Vector2.Zero; - private ulong prevSelect; + public ulong prevSelectVersion { get; private set; } = 0; private Vector3? mSelectedPoint; private int mWallIdx = -1; private int mUnitIdx = -1; @@ -419,6 +419,7 @@ public void Draw(Vector2 size, double deltaSeconds, IDictionary la } } + if (ImGui.IsItemClicked()) { bool isModeActor = mHoveredObject != null; @@ -438,29 +439,18 @@ public void Draw(Vector2 size, double deltaSeconds, IDictionary la * we clear our selected actors array */ if (mHoveredObject == null) { - mEditContext.DeselectAll(); + if(!ImGui.IsKeyDown(ImGuiKey.LeftShift)) + mEditContext.DeselectAll(); } else if (mHoveredObject is IViewportSelectable obj) { - if (ImGui.IsKeyDown(ImGuiKey.LeftShift)) - { - prevSelect = mEditContext.SelectionVersion; - mEditContext.Select(mHoveredObject!); - } - else if(!mEditContext.IsSelected(mHoveredObject)) - { - mEditContext.DeselectAll(); - mEditContext.Select(mHoveredObject!); - } - foreach(CourseActor actor in mEditContext.GetSelectedObjects()) - { - actor.mStartingTrans = actor.mTranslation; - } + prevSelectVersion = mEditContext.SelectionVersion; obj.OnSelect(mEditContext); } else { //TODO remove this once all course objects have IViewportSelectable SceneObjs + prevSelectVersion = mEditContext.SelectionVersion; IViewportSelectable.DefaultSelect(mEditContext, mHoveredObject); } @@ -474,20 +464,20 @@ public void Draw(Vector2 size, double deltaSeconds, IDictionary la } } - if(mHoveredObject != null && ImGui.IsMouseReleased(ImGuiMouseButton.Left) && - mHoveredObject is not BGUnitRailSceneObj && mHoveredObject is not BGUnitRailSceneObj.RailPoint) + if(mHoveredObject != null && + ImGui.IsMouseReleased(ImGuiMouseButton.Left)) { if (ImGui.GetIO().MouseDragMaxDistanceSqr[0] <= ImGui.GetIO().MouseDragThreshold) { - if(ImGui.IsKeyDown(ImGuiKey.LeftShift) && - (mEditContext.SelectionVersion == prevSelect)) + if(ImGui.IsKeyDown(ImGuiKey.LeftShift) + && prevSelectVersion == mEditContext.SelectionVersion) { mEditContext.Deselect(mHoveredObject!); } else if(!ImGui.IsKeyDown(ImGuiKey.LeftShift)) { mEditContext.DeselectAll(); - mEditContext.Select(mHoveredObject!); + IViewportSelectable.DefaultSelect(mEditContext, mHoveredObject); } } } From 672f2874d56cbe4c56deb0bd883a1b68f7e12ff5 Mon Sep 17 00:00:00 2001 From: Donavin Draws <51259260+DonavinDraws@users.noreply.github.com> Date: Sat, 25 Nov 2023 19:23:44 -0600 Subject: [PATCH 4/6] Recursive Pack Parsing & Minimap Base --- Fushigi/actor_pack/ActorPack.cs | 74 ++++++++++++++--- Fushigi/actor_pack/components/ModelInfo.cs | 6 ++ Fushigi/ui/widgets/CourseMiniView.cs | 81 +++++++++++++++++++ Fushigi/ui/widgets/CourseScene.cs | 94 +++++++++++++++++++++- Fushigi/ui/widgets/LevelViewport.cs | 71 ++++++++-------- 5 files changed, 280 insertions(+), 46 deletions(-) create mode 100644 Fushigi/ui/widgets/CourseMiniView.cs diff --git a/Fushigi/actor_pack/ActorPack.cs b/Fushigi/actor_pack/ActorPack.cs index dfb17cc7..a79242fe 100644 --- a/Fushigi/actor_pack/ActorPack.cs +++ b/Fushigi/actor_pack/ActorPack.cs @@ -33,6 +33,7 @@ public static ActorPack Load(string gyml) public class ActorPack { + Dictionary paramTree = []; public ModelInfo DrawArrayModelInfoRef; public ModelInfo ModelInfoRef; public ModelExpandParam ModelExpandParamRef; @@ -84,11 +85,35 @@ private void Load(string path) { var paramInfo = BymlSerialize.Deserialize(sarc.OpenFile(file)); - LoadComponents(sarc, paramInfo); + paramInfo.path = file; + if(paramInfo.Components != null) + paramTree.Add(GetPathGyml(paramInfo.parent ?? "root"), paramInfo); + } + + foreach (var param in paramTree) + { + if(param.Key == "root") + { + LoadComponents(sarc, param.Value); + + if (!string.IsNullOrEmpty(param.Value.Category)) + this.Category = param.Value.Category; + + var parFile = param.Value.path; + while(paramTree.ContainsKey(parFile)) + { + var parent = paramTree[parFile]; + + LoadComponents(sarc, parent); + + if (!string.IsNullOrEmpty(parent.Category)) + this.Category = parent.Category; - if (!string.IsNullOrEmpty(paramInfo.Category)) - this.Category = paramInfo.Category; + parFile = parent.path; + } + } } + stream.Dispose(); } @@ -109,10 +134,29 @@ private void LoadComponents(SARC.SARC sarc, ActorParam param) switch (component.Key) { case "DrawArrayModelInfoRef": - this.DrawArrayModelInfoRef = BymlSerialize.Deserialize(data); + if(DrawArrayModelInfoRef == null) + this.DrawArrayModelInfoRef = BymlSerialize.Deserialize(data); + else{ + var child = BymlSerialize.Deserialize(data); + foreach(var v in DrawArrayModelInfoRef.GetType().GetProperties()) + { + if (v.GetValue(child) != null && v.GetValue(child) != default) + v.SetValue(DrawArrayModelInfoRef, v.GetValue(child)); + } + } break; case "ModelInfoRef": - this.ModelInfoRef = BymlSerialize.Deserialize(data); + if(ModelInfoRef == null) + this.ModelInfoRef = BymlSerialize.Deserialize(data); + else{ + var child = BymlSerialize.Deserialize(data); + foreach(var v in ModelInfoRef.GetType().GetProperties()) + { + + if (v.GetValue(child) != null && v.GetValue(child) != default) + v.SetValue(ModelInfoRef, v.GetValue(child)); + } + } break; case "ModelExpandRef": this.ModelExpandParamRef = BymlSerialize.Deserialize(data); @@ -123,14 +167,13 @@ private void LoadComponents(SARC.SARC sarc, ActorParam param) case "GamePhysicsRef": this.GamePhysicsRef = BymlSerialize.Deserialize(data); if(!string.IsNullOrEmpty(GamePhysicsRef.mPath)) - GetActorShape(sarc, data, filePath); - + ShapeParams = GetActorShape(sarc, data, filePath); break; } } } - private void GetActorShape(SARC.SARC sarc, byte[] data, string filePath) + private ShapeParamList GetActorShape(SARC.SARC sarc, byte[] data, string filePath) { filePath = GetPathGyml(GamePhysicsRef.mPath); data = sarc.OpenFile(filePath); @@ -138,13 +181,14 @@ private void GetActorShape(SARC.SARC sarc, byte[] data, string filePath) if(ControllerPath.ShapeNamePathAry != null) { var shapes = ControllerPath.ShapeNamePathAry; - if (!string.IsNullOrEmpty(ControllerPath.parent)) + while (!string.IsNullOrEmpty(ControllerPath.parent) && + ControllerPath.mRigids == null && ControllerPath.mEntity == null) { filePath = GetPathGyml(ControllerPath.parent); data = sarc.OpenFile(filePath); ControllerPath = BymlSerialize.Deserialize(data); } - var rigidBodies = ControllerPath.mRigids != null && ControllerPath.mRigids.Count > 0 ? ControllerPath.mRigids : ControllerPath.mEntity; + var rigidBodies = (ControllerPath.mRigids ?? new()).Concat(ControllerPath.mEntity ?? new()); foreach(var rigid in rigidBodies) { @@ -160,7 +204,7 @@ private void GetActorShape(SARC.SARC sarc, byte[] data, string filePath) { filePath = GetPathGyml(shape.FilePath); data = sarc.OpenFile(filePath); - ShapeParams = BymlSerialize.Deserialize(data); + return BymlSerialize.Deserialize(data); } } else if(body.ShapeNames != null) @@ -169,12 +213,13 @@ private void GetActorShape(SARC.SARC sarc, byte[] data, string filePath) { filePath = GetPathGyml(shape.FilePath); data = sarc.OpenFile(filePath); - ShapeParams = BymlSerialize.Deserialize(data); + return BymlSerialize.Deserialize(data); } } } } } + return null; } private string GetPathGyml(string path) @@ -185,6 +230,11 @@ private string GetPathGyml(string path) class ActorParam { + public string path; + + [BymlProperty("$parent")] + public string parent { get; set; } + public string Category { get; set; } public Dictionary Components { get; set; } } diff --git a/Fushigi/actor_pack/components/ModelInfo.cs b/Fushigi/actor_pack/components/ModelInfo.cs index fcaec0b1..2a59b414 100644 --- a/Fushigi/actor_pack/components/ModelInfo.cs +++ b/Fushigi/actor_pack/components/ModelInfo.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Numerics; using System.Text; using System.Threading.Tasks; @@ -10,12 +11,17 @@ namespace Fushigi.actor_pack.components [Serializable] public class ModelInfo { + [BymlProperty("$parent")] + public string parent { get; set; } + [BymlProperty("FmdbName", DefaultValue = "")] public string mModelName { get; set; } [BymlProperty("ModelProjectName", DefaultValue = "")] public string mFilePath { get; set; } + [BymlProperty("DebugModelScale")] + public Vector3 mModelScale { get; set; } public string SearchModelKey { get; set; } public List SubModels { get; set; } diff --git a/Fushigi/ui/widgets/CourseMiniView.cs b/Fushigi/ui/widgets/CourseMiniView.cs new file mode 100644 index 00000000..ee0593be --- /dev/null +++ b/Fushigi/ui/widgets/CourseMiniView.cs @@ -0,0 +1,81 @@ +using Fushigi.course; +using ImGuiNET; +using System.Numerics; + +namespace Fushigi.ui.widgets +{ + internal class CourseMiniView + { + float ratio; + Vector2 center; + + Vector4 levelBounds; + Vector2 levelRect; + Vector2 miniLevelRect; + + Vector2 miniCamPos; + Vector2 miniCamSize; + + Vector3 camSave; + + public void Draw(CourseArea area, CourseAreaEditContext editContext, LevelViewport viewport) + { + var topLeft = ImGui.GetCursorScreenPos(); + ImGui.SetCursorScreenPos(topLeft); + + var size = ImGui.GetContentRegionAvail(); + + var cam = viewport.Camera; + var camSize = viewport.GetCameraSizeIn2DWorldSpace(); + + foreach(var actor in area.GetActors()) + { + levelBounds = new(Math.Min(levelBounds.X, actor.mTranslation.X), + Math.Min(levelBounds.Y, actor.mTranslation.Y), + Math.Max(levelBounds.Z, actor.mTranslation.X), + Math.Max(levelBounds.W, actor.mTranslation.Y)); + } + levelRect = new Vector2(levelBounds.Z-levelBounds.X, levelBounds.W - levelBounds.Y); + + ratio = size.X/levelBounds.X < size.Y/levelBounds.Y ? + size.X/levelBounds.X : size.Y/levelBounds.Y; + + miniLevelRect = levelRect*ratio; + + miniCamPos = new Vector2(cam.Target.X - levelBounds.X, -cam.Target.Y + levelBounds.Y)*ratio-miniCamSize/2; + miniCamSize = camSize*ratio; + center = new Vector2((size.X - levelRect.X)/2, (size.Y - levelRect.Y)/2); + + var lvlTopLeft = topLeft + center; + + ImGui.GetWindowDrawList().AddRect(lvlTopLeft, + lvlTopLeft + miniLevelRect, ImGui.ColorConvertFloat4ToU32(new(1, 1, 1, 1))); + + ImGui.GetWindowDrawList().AddRect(lvlTopLeft + miniCamPos + new Vector2(0, miniLevelRect.Y), + lvlTopLeft + miniCamPos + miniCamSize + new Vector2(0, miniLevelRect.Y), ImGui.ColorConvertFloat4ToU32(new(0, 0, 1, 1))); + + if (ImGui.IsMouseClicked(ImGuiMouseButton.Right) && !ImGui.IsMouseDown(ImGuiMouseButton.Left) + && ImGui.IsWindowHovered()) + { + camSave = cam.Target; + } + + if ((ImGui.IsMouseDown(ImGuiMouseButton.Left) || ImGui.IsMouseDown(ImGuiMouseButton.Right)) + && ImGui.IsWindowFocused() && + ((!ImGui.IsMouseClicked(ImGuiMouseButton.Left) && !ImGui.IsMouseClicked(ImGuiMouseButton.Right)) + || ImGui.IsWindowHovered())) + { + var pos = ImGui.GetMousePos(); + pos.Y *= -1; + cam.Target = new((pos - lvlTopLeft)/ratio + new Vector2(levelBounds.X, levelBounds.Y), + cam.Target.Z); + } + + + if (ImGui.IsMouseReleased(ImGuiMouseButton.Right) && !ImGui.IsMouseDown(ImGuiMouseButton.Left)) + { + cam.Target = camSave; + } + } + } +} \ No newline at end of file diff --git a/Fushigi/ui/widgets/CourseScene.cs b/Fushigi/ui/widgets/CourseScene.cs index eca6b4fe..00d9c01b 100644 --- a/Fushigi/ui/widgets/CourseScene.cs +++ b/Fushigi/ui/widgets/CourseScene.cs @@ -1,4 +1,5 @@ using Fushigi.course; +using Fushigi.gl; using Fushigi.gl.Bfres; using Fushigi.param; using Fushigi.ui.SceneObjects; @@ -21,6 +22,7 @@ class CourseScene Dictionary? lastCreatedViewports; public LevelViewport activeViewport; UndoWindow undoWindow; + Vector3 camSave; readonly Course course; CourseArea selectedArea; @@ -166,6 +168,8 @@ public void DrawUI(GL gl, double deltaSeconds) BGUnitPanel(); + CourseMiniView(); + if (mShowAddActor) { SelectActorToAdd(); @@ -222,7 +226,7 @@ public void DrawUI(GL gl, double deltaSeconds) ImGui.OpenPopup("AreaParams"); //Display Mouse Position - if (new RectangleF((PointF)topLeft, (SizeF)size).Contains((PointF)ImGui.GetMousePos())) + if (ImGui.IsMouseHoveringRect(topLeft, topLeft + size)) { var _mousePos = activeViewport.ScreenToWorld(ImGui.GetMousePos()); ImGui.Text("X: " + Math.Round(_mousePos.X, 3) + "\nY: " + Math.Round(_mousePos.Y, 3)); @@ -257,6 +261,8 @@ public void DrawUI(GL gl, double deltaSeconds) lastCreatedViewports = viewports; } + //minimap.Draw(selectedArea, areaScenes[selectedArea].EditContext, viewports[selectedArea]); + if (status) ImGui.End(); } @@ -1503,6 +1509,92 @@ private void CourseActorsLayerView(CourseActorHolder actorArray) ImGui.EndChild(); } + private void CourseMiniView() + { + var area = selectedArea; + var editContext = areaScenes[area].EditContext; + var view = viewports[area]; + bool status = ImGui.Begin("Minimap", ImGuiWindowFlags.NoNav); + + var topLeft = ImGui.GetCursorScreenPos(); + + ImGui.SetNextItemAllowOverlap(); + ImGui.SetCursorScreenPos(topLeft); + + //ImGui.SetNextItemAllowOverlap(); + var size = ImGui.GetContentRegionAvail(); + + ImGui.SetNextItemAllowOverlap(); + ImGui.SetCursorScreenPos(topLeft); + + var cam = view.Camera; + + Vector4 bounds = Vector4.Zero; + foreach(var actor in area.GetActors()) + { + bounds = new(Math.Min(bounds.X, actor.mTranslation.X), + Math.Min(bounds.Y, actor.mTranslation.Y), + Math.Max(bounds.Z, actor.mTranslation.X), + Math.Max(bounds.W, actor.mTranslation.Y)); + } + var levelRect = new Vector2(bounds.Z-bounds.X, bounds.W - bounds.Y); + + float tanFOV = MathF.Tan(cam.Fov / 2); + + var ratio = size.X/levelRect.X < size.Y/levelRect.Y ? size.X/levelRect.X : size.Y/levelRect.Y; + var miniRect = levelRect*ratio; + var miniCam = new Vector2(cam.Target.X, -cam.Target.Y)*ratio; + var miniCamSize = view.GetCameraSizeIn2DWorldSpace()*ratio; + var miniSaveCam = new Vector2(camSave.X, -camSave.Y)*ratio; + var center = new Vector2((size.X - miniRect.X)/2, (size.Y - miniRect.Y)/2); + + var col = ImGuiCol.ButtonActive; + + //ImGui.SetNextItemAllowOverlap(); + if (ImGui.IsMouseClicked(ImGuiMouseButton.Right) && !ImGui.IsMouseDown(ImGuiMouseButton.Left) + && ImGui.IsWindowHovered()) + { + camSave = cam.Target; + } + + if ((ImGui.IsMouseDown(ImGuiMouseButton.Left) || ImGui.IsMouseDown(ImGuiMouseButton.Right)) + && ImGui.IsWindowFocused() && + ((!ImGui.IsMouseClicked(ImGuiMouseButton.Right) && !ImGui.IsMouseClicked(ImGuiMouseButton.Left)) + || ImGui.IsWindowHovered())) + { + if (camSave != default) + { + col = ImGuiCol.TextDisabled; + ImGui.GetWindowDrawList().AddRect(topLeft + miniSaveCam - miniCamSize/2 + new Vector2(0, miniRect.Y) + center, + topLeft + miniSaveCam + miniCamSize/2 + new Vector2(0, miniRect.Y) + center, + ImGui.ColorConvertFloat4ToU32(ImGui.GetStyle().Colors[(int)ImGuiCol.Button]),6,0,3); + } + + var pos = ImGui.GetMousePos(); + cam.Target = new((pos.X - (topLeft.X + center.X))/ratio, + (-pos.Y + topLeft.Y + center.Y + miniRect.Y)/ratio, cam.Target.Z); + } + + if (ImGui.IsMouseReleased(ImGuiMouseButton.Right) && !ImGui.IsMouseDown(ImGuiMouseButton.Left) + && camSave != default) + { + cam.Target = camSave; + camSave = default; + } + + ImGui.GetWindowDrawList().AddRect(topLeft + center, + topLeft + miniRect + center, + ImGui.ColorConvertFloat4ToU32(ImGui.GetStyle().Colors[(int)ImGuiCol.Text]),6,0,3); + + ImGui.GetWindowDrawList().AddRect(topLeft + miniCam - miniCamSize/2 + new Vector2(0, miniRect.Y) + center, + topLeft + miniCam + miniCamSize/2 + new Vector2(0, miniRect.Y) + center, + ImGui.ColorConvertFloat4ToU32(ImGui.GetStyle().Colors[(int)col]),6,0,3); + + if (status) + ImGui.End(); + + } + private static void PlacementNode(CourseActor actor) { static void EditFloat3RadAsDeg(string label, ref System.Numerics.Vector3 rad, float speed) diff --git a/Fushigi/ui/widgets/LevelViewport.cs b/Fushigi/ui/widgets/LevelViewport.cs index 4bd5ece6..a597def9 100644 --- a/Fushigi/ui/widgets/LevelViewport.cs +++ b/Fushigi/ui/widgets/LevelViewport.cs @@ -4,6 +4,7 @@ using Fushigi.gl.Bfres; using Fushigi.util; using ImGuiNET; +using Silk.NET.Maths; using Silk.NET.OpenGL; using System.Drawing; using System.Numerics; @@ -108,6 +109,12 @@ public enum EditorMode public Matrix4x4 GetCameraMatrix() => Camera.ViewProjectionMatrix; + public Vector2 GetCameraSizeIn2DWorldSpace() + { + var cameraBoundsSize = ScreenToWorld(mSize) - ScreenToWorld(new Vector2(0)); + return new Vector2(cameraBoundsSize.X, Math.Abs(cameraBoundsSize.Y)); + } + public Vector2 WorldToScreen(Vector3 pos) => WorldToScreen(pos, out _); public Vector2 WorldToScreen(Vector3 pos, out float ndcDepth) { @@ -164,7 +171,7 @@ public void SelectedActor(CourseActor actor) public void HandleCameraControls(double deltaSeconds) { - bool isPanGesture = (ImGui.IsMouseDragging(ImGuiMouseButton.Middle)) || + bool isPanGesture = ImGui.IsMouseDragging(ImGuiMouseButton.Middle) || (ImGui.IsMouseDragging(ImGuiMouseButton.Left) && ImGui.GetIO().KeyShift && !mEditContext.IsAnySelected()); if (IsViewportActive && isPanGesture) @@ -272,35 +279,35 @@ private void RenderActor(CourseActor actor, ModelInfo modelInfo) var rotMat = Matrix4x4.CreateRotationX(actor.mRotation.X) * Matrix4x4.CreateRotationY(actor.mRotation.Y) * Matrix4x4.CreateRotationZ(actor.mRotation.Z); + + var debugSMat = Matrix4x4.CreateScale(modelInfo.mModelScale != default ? modelInfo.mModelScale:Vector3.One); - var mat = scaleMat * rotMat * transMat; + var mat = debugSMat * scaleMat * rotMat * transMat; var model = render.Models[modelName]; //switch for drawing models with different methods easier - switch (modelName){ - case "DokanJunction": - case "DokanTop": - var drainRef = actor.mActorPack.DrainPipeRef; - - var KeyMats = new Dictionary{ - {drainRef.ModelKeyTop, - Matrix4x4.CreateScale(actor.mScale.X, actor.mScale.X, actor.mScale.Z) * - Matrix4x4.CreateTranslation(0, (actor.mScale.Y-actor.mScale.X)*2, 0) * - rotMat * - transMat}, - - {drainRef.ModelKeyMiddle, - Matrix4x4.CreateScale(actor.mScale.X, actor.mScale.Y*2, actor.mScale.Z) * - rotMat * - transMat}}; - - render.Models[modelName].Render(gl, render, KeyMats[modelInfo.SearchModelKey], this.Camera); - if(modelInfo.SubModels.Any()) - render.Models[modelInfo.SubModels[0].FmdbName].Render(gl, render, KeyMats[modelInfo.SubModels[0].SearchModelKey], this.Camera); - break; - default: - model.Render(gl, render, mat, this.Camera); - break; + if(actor.mActorPack.DrainPipeRef != null){ + var drainRef = actor.mActorPack.DrainPipeRef; + var calc = actor.mActorPack.ShapeParams.mCalc; + var KeyMats = new Dictionary{ + {drainRef.ModelKeyTop ?? "Top", debugSMat * + Matrix4x4.CreateScale(actor.mScale.X, actor.mScale.X, actor.mScale.Z) * + Matrix4x4.CreateTranslation(0, (actor.mScale.Y-actor.mScale.X)*(calc.mMax.Y-calc.mMin.Y), 0) * + rotMat * + transMat}, + + {drainRef.ModelKeyMiddle ?? "Middle", debugSMat * + Matrix4x4.CreateScale(actor.mScale.X, (actor.mScale.Y-1)*2, actor.mScale.Z) * + rotMat * + transMat}}; + + render.Models[modelName].Render(gl, render, KeyMats[modelInfo.SearchModelKey], this.Camera); + if(modelInfo.SubModels?.Any() ?? false) + render.Models[modelInfo.SubModels[0].FmdbName].Render(gl, render, KeyMats[modelInfo.SubModels[0].SearchModelKey], this.Camera); + } + else + { + model.Render(gl, render, mat, this.Camera); } } @@ -464,7 +471,7 @@ public void Draw(Vector2 size, double deltaSeconds, IDictionary la } } - if(mHoveredObject != null && + if(mHoveredObject != null && mHoveredObject is CourseActor && ImGui.IsMouseReleased(ImGuiMouseButton.Left)) { if (ImGui.GetIO().MouseDragMaxDistanceSqr[0] <= ImGui.GetIO().MouseDragThreshold) @@ -982,15 +989,12 @@ Vector2[] GetPoints() { var calc = actor.mActorPack.ShapeParams.mCalc; - if(actor.mActorPack.ShapeParams.mSphere != null) + if(((actor.mActorPack.ShapeParams.mSphere?.Count ?? 0) > 0) || + ((actor.mActorPack.ShapeParams.mCapsule?.Count?? 0) > 0)) { drawing = "sphere"; } - if(actor.mActorPack.ShapeParams.mCapsule != null) - { - drawing = "sphere"; - } - if(actor.mActorPack.ShapeParams.mPoly != null && actor.mActorPack.ShapeParams.mPoly.Count > 0) + else if((actor.mActorPack.ShapeParams.mPoly?.Count ?? 0) > 0) { calc = actor.mActorPack.ShapeParams.mPoly[0].mCalc; } @@ -1057,6 +1061,7 @@ Vector2[] GetPoints() var scale = Matrix4x4.CreateScale(actor.mScale); Vector2 rad = (WorldToScreen(Vector3.Transform(max, scale))-WorldToScreen(Vector3.Transform(min, scale)))/2; mDrawList.AddEllipse(pos, Math.Abs(rad.X), Math.Abs(rad.Y), color, -actor.mRotation.Z, 0, isHovered ? 2.5f : 1.5f); + break; } if (mEditContext.IsSelected(actor)) From e812ec9ee156d9ad68cc0f9cd455ed7cc7f698fa Mon Sep 17 00:00:00 2001 From: Donavin Draws <51259260+DonavinDraws@users.noreply.github.com> Date: Mon, 27 Nov 2023 22:36:47 -0600 Subject: [PATCH 5/6] Rough Base for Local Link Trees Still need to implement recursion on getting links, currently just displays the top most links --- Fushigi/ui/widgets/CourseScene.cs | 125 +++++++++++++++++++++++++++- Fushigi/ui/widgets/LevelViewport.cs | 1 + 2 files changed, 125 insertions(+), 1 deletion(-) diff --git a/Fushigi/ui/widgets/CourseScene.cs b/Fushigi/ui/widgets/CourseScene.cs index 00d9c01b..6541a7f9 100644 --- a/Fushigi/ui/widgets/CourseScene.cs +++ b/Fushigi/ui/widgets/CourseScene.cs @@ -166,6 +166,8 @@ public void DrawUI(GL gl, double deltaSeconds) GlobalLinksPanel(); + LocalLinksPanel(); + BGUnitPanel(); CourseMiniView(); @@ -224,6 +226,7 @@ public void DrawUI(GL gl, double deltaSeconds) //Load popup when button is pressed if (ImGui.Button("Area Parameters")) ImGui.OpenPopup("AreaParams"); + ImGui.SameLine(); //Display Mouse Position if (ImGui.IsMouseHoveringRect(topLeft, topLeft + size)) @@ -550,6 +553,19 @@ private void GlobalLinksPanel() ImGui.End(); } + private void LocalLinksPanel() + { + ImGui.Begin("Local Links"); + + ImGui.Checkbox("Wonder View", ref activeViewport.IsWonderView); + + ImGui.Separator(); + + AreaLocalLinksView(selectedArea); + + ImGui.End(); + } + private void SelectionParameterPanel() { var editContext = areaScenes[selectedArea].EditContext; @@ -1333,6 +1349,112 @@ private void CourseGlobalLinksView(CourseLinkHolder linkHolder) } } } + + //VERY ROUGH BASE + //Still need to implement recursion on getting links, currently just displays the top most links + private void AreaLocalLinksView(CourseArea area) + { + var links = area.mLinkHolder; + var editContext = areaScenes[selectedArea].EditContext; + + float em = ImGui.GetFrameHeight(); + var wcMin = ImGui.GetCursorScreenPos() + new Vector2(0, ImGui.GetScrollY()); + var wcMax = wcMin + ImGui.GetContentRegionAvail(); + + RecursiveLinkFind(area, links, editContext, em); + + ImGui.PopClipRect(); + + ImGui.EndChild(); + } + + private void RecursiveLinkFind(CourseArea area, CourseLinkHolder links, CourseAreaEditContext editContext, float em) + { + foreach (CourseActor actor in area.GetActors().Where(x => !links.GetSrcHashesFromDest(x.mActorHash).Any() && links.GetDestHashesFromSrc(x.mActorHash).Any())) + { + ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags.FramePadding | ImGuiTreeNodeFlags.OpenOnArrow; + ImGui.PushID(actor.mActorHash.ToString()); + bool expanded = false; + bool isVisible = true; + float margin = 1.5f * em; + float headerHeight = 1.4f * em; + Vector2 cp = ImGui.GetCursorScreenPos(); + expanded = ImGui.TreeNodeEx(actor.mActorHash.ToString(), node_flags, actor.mActorName); + + if (ImGui.IsItemFocused()) + { + activeViewport.SelectedActor(actor); + } + + if (ImGui.IsItemHovered() && ImGui.IsMouseDoubleClicked(0)) + { + activeViewport.FrameSelectedActor(actor); + } + + if (!isVisible) + ImGui.BeginDisabled(); + + if (expanded) + { + foreach (var link in links.GetDestHashesFromSrc(actor.mActorHash)) + { + if(ImGui.TreeNodeEx(actor.mActorHash.ToString() + link.Key, ImGuiTreeNodeFlags.FramePadding, link.Key)) + { + foreach (CourseActor linkActor in area.GetActors().Where(x => link.Value.Contains(x.mActorHash))) + { + var act = linkActor; + string actorName = act.mActorName; + string name = act.mName; + ulong actorHash = act.mActorHash; + string actorLink = link.Key; + //Check if the node is within the necessary search filter requirements if search is used + bool HasText = act.mName.IndexOf(mActorSearchText, StringComparison.OrdinalIgnoreCase) >= 0 || + act.mActorName.IndexOf(mActorSearchText, StringComparison.OrdinalIgnoreCase) >= 0 || + act.ToString().Equals(mActorSearchText); + + if (!HasText) + continue; + + bool isSelected = editContext.IsSelected(act); + + ImGui.PushID(actorHash.ToString()); + ImGui.Columns(2); + + if (ImGui.Selectable(actorName, isSelected, ImGuiSelectableFlags.SpanAllColumns)) + { + activeViewport.SelectedActor(act); + } + else if (ImGui.IsItemFocused()) + { + activeViewport.SelectedActor(act); + } + + if (ImGui.IsItemHovered() && ImGui.IsMouseDoubleClicked(0)) + { + activeViewport.FrameSelectedActor(act); + } + + + ImGui.NextColumn(); + ImGui.BeginDisabled(); + ImGui.Text(name); + ImGui.EndDisabled(); + ImGui.Columns(1); + + ImGui.PopID(); + ImGui.TreePop(); + } + } + } + ImGui.TreePop(); + } + + if (!isVisible) + ImGui.EndDisabled(); + + ImGui.PopID(); + } + } private void UpdateAllLayerVisiblity() { @@ -1528,6 +1650,7 @@ private void CourseMiniView() ImGui.SetCursorScreenPos(topLeft); var cam = view.Camera; + var camSize = view.GetCameraSizeIn2DWorldSpace(); Vector4 bounds = Vector4.Zero; foreach(var actor in area.GetActors()) @@ -1544,7 +1667,7 @@ private void CourseMiniView() var ratio = size.X/levelRect.X < size.Y/levelRect.Y ? size.X/levelRect.X : size.Y/levelRect.Y; var miniRect = levelRect*ratio; var miniCam = new Vector2(cam.Target.X, -cam.Target.Y)*ratio; - var miniCamSize = view.GetCameraSizeIn2DWorldSpace()*ratio; + var miniCamSize = camSize*ratio; var miniSaveCam = new Vector2(camSave.X, -camSave.Y)*ratio; var center = new Vector2((size.X - miniRect.X)/2, (size.Y - miniRect.Y)/2); diff --git a/Fushigi/ui/widgets/LevelViewport.cs b/Fushigi/ui/widgets/LevelViewport.cs index a597def9..e8ea6731 100644 --- a/Fushigi/ui/widgets/LevelViewport.cs +++ b/Fushigi/ui/widgets/LevelViewport.cs @@ -61,6 +61,7 @@ internal class LevelViewport(CourseArea area, GL gl, CourseAreaScene areaScene) public bool IsViewportHovered; public bool IsViewportActive; + public bool IsWonderView; Vector2 mSize = Vector2.Zero; From 636bf9e5921e25b8de99c71e6ce4093619070355 Mon Sep 17 00:00:00 2001 From: Donavin Draws <51259260+DonavinDraws@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:04:35 -0600 Subject: [PATCH 6/6] proper actor name variable update my code to fit new course actor variables --- Fushigi/ui/widgets/CourseScene.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Fushigi/ui/widgets/CourseScene.cs b/Fushigi/ui/widgets/CourseScene.cs index 4932f595..15e20b8d 100644 --- a/Fushigi/ui/widgets/CourseScene.cs +++ b/Fushigi/ui/widgets/CourseScene.cs @@ -1508,16 +1508,16 @@ private void AreaLocalLinksView(CourseArea area) private void RecursiveLinkFind(CourseArea area, CourseLinkHolder links, CourseAreaEditContext editContext, float em) { - foreach (CourseActor actor in area.GetActors().Where(x => !links.GetSrcHashesFromDest(x.mActorHash).Any() && links.GetDestHashesFromSrc(x.mActorHash).Any())) + foreach (CourseActor actor in area.GetActors().Where(x => !links.GetSrcHashesFromDest(x.mHash).Any() && links.GetDestHashesFromSrc(x.mHash).Any())) { ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags.FramePadding | ImGuiTreeNodeFlags.OpenOnArrow; - ImGui.PushID(actor.mActorHash.ToString()); + ImGui.PushID(actor.mHash.ToString()); bool expanded = false; bool isVisible = true; float margin = 1.5f * em; float headerHeight = 1.4f * em; Vector2 cp = ImGui.GetCursorScreenPos(); - expanded = ImGui.TreeNodeEx(actor.mActorHash.ToString(), node_flags, actor.mActorName); + expanded = ImGui.TreeNodeEx(actor.mHash.ToString(), node_flags, actor.mPackName); if (ImGui.IsItemFocused()) { @@ -1534,20 +1534,20 @@ private void RecursiveLinkFind(CourseArea area, CourseLinkHolder links, CourseAr if (expanded) { - foreach (var link in links.GetDestHashesFromSrc(actor.mActorHash)) + foreach (var link in links.GetDestHashesFromSrc(actor.mHash)) { - if(ImGui.TreeNodeEx(actor.mActorHash.ToString() + link.Key, ImGuiTreeNodeFlags.FramePadding, link.Key)) + if(ImGui.TreeNodeEx(actor.mHash.ToString() + link.Key, ImGuiTreeNodeFlags.FramePadding, link.Key)) { - foreach (CourseActor linkActor in area.GetActors().Where(x => link.Value.Contains(x.mActorHash))) + foreach (CourseActor linkActor in area.GetActors().Where(x => link.Value.Contains(x.mHash))) { var act = linkActor; - string actorName = act.mActorName; + string actorName = act.mPackName; string name = act.mName; - ulong actorHash = act.mActorHash; + ulong actorHash = act.mHash; string actorLink = link.Key; //Check if the node is within the necessary search filter requirements if search is used bool HasText = act.mName.IndexOf(mActorSearchText, StringComparison.OrdinalIgnoreCase) >= 0 || - act.mActorName.IndexOf(mActorSearchText, StringComparison.OrdinalIgnoreCase) >= 0 || + act.mPackName.IndexOf(mActorSearchText, StringComparison.OrdinalIgnoreCase) >= 0 || act.ToString().Equals(mActorSearchText); if (!HasText)