diff --git a/Editor/src/Misc/GizmoDrawer.cpp b/Editor/src/Misc/GizmoDrawer.cpp index e93b6f27..7be76346 100644 --- a/Editor/src/Misc/GizmoDrawer.cpp +++ b/Editor/src/Misc/GizmoDrawer.cpp @@ -196,6 +196,7 @@ void GizmoDrawer::DrawGizmos(Ref scene, bool occluded) const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation); m_LineShader->Bind(); + m_LineShader->SetUniform1f("u_Opacity", 0.5f); m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix, box.Size)); m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective()); @@ -213,6 +214,7 @@ void GizmoDrawer::DrawGizmos(Ref scene, bool occluded) auto [transform, sphere] = scene->m_Registry.get(e); m_LineShader->Bind(); + m_LineShader->SetUniform1f("u_Opacity", 0.5f); m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])), Vector3(sphere.Radius))); m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective()); @@ -238,6 +240,7 @@ void GizmoDrawer::DrawGizmos(Ref scene, bool occluded) Vector3 globalPosition = Vector3(transform.GetGlobalTransform()[3]); m_LineShader->Bind(); + m_LineShader->SetUniform1f("u_Opacity", 0.5f); m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), globalPosition), Vector3(emitter.MaxDistance))); m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective()); @@ -270,6 +273,7 @@ void GizmoDrawer::DrawGizmos(Ref scene, bool occluded) const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation); m_LineShader->Bind(); + m_LineShader->SetUniform1f("u_Opacity", 0.5f); m_LineShader->SetUniformMat4f("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix); m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective()); @@ -299,6 +303,7 @@ void GizmoDrawer::DrawGizmos(Ref scene, bool occluded) const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation); m_LineShader->Bind(); + m_LineShader->SetUniform1f("u_Opacity", 0.5f); m_LineShader->SetUniformMat4f("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix); m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective()); @@ -316,6 +321,7 @@ void GizmoDrawer::DrawGizmos(Ref scene, bool occluded) auto [transform, particle] = scene->m_Registry.get(e); m_LineShader->Bind(); + m_LineShader->SetUniform1f("u_Opacity", 0.5f); m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])), Vector3(particle.Radius))); m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective()); diff --git a/Editor/src/Windows/EditorInterface.cpp b/Editor/src/Windows/EditorInterface.cpp index 83e19b36..564592ae 100644 --- a/Editor/src/Windows/EditorInterface.cpp +++ b/Editor/src/Windows/EditorInterface.cpp @@ -53,6 +53,7 @@ #include #include +#include namespace Nuake { @@ -115,22 +116,28 @@ namespace Nuake { if (Engine::IsPlayMode()) { - if (ImGui::Button(ICON_FA_PAUSE, ImVec2(30, 30)) || (Input::IsKeyPressed(GLFW_KEY_F5))) + if (ImGui::Button(ICON_FA_PAUSE, ImVec2(30, 30)) || (Input::IsKeyDown(GLFW_KEY_F5))) { Engine::ExitPlayMode(); - + Engine::LoadScene(SceneSnapshot); Selection = EditorSelection(); } } else { - if (ImGui::Button(ICON_FA_PLAY, ImVec2(30, 30)) || (Input::IsKeyPressed(GLFW_KEY_F5))) + if (ImGui::Button(ICON_FA_PLAY, ImVec2(30, 30)) ) { - SceneSnapshot = Engine::GetCurrentScene()->Copy(); + this->SceneSnapshot = Engine::GetCurrentScene()->Copy(); - ScriptingEngineNet::Get().BuildProjectAssembly(Engine::GetProject()); - Engine::EnterPlayMode(); + auto job = [this]() + { + ScriptingEngineNet::Get().BuildProjectAssembly(Engine::GetProject()); + }; + + Selection = EditorSelection(); + + JobSystem::Get().Dispatch(job, []() { Engine::EnterPlayMode(); }); } if (ImGui::BeginItemTooltip()) @@ -148,7 +155,7 @@ namespace Nuake { ImGui::BeginDisabled(); } - if ((ImGui::Button(ICON_FA_STOP, ImVec2(30, 30)) || Input::IsKeyPressed(GLFW_KEY_F8)) && Engine::IsPlayMode()) + if ((ImGui::Button(ICON_FA_STOP, ImVec2(30, 30)) || Input::IsKeyPressed(GLFW_KEY_F5)) && Engine::IsPlayMode()) { Engine::ExitPlayMode(); @@ -240,7 +247,12 @@ namespace Nuake { if (ImGui::Button(ICON_FA_HAMMER, ImVec2(30, 30))) { - Nuake::ScriptingEngineNet::Get().BuildProjectAssembly(Engine::GetProject()); + JobSystem::Get().Dispatch([]() + { + Nuake::ScriptingEngineNet::Get().BuildProjectAssembly(Engine::GetProject()); + }, + []() {} + ); } if (ImGui::BeginItemTooltip()) @@ -360,7 +372,7 @@ namespace Nuake { m_IsViewportFocused = ImGui::IsWindowFocused(); - if (ImGui::GetIO().WantCaptureMouse && m_IsHoveringViewport && Input::IsMouseButtonPressed(GLFW_MOUSE_BUTTON_1) && !ImGuizmo::IsUsing() && m_IsViewportFocused) + if (!Engine::IsPlayMode() && ImGui::GetIO().WantCaptureMouse && m_IsHoveringViewport && Input::IsMouseButtonPressed(GLFW_MOUSE_BUTTON_1) && !ImGuizmo::IsUsing() && m_IsViewportFocused) { const auto windowPosNuake = Vector2(windowPos.x, windowPos.y); @@ -1952,7 +1964,8 @@ namespace Nuake { std::string projectPath = FileDialog::OpenFile(".scene"); Ref scene = Scene::New(); - if (!scene->Deserialize(FileSystem::ReadFile(projectPath, true))) + const std::string& fileContent = FileSystem::ReadFile(projectPath, true); + if (!scene->Deserialize(json::parse(fileContent))) { Logger::Log("Error failed loading scene: " + projectPath, "editor", CRITICAL); return; diff --git a/Editor/src/Windows/EditorSelectionPanel.cpp b/Editor/src/Windows/EditorSelectionPanel.cpp index ce15b92e..7856d7e1 100644 --- a/Editor/src/Windows/EditorSelectionPanel.cpp +++ b/Editor/src/Windows/EditorSelectionPanel.cpp @@ -170,6 +170,8 @@ void EditorSelectionPanel::DrawAddComponentMenu(Nuake::Entity entity) MenuItemComponent("Quake map", QuakeMapComponent); ImGui::Separator(); MenuItemComponent("Audio Emitter", AudioEmitterComponent); + ImGui::Separator(); + MenuItemComponent("Path", AudioEmitterComponent); ImGui::EndPopup(); } ImGui::Separator(); diff --git a/Editor/src/Windows/FileSystemUI.cpp b/Editor/src/Windows/FileSystemUI.cpp index 79064785..2791443e 100644 --- a/Editor/src/Windows/FileSystemUI.cpp +++ b/Editor/src/Windows/FileSystemUI.cpp @@ -355,7 +355,7 @@ namespace Nuake } ImGui::SetCursorPos(prevCursor); - ImGui::Image((ImTextureID)textureImage->GetID(), ImVec2(100, 100), ImVec2(0, 1), ImVec2(1, 0)); + ImGui::Image(reinterpret_cast(textureImage->GetID()), ImVec2(100, 100), ImVec2(0, 1), ImVec2(1, 0)); ImGui::PopStyleVar(); auto imguiStyle = ImGui::GetStyle(); diff --git a/Nuake/Engine.cpp b/Nuake/Engine.cpp index f323daf7..2cbe34a5 100644 --- a/Nuake/Engine.cpp +++ b/Nuake/Engine.cpp @@ -6,7 +6,7 @@ #include "src/Core/FileSystem.h" #include "src/Scripting/ScriptingEngine.h" #include "src/Audio/AudioManager.h" - +#include "src/Threading/JobSystem.h" #include "src/Rendering/Renderer.h" #include "src/Rendering/Renderer2D.h" @@ -41,6 +41,8 @@ namespace Nuake void Engine::Tick() { + JobSystem::Get().Update(); + s_Time = static_cast(glfwGetTime()); s_TimeStep = s_Time - s_LastFrameTime; s_LastFrameTime = s_Time; diff --git a/Nuake/src/Core/Input.cpp b/Nuake/src/Core/Input.cpp index a007acc5..81166c4f 100644 --- a/Nuake/src/Core/Input.cpp +++ b/Nuake/src/Core/Input.cpp @@ -41,7 +41,7 @@ namespace Nuake bool result = state == GLFW_PRESS; // First time pressed? - if (m_Keys.find(keycode) == m_Keys.end() || m_Keys[keycode] == true) + if (m_Keys.find(keycode) == m_Keys.end() || m_Keys[keycode] == false) { if (result) m_Keys[keycode] = true; diff --git a/Nuake/src/Physics/CollisionData.h b/Nuake/src/Physics/CollisionData.h new file mode 100644 index 00000000..d6f6d95e --- /dev/null +++ b/Nuake/src/Physics/CollisionData.h @@ -0,0 +1,16 @@ +#pragma once +#include + +namespace Nuake { + + namespace Physics { + + struct CollisionData + { + uint32_t Entity1; + uint32_t Entity2; + Vector3 Normal; + Vector3 Position; + }; + } +} diff --git a/Nuake/src/Physics/DynamicWorld.cpp b/Nuake/src/Physics/DynamicWorld.cpp index 2b65b61a..c1308fad 100644 --- a/Nuake/src/Physics/DynamicWorld.cpp +++ b/Nuake/src/Physics/DynamicWorld.cpp @@ -72,24 +72,10 @@ namespace Nuake static constexpr uint8_t NON_MOVING = 0; static constexpr uint8_t MOVING = 1; static constexpr uint8_t KINEMATIC = 2; - static constexpr uint8_t NUM_LAYERS = 3; - }; - - // Function that determines if two object layers can collide - static bool MyObjectCanCollide(JPH::ObjectLayer inObject1, JPH::ObjectLayer inObject2) - { - switch (inObject1) - { - case Layers::NON_MOVING: - return inObject2 == Layers::MOVING || inObject2 == Layers::KINEMATIC; // Non moving only collides with moving - case Layers::MOVING: - return true; // Moving collides with everything - case Layers::KINEMATIC: - return inObject2 == Layers::NON_MOVING || inObject2 == Layers::MOVING; // Only collides with non moving - default: - //JPH_ASSERT(false); - return false; - } + static constexpr uint8_t CHARACTER_GHOST = 3; + static constexpr uint8_t CHARACTER = 4; + static constexpr uint8_t SENSORS = 5; + static constexpr uint8_t NUM_LAYERS = 6; }; // Each broadphase layer results in a separate bounding volume tree in the broad phase. You at least want to have @@ -114,6 +100,9 @@ namespace Nuake // Create a mapping table from object to broad phase layer mObjectToBroadPhase[Layers::NON_MOVING] = BroadPhaseLayers::NON_MOVING; mObjectToBroadPhase[Layers::MOVING] = BroadPhaseLayers::MOVING; + mObjectToBroadPhase[Layers::CHARACTER] = BroadPhaseLayers::MOVING; + mObjectToBroadPhase[Layers::CHARACTER_GHOST] = BroadPhaseLayers::MOVING; + mObjectToBroadPhase[Layers::SENSORS] = BroadPhaseLayers::MOVING; } virtual JPH::uint GetNumBroadPhaseLayers() const override @@ -128,54 +117,51 @@ namespace Nuake return mObjectToBroadPhase[inLayer]; } -#if defined(JPH_EXTERNAL_PROFILE) || defined(JPH_PROFILE_ENABLED) - virtual const char* GetBroadPhaseLayerName(BroadPhaseLayer inLayer) const override - { - switch ((BroadPhaseLayer::Type)inLayer) - { - case (BroadPhaseLayer::Type)BroadPhaseLayers::NON_MOVING: return "NON_MOVING"; - case (BroadPhaseLayer::Type)BroadPhaseLayers::MOVING: return "MOVING"; - default: JPH_ASSERT(false); return "INVALID"; - } - } -#endif // JPH_EXTERNAL_PROFILE || JPH_PROFILE_ENABLED - private: JPH::BroadPhaseLayer mObjectToBroadPhase[Layers::NUM_LAYERS]; }; - // Function that determines if two broadphase layers can collide - static bool MyBroadPhaseCanCollide(JPH::ObjectLayer inLayer1, JPH::BroadPhaseLayer inLayer2) - { - using namespace JPH; - switch (inLayer1) - { - case Layers::NON_MOVING: - return inLayer2 == BroadPhaseLayers::MOVING; - case Layers::MOVING: - return true; - default: - JPH_ASSERT(false); - return false; - } - } - // An example contact listener class MyContactListener : public JPH::ContactListener { + private: + Physics::DynamicWorld* _World; + public: + MyContactListener(Physics::DynamicWorld* world) + : _World(world) + { + } + // See: ContactListener virtual JPH::ValidateResult OnContactValidate(const JPH::Body& inBody1, const JPH::Body& inBody2, JPH::RVec3Arg inBaseOffset, const JPH::CollideShapeResult& inCollisionResult) override { //std::cout << "Contact validate callback" << std::endl; // Allows you to ignore a contact before it is created (using layers to not make objects collide is cheaper!) - return JPH::ValidateResult::AcceptAllContactsForThisBodyPair; + return JPH::ValidateResult::AcceptAllContactsForThisBodyPair; } virtual void OnContactAdded(const JPH::Body& inBody1, const JPH::Body& inBody2, const JPH::ContactManifold& inManifold, JPH::ContactSettings& ioSettings) override { - //std::cout << "A contact was added" << std::endl; + int entity1 = static_cast(inBody1.GetUserData()); + int entity2 = static_cast(inBody2.GetUserData()); + + JPH::Vec3 joltNormal = inManifold.mWorldSpaceNormal; + Vector3 normal = Vector3(joltNormal.GetX(), joltNormal.GetY(), joltNormal.GetZ()); + + JPH::Vec3 joltPos = inManifold.GetWorldSpaceContactPointOn1(0); + Vector3 position = Vector3(joltPos.GetX(), joltPos.GetY(), joltPos.GetZ()); + + Physics::CollisionData data + { + entity1, + entity2, + normal, + position + }; + + _World->RegisterCollisionCallback(std::move(data)); } virtual void OnContactPersisted(const JPH::Body& inBody1, const JPH::Body& inBody2, const JPH::ContactManifold& inManifold, JPH::ContactSettings& ioSettings) override @@ -215,8 +201,9 @@ namespace Nuake return inLayer2 == BroadPhaseLayers::MOVING; case Layers::MOVING: return true; + case Layers::SENSORS: + return inLayer2 == BroadPhaseLayers::MOVING;; default: - return false; } } @@ -230,9 +217,15 @@ namespace Nuake switch (inObject1) { case Layers::NON_MOVING: - return inObject2 == Layers::MOVING; // Non moving only collides with moving + return inObject2 == Layers::MOVING || inObject2 == Layers::CHARACTER_GHOST || inObject2 == Layers::CHARACTER; // Non moving only collides with moving case Layers::MOVING: return true; // Moving collides with everything + case Layers::CHARACTER_GHOST: + return inObject2 != Layers::CHARACTER; + case Layers::CHARACTER: + return inObject2 != Layers::CHARACTER_GHOST; + case Layers::SENSORS: + return inObject2 == Layers::MOVING || inObject2 == Layers::CHARACTER_GHOST; default: return false; @@ -240,7 +233,6 @@ namespace Nuake } }; - BPLayerInterfaceImpl JoltBroadphaseLayerInterface = BPLayerInterfaceImpl(); ObjectVsBroadPhaseLayerFilterImpl JoltObjectVSBroadphaseLayerFilter = ObjectVsBroadPhaseLayerFilterImpl(); ObjectLayerPairFilterImpl JoltObjectVSObjectLayerFilter; @@ -249,7 +241,7 @@ namespace Nuake { DynamicWorld::DynamicWorld() : _stepCount(0) { - _registeredCharacters = std::map>(); + _registeredCharacters = std::map(); // Initialize Jolt Physics const uint32_t MaxBodies = 4096; @@ -269,7 +261,7 @@ namespace Nuake // A contact listener gets notified when bodies (are about to) collide, and when they separate again. // Note that this is called from a job so whatever you do here needs to be thread safe. // Registering one is entirely optional. - _contactListener = CreateScope(); + _contactListener = CreateScope(this); _JoltPhysicsSystem->SetContactListener(_contactListener.get()); // The main way to interact with the bodies in the physics system is through the body interface. There is a locking and a non-locking @@ -309,12 +301,29 @@ namespace Nuake layer = Layers::MOVING; } + if (rb->IsTrigger()) + { + layer = Layers::SENSORS; + motionType = JPH::EMotionType::Kinematic; + } + const auto& startPos = rb->GetPosition(); const Quat& bodyRotation = rb->GetRotation(); const auto& joltRotation = JPH::Quat(bodyRotation.x, bodyRotation.y, bodyRotation.z, bodyRotation.w); const auto& joltPos = JPH::Vec3(startPos.x, startPos.y, startPos.z); - auto joltShape = GetJoltShape(rb->GetShape()); + JPH::Ref joltShape = GetJoltShape(rb->GetShape()); + + if (!joltShape) + { + return; + } + JPH::BodyCreationSettings bodySettings(joltShape, joltPos, joltRotation, motionType, layer); + bodySettings.mIsSensor = rb->IsTrigger(); + if (bodySettings.mIsSensor) + { + bodySettings.mCollideKinematicVsNonDynamic = true; + } bodySettings.mAllowedDOFs = (JPH::EAllowedDOFs::All); @@ -354,7 +363,7 @@ namespace Nuake bodySettings.mUserData = entityId; // Create the actual rigid body JPH::BodyID body = _JoltBodyInterface->CreateAndAddBody(bodySettings, JPH::EActivation::Activate); // Note that if we run out of bodies this can return nullptr - uint32_t bodyIndex = (uint32_t)body.GetIndex(); + uint32_t bodyIndex = (uint32_t)body.GetIndexAndSequenceNumber(); _registeredBodies.push_back(bodyIndex); } @@ -372,15 +381,38 @@ namespace Nuake settings->mPenetrationRecoverySpeed = 1.0f; settings->mPredictiveContactDistance = 0.01f; settings->mShape = GetJoltShape(cc->Shape); - auto joltPosition = JPH::Vec3(cc->Position.x, cc->Position.y, cc->Position.z); const Quat& bodyRotation = cc->Rotation; const auto& joltRotation = JPH::Quat(bodyRotation.x, bodyRotation.y, bodyRotation.z, bodyRotation.w); - auto character = CreateRef(settings, std::move(joltPosition), std::move(joltRotation), _JoltPhysicsSystem.get()); + auto character = CreateRef(settings, std::move(joltPosition), joltRotation, _JoltPhysicsSystem.get()); + + // add ghost kinematic body to respond to hit test as the virtual char are not present in the world. + JPH::BodyInterface& bodyInterface = _JoltPhysicsSystem->GetBodyInterface(); + + const float mass = 0.0f; + JPH::EMotionType motionType = JPH::EMotionType::Dynamic; + JPH::ObjectLayer layer = Layers::CHARACTER_GHOST; + + const auto& startPos = joltPosition; + auto joltShape = GetJoltShape(cc->Shape); + JPH::BodyCreationSettings bodySettings(joltShape, startPos, joltRotation, motionType, layer); + + int entityId = cc->GetEntity().GetID(); + if (entityId == 0) + { + Logger::Log("ERROR"); + } + + bodySettings.mUserData = cc->Owner.GetHandle(); + + // Create the actual rigid body + JPH::BodyID body = _JoltBodyInterface->CreateAndAddBody(bodySettings, JPH::EActivation::Activate); // Note that if we run out of bodies this can return nullptr + uint32_t bodyIndex = body.GetIndexAndSequenceNumber(); + //_registeredBodies.push_back(bodyIndex); // To get the jolt character control from a scene entity. - _registeredCharacters[cc->Owner.GetHandle()] = character; + _registeredCharacters[cc->Owner.GetHandle()] = CharacterGhostPair{ character, bodyIndex }; } bool DynamicWorld::IsCharacterGrounded(const Entity& entity) @@ -388,7 +420,7 @@ namespace Nuake const uint32_t entityHandle = entity.GetHandle(); if (_registeredCharacters.find(entityHandle) != _registeredCharacters.end()) { - auto& characterController = _registeredCharacters[entityHandle]; + auto& characterController = _registeredCharacters[entityHandle].Character; const auto groundState = characterController->GetGroundState(); return groundState == JPH::CharacterBase::EGroundState::OnGround; @@ -398,6 +430,16 @@ namespace Nuake return false; } + void DynamicWorld::SetCharacterControllerPosition(const Entity & entity, const Vector3 & position) + { + const uint32_t entityHandle = entity.GetHandle(); + if (_registeredCharacters.find(entityHandle) != _registeredCharacters.end()) + { + auto& characterController = _registeredCharacters[entityHandle].Character; + characterController->SetPosition({ position.x, position.y, position.z }); + } + } + std::vector DynamicWorld::Raycast(const Vector3& from, const Vector3& to) { // Create jolt ray @@ -442,28 +484,27 @@ namespace Nuake for (const auto& body : _registeredBodies) { auto bodyId = static_cast(body); - JPH::Vec3 position = bodyInterface.GetCenterOfMassPosition(bodyId); - JPH::Vec3 velocity = bodyInterface.GetLinearVelocity(bodyId); - JPH::Mat44 joltTransform = bodyInterface.GetWorldTransform(bodyId); - const auto bodyRotation = bodyInterface.GetRotation(bodyId); - - Matrix4 transform = glm::mat4( - joltTransform(0, 0), joltTransform(1, 0), joltTransform(2, 0), joltTransform(3, 0), - joltTransform(0, 1), joltTransform(1, 1), joltTransform(2, 1), joltTransform(3, 1), - joltTransform(0, 2), joltTransform(1, 2), joltTransform(2, 2), joltTransform(3, 2), - joltTransform(0, 3), joltTransform(1, 3), joltTransform(2, 3), joltTransform(3, 3) - ); - - Vector3 scale = Vector3(); - Quat rotation = Quat(); - Vector3 pos = Vector3(); - Vector3 skew = Vector3(); - Vector4 pesp = Vector4(); - glm::decompose(transform, scale, rotation, pos, skew, pesp); - - auto entId = static_cast(bodyInterface.GetUserData(bodyId)); - if (entId != 0) + if (auto entId = static_cast(bodyInterface.GetUserData(bodyId)); entId != 0) { + JPH::Vec3 position = bodyInterface.GetCenterOfMassPosition(bodyId); + JPH::Vec3 velocity = bodyInterface.GetLinearVelocity(bodyId); + JPH::Mat44 joltTransform = bodyInterface.GetWorldTransform(bodyId); + const auto bodyRotation = bodyInterface.GetRotation(bodyId); + + Matrix4 transform = glm::mat4( + joltTransform(0, 0), joltTransform(1, 0), joltTransform(2, 0), joltTransform(3, 0), + joltTransform(0, 1), joltTransform(1, 1), joltTransform(2, 1), joltTransform(3, 1), + joltTransform(0, 2), joltTransform(1, 2), joltTransform(2, 2), joltTransform(3, 2), + joltTransform(0, 3), joltTransform(1, 3), joltTransform(2, 3), joltTransform(3, 3) + ); + + Vector3 scale = Vector3(); + Quat rotation = Quat(); + Vector3 pos = Vector3(); + Vector3 skew = Vector3(); + Vector4 pesp = Vector4(); + glm::decompose(transform, scale, rotation, pos, skew, pesp); + Entity entity = Engine::GetCurrentScene()->GetEntityByID(entId); auto& transformComponent = entity.GetComponent(); transformComponent.SetLocalPosition(pos); @@ -476,15 +517,11 @@ namespace Nuake void DynamicWorld::SyncCharactersTransforms() { - // TODO(ANTO): Finish this to connect updated jolt transforms back to the entity. - // The problem was that I dont know yet how to go from jolt body ptr to the entity - // Combinations of find and iterators etc. I do not have the brain power rn zzz. - // const auto& bodyInterface = _JoltPhysicsSystem->GetBodyInterface(); for (const auto& e : _registeredCharacters) { Entity entity { (entt::entity)e.first, Engine::GetCurrentScene().get()}; - Ref characterController = e.second; + Ref characterController = e.second.Character; JPH::Mat44 joltTransform = characterController->GetWorldTransform(); const auto bodyRotation = characterController->GetRotation(); @@ -512,6 +549,12 @@ namespace Nuake void DynamicWorld::StepSimulation(Timestep ts) { + // Clear collisions, before very step + { + std::scoped_lock lock(_CollisionCallbackMutex); + _CollisionCallbacks.clear(); + } + if (ts > 0.1f) { ts = 0.08f; @@ -529,7 +572,7 @@ namespace Nuake if(ts > minStepDuration) { #ifdef NK_DEBUG - Logger::Log("Large step detected: " + std::to_string(ts), "physics", WARNING); + //Logger::Log("Large step detected: " + std::to_string(ts), "physics", WARNING); #endif collisionSteps = static_cast(ts) / minStepDuration; } @@ -562,7 +605,7 @@ namespace Nuake auto characterController = characterControllerComponent.GetCharacterController(); const auto& broadPhaseLayerFilter = _JoltPhysicsSystem->GetDefaultBroadPhaseLayerFilter(Layers::NON_MOVING); - const auto& LayerFilter = _JoltPhysicsSystem->GetDefaultLayerFilter(Layers::MOVING); + const auto& LayerFilter = _JoltPhysicsSystem->GetDefaultLayerFilter(Layers::CHARACTER); const auto& joltGravity = _JoltPhysicsSystem->GetGravity(); auto& tempAllocatorPtr = *(joltTempAllocator); if (characterController->AutoStepping) @@ -574,12 +617,33 @@ namespace Nuake joltUpdateSettings.mWalkStairsStepForwardTest = characterController->StepDistance; joltUpdateSettings.mWalkStairsMinStepForward = characterController->StepMinDistance; - c.second->ExtendedUpdate(ts, joltGravity, joltUpdateSettings, broadPhaseLayerFilter, LayerFilter, { }, { }, tempAllocatorPtr); + c.second.Character->ExtendedUpdate(ts, joltGravity, joltUpdateSettings, broadPhaseLayerFilter, LayerFilter, { }, { }, tempAllocatorPtr); } else { - c.second->Update(ts, joltGravity, broadPhaseLayerFilter, LayerFilter, {}, {}, tempAllocatorPtr); + c.second.Character->Update(ts, joltGravity, broadPhaseLayerFilter, LayerFilter, {}, {}, tempAllocatorPtr); } + + uint32_t ghostId = c.second.Ghost; + + JPH::Mat44 joltTransform = c.second.Character->GetWorldTransform(); + const auto bodyRotation = c.second.Character->GetRotation(); + Matrix4 transform = glm::mat4( + joltTransform(0, 0), joltTransform(1, 0), joltTransform(2, 0), joltTransform(3, 0), + joltTransform(0, 1), joltTransform(1, 1), joltTransform(2, 1), joltTransform(3, 1), + joltTransform(0, 2), joltTransform(1, 2), joltTransform(2, 2), joltTransform(3, 2), + joltTransform(0, 3), joltTransform(1, 3), joltTransform(2, 3), joltTransform(3, 3) + ); + + Vector3 scale = Vector3(); + Quat rotation = Quat(); + Vector3 pos = Vector3(); + Vector3 skew = Vector3(); + Vector4 pesp = Vector4(); + glm::decompose(transform, scale, rotation, pos, skew, pesp); + + //auto& bodyInterface = _JoltPhysicsSystem->GetBodyInterfaceNoLock(); + _JoltBodyInterface->MoveKinematic(static_cast(ghostId), JPH::Vec3{ pos.x, pos.y, pos.z }, { rotation.x, rotation.y, rotation.z, rotation.w }, ts); } } @@ -590,6 +654,11 @@ namespace Nuake Logger::Log("Failed to run simulation update", "physics", CRITICAL); } + for (auto& c : _registeredCharacters) + { + + } + SyncEntitiesTranforms(); SyncCharactersTransforms(); } @@ -615,13 +684,36 @@ namespace Nuake } } + void DynamicWorld::RegisterCollisionCallback(const CollisionData& data) + { + // This will be called from multiple threads + std::scoped_lock lock(_CollisionCallbackMutex); + + _CollisionCallbacks.push_back(std::move(data)); + } + + const std::vector& DynamicWorld::GetCollisionsData() + { + std::scoped_lock lock(_CollisionCallbackMutex); + return _CollisionCallbacks; + } + void DynamicWorld::MoveAndSlideCharacterController(const Entity& entity, const Vector3& velocity) { const uint32_t entityHandle = entity.GetHandle(); if (_registeredCharacters.find(entityHandle) != _registeredCharacters.end()) { - auto& characterController = _registeredCharacters[entityHandle]; - characterController->SetLinearVelocity(JPH::Vec3(velocity.x, velocity.y, velocity.z)); + auto& characterController = _registeredCharacters[entityHandle].Character; + const auto& joltVelocity = JPH::Vec3(velocity.x, velocity.y, velocity.z); + characterController->SetLinearVelocity(joltVelocity); + + auto& ghost = _registeredCharacters[entityHandle].Ghost; + auto ghostPos = _JoltBodyInterface->GetPosition(static_cast(ghost)); + //std::cout << "Ghost pos: " << ghostPos.GetX() << ", " << ghostPos.GetY() << ", " << ghostPos.GetZ() << std::endl; + + auto charPos = characterController->GetPosition(); + //std::cout << "Char pos: " << charPos.GetX() << ", " << charPos.GetY() << ", " << charPos.GetZ() << std::endl; + //_JoltBodyInterface->SetLinearVelocity(static_cast(ghost), joltVelocity); } } @@ -631,7 +723,7 @@ namespace Nuake for (const auto& body : _registeredBodies) { auto bodyId = static_cast(body); - auto entityId = static_cast(bodyInterface.GetUserData(bodyId)); + auto entityId = bodyInterface.GetUserData(bodyId); if (entityId == entity.GetID()) { bodyInterface.AddForce(bodyId, JPH::Vec3(force.x, force.y, force.z)); @@ -728,6 +820,14 @@ namespace Nuake break; } + if (!result.IsValid()) + { + const std::string errorMessage = std::string("Failed to create physics shape: ") + result.GetError().c_str(); + Logger::Log(errorMessage, "physics", WARNING); + + return nullptr; + } + return result.Get(); } } diff --git a/Nuake/src/Physics/DynamicWorld.h b/Nuake/src/Physics/DynamicWorld.h index 5569b799..698b725b 100644 --- a/Nuake/src/Physics/DynamicWorld.h +++ b/Nuake/src/Physics/DynamicWorld.h @@ -9,9 +9,11 @@ #include #include "CharacterController.h" +#include "CollisionData.h" #include "Jolt/Jolt.h" +#include namespace JPH { @@ -35,6 +37,14 @@ namespace Nuake namespace Physics { + struct CharacterGhostPair + { + Ref Character; + uint32_t Ghost; + }; + + + class DynamicWorld { private: @@ -48,8 +58,10 @@ namespace Nuake BPLayerInterfaceImpl* _JoltBroadphaseLayerInterface; std::vector _registeredBodies; - std::map> _registeredCharacters; + std::map _registeredCharacters; + std::mutex _CollisionCallbackMutex; + std::vector _CollisionCallbacks; public: DynamicWorld(); @@ -61,6 +73,8 @@ namespace Nuake void AddGhostbody(Ref gb); void AddCharacterController(Ref cc); bool IsCharacterGrounded(const Entity& entity); + void SetCharacterControllerPosition(const Entity& entity, const Vector3& position); + // This is going to be ugly. TODO: Find a better way that passing itself as a parameter void MoveAndSlideCharacterController(const Entity& entity, const Vector3& velocity); void AddForceToRigidBody(Entity& entity, const Vector3& force); @@ -69,6 +83,8 @@ namespace Nuake void StepSimulation(Timestep ts); void Clear(); + void RegisterCollisionCallback(const CollisionData& data); + const std::vector& GetCollisionsData(); private: JPH::Ref GetJoltShape(const Ref shape); void SyncEntitiesTranforms(); diff --git a/Nuake/src/Physics/PhysicsManager.cpp b/Nuake/src/Physics/PhysicsManager.cpp index 620c5b77..d48b0b98 100644 --- a/Nuake/src/Physics/PhysicsManager.cpp +++ b/Nuake/src/Physics/PhysicsManager.cpp @@ -27,6 +27,11 @@ namespace Nuake m_World->AddCharacterController(cc); } + void PhysicsManager::SetCharacterControllerPosition(const Entity& entity, const Vector3& position) + { + m_World->SetCharacterControllerPosition(entity, position); + } + void PhysicsManager::Step(Timestep ts) { m_World->StepSimulation(ts); @@ -42,6 +47,11 @@ namespace Nuake return m_World->Raycast(from, to); } + const std::vector& PhysicsManager::GetCollisions() + { + return m_World->GetCollisionsData(); + } + void PhysicsManager::DrawDebug() { if (m_DrawDebug) diff --git a/Nuake/src/Physics/PhysicsManager.h b/Nuake/src/Physics/PhysicsManager.h index f4074f07..418f60ce 100644 --- a/Nuake/src/Physics/PhysicsManager.h +++ b/Nuake/src/Physics/PhysicsManager.h @@ -3,6 +3,7 @@ #include "../Scene/Entities/Entity.h" #include "DynamicWorld.h" #include "Rigibody.h" +#include "CollisionData.h" #include "RaycastResult.h" @@ -49,8 +50,12 @@ namespace Nuake std::vector Raycast(const Vector3& from, const Vector3& to); + const std::vector& GetCollisions(); + void RegisterBody(Ref rb); void RegisterGhostBody(Ref rb); void RegisterCharacterController(Ref c); + + void SetCharacterControllerPosition(const Entity& entity, const Vector3& position); }; } diff --git a/Nuake/src/Physics/Rigibody.h b/Nuake/src/Physics/Rigibody.h index 8344a9b0..a6282569 100644 --- a/Nuake/src/Physics/Rigibody.h +++ b/Nuake/src/Physics/Rigibody.h @@ -20,6 +20,7 @@ namespace Nuake Quat _rotation; Entity _entity; + bool _isTrigger = false; bool m_LockXAxis = false; bool m_LockYAxis = false; bool m_LockZAxis = false; @@ -33,13 +34,16 @@ namespace Nuake void UpdateTransform(); + void SetIsTrigger(bool isTrigger) { _isTrigger = isTrigger; } + bool IsTrigger() const { return _isTrigger; } + bool GetLockXAxis() const { return m_LockXAxis; } bool GetLockYAxis() const { return m_LockYAxis; } bool GetLockZAxis() const { return m_LockZAxis; } - void setLockXAxis(bool lock) { m_LockXAxis = lock; } - void setLockYAxis(bool lock) { m_LockYAxis = lock; } - void setLockZAxis(bool lock) { m_LockZAxis = lock; } + void SetLockXAxis(bool lock) { m_LockXAxis = lock; } + void SetLockYAxis(bool lock) { m_LockYAxis = lock; } + void SetLockZAxis(bool lock) { m_LockZAxis = lock; } void SetEntityID(Entity ent); Vector3 GetPosition() const { return _position; } diff --git a/Nuake/src/Resource/StaticResources.cpp b/Nuake/src/Resource/StaticResources.cpp index 991b291b..f6f37e48 100644 --- a/Nuake/src/Resource/StaticResources.cpp +++ b/Nuake/src/Resource/StaticResources.cpp @@ -235206,13 +235206,17 @@ const std::string Resources_Shaders_gizmo_shader_path = R"(Resources/Shaders/giz 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x2a, 0x20, 0x76, 0x65, 0x63, 0x34, 0x28, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x75, 0x5f, 0x4f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x29, 0x3b, 0x0d, 0x0a, - 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x45, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x49, 0x44, 0x20, 0x3d, 0x20, 0x75, 0x5f, 0x45, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x49, 0x44, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, - 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x7d + 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x28, 0x75, 0x5f, 0x4f, + 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x20, 0x3e, 0x3d, 0x20, 0x30, 0x2e, + 0x35, 0x66, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0d, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x67, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x49, 0x44, 0x20, 0x3d, 0x20, 0x75, 0x5f, 0x45, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x49, 0x44, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x46, 0x72, + 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x6f, + 0x6c, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x7d }; - unsigned int Resources_Shaders_gizmo_shader_len = 994; + unsigned int Resources_Shaders_gizmo_shader_len = 1039; // Data for file: Resources_Shaders_line_shader_path const std::string Resources_Shaders_line_shader_path = R"(Resources/Shaders/line.shader)"; @@ -235325,66 +235329,80 @@ const std::string Resources_Shaders_outline_shader_path = R"(Resources/Shaders/o 0x61, 0x74, 0x20, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x20, 0x3d, 0x20, 0x34, 0x2e, 0x66, 0x3b, 0x0d, 0x0a, 0x09, 0x76, 0x65, 0x63, 0x32, 0x20, 0x75, 0x76, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x55, 0x56, 0x3b, 0x0d, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, - 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x61, 0x73, 0x70, - 0x65, 0x63, 0x74, 0x20, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x0d, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x61, 0x73, 0x70, 0x65, - 0x63, 0x74, 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x20, 0x2f, 0x20, 0x76, - 0x65, 0x63, 0x32, 0x28, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x53, - 0x69, 0x7a, 0x65, 0x28, 0x75, 0x5f, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x30, 0x29, 0x29, - 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, 0x09, 0x76, 0x65, - 0x63, 0x34, 0x20, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, - 0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, 0x34, 0x28, 0x30, 0x2e, 0x30, 0x2c, - 0x20, 0x30, 0x2e, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c, 0x20, 0x30, - 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, - 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, - 0x2e, 0x30, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x54, 0x41, 0x55, 0x3b, - 0x20, 0x69, 0x20, 0x2b, 0x3d, 0x20, 0x54, 0x41, 0x55, 0x20, 0x2f, 0x20, - 0x73, 0x74, 0x65, 0x70, 0x73, 0x29, 0x20, 0x0d, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x2f, 0x2f, 0x20, 0x53, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x69, 0x6e, - 0x20, 0x61, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x20, - 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x0d, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x6f, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, - 0x73, 0x69, 0x6e, 0x28, 0x69, 0x29, 0x2c, 0x20, 0x63, 0x6f, 0x73, 0x28, - 0x69, 0x29, 0x29, 0x20, 0x2a, 0x20, 0x61, 0x73, 0x70, 0x65, 0x63, 0x74, - 0x20, 0x2a, 0x20, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3b, 0x0d, 0x0a, - 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x20, 0x3d, - 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x28, 0x75, 0x5f, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, - 0x2c, 0x20, 0x75, 0x76, 0x20, 0x2b, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x29, 0x2e, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x0d, 0x0a, 0x09, - 0x09, 0x2f, 0x2f, 0x20, 0x4d, 0x69, 0x78, 0x20, 0x6f, 0x75, 0x74, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x62, 0x61, 0x63, - 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x09, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x20, 0x3d, - 0x20, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x28, - 0x30, 0x2e, 0x35, 0x2c, 0x20, 0x30, 0x2e, 0x37, 0x2c, 0x20, 0x69, 0x6e, - 0x74, 0x28, 0x63, 0x6f, 0x6c, 0x20, 0x21, 0x3d, 0x20, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x29, 0x20, 0x2a, 0x20, 0x31, 0x30, 0x2e, 0x30, 0x66, - 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, - 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x78, 0x28, 0x66, 0x72, - 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x75, 0x5f, 0x4f, - 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, - 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, - 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x28, - 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x61, 0x20, - 0x3e, 0x20, 0x30, 0x2e, 0x31, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, - 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x61, 0x20, 0x3d, - 0x20, 0x31, 0x2e, 0x30, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, - 0x20, 0x6d, 0x69, 0x78, 0x28, 0x76, 0x65, 0x63, 0x34, 0x28, 0x30, 0x29, - 0x2c, 0x20, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, - 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x28, 0x75, 0x5f, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, - 0x2c, 0x20, 0x75, 0x76, 0x29, 0x2e, 0x72, 0x20, 0x3d, 0x3d, 0x20, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a + 0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, 0x09, 0x2f, 0x2f, 0x20, 0x73, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x0d, + 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6d, 0x69, 0x64, 0x64, 0x6c, + 0x65, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x74, 0x65, + 0x78, 0x74, 0x75, 0x72, 0x65, 0x28, 0x75, 0x5f, 0x45, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x75, + 0x76, 0x29, 0x2e, 0x72, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x2f, 0x2f, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, + 0x61, 0x73, 0x70, 0x65, 0x63, 0x74, 0x20, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x61, + 0x73, 0x70, 0x65, 0x63, 0x74, 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x20, + 0x2f, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, 0x74, 0x65, 0x78, 0x74, 0x75, + 0x72, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x28, 0x75, 0x5f, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, + 0x30, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, + 0x09, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x68, 0x61, 0x73, 0x48, 0x69, + 0x74, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x30, 0x66, 0x3b, 0x0d, 0x0a, 0x09, + 0x76, 0x65, 0x63, 0x34, 0x20, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, + 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, 0x34, 0x28, 0x30, 0x2e, + 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c, + 0x20, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x66, 0x6f, + 0x72, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x69, 0x20, 0x3d, + 0x20, 0x30, 0x2e, 0x30, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x54, 0x41, + 0x55, 0x3b, 0x20, 0x69, 0x20, 0x2b, 0x3d, 0x20, 0x54, 0x41, 0x55, 0x20, + 0x2f, 0x20, 0x73, 0x74, 0x65, 0x70, 0x73, 0x29, 0x20, 0x0d, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x2f, 0x2f, 0x20, 0x53, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, + 0x69, 0x6e, 0x20, 0x61, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6c, 0x61, + 0x72, 0x20, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x0d, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, + 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, + 0x32, 0x28, 0x73, 0x69, 0x6e, 0x28, 0x69, 0x29, 0x2c, 0x20, 0x63, 0x6f, + 0x73, 0x28, 0x69, 0x29, 0x29, 0x20, 0x2a, 0x20, 0x61, 0x73, 0x70, 0x65, + 0x63, 0x74, 0x20, 0x2a, 0x20, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3b, + 0x0d, 0x0a, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x63, 0x6f, 0x6c, + 0x20, 0x3d, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x28, 0x75, + 0x5f, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x65, 0x78, 0x74, 0x75, + 0x72, 0x65, 0x2c, 0x20, 0x75, 0x76, 0x20, 0x2b, 0x20, 0x6f, 0x66, 0x66, + 0x73, 0x65, 0x74, 0x29, 0x2e, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x0d, + 0x0a, 0x09, 0x09, 0x69, 0x66, 0x28, 0x63, 0x6f, 0x6c, 0x20, 0x3d, 0x3d, + 0x20, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x29, 0x0d, 0x0a, 0x09, 0x09, + 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x68, 0x61, 0x73, 0x48, 0x69, 0x74, + 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x66, 0x3b, 0x0d, 0x0a, 0x09, 0x09, + 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x2f, 0x2f, 0x20, 0x4d, 0x69, + 0x78, 0x20, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, + 0x64, 0x0d, 0x0a, 0x09, 0x09, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x20, 0x3d, 0x20, 0x73, 0x6d, 0x6f, 0x6f, 0x74, + 0x68, 0x73, 0x74, 0x65, 0x70, 0x28, 0x30, 0x2e, 0x35, 0x2c, 0x20, 0x30, + 0x2e, 0x39, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x28, 0x63, 0x6f, 0x6c, 0x20, + 0x21, 0x3d, 0x20, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x29, 0x20, 0x2a, + 0x20, 0x68, 0x61, 0x73, 0x48, 0x69, 0x74, 0x20, 0x2a, 0x20, 0x31, 0x30, + 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x66, 0x72, 0x61, + 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x78, + 0x28, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, + 0x75, 0x5f, 0x4f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, + 0x6f, 0x72, 0x2c, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x29, 0x3b, 0x0d, + 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x69, 0x66, 0x28, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, + 0x2e, 0x61, 0x20, 0x3e, 0x20, 0x30, 0x2e, 0x31, 0x29, 0x0d, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, + 0x61, 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x66, 0x3b, 0x0d, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, + 0x72, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x78, 0x28, 0x76, 0x65, 0x63, 0x34, + 0x28, 0x30, 0x29, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, + 0x6f, 0x72, 0x2c, 0x20, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x53, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x21, 0x3d, 0x20, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x20, 0x26, 0x26, 0x20, 0x68, 0x61, 0x73, 0x48, 0x69, 0x74, + 0x20, 0x3e, 0x20, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, + 0x0d, 0x0a }; - unsigned int Resources_Shaders_outline_shader_len = 1260; + unsigned int Resources_Shaders_outline_shader_len = 1418; // Data for file: Resources_Shaders_pbr_shader_path const std::string Resources_Shaders_pbr_shader_path = R"(Resources/Shaders/pbr.shader)"; diff --git a/Nuake/src/Scene/Systems/PhysicsSystem.cpp b/Nuake/src/Scene/Systems/PhysicsSystem.cpp index e0bd94c7..3988b325 100644 --- a/Nuake/src/Scene/Systems/PhysicsSystem.cpp +++ b/Nuake/src/Scene/Systems/PhysicsSystem.cpp @@ -52,12 +52,6 @@ namespace Nuake { auto [transform, brush] = brushes.get(e); - for (auto& r : brush.Rigidbody) - { - //r->m_Transform->setOrigin(btVector3(transform.GlobalTranslation.x, transform.GlobalTranslation.y, transform.GlobalTranslation.z)); - //r->UpdateTransform(*r->m_Transform); - } - if (!brush.IsFunc) continue; @@ -73,37 +67,6 @@ namespace Nuake } } } - - //auto bspTriggerView = m_Scene->m_Registry.view(); - //for (auto e : bspTriggerView) - //{ - // auto [transform, brush, trigger] = bspTriggerView.get(e); - // trigger.GhostObject->ScanOverlap(); - - // brush.Targets.clear(); - // auto targetnameView = m_Scene->m_Registry.view(); - // for (auto e2 : targetnameView) - // { - // auto [ttransform, name] = targetnameView.get(e2); - - // if (name.Name == brush.target) { - // brush.Targets.push_back(Entity{ e2, m_Scene }); - // } - // } - //} - - - /*auto physicGroup = m_Scene->m_Registry.view(); - for (auto e : physicGroup) { - auto [transform, rb] = physicGroup.get(e); - rb.SyncTransformComponent(&m_Scene->m_Registry.get(e)); - }*/ - - //auto ccGroup = m_Scene->m_Registry.view(); - //for (auto e : ccGroup) { - // auto [transform, rb] = ccGroup.get(e); - // rb.SyncWithTransform(m_Scene->m_Registry.get(e)); - //} } void PhysicsSystem::FixedUpdate(Timestep ts) @@ -219,6 +182,8 @@ namespace Nuake Entity ent = Entity({ e, m_Scene }); Ref rigidBody; Ref shape; + + bool isTrigger = false; if (rigidBodyComponent.GetRigidBody()) { continue; @@ -227,6 +192,7 @@ namespace Nuake if (ent.HasComponent()) { BoxColliderComponent& boxComponent = ent.GetComponent(); + isTrigger = boxComponent.IsTrigger; shape = CreateRef(boxComponent.Size); } @@ -235,6 +201,7 @@ namespace Nuake auto& capsuleComponent = ent.GetComponent(); float radius = capsuleComponent.Radius; float height = capsuleComponent.Height; + isTrigger = capsuleComponent.IsTrigger; shape = CreateRef(radius, height); } @@ -243,12 +210,14 @@ namespace Nuake auto& cylinderComponent = ent.GetComponent(); float radius = cylinderComponent.Radius; float height = cylinderComponent.Height; + isTrigger = cylinderComponent.IsTrigger; shape = CreateRef(radius, height); } if (ent.HasComponent()) { const auto& component = ent.GetComponent(); + isTrigger = component.IsTrigger; shape = CreateRef(component.Radius); } @@ -262,6 +231,8 @@ namespace Nuake const auto& modelComponent = ent.GetComponent(); const auto& component = ent.GetComponent(); + isTrigger = component.IsTrigger; + if (modelComponent.ModelResource) { uint32_t subMeshId = component.SubMesh; @@ -282,10 +253,14 @@ namespace Nuake } rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalRotation(), transform.GetGlobalTransform(), shape, ent); - rigidBody->setLockXAxis(rigidBodyComponent.LockX); - rigidBody->setLockYAxis(rigidBodyComponent.LockY); - rigidBody->setLockZAxis(rigidBodyComponent.LockZ); + rigidBody->SetLockXAxis(rigidBodyComponent.LockX); + rigidBody->SetLockYAxis(rigidBodyComponent.LockY); + rigidBody->SetLockZAxis(rigidBodyComponent.LockZ); + + rigidBody->SetIsTrigger(isTrigger); + PhysicsManager::Get().RegisterBody(rigidBody); + rigidBodyComponent.Rigidbody = rigidBody; } } diff --git a/Nuake/src/Scene/Systems/ScriptingSystem.cpp b/Nuake/src/Scene/Systems/ScriptingSystem.cpp index cb0b9487..f7586ce0 100644 --- a/Nuake/src/Scene/Systems/ScriptingSystem.cpp +++ b/Nuake/src/Scene/Systems/ScriptingSystem.cpp @@ -5,7 +5,7 @@ #include "Engine.h" #include "src/Scripting/ScriptingEngineNet.h" - +#include "src/Physics/PhysicsManager.h" namespace Nuake { @@ -52,13 +52,22 @@ namespace Nuake if (netScriptComponent.ScriptPath.empty()) continue; - // Creates an instance of the entity script in C# auto entity = Entity{ e, m_Scene }; - scriptingEngineNet.RegisterEntityScript(entity); - // We can now call on init on it. - auto scriptInstance = scriptingEngineNet.GetEntityScript(entity); - scriptInstance.InvokeMethod("OnInit"); + // Creates an instance of the entity script in C# + scriptingEngineNet.RegisterEntityScript(entity); + } + + for (auto& e : netEntities) + { + auto entity = Entity{ e, m_Scene }; + + if (entity.IsValid() && scriptingEngineNet.HasEntityScriptInstance(entity)) + { + // We can now call on init on it. + auto scriptInstance = scriptingEngineNet.GetEntityScript(entity); + scriptInstance.InvokeMethod("OnInit"); + } } return true; @@ -91,6 +100,8 @@ namespace Nuake auto scriptInstance = scriptingEngineNet.GetEntityScript(entity); scriptInstance.InvokeMethod("OnUpdate", ts.GetSeconds()); } + + DispatchPhysicCallbacks(); } void ScriptingSystem::FixedUpdate(Timestep ts) @@ -157,4 +168,23 @@ namespace Nuake ScriptingEngine::Close(); ScriptingEngineNet::Get().Uninitialize(); } + + void ScriptingSystem::DispatchPhysicCallbacks() + { + auto& scriptingEngineNet = ScriptingEngineNet::Get(); + + auto& physicsManager = PhysicsManager::Get(); + const auto& collisions = physicsManager.GetCollisions(); + for (const auto& col : collisions) + { + Entity entity1 = m_Scene->GetEntityByID(col.Entity1); + Entity entity2 = m_Scene->GetEntityByID(col.Entity2); + + if (entity1.IsValid() && scriptingEngineNet.HasEntityScriptInstance(entity1)) + { + auto scriptInstance = scriptingEngineNet.GetEntityScript(entity1); + scriptInstance.InvokeMethod("OnCollisionInternal", (int)col.Entity1, (int)col.Entity2); + } + } + } } diff --git a/Nuake/src/Scene/Systems/ScriptingSystem.h b/Nuake/src/Scene/Systems/ScriptingSystem.h index 6ab630c2..106e7ba8 100644 --- a/Nuake/src/Scene/Systems/ScriptingSystem.h +++ b/Nuake/src/Scene/Systems/ScriptingSystem.h @@ -13,5 +13,8 @@ namespace Nuake { void Draw() override {} void FixedUpdate(Timestep ts) override; void Exit() override; + + private: + void DispatchPhysicCallbacks(); }; } diff --git a/Nuake/src/Scripting/NetModules/EngineNetAPI.cpp b/Nuake/src/Scripting/NetModules/EngineNetAPI.cpp index 4b9725aa..34bcb0c8 100644 --- a/Nuake/src/Scripting/NetModules/EngineNetAPI.cpp +++ b/Nuake/src/Scripting/NetModules/EngineNetAPI.cpp @@ -2,9 +2,9 @@ namespace Nuake { - void Log(Coral::NativeString string) + void Log(Coral::String string) { - Logger::Log(string.ToString(), ".net", VERBOSE); + Logger::Log(string, ".net", VERBOSE); } void EngineNetAPI::RegisterMethods() diff --git a/Nuake/src/Scripting/NetModules/InputNetAPI.cpp b/Nuake/src/Scripting/NetModules/InputNetAPI.cpp index 44e0d214..32b41358 100644 --- a/Nuake/src/Scripting/NetModules/InputNetAPI.cpp +++ b/Nuake/src/Scripting/NetModules/InputNetAPI.cpp @@ -2,25 +2,45 @@ #include "src/Core/Input.h" -#include +#include namespace Nuake { + void ShowMouse(bool visible) + { + if (visible) + { + Input::ShowMouse(); + } + else + { + Input::HideMouse(); + } + } + bool IsKeyDown(int keyCode) { return Input::IsKeyDown(keyCode); } - Coral::NativeArray GetMousePosition() + bool IsKeyPressed(int keyCode) + { + return Input::IsKeyPressed(keyCode); + } + + Coral::Array GetMousePosition() { Vector2 mousePosition = Input::GetMousePosition(); - return { mousePosition.x, mousePosition.y}; + return Coral::Array::New({ mousePosition.x, mousePosition.y }); } void InputNetAPI::RegisterMethods() { + RegisterMethod("Input.ShowMouseIcall", &ShowMouse); RegisterMethod("Input.IsKeyDownIcall", &IsKeyDown); + RegisterMethod("Input.IsKeyPressedIcall", &IsKeyPressed); + RegisterMethod("Input.GetMousePositionIcall", &GetMousePosition); } diff --git a/Nuake/src/Scripting/NetModules/NetAPIModule.h b/Nuake/src/Scripting/NetModules/NetAPIModule.h index b388c69b..10af937b 100644 --- a/Nuake/src/Scripting/NetModules/NetAPIModule.h +++ b/Nuake/src/Scripting/NetModules/NetAPIModule.h @@ -2,7 +2,7 @@ #include "src/Core/Core.h" #include "src/Core/Logger.h" -#include +#include namespace Nuake { diff --git a/Nuake/src/Scripting/NetModules/SceneNetAPI.cpp b/Nuake/src/Scripting/NetModules/SceneNetAPI.cpp index 1bbe5e9e..cc19cf58 100644 --- a/Nuake/src/Scripting/NetModules/SceneNetAPI.cpp +++ b/Nuake/src/Scripting/NetModules/SceneNetAPI.cpp @@ -21,23 +21,40 @@ #include "src/Scene/Components/QuakeMap.h" #include "src/Physics/PhysicsManager.h" +#include "src/Scripting/ScriptingEngineNet.h" -#include +#include namespace Nuake { - uint32_t GetEntity(Coral::NativeString entityName) + uint32_t GetEntity(Coral::String entityName) { auto scene = Engine::GetCurrentScene(); - - std::string entityNameString = entityName.ToString(); - if (!scene->EntityExists(entityNameString)) + if (!scene->EntityExists(entityName)) { return UINT32_MAX; // Error code: entity not found. } - return scene->GetEntity(entityNameString).GetHandle(); + return scene->GetEntity(entityName).GetHandle(); + } + + Coral::ManagedObject GetEntityScript(Coral::String entityName) + { + auto scene = Engine::GetCurrentScene(); + if (!scene->EntityExists(entityName)) + { + return Coral::ManagedObject(); // Error code: entity not found. + } + + Entity entity = scene->GetEntity(entityName); + + auto& scriptingEngine = ScriptingEngineNet::Get(); + if (scriptingEngine.HasEntityScriptInstance(entity)) + { + auto instance = scriptingEngine.GetEntityScript(entity); + return instance; + } } static enum ComponentTypes @@ -112,6 +129,24 @@ namespace Nuake { { auto& component = entity.GetComponent(); component.SetLocalPosition({ x, y, z }); + + if (entity.HasComponent()) + { + PhysicsManager::Get().SetCharacterControllerPosition(entity, { x, y, z }); + } + } + } + + Coral::Array TransformGetGlobalPosition(int entityId) + { + Entity entity = { (entt::entity)(entityId), Engine::GetCurrentScene().get() }; + + if (entity.IsValid() && entity.HasComponent()) + { + auto& component = entity.GetComponent(); + const auto& globalPosition = component.GetGlobalPosition(); + Coral::Array result = Coral::Array::New({ globalPosition.x, globalPosition.y, globalPosition.z }); + return result; } } @@ -127,7 +162,7 @@ namespace Nuake { } } - Coral::NativeArray CameraGetDirection(int entityId) + Coral::Array CameraGetDirection(int entityId) { Entity entity = { (entt::entity)(entityId), Engine::GetCurrentScene().get() }; @@ -135,7 +170,7 @@ namespace Nuake { { auto& component = entity.GetComponent(); const Vector3 camDirection = component.CameraInstance->GetDirection(); - return { camDirection.x, camDirection.y, camDirection.z }; + return Coral::Array::New({ camDirection.x, camDirection.y, camDirection.z }); } } @@ -169,19 +204,50 @@ namespace Nuake { return false; } + void Play(int entityId, Coral::String animation) + { + Entity entity = Entity((entt::entity)(entityId), Engine::GetCurrentScene().get()); + + if (entity.IsValid() && entity.HasComponent()) + { + auto& skinnedModel = entity.GetComponent(); + + if (skinnedModel.ModelResource) + { + auto& model = skinnedModel.ModelResource; + + // Find animation from name + int animIndex = 0; + for (const auto& anim : model->GetAnimations()) + { + if (anim->GetName() == animation) + { + model->PlayAnimation(animIndex); + } + + animIndex++; + } + } + } + } + void Nuake::SceneNetAPI::RegisterMethods() { RegisterMethod("Entity.EntityHasComponentIcall", &EntityHasComponent); RegisterMethod("Scene.GetEntityIcall", &GetEntity); + RegisterMethod("Scene.GetEntityScriptIcall", &GetEntityScript); // Components RegisterMethod("TransformComponent.SetPositionIcall", &TransformSetPosition); + RegisterMethod("TransformComponent.GetGlobalPositionIcall", &TransformGetGlobalPosition); RegisterMethod("TransformComponent.RotateIcall", &TransformRotate); RegisterMethod("CameraComponent.GetDirectionIcall", &CameraGetDirection); RegisterMethod("CharacterControllerComponent.MoveAndSlideIcall", &MoveAndSlide); RegisterMethod("CharacterControllerComponent.IsOnGroundIcall", &IsOnGround); + + RegisterMethod("SkinnedModelComponent.PlayIcall", &Play); } } diff --git a/Nuake/src/Scripting/ScriptingEngineNet.cpp b/Nuake/src/Scripting/ScriptingEngineNet.cpp index 747f3724..67eca17a 100644 --- a/Nuake/src/Scripting/ScriptingEngineNet.cpp +++ b/Nuake/src/Scripting/ScriptingEngineNet.cpp @@ -3,6 +3,7 @@ #include "src/Core/Logger.h" #include "src/Core/FileSystem.h" #include "src/Core/OS.h" +#include "src/Threading/JobSystem.h" #include "src/Resource/Project.h" #include "src/Scene/Components/NetScriptComponent.h" @@ -12,7 +13,7 @@ #include #include -#include +#include #include @@ -136,7 +137,7 @@ namespace Nuake } const std::string sanitizedProjectName = String::Sanitize(project->Name); - const std::string assemblyPath = "/bin/Debug/net7.0/" + sanitizedProjectName + ".dll"; + const std::string assemblyPath = "/bin/Debug/net8.0/" + sanitizedProjectName + ".dll"; if (!FileSystem::FileExists(assemblyPath)) { @@ -149,13 +150,15 @@ namespace Nuake for (auto& type : m_GameAssembly.GetTypes()) { - Logger::Log(std::string("Detected type: ") + std::string(type->GetName()), ".net"); - Logger::Log(std::string("Detected base type: ") + std::string(type->GetBaseType().GetName()), ".net"); + Logger::Log(std::string("Detected type: ") + std::string(type->GetFullName()), ".net"); + Logger::Log(std::string("Detected base type: ") + std::string(type->GetBaseType().GetFullName()), ".net"); - const std::string baseTypeName = std::string(type->GetBaseType().GetName()); - if (baseTypeName == "Entity") + const std::string baseTypeName = std::string(type->GetBaseType().GetFullName()); + if (baseTypeName == "Nuake.Net.Entity") { - m_GameEntityTypes[std::string(type->GetName())] = type; // We have found an entity script. + auto typeSplits = String::Split(type->GetFullName(), '.'); + std::string shortenedTypeName = typeSplits[typeSplits.size() - 1]; + m_GameEntityTypes[shortenedTypeName] = type; // We have found an entity script. } } } @@ -222,7 +225,6 @@ namespace Nuake size_t classNameLength = semiColonPos - classNameStartIndex; const std::string className = fileContent.substr(classNameStartIndex, classNameLength); - if(m_GameEntityTypes.find(className) == m_GameEntityTypes.end()) { // The class name parsed in the file was not found in the game's DLL. @@ -246,8 +248,10 @@ namespace Nuake { if (!HasEntityScriptInstance(entity)) { + std::string name = entity.GetComponent().Name; + Logger::Log(name); Logger::Log("Failed to get entity .Net script instance, doesn't exist", ".net", CRITICAL); - throw std::exception("Failed to get entity .Net script instance, doesn't exist"); + return Coral::ManagedObject(); } return m_EntityToManagedObjects[entity.GetID()]; @@ -294,10 +298,10 @@ namespace Nuake const std::string cleanProjectName = String::Sanitize(projectName); const std::string premakeScript = R"( workspace ")" + cleanProjectName + R"(" +configurations { "Debug", "Release" } project ")" + cleanProjectName + R"(" language "C#" - dotnetframework "net7.0" - + dotnetframework "net8.0" kind "SharedLib" clr "Unsafe" diff --git a/Nuake/src/Threading/Job.cpp b/Nuake/src/Threading/Job.cpp new file mode 100644 index 00000000..36b18160 --- /dev/null +++ b/Nuake/src/Threading/Job.cpp @@ -0,0 +1,25 @@ +#include "Job.h" + +namespace Nuake { + + Job::Job(std::function job, std::function end) + : m_Job(job) + , m_End(end) + { + m_End = end; + + m_Thread = std::thread([this, job]() + { + job(); + m_IsDone = true; + }); + } + + void Job::End() + { + if (m_End) + { + m_End(); + } + } +} \ No newline at end of file diff --git a/Nuake/src/Threading/Job.h b/Nuake/src/Threading/Job.h new file mode 100644 index 00000000..c4f3bd0e --- /dev/null +++ b/Nuake/src/Threading/Job.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include + +namespace Nuake { + + class Job + { + public: + Job(std::function job, std::function end); + Job(const Job&) = delete; + Job& operator=(const Job&) = delete; + ~Job() { m_Thread.join(); } + bool IsDone() { return m_IsDone; } + + void End(); + private: + std::thread m_Thread; + std::atomic m_IsDone; + std::function m_Job; + std::function m_End; + }; +} \ No newline at end of file diff --git a/Nuake/src/Threading/JobSystem.h b/Nuake/src/Threading/JobSystem.h new file mode 100644 index 00000000..a1b39a29 --- /dev/null +++ b/Nuake/src/Threading/JobSystem.h @@ -0,0 +1,43 @@ +#pragma once +#include "Job.h" + +namespace Nuake { + + class JobSystem + { + private: + std::vector> m_Jobs; + + public: + + JobSystem() = default; + ~JobSystem() = default; + + static JobSystem& Get() + { + static JobSystem instance; + return instance; + } + + void Dispatch(std::function job, std::function end) + { + m_Jobs.push_back(std::make_unique(job, end)); + } + + void Update() + { + for (auto it = m_Jobs.begin(); it != m_Jobs.end();) + { + if (it->get()->IsDone()) + { + it->get()->End(); + it = m_Jobs.erase(it); + } + else + { + ++it; + } + } + } + }; +} \ No newline at end of file diff --git a/NuakeNet/premake5.lua b/NuakeNet/premake5.lua index 567d0b61..cef4d968 100644 --- a/NuakeNet/premake5.lua +++ b/NuakeNet/premake5.lua @@ -1,6 +1,6 @@ project "NuakeNet" language "C#" - dotnetframework "net7.0" + dotnetframework "net8.0" kind "SharedLib" clr "Unsafe" diff --git a/NuakeNet/src/Components.cs b/NuakeNet/src/Components.cs index 73f82568..5bb6be0b 100644 --- a/NuakeNet/src/Components.cs +++ b/NuakeNet/src/Components.cs @@ -22,12 +22,24 @@ namespace Nuake.Net } public class NameComponent : IComponent { + internal static unsafe delegate* GetNameIcall; + public NameComponent(int entityId) { EntityID = entityId; } - public string Name { get; set; } + public string Name + { + get + { + unsafe { return GetNameIcall(EntityID).ToString(); } + } + set + { + + } + } } public class PrefabComponent : IComponent @@ -39,6 +51,7 @@ namespace Nuake.Net public class TransformComponent : IComponent { + internal static unsafe delegate*> GetGlobalPositionIcall; internal static unsafe delegate* SetPositionIcall; internal static unsafe delegate* RotateIcall; @@ -76,7 +89,18 @@ namespace Nuake.Net unsafe { SetPositionIcall(EntityID, value.X, value.Y, value.Z); } } } - public Vector3 GlobalPosition { get; set; } + public Vector3 GlobalPosition + { + get + { + unsafe + { + NativeArray result = GetGlobalPositionIcall(EntityID); + return new Vector3(result[0], result[1], result[2]); + } + } + set { } + } } public class LightComponent : IComponent @@ -152,10 +176,20 @@ namespace Nuake.Net public class SkinnedModelComponent : IComponent { - public SkinnedModelComponent(int entityId) { } + internal static unsafe delegate* PlayIcall; + + public SkinnedModelComponent(int entityId) + { + EntityID = entityId; + } public bool Playing { get; set; } public int CurrentAnimation { get; set; } + + public void Play(String name) + { + unsafe { PlayIcall(EntityID, name); } + } } public class BoneComponent : IComponent diff --git a/NuakeNet/src/Entity.cs b/NuakeNet/src/Entity.cs index e5b2747f..4118778e 100644 --- a/NuakeNet/src/Entity.cs +++ b/NuakeNet/src/Entity.cs @@ -1,11 +1,20 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Numerics; using System.Text; using System.Threading.Tasks; namespace Nuake.Net { + public struct CollisionData + { + Entity Entity1; + Entity Entity2; + Vector3 Normal; + Vector3 Position; + } + public class Entity { internal static unsafe delegate* EntityHasComponentIcall; @@ -43,6 +52,16 @@ namespace Nuake.Net public virtual void OnFixedUpdate(float dt) { } public virtual void OnDestroy() { } + public virtual void OnCollision(Entity entity1, Entity entity2) + { + } + + // Physics + public void OnCollisionInternal(int entity1, int entity2) + { + OnCollision(new Entity { ECSHandle = entity1 }, new Entity { ECSHandle = entity2 }); + } + protected static Dictionary MappingTypeEnum = new Dictionary() { { typeof(ParentComponent), ComponentTypes.PARENT }, diff --git a/NuakeNet/src/Input.cs b/NuakeNet/src/Input.cs index 4b672af1..23183e59 100644 --- a/NuakeNet/src/Input.cs +++ b/NuakeNet/src/Input.cs @@ -134,14 +134,26 @@ namespace Nuake.Net public class Input { + internal static unsafe delegate* ShowMouseIcall; internal static unsafe delegate* IsKeyDownIcall; + internal static unsafe delegate* IsKeyPressedIcall; internal static unsafe delegate*> GetMousePositionIcall; + public static void ShowMouse(bool visible) + { + unsafe { ShowMouseIcall(visible); } + } + public static bool IsKeyDown(Key keys) { unsafe { return IsKeyDownIcall((int)keys); } } + public static bool IsKeyPressed(Key key) + { + unsafe { return IsKeyPressedIcall((int)key); } + } + public static Vector2 GetMousePosition() { NativeArray result; diff --git a/NuakeNet/src/Scene.cs b/NuakeNet/src/Scene.cs index 1010f094..b8306b32 100644 --- a/NuakeNet/src/Scene.cs +++ b/NuakeNet/src/Scene.cs @@ -6,6 +6,21 @@ namespace Nuake.Net public class Scene { internal static unsafe delegate* GetEntityIcall; + internal static unsafe delegate*> GetEntityScriptIcall; + + public static T? GetEntity(string entityName) where T : class + { + NativeInstance handle; + unsafe { handle = GetEntityScriptIcall(entityName); } + + Entity? entity = handle.Get(); + if (entity != null && entity is T) + { + return entity as T; + } + + return null; + } public static Entity GetEntity(string entityName) { @@ -21,6 +36,7 @@ namespace Nuake.Net { ECSHandle = handle }; + return entity; } } diff --git a/Resources/Images/project_icon.png b/Resources/Images/project_icon.png new file mode 100644 index 00000000..384eabf2 Binary files /dev/null and b/Resources/Images/project_icon.png differ diff --git a/Resources/Shaders/gizmo.shader b/Resources/Shaders/gizmo.shader index d7239976..bd418f96 100644 --- a/Resources/Shaders/gizmo.shader +++ b/Resources/Shaders/gizmo.shader @@ -42,7 +42,10 @@ void main() vec4 px_color = texture(gizmo_texture, a_UV).rgba; color = px_color * vec4(1, 1, 1, u_Opacity); - gEntityID = u_EntityID; + if(u_Opacity >= 0.5f) + { + gEntityID = u_EntityID; + } FragColor = color; } \ No newline at end of file diff --git a/Resources/Shaders/outline.shader b/Resources/Shaders/outline.shader index 8cc25404..0219f089 100644 --- a/Resources/Shaders/outline.shader +++ b/Resources/Shaders/outline.shader @@ -32,9 +32,13 @@ void main() float radius = 4.f; vec2 uv = a_UV; + // sample middle + uint middleSample = texture(u_EntityTexture, uv).r; + // Correct aspect ratio vec2 aspect = 1.0 / vec2(textureSize(u_EntityTexture, 0)); + float hasHit = 0.0f; vec4 fragColor = vec4(0.0, 0.0, 0.0, 0.0f); for (float i = 0.0; i < TAU; i += TAU / steps) { @@ -42,8 +46,13 @@ void main() vec2 offset = vec2(sin(i), cos(i)) * aspect * radius; uint col = texture(u_EntityTexture, uv + offset).r; + if(col == target) + { + hasHit = 1.0f; + } + // Mix outline with background - float alpha = smoothstep(0.5, 0.7, int(col != target) * 10.0f); + float alpha = smoothstep(0.5, 0.9, int(col != target) * hasHit * 10.0f); fragColor = mix(fragColor, u_OutlineColor, alpha); } @@ -52,5 +61,5 @@ void main() fragColor.a = 1.0f; } - FragColor = mix(vec4(0), fragColor, texture(u_EntityTexture, uv).r == target); + FragColor = mix(vec4(0), fragColor, middleSample != target && hasHit > 0.0f); } diff --git a/premake5.lua b/premake5.lua index 6994ebce..d8807e7e 100644 --- a/premake5.lua +++ b/premake5.lua @@ -1,5 +1,6 @@ workspace "Nuake" - conformancemode "On" + architecture "x64" + configurations { "Debug", @@ -19,12 +20,6 @@ workspace "Nuake" "NK_DEBUG" } - filter { "language:C++" } - architecture "x64" - - filter { "language:C" } - architecture "x64" - outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}" include "Nuake/dependencies/glfw_p5.lua" @@ -34,9 +29,6 @@ include "Nuake/dependencies/freetype_p5.lua" include "Nuake/dependencies/jolt_p5.lua" include "Nuake/dependencies/soloud_p5.lua" include "Nuake/dependencies/optick_p5.lua" -include "Nuake/dependencies/coral_p5.lua" - -include "NuakeNet/premake5.lua" project "Nuake" location "Nuake" @@ -88,8 +80,7 @@ project "Nuake" "%{prj.name}/src/Vendors/wren/src/include", "%{prj.name}/src/Vendors/incbin", "%{prj.name}/dependencies/build", - "%{prj.name}/dependencies/soloud/include", - "%{prj.name}/dependencies/Coral/Coral.Native/Include" + "%{prj.name}/dependencies/soloud/include" } links @@ -99,16 +90,15 @@ project "Nuake" } filter "system:linux" - defines - { + defines { "GLFW_STATIC", "NK_LINUX" } links - { - "glib-2.0" - } + { + "glib-2.0" + } buildoptions { "`pkg-config --cflags glib-2.0 pango gdk-pixbuf-2.0 atk`" } linkoptions { "`pkg-config --libs glib-2.0 pango gdk-pixbuf-2.0`" } @@ -117,7 +107,7 @@ project "Nuake" { "/usr/include/gtk-3.0/", "/usr/lib/glib-2.0/include", - "/usr/include/glib-2.0", + "/usr/include/glib-2.0", } filter "system:windows" @@ -127,7 +117,7 @@ project "Nuake" "NK_WIN" } - + buildoptions { "-permissive", "-cxxflags", "gtk+-3.0"} filter "configurations:Debug" runtime "Debug" symbols "on" @@ -179,8 +169,7 @@ project "NuakeRuntime" "%{prj.name}/../Nuake/src/Vendors/msdfgen", "%{prj.name}/../Nuake/src/Vendors/wren/src/include", "%{prj.name}/../Nuake/dependencies/JoltPhysics/bin/%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}/JoltPhysics/", - "%{prj.name}/../Nuake/dependencies/soloud/bin/%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}", - "%{prj.name}/../Nuake/dependencies/Coral/NetCore/7.0.7/" + "%{prj.name}/../Nuake/dependencies/soloud/bin/%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}" } links @@ -191,10 +180,7 @@ project "NuakeRuntime" "assimp", "Freetype", "JoltPhysics", - "soloud", - "Coral.Native", - "nethost", - "libnethost" + "soloud" } filter "system:windows" @@ -208,16 +194,6 @@ project "NuakeRuntime" "opengl32.lib" } - externalincludedirs { "%{prj.name}/../Nuake/dependencies/Coral/Coral.Native/Include/" } - - postbuildcommands { - '{ECHO} Copying "%{wks.location}/NetCore/7.0.7/nethost.dll" to "%{cfg.targetdir}"', - '{COPYFILE} "%{wks.location}/Nuake/dependencies/Coral/NetCore/7.0.7/nethost.dll" "%{cfg.targetdir}"', - '{COPYFILE} "%{wks.location}/Nuake/dependencies/Coral/Coral.Managed/Coral.Managed.runtimeconfig.json" "%{wks.location}/%{prj.name}"', - '{COPYFILE} "%{wks.location}/Nuake/dependencies/Coral/Coral.Managed/Build/%{cfg.buildcfg}-%{cfg.system}/Coral.Managed.dll" "%{wks.location}/%{prj.name}"', - '{COPYFILE} "%{wks.location}/NuakeNet/bin/%{cfg.buildcfg}/NuakeNet.dll" "%{wks.location}/%{prj.name}"' - } - filter "system:linux" links { @@ -236,7 +212,7 @@ project "NuakeRuntime" { "/usr/include/gtk-3.0/", "/usr/lib/glib-2.0/include", - "/usr/include/glib-2.0", + "/usr/include/glib-2.0", } buildoptions { "`pkg-config --cflags glib-2.0 pango gdk-pixbuf-2.0 gtk-3 atk tk-3.0 glib-2.0`" } @@ -303,7 +279,7 @@ project "Editor" "%{prj.name}/../Nuake/dependencies/JoltPhysics", "%{prj.name}/../Nuake/dependencies/build", "%{prj.name}/../Nuake/dependencies/soloud/include", - "/usr/include/gtk-3.0/", + "/usr/include/gtk-3.0/" } libdirs @@ -317,8 +293,7 @@ project "Editor" "%{prj.name}/../Nuake/src/Vendors/msdfgen", "%{prj.name}/../Nuake/src/Vendors/wren/src/include", "%{prj.name}/../Nuake/dependencies/JoltPhysics/bin/%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}/JoltPhysics/", - "%{prj.name}/../Nuake/dependencies/soloud/bin/%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}", - "%{prj.name}/../Nuake/dependencies/Coral/NetCore/7.0.7/" + "%{prj.name}/../Nuake/dependencies/soloud/bin/%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}" } links @@ -327,12 +302,9 @@ project "Editor" "glad", "GLFW", "assimp", - "Freetype", - "JoltPhysics", - "soloud", - "Coral.Native", - "nethost", - "libnethost" + "Freetype", + "JoltPhysics", + "soloud" } filter "system:Windows" @@ -349,16 +321,6 @@ project "Editor" { "NK_WIN" } - - externalincludedirs { "%{prj.name}/../Nuake/dependencies/Coral/Coral.Native/Include/" } - - postbuildcommands { - '{ECHO} Copying "%{wks.location}/NetCore/7.0.7/nethost.dll" to "%{cfg.targetdir}"', - '{COPYFILE} "%{wks.location}/Nuake/dependencies/Coral/NetCore/7.0.7/nethost.dll" "%{cfg.targetdir}"', - '{COPYFILE} "%{wks.location}/Nuake/dependencies/Coral/Coral.Managed/Coral.Managed.runtimeconfig.json" "%{wks.location}/%{prj.name}"', - '{COPYFILE} "%{wks.location}/Nuake/dependencies/Coral/Coral.Managed/Build/%{cfg.buildcfg}-%{cfg.system}/Coral.Managed.dll" "%{wks.location}/%{prj.name}"', - '{COPYFILE} "%{wks.location}/NuakeNet/bin/%{cfg.buildcfg}/NuakeNet.dll" "%{wks.location}/%{prj.name}"' - } filter "system:linux" @@ -371,8 +333,8 @@ project "Editor" "asound", "glib-2.0", "gtk-3", - "gobject-2.0", - "asound" + "gobject-2.0", + "asound" } buildoptions { "`pkg-config --cflags glib-2.0 pango gdk-pixbuf-2.0 gtk-3 atk tk-3.0 glib-2.0`" } @@ -383,8 +345,10 @@ project "Editor" { "/usr/include/gtk-3.0/", "/usr/lib/glib-2.0/include", - "/usr/include/glib-2.0", + "/usr/include/glib-2.0", } + + defines { @@ -420,5 +384,4 @@ project "Editor" -- copy a file from the objects directory to the target directory postbuildcommands { --"{COPY} "Nuake/dependencies/GLFW/lib-vc2019/glfw3.dll" " .. "./bin/" .. outputdir .. "/%{prj.name}/glfw3.dll" - } - + } \ No newline at end of file