diff --git a/.gitmodules b/.gitmodules index eebbba3..14e05b4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -21,4 +21,7 @@ url = https://github.com/aharabada/msdfgen-beef.git [submodule "GlitchyEngine/vendor/imgui"] path = GlitchyEngine/vendor/imgui - url = https://github.com/aharabada/ImGui_GlitchyEngine.git \ No newline at end of file + url = https://github.com/aharabada/ImGui_GlitchyEngine.git +[submodule "GlitchyEngineHelper/vendor/xxHash"] + path = GlitchyEngineHelper/vendor/xxHash + url = https://github.com/Cyan4973/xxHash.git diff --git a/BeefSpace.toml b/BeefSpace.toml index 9225ad3..d81985f 100644 --- a/BeefSpace.toml +++ b/BeefSpace.toml @@ -1,5 +1,6 @@ FileVersion = 1 -Projects = {Sandbox = {Path = "Sandbox"}, GlitchyEngine = {Path = "GlitchyEngine"}, GlitchLog = {Path = "GlitchLog"}, DirectX = {Path = "GlitchyEngine/vendor/directx/DirectX"}, DirectXTK = {Path = "GlitchyEngine/vendor/DirectXTK/DirectXTK-beef"}, LodePng = {Path = "vendor/lodepng-beef/lodepng-beef"}, FreeType = {Path = "GlitchyEngine/vendor/freetype"}, cgltf-beef = {Path = "GlitchyEngine/vendor/gltf/cgltf-beef"}, GlitchyEditor = {Path = "GlitchyEditor"}, msdfgen-beef = {Path = "GlitchyEngine/vendor/msdfgen/msdfgen-beef"}, ImGui = {Path = "GlitchyEngine/vendor/imgui/ImGui"}, ImGuiImplDX11 = {Path = "GlitchyEngine/vendor/imgui/ImGuiImplDX11"}, ImGuiImplWin32 = {Path = "GlitchyEngine/vendor/imgui/ImGuiImplWin32"}, ImGuizmo = {Path = "GlitchyEngine/vendor/imgui/ImGuizmo"}} +Projects = {Sandbox = {Path = "Sandbox"}, GlitchyEngine = {Path = "GlitchyEngine"}, GlitchLog = {Path = "GlitchLog"}, DirectX = {Path = "GlitchyEngine/vendor/directx/DirectX"}, DirectXTK = {Path = "GlitchyEngine/vendor/DirectXTK/DirectXTK-beef"}, LodePng = {Path = "vendor/lodepng-beef/lodepng-beef"}, FreeType = {Path = "GlitchyEngine/vendor/freetype"}, cgltf-beef = {Path = "GlitchyEngine/vendor/gltf/cgltf-beef"}, GlitchyEditor = {Path = "GlitchyEditor"}, msdfgen-beef = {Path = "GlitchyEngine/vendor/msdfgen/msdfgen-beef"}, ImGui = {Path = "GlitchyEngine/vendor/imgui/ImGui"}, ImGuiImplDX11 = {Path = "GlitchyEngine/vendor/imgui/ImGuiImplDX11"}, ImGuiImplWin32 = {Path = "GlitchyEngine/vendor/imgui/ImGuiImplWin32"}, ImGuizmo = {Path = "GlitchyEngine/vendor/imgui/ImGuizmo"}, GlitchyEngineHelper = {Path = "GlitchyEngineHelper"}} +WorkspaceFolders = {GlitchyEngine = ["GlitchyEngine", "GlitchLog", "GlitchyEngineHelper"], Dependencies = ["cgltf-beef", "DirectX", "DirectXTK", "FreeType", "ImGui", "ImGuiImplDX11", "ImGuiImplWin32", "ImGuizmo", "LodePng", "msdfgen-beef"]} [Workspace] StartupProject = "GlitchyEditor" diff --git a/GlitchyEditor/content/Textures/rocket.png b/GlitchyEditor/content/Textures/rocket.png new file mode 100644 index 0000000..cd34f90 Binary files /dev/null and b/GlitchyEditor/content/Textures/rocket.png differ diff --git a/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf b/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf index 5dab291..577ae1e 100644 --- a/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf +++ b/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf @@ -5,6 +5,8 @@ using GlitchyEngine.Math; namespace GlitchyEditor.EditWindows { + using internal GlitchyEngine.World.TransformComponent; + class ComponentEditWindow : EditorWindow { public const String s_WindowTitle = "Components"; @@ -77,117 +79,109 @@ namespace GlitchyEditor.EditWindows } } + private static bool Vector3Control(StringView label, ref Vector3 value, Vector3 resetValues = .Zero, float dragSpeed = 0.1f, float columnWidth = 100f) + { + bool changed = false; + + ImGui.PushID(label); + defer ImGui.PopID(); + + ImGui.Columns(2); + defer ImGui.Columns(1); + ImGui.SetColumnWidth(0, columnWidth); + + ImGui.TextUnformatted(label); + + ImGui.NextColumn(); + + ImGui.PushMultiItemsWidths(3, ImGui.CalcItemWidth()); + ImGui.PushStyleVar(.ItemSpacing, ImGui.Vec2.Zero); + defer ImGui.PopStyleVar(); + + float lineHeight = ImGui.GetFont().FontSize + ImGui.GetStyle().FramePadding.y * 2.0f; + ImGui.Vec2 buttonSize = .(lineHeight + 3.0f, lineHeight); + + ImGui.PushStyleColor(.Button, ImGui.Color(230, 25, 45).Value); + ImGui.PushStyleColor(.ButtonHovered, ImGui.Color(150, 25, 45).Value); + ImGui.PushStyleColor(.ButtonActive, ImGui.Color(230, 120, 130).Value); + + if (ImGui.Button("X", buttonSize)) + { + value.X = resetValues.X; + changed = true; + } + + ImGui.SameLine(); + + if (ImGui.DragFloat("##X", &value.X, dragSpeed)) + changed = true; + + ImGui.PopItemWidth(); + ImGui.SameLine(); + + ImGui.PopStyleColor(3); + ImGui.PushStyleColor(.Button, ImGui.Color(50, 190, 15).Value); + ImGui.PushStyleColor(.ButtonHovered, ImGui.Color(50, 120, 15).Value); + ImGui.PushStyleColor(.ButtonActive, ImGui.Color(116, 190, 99).Value); + + if (ImGui.Button("Y", buttonSize)) + { + value.Y = resetValues.Y; + changed = true; + } + + ImGui.SameLine(); + + if (ImGui.DragFloat("##Y", &value.Y, dragSpeed)) + changed = true; + + ImGui.PopItemWidth(); + ImGui.SameLine(); + + ImGui.PopStyleColor(3); + ImGui.PushStyleColor(.Button, ImGui.Color(55, 55, 230).Value); + ImGui.PushStyleColor(.ButtonHovered, ImGui.Color(55, 55, 150).Value); + ImGui.PushStyleColor(.ButtonActive, ImGui.Color(90, 90, 230).Value); + + if (ImGui.Button("Z", buttonSize)) + { + value.Z = resetValues.Z; + changed = true; + } + + ImGui.SameLine(); + + if (ImGui.DragFloat("##Z", &value.Z, dragSpeed)) + changed = true; + + ImGui.PopItemWidth(); + + ImGui.PopStyleColor(3); + + return changed; + } + private static void ShowTransformComponentEditor(Entity entity) { - if (!entity.HasComponent()) + if (!entity.HasComponent()) return; - var transform = entity.GetComponent(); + var transform = entity.GetComponent(); if(ImGui.TreeNodeEx("Transform", .DefaultOpen)) { - bool ShowValue(String text, ref float value, String id) - { - ImGui.Text(text); - ImGui.SameLine(); - ImGui.PushID(id); - bool valueChanged = ImGui.DragFloat(String.Empty, &value, 0.1f); - ImGui.PopID(); - - return valueChanged; - } - - bool ShowTableRow(String name, ref Vector3 value) - { - bool changed = false; - - ImGui.TableNextColumn(); - - ImGui.Text(name); - ImGui.TableNextColumn(); - changed |= ShowValue("X: ", ref value.X, scope $"{name}X"); - ImGui.TableNextColumn(); - changed |= ShowValue("Y: ", ref value.Y, scope $"{name}Y"); - ImGui.TableNextColumn(); - changed |= ShowValue("Z: ", ref value.Z, scope $"{name}Z"); - - ImGui.TableNextRow(); - - return changed; - } - - Matrix.Decompose(transform.Transform, var position, var rotation, var scale); - - ImGui.BeginTable("posRotScaleTable", 4); - - if (ShowTableRow("Position", ref position)) - { - transform.Transform.Translation = position; - } - - var oldScale = scale; - if (ShowTableRow("Scale", ref scale)) - { - Vector3 v = 1.0f / oldScale * scale; - - transform.Transform.Scale = (Vector3)transform.Transform.Scale * v; - } - - - ImGui.EndTable(); - - /* Vector3 position = transform.Position; - bool positionChanged = false; + if (Vector3Control("Position", ref position)) + transform.Position = position; + + Vector3 rotationEuler = MathHelper.ToDegrees(transform.EditorRotationEuler); + if (Vector3Control("Rotation", ref rotationEuler)) + transform.EditorRotationEuler = MathHelper.ToRadians(rotationEuler); - Vector3 rotationEuler = MathHelper.ToDegrees(component.RotationEuler); - bool rotationChanged = false; - - Vector3 scale = component.Scale; - bool scaleChanged = false; + Vector3 scale = transform.Scale; + if (Vector3Control("Scale", ref scale, .One)) + transform.Scale = scale; - void ShowValue(String text, ref float value, ref bool valueChanged, String id) - { - ImGui.Text(text); - ImGui.SameLine(); - ImGui.PushID(id); - valueChanged |= ImGui.DragFloat(String.Empty, &value, 0.1f); - ImGui.PopID(); - } - - void ShowTableRow(String name, ref Vector3 value, ref bool valueChanged) - { - ImGui.TableNextColumn(); - - ImGui.Text(name); - ImGui.TableNextColumn(); - ShowValue("X: ", ref value.X, ref valueChanged, scope $"{name}X"); - ImGui.TableNextColumn(); - ShowValue("Y: ", ref value.Y, ref valueChanged, scope $"{name}Y"); - ImGui.TableNextColumn(); - ShowValue("Z: ", ref value.Z, ref valueChanged, scope $"{name}Z"); - - ImGui.TableNextRow(); - } - - ImGui.BeginTable("posRotScaleTable", 4); - - ShowTableRow("Position", ref position, ref positionChanged); - ShowTableRow("Rotation", ref rotationEuler, ref rotationChanged); - ShowTableRow("Scale", ref scale, ref scaleChanged); - - ImGui.EndTable(); - - if(positionChanged) - component.Position = position; - - if(rotationChanged) - component.RotationEuler = MathHelper.ToRadians(rotationEuler); - - if(scaleChanged) - component.Scale = scale; - - */ ImGui.TreePop(); } } diff --git a/GlitchyEditor/src/EditWindows/EntityHierarchyWindow.bf b/GlitchyEditor/src/EditWindows/EntityHierarchyWindow.bf index 9131ca7..c6d9c92 100644 --- a/GlitchyEditor/src/EditWindows/EntityHierarchyWindow.bf +++ b/GlitchyEditor/src/EditWindows/EntityHierarchyWindow.bf @@ -55,7 +55,7 @@ namespace GlitchyEditor.EditWindows for(var selectedEntity in _selectedEntities) { - var transformComponent = selectedEntity.GetComponent(); + var transformComponent = selectedEntity.GetComponent(); if(parent == .InvalidEntity) { @@ -73,7 +73,7 @@ namespace GlitchyEditor.EditWindows /// Finds all children of the given entity and stores their IDs in the given list. internal void FindChildren(EcsEntity entity, List entities) { - for(var (child, childTransform) in _scene.[Friend]_ecsWorld.Enumerate()) + for(var (child, childTransform) in _scene.[Friend]_ecsWorld.Enumerate()) { if(childTransform.Parent == entity) { @@ -124,7 +124,7 @@ namespace GlitchyEditor.EditWindows { var newEntity = _scene.CreateEntity(); - var transformCmp = newEntity.GetComponent(); + var transformCmp = newEntity.GetComponent(); // Last entity in list is the entity that has been selected last. transformCmp.Parent = _selectedEntities.Back.Handle; } @@ -134,7 +134,7 @@ namespace GlitchyEditor.EditWindows if(ImGui.MenuItem("Empty Parent", null, false, !_selectedEntities.IsEmpty && AllSelectionsOnSameLevel())) { - var commonParent = _selectedEntities.Front.GetComponent(); + var commonParent = _selectedEntities.Front.GetComponent(); var newEntity = _scene.CreateEntity(); @@ -142,14 +142,14 @@ namespace GlitchyEditor.EditWindows { // parent of selected entities is parent of the new entity. // (which is why this doesn't work if the entities don't have the same parent) - var newEntityTransform = newEntity.GetComponent(); + var newEntityTransform = newEntity.GetComponent(); newEntityTransform.Parent = commonParent.Parent; } // new entity is parent of all selected entities. for(var selectedEntity in _selectedEntities) { - var selectedTransform = selectedEntity.GetComponent(); + var selectedTransform = selectedEntity.GetComponent(); selectedTransform.Parent = newEntity.Handle; } } @@ -163,7 +163,8 @@ namespace GlitchyEditor.EditWindows if(ImGui.IsItemHovered()) ImGui.SetTooltip("Create a new Entity."); - if(ImGui.MenuItem("Delete", null, false, !_selectedEntities.IsEmpty) || Input.IsKeyPressed(.Delete)) + if(ImGui.MenuItem("Delete", null, false, !_selectedEntities.IsEmpty) || + (Input.IsKeyPressed(.Delete) && ImGui.IsWindowHovered())) { DeleteSelectedEntities(); } @@ -232,7 +233,7 @@ namespace GlitchyEditor.EditWindows // make sure the dropped entity is not a parent of the entity we dropped it on. while(true) { - var parentTransform = walker.GetComponent(); + var parentTransform = walker.GetComponent(); if(parentTransform.Parent == .InvalidEntity) { @@ -250,7 +251,7 @@ namespace GlitchyEditor.EditWindows if(dropLegal) { - var movedEntityTransform = movedEntity.GetComponent(); + var movedEntityTransform = movedEntity.GetComponent(); movedEntityTransform.Parent = tree.Value.Handle; } } @@ -302,7 +303,7 @@ namespace GlitchyEditor.EditWindows TreeNode InsertIntoTree(Entity entity) { - var transform = entity.GetComponent(); + var transform = entity.GetComponent(); if(transform == null) { @@ -342,7 +343,7 @@ namespace GlitchyEditor.EditWindows Entity movedEntity = *(Entity*)payload.Data; // Also mark transform as dirty - var transformComponent = movedEntity.GetComponent(); + var transformComponent = movedEntity.GetComponent(); transformComponent.Parent = .InvalidEntity; //transformComponent?.IsDirty = true; } diff --git a/GlitchyEditor/src/EditWindows/SceneViewportWindow.bf b/GlitchyEditor/src/EditWindows/SceneViewportWindow.bf index df00ad7..357cbd2 100644 --- a/GlitchyEditor/src/EditWindows/SceneViewportWindow.bf +++ b/GlitchyEditor/src/EditWindows/SceneViewportWindow.bf @@ -10,7 +10,7 @@ namespace GlitchyEditor.EditWindows { class SceneViewportWindow : EditorWindow { - public OldCamera _camera; + //public OldCamera _camera; public const String s_WindowTitle = "Scene"; @@ -38,6 +38,8 @@ namespace GlitchyEditor.EditWindows private ImGui.Vec2 oldViewportSize; private bool viewPortChanged; + public Entity CameraEntity { get; set; } + protected override void InternalShow() { ImGui.PushStyleVar(.WindowPadding, ImGui.Vec2(1, 1)); @@ -87,8 +89,11 @@ namespace GlitchyEditor.EditWindows topLeft.y += cntMin.y; ImGuizmo.SetRect(topLeft.x, topLeft.y, viewportSize.x, viewportSize.y); - var view = _camera.View; - var projection = _camera.Projection; + var cameraTransformCmp = CameraEntity.GetComponent(); + var view = cameraTransformCmp.WorldTransform.Invert(); + + var cameraCmp = CameraEntity.GetComponent(); + var projection = cameraCmp.Camera.Projection; Matrix mat = .Identity; ImGuizmo.DrawGrid((.)&view, (.)&projection, (.)&mat, 10); diff --git a/GlitchyEditor/src/EditorCameraController.bf b/GlitchyEditor/src/EditorCameraController.bf new file mode 100644 index 0000000..e1f61eb --- /dev/null +++ b/GlitchyEditor/src/EditorCameraController.bf @@ -0,0 +1,63 @@ +using GlitchyEngine; +using GlitchyEngine.Math; +using GlitchyEngine.World; + +namespace GlitchyEditor +{ + class EditorCameraController : ScriptableEntity + { + private float _cameraTranslationSpeed = 2.0f; + private float _cameraRotationSpeedX = 0.001f; + private float _cameraRotationSpeedY = 0.001f; + + public bool IsEnabled = false; + + protected override void OnUpdate(GameTime gt) + { + if (!IsEnabled) + return; + + Debug.Profiler.ProfileFunction!(); + + Vector3 movement = .(); + + if(Input.IsKeyPressed(Key.W)) + movement.Z += 1; + if(Input.IsKeyPressed(Key.S)) + movement.Z -= 1; + + if(Input.IsKeyPressed(Key.A)) + movement.X -= 1; + if(Input.IsKeyPressed(Key.D)) + movement.X += 1; + + if(Input.IsKeyPressed(Key.Space)) + movement.Y += 1; + if(Input.IsKeyPressed(Key.Control)) + movement.Y -= 1; + + var transformComponent = transform; + + if(movement != .Zero) + { + movement.Normalize(); + + movement *= (float)(gt.FrameTime.TotalSeconds) * _cameraTranslationSpeed; + + Matrix view = transformComponent.WorldTransform.Invert(); + + Vector4 delta = Vector4(movement, 1.0f) * view; + + transformComponent.Position = transformComponent.Position + delta.XYZ; + } + + // Camera rotation + var mouseDelta = Input.GetMouseMovement(); + + float rotY = mouseDelta.X * _cameraRotationSpeedX; + float rotX = mouseDelta.Y * _cameraRotationSpeedY; + + transformComponent.RotationEuler = transformComponent.RotationEuler + .(rotX, rotY, 0); + } + } +} \ No newline at end of file diff --git a/GlitchyEditor/src/EditorLayer.bf b/GlitchyEditor/src/EditorLayer.bf index 635c3a9..5e5974c 100644 --- a/GlitchyEditor/src/EditorLayer.bf +++ b/GlitchyEditor/src/EditorLayer.bf @@ -25,8 +25,6 @@ namespace GlitchyEditor Editor _editor ~ delete _; - PerspectiveCameraController _cameraController ~ delete _; - RenderTarget2D _viewportTarget ~ _?.ReleaseRef(); Entity _cameraEntity; @@ -41,24 +39,28 @@ namespace GlitchyEditor protected override void OnUpdate(GameTime gameTime) { - var transformCmp = GetComponent(); + var transformCmp = GetComponent(); + + Vector3 position = transformCmp.Position; if (Input.IsKeyPressed(Key.A)) { - transformCmp.Transform.Translation.X -= gameTime.DeltaTime; + position.X -= gameTime.DeltaTime; } if (Input.IsKeyPressed(Key.D)) { - transformCmp.Transform.Translation.X += gameTime.DeltaTime; + position.X += gameTime.DeltaTime; } if (Input.IsKeyPressed(Key.W)) { - transformCmp.Transform.Translation.Y += gameTime.DeltaTime; + position.Y += gameTime.DeltaTime; } if (Input.IsKeyPressed(Key.S)) { - transformCmp.Transform.Translation.Y -= gameTime.DeltaTime; + position.Y -= gameTime.DeltaTime; } + + transformCmp.Position = position; } protected override void OnDestroy() @@ -72,8 +74,6 @@ namespace GlitchyEditor Application.Get().Window.IsVSync = false; InitGraphics(); - //InitEcs(); - InitEditor(); { _cameraEntity = _scene.CreateEntity("Camera Entity"); @@ -81,10 +81,10 @@ namespace GlitchyEditor camera.Camera.SetPerspective(MathHelper.ToRadians(75), 0.1f, 10000.0f); camera.Primary = true; camera.FixedAspectRatio = false; - let transform = _cameraEntity.GetComponent(); - transform.Transform = Matrix.Translation(0, 0, -5); + let transform = _cameraEntity.GetComponent(); + transform.Position = .(0, 0, -5); - _cameraEntity.AddComponent().Bind(); + _cameraEntity.AddComponent().Bind(); _cameraEntity.AddComponent(); } @@ -94,12 +94,14 @@ namespace GlitchyEditor camera.Camera.SetPerspective(MathHelper.ToRadians(45), 0.1f, 1000.0f); camera.Primary = false; camera.FixedAspectRatio = false; - let transform = _otherCameraEntity.GetComponent(); - transform.Transform = Matrix.Translation(0, 0, -5); + let transform = _otherCameraEntity.GetComponent(); + transform.Position = .(0, 0, -5); - _otherCameraEntity.AddComponent().Bind(); + _otherCameraEntity.AddComponent().Bind(); _otherCameraEntity.AddComponent(); } + + InitEditor(); } private void InitGraphics() @@ -129,19 +131,19 @@ namespace GlitchyEditor _editor = new Editor(_scene); _editor.SceneViewportWindow.ViewportSizeChangedEvent.Add(new (s, e) => ViewportSizeChanged(s, e)); - _cameraController = new .(_context.SwapChain.AspectRatio); - _cameraController.CameraPosition = .(0, 0, -5); - _cameraController.TranslationSpeed = 10; - //_editor.[Friend]CreateEntityWithTransform(); - _editor.SceneViewportWindow._camera = _cameraController.Camera; + _editor.SceneViewportWindow.CameraEntity = _cameraEntity; } public override void Update(GameTime gameTime) { - if(_editor.SceneViewportWindow.HasFocus && Input.IsMouseButtonPressed(.RightButton)) - _cameraController.Update(gameTime); + var scriptComponent = _cameraEntity.GetComponent(); + + if (var camController = scriptComponent.Instance as EditorCameraController) + { + camController.IsEnabled = (_editor.SceneViewportWindow.HasFocus && Input.IsMouseButtonPressed(.RightButton)); + } //TransformSystem.Update(_world); @@ -173,8 +175,6 @@ namespace GlitchyEditor public override void OnEvent(Event event) { - _cameraController.OnEvent(event); - EventDispatcher dispatcher = EventDispatcher(event); dispatcher.Dispatch(scope (e) => OnImGuiRender(e)); @@ -257,8 +257,6 @@ namespace GlitchyEditor _viewportTarget.Resize(sizeX, sizeY); - _cameraController.AspectRatio = (float)sizeX / (float)sizeY; - _scene.OnViewportResize(sizeX, sizeY); } } diff --git a/GlitchyEngine/src/Application.bf b/GlitchyEngine/src/Application.bf index bff531f..af6200a 100644 --- a/GlitchyEngine/src/Application.bf +++ b/GlitchyEngine/src/Application.bf @@ -3,6 +3,7 @@ using GlitchyEngine.Events; using GlitchyEngine.ImGui; using GlitchyEngine.Renderer; using GlitchyEngine.Debug; +using GlitchyEngine.Content; namespace GlitchyEngine { @@ -24,12 +25,16 @@ namespace GlitchyEngine #endif private GameTime _gameTime; + + private IContentManager _contentManager; public bool IsRunning => _running; public Window Window => _window; public EffectLibrary EffectLibrary => _effectLibrary; + public IContentManager ContentManager => _contentManager; + public bool IsMinimized => _isMinimized; [Inline] @@ -51,6 +56,8 @@ namespace GlitchyEngine _rendererApi = new RendererAPI(); _rendererApi.Context = _window.Context; + _contentManager = new ContentManager("./content"); + SamplerStateManager.Init(); RenderCommand.RendererAPI = _rendererApi; @@ -73,6 +80,9 @@ namespace GlitchyEngine Renderer.Deinit(); delete _effectLibrary; + + delete _contentManager; + delete _rendererApi; delete _window; diff --git a/GlitchyEngine/src/ImGui/ImGuiExtension.bf b/GlitchyEngine/src/ImGui/ImGuiExtension.bf index c08de43..a00593c 100644 --- a/GlitchyEngine/src/ImGui/ImGuiExtension.bf +++ b/GlitchyEngine/src/ImGui/ImGuiExtension.bf @@ -1,5 +1,6 @@ using GlitchyEngine.Math; using GlitchyEngine.Renderer; +using System; namespace ImGui { @@ -21,6 +22,10 @@ namespace ImGui // Wouldn't be necesseary if RenderTarget2D was Texture2D public static extern void Image(RenderTarget2D texture, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 tint_col = Vec4.Ones, Vec4 border_col = Vec4.Zero); + public static void TextUnformatted(StringView text) => TextUnformattedImpl(text.Ptr, text.Ptr + text.Length); + + public static void PushID(StringView id) => PushID(id.Ptr, id.Ptr + id.Length); + /// Releases references that accumulated calls like ImGui::Image protected internal static extern void CleanupFrame(); diff --git a/GlitchyEngine/src/Math/MathHelper.bf b/GlitchyEngine/src/Math/MathHelper.bf index fa8d13c..3a7ad5a 100644 --- a/GlitchyEngine/src/Math/MathHelper.bf +++ b/GlitchyEngine/src/Math/MathHelper.bf @@ -18,10 +18,10 @@ namespace GlitchyEngine.Math public const float PiOverFour = 0.785398163f; /// Converts radians to degrees - const float RadToDeg = 180.0f / Pi; + public const float RadToDeg = 180.0f / Pi; /// Converts radians to degrees - const float DegToRad = Pi / 180.0f; + public const float DegToRad = Pi / 180.0f; // Converts the given radians to degrees public static float ToDegrees(float radians) diff --git a/GlitchyEngine/src/Math/Quaternion.bf b/GlitchyEngine/src/Math/Quaternion.bf index 5967176..5fc3e27 100644 --- a/GlitchyEngine/src/Math/Quaternion.bf +++ b/GlitchyEngine/src/Math/Quaternion.bf @@ -314,35 +314,65 @@ namespace GlitchyEngine.Math return result; } - public static Vector3 ToEulerAngles(Quaternion q1) + public static Vector3 ToEulerAngles(Quaternion q) { // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/ - + Vector3 result; - float sqw = q1.W*q1.W; - float sqx = q1.X*q1.X; - float sqy = q1.Y*q1.Y; - float sqz = q1.Z*q1.Z; + float sqw = q.W*q.W; + float sqx = q.X*q.X; + float sqy = q.Y*q.Y; + float sqz = q.Z*q.Z; float unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor - float test = q1.X*q1.Y + q1.Z*q1.W; - if (test > 0.499f*unit) { // singularity at north pole - result.Y = 2.0f * Math.Atan2(q1.X,q1.W); + float test = q.X*q.Y + q.Z*q.W; + if (test > 0.4999f*unit) { // singularity at north pole + result.Y = 2.0f * Math.Atan2(q.X,q.W); result.Z = Math.PI_f / 2.0f; result.X = 0.0f; return result; } - if (test < -0.499f*unit) { // singularity at south pole - result.Y = -2.0f * Math.Atan2(q1.X,q1.W); + if (test < -0.4999f*unit) { // singularity at south pole + result.Y = -2.0f * Math.Atan2(q.X,q.W); result.Z = -Math.PI_f / 2.0f; result.X = 0.0f; return result; } - result.Y = Math.Atan2(2*q1.Y*q1.W-2*q1.X*q1.Z , sqx - sqy - sqz + sqw); + result.Y = Math.Atan2(2*q.Y*q.W-2*q.X*q.Z , sqx - sqy - sqz + sqw); result.Z = Math.Asin(2*test/unit); - result.X = Math.Atan2(2*q1.X*q1.W-2*q1.Y*q1.Z , -sqx + sqy - sqz + sqw); + result.X = Math.Atan2(2*q.X*q.W-2*q.Y*q.Z , -sqx + sqy - sqz + sqw); return result; + + //return .(q.Pitch(), q.Yaw(), q.Roll()); } + /* + public float Pitch() + { + float y = 2.0f * (Y * Z + W * X); + float x = W * W - X * X - Y * Y + Z * Z; + + if (Vector2(x, y).Equals(.Zero)) //avoid atan2(0,0) - handle singularity - Matiis + return 2.0f * Math.Atan2(X, W); + + return Math.Atan2(y, x); + } + + public float Yaw() + { + return Math.Asin(Math.Clamp(-2.0f * (X * Z - W * Y), -1.0f, 1.0f)); + } + + public float Roll() + { + float y = 2.0f * (X * Y + W * Z); + float x = W * W + X * X - Y * Y - Z * Z; + + if (Vector2(x, y).Equals(.Zero)) //avoid atan2(0,0) - handle singularity - Matiis + return 0; + + return Math.Atan2(y, x); + } + */ } } diff --git a/GlitchyEngine/src/Math/Vector2.bf b/GlitchyEngine/src/Math/Vector2.bf index a74b57a..f2eff59 100644 --- a/GlitchyEngine/src/Math/Vector2.bf +++ b/GlitchyEngine/src/Math/Vector2.bf @@ -284,5 +284,10 @@ namespace GlitchyEngine.Math [Inline] public static explicit operator Self(float value) => Self(value); + + public bool Equals(Vector2 v, float epsilon = Math.[Friend]sMachineEpsilonFloat) + { + return (Math.Abs(v.X - X) < epsilon) && (Math.Abs(v.Y - Y) < epsilon); + } } } diff --git a/GlitchyEngine/src/World/Components.bf b/GlitchyEngine/src/World/Components.bf index a69b012..2748e67 100644 --- a/GlitchyEngine/src/World/Components.bf +++ b/GlitchyEngine/src/World/Components.bf @@ -13,36 +13,25 @@ namespace GlitchyEngine.World } } - - struct SimpleTransformComponent - { - public EcsEntity Parent = .InvalidEntity; - public Matrix Transform = Matrix.Identity; - - public this() - { - - } - - public this(Matrix transform) - { - Transform = transform; - } - } - struct SpriterRendererComponent + struct SpriterRendererComponent : IDisposableComponent { + public Texture2D Sprite = null; public ColorRGBA Color = .White; public this() { - } public this(ColorRGBA color) { Color = color; } + + public void Dispose() + { + Sprite?.ReleaseRef(); + } } struct SceneCamera : Camera @@ -229,7 +218,7 @@ namespace GlitchyEngine.World private void CalculateProjection() mut { - if (_projectionType case .Orthographic)//(let nearPlane, let farPlane, let projectionHeight)) + if (_projectionType case .Orthographic) { float halfHeight = _orthographicHeight / 2.0f; float halfWidth = halfHeight * _aspectRatio; @@ -237,11 +226,11 @@ namespace GlitchyEngine.World _projection = Matrix.OrthographicProjectionOffCenter(-halfWidth, halfWidth, halfHeight, -halfHeight, _orthographicNearPlane, _orthographicFarPlane); } - else if (_projectionType case .Perspective)//(let nearPlane, let farPlane, let fovY)) + else if (_projectionType case .Perspective) { _projection = Matrix.PerspectiveProjection(_perspectiveFovY, _aspectRatio, _perspectiveNearPlane, _perspectiveFarPlane); } - else if (_projectionType case .InfinitePerspective)//(let nearPlane, let fovY)) + else if (_projectionType case .InfinitePerspective) { _projection = Matrix.InfinitePerspectiveProjection(_perspectiveFovY, _aspectRatio, _perspectiveNearPlane); } diff --git a/GlitchyEngine/src/World/Scene.bf b/GlitchyEngine/src/World/Scene.bf index 546c68a..07648ff 100644 --- a/GlitchyEngine/src/World/Scene.bf +++ b/GlitchyEngine/src/World/Scene.bf @@ -16,7 +16,10 @@ namespace GlitchyEngine.World entity.AddComponent(.(ColorRGBA(0.2f, 0.9f, 0.15f))); Entity entity2 = CreateEntity("Red Square"); - entity2.AddComponent(.(ColorRGBA(0.95f, 0.1f, 0.3f))); + var v = entity2.AddComponent(.(ColorRGBA(0.95f, 0.1f, 0.3f))); + v.Sprite = new Texture2D("Textures/rocket.png"); + v.Sprite.SamplerState = SamplerStateManager.PointClamp; + } public ~this() @@ -25,7 +28,7 @@ namespace GlitchyEngine.World public void Update(GameTime gameTime) { - //TransformSystem.Update(_ecsWorld); + TransformSystem.Update(_ecsWorld); for (var (entity, script) in _ecsWorld.Enumerate()) { @@ -40,25 +43,25 @@ namespace GlitchyEngine.World } Camera* primaryCamera = null; - Matrix* primaryCameraTransform = null; + Matrix primaryCameraTransform = default; - for (var (entity, transform, camera) in _ecsWorld.Enumerate()) + for (var (entity, transform, camera) in _ecsWorld.Enumerate()) { if (camera.Primary) { primaryCamera = &camera.Camera; - primaryCameraTransform = &transform.Transform; + primaryCameraTransform = transform.WorldTransform; } } // Sprite renderer if (primaryCamera != null) { - Renderer2D.BeginScene(*primaryCamera, *primaryCameraTransform); + Renderer2D.BeginScene(*primaryCamera, primaryCameraTransform); - for (var (entity, transform, sprite) in _ecsWorld.Enumerate()) + for (var (entity, transform, sprite) in _ecsWorld.Enumerate()) { - Renderer2D.DrawQuad(transform.Transform, sprite.Color); + Renderer2D.DrawQuad(transform.WorldTransform, sprite.Sprite, sprite.Color); } Renderer2D.EndScene(); @@ -68,7 +71,7 @@ namespace GlitchyEngine.World public Entity CreateEntity(String name = "") { Entity entity = Entity(_ecsWorld.NewEntity(), this); - entity.AddComponent(.(.Identity)); + entity.AddComponent(); let nameComponent = entity.AddComponent(); nameComponent.SetName(name.IsEmpty ? "Entity" : name); diff --git a/GlitchyEngine/src/World/ScriptableEntity.bf b/GlitchyEngine/src/World/ScriptableEntity.bf index bb57ab9..df06cd4 100644 --- a/GlitchyEngine/src/World/ScriptableEntity.bf +++ b/GlitchyEngine/src/World/ScriptableEntity.bf @@ -4,6 +4,8 @@ namespace GlitchyEngine.World { internal Entity _entity; + protected TransformComponent* transform => GetComponent(); + public T* AddComponent(T value = T()) where T: struct, new { return _entity.AddComponent(value); diff --git a/GlitchyEngine/src/World/TransformComponent.bf b/GlitchyEngine/src/World/TransformComponent.bf index f24f0ec..747de1e 100644 --- a/GlitchyEngine/src/World/TransformComponent.bf +++ b/GlitchyEngine/src/World/TransformComponent.bf @@ -4,9 +4,13 @@ namespace GlitchyEngine.World { public struct TransformComponent { - Vector3 _position = .Zero; - Quaternion _rotation = .Identity; - Vector3 _scale = .One; + EcsEntity _parent = .InvalidEntity; + + Vector3 _position = .(0, 0, 0); + Quaternion _rotation = .(0, 0, 0, 1); + Vector3 _scale = .(1, 1, 1); + + Vector3 _editorRotationEuler = .Zero; Matrix _localTransform = .Identity; public bool IsDirty = false; @@ -16,6 +20,19 @@ namespace GlitchyEngine.World /// The frame when the transform was recalculated public uint Frame; + public EcsEntity Parent + { + get => _parent; + set mut + { + if (_parent == value) + return; + + _parent = value; + IsDirty = true; + } + } + public Matrix LocalTransform { get => _localTransform; @@ -55,6 +72,24 @@ namespace GlitchyEngine.World _rotation = value; IsDirty = true; + + _editorRotationEuler = Quaternion.ToEulerAngles(_rotation); + } + } + + /// Allows the user to edit the euler angles in the editor without rotations getting funky because of singularities or ambiguity of angles. + internal Vector3 EditorRotationEuler + { + get => _editorRotationEuler; + set mut + { + if (_editorRotationEuler == value) + return; + + _editorRotationEuler = value; + + _rotation = Quaternion.FromEulerAngles(_editorRotationEuler.Y, _editorRotationEuler.X, _editorRotationEuler.Z); + IsDirty = true; } } @@ -65,16 +100,7 @@ namespace GlitchyEngine.World public Vector3 RotationEuler { get => Quaternion.ToEulerAngles(_rotation); - set mut - { - Quaternion quat = Quaternion.FromEulerAngles(value.Y, value.X, value.Z); - - if(_rotation == quat) - return; - - _rotation = quat; - IsDirty = true; - } + set mut => Rotation = Quaternion.FromEulerAngles(value.Y, value.X, value.Z); } /** diff --git a/GlitchyEngine/src/World/TransformSystem.bf b/GlitchyEngine/src/World/TransformSystem.bf index e3afb5c..f8e485e 100644 --- a/GlitchyEngine/src/World/TransformSystem.bf +++ b/GlitchyEngine/src/World/TransformSystem.bf @@ -26,7 +26,7 @@ namespace GlitchyEngine.World transform.Frame = _frame; - var parent = world.GetComponent(entity); + //var parent = world.GetComponent(entity); if(transform.IsDirty) { @@ -35,18 +35,16 @@ namespace GlitchyEngine.World transform.IsDirty = false; - if(parent == null) + if(transform.Parent == EcsEntity.InvalidEntity) { transform.WorldTransform = transform.LocalTransform; } } - if(parent != null) + if(transform.Parent != EcsEntity.InvalidEntity) { - var parentEntity = parent.Entity; - - var parentTransform = world.GetComponent(parentEntity); - UpdateEntity(parentEntity, parentTransform, world); + var parentTransform = world.GetComponent(transform.Parent); + UpdateEntity(transform.Parent, parentTransform, world); // TODO: I think we unnecessarily recalculate world transform every frame // Parent transform is newer than our transform or was updated this frame