From 202083930a53130aaed4a8c657fb594c548fe97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Thu, 6 Oct 2022 16:33:33 +0200 Subject: [PATCH] Play Button --- .../content/Textures/EditorIcons.dds | Bin 65664 -> 98432 bytes .../content/Textures/EditorIcons.psd | Bin 16300 -> 20136 bytes GlitchyEditor/src/EditWindows/EditorWindow.bf | 1 + .../src/EditWindows/SceneViewportWindow.bf | 135 ++++++++------- GlitchyEditor/src/EditorIcons.bf | 4 + GlitchyEditor/src/EditorLayer.bf | 77 ++++++++- .../src/Platform/DX11/Renderer/Dx11Buffer.bf | 4 +- GlitchyEngine/src/Renderer/Renderer.bf | 2 +- GlitchyEngine/src/World/Scene.bf | 159 +++++++++++++++++- 9 files changed, 317 insertions(+), 65 deletions(-) diff --git a/GlitchyEditor/content/Textures/EditorIcons.dds b/GlitchyEditor/content/Textures/EditorIcons.dds index c2de4251e24b772361feec0f4b60c09a2b614a35..70df89adc29f1a21a228f192363745ac823d73be 100644 GIT binary patch literal 98432 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 CT5N;> delta 1919 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 literal 16300 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 tfi!&%)Q-EAzYidCv> ViewportSizeChangedEvent ~ _.Dispose(); - public Event> EntityClickedEvent ~ _.Dispose(); + private ImGuizmo.OPERATION _gizmoType = .TRANSLATE; + private ImGuizmo.MODE _gizmoMode = .LOCAL; + private float _snap = 0.5f; + private float _angleSnap = 45.0f; + private bool _doSnap = false; + public uint32 SelectedEntityId {get; private set; } + public bool SelectionChanged { get; private set; } + + public Vector2 ViewportSize => (Vector2)_oldViewportSize; + // Occurs when the viewport is resized. + public Event> ViewportSizeChanged ~ _.Dispose(); + // Occurs when an entity was clicked. + public Event> EntityClicked ~ _.Dispose(); + + /// The render target that is shown in the viewport window. public RenderTargetGroup RenderTarget { get => _renderTarget; @@ -30,21 +49,14 @@ namespace GlitchyEditor.EditWindows } } + /// Gets or sets whether the editor functionality (gizmo, picking etc.) is enabled. + public bool EditorMode { get; set; } = true + public this(Editor editor) { _editor = editor; } - private ImGui.Vec2 oldViewportSize = .(100, 100); - private bool viewPortChanged; - - public uint32 SelectedEntityId; - public bool SelectionChanged; - - public Vector2 ViewportSize => (Vector2)oldViewportSize; - - private bool _wrappedCursor; - protected override void InternalShow() { ImGui.PushStyleVar(.WindowPadding, ImGui.Vec2(1, 1)); @@ -56,8 +68,6 @@ namespace GlitchyEditor.EditWindows return; } - ShowMenuBar(); - let viewportSize = ImGui.GetContentRegionAvail(); if(ImGui.IsWindowHovered() && Input.IsMouseButtonPressing(.RightButton)) @@ -67,62 +77,74 @@ namespace GlitchyEditor.EditWindows } _hasFocus = ImGui.IsWindowFocused(); - - if (_editor.CurrentCamera.[Friend]BindMouse && _hasFocus) - WrapMouseInViewport(); - - // If we wrapped this frame we weren't hovering because the cursor has to be out of bounds to wrap - _editor.CurrentCamera.AllowMove = _hasFocus && (ImGui.IsWindowHovered() || _wrappedCursor); - - if (_hasFocus && !_editor.CurrentCamera.InUse) + + if (EditorMode) { - if (Input.IsKeyPressing(.Q)) - _gizmoType = .TRANSLATE; - if (Input.IsKeyPressing(.W)) - _gizmoType = .ROTATE; - if (Input.IsKeyPressing(.E)) - _gizmoType = .SCALE; + ShowMenuBar(); + + if (_editor.CurrentCamera.[Friend]BindMouse && _hasFocus) + WrapMouseInViewport(); - if (Input.IsKeyPressing(.G)) - _gizmoMode = .WORLD; - if (Input.IsKeyPressing(.L)) - _gizmoMode = .LOCAL; + // If we wrapped this frame we weren't hovering because the cursor has to be be out of bounds to wrap + _editor.CurrentCamera.AllowMove = _hasFocus && (ImGui.IsWindowHovered() || _wrappedCursor); + + if (_hasFocus && !_editor.CurrentCamera.InUse) + { + if (Input.IsKeyPressing(.Q)) + _gizmoType = .TRANSLATE; + if (Input.IsKeyPressing(.W)) + _gizmoType = .ROTATE; + if (Input.IsKeyPressing(.E)) + _gizmoType = .SCALE; + + if (Input.IsKeyPressing(.G)) + _gizmoMode = .WORLD; + if (Input.IsKeyPressing(.L)) + _gizmoMode = .LOCAL; + } } - + if(_renderTarget != null) { ImGui.Image(_renderTarget.GetViewBinding(0), viewportSize); //ImGui.Image(_editor.CurrentCamera.RenderTarget.GetViewBinding(0), viewportSize); //ImGui.Image(_editor.CurrentScene.[Friend]_compositeTarget.GetViewBinding(0), viewportSize); } - + + if (EditorMode) + { + HandleDropTarget(); + + bool gizmoUsed = DrawImGuizmo(viewportSize); + + MousePicking(viewportSize, gizmoUsed); + } + + ImGui.End(); + + if(_oldViewportSize != viewportSize) + { + ViewportSizeChanged.Invoke(this, (Vector2)viewportSize); + _viewPortChanged = true; + _oldViewportSize = viewportSize; + } + } + + /// Provides the ImGui Drop target and handles dropped payload. + private void HandleDropTarget() + { if (ImGui.BeginDragDropTarget()) { ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM"); if (payload != null) { - Log.EngineLogger.Warning(""); - StringView path = .((char8*)payload.Data, (int)payload.DataSize); _editor.RequestOpenScene(this, path); } ImGui.EndDragDropTarget(); } - - bool gizmoUsed = DrawImGuizmo(viewportSize); - - MousePicking(viewportSize, gizmoUsed); - - ImGui.End(); - - if(oldViewportSize != viewportSize) - { - ViewportSizeChangedEvent.Invoke(this, (Vector2)viewportSize); - viewPortChanged = true; - oldViewportSize = viewportSize; - } } /// Wraps the mouse, so that it always stays in the viewport. @@ -158,11 +180,15 @@ namespace GlitchyEditor.EditWindows if (newMousePos != mousePos) { Input.SetMousePosition((Int2)newMousePos); + // After wrapping the cursor the the other side, the camera controller must not compare the positions, + // because the delta doesn't represent the correct movement of the cursor. + // TODO: can be solved by using direct mouse movement instead of comparing positions _editor.CurrentCamera.[Friend]MouseCooldown = 2; _wrappedCursor = true; } } + /// If the user clicks, the entity beneath the cursor will be selected. private void MousePicking(ImGui.Vec2 viewportSize, bool gizmoUsed) { Vector2 relativeMouse = (Vector2)ImGui.GetMousePos() - (Vector2)ImGui.GetItemRectMin(); @@ -183,7 +209,7 @@ namespace GlitchyEditor.EditWindows SelectionChanged = true; SelectedEntityId = id; - EntityClickedEvent(this, id); + EntityClicked(this, id); } else { @@ -191,12 +217,6 @@ namespace GlitchyEditor.EditWindows } } - private ImGuizmo.OPERATION _gizmoType = .TRANSLATE; - private ImGuizmo.MODE _gizmoMode = .LOCAL; - private float _snap = 0.5f; - private float _angleSnap = 45.0f; - private bool _doSnap = false; - private void ShowMenuBar() { if(ImGui.BeginMenuBar()) @@ -262,6 +282,7 @@ namespace GlitchyEditor.EditWindows private bool DrawImGuizmo(ImGui.Vec2 viewportSize) { + // TODO: Needed if we have a orthographic editor-camera (or support gizmos in the Play-Window, where we can also have ortho projections) ImGuizmo.SetOrthographic(false); ImGuizmo.SetDrawlist(); @@ -299,7 +320,7 @@ namespace GlitchyEditor.EditWindows { // TODO: Fix when parent is scaled // Seems to work fine for parent rotation and translation but scaled parent ruins everything - // (probably because scaling a rotated matrix results in a skewed matrix, but unity can do it, so should we) + // (probably because scaling a rotated matrix results in a skewed matrix, but unity can do it and so should we) transformCmp.LocalTransform = parentView * worldTransform; } diff --git a/GlitchyEditor/src/EditorIcons.bf b/GlitchyEditor/src/EditorIcons.bf index 9580983..686737b 100644 --- a/GlitchyEditor/src/EditorIcons.bf +++ b/GlitchyEditor/src/EditorIcons.bf @@ -13,6 +13,8 @@ namespace GlitchyEditor public SubTexture2D Camera ~ _.ReleaseRef(); public SubTexture2D Folder ~ _.ReleaseRef(); public SubTexture2D File ~ _.ReleaseRef(); + public SubTexture2D Play ~ _.ReleaseRef(); + public SubTexture2D Stop ~ _.ReleaseRef(); public SamplerState SamplerState { @@ -30,6 +32,8 @@ namespace GlitchyEditor Camera = GetNextGridTexture(ref pen, iconSize); Folder = GetNextGridTexture(ref pen, iconSize); File = GetNextGridTexture(ref pen, iconSize); + Play = GetNextGridTexture(ref pen, iconSize); + Stop = GetNextGridTexture(ref pen, iconSize); } private SubTexture2D GetNextGridTexture(ref Vector2 pen, Vector2 iconSize) diff --git a/GlitchyEditor/src/EditorLayer.bf b/GlitchyEditor/src/EditorLayer.bf index e7aad13..9064ea1 100644 --- a/GlitchyEditor/src/EditorLayer.bf +++ b/GlitchyEditor/src/EditorLayer.bf @@ -56,6 +56,16 @@ namespace GlitchyEditor EditorIcons _editorIcons ~ _.ReleaseRef(); + enum SceneState + { + Edit, + Play, + // Pause, + // Simulate + } + + SceneState _sceneState = .Edit; + public this() : base("Example") { Application.Get().Window.IsVSync = false; @@ -121,7 +131,7 @@ namespace GlitchyEditor private void InitEditor() { _editor = new Editor(_scene); - _editor.SceneViewportWindow.ViewportSizeChangedEvent.Add(new (s, e) => ViewportSizeChanged(s, e)); + _editor.SceneViewportWindow.ViewportSizeChanged.Add(new (s, e) => ViewportSizeChanged(s, e)); _editor.CurrentCamera = &_camera; _editor.RequestOpenScene.Add(new (s, fileName) => { @@ -141,7 +151,10 @@ namespace GlitchyEditor RenderCommand.SetBlendState(_alphaBlendState); RenderCommand.SetDepthStencilState(_depthStencilState); - _scene.UpdateEditor(gameTime, _camera, _viewportTarget, scope => DebugDraw3D, scope => DebugDraw2D); + if (_sceneState == .Edit) + _scene.UpdateEditor(gameTime, _camera, _viewportTarget, scope => DebugDraw3D, scope => DebugDraw2D); + else if (_sceneState == .Play) + _scene.UpdateRuntime(gameTime, _viewportTarget); RenderCommand.UnbindRenderTargets(); RenderCommand.SetRenderTarget(null, 0, true); @@ -232,7 +245,7 @@ namespace GlitchyEditor private bool OnImGuiRender(ImGuiRenderEvent event) { - //viewer.ViewTexture(Renderer.[Friend]_gBuffer.Albedo); + //viewer.ViewTexture(Renderer.[Friend]_gBuffer.Target); ImGui.Viewport* viewport = ImGui.GetMainViewport(); ImGui.DockSpaceOverViewport(viewport); @@ -245,9 +258,66 @@ namespace GlitchyEditor _settingsWindow.Show(); + UI_Toolbar(); + return false; } + private void UI_Toolbar() + { + ImGui.PushStyleVar(.WindowPadding, ImGui.Vec2(0, 2)); + ImGui.PushStyleVar(.ItemInnerSpacing, ImGui.Vec2(0, 0)); + ImGui.PushStyleColor(.Button, ImGui.Vec4(0, 0, 0, 0)); + + let colors = ImGui.GetStyle().Colors; + + ImGui.Vec4 hoveredColor = colors[(int)ImGui.Col.ButtonHovered]; + hoveredColor.w = 0.5f; + + ImGui.Vec4 activeColor = colors[(int)ImGui.Col.ButtonActive]; + activeColor.w = 0.5f; + + ImGui.PushStyleColor(.ButtonHovered, hoveredColor); + ImGui.PushStyleColor(.ButtonActive, activeColor); + + ImGui.Begin("##toolbar", null, .NoDecoration | .NoScrollbar | .NoScrollWithMouse); + + SubTexture2D icon = _sceneState == .Edit ? _editorIcons.Play : _editorIcons.Stop; + + float size = ImGui.GetWindowHeight() - 4.0f; + + ImGui.SameLine((ImGui.GetContentRegionMax().x / 2 - size / 2)); + + if (ImGui.ImageButton(icon, .(size, size), .Zero, .Ones, 0)) + { + if (_sceneState == .Edit) + { + OnScenePlay(); + } + else if (_sceneState == .Play) + { + OnSceneStop(); + } + } + + ImGui.End(); + + ImGui.PopStyleColor(3); + ImGui.PopStyleVar(2); + } + + private void OnScenePlay() + { + _sceneState = .Play; + _editor.SceneViewportWindow.EditorMode = false; + } + + private void OnSceneStop() + { + _sceneState = .Edit; + _editor.SceneViewportWindow.EditorMode = true; + } + // Just for testing private void TestEntitiesWithModels() { @@ -282,6 +352,7 @@ namespace GlitchyEditor let camera = cameraNtt.AddComponent(); camera.Primary = true; camera.Camera.SetPerspective(MathHelper.ToRadians(45), 0.1f, 10.0f); + camera.RenderTarget = _cameraTarget; } var fxLib = Application.Get().EffectLibrary; diff --git a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11Buffer.bf b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11Buffer.bf index 8a9ad71..26f4914 100644 --- a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11Buffer.bf +++ b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11Buffer.bf @@ -84,7 +84,7 @@ namespace GlitchyEngine.Renderer return .Ok; } - protected override Result PlatformSetData(void* data, uint32 byteLength, uint32 dstByteOffset, GlitchyEngine.Renderer.MapType mapType) + protected override Result PlatformSetData(void* data, uint32 byteLength, uint32 dstByteOffset, Renderer.MapType mapType) { Debug.Profiler.ProfileResourceFunction!(); @@ -102,7 +102,7 @@ namespace GlitchyEngine.Renderer Box dataBox = .(dstByteOffset, 0, 0, dstByteOffset + byteLength, 1, 1); NativeContext.UpdateSubresource(nativeBuffer, 0, &dataBox, data, byteLength, byteLength); case .Dynamic: - Debug.Assert(mapType.CanWrite, "The map type has to have write access."); + Log.EngineLogger.Assert(mapType == .WriteDiscard || mapType == .WriteNoOverwrite, scope $"When writing to dynamic resources the map type must be {nameof(Renderer.MapType.WriteDiscard)} or {nameof(Renderer.MapType.WriteNoOverwrite)}."); // Todo: DoNotWaitFlag MappedSubresource map = ?; NativeContext.Map(nativeBuffer, 0, (.)mapType, .None, &map); diff --git a/GlitchyEngine/src/Renderer/Renderer.bf b/GlitchyEngine/src/Renderer/Renderer.bf index 7bc0da6..4088cbb 100644 --- a/GlitchyEngine/src/Renderer/Renderer.bf +++ b/GlitchyEngine/src/Renderer/Renderer.bf @@ -232,7 +232,7 @@ namespace GlitchyEngine.Renderer _sceneConstants.CameraTarget = renderTarget; _sceneConstants.CompositionTarget = finalTarget; - _sceneBuffer.SetData(viewProjection); + _sceneBuffer.SetData(viewProjection , 0, .WriteDiscard); } public static void BeginScene(EditorCamera camera, RenderTargetGroup finalTarget) diff --git a/GlitchyEngine/src/World/Scene.bf b/GlitchyEngine/src/World/Scene.bf index b9336d0..11beb4a 100644 --- a/GlitchyEngine/src/World/Scene.bf +++ b/GlitchyEngine/src/World/Scene.bf @@ -63,8 +63,163 @@ namespace GlitchyEngine.World public void UpdateRuntime(GameTime gameTime, RenderTargetGroup finalTarget) { - // TODO: adapt changes from UpdateEditor! - Runtime.NotImplemented(); + Debug.Profiler.ProfileRendererFunction!(); + + finalTarget.AddRef(); + + TransformSystem.Update(_ecsWorld); + + // Find camera + Camera* primaryCamera = null; + Matrix primaryCameraTransform = default; + RenderTargetGroup renderTarget = null; + + for (var (entity, transform, camera) in _ecsWorld.Enumerate()) + { + if (camera.Primary)// && camera.RenderTarget != null) + { + primaryCamera = &camera.Camera; + primaryCameraTransform = transform.WorldTransform; + renderTarget = camera.RenderTarget..AddRef(); + } + } + + // 3D render + Renderer.BeginScene(*primaryCamera, primaryCameraTransform, renderTarget, _compositeTarget); + + for (var (entity, transform, mesh, meshRenderer) in _ecsWorld.Enumerate()) + { + Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform); + } + + for (var (entity, transform, light) in _ecsWorld.Enumerate()) + { + Renderer.Submit(light.SceneLight, transform.WorldTransform); + } + + Renderer.EndScene(); + + renderTarget.ReleaseRef(); + + // TODO: alphablending (handle in Renderer2D) + // TODO: 2D-Postprocessing requires rendering into separate target instead of directly into compositeTarget + + RenderCommand.SetRenderTargetGroup(_compositeTarget); + RenderCommand.BindRenderTargets(); + + // Sprite renderer + Renderer2D.BeginScene(*primaryCamera, primaryCameraTransform, .BackToFront); + + for (var (entity, transform, sprite) in _ecsWorld.Enumerate()) + { + Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index); + } + + Renderer2D.EndScene(); + + // Gamma correct composit target and draw it into viewport + { + RenderCommand.UnbindRenderTargets(); + RenderCommand.SetRenderTargetGroup(finalTarget, false); + RenderCommand.BindRenderTargets(); + + _gammaCorrectEffect.SetTexture("Texture", _compositeTarget, 0); + // TODO: iiihhh + _gammaCorrectEffect.Bind(Application.Get().Window.Context); + + FullscreenQuad.Draw(); + } + + finalTarget.ReleaseRef(); + + + /*Debug.Profiler.ProfileRendererFunction!(); + + finalTarget.AddRef(); + + TransformSystem.Update(_ecsWorld); + + // Run scripts + for (var (entity, script) in _ecsWorld.Enumerate()) + { + if (script.Instance == null) + { + script.Instance = script.InstantiateFunction(); + script.Instance._entity = Entity(entity, this); + script.Instance.[Friend]OnCreate(); + } + + script.Instance.[Friend]OnUpdate(gameTime); + } + + // Find camera + Camera* primaryCamera = null; + Matrix primaryCameraTransform = default; + RenderTargetGroup renderTarget = null; + + for (var (entity, transform, camera) in _ecsWorld.Enumerate()) + { + if (camera.Primary)// && camera.RenderTarget != null) + { + primaryCamera = &camera.Camera; + primaryCameraTransform = transform.WorldTransform; + //renderTarget = camera.RenderTarget..AddRef(); + } + } + + if (primaryCamera != null) + { + // 3D render + Renderer.BeginScene(*primaryCamera, primaryCameraTransform, _compositeTarget, finalTarget); + + for (var (entity, transform, mesh, meshRenderer) in _ecsWorld.Enumerate()) + { + Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform); + } + + for (var (entity, transform, light) in _ecsWorld.Enumerate()) + { + Renderer.Submit(light.SceneLight, transform.WorldTransform); + } + + Renderer.EndScene(); + + // TODO: alphablending (handle in Renderer2D) + // TODO: 2D-Postprocessing requires rendering into separate target instead of directly into compositeTarget + + RenderCommand.SetRenderTargetGroup(_compositeTarget); + RenderCommand.BindRenderTargets(); + + // Sprite renderer + Renderer2D.BeginScene(*primaryCamera, primaryCameraTransform, .BackToFront); + + for (var (entity, transform, sprite) in _ecsWorld.Enumerate()) + { + Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index); + } + + Renderer2D.EndScene(); + + // Gamma correct composit target and draw it into viewport + { + RenderCommand.UnbindRenderTargets(); + RenderCommand.SetRenderTargetGroup(finalTarget, false); + RenderCommand.BindRenderTargets(); + + _gammaCorrectEffect.SetTexture("Texture", _compositeTarget, 0); + // TODO: iiihhh + _gammaCorrectEffect.Bind(Application.Get().Window.Context); + + FullscreenQuad.Draw(); + } + } + + finalTarget.ReleaseRef();*/ + + + + + /* Debug.Profiler.ProfileRendererFunction!();