1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-08 09:37:53 +00:00
OpenMW/apps/openmw/mwworld/refdata.cpp
MiroslavR 55e670c5fe Fix animation state not saving
References with animation state changed but otherwise identical to their content file counterparts
were previously considered unchanged and thus dropped while saving.
2016-09-15 16:11:54 +02:00

289 lines
6.4 KiB
C++

#include "refdata.hpp"
#include <components/esm/objectstate.hpp>
#include "customdata.hpp"
#include "cellstore.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
namespace
{
enum RefDataFlags
{
Flag_SuppressActivate = 1, // If set, activation will be suppressed and redirected to the OnActivate flag, which can then be handled by a script.
Flag_OnActivate = 2
};
}
namespace MWWorld
{
void RefData::copy (const RefData& refData)
{
mBaseNode = refData.mBaseNode;
mLocals = refData.mLocals;
mEnabled = refData.mEnabled;
mCount = refData.mCount;
mPosition = refData.mPosition;
mChanged = refData.mChanged;
mDeletedByContentFile = refData.mDeletedByContentFile;
mFlags = refData.mFlags;
mAnimationState = refData.mAnimationState;
mCustomData = refData.mCustomData ? refData.mCustomData->clone() : 0;
}
void RefData::cleanup()
{
mBaseNode = 0;
delete mCustomData;
mCustomData = 0;
}
RefData::RefData()
: mBaseNode(0), mDeletedByContentFile(false), mEnabled (true), mCount (1), mCustomData (0), mChanged(false), mFlags(0)
{
for (int i=0; i<3; ++i)
{
mPosition.pos[i] = 0;
mPosition.rot[i] = 0;
}
}
RefData::RefData (const ESM::CellRef& cellRef)
: mBaseNode(0), mDeletedByContentFile(false), mEnabled (true),
mCount (1), mPosition (cellRef.mPos),
mCustomData (0),
mChanged(false), mFlags(0) // Loading from ESM/ESP files -> assume unchanged
{
}
RefData::RefData (const ESM::ObjectState& objectState, bool deletedByContentFile)
: mBaseNode(0), mDeletedByContentFile(deletedByContentFile),
mEnabled (objectState.mEnabled != 0),
mCount (objectState.mCount),
mPosition (objectState.mPosition),
mAnimationState(objectState.mAnimationState),
mCustomData (0),
mChanged(true), mFlags(objectState.mFlags) // Loading from a savegame -> assume changed
{
// "Note that the ActivationFlag_UseEnabled is saved to the reference,
// which will result in permanently suppressed activation if the reference script is removed.
// This occurred when removing the animated containers mod, and the fix in MCP is to reset UseEnabled to true on loading a game."
mFlags &= (~Flag_SuppressActivate);
}
RefData::RefData (const RefData& refData)
: mBaseNode(0), mCustomData (0)
{
try
{
copy (refData);
}
catch (...)
{
cleanup();
throw;
}
}
void RefData::write (ESM::ObjectState& objectState, const std::string& scriptId) const
{
objectState.mHasLocals = mLocals.write (objectState.mLocals, scriptId);
objectState.mEnabled = mEnabled;
objectState.mCount = mCount;
objectState.mPosition = mPosition;
objectState.mFlags = mFlags;
objectState.mAnimationState = mAnimationState;
}
RefData& RefData::operator= (const RefData& refData)
{
try
{
cleanup();
copy (refData);
}
catch (...)
{
cleanup();
throw;
}
return *this;
}
RefData::~RefData()
{
try
{
cleanup();
}
catch (...)
{}
}
void RefData::setBaseNode(SceneUtil::PositionAttitudeTransform *base)
{
mBaseNode = base;
}
SceneUtil::PositionAttitudeTransform* RefData::getBaseNode()
{
return mBaseNode;
}
const SceneUtil::PositionAttitudeTransform* RefData::getBaseNode() const
{
return mBaseNode;
}
int RefData::getCount() const
{
return mCount;
}
void RefData::setLocals (const ESM::Script& script)
{
if (mLocals.configure (script) && !mLocals.isEmpty())
mChanged = true;
}
void RefData::setCount (int count)
{
if(count == 0)
MWBase::Environment::get().getWorld()->removeRefScript(this);
mChanged = true;
mCount = count;
}
void RefData::setDeletedByContentFile(bool deleted)
{
mDeletedByContentFile = deleted;
}
bool RefData::isDeleted() const
{
return mDeletedByContentFile || mCount == 0;
}
bool RefData::isDeletedByContentFile() const
{
return mDeletedByContentFile;
}
MWScript::Locals& RefData::getLocals()
{
return mLocals;
}
bool RefData::isEnabled() const
{
return mEnabled;
}
void RefData::enable()
{
if (!mEnabled)
{
mChanged = true;
mEnabled = true;
}
}
void RefData::disable()
{
if (mEnabled)
{
mChanged = true;
mEnabled = false;
}
}
void RefData::setPosition(const ESM::Position& pos)
{
mChanged = true;
mPosition = pos;
}
const ESM::Position& RefData::getPosition() const
{
return mPosition;
}
void RefData::setCustomData (CustomData *data)
{
mChanged = true; // We do not currently track CustomData, so assume anything with a CustomData is changed
delete mCustomData;
mCustomData = data;
}
CustomData *RefData::getCustomData()
{
return mCustomData;
}
const CustomData *RefData::getCustomData() const
{
return mCustomData;
}
bool RefData::hasChanged() const
{
return mChanged || !mAnimationState.empty();
}
bool RefData::activate()
{
if (!(mFlags & Flag_SuppressActivate))
return true;
else
{
mFlags |= Flag_OnActivate;
return false;
}
}
bool RefData::onActivate()
{
mFlags |= Flag_SuppressActivate;
if (mFlags & Flag_OnActivate)
{
mFlags &= (~Flag_OnActivate);
return true;
}
return false;
}
bool RefData::activateByScript()
{
if (mFlags & Flag_SuppressActivate)
{
mFlags &= (~Flag_SuppressActivate);
return true;
}
else
return false;
}
const ESM::AnimationState& RefData::getAnimationState() const
{
return mAnimationState;
}
ESM::AnimationState& RefData::getAnimationState()
{
return mAnimationState;
}
}