mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 23:23:52 +00:00
Native animated containers support (feature #4730)
This commit is contained in:
parent
0d5876f4bb
commit
a53333c3d5
15 changed files with 126 additions and 0 deletions
|
@ -14,6 +14,7 @@
|
||||||
Feature #3442: Default values for fallbacks from ini file
|
Feature #3442: Default values for fallbacks from ini file
|
||||||
Feature #3610: Option to invert X axis
|
Feature #3610: Option to invert X axis
|
||||||
Feature #4673: Weapon sheathing
|
Feature #4673: Weapon sheathing
|
||||||
|
Feature #4730: Native animated containers support
|
||||||
Task #4686: Upgrade media decoder to a more current FFmpeg API
|
Task #4686: Upgrade media decoder to a more current FFmpeg API
|
||||||
|
|
||||||
0.45.0
|
0.45.0
|
||||||
|
|
|
@ -237,6 +237,9 @@ namespace MWBase
|
||||||
|
|
||||||
virtual float getActorsProcessingRange() const = 0;
|
virtual float getActorsProcessingRange() const = 0;
|
||||||
|
|
||||||
|
virtual bool onOpen(const MWWorld::Ptr& ptr) = 0;
|
||||||
|
virtual void onClose(const MWWorld::Ptr& ptr) = 0;
|
||||||
|
|
||||||
/// Check if the target actor was detected by an observer
|
/// Check if the target actor was detected by an observer
|
||||||
/// If the observer is a non-NPC, check all actors in AI processing distance as observers
|
/// If the observer is a non-NPC, check all actors in AI processing distance as observers
|
||||||
virtual bool isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer) = 0;
|
virtual bool isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer) = 0;
|
||||||
|
|
|
@ -303,6 +303,8 @@ namespace MWBase
|
||||||
///< Queues movement for \a ptr (in local space), to be applied in the next call to
|
///< Queues movement for \a ptr (in local space), to be applied in the next call to
|
||||||
/// doPhysics.
|
/// doPhysics.
|
||||||
|
|
||||||
|
virtual void updateAnimatedCollisionShape(const MWWorld::Ptr &ptr) = 0;
|
||||||
|
|
||||||
virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2, int mask) = 0;
|
virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2, int mask) = 0;
|
||||||
///< cast a Ray and return true if there is an object in the ray path.
|
///< cast a Ray and return true if there is an object in the ray path.
|
||||||
|
|
||||||
|
|
|
@ -162,6 +162,8 @@ namespace MWGui
|
||||||
|
|
||||||
if (mModel)
|
if (mModel)
|
||||||
mModel->onClose();
|
mModel->onClose();
|
||||||
|
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->onClose(mPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
|
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
|
||||||
|
|
|
@ -419,6 +419,43 @@ void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CharacterController::onOpen()
|
||||||
|
{
|
||||||
|
if (mPtr.getTypeName() == typeid(ESM::Container).name())
|
||||||
|
{
|
||||||
|
if (!mAnimation->hasAnimation("containeropen"))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (mAnimation->isPlaying("containeropen"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mAnimation->isPlaying("containerclose"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mAnimation->play("containeropen", Priority_Persistent, MWRender::Animation::BlendMask_All, false, 1.0f, "start", "stop", 0.f, 0);
|
||||||
|
if (mAnimation->isPlaying("containeropen"))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CharacterController::onClose()
|
||||||
|
{
|
||||||
|
if (mPtr.getTypeName() == typeid(ESM::Container).name())
|
||||||
|
{
|
||||||
|
if (!mAnimation->hasAnimation("containerclose"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
float complete, startPoint = 0.f;
|
||||||
|
bool animPlaying = mAnimation->getInfo("containeropen", &complete);
|
||||||
|
if (animPlaying)
|
||||||
|
startPoint = 1.f - complete;
|
||||||
|
|
||||||
|
mAnimation->play("containerclose", Priority_Persistent, MWRender::Animation::BlendMask_All, false, 1.0f, "start", "stop", startPoint, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CharacterController::refreshMovementAnims(const WeaponInfo* weap, CharacterState movement, CharacterState& idle, bool force)
|
void CharacterController::refreshMovementAnims(const WeaponInfo* weap, CharacterState movement, CharacterState& idle, bool force)
|
||||||
{
|
{
|
||||||
if (movement == mMovementState && idle == mIdleState && !force)
|
if (movement == mMovementState && idle == mIdleState && !force)
|
||||||
|
@ -1079,6 +1116,8 @@ void CharacterController::handleTextKey(const std::string &groupname, const std:
|
||||||
|
|
||||||
else if (groupname == "shield" && evt.compare(off, len, "block hit") == 0)
|
else if (groupname == "shield" && evt.compare(off, len, "block hit") == 0)
|
||||||
mPtr.getClass().block(mPtr);
|
mPtr.getClass().block(mPtr);
|
||||||
|
else if (groupname == "containeropen" && evt.compare(off, len, "loot") == 0)
|
||||||
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container, mPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterController::updatePtr(const MWWorld::Ptr &ptr)
|
void CharacterController::updatePtr(const MWWorld::Ptr &ptr)
|
||||||
|
|
|
@ -259,6 +259,9 @@ public:
|
||||||
|
|
||||||
void update(float duration, bool animationOnly=false);
|
void update(float duration, bool animationOnly=false);
|
||||||
|
|
||||||
|
bool onOpen();
|
||||||
|
void onClose();
|
||||||
|
|
||||||
void persistAnimationState();
|
void persistAnimationState();
|
||||||
void unpersistAnimationState();
|
void unpersistAnimationState();
|
||||||
|
|
||||||
|
|
|
@ -845,6 +845,20 @@ namespace MWMechanics
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MechanicsManager::onOpen(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
if(ptr.getClass().isActor())
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return mObjects.onOpen(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MechanicsManager::onClose(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
if(!ptr.getClass().isActor())
|
||||||
|
mObjects.onClose(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
void MechanicsManager::persistAnimationStates()
|
void MechanicsManager::persistAnimationStates()
|
||||||
{
|
{
|
||||||
mActors.persistAnimationStates();
|
mActors.persistAnimationStates();
|
||||||
|
|
|
@ -182,6 +182,9 @@ namespace MWMechanics
|
||||||
|
|
||||||
virtual void playerLoaded() override;
|
virtual void playerLoaded() override;
|
||||||
|
|
||||||
|
virtual bool onOpen(const MWWorld::Ptr& ptr) override;
|
||||||
|
virtual void onClose(const MWWorld::Ptr& ptr) override;
|
||||||
|
|
||||||
virtual int countSavedGameRecords() const override;
|
virtual int countSavedGameRecords() const override;
|
||||||
|
|
||||||
virtual void write (ESM::ESMWriter& writer, Loading::Listener& listener) const override;
|
virtual void write (ESM::ESMWriter& writer, Loading::Listener& listener) const override;
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
#include "objects.hpp"
|
#include "objects.hpp"
|
||||||
|
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
#include <components/esm/loadcont.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "movement.hpp"
|
#include "movement.hpp"
|
||||||
|
@ -77,6 +79,40 @@ void Objects::update(float duration, bool paused)
|
||||||
for(PtrControllerMap::iterator iter(mObjects.begin());iter != mObjects.end();++iter)
|
for(PtrControllerMap::iterator iter(mObjects.begin());iter != mObjects.end();++iter)
|
||||||
iter->second->update(duration);
|
iter->second->update(duration);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We still should play container opening animation in the Container GUI mode.
|
||||||
|
MWGui::GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode();
|
||||||
|
if(mode != MWGui::GM_Container)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(PtrControllerMap::iterator iter(mObjects.begin());iter != mObjects.end();++iter)
|
||||||
|
{
|
||||||
|
if (iter->first.getTypeName() != typeid(ESM::Container).name())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (iter->second->isAnimPlaying("containeropen"))
|
||||||
|
{
|
||||||
|
iter->second->update(duration);
|
||||||
|
MWBase::Environment::get().getWorld()->updateAnimatedCollisionShape(iter->first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Objects::onOpen(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
PtrControllerMap::iterator iter = mObjects.find(ptr);
|
||||||
|
if(iter != mObjects.end())
|
||||||
|
return iter->second->onOpen();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Objects::onClose(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
PtrControllerMap::iterator iter = mObjects.find(ptr);
|
||||||
|
if(iter != mObjects.end())
|
||||||
|
iter->second->onClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Objects::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number, bool persist)
|
bool Objects::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number, bool persist)
|
||||||
|
|
|
@ -38,6 +38,9 @@ namespace MWMechanics
|
||||||
void update(float duration, bool paused);
|
void update(float duration, bool paused);
|
||||||
///< Update object animations
|
///< Update object animations
|
||||||
|
|
||||||
|
bool onOpen(const MWWorld::Ptr& ptr);
|
||||||
|
void onClose(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
bool playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number, bool persist=false);
|
bool playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number, bool persist=false);
|
||||||
void skipAnimation(const MWWorld::Ptr& ptr);
|
void skipAnimation(const MWWorld::Ptr& ptr);
|
||||||
void persistAnimationStates();
|
void persistAnimationStates();
|
||||||
|
|
|
@ -1363,6 +1363,13 @@ namespace MWPhysics
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhysicsSystem::updateAnimatedCollisionShape(const MWWorld::Ptr& object)
|
||||||
|
{
|
||||||
|
ObjectMap::iterator found = mObjects.find(object);
|
||||||
|
if (found != mObjects.end())
|
||||||
|
found->second->animateCollisionShapes(mCollisionWorld);
|
||||||
|
}
|
||||||
|
|
||||||
void PhysicsSystem::debugDraw()
|
void PhysicsSystem::debugDraw()
|
||||||
{
|
{
|
||||||
if (mDebugDrawer.get())
|
if (mDebugDrawer.get())
|
||||||
|
|
|
@ -178,6 +178,8 @@ namespace MWPhysics
|
||||||
|
|
||||||
bool isOnSolidGround (const MWWorld::Ptr& actor) const;
|
bool isOnSolidGround (const MWWorld::Ptr& actor) const;
|
||||||
|
|
||||||
|
void updateAnimatedCollisionShape(const MWWorld::Ptr& object);
|
||||||
|
|
||||||
template <class Function>
|
template <class Function>
|
||||||
void forEachAnimatedObject(Function&& function) const
|
void forEachAnimatedObject(Function&& function) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "actionopen.hpp"
|
#include "actionopen.hpp"
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/disease.hpp"
|
#include "../mwmechanics/disease.hpp"
|
||||||
|
@ -20,6 +21,9 @@ namespace MWWorld
|
||||||
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!MWBase::Environment::get().getMechanicsManager()->onOpen(getTarget()))
|
||||||
|
return;
|
||||||
|
|
||||||
MWMechanics::diseaseContact(actor, getTarget());
|
MWMechanics::diseaseContact(actor, getTarget());
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container, getTarget());
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container, getTarget());
|
||||||
|
|
|
@ -1527,6 +1527,11 @@ namespace MWWorld
|
||||||
mPhysics->queueObjectMovement(ptr, velocity);
|
mPhysics->queueObjectMovement(ptr, velocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::updateAnimatedCollisionShape(const Ptr &ptr)
|
||||||
|
{
|
||||||
|
mPhysics->updateAnimatedCollisionShape(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
void World::doPhysics(float duration)
|
void World::doPhysics(float duration)
|
||||||
{
|
{
|
||||||
mPhysics->stepSimulation(duration);
|
mPhysics->stepSimulation(duration);
|
||||||
|
|
|
@ -412,6 +412,8 @@ namespace MWWorld
|
||||||
///< Queues movement for \a ptr (in local space), to be applied in the next call to
|
///< Queues movement for \a ptr (in local space), to be applied in the next call to
|
||||||
/// doPhysics.
|
/// doPhysics.
|
||||||
|
|
||||||
|
void updateAnimatedCollisionShape(const Ptr &ptr) override;
|
||||||
|
|
||||||
bool castRay (float x1, float y1, float z1, float x2, float y2, float z2, int mask) override;
|
bool castRay (float x1, float y1, float z1, float x2, float y2, float z2, int mask) override;
|
||||||
///< cast a Ray and return true if there is an object in the ray path.
|
///< cast a Ray and return true if there is an object in the ray path.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue