diff --git a/Editor/assets/meshes/Sphere1m.fbx b/Editor/assets/meshes/Sphere1m.fbx index 06d1a46..4b50440 100644 Binary files a/Editor/assets/meshes/Sphere1m.fbx and b/Editor/assets/meshes/Sphere1m.fbx differ diff --git a/Editor/assets/scenes/2DTest.scene b/Editor/assets/scenes/2DTest.scene new file mode 100644 index 0000000..09c0b82 --- /dev/null +++ b/Editor/assets/scenes/2DTest.scene @@ -0,0 +1,155 @@ +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: 12498244675852797835 + TagComponent: + Tag: Box + TransformComponent: + Position: [-12.0348625, 6.59647179, 9.60061925e-07] + Rotation: [1, 0, 0, 0] + Scale: [3.00000024, 0.300000012, 1] + MeshComponent: + AssetPath: assets/meshes/Cube1m.fbx + RigidBody2DComponent: + BodyType: 0 + Mass: 1 + BoxCollider2DComponent: + Offset: [0, 0] + Size: [1.5, 0.150000006] + Density: 1 + Friction: 1 + - Entity: 5178862374589434728 + TagComponent: + Tag: Camera + TransformComponent: + Position: [-21.7406311, 9.70659542, 15] + Rotation: [0.999910355, -0.0133911213, 0, 0] + Scale: [1, 1, 1] + ScriptComponent: + ModuleName: Example.BasicController + StoredFields: + - Name: Speed + Type: 1 + Data: 12 + CameraComponent: + Camera: some camera data... + Primary: true + - Entity: 1289165777996378215 + TagComponent: + Tag: Cube + TransformComponent: + Position: [500, 0, 0] + Rotation: [1, 0, 0, 0] + Scale: [1200, 1, 5] + MeshComponent: + AssetPath: assets/meshes/Cube1m.fbx + RigidBody2DComponent: + BodyType: 0 + Mass: 1 + BoxCollider2DComponent: + Offset: [0, 0] + Size: [600, 0.5] + Density: 1 + Friction: 2 + - Entity: 14057422478420564497 + TagComponent: + Tag: Player + TransformComponent: + Position: [-23.6932545, 1.59184527, -1.96369365e-06] + Rotation: [1, 0, 0, 0] + Scale: [1, 1, 1] + ScriptComponent: + ModuleName: Example.PlayerCube + StoredFields: + - Name: HorizontalForce + Type: 1 + Data: 0.5 + - Name: MaxSpeed + Type: 5 + Data: [7, 10] + - Name: JumpForce + Type: 1 + Data: 3 + MeshComponent: + AssetPath: assets/meshes/Sphere1m.fbx + RigidBody2DComponent: + BodyType: 1 + Mass: 29.2000008 + CircleCollider2DComponent: + Offset: [0, 0] + Radius: 0.5 + Density: 1 + Friction: 1 + - Entity: 1352995477042327524 + TagComponent: + Tag: Box + TransformComponent: + Position: [-29.6808929, 29.7597198, 0] + Rotation: [0.707106769, 0, 0, 0.707106769] + Scale: [58.4179001, 4.47999144, 4.48000002] + MeshComponent: + AssetPath: assets/meshes/Cube1m.fbx + RigidBody2DComponent: + BodyType: 0 + Mass: 3 + BoxCollider2DComponent: + Offset: [0, 0] + Size: [29.7000008, 2.24000001] + Density: 1 + Friction: 1 + - Entity: 15223077898852293773 + TagComponent: + Tag: Box + TransformComponent: + Position: [6.12674046, 45.5617676, 0] + Rotation: [0.977883637, 0, 0, -0.209149584] + 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] + Density: 1 + Friction: 1 + - Entity: 5421735812495444456 + TagComponent: + Tag: Box + TransformComponent: + Position: [-20.766222, 2.29431438, 0] + Rotation: [1, 0, 0, 0] + Scale: [3.00000024, 0.300000012, 1] + MeshComponent: + AssetPath: assets/meshes/Cube1m.fbx + RigidBody2DComponent: + BodyType: 0 + Mass: 1 + BoxCollider2DComponent: + Offset: [0, 0] + Size: [1.5, 0.150000006] + Density: 1 + Friction: 1 + - Entity: 2842299641876190180 + TagComponent: + Tag: Box + TransformComponent: + Position: [-16.6143265, 4.39151001, 6.43359499e-09] + Rotation: [1, 0, 0, 0] + Scale: [3.00000024, 0.300000012, 1] + MeshComponent: + AssetPath: assets/meshes/Cube1m.fbx + RigidBody2DComponent: + BodyType: 0 + Mass: 1 + BoxCollider2DComponent: + Offset: [0, 0] + Size: [1.5, 0.150000006] + Density: 1 + Friction: 1 diff --git a/ExampleApp/Src/BasicContorller.cs b/ExampleApp/Src/BasicContorller.cs index 5dfe641..b9180e5 100644 --- a/ExampleApp/Src/BasicContorller.cs +++ b/ExampleApp/Src/BasicContorller.cs @@ -6,27 +6,20 @@ namespace Example { public float Speed; + private Entity m_PlayerEntity; + public void OnCreate() { + m_PlayerEntity = FindEntityByTag("Player"); } public void OnUpdate(float ts) { Mat4 transform = GetTransform(); + Vec3 translation = transform.Translation; - - float speed = Speed * ts; - - if (Input.IsKeyPressed(KeyCode.Up)) - translation.Y += speed; - else if (Input.IsKeyPressed(KeyCode.Down)) - translation.Y -= speed; - if (Input.IsKeyPressed(KeyCode.Right)) - translation.X += speed; - else if (Input.IsKeyPressed(KeyCode.Left)) - translation.X -= speed; - - + translation.XY = m_PlayerEntity.GetTransform().Translation.XY; + translation.Y = Math.Max(translation.Y, 4.5f); transform.Translation = translation; SetTransform(transform); } diff --git a/ExampleApp/Src/PlayerCube.cs b/ExampleApp/Src/PlayerCube.cs index 7979007..392000f 100644 --- a/ExampleApp/Src/PlayerCube.cs +++ b/ExampleApp/Src/PlayerCube.cs @@ -11,11 +11,17 @@ namespace Example class PlayerCube : Entity { public float HorizontalForce = 10.0f; - public float VerticalForce = 10.0f; + public float JumpForce = 10.0f; private RigidBody2DComponent m_PhysicsBody; private MaterialInstance m_MeshMaterial; + int m_CollisionCounter = 0; + + public Vec2 MaxSpeed = new Vec2(); + + private bool Colliding => m_CollisionCounter > 0; + void OnCreate() { m_PhysicsBody = GetComponent(); @@ -23,23 +29,46 @@ namespace Example MeshComponent meshComponent = GetComponent(); m_MeshMaterial = meshComponent.Mesh.GetMaterial(0); m_MeshMaterial.Set("u_Metalness", 0.0f); + + AddCollision2DBeginCallback(OnPlayerCollisionBegin); + AddCollision2DEndCallback(OnPlayerCollisionEnd); + } + + + void OnPlayerCollisionBegin(float value) + { + m_CollisionCounter++; + } + + void OnPlayerCollisionEnd(float value) + { + m_CollisionCounter--; } void OnUpdate(float ts) { + float movementForce = HorizontalForce; + + if (!Colliding) + { + movementForce *= 0.4f; + } if (Input.IsKeyPressed(KeyCode.D)) - m_PhysicsBody.ApplyLinearImpulse(new Vec2(HorizontalForce, 0), new Vec2(), true); + m_PhysicsBody.ApplyLinearImpulse(new Vec2(movementForce, 0), new Vec2(), true); else if (Input.IsKeyPressed(KeyCode.A)) - m_PhysicsBody.ApplyLinearImpulse(new Vec2(-HorizontalForce, 0), new Vec2(), true); + m_PhysicsBody.ApplyLinearImpulse(new Vec2(-movementForce, 0), new Vec2(), true); - if (Input.IsKeyPressed(KeyCode.Space)) - m_PhysicsBody.ApplyLinearImpulse(new Vec2(0, VerticalForce), new Vec2(0, -10), true); + if (Colliding && Input.IsKeyPressed(KeyCode.Space)) + m_PhysicsBody.ApplyLinearImpulse(new Vec2(0, JumpForce), new Vec2(0, 0), 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); + if (m_CollisionCounter > 0) + m_MeshMaterial.Set("u_AlbedoColor", new Vec3(1.0f, 0.0f, 0.0f)); + else + m_MeshMaterial.Set("u_AlbedoColor", new Vec3(0.8f, 0.8f, 0.8f)); - m_MeshMaterial.Set("u_AlbedoColor", color); + Vec2 linearVelocity = m_PhysicsBody.GetLinearVelocity(); + linearVelocity.Clamp(new Vec2(-MaxSpeed.X, -1000), MaxSpeed); + m_PhysicsBody.SetLinearVelocity(linearVelocity); if (Input.IsKeyPressed(KeyCode.R)) { diff --git a/Prism-ScriptCore/Src/Prism/Entity.cs b/Prism-ScriptCore/Src/Prism/Entity.cs index e29f53c..bb1dba9 100644 --- a/Prism-ScriptCore/Src/Prism/Entity.cs +++ b/Prism-ScriptCore/Src/Prism/Entity.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Runtime.CompilerServices; namespace Prism @@ -10,6 +11,16 @@ namespace Prism { } + private List> m_Collision2DBeginCallbacks = new List>(); + private List> m_Collision2DEndCallbacks = new List>(); + + protected Entity() { ID = 0; } + + internal Entity(ulong id) + { + ID = id; + } + public T CreateComponent() where T : Component, new() { CreateComponent_Native(ID, typeof(T)); @@ -34,6 +45,12 @@ namespace Prism return null; } + public Entity FindEntityByTag(string tag) + { + ulong entityID = FindEntityByTag_Native(tag); + return new Entity(entityID); + } + public Mat4 GetTransform() { Mat4 mat4Instance; @@ -46,6 +63,28 @@ namespace Prism SetTransform_Native(ID, ref transform); } + public void AddCollision2DBeginCallback(Action callback) + { + m_Collision2DBeginCallbacks.Add(callback); + } + + public void AddCollision2DEndCallback(Action callback) + { + m_Collision2DEndCallbacks.Add(callback); + } + + private void OnCollision2DBegin(float data) + { + foreach (var callback in m_Collision2DBeginCallbacks) + callback.Invoke(data); + } + + private void OnCollision2DEnd(float data) + { + foreach (var callback in m_Collision2DEndCallbacks) + callback.Invoke(data); + } + [MethodImpl(MethodImplOptions.InternalCall)] private static extern void CreateComponent_Native(ulong entityID, Type type); [MethodImpl(MethodImplOptions.InternalCall)] @@ -54,6 +93,8 @@ namespace Prism private static extern void GetTransform_Native(ulong entityID, out Mat4 matrix); [MethodImpl(MethodImplOptions.InternalCall)] private static extern void SetTransform_Native(ulong entityID, ref Mat4 matrix); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern ulong FindEntityByTag_Native(string tag); } } diff --git a/Prism-ScriptCore/Src/Prism/Math/Vec2.cs b/Prism-ScriptCore/Src/Prism/Math/Vec2.cs index 13a22f0..73f0702 100644 --- a/Prism-ScriptCore/Src/Prism/Math/Vec2.cs +++ b/Prism-ScriptCore/Src/Prism/Math/Vec2.cs @@ -18,5 +18,27 @@ namespace Prism X = x; Y = y; } + + public Vec2(Vec3 vec) { + X = vec.X; + Y = vec.Y; + } + + public void Clamp(Vec2 min, Vec2 max) { + if (X < min.X) + X = min.X; + if (X > max.X) + X = max.X; + + if (Y < min.Y) + Y = min.Y; + if (Y > max.Y) + Y = max.Y; + } + + public static Vec2 operator -(Vec2 vector) + { + return new Vec2(-vector.X, -vector.Y); + } } } \ No newline at end of file diff --git a/Prism-ScriptCore/Src/Prism/Math/Vec3.cs b/Prism-ScriptCore/Src/Prism/Math/Vec3.cs index a5dfeec..6c94863 100644 --- a/Prism-ScriptCore/Src/Prism/Math/Vec3.cs +++ b/Prism-ScriptCore/Src/Prism/Math/Vec3.cs @@ -2,18 +2,24 @@ using System.Runtime.InteropServices; namespace Prism { - [StructLayout(LayoutKind.Explicit)] + [StructLayout(LayoutKind.Sequential)] public struct Vec3 { - [FieldOffset(0)] public float X; - [FieldOffset(4)] public float Y; - [FieldOffset(8)] public float Z; + public float X; + public float Y; + public float Z; public Vec3(float scalar) { X = Y = Z = scalar; } + public Vec3(Vec2 vec) { + X = vec.X; + Y = vec.Y; + Z = 0.0f; + } + public Vec3(float x, float y, float z) { X = x; @@ -21,6 +27,27 @@ namespace Prism Z = z; } + public Vec3(Vec4 vec) { + X = vec.X; + Y = vec.Y; + Z = vec.Z; + } + + public Vec2 XY { + get { return new Vec2(X, Y); } + set { X = value.X; Y = value.Y; } + } + + public Vec2 XZ + { + get { return new Vec2(X, Z); } + set { X = value.X; Z = value.Y; } + } + public Vec2 YZ + { + get { return new Vec2(Y, Z); } + set { Y = value.X; Z = value.Y; } + } } } \ No newline at end of file diff --git a/Prism-ScriptCore/Src/Prism/Scene/Component.cs b/Prism-ScriptCore/Src/Prism/Scene/Component.cs index c2b21bf..f965c74 100644 --- a/Prism-ScriptCore/Src/Prism/Scene/Component.cs +++ b/Prism-ScriptCore/Src/Prism/Scene/Component.cs @@ -100,7 +100,27 @@ namespace Prism ApplyLinearImpulse_Native(Entity.ID, ref impulse, ref offset, wake); } + public Vec2 GetLinearVelocity() + { + GetLinearVelocity_Native(Entity.ID, out Vec2 velocity); + return velocity; + } + + public void SetLinearVelocity(Vec2 velocity) + { + SetLinearVelocity_Native(Entity.ID, ref velocity); + } + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern void ApplyLinearImpulse_Native(ulong entityID, ref Vec2 impulse, ref Vec2 offset, bool wake); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void GetLinearVelocity_Native(ulong entityID, out Vec2 velocity); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void SetLinearVelocity_Native(ulong entityID, ref Vec2 velocity); + } + + public class BoxCollider2DComponent : Component + { } } diff --git a/Prism/src/Prism/Core/Buffer.h b/Prism/src/Prism/Core/Buffer.h index 05769cc..07e34db 100644 --- a/Prism/src/Prism/Core/Buffer.h +++ b/Prism/src/Prism/Core/Buffer.h @@ -52,6 +52,12 @@ namespace Prism memset(Data, 0, Size); } + template + T& Read(const uint32_t offset = 0) + { + return *static_cast(Data + offset); + } + void Write(const void* data, const uint32_t size, const uint32_t offset = 0) const { PM_CORE_ASSERT(offset + size <= Size, "Buffer overflow!"); diff --git a/Prism/src/Prism/Core/Ref.h b/Prism/src/Prism/Core/Ref.h index ed0eb93..8c1d8fe 100644 --- a/Prism/src/Prism/Core/Ref.h +++ b/Prism/src/Prism/Core/Ref.h @@ -48,14 +48,14 @@ namespace Prism template Ref(const Ref& other) { - m_Instance = other.m_Instance; + m_Instance = (T*)other.m_Instance; IncRef(); } template - Ref(Ref&& other) + Ref(Ref&& other) { - m_Instance = other.m_Instance; + m_Instance = (T*)other.m_Instance; other.m_Instance = nullptr; } diff --git a/Prism/src/Prism/Editor/EditorCamera.h b/Prism/src/Prism/Editor/EditorCamera.h index b210160..c2e01c2 100644 --- a/Prism/src/Prism/Editor/EditorCamera.h +++ b/Prism/src/Prism/Editor/EditorCamera.h @@ -73,7 +73,6 @@ namespace Prism float m_Distance; - float m_Exposure = 0.8f; float m_Pitch, m_Yaw; }; diff --git a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp index a7db5ba..6e50655 100644 --- a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp +++ b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp @@ -111,6 +111,30 @@ namespace Prism ImGui::CloseCurrentPopup(); } } + if (!m_SelectionContext.HasComponent()) + { + if (ImGui::Button("Rigidbody 2D")) + { + m_SelectionContext.AddComponent(); + ImGui::CloseCurrentPopup(); + } + } + if (!m_SelectionContext.HasComponent()) + { + if (ImGui::Button("Box Collider 2D")) + { + m_SelectionContext.AddComponent(); + ImGui::CloseCurrentPopup(); + } + } + if (!m_SelectionContext.HasComponent()) + { + if (ImGui::Button("Circle Collider 2D")) + { + m_SelectionContext.AddComponent(); + ImGui::CloseCurrentPopup(); + } + } ImGui::EndPopup(); } } @@ -323,6 +347,28 @@ namespace Prism ImGui::NextColumn(); } + static bool Property(const char* label, bool& value) + { + bool modified = false; + + ImGui::Text(label); + ImGui::NextColumn(); + ImGui::PushItemWidth(-1); + + s_IDBuffer[0] = '#'; + s_IDBuffer[1] = '#'; + memset(s_IDBuffer + 2, 0, 14); + // itoa(s_Counter++, s_IDBuffer + 2, 16); + snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++); + if (ImGui::Checkbox(s_IDBuffer, &value)) + modified = true; + + ImGui::PopItemWidth(); + ImGui::NextColumn(); + + return modified; + } + static bool Property(const char* label, int& value) { bool modified = false; @@ -444,6 +490,48 @@ namespace Prism PopID(); } + template + static void DrawComponent(const std::string& name, Entity entity, UIFunction uiFunction) + { + if (entity.HasComponent()) + { + bool removeComponent = false; + + auto& component = entity.GetComponent(); + const bool open = ImGui::TreeNodeEx((void*)((uint32_t)entity | typeid(T).hash_code()), ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_AllowOverlap, name.c_str()); + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0)); + if (ImGui::Button("+")) + { + ImGui::OpenPopup("ComponentSettings"); + } + + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + + if (ImGui::BeginPopup("ComponentSettings")) + { + if (ImGui::MenuItem("Remove component")) + removeComponent = true; + + ImGui::EndPopup(); + } + + if (open) + { + uiFunction(component); + ImGui::NextColumn(); + ImGui::Columns(1); + ImGui::TreePop(); + } + ImGui::Separator(); + + if (removeComponent) + entity.RemoveComponent(); + } + } + void SceneHierarchyPanel::DrawComponents(Entity entity) { ImGui::AlignTextToFramePadding(); @@ -532,225 +620,243 @@ namespace Prism ImGui::Separator(); } + DrawComponent("Mesh", entity, [](MeshComponent& meshComponent) { + ImGui::Columns(3); + ImGui::SetColumnWidth(0, 100); + ImGui::SetColumnWidth(1, 300); + ImGui::SetColumnWidth(2, 40); + ImGui::Text("File Path"); + ImGui::NextColumn(); + ImGui::PushItemWidth(-1); - if (entity.HasComponent()) - { - auto& mc = entity.GetComponent(); - if (ImGui::TreeNodeEx((void*)((uint32_t)entity | typeid(MeshComponent).hash_code()), ImGuiTreeNodeFlags_DefaultOpen, "Mesh")) + if (meshComponent.Mesh) + ImGui::InputText("##meshFilePath", (char*)meshComponent.Mesh->GetFilePath().c_str(), 256, ImGuiInputTextFlags_ReadOnly); + else + ImGui::InputText("##meshFilePath", (char*)"Null", 256, ImGuiInputTextFlags_ReadOnly); + + ImGui::PopItemWidth(); + ImGui::NextColumn(); + if (ImGui::Button("...##openmesh")) { - ImGui::Columns(3); - ImGui::SetColumnWidth(0, 100); - ImGui::SetColumnWidth(1, 300); - ImGui::SetColumnWidth(2, 40); - ImGui::Text("File Path"); - ImGui::NextColumn(); - ImGui::PushItemWidth(-1); - - if (mc.Mesh) - ImGui::InputText("##meshFilePath", (char*)mc.Mesh->GetFilePath().c_str(), 256, ImGuiInputTextFlags_ReadOnly); - else - ImGui::InputText("##meshFilePath", (char*)"Null", 256, ImGuiInputTextFlags_ReadOnly); - - ImGui::PopItemWidth(); - ImGui::NextColumn(); - if (ImGui::Button("...##openmesh")) - { - const std::string file = Application::Get().OpenFile(); - if (!file.empty()) - mc.Mesh = Ref::Create(file); - } - ImGui::NextColumn(); - ImGui::Columns(1); - - ImGui::TreePop(); + const std::string file = Application::Get().OpenFile(); + if (!file.empty()) + meshComponent.Mesh = Ref::Create(file); } - ImGui::Separator(); - } + }); - if (entity.HasComponent()) - { - auto& cc = entity.GetComponent(); - if (ImGui::TreeNodeEx((void*)((uint32_t)entity | typeid(CameraComponent).hash_code()), ImGuiTreeNodeFlags_DefaultOpen, "Camera")) + + DrawComponent("Camera", entity, [](CameraComponent& cameraComponent) { + // Projection Type + const char* projTypeStrings[] = { "Perspective", "Orthographic" }; + const char* currentProj = projTypeStrings[(int)cameraComponent.Camera.GetProjectionType()]; + if (ImGui::BeginCombo("Projection", currentProj)) { - // Projection Type - const char* projTypeStrings[] = { "Perspective", "Orthographic" }; - const char* currentProj = projTypeStrings[(int)cc.Camera.GetProjectionType()]; - if (ImGui::BeginCombo("Projection", currentProj)) + for (int type = 0; type < 2; type++) { - for (int type = 0; type < 2; type++) + const bool is_selected = (currentProj == projTypeStrings[type]); + if (ImGui::Selectable(projTypeStrings[type], is_selected)) { - bool is_selected = (currentProj == projTypeStrings[type]); - if (ImGui::Selectable(projTypeStrings[type], is_selected)) - { - currentProj = projTypeStrings[type]; - cc.Camera.SetProjectionType((SceneCamera::ProjectionType)type); - } - if (is_selected) - ImGui::SetItemDefaultFocus(); + currentProj = projTypeStrings[type]; + cameraComponent.Camera.SetProjectionType((SceneCamera::ProjectionType)type); } - ImGui::EndCombo(); + if (is_selected) + ImGui::SetItemDefaultFocus(); } - - BeginPropertyGrid(); - // Perspective parameters - if (cc.Camera.GetProjectionType() == SceneCamera::ProjectionType::Perspective) - { - float verticalFOV = cc.Camera.GetPerspectiveVerticalFOV(); - if (Property("Vertical FOV", verticalFOV)) - cc.Camera.SetPerspectiveVerticalFOV(verticalFOV); - - float nearClip = cc.Camera.GetPerspectiveNearClip(); - if (Property("Near Clip", nearClip)) - cc.Camera.SetPerspectiveNearClip(nearClip); - ImGui::SameLine(); - float farClip = cc.Camera.GetPerspectiveFarClip(); - if (Property("Far Clip", farClip)) - cc.Camera.SetPerspectiveFarClip(farClip); - } - - // Orthographic parameters - else if (cc.Camera.GetProjectionType() == SceneCamera::ProjectionType::Orthographic) - { - float orthoSize = cc.Camera.GetOrthographicSize(); - if (Property("Size", orthoSize)) - cc.Camera.SetOrthographicSize(orthoSize); - - float nearClip = cc.Camera.GetOrthographicNearClip(); - if (Property("Near Clip", nearClip)) - cc.Camera.SetOrthographicNearClip(nearClip); - ImGui::SameLine(); - float farClip = cc.Camera.GetOrthographicFarClip(); - if (Property("Far Clip", farClip)) - cc.Camera.SetOrthographicFarClip(farClip); - } - - EndPropertyGrid(); - - ImGui::TreePop(); + ImGui::EndCombo(); } - ImGui::Separator(); - } - if (entity.HasComponent()) - { - auto& src = entity.GetComponent(); - if (ImGui::TreeNodeEx((void*)((uint32_t)entity | typeid(SpriteRendererComponent).hash_code()), ImGuiTreeNodeFlags_DefaultOpen, "Sprite Renderer")) + BeginPropertyGrid(); + // Perspective parameters + if (cameraComponent.Camera.GetProjectionType() == SceneCamera::ProjectionType::Perspective) { + float verticalFOV = cameraComponent.Camera.GetPerspectiveVerticalFOV(); + if (Property("Vertical FOV", verticalFOV)) + cameraComponent.Camera.SetPerspectiveVerticalFOV(verticalFOV); - ImGui::TreePop(); + float nearClip = cameraComponent.Camera.GetPerspectiveNearClip(); + if (Property("Near Clip", nearClip)) + cameraComponent.Camera.SetPerspectiveNearClip(nearClip); + ImGui::SameLine(); + float farClip = cameraComponent.Camera.GetPerspectiveFarClip(); + if (Property("Far Clip", farClip)) + cameraComponent.Camera.SetPerspectiveFarClip(farClip); } - ImGui::Separator(); - } - if (entity.HasComponent()) - { - auto& sc = entity.GetComponent(); - if (ImGui::TreeNodeEx((void*)((uint32_t)entity | typeid(ScriptComponent).hash_code()), ImGuiTreeNodeFlags_DefaultOpen, "Script")) + // Orthographic parameters + else if (cameraComponent.Camera.GetProjectionType() == SceneCamera::ProjectionType::Orthographic) { - BeginPropertyGrid(); - std::string oldName = sc.ModuleName; + float orthoSize = cameraComponent.Camera.GetOrthographicSize(); + if (Property("Size", orthoSize)) + cameraComponent.Camera.SetOrthographicSize(orthoSize); - if (Property("Module Name", sc.ModuleName, !ScriptEngine::ModuleExists(sc.ModuleName))) // TODO: no live edit + float nearClip = cameraComponent.Camera.GetOrthographicNearClip(); + if (Property("Near Clip", nearClip)) + cameraComponent.Camera.SetOrthographicNearClip(nearClip); + ImGui::SameLine(); + float farClip = cameraComponent.Camera.GetOrthographicFarClip(); + if (Property("Far Clip", farClip)) + cameraComponent.Camera.SetOrthographicFarClip(farClip); + } + EndPropertyGrid(); + }); + + DrawComponent("Sprite Renderer", entity, [](SpriteRendererComponent& mc) + { + }); + + DrawComponent("Script", entity, [=](ScriptComponent& scriptComponent) mutable { + BeginPropertyGrid(); + std::string oldName = scriptComponent.ModuleName; + if (Property("Module Name", scriptComponent.ModuleName, !ScriptEngine::ModuleExists(scriptComponent.ModuleName))) // TODO: no live edit + { + // Shutdown old script + if (ScriptEngine::ModuleExists(oldName)) + ScriptEngine::ShutdownScriptEntity(entity, oldName); + + if (ScriptEngine::ModuleExists(scriptComponent.ModuleName)) + ScriptEngine::InitScriptEntity(entity); + } + + // Public Fields + if (ScriptEngine::ModuleExists(scriptComponent.ModuleName)) + { + EntityInstanceData& entityInstanceData = ScriptEngine::GetEntityInstanceData(entity.GetSceneUUID(), id); + auto& moduleFieldMap = entityInstanceData.ModuleFieldMap; + if (moduleFieldMap.find(scriptComponent.ModuleName) != moduleFieldMap.end()) { - // Shutdown old script - if (ScriptEngine::ModuleExists(oldName)) - ScriptEngine::ShutdownScriptEntity(entity, oldName); - - if (ScriptEngine::ModuleExists(sc.ModuleName)) - ScriptEngine::InitScriptEntity(entity); - } - - if (ScriptEngine::ModuleExists(sc.ModuleName)) - { - EntityInstanceData& entityInstanceData = ScriptEngine::GetEntityInstanceData(entity.GetSceneUUID(), id); - auto& moduleFieldMap = entityInstanceData.ModuleFieldMap; - if (moduleFieldMap.find(sc.ModuleName) != moduleFieldMap.end()) + auto& publicFields = moduleFieldMap.at(scriptComponent.ModuleName); + for (auto& [name, field] : publicFields) { - auto& publicFields = moduleFieldMap.at(sc.ModuleName); - for (auto& [name, field] : publicFields) + bool isRuntime = m_Context->m_IsPlaying && field.IsRuntimeAvailable(); + switch (field.Type) { - bool isRuntime = m_Context->m_IsPlaying && field.IsRuntimeAvailable(); - switch (field.Type) + case FieldType::Int: + { + int value = isRuntime ? field.GetRuntimeValue() : field.GetStoredValue(); + if (Property(field.Name.c_str(), value)) { - case FieldType::Int: - { - int value = isRuntime ? field.GetRuntimeValue() : field.GetStoredValue(); - if (Property(field.Name.c_str(), value)) - { - if (isRuntime) - field.SetRuntimeValue(value); - else - field.SetStoredValue(value); - } - break; - } - case FieldType::Float: - { - float value = isRuntime ? field.GetRuntimeValue() : field.GetStoredValue(); - if (Property(field.Name.c_str(), value, 0.2f)) - { - if (isRuntime) - field.SetRuntimeValue(value); + if (isRuntime) + field.SetRuntimeValue(value); else field.SetStoredValue(value); - } - break; } - case FieldType::Vec2: + break; + } + case FieldType::Float: + { + float value = isRuntime ? field.GetRuntimeValue() : field.GetStoredValue(); + if (Property(field.Name.c_str(), value, 0.2f)) { - glm::vec2 value = isRuntime ? field.GetRuntimeValue() : field.GetStoredValue(); - if (Property(field.Name.c_str(), value, 0.2f)) - { - if (isRuntime) - field.SetRuntimeValue(value); - else - field.SetStoredValue(value); - } - break; + if (isRuntime) + field.SetRuntimeValue(value); + else + field.SetStoredValue(value); } - case FieldType::Vec3: + break; + } + case FieldType::Vec2: + { + glm::vec2 value = isRuntime ? field.GetRuntimeValue() : field.GetStoredValue(); + if (Property(field.Name.c_str(), value, 0.2f)) { - glm::vec3 value = isRuntime ? field.GetRuntimeValue() : field.GetStoredValue(); - if (Property(field.Name.c_str(), value, 0.2f)) - { - if (isRuntime) - field.SetRuntimeValue(value); - else - field.SetStoredValue(value); - } - break; + if (isRuntime) + field.SetRuntimeValue(value); + else + field.SetStoredValue(value); } - case FieldType::Vec4: + break; + } + case FieldType::Vec3: + { + glm::vec3 value = isRuntime ? field.GetRuntimeValue() : field.GetStoredValue(); + if (Property(field.Name.c_str(), value, 0.2f)) { - glm::vec4 value = isRuntime ? field.GetRuntimeValue() : field.GetStoredValue(); - if (Property(field.Name.c_str(), value, 0.2f)) - { - if (isRuntime) - field.SetRuntimeValue(value); - else - field.SetStoredValue(value); - } - break; + if (isRuntime) + field.SetRuntimeValue(value); + else + field.SetStoredValue(value); } + break; + } + case FieldType::Vec4: + { + glm::vec4 value = isRuntime ? field.GetRuntimeValue() : field.GetStoredValue(); + if (Property(field.Name.c_str(), value, 0.2f)) + { + if (isRuntime) + field.SetRuntimeValue(value); + else + field.SetStoredValue(value); } + break; + } } } } - - EndPropertyGrid(); - -#if TODO - - if (ImGui::Button("Run Script")) - { - ScriptEngine::OnCreateEntity(entity); - } -#endif - - ImGui::TreePop(); } - ImGui::Separator(); - } + + EndPropertyGrid(); +#if TODO + if (ImGui::Button("Run Script")) + { + ScriptEngine::OnCreateEntity(entity); + } +#endif + }); + + + DrawComponent("Rigidbody 2D", entity, [](RigidBody2DComponent& rb2dComponent) + { + // Rigidbody2D Type + const char* rb2dTypeStrings[] = { "Static", "Dynamic", "Kinematic" }; + const char* currentType = rb2dTypeStrings[(int)rb2dComponent.BodyType]; + if (ImGui::BeginCombo("Type", currentType)) + { + for (int type = 0; type < 3; type++) + { + bool is_selected = (currentType == rb2dTypeStrings[type]); + if (ImGui::Selectable(rb2dTypeStrings[type], is_selected)) + { + currentType = rb2dTypeStrings[type]; + rb2dComponent.BodyType = (RigidBody2DComponent::Type)type; + } + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + + if (rb2dComponent.BodyType == RigidBody2DComponent::Type::Dynamic) + { + BeginPropertyGrid(); + Property("Fixed Rotation", rb2dComponent.FixedRotation); + EndPropertyGrid(); + } + }); + + DrawComponent("Box Collider 2D", entity, [](BoxCollider2DComponent& bc2dComponent) + { + BeginPropertyGrid(); + + Property("Offset", bc2dComponent.Offset); + Property("Size", bc2dComponent.Size); + Property("Density", bc2dComponent.Density); + Property("Friction", bc2dComponent.Friction); + + EndPropertyGrid(); + }); + + DrawComponent("Circle Collider 2D", entity, [](CircleCollider2DComponent& cc2dComponent) + { + BeginPropertyGrid(); + + Property("Offset", cc2dComponent.Offset); + Property("Radius", cc2dComponent.Radius); + Property("Density", cc2dComponent.Density); + Property("Friction", cc2dComponent.Friction); + + EndPropertyGrid(); + }); } diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLBuffer.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLBuffer.cpp index e8996d5..4fea116 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLBuffer.cpp +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLBuffer.cpp @@ -48,14 +48,10 @@ namespace Prism OpenGLVertexBuffer::~OpenGLVertexBuffer() { -#ifdef __MINGW32__ - glDeleteBuffers(1, &m_RendererID); -#else GLuint rendererID = m_RendererID; Renderer::Submit([rendererID](){ glDeleteBuffers(1, &rendererID); }); -#endif } void OpenGLVertexBuffer::SetData(void* buffer, uint32_t size, uint32_t offset) @@ -105,13 +101,10 @@ namespace Prism OpenGLIndexBuffer::~OpenGLIndexBuffer() { -#ifdef __MINGW32__ - glDeleteBuffers(1, &m_RendererID); -#else - Renderer::Submit([this](){ - glDeleteBuffers(1, &m_RendererID); + const GLuint rendererID = m_RendererID; + Renderer::Submit([rendererID](){ + glDeleteBuffers(1, &rendererID); }); -#endif } void OpenGLIndexBuffer::SetData(void* data, uint32_t size, uint32_t offset) diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp index 7115466..1faa6ba 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp @@ -19,13 +19,10 @@ namespace Prism OpenGLFrameBuffer::~OpenGLFrameBuffer() { -#ifdef __MINGW32__ - glDeleteFramebuffers(1, &m_RendererID); -#else - Renderer::Submit([=](){ - glDeleteFramebuffers(1, &m_RendererID); + GLuint rendererID = m_RendererID; + Renderer::Submit([rendererID](){ + glDeleteFramebuffers(1, &rendererID); }); -#endif } void OpenGLFrameBuffer::Bind() const @@ -71,13 +68,12 @@ namespace Prism // TODO: Create Prism texture object based on format here if (m_Specification.Format == FramebufferFormat::RGBA16F) { - glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_RGBA16F, m_Specification.Width, m_Specification.Height, GL_FALSE); - //glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_RGBA16F, m_Specification.Width, m_Specification.Height, GL_FALSE); + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_RGBA16F, m_Specification.Width, m_Specification.Height, GL_TRUE); } else if (m_Specification.Format == FramebufferFormat::RGBA8) { // glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_RGBA8, m_Specification.Width, m_Specification.Height, GL_TRUE); - glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_RGBA8, m_Specification.Width, m_Specification.Height, GL_FALSE); + glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_RGBA8, m_Specification.Width, m_Specification.Height, GL_TRUE); } // glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -108,7 +104,7 @@ namespace Prism glCreateTextures(GL_TEXTURE_2D_MULTISAMPLE, 1, &m_DepthAttachment); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_DepthAttachment); // glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height, GL_TRUE); - glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height, GL_FALSE); + glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height, GL_TRUE); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); // glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, m_DepthAttachment, 0); } diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLTexture.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLTexture.cpp index 0d60e5e..0fff672 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLTexture.cpp +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLTexture.cpp @@ -118,14 +118,10 @@ namespace Prism OpenGLTexture2D::~OpenGLTexture2D() { -#ifdef __MINGW32__ - glDeleteTextures(1, &m_RendererID); -#else GLuint rendererID = m_RendererID; Renderer::Submit([rendererID](){ glDeleteTextures(1, &rendererID); }); -#endif } void OpenGLTexture2D::Bind(uint32_t slot) const @@ -286,14 +282,10 @@ namespace Prism OpenGLTextureCube::~OpenGLTextureCube() { -#ifdef __MINGW32__ - glDeleteTextures(1, &m_RendererID); -#else GLuint rendererID = m_RendererID; Renderer::Submit([rendererID]() { glDeleteTextures(1, &rendererID); }); -#endif } void OpenGLTextureCube::Bind(uint32_t slot) const diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLVertexArray.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLVertexArray.cpp index 0c04aa3..10770f7 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLVertexArray.cpp +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLVertexArray.cpp @@ -40,14 +40,10 @@ namespace Prism OpenGLVertexArray::~OpenGLVertexArray() { -#ifdef __MINGW32__ - glDeleteVertexArrays(1, &m_RendererID); -#else GLuint rendererID = m_RendererID; Renderer::Submit([rendererID](){ glDeleteVertexArrays(1, &rendererID); }); -#endif } void OpenGLVertexArray::Bind() const diff --git a/Prism/src/Prism/Renderer/Material.h b/Prism/src/Prism/Renderer/Material.h index 34ea1b1..1b64433 100644 --- a/Prism/src/Prism/Renderer/Material.h +++ b/Prism/src/Prism/Renderer/Material.h @@ -38,6 +38,24 @@ namespace Prism uint32_t GetFlags() const { return m_MaterialFlags; } void SetFlag(MaterialFlag flag) { m_MaterialFlags |= (uint32_t)flag; } + template + T& Get(const std::string& name) + { + auto decl = FindUniformDeclaration(name); + PM_CORE_ASSERT(decl, "Could not find uniform with name x"); + auto& buffer = GetUniformBufferTarget(decl); + return buffer.Read(decl->GetOffset()); + } + + template + Ref GetResource(const std::string& name) + { + const auto decl = FindResourceDeclaration(name); + const uint32_t slot = decl->GetRegister(); + PM_CORE_ASSERT(slot < m_Textures.size(), "Texture slot is invalid!"); + return m_Textures[slot]; + } + template void Set(const std::string& name, const T& value); @@ -45,7 +63,11 @@ namespace Prism void Set(const std::string& name, const Ref& texture) { const auto decl = FindResourceDeclaration(name); - if (!decl) return; + if (!decl) + { + PM_CORE_WARN("Cannot find material property: ", name); + return; + } uint32_t slot = decl->GetRegister(); if (m_Textures.size() <= slot) m_Textures.resize((size_t)slot + 1); @@ -92,6 +114,41 @@ namespace Prism static Ref Create(const Ref& material); + template + T& Get(const std::string& name) + { + const auto decl = m_Material->FindUniformDeclaration(name); + PM_CORE_ASSERT(decl, "Could not find uniform with name x"); + auto& buffer = GetUniformBufferTarget(decl); + return buffer.Read(decl->GetOffset()); + } + + template + Ref GetResource(const std::string& name) + { + const auto decl = m_Material->FindResourceDeclaration(name); + PM_CORE_ASSERT(decl, "Could not find uniform with name x"); + uint32_t slot = decl->GetRegister(); + PM_CORE_ASSERT(slot < m_Textures.size(), "Texture slot is invalid!"); + return Ref(m_Textures[slot]); + } + + template + Ref TryGetResource(const std::string& name) + { + const auto decl = m_Material->FindResourceDeclaration(name); + if (!decl) + return nullptr; + + const uint32_t slot = decl->GetRegister(); + if (slot >= m_Textures.size()) + return nullptr; + + return Ref(m_Textures[slot]); + } + + + template void Set(const std::string& name, const T& value) { @@ -151,9 +208,8 @@ namespace Prism void Material::Set(const std::string& name, const T& value) { auto decl = FindUniformDeclaration(name); - // HZ_CORE_ASSERT(decl, "Could not find uniform with name '{0}'", name); - PM_CORE_ASSERT(decl, "Could not find uniform with name 'x'"); - auto& buffer = GetUniformBufferTarget(decl); + PM_CORE_ASSERT(decl, "Could not find uniform with name x"); + const auto& buffer = GetUniformBufferTarget(decl); buffer.Write(&value, decl->GetSize(), decl->GetOffset()); for (auto mi : m_MaterialInstances) diff --git a/Prism/src/Prism/Renderer/Mesh.cpp b/Prism/src/Prism/Renderer/Mesh.cpp index f279090..071d1d1 100644 --- a/Prism/src/Prism/Renderer/Mesh.cpp +++ b/Prism/src/Prism/Renderer/Mesh.cpp @@ -272,11 +272,12 @@ namespace Prism PM_CORE_TRACE("COLOR = {0}, {1}, {2}", aiColor.r, aiColor.g, aiColor.b); float shininess, metalness; - aiMaterial->Get(AI_MATKEY_SHININESS, shininess); + if (aiMaterial->Get(AI_MATKEY_SHININESS, shininess) != aiReturn_SUCCESS) + shininess = 80.0f; // Default value aiMaterial->Get(AI_MATKEY_REFLECTIVITY, metalness); + if (aiMaterial->Get(AI_MATKEY_REFLECTIVITY, metalness) != aiReturn_SUCCESS) + metalness = 0.0f; - // float roughness = 1.0f - shininess * 0.01f; - // roughness *= roughness; float roughness = 1.0f - glm::sqrt(shininess / 100.0f); PM_MESH_LOG(" COLOR = {0}, {1}, {2}", aiColor.r, aiColor.g, aiColor.b); PM_MESH_LOG(" ROUGHNESS = {0}", roughness); diff --git a/Prism/src/Prism/Renderer/Mesh.h b/Prism/src/Prism/Renderer/Mesh.h index 302b37d..0d86259 100644 --- a/Prism/src/Prism/Renderer/Mesh.h +++ b/Prism/src/Prism/Renderer/Mesh.h @@ -120,7 +120,7 @@ namespace Prism const std::vector>& GetTextures() const { return m_Textures; } const std::string& GetFilePath() const { return m_FilePath; } - const std::vector GetTriangleCache(uint32_t index) const { return m_TriangleCache.at(index); } + std::vector GetTriangleCache(const uint32_t index) const { return m_TriangleCache.at(index); } private: void BoneTransform(float time); void ReadNodeHierarchy(float AnimationTime, const aiNode* pNode, const glm::mat4& ParentTransform); diff --git a/Prism/src/Prism/Renderer/SceneRenderer.cpp b/Prism/src/Prism/Renderer/SceneRenderer.cpp index 7d58673..b0db3d6 100644 --- a/Prism/src/Prism/Renderer/SceneRenderer.cpp +++ b/Prism/src/Prism/Renderer/SceneRenderer.cpp @@ -76,7 +76,6 @@ namespace Prism s_Data.CompositePass = RenderPass::Create(compRenderPassSpec); s_Data.CompositeShader = Shader::Create("assets/shaders/SceneComposite.glsl"); - // s_Data.CompositeShader = Shader::Create("assets/shaders/hdr.glsl"); s_Data.BRDFLUT = Texture2D::Create("assets/textures/BRDF_LUT.tga"); diff --git a/Prism/src/Prism/Scene/Components.h b/Prism/src/Prism/Scene/Components.h index 92d333b..f08a2ef 100644 --- a/Prism/src/Prism/Scene/Components.h +++ b/Prism/src/Prism/Scene/Components.h @@ -27,8 +27,7 @@ namespace Prism std::string Tag; TagComponent() = default; - TagComponent(const TagComponent& other) - : Tag(other.Tag) {} + TagComponent(const TagComponent& other) = default; TagComponent(const std::string& tag) : Tag(tag) {} @@ -42,8 +41,7 @@ namespace Prism glm::mat4 Transform; TransformComponent() = default; - TransformComponent(const TransformComponent& other) - : Transform(other.Transform) {} + TransformComponent(const TransformComponent& other) = default; TransformComponent(const glm::mat4& transform) : Transform(transform) {} @@ -57,8 +55,7 @@ namespace Prism Ref Mesh; MeshComponent() = default; - MeshComponent(const MeshComponent& other) - : Mesh(other.Mesh) {} + MeshComponent(const MeshComponent& other) = default; MeshComponent(const Ref& mesh) : Mesh(mesh) {} @@ -71,8 +68,7 @@ namespace Prism std::string ModuleName; ScriptComponent() = default; - ScriptComponent(const ScriptComponent& other) - : ModuleName(other.ModuleName) {} + ScriptComponent(const ScriptComponent& other) = default; ScriptComponent(const std::string& moduleName) : ModuleName(moduleName) {} }; @@ -84,8 +80,7 @@ namespace Prism bool Primary = true; CameraComponent() = default; - CameraComponent(const CameraComponent& other) - : Camera(other.Camera), Primary(other.Primary) {} + CameraComponent(const CameraComponent& other) = default; operator SceneCamera& () { return Camera; } operator const SceneCamera& () const { return Camera; } @@ -99,22 +94,20 @@ namespace Prism float TilingFactor = 1.0f; SpriteRendererComponent() = default; - SpriteRendererComponent(const SpriteRendererComponent& other) - : Color(other.Color), Texture(other.Texture), TilingFactor(other.TilingFactor) {} + SpriteRendererComponent(const SpriteRendererComponent& other) = default; }; struct RigidBody2DComponent { enum class Type { Static, Dynamic, Kinematic }; Type BodyType; - float Mass = 1.0f; + bool FixedRotation = false; // 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) {} + RigidBody2DComponent(const RigidBody2DComponent& other) = default; }; struct BoxCollider2DComponent @@ -122,12 +115,13 @@ namespace Prism glm::vec2 Offset = { 0.0f,0.0f }; glm::vec2 Size = { 1.0f, 1.0f }; + float Density = 1.0f; + float Friction = 1.0f; // Storage for runtime // void* RuntimeFixture = nullptr; BoxCollider2DComponent() = default; - BoxCollider2DComponent(const BoxCollider2DComponent& other) - : Offset(other.Offset), Size(other.Size) {} + BoxCollider2DComponent(const BoxCollider2DComponent& other) = default; }; struct CircleCollider2DComponent @@ -135,12 +129,13 @@ namespace Prism glm::vec2 Offset = { 0.0f,0.0f }; float Radius = 1.0f; + float Density = 1.0f; + float Friction = 1.0f; // Storage for runtime // void* RuntimeFixture = nullptr; CircleCollider2DComponent() = default; - CircleCollider2DComponent(const CircleCollider2DComponent& other) - : Offset(other.Offset), Radius(other.Radius) {} + CircleCollider2DComponent(const CircleCollider2DComponent& other) = default; }; } diff --git a/Prism/src/Prism/Scene/Entity.h b/Prism/src/Prism/Scene/Entity.h index 6315f5b..1be026a 100644 --- a/Prism/src/Prism/Scene/Entity.h +++ b/Prism/src/Prism/Scene/Entity.h @@ -25,12 +25,14 @@ namespace Prism template T& AddComponent(Args&&... args) { + PM_CORE_ASSERT(!HasComponent(), "Entity already has component!"); return m_Scene->m_Registry.emplace(m_EntityHandle, std::forward(args)...); } template T& GetComponent() { + PM_CORE_ASSERT(HasComponent(), "Entity doesn't have component!"); return m_Scene->m_Registry.get(m_EntityHandle); } @@ -42,6 +44,7 @@ namespace Prism template void RemoveComponent() const { + PM_CORE_ASSERT(HasComponent(), "Entity doesn't have component!"); if (HasComponent()) m_Scene->m_Registry.remove(m_EntityHandle); } @@ -64,7 +67,7 @@ namespace Prism } UUID GetUUID() { return GetComponent().ID; } - UUID GetSceneUUID() { return m_Scene->GetUUID(); } + UUID GetSceneUUID() const { return m_Scene->GetUUID(); } private: explicit Entity(const std::string& name); diff --git a/Prism/src/Prism/Scene/Scene.cpp b/Prism/src/Prism/Scene/Scene.cpp index d26cca0..191e258 100644 --- a/Prism/src/Prism/Scene/Scene.cpp +++ b/Prism/src/Prism/Scene/Scene.cpp @@ -16,6 +16,11 @@ namespace Prism { + + // TODO: THIS SHOULD MOVE TO PHYSICS FILE! + + + std::unordered_map s_ActiveScenes; static uint32_t s_SceneIDCounter = 0; @@ -29,7 +34,7 @@ namespace Prism { b2WorldId World; - Box2DWorldComponent() = default; + Box2DWorldComponent() = delete; Box2DWorldComponent(const b2Vec2& gravity) { b2WorldDef worldDef = b2DefaultWorldDef(); worldDef.gravity = gravity; @@ -37,9 +42,44 @@ namespace Prism } }; + void ProcessContactEvents(const b2WorldId worldId) { + const b2ContactEvents contactEvents = b2World_GetContactEvents(worldId); + + // Contact Begin Touch + for (int i = 0; i < contactEvents.beginCount; ++i) { + const b2ContactBeginTouchEvent& event = contactEvents.beginEvents[i]; + + auto& entityA = *static_cast(b2Body_GetUserData(b2Shape_GetBody(event.shapeIdA))); + auto& entityB = *static_cast(b2Body_GetUserData(b2Shape_GetBody(event.shapeIdB))); + + if (entityA.HasComponent() && ScriptEngine::ModuleExists(entityA.GetComponent().ModuleName)) + ScriptEngine::OnCollision2DBegin(entityA); + + if (entityB.HasComponent() && ScriptEngine::ModuleExists(entityB.GetComponent().ModuleName)) + ScriptEngine::OnCollision2DBegin(entityB); + } + + + // Contact Begin Touch + for (int i = 0; i < contactEvents.endCount; ++i) { + const b2ContactEndTouchEvent& event = contactEvents.endEvents[i]; + + auto& entityA = *static_cast(b2Body_GetUserData(b2Shape_GetBody(event.shapeIdA))); + auto& entityB = *static_cast(b2Body_GetUserData(b2Shape_GetBody(event.shapeIdB))); + + if (entityA.HasComponent() && ScriptEngine::ModuleExists(entityA.GetComponent().ModuleName)) + ScriptEngine::OnCollision2DEnd(entityA); + + if (entityB.HasComponent() && ScriptEngine::ModuleExists(entityB.GetComponent().ModuleName)) + ScriptEngine::OnCollision2DEnd(entityB); + } + } + + + void OnTransformConstruct(entt::registry& registry, entt::entity entity) { - // HZ_CORE_TRACE("Transform Component constructed!"); + // PM_CORE_TRACE("Transform Component constructed!"); } void OnScriptComponentConstruct(entt::registry& registry, entt::entity entity) @@ -55,6 +95,15 @@ namespace Prism ScriptEngine::InitScriptEntity(scene->m_EntityIDMap.at(entityID)); } + void OnScriptComponentDestroy(entt::registry& registry, entt::entity entity) + { + const auto sceneView = registry.view(); + const UUID sceneID = registry.get(sceneView.front()).SceneID; + + const auto entityID = registry.get(entity).ID; + ScriptEngine::OnScriptComponentDestroyed(sceneID, entityID); + } + static std::tuple GetTransformDecomposition(const glm::mat4& transform) { glm::vec3 scale, translation, skew; @@ -79,8 +128,9 @@ 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 }); + Box2DWorldComponent& b2World = m_Registry.emplace(m_SceneEntity, b2Vec2{ 0.0f, -9.8f }); s_ActiveScenes[m_SceneID] = this; @@ -89,6 +139,7 @@ namespace Prism Scene::~Scene() { + m_Registry.on_destroy().disconnect(); m_Registry.clear(); s_ActiveScenes.erase(m_SceneID); @@ -117,16 +168,27 @@ namespace Prism // Box2D physics - auto sceneView = m_Registry.view(); - auto& box2DWorld = m_Registry.get(sceneView.front()).World; + const auto sceneView = m_Registry.view(); + const auto& box2DWorld = m_Registry.get(sceneView.front()).World; int32_t velocityIterations = 6; - int32_t positionIterations = 2; + constexpr int32_t positionIterations = 2; // box2DWorld->Step(ts, velocityIterations, positionIterations); b2World_Step(box2DWorld, ts, positionIterations); { - auto view = m_Registry.view(); - for (auto entity : view) + ProcessContactEvents(box2DWorld); + /* + const b2ContactEvents contactEvents = b2World_GetContactEvents(box2DWorld); + if (contactEvents.beginCount > 0) + PM_CORE_WARN("collision box counts in begin: {}", contactEvents.beginCount); + if (contactEvents.endCount > 0) + PM_CORE_WARN("collision box counts in end: {}", contactEvents.endCount); + */ + } + + { + const auto view = m_Registry.view(); + for (const auto entity : view) { Entity e = { entity, this }; auto& transform = e.Transform(); @@ -163,10 +225,10 @@ namespace Prism m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod); auto group = m_Registry.group(entt::get); - SceneRenderer::BeginScene(this, { camera, cameraViewMatrix }); + SceneRenderer::BeginScene(this, { static_cast(camera), cameraViewMatrix }); for (auto entity : group) { - auto [transformComponent, meshComponent] = group.get(entity); + const auto& [transformComponent, meshComponent] = group.get(entity); if (meshComponent.Mesh) { meshComponent.Mesh->OnUpdate(ts); @@ -208,7 +270,7 @@ namespace Prism SceneRenderer::BeginScene(this, { static_cast(editorCamera), editorCamera.GetViewMatrix() }); for (auto entity : group) { - auto [transformComponent, meshComponent] = group.get(entity); + const auto& [transformComponent, meshComponent] = group.get(entity); if (meshComponent.Mesh) { meshComponent.Mesh->OnUpdate(ts); @@ -218,7 +280,7 @@ namespace Prism if (m_SelectedEntity == entity) SceneRenderer::SubmitSelectedMesh(meshComponent, transformComponent); else - SceneRenderer::SubmitMesh(meshComponent, transformComponent, nullptr); + SceneRenderer::SubmitMesh(meshComponent, transformComponent); } } SceneRenderer::EndScene(); @@ -266,9 +328,12 @@ namespace Prism auto& world = m_Registry.get(sceneView.front()).World; { auto view = m_Registry.view(); - for (auto entity : view) + m_PhysicsBodyEntityBuffer = new Entity[view.size()]; + uint32_t physicsBodyEntityBufferIndex = 0; + for (auto entity : view) { Entity e = { entity, this }; + UUID entityID = e.GetComponent().ID; auto& transform = e.Transform(); auto& rigidBody2D = m_Registry.get(entity); @@ -285,6 +350,13 @@ namespace Prism float rotationZ = glm::eulerAngles(rotationQuat).z; bodyDef.rotation = b2Rot{cos(rotationZ), sin(rotationZ)}; + // box2D fixRotation renamed to motionlocks + bodyDef.motionLocks = b2MotionLocks{false, false, rigidBody2D.FixedRotation}; + + Entity* entityStorage = &m_PhysicsBodyEntityBuffer[physicsBodyEntityBufferIndex++]; + *entityStorage = e; + bodyDef.userData = entityStorage; + rigidBody2D.RuntimeBodyID = b2CreateBody(world, &bodyDef); } } @@ -306,10 +378,10 @@ namespace Prism 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; + shapeDef.density = boxCollider2D.Density; + shapeDef.material.friction = boxCollider2D.Friction; + shapeDef.enableContactEvents = true; b2CreatePolygonShape(bodyId, &shapeDef, &boxShape); } @@ -321,7 +393,6 @@ namespace Prism for (auto entity : view) { Entity e = { entity, this }; - auto& transform = e.Transform(); auto& circleCollider2D = m_Registry.get(entity); if (e.HasComponent()) @@ -333,15 +404,15 @@ namespace Prism b2Vec2 centor = {circleCollider2D.Offset.x, circleCollider2D.Offset.y}; - b2Circle circleShape{ - .center = centor, - .radius = circleCollider2D.Radius - }; + b2Circle circleShape; + circleShape.center = centor; + circleShape.radius = circleCollider2D.Radius; b2ShapeDef shapeDef = b2DefaultShapeDef(); - shapeDef.density = 1.0f; - shapeDef.material.friction = 1.0f; + shapeDef.density = circleCollider2D.Density; + shapeDef.material.friction = circleCollider2D.Friction; + shapeDef.enableContactEvents = true; b2CreateCircleShape(bodyId, &shapeDef, &circleShape); } @@ -354,6 +425,7 @@ namespace Prism void Scene::OnRuntimeStop() { + delete[] m_PhysicsBodyEntityBuffer; m_IsPlaying = false; } @@ -464,6 +536,19 @@ namespace Prism CopyComponentIfExists(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); } + Entity Scene::FindEntityByTag(const std::string &tag) { + // TODO: If this becomes used often, consider indexing by tag + const auto view = m_Registry.view(); + for (const auto entity : view) + { + const auto& canditate = view.get(entity).Tag; + if (canditate == tag) + return Entity(entity, this); + } + + return Entity{}; + } + void Scene::CopyTo(Ref& target) { target->m_Light = m_Light; diff --git a/Prism/src/Prism/Scene/Scene.h b/Prism/src/Prism/Scene/Scene.h index e93f011..1069078 100644 --- a/Prism/src/Prism/Scene/Scene.h +++ b/Prism/src/Prism/Scene/Scene.h @@ -28,7 +28,7 @@ namespace Prism struct Light { - glm::vec3 Direction{0.0f, 0.0f, 0.0f}; + glm::vec3 Direction{-0.314f, -0.941f, -0.209f}; glm::vec3 Radiance{ 0.0f, 0.0f, 0.0f}; float Multiplier = 1.0f; @@ -80,6 +80,8 @@ namespace Prism return m_Registry.view(); } + Entity FindEntityByTag(const std::string& tag); + const EntityMap& GetEntityMap() const { return m_EntityIDMap; } void CopyTo(Ref& target); @@ -107,6 +109,7 @@ namespace Prism EntityMap m_EntityIDMap; entt::entity m_SelectedEntity; + Entity* m_PhysicsBodyEntityBuffer = nullptr; Light m_Light; float m_LightMultiplier = 0.3f; @@ -124,6 +127,7 @@ namespace Prism friend class SceneSerializer; friend class SceneHierarchyPanel; friend void OnScriptComponentConstruct(entt::registry& registry, entt::entity entity); + friend void OnScriptComponentDestroy(entt::registry& registry, entt::entity entity); }; } diff --git a/Prism/src/Prism/Scene/SceneSerializer.cpp b/Prism/src/Prism/Scene/SceneSerializer.cpp index 5a4a5bd..b25f1ac 100644 --- a/Prism/src/Prism/Scene/SceneSerializer.cpp +++ b/Prism/src/Prism/Scene/SceneSerializer.cpp @@ -296,7 +296,7 @@ namespace Prism const auto& rigidbody2DComponent = entity.GetComponent(); out << YAML::Key << "BodyType" << YAML::Value << (int)rigidbody2DComponent.BodyType; - out << YAML::Key << "Mass" << YAML::Value << rigidbody2DComponent.Mass; + out << YAML::Key << "FixedRotation" << YAML::Value << rigidbody2DComponent.FixedRotation; out << YAML::EndMap; // RigidBody2DComponent } @@ -309,6 +309,8 @@ namespace Prism const auto& boxCollider2DComponent = entity.GetComponent(); out << YAML::Key << "Offset" << YAML::Value << boxCollider2DComponent.Offset; out << YAML::Key << "Size" << YAML::Value << boxCollider2DComponent.Size; + out << YAML::Key << "Density" << YAML::Value << boxCollider2DComponent.Density; + out << YAML::Key << "Friction" << YAML::Value << boxCollider2DComponent.Friction; out << YAML::EndMap; // BoxCollider2DComponent } @@ -321,6 +323,8 @@ namespace Prism const auto& circleCollider2DComponent = entity.GetComponent(); out << YAML::Key << "Offset" << YAML::Value << circleCollider2DComponent.Offset; out << YAML::Key << "Radius" << YAML::Value << circleCollider2DComponent.Radius; + out << YAML::Key << "Density" << YAML::Value << circleCollider2DComponent.Density; + out << YAML::Key << "Friction" << YAML::Value << circleCollider2DComponent.Friction; out << YAML::EndMap; // CircleCollider2DComponent } @@ -538,7 +542,7 @@ namespace Prism { auto& component = deserializedEntity.AddComponent(); component.BodyType = (RigidBody2DComponent::Type)rigidBody2DComponent["BodyType"].as(); - component.Mass = rigidBody2DComponent["Mass"].as(); + component.FixedRotation = rigidBody2DComponent["FixedRotation"] ? rigidBody2DComponent["FixedRotation"].as() : false; } if (auto boxCollider2DComponent = entity["BoxCollider2DComponent"]) @@ -546,6 +550,8 @@ namespace Prism auto& component = deserializedEntity.AddComponent(); component.Offset = boxCollider2DComponent["Offset"].as(); component.Size = boxCollider2DComponent["Size"].as(); + component.Density = boxCollider2DComponent["Density"] ? boxCollider2DComponent["Density"].as() : 1.0f; + component.Friction = boxCollider2DComponent["Friction"] ? boxCollider2DComponent["Friction"].as() : 1.0f; } if (auto circleCollider2DComponent = entity["CircleCollider2DComponent"]) @@ -553,6 +559,8 @@ namespace Prism auto& component = deserializedEntity.AddComponent(); component.Offset = circleCollider2DComponent["Offset"].as(); component.Radius = circleCollider2DComponent["Radius"].as(); + component.Density = circleCollider2DComponent["Density"] ? circleCollider2DComponent["Density"].as() : 1.0f; + component.Friction = circleCollider2DComponent["Friction"] ? circleCollider2DComponent["Friction"].as() : 1.0f; } } } diff --git a/Prism/src/Prism/Script/ScriptEngine.cpp b/Prism/src/Prism/Script/ScriptEngine.cpp index 07a83c2..e019ca5 100644 --- a/Prism/src/Prism/Script/ScriptEngine.cpp +++ b/Prism/src/Prism/Script/ScriptEngine.cpp @@ -28,6 +28,12 @@ namespace Prism static EntityInstanceMap s_EntityInstanceMap; + static MonoAssembly* s_AppAssembly = nullptr; + static MonoAssembly* s_CoreAssembly = nullptr; + MonoImage* s_AppAssemblyImage = nullptr; + MonoImage* s_CoreAssemblyImage = nullptr; + + static MonoMethod* GetMethod(MonoImage* image, const std::string& methodDesc); struct EntityScriptClass @@ -41,10 +47,18 @@ namespace Prism MonoMethod* OnDestroyMethod = nullptr; MonoMethod* OnUpdateMethod = nullptr; + // Physics + MonoMethod* OnCollision2DBeginMethod = nullptr; + MonoMethod* OnCollision2DEndMethod = nullptr; + void InitClassMethods(MonoImage* image) { OnCreateMethod = GetMethod(image, FullName + ":OnCreate()"); OnUpdateMethod = GetMethod(image, FullName + ":OnUpdate(single)"); + + // Physics (Entity class) + OnCollision2DBeginMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollision2DBegin(single)"); + OnCollision2DEndMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollision2DEnd(single)"); } }; @@ -159,11 +173,11 @@ namespace Prism { MonoMethodDesc* desc = mono_method_desc_new(methodDesc.c_str(), 0); if (!desc) - std::cout << "mono_method_desc_new failed" << std::endl; + PM_CORE_ERROR("mono_method_desc_new failed: {}", methodDesc); MonoMethod* method = mono_method_desc_search_in_image(desc, image); if (!method) - std::cout << "mono_method_desc_search_in_image failed" << std::endl; + PM_CORE_ERROR("mono_method_desc_search_in_image failed: {}", methodDesc); return method; } @@ -206,11 +220,6 @@ namespace Prism } } - static MonoAssembly* s_AppAssembly = nullptr; - static MonoAssembly* s_CoreAssembly = nullptr; - MonoImage* s_AppAssemblyImage = nullptr; - MonoImage* s_CoreAssemblyImage = nullptr; - static void LoadPrismRuntimeAssembly(const std::string& path) { if (s_AppAssembly) @@ -445,7 +454,41 @@ namespace Prism } } - void ScriptEngine::OnScriptComponentDestroyed(UUID sceneID, UUID entityID) + void ScriptEngine::OnCollision2DBegin(Entity entity) + { + OnCollision2DBegin(entity.m_Scene->GetUUID(), entity.GetComponent().ID); + } + + void ScriptEngine::OnCollision2DBegin(const UUID &sceneID, const UUID &entityID) + { + EntityInstance& entityInstance = GetEntityInstanceData(sceneID, entityID).Instance; + if (entityInstance.ScriptClass->OnCollision2DBeginMethod) + { + float value = 5.0f; + void* args[] = { &value }; + CallMethod(entityInstance.GetInstance(), entityInstance.ScriptClass->OnCollision2DBeginMethod, args); + } + + } + + void ScriptEngine::OnCollision2DEnd(Entity entity) + { + OnCollision2DEnd(entity.m_Scene->GetUUID(), entity.GetComponent().ID); + } + + void ScriptEngine::OnCollision2DEnd(const UUID &sceneID, const UUID &entityID) + { + EntityInstance& entityInstance = GetEntityInstanceData(sceneID, entityID).Instance; + if (entityInstance.ScriptClass->OnCollision2DEndMethod) + { + float value = 5.0f; + void* args[] = { &value }; + CallMethod(entityInstance.GetInstance(), entityInstance.ScriptClass->OnCollision2DEndMethod, args); + } + + } + + void ScriptEngine::OnScriptComponentDestroyed(const UUID &sceneID, const UUID &entityID) { PM_CORE_ASSERT(s_EntityInstanceMap.find(sceneID) != s_EntityInstanceMap.end()); auto& entityMap = s_EntityInstanceMap.at(sceneID); diff --git a/Prism/src/Prism/Script/ScriptEngine.h b/Prism/src/Prism/Script/ScriptEngine.h index 582db18..5cbdf10 100644 --- a/Prism/src/Prism/Script/ScriptEngine.h +++ b/Prism/src/Prism/Script/ScriptEngine.h @@ -118,7 +118,12 @@ namespace Prism static void OnCreateEntity(UUID sceneID, UUID entityID); static void OnUpdateEntity(UUID sceneID, UUID entityID, TimeStep ts); - static void OnScriptComponentDestroyed(UUID sceneID, UUID entityID); + static void OnCollision2DBegin(Entity entity); + static void OnCollision2DBegin(const UUID &sceneID, const UUID &entityID); + static void OnCollision2DEnd(Entity entity); + static void OnCollision2DEnd(const UUID &sceneID, const UUID &entityID); + + static void OnScriptComponentDestroyed(const UUID &sceneID, const UUID &entityID); static bool ModuleExists(const std::string& moduleName); static void InitScriptEntity(Entity entity); diff --git a/Prism/src/Prism/Script/ScriptEngineRegistry.cpp b/Prism/src/Prism/Script/ScriptEngineRegistry.cpp index a4528bf..bdc955f 100644 --- a/Prism/src/Prism/Script/ScriptEngineRegistry.cpp +++ b/Prism/src/Prism/Script/ScriptEngineRegistry.cpp @@ -52,6 +52,7 @@ namespace Prism mono_add_internal_call("Prism.Entity::SetTransform_Native",(const void*)Prism::Script::Prism_Entity_SetTransform); mono_add_internal_call("Prism.Entity::CreateComponent_Native",(const void*)Prism::Script::Prism_Entity_CreateComponent); mono_add_internal_call("Prism.Entity::HasComponent_Native",(const void*)Prism::Script::Prism_Entity_HasComponent); + mono_add_internal_call("Prism.Entity::FindEntityByTag_Native", (const void*)Prism::Script::Prism_Entity_FindEntityByTag); mono_add_internal_call("Prism.MeshComponent::GetMesh_Native",(const void*)Prism::Script::Prism_MeshComponent_GetMesh); mono_add_internal_call("Prism.MeshComponent::SetMesh_Native",(const void*)Prism::Script::Prism_MeshComponent_SetMesh); @@ -59,6 +60,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.RigidBody2DComponent::GetLinearVelocity_Native", (const void *)Prism::Script::Prism_RigidBody2DComponent_GetLinearVelocity); + mono_add_internal_call("Prism.RigidBody2DComponent::SetLinearVelocity_Native", (const void *)Prism::Script::Prism_RigidBody2DComponent_SetLinearVelocity); 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); diff --git a/Prism/src/Prism/Script/ScriptWarppers.cpp b/Prism/src/Prism/Script/ScriptWarppers.cpp index 7cdd542..5605949 100644 --- a/Prism/src/Prism/Script/ScriptWarppers.cpp +++ b/Prism/src/Prism/Script/ScriptWarppers.cpp @@ -108,6 +108,18 @@ namespace Prism { namespace Script { return result; } + uint64_t Prism_Entity_FindEntityByTag(MonoString* tag) + { + Ref scene = ScriptEngine::GetCurrentSceneContext(); + PM_CORE_ASSERT(scene, "No active scene!"); + + Entity entity = scene->FindEntityByTag(mono_string_to_utf8(tag)); + if (entity) + return entity.GetComponent().ID; + + return 0; + } + void* Prism_MeshComponent_GetMesh(uint64_t entityID) { Ref scene = ScriptEngine::GetCurrentSceneContext(); @@ -148,6 +160,68 @@ namespace Prism { namespace Script { b2Body_ApplyLinearImpulse(body, *(const b2Vec2*)impulse, b2Body_GetWorldCenterOfMass(body) + *(const b2Vec2*)offset, wake); } + void Prism_RigidBody2DComponent_GetLinearVelocity(uint64_t entityID, glm::vec2 *outVelocity) + { + 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(); + + b2Vec2 velocity = b2Body_GetLinearVelocity(component.RuntimeBodyID); + + PM_CORE_ASSERT(outVelocity); + *outVelocity = { velocity.x, velocity.y }; +} + + void Prism_RigidBody2DComponent_SetLinearVelocity(uint64_t entityID, glm::vec2 *velocity) + { + 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(); + + PM_CORE_ASSERT(velocity); + b2Body_SetLinearVelocity(component.RuntimeBodyID, {velocity->x, velocity->y}); + } + + void Hazel_RigidBody2DComponent_GetLinearVelocity(uint64_t entityID, glm::vec2* outVelocity) + { + 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(); + const auto& velocity = b2Body_GetLinearVelocity(component.RuntimeBodyID); + PM_CORE_ASSERT(outVelocity); + *outVelocity = { velocity.x, velocity.y }; + } + + void Hazel_RigidBody2DComponent_SetLinearVelocity(uint64_t entityID, glm::vec2* velocity) + { + 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()); + const auto& component = entity.GetComponent(); + PM_CORE_ASSERT(velocity); + b2Body_SetLinearVelocity(component.RuntimeBodyID, {velocity->x, velocity->y}); + } + + Ref* Prism_Mesh_Constructor(MonoString* filepath) { return new Ref(new Mesh(mono_string_to_utf8(filepath))); diff --git a/Prism/src/Prism/Script/ScriptWarppers.h b/Prism/src/Prism/Script/ScriptWarppers.h index 0b5d716..c173b2f 100644 --- a/Prism/src/Prism/Script/ScriptWarppers.h +++ b/Prism/src/Prism/Script/ScriptWarppers.h @@ -28,12 +28,15 @@ namespace Prism { namespace Script { void Prism_Entity_SetTransform(uint64_t entityID, glm::mat4* inTransform); void Prism_Entity_CreateComponent(uint64_t entityID, void* type); bool Prism_Entity_HasComponent(uint64_t entityID, void* type); + uint64_t Prism_Entity_FindEntityByTag(MonoString* tag); 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); + void Prism_RigidBody2DComponent_GetLinearVelocity(uint64_t entityID, glm::vec2* outVelocity); + void Prism_RigidBody2DComponent_SetLinearVelocity(uint64_t entityID, glm::vec2* velocity); // Renderer // Texture2D