BsScriptSerializableUtility.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Wrappers/BsScriptSerializableUtility.h"
  4. #include "BsMonoManager.h"
  5. #include "BsMonoClass.h"
  6. #include "BsMonoMethod.h"
  7. #include "BsMonoUtil.h"
  8. #include "Serialization/BsScriptAssemblyManager.h"
  9. #include "Serialization/BsManagedSerializableField.h"
  10. #include "Serialization/BsMemorySerializer.h"
  11. namespace bs
  12. {
  13. ScriptSerializableUtility::ScriptSerializableUtility(MonoObject* instance)
  14. :ScriptObject(instance)
  15. { }
  16. void ScriptSerializableUtility::initRuntimeData()
  17. {
  18. metaData.scriptClass->addInternalCall("Internal_Clone", (void*)&ScriptSerializableUtility::internal_Clone);
  19. metaData.scriptClass->addInternalCall("Internal_Create", (void*)&ScriptSerializableUtility::internal_Create);
  20. }
  21. MonoObject* ScriptSerializableUtility::internal_Clone(MonoObject* original)
  22. {
  23. if (original == nullptr)
  24. return nullptr;
  25. ::MonoClass* monoClass = MonoUtil::getClass(original);
  26. MonoClass* engineClass = MonoManager::instance().findClass(monoClass);
  27. SPtr<ManagedSerializableTypeInfo> typeInfo = ScriptAssemblyManager::instance().getTypeInfo(engineClass);
  28. if (typeInfo == nullptr)
  29. {
  30. LOGWRN("Cannot clone an instance of type \"" +
  31. engineClass->getFullName() + "\", it is not marked as serializable.");
  32. return nullptr;
  33. }
  34. SPtr<ManagedSerializableFieldData> data = ManagedSerializableFieldData::create(typeInfo, original);
  35. MemorySerializer ms;
  36. // Note: This code unnecessarily encodes to binary and decodes from it. I could have added a specialized clone method that does it directly,
  37. // but didn't feel the extra code was justified.
  38. UINT32 size = 0;
  39. UINT8* encodedData = ms.encode(data.get(), size);
  40. SPtr<ManagedSerializableFieldData> clonedData = std::static_pointer_cast<ManagedSerializableFieldData>(ms.decode(encodedData, size));
  41. clonedData->deserialize();
  42. return clonedData->getValueBoxed(typeInfo);
  43. }
  44. MonoObject* ScriptSerializableUtility::internal_Create(MonoReflectionType* reflType)
  45. {
  46. if (reflType == nullptr)
  47. return nullptr;
  48. ::MonoClass* monoClass = MonoUtil::getClass(reflType);
  49. MonoClass* engineClass = MonoManager::instance().findClass(monoClass);
  50. SPtr<ManagedSerializableTypeInfo> typeInfo = ScriptAssemblyManager::instance().getTypeInfo(engineClass);
  51. if (typeInfo == nullptr)
  52. {
  53. LOGWRN("Cannot create an instance of type \"" +
  54. engineClass->getFullName() + "\", it is not marked as serializable.");
  55. return nullptr;
  56. }
  57. SPtr<ManagedSerializableFieldData> data = ManagedSerializableFieldData::createDefault(typeInfo);
  58. MemorySerializer ms;
  59. // Note: This code unnecessarily encodes to binary and decodes from it. I could have added a specialized create method that does it directly,
  60. // but didn't feel the extra code was justified.
  61. UINT32 size = 0;
  62. UINT8* encodedData = ms.encode(data.get(), size);
  63. SPtr<ManagedSerializableFieldData> createdData = std::static_pointer_cast<ManagedSerializableFieldData>(ms.decode(encodedData, size));
  64. createdData->deserialize();
  65. return createdData->getValueBoxed(typeInfo);
  66. }
  67. }