Skip to content

Commit

Permalink
refactor: generalize serializer and versioning objects
Browse files Browse the repository at this point in the history
  • Loading branch information
poi-vrc committed Aug 23, 2023
1 parent 5e8df3b commit c20d26d
Show file tree
Hide file tree
Showing 23 changed files with 277 additions and 159 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using Chocopoi.DressingTools.Cabinet;
using Chocopoi.DressingTools.Lib.Cabinet;
using Chocopoi.DressingTools.Lib.Wearable;
using Newtonsoft.Json;
using UnityEditor;
using UnityEngine;

Expand Down Expand Up @@ -96,7 +97,7 @@ public static void AddCabinetWearable(DTCabinet cabinet, WearableConfig config,
var cabinetWearable = wearableGameObject.AddComponent<DTCabinetWearable>();

cabinetWearable.wearableGameObject = wearableGameObject;
cabinetWearable.configJson = config.Serialize();
cabinetWearable.configJson = config.Serialize().ToString(Formatting.None);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ private void OnAddModuleButtonClick()
UpdateModulesView();
}

private ModuleEditor CreateModuleEditor(ModuleProviderBase provider, ModuleConfig module)
private ModuleEditor CreateModuleEditor(ModuleProviderBase provider, IModuleConfig module)
{
// prepare cache if not yet
if (s_moduleEditorTypesCache == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ internal class AnimationGenerationModuleEditor : ModuleEditor, IAnimationGenerat
private bool _foldoutWearableAnimationPresetToggles;
private bool _foldoutWearableAnimationPresetBlendshapes;

public AnimationGenerationModuleEditor(IModuleEditorViewParent parentView, ModuleProviderBase provider, ModuleConfig target) : base(parentView, provider, target)
public AnimationGenerationModuleEditor(IModuleEditorViewParent parentView, ModuleProviderBase provider, IModuleConfig target) : base(parentView, provider, target)
{
_parentView = parentView;
_presenter = new AnimationGenerationModuleEditorPresenter(this, parentView, (AnimationGenerationModuleConfig)target);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ internal class ArmatureMappingModuleEditor : ModuleEditor, IArmatureMappingModul
private bool _removeExistingPrefixSuffix;
private bool _groupBones;

public ArmatureMappingModuleEditor(IModuleEditorViewParent parentView, ModuleProviderBase provider, ModuleConfig target) : base(parentView, provider, target)
public ArmatureMappingModuleEditor(IModuleEditorViewParent parentView, ModuleProviderBase provider, IModuleConfig target) : base(parentView, provider, target)
{
_parentView = parentView;
_presenter = new ArmatureMappingModuleEditorPresenter(this, parentView, (ArmatureMappingModuleConfig)target);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ internal class BlendshapeSyncModuleEditor : ModuleEditor, IBlendshapeSyncModuleE
private IModuleEditorViewParent _parentView;
private BlendshapeSyncModuleEditorPresenter _presenter;

public BlendshapeSyncModuleEditor(IModuleEditorViewParent parentView, ModuleProviderBase provider, ModuleConfig target) : base(parentView, provider, target)
public BlendshapeSyncModuleEditor(IModuleEditorViewParent parentView, ModuleProviderBase provider, IModuleConfig target) : base(parentView, provider, target)
{
_parentView = parentView;
_presenter = new BlendshapeSyncModuleEditorPresenter(this, (BlendshapeSyncModuleConfig)target);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ internal class MoveRootModuleEditor : ModuleEditor, IMoveRootModuleEditorView
private IModuleEditorViewParent _parentView;
private GameObject _moveToGameObject;

public MoveRootModuleEditor(IModuleEditorViewParent parentView, MoveRootModuleProvider provider, ModuleConfig target) : base(parentView, provider, target)
public MoveRootModuleEditor(IModuleEditorViewParent parentView, MoveRootModuleProvider provider, IModuleConfig target) : base(parentView, provider, target)
{
_parentView = parentView;
_presenter = new MoveRootModuleEditorPresenter(this, parentView, (MoveRootModuleConfig)target);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public class ModuleEditor : EditorViewBase

protected ModuleProviderBase provider;

protected ModuleConfig target;
protected IModuleConfig target;

public ModuleEditor(IModuleEditorViewParent parentView, ModuleProviderBase provider, ModuleConfig target)
public ModuleEditor(IModuleEditorViewParent parentView, ModuleProviderBase provider, IModuleConfig target)
{
this.parentView = parentView;
this.provider = provider;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,29 @@
using Chocopoi.DressingTools.Lib.Cabinet;
using Chocopoi.DressingTools.Lib.Logging;
using Chocopoi.DressingTools.Lib.Proxy;
using Chocopoi.DressingTools.Lib.Wearable.Serializers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;

namespace Chocopoi.DressingTools.Lib.Wearable.Modules
{
public class WearableModule
{
public string moduleName;
public ModuleConfig config;
}
public interface IModuleConfig { }

public abstract class ModuleConfig { }
public abstract class VersionedModuleConfig : WearableConfigVersionedObject, IModuleConfig { }

public class UnknownModuleConfig : ModuleConfig
public class UnknownModuleConfig : IModuleConfig
{
public string RawJson { get; private set; }
public UnknownModuleConfig(string rawJson)
{
RawJson = rawJson;
}
}

public class WearableModule
{
public string moduleName;
public IModuleConfig config;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ public abstract class ModuleProviderBase
public abstract int ApplyOrder { get; }
public abstract bool AllowMultiple { get; }

public abstract ModuleConfig DeserializeModuleConfig(JObject jObject);
public virtual string SerializeModuleConfig(ModuleConfig moduleConfig) => JsonConvert.SerializeObject(moduleConfig);
public abstract ModuleConfig NewModuleConfig();
public virtual bool OnBeforeApplyCabinet(ApplyCabinetContext ctx, ModuleConfig moduleConfig) => true;
public virtual bool OnApplyWearable(ApplyCabinetContext cabCtx, ApplyWearableContext wearCtx, ModuleConfig moduleConfig) => true;
public virtual bool OnAfterApplyCabinet(ApplyCabinetContext ctx, ModuleConfig moduleConfig) => true;
public abstract IModuleConfig DeserializeModuleConfig(JObject jObject);
public virtual string SerializeModuleConfig(IModuleConfig moduleConfig) => JsonConvert.SerializeObject(moduleConfig);
public abstract IModuleConfig NewModuleConfig();
public virtual bool OnBeforeApplyCabinet(ApplyCabinetContext ctx, IModuleConfig moduleConfig) => true;
public virtual bool OnApplyWearable(ApplyCabinetContext cabCtx, ApplyWearableContext wearCtx, IModuleConfig moduleConfig) => true;
public virtual bool OnAfterApplyCabinet(ApplyCabinetContext ctx, IModuleConfig moduleConfig) => true;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* File: IWearableConfigSerializer.cs
* File: ISerializer.cs
* Project: DressingTools
* Created Date: Saturday, Aug 22nd 2023, 16:35:11 pm
* Author: chocopoi ([email protected])
Expand All @@ -20,12 +20,13 @@
using System.Globalization;
using Chocopoi.DressingTools.Lib.Wearable.Modules;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Chocopoi.DressingTools.Lib.Wearable.Serializers
{
public interface IWearableConfigSerializer
public interface ISerializer
{
string Serialize(WearableConfig config);
WearableConfig Deserialize(string json);
JObject SerializeFrom(object obj);
void DeserializeFrom(object obj, JObject jObject);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

namespace Chocopoi.DressingTools.Lib.Wearable.Serializers
{
public class Version1Serializer : IWearableConfigSerializer
public class Version1Serializer : ISerializer
{
private class ModuleConverter : JsonConverter
{
Expand All @@ -35,7 +35,7 @@ private class ModuleConverter : JsonConverter
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// we do this serialization ourselves
if (objectType == typeof(ModuleConfig))
if (objectType == typeof(IModuleConfig))
{
return null;
}
Expand Down Expand Up @@ -79,7 +79,7 @@ private static WearableModule DeserializeModule(JObject jObject)
var moduleName = jObject["moduleName"].Value<string>();
var provider = ModuleProviderLocator.Instance.GetProvider(moduleName);

ModuleConfig moduleConfig = provider == null ?
IModuleConfig moduleConfig = provider == null ?
new UnknownModuleConfig(configJObject.ToString(Formatting.None)) :
provider.DeserializeModuleConfig(configJObject);

Expand All @@ -95,12 +95,10 @@ private static WearableModule DeserializeModule(JObject jObject)
private const string KeyAvatarConfig = "avatarConfig";
private const string KeyModules = "modules";

public WearableConfig Deserialize(string json)
public void DeserializeFrom(object obj, JObject jObject)
{
// TODO: perform schema check here

var config = new WearableConfig();
JObject jObject = JObject.Parse(json);
var config = (WearableConfig)obj;

if (!jObject.ContainsKey(KeyVersion) || jObject[KeyVersion].Type != JTokenType.String ||
!jObject.ContainsKey(KeyInfo) || jObject[KeyInfo].Type != JTokenType.Object ||
Expand All @@ -127,12 +125,11 @@ public WearableConfig Deserialize(string json)
var module = DeserializeModule((JObject)moduleJtoken);
config.Modules.Add(module);
}

return config;
}

public string Serialize(WearableConfig config)
public JObject SerializeFrom(object obj)
{
var config = (WearableConfig)obj;
var jObject = new JObject
{
[KeyVersion] = config.Version.ToString(),
Expand All @@ -147,7 +144,7 @@ public string Serialize(WearableConfig config)
}
jObject[KeyModules] = modulesArray;

return jObject.ToString(Formatting.None);
return jObject;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,101 +36,17 @@ public static bool Migrate(string inputJson, out string outputJson)
}
}

public class WearableConfigVersion
{
public int Major { get; private set; }
public int Minor { get; private set; }
public int Patch { get; private set; }
public string Extra { get; private set; }

public WearableConfigVersion(int major, int minor, int patch)
{
Major = major;
Minor = minor;
Patch = patch;
Extra = null;
}

public WearableConfigVersion(int major, int minor, int patch, string extra)
{
Major = major;
Minor = minor;
Patch = patch;
Extra = extra;
}

public WearableConfigVersion(string str)
{
var hyphenIndex = str.IndexOf('-');
string versionStr = null;
if (hyphenIndex != -1)
{
Extra = str.Substring(hyphenIndex + 1);
versionStr = str.Substring(0, hyphenIndex);
}
else
{
versionStr = str;
}

if (versionStr.Length == 0)
{
throw new ArgumentException("Version part is empty");
}

var splits = versionStr.Split('.');
if (splits.Length < 2)
{
throw new ArgumentException("Version string is not in major, minor or optionally patch format");
}

if (!int.TryParse(splits[0], out var major))
{
throw new ArgumentException("Could not parse major: " + splits[0]);
}
Major = major;

if (!int.TryParse(splits[1], out var minor))
{
throw new ArgumentException("Could not parse minor: " + splits[1]);
}
Minor = minor;

if (splits.Length > 2)
{
if (!int.TryParse(splits[2], out var patch))
{
throw new ArgumentException("Could not parse patch: " + splits[2]);
}
Patch = patch;
}
else
{
Patch = 0;
}
}

public override string ToString()
{
var output = string.Format("{0}.{1}.{2}", Major, Minor, Patch);
if (Extra != null)
{
output += "-" + Extra;
}
return output;
}
}

public class WearableConfig
public class WearableConfig : WearableConfigVersionedObject
{
public static readonly WearableConfigVersion CurrentConfigVersion = new WearableConfigVersion(1, 0, 0);
private static readonly Dictionary<int, IWearableConfigSerializer> Serializers = new Dictionary<int, IWearableConfigSerializer>() {
private static readonly Dictionary<int, ISerializer> Serializers = new Dictionary<int, ISerializer>() {
{ 1, new Version1Serializer() },
};

public WearableConfigVersion Version { get; set; }
public override WearableConfigVersion Version { get; set; }
public WearableInfo Info { get; set; }
public AvatarConfig AvatarConfig { get; set; }

public List<WearableModule> Modules;

public WearableConfig()
Expand All @@ -147,39 +63,38 @@ public WearableConfig()
Modules = new List<WearableModule>();
}

public string Serialize()
public override ISerializer GetSerializerByVersion(WearableConfigVersion version)
{
var serializer = Serializers[CurrentConfigVersion.Major];
return serializer.Serialize(this);
if (version == null)
{
return null;
}
return Serializers.ContainsKey(version.Major) ? Serializers[version.Major] : null;
}

public static WearableConfig Deserialize(string json)
{
JObject jObject = JObject.Parse(json);
if (!jObject.ContainsKey("version"))
{
throw new JsonException("Config does not contain version");
}
var configVersion = new WearableConfigVersion(jObject["version"].Value<string>());

if (!Serializers.ContainsKey(configVersion.Major))
{
throw new Exception("Incompatible config version: " + configVersion.Major);
}
// TODO: perform schema check
var jObject = JObject.Parse(json);
return Deserialize(jObject);
}

var serializer = Serializers[configVersion.Major];
return serializer.Deserialize(json);
public static WearableConfig Deserialize(JObject jObject)
{
var config = new WearableConfig();
config.DeserializeFrom(jObject);
return config;
}

public WearableConfig Clone()
{
// a tricky and easier way to copy
// a tricky and easier way to copy
return Deserialize(Serialize());
}

public override string ToString()
{
return Serialize();
return Serialize().ToString(Formatting.None);
}
}
}
Loading

0 comments on commit c20d26d

Please sign in to comment.