diff --git a/Editor/Editor/EditorLayer.cpp b/Editor/Editor/EditorLayer.cpp index 683e33a..6be88fb 100644 --- a/Editor/Editor/EditorLayer.cpp +++ b/Editor/Editor/EditorLayer.cpp @@ -4,6 +4,10 @@ #include "EditorLayer.h" #include "ImGuizmo.h" +#define GLM_ENABLE_EXPERIMENTAL +#include + +#include "glm/gtx/matrix_decompose.hpp" #include "Prism/Core/Input.h" #include "Prism/Renderer/Renderer2D.h" #include "Prism/Script/ScriptEngine.h" @@ -12,97 +16,131 @@ namespace Prism { enum class PropertyFlag { - None = 0, ColorProperty = 1 + None = 0, ColorProperty = 1, SliderProperty = 2, DragProperty = 4 }; + static std::tuple GetTransformDecomposition(const glm::mat4& transform) + { + glm::vec3 scale, translation, skew; + glm::vec4 perspective; + glm::quat orientation; + glm::decompose(transform, scale, orientation, translation, skew, perspective); + + return { translation, orientation, scale }; + } + bool Property(const std::string& name, bool& value) { ImGui::Text(name.c_str()); ImGui::NextColumn(); ImGui::PushItemWidth(-1); const std::string id = "##" + name; - const bool result = ImGui::Checkbox(id.c_str(), &value); + const bool isChanged = ImGui::Checkbox(id.c_str(), &value); ImGui::PopItemWidth(); ImGui::NextColumn(); - return result; + return isChanged; } - void Property(const std::string& name, float& value, const float min = -1.0f, const float max = 1.0f, PropertyFlag flags = PropertyFlag::None) + bool Property(const std::string& name, float& value, const float min = -1.0f, const float max = 1.0f, PropertyFlag flags = PropertyFlag::None) { ImGui::Text(name.c_str()); ImGui::NextColumn(); ImGui::PushItemWidth(-1); const std::string id = "##" + name; - ImGui::SliderFloat(id.c_str(), &value, min, max); + + bool isChanged = false; + if (flags == PropertyFlag::SliderProperty) + isChanged = ImGui::SliderFloat(id.c_str(), &value, min, max); + else + isChanged = ImGui::DragFloat(id.c_str(), &value, 1.0f, min, max); ImGui::PopItemWidth(); ImGui::NextColumn(); + + return isChanged; } - void Property(const std::string& name, glm::vec3& value, const float min = -1.0f, const float max = 1.0f, PropertyFlag flags = PropertyFlag::None) + bool Property(const std::string& name, glm::vec3& value, const float min = -1.0f, const float max = 1.0f, PropertyFlag flags = PropertyFlag::None) { ImGui::Text(name.c_str()); ImGui::NextColumn(); ImGui::PushItemWidth(-1); std::string id = "##" + name; - if ((int)flags & (int)PropertyFlag::ColorProperty) - ImGui::ColorEdit3(id.c_str(), glm::value_ptr(value), ImGuiColorEditFlags_NoInputs); + bool isChanged = false; + if (flags == PropertyFlag::ColorProperty) + isChanged = ImGui::ColorEdit3(id.c_str(), glm::value_ptr(value), ImGuiColorEditFlags_NoInputs); + else if (flags == PropertyFlag::SliderProperty) + isChanged = ImGui::SliderFloat3(id.c_str(), glm::value_ptr(value), min, max); else - ImGui::SliderFloat3(id.c_str(), glm::value_ptr(value), min, max); + isChanged = ImGui::DragFloat3(id.c_str(), glm::value_ptr(value), 1.0f, min, max); ImGui::PopItemWidth(); ImGui::NextColumn(); + + return isChanged; } - void Property(const std::string& name, glm::vec3& value, PropertyFlag flags) + bool Property(const std::string& name, glm::vec3& value, PropertyFlag flags) { - Property(name, value, -1.0f, 1.0f, flags); + return Property(name, value, -1.0f, 1.0f, flags); } - void Property(const std::string& name, glm::vec4& value, const float min = -1.0f, const float max = 1.0f, PropertyFlag flags = PropertyFlag::None) + bool Property(const std::string& name, glm::vec4& value, const float min = -1.0f, const float max = 1.0f, PropertyFlag flags = PropertyFlag::None) { ImGui::Text(name.c_str()); ImGui::NextColumn(); ImGui::PushItemWidth(-1); std::string id = "##" + name; - if ((int)flags & (int)PropertyFlag::ColorProperty) - ImGui::ColorEdit4(id.c_str(), glm::value_ptr(value), ImGuiColorEditFlags_NoInputs); + bool isChanged = false; + + if (flags == PropertyFlag::ColorProperty) + isChanged = ImGui::ColorEdit4(id.c_str(), glm::value_ptr(value), ImGuiColorEditFlags_NoInputs); + else if (flags == PropertyFlag::SliderProperty) + isChanged = ImGui::SliderFloat4(id.c_str(), glm::value_ptr(value), min, max); else - ImGui::SliderFloat4(id.c_str(), glm::value_ptr(value), min, max); + isChanged = ImGui::DragFloat4(id.c_str(), glm::value_ptr(value), 1.0f, min, max); ImGui::PopItemWidth(); ImGui::NextColumn(); + + return isChanged; } - void Property(const std::string& name, glm::vec4& value, const PropertyFlag flags) + bool Property(const std::string& name, glm::vec4& value, const PropertyFlag flags) { - Property(name, value, -1.0f, 1.0f, flags); + return Property(name, value, -1.0f, 1.0f, flags); } - void Property(const std::string& name, glm::vec2& value, const float min, const float max, PropertyFlag flags) + bool Property(const std::string& name, glm::vec2& value, const float min, const float max, PropertyFlag flags) { ImGui::Text(name.c_str()); ImGui::NextColumn(); ImGui::PushItemWidth(-1); const std::string id = "##" + name; - ImGui::SliderFloat2(id.c_str(), glm::value_ptr(value), min, max); + bool isChanged = false; + if (flags == PropertyFlag::SliderProperty) + isChanged = ImGui::SliderFloat2(id.c_str(), glm::value_ptr(value), min, max); + else + isChanged = ImGui::DragFloat2(id.c_str(), glm::value_ptr(value), 1.0f, min, max); ImGui::PopItemWidth(); ImGui::NextColumn(); + + return isChanged; } - void Property(const std::string& name, glm::vec2& value, const PropertyFlag flags) + bool Property(const std::string& name, glm::vec2& value, const PropertyFlag flags) { - Property(name, value, -1.0f, 1.0f, flags); + return Property(name, value, -1.0f, 1.0f, flags); } @@ -139,7 +177,7 @@ namespace Prism m_SceneHierarchyPanel = CreateScope(m_EditorScene); m_SceneHierarchyPanel->SetSelectionChangedCallback(std::bind(&EditorLayer::SelectEntity, this, std::placeholders::_1)); m_SceneHierarchyPanel->SetEntityDeletedCallback(std::bind(&EditorLayer::OnEntityDeleted, this, std::placeholders::_1)); - + UpdateWindowTitle("untitled Scene"); } void EditorLayer::OnDetach() @@ -152,7 +190,7 @@ namespace Prism { case SceneState::Edit: { - if (m_ViewportPanelFocused) + // if (m_ViewportPanelFocused) m_EditorCamera.OnUpdate(deltaTime); m_EditorScene->OnRenderEditor(deltaTime, m_EditorCamera); @@ -167,7 +205,7 @@ namespace Prism Renderer::EndRenderPass(); } - if (m_SelectionContext.size() && false) + if (!m_SelectionContext.empty() && false) { auto& selection = m_SelectionContext[0]; @@ -182,7 +220,26 @@ namespace Prism Renderer::EndRenderPass(); } } - break; + + if (!m_SelectionContext.empty()) + { + auto& selection = m_SelectionContext[0]; + + if (selection.Entity.HasComponent()) + { + const auto& size = selection.Entity.GetComponent().Size; + auto [translation, rotationQuat, scale] = GetTransformDecomposition(selection.Entity.GetComponent().Transform); + const glm::vec3 rotation = glm::eulerAngles(rotationQuat); + + Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false); + auto viewProj = m_EditorCamera.GetViewProjection(); + Renderer2D::BeginScene(viewProj, false); + Renderer2D::DrawRotatedQuad({ translation.x, translation.y }, size * 2.0f, glm::degrees(rotation.z), { 1.0f, 0.0f, 1.0f, 1.0f }); + Renderer2D::EndScene(); + Renderer::EndRenderPass(); + } + } + break; } case SceneState::Play: @@ -209,7 +266,6 @@ namespace Prism void EditorLayer::OnImGuiRender() { -#if ENABLE_DOCKSPACE static bool p_open = true; static bool opt_fullscreen = true; @@ -284,6 +340,9 @@ namespace Prism SceneSerializer serializer(newScene); serializer.Deserialize(filepath); m_EditorScene = newScene; + std::filesystem::path path = filepath; + UpdateWindowTitle(path.filename().string()); + m_SceneHierarchyPanel->SetContext(m_EditorScene); ScriptEngine::SetSceneContext(m_EditorScene); @@ -297,28 +356,82 @@ namespace Prism std::string filepath = app.SaveFile(R"(Scene file (*.hsc)*.hsc)"); SceneSerializer serializer(m_EditorScene); serializer.Serialize(filepath); + + std::filesystem::path path = filepath; + UpdateWindowTitle(path.filename().string()); } ImGui::Separator(); + /* if (ImGui::MenuItem("Reload C# Assembly")) ScriptEngine::ReloadAssembly("assets/scripts/ExampleApp.dll"); + */ ImGui::Separator(); if (ImGui::MenuItem("Exit")) p_open = false; ImGui::EndMenu(); } + if (ImGui::BeginMenu("Script")) + { + if (ImGui::MenuItem("Reload C# Assembly")) + ScriptEngine::ReloadAssembly("assets/scripts/ExampleApp.dll"); + + ImGui::MenuItem("Reload assembly on play", nullptr, &m_ReloadScriptOnPlay); + ImGui::EndMenu(); + } + ImGui::EndMenuBar(); } m_SceneHierarchyPanel->OnImGuiRender(); + ImGui::Begin("Materials"); + + if (!m_SelectionContext.empty()) + { + Entity selectedEntity = m_SelectionContext.front().Entity; + if (selectedEntity.HasComponent()) + { + Ref mesh = selectedEntity.GetComponent().Mesh; + if (mesh) + { + const auto& materials = mesh->GetMaterials(); + static uint32_t selectedMaterialIndex = 0; + for (uint32_t i = 0; i < materials.size(); i++) + { + const auto& materialInstance = materials[i]; + + ImGuiTreeNodeFlags node_flags = (selectedMaterialIndex == i ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_Leaf; + bool opened = ImGui::TreeNodeEx((void*)(&materialInstance), node_flags, "%s", materialInstance->GetName().c_str()); + if (ImGui::IsItemClicked()) + { + selectedMaterialIndex = i; + } + if (opened) + ImGui::TreePop(); + + } + + ImGui::Separator(); + + if (selectedMaterialIndex < materials.size()) + { + ImGui::Text("Shader: %s", materials[selectedMaterialIndex]->GetShader()->GetName().c_str()); + } + } + } + } + + ImGui::End(); + + + ScriptEngine::OnImGuiRender(); ImGui::End(); -#endif // Editor Panel ------------------------------------------------------------------------------ ImGui::Begin("Model"); @@ -338,13 +451,30 @@ namespace Prism ImGui::AlignTextToFramePadding(); auto& light = m_EditorScene->GetLight(); - Property("Light Direction", light.Direction); + Property("Light Direction", light.Direction, PropertyFlag::SliderProperty); Property("Light Radiance", light.Radiance, PropertyFlag::ColorProperty); - Property("Light Multiplier", light.Multiplier, 0.0f, 5.0f); - Property("Exposure", m_EditorCamera.GetExposure(), 0.0f, 5.0f); + Property("Light Multiplier", light.Multiplier, 0.0f, 5.0f, PropertyFlag::SliderProperty); + Property("Exposure", m_EditorCamera.GetExposure(), 0.0f, 5.0f, PropertyFlag::SliderProperty); Property("Radiance Prefiltering", m_RadiancePrefilter); - Property("Env Map Rotation", m_EnvMapRotation, -360.0f, 360.0f); + Property("Env Map Rotation", m_EnvMapRotation, -360.0f, 360.0f, PropertyFlag::SliderProperty); + + if (m_SceneState == SceneState::Edit) + { + float physics2DGravity = m_EditorScene->GetPhysics2DGravity(); + if (Property("Gravity", physics2DGravity, -10000.0f, 10000.0f, PropertyFlag::DragProperty)) + { + m_EditorScene->SetPhysics2DGravity(physics2DGravity); + } + } + else if (m_SceneState == SceneState::Play) + { + float physics2DGravity = m_RuntimeScene->GetPhysics2DGravity(); + if (Property("Gravity", physics2DGravity, -10000.0f, 10000.0f, PropertyFlag::DragProperty)) + { + m_RuntimeScene->SetPhysics2DGravity(physics2DGravity); + } + } if (Property("Show Bounding Boxes", m_UIShowBoundingBoxes)) ShowBoundingBoxes(m_UIShowBoundingBoxes, m_UIShowBoundingBoxesOnTop); @@ -732,7 +862,8 @@ namespace Prism bool EditorLayer::OnMouseButtonPressedEvent(MouseButtonPressedEvent& e) { auto [mx, my] = Input::GetMousePosition(); - if (e.GetMouseButton() == PM_MOUSE_BUTTON_LEFT && !Input::IsKeyPressed(KeyCode::LEFT_ALT) && !ImGuizmo::IsOver()) + + if (e.GetMouseButton() == PM_MOUSE_BUTTON_LEFT && !Input::IsKeyPressed(KeyCode::LEFT_ALT) && !ImGuizmo::IsOver() && m_SceneState != SceneState::Play) { auto [mouseX, mouseY] = GetMouseViewportSpace(); if (mouseX > -1.0f && mouseX < 1.0f && mouseY > -1.0f && mouseY < 1.0f) @@ -809,6 +940,13 @@ namespace Prism m_EditorScene->SetSelectedEntity(entity); } + void EditorLayer::UpdateWindowTitle(const std::string &sceneName) + { + + const std::string title = sceneName + " - Prism - " + Application::GetPlatformName() + " (" + Application::GetConfigurationName() + ")"; + Application::Get().GetWindow().SetTitle(title); + } + std::pair EditorLayer::GetMouseViewportSpace() const { auto [mx, my] = ImGui::GetMousePos(); // Input::GetMousePosition(); @@ -866,6 +1004,9 @@ namespace Prism m_SceneState = SceneState::Play; + if (m_ReloadScriptOnPlay) + ScriptEngine::ReloadAssembly("assets/scripts/ExampleApp.dll"); + m_RuntimeScene = Ref::Create(); m_EditorScene->CopyTo(m_RuntimeScene); diff --git a/Editor/Editor/EditorLayer.h b/Editor/Editor/EditorLayer.h index 03530df..0c792db 100644 --- a/Editor/Editor/EditorLayer.h +++ b/Editor/Editor/EditorLayer.h @@ -28,6 +28,8 @@ namespace Prism void ShowBoundingBoxes(bool show, bool onTop = false); void SelectEntity(Entity entity); + + void UpdateWindowTitle(const std::string& sceneName); private: std::pair GetMouseViewportSpace() const; std::pair CastRay(float mx, float my); @@ -49,6 +51,7 @@ namespace Prism Ref m_ActiveScene; Ref m_RuntimeScene, m_EditorScene; + bool m_ReloadScriptOnPlay = false; EditorCamera m_EditorCamera; diff --git a/Editor/assets/meshes/Cube1m.fbx b/Editor/assets/meshes/Cube1m.fbx new file mode 100644 index 0000000..4673f26 Binary files /dev/null and b/Editor/assets/meshes/Cube1m.fbx differ diff --git a/Editor/assets/meshes/Sphere1m.fbx b/Editor/assets/meshes/Sphere1m.fbx index cfe36ea..06d1a46 100644 Binary files a/Editor/assets/meshes/Sphere1m.fbx and b/Editor/assets/meshes/Sphere1m.fbx differ diff --git a/Editor/assets/scenes/Physics2DTest.hsc b/Editor/assets/scenes/Physics2DTest.hsc new file mode 100644 index 0000000..f8b607a --- /dev/null +++ b/Editor/assets/scenes/Physics2DTest.hsc @@ -0,0 +1,174 @@ +Scene: Scene Name +Environment: + AssetPath: assets/env/pink_sunrise_4k.hdr + Light: + Direction: [-0.787, -0.73299998, 1] + Radiance: [1, 1, 1] + Multiplier: 0.514999986 +Entities: + - Entity: 15861629587505754 + TagComponent: + Tag: Box + TransformComponent: + Position: [-18.2095661, 39.2518234, 0] + Rotation: [0.967056513, 0, 0, -0.254561812] + Scale: [4.47999525, 4.47999525, 4.48000002] + MeshComponent: + AssetPath: assets/meshes/Cube1m.fbx + RigidBody2DComponent: + BodyType: 1 + Mass: 1 + BoxCollider2DComponent: + Offset: [0, 0] + Size: [2.24000001, 2.24000001] + - Entity: 15223077898852293773 + TagComponent: + Tag: Box + TransformComponent: + Position: [5.37119865, 43.8762894, 0] + Rotation: [0.977883637, 0, 0, -0.209149718] + Scale: [4.47999668, 4.47999668, 4.48000002] + MeshComponent: + AssetPath: assets/meshes/Cube1m.fbx + RigidBody2DComponent: + BodyType: 1 + Mass: 1 + BoxCollider2DComponent: + Offset: [0, 0] + Size: [2.24000001, 2.24000001] + - Entity: 2157107598622182863 + TagComponent: + Tag: Box + TransformComponent: + Position: [-7.60411549, 44.1442184, 0] + Rotation: [0.989285827, 0, 0, 0.145991713] + Scale: [4.47999287, 4.47999287, 4.48000002] + MeshComponent: + AssetPath: assets/meshes/Cube1m.fbx + RigidBody2DComponent: + BodyType: 1 + Mass: 0.5 + BoxCollider2DComponent: + Offset: [0, 0] + Size: [2.24000001, 2.24000001] + - Entity: 8080964283681139153 + TagComponent: + Tag: Box + TransformComponent: + Position: [-0.739211679, 37.7653275, 0] + Rotation: [0.956475914, 0, 0, -0.291811317] + Scale: [5, 2, 2] + MeshComponent: + AssetPath: assets/meshes/Cube1m.fbx + RigidBody2DComponent: + BodyType: 1 + Mass: 0.25 + BoxCollider2DComponent: + Offset: [0, 0] + Size: [2.5, 1] + - Entity: 1352995477042327524 + TagComponent: + Tag: Box + TransformComponent: + Position: [-8.32969856, 30.4078159, 0] + Rotation: [0.781595349, 0, 0, 0.623785794] + Scale: [14.000001, 4.47999334, 4.48000002] + MeshComponent: + AssetPath: assets/meshes/Cube1m.fbx + RigidBody2DComponent: + BodyType: 1 + Mass: 3 + BoxCollider2DComponent: + Offset: [0, 0] + Size: [7, 2.24000001] + - Entity: 935615878363259513 + TagComponent: + Tag: Box + TransformComponent: + Position: [6.88031197, 31.942337, 0] + Rotation: [0.986578286, 0, 0, 0.163288936] + Scale: [4.47999954, 4.47999954, 4.48000002] + MeshComponent: + AssetPath: assets/meshes/Cube1m.fbx + RigidBody2DComponent: + BodyType: 1 + Mass: 1 + BoxCollider2DComponent: + Offset: [0, 0] + Size: [2.24000001, 2.24000001] + - Entity: 14057422478420564497 + TagComponent: + Tag: Player + TransformComponent: + Position: [0, 22.774044, 0] + Rotation: [0.942591429, 0, 0, -0.333948225] + Scale: [6.00000048, 6.00000048, 4.48000002] + ScriptComponent: + ModuleName: Example.PlayerCube + StoredFields: + - Name: HorizontalForce + Type: 1 + Data: 10 + - Name: VerticalForce + Type: 1 + Data: 10 + MeshComponent: + AssetPath: assets/meshes/Sphere1m.fbx + RigidBody2DComponent: + BodyType: 1 + Mass: 1 + CircleCollider2DComponent: + Offset: [0, 0] + Radius: 3 + - Entity: 1289165777996378215 + TagComponent: + Tag: Cube + TransformComponent: + Position: [0, 0, 0] + Rotation: [1, 0, 0, 0] + Scale: [50, 1, 50] + ScriptComponent: + ModuleName: Example.Sink + StoredFields: + - Name: SinkSpeed + Type: 1 + Data: 0 + MeshComponent: + AssetPath: assets/meshes/Cube1m.fbx + RigidBody2DComponent: + BodyType: 0 + Mass: 1 + BoxCollider2DComponent: + Offset: [0, 0] + Size: [25, 0.5] + - Entity: 5178862374589434728 + TagComponent: + Tag: Camera + TransformComponent: + Position: [0, 25, 79.75] + Rotation: [0.995602965, -0.0936739072, 0, 0] + Scale: [1, 0.999999821, 0.999999821] + ScriptComponent: + ModuleName: Example.BasicController + StoredFields: + - Name: Speed + Type: 1 + Data: 12 + CameraComponent: + Camera: some camera data... + Primary: true + - Entity: 3948844418381294888 + TagComponent: + Tag: Box + TransformComponent: + Position: [-1.48028564, 49.5945244, -2.38418579e-07] + Rotation: [0.977883637, 0, 0, -0.209149733] + Scale: [1.99999976, 1.99999976, 2] + MeshComponent: + AssetPath: assets/meshes/Cube1m.fbx + RigidBody2DComponent: + BodyType: 1 + Mass: 1 + BoxCollider2DComponent: + Offset: [0, 0] + Size: [1, 1] \ No newline at end of file diff --git a/ExampleApp/Src/PlayerCube.cs b/ExampleApp/Src/PlayerCube.cs new file mode 100644 index 0000000..7979007 --- /dev/null +++ b/ExampleApp/Src/PlayerCube.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Prism; + +namespace Example +{ + class PlayerCube : Entity + { + public float HorizontalForce = 10.0f; + public float VerticalForce = 10.0f; + + private RigidBody2DComponent m_PhysicsBody; + private MaterialInstance m_MeshMaterial; + + void OnCreate() + { + m_PhysicsBody = GetComponent(); + + MeshComponent meshComponent = GetComponent(); + m_MeshMaterial = meshComponent.Mesh.GetMaterial(0); + m_MeshMaterial.Set("u_Metalness", 0.0f); + } + + void OnUpdate(float ts) + { + if (Input.IsKeyPressed(KeyCode.D)) + m_PhysicsBody.ApplyLinearImpulse(new Vec2(HorizontalForce, 0), new Vec2(), true); + else if (Input.IsKeyPressed(KeyCode.A)) + m_PhysicsBody.ApplyLinearImpulse(new Vec2(-HorizontalForce, 0), new Vec2(), true); + + if (Input.IsKeyPressed(KeyCode.Space)) + m_PhysicsBody.ApplyLinearImpulse(new Vec2(0, VerticalForce), new Vec2(0, -10), true); + + Vec3 color = new Vec3(0.8f, 0.8f, 0.8f); + if (Input.IsKeyPressed(KeyCode.Q)) + color = new Vec3(0.0f, 1.0f, 0.0f); + + m_MeshMaterial.Set("u_AlbedoColor", color); + + if (Input.IsKeyPressed(KeyCode.R)) + { + Mat4 transform = GetTransform(); + transform.Translation = new Vec3(0.0f); + SetTransform(transform); + } + + } + + } +} diff --git a/ExampleApp/Src/RandomColor.cs b/ExampleApp/Src/RandomColor.cs new file mode 100644 index 0000000..c1cc7cd --- /dev/null +++ b/ExampleApp/Src/RandomColor.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Prism; + +namespace Example +{ + class RandomColor : Entity + { + void OnCreate() + { + Random random = new Random(); + + MeshComponent meshComponent = GetComponent(); + MaterialInstance material = meshComponent.Mesh.GetMaterial(0); + float r = (float)random.NextDouble(); + float g = (float)random.NextDouble(); + float b = (float)random.NextDouble(); + material.Set("u_AlbedoColor", new Vec3(r, g, b)); + } + + } +} diff --git a/Prism-ScriptCore/Src/Prism/Renderer/Material.cs b/Prism-ScriptCore/Src/Prism/Renderer/Material.cs index b805379..dbc2d12 100644 --- a/Prism-ScriptCore/Src/Prism/Renderer/Material.cs +++ b/Prism-ScriptCore/Src/Prism/Renderer/Material.cs @@ -57,6 +57,10 @@ namespace Prism SetVec3_Native(m_UnmanagedInstance, uniform, ref value); } + public void Set(string uniform, Vec4 value) + { + SetVec4_Native(m_UnmanagedInstance, uniform, ref value); + } public void SetTexture(string uniform, Texture2D texture) { @@ -82,6 +86,8 @@ namespace Prism [MethodImpl(MethodImplOptions.InternalCall)] public static extern void SetVec3_Native(IntPtr unmanagedInstance, string uniform, ref Vec3 value); [MethodImpl(MethodImplOptions.InternalCall)] + public static extern void SetVec4_Native(IntPtr unmanagedInstance, string uniform, ref Vec4 value); + [MethodImpl(MethodImplOptions.InternalCall)] public static extern void SetTexture_Native(IntPtr unmanagedInstance, string uniform, IntPtr texture); } } diff --git a/Prism-ScriptCore/Src/Prism/Scene/Component.cs b/Prism-ScriptCore/Src/Prism/Scene/Component.cs index 8df6510..c2b21bf 100644 --- a/Prism-ScriptCore/Src/Prism/Scene/Component.cs +++ b/Prism-ScriptCore/Src/Prism/Scene/Component.cs @@ -71,10 +71,10 @@ namespace Prism } [MethodImpl(MethodImplOptions.InternalCall)] - public static extern IntPtr GetMesh_Native(ulong entityID); + internal static extern IntPtr GetMesh_Native(ulong entityID); [MethodImpl(MethodImplOptions.InternalCall)] - public static extern void SetMesh_Native(ulong entityID, IntPtr unmanagedInstance); + internal static extern void SetMesh_Native(ulong entityID, IntPtr unmanagedInstance); } @@ -92,4 +92,15 @@ namespace Prism { // TODO } + + public class RigidBody2DComponent : Component + { + public void ApplyLinearImpulse(Vec2 impulse, Vec2 offset, bool wake) + { + ApplyLinearImpulse_Native(Entity.ID, ref impulse, ref offset, wake); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void ApplyLinearImpulse_Native(ulong entityID, ref Vec2 impulse, ref Vec2 offset, bool wake); + } } diff --git a/Prism/CMakeLists.txt b/Prism/CMakeLists.txt index 04622f6..e5940fc 100644 --- a/Prism/CMakeLists.txt +++ b/Prism/CMakeLists.txt @@ -55,7 +55,6 @@ set(LINK_LIBRARIES_PRIVATE tinyFileDialogs FastNoise yaml-cpp - box2d ) set(LINK_LIBRARIES_PUBLIC @@ -63,6 +62,7 @@ set(LINK_LIBRARIES_PUBLIC glm EnTT::EnTT mono + box2d ) # link library opengl diff --git a/Prism/src/Prism/Core/Application.cpp b/Prism/src/Prism/Core/Application.cpp index 9953c6c..5beea67 100644 --- a/Prism/src/Prism/Core/Application.cpp +++ b/Prism/src/Prism/Core/Application.cpp @@ -227,4 +227,12 @@ namespace Prism { return (float)glfwGetTime(); } + + const char * Application::GetConfigurationName() { + return "Debug"; // TODO: to support Release string + } + + const char * Application::GetPlatformName() { + return "windows x64"; // TODO: to support linux platform + } } diff --git a/Prism/src/Prism/Core/Application.h b/Prism/src/Prism/Core/Application.h index fb131fb..ae2fd61 100644 --- a/Prism/src/Prism/Core/Application.h +++ b/Prism/src/Prism/Core/Application.h @@ -44,11 +44,15 @@ namespace Prism void PushLayer(Layer* layer); void PushOverlay(Layer* layer); + + float GetTime() const; // TODO: should impl in platform + + static const char* GetConfigurationName(); + static const char* GetPlatformName(); private: bool OnWindowResize(const WindowResizeEvent& e); bool OnWindowClose(WindowCloseEvent& e); - float GetTime() const; // TODO: should impl in platform private: TimeStep m_TimeStep; float m_LastFrameTime = 0.0f; diff --git a/Prism/src/Prism/Core/Window.h b/Prism/src/Prism/Core/Window.h index d3f9f25..5830818 100644 --- a/Prism/src/Prism/Core/Window.h +++ b/Prism/src/Prism/Core/Window.h @@ -47,6 +47,9 @@ namespace Prism static Window* Create(const WindowProps& props); + virtual const std::string& GetTitle() const = 0; + virtual void SetTitle(const std::string& title) = 0; + virtual void* GetNativeWindow() const = 0; }; } diff --git a/Prism/src/Prism/Platform/Windows/WindowsWindow.cpp b/Prism/src/Prism/Platform/Windows/WindowsWindow.cpp index 3c4585d..cc6b6e1 100644 --- a/Prism/src/Prism/Platform/Windows/WindowsWindow.cpp +++ b/Prism/src/Prism/Platform/Windows/WindowsWindow.cpp @@ -65,6 +65,11 @@ namespace Prism return { (float)x, (float)y }; } + void WindowsWindow::SetTitle(const std::string &title) { + m_Data.Title = title; + glfwSetWindowTitle(m_Window, m_Data.Title.c_str()); + } + void WindowsWindow::Init(const WindowProps& props) { m_Data.Title = props.Title; diff --git a/Prism/src/Prism/Platform/Windows/WindowsWindow.h b/Prism/src/Prism/Platform/Windows/WindowsWindow.h index 7863ada..35282c5 100644 --- a/Prism/src/Prism/Platform/Windows/WindowsWindow.h +++ b/Prism/src/Prism/Platform/Windows/WindowsWindow.h @@ -27,6 +27,9 @@ namespace Prism virtual std::pair GetSize() const override { return { m_Data.Width, m_Data.Height }; } virtual std::pair GetWindowPos() const override; + virtual const std::string& GetTitle() const override { return m_Data.Title; } + virtual void SetTitle(const std::string& title) override; + inline void* GetNativeWindow() const override { return m_Window; } private: diff --git a/Prism/src/Prism/Renderer/Material.cpp b/Prism/src/Prism/Renderer/Material.cpp index 3df360e..a82689d 100644 --- a/Prism/src/Prism/Renderer/Material.cpp +++ b/Prism/src/Prism/Renderer/Material.cpp @@ -122,13 +122,14 @@ namespace Prism } } - MaterialInstance::MaterialInstance(const Ref& material) - : m_Material(material) + MaterialInstance::MaterialInstance(const Ref &material, const std::string &name) + : m_Material(material), m_Name(name) { m_Material->m_MaterialInstances.insert(this); AllocateStorage(); } + MaterialInstance::~MaterialInstance() { m_Material->m_MaterialInstances.erase(this); diff --git a/Prism/src/Prism/Renderer/Material.h b/Prism/src/Prism/Renderer/Material.h index d789d61..34ea1b1 100644 --- a/Prism/src/Prism/Renderer/Material.h +++ b/Prism/src/Prism/Renderer/Material.h @@ -87,7 +87,7 @@ namespace Prism { friend class Material; public: - MaterialInstance(const Ref& material); + MaterialInstance(const Ref& material, const std::string& name = ""); virtual ~MaterialInstance(); static Ref Create(const Ref& material); @@ -128,7 +128,8 @@ namespace Prism bool GetFlag(MaterialFlag flag) const { return (uint32_t)flag & m_Material->m_MaterialFlags; } void SetFlag(MaterialFlag flag, bool value = true); - RefGetShader() { return m_Material->m_Shader; } + Ref GetShader() const { return m_Material->m_Shader; } + const std::string& GetName() const { return m_Name; } private: void AllocateStorage(); void OnShaderReloaded(); @@ -136,6 +137,7 @@ namespace Prism void OnMaterialValueUpdated(ShaderUniformDeclaration* decl); private: Ref m_Material; + std::string m_Name; Buffer m_VSUniformStorageBuffer; Buffer m_PSUniformStorageBuffer; diff --git a/Prism/src/Prism/Renderer/Mesh.cpp b/Prism/src/Prism/Renderer/Mesh.cpp index fa32c26..f279090 100644 --- a/Prism/src/Prism/Renderer/Mesh.cpp +++ b/Prism/src/Prism/Renderer/Mesh.cpp @@ -259,7 +259,7 @@ namespace Prism auto aiMaterial = scene->mMaterials[i]; auto aiMaterialName = aiMaterial->GetName(); - auto mi = Ref::Create(m_BaseMaterial); + auto mi = Ref::Create(m_BaseMaterial, aiMaterialName.data); m_Materials[i] = mi; PM_MESH_LOG(" {0} (Index = {1})", aiMaterialName.data, i); @@ -690,9 +690,8 @@ namespace Prism PM_CORE_ASSERT(NextPositionIndex < nodeAnim->mNumPositionKeys); float DeltaTime = (float)(nodeAnim->mPositionKeys[NextPositionIndex].mTime - nodeAnim->mPositionKeys[PositionIndex].mTime); float Factor = (animationTime - (float)nodeAnim->mPositionKeys[PositionIndex].mTime) / DeltaTime; - if (Factor < 0.0f) - Factor = 0.0f; PM_CORE_ASSERT(Factor <= 1.0f, "Factor must be below 1.0f"); + Factor = glm::clamp(Factor, 0.0f, 1.0f); const aiVector3D& Start = nodeAnim->mPositionKeys[PositionIndex].mValue; const aiVector3D& End = nodeAnim->mPositionKeys[NextPositionIndex].mValue; aiVector3D Delta = End - Start; @@ -714,9 +713,8 @@ namespace Prism PM_CORE_ASSERT(NextRotationIndex < nodeAnim->mNumRotationKeys); float DeltaTime = (float)(nodeAnim->mRotationKeys[NextRotationIndex].mTime - nodeAnim->mRotationKeys[RotationIndex].mTime); float Factor = (animationTime - (float)nodeAnim->mRotationKeys[RotationIndex].mTime) / DeltaTime; - if (Factor < 0.0f) - Factor = 0.0f; PM_CORE_ASSERT(Factor <= 1.0f, "Factor must be below 1.0f"); + Factor = glm::clamp(Factor, 0.0f, 1.0f); const aiQuaternion& StartRotationQ = nodeAnim->mRotationKeys[RotationIndex].mValue; const aiQuaternion& EndRotationQ = nodeAnim->mRotationKeys[NextRotationIndex].mValue; auto q = aiQuaternion(); @@ -739,9 +737,8 @@ namespace Prism PM_CORE_ASSERT(nextIndex < nodeAnim->mNumScalingKeys); float deltaTime = (float)(nodeAnim->mScalingKeys[nextIndex].mTime - nodeAnim->mScalingKeys[index].mTime); float factor = (animationTime - (float)nodeAnim->mScalingKeys[index].mTime) / deltaTime; - if (factor < 0.0f) - factor = 0.0f; PM_CORE_ASSERT(factor <= 1.0f, "Factor must be below 1.0f"); + factor = glm::clamp(factor, 0.0f, 1.0f); const auto& start = nodeAnim->mScalingKeys[index].mValue; const auto& end = nodeAnim->mScalingKeys[nextIndex].mValue; auto delta = end - start; diff --git a/Prism/src/Prism/Renderer/Renderer2D.cpp b/Prism/src/Prism/Renderer/Renderer2D.cpp index ed9941e..2d84634 100644 --- a/Prism/src/Prism/Renderer/Renderer2D.cpp +++ b/Prism/src/Prism/Renderer/Renderer2D.cpp @@ -378,7 +378,7 @@ namespace Prism * glm::rotate(glm::mat4(1.0f), glm::radians(rotation), { 0.0f, 0.0f, 1.0f }) * glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }); - for (uint32_t i = 1; i < 4; i++) + for (uint32_t i = 0; i < 4; i++) { s_Data.QuadVertexBufferPtr->Position = transform * s_Data.QuadVertexPositions[i]; s_Data.QuadVertexBufferPtr->Color = color; @@ -426,7 +426,7 @@ namespace Prism * glm::rotate(glm::mat4(1.0f), glm::radians(rotation), { 0.0f, 0.0f, 1.0f }) * glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }); - for (uint32_t i = 1; i < 4; i++) + for (uint32_t i = 0; i < 4; i++) { s_Data.QuadVertexBufferPtr->Position = transform * s_Data.QuadVertexPositions[i]; s_Data.QuadVertexBufferPtr->Color = color; diff --git a/Prism/src/Prism/Scene/Components.h b/Prism/src/Prism/Scene/Components.h index ec32bbe..92d333b 100644 --- a/Prism/src/Prism/Scene/Components.h +++ b/Prism/src/Prism/Scene/Components.h @@ -8,6 +8,7 @@ #include #include "SceneCamera.h" +#include "box2d/id.h" #include "glm/glm.hpp" #include "Prism/Core/Ref.h" #include "Prism/Core/UUID.h" @@ -101,6 +102,46 @@ namespace Prism SpriteRendererComponent(const SpriteRendererComponent& other) : Color(other.Color), Texture(other.Texture), TilingFactor(other.TilingFactor) {} }; + + struct RigidBody2DComponent + { + enum class Type { Static, Dynamic, Kinematic }; + Type BodyType; + float Mass = 1.0f; + + // Storage for BodyID (box2d version 3.0^ use handle to resolve this) + b2BodyId RuntimeBodyID = b2_nullBodyId; + + RigidBody2DComponent() = default; + RigidBody2DComponent(const RigidBody2DComponent& other) + : BodyType(other.BodyType), Mass(other.Mass) {} + }; + + struct BoxCollider2DComponent + { + glm::vec2 Offset = { 0.0f,0.0f }; + glm::vec2 Size = { 1.0f, 1.0f }; + + // Storage for runtime + // void* RuntimeFixture = nullptr; + + BoxCollider2DComponent() = default; + BoxCollider2DComponent(const BoxCollider2DComponent& other) + : Offset(other.Offset), Size(other.Size) {} + }; + + struct CircleCollider2DComponent + { + glm::vec2 Offset = { 0.0f,0.0f }; + float Radius = 1.0f; + + // Storage for runtime + // void* RuntimeFixture = nullptr; + + CircleCollider2DComponent() = default; + CircleCollider2DComponent(const CircleCollider2DComponent& other) + : Offset(other.Offset), Radius(other.Radius) {} + }; } diff --git a/Prism/src/Prism/Scene/Entity.h b/Prism/src/Prism/Scene/Entity.h index cf84712..6315f5b 100644 --- a/Prism/src/Prism/Scene/Entity.h +++ b/Prism/src/Prism/Scene/Entity.h @@ -40,6 +40,12 @@ namespace Prism return m_Scene->m_Registry.storage().contains(m_EntityHandle); } + template + void RemoveComponent() const { + if (HasComponent()) + m_Scene->m_Registry.remove(m_EntityHandle); + } + glm::mat4& Transform() { return m_Scene->m_Registry.get(m_EntityHandle); } const glm::mat4& Transform() const { return m_Scene->m_Registry.get(m_EntityHandle); } diff --git a/Prism/src/Prism/Scene/Scene.cpp b/Prism/src/Prism/Scene/Scene.cpp index 93f8db8..d26cca0 100644 --- a/Prism/src/Prism/Scene/Scene.cpp +++ b/Prism/src/Prism/Scene/Scene.cpp @@ -8,6 +8,11 @@ #include "Entity.h" #include "Prism/Renderer/SceneRenderer.h" #include "Prism/Script/ScriptEngine.h" +#include + +#define GLM_ENABLE_EXPERIMENTAL +#include +#include namespace Prism { @@ -20,6 +25,18 @@ namespace Prism UUID SceneID; }; + struct Box2DWorldComponent + { + b2WorldId World; + + Box2DWorldComponent() = default; + Box2DWorldComponent(const b2Vec2& gravity) { + b2WorldDef worldDef = b2DefaultWorldDef(); + worldDef.gravity = gravity; + World = b2CreateWorld(&worldDef); + } + }; + void OnTransformConstruct(entt::registry& registry, entt::entity entity) { // HZ_CORE_TRACE("Transform Component constructed!"); @@ -38,6 +55,16 @@ namespace Prism ScriptEngine::InitScriptEntity(scene->m_EntityIDMap.at(entityID)); } + static std::tuple GetTransformDecomposition(const glm::mat4& transform) + { + glm::vec3 scale, translation, skew; + glm::vec4 perspective; + glm::quat orientation; + glm::decompose(transform, scale, orientation, translation, skew, perspective); + + return { translation, orientation, scale }; + } + Environment Environment::Load(const std::string& filepath) { auto [radiance, irradiance] = SceneRenderer::CreateEnvironmentMap(filepath); @@ -52,6 +79,8 @@ namespace Prism m_SceneEntity = m_Registry.create(); m_Registry.emplace(m_SceneEntity, m_SceneID); + // TODO: Obviously not necessary in all cases + m_Registry.emplace(m_SceneEntity, b2Vec2{ 0.0f, -9.8f }); s_ActiveScenes[m_SceneID] = this; @@ -85,6 +114,36 @@ namespace Prism ScriptEngine::OnUpdateEntity(m_SceneID, entityID, ts); } } + + // Box2D physics + + auto sceneView = m_Registry.view(); + auto& box2DWorld = m_Registry.get(sceneView.front()).World; + int32_t velocityIterations = 6; + int32_t positionIterations = 2; + // box2DWorld->Step(ts, velocityIterations, positionIterations); + b2World_Step(box2DWorld, ts, positionIterations); + + { + auto view = m_Registry.view(); + for (auto entity : view) + { + Entity e = { entity, this }; + auto& transform = e.Transform(); + const auto& rb2d = e.GetComponent(); + + const auto& position = b2Body_GetPosition(rb2d.RuntimeBodyID); + auto [translation, rotationQuat, scale] = GetTransformDecomposition(transform); + glm::vec3 rotation = glm::eulerAngles(rotationQuat); + + float angle = b2Rot_GetAngle(b2Body_GetRotation(rb2d.RuntimeBodyID)); + + transform = glm::translate(glm::mat4(1.0f), { position.x, position.y, transform[3].z }) * + glm::toMat4(glm::quat({ rotation.x, rotation.y, angle })) * + glm::scale(glm::mat4(1.0f), scale); + } + } + } void Scene::OnRenderRuntime(TimeStep ts) @@ -191,15 +250,105 @@ namespace Prism void Scene::OnRuntimeStart() { ScriptEngine::SetSceneContext(this); - - auto view = m_Registry.view(); - for (auto entity : view) { - Entity e = { entity, this }; - if (ScriptEngine::ModuleExists(e.GetComponent().ModuleName)) - ScriptEngine::InstantiateEntityClass(e); + auto view = m_Registry.view(); + for (auto entity : view) + { + Entity e = { entity, this }; + if (ScriptEngine::ModuleExists(e.GetComponent().ModuleName)) + ScriptEngine::InstantiateEntityClass(e); + } } + + // Box2D physics + auto sceneView = m_Registry.view(); + auto& world = m_Registry.get(sceneView.front()).World; + { + auto view = m_Registry.view(); + for (auto entity : view) + { + Entity e = { entity, this }; + auto& transform = e.Transform(); + auto& rigidBody2D = m_Registry.get(entity); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + if (rigidBody2D.BodyType == RigidBody2DComponent::Type::Static) + bodyDef.type = b2_staticBody; + else if (rigidBody2D.BodyType == RigidBody2DComponent::Type::Dynamic) + bodyDef.type = b2_dynamicBody; + else if (rigidBody2D.BodyType == RigidBody2DComponent::Type::Kinematic) + bodyDef.type = b2_kinematicBody; + bodyDef.position = {transform[3].x, transform[3].y}; + + auto [translation, rotationQuat, scale] = GetTransformDecomposition(transform); + float rotationZ = glm::eulerAngles(rotationQuat).z; + bodyDef.rotation = b2Rot{cos(rotationZ), sin(rotationZ)}; + + rigidBody2D.RuntimeBodyID = b2CreateBody(world, &bodyDef); + } + } + + + { + auto view = m_Registry.view(); + for (auto entity : view) + { + Entity e = { entity, this }; + auto& transform = e.Transform(); + + auto& boxCollider2D = m_Registry.get(entity); + if (e.HasComponent()) + { + const auto& rigidBody2D = e.GetComponent(); + PM_CORE_ASSERT(b2Body_IsValid(rigidBody2D.RuntimeBodyID)); + + b2BodyId bodyId = rigidBody2D.RuntimeBodyID; + + b2Polygon boxShape = b2MakeOffsetBox(boxCollider2D.Size.x, boxCollider2D.Size.y, {boxCollider2D.Offset.x,boxCollider2D.Offset.y}, {1.0f, 0.0f}); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + shapeDef.material.friction = 1.0f; + + b2CreatePolygonShape(bodyId, &shapeDef, &boxShape); + } + } + } + + { + auto view = m_Registry.view(); + for (auto entity : view) + { + Entity e = { entity, this }; + auto& transform = e.Transform(); + + auto& circleCollider2D = m_Registry.get(entity); + if (e.HasComponent()) + { + auto& rigidBody2D = e.GetComponent(); + PM_CORE_ASSERT(b2Body_IsValid(rigidBody2D.RuntimeBodyID)); + + b2BodyId bodyId = rigidBody2D.RuntimeBodyID; + + b2Vec2 centor = {circleCollider2D.Offset.x, circleCollider2D.Offset.y}; + + b2Circle circleShape{ + .center = centor, + .radius = circleCollider2D.Radius + }; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + shapeDef.density = 1.0f; + shapeDef.material.friction = 1.0f; + + b2CreateCircleShape(bodyId, &shapeDef, &circleShape); + } + } + } + + m_IsPlaying = true; } @@ -310,6 +459,9 @@ namespace Prism CopyComponentIfExists(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); CopyComponentIfExists(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); CopyComponentIfExists(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); + CopyComponentIfExists(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); + CopyComponentIfExists(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); + CopyComponentIfExists(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); } void Scene::CopyTo(Ref& target) @@ -337,10 +489,14 @@ namespace Prism CopyComponent(target->m_Registry, m_Registry, enttMap); CopyComponent(target->m_Registry, m_Registry, enttMap); CopyComponent(target->m_Registry, m_Registry, enttMap); + CopyComponent(target->m_Registry, m_Registry, enttMap); + CopyComponent(target->m_Registry, m_Registry, enttMap); + CopyComponent(target->m_Registry, m_Registry, enttMap); const auto& entityInstanceMap = ScriptEngine::GetEntityInstanceMap(); if (entityInstanceMap.find(target->GetUUID()) != entityInstanceMap.end()) ScriptEngine::CopyEntityScriptData(target->GetUUID(), m_SceneID); + target->SetPhysics2DGravity(GetPhysics2DGravity()); } Ref Scene::GetScene(const UUID& uuid) @@ -351,6 +507,17 @@ namespace Prism return {}; } + float Scene::GetPhysics2DGravity() const + { + const auto gravity = b2World_GetGravity(m_Registry.get(m_SceneEntity).World); + return gravity.y; + } + + void Scene::SetPhysics2DGravity(const float gravity) + { + b2World_SetGravity(m_Registry.get(m_SceneEntity).World, {0.0f, gravity}); + } + void Scene::DestroyEntity(Entity entity) { diff --git a/Prism/src/Prism/Scene/Scene.h b/Prism/src/Prism/Scene/Scene.h index 303219d..e93f011 100644 --- a/Prism/src/Prism/Scene/Scene.h +++ b/Prism/src/Prism/Scene/Scene.h @@ -87,6 +87,9 @@ namespace Prism static Ref GetScene(const UUID& uuid); + float GetPhysics2DGravity() const; + void SetPhysics2DGravity(float gravity); + // Editor-specific void SetSelectedEntity(entt::entity entity) { m_SelectedEntity = entity; } diff --git a/Prism/src/Prism/Scene/SceneSerializer.cpp b/Prism/src/Prism/Scene/SceneSerializer.cpp index e66558d..5a4a5bd 100644 --- a/Prism/src/Prism/Scene/SceneSerializer.cpp +++ b/Prism/src/Prism/Scene/SceneSerializer.cpp @@ -268,7 +268,7 @@ namespace Prism out << YAML::Key << "CameraComponent"; out << YAML::BeginMap; // CameraComponent - auto cameraComponent = entity.GetComponent(); + const auto& cameraComponent = entity.GetComponent(); out << YAML::Key << "Camera" << YAML::Value << "some camera data..."; out << YAML::Key << "Primary" << YAML::Value << cameraComponent.Primary; @@ -280,7 +280,7 @@ namespace Prism out << YAML::Key << "SpriteRendererComponent"; out << YAML::BeginMap; // SpriteRendererComponent - auto spriteRendererComponent = entity.GetComponent(); + const auto& spriteRendererComponent = entity.GetComponent(); out << YAML::Key << "Color" << YAML::Value << spriteRendererComponent.Color; if (spriteRendererComponent.Texture) out << YAML::Key << "TextureAssetPath" << YAML::Value << "path/to/asset"; @@ -289,6 +289,42 @@ namespace Prism out << YAML::EndMap; // SpriteRendererComponent } + if (entity.HasComponent()) + { + out << YAML::Key << "RigidBody2DComponent"; + out << YAML::BeginMap; // RigidBody2DComponent + + const auto& rigidbody2DComponent = entity.GetComponent(); + out << YAML::Key << "BodyType" << YAML::Value << (int)rigidbody2DComponent.BodyType; + out << YAML::Key << "Mass" << YAML::Value << rigidbody2DComponent.Mass; + + out << YAML::EndMap; // RigidBody2DComponent + } + + if (entity.HasComponent()) + { + out << YAML::Key << "BoxCollider2DComponent"; + out << YAML::BeginMap; // BoxCollider2DComponent + + const auto& boxCollider2DComponent = entity.GetComponent(); + out << YAML::Key << "Offset" << YAML::Value << boxCollider2DComponent.Offset; + out << YAML::Key << "Size" << YAML::Value << boxCollider2DComponent.Size; + + out << YAML::EndMap; // BoxCollider2DComponent + } + + if (entity.HasComponent()) + { + out << YAML::Key << "CircleCollider2DComponent"; + out << YAML::BeginMap; // CircleCollider2DComponent + + const auto& circleCollider2DComponent = entity.GetComponent(); + out << YAML::Key << "Offset" << YAML::Value << circleCollider2DComponent.Offset; + out << YAML::Key << "Radius" << YAML::Value << circleCollider2DComponent.Radius; + + out << YAML::EndMap; // CircleCollider2DComponent + } + out << YAML::EndMap; // Entity } @@ -470,8 +506,7 @@ namespace Prism } } - auto meshComponent = entity["MeshComponent"]; - if (meshComponent) + if (auto meshComponent = entity["MeshComponent"]) { std::string meshPath = meshComponent["AssetPath"].as(); // TEMP (because script creates mesh component...) @@ -481,8 +516,7 @@ namespace Prism PM_CORE_INFO(" Mesh Asset Path: {0}", meshPath); } - auto cameraComponent = entity["CameraComponent"]; - if (cameraComponent) + if (auto cameraComponent = entity["CameraComponent"]) { auto& component = deserializedEntity.AddComponent(); component.Camera = SceneCamera(); @@ -491,8 +525,7 @@ namespace Prism PM_CORE_INFO(" Primary Camera: {0}", component.Primary); } - auto spriteRendererComponent = entity["SpriteRendererComponent"]; - if (spriteRendererComponent) + if (auto spriteRendererComponent = entity["SpriteRendererComponent"]) { auto& component = deserializedEntity.AddComponent(); component.Color = spriteRendererComponent["Color"].as(); @@ -500,6 +533,27 @@ namespace Prism PM_CORE_INFO(" SpriteRendererComponent present."); } + + if (auto rigidBody2DComponent = entity["RigidBody2DComponent"]) + { + auto& component = deserializedEntity.AddComponent(); + component.BodyType = (RigidBody2DComponent::Type)rigidBody2DComponent["BodyType"].as(); + component.Mass = rigidBody2DComponent["Mass"].as(); + } + + if (auto boxCollider2DComponent = entity["BoxCollider2DComponent"]) + { + auto& component = deserializedEntity.AddComponent(); + component.Offset = boxCollider2DComponent["Offset"].as(); + component.Size = boxCollider2DComponent["Size"].as(); + } + + if (auto circleCollider2DComponent = entity["CircleCollider2DComponent"]) + { + auto& component = deserializedEntity.AddComponent(); + component.Offset = circleCollider2DComponent["Offset"].as(); + component.Radius = circleCollider2DComponent["Radius"].as(); + } } } return true; diff --git a/Prism/src/Prism/Script/ScriptEngineRegistry.cpp b/Prism/src/Prism/Script/ScriptEngineRegistry.cpp index 18c2689..a4528bf 100644 --- a/Prism/src/Prism/Script/ScriptEngineRegistry.cpp +++ b/Prism/src/Prism/Script/ScriptEngineRegistry.cpp @@ -38,6 +38,8 @@ namespace Prism Component_RegisterType(ScriptComponent); Component_RegisterType(CameraComponent); Component_RegisterType(SpriteRendererComponent); + Component_RegisterType(RigidBody2DComponent); + Component_RegisterType(BoxCollider2DComponent); } void ScriptEngineRegistry::RegisterAll() @@ -56,6 +58,8 @@ namespace Prism mono_add_internal_call("Prism.Input::IsKeyPressed_Native", (const void*)Prism::Script::Prism_Input_IsKeyPressed); + mono_add_internal_call("Prism.RigidBody2DComponent::ApplyLinearImpulse_Native", (const void*)Prism::Script::Prism_RigidBody2DComponent_ApplyLinearImpulse); + mono_add_internal_call("Prism.Texture2D::Constructor_Native", (const void*)Prism::Script::Prism_Texture2D_Constructor); mono_add_internal_call("Prism.Texture2D::Destructor_Native", (const void*)Prism::Script::Prism_Texture2D_Destructor); mono_add_internal_call("Prism.Texture2D::SetData_Native", (const void*)Prism::Script::Prism_Texture2D_SetData); @@ -66,7 +70,8 @@ namespace Prism mono_add_internal_call("Prism.MaterialInstance::Destructor_Native", (const void*)Prism::Script::Prism_MaterialInstance_Destructor); mono_add_internal_call("Prism.MaterialInstance::SetFloat_Native", (const void*)Prism::Script::Prism_MaterialInstance_SetFloat); - mono_add_internal_call("Prism.MaterialInstance::SetVector3_Native", (const void*)Prism::Script::Prism_MaterialInstance_SetVector3); + mono_add_internal_call("Prism.MaterialInstance::SetVec3_Native", (const void*)Prism::Script::Prism_MaterialInstance_SetVector3); + mono_add_internal_call("Prism.MaterialInstance::SetVec4_Native", (const void*)Prism::Script::Prism_MaterialInstance_SetVector4); mono_add_internal_call("Prism.MaterialInstance::SetTexture_Native", (const void*)Prism::Script::Prism_MaterialInstance_SetTexture); mono_add_internal_call("Prism.Mesh::Constructor_Native", (const void*)Prism::Script::Prism_Mesh_Constructor); diff --git a/Prism/src/Prism/Script/ScriptWarppers.cpp b/Prism/src/Prism/Script/ScriptWarppers.cpp index 7aecc4e..7cdd542 100644 --- a/Prism/src/Prism/Script/ScriptWarppers.cpp +++ b/Prism/src/Prism/Script/ScriptWarppers.cpp @@ -5,6 +5,7 @@ #include "ScriptWarppers.h" #include "ScriptEngine.h" +#include "box2d/box2d.h" #include "mono/metadata/metadata.h" #include "mono/metadata/object.h" #include "mono/metadata/reflection.h" @@ -131,6 +132,22 @@ namespace Prism { namespace Script { meshComponent.Mesh = inMesh ? *inMesh : nullptr; } + void Prism_RigidBody2DComponent_ApplyLinearImpulse(uint64_t entityID, glm::vec2 *impulse, glm::vec2 *offset, bool wake) + { + Ref scene = ScriptEngine::GetCurrentSceneContext(); + PM_CORE_ASSERT(scene, "No active scene!"); + const auto& entityMap = scene->GetEntityMap(); + PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!"); + + Entity entity = entityMap.at(entityID); + PM_CORE_ASSERT(entity.HasComponent()); + auto& component = entity.GetComponent(); + + b2BodyId body = component.RuntimeBodyID; + + b2Body_ApplyLinearImpulse(body, *(const b2Vec2*)impulse, b2Body_GetWorldCenterOfMass(body) + *(const b2Vec2*)offset, wake); + } + Ref* Prism_Mesh_Constructor(MonoString* filepath) { return new Ref(new Mesh(mono_string_to_utf8(filepath))); @@ -233,6 +250,12 @@ namespace Prism { namespace Script { instance->Set(mono_string_to_utf8(uniform), *value); } + void Prism_MaterialInstance_SetVector4(Ref *_this, MonoString *uniform, glm::vec4 *value) + { + Ref& instance = *(Ref*)_this; + instance->Set(mono_string_to_utf8(uniform), *value); + } + void Prism_MaterialInstance_SetTexture(Ref* _this, MonoString* uniform, Ref* texture) { Ref& instance = *(Ref*)_this; diff --git a/Prism/src/Prism/Script/ScriptWarppers.h b/Prism/src/Prism/Script/ScriptWarppers.h index 261616b..0b5d716 100644 --- a/Prism/src/Prism/Script/ScriptWarppers.h +++ b/Prism/src/Prism/Script/ScriptWarppers.h @@ -32,6 +32,9 @@ namespace Prism { namespace Script { void* Prism_MeshComponent_GetMesh(uint64_t entityID); void Prism_MeshComponent_SetMesh(uint64_t entityID, Ref* inMesh); + // 2D Physic + void Prism_RigidBody2DComponent_ApplyLinearImpulse(uint64_t entityID, glm::vec2* impulse, glm::vec2* offset, bool wake); + // Renderer // Texture2D void* Prism_Texture2D_Constructor(uint32_t width, uint32_t height); @@ -46,6 +49,7 @@ namespace Prism { namespace Script { void Prism_MaterialInstance_Destructor(Ref* _this); void Prism_MaterialInstance_SetFloat(Ref* _this, MonoString* uniform, float value); void Prism_MaterialInstance_SetVector3(Ref* _this, MonoString* uniform, glm::vec3* value); + void Prism_MaterialInstance_SetVector4(Ref* _this, MonoString* uniform, glm::vec4* value); void Prism_MaterialInstance_SetTexture(Ref* _this, MonoString* uniform, Ref* texture); // Mesh