Play Button

This commit is contained in:
Simon Lübeß
2022-10-06 16:33:33 +02:00
parent 6958d27c30
commit 202083930a
9 changed files with 317 additions and 65 deletions
Binary file not shown.
Binary file not shown.
@@ -1,3 +1,4 @@
using System;
namespace GlitchyEditor.EditWindows namespace GlitchyEditor.EditWindows
{ {
abstract class EditorWindow abstract class EditorWindow
@@ -13,11 +13,30 @@ namespace GlitchyEditor.EditWindows
{ {
public const String s_WindowTitle = "Scene"; public const String s_WindowTitle = "Scene";
private ImGui.Vec2 _oldViewportSize = .(100, 100);
private bool _viewPortChanged;
/// True if the cursor wrapped from one side of the viewport to the other last frame.
private bool _wrappedCursor;
private RenderTargetGroup _renderTarget ~ _?.ReleaseRef(); private RenderTargetGroup _renderTarget ~ _?.ReleaseRef();
public Event<EventHandler<Vector2>> ViewportSizeChangedEvent ~ _.Dispose(); private ImGuizmo.OPERATION _gizmoType = .TRANSLATE;
public Event<EventHandler<uint32>> EntityClickedEvent ~ _.Dispose(); 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<EventHandler<Vector2>> ViewportSizeChanged ~ _.Dispose();
// Occurs when an entity was clicked.
public Event<EventHandler<uint32>> EntityClicked ~ _.Dispose();
/// The render target that is shown in the viewport window.
public RenderTargetGroup RenderTarget public RenderTargetGroup RenderTarget
{ {
get => _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) public this(Editor editor)
{ {
_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() protected override void InternalShow()
{ {
ImGui.PushStyleVar(.WindowPadding, ImGui.Vec2(1, 1)); ImGui.PushStyleVar(.WindowPadding, ImGui.Vec2(1, 1));
@@ -56,8 +68,6 @@ namespace GlitchyEditor.EditWindows
return; return;
} }
ShowMenuBar();
let viewportSize = ImGui.GetContentRegionAvail(); let viewportSize = ImGui.GetContentRegionAvail();
if(ImGui.IsWindowHovered() && Input.IsMouseButtonPressing(.RightButton)) if(ImGui.IsWindowHovered() && Input.IsMouseButtonPressing(.RightButton))
@@ -67,62 +77,74 @@ namespace GlitchyEditor.EditWindows
} }
_hasFocus = ImGui.IsWindowFocused(); _hasFocus = ImGui.IsWindowFocused();
if (_editor.CurrentCamera.[Friend]BindMouse && _hasFocus) if (EditorMode)
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 (Input.IsKeyPressing(.Q)) ShowMenuBar();
_gizmoType = .TRANSLATE;
if (Input.IsKeyPressing(.W)) if (_editor.CurrentCamera.[Friend]BindMouse && _hasFocus)
_gizmoType = .ROTATE; WrapMouseInViewport();
if (Input.IsKeyPressing(.E))
_gizmoType = .SCALE;
if (Input.IsKeyPressing(.G)) // If we wrapped this frame we weren't hovering because the cursor has to be be out of bounds to wrap
_gizmoMode = .WORLD; _editor.CurrentCamera.AllowMove = _hasFocus && (ImGui.IsWindowHovered() || _wrappedCursor);
if (Input.IsKeyPressing(.L))
_gizmoMode = .LOCAL; 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) if(_renderTarget != null)
{ {
ImGui.Image(_renderTarget.GetViewBinding(0), viewportSize); ImGui.Image(_renderTarget.GetViewBinding(0), viewportSize);
//ImGui.Image(_editor.CurrentCamera.RenderTarget.GetViewBinding(0), viewportSize); //ImGui.Image(_editor.CurrentCamera.RenderTarget.GetViewBinding(0), viewportSize);
//ImGui.Image(_editor.CurrentScene.[Friend]_compositeTarget.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()) if (ImGui.BeginDragDropTarget())
{ {
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM"); ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM");
if (payload != null) if (payload != null)
{ {
Log.EngineLogger.Warning("");
StringView path = .((char8*)payload.Data, (int)payload.DataSize); StringView path = .((char8*)payload.Data, (int)payload.DataSize);
_editor.RequestOpenScene(this, path); _editor.RequestOpenScene(this, path);
} }
ImGui.EndDragDropTarget(); 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. /// Wraps the mouse, so that it always stays in the viewport.
@@ -158,11 +180,15 @@ namespace GlitchyEditor.EditWindows
if (newMousePos != mousePos) if (newMousePos != mousePos)
{ {
Input.SetMousePosition((Int2)newMousePos); 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; _editor.CurrentCamera.[Friend]MouseCooldown = 2;
_wrappedCursor = true; _wrappedCursor = true;
} }
} }
/// If the user clicks, the entity beneath the cursor will be selected.
private void MousePicking(ImGui.Vec2 viewportSize, bool gizmoUsed) private void MousePicking(ImGui.Vec2 viewportSize, bool gizmoUsed)
{ {
Vector2 relativeMouse = (Vector2)ImGui.GetMousePos() - (Vector2)ImGui.GetItemRectMin(); Vector2 relativeMouse = (Vector2)ImGui.GetMousePos() - (Vector2)ImGui.GetItemRectMin();
@@ -183,7 +209,7 @@ namespace GlitchyEditor.EditWindows
SelectionChanged = true; SelectionChanged = true;
SelectedEntityId = id; SelectedEntityId = id;
EntityClickedEvent(this, id); EntityClicked(this, id);
} }
else 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() private void ShowMenuBar()
{ {
if(ImGui.BeginMenuBar()) if(ImGui.BeginMenuBar())
@@ -262,6 +282,7 @@ namespace GlitchyEditor.EditWindows
private bool DrawImGuizmo(ImGui.Vec2 viewportSize) 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.SetOrthographic(false);
ImGuizmo.SetDrawlist(); ImGuizmo.SetDrawlist();
@@ -299,7 +320,7 @@ namespace GlitchyEditor.EditWindows
{ {
// TODO: Fix when parent is scaled // TODO: Fix when parent is scaled
// Seems to work fine for parent rotation and translation but scaled parent ruins everything // 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; transformCmp.LocalTransform = parentView * worldTransform;
} }
+4
View File
@@ -13,6 +13,8 @@ namespace GlitchyEditor
public SubTexture2D Camera ~ _.ReleaseRef(); public SubTexture2D Camera ~ _.ReleaseRef();
public SubTexture2D Folder ~ _.ReleaseRef(); public SubTexture2D Folder ~ _.ReleaseRef();
public SubTexture2D File ~ _.ReleaseRef(); public SubTexture2D File ~ _.ReleaseRef();
public SubTexture2D Play ~ _.ReleaseRef();
public SubTexture2D Stop ~ _.ReleaseRef();
public SamplerState SamplerState public SamplerState SamplerState
{ {
@@ -30,6 +32,8 @@ namespace GlitchyEditor
Camera = GetNextGridTexture(ref pen, iconSize); Camera = GetNextGridTexture(ref pen, iconSize);
Folder = GetNextGridTexture(ref pen, iconSize); Folder = GetNextGridTexture(ref pen, iconSize);
File = 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) private SubTexture2D GetNextGridTexture(ref Vector2 pen, Vector2 iconSize)
+74 -3
View File
@@ -56,6 +56,16 @@ namespace GlitchyEditor
EditorIcons _editorIcons ~ _.ReleaseRef(); EditorIcons _editorIcons ~ _.ReleaseRef();
enum SceneState
{
Edit,
Play,
// Pause,
// Simulate
}
SceneState _sceneState = .Edit;
public this() : base("Example") public this() : base("Example")
{ {
Application.Get().Window.IsVSync = false; Application.Get().Window.IsVSync = false;
@@ -121,7 +131,7 @@ namespace GlitchyEditor
private void InitEditor() private void InitEditor()
{ {
_editor = new Editor(_scene); _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.CurrentCamera = &_camera;
_editor.RequestOpenScene.Add(new (s, fileName) => { _editor.RequestOpenScene.Add(new (s, fileName) => {
@@ -141,7 +151,10 @@ namespace GlitchyEditor
RenderCommand.SetBlendState(_alphaBlendState); RenderCommand.SetBlendState(_alphaBlendState);
RenderCommand.SetDepthStencilState(_depthStencilState); 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.UnbindRenderTargets();
RenderCommand.SetRenderTarget(null, 0, true); RenderCommand.SetRenderTarget(null, 0, true);
@@ -232,7 +245,7 @@ namespace GlitchyEditor
private bool OnImGuiRender(ImGuiRenderEvent event) private bool OnImGuiRender(ImGuiRenderEvent event)
{ {
//viewer.ViewTexture(Renderer.[Friend]_gBuffer.Albedo); //viewer.ViewTexture(Renderer.[Friend]_gBuffer.Target);
ImGui.Viewport* viewport = ImGui.GetMainViewport(); ImGui.Viewport* viewport = ImGui.GetMainViewport();
ImGui.DockSpaceOverViewport(viewport); ImGui.DockSpaceOverViewport(viewport);
@@ -245,9 +258,66 @@ namespace GlitchyEditor
_settingsWindow.Show(); _settingsWindow.Show();
UI_Toolbar();
return false; 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 // Just for testing
private void TestEntitiesWithModels() private void TestEntitiesWithModels()
{ {
@@ -282,6 +352,7 @@ namespace GlitchyEditor
let camera = cameraNtt.AddComponent<CameraComponent>(); let camera = cameraNtt.AddComponent<CameraComponent>();
camera.Primary = true; camera.Primary = true;
camera.Camera.SetPerspective(MathHelper.ToRadians(45), 0.1f, 10.0f); camera.Camera.SetPerspective(MathHelper.ToRadians(45), 0.1f, 10.0f);
camera.RenderTarget = _cameraTarget;
} }
var fxLib = Application.Get().EffectLibrary; var fxLib = Application.Get().EffectLibrary;
@@ -84,7 +84,7 @@ namespace GlitchyEngine.Renderer
return .Ok; return .Ok;
} }
protected override Result<void> PlatformSetData(void* data, uint32 byteLength, uint32 dstByteOffset, GlitchyEngine.Renderer.MapType mapType) protected override Result<void> PlatformSetData(void* data, uint32 byteLength, uint32 dstByteOffset, Renderer.MapType mapType)
{ {
Debug.Profiler.ProfileResourceFunction!(); Debug.Profiler.ProfileResourceFunction!();
@@ -102,7 +102,7 @@ namespace GlitchyEngine.Renderer
Box dataBox = .(dstByteOffset, 0, 0, dstByteOffset + byteLength, 1, 1); Box dataBox = .(dstByteOffset, 0, 0, dstByteOffset + byteLength, 1, 1);
NativeContext.UpdateSubresource(nativeBuffer, 0, &dataBox, data, byteLength, byteLength); NativeContext.UpdateSubresource(nativeBuffer, 0, &dataBox, data, byteLength, byteLength);
case .Dynamic: 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 // Todo: DoNotWaitFlag
MappedSubresource map = ?; MappedSubresource map = ?;
NativeContext.Map(nativeBuffer, 0, (.)mapType, .None, &map); NativeContext.Map(nativeBuffer, 0, (.)mapType, .None, &map);
+1 -1
View File
@@ -232,7 +232,7 @@ namespace GlitchyEngine.Renderer
_sceneConstants.CameraTarget = renderTarget; _sceneConstants.CameraTarget = renderTarget;
_sceneConstants.CompositionTarget = finalTarget; _sceneConstants.CompositionTarget = finalTarget;
_sceneBuffer.SetData<Matrix>(viewProjection); _sceneBuffer.SetData<Matrix>(viewProjection , 0, .WriteDiscard);
} }
public static void BeginScene(EditorCamera camera, RenderTargetGroup finalTarget) public static void BeginScene(EditorCamera camera, RenderTargetGroup finalTarget)
+157 -2
View File
@@ -63,8 +63,163 @@ namespace GlitchyEngine.World
public void UpdateRuntime(GameTime gameTime, RenderTargetGroup finalTarget) public void UpdateRuntime(GameTime gameTime, RenderTargetGroup finalTarget)
{ {
// TODO: adapt changes from UpdateEditor! Debug.Profiler.ProfileRendererFunction!();
Runtime.NotImplemented();
finalTarget.AddRef();
TransformSystem.Update(_ecsWorld);
// Find camera
Camera* primaryCamera = null;
Matrix primaryCameraTransform = default;
RenderTargetGroup renderTarget = null;
for (var (entity, transform, camera) in _ecsWorld.Enumerate<TransformComponent, CameraComponent>())
{
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<TransformComponent, MeshComponent, MeshRendererComponent>())
{
Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform);
}
for (var (entity, transform, light) in _ecsWorld.Enumerate<TransformComponent, LightComponent>())
{
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<TransformComponent, SpriterRendererComponent>())
{
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<NativeScriptComponent>())
{
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<TransformComponent, CameraComponent>())
{
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<TransformComponent, MeshComponent, MeshRendererComponent>())
{
Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform);
}
for (var (entity, transform, light) in _ecsWorld.Enumerate<TransformComponent, LightComponent>())
{
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<TransformComponent, SpriterRendererComponent>())
{
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!(); Debug.Profiler.ProfileRendererFunction!();