forked from Mirrors/openclonk
Implement mesh serialization
parent
79d2c869ed
commit
6b53d75997
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue