mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-30 13:15:32 +00:00
Merge pull request #2053 from akortunov/animatedContainers
Native animated containers support
This commit is contained in:
commit
6d7aacab5e
15 changed files with 126 additions and 0 deletions
|
@ -15,6 +15,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…
Reference in a new issue