From d9237f83d23e6b64bf31d20aa6655a2cb8f819b4 Mon Sep 17 00:00:00 2001 From: Antoine Pilote Date: Mon, 2 Sep 2024 18:09:02 -0400 Subject: [PATCH] Added ground normal & ground velocity C# API e --- Editor/src/Commands/Commands/Commands.cpp | 6 +-- Nuake/Engine.h | 2 + Nuake/src/Physics/DynamicWorld.cpp | 39 ++++++++++++++- Nuake/src/Physics/DynamicWorld.h | 3 ++ Nuake/src/Resource/Project.cpp | 8 +++ .../src/Scripting/NetModules/SceneNetAPI.cpp | 49 ++++++++++++++++++- Nuake/src/Scripting/ScriptingEngineNet.cpp | 5 +- Nuake/src/Scripting/ScriptingEngineNet.h | 1 + NuakeNet/src/Components.cs | 20 ++++++++ 9 files changed, 125 insertions(+), 8 deletions(-) diff --git a/Editor/src/Commands/Commands/Commands.cpp b/Editor/src/Commands/Commands/Commands.cpp index 51bde9d3..682200ac 100644 --- a/Editor/src/Commands/Commands/Commands.cpp +++ b/Editor/src/Commands/Commands/Commands.cpp @@ -69,8 +69,8 @@ namespace NuakeEditor "name": "Trigger", "attribs": [ "transparent" ], "match": "classname", - "pattern": "trigger_*", - "texture": "trigger" + "pattern": "Trigger*", + "texture": "trigger.png" } ], "brushface": [ @@ -135,7 +135,7 @@ namespace NuakeEditor // Copy Icon.png if (FileSystem::FileExists("icon.png")) { - std::filesystem::copy_file(FileSystem::RelativeToAbsolute("icon.png"), gameConfigFolderPath + "Icon.png"); + std::filesystem::copy_file(FileSystem::RelativeToAbsolute("icon.png"), gameConfigFolderPath + "Icon.png", std::filesystem::copy_options::overwrite_existing); } return true; } diff --git a/Nuake/Engine.h b/Nuake/Engine.h index ee76641a..e7941e7b 100644 --- a/Nuake/Engine.h +++ b/Nuake/Engine.h @@ -53,6 +53,7 @@ namespace Nuake static inline float GetTime() { return s_Time; } static inline Timestep GetTimestep() { return s_TimeStep; } static inline void SetPhysicsStep(int amount) { s_FixedUpdateRate = 1.0f / static_cast(amount); } + static inline float GetFixedTimeStep() { return s_FixedUpdateRate; } static inline void SetTimeScale(float timeScale) { s_TimeScale = timeScale; } static inline float GetTimeScale() { return s_TimeScale; } @@ -63,6 +64,7 @@ namespace Nuake static bool LoadProject(Ref project); static Ref GetProject(); + }; } diff --git a/Nuake/src/Physics/DynamicWorld.cpp b/Nuake/src/Physics/DynamicWorld.cpp index cddeedd8..ddb53392 100644 --- a/Nuake/src/Physics/DynamicWorld.cpp +++ b/Nuake/src/Physics/DynamicWorld.cpp @@ -352,6 +352,12 @@ namespace Nuake layer = Layers::MOVING; } + if (rb->GetForceKinematic()) + { + motionType = JPH::EMotionType::Kinematic; + layer = Layers::MOVING; + } + const std::string name = rb->GetEntity().GetComponent().Name; if (rb->IsTrigger()) { @@ -474,6 +480,35 @@ namespace Nuake return false; } + Vector3 DynamicWorld::GetCharacterGroundVelocity(const Entity& entity) + { + const uint32_t entityHandle = entity.GetHandle(); + if (_registeredCharacters.find(entityHandle) != _registeredCharacters.end()) + { + auto& characterController = _registeredCharacters[entityHandle].Character; + characterController->UpdateGroundVelocity(); + const auto groundVelocity = characterController->GetGroundVelocity(); + + return Vector3(groundVelocity.GetX(), groundVelocity.GetY(), groundVelocity.GetZ()); + } + + return { 0, 0, 0 }; + } + + Vector3 DynamicWorld::GetCharacterGroundNormal(const Entity& entity) + { + const uint32_t entityHandle = entity.GetHandle(); + if (_registeredCharacters.find(entityHandle) != _registeredCharacters.end()) + { + auto& characterController = _registeredCharacters[entityHandle].Character; + const auto groundNormal = characterController->GetGroundNormal(); + + return Vector3(groundNormal.GetX(), groundNormal.GetY(), groundNormal.GetZ()); + } + + return { 0, 0, 0 }; + } + void DynamicWorld::SetBodyPosition(const Entity& entity, const Vector3& position, const Quat& rotation) { const auto& bodyInterface = _JoltPhysicsSystem->GetBodyInterface(); @@ -499,7 +534,7 @@ namespace Nuake { case JPH::EMotionType::Kinematic: { - _JoltBodyInterface->MoveKinematic(bodyId, newPosition, newRotation, 0.0f); + _JoltBodyInterface->MoveKinematic(bodyId, newPosition, newRotation, Engine::GetFixedTimeStep()); break; } case JPH::EMotionType::Static: @@ -627,7 +662,7 @@ namespace Nuake continue; } - JPH::Vec3 position = bodyInterface.GetCenterOfMassPosition(bodyId); + JPH::Vec3 position = bodyInterface.GetPosition(bodyId); JPH::Vec3 velocity = bodyInterface.GetLinearVelocity(bodyId); JPH::Mat44 joltTransform = bodyInterface.GetWorldTransform(bodyId); const auto bodyRotation = bodyInterface.GetRotation(bodyId); diff --git a/Nuake/src/Physics/DynamicWorld.h b/Nuake/src/Physics/DynamicWorld.h index f8436836..9ab03032 100644 --- a/Nuake/src/Physics/DynamicWorld.h +++ b/Nuake/src/Physics/DynamicWorld.h @@ -75,6 +75,9 @@ namespace Nuake void AddGhostbody(Ref gb); void AddCharacterController(Ref cc); bool IsCharacterGrounded(const Entity& entity); + Vector3 GetCharacterGroundVelocity(const Entity& entity); + Vector3 GetCharacterGroundNormal(const Entity& entity); + void SetCharacterControllerPosition(const Entity& entity, const Vector3& position); void SetBodyPosition(const Entity& entity, const Vector3& position, const Quat& rotation); diff --git a/Nuake/src/Resource/Project.cpp b/Nuake/src/Resource/Project.cpp index 65c9e254..ef91a7d3 100644 --- a/Nuake/src/Resource/Project.cpp +++ b/Nuake/src/Resource/Project.cpp @@ -150,6 +150,7 @@ namespace Nuake } file->PointEntities.clear(); + std::vector bases; for (auto& [name, type] : ScriptingEngineNet::Get().GetPointEntities()) { FGDPointEntity pointEntity = FGDPointEntity(name); @@ -207,6 +208,13 @@ namespace Nuake file->PointEntities.push_back(pointEntity); } + for (auto& b : bases) + { + FGDBaseEntity baseEntity; + baseEntity.Name = b; + file->BaseEntities.push_back(baseEntity); + } + file->Export(); } diff --git a/Nuake/src/Scripting/NetModules/SceneNetAPI.cpp b/Nuake/src/Scripting/NetModules/SceneNetAPI.cpp index ac355b84..f8c88661 100644 --- a/Nuake/src/Scripting/NetModules/SceneNetAPI.cpp +++ b/Nuake/src/Scripting/NetModules/SceneNetAPI.cpp @@ -399,6 +399,52 @@ namespace Nuake { return false; } + Coral::Array GetGroundVelocity(int entityId) + { + Entity entity = Entity((entt::entity)(entityId), Engine::GetCurrentScene().get()); + + Coral::Array resultArray = Coral::Array::New(3); + if (entity.IsValid() && entity.HasComponent()) + { + auto& characterController = entity.GetComponent(); + Vector3 groundVelocity = PhysicsManager::Get().GetWorld()->GetCharacterGroundVelocity(entity); + + resultArray[0] = groundVelocity.x; + resultArray[1] = groundVelocity.y; + resultArray[2] = groundVelocity.z; + + return resultArray; + } + + resultArray[0] = 0.0f; + resultArray[1] = 0.0f; + resultArray[2] = 0.0f; + return resultArray; + } + + Coral::Array GetGroundNormal(int entityId) + { + Entity entity = Entity((entt::entity)(entityId), Engine::GetCurrentScene().get()); + + Coral::Array resultArray = Coral::Array::New(3); + if (entity.IsValid() && entity.HasComponent()) + { + auto& characterController = entity.GetComponent(); + Vector3 groundVelocity = PhysicsManager::Get().GetWorld()->GetCharacterGroundNormal(entity); + + resultArray[0] = groundVelocity.x; + resultArray[1] = groundVelocity.y; + resultArray[2] = groundVelocity.z; + + return resultArray; + } + + resultArray[0] = 0.0f; + resultArray[1] = 0.0f; + resultArray[2] = 0.0f; + return resultArray; + } + void Play(int entityId, Coral::String animation) { Entity entity = Entity((entt::entity)(entityId), Engine::GetCurrentScene().get()); @@ -520,7 +566,8 @@ namespace Nuake { // Character Controller RegisterMethod("CharacterControllerComponent.MoveAndSlideIcall", &MoveAndSlide); RegisterMethod("CharacterControllerComponent.IsOnGroundIcall", &IsOnGround); - + RegisterMethod("CharacterControllerComponent.GetGroundVelocityIcall", &GetGroundVelocity); + RegisterMethod("CharacterControllerComponent.GetGroundNormalIcall", &GetGroundNormal); // Skinned RegisterMethod("SkinnedModelComponent.PlayIcall", &Play); diff --git a/Nuake/src/Scripting/ScriptingEngineNet.cpp b/Nuake/src/Scripting/ScriptingEngineNet.cpp index 2db81615..e78e5ad7 100644 --- a/Nuake/src/Scripting/ScriptingEngineNet.cpp +++ b/Nuake/src/Scripting/ScriptingEngineNet.cpp @@ -323,7 +323,7 @@ namespace Nuake // Point bool isPointScript = false; std::string pointDescription; - + std::string pointBase; for (auto& attribute : type->GetAttributes()) { if (attribute.GetType() == brushScriptAttributeType) @@ -336,6 +336,7 @@ namespace Nuake if (attribute.GetType() == pointScriptAttributeType) { pointDescription = attribute.GetFieldValue("Description"); + pointBase = attribute.GetFieldValue("Base"); isPointScript = true; } } @@ -354,7 +355,7 @@ namespace Nuake NetGameScriptObject gameScriptObject; gameScriptObject.coralType = type; gameScriptObject.exposedVars = std::vector(); - + gameScriptObject.Base = baseTypeName; for (auto& f : type->GetFields()) { for (auto& a : f.GetAttributes()) diff --git a/Nuake/src/Scripting/ScriptingEngineNet.h b/Nuake/src/Scripting/ScriptingEngineNet.h index 40a06430..427249ee 100644 --- a/Nuake/src/Scripting/ScriptingEngineNet.h +++ b/Nuake/src/Scripting/ScriptingEngineNet.h @@ -48,6 +48,7 @@ namespace Nuake { Coral::Type* coralType; std::vector exposedVars; + std::string Base = ""; bool isTrigger = false; std::string Description = ""; AABB aabb = AABB({0, 0, 0}, { 1, 1, 1 }); diff --git a/NuakeNet/src/Components.cs b/NuakeNet/src/Components.cs index c4a6bfea..3962381d 100644 --- a/NuakeNet/src/Components.cs +++ b/NuakeNet/src/Components.cs @@ -311,6 +311,8 @@ namespace Nuake.Net { internal static unsafe delegate* MoveAndSlideIcall; internal static unsafe delegate* IsOnGroundIcall; + internal static unsafe delegate*> GetGroundVelocityIcall; + internal static unsafe delegate*> GetGroundNormalIcall; public CharacterControllerComponent(int entityId) { @@ -326,6 +328,24 @@ namespace Nuake.Net { unsafe { return IsOnGroundIcall(EntityID); } } + + public Vector3 GetGroundNormal() + { + unsafe + { + NativeArray resultArray = GetGroundNormalIcall(EntityID); + return new(resultArray[0], resultArray[1], resultArray[2]); + } + } + + public Vector3 GetGroundVelocity() + { + unsafe + { + NativeArray resultArray = GetGroundVelocityIcall(EntityID); + return new(resultArray[0], resultArray[1], resultArray[2]); + } + } } public class ParticleEmitterComponent : IComponent