Commit cd4a1ffd authored by scrawl's avatar scrawl

Fast version of dynamic_cast for MWClass

parent db71634a
......@@ -27,23 +27,26 @@
#include "../mwmechanics/npcstats.hpp"
namespace
namespace MWClass
{
struct ContainerCustomData : public MWWorld::CustomData
class ContainerCustomData : public MWWorld::CustomData
{
public:
MWWorld::ContainerStore mContainerStore;
virtual MWWorld::CustomData *clone() const;
virtual ContainerCustomData& asContainerCustomData()
{
return *this;
}
};
MWWorld::CustomData *ContainerCustomData::clone() const
{
return new ContainerCustomData (*this);
}
}
namespace MWClass
{
std::string Container::getId (const MWWorld::Ptr& ptr) const
{
return ptr.get<ESM::Container>()->mBase->mId;
......@@ -202,7 +205,7 @@ namespace MWClass
{
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
......
......@@ -40,14 +40,29 @@
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;
MWWorld::ContainerStore* mContainerStore; // may be InventoryStore for some creatures
MWMechanics::Movement mMovement;
virtual MWWorld::CustomData *clone() const;
virtual CreatureCustomData& asCreatureCustomData()
{
return *this;
}
CreatureCustomData() : mContainerStore(0) {}
virtual ~CreatureCustomData() { delete mContainerStore; }
};
......@@ -59,14 +74,6 @@ namespace
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()
{
static GMST gmst;
......@@ -193,7 +200,7 @@ namespace MWClass
{
ensureCustomData (ptr);
return dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData()).mCreatureStats;
return ptr.getRefData().getCustomData()->asCreatureCustomData().mCreatureStats;
}
......@@ -421,7 +428,7 @@ namespace MWClass
{
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
......@@ -511,7 +518,7 @@ namespace MWClass
{
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
......@@ -711,7 +718,7 @@ namespace MWClass
else
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.mCreatureStats.readState (state2.mCreatureStats);
......@@ -730,7 +737,7 @@ namespace MWClass
ensureCustomData (ptr);
CreatureCustomData& customData = dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData());
CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData();
customData.mContainerStore->writeState (state2.mInventory);
customData.mCreatureStats.writeState (state2.mCreatureStats);
......
......@@ -7,25 +7,28 @@
#include "../mwworld/customdata.hpp"
namespace
namespace MWClass
{
struct CreatureLevListCustomData : public MWWorld::CustomData
class CreatureLevListCustomData : public MWWorld::CustomData
{
public:
// actorId of the creature we spawned
int mSpawnActorId;
bool mSpawn; // Should a new creature be spawned?
virtual MWWorld::CustomData *clone() const;
virtual CreatureLevListCustomData& asCreatureLevListCustomData()
{
return *this;
}
};
MWWorld::CustomData *CreatureLevListCustomData::clone() const
{
return new CreatureLevListCustomData (*this);
}
}
namespace MWClass
{
std::string CreatureLevList::getId (const MWWorld::Ptr& ptr) const
{
return ptr.get<ESM::CreatureLevList>()->mBase->mId;
......@@ -40,7 +43,7 @@ namespace MWClass
{
ensureCustomData(ptr);
CreatureLevListCustomData& customData = dynamic_cast<CreatureLevListCustomData&> (*ptr.getRefData().getCustomData());
CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
customData.mSpawn = true;
}
......@@ -55,7 +58,7 @@ namespace MWClass
{
ensureCustomData(ptr);
CreatureLevListCustomData& customData = dynamic_cast<CreatureLevListCustomData&> (*ptr.getRefData().getCustomData());
CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
if (!customData.mSpawn)
return;
......@@ -104,7 +107,7 @@ namespace MWClass
const ESM::CreatureLevListState& state2 = dynamic_cast<const ESM::CreatureLevListState&> (state);
ensureCustomData(ptr);
CreatureLevListCustomData& customData = dynamic_cast<CreatureLevListCustomData&> (*ptr.getRefData().getCustomData());
CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
customData.mSpawnActorId = state2.mSpawnActorId;
customData.mSpawn = state2.mSpawn;
}
......@@ -115,7 +118,7 @@ namespace MWClass
ESM::CreatureLevListState& state2 = dynamic_cast<ESM::CreatureLevListState&> (state);
ensureCustomData(ptr);
CreatureLevListCustomData& customData = dynamic_cast<CreatureLevListCustomData&> (*ptr.getRefData().getCustomData());
CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
state2.mSpawnActorId = customData.mSpawnActorId;
state2.mSpawn = customData.mSpawn;
}
......
......@@ -28,23 +28,26 @@
#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
virtual MWWorld::CustomData *clone() const;
virtual DoorCustomData& asDoorCustomData()
{
return *this;
}
};
MWWorld::CustomData *DoorCustomData::clone() const
{
return new DoorCustomData (*this);
}
}
namespace MWClass
{
std::string Door::getId (const MWWorld::Ptr& ptr) const
{
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
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)
{
MWBase::Environment::get().getWorld()->activateDoor(ptr, customData.mDoorState);
......@@ -324,7 +327,7 @@ namespace MWClass
int Door::getDoorState (const MWWorld::Ptr &ptr) const
{
ensureCustomData(ptr);
const DoorCustomData& customData = dynamic_cast<const DoorCustomData&>(*ptr.getRefData().getCustomData());
const DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData();
return customData.mDoorState;
}
......@@ -334,14 +337,14 @@ namespace MWClass
throw std::runtime_error("load doors can't be moved");
ensureCustomData(ptr);
DoorCustomData& customData = dynamic_cast<DoorCustomData&>(*ptr.getRefData().getCustomData());
DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData();
customData.mDoorState = state;
}
void Door::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const
{
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);
customData.mDoorState = state2.mDoorState;
......@@ -350,7 +353,7 @@ namespace MWClass
void Door::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) const
{
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);
state2.mDoorState = customData.mDoorState;
......
......@@ -42,19 +42,6 @@
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) {
double int_part;
......@@ -251,6 +238,27 @@ namespace
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()
{
static GMST gmst;
......@@ -446,14 +454,14 @@ namespace MWClass
{
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
{
ensureCustomData (ptr);
return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mNpcStats;
return ptr.getRefData().getCustomData()->asNpcCustomData().mNpcStats;
}
......@@ -780,7 +788,7 @@ namespace MWClass
{
ensureCustomData (ptr);
return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mInventoryStore;
return ptr.getRefData().getCustomData()->asNpcCustomData().mInventoryStore;
}
MWWorld::InventoryStore& Npc::getInventoryStore (const MWWorld::Ptr& ptr)
......@@ -788,7 +796,7 @@ namespace MWClass
{
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
......@@ -897,7 +905,7 @@ namespace MWClass
{
ensureCustomData (ptr);
return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mMovement;
return ptr.getRefData().getCustomData()->asNpcCustomData().mMovement;
}
bool Npc::isEssential (const MWWorld::Ptr& ptr) const
......@@ -1161,7 +1169,7 @@ namespace MWClass
else
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.mNpcStats.readState (state2.mNpcStats);
......@@ -1181,7 +1189,7 @@ namespace MWClass
ensureCustomData (ptr);
NpcCustomData& customData = dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData());
NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData();
customData.mInventoryStore.writeState (state2.mInventory);
customData.mNpcStats.writeState (state2.mNpcStats);
......
#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());
}
}
#ifndef GAME_MWWORLD_CUSTOMDATA_H
#define GAME_MWWORLD_CUSTOMDATA_H
namespace MWClass
{
class CreatureCustomData;
class NpcCustomData;
class ContainerCustomData;
class DoorCustomData;
class CreatureLevListCustomData;
}
namespace MWWorld
{
/// \brief Base class for the MW-class-specific part of RefData
......@@ -11,6 +20,18 @@ namespace MWWorld
virtual ~CustomData() {}
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();
};
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment