You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw-tes3mp/components/nif/recordptr.hpp

163 lines
3.7 KiB
C++

#ifndef OPENMW_COMPONENTS_NIF_RECORDPTR_HPP
#define OPENMW_COMPONENTS_NIF_RECORDPTR_HPP
#include <cassert>
#include <vector>
#include "niffile.hpp"
#include "nifstream.hpp"
namespace Nif
{
/** A reference to another record. It is read as an index from the
NIF, and later looked up in the index table to get an actual
pointer.
*/
template <class X>
class RecordPtrT
{
union {
intptr_t index;
X* ptr;
};
public:
RecordPtrT() : index(-2) {}
/// Read the index from the nif
void read(NIFStream *nif)
{
// Can only read the index once
assert(index == -2);
// Store the index for later
index = nif->getInt();
assert(index >= -1);
}
/// Resolve index to pointer
void post(NIFFile *nif)
{
if(index < 0)
ptr = nullptr;
else
{
Record *r = nif->getRecord(index);
// And cast it
ptr = dynamic_cast<X*>(r);
assert(ptr != nullptr);
}
}
/// Look up the actual object from the index
const X* getPtr() const
{
assert(ptr != nullptr);
return ptr;
}
X* getPtr()
{
assert(ptr != nullptr);
return ptr;
}
const X& get() const
{ return *getPtr(); }
X& get()
{ return *getPtr(); }
/// Syntactic sugar
const X* operator->() const
{ return getPtr(); }
X* operator->()
{ return getPtr(); }
/// Pointers are allowed to be empty
bool empty() const
{ return ptr == nullptr; }
};
/** A list of references to other records. These are read as a list,
and later converted to pointers as needed. Not an optimized
implementation.
*/
template <class X>
class RecordListT
{
typedef RecordPtrT<X> Ptr;
std::vector<Ptr> list;
public:
void read(NIFStream *nif)
{
int len = nif->getInt();
list.resize(len);
for(size_t i=0;i < list.size();i++)
list[i].read(nif);
}
void post(NIFFile *nif)
{
for(size_t i=0;i < list.size();i++)
list[i].post(nif);
}
const Ptr& operator[](size_t index) const
{ return list.at(index); }
Ptr& operator[](size_t index)
{ return list.at(index); }
size_t length() const
{ return list.size(); }
};
class Node;
class Extra;
class Property;
class NiUVData;
class NiPosData;
class NiVisData;
class Controller;
class Controlled;
class NiSkinData;
class NiFloatData;
struct NiMorphData;
class NiPixelData;
class NiColorData;
struct NiKeyframeData;
class NiTriShapeData;
class NiSkinInstance;
class NiSourceTexture;
class NiRotatingParticlesData;
class NiAutoNormalParticlesData;
typedef RecordPtrT<Node> NodePtr;
typedef RecordPtrT<Extra> ExtraPtr;
typedef RecordPtrT<NiUVData> NiUVDataPtr;
typedef RecordPtrT<NiPosData> NiPosDataPtr;
typedef RecordPtrT<NiVisData> NiVisDataPtr;
typedef RecordPtrT<Controller> ControllerPtr;
typedef RecordPtrT<Controlled> ControlledPtr;
typedef RecordPtrT<NiSkinData> NiSkinDataPtr;
typedef RecordPtrT<NiMorphData> NiMorphDataPtr;
typedef RecordPtrT<NiPixelData> NiPixelDataPtr;
typedef RecordPtrT<NiFloatData> NiFloatDataPtr;
typedef RecordPtrT<NiColorData> NiColorDataPtr;
typedef RecordPtrT<NiKeyframeData> NiKeyframeDataPtr;
typedef RecordPtrT<NiTriShapeData> NiTriShapeDataPtr;
typedef RecordPtrT<NiSkinInstance> NiSkinInstancePtr;
typedef RecordPtrT<NiSourceTexture> NiSourceTexturePtr;
typedef RecordPtrT<NiRotatingParticlesData> NiRotatingParticlesDataPtr;
typedef RecordPtrT<NiAutoNormalParticlesData> NiAutoNormalParticlesDataPtr;
typedef RecordListT<Node> NodeList;
typedef RecordListT<Property> PropertyList;
typedef RecordListT<NiSourceTexture> NiSourceTextureList;
} // Namespace
#endif