diff --git a/.vscode/settings.json b/.vscode/settings.json index 05d74cf..70c0c20 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,6 +13,19 @@ "string_view": "cpp", "atomic": "cpp", "memory_resource": "cpp", - "stop_token": "cpp" + "stop_token": "cpp", + "random": "cpp", + "future": "cpp", + "array": "cpp", + "deque": "cpp", + "list": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "initializer_list": "cpp", + "span": "cpp", + "chrono": "cpp", + "format": "cpp" } } \ No newline at end of file diff --git a/assets/blender/vehicles/boat.blend b/assets/blender/vehicles/boat.blend index b048859..19771ae 100644 --- a/assets/blender/vehicles/boat.blend +++ b/assets/blender/vehicles/boat.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1416cfab6c590a98fbacc2de7a27026e64dad35ba7e278f9df994d30051e28bb -size 378101 +oid sha256:64b6e1ece8f3b453151d64ecccb377efddf36606fa45f89788298f110db81b02 +size 378269 diff --git a/lua-scripts/data.lua b/lua-scripts/data.lua index b03e032..b8af6dc 100644 --- a/lua-scripts/data.lua +++ b/lua-scripts/data.lua @@ -230,7 +230,6 @@ function StartGameQuest() local mc_is_free = function() this.boat_id = ecs_vehicle_set("boat", 0, 0, -20, 1.75) this.boat2_id = ecs_vehicle_set("boat", -10, 0, -20, 1.55) - this.trigger_id = ecs_child_character_trigger(this.boat_id, "entered_boat", 0, 0, 0, 3, 3) this.npc_id = ecs_npc_set("normal-female.glb", 0, 2, -20, 1.75) this.boat = true -- ecs_set_slot(this.boat_id, this.npc_id, "captain_seat") diff --git a/src/gamedata/BoatModule.cpp b/src/gamedata/BoatModule.cpp index bac6fd9..8a1edb1 100644 --- a/src/gamedata/BoatModule.cpp +++ b/src/gamedata/BoatModule.cpp @@ -58,8 +58,7 @@ BoatModule::BoatModule(flecs::world &ecs) Ogre::ResourceGroupManager:: AUTODETECT_RESOURCE_GROUP_NAME); SceneLoader loader; - loader.load(scene, "General", attachment, - (int)e.raw_id()); + loader.load(scene, "General", attachment, e); // attachment->loadChildren(type.resourceName); std::vector v = attachment->getChildren(); diff --git a/src/gamedata/CMakeLists.txt b/src/gamedata/CMakeLists.txt index 257dd4c..77e41d7 100644 --- a/src/gamedata/CMakeLists.txt +++ b/src/gamedata/CMakeLists.txt @@ -1,6 +1,6 @@ project(gamedata) find_package(OGRE REQUIRED COMPONENTS Bites Bullet Paging Terrain Overlay CONFIG) add_library(GameData STATIC GameData.cpp CharacterModule.cpp WaterModule.cpp SunModule.cpp TerrainModule.cpp GUIModule.cpp LuaData.cpp WorldMapModule.cpp - BoatModule.cpp EventTriggerModule.cpp) + BoatModule.cpp EventTriggerModule.cpp CharacterAnimationModule.cpp) target_link_libraries(GameData PUBLIC OgreMain OgreBites OgreBullet OgrePaging OgreTerrain OgreOverlay flecs::flecs_static lua sceneloader) target_include_directories(GameData PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/gamedata/CharacterAnimationModule.cpp b/src/gamedata/CharacterAnimationModule.cpp new file mode 100644 index 0000000..64f37cf --- /dev/null +++ b/src/gamedata/CharacterAnimationModule.cpp @@ -0,0 +1,557 @@ +#include +#include "Components.h" +#include "CharacterModule.h" +#include "CharacterAnimationModule.h" +namespace ECS +{ +#if 0 +struct AnimationSystem { + struct AnimationDataNode { + float weight; + }; + int root_index; + struct AnimationSystemBuilder { + struct AnimationNode { + enum { + ANIMATION_NODE_OUTPUT, + ANIMATION_NODE_BLEND2, + ANIMATION_NODE_ANIMATION, + ANIMATION_NODE_STATEMACHINE, + ANIMATION_NODE_STATE, + ANIMATION_NODE_TRANSITION + }; + AnimationNode *outputs[32]; + int output_count; + int type; + std::string anchor; + }; + AnimationNode *parent; + std::list parent_stack; + std::vector animation_nodes; + struct ANOutput : AnimationNode {}; + struct ANBlend2 : AnimationNode { + float weight; + }; + struct ANAnimation : AnimationNode { + std::string animation; + }; + struct ANStateMachine : AnimationNode {}; + struct ANState : AnimationNode { + std::string name; + bool start; + bool end; + }; + struct ANStateMachineTransition : AnimationNode { + std::string from, to; + bool at_end; + }; + AnimationSystemBuilder *output() + { + ANOutput *onode = new ANOutput; + onode->output_count = 0; + onode->type = AnimationNode::ANIMATION_NODE_OUTPUT; + onode->anchor = ""; + animation_nodes.push_back(onode); + parent = onode; + + return this; + } + AnimationSystemBuilder *blend2(float blend, + const std::string &anchor = "") + { + ANBlend2 *onode = new ANBlend2; + onode->output_count = 0; + onode->type = AnimationNode::ANIMATION_NODE_BLEND2; + onode->anchor = anchor; + onode->weight = blend; + animation_nodes.push_back(onode); + parent->outputs[parent->output_count++] = onode; + parent_stack.push_back(parent); + parent = onode; + return this; + } + AnimationSystemBuilder * + animation(const std::string &animation, + const std::string &anchor = "") + { + ANAnimation *onode = new ANAnimation; + onode->output_count = 0; + onode->type = AnimationNode::ANIMATION_NODE_ANIMATION; + onode->anchor = anchor; + onode->animation = animation; + animation_nodes.push_back(onode); + parent->outputs[parent->output_count++] = onode; + parent_stack.push_back(parent); + parent = onode; + return this; + } + AnimationSystemBuilder *end() + { + parent = parent_stack.back(); + parent_stack.pop_back(); + return this; + } + AnimationSystemBuilder * + state_machine(const std::string &anchor = "") + { + ANStateMachine *onode = new ANStateMachine; + onode->output_count = 0; + onode->type = + AnimationNode::ANIMATION_NODE_STATEMACHINE; + onode->anchor = anchor; + animation_nodes.push_back(onode); + parent->outputs[parent->output_count++] = onode; + parent_stack.push_back(parent); + parent = onode; + return this; + } + AnimationSystemBuilder *state(const std::string &name) + { + ANState *onode = new ANState; + onode->output_count = 0; + onode->type = AnimationNode::ANIMATION_NODE_STATE; + onode->anchor = ""; + onode->name = name; + animation_nodes.push_back(onode); + parent->outputs[parent->output_count++] = onode; + parent_stack.push_back(parent); + parent = onode; + return this; + } + AnimationSystemBuilder * + transition(const std::string &from, const std::string &to, + bool at_end, const std::string &anchor = "") + { + ANStateMachineTransition *onode = + new ANStateMachineTransition; + onode->output_count = 0; + onode->type = AnimationNode::ANIMATION_NODE_TRANSITION; + onode->anchor = anchor; + onode->from = from; + onode->to = to; + onode->at_end = at_end; + animation_nodes.push_back(onode); + parent->outputs[parent->output_count++] = onode; + parent_stack.push_back(parent); + parent = onode; + return this; + } + void build() + { + } + }; + AnimationSystemBuilder m_builder; + std::map + mruntimeData; + AnimationSystemBuilder *builder() + { + m_builder.animation_nodes.reserve(8); + m_builder.parent = nullptr; + return &m_builder; + } + void update(float delta) + { + std::deque queue; + root_index = -1; + if (mruntimeData.size() == 0) { + int i; + for (i = 0; i < m_builder.animation_nodes.size(); i++) { + AnimationDataNode data; + data.weight = 0; + mruntimeData[m_builder.animation_nodes[i]] = + data; + std::cout << "type: " + << m_builder.animation_nodes[i]->type + << std::endl; + } + for (i = 0; i < m_builder.animation_nodes.size(); i++) { + if (m_builder.animation_nodes[i]->type == + AnimationSystemBuilder::AnimationNode:: + ANIMATION_NODE_OUTPUT) { + root_index = i; + break; + } + } + } + std::cout << "root index: " << root_index << " " + << m_builder.animation_nodes.size() << std::endl; + queue.push_back(m_builder.animation_nodes[root_index]); + int i; + while (queue.size() > 0) { + AnimationSystemBuilder::AnimationNode *item = + queue.front(); + queue.pop_front(); + switch (item->type) { + case AnimationSystemBuilder::AnimationNode:: + ANIMATION_NODE_OUTPUT: + for (i = 0; i < item->output_count; i++) { + AnimationSystemBuilder::AnimationNode + *out = item->outputs[i]; + mruntimeData[out].weight = 1.0f; + } + break; + case AnimationSystemBuilder::AnimationNode:: + ANIMATION_NODE_BLEND2: { + float weight = + static_cast(item) + ->weight; + for (i = 0; i < item->output_count; i++) { + AnimationSystemBuilder::AnimationNode + *out = item->outputs[i]; + if (i == 0) + mruntimeData[out].weight = + weight; + else if (i == 0) + mruntimeData[out].weight = + (1.0f - weight); + else + mruntimeData[out].weight = 0.0f; + } + } break; + case AnimationSystemBuilder::AnimationNode:: + ANIMATION_NODE_ANIMATION: { + const std::string &animation = + static_cast(item) + ->animation; + std::cout << "animation: " << animation << " " + << mruntimeData[item].weight + << std::endl; + } break; + case AnimationSystemBuilder::AnimationNode:: + ANIMATION_NODE_STATEMACHINE: + break; + case AnimationSystemBuilder::AnimationNode:: + ANIMATION_NODE_STATE: + break; + } + for (i = 0; i < item->output_count; i++) { + queue.push_back(item->outputs[i]); + } + } + +#if 0 + while (breadth) { + int i; + switch (breadth->type) { + case AnimationSystemBuilder::AnimationNode:: + ANIMATION_NODE_OUTPUT: + for (i = 0; i < breadth->output_count; i++) { + AnimationSystemBuilder::AnimationNode + *out = breadth->outputs[i]; + mruntimeData[out].weight = 1.0f; + } + break; + case AnimationSystemBuilder::AnimationNode:: + ANIMATION_NODE_BLEND2: { + float weight = + static_cast(breadth) + ->weight; + for (i = 0; i < breadth->output_count; i++) { + AnimationSystemBuilder::AnimationNode + *out = breadth->outputs[i]; + if (i == 0) + mruntimeData[out].weight = + weight; + else if (i == 0) + mruntimeData[out].weight = + (1.0f - weight); + else + mruntimeData[out].weight = 0.0f; + } + } break; + case AnimationSystemBuilder::AnimationNode:: + ANIMATION_NODE_ANIMATION: + break; + case AnimationSystemBuilder::AnimationNode:: + ANIMATION_NODE_STATEMACHINE: + break; + case AnimationSystemBuilder::AnimationNode:: + ANIMATION_NODE_STATE: + break; + } + visited.insert(breadth); + AnimationSystemBuilder::AnimationNode *next = nullptr; + while (!next && parents.size() > 0) { + for (i = 0; i < breadth->output_count; i++) { + if (visited.find(breadth->outputs[i]) == + visited.end()) { + next = breadth->outputs[i]; + break; + } + } + if (next) + break; + else { + breadth = parents.back(); + parents.pop_back(); + } + } + if (next) { + parents.push_back(breadth); + breadth = next; + } + } +#endif + OgreAssert(false, "update"); + } +}; +struct AnimationTree { + AnimationSystem *manimationSystem; +}; +#endif +CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs) +{ + ecs.module(); + ecs.component(); + ecs.system("HandleAnimations") + .kind(flecs::OnUpdate) + .each([this](flecs::entity e, const CharacterBase &ch, + AnimationControl &anim) { + if (!anim.configured && ch.mSkeleton) { + int i, j; + ch.mSkeleton->setBlendMode( + Ogre::ANIMBLEND_CUMULATIVE); + Ogre::String animNames[] = { "idle", "walking", + "running", + "treading_water", + "swimming" }; + int state_count = sizeof(animNames) / + sizeof(animNames[0]); + anim.mAnimationSystem = new AnimationSystem(); + for (i = 0; i < state_count; i++) { + Animation *animation = new Animation( + ch.mBodyEnt->getAnimationState( + animNames[i]), + ch.mSkeleton->getAnimation( + animNames[i]) + + ); + animation->setLoop(true); + anim.mAnimationSystem->add_animation( + animNames[i], animation); + } + anim.mAnimationSystem + ->builder() + /* clang-format off */ + ->output() + ->state_machine(ANIM_FADE_SPEED, "state") + ->state("idle") + ->animation("idle") + ->end() + ->state("walking") + ->animation("walking") + ->end() + ->state("running") + ->animation("running") + ->end() + ->state("treading_water") + ->animation("treading_water") + ->end() + ->state("swimming") + ->animation("swimming") + ->end() + ->state("swimming-fast") + ->speed(20.0f) + ->animation("swimming") + ->end() + ->end() + ->end(); + /* clang-format on */ + + anim.mAnimationSystem + ->get( + "state") + ->setAnimation("idle"); + anim.configured = true; + } + }); + ecs.system("HandleAnimations1") + .kind(flecs::OnUpdate) + .each([this](const EngineData &eng, const Input &input, + CharacterBase &ch, AnimationControl &anim) { + float delta = eng.delta; + anim.mAnimationSystem->addTime(delta); + // fadeAnimations(anim, delta); + if (!ch.mRootBone) + return; + ch.mBoneMotion += ch.mRootBone->getPosition(); + }); + ecs.system( + "HandleRootMotionVelocity") + .kind(flecs::OnUpdate) + .with() + .with() + .each([this](flecs::entity e, const EngineData &eng, + const CharacterBase &ch, CharacterVelocity &v) { + if (eng.delta < 0.0000001f) + return; + if (!ch.mBodyNode) + return; + Ogre::Quaternion rot = ch.mBodyNode->getOrientation(); + 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); + }); + ecs.system("HandleSwimming") + .kind(flecs::OnUpdate) + .with() + .with() + .with() + .with() + .each([this](flecs::entity e, const EngineData &eng, + const AnimationControl &anim, + const CharacterBase &ch, CharacterVelocity &gr) { + if (anim.mAnimationSystem + ->get("state") + ->getCurrentState() == "swimming") { + float h = Ogre::Math::Clamp( + 0.0f - ch.mBodyNode->getPosition().y, + 0.0f, 2000.0f); + if (h > 0.05 && h < 2.0f) + gr.gvelocity.y += 0.1f * (h + 1.0f) * + h * eng.delta; + } + }); + ecs.system("HandleRootMotion") + .kind(flecs::OnUpdate) + .each([this](flecs::entity e, const EngineData &eng, + CharacterBase &ch, CharacterBody &body, + AnimationControl &anim, CharacterVelocity &v) { + if (!ch.mBodyNode) + return; + if (eng.delta < 0.0000001f) + return; + OgreAssert(eng.delta > 0.0f, "Zero delta"); + int maxPen = 0; + Ogre::Vector3 colNormal; + bool is_on_floor = false; + bool penetration = false; + if (eng.startupDelay < 0.0f) { + if (body.mController) { + Ogre::Vector3 rotMotion = + v.velocity * eng.delta; + btVector3 currentPosition = + body.mGhostObject + ->getWorldTransform() + .getOrigin(); + is_on_floor = + body.mController->isOnFloor(); + penetration = body.mController + ->isPenetrating(); + if (is_on_floor) + v.gvelocity = Ogre::Vector3( + 0.0f, 0.0f, 0.0f); + + btTransform from( + Ogre::Bullet::convert( + ch.mBodyNode + ->getOrientation()), + Ogre::Bullet::convert( + ch.mBodyNode + ->getPosition())); + ch.mBodyNode->setPosition( + ch.mBodyNode->getPosition() + + rotMotion); + + ch.mBoneMotion = Ogre::Vector3(0, 0, 0); + } + } + }); + ecs.system( + "HandlePlayerAnimations") + .kind(flecs::OnUpdate) + .with() + .with() + .each([](flecs::entity e, const Input &input, + const CharacterBase &ch, AnimationControl &anim) { + if (!anim.configured) + return; + if (input.fast) + std::cout << "fast!" << std::endl; + AnimationNodeStateMachine *state_machine = + anim.mAnimationSystem + ->get( + "state"); + Ogre::String current_state = + state_machine->getCurrentState(); + bool controls_idle = input.motion.zeroLength(); + bool anim_is_idle = current_state == "idle" || + current_state == "treading_water"; + bool anim_is_walking = current_state == "walking"; + bool anim_is_running = current_state == "running"; + bool anim_is_swimming_slow = current_state == + "swimming"; + bool anim_is_swimming_fast = current_state == + "swimming-fast"; + bool anim_is_swimming = anim_is_swimming_slow || + anim_is_swimming_fast; + bool anim_is_motion = anim_is_walking || + anim_is_running || + anim_is_swimming; + bool start_motion = !controls_idle && anim_is_idle; + bool end_motion = controls_idle && !anim_is_idle; + if (controls_idle && anim_is_idle) { + if (current_state != "treading_water" && + ch.is_submerged) + state_machine->setAnimation( + "treading_water"); + else if (current_state != "idle" && + !ch.is_submerged) + state_machine->setAnimation("idle"); + } else if (start_motion) { + if (ch.is_submerged) { + if (input.fast) + state_machine->setAnimation( + "swimming-fast", true); + else + state_machine->setAnimation( + "swimming", true); + } else { + if (input.fast) + state_machine->setAnimation( + "running", true); + else + state_machine->setAnimation( + "walking", true); + } + } else if (end_motion) { + if (ch.is_submerged) + state_machine->setAnimation( + "treading_water"); + else + state_machine->setAnimation("idle"); + } else { + if (ch.is_submerged) { + if (input.fast && + !anim_is_swimming_fast) { + state_machine->setAnimation( + "swimming-fast"); + } else if (!input.fast && + !anim_is_swimming_slow) { + state_machine->setAnimation( + "swimming"); + } + } else { + if (input.fast && !anim_is_running) + state_machine->setAnimation( + "running"); + else if (!input.fast && + !anim_is_walking) + state_machine->setAnimation( + "walking"); + } + } + }); +} +} \ No newline at end of file diff --git a/src/gamedata/CharacterAnimationModule.h b/src/gamedata/CharacterAnimationModule.h new file mode 100644 index 0000000..a8597d6 --- /dev/null +++ b/src/gamedata/CharacterAnimationModule.h @@ -0,0 +1,483 @@ +#ifndef CHARACTER_ANIMATION_MODULE_H_ +#define CHARACTER_ANIMATION_MODULE_H_ +#include +#include +namespace ECS +{ +struct Animation { + Ogre::AnimationState *mAnimationState; + Ogre::Animation *mSkelAnimation; + Ogre::NodeAnimationTrack *mHipsTrack; + Ogre::NodeAnimationTrack *mRootTrack; + float m_weight; + float m_accWeight; + Animation(Ogre::AnimationState *animState, + Ogre::Animation *skelAnimation) + : mAnimationState(animState) + , mSkelAnimation(skelAnimation) + , m_weight(0) + , m_accWeight(0) + { + int j; + for (const auto &it : mSkelAnimation->_getNodeTrackList()) { + Ogre::NodeAnimationTrack *track = it.second; + Ogre::String trackName = + track->getAssociatedNode()->getName(); + if (trackName == "mixamorig:Hips") { + mHipsTrack = track; + } else if (trackName == "Root") { + mRootTrack = track; + // mRootTracks[i]->removeAllKeyFrames(); + } + } + 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; + } + } + Ogre::String getName() + { + return mAnimationState->getAnimationName(); + } + void setLoop(bool loop) + { + mAnimationState->setLoop(loop); + } + bool getLoop() const + { + return mAnimationState->getLoop(); + } + void setEnabled(bool enabled) + { + mAnimationState->setEnabled(enabled); + } + bool getEnabled() const + { + return mAnimationState->getEnabled(); + } + void setWeight(float weight) + { + bool enabled = weight > 0.001f; + setEnabled(enabled); + mAnimationState->setWeight(weight); + m_weight = weight; + } + float getWeight() const + { + return m_weight; + } + void addTime(float time) + { + mAnimationState->addTime(time); + } + void reset() + { + mAnimationState->setTimePosition(0); + } + void resetAccWeight() + { + m_accWeight = 0; + } + void increaseAccWeight(float weight) + { + m_accWeight += weight; + } + float getAccWeight() const + { + return m_accWeight; + } +}; + +struct AnimationNode { + std::vector children; + float m_weight; + Ogre::String m_name; + AnimationNode() + : m_weight(0) + { + } + virtual void addTime(float time) = 0; + virtual void setWeight(float weight) = 0; + virtual void reset() = 0; + float getWeight() + { + return m_weight; + } + const Ogre::String &getName() + { + return m_name; + } + void setName(const Ogre::String &name) + { + m_name = name; + } +}; + +struct AnimationNodeAnimation : AnimationNode { + Animation *mAnimation; + bool enabled; + AnimationNodeAnimation(Animation *animation) + : AnimationNode() + , mAnimation(animation) + { + } + void addTime(float time) + { + mAnimation->addTime(time); + } + void setWeight(float weight) + { + m_weight = weight; + enabled = weight > 0.001f; + } + void reset() + { + mAnimation->reset(); + } +}; +struct AnimationNodeStateMachineState : AnimationNode { + AnimationNodeStateMachineState() + : AnimationNode() + { + } + void addTime(float time) + { + children[0]->addTime(time); + } + void setWeight(float weight) + { + m_weight = weight; + bool enabled = weight > 0.001f; + children[0]->setWeight(weight); + } + void reset() + { + children[0]->reset(); + } +}; +struct AnimationNodeSpeed : AnimationNode { + float m_speed; + bool enabled; + AnimationNodeSpeed(float speed) + : AnimationNode() + , m_speed(speed) + , enabled(false) + { + } + void addTime(float time) + { + children[0]->addTime(time * m_speed); + } + void setWeight(float weight) + { + m_weight = weight; + children[0]->setWeight(weight); + } + void reset() + { + children[0]->reset(); + } +}; +struct AnimationNodeStateMachine : AnimationNode { + std::map stateMap; + std::set fade_in, fade_out; + AnimationNode *currentAnim, *nextAnim; + float fade_speed; + Ogre::String mCurrentStateName; + bool configured; + AnimationNodeStateMachine(float fade_speed) + : AnimationNode() + , currentAnim(nullptr) + , nextAnim(nullptr) + , fade_speed(fade_speed) + , mCurrentStateName("") + , configured(false) + { + m_weight = 1.0f; + } + void addTime(float time) + { + int i; + if (!configured) { + configure(); + configured = true; + } + for (i = 0; i < children.size(); i++) { + AnimationNode *child = children[i]; + if (fade_in.find(child) != fade_in.end()) { + Ogre::Real newWeight = + child->getWeight() + time * fade_speed; + child->setWeight(Ogre::Math::Clamp( + newWeight * m_weight, 0, m_weight)); + if (newWeight >= m_weight) + fade_in.erase(child); + } + if (fade_out.find(child) != fade_out.end()) { + Ogre::Real newWeight = + child->getWeight() - time * fade_speed; + child->setWeight(Ogre::Math::Clamp( + newWeight * m_weight, 0, m_weight)); + if (newWeight <= 0) + fade_out.erase(child); + } + } + OgreAssert(currentAnim, "bad current anim"); + if (currentAnim) + currentAnim->addTime(time); + } + void setWeight(float weight) + { + m_weight = weight; + bool enabled = weight > 0.001f; + /* do not update child state yet */ + } + void addState(AnimationNode *state) + { + const Ogre::String &name = state->getName(); + stateMap[name] = state; + state->setWeight(0); + fade_in.erase(state); + fade_out.erase(state); + std::cout << "registered state: " << name << std::endl; + } + void configure() + { + int i; + std::cout << "children: " << children.size() << std::endl; + for (i = 0; i < children.size(); i++) + addState(children[i]); + std::cout << "configure called" << std::endl; + } + void reset() + { + int i; + for (i = 0; i < children.size(); i++) { + children[i]->reset(); + } + } + void setAnimation(const Ogre::String &anim_state, bool reset = false) + { + if (!configured) { + configure(); + configured = true; + } + OgreAssert(stateMap.find(anim_state) != stateMap.end(), + "Bad animation state: " + anim_state); + std::cout << "STATE: " << anim_state << std::endl; + nextAnim = stateMap[anim_state]; + if (nextAnim == currentAnim) + return; + if (currentAnim != nullptr) { + fade_out.insert(currentAnim); + fade_in.erase(currentAnim); + } + fade_out.erase(nextAnim); + fade_in.insert(nextAnim); + nextAnim->setWeight(0); + if (reset) + nextAnim->reset(); + currentAnim = nextAnim; + mCurrentStateName = anim_state; + } + const Ogre::String &getCurrentState() const + { + return mCurrentStateName; + } +}; + +#define ANIM_FADE_SPEED \ + 7.5f // animation crossfade speed in % of full weight per second + +struct AnimationNodeOutput : AnimationNode { + float m_weight; + float m_speed; + AnimationNodeOutput() + : AnimationNode() + , m_weight(1.0f) + , m_speed(1.0f) + { + } + void addTime(float time) + { + children[0]->addTime(time * m_speed); + } + void setWeight(float weight) + { + m_weight = weight; + bool enabled = weight > 0.001f; + children[0]->setWeight(weight); + } + void reset() + { + children[0]->reset(); + } +}; + +struct AnimationSystem : AnimationNode { + AnimationSystem() + : m_builder(this) + { + } + std::unordered_map animation_list; + std::vector vanimation_list; + void add_animation(const Ogre::String &name, Animation *animation) + { + animation_list[name] = animation; + vanimation_list.push_back(animation); + } + void clear_animations() + { + animation_list.clear(); + vanimation_list.clear(); + } + struct AnimationSystemBuilder { + AnimationSystem *mAnimationSystem; + std::vector animation_nodes; + AnimationNode *parent; + std::list parent_stack; + std::unordered_map nodeMap; + std::vector animationNodeList; + AnimationSystemBuilder(AnimationSystem *animationSystem) + : mAnimationSystem(animationSystem) + { + } + AnimationSystemBuilder *output() + { + AnimationNodeOutput *onode = new AnimationNodeOutput(); + animation_nodes.push_back(onode); + parent = onode; + return this; + } + AnimationSystemBuilder * + animation(const Ogre::String &animation_name) + { + OgreAssert(parent, "bad parent"); + Animation *animation = + mAnimationSystem->animation_list[animation_name]; + AnimationNodeAnimation *onode = + new AnimationNodeAnimation(animation); + animation_nodes.push_back(onode); + parent->children.push_back(onode); + animationNodeList.push_back(onode); + return this; + } + AnimationSystemBuilder *speed(float speed, + const Ogre::String &anchor = "") + { + OgreAssert(parent, "bad parent"); + AnimationNodeSpeed *onode = + new AnimationNodeSpeed(speed); + animation_nodes.push_back(onode); + parent->children.push_back(onode); + parent_stack.push_back(parent); + parent = onode; + if (anchor.length() > 0) + nodeMap[anchor] = onode; + return this; + } + AnimationSystemBuilder * + state_machine(float fade_time = ANIM_FADE_SPEED, + const Ogre::String &anchor = "") + { + OgreAssert(parent, "bad parent"); + AnimationNodeStateMachine *onode = + new AnimationNodeStateMachine(fade_time); + animation_nodes.push_back(onode); + parent->children.push_back(onode); + parent_stack.push_back(parent); + parent = onode; + if (anchor.length() > 0) + nodeMap[anchor] = onode; + return this; + } + AnimationSystemBuilder *state(const Ogre::String &state_name) + { + OgreAssert(parent, "bad parent"); + AnimationNodeStateMachineState *onode = + new AnimationNodeStateMachineState; + animation_nodes.push_back(onode); + parent->children.push_back(onode); + parent_stack.push_back(parent); + parent = onode; + onode->setName(state_name); + return this; + } + AnimationSystemBuilder *end() + { + parent = parent_stack.back(); + parent_stack.pop_back(); + return this; + } + }; + AnimationSystemBuilder m_builder; + void addTime(float time) + { + int i; + m_builder.animation_nodes[0]->addTime(time); + for (i = 0; i < m_builder.animationNodeList.size(); i++) { + AnimationNodeAnimation *anim = + m_builder.animationNodeList[i]; + float weight = anim->getWeight(); + anim->mAnimation->increaseAccWeight(weight); + std::cout << i << " weight: " << weight << std::endl; + } + for (i = 0; i < vanimation_list.size(); i++) { + float weight = vanimation_list[i]->getAccWeight(); + vanimation_list[i]->setWeight(weight); + vanimation_list[i]->resetAccWeight(); + std::cout << i << vanimation_list[i]->getName() + << " acc weight: " << weight << std::endl; + } + } + void setWeight(float weight) + { + m_builder.animation_nodes[0]->setWeight(weight); + } + void reset() + { + m_builder.animation_nodes[0]->reset(); + } + AnimationSystemBuilder *builder() + { + m_builder.animation_nodes.reserve(8); + m_builder.parent = nullptr; + return &m_builder; + } + template T *get(const Ogre::String &name) + { + return static_cast(m_builder.nodeMap[name]); + } +}; + +struct AnimationControl { + // AnimID currentAnim; + // AnimID nextAnim; + // bool reset; + bool configured; + // Ogre::AnimationState *mAnims[NUM_ANIMS]; // master animation list + // Ogre::Animation *mSkelAnimations[NUM_ANIMS]; + // bool mFadingIn[NUM_ANIMS]; // which animations are fading in + // bool mFadingOut[NUM_ANIMS]; // which animations are fading out + // Ogre::NodeAnimationTrack *mHipsTracks[NUM_ANIMS]; + // Ogre::NodeAnimationTrack *mRootTracks[NUM_ANIMS]; + // std::vector mAnimations; + // AnimationNodeStateMachine *mStateMachine; + AnimationSystem *mAnimationSystem; +}; +struct CharacterAnimationModule { + CharacterAnimationModule(flecs::world &ecs); + // void setAnimation(AnimationControl &anim); + // void fadeAnimations(AnimationControl &anim, Ogre::Real deltaTime); +}; +} +#endif diff --git a/src/gamedata/CharacterModule.cpp b/src/gamedata/CharacterModule.cpp index f643b84..6d7fc1c 100644 --- a/src/gamedata/CharacterModule.cpp +++ b/src/gamedata/CharacterModule.cpp @@ -2,10 +2,11 @@ #include #include #include "GameData.h" -#include "CharacterModule.h" #include "WaterModule.h" #include "TerrainModule.h" #include "Components.h" +#include "CharacterAnimationModule.h" +#include "CharacterModule.h" namespace ECS { CharacterModule::CharacterModule(flecs::world &ecs) @@ -81,111 +82,6 @@ CharacterModule::CharacterModule(flecs::world &ecs) } ECS::get().modified(); }); - ecs.system("HandleAnimations") - .kind(flecs::OnUpdate) - .each([this](flecs::entity e, const CharacterBase &ch, - AnimationControl &anim) { - if (!anim.configured && ch.mSkeleton) { - int i, j; - ch.mSkeleton->setBlendMode( - Ogre::ANIMBLEND_CUMULATIVE); - Ogre::String - animNames[AnimationControl::NUM_ANIMS] = { - "idle", "walking", "running", - "treading_water", "swimming" - }; - for (i = 0; i < AnimationControl::NUM_ANIMS; - i++) { - anim.mAnims[i] = - ch.mBodyEnt->getAnimationState( - animNames[i]); - anim.mAnims[i]->setLoop(true); - anim.mAnims[i]->setEnabled(true); - anim.mAnims[i]->setWeight(0); - anim.mFadingIn[i] = false; - anim.mFadingOut[i] = false; - anim.mSkelAnimations[i] = - ch.mSkeleton->getAnimation( - animNames[i]); - for (const auto &it : - anim.mSkelAnimations[i] - ->_getNodeTrackList()) { - Ogre::NodeAnimationTrack *track = - it.second; - Ogre::String trackName = - track->getAssociatedNode() - ->getName(); - if (trackName == - "mixamorig:Hips") { - anim.mHipsTracks[i] = - track; - } else if (trackName == - "Root") { - anim.mRootTracks[i] = - track; - // mRootTracks[i]->removeAllKeyFrames(); - } - } - Ogre::Vector3 delta = - Ogre::Vector3::ZERO; - Ogre::Vector3 motion = - Ogre::Vector3::ZERO; - for (j = 0; - j < anim.mRootTracks[i] - ->getNumKeyFrames(); - j++) { - Ogre::Vector3 trans = - anim.mRootTracks[i] - ->getNodeKeyFrame( - j) - ->getTranslate(); - if (j == 0) - delta = trans; - else - delta = trans - motion; - anim.mRootTracks[i] - ->getNodeKeyFrame(j) - ->setTranslate(delta); - motion = trans; - } - } - anim.nextAnim = AnimationControl::ANIM_IDLE; - setAnimation(anim); - anim.configured = true; - } - }); - ecs.system("HandleAnimations0") - .kind(flecs::OnUpdate) - .each([this](flecs::entity e, AnimationControl &anim) { - if (anim.currentAnim != anim.nextAnim) - setAnimation(anim); - }); - ecs.system("HandleAnimations1") - .kind(flecs::OnUpdate) - .each([this](const EngineData &eng, const Input &input, - CharacterBase &ch, AnimationControl &anim) { - float delta = eng.delta; - Ogre::Real animSpeed = 1; - if (anim.currentAnim != AnimationControl::ANIM_NONE) { - if (anim.currentAnim == - AnimationControl::ANIM_WALK) - anim.mAnims[anim.currentAnim]->addTime( - delta * 1.0f); - else if (anim.currentAnim == - AnimationControl::ANIM_SWIMMING && - input.fast) - anim.mAnims[anim.currentAnim]->addTime( - delta * 20.0f); - else - anim.mAnims[anim.currentAnim]->addTime( - delta * animSpeed); - } - fadeAnimations(anim, delta); - if (!ch.mRootBone) - return; - ch.mBoneMotion = ch.mRootBone->getPosition(); - }); ecs.system() .kind(flecs::OnUpdate) .with() @@ -261,186 +157,6 @@ CharacterModule::CharacterModule(flecs::world &ecs) gr.gvelocity *= (1.0 - eng.delta); gr.velocity.y *= (1.0 - eng.delta); }); - ecs.system("HandleSwimming") - .kind(flecs::OnUpdate) - .with() - .with() - .with() - .with() - .each([this](flecs::entity e, const EngineData &eng, - const AnimationControl &anim, - const CharacterBase &ch, CharacterVelocity &gr) { - if (anim.currentAnim == - AnimationControl::ANIM_SWIMMING) { - float h = Ogre::Math::Clamp( - 0.0f - ch.mBodyNode->getPosition().y, - 0.0f, 2000.0f); - if (h > 0.05 && h < 2.0f) - gr.gvelocity.y += 0.1f * (h + 1.0f) * - h * eng.delta; - } - }); - ecs.system( - "HandleRootMotionVelocity") - .kind(flecs::OnUpdate) - .with() - .with() - .each([this](flecs::entity e, const EngineData &eng, - const CharacterBase &ch, CharacterVelocity &v) { - if (eng.delta < 0.0000001f) - return; - if (!ch.mBodyNode) - return; - Ogre::Quaternion rot = ch.mBodyNode->getOrientation(); - 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); - }); - ecs.system("HandleRootMotion") - .kind(flecs::OnUpdate) - .each([this](flecs::entity e, const EngineData &eng, - CharacterBase &ch, CharacterBody &body, - AnimationControl &anim, CharacterVelocity &v) { - if (!ch.mBodyNode) - return; - if (eng.delta < 0.0000001f) - return; - OgreAssert(eng.delta > 0.0f, "Zero delta"); - int maxPen = 0; - Ogre::Vector3 colNormal; - bool is_on_floor = false; - bool penetration = false; - if (eng.startupDelay < 0.0f) { - if (body.mController) { - Ogre::Vector3 rotMotion = - v.velocity * eng.delta; - btVector3 currentPosition = - body.mGhostObject - ->getWorldTransform() - .getOrigin(); - is_on_floor = - body.mController->isOnFloor(); - penetration = body.mController - ->isPenetrating(); - if (is_on_floor) - v.gvelocity = Ogre::Vector3( - 0.0f, 0.0f, 0.0f); - - btTransform from( - Ogre::Bullet::convert( - ch.mBodyNode - ->getOrientation()), - Ogre::Bullet::convert( - ch.mBodyNode - ->getPosition())); - ch.mBodyNode->setPosition( - ch.mBodyNode->getPosition() + - rotMotion); - ch.mBoneMotion = Ogre::Vector3(0, 0, 0); - } - } - }); - ecs.system( - "HandlePlayerAnimations") - .kind(flecs::OnUpdate) - .with() - .with() - .each([](flecs::entity e, const Input &input, - const CharacterBase &ch, AnimationControl &anim) { - if (!anim.configured) - return; - bool controls_idle = input.motion.zeroLength(); - bool anim_is_idle = - anim.currentAnim == - AnimationControl::ANIM_IDLE || - anim.currentAnim == - AnimationControl::ANIM_TREADING_WATER; - bool anim_is_walking = anim.currentAnim == - AnimationControl::ANIM_WALK; - bool anim_is_running = anim.currentAnim == - AnimationControl::ANIM_RUN; - bool anim_is_swimming = anim.currentAnim == - AnimationControl::ANIM_SWIMMING; - bool anim_is_motion = anim_is_walking || - anim_is_running || - anim_is_swimming; - if (controls_idle) { - if (anim.currentAnim == - AnimationControl::ANIM_IDLE && - ch.is_submerged) - anim.nextAnim = AnimationControl:: - ANIM_TREADING_WATER; - else if (anim.currentAnim == - AnimationControl:: - ANIM_TREADING_WATER && - !ch.is_submerged) - anim.nextAnim = - AnimationControl::ANIM_IDLE; - } - if (!controls_idle && anim_is_idle) { - anim.reset = true; - if (ch.is_submerged) { - if (input.fast) - anim.nextAnim = - AnimationControl:: - ANIM_SWIMMING; - else - anim.nextAnim = - AnimationControl:: - ANIM_SWIMMING; - } else { - if (input.fast) - anim.nextAnim = - AnimationControl::ANIM_RUN; - else - anim.nextAnim = - AnimationControl:: - ANIM_WALK; - } - } else - anim.reset = false; - if (controls_idle && anim_is_motion) - if (ch.is_submerged) - anim.nextAnim = AnimationControl:: - ANIM_TREADING_WATER; - else - anim.nextAnim = - AnimationControl::ANIM_IDLE; - else if (!controls_idle && anim_is_motion) { - if (input.fast && anim_is_walking) - anim.nextAnim = - AnimationControl::ANIM_RUN; - else if (!input.fast && anim_is_running) - anim.nextAnim = - AnimationControl::ANIM_WALK; - if ((anim_is_walking || anim_is_running) && - ch.is_submerged) { - if (input.fast) - anim.nextAnim = - AnimationControl:: - ANIM_SWIMMING; - else - anim.nextAnim = - AnimationControl:: - ANIM_SWIMMING; - } else if ((anim_is_swimming) && - !ch.is_submerged) { - if (input.fast) - anim.nextAnim = - AnimationControl::ANIM_RUN; - else - anim.nextAnim = - AnimationControl:: - ANIM_WALK; - } - } - }); #define TURN_SPEED 500.0f // character turning in degrees per second ecs.system("UpdateBody") .kind(flecs::OnUpdate) @@ -574,9 +290,6 @@ CharacterModule::CharacterModule(flecs::world &ecs) OgreAssert(body.mCollisionShape, "No collision shape"); e.add(); e.add(); - anim.currentAnim = AnimationControl::ANIM_NONE; - anim.nextAnim = AnimationControl::ANIM_NONE; - anim.reset = false; anim.configured = false; }); ecs.system( @@ -777,54 +490,6 @@ CharacterModule::CharacterModule(flecs::world &ecs) }); } -void CharacterModule::setAnimation(AnimationControl &anim) -{ - OgreAssert(anim.nextAnim >= 0 && - anim.nextAnim < AnimationControl::NUM_ANIMS, - "Bad animation"); - if (anim.currentAnim != AnimationControl::ANIM_NONE) { - anim.mFadingIn[anim.currentAnim] = false; - anim.mFadingOut[anim.currentAnim] = true; - } - if (anim.nextAnim != AnimationControl::ANIM_NONE) { - anim.mAnims[anim.nextAnim]->setEnabled(true); - anim.mAnims[anim.nextAnim]->setWeight(0); - anim.mFadingOut[anim.nextAnim] = false; - anim.mFadingIn[anim.nextAnim] = true; - if (anim.reset) - anim.mAnims[anim.nextAnim]->setTimePosition(0); - } - anim.currentAnim = anim.nextAnim; - anim.reset = false; -} -#define ANIM_FADE_SPEED \ - 7.5f // animation crossfade speed in % of full weight per second - -void CharacterModule::fadeAnimations(AnimationControl &anim, Ogre::Real delta) -{ - int i; - for (i = 0; i < AnimationControl::NUM_ANIMS; i++) { - if (anim.mFadingIn[i]) { - // slowly fade this animation in until it has full weight - Ogre::Real newWeight = anim.mAnims[i]->getWeight() + - delta * ANIM_FADE_SPEED; - anim.mAnims[i]->setWeight( - Ogre::Math::Clamp(newWeight, 0, 1)); - if (newWeight >= 1) - anim.mFadingIn[i] = false; - } else if (anim.mFadingOut[i]) { - // slowly fade this animation out until it has no weight, and then disable it - Ogre::Real newWeight = anim.mAnims[i]->getWeight() - - delta * ANIM_FADE_SPEED; - anim.mAnims[i]->setWeight( - Ogre::Math::Clamp(newWeight, 0, 1)); - if (newWeight <= 0) { - anim.mAnims[i]->setEnabled(false); - anim.mFadingOut[i] = false; - } - } - } -} void CharacterModule::updateCameraGoal(Camera &camera, Ogre::Real deltaYaw, Ogre::Real deltaPitch, Ogre::Real deltaZoom) diff --git a/src/gamedata/CharacterModule.h b/src/gamedata/CharacterModule.h index daa24dc..ca1b3cf 100644 --- a/src/gamedata/CharacterModule.h +++ b/src/gamedata/CharacterModule.h @@ -45,31 +45,8 @@ struct CharacterVelocity { Ogre::Vector3 gvelocity; Ogre::Vector3 velocity; }; -struct AnimationControl { - enum AnimID { - ANIM_IDLE = 0, - ANIM_WALK, - ANIM_RUN, - ANIM_TREADING_WATER, - ANIM_SWIMMING, - NUM_ANIMS, - ANIM_NONE = NUM_ANIMS - }; - AnimID currentAnim; - AnimID nextAnim; - bool reset; - bool configured; - Ogre::AnimationState *mAnims[NUM_ANIMS]; // master animation list - Ogre::Animation *mSkelAnimations[NUM_ANIMS]; - bool mFadingIn[NUM_ANIMS]; // which animations are fading in - bool mFadingOut[NUM_ANIMS]; // which animations are fading out - Ogre::NodeAnimationTrack *mHipsTracks[NUM_ANIMS]; - Ogre::NodeAnimationTrack *mRootTracks[NUM_ANIMS]; -}; struct CharacterModule { CharacterModule(flecs::world &ecs); - void setAnimation(AnimationControl &anim); - void fadeAnimations(AnimationControl &anim, Ogre::Real deltaTime); void updateCameraGoal(Camera &camera, Ogre::Real deltaYaw, Ogre::Real deltaPitch, Ogre::Real deltaZoom); }; diff --git a/src/gamedata/GameData.cpp b/src/gamedata/GameData.cpp index 95a07ce..3bd216a 100644 --- a/src/gamedata/GameData.cpp +++ b/src/gamedata/GameData.cpp @@ -11,6 +11,7 @@ #include "WorldMapModule.h" #include "BoatModule.h" #include "EventTriggerModule.h" +#include "CharacterAnimationModule.h" namespace ECS { @@ -47,6 +48,7 @@ void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world, ecs.import (); ecs.import (); ecs.import (); + ecs.import (); ecs.system("UpdateDelta") .kind(flecs::OnUpdate) diff --git a/src/sceneloader/CMakeLists.txt b/src/sceneloader/CMakeLists.txt index 5567b7b..b81b29b 100644 --- a/src/sceneloader/CMakeLists.txt +++ b/src/sceneloader/CMakeLists.txt @@ -1,6 +1,6 @@ project(sceneloader) add_library(sceneloader loader.cpp) target_include_directories(sceneloader PUBLIC .) -target_link_libraries(sceneloader PUBLIC OgreMain PRIVATE pugixml) +target_link_libraries(sceneloader PUBLIC OgreMain PRIVATE pugixml GameData) target_link_libraries(sceneloader PUBLIC OgreTerrain) diff --git a/src/sceneloader/loader.cpp b/src/sceneloader/loader.cpp index 901a70a..d2ce170 100644 --- a/src/sceneloader/loader.cpp +++ b/src/sceneloader/loader.cpp @@ -3,6 +3,8 @@ #include #include #include +#include "GameData.h" +#include "EventTriggerModule.h" #include "loader.h" using namespace Ogre; @@ -120,35 +122,6 @@ static ColourValue parseColour(pugi::xml_node &XMLNode) 1); } -struct SceneCodec : public Codec { - String magicNumberToFileExt(const char *magicNumberPtr, - size_t maxbytes) const override - { - return ""; - } - String getType() const override - { - return "scene"; - } - void decode(const DataStreamPtr &stream, - const Any &output) const override - { - DataStreamPtr _stream(stream); - SceneLoader loader; - loader.load(_stream, - ResourceGroupManager::getSingleton() - .getWorldResourceGroupName(), - any_cast(output), 0); - } - - void encodeToFile(const Any &input, - const String &outFileName) const override - { - SceneLoader loader; - loader.exportScene(any_cast(input), outFileName); - } -}; - SceneLoader::SceneLoader() : mSceneMgr(0) , mBackgroundColour(ColourValue::Black) @@ -160,12 +133,12 @@ SceneLoader::~SceneLoader() } void SceneLoader::load(DataStreamPtr &stream, const String &groupName, - SceneNode *rootNode, int counter) + SceneNode *rootNode, flecs::entity e) { m_sGroupName = groupName; mSceneMgr = rootNode->getCreator(); mNamePrefix = rootNode->getName(); - this->counter = counter; + this->counter = (int)e.raw_id(); if (counter >= 0) { if (mNamePrefix.length() > 0) mNamePrefix += "/"; @@ -173,6 +146,7 @@ void SceneLoader::load(DataStreamPtr &stream, const String &groupName, } if (mNamePrefix.length() > 0) mNamePrefix += "/"; + base_e = e; pugi::xml_document XMLDoc; // character type defaults to char @@ -571,6 +545,23 @@ void SceneLoader::processNode(pugi::xml_node &XMLNode, SceneNode *pParent) // Process node animations (?) if (auto pElement = XMLNode.child("animations")) processNodeAnimations(pElement, pNode); + Ogre::Any triggerAny = + pNode->getUserObjectBindings().getUserAny("trigger"); + if (triggerAny.has_value()) { + flecs::entity e = ECS::get().entity().child_of(base_e); + Ogre::String event = Ogre::any_cast(triggerAny); + float h = 2.0f, r = 3.0f; + Ogre::Any anyh = pNode->getUserObjectBindings().getUserAny( + "trigger_height"); + if (anyh.has_value()) + h = Ogre::any_cast(anyh); + Ogre::Any anyr = pNode->getUserObjectBindings().getUserAny( + "trigger_radius"); + if (anyr.has_value()) + r = Ogre::any_cast(anyr); + e.set( + { pNode, Ogre::Vector3(0, 0, 0), h, r, event }); + } } void SceneLoader::processLookTarget(pugi::xml_node &XMLNode, SceneNode *pParent) diff --git a/src/sceneloader/loader.h b/src/sceneloader/loader.h index b6394f8..9d5e621 100644 --- a/src/sceneloader/loader.h +++ b/src/sceneloader/loader.h @@ -6,6 +6,7 @@ #include #include #include +#include class SceneLoader { public: @@ -13,7 +14,7 @@ public: virtual ~SceneLoader(); void load(Ogre::DataStreamPtr &stream, const Ogre::String &groupName, - Ogre::SceneNode *rootNode, int counter); + Ogre::SceneNode *rootNode, flecs::entity e); void exportScene(Ogre::SceneNode *rootNode, const Ogre::String &outFileName); @@ -74,6 +75,7 @@ protected: Ogre::ColourValue mBackgroundColour; Ogre::String mNamePrefix; int counter; + flecs::entity base_e; }; #endif