From 4e321d74c9154c4b34ed9b47bc415394c32e42d9 Mon Sep 17 00:00:00 2001 From: 4sval Date: Sun, 30 Oct 2022 04:05:33 +0100 Subject: [PATCH] docking gets saved now wtf --- CUE4Parse | 2 +- FModel/Framework/ImGuiController.cs | 5 +- FModel/Views/Snooper/FramebufferObject.cs | 4 - FModel/Views/Snooper/Material.cs | 131 ++++++++++----------- FModel/Views/Snooper/Model.cs | 5 +- FModel/Views/Snooper/Renderer.cs | 11 +- FModel/Views/Snooper/Section.cs | 6 + FModel/Views/Snooper/SnimGui.cs | 137 ++++++++++++++++++++-- FModel/Views/Snooper/Snooper.cs | 30 ++--- 9 files changed, 224 insertions(+), 107 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 7fb8679a..1cf7b4bc 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 7fb8679a4ec5e0057cf1d6138cbfd2c1f658a2a3 +Subproject commit 1cf7b4bc8e2f91e60fc5c9e60c6cb9a1ff1af315 diff --git a/FModel/Framework/ImGuiController.cs b/FModel/Framework/ImGuiController.cs index d0388d1d..3eab99c9 100644 --- a/FModel/Framework/ImGuiController.cs +++ b/FModel/Framework/ImGuiController.cs @@ -49,10 +49,13 @@ public ImGuiController(int width, int height) IntPtr context = ImGui.CreateContext(); ImGui.SetCurrentContext(context); var io = ImGui.GetIO(); - io.Fonts.AddFontDefault(); + // io.Fonts.AddFontDefault(); io.Fonts.AddFontFromFileTTF("C:\\Windows\\Fonts\\segoeui.ttf", 16); io.BackendFlags |= ImGuiBackendFlags.RendererHasVtxOffset; + io.ConfigFlags |= ImGuiConfigFlags.NavEnableKeyboard; + io.ConfigFlags |= ImGuiConfigFlags.DockingEnable; + io.ConfigFlags |= ImGuiConfigFlags.ViewportsEnable; CreateDeviceResources(); SetKeyMappings(); diff --git a/FModel/Views/Snooper/FramebufferObject.cs b/FModel/Views/Snooper/FramebufferObject.cs index 6b1608b8..0fba96d4 100644 --- a/FModel/Views/Snooper/FramebufferObject.cs +++ b/FModel/Views/Snooper/FramebufferObject.cs @@ -89,10 +89,6 @@ public void BindMsaa() GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, _framebufferHandle); GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, _postProcessingHandle); GL.BlitFramebuffer(0, 0, _width, _height, 0, 0, _width, _height, ClearBufferMask.ColorBufferBit, BlitFramebufferFilter.Nearest); - } - - public void BindStuff() - { GL.Disable(EnableCap.DepthTest); _shader.Use(); diff --git a/FModel/Views/Snooper/Material.cs b/FModel/Views/Snooper/Material.cs index 5e846f53..ab2b309e 100644 --- a/FModel/Views/Snooper/Material.cs +++ b/FModel/Views/Snooper/Material.cs @@ -12,8 +12,6 @@ public class Material : IDisposable { private int _handle; - private Vector3 _ambientLight; - public readonly CMaterialParams2 Parameters; public readonly int UvNumber; public bool IsUsed; @@ -28,18 +26,29 @@ public class Material : IDisposable public bool HasSpecularMap; public bool HasDiffuseColor; - public Material() + private Vector3 _ambientLight; + + public Material(int numUvs) { Parameters = new CMaterialParams2(); - UvNumber = 1; + UvNumber = numUvs; + IsUsed = false; + + Diffuse = Array.Empty(); + Normals = Array.Empty(); + SpecularMasks = Array.Empty(); + Emissive = Array.Empty(); + DiffuseColor = Vector4.Zero; EmissionColor = Array.Empty(); - IsUsed = false; + HasSpecularMap = false; + HasDiffuseColor = false; + + _ambientLight = Vector3.One; } - public Material(int numUvs, UMaterialInterface unrealMaterial) : this() + public Material(int numUvs, UMaterialInterface unrealMaterial) : this(numUvs) { - UvNumber = numUvs; SwapMaterial(unrealMaterial); } @@ -52,72 +61,62 @@ public void Setup(Cache cache) { _handle = GL.CreateProgram(); - int index; - var platform = UserSettings.Default.OverridedPlatform; - void Add(Texture[] array, UTexture2D original) - { - var guid = original.LightingGuid; - if (cache.TryGetTexture(guid, out var texture)) - { - array[index] = texture; - } - else if (original.GetFirstMip() is { } mip) - { - TextureDecoder.DecodeTexture(mip, original.Format, original.isNormalMap, platform, out var data, out _); - - var t = new Texture(data, mip.SizeX, mip.SizeY, original); - cache.AddTexture(guid, t); - array[index] = t; - } - } - - index = 0; - Diffuse = new Texture[UvNumber]; - foreach (var d in Parameters.GetDiffuseTextures()) - { - if (index < UvNumber && d is UTexture2D original) - Add(Diffuse, original); - index++; - } - - index = 0; - Normals = new Texture[UvNumber]; - foreach (var n in Parameters.GetNormalsTextures()) + if (Parameters.IsNull) { - if (index < UvNumber && n is UTexture2D original) - Add(Normals, original); - index++; + DiffuseColor = new Vector4(1, 0, 0, 1); } - - index = 0; - SpecularMasks = new Texture[UvNumber]; - foreach (var s in Parameters.GetSpecularMasksTextures()) + else { - if (index < UvNumber && s is UTexture2D original) - Add(SpecularMasks, original); - index++; - } - - index = 0; - Emissive = new Texture[UvNumber]; - EmissionColor = new Vector4[UvNumber]; - foreach (var e in Parameters.GetEmissiveTextures()) - { - if (index < UvNumber && e is UTexture2D original) + var platform = UserSettings.Default.OverridedPlatform; + bool TryGetCached(UTexture2D o, out Texture t) { - if (Parameters.TryGetLinearColor(out var color, $"Emissive{(index > 0 ? index + 1 : "")}") && color is { A: > 0}) - EmissionColor[index] = new Vector4(color.R, color.G, color.B, color.A); - else EmissionColor[index] = Vector4.One; - - Add(Emissive, original); + var guid = o.LightingGuid; + if (!cache.TryGetTexture(guid, out t)) + { + if (o.GetFirstMip() is { } mip) + { + TextureDecoder.DecodeTexture(mip, o.Format, o.isNormalMap, platform, out var data, out _); + + t = new Texture(data, mip.SizeX, mip.SizeY, o); + cache.AddTexture(guid, t); + } + else t = null; + } + return t != null; } - else if (index < UvNumber) EmissionColor[index] = Vector4.Zero; - index++; + + Diffuse = new Texture[UvNumber]; + for (int i = 0; i < Diffuse.Length; i++) + if (Parameters.TryGetTexture2d(out var o, CMaterialParams2.Diffuse[i]) && TryGetCached(o, out var t)) + Diffuse[i] = t; + + Normals = new Texture[UvNumber]; + for (int i = 0; i < Normals.Length; i++) + if (Parameters.TryGetTexture2d(out var o, CMaterialParams2.Normals[i]) && TryGetCached(o, out var t)) + Normals[i] = t; + + SpecularMasks = new Texture[UvNumber]; + for (int i = 0; i < SpecularMasks.Length; i++) + if (Parameters.TryGetTexture2d(out var o, CMaterialParams2.SpecularMasks[i]) && TryGetCached(o, out var t)) + SpecularMasks[i] = t; + + Emissive = new Texture[UvNumber]; + EmissionColor = new Vector4[UvNumber]; + for (int i = 0; i < Emissive.Length; i++) + if (Parameters.TryGetTexture2d(out var o, CMaterialParams2.Emissive[i]) && TryGetCached(o, out var t)) + { + Emissive[i] = t; + + if (Parameters.TryGetLinearColor(out var color, $"Emissive{(i > 0 ? i + 1 : "")}") && color is { A: > 0}) + EmissionColor[i] = new Vector4(color.R, color.G, color.B, color.A); + else EmissionColor[i] = Vector4.One; + } + + // diffuse light is based on normal map, so increase ambient if no normal map + _ambientLight = new Vector3(Normals[0] == null ? 1.0f : 0.2f); + HasSpecularMap = SpecularMasks[0] != null; } - // diffuse light is based on normal map, so increase ambient if no normal map - _ambientLight = new Vector3(Normals[0] == null ? 1.0f : 0.2f); - HasSpecularMap = SpecularMasks[0] != null; HasDiffuseColor = DiffuseColor != Vector4.Zero; } diff --git a/FModel/Views/Snooper/Model.cs b/FModel/Views/Snooper/Model.cs index c472d5b1..e956d774 100644 --- a/FModel/Views/Snooper/Model.cs +++ b/FModel/Views/Snooper/Model.cs @@ -80,7 +80,7 @@ private Model(string name, string type, ResolvedObject[] materials, CBaseMeshLod { if ((materials[m]?.TryLoad(out var material) ?? false) && material is UMaterialInterface unrealMaterial) Materials[m] = new Material(lod.NumTexCoords, unrealMaterial); // lod.NumTexCoords - else Materials[m] = new Material(); + else Materials[m] = new Material(1); } if (lod.VertexColors is { Length: > 0}) @@ -104,8 +104,7 @@ private Model(string name, string type, ResolvedObject[] materials, CBaseMeshLod for (var s = 0; s < sections.Length; s++) { var section = sections[s]; - Materials[section.MaterialIndex].IsUsed = true; - Sections[s] = new Section(section.MaterialIndex, section.NumFaces * _faceSize, section.FirstIndex); + Sections[s] = new Section(section.MaterialIndex, section.NumFaces * _faceSize, section.FirstIndex, Materials[section.MaterialIndex]); for (uint face = 0; face < section.NumFaces; face++) { foreach (var f in _facesIndex) diff --git a/FModel/Views/Snooper/Renderer.cs b/FModel/Views/Snooper/Renderer.cs index c827ed45..4a9d7aa8 100644 --- a/FModel/Views/Snooper/Renderer.cs +++ b/FModel/Views/Snooper/Renderer.cs @@ -75,11 +75,6 @@ public void Render(Camera cam) _shader.SetUniform("uProjection", projMatrix); _shader.SetUniform("viewPos", cam.Position); - // _shader.SetUniform("material.diffuseMap", 0); - // _shader.SetUniform("material.normalMap", 1); - // _shader.SetUniform("material.specularMap", 2); - // _shader.SetUniform("material.emissionMap", 3); - _shader.SetUniform("light.position", cam.Position); _shader.SetUniform("light.diffuse", _diffuseLight); _shader.SetUniform("light.specular", _specularLight); @@ -191,13 +186,13 @@ private Camera LoadWorld(CancellationToken cancellationToken, UWorld original) if (textureDataIdx.TryGetValue(out FPackageIndex diffuse, "Diffuse") && diffuse.Load() is UTexture2D diffuseTexture) - model.Materials[model.Sections[j].MaterialIndex].Parameters.Textures[CMaterialParams2.Diffuse[0]] = diffuseTexture; + model.Materials[model.Sections[j].MaterialIndex].Parameters.Textures[CMaterialParams2.Diffuse[0][0]] = diffuseTexture; if (textureDataIdx.TryGetValue(out FPackageIndex normal, "Normal") && normal.Load() is UTexture2D normalTexture) - model.Materials[model.Sections[j].MaterialIndex].Parameters.Textures[CMaterialParams2.Normals[0]] = normalTexture; + model.Materials[model.Sections[j].MaterialIndex].Parameters.Textures[CMaterialParams2.Normals[0][0]] = normalTexture; if (textureDataIdx.TryGetValue(out FPackageIndex specular, "Specular") && specular.Load() is UTexture2D specularTexture) - model.Materials[model.Sections[j].MaterialIndex].Parameters.Textures[CMaterialParams2.SpecularMasks[0]] = specularTexture; + model.Materials[model.Sections[j].MaterialIndex].Parameters.Textures[CMaterialParams2.SpecularMasks[0][0]] = specularTexture; } } if (staticMeshComp.TryGetValue(out FPackageIndex[] overrideMaterials, "OverrideMaterials")) diff --git a/FModel/Views/Snooper/Section.cs b/FModel/Views/Snooper/Section.cs index b53dfc3b..7c3555ca 100644 --- a/FModel/Views/Snooper/Section.cs +++ b/FModel/Views/Snooper/Section.cs @@ -22,6 +22,12 @@ public Section(int index, int facesCount, int firstFaceIndex) Show = true; } + public Section(int index, int facesCount, int firstFaceIndex, Material material) : this(index, facesCount, firstFaceIndex) + { + material.IsUsed = true; + Show = !material.Parameters.IsNull && !material.Parameters.IsTransparent; + } + public void Setup() { _handle = GL.CreateProgram(); diff --git a/FModel/Views/Snooper/SnimGui.cs b/FModel/Views/Snooper/SnimGui.cs index ac5e1cfd..f317572b 100644 --- a/FModel/Views/Snooper/SnimGui.cs +++ b/FModel/Views/Snooper/SnimGui.cs @@ -1,10 +1,13 @@ using System; using System.Collections.Generic; -using System.Numerics; +using System.Windows; using CUE4Parse.UE4.Objects.Core.Misc; using FModel.Framework; using ImGuiNET; +using OpenTK.Mathematics; using OpenTK.Windowing.Desktop; +using Vector2 = System.Numerics.Vector2; +using Vector4 = System.Numerics.Vector4; namespace FModel.Views.Snooper; @@ -34,27 +37,141 @@ public SnimGui(int width, int height) var viewport = ImGui.GetMainViewport(); var titleBarHeight = ImGui.GetFontSize() + style.FramePadding.Y * 2; - _outlinerSize = new Vector2(400, 300); - _outlinerPosition = new Vector2(viewport.WorkSize.X - _outlinerSize.X, titleBarHeight); - _propertiesSize = _outlinerSize with { Y = viewport.WorkSize.Y - _outlinerSize.Y - titleBarHeight }; - _propertiesPosition = new Vector2(viewport.WorkSize.X - _propertiesSize.X, _outlinerPosition.Y + _outlinerSize.Y); - _viewportSize = _outlinerPosition with { Y = viewport.WorkSize.Y - titleBarHeight - 150 }; + // _outlinerSize = new Vector2(400, 300); + // _outlinerPosition = new Vector2(viewport.WorkSize.X - _outlinerSize.X, titleBarHeight); + // _propertiesSize = _outlinerSize with { Y = viewport.WorkSize.Y - _outlinerSize.Y - titleBarHeight }; + // _propertiesPosition = new Vector2(viewport.WorkSize.X - _propertiesSize.X, _outlinerPosition.Y + _outlinerSize.Y); + _viewportSize = new Vector2(width, height); _viewportPosition = new Vector2(0, titleBarHeight); - _textureSize = _viewportSize with { Y = viewport.WorkSize.Y - _viewportSize.Y - titleBarHeight }; - _texturePosition = new Vector2(0, _viewportPosition.Y + _viewportSize.Y); + // _textureSize = _viewportSize with { Y = viewport.WorkSize.Y - _viewportSize.Y - titleBarHeight }; + // _texturePosition = new Vector2(0, _viewportPosition.Y + _viewportSize.Y); Theme(style); } - public void Render() + public void Render(Vector2i size, FramebufferObject framebuffer, Camera camera) { - ImGui.ShowDemoWindow(); + DrawDockSpace(size); + + DrawNavbar(); + ImGui.Begin("Outliner"); + ImGui.End(); + ImGui.Begin("Properties"); + ImGui.End(); + ImGui.Begin("UV Editor"); + ImGui.End(); + ImGui.Begin("Timeline"); + ImGui.End(); + Draw3DViewport(framebuffer, camera); _controller.Render(); ImGuiController.CheckGLError("End of frame"); } + private void DrawDockSpace(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; + + if (ImGui.BeginMenu("Window")) + { + ImGui.MenuItem("Append", "R"); + ImGui.MenuItem("Close", "ESC"); + ImGui.EndMenu(); + } + if (ImGui.BeginMenu("Edit")) + { + if (ImGui.MenuItem("Undo", "CTRL+Z")) {} + if (ImGui.MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item + ImGui.Separator(); + if (ImGui.MenuItem("Cut", "CTRL+X")) {} + if (ImGui.MenuItem("Copy", "CTRL+C")) {} + if (ImGui.MenuItem("Paste", "CTRL+V")) {} + ImGui.EndMenu(); + } + + const string text = "Press ESC to Exit..."; + ImGui.SetCursorPosX(ImGui.GetWindowViewport().WorkSize.X - ImGui.CalcTextSize(text).X - 5); + ImGui.TextColored(new Vector4(0.36f, 0.42f, 0.47f, 1.00f), text); // ImGuiCol.TextDisabled + + ImGui.EndMainMenuBar(); + } + + private void Draw3DViewport(FramebufferObject framebuffer, Camera camera) + { + const float lookSensitivity = 0.1f; + const ImGuiWindowFlags flags = + ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse | + ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.AlwaysUseWindowPadding; + + // ImGui.SetNextWindowSize(_viewportSize, _firstUse); + // ImGui.SetNextWindowPos(_viewportPosition, _firstUse); + ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero); + ImGui.Begin("3D Viewport"); + ImGui.PopStyleVar(); + + var largest = ImGui.GetContentRegionAvail(); + largest.X -= ImGui.GetScrollX(); + largest.Y -= ImGui.GetScrollY(); + + var size = new Vector2(largest.X, largest.Y); + camera.AspectRatio = size.X / size.Y; + ImGui.ImageButton(framebuffer.GetPointer(), size, new Vector2(0, 1), new Vector2(1, 0), 0); + + // it took me 5 hours to make it work, don't change any of the following code + // basically the Raw cursor doesn't actually freeze the mouse position + // so for ImGui, the IsItemHovered will be false if mouse leave, even in Raw mode + // var io = ImGui.GetIO(); + // if (ImGui.IsItemHovered()) + // { + // // if right button down while mouse is hover viewport + // if (ImGui.IsMouseDown(ImGuiMouseButton.Right) && !_viewportFocus) + // _viewportFocus = true; + // } + + // this can't be inside IsItemHovered! read it as + // if right mouse button was pressed while hovering the viewport + // move camera until right mouse button is released + // no matter where mouse position end up + // if (ImGui.IsMouseDragging(ImGuiMouseButton.Right, lookSensitivity) && _viewportFocus) + // { + // var delta = io.MouseDelta * lookSensitivity; + // camera.ModifyDirection(delta.X, delta.Y); + // mouse.Cursor.CursorMode = CursorMode.Raw; + // } + + // if left button up and mouse was in viewport + // if (ImGui.IsMouseReleased(ImGuiMouseButton.Right) && _viewportFocus) + // { + // _viewportFocus = false; + // mouse.Cursor.CursorMode = CursorMode.Normal; + // } + + // const float padding = 5f; + // float framerate = ImGui.GetIO().Framerate; + // var text = $"FPS: {framerate:0} ({1000.0f / framerate:0.##} ms)"; + // ImGui.SetCursorPos(new Vector2(pos.X + padding, pos.Y + size.Y - ImGui.CalcTextSize(text).Y - padding)); + // ImGui.Text(text); + + ImGui.End(); + } + private void PushStyleCompact() { var style = ImGui.GetStyle(); diff --git a/FModel/Views/Snooper/Snooper.cs b/FModel/Views/Snooper/Snooper.cs index d7d0b149..fc4a92ba 100644 --- a/FModel/Views/Snooper/Snooper.cs +++ b/FModel/Views/Snooper/Snooper.cs @@ -12,7 +12,7 @@ namespace FModel.Views.Snooper; public class Snooper : GameWindow { - // private readonly FramebufferObject _framebuffer; + private FramebufferObject _framebuffer; private readonly Skybox _skybox; private readonly Grid _grid; private readonly Renderer _renderer; @@ -25,7 +25,7 @@ public class Snooper : GameWindow public Snooper(GameWindowSettings gwSettings, NativeWindowSettings nwSettings) : base(gwSettings, nwSettings) { - // _framebuffer = new FramebufferObject(Size); + _framebuffer = new FramebufferObject(Size); _skybox = new Skybox(); _grid = new Grid(); _renderer = new Renderer(); @@ -54,7 +54,7 @@ private unsafe void WindowShouldClose(bool value, bool clear) } GLFW.SetWindowShouldClose(WindowPtr, value); // start / stop game loop - CursorState = value ? CursorState.Normal : CursorState.Grabbed; + // CursorState = value ? CursorState.Normal : CursorState.Grabbed; IsVisible = !value; } @@ -85,7 +85,7 @@ protected override void OnLoad() GL.StencilOp(StencilOp.Keep, StencilOp.Replace, StencilOp.Replace); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); - // _framebuffer.Setup(); + _framebuffer.Setup(); _skybox.Setup(); _grid.Setup(); _renderer.Setup(); @@ -99,19 +99,19 @@ protected override void OnRenderFrame(FrameEventArgs args) return; _gui.Update(this, (float)args.Time); - ClearWhatHasBeenDrawn(); // in main window + ClearWhatHasBeenDrawn(); - // _framebuffer.Bind(); // switch to dedicated window - // ClearWhatHasBeenDrawn(); // in dedicated window + _framebuffer.Bind(); + ClearWhatHasBeenDrawn(); _skybox.Render(_camera); _grid.Render(_camera); _renderer.Render(_camera); - _gui.Render(); - // _framebuffer.BindMsaa(); - // _framebuffer.Bind(0); // switch back to main window - // _framebuffer.BindStuff(); + _framebuffer.BindMsaa(); + _framebuffer.Bind(0); + + _gui.Render(Size, _framebuffer, _camera); SwapBuffers(); } @@ -128,9 +128,9 @@ protected override void OnMouseMove(MouseMoveEventArgs e) if (!IsVisible) return; - const float lookSensitivity = 0.1f; - var delta = e.Delta * lookSensitivity; - _camera.ModifyDirection(delta.X, delta.Y); + // const float lookSensitivity = 0.1f; + // var delta = e.Delta * lookSensitivity; + // _camera.ModifyDirection(delta.X, delta.Y); } protected override void OnUpdateFrame(FrameEventArgs e) @@ -170,6 +170,8 @@ protected override void OnResize(ResizeEventArgs e) GL.Viewport(0, 0, Size.X, Size.Y); + _framebuffer = new FramebufferObject(Size); + _framebuffer.Setup(); _camera.AspectRatio = Size.X / (float)Size.Y; _gui.WindowResized(ClientSize.X, ClientSize.Y); }