-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgizmo_interaction_fix.cs
More file actions
122 lines (99 loc) · 4.66 KB
/
gizmo_interaction_fix.cs
File metadata and controls
122 lines (99 loc) · 4.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// #author habeebweeb
// #name Gizmo Interaction Fix
// #desc Only allows for one translation/scale gizmo to register mouse input at a time
using System.Collections.Generic;
using System.Reflection.Emit;
using HarmonyLib;
using UnityEngine;
public static class GizmoInteractionFix
{
private static Harmony harmony;
private static bool gizmoInteracting;
private static int interactingGizmoID = -1;
public static void Main() =>
harmony = Harmony.CreateAndPatchAll(typeof(GizmoInteractionFix));
public static void Unload()
{
if (harmony is null)
return;
harmony.UnpatchSelf();
harmony = null;
}
private static void UpdateInteracting(GizmoRender gizmoRender, GizmoRender.MOVETYPE startMoveType)
{
if (gizmoInteracting && !NInput.GetMouseButton(0))
{
gizmoInteracting = false;
interactingGizmoID = -1;
}
else if (startMoveType != gizmoRender.beSelectedType && startMoveType == GizmoRender.MOVETYPE.NONE)
{
gizmoInteracting = true;
interactingGizmoID = gizmoRender.GetInstanceID();
}
}
private static void VisibleUpdateInteracting(GizmoRender gizmoRender)
{
if (!gizmoInteracting || !NInput.GetMouseButton(0))
return;
if (gizmoRender.GetInstanceID() != interactingGizmoID)
return;
gizmoInteracting = false;
interactingGizmoID = -1;
}
[HarmonyPatch(typeof(GizmoRender), nameof(GizmoRender.OnRenderObject))]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> OnRenderObjectTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator ilGenerator)
{
var matcher = new CodeMatcher(instructions, ilGenerator);
matcher
// Find end of if (!Visible) block
.MatchEndForward(
new CodeMatch(OpCodes.Ldarg_0),
new CodeMatch(OpCodes.Ldc_I4_0),
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(GizmoRender), nameof(GizmoRender.beSelectedType))))
.Advance(1)
// Disable gizmo interacting if the non-visible gizmo is the interacting gizmo
.InsertAndAdvance(
new CodeInstruction(OpCodes.Ldarg_0),
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(GizmoInteractionFix), nameof(VisibleUpdateInteracting))))
// Find end of initializing the mOVETYPE variable
.MatchEndForward(
new CodeInstruction(OpCodes.Ldarg_0),
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(GizmoRender), nameof(GizmoRender.beSelectedType))),
new CodeInstruction(OpCodes.Stloc_0))
.Advance(1)
.CreateLabel(out var originalPosition)
// Skip checking interacting gizmo and ID if no gizmo is being interacted with
.InsertAndAdvance(
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(GizmoInteractionFix), nameof(gizmoInteracting))),
new CodeInstruction(OpCodes.Brfalse, originalPosition))
// Add gizmo ID and interacting gizmo ID to the stack
.InsertAndAdvance(
new CodeInstruction(OpCodes.Ldarg_0),
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Object), nameof(Object.GetInstanceID))),
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(GizmoInteractionFix), nameof(interactingGizmoID))));
var gizmoIDCheckPosition = matcher.Pos;
matcher
.End()
// Find the "end" of the method and make a label to jump to
.MatchStartBackwards(
new CodeMatch(OpCodes.Ldloc_0),
new CodeMatch(OpCodes.Brtrue),
new CodeMatch(OpCodes.Ldarg_0),
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GizmoRender), nameof(GizmoRender.beSelectedType))))
.CreateLabel(out var renderGizmoEndLabel)
// Go back to id check position
.Start()
.Advance(gizmoIDCheckPosition)
// Branch to end label if the gizmo id does not match the interacting gizmo ID
.InsertAndAdvance(new CodeInstruction(OpCodes.Bne_Un, renderGizmoEndLabel))
.End()
// Update interaction status at the end
.InsertAndAdvance(
new CodeInstruction(OpCodes.Ldarg_0),
new CodeInstruction(OpCodes.Ldloc_0),
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(GizmoInteractionFix), nameof(UpdateInteracting))));
return matcher.InstructionEnumeration();
}
}