Refactor Variant type ManagedObject serialization to be usable for Visual Scripting
This commit is contained in:
@@ -359,6 +359,7 @@ namespace FlaxEditor.Utilities
|
||||
Type type = null;
|
||||
var variantType = (VariantType)stream.ReadByte();
|
||||
var typeNameLength = stream.ReadInt32();
|
||||
string typeName = string.Empty;
|
||||
if (typeNameLength == int.MaxValue)
|
||||
{
|
||||
typeNameLength = stream.ReadInt32();
|
||||
@@ -368,7 +369,7 @@ namespace FlaxEditor.Utilities
|
||||
var c = stream.ReadByte();
|
||||
data[i] = (byte)(c ^ 77);
|
||||
}
|
||||
var typeName = System.Text.Encoding.ASCII.GetString(data);
|
||||
typeName = System.Text.Encoding.ASCII.GetString(data);
|
||||
type = TypeUtils.GetManagedType(typeName);
|
||||
}
|
||||
else if (typeNameLength > 0)
|
||||
@@ -380,13 +381,12 @@ namespace FlaxEditor.Utilities
|
||||
var c = stream.ReadUInt16();
|
||||
data[i] = (char)(c ^ 77);
|
||||
}
|
||||
var typeName = new string(data);
|
||||
typeName = new string(data);
|
||||
type = TypeUtils.GetManagedType(typeName);
|
||||
}
|
||||
switch (variantType)
|
||||
{
|
||||
case VariantType.Null:
|
||||
case VariantType.ManagedObject:
|
||||
case VariantType.Void: return null;
|
||||
case VariantType.Bool: return stream.ReadByte() != 0;
|
||||
case VariantType.Int16: return stream.ReadInt16();
|
||||
@@ -475,9 +475,26 @@ namespace FlaxEditor.Utilities
|
||||
var c = stream.ReadByte();
|
||||
data[i] = (byte)(c ^ -14);
|
||||
}
|
||||
var typeName = System.Text.Encoding.ASCII.GetString(data);
|
||||
typeName = System.Text.Encoding.ASCII.GetString(data);
|
||||
return TypeUtils.GetType(typeName);
|
||||
}
|
||||
case VariantType.ManagedObject:
|
||||
{
|
||||
if (type == null)
|
||||
throw new Exception("Missing type of the Variant typename " + typeName);
|
||||
var format = stream.ReadByte();
|
||||
if (format == 0)
|
||||
{
|
||||
// No Data
|
||||
}
|
||||
else if (format == 1)
|
||||
{
|
||||
// Json
|
||||
var json = stream.ReadStrAnsi(-71);
|
||||
return FlaxEngine.Json.JsonSerializer.Deserialize(json, type);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
default: throw new ArgumentOutOfRangeException($"Unknown Variant Type {variantType}." + (type != null ? $" Type: {type.FullName}" : string.Empty));
|
||||
}
|
||||
}
|
||||
@@ -515,6 +532,7 @@ namespace FlaxEditor.Utilities
|
||||
break;
|
||||
case VariantType.Enum:
|
||||
case VariantType.Structure:
|
||||
case VariantType.ManagedObject:
|
||||
stream.Write(int.MaxValue);
|
||||
stream.WriteStrAnsi(type.FullName, 77);
|
||||
break;
|
||||
@@ -645,6 +663,14 @@ namespace FlaxEditor.Utilities
|
||||
else if (value is ScriptType)
|
||||
stream.WriteStrAnsi(((ScriptType)value).TypeName, -14);
|
||||
break;
|
||||
case VariantType.ManagedObject:
|
||||
{
|
||||
stream.Write((byte)1);
|
||||
var json = FlaxEngine.Json.JsonSerializer.Serialize(value, type);
|
||||
stream.WriteStrAnsi(json, -71);
|
||||
break;
|
||||
}
|
||||
default: throw new ArgumentOutOfRangeException($"Unknown Variant Type {variantType} for type {type.FullName}.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -700,7 +726,6 @@ namespace FlaxEditor.Utilities
|
||||
switch (variantType)
|
||||
{
|
||||
case VariantType.Null:
|
||||
case VariantType.ManagedObject:
|
||||
case VariantType.Void:
|
||||
stream.WriteStartObject();
|
||||
stream.WriteEndObject();
|
||||
@@ -1089,7 +1114,13 @@ namespace FlaxEditor.Utilities
|
||||
else if (value is ScriptType)
|
||||
stream.WriteValue(((ScriptType)value).TypeName);
|
||||
break;
|
||||
default: throw new NotImplementedException($"TODO: serialize {variantType} to Json");
|
||||
case VariantType.ManagedObject:
|
||||
{
|
||||
var json = FlaxEngine.Json.JsonSerializer.Serialize(value, type);
|
||||
stream.WriteRaw(json);
|
||||
break;
|
||||
}
|
||||
default: throw new ArgumentOutOfRangeException($"Unknown Variant Type {variantType} for type {type.FullName}.");
|
||||
}
|
||||
// ReSharper restore PossibleNullReferenceException
|
||||
|
||||
|
||||
@@ -289,7 +289,7 @@ void VisualScriptExecutor::ProcessGroupPacking(Box* box, Node* node, Value& valu
|
||||
if (mclass)
|
||||
{
|
||||
// Fallback to C#-only types
|
||||
auto instance = mono_gchandle_get_target(structureValue.AsUint);
|
||||
auto instance = (MonoObject*)structureValue.AsUint;
|
||||
CHECK(instance);
|
||||
if (structureValue.Type.Type != VariantType::ManagedObject || mono_object_get_class(instance) != mclass->GetNative())
|
||||
{
|
||||
@@ -1768,7 +1768,18 @@ ScriptingObject* VisualScriptingBinaryModule::VisualScriptObjectSpawn(const Scri
|
||||
auto& instanceParams = visualScript->_instances[object->GetID()].Params;
|
||||
instanceParams.Resize(visualScript->Graph.Parameters.Count());
|
||||
for (int32 i = 0; i < instanceParams.Count(); i++)
|
||||
instanceParams[i] = visualScript->Graph.Parameters[i].Value;
|
||||
{
|
||||
auto& param = instanceParams[i];
|
||||
param = visualScript->Graph.Parameters[i].Value;
|
||||
if (param.Type.Type == VariantType::ManagedObject)
|
||||
{
|
||||
// Special case for C# object property in Visual Script so duplicate the object instead of cloning the reference to it
|
||||
MemoryWriteStream writeStream;
|
||||
writeStream.WriteVariant(param);
|
||||
MemoryReadStream readStream(writeStream.GetHandle(), writeStream.GetPosition());
|
||||
readStream.ReadVariant(¶m);
|
||||
}
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
@@ -2135,9 +2146,9 @@ VisualScript::Instance* VisualScript::GetScriptInstance(ScriptingObject* instanc
|
||||
return instance ? _instances.TryGet(instance->GetID()) : nullptr;
|
||||
}
|
||||
|
||||
Variant VisualScript::GetScriptInstanceParameterValue(const StringView& name, ScriptingObject* instance) const
|
||||
const Variant& VisualScript::GetScriptInstanceParameterValue(const StringView& name, ScriptingObject* instance) const
|
||||
{
|
||||
CHECK_RETURN(instance, Variant());
|
||||
CHECK_RETURN(instance, Variant::Null);
|
||||
for (int32 paramIndex = 0; paramIndex < Graph.Parameters.Count(); paramIndex++)
|
||||
{
|
||||
if (Graph.Parameters[paramIndex].Name == name)
|
||||
@@ -2150,7 +2161,7 @@ Variant VisualScript::GetScriptInstanceParameterValue(const StringView& name, Sc
|
||||
}
|
||||
}
|
||||
LOG(Warning, "Failed to get {0} parameter '{1}'", ToString(), name);
|
||||
return Variant();
|
||||
return Variant::Null;
|
||||
}
|
||||
|
||||
void VisualScript::SetScriptInstanceParameterValue(const StringView& name, ScriptingObject* instance, const Variant& value) const
|
||||
|
||||
@@ -210,7 +210,7 @@ public:
|
||||
/// <param name="name">The parameter name.</param>
|
||||
/// <param name="instance">The object instance.</param>
|
||||
/// <returns>The property value.</returns>
|
||||
API_FUNCTION() Variant GetScriptInstanceParameterValue(const StringView& name, ScriptingObject* instance) const;
|
||||
API_FUNCTION() const Variant& GetScriptInstanceParameterValue(const StringView& name, ScriptingObject* instance) const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of the Visual Script parameter of the given instance.
|
||||
|
||||
@@ -57,6 +57,20 @@ VariantType::VariantType(Types type, const StringAnsiView& typeName)
|
||||
}
|
||||
}
|
||||
|
||||
VariantType::VariantType(Types type, _MonoClass* klass)
|
||||
{
|
||||
Type = type;
|
||||
TypeName = nullptr;
|
||||
if (klass)
|
||||
{
|
||||
MString typeName;
|
||||
MUtils::GetClassFullname(klass, typeName);
|
||||
int32 length = typeName.Length() + 1;
|
||||
TypeName = static_cast<char*>(Allocator::Allocate(length));
|
||||
Platform::MemoryCopy(TypeName, typeName.Get(), length);
|
||||
}
|
||||
}
|
||||
|
||||
VariantType::VariantType(const VariantType& other)
|
||||
{
|
||||
Type = other.Type;
|
||||
@@ -501,7 +515,7 @@ Variant::Variant(Asset* v)
|
||||
}
|
||||
|
||||
Variant::Variant(_MonoObject* v)
|
||||
: Type(VariantType::ManagedObject)
|
||||
: Type(VariantType::ManagedObject, v ? mono_object_get_class(v) : nullptr)
|
||||
{
|
||||
AsUint = v ? mono_gchandle_new(v, true) : 0;
|
||||
}
|
||||
@@ -999,6 +1013,7 @@ bool Variant::operator==(const Variant& other) const
|
||||
}
|
||||
return true;
|
||||
case VariantType::ManagedObject:
|
||||
// TODO: invoke C# Equality logic?
|
||||
return AsUint == other.AsUint || mono_gchandle_get_target(AsUint) == mono_gchandle_get_target(other.AsUint);
|
||||
case VariantType::Typename:
|
||||
if (AsBlob.Data == nullptr && other.AsBlob.Data == nullptr)
|
||||
@@ -1443,7 +1458,7 @@ Variant::operator void*() const
|
||||
case VariantType::Blob:
|
||||
return AsBlob.Data;
|
||||
case VariantType::ManagedObject:
|
||||
return mono_gchandle_get_target(AsUint);
|
||||
return AsUint ? mono_gchandle_get_target(AsUint) : nullptr;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1484,6 +1499,11 @@ Variant::operator ScriptingObject*() const
|
||||
}
|
||||
}
|
||||
|
||||
Variant::operator _MonoObject*() const
|
||||
{
|
||||
return AsUint ? mono_gchandle_get_target(AsUint) : nullptr;
|
||||
}
|
||||
|
||||
Variant::operator Asset*() const
|
||||
{
|
||||
switch (Type.Type)
|
||||
@@ -2220,6 +2240,22 @@ void Variant::SetObject(ScriptingObject* object)
|
||||
object->Deleted.Bind<Variant, &Variant::OnObjectDeleted>(this);
|
||||
}
|
||||
|
||||
void Variant::SetManagedObject(_MonoObject* object)
|
||||
{
|
||||
if (object)
|
||||
{
|
||||
if (Type.Type != VariantType::ManagedObject)
|
||||
SetType(VariantType(VariantType::ManagedObject, mono_object_get_class(object)));
|
||||
AsUint = mono_gchandle_new(object, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Type.Type != VariantType::ManagedObject || Type.TypeName)
|
||||
SetType(VariantType(VariantType::ManagedObject));
|
||||
AsUint = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Variant::SetAsset(Asset* asset)
|
||||
{
|
||||
if (Type.Type != VariantType::Asset)
|
||||
|
||||
@@ -92,6 +92,7 @@ public:
|
||||
|
||||
explicit VariantType(Types type, const StringView& typeName);
|
||||
explicit VariantType(Types type, const StringAnsiView& typeName);
|
||||
explicit VariantType(Types type, struct _MonoClass* klass);
|
||||
VariantType(const VariantType& other);
|
||||
VariantType(VariantType&& other) noexcept;
|
||||
|
||||
@@ -272,6 +273,7 @@ public:
|
||||
explicit operator StringView() const;
|
||||
explicit operator StringAnsiView() const;
|
||||
explicit operator ScriptingObject*() const;
|
||||
explicit operator struct _MonoObject*() const;
|
||||
explicit operator Asset*() const;
|
||||
explicit operator Vector2() const;
|
||||
explicit operator Vector3() const;
|
||||
@@ -309,6 +311,7 @@ public:
|
||||
void SetBlob(int32 length);
|
||||
void SetBlob(const void* data, int32 length);
|
||||
void SetObject(ScriptingObject* object);
|
||||
void SetManagedObject(struct _MonoObject* object);
|
||||
void SetAsset(Asset* asset);
|
||||
String ToString() const;
|
||||
|
||||
|
||||
@@ -459,7 +459,7 @@ MonoObject* MUtils::BoxVariant(const Variant& value)
|
||||
return nullptr;
|
||||
}
|
||||
case VariantType::ManagedObject:
|
||||
return mono_gchandle_get_target(value.AsUint);
|
||||
return (MonoObject*)value;
|
||||
case VariantType::Typename:
|
||||
{
|
||||
const auto klass = Scripting::FindClassNative((StringAnsiView)value);
|
||||
@@ -666,7 +666,7 @@ MonoClass* MUtils::GetClass(const Variant& value)
|
||||
case VariantType::Enum:
|
||||
return Scripting::FindClassNative(StringAnsiView(value.Type.TypeName));
|
||||
case VariantType::ManagedObject:
|
||||
return GetClass(mono_gchandle_get_target(value.AsUint));
|
||||
return GetClass((MonoObject*)value);
|
||||
default: ;
|
||||
}
|
||||
return nullptr;
|
||||
@@ -755,7 +755,7 @@ void* MUtils::VariantToManagedArgPtr(Variant& value, const MType& type, bool& fa
|
||||
{
|
||||
if (value.Type.Type != VariantType::Enum)
|
||||
{
|
||||
value.SetType(VariantType(VariantType::Enum, GetClassFullname(klass)));
|
||||
value.SetType(VariantType(VariantType::Enum, klass));
|
||||
value.AsUint64 = 0;
|
||||
}
|
||||
return &value.AsUint64;
|
||||
|
||||
@@ -86,6 +86,8 @@ void ManagedSerialization::SerializeDiff(ISerializable::SerializeStream& stream,
|
||||
|
||||
void ManagedSerialization::Deserialize(ISerializable::DeserializeStream& stream, MonoObject* object)
|
||||
{
|
||||
if (!object)
|
||||
return;
|
||||
ASSERT(stream.IsObject());
|
||||
|
||||
// Get serialized data
|
||||
@@ -93,15 +95,15 @@ void ManagedSerialization::Deserialize(ISerializable::DeserializeStream& stream,
|
||||
rapidjson_flax::Writer<rapidjson_flax::StringBuffer> writer(buffer);
|
||||
stream.Accept(writer);
|
||||
|
||||
Deserialize(buffer, object);
|
||||
Deserialize(StringAnsiView(buffer.GetString(), (int32)buffer.GetSize()), object);
|
||||
}
|
||||
|
||||
void ManagedSerialization::Deserialize(const rapidjson_flax::StringBuffer& data, MonoObject* object)
|
||||
void ManagedSerialization::Deserialize(const StringAnsiView& data, MonoObject* object)
|
||||
{
|
||||
if (!object)
|
||||
return;
|
||||
const char* str = data.GetString();
|
||||
const int32 len = (int32)data.GetSize();
|
||||
const char* str = data.Get();
|
||||
const int32 len = data.Length();
|
||||
|
||||
// Skip case {} to improve performance
|
||||
if (StringUtils::Compare(str, "{}") == 0)
|
||||
|
||||
@@ -39,5 +39,5 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="data">The input data.</param>
|
||||
/// <param name="object">The object to deserialize.</param>
|
||||
static void Deserialize(const rapidjson_flax::StringBuffer& data, MonoObject* object);
|
||||
static void Deserialize(const StringAnsiView& data, MonoObject* object);
|
||||
};
|
||||
|
||||
@@ -279,7 +279,16 @@ namespace FlaxEngine.Json
|
||||
cache.MemoryStream.Initialize(jsonBuffer, jsonLength);
|
||||
cache.Reader.DiscardBufferedData();
|
||||
var jsonReader = new JsonTextReader(cache.Reader);
|
||||
cache.JsonSerializer.Populate(jsonReader, input);
|
||||
if (*jsonBuffer != (byte)'{' && input is LocalizedString asLocalizedString)
|
||||
{
|
||||
// Hack for objects that are serialized into sth different thant "{..}" (eg. LocalizedString can be saved as plain string if not using localization)
|
||||
asLocalizedString.Id = null;
|
||||
asLocalizedString.Value = jsonReader.ReadAsString();
|
||||
}
|
||||
else
|
||||
{
|
||||
cache.JsonSerializer.Populate(jsonReader, input);
|
||||
}
|
||||
|
||||
if (!cache.JsonSerializer.CheckAdditionalContent)
|
||||
return;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "Serialization.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Types/Version.h"
|
||||
#include "Engine/Core/Types/Variant.h"
|
||||
#include "Engine/Core/Types/DateTime.h"
|
||||
@@ -20,7 +21,12 @@
|
||||
#include "Engine/Core/Math/Color.h"
|
||||
#include "Engine/Core/Math/Color32.h"
|
||||
#include "Engine/Core/Math/Matrix.h"
|
||||
#include "Engine/Scripting/ManagedSerialization.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MUtils.h"
|
||||
#include "Engine/Utilities/Encryption.h"
|
||||
#if USE_MONO
|
||||
#include <ThirdParty/mono-2.0/mono/metadata/object.h>
|
||||
#endif
|
||||
|
||||
void ISerializable::DeserializeIfExists(DeserializeStream& stream, const char* memberName, ISerializeModifier* modifier)
|
||||
{
|
||||
@@ -99,7 +105,6 @@ void Serialization::Serialize(ISerializable::SerializeStream& stream, const Vari
|
||||
{
|
||||
case VariantType::Null:
|
||||
case VariantType::Void:
|
||||
case VariantType::ManagedObject:
|
||||
stream.StartObject();
|
||||
stream.EndObject();
|
||||
break;
|
||||
@@ -201,6 +206,9 @@ void Serialization::Serialize(ISerializable::SerializeStream& stream, const Vari
|
||||
else
|
||||
stream.String("", 0);
|
||||
break;
|
||||
case VariantType::ManagedObject:
|
||||
ManagedSerialization::Serialize(stream, (MonoObject*)v);
|
||||
break;
|
||||
default:
|
||||
Platform::CheckFailed("", __FILE__, __LINE__);
|
||||
stream.StartObject();
|
||||
@@ -217,7 +225,7 @@ void Serialization::Deserialize(ISerializable::DeserializeStream& stream, Varian
|
||||
return;
|
||||
VariantType type;
|
||||
Deserialize(mType->value, type, modifier);
|
||||
v.SetType(type);
|
||||
v.SetType(MoveTemp(type));
|
||||
|
||||
const auto mValue = SERIALIZE_FIND_MEMBER(stream, "Value");
|
||||
if (mValue == stream.MemberEnd())
|
||||
@@ -228,7 +236,6 @@ void Serialization::Deserialize(ISerializable::DeserializeStream& stream, Varian
|
||||
{
|
||||
case VariantType::Null:
|
||||
case VariantType::Void:
|
||||
case VariantType::ManagedObject:
|
||||
break;
|
||||
case VariantType::Bool:
|
||||
v.AsBool = value.GetBool();
|
||||
@@ -330,6 +337,30 @@ void Serialization::Deserialize(ISerializable::DeserializeStream& stream, Varian
|
||||
CHECK(value.IsString());
|
||||
v.SetTypename(value.GetStringAnsiView());
|
||||
break;
|
||||
case VariantType::ManagedObject:
|
||||
{
|
||||
auto obj = (MonoObject*)v;
|
||||
if (!obj && v.Type.TypeName)
|
||||
{
|
||||
MonoClass* klass = MUtils::GetClass(v.Type);
|
||||
if (!klass)
|
||||
{
|
||||
LOG(Error, "Invalid variant type {0}", v.Type);
|
||||
return;
|
||||
}
|
||||
obj = mono_object_new(mono_domain_get(), klass);
|
||||
if (!obj)
|
||||
{
|
||||
LOG(Error, "Failed to managed instance of the variant type {0}", v.Type);
|
||||
return;
|
||||
}
|
||||
if (!mono_class_is_valuetype(klass))
|
||||
mono_runtime_object_init(obj);
|
||||
v.SetManagedObject(obj);
|
||||
}
|
||||
ManagedSerialization::Deserialize(value, obj);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Platform::CheckFailed("", __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
@@ -2,13 +2,18 @@
|
||||
|
||||
#include "ReadStream.h"
|
||||
#include "WriteStream.h"
|
||||
#include "JsonWriters.h"
|
||||
#include "Engine/Core/Types/CommonValue.h"
|
||||
#include "Engine/Core/Types/Variant.h"
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
#include "Engine/Content/Asset.h"
|
||||
#include "Engine/Debug/DebugLog.h"
|
||||
#include "Engine/Scripting/ManagedSerialization.h"
|
||||
#include "Engine/Scripting/Scripting.h"
|
||||
#include "Engine/Scripting/ScriptingObject.h"
|
||||
#include "Engine/Scripting/ScriptingObjectReference.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MCore.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MUtils.h"
|
||||
|
||||
void ReadStream::ReadStringAnsi(StringAnsi* data)
|
||||
{
|
||||
@@ -269,7 +274,6 @@ void ReadStream::ReadVariant(Variant* data)
|
||||
{
|
||||
case VariantType::Null:
|
||||
case VariantType::Void:
|
||||
case VariantType::ManagedObject:
|
||||
break;
|
||||
case VariantType::Bool:
|
||||
data->AsBool = ReadBool();
|
||||
@@ -335,6 +339,42 @@ void ReadStream::ReadVariant(Variant* data)
|
||||
data->SetObject(FindObject(id, ScriptingObject::GetStaticClass()));
|
||||
break;
|
||||
}
|
||||
case VariantType::ManagedObject:
|
||||
{
|
||||
const byte format = ReadByte();
|
||||
if (format == 0)
|
||||
{
|
||||
// No data
|
||||
}
|
||||
else if (format == 1)
|
||||
{
|
||||
// Json
|
||||
StringAnsi json;
|
||||
ReadStringAnsi(&json, -71);
|
||||
MCore::AttachThread();
|
||||
MonoClass* klass = MUtils::GetClass(data->Type);
|
||||
if (!klass)
|
||||
{
|
||||
LOG(Error, "Invalid variant type {0}", data->Type);
|
||||
return;
|
||||
}
|
||||
MonoObject* obj = mono_object_new(mono_domain_get(), klass);
|
||||
if (!obj)
|
||||
{
|
||||
LOG(Error, "Failed to managed instance of the variant type {0}", data->Type);
|
||||
return;
|
||||
}
|
||||
if (!mono_class_is_valuetype(klass))
|
||||
mono_runtime_object_init(obj);
|
||||
ManagedSerialization::Deserialize(json, obj);
|
||||
data->SetManagedObject(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(Error, "Invalid Variant {0) format {1}", data->Type.ToString(), format);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VariantType::Structure:
|
||||
{
|
||||
int32 length;
|
||||
@@ -572,7 +612,6 @@ void WriteStream::WriteVariant(const Variant& data)
|
||||
{
|
||||
case VariantType::Null:
|
||||
case VariantType::Void:
|
||||
case VariantType::ManagedObject:
|
||||
break;
|
||||
case VariantType::Bool:
|
||||
WriteBool(data.AsBool);
|
||||
@@ -674,6 +713,25 @@ void WriteStream::WriteVariant(const Variant& data)
|
||||
case VariantType::Typename:
|
||||
WriteStringAnsi((StringAnsiView)data, -14);
|
||||
break;
|
||||
case VariantType::ManagedObject:
|
||||
{
|
||||
MonoObject* obj = (MonoObject*)data;
|
||||
if (obj)
|
||||
{
|
||||
WriteByte(1);
|
||||
rapidjson_flax::StringBuffer json;
|
||||
CompactJsonWriter writerObj(json);
|
||||
MCore::AttachThread();
|
||||
ManagedSerialization::Serialize(writerObj, obj);
|
||||
WriteStringAnsi(StringAnsiView(json.GetString(), (int32)json.GetSize()), -71);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteByte(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CRASH;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user