mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-02 06:19:22 +00:00
further cleanup of repo
This commit is contained in:
parent
4f8dcb0cd0
commit
323eb92f2e
140 changed files with 1 additions and 2430 deletions
|
@ -0,0 +1,229 @@
|
|||
using ABI.CCK.Components;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NAK.AvatarCloneTest;
|
||||
|
||||
public partial class AvatarClone
|
||||
{
|
||||
#region Exclusions
|
||||
|
||||
private FPRExclusion[] _exclusions;
|
||||
|
||||
private void AddExclusionToHeadIfNeeded()
|
||||
{
|
||||
if (!TryGetComponent(out Animator animator)
|
||||
|| !animator.isHuman
|
||||
|| !animator.avatar
|
||||
|| !animator.avatar.isValid)
|
||||
return;
|
||||
|
||||
Transform head = animator.GetBoneTransform(HumanBodyBones.Head);
|
||||
if (!head)
|
||||
return;
|
||||
|
||||
GameObject headGo = head.gameObject;
|
||||
if (headGo.TryGetComponent(out FPRExclusion exclusion))
|
||||
return;
|
||||
|
||||
exclusion = headGo.AddComponent<FPRExclusion>();
|
||||
exclusion.target = head;
|
||||
exclusion.isShown = false;
|
||||
}
|
||||
|
||||
private void InitializeExclusions()
|
||||
{
|
||||
_exclusions = GetComponentsInChildren<FPRExclusion>(true);
|
||||
var exclusionRoots = new Dictionary<Transform, AvatarCloneExclusion>(_exclusions.Length);
|
||||
|
||||
// **1. Precompute Exclusions**
|
||||
foreach (FPRExclusion exclusion in _exclusions)
|
||||
{
|
||||
Transform target = exclusion.target ??= exclusion.transform;
|
||||
if (exclusionRoots.ContainsKey(target) || !target.gameObject.scene.IsValid())
|
||||
continue;
|
||||
|
||||
AvatarCloneExclusion behaviour = new AvatarCloneExclusion(this, target);
|
||||
exclusion.behaviour = behaviour;
|
||||
exclusionRoots.Add(target, behaviour);
|
||||
}
|
||||
|
||||
// Process Exclusion Transforms
|
||||
Renderer ourRenderer;
|
||||
|
||||
void ProcessTransformHierarchy(Transform current, Transform root, AvatarCloneExclusion behaviour)
|
||||
{
|
||||
if (exclusionRoots.ContainsKey(current) && current != root) return;
|
||||
|
||||
behaviour.affectedTransforms.Add(current);
|
||||
if (current.TryGetComponent(out ourRenderer))
|
||||
behaviour.affectedRenderers.Add(ourRenderer);
|
||||
|
||||
for (int i = 0; i < current.childCount; i++)
|
||||
{
|
||||
Transform child = current.GetChild(i);
|
||||
if (!exclusionRoots.ContainsKey(child))
|
||||
ProcessTransformHierarchy(child, root, behaviour);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var entry in exclusionRoots)
|
||||
{
|
||||
Transform rootTransform = entry.Key;
|
||||
AvatarCloneExclusion behaviour = entry.Value;
|
||||
ProcessTransformHierarchy(rootTransform, rootTransform, behaviour);
|
||||
behaviour.affectedTransformSet = new HashSet<Transform>(behaviour.affectedTransforms);
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// **OPTIMIZED EXCLUSION BONE MAPPING**
|
||||
// ------------------------------
|
||||
|
||||
Dictionary<Transform, AvatarCloneExclusion>.ValueCollection exclusionBehaviours = exclusionRoots.Values;
|
||||
int skinnedCount = _skinnedClones.Count;
|
||||
|
||||
// **2. Precompute Bone-to-Exclusion Mapping**
|
||||
int estimatedBoneCount = skinnedCount * 20; // Estimated bones per skinned mesh
|
||||
var boneToExclusion = new Dictionary<Transform, List<AvatarCloneExclusion>>(estimatedBoneCount);
|
||||
|
||||
foreach (AvatarCloneExclusion behaviour in exclusionBehaviours)
|
||||
{
|
||||
foreach (Transform bone in behaviour.affectedTransformSet)
|
||||
{
|
||||
if (!boneToExclusion.TryGetValue(bone, out var list))
|
||||
{
|
||||
list = new List<AvatarCloneExclusion>(2);
|
||||
boneToExclusion[bone] = list;
|
||||
}
|
||||
list.Add(behaviour);
|
||||
}
|
||||
}
|
||||
|
||||
// **3. Process Skinned Mesh Renderers**
|
||||
for (int s = 0; s < skinnedCount; s++)
|
||||
{
|
||||
SkinnedMeshRenderer source = _skinnedRenderers[s];
|
||||
var bones = source.bones; // Cache bones array
|
||||
|
||||
SkinnedMeshRenderer smr = _skinnedClones[s];
|
||||
int boneCount = bones.Length;
|
||||
|
||||
for (int i = 0; i < boneCount; i++)
|
||||
{
|
||||
Transform bone = bones[i];
|
||||
|
||||
// **Skip if the bone isn't mapped to exclusions**
|
||||
if (!bone // Skip null bones
|
||||
|| !boneToExclusion.TryGetValue(bone, out var behaviours))
|
||||
continue;
|
||||
|
||||
// **Avoid redundant dictionary lookups**
|
||||
for (int j = 0; j < behaviours.Count; j++)
|
||||
{
|
||||
AvatarCloneExclusion behaviour = behaviours[j];
|
||||
|
||||
if (!behaviour.skinnedToBoneIndex.TryGetValue(smr, out var indices))
|
||||
{
|
||||
indices = new List<int>(4);
|
||||
behaviour.skinnedToBoneIndex[smr] = indices;
|
||||
}
|
||||
|
||||
indices.Add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ApplyInitialExclusionState();
|
||||
}
|
||||
|
||||
public void ApplyInitialExclusionState()
|
||||
{
|
||||
foreach (FPRExclusion exclusion in _exclusions)
|
||||
{
|
||||
exclusion._wasShown = exclusion.isShown;
|
||||
if (!exclusion.isShown) exclusion.UpdateExclusions();
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleExclusionUpdate(AvatarCloneExclusion exclusion, bool isShown)
|
||||
{
|
||||
#if ENABLE_PROFILER
|
||||
s_UpdateExclusions.Begin();
|
||||
#endif
|
||||
|
||||
// **1. Update Renderer Visibility**
|
||||
foreach (Renderer renderer in exclusion.affectedRenderers)
|
||||
{
|
||||
if (renderer is SkinnedMeshRenderer skinned)
|
||||
{
|
||||
int index = _skinnedRenderers.IndexOf(skinned);
|
||||
if (index >= 0) _skinnedClones[index].gameObject.SetActive(isShown);
|
||||
}
|
||||
else if (renderer is MeshRenderer mesh)
|
||||
{
|
||||
int index = _meshRenderers.IndexOf(mesh);
|
||||
if (index >= 0)
|
||||
{
|
||||
if (Setting_CloneMeshRenderers)
|
||||
{
|
||||
_meshClones[index].gameObject.SetActive(isShown);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Other renderer (never cloned) - update shadow casting state
|
||||
_sourceShouldBeHiddenFromFPR[index] = !isShown; // When hidden, use for shadows
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (renderer)
|
||||
{
|
||||
int index = _otherRenderers.IndexOf(renderer);
|
||||
if (index >= 0)
|
||||
{
|
||||
int shadowIndex = index + (Setting_CloneMeshRenderers ? _meshRenderers.Count : 0);
|
||||
_sourceShouldBeHiddenFromFPR[shadowIndex] = !isShown; // When hidden, use for shadows
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// **2. Update Bone References in Skinned Mesh Renderers**
|
||||
UpdateSkinnedMeshBones(exclusion, exclusion._shrinkBone, isShown);
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_UpdateExclusions.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void UpdateSkinnedMeshBones(AvatarCloneExclusion exclusion, Transform shrinkBone, bool isShown)
|
||||
{
|
||||
#if ENABLE_PROFILER
|
||||
s_HandleBoneUpdates.Begin();
|
||||
#endif
|
||||
|
||||
foreach (var smrEntry in exclusion.skinnedToBoneIndex)
|
||||
{
|
||||
SkinnedMeshRenderer smr = smrEntry.Key;
|
||||
var indices = smrEntry.Value;
|
||||
bool needsUpdate = false;
|
||||
|
||||
var parentBones = smr.transform.parent.GetComponent<SkinnedMeshRenderer>().bones;
|
||||
var cloneBones = smr.bones;
|
||||
Array.Resize(ref cloneBones, parentBones.Length);
|
||||
|
||||
// Only modify our bones, other exclusions may have modified others
|
||||
for (int i = 0; i < indices.Count; i++)
|
||||
{
|
||||
int index = indices[i];
|
||||
if (!isShown) cloneBones[index] = shrinkBone;
|
||||
else cloneBones[index] = parentBones[index];
|
||||
needsUpdate = true;
|
||||
}
|
||||
if (needsUpdate) smr.bones = cloneBones;
|
||||
}
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_HandleBoneUpdates.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion Exclusions
|
||||
}
|
304
.Deprecated/AvatarCloneTest/AvatarClone/AvatarClone.Init.cs
Normal file
304
.Deprecated/AvatarCloneTest/AvatarClone/AvatarClone.Init.cs
Normal file
|
@ -0,0 +1,304 @@
|
|||
using ABI_RC.Core.Player.ShadowClone;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace NAK.AvatarCloneTest;
|
||||
|
||||
public partial class AvatarClone
|
||||
{
|
||||
#region Initialization
|
||||
|
||||
private void InitializeCollections()
|
||||
{
|
||||
#if ENABLE_PROFILER
|
||||
s_InitializeData.Begin();
|
||||
#endif
|
||||
|
||||
// Initialize source collections
|
||||
_skinnedRenderers = new List<SkinnedMeshRenderer>();
|
||||
_blendShapeWeights = new List<List<float>>();
|
||||
|
||||
_meshRenderers = new List<MeshRenderer>();
|
||||
_meshFilters = new List<MeshFilter>();
|
||||
|
||||
_otherRenderers = new List<Renderer>();
|
||||
|
||||
// Initialize clone collections
|
||||
_skinnedClones = new List<SkinnedMeshRenderer>();
|
||||
_skinnedCloneMaterials = new List<Material[]>();
|
||||
_skinnedCloneCullingMaterials = new List<Material[]>();
|
||||
|
||||
if (Setting_CloneMeshRenderers)
|
||||
{
|
||||
_meshClones = new List<MeshRenderer>();
|
||||
_meshCloneFilters = new List<MeshFilter>();
|
||||
_meshCloneMaterials = new List<Material[]>();
|
||||
_meshCloneCullingMaterials = new List<Material[]>();
|
||||
}
|
||||
|
||||
// Initialize shared resources
|
||||
_materialWorkingList = new List<Material>();
|
||||
_propertyBlock = new MaterialPropertyBlock();
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_InitializeData.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void CollectRenderers()
|
||||
{
|
||||
#if ENABLE_PROFILER
|
||||
s_InitializeData.Begin();
|
||||
#endif
|
||||
|
||||
var renderers = GetComponentsInChildren<Renderer>(true);
|
||||
var currentIndex = 0;
|
||||
var nonCloned = 0;
|
||||
|
||||
// Single pass: directly categorize renderers
|
||||
foreach (Renderer renderer in renderers)
|
||||
{
|
||||
switch (renderer)
|
||||
{
|
||||
case SkinnedMeshRenderer skinned when skinned.sharedMesh != null:
|
||||
AddSkinnedRenderer(skinned);
|
||||
currentIndex++;
|
||||
break;
|
||||
|
||||
case MeshRenderer mesh:
|
||||
MeshFilter filter = mesh.GetComponent<MeshFilter>();
|
||||
if (filter != null && filter.sharedMesh != null)
|
||||
{
|
||||
if (Setting_CloneMeshRenderers)
|
||||
{
|
||||
AddMeshRenderer(mesh, filter);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddMeshRenderer(mesh, filter);
|
||||
nonCloned++;
|
||||
}
|
||||
currentIndex++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
AddOtherRenderer(renderer);
|
||||
currentIndex++;
|
||||
nonCloned++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_rendererActiveStates = new bool[currentIndex];
|
||||
_originalShadowCastingMode = new ShadowCastingMode[currentIndex];
|
||||
_sourceShouldBeHiddenFromFPR = new bool[nonCloned];
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_InitializeData.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void AddSkinnedRenderer(SkinnedMeshRenderer renderer)
|
||||
{
|
||||
#if ENABLE_PROFILER
|
||||
s_AddRenderer.Begin();
|
||||
#endif
|
||||
|
||||
_skinnedRenderers.Add(renderer);
|
||||
|
||||
// Clone materials array for clone renderer
|
||||
var materials = renderer.sharedMaterials;
|
||||
var cloneMaterials = new Material[materials.Length];
|
||||
for (int i = 0; i < materials.Length; i++) cloneMaterials[i] = materials[i];
|
||||
_skinnedCloneMaterials.Add(cloneMaterials);
|
||||
|
||||
// Cache culling materials
|
||||
var cullingMaterialArray = new Material[materials.Length];
|
||||
#if !UNITY_EDITOR
|
||||
for (int i = 0; i < materials.Length; i++) cullingMaterialArray[i] = ShadowCloneUtils.cullingMaterial;
|
||||
#else
|
||||
for (int i = 0; i < materials.Length; i++) cullingMaterialArray[i] = cullingMaterial;
|
||||
#endif
|
||||
_skinnedCloneCullingMaterials.Add(cullingMaterialArray);
|
||||
|
||||
// Cache blend shape weights
|
||||
var weights = new List<float>(renderer.sharedMesh.blendShapeCount);
|
||||
for (int i = 0; i < renderer.sharedMesh.blendShapeCount; i++) weights.Add(0f);
|
||||
_blendShapeWeights.Add(weights);
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_AddRenderer.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void AddMeshRenderer(MeshRenderer renderer, MeshFilter filter)
|
||||
{
|
||||
#if ENABLE_PROFILER
|
||||
s_AddRenderer.Begin();
|
||||
#endif
|
||||
|
||||
_meshRenderers.Add(renderer);
|
||||
_meshFilters.Add(filter);
|
||||
|
||||
if (!Setting_CloneMeshRenderers) return;
|
||||
|
||||
// Clone materials array for clone renderer
|
||||
var materials = renderer.sharedMaterials;
|
||||
var cloneMaterials = new Material[materials.Length];
|
||||
for (int i = 0; i < materials.Length; i++) cloneMaterials[i] = materials[i];
|
||||
_meshCloneMaterials.Add(cloneMaterials);
|
||||
|
||||
// Cache culling materials
|
||||
var cullingMaterialArray = new Material[materials.Length];
|
||||
#if !UNITY_EDITOR
|
||||
for (int i = 0; i < materials.Length; i++) cullingMaterialArray[i] = ShadowCloneUtils.cullingMaterial;
|
||||
#else
|
||||
for (int i = 0; i < materials.Length; i++) cullingMaterialArray[i] = cullingMaterial;
|
||||
#endif
|
||||
_meshCloneCullingMaterials.Add(cullingMaterialArray);
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_AddRenderer.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void AddOtherRenderer(Renderer renderer)
|
||||
{
|
||||
#if ENABLE_PROFILER
|
||||
s_AddRenderer.Begin();
|
||||
#endif
|
||||
_otherRenderers.Add(renderer);
|
||||
#if ENABLE_PROFILER
|
||||
s_AddRenderer.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void CreateClones()
|
||||
{
|
||||
#if ENABLE_PROFILER
|
||||
s_InitializeData.Begin();
|
||||
#endif
|
||||
|
||||
// Always create skinned mesh clones
|
||||
int skinnedCount = _skinnedRenderers.Count;
|
||||
for (int i = 0; i < skinnedCount; i++)
|
||||
{
|
||||
CreateSkinnedClone(i);
|
||||
}
|
||||
|
||||
// Optionally create mesh clones
|
||||
if (Setting_CloneMeshRenderers)
|
||||
{
|
||||
int meshCount = _meshRenderers.Count;
|
||||
for (int i = 0; i < meshCount; i++)
|
||||
{
|
||||
CreateMeshClone(i);
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_InitializeData.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void CreateSkinnedClone(int index)
|
||||
{
|
||||
#if ENABLE_PROFILER
|
||||
s_CreateClone.Begin();
|
||||
#endif
|
||||
|
||||
SkinnedMeshRenderer source = _skinnedRenderers[index];
|
||||
|
||||
GameObject clone = new(source.name + "_Clone")
|
||||
{
|
||||
layer = CLONE_LAYER
|
||||
};
|
||||
|
||||
clone.transform.SetParent(source.transform, false);
|
||||
|
||||
SkinnedMeshRenderer cloneRenderer = clone.AddComponent<SkinnedMeshRenderer>();
|
||||
|
||||
// Basic setup
|
||||
cloneRenderer.sharedMaterials = _skinnedCloneMaterials[index];
|
||||
cloneRenderer.shadowCastingMode = ShadowCastingMode.Off;
|
||||
cloneRenderer.probeAnchor = source.probeAnchor;
|
||||
cloneRenderer.sharedMesh = source.sharedMesh;
|
||||
cloneRenderer.rootBone = source.rootBone;
|
||||
cloneRenderer.bones = source.bones;
|
||||
|
||||
#if !UNITY_EDITOR
|
||||
cloneRenderer.localBounds = new Bounds(source.localBounds.center, source.localBounds.size * 2f);
|
||||
#endif
|
||||
|
||||
// Quality settings
|
||||
cloneRenderer.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion;
|
||||
cloneRenderer.allowOcclusionWhenDynamic = false;
|
||||
cloneRenderer.updateWhenOffscreen = false;
|
||||
cloneRenderer.skinnedMotionVectors = false;
|
||||
cloneRenderer.forceMatrixRecalculationPerRender = false;
|
||||
cloneRenderer.quality = SkinQuality.Bone4;
|
||||
|
||||
source.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion;
|
||||
source.allowOcclusionWhenDynamic = false;
|
||||
source.updateWhenOffscreen = false;
|
||||
source.skinnedMotionVectors = false;
|
||||
source.forceMatrixRecalculationPerRender = false;
|
||||
source.quality = SkinQuality.Bone4;
|
||||
|
||||
// Add to clone list
|
||||
_skinnedClones.Add(cloneRenderer);
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_CreateClone.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void CreateMeshClone(int index)
|
||||
{
|
||||
#if ENABLE_PROFILER
|
||||
s_CreateClone.Begin();
|
||||
#endif
|
||||
|
||||
MeshRenderer source = _meshRenderers[index];
|
||||
MeshFilter sourceFilter = _meshFilters[index];
|
||||
|
||||
GameObject clone = new(source.name + "_Clone")
|
||||
{
|
||||
layer = CLONE_LAYER
|
||||
};
|
||||
|
||||
clone.transform.SetParent(source.transform, false);
|
||||
|
||||
MeshRenderer cloneRenderer = clone.AddComponent<MeshRenderer>();
|
||||
MeshFilter cloneFilter = clone.AddComponent<MeshFilter>();
|
||||
|
||||
// Basic setup
|
||||
cloneRenderer.sharedMaterials = _meshCloneMaterials[index];
|
||||
cloneRenderer.shadowCastingMode = ShadowCastingMode.Off;
|
||||
cloneRenderer.probeAnchor = source.probeAnchor;
|
||||
|
||||
#if !UNITY_EDITOR
|
||||
cloneRenderer.localBounds = new Bounds(source.localBounds.center, source.localBounds.size * 2f);
|
||||
#endif
|
||||
|
||||
cloneFilter.sharedMesh = sourceFilter.sharedMesh;
|
||||
|
||||
// Quality settings
|
||||
cloneRenderer.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion;
|
||||
cloneRenderer.allowOcclusionWhenDynamic = false;
|
||||
|
||||
source.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion;
|
||||
source.allowOcclusionWhenDynamic = false;
|
||||
|
||||
// Add to clone lists
|
||||
_meshClones.Add(cloneRenderer);
|
||||
_meshCloneFilters.Add(cloneFilter);
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_CreateClone.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion Initialization
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace NAK.AvatarCloneTest;
|
||||
|
||||
public partial class AvatarClone
|
||||
{
|
||||
#region Render State Management
|
||||
|
||||
private void MyOnPreCull(Camera cam)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// Scene & Preview cameras are not needed
|
||||
if (cam.cameraType != CameraType.Game)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_PreCullUpdate.Begin();
|
||||
#endif
|
||||
|
||||
bool isOurUiCamera = IsUIInternalCamera(cam);
|
||||
bool rendersOurPlayerLayer = CameraRendersPlayerLocalLayer(cam);
|
||||
bool rendersOurCloneLayer = CameraRendersPlayerCloneLayer(cam);
|
||||
|
||||
bool rendersBothPlayerLayers = rendersOurPlayerLayer && rendersOurCloneLayer;
|
||||
|
||||
// Handle shadow casting when camera renders both layers
|
||||
if (!_sourcesSetForShadowCasting
|
||||
&& rendersBothPlayerLayers)
|
||||
{
|
||||
ConfigureSourceShadowCasting(true);
|
||||
_sourcesSetForShadowCasting = true;
|
||||
}
|
||||
else if (_sourcesSetForShadowCasting && !rendersBothPlayerLayers)
|
||||
{
|
||||
ConfigureSourceShadowCasting(false);
|
||||
_sourcesSetForShadowCasting = false;
|
||||
}
|
||||
|
||||
// Handle UI culling for clone layer
|
||||
if (!_clonesSetForUiCulling
|
||||
&& isOurUiCamera && rendersOurCloneLayer)
|
||||
{
|
||||
ConfigureCloneUICulling(true);
|
||||
_clonesSetForUiCulling = true;
|
||||
}
|
||||
else if (_clonesSetForUiCulling)
|
||||
{
|
||||
ConfigureCloneUICulling(false);
|
||||
_clonesSetForUiCulling = false;
|
||||
}
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_PreCullUpdate.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void ConfigureSourceShadowCasting(bool setSourcesToShadowCast)
|
||||
{
|
||||
#if ENABLE_PROFILER
|
||||
s_ConfigureShadowCasting.Begin();
|
||||
#endif
|
||||
|
||||
int currentIndex = 0;
|
||||
int shadowArrayIndex = 0;
|
||||
|
||||
// Handle skinned mesh renderers (always have clones)
|
||||
int skinnedCount = _skinnedRenderers.Count;
|
||||
for (int i = 0; i < skinnedCount; i++, currentIndex++)
|
||||
{
|
||||
if (!_rendererActiveStates[currentIndex]) continue;
|
||||
|
||||
SkinnedMeshRenderer source = _skinnedRenderers[i];
|
||||
|
||||
if (setSourcesToShadowCast)
|
||||
{
|
||||
ShadowCastingMode originalMode = _originalShadowCastingMode[currentIndex] = source.shadowCastingMode;
|
||||
if (originalMode == ShadowCastingMode.Off)
|
||||
source.forceRenderingOff = true;
|
||||
else
|
||||
source.shadowCastingMode = ShadowCastingMode.ShadowsOnly;
|
||||
}
|
||||
else
|
||||
{
|
||||
source.shadowCastingMode = _originalShadowCastingMode[currentIndex];
|
||||
source.forceRenderingOff = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle mesh renderers based on clone setting
|
||||
if (Setting_CloneMeshRenderers)
|
||||
{
|
||||
int meshCount = _meshRenderers.Count;
|
||||
for (int i = 0; i < meshCount; i++, currentIndex++)
|
||||
{
|
||||
if (!_rendererActiveStates[currentIndex]) continue;
|
||||
|
||||
MeshRenderer source = _meshRenderers[i];
|
||||
|
||||
if (setSourcesToShadowCast)
|
||||
{
|
||||
ShadowCastingMode originalMode = _originalShadowCastingMode[currentIndex] = source.shadowCastingMode;
|
||||
if (originalMode == ShadowCastingMode.Off)
|
||||
source.forceRenderingOff = true;
|
||||
else
|
||||
source.shadowCastingMode = ShadowCastingMode.ShadowsOnly;
|
||||
}
|
||||
else
|
||||
{
|
||||
source.shadowCastingMode = _originalShadowCastingMode[currentIndex];
|
||||
source.forceRenderingOff = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// When not cloned, mesh renderers use the shadow casting array
|
||||
int meshCount = _meshRenderers.Count;
|
||||
for (int i = 0; i < meshCount; i++, shadowArrayIndex++, currentIndex++)
|
||||
{
|
||||
if (!_rendererActiveStates[currentIndex]) continue;
|
||||
if (!_sourceShouldBeHiddenFromFPR[shadowArrayIndex]) continue;
|
||||
|
||||
MeshRenderer source = _meshRenderers[i];
|
||||
|
||||
if (setSourcesToShadowCast)
|
||||
{
|
||||
ShadowCastingMode originalMode = _originalShadowCastingMode[currentIndex] = source.shadowCastingMode;
|
||||
if (originalMode == ShadowCastingMode.Off)
|
||||
source.forceRenderingOff = true;
|
||||
else
|
||||
source.shadowCastingMode = ShadowCastingMode.ShadowsOnly;
|
||||
}
|
||||
else
|
||||
{
|
||||
source.shadowCastingMode = _originalShadowCastingMode[currentIndex];
|
||||
source.forceRenderingOff = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle other renderers (never cloned)
|
||||
int otherCount = _otherRenderers.Count;
|
||||
for (int i = 0; i < otherCount; i++, shadowArrayIndex++, currentIndex++)
|
||||
{
|
||||
if (!_rendererActiveStates[currentIndex]) continue;
|
||||
if (!_sourceShouldBeHiddenFromFPR[shadowArrayIndex]) continue;
|
||||
|
||||
Renderer source = _otherRenderers[i];
|
||||
|
||||
if (setSourcesToShadowCast)
|
||||
{
|
||||
ShadowCastingMode originalMode = _originalShadowCastingMode[currentIndex] = source.shadowCastingMode;
|
||||
if (originalMode == ShadowCastingMode.Off)
|
||||
source.forceRenderingOff = true;
|
||||
else
|
||||
source.shadowCastingMode = ShadowCastingMode.ShadowsOnly;
|
||||
}
|
||||
else
|
||||
{
|
||||
source.shadowCastingMode = _originalShadowCastingMode[currentIndex];
|
||||
source.forceRenderingOff = false;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_ConfigureShadowCasting.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void ConfigureCloneUICulling(bool enableCulling)
|
||||
{
|
||||
#if ENABLE_PROFILER
|
||||
s_ConfigureUICulling.Begin();
|
||||
#endif
|
||||
|
||||
// Set the materials to our culling materials
|
||||
int currentIndex = 0;
|
||||
|
||||
int skinnedCount = _skinnedRenderers.Count;
|
||||
for (int i = 0; i < skinnedCount; i++, currentIndex++)
|
||||
{
|
||||
if (!_rendererActiveStates[currentIndex])
|
||||
continue;
|
||||
|
||||
_skinnedClones[i].sharedMaterials = enableCulling ?
|
||||
_skinnedCloneCullingMaterials[i] :
|
||||
_skinnedCloneMaterials[i];
|
||||
}
|
||||
|
||||
if (Setting_CloneMeshRenderers)
|
||||
{
|
||||
int meshCount = _meshRenderers.Count;
|
||||
for (int i = 0; i < meshCount; i++, currentIndex++)
|
||||
{
|
||||
if (!_rendererActiveStates[currentIndex])
|
||||
continue;
|
||||
|
||||
_meshClones[i].sharedMaterials = enableCulling ?
|
||||
_meshCloneCullingMaterials[i] :
|
||||
_meshCloneMaterials[i];
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_ConfigureUICulling.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion Render State Management
|
||||
}
|
156
.Deprecated/AvatarCloneTest/AvatarClone/AvatarClone.StateSync.cs
Normal file
156
.Deprecated/AvatarCloneTest/AvatarClone/AvatarClone.StateSync.cs
Normal file
|
@ -0,0 +1,156 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace NAK.AvatarCloneTest;
|
||||
|
||||
public partial class AvatarClone
|
||||
{
|
||||
#region State Syncing
|
||||
|
||||
private void SyncEnabledState()
|
||||
{
|
||||
#if ENABLE_PROFILER
|
||||
s_CopyEnabledState.Begin();
|
||||
#endif
|
||||
|
||||
int currentIndex = 0;
|
||||
|
||||
// Update skinned mesh renderers
|
||||
int skinnedCount = _skinnedRenderers.Count;
|
||||
for (int i = 0; i < skinnedCount; i++, currentIndex++)
|
||||
{
|
||||
SkinnedMeshRenderer source = _skinnedRenderers[i];
|
||||
_skinnedClones[i].enabled = _rendererActiveStates[currentIndex] = IsRendererActive(source);
|
||||
}
|
||||
|
||||
// Update mesh renderers
|
||||
int meshCount = _meshRenderers.Count;
|
||||
for (int i = 0; i < meshCount; i++, currentIndex++)
|
||||
{
|
||||
MeshRenderer source = _meshRenderers[i];
|
||||
if (Setting_CloneMeshRenderers) _meshClones[i].enabled = _rendererActiveStates[currentIndex] = IsRendererActive(source);
|
||||
else _rendererActiveStates[currentIndex] = IsRendererActive(source);
|
||||
}
|
||||
|
||||
// Update other renderers
|
||||
int otherCount = _otherRenderers.Count;
|
||||
for (int i = 0; i < otherCount; i++, currentIndex++)
|
||||
{
|
||||
Renderer source = _otherRenderers[i];
|
||||
_rendererActiveStates[currentIndex] = IsRendererActive(source);
|
||||
}
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_CopyEnabledState.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void SyncMaterials()
|
||||
{
|
||||
#if ENABLE_PROFILER
|
||||
s_CopyMaterials.Begin();
|
||||
#endif
|
||||
int currentIndex = 0;
|
||||
|
||||
// Sync skinned mesh materials
|
||||
int skinnedCount = _skinnedRenderers.Count;
|
||||
for (int i = 0; i < skinnedCount; i++, currentIndex++)
|
||||
{
|
||||
if (!_rendererActiveStates[currentIndex])
|
||||
continue;
|
||||
|
||||
CopyMaterialsAndProperties(
|
||||
_skinnedRenderers[i],
|
||||
_skinnedClones[i],
|
||||
_propertyBlock,
|
||||
_materialWorkingList,
|
||||
_skinnedCloneMaterials[i]);
|
||||
}
|
||||
|
||||
// Sync mesh materials if enabled
|
||||
if (Setting_CloneMeshRenderers)
|
||||
{
|
||||
int meshCount = _meshRenderers.Count;
|
||||
for (int i = 0; i < meshCount; i++, currentIndex++)
|
||||
{
|
||||
if (!_rendererActiveStates[currentIndex])
|
||||
continue;
|
||||
|
||||
CopyMaterialsAndProperties(
|
||||
_meshRenderers[i],
|
||||
_meshClones[i],
|
||||
_propertyBlock,
|
||||
_materialWorkingList,
|
||||
_meshCloneMaterials[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_CopyMaterials.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void SyncBlendShapes()
|
||||
{
|
||||
#if ENABLE_PROFILER
|
||||
s_CopyBlendShapes.Begin();
|
||||
#endif
|
||||
|
||||
int skinnedCount = _skinnedRenderers.Count;
|
||||
for (int i = 0; i < skinnedCount; i++)
|
||||
{
|
||||
SkinnedMeshRenderer source = _skinnedRenderers[i];
|
||||
if (!_rendererActiveStates[i])
|
||||
continue;
|
||||
|
||||
CopyBlendShapes(
|
||||
source,
|
||||
_skinnedClones[i],
|
||||
_blendShapeWeights[i]);
|
||||
}
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
s_CopyBlendShapes.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void CopyMaterialsAndProperties(
|
||||
Renderer source,
|
||||
Renderer clone,
|
||||
MaterialPropertyBlock propertyBlock,
|
||||
List<Material> workingList,
|
||||
Material[] cloneMaterials)
|
||||
{
|
||||
source.GetSharedMaterials(workingList);
|
||||
|
||||
int matCount = workingList.Count;
|
||||
bool hasChanged = false;
|
||||
|
||||
for (int i = 0; i < matCount; i++)
|
||||
{
|
||||
if (ReferenceEquals(workingList[i], cloneMaterials[i])) continue;
|
||||
cloneMaterials[i] = workingList[i];
|
||||
hasChanged = true;
|
||||
}
|
||||
if (hasChanged) clone.sharedMaterials = cloneMaterials;
|
||||
|
||||
source.GetPropertyBlock(propertyBlock);
|
||||
clone.SetPropertyBlock(propertyBlock);
|
||||
}
|
||||
|
||||
private static void CopyBlendShapes(
|
||||
SkinnedMeshRenderer source,
|
||||
SkinnedMeshRenderer clone,
|
||||
List<float> weights)
|
||||
{
|
||||
int weightCount = weights.Count;
|
||||
for (int i = 0; i < weightCount; i++)
|
||||
{
|
||||
float weight = source.GetBlendShapeWeight(i);
|
||||
// ReSharper disable once CompareOfFloatsByEqualityOperator
|
||||
if (weight == weights[i]) continue; // Halves the work
|
||||
clone.SetBlendShapeWeight(i, weights[i] = weight);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion State Syncing
|
||||
}
|
81
.Deprecated/AvatarCloneTest/AvatarClone/AvatarClone.Util.cs
Normal file
81
.Deprecated/AvatarCloneTest/AvatarClone/AvatarClone.Util.cs
Normal file
|
@ -0,0 +1,81 @@
|
|||
using ABI_RC.Core.Player;
|
||||
using MagicaCloth;
|
||||
using MagicaCloth2;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NAK.AvatarCloneTest;
|
||||
|
||||
public partial class AvatarClone
|
||||
{
|
||||
#region Utilities
|
||||
|
||||
private static bool IsRendererActive(Renderer renderer)
|
||||
=> renderer && renderer.enabled && renderer.gameObject.activeInHierarchy;
|
||||
|
||||
private static bool CameraRendersPlayerLocalLayer(Camera cam)
|
||||
=> (cam.cullingMask & (1 << LOCAL_LAYER)) != 0;
|
||||
|
||||
private static bool CameraRendersPlayerCloneLayer(Camera cam)
|
||||
=> (cam.cullingMask & (1 << CLONE_LAYER)) != 0;
|
||||
|
||||
private static bool IsUIInternalCamera(Camera cam)
|
||||
#if !UNITY_EDITOR
|
||||
=> cam == PlayerSetup.Instance.activeUiCam;
|
||||
#else
|
||||
=> cam.gameObject.layer == 15;
|
||||
#endif
|
||||
|
||||
#endregion Utilities
|
||||
|
||||
#region Magica Cloth Support
|
||||
|
||||
private void SetupMagicaClothSupport()
|
||||
{
|
||||
var magicaCloths1 = GetComponentsInChildren<BaseCloth>(true);
|
||||
foreach (BaseCloth magicaCloth1 in magicaCloths1)
|
||||
magicaCloth1.SetCullingMode(PhysicsTeam.TeamCullingMode.Off);
|
||||
|
||||
var magicaCloths2 = base.GetComponentsInChildren<MagicaCloth2.MagicaCloth>(true);
|
||||
foreach (MagicaCloth2.MagicaCloth magicaCloth2 in magicaCloths2)
|
||||
magicaCloth2.serializeData.cullingSettings.cameraCullingMode = CullingSettings.CameraCullingMode.AnimatorLinkage;
|
||||
}
|
||||
|
||||
public void OnMagicaClothMeshSwapped(Renderer render, Mesh newMesh)
|
||||
{
|
||||
switch (render)
|
||||
{
|
||||
case MeshRenderer mesh:
|
||||
{
|
||||
int index = _meshRenderers.IndexOf(mesh);
|
||||
if (index != -1) _meshCloneFilters[index].sharedMesh = newMesh;
|
||||
break;
|
||||
}
|
||||
case SkinnedMeshRenderer skinned:
|
||||
{
|
||||
int index = _skinnedRenderers.IndexOf(skinned);
|
||||
if (index != -1)
|
||||
{
|
||||
// Copy the mesh
|
||||
_skinnedClones[index].sharedMesh = newMesh;
|
||||
|
||||
// Copy appended bones if count is different
|
||||
var cloneBones = _skinnedClones[index].bones; // alloc
|
||||
var sourceBones = skinned.bones; // alloc
|
||||
|
||||
int cloneBoneCount = cloneBones.Length;
|
||||
int sourceBoneCount = sourceBones.Length;
|
||||
if (cloneBoneCount != sourceBoneCount)
|
||||
{
|
||||
// Copy the new bones only
|
||||
Array.Resize(ref cloneBones, sourceBoneCount);
|
||||
for (int i = cloneBoneCount; i < sourceBoneCount; i++) cloneBones[i] = sourceBones[i];
|
||||
_skinnedClones[index].bones = cloneBones;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Magica Cloth Support
|
||||
}
|
147
.Deprecated/AvatarCloneTest/AvatarClone/AvatarClone.cs
Normal file
147
.Deprecated/AvatarCloneTest/AvatarClone/AvatarClone.cs
Normal file
|
@ -0,0 +1,147 @@
|
|||
using NAK.AvatarCloneTest;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace NAK.AvatarCloneTest;
|
||||
|
||||
public partial class AvatarClone : MonoBehaviour
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const int LOCAL_LAYER = 8;
|
||||
private const int CLONE_LAYER = 9;
|
||||
|
||||
#endregion Constants
|
||||
|
||||
#region Profiler Markers
|
||||
|
||||
#if ENABLE_PROFILER
|
||||
private static readonly ProfilerMarker s_CopyEnabledState = new($"{nameof(AvatarClone)}.{nameof(SyncEnabledState)}");
|
||||
private static readonly ProfilerMarker s_CopyMaterials = new($"{nameof(AvatarClone)}.{nameof(CopyMaterialsAndProperties)}");
|
||||
private static readonly ProfilerMarker s_CopyBlendShapes = new($"{nameof(AvatarClone)}.{nameof(CopyBlendShapes)}");
|
||||
private static readonly ProfilerMarker s_InitializeData = new($"{nameof(AvatarClone)}.Initialize");
|
||||
private static readonly ProfilerMarker s_UpdateExclusions = new($"{nameof(AvatarClone)}.{nameof(HandleExclusionUpdate)}");
|
||||
private static readonly ProfilerMarker s_CollectExclusionData = new($"{nameof(AvatarClone)}.{nameof(CollectExclusionData)}");
|
||||
private static readonly ProfilerMarker s_HandleBoneUpdates = new($"{nameof(AvatarClone)}.{nameof(UpdateSkinnedMeshBones)}");
|
||||
private static readonly ProfilerMarker s_PreCullUpdate = new($"{nameof(AvatarClone)}.{nameof(MyOnPreCull)}");
|
||||
private static readonly ProfilerMarker s_ConfigureShadowCasting = new($"{nameof(AvatarClone)}.{nameof(ConfigureSourceShadowCasting)}");
|
||||
private static readonly ProfilerMarker s_ConfigureUICulling = new($"{nameof(AvatarClone)}.{nameof(ConfigureCloneUICulling)}");
|
||||
private static readonly ProfilerMarker s_AddRenderer = new($"{nameof(AvatarClone)}.AddRenderer");
|
||||
private static readonly ProfilerMarker s_CreateClone = new($"{nameof(AvatarClone)}.CreateClone");
|
||||
#endif
|
||||
|
||||
#endregion Profiler Markers
|
||||
|
||||
#region Settings
|
||||
|
||||
public bool Setting_CloneMeshRenderers;
|
||||
public bool Setting_CopyMaterials = true;
|
||||
public bool Setting_CopyBlendShapes = true;
|
||||
|
||||
#endregion Settings
|
||||
|
||||
#region Source Collections - Cloned Renderers
|
||||
|
||||
// Skinned mesh renderers (always cloned)
|
||||
private List<SkinnedMeshRenderer> _skinnedRenderers;
|
||||
private List<List<float>> _blendShapeWeights;
|
||||
|
||||
// Mesh renderers (optionally cloned)
|
||||
private List<MeshRenderer> _meshRenderers;
|
||||
private List<MeshFilter> _meshFilters;
|
||||
|
||||
#endregion Source Collections - Cloned Renderers
|
||||
|
||||
#region Source Collections - Non-Cloned Renderers
|
||||
|
||||
// All other renderers (never cloned)
|
||||
private List<Renderer> _otherRenderers;
|
||||
|
||||
// True if source renderer should hide. False if source renderer should show.
|
||||
// Only used for non-cloned renderers (MeshRenderers and other Renderers).
|
||||
private bool[] _sourceShouldBeHiddenFromFPR;
|
||||
// Three states: On, ShadowsOnly, Off
|
||||
private ShadowCastingMode[] _originalShadowCastingMode;
|
||||
|
||||
#endregion Source Collections - Non-Cloned Renderers
|
||||
|
||||
#region Clone Collections
|
||||
|
||||
// Skinned mesh clones
|
||||
private List<SkinnedMeshRenderer> _skinnedClones;
|
||||
private List<Material[]> _skinnedCloneMaterials;
|
||||
private List<Material[]> _skinnedCloneCullingMaterials;
|
||||
|
||||
// Mesh clones (optional)
|
||||
private List<MeshRenderer> _meshClones;
|
||||
private List<MeshFilter> _meshCloneFilters;
|
||||
private List<Material[]> _meshCloneMaterials;
|
||||
private List<Material[]> _meshCloneCullingMaterials;
|
||||
|
||||
#endregion Clone Collections
|
||||
|
||||
#region Shared Resources
|
||||
|
||||
private List<Material> _materialWorkingList; // Used for GetSharedMaterials
|
||||
private MaterialPropertyBlock _propertyBlock;
|
||||
|
||||
#endregion Shared Resources
|
||||
|
||||
#region State
|
||||
|
||||
private bool _sourcesSetForShadowCasting;
|
||||
private bool _clonesSetForUiCulling;
|
||||
private bool[] _rendererActiveStates;
|
||||
|
||||
#endregion State
|
||||
|
||||
#region Unity Events
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Setting_CloneMeshRenderers = AvatarCloneTestMod.EntryCloneMeshRenderers.Value;
|
||||
|
||||
InitializeCollections();
|
||||
CollectRenderers();
|
||||
CreateClones();
|
||||
AddExclusionToHeadIfNeeded();
|
||||
InitializeExclusions();
|
||||
SetupMagicaClothSupport();
|
||||
|
||||
// bool animatesClone = transform.Find("[ExplicitlyAnimatesVisualClones]") != null;
|
||||
// Setting_CopyMaterials = !animatesClone;
|
||||
// Setting_CopyBlendShapes = !animatesClone;
|
||||
// Animator animator = GetComponent<Animator>();
|
||||
// if (animator && animatesClone) animator.Rebind();
|
||||
|
||||
// Likely a Unity bug with where we can touch shadowCastingMode & forceRenderingOff
|
||||
#if !UNITY_EDITOR
|
||||
Camera.onPreCull += MyOnPreCull;
|
||||
#else
|
||||
Camera.onPreRender += MyOnPreCull;
|
||||
#endif
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
SyncEnabledState();
|
||||
|
||||
if (Setting_CopyMaterials && AvatarCloneTestMod.EntryCopyMaterials.Value)
|
||||
SyncMaterials();
|
||||
|
||||
if (Setting_CopyBlendShapes && AvatarCloneTestMod.EntryCopyBlendShapes.Value)
|
||||
SyncBlendShapes();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
// Likely a Unity bug with where we can touch shadowCastingMode & forceRenderingOff
|
||||
#if !UNITY_EDITOR
|
||||
Camera.onPreCull -= MyOnPreCull;
|
||||
#else
|
||||
Camera.onPreRender -= MyOnPreCull;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion Unity Events
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
using ABI.CCK.Components;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NAK.AvatarCloneTest;
|
||||
|
||||
public class AvatarCloneExclusion : IExclusionBehaviour
|
||||
{
|
||||
public readonly Dictionary<SkinnedMeshRenderer, List<int>> skinnedToBoneIndex = new();
|
||||
public readonly List<Transform> affectedTransforms = new();
|
||||
public readonly List<Renderer> affectedRenderers = new();
|
||||
public HashSet<Transform> affectedTransformSet = new();
|
||||
|
||||
private readonly AvatarClone _cloneSystem;
|
||||
private readonly Transform _target;
|
||||
internal Transform _shrinkBone;
|
||||
|
||||
public bool isImmuneToGlobalState { get; set; }
|
||||
|
||||
public AvatarCloneExclusion(AvatarClone cloneSystem, Transform target)
|
||||
{
|
||||
_cloneSystem = cloneSystem;
|
||||
_target = target;
|
||||
}
|
||||
|
||||
public void UpdateExclusions(bool isShown, bool shrinkToZero)
|
||||
{
|
||||
if (_shrinkBone == null)
|
||||
{
|
||||
// Create shrink bone parented directly to target
|
||||
_shrinkBone = new GameObject($"{_target.name}_Shrink").transform;
|
||||
_shrinkBone.SetParent(_target, false);
|
||||
}
|
||||
// Set scale based on shrink mode
|
||||
_shrinkBone.localScale = shrinkToZero ? Vector3.zero : Vector3.positiveInfinity;
|
||||
|
||||
// Replace the bone references with the shrink bone for the indicies we modify
|
||||
_cloneSystem.HandleExclusionUpdate(this, isShown);
|
||||
}
|
||||
}
|
9
.Deprecated/AvatarCloneTest/AvatarCloneTest.csproj
Normal file
9
.Deprecated/AvatarCloneTest/AvatarCloneTest.csproj
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<RootNamespace>LocalCloneFix</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<DefineConstants>TRACE;TRACE;</DefineConstants>
|
||||
</PropertyGroup>
|
||||
</Project>
|
81
.Deprecated/AvatarCloneTest/Main.cs
Normal file
81
.Deprecated/AvatarCloneTest/Main.cs
Normal file
|
@ -0,0 +1,81 @@
|
|||
using ABI_RC.Core;
|
||||
using ABI_RC.Core.EventSystem;
|
||||
using ABI_RC.Core.Savior;
|
||||
using MelonLoader;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NAK.AvatarCloneTest;
|
||||
|
||||
public class AvatarCloneTestMod : MelonMod
|
||||
{
|
||||
#region Melon Preferences
|
||||
|
||||
private static readonly MelonPreferences_Category Category =
|
||||
MelonPreferences.CreateCategory(nameof(AvatarCloneTest));
|
||||
|
||||
internal static readonly MelonPreferences_Entry<bool> EntryUseAvatarCloneTest =
|
||||
Category.CreateEntry("use_avatar_clone_test", true,
|
||||
"Use Avatar Clone", description: "Uses the Avatar Clone setup for the local avatar.");
|
||||
|
||||
internal static readonly MelonPreferences_Entry<bool> EntryCloneMeshRenderers =
|
||||
Category.CreateEntry("clone_mesh_renderers", false,
|
||||
"Clone Mesh Renderers", description: "Clones the mesh renderers from the original avatar to the clone.");
|
||||
|
||||
internal static readonly MelonPreferences_Entry<bool> EntryCopyBlendShapes =
|
||||
Category.CreateEntry("copy_blend_shapes", true,
|
||||
"Copy Blend Shapes", description: "Copies the blend shapes from the original avatar to the clone.");
|
||||
|
||||
internal static readonly MelonPreferences_Entry<bool> EntryCopyMaterials =
|
||||
Category.CreateEntry("copy_materials", true,
|
||||
"Copy Materials", description: "Copies the materials from the original avatar to the clone.");
|
||||
|
||||
#endregion Melon Preferences
|
||||
|
||||
#region Melon Events
|
||||
|
||||
public override void OnInitializeMelon()
|
||||
{
|
||||
ApplyPatches(typeof(Patches)); // slapped together a fix cause HarmonyInstance.Patch was null ref for no reason?
|
||||
}
|
||||
|
||||
public override void OnUpdate()
|
||||
{
|
||||
// press f1 to find all cameras that arent tagged main and set them tno not render CVRLayers.PlayerClone
|
||||
if (Input.GetKeyDown(KeyCode.F1))
|
||||
{
|
||||
foreach (var camera in UnityEngine.Object.FindObjectsOfType<UnityEngine.Camera>())
|
||||
{
|
||||
if (camera.tag != "MainCamera")
|
||||
{
|
||||
camera.cullingMask &= ~(1 << CVRLayers.PlayerClone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if pressing ctrl + r, reload avatar
|
||||
if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.R))
|
||||
{
|
||||
var player = MetaPort.Instance.currentAvatarGuid;
|
||||
AssetManagement.Instance.LoadLocalAvatar(player);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Melon Events
|
||||
|
||||
#region Melon Mod Utilities
|
||||
|
||||
private void ApplyPatches(Type type)
|
||||
{
|
||||
try
|
||||
{
|
||||
HarmonyInstance.PatchAll(type);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LoggerInstance.Msg($"Failed while patching {type.Name}!");
|
||||
LoggerInstance.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Melon Mod Utilities
|
||||
}
|
22
.Deprecated/AvatarCloneTest/Patches.cs
Normal file
22
.Deprecated/AvatarCloneTest/Patches.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
using ABI_RC.Core;
|
||||
using ABI_RC.Core.Player;
|
||||
using ABI_RC.Core.Player.TransformHider;
|
||||
using ABI_RC.Core.Savior;
|
||||
using ABI_RC.Systems.Camera;
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NAK.AvatarCloneTest;
|
||||
|
||||
public static class Patches
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(TransformHiderUtils), nameof(TransformHiderUtils.SetupAvatar))]
|
||||
private static bool OnSetupAvatar(GameObject avatar)
|
||||
{
|
||||
if (!AvatarCloneTestMod.EntryUseAvatarCloneTest.Value) return true;
|
||||
avatar.AddComponent<AvatarClone>();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
32
.Deprecated/AvatarCloneTest/Properties/AssemblyInfo.cs
Normal file
32
.Deprecated/AvatarCloneTest/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,32 @@
|
|||
using MelonLoader;
|
||||
using NAK.AvatarCloneTest.Properties;
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyVersion(AssemblyInfoParams.Version)]
|
||||
[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)]
|
||||
[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)]
|
||||
[assembly: AssemblyTitle(nameof(NAK.AvatarCloneTest))]
|
||||
[assembly: AssemblyCompany(AssemblyInfoParams.Author)]
|
||||
[assembly: AssemblyProduct(nameof(NAK.AvatarCloneTest))]
|
||||
|
||||
[assembly: MelonInfo(
|
||||
typeof(NAK.AvatarCloneTest.AvatarCloneTestMod),
|
||||
nameof(NAK.AvatarCloneTest),
|
||||
AssemblyInfoParams.Version,
|
||||
AssemblyInfoParams.Author,
|
||||
downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/AvatarCloneTest"
|
||||
)]
|
||||
|
||||
[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")]
|
||||
[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
||||
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
|
||||
[assembly: MelonColor(255, 246, 25, 99)] // red-pink
|
||||
[assembly: MelonAuthorColor(255, 158, 21, 32)] // red
|
||||
[assembly: HarmonyDontPatchAll]
|
||||
|
||||
namespace NAK.AvatarCloneTest.Properties;
|
||||
internal static class AssemblyInfoParams
|
||||
{
|
||||
public const string Version = "1.0.3";
|
||||
public const string Author = "NotAKidoS";
|
||||
}
|
18
.Deprecated/AvatarCloneTest/README.md
Normal file
18
.Deprecated/AvatarCloneTest/README.md
Normal file
|
@ -0,0 +1,18 @@
|
|||
# VisualCloneFix
|
||||
|
||||
Fixes the Visual Clone system and allows you to use it again.
|
||||
|
||||
Using the Visual Clone should be faster than the default Head Hiding & Shadow Clones, but will add a longer hitch on initial avatar load.
|
||||
|
||||
**NOTE:** The Visual Clone is still an experimental feature that was temporarily removed in [ChilloutVR 2024r175 Hotfix 1](https://abinteractive.net/blog/chilloutvr_2024r175_hotfix_1), so there may be bugs or issues with it.
|
||||
|
||||
---
|
||||
|
||||
Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI.
|
||||
https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games
|
||||
|
||||
> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive.
|
||||
|
||||
> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use.
|
||||
|
||||
> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive.
|
23
.Deprecated/AvatarCloneTest/format.json
Normal file
23
.Deprecated/AvatarCloneTest/format.json
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"_id": 221,
|
||||
"name": "VisualCloneFix",
|
||||
"modversion": "1.0.1",
|
||||
"gameversion": "2024r175",
|
||||
"loaderversion": "0.6.1",
|
||||
"modtype": "Mod",
|
||||
"author": "NotAKidoS",
|
||||
"description": "Fixes the Visual Clone system and allows you to use it again.\n\nUsing the Visual Clone should be faster than the default Head Hiding & Shadow Clones, but will add a longer hitch on initial avatar load.\n\n**NOTE:** The Visual Clone is still an experimental feature that was temporarily removed in [ChilloutVR 2024r175 Hotfix 1](https://abinteractive.net/blog/chilloutvr_2024r175_hotfix_1), so there may be bugs or issues with it.",
|
||||
"searchtags": [
|
||||
"visual",
|
||||
"clone",
|
||||
"head",
|
||||
"hiding"
|
||||
],
|
||||
"requirements": [
|
||||
"None"
|
||||
],
|
||||
"downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r36/VisualCloneFix.dll",
|
||||
"sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/VisualCloneFix/",
|
||||
"changelog": "- Fixed FPRExclusions IsShown state being inverted when toggled.\n- Fixed head FPRExclusion generation not checking for existing exclusion.\n- Sped up FindExclusionVertList by 100x by not being an idiot. This heavily reduces avatar hitch with Visual Clone active.",
|
||||
"embedcolor": "#f61963"
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue