Angelscript/add_on/serializer/serializer.h

194 lines
5.1 KiB
C++

//
// CSerializer
//
// This code was based on the CScriptReloader written by FDsagizi
// http://www.gamedev.net/topic/604890-dynamic-reloading-script/
//
#ifndef SERIALIZER_H
#define SERIALIZER_H
#ifndef ANGELSCRIPT_H
// Avoid having to inform include path if header is already include before
#include <angelscript.h>
#endif
#include <vector>
#include <string>
#include <map>
BEGIN_AS_NAMESPACE
class CSerializer;
class CSerializedValue;
// Need for register user types objects
// string, any, array... for all object
// user ref type.
struct CUserType
{
virtual ~CUserType() {};
virtual void Store(CSerializedValue *val, void *ptr) = 0;
virtual void Restore(CSerializedValue *val, void *ptr) = 0;
virtual void CleanupUserData(CSerializedValue * /*val*/) {}
};
class CSerializedValue
{
public:
CSerializedValue();
CSerializedValue(CSerializedValue *parent, const std::string &name, const std::string &nameSpace, void *ref, int typeId);
~CSerializedValue();
// Save the object and its children
void Store(void *ref, int refTypeId);
// Restore the object and its children
void Restore(void *ref, int refTypeId);
// Set type of this var
void SetType(int typeId);
// Returns the object type for non-primitives
asITypeInfo *GetType();
// Get child by name variable
CSerializedValue *FindByName(const std::string &name, const std::string &nameSpace);
// Find variable by ptr
CSerializedValue *FindByPtr(void *ptr);
// User data
void *GetUserData();
void SetUserData(void *data);
// Children, e.g. properties of a script class, or elements
// of an array, or object pointed to by a handle unless it
// is already a variable)
std::vector<CSerializedValue*> m_children;
protected:
friend class CSerializer;
void Init();
void Uninit();
// you first need to save all the objects before you can save references to objects
void ReplaceHandles();
// After the objects has been restored, the handles needs to
// be updated to point to the right objects
void RestoreHandles();
// Recursively get all ptrs of the children
void GetAllPointersOfChildren(std::vector<void*> *ptrs);
// may be that the two references refer to the same variable.
// But this variable is not available in the global list.
// According to this reference will be restores it.
// And so two links are not created 2 variables,
// it is necessary to cancel the creation of one of them.
void CancelDuplicates(CSerializedValue *from);
// Find variable by ptr but looking only at those in the references, which will create a new object
CSerializedValue *FindByPtrInHandles(void *ptr);
// ptr - is a handle to class
void *GetPointerToRestoredObject(void *ptr);
// Cleanup children
void ClearChildren();
// The serializer object
CSerializer *m_serializer;
// The user data can be used by CUserType to store extra information
void *m_userData;
// The type id of the stored value
int m_typeId;
// For non-primitives the typeId may change if the module is reloaded so
// it is necessary to store the type name to determine the new type id
std::string m_typeName;
// Name of variable or property
std::string m_name;
std::string m_nameSpace;
// Is initialized
bool m_isInit;
// 'this' pointer to variable.
// While storing, this points to the actual variable that was stored.
// While restoring, it is just a unique identifier.
void *m_originalPtr;
// where handle references
// While storing, this points to the actual object.
// While restoring, it is just a unique identifier.
void *m_handlePtr;
// new address object, ie address the restoration
// While storing this isn't used.
// While restoring it will point to the actual variable/object that is restored.
void *m_restorePtr;
// Serialized data for primitives
std::vector<char> m_mem;
};
// This class keeps a list of variables, then restores them after the script is rebuilt.
// But you have to be careful with the change of signature in classes, or
// changing the types of objects. You can remove or add variables, functions,
// methods, but you can not (yet) change the type of variables.
//
// You also need to understand that after a rebuild you should get
// new functions and typeids from the module.
class CSerializer
{
public:
CSerializer();
~CSerializer();
// Add implementation for serializing user types
void AddUserType(CUserType *ref, const std::string &name);
// Store all global variables in the module
int Store(asIScriptModule *mod);
// Restore all global variables after reloading script
int Restore(asIScriptModule *mod);
// Store extra objects that are not seen from the module's global variables
void AddExtraObjectToStore(asIScriptObject *object);
// Return new pointer to restored object
void *GetPointerToRestoredObject(void *originalObject);
protected:
friend class CSerializedValue;
CSerializedValue m_root;
asIScriptEngine *m_engine;
asIScriptModule *m_mod;
std::map<std::string, CUserType*> m_userTypes;
struct SExtraObject
{
asIScriptObject *originalObject;
std::string originalClassName;
int originalTypeId;
};
std::vector<SExtraObject> m_extraObjects;
};
END_AS_NAMESPACE
#endif