using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using FistVR;
using JerryGloves;
using Microsoft.CodeAnalysis;
using Sodalite;
using Sodalite.Api;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace GT3PoseKit
{
[Serializable]
public class Xf
{
public float[] p = new float[3];
public float[] r = new float[4] { 0f, 0f, 0f, 1f };
public Vector3 Pos
{
get
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
if (p == null || p.Length < 3)
{
return Vector3.zero;
}
return new Vector3(p[0], p[1], p[2]);
}
}
public Quaternion Rot
{
get
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
if (r == null || r.Length < 4)
{
return Quaternion.identity;
}
Quaternion val = default(Quaternion);
((Quaternion)(ref val))..ctor(r[0], r[1], r[2], r[3]);
float num = Mathf.Sqrt(val.x * val.x + val.y * val.y + val.z * val.z + val.w * val.w);
if (!(num < 1E-06f))
{
return new Quaternion(val.x / num, val.y / num, val.z / num, val.w / num);
}
return Quaternion.identity;
}
}
public static Xf From(Vector3 pos, Quaternion rot)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
Xf xf = new Xf();
xf.p = new float[3] { pos.x, pos.y, pos.z };
xf.r = new float[4] { rot.x, rot.y, rot.z, rot.w };
return xf;
}
}
[Serializable]
public class PoseData
{
public string slot;
public Xf[] joints;
}
[Serializable]
public class MatchData
{
public string[] itemIds = new string[0];
public string[] objectNames = new string[0];
}
[Serializable]
public class PoseSet
{
public string format;
public int version;
public string name;
public MatchData match;
public bool hasTrigger;
public bool useGrabPos;
public Xf grabPos;
public int jointCount;
public PoseData[] poses;
public bool noAutoCopy;
public PartPoses[] parts;
public MagazinePoses magazine;
}
[Serializable]
public class PartPoses
{
public string name;
public string path;
public string type;
public PoseData[] poses;
}
[Serializable]
public class MagazinePoses
{
public string[] itemIds = new string[0];
public string[] magazineTypes = new string[0];
public PoseData[] poses;
}
[Serializable]
public class RigJoint
{
public string name;
public int parent;
public Xf local;
}
[Serializable]
public class RigHand
{
public string side;
public string rootName;
public RigJoint[] joints;
}
[Serializable]
public class RigDump
{
public string format = "gt3rig";
public int version = 1;
public RigHand left;
public RigHand right;
}
[Serializable]
public class GloveHand
{
public string side;
public int jointCount;
public Xf[] bakeJoints;
public float[] v;
public float[] uv;
public int[] t;
public int[] bi;
public float[] bw;
public string weights;
public string texture;
public float[] color;
public string meshName;
}
[Serializable]
public class GloveDump
{
public string format = "gt3glove";
public int version = 1;
public GloveHand left;
public GloveHand right;
}
[Serializable]
public class GeoPrim
{
public string kind;
public string name;
public Xf xf;
public float[] scale;
public float[] center;
public float[] size;
public float radius;
public float height;
public int dir;
public bool trigger;
}
[Serializable]
public class GeoMesh
{
public string name;
public float[] v;
public int[] t;
}
[Serializable]
public class Marker
{
public string name;
public Xf xf;
}
[Serializable]
public class PartInfo
{
public string name;
public string path;
public string type;
public Xf xf;
}
[Serializable]
public class GunGeo
{
public GeoPrim[] prims;
public GeoMesh[] meshes;
public Marker[] markers;
public PartInfo[] parts;
}
[Serializable]
public class ModelData
{
public string format = "gt3model";
public int version = 1;
public string itemId;
public string name;
public string category;
public int readableMeshes;
public int boxedMeshes;
public string magazineType;
public bool isMagazine;
public string[] compatibleMags;
public GunGeo geo;
}
[Serializable]
public class ItemInfo
{
public string id;
public string name;
public string cat;
public bool mod;
}
[Serializable]
public class LocalSet
{
public string key;
public string file;
public string[] itemIds;
public string modified;
}
[Serializable]
public class LocalSetList
{
public string format = "gt3sets";
public LocalSet[] sets;
}
[Serializable]
public class ItemList
{
public string format = "gt3items";
public ItemInfo[] items;
}
[Serializable]
public class BridgeStatus
{
public string format = "gt3bridge";
public string version;
public int items;
public bool gloves;
public string poseFolder;
}
[Serializable]
public class CaptureData
{
public string format = "gt3capture";
public int version = 1;
public string itemId;
public string objectName;
public string side;
public bool onForegrip;
public bool fromPhysics;
public string partPath;
public string partType;
public Xf partXf;
public string magazineType;
public bool isMagazine;
public Xf handRoot;
public Xf[] joints;
public RigHand rig;
public GunGeo geo;
}
public static class GloveExport
{
public static GloveHand Build(HandsPoseSystem sys, bool left, int maxTexture, out string error)
{
//IL_031b: Unknown result type (might be due to invalid IL or missing references)
//IL_0322: Expected O, but got Unknown
//IL_06cd: Unknown result type (might be due to invalid IL or missing references)
//IL_06d2: Unknown result type (might be due to invalid IL or missing references)
//IL_06d8: Unknown result type (might be due to invalid IL or missing references)
//IL_06df: Unknown result type (might be due to invalid IL or missing references)
//IL_06e4: Unknown result type (might be due to invalid IL or missing references)
//IL_0620: Unknown result type (might be due to invalid IL or missing references)
//IL_0625: Unknown result type (might be due to invalid IL or missing references)
//IL_062f: Unknown result type (might be due to invalid IL or missing references)
//IL_0639: Unknown result type (might be due to invalid IL or missing references)
//IL_0643: Unknown result type (might be due to invalid IL or missing references)
//IL_064d: Unknown result type (might be due to invalid IL or missing references)
//IL_052c: Unknown result type (might be due to invalid IL or missing references)
//IL_0531: Unknown result type (might be due to invalid IL or missing references)
//IL_0384: Unknown result type (might be due to invalid IL or missing references)
//IL_0389: Unknown result type (might be due to invalid IL or missing references)
//IL_038f: Unknown result type (might be due to invalid IL or missing references)
//IL_0396: Unknown result type (might be due to invalid IL or missing references)
//IL_039b: Unknown result type (might be due to invalid IL or missing references)
//IL_039d: Unknown result type (might be due to invalid IL or missing references)
//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
//IL_03ac: Unknown result type (might be due to invalid IL or missing references)
//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
//IL_03be: Unknown result type (might be due to invalid IL or missing references)
//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
//IL_0286: Unknown result type (might be due to invalid IL or missing references)
//IL_028b: Unknown result type (might be due to invalid IL or missing references)
//IL_0290: Unknown result type (might be due to invalid IL or missing references)
//IL_040a: Unknown result type (might be due to invalid IL or missing references)
//IL_040f: Unknown result type (might be due to invalid IL or missing references)
//IL_0413: Unknown result type (might be due to invalid IL or missing references)
//IL_0421: Unknown result type (might be due to invalid IL or missing references)
error = null;
if ((Object)(object)sys == (Object)null)
{
error = "Spawn the GlovesTan3 gloves first";
return null;
}
List<KeyValuePair<GameObject[], Dictionary<Transform, int>>> list = new List<KeyValuePair<GameObject[], Dictionary<Transform, int>>>();
GameObject[][] array = new GameObject[2][] { sys.Fingers, sys.realfingers };
foreach (GameObject[] array2 in array)
{
if (array2 == null || array2.Length == 0)
{
continue;
}
Dictionary<Transform, int> dictionary = new Dictionary<Transform, int>();
for (int j = 0; j < array2.Length; j++)
{
if ((Object)(object)array2[j] != (Object)null)
{
dictionary[array2[j].transform] = j;
}
}
list.Add(new KeyValuePair<GameObject[], Dictionary<Transform, int>>(array2, dictionary));
}
if (list.Count == 0)
{
error = "GlovesTan3 hand has no joints";
return null;
}
List<GameObject> list2 = new List<GameObject>();
if ((Object)(object)sys.HandPhys != (Object)null && sys.HandPhys.activeInHierarchy)
{
list2.Add(sys.HandPhys);
}
if ((Object)(object)sys.HandAnim != (Object)null)
{
list2.Add(sys.HandAnim);
}
if ((Object)(object)sys.HandPhys != (Object)null && !list2.Contains(sys.HandPhys))
{
list2.Add(sys.HandPhys);
}
list2.Add(((Component)sys).gameObject);
SkinnedMeshRenderer[] array3 = null;
foreach (GameObject item in list2)
{
SkinnedMeshRenderer[] componentsInChildren = item.GetComponentsInChildren<SkinnedMeshRenderer>(true);
if (componentsInChildren.Length != 0)
{
array3 = componentsInChildren;
break;
}
}
if (array3 == null)
{
error = "No skinned glove mesh found on the GlovesTan3 hand";
return null;
}
GameObject[] key = list[0].Key;
Dictionary<Transform, int> value = list[0].Value;
int num = -1;
SkinnedMeshRenderer[] array4;
foreach (KeyValuePair<GameObject[], Dictionary<Transform, int>> item2 in list)
{
int num2 = 0;
array4 = array3;
for (int i = 0; i < array4.Length; i++)
{
Transform[] array5 = (Transform[])(((object)array4[i].bones) ?? ((object)new Transform[0]));
foreach (Transform val in array5)
{
if ((Object)(object)val != (Object)null && item2.Value.ContainsKey(val))
{
num2++;
}
}
}
if (num2 > num)
{
num = num2;
key = item2.Key;
value = item2.Value;
}
}
Transform root = CommonRoot(key);
if ((Object)(object)root == (Object)null)
{
error = "Could not find the hand root";
return null;
}
Quaternion invRot = Quaternion.Inverse(root.rotation);
Func<Vector3, Vector3> func = (Vector3 w) => invRot * (w - root.position);
List<float> list3 = new List<float>();
List<float> list4 = new List<float>();
List<int> list5 = new List<int>();
List<int> list6 = new List<int>();
List<float> list7 = new List<float>();
bool flag = true;
string text = "";
string text2 = "";
float[] color = new float[4] { 1f, 1f, 1f, 1f };
array4 = array3;
foreach (SkinnedMeshRenderer val2 in array4)
{
if ((Object)(object)val2 == (Object)null || (Object)(object)val2.sharedMesh == (Object)null)
{
continue;
}
Mesh val3 = new Mesh();
try
{
val2.BakeMesh(val3);
}
catch
{
continue;
}
Vector3[] vertices = val3.vertices;
int[] triangles = val3.triangles;
if (vertices == null || vertices.Length == 0 || triangles == null || triangles.Length == 0)
{
continue;
}
int num3 = list3.Count / 3;
Transform transform = ((Component)val2).transform;
Vector3[] array6 = vertices;
foreach (Vector3 val4 in array6)
{
Vector3 val5 = func(transform.position + transform.rotation * val4);
list3.Add(val5.x);
list3.Add(val5.y);
list3.Add(val5.z);
}
Vector2[] uv = val3.uv;
if (uv != null && uv.Length == vertices.Length)
{
Vector2[] array7 = uv;
foreach (Vector2 val6 in array7)
{
list4.Add(val6.x);
list4.Add(val6.y);
}
}
else
{
for (int num4 = 0; num4 < vertices.Length; num4++)
{
list4.Add(0f);
list4.Add(0f);
}
}
int[] array8 = triangles;
foreach (int num5 in array8)
{
list5.Add(num5 + num3);
}
BoneWeight[] array9 = null;
Mesh sharedMesh = val2.sharedMesh;
if (sharedMesh.isReadable)
{
try
{
array9 = sharedMesh.boneWeights;
}
catch
{
array9 = null;
}
}
Transform[] array10 = (Transform[])(((object)val2.bones) ?? ((object)new Transform[0]));
if (array9 != null && array9.Length == vertices.Length && array10.Length != 0)
{
int[] array11 = new int[array10.Length];
for (int num6 = 0; num6 < array10.Length; num6++)
{
array11[num6] = JointFor(array10[num6], value, root);
}
BoneWeight[] array12 = array9;
for (int k = 0; k < array12.Length; k++)
{
BoneWeight val7 = array12[k];
AddWeight(list6, list7, Map(array11, ((BoneWeight)(ref val7)).boneIndex0), ((BoneWeight)(ref val7)).weight0);
AddWeight(list6, list7, Map(array11, ((BoneWeight)(ref val7)).boneIndex1), ((BoneWeight)(ref val7)).weight1);
AddWeight(list6, list7, Map(array11, ((BoneWeight)(ref val7)).boneIndex2), ((BoneWeight)(ref val7)).weight2);
AddWeight(list6, list7, Map(array11, ((BoneWeight)(ref val7)).boneIndex3), ((BoneWeight)(ref val7)).weight3);
}
}
else
{
flag = false;
NearestWeights(vertices, transform, key, root, func, list6, list7);
}
if (text2 == "")
{
text2 = ((Object)sharedMesh).name;
}
if (text == "")
{
Material sharedMaterial = ((Renderer)val2).sharedMaterial;
if ((Object)(object)sharedMaterial != (Object)null)
{
if (sharedMaterial.HasProperty("_Color"))
{
Color color2 = sharedMaterial.color;
color = new float[4] { color2.r, color2.g, color2.b, color2.a };
}
text = ReadTexture(sharedMaterial.mainTexture, maxTexture);
}
}
Object.Destroy((Object)(object)val3);
}
if (list3.Count == 0)
{
error = "The glove mesh could not be read";
return null;
}
Xf[] array13 = new Xf[key.Length];
for (int num7 = 0; num7 < key.Length; num7++)
{
if ((Object)(object)key[num7] == (Object)null)
{
array13[num7] = new Xf();
continue;
}
Transform transform2 = key[num7].transform;
array13[num7] = Xf.From(func(transform2.position), invRot * transform2.rotation);
}
return new GloveHand
{
side = (left ? "L" : "R"),
jointCount = key.Length,
bakeJoints = array13,
v = list3.ToArray(),
uv = list4.ToArray(),
t = list5.ToArray(),
bi = list6.ToArray(),
bw = list7.ToArray(),
weights = (flag ? "skin" : "nearest"),
texture = text,
color = color,
meshName = text2
};
}
private static int Map(int[] map, int boneIndex)
{
if (boneIndex < 0 || boneIndex >= map.Length)
{
return -1;
}
return map[boneIndex];
}
private static void AddWeight(List<int> bi, List<float> bw, int joint, float weight)
{
bi.Add(joint);
bw.Add(weight);
}
private static int JointFor(Transform bone, Dictionary<Transform, int> index, Transform root)
{
Transform val = bone;
while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root)
{
if (index.TryGetValue(val, out var value))
{
return value;
}
val = val.parent;
}
return -1;
}
private static void NearestWeights(Vector3[] bv, Transform smrT, GameObject[] joints, Transform root, Func<Vector3, Vector3> toRoot, List<int> bi, List<float> bw)
{
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
//IL_01af: Unknown result type (might be due to invalid IL or missing references)
//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
//IL_0180: Unknown result type (might be due to invalid IL or missing references)
//IL_0185: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_015e: Unknown result type (might be due to invalid IL or missing references)
//IL_0168: Unknown result type (might be due to invalid IL or missing references)
//IL_016d: Unknown result type (might be due to invalid IL or missing references)
//IL_0172: Unknown result type (might be due to invalid IL or missing references)
//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
int num = joints.Length;
Vector3[] array = (Vector3[])(object)new Vector3[num];
int[] array2 = new int[num];
bool[] array3 = new bool[num];
Dictionary<Transform, int> dictionary = new Dictionary<Transform, int>();
for (int i = 0; i < num; i++)
{
if ((Object)(object)joints[i] != (Object)null)
{
dictionary[joints[i].transform] = i;
array[i] = joints[i].transform.position;
}
}
for (int j = 0; j < num; j++)
{
array2[j] = -1;
if ((Object)(object)joints[j] == (Object)null)
{
continue;
}
Transform parent = joints[j].transform.parent;
while ((Object)(object)parent != (Object)null && (Object)(object)parent != (Object)(object)root)
{
if (dictionary.TryGetValue(parent, out var value))
{
array2[j] = value;
break;
}
parent = parent.parent;
}
if (array2[j] >= 0)
{
array3[array2[j]] = true;
}
}
Vector3[] array4 = (Vector3[])(object)new Vector3[num];
Vector3[] array5 = (Vector3[])(object)new Vector3[num];
for (int k = 0; k < num; k++)
{
array4[k] = array[k];
int num2 = -1;
for (int l = 0; l < num; l++)
{
if (array2[l] == k)
{
num2 = l;
break;
}
}
if (num2 >= 0)
{
array5[k] = array[num2];
}
else if (array2[k] >= 0)
{
array5[k] = array[k] + (array[k] - array[array2[k]]) * 0.7f;
}
else
{
array5[k] = array[k];
}
}
foreach (Vector3 val in bv)
{
Vector3 p = smrT.position + smrT.rotation * val;
int num3 = -1;
int num4 = -1;
float num5 = float.MaxValue;
float num6 = float.MaxValue;
for (int n = 0; n < num; n++)
{
if (!((Object)(object)joints[n] == (Object)null))
{
float num7 = SegDist(p, array4[n], array5[n]);
if (num7 < num5)
{
num6 = num5;
num4 = num3;
num5 = num7;
num3 = n;
}
else if (num7 < num6)
{
num6 = num7;
num4 = n;
}
}
}
float num8 = 1f / Mathf.Pow(Mathf.Max(num5, 0.0001f), 4f);
float num9 = ((num4 >= 0) ? (1f / Mathf.Pow(Mathf.Max(num6, 0.0001f), 4f)) : 0f);
float num10 = num8 + num9;
bi.Add(num3);
bw.Add(num8 / num10);
bi.Add((num4 >= 0) ? num4 : num3);
bw.Add(num9 / num10);
bi.Add(num3);
bw.Add(0f);
bi.Add(num3);
bw.Add(0f);
}
}
private static float SegDist(Vector3 p, Vector3 a, Vector3 b)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = b - a;
float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
float num = ((sqrMagnitude < 1E-10f) ? 0f : Mathf.Clamp01(Vector3.Dot(p - a, val) / sqrMagnitude));
Vector3 val2 = p - (a + val * num);
return ((Vector3)(ref val2)).magnitude;
}
private static string ReadTexture(Texture tex, int maxSize)
{
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Expected O, but got Unknown
if ((Object)(object)tex == (Object)null)
{
return "";
}
try
{
int width = tex.width;
int height = tex.height;
float num = Mathf.Min(1f, (float)maxSize / (float)Mathf.Max(width, height));
width = Mathf.Max(1, Mathf.RoundToInt((float)width * num));
height = Mathf.Max(1, Mathf.RoundToInt((float)height * num));
RenderTexture temporary = RenderTexture.GetTemporary(width, height, 0, (RenderTextureFormat)0);
RenderTexture active = RenderTexture.active;
Graphics.Blit(tex, temporary);
RenderTexture.active = temporary;
Texture2D val = new Texture2D(width, height, (TextureFormat)5, false);
val.ReadPixels(new Rect(0f, 0f, (float)width, (float)height), 0, 0);
val.Apply();
RenderTexture.active = active;
RenderTexture.ReleaseTemporary(temporary);
byte[] array = val.EncodeToPNG();
Object.Destroy((Object)val);
return (array != null) ? Convert.ToBase64String(array) : "";
}
catch
{
return "";
}
}
private static Transform CommonRoot(GameObject[] joints)
{
List<Transform> list = null;
GameObject[] array = joints;
foreach (GameObject val in array)
{
if ((Object)(object)val == (Object)null)
{
continue;
}
List<Transform> list2 = new List<Transform>();
Transform val2 = val.transform;
while ((Object)(object)val2 != (Object)null)
{
list2.Insert(0, val2);
val2 = val2.parent;
}
if (list == null)
{
list = list2;
continue;
}
int j;
for (j = 0; j < list.Count && j < list2.Count && (Object)(object)list[j] == (Object)(object)list2[j]; j++)
{
}
list.RemoveRange(j, list.Count - j);
}
if (list == null || list.Count == 0)
{
return null;
}
Transform val3 = list[list.Count - 1];
array = joints;
foreach (GameObject val4 in array)
{
if ((Object)(object)val4 != (Object)null && (Object)(object)val4.transform == (Object)(object)val3)
{
return val3.parent ?? val3;
}
}
return val3;
}
}
public class ModelServer
{
public delegate void Handler(string method, string path, Dictionary<string, string> query, string body, out int status, out string json);
private const long MaxBody = 33554432L;
private readonly HttpListener _listener = new HttpListener();
private readonly Queue<HttpListenerContext> _pending = new Queue<HttpListenerContext>();
private readonly Handler _handler;
private Thread _thread;
private volatile bool _running;
public byte[] PageHtml;
public int Port { get; private set; }
public ModelServer(int port, Handler handler)
{
Port = port;
_handler = handler;
_listener.Prefixes.Add("http://127.0.0.1:" + port + "/");
_listener.Prefixes.Add("http://localhost:" + port + "/");
}
public void Start()
{
_listener.Start();
_running = true;
_thread = new Thread(Loop)
{
IsBackground = true,
Name = "GT3PoseKit bridge"
};
_thread.Start();
}
public void Stop()
{
_running = false;
try
{
_listener.Stop();
_listener.Close();
}
catch
{
}
}
private void Loop()
{
while (_running)
{
try
{
HttpListenerContext context = _listener.GetContext();
lock (_pending)
{
_pending.Enqueue(context);
}
}
catch
{
if (!_running)
{
break;
}
}
}
}
public void Pump(int max)
{
for (int i = 0; i < max; i++)
{
HttpListenerContext ctx;
lock (_pending)
{
if (_pending.Count == 0)
{
break;
}
ctx = _pending.Dequeue();
}
Respond(ctx);
}
}
private void Respond(HttpListenerContext ctx)
{
int status = 200;
try
{
HttpListenerResponse response = ctx.Response;
response.AddHeader("Access-Control-Allow-Origin", "*");
response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
response.AddHeader("Access-Control-Allow-Headers", "Content-Type, X-PoseKit");
response.AddHeader("Access-Control-Allow-Private-Network", "true");
response.AddHeader("Cache-Control", "no-store");
string httpMethod = ctx.Request.HttpMethod;
string text = ctx.Request.Url.AbsolutePath.TrimEnd(new char[1] { '/' }).ToLowerInvariant();
if (httpMethod == "GET" && PageHtml != null)
{
switch (text)
{
case "":
case "/editor":
case "/index.html":
response.StatusCode = 200;
response.ContentType = "text/html; charset=utf-8";
response.ContentLength64 = PageHtml.Length;
response.OutputStream.Write(PageHtml, 0, PageHtml.Length);
response.OutputStream.Close();
return;
}
}
string json;
if (httpMethod == "OPTIONS")
{
json = "";
status = 204;
}
else if (httpMethod != "GET" && httpMethod != "POST")
{
json = Err("only GET and POST are supported");
status = 405;
}
else if (httpMethod == "POST" && ctx.Request.Headers["X-PoseKit"] == null)
{
json = Err("missing X-PoseKit header");
status = 403;
}
else if (httpMethod == "POST" && ctx.Request.ContentLength64 > 33554432)
{
json = Err("request too large");
status = 413;
}
else
{
Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
NameValueCollection queryString = ctx.Request.QueryString;
string[] allKeys = queryString.AllKeys;
foreach (string text2 in allKeys)
{
if (text2 != null)
{
dictionary[text2] = queryString[text2];
}
}
string body = null;
if (httpMethod == "POST")
{
using StreamReader streamReader = new StreamReader(ctx.Request.InputStream, Encoding.UTF8);
body = streamReader.ReadToEnd();
}
try
{
_handler(httpMethod, ctx.Request.Url.AbsolutePath.TrimEnd(new char[1] { '/' }).ToLowerInvariant(), dictionary, body, out status, out json);
}
catch (Exception ex)
{
status = 500;
json = Err(ex.Message);
}
}
byte[] bytes = Encoding.UTF8.GetBytes(json ?? "");
response.StatusCode = status;
response.ContentType = "application/json; charset=utf-8";
response.ContentLength64 = bytes.Length;
if (bytes.Length != 0)
{
response.OutputStream.Write(bytes, 0, bytes.Length);
}
response.OutputStream.Close();
}
catch
{
try
{
ctx.Response.Abort();
}
catch
{
}
}
}
public static string Err(string msg)
{
return "{\"error\":\"" + (msg ?? "").Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", " ") + "\"}";
}
}
[BepInPlugin("gt3posekit.loader", "GlovesTan3 PoseKit", "1.0.0")]
[BepInProcess("h3vr.exe")]
public class PoseKitPlugin : BaseUnityPlugin
{
private class Injected
{
public HandPoseItem hpi;
public Transform parent;
public PoseSet set;
public string target;
}
public const string Guid = "gt3posekit.loader";
public const string Version = "1.0.0";
private const string InjectedName = "GT3PoseKit_HandPoseItem";
private static readonly string[] Slots = new string[8] { "IdleL", "IdleR", "ForeL", "ForeR", "FireStartL", "FireStartR", "FireEndL", "FireEndR" };
private string _dir;
private readonly Dictionary<string, PoseSet> _byItemId = new Dictionary<string, PoseSet>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, PoseSet> _byName = new Dictionary<string, PoseSet>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, PoseSet> _magById = new Dictionary<string, PoseSet>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, PoseSet> _magByType = new Dictionary<string, PoseSet>(StringComparer.OrdinalIgnoreCase);
private readonly HashSet<int> _checked = new HashSet<int>();
private ConfigEntry<KeyCode> _keyCaptureL;
private ConfigEntry<KeyCode> _keyCaptureR;
private ConfigEntry<KeyCode> _keyReload;
private ConfigEntry<KeyCode> _keyDumpRig;
private ConfigEntry<KeyCode> _keyExportModel;
private ConfigEntry<KeyCode> _keyOpenEditor;
private ConfigEntry<bool> _exportMeshes;
private ConfigEntry<bool> _bridgeEnabled;
private ConfigEntry<bool> _allowLive;
private ConfigEntry<bool> _autoCopy;
private ConfigEntry<bool> _openOnStart;
private ConfigEntry<float> _autoCopyThreshold;
private ConfigEntry<int> _maxMeshVerts;
private ConfigEntry<int> _bridgePort;
private ConfigEntry<int> _gloveTexSize;
private ModelServer _server;
private readonly List<Injected> _injected = new List<Injected>();
private static readonly FieldInfo LockedHpiField = typeof(HandsPoseSystem).GetField("lockedHpi", BindingFlags.Instance | BindingFlags.NonPublic);
private readonly Dictionary<string, PoseSet> _similarCache = new Dictionary<string, PoseSet>(StringComparer.OrdinalIgnoreCase);
private void Awake()
{
_dir = Path.Combine(Paths.ConfigPath, "GlovesTan3Poses");
Directory.CreateDirectory(_dir);
Directory.CreateDirectory(Path.Combine(_dir, "captures"));
Directory.CreateDirectory(Path.Combine(_dir, "models"));
_keyCaptureL = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "CaptureLeft", (KeyCode)286, "Capture the left hand's pose on the object it holds.");
_keyCaptureR = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "CaptureRight", (KeyCode)287, "Capture the right hand's pose on the object it holds.");
_keyReload = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "ReloadPoses", (KeyCode)288, "Reload every pose file and re-apply to spawned objects.");
_keyDumpRig = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "DumpRig", (KeyCode)289, "Write the GlovesTan3 hand skeleton to rig.json.");
_exportMeshes = ((BaseUnityPlugin)this).Config.Bind<bool>("Capture", "ExportMeshes", true, "Include readable gun meshes in captures (the editor shows them as reference).");
_maxMeshVerts = ((BaseUnityPlugin)this).Config.Bind<int>("Capture", "MaxMeshVertices", 120000, "Upper limit on total exported mesh vertices per capture or model.");
_gloveTexSize = ((BaseUnityPlugin)this).Config.Bind<int>("Capture", "GloveTextureSize", 1024, "Largest side of the glove texture sent to the editor (pixels).");
_keyExportModel = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "ExportHeldModel", (KeyCode)290, "Write the model of the object in either hand to the models folder.");
_keyOpenEditor = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "OpenEditor", (KeyCode)291, "Open the PoseKit editor in your default browser.");
_bridgeEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Editor bridge", "Enabled", true, "Serve item models, the hand rig and captures to the PoseKit editor over localhost.");
_openOnStart = ((BaseUnityPlugin)this).Config.Bind<bool>("Editor bridge", "OpenEditorOnStart", false, "Open the editor in your default browser automatically when the game starts.");
_bridgePort = ((BaseUnityPlugin)this).Config.Bind<int>("Editor bridge", "Port", 48261, "Localhost port for the editor bridge (must match the port in the editor).");
_allowLive = ((BaseUnityPlugin)this).Config.Bind<bool>("Editor bridge", "AllowLiveImport", true, "Let the editor push pose sets into the running game (and save them into the pose folder when asked).");
_autoCopy = ((BaseUnityPlugin)this).Config.Bind<bool>("Auto copy", "InGameFallback", false, "Off by default: use the editor's \"Auto copy to similar guns\" button instead. When on, a gun without poses silently reuses the poses of the most similarly named gun that has them (e.g. G18 uses G17's).");
_autoCopyThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("Auto copy", "MinimumSimilarity", 0.8f, "How alike the names must be, 0 to 1. 0.9 = only number variants like G17/G18; 0.85 also allows suffixes like G17L.");
LoadPoseSets();
try
{
RegisterWristMenu();
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Sodalite wrist menu unavailable, hotkeys only: " + ex.Message));
}
if (_bridgeEnabled.Value)
{
try
{
_server = new ModelServer(_bridgePort.Value, HandleRequest);
_server.PageHtml = LoadEditorPage();
_server.Start();
((BaseUnityPlugin)this).Logger.LogInfo((object)("Editor bridge listening on http://127.0.0.1:" + _bridgePort.Value + "/" + ((_server.PageHtml != null) ? " (open that address in a browser for the editor)" : "")));
if (_openOnStart.Value)
{
OpenEditor();
}
}
catch (Exception ex2)
{
_server = null;
((BaseUnityPlugin)this).Logger.LogError((object)("Editor bridge could not start on port " + _bridgePort.Value + ": " + ex2.Message));
}
}
((BaseUnityPlugin)this).Logger.LogInfo((object)("Pose folder: " + _dir));
}
private byte[] LoadEditorPage()
{
try
{
string path = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "index.html");
if (File.Exists(path))
{
return File.ReadAllBytes(path);
}
using Stream stream = typeof(PoseKitPlugin).Assembly.GetManifestResourceStream("GT3PoseKit.editor.html");
if (stream == null)
{
return null;
}
byte[] array = new byte[stream.Length];
int num;
for (int i = 0; i < array.Length; i += num)
{
num = stream.Read(array, i, array.Length - i);
if (num <= 0)
{
break;
}
}
return array;
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Editor page unavailable: " + ex.Message));
return null;
}
}
private void OnDestroy()
{
if (_server != null)
{
_server.Stop();
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void RegisterWristMenu()
{
AddButton("PoseKit: Capture L", delegate
{
Capture(left: true);
});
AddButton("PoseKit: Capture R", delegate
{
Capture(left: false);
});
AddButton("PoseKit: Reload poses", delegate
{
Reload();
});
AddButton("PoseKit: Dump rig", delegate
{
DumpRig();
});
AddButton("PoseKit: Export held model", delegate
{
ExportHeldModel();
});
AddButton("PoseKit: Open editor", delegate
{
OpenEditor();
});
}
private void OpenEditor()
{
if (_server == null || _server.PageHtml == null)
{
Notify("The editor bridge isn't running (check [Editor bridge] Enabled in gt3posekit.loader.cfg)");
return;
}
string text = "http://127.0.0.1:" + _server.Port + "/";
try
{
Application.OpenURL(text);
Notify("Opened the PoseKit editor in your browser: " + text);
}
catch (Exception ex)
{
Notify("Could not open a browser (" + ex.Message + "). Open " + text + " yourself.");
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void AddButton(string text, Action<FVRViveHand> onClick)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected O, but got Unknown
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected O, but got Unknown
WristMenuButton item = new WristMenuButton(text, (ButtonClickEvent)delegate(object sender, ButtonClickEventArgs args)
{
onClick(args.Hand);
});
WristMenuAPI.Buttons.Add(item);
}
private void Update()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
if (Input.GetKeyDown(_keyCaptureL.Value))
{
Capture(left: true);
}
if (Input.GetKeyDown(_keyCaptureR.Value))
{
Capture(left: false);
}
if (Input.GetKeyDown(_keyReload.Value))
{
Reload();
}
if (Input.GetKeyDown(_keyDumpRig.Value))
{
DumpRig();
}
if (Input.GetKeyDown(_keyExportModel.Value))
{
ExportHeldModel();
}
if (Input.GetKeyDown(_keyOpenEditor.Value))
{
OpenEditor();
}
if (_server != null)
{
_server.Pump(2);
}
if (_byItemId.Count == 0 && _byName.Count == 0 && _magById.Count == 0 && _magByType.Count == 0)
{
return;
}
FVRMovementManager currentMovementManager = GM.CurrentMovementManager;
if ((Object)(object)currentMovementManager == (Object)null || currentMovementManager.Hands == null)
{
return;
}
FVRViveHand[] hands = currentMovementManager.Hands;
foreach (FVRViveHand val in hands)
{
if (!((Object)(object)val == (Object)null))
{
FVRPhysicalObject val2 = RootObject(val.CurrentInteractable);
if ((Object)(object)val2 != (Object)null)
{
TryInject(val2);
}
}
}
}
private static bool HasPoses(PoseData[] poses)
{
if (poses == null)
{
return false;
}
foreach (PoseData poseData in poses)
{
if (poseData != null && poseData.joints != null && poseData.joints.Length != 0)
{
return true;
}
}
return false;
}
private void LoadPoseSets()
{
_byItemId.Clear();
_byName.Clear();
_magById.Clear();
_magByType.Clear();
int num = 0;
string[] files = Directory.GetFiles(_dir, "*.json");
foreach (string text in files)
{
if (Path.GetFileName(text).Equals("rig.json", StringComparison.OrdinalIgnoreCase))
{
continue;
}
try
{
PoseSet poseSet = JsonUtility.FromJson<PoseSet>(File.ReadAllText(text));
if (poseSet != null && !(poseSet.format != "gt3poses"))
{
if (poseSet.match == null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)(text + ": no match block, skipped"));
continue;
}
Register(poseSet);
num++;
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)("Failed to read " + text + ": " + ex.Message));
}
}
((BaseUnityPlugin)this).Logger.LogInfo((object)("Loaded " + num + " pose set(s)."));
}
private void Register(PoseSet set)
{
string[] array;
if (set.match != null)
{
array = set.match.itemIds ?? new string[0];
foreach (string text in array)
{
if (!string.IsNullOrEmpty(text))
{
_byItemId[text.Trim()] = set;
}
}
array = set.match.objectNames ?? new string[0];
foreach (string text2 in array)
{
if (!string.IsNullOrEmpty(text2))
{
_byName[text2.Trim()] = set;
}
}
}
MagazinePoses magazine = set.magazine;
if (magazine == null || !HasPoses(magazine.poses))
{
return;
}
array = magazine.itemIds ?? new string[0];
foreach (string text3 in array)
{
if (!string.IsNullOrEmpty(text3))
{
_magById[text3.Trim()] = set;
}
}
array = magazine.magazineTypes ?? new string[0];
foreach (string text4 in array)
{
if (!string.IsNullOrEmpty(text4))
{
_magByType[text4.Trim()] = set;
}
}
}
private static string SetKey(PoseSet s)
{
if (s == null)
{
return "";
}
if (!string.IsNullOrEmpty(s.name))
{
return s.name.Trim();
}
if (s.match != null && s.match.itemIds != null && s.match.itemIds.Length != 0)
{
return s.match.itemIds[0];
}
if (s.magazine != null && s.magazine.magazineTypes != null && s.magazine.magazineTypes.Length != 0)
{
return "mag:" + s.magazine.magazineTypes[0];
}
return "";
}
private static void Unregister(Dictionary<string, PoseSet> dict, string key)
{
List<string> list = new List<string>();
foreach (KeyValuePair<string, PoseSet> item in dict)
{
if (SetKey(item.Value) == key)
{
list.Add(item.Key);
}
}
foreach (string item2 in list)
{
dict.Remove(item2);
}
}
private static PoseData[] PosesFor(PoseSet set, string target)
{
if (target == "gun")
{
return set.poses;
}
if (target == "mag")
{
if (set.magazine == null)
{
return null;
}
return set.magazine.poses;
}
if (target.StartsWith("part:"))
{
string text = target.Substring(5);
PartPoses[] array = set.parts ?? new PartPoses[0];
foreach (PartPoses partPoses in array)
{
if (partPoses != null && partPoses.path == text)
{
return partPoses.poses;
}
}
}
return null;
}
private static HandPose GetSlot(HandPoseItem h, string slot)
{
return (HandPose)(slot switch
{
"IdleL" => h.IdleL,
"IdleR" => h.IdleR,
"ForeL" => h.ForeL,
"ForeR" => h.ForeR,
"FireStartL" => h.FireStartL,
"FireStartR" => h.FireStartR,
"FireEndL" => h.FireEndL,
_ => h.FireEndR,
});
}
private static bool UpdateInPlace(HandPoseItem h, PoseData[] data, bool hasTrigger)
{
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: Unknown result type (might be due to invalid IL or missing references)
Dictionary<string, PoseData> dictionary = new Dictionary<string, PoseData>();
PoseData[] array = data ?? new PoseData[0];
foreach (PoseData poseData in array)
{
if (poseData != null && !string.IsNullOrEmpty(poseData.slot) && poseData.joints != null && poseData.joints.Length != 0)
{
dictionary[poseData.slot] = poseData;
}
}
string[] slots = Slots;
foreach (string text in slots)
{
HandPose slot = GetSlot(h, text);
PoseData value;
bool flag = dictionary.TryGetValue(text, out value);
if ((Object)(object)slot != (Object)null != flag)
{
return false;
}
if ((Object)(object)slot != (Object)null && (slot.Fingers == null || slot.Fingers.Length != value.joints.Length))
{
return false;
}
}
slots = Slots;
foreach (string text2 in slots)
{
HandPose slot2 = GetSlot(h, text2);
if ((Object)(object)slot2 == (Object)null)
{
continue;
}
PoseData poseData2 = dictionary[text2];
for (int j = 0; j < slot2.Fingers.Length; j++)
{
if (!((Object)(object)slot2.Fingers[j] == (Object)null))
{
slot2.Fingers[j].transform.localPosition = poseData2.joints[j].Pos;
slot2.Fingers[j].transform.localRotation = poseData2.joints[j].Rot;
}
}
}
h.hasTrigger = hasTrigger && (((Object)(object)h.FireStartL != (Object)null && (Object)(object)h.FireEndL != (Object)null) || ((Object)(object)h.FireStartR != (Object)null && (Object)(object)h.FireEndR != (Object)null));
return true;
}
private static void Relock(HandPoseItem oldHpi, HandPoseItem newHpi)
{
if ((object)LockedHpiField == null)
{
return;
}
HandsPoseSystem[] array = Object.FindObjectsOfType<HandsPoseSystem>();
foreach (HandsPoseSystem val in array)
{
if ((Object)(object)val != (Object)null && LockedHpiField.GetValue(val) == oldHpi)
{
LockedHpiField.SetValue(val, newHpi);
}
}
}
private string ApplyLive(PoseSet set, bool save)
{
string text = SetKey(set);
if (text == "")
{
throw new Exception("pose set needs a name or an item ID");
}
Unregister(_byItemId, text);
Unregister(_byName, text);
Unregister(_magById, text);
Unregister(_magByType, text);
Register(set);
int num = 0;
int num2 = 0;
int num3 = 0;
Injected[] array = _injected.ToArray();
foreach (Injected injected in array)
{
if ((Object)(object)injected.hpi == (Object)null || (Object)(object)injected.parent == (Object)null)
{
_injected.Remove(injected);
}
else
{
if (SetKey(injected.set) != text && !SharesKeys(injected.set, set))
{
continue;
}
PoseData[] array2 = PosesFor(set, injected.target);
bool hasTrigger = injected.target == "gun" && set.hasTrigger;
if (!HasPoses(array2))
{
Object.Destroy((Object)(object)((Component)injected.hpi).gameObject);
_injected.Remove(injected);
num3++;
continue;
}
((Component)injected.hpi).transform.SetSiblingIndex(0);
if (UpdateInPlace(injected.hpi, array2, hasTrigger))
{
num++;
}
else
{
HandPoseItem hpi = injected.hpi;
injected.hpi = InjectHpi(injected.parent, array2, hasTrigger, (injected.target == "gun" && set.useGrabPos) ? set.grabPos : null);
Relock(hpi, injected.hpi);
Object.DestroyImmediate((Object)(object)((Component)hpi).gameObject);
num2++;
}
injected.set = set;
}
}
_checked.Clear();
_similarCache.Clear();
string text2 = "";
if (save)
{
text2 = Path.Combine(_dir, SafeFileName(text) + ".json");
File.WriteAllText(text2, JsonUtility.ToJson((object)set, true));
}
((BaseUnityPlugin)this).Logger.LogInfo((object)("Live update '" + text + "': " + num + " updated, " + num2 + " rebuilt, " + num3 + " removed" + (save ? (", saved to " + text2) : "")));
return "{\"ok\":true,\"key\":\"" + Esc(text) + "\",\"updated\":" + num + ",\"rebuilt\":" + num2 + ",\"removed\":" + num3 + ",\"saved\":\"" + Esc(text2) + "\"}";
}
private static bool SharesKeys(PoseSet a, PoseSet b)
{
Func<string[], string[], bool> func = delegate(string[] x, string[] y)
{
if (x == null || y == null)
{
return false;
}
foreach (string text in x)
{
foreach (string text2 in y)
{
if (!string.IsNullOrEmpty(text) && string.Equals(text.Trim(), (text2 ?? "").Trim(), StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
}
return false;
};
if (a == null || b == null)
{
return false;
}
if (a.match != null && b.match != null && (func(a.match.itemIds, b.match.itemIds) || func(a.match.objectNames, b.match.objectNames)))
{
return true;
}
if (a.magazine != null && b.magazine != null)
{
if (!func(a.magazine.itemIds, b.magazine.itemIds))
{
return func(a.magazine.magazineTypes, b.magazine.magazineTypes);
}
return true;
}
return false;
}
private static string Esc(string s)
{
return (s ?? "").Replace("\\", "\\\\").Replace("\"", "\\\"");
}
private void Reload()
{
HandPoseItem[] array = Object.FindObjectsOfType<HandPoseItem>();
foreach (HandPoseItem val in array)
{
if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name == "GT3PoseKit_HandPoseItem")
{
Object.Destroy((Object)(object)((Component)val).gameObject);
}
}
_injected.Clear();
_checked.Clear();
_similarCache.Clear();
LoadPoseSets();
Notify("Poses reloaded (" + (_byItemId.Count + _byName.Count) + " gun keys, " + (_magById.Count + _magByType.Count) + " magazine keys)");
}
private PoseSet FindSet(FVRPhysicalObject phys)
{
string text = (((Object)(object)phys.ObjectWrapper != (Object)null) ? phys.ObjectWrapper.ItemID : null);
if (!string.IsNullOrEmpty(text) && _byItemId.TryGetValue(text, out var value))
{
return value;
}
if (_byName.TryGetValue(((Object)((Component)phys).gameObject).name, out value))
{
return value;
}
return AutoCopy(phys, text);
}
private static string DisplayNameOf(string itemId)
{
if (IM.OD == null || !IM.OD.TryGetValue(itemId, out var value) || !((Object)(object)value != (Object)null))
{
return null;
}
return value.DisplayName;
}
private PoseSet AutoCopy(FVRPhysicalObject phys, string id)
{
if (!_autoCopy.Value || string.IsNullOrEmpty(id) || phys is FVRFireArmMagazine || !(phys is FVRFireArm))
{
return null;
}
if (_similarCache.TryGetValue(id, out var value))
{
return value;
}
string text = (((Object)(object)phys.ObjectWrapper != (Object)null) ? phys.ObjectWrapper.DisplayName : null);
PoseSet poseSet = null;
string text2 = null;
float num = _autoCopyThreshold.Value;
foreach (KeyValuePair<string, PoseSet> item in _byItemId)
{
if (item.Value != null && !item.Value.noAutoCopy && (HasPoses(item.Value.poses) || (item.Value.parts != null && item.Value.parts.Length != 0)))
{
float num2 = Similarity.Score(id, item.Key);
string text3 = DisplayNameOf(item.Key);
if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(text3))
{
num2 = Math.Max(num2, Similarity.Score(text, text3));
}
if (num2 >= num)
{
num = num2;
poseSet = item.Value;
text2 = item.Key;
}
}
}
_similarCache[id] = poseSet;
if (poseSet != null)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("Auto copy: " + id + " uses the poses of " + text2 + " ('" + poseSet.name + "', similarity " + num.ToString("0.00") + ")"));
}
return poseSet;
}
private PoseSet FindMagazineSet(FVRFireArmMagazine mag)
{
string text = (((Object)(object)((FVRPhysicalObject)mag).ObjectWrapper != (Object)null) ? ((FVRPhysicalObject)mag).ObjectWrapper.ItemID : null);
if (!string.IsNullOrEmpty(text) && _magById.TryGetValue(text, out var value))
{
return value;
}
if (_magByType.TryGetValue(((object)Unsafe.As<FireArmMagazineType, FireArmMagazineType>(ref mag.MagazineType)/*cast due to .constrained prefix*/).ToString(), out value))
{
return value;
}
return null;
}
private static Transform HpiParent(FVRInteractiveObject io)
{
if (!((Object)(object)io.GameObject != (Object)null))
{
return ((Component)io).transform;
}
return io.GameObject.transform;
}
private static bool HasDirectHpi(Transform t)
{
for (int i = 0; i < t.childCount; i++)
{
if ((Object)(object)((Component)t.GetChild(i)).GetComponent<HandPoseItem>() != (Object)null)
{
return true;
}
}
return false;
}
private static string RelPath(Transform root, Transform t)
{
List<string> list = new List<string>();
while ((Object)(object)t != (Object)null && (Object)(object)t != (Object)(object)root)
{
list.Insert(0, ((Object)t).name);
t = t.parent;
}
return string.Join("/", list.ToArray());
}
private static bool IsPart(FVRInteractiveObject io, Transform root)
{
if ((Object)(object)io != (Object)null && (Object)(object)((Component)io).transform != (Object)(object)root && !(io is FVRPhysicalObject) && !(io is FVRAlternateGrip))
{
return (Object)(object)((Component)io).GetComponentInParent<HandPoseItem>() == (Object)null;
}
return false;
}
private static FVRInteractiveObject FindPart(Transform root, PartPoses part)
{
FVRInteractiveObject[] componentsInChildren = ((Component)root).GetComponentsInChildren<FVRInteractiveObject>(true);
FVRInteractiveObject[] array = componentsInChildren;
foreach (FVRInteractiveObject val in array)
{
if (IsPart(val, root) && RelPath(root, ((Component)val).transform) == part.path)
{
return val;
}
}
if (!string.IsNullOrEmpty(part.type))
{
array = componentsInChildren;
foreach (FVRInteractiveObject val2 in array)
{
if (IsPart(val2, root) && ((object)val2).GetType().Name == part.type)
{
return val2;
}
}
}
return null;
}
private void TryInject(FVRPhysicalObject phys)
{
int instanceID = ((Object)phys).GetInstanceID();
if (_checked.Contains(instanceID))
{
return;
}
_checked.Add(instanceID);
PoseSet poseSet = FindSet(phys);
if (poseSet != null)
{
try
{
InjectGun(phys, poseSet);
return;
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)("Could not apply '" + poseSet.name + "': " + ex));
return;
}
}
FVRFireArmMagazine val = (FVRFireArmMagazine)(object)((phys is FVRFireArmMagazine) ? phys : null);
if (!((Object)(object)val != (Object)null))
{
return;
}
poseSet = FindMagazineSet(val);
if (poseSet == null)
{
return;
}
Transform val2 = HpiParent((FVRInteractiveObject)(object)val);
if (HasDirectHpi(val2))
{
return;
}
try
{
Track(InjectHpi(val2, poseSet.magazine.poses, hasTrigger: false, null), val2, poseSet, "mag");
((BaseUnityPlugin)this).Logger.LogInfo((object)("Applied magazine poses from '" + poseSet.name + "' to " + ((Object)((Component)val).gameObject).name));
}
catch (Exception ex2)
{
((BaseUnityPlugin)this).Logger.LogError((object)("Could not apply magazine poses from '" + poseSet.name + "': " + ex2));
}
}
private void InjectGun(FVRPhysicalObject phys, PoseSet set)
{
Transform transform = ((Component)phys).transform;
Transform val = HpiParent((FVRInteractiveObject)(object)phys);
if (HasPoses(set.poses) && !HasDirectHpi(val))
{
Track(InjectHpi(val, set.poses, set.hasTrigger, set.useGrabPos ? set.grabPos : null), val, set, "gun");
((BaseUnityPlugin)this).Logger.LogInfo((object)("Applied pose set '" + set.name + "' to " + ((Object)((Component)phys).gameObject).name));
}
PartPoses[] array = set.parts ?? new PartPoses[0];
foreach (PartPoses partPoses in array)
{
if (partPoses == null || !HasPoses(partPoses.poses))
{
continue;
}
FVRInteractiveObject val2 = FindPart(transform, partPoses);
if ((Object)(object)val2 == (Object)null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("'" + set.name + "': part '" + partPoses.path + "' not found on " + ((Object)((Component)phys).gameObject).name));
}
else
{
Transform val3 = HpiParent(val2);
if (!HasDirectHpi(val3))
{
Track(InjectHpi(val3, partPoses.poses, hasTrigger: false, null), val3, set, "part:" + partPoses.path);
((BaseUnityPlugin)this).Logger.LogInfo((object)("Applied '" + (partPoses.name ?? partPoses.path) + "' poses to " + ((Object)((Component)phys).gameObject).name));
}
}
}
}
private void Track(HandPoseItem hpi, Transform parent, PoseSet set, string target)
{
_injected.Add(new Injected
{
hpi = hpi,
parent = parent,
set = set,
target = target
});
}
private HandPoseItem InjectHpi(Transform parent, PoseData[] data, bool hasTrigger, Xf grabPos)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0258: Unknown result type (might be due to invalid IL or missing references)
//IL_025f: Expected O, but got Unknown
//IL_027b: Unknown result type (might be due to invalid IL or missing references)
//IL_028e: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("GT3PoseKit_HandPoseItem");
val.SetActive(false);
val.transform.SetParent(parent, false);
val.transform.SetSiblingIndex(0);
val.transform.localPosition = Vector3.zero;
val.transform.localRotation = Quaternion.identity;
Vector3 lossyScale = parent.lossyScale;
val.transform.localScale = new Vector3(SafeInv(lossyScale.x), SafeInv(lossyScale.y), SafeInv(lossyScale.z));
Dictionary<string, PoseData> dictionary = new Dictionary<string, PoseData>();
PoseData[] array = data ?? new PoseData[0];
foreach (PoseData poseData in array)
{
if (poseData != null && !string.IsNullOrEmpty(poseData.slot) && poseData.joints != null && poseData.joints.Length != 0)
{
dictionary[poseData.slot] = poseData;
}
}
HandPoseItem val2 = val.AddComponent<HandPoseItem>();
val2.IdleL = Build(val.transform, "IdleL", dictionary);
val2.IdleR = Build(val.transform, "IdleR", dictionary);
val2.ForeL = Build(val.transform, "ForeL", dictionary);
val2.ForeR = Build(val.transform, "ForeR", dictionary);
val2.FireStartL = Build(val.transform, "FireStartL", dictionary);
val2.FireStartR = Build(val.transform, "FireStartR", dictionary);
val2.FireEndL = Build(val.transform, "FireEndL", dictionary);
val2.FireEndR = Build(val.transform, "FireEndR", dictionary);
val2.CurPoseL = (((Object)(object)val2.IdleL != (Object)null) ? Build(val.transform, "CurPoseL", dictionary["IdleL"]) : null);
val2.CurPoseR = (((Object)(object)val2.IdleR != (Object)null) ? Build(val.transform, "CurPoseR", dictionary["IdleR"]) : null);
val2.hasTrigger = hasTrigger && (((Object)(object)val2.FireStartL != (Object)null && (Object)(object)val2.FireEndL != (Object)null) || ((Object)(object)val2.FireStartR != (Object)null && (Object)(object)val2.FireEndR != (Object)null));
if (grabPos != null)
{
GameObject val3 = new GameObject("GrabPos");
val3.transform.SetParent(val.transform, false);
val3.transform.localPosition = grabPos.Pos;
val3.transform.localRotation = grabPos.Rot;
val2.grabpos = val3;
}
val.SetActive(true);
return val2;
}
private static HandPose Build(Transform parent, string slot, Dictionary<string, PoseData> poses)
{
if (!poses.TryGetValue(slot, out var value))
{
return null;
}
return Build(parent, slot, value);
}
private static HandPose Build(Transform parent, string name, PoseData pd)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Expected O, but got Unknown
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject(name);
val.transform.SetParent(parent, false);
HandPose val2 = val.AddComponent<HandPose>();
GameObject[] array = (GameObject[])(object)new GameObject[pd.joints.Length];
for (int i = 0; i < array.Length; i++)
{
GameObject val3 = new GameObject("j" + i);
val3.transform.SetParent(val.transform, false);
val3.transform.localPosition = pd.joints[i].Pos;
val3.transform.localRotation = pd.joints[i].Rot;
array[i] = val3;
}
val2.Fingers = array;
return val2;
}
private static float SafeInv(float v)
{
if (!(Mathf.Abs(v) < 1E-06f))
{
return 1f / v;
}
return 1f;
}
private static FVRPhysicalObject RootObject(FVRInteractiveObject io)
{
if ((Object)(object)io == (Object)null)
{
return null;
}
FVRAlternateGrip val = (FVRAlternateGrip)(object)((io is FVRAlternateGrip) ? io : null);
if ((Object)(object)val != (Object)null && (Object)(object)val.PrimaryObject != (Object)null)
{
return val.PrimaryObject;
}
FVRPhysicalObject val2 = (FVRPhysicalObject)(object)((io is FVRPhysicalObject) ? io : null);
if ((Object)(object)val2 != (Object)null)
{
return val2;
}
return ((Component)io).GetComponentInParent<FVRPhysicalObject>();
}
private static HandsPoseSystem FindSystem(bool left)
{
HandsPoseSystem[] array = Object.FindObjectsOfType<HandsPoseSystem>();
foreach (HandsPoseSystem val in array)
{
if ((Object)(object)val != (Object)null && val.isLeft == left)
{
return val;
}
}
return null;
}
private static FVRViveHand FindHand(bool left)
{
FVRMovementManager currentMovementManager = GM.CurrentMovementManager;
if ((Object)(object)currentMovementManager == (Object)null || currentMovementManager.Hands == null)
{
return null;
}
FVRViveHand[] hands = currentMovementManager.Hands;
foreach (FVRViveHand val in hands)
{
if ((Object)(object)val != (Object)null && val.IsThisTheRightHand != left)
{
return val;
}
}
return null;
}
private static Xf ToGunSpace(Transform gun, Transform t)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
Quaternion val = Quaternion.Inverse(gun.rotation);
return Xf.From(val * (t.position - gun.position), val * t.rotation);
}
private static Transform CommonRoot(GameObject[] joints)
{
List<Transform> list = null;
GameObject[] array = joints;
foreach (GameObject val in array)
{
if ((Object)(object)val == (Object)null)
{
continue;
}
List<Transform> list2 = new List<Transform>();
Transform val2 = val.transform;
while ((Object)(object)val2 != (Object)null)
{
list2.Insert(0, val2);
val2 = val2.parent;
}
if (list == null)
{
list = list2;
continue;
}
int j;
for (j = 0; j < list.Count && j < list2.Count && (Object)(object)list[j] == (Object)(object)list2[j]; j++)
{
}
list.RemoveRange(j, list.Count - j);
}
if (list == null || list.Count == 0)
{
return null;
}
Transform val3 = list[list.Count - 1];
array = joints;
foreach (GameObject val4 in array)
{
if ((Object)(object)val4 != (Object)null && (Object)(object)val4.transform == (Object)(object)val3)
{
return val3.parent ?? val3;
}
}
return val3;
}
private static RigHand BuildRig(bool left, GameObject[] src)
{
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_0129: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0108: Unknown result type (might be due to invalid IL or missing references)
Transform val = CommonRoot(src);
Dictionary<Transform, int> dictionary = new Dictionary<Transform, int>();
for (int i = 0; i < src.Length; i++)
{
if ((Object)(object)src[i] != (Object)null)
{
dictionary[src[i].transform] = i;
}
}
RigJoint[] array = new RigJoint[src.Length];
for (int j = 0; j < src.Length; j++)
{
RigJoint obj = new RigJoint
{
name = (((Object)(object)src[j] != (Object)null) ? ((Object)src[j]).name : ("missing" + j)),
parent = -1,
local = new Xf()
};
RigJoint rigJoint = (array[j] = obj);
if ((Object)(object)src[j] == (Object)null)
{
continue;
}
Transform transform = src[j].transform;
Transform val2 = val;
Transform parent = transform.parent;
while ((Object)(object)parent != (Object)null && (Object)(object)parent != (Object)(object)val)
{
if (dictionary.TryGetValue(parent, out var value))
{
rigJoint.parent = value;
val2 = parent;
break;
}
parent = parent.parent;
}
if ((Object)(object)val2 == (Object)null)
{
rigJoint.local = Xf.From(transform.position, transform.rotation);
continue;
}
Quaternion val3 = Quaternion.Inverse(val2.rotation);
rigJoint.local = Xf.From(val3 * (transform.position - val2.position), val3 * transform.rotation);
}
return new RigHand
{
side = (left ? "L" : "R"),
rootName = (((Object)(object)val != (Object)null) ? ((Object)val).name : ""),
joints = array
};
}
private static GameObject[] PoseSource(HandsPoseSystem sys, out bool fromPhysics)
{
fromPhysics = (Object)(object)sys.HandPhys != (Object)null && sys.HandPhys.activeInHierarchy && sys.realfingers != null && sys.Fingers != null && sys.realfingers.Length == sys.Fingers.Length;
if (!fromPhysics)
{
return sys.Fingers;
}
return sys.realfingers;
}
private RigDump BuildRigDump(out string error)
{
error = null;
HandsPoseSystem val = FindSystem(left: true);
HandsPoseSystem val2 = FindSystem(left: false);
if ((Object)(object)val == (Object)null && (Object)(object)val2 == (Object)null)
{
error = "Spawn the GlovesTan3 gloves first";
return null;
}
bool fromPhysics;
return new RigDump
{
left = (((Object)(object)val != (Object)null) ? BuildRig(left: true, PoseSource(val, out fromPhysics)) : null),
right = (((Object)(object)val2 != (Object)null) ? BuildRig(left: false, PoseSource(val2, out fromPhysics)) : null)
};
}
private void DumpRig()
{
string error;
RigDump rigDump = BuildRigDump(out error);
if (rigDump == null)
{
Notify(error);
return;
}
string text = Path.Combine(_dir, "rig.json");
File.WriteAllText(text, JsonUtility.ToJson((object)rigDump, true));
Notify("Rig written: " + text);
GloveDump gloveDump = BuildGloveDump(out error);
if (gloveDump != null)
{
string text2 = Path.Combine(_dir, "glove.json");
File.WriteAllText(text2, JsonUtility.ToJson((object)gloveDump));
Notify("Glove model written: " + text2);
}
else
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Glove model not exported: " + error));
}
}
private GloveDump BuildGloveDump(out string error)
{
error = null;
HandsPoseSystem val = FindSystem(left: true);
HandsPoseSystem val2 = FindSystem(left: false);
if ((Object)(object)val == (Object)null && (Object)(object)val2 == (Object)null)
{
error = "Spawn the GlovesTan3 gloves first";
return null;
}
string error2 = null;
string error3 = null;
GloveDump gloveDump = new GloveDump
{
left = (((Object)(object)val != (Object)null) ? GloveExport.Build(val, left: true, _gloveTexSize.Value, out error2) : null),
right = (((Object)(object)val2 != (Object)null) ? GloveExport.Build(val2, left: false, _gloveTexSize.Value, out error3) : null)
};
if (gloveDump.left == null && gloveDump.right == null)
{
error = error3 ?? error2 ?? "No glove mesh found";
return null;
}
return gloveDump;
}
private CaptureData BuildCapture(bool left, out string error)
{
error = null;
HandsPoseSystem val = FindSystem(left);
if ((Object)(object)val == (Object)null)
{
error = "Spawn the GlovesTan3 gloves first";
return null;
}
FVRViveHand val2 = FindHand(left);
FVRInteractiveObject val3 = (((Object)(object)val2 != (Object)null) ? val2.CurrentInteractable : null);
FVRPhysicalObject val4 = RootObject(val3);
if ((Object)(object)val4 == (Object)null)
{
error = "Hold an object with the " + (left ? "left" : "right") + " hand to capture";
return null;
}
bool fromPhysics;
GameObject[] array = PoseSource(val, out fromPhysics);
Transform transform = ((Component)val4).transform;
Transform val5 = CommonRoot(array);
int readable;
int boxed;
CaptureData captureData = new CaptureData
{
itemId = (((Object)(object)val4.ObjectWrapper != (Object)null) ? val4.ObjectWrapper.ItemID : ""),
objectName = ((Object)((Component)val4).gameObject).name,
side = (left ? "L" : "R"),
onForegrip = (val3 is FVRAlternateGrip),
fromPhysics = fromPhysics,
handRoot = (((Object)(object)val5 != (Object)null) ? ToGunSpace(transform, val5) : new Xf()),
joints = new Xf[array.Length],
rig = BuildRig(left, array),
geo = BuildGeo(transform, out readable, out boxed)
};
for (int i = 0; i < array.Length; i++)
{
captureData.joints[i] = (((Object)(object)array[i] != (Object)null) ? ToGunSpace(transform, array[i].transform) : new Xf());
}
if (IsPart(val3, transform))
{
captureData.partPath = RelPath(transform, ((Component)val3).transform);
captureData.partType = ((object)val3).GetType().Name;
captureData.partXf = ToGunSpace(transform, HpiParent(val3));
}
FVRFireArmMagazine val6 = (FVRFireArmMagazine)(object)((val4 is FVRFireArmMagazine) ? val4 : null);
if ((Object)(object)val6 != (Object)null)
{
captureData.isMagazine = true;
captureData.magazineType = ((object)Unsafe.As<FireArmMagazineType, FireArmMagazineType>(ref val6.MagazineType)/*cast due to .constrained prefix*/).ToString();
}
return captureData;
}
private void Capture(bool left)
{
string error;
CaptureData captureData = BuildCapture(left, out error);
if (captureData == null)
{
Notify(error);
return;
}
string text = SafeFileName(string.IsNullOrEmpty(captureData.itemId) ? captureData.objectName : captureData.itemId);
string text2 = Path.Combine(Path.Combine(_dir, "captures"), text + "_" + captureData.side + (captureData.onForegrip ? "_fore" : "") + "_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".json");
File.WriteAllText(text2, JsonUtility.ToJson((object)captureData));
Notify("Captured " + captureData.side + " on " + text);
((BaseUnityPlugin)this).Logger.LogInfo((object)("Capture written: " + text2));
}
private static string SafeFileName(string s)
{
if (string.IsNullOrEmpty(s))
{
s = "object";
}
char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
foreach (char oldChar in invalidFileNameChars)
{
s = s.Replace(oldChar, '_');
}
return s;
}
private ModelData BuildModel(string itemId, string name, string category, Transform root)
{
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
int readable;
int boxed;
GunGeo geo = BuildGeo(root, out readable, out boxed);
ModelData modelData = new ModelData
{
itemId = itemId,
name = name,
category = category,
readableMeshes = readable,
boxedMeshes = boxed,
geo = geo
};
FVRFireArmMagazine component = ((Component)root).GetComponent<FVRFireArmMagazine>();
FVRFireArm component2 = ((Component)root).GetComponent<FVRFireArm>();
if ((Object)(object)component != (Object)null)
{
modelData.isMagazine = true;
modelData.magazineType = ((object)Unsafe.As<FireArmMagazineType, FireArmMagazineType>(ref component.MagazineType)/*cast due to .constrained prefix*/).ToString();
}
else if ((Object)(object)component2 != (Object)null)
{
modelData.magazineType = ((object)Unsafe.As<FireArmMagazineType, FireArmMagazineType>(ref component2.MagazineType)/*cast due to .constrained prefix*/).ToString();
List<string> list = new List<string>();
if (IM.CompatMags != null && IM.CompatMags.TryGetValue(component2.MagazineType, out var value) && value != null)
{
foreach (FVRObject item in value)
{
if ((Object)(object)item != (Object)null && !string.IsNullOrEmpty(item.ItemID))
{
list.Add(item.ItemID);
}
}
}
modelData.compatibleMags = list.ToArray();
}
return modelData;
}
private void ExportHeldModel()
{
FVRMovementManager currentMovementManager = GM.CurrentMovementManager;
FVRPhysicalObject val = null;
if ((Object)(object)currentMovementManager != (Object)null && currentMovementManager.Hands != null)
{
FVRViveHand[] hands = currentMovementManager.Hands;
foreach (FVRViveHand val2 in hands)
{
if ((Object)(object)val2 != (Object)null && (Object)(object)val == (Object)null)
{
val = RootObject(val2.CurrentInteractable);
}
}
}
if ((Object)(object)val == (Object)null)
{
Notify("Hold an object to export its model");
return;
}
FVRObject objectWrapper = val.ObjectWrapper;
string text = (((Object)(object)objectWrapper != (Object)null) ? objectWrapper.ItemID : ((Object)((Component)val).gameObject).name);
ModelData modelData = BuildModel(text, ((Object)(object)objectWrapper != (Object)null) ? objectWrapper.DisplayName : ((Object)((Component)val).gameObject).name, ((Object)(object)objectWrapper != (Object)null) ? ((object)Unsafe.As<ObjectCategory, ObjectCategory>(ref objectWrapper.Category)/*cast due to .constrained prefix*/).ToString() : "", ((Component)val).transform);
string text2 = Path.Combine(Path.Combine(_dir, "models"), SafeFileName(text) + ".json");
File.WriteAllText(text2, JsonUtility.ToJson((object)modelData));
Notify("Model written: " + text2 + " (" + modelData.readableMeshes + " meshes, " + modelData.boxedMeshes + " boxed)");
}
private void HandleRequest(string method, string path, Dictionary<string, string> q, string body, out int status, out string json)
{
status = 200;
string value;
if (method == "POST")
{
if (path != "/poses")
{
status = 404;
json = ModelServer.Err("Unknown endpoint " + path);
return;
}
if (!_allowLive.Value)
{
status = 403;
json = ModelServer.Err("Live import is turned off in gt3posekit.loader.cfg");
return;
}
PoseSet poseSet;
try
{
poseSet = JsonUtility.FromJson<PoseSet>(body ?? "");
}
catch (Exception ex)
{
status = 400;
json = ModelServer.Err("Not valid JSON: " + ex.Message);
return;
}
if (poseSet == null || poseSet.format != "gt3poses")
{
status = 400;
json = ModelServer.Err("Expected a gt3poses pose set");
return;
}
bool save = q.TryGetValue("save", out value) && (value == "1" || value == "true");
try
{
json = ApplyLive(poseSet, save);
return;
}
catch (Exception ex2)
{
status = 400;
json = ModelServer.Err(ex2.Message);
return;
}
}
string error;
switch (path)
{
case "/status":
json = JsonUtility.ToJson((object)new BridgeStatus
{
version = "1.0.0",
items = ((IM.OD != null) ? IM.OD.Count : 0),
gloves = ((Object)(object)FindSystem(left: true) != (Object)null || (Object)(object)FindSystem(left: false) != (Object)null),
poseFolder = _dir
});
break;
case "/posesets":
{
List<LocalSet> list2 = new List<LocalSet>();
string[] files = Directory.GetFiles(_dir, "*.json");
foreach (string path2 in files)
{
string fileName = Path.GetFileName(path2);
if (fileName.Equals("rig.json", StringComparison.OrdinalIgnoreCase) || fileName.Equals("glove.json", StringComparison.OrdinalIgnoreCase))
{
continue;
}
try
{
PoseSet poseSet2 = JsonUtility.FromJson<PoseSet>(File.ReadAllText(path2));
if (poseSet2 != null && !(poseSet2.format != "gt3poses"))
{
list2.Add(new LocalSet
{
key = SetKey(poseSet2),
file = fileName,
itemIds = ((poseSet2.match != null && poseSet2.match.itemIds != null) ? poseSet2.match.itemIds : new string[0]),
modified = File.GetLastWriteTime(path2).ToString("yyyy-MM-ddTHH:mm:ss")
});
}
}
catch
{
}
}
json = JsonUtility.ToJson((object)new LocalSetList
{
sets = list2.ToArray()
});
break;
}
case "/items":
{
List<ItemInfo> list = new List<ItemInfo>();
if (IM.OD != null)
{
foreach (KeyValuePair<string, FVRObject> item in IM.OD)
{
FVRObject value2 = item.Value;
if (!((Object)(object)value2 == (Object)null))
{
list.Add(new ItemInfo
{
id = item.Key,
name = value2.DisplayName,
cat = ((object)Unsafe.As<ObjectCategory, ObjectCategory>(ref value2.Category)/*cast due to .constrained prefix*/).ToString(),
mod = value2.IsModContent
});
}
}
}
list.Sort((ItemInfo a, ItemInfo b) => string.Compare(a.name ?? a.id, b.name ?? b.id, StringComparison.OrdinalIgnoreCase));
json = JsonUtility.ToJson((object)new ItemList
{
items = list.ToArray()
});
break;
}
case "/model":
{
if (!q.TryGetValue("id", out value) || IM.OD == null || !IM.OD.TryGetValue(value, out var value3) || (Object)(object)value3 == (Object)null)
{
status = 404;
json = ModelServer.Err("No item with ID '" + value + "'");
break;
}
GameObject gameObject;
try
{
gameObject = ((AnvilAsset)value3).GetGameObject();
}
catch (Exception ex3)
{
status = 500;
json = ModelServer.Err("Could not load " + value + ": " + ex3.Message);
break;
}
if ((Object)(object)gameObject == (Object)null)
{
status = 404;
json = ModelServer.Err(value + " has no prefab");
}
else
{
json = JsonUtility.ToJson((object)BuildModel(value3.ItemID, value3.DisplayName, ((object)Unsafe.As<ObjectCategory, ObjectCategory>(ref value3.Category)/*cast due to .constrained prefix*/).ToString(), gameObject.transform));
}
break;
}
case "/rig":
{
RigDump rigDump = BuildRigDump(out error);
if (rigDump == null)
{
status = 409;
json = ModelServer.Err(error);
}
else
{
json = JsonUtility.ToJson((object)rigDump);
}
break;
}
case "/glove":
{
GloveDump gloveDump = BuildGloveDump(out error);
if (gloveDump == null)
{
status = 409;
json = ModelServer.Err(error);
}
else
{
json = JsonUtility.ToJson((object)gloveDump);
}
break;
}
case "/capture":
{
bool left = q.TryGetValue("side", out value) && value.ToUpperInvariant().StartsWith("L");
CaptureData captureData = BuildCapture(left, out error);
if (captureData == null)
{
status = 409;
json = ModelServer.Err(error);
}
else
{
json = JsonUtility.ToJson((object)captureData);
}
break;
}
default:
status = 404;
json = ModelServer.Err("Unknown endpoint " + path);
break;
}
}
private static bool ActiveUnder(Transform t, Transform root)
{
while ((Object)(object)t != (Object)null)
{
if (!((Component)t).gameObject.activeSelf)
{
return false;
}
if ((Object)(object)t == (Object)(object)root)
{
return true;
}
t = t.parent;
}
return true;
}
private GunGeo BuildGeo(Transform gun, out int readable, out int boxed)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0513: Unknown result type (might be due to invalid IL or missing references)
//IL_0518: Unknown result type (might be due to invalid IL or missing references)
//IL_055f: Unknown result type (might be due to invalid IL or missing references)
//IL_0573: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_017b: Unknown result type (might be due to invalid IL or missing references)
//IL_047d: Unknown result type (might be due to invalid IL or missing references)
//IL_0484: Unknown result type (might be due to invalid IL or missing references)
//IL_0489: Unknown result type (might be due to invalid IL or missing references)
//IL_0494: Unknown result type (might be due to invalid IL or missing references)
//IL_0499: Unknown result type (might be due to invalid IL or missing references)
//IL_049e: Unknown result type (might be due to invalid IL or missing references)
//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
//IL_04bb: Unknown result type (might be due to invalid IL or missing references)
//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
//IL_0244: Unknown result type (might be due to invalid IL or missing references)
//IL_0249: Unknown result type (might be due to invalid IL or missing references)
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_0272: Unknown result type (might be due to invalid IL or missing references)
readable = 0;
boxed = 0;
List<GeoPrim> list = new List<GeoPrim>();
List<GeoMesh> list2 = new List<GeoMesh>();
List<Marker> markers = new List<Marker>();
Quaternion val = Quaternion.Inverse(gun.rotation);
Vector3 gs = gun.lossyScale;
Func<Transform, bool> func = (Transform t) => (Object)(object)((Component)t).GetComponentInParent<HandPoseItem>() != (Object)null;
Func<Transform, float[]> func2 = delegate(Transform t)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
Vector3 lossyScale = t.lossyScale;
return new float[3]
{
lossyScale.x * SafeInv(gs.x),
lossyScale.y * SafeInv(gs.y),
lossyScale.z * SafeInv(gs.z)
};
};
Func<Vector3, float[]> func3 = (Vector3 v) => new float[3] { v.x, v.y, v.z };
Collider[] componentsInChildren = ((Component)gun).GetComponentsInChildren<Collider>(true);
foreach (Collider val2 in componentsInChildren)
{
if ((Object)(object)val2 == (Object)null || func(((Component)val2).transform))
{
continue;
}
GeoPrim geoPrim = new GeoPrim
{
name = ((Object)val2).name,
xf = ToGunSpace(gun, ((Component)val2).transform),
scale = func2(((Component)val2).transform),
trigger = val2.isTrigger
};
BoxCollider val3 = (BoxCollider)(object)((val2 is BoxCollider) ? val2 : null);
SphereCollider val4 = (SphereCollider)(object)((val2 is SphereCollider) ? val2 : null);
CapsuleCollider val5 = (CapsuleCollider)(object)((val2 is CapsuleCollider) ? val2 : null);
MeshCollider val6 = (MeshCollider)(object)((val2 is MeshCollider) ? val2 : null);
if ((Object)(object)val3 != (Object)null)
{
geoPrim.kind = "box";
geoPrim.center = func3(val3.center);
geoPrim.size = func3(val3.size);
}
else if ((Object)(object)val4 != (Object)null)
{
geoPrim.kind = "sphere";
geoPrim.center = func3(val4.center);
geoPrim.radius = val4.radius;
}
else if ((Object)(object)val5 != (Object)null)
{
geoPrim.kind = "capsule";
geoPrim.center = func3(val5.center);
geoPrim.radius = val5.radius;
geoPrim.height = val5.height;
geoPrim.dir = val5.direction;
}
else
{
if (!((Object)(object)val6 != (Object)null) || !((Object)(object)val6.sharedMesh != (Object)null))
{
continue;
}
Bounds bounds = val6.sharedMesh.bounds;
geoPrim.kind = "bounds";
geoPrim.center = func3(((Bounds)(ref bounds)).center);
geoPrim.size = func3(((Bounds)(ref bounds)).size);
}
list.Add(geoPrim);
}
if (_exportMeshes.Value)
{
int num2 = _maxMeshVerts.Value;
List<KeyValuePair<Transform, Mesh>> list3 = new List<KeyValuePair<Transform, Mesh>>();
MeshFilter[] componentsInChildren2 = ((Component)gun).GetComponentsInChildren<MeshFilter>(true);
foreach (MeshFilter val7 in componentsInChildren2)
{
if (!((Object)(object)val7 == (Object)null) && !((Object)(object)val7.sharedMesh == (Object)null) && !func(((Component)val7).transform) && ActiveUnder(((Component)val7).transform, gun))
{
MeshRenderer component = ((Component)val7).GetComponent<MeshRenderer>();
if (!((Object)(object)component == (Object)null) && ((Renderer)component).enabled)
{
list3.Add(new KeyValuePair<Transform, Mesh>(((Component)val7).transform, val7.sharedMesh));
}
}
}
SkinnedMeshRenderer[] componentsInChildren3 = ((Component)gun).GetComponentsInChildren<SkinnedMeshRenderer>(true);
foreach (SkinnedMeshRenderer val8 in componentsInChildren3)
{
if (!((Object)(object)val8 == (Object)null) && !((Object)(object)val8.sharedMesh == (Object)null) && ((Renderer)val8).enabled && !func(((Component)val8).transform) && ActiveUnder(((Component)val8).transform, gun))
{
list3.Add(new KeyValuePair<Transform, Mesh>(((Component)val8).transform, val8.sharedMesh));
}
}
foreach (KeyValuePair<Transform, Mesh> item in list3)
{
Transform key = item.Key;
Mesh value = item.Value;
Vector3[] array = null;
int[] array2 = null;
if (value.isReadable && value.vertexCount <= num2)
{
try
{
array = value.vertices;
array2 = value.triangles;
}
catch
{
array = null;
}
}
if (array != null && array.Length != 0 && array2 != null && array2.Length != 0)
{
num2 -= array.Length;
float[] array3 = new float[array.Length * 3];
for (int num3 = 0; num3 < array.Length; num3++)
{
Vector3 val9 = val * (key.TransformPoint(array[num3]) - gun.position);
array3[num3 * 3] = val9.x;
array3[num3 * 3 + 1] = val9.y;
array3[num3 * 3 + 2] = val9.z;
}
list2.Add(new GeoMesh
{
name = ((Object)key).name,
v = array3,
t = array2
});
readable++;
}
else
{
Bounds bounds2 = value.bounds;
list.Add(new GeoPrim
{
kind = "meshbox",
name = ((Object)key).name,
xf = ToGunSpace(gun, key),
scale = func2(key),
center = func3(((Bounds)(ref bounds2)).center),
size = func3(((Bounds)(ref bounds2)).size)
});
boxed++;
}
}
}
HashSet<Transform> seen = new HashSet<Transform>();
Action<string, Transform> action = delegate(string n, Transform t)
{
if (!((Object)(object)t == (Object)null) && !seen.Contains(t) && markers.Count < 64)
{
seen.Add(t);
markers.Add(new Marker
{
name = n,
xf = ToGunSpace(gun, t)
});
}
};
FVRInteractiveObject[] componentsInChildren4 = ((Component)gun).GetComponentsInChildren<FVRInteractiveObject>(true);
foreach (FVRInteractiveObject val10 in componentsInChildren4)
{
if ((Object)(object)val10 != (Object)null && (Object)(object)val10.PoseOverride != (Object)null)
{
action("PoseOverride: " + ((Object)val10).name, val10.PoseOverride);
}
}
string[] array4 = new string[11]
{
"trigger", "safety", "magrelease", "mag_release", "selector", "foregrip", "grip", "hammer", "slide", "bolt",
"handle"
};
Transform[] componentsInChildren5 = ((Component)gun).GetComponentsInChildren<Transform>(true);
foreach (Transform val11 in componentsInChildren5)
{
if (func(val11))
{
continue;
}
string text = ((Object)val11).name.ToLowerInvariant();
string[] array5 = array4;
foreach (string value2 in array5)
{
if (text.Contains(value2))
{
action(((Object)val11).name, val11);
break;
}
}
}
List<PartInfo> list4 = new List<PartInfo>();
componentsInChildren4 = ((Component)gun).GetComponentsInChildren<FVRInteractiveObject>(true);
foreach (FVRInteractiveObject val12 in componentsInChildren4)
{
if (IsPart(val12, gun))
{
list4.Add(new PartInfo
{
name = ((Object)val12).name,
path = RelPath(gun, ((Component)val12).transform),
type = ((object)val12).GetType().Name,
xf = ToGunSpace(gun, HpiParent(val12))
});
}
}
return new GunGeo
{
prims = list.ToArray(),
meshes = list2.ToArray(),
markers = markers.ToArray(),
parts = list4.ToArray()
};
}
private void Notify(string msg)
{
((BaseUnityPlugin)this).Logger.LogMessage((object)msg);
}
}
public static class Similarity
{
public const float DefaultThreshold = 0.8f;
public static float Score(string a, string b)
{
string text = Normalize(a);
string text2 = Normalize(b);
if (text.Length == 0 || text2.Length == 0)
{
return 0f;
}
if (text == text2)
{
return 1f;
}
List<string> list = Tokens(text);
List<string> list2 = Tokens(text2);
if (list.Count == 0 || list2.Count == 0)
{
return 0f;
}
if (FirstAlpha(list) != FirstAlpha(list2))
{
return 0f;
}
if (list.Count == list2.Count)
{
bool flag = true;
bool flag2 = false;
for (int i = 0; i < list.Count; i++)
{
if (!(list[i] == list2[i]))
{
flag2 = true;
int result;
bool num = int.TryParse(list[i], out result);
int result2;
bool flag3 = int.TryParse(list2[i], out result2);
if (!(num && flag3) || Math.Abs(result - result2) > 2)
{
flag = false;
break;
}
}
}
if (flag2 && flag)
{
return 0.9f;
}
}
List<string> list3 = ((list.Count < list2.Count) ? list : list2);
List<string> list4 = ((list.Count < list2.Count) ? list2 : list);
if (list3.Count != list4.Count && list3.Count >= 2)
{
bool flag4 = true;
for (int j = 0; j < list3.Count; j++)
{
if (list3[j] != list4[j])
{
flag4 = false;
break;
}
}
if (flag4)
{
return 0.85f;
}
}
int num2 = Levenshtein(text, text2);
return 1f - (float)num2 / (float)Math.Max(text.Length, text2.Length);
}
public static string Normalize(string s)
{
if (string.IsNullOrEmpty(s))
{
return "";
}
StringBuilder stringBuilder = new StringBuilder();
string text = s.ToLowerInvariant();
foreach (char c in text)
{
if (char.IsLetterOrDigit(c))
{
stringBuilder.Append(c);
}
}
return stringBuilder.ToString();
}
private static List<string> Tokens(string s)
{
List<string> list = new List<string>();
StringBuilder stringBuilder = new StringBuilder();
int num = -1;
foreach (char c in s)
{
bool num2 = char.IsDigit(c);
if ((num2 ? 1 : 0) != num && stringBuilder.Length > 0)
{
list.Add(stringBuilder.ToString());
stringBuilder.Length = 0;
}
num = (num2 ? 1 : 0);
stringBuilder.Append(c);
}
if (stringBuilder.Length > 0)
{
list.Add(stringBuilder.ToString());
}
for (int j = 0; j < list.Count; j++)
{
if (char.IsDigit(list[j][0]))
{
string text = list[j].TrimStart(new char[1] { '0' });
list[j] = ((text.Length == 0) ? "0" : text);
}
}
return list;
}
private static string FirstAlpha(List<string> t)
{
foreach (string item in t)
{
if (!char.IsDigit(item[0]))
{
return item;
}
}
return "";
}
private static int Levenshtein(string a, string b)
{
int[] array = new int[b.Length + 1];
int[] array2 = new int[b.Length + 1];
for (int i = 0; i <= b.Length; i++)
{
array[i] = i;
}
for (int j = 1; j <= a.Length; j++)
{
array2[0] = j;
for (int k = 1; k <= b.Length; k++)
{
array2[k] = Math.Min(Math.Min(array2[k - 1] + 1, array[k] + 1), array[k - 1] + ((a[j - 1] != b[k - 1]) ? 1 : 0));
}
int[] array3 = array;
array = array2;
array2 = array3;
}
return array[b.Length];
}
}
}