Implement mesh serialization

stable-5.1
Armin Burgmeier 2010-04-01 23:00:05 +02:00
parent 79d2c869ed
commit 6b53d75997
8 changed files with 879 additions and 109 deletions

View File

@ -197,7 +197,7 @@ protected:
C4DefGraphics *pSourceGfx; // source graphics - used for savegame saving and comparisons in ReloadDef
char Action[C4MaxName+1]; // action used as overlay in source gfx
C4TargetFacet fctBlit; // current blit data for bitmap graphics
StdMeshInstance* pMeshInstance; // current blit data for mesh graphics
StdMeshInstance* pMeshInstance; // NoSave // - current blit data for mesh graphics
uint32_t dwBlitMode; // extra parameters for additive blits, etc.
uint32_t dwClrModulation; // colormod for this overlay
C4ObjectPtr OverlayObj; // object to be drawn as overlay in MODE_Object

View File

@ -22,6 +22,25 @@
#include "C4ValueList.h"
#include "C4Game.h"
namespace
{
// Register value providers for serialization
const StdMeshInstance::SerializableValueProvider::ID<C4ValueProviderConst> C4ValueProviderConstID("const");
const StdMeshInstance::SerializableValueProvider::ID<C4ValueProviderLinear> C4ValueProviderLinearID("linear");
const StdMeshInstance::SerializableValueProvider::ID<C4ValueProviderX> C4ValueProviderXID("x");
const StdMeshInstance::SerializableValueProvider::ID<C4ValueProviderY> C4ValueProviderYID("y");
const StdMeshInstance::SerializableValueProvider::ID<C4ValueProviderAbsX> C4ValueProviderAbsXID("absx");
const StdMeshInstance::SerializableValueProvider::ID<C4ValueProviderAbsY> C4ValueProviderAbsYID("absy");
const StdMeshInstance::SerializableValueProvider::ID<C4ValueProviderXDir> C4ValueProviderXDirID("xdir");
const StdMeshInstance::SerializableValueProvider::ID<C4ValueProviderYDir> C4ValueProviderYDirID("ydir");
const StdMeshInstance::SerializableValueProvider::ID<C4ValueProviderRDir> C4ValueProviderRDirID("rdir");
const StdMeshInstance::SerializableValueProvider::ID<C4ValueProviderCosR> C4ValueProviderCosRID("cosr");
const StdMeshInstance::SerializableValueProvider::ID<C4ValueProviderSinR> C4ValueProviderSinRID("sinr");
const StdMeshInstance::SerializableValueProvider::ID<C4ValueProviderCosV> C4ValueProviderCosVID("cosv");
const StdMeshInstance::SerializableValueProvider::ID<C4ValueProviderSinV> C4ValueProviderSinVID("sinv");
const StdMeshInstance::SerializableValueProvider::ID<C4ValueProviderAction> C4ValueProviderActionID("action");
}
StdMeshInstance::ValueProvider* CreateValueProviderFromArray(C4Object* pForObj, C4ValueArray& Data)
{
int32_t type = Data[0].getInt();
@ -114,7 +133,31 @@ bool C4ValueProviderLinear::Execute()
return true;
}
C4ValueProviderX::C4ValueProviderX(const C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length):
void C4ValueProviderLinear::CompileFunc(StdCompiler* pComp)
{
const StdEnumEntry<C4AnimationEnding> Endings[] =
{
{ "Loop", ANIM_Loop },
{ "Hold", ANIM_Hold },
{ "Remove", ANIM_Remove },
{ NULL, static_cast<C4AnimationEnding>(0) }
};
SerializableValueProvider::CompileFunc(pComp);
pComp->Seperator();
pComp->Value(Begin);
pComp->Seperator();
pComp->Value(End);
pComp->Seperator();
pComp->Value(Length);
pComp->Seperator();
pComp->Value(mkEnumAdapt(Ending, Endings));
pComp->Seperator();
pComp->Value(LastTick);
}
C4ValueProviderX::C4ValueProviderX(C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length):
Object(object), Begin(begin), End(end), Length(length), LastX(object->fix_x)
{
Value = pos;
@ -144,7 +187,22 @@ bool C4ValueProviderX::Execute()
return true;
}
C4ValueProviderY::C4ValueProviderY(const C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length):
void C4ValueProviderX::CompileFunc(StdCompiler* pComp)
{
SerializableValueProvider::CompileFunc(pComp);
pComp->Seperator();
pComp->Value(Object);
pComp->Seperator();
pComp->Value(Begin);
pComp->Seperator();
pComp->Value(End);
pComp->Seperator();
pComp->Value(Length);
pComp->Seperator();
pComp->Value(LastX);
}
C4ValueProviderY::C4ValueProviderY(C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length):
Object(object), Begin(begin), End(end), Length(length), LastY(object->fix_y)
{
Value = pos;
@ -174,7 +232,22 @@ bool C4ValueProviderY::Execute()
return true;
}
C4ValueProviderAbsX::C4ValueProviderAbsX(const C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length):
void C4ValueProviderY::CompileFunc(StdCompiler* pComp)
{
SerializableValueProvider::CompileFunc(pComp);
pComp->Seperator();
pComp->Value(Object);
pComp->Seperator();
pComp->Value(Begin);
pComp->Seperator();
pComp->Value(End);
pComp->Seperator();
pComp->Value(Length);
pComp->Seperator();
pComp->Value(LastY);
}
C4ValueProviderAbsX::C4ValueProviderAbsX(C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length):
Object(object), Begin(begin), End(end), Length(length), LastX(object->fix_x)
{
Value = pos;
@ -192,7 +265,22 @@ bool C4ValueProviderAbsX::Execute()
return true;
}
C4ValueProviderAbsY::C4ValueProviderAbsY(const C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length):
void C4ValueProviderAbsX::CompileFunc(StdCompiler* pComp)
{
SerializableValueProvider::CompileFunc(pComp);
pComp->Seperator();
pComp->Value(Object);
pComp->Seperator();
pComp->Value(Begin);
pComp->Seperator();
pComp->Value(End);
pComp->Seperator();
pComp->Value(Length);
pComp->Seperator();
pComp->Value(LastX);
}
C4ValueProviderAbsY::C4ValueProviderAbsY(C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length):
Object(object), Begin(begin), End(end), Length(length), LastY(object->fix_y)
{
Value = pos;
@ -210,20 +298,47 @@ bool C4ValueProviderAbsY::Execute()
return true;
}
C4ValueProviderXDir::C4ValueProviderXDir(const C4Object* object, FIXED begin, FIXED end, FIXED max_xdir):
void C4ValueProviderAbsY::CompileFunc(StdCompiler* pComp)
{
SerializableValueProvider::CompileFunc(pComp);
pComp->Seperator();
pComp->Value(Object);
pComp->Seperator();
pComp->Value(Begin);
pComp->Seperator();
pComp->Value(End);
pComp->Seperator();
pComp->Value(Length);
pComp->Seperator();
pComp->Value(LastY);
}
C4ValueProviderXDir::C4ValueProviderXDir(C4Object* object, FIXED begin, FIXED end, FIXED max_xdir):
Object(object), Begin(begin), End(end), MaxXDir(max_xdir)
{
Execute();
}
bool C4ValueProviderXDir::Execute()
{
Value = Begin + (End - Begin) * Min<FIXED>(Abs(Object->xdir/MaxXDir), itofix(1));
return true;
}
C4ValueProviderYDir::C4ValueProviderYDir(const C4Object* object, FIXED begin, FIXED end, FIXED max_ydir):
void C4ValueProviderXDir::CompileFunc(StdCompiler* pComp)
{
SerializableValueProvider::CompileFunc(pComp);
pComp->Seperator();
pComp->Value(Object);
pComp->Seperator();
pComp->Value(Begin);
pComp->Seperator();
pComp->Value(End);
pComp->Seperator();
pComp->Value(MaxXDir);
}
C4ValueProviderYDir::C4ValueProviderYDir(C4Object* object, FIXED begin, FIXED end, FIXED max_ydir):
Object(object), Begin(begin), End(end), MaxYDir(max_ydir)
{
Execute();
@ -235,7 +350,20 @@ bool C4ValueProviderYDir::Execute()
return true;
}
C4ValueProviderRDir::C4ValueProviderRDir(const C4Object* object, FIXED begin, FIXED end, FIXED max_rdir):
void C4ValueProviderYDir::CompileFunc(StdCompiler* pComp)
{
SerializableValueProvider::CompileFunc(pComp);
pComp->Seperator();
pComp->Value(Object);
pComp->Seperator();
pComp->Value(Begin);
pComp->Seperator();
pComp->Value(End);
pComp->Seperator();
pComp->Value(MaxYDir);
}
C4ValueProviderRDir::C4ValueProviderRDir(C4Object* object, FIXED begin, FIXED end, FIXED max_rdir):
Object(object), Begin(begin), End(end), MaxRDir(max_rdir)
{
Execute();
@ -247,7 +375,20 @@ bool C4ValueProviderRDir::Execute()
return true;
}
C4ValueProviderCosR::C4ValueProviderCosR(const C4Object* object, FIXED begin, FIXED end, FIXED offset):
void C4ValueProviderRDir::CompileFunc(StdCompiler* pComp)
{
SerializableValueProvider::CompileFunc(pComp);
pComp->Seperator();
pComp->Value(Object);
pComp->Seperator();
pComp->Value(Begin);
pComp->Seperator();
pComp->Value(End);
pComp->Seperator();
pComp->Value(MaxRDir);
}
C4ValueProviderCosR::C4ValueProviderCosR(C4Object* object, FIXED begin, FIXED end, FIXED offset):
Object(object), Begin(begin), End(end), Offset(offset)
{
Execute();
@ -259,7 +400,20 @@ bool C4ValueProviderCosR::Execute()
return true;
}
C4ValueProviderSinR::C4ValueProviderSinR(const C4Object* object, FIXED begin, FIXED end, FIXED offset):
void C4ValueProviderCosR::CompileFunc(StdCompiler* pComp)
{
SerializableValueProvider::CompileFunc(pComp);
pComp->Seperator();
pComp->Value(Object);
pComp->Seperator();
pComp->Value(Begin);
pComp->Seperator();
pComp->Value(End);
pComp->Seperator();
pComp->Value(Offset);
}
C4ValueProviderSinR::C4ValueProviderSinR(C4Object* object, FIXED begin, FIXED end, FIXED offset):
Object(object), Begin(begin), End(end), Offset(offset)
{
Execute();
@ -271,7 +425,20 @@ bool C4ValueProviderSinR::Execute()
return true;
}
C4ValueProviderCosV::C4ValueProviderCosV(const C4Object* object, FIXED begin, FIXED end, FIXED offset):
void C4ValueProviderSinR::CompileFunc(StdCompiler* pComp)
{
SerializableValueProvider::CompileFunc(pComp);
pComp->Seperator();
pComp->Value(Object);
pComp->Seperator();
pComp->Value(Begin);
pComp->Seperator();
pComp->Value(End);
pComp->Seperator();
pComp->Value(Offset);
}
C4ValueProviderCosV::C4ValueProviderCosV(C4Object* object, FIXED begin, FIXED end, FIXED offset):
Object(object), Begin(begin), End(end), Offset(offset)
{
Execute();
@ -287,7 +454,20 @@ bool C4ValueProviderCosV::Execute()
return true;
}
C4ValueProviderSinV::C4ValueProviderSinV(const C4Object* object, FIXED begin, FIXED end, FIXED offset):
void C4ValueProviderCosV::CompileFunc(StdCompiler* pComp)
{
SerializableValueProvider::CompileFunc(pComp);
pComp->Seperator();
pComp->Value(Object);
pComp->Seperator();
pComp->Value(Begin);
pComp->Seperator();
pComp->Value(End);
pComp->Seperator();
pComp->Value(Offset);
}
C4ValueProviderSinV::C4ValueProviderSinV(C4Object* object, FIXED begin, FIXED end, FIXED offset):
Object(object), Begin(begin), End(end), Offset(offset)
{
Execute();
@ -303,6 +483,19 @@ bool C4ValueProviderSinV::Execute()
return true;
}
void C4ValueProviderSinV::CompileFunc(StdCompiler* pComp)
{
SerializableValueProvider::CompileFunc(pComp);
pComp->Seperator();
pComp->Value(Object);
pComp->Seperator();
pComp->Value(Begin);
pComp->Seperator();
pComp->Value(End);
pComp->Seperator();
pComp->Value(Offset);
}
C4ValueProviderAction::C4ValueProviderAction(C4Object* object):
Object(object)
{
@ -325,3 +518,10 @@ bool C4ValueProviderAction::Execute()
return true;
}
void C4ValueProviderAction::CompileFunc(StdCompiler* pComp)
{
SerializableValueProvider::CompileFunc(pComp);
pComp->Seperator();
pComp->Value(Object);
}

View File

@ -22,6 +22,7 @@
#define INC_C4MeshAnimation
#include "StdMesh.h"
#include "C4ObjectPtr.h"
class C4Action;
class C4Object;
@ -53,188 +54,239 @@ enum C4AnimationEnding
};
// Keep a constant value
class C4ValueProviderConst: public StdMeshInstance::ValueProvider
class C4ValueProviderConst: public StdMeshInstance::SerializableValueProvider
{
public:
C4ValueProviderConst() {}
C4ValueProviderConst(FIXED value);
virtual bool Execute();
};
// Interpolate linearly in time between two values
class C4ValueProviderLinear: public StdMeshInstance::ValueProvider
class C4ValueProviderLinear: public StdMeshInstance::SerializableValueProvider
{
public:
C4ValueProviderLinear(): Begin(Fix0), End(Fix0), Length(0), Ending(ANIM_Loop), LastTick(0) {}
C4ValueProviderLinear(FIXED pos, FIXED begin, FIXED end, int32_t length, C4AnimationEnding ending);
virtual bool Execute();
virtual void CompileFunc(StdCompiler* pComp);
private:
const FIXED Begin;
const FIXED End;
const int32_t Length;
const C4AnimationEnding Ending;
FIXED Begin;
FIXED End;
int32_t Length;
C4AnimationEnding Ending;
int32_t LastTick;
};
class C4ValueProviderX: public StdMeshInstance::ValueProvider
class C4ValueProviderX: public StdMeshInstance::SerializableValueProvider
{
public:
C4ValueProviderX(const C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length);
C4ValueProviderX(): Object(NULL), Begin(Fix0), End(Fix0), Length(0), LastX(Fix0) {}
C4ValueProviderX(C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length);
virtual bool Execute();
virtual void CompileFunc(StdCompiler* pComp);
virtual void DenumeratePointers() { Object.DenumeratePointers(); }
virtual void EnumeratePointers() { Object.EnumeratePointers(); }
private:
const C4Object* const Object;
const FIXED Begin;
const FIXED End;
const int32_t Length;
C4ObjectPtr Object;
FIXED Begin;
FIXED End;
int32_t Length;
FIXED LastX;
};
class C4ValueProviderY: public StdMeshInstance::ValueProvider
class C4ValueProviderY: public StdMeshInstance::SerializableValueProvider
{
public:
C4ValueProviderY(const C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length);
C4ValueProviderY(): Object(NULL), Begin(Fix0), End(Fix0), Length(0), LastY(Fix0) {}
C4ValueProviderY(C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length);
virtual bool Execute();
virtual void CompileFunc(StdCompiler* pComp);
virtual void DenumeratePointers() { Object.DenumeratePointers(); }
virtual void EnumeratePointers() { Object.EnumeratePointers(); }
private:
const C4Object* const Object;
const FIXED Begin;
const FIXED End;
const int32_t Length;
C4ObjectPtr Object;
FIXED Begin;
FIXED End;
int32_t Length;
FIXED LastY;
};
class C4ValueProviderAbsX: public StdMeshInstance::ValueProvider
class C4ValueProviderAbsX: public StdMeshInstance::SerializableValueProvider
{
public:
C4ValueProviderAbsX(const C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length);
C4ValueProviderAbsX(): Object(NULL), Begin(Fix0), End(Fix0), Length(0), LastX(Fix0) {}
C4ValueProviderAbsX(C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length);
virtual bool Execute();
virtual void CompileFunc(StdCompiler* pComp);
virtual void DenumeratePointers() { Object.DenumeratePointers(); }
virtual void EnumeratePointers() { Object.EnumeratePointers(); }
private:
const C4Object* const Object;
const FIXED Begin;
const FIXED End;
const int32_t Length;
C4ObjectPtr Object;
FIXED Begin;
FIXED End;
int32_t Length;
FIXED LastX;
};
class C4ValueProviderAbsY: public StdMeshInstance::ValueProvider
class C4ValueProviderAbsY: public StdMeshInstance::SerializableValueProvider
{
public:
C4ValueProviderAbsY(const C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length);
C4ValueProviderAbsY(): Object(NULL), Begin(Fix0), End(Fix0), Length(0), LastY(Fix0) {}
C4ValueProviderAbsY(C4Object* object, FIXED pos, FIXED begin, FIXED end, int32_t length);
virtual bool Execute();
virtual void CompileFunc(StdCompiler* pComp);
virtual void DenumeratePointers() { Object.DenumeratePointers(); }
virtual void EnumeratePointers() { Object.EnumeratePointers(); }
private:
const C4Object* const Object;
const FIXED Begin;
const FIXED End;
const int32_t Length;
C4ObjectPtr Object;
FIXED Begin;
FIXED End;
int32_t Length;
FIXED LastY;
};
class C4ValueProviderXDir: public StdMeshInstance::ValueProvider
class C4ValueProviderXDir: public StdMeshInstance::SerializableValueProvider
{
public:
C4ValueProviderXDir(const C4Object* object, FIXED begin, FIXED end, FIXED max_xdir);
C4ValueProviderXDir(): Object(NULL), Begin(Fix0), End(Fix0), MaxXDir(Fix0) {}
C4ValueProviderXDir(C4Object* object, FIXED begin, FIXED end, FIXED max_xdir);
virtual bool Execute();
virtual void CompileFunc(StdCompiler* pComp);
virtual void DenumeratePointers() { Object.DenumeratePointers(); }
virtual void EnumeratePointers() { Object.EnumeratePointers(); }
private:
const C4Object* const Object;
const FIXED Begin;
const FIXED End;
const FIXED MaxXDir;
C4ObjectPtr Object;
FIXED Begin;
FIXED End;
FIXED MaxXDir;
};
class C4ValueProviderYDir: public StdMeshInstance::ValueProvider
class C4ValueProviderYDir: public StdMeshInstance::SerializableValueProvider
{
public:
C4ValueProviderYDir(const C4Object* object, FIXED begin, FIXED end, FIXED max_ydir);
C4ValueProviderYDir(): Object(NULL), Begin(Fix0), End(Fix0), MaxYDir(Fix0) {}
C4ValueProviderYDir(C4Object* object, FIXED begin, FIXED end, FIXED max_ydir);
virtual bool Execute();
virtual void CompileFunc(StdCompiler* pComp);
virtual void DenumeratePointers() { Object.DenumeratePointers(); }
virtual void EnumeratePointers() { Object.EnumeratePointers(); }
private:
const C4Object* const Object;
const FIXED Begin;
const FIXED End;
const FIXED MaxYDir;
C4ObjectPtr Object;
FIXED Begin;
FIXED End;
FIXED MaxYDir;
};
class C4ValueProviderRDir: public StdMeshInstance::ValueProvider
class C4ValueProviderRDir: public StdMeshInstance::SerializableValueProvider
{
public:
C4ValueProviderRDir(const C4Object* object, FIXED begin, FIXED end, FIXED max_rdir);
C4ValueProviderRDir(): Object(NULL), Begin(Fix0), End(Fix0), MaxRDir(Fix0) {}
C4ValueProviderRDir(C4Object* object, FIXED begin, FIXED end, FIXED max_rdir);
virtual bool Execute();
virtual void CompileFunc(StdCompiler* pComp);
virtual void DenumeratePointers() { Object.DenumeratePointers(); }
virtual void EnumeratePointers() { Object.EnumeratePointers(); }
private:
const C4Object* const Object;
const FIXED Begin;
const FIXED End;
const FIXED MaxRDir;
C4ObjectPtr Object;
FIXED Begin;
FIXED End;
FIXED MaxRDir;
};
class C4ValueProviderCosR: public StdMeshInstance::ValueProvider
class C4ValueProviderCosR: public StdMeshInstance::SerializableValueProvider
{
public:
C4ValueProviderCosR(const C4Object* object, FIXED begin, FIXED end, FIXED offset);
C4ValueProviderCosR(): Object(NULL), Begin(Fix0), End(Fix0), Offset(Fix0) {}
C4ValueProviderCosR(C4Object* object, FIXED begin, FIXED end, FIXED offset);
virtual bool Execute();
virtual void CompileFunc(StdCompiler* pComp);
virtual void DenumeratePointers() { Object.DenumeratePointers(); }
virtual void EnumeratePointers() { Object.EnumeratePointers(); }
private:
const C4Object* const Object;
const FIXED Begin;
const FIXED End;
const FIXED Offset;
C4ObjectPtr Object;
FIXED Begin;
FIXED End;
FIXED Offset;
};
class C4ValueProviderSinR: public StdMeshInstance::ValueProvider
class C4ValueProviderSinR: public StdMeshInstance::SerializableValueProvider
{
public:
C4ValueProviderSinR(const C4Object* object, FIXED begin, FIXED end, FIXED offset);
C4ValueProviderSinR(): Object(NULL), Begin(Fix0), End(Fix0), Offset(Fix0) {}
C4ValueProviderSinR(C4Object* object, FIXED begin, FIXED end, FIXED offset);
virtual bool Execute();
virtual void CompileFunc(StdCompiler* pComp);
virtual void DenumeratePointers() { Object.DenumeratePointers(); }
virtual void EnumeratePointers() { Object.EnumeratePointers(); }
private:
const C4Object* const Object;
const FIXED Begin;
const FIXED End;
const FIXED Offset;
C4ObjectPtr Object;
FIXED Begin;
FIXED End;
FIXED Offset;
};
class C4ValueProviderCosV: public StdMeshInstance::ValueProvider
class C4ValueProviderCosV: public StdMeshInstance::SerializableValueProvider
{
public:
C4ValueProviderCosV(const C4Object* object, FIXED begin, FIXED end, FIXED offset);
C4ValueProviderCosV(): Object(NULL), Begin(Fix0), End(Fix0), Offset(Fix0) {}
C4ValueProviderCosV(C4Object* object, FIXED begin, FIXED end, FIXED offset);
virtual bool Execute();
virtual void CompileFunc(StdCompiler* pComp);
virtual void DenumeratePointers() { Object.DenumeratePointers(); }
virtual void EnumeratePointers() { Object.EnumeratePointers(); }
private:
const C4Object* const Object;
const FIXED Begin;
const FIXED End;
const FIXED Offset;
C4ObjectPtr Object;
FIXED Begin;
FIXED End;
FIXED Offset;
};
class C4ValueProviderSinV: public StdMeshInstance::ValueProvider
class C4ValueProviderSinV: public StdMeshInstance::SerializableValueProvider
{
public:
C4ValueProviderSinV(const C4Object* object, FIXED begin, FIXED end, FIXED offset);
C4ValueProviderSinV(): Object(NULL), Begin(Fix0), End(Fix0), Offset(Fix0) {}
C4ValueProviderSinV(C4Object* object, FIXED begin, FIXED end, FIXED offset);
virtual bool Execute();
virtual void CompileFunc(StdCompiler* pComp);
virtual void DenumeratePointers() { Object.DenumeratePointers(); }
virtual void EnumeratePointers() { Object.EnumeratePointers(); }
private:
const C4Object* const Object;
const FIXED Begin;
const FIXED End;
const FIXED Offset;
C4ObjectPtr Object;
FIXED Begin;
FIXED End;
FIXED Offset;
};
class C4ValueProviderAction: public StdMeshInstance::ValueProvider
class C4ValueProviderAction: public StdMeshInstance::SerializableValueProvider
{
public:
C4ValueProviderAction(): Object(NULL) {}
C4ValueProviderAction(C4Object* object);
virtual bool Execute();
virtual void CompileFunc(StdCompiler* pComp);
virtual void DenumeratePointers() { Object.DenumeratePointers(); }
virtual void EnumeratePointers() { Object.EnumeratePointers(); }
private:
C4Object* Object;
C4ObjectPtr Object;
};
// Reference another value (which is convertible to FIXED), and optionally scale it

View File

@ -53,6 +53,75 @@
#include <C4Record.h>
#include <C4MeshAnimation.h>
namespace
{
const StdMeshInstance::AttachedMesh::DenumeratorFactoryFunc C4MeshDenumeratorFactory = StdMeshInstance::AttachedMesh::DenumeratorFactory<C4MeshDenumerator>;
}
void C4MeshDenumerator::CompileFunc(StdCompiler* pComp, StdMeshInstance::AttachedMesh* attach)
{
if(pComp->isCompiler())
{
int32_t def;
pComp->Value(mkNamingCountAdapt(def, "ChildInstance"));
if(def)
{
C4DefGraphics* pGfx = NULL;
pComp->Value(mkNamingAdapt(C4DefGraphicsAdapt(pGfx), "ChildMesh"));
if(pGfx->Type != C4DefGraphics::TYPE_Mesh)
pComp->excCorrupt("ChildMesh points to non-mesh graphics");
assert(!attach->Child);
pComp->Value(mkParAdapt(mkNamingContextPtrAdapt(attach->Child, *pGfx->Mesh, "ChildInstance"), C4MeshDenumeratorFactory));
attach->OwnChild = true; // Delete the newly allocated child instance when the parent instance is gone
}
else
{
pComp->Value(mkNamingAdapt(Object, "ChildObject"));
attach->OwnChild = false; // Keep child instance when parent instance is gone since it belongs to a different object
}
}
else
{
int32_t def = 0;
if(Def) ++def;
pComp->Value(mkNamingCountAdapt(def, "ChildInstance"));
if(Def)
{
assert(attach->OwnChild);
C4DefGraphics* pGfx = &Def->Graphics;
assert(pGfx->Type != C4DefGraphics::TYPE_Mesh);
pComp->Value(mkNamingAdapt(C4DefGraphicsAdapt(pGfx), "ChildMesh"));
pComp->Value(mkParAdapt(mkNamingContextPtrAdapt(attach->Child, *pGfx->Mesh, "ChildInstance"), C4MeshDenumeratorFactory));
}
else
{
assert(!attach->OwnChild);
pComp->Value(mkNamingAdapt(Object, "ChildObject"));
}
}
}
void C4MeshDenumerator::EnumeratePointers(StdMeshInstance::AttachedMesh* attach)
{
Object.EnumeratePointers();
}
void C4MeshDenumerator::DenumeratePointers(StdMeshInstance::AttachedMesh* attach)
{
Object.DenumeratePointers();
// Set child instance of attach after denumeration
if(Object)
{
assert(!attach->OwnChild);
assert(!attach->Child || attach->Child == Object->pMeshInstance);
if(!attach->Child)
attach->Child = Object->pMeshInstance;
}
}
void DrawVertex(C4Facet &cgo, int32_t tx, int32_t ty, int32_t col, int32_t contact)
{
if (Inside<int32_t>(tx,1,cgo.Wdt-2) && Inside<int32_t>(ty,1,cgo.Hgt-2))
@ -2708,6 +2777,24 @@ void C4Object::CompileFunc(StdCompiler *pComp)
pComp->Value(mkNamingPtrAdapt( pEffects, "Effects" ));
pComp->Value(mkNamingAdapt( C4GraphicsOverlayListAdapt(pGfxOverlay),"GfxOverlay", (C4GraphicsOverlay *)NULL));
// Serialize mesh instance if we have a mesh graphics
if(pGraphics->Type == C4DefGraphics::TYPE_Mesh)
{
if(pComp->isCompiler())
{
assert(!pMeshInstance);
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh);
}
pComp->Value(mkNamingAdapt(mkParAdapt(*pMeshInstance, C4MeshDenumeratorFactory), "Mesh"));
// Does not work because unanimated meshes without attached meshes
// do not even write a [Mesh] header so this does not create a mesh instance in that case
/* pComp->Value(mkNamingContextPtrAdapt( pMeshInstance, *pGraphics->Mesh, "Mesh"));
if(!pMeshInstance)
pComp->excCorrupt("Mesh graphics without mesh instance");*/
}
if (PhysicalTemporary)
{
pComp->FollowName("Physical");
@ -2766,7 +2853,11 @@ void C4Object::CompileFunc(StdCompiler *pComp)
// Set Action animation by slot 0
if (pMeshInstance)
{
Action.Animation = pMeshInstance->GetRootAnimationForSlot(0);
if ( ((ColorMod >> 24) & 0xff) != 0xff) // Sort faces if the object is transparent
pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_NearestToFarthest);
}
// if on fire but no effect is present (old-style savegames), re-incinerate
int32_t iFireNumber;
@ -2806,6 +2897,9 @@ void C4Object::EnumeratePointers()
if (pGfxOverlay)
for (C4GraphicsOverlay *pGfxOvrl = pGfxOverlay; pGfxOvrl; pGfxOvrl = pGfxOvrl->GetNext())
pGfxOvrl->EnumeratePointers();
// mesh instance
if (pMeshInstance) pMeshInstance->EnumeratePointers();
}
void C4Object::DenumeratePointers()
@ -2831,6 +2925,9 @@ void C4Object::DenumeratePointers()
if (pGfxOverlay)
for (C4GraphicsOverlay *pGfxOvrl = pGfxOverlay; pGfxOvrl; pGfxOvrl = pGfxOvrl->GetNext())
pGfxOvrl->DenumeratePointers();
// mesh instance
if (pMeshInstance) pMeshInstance->DenumeratePointers();
}
void C4Object::DrawPicture(C4Facet &cgo, bool fSelected, C4RegionList *pRegions)

View File

@ -85,6 +85,23 @@ class C4Command;
class C4MaterialList;
class C4Player;
// Helper struct to serialize an object's mesh instance with other object's mesh instances attached
class C4MeshDenumerator: public StdMeshInstance::AttachedMesh::Denumerator
{
private:
C4Def* Def; // Set if a definition mesh was attached
C4ObjectPtr Object; // Set if an instance mesh was attached
public:
C4MeshDenumerator(): Def(NULL), Object(NULL) {}
C4MeshDenumerator(C4Def* def): Def(def), Object(NULL) {}
C4MeshDenumerator(C4Object* object): Def(NULL), Object(object) {}
virtual void CompileFunc(StdCompiler* pComp, StdMeshInstance::AttachedMesh* attach);
virtual void EnumeratePointers(StdMeshInstance::AttachedMesh* attach);
virtual void DenumeratePointers(StdMeshInstance::AttachedMesh* attach);
};
class C4Action
{
public:

View File

@ -5822,7 +5822,7 @@ static C4Value FnAttachMesh(C4AulContext *ctx, C4Value* pPars)
if (pObj)
{
if (!pObj->pMeshInstance) return C4VNull;
attach = ctx->Obj->pMeshInstance->AttachMesh(*pObj->pMeshInstance, szParentBone->GetData(), szChildBone->GetData(), trans);
attach = ctx->Obj->pMeshInstance->AttachMesh(*pObj->pMeshInstance, new C4MeshDenumerator(pObj), szParentBone->GetData(), szChildBone->GetData(), trans);
}
else
{
@ -5831,7 +5831,7 @@ static C4Value FnAttachMesh(C4AulContext *ctx, C4Value* pPars)
C4Def* pDef = C4Id2Def(id);
if (pDef->Graphics.Type != C4DefGraphics::TYPE_Mesh) return C4VNull;
attach = ctx->Obj->pMeshInstance->AttachMesh(*pDef->Graphics.Mesh, szParentBone->GetData(), szChildBone->GetData(), trans);
attach = ctx->Obj->pMeshInstance->AttachMesh(*pDef->Graphics.Mesh, new C4MeshDenumerator(pDef), szParentBone->GetData(), szChildBone->GetData(), trans);
}
if (!attach) return C4VNull;

View File

@ -26,6 +26,8 @@
#include <algorithm>
std::vector<StdMeshInstance::SerializableValueProvider::IDBase*>* StdMeshInstance::SerializableValueProvider::IDs = NULL;
namespace
{
// Helper to sort faces for FaceOrdering
@ -62,6 +64,86 @@ namespace
}
};
// Seralize a ValueProvider with StdCompiler
struct ValueProviderAdapt
{
ValueProviderAdapt(StdMeshInstance::ValueProvider** Provider):
ValueProvider(Provider) {}
StdMeshInstance::ValueProvider** ValueProvider;
void CompileFunc(StdCompiler* pComp)
{
const StdMeshInstance::SerializableValueProvider::IDBase* id;
StdMeshInstance::SerializableValueProvider* svp = NULL;
if(pComp->isCompiler())
{
StdCopyStrBuf id_str;
pComp->Value(mkParAdapt(id_str, StdCompiler::RCT_Idtf));
id = StdMeshInstance::SerializableValueProvider::Lookup(id_str.getData());
if(!id) pComp->excCorrupt("No value provider for ID \"%s\"", id_str.getData());
}
else
{
svp = dynamic_cast<StdMeshInstance::SerializableValueProvider*>(*ValueProvider);
if(!svp) pComp->excCorrupt("Value provider cannot be compiled");
id = StdMeshInstance::SerializableValueProvider::Lookup(typeid(*svp));
if(!id) pComp->excCorrupt("No ID for value provider registered");
StdCopyStrBuf id_str(id->name);
pComp->Value(mkParAdapt(id_str, StdCompiler::RCT_Idtf));
}
pComp->Seperator(StdCompiler::SEP_START);
pComp->Value(mkContextPtrAdapt(svp, *id, false));
pComp->Seperator(StdCompiler::SEP_END);
if(pComp->isCompiler())
*ValueProvider = svp;
}
};
ValueProviderAdapt mkValueProviderAdapt(StdMeshInstance::ValueProvider** ValueProvider) { return ValueProviderAdapt(ValueProvider); }
// Serialize a bone index by name with StdCompiler
struct TransformAdapt
{
StdMeshMatrix& Matrix;
TransformAdapt(StdMeshMatrix& matrix): Matrix(matrix) {}
void CompileFunc(StdCompiler* pComp)
{
pComp->Seperator(StdCompiler::SEP_START);
for(unsigned int i = 0; i < 3; ++i)
{
for(unsigned int j = 0; j < 4; ++j)
{
if(i != 0 || j != 0) pComp->Seperator();
// TODO: Teach StdCompiler how to handle float
// pComp->Value(Matrix(i, j));
if(pComp->isCompiler())
{
FIXED f;
pComp->Value(f);
Matrix(i,j) = fixtof(f);
}
else
{
FIXED f = ftofix(Matrix(i,j));
pComp->Value(f);
}
}
}
pComp->Seperator(StdCompiler::SEP_END);
}
};
TransformAdapt mkTransformAdapt(StdMeshMatrix& Matrix) { return TransformAdapt(Matrix); }
// Reset all animation list entries corresponding to node or its children
void ClearAnimationListRecursively(std::vector<StdMeshInstance::AnimationNode*>& list, StdMeshInstance::AnimationNode* node)
{
@ -832,6 +914,18 @@ void StdSubMeshInstance::SetMaterial(const StdMeshMaterial& material)
}
}
void StdMeshInstance::SerializableValueProvider::CompileFunc(StdCompiler* pComp)
{
pComp->Value(Value);
}
StdMeshInstance::AnimationNode::AnimationNode():
Type(LeafNode), Parent(NULL)
{
Leaf.Animation = NULL;
Leaf.Position = NULL;
}
StdMeshInstance::AnimationNode::AnimationNode(const StdMeshAnimation* animation, ValueProvider* position):
Type(LeafNode), Parent(NULL)
{
@ -889,9 +983,97 @@ bool StdMeshInstance::AnimationNode::GetBoneTransform(unsigned int bone, StdMesh
}
}
StdMeshInstance::AttachedMesh::AttachedMesh(unsigned int number, StdMeshInstance* parent, StdMeshInstance* child, bool own_child,
unsigned int parent_bone, unsigned int child_bone, const StdMeshMatrix& transform):
Number(number), Parent(parent), Child(child), OwnChild(own_child),
void StdMeshInstance::AnimationNode::CompileFunc(StdCompiler* pComp, const StdMesh* Mesh)
{
static const StdEnumEntry<NodeType> NodeTypes[] =
{
{ "Leaf", LeafNode },
{ "LinearInterpolation", LinearInterpolationNode },
{ NULL, static_cast<NodeType>(0) }
};
pComp->Value(mkNamingAdapt(Slot, "Slot"));
pComp->Value(mkNamingAdapt(Number, "Number"));
pComp->Value(mkNamingAdapt(mkEnumAdapt(Type, NodeTypes), "Type"));
switch(Type)
{
case LeafNode:
if(pComp->isCompiler())
{
StdCopyStrBuf anim_name;
pComp->Value(mkNamingAdapt(toC4CStrBuf(anim_name), "Animation"));
Leaf.Animation = Mesh->GetAnimationByName(anim_name);
if(!Leaf.Animation) pComp->excCorrupt("No such animation: \"%s\"", anim_name.getData());
}
else
{
pComp->Value(mkNamingAdapt(mkParAdapt(mkDecompileAdapt(Leaf.Animation->Name), StdCompiler::RCT_All), "Animation"));
}
pComp->Value(mkNamingAdapt(mkValueProviderAdapt(&Leaf.Position), "Position"));
break;
case LinearInterpolationNode:
pComp->Value(mkParAdapt(mkNamingPtrAdapt(LinearInterpolation.ChildLeft, "ChildLeft"), Mesh));
pComp->Value(mkParAdapt(mkNamingPtrAdapt(LinearInterpolation.ChildRight, "ChildRight"), Mesh));
pComp->Value(mkNamingAdapt(mkValueProviderAdapt(&LinearInterpolation.Weight), "Weight"));
if(pComp->isCompiler())
{
if(LinearInterpolation.ChildLeft->Slot != Slot)
pComp->excCorrupt("Slot of left child does not match parent slot");
if(LinearInterpolation.ChildRight->Slot != Slot)
pComp->excCorrupt("Slof of right child does not match parent slot");
LinearInterpolation.ChildRight->Parent = this;
LinearInterpolation.ChildRight->Parent = this;
}
break;
default:
pComp->excCorrupt("Invalid animation node type");
break;
}
}
void StdMeshInstance::AnimationNode::EnumeratePointers()
{
SerializableValueProvider* value_provider = NULL;
switch(Type)
{
case LeafNode:
value_provider = dynamic_cast<SerializableValueProvider*>(Leaf.Position);
break;
case LinearInterpolationNode:
value_provider = dynamic_cast<SerializableValueProvider*>(LinearInterpolation.Weight);
break;
}
if(value_provider) value_provider->EnumeratePointers();
}
void StdMeshInstance::AnimationNode::DenumeratePointers()
{
SerializableValueProvider* value_provider = NULL;
switch(Type)
{
case LeafNode:
value_provider = dynamic_cast<SerializableValueProvider*>(Leaf.Position);
break;
case LinearInterpolationNode:
value_provider = dynamic_cast<SerializableValueProvider*>(LinearInterpolation.Weight);
break;
}
if(value_provider) value_provider->DenumeratePointers();
}
StdMeshInstance::AttachedMesh::AttachedMesh():
Number(0), Parent(NULL), Child(NULL), OwnChild(true), ChildDenumerator(NULL), ParentBone(0), ChildBone(0), FinalTransformDirty(false)
{
}
StdMeshInstance::AttachedMesh::AttachedMesh(unsigned int number, StdMeshInstance* parent, StdMeshInstance* child, bool own_child, Denumerator* denumerator,
unsigned int parent_bone, unsigned int child_bone, const StdMeshMatrix& transform):
Number(number), Parent(parent), Child(child), OwnChild(own_child), ChildDenumerator(denumerator),
ParentBone(parent_bone), ChildBone(child_bone), AttachTrans(transform),
FinalTransformDirty(true)
{
@ -901,6 +1083,7 @@ StdMeshInstance::AttachedMesh::~AttachedMesh()
{
if (OwnChild)
delete Child;
delete ChildDenumerator;
}
bool StdMeshInstance::AttachedMesh::SetParentBone(const StdStrBuf& bone)
@ -929,6 +1112,32 @@ void StdMeshInstance::AttachedMesh::SetAttachTransformation(const StdMeshMatrix&
FinalTransformDirty = true;
}
void StdMeshInstance::AttachedMesh::CompileFunc(StdCompiler* pComp, DenumeratorFactoryFunc Factory)
{
if(pComp->isCompiler())
{
FinalTransformDirty = true;
ChildDenumerator = Factory();
}
pComp->Value(mkNamingAdapt(Number, "Number"));
pComp->Value(mkNamingAdapt(ParentBone, "ParentBone")); // TODO: Save as string
pComp->Value(mkNamingAdapt(ChildBone, "ChildBone")); // TODO: Save as string (note we can only resolve this in DenumeratePointers then!)
pComp->Value(mkNamingAdapt(mkTransformAdapt(AttachTrans), "AttachTransformation"));
pComp->Value(mkParAdapt(*ChildDenumerator, this));
}
void StdMeshInstance::AttachedMesh::EnumeratePointers()
{
ChildDenumerator->EnumeratePointers(this);
}
void StdMeshInstance::AttachedMesh::DenumeratePointers()
{
ChildDenumerator->DenumeratePointers(this);
}
StdMeshInstance::StdMeshInstance(const StdMesh& mesh):
Mesh(mesh), CurrentFaceOrdering(FO_Fixed),
BoneTransforms(Mesh.GetNumBones(), StdMeshMatrix::Identity()),
@ -1198,17 +1407,19 @@ void StdMeshInstance::ExecuteAnimation(float dt)
(*iter)->Child->ExecuteAnimation(dt);
}
StdMeshInstance::AttachedMesh* StdMeshInstance::AttachMesh(const StdMesh& mesh, const StdStrBuf& parent_bone, const StdStrBuf& child_bone, const StdMeshMatrix& transformation)
StdMeshInstance::AttachedMesh* StdMeshInstance::AttachMesh(const StdMesh& mesh, AttachedMesh::Denumerator* denumerator, const StdStrBuf& parent_bone, const StdStrBuf& child_bone, const StdMeshMatrix& transformation)
{
StdMeshInstance* instance = new StdMeshInstance(mesh);
instance->SetFaceOrdering(CurrentFaceOrdering);
AttachedMesh* attach = AttachMesh(*instance, parent_bone, child_bone, transformation, true);
if (!attach) { delete instance; return NULL; }
AttachedMesh* attach = AttachMesh(*instance, denumerator, parent_bone, child_bone, transformation, true);
if (!attach) { delete instance; delete denumerator; return NULL; }
return attach;
}
StdMeshInstance::AttachedMesh* StdMeshInstance::AttachMesh(StdMeshInstance& instance, const StdStrBuf& parent_bone, const StdStrBuf& child_bone, const StdMeshMatrix& transformation, bool own_child)
StdMeshInstance::AttachedMesh* StdMeshInstance::AttachMesh(StdMeshInstance& instance, AttachedMesh::Denumerator* denumerator, const StdStrBuf& parent_bone, const StdStrBuf& child_bone, const StdMeshMatrix& transformation, bool own_child)
{
std::auto_ptr<AttachedMesh::Denumerator> auto_denumerator(denumerator);
// We don't allow an instance to be attached to multiple parent instances for now
if (instance.AttachParent) return NULL;
@ -1230,7 +1441,7 @@ StdMeshInstance::AttachedMesh* StdMeshInstance::AttachMesh(StdMeshInstance& inst
if (!parent_bone_obj || !child_bone_obj) return NULL;
// TODO: Face Ordering is not lined up... can't do that properly here
attach = new AttachedMesh(number, this, &instance, own_child, parent_bone_obj->Index, child_bone_obj->Index, transformation);
attach = new AttachedMesh(number, this, &instance, own_child, auto_denumerator.release(), parent_bone_obj->Index, child_bone_obj->Index, transformation);
instance.AttachParent = attach;
AttachChildren.push_back(attach);
@ -1377,6 +1588,94 @@ void StdMeshInstance::UpdateBoneTransforms()
BoneTransformsDirty = false;
}
void StdMeshInstance::CompileFunc(StdCompiler* pComp, AttachedMesh::DenumeratorFactoryFunc Factory)
{
if(pComp->isCompiler())
{
// Only initially created instances can be compiled
assert(!AttachParent);
assert(AttachChildren.empty());
assert(AnimationStack.empty());
BoneTransformsDirty = true;
int32_t iAnimCnt = AnimationStack.size();
pComp->Value(mkNamingCountAdapt(iAnimCnt, "AnimationNode"));
for(int32_t i = 0; i < iAnimCnt; ++i)
{
AnimationNode* node = NULL;
pComp->Value(mkParAdapt(mkNamingPtrAdapt(node, "AnimationNode"), &Mesh));
AnimationNodeList::iterator iter = GetStackIterForSlot(node->Slot, true);
if(*iter != NULL) { delete node; pComp->excCorrupt("Duplicate animation slot index"); }
*iter = node;
// Add nodes into lookup table
std::vector<AnimationNode*> nodes(1, node);
while(!nodes.empty())
{
node = nodes.back();
nodes.erase(nodes.end()-1);
AnimationNodes.resize(node->Number+1);
if(AnimationNodes[node->Number] != NULL) pComp->excCorrupt("Duplicate animation node number");
AnimationNodes[node->Number] = node;
if(node->Type == AnimationNode::LinearInterpolationNode)
{
nodes.push_back(node->LinearInterpolation.ChildLeft);
nodes.push_back(node->LinearInterpolation.ChildRight);
}
}
}
int32_t iAttachedCnt;
pComp->Value(mkNamingCountAdapt(iAttachedCnt, "Attached"));
for(int32_t i = 0; i < iAttachedCnt; ++i)
{
AttachChildren.push_back(new AttachedMesh);
AttachedMesh* attach = AttachChildren.back();
attach->Parent = this;
pComp->Value(mkNamingAdapt(mkParAdapt(*attach, Factory), "Attached"));
}
}
else
{
int32_t iAnimCnt = AnimationStack.size();
pComp->Value(mkNamingCountAdapt(iAnimCnt, "AnimationNode"));
for(AnimationNodeList::iterator iter = AnimationStack.begin(); iter != AnimationStack.end(); ++iter)
pComp->Value(mkParAdapt(mkNamingPtrAdapt(*iter, "AnimationNode"), &Mesh));
int32_t iAttachedCnt = AttachChildren.size();
pComp->Value(mkNamingCountAdapt(iAttachedCnt, "Attached"));
for(unsigned int i = 0; i < AttachChildren.size(); ++i)
pComp->Value(mkNamingAdapt(mkParAdapt(*AttachChildren[i], Factory), "Attached"));
}
}
void StdMeshInstance::EnumeratePointers()
{
for(unsigned int i = 0; i < AnimationNodes.size(); ++i)
if(AnimationNodes[i])
AnimationNodes[i]->EnumeratePointers();
for(unsigned int i = 0; i < AttachChildren.size(); ++i)
AttachChildren[i]->EnumeratePointers();
}
void StdMeshInstance::DenumeratePointers()
{
for(unsigned int i = 0; i < AnimationNodes.size(); ++i)
if(AnimationNodes[i])
AnimationNodes[i]->DenumeratePointers();
for(unsigned int i = 0; i < AttachChildren.size(); ++i)
AttachChildren[i]->DenumeratePointers();
}
StdMeshInstance::AnimationNodeList::iterator StdMeshInstance::GetStackIterForSlot(int slot, bool create)
{
// TODO: bsearch

View File

@ -21,6 +21,8 @@
#include <StdMeshMaterial.h>
class StdCompiler;
// OGRE mesh
struct StdMeshVector
@ -370,6 +372,71 @@ public:
FIXED Value; // Current provider value
};
// Serializable value providers need to be registered with SerializeableValueProvider::Register.
// They also need to implement a default constructor and a compile func
class SerializableValueProvider: public ValueProvider
{
public:
struct IDBase;
private:
// Pointer for deterministic initialization
static std::vector<IDBase*>* IDs;
public:
struct IDBase
{
typedef SerializableValueProvider*(*NewFunc)();
protected:
IDBase(const char* name, const std::type_info& type, NewFunc newfunc):
name(name), type(type), newfunc(newfunc)
{
if(!IDs) IDs = new std::vector<IDBase*>;
IDs->push_back(this);
}
public:
const char* name;
const std::type_info& type;
NewFunc newfunc;
};
template<typename T>
struct ID: IDBase
{
private:
static SerializableValueProvider* CreateFunc() { return new T; }
public:
ID(const char* name):
IDBase(name, typeid(T), CreateFunc) {}
};
static const IDBase* Lookup(const char* name)
{
if(!IDs) return NULL;
for(unsigned int i = 0; i < IDs->size(); ++i)
if(strcmp((*IDs)[i]->name, name) == 0)
return (*IDs)[i];
return NULL;
}
static const IDBase* Lookup(const std::type_info& type)
{
if(!IDs) return NULL;
for(unsigned int i = 0; i < IDs->size(); ++i)
if((*IDs)[i]->type == type)
return (*IDs)[i];
return NULL;
}
virtual void CompileFunc(StdCompiler* pComp);
virtual void EnumeratePointers() {}
virtual void DenumeratePointers() {}
};
// A node in the animation tree
// Can be either a leaf node, or interpolation between two other nodes
class AnimationNode
@ -378,6 +445,7 @@ public:
public:
enum NodeType { LeafNode, LinearInterpolationNode };
AnimationNode();
AnimationNode(const StdMeshAnimation* animation, ValueProvider* position);
AnimationNode(AnimationNode* child_left, AnimationNode* child_right, ValueProvider* weight);
~AnimationNode();
@ -398,11 +466,15 @@ public:
ValueProvider* GetWeightProvider() { assert(Type == LinearInterpolationNode); return LinearInterpolation.Weight; }
FIXED GetWeight() const { assert(Type == LinearInterpolationNode); return LinearInterpolation.Weight->Value; }
void CompileFunc(StdCompiler* pComp, const StdMesh* Mesh);
void EnumeratePointers();
void DenumeratePointers();
protected:
int Slot;
unsigned int Number;
NodeType Type;
AnimationNode* Parent;
AnimationNode* Parent; // NoSave
union
{
@ -441,37 +513,59 @@ public:
{
friend class StdMeshInstance;
public:
AttachedMesh(unsigned int number, StdMeshInstance* parent, StdMeshInstance* child, bool own_child,
// The job of this class is to help serialize the Child and OwnChild members of AttachedMesh
class Denumerator
{
public:
virtual ~Denumerator() {}
virtual void CompileFunc(StdCompiler* pComp, AttachedMesh* attach) = 0;
virtual void EnumeratePointers(AttachedMesh* attach) {}
virtual void DenumeratePointers(AttachedMesh* attach) {}
};
typedef Denumerator*(*DenumeratorFactoryFunc)();
template<typename T>
static Denumerator* DenumeratorFactory() { return new T; }
AttachedMesh();
AttachedMesh(unsigned int number, StdMeshInstance* parent, StdMeshInstance* child, bool own_child, Denumerator* denumerator,
unsigned int parent_bone, unsigned int child_bone, const StdMeshMatrix& transform);
~AttachedMesh();
const unsigned int Number;
StdMeshInstance* const Parent;
StdMeshInstance* const Child;
const bool OwnChild; // Whether to delete child on destruction
uint32_t Number;
StdMeshInstance* Parent; // NoSave (set by parent)
StdMeshInstance* Child;
bool OwnChild; // NoSave
Denumerator* ChildDenumerator;
bool SetParentBone(const StdStrBuf& bone);
bool SetChildBone(const StdStrBuf& bone);
void SetAttachTransformation(const StdMeshMatrix& transformation);
const StdMeshMatrix& GetFinalTransformation() const { return FinalTrans; }
void CompileFunc(StdCompiler* pComp, DenumeratorFactoryFunc Factory);
void EnumeratePointers();
void DenumeratePointers();
private:
unsigned int ParentBone;
unsigned int ChildBone;
StdMeshMatrix AttachTrans;
// Cache final attach transformation, updated in UpdateBoneTransform
StdMeshMatrix FinalTrans;
bool FinalTransformDirty; // Whether FinalTrans is up to date or not
StdMeshMatrix FinalTrans; // NoSave
bool FinalTransformDirty; // NoSave; Whether FinalTrans is up to date or not
};
typedef std::vector<AttachedMesh*> AttachedMeshList;
typedef AttachedMeshList::const_iterator AttachedMeshIter;
// Create a new instance and attach it to this mesh.
AttachedMesh* AttachMesh(const StdMesh& mesh, const StdStrBuf& parent_bone, const StdStrBuf& child_bone, const StdMeshMatrix& transformation = StdMeshMatrix::Identity());
// Attach an instance to this instance. If own_child is true then take ownership of instance, deleting it when the mesh is detached.
AttachedMesh* AttachMesh(StdMeshInstance& instance, const StdStrBuf& parent_bone, const StdStrBuf& child_bone, const StdMeshMatrix& transformation = StdMeshMatrix::Identity(), bool own_child = false);
// Create a new instance and attach it to this mesh. Takes ownership of denumerator
AttachedMesh* AttachMesh(const StdMesh& mesh, AttachedMesh::Denumerator* denumerator, const StdStrBuf& parent_bone, const StdStrBuf& child_bone, const StdMeshMatrix& transformation = StdMeshMatrix::Identity());
// Attach an instance to this instance. Takes ownership of denumerator. If own_child is true deletes instance on detach.
AttachedMesh* AttachMesh(StdMeshInstance& instance, AttachedMesh::Denumerator* denumerator, const StdStrBuf& parent_bone, const StdStrBuf& child_bone, const StdMeshMatrix& transformation = StdMeshMatrix::Identity(), bool own_child = false);
// Removes attachment with given number
bool DetachMesh(unsigned int number);
// Returns attached mesh with given number
@ -493,6 +587,10 @@ public:
// which would also not update its attach transformation. Call this once before rendering.
void UpdateBoneTransforms();
void CompileFunc(StdCompiler* pComp, AttachedMesh::DenumeratorFactoryFunc Factory);
void EnumeratePointers();
void DenumeratePointers();
const StdMesh& Mesh;
protected:
@ -521,4 +619,11 @@ private:
StdMeshInstance& operator=(const StdMeshInstance& other); // noncopyable
};
inline void CompileNewFuncCtx(StdMeshInstance::SerializableValueProvider *&pStruct, StdCompiler *pComp, const StdMeshInstance::SerializableValueProvider::IDBase& rID)
{
std::auto_ptr<StdMeshInstance::SerializableValueProvider> temp(rID.newfunc());
pComp->Value(*temp);
pStruct = temp.release();
}
#endif