From: Daniel Karbach Date: Sun, 17 Mar 2013 17:09:08 +0000 (+0100) Subject: initialize objects after loading X-Git-Url: http://git.localhorst.tv/?p=l2e.git;a=commitdiff_plain;h=0e7b9eca67383e45e04aa419cb783c92722f7801 initialize objects after loading this links the vtables and runs any custom loading function --- diff --git a/src/graphics/Animation.cpp b/src/graphics/Animation.cpp index 602d7ef..bdd4b29 100644 --- a/src/graphics/Animation.cpp +++ b/src/graphics/Animation.cpp @@ -14,6 +14,11 @@ using loader::TypeDescription; namespace graphics { +Animation::Animation(loader::noinit_t) { + +} + + void Animation::CreateTypeDescription() { TypeDescription &td(TypeDescription::Create(TYPE_ID, "Animation")); td.SetDescription("Abstract base type for animations."); diff --git a/src/graphics/Animation.h b/src/graphics/Animation.h index a224f54..ddbf095 100644 --- a/src/graphics/Animation.h +++ b/src/graphics/Animation.h @@ -11,6 +11,7 @@ namespace loader { #include "../app/Timer.h" #include "../math/Vector.h" +#include "../loader/noinit.h" #include #include @@ -30,6 +31,8 @@ public: Animation(const Sprite *sprite, int frameTime, bool repeat = false) : sprite(sprite), frameTime(frameTime), repeat(repeat) { } virtual ~Animation() { }; +protected: + Animation(loader::noinit_t); public: const Sprite *GetSprite() const { return sprite; } diff --git a/src/graphics/ComplexAnimation.cpp b/src/graphics/ComplexAnimation.cpp index 95f5869..942db77 100644 --- a/src/graphics/ComplexAnimation.cpp +++ b/src/graphics/ComplexAnimation.cpp @@ -26,6 +26,11 @@ ComplexAnimation::ComplexAnimation( } +ComplexAnimation::ComplexAnimation(loader::noinit_t n) +: Animation(n) { + +} + int ComplexAnimation::NumFrames() const { return numFrames; @@ -51,6 +56,7 @@ void ComplexAnimation::CreateTypeDescription() { TypeDescription &td(TypeDescription::Create(TYPE_ID, "ComplexAnimation")); td.SetDescription("Complex animation type that supports per-frame disposition and non-linear sprite offset selection."); td.SetConstructor(&Construct); + td.SetInitializer(&Initialize); td.SetSize(sizeof(ComplexAnimation)); td.AddSupertype(Animation::TYPE_ID, ((char *)a) - ((char *)&ca)); @@ -73,4 +79,8 @@ void ComplexAnimation::Construct(void *data) { new (data) ComplexAnimation; } +void ComplexAnimation::Initialize(void *data) { + new (data) ComplexAnimation(loader::noinit); +} + } diff --git a/src/graphics/ComplexAnimation.h b/src/graphics/ComplexAnimation.h index 92562c5..380ea2a 100644 --- a/src/graphics/ComplexAnimation.h +++ b/src/graphics/ComplexAnimation.h @@ -2,6 +2,7 @@ #define GRAPHICS_COMPLEXANIMATION_H_ #include "Animation.h" +#include "../loader/noinit.h" namespace graphics { @@ -14,6 +15,8 @@ public: public: ComplexAnimation(); ComplexAnimation(const Sprite *sprite, int frameTime, bool repeat = false); +protected: + ComplexAnimation(loader::noinit_t); public: struct FrameProp { @@ -29,6 +32,7 @@ public: static void CreateTypeDescription(); static void Construct(void *); + static void Initialize(void *); protected: virtual int NumFrames() const; diff --git a/src/graphics/SimpleAnimation.cpp b/src/graphics/SimpleAnimation.cpp index 24985f9..75a327b 100644 --- a/src/graphics/SimpleAnimation.cpp +++ b/src/graphics/SimpleAnimation.cpp @@ -30,6 +30,11 @@ SimpleAnimation::SimpleAnimation( } +SimpleAnimation::SimpleAnimation(loader::noinit_t n) +: Animation(n) { + +} + int SimpleAnimation::NumFrames() const { return numFrames; @@ -51,6 +56,7 @@ void SimpleAnimation::CreateTypeDescription() { TypeDescription &td(TypeDescription::Create(TYPE_ID, "SimpleAnimation")); td.SetDescription("An animation that uses a fixed column and increasing row of a sprite based on the frame number."); td.SetConstructor(&Construct); + td.SetInitializer(&Initialize); td.SetSize(sizeof(SimpleAnimation)); td.AddSupertype(Animation::TYPE_ID, ((char *)a) - ((char *)&sa)); @@ -64,4 +70,8 @@ void SimpleAnimation::Construct(void *data) { new (data) SimpleAnimation; } +void SimpleAnimation::Initialize(void *data) { + new (data) SimpleAnimation(loader::noinit); +} + } diff --git a/src/graphics/SimpleAnimation.h b/src/graphics/SimpleAnimation.h index 7e5a99a..0864d2b 100644 --- a/src/graphics/SimpleAnimation.h +++ b/src/graphics/SimpleAnimation.h @@ -2,6 +2,7 @@ #define GRAPHICS_SIMPLEANIMATION_H_ #include "Animation.h" +#include "../loader/noinit.h" namespace graphics { @@ -15,6 +16,8 @@ public: SimpleAnimation(); SimpleAnimation(const Sprite *sprite, int frameTime, int numFrames, int col = 0, int row = 0, bool repeat = false); +protected: + SimpleAnimation(loader::noinit_t); public: void SetNumFrames(int n) { numFrames = n; } @@ -23,6 +26,7 @@ public: static void CreateTypeDescription(); static void Construct(void *); + static void Initialize(void *); protected: virtual int NumFrames() const; diff --git a/src/loader/Loader.cpp b/src/loader/Loader.cpp index dbfbe31..961ec7c 100644 --- a/src/loader/Loader.cpp +++ b/src/loader/Loader.cpp @@ -61,6 +61,13 @@ void Loader::Load(const std::string &filePath) { LoadImages(header->ident, header->ImagesBegin(), header->ImagesEnd()); + + InitObjects( + header->ObjectsBegin(), + header->ObjectsEnd()); + InitArrays( + header->ArraysBegin(), + header->ArraysEnd()); } catch (...) { delete[] block; throw; @@ -159,4 +166,42 @@ void Loader::LoadArrays(char *src, Array *begin, Array *end) { } } + +void Loader::InitObjects(Object *begin, Object *end) { + for (Object *i = begin; i < end; i = i->Next()) { + const TypeDescription &td = + TypeDescription::Get(i->typeId); + InitObject(i->RawObject(), td); + } +} + +void Loader::InitObject(char *object, const TypeDescription &td) { + td.Init(object); + td.Load(object); + for (TypeDescription::FieldIterator + i(td.FieldsBegin()), end(td.FieldsEnd()); + i != end; ++i) { + const FieldDescription &field = i->second; + if (field.IsReferenced() || field.IsAggregate()) { + continue; + } + const TypeDescription &nestedType + = TypeDescription::Get(field.TypeId()); + InitObject(object + field.Offset(), nestedType); + } +} + +void Loader::InitArrays(Array *begin, Array *end) { + for (Array *i = begin; i < end; i = i->Next()) { + if (i->ref) { + continue; + } + const TypeDescription &td = TypeDescription::Get(i->typeId); + for (char *j = i->Data(), *end = i->Data() + i->size; + j < end; j += td.Size()) { + InitObject(j, td); + } + } +} + } diff --git a/src/loader/Loader.h b/src/loader/Loader.h index 0839ecb..5087638 100644 --- a/src/loader/Loader.h +++ b/src/loader/Loader.h @@ -29,6 +29,10 @@ private: void LoadObject(char *src, char *dest, const TypeDescription &); void LoadArrays(char *src, Array *begin, Array *end); + void InitObjects(Object *begin, Object *end); + void InitObject(char *object, const TypeDescription &); + void InitArrays(Array *begin, Array *end); + private: std::map objectFiles; std::map exports; diff --git a/src/loader/TypeDescription.cpp b/src/loader/TypeDescription.cpp index 19974fb..bd63d70 100644 --- a/src/loader/TypeDescription.cpp +++ b/src/loader/TypeDescription.cpp @@ -46,6 +46,12 @@ void TypeDescription::Construct(void *data) const { } } +void TypeDescription::Init(void *data) const { + if (initializer) { + (*initializer)(data); + } +} + void TypeDescription::Load(void *data) const { if (loader) { (*loader)(data); diff --git a/src/loader/TypeDescription.h b/src/loader/TypeDescription.h index 7b74836..078002f 100644 --- a/src/loader/TypeDescription.h +++ b/src/loader/TypeDescription.h @@ -40,9 +40,11 @@ public: bool HasField(const std::string &name) const; const FieldDescription &GetField(const std::string &name) const; void Construct(void *) const; + void Init(void *) const; void Load(void *) const; void SetConstructor(void (*ctor)(void *)) { constructor = ctor; } + void SetInitializer(void (*init)(void *)) { initializer = init; } void SetLoader(void (*ld)(void *)) { loader = ld; } void AddSupertype(int id, std::ptrdiff_t offset); bool IsSubtypeOf(int id) const; @@ -72,10 +74,19 @@ public: static void WriteSourceWiki(std::ostream &); private: - TypeDescription(int id, const std::string &name) : constructor(0), loader(0), description(0), name(name), id(id), size(0) { } + TypeDescription(int id, const std::string &name) + : constructor(0) + , initializer(0) + , loader(0) + , description(0) + , name(name) + , id(id) + , size(0) + { } private: void (*constructor)(void *); + void (*initializer)(void *); void (*loader)(void *); const char *description; std::string name; diff --git a/src/loader/noinit.h b/src/loader/noinit.h new file mode 100644 index 0000000..fe9ce7e --- /dev/null +++ b/src/loader/noinit.h @@ -0,0 +1,12 @@ +#ifndef LOADER_NOINIT_H_ +#define LOADER_NOINIT_H_ + +namespace loader { + +enum noinit_t { + noinit, +}; + +} + +#endif