mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Refactored Scene serialization
This commit is contained in:
@@ -1151,7 +1151,7 @@ static class ScriptGlue
|
|||||||
|
|
||||||
char8* rawTypeName = Mono.mono_string_to_utf8(typeName);
|
char8* rawTypeName = Mono.mono_string_to_utf8(typeName);
|
||||||
|
|
||||||
SerializedObject newObject = new SerializedObject(context.AllObjects, StringView(rawTypeName));
|
SerializedObject newObject = new SerializedObject(context.Serializer, StringView(rawTypeName));
|
||||||
|
|
||||||
Mono.mono_free(rawTypeName);
|
Mono.mono_free(rawTypeName);
|
||||||
|
|
||||||
@@ -1182,9 +1182,9 @@ static class ScriptGlue
|
|||||||
|
|
||||||
objectContext = null;
|
objectContext = null;
|
||||||
|
|
||||||
Log.EngineLogger.AssertDebug(context.AllObjects.ContainsKey(context.Id));
|
Log.EngineLogger.AssertDebug(context.Serializer.ContainsId(context.Id));
|
||||||
|
|
||||||
if (!context.AllObjects.TryGetValue(id, let foundObject))
|
if (!context.Serializer.TryGetSerializedObject(id, let foundObject))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
objectContext = Internal.UnsafeCastToPtr(foundObject);
|
objectContext = Internal.UnsafeCastToPtr(foundObject);
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class ScriptInstanceSerializer
|
|||||||
/// Serializes the given script instance.
|
/// Serializes the given script instance.
|
||||||
public void SerializeScriptInstance(ScriptInstance script)
|
public void SerializeScriptInstance(ScriptInstance script)
|
||||||
{
|
{
|
||||||
SerializedObject object = new SerializedObject(_serializedData, script.ScriptClass.FullName, script.EntityId);
|
SerializedObject object = new SerializedObject(this, script.ScriptClass.FullName, script.EntityId);
|
||||||
object.Serialize(script);
|
object.Serialize(script);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,4 +94,14 @@ public class ScriptInstanceSerializer
|
|||||||
{
|
{
|
||||||
return _serializedData.TryGetValue(id, out object);
|
return _serializedData.TryGetValue(id, out object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ContainsId(UUID id)
|
||||||
|
{
|
||||||
|
return _serializedData.ContainsKey(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AddObject(SerializedObject object)
|
||||||
|
{
|
||||||
|
_serializedData.Add(object.Id, object);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ using System.Reflection;
|
|||||||
|
|
||||||
namespace GlitchyEngine.Serialization;
|
namespace GlitchyEngine.Serialization;
|
||||||
|
|
||||||
|
using internal GlitchyEngine.Scripting;
|
||||||
|
|
||||||
[BonTarget]
|
[BonTarget]
|
||||||
class SerializedObject
|
class SerializedObject
|
||||||
{
|
{
|
||||||
@@ -33,18 +35,18 @@ class SerializedObject
|
|||||||
|
|
||||||
public String TypeName ~ delete:append _;
|
public String TypeName ~ delete:append _;
|
||||||
|
|
||||||
public Dictionary<UUID, SerializedObject> AllObjects;
|
public ScriptInstanceSerializer Serializer;
|
||||||
|
|
||||||
private List<String> _ownedString = new List<String>() ~ DeleteContainerAndItems!(_);
|
private List<String> _ownedString = new List<String>() ~ DeleteContainerAndItems!(_);
|
||||||
|
|
||||||
public append Dictionary<StringView, (SerializationType PrimitiveType, FieldData Data)> Fields = .();
|
public append Dictionary<StringView, (SerializationType PrimitiveType, FieldData Data)> Fields = .();
|
||||||
|
|
||||||
[AllowAppend]
|
[AllowAppend]
|
||||||
public this(Dictionary<UUID, SerializedObject> allObjects, StringView? typeName, UUID? id = null)
|
public this(ScriptInstanceSerializer serializer, StringView? typeName, UUID? id = null)
|
||||||
{
|
{
|
||||||
String typeNameCopy = append String(typeName.Value);
|
String typeNameCopy = append String(typeName.Value);
|
||||||
|
|
||||||
AllObjects = allObjects;
|
Serializer = serializer;
|
||||||
|
|
||||||
if (id == null)
|
if (id == null)
|
||||||
{
|
{
|
||||||
@@ -53,14 +55,14 @@ class SerializedObject
|
|||||||
{
|
{
|
||||||
Id = UUID.Create();
|
Id = UUID.Create();
|
||||||
}
|
}
|
||||||
while (AllObjects.ContainsKey(Id));
|
while (Serializer.ContainsId(Id));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Id = id.Value;
|
Id = id.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
AllObjects.Add(Id, this);
|
Serializer.AddObject(this);
|
||||||
|
|
||||||
TypeName = typeNameCopy;
|
TypeName = typeNameCopy;
|
||||||
}
|
}
|
||||||
@@ -364,7 +366,7 @@ class SerializedObject
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Result<SerializedObject> BonDeserialize(BonReader reader, Dictionary<UUID, SerializedObject> allObjects, BonEnvironment environment = gBonEnv)
|
public static Result<SerializedObject> BonDeserialize(BonReader reader, ScriptInstanceSerializer scriptSerializer, int sceneFileVersion, BonEnvironment environment = gBonEnv)
|
||||||
{
|
{
|
||||||
StringView type = Try!(reader.Type());
|
StringView type = Try!(reader.Type());
|
||||||
|
|
||||||
@@ -372,7 +374,7 @@ class SerializedObject
|
|||||||
|
|
||||||
Try!(Deserialize.Value<UUID>(reader, "ID", let objectId, environment));
|
Try!(Deserialize.Value<UUID>(reader, "ID", let objectId, environment));
|
||||||
|
|
||||||
SerializedObject object = new SerializedObject(allObjects, type, objectId);
|
SerializedObject object = new SerializedObject(scriptSerializer, type, objectId);
|
||||||
|
|
||||||
while (reader.ObjectHasMore())
|
while (reader.ObjectHasMore())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ using internal GlitchyEngine.World;
|
|||||||
|
|
||||||
class SceneSerializer
|
class SceneSerializer
|
||||||
{
|
{
|
||||||
|
private const int FileVersion = 1;
|
||||||
|
|
||||||
private Scene _scene;
|
private Scene _scene;
|
||||||
|
|
||||||
// Maps from ParentID to ChildEntity
|
// Maps from ParentID to ChildEntity
|
||||||
@@ -32,6 +34,8 @@ class SceneSerializer
|
|||||||
|
|
||||||
private HashSet<UUID> _objectsNotWritten;
|
private HashSet<UUID> _objectsNotWritten;
|
||||||
|
|
||||||
|
private int _fileVersion;
|
||||||
|
|
||||||
public ScriptInstanceSerializer ScriptSerializer => _scriptSerializer;
|
public ScriptInstanceSerializer ScriptSerializer => _scriptSerializer;
|
||||||
|
|
||||||
public this(Scene scene)
|
public this(Scene scene)
|
||||||
@@ -63,6 +67,8 @@ class SceneSerializer
|
|||||||
// TODO: Scene name goes here!
|
// TODO: Scene name goes here!
|
||||||
Serialize.Value(writer, "Name", "Scene name here pls!!!");
|
Serialize.Value(writer, "Name", "Scene name here pls!!!");
|
||||||
|
|
||||||
|
Serialize.Value(writer, "Version", FileVersion);
|
||||||
|
|
||||||
writer.Identifier("Entities");
|
writer.Identifier("Entities");
|
||||||
|
|
||||||
using (writer.ArrayBlock())
|
using (writer.ArrayBlock())
|
||||||
@@ -280,6 +286,31 @@ class SceneSerializer
|
|||||||
Runtime.NotImplemented();
|
Runtime.NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Result<void> DeserializeValue<T>(BonReader reader, StringView identifier, out T value, bool tryEndEntry = true, BonEnvironment env = gBonEnv)
|
||||||
|
{
|
||||||
|
Try!(Deserialize.Value(reader, identifier, out value, env));
|
||||||
|
|
||||||
|
TryEndEntry(reader);
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool Check(BonReader reader, char8 token, bool consume = true)
|
||||||
|
{
|
||||||
|
return reader.[Friend]Check(token, consume);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryEndEntry(BonReader reader)
|
||||||
|
{
|
||||||
|
if (Check(reader, ',', false))
|
||||||
|
{
|
||||||
|
reader.EntryEnd();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public Result<void> Deserialize(StringView filePath, bool loadAsPrefab = false)
|
public Result<void> Deserialize(StringView filePath, bool loadAsPrefab = false)
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
@@ -299,55 +330,30 @@ class SceneSerializer
|
|||||||
|
|
||||||
_scene.Name = Path.GetFileName(filePath, .. scope .());
|
_scene.Name = Path.GetFileName(filePath, .. scope .());
|
||||||
|
|
||||||
// TODO: Scene name goes here!
|
Try!(DeserializeValue(reader, "Version", out _fileVersion));
|
||||||
String testName;
|
|
||||||
Deserialize.Value(reader, "Name", out testName);
|
|
||||||
delete testName;
|
|
||||||
|
|
||||||
Try!(reader.EntryEnd());
|
if (_fileVersion == 0 || _fileVersion > FileVersion)
|
||||||
|
|
||||||
if (Try!(reader.Identifier()) != "Entities")
|
|
||||||
return .Err;
|
|
||||||
|
|
||||||
Try!(reader.ArrayBlock());
|
|
||||||
|
|
||||||
bool first = true;
|
|
||||||
while (reader.ArrayHasMore())
|
|
||||||
{
|
{
|
||||||
if (!first)
|
Log.EngineLogger.Warning("The scene file either has no version or it's newer than the current editor. Deserialization might fail.");
|
||||||
{
|
|
||||||
Try!(reader.EntryEnd());
|
|
||||||
}
|
|
||||||
|
|
||||||
Try!(DeserializeEntity(reader, loadAsPrefab));
|
|
||||||
|
|
||||||
first = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Try!(reader.ArrayBlockEnd());
|
while (reader.ObjectHasMore())
|
||||||
|
|
||||||
Try!(reader.EntryEnd());
|
|
||||||
|
|
||||||
if (Try!(reader.Identifier()) != "ReferencedObjects")
|
|
||||||
return .Err;
|
|
||||||
|
|
||||||
Try!(reader.ArrayBlock());
|
|
||||||
|
|
||||||
first = true;
|
|
||||||
while (reader.ArrayHasMore())
|
|
||||||
{
|
{
|
||||||
if (!first)
|
StringView identifier = Try!(reader.Identifier());
|
||||||
|
|
||||||
|
switch (identifier)
|
||||||
{
|
{
|
||||||
Try!(reader.EntryEnd());
|
case "Entities":
|
||||||
|
Try!(DeserializeEntities(reader, loadAsPrefab));
|
||||||
|
case "ReferencedObjects":
|
||||||
|
Try!(DeserializeReferencedObjects(reader));
|
||||||
|
default:
|
||||||
|
Log.EngineLogger.Warning($"Encountered unexpected Identifier \"{identifier}\".");
|
||||||
}
|
}
|
||||||
|
|
||||||
Try!(SerializedObject.BonDeserialize(reader, _scriptSerializer.SerializedObjects, gBonEnv));
|
TryEndEntry(reader);
|
||||||
|
|
||||||
first = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Try!(reader.ArrayBlockEnd());
|
|
||||||
|
|
||||||
Try!(reader.ObjectBlockEnd());
|
Try!(reader.ObjectBlockEnd());
|
||||||
|
|
||||||
Try!(Deserialize.End(reader));
|
Try!(Deserialize.End(reader));
|
||||||
@@ -368,6 +374,38 @@ class SceneSerializer
|
|||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Result<void> DeserializeEntities(BonReader reader, bool loadAsPrefab)
|
||||||
|
{
|
||||||
|
Try!(reader.ArrayBlock());
|
||||||
|
|
||||||
|
while (reader.ArrayHasMore())
|
||||||
|
{
|
||||||
|
Try!(DeserializeEntity(reader, loadAsPrefab));
|
||||||
|
|
||||||
|
TryEndEntry(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
Try!(reader.ArrayBlockEnd());
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result<void> DeserializeReferencedObjects(BonReader reader)
|
||||||
|
{
|
||||||
|
Try!(reader.ArrayBlock());
|
||||||
|
|
||||||
|
while (reader.ArrayHasMore())
|
||||||
|
{
|
||||||
|
Try!(SerializedObject.BonDeserialize(reader, _scriptSerializer, _fileVersion, gBonEnv));
|
||||||
|
|
||||||
|
TryEndEntry(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
Try!(reader.ArrayBlockEnd());
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
/// Deserializes the next entity in the file
|
/// Deserializes the next entity in the file
|
||||||
/// @param reader the reader
|
/// @param reader the reader
|
||||||
/// @param replaceId If false, the ID that is stored in the file will be used as ID in the scene.
|
/// @param replaceId If false, the ID that is stored in the file will be used as ID in the scene.
|
||||||
@@ -407,7 +445,8 @@ class SceneSerializer
|
|||||||
|
|
||||||
Try!(reader.ObjectBlock());
|
Try!(reader.ObjectBlock());
|
||||||
|
|
||||||
Deserialize.Value<uint64>(reader, "Id", let rawUuid);
|
// We must start with the Id because we need to construct the entity!
|
||||||
|
DeserializeValue<uint64>(reader, "Id", let rawUuid);
|
||||||
|
|
||||||
UUID uuid = RemapId(UUID(rawUuid));
|
UUID uuid = RemapId(UUID(rawUuid));
|
||||||
|
|
||||||
@@ -415,58 +454,65 @@ class SceneSerializer
|
|||||||
|
|
||||||
while(reader.ObjectHasMore())
|
while(reader.ObjectHasMore())
|
||||||
{
|
{
|
||||||
Try!(reader.EntryEnd());
|
TryEndEntry(reader);
|
||||||
|
|
||||||
StringView identifier = Try!(reader.Identifier());
|
StringView componentIdentifier = Try!(reader.Identifier());
|
||||||
|
|
||||||
switch(identifier)
|
switch(componentIdentifier)
|
||||||
{
|
{
|
||||||
case "NameComponent":
|
case "NameComponent":
|
||||||
Try!(DeserializeComponent<NameComponent>(reader, entity, scope (component) =>
|
Try!(DeserializeComponent<NameComponent>(reader, entity, scope (component) =>
|
||||||
{
|
{
|
||||||
String name;
|
Try!(Deserialize.Value<String>(reader, "Name", let name));
|
||||||
|
|
||||||
Deserialize.Value(reader, "Name", out name);
|
|
||||||
|
|
||||||
component.Name = name;
|
component.Name = name;
|
||||||
|
|
||||||
delete name;
|
delete name;
|
||||||
|
|
||||||
return .Ok;
|
return .Ok;
|
||||||
}));
|
}));
|
||||||
case "SpriteRendererComponent":
|
case "SpriteRendererComponent":
|
||||||
Try!(DeserializeComponent<SpriteRendererComponent>(reader, entity, scope (component) =>
|
Try!(DeserializeComponentFields<SpriteRendererComponent>(reader, componentIdentifier, entity, scope (component, fieldIdentifier) =>
|
||||||
{
|
{
|
||||||
Try!(Deserialize.Value(reader, "Color", out component.Color));
|
switch(fieldIdentifier)
|
||||||
reader.EntryEnd();
|
{
|
||||||
Try!(Deserialize.Value(reader, "Sprite", out component.Sprite));
|
case "Color":
|
||||||
reader.EntryEnd();
|
Try!(Deserialize.Value(reader, out component.Color));
|
||||||
Try!(Deserialize.Value(reader, "UvTransform", out component.UvTransform));
|
case "Sprite":
|
||||||
|
Try!(Deserialize.Value(reader, out component.Sprite));
|
||||||
|
case "UvTransform":
|
||||||
|
Try!(Deserialize.Value(reader, out component.UvTransform));
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return .Ok;
|
return true;
|
||||||
}));
|
}));
|
||||||
case "CircleRendererComponent":
|
case "CircleRendererComponent":
|
||||||
Try!(DeserializeComponent<CircleRendererComponent>(reader, entity, scope (component) =>
|
Try!(DeserializeComponentFields<CircleRendererComponent>(reader, componentIdentifier, entity, scope (component, fieldIdentifier) =>
|
||||||
{
|
{
|
||||||
Try!(Deserialize.Value(reader, "Color", out component.Color));
|
switch(fieldIdentifier)
|
||||||
reader.EntryEnd();
|
{
|
||||||
Try!(Deserialize.Value(reader, "InnerRadius", out component.InnerRadius));
|
case "Color":
|
||||||
reader.EntryEnd();
|
Try!(Deserialize.Value(reader, out component.Color));
|
||||||
Try!(Deserialize.Value(reader, "Sprite", out component.Sprite));
|
case "InnerRadius":
|
||||||
reader.EntryEnd();
|
Try!(Deserialize.Value(reader, out component.InnerRadius));
|
||||||
Try!(Deserialize.Value(reader, "UvTransform", out component.UvTransform));
|
case "Sprite":
|
||||||
|
Try!(Deserialize.Value(reader, out component.Sprite));
|
||||||
|
case "UvTransform":
|
||||||
|
Try!(Deserialize.Value(reader, out component.UvTransform));
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return .Ok;
|
return true;
|
||||||
}));
|
}));
|
||||||
case "TransformComponent":
|
case "TransformComponent":
|
||||||
Try!(DeserializeComponent<TransformComponent>(reader, entity, scope (component) =>
|
Try!(DeserializeComponentFields<TransformComponent>(reader, componentIdentifier, entity, scope (component, fieldIdentifier) =>
|
||||||
{
|
{
|
||||||
let nextId = Try!(reader.Identifier());
|
switch(fieldIdentifier)
|
||||||
if (nextId == "ParentId")
|
|
||||||
{
|
{
|
||||||
|
case "ParentId":
|
||||||
UUID rawParentId;
|
UUID rawParentId;
|
||||||
Deserialize.Value(reader, out rawParentId);
|
Try!(Deserialize.Value(reader, out rawParentId));
|
||||||
reader.EntryEnd();
|
|
||||||
|
|
||||||
UUID parentId = RemapId(rawParentId);
|
UUID parentId = RemapId(rawParentId);
|
||||||
|
|
||||||
@@ -480,155 +526,170 @@ class SceneSerializer
|
|||||||
{
|
{
|
||||||
_entitiesMissingParent.Add((entity, parentId));
|
_entitiesMissingParent.Add((entity, parentId));
|
||||||
}
|
}
|
||||||
|
case "Position":
|
||||||
Deserialize.Value(reader, "Position", out component.[Friend]_position);
|
Try!(Deserialize.Value(reader, out component.[Friend]_position));
|
||||||
reader.EntryEnd();
|
case "Rotation":
|
||||||
|
Try!(Deserialize.Value(reader, out component.[Friend]_rotation));
|
||||||
|
case "Scale":
|
||||||
|
Try!(Deserialize.Value(reader, out component.[Friend]_scale));
|
||||||
|
case "EditorEulerRotation":
|
||||||
|
Try!(Deserialize.Value(reader, out component.[Friend]_editorRotationEuler));
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else if (nextId == "Position")
|
|
||||||
{
|
|
||||||
Deserialize.Value(reader, out component.[Friend]_position);
|
|
||||||
reader.EntryEnd();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return .Err;
|
|
||||||
}
|
|
||||||
|
|
||||||
Deserialize.Value(reader, "Rotation", out component.[Friend]_rotation);
|
|
||||||
reader.EntryEnd();
|
|
||||||
Deserialize.Value(reader, "Scale", out component.[Friend]_scale);
|
|
||||||
reader.EntryEnd();
|
|
||||||
|
|
||||||
Deserialize.Value(reader, "EditorEulerRotation", out component.[Friend]_editorRotationEuler);
|
|
||||||
|
|
||||||
component.IsDirty = true;
|
component.IsDirty = true;
|
||||||
|
|
||||||
return .Ok;
|
return true;
|
||||||
}));
|
}));
|
||||||
case "CameraComponent":
|
case "CameraComponent":
|
||||||
Try!(DeserializeComponent<CameraComponent>(reader, entity, scope (component) =>
|
Try!(DeserializeComponentFields<CameraComponent>(reader, componentIdentifier, entity, scope (component, fieldIdentifier) =>
|
||||||
{
|
{
|
||||||
SceneCamera camera = component.Camera;
|
ref SceneCamera camera = ref component.Camera;
|
||||||
|
|
||||||
Deserialize.Value(reader, "Primary", out component.Primary);
|
switch(fieldIdentifier)
|
||||||
reader.EntryEnd();
|
{
|
||||||
|
case "Primary":
|
||||||
|
Try!(Deserialize.Value(reader, out component.Primary));
|
||||||
|
case "ProjectionType":
|
||||||
|
Try!(Deserialize.Value(reader, out camera.[Friend]_projectionType));
|
||||||
|
|
||||||
// TODO: Render target
|
case "PerspectiveFovY":
|
||||||
|
Try!(Deserialize.Value(reader, out camera.[Friend]_perspectiveFovY));
|
||||||
|
case "PerspectiveNearPlane":
|
||||||
|
Try!(Deserialize.Value(reader, out camera.[Friend]_perspectiveNearPlane));
|
||||||
|
case "PerspectiveFarPlane":
|
||||||
|
Try!(Deserialize.Value(reader, out camera.[Friend]_perspectiveFarPlane));
|
||||||
|
|
||||||
Deserialize.Value(reader, "ProjectionType", out camera.[Friend]_projectionType);
|
case "OrthographicHeight":
|
||||||
reader.EntryEnd();
|
Try!(Deserialize.Value(reader, out camera.[Friend]_orthographicHeight));
|
||||||
|
case "OrthographicNearPlane":
|
||||||
|
Try!(Deserialize.Value(reader, out camera.[Friend]_orthographicNearPlane));
|
||||||
|
case "OrthographicFarPlane":
|
||||||
|
Try!(Deserialize.Value(reader, out camera.[Friend]_orthographicFarPlane));
|
||||||
|
case "AspectRatio":
|
||||||
|
Try!(Deserialize.Value(reader, out camera.[Friend]_aspectRatio));
|
||||||
|
case "FixedAspectRatio":
|
||||||
|
Try!(Deserialize.Value(reader, out camera.[Friend]_fixedAspectRatio));
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Deserialize.Value(reader, "PerspectiveFovY", out camera.[Friend]_perspectiveFovY);
|
return true;
|
||||||
reader.EntryEnd();
|
}));
|
||||||
Deserialize.Value(reader, "PerspectiveNearPlane", out camera.[Friend]_perspectiveNearPlane);
|
|
||||||
reader.EntryEnd();
|
|
||||||
Deserialize.Value(reader, "PerspectiveFarPlane", out camera.[Friend]_perspectiveFarPlane);
|
|
||||||
reader.EntryEnd();
|
|
||||||
Deserialize.Value(reader, "OrthographicHeight", out camera.[Friend]_orthographicHeight);
|
|
||||||
reader.EntryEnd();
|
|
||||||
Deserialize.Value(reader, "OrthographicNearPlane", out camera.[Friend]_orthographicNearPlane);
|
|
||||||
reader.EntryEnd();
|
|
||||||
Deserialize.Value(reader, "OrthographicFarPlane", out camera.[Friend]_orthographicFarPlane);
|
|
||||||
reader.EntryEnd();
|
|
||||||
Deserialize.Value(reader, "AspectRatio", out camera.[Friend]_aspectRatio);
|
|
||||||
reader.EntryEnd();
|
|
||||||
Deserialize.Value(reader, "FixedAspectRatio", out camera.[Friend]_fixedAspectRatio);
|
|
||||||
|
|
||||||
camera.[Friend]CalculateProjection();
|
|
||||||
|
|
||||||
return .Ok;
|
|
||||||
}));
|
|
||||||
case "LightComponent":
|
case "LightComponent":
|
||||||
Try!(DeserializeComponent<LightComponent>(reader, entity, scope (component) =>
|
Try!(DeserializeComponentFields<LightComponent>(reader, componentIdentifier, entity, scope (component, fieldIdentifier) =>
|
||||||
{
|
{
|
||||||
ref SceneLight light = ref component.SceneLight;
|
ref SceneLight light = ref component.SceneLight;
|
||||||
|
|
||||||
Deserialize.Value(reader, "LightType", out light.[Friend]_type);
|
switch(fieldIdentifier)
|
||||||
reader.EntryEnd();
|
{
|
||||||
|
case "LightType":
|
||||||
|
Try!(Deserialize.Value(reader, out light.[Friend]_type));
|
||||||
|
case "Illuminance":
|
||||||
|
Try!(Deserialize.Value(reader, out light.[Friend]_illuminance));
|
||||||
|
case "Color":
|
||||||
|
Try!(Deserialize.Value(reader, out light.[Friend]_color));
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Deserialize.Value(reader, "Illuminance", out light.[Friend]_illuminance);
|
return true;
|
||||||
reader.EntryEnd();
|
|
||||||
|
|
||||||
Deserialize.Value(reader, "Color", out light.[Friend]_color);
|
|
||||||
return .Ok;
|
|
||||||
}));
|
}));
|
||||||
case "Rigidbody2D":
|
case "Rigidbody2D":
|
||||||
Try!(DeserializeComponent<Rigidbody2DComponent>(reader, entity, scope (component) =>
|
Try!(DeserializeComponentFields<Rigidbody2DComponent>(reader, componentIdentifier, entity, scope (component, fieldIdentifier) =>
|
||||||
{
|
{
|
||||||
Rigidbody2DComponent.BodyType bodyType = .Static;
|
switch(fieldIdentifier)
|
||||||
Deserialize.Value(reader, "BodyType", out bodyType);
|
{
|
||||||
component.BodyType = bodyType;
|
case "BodyType":
|
||||||
|
Rigidbody2DComponent.BodyType bodyType = .Static;
|
||||||
|
Try!(Deserialize.Value(reader, out bodyType));
|
||||||
|
component.BodyType = bodyType;
|
||||||
|
case "FixedRotation":
|
||||||
|
Try!(Deserialize.Value<bool>(reader, let fixedRotation));
|
||||||
|
component.FixedRotation = fixedRotation;
|
||||||
|
case "GravityScale":
|
||||||
|
Try!(Deserialize.Value<float>(reader, let gravityScale));
|
||||||
|
component.GravityScale = gravityScale;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
reader.EntryEnd();
|
return true;
|
||||||
|
|
||||||
bool fixedRotation = false;
|
|
||||||
Deserialize.Value(reader, "FixedRotation", out fixedRotation);
|
|
||||||
component.FixedRotation = fixedRotation;
|
|
||||||
|
|
||||||
reader.EntryEnd();
|
|
||||||
|
|
||||||
Deserialize.Value<float>(reader, "GravityScale", let gravityScale);
|
|
||||||
component.GravityScale = gravityScale;
|
|
||||||
|
|
||||||
return .Ok;
|
|
||||||
}));
|
}));
|
||||||
case "BoxCollider2D":
|
case "BoxCollider2D":
|
||||||
Try!(DeserializeComponent<BoxCollider2DComponent>(reader, entity, scope (component) =>
|
Try!(DeserializeComponentFields<BoxCollider2DComponent>(reader, componentIdentifier, entity, scope (component, fieldIdentifier) =>
|
||||||
{
|
{
|
||||||
Deserialize.Value(reader, "Offset", out component.Offset);
|
switch(fieldIdentifier)
|
||||||
reader.EntryEnd();
|
{
|
||||||
Deserialize.Value(reader, "Size", out component.Size);
|
case "Offset":
|
||||||
reader.EntryEnd();
|
Try!(Deserialize.Value(reader, out component.Offset));
|
||||||
|
case "Size":
|
||||||
|
Try!(Deserialize.Value(reader, out component.Size));
|
||||||
|
|
||||||
Deserialize.Value(reader, "Density", out component.Density);
|
case "Density":
|
||||||
reader.EntryEnd();
|
Try!(Deserialize.Value(reader, out component.Density));
|
||||||
Deserialize.Value(reader, "Friction", out component.Friction);
|
case "Friction":
|
||||||
reader.EntryEnd();
|
Try!(Deserialize.Value(reader, out component.Friction));
|
||||||
Deserialize.Value(reader, "Restitution", out component.Restitution);
|
case "Restitution":
|
||||||
reader.EntryEnd();
|
Try!(Deserialize.Value(reader, out component.Restitution));
|
||||||
Deserialize.Value(reader, "RestitutionThreshold", out component.RestitutionThreshold);
|
case "RestitutionThreshold":
|
||||||
|
Try!(Deserialize.Value(reader, out component.RestitutionThreshold));
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return .Ok;
|
return true;
|
||||||
}));
|
}));
|
||||||
case "CircleCollider2D":
|
case "CircleCollider2D":
|
||||||
Try!(DeserializeComponent<CircleCollider2DComponent>(reader, entity, scope (component) =>
|
Try!(DeserializeComponentFields<CircleCollider2DComponent>(reader, componentIdentifier, entity, scope (component, fieldIdentifier) =>
|
||||||
{
|
{
|
||||||
Deserialize.Value(reader, "Offset", out component.Offset);
|
switch(fieldIdentifier)
|
||||||
reader.EntryEnd();
|
{
|
||||||
Deserialize.Value(reader, "Radius", out component.Radius);
|
case "Offset":
|
||||||
reader.EntryEnd();
|
Try!(Deserialize.Value(reader, out component.Offset));
|
||||||
|
case "Radius":
|
||||||
|
Try!(Deserialize.Value(reader, out component.Radius));
|
||||||
|
|
||||||
Deserialize.Value(reader, "Density", out component.Density);
|
case "Density":
|
||||||
reader.EntryEnd();
|
Try!(Deserialize.Value(reader, out component.Density));
|
||||||
Deserialize.Value(reader, "Friction", out component.Friction);
|
case "Friction":
|
||||||
reader.EntryEnd();
|
Try!(Deserialize.Value(reader, out component.Friction));
|
||||||
Deserialize.Value(reader, "Restitution", out component.Restitution);
|
case "Restitution":
|
||||||
reader.EntryEnd();
|
Try!(Deserialize.Value(reader, out component.Restitution));
|
||||||
Deserialize.Value(reader, "RestitutionThreshold", out component.RestitutionThreshold);
|
case "RestitutionThreshold":
|
||||||
|
Try!(Deserialize.Value(reader, out component.RestitutionThreshold));
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return .Ok;
|
return true;
|
||||||
}));
|
}));
|
||||||
case "PolygonCollider2D":
|
case "PolygonCollider2D":
|
||||||
Try!(DeserializeComponent<PolygonCollider2DComponent>(reader, entity, scope (component) =>
|
Try!(DeserializeComponentFields<PolygonCollider2DComponent>(reader, componentIdentifier, entity, scope (component, fieldIdentifier) =>
|
||||||
{
|
{
|
||||||
Deserialize.Value(reader, "Offset", out component.Offset);
|
switch(fieldIdentifier)
|
||||||
reader.EntryEnd();
|
{
|
||||||
|
case "Offset":
|
||||||
|
Try!(Deserialize.Value(reader, out component.Offset));
|
||||||
|
case "Vertices":
|
||||||
|
Try!(Deserialize.Value(reader, out component.Vertices));
|
||||||
|
case "VertexCount":
|
||||||
|
Try!(Deserialize.Value(reader, out component.VertexCount));
|
||||||
|
|
||||||
Deserialize.Value(reader, "Vertices", out component.Vertices);
|
case "Density":
|
||||||
reader.EntryEnd();
|
Try!(Deserialize.Value(reader, out component.Density));
|
||||||
Deserialize.Value(reader, "VertexCount", out component.VertexCount);
|
case "Friction":
|
||||||
reader.EntryEnd();
|
Try!(Deserialize.Value(reader, out component.Friction));
|
||||||
|
case "Restitution":
|
||||||
|
Try!(Deserialize.Value(reader, out component.Restitution));
|
||||||
|
case "RestitutionThreshold":
|
||||||
|
Try!(Deserialize.Value(reader, out component.RestitutionThreshold));
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
Deserialize.Value(reader, "Density", out component.Density);
|
|
||||||
reader.EntryEnd();
|
|
||||||
Deserialize.Value(reader, "Friction", out component.Friction);
|
|
||||||
reader.EntryEnd();
|
|
||||||
Deserialize.Value(reader, "Restitution", out component.Restitution);
|
|
||||||
reader.EntryEnd();
|
|
||||||
Deserialize.Value(reader, "RestitutionThreshold", out component.RestitutionThreshold);
|
|
||||||
|
|
||||||
return .Ok;
|
|
||||||
}));
|
}));
|
||||||
case "MeshComponent":
|
case "MeshComponent":
|
||||||
Try!(DeserializeComponent<MeshComponent>(reader, entity, scope (component) =>
|
Try!(DeserializeComponent<MeshComponent>(reader, entity, scope (component) =>
|
||||||
@@ -645,29 +706,21 @@ class SceneSerializer
|
|||||||
return .Ok;
|
return .Ok;
|
||||||
}));
|
}));
|
||||||
case "ScriptComponent":
|
case "ScriptComponent":
|
||||||
Try!(DeserializeComponent<ScriptComponent>(reader, entity, scope (component) =>
|
Try!(DeserializeComponentFields<ScriptComponent>(reader, componentIdentifier, entity, scope (component, fieldIdentifier) =>
|
||||||
{
|
{
|
||||||
String scriptClassName = null;
|
switch(fieldIdentifier)
|
||||||
|
|
||||||
Try!(Deserialize.Value(reader, "ScriptClass", out scriptClassName));
|
|
||||||
|
|
||||||
if (scriptClassName != null)
|
|
||||||
{
|
{
|
||||||
|
case "ScriptClass":
|
||||||
|
Try!(Deserialize.Value<String>(reader, let scriptClassName));
|
||||||
component.ScriptClassName = scriptClassName;
|
component.ScriptClassName = scriptClassName;
|
||||||
|
|
||||||
delete scriptClassName;
|
delete scriptClassName;
|
||||||
|
case "Fields":
|
||||||
|
Try!(SerializedObject.BonDeserialize(reader, _scriptSerializer, _fileVersion, gBonEnv));
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
if (reader.ObjectHasMore())
|
|
||||||
{
|
|
||||||
Try!(reader.EntryEnd());
|
|
||||||
|
|
||||||
if (Try!(reader.Identifier()) == "Fields")
|
|
||||||
SerializedObject.BonDeserialize(reader, _scriptSerializer.SerializedObjects, gBonEnv);
|
|
||||||
}
|
|
||||||
|
|
||||||
return .Ok;
|
|
||||||
}));
|
}));
|
||||||
case "Editor":
|
case "Editor":
|
||||||
Try!(DeserializeComponent<EditorFlagsComponent>(reader, entity, scope (component) =>
|
Try!(DeserializeComponent<EditorFlagsComponent>(reader, entity, scope (component) =>
|
||||||
@@ -677,104 +730,32 @@ class SceneSerializer
|
|||||||
return .Ok;
|
return .Ok;
|
||||||
}));
|
}));
|
||||||
case "TextRenderer":
|
case "TextRenderer":
|
||||||
Try!(DeserializeComponent<TextRendererComponent>(reader, entity, scope (component) =>
|
Try!(DeserializeComponentFields<TextRendererComponent>(reader, componentIdentifier, entity, scope (component, fieldIdentifier) =>
|
||||||
{
|
{
|
||||||
Try!(Deserialize.Value<bool>(reader, "IsRichText", let isRichText));
|
switch(fieldIdentifier)
|
||||||
component.IsRichText = isRichText;
|
|
||||||
|
|
||||||
Try!(reader.EntryEnd());
|
|
||||||
|
|
||||||
String text = null;
|
|
||||||
|
|
||||||
Try!(Deserialize.Value<String>(reader, "Text", out text));
|
|
||||||
|
|
||||||
if (text != null)
|
|
||||||
{
|
{
|
||||||
|
case "IsRichText":
|
||||||
|
Try!(Deserialize.Value<bool>(reader, let isRichText));
|
||||||
|
component.IsRichText = isRichText;
|
||||||
|
case "Text":
|
||||||
|
Try!(Deserialize.Value<String>(reader, let text));
|
||||||
component.Text = text;
|
component.Text = text;
|
||||||
|
|
||||||
delete text;
|
delete text;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok;
|
return true;
|
||||||
}));
|
}));
|
||||||
default:
|
default:
|
||||||
Log.EngineLogger.AssertDebug(false, "Unknown component type");
|
Log.EngineLogger.Error($"Unknown component type \"{componentIdentifier}\" in entity {entity.UUID}");
|
||||||
//return .Err;
|
return .Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Try!(reader.ObjectBlockEnd());
|
Try!(reader.ObjectBlockEnd());
|
||||||
|
|
||||||
return .Ok;
|
return .Ok;
|
||||||
|
|
||||||
/*writer.EntryStart();
|
|
||||||
|
|
||||||
using (writer.ObjectBlock())
|
|
||||||
{
|
|
||||||
// TODO: Entity GUID goes here!
|
|
||||||
Serialize.Value(writer, "Id", entity.Handle.Index);
|
|
||||||
|
|
||||||
SerializeComponent<EditorComponent>(writer, entity, "EditorComponent", scope (component) => {});
|
|
||||||
|
|
||||||
SerializeComponent<DebugNameComponent>(writer, entity, "NameComponent", scope (component) =>
|
|
||||||
{
|
|
||||||
Serialize.Value(writer, "Name", component.DebugName);
|
|
||||||
});
|
|
||||||
|
|
||||||
SerializeComponent<SpriterRendererComponent>(writer, entity, "SpriterRendererComponent", scope (component) =>
|
|
||||||
{
|
|
||||||
// TODO: Texture
|
|
||||||
|
|
||||||
Serialize.Value(writer, "Color", component.Color);
|
|
||||||
});
|
|
||||||
|
|
||||||
SerializeComponent<TransformComponent>(writer, entity, "TransformComponent", scope (component) =>
|
|
||||||
{
|
|
||||||
// TODO: Use GUIDs
|
|
||||||
if (component.Parent != .InvalidEntity)
|
|
||||||
Serialize.Value(writer, "ParentId", component.Parent.Index);
|
|
||||||
|
|
||||||
Serialize.Value(writer, "Position", component.Position);
|
|
||||||
Serialize.Value(writer, "Rotation", component.Rotation);
|
|
||||||
Serialize.Value(writer, "Scale", component.Scale);
|
|
||||||
|
|
||||||
Serialize.Value(writer, "EditorEulerRotation", component.EditorRotationEuler);
|
|
||||||
});
|
|
||||||
|
|
||||||
SerializeComponent<CameraComponent>(writer, entity, "CameraComponent", scope (component) =>
|
|
||||||
{
|
|
||||||
SceneCamera camera = component.Camera;
|
|
||||||
|
|
||||||
Serialize.Value(writer, "Primary", component.Primary);
|
|
||||||
|
|
||||||
// TODO: Render target
|
|
||||||
|
|
||||||
Serialize.Value(writer, "ProjectionType", camera.ProjectionType);
|
|
||||||
|
|
||||||
Serialize.Value(writer, "PerspectiveFovY", camera.PerspectiveFovY);
|
|
||||||
Serialize.Value(writer, "PerspectiveNearPlane", camera.PerspectiveNearPlane);
|
|
||||||
Serialize.Value(writer, "PerspectiveFarPlane", camera.PerspectiveFarPlane);
|
|
||||||
Serialize.Value(writer, "OrthographicHeight", camera.OrthographicHeight);
|
|
||||||
Serialize.Value(writer, "OrthographicNearPlane", camera.OrthographicNearPlane);
|
|
||||||
Serialize.Value(writer, "OrthographicFarPlane", camera.OrthographicFarPlane);
|
|
||||||
Serialize.Value(writer, "AspectRatio", camera.AspectRatio);
|
|
||||||
Serialize.Value(writer, "FixedAspectRatio", camera.FixedAspectRatio);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
SerializeComponent<LightComponent>(writer, entity, "LightComponent", scope (component) =>
|
|
||||||
{
|
|
||||||
SceneLight light = component.SceneLight;
|
|
||||||
|
|
||||||
Serialize.Value(writer, "LightType", light.LightType);
|
|
||||||
|
|
||||||
Serialize.Value(writer, "Illuminance", light.Illuminance);
|
|
||||||
|
|
||||||
Serialize.Value(writer, "Color", light.Color);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.EntryEnd();*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result<void> DeserializeComponent<T>(BonReader reader, Entity entity, delegate Result<void>(T* component) deserialize) where T : struct, new
|
static Result<void> DeserializeComponent<T>(BonReader reader, Entity entity, delegate Result<void>(T* component) deserialize) where T : struct, new
|
||||||
@@ -795,6 +776,35 @@ class SceneSerializer
|
|||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Result<void> DeserializeComponentFields<T>(BonReader reader, StringView prettyComponentName, Entity entity, delegate Result<bool>(T* component, StringView identifier) deserializeField) where T : struct, new
|
||||||
|
{
|
||||||
|
Try!(reader.ObjectBlock());
|
||||||
|
|
||||||
|
T* component;
|
||||||
|
|
||||||
|
if (entity.HasComponent<T>())
|
||||||
|
component = entity.GetComponent<T>();
|
||||||
|
else
|
||||||
|
component = entity.AddComponent<T>();
|
||||||
|
|
||||||
|
while(reader.ObjectHasMore())
|
||||||
|
{
|
||||||
|
StringView fieldIdentifier = Try!(reader.Identifier());
|
||||||
|
|
||||||
|
if (!Try!(deserializeField(component, fieldIdentifier)))
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error($"Unknown identifier \"{fieldIdentifier}\" in component \"{prettyComponentName}\" of entity {entity.UUID}");
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
TryEndEntry(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
Try!(reader.ObjectBlockEnd());
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
public bool DeserializeRuntime(StringView filePath)
|
public bool DeserializeRuntime(StringView filePath)
|
||||||
{
|
{
|
||||||
Runtime.NotImplemented();
|
Runtime.NotImplemented();
|
||||||
|
|||||||
Reference in New Issue
Block a user