mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-02 14:29:25 +00:00
[BetterShadowClone] holyshit i overcomplicated it
This commit is contained in:
parent
1de39260f4
commit
c4099d90a0
5 changed files with 155 additions and 123 deletions
|
@ -43,7 +43,7 @@ public static class ShadowCloneHelper
|
||||||
|
|
||||||
private static void ProcessRenderers(IEnumerable<Renderer> renderers, Transform root, Transform headBone)
|
private static void ProcessRenderers(IEnumerable<Renderer> renderers, Transform root, Transform headBone)
|
||||||
{
|
{
|
||||||
var exclusions = CollectExclusions2(root, headBone);
|
IReadOnlyDictionary<Transform, FPRExclusion> exclusions = CollectTransformToExclusionMap(root, headBone);
|
||||||
|
|
||||||
foreach (Renderer renderer in renderers)
|
foreach (Renderer renderer in renderers)
|
||||||
{
|
{
|
||||||
|
@ -55,7 +55,8 @@ public static class ShadowCloneHelper
|
||||||
if (clone != null) ShadowCloneManager.Instance.AddShadowClone(clone);
|
if (clone != null) ShadowCloneManager.Instance.AddShadowClone(clone);
|
||||||
}
|
}
|
||||||
|
|
||||||
TransformHiderManager.CreateTransformHider(renderer, exclusions);
|
ITransformHider hider = TransformHiderManager.CreateTransformHider(renderer, exclusions);
|
||||||
|
if (hider != null) TransformHiderManager.Instance.AddTransformHider(hider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +64,7 @@ public static class ShadowCloneHelper
|
||||||
|
|
||||||
#region FPR Exclusion Processing
|
#region FPR Exclusion Processing
|
||||||
|
|
||||||
private static Dictionary<Transform, FPRExclusion> CollectExclusions2(Transform root, Transform headBone)
|
private static Dictionary<Transform, FPRExclusion> CollectTransformToExclusionMap(Component root, Transform headBone)
|
||||||
{
|
{
|
||||||
// add an fpr exclusion to the head bone
|
// add an fpr exclusion to the head bone
|
||||||
headBone.gameObject.AddComponent<FPRExclusion>().target = headBone;
|
headBone.gameObject.AddComponent<FPRExclusion>().target = headBone;
|
||||||
|
@ -72,7 +73,7 @@ public static class ShadowCloneHelper
|
||||||
var fprExclusions = root.GetComponentsInChildren<FPRExclusion>(true).ToList();
|
var fprExclusions = root.GetComponentsInChildren<FPRExclusion>(true).ToList();
|
||||||
|
|
||||||
// get all valid exclusion targets, and destroy invalid exclusions
|
// get all valid exclusion targets, and destroy invalid exclusions
|
||||||
Dictionary<Transform, FPRExclusion> exclusionTargetRoots = new();
|
Dictionary<Transform, FPRExclusion> exclusionTargets = new();
|
||||||
for (int i = fprExclusions.Count - 1; i >= 0; i--)
|
for (int i = fprExclusions.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
FPRExclusion exclusion = fprExclusions[i];
|
FPRExclusion exclusion = fprExclusions[i];
|
||||||
|
@ -82,7 +83,7 @@ public static class ShadowCloneHelper
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
exclusionTargetRoots.Add(exclusion.target, exclusion);
|
exclusionTargets.Add(exclusion.target, exclusion);
|
||||||
}
|
}
|
||||||
|
|
||||||
// process each FPRExclusion (recursive)
|
// process each FPRExclusion (recursive)
|
||||||
|
@ -91,14 +92,15 @@ public static class ShadowCloneHelper
|
||||||
|
|
||||||
// log totals
|
// log totals
|
||||||
ShadowCloneMod.Logger.Msg($"Exclusions: {fprExclusions.Count}");
|
ShadowCloneMod.Logger.Msg($"Exclusions: {fprExclusions.Count}");
|
||||||
return exclusionTargetRoots;
|
return exclusionTargets;
|
||||||
|
|
||||||
void ProcessExclusion(FPRExclusion exclusion, Transform transform)
|
void ProcessExclusion(FPRExclusion exclusion, Transform transform)
|
||||||
{
|
{
|
||||||
if (exclusionTargetRoots.ContainsKey(transform)
|
if (exclusionTargets.ContainsKey(transform)
|
||||||
&& exclusionTargetRoots[transform] != exclusion) return; // found other exclusion root
|
&& exclusionTargets[transform] != exclusion) return; // found other exclusion root
|
||||||
|
|
||||||
exclusion.affectedChildren.Add(transform); // associate with the exclusion
|
exclusion.affectedChildren.Add(transform); // associate with the exclusion
|
||||||
|
exclusionTargets.Add(transform, exclusion); // add to the list (yes theres duplicates)
|
||||||
|
|
||||||
foreach (Transform child in transform)
|
foreach (Transform child in transform)
|
||||||
ProcessExclusion(exclusion, child); // process children
|
ProcessExclusion(exclusion, child); // process children
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class FPRExclusion : MonoBehaviour
|
||||||
internal List<Transform> affectedChildren = new();
|
internal List<Transform> affectedChildren = new();
|
||||||
|
|
||||||
[NonSerialized]
|
[NonSerialized]
|
||||||
internal ITransformHider[] relevantHiders;
|
internal readonly List<IFPRExclusionTask> relatedTasks = new();
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
=> SetFPRState(true);
|
=> SetFPRState(true);
|
||||||
|
@ -23,8 +23,13 @@ public class FPRExclusion : MonoBehaviour
|
||||||
|
|
||||||
private void SetFPRState(bool state)
|
private void SetFPRState(bool state)
|
||||||
{
|
{
|
||||||
if (relevantHiders == null) return; // no hiders to set
|
if (relatedTasks == null) return; // no hiders to set
|
||||||
foreach (ITransformHider hider in relevantHiders)
|
foreach (IFPRExclusionTask task in relatedTasks)
|
||||||
hider.IsActive = state;
|
task.IsActive = state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IFPRExclusionTask
|
||||||
|
{
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ using UnityEngine.Rendering;
|
||||||
|
|
||||||
namespace NAK.BetterShadowClone;
|
namespace NAK.BetterShadowClone;
|
||||||
|
|
||||||
public class MeshTransformHider : ITransformHider
|
public class MeshTransformHider : ITransformHider, IFPRExclusionTask
|
||||||
{
|
{
|
||||||
// lame 2 frame init stuff
|
// lame 2 frame init stuff
|
||||||
private const int FrameInitCount = 0;
|
private const int FrameInitCount = 0;
|
||||||
|
@ -23,8 +23,19 @@ public class MeshTransformHider : ITransformHider
|
||||||
// anything player can touch is suspect to death
|
// anything player can touch is suspect to death
|
||||||
public bool IsValid => _mainMesh != null && !_markedForDeath;
|
public bool IsValid => _mainMesh != null && !_markedForDeath;
|
||||||
|
|
||||||
public MeshTransformHider(MeshRenderer renderer)
|
public MeshTransformHider(MeshRenderer renderer, IReadOnlyDictionary<Transform, FPRExclusion> exclusions)
|
||||||
{
|
{
|
||||||
|
Transform rootBone = renderer.transform;
|
||||||
|
|
||||||
|
// if no key found, dispose
|
||||||
|
if (!exclusions.TryGetValue(rootBone, out FPRExclusion exclusion))
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
exclusion.relatedTasks.Add(this);
|
||||||
|
|
||||||
_mainMesh = renderer;
|
_mainMesh = renderer;
|
||||||
|
|
||||||
if (_mainMesh == null
|
if (_mainMesh == null
|
||||||
|
|
|
@ -19,37 +19,28 @@ public class SkinnedTransformHider : ITransformHider
|
||||||
private bool _markedForDeath;
|
private bool _markedForDeath;
|
||||||
|
|
||||||
// mesh & bone
|
// mesh & bone
|
||||||
private readonly Transform _shrinkBone;
|
|
||||||
private readonly SkinnedMeshRenderer _mainMesh;
|
private readonly SkinnedMeshRenderer _mainMesh;
|
||||||
private readonly Transform _rootBone;
|
private readonly Transform _rootBone;
|
||||||
|
|
||||||
// exclusion
|
// main hider stuff
|
||||||
private readonly FPRExclusion _exclusion;
|
|
||||||
|
|
||||||
// hider stuff
|
|
||||||
private GraphicsBuffer _graphicsBuffer;
|
private GraphicsBuffer _graphicsBuffer;
|
||||||
private int _bufferLayout;
|
private int _bufferLayout;
|
||||||
|
|
||||||
private ComputeBuffer _computeBuffer;
|
// subtasks
|
||||||
private int _vertexCount;
|
private readonly List<SubTask> _subTasks = new();
|
||||||
private int _threadGroups;
|
|
||||||
|
|
||||||
#region ITransformHider Methods
|
#region ITransformHider Methods
|
||||||
|
|
||||||
public bool IsActive { get; set; } = true; // default hide, but FPRExclusion can override
|
public bool IsActive { get; set; } = true; // default hide, but FPRExclusion can override
|
||||||
|
|
||||||
// anything player can touch is suspect to death
|
// anything player can touch is suspect to death
|
||||||
public bool IsValid => _mainMesh != null && _shrinkBone != null && !_markedForDeath;
|
public bool IsValid => !_markedForDeath && _mainMesh != null && _rootBone != null;
|
||||||
|
|
||||||
public SkinnedTransformHider(SkinnedMeshRenderer renderer, FPRExclusion exclusion)
|
public SkinnedTransformHider(SkinnedMeshRenderer renderer, IReadOnlyDictionary<Transform, FPRExclusion> exclusions)
|
||||||
{
|
{
|
||||||
_mainMesh = renderer;
|
_mainMesh = renderer;
|
||||||
_shrinkBone = exclusion.target;
|
|
||||||
_exclusion = exclusion;
|
|
||||||
|
|
||||||
if (_exclusion == null
|
if (_mainMesh == null
|
||||||
|| _shrinkBone == null
|
|
||||||
|| _mainMesh == null
|
|
||||||
|| _mainMesh.sharedMesh == null
|
|| _mainMesh.sharedMesh == null
|
||||||
|| _mainMesh.sharedMaterials == null
|
|| _mainMesh.sharedMaterials == null
|
||||||
|| _mainMesh.sharedMaterials.Length == 0)
|
|| _mainMesh.sharedMaterials.Length == 0)
|
||||||
|
@ -58,20 +49,39 @@ public class SkinnedTransformHider : ITransformHider
|
||||||
return; // no mesh or bone!
|
return; // no mesh or bone!
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the head vertices
|
|
||||||
var exclusionVerts = FindExclusionVertList();
|
|
||||||
if (exclusionVerts.Count == 0)
|
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
return; // no head vertices!
|
|
||||||
}
|
|
||||||
|
|
||||||
_rootBone = _mainMesh.rootBone;
|
_rootBone = _mainMesh.rootBone;
|
||||||
_rootBone ??= _mainMesh.transform; // fallback to transform if no root bone
|
_rootBone ??= _mainMesh.transform; // fallback to transform if no root bone
|
||||||
|
|
||||||
_vertexCount = exclusionVerts.Count;
|
// subtask creation
|
||||||
_computeBuffer = new ComputeBuffer(_vertexCount, sizeof(int));
|
|
||||||
_computeBuffer.SetData(exclusionVerts.ToArray());
|
var bones = renderer.bones;
|
||||||
|
List<FPRExclusion> fprExclusions = new();
|
||||||
|
|
||||||
|
foreach (Transform bone in bones)
|
||||||
|
{
|
||||||
|
if (bone == null)
|
||||||
|
continue; // thanks AdvancedSafety for preventing null ref for so long...
|
||||||
|
|
||||||
|
if (!exclusions.TryGetValue(bone, out FPRExclusion exclusion))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fprExclusions.Add(exclusion);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int> exclusionVerts;
|
||||||
|
foreach (FPRExclusion exclusion in fprExclusions)
|
||||||
|
{
|
||||||
|
exclusionVerts = SubTask.FindExclusionVertList(renderer, exclusion);
|
||||||
|
if (exclusionVerts.Count == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SubTask subTask = new(this, exclusion.target, exclusionVerts);
|
||||||
|
_subTasks.Add(subTask);
|
||||||
|
exclusion.relatedTasks.Add(subTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_subTasks.Count == 0)
|
||||||
|
Dispose(); // had the bones, but not the weights :?
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Process()
|
public bool Process()
|
||||||
|
@ -104,24 +114,17 @@ public class SkinnedTransformHider : ITransformHider
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool PostProcess()
|
public bool PostProcess()
|
||||||
{
|
=> false; // not needed
|
||||||
return false; // not needed
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HideTransform()
|
public void HideTransform()
|
||||||
{
|
{
|
||||||
_mainMesh.forceRenderingOff = false;
|
_mainMesh.forceRenderingOff = false;
|
||||||
|
|
||||||
// probably fine
|
|
||||||
Vector3 pos = _rootBone.transform.InverseTransformPoint(_shrinkBone.position) * _rootBone.lossyScale.y;
|
|
||||||
|
|
||||||
_graphicsBuffer = _mainMesh.GetVertexBuffer();
|
_graphicsBuffer = _mainMesh.GetVertexBuffer();
|
||||||
TransformHiderManager.shader.SetVector(s_Pos, pos);
|
|
||||||
TransformHiderManager.shader.SetInt(s_WeightedCount, _vertexCount);
|
foreach (SubTask subTask in _subTasks)
|
||||||
TransformHiderManager.shader.SetInt(s_BufferLayout, _bufferLayout);
|
if (subTask.IsActive && subTask.IsValid) subTask.Dispatch();
|
||||||
TransformHiderManager.shader.SetBuffer(0, s_WeightedVertices, _computeBuffer);
|
|
||||||
TransformHiderManager.shader.SetBuffer(0, s_VertexBuffer, _graphicsBuffer);
|
|
||||||
TransformHiderManager.shader.Dispatch(0, _threadGroups, 1, 1);
|
|
||||||
_graphicsBuffer.Release();
|
_graphicsBuffer.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,10 +136,11 @@ public class SkinnedTransformHider : ITransformHider
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_markedForDeath = true;
|
_markedForDeath = true;
|
||||||
|
foreach (SubTask subTask in _subTasks)
|
||||||
|
subTask.Dispose();
|
||||||
|
|
||||||
_graphicsBuffer?.Dispose();
|
_graphicsBuffer?.Dispose();
|
||||||
_graphicsBuffer = null;
|
_graphicsBuffer = null;
|
||||||
_computeBuffer?.Dispose();
|
|
||||||
_computeBuffer = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -152,39 +156,82 @@ public class SkinnedTransformHider : ITransformHider
|
||||||
if (mesh.HasVertexAttribute(VertexAttribute.Position)) _bufferLayout += 3;
|
if (mesh.HasVertexAttribute(VertexAttribute.Position)) _bufferLayout += 3;
|
||||||
if (mesh.HasVertexAttribute(VertexAttribute.Normal)) _bufferLayout += 3;
|
if (mesh.HasVertexAttribute(VertexAttribute.Normal)) _bufferLayout += 3;
|
||||||
if (mesh.HasVertexAttribute(VertexAttribute.Tangent)) _bufferLayout += 4;
|
if (mesh.HasVertexAttribute(VertexAttribute.Tangent)) _bufferLayout += 4;
|
||||||
|
|
||||||
// ComputeShader is doing bitshift so we dont need to multiply by 4
|
// ComputeShader is doing bitshift so we dont need to multiply by 4
|
||||||
//_bufferLayout *= 4; // 4 bytes per float
|
|
||||||
|
|
||||||
const float xThreadGroups = 64f;
|
|
||||||
_threadGroups = Mathf.CeilToInt(mesh.vertexCount / xThreadGroups);
|
|
||||||
|
|
||||||
_mainMesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw;
|
_mainMesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<int> FindExclusionVertList()
|
#endregion
|
||||||
|
|
||||||
|
#region Sub Task Class
|
||||||
|
|
||||||
|
private class SubTask : IFPRExclusionTask
|
||||||
{
|
{
|
||||||
var boneWeights = _mainMesh.sharedMesh.boneWeights;
|
public bool IsActive { get; set; } = true;
|
||||||
var bones = _exclusion.affectedChildren;
|
public bool IsValid => _computeBuffer != null; // TODO: cleanup dead tasks
|
||||||
|
|
||||||
HashSet<int> weights = new(); //get indexs of child bones
|
private readonly SkinnedTransformHider _parent;
|
||||||
for (int i = 0; i < _mainMesh.bones.Length; i++)
|
private readonly Transform _shrinkBone;
|
||||||
if (bones.Contains(_mainMesh.bones[i])) weights.Add(i);
|
private readonly int _vertexCount;
|
||||||
|
private readonly ComputeBuffer _computeBuffer;
|
||||||
|
private readonly int _threadGroups;
|
||||||
|
|
||||||
List<int> headVertices = new();
|
public SubTask(SkinnedTransformHider parent, Transform shrinkBone, List<int> exclusionVerts)
|
||||||
|
|
||||||
for (int i = 0; i < boneWeights.Length; i++)
|
|
||||||
{
|
{
|
||||||
BoneWeight weight = boneWeights[i];
|
_parent = parent;
|
||||||
const float minWeightThreshold = 0.2f;
|
_shrinkBone = shrinkBone;
|
||||||
if (weights.Contains(weight.boneIndex0) && weight.weight0 > minWeightThreshold
|
|
||||||
|| weights.Contains(weight.boneIndex1) && weight.weight1 > minWeightThreshold
|
_vertexCount = exclusionVerts.Count;
|
||||||
|| weights.Contains(weight.boneIndex2) && weight.weight2 > minWeightThreshold
|
_computeBuffer = new ComputeBuffer(_vertexCount, sizeof(int));
|
||||||
|| weights.Contains(weight.boneIndex3) && weight.weight3 > minWeightThreshold)
|
_computeBuffer.SetData(exclusionVerts.ToArray());
|
||||||
headVertices.Add(i);
|
|
||||||
|
const float xThreadGroups = 64f;
|
||||||
|
_threadGroups = Mathf.CeilToInt(_vertexCount / xThreadGroups);
|
||||||
}
|
}
|
||||||
|
|
||||||
return headVertices;
|
public void Dispatch()
|
||||||
|
{
|
||||||
|
Vector3 pos = _parent._rootBone.transform.InverseTransformPoint(_shrinkBone.position) * _parent._rootBone.lossyScale.y;
|
||||||
|
TransformHiderManager.shader.SetVector(s_Pos, pos);
|
||||||
|
TransformHiderManager.shader.SetInt(s_WeightedCount, _vertexCount);
|
||||||
|
TransformHiderManager.shader.SetInt(s_BufferLayout, _parent._bufferLayout);
|
||||||
|
TransformHiderManager.shader.SetBuffer(0, s_WeightedVertices, _computeBuffer);
|
||||||
|
TransformHiderManager.shader.SetBuffer(0, s_VertexBuffer, _parent._graphicsBuffer);
|
||||||
|
TransformHiderManager.shader.Dispatch(0, _threadGroups, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_computeBuffer?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
public static List<int> FindExclusionVertList(SkinnedMeshRenderer renderer, FPRExclusion exclusion)
|
||||||
|
{
|
||||||
|
var boneWeights = renderer.sharedMesh.boneWeights;
|
||||||
|
var bones = exclusion.affectedChildren;
|
||||||
|
|
||||||
|
HashSet<int> weights = new();
|
||||||
|
for (int i = 0; i < renderer.bones.Length; i++)
|
||||||
|
if (bones.Contains(renderer.bones[i])) weights.Add(i);
|
||||||
|
|
||||||
|
List<int> headVertices = new();
|
||||||
|
for (int i = 0; i < boneWeights.Length; i++)
|
||||||
|
{
|
||||||
|
BoneWeight weight = boneWeights[i];
|
||||||
|
const float minWeightThreshold = 0.2f;
|
||||||
|
if (weights.Contains(weight.boneIndex0) && weight.weight0 > minWeightThreshold
|
||||||
|
|| weights.Contains(weight.boneIndex1) && weight.weight1 > minWeightThreshold
|
||||||
|
|| weights.Contains(weight.boneIndex2) && weight.weight2 > minWeightThreshold
|
||||||
|
|| weights.Contains(weight.boneIndex3) && weight.weight3 > minWeightThreshold)
|
||||||
|
headVertices.Add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return headVertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using ABI_RC.Core.Player;
|
||||||
using ABI_RC.Core.Player;
|
|
||||||
using ABI_RC.Core.Savior;
|
|
||||||
using ABI_RC.Systems.Camera;
|
|
||||||
using MagicaCloth;
|
using MagicaCloth;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
@ -190,48 +187,18 @@ public class TransformHiderManager : MonoBehaviour
|
||||||
internal static bool IsLegacyFPRExcluded(Component renderer)
|
internal static bool IsLegacyFPRExcluded(Component renderer)
|
||||||
=> renderer.gameObject.name.Contains("[FPR]");
|
=> renderer.gameObject.name.Contains("[FPR]");
|
||||||
|
|
||||||
internal static ITransformHider CreateTransformHider(Component renderer, Transform bone)
|
internal static ITransformHider CreateTransformHider(Component renderer, IReadOnlyDictionary<Transform, FPRExclusion> exclusions)
|
||||||
{
|
{
|
||||||
if (IsLegacyFPRExcluded(renderer))
|
if (IsLegacyFPRExcluded(renderer))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return renderer switch
|
return renderer switch
|
||||||
{
|
{
|
||||||
//SkinnedMeshRenderer skinnedMeshRenderer => new SkinnedTransformHider(skinnedMeshRenderer, bone),
|
SkinnedMeshRenderer skinnedMeshRenderer => new SkinnedTransformHider(skinnedMeshRenderer, exclusions),
|
||||||
MeshRenderer meshRenderer => new MeshTransformHider(meshRenderer),
|
MeshRenderer meshRenderer => new MeshTransformHider(meshRenderer, exclusions),
|
||||||
_ => null
|
_ => null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void CreateTransformHider(Component renderer, Dictionary<Transform, FPRExclusion> exclusions)
|
|
||||||
{
|
|
||||||
if (IsLegacyFPRExcluded(renderer))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (renderer is SkinnedMeshRenderer skinnedMeshRenderer)
|
|
||||||
{
|
|
||||||
// get all bones for renderer
|
|
||||||
var bones = skinnedMeshRenderer.bones;
|
|
||||||
List<FPRExclusion> fprExclusions = new();
|
|
||||||
|
|
||||||
// check if any bones are excluded
|
|
||||||
foreach (Transform bone in bones)
|
|
||||||
{
|
|
||||||
if (!exclusions.TryGetValue(bone, out FPRExclusion exclusion))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
fprExclusions.Add(exclusion);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (FPRExclusion exclusion in fprExclusions)
|
|
||||||
{
|
|
||||||
ITransformHider hider = new SkinnedTransformHider(skinnedMeshRenderer, exclusion);
|
|
||||||
Instance.AddTransformHider(hider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue