Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use duality serializer for editoruserdata #865

Merged
merged 19 commits into from
Jul 22, 2020
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
e766421
Use duality serializer for editoruserdata
Barsonax Jul 13, 2020
9e4c084
MainForm: Renamed variable "str" to "stream" and grouped API methods …
ilexp Jul 16, 2020
69504da
Shortened DualityEditorApp app / user data property names
ilexp Jul 16, 2020
0db620d
Fixed whitespace and tweaked docs for settings properties
ilexp Jul 16, 2020
b080c51
Renamed design-time data property to "PerObjectData"
ilexp Jul 16, 2020
e9568d4
Renamed DesignTimeObjectDataManager API to avoid redundant "DesignTim…
ilexp Jul 16, 2020
87e1103
Reordered DualityEditorUserData and PluginSettings members to match s…
ilexp Jul 16, 2020
31ce8fe
Split up classes to one-class-per-file to match style guide
ilexp Jul 16, 2020
7e9906b
Added XML docs to DualityEditorUserData and PluginSettings
ilexp Jul 16, 2020
9603987
Fixed "FirstSession" flag never being set to false
ilexp Jul 17, 2020
ce61a3e
Rewired editor internals to use the new UserData instance
ilexp Jul 17, 2020
7a0d14f
Fixed FirstSession behavior
ilexp Jul 17, 2020
7f5f8fe
Tweaked SettingsContainer member ordering (style guide) and XML docs …
ilexp Jul 18, 2020
64150ba
Fixed typo in XML docs
ilexp Jul 18, 2020
458ea2c
SettingsContainer Apply method and Saving / Applied events to allow r…
ilexp Jul 18, 2020
796e8f3
Merge branch 'master' into feature/usedualityserializerforeditoruserdata
ilexp Jul 18, 2020
0300363
Moved dock panel serialization from explicit calls to settings event …
ilexp Jul 19, 2020
5eba5b3
Moved plugin user data serialization from explicit calls to settings …
ilexp Jul 19, 2020
42fa673
Moved MainForm launch options UI update to EditorAppData apply event …
ilexp Jul 19, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions Source/Core/Duality/DualityApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,15 +222,13 @@ public static SoundDevice Sound
get { return sound; }
}
/// <summary>
/// [GET / SET] Provides access to Duality's current <see cref="DualityAppData">application data</see>. This is never null.
/// [GET] Provides access to core application / game config, such as physics or backend settings. This is never null.
/// </summary>
public static SettingsContainer<DualityAppData> AppData { get; } = new SettingsContainer<DualityAppData>("AppData.xml");

/// <summary>
/// [GET / SET] Provides access to Duality's current <see cref="DualityUserData">user data</see>. This is never null.
/// [GET] Provides access to game options / user data, such as display resolution or audio volume. This is never null.
/// </summary>
public static SettingsContainer<DualityUserData> UserData { get; } = new SettingsContainer<DualityUserData>(execContext == ExecutionContext.Editor ? "DefaultUserData.xml" : "UserData.xml");

/// <summary>
/// [GET] Returns the <see cref="ExecutionContext"/> in which this DualityApp is currently running.
/// </summary>
Expand Down
8 changes: 4 additions & 4 deletions Source/Core/Duality/Utility/SettingsContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Duality
public class SettingsContainer<TSettings> : ISettingsContainer
where TSettings : class, new()
{
private readonly string path;
public string Path { get; }

/// <summary>
/// Fired when <see cref="Instance"/> has changed.
Expand All @@ -28,15 +28,15 @@ public class SettingsContainer<TSettings> : ISettingsContainer
/// <param name="path"></param>
public SettingsContainer(string path)
{
this.path = path;
this.Path = path;
}

/// <summary>
/// Loads the data of <typeparamref name="TSettings"/> from file.
/// </summary>
public void Load()
{
this.Instance = Serializer.TryReadObject<TSettings>(this.path, typeof(XmlSerializer)) ?? new TSettings();
this.Instance = Serializer.TryReadObject<TSettings>(this.Path, typeof(XmlSerializer)) ?? new TSettings();
this.Changed?.Invoke(this, EventArgs.Empty);
}

Expand All @@ -45,7 +45,7 @@ public void Load()
/// </summary>
public void Save()
{
Serializer.WriteObject(this.Instance, this.path, typeof(XmlSerializer));
Serializer.WriteObject(this.Instance, this.Path, typeof(XmlSerializer));
}
}
}
137 changes: 6 additions & 131 deletions Source/Editor/DualityEditor/DesignTimeObjectData.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.IO;

using Duality;
using Duality.Serialization;
using Duality.Resources;

Expand Down Expand Up @@ -77,42 +74,20 @@ public bool Equals(DataContainer other)
}
}

private static DesignTimeObjectDataManager manager = new DesignTimeObjectDataManager();

internal static void Init()
{
Load(DualityEditorApp.DesignTimeDataFile);
Scene.Leaving += Scene_Leaving;
}
internal static void Terminate()
{
Scene.Leaving -= Scene_Leaving;
Save(DualityEditorApp.DesignTimeDataFile);
}

public static DesignTimeObjectData Get(Guid objId)
{
return manager.RequestDesignTimeData(objId);
}
public static DesignTimeObjectData Get(GameObject obj)
{
return manager.RequestDesignTimeData(obj.Id);
}

private static void Save(string filePath)
{
Serializer.WriteObject(manager, filePath, typeof(BinarySerializer));
}
private static void Load(string filePath)
{
manager = Serializer.TryReadObject<DesignTimeObjectDataManager>(filePath) ?? new DesignTimeObjectDataManager();
}
private static void Scene_Leaving(object sender, EventArgs e)
{
manager.CleanupDesignTimeData();
DualityEditorApp.UserData.Instance?.PerObjectData.Cleanup();
}


public static readonly DesignTimeObjectData Default = new DesignTimeObjectData();

private Guid objId = Guid.Empty;
Expand Down Expand Up @@ -184,6 +159,11 @@ public DesignTimeObjectData(Guid parentId, DesignTimeObjectData baseData)
this.attached = true;
}

public static DesignTimeObjectData Get(GameObject obj)
{
return DualityEditorApp.UserData.Instance.PerObjectData.Request(obj.Id);
}

public T RequestCustomData<T>() where T : new()
{
this.Detach();
Expand Down Expand Up @@ -230,109 +210,4 @@ private void Detach()
this.attached = false;
}
}

internal class DesignTimeObjectDataManager : ISerializeExplicit
{
private static readonly int GuidByteLength = Guid.Empty.ToByteArray().Length;
private const int Version_First = 1;

private Dictionary<Guid,DesignTimeObjectData> dataStore = new Dictionary<Guid,DesignTimeObjectData>();


public DesignTimeObjectData RequestDesignTimeData(Guid objId)
{
DesignTimeObjectData data;
if (!this.dataStore.TryGetValue(objId, out data))
{
data = new DesignTimeObjectData(objId, DesignTimeObjectData.Default);
this.dataStore[objId] = data;
}
return data;
}
public void CleanupDesignTimeData()
{
// Remove trivial / default data
var removeQuery =
from p in this.dataStore
where p.Value.IsDefault
select p.Value.ParentObjectId;
foreach (Guid objId in removeQuery.ToArray())
this.dataStore.Remove(objId);
}
public void OptimizeDesignTimeData()
{
// Optimize data by sharing
var shareValues = this.dataStore.Values.ToList();
while (shareValues.Count > 0)
{
DesignTimeObjectData data = shareValues[shareValues.Count - 1];
foreach (DesignTimeObjectData other in shareValues)
{
data.TryShareData(other);
}
shareValues.RemoveAt(shareValues.Count - 1);
}
}

void ISerializeExplicit.WriteData(IDataWriter writer)
{
this.CleanupDesignTimeData();
this.OptimizeDesignTimeData();

Guid[] guidArray = dataStore.Keys.ToArray();
byte[] data = new byte[guidArray.Length * GuidByteLength];
for (int i = 0; i < guidArray.Length; i++)
{
Array.Copy(
guidArray[i].ToByteArray(), 0,
data, i * GuidByteLength, GuidByteLength);
}
DesignTimeObjectData.DataContainer[] objData = dataStore.Values.Select(d => d.Data).ToArray();
bool[] objDataDirty = dataStore.Values.Select(d => d.IsAttached).ToArray();

writer.WriteValue("version", Version_First);
writer.WriteValue("dataStoreKeys", data);
writer.WriteValue("dataStoreValues", objData);
writer.WriteValue("dataStoreDirtyFlag", objDataDirty);
}
void ISerializeExplicit.ReadData(IDataReader reader)
{
int version;
reader.ReadValue("version", out version);

if (this.dataStore == null)
this.dataStore = new Dictionary<Guid,DesignTimeObjectData>();
else
this.dataStore.Clear();

if (version == Version_First)
{
byte[] data;
DesignTimeObjectData.DataContainer[] objData;
bool[] objDataDirty;
reader.ReadValue("dataStoreKeys", out data);
reader.ReadValue("dataStoreValues", out objData);
reader.ReadValue("dataStoreDirtyFlag", out objDataDirty);

Guid[] guidArray = new Guid[data.Length / GuidByteLength];
byte[] guidData = new byte[GuidByteLength];
for (int i = 0; i < guidArray.Length; i++)
{
Array.Copy(
data, i * GuidByteLength,
guidData, 0, GuidByteLength);
guidArray[i] = new Guid(guidData);
}

for (int i = 0; i < objData.Length; i++)
{
this.dataStore.Add(guidArray[i], new DesignTimeObjectData(guidArray[i], objData[i], objDataDirty[i]));
}
}
else
{
// Unknown format
}
}
}
}
113 changes: 113 additions & 0 deletions Source/Editor/DualityEditor/DesignTimeObjectDataManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Linq;

using Duality.Serialization;
using Duality.Resources;

namespace Duality.Editor
{
internal class DesignTimeObjectDataManager : ISerializeExplicit
{
private static readonly int GuidByteLength = Guid.Empty.ToByteArray().Length;
private const int Version_First = 1;

private Dictionary<Guid,DesignTimeObjectData> dataStore = new Dictionary<Guid,DesignTimeObjectData>();

public DesignTimeObjectData Request(Guid objId)
{
DesignTimeObjectData data;
if (!this.dataStore.TryGetValue(objId, out data))
{
data = new DesignTimeObjectData(objId, DesignTimeObjectData.Default);
this.dataStore[objId] = data;
}
return data;
}
public void Cleanup()
{
// Remove trivial / default data
var removeQuery =
from p in this.dataStore
where p.Value.IsDefault
select p.Value.ParentObjectId;
foreach (Guid objId in removeQuery.ToArray())
this.dataStore.Remove(objId);
}
public void Optimize()
{
// Optimize data by sharing
var shareValues = this.dataStore.Values.ToList();
while (shareValues.Count > 0)
{
DesignTimeObjectData data = shareValues[shareValues.Count - 1];
foreach (DesignTimeObjectData other in shareValues)
{
data.TryShareData(other);
}
shareValues.RemoveAt(shareValues.Count - 1);
}
}

void ISerializeExplicit.WriteData(IDataWriter writer)
{
this.Cleanup();
this.Optimize();

Guid[] guidArray = this.dataStore.Keys.ToArray();
byte[] data = new byte[guidArray.Length * GuidByteLength];
for (int i = 0; i < guidArray.Length; i++)
{
Array.Copy(
guidArray[i].ToByteArray(), 0,
data, i * GuidByteLength, GuidByteLength);
}
DesignTimeObjectData.DataContainer[] objData = this.dataStore.Values.Select(d => d.Data).ToArray();
bool[] objDataDirty = this.dataStore.Values.Select(d => d.IsAttached).ToArray();

writer.WriteValue("version", Version_First);
writer.WriteValue("dataStoreKeys", data);
writer.WriteValue("dataStoreValues", objData);
writer.WriteValue("dataStoreDirtyFlag", objDataDirty);
}
void ISerializeExplicit.ReadData(IDataReader reader)
{
int version;
reader.ReadValue("version", out version);

if (this.dataStore == null)
this.dataStore = new Dictionary<Guid, DesignTimeObjectData>();
else
this.dataStore.Clear();

if (version == Version_First)
{
byte[] data;
DesignTimeObjectData.DataContainer[] objData;
bool[] objDataDirty;
reader.ReadValue("dataStoreKeys", out data);
reader.ReadValue("dataStoreValues", out objData);
reader.ReadValue("dataStoreDirtyFlag", out objDataDirty);

Guid[] guidArray = new Guid[data.Length / GuidByteLength];
byte[] guidData = new byte[GuidByteLength];
for (int i = 0; i < guidArray.Length; i++)
{
Array.Copy(
data, i * GuidByteLength,
guidData, 0, GuidByteLength);
guidArray[i] = new Guid(guidData);
}

for (int i = 0; i < objData.Length; i++)
{
this.dataStore.Add(guidArray[i], new DesignTimeObjectData(guidArray[i], objData[i], objDataDirty[i]));
}
}
else
{
// Unknown format
}
}
}
}
Loading