forked from GoldenJude/BlacksmithTools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
BodyPartController.cs
170 lines (142 loc) · 5.89 KB
/
BodyPartController.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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace BlacksmithTools
{
class BodyPartController : MonoBehaviour
{
/*
override bones array needs to be here, implement at a later date when making gore mod
*/
public List<VisEquipment.PlayerModel> originalModels = new List<VisEquipment.PlayerModel>();
public VisEquipment viseq;
public void FullUpdate()
{
UpdateBodyModel();
}
public void UpdateBodyModel()
{
if(BodypartSystem.bodypartSettingsAsBones.Keys.Count != BodypartSystem.bodypartSettings.Keys.Count)
{
BodypartSystem.PartCfgToBoneindexes();
BodypartSystem.CleanupCfgs();
}
List<int> boneIndexes = new List<int>();
foreach (int hash in Util.GetEquippedHashes(viseq))
{
foreach (string itemName in BodypartSystem.bodypartSettingsAsBones.Keys)
{
//gotta take into account autistic RRR armor names, method in util
if (itemName.GetStableHashCode() == hash || Util.CorrectRRRArmorPrefabName(itemName).GetStableHashCode() == hash)
{
boneIndexes.AddRange(BodypartSystem.bodypartSettingsAsBones[itemName].ToArray());
}
}
}
Util.LogMessage("Hiding " + boneIndexes.Count.ToString() + " bones");
if (boneIndexes.Count == 0)
{
viseq.m_models[viseq.GetModelIndex()].m_mesh = originalModels[viseq.GetModelIndex()].m_mesh;
return;
}
Mesh freshBody = originalModels[viseq.GetModelIndex()].m_mesh;
Mesh amputatedBody = Amputate(UnityEngine.Object.Instantiate(freshBody), boneIndexes.ToArray());
amputatedBody.name = freshBody.name;
viseq.m_models[viseq.GetModelIndex()].m_mesh = amputatedBody;
}
private Mesh Amputate(Mesh body, int[] bonesToHide)
{
const float minWeightToHide = 0.9f;
const int vertexThreshold = 1;
List<int> tris;
BoneWeight[] weights = body.boneWeights;
for (int subM = 0; subM < body.subMeshCount; subM++)
{
tris = new List<int>( body.GetTriangles(subM) );
bool toHide;
int tri = 0;
while (tri < tris.Count)
{
toHide = false;
int detectedVerts = 0;
for (int vert = 0; vert < 2; vert++)
{
if (toHide) break;
BoneWeight weight = weights[tris[tri + vert]];
float highestWeight = Mathf.Max(weight.weight0, weight.weight1, weight.weight2, weight.weight3);
for (int bone = 0; bone < 4; bone++)
{
int boneIndex = GetBoneIndex(weight, bone);
foreach (int boneToHide in bonesToHide)
{
if (toHide) break;
if (boneIndex != boneToHide) continue;
float value = GetBoneWeight(weight, bone);
if ((value / highestWeight) > minWeightToHide)
{
if (++detectedVerts == vertexThreshold)
{
toHide = true;
break;
}
}
}
}
}
if (toHide)
{
tris.RemoveAt(tri);
tris.RemoveAt(tri);
tris.RemoveAt(tri);
}
else
{
tri += 3;
}
}
body.SetTriangles(tris.ToArray(), subM);
}
return body;
}
int GetBoneIndex(BoneWeight boneWeight, int bone)
{
if (bone == 0) return boneWeight.boneIndex0;
if (bone == 1) return boneWeight.boneIndex1;
if (bone == 2) return boneWeight.boneIndex2;
if (bone == 3) return boneWeight.boneIndex3;
return -1;
}
float GetBoneWeight(BoneWeight boneWeight, int bone)
{
if (bone == 0) return boneWeight.weight0;
if (bone == 1) return boneWeight.weight1;
if (bone == 2) return boneWeight.weight2;
if (bone == 3) return boneWeight.weight3;
return 0f;
}
public void Setup(VisEquipment _viseq)
{
viseq = _viseq;
SaveOriginalModels();
UpdateBodyModel();
Util.LogMessage("bodypart controller attached to " + viseq.name, BepInEx.Logging.LogLevel.Message);
}
void SaveOriginalModels()
{
for (int i = 0; i < viseq.m_models.Length; i++)
{
VisEquipment.PlayerModel model = viseq.m_models[i];
if (model.m_baseMaterial == null) Util.LogMessage("mat null");
Material mat = new Material(model.m_baseMaterial);
mat.name = model.m_baseMaterial.name;
if (model.m_mesh == null) Util.LogMessage("mesh null");
Mesh mesh = UnityEngine.Object.Instantiate(model.m_mesh);
mesh.name = model.m_mesh.name;
originalModels.Add(new VisEquipment.PlayerModel() { m_baseMaterial = mat, m_mesh = mesh });
}
}
}
}