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/components/nif/recordptr.hpp

241 lines
7.9 KiB
C++

#ifndef OPENMW_COMPONENTS_NIF_RECORDPTR_HPP
#define OPENMW_COMPONENTS_NIF_RECORDPTR_HPP
#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)
{
}
RecordPtrT(X* ptr)
: ptr(ptr)
{
}
/// 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->get<int32_t>();
assert(index >= -1);
}
/// Resolve index to pointer
void post(Reader& 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>
using RecordListT = std::vector<RecordPtrT<X>>;
template <class T>
void readRecordList(NIFStream* nif, RecordListT<T>& list)
{
const std::uint32_t length = nif->get<std::uint32_t>();
// No reasonable list can hit this generous limit
if (length >= (1 << 24))
throw std::runtime_error("Record list too long: " + std::to_string(length));
list.resize(length);
for (auto& value : list)
value.read(nif);
}
template <class T>
void postRecordList(Reader& nif, RecordListT<T>& list)
{
for (auto& value : list)
value.post(nif);
}
struct NiAVObject;
struct Extra;
struct NiProperty;
struct NiUVData;
struct NiPosData;
struct NiVisData;
struct NiTimeController;
struct NiObjectNET;
struct NiSkinData;
struct NiFloatData;
struct NiMorphData;
struct NiPixelData;
struct NiColorData;
struct NiKeyframeData;
struct NiTriStripsData;
struct NiSkinInstance;
struct NiSourceTexture;
struct NiPalette;
struct NiParticleModifier;
struct BSMasterParticleSystem;
struct NiParticleSystem;
struct NiPSysCollider;
struct NiPSysColliderManager;
struct NiPSysEmitterCtlrData;
struct NiPSysModifier;
struct NiPSysSpawnModifier;
struct NiBoolData;
struct NiBSplineData;
struct NiBSplineBasisData;
struct NiSkinPartition;
struct BSShaderTextureSet;
struct NiTriBasedGeom;
struct NiGeometryData;
struct BSShaderProperty;
struct NiAlphaProperty;
struct NiCollisionObject;
struct bhkSystem;
struct bhkWorldObject;
struct bhkShape;
struct bhkSerializable;
struct bhkEntity;
struct bhkConvexShape;
struct bhkRigidBody;
struct hkPackedNiTriStripsData;
struct NiAccumulator;
struct NiInterpolator;
struct NiStringPalette;
struct NiControllerManager;
struct NiBlendInterpolator;
struct NiDefaultAVObjectPalette;
struct NiControllerSequence;
struct bhkCompressedMeshShapeData;
struct BSMultiBound;
struct BSMultiBoundData;
struct BSSkinBoneData;
struct BSAnimNote;
struct BSAnimNotes;
using NiAVObjectPtr = RecordPtrT<NiAVObject>;
using ExtraPtr = RecordPtrT<Extra>;
using NiUVDataPtr = RecordPtrT<NiUVData>;
using NiPosDataPtr = RecordPtrT<NiPosData>;
using NiVisDataPtr = RecordPtrT<NiVisData>;
using NiTimeControllerPtr = RecordPtrT<NiTimeController>;
using NiObjectNETPtr = RecordPtrT<NiObjectNET>;
using NiSkinDataPtr = RecordPtrT<NiSkinData>;
using NiMorphDataPtr = RecordPtrT<NiMorphData>;
using NiPixelDataPtr = RecordPtrT<NiPixelData>;
using NiFloatDataPtr = RecordPtrT<NiFloatData>;
using NiColorDataPtr = RecordPtrT<NiColorData>;
using NiKeyframeDataPtr = RecordPtrT<NiKeyframeData>;
using NiSkinInstancePtr = RecordPtrT<NiSkinInstance>;
using NiSourceTexturePtr = RecordPtrT<NiSourceTexture>;
using NiPalettePtr = RecordPtrT<NiPalette>;
using NiParticleModifierPtr = RecordPtrT<NiParticleModifier>;
using BSMasterParticleSystemPtr = RecordPtrT<BSMasterParticleSystem>;
using NiParticleSystemPtr = RecordPtrT<NiParticleSystem>;
using NiPSysColliderPtr = RecordPtrT<NiPSysCollider>;
using NiPSysColliderManagerPtr = RecordPtrT<NiPSysColliderManager>;
using NiPSysEmitterCtlrDataPtr = RecordPtrT<NiPSysEmitterCtlrData>;
using NiPSysModifierPtr = RecordPtrT<NiPSysModifier>;
using NiPSysSpawnModifierPtr = RecordPtrT<NiPSysSpawnModifier>;
using NiBoolDataPtr = RecordPtrT<NiBoolData>;
using NiBSplineDataPtr = RecordPtrT<NiBSplineData>;
using NiBSplineBasisDataPtr = RecordPtrT<NiBSplineBasisData>;
using NiSkinPartitionPtr = RecordPtrT<NiSkinPartition>;
using BSShaderTextureSetPtr = RecordPtrT<BSShaderTextureSet>;
using NiTriBasedGeomPtr = RecordPtrT<NiTriBasedGeom>;
using NiGeometryDataPtr = RecordPtrT<NiGeometryData>;
using BSShaderPropertyPtr = RecordPtrT<BSShaderProperty>;
using NiAlphaPropertyPtr = RecordPtrT<NiAlphaProperty>;
using NiCollisionObjectPtr = RecordPtrT<NiCollisionObject>;
using bhkSystemPtr = RecordPtrT<bhkSystem>;
using bhkWorldObjectPtr = RecordPtrT<bhkWorldObject>;
using bhkShapePtr = RecordPtrT<bhkShape>;
using bhkEntityPtr = RecordPtrT<bhkEntity>;
using bhkConvexShapePtr = RecordPtrT<bhkConvexShape>;
using bhkRigidBodyPtr = RecordPtrT<bhkRigidBody>;
using hkPackedNiTriStripsDataPtr = RecordPtrT<hkPackedNiTriStripsData>;
using NiAccumulatorPtr = RecordPtrT<NiAccumulator>;
using NiInterpolatorPtr = RecordPtrT<NiInterpolator>;
using NiStringPalettePtr = RecordPtrT<NiStringPalette>;
using NiControllerManagerPtr = RecordPtrT<NiControllerManager>;
using NiBlendInterpolatorPtr = RecordPtrT<NiBlendInterpolator>;
using NiDefaultAVObjectPalettePtr = RecordPtrT<NiDefaultAVObjectPalette>;
using bhkCompressedMeshShapeDataPtr = RecordPtrT<bhkCompressedMeshShapeData>;
using BSMultiBoundPtr = RecordPtrT<BSMultiBound>;
using BSMultiBoundDataPtr = RecordPtrT<BSMultiBoundData>;
using BSSkinBoneDataPtr = RecordPtrT<BSSkinBoneData>;
using NiAVObjectList = RecordListT<NiAVObject>;
using NiPropertyList = RecordListT<NiProperty>;
using ExtraList = RecordListT<Extra>;
using NiSourceTextureList = RecordListT<NiSourceTexture>;
using NiInterpolatorList = RecordListT<NiInterpolator>;
using NiTriStripsDataList = RecordListT<NiTriStripsData>;
using bhkShapeList = RecordListT<bhkShape>;
using bhkSerializableList = RecordListT<bhkSerializable>;
using bhkEntityList = RecordListT<bhkEntity>;
using bhkRigidBodyList = RecordListT<bhkEntity>;
using NiControllerSequenceList = RecordListT<NiControllerSequence>;
using NiPSysModifierList = RecordListT<NiPSysModifier>;
using NiTriBasedGeomList = RecordListT<NiTriBasedGeom>;
using BSAnimNoteList = RecordListT<BSAnimNote>;
using BSAnimNotesList = RecordListT<BSAnimNotes>;
} // Namespace
#endif