mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 21:01:52 +00:00
Refactored script instance serialization and now the refactoring is finally finished...
This commit is contained in:
@@ -96,7 +96,7 @@ static class ScriptEngine
|
||||
|
||||
private static Dictionary<StringView, ScriptClass> _entityScripts = new .() ~ DeleteDictionaryAndReleaseValues!(_);
|
||||
|
||||
private static Dictionary<UUID, ScriptInstance> _entityScriptInstances = new .() ~ {
|
||||
internal static Dictionary<UUID, ScriptInstance> _entityScriptInstances = new .() ~ {
|
||||
for (var entry in _)
|
||||
{
|
||||
entry.value?.ReleaseRef();
|
||||
@@ -485,9 +485,9 @@ static class ScriptEngine
|
||||
|
||||
Log.EngineLogger.Info("Reloading script assemblies.");
|
||||
|
||||
Dictionary<UUID, SerializedObject> serializedData = scope .();
|
||||
ScriptInstanceSerializer contextSerializer = scope .();
|
||||
|
||||
SerializeScriptInstances(serializedData);
|
||||
contextSerializer.SerializeScriptInstances();
|
||||
|
||||
Mono.mono_domain_set(s_RootDomain, true);
|
||||
|
||||
@@ -513,9 +513,7 @@ static class ScriptEngine
|
||||
}
|
||||
}
|
||||
|
||||
DeserializeScriptInstances(serializedData);
|
||||
|
||||
ClearDictionaryAndDeleteValues!(serializedData);
|
||||
contextSerializer.DeserializeScriptInstances();
|
||||
|
||||
Log.EngineLogger.Info("Script assemblies reloaded!");
|
||||
}
|
||||
@@ -582,63 +580,4 @@ static class ScriptEngine
|
||||
|
||||
Classes.EntityEditor.ShowEntityEditor(scriptComponent.Instance, entity.UUID);
|
||||
}
|
||||
|
||||
/// Serializes all script instances
|
||||
public static void SerializeScriptInstances(Dictionary<UUID, SerializedObject> allObjects)
|
||||
{
|
||||
Debug.Profiler.ProfileFunction!();
|
||||
|
||||
for (let (id, script) in _entityScriptInstances)
|
||||
{
|
||||
SerializeScriptInstance(script, allObjects);
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes the given script instance
|
||||
public static void SerializeScriptInstance(ScriptInstance script, Dictionary<UUID, SerializedObject> allObjects)
|
||||
{
|
||||
SerializedObject object = new SerializedObject(allObjects, script.ScriptClass.FullName, script.EntityId);
|
||||
object.Serialize(script);
|
||||
}
|
||||
|
||||
/// Deserializes the given data into the script instances
|
||||
public static void DeserializeScriptInstances(Dictionary<UUID, SerializedObject> allObjects)
|
||||
{
|
||||
Debug.Profiler.ProfileFunction!();
|
||||
|
||||
for (let (id, script) in _entityScriptInstances)
|
||||
{
|
||||
DeserializeScriptInstance(id, script, allObjects);
|
||||
}
|
||||
}
|
||||
|
||||
/// Deserializes the given script instance.
|
||||
/// @returns true if the script had serialized data; false otherwise.
|
||||
public static bool DeserializeScriptInstance(UUID id, ScriptInstance script, Dictionary<UUID, SerializedObject> allObjects)
|
||||
{
|
||||
if (allObjects.TryGetValue(id, let object))
|
||||
{
|
||||
object.Deserialize(script);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Replaces Entity references in the given serialized data using the specified translation table.
|
||||
public static void FixupSerializedIds(Dictionary<UUID, UUID> originalToCopyIds, Dictionary<UUID, SerializedObject> allObjects)
|
||||
{
|
||||
for (let (id, object) in allObjects)
|
||||
{
|
||||
for (var fieldData in ref object.Fields.Values)
|
||||
{
|
||||
if (fieldData.PrimitiveType != .EntityReference && fieldData.PrimitiveType != .ComponentReference)
|
||||
continue;
|
||||
|
||||
if (originalToCopyIds.TryGetValue(fieldData.Data.EngineObject.ID, let copyId))
|
||||
fieldData.Data.EngineObject.ID = copyId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
using System.Collections;
|
||||
using GlitchyEngine.Core;
|
||||
using GlitchyEngine.Serialization;
|
||||
|
||||
namespace GlitchyEngine.Scripting;
|
||||
|
||||
using internal GlitchyEngine.Scripting;
|
||||
|
||||
/// Provides capability to serialize and deserialize C# objects managed by the script engine
|
||||
public class ScriptInstanceSerializer
|
||||
{
|
||||
append Dictionary<UUID, SerializedObject> _serializedData = .();
|
||||
|
||||
public int SerializedObjectCount => _serializedData.Count;
|
||||
|
||||
public Dictionary<UUID, SerializedObject> SerializedObjects => _serializedData;
|
||||
|
||||
public ~this()
|
||||
{
|
||||
Clear();
|
||||
delete:append _serializedData;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
ClearDictionaryAndDeleteValues!(_serializedData);
|
||||
}
|
||||
|
||||
/// Serializes all script instances that are currently managed by the ScriptEngine.
|
||||
public void SerializeScriptInstances()
|
||||
{
|
||||
Debug.Profiler.ProfileFunction!();
|
||||
|
||||
for (let (id, script) in ScriptEngine._entityScriptInstances)
|
||||
{
|
||||
SerializeScriptInstance(script);
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes the given script instance.
|
||||
public void SerializeScriptInstance(ScriptInstance script)
|
||||
{
|
||||
SerializedObject object = new SerializedObject(_serializedData, script.ScriptClass.FullName, script.EntityId);
|
||||
object.Serialize(script);
|
||||
}
|
||||
|
||||
/// Deserializes this context into the instances currently managed by the script engine.
|
||||
public void DeserializeScriptInstances()
|
||||
{
|
||||
Debug.Profiler.ProfileFunction!();
|
||||
|
||||
for (let (id, script) in ScriptEngine._entityScriptInstances)
|
||||
{
|
||||
DeserializeScriptInstance(id, script);
|
||||
}
|
||||
}
|
||||
|
||||
/// Deserializes the data into the given script instance, if there is data available.
|
||||
/// @returns true if the script had serialized data; false otherwise.
|
||||
public bool DeserializeScriptInstance(UUID id, ScriptInstance script)
|
||||
{
|
||||
if (_serializedData.TryGetValue(id, let object))
|
||||
{
|
||||
object.Deserialize(script);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Replaces Entity references in the given serialized data using the specified translation table.
|
||||
public void FixupSerializedIds(Dictionary<UUID, UUID> originalToCopyIds)
|
||||
{
|
||||
for (let (id, object) in _serializedData)
|
||||
{
|
||||
for (var fieldData in ref object.Fields.Values)
|
||||
{
|
||||
if (fieldData.PrimitiveType != .EntityReference && fieldData.PrimitiveType != .ComponentReference)
|
||||
continue;
|
||||
|
||||
if (originalToCopyIds.TryGetValue(fieldData.Data.EngineObject.ID, let copyId))
|
||||
fieldData.Data.EngineObject.ID = copyId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SerializedObject GetSerializedObject(UUID id)
|
||||
{
|
||||
return _serializedData[id];
|
||||
}
|
||||
|
||||
public bool TryGetSerializedObject(UUID id, out SerializedObject object)
|
||||
{
|
||||
return _serializedData.TryGetValue(id, out object);
|
||||
}
|
||||
}
|
||||
@@ -958,8 +958,9 @@ namespace GlitchyEngine.World
|
||||
*/
|
||||
public Entity CreateInstance(Entity entity)
|
||||
{
|
||||
Dictionary<UUID, SerializedObject> serializedData = scope .();
|
||||
defer { ClearDictionaryAndDeleteValues!(serializedData); }
|
||||
//Dictionary<UUID, SerializedObject> serializedData = scope .();
|
||||
ScriptInstanceSerializer scriptSerializer = scope .();
|
||||
//defer { ClearDictionaryAndDeleteValues!(serializedData); }
|
||||
|
||||
List<Entity> newEntities = scope .();
|
||||
Dictionary<EcsEntity, EcsEntity> sourceToTargetEntity = scope .();
|
||||
@@ -1002,7 +1003,7 @@ namespace GlitchyEngine.World
|
||||
|
||||
if (sourceScript.Instance != null)
|
||||
{
|
||||
ScriptEngine.SerializeScriptInstance(sourceScript.Instance, serializedData);
|
||||
scriptSerializer.SerializeScriptInstance(sourceScript.Instance);
|
||||
|
||||
// Initializes the created instance
|
||||
// TODO: this returns false, if no script with ScriptClassName exists, we have to handle this case correctly I think.
|
||||
@@ -1024,13 +1025,13 @@ namespace GlitchyEngine.World
|
||||
Entity newEntity = CopyEntityAndChildren(entity, null);
|
||||
|
||||
// Replace old IDs with new ones
|
||||
ScriptEngine.FixupSerializedIds(sourceIdToTargetId, serializedData);
|
||||
scriptSerializer.FixupSerializedIds(sourceIdToTargetId);
|
||||
|
||||
// Use separate loops for deserialization and OnCreate to ensure complete entities and references in OnCreate
|
||||
|
||||
for (let (originalId, newScriptInstance) in newScripts)
|
||||
{
|
||||
ScriptEngine.DeserializeScriptInstance(originalId, newScriptInstance, serializedData);
|
||||
scriptSerializer.DeserializeScriptInstance(originalId, newScriptInstance);
|
||||
}
|
||||
|
||||
for (let (_, newScriptInstance) in newScripts)
|
||||
|
||||
@@ -28,11 +28,11 @@ class SceneSerializer
|
||||
// Maps from ID in the prefab file to the actual ID in the scene.
|
||||
private Dictionary<UUID, UUID> _fileToSceneId;
|
||||
|
||||
private Dictionary<UUID, SerializedObject> _serializedObjects ~ DeleteDictionaryAndValues!(_);
|
||||
private append ScriptInstanceSerializer _scriptSerializer = .(); //Dictionary<UUID, SerializedObject> _serializedObjects ~ DeleteDictionaryAndValues!(_);
|
||||
|
||||
private HashSet<UUID> _objectsNotWritten;
|
||||
|
||||
public Dictionary<UUID, SerializedObject> SerializedObjects => _serializedObjects;
|
||||
public ScriptInstanceSerializer ScriptSerializer => _scriptSerializer;
|
||||
|
||||
public this(Scene scene)
|
||||
{
|
||||
@@ -43,13 +43,11 @@ class SceneSerializer
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
_serializedObjects = new .();
|
||||
_scriptSerializer.SerializeScriptInstances();
|
||||
|
||||
ScriptEngine.SerializeScriptInstances(_serializedObjects);
|
||||
_objectsNotWritten = new .(_scriptSerializer.SerializedObjectCount);
|
||||
|
||||
_objectsNotWritten = new .(_serializedObjects.Count);
|
||||
|
||||
for (UUID key in _serializedObjects.Keys)
|
||||
for (UUID key in _scriptSerializer.SerializedObjects.Keys)
|
||||
{
|
||||
_objectsNotWritten.Add(key);
|
||||
}
|
||||
@@ -84,11 +82,12 @@ class SceneSerializer
|
||||
|
||||
writer.Identifier("ReferencedObjects");
|
||||
|
||||
// Write all objects that don't belong to an entity. (referenced Arrays, Classes, etc...)
|
||||
using (writer.ArrayBlock())
|
||||
{
|
||||
for (UUID id in _objectsNotWritten)
|
||||
{
|
||||
Serialize.Value(writer, _serializedObjects[id]);
|
||||
Serialize.Value(writer, _scriptSerializer.GetSerializedObject(id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +236,7 @@ class SceneSerializer
|
||||
{
|
||||
Serialize.Value(writer, "ScriptClass", component.ScriptClassName);
|
||||
|
||||
if (_serializedObjects.TryGetValue(entity.UUID, let value))
|
||||
if (_scriptSerializer.TryGetSerializedObject(entity.UUID, let value))
|
||||
{
|
||||
Serialize.Value(writer, "Fields", value);
|
||||
|
||||
@@ -285,8 +284,6 @@ class SceneSerializer
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
_serializedObjects = new .();
|
||||
|
||||
_parentIdToChild = scope Dictionary<UUID, Entity>();
|
||||
_entitiesMissingParent = scope List<(Entity Entity, UUID ParentId)>();
|
||||
_fileToSceneId = scope Dictionary<UUID, UUID>();
|
||||
@@ -344,7 +341,7 @@ class SceneSerializer
|
||||
Try!(reader.EntryEnd());
|
||||
}
|
||||
|
||||
Try!(SerializedObject.BonDeserialize(reader, _serializedObjects, gBonEnv));
|
||||
Try!(SerializedObject.BonDeserialize(reader, _scriptSerializer.SerializedObjects, gBonEnv));
|
||||
|
||||
first = false;
|
||||
}
|
||||
@@ -667,7 +664,7 @@ class SceneSerializer
|
||||
Try!(reader.EntryEnd());
|
||||
|
||||
if (Try!(reader.Identifier()) == "Fields")
|
||||
SerializedObject.BonDeserialize(reader, _serializedObjects, gBonEnv);
|
||||
SerializedObject.BonDeserialize(reader, _scriptSerializer.SerializedObjects, gBonEnv);
|
||||
}
|
||||
|
||||
return .Ok;
|
||||
|
||||
Reference in New Issue
Block a user