diff --git a/Source/Editor/CustomEditors/Editors/TypeEditor.cs b/Source/Editor/CustomEditors/Editors/TypeEditor.cs
index 722235088..9ee2c37a4 100644
--- a/Source/Editor/CustomEditors/Editors/TypeEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/TypeEditor.cs
@@ -393,11 +393,8 @@ namespace FlaxEditor.CustomEditors.Editors
if (_element != null)
{
_element.CustomControl.ValueChanged += () => SetValue(_element.CustomControl.Value.Type);
-
if (_element.CustomControl.Type == ScriptType.Object)
- {
_element.CustomControl.Type = Values.Type.Type != typeof(object) || Values[0] == null ? ScriptType.Object : TypeUtils.GetObjectType(Values[0]);
- }
}
}
@@ -407,9 +404,7 @@ namespace FlaxEditor.CustomEditors.Editors
base.Refresh();
if (!HasDifferentValues)
- {
_element.CustomControl.Value = new ScriptType(Values[0] as Type);
- }
}
}
@@ -425,9 +420,7 @@ namespace FlaxEditor.CustomEditors.Editors
base.Initialize(layout);
if (_element != null)
- {
_element.CustomControl.ValueChanged += () => SetValue(_element.CustomControl.Value);
- }
}
///
@@ -436,9 +429,32 @@ namespace FlaxEditor.CustomEditors.Editors
base.Refresh();
if (!HasDifferentValues)
- {
_element.CustomControl.Value = (ScriptType)Values[0];
- }
+ }
+ }
+
+ ///
+ /// Default implementation of the inspector used to edit reference to the . Used to pick classes.
+ ///
+ [CustomEditor(typeof(SoftTypeReference)), DefaultEditor]
+ public class SoftTypeReferenceEditor : TypeEditorBase
+ {
+ ///
+ public override void Initialize(LayoutElementsContainer layout)
+ {
+ base.Initialize(layout);
+
+ if (_element != null)
+ _element.CustomControl.ValueChanged += () => SetValue(new SoftTypeReference(_element.CustomControl.ValueTypeName));
+ }
+
+ ///
+ public override void Refresh()
+ {
+ base.Refresh();
+
+ if (!HasDifferentValues)
+ _element.CustomControl.ValueTypeName = ((SoftTypeReference)Values[0]).TypeName;
}
}
diff --git a/Source/Engine/Scripting/SoftTypeReference.cs b/Source/Engine/Scripting/SoftTypeReference.cs
new file mode 100644
index 000000000..f12f2bdb7
--- /dev/null
+++ b/Source/Engine/Scripting/SoftTypeReference.cs
@@ -0,0 +1,87 @@
+// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
+
+using System;
+
+namespace FlaxEngine
+{
+ ///
+ /// The soft reference to the scripting type contained in the scripting assembly.
+ ///
+ public struct SoftTypeReference : IComparable, IComparable
+ {
+ private string _typeName;
+
+ ///
+ /// Gets or sets the type full name (eg. FlaxEngine.Actor).
+ ///
+ public string TypeName
+ {
+ get => _typeName;
+ set => _typeName = value;
+ }
+
+ ///
+ /// Gets or sets the type (resolves soft reference).
+ ///
+ public Type Type
+ {
+ get => _typeName != null ? Type.GetType(_typeName) : null;
+ set => _typeName = value?.FullName;
+ }
+
+ ///
+ /// Initializes a new instance of the .
+ ///
+ /// The type name.
+ public SoftTypeReference(string typeName)
+ {
+ _typeName = typeName;
+ }
+
+ ///
+ /// Gets the soft type reference from full name.
+ ///
+ /// The type name.
+ /// The soft type reference.
+ public static implicit operator SoftTypeReference(string s)
+ {
+ return new SoftTypeReference { _typeName = s };
+ }
+
+ ///
+ /// Gets the soft type reference from runtime type.
+ ///
+ /// The type.
+ /// The soft type reference.
+ public static implicit operator SoftTypeReference(Type s)
+ {
+ return new SoftTypeReference { _typeName = s?.FullName };
+ }
+
+ ///
+ public override string ToString()
+ {
+ return _typeName;
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return _typeName?.GetHashCode() ?? 0;
+ }
+
+ ///
+ public int CompareTo(object obj)
+ {
+ if (obj is SoftTypeReference other)
+ return CompareTo(other);
+ return 0;
+ }
+
+ ///
+ public int CompareTo(SoftTypeReference other)
+ {
+ return string.Compare(_typeName, other._typeName, StringComparison.Ordinal);
+ }
+ }
+}
diff --git a/Source/Engine/Scripting/SoftTypeReference.h b/Source/Engine/Scripting/SoftTypeReference.h
new file mode 100644
index 000000000..30508f639
--- /dev/null
+++ b/Source/Engine/Scripting/SoftTypeReference.h
@@ -0,0 +1,151 @@
+// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
+
+#pragma once
+
+#include "Scripting.h"
+#include "ScriptingObject.h"
+#include "Engine/Core/Log.h"
+#include "Engine/Core/Types/String.h"
+#include "Engine/Serialization/SerializationFwd.h"
+
+///
+/// The soft reference to the scripting type contained in the scripting assembly.
+///
+template
+API_STRUCT(InBuild) struct SoftTypeReference
+{
+protected:
+ StringAnsi _typeName;
+
+public:
+ SoftTypeReference() = default;
+
+ SoftTypeReference(const SoftTypeReference& s)
+ : _typeName(s._typeName)
+ {
+ }
+
+ SoftTypeReference(SoftTypeReference&& s) noexcept
+ : _typeName(MoveTemp(s._typeName))
+ {
+ }
+
+ SoftTypeReference(const StringView& s)
+ : _typeName(s)
+ {
+ }
+
+ SoftTypeReference(const StringAnsiView& s)
+ : _typeName(s)
+ {
+ }
+
+ SoftTypeReference(const char* s)
+ : _typeName(s)
+ {
+ }
+
+public:
+ FORCE_INLINE SoftTypeReference& operator=(SoftTypeReference&& s) noexcept
+ {
+ _typeName = MoveTemp(s._typeName);
+ return *this;
+ }
+
+ FORCE_INLINE SoftTypeReference& operator=(StringAnsi&& s) noexcept
+ {
+ _typeName = MoveTemp(s);
+ return *this;
+ }
+
+ FORCE_INLINE SoftTypeReference& operator=(const SoftTypeReference& s)
+ {
+ _typeName = s._typeName;
+ return *this;
+ }
+
+ FORCE_INLINE SoftTypeReference& operator=(const StringAnsiView& s)
+ {
+ _typeName = s;
+ return *this;
+ }
+
+ FORCE_INLINE bool operator==(const SoftTypeReference& other) const
+ {
+ return _typeName == other._typeName;
+ }
+
+ FORCE_INLINE bool operator!=(const SoftTypeReference& other) const
+ {
+ return _typeName != other._typeName;
+ }
+
+ FORCE_INLINE bool operator==(const StringAnsiView& other) const
+ {
+ return _typeName == other;
+ }
+
+ FORCE_INLINE bool operator!=(const StringAnsiView& other) const
+ {
+ return _typeName != other;
+ }
+
+ FORCE_INLINE operator bool() const
+ {
+ return _typeName.HasChars();
+ }
+
+public:
+ // Gets the type full name (eg. FlaxEngine.Actor).
+ StringAnsiView GetTypeName() const
+ {
+ return StringAnsiView(_typeName);
+ }
+
+ // Gets the type (resolves soft reference).
+ ScriptingTypeHandle GetType() const
+ {
+ return Scripting::FindScriptingType(_typeName);
+ }
+
+ // Creates a new objects of that type (or of type T if failed to solve typename).
+ T* NewObject() const
+ {
+ const ScriptingTypeHandle type = Scripting::FindScriptingType(_typeName);
+ auto obj = ScriptingObject::NewObject(type);
+ if (!obj)
+ {
+ if (_typeName.HasChars())
+ LOG(Error, "Unknown or invalid type {0}", String(_typeName));
+ obj = ScriptingObject::NewObject();
+ }
+ return obj;
+ }
+};
+
+template
+uint32 GetHash(const SoftTypeReference& key)
+{
+ return GetHash(key.GetTypeName());
+}
+
+// @formatter:off
+namespace Serialization
+{
+ template
+ bool ShouldSerialize(const SoftTypeReference& v, const void* otherObj)
+ {
+ return !otherObj || v != *(SoftTypeReference*)otherObj;
+ }
+ template
+ void Serialize(ISerializable::SerializeStream& stream, const SoftTypeReference& v, const void* otherObj)
+ {
+ stream.String(v.GetTypeName());
+ }
+ template
+ void Deserialize(ISerializable::DeserializeStream& stream, SoftTypeReference& v, ISerializeModifier* modifier)
+ {
+ v = stream.GetTextAnsi();
+ }
+}
+// @formatter:on
diff --git a/Source/Engine/Serialization/JsonConverters.cs b/Source/Engine/Serialization/JsonConverters.cs
index 07388a09b..40f9cb5a2 100644
--- a/Source/Engine/Serialization/JsonConverters.cs
+++ b/Source/Engine/Serialization/JsonConverters.cs
@@ -7,7 +7,7 @@ using Newtonsoft.Json;
namespace FlaxEngine.Json
{
///
- /// Serialize references to the FlaxEngine.Object as Guid.
+ /// Serialize references to the as Guid.
///
///
internal class FlaxObjectConverter : JsonConverter
@@ -46,7 +46,7 @@ namespace FlaxEngine.Json
}
///
- /// Serialize SceneReference as Guid in internal format.
+ /// Serialize as Guid in internal format.
///
///
internal class SceneReferenceConverter : JsonConverter
@@ -79,7 +79,7 @@ namespace FlaxEngine.Json
}
///
- /// Serialize SoftObjectReference as Guid in internal format.
+ /// Serialize as Guid in internal format.
///
///
internal class SoftObjectReferenceConverter : JsonConverter
@@ -111,7 +111,36 @@ namespace FlaxEngine.Json
}
///
- /// Serialize SoftObjectReference as Guid in internal format.
+ /// Serialize as typename string in internal format.
+ ///
+ ///
+ internal class SoftTypeReferenceConverter : JsonConverter
+ {
+ ///
+ public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ writer.WriteValue(((SoftTypeReference)value).TypeName);
+ }
+
+ ///
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ var result = new SoftTypeReference();
+ if (reader.TokenType == JsonToken.String)
+ result.TypeName = (string)reader.Value;
+
+ return result;
+ }
+
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(SoftTypeReference);
+ }
+ }
+
+ ///
+ /// Serialize as Guid in internal format.
///
///
internal class MarginConverter : JsonConverter
@@ -237,7 +266,7 @@ namespace FlaxEngine.Json
}
///
- /// Serialize LocalizedString as inlined text is not using localization (Id member is empty).
+ /// Serialize as inlined text is not using localization (Id member is empty).
///
///
internal class LocalizedStringConverter : JsonConverter
diff --git a/Source/Engine/Serialization/JsonSerializer.cs b/Source/Engine/Serialization/JsonSerializer.cs
index 617768a83..30889fce0 100644
--- a/Source/Engine/Serialization/JsonSerializer.cs
+++ b/Source/Engine/Serialization/JsonSerializer.cs
@@ -123,6 +123,7 @@ namespace FlaxEngine.Json
settings.Converters.Add(ObjectConverter);
settings.Converters.Add(new SceneReferenceConverter());
settings.Converters.Add(new SoftObjectReferenceConverter());
+ settings.Converters.Add(new SoftTypeReferenceConverter());
settings.Converters.Add(new MarginConverter());
settings.Converters.Add(new VersionConverter());
settings.Converters.Add(new LocalizedStringConverter());