// // 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 #endif #include #include #include 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 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 *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 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 m_userTypes; struct SExtraObject { asIScriptObject *originalObject; std::string originalClassName; int originalTypeId; }; std::vector m_extraObjects; }; END_AS_NAMESPACE #endif