| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
- //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
- #include "Serialization/BsManagedSerializableObject.h"
- #include "RTTI/BsManagedSerializableObjectRTTI.h"
- #include "Serialization/BsManagedSerializableObjectInfo.h"
- #include "Serialization/BsManagedSerializableField.h"
- #include "Serialization/BsScriptAssemblyManager.h"
- #include "BsMonoField.h"
- #include "BsMonoClass.h"
- #include "BsMonoUtil.h"
- namespace bs
- {
- inline size_t ManagedSerializableObject::Hash::operator()(const ManagedSerializableFieldKey& x) const
- {
- size_t seed = 0;
- hash_combine(seed, (UINT32)x.mFieldId);
- hash_combine(seed, (UINT32)x.mTypeId);
- return seed;
- }
- inline bool ManagedSerializableObject::Equals::operator()(const ManagedSerializableFieldKey& a, const ManagedSerializableFieldKey& b) const
- {
- return a.mFieldId == b.mFieldId && a.mTypeId == b.mTypeId;
- }
- ManagedSerializableObject::ManagedSerializableObject(const ConstructPrivately& dummy)
- {
- }
- ManagedSerializableObject::ManagedSerializableObject(const ConstructPrivately& dummy, SPtr<ManagedSerializableObjectInfo> objInfo, MonoObject* managedInstance)
- :mObjInfo(objInfo)
- {
- mGCHandle = MonoUtil::newGCHandle(managedInstance, false);
- }
- ManagedSerializableObject::~ManagedSerializableObject()
- {
- if(mGCHandle != 0)
- {
- MonoUtil::freeGCHandle(mGCHandle);
- mGCHandle = 0;
- }
- }
- SPtr<ManagedSerializableObject> ManagedSerializableObject::createFromExisting(MonoObject* managedInstance)
- {
- if(managedInstance == nullptr)
- return nullptr;
- String elementNs;
- String elementTypeName;
- MonoUtil::getClassName(managedInstance, elementNs, elementTypeName);
- SPtr<ManagedSerializableObjectInfo> objInfo;
- if(!ScriptAssemblyManager::instance().getSerializableObjectInfo(elementNs, elementTypeName, objInfo))
- return nullptr;
- return bs_shared_ptr_new<ManagedSerializableObject>(ConstructPrivately(), objInfo, managedInstance);
- }
- SPtr<ManagedSerializableObject> ManagedSerializableObject::createNew(const SPtr<ManagedSerializableTypeInfoObject>& type)
- {
- SPtr<ManagedSerializableObjectInfo> currentObjInfo = nullptr;
- // See if this type even still exists
- if (!ScriptAssemblyManager::instance().getSerializableObjectInfo(type->mTypeNamespace, type->mTypeName, currentObjInfo))
- return nullptr;
- return bs_shared_ptr_new<ManagedSerializableObject>(ConstructPrivately(), currentObjInfo, createManagedInstance(type));
- }
- MonoObject* ManagedSerializableObject::createManagedInstance(const SPtr<ManagedSerializableTypeInfoObject>& type)
- {
- SPtr<ManagedSerializableObjectInfo> currentObjInfo = nullptr;
- // See if this type even still exists
- if (!ScriptAssemblyManager::instance().getSerializableObjectInfo(type->mTypeNamespace, type->mTypeName, currentObjInfo))
- return nullptr;
- if(!currentObjInfo->mTypeInfo->mFlags.isSet(ScriptTypeFlag::Serializable))
- return nullptr;
- const bool construct = currentObjInfo->mMonoClass->getMethod(".ctor", 0) != nullptr;
- return currentObjInfo->mMonoClass->createInstance(construct);
- }
- SPtr<ManagedSerializableObject> ManagedSerializableObject::createEmpty()
- {
- return bs_shared_ptr_new<ManagedSerializableObject>(ConstructPrivately());
- }
- MonoObject* ManagedSerializableObject::getManagedInstance() const
- {
- if(mGCHandle != 0)
- return MonoUtil::getObjectFromGCHandle(mGCHandle);
- return nullptr;
- }
- void ManagedSerializableObject::serialize()
- {
- if(mGCHandle == 0)
- return;
- mCachedData.clear();
- SPtr<ManagedSerializableObjectInfo> curType = mObjInfo;
- while (curType != nullptr)
- {
- for (auto& field : curType->mFields)
- {
- if (field.second->isSerializable())
- {
- ManagedSerializableFieldKey key(field.second->mParentTypeId, field.second->mFieldId);
- mCachedData[key] = getFieldData(field.second);
- }
- }
- curType = curType->mBaseClass;
- }
- // Serialize children
- for (auto& fieldEntry : mCachedData)
- fieldEntry.second->serialize();
- MonoUtil::freeGCHandle(mGCHandle);
- mGCHandle = 0;
- }
- MonoObject* ManagedSerializableObject::deserialize()
- {
- // See if this type even still exists
- SPtr<ManagedSerializableObjectInfo> currentObjInfo = nullptr;
- if (!ScriptAssemblyManager::instance().getSerializableObjectInfo(mObjInfo->mTypeInfo->mTypeNamespace,
- mObjInfo->mTypeInfo->mTypeName, currentObjInfo))
- {
- return nullptr;
- }
- MonoObject* managedInstance = createManagedInstance(currentObjInfo->mTypeInfo);
- deserialize(managedInstance, currentObjInfo);
- return managedInstance;
- }
- void ManagedSerializableObject::deserialize(MonoObject* instance, const SPtr<ManagedSerializableObjectInfo>& objInfo)
- {
- if (instance == nullptr)
- return;
- // Deserialize children
- for (auto& fieldEntry : mCachedData)
- fieldEntry.second->deserialize();
- // Scan all fields and ensure the fields still exist
- UINT32 i = 0;
- SPtr<ManagedSerializableObjectInfo> curType = mObjInfo;
- while (curType != nullptr)
- {
- for (auto& field : curType->mFields)
- {
- if (field.second->isSerializable())
- {
- UINT32 fieldId = field.second->mFieldId;
- UINT32 typeID = field.second->mParentTypeId;
- ManagedSerializableFieldKey key(typeID, fieldId);
- SPtr<ManagedSerializableMemberInfo> matchingFieldInfo = objInfo->findMatchingField(field.second, curType->mTypeInfo);
- if (matchingFieldInfo != nullptr)
- matchingFieldInfo->setValue(instance, mCachedData[key]->getValue(matchingFieldInfo->mTypeInfo));
- i++;
- }
- }
- curType = curType->mBaseClass;
- }
- }
- void ManagedSerializableObject::setFieldData(const SPtr<ManagedSerializableMemberInfo>& fieldInfo, const SPtr<ManagedSerializableFieldData>& val)
- {
- if (mGCHandle != 0)
- {
- MonoObject* managedInstance = MonoUtil::getObjectFromGCHandle(mGCHandle);
- fieldInfo->setValue(managedInstance, val->getValue(fieldInfo->mTypeInfo));
- }
- else
- {
- ManagedSerializableFieldKey key(fieldInfo->mParentTypeId, fieldInfo->mFieldId);
- mCachedData[key] = val;
- }
- }
- SPtr<ManagedSerializableFieldData> ManagedSerializableObject::getFieldData(const SPtr<ManagedSerializableMemberInfo>& fieldInfo) const
- {
- if (mGCHandle != 0)
- {
- MonoObject* managedInstance = MonoUtil::getObjectFromGCHandle(mGCHandle);
- MonoObject* fieldValue = fieldInfo->getValue(managedInstance);
- return ManagedSerializableFieldData::create(fieldInfo->mTypeInfo, fieldValue);
- }
- else
- {
- ManagedSerializableFieldKey key(fieldInfo->mParentTypeId, fieldInfo->mFieldId);
- auto iterFind = mCachedData.find(key);
- if (iterFind != mCachedData.end())
- return iterFind->second;
- return nullptr;
- }
- }
- RTTITypeBase* ManagedSerializableObject::getRTTIStatic()
- {
- return ManagedSerializableObjectRTTI::instance();
- }
- RTTITypeBase* ManagedSerializableObject::getRTTI() const
- {
- return ManagedSerializableObject::getRTTIStatic();
- }
- }
|