Skip to content

Commit

Permalink
Merge branch 'shibbo:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
DonavinDraws authored Dec 9, 2023
2 parents 960aaa4 + 65387e1 commit 852532a
Show file tree
Hide file tree
Showing 4 changed files with 279 additions and 61 deletions.
48 changes: 28 additions & 20 deletions Fushigi/course/CourseActor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ public class CourseActor
{
public CourseActor(BymlHashTable actorNode)
{
mActorParameters = new Dictionary<string, object>();

mPackName = BymlUtil.GetNodeData<string>(actorNode["Gyaml"]);
mLayer = BymlUtil.GetNodeData<string>(actorNode["Layer"]);

Expand All @@ -42,15 +40,17 @@ public CourseActor(BymlHashTable actorNode)
var components = ParamDB.GetComponentParams(p);
var dynamicNode = actorNode["Dynamic"] as BymlHashTable;

var actorParameters = new Dictionary<string, object>();

foreach (string component in components.Keys)
{
if (dynamicNode.ContainsKey(component) && !mActorParameters.ContainsKey(component))
if (dynamicNode.ContainsKey(component) && !actorParameters.ContainsKey(component))
{
mActorParameters.Add(component, BymlUtil.GetValueFromDynamicNode(dynamicNode[component], component, components[component].Type));
actorParameters.Add(component, BymlUtil.GetValueFromDynamicNode(dynamicNode[component], component, components[component].Type));
}
else
{
if (mActorParameters.ContainsKey(component))
if (actorParameters.ContainsKey(component))
{
continue;
}
Expand All @@ -63,20 +63,22 @@ public CourseActor(BymlHashTable actorNode)
case "S16":
case "U32":
case "S32":
mActorParameters.Add(component, Convert.ToInt32(components[component].InitValue));
actorParameters.Add(component, Convert.ToInt32(components[component].InitValue));
break;
case "F32":
mActorParameters.Add(component, Convert.ToSingle(components[component].InitValue));
actorParameters.Add(component, Convert.ToSingle(components[component].InitValue));
break;
case "Bool":
mActorParameters.Add(component, (bool)components[component].InitValue);
actorParameters.Add(component, (bool)components[component].InitValue);
break;
case "String":
mActorParameters.Add(component, (string)components[component].InitValue);
actorParameters.Add(component, (string)components[component].InitValue);
break;
}
}
}

mActorParameters = new PropertyDict(actorParameters);
}
}
}
Expand All @@ -87,7 +89,9 @@ public CourseActor(BymlHashTable actorNode)

if (actorNode.ContainsKey("System"))
{
foreach(string node in ((BymlHashTable)actorNode["System"]).Keys)
var systemParameters = new List<PropertyDict.Entry>();

foreach (string node in ((BymlHashTable)actorNode["System"]).Keys)
{
BymlHashTable systemNode = ((BymlHashTable)actorNode["System"]);
var curNode = systemNode[node];
Expand All @@ -108,8 +112,10 @@ public CourseActor(BymlHashTable actorNode)
throw new Exception("CourseActor::CourseActor() -- You are the chosen one. You have found a type we don't account for in the system params. WOAH!");
}

mSystemParameters.Add(node, data);
systemParameters.Add(new(node, data));
}

mSystemParameters = new PropertyDict(systemParameters);
}
}

Expand All @@ -130,7 +136,7 @@ public CourseActor(string packName, uint areaHash, string actorLayer)

public void InitializeDefaultDynamicParams()
{
mActorParameters.Clear();
var actorParameters = new Dictionary<string, object>();

if (ParamDB.HasActorComponents(mPackName))
{
Expand All @@ -142,7 +148,7 @@ public void InitializeDefaultDynamicParams()

foreach (string component in components.Keys)
{
if (mActorParameters.ContainsKey(component))
if (actorParameters.ContainsKey(component))
{
continue;
}
Expand All @@ -155,21 +161,23 @@ public void InitializeDefaultDynamicParams()
case "S16":
case "U32":
case "S32":
mActorParameters.Add(component, Convert.ToInt32(components[component].InitValue));
actorParameters.Add(component, Convert.ToInt32(components[component].InitValue));
break;
case "F32":
mActorParameters.Add(component, Convert.ToSingle(components[component].InitValue));
actorParameters.Add(component, Convert.ToSingle(components[component].InitValue));
break;
case "Bool":
mActorParameters.Add(component, (bool)components[component].InitValue);
actorParameters.Add(component, (bool)components[component].InitValue);
break;
case "String":
mActorParameters.Add(component, (string)components[component].InitValue);
actorParameters.Add(component, (string)components[component].InitValue);
break;
}
}
}
}

mActorParameters = new PropertyDict(actorParameters);
}

public BymlHashTable BuildNode(CourseLinkHolder linkHolder)
Expand All @@ -185,7 +193,7 @@ public BymlHashTable BuildNode(CourseLinkHolder linkHolder)
{
BymlHashTable dynamicNode = new();

foreach (KeyValuePair<string, object> dynParam in mActorParameters)
foreach (PropertyDict.Entry dynParam in mActorParameters)
{
object param = mActorParameters[dynParam.Key];

Expand Down Expand Up @@ -256,8 +264,8 @@ public BymlHashTable BuildNode(CourseLinkHolder linkHolder)
public System.Numerics.Vector3 mScale;
public uint mAreaHash;
public ulong mHash;
public Dictionary<string, object> mActorParameters = new();
public Dictionary<string, object> mSystemParameters = new();
public PropertyDict mActorParameters = PropertyDict.Empty;
public PropertyDict mSystemParameters = PropertyDict.Empty;

public ActorPack mActorPack;
}
Expand Down
136 changes: 113 additions & 23 deletions Fushigi/ui/undo/PropertySetUndo.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
using Fasterflect;
using Fushigi.util;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;

namespace Fushigi.ui.undo
{
public abstract class PropertyCapture<T>
public interface IPropertyCapture
{
bool HasChanges();
bool HasChangesSinceLastCheckpoint();
void MakeCheckpoint();
bool TryGetRevertable([NotNullWhen(true)] out IRevertable? revertable, Func<string[], string> nameFunc);
}

public abstract class PropertyCapture<T> : IPropertyCapture
{
protected readonly T mTarget;

Expand Down Expand Up @@ -37,10 +46,10 @@ public void MakeCheckpoint()
}
}

protected abstract IRevertable GetRevertable((string name, object oldValue)[] changedProperties);
protected abstract IRevertable GetRevertable((string name, object oldValue)[] changedProperties, string name);

public bool TryGetRevertable([NotNullWhen(true)] out IRevertable? revertable,
[NotNullWhen(true)] out string[]? names)
Func<string[], string> nameFunc)
{
(string name, object oldValue)[] changedProperties =
mCapturedProperties
Expand All @@ -51,28 +60,32 @@ public bool TryGetRevertable([NotNullWhen(true)] out IRevertable? revertable,
if (changedProperties.Length == 0)
{
revertable = null;
names = null;
return false;
}

revertable = GetRevertable(changedProperties);
names = new string[changedProperties.Length];

var names = new string[changedProperties.Length];
for (int i = 0; i < changedProperties.Length; i++)
names[i] = changedProperties[i].name;

revertable = GetRevertable(changedProperties, nameFunc(names));

return true;
}
}

public class PropertyFieldsCapture : PropertyCapture<object?>
{
public static string[] GetPropertyFieldNames(object target)
internal static BindingFlags sBindingFlags = BindingFlags.Instance | BindingFlags.Public;
public static string[] GetPropertyFieldNames(object target, params Type[] additionalFieldCaptureTypes)
{
List<string> names = [];

foreach (var info in target.GetType().Fields(BindingFlags.Public | BindingFlags.Instance))
foreach (var info in target.GetType().Fields(sBindingFlags))
{
var fieldType = info.Type();
if (!(fieldType.IsValueType || fieldType == typeof(string)))
if (!(fieldType.IsValueType ||
fieldType == typeof(string) ||
additionalFieldCaptureTypes.Contains(fieldType)))
continue;

names.Add(info.Name);
Expand All @@ -86,13 +99,13 @@ public static string[] GetPropertyFieldNames(object target)
private PropertyFieldsCapture()
: base(null, Array.Empty<string>()) { }

public PropertyFieldsCapture(object target)
: base(target, GetPropertyFieldNames(target)) { }
public PropertyFieldsCapture(object target, params Type[] additionalFieldCaptureTypes)
: base(target, GetPropertyFieldNames(target, additionalFieldCaptureTypes)) { }

protected override IRevertable GetRevertable((string name, object oldValue)[] changedProperties)
protected override IRevertable GetRevertable((string name, object oldValue)[] changedProperties, string name)
{
Debug.Assert(mTarget != null);
return new PropertyFieldsSetUndo(mTarget, changedProperties);
return new PropertyFieldsSetUndo(mTarget, changedProperties, name);
}

protected override object GetValue(string name)
Expand All @@ -108,9 +121,10 @@ protected override void SetValue(string name, object value)
}
}

public class PropertyFieldsSetUndo(object target, (string name, object oldValue)[] changedProperties) : IRevertable
public class PropertyFieldsSetUndo(object target, (string name, object oldValue)[] changedProperties,
string name = "Change properties") : IRevertable
{
public string Name => "Change properties";
public string Name => name;

public IRevertable Revert()
{
Expand All @@ -127,19 +141,19 @@ public IRevertable Revert()
}
}

public class PropertyDictCapture : PropertyCapture<IDictionary<string, object>?>
public class PropertyDictCapture : PropertyCapture<PropertyDict?>
{
public static readonly PropertyDictCapture Empty = new PropertyDictCapture();

private PropertyDictCapture()
: base(null, Array.Empty<string>()) { }

public PropertyDictCapture(IDictionary<string, object> target): base(target, [.. target.Keys]) { }
public PropertyDictCapture(PropertyDict target): base(target, [.. target.Keys]) { }

protected override IRevertable GetRevertable((string name, object oldValue)[] changedProperties)
protected override IRevertable GetRevertable((string name, object oldValue)[] changedProperties, string name)
{
Debug.Assert(mTarget != null);
return new PropertyDictSetUndo(mTarget, changedProperties);
return new PropertyDictSetUndo(mTarget, changedProperties, name);
}

protected override object GetValue(string name)
Expand All @@ -155,10 +169,11 @@ protected override void SetValue(string name, object value)
}
}

public class PropertyDictSetUndo(IDictionary<string, object> target,
(string name, object oldValue)[] changedProperties) : IRevertable
public class PropertyDictSetUndo(PropertyDict target,
(string name, object oldValue)[] changedProperties,
string name = "Change properties") : IRevertable
{
public string Name => "Change properties";
public string Name => name;

public IRevertable Revert()
{
Expand All @@ -174,4 +189,79 @@ public IRevertable Revert()
return new PropertyDictSetUndo(target, newChangedProperties);
}
}

public class FullPropertyCapture : IPropertyCapture
{
public static readonly FullPropertyCapture Empty = new FullPropertyCapture();
private readonly PropertyFieldsCapture mFieldsCapture = PropertyFieldsCapture.Empty;
private readonly PropertyDictCapture[] mDictCaptures = [];

private FullPropertyCapture() { }

public FullPropertyCapture(object target)
{
mFieldsCapture = new PropertyFieldsCapture(target, typeof(PropertyDict));

List<PropertyDictCapture> dictCaptures = [];

foreach (var info in target.GetType().Fields(PropertyFieldsCapture.sBindingFlags))
{
var fieldType = info.Type();
if (fieldType != typeof(PropertyDict))
continue;

var value = target.GetFieldValue(info.Name);
dictCaptures.Add(new PropertyDictCapture((PropertyDict)value));
}

mDictCaptures = dictCaptures.ToArray();
}

public bool HasChanges() =>
mFieldsCapture.HasChanges() ||
mDictCaptures.Any(x => x.HasChanges());

public bool HasChangesSinceLastCheckpoint() =>
mFieldsCapture.HasChangesSinceLastCheckpoint() ||
mDictCaptures.Any(x => x.HasChangesSinceLastCheckpoint());

public void MakeCheckpoint()
{
mFieldsCapture.MakeCheckpoint();
foreach (var capture in mDictCaptures)
capture.MakeCheckpoint();
}

public bool TryGetRevertable([NotNullWhen(true)] out IRevertable? revertable,
Func<string[], string> nameFunc)
{
List<IRevertable> revertables = [];
List<string> allNames = [];

if(mFieldsCapture.TryGetRevertable(out IRevertable? fieldRevertable,
names => { allNames.AddRange(names); return null!; }))
{
revertables.Add(fieldRevertable);
}

foreach (var capture in mDictCaptures)
{
if (!capture.TryGetRevertable(out IRevertable? dictRevertable,
names => { allNames.AddRange(names); return null!; }))
continue;

revertables.Add(dictRevertable);
}

if (revertables.Count == 0)
{
revertable = null;
return false;
}

var names = allNames.ToArray();
revertable = new UndoHandler.MultiRevertable(nameFunc(names), [.. revertables]);
return true;
}
}
}
Loading

0 comments on commit 852532a

Please sign in to comment.