forked from TheMysticSword/MysticsRisky2Utils
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCharacterModelMaterialOverrides.cs
143 lines (133 loc) · 6 KB
/
CharacterModelMaterialOverrides.cs
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using Mono.Cecil.Cil;
using MonoMod.Cil;
using RoR2;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace MysticsRisky2Utils
{
public static class CharacterModelMaterialOverrides
{
internal static void Init()
{
On.RoR2.CharacterModel.Awake += (orig, self) =>
{
orig(self);
self.gameObject.AddComponent<MysticsRisky2UtilsCharacterModelMaterialOverridesComponent>();
};
IL.RoR2.CharacterModel.UpdateRendererMaterials += (il) =>
{
ILCursor c = new ILCursor(il);
int ignoreOverlaysPos = 0;
if (c.TryGotoNext(
MoveType.AfterLabel,
x => x.MatchLdarg(out ignoreOverlaysPos),
x => x.MatchBrtrue(out _),
x => x.MatchLdarg(0),
x => x.MatchLdfld<CharacterModel>("activeOverlayCount")
))
{
c.Emit(OpCodes.Ldarg, 0);
c.Emit(OpCodes.Ldloc, 0);
c.Emit(OpCodes.Ldarg, ignoreOverlaysPos);
bool ignoreOverlays2 = false;
c.EmitDelegate<System.Func<CharacterModel, Material, bool, Material>>((characterModel, material, ignoreOverlays) =>
{
var component = characterModel.GetComponent<MysticsRisky2UtilsCharacterModelMaterialOverridesComponent>();
if (component)
{
var activeOverride = materialOverrides.FirstOrDefault(x => component.activeOverrides.Contains(x.key));
if (!activeOverride.Equals(default(MaterialOverrideInfo)))
{
activeOverride.handler(characterModel, ref material, ref ignoreOverlays);
}
}
ignoreOverlays2 = ignoreOverlays;
return material;
});
c.Emit(OpCodes.Stloc, 0);
c.EmitDelegate<System.Func<bool>>(() =>
{
return ignoreOverlays2;
});
c.Emit(OpCodes.Starg, ignoreOverlaysPos);
}
};
IL.RoR2.CharacterModel.UpdateMaterials += (il) =>
{
ILCursor c = new ILCursor(il);
int itemDisplayPos = 0;
if (c.TryGotoNext(
MoveType.AfterLabel,
x => x.MatchCallOrCallvirt<CharacterModel.ParentedPrefabDisplay>("get_itemDisplay"),
x => x.MatchStloc(out itemDisplayPos)
) && c.TryGotoNext(
MoveType.AfterLabel,
x => x.MatchCallOrCallvirt<ItemDisplay>("SetVisibilityLevel")
))
{
c.Emit(OpCodes.Ldarg, 0);
c.Emit(OpCodes.Ldloc, itemDisplayPos);
c.EmitDelegate<System.Action<CharacterModel, ItemDisplay>>((characterModel, itemDisplay) =>
{
var component = characterModel.GetComponent<MysticsRisky2UtilsCharacterModelMaterialOverridesComponent>();
if (component)
{
var activeOverride = materialOverrides.FirstOrDefault(x => component.activeOverrides.Contains(x.key));
if (!activeOverride.Equals(default(MaterialOverrideInfo)))
{
Material material = null;
bool ignoreOverlays = false;
activeOverride.handler(characterModel, ref material, ref ignoreOverlays);
foreach (var rendererInfo in itemDisplay.rendererInfos)
{
rendererInfo.renderer.material = material;
}
}
}
});
}
};
}
private class MysticsRisky2UtilsCharacterModelMaterialOverridesComponent : MonoBehaviour
{
public List<string> activeOverrides = new List<string>();
};
public static void SetOverrideActive(CharacterModel model, string key, bool active)
{
var component = model.GetComponent<MysticsRisky2UtilsCharacterModelMaterialOverridesComponent>();
if (component)
{
var isActiveNow = component.activeOverrides.Contains(key);
if (isActiveNow != active)
{
if (isActiveNow) component.activeOverrides.Remove(key);
else component.activeOverrides.Add(key);
model.materialsDirty = true;
foreach (var parentedPrefabDisplay in model.parentedPrefabDisplays)
{
var itemDisplay = parentedPrefabDisplay.itemDisplay;
var visibilityLevel = itemDisplay.visibilityLevel;
itemDisplay.visibilityLevel = (VisibilityLevel)(-1);
itemDisplay.SetVisibilityLevel(visibilityLevel);
}
}
}
}
public static void AddOverride(string key, MaterialOverrideHandler handler)
{
materialOverrides.Add(new MaterialOverrideInfo
{
key = key,
handler = handler
});
}
public delegate void MaterialOverrideHandler(CharacterModel characterModel, ref Material material, ref bool ignoreOverlays);
public struct MaterialOverrideInfo
{
public string key;
public MaterialOverrideHandler handler;
}
public static List<MaterialOverrideInfo> materialOverrides = new List<MaterialOverrideInfo>();
}
}