mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Start of serializaation
- Allow enumerating over unregistered components - Refactored Editor a bit
This commit is contained in:
@@ -30,6 +30,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
public void SetContext(Scene scene)
|
public void SetContext(Scene scene)
|
||||||
{
|
{
|
||||||
|
_selectedEntities.Clear();
|
||||||
_scene = scene;
|
_scene = scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ namespace GlitchyEditor.EditWindows
|
|||||||
{
|
{
|
||||||
class SceneViewportWindow : EditorWindow
|
class SceneViewportWindow : EditorWindow
|
||||||
{
|
{
|
||||||
//public OldCamera _camera;
|
|
||||||
|
|
||||||
public const String s_WindowTitle = "Scene";
|
public const String s_WindowTitle = "Scene";
|
||||||
|
|
||||||
private RenderTarget2D _renderTarget ~ _?.ReleaseRef();
|
private RenderTarget2D _renderTarget ~ _?.ReleaseRef();
|
||||||
@@ -38,8 +36,6 @@ namespace GlitchyEditor.EditWindows
|
|||||||
private ImGui.Vec2 oldViewportSize;
|
private ImGui.Vec2 oldViewportSize;
|
||||||
private bool viewPortChanged;
|
private bool viewPortChanged;
|
||||||
|
|
||||||
public Entity CameraEntity { get; set; }
|
|
||||||
|
|
||||||
protected override void InternalShow()
|
protected override void InternalShow()
|
||||||
{
|
{
|
||||||
ImGui.PushStyleVar(.WindowPadding, ImGui.Vec2(1, 1));
|
ImGui.PushStyleVar(.WindowPadding, ImGui.Vec2(1, 1));
|
||||||
@@ -89,20 +85,20 @@ namespace GlitchyEditor.EditWindows
|
|||||||
topLeft.y += cntMin.y;
|
topLeft.y += cntMin.y;
|
||||||
ImGuizmo.SetRect(topLeft.x, topLeft.y, viewportSize.x, viewportSize.y);
|
ImGuizmo.SetRect(topLeft.x, topLeft.y, viewportSize.x, viewportSize.y);
|
||||||
|
|
||||||
var cameraTransformCmp = CameraEntity.GetComponent<TransformComponent>();
|
var cameraTransformCmp = _editor.CurrentCamera.GetComponent<TransformComponent>();
|
||||||
var view = cameraTransformCmp.WorldTransform.Invert();
|
var view = cameraTransformCmp.WorldTransform.Invert();
|
||||||
|
|
||||||
var cameraCmp = CameraEntity.GetComponent<CameraComponent>();
|
var cameraCmp = _editor.CurrentCamera.GetComponent<CameraComponent>();
|
||||||
var projection = cameraCmp.Camera.Projection;
|
var projection = cameraCmp.Camera.Projection;
|
||||||
|
|
||||||
Matrix mat = .Identity;
|
Matrix mat = .Identity;
|
||||||
ImGuizmo.DrawGrid((.)&view, (.)&projection, (.)&mat, 10);
|
ImGuizmo.DrawGrid((.)&view, (.)&projection, (.)&mat, 10);
|
||||||
|
|
||||||
if(_editor.SelectedEntities.Count > 0)
|
if(_editor.EntityHierarchyWindow.SelectedEntities.Count > 0)
|
||||||
{
|
{
|
||||||
var entity = _editor.SelectedEntities.Front;
|
var entity = _editor.EntityHierarchyWindow.SelectedEntities.Front;
|
||||||
|
|
||||||
var transformCmp = _editor.World.GetComponent<TransformComponent>(entity);
|
var transformCmp = entity.GetComponent<TransformComponent>();
|
||||||
|
|
||||||
var transform = transformCmp.LocalTransform;
|
var transform = transformCmp.LocalTransform;
|
||||||
|
|
||||||
|
|||||||
+29
-77
@@ -4,115 +4,67 @@ using System;
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using GlitchyEngine.Collections;
|
using GlitchyEngine.Collections;
|
||||||
using GlitchyEditor.EditWindows;
|
using GlitchyEditor.EditWindows;
|
||||||
|
using GlitchyEngine;
|
||||||
|
|
||||||
namespace GlitchyEditor
|
namespace GlitchyEditor
|
||||||
{
|
{
|
||||||
class Editor
|
class Editor
|
||||||
{
|
{
|
||||||
private EcsWorld _ecsWorld;
|
|
||||||
private Scene _scene;
|
private Scene _scene;
|
||||||
|
private Entity _currentCamera;
|
||||||
|
|
||||||
private EntityHierarchyWindow _entityHierarchyWindow ~ delete _;
|
private EntityHierarchyWindow _entityHierarchyWindow ~ delete _;
|
||||||
private ComponentEditWindow _componentEditWindow ~ delete _;
|
private ComponentEditWindow _componentEditWindow ~ delete _;
|
||||||
private SceneViewportWindow _sceneViewportWindow = new .(this) ~ delete _;
|
private SceneViewportWindow _sceneViewportWindow = new .(this) ~ delete _;
|
||||||
|
|
||||||
private List<EcsEntity> _selectedEntities = new .() ~ delete _;
|
|
||||||
|
|
||||||
public EcsWorld World => _ecsWorld;
|
|
||||||
|
|
||||||
public List<EcsEntity> SelectedEntities => _selectedEntities;
|
|
||||||
|
|
||||||
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 Scene CurrentScene
|
||||||
|
{
|
||||||
|
get => _scene;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_scene = value;
|
||||||
|
_entityHierarchyWindow.SetContext(_scene);
|
||||||
|
FindCurrentEditorCamera();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entity CurrentCamera => _currentCamera;
|
||||||
|
|
||||||
/// Creates a new editor for the given world
|
/// Creates a new editor for the given world
|
||||||
public this(Scene scene)
|
public this(Scene scene)
|
||||||
{
|
{
|
||||||
_scene = scene;
|
|
||||||
_ecsWorld = _scene.[Friend]_ecsWorld;
|
|
||||||
|
|
||||||
_entityHierarchyWindow = new EntityHierarchyWindow(_scene);
|
_entityHierarchyWindow = new EntityHierarchyWindow(_scene);
|
||||||
|
CurrentScene = scene;
|
||||||
|
|
||||||
_componentEditWindow = new ComponentEditWindow(_entityHierarchyWindow);
|
_componentEditWindow = new ComponentEditWindow(_entityHierarchyWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
|
var scriptComponent = CurrentCamera.GetComponent<NativeScriptComponent>();
|
||||||
|
|
||||||
|
if (var camController = scriptComponent?.Instance as EditorCameraController)
|
||||||
|
{
|
||||||
|
camController.IsEnabled = (SceneViewportWindow.HasFocus && Input.IsMouseButtonPressed(.RightButton));
|
||||||
|
}
|
||||||
|
|
||||||
_entityHierarchyWindow.Show();
|
_entityHierarchyWindow.Show();
|
||||||
_componentEditWindow.Show();
|
_componentEditWindow.Show();
|
||||||
_sceneViewportWindow.Show();
|
_sceneViewportWindow.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new entity with a transform component.
|
private void FindCurrentEditorCamera()
|
||||||
internal EcsEntity CreateEntityWithTransform()
|
|
||||||
{
|
{
|
||||||
var entity = _ecsWorld.NewEntity();
|
_currentCamera = .(.InvalidEntity, _scene);
|
||||||
|
// TODO: a bit sketchy
|
||||||
var transformComponent = ref *_ecsWorld.AssignComponent<TransformComponent>(entity);
|
for (var (entity, editComp, cam) in _scene.[Friend]_ecsWorld.Enumerate<EditorComponent, CameraComponent>())
|
||||||
transformComponent = TransformComponent();
|
|
||||||
|
|
||||||
var nameComponent = ref *_ecsWorld.AssignComponent<DebugNameComponent>(entity);
|
|
||||||
nameComponent.SetName("Entity");
|
|
||||||
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Returns whether or not all selected entities have the same parent.
|
|
||||||
internal bool AllSelectionsOnSameLevel()
|
|
||||||
{
|
{
|
||||||
EcsEntity? parent = .InvalidEntity;
|
_currentCamera = .(entity, CurrentScene);
|
||||||
|
|
||||||
for(var selectedEntity in _selectedEntities)
|
|
||||||
{
|
|
||||||
var parentComponent = _ecsWorld.GetComponent<ParentComponent>(selectedEntity);
|
|
||||||
|
|
||||||
if(parent == .InvalidEntity)
|
|
||||||
{
|
|
||||||
parent = parentComponent?.Entity;
|
|
||||||
}
|
|
||||||
else if(parentComponent?.Entity != parent)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Finds all children of the given entity and stores their IDs in the given list.
|
|
||||||
internal void FindChildren(EcsEntity entity, List<EcsEntity> entities)
|
|
||||||
{
|
|
||||||
for(var (child, childParent) in _ecsWorld.Enumerate<ParentComponent>())
|
|
||||||
{
|
|
||||||
if(childParent.Entity == entity)
|
|
||||||
{
|
|
||||||
if(!entities.Contains(child))
|
|
||||||
entities.Add(child);
|
|
||||||
|
|
||||||
FindChildren(child, entities);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes all selected entities and their children.
|
|
||||||
internal void DeleteSelectedEntities()
|
|
||||||
{
|
|
||||||
List<EcsEntity> entities = scope .();
|
|
||||||
|
|
||||||
for(var entity in _selectedEntities)
|
|
||||||
{
|
|
||||||
entities.Add(entity);
|
|
||||||
|
|
||||||
FindChildren(entity, entities);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(var entity in entities)
|
|
||||||
{
|
|
||||||
_ecsWorld.RemoveEntity(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
_selectedEntities.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+236
-131
@@ -10,6 +10,7 @@ using GlitchyEngine.World;
|
|||||||
using GlitchyEngine.Content;
|
using GlitchyEngine.Content;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using GlitchyEngine.Renderer.Animation;
|
using GlitchyEngine.Renderer.Animation;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace GlitchyEditor
|
namespace GlitchyEditor
|
||||||
{
|
{
|
||||||
@@ -25,6 +26,19 @@ namespace GlitchyEditor
|
|||||||
DepthStencilState _depthStencilState ~ _.ReleaseRef();
|
DepthStencilState _depthStencilState ~ _.ReleaseRef();
|
||||||
|
|
||||||
Scene _scene = new Scene() ~ delete _;
|
Scene _scene = new Scene() ~ delete _;
|
||||||
|
String _sceneFilePath = new String() ~ delete _;
|
||||||
|
|
||||||
|
public String SceneFilePath
|
||||||
|
{
|
||||||
|
get => _sceneFilePath;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_sceneFilePath.Clear();
|
||||||
|
|
||||||
|
if (value != null)
|
||||||
|
_sceneFilePath.Append(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Editor _editor ~ delete _;
|
Editor _editor ~ delete _;
|
||||||
|
|
||||||
@@ -81,48 +95,112 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
InitGraphics();
|
InitGraphics();
|
||||||
|
|
||||||
{
|
NewScene();
|
||||||
_cameraEntity = _scene.CreateEntity("Camera Entity");
|
|
||||||
let camera = _cameraEntity.AddComponent<CameraComponent>();
|
|
||||||
camera.Camera.SetPerspective(MathHelper.ToRadians(75), 0.1f, 10000.0f);
|
|
||||||
camera.Primary = true;
|
|
||||||
camera.FixedAspectRatio = false;
|
|
||||||
camera.RenderTarget = _cameraTarget;
|
|
||||||
let transform = _cameraEntity.GetComponent<TransformComponent>();
|
|
||||||
//transform.Position = .(-1.5f, 1.5f, -2.5f);
|
|
||||||
transform.Position = .(3.5f, 1.25f, 2.75f);
|
|
||||||
//transform.RotationEuler = .(MathHelper.ToRadians(25), MathHelper.ToRadians(35), 0);
|
|
||||||
transform.RotationEuler = .(MathHelper.ToRadians(25), MathHelper.ToRadians(40), 0);
|
|
||||||
|
|
||||||
_cameraEntity.AddComponent<NativeScriptComponent>().Bind<EditorCameraController>();
|
InitEditor();
|
||||||
_cameraEntity.AddComponent<EditorComponent>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*{
|
private void InitGraphics()
|
||||||
_otherCameraEntity = _scene.CreateEntity("Other Camera Entity");
|
|
||||||
let camera = _otherCameraEntity.AddComponent<CameraComponent>();
|
|
||||||
camera.Camera.SetPerspective(MathHelper.ToRadians(45), 0.1f, 1000.0f);
|
|
||||||
camera.Primary = false;
|
|
||||||
camera.FixedAspectRatio = false;
|
|
||||||
camera.RenderTarget = _viewportTarget;
|
|
||||||
let transform = _otherCameraEntity.GetComponent<TransformComponent>();
|
|
||||||
transform.Position = .(0, 0, -5);
|
|
||||||
|
|
||||||
_otherCameraEntity.AddComponent<NativeScriptComponent>().Bind<EditorCameraController>();
|
|
||||||
_otherCameraEntity.AddComponent<EditorComponent>();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
{
|
{
|
||||||
var lightNtt = _scene.CreateEntity("My Sexy Sun");
|
_context = Application.Get().Window.Context..AddRef();
|
||||||
let transform = lightNtt.GetComponent<TransformComponent>();
|
|
||||||
transform.Position = .(0, 0, 0);
|
|
||||||
transform.RotationEuler = .(MathHelper.ToRadians(45), MathHelper.ToRadians(-100), 0);
|
|
||||||
|
|
||||||
let light = lightNtt.AddComponent<LightComponent>();
|
RasterizerStateDescription rsDesc = .(.Solid, .Back, true);
|
||||||
light.SceneLight.Illuminance = 10.0f;
|
_rasterizerState = new RasterizerState(rsDesc);
|
||||||
light.SceneLight.Color = .(1.0f, 0.95f, 0.8f);
|
|
||||||
|
rsDesc.FrontCounterClockwise = false;
|
||||||
|
_rasterizerStateClockWise = new RasterizerState(rsDesc);
|
||||||
|
|
||||||
|
BlendStateDescription blendDesc = .();
|
||||||
|
blendDesc.RenderTarget[0] = .(true, .SourceAlpha, .InvertedSourceAlpha, .Add, .SourceAlpha, .InvertedSourceAlpha, .Add, .All);
|
||||||
|
_alphaBlendState = new BlendState(blendDesc);
|
||||||
|
_opaqueBlendState = new BlendState(.Default);
|
||||||
|
|
||||||
|
DepthStencilStateDescription dsDesc = .();
|
||||||
|
_depthStencilState = new DepthStencilState(dsDesc);
|
||||||
|
|
||||||
|
_cameraTarget = new RenderTarget2D(RenderTarget2DDescription(.R16G16B16A16_Float, 100, 100) {DepthStencilFormat = .D32_Float});
|
||||||
|
_cameraTarget.SamplerState = SamplerStateManager.LinearClamp;
|
||||||
|
|
||||||
|
_viewportTarget = new RenderTarget2D(RenderTarget2DDescription(.R8G8B8A8_UNorm, 100, 100));
|
||||||
|
_viewportTarget.SamplerState = SamplerStateManager.LinearClamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitEditor()
|
||||||
|
{
|
||||||
|
_editor = new Editor(_scene);
|
||||||
|
_editor.SceneViewportWindow.ViewportSizeChangedEvent.Add(new (s, e) => ViewportSizeChanged(s, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(GameTime gameTime)
|
||||||
|
{
|
||||||
|
// Clear the swapchain-buffer
|
||||||
|
RenderCommand.Clear(null, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
|
||||||
|
|
||||||
|
RenderCommand.Clear(_viewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
|
||||||
|
|
||||||
|
RenderCommand.SetRenderTarget(_viewportTarget, 0, true);
|
||||||
|
RenderCommand.BindRenderTargets();
|
||||||
|
|
||||||
|
RenderCommand.SetViewport(Viewport(0, 0, _viewportTarget.Width, _viewportTarget.Height));
|
||||||
|
|
||||||
|
RenderCommand.SetBlendState(_alphaBlendState);
|
||||||
|
RenderCommand.SetDepthStencilState(_depthStencilState);
|
||||||
|
|
||||||
|
_scene.Update(gameTime, _viewportTarget);
|
||||||
|
|
||||||
|
RenderCommand.UnbindRenderTargets();
|
||||||
|
RenderCommand.SetRenderTarget(null, 0, true);
|
||||||
|
RenderCommand.BindRenderTargets();
|
||||||
|
|
||||||
|
RenderCommand.SetViewport(_context.SwapChain.BackbufferViewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnEvent(Event event)
|
||||||
|
{
|
||||||
|
EventDispatcher dispatcher = EventDispatcher(event);
|
||||||
|
|
||||||
|
dispatcher.Dispatch<ImGuiRenderEvent>(scope (e) => OnImGuiRender(e));
|
||||||
|
dispatcher.Dispatch<WindowResizeEvent>(scope (e) => OnWindowResize(e));
|
||||||
|
dispatcher.Dispatch<KeyPressedEvent>(scope (e) => OnKeyPressed(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.ID _mainDockspaceId;
|
||||||
|
|
||||||
|
TextureViewer viewer = new TextureViewer() ~ delete _;
|
||||||
|
|
||||||
|
private bool OnImGuiRender(ImGuiRenderEvent event)
|
||||||
|
{
|
||||||
|
viewer.ViewTexture(_cameraTarget);
|
||||||
|
|
||||||
|
/*ImGui.Begin("Test");
|
||||||
|
|
||||||
|
static bool cameraA = true;
|
||||||
|
|
||||||
|
if (ImGui.Checkbox("Camera A", &cameraA))
|
||||||
|
{
|
||||||
|
_cameraEntity.GetComponent<CameraComponent>().Primary = cameraA;
|
||||||
|
_otherCameraEntity.GetComponent<CameraComponent>().Primary = !cameraA;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.End();*/
|
||||||
|
|
||||||
|
ImGui.Viewport* viewport = ImGui.GetMainViewport();
|
||||||
|
ImGui.DockSpaceOverViewport(viewport);
|
||||||
|
|
||||||
|
DrawMainMenuBar();
|
||||||
|
|
||||||
|
_editor.SceneViewportWindow.RenderTarget = _viewportTarget;
|
||||||
|
|
||||||
|
_editor.Update();
|
||||||
|
|
||||||
|
_settingsWindow.Show();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just for testing
|
||||||
|
private void TestEntitiesWithModels()
|
||||||
|
{
|
||||||
{
|
{
|
||||||
var lightNtt = _scene.CreateEntity("My Sexy Sun 2");
|
var lightNtt = _scene.CreateEntity("My Sexy Sun 2");
|
||||||
let transform = lightNtt.GetComponent<TransformComponent>();
|
let transform = lightNtt.GetComponent<TransformComponent>();
|
||||||
@@ -145,20 +223,17 @@ namespace GlitchyEditor
|
|||||||
light.SceneLight.Color = .(1.0f, 0.95f, 0.8f);
|
light.SceneLight.Color = .(1.0f, 0.95f, 0.8f);
|
||||||
}
|
}
|
||||||
|
|
||||||
InitEditor();
|
|
||||||
|
|
||||||
TestEntitiesWithModels();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TestEntitiesWithModels()
|
|
||||||
{
|
|
||||||
var fxLib = Application.Get().EffectLibrary;
|
var fxLib = Application.Get().EffectLibrary;
|
||||||
|
|
||||||
using (Effect myEffect = fxLib.Load("content/Shaders/myEffect.hlsl"))
|
using (Effect myEffect = fxLib.Load("content/Shaders/myEffect.hlsl"))
|
||||||
using (Texture2D albedo = new Texture2D("Textures/TestMat/rustediron2_albedo.png", true))
|
using (Texture2D albedo = new Texture2D("Textures/White.png", true))
|
||||||
|
using (Texture2D normal = new Texture2D("Textures/White.png"))
|
||||||
|
using (Texture2D rough = new Texture2D("Textures/White.png"))
|
||||||
|
using (Texture2D metal = new Texture2D("Textures/White.png"))
|
||||||
|
/*using (Texture2D albedo = new Texture2D("Textures/TestMat/rustediron2_albedo.png", true))
|
||||||
using (Texture2D normal = new Texture2D("Textures/TestMat/rustediron2_normal.png"))
|
using (Texture2D normal = new Texture2D("Textures/TestMat/rustediron2_normal.png"))
|
||||||
using (Texture2D rough = new Texture2D("Textures/TestMat/rustediron2_roughness.png"))
|
using (Texture2D rough = new Texture2D("Textures/TestMat/rustediron2_roughness.png"))
|
||||||
using (Texture2D metal = new Texture2D("Textures/TestMat/rustediron2_metallic.png"))
|
using (Texture2D metal = new Texture2D("Textures/TestMat/rustediron2_metallic.png"))*/
|
||||||
{
|
{
|
||||||
albedo.SamplerState = SamplerStateManager.AnisotropicWrap;
|
albedo.SamplerState = SamplerStateManager.AnisotropicWrap;
|
||||||
normal.SamplerState = SamplerStateManager.AnisotropicWrap;
|
normal.SamplerState = SamplerStateManager.AnisotropicWrap;
|
||||||
@@ -238,118 +313,100 @@ namespace GlitchyEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitGraphics()
|
private void PrepareSceneForEditor()
|
||||||
{
|
{
|
||||||
_context = Application.Get().Window.Context..AddRef();
|
// Create the editor camera
|
||||||
|
{
|
||||||
|
_cameraEntity = _scene.CreateEntity("Editor Camera");
|
||||||
|
// Add EditorComponent so that the engine knows that this is not part of the game.
|
||||||
|
_cameraEntity.AddComponent<EditorComponent>();
|
||||||
|
// Script for controlling the camera.
|
||||||
|
_cameraEntity.AddComponent<NativeScriptComponent>().Bind<EditorCameraController>();
|
||||||
|
|
||||||
RasterizerStateDescription rsDesc = .(.Solid, .Back, true);
|
let camera = _cameraEntity.AddComponent<CameraComponent>();
|
||||||
_rasterizerState = new RasterizerState(rsDesc);
|
camera.Camera.SetPerspective(MathHelper.ToRadians(75), 0.1f, 10000.0f);
|
||||||
|
camera.Primary = true;
|
||||||
|
camera.RenderTarget = _cameraTarget;
|
||||||
|
let transform = _cameraEntity.GetComponent<TransformComponent>();
|
||||||
|
//transform.Position = .(-1.5f, 1.5f, -2.5f);
|
||||||
|
transform.Position = .(3.5f, 1.25f, 2.75f);
|
||||||
|
//transform.RotationEuler = .(MathHelper.ToRadians(25), MathHelper.ToRadians(35), 0);
|
||||||
|
transform.RotationEuler = .(MathHelper.ToRadians(25), MathHelper.ToRadians(40), 0);
|
||||||
|
|
||||||
rsDesc.FrontCounterClockwise = false;
|
}
|
||||||
_rasterizerStateClockWise = new RasterizerState(rsDesc);
|
|
||||||
|
|
||||||
BlendStateDescription blendDesc = .();
|
|
||||||
blendDesc.RenderTarget[0] = .(true, .SourceAlpha, .InvertedSourceAlpha, .Add, .SourceAlpha, .InvertedSourceAlpha, .Add, .All);
|
|
||||||
_alphaBlendState = new BlendState(blendDesc);
|
|
||||||
_opaqueBlendState = new BlendState(.Default);
|
|
||||||
|
|
||||||
DepthStencilStateDescription dsDesc = .();
|
|
||||||
_depthStencilState = new DepthStencilState(dsDesc);
|
|
||||||
|
|
||||||
_cameraTarget = new RenderTarget2D(RenderTarget2DDescription(.R16G16B16A16_Float, 100, 100) {DepthStencilFormat = .D32_Float});
|
|
||||||
_cameraTarget.SamplerState = SamplerStateManager.LinearClamp;
|
|
||||||
|
|
||||||
_viewportTarget = new RenderTarget2D(RenderTarget2DDescription(.R8G8B8A8_UNorm, 100, 100));
|
|
||||||
_viewportTarget.SamplerState = SamplerStateManager.LinearClamp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitEditor()
|
/// Creates a new scene.
|
||||||
|
private void NewScene()
|
||||||
{
|
{
|
||||||
_editor = new Editor(_scene);
|
SceneFilePath = null;
|
||||||
_editor.SceneViewportWindow.ViewportSizeChangedEvent.Add(new (s, e) => ViewportSizeChanged(s, e));
|
|
||||||
|
|
||||||
//_editor.[Friend]CreateEntityWithTransform();
|
// Create the default light source
|
||||||
|
{
|
||||||
|
var lightNtt = _scene.CreateEntity("Light");
|
||||||
|
let transform = lightNtt.GetComponent<TransformComponent>();
|
||||||
|
transform.Position = .(0, 0, 0);
|
||||||
|
transform.RotationEuler = .(MathHelper.ToRadians(45), MathHelper.ToRadians(-100), 0);
|
||||||
|
|
||||||
_editor.SceneViewportWindow.CameraEntity = _cameraEntity;
|
let light = lightNtt.AddComponent<LightComponent>();
|
||||||
|
light.SceneLight.Illuminance = 10.0f;
|
||||||
|
light.SceneLight.Color = .(1.0f, 0.95f, 0.8f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(GameTime gameTime)
|
TestEntitiesWithModels();
|
||||||
{
|
|
||||||
var scriptComponent = _cameraEntity.GetComponent<NativeScriptComponent>();
|
|
||||||
|
|
||||||
if (var camController = scriptComponent.Instance as EditorCameraController)
|
PrepareSceneForEditor();
|
||||||
{
|
|
||||||
camController.IsEnabled = (_editor.SceneViewportWindow.HasFocus && Input.IsMouseButtonPressed(.RightButton));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TransformSystem.Update(_world);
|
/// Saves the scene in the file that is was loaded from or saved to last. If there is no such path (i.e. it is a new scene) the save file dialog will open.
|
||||||
|
private void SaveScene()
|
||||||
RenderCommand.Clear(_viewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
|
{
|
||||||
|
if (String.IsNullOrWhiteSpace(SceneFilePath))
|
||||||
RenderCommand.SetRenderTarget(_viewportTarget, 0, true);
|
{
|
||||||
RenderCommand.BindRenderTargets();
|
SaveSceneAs();
|
||||||
|
return;
|
||||||
RenderCommand.SetViewport(Viewport(0, 0, _viewportTarget.Width, _viewportTarget.Height));
|
|
||||||
|
|
||||||
RenderCommand.SetBlendState(_alphaBlendState);
|
|
||||||
RenderCommand.SetDepthStencilState(_depthStencilState);
|
|
||||||
|
|
||||||
//Renderer.BeginScene(_cameraController.Camera);
|
|
||||||
|
|
||||||
//DebugRenderer.Render(_scene.[Friend]_ecsWorld);
|
|
||||||
|
|
||||||
//Renderer.EndScene();
|
|
||||||
|
|
||||||
_scene.Update(gameTime, _viewportTarget);
|
|
||||||
|
|
||||||
RenderCommand.Clear(null, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
|
|
||||||
|
|
||||||
RenderCommand.SetRenderTarget(null, 0, true);
|
|
||||||
RenderCommand.BindRenderTargets();
|
|
||||||
|
|
||||||
RenderCommand.SetViewport(_context.SwapChain.BackbufferViewport);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnEvent(Event event)
|
SceneSerializer serializer = scope .(_scene);
|
||||||
{
|
serializer.Serialize(SceneFilePath);
|
||||||
EventDispatcher dispatcher = EventDispatcher(event);
|
|
||||||
|
|
||||||
dispatcher.Dispatch<ImGuiRenderEvent>(scope (e) => OnImGuiRender(e));
|
|
||||||
dispatcher.Dispatch<WindowResizeEvent>(scope (e) => OnWindowResize(e));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.ID _mainDockspaceId;
|
/// Opens a save file dialog and saves the scene at the user specified location.
|
||||||
|
private void SaveSceneAs()
|
||||||
TextureViewer viewer = new TextureViewer() ~ delete _;
|
|
||||||
|
|
||||||
private bool OnImGuiRender(ImGuiRenderEvent event)
|
|
||||||
{
|
{
|
||||||
viewer.ViewTexture(_cameraTarget);
|
SaveFileDialog sfd = scope .();
|
||||||
|
if (sfd.ShowDialog() case .Ok(let val))
|
||||||
/*ImGui.Begin("Test");
|
|
||||||
|
|
||||||
static bool cameraA = true;
|
|
||||||
|
|
||||||
if (ImGui.Checkbox("Camera A", &cameraA))
|
|
||||||
{
|
{
|
||||||
_cameraEntity.GetComponent<CameraComponent>().Primary = cameraA;
|
if (val == .OK)
|
||||||
_otherCameraEntity.GetComponent<CameraComponent>().Primary = !cameraA;
|
{
|
||||||
|
SceneFilePath = sfd.FileNames[0];
|
||||||
|
|
||||||
|
SaveScene();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.End();*/
|
/// Opens a open file dialog and load the scene selected by the user specified.
|
||||||
|
private void OpenScene()
|
||||||
|
{
|
||||||
|
OpenFileDialog ofd = scope .();
|
||||||
|
if (ofd.ShowDialog() case .Ok(let val))
|
||||||
|
{
|
||||||
|
if (val == .OK)
|
||||||
|
{
|
||||||
|
SceneFilePath = ofd.FileNames[0];
|
||||||
|
|
||||||
ImGui.Viewport* viewport = ImGui.GetMainViewport();
|
delete _scene;
|
||||||
ImGui.DockSpaceOverViewport(viewport);
|
_scene = new Scene();
|
||||||
|
|
||||||
DrawMainMenuBar();
|
SceneSerializer serializer = scope .(_scene);
|
||||||
|
serializer.Deserialize(SceneFilePath);
|
||||||
|
|
||||||
_editor.SceneViewportWindow.RenderTarget = _viewportTarget;
|
PrepareSceneForEditor();
|
||||||
|
|
||||||
_editor.Update();
|
_editor.CurrentScene = _scene;
|
||||||
|
}
|
||||||
_settingsWindow.Show();
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawMainMenuBar()
|
private void DrawMainMenuBar()
|
||||||
@@ -358,9 +415,28 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
if(ImGui.BeginMenu("File", true))
|
if(ImGui.BeginMenu("File", true))
|
||||||
{
|
{
|
||||||
|
if (ImGui.MenuItem("New", "Ctrl+N"))
|
||||||
|
NewScene();
|
||||||
|
|
||||||
|
if (ImGui.MenuItem("Save", "Ctrl+S"))
|
||||||
|
SaveScene();
|
||||||
|
|
||||||
|
if (ImGui.MenuItem("Save as...", "Ctrl+Shift+N"))
|
||||||
|
SaveSceneAs();
|
||||||
|
|
||||||
|
if (ImGui.MenuItem("Open...", "Ctrl+O"))
|
||||||
|
OpenScene();
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
|
||||||
if (ImGui.MenuItem("Settings"))
|
if (ImGui.MenuItem("Settings"))
|
||||||
_settingsWindow.Open = true;
|
_settingsWindow.Open = true;
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
|
||||||
|
if (ImGui.MenuItem("Exit"))
|
||||||
|
Application.Get().Close();
|
||||||
|
|
||||||
ImGui.EndMenu();
|
ImGui.EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,5 +482,34 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
_scene.OnViewportResize(sizeX, sizeY);
|
_scene.OnViewportResize(sizeX, sizeY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool OnKeyPressed(KeyPressedEvent e)
|
||||||
|
{
|
||||||
|
bool control = Input.IsKeyPressed(Key.Control);
|
||||||
|
bool shift = Input.IsKeyPressed(Key.Shift);
|
||||||
|
|
||||||
|
if (control)
|
||||||
|
{
|
||||||
|
switch (e.KeyCode)
|
||||||
|
{
|
||||||
|
case .N:
|
||||||
|
NewScene();
|
||||||
|
return true;
|
||||||
|
case .O:
|
||||||
|
OpenScene();
|
||||||
|
return true;
|
||||||
|
case .S:
|
||||||
|
if (shift)
|
||||||
|
SaveSceneAs();
|
||||||
|
else
|
||||||
|
SaveScene();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,6 +167,12 @@ namespace GlitchyEngine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Closes the applcation.
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
_running = false;
|
||||||
|
}
|
||||||
|
|
||||||
public void PushLayer(Layer ownLayer)
|
public void PushLayer(Layer ownLayer)
|
||||||
{
|
{
|
||||||
Profiler.ProfileFunction!();
|
Profiler.ProfileFunction!();
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Bon.Integrated
|
||||||
|
{
|
||||||
|
extension Serialize
|
||||||
|
{
|
||||||
|
public static void Value<T>(BonWriter writer, StringView identifier, in T value, BonEnvironment env = gBonEnv)
|
||||||
|
{
|
||||||
|
writer.Identifier(identifier);
|
||||||
|
Serialize.Value(writer, ValueView(typeof(T), &value), env);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Value<T>(BonWriter writer, in T value, BonEnvironment env = gBonEnv)
|
||||||
|
{
|
||||||
|
Serialize.Value(writer, ValueView(typeof(T), &value), env);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Deserialize
|
||||||
|
{
|
||||||
|
public static Result<void> Value<T>(BonReader reader, StringView identifier, out T value, BonEnvironment env = gBonEnv)
|
||||||
|
{
|
||||||
|
value = ?;
|
||||||
|
|
||||||
|
if (Try!(reader.Identifier()) != identifier)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
return Deserialize.Value(reader, ValueView(typeof(T), &value), env);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result<void> Value<T>(BonReader reader, out T value, BonEnvironment env = gBonEnv)
|
||||||
|
{
|
||||||
|
value = ?;
|
||||||
|
return Deserialize.Value(reader, ValueView(typeof(T), &value), env);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
|
using Bon;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace GlitchyEngine.Math
|
namespace GlitchyEngine.Math
|
||||||
{
|
{
|
||||||
|
[BonTarget]
|
||||||
public struct Quaternion
|
public struct Quaternion
|
||||||
{
|
{
|
||||||
public const Quaternion Zero = .();
|
public const Quaternion Zero = .();
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
using Bon;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace GlitchyEngine.Math
|
namespace GlitchyEngine.Math
|
||||||
{
|
{
|
||||||
|
[BonTarget]
|
||||||
[SwizzleVector(2, "Vector")]
|
[SwizzleVector(2, "Vector")]
|
||||||
public struct Vector2
|
public struct Vector2
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
using Bon;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace GlitchyEngine.Math
|
namespace GlitchyEngine.Math
|
||||||
{
|
{
|
||||||
|
[BonTarget]
|
||||||
[SwizzleVector(3, "Vector")]
|
[SwizzleVector(3, "Vector")]
|
||||||
public struct Vector3
|
public struct Vector3
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
using Bon;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace GlitchyEngine.Math
|
namespace GlitchyEngine.Math
|
||||||
{
|
{
|
||||||
|
[BonTarget]
|
||||||
[SwizzleVector(4, "Vector")]
|
[SwizzleVector(4, "Vector")]
|
||||||
public struct Vector4
|
public struct Vector4
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#pragma warning disable 4204
|
#pragma warning disable 4204
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using Bon;
|
||||||
|
|
||||||
namespace GlitchyEngine.Math
|
namespace GlitchyEngine.Math
|
||||||
{
|
{
|
||||||
@@ -35,4 +36,16 @@ namespace GlitchyEngine.Math
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace DirectX
|
||||||
|
{
|
||||||
|
[BonTarget]
|
||||||
|
extension Color;
|
||||||
|
|
||||||
|
[BonTarget]
|
||||||
|
extension ColorRGB;
|
||||||
|
|
||||||
|
[BonTarget]
|
||||||
|
extension ColorRGBA;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
using System;
|
||||||
using GlitchyEngine.Math;
|
using GlitchyEngine.Math;
|
||||||
using GlitchyEngine.Renderer;
|
using GlitchyEngine.Renderer;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace GlitchyEngine.World
|
namespace GlitchyEngine.World
|
||||||
{
|
{
|
||||||
@@ -251,9 +251,8 @@ namespace GlitchyEngine.World
|
|||||||
|
|
||||||
struct CameraComponent : IDisposableComponent
|
struct CameraComponent : IDisposableComponent
|
||||||
{
|
{
|
||||||
public SceneCamera Camera;
|
public SceneCamera Camera = .();
|
||||||
public bool Primary = true; // Todo: probably move into scene
|
public bool Primary = true; // Todo: probably move into scene
|
||||||
public bool FixedAspectRatio = false;
|
|
||||||
private RenderTarget2D _renderTarget = null;
|
private RenderTarget2D _renderTarget = null;
|
||||||
|
|
||||||
public RenderTarget2D RenderTarget
|
public RenderTarget2D RenderTarget
|
||||||
@@ -265,11 +264,6 @@ namespace GlitchyEngine.World
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public this()
|
|
||||||
{
|
|
||||||
Camera = .();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_renderTarget?.ReleaseRef();
|
_renderTarget?.ReleaseRef();
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ namespace GlitchyEngine.World
|
|||||||
|
|
||||||
for (var (entity, transform, camera) in _ecsWorld.Enumerate<TransformComponent, CameraComponent>())
|
for (var (entity, transform, camera) in _ecsWorld.Enumerate<TransformComponent, CameraComponent>())
|
||||||
{
|
{
|
||||||
if (camera.Primary)
|
if (camera.Primary && camera.RenderTarget != null)
|
||||||
{
|
{
|
||||||
primaryCamera = &camera.Camera;
|
primaryCamera = &camera.Camera;
|
||||||
primaryCameraTransform = transform.WorldTransform;
|
primaryCameraTransform = transform.WorldTransform;
|
||||||
@@ -134,7 +134,7 @@ namespace GlitchyEngine.World
|
|||||||
|
|
||||||
for (var (entity, cameraComponent) in _ecsWorld.Enumerate<CameraComponent>())
|
for (var (entity, cameraComponent) in _ecsWorld.Enumerate<CameraComponent>())
|
||||||
{
|
{
|
||||||
if (!cameraComponent.FixedAspectRatio)
|
if (!cameraComponent.Camera.FixedAspectRatio)
|
||||||
{
|
{
|
||||||
cameraComponent.Camera.SetViewportSize(width, height);
|
cameraComponent.Camera.SetViewportSize(width, height);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,445 @@
|
|||||||
|
using Bon;
|
||||||
|
using Bon.Integrated;
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.IO;
|
||||||
|
using GlitchyEngine.Math;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.World
|
||||||
|
{
|
||||||
|
using internal GlitchyEngine.World;
|
||||||
|
|
||||||
|
class SceneSerializer
|
||||||
|
{
|
||||||
|
private Scene _scene;
|
||||||
|
|
||||||
|
public this(Scene scene)
|
||||||
|
{
|
||||||
|
_scene = scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Serialize(StringView filePath)
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
|
String buffer = scope String();
|
||||||
|
let writer = scope BonWriter(buffer, true);
|
||||||
|
Serialize.Start(writer);
|
||||||
|
|
||||||
|
gBonEnv.serializeFlags |= .IncludeDefault | .Verbose;
|
||||||
|
|
||||||
|
using (writer.ObjectBlock())
|
||||||
|
{
|
||||||
|
// TODO: Scene name goes here!
|
||||||
|
Serialize.Value(writer, "Name", "Scene name here pls!!!");
|
||||||
|
|
||||||
|
writer.Identifier("Entities");
|
||||||
|
|
||||||
|
using (writer.ArrayBlock())
|
||||||
|
{
|
||||||
|
for (EcsEntity e in _scene._ecsWorld.Enumerate())
|
||||||
|
{
|
||||||
|
Entity entity = .(e, _scene);
|
||||||
|
|
||||||
|
// TODO: also serialize object with EditorComponent (e.g. to save the location of the editor camera)
|
||||||
|
if (entity.HasComponent<EditorComponent>())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SerializeEntity(writer, entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.EntryEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
Serialize.End(writer);
|
||||||
|
|
||||||
|
String targetDirectory = Path.GetDirectoryPath(filePath, .. scope String());
|
||||||
|
Directory.CreateDirectory(targetDirectory);
|
||||||
|
|
||||||
|
File.WriteAllText(filePath, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SerializeEntity(BonWriter writer, Entity entity)
|
||||||
|
{
|
||||||
|
writer.EntryStart();
|
||||||
|
|
||||||
|
using (writer.ObjectBlock())
|
||||||
|
{
|
||||||
|
// TODO: Entity GUID goes here!
|
||||||
|
Serialize.Value(writer, "Id", entity.Handle.Index);
|
||||||
|
|
||||||
|
SerializeComponent<EditorComponent>(writer, entity, "EditorComponent", scope (component) => {});
|
||||||
|
|
||||||
|
SerializeComponent<DebugNameComponent>(writer, entity, "NameComponent", scope (component) =>
|
||||||
|
{
|
||||||
|
Serialize.Value(writer, "Name", component.DebugName);
|
||||||
|
});
|
||||||
|
|
||||||
|
SerializeComponent<SpriterRendererComponent>(writer, entity, "SpriterRendererComponent", scope (component) =>
|
||||||
|
{
|
||||||
|
// TODO: Texture
|
||||||
|
|
||||||
|
Serialize.Value(writer, "Color", component.Color);
|
||||||
|
});
|
||||||
|
|
||||||
|
SerializeComponent<TransformComponent>(writer, entity, "TransformComponent", scope (component) =>
|
||||||
|
{
|
||||||
|
// TODO: Use GUIDs
|
||||||
|
if (component.Parent != .InvalidEntity)
|
||||||
|
Serialize.Value(writer, "ParentId", component.Parent.Index);
|
||||||
|
|
||||||
|
Serialize.Value(writer, "Position", component.Position);
|
||||||
|
Serialize.Value(writer, "Rotation", component.Rotation);
|
||||||
|
Serialize.Value(writer, "Scale", component.Scale);
|
||||||
|
|
||||||
|
Serialize.Value(writer, "EditorEulerRotation", component.EditorRotationEuler);
|
||||||
|
});
|
||||||
|
|
||||||
|
SerializeComponent<CameraComponent>(writer, entity, "CameraComponent", scope (component) =>
|
||||||
|
{
|
||||||
|
SceneCamera camera = component.Camera;
|
||||||
|
|
||||||
|
Serialize.Value(writer, "Primary", component.Primary);
|
||||||
|
|
||||||
|
// TODO: Render target
|
||||||
|
|
||||||
|
Serialize.Value(writer, "ProjectionType", camera.ProjectionType);
|
||||||
|
|
||||||
|
Serialize.Value(writer, "PerspectiveFovY", camera.PerspectiveFovY);
|
||||||
|
Serialize.Value(writer, "PerspectiveNearPlane", camera.PerspectiveNearPlane);
|
||||||
|
Serialize.Value(writer, "PerspectiveFarPlane", camera.PerspectiveFarPlane);
|
||||||
|
Serialize.Value(writer, "OrthographicHeight", camera.OrthographicHeight);
|
||||||
|
Serialize.Value(writer, "OrthographicNearPlane", camera.OrthographicNearPlane);
|
||||||
|
Serialize.Value(writer, "OrthographicFarPlane", camera.OrthographicFarPlane);
|
||||||
|
Serialize.Value(writer, "AspectRatio", camera.AspectRatio);
|
||||||
|
Serialize.Value(writer, "FixedAspectRatio", camera.FixedAspectRatio);
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: native script component
|
||||||
|
|
||||||
|
SerializeComponent<LightComponent>(writer, entity, "LightComponent", scope (component) =>
|
||||||
|
{
|
||||||
|
SceneLight light = component.SceneLight;
|
||||||
|
|
||||||
|
Serialize.Value(writer, "LightType", light.LightType);
|
||||||
|
|
||||||
|
Serialize.Value(writer, "Illuminance", light.Illuminance);
|
||||||
|
|
||||||
|
Serialize.Value(writer, "Color", light.Color);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.EntryEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SerializeComponent<T>(BonWriter writer, Entity entity, String identifier, delegate void(T* component) serialize) where T : struct, new
|
||||||
|
{
|
||||||
|
if (!entity.HasComponent<T>())
|
||||||
|
return;
|
||||||
|
|
||||||
|
var component = entity.GetComponent<T>();
|
||||||
|
|
||||||
|
writer.Identifier(identifier);
|
||||||
|
|
||||||
|
using (writer.ObjectBlock())
|
||||||
|
{
|
||||||
|
serialize(component);
|
||||||
|
}
|
||||||
|
writer.EntryEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SerializeRuntime(StringView filePath)
|
||||||
|
{
|
||||||
|
Runtime.NotImplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<void> Deserialize(StringView filePath)
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
|
String buffer = scope String();
|
||||||
|
File.ReadAllText(filePath, buffer);
|
||||||
|
|
||||||
|
let reader = scope BonReader();
|
||||||
|
Try!(reader.Setup(buffer));
|
||||||
|
Try!(Deserialize.Start(reader));
|
||||||
|
|
||||||
|
Try!(reader.ObjectBlock());
|
||||||
|
|
||||||
|
// TODO: Scene name goes here!
|
||||||
|
String testName;
|
||||||
|
Deserialize.Value(reader, "Name", out testName);
|
||||||
|
delete testName;
|
||||||
|
|
||||||
|
Try!(reader.EntryEnd());
|
||||||
|
|
||||||
|
if (Try!(reader.Identifier()) != "Entities")
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
Try!(reader.ArrayBlock());
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
while (reader.ArrayHasMore())
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
{
|
||||||
|
Try!(reader.EntryEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
Try!(DeserializeEntity(reader));
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Try!(reader.ArrayBlockEnd());
|
||||||
|
|
||||||
|
Try!(reader.ObjectBlockEnd());
|
||||||
|
|
||||||
|
Try!(Deserialize.End(reader));
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result<void> DeserializeEntity(BonReader reader)
|
||||||
|
{
|
||||||
|
Try!(reader.ObjectBlock());
|
||||||
|
|
||||||
|
Entity entity = _scene.CreateEntity();
|
||||||
|
|
||||||
|
// TODO: GUID?
|
||||||
|
Deserialize.Value<uint32>(reader, "Id", let id);
|
||||||
|
|
||||||
|
while(reader.ObjectHasMore())
|
||||||
|
{
|
||||||
|
Try!(reader.EntryEnd());
|
||||||
|
|
||||||
|
StringView identifier = Try!(reader.Identifier());
|
||||||
|
|
||||||
|
switch(identifier)
|
||||||
|
{
|
||||||
|
case "EditorComponent":
|
||||||
|
Try!(DeserializeComponent<EditorComponent>(reader, entity, scope (component) => { return .Ok; }));
|
||||||
|
case "NameComponent":
|
||||||
|
Try!(DeserializeComponent<DebugNameComponent>(reader, entity, scope (component) =>
|
||||||
|
{
|
||||||
|
String name;
|
||||||
|
|
||||||
|
Deserialize.Value(reader, "Name", out name);
|
||||||
|
|
||||||
|
component.SetName(name);
|
||||||
|
|
||||||
|
delete name;
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}));
|
||||||
|
case "NameComponent":
|
||||||
|
Try!(DeserializeComponent<DebugNameComponent>(reader, entity, scope (component) =>
|
||||||
|
{
|
||||||
|
String name;
|
||||||
|
|
||||||
|
Deserialize.Value(reader, "Name", out name);
|
||||||
|
|
||||||
|
component.SetName(name);
|
||||||
|
|
||||||
|
delete name;
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}));
|
||||||
|
case "SpriterRendererComponent":
|
||||||
|
Try!(DeserializeComponent<SpriterRendererComponent>(reader, entity, scope (component) =>
|
||||||
|
{
|
||||||
|
// TODO: Texture
|
||||||
|
|
||||||
|
Try!(Deserialize.Value(reader, "Color", out component.Color));
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}));
|
||||||
|
case "TransformComponent":
|
||||||
|
Try!(DeserializeComponent<TransformComponent>(reader, entity, scope (component) =>
|
||||||
|
{
|
||||||
|
let nextId = Try!(reader.Identifier());
|
||||||
|
if (nextId == "ParentId")
|
||||||
|
{
|
||||||
|
// TODO: Use GUIDs
|
||||||
|
uint32 pId;
|
||||||
|
Deserialize.Value(reader, out pId);
|
||||||
|
reader.EntryEnd();
|
||||||
|
Deserialize.Value(reader, "Position", out component.[Friend]_position);
|
||||||
|
reader.EntryEnd();
|
||||||
|
}
|
||||||
|
else if (nextId == "Position")
|
||||||
|
{
|
||||||
|
Deserialize.Value(reader, out component.[Friend]_position);
|
||||||
|
reader.EntryEnd();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
Deserialize.Value(reader, "Rotation", out component.[Friend]_rotation);
|
||||||
|
reader.EntryEnd();
|
||||||
|
Deserialize.Value(reader, "Scale", out component.[Friend]_scale);
|
||||||
|
reader.EntryEnd();
|
||||||
|
|
||||||
|
Deserialize.Value(reader, "EditorEulerRotation", out component.[Friend]_editorRotationEuler);
|
||||||
|
|
||||||
|
component.IsDirty = true;
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}));
|
||||||
|
case "CameraComponent":
|
||||||
|
Try!(DeserializeComponent<CameraComponent>(reader, entity, scope (component) =>
|
||||||
|
{
|
||||||
|
SceneCamera camera = component.Camera;
|
||||||
|
|
||||||
|
Deserialize.Value(reader, "Primary", out component.Primary);
|
||||||
|
reader.EntryEnd();
|
||||||
|
|
||||||
|
// TODO: Render target
|
||||||
|
|
||||||
|
Deserialize.Value(reader, "ProjectionType", out camera.[Friend]_projectionType);
|
||||||
|
reader.EntryEnd();
|
||||||
|
|
||||||
|
Deserialize.Value(reader, "PerspectiveFovY", out camera.[Friend]_perspectiveFovY);
|
||||||
|
reader.EntryEnd();
|
||||||
|
Deserialize.Value(reader, "PerspectiveNearPlane", out camera.[Friend]_perspectiveNearPlane);
|
||||||
|
reader.EntryEnd();
|
||||||
|
Deserialize.Value(reader, "PerspectiveFarPlane", out camera.[Friend]_perspectiveFarPlane);
|
||||||
|
reader.EntryEnd();
|
||||||
|
Deserialize.Value(reader, "OrthographicHeight", out camera.[Friend]_orthographicHeight);
|
||||||
|
reader.EntryEnd();
|
||||||
|
Deserialize.Value(reader, "OrthographicNearPlane", out camera.[Friend]_orthographicNearPlane);
|
||||||
|
reader.EntryEnd();
|
||||||
|
Deserialize.Value(reader, "OrthographicFarPlane", out camera.[Friend]_orthographicFarPlane);
|
||||||
|
reader.EntryEnd();
|
||||||
|
Deserialize.Value(reader, "AspectRatio", out camera.[Friend]_aspectRatio);
|
||||||
|
reader.EntryEnd();
|
||||||
|
Deserialize.Value(reader, "FixedAspectRatio", out camera.[Friend]_fixedAspectRatio);
|
||||||
|
|
||||||
|
camera.[Friend]CalculateProjection();
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}));
|
||||||
|
// TODO: native script component
|
||||||
|
case "LightComponent":
|
||||||
|
Try!(DeserializeComponent<LightComponent>(reader, entity, scope (component) =>
|
||||||
|
{
|
||||||
|
SceneLight light = component.SceneLight;
|
||||||
|
|
||||||
|
Deserialize.Value(reader, "LightType", out light.[Friend]_type);
|
||||||
|
reader.EntryEnd();
|
||||||
|
|
||||||
|
Deserialize.Value(reader, "Illuminance", out light.[Friend]_illuminance);
|
||||||
|
reader.EntryEnd();
|
||||||
|
|
||||||
|
Deserialize.Value(reader, "Color", out light.[Friend]_color);
|
||||||
|
return .Ok;
|
||||||
|
}));
|
||||||
|
|
||||||
|
default:
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Try!(reader.ObjectBlockEnd());
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
|
||||||
|
/*writer.EntryStart();
|
||||||
|
|
||||||
|
using (writer.ObjectBlock())
|
||||||
|
{
|
||||||
|
// TODO: Entity GUID goes here!
|
||||||
|
Serialize.Value(writer, "Id", entity.Handle.Index);
|
||||||
|
|
||||||
|
SerializeComponent<EditorComponent>(writer, entity, "EditorComponent", scope (component) => {});
|
||||||
|
|
||||||
|
SerializeComponent<DebugNameComponent>(writer, entity, "NameComponent", scope (component) =>
|
||||||
|
{
|
||||||
|
Serialize.Value(writer, "Name", component.DebugName);
|
||||||
|
});
|
||||||
|
|
||||||
|
SerializeComponent<SpriterRendererComponent>(writer, entity, "SpriterRendererComponent", scope (component) =>
|
||||||
|
{
|
||||||
|
// TODO: Texture
|
||||||
|
|
||||||
|
Serialize.Value(writer, "Color", component.Color);
|
||||||
|
});
|
||||||
|
|
||||||
|
SerializeComponent<TransformComponent>(writer, entity, "TransformComponent", scope (component) =>
|
||||||
|
{
|
||||||
|
// TODO: Use GUIDs
|
||||||
|
if (component.Parent != .InvalidEntity)
|
||||||
|
Serialize.Value(writer, "ParentId", component.Parent.Index);
|
||||||
|
|
||||||
|
Serialize.Value(writer, "Position", component.Position);
|
||||||
|
Serialize.Value(writer, "Rotation", component.Rotation);
|
||||||
|
Serialize.Value(writer, "Scale", component.Scale);
|
||||||
|
|
||||||
|
Serialize.Value(writer, "EditorEulerRotation", component.EditorRotationEuler);
|
||||||
|
});
|
||||||
|
|
||||||
|
SerializeComponent<CameraComponent>(writer, entity, "CameraComponent", scope (component) =>
|
||||||
|
{
|
||||||
|
SceneCamera camera = component.Camera;
|
||||||
|
|
||||||
|
Serialize.Value(writer, "Primary", component.Primary);
|
||||||
|
|
||||||
|
// TODO: Render target
|
||||||
|
|
||||||
|
Serialize.Value(writer, "ProjectionType", camera.ProjectionType);
|
||||||
|
|
||||||
|
Serialize.Value(writer, "PerspectiveFovY", camera.PerspectiveFovY);
|
||||||
|
Serialize.Value(writer, "PerspectiveNearPlane", camera.PerspectiveNearPlane);
|
||||||
|
Serialize.Value(writer, "PerspectiveFarPlane", camera.PerspectiveFarPlane);
|
||||||
|
Serialize.Value(writer, "OrthographicHeight", camera.OrthographicHeight);
|
||||||
|
Serialize.Value(writer, "OrthographicNearPlane", camera.OrthographicNearPlane);
|
||||||
|
Serialize.Value(writer, "OrthographicFarPlane", camera.OrthographicFarPlane);
|
||||||
|
Serialize.Value(writer, "AspectRatio", camera.AspectRatio);
|
||||||
|
Serialize.Value(writer, "FixedAspectRatio", camera.FixedAspectRatio);
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: native script component
|
||||||
|
|
||||||
|
|
||||||
|
SerializeComponent<LightComponent>(writer, entity, "LightComponent", scope (component) =>
|
||||||
|
{
|
||||||
|
SceneLight light = component.SceneLight;
|
||||||
|
|
||||||
|
Serialize.Value(writer, "LightType", light.LightType);
|
||||||
|
|
||||||
|
Serialize.Value(writer, "Illuminance", light.Illuminance);
|
||||||
|
|
||||||
|
Serialize.Value(writer, "Color", light.Color);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.EntryEnd();*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result<void> DeserializeComponent<T>(BonReader reader, Entity entity, delegate Result<void>(T* component) deserialize) where T : struct, new
|
||||||
|
{
|
||||||
|
Try!(reader.ObjectBlock());
|
||||||
|
|
||||||
|
T* component;
|
||||||
|
|
||||||
|
if (entity.HasComponent<T>())
|
||||||
|
component = entity.GetComponent<T>();
|
||||||
|
else
|
||||||
|
component = entity.AddComponent<T>();
|
||||||
|
|
||||||
|
Try!(deserialize(component));
|
||||||
|
|
||||||
|
Try!(reader.ObjectBlockEnd());
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeserializeRuntime(StringView filePath)
|
||||||
|
{
|
||||||
|
Runtime.NotImplemented();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,8 @@ namespace GlitchyEngine.World
|
|||||||
internal EcsWorld.BitmaskEntry* _currentEntry;
|
internal EcsWorld.BitmaskEntry* _currentEntry;
|
||||||
internal EcsWorld.BitmaskEntry* _endEntry;
|
internal EcsWorld.BitmaskEntry* _endEntry;
|
||||||
|
|
||||||
|
public bool IsEmpty => _bitMask == null;
|
||||||
|
|
||||||
public this(EcsWorld world, Type[] componentTypes)
|
public this(EcsWorld world, Type[] componentTypes)
|
||||||
{
|
{
|
||||||
_world = world;
|
_world = world;
|
||||||
@@ -32,7 +34,11 @@ namespace GlitchyEngine.World
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.EngineLogger.AssertDebug(false, "Queried component is not registered for this world. This is invalid because the query would never return any results.");
|
#if GE_WORLD_ENUMERATOR_UNREGISTERED_COMPONENT_IS_WARNING
|
||||||
|
Log.EngineLogger.Warning($"Queried component of type \"{type}\" is not registered for this world. The query will never return any results.");
|
||||||
|
#endif
|
||||||
|
DeleteAndNullify!(_bitMask);
|
||||||
|
_endEntry = _currentEntry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,9 +72,16 @@ namespace GlitchyEngine.World
|
|||||||
internal EcsWorld.ComponentPoolEntry* _componentPool;
|
internal EcsWorld.ComponentPoolEntry* _componentPool;
|
||||||
|
|
||||||
public this(EcsWorld world) : base(world, scope Type[](typeof(TComponent)))
|
public this(EcsWorld world) : base(world, scope Type[](typeof(TComponent)))
|
||||||
|
{
|
||||||
|
if (base.IsEmpty)
|
||||||
|
{
|
||||||
|
_componentPool = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
_componentPool = &world.GetComponentPool<TComponent>();
|
_componentPool = &world.GetComponentPool<TComponent>();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public new Result<(EcsEntity Entity, TComponent* Component)> GetNext() mut
|
public new Result<(EcsEntity Entity, TComponent* Component)> GetNext() mut
|
||||||
{
|
{
|
||||||
@@ -91,10 +104,18 @@ namespace GlitchyEngine.World
|
|||||||
internal EcsWorld.ComponentPoolEntry* _componentPool1;
|
internal EcsWorld.ComponentPoolEntry* _componentPool1;
|
||||||
|
|
||||||
public this(EcsWorld world) : base(world, scope Type[](typeof(TComponent0), typeof(TComponent1)))
|
public this(EcsWorld world) : base(world, scope Type[](typeof(TComponent0), typeof(TComponent1)))
|
||||||
|
{
|
||||||
|
if (base.IsEmpty)
|
||||||
|
{
|
||||||
|
_componentPool0 = null;
|
||||||
|
_componentPool1 = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
_componentPool0 = &world.GetComponentPool<TComponent0>();
|
_componentPool0 = &world.GetComponentPool<TComponent0>();
|
||||||
_componentPool1 = &world.GetComponentPool<TComponent1>();
|
_componentPool1 = &world.GetComponentPool<TComponent1>();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public new Result<(EcsEntity Entity, TComponent0* Component0, TComponent1* Component1)> GetNext() mut
|
public new Result<(EcsEntity Entity, TComponent0* Component0, TComponent1* Component1)> GetNext() mut
|
||||||
{
|
{
|
||||||
@@ -119,11 +140,20 @@ namespace GlitchyEngine.World
|
|||||||
internal EcsWorld.ComponentPoolEntry* _componentPool2;
|
internal EcsWorld.ComponentPoolEntry* _componentPool2;
|
||||||
|
|
||||||
public this(EcsWorld world) : base(world, scope Type[](typeof(TComponent0), typeof(TComponent1), typeof(TComponent2)))
|
public this(EcsWorld world) : base(world, scope Type[](typeof(TComponent0), typeof(TComponent1), typeof(TComponent2)))
|
||||||
|
{
|
||||||
|
if (base.IsEmpty)
|
||||||
|
{
|
||||||
|
_componentPool0 = null;
|
||||||
|
_componentPool1 = null;
|
||||||
|
_componentPool2 = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
_componentPool0 = &world.GetComponentPool<TComponent0>();
|
_componentPool0 = &world.GetComponentPool<TComponent0>();
|
||||||
_componentPool1 = &world.GetComponentPool<TComponent1>();
|
_componentPool1 = &world.GetComponentPool<TComponent1>();
|
||||||
_componentPool2 = &world.GetComponentPool<TComponent2>();
|
_componentPool2 = &world.GetComponentPool<TComponent2>();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public new Result<(EcsEntity Entity, TComponent0* Component0, TComponent1* Component1, TComponent2* Component2)> GetNext() mut
|
public new Result<(EcsEntity Entity, TComponent0* Component0, TComponent1* Component1, TComponent2* Component2)> GetNext() mut
|
||||||
{
|
{
|
||||||
@@ -150,12 +180,22 @@ namespace GlitchyEngine.World
|
|||||||
internal EcsWorld.ComponentPoolEntry* _componentPool3;
|
internal EcsWorld.ComponentPoolEntry* _componentPool3;
|
||||||
|
|
||||||
public this(EcsWorld world) : base(world, scope Type[](typeof(TComponent0), typeof(TComponent1), typeof(TComponent2), typeof(TComponent3)))
|
public this(EcsWorld world) : base(world, scope Type[](typeof(TComponent0), typeof(TComponent1), typeof(TComponent2), typeof(TComponent3)))
|
||||||
|
{
|
||||||
|
if (base.IsEmpty)
|
||||||
|
{
|
||||||
|
_componentPool0 = null;
|
||||||
|
_componentPool1 = null;
|
||||||
|
_componentPool2 = null;
|
||||||
|
_componentPool3 = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
_componentPool0 = &world.GetComponentPool<TComponent0>();
|
_componentPool0 = &world.GetComponentPool<TComponent0>();
|
||||||
_componentPool1 = &world.GetComponentPool<TComponent1>();
|
_componentPool1 = &world.GetComponentPool<TComponent1>();
|
||||||
_componentPool2 = &world.GetComponentPool<TComponent2>();
|
_componentPool2 = &world.GetComponentPool<TComponent2>();
|
||||||
_componentPool3 = &world.GetComponentPool<TComponent3>();
|
_componentPool3 = &world.GetComponentPool<TComponent3>();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public new Result<(EcsEntity Entity, TComponent0* Component0, TComponent1* Component1, TComponent2* Component2, TComponent3* Component3)> GetNext() mut
|
public new Result<(EcsEntity Entity, TComponent0* Component0, TComponent1* Component1, TComponent2* Component2, TComponent3* Component3)> GetNext() mut
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user