add Physics2D class; For Physics2D add DistanceJoint RevoluteJoint PrismaticJoint WeldJoint Component and serialize/deserialize code; use template to Copy Component from entity to entity; remove useless code, fix some error code
This commit is contained in:
@ -105,7 +105,7 @@ namespace Prism
|
||||
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
||||
const auto viewProj = m_EditorCamera.GetViewProjection();
|
||||
Renderer2D::BeginScene(viewProj, false);
|
||||
Renderer2D::DrawRotatedRect({ transform.Translation.x + collider.Offset.x, transform.Translation.y + collider.Offset.y }, collider.Size * 2.0f, transform.Rotation.z, { 0.0f, 0.0f, 1.0f, 1.0f });
|
||||
Renderer2D::DrawRotatedRect({ transform.Translation.x + collider.Offset.x, transform.Translation.y + collider.Offset.y }, {transform.Scale.x * collider.Size.x, transform.Scale.y * collider.Size.y}, transform.Rotation.z, { 0.0f, 0.0f, 1.0f, 1.0f });
|
||||
Renderer2D::EndScene();
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
@ -639,10 +639,9 @@ namespace Prism
|
||||
ImVec2 maxBound = { minBound.x + windowSize.x, minBound.y + windowSize.y };
|
||||
m_ViewportBounds[0] = { minBound.x, minBound.y };
|
||||
m_ViewportBounds[1] = { maxBound.x, maxBound.y };
|
||||
m_AllowViewportCameraEvents = ImGui::IsMouseHoveringRect(minBound, maxBound);
|
||||
|
||||
// ImGuizmo
|
||||
if (m_GizmoType != -1 && !m_SelectionContext.empty())
|
||||
if (m_GizmoType != -1 && !m_SelectionContext.empty() && m_SceneState == SceneState::Edit)
|
||||
{
|
||||
auto& selection = m_SelectionContext[0];
|
||||
|
||||
|
||||
@ -136,8 +136,6 @@ namespace Prism
|
||||
Ref<Texture2D> m_PlayButtonTex, m_StopButtonTex, m_PauseButtonTex;
|
||||
|
||||
|
||||
// configure button
|
||||
bool m_AllowViewportCameraEvents = false;
|
||||
|
||||
bool m_UIShowBoundingBoxes = false;
|
||||
|
||||
|
||||
@ -32,6 +32,15 @@ namespace Prism
|
||||
|
||||
}
|
||||
|
||||
void AnimationController::SetSkeleton(const Ref<Skeleton>& skeleton)
|
||||
{
|
||||
m_skeleton = skeleton;
|
||||
if (m_skeleton)
|
||||
{
|
||||
ComputeBindPoseTransforms();
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationController::ComputeBoneTransforms(float time)
|
||||
{
|
||||
const auto boneCount = (uint32_t)m_skeleton->m_Bones.size();
|
||||
|
||||
@ -28,16 +28,9 @@ namespace Prism
|
||||
const std::vector<glm::mat4>& GetFinalBoneTransforms() const { return m_FinalBoneTransforms; }
|
||||
|
||||
|
||||
void AnimationController::SetSkeleton(const Ref<Skeleton>& skeleton)
|
||||
{
|
||||
m_skeleton = skeleton;
|
||||
if (m_skeleton)
|
||||
{
|
||||
ComputeBindPoseTransforms();
|
||||
}
|
||||
}
|
||||
void AnimationController::SetAnimationClip(const Ref<AnimationClip>& clip) { m_currentClip = clip; }
|
||||
void AnimationController::SetGlobalInverseTransform(const glm::mat4& inv) { m_GlobalInverseTransform = inv; }
|
||||
void SetSkeleton(const Ref<Skeleton>& skeleton);
|
||||
void SetAnimationClip(const Ref<AnimationClip>& clip) { m_currentClip = clip; }
|
||||
void SetGlobalInverseTransform(const glm::mat4& inv) { m_GlobalInverseTransform = inv; }
|
||||
|
||||
void Play() { m_State = PLAY; }
|
||||
void Pause() { m_State = PAUSE; }
|
||||
|
||||
@ -26,6 +26,56 @@ namespace Prism
|
||||
|
||||
glm::mat4 Mat4FromAssimpMat4(const aiMatrix4x4& matrix);
|
||||
|
||||
void SceneHierarchyPanel::DrawConnectedBodySelector(Entity currentEntity, UUID& connectedBody, Scene* context, const char* popupId)
|
||||
{
|
||||
Entity connectedEntity = context->FindEntityByUUID(connectedBody);
|
||||
std::string connectedName = connectedEntity ? connectedEntity.GetComponent<TagComponent>().Tag : "None";
|
||||
|
||||
ImGui::Text("Connected Body");
|
||||
ImGui::NextColumn();
|
||||
ImGui::PushItemWidth(-1);
|
||||
const std::string buttonLabel = connectedName + "##" + std::to_string(currentEntity.GetUUID());
|
||||
if (ImGui::Button(buttonLabel.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0)))
|
||||
{
|
||||
ImGui::OpenPopup(popupId);
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::NextColumn();
|
||||
|
||||
if (ImGui::BeginPopup(popupId))
|
||||
{
|
||||
ImGui::Text("Select Entity");
|
||||
ImGui::Separator();
|
||||
|
||||
context->m_Registry.view<entt::entity>().each([&](auto entityID)
|
||||
{
|
||||
Entity e{entityID, context};
|
||||
if (e.HasComponent<TagComponent>())
|
||||
{
|
||||
const auto& tag = e.GetComponent<TagComponent>().Tag;
|
||||
if (e == currentEntity) return; // 排除自身
|
||||
|
||||
ImGui::PushID((const void*)(uintptr_t)(uint32_t)e);
|
||||
if (ImGui::Selectable(tag.c_str(), e.GetUUID() == connectedBody))
|
||||
{
|
||||
connectedBody = e.GetUUID();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
});
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::Selectable("None", connectedBody == 0))
|
||||
{
|
||||
connectedBody = 0;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
SceneHierarchyPanel::SceneHierarchyPanel(const Ref<Scene>& context)
|
||||
: m_Context(context)
|
||||
{
|
||||
@ -564,6 +614,12 @@ namespace Prism
|
||||
AddComponentPopup<BoxCollider2DComponent>("BoxCollider2D");
|
||||
AddComponentPopup<CircleCollider2DComponent>("CircleCollider2D");
|
||||
|
||||
ImGui::SeparatorText("2D Joint Component");
|
||||
AddComponentPopup<DistanceJoint2DComponent>("DistanceJoint2D");
|
||||
AddComponentPopup<RevoluteJoint2DComponent>("RevoluteJoint2D");
|
||||
AddComponentPopup<PrismaticJoint2DComponent>("PrismaticJoint2D");
|
||||
AddComponentPopup<WeldJoint2DComponent>("WeldJoint2DComponent");
|
||||
|
||||
ImGui::SeparatorText("3D Component");
|
||||
AddComponentPopup<MeshComponent>("Mesh");
|
||||
AddComponentPopup<AnimationComponent>("Animation", [&](AnimationComponent& component)
|
||||
@ -649,14 +705,169 @@ namespace Prism
|
||||
|
||||
}
|
||||
|
||||
DrawComponent<DistanceJoint2DComponent>("DistanceJoint2D", entity, [&](DistanceJoint2DComponent& component)
|
||||
{
|
||||
UI::BeginPropertyGrid();
|
||||
|
||||
DrawConnectedBodySelector(entity, component.ConnectedBody, m_Context.Raw(), "SelectConnectedBodyDist");
|
||||
|
||||
|
||||
UI::Property("Local Anchor A", component.LocalAnchorA);
|
||||
UI::Property("Local Anchor B", component.LocalAnchorB);
|
||||
|
||||
UI::Property("Length", component.Length);
|
||||
UI::Separator();
|
||||
UI::Property("Enable Spring", component.EnableSpring);
|
||||
if (component.EnableSpring)
|
||||
{
|
||||
UI::Property("Lower Spring Force", component.LowerSpringForce);
|
||||
UI::Property("Upper Spring Force", component.UpperSpringForce);
|
||||
UI::Property("Hertz", component.Hertz);
|
||||
UI::Property("Damping Ratio", component.DampingRatio);
|
||||
}
|
||||
UI::Separator();
|
||||
|
||||
UI::Property("Enable Limit", component.EnableLimit);
|
||||
if (component.EnableLimit)
|
||||
{
|
||||
UI::Property("Min Length", component.MinLength);
|
||||
UI::Property("Max Length", component.MaxLength);
|
||||
}
|
||||
UI::Separator();
|
||||
|
||||
|
||||
UI::Property("Enable Motor", component.EnableMotor);
|
||||
if (component.EnableMotor)
|
||||
{
|
||||
UI::Property("Max Motor Force", component.MaxMotorForce);
|
||||
UI::Property("Motor Speed", component.MotorSpeed);
|
||||
}
|
||||
UI::Separator();
|
||||
|
||||
|
||||
UI::EndPropertyGrid();
|
||||
});
|
||||
|
||||
DrawComponent<RevoluteJoint2DComponent>("Revolute Joint 2D", entity, [&](RevoluteJoint2DComponent& component)
|
||||
{
|
||||
UI::BeginPropertyGrid();
|
||||
|
||||
// Connected Body selector
|
||||
DrawConnectedBodySelector(entity, component.ConnectedBody, m_Context.Raw(), "SelectConnectedBodyDist");
|
||||
|
||||
|
||||
// 锚点
|
||||
UI::Property("Local Anchor A", component.LocalAnchorA);
|
||||
UI::Property("Local Anchor B", component.LocalAnchorB);
|
||||
UI::Separator();
|
||||
|
||||
// 弹簧参数
|
||||
UI::Property("Enable Spring", component.EnableSpring);
|
||||
if (component.EnableSpring)
|
||||
{
|
||||
UI::Property("Target Angle (rad)", component.TargetAngle);
|
||||
UI::Property("Hertz", component.Hertz);
|
||||
UI::Property("Damping Ratio", component.DampingRatio);
|
||||
}
|
||||
UI::Separator();
|
||||
|
||||
// 限制参数
|
||||
UI::Property("Enable Limit", component.EnableLimit);
|
||||
if (component.EnableLimit)
|
||||
{
|
||||
UI::Property("Lower Angle (rad)", component.LowerAngle);
|
||||
UI::Property("Upper Angle (rad)", component.UpperAngle);
|
||||
}
|
||||
UI::Separator();
|
||||
|
||||
// 马达参数
|
||||
UI::Property("Enable Motor", component.EnableMotor);
|
||||
if (component.EnableMotor)
|
||||
{
|
||||
UI::Property("Motor Speed (rad/s)", component.MotorSpeed);
|
||||
UI::Property("Max Motor Torque", component.MaxMotorTorque);
|
||||
}
|
||||
UI::Separator();
|
||||
|
||||
UI::EndPropertyGrid();
|
||||
});
|
||||
|
||||
DrawComponent<PrismaticJoint2DComponent>("Prismatic Joint 2D", entity, [&](PrismaticJoint2DComponent& component)
|
||||
{
|
||||
UI::BeginPropertyGrid();
|
||||
|
||||
// Connected Body selector
|
||||
DrawConnectedBodySelector(entity, component.ConnectedBody, m_Context.Raw(), "SelectConnectedBodyDist");
|
||||
|
||||
// 锚点
|
||||
UI::Property("Local Anchor A", component.LocalAnchorA);
|
||||
UI::Property("Local Anchor B", component.LocalAnchorB);
|
||||
// 滑动轴
|
||||
UI::Property("Local Axis A", component.LocalAxisA);
|
||||
UI::Separator();
|
||||
|
||||
// 弹簧参数
|
||||
UI::Property("Enable Spring", component.EnableSpring);
|
||||
if (component.EnableSpring)
|
||||
{
|
||||
UI::Property("Target Translation", component.TargetTranslation);
|
||||
UI::Property("Hertz", component.Hertz);
|
||||
UI::Property("Damping Ratio", component.DampingRatio);
|
||||
}
|
||||
UI::Separator();
|
||||
|
||||
// 限制参数
|
||||
UI::Property("Enable Limit", component.EnableLimit);
|
||||
if (component.EnableLimit)
|
||||
{
|
||||
UI::Property("Lower Translation", component.LowerTranslation);
|
||||
UI::Property("Upper Translation", component.UpperTranslation);
|
||||
}
|
||||
UI::Separator();
|
||||
|
||||
// 马达参数
|
||||
UI::Property("Enable Motor", component.EnableMotor);
|
||||
if (component.EnableMotor)
|
||||
{
|
||||
UI::Property("Motor Speed", component.MotorSpeed);
|
||||
UI::Property("Max Motor Force", component.MaxMotorForce);
|
||||
}
|
||||
UI::Separator();
|
||||
|
||||
UI::EndPropertyGrid();
|
||||
});
|
||||
|
||||
DrawComponent<WeldJoint2DComponent>("Weld Joint 2D", entity, [&](WeldJoint2DComponent& component)
|
||||
{
|
||||
UI::BeginPropertyGrid();
|
||||
|
||||
// Connected Body selector
|
||||
DrawConnectedBodySelector(entity, component.ConnectedBody, m_Context.Raw(), "SelectConnectedBodyDist");
|
||||
|
||||
// 锚点
|
||||
UI::Property("Local Anchor A", component.LocalAnchorA);
|
||||
UI::Property("Local Anchor B", component.LocalAnchorB);
|
||||
UI::Separator();
|
||||
|
||||
// 焊接关节特有参数(线性和角度的 Hertz 和阻尼)
|
||||
UI::Property("Linear Hertz", component.LinearHertz);
|
||||
UI::Property("Angular Hertz", component.AngularHertz);
|
||||
UI::Property("Linear Damping Ratio", component.LinearDampingRatio);
|
||||
UI::Property("Angular Damping Ratio", component.AngularDampingRatio);
|
||||
UI::Separator();
|
||||
|
||||
UI::EndPropertyGrid();
|
||||
});
|
||||
|
||||
|
||||
DrawComponent<MeshComponent>("Mesh", entity, [](MeshComponent& meshComponent) {
|
||||
|
||||
UI::BeginPropertyGrid();
|
||||
UI::PropertyAssetReference("Mesh", meshComponent.Mesh, AssetType::Mesh);
|
||||
UI::Property("AnimationPlaying", meshComponent.Mesh->m_AnimationPlaying);
|
||||
UI::Property("TimeMultiple", meshComponent.Mesh->m_TimeMultiplier);
|
||||
UI::Property("AnimationTime", meshComponent.Mesh->m_AnimationTime);
|
||||
UI::Property("WorldTime", meshComponent.Mesh->m_WorldTime);
|
||||
// UI::Property("AnimationPlaying", meshComponent.Mesh->m_AnimationPlaying);
|
||||
// UI::Property("TimeMultiple", meshComponent.Mesh->m_TimeMultiplier);
|
||||
// UI::Property("AnimationTime", meshComponent.Mesh->m_AnimationTime);
|
||||
// UI::Property("WorldTime", meshComponent.Mesh->m_WorldTime);
|
||||
|
||||
UI::EndPropertyGrid();
|
||||
});
|
||||
|
||||
@ -34,6 +34,8 @@ namespace Prism
|
||||
|
||||
template<class T, typename Function>
|
||||
void AddComponentPopup(const char* componentName, Function function);
|
||||
|
||||
static void DrawConnectedBodySelector(Entity currentEntity, UUID& connectedBody, Scene* context, const char* popupId);
|
||||
private:
|
||||
Ref<Scene> m_Context;
|
||||
Entity m_SelectionContext;
|
||||
|
||||
383
Prism/src/Prism/Physics/Physics2D.cpp
Normal file
383
Prism/src/Prism/Physics/Physics2D.cpp
Normal file
@ -0,0 +1,383 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/11.
|
||||
//
|
||||
|
||||
#include "Physics2D.h"
|
||||
|
||||
#include "Prism/Scene/Entity.h"
|
||||
#include "Prism/Script/ScriptEngine.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
void Physics2D::CreateBody(Scene* scene)
|
||||
{
|
||||
auto sceneView = scene->m_Registry.view<Box2DWorldComponent>();
|
||||
auto& world = scene->m_Registry.get<Box2DWorldComponent>(sceneView.front()).World;
|
||||
{
|
||||
auto view = scene->m_Registry.view<RigidBody2DComponent>();
|
||||
scene->m_Physics2DBodyEntityBuffer = new Entity[view.size()];
|
||||
uint32_t physicsBodyEntityBufferIndex = 0;
|
||||
for (auto entity : view)
|
||||
{
|
||||
Entity e = { entity, scene };
|
||||
auto& transform = e.Transform();
|
||||
auto& rigidBody2D = scene->m_Registry.get<RigidBody2DComponent>(entity);
|
||||
|
||||
b2BodyDef bodyDef = b2DefaultBodyDef();
|
||||
if (rigidBody2D.BodyType == RigidBody2DComponent::Type::Static)
|
||||
bodyDef.type = b2_staticBody;
|
||||
else if (rigidBody2D.BodyType == RigidBody2DComponent::Type::Dynamic)
|
||||
bodyDef.type = b2_dynamicBody;
|
||||
else if (rigidBody2D.BodyType == RigidBody2DComponent::Type::Kinematic)
|
||||
bodyDef.type = b2_kinematicBody;
|
||||
bodyDef.position = {transform.Translation.x, transform.Translation.y};
|
||||
|
||||
float rotationZ = transform.Rotation.z;
|
||||
bodyDef.rotation = b2Rot{cos(rotationZ), sin(rotationZ)};
|
||||
|
||||
// box2D fixRotation renamed to MotionLocks
|
||||
bodyDef.motionLocks = b2MotionLocks{false, false, rigidBody2D.FixedRotation};
|
||||
|
||||
Entity* entityStorage = &scene->m_Physics2DBodyEntityBuffer[physicsBodyEntityBufferIndex++];
|
||||
*entityStorage = e;
|
||||
bodyDef.userData = entityStorage;
|
||||
|
||||
rigidBody2D.RuntimeBodyID = b2CreateBody(world, &bodyDef);
|
||||
}
|
||||
}
|
||||
|
||||
// BoxCollider2DComponent
|
||||
{
|
||||
auto view = scene->m_Registry.view<BoxCollider2DComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
Entity e = { entity, scene };
|
||||
|
||||
auto& boxCollider2D = scene->m_Registry.get<BoxCollider2DComponent>(entity);
|
||||
if (e.HasComponent<RigidBody2DComponent>())
|
||||
{
|
||||
const auto& rigidBody2D = e.GetComponent<RigidBody2DComponent>();
|
||||
const auto& transform = e.GetComponent<TransformComponent>();
|
||||
PM_CORE_ASSERT(b2Body_IsValid(rigidBody2D.RuntimeBodyID));
|
||||
|
||||
b2BodyId bodyId = rigidBody2D.RuntimeBodyID;
|
||||
|
||||
glm::vec2 halfSize = boxCollider2D.Size * 0.5f;
|
||||
|
||||
b2Polygon boxShape = b2MakeOffsetBox(halfSize.x * transform.Scale.x, halfSize.y * transform.Scale.y, {boxCollider2D.Offset.x,boxCollider2D.Offset.y}, {1.0f, 0.0f});
|
||||
b2ShapeDef shapeDef = b2DefaultShapeDef();
|
||||
shapeDef.density = boxCollider2D.Density;
|
||||
shapeDef.material.friction = boxCollider2D.Friction;
|
||||
shapeDef.enableContactEvents = true;
|
||||
|
||||
b2CreatePolygonShape(bodyId, &shapeDef, &boxShape);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CircleCollider2DComponent
|
||||
{
|
||||
auto view = scene->m_Registry.view<CircleCollider2DComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
Entity e = { entity, scene };
|
||||
|
||||
auto& circleCollider2D = scene->m_Registry.get<CircleCollider2DComponent>(entity);
|
||||
if (e.HasComponent<RigidBody2DComponent>())
|
||||
{
|
||||
auto& rigidBody2D = e.GetComponent<RigidBody2DComponent>();
|
||||
auto& transform = e.GetComponent<TransformComponent>();
|
||||
PM_CORE_ASSERT(b2Body_IsValid(rigidBody2D.RuntimeBodyID));
|
||||
|
||||
b2BodyId bodyId = rigidBody2D.RuntimeBodyID;
|
||||
|
||||
b2Vec2 centor = {circleCollider2D.Offset.x, circleCollider2D.Offset.y};
|
||||
|
||||
b2Circle circleShape;
|
||||
circleShape.center = centor;
|
||||
circleShape.radius = circleCollider2D.Radius;
|
||||
|
||||
b2ShapeDef shapeDef = b2DefaultShapeDef();
|
||||
|
||||
shapeDef.density = circleCollider2D.Density;
|
||||
shapeDef.material.friction = circleCollider2D.Friction;
|
||||
shapeDef.enableContactEvents = true;
|
||||
|
||||
b2CreateCircleShape(bodyId, &shapeDef, &circleShape);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DistanceJoint2DComponent
|
||||
{
|
||||
auto view = scene->m_Registry.view<DistanceJoint2DComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
auto& jointComp = view.get<DistanceJoint2DComponent>(entity);
|
||||
|
||||
// 验证实体引用
|
||||
Entity bodyA = { entity, scene };
|
||||
Entity bodyB = scene->FindEntityByUUID(jointComp.ConnectedBody);
|
||||
if (!bodyA || !bodyB)
|
||||
{
|
||||
PM_CORE_WARN("DistanceJoint has invalid body references");
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: temp solve
|
||||
if (!bodyA.HasComponent<RigidBody2DComponent>() || !bodyB.HasComponent<RigidBody2DComponent>()) continue;
|
||||
|
||||
auto& rbA = bodyA.GetComponent<RigidBody2DComponent>();
|
||||
auto& rbB = bodyB.GetComponent<RigidBody2DComponent>();
|
||||
|
||||
if (!b2Body_IsValid(rbA.RuntimeBodyID) || !b2Body_IsValid(rbB.RuntimeBodyID))
|
||||
{
|
||||
PM_CORE_WARN("One of the bodies for DistanceJoint is not valid");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 填充关节定义
|
||||
b2DistanceJointDef jointDef = b2DefaultDistanceJointDef();
|
||||
jointDef.base.bodyIdA = rbA.RuntimeBodyID;
|
||||
jointDef.base.bodyIdB = rbB.RuntimeBodyID;
|
||||
jointDef.base.localFrameA = {
|
||||
{ jointComp.LocalAnchorA.x, jointComp.LocalAnchorA.y },
|
||||
b2Rot_identity // 通常不需要旋转,保持单位即可
|
||||
};
|
||||
jointDef.base.localFrameB = {
|
||||
{ jointComp.LocalAnchorB.x, jointComp.LocalAnchorB.y },
|
||||
b2Rot_identity
|
||||
};
|
||||
jointDef.base.collideConnected = jointComp.CollideConnected;
|
||||
|
||||
// 设置距离关节特有参数
|
||||
jointDef.length = jointComp.Length;
|
||||
jointDef.enableSpring = jointComp.EnableSpring;
|
||||
jointDef.lowerSpringForce = jointComp.LowerSpringForce;
|
||||
jointDef.upperSpringForce = jointComp.UpperSpringForce;
|
||||
jointDef.hertz = jointComp.Hertz;
|
||||
jointDef.dampingRatio = jointComp.DampingRatio;
|
||||
jointDef.enableLimit = jointComp.EnableLimit;
|
||||
jointDef.minLength = jointComp.MinLength;
|
||||
jointDef.maxLength = jointComp.MaxLength;
|
||||
jointDef.enableMotor = jointComp.EnableMotor;
|
||||
jointDef.maxMotorForce = jointComp.MaxMotorForce;
|
||||
jointDef.motorSpeed = jointComp.MotorSpeed;
|
||||
|
||||
jointComp.RuntimeJointId = b2CreateDistanceJoint(world, &jointDef);
|
||||
PM_CORE_ASSERT(b2Joint_IsValid(jointComp.RuntimeJointId));
|
||||
}
|
||||
}
|
||||
|
||||
// RevoluteJoint2DComponent
|
||||
{
|
||||
auto view = scene->m_Registry.view<RevoluteJoint2DComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
auto& jointComp = view.get<RevoluteJoint2DComponent>(entity);
|
||||
|
||||
Entity bodyA = { entity, scene };
|
||||
Entity bodyB = scene->FindEntityByUUID(jointComp.ConnectedBody);
|
||||
if (!bodyA || !bodyB) continue;
|
||||
|
||||
// TODO: temp solve
|
||||
if (!bodyA.HasComponent<RigidBody2DComponent>() || !bodyB.HasComponent<RigidBody2DComponent>()) continue;
|
||||
|
||||
auto& rbA = bodyA.GetComponent<RigidBody2DComponent>();
|
||||
auto& rbB = bodyB.GetComponent<RigidBody2DComponent>();
|
||||
if (!b2Body_IsValid(rbA.RuntimeBodyID) || !b2Body_IsValid(rbB.RuntimeBodyID))
|
||||
continue;
|
||||
|
||||
b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef();
|
||||
|
||||
// 通用属性(必须通过 base 访问)
|
||||
jointDef.base.bodyIdA = rbA.RuntimeBodyID;
|
||||
jointDef.base.bodyIdB = rbB.RuntimeBodyID;
|
||||
jointDef.base.localFrameA = {
|
||||
{ jointComp.LocalAnchorA.x, jointComp.LocalAnchorA.y },
|
||||
b2Rot_identity
|
||||
};
|
||||
jointDef.base.localFrameB = {
|
||||
{ jointComp.LocalAnchorB.x, jointComp.LocalAnchorB.y },
|
||||
b2Rot_identity
|
||||
};
|
||||
jointDef.base.collideConnected = jointComp.CollideConnected;
|
||||
|
||||
// 旋转关节特有属性
|
||||
jointDef.targetAngle = jointComp.TargetAngle;
|
||||
jointDef.enableSpring = jointComp.EnableSpring;
|
||||
jointDef.hertz = jointComp.Hertz;
|
||||
jointDef.dampingRatio = jointComp.DampingRatio;
|
||||
jointDef.enableLimit = jointComp.EnableLimit;
|
||||
jointDef.lowerAngle = jointComp.LowerAngle;
|
||||
jointDef.upperAngle = jointComp.UpperAngle;
|
||||
jointDef.enableMotor = jointComp.EnableMotor;
|
||||
jointDef.motorSpeed = jointComp.MotorSpeed;
|
||||
jointDef.maxMotorTorque = jointComp.MaxMotorTorque;
|
||||
|
||||
jointComp.RuntimeJointId = b2CreateRevoluteJoint(world, &jointDef);
|
||||
PM_CORE_ASSERT(b2Joint_IsValid(jointComp.RuntimeJointId));
|
||||
}
|
||||
}
|
||||
|
||||
// PrismaticJoint2DComponent
|
||||
{
|
||||
auto view = scene->m_Registry.view<PrismaticJoint2DComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
auto& jointComp = view.get<PrismaticJoint2DComponent>(entity);
|
||||
|
||||
Entity bodyA = { entity, scene };
|
||||
Entity bodyB = scene->FindEntityByUUID(jointComp.ConnectedBody);
|
||||
if (!bodyA || !bodyB) continue;
|
||||
|
||||
// TODO: temp solve
|
||||
if (!bodyA.HasComponent<RigidBody2DComponent>() || !bodyB.HasComponent<RigidBody2DComponent>()) continue;
|
||||
|
||||
auto& rbA = bodyA.GetComponent<RigidBody2DComponent>();
|
||||
auto& rbB = bodyB.GetComponent<RigidBody2DComponent>();
|
||||
if (!b2Body_IsValid(rbA.RuntimeBodyID) || !b2Body_IsValid(rbB.RuntimeBodyID))
|
||||
continue;
|
||||
|
||||
b2PrismaticJointDef jointDef = b2DefaultPrismaticJointDef();
|
||||
|
||||
jointDef.base.bodyIdA = rbA.RuntimeBodyID;
|
||||
jointDef.base.bodyIdB = rbB.RuntimeBodyID;
|
||||
|
||||
float angle = atan2(jointComp.LocalAxisA.y, jointComp.LocalAxisA.x);
|
||||
jointDef.base.localFrameA = {
|
||||
{ jointComp.LocalAnchorA.x, jointComp.LocalAnchorA.y },
|
||||
b2MakeRot(angle)
|
||||
};
|
||||
|
||||
jointDef.base.localFrameB = {
|
||||
{ jointComp.LocalAnchorB.x, jointComp.LocalAnchorB.y },
|
||||
b2Rot_identity
|
||||
};
|
||||
|
||||
jointDef.base.collideConnected = jointComp.CollideConnected;
|
||||
|
||||
jointDef.enableSpring = jointComp.EnableSpring;
|
||||
jointDef.hertz = jointComp.Hertz;
|
||||
jointDef.dampingRatio = jointComp.DampingRatio;
|
||||
jointDef.targetTranslation = jointComp.TargetTranslation;
|
||||
jointDef.enableLimit = jointComp.EnableLimit;
|
||||
jointDef.lowerTranslation = jointComp.LowerTranslation;
|
||||
jointDef.upperTranslation = jointComp.UpperTranslation;
|
||||
jointDef.enableMotor = jointComp.EnableMotor;
|
||||
jointDef.motorSpeed = jointComp.MotorSpeed;
|
||||
jointDef.maxMotorForce = jointComp.MaxMotorForce;
|
||||
|
||||
jointComp.RuntimeJointId = b2CreatePrismaticJoint(world, &jointDef);
|
||||
PM_CORE_ASSERT(b2Joint_IsValid(jointComp.RuntimeJointId));
|
||||
}
|
||||
}
|
||||
|
||||
// WeldJoint2DComponent
|
||||
{
|
||||
auto view = scene->m_Registry.view<WeldJoint2DComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
auto& jointComp = view.get<WeldJoint2DComponent>(entity);
|
||||
|
||||
Entity bodyA = { entity, scene };
|
||||
Entity bodyB = scene->FindEntityByUUID(jointComp.ConnectedBody);
|
||||
if (!bodyA || !bodyB) continue;
|
||||
|
||||
// TODO: temp solve
|
||||
if (!bodyA.HasComponent<RigidBody2DComponent>() || !bodyB.HasComponent<RigidBody2DComponent>()) continue;
|
||||
|
||||
auto& rbA = bodyA.GetComponent<RigidBody2DComponent>();
|
||||
auto& rbB = bodyB.GetComponent<RigidBody2DComponent>();
|
||||
if (!b2Body_IsValid(rbA.RuntimeBodyID) || !b2Body_IsValid(rbB.RuntimeBodyID))
|
||||
continue;
|
||||
|
||||
b2WeldJointDef jointDef = b2DefaultWeldJointDef();
|
||||
|
||||
jointDef.base.bodyIdA = rbA.RuntimeBodyID;
|
||||
jointDef.base.bodyIdB = rbB.RuntimeBodyID;
|
||||
jointDef.base.localFrameA = {
|
||||
{ jointComp.LocalAnchorA.x, jointComp.LocalAnchorA.y },
|
||||
b2Rot_identity
|
||||
};
|
||||
jointDef.base.localFrameB = {
|
||||
{ jointComp.LocalAnchorB.x, jointComp.LocalAnchorB.y },
|
||||
b2Rot_identity
|
||||
};
|
||||
jointDef.base.collideConnected = jointComp.CollideConnected;
|
||||
|
||||
jointDef.linearHertz = jointComp.LinearHertz;
|
||||
jointDef.angularHertz = jointComp.AngularHertz;
|
||||
jointDef.linearDampingRatio = jointComp.LinearDampingRatio;
|
||||
jointDef.angularDampingRatio = jointComp.AngularDampingRatio;
|
||||
|
||||
jointComp.RuntimeJointId = b2CreateWeldJoint(world, &jointDef);
|
||||
PM_CORE_ASSERT(b2Joint_IsValid(jointComp.RuntimeJointId));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Physics2D::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 Physics2D::OnTransformConstruct(entt::registry& registry, entt::entity entity)
|
||||
{
|
||||
// PM_CORE_TRACE("Transform Component constructed!");
|
||||
}
|
||||
|
||||
void Physics2D::OnScriptComponentConstruct(entt::registry& registry, entt::entity entity)
|
||||
{
|
||||
// Note: there should be exactly one scene component per registry
|
||||
const auto sceneView = registry.view<SceneComponent>();
|
||||
const UUID sceneID = registry.get<SceneComponent>(sceneView.front()).SceneID;
|
||||
|
||||
Scene* scene = Scene::s_ActiveScenes[sceneID];
|
||||
|
||||
const auto entityID = registry.get<IDComponent>(entity).ID;
|
||||
PM_CORE_ASSERT(scene->m_EntityIDMap.find(entityID) != scene->m_EntityIDMap.end());
|
||||
ScriptEngine::InitScriptEntity(scene->m_EntityIDMap.at(entityID));
|
||||
}
|
||||
|
||||
void Physics2D::OnScriptComponentDestroy(entt::registry& registry, const 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);
|
||||
}
|
||||
|
||||
}
|
||||
41
Prism/src/Prism/Physics/Physics2D.h
Normal file
41
Prism/src/Prism/Physics/Physics2D.h
Normal file
@ -0,0 +1,41 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/11.
|
||||
//
|
||||
|
||||
#ifndef PRISM_PHYSICS2D_H
|
||||
#define PRISM_PHYSICS2D_H
|
||||
|
||||
#include <box2d/box2d.h>
|
||||
|
||||
#include "entt/entity/registry.hpp"
|
||||
#include "Prism/Scene/Scene.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
struct Box2DWorldComponent
|
||||
{
|
||||
b2WorldId World{};
|
||||
|
||||
Box2DWorldComponent() = delete;
|
||||
Box2DWorldComponent(const b2Vec2& gravity) {
|
||||
b2WorldDef worldDef = b2DefaultWorldDef();
|
||||
worldDef.gravity = gravity;
|
||||
World = b2CreateWorld(&worldDef);
|
||||
}
|
||||
};
|
||||
|
||||
class Physics2D
|
||||
{
|
||||
public:
|
||||
|
||||
static void CreateBody(Scene* scene);
|
||||
static void ProcessContactEvents(b2WorldId worldId);
|
||||
static void OnTransformConstruct(entt::registry& registry, entt::entity entity);
|
||||
static void OnScriptComponentConstruct(entt::registry& registry, entt::entity entity);
|
||||
static void OnScriptComponentDestroy(entt::registry& registry, entt::entity entity);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //PRISM_PHYSICS2D_H
|
||||
@ -9,7 +9,7 @@ namespace Prism
|
||||
template<typename T, typename ConditionFunction>
|
||||
static bool RemoveIfExists(std::vector<T>& vector, ConditionFunction condition)
|
||||
{
|
||||
for (std::vector<T>::iterator it = vector.begin(); it != vector.end(); ++it)
|
||||
for (auto it = vector.begin(); it != vector.end(); ++it)
|
||||
{
|
||||
if (condition(*it))
|
||||
{
|
||||
|
||||
@ -176,10 +176,10 @@ namespace Prism
|
||||
|
||||
// Animation
|
||||
bool m_IsAnimated = false;
|
||||
bool m_AnimationPlaying = false;
|
||||
float m_AnimationTime = 0.0f;
|
||||
float m_WorldTime = 0.0f;
|
||||
float m_TimeMultiplier = 1.0f;
|
||||
// bool m_AnimationPlaying = false;
|
||||
// float m_AnimationTime = 0.0f;
|
||||
// float m_WorldTime = 0.0f;
|
||||
// float m_TimeMultiplier = 1.0f;
|
||||
|
||||
std::string m_FilePath;
|
||||
private:
|
||||
|
||||
@ -432,7 +432,6 @@ namespace Prism
|
||||
s_Data.CompositeShader->SetFloat("u_Exposure", s_Data.AutoExposureData.EnableAutoExposure ? s_Data.AutoExposureData.CurrentExposure : s_Data.SceneData.SceneCamera.Camera.GetExposure());
|
||||
s_Data.CompositeShader->SetInt("u_TextureSamples", s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetSpecification().Samples);
|
||||
s_Data.CompositeShader->SetFloat("u_EnableBloom", s_Data.EnableBloom);
|
||||
s_Data.CompositeShader->SetInt("u_DepthTexture", 1);
|
||||
|
||||
s_Data.GeoPass->GetSpecification().TargetFramebuffer->BindTexture();
|
||||
Renderer::Submit([]()
|
||||
|
||||
@ -187,6 +187,99 @@ namespace Prism
|
||||
CircleCollider2DComponent(const CircleCollider2DComponent& other) = default;
|
||||
};
|
||||
|
||||
struct DistanceJoint2DComponent
|
||||
{
|
||||
UUID ConnectedBody = 0;
|
||||
bool CollideConnected = false;
|
||||
|
||||
// 局部锚点(相对于刚体原点)
|
||||
glm::vec2 LocalAnchorA = {0.0f, 0.0f};
|
||||
glm::vec2 LocalAnchorB = {0.0f, 0.0f};
|
||||
|
||||
// 距离关节特有参数(与b2DistanceJointDef对应)
|
||||
float Length = 1.0f;
|
||||
bool EnableSpring = false;
|
||||
float LowerSpringForce = 0.0f;
|
||||
float UpperSpringForce = 0.0f;
|
||||
float Hertz = 0.0f;
|
||||
float DampingRatio = 0.0f;
|
||||
bool EnableLimit = false;
|
||||
float MinLength = 0.0f;
|
||||
float MaxLength = 1.0f;
|
||||
bool EnableMotor = false;
|
||||
float MaxMotorForce = 0.0f;
|
||||
float MotorSpeed = 0.0f;
|
||||
|
||||
b2JointId RuntimeJointId = b2_nullJointId;
|
||||
};
|
||||
|
||||
struct RevoluteJoint2DComponent
|
||||
{
|
||||
UUID ConnectedBody = 0;
|
||||
bool CollideConnected = false;
|
||||
|
||||
glm::vec2 LocalAnchorA = {0.0f, 0.0f};
|
||||
glm::vec2 LocalAnchorB = {0.0f, 0.0f};
|
||||
|
||||
// 旋转关节特有属性(直接对应 b2RevoluteJointDef 成员)
|
||||
float TargetAngle = 0.0f; // 弹簧驱动的目标角度(弧度)
|
||||
bool EnableSpring = false;
|
||||
float Hertz = 0.0f;
|
||||
float DampingRatio = 0.0f;
|
||||
bool EnableLimit = false;
|
||||
float LowerAngle = 0.0f;
|
||||
float UpperAngle = 0.0f;
|
||||
bool EnableMotor = false;
|
||||
float MotorSpeed = 0.0f;
|
||||
float MaxMotorTorque = 0.0f;
|
||||
|
||||
b2JointId RuntimeJointId = b2_nullJointId;
|
||||
};
|
||||
|
||||
struct PrismaticJoint2DComponent
|
||||
{
|
||||
UUID ConnectedBody = 0;
|
||||
bool CollideConnected = false;
|
||||
|
||||
glm::vec2 LocalAnchorA = {0.0f, 0.0f}; // 局部锚点 A
|
||||
glm::vec2 LocalAnchorB = {0.0f, 0.0f}; // 局部锚点 B
|
||||
glm::vec2 LocalAxisA = {1.0f, 0.0f}; // 局部轴方向(在 BodyA 空间中,应归一化)
|
||||
|
||||
// 弹簧参数
|
||||
bool EnableSpring = false;
|
||||
float Hertz = 0.0f;
|
||||
float DampingRatio = 0.0f;
|
||||
float TargetTranslation = 0.0f;
|
||||
|
||||
// 限制参数
|
||||
bool EnableLimit = false;
|
||||
float LowerTranslation = 0.0f;
|
||||
float UpperTranslation = 0.0f;
|
||||
|
||||
// 马达参数
|
||||
bool EnableMotor = false;
|
||||
float MotorSpeed = 0.0f;
|
||||
float MaxMotorForce = 0.0f;
|
||||
|
||||
b2JointId RuntimeJointId = b2_nullJointId;
|
||||
};
|
||||
|
||||
struct WeldJoint2DComponent
|
||||
{
|
||||
UUID ConnectedBody = 0;
|
||||
bool CollideConnected = false;
|
||||
|
||||
glm::vec2 LocalAnchorA = {0.0f, 0.0f};
|
||||
glm::vec2 LocalAnchorB = {0.0f, 0.0f};
|
||||
|
||||
float LinearHertz = 0.0f;
|
||||
float AngularHertz = 0.0f;
|
||||
float LinearDampingRatio = 0.0f;
|
||||
float AngularDampingRatio = 0.0f;
|
||||
|
||||
b2JointId RuntimeJointId = b2_nullJointId;
|
||||
};
|
||||
|
||||
|
||||
struct SphereColliderComponent
|
||||
{
|
||||
@ -305,6 +398,22 @@ namespace Prism
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Components>
|
||||
struct ComponentGroup
|
||||
{
|
||||
};
|
||||
using AllComponent = ComponentGroup<
|
||||
TagComponent, RelationshipComponent,
|
||||
TransformComponent, SpriteRendererComponent,
|
||||
RigidBody2DComponent, BoxCollider2DComponent, CircleCollider2DComponent,
|
||||
DistanceJoint2DComponent, RevoluteJoint2DComponent, PrismaticJoint2DComponent, WeldJoint2DComponent,
|
||||
MeshComponent,
|
||||
RigidBodyComponent, BoxColliderComponent, SphereColliderComponent, CapsuleColliderComponent, MeshColliderComponent,
|
||||
AnimationComponent,
|
||||
DirectionalLightComponent, SkyLightComponent,
|
||||
ScriptComponent,
|
||||
CameraComponent
|
||||
>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
#include "Entity.h"
|
||||
#include "Prism/Renderer/SceneRenderer.h"
|
||||
#include "Prism/Script/ScriptEngine.h"
|
||||
#include <box2d/box2d.h>
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
@ -22,102 +21,26 @@
|
||||
#include "Prism/Asset/AssetsManager.h"
|
||||
#include "Prism/Core/Input.h"
|
||||
#include "Prism/Core/Math/Math.h"
|
||||
#include "Prism/Physics/Physics2D.h"
|
||||
#include "Prism/Renderer/Renderer.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
|
||||
std::unordered_map<UUID, Scene*> s_ActiveScenes;
|
||||
std::unordered_map<UUID, Scene*> Scene::s_ActiveScenes;
|
||||
|
||||
static uint32_t s_SceneIDCounter = 0;
|
||||
|
||||
struct SceneComponent
|
||||
{
|
||||
UUID SceneID;
|
||||
};
|
||||
|
||||
struct Box2DWorldComponent
|
||||
{
|
||||
b2WorldId World;
|
||||
|
||||
Box2DWorldComponent() = delete;
|
||||
Box2DWorldComponent(const b2Vec2& gravity) {
|
||||
b2WorldDef worldDef = b2DefaultWorldDef();
|
||||
worldDef.gravity = gravity;
|
||||
World = b2CreateWorld(&worldDef);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
// PM_CORE_TRACE("Transform Component constructed!");
|
||||
}
|
||||
|
||||
void OnScriptComponentConstruct(entt::registry& registry, entt::entity entity)
|
||||
{
|
||||
// Note: there should be exactly one scene component per registry
|
||||
const auto sceneView = registry.view<SceneComponent>();
|
||||
UUID sceneID = registry.get<SceneComponent>(sceneView.front()).SceneID;
|
||||
|
||||
Scene* scene = s_ActiveScenes[sceneID];
|
||||
|
||||
auto entityID = registry.get<IDComponent>(entity).ID;
|
||||
PM_CORE_ASSERT(scene->m_EntityIDMap.find(entityID) != scene->m_EntityIDMap.end());
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
Scene::Scene(const std::string& debugName, const bool isEditorScene)
|
||||
: m_SceneID(++s_SceneIDCounter), m_DebugName(debugName)
|
||||
{
|
||||
m_Registry.on_construct<TransformComponent>().connect<&OnTransformConstruct>();
|
||||
m_Registry.on_construct<ScriptComponent>().connect<&OnScriptComponentConstruct>();
|
||||
m_Registry.on_construct<TransformComponent>().connect<&Physics2D::OnTransformConstruct>();
|
||||
m_Registry.on_construct<ScriptComponent>().connect<&Physics2D::OnScriptComponentConstruct>();
|
||||
|
||||
m_SceneEntity = m_Registry.create();
|
||||
m_Registry.emplace<SceneComponent>(m_SceneEntity, m_SceneID);
|
||||
@ -152,14 +75,12 @@ namespace Prism
|
||||
|
||||
m_CameraIcon = AssetsManager::GetAsset<Texture2D>("assets/editor/Camera.png");
|
||||
m_LightIcon = AssetsManager::GetAsset<Texture2D>("assets/editor/light.png");
|
||||
|
||||
}
|
||||
|
||||
void Scene::OnShutdown()
|
||||
{
|
||||
/*
|
||||
auto b2WorldView = m_Registry.view<Box2DWorldComponent>();
|
||||
b2DestroyWorld(m_Registry.get<Box2DWorldComponent>(m_SceneEntity).World);
|
||||
*/
|
||||
}
|
||||
|
||||
void Scene::OnUpdate(TimeStep ts)
|
||||
@ -175,7 +96,7 @@ namespace Prism
|
||||
b2World_Step(box2DWorld, ts, positionIterations);
|
||||
|
||||
// Process Contact Envents box2d version 3.0^ should impl contact event after b2World_Step
|
||||
ProcessContactEvents(box2DWorld);
|
||||
Physics2D::ProcessContactEvents(box2DWorld);
|
||||
|
||||
{
|
||||
const auto view = m_Registry.view<RigidBody2DComponent>();
|
||||
@ -283,7 +204,7 @@ namespace Prism
|
||||
|
||||
m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod);
|
||||
|
||||
SceneRenderer::BeginScene(this, { static_cast<Camera>(camera), cameraViewMatrix });
|
||||
SceneRenderer::BeginScene(this, { static_cast<Camera>(camera), cameraViewMatrix }, false);
|
||||
{
|
||||
const auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
||||
for (const auto entity : group)
|
||||
@ -367,8 +288,8 @@ namespace Prism
|
||||
m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod);
|
||||
|
||||
// TODO: this value should be storage and can modify
|
||||
|
||||
SceneRenderer::BeginScene(this, { static_cast<Camera>(editorCamera), editorCamera.GetViewMatrix(), 0.1f, 1000.0f, 45.0f});
|
||||
// TODO: Renderer2D cannot blend with Renderer3D
|
||||
SceneRenderer::BeginScene(this, { static_cast<Camera>(editorCamera), editorCamera.GetViewMatrix(), 0.1f, 1000.0f, 45.0f}, false);
|
||||
{
|
||||
const auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
||||
{
|
||||
@ -471,97 +392,7 @@ namespace Prism
|
||||
|
||||
|
||||
// Box2D physics
|
||||
auto sceneView = m_Registry.view<Box2DWorldComponent>();
|
||||
auto& world = m_Registry.get<Box2DWorldComponent>(sceneView.front()).World;
|
||||
{
|
||||
auto view = m_Registry.view<RigidBody2DComponent>();
|
||||
m_Physics2DBodyEntityBuffer = new Entity[view.size()];
|
||||
uint32_t physicsBodyEntityBufferIndex = 0;
|
||||
for (auto entity : view)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
auto& transform = e.Transform();
|
||||
auto& rigidBody2D = m_Registry.get<RigidBody2DComponent>(entity);
|
||||
|
||||
b2BodyDef bodyDef = b2DefaultBodyDef();
|
||||
if (rigidBody2D.BodyType == RigidBody2DComponent::Type::Static)
|
||||
bodyDef.type = b2_staticBody;
|
||||
else if (rigidBody2D.BodyType == RigidBody2DComponent::Type::Dynamic)
|
||||
bodyDef.type = b2_dynamicBody;
|
||||
else if (rigidBody2D.BodyType == RigidBody2DComponent::Type::Kinematic)
|
||||
bodyDef.type = b2_kinematicBody;
|
||||
bodyDef.position = {transform.Translation.x, transform.Translation.y};
|
||||
|
||||
float rotationZ = transform.Rotation.z;
|
||||
bodyDef.rotation = b2Rot{cos(rotationZ), sin(rotationZ)};
|
||||
|
||||
// box2D fixRotation renamed to motionlocks
|
||||
bodyDef.motionLocks = b2MotionLocks{false, false, rigidBody2D.FixedRotation};
|
||||
|
||||
Entity* entityStorage = &m_Physics2DBodyEntityBuffer[physicsBodyEntityBufferIndex++];
|
||||
*entityStorage = e;
|
||||
bodyDef.userData = entityStorage;
|
||||
|
||||
rigidBody2D.RuntimeBodyID = b2CreateBody(world, &bodyDef);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
auto view = m_Registry.view<BoxCollider2DComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
|
||||
auto& boxCollider2D = m_Registry.get<BoxCollider2DComponent>(entity);
|
||||
if (e.HasComponent<RigidBody2DComponent>())
|
||||
{
|
||||
const auto& rigidBody2D = e.GetComponent<RigidBody2DComponent>();
|
||||
PM_CORE_ASSERT(b2Body_IsValid(rigidBody2D.RuntimeBodyID));
|
||||
|
||||
b2BodyId bodyId = rigidBody2D.RuntimeBodyID;
|
||||
|
||||
b2Polygon boxShape = b2MakeOffsetBox(boxCollider2D.Size.x, boxCollider2D.Size.y, {boxCollider2D.Offset.x,boxCollider2D.Offset.y}, {1.0f, 0.0f});
|
||||
b2ShapeDef shapeDef = b2DefaultShapeDef();
|
||||
shapeDef.density = boxCollider2D.Density;
|
||||
shapeDef.material.friction = boxCollider2D.Friction;
|
||||
shapeDef.enableContactEvents = true;
|
||||
|
||||
b2CreatePolygonShape(bodyId, &shapeDef, &boxShape);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto view = m_Registry.view<CircleCollider2DComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
|
||||
auto& circleCollider2D = m_Registry.get<CircleCollider2DComponent>(entity);
|
||||
if (e.HasComponent<RigidBody2DComponent>())
|
||||
{
|
||||
auto& rigidBody2D = e.GetComponent<RigidBody2DComponent>();
|
||||
PM_CORE_ASSERT(b2Body_IsValid(rigidBody2D.RuntimeBodyID));
|
||||
|
||||
b2BodyId bodyId = rigidBody2D.RuntimeBodyID;
|
||||
|
||||
b2Vec2 centor = {circleCollider2D.Offset.x, circleCollider2D.Offset.y};
|
||||
|
||||
b2Circle circleShape;
|
||||
circleShape.center = centor;
|
||||
circleShape.radius = circleCollider2D.Radius;
|
||||
|
||||
b2ShapeDef shapeDef = b2DefaultShapeDef();
|
||||
|
||||
shapeDef.density = circleCollider2D.Density;
|
||||
shapeDef.material.friction = circleCollider2D.Friction;
|
||||
shapeDef.enableContactEvents = true;
|
||||
|
||||
b2CreateCircleShape(bodyId, &shapeDef, &circleShape);
|
||||
}
|
||||
}
|
||||
}
|
||||
Physics2D::CreateBody(this);
|
||||
|
||||
{
|
||||
auto view = m_Registry.view<RigidBodyComponent>();
|
||||
@ -663,9 +494,14 @@ namespace Prism
|
||||
auto& destComponent = dstRegistry.emplace_or_replace<T>(destEntity, srcComponent);
|
||||
}
|
||||
}
|
||||
template<typename ... Component>
|
||||
static void CopyComponent(ComponentGroup<Component ...>, entt::registry& dst, entt::registry& src, const std::unordered_map<UUID, entt::entity>& enttMap)
|
||||
{
|
||||
(CopyComponent<Component>(dst, src, enttMap), ...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void CopyComponentIfExists(entt::entity dst, entt::entity src, entt::registry& registry)
|
||||
static void CopyComponentIfExists(const entt::entity dst, const entt::entity src, entt::registry& registry)
|
||||
{
|
||||
if (registry.storage<T>().contains(src))
|
||||
{
|
||||
@ -673,6 +509,11 @@ namespace Prism
|
||||
registry.emplace_or_replace<T>(dst, srcComponent);
|
||||
}
|
||||
}
|
||||
template<typename ... Component>
|
||||
static auto CopyComponentIfExists(ComponentGroup<Component...>, const entt::entity dst, const entt::entity src, entt::registry& registry) -> void
|
||||
{
|
||||
(CopyComponentIfExists<Component>(dst, src, registry), ...);
|
||||
}
|
||||
|
||||
|
||||
void Scene::DuplicateEntity(Entity entity)
|
||||
@ -683,6 +524,8 @@ namespace Prism
|
||||
else
|
||||
newEntity = CreateEntity();
|
||||
|
||||
CopyComponentIfExists(AllComponent{},newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
/*
|
||||
CopyComponentIfExists<TransformComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
|
||||
CopyComponentIfExists<RelationshipComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
@ -701,6 +544,14 @@ namespace Prism
|
||||
CopyComponentIfExists<SphereColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<CapsuleColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<MeshColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<AnimationComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<DistanceJoint2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<RevoluteJoint2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<PrismaticJoint2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<WeldJoint2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
Entity Scene::FindEntityByTag(const std::string &tag) {
|
||||
@ -759,7 +610,8 @@ namespace Prism
|
||||
Entity e = target->CreateEntityWithID(uuid, "", true);
|
||||
enttMap[uuid] = e.m_EntityHandle;
|
||||
}
|
||||
|
||||
CopyComponent(AllComponent{},target->m_Registry, m_Registry, enttMap);
|
||||
/*
|
||||
CopyComponent<TagComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<TransformComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
|
||||
@ -779,6 +631,12 @@ namespace Prism
|
||||
CopyComponent<SphereColliderComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<CapsuleColliderComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<MeshColliderComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<AnimationComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<DistanceJoint2DComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<RevoluteJoint2DComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<PrismaticJoint2DComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<WeldJoint2DComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
*/
|
||||
|
||||
const auto& entityInstanceMap = ScriptEngine::GetEntityInstanceMap();
|
||||
if (entityInstanceMap.find(target->GetUUID()) != entityInstanceMap.end())
|
||||
|
||||
@ -46,6 +46,11 @@ namespace Prism
|
||||
class Entity;
|
||||
using EntityMap = std::unordered_map<UUID, Entity>;
|
||||
|
||||
struct SceneComponent
|
||||
{
|
||||
UUID SceneID;
|
||||
};
|
||||
|
||||
class PRISM_API Scene : public RefCounted
|
||||
{
|
||||
public:
|
||||
@ -141,8 +146,10 @@ namespace Prism
|
||||
Ref<Texture2D> m_CameraIcon;
|
||||
Ref<Texture2D> m_LightIcon;
|
||||
|
||||
static std::unordered_map<UUID, Scene*> s_ActiveScenes;
|
||||
private:
|
||||
friend class Entity;
|
||||
friend class Physics2D;
|
||||
friend class Renderer3D;
|
||||
friend class SceneRenderer;
|
||||
friend class SceneSerializer;
|
||||
|
||||
@ -370,6 +370,109 @@ namespace Prism
|
||||
out << YAML::EndMap; // CircleCollider2DComponent
|
||||
}
|
||||
|
||||
if (entity.HasComponent<DistanceJoint2DComponent>())
|
||||
{
|
||||
out << YAML::Key << "DistanceJoint2DComponent";
|
||||
out << YAML::BeginMap; // DistanceJoint2DComponent
|
||||
|
||||
const auto& distanceJoint2DComponent = entity.GetComponent<DistanceJoint2DComponent>();
|
||||
out << YAML::Key << "ConnectedBody" << YAML::Value << distanceJoint2DComponent.ConnectedBody;
|
||||
out << YAML::Key << "LocalAnchorA" << YAML::Value << distanceJoint2DComponent.LocalAnchorA;
|
||||
out << YAML::Key << "LocalAnchorB" << YAML::Value << distanceJoint2DComponent.LocalAnchorB;
|
||||
out << YAML::Key << "Length" << YAML::Value << distanceJoint2DComponent.Length;
|
||||
|
||||
out << YAML::Key << "EnableSpring" << YAML::Value << distanceJoint2DComponent.EnableSpring;
|
||||
out << YAML::Key << "LowerSpringForce" << YAML::Value << distanceJoint2DComponent.LowerSpringForce;
|
||||
out << YAML::Key << "UpperSpringForce" << YAML::Value << distanceJoint2DComponent.UpperSpringForce;
|
||||
out << YAML::Key << "Hertz" << YAML::Value << distanceJoint2DComponent.Hertz;
|
||||
out << YAML::Key << "DampingRatio" << YAML::Value << distanceJoint2DComponent.DampingRatio;
|
||||
|
||||
out << YAML::Key << "EnableLimit" << YAML::Value << distanceJoint2DComponent.EnableLimit;
|
||||
out << YAML::Key << "MinLength" << YAML::Value << distanceJoint2DComponent.MinLength;
|
||||
out << YAML::Key << "MaxLength" << YAML::Value << distanceJoint2DComponent.MaxLength;
|
||||
|
||||
out << YAML::Key << "EnableMotor" << YAML::Value << distanceJoint2DComponent.EnableMotor;
|
||||
out << YAML::Key << "MaxMotorForce" << YAML::Value << distanceJoint2DComponent.MaxMotorForce;
|
||||
out << YAML::Key << "MotorSpeed" << YAML::Value << distanceJoint2DComponent.MotorSpeed;
|
||||
|
||||
out << YAML::EndMap; // CircleBollider2DComponent
|
||||
}
|
||||
|
||||
if (entity.HasComponent<RevoluteJoint2DComponent>())
|
||||
{
|
||||
out << YAML::Key << "RevoluteJoint2DComponent";
|
||||
out << YAML::BeginMap;
|
||||
|
||||
const auto& component = entity.GetComponent<RevoluteJoint2DComponent>();
|
||||
out << YAML::Key << "ConnectedBody" << YAML::Value << component.ConnectedBody;
|
||||
out << YAML::Key << "CollideConnected" << YAML::Value << component.CollideConnected;
|
||||
out << YAML::Key << "LocalAnchorA" << YAML::Value << component.LocalAnchorA;
|
||||
out << YAML::Key << "LocalAnchorB" << YAML::Value << component.LocalAnchorB;
|
||||
|
||||
out << YAML::Key << "TargetAngle" << YAML::Value << component.TargetAngle;
|
||||
out << YAML::Key << "EnableSpring" << YAML::Value << component.EnableSpring;
|
||||
out << YAML::Key << "Hertz" << YAML::Value << component.Hertz;
|
||||
out << YAML::Key << "DampingRatio" << YAML::Value << component.DampingRatio;
|
||||
|
||||
out << YAML::Key << "EnableLimit" << YAML::Value << component.EnableLimit;
|
||||
out << YAML::Key << "LowerAngle" << YAML::Value << component.LowerAngle;
|
||||
out << YAML::Key << "UpperAngle" << YAML::Value << component.UpperAngle;
|
||||
|
||||
out << YAML::Key << "EnableMotor" << YAML::Value << component.EnableMotor;
|
||||
out << YAML::Key << "MotorSpeed" << YAML::Value << component.MotorSpeed;
|
||||
out << YAML::Key << "MaxMotorTorque" << YAML::Value << component.MaxMotorTorque;
|
||||
|
||||
out << YAML::EndMap;
|
||||
}
|
||||
|
||||
if (entity.HasComponent<PrismaticJoint2DComponent>())
|
||||
{
|
||||
out << YAML::Key << "PrismaticJoint2DComponent";
|
||||
out << YAML::BeginMap;
|
||||
|
||||
const auto& component = entity.GetComponent<PrismaticJoint2DComponent>();
|
||||
out << YAML::Key << "ConnectedBody" << YAML::Value << component.ConnectedBody;
|
||||
out << YAML::Key << "CollideConnected" << YAML::Value << component.CollideConnected;
|
||||
out << YAML::Key << "LocalAnchorA" << YAML::Value << component.LocalAnchorA;
|
||||
out << YAML::Key << "LocalAnchorB" << YAML::Value << component.LocalAnchorB;
|
||||
out << YAML::Key << "LocalAxisA" << YAML::Value << component.LocalAxisA;
|
||||
|
||||
out << YAML::Key << "EnableSpring" << YAML::Value << component.EnableSpring;
|
||||
out << YAML::Key << "Hertz" << YAML::Value << component.Hertz;
|
||||
out << YAML::Key << "DampingRatio" << YAML::Value << component.DampingRatio;
|
||||
out << YAML::Key << "TargetTranslation" << YAML::Value << component.TargetTranslation;
|
||||
|
||||
out << YAML::Key << "EnableLimit" << YAML::Value << component.EnableLimit;
|
||||
out << YAML::Key << "LowerTranslation" << YAML::Value << component.LowerTranslation;
|
||||
out << YAML::Key << "UpperTranslation" << YAML::Value << component.UpperTranslation;
|
||||
|
||||
out << YAML::Key << "EnableMotor" << YAML::Value << component.EnableMotor;
|
||||
out << YAML::Key << "MotorSpeed" << YAML::Value << component.MotorSpeed;
|
||||
out << YAML::Key << "MaxMotorForce" << YAML::Value << component.MaxMotorForce;
|
||||
|
||||
out << YAML::EndMap;
|
||||
}
|
||||
|
||||
if (entity.HasComponent<WeldJoint2DComponent>())
|
||||
{
|
||||
out << YAML::Key << "WeldJoint2DComponent";
|
||||
out << YAML::BeginMap;
|
||||
|
||||
const auto& component = entity.GetComponent<WeldJoint2DComponent>();
|
||||
out << YAML::Key << "ConnectedBody" << YAML::Value << component.ConnectedBody;
|
||||
out << YAML::Key << "CollideConnected" << YAML::Value << component.CollideConnected;
|
||||
out << YAML::Key << "LocalAnchorA" << YAML::Value << component.LocalAnchorA;
|
||||
out << YAML::Key << "LocalAnchorB" << YAML::Value << component.LocalAnchorB;
|
||||
|
||||
out << YAML::Key << "LinearHertz" << YAML::Value << component.LinearHertz;
|
||||
out << YAML::Key << "AngularHertz" << YAML::Value << component.AngularHertz;
|
||||
out << YAML::Key << "LinearDampingRatio" << YAML::Value << component.LinearDampingRatio;
|
||||
out << YAML::Key << "AngularDampingRatio" << YAML::Value << component.AngularDampingRatio;
|
||||
|
||||
out << YAML::EndMap;
|
||||
}
|
||||
|
||||
|
||||
if (entity.HasComponent<RigidBodyComponent>())
|
||||
{
|
||||
out << YAML::Key << "RigidBodyComponent";
|
||||
@ -825,6 +928,91 @@ namespace Prism
|
||||
component.Friction = boxCollider2DComponent["Friction"] ? boxCollider2DComponent["Friction"].as<float>() : 1.0f;
|
||||
}
|
||||
|
||||
if (auto distanceJoint2DComponent = entity["DistanceJoint2DComponent"])
|
||||
{
|
||||
auto& component = deserializedEntity.AddComponent<DistanceJoint2DComponent>();
|
||||
component.ConnectedBody = distanceJoint2DComponent["ConnectedBody"].as<uint64_t>();
|
||||
component.LocalAnchorA = distanceJoint2DComponent["LocalAnchorA"].as<glm::vec2>();
|
||||
component.LocalAnchorB = distanceJoint2DComponent["LocalAnchorB"].as<glm::vec2>();
|
||||
|
||||
component.Length = distanceJoint2DComponent["Length"].as<float>();
|
||||
|
||||
component.EnableSpring = distanceJoint2DComponent["EnableSpring"].as<bool>();
|
||||
|
||||
component.LowerSpringForce = distanceJoint2DComponent["LowerSpringForce"].as<float>();
|
||||
component.UpperSpringForce = distanceJoint2DComponent["UpperSpringForce"].as<float>();
|
||||
component.Hertz = distanceJoint2DComponent["Hertz"].as<float>();
|
||||
component.DampingRatio = distanceJoint2DComponent["DampingRatio"].as<float>();
|
||||
|
||||
component.EnableLimit = distanceJoint2DComponent["EnableLimit"].as<bool>();
|
||||
component.MinLength = distanceJoint2DComponent["MinLength"].as<float>();
|
||||
component.MaxLength = distanceJoint2DComponent["MaxLength"].as<float>();
|
||||
|
||||
component.EnableMotor = distanceJoint2DComponent["EnableMotor"].as<bool>();
|
||||
component.MaxMotorForce = distanceJoint2DComponent["MaxMotorForce"].as<float>();
|
||||
component.MotorSpeed = distanceJoint2DComponent["MotorSpeed"].as<float>();
|
||||
}
|
||||
|
||||
if (auto revoluteJoint = entity["RevoluteJoint2DComponent"])
|
||||
{
|
||||
auto& component = deserializedEntity.AddComponent<RevoluteJoint2DComponent>();
|
||||
component.ConnectedBody = revoluteJoint["ConnectedBody"].as<uint64_t>();
|
||||
component.CollideConnected = revoluteJoint["CollideConnected"].as<bool>();
|
||||
component.LocalAnchorA = revoluteJoint["LocalAnchorA"].as<glm::vec2>();
|
||||
component.LocalAnchorB = revoluteJoint["LocalAnchorB"].as<glm::vec2>();
|
||||
|
||||
component.TargetAngle = revoluteJoint["TargetAngle"].as<float>();
|
||||
component.EnableSpring = revoluteJoint["EnableSpring"].as<bool>();
|
||||
component.Hertz = revoluteJoint["Hertz"].as<float>();
|
||||
component.DampingRatio = revoluteJoint["DampingRatio"].as<float>();
|
||||
|
||||
component.EnableLimit = revoluteJoint["EnableLimit"].as<bool>();
|
||||
component.LowerAngle = revoluteJoint["LowerAngle"].as<float>();
|
||||
component.UpperAngle = revoluteJoint["UpperAngle"].as<float>();
|
||||
|
||||
component.EnableMotor = revoluteJoint["EnableMotor"].as<bool>();
|
||||
component.MotorSpeed = revoluteJoint["MotorSpeed"].as<float>();
|
||||
component.MaxMotorTorque = revoluteJoint["MaxMotorTorque"].as<float>();
|
||||
}
|
||||
|
||||
if (auto prismaticJoint = entity["PrismaticJoint2DComponent"])
|
||||
{
|
||||
auto& component = deserializedEntity.AddComponent<PrismaticJoint2DComponent>();
|
||||
component.ConnectedBody = prismaticJoint["ConnectedBody"].as<uint64_t>();
|
||||
component.CollideConnected = prismaticJoint["CollideConnected"].as<bool>();
|
||||
component.LocalAnchorA = prismaticJoint["LocalAnchorA"].as<glm::vec2>();
|
||||
component.LocalAnchorB = prismaticJoint["LocalAnchorB"].as<glm::vec2>();
|
||||
component.LocalAxisA = prismaticJoint["LocalAxisA"].as<glm::vec2>();
|
||||
|
||||
component.EnableSpring = prismaticJoint["EnableSpring"].as<bool>();
|
||||
component.Hertz = prismaticJoint["Hertz"].as<float>();
|
||||
component.DampingRatio = prismaticJoint["DampingRatio"].as<float>();
|
||||
component.TargetTranslation = prismaticJoint["TargetTranslation"].as<float>();
|
||||
|
||||
component.EnableLimit = prismaticJoint["EnableLimit"].as<bool>();
|
||||
component.LowerTranslation = prismaticJoint["LowerTranslation"].as<float>();
|
||||
component.UpperTranslation = prismaticJoint["UpperTranslation"].as<float>();
|
||||
|
||||
component.EnableMotor = prismaticJoint["EnableMotor"].as<bool>();
|
||||
component.MotorSpeed = prismaticJoint["MotorSpeed"].as<float>();
|
||||
component.MaxMotorForce = prismaticJoint["MaxMotorForce"].as<float>();
|
||||
}
|
||||
|
||||
if (auto weldJoint = entity["WeldJoint2DComponent"])
|
||||
{
|
||||
auto& component = deserializedEntity.AddComponent<WeldJoint2DComponent>();
|
||||
component.ConnectedBody = weldJoint["ConnectedBody"].as<uint64_t>();
|
||||
component.CollideConnected = weldJoint["CollideConnected"].as<bool>();
|
||||
component.LocalAnchorA = weldJoint["LocalAnchorA"].as<glm::vec2>();
|
||||
component.LocalAnchorB = weldJoint["LocalAnchorB"].as<glm::vec2>();
|
||||
|
||||
component.LinearHertz = weldJoint["LinearHertz"].as<float>();
|
||||
component.AngularHertz = weldJoint["AngularHertz"].as<float>();
|
||||
component.LinearDampingRatio = weldJoint["LinearDampingRatio"].as<float>();
|
||||
component.AngularDampingRatio = weldJoint["AngularDampingRatio"].as<float>();
|
||||
}
|
||||
|
||||
|
||||
if (auto circleCollider2DComponent = entity["CircleCollider2DComponent"])
|
||||
{
|
||||
auto& component = deserializedEntity.AddComponent<CircleCollider2DComponent>();
|
||||
|
||||
Reference in New Issue
Block a user