diff --git a/src/features/editScene/EditorApp.cpp b/src/features/editScene/EditorApp.cpp index bc0c726..5bcecff 100644 --- a/src/features/editScene/EditorApp.cpp +++ b/src/features/editScene/EditorApp.cpp @@ -27,6 +27,7 @@ #include "components/RigidBody.hpp" #include "components/GeneratedPhysicsTag.hpp" #include "components/BuoyancyInfo.hpp" +#include "components/InWater.hpp" #include "components/WaterPhysics.hpp" #include "components/WaterPlane.hpp" #include "components/Light.hpp" @@ -493,6 +494,7 @@ void EditorApp::setupECS() // Register game components m_world.component(); m_world.component(); + m_world.component(); // Register CellGrid/Town components CellGridModule::registerComponents(m_world); diff --git a/src/features/editScene/components/InWater.hpp b/src/features/editScene/components/InWater.hpp new file mode 100644 index 0000000..2ecfa17 --- /dev/null +++ b/src/features/editScene/components/InWater.hpp @@ -0,0 +1,12 @@ +#ifndef EDITSCENE_INWATER_HPP +#define EDITSCENE_INWATER_HPP +#pragma once + +/** + * Tag component indicating the entity is currently in water. + * Automatically added/removed by BuoyancySystem. + */ +struct InWater { +}; + +#endif // EDITSCENE_INWATER_HPP diff --git a/src/features/editScene/components/PlayerController.hpp b/src/features/editScene/components/PlayerController.hpp index 2e81eee..1a595c0 100644 --- a/src/features/editScene/components/PlayerController.hpp +++ b/src/features/editScene/components/PlayerController.hpp @@ -21,6 +21,11 @@ struct PlayerControllerComponent { Ogre::String idleState = "idle"; Ogre::String walkState = "walking"; Ogre::String runState = "running"; + + /* Swim animation states (used when character is in water) */ + Ogre::String swimIdleState = "swim-idle"; + Ogre::String swimState = "swim"; + Ogre::String swimFastState = "swim-fast"; }; #endif // EDITSCENE_PLAYERCONTROLLER_HPP diff --git a/src/features/editScene/systems/BuoyancySystem.cpp b/src/features/editScene/systems/BuoyancySystem.cpp index 8a789a5..6a34911 100644 --- a/src/features/editScene/systems/BuoyancySystem.cpp +++ b/src/features/editScene/systems/BuoyancySystem.cpp @@ -52,6 +52,15 @@ void BuoyancySystem::update(float deltaTime) // Clear previous frame's water bodies m_bodiesInWater.clear(); + // Remove InWater tag from entities that were in water last frame + for (flecs::entity_t id : m_entitiesInWater) { + flecs::entity e = m_world.entity(id); + if (e.is_alive() && e.has()) { + e.remove(); + } + } + m_entitiesInWater.clear(); + // Perform broadphase query to find bodies in water // Use water surface position from WaterPhysics component, camera XZ position Ogre::Vector3 waterSurfacePos(m_cameraPosition.x, @@ -101,6 +110,12 @@ void BuoyancySystem::update(float deltaTime) continue; } + // Mark entity as in water + if (!entity.has()) { + entity.add(); + } + m_entitiesInWater.insert(entity.id()); + // Debug logging for buoyancy application if (m_debugEnabled) { Ogre::Vector3 bodyPos = m_physics->getPosition(bodyID); diff --git a/src/features/editScene/systems/BuoyancySystem.hpp b/src/features/editScene/systems/BuoyancySystem.hpp index 9804dd5..b56bdc7 100644 --- a/src/features/editScene/systems/BuoyancySystem.hpp +++ b/src/features/editScene/systems/BuoyancySystem.hpp @@ -8,6 +8,7 @@ #include #include "../physics/physics.h" #include "../components/BuoyancyInfo.hpp" +#include "../components/InWater.hpp" #include "../components/WaterPhysics.hpp" #include "../components/Transform.hpp" @@ -91,6 +92,9 @@ private: // Cache for scene node -> entity mapping std::unordered_map m_nodeToEntity; + // Entities that were in water last frame (for InWater tag management) + std::set m_entitiesInWater; + // Query for entities with BuoyancyInfo component flecs::query m_buoyancyInfoQuery; }; diff --git a/src/features/editScene/systems/PlayerControllerSystem.cpp b/src/features/editScene/systems/PlayerControllerSystem.cpp index 74b2af4..aef7dfa 100644 --- a/src/features/editScene/systems/PlayerControllerSystem.cpp +++ b/src/features/editScene/systems/PlayerControllerSystem.cpp @@ -1,6 +1,7 @@ #include "PlayerControllerSystem.hpp" #include "../EditorApp.hpp" #include "../components/PlayerController.hpp" +#include "../components/InWater.hpp" #include "../components/Character.hpp" #include "../components/Transform.hpp" #include "../components/EntityName.hpp" @@ -362,13 +363,24 @@ void PlayerControllerSystem::updateLocomotion(PlayerControllerComponent &pc, if (!ats) return; + bool inWater = state.targetEntity.has(); Ogre::String animState; - if (!isMoving) { - animState = pc.idleState; - } else if (input.shift) { - animState = pc.runState; + if (inWater) { + if (!isMoving) { + animState = pc.swimIdleState; + } else if (input.shift) { + animState = pc.swimFastState; + } else { + animState = pc.swimState; + } } else { - animState = pc.walkState; + if (!isMoving) { + animState = pc.idleState; + } else if (input.shift) { + animState = pc.runState; + } else { + animState = pc.walkState; + } } if (!animState.empty()) { diff --git a/src/features/editScene/systems/SceneSerializer.cpp b/src/features/editScene/systems/SceneSerializer.cpp index 0373fd6..31506ff 100644 --- a/src/features/editScene/systems/SceneSerializer.cpp +++ b/src/features/editScene/systems/SceneSerializer.cpp @@ -2189,6 +2189,9 @@ nlohmann::json SceneSerializer::serializePlayerController(flecs::entity entity) json["idleState"] = pc.idleState; json["walkState"] = pc.walkState; json["runState"] = pc.runState; + json["swimIdleState"] = pc.swimIdleState; + json["swimState"] = pc.swimState; + json["swimFastState"] = pc.swimFastState; return json; } @@ -2222,6 +2225,9 @@ void SceneSerializer::deserializePlayerController(flecs::entity entity, pc.idleState = json.value("idleState", pc.idleState); pc.walkState = json.value("walkState", pc.walkState); pc.runState = json.value("runState", pc.runState); + pc.swimIdleState = json.value("swimIdleState", pc.swimIdleState); + pc.swimState = json.value("swimState", pc.swimState); + pc.swimFastState = json.value("swimFastState", pc.swimFastState); entity.set(pc); } diff --git a/src/features/editScene/ui/PlayerControllerEditor.cpp b/src/features/editScene/ui/PlayerControllerEditor.cpp index e150a9a..c0f6136 100644 --- a/src/features/editScene/ui/PlayerControllerEditor.cpp +++ b/src/features/editScene/ui/PlayerControllerEditor.cpp @@ -78,6 +78,35 @@ bool PlayerControllerEditor::renderComponent(flecs::entity entity, modified = true; } + ImGui::Separator(); + ImGui::Text("Swim States (used when in water)"); + + char swimIdleBuf[256]; + snprintf(swimIdleBuf, sizeof(swimIdleBuf), "%s", + pc.swimIdleState.c_str()); + if (ImGui::InputText("Swim Idle State", swimIdleBuf, + sizeof(swimIdleBuf))) { + pc.swimIdleState = swimIdleBuf; + modified = true; + } + + char swimBuf[256]; + snprintf(swimBuf, sizeof(swimBuf), "%s", + pc.swimState.c_str()); + if (ImGui::InputText("Swim State", swimBuf, sizeof(swimBuf))) { + pc.swimState = swimBuf; + modified = true; + } + + char swimFastBuf[256]; + snprintf(swimFastBuf, sizeof(swimFastBuf), "%s", + pc.swimFastState.c_str()); + if (ImGui::InputText("Swim Fast State", swimFastBuf, + sizeof(swimFastBuf))) { + pc.swimFastState = swimFastBuf; + modified = true; + } + ImGui::Unindent(); }