Native animated containers support (feature #4730)

pull/2053/head
Andrei Kortunov 6 years ago
parent 0d5876f4bb
commit a53333c3d5

@ -14,6 +14,7 @@
Feature #3442: Default values for fallbacks from ini file
Feature #3610: Option to invert X axis
Feature #4673: Weapon sheathing
Feature #4730: Native animated containers support
Task #4686: Upgrade media decoder to a more current FFmpeg API
0.45.0

@ -237,6 +237,9 @@ namespace MWBase
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
/// 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;

@ -303,6 +303,8 @@ namespace MWBase
///< Queues movement for \a ptr (in local space), to be applied in the next call to
/// 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;
///< cast a Ray and return true if there is an object in the ray path.

@ -162,6 +162,8 @@ namespace MWGui
if (mModel)
mModel->onClose();
MWBase::Environment::get().getMechanicsManager()->onClose(mPtr);
}
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)
{
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)
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)

@ -259,6 +259,9 @@ public:
void update(float duration, bool animationOnly=false);
bool onOpen();
void onClose();
void persistAnimationState();
void unpersistAnimationState();

@ -845,6 +845,20 @@ namespace MWMechanics
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()
{
mActors.persistAnimationStates();

@ -182,6 +182,9 @@ namespace MWMechanics
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 void write (ESM::ESMWriter& writer, Loading::Listener& listener) const override;

@ -1,8 +1,10 @@
#include "objects.hpp"
#include <components/debug/debuglog.hpp>
#include <components/esm/loadcont.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.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)
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)

@ -38,6 +38,9 @@ namespace MWMechanics
void update(float duration, bool paused);
///< 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);
void skipAnimation(const MWWorld::Ptr& ptr);
void persistAnimationStates();

@ -1363,6 +1363,13 @@ namespace MWPhysics
#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()
{
if (mDebugDrawer.get())

@ -178,6 +178,8 @@ namespace MWPhysics
bool isOnSolidGround (const MWWorld::Ptr& actor) const;
void updateAnimatedCollisionShape(const MWWorld::Ptr& object);
template <class Function>
void forEachAnimatedObject(Function&& function) const
{

@ -1,6 +1,7 @@
#include "actionopen.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwmechanics/disease.hpp"
@ -20,6 +21,9 @@ namespace MWWorld
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return;
if (!MWBase::Environment::get().getMechanicsManager()->onOpen(getTarget()))
return;
MWMechanics::diseaseContact(actor, getTarget());
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container, getTarget());

@ -1527,6 +1527,11 @@ namespace MWWorld
mPhysics->queueObjectMovement(ptr, velocity);
}
void World::updateAnimatedCollisionShape(const Ptr &ptr)
{
mPhysics->updateAnimatedCollisionShape(ptr);
}
void World::doPhysics(float 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
/// doPhysics.
void updateAnimatedCollisionShape(const Ptr &ptr) 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.

Loading…
Cancel
Save