add box2D colliders simple impl, some little tweaks, fixed camera bug

This commit is contained in:
2025-12-13 22:42:03 +08:00
parent 4140a5b4be
commit c92c831d02
30 changed files with 964 additions and 310 deletions

Binary file not shown.

View File

@ -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

View File

@ -6,27 +6,20 @@ namespace Example
{ {
public float Speed; public float Speed;
private Entity m_PlayerEntity;
public void OnCreate() public void OnCreate()
{ {
m_PlayerEntity = FindEntityByTag("Player");
} }
public void OnUpdate(float ts) public void OnUpdate(float ts)
{ {
Mat4 transform = GetTransform(); Mat4 transform = GetTransform();
Vec3 translation = transform.Translation; Vec3 translation = transform.Translation;
translation.XY = m_PlayerEntity.GetTransform().Translation.XY;
float speed = Speed * ts; translation.Y = Math.Max(translation.Y, 4.5f);
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;
transform.Translation = translation; transform.Translation = translation;
SetTransform(transform); SetTransform(transform);
} }

View File

@ -11,11 +11,17 @@ namespace Example
class PlayerCube : Entity class PlayerCube : Entity
{ {
public float HorizontalForce = 10.0f; public float HorizontalForce = 10.0f;
public float VerticalForce = 10.0f; public float JumpForce = 10.0f;
private RigidBody2DComponent m_PhysicsBody; private RigidBody2DComponent m_PhysicsBody;
private MaterialInstance m_MeshMaterial; private MaterialInstance m_MeshMaterial;
int m_CollisionCounter = 0;
public Vec2 MaxSpeed = new Vec2();
private bool Colliding => m_CollisionCounter > 0;
void OnCreate() void OnCreate()
{ {
m_PhysicsBody = GetComponent<RigidBody2DComponent>(); m_PhysicsBody = GetComponent<RigidBody2DComponent>();
@ -23,23 +29,46 @@ namespace Example
MeshComponent meshComponent = GetComponent<MeshComponent>(); MeshComponent meshComponent = GetComponent<MeshComponent>();
m_MeshMaterial = meshComponent.Mesh.GetMaterial(0); m_MeshMaterial = meshComponent.Mesh.GetMaterial(0);
m_MeshMaterial.Set("u_Metalness", 0.0f); 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) void OnUpdate(float ts)
{ {
float movementForce = HorizontalForce;
if (!Colliding)
{
movementForce *= 0.4f;
}
if (Input.IsKeyPressed(KeyCode.D)) 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)) 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)) if (Colliding && Input.IsKeyPressed(KeyCode.Space))
m_PhysicsBody.ApplyLinearImpulse(new Vec2(0, VerticalForce), new Vec2(0, -10), true); m_PhysicsBody.ApplyLinearImpulse(new Vec2(0, JumpForce), new Vec2(0, 0), true);
Vec3 color = new Vec3(0.8f, 0.8f, 0.8f); if (m_CollisionCounter > 0)
if (Input.IsKeyPressed(KeyCode.Q)) m_MeshMaterial.Set("u_AlbedoColor", new Vec3(1.0f, 0.0f, 0.0f));
color = new Vec3(0.0f, 1.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)) if (Input.IsKeyPressed(KeyCode.R))
{ {

View File

@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace Prism namespace Prism
@ -10,6 +11,16 @@ namespace Prism
{ {
} }
private List<Action<float>> m_Collision2DBeginCallbacks = new List<Action<float>>();
private List<Action<float>> m_Collision2DEndCallbacks = new List<Action<float>>();
protected Entity() { ID = 0; }
internal Entity(ulong id)
{
ID = id;
}
public T CreateComponent<T>() where T : Component, new() public T CreateComponent<T>() where T : Component, new()
{ {
CreateComponent_Native(ID, typeof(T)); CreateComponent_Native(ID, typeof(T));
@ -34,6 +45,12 @@ namespace Prism
return null; return null;
} }
public Entity FindEntityByTag(string tag)
{
ulong entityID = FindEntityByTag_Native(tag);
return new Entity(entityID);
}
public Mat4 GetTransform() public Mat4 GetTransform()
{ {
Mat4 mat4Instance; Mat4 mat4Instance;
@ -46,6 +63,28 @@ namespace Prism
SetTransform_Native(ID, ref transform); SetTransform_Native(ID, ref transform);
} }
public void AddCollision2DBeginCallback(Action<float> callback)
{
m_Collision2DBeginCallbacks.Add(callback);
}
public void AddCollision2DEndCallback(Action<float> 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)] [MethodImpl(MethodImplOptions.InternalCall)]
private static extern void CreateComponent_Native(ulong entityID, Type type); private static extern void CreateComponent_Native(ulong entityID, Type type);
[MethodImpl(MethodImplOptions.InternalCall)] [MethodImpl(MethodImplOptions.InternalCall)]
@ -54,6 +93,8 @@ namespace Prism
private static extern void GetTransform_Native(ulong entityID, out Mat4 matrix); private static extern void GetTransform_Native(ulong entityID, out Mat4 matrix);
[MethodImpl(MethodImplOptions.InternalCall)] [MethodImpl(MethodImplOptions.InternalCall)]
private static extern void SetTransform_Native(ulong entityID, ref Mat4 matrix); private static extern void SetTransform_Native(ulong entityID, ref Mat4 matrix);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern ulong FindEntityByTag_Native(string tag);
} }
} }

View File

@ -18,5 +18,27 @@ namespace Prism
X = x; X = x;
Y = y; 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);
}
} }
} }

View File

@ -2,18 +2,24 @@ using System.Runtime.InteropServices;
namespace Prism namespace Prism
{ {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Sequential)]
public struct Vec3 public struct Vec3
{ {
[FieldOffset(0)] public float X; public float X;
[FieldOffset(4)] public float Y; public float Y;
[FieldOffset(8)] public float Z; public float Z;
public Vec3(float scalar) public Vec3(float scalar)
{ {
X = Y = Z = 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) public Vec3(float x, float y, float z)
{ {
X = x; X = x;
@ -21,6 +27,27 @@ namespace Prism
Z = z; 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; }
}
} }
} }

View File

@ -100,7 +100,27 @@ namespace Prism
ApplyLinearImpulse_Native(Entity.ID, ref impulse, ref offset, wake); 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)] [MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void ApplyLinearImpulse_Native(ulong entityID, ref Vec2 impulse, ref Vec2 offset, bool wake); 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
{
} }
} }

View File

@ -52,6 +52,12 @@ namespace Prism
memset(Data, 0, Size); memset(Data, 0, Size);
} }
template<typename T>
T& Read(const uint32_t offset = 0)
{
return *static_cast<T*>(Data + offset);
}
void Write(const void* data, const uint32_t size, const uint32_t offset = 0) const void Write(const void* data, const uint32_t size, const uint32_t offset = 0) const
{ {
PM_CORE_ASSERT(offset + size <= Size, "Buffer overflow!"); PM_CORE_ASSERT(offset + size <= Size, "Buffer overflow!");

View File

@ -48,14 +48,14 @@ namespace Prism
template<typename T2> template<typename T2>
Ref(const Ref<T2>& other) Ref(const Ref<T2>& other)
{ {
m_Instance = other.m_Instance; m_Instance = (T*)other.m_Instance;
IncRef(); IncRef();
} }
template<typename T2> template<typename T2>
Ref(Ref&& other) Ref(Ref<T2*>&& other)
{ {
m_Instance = other.m_Instance; m_Instance = (T*)other.m_Instance;
other.m_Instance = nullptr; other.m_Instance = nullptr;
} }

View File

@ -73,7 +73,6 @@ namespace Prism
float m_Distance; float m_Distance;
float m_Exposure = 0.8f;
float m_Pitch, m_Yaw; float m_Pitch, m_Yaw;
}; };

View File

@ -111,6 +111,30 @@ namespace Prism
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
} }
if (!m_SelectionContext.HasComponent<RigidBody2DComponent>())
{
if (ImGui::Button("Rigidbody 2D"))
{
m_SelectionContext.AddComponent<RigidBody2DComponent>();
ImGui::CloseCurrentPopup();
}
}
if (!m_SelectionContext.HasComponent<BoxCollider2DComponent>())
{
if (ImGui::Button("Box Collider 2D"))
{
m_SelectionContext.AddComponent<BoxCollider2DComponent>();
ImGui::CloseCurrentPopup();
}
}
if (!m_SelectionContext.HasComponent<CircleCollider2DComponent>())
{
if (ImGui::Button("Circle Collider 2D"))
{
m_SelectionContext.AddComponent<CircleCollider2DComponent>();
ImGui::CloseCurrentPopup();
}
}
ImGui::EndPopup(); ImGui::EndPopup();
} }
} }
@ -323,6 +347,28 @@ namespace Prism
ImGui::NextColumn(); 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) static bool Property(const char* label, int& value)
{ {
bool modified = false; bool modified = false;
@ -444,6 +490,48 @@ namespace Prism
PopID(); PopID();
} }
template<typename T, typename UIFunction>
static void DrawComponent(const std::string& name, Entity entity, UIFunction uiFunction)
{
if (entity.HasComponent<T>())
{
bool removeComponent = false;
auto& component = entity.GetComponent<T>();
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<T>();
}
}
void SceneHierarchyPanel::DrawComponents(Entity entity) void SceneHierarchyPanel::DrawComponents(Entity entity)
{ {
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
@ -532,225 +620,243 @@ namespace Prism
ImGui::Separator(); ImGui::Separator();
} }
DrawComponent<MeshComponent>("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<MeshComponent>()) if (meshComponent.Mesh)
{ ImGui::InputText("##meshFilePath", (char*)meshComponent.Mesh->GetFilePath().c_str(), 256, ImGuiInputTextFlags_ReadOnly);
auto& mc = entity.GetComponent<MeshComponent>(); else
if (ImGui::TreeNodeEx((void*)((uint32_t)entity | typeid(MeshComponent).hash_code()), ImGuiTreeNodeFlags_DefaultOpen, "Mesh")) ImGui::InputText("##meshFilePath", (char*)"Null", 256, ImGuiInputTextFlags_ReadOnly);
ImGui::PopItemWidth();
ImGui::NextColumn();
if (ImGui::Button("...##openmesh"))
{ {
ImGui::Columns(3); const std::string file = Application::Get().OpenFile();
ImGui::SetColumnWidth(0, 100); if (!file.empty())
ImGui::SetColumnWidth(1, 300); meshComponent.Mesh = Ref<Mesh>::Create(file);
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<Mesh>::Create(file);
}
ImGui::NextColumn();
ImGui::Columns(1);
ImGui::TreePop();
} }
ImGui::Separator(); });
}
if (entity.HasComponent<CameraComponent>())
{ DrawComponent<CameraComponent>("Camera", entity, [](CameraComponent& cameraComponent) {
auto& cc = entity.GetComponent<CameraComponent>(); // Projection Type
if (ImGui::TreeNodeEx((void*)((uint32_t)entity | typeid(CameraComponent).hash_code()), ImGuiTreeNodeFlags_DefaultOpen, "Camera")) const char* projTypeStrings[] = { "Perspective", "Orthographic" };
const char* currentProj = projTypeStrings[(int)cameraComponent.Camera.GetProjectionType()];
if (ImGui::BeginCombo("Projection", currentProj))
{ {
// Projection Type for (int type = 0; type < 2; 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++) const bool is_selected = (currentProj == projTypeStrings[type]);
if (ImGui::Selectable(projTypeStrings[type], is_selected))
{ {
bool is_selected = (currentProj == projTypeStrings[type]); currentProj = projTypeStrings[type];
if (ImGui::Selectable(projTypeStrings[type], is_selected)) cameraComponent.Camera.SetProjectionType((SceneCamera::ProjectionType)type);
{
currentProj = projTypeStrings[type];
cc.Camera.SetProjectionType((SceneCamera::ProjectionType)type);
}
if (is_selected)
ImGui::SetItemDefaultFocus();
} }
ImGui::EndCombo(); if (is_selected)
ImGui::SetItemDefaultFocus();
} }
ImGui::EndCombo();
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::Separator();
}
if (entity.HasComponent<SpriteRendererComponent>()) BeginPropertyGrid();
{ // Perspective parameters
auto& src = entity.GetComponent<SpriteRendererComponent>(); if (cameraComponent.Camera.GetProjectionType() == SceneCamera::ProjectionType::Perspective)
if (ImGui::TreeNodeEx((void*)((uint32_t)entity | typeid(SpriteRendererComponent).hash_code()), ImGuiTreeNodeFlags_DefaultOpen, "Sprite Renderer"))
{ {
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<ScriptComponent>()) // Orthographic parameters
{ else if (cameraComponent.Camera.GetProjectionType() == SceneCamera::ProjectionType::Orthographic)
auto& sc = entity.GetComponent<ScriptComponent>();
if (ImGui::TreeNodeEx((void*)((uint32_t)entity | typeid(ScriptComponent).hash_code()), ImGuiTreeNodeFlags_DefaultOpen, "Script"))
{ {
BeginPropertyGrid(); float orthoSize = cameraComponent.Camera.GetOrthographicSize();
std::string oldName = sc.ModuleName; 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<SpriteRendererComponent>("Sprite Renderer", entity, [](SpriteRendererComponent& mc)
{
});
DrawComponent<ScriptComponent>("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 auto& publicFields = moduleFieldMap.at(scriptComponent.ModuleName);
if (ScriptEngine::ModuleExists(oldName)) for (auto& [name, field] : publicFields)
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(sc.ModuleName); bool isRuntime = m_Context->m_IsPlaying && field.IsRuntimeAvailable();
for (auto& [name, field] : publicFields) switch (field.Type)
{ {
bool isRuntime = m_Context->m_IsPlaying && field.IsRuntimeAvailable(); case FieldType::Int:
switch (field.Type) {
int value = isRuntime ? field.GetRuntimeValue<int>() : field.GetStoredValue<int>();
if (Property(field.Name.c_str(), value))
{ {
case FieldType::Int: if (isRuntime)
{ field.SetRuntimeValue(value);
int value = isRuntime ? field.GetRuntimeValue<int>() : field.GetStoredValue<int>();
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<float>() : field.GetStoredValue<float>();
if (Property(field.Name.c_str(), value, 0.2f))
{
if (isRuntime)
field.SetRuntimeValue(value);
else else
field.SetStoredValue(value); field.SetStoredValue(value);
}
break;
} }
case FieldType::Vec2: break;
}
case FieldType::Float:
{
float value = isRuntime ? field.GetRuntimeValue<float>() : field.GetStoredValue<float>();
if (Property(field.Name.c_str(), value, 0.2f))
{ {
glm::vec2 value = isRuntime ? field.GetRuntimeValue<glm::vec2>() : field.GetStoredValue<glm::vec2>(); if (isRuntime)
if (Property(field.Name.c_str(), value, 0.2f)) field.SetRuntimeValue(value);
{ else
if (isRuntime) field.SetStoredValue(value);
field.SetRuntimeValue(value);
else
field.SetStoredValue(value);
}
break;
} }
case FieldType::Vec3: break;
}
case FieldType::Vec2:
{
glm::vec2 value = isRuntime ? field.GetRuntimeValue<glm::vec2>() : field.GetStoredValue<glm::vec2>();
if (Property(field.Name.c_str(), value, 0.2f))
{ {
glm::vec3 value = isRuntime ? field.GetRuntimeValue<glm::vec3>() : field.GetStoredValue<glm::vec3>(); if (isRuntime)
if (Property(field.Name.c_str(), value, 0.2f)) field.SetRuntimeValue(value);
{ else
if (isRuntime) field.SetStoredValue(value);
field.SetRuntimeValue(value);
else
field.SetStoredValue(value);
}
break;
} }
case FieldType::Vec4: break;
}
case FieldType::Vec3:
{
glm::vec3 value = isRuntime ? field.GetRuntimeValue<glm::vec3>() : field.GetStoredValue<glm::vec3>();
if (Property(field.Name.c_str(), value, 0.2f))
{ {
glm::vec4 value = isRuntime ? field.GetRuntimeValue<glm::vec4>() : field.GetStoredValue<glm::vec4>(); if (isRuntime)
if (Property(field.Name.c_str(), value, 0.2f)) field.SetRuntimeValue(value);
{ else
if (isRuntime) field.SetStoredValue(value);
field.SetRuntimeValue(value);
else
field.SetStoredValue(value);
}
break;
} }
break;
}
case FieldType::Vec4:
{
glm::vec4 value = isRuntime ? field.GetRuntimeValue<glm::vec4>() : field.GetStoredValue<glm::vec4>();
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<RigidBody2DComponent>("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<BoxCollider2DComponent>("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<CircleCollider2DComponent>("Circle Collider 2D", entity, [](CircleCollider2DComponent& cc2dComponent)
{
BeginPropertyGrid();
Property("Offset", cc2dComponent.Offset);
Property("Radius", cc2dComponent.Radius);
Property("Density", cc2dComponent.Density);
Property("Friction", cc2dComponent.Friction);
EndPropertyGrid();
});
} }

View File

@ -48,14 +48,10 @@ namespace Prism
OpenGLVertexBuffer::~OpenGLVertexBuffer() OpenGLVertexBuffer::~OpenGLVertexBuffer()
{ {
#ifdef __MINGW32__
glDeleteBuffers(1, &m_RendererID);
#else
GLuint rendererID = m_RendererID; GLuint rendererID = m_RendererID;
Renderer::Submit([rendererID](){ Renderer::Submit([rendererID](){
glDeleteBuffers(1, &rendererID); glDeleteBuffers(1, &rendererID);
}); });
#endif
} }
void OpenGLVertexBuffer::SetData(void* buffer, uint32_t size, uint32_t offset) void OpenGLVertexBuffer::SetData(void* buffer, uint32_t size, uint32_t offset)
@ -105,13 +101,10 @@ namespace Prism
OpenGLIndexBuffer::~OpenGLIndexBuffer() OpenGLIndexBuffer::~OpenGLIndexBuffer()
{ {
#ifdef __MINGW32__ const GLuint rendererID = m_RendererID;
glDeleteBuffers(1, &m_RendererID); Renderer::Submit([rendererID](){
#else glDeleteBuffers(1, &rendererID);
Renderer::Submit([this](){
glDeleteBuffers(1, &m_RendererID);
}); });
#endif
} }
void OpenGLIndexBuffer::SetData(void* data, uint32_t size, uint32_t offset) void OpenGLIndexBuffer::SetData(void* data, uint32_t size, uint32_t offset)

View File

@ -19,13 +19,10 @@ namespace Prism
OpenGLFrameBuffer::~OpenGLFrameBuffer() OpenGLFrameBuffer::~OpenGLFrameBuffer()
{ {
#ifdef __MINGW32__ GLuint rendererID = m_RendererID;
glDeleteFramebuffers(1, &m_RendererID); Renderer::Submit([rendererID](){
#else glDeleteFramebuffers(1, &rendererID);
Renderer::Submit([=](){
glDeleteFramebuffers(1, &m_RendererID);
}); });
#endif
} }
void OpenGLFrameBuffer::Bind() const void OpenGLFrameBuffer::Bind() const
@ -71,13 +68,12 @@ namespace Prism
// TODO: Create Prism texture object based on format here // TODO: Create Prism texture object based on format here
if (m_Specification.Format == FramebufferFormat::RGBA16F) if (m_Specification.Format == FramebufferFormat::RGBA16F)
{ {
glTexImage2DMultisample(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);
//glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_RGBA16F, m_Specification.Width, m_Specification.Height, GL_FALSE);
} }
else if (m_Specification.Format == FramebufferFormat::RGBA8) else if (m_Specification.Format == FramebufferFormat::RGBA8)
{ {
// glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_RGBA8, m_Specification.Width, m_Specification.Height, GL_TRUE); // 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_MIN_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_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); glCreateTextures(GL_TEXTURE_2D_MULTISAMPLE, 1, &m_DepthAttachment);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 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); // 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); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
// glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, m_DepthAttachment, 0); // glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, m_DepthAttachment, 0);
} }

View File

@ -118,14 +118,10 @@ namespace Prism
OpenGLTexture2D::~OpenGLTexture2D() OpenGLTexture2D::~OpenGLTexture2D()
{ {
#ifdef __MINGW32__
glDeleteTextures(1, &m_RendererID);
#else
GLuint rendererID = m_RendererID; GLuint rendererID = m_RendererID;
Renderer::Submit([rendererID](){ Renderer::Submit([rendererID](){
glDeleteTextures(1, &rendererID); glDeleteTextures(1, &rendererID);
}); });
#endif
} }
void OpenGLTexture2D::Bind(uint32_t slot) const void OpenGLTexture2D::Bind(uint32_t slot) const
@ -286,14 +282,10 @@ namespace Prism
OpenGLTextureCube::~OpenGLTextureCube() OpenGLTextureCube::~OpenGLTextureCube()
{ {
#ifdef __MINGW32__
glDeleteTextures(1, &m_RendererID);
#else
GLuint rendererID = m_RendererID; GLuint rendererID = m_RendererID;
Renderer::Submit([rendererID]() { Renderer::Submit([rendererID]() {
glDeleteTextures(1, &rendererID); glDeleteTextures(1, &rendererID);
}); });
#endif
} }
void OpenGLTextureCube::Bind(uint32_t slot) const void OpenGLTextureCube::Bind(uint32_t slot) const

View File

@ -40,14 +40,10 @@ namespace Prism
OpenGLVertexArray::~OpenGLVertexArray() OpenGLVertexArray::~OpenGLVertexArray()
{ {
#ifdef __MINGW32__
glDeleteVertexArrays(1, &m_RendererID);
#else
GLuint rendererID = m_RendererID; GLuint rendererID = m_RendererID;
Renderer::Submit([rendererID](){ Renderer::Submit([rendererID](){
glDeleteVertexArrays(1, &rendererID); glDeleteVertexArrays(1, &rendererID);
}); });
#endif
} }
void OpenGLVertexArray::Bind() const void OpenGLVertexArray::Bind() const

View File

@ -38,6 +38,24 @@ namespace Prism
uint32_t GetFlags() const { return m_MaterialFlags; } uint32_t GetFlags() const { return m_MaterialFlags; }
void SetFlag(MaterialFlag flag) { m_MaterialFlags |= (uint32_t)flag; } void SetFlag(MaterialFlag flag) { m_MaterialFlags |= (uint32_t)flag; }
template <typename T>
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<T>(decl->GetOffset());
}
template <typename T>
Ref<T> 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 <typename T> template <typename T>
void Set(const std::string& name, const T& value); void Set(const std::string& name, const T& value);
@ -45,7 +63,11 @@ namespace Prism
void Set(const std::string& name, const Ref<Texture>& texture) void Set(const std::string& name, const Ref<Texture>& texture)
{ {
const auto decl = FindResourceDeclaration(name); const auto decl = FindResourceDeclaration(name);
if (!decl) return; if (!decl)
{
PM_CORE_WARN("Cannot find material property: ", name);
return;
}
uint32_t slot = decl->GetRegister(); uint32_t slot = decl->GetRegister();
if (m_Textures.size() <= slot) if (m_Textures.size() <= slot)
m_Textures.resize((size_t)slot + 1); m_Textures.resize((size_t)slot + 1);
@ -92,6 +114,41 @@ namespace Prism
static Ref<MaterialInstance> Create(const Ref<Material>& material); static Ref<MaterialInstance> Create(const Ref<Material>& material);
template<typename T>
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<T>(decl->GetOffset());
}
template<typename T>
Ref<T> 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<T>(m_Textures[slot]);
}
template<typename T>
Ref<T> 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<T>(m_Textures[slot]);
}
template <typename T> template <typename T>
void Set(const std::string& name, const T& value) 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) void Material::Set(const std::string& name, const T& value)
{ {
auto decl = FindUniformDeclaration(name); 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");
PM_CORE_ASSERT(decl, "Could not find uniform with name 'x'"); const auto& buffer = GetUniformBufferTarget(decl);
auto& buffer = GetUniformBufferTarget(decl);
buffer.Write(&value, decl->GetSize(), decl->GetOffset()); buffer.Write(&value, decl->GetSize(), decl->GetOffset());
for (auto mi : m_MaterialInstances) for (auto mi : m_MaterialInstances)

View File

@ -272,11 +272,12 @@ namespace Prism
PM_CORE_TRACE("COLOR = {0}, {1}, {2}", aiColor.r, aiColor.g, aiColor.b); PM_CORE_TRACE("COLOR = {0}, {1}, {2}", aiColor.r, aiColor.g, aiColor.b);
float shininess, metalness; 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); 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); 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(" COLOR = {0}, {1}, {2}", aiColor.r, aiColor.g, aiColor.b);
PM_MESH_LOG(" ROUGHNESS = {0}", roughness); PM_MESH_LOG(" ROUGHNESS = {0}", roughness);

View File

@ -120,7 +120,7 @@ namespace Prism
const std::vector<Ref<Texture2D>>& GetTextures() const { return m_Textures; } const std::vector<Ref<Texture2D>>& GetTextures() const { return m_Textures; }
const std::string& GetFilePath() const { return m_FilePath; } const std::string& GetFilePath() const { return m_FilePath; }
const std::vector<Triangle> GetTriangleCache(uint32_t index) const { return m_TriangleCache.at(index); } std::vector<Triangle> GetTriangleCache(const uint32_t index) const { return m_TriangleCache.at(index); }
private: private:
void BoneTransform(float time); void BoneTransform(float time);
void ReadNodeHierarchy(float AnimationTime, const aiNode* pNode, const glm::mat4& ParentTransform); void ReadNodeHierarchy(float AnimationTime, const aiNode* pNode, const glm::mat4& ParentTransform);

View File

@ -76,7 +76,6 @@ namespace Prism
s_Data.CompositePass = RenderPass::Create(compRenderPassSpec); s_Data.CompositePass = RenderPass::Create(compRenderPassSpec);
s_Data.CompositeShader = Shader::Create("assets/shaders/SceneComposite.glsl"); 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"); s_Data.BRDFLUT = Texture2D::Create("assets/textures/BRDF_LUT.tga");

View File

@ -27,8 +27,7 @@ namespace Prism
std::string Tag; std::string Tag;
TagComponent() = default; TagComponent() = default;
TagComponent(const TagComponent& other) TagComponent(const TagComponent& other) = default;
: Tag(other.Tag) {}
TagComponent(const std::string& tag) TagComponent(const std::string& tag)
: Tag(tag) {} : Tag(tag) {}
@ -42,8 +41,7 @@ namespace Prism
glm::mat4 Transform; glm::mat4 Transform;
TransformComponent() = default; TransformComponent() = default;
TransformComponent(const TransformComponent& other) TransformComponent(const TransformComponent& other) = default;
: Transform(other.Transform) {}
TransformComponent(const glm::mat4& transform) TransformComponent(const glm::mat4& transform)
: Transform(transform) {} : Transform(transform) {}
@ -57,8 +55,7 @@ namespace Prism
Ref<Prism::Mesh> Mesh; Ref<Prism::Mesh> Mesh;
MeshComponent() = default; MeshComponent() = default;
MeshComponent(const MeshComponent& other) MeshComponent(const MeshComponent& other) = default;
: Mesh(other.Mesh) {}
MeshComponent(const Ref<Prism::Mesh>& mesh) MeshComponent(const Ref<Prism::Mesh>& mesh)
: Mesh(mesh) {} : Mesh(mesh) {}
@ -71,8 +68,7 @@ namespace Prism
std::string ModuleName; std::string ModuleName;
ScriptComponent() = default; ScriptComponent() = default;
ScriptComponent(const ScriptComponent& other) ScriptComponent(const ScriptComponent& other) = default;
: ModuleName(other.ModuleName) {}
ScriptComponent(const std::string& moduleName) ScriptComponent(const std::string& moduleName)
: ModuleName(moduleName) {} : ModuleName(moduleName) {}
}; };
@ -84,8 +80,7 @@ namespace Prism
bool Primary = true; bool Primary = true;
CameraComponent() = default; CameraComponent() = default;
CameraComponent(const CameraComponent& other) CameraComponent(const CameraComponent& other) = default;
: Camera(other.Camera), Primary(other.Primary) {}
operator SceneCamera& () { return Camera; } operator SceneCamera& () { return Camera; }
operator const SceneCamera& () const { return Camera; } operator const SceneCamera& () const { return Camera; }
@ -99,22 +94,20 @@ namespace Prism
float TilingFactor = 1.0f; float TilingFactor = 1.0f;
SpriteRendererComponent() = default; SpriteRendererComponent() = default;
SpriteRendererComponent(const SpriteRendererComponent& other) SpriteRendererComponent(const SpriteRendererComponent& other) = default;
: Color(other.Color), Texture(other.Texture), TilingFactor(other.TilingFactor) {}
}; };
struct RigidBody2DComponent struct RigidBody2DComponent
{ {
enum class Type { Static, Dynamic, Kinematic }; enum class Type { Static, Dynamic, Kinematic };
Type BodyType; Type BodyType;
float Mass = 1.0f; bool FixedRotation = false;
// Storage for BodyID (box2d version 3.0^ use handle to resolve this) // Storage for BodyID (box2d version 3.0^ use handle to resolve this)
b2BodyId RuntimeBodyID = b2_nullBodyId; b2BodyId RuntimeBodyID = b2_nullBodyId;
RigidBody2DComponent() = default; RigidBody2DComponent() = default;
RigidBody2DComponent(const RigidBody2DComponent& other) RigidBody2DComponent(const RigidBody2DComponent& other) = default;
: BodyType(other.BodyType), Mass(other.Mass) {}
}; };
struct BoxCollider2DComponent struct BoxCollider2DComponent
@ -122,12 +115,13 @@ namespace Prism
glm::vec2 Offset = { 0.0f,0.0f }; glm::vec2 Offset = { 0.0f,0.0f };
glm::vec2 Size = { 1.0f, 1.0f }; glm::vec2 Size = { 1.0f, 1.0f };
float Density = 1.0f;
float Friction = 1.0f;
// Storage for runtime // Storage for runtime
// void* RuntimeFixture = nullptr; // void* RuntimeFixture = nullptr;
BoxCollider2DComponent() = default; BoxCollider2DComponent() = default;
BoxCollider2DComponent(const BoxCollider2DComponent& other) BoxCollider2DComponent(const BoxCollider2DComponent& other) = default;
: Offset(other.Offset), Size(other.Size) {}
}; };
struct CircleCollider2DComponent struct CircleCollider2DComponent
@ -135,12 +129,13 @@ namespace Prism
glm::vec2 Offset = { 0.0f,0.0f }; glm::vec2 Offset = { 0.0f,0.0f };
float Radius = 1.0f; float Radius = 1.0f;
float Density = 1.0f;
float Friction = 1.0f;
// Storage for runtime // Storage for runtime
// void* RuntimeFixture = nullptr; // void* RuntimeFixture = nullptr;
CircleCollider2DComponent() = default; CircleCollider2DComponent() = default;
CircleCollider2DComponent(const CircleCollider2DComponent& other) CircleCollider2DComponent(const CircleCollider2DComponent& other) = default;
: Offset(other.Offset), Radius(other.Radius) {}
}; };
} }

View File

@ -25,12 +25,14 @@ namespace Prism
template<typename T, typename... Args> template<typename T, typename... Args>
T& AddComponent(Args&&... args) T& AddComponent(Args&&... args)
{ {
PM_CORE_ASSERT(!HasComponent<T>(), "Entity already has component!");
return m_Scene->m_Registry.emplace<T>(m_EntityHandle, std::forward<Args>(args)...); return m_Scene->m_Registry.emplace<T>(m_EntityHandle, std::forward<Args>(args)...);
} }
template<typename T> template<typename T>
T& GetComponent() T& GetComponent()
{ {
PM_CORE_ASSERT(HasComponent<T>(), "Entity doesn't have component!");
return m_Scene->m_Registry.get<T>(m_EntityHandle); return m_Scene->m_Registry.get<T>(m_EntityHandle);
} }
@ -42,6 +44,7 @@ namespace Prism
template<typename T> template<typename T>
void RemoveComponent() const { void RemoveComponent() const {
PM_CORE_ASSERT(HasComponent<T>(), "Entity doesn't have component!");
if (HasComponent<T>()) if (HasComponent<T>())
m_Scene->m_Registry.remove<T>(m_EntityHandle); m_Scene->m_Registry.remove<T>(m_EntityHandle);
} }
@ -64,7 +67,7 @@ namespace Prism
} }
UUID GetUUID() { return GetComponent<IDComponent>().ID; } UUID GetUUID() { return GetComponent<IDComponent>().ID; }
UUID GetSceneUUID() { return m_Scene->GetUUID(); } UUID GetSceneUUID() const { return m_Scene->GetUUID(); }
private: private:
explicit Entity(const std::string& name); explicit Entity(const std::string& name);

View File

@ -16,6 +16,11 @@
namespace Prism namespace Prism
{ {
// TODO: THIS SHOULD MOVE TO PHYSICS FILE!
std::unordered_map<UUID, Scene*> s_ActiveScenes; std::unordered_map<UUID, Scene*> s_ActiveScenes;
static uint32_t s_SceneIDCounter = 0; static uint32_t s_SceneIDCounter = 0;
@ -29,7 +34,7 @@ namespace Prism
{ {
b2WorldId World; b2WorldId World;
Box2DWorldComponent() = default; Box2DWorldComponent() = delete;
Box2DWorldComponent(const b2Vec2& gravity) { Box2DWorldComponent(const b2Vec2& gravity) {
b2WorldDef worldDef = b2DefaultWorldDef(); b2WorldDef worldDef = b2DefaultWorldDef();
worldDef.gravity = gravity; 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<Entity *>(b2Body_GetUserData(b2Shape_GetBody(event.shapeIdA)));
auto& entityB = *static_cast<Entity *>(b2Body_GetUserData(b2Shape_GetBody(event.shapeIdB)));
if (entityA.HasComponent<ScriptComponent>() && ScriptEngine::ModuleExists(entityA.GetComponent<ScriptComponent>().ModuleName))
ScriptEngine::OnCollision2DBegin(entityA);
if (entityB.HasComponent<ScriptComponent>() && ScriptEngine::ModuleExists(entityB.GetComponent<ScriptComponent>().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<Entity *>(b2Body_GetUserData(b2Shape_GetBody(event.shapeIdA)));
auto& entityB = *static_cast<Entity *>(b2Body_GetUserData(b2Shape_GetBody(event.shapeIdB)));
if (entityA.HasComponent<ScriptComponent>() && ScriptEngine::ModuleExists(entityA.GetComponent<ScriptComponent>().ModuleName))
ScriptEngine::OnCollision2DEnd(entityA);
if (entityB.HasComponent<ScriptComponent>() && ScriptEngine::ModuleExists(entityB.GetComponent<ScriptComponent>().ModuleName))
ScriptEngine::OnCollision2DEnd(entityB);
}
}
void OnTransformConstruct(entt::registry& registry, entt::entity entity) 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) void OnScriptComponentConstruct(entt::registry& registry, entt::entity entity)
@ -55,6 +95,15 @@ namespace Prism
ScriptEngine::InitScriptEntity(scene->m_EntityIDMap.at(entityID)); ScriptEngine::InitScriptEntity(scene->m_EntityIDMap.at(entityID));
} }
void OnScriptComponentDestroy(entt::registry& registry, entt::entity entity)
{
const auto sceneView = registry.view<SceneComponent>();
const UUID sceneID = registry.get<SceneComponent>(sceneView.front()).SceneID;
const auto entityID = registry.get<IDComponent>(entity).ID;
ScriptEngine::OnScriptComponentDestroyed(sceneID, entityID);
}
static std::tuple<glm::vec3, glm::quat, glm::vec3> GetTransformDecomposition(const glm::mat4& transform) static std::tuple<glm::vec3, glm::quat, glm::vec3> GetTransformDecomposition(const glm::mat4& transform)
{ {
glm::vec3 scale, translation, skew; glm::vec3 scale, translation, skew;
@ -79,8 +128,9 @@ namespace Prism
m_SceneEntity = m_Registry.create(); m_SceneEntity = m_Registry.create();
m_Registry.emplace<SceneComponent>(m_SceneEntity, m_SceneID); m_Registry.emplace<SceneComponent>(m_SceneEntity, m_SceneID);
// TODO: Obviously not necessary in all cases // TODO: Obviously not necessary in all cases
m_Registry.emplace<Box2DWorldComponent>(m_SceneEntity, b2Vec2{ 0.0f, -9.8f }); Box2DWorldComponent& b2World = m_Registry.emplace<Box2DWorldComponent>(m_SceneEntity, b2Vec2{ 0.0f, -9.8f });
s_ActiveScenes[m_SceneID] = this; s_ActiveScenes[m_SceneID] = this;
@ -89,6 +139,7 @@ namespace Prism
Scene::~Scene() Scene::~Scene()
{ {
m_Registry.on_destroy<ScriptComponent>().disconnect();
m_Registry.clear(); m_Registry.clear();
s_ActiveScenes.erase(m_SceneID); s_ActiveScenes.erase(m_SceneID);
@ -117,16 +168,27 @@ namespace Prism
// Box2D physics // Box2D physics
auto sceneView = m_Registry.view<Box2DWorldComponent>(); const auto sceneView = m_Registry.view<Box2DWorldComponent>();
auto& box2DWorld = m_Registry.get<Box2DWorldComponent>(sceneView.front()).World; const auto& box2DWorld = m_Registry.get<Box2DWorldComponent>(sceneView.front()).World;
int32_t velocityIterations = 6; int32_t velocityIterations = 6;
int32_t positionIterations = 2; constexpr int32_t positionIterations = 2;
// box2DWorld->Step(ts, velocityIterations, positionIterations); // box2DWorld->Step(ts, velocityIterations, positionIterations);
b2World_Step(box2DWorld, ts, positionIterations); b2World_Step(box2DWorld, ts, positionIterations);
{ {
auto view = m_Registry.view<RigidBody2DComponent>(); ProcessContactEvents(box2DWorld);
for (auto entity : view) /*
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<RigidBody2DComponent>();
for (const auto entity : view)
{ {
Entity e = { entity, this }; Entity e = { entity, this };
auto& transform = e.Transform(); auto& transform = e.Transform();
@ -163,10 +225,10 @@ namespace Prism
m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod); m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod);
auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>); auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
SceneRenderer::BeginScene(this, { camera, cameraViewMatrix }); SceneRenderer::BeginScene(this, { static_cast<Camera>(camera), cameraViewMatrix });
for (auto entity : group) for (auto entity : group)
{ {
auto [transformComponent, meshComponent] = group.get<TransformComponent, MeshComponent>(entity); const auto& [transformComponent, meshComponent] = group.get<TransformComponent, MeshComponent>(entity);
if (meshComponent.Mesh) if (meshComponent.Mesh)
{ {
meshComponent.Mesh->OnUpdate(ts); meshComponent.Mesh->OnUpdate(ts);
@ -208,7 +270,7 @@ namespace Prism
SceneRenderer::BeginScene(this, { static_cast<Camera>(editorCamera), editorCamera.GetViewMatrix() }); SceneRenderer::BeginScene(this, { static_cast<Camera>(editorCamera), editorCamera.GetViewMatrix() });
for (auto entity : group) for (auto entity : group)
{ {
auto [transformComponent, meshComponent] = group.get<TransformComponent, MeshComponent>(entity); const auto& [transformComponent, meshComponent] = group.get<TransformComponent, MeshComponent>(entity);
if (meshComponent.Mesh) if (meshComponent.Mesh)
{ {
meshComponent.Mesh->OnUpdate(ts); meshComponent.Mesh->OnUpdate(ts);
@ -218,7 +280,7 @@ namespace Prism
if (m_SelectedEntity == entity) if (m_SelectedEntity == entity)
SceneRenderer::SubmitSelectedMesh(meshComponent, transformComponent); SceneRenderer::SubmitSelectedMesh(meshComponent, transformComponent);
else else
SceneRenderer::SubmitMesh(meshComponent, transformComponent, nullptr); SceneRenderer::SubmitMesh(meshComponent, transformComponent);
} }
} }
SceneRenderer::EndScene(); SceneRenderer::EndScene();
@ -266,9 +328,12 @@ namespace Prism
auto& world = m_Registry.get<Box2DWorldComponent>(sceneView.front()).World; auto& world = m_Registry.get<Box2DWorldComponent>(sceneView.front()).World;
{ {
auto view = m_Registry.view<RigidBody2DComponent>(); auto view = m_Registry.view<RigidBody2DComponent>();
for (auto entity : view) m_PhysicsBodyEntityBuffer = new Entity[view.size()];
uint32_t physicsBodyEntityBufferIndex = 0;
for (auto entity : view)
{ {
Entity e = { entity, this }; Entity e = { entity, this };
UUID entityID = e.GetComponent<IDComponent>().ID;
auto& transform = e.Transform(); auto& transform = e.Transform();
auto& rigidBody2D = m_Registry.get<RigidBody2DComponent>(entity); auto& rigidBody2D = m_Registry.get<RigidBody2DComponent>(entity);
@ -285,6 +350,13 @@ namespace Prism
float rotationZ = glm::eulerAngles(rotationQuat).z; float rotationZ = glm::eulerAngles(rotationQuat).z;
bodyDef.rotation = b2Rot{cos(rotationZ), sin(rotationZ)}; 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); rigidBody2D.RuntimeBodyID = b2CreateBody(world, &bodyDef);
} }
} }
@ -306,10 +378,10 @@ namespace Prism
b2BodyId bodyId = 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}); b2Polygon boxShape = b2MakeOffsetBox(boxCollider2D.Size.x, boxCollider2D.Size.y, {boxCollider2D.Offset.x,boxCollider2D.Offset.y}, {1.0f, 0.0f});
b2ShapeDef shapeDef = b2DefaultShapeDef(); b2ShapeDef shapeDef = b2DefaultShapeDef();
shapeDef.density = 1.0f; shapeDef.density = boxCollider2D.Density;
shapeDef.material.friction = 1.0f; shapeDef.material.friction = boxCollider2D.Friction;
shapeDef.enableContactEvents = true;
b2CreatePolygonShape(bodyId, &shapeDef, &boxShape); b2CreatePolygonShape(bodyId, &shapeDef, &boxShape);
} }
@ -321,7 +393,6 @@ namespace Prism
for (auto entity : view) for (auto entity : view)
{ {
Entity e = { entity, this }; Entity e = { entity, this };
auto& transform = e.Transform();
auto& circleCollider2D = m_Registry.get<CircleCollider2DComponent>(entity); auto& circleCollider2D = m_Registry.get<CircleCollider2DComponent>(entity);
if (e.HasComponent<RigidBody2DComponent>()) if (e.HasComponent<RigidBody2DComponent>())
@ -333,15 +404,15 @@ namespace Prism
b2Vec2 centor = {circleCollider2D.Offset.x, circleCollider2D.Offset.y}; b2Vec2 centor = {circleCollider2D.Offset.x, circleCollider2D.Offset.y};
b2Circle circleShape{ b2Circle circleShape;
.center = centor, circleShape.center = centor;
.radius = circleCollider2D.Radius circleShape.radius = circleCollider2D.Radius;
};
b2ShapeDef shapeDef = b2DefaultShapeDef(); b2ShapeDef shapeDef = b2DefaultShapeDef();
shapeDef.density = 1.0f; shapeDef.density = circleCollider2D.Density;
shapeDef.material.friction = 1.0f; shapeDef.material.friction = circleCollider2D.Friction;
shapeDef.enableContactEvents = true;
b2CreateCircleShape(bodyId, &shapeDef, &circleShape); b2CreateCircleShape(bodyId, &shapeDef, &circleShape);
} }
@ -354,6 +425,7 @@ namespace Prism
void Scene::OnRuntimeStop() void Scene::OnRuntimeStop()
{ {
delete[] m_PhysicsBodyEntityBuffer;
m_IsPlaying = false; m_IsPlaying = false;
} }
@ -464,6 +536,19 @@ namespace Prism
CopyComponentIfExists<CircleCollider2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); CopyComponentIfExists<CircleCollider2DComponent>(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<TagComponent>();
for (const auto entity : view)
{
const auto& canditate = view.get<TagComponent>(entity).Tag;
if (canditate == tag)
return Entity(entity, this);
}
return Entity{};
}
void Scene::CopyTo(Ref<Scene>& target) void Scene::CopyTo(Ref<Scene>& target)
{ {
target->m_Light = m_Light; target->m_Light = m_Light;

View File

@ -28,7 +28,7 @@ namespace Prism
struct Light 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}; glm::vec3 Radiance{ 0.0f, 0.0f, 0.0f};
float Multiplier = 1.0f; float Multiplier = 1.0f;
@ -80,6 +80,8 @@ namespace Prism
return m_Registry.view<T>(); return m_Registry.view<T>();
} }
Entity FindEntityByTag(const std::string& tag);
const EntityMap& GetEntityMap() const { return m_EntityIDMap; } const EntityMap& GetEntityMap() const { return m_EntityIDMap; }
void CopyTo(Ref<Scene>& target); void CopyTo(Ref<Scene>& target);
@ -107,6 +109,7 @@ namespace Prism
EntityMap m_EntityIDMap; EntityMap m_EntityIDMap;
entt::entity m_SelectedEntity; entt::entity m_SelectedEntity;
Entity* m_PhysicsBodyEntityBuffer = nullptr;
Light m_Light; Light m_Light;
float m_LightMultiplier = 0.3f; float m_LightMultiplier = 0.3f;
@ -124,6 +127,7 @@ namespace Prism
friend class SceneSerializer; friend class SceneSerializer;
friend class SceneHierarchyPanel; friend class SceneHierarchyPanel;
friend void OnScriptComponentConstruct(entt::registry& registry, entt::entity entity); friend void OnScriptComponentConstruct(entt::registry& registry, entt::entity entity);
friend void OnScriptComponentDestroy(entt::registry& registry, entt::entity entity);
}; };
} }

View File

@ -296,7 +296,7 @@ namespace Prism
const auto& rigidbody2DComponent = entity.GetComponent<RigidBody2DComponent>(); const auto& rigidbody2DComponent = entity.GetComponent<RigidBody2DComponent>();
out << YAML::Key << "BodyType" << YAML::Value << (int)rigidbody2DComponent.BodyType; 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 out << YAML::EndMap; // RigidBody2DComponent
} }
@ -309,6 +309,8 @@ namespace Prism
const auto& boxCollider2DComponent = entity.GetComponent<BoxCollider2DComponent>(); const auto& boxCollider2DComponent = entity.GetComponent<BoxCollider2DComponent>();
out << YAML::Key << "Offset" << YAML::Value << boxCollider2DComponent.Offset; out << YAML::Key << "Offset" << YAML::Value << boxCollider2DComponent.Offset;
out << YAML::Key << "Size" << YAML::Value << boxCollider2DComponent.Size; 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 out << YAML::EndMap; // BoxCollider2DComponent
} }
@ -321,6 +323,8 @@ namespace Prism
const auto& circleCollider2DComponent = entity.GetComponent<CircleCollider2DComponent>(); const auto& circleCollider2DComponent = entity.GetComponent<CircleCollider2DComponent>();
out << YAML::Key << "Offset" << YAML::Value << circleCollider2DComponent.Offset; out << YAML::Key << "Offset" << YAML::Value << circleCollider2DComponent.Offset;
out << YAML::Key << "Radius" << YAML::Value << circleCollider2DComponent.Radius; 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 out << YAML::EndMap; // CircleCollider2DComponent
} }
@ -538,7 +542,7 @@ namespace Prism
{ {
auto& component = deserializedEntity.AddComponent<RigidBody2DComponent>(); auto& component = deserializedEntity.AddComponent<RigidBody2DComponent>();
component.BodyType = (RigidBody2DComponent::Type)rigidBody2DComponent["BodyType"].as<int>(); component.BodyType = (RigidBody2DComponent::Type)rigidBody2DComponent["BodyType"].as<int>();
component.Mass = rigidBody2DComponent["Mass"].as<float>(); component.FixedRotation = rigidBody2DComponent["FixedRotation"] ? rigidBody2DComponent["FixedRotation"].as<bool>() : false;
} }
if (auto boxCollider2DComponent = entity["BoxCollider2DComponent"]) if (auto boxCollider2DComponent = entity["BoxCollider2DComponent"])
@ -546,6 +550,8 @@ namespace Prism
auto& component = deserializedEntity.AddComponent<BoxCollider2DComponent>(); auto& component = deserializedEntity.AddComponent<BoxCollider2DComponent>();
component.Offset = boxCollider2DComponent["Offset"].as<glm::vec2>(); component.Offset = boxCollider2DComponent["Offset"].as<glm::vec2>();
component.Size = boxCollider2DComponent["Size"].as<glm::vec2>(); component.Size = boxCollider2DComponent["Size"].as<glm::vec2>();
component.Density = boxCollider2DComponent["Density"] ? boxCollider2DComponent["Density"].as<float>() : 1.0f;
component.Friction = boxCollider2DComponent["Friction"] ? boxCollider2DComponent["Friction"].as<float>() : 1.0f;
} }
if (auto circleCollider2DComponent = entity["CircleCollider2DComponent"]) if (auto circleCollider2DComponent = entity["CircleCollider2DComponent"])
@ -553,6 +559,8 @@ namespace Prism
auto& component = deserializedEntity.AddComponent<CircleCollider2DComponent>(); auto& component = deserializedEntity.AddComponent<CircleCollider2DComponent>();
component.Offset = circleCollider2DComponent["Offset"].as<glm::vec2>(); component.Offset = circleCollider2DComponent["Offset"].as<glm::vec2>();
component.Radius = circleCollider2DComponent["Radius"].as<float>(); component.Radius = circleCollider2DComponent["Radius"].as<float>();
component.Density = circleCollider2DComponent["Density"] ? circleCollider2DComponent["Density"].as<float>() : 1.0f;
component.Friction = circleCollider2DComponent["Friction"] ? circleCollider2DComponent["Friction"].as<float>() : 1.0f;
} }
} }
} }

View File

@ -28,6 +28,12 @@ namespace Prism
static EntityInstanceMap s_EntityInstanceMap; 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); static MonoMethod* GetMethod(MonoImage* image, const std::string& methodDesc);
struct EntityScriptClass struct EntityScriptClass
@ -41,10 +47,18 @@ namespace Prism
MonoMethod* OnDestroyMethod = nullptr; MonoMethod* OnDestroyMethod = nullptr;
MonoMethod* OnUpdateMethod = nullptr; MonoMethod* OnUpdateMethod = nullptr;
// Physics
MonoMethod* OnCollision2DBeginMethod = nullptr;
MonoMethod* OnCollision2DEndMethod = nullptr;
void InitClassMethods(MonoImage* image) void InitClassMethods(MonoImage* image)
{ {
OnCreateMethod = GetMethod(image, FullName + ":OnCreate()"); OnCreateMethod = GetMethod(image, FullName + ":OnCreate()");
OnUpdateMethod = GetMethod(image, FullName + ":OnUpdate(single)"); 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); MonoMethodDesc* desc = mono_method_desc_new(methodDesc.c_str(), 0);
if (!desc) 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); MonoMethod* method = mono_method_desc_search_in_image(desc, image);
if (!method) 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; 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) static void LoadPrismRuntimeAssembly(const std::string& path)
{ {
if (s_AppAssembly) 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<IDComponent>().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<IDComponent>().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()); PM_CORE_ASSERT(s_EntityInstanceMap.find(sceneID) != s_EntityInstanceMap.end());
auto& entityMap = s_EntityInstanceMap.at(sceneID); auto& entityMap = s_EntityInstanceMap.at(sceneID);

View File

@ -118,7 +118,12 @@ namespace Prism
static void OnCreateEntity(UUID sceneID, UUID entityID); static void OnCreateEntity(UUID sceneID, UUID entityID);
static void OnUpdateEntity(UUID sceneID, UUID entityID, TimeStep ts); 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 bool ModuleExists(const std::string& moduleName);
static void InitScriptEntity(Entity entity); static void InitScriptEntity(Entity entity);

View File

@ -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::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::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::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::GetMesh_Native",(const void*)Prism::Script::Prism_MeshComponent_GetMesh);
mono_add_internal_call("Prism.MeshComponent::SetMesh_Native",(const void*)Prism::Script::Prism_MeshComponent_SetMesh); 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.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::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::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::Destructor_Native", (const void*)Prism::Script::Prism_Texture2D_Destructor);

View File

@ -108,6 +108,18 @@ namespace Prism { namespace Script {
return result; return result;
} }
uint64_t Prism_Entity_FindEntityByTag(MonoString* tag)
{
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
PM_CORE_ASSERT(scene, "No active scene!");
Entity entity = scene->FindEntityByTag(mono_string_to_utf8(tag));
if (entity)
return entity.GetComponent<IDComponent>().ID;
return 0;
}
void* Prism_MeshComponent_GetMesh(uint64_t entityID) void* Prism_MeshComponent_GetMesh(uint64_t entityID)
{ {
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext(); Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
@ -148,6 +160,68 @@ namespace Prism { namespace Script {
b2Body_ApplyLinearImpulse(body, *(const b2Vec2*)impulse, b2Body_GetWorldCenterOfMass(body) + *(const b2Vec2*)offset, wake); 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> 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<RigidBody2DComponent>());
auto& component = entity.GetComponent<RigidBody2DComponent>();
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> 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<RigidBody2DComponent>());
auto& component = entity.GetComponent<RigidBody2DComponent>();
PM_CORE_ASSERT(velocity);
b2Body_SetLinearVelocity(component.RuntimeBodyID, {velocity->x, velocity->y});
}
void Hazel_RigidBody2DComponent_GetLinearVelocity(uint64_t entityID, glm::vec2* outVelocity)
{
Ref<Scene> 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<RigidBody2DComponent>());
auto& component = entity.GetComponent<RigidBody2DComponent>();
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> 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<RigidBody2DComponent>());
const auto& component = entity.GetComponent<RigidBody2DComponent>();
PM_CORE_ASSERT(velocity);
b2Body_SetLinearVelocity(component.RuntimeBodyID, {velocity->x, velocity->y});
}
Ref<Mesh>* Prism_Mesh_Constructor(MonoString* filepath) Ref<Mesh>* Prism_Mesh_Constructor(MonoString* filepath)
{ {
return new Ref<Mesh>(new Mesh(mono_string_to_utf8(filepath))); return new Ref<Mesh>(new Mesh(mono_string_to_utf8(filepath)));

View File

@ -28,12 +28,15 @@ namespace Prism { namespace Script {
void Prism_Entity_SetTransform(uint64_t entityID, glm::mat4* inTransform); void Prism_Entity_SetTransform(uint64_t entityID, glm::mat4* inTransform);
void Prism_Entity_CreateComponent(uint64_t entityID, void* type); void Prism_Entity_CreateComponent(uint64_t entityID, void* type);
bool Prism_Entity_HasComponent(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_GetMesh(uint64_t entityID);
void Prism_MeshComponent_SetMesh(uint64_t entityID, Ref<Mesh>* inMesh); void Prism_MeshComponent_SetMesh(uint64_t entityID, Ref<Mesh>* inMesh);
// 2D Physic // 2D Physic
void Prism_RigidBody2DComponent_ApplyLinearImpulse(uint64_t entityID, glm::vec2* impulse, glm::vec2* offset, bool wake); 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 // Renderer
// Texture2D // Texture2D