Fast version of dynamic_cast for MWClass

openmw-38
scrawl 9 years ago
parent db71634a2d
commit cd4a1ffd16

@ -27,23 +27,26 @@
#include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/npcstats.hpp"
namespace namespace MWClass
{ {
struct ContainerCustomData : public MWWorld::CustomData class ContainerCustomData : public MWWorld::CustomData
{ {
public:
MWWorld::ContainerStore mContainerStore; MWWorld::ContainerStore mContainerStore;
virtual MWWorld::CustomData *clone() const; virtual MWWorld::CustomData *clone() const;
virtual ContainerCustomData& asContainerCustomData()
{
return *this;
}
}; };
MWWorld::CustomData *ContainerCustomData::clone() const MWWorld::CustomData *ContainerCustomData::clone() const
{ {
return new ContainerCustomData (*this); return new ContainerCustomData (*this);
} }
}
namespace MWClass
{
std::string Container::getId (const MWWorld::Ptr& ptr) const std::string Container::getId (const MWWorld::Ptr& ptr) const
{ {
return ptr.get<ESM::Container>()->mBase->mId; return ptr.get<ESM::Container>()->mBase->mId;
@ -202,7 +205,7 @@ namespace MWClass
{ {
ensureCustomData (ptr); ensureCustomData (ptr);
return dynamic_cast<ContainerCustomData&> (*ptr.getRefData().getCustomData()).mContainerStore; return ptr.getRefData().getCustomData()->asContainerCustomData().mContainerStore;
} }
std::string Container::getScript (const MWWorld::Ptr& ptr) const std::string Container::getScript (const MWWorld::Ptr& ptr) const

@ -40,14 +40,29 @@
namespace namespace
{ {
struct CreatureCustomData : public MWWorld::CustomData bool isFlagBitSet(const MWWorld::Ptr &ptr, ESM::Creature::Flags bitMask)
{
return (ptr.get<ESM::Creature>()->mBase->mFlags & bitMask) != 0;
}
}
namespace MWClass
{
class CreatureCustomData : public MWWorld::CustomData
{ {
public:
MWMechanics::CreatureStats mCreatureStats; MWMechanics::CreatureStats mCreatureStats;
MWWorld::ContainerStore* mContainerStore; // may be InventoryStore for some creatures MWWorld::ContainerStore* mContainerStore; // may be InventoryStore for some creatures
MWMechanics::Movement mMovement; MWMechanics::Movement mMovement;
virtual MWWorld::CustomData *clone() const; virtual MWWorld::CustomData *clone() const;
virtual CreatureCustomData& asCreatureCustomData()
{
return *this;
}
CreatureCustomData() : mContainerStore(0) {} CreatureCustomData() : mContainerStore(0) {}
virtual ~CreatureCustomData() { delete mContainerStore; } virtual ~CreatureCustomData() { delete mContainerStore; }
}; };
@ -59,14 +74,6 @@ namespace
return cloned; return cloned;
} }
bool isFlagBitSet(const MWWorld::Ptr &ptr, ESM::Creature::Flags bitMask)
{
return (ptr.get<ESM::Creature>()->mBase->mFlags & bitMask) != 0;
}
}
namespace MWClass
{
const Creature::GMST& Creature::getGmst() const Creature::GMST& Creature::getGmst()
{ {
static GMST gmst; static GMST gmst;
@ -193,7 +200,7 @@ namespace MWClass
{ {
ensureCustomData (ptr); ensureCustomData (ptr);
return dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData()).mCreatureStats; return ptr.getRefData().getCustomData()->asCreatureCustomData().mCreatureStats;
} }
@ -421,7 +428,7 @@ namespace MWClass
{ {
ensureCustomData (ptr); ensureCustomData (ptr);
return *dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData()).mContainerStore; return *ptr.getRefData().getCustomData()->asCreatureCustomData().mContainerStore;
} }
MWWorld::InventoryStore& Creature::getInventoryStore(const MWWorld::Ptr &ptr) const MWWorld::InventoryStore& Creature::getInventoryStore(const MWWorld::Ptr &ptr) const
@ -511,7 +518,7 @@ namespace MWClass
{ {
ensureCustomData (ptr); ensureCustomData (ptr);
return dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData()).mMovement; return ptr.getRefData().getCustomData()->asCreatureCustomData().mMovement;
} }
MWGui::ToolTipInfo Creature::getToolTipInfo (const MWWorld::Ptr& ptr) const MWGui::ToolTipInfo Creature::getToolTipInfo (const MWWorld::Ptr& ptr) const
@ -711,7 +718,7 @@ namespace MWClass
else else
ensureCustomData(ptr); // in openmw 0.30 savegames not all state was saved yet, so need to load it regardless. ensureCustomData(ptr); // in openmw 0.30 savegames not all state was saved yet, so need to load it regardless.
CreatureCustomData& customData = dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData()); CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData();
customData.mContainerStore->readState (state2.mInventory); customData.mContainerStore->readState (state2.mInventory);
customData.mCreatureStats.readState (state2.mCreatureStats); customData.mCreatureStats.readState (state2.mCreatureStats);
@ -730,7 +737,7 @@ namespace MWClass
ensureCustomData (ptr); ensureCustomData (ptr);
CreatureCustomData& customData = dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData()); CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData();
customData.mContainerStore->writeState (state2.mInventory); customData.mContainerStore->writeState (state2.mInventory);
customData.mCreatureStats.writeState (state2.mCreatureStats); customData.mCreatureStats.writeState (state2.mCreatureStats);

@ -7,25 +7,28 @@
#include "../mwworld/customdata.hpp" #include "../mwworld/customdata.hpp"
namespace namespace MWClass
{ {
struct CreatureLevListCustomData : public MWWorld::CustomData class CreatureLevListCustomData : public MWWorld::CustomData
{ {
public:
// actorId of the creature we spawned // actorId of the creature we spawned
int mSpawnActorId; int mSpawnActorId;
bool mSpawn; // Should a new creature be spawned? bool mSpawn; // Should a new creature be spawned?
virtual MWWorld::CustomData *clone() const; virtual MWWorld::CustomData *clone() const;
virtual CreatureLevListCustomData& asCreatureLevListCustomData()
{
return *this;
}
}; };
MWWorld::CustomData *CreatureLevListCustomData::clone() const MWWorld::CustomData *CreatureLevListCustomData::clone() const
{ {
return new CreatureLevListCustomData (*this); return new CreatureLevListCustomData (*this);
} }
}
namespace MWClass
{
std::string CreatureLevList::getId (const MWWorld::Ptr& ptr) const std::string CreatureLevList::getId (const MWWorld::Ptr& ptr) const
{ {
return ptr.get<ESM::CreatureLevList>()->mBase->mId; return ptr.get<ESM::CreatureLevList>()->mBase->mId;
@ -40,7 +43,7 @@ namespace MWClass
{ {
ensureCustomData(ptr); ensureCustomData(ptr);
CreatureLevListCustomData& customData = dynamic_cast<CreatureLevListCustomData&> (*ptr.getRefData().getCustomData()); CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
customData.mSpawn = true; customData.mSpawn = true;
} }
@ -55,7 +58,7 @@ namespace MWClass
{ {
ensureCustomData(ptr); ensureCustomData(ptr);
CreatureLevListCustomData& customData = dynamic_cast<CreatureLevListCustomData&> (*ptr.getRefData().getCustomData()); CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
if (!customData.mSpawn) if (!customData.mSpawn)
return; return;
@ -104,7 +107,7 @@ namespace MWClass
const ESM::CreatureLevListState& state2 = dynamic_cast<const ESM::CreatureLevListState&> (state); const ESM::CreatureLevListState& state2 = dynamic_cast<const ESM::CreatureLevListState&> (state);
ensureCustomData(ptr); ensureCustomData(ptr);
CreatureLevListCustomData& customData = dynamic_cast<CreatureLevListCustomData&> (*ptr.getRefData().getCustomData()); CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
customData.mSpawnActorId = state2.mSpawnActorId; customData.mSpawnActorId = state2.mSpawnActorId;
customData.mSpawn = state2.mSpawn; customData.mSpawn = state2.mSpawn;
} }
@ -115,7 +118,7 @@ namespace MWClass
ESM::CreatureLevListState& state2 = dynamic_cast<ESM::CreatureLevListState&> (state); ESM::CreatureLevListState& state2 = dynamic_cast<ESM::CreatureLevListState&> (state);
ensureCustomData(ptr); ensureCustomData(ptr);
CreatureLevListCustomData& customData = dynamic_cast<CreatureLevListCustomData&> (*ptr.getRefData().getCustomData()); CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
state2.mSpawnActorId = customData.mSpawnActorId; state2.mSpawnActorId = customData.mSpawnActorId;
state2.mSpawn = customData.mSpawn; state2.mSpawn = customData.mSpawn;
} }

@ -28,23 +28,26 @@
#include "../mwmechanics/actorutil.hpp" #include "../mwmechanics/actorutil.hpp"
namespace namespace MWClass
{ {
struct DoorCustomData : public MWWorld::CustomData class DoorCustomData : public MWWorld::CustomData
{ {
public:
int mDoorState; // 0 = nothing, 1 = opening, 2 = closing int mDoorState; // 0 = nothing, 1 = opening, 2 = closing
virtual MWWorld::CustomData *clone() const; virtual MWWorld::CustomData *clone() const;
virtual DoorCustomData& asDoorCustomData()
{
return *this;
}
}; };
MWWorld::CustomData *DoorCustomData::clone() const MWWorld::CustomData *DoorCustomData::clone() const
{ {
return new DoorCustomData (*this); return new DoorCustomData (*this);
} }
}
namespace MWClass
{
std::string Door::getId (const MWWorld::Ptr& ptr) const std::string Door::getId (const MWWorld::Ptr& ptr) const
{ {
return ptr.get<ESM::Door>()->mBase->mId; return ptr.get<ESM::Door>()->mBase->mId;
@ -65,7 +68,7 @@ namespace MWClass
// Resume the door's opening/closing animation if it wasn't finished // Resume the door's opening/closing animation if it wasn't finished
if (ptr.getRefData().getCustomData()) if (ptr.getRefData().getCustomData())
{ {
const DoorCustomData& customData = dynamic_cast<const DoorCustomData&>(*ptr.getRefData().getCustomData()); const DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData();
if (customData.mDoorState > 0) if (customData.mDoorState > 0)
{ {
MWBase::Environment::get().getWorld()->activateDoor(ptr, customData.mDoorState); MWBase::Environment::get().getWorld()->activateDoor(ptr, customData.mDoorState);
@ -324,7 +327,7 @@ namespace MWClass
int Door::getDoorState (const MWWorld::Ptr &ptr) const int Door::getDoorState (const MWWorld::Ptr &ptr) const
{ {
ensureCustomData(ptr); ensureCustomData(ptr);
const DoorCustomData& customData = dynamic_cast<const DoorCustomData&>(*ptr.getRefData().getCustomData()); const DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData();
return customData.mDoorState; return customData.mDoorState;
} }
@ -334,14 +337,14 @@ namespace MWClass
throw std::runtime_error("load doors can't be moved"); throw std::runtime_error("load doors can't be moved");
ensureCustomData(ptr); ensureCustomData(ptr);
DoorCustomData& customData = dynamic_cast<DoorCustomData&>(*ptr.getRefData().getCustomData()); DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData();
customData.mDoorState = state; customData.mDoorState = state;
} }
void Door::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const void Door::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const
{ {
ensureCustomData(ptr); ensureCustomData(ptr);
DoorCustomData& customData = dynamic_cast<DoorCustomData&>(*ptr.getRefData().getCustomData()); DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData();
const ESM::DoorState& state2 = dynamic_cast<const ESM::DoorState&>(state); const ESM::DoorState& state2 = dynamic_cast<const ESM::DoorState&>(state);
customData.mDoorState = state2.mDoorState; customData.mDoorState = state2.mDoorState;
@ -350,7 +353,7 @@ namespace MWClass
void Door::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) const void Door::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) const
{ {
ensureCustomData(ptr); ensureCustomData(ptr);
const DoorCustomData& customData = dynamic_cast<const DoorCustomData&>(*ptr.getRefData().getCustomData()); const DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData();
ESM::DoorState& state2 = dynamic_cast<ESM::DoorState&>(state); ESM::DoorState& state2 = dynamic_cast<ESM::DoorState&>(state);
state2.mDoorState = customData.mDoorState; state2.mDoorState = customData.mDoorState;

@ -42,19 +42,6 @@
namespace namespace
{ {
struct NpcCustomData : public MWWorld::CustomData
{
MWMechanics::NpcStats mNpcStats;
MWMechanics::Movement mMovement;
MWWorld::InventoryStore mInventoryStore;
virtual MWWorld::CustomData *clone() const;
};
MWWorld::CustomData *NpcCustomData::clone() const
{
return new NpcCustomData (*this);
}
int is_even(double d) { int is_even(double d) {
double int_part; double int_part;
@ -251,6 +238,27 @@ namespace
namespace MWClass namespace MWClass
{ {
class NpcCustomData : public MWWorld::CustomData
{
public:
MWMechanics::NpcStats mNpcStats;
MWMechanics::Movement mMovement;
MWWorld::InventoryStore mInventoryStore;
virtual MWWorld::CustomData *clone() const;
virtual NpcCustomData& asNpcCustomData()
{
return *this;
}
};
MWWorld::CustomData *NpcCustomData::clone() const
{
return new NpcCustomData (*this);
}
const Npc::GMST& Npc::getGmst() const Npc::GMST& Npc::getGmst()
{ {
static GMST gmst; static GMST gmst;
@ -446,14 +454,14 @@ namespace MWClass
{ {
ensureCustomData (ptr); ensureCustomData (ptr);
return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mNpcStats; return ptr.getRefData().getCustomData()->asNpcCustomData().mNpcStats;
} }
MWMechanics::NpcStats& Npc::getNpcStats (const MWWorld::Ptr& ptr) const MWMechanics::NpcStats& Npc::getNpcStats (const MWWorld::Ptr& ptr) const
{ {
ensureCustomData (ptr); ensureCustomData (ptr);
return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mNpcStats; return ptr.getRefData().getCustomData()->asNpcCustomData().mNpcStats;
} }
@ -780,7 +788,7 @@ namespace MWClass
{ {
ensureCustomData (ptr); ensureCustomData (ptr);
return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mInventoryStore; return ptr.getRefData().getCustomData()->asNpcCustomData().mInventoryStore;
} }
MWWorld::InventoryStore& Npc::getInventoryStore (const MWWorld::Ptr& ptr) MWWorld::InventoryStore& Npc::getInventoryStore (const MWWorld::Ptr& ptr)
@ -788,7 +796,7 @@ namespace MWClass
{ {
ensureCustomData (ptr); ensureCustomData (ptr);
return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mInventoryStore; return ptr.getRefData().getCustomData()->asNpcCustomData().mInventoryStore;
} }
std::string Npc::getScript (const MWWorld::Ptr& ptr) const std::string Npc::getScript (const MWWorld::Ptr& ptr) const
@ -897,7 +905,7 @@ namespace MWClass
{ {
ensureCustomData (ptr); ensureCustomData (ptr);
return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mMovement; return ptr.getRefData().getCustomData()->asNpcCustomData().mMovement;
} }
bool Npc::isEssential (const MWWorld::Ptr& ptr) const bool Npc::isEssential (const MWWorld::Ptr& ptr) const
@ -1161,7 +1169,7 @@ namespace MWClass
else else
ensureCustomData(ptr); // in openmw 0.30 savegames not all state was saved yet, so need to load it regardless. ensureCustomData(ptr); // in openmw 0.30 savegames not all state was saved yet, so need to load it regardless.
NpcCustomData& customData = dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()); NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData();
customData.mInventoryStore.readState (state2.mInventory); customData.mInventoryStore.readState (state2.mInventory);
customData.mNpcStats.readState (state2.mNpcStats); customData.mNpcStats.readState (state2.mNpcStats);
@ -1181,7 +1189,7 @@ namespace MWClass
ensureCustomData (ptr); ensureCustomData (ptr);
NpcCustomData& customData = dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()); NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData();
customData.mInventoryStore.writeState (state2.mInventory); customData.mInventoryStore.writeState (state2.mInventory);
customData.mNpcStats.writeState (state2.mNpcStats); customData.mNpcStats.writeState (state2.mNpcStats);

@ -0,0 +1,46 @@
#include "customdata.hpp"
#include <stdexcept>
#include <sstream>
#include <typeinfo>
namespace MWWorld
{
MWClass::CreatureCustomData &CustomData::asCreatureCustomData()
{
std::stringstream error;
error << "bad cast " << typeid(this).name() << " to CreatureCustomData";
throw std::logic_error(error.str());
}
MWClass::NpcCustomData &CustomData::asNpcCustomData()
{
std::stringstream error;
error << "bad cast " << typeid(this).name() << " to NpcCustomData";
throw std::logic_error(error.str());
}
MWClass::ContainerCustomData &CustomData::asContainerCustomData()
{
std::stringstream error;
error << "bad cast " << typeid(this).name() << " to ContainerCustomData";
throw std::logic_error(error.str());
}
MWClass::DoorCustomData &CustomData::asDoorCustomData()
{
std::stringstream error;
error << "bad cast " << typeid(this).name() << " to DoorCustomData";
throw std::logic_error(error.str());
}
MWClass::CreatureLevListCustomData &CustomData::asCreatureLevListCustomData()
{
std::stringstream error;
error << "bad cast " << typeid(this).name() << " to CreatureLevListCustomData";
throw std::logic_error(error.str());
}
}

@ -1,6 +1,15 @@
#ifndef GAME_MWWORLD_CUSTOMDATA_H #ifndef GAME_MWWORLD_CUSTOMDATA_H
#define GAME_MWWORLD_CUSTOMDATA_H #define GAME_MWWORLD_CUSTOMDATA_H
namespace MWClass
{
class CreatureCustomData;
class NpcCustomData;
class ContainerCustomData;
class DoorCustomData;
class CreatureLevListCustomData;
}
namespace MWWorld namespace MWWorld
{ {
/// \brief Base class for the MW-class-specific part of RefData /// \brief Base class for the MW-class-specific part of RefData
@ -11,6 +20,18 @@ namespace MWWorld
virtual ~CustomData() {} virtual ~CustomData() {}
virtual CustomData *clone() const = 0; virtual CustomData *clone() const = 0;
// Fast version of dynamic_cast<X&>. Needs to be overridden in the respective class.
virtual MWClass::CreatureCustomData& asCreatureCustomData();
virtual MWClass::NpcCustomData& asNpcCustomData();
virtual MWClass::ContainerCustomData& asContainerCustomData();
virtual MWClass::DoorCustomData& asDoorCustomData();
virtual MWClass::CreatureLevListCustomData& asCreatureLevListCustomData();
}; };
} }

Loading…
Cancel
Save