From e8b061f018872a140345bc84cb61ea1bd586ae0f Mon Sep 17 00:00:00 2001 From: Asval Date: Fri, 28 Mar 2025 19:19:50 +0100 Subject: [PATCH] added a guizmo for model transformation --- CUE4Parse | 2 +- FModel/FModel.csproj | 2 +- FModel/Framework/ImGuiController.cs | 67 +++++---- FModel/ViewModels/CUE4ParseViewModel.cs | 8 +- FModel/Views/Snooper/Models/SkeletalModel.cs | 1 + FModel/Views/Snooper/Models/UModel.cs | 1 + FModel/Views/Snooper/Shading/Material.cs | 2 +- FModel/Views/Snooper/SnimGui.cs | 150 ++++++++++++------- FModel/Views/Snooper/Transform.cs | 77 ++++------ 9 files changed, 171 insertions(+), 139 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 24c816df..4514f1ac 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 24c816dfd462a95e087344419486a8f8008f77f5 +Subproject commit 4514f1acd51c9d3458eb0eda0abf37bb77453d2b diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 34e7e4e1..dc171282 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -156,7 +156,6 @@ - @@ -168,6 +167,7 @@ + diff --git a/FModel/Framework/ImGuiController.cs b/FModel/Framework/ImGuiController.cs index 66dd6f47..6bd5c620 100644 --- a/FModel/Framework/ImGuiController.cs +++ b/FModel/Framework/ImGuiController.cs @@ -3,12 +3,12 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Numerics; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Forms; using FModel.Settings; using ImGuiNET; +using ImGuizmoNET; using OpenTK.Graphics.OpenGL4; using OpenTK.Windowing.Desktop; using OpenTK.Windowing.GraphicsLibraryFramework; @@ -54,11 +54,12 @@ public class ImGuiController : IDisposable int major = GL.GetInteger(GetPName.MajorVersion); int minor = GL.GetInteger(GetPName.MinorVersion); - KHRDebugAvailable = (major == 4 && minor >= 3) || IsExtensionSupported("KHR_debug"); IntPtr context = ImGui.CreateContext(); ImGui.SetCurrentContext(context); + IntPtr imguiCtx = ImGui.CreateContext(); + ImGui.SetCurrentContext(imguiCtx); var io = ImGui.GetIO(); unsafe @@ -69,32 +70,24 @@ public class ImGuiController : IDisposable FontNormal = io.Fonts.AddFontFromFileTTF("C:\\Windows\\Fonts\\segoeui.ttf", 16 * DpiScale); FontBold = io.Fonts.AddFontFromFileTTF("C:\\Windows\\Fonts\\segoeuib.ttf", 16 * DpiScale); FontSemiBold = io.Fonts.AddFontFromFileTTF("C:\\Windows\\Fonts\\seguisb.ttf", 16 * DpiScale); + io.Fonts.AddFontDefault(); + io.Fonts.Build(); // Build font atlas io.BackendFlags |= ImGuiBackendFlags.RendererHasVtxOffset; io.ConfigFlags |= ImGuiConfigFlags.NavEnableKeyboard; io.ConfigFlags |= ImGuiConfigFlags.DockingEnable; - io.ConfigFlags |= ImGuiConfigFlags.ViewportsEnable; io.Fonts.Flags |= ImFontAtlasFlags.NoBakedLines; - // io.ConfigDockingWithShift = true; + io.ConfigDockingWithShift = true; io.ConfigWindowsMoveFromTitleBarOnly = true; + io.BackendRendererUserData = 0; CreateDeviceResources(); - - SetPerFrameImGuiData(1f / 60f); - - ImGui.NewFrame(); - _frameBegun = true; } + public void Normal() => PushFont(FontNormal); public void Bold() => PushFont(FontBold); public void SemiBold() => PushFont(FontSemiBold); - public void PopFont() - { - ImGui.PopFont(); - PushFont(FontNormal); - } - private void PushFont(ImFontPtr ptr) => ImGui.PushFont(ptr); public void WindowResized(int width, int height) @@ -132,34 +125,42 @@ public class ImGuiController : IDisposable RecreateFontDeviceTexture(); - string VertexSource = @"#version 460 core + string VertexSource = @"#version 330 core + uniform mat4 projection_matrix; + layout(location = 0) in vec2 in_position; layout(location = 1) in vec2 in_texCoord; layout(location = 2) in vec4 in_color; + out vec4 color; out vec2 texCoord; + void main() { -gl_Position = projection_matrix * vec4(in_position, 0, 1); -color = in_color; -texCoord = in_texCoord; + gl_Position = projection_matrix * vec4(in_position, 0, 1); + color = in_color; + texCoord = in_texCoord; }"; - string FragmentSource = @"#version 460 core + string FragmentSource = @"#version 330 core + uniform sampler2D in_fontTexture; + in vec4 color; in vec2 texCoord; + out vec4 outputColor; + void main() { -outputColor = color * texture(in_fontTexture, texCoord); + outputColor = color * texture(in_fontTexture, texCoord); }"; _shader = CreateProgram("ImGui", VertexSource, FragmentSource); _shaderProjectionMatrixLocation = GL.GetUniformLocation(_shader, "projection_matrix"); _shaderFontTextureLocation = GL.GetUniformLocation(_shader, "in_fontTexture"); - int stride = Unsafe.SizeOf(); + int stride = Marshal.SizeOf(); GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, stride, 0); GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, stride, 8); GL.VertexAttribPointer(2, 4, VertexAttribPointerType.UnsignedByte, true, stride, 16); @@ -225,7 +226,6 @@ outputColor = color * texture(in_fontTexture, texCoord); ImGui.Render(); RenderImDrawData(ImGui.GetDrawData()); } - CheckGLError("End of frame"); } /// @@ -243,6 +243,7 @@ outputColor = color * texture(in_fontTexture, texCoord); _frameBegun = true; ImGui.NewFrame(); + ImGuizmo.BeginFrame(); } /// @@ -252,7 +253,6 @@ outputColor = color * texture(in_fontTexture, texCoord); private void SetPerFrameImGuiData(float deltaSeconds) { ImGuiIOPtr io = ImGui.GetIO(); - // if (io.WantSaveIniSettings) ImGui.SaveIniSettingsToDisk(_iniPath); io.DisplaySize = new Vector2( _windowWidth / _scaleFactor.X, _windowHeight / _scaleFactor.Y); @@ -265,6 +265,7 @@ outputColor = color * texture(in_fontTexture, texCoord); private void UpdateImGuiInput(GameWindow wnd) { ImGuiIOPtr io = ImGui.GetIO(); + var mState = wnd.MouseState; var kState = wnd.KeyboardState; @@ -276,7 +277,7 @@ outputColor = color * texture(in_fontTexture, texCoord); io.AddMouseButtonEvent(4, mState[MouseButton.Button2]); io.AddMouseWheelEvent(mState.ScrollDelta.X, mState.ScrollDelta.Y); - foreach (Keys key in Enum.GetValues(typeof(Keys))) + foreach (Keys key in Enum.GetValues()) { if (key == Keys.Unknown) continue; io.AddKeyEvent(TranslateKey(key), kState.IsKeyDown(key)); @@ -294,7 +295,7 @@ outputColor = color * texture(in_fontTexture, texCoord); io.KeySuper = kState.IsKeyDown(Keys.LeftSuper) || kState.IsKeyDown(Keys.RightSuper); } - public void PressChar(char keyChar) + internal void PressChar(char keyChar) { PressedChars.Add(keyChar); } @@ -340,7 +341,7 @@ outputColor = color * texture(in_fontTexture, texCoord); { ImDrawListPtr cmd_list = draw_data.CmdLists[i]; - int vertexSize = cmd_list.VtxBuffer.Size * Unsafe.SizeOf(); + int vertexSize = cmd_list.VtxBuffer.Size * Marshal.SizeOf(); if (vertexSize > _vertexBufferSize) { int newSize = (int)Math.Max(_vertexBufferSize * 1.5f, vertexSize); @@ -390,7 +391,7 @@ outputColor = color * texture(in_fontTexture, texCoord); { ImDrawListPtr cmd_list = draw_data.CmdLists[n]; - GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, cmd_list.VtxBuffer.Size * Unsafe.SizeOf(), cmd_list.VtxBuffer.Data); + GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, cmd_list.VtxBuffer.Size * Marshal.SizeOf(), cmd_list.VtxBuffer.Data); CheckGLError($"Data Vert {n}"); GL.BufferSubData(BufferTarget.ElementArrayBuffer, IntPtr.Zero, cmd_list.IdxBuffer.Size * sizeof(ushort), cmd_list.IdxBuffer.Data); @@ -544,16 +545,16 @@ outputColor = color * texture(in_fontTexture, texCoord); public static ImGuiKey TranslateKey(Keys key) { - if (key is >= Keys.D0 and <= Keys.D9) + if (key >= Keys.D0 && key <= Keys.D9) return key - Keys.D0 + ImGuiKey._0; - if (key is >= Keys.A and <= Keys.Z) + if (key >= Keys.A && key <= Keys.Z) return key - Keys.A + ImGuiKey.A; - if (key is >= Keys.KeyPad0 and <= Keys.KeyPad9) + if (key >= Keys.KeyPad0 && key <= Keys.KeyPad9) return key - Keys.KeyPad0 + ImGuiKey.Keypad0; - if (key is >= Keys.F1 and <= Keys.F24) + if (key >= Keys.F1 && key <= Keys.F24) return key - Keys.F1 + ImGuiKey.F24; return key switch @@ -596,7 +597,7 @@ outputColor = color * texture(in_fontTexture, texCoord); Keys.KeyPadAdd => ImGuiKey.KeypadAdd, Keys.KeyPadEnter => ImGuiKey.KeypadEnter, Keys.KeyPadEqual => ImGuiKey.KeypadEqual, - Keys.LeftShift => ImGuiKey.LeftShift, + Keys.LeftShift => ImGuiKey.ModShift, Keys.LeftControl => ImGuiKey.LeftCtrl, Keys.LeftAlt => ImGuiKey.LeftAlt, Keys.LeftSuper => ImGuiKey.LeftSuper, diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 2ae406d7..be379030 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -390,6 +390,12 @@ public class CUE4ParseViewModel : ViewModel FLogger.Text("Additive animations have their reference pose stripped, which will lead to inaccurate preview and export", Constants.WHITE, true)); } + if (Provider.Versions.Game is EGame.GAME_UE4_LATEST or EGame.GAME_UE5_LATEST && !Provider.ProjectName.Equals("FortniteGame", StringComparison.OrdinalIgnoreCase)) // ignore fortnite globally + { + FLogger.Append(ELog.Warning, () => + FLogger.Text($"Experimental UE version selected, likely unsuitable for '{Provider.GameDisplayName ?? Provider.ProjectName}'", Constants.WHITE, true)); + } + return Task.CompletedTask; } @@ -578,7 +584,7 @@ public class CUE4ParseViewModel : ViewModel case "manifest": case "uplugin": case "archive": - case "vmodule": + case "vmodule": case "uparam": // Steel Hunters case "verse": case "html": diff --git a/FModel/Views/Snooper/Models/SkeletalModel.cs b/FModel/Views/Snooper/Models/SkeletalModel.cs index 8804bb93..fcc25ac8 100644 --- a/FModel/Views/Snooper/Models/SkeletalModel.cs +++ b/FModel/Views/Snooper/Models/SkeletalModel.cs @@ -174,6 +174,7 @@ public class SkeletalModel : UModel public void Render(Shader shader) { shader.SetUniform("uMorphTime", MorphTime); + shader.SetUniform("uIsSpline", false); Skeleton.Render(shader); } diff --git a/FModel/Views/Snooper/Models/UModel.cs b/FModel/Views/Snooper/Models/UModel.cs index 603a2189..a600d796 100644 --- a/FModel/Views/Snooper/Models/UModel.cs +++ b/FModel/Views/Snooper/Models/UModel.cs @@ -373,6 +373,7 @@ public abstract class UModel : IRenderableModel MatrixVbo = new BufferObject(TransformsCount, BufferTarget.ArrayBuffer); for (int instance = 0; instance < TransformsCount; instance++) { + Transforms[instance].Save(); MatrixVbo.Update(instance, Transforms[instance].Matrix); } Vao.BindInstancing(); // VertexAttributePointer diff --git a/FModel/Views/Snooper/Shading/Material.cs b/FModel/Views/Snooper/Shading/Material.cs index a3e58d49..729aa766 100644 --- a/FModel/Views/Snooper/Shading/Material.cs +++ b/FModel/Views/Snooper/Shading/Material.cs @@ -343,7 +343,7 @@ public class Material : IDisposable var texture = GetSelectedTexture() ?? icons["noimage"]; ImGui.Image(texture.GetPointer(), new Vector2(ImGui.GetContentRegionAvail().X - ImGui.GetScrollX()), - Vector2.Zero, Vector2.One, Vector4.One, new Vector4(1.0f, 1.0f, 1.0f, 0.25f)); + Vector2.Zero, Vector2.One); return ImGui.IsItemHovered() && ImGui.IsMouseDoubleClicked(ImGuiMouseButton.Left); } diff --git a/FModel/Views/Snooper/SnimGui.cs b/FModel/Views/Snooper/SnimGui.cs index e01ef3d7..191f95b6 100644 --- a/FModel/Views/Snooper/SnimGui.cs +++ b/FModel/Views/Snooper/SnimGui.cs @@ -11,6 +11,7 @@ using FModel.Settings; using FModel.Views.Snooper.Animations; using FModel.Views.Snooper.Models; using FModel.Views.Snooper.Shading; +using ImGuizmoNET; using OpenTK.Graphics.OpenGL4; namespace FModel.Views.Snooper; @@ -67,7 +68,9 @@ public class SnimGui private Vector2 _outlinerSize; private bool _tiOpen; + private bool _transformOpen; private bool _viewportFocus; + private OPERATION _guizmoOperation; private readonly Vector4 _accentColor = new (0.125f, 0.42f, 0.831f, 1.0f); private readonly Vector4 _alertColor = new (0.831f, 0.573f, 0.125f, 1.0f); @@ -82,14 +85,14 @@ public class SnimGui _renderer = GL.GetString(StringName.Renderer); _version = "OpenGL " + GL.GetString(StringName.Version); _tableWidth = 17 * Controller.DpiScale; + _guizmoOperation = OPERATION.TRANSLATE; Theme(); } public void Render(Snooper s) { - Controller.SemiBold(); - DrawDockSpace(s.ClientSize); + ImGui.DockSpaceOverViewport(_dockspaceId, ImGui.GetMainViewport(), ImGuiDockNodeFlags.PassthruCentralNode); SectionWindow("Material Inspector", s.Renderer, DrawMaterialInspector, false); AnimationWindow("Timeline", s.Renderer, (icons, tracker, animations) => @@ -249,22 +252,6 @@ public class SnimGui } } - private void DrawDockSpace(OpenTK.Mathematics.Vector2i size) - { - const ImGuiWindowFlags flags = - ImGuiWindowFlags.MenuBar | ImGuiWindowFlags.NoDocking | - ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoResize | - ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoMove | - ImGuiWindowFlags.NoBringToFrontOnFocus | ImGuiWindowFlags.NoNavFocus; - - ImGui.SetNextWindowPos(new Vector2(0, 0)); - ImGui.SetNextWindowSize(new Vector2(size.X, size.Y)); - ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero); - ImGui.Begin("Oui oui", flags); - ImGui.PopStyleVar(); - ImGui.DockSpace(_dockspaceId); - } - private void DrawNavbar() { if (!ImGui.BeginMainMenuBar()) return; @@ -604,14 +591,43 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio ImGui.EndTabItem(); } - if (ImGui.BeginTabItem("Transform")) + _transformOpen = ImGui.BeginTabItem("Transform"); + if (_transformOpen) { ImGui.PushID(0); ImGui.BeginDisabled(model.TransformsCount < 2); ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X); ImGui.SliderInt("", ref model.SelectedInstance, 0, model.TransformsCount - 1, "Instance %i", ImGuiSliderFlags.AlwaysClamp); ImGui.EndDisabled(); ImGui.PopID(); - model.Transforms[model.SelectedInstance].ImGuiTransform(s.Renderer.CameraOp.Speed / 100f); + if (ImGui.BeginTable("guizmo_controls", 2, ImGuiTableFlags.SizingStretchProp)) + { + var t = model.Transforms[model.SelectedInstance]; + var c = _guizmoOperation switch + { + OPERATION.TRANSLATE => 0, + OPERATION.ROTATE => 1, + OPERATION.SCALE => 2, + _ => 3 + }; + + Layout("Operation "); + ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X * 0.6f); + ImGui.PushID(1);ImGui.Combo("", ref c, "Translate\0Rotate\0Scale\0"); + ImGui.PopID();ImGui.SameLine();if (ImGui.Button("Reset All")) t.Reset(); + Layout("Position");ImGui.Text(t.Position.ToString()); + Layout("Rotation");ImGui.Text(t.Rotation.ToString()); + Layout("Scale");ImGui.Text(t.Scale.ToString()); + + _guizmoOperation = c switch + { + 0 => OPERATION.TRANSLATE, + 1 => OPERATION.ROTATE, + 2 => OPERATION.SCALE, + _ => OPERATION.UNIVERSAL + }; + + ImGui.EndTable(); + } ImGui.EndTabItem(); } @@ -719,8 +735,8 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio { (model.Materials[section.MaterialIndex].GetSelectedTexture() ?? s.Renderer.Options.Icons["noimage"]).ImGuiTextureInspector(); } - ImGui.End(); // if window is collapsed } + ImGui.End(); } private void DrawSkeletonTree(Snooper s) @@ -741,8 +757,8 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio ImGui.EndTable(); } } - ImGui.End(); // if window is collapsed } + ImGui.End(); ImGui.PopStyleVar(); } @@ -756,41 +772,54 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio largest.Y -= ImGui.GetScrollY(); var size = new Vector2(largest.X, largest.Y); + var pos = ImGui.GetWindowPos(); + var fHeight = ImGui.GetFrameHeight(); + s.Renderer.CameraOp.AspectRatio = size.X / size.Y; - ImGui.Image(s.Framebuffer.GetPointer(), size, new Vector2(0, 1), new Vector2(1, 0), Vector4.One); + ImGui.Image(s.Framebuffer.GetPointer(), size, new Vector2(0, 1), new Vector2(1, 0)); - if (ImGui.IsItemHovered()) + if (_transformOpen) { - // if left button down while mouse is hover viewport - if (ImGui.IsMouseDown(ImGuiMouseButton.Left) && !_viewportFocus) - { - _viewportFocus = true; - s.CursorState = CursorState.Grabbed; - } - if (ImGui.IsMouseClicked(ImGuiMouseButton.Right)) - { - var guid = s.Renderer.Picking.ReadPixel(ImGui.GetMousePos(), ImGui.GetCursorScreenPos(), size); - s.Renderer.Options.SelectModel(guid); - ImGui.SetWindowFocus("Outliner"); - ImGui.SetWindowFocus("Details"); - } + ImGuizmo.SetDrawlist(ImGui.GetWindowDrawList()); + ImGuizmo.SetRect(pos.X, pos.Y + fHeight, size.X, size.Y); + DrawGuizmo(s); } - if (ImGui.IsMouseDragging(ImGuiMouseButton.Left) && _viewportFocus) + if (!ImGuizmo.IsUsing()) { - s.Renderer.CameraOp.Modify(ImGui.GetIO().MouseDelta); - } + if (ImGui.IsItemHovered()) + { + // if left button down while mouse is hover viewport + if (ImGui.IsMouseDown(ImGuiMouseButton.Left) && !_viewportFocus) + { + _viewportFocus = true; + s.CursorState = CursorState.Grabbed; + } + if (ImGui.IsMouseClicked(ImGuiMouseButton.Right)) + { + var guid = s.Renderer.Picking.ReadPixel(ImGui.GetMousePos(), ImGui.GetCursorScreenPos(), size); + s.Renderer.Options.SelectModel(guid); + ImGui.SetWindowFocus("Outliner"); + ImGui.SetWindowFocus("Details"); + } + } - // if left button up and mouse was in viewport - if (ImGui.IsMouseReleased(ImGuiMouseButton.Left) && _viewportFocus) - { - _viewportFocus = false; - s.CursorState = CursorState.Normal; + if (_viewportFocus && ImGui.IsMouseDragging(ImGuiMouseButton.Left)) + { + s.Renderer.CameraOp.Modify(ImGui.GetIO().MouseDelta); + } + + // if left button up and mouse was in viewport + if (_viewportFocus && ImGui.IsMouseReleased(ImGuiMouseButton.Left)) + { + _viewportFocus = false; + s.CursorState = CursorState.Normal; + } } const float margin = 7.5f; var buttonWidth = 14.0f * ImGui.GetWindowDpiScale(); - var basePos = new Vector2( size.X - buttonWidth - margin * 2, ImGui.GetFrameHeight() + margin); + var basePos = new Vector2( size.X - buttonWidth - margin * 2, fHeight + margin); ImGui.SetCursorPos(basePos); ImGui.PushStyleColor(ImGuiCol.Button, Vector4.Zero); ImGui.PushStyleColor(ImGuiCol.ButtonHovered, new Vector4(0.2f)); @@ -821,6 +850,26 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio ImGui.PopStyleVar(); } + private void DrawGuizmo(Snooper s) + { + var enableGuizmo = s.Renderer.Options.TryGetModel(out var selected) && selected.IsVisible; + if (enableGuizmo) + { + var view = s.Renderer.CameraOp.GetViewMatrix(); + var proj = s.Renderer.CameraOp.GetProjectionMatrix(); + var transform = selected.Transforms[selected.SelectedInstance]; + var matrix = transform.Matrix; + + if (ImGuizmo.Manipulate(ref view.M11, ref proj.M11, _guizmoOperation, MODE.LOCAL, ref matrix.M11) && + Matrix4x4.Invert(transform.Relation, out var invRelation)) // matrix * invRelation = local matrix + { + // ^ long story short: there was issues with other transformation methods + // that's one way of modifying root elements without breaking the world matrix + transform.ModifyLocal(matrix * invRelation); + } + } + } + public static void Popup(Action content) { ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(4f)); @@ -850,12 +899,13 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio { if (ImGui.Begin(name, ImGuiWindowFlags.NoScrollbar)) { - Controller.PopFont(); + Controller.Normal(); if (styled) PushStyleCompact(); content(); if (styled) PopStyleCompact(); - ImGui.End(); + ImGui.PopFont(); } + ImGui.End(); } private void MeshWindow(string name, Renderer renderer, Action, UModel> content, bool styled = true) @@ -908,7 +958,7 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio ImGui.GetCursorPosY() + (region.Y - size.Y) / 2)); Controller.Bold(); ImGui.TextColored(color, text); - Controller.PopFont(); + ImGui.PopFont(); } public static void Layout(string name, bool tooltip = false) @@ -1027,7 +1077,7 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio style.Colors[(int) ImGuiCol.TableRowBgAlt] = new Vector4(1.00f, 1.00f, 1.00f, 0.06f); style.Colors[(int) ImGuiCol.TextSelectedBg] = new Vector4(0.26f, 0.59f, 0.98f, 0.35f); style.Colors[(int) ImGuiCol.DragDropTarget] = new Vector4(1.00f, 1.00f, 0.00f, 0.90f); - style.Colors[(int) ImGuiCol.NavHighlight] = new Vector4(0.26f, 0.59f, 0.98f, 1.00f); + style.Colors[(int) ImGuiCol.NavCursor] = new Vector4(0.26f, 0.59f, 0.98f, 1.00f); style.Colors[(int) ImGuiCol.NavWindowingHighlight] = new Vector4(1.00f, 1.00f, 1.00f, 0.70f); style.Colors[(int) ImGuiCol.NavWindowingDimBg] = new Vector4(0.80f, 0.80f, 0.80f, 0.20f); style.Colors[(int) ImGuiCol.ModalWindowDimBg] = new Vector4(0.80f, 0.80f, 0.80f, 0.35f); diff --git a/FModel/Views/Snooper/Transform.cs b/FModel/Views/Snooper/Transform.cs index a36ba7a1..ec9d270a 100644 --- a/FModel/Views/Snooper/Transform.cs +++ b/FModel/Views/Snooper/Transform.cs @@ -1,6 +1,5 @@ using System.Numerics; using CUE4Parse.UE4.Objects.Core.Math; -using ImGuiNET; namespace FModel.Views.Snooper; @@ -16,63 +15,37 @@ public class Transform public FQuat Rotation = FQuat.Identity; public FVector Scale = FVector.OneVector; - public Matrix4x4 LocalMatrix => - Matrix4x4.CreateScale(Scale.X, Scale.Z, Scale.Y) * - Matrix4x4.CreateFromQuaternion(Quaternion.Normalize(new Quaternion(Rotation.X, Rotation.Z, Rotation.Y, -Rotation.W))) * - Matrix4x4.CreateTranslation(Position.X, Position.Z, Position.Y); + private Matrix4x4? _saved; + public Matrix4x4 LocalMatrix => Matrix4x4.CreateScale(Scale.X, Scale.Z, Scale.Y) * + Matrix4x4.CreateFromQuaternion(Quaternion.Normalize(new Quaternion(Rotation.X, Rotation.Z, Rotation.Y, -Rotation.W))) * + Matrix4x4.CreateTranslation(Position.X, Position.Z, Position.Y); public Matrix4x4 Matrix => LocalMatrix * Relation; - public void ImGuiTransform(float speed) + public void Save() { - const float width = 100f; + _saved = LocalMatrix; + } - ImGui.SetNextItemOpen(true, ImGuiCond.Appearing); - if (ImGui.TreeNode("Location")) - { - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("X", ref Position.X, speed, 0f, 0f, "%.2f m"); + public void ModifyLocal(Matrix4x4 matrix) + { + Matrix4x4.Decompose(matrix, out var scale, out var rotation, out var position); - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("Y", ref Position.Z, speed, 0f, 0f, "%.2f m"); + Scale.X = scale.X; + Scale.Y = scale.Z; + Scale.Z = scale.Y; + Rotation.X = rotation.X; + Rotation.Y = rotation.Z; + Rotation.Z = rotation.Y; + Rotation.W = -rotation.W; + Position.X = position.X; + Position.Z = position.Y; + Position.Y = position.Z; + } - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("Z", ref Position.Y, speed, 0f, 0f, "%.2f m"); - - ImGui.TreePop(); - } - - ImGui.SetNextItemOpen(true, ImGuiCond.Appearing); - if (ImGui.TreeNode("Rotation")) - { - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("W", ref Rotation.W, .005f, 0f, 0f, "%.3f rad"); - - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("X", ref Rotation.X, .005f, 0f, 0f, "%.3f rad"); - - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("Y", ref Rotation.Z, .005f, 0f, 0f, "%.3f rad"); - - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("Z", ref Rotation.Y, .005f, 0f, 0f, "%.3f rad"); - - ImGui.TreePop(); - } - - ImGui.SetNextItemOpen(true, ImGuiCond.Appearing); - if (ImGui.TreeNode("Scale")) - { - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("X", ref Scale.X, speed, 0f, 0f, "%.3f"); - - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("Y", ref Scale.Z, speed, 0f, 0f, "%.3f"); - - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("Z", ref Scale.Y, speed, 0f, 0f, "%.3f"); - - ImGui.TreePop(); - } + public void Reset() + { + if (!_saved.HasValue) return; + ModifyLocal(_saved.Value); } public override string ToString() => Matrix.Translation.ToString();