Separated window for game and editor

This commit is contained in:
Simon Lübeß
2023-03-24 22:48:55 +01:00
parent 184480243f
commit f16fbc3984
6 changed files with 493 additions and 271 deletions
@@ -0,0 +1,106 @@
using System;
using ImGui;
using GlitchyEngine.Renderer;
using GlitchyEngine.Math;
using GlitchyEngine;
using GlitchyEngine.World;
using ImGuizmo;
using GlitchyEngine.Events;
namespace GlitchyEditor.EditWindows
{
class GameViewportWindow : EditorWindow
{
public const String s_WindowTitle = "Game";
private ImGui.Vec2 _oldViewportSize = .(100, 100);
private bool _viewPortChanged;
private bool _visible;
private RenderTargetGroup _renderTarget ~ _?.ReleaseRef();
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
{
get => _renderTarget;
set
{
if(_renderTarget == value)
return;
SetReference!(_renderTarget, value);
}
}
public bool Visible => _visible;
public this(Editor editor)
{
_editor = editor;
}
protected override void InternalShow()
{
ImGui.PushStyleVar(.WindowPadding, ImGui.Vec2(1, 1));
defer ImGui.PopStyleVar();
if(!ImGui.Begin(s_WindowTitle, &_open, .NoScrollbar | .MenuBar))
{
ImGui.End();
_visible = false;
return;
}
_visible = true;
let viewportSize = ImGui.GetContentRegionAvail();
if(ImGui.IsWindowHovered() && Input.IsMouseButtonPressing(.RightButton))
{
let currentWindow = ImGui.GetCurrentWindow();
ImGui.FocusWindow(currentWindow);
}
_hasFocus = ImGui.IsWindowFocused();
if(_renderTarget != null)
{
ImGui.Image(_renderTarget.GetViewBinding(0), viewportSize);
}
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)
{
StringView path = .((char8*)payload.Data, (int)payload.DataSize);
_editor.RequestOpenScene(this, path);
}
ImGui.EndDragDropTarget();
}
}
}
}
@@ -27,6 +27,8 @@ namespace GlitchyEditor.EditWindows
private float _angleSnap = 45.0f; private float _angleSnap = 45.0f;
private bool _doSnap = false; private bool _doSnap = false;
private bool _visible;
public uint32 SelectedEntityId {get; private set; } public uint32 SelectedEntityId {get; private set; }
public bool SelectionChanged { get; private set; } public bool SelectionChanged { get; private set; }
@@ -52,6 +54,8 @@ namespace GlitchyEditor.EditWindows
/// Gets or sets whether the editor functionality (gizmo, picking etc.) is enabled. /// Gets or sets whether the editor functionality (gizmo, picking etc.) is enabled.
public bool EditorMode { get; set; } = true public bool EditorMode { get; set; } = true
public bool Visible => _visible;
public this(Editor editor) public this(Editor editor)
{ {
_editor = editor; _editor = editor;
@@ -65,9 +69,13 @@ namespace GlitchyEditor.EditWindows
if(!ImGui.Begin(s_WindowTitle, &_open, .NoScrollbar | .MenuBar)) if(!ImGui.Begin(s_WindowTitle, &_open, .NoScrollbar | .MenuBar))
{ {
ImGui.End(); ImGui.End();
_visible = false;
return; return;
} }
_visible = true;
let viewportSize = ImGui.GetContentRegionAvail(); let viewportSize = ImGui.GetContentRegionAvail();
if(ImGui.IsWindowHovered() && Input.IsMouseButtonPressing(.RightButton)) if(ImGui.IsWindowHovered() && Input.IsMouseButtonPressing(.RightButton))
@@ -78,30 +86,27 @@ namespace GlitchyEditor.EditWindows
_hasFocus = ImGui.IsWindowFocused(); _hasFocus = ImGui.IsWindowFocused();
if (EditorMode) ShowMenuBar();
if (_editor.CurrentCamera.[Friend]BindMouse && _hasFocus)
WrapMouseInViewport();
// 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)
{ {
ShowMenuBar(); if (Input.IsKeyPressing(.Q))
_gizmoType = .TRANSLATE;
if (_editor.CurrentCamera.[Friend]BindMouse && _hasFocus) if (Input.IsKeyPressing(.W))
WrapMouseInViewport(); _gizmoType = .ROTATE;
if (Input.IsKeyPressing(.E))
_gizmoType = .SCALE;
// If we wrapped this frame we weren't hovering because the cursor has to be be out of bounds to wrap if (Input.IsKeyPressing(.G))
_editor.CurrentCamera.AllowMove = _hasFocus && (ImGui.IsWindowHovered() || _wrappedCursor); _gizmoMode = .WORLD;
if (Input.IsKeyPressing(.L))
if (_hasFocus && !_editor.CurrentCamera.InUse) _gizmoMode = .LOCAL;
{
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)
@@ -111,14 +116,11 @@ namespace GlitchyEditor.EditWindows
//ImGui.Image(_editor.CurrentScene.[Friend]_compositeTarget.GetViewBinding(0), viewportSize); //ImGui.Image(_editor.CurrentScene.[Friend]_compositeTarget.GetViewBinding(0), viewportSize);
} }
if (EditorMode) HandleDropTarget();
{
HandleDropTarget(); bool gizmoUsed = DrawImGuizmo(viewportSize);
bool gizmoUsed = DrawImGuizmo(viewportSize); MousePicking(viewportSize, gizmoUsed);
MousePicking(viewportSize, gizmoUsed);
}
ImGui.End(); ImGui.End();
@@ -156,25 +158,27 @@ namespace GlitchyEditor.EditWindows
let winPos = (Vector2)ImGui.GetWindowPos(); let winPos = (Vector2)ImGui.GetWindowPos();
let regionMin = winPos + (Vector2)ImGui.GetWindowContentRegionMin(); let regionMin = winPos + (Vector2)ImGui.GetWindowContentRegionMin();
let regionMax = winPos + (Vector2)ImGui.GetWindowContentRegionMax(); let regionMax = winPos + (Vector2)ImGui.GetWindowContentRegionMax();
ImGui.DrawRect((.)regionMin, (.)regionMax, .(0, 255, 0));
Vector2 newMousePos = mousePos; Vector2 newMousePos = mousePos;
if (mousePos.X < regionMin.X) if (mousePos.X < regionMin.X + 1)
{ {
newMousePos.X = regionMax.X - 1; newMousePos.X = regionMax.X - 2;
} }
else if (mousePos.X > regionMax.X - 1) else if (mousePos.X > regionMax.X - 1)
{ {
newMousePos.X = regionMin.X + 1; newMousePos.X = regionMin.X + 2;
} }
if (mousePos.Y < regionMin.Y) if (mousePos.Y < regionMin.Y + 1)
{ {
newMousePos.Y = regionMax.Y - 1; newMousePos.Y = regionMax.Y - 100;
} }
else if (mousePos.Y > regionMax.Y - 1) else if (mousePos.Y > regionMax.Y - 1)
{ {
newMousePos.Y = regionMin.Y + 1; newMousePos.Y = regionMin.Y + 10;
} }
if (newMousePos != mousePos) if (newMousePos != mousePos)
@@ -193,8 +197,8 @@ namespace GlitchyEditor.EditWindows
{ {
Vector2 relativeMouse = (Vector2)ImGui.GetMousePos() - (Vector2)ImGui.GetItemRectMin(); Vector2 relativeMouse = (Vector2)ImGui.GetMousePos() - (Vector2)ImGui.GetItemRectMin();
int rtWidth = _editor.CurrentScene.[Friend]_compositeTarget.Width; int rtWidth = _editor.EditorSceneRenderer.CompositeTarget.Width;
int rtHeight = _editor.CurrentScene.[Friend]_compositeTarget.Height; int rtHeight = _editor.EditorSceneRenderer.CompositeTarget.Height;
if (Input.IsMouseButtonPressing(.LeftButton) && if (Input.IsMouseButtonPressing(.LeftButton) &&
ImGui.IsWindowHovered() && !gizmoUsed && !_editor.CurrentCamera.InUse && ImGui.IsWindowHovered() && !gizmoUsed && !_editor.CurrentCamera.InUse &&
@@ -204,7 +208,7 @@ namespace GlitchyEditor.EditWindows
{ {
uint32 id = uint32.MaxValue; uint32 id = uint32.MaxValue;
_editor.CurrentScene.[Friend]_compositeTarget.GetData<uint32>(&id, 1, (.)relativeMouse.X, (.)relativeMouse.Y, 1, 1); _editor.EditorSceneRenderer.CompositeTarget.GetData<uint32>(&id, 1, (.)relativeMouse.X, (.)relativeMouse.Y, 1, 1);
SelectionChanged = true; SelectionChanged = true;
SelectedEntityId = id; SelectedEntityId = id;
+8 -1
View File
@@ -17,7 +17,8 @@ namespace GlitchyEditor
private EntityHierarchyWindow _entityHierarchyWindow ~ delete _; private EntityHierarchyWindow _entityHierarchyWindow ~ delete _;
private ComponentEditWindow _componentEditWindow ~ delete _; private ComponentEditWindow _componentEditWindow ~ delete _;
private SceneViewportWindow _sceneViewportWindow~ delete _; private SceneViewportWindow _sceneViewportWindow ~ delete _;
private GameViewportWindow _gameViewportWindow ~ delete _;
private ContentBrowserWindow _contentBrowserWindow ~ delete _; private ContentBrowserWindow _contentBrowserWindow ~ delete _;
private PropertiesWindow _propertiesWindow ~ delete _; private PropertiesWindow _propertiesWindow ~ delete _;
@@ -39,6 +40,7 @@ namespace GlitchyEditor
public EntityHierarchyWindow EntityHierarchyWindow => _entityHierarchyWindow; public EntityHierarchyWindow EntityHierarchyWindow => _entityHierarchyWindow;
public ComponentEditWindow ComponentEditWindow => _componentEditWindow; public ComponentEditWindow ComponentEditWindow => _componentEditWindow;
public SceneViewportWindow SceneViewportWindow => _sceneViewportWindow; public SceneViewportWindow SceneViewportWindow => _sceneViewportWindow;
public GameViewportWindow GameViewportWindow => _gameViewportWindow;
public ContentBrowserWindow ContentBrowserWindow => _contentBrowserWindow; public ContentBrowserWindow ContentBrowserWindow => _contentBrowserWindow;
public PropertiesWindow PropertiesWindow => _propertiesWindow; public PropertiesWindow PropertiesWindow => _propertiesWindow;
@@ -46,6 +48,9 @@ namespace GlitchyEditor
public Event<EventHandler<StringView>> RequestOpenScene ~ _.Dispose(); public Event<EventHandler<StringView>> RequestOpenScene ~ _.Dispose();
public SceneRenderer GameSceneRenderer {get; set;}
public SceneRenderer EditorSceneRenderer {get; set;}
/// Creates a new editor for the given world /// Creates a new editor for the given world
public this(Scene scene, EditorContentManager contentManager) public this(Scene scene, EditorContentManager contentManager)
{ {
@@ -58,6 +63,7 @@ namespace GlitchyEditor
private void InitWindows() private void InitWindows()
{ {
_sceneViewportWindow = new SceneViewportWindow(this); _sceneViewportWindow = new SceneViewportWindow(this);
_gameViewportWindow = new GameViewportWindow(this);
_entityHierarchyWindow = new EntityHierarchyWindow(this, _scene); _entityHierarchyWindow = new EntityHierarchyWindow(this, _scene);
_componentEditWindow = new ComponentEditWindow(_entityHierarchyWindow); _componentEditWindow = new ComponentEditWindow(_entityHierarchyWindow);
_contentBrowserWindow = new ContentBrowserWindow((.)Application.Get().ContentManager); _contentBrowserWindow = new ContentBrowserWindow((.)Application.Get().ContentManager);
@@ -67,6 +73,7 @@ namespace GlitchyEditor
public void Update() public void Update()
{ {
_sceneViewportWindow.Show(); _sceneViewportWindow.Show();
_gameViewportWindow.Show();
_entityHierarchyWindow.Show(); _entityHierarchyWindow.Show();
_componentEditWindow.Show(); _componentEditWindow.Show();
_contentBrowserWindow.Show(); _contentBrowserWindow.Show();
+71 -12
View File
@@ -30,6 +30,9 @@ namespace GlitchyEditor
Scene _activeScene ~ _?.ReleaseRef(); Scene _activeScene ~ _?.ReleaseRef();
Scene _editorScene ~ _?.ReleaseRef(); Scene _editorScene ~ _?.ReleaseRef();
SceneRenderer _gameSceneRenderer ~ delete _;
SceneRenderer _editorSceneRenderer ~ delete _;
String _sceneFilePath = new String() ~ delete _; String _sceneFilePath = new String() ~ delete _;
public String SceneFilePath public String SceneFilePath
@@ -47,7 +50,8 @@ namespace GlitchyEditor
Editor _editor ~ delete _; Editor _editor ~ delete _;
RenderTargetGroup _cameraTarget ~ _.ReleaseRef(); RenderTargetGroup _cameraTarget ~ _.ReleaseRef();
RenderTargetGroup _viewportTarget ~ _.ReleaseRef(); RenderTargetGroup _editorViewportTarget ~ _.ReleaseRef();
RenderTargetGroup _gameViewportTarget ~ _.ReleaseRef();
SettingsWindow _settingsWindow = new .() ~ delete _; SettingsWindow _settingsWindow = new .() ~ delete _;
@@ -83,6 +87,9 @@ namespace GlitchyEditor
_editorScene = new Scene(); _editorScene = new Scene();
SetReference!(_activeScene, _editorScene); SetReference!(_activeScene, _editorScene);
_gameSceneRenderer = new SceneRenderer();
_editorSceneRenderer = new SceneRenderer();
_camera = EditorCamera(Vector3(3.5f, 1.25f, 2.75f), Quaternion.FromEulerAngles(MathHelper.ToRadians(40), MathHelper.ToRadians(25), 0), MathHelper.ToRadians(75), 0.1f, 1); _camera = EditorCamera(Vector3(3.5f, 1.25f, 2.75f), Quaternion.FromEulerAngles(MathHelper.ToRadians(40), MathHelper.ToRadians(25), 0), MathHelper.ToRadians(75), 0.1f, 1);
_camera.RenderTarget = _cameraTarget; _camera.RenderTarget = _cameraTarget;
@@ -144,7 +151,15 @@ namespace GlitchyEditor
DepthTargetDescription = .(.D24_UNorm_S8_UInt) DepthTargetDescription = .(.D24_UNorm_S8_UInt)
}); });
_viewportTarget = new RenderTargetGroup(.() _editorViewportTarget = new RenderTargetGroup(.()
{
Width = 100,
Height = 100,
ColorTargetDescriptions = TargetDescription[](
.(.R8G8B8A8_UNorm))
});
_gameViewportTarget = new RenderTargetGroup(.()
{ {
Width = 100, Width = 100,
Height = 100, Height = 100,
@@ -167,8 +182,11 @@ namespace GlitchyEditor
private void InitEditor() private void InitEditor()
{ {
_editor = new Editor(_editorScene, _contentManager); _editor = new Editor(_editorScene, _contentManager);
_editor.SceneViewportWindow.ViewportSizeChanged.Add(new (s, e) => ViewportSizeChanged(s, e)); _editor.SceneViewportWindow.ViewportSizeChanged.Add(new (s, e) => EditorViewportSizeChanged(s, e));
_editor.GameViewportWindow.ViewportSizeChanged.Add(new (s, e) => GameViewportSizeChanged(s, e));
_editor.CurrentCamera = &_camera; _editor.CurrentCamera = &_camera;
_editor.GameSceneRenderer = _gameSceneRenderer;
_editor.EditorSceneRenderer = _editorSceneRenderer;
_editor.RequestOpenScene.Add(new (s, fileName) => { _editor.RequestOpenScene.Add(new (s, fileName) => {
LoadSceneFile(fileName); LoadSceneFile(fileName);
@@ -177,22 +195,38 @@ namespace GlitchyEditor
public override void Update(GameTime gameTime) public override void Update(GameTime gameTime)
{ {
Debug.Profiler.ProfileFunction!();
_camera.Update(gameTime); _camera.Update(gameTime);
_editor.CurrentScene = _activeScene; _editor.CurrentScene = _activeScene;
_activeScene.Update(gameTime, (_sceneState == .Edit) ? .Editor : .Runtime);
// Clear the swapchain-buffer // Clear the swapchain-buffer
RenderCommand.Clear(null, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0); RenderCommand.Clear(null, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
RenderCommand.SetBlendState(_alphaBlendState);
RenderCommand.SetDepthStencilState(_depthStencilState);
if (_editor.SceneViewportWindow.Visible)
{
_editorSceneRenderer.Scene = _activeScene;
RenderCommand.Clear(_viewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0); RenderCommand.Clear(_editorViewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
_editorSceneRenderer.RenderEditor(gameTime, _camera, _editorViewportTarget, scope => DebugDraw3D, scope => DebugDraw2D);
}
RenderCommand.SetBlendState(_alphaBlendState); RenderCommand.SetBlendState(_alphaBlendState);
RenderCommand.SetDepthStencilState(_depthStencilState); RenderCommand.SetDepthStencilState(_depthStencilState);
if (_sceneState == .Edit) if (_editor.GameViewportWindow.Visible)
_activeScene.UpdateEditor(gameTime, _camera, _viewportTarget, scope => DebugDraw3D, scope => DebugDraw2D); {
else if (_sceneState == .Play) _gameSceneRenderer.Scene = _activeScene;
_activeScene.UpdateRuntime(gameTime, _viewportTarget);
RenderCommand.Clear(_gameViewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
_gameSceneRenderer.RenderRuntime(gameTime, _gameViewportTarget);
}
RenderCommand.UnbindRenderTargets(); RenderCommand.UnbindRenderTargets();
RenderCommand.SetRenderTarget(null, 0, true); RenderCommand.SetRenderTarget(null, 0, true);
@@ -301,7 +335,8 @@ namespace GlitchyEditor
DrawMainMenuBar(); DrawMainMenuBar();
_editor.SceneViewportWindow.RenderTarget = _viewportTarget; _editor.SceneViewportWindow.RenderTarget = _editorViewportTarget;
_editor.GameViewportWindow.RenderTarget = _gameViewportTarget;
_editor.Update(); _editor.Update();
@@ -381,6 +416,13 @@ namespace GlitchyEditor
_sceneState = .Edit; _sceneState = .Edit;
_editor.CurrentScene = _activeScene; _editor.CurrentScene = _activeScene;
/*
* Update the viewport size because if the game windows size changed in
* "Game"-mode the updated aspect-rations will reset once we go back
* into "Editor"-mode (because Game-Mode works on a copy of the scene).
*/
GameViewportSizeChanged(null, _editor.GameViewportWindow.ViewportSize);
} }
// Just for testing // Just for testing
@@ -671,7 +713,7 @@ namespace GlitchyEditor
return false; return false;
} }
private void ViewportSizeChanged(Object sender, Vector2 viewportSize) private void EditorViewportSizeChanged(Object sender, Vector2 viewportSize)
{ {
uint32 sizeX = (uint32)viewportSize.X; uint32 sizeX = (uint32)viewportSize.X;
uint32 sizeY = (uint32)viewportSize.Y; uint32 sizeY = (uint32)viewportSize.Y;
@@ -679,11 +721,28 @@ namespace GlitchyEditor
if(sizeX == 0 || sizeY == 0) if(sizeX == 0 || sizeY == 0)
return; return;
_viewportTarget.Resize(sizeX, sizeY); _editorViewportTarget.Resize(sizeX, sizeY);
_cameraTarget.Resize(sizeX, sizeY); _cameraTarget.Resize(sizeX, sizeY);
_activeScene.OnViewportResize(sizeX, sizeY); //_activeScene.OnViewportResize(sizeX, sizeY);
_camera.OnViewportResize(sizeX, sizeY); _camera.OnViewportResize(sizeX, sizeY);
_editorSceneRenderer.OnViewportResize(sizeX, sizeY);
}
private void GameViewportSizeChanged(Object sender, Vector2 viewportSize)
{
uint32 sizeX = (uint32)viewportSize.X;
uint32 sizeY = (uint32)viewportSize.Y;
if(sizeX == 0 || sizeY == 0)
return;
_gameViewportTarget.Resize(sizeX, sizeY);
_activeScene.OnViewportResize(sizeX, sizeY);
_gameSceneRenderer.OnViewportResize(sizeX, sizeY);
} }
private bool OnKeyPressed(KeyPressedEvent e) private bool OnKeyPressed(KeyPressedEvent e)
+44 -218
View File
@@ -19,13 +19,6 @@ namespace GlitchyEngine.World
private Dictionary<Type, function void(Entity entity, Type componentType, void* component)> _onComponentAddedHandlers = new .() ~ delete _; private Dictionary<Type, function void(Entity entity, Type componentType, void* component)> _onComponentAddedHandlers = new .() ~ delete _;
private RenderTargetGroup _compositeTarget ~ _.ReleaseRef();
// Temporary target for camera. Needs to change as soon as we support multiple cameras
private RenderTargetGroup _cameraTarget ~ _.ReleaseRef();
private AssetHandle _gammaCorrectEffect;
private uint32 _viewportWidth, _viewportHeight; private uint32 _viewportWidth, _viewportHeight;
// Maps ids to the entities they represent. // Maps ids to the entities they represent.
@@ -52,25 +45,6 @@ namespace GlitchyEngine.World
cameraComponent.Camera.SetViewportSize(e.Scene._viewportWidth, e.Scene._viewportHeight); cameraComponent.Camera.SetViewportSize(e.Scene._viewportWidth, e.Scene._viewportHeight);
}); });
RenderTargetGroupDescription desc = .(100, 100,
TargetDescription[](
RenderTargetFormat.R16G16B16A16_Float,
.(RenderTargetFormat.R32_UInt) {ClearColor = .UInt(uint32.MaxValue)}),
RenderTargetFormat.D24_UNorm_S8_UInt);
_compositeTarget = new RenderTargetGroup(desc);
_cameraTarget = new RenderTargetGroup(.(){
Width = 100,
Height = 100,
ColorTargetDescriptions = TargetDescription[](
.(.R16G16B16A16_Float),
.(.R32_UInt)
),
DepthTargetDescription = .(.D24_UNorm_S8_UInt)
});
_gammaCorrectEffect = Content.LoadAsset("Shaders/GammaCorrect.hlsl");//Application.Get().EffectLibrary.Load("content/Shaders/GammaCorrect.hlsl");
} }
public ~this() public ~this()
@@ -215,207 +189,62 @@ namespace GlitchyEngine.World
_physicsWorld2D = null; _physicsWorld2D = null;
} }
public void UpdateRuntime(GameTime gameTime, RenderTargetGroup finalTarget) public enum UpdateMode
{ {
Debug.Profiler.ProfileRendererFunction!(); Editor = 0x01,
Physics = 0x02,
finalTarget.AddRef(); Runtime = 0x04 | Physics,
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);
}
// Update 2D physics
{
const int32 velocityIterations = 6;
const int32 positionIterations = 2;
const int32 particleIterations = 2;
Box2D.World.Step(_physicsWorld2D, gameTime.DeltaTime, velocityIterations, positionIterations, particleIterations);
// Retrieve transform from Box2D
for (var entry in _ecsWorld.Enumerate<Rigidbody2DComponent>())
{
Entity entity = .(entry.Entity, this);
var transform = entity.Transform;
var rigidbody = entry.Component;
b2Body* body = rigidbody.RuntimeBody;
b2Vec2 position = Box2D.Body.GetPosition(body);
float angle = Box2D.Body.GetAngle(body);
transform.Position = .(position.x, position.y, transform.Position.Z);
transform.RotationEuler = .(transform.RotationEuler.XY, angle);
}
}
// 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;
// TODO: bind render targets to cameras
// renderTarget = camera.RenderTarget..AddRef();
}
}
renderTarget = _cameraTarget..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, SpriteRendererComponent>())
{
Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index);
}
for (var (entity, transform, circle) in _ecsWorld.Enumerate<TransformComponent, CircleRendererComponent>())
{
Renderer2D.DrawCircle(transform.WorldTransform, circle, entity.Index);
}
Renderer2D.EndScene();
// Gamma correct composit target and draw it into viewport
{
RenderCommand.UnbindRenderTargets();
RenderCommand.SetRenderTargetGroup(finalTarget, false);
RenderCommand.BindRenderTargets();
Effect gammaEffect = Content.GetAsset<Effect>(_gammaCorrectEffect);
gammaEffect.SetTexture("Texture", _compositeTarget, 0);
// TODO: iiihhh
gammaEffect.ApplyChanges();
gammaEffect.Bind();
FullscreenQuad.Draw();
}
finalTarget.ReleaseRef();
} }
public void UpdateEditor(GameTime gameTime, EditorCamera camera, RenderTargetGroup viewportTarget, delegate void() DebugDraw3D, delegate void() DrawDebug2D) public void Update(GameTime gameTime, UpdateMode mode)
{ {
Debug.Profiler.ProfileRendererFunction!(); Debug.Profiler.ProfileRendererFunction!();
viewportTarget.AddRef();
TransformSystem.Update(_ecsWorld); TransformSystem.Update(_ecsWorld);
// 3D render if (mode.HasFlag(.Runtime))
Renderer.BeginScene(camera, _compositeTarget);
for (var (entity, transform, mesh, meshRenderer) in _ecsWorld.Enumerate<TransformComponent, MeshComponent, MeshRendererComponent>())
{ {
if (mesh.Mesh == .Invalid || meshRenderer.Material == .Invalid) // Run scripts
continue; for (var (entity, script) in _ecsWorld.Enumerate<NativeScriptComponent>())
{
Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform); if (script.Instance == null)
} {
script.Instance = script.InstantiateFunction();
for (var (entity, transform, light) in _ecsWorld.Enumerate<TransformComponent, LightComponent>()) script.Instance._entity = Entity(entity, this);
{ script.Instance.[Friend]OnCreate();
Renderer.Submit(light.SceneLight, transform.WorldTransform); }
}
DebugDraw3D();
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(camera, .BackToFront);
for (var (entity, transform, sprite) in _ecsWorld.Enumerate<TransformComponent, SpriteRendererComponent>())
{
Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index);
}
for (var (entity, transform, circle) in _ecsWorld.Enumerate<TransformComponent, CircleRendererComponent>())
{
Renderer2D.DrawCircle(transform.WorldTransform, circle, entity.Index);
}
Renderer2D.DrawLine(Vector3.Zero, Vector3.Up, .Red);
Renderer2D.DrawLine(Vector3.Zero, Vector3(0, 0, 1), .Green);
Renderer2D.DrawRay(Vector3.Zero, Vector3(1, 0, 0), .Blue);
Renderer2D.DrawRect(Vector2(2.0f, 1.0f), Vector2(1.0f, 2.0f), .Yellow);
Renderer2D.DrawRect(Matrix.Translation(2, 2, 1) * Matrix.RotationZ(MathHelper.PiOverFour), .Purple);
Renderer2D.EndScene();
Renderer2D.BeginScene(camera, .BackToFront);
DrawDebug2D();
Renderer2D.EndScene();
// Gamma correct composit target and draw it into viewport
{
RenderCommand.UnbindRenderTargets();
RenderCommand.SetRenderTargetGroup(viewportTarget, false);
RenderCommand.BindRenderTargets();
Effect gammaEffect = Content.GetAsset<Effect>(_gammaCorrectEffect);
gammaEffect.SetTexture("Texture", _compositeTarget, 0);
// TODO: iiihhh
gammaEffect.ApplyChanges();
gammaEffect.Bind();
FullscreenQuad.Draw(); script.Instance.[Friend]OnUpdate(gameTime);
}
} }
if (mode.HasFlag(.Physics))
{
// Update 2D physics
{
const int32 velocityIterations = 6;
const int32 positionIterations = 2;
const int32 particleIterations = 2;
viewportTarget.ReleaseRef(); Box2D.World.Step(_physicsWorld2D, gameTime.DeltaTime, velocityIterations, positionIterations, particleIterations);
// Retrieve transform from Box2D
for (var entry in _ecsWorld.Enumerate<Rigidbody2DComponent>())
{
Entity entity = .(entry.Entity, this);
var transform = entity.Transform;
var rigidbody = entry.Component;
b2Body* body = rigidbody.RuntimeBody;
b2Vec2 position = Box2D.Body.GetPosition(body);
float angle = Box2D.Body.GetAngle(body);
transform.Position = .(position.x, position.y, transform.Position.Z);
transform.RotationEuler = .(transform.RotationEuler.XY, angle);
}
}
}
} }
/// Creates a new Entity with the given name. /// Creates a new Entity with the given name.
@@ -479,9 +308,6 @@ namespace GlitchyEngine.World
cameraComponent.Camera.SetViewportSize(width, height); cameraComponent.Camera.SetViewportSize(width, height);
} }
} }
_compositeTarget.Resize(_viewportWidth, _viewportHeight);
_cameraTarget.Resize(_viewportWidth, _viewportHeight);
} }
private void OnComponentAdded(Entity entity, Type componentType, void* component) private void OnComponentAdded(Entity entity, Type componentType, void* component)
+220
View File
@@ -0,0 +1,220 @@
using GlitchyEngine.Renderer;
using GlitchyEngine.Content;
using GlitchyEngine.Math;
namespace GlitchyEngine.World;
using internal GlitchyEngine.World;
class SceneRenderer
{
public Scene Scene { get; set; }
private RenderTargetGroup _compositeTarget ~ _.ReleaseRef();
// Temporary target for camera. Needs to change as soon as we support multiple cameras
private RenderTargetGroup _cameraTarget ~ _.ReleaseRef();
private uint32 _viewportWidth;
private uint32 _viewportHeight;
private AssetHandle _gammaCorrectEffect;
public RenderTargetGroup CompositeTarget => _compositeTarget;
public this()
{
RenderTargetGroupDescription desc = .(100, 100,
TargetDescription[](
RenderTargetFormat.R16G16B16A16_Float,
.(RenderTargetFormat.R32_UInt) {ClearColor = .UInt(uint32.MaxValue)}),
RenderTargetFormat.D24_UNorm_S8_UInt);
_compositeTarget = new RenderTargetGroup(desc);
_cameraTarget = new RenderTargetGroup(.(){
Width = 100,
Height = 100,
ColorTargetDescriptions = TargetDescription[](
.(.R16G16B16A16_Float),
.(.R32_UInt)
),
DepthTargetDescription = .(.D24_UNorm_S8_UInt)
});
_gammaCorrectEffect = Content.LoadAsset("Shaders/GammaCorrect.hlsl");//Application.Get().EffectLibrary.Load("content/Shaders/GammaCorrect.hlsl");
}
/// Sets the size of the viewport into which the scene will be rendered.
public void OnViewportResize(uint32 width, uint32 height)
{
_viewportWidth = width;
_viewportHeight = height;
_compositeTarget.Resize(_viewportWidth, _viewportHeight);
_cameraTarget.Resize(_viewportWidth, _viewportHeight);
}
public void RenderRuntime(GameTime gameTime, RenderTargetGroup finalTarget)
{
Debug.Profiler.ProfileRendererFunction!();
// Find camera
Camera* primaryCamera = null;
Matrix primaryCameraTransform = default;
RenderTargetGroup renderTarget = null;
for (var (entity, transform, camera) in Scene._ecsWorld.Enumerate<TransformComponent, CameraComponent>())
{
if (camera.Primary)// && camera.RenderTarget != null)
{
primaryCamera = &camera.Camera;
primaryCameraTransform = transform.WorldTransform;
// TODO: bind render targets to cameras
// renderTarget = camera.RenderTarget..AddRef();
}
}
if (primaryCamera == null)
return;
finalTarget.AddRef();
renderTarget = _cameraTarget..AddRef();
// 3D render
Renderer.BeginScene(*primaryCamera, primaryCameraTransform, renderTarget, _compositeTarget);
for (var (entity, transform, mesh, meshRenderer) in Scene._ecsWorld.Enumerate<TransformComponent, MeshComponent, MeshRendererComponent>())
{
Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform);
}
for (var (entity, transform, light) in Scene._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 Scene._ecsWorld.Enumerate<TransformComponent, SpriteRendererComponent>())
{
Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index);
}
for (var (entity, transform, circle) in Scene._ecsWorld.Enumerate<TransformComponent, CircleRendererComponent>())
{
Renderer2D.DrawCircle(transform.WorldTransform, circle, entity.Index);
}
Renderer2D.EndScene();
// Gamma correct composit target and draw it into viewport
{
RenderCommand.UnbindRenderTargets();
RenderCommand.SetRenderTargetGroup(finalTarget, false);
RenderCommand.BindRenderTargets();
Effect gammaEffect = Content.GetAsset<Effect>(_gammaCorrectEffect);
gammaEffect.SetTexture("Texture", _compositeTarget, 0);
// TODO: iiihhh
gammaEffect.ApplyChanges();
gammaEffect.Bind();
FullscreenQuad.Draw();
}
finalTarget.ReleaseRef();
}
public void RenderEditor(GameTime gameTime, EditorCamera camera, RenderTargetGroup viewportTarget, delegate void() DebugDraw3D, delegate void() DrawDebug2D)
{
Debug.Profiler.ProfileRendererFunction!();
viewportTarget.AddRef();
// 3D render
Renderer.BeginScene(camera, _compositeTarget);
for (var (entity, transform, mesh, meshRenderer) in Scene._ecsWorld.Enumerate<TransformComponent, MeshComponent, MeshRendererComponent>())
{
if (mesh.Mesh == .Invalid || meshRenderer.Material == .Invalid)
continue;
Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform);
}
for (var (entity, transform, light) in Scene._ecsWorld.Enumerate<TransformComponent, LightComponent>())
{
Renderer.Submit(light.SceneLight, transform.WorldTransform);
}
DebugDraw3D();
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(camera, .BackToFront);
for (var (entity, transform, sprite) in Scene._ecsWorld.Enumerate<TransformComponent, SpriteRendererComponent>())
{
Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index);
}
for (var (entity, transform, circle) in Scene._ecsWorld.Enumerate<TransformComponent, CircleRendererComponent>())
{
Renderer2D.DrawCircle(transform.WorldTransform, circle, entity.Index);
}
Renderer2D.DrawLine(Vector3.Zero, Vector3.Up, .Red);
Renderer2D.DrawLine(Vector3.Zero, Vector3(0, 0, 1), .Green);
Renderer2D.DrawRay(Vector3.Zero, Vector3(1, 0, 0), .Blue);
Renderer2D.DrawRect(Vector2(2.0f, 1.0f), Vector2(1.0f, 2.0f), .Yellow);
Renderer2D.DrawRect(Matrix.Translation(2, 2, 1) * Matrix.RotationZ(MathHelper.PiOverFour), .Purple);
Renderer2D.EndScene();
Renderer2D.BeginScene(camera, .BackToFront);
DrawDebug2D();
Renderer2D.EndScene();
// Gamma correct composit target and draw it into viewport
{
RenderCommand.UnbindRenderTargets();
RenderCommand.SetRenderTargetGroup(viewportTarget, false);
RenderCommand.BindRenderTargets();
Effect gammaEffect = Content.GetAsset<Effect>(_gammaCorrectEffect);
gammaEffect.SetTexture("Texture", _compositeTarget, 0);
// TODO: iiihhh
gammaEffect.ApplyChanges();
gammaEffect.Bind();
FullscreenQuad.Draw();
}
viewportTarget.ReleaseRef();
}
}