diff --git a/AvatarCloneTest/AvatarClone/AvatarClone.API.cs b/AvatarCloneTest/AvatarClone/AvatarClone.API.cs deleted file mode 100644 index 89835bd..0000000 --- a/AvatarCloneTest/AvatarClone/AvatarClone.API.cs +++ /dev/null @@ -1,68 +0,0 @@ -using UnityEngine; - -namespace NAK.AvatarCloneTest; - -public partial class AvatarClone -{ - #region Public API Methods - - /// - /// Sets whether the specific renderer requires additional runtime checks when copying to the clone. - /// For example, Magica Cloth modifies the sharedMesh & bones of the renderer at runtime. This is not needed - /// for most renderers, so copying for all renderers would be inefficient. - /// - public void SetRendererNeedsAdditionalChecks(Renderer rend, bool needsChecks) - { - switch (rend) - { - case MeshRenderer meshRenderer: - { - int index = _standardRenderers.IndexOf(meshRenderer); - if (index == -1) return; - - if (needsChecks && !_standardRenderersNeedingChecks.Contains(index)) - { - int insertIndex = _standardRenderersNeedingChecks.Count; - _standardRenderersNeedingChecks.Add(index); - _cachedSharedMeshes.Insert(insertIndex, null); - } - else if (!needsChecks) - { - int removeIndex = _standardRenderersNeedingChecks.IndexOf(index); - if (removeIndex != -1) - { - _standardRenderersNeedingChecks.RemoveAt(removeIndex); - _cachedSharedMeshes.RemoveAt(removeIndex); - } - } - return; - } - case SkinnedMeshRenderer skinnedRenderer: - { - int index = _skinnedRenderers.IndexOf(skinnedRenderer); - if (index == -1) return; - - if (needsChecks && !_skinnedRenderersNeedingChecks.Contains(index)) - { - int insertIndex = _skinnedRenderersNeedingChecks.Count; - _skinnedRenderersNeedingChecks.Add(index); - _cachedSharedMeshes.Insert(_standardRenderersNeedingChecks.Count + insertIndex, null); - _cachedSkinnedBoneCounts.Add(0); - } - else if (!needsChecks) - { - int removeIndex = _skinnedRenderersNeedingChecks.IndexOf(index); - if (removeIndex != -1) - { - _skinnedRenderersNeedingChecks.RemoveAt(removeIndex); - _cachedSharedMeshes.RemoveAt(_standardRenderersNeedingChecks.Count + removeIndex); - _cachedSkinnedBoneCounts.RemoveAt(removeIndex); - } - } - break; - } - } - } - - #endregion Public API Methods -} \ No newline at end of file diff --git a/AvatarCloneTest/AvatarClone/AvatarClone.Clones.cs b/AvatarCloneTest/AvatarClone/AvatarClone.Clones.cs deleted file mode 100644 index 8fb54ec..0000000 --- a/AvatarCloneTest/AvatarClone/AvatarClone.Clones.cs +++ /dev/null @@ -1,103 +0,0 @@ -using ABI_RC.Core; -using UnityEngine; -using UnityEngine.Rendering; - -namespace NAK.AvatarCloneTest; - -public partial class AvatarClone -{ - #region Clone Creation - - private void CreateClones() - { - int standardCount = _standardRenderers.Count; - _standardClones = new List(standardCount); - _standardCloneFilters = new List(standardCount); - for (int i = 0; i < standardCount; i++) CreateStandardClone(i); - - int skinnedCount = _skinnedRenderers.Count; - _skinnedClones = new List(skinnedCount); - for (int i = 0; i < skinnedCount; i++) CreateSkinnedClone(i); - } - - private void CreateStandardClone(int index) - { - MeshRenderer sourceRenderer = _standardRenderers[index]; - MeshFilter sourceFilter = _standardFilters[index]; - - GameObject go = new(sourceRenderer.name + "_VisualClone") - { - layer = CVRLayers.PlayerClone - }; - - go.transform.SetParent(sourceRenderer.transform, false); - //go.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); - - MeshRenderer cloneRenderer = go.AddComponent(); - MeshFilter cloneFilter = go.AddComponent(); - - // Initial setup - cloneRenderer.sharedMaterials = sourceRenderer.sharedMaterials; - cloneRenderer.shadowCastingMode = ShadowCastingMode.Off; - cloneRenderer.probeAnchor = sourceRenderer.probeAnchor; - cloneRenderer.localBounds = new Bounds(Vector3.zero, Vector3.positiveInfinity); - cloneFilter.sharedMesh = sourceFilter.sharedMesh; - - // Optimizations to enforce - cloneRenderer.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion; - cloneRenderer.allowOcclusionWhenDynamic = false; - - // Optimizations to enforce - sourceRenderer.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion; - sourceRenderer.allowOcclusionWhenDynamic = false; - - _standardClones.Add(cloneRenderer); - _standardCloneFilters.Add(cloneFilter); - } - - private void CreateSkinnedClone(int index) - { - SkinnedMeshRenderer source = _skinnedRenderers[index]; - - GameObject go = new(source.name + "_VisualClone") - { - layer = CVRLayers.PlayerClone - }; - - go.transform.SetParent(source.transform, false); - //go.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); - - SkinnedMeshRenderer clone = go.AddComponent(); - - // Initial setup - clone.sharedMaterials = source.sharedMaterials; - clone.shadowCastingMode = ShadowCastingMode.Off; - clone.probeAnchor = source.probeAnchor; - clone.localBounds = new Bounds(Vector3.zero, Vector3.positiveInfinity); - clone.sharedMesh = source.sharedMesh; - clone.rootBone = source.rootBone; - clone.bones = source.bones; - clone.quality = source.quality; - clone.updateWhenOffscreen = source.updateWhenOffscreen; - - // Optimizations to enforce - clone.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion; - clone.allowOcclusionWhenDynamic = false; - clone.updateWhenOffscreen = false; - clone.skinnedMotionVectors = false; - clone.forceMatrixRecalculationPerRender = false; - clone.quality = SkinQuality.Bone4; - - // Optimizations to enforce - source.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion; - source.allowOcclusionWhenDynamic = false; - source.updateWhenOffscreen = false; - source.skinnedMotionVectors = false; - source.forceMatrixRecalculationPerRender = false; - source.quality = SkinQuality.Bone4; - - _skinnedClones.Add(clone); - } - - #endregion Clone Creation -} \ No newline at end of file diff --git a/AvatarCloneTest/AvatarClone/AvatarClone.Exclusion.cs b/AvatarCloneTest/AvatarClone/AvatarClone.Exclusion.cs deleted file mode 100644 index d5136e3..0000000 --- a/AvatarCloneTest/AvatarClone/AvatarClone.Exclusion.cs +++ /dev/null @@ -1,141 +0,0 @@ -using ABI.CCK.Components; -using UnityEngine; - -namespace NAK.AvatarCloneTest; - -public partial class AvatarClone -{ - private readonly Dictionary> _exclusionDirectRenderers = new(); - private readonly Dictionary> _exclusionControlledBones = new(); - - private void InitializeExclusions() - { - // Add head exclusion for humanoid avatars if not present - var animator = GetComponent(); - if (animator != null && animator.isHuman) - { - var headBone = animator.GetBoneTransform(HumanBodyBones.Head); - if (headBone != null && headBone.GetComponent() == null) - { - var exclusion = headBone.gameObject.AddComponent(); - exclusion.isShown = false; - exclusion.target = headBone; - exclusion.shrinkToZero = true; - } - } - - // Process existing exclusions bottom-up - var exclusions = GetComponentsInChildren(true); - - for (int i = exclusions.Length - 1; i >= 0; i--) - { - var exclusion = exclusions[i]; - if (exclusion.target == null) - exclusion.target = exclusion.transform; - - // Skip invalid exclusions or already processed targets - if (exclusion.target == null || _exclusionDirectRenderers.ContainsKey(exclusion.target)) - { - Destroy(exclusion); - continue; - } - - // Initialize data for this exclusion - _exclusionDirectRenderers[exclusion.target] = new HashSet(); - _exclusionControlledBones[exclusion.target] = new HashSet(); - - // Set up our behaviour - exclusion.behaviour = new AvatarCloneExclusion(this, exclusion.target); - - // Collect affected renderers and bones - CollectExclusionData(exclusion.target); - - // Initial update - exclusion.UpdateExclusions(); - } - } - - private void CollectExclusionData(Transform target) - { - var stack = new Stack(); - stack.Push(target); - - while (stack.Count > 0) - { - var current = stack.Pop(); - - // Skip if this transform belongs to another exclusion - if (current != target && current.GetComponent() != null) - continue; - - _exclusionControlledBones[target].Add(current); - - // Add renderers that will need their clone visibility toggled - foreach (var renderer in current.GetComponents()) - { - // Find corresponding clone renderer - if (renderer is MeshRenderer meshRenderer) - { - int index = _standardRenderers.IndexOf(meshRenderer); - if (index != -1) - _exclusionDirectRenderers[target].Add(_standardClones[index]); - } - else if (renderer is SkinnedMeshRenderer skinnedRenderer) - { - int index = _skinnedRenderers.IndexOf(skinnedRenderer); - if (index != -1) - _exclusionDirectRenderers[target].Add(_skinnedClones[index]); - } - } - - // Add children to stack - foreach (Transform child in current) - { - stack.Push(child); - } - } - } - - public void HandleExclusionUpdate(Transform target, Transform shrinkBone, bool isShown) - { - if (!_exclusionDirectRenderers.TryGetValue(target, out var directCloneRenderers) || - !_exclusionControlledBones.TryGetValue(target, out var controlledBones)) - return; - - // Handle direct clone renderers - foreach (var cloneRenderer in directCloneRenderers) - { - cloneRenderer.enabled = isShown; - } - - // Update bone references in clone renderers - int cloneCount = _skinnedClones.Count; - var cloneRenderers = _skinnedClones; - var sourceRenderers = _skinnedRenderers; - - for (int i = 0; i < cloneCount; i++) - { - var clone = cloneRenderers[i]; - var source = sourceRenderers[i]; - var sourceBones = source.bones; - var cloneBones = clone.bones; - int boneCount = cloneBones.Length; - bool needsUpdate = false; - - for (int j = 0; j < boneCount; j++) - { - // Check if this bone is in our controlled set - if (controlledBones.Contains(sourceBones[j])) - { - cloneBones[j] = isShown ? sourceBones[j] : shrinkBone; - needsUpdate = true; - } - } - - if (needsUpdate) - { - clone.bones = cloneBones; - } - } - } -} \ No newline at end of file diff --git a/AvatarCloneTest/AvatarClone/AvatarClone.Fields.cs b/AvatarCloneTest/AvatarClone/AvatarClone.Fields.cs deleted file mode 100644 index 0ba69b0..0000000 --- a/AvatarCloneTest/AvatarClone/AvatarClone.Fields.cs +++ /dev/null @@ -1,67 +0,0 @@ -using UnityEngine; - -namespace NAK.AvatarCloneTest; - -public partial class AvatarClone -{ - #region Profile Markers -//#if UNITY_EDITOR - private static readonly UnityEngine.Profiling.CustomSampler s_CopyMaterials = - UnityEngine.Profiling.CustomSampler.Create("AvatarClone2.CopyMaterials"); - private static readonly UnityEngine.Profiling.CustomSampler s_CopyBlendShapes = - UnityEngine.Profiling.CustomSampler.Create("AvatarClone2.CopyBlendShapes"); - private static readonly UnityEngine.Profiling.CustomSampler s_CopyMeshes = - UnityEngine.Profiling.CustomSampler.Create("AvatarClone2.CopyMeshes"); - - private static readonly UnityEngine.Profiling.CustomSampler s_MyOnPreRender = - UnityEngine.Profiling.CustomSampler.Create("AvatarClone2.MyOnPreRender"); - private static readonly UnityEngine.Profiling.CustomSampler s_SetShadowsOnly = - UnityEngine.Profiling.CustomSampler.Create("AvatarClone2.SetShadowsOnly"); - private static readonly UnityEngine.Profiling.CustomSampler s_UndoShadowsOnly = - UnityEngine.Profiling.CustomSampler.Create("AvatarClone2.UndoShadowsOnly"); - private static readonly UnityEngine.Profiling.CustomSampler s_SetUiCulling = - UnityEngine.Profiling.CustomSampler.Create("AvatarClone2.SetUiCulling"); - private static readonly UnityEngine.Profiling.CustomSampler s_UndoUiCulling = - UnityEngine.Profiling.CustomSampler.Create("AvatarClone2.UndoUiCulling"); - -//#endif - #endregion Profile Markers - - #region Source Renderers - private List _standardRenderers; - private List _standardFilters; - private List _skinnedRenderers; - private List _allSourceRenderers; // For shadow casting only - #endregion Source Renderers - - #region Clone Renderers - private List _standardClones; - private List _standardCloneFilters; - private List _skinnedClones; - #endregion Clone Renderers - - #region Dynamic Check Lists - private List _standardRenderersNeedingChecks; // Stores indices into _standardRenderers - private List _skinnedRenderersNeedingChecks; // Stores indices into _skinnedRenderers - private List _cachedSkinnedBoneCounts; // So we don't copy the bones unless they've changed - private List _cachedSharedMeshes; // So we don't copy the mesh unless it's changed - #endregion Dynamic Check Lists - - #region Material Data - private List _localMaterials; - private List _cullingMaterials; - private List _mainMaterials; - private MaterialPropertyBlock _propertyBlock; - #endregion Material Data - - #region Blend Shape Data - private List> _blendShapeWeights; - #endregion Blend Shape Data - - #region Shadow and UI Culling Settings - private bool _uiCullingActive; - private bool _shadowsOnlyActive; - private bool[] _originallyHadShadows; - private bool[] _originallyWasEnabled; - #endregion Shadow and UI Culling Settings -} \ No newline at end of file diff --git a/AvatarCloneTest/AvatarClone/AvatarClone.Init.cs b/AvatarCloneTest/AvatarClone/AvatarClone.Init.cs deleted file mode 100644 index 41bd84b..0000000 --- a/AvatarCloneTest/AvatarClone/AvatarClone.Init.cs +++ /dev/null @@ -1,128 +0,0 @@ -using ABI_RC.Core.Player.ShadowClone; -using UnityEngine; - -namespace NAK.AvatarCloneTest; - -public partial class AvatarClone -{ - #region Initialization - - private void InitializeCollections() - { - _standardRenderers = new List(); - _standardFilters = new List(); - _skinnedRenderers = new List(); - _allSourceRenderers = new List(); - - _standardClones = new List(); - _standardCloneFilters = new List(); - _skinnedClones = new List(); - - _standardRenderersNeedingChecks = new List(); - _skinnedRenderersNeedingChecks = new List(); - _cachedSkinnedBoneCounts = new List(); - _cachedSharedMeshes = new List(); - - _localMaterials = new List(); - _cullingMaterials = new List(); - _mainMaterials = new List(); - _propertyBlock = new MaterialPropertyBlock(); - - _blendShapeWeights = new List>(); - } - - private void InitializeRenderers() - { - var renderers = GetComponentsInChildren(true); - - // Pre-size lists based on found renderers - // _standardRenderers.Capacity = renderers.Length; - // _standardFilters.Capacity = renderers.Length; - // _skinnedRenderers.Capacity = renderers.Length; - // _allSourceRenderers.Capacity = renderers.Length; - - // Sort renderers into their respective lists - foreach (Renderer render in renderers) - { - _allSourceRenderers.Add(render); - - switch (render) - { - case MeshRenderer meshRenderer: - { - MeshFilter filter = meshRenderer.GetComponent(); - if (filter != null && filter.sharedMesh != null) - { - _standardRenderers.Add(meshRenderer); - _standardFilters.Add(filter); - } - break; - } - case SkinnedMeshRenderer skinnedRenderer: - { - if (skinnedRenderer.sharedMesh != null) _skinnedRenderers.Add(skinnedRenderer); - break; - } - } - } - } - - private void SetupMaterialsAndBlendShapes() - { - // Cache counts - int standardCount = _standardRenderers.Count; - int skinnedCount = _skinnedRenderers.Count; - var standardRenderers = _standardRenderers; - var skinnedRenderers = _skinnedRenderers; - var localMats = _localMaterials; - var cullingMats = _cullingMaterials; - var blendWeights = _blendShapeWeights; - - // Setup standard renderer materials - for (int i = 0; i < standardCount; i++) - { - MeshRenderer render = standardRenderers[i]; - int matCount = render.sharedMaterials.Length; - - // Local materials array - var localMatArray = new Material[matCount]; - for (int j = 0; j < matCount; j++) localMatArray[j] = render.sharedMaterials[j]; - localMats.Add(localMatArray); - - // Culling materials array - var cullingMatArray = new Material[matCount]; - for (int j = 0; j < matCount; j++) cullingMatArray[j] = ShadowCloneUtils.cullingMaterial; - cullingMats.Add(cullingMatArray); - } - - // Setup skinned renderer materials and blend shapes - for (int i = 0; i < skinnedCount; i++) - { - SkinnedMeshRenderer render = skinnedRenderers[i]; - int matCount = render.sharedMaterials.Length; - - // Local materials array - var localMatArray = new Material[matCount]; - for (int j = 0; j < matCount; j++) localMatArray[j] = render.sharedMaterials[j]; - localMats.Add(localMatArray); - - // Culling materials array - var cullingMatArray = new Material[matCount]; - for (int j = 0; j < matCount; j++) cullingMatArray[j] = ShadowCloneUtils.cullingMaterial; - cullingMats.Add(cullingMatArray); - - // Blend shape weights - int blendShapeCount = render.sharedMesh.blendShapeCount; - var weights = new List(blendShapeCount); - for (int j = 0; j < blendShapeCount; j++) weights.Add(0f); - blendWeights.Add(weights); - } - - // Initialize renderer state arrays - int totalRenderers = _allSourceRenderers.Count; - _originallyHadShadows = new bool[totalRenderers]; - _originallyWasEnabled = new bool[totalRenderers]; - } - - #endregion Initialization -} \ No newline at end of file diff --git a/AvatarCloneTest/AvatarClone/AvatarClone.MagicaSupport.cs b/AvatarCloneTest/AvatarClone/AvatarClone.MagicaSupport.cs deleted file mode 100644 index 7ae5855..0000000 --- a/AvatarCloneTest/AvatarClone/AvatarClone.MagicaSupport.cs +++ /dev/null @@ -1,34 +0,0 @@ -using MagicaCloth; -using MagicaCloth2; -using UnityEngine; - -namespace NAK.AvatarCloneTest; - -public partial class AvatarClone -{ - #region Magica Cloth Support - - private void SetupMagicaClothSupport() - { - var magicaCloths1 = GetComponentsInChildren(true); - foreach (MagicaRenderDeformer magicaCloth in magicaCloths1) - { - // Get the renderer on the same object - Renderer renderer = magicaCloth.gameObject.GetComponent(); - SetRendererNeedsAdditionalChecks(renderer, true); - } - - var magicaCloths2 = GetComponentsInChildren(true); - foreach (MagicaCloth2.MagicaCloth magicaCloth in magicaCloths2) - { - if (magicaCloth.serializeData.clothType != ClothProcess.ClothType.MeshCloth) - continue; // Only matters for cloth physics - - // Set the affected renderers as requiring extra checks - var renderers = magicaCloth.serializeData.sourceRenderers; - foreach (Renderer renderer in renderers) SetRendererNeedsAdditionalChecks(renderer, true); - } - } - - #endregion Magica Cloth Support -} \ No newline at end of file diff --git a/AvatarCloneTest/AvatarClone/AvatarClone.Update.cs b/AvatarCloneTest/AvatarClone/AvatarClone.Update.cs deleted file mode 100644 index 42cef73..0000000 --- a/AvatarCloneTest/AvatarClone/AvatarClone.Update.cs +++ /dev/null @@ -1,181 +0,0 @@ -using UnityEngine; - -namespace NAK.AvatarCloneTest; - -public partial class AvatarClone -{ - #region Update Methods - - private void UpdateStandardRenderers() - { - int count = _standardRenderers.Count; - var sourceRenderers = _standardRenderers; - var cloneRenderers = _standardClones; - var localMats = _localMaterials; - - for (int i = 0; i < count; i++) - { - if (!IsRendererValid(sourceRenderers[i])) continue; - CopyMaterialsAndProperties( - sourceRenderers[i], - cloneRenderers[i], - _propertyBlock, - _mainMaterials, - localMats[i]); - } - } - - private void UpdateSkinnedRenderers() - { - int standardCount = _standardRenderers.Count; - int count = _skinnedRenderers.Count; - var sourceRenderers = _skinnedRenderers; - var cloneRenderers = _skinnedClones; - var localMats = _localMaterials; - var blendWeights = _blendShapeWeights; - - for (int i = 0; i < count; i++) - { - SkinnedMeshRenderer source = sourceRenderers[i]; - if (!IsRendererValid(source)) continue; - - SkinnedMeshRenderer clone = cloneRenderers[i]; - CopyMaterialsAndProperties( - source, - clone, - _propertyBlock, - _mainMaterials, - localMats[i + standardCount]); - - CopyBlendShapes(source, clone, blendWeights[i]); - } - } - - private void UpdateStandardRenderersWithChecks() - { - s_CopyMeshes.Begin(); - - var cloneFilters = _standardCloneFilters; - var sourceFilters = _standardFilters; - var cachedMeshes = _cachedSharedMeshes; - var checkIndices = _standardRenderersNeedingChecks; - int checkCount = checkIndices.Count; - - while (cachedMeshes.Count < checkCount) cachedMeshes.Add(null); - - for (int i = 0; i < checkCount; i++) - { - int rendererIndex = checkIndices[i]; - Mesh newMesh = sourceFilters[rendererIndex].sharedMesh; - if (ReferenceEquals(newMesh, cachedMeshes[i])) continue; - cloneFilters[rendererIndex].sharedMesh = newMesh; // expensive & allocates - cachedMeshes[i] = newMesh; - } - - s_CopyMeshes.End(); - } - - private void UpdateSkinnedRenderersWithChecks() - { - s_CopyMeshes.Begin(); - - var sourceRenderers = _skinnedRenderers; - var cloneRenderers = _skinnedClones; - var cachedMeshes = _cachedSharedMeshes; - var cachedBoneCounts = _cachedSkinnedBoneCounts; - var checkIndices = _skinnedRenderersNeedingChecks; - int checkCount = checkIndices.Count; - int meshOffset = _standardRenderersNeedingChecks.Count; - - // Ensure cache lists are properly sized - while (cachedMeshes.Count < meshOffset + checkCount) cachedMeshes.Add(null); - while (cachedBoneCounts.Count < checkCount) cachedBoneCounts.Add(0); - - for (int i = 0; i < checkCount; i++) - { - int rendererIndex = checkIndices[i]; - SkinnedMeshRenderer source = sourceRenderers[rendererIndex]; - SkinnedMeshRenderer clone = cloneRenderers[rendererIndex]; - - // Check mesh changes - Mesh newMesh = source.sharedMesh; // expensive & allocates - if (!ReferenceEquals(newMesh, cachedMeshes[meshOffset + i])) - { - clone.sharedMesh = newMesh; - cachedMeshes[meshOffset + i] = newMesh; - } - - // Check bone changes - var sourceBones = source.bones; - int newBoneCount = sourceBones.Length; - int oldBoneCount = cachedBoneCounts[i]; - if (newBoneCount == oldBoneCount) - continue; - - var cloneBones = clone.bones; // expensive & allocates - if (newBoneCount > oldBoneCount) - { - // Resize array and copy only the new bones (Magica Cloth appends bones when enabling Mesh Cloth) - Array.Resize(ref cloneBones, newBoneCount); - for (int boneIndex = oldBoneCount; boneIndex < newBoneCount; boneIndex++) - cloneBones[boneIndex] = sourceBones[boneIndex]; - clone.bones = cloneBones; - } - else - { - // If shrinking, just set the whole array - clone.bones = sourceBones; - } - - cachedBoneCounts[i] = newBoneCount; - } - - s_CopyMeshes.End(); - } - - private static void CopyMaterialsAndProperties( - Renderer source, Renderer clone, - MaterialPropertyBlock propertyBlock, - List mainMaterials, - Material[] localMaterials) - { - s_CopyMaterials.Begin(); - - source.GetSharedMaterials(mainMaterials); - - int matCount = mainMaterials.Count; - bool hasChanged = false; - for (var i = 0; i < matCount; i++) - { - if (ReferenceEquals(mainMaterials[i], localMaterials[i])) continue; - localMaterials[i] = mainMaterials[i]; - hasChanged = true; - } - if (hasChanged) clone.sharedMaterials = localMaterials; - - source.GetPropertyBlock(propertyBlock); - clone.SetPropertyBlock(propertyBlock); - - s_CopyMaterials.End(); - } - - private static void CopyBlendShapes( - SkinnedMeshRenderer source, - SkinnedMeshRenderer target, - List blendShapeWeights) - { - s_CopyBlendShapes.Begin(); - - int weightCount = blendShapeWeights.Count; - for (var i = 0; i < weightCount; i++) - { - var weight = source.GetBlendShapeWeight(i); - // ReSharper disable once CompareOfFloatsByEqualityOperator - if (weight == blendShapeWeights[i]) continue; // Halves the work - target.SetBlendShapeWeight(i, blendShapeWeights[i] = weight); - } - - s_CopyBlendShapes.End(); - } - #endregion Update Methods -} \ No newline at end of file diff --git a/AvatarCloneTest/AvatarClone/AvatarClone.Util.cs b/AvatarCloneTest/AvatarClone/AvatarClone.Util.cs deleted file mode 100644 index c6fb033..0000000 --- a/AvatarCloneTest/AvatarClone/AvatarClone.Util.cs +++ /dev/null @@ -1,20 +0,0 @@ -using ABI_RC.Core; -using ABI_RC.Core.Player; -using UnityEngine; - -namespace NAK.AvatarCloneTest; - -public partial class AvatarClone -{ - private static bool CameraRendersPlayerLocalLayer(Camera cam) - => (cam.cullingMask & (1 << CVRLayers.PlayerLocal)) != 0; - - private static bool CameraRendersPlayerCloneLayer(Camera cam) - => (cam.cullingMask & (1 << CVRLayers.PlayerClone)) != 0; - - private static bool IsUIInternalCamera(Camera cam) - => cam == PlayerSetup.Instance.activeUiCam; - - private static bool IsRendererValid(Renderer renderer) - => renderer && renderer.gameObject.activeInHierarchy; -} \ No newline at end of file diff --git a/AvatarCloneTest/AvatarClone/AvatarClone.cs b/AvatarCloneTest/AvatarClone/AvatarClone.cs deleted file mode 100644 index 88c8112..0000000 --- a/AvatarCloneTest/AvatarClone/AvatarClone.cs +++ /dev/null @@ -1,134 +0,0 @@ -using UnityEngine; -using UnityEngine.Rendering; - -namespace NAK.AvatarCloneTest; - -public partial class AvatarClone : MonoBehaviour -{ - #region Unity Events - - private void Start() - { - InitializeCollections(); - InitializeRenderers(); - SetupMaterialsAndBlendShapes(); - CreateClones(); - - InitializeExclusions(); - SetupMagicaClothSupport(); - - Camera.onPreCull += MyOnPreRender; - } - - private void OnDestroy() - { - Camera.onPreCull -= MyOnPreRender; - } - - private void LateUpdate() - { - // Update all renderers with basic properties (Materials & BlendShapes) - UpdateStandardRenderers(); - UpdateSkinnedRenderers(); - - // Additional pass for renderers needing extra checks (Shared Mesh & Bone Changes) - UpdateStandardRenderersWithChecks(); - UpdateSkinnedRenderersWithChecks(); - } - - private void MyOnPreRender(Camera cam) - { - s_MyOnPreRender.Begin(); - - bool isOurUiCamera = IsUIInternalCamera(cam); - bool rendersOurPlayerLayer = CameraRendersPlayerLocalLayer(cam); - bool rendersOurCloneLayer = CameraRendersPlayerCloneLayer(cam); - - // Renders both player layers. - // PlayerLocal will now act as a shadow caster, while PlayerClone will act as the actual head-hidden renderer. - bool rendersBothPlayerLayers = rendersOurPlayerLayer && rendersOurCloneLayer; - if (!_shadowsOnlyActive && rendersBothPlayerLayers) - { - s_SetShadowsOnly.Begin(); - - int sourceCount = _allSourceRenderers.Count; - var sourceRenderers = _allSourceRenderers; - for (int i = 0; i < sourceCount; i++) - { - Renderer renderer = sourceRenderers[i]; - if (!IsRendererValid(renderer)) continue; - - bool shouldRender = renderer.shadowCastingMode != ShadowCastingMode.Off; - _originallyWasEnabled[i] = renderer.enabled; - _originallyHadShadows[i] = shouldRender; - renderer.shadowCastingMode = ShadowCastingMode.ShadowsOnly; - if (renderer.forceRenderingOff == shouldRender) renderer.forceRenderingOff = !shouldRender; // TODO: Eval if check is needed - } - _shadowsOnlyActive = true; - - s_SetShadowsOnly.End(); - } - else if (_shadowsOnlyActive && !rendersBothPlayerLayers) - { - s_UndoShadowsOnly.Begin(); - - int sourceCount = _allSourceRenderers.Count; - var sourceRenderers = _allSourceRenderers; - for (int i = 0; i < sourceCount; i++) - { - Renderer renderer = sourceRenderers[i]; - if (!IsRendererValid(renderer)) continue; - - renderer.shadowCastingMode = _originallyHadShadows[i] ? ShadowCastingMode.On : ShadowCastingMode.Off; - if (renderer.forceRenderingOff == _originallyWasEnabled[i]) renderer.forceRenderingOff = !_originallyWasEnabled[i]; // TODO: Eval if check is needed - } - _shadowsOnlyActive = false; - - s_UndoShadowsOnly.End(); - } - - // Handle UI culling material changes - if (isOurUiCamera && !_uiCullingActive && rendersOurCloneLayer) - { - s_SetUiCulling.Begin(); - - int standardCount = _standardRenderers.Count; - var standardClones = _standardClones; - var cullingMaterials = _cullingMaterials; - for (int i = 0; i < standardCount; i++) - standardClones[i].sharedMaterials = cullingMaterials[i]; - - int skinnedCount = _skinnedRenderers.Count; - var skinnedClones = _skinnedClones; - for (int i = 0; i < skinnedCount; i++) - skinnedClones[i].sharedMaterials = cullingMaterials[i + standardCount]; - - _uiCullingActive = true; - - s_SetUiCulling.End(); - } - else if (!isOurUiCamera && _uiCullingActive) - { - s_UndoUiCulling.Begin(); - - int standardCount = _standardRenderers.Count; - var standardClones = _standardClones; - var localMaterials = _localMaterials; - for (int i = 0; i < standardCount; i++) - standardClones[i].sharedMaterials = localMaterials[i]; - - int skinnedCount = _skinnedRenderers.Count; - var skinnedClones = _skinnedClones; - for (int i = 0; i < skinnedCount; i++) - skinnedClones[i].sharedMaterials = localMaterials[i + standardCount]; - - _uiCullingActive = false; - - s_UndoUiCulling.End(); - } - - s_MyOnPreRender.End(); - } - - #endregion Unity Events -} \ No newline at end of file diff --git a/AvatarCloneTest/AvatarClone/FPRExclusion/AvatarCloneExclusion.cs b/AvatarCloneTest/AvatarClone/FPRExclusion/AvatarCloneExclusion.cs deleted file mode 100644 index 5681761..0000000 --- a/AvatarCloneTest/AvatarClone/FPRExclusion/AvatarCloneExclusion.cs +++ /dev/null @@ -1,38 +0,0 @@ -using ABI.CCK.Components; -using UnityEngine; - -namespace NAK.AvatarCloneTest; - -public class AvatarCloneExclusion : IExclusionBehaviour -{ - private readonly AvatarClone _cloneSystem; - private readonly Transform _target; - private Transform _shrinkBone; - - public bool isImmuneToGlobalState { get; set; } - - public AvatarCloneExclusion(AvatarClone cloneSystem, Transform target) - { - _cloneSystem = cloneSystem; - _target = target; - } - - public void UpdateExclusions(bool isShown, bool shrinkToZero) - { - Debug.Log($"[AvatarClone2] Updating exclusion for {_target.name}: isShown={isShown}, shrinkToZero={shrinkToZero}"); - - if (_shrinkBone == null) - { - // Create shrink bone parented directly to target - _shrinkBone = new GameObject($"{_target.name}_Shrink").transform; - _shrinkBone.SetParent(_target, false); - Debug.Log($"[AvatarClone2] Created shrink bone for {_target.name}"); - } - - // Set scale based on shrink mode - _shrinkBone.localScale = shrinkToZero ? Vector3.zero : Vector3.positiveInfinity; - - // Let the clone system handle the update - _cloneSystem.HandleExclusionUpdate(_target, _shrinkBone, isShown); - } -} \ No newline at end of file diff --git a/AvatarCloneTest/AvatarCloneTest.csproj b/AvatarCloneTest/AvatarCloneTest.csproj deleted file mode 100644 index 2e58669..0000000 --- a/AvatarCloneTest/AvatarCloneTest.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - LocalCloneFix - - - TRACE;TRACE; - - diff --git a/AvatarCloneTest/Main.cs b/AvatarCloneTest/Main.cs deleted file mode 100644 index 21a34bf..0000000 --- a/AvatarCloneTest/Main.cs +++ /dev/null @@ -1,72 +0,0 @@ -using ABI_RC.Core; -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 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 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 EntryCopyMaterials = - // Category.CreateEntry("copy_materials", true, - // "Copy Materials", description: "Copies the materials from the original avatar to the clone."); - // - // internal static readonly MelonPreferences_Entry EntryCopyMeshes = - // Category.CreateEntry("copy_meshes", true, - // "Copy Meshes", description: "Copies the meshes 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()) - { - if (camera.tag != "MainCamera") - { - camera.cullingMask &= ~(1 << CVRLayers.PlayerClone); - } - } - } - } - - #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 -} \ No newline at end of file diff --git a/AvatarCloneTest/Patches.cs b/AvatarCloneTest/Patches.cs deleted file mode 100644 index b4cec17..0000000 --- a/AvatarCloneTest/Patches.cs +++ /dev/null @@ -1,87 +0,0 @@ -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(); - return false; - } - - // [HarmonyPostfix] - // [HarmonyPatch(typeof(FPRExclusion), nameof(FPRExclusion.UpdateExclusions))] - // private static void OnUpdateExclusions(ref FPRExclusion __instance) - // { - // AvatarClone clone = PlayerSetup.Instance._avatar.GetComponent(); - // if (clone == null) return; - // clone.SetBoneChainVisibility(__instance.target, !__instance.isShown, !__instance.shrinkToZero); - // } - - [HarmonyPostfix] - [HarmonyPatch(typeof(CVRMirror), nameof(CVRMirror.Start))] - private static void OnMirrorStart(CVRMirror __instance) - { - if (!AvatarCloneTestMod.EntryUseAvatarCloneTest.Value) - return; - - // Don't reflect the player clone layer - __instance.m_ReflectLayers &= ~(1 << CVRLayers.PlayerClone); - } - - [HarmonyPostfix] - [HarmonyPatch(typeof(PlayerSetup), nameof(PlayerSetup.Update))] - private static void OnTransformHiderManagerUpdate(PlayerSetup __instance) - { - if (!AvatarCloneTestMod.EntryUseAvatarCloneTest.Value) - return; - - if (MetaPort.Instance.settings.GetSettingsBool("ExperimentalAvatarOverrenderUI")) - __instance.activeUiCam.cullingMask |= 1 << CVRLayers.PlayerClone; - else - __instance.activeUiCam.cullingMask &= ~(1 << CVRLayers.PlayerClone); - } - - private static bool _wasDebugInPortableCamera; - - [HarmonyPostfix] - [HarmonyPatch(typeof(PortableCamera), nameof(PortableCamera.Update))] - private static void OnPortableCameraUpdate(ref PortableCamera __instance) - { - if (!AvatarCloneTestMod.EntryUseAvatarCloneTest.Value) - { - // Show both PlayerLocal and PlayerClone - __instance.cameraComponent.cullingMask |= 1 << CVRLayers.PlayerLocal; - __instance.cameraComponent.cullingMask |= 1 << CVRLayers.PlayerClone; - return; - } - - if (TransformHiderManager.s_DebugInPortableCamera == _wasDebugInPortableCamera) - return; - - if (TransformHiderManager.s_DebugInPortableCamera) - { - // Hide PlayerLocal, show PlayerClone - __instance.cameraComponent.cullingMask &= ~(1 << CVRLayers.PlayerLocal); - __instance.cameraComponent.cullingMask |= 1 << CVRLayers.PlayerClone; - } - else - { - // Show PlayerLocal, hide PlayerClone - __instance.cameraComponent.cullingMask |= 1 << CVRLayers.PlayerLocal; - __instance.cameraComponent.cullingMask &= ~(1 << CVRLayers.PlayerClone); - } - - _wasDebugInPortableCamera = TransformHiderManager.s_DebugInPortableCamera; - } -} \ No newline at end of file diff --git a/AvatarCloneTest/Properties/AssemblyInfo.cs b/AvatarCloneTest/Properties/AssemblyInfo.cs deleted file mode 100644 index 3334b28..0000000 --- a/AvatarCloneTest/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,32 +0,0 @@ -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.0"; - public const string Author = "NotAKidoS"; -} \ No newline at end of file diff --git a/AvatarCloneTest/README.md b/AvatarCloneTest/README.md deleted file mode 100644 index cc12a9c..0000000 --- a/AvatarCloneTest/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# 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. diff --git a/AvatarCloneTest/format.json b/AvatarCloneTest/format.json deleted file mode 100644 index 6634e9f..0000000 --- a/AvatarCloneTest/format.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "_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" -} \ No newline at end of file