diff --git a/assets/blender/edited-normal-female.blend b/assets/blender/edited-normal-female.blend index 93b739e..c0af344 100644 --- a/assets/blender/edited-normal-female.blend +++ b/assets/blender/edited-normal-female.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3ffa6224a7bb323fe36038de5c4539c5a305c5b1bc0a9cf4d605a3504f0fcc3 -size 16289842 +oid sha256:3373f5d81a125eea24d73e487be0bc335bf28de5019e69a1fe72e591fea15643 +size 16554740 diff --git a/assets/blender/edited-normal-male.blend b/assets/blender/edited-normal-male.blend index e4fb9c7..af19d31 100644 --- a/assets/blender/edited-normal-male.blend +++ b/assets/blender/edited-normal-male.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49e1ea4ee70f3e37347c4301cb9aaf794597192555b5d5feb835bf8d3504b70f -size 12063340 +oid sha256:2d702f3ebec3df919d00e43ab365a64cb77b559b34a489e6a4bd8dba5d9e464e +size 12542174 diff --git a/assets/blender/vehicles/raft.blend b/assets/blender/vehicles/raft.blend index c84bf03..b924aa4 100644 --- a/assets/blender/vehicles/raft.blend +++ b/assets/blender/vehicles/raft.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:10d57e0918b872573d77821178f305da327904cec61fe6a49c61ddd1e9afd7b4 -size 395684 +oid sha256:302a581e88d6f54848185fe523ba158e8fa506dbd569d0b70c04eab995fe7f9c +size 395032 diff --git a/lua-scripts/data.lua b/lua-scripts/data.lua index 9b9247f..52d208b 100644 --- a/lua-scripts/data.lua +++ b/lua-scripts/data.lua @@ -132,7 +132,7 @@ function Quest(name, book) this.story:begin() this:_narration() end, - event = function(this, event) + event = function(this, event, event_data) if not this.active then return end @@ -250,11 +250,14 @@ function StartGameQuest() end quests = {} -- ecs_set_debug_drawing(true) -setup_handler(function(event, entity) +setup_handler(function(event, trigger_entity, what_entity) print(event) for k, v in pairs(quests) do if v.active then - v:event(event) + local event_data = {} + event_data.trigger_entity = trigger_entity + event_data.object_entity = what_entity + v:event(event, event_data) end end if event == "startup" then @@ -263,7 +266,6 @@ setup_handler(function(event, entity) print("narration progress!") elseif event == "narration_answered" then local answer = narration_get_answer() --- story:choose(answer) print("answered:", answer) elseif event == "new_game" then ecs_character_params_set("player", "gravity", true) @@ -274,5 +276,19 @@ setup_handler(function(event, entity) print(k, v.active) end quest:activate() + elseif event == "actuator_enter" then + ecs_character_physics_control(what_entity, false) + ecs_character_set_actuator(what_entity, "swimming-hold-edge") + ecs_trigger_set_position(trigger_entity, what_entity) + local ent = ecs_get_entity(what_entity) + if (ent.is_character()) then + print("character") + end + if (ent.is_player()) then + print("player") + end +-- crash() + elseif event == "actuator_exit" then + crash() end end) diff --git a/src/gamedata/BoatModule.cpp b/src/gamedata/BoatModule.cpp index 8a1edb1..bd54d2b 100644 --- a/src/gamedata/BoatModule.cpp +++ b/src/gamedata/BoatModule.cpp @@ -15,12 +15,12 @@ BoatModule::BoatModule(flecs::world &ecs) ecs.module(); ecs.component(); ecs.component(); - ecs.system("CreateBoat") + ecs.system("CreateBoat") .kind(flecs::OnUpdate) .without() .without() - .each([](flecs::entity e, const EngineData &eng, - BoatType &type) { + .each([](flecs::entity e, const EngineData &eng, BoatType &type, + Body2Entity &b2e) { BoatBase &boat = e.ensure(); if (type.resourceName.find(".glb") != std::string::npos) { @@ -40,6 +40,7 @@ BoatModule::BoatModule(flecs::world &ecs) 0, boat.mEnt, Ogre::Bullet::CT_TRIMESH, nullptr, 2, 0x7fffffff); + b2e.entities[body.body] = e; } else if (type.resourceName.find(".scene") != std::string::npos) { boat.mNode = @@ -90,13 +91,7 @@ BoatModule::BoatModule(flecs::world &ecs) 0, boat.mEnt, Ogre::Bullet::CT_TRIMESH, nullptr, 2, 0x7fffffff); -#if 0 - boat.mEnt = eng.mScnMgr->getEntity("boat"); - boat.mNode = boat.mEnt->get - /* no need to attach anything */ - BoatBody &body = - e.ensure(); -#endif + b2e.entities[body.body] = e; std::vector slots = boat.mNode->getChildren(); for (i = 0; i < slots.size(); i++) { @@ -114,8 +109,8 @@ BoatModule::BoatModule(flecs::world &ecs) << std::endl; } if (slots.size() > 0) { - VehicleSlots &vs = - e.ensure(); + ObjectSlots &vs = + e.ensure(); for (i = 0; i < slots.size(); i++) { Ogre::Any any = static_cast( any); - vs.seats[obj_name] = { + vs.slots[obj_name] = { obj_type, static_cast( diff --git a/src/gamedata/CharacterAnimationModule.cpp b/src/gamedata/CharacterAnimationModule.cpp index 9e06095..0b04bc1 100644 --- a/src/gamedata/CharacterAnimationModule.cpp +++ b/src/gamedata/CharacterAnimationModule.cpp @@ -16,10 +16,12 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs) int i, j; ch.mSkeleton->setBlendMode( Ogre::ANIMBLEND_CUMULATIVE); - Ogre::String animNames[] = { "idle", "walking", - "running", - "treading_water", - "swimming" }; + Ogre::String animNames[] = { + "idle", "walking", + "running", "treading_water", + "swimming", "hanging-idle", + "hanging-climb", "swimming-hold-edge" + }; int state_count = sizeof(animNames) / sizeof(animNames[0]); anim.mAnimationSystem = @@ -68,6 +70,19 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs) ->end() ->end() ->end() + ->state("actuator") + ->state_machine(ANIM_FADE_SPEED, "actuator-state") + ->state("hanging-idle") + ->animation("hanging-idle") + ->end() + ->state("swimming-hold-edge") + ->animation("swimming-hold-edge") + ->end() + ->state("hanging-climb") + ->animation("hanging-climb") + ->end() + ->end() + ->end() ->end(); /* clang-format on */ @@ -107,10 +122,13 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs) Ogre::Vector3 pos = ch.mBodyNode->getPosition(); Ogre::Vector3 boneMotion = ch.mBoneMotion; v.velocity = rot * boneMotion / eng.delta; - if (eng.startupDelay <= 0.0f) - v.velocity += v.gvelocity; - v.velocity.y = Ogre::Math::Clamp(v.velocity.y, -10.5f, - 1000000.0f); + if (!e.has() && + !e.has()) { + if (eng.startupDelay <= 0.0f) + v.velocity += v.gvelocity; + v.velocity.y = Ogre::Math::Clamp( + v.velocity.y, -10.5f, 1000000.0f); + } }); ecs.system("HandleSwimming") @@ -119,6 +137,8 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs) .with() .with() .with() + .without() + .without() .each([this](flecs::entity e, const EngineData &eng, const AnimationControl &anim, const CharacterBase &ch, CharacterVelocity &gr) { @@ -204,11 +224,51 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs) next_state = "idle"; state_machine->setAnimation(next_state); }); + ecs.system("HandlePlayerAnimationsActuator") + .kind(flecs::OnUpdate) + .with() + .each([](flecs::entity e, const CharacterBase &ch, + const CharacterInActuator &inact, + AnimationControl &anim) { + if (!anim.configured) + return; + AnimationNodeStateMachine *main_sm = + anim.mAnimationSystem + ->get( + "main"); + AnimationNodeStateMachine *actuator_sm = + anim.mAnimationSystem + ->get( + "actuator-state"); + Ogre::String current_state = main_sm->getCurrentState(); + if (current_state != "actuator") + main_sm->setAnimation("actuator"); + actuator_sm->setAnimation(inact.animationState); + }); + ecs.system( + "HandlePlayerAnimationsNoActuator") + .kind(flecs::OnUpdate) + .with() + .without() + .each([](flecs::entity e, const CharacterBase &ch, + AnimationControl &anim) { + if (!anim.configured) + return; + AnimationNodeStateMachine *main_sm = + anim.mAnimationSystem + ->get( + "main"); + Ogre::String current_state = main_sm->getCurrentState(); + if (current_state != "locomotion") + main_sm->setAnimation("locomotion"); + }); ecs.system( "HandlePlayerAnimations") .kind(flecs::OnUpdate) .with() .with() + .without() .each([](flecs::entity e, const Input &input, const CharacterBase &ch, AnimationControl &anim) { if (!anim.configured) diff --git a/src/gamedata/CharacterAnimationModule.h b/src/gamedata/CharacterAnimationModule.h index 4d61e92..868d19f 100644 --- a/src/gamedata/CharacterAnimationModule.h +++ b/src/gamedata/CharacterAnimationModule.h @@ -2,8 +2,64 @@ #define CHARACTER_ANIMATION_MODULE_H_ #include #include +#include "GameData.h" +#include "LuaData.h" namespace ECS { +struct AnimationTrigger; +struct AnimationTriggerSubscriber { + virtual void operator()(const AnimationTrigger *trigger) = 0; +}; +struct AnimationTrigger { + Ogre::String name; + float time; + float weight; + std::vector subscriber_list; + float getTriggerTime() const + { + return time; + } + float getMinWeight() const + { + return weight; + } + const Ogre::String &getName() const + { + return name; + } + void notify(float weight) + { + int i; + if (weight < this->weight) + return; + for (i = 0; i < subscriber_list.size(); i++) + (*subscriber_list[i])(this); + } + void addSubscriber(AnimationTriggerSubscriber *sub) + { + if (std::find(subscriber_list.begin(), subscriber_list.end(), + sub) != subscriber_list.end()) + return; + subscriber_list.push_back(sub); + } + void removeSubscriber(AnimationTriggerSubscriber *sub) + { + auto it = std::find(subscriber_list.begin(), + subscriber_list.end(), sub); + if (it != subscriber_list.end()) + subscriber_list.erase(it); + } + void clearSubscribers() + { + subscriber_list.clear(); + } + AnimationTrigger(const Ogre::String name, float time, float weight) + : name(name) + , time(time) + , weight(weight) + { + } +}; struct Animation { Ogre::AnimationState *mAnimationState; Ogre::Animation *mSkelAnimation; @@ -11,6 +67,7 @@ struct Animation { Ogre::NodeAnimationTrack *mRootTrack; float m_weight; float m_accWeight; + std::multimap trigger_list; Animation(Ogre::AnimationState *animState, Ogre::Animation *skelAnimation) : mAnimationState(animState) @@ -30,19 +87,25 @@ struct Animation { // mRootTracks[i]->removeAllKeyFrames(); } } +#if 0 OgreAssert(mHipsTrack, "no hips track"); OgreAssert(mRootTrack, "no Root track"); - Ogre::Vector3 delta = Ogre::Vector3::ZERO; - Ogre::Vector3 motion = Ogre::Vector3::ZERO; - for (j = 0; j < mRootTrack->getNumKeyFrames(); j++) { - Ogre::Vector3 trans = - mRootTrack->getNodeKeyFrame(j)->getTranslate(); - if (j == 0) - delta = trans; - else - delta = trans - motion; - mRootTrack->getNodeKeyFrame(j)->setTranslate(delta); - motion = trans; +#endif + if (mRootTrack) { + Ogre::Vector3 delta = Ogre::Vector3::ZERO; + Ogre::Vector3 motion = Ogre::Vector3::ZERO; + for (j = 0; j < mRootTrack->getNumKeyFrames(); j++) { + Ogre::Vector3 trans = + mRootTrack->getNodeKeyFrame(j) + ->getTranslate(); + if (j == 0) + delta = trans; + else + delta = trans - motion; + mRootTrack->getNodeKeyFrame(j)->setTranslate( + delta); + motion = trans; + } } } Ogre::String getName() @@ -78,7 +141,9 @@ struct Animation { } void addTime(float time) { + preUpdateTriggers(); mAnimationState->addTime(time); + postUpdateTriggers(time); } void reset() { @@ -96,6 +161,67 @@ struct Animation { { return m_accWeight; } + void addTrigger(AnimationTrigger *trigger) + { + trigger_list.insert(std::pair( + trigger->getTriggerTime(), trigger)); + } + void clearTriggers() + { + auto it = trigger_list.begin(); + while (it != trigger_list.end()) { + delete it->second; + it++; + } + trigger_list.clear(); + } + float mpreUpdateTime; + void preUpdateTriggers() + { + mpreUpdateTime = mAnimationState->getTimePosition() / + mAnimationState->getLength(); + } + void postUpdateTriggers(float delta) + { + float postUpdateTime = mAnimationState->getTimePosition() / + mAnimationState->getLength(); + bool positive = delta >= 0.0f; + if (positive) + updateTriggers(mpreUpdateTime, postUpdateTime); + else + updateTriggers(postUpdateTime, mpreUpdateTime); + } + void updateTriggers(float currentTime, float nextTime) + { + int i; + float weight = getWeight(); + if (currentTime <= nextTime) { + auto it = trigger_list.lower_bound(currentTime); + while (it != trigger_list.end()) { + if (nextTime <= + it->second->getTriggerTime()) // in future, sorrted by time + return; + it->second->notify(weight); + } + } else { + updateTriggers(currentTime, 1); + updateTriggers(0, nextTime); + } + } + float getLength() const + { + if (getEnabled()) + return mAnimationState->getLength(); + else + return 0.0f; + } + float getTimePosition() const + { + if (getEnabled()) + return mAnimationState->getTimePosition(); + else + return 0.0f; + } }; struct AnimationNode { @@ -109,6 +235,8 @@ struct AnimationNode { virtual void addTime(float time) = 0; virtual void setWeight(float weight) = 0; virtual void reset() = 0; + virtual float getLength() const = 0; + virtual float getTimePosition() const = 0; float getWeight() { return m_weight; @@ -121,6 +249,13 @@ struct AnimationNode { { m_name = name; } + virtual float getTime() const + { + float l = getLength(); + if (l > 0.0f) + return getTimePosition() / l; + return 0.0f; + } }; struct AnimationNodeAnimation : AnimationNode { @@ -144,6 +279,20 @@ struct AnimationNodeAnimation : AnimationNode { { mAnimation->reset(); } + float getLength() const + { + if (enabled) + return mAnimation->getLength(); + else + return 0.0f; + } + float getTimePosition() const + { + if (enabled) + return mAnimation->getTimePosition(); + else + return 0.0f; + } }; struct AnimationNodeStateMachineState : AnimationNode { AnimationNodeStateMachineState() @@ -164,6 +313,14 @@ struct AnimationNodeStateMachineState : AnimationNode { { children[0]->reset(); } + float getLength() const + { + return children[0]->getLength(); + } + float getTimePosition() const + { + return children[0]->getLength(); + } }; struct AnimationNodeSpeed : AnimationNode { float m_speed; @@ -187,6 +344,25 @@ struct AnimationNodeSpeed : AnimationNode { { children[0]->reset(); } + float getLength() const + { + if (m_speed > 0.0f || m_speed < 0.0f) + return children[0]->getLength() / m_speed; + return 0.0f; + } + float getTimePosition() const + { + if (m_speed > 0.0f || m_speed < 0.0f) + return children[0]->getTimePosition() / m_speed; + return 0.0f; + } + float getTime() const override + { + float l = children[0]->getLength(); + if (l > 0.0f) + return children[0]->getTimePosition() / l; + return 0.0f; + } }; struct AnimationNodeStateMachine : AnimationNode { std::map stateMap; @@ -215,8 +391,10 @@ struct AnimationNodeStateMachine : AnimationNode { configured = true; } if (debug) { - std::cout<< "state machine addTime" << std::endl; - std::cout << "state machine children: " << children.size() << std::endl; + std::cout << "state machine addTime" << std::endl; + std::cout + << "state machine children: " << children.size() + << std::endl; } for (i = 0; i < children.size(); i++) { if (debug) @@ -230,8 +408,10 @@ struct AnimationNodeStateMachine : AnimationNode { child->setWeight(Ogre::Math::Clamp( newWeight * m_weight, 0, m_weight)); if (debug) { - std::cout << "fade in: " << newWeight << std::endl; - std::cout << "m_weight: " << m_weight << std::endl; + std::cout << "fade in: " << newWeight + << std::endl; + std::cout << "m_weight: " << m_weight + << std::endl; } if (newWeight >= 1) fade_in.erase(child); @@ -254,7 +434,8 @@ struct AnimationNodeStateMachine : AnimationNode { int i; if (weight > m_weight && currentAnim) fade_in.insert(currentAnim); - if (weight < m_weight && currentAnim && currentAnim->getWeight() > weight) + if (weight < m_weight && currentAnim && + currentAnim->getWeight() > weight) currentAnim->setWeight(weight); m_weight = weight; bool enabled = weight > 0.001f; @@ -273,7 +454,8 @@ struct AnimationNodeStateMachine : AnimationNode { { int i; if (debug) - std::cout << "children: " << children.size() << std::endl; + std::cout << "children: " << children.size() + << std::endl; for (i = 0; i < children.size(); i++) addState(children[i]); if (debug) @@ -312,6 +494,20 @@ struct AnimationNodeStateMachine : AnimationNode { { return mCurrentStateName; } + float getLength() const + { + if (currentAnim) + return currentAnim->getLength(); + else + return 0.0f; + } + float getTimePosition() const + { + if (currentAnim) + return currentAnim->getTimePosition(); + else + return 0.0f; + } }; #define ANIM_FADE_SPEED \ @@ -340,6 +536,14 @@ struct AnimationNodeOutput : AnimationNode { { children[0]->reset(); } + float getLength() const + { + return children[0]->getLength(); + } + float getTimePosition() const + { + return children[0]->getTimePosition(); + } }; struct AnimationSystem : AnimationNode { @@ -353,6 +557,7 @@ struct AnimationSystem : AnimationNode { std::vector vanimation_list; void add_animation(const Ogre::String &name, Animation *animation) { + OgreAssert(animation, "No animation " + name); animation_list[name] = animation; vanimation_list.push_back(animation); } @@ -388,13 +593,49 @@ struct AnimationSystem : AnimationNode { OgreAssert(parent, "bad parent"); Animation *animation = mAnimationSystem->animation_list[animation_name]; + OgreAssert(animation, + "bad animation " + animation_name); AnimationNodeAnimation *onode = new AnimationNodeAnimation(animation); + OgreAssert(onode, "bad animation"); + OgreAssert(onode->mAnimation, "bad animation"); animation_nodes.push_back(onode); parent->children.push_back(onode); animationNodeList.push_back(onode); return this; } + AnimationSystemBuilder *trigger(flecs::entity e, + const Ogre::String &name, + float time, + const Ogre::String &event) + { + struct EventSubscriber : AnimationTriggerSubscriber { + flecs::entity ent; + Ogre::String event; + void operator()(const AnimationTrigger *trigger) + { + ECS::get_mut().call_handler( + event, ent, ent); + } + EventSubscriber(flecs::entity e, + const Ogre::String &event) + : ent(e) + , event(event) + { + } + }; + OgreAssert(parent, "bad parent"); + Animation *animation = + static_cast(parent) + ->mAnimation; + OgreAssert(animation, "bad animation"); + AnimationTrigger *trigger = + new AnimationTrigger(name, time, 0.1f); + EventSubscriber *sub = new EventSubscriber(e, event); + trigger->addSubscriber(sub); + animation->addTrigger(trigger); + return this; + } AnimationSystemBuilder *speed(float speed, const Ogre::String &anchor = "") { @@ -451,6 +692,7 @@ struct AnimationSystem : AnimationNode { for (i = 0; i < m_builder.animationNodeList.size(); i++) { AnimationNodeAnimation *anim = m_builder.animationNodeList[i]; + OgreAssert(anim->mAnimation, "No animation"); float weight = anim->getWeight(); anim->mAnimation->increaseAccWeight(weight); #ifdef VDEBUG @@ -490,6 +732,14 @@ struct AnimationSystem : AnimationNode { { return static_cast(m_builder.nodeMap[name]); } + float getLength() const + { + return m_builder.animation_nodes[0]->getLength(); + } + float getTimePosition() const + { + return m_builder.animation_nodes[0]->getTimePosition(); + } }; struct AnimationControl { diff --git a/src/gamedata/CharacterModule.cpp b/src/gamedata/CharacterModule.cpp index 6d7fc1c..44c5710 100644 --- a/src/gamedata/CharacterModule.cpp +++ b/src/gamedata/CharacterModule.cpp @@ -20,6 +20,7 @@ CharacterModule::CharacterModule(flecs::world &ecs) ecs.component(); ecs.component(); ecs.component(); + ecs.component(); ecs.system("UpdateTimer") .kind(flecs::OnUpdate) .each([this](EngineData &eng, CharacterBase &ch) { @@ -107,6 +108,7 @@ CharacterModule::CharacterModule(flecs::world &ecs) .with() .with() .without() + .without() .each([this](flecs::entity e, const EngineData &eng, const CharacterBase &ch, CharacterVelocity &gr) { Ogre::Vector3 gravity(0, -9.8f, 0); @@ -162,6 +164,7 @@ CharacterModule::CharacterModule(flecs::world &ecs) .kind(flecs::OnUpdate) .with() .with() + .without() .each([](flecs::entity e, const Input &input, const Camera &camera, CharacterBase &ch) { ch.mGoalDirection = Ogre::Vector3::ZERO; @@ -225,14 +228,14 @@ CharacterModule::CharacterModule(flecs::world &ecs) } }); ecs.system("SetupCharacter") + const CharacterConf, Body2Entity>("SetupCharacter") .kind(flecs::OnUpdate) .with() .without() .without() .each([](flecs::entity e, const EngineData &eng, const CharacterLocation &loc, - const CharacterConf &conf) { + const CharacterConf &conf, Body2Entity &b2e) { CharacterBase &ch = e.ensure(); CharacterBody &body = e.ensure(); AnimationControl &anim = e.ensure(); @@ -256,6 +259,7 @@ CharacterModule::CharacterModule(flecs::world &ecs) body.mGhostObject = nullptr; body.mController = nullptr; body.mGhostObject = new btPairCachingGhostObject(); + b2e.entities[body.mGhostObject] = e; body.mCollisionShape = new btCompoundShape(false); body.mGhostObject->setCollisionShape( body.mCollisionShape); @@ -446,23 +450,23 @@ CharacterModule::CharacterModule(flecs::world &ecs) << "\n"; }); #endif - ecs.system( + ecs.system( "UpdatePhysics2") .kind(flecs::OnUpdate) .with() .each([](flecs::entity e, const EngineData &eng, - const CharacterBase &ch, CharacterSlot &slot) { - if (slot.parent_e.has()) { - const VehicleSlots &slots = - slot.parent_e.get(); - if (slots.seats.find(slot.slot_name) == - slots.seats.end()) + const CharacterBase &ch, ParentSlot &slot) { + if (slot.parent_e.has()) { + const ObjectSlots &slots = + slot.parent_e.get(); + if (slots.slots.find(slot.slot_name) == + slots.slots.end()) // invalid setting - e.remove(); + e.remove(); if (slot.activated) return; Ogre::SceneNode *slot_base = - slots.seats.at(slot.slot_name).second; + slots.slots.at(slot.slot_name).second; Ogre::Vector3 position = slot_base->_getDerivedPosition(); Ogre::Quaternion orientation = diff --git a/src/gamedata/CharacterModule.h b/src/gamedata/CharacterModule.h index ca1b3cf..43fb18a 100644 --- a/src/gamedata/CharacterModule.h +++ b/src/gamedata/CharacterModule.h @@ -11,11 +11,6 @@ struct CharacterGravity {}; struct CharacterBuoyancy {}; struct CharacterDisablePhysics {}; struct CharacterUpdatePhysicsState {}; -struct CharacterSlot { - flecs::entity parent_e; - Ogre::String slot_name; - bool activated; -}; struct CharacterBase { Ogre::String type; float mTimer; @@ -45,6 +40,9 @@ struct CharacterVelocity { Ogre::Vector3 gvelocity; Ogre::Vector3 velocity; }; +struct CharacterInActuator { + Ogre::String animationState; +}; struct CharacterModule { CharacterModule(flecs::world &ecs); void updateCameraGoal(Camera &camera, Ogre::Real deltaYaw, diff --git a/src/gamedata/Components.h b/src/gamedata/Components.h index ace9917..02b1e4f 100644 --- a/src/gamedata/Components.h +++ b/src/gamedata/Components.h @@ -1,5 +1,6 @@ #ifndef COMPONENTS_H_ #define COMPONENTS_H_ +#include #include #include namespace Ogre @@ -76,10 +77,18 @@ struct InWater {}; struct TerrainReady {}; struct WaterReady {}; struct GroundCheckReady {}; -struct VehicleSlots { +struct ParentSlot { + flecs::entity parent_e; + Ogre::String slot_name; + bool activated; +}; +struct ObjectSlots { std::unordered_map > - seats; + slots; +}; +struct Body2Entity { + std::unordered_map entities; }; } #endif \ No newline at end of file diff --git a/src/gamedata/EventTriggerModule.cpp b/src/gamedata/EventTriggerModule.cpp index cc6a017..00b6f8b 100644 --- a/src/gamedata/EventTriggerModule.cpp +++ b/src/gamedata/EventTriggerModule.cpp @@ -62,7 +62,7 @@ struct DeepPenetrationContactResultCallback : public btManifoldResult { ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs) { ecs.module(); - ecs.component(); + ecs.component(); ecs.component().on_add([](flecs::entity e, TriggerBody &body) { bool kinematic = false; @@ -81,14 +81,6 @@ ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs) e.get().position, Ogre::Quaternion(0, 0, 0, 1)); } - /* - Ogre::MeshPtr mesh = - Ogre::MeshManager::getSingleton().createManual( - "trigger", "General"); - Ogre::Entity *ent = - ECS::get().mScnMgr->createEntity(mesh); - body.mSceneNode->attachObject(ent); -*/ body.mBody = new btPairCachingGhostObject(); body.mBody->getWorldTransform().setOrigin(Ogre::Bullet::convert( body.mSceneNode->_getDerivedPosition())); @@ -102,10 +94,6 @@ ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs) if (kinematic) flags |= btCollisionObject::CF_STATIC_OBJECT; body.mBody->setCollisionFlags(flags); - /* - ECS::get().mWorld->attachCollisionObject( - body.mBody, ent, 16, 0x1); -*/ ECS::get().mWorld->getBtWorld()->addCollisionObject( body.mBody, 16, 0x1); struct EntityCollisionListener { @@ -142,12 +130,14 @@ ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs) ecs.component().on_set( [](flecs::entity e, EventTrigger &ev) { e.add(); + e.set({}); }); - ecs.system( - "CheckCollisions") + ecs.system("CheckCollisions") .kind(flecs::OnUpdate) .each([](flecs::entity e, const EngineData &eng, - const EventTrigger &evt, TriggerBody &body) { + const EventTrigger &evt, TriggerBody &body, + EventTriggerData &data) { btDispatcher *dispatch = eng.mWorld->getBtWorld()->getDispatcher(); btHashedOverlappingPairCache *cache = @@ -255,12 +245,33 @@ ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs) .end()) { body.contactBodies .insert(other); + OgreAssert( + ECS::get< + Body2Entity>() + .entities + .find(const_cast< + btCollisionObject + *>( + other)) != + ECS::get< + Body2Entity>() + .entities + .end(), + "No body to entity mapping"); ECS::get< LuaBase>() .mLua ->call_handler( - evt.event, - e); + evt.event + + "_enter", + e, + ECS::get< + Body2Entity>() + .entities + .at(const_cast< + btCollisionObject + *>( + other))); } } } @@ -272,18 +283,15 @@ ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs) while (it != body.contactBodies.end()) { if (currentContactBodies.find(*it) == currentContactBodies.end()) { - if (e.has()) { - const Ogre::String &exit_event = - ECS::get< - EventTriggerExit>() - .event; - ECS::get() - .mLua->call_handler( - exit_event); - } else { - std::cout << "body exited" - << std::endl; - } + ECS::get().mLua->call_handler( + evt.event + "_exit", e, + ECS::get() + .entities + .at(const_cast< + btCollisionObject + *>( + *it))); + std::cout << "body exited" << std::endl; it = body.contactBodies.erase(it); if (it == body.contactBodies.end()) break; diff --git a/src/gamedata/EventTriggerModule.h b/src/gamedata/EventTriggerModule.h index e1506d7..cc9d5dc 100644 --- a/src/gamedata/EventTriggerModule.h +++ b/src/gamedata/EventTriggerModule.h @@ -11,9 +11,10 @@ struct EventTrigger { float radius; Ogre::String event; Ogre::SceneNode *node; + bool once; }; -struct EventTriggerExit { - Ogre::String event; +struct EventTriggerData { + std::set entities; }; struct EventTriggerModule { EventTriggerModule(flecs::world &ecs); diff --git a/src/gamedata/GameData.cpp b/src/gamedata/GameData.cpp index 3bd216a..fc1ec1f 100644 --- a/src/gamedata/GameData.cpp +++ b/src/gamedata/GameData.cpp @@ -38,6 +38,9 @@ void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world, .add(flecs::Singleton); /* lots of things depend on it */ ecs.component().add(flecs::Singleton); + ecs.component(); + ecs.component(); + ecs.component().add(flecs::Singleton); ecs.import (); ecs.import (); ecs.import (); @@ -96,6 +99,7 @@ void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world, nullptr, false, { 0, 0, 0 } }); + ecs.set({}); std::cout << "Setup GameData done\n"; /* Create player */ diff --git a/src/gamedata/LuaData.cpp b/src/gamedata/LuaData.cpp index 7f9172c..0df0eb2 100644 --- a/src/gamedata/LuaData.cpp +++ b/src/gamedata/LuaData.cpp @@ -63,7 +63,8 @@ int LuaData::call_handler(const Ogre::String &event) lua_rawgeti(L, LUA_REGISTRYINDEX, setup_handlers[i]); lua_pushstring(L, event.c_str()); lua_pushinteger(L, -1); - if (lua_pcall(L, 2, 0, 0)) { + lua_pushinteger(L, -1); + if (lua_pcall(L, 3, 0, 0)) { Ogre::LogManager::getSingleton().stream() << lua_tostring(L, -1); OgreAssert(false, "Lua error"); @@ -72,14 +73,16 @@ int LuaData::call_handler(const Ogre::String &event) return 0; } -int LuaData::call_handler(const Ogre::String &event, flecs::entity e) +int LuaData::call_handler(const Ogre::String &event, flecs::entity e, + flecs::entity o) { int i; for (i = 0; i < setup_handlers.size(); i++) { lua_rawgeti(L, LUA_REGISTRYINDEX, setup_handlers[i]); lua_pushstring(L, event.c_str()); lua_pushinteger(L, idmap.add_entity(e)); - if (lua_pcall(L, 2, 0, 0)) { + lua_pushinteger(L, idmap.add_entity(o)); + if (lua_pcall(L, 3, 0, 0)) { Ogre::LogManager::getSingleton().stream() << lua_tostring(L, -1); OgreAssert(false, "Lua error"); @@ -373,6 +376,31 @@ LuaData::LuaData() return 1; }); lua_setglobal(L, "ecs_child_character_trigger"); + lua_pushcfunction(L, [](lua_State *L) -> int { + luaL_checktype(L, 1, LUA_TNUMBER); // trigger + luaL_checktype(L, 2, LUA_TNUMBER); // object + int trigger = lua_tointeger(L, 1); + int object = lua_tointeger(L, 2); + flecs::entity trigger_e = idmap.get_entity(trigger); + flecs::entity object_e = idmap.get_entity(object); + Ogre::SceneNode *target_node = nullptr; + Ogre::Any targetAny = trigger_e.get() + .node->getUserObjectBindings() + .getUserAny("target"); + OgreAssert(targetAny.has_value(), "need target"); + target_node = Ogre::any_cast(targetAny); + Ogre::Vector3 position = target_node->_getDerivedPosition(); + Ogre::Quaternion orientation = + target_node->_getDerivedOrientation(); + if (object_e.has()) { + object_e.get_mut() + .mBodyNode->_setDerivedPosition(position); + object_e.get_mut() + .mBodyNode->_setDerivedOrientation(orientation); + } + return 0; + }); + lua_setglobal(L, "ecs_trigger_set_position"); lua_pushcfunction(L, [](lua_State *L) -> int { OgreAssert(lua_gettop(L) == 5, "Invalid parameters"); luaL_checktype(L, 1, LUA_TSTRING); // type @@ -444,6 +472,20 @@ LuaData::LuaData() return 0; }); lua_setglobal(L, "ecs_character_physics_control"); + lua_pushcfunction(L, [](lua_State *L) -> int { + luaL_checktype(L, 1, LUA_TNUMBER); // object + luaL_checktype(L, 2, LUA_TSTRING); // animation + Ogre::String animation = lua_tostring(L, 2); + + int object = lua_tointeger(L, 1); + flecs::entity object_e = idmap.get_entity(object); + if (animation.length()) + object_e.set({ animation }); + else + object_e.remove(); + return 0; + }); + lua_setglobal(L, "ecs_character_set_actuator"); lua_pushcfunction(L, [](lua_State *L) -> int { OgreAssert(lua_gettop(L) == 3, "Bad parameters"); luaL_checktype(L, 1, LUA_TNUMBER); // parent @@ -454,7 +496,7 @@ LuaData::LuaData() Ogre::String slot = lua_tostring(L, 3); flecs::entity parent_e = idmap.get_entity(parent); flecs::entity object_e = idmap.get_entity(object); - object_e.set({ parent_e, slot, false }); + object_e.set({ parent_e, slot, false }); return 0; }); lua_setglobal(L, "ecs_set_slot"); diff --git a/src/gamedata/LuaData.h b/src/gamedata/LuaData.h index 6e2af3b..b904cf7 100644 --- a/src/gamedata/LuaData.h +++ b/src/gamedata/LuaData.h @@ -12,7 +12,8 @@ struct LuaData { std::vector setup_handlers; int setup_handler(); int call_handler(const Ogre::String &event); - int call_handler(const Ogre::String &event, flecs::entity e); + int call_handler(const Ogre::String &event, flecs::entity e, + flecs::entity o); LuaData(); virtual ~LuaData(); diff --git a/src/sceneloader/loader.cpp b/src/sceneloader/loader.cpp index e8d71d8..d91115e 100644 --- a/src/sceneloader/loader.cpp +++ b/src/sceneloader/loader.cpp @@ -561,6 +561,43 @@ void SceneLoader::processNode(pugi::xml_node &XMLNode, SceneNode *pParent) r = Ogre::any_cast(anyr); e.set( { pNode, Ogre::Vector3(0, 0, 0), h, r, event, pNode }); + Ogre::Node::ChildNodeMap children = pNode->getChildren(); + if (children.size() == 1) + pNode->getUserObjectBindings().setUserAny( + "target", + static_cast(children[0])); + else if (children.size() == 0) + pNode->getUserObjectBindings().setUserAny("target", + pNode); + else { + int i; + bool ok = false; + for (i = 0; i < children.size(); i++) { + Ogre::Any nodeName = + children[i] + ->getUserObjectBindings() + .getUserAny("name"); + if (nodeName.has_value()) { + Ogre::String snodeName = + Ogre::any_cast( + nodeName); + if (snodeName == "target") { + pNode->getUserObjectBindings().setUserAny( + "target", + static_cast( + children[i])); + ok = true; + break; + } + } + } + if (!ok) + pNode->getUserObjectBindings().setUserAny( + "target", + static_cast( + children[0])); + } } }