Skip to content

Commit afa0fbd

Browse files
committed
Finish porting from the Resonite integration
1 parent 5906213 commit afa0fbd

File tree

6 files changed

+128
-114
lines changed

6 files changed

+128
-114
lines changed

ArrayEditing/ArrayEditing.csproj

+10-7
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
<Version>1.0.0</Version>
1313
<Description>Adds proxy list UI for editing arrays in inspectors. Also improves the look of list UI a bit.</Description>
1414
<PackageLicenseExpression>LGPL-3.0-or-later</PackageLicenseExpression>
15-
<PackageProjectUrl>https://github.com/Nytra/ResoniteArrayEditing</PackageProjectUrl>
16-
<PackageTags>mod; mods; monkeyloader; resonite</PackageTags>
15+
<PackageProjectUrl>https://github.com/ResoniteModdingGroup/ArrayEditing</PackageProjectUrl>
16+
<RepositoryUrl>$(PackageProjectUrl).git</RepositoryUrl>
17+
<PackageTags>mod; mods; monkeyloader; resonite; inspector; inspectors; array; arrays; editing; member; editor</PackageTags>
1718
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage)</TargetsForTfmSpecificContentInPackage>
1819
</PropertyGroup>
1920

@@ -35,15 +36,17 @@
3536
</ItemGroup>
3637

3738
<ItemGroup>
38-
<PackageReference Include="MonkeyLoader" Version="0.22.12-beta" />
39-
<PackageReference Include="MonkeyLoader.GamePacks.Unity" Version="0.6.0-beta" />
40-
<PackageReference Include="MonkeyLoader.GamePacks.Resonite" Version="0.19.2-beta" GeneratePathProperty="true" />
39+
<PackageReference Include="MicroUtils.HarmonyAnalyzers" Version="1.3.0">
40+
<PrivateAssets>all</PrivateAssets>
41+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
42+
</PackageReference>
43+
<PackageReference Include="MonkeyLoader.GamePacks.Resonite" Version="0.20.0-beta" GeneratePathProperty="true" />
4144
<PackageReference Include="PolySharp" Version="1.14.1">
4245
<PrivateAssets>all</PrivateAssets>
4346
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
4447
</PackageReference>
45-
<PackageReference Include="Resonite.Elements.Core" Version="1.2.1" />
46-
<PackageReference Include="Resonite.FrooxEngine" Version="2024.8.6.1341" />
48+
<PackageReference Include="Resonite.Elements.Core" Version="1.3.1" />
49+
<PackageReference Include="Resonite.FrooxEngine" Version="2024.9.31.1216" />
4750
<PackageReference Include="System.Text.Json" Version="8.0.4">
4851
<PrivateAssets>all</PrivateAssets>
4952
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

ArrayEditing/ArrayEditing.cs renamed to ArrayEditing/ArrayEditor.cs

+66-98
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,55 @@
1010
using System.Reflection;
1111
using EnumerableToolkit;
1212
using MonkeyLoader.Resonite;
13+
using MonkeyLoader.Resonite.UI.Inspectors;
1314

1415
namespace ArrayEditing
1516
{
16-
[HarmonyPatchCategory(nameof(SyncArrayEditor))]
17-
[HarmonyPatch(typeof(SyncMemberEditorBuilder), nameof(SyncMemberEditorBuilder.BuildArray))]
18-
internal sealed class SyncArrayEditor : ResoniteMonkey<SyncArrayEditor>
17+
internal sealed class ArrayEditor : ResoniteCancelableEventHandlerMonkey<ArrayEditor, BuildArrayEditorEvent>
1918
{
20-
private static readonly MethodInfo _addLinearValueProxying = AccessTools.Method(typeof(SyncArrayEditor), nameof(AddLinearValueProxying));
21-
private static readonly MethodInfo _addListReferenceProxying = AccessTools.Method(typeof(SyncArrayEditor), nameof(AddListReferenceProxying));
22-
private static readonly MethodInfo _addListValueProxying = AccessTools.Method(typeof(SyncArrayEditor), nameof(AddListValueProxying));
23-
private static readonly MethodInfo _addCurveValueProxying = AccessTools.Method(typeof(SyncArrayEditor), nameof(AddCurveValueProxying));
19+
private static readonly MethodInfo _addCurveValueProxying = AccessTools.Method(typeof(ArrayEditor), nameof(AddCurveValueProxying));
20+
private static readonly MethodInfo _addLinearValueProxying = AccessTools.Method(typeof(ArrayEditor), nameof(AddLinearValueProxying));
21+
private static readonly MethodInfo _addListReferenceProxying = AccessTools.Method(typeof(ArrayEditor), nameof(AddListReferenceProxying));
22+
private static readonly MethodInfo _addListValueProxying = AccessTools.Method(typeof(ArrayEditor), nameof(AddListValueProxying));
2423
private static readonly Type _iWorldElementType = typeof(IWorldElement);
2524
private static readonly Type _particleBurstType = typeof(ParticleBurst);
2625

2726
public override bool CanBeDisabled => true;
2827

29-
protected override IEnumerable<IFeaturePatch> GetFeaturePatches() => Enumerable.Empty<IFeaturePatch>();
28+
public override int Priority => HarmonyLib.Priority.High;
29+
30+
public override bool SkipCanceled => true;
31+
32+
protected override bool AppliesTo(BuildArrayEditorEvent eventData) => Enabled;
33+
34+
protected override IEnumerable<IFeaturePatch> GetFeaturePatches() => [];
35+
36+
protected override void Handle(BuildArrayEditorEvent eventData)
37+
=> eventData.Canceled = BuildArray(eventData.Member, eventData.Name, eventData.FieldInfo, eventData.UI, eventData.LabelSize!.Value);
38+
39+
private static void AddCurveValueProxying<T>(SyncArray<CurveKey<T>> array, SyncElementList<ValueGradientDriver<T>.Point> list)
40+
where T : IEquatable<T>
41+
{
42+
foreach (var key in array)
43+
{
44+
var point = list.Add();
45+
point.Position.Value = key.time;
46+
point.Value.Value = key.value;
47+
}
48+
49+
AddUpdateProxies(array, list, list.Elements);
50+
51+
list.ElementsAdded += (list, startIndex, count) =>
52+
{
53+
var addedElements = list.Elements.Skip(startIndex).Take(count).ToArray();
54+
var buffer = addedElements.Select(point => new CurveKey<T>(point.Position, point.Value)).ToArray();
55+
56+
array.Insert(buffer, startIndex);
57+
AddUpdateProxies(array, list, addedElements);
58+
};
59+
60+
list.ElementsRemoved += (list, startIndex, count) => array.Remove(startIndex, count);
61+
}
3062

3163
private static void AddLinearValueProxying<T>(SyncArray<LinearKey<T>> array, SyncElementList<ValueGradientDriver<T>.Point> list)
3264
where T : IEquatable<T>
@@ -144,30 +176,6 @@ private static void AddTubePointProxying(SyncArray<TubePoint> array, SyncElement
144176
list.ElementsRemoved += (list, startIndex, count) => array.Remove(startIndex, count);
145177
}
146178

147-
private static void AddCurveValueProxying<T>(SyncArray<CurveKey<T>> array, SyncElementList<ValueGradientDriver<T>.Point> list)
148-
where T : IEquatable<T>
149-
{
150-
foreach (var key in array)
151-
{
152-
var point = list.Add();
153-
point.Position.Value = key.time;
154-
point.Value.Value = key.value;
155-
}
156-
157-
AddUpdateProxies(array, list, list.Elements);
158-
159-
list.ElementsAdded += (list, startIndex, count) =>
160-
{
161-
var addedElements = list.Elements.Skip(startIndex).Take(count).ToArray();
162-
var buffer = addedElements.Select(point => new CurveKey<T>(point.Position, point.Value)).ToArray();
163-
164-
array.Insert(buffer, startIndex);
165-
AddUpdateProxies(array, list, addedElements);
166-
};
167-
168-
list.ElementsRemoved += (list, startIndex, count) => array.Remove(startIndex, count);
169-
}
170-
171179
private static void AddUpdateProxies<T>(SyncArray<LinearKey<T>> array,
172180
SyncElementList<ValueGradientDriver<T>.Point> list, IEnumerable<ValueGradientDriver<T>.Point> elements)
173181
where T : IEquatable<T>
@@ -249,23 +257,10 @@ private static void AddUpdateProxies<T>(SyncArray<CurveKey<T>> array,
249257
}
250258
}
251259

252-
private static Component GetOrAttachComponent(Slot targetSlot, Type type, out bool attachedNew)
260+
private static bool BuildArray(ISyncArray array, string name, FieldInfo fieldInfo, UIBuilder ui, float labelSize)
253261
{
254-
attachedNew = false;
255-
if (targetSlot.GetComponent(type) is not Component comp)
256-
{
257-
comp = targetSlot.AttachComponent(type);
258-
attachedNew = true;
259-
}
260-
return comp;
261-
}
262-
263-
private static bool Prefix(ISyncArray array, string name, FieldInfo fieldInfo, UIBuilder ui, float labelSize)
264-
{
265-
if (!Enabled) return true;
266-
267262
if (!TryGetGenericParameters(typeof(SyncArray<>), array.GetType(), out var genericParameters))
268-
return true;
263+
return false;
269264

270265
var isSyncLinear = TryGetGenericParameters(typeof(SyncLinear<>), array.GetType(), out var syncLinearGenericParameters);
271266

@@ -295,7 +290,7 @@ private static bool Prefix(ISyncArray array, string name, FieldInfo fieldInfo, U
295290
if (isSyncLinear && SupportsLerp(syncLinearType!))
296291
{
297292
var gradientType = typeof(ValueGradientDriver<>).MakeGenericType(syncLinearType);
298-
var gradient = GetOrAttachComponent(proxySlot, gradientType, out bool attachedNew);
293+
var gradient = GetOrAttachComponent(proxySlot, gradientType, out var attachedNew);
299294

300295
list = (ISyncList)gradient.GetSyncMember(nameof(ValueGradientDriver<float>.Points));
301296
listField = gradient.GetSyncMemberFieldInfo(nameof(ValueGradientDriver<float>.Points));
@@ -305,27 +300,27 @@ private static bool Prefix(ISyncArray array, string name, FieldInfo fieldInfo, U
305300
if (isParticleBurst)
306301
AddParticleBurstListProxying((SyncArray<LinearKey<ParticleBurst>>)array, (SyncElementList<ValueGradientDriver<int2>.Point>)list);
307302
else
308-
_addLinearValueProxying.MakeGenericMethod(syncLinearType).Invoke(null, new object[] { array, list });
303+
_addLinearValueProxying.MakeGenericMethod(syncLinearType).Invoke(null, [array, list]);
309304
}
310305
}
311306
else if (isSyncCurve && SupportsLerp(syncCurveType!))
312307
{
313308
var gradientType = typeof(ValueGradientDriver<>).MakeGenericType(syncCurveType);
314-
var gradient = GetOrAttachComponent(proxySlot, gradientType, out bool attachedNew);
309+
var gradient = GetOrAttachComponent(proxySlot, gradientType, out var attachedNew);
315310

316311
list = (ISyncList)gradient.GetSyncMember(nameof(ValueGradientDriver<float>.Points));
317312
listField = gradient.GetSyncMemberFieldInfo(nameof(ValueGradientDriver<float>.Points));
318313

319314
if (attachedNew)
320315
{
321-
_addCurveValueProxying.MakeGenericMethod(syncCurveType).Invoke(null, new object[] { array, list });
316+
_addCurveValueProxying.MakeGenericMethod(syncCurveType).Invoke(null, [array, list]);
322317
}
323318
}
324319
else
325320
{
326321
if (arrayType == typeof(TubePoint))
327322
{
328-
var gradient = GetOrAttachComponent(proxySlot, typeof(ValueGradientDriver<float3>), out bool attachedNew);
323+
var gradient = GetOrAttachComponent(proxySlot, typeof(ValueGradientDriver<float3>), out var attachedNew);
329324

330325
list = (ISyncList)gradient.GetSyncMember(nameof(ValueGradientDriver<float3>.Points));
331326
listField = gradient.GetSyncMemberFieldInfo(nameof(ValueGradientDriver<float3>.Points));
@@ -338,27 +333,27 @@ private static bool Prefix(ISyncArray array, string name, FieldInfo fieldInfo, U
338333
else if (Coder.IsEnginePrimitive(arrayType))
339334
{
340335
var multiplexerType = typeof(ValueMultiplexer<>).MakeGenericType(arrayType);
341-
var multiplexer = GetOrAttachComponent(proxySlot, multiplexerType, out bool attachedNew);
336+
var multiplexer = GetOrAttachComponent(proxySlot, multiplexerType, out var attachedNew);
342337
list = (ISyncList)multiplexer.GetSyncMember(nameof(ValueMultiplexer<float>.Values));
343338
listField = multiplexer.GetSyncMemberFieldInfo(nameof(ValueMultiplexer<float>.Values));
344339

345340
if (attachedNew)
346-
_addListValueProxying.MakeGenericMethod(arrayType).Invoke(null, new object[] { array, list });
341+
_addListValueProxying.MakeGenericMethod(arrayType).Invoke(null, [array, list]);
347342
}
348343
else if (_iWorldElementType.IsAssignableFrom(arrayType))
349344
{
350345
var multiplexerType = typeof(ReferenceMultiplexer<>).MakeGenericType(arrayType);
351-
var multiplexer = GetOrAttachComponent(proxySlot, multiplexerType, out bool attachedNew);
346+
var multiplexer = GetOrAttachComponent(proxySlot, multiplexerType, out var attachedNew);
352347
list = (ISyncList)multiplexer.GetSyncMember(nameof(ReferenceMultiplexer<Slot>.References));
353348
listField = multiplexer.GetSyncMemberFieldInfo(nameof(ReferenceMultiplexer<Slot>.References));
354349

355350
if (attachedNew)
356-
_addListReferenceProxying.MakeGenericMethod(arrayType).Invoke(null, new object[] { array, list });
351+
_addListReferenceProxying.MakeGenericMethod(arrayType).Invoke(null, [array, list]);
357352
}
358353
else
359354
{
360355
proxySlot.Destroy();
361-
return true;
356+
return false;
362357
}
363358
}
364359

@@ -392,7 +387,20 @@ void ArrayChanged(IChangeable changeable)
392387
ui.Text(in text);
393388
}
394389

395-
return false;
390+
return true;
391+
}
392+
393+
private static Component GetOrAttachComponent(Slot targetSlot, Type type, out bool attachedNew)
394+
{
395+
attachedNew = false;
396+
397+
if (targetSlot.GetComponent(type) is not Component comp)
398+
{
399+
comp = targetSlot.AttachComponent(type);
400+
attachedNew = true;
401+
}
402+
403+
return comp;
396404
}
397405

398406
private static bool SupportsLerp(Type type)
@@ -417,44 +425,4 @@ private static bool TryGetGenericParameters(Type baseType, Type concreteType, [N
417425
return TryGetGenericParameters(baseType, concreteType.BaseType, out genericParameters);
418426
}
419427
}
420-
421-
internal sealed class ListUI_Improvements : ResoniteMonkey<ListUI_Improvements>
422-
{
423-
public override bool CanBeDisabled => true;
424-
425-
protected override IEnumerable<IFeaturePatch> GetFeaturePatches() => Enumerable.Empty<IFeaturePatch>();
426-
427-
[HarmonyPatchCategory(nameof(ListUI_Improvements))]
428-
[HarmonyPatch(typeof(SyncMemberEditorBuilder), "GenerateMemberField")]
429-
class SyncMemberEditorBuilder_GenerateMemberField_Patch
430-
{
431-
private static bool Prefix(ISyncMember member, string name, UIBuilder ui, float labelSize)
432-
{
433-
if (Enabled && member.Parent is ISyncList && member is SyncObject)
434-
{
435-
ui.CurrentRect.Slot.AttachComponent<HorizontalLayout>();
436-
if (ui.CurrentRect.Slot.GetComponent<LayoutElement>() is LayoutElement layoutElement)
437-
{
438-
layoutElement.MinWidth.Value = 48f;
439-
layoutElement.FlexibleWidth.Value = -1f;
440-
}
441-
}
442-
return true;
443-
}
444-
}
445-
446-
[HarmonyPatchCategory(nameof(ListUI_Improvements))]
447-
[HarmonyPatch(typeof(ListEditor), "BuildListElement")]
448-
class ListEditor_BuildListElement_Patch
449-
{
450-
private static bool Prefix(ISyncList list, ISyncMember member, string name, UIBuilder ui)
451-
{
452-
if (Enabled)
453-
{
454-
ui.Style.MinHeight = 24f;
455-
}
456-
return true;
457-
}
458-
}
459-
}
460428
}

ArrayEditing/ListUIImprovements.cs

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using FrooxEngine.UIX;
2+
using FrooxEngine;
3+
using HarmonyLib;
4+
using MonkeyLoader.Patching;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using MonkeyLoader.Resonite;
8+
9+
namespace ArrayEditing
10+
{
11+
[HarmonyPatch]
12+
[HarmonyPatchCategory(nameof(ListUIImprovements))]
13+
internal sealed class ListUIImprovements : ResoniteMonkey<ListUIImprovements>
14+
{
15+
public override bool CanBeDisabled => true;
16+
17+
protected override IEnumerable<IFeaturePatch> GetFeaturePatches() => [];
18+
19+
[HarmonyPatch(typeof(ListEditor), "BuildListElement")]
20+
private static bool Prefix(UIBuilder ui)
21+
{
22+
if (Enabled)
23+
ui.Style.MinHeight = 24f;
24+
25+
return true;
26+
}
27+
28+
[HarmonyPatch(typeof(SyncMemberEditorBuilder), "GenerateMemberField")]
29+
private static bool Prefix(ISyncMember member, UIBuilder ui)
30+
{
31+
if (!Enabled || member.Parent is not ISyncList || member is not SyncObject)
32+
return true;
33+
34+
ui.CurrentRect.Slot.AttachComponent<HorizontalLayout>();
35+
if (ui.CurrentRect.Slot.GetComponent<LayoutElement>() is LayoutElement layoutElement)
36+
{
37+
layoutElement.MinWidth.Value = 48f;
38+
layoutElement.FlexibleWidth.Value = -1f;
39+
}
40+
41+
return true;
42+
}
43+
}
44+
}

ArrayEditing/Locale/de.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"localeCode": "de",
33
"authors": [ "Banane9" ],
44
"messages": {
5-
"ModTemplate.KeyA": "Lokalisierungsschlüssel A",
6-
"ModTemplate.KeyB": "Noch eine Lokalisierung"
5+
"ArrayEditing.ArrayEditor.Description": "Erstellt eine Liste als Proxy für Arrays, um diese in Inspektoren editieren zu können.",
6+
"ArrayEditing.ListUIImprovements.Description": "Verbessert das UI der Editoren für Listen."
77
}
88
}

ArrayEditing/Locale/en.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"localeCode": "en",
33
"authors": [ "Banane9" ],
44
"messages": {
5-
"ModTemplate.KeyA": "Localization key A",
6-
"ModTemplate.KeyB": "Another localization"
5+
"ArrayEditing.ArrayEditor.Description": "Proxies Arrays to Lists to allow editing them in inspectors.",
6+
"ArrayEditing.ListUIImprovements.Description": "Improves the UI of List Editors."
77
}
88
}

0 commit comments

Comments
 (0)