Skip to content

Commit 75c2d2e

Browse files
committed
Add basic outline for DynamicVariable MemberActions
1 parent aee0177 commit 75c2d2e

3 files changed

Lines changed: 178 additions & 0 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace DynamicVariablePowerTools
6+
{
7+
// Offer dynamic reference variable drive based on dropped dynamic reference (variable)
8+
internal sealed class DynamicReferenceReceiving
9+
{
10+
}
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace DynamicVariablePowerTools
6+
{
7+
// Offer dynamic value variable drive based on dropped dynamic value variable / field reference
8+
internal sealed class DynamicValueReceiving
9+
{
10+
}
11+
}
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
using FrooxEngine;
2+
using FrooxEngine.UIX;
3+
using HarmonyLib;
4+
using MonkeyLoader;
5+
using MonkeyLoader.Resonite;
6+
using MonkeyLoader.Resonite.UI.Inspectors;
7+
using System;
8+
using System.Collections.Generic;
9+
using System.Linq;
10+
using System.Reflection;
11+
using System.Text;
12+
using System.Threading.Tasks;
13+
14+
namespace DynamicVariablePowerTools
15+
{
16+
internal sealed class SetupVariableMemberActions
17+
: ResoniteAsyncEventHandlerMonkey<SetupVariableMemberActions, InspectorMemberActionsMenuItemsGenerationEvent>
18+
{
19+
private static readonly MethodInfo _createFieldItemsMethod = AccessTools.DeclaredMethod(typeof(SetupVariableMemberActions), nameof(CreateFieldItems));
20+
private static readonly MethodInfo _createSyncRefItemsMethod = AccessTools.DeclaredMethod(typeof(SetupVariableMemberActions), nameof(CreateSyncRefItems));
21+
22+
private static readonly Dictionary<Type, Action<InspectorMemberActionsMenuItemsGenerationEvent>> _itemCreatorsByType = new()
23+
{
24+
{ typeof(Type), AccessTools.MethodDelegate<Action<InspectorMemberActionsMenuItemsGenerationEvent>>(AccessTools.DeclaredMethod(typeof(SetupVariableMemberActions), nameof(CreateTypeFieldItems))) }
25+
};
26+
27+
public override bool CanBeDisabled => true;
28+
public override int Priority => HarmonyLib.Priority.Normal;
29+
30+
protected override bool AppliesTo(InspectorMemberActionsMenuItemsGenerationEvent eventData)
31+
=> base.AppliesTo(eventData) && eventData.Target is IField;
32+
33+
protected override Task Handle(InspectorMemberActionsMenuItemsGenerationEvent eventData)
34+
{
35+
Action<InspectorMemberActionsMenuItemsGenerationEvent>? createItems = null;
36+
37+
// Check ISyncRef first because those are IField<RefID>
38+
if (eventData.Target is ISyncRef syncRef)
39+
{
40+
if (!_itemCreatorsByType.TryGetValue(syncRef.TargetType, out createItems))
41+
{
42+
createItems = MakeMethod(_createSyncRefItemsMethod, syncRef.TargetType);
43+
_itemCreatorsByType.Add(syncRef.TargetType, createItems);
44+
}
45+
}
46+
else if (eventData.Target is IField field)
47+
{
48+
if (!_itemCreatorsByType.TryGetValue(field.ValueType, out createItems))
49+
{
50+
createItems = MakeMethod(_createFieldItemsMethod, field.ValueType);
51+
_itemCreatorsByType.Add(field.ValueType, createItems);
52+
}
53+
}
54+
else
55+
{
56+
Logger.Warn(() => $"Tried to create inspector member action items for unsupported target: {eventData.Target.GetType().CompactDescription()}");
57+
return Task.CompletedTask;
58+
}
59+
60+
createItems(eventData);
61+
62+
return Task.CompletedTask;
63+
}
64+
65+
private static void CreateFieldItems<T>(InspectorMemberActionsMenuItemsGenerationEvent eventData)
66+
{
67+
var menuItem = eventData.ContextMenu.AddItem("Set up DynamicField", (Uri)null!, RadiantUI_Constants.Sub.PURPLE);
68+
69+
menuItem.Button.LocalPressed += (button, args) =>
70+
{
71+
// Swap to eventData.Worker when updated
72+
var slot = eventData.Target.FindNearestParent<Slot>();
73+
var dynamicField = slot.AttachComponent<DynamicField<T>>();
74+
dynamicField.TargetField.Target = (IField<T>)eventData.Target;
75+
76+
button.World.LocalUser.CloseContextMenu(eventData.MemberActions);
77+
};
78+
79+
menuItem = eventData.ContextMenu.AddItem("Drive from Dynamic Variable", (Uri)null!, RadiantUI_Constants.Sub.PURPLE);
80+
81+
menuItem.Button.LocalPressed += (button, args) =>
82+
{
83+
button.World.LocalUser.CloseContextMenu(eventData.MemberActions);
84+
85+
button.Slot.StartTask(async () =>
86+
{
87+
await button.World.LocalUser.OpenContextMenu(eventData.MemberActions, args.source.Slot);
88+
89+
// Need to check dynamic variable spaces hiding eachother
90+
// Also use full space/varName for drive
91+
var slot = eventData.Target.FindNearestParent<Slot>();
92+
var options = slot.GetComponentsInParents<DynamicVariableSpace>()
93+
.SelectMany(space => space._dynamicValues.Keys.Where(variable => typeof(T).IsAssignableFrom(variable.type)))
94+
.ToArray();
95+
96+
var menuItem2 = eventData.ContextMenu.AddItem("Blank", (Uri)null!, RadiantUI_Constants.Sub.PURPLE);
97+
menuItem2.Button.LocalPressed += (button2, args2) =>
98+
{
99+
var driver = slot.AttachComponent<DynamicValueVariableDriver<T>>();
100+
driver.Target.Target = (IField<T>)eventData.Target;
101+
button.World.LocalUser.CloseContextMenu(eventData.MemberActions);
102+
};
103+
104+
foreach (var option in options)
105+
{
106+
var menuItem3 = eventData.ContextMenu.AddItem(option.name, (Uri)null!, RadiantUI_Constants.Sub.PURPLE);
107+
menuItem3.Button.LocalPressed += (button2, args2) =>
108+
{
109+
((IField<T>)eventData.Target).DriveFromVariable(option.name);
110+
button.World.LocalUser.CloseContextMenu(eventData.MemberActions);
111+
};
112+
}
113+
});
114+
};
115+
}
116+
117+
private static void CreateSyncRefItems<T>(InspectorMemberActionsMenuItemsGenerationEvent eventData)
118+
where T : class, IWorldElement
119+
{
120+
if (eventData.Target is not SyncRef<T> syncRefTarget)
121+
return;
122+
123+
var menuItem = eventData.ContextMenu.AddItem("Set up DynamicReference", (Uri)null!, RadiantUI_Constants.Sub.PURPLE);
124+
125+
menuItem.Button.LocalPressed += (sender, args) =>
126+
{
127+
// Swap to eventData.Worker when updated
128+
var slot = eventData.Target.FindNearestParent<Slot>();
129+
var dynamicReference = slot.AttachComponent<DynamicReference<T>>();
130+
dynamicReference.TargetReference.Target = syncRefTarget;
131+
};
132+
}
133+
134+
private static void CreateTypeFieldItems(InspectorMemberActionsMenuItemsGenerationEvent eventData)
135+
{
136+
if (eventData.Target is not SyncType syncTypeTarget)
137+
return;
138+
139+
var menuItem = eventData.ContextMenu.AddItem("Set up DynamicTypeField", (Uri)null!, RadiantUI_Constants.Sub.PURPLE);
140+
141+
menuItem.Button.LocalPressed += (sender, args) =>
142+
{
143+
// Swap to eventData.Worker when updated
144+
var slot = eventData.Target.FindNearestParent<Slot>();
145+
var dynamicReference = slot.AttachComponent<DynamicTypeField>();
146+
dynamicReference.TargetField.Target = syncTypeTarget;
147+
};
148+
}
149+
150+
private static Action<InspectorMemberActionsMenuItemsGenerationEvent> MakeMethod(MethodInfo method, Type type)
151+
{
152+
method = method.MakeGenericMethod(type);
153+
return AccessTools.MethodDelegate<Action<InspectorMemberActionsMenuItemsGenerationEvent>>(method);
154+
}
155+
}
156+
}

0 commit comments

Comments
 (0)