NSNzBF`)5bT< z6~`0*KewXpTe*;x0{pz|juw!JCqW7c*#(!q)L-ZU66+b(lDZI)TD962@;4k2>YYc{ zQa-y?3~B>~)+^zI`o&&>4~nKpx{H5wgW)`j zhM!=ay?lbcA}+oxbBMt%cB%aOQlG} s>4#1(=wvS^ nEwPis8vKn71CZJ^>X!Ze$W1t+I4oM7&hv#d{;teH)epR)u# z@o+y?>A!NZg6h_1zf9fyM9mVgEX{27ZBOUA%L*2C(&K($u>xNgqZt7osV_cn^+!n} zWv==*s<6QT%n{snO^@l)ppKG#5=cF}Ks5Y~U_|U9I2MG)vWP2ogSa|l&6ozVJ7)p; zEmSRy!-+>#=Ym{C_Mc~4LP1u#dzQU_(6!dVYUL~o^whbcFOsi7wV3|5WJAxd$7Si= z-+!Ru2BOGprfOK!wduii%xM)jdSpdGi?aDy%oEh{Sn+GclL9ur$uiaN6#Pa@%q9v` z$^CHZ#{bh|o$_lIO~|xtajPiMFW6jt3 1Z*SFT2wPo9u z77PS3wW0B65C@Wdidrh_VGRQO2?PU)EvFK5^;k<|B0rGOC-?UuJAq|r`m)y?mymV7 zG!0Jn0KxupCHIQuFweJn7az__SHT)N)Jr(vjJkM$ZlupxwnA(7hj!$&*6vt~^Gl7l zC{+52HpD~oWOJ0E?N8_0M}j&80ji0y@h|;PF1MX^BGLG`%P)v62ig;>dB>I9px|Kr z@vVA57+Fzfj7(OE$D 8_=DdrRy^(?j3@xg zBx)P}s^k;HPD{HRHB#{hNVgXBm79;96q8`zO_bxY GdAJt-G4E SO) zn*N+CAH*mUv%@sLQ{j%6aDnD5Z&YX{6z2yEl z0ZbtHdcF%vttk5!kEOs@E}VAz zi-}!@!A1Bv!Q{Q{=7iwQ4IZ IOL@{$wR-c
7}{HVV!PoE&6o`idF$Lv_`uP;Je8SKRsuUXg_Y9mvK{zxNGomTGn1`Ec8 z-rA{ZnQ1-&0?GSzNEFpdxR!EO{W(*bcL+f0Wr7mM3DSGIT?Z1d2`#VsVSKYx5RtCo z-BQCjsWwUH4pSo-n$gm8oto|@en`vFCzB{X(%>lvqUfPKLB8mUFTKH7eA Ei7A {DlHS<;sidSZ5*>)Yn+2#Ov&)l^{+>VNHDqdJ5XUroQd z@8zvyf%pNyn>5j!Y{hKo0QO*pt)ltJDH*IvT^dYBsFa3 IGO0~a)pc8Y>9W;%V>D6& Xzmy29udSO(taj=*6R@}c{xlMt`RPha diff --git a/BetterShadowClone/ShadowClone/IShadowClone/IShadowClone.cs b/BetterShadowClone/ShadowClone/IShadowClone/IShadowClone.cs deleted file mode 100644 index e6cc161..0000000 --- a/BetterShadowClone/ShadowClone/IShadowClone/IShadowClone.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace NAK.BetterShadowClone; - -public interface IShadowClone : IDisposable -{ - bool IsValid { get; } - bool Process(); - void RenderForShadow(); - void RenderForUiCulling(); - void ResetMainMesh(); -} \ No newline at end of file diff --git a/BetterShadowClone/ShadowClone/IShadowClone/MeshShadowClone.cs b/BetterShadowClone/ShadowClone/IShadowClone/MeshShadowClone.cs deleted file mode 100644 index d27883b..0000000 --- a/BetterShadowClone/ShadowClone/IShadowClone/MeshShadowClone.cs +++ /dev/null @@ -1,158 +0,0 @@ -using System; -using UnityEngine; -using UnityEngine.Rendering; - -namespace NAK.BetterShadowClone; - -public struct MeshShadowClone : IShadowClone -{ - // We technically don't need a clone mesh for MeshRenderer shadow clone handling, - // but as the shadows are also utilized for UI culling, we need to have a clone mesh. - // If we don't stick with UI culling, we can just set the shadowCastingMode to ShadowsOnly when player camera renders. - - // lame 2 frame init stuff - private const int FrameInitCount = 0; - private int _frameInitCounter; - private bool _hasInitialized; - - // shadow is used to cull ui, clone always exists - private readonly bool _shouldCastShadows; - private readonly MeshRenderer _mainMesh; - private readonly MeshRenderer _shadowMesh; - private readonly MeshFilter _shadowMeshFilter; - - // material copying (unity is shit) - private bool _hasShadowMaterials; - private readonly Material[] _shadowMaterials; - private readonly MaterialPropertyBlock _shadowMaterialBlock; - - #region IShadowClone Methods - - public void ResetMainMesh(){} - - public bool IsValid => _mainMesh != null && _shadowMesh != null; - - public MeshShadowClone(MeshRenderer meshRenderer) - { - _mainMesh = meshRenderer; - MeshFilter _mainMeshFilter = meshRenderer.GetComponent (); - - if (_mainMesh == null - || _mainMesh.sharedMaterials == null - || _mainMesh.sharedMaterials.Length == 0 - || _mainMeshFilter == null - || _mainMeshFilter.sharedMesh == null) - { - Dispose(); - return; // no mesh! - } - - _shouldCastShadows = _mainMesh.shadowCastingMode != ShadowCastingMode.Off; - _mainMesh.shadowCastingMode = ShadowCastingMode.Off; // visual mesh doesn't cast shadows - - (_shadowMesh, _shadowMeshFilter) = ShadowCloneManager.InstantiateShadowClone(_mainMesh); - _shadowMesh.forceRenderingOff = true; - - // material copying shit - int materialCount = _mainMesh.sharedMaterials.Length; - Material shadowMaterial = ShadowCloneHelper.shadowMaterial; - - _shadowMaterialBlock = new MaterialPropertyBlock(); - _shadowMaterials = new Material[materialCount]; - for (int i = 0; i < materialCount; i++) _shadowMaterials[i] = shadowMaterial; - } - - public bool Process() - { - bool shouldRender = _mainMesh.enabled && _mainMesh.gameObject.activeInHierarchy; - - // copying behaviour of SkinnedShadowClone, to visually be the same when a mesh toggles - if (!shouldRender) - { - _frameInitCounter = 0; - _hasInitialized = false; - _shadowMesh.forceRenderingOff = true; - return false; - } - - if (_frameInitCounter >= FrameInitCount) - { - if (_hasInitialized) - return true; - - _hasInitialized = true; - return true; - } - - _frameInitCounter++; - return false; - } - - public void RenderForShadow() - { - _shadowMesh.shadowCastingMode = ShadowCloneManager.s_DebugShowShadow - ? ShadowCastingMode.On : ShadowCastingMode.ShadowsOnly; - - _shadowMesh.forceRenderingOff = !_shouldCastShadows; - - // shadow casting needs clone to have original materials (uv discard) - // we also want to respect material swaps... but this is fucking slow :( - - if (!ShadowCloneManager.s_CopyMaterialsToShadow) - return; - - if (_hasShadowMaterials) - { - // NOTE: will not handle material swaps unless Avatar Overrender Ui is on - _shadowMesh.sharedMaterials = _mainMesh.sharedMaterials; - _hasShadowMaterials = false; - } - - UpdateCloneMaterialProperties(); - } - - public void RenderForUiCulling() - { - _shadowMesh.shadowCastingMode = ShadowCastingMode.On; - _shadowMesh.forceRenderingOff = false; - - // UI culling needs clone to have write-to-depth shader - if (_hasShadowMaterials) return; - _shadowMesh.sharedMaterials = _shadowMaterials; - _hasShadowMaterials = true; - - // Not needed- MaterialPropertyBlock applied to renderer in RenderForShadow - //UpdateCloneMaterialProperties(); - } - - public void Dispose() - { - if (_shadowMesh == null) - return; // uh oh - - // Cleanup instanced Mesh & Materials - GameObject shadowMeshObject = _shadowMesh.gameObject; - UnityEngine.Object.Destroy(_shadowMeshFilter.sharedMesh); - UnityEngine.Object.Destroy(_shadowMeshFilter); - if (!_hasShadowMaterials) - { - var materials = _shadowMesh.sharedMaterials; - foreach (Material mat in materials) UnityEngine.Object.Destroy(mat); - } - UnityEngine.Object.Destroy(_shadowMesh); - UnityEngine.Object.Destroy(shadowMeshObject); - } - - #endregion - - #region Private Methods - - private void UpdateCloneMaterialProperties() - { - // copy material properties to shadow clone materials - _mainMesh.GetPropertyBlock(_shadowMaterialBlock); - _shadowMesh.SetPropertyBlock(_shadowMaterialBlock); - } - - #endregion -} \ No newline at end of file diff --git a/BetterShadowClone/ShadowClone/IShadowClone/SkinnedShadowClone.cs b/BetterShadowClone/ShadowClone/IShadowClone/SkinnedShadowClone.cs deleted file mode 100644 index 89d7494..0000000 --- a/BetterShadowClone/ShadowClone/IShadowClone/SkinnedShadowClone.cs +++ /dev/null @@ -1,296 +0,0 @@ -using System; -using UnityEngine; -using UnityEngine.Rendering; - -namespace NAK.BetterShadowClone; - -public class SkinnedShadowClone : IShadowClone -{ - private static readonly int s_SourceBufferId = Shader.PropertyToID("_sourceBuffer"); - private static readonly int s_TargetBufferId = Shader.PropertyToID("_targetBuffer"); - private static readonly int s_HiddenVerticiesId = Shader.PropertyToID("_hiddenVertices"); - private static readonly int s_HiddenVertexPos = Shader.PropertyToID("_hiddenVertexPos"); - private static readonly int s_SourceBufferLayoutId = Shader.PropertyToID("_sourceBufferLayout"); - private static readonly int s_SourceRootMatrix = Shader.PropertyToID("_rootBoneMatrix"); - - // lame 2 frame init stuff - private const int FrameInitCount = 0; - private int _frameInitCounter; - private bool _hasInitialized; - - // shadow is used to cull ui, clone always exists - private readonly bool _shouldCastShadows; - private readonly SkinnedMeshRenderer _mainMesh; - private readonly MeshRenderer _shadowMesh; - private readonly MeshFilter _shadowMeshFilter; - private readonly Transform _rootBone; - - // clone copying - private GraphicsBuffer _graphicsBuffer; - private GraphicsBuffer _targetBuffer; - private ComputeBuffer _computeBuffer; - private int _threadGroups; - private int _bufferLayout; - - // material copying (unity is shit) - private bool _hasShadowMaterials; - private readonly Material[] _shadowMaterials; - private readonly MaterialPropertyBlock _shadowMaterialBlock; - - #region IShadowClone Methods - - // anything player can touch is suspect to death - public bool IsValid => _mainMesh != null && _shadowMesh != null && _rootBone != null; - - internal SkinnedShadowClone(SkinnedMeshRenderer renderer, FPRExclusion exclusion) - { - _mainMesh = renderer; - - if (_mainMesh == null - || _mainMesh.sharedMesh == null - || _mainMesh.sharedMaterials == null - || _mainMesh.sharedMaterials.Length == 0) - { - Dispose(); - return; // no mesh! - } - - - FindExclusionVertList(_mainMesh, exclusion); - - if (exclusion.affectedVertexIndices.Count == 0) - { - Dispose(); - return; // no affected verts! - } - - _computeBuffer = new ComputeBuffer(_mainMesh.sharedMesh.vertexCount, sizeof(int)); - _computeBuffer.SetData(exclusion.affectedVertexIndices.ToArray()); - exclusion.affectedVertexIndices.Clear(); - - - - _shouldCastShadows = _mainMesh.shadowCastingMode != ShadowCastingMode.Off; - //_mainMesh.shadowCastingMode = ShadowCastingMode.On; // visual mesh doesn't cast shadows - - (_shadowMesh, _shadowMeshFilter) = ShadowCloneManager.InstantiateShadowClone(_mainMesh); - _shadowMesh.shadowCastingMode = ShadowCastingMode.Off; // shadow mesh doesn't cast shadows - _shadowMesh.forceRenderingOff = false; - - - _rootBone = _mainMesh.rootBone; - _rootBone ??= _mainMesh.transform; // fallback to transform if no root bone - - // material copying shit - int materialCount = _mainMesh.sharedMaterials.Length; - Material shadowMaterial = ShadowCloneHelper.shadowMaterial; - - _shadowMaterialBlock = new MaterialPropertyBlock(); // TODO: check if we need one per material on renderer, idk if this is only first index - _shadowMaterials = new Material[materialCount]; - for (int i = 0; i < materialCount; i++) _shadowMaterials[i] = shadowMaterial; - } - - public bool Process() - { - // some people animate renderer.enabled instead of gameObject.activeInHierarchy - // do not disable shadow clone game object, it causes a flicker when re-enabled! - bool shouldRender = _mainMesh.enabled && _mainMesh.gameObject.activeInHierarchy; - - // GraphicsBuffer becomes stale when mesh is disabled - if (!shouldRender) - { - _frameInitCounter = 0; - _hasInitialized = false; - _shadowMesh.forceRenderingOff = true; // force off if mesh is disabled - return false; // TODO: dispose stale buffers - } - - // Unity is weird, so we need to wait 2 frames before we can get the graphics buffer - if (_frameInitCounter >= FrameInitCount) - { - if (_hasInitialized) - return true; - - _hasInitialized = true; - SetupGraphicsBuffer(); - return true; - } - - _frameInitCounter++; - return false; - } - - public void RenderForShadow() - { - ResetShadowClone(); - RenderShadowClone(); - } - - public void RenderForUiCulling() - { - ConfigureShadowCloneForUiCulling(); - RenderShadowClone(); - } - - public void Dispose() - { - if (_shadowMesh != null) - { - // Cleanup instanced Mesh & Materials - GameObject shadowMeshObject = _shadowMesh.gameObject; - UnityEngine.Object.Destroy(_shadowMeshFilter.mesh); - UnityEngine.Object.Destroy(_shadowMeshFilter); - - // explain why this works - if (_hasShadowMaterials) _shadowMesh.sharedMaterials = _mainMesh.sharedMaterials; - foreach (Material mat in _shadowMesh.sharedMaterials) UnityEngine.Object.Destroy(mat); - - UnityEngine.Object.Destroy(_shadowMesh); - UnityEngine.Object.Destroy(shadowMeshObject); - } - - _graphicsBuffer?.Dispose(); - _graphicsBuffer = null; - _targetBuffer?.Dispose(); - _targetBuffer = null; - _computeBuffer?.Dispose(); - _computeBuffer = null; - } - - #endregion - - #region Private Methods - - // Unity is weird, so we need to wait 2 frames before we can get the graphics buffer - private void SetupGraphicsBuffer() - { - Mesh mesh = _mainMesh.sharedMesh; - Mesh shadowMesh = _shadowMesh.GetComponent ().mesh; - - _bufferLayout = 0; - if (mesh.HasVertexAttribute(VertexAttribute.Position)) _bufferLayout += 3; - if (mesh.HasVertexAttribute(VertexAttribute.Normal)) _bufferLayout += 3; - if (mesh.HasVertexAttribute(VertexAttribute.Tangent)) _bufferLayout += 4; - _bufferLayout *= 4; // 4 bytes per float - - const float xThreadGroups = 32f; - _threadGroups = Mathf.CeilToInt(mesh.vertexCount / xThreadGroups); - - _mainMesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw; - shadowMesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw; - - _targetBuffer = shadowMesh.GetVertexBuffer(0); - - //Debug.Log($"Initialized! BufferLayout: {_bufferLayout}, GraphicsBuffer: {_graphicsBuffer != null}, TargetBuffer: {_targetBuffer != null}"); - } - - public static void FindExclusionVertList(SkinnedMeshRenderer renderer, FPRExclusion exclusion) - { - var boneWeights = renderer.sharedMesh.boneWeights; - - HashSet weights = new(); - for (int i = 0; i < renderer.bones.Length; i++) - { - if (exclusion.affectedChildren.Contains(renderer.bones[i])) - weights.Add(i); - } - - for (int i = 0; i < boneWeights.Length; i++) - { - BoneWeight weight = boneWeights[i]; - - Transform bone = null; - const float minWeightThreshold = 0.2f; - if (weights.Contains(weight.boneIndex0) && weight.weight0 > minWeightThreshold) - bone = renderer.bones[weight.boneIndex0]; - else if (weights.Contains(weight.boneIndex1) && weight.weight1 > minWeightThreshold) - bone = renderer.bones[weight.boneIndex1]; - else if (weights.Contains(weight.boneIndex2) && weight.weight2 > minWeightThreshold) - bone = renderer.bones[weight.boneIndex2]; - else if (weights.Contains(weight.boneIndex3) && weight.weight3 > minWeightThreshold) - bone = renderer.bones[weight.boneIndex3]; - - exclusion.affectedVertexIndices.Add(bone != null ? i : -1); - } - } - - public void ResetMainMesh() - { - _mainMesh.shadowCastingMode = ShadowCastingMode.On; - _mainMesh.forceRenderingOff = false; - - _shadowMesh.transform.position = Vector3.positiveInfinity; // nan - } - - private void ResetShadowClone() - { - if (ShadowCloneManager.s_DebugShowShadow) - { - _mainMesh.shadowCastingMode = ShadowCastingMode.ShadowsOnly; - _mainMesh.forceRenderingOff = false; - - _shadowMesh.shadowCastingMode = ShadowCastingMode.On; - _shadowMesh.forceRenderingOff = false; - - _shadowMesh.transform.localPosition = Vector3.zero; - } - else - { - _mainMesh.shadowCastingMode = ShadowCastingMode.On; - _mainMesh.forceRenderingOff = false; - - _shadowMesh.shadowCastingMode = ShadowCastingMode.ShadowsOnly; - _shadowMesh.forceRenderingOff = !_shouldCastShadows; - } - - //_shadowMesh.enabled = true; - - // shadow casting needs clone to have original materials (uv discard) - // we also want to respect material swaps... but this is fucking slow :( - - if (!ShadowCloneManager.s_CopyMaterialsToShadow) - return; - - _shadowMesh.sharedMaterials = _mainMesh.sharedMaterials; - UpdateCloneMaterialProperties(); - } - - private void ConfigureShadowCloneForUiCulling() - { - _shadowMesh.shadowCastingMode = ShadowCastingMode.On; - _shadowMesh.forceRenderingOff = false; - - // UI culling needs clone to have write-to-depth shader - _shadowMesh.sharedMaterials = _shadowMaterials; - - // Not needed- MaterialPropertyBlock applied to renderer in RenderForShadow - UpdateCloneMaterialProperties(); - } - - private void RenderShadowClone() - { - // thanks sdraw, i suck at matrix math - Matrix4x4 rootMatrix = _mainMesh.localToWorldMatrix.inverse * Matrix4x4.TRS(_rootBone.position, _rootBone.rotation, Vector3.one); - - _graphicsBuffer = _mainMesh.GetVertexBuffer(); - ShadowCloneHelper.shader.SetMatrix(s_SourceRootMatrix, rootMatrix); - ShadowCloneHelper.shader.SetBuffer(0, s_SourceBufferId, _graphicsBuffer); - ShadowCloneHelper.shader.SetBuffer(0, s_TargetBufferId, _targetBuffer); - - ShadowCloneHelper.shader.SetBuffer(0, s_HiddenVerticiesId, _computeBuffer); - ShadowCloneHelper.shader.SetVector(s_HiddenVertexPos, Vector4.positiveInfinity); // temp - - ShadowCloneHelper.shader.SetInt(s_SourceBufferLayoutId, _bufferLayout); - ShadowCloneHelper.shader.Dispatch(0, _threadGroups, 1, 1); - _graphicsBuffer.Release(); - } - - private void UpdateCloneMaterialProperties() - { - // copy material properties to shadow clone materials - _mainMesh.GetPropertyBlock(_shadowMaterialBlock); - _shadowMesh.SetPropertyBlock(_shadowMaterialBlock); - } - - #endregion -} \ No newline at end of file diff --git a/BetterShadowClone/ShadowClone/ShadowCloneManager.cs b/BetterShadowClone/ShadowClone/ShadowCloneManager.cs deleted file mode 100644 index 4443efd..0000000 --- a/BetterShadowClone/ShadowClone/ShadowCloneManager.cs +++ /dev/null @@ -1,251 +0,0 @@ -using System.Collections.Generic; -using ABI_RC.Core; -using ABI_RC.Core.Player; -using ABI_RC.Core.Savior; -using MagicaCloth; -using UnityEngine; -using UnityEngine.Rendering; - -namespace NAK.BetterShadowClone; - -public class ShadowCloneManager : MonoBehaviour -{ - #region Singleton Implementation - - private static ShadowCloneManager _instance; - public static ShadowCloneManager Instance - { - get - { - if (_instance != null) return _instance; - _instance = new GameObject("NAK.ShadowCloneManager").AddComponent (); - DontDestroyOnLoad(_instance.gameObject); - return _instance; - } - } - - #endregion - - private const string ShadowClonePostfix = "_ShadowClone"; - //public const string CVRIgnoreForUiCulling = "CVRIgnoreForUiCulling"; // TODO: Shader Tag to ignore for UI culling? - - // Game cameras - private static Camera s_MainCamera; - private static Camera s_UiCamera; - - // Settings - internal static bool s_CopyMaterialsToShadow = true; - internal static bool s_DebugShowShadow = false; - internal static bool s_DebugShowInFront = false; - private static bool s_UseShadowToCullUi; - private const string ShadowCullUiSettingName = "ExperimentalAvatarOverrenderUI"; - - // Implementation - private bool _hasRenderedThisFrame; - public static readonly List s_Exclusions = new(); - - // Shadow Clones - private readonly List s_ShadowClones = new(); - public void AddShadowClone(IShadowClone clone) - => s_ShadowClones.Add(clone); - - // Debug - private bool _debugShadowProcessingTime; - private readonly StopWatch _stopWatch = new(); - - #region Unity Events - - private void Start() - { - if (Instance != null - && Instance != this) - { - Destroy(this); - return; - } - - UpdatePlayerCameras(); - - s_CopyMaterialsToShadow = ModSettings.EntryCopyMaterialToShadow.Value; - s_DebugShowShadow = ModSettings.EntryDebugShowShadow.Value; - s_DebugShowInFront = ModSettings.EntryDebugShowInFront.Value; - s_UseShadowToCullUi = MetaPort.Instance.settings.GetSettingsBool(ShadowCullUiSettingName); - MetaPort.Instance.settings.settingBoolChanged.AddListener(OnSettingsBoolChanged); - } - - private void OnEnable() - => Camera.onPreRender += MyOnPreCull; - - private void OnDisable() - => Camera.onPreRender -= MyOnPreCull; - - private void OnDestroy() - { - MetaPort.Instance.settings.settingBoolChanged.RemoveListener(OnSettingsBoolChanged); - } - - #endregion - - #region Shadow Clone Managment - - private void Update() - { - _hasRenderedThisFrame = false; - - for (int i = s_ShadowClones.Count - 1; i >= 0; i--) - { - IShadowClone clone = s_ShadowClones[i]; - if (clone is not { IsValid: true }) - { - clone?.Dispose(); - s_ShadowClones.RemoveAt(i); - continue; // invalid or dead - } - - clone.ResetMainMesh(); - } - } - - private void MyOnPreCull(Camera cam) - { - //bool forceRenderForUiCull = s_UseShadowToCullUi && cam == s_UiCamera; - if (cam != s_MainCamera) - return; - - _hasRenderedThisFrame = true; - - _stopWatch.Start(); - - for (int i = s_ShadowClones.Count - 1; i >= 0; i--) - { - IShadowClone clone = s_ShadowClones[i]; - if (clone is not { IsValid: true }) - { - clone?.Dispose(); - s_ShadowClones.RemoveAt(i); - continue; // invalid or dead - } - - if (!clone.Process()) continue; // not ready yet or disabled - - clone.RenderForShadow(); // first cam to render - } - - _stopWatch.Stop(); - } - - #endregion - - #region Game Events - - public void OnAvatarCleared() - { - // Dispose all shadow clones BEFORE game unloads avatar - // Otherwise we memory leak the shadow clones mesh & material instances!!! - foreach (IShadowClone clone in s_ShadowClones) - clone.Dispose(); - s_ShadowClones.Clear(); - } - - private void OnSettingsBoolChanged(string settingName, bool settingValue) - { - if (settingName == ShadowCullUiSettingName) - { - s_UseShadowToCullUi = settingValue; - s_UiCamera.cullingMask = settingValue // make UI camera not see CVRLayers.PlayerClone - ? s_UiCamera.cullingMask | (1 << CVRLayers.PlayerClone) - : s_UiCamera.cullingMask & ~(1 << CVRLayers.PlayerClone); - } - } - - private void OnVRModeSwitchCompleted(bool _, Camera __) - { - UpdatePlayerCameras(); - } - - #endregion - - #region Private Methods - - private static void UpdatePlayerCameras() - { - s_MainCamera = PlayerSetup.Instance.GetActiveCamera().GetComponent (); - s_UiCamera = s_MainCamera.transform.Find("_UICamera").GetComponent (); - - //s_PortableCamera = PortableCamera.Instance.cameraComponent; - } - - #endregion - - #region Static Helpers - - internal static IShadowClone CreateShadowClone(Renderer renderer, FPRExclusion exclusion) - { - return renderer switch - { - SkinnedMeshRenderer skinnedMeshRenderer => new SkinnedShadowClone(skinnedMeshRenderer, exclusion), - MeshRenderer meshRenderer => new MeshShadowClone(meshRenderer), - _ => null - }; - } - - internal static (MeshRenderer, MeshFilter) InstantiateShadowClone(SkinnedMeshRenderer meshRenderer) - { - GameObject shadowClone = new (meshRenderer.name + ShadowClonePostfix) { layer = CVRLayers.PlayerClone }; - shadowClone.transform.SetParent(meshRenderer.transform, false); - shadowClone.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); - shadowClone.transform.localScale = Vector3.one; - - if (s_DebugShowShadow && s_DebugShowInFront) - { - float scale = PlayerSetup.Instance.GetPlaySpaceScale(); - Transform playerTransform = PlayerSetup.Instance.transform; - shadowClone.transform.position += playerTransform.forward * scale * 1f; - shadowClone.transform.rotation = Quaternion.AngleAxis(180f, playerTransform.up) * shadowClone.transform.rotation; - } - - MeshRenderer newMesh = shadowClone.AddComponent (); - MeshFilter newMeshFilter = shadowClone.AddComponent (); - - ShadowCloneHelper.ConfigureRenderer(newMesh, true); - - // only shadow clone should cast shadows - newMesh.shadowCastingMode = ShadowCastingMode.ShadowsOnly; - - // copy mesh and materials - newMeshFilter.sharedMesh = meshRenderer.sharedMesh; - newMesh.sharedMaterials = meshRenderer.sharedMaterials; - - // copy probe anchor - newMesh.probeAnchor = meshRenderer.probeAnchor; - - return (newMesh, newMeshFilter); - } - - internal static (MeshRenderer, MeshFilter) InstantiateShadowClone(MeshRenderer meshRenderer) - { - GameObject shadowClone = new (meshRenderer.name + ShadowClonePostfix) { layer = CVRLayers.PlayerClone }; - shadowClone.transform.SetParent(meshRenderer.transform, false); - shadowClone.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); - shadowClone.transform.localScale = Vector3.one; - - MeshRenderer newMesh = shadowClone.AddComponent (); - MeshFilter newMeshFilter = shadowClone.AddComponent (); - - ShadowCloneHelper.ConfigureRenderer(newMesh, true); - - // only shadow clone should cast shadows - newMesh.shadowCastingMode = ShadowCastingMode.ShadowsOnly; - - // copy mesh and materials - newMeshFilter.sharedMesh = meshRenderer.GetComponent ().sharedMesh; - newMesh.sharedMaterials = meshRenderer.sharedMaterials; - - // copy probe anchor - newMesh.probeAnchor = meshRenderer.probeAnchor; - - return (newMesh, newMeshFilter); - } - - #endregion -} \ No newline at end of file diff --git a/BetterShadowClone/ShadowCloneHelper.cs b/BetterShadowClone/ShadowCloneHelper.cs deleted file mode 100644 index 797ebb7..0000000 --- a/BetterShadowClone/ShadowCloneHelper.cs +++ /dev/null @@ -1,168 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using ABI_RC.Core; -using ABI.CCK.Components; -using UnityEngine; -using UnityEngine.Rendering; -using Object = UnityEngine.Object; - -namespace NAK.BetterShadowClone; - -public static class ShadowCloneHelper -{ - public static ComputeShader shader; - public static Material shadowMaterial; - - #region Avatar Setup - - public static void SetupAvatar(GameObject avatar) - { - Animator animator = avatar.GetComponent (); - if (animator == null || animator.avatar == null || animator.avatar.isHuman == false) - { - ShadowCloneMod.Logger.Warning("Avatar is not humanoid!"); - return; - } - - Transform headBone = animator.GetBoneTransform(HumanBodyBones.Head); - if (headBone == null) - { - ShadowCloneMod.Logger.Warning("Head bone not found!"); - return; - } - - var renderers = avatar.GetComponentsInChildren (true); - if (renderers == null || renderers.Length == 0) - { - ShadowCloneMod.Logger.Warning("No renderers found!"); - return; - } - - ShadowCloneMod.Logger.Msg($"Found {renderers.Length} renderers. Processing..."); - - // create shadow clones - ProcessRenderers(renderers, avatar.transform, headBone); - } - - private static void ProcessRenderers(IEnumerable renderers, Transform root, Transform headBone) - { - Stopwatch sw = Stopwatch.StartNew(); - - IReadOnlyDictionary exclusions = CollectTransformToExclusionMap(root, headBone); - var exclusion = headBone.gameObject.GetComponent (); - - // log current time - ShadowCloneMod.Logger.Msg($"CollectTransformToExclusionMap in {sw.ElapsedMilliseconds}ms"); - - foreach (Renderer renderer in renderers) - { - ConfigureRenderer(renderer); - - if (ModSettings.EntryUseShadowClone.Value) - { - IShadowClone clone = ShadowCloneManager.CreateShadowClone(renderer, exclusion); - if (clone != null) ShadowCloneManager.Instance.AddShadowClone(clone); - } - - // ITransformHider hider = TransformHiderManager.CreateTransformHider(renderer, exclusions); - // if (hider != null) TransformHiderManager.Instance.AddTransformHider(hider); - } - - sw.Stop(); - - // log current time - ShadowCloneMod.Logger.Msg($"ProcessRenderers in {sw.ElapsedMilliseconds}ms"); - } - - #endregion - - #region FPR Exclusion Processing - - private static Dictionary CollectTransformToExclusionMap(Component root, Transform headBone) - { - // add an fpr exclusion to the head bone - headBone.gameObject.AddComponent ().target = headBone; - - // add an FPRExclusion for all target entries on CVRAvatar (Experimental feature) - CVRAvatar avatar = root.GetComponent (); - if (avatar != null) - { - foreach (CVRAvatarFPREntry fprEntry in avatar.fprSettingsList.Where(fprEntry => fprEntry.transform != null)) - fprEntry.transform.gameObject.AddComponent ().target = fprEntry.transform; - } - - // get all FPRExclusions - var fprExclusions = root.GetComponentsInChildren (true).ToList(); - - // get all valid exclusion targets, and destroy invalid exclusions - Dictionary exclusionTargets = new(); - for (int i = fprExclusions.Count - 1; i >= 0; i--) - { - FPRExclusion exclusion = fprExclusions[i]; - if (exclusion.target == null) - { - Object.Destroy(exclusion); - continue; - } - - // first to add wins - exclusionTargets.TryAdd(exclusion.target, exclusion); - } - - // process each FPRExclusion (recursive) - foreach (FPRExclusion exclusion in fprExclusions) - ProcessExclusion(exclusion, exclusion.target); - - // log totals - ShadowCloneMod.Logger.Msg($"Exclusions: {fprExclusions.Count}"); - return exclusionTargets; - - void ProcessExclusion(FPRExclusion exclusion, Transform transform) - { - if (exclusionTargets.ContainsKey(transform) - && exclusionTargets[transform] != exclusion) return; // found other exclusion root - - exclusion.affectedChildren.Add(transform); // associate with the exclusion - exclusionTargets.TryAdd(transform, exclusion); // add to the dictionary (yes its wasteful) - - foreach (Transform child in transform) - ProcessExclusion(exclusion, child); // process children - } - } - - #endregion - - #region Generic Renderer Configuration - - internal static void ConfigureRenderer(Renderer renderer, bool isShadowClone = false) - { - // generic optimizations - renderer.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion; - - // don't let visual/shadow mesh cull in weird worlds - renderer.allowOcclusionWhenDynamic = false; // (third person stripped local player naked when camera was slightly occluded) - - // shadow clone optimizations (always MeshRenderer) - if (isShadowClone) - { - // renderer.receiveShadows = false; - // renderer.lightProbeUsage = LightProbeUsage.Off; - // renderer.reflectionProbeUsage = ReflectionProbeUsage.Off; - return; - } - - if (renderer is not SkinnedMeshRenderer skinnedMeshRenderer) - return; - - // GraphicsBuffer becomes stale randomly otherwise ??? - //skinnedMeshRenderer.updateWhenOffscreen = true; - - // skin mesh renderer optimizations - skinnedMeshRenderer.skinnedMotionVectors = false; - skinnedMeshRenderer.forceMatrixRecalculationPerRender = false; // expensive - skinnedMeshRenderer.quality = SkinQuality.Bone4; - } - - #endregion -} \ No newline at end of file diff --git a/BetterShadowClone/TransformHider/FPRExclusion.cs b/BetterShadowClone/TransformHider/FPRExclusion.cs deleted file mode 100644 index b07aeea..0000000 --- a/BetterShadowClone/TransformHider/FPRExclusion.cs +++ /dev/null @@ -1,35 +0,0 @@ -using UnityEngine; - -namespace NAK.BetterShadowClone; - -/// -/// Manual exclusion component for the TransformHider (FPR) system. -/// Allows you to manually hide and show a transform that would otherwise be hidden. -/// -public class FPRExclusion : MonoBehaviour -{ - public Transform target; - - internal readonly ListaffectedVertexIndices = new(); - - internal readonly List affectedChildren = new(); - internal readonly List relatedTasks = new(); - - private void OnEnable() - => SetFPRState(true); - - private void OnDisable() - => SetFPRState(false); - - private void SetFPRState(bool state) - { - if (relatedTasks == null) return; // no hiders to set - foreach (IFPRExclusionTask task in relatedTasks) - task.IsActive = state; - } -} - -public interface IFPRExclusionTask -{ - public bool IsActive { get; set; } -} \ No newline at end of file diff --git a/BetterShadowClone/TransformHider/ITransformHider/ITransformHider.cs b/BetterShadowClone/TransformHider/ITransformHider/ITransformHider.cs deleted file mode 100644 index 4922adf..0000000 --- a/BetterShadowClone/TransformHider/ITransformHider/ITransformHider.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace NAK.BetterShadowClone; - -public interface ITransformHider : IDisposable -{ - bool IsActive { get; set; } - bool IsValid { get; } - bool Process(); - bool PostProcess(); - void HideTransform(bool forced = false); - void ShowTransform(); -} \ No newline at end of file diff --git a/BetterShadowClone/TransformHider/ITransformHider/MeshTransformHider.cs b/BetterShadowClone/TransformHider/ITransformHider/MeshTransformHider.cs deleted file mode 100644 index 523aab3..0000000 --- a/BetterShadowClone/TransformHider/ITransformHider/MeshTransformHider.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using UnityEngine; -using UnityEngine.Rendering; - -namespace NAK.BetterShadowClone; - -public class MeshTransformHider : ITransformHider, IFPRExclusionTask -{ - // lame 2 frame init stuff - private const int FrameInitCount = 0; - private int _frameInitCounter; - private bool _hasInitialized; - private bool _markedForDeath; - - // mesh - private readonly MeshRenderer _mainMesh; - private bool _enabledState; - - #region ITransformHider Methods - - public bool IsActive { get; set; } = true; // default hide, but FPRExclusion can override - - // anything player can touch is suspect to death - public bool IsValid => _mainMesh != null && !_markedForDeath; - - public MeshTransformHider(MeshRenderer renderer, IReadOnlyDictionary 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; - - if (_mainMesh == null - || _mainMesh.sharedMaterials == null - || _mainMesh.sharedMaterials.Length == 0) - { - Dispose(); - } - } - - public bool Process() - { - bool shouldRender = _mainMesh.enabled && _mainMesh.gameObject.activeInHierarchy; - - // GraphicsBuffer becomes stale when mesh is disabled - if (!shouldRender) - { - _frameInitCounter = 0; - _hasInitialized = false; - return false; - } - - // Unity is weird, so we need to wait 2 frames before we can get the graphics buffer - if (_frameInitCounter >= FrameInitCount) - { - if (_hasInitialized) - return true; - - _hasInitialized = true; - return true; - } - - _frameInitCounter++; - return false; - } - - public bool PostProcess() - => true; - - public void HideTransform(bool forced = false) - { - if (!forced && !IsActive) - return; - - _enabledState = _mainMesh.enabled; - _mainMesh.enabled = false; - } - - public void ShowTransform() - { - _mainMesh.enabled = _enabledState; - } - - public void Dispose() - { - _markedForDeath = true; - } - - #endregion -} \ No newline at end of file diff --git a/BetterShadowClone/TransformHider/ITransformHider/SkinnedTransformHider.cs b/BetterShadowClone/TransformHider/ITransformHider/SkinnedTransformHider.cs deleted file mode 100644 index 10a32b3..0000000 --- a/BetterShadowClone/TransformHider/ITransformHider/SkinnedTransformHider.cs +++ /dev/null @@ -1,253 +0,0 @@ -using System; -using System.Diagnostics; -using UnityEngine; -using UnityEngine.Rendering; - -namespace NAK.BetterShadowClone; - -public class SkinnedTransformHider : ITransformHider -{ - private static readonly int s_Pos = Shader.PropertyToID("pos"); - private static readonly int s_BufferLayout = Shader.PropertyToID("bufferLayout"); - private static readonly int s_WeightedCount = Shader.PropertyToID("weightedCount"); - private static readonly int s_WeightedVertices = Shader.PropertyToID("weightedVertices"); - private static readonly int s_VertexBuffer = Shader.PropertyToID("VertexBuffer"); - - // lame 2 frame init stuff - private const int FrameInitCount = 0; - private int _frameInitCounter; - private bool _hasInitialized; - private bool _markedForDeath; - - // mesh & bone - private readonly SkinnedMeshRenderer _mainMesh; - private readonly Transform _rootBone; - - // main hider stuff - private GraphicsBuffer _graphicsBuffer; - private int _bufferLayout; - - // subtasks - private readonly List _subTasks = new(); - - #region ITransformHider Methods - - public bool IsActive { get; set; } = true; // default hide, but FPRExclusion can override - - // anything player can touch is suspect to death - public bool IsValid => !_markedForDeath && _mainMesh != null && _rootBone != null; - - public SkinnedTransformHider(SkinnedMeshRenderer renderer, IReadOnlyDictionary exclusions) - { - Stopwatch sw = Stopwatch.StartNew(); - - _mainMesh = renderer; - - if (_mainMesh == null - || _mainMesh.sharedMesh == null - || _mainMesh.sharedMaterials == null - || _mainMesh.sharedMaterials.Length == 0) - { - Dispose(); - return; // no mesh or bone! - } - - _rootBone = _mainMesh.rootBone; - _rootBone ??= _mainMesh.transform; // fallback to transform if no root bone - - // log current time - ShadowCloneMod.Logger.Msg($"SkinnedTransformHider part 1 in {sw.ElapsedMilliseconds}ms"); - - SubTask.FindExclusionVertList(renderer, exclusions); - - foreach (var exclusion in exclusions) - { - FPRExclusion fprExclusion = exclusion.Value; - if (fprExclusion.affectedVertexIndices.Count == 0) - continue; // no affected verts - - SubTask subTask = new(this, fprExclusion, fprExclusion.affectedVertexIndices); - _subTasks.Add(subTask); - fprExclusion.relatedTasks.Add(subTask); - fprExclusion.affectedVertexIndices.Clear(); // clear list for next SkinnedTransformHider - } - - // log current time - ShadowCloneMod.Logger.Msg($"SkinnedTransformHider part 3 in {sw.ElapsedMilliseconds}ms"); - - if (_subTasks.Count == 0) - { - Dispose(); // had the bones, but not the weights :? - ShadowCloneMod.Logger.Warning("SkinnedTransformHider No valid exclusions found!"); - } - - sw.Stop(); - - ShadowCloneMod.Logger.Msg($"SkinnedTransformHider created in {sw.ElapsedMilliseconds}ms"); - } - - public bool Process() - { - bool shouldRender = _mainMesh.enabled && _mainMesh.gameObject.activeInHierarchy; - - // GraphicsBuffer becomes stale when mesh is disabled - if (!shouldRender) - { - _frameInitCounter = 0; - _hasInitialized = false; - return false; - } - - // Unity is weird, so we need to wait 2 frames before we can get the graphics buffer - if (_frameInitCounter >= FrameInitCount) - { - if (_hasInitialized) - return true; - - _hasInitialized = true; - SetupGraphicsBuffer(); - return true; - } - - _mainMesh.forceRenderingOff = true; // force off if mesh is disabled - - _frameInitCounter++; - return false; - } - - public bool PostProcess() - => false; // not needed - - public void HideTransform(bool forced = false) - { - _mainMesh.forceRenderingOff = false; - - _graphicsBuffer = _mainMesh.GetVertexBuffer(); - - foreach (SubTask subTask in _subTasks) - if ((forced || subTask.IsActive) && subTask.IsValid) - subTask.Dispatch(); - - _graphicsBuffer.Release(); - } - - public void ShowTransform() - { - // not needed - } - - public void Dispose() - { - _markedForDeath = true; - foreach (SubTask subTask in _subTasks) - subTask.Dispose(); - - _graphicsBuffer?.Dispose(); - _graphicsBuffer = null; - } - - #endregion - - #region Private Methods - - // Unity is weird, so we need to wait 2 frames before we can get the graphics buffer - private void SetupGraphicsBuffer() - { - Mesh mesh = _mainMesh.sharedMesh; - - _bufferLayout = 0; - if (mesh.HasVertexAttribute(VertexAttribute.Position)) _bufferLayout += 3; - if (mesh.HasVertexAttribute(VertexAttribute.Normal)) _bufferLayout += 3; - if (mesh.HasVertexAttribute(VertexAttribute.Tangent)) _bufferLayout += 4; - // ComputeShader is doing bitshift so we dont need to multiply by 4 - - _mainMesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw; - } - - #endregion - - #region Sub Task Class - - private class SubTask : IFPRExclusionTask - { - public bool IsActive { get; set; } = true; - public bool IsValid => _computeBuffer != null; // TODO: cleanup dead tasks - - private readonly SkinnedTransformHider _parent; - private readonly Transform _shrinkBone; - private readonly int _vertexCount; - private readonly ComputeBuffer _computeBuffer; - private readonly int _threadGroups; - - public SubTask(SkinnedTransformHider parent, FPRExclusion exclusion, List exclusionVerts) - { - _parent = parent; - _shrinkBone = exclusion.target; - - _vertexCount = exclusionVerts.Count; - _computeBuffer = new ComputeBuffer(_vertexCount, sizeof(int)); - _computeBuffer.SetData(exclusionVerts.ToArray()); - - const float xThreadGroups = 64f; - _threadGroups = Mathf.CeilToInt(_vertexCount / xThreadGroups); - } - - 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 void FindExclusionVertList(SkinnedMeshRenderer renderer, IReadOnlyDictionary exclusions) - { - var boneWeights = renderer.sharedMesh.boneWeights; - - HashSet weights = new(); - for (int i = 0; i < renderer.bones.Length; i++) - { - // if bone == any key in exclusions, add to weights - if (!exclusions.TryGetValue(renderer.bones[i], out FPRExclusion _)) - continue; - - weights.Add(i); - } - - for (int i = 0; i < boneWeights.Length; i++) - { - BoneWeight weight = boneWeights[i]; - - Transform bone = null; - const float minWeightThreshold = 0.2f; - if (weights.Contains(weight.boneIndex0) && weight.weight0 > minWeightThreshold) - bone = renderer.bones[weight.boneIndex0]; - else if (weights.Contains(weight.boneIndex1) && weight.weight1 > minWeightThreshold) - bone = renderer.bones[weight.boneIndex1]; - else if (weights.Contains(weight.boneIndex2) && weight.weight2 > minWeightThreshold) - bone = renderer.bones[weight.boneIndex2]; - else if (weights.Contains(weight.boneIndex3) && weight.weight3 > minWeightThreshold) - bone = renderer.bones[weight.boneIndex3]; - - if (bone == null) continue; // no bone found - - // add vertex to exclusion list - exclusions[bone].affectedVertexIndices.Add(i); - } - } - - #endregion - } - - #endregion -} \ No newline at end of file diff --git a/BetterShadowClone/TransformHider/TransformHiderManager.cs b/BetterShadowClone/TransformHider/TransformHiderManager.cs deleted file mode 100644 index 2c14854..0000000 --- a/BetterShadowClone/TransformHider/TransformHiderManager.cs +++ /dev/null @@ -1,213 +0,0 @@ -using ABI_RC.Core.Player; -using ABI_RC.Systems.VRModeSwitch; -using MagicaCloth; -using UnityEngine; - -namespace NAK.BetterShadowClone; - -// Built on top of Koneko's BoneHider but to mimic the ShadowCloneManager - -public class TransformHiderManager : MonoBehaviour -{ - public static ComputeShader shader; - - #region Singleton Implementation - - private static TransformHiderManager _instance; - public static TransformHiderManager Instance - { - get - { - if (_instance != null) return _instance; - _instance = new GameObject("Koneko.TransformHiderManager").AddComponent (); - DontDestroyOnLoad(_instance.gameObject); - return _instance; - } - } - - #endregion - - // Game cameras - private static Camera s_MainCamera; - private static Camera s_UiCamera; - - // Settings - internal static bool s_DebugHeadHide; - internal static bool s_DisallowFprExclusions = true; - - // Implementation - private bool _hasRenderedThisFrame; - - // Shadow Clones - private readonly List s_TransformHider = new(); - public void AddTransformHider(ITransformHider clone) - => s_TransformHider.Add(clone); - - // Debug - private bool _debugHeadHiderProcessingTime; - private readonly StopWatch _stopWatch = new(); - - #region Unity Events - - private void Start() - { - if (Instance != null - && Instance != this) - { - Destroy(this); - return; - } - - UpdatePlayerCameras(); - - s_DisallowFprExclusions = ModSettings.EntryDontRespectFPR.Value; - s_DebugHeadHide = ModSettings.EntryDebugHeadHide.Value; - - VRModeSwitchEvents.OnCompletedVRModeSwitch.AddListener(OnVRModeSwitchCompleted); - } - - private void OnEnable() - { - Camera.onPreRender += MyOnPreRender; - Camera.onPostRender += MyOnPostRender; - } - - private void OnDisable() - { - Camera.onPreRender -= MyOnPreRender; - Camera.onPostRender -= MyOnPostRender; - } - - private void OnDestroy() - { - VRModeSwitchEvents.OnCompletedVRModeSwitch.RemoveListener(OnVRModeSwitchCompleted); - OnAvatarCleared(); - } - - #endregion - - #region Transform Hider Managment - - private void Update() - { - _hasRenderedThisFrame = false; - } - - private void MyOnPreRender(Camera cam) - { - if (_hasRenderedThisFrame) - return; // can only hide head once per frame - - if (cam != s_MainCamera // only hide in player cam, or if debug is on - && !s_DebugHeadHide) - return; - - if (!CheckPlayerCamWithinRange()) - return; // player is too far away (likely HoloPort or Sitting) - - if (!ShadowCloneMod.CheckWantsToHideHead(cam)) - return; // listener said no (Third Person, etc) - - _hasRenderedThisFrame = true; - - _stopWatch.Start(); - - for (int i = s_TransformHider.Count - 1; i >= 0; i--) - { - ITransformHider hider = s_TransformHider[i]; - if (hider is not { IsValid: true }) - { - hider?.Dispose(); - s_TransformHider.RemoveAt(i); - continue; // invalid or dead - } - - if (!hider.Process()) continue; // not ready yet or disabled - - hider.HideTransform(s_DisallowFprExclusions); - } - - _stopWatch.Stop(); - if (_debugHeadHiderProcessingTime) Debug.Log($"TransformHiderManager.MyOnPreRender({s_DebugHeadHide}) took {_stopWatch.ElapsedMilliseconds}ms"); - } - - private void MyOnPostRender(Camera cam) - { - if (cam != s_UiCamera) return; // ui camera is expected to render last - - for (int i = s_TransformHider.Count - 1; i >= 0; i--) - { - ITransformHider hider = s_TransformHider[i]; - if (hider is not { IsValid: true }) - { - hider?.Dispose(); - s_TransformHider.RemoveAt(i); - continue; // invalid or dead - } - - if (!hider.PostProcess()) continue; // does not need post processing - - hider.ShowTransform(); - } - } - - #endregion - - #region Game Events - - public void OnAvatarCleared() - { - // Dispose all shadow clones BEFORE game unloads avatar - // Otherwise we memory leak the shadow clones mesh & material instances!!! - foreach (ITransformHider hider in s_TransformHider) - hider.Dispose(); - s_TransformHider.Clear(); - } - - private void OnVRModeSwitchCompleted(bool _) - => UpdatePlayerCameras(); - - #endregion - - #region Private Methods - - private static void UpdatePlayerCameras() - { - s_MainCamera = PlayerSetup.Instance.GetActiveCamera().GetComponent (); - s_UiCamera = s_MainCamera.transform.Find("_UICamera").GetComponent (); - } - - private static bool CheckPlayerCamWithinRange() - { - if (PlayerSetup.Instance == null) - return false; // hack - - const float MinHeadHidingRange = 0.5f; - Vector3 playerHeadPos = PlayerSetup.Instance.GetViewWorldPosition(); - Vector3 playerCamPos = s_MainCamera.transform.position; - float scaleModifier = PlayerSetup.Instance.GetPlaySpaceScale(); - return (Vector3.Distance(playerHeadPos, playerCamPos) < (MinHeadHidingRange * scaleModifier)); - } - - #endregion - - #region Static Helpers - - internal static bool IsLegacyFPRExcluded(Component renderer) - => renderer.gameObject.name.Contains("[FPR]"); - - internal static ITransformHider CreateTransformHider(Component renderer, IReadOnlyDictionary exclusions) - { - if (IsLegacyFPRExcluded(renderer)) - return null; - - return renderer switch - { - SkinnedMeshRenderer skinnedMeshRenderer => new SkinnedTransformHider(skinnedMeshRenderer, exclusions), - MeshRenderer meshRenderer => new MeshTransformHider(meshRenderer, exclusions), - _ => null - }; - } - - #endregion -} \ No newline at end of file diff --git a/BetterShadowClone/format.json b/BetterShadowClone/format.json deleted file mode 100644 index a2374f1..0000000 --- a/BetterShadowClone/format.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "_id": -1, - "name": "EzCurls", - "modversion": "1.0.0", - "gameversion": "2023r173", - "loaderversion": "0.6.1", - "modtype": "Mod", - "author": "NotAKidoS", - "description": "A mod that allows you to tune your finger curls to your liking. Supposedly can help with VR sign language, as raw finger curls are not that great for quick and precise gestures.\n\nThe settings are not too coherent, it is mostly a bunch of things thrown at the wall, but it works for me. I hope it works for you too.", - "searchtags": [ - "curls", - "fingers", - "index", - "knuckles" - ], - "requirements": [ - "UIExpansionKit" - ], - "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r24/EzCurls.dll", - "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/EzCurls/", - "changelog": "- Initial CVRMG release", - "embedcolor": "7d7d7d" -} \ No newline at end of file diff --git a/FuckCameraIndicator/FuckCameraIndicator.csproj b/FuckCameraIndicator/FuckCameraIndicator.csproj deleted file mode 100644 index e94f9dc..0000000 --- a/FuckCameraIndicator/FuckCameraIndicator.csproj +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/FuckCameraIndicator/Main.cs b/FuckCameraIndicator/Main.cs deleted file mode 100644 index a0c7957..0000000 --- a/FuckCameraIndicator/Main.cs +++ /dev/null @@ -1,34 +0,0 @@ -using MelonLoader; -using System.Reflection; -using ABI_RC.Core.Player; -using UnityEngine; - -namespace NAK.FuckCameraIndicator; - -public class FuckCameraIndicator : MelonMod -{ - public override void OnInitializeMelon() - { - HarmonyInstance.Patch( - typeof(PuppetMaster).GetMethod(nameof(PuppetMaster.Start), BindingFlags.NonPublic | BindingFlags.Instance), - postfix: new HarmonyLib.HarmonyMethod(typeof(FuckCameraIndicator).GetMethod(nameof(OnPuppetMasterStart_Postfix), BindingFlags.NonPublic | BindingFlags.Static)) - ); - } - - private static void OnPuppetMasterStart_Postfix(PuppetMaster __instance) - { - // thanks for not making it modular, fucking spaghetti - // and why leave it a skinned mesh... lazy fucking implementation - - GameObject indicator = __instance.cameraIndicator; - GameObject lens = __instance.cameraIndicatorLense; - - // Disable NamePlate child object - const string c_CanvasPath = "[NamePlate]/Canvas"; - GameObject canvas = indicator.transform.Find(c_CanvasPath).gameObject; - canvas.SetActive(false); - - // Disable lens renderer - lens.GetComponent ().forceRenderingOff = true; - } -} \ No newline at end of file diff --git a/FuckCameraIndicator/Properties/AssemblyInfo.cs b/FuckCameraIndicator/Properties/AssemblyInfo.cs deleted file mode 100644 index 05525a7..0000000 --- a/FuckCameraIndicator/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,29 +0,0 @@ -using MelonLoader; -using NAK.FuckCameraIndicator.Properties; -using System.Reflection; - -[assembly: AssemblyVersion(AssemblyInfoParams.Version)] -[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] -[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] -[assembly: AssemblyTitle(nameof(NAK.FuckCameraIndicator))] -[assembly: AssemblyCompany(AssemblyInfoParams.Author)] -[assembly: AssemblyProduct(nameof(NAK.FuckCameraIndicator))] - -[assembly: MelonInfo( - typeof(NAK.FuckCameraIndicator.FuckCameraIndicator), - nameof(NAK.FuckCameraIndicator), - AssemblyInfoParams.Version, - AssemblyInfoParams.Author, - downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/FuckCameraIndicator" -)] - -[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")] -[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] -[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] - -namespace NAK.FuckCameraIndicator.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/FuckCameraIndicator/README.md b/FuckCameraIndicator/README.md deleted file mode 100644 index af9d39c..0000000 --- a/FuckCameraIndicator/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# EzCurls - -A mod that allows you to tune your finger curls to your liking. Supposedly can help with VR sign language, as raw finger curls are not that great for quick and precise gestures. - -The settings are not too coherent, it is mostly a bunch of things thrown at the wall, but it works for me. I hope it works for you too. - ---- - -Here is the block of text where I tell you this mod is not affiliated or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games - -> This mod is an independent creation and is 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/FuckCameraIndicator/format.json b/FuckCameraIndicator/format.json deleted file mode 100644 index a2374f1..0000000 --- a/FuckCameraIndicator/format.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "_id": -1, - "name": "EzCurls", - "modversion": "1.0.0", - "gameversion": "2023r173", - "loaderversion": "0.6.1", - "modtype": "Mod", - "author": "NotAKidoS", - "description": "A mod that allows you to tune your finger curls to your liking. Supposedly can help with VR sign language, as raw finger curls are not that great for quick and precise gestures.\n\nThe settings are not too coherent, it is mostly a bunch of things thrown at the wall, but it works for me. I hope it works for you too.", - "searchtags": [ - "curls", - "fingers", - "index", - "knuckles" - ], - "requirements": [ - "UIExpansionKit" - ], - "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r24/EzCurls.dll", - "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/EzCurls/", - "changelog": "- Initial CVRMG release", - "embedcolor": "7d7d7d" -} \ No newline at end of file diff --git a/MirrorClone/Main.cs b/MirrorClone/Main.cs deleted file mode 100644 index 87afe20..0000000 --- a/MirrorClone/Main.cs +++ /dev/null @@ -1,80 +0,0 @@ -using MelonLoader; -using System.Reflection; -using ABI_RC.Core.Player; -using ABI_RC.Core.Util; -using ABI_RC.Systems.IK; -using UnityEngine; - -namespace NAK.BetterShadowClone; - -public class MirrorCloneMod : MelonMod -{ - internal static MelonLogger.Instance Logger; - - public override void OnInitializeMelon() - { - Logger = LoggerInstance; - - ModSettings.Initialize(); - - try - { - InitializePatches(); - } - catch (Exception e) - { - Logger.Error(e); - } - } - - #region Harmony Patches - - private void InitializePatches() - { - HarmonyInstance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.Awake), BindingFlags.NonPublic | BindingFlags.Instance), - postfix: new HarmonyLib.HarmonyMethod(typeof(MirrorCloneMod).GetMethod(nameof(OnPlayerSetup_Awake_Postfix), BindingFlags.NonPublic | BindingFlags.Static)) - ); - - HarmonyInstance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)), - prefix: new HarmonyLib.HarmonyMethod(typeof(MirrorCloneMod).GetMethod(nameof(OnPlayerSetup_SetupAvatar_Prefix), BindingFlags.NonPublic | BindingFlags.Static)), - postfix: new HarmonyLib.HarmonyMethod(typeof(MirrorCloneMod).GetMethod(nameof(OnPlayerSetup_SetupAvatar_Postfix), BindingFlags.NonPublic | BindingFlags.Static)) - ); - - HarmonyInstance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)), - prefix: new HarmonyLib.HarmonyMethod(typeof(MirrorCloneMod).GetMethod(nameof(OnPlayerSetup_ClearAvatar_Prefix), BindingFlags.NonPublic | BindingFlags.Static)) - ); - - HarmonyInstance.Patch( - typeof(IKSystem).GetMethod(nameof(IKSystem.OnPostSolverUpdateGeneral), BindingFlags.NonPublic | BindingFlags.Instance), - postfix: new HarmonyLib.HarmonyMethod(typeof(MirrorCloneMod).GetMethod(nameof(OnIKSystem_OnPostSolverUpdateGeneral_Postfix), BindingFlags.NonPublic | BindingFlags.Static)) - ); - - HarmonyInstance.Patch( - typeof(TransformHiderForMainCamera).GetMethod(nameof(TransformHiderForMainCamera.ProcessHierarchy)), - prefix: new HarmonyLib.HarmonyMethod(typeof(MirrorCloneMod).GetMethod(nameof(OnTransformHiderForMainCamera_ProcessHierarchy_Prefix), BindingFlags.NonPublic | BindingFlags.Static)) - ); - } - - private static void OnPlayerSetup_Awake_Postfix() - => MirrorCloneManager.OnPlayerSetupAwake(); - - private static void OnPlayerSetup_SetupAvatar_Prefix(GameObject inAvatar) - => MirrorCloneManager.Instance.OnAvatarInitialized(inAvatar); - - private static void OnPlayerSetup_SetupAvatar_Postfix() - => MirrorCloneManager.Instance.OnAvatarConfigured(); - - private static void OnPlayerSetup_ClearAvatar_Prefix() - => MirrorCloneManager.Instance.OnAvatarDestroyed(); - - private static void OnIKSystem_OnPostSolverUpdateGeneral_Postfix() - => MirrorCloneManager.Instance.OnPostSolverUpdateGeneral(); - - private static void OnTransformHiderForMainCamera_ProcessHierarchy_Prefix(ref bool __runOriginal) - => __runOriginal = !ModSettings.EntryEnabled.Value; - - #endregion -} \ No newline at end of file diff --git a/MirrorClone/MirrorClone.csproj b/MirrorClone/MirrorClone.csproj deleted file mode 100644 index e94f9dc..0000000 --- a/MirrorClone/MirrorClone.csproj +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/MirrorClone/MirrorClone/MirrorCloneManager.cs b/MirrorClone/MirrorClone/MirrorCloneManager.cs deleted file mode 100644 index 035c9c0..0000000 --- a/MirrorClone/MirrorClone/MirrorCloneManager.cs +++ /dev/null @@ -1,247 +0,0 @@ -using ABI_RC.Core; -using ABI_RC.Core.Player; -using ABI_RC.Core.Savior; -using ABI_RC.Systems.IK; -using ABI.CCK.Components; -using UnityEngine; -using UnityEngine.Rendering; - -namespace NAK.BetterShadowClone; - -public class MirrorCloneManager : MonoBehaviour -{ - #region Static Instance - - public static MirrorCloneManager Instance { get; private set; } - - #endregion - - private bool _isAvatarConfigured; - - private GameObject _avatar; - private GameObject _mirrorClone; - private GameObject _initializationTarget; - - private CVRAnimatorManager _animatorManager; - private Animator _mirrorAnimator; - - #region Unity Events - - private void Awake() - { - if (Instance != null - && Instance != this) - { - DestroyImmediate(this); - return; - } - - Instance = this; - - MirrorCloneMod.Logger.Msg("Mirror Clone Manager initialized."); - - _animatorManager = PlayerSetup.Instance.animatorManager; - - // Create initialization target (so no components are initialized before we're ready) - _initializationTarget = new GameObject(nameof(MirrorCloneManager) + " Initialization Target"); - _initializationTarget.transform.SetParent(transform); - _initializationTarget.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); - _initializationTarget.transform.localScale = Vector3.one; - _initializationTarget.SetActive(false); - } - - private void OnDestroy() - { - if (Instance == this) - Instance = null; - } - - #endregion - - #region Game Events - - public static void OnPlayerSetupAwake() - { - if (Instance != null) - return; - - GameObject manager = new (nameof(MirrorCloneManager), typeof(MirrorCloneManager)); - DontDestroyOnLoad(manager); - } - - public void OnAvatarInitialized(GameObject avatar) - { - if (!ModSettings.EntryEnabled.Value) - return; - - if (avatar == null - || _isAvatarConfigured) - return; - - _isAvatarConfigured = true; - - _avatar = avatar; - _mirrorClone = InstantiateMirrorCopy(_avatar); - } - - public void OnAvatarConfigured() - { - if (!_isAvatarConfigured) - return; - - Animator baseAnimator = _avatar.GetComponent (); - - if (!_mirrorClone.TryGetComponent(out _mirrorAnimator)) - _mirrorAnimator = gameObject.AddComponent (); - _mirrorAnimator.runtimeAnimatorController = baseAnimator.runtimeAnimatorController; - - _animatorManager._copyAnimator = _mirrorAnimator; // thank you for existing - - var cameras = PlayerSetup.Instance.GetComponentsInChildren (true); - foreach (var camera in cameras) - { - // hide PlayerClone layer from all cameras - camera.cullingMask &= ~(1 << CVRLayers.PlayerClone); - } - - var mirrors = Resources.FindObjectsOfTypeAll (); - foreach (CVRMirror mirror in mirrors) - { - // hide PlayerLocal layer from all mirrors - mirror.m_ReflectLayers &= ~(1 << CVRLayers.PlayerLocal); - } - - // scale avatar head bone to 0 0 0 - Transform headBone = baseAnimator.GetBoneTransform(HumanBodyBones.Head); - headBone.localScale = Vector3.zero; - - CleanupAvatar(); - CleanupMirrorClone(); - SetupHumanPoseHandler(); - - _initializationTarget.SetActive(true); - } - - public void OnAvatarDestroyed() - { - if (!_isAvatarConfigured) - return; - - _avatar = null; - _mirrorAnimator = null; - if (_mirrorClone != null) - Destroy(_mirrorClone); - - _initializationTarget.SetActive(false); - - _isAvatarConfigured = false; - } - - public void OnPostSolverUpdateGeneral() - { - if (!_isAvatarConfigured) - return; - - StealTransforms(); - } - - #endregion - - #region Private Methods - - private GameObject InstantiateMirrorCopy(GameObject original) - { - GameObject clone = Instantiate(original, _initializationTarget.transform); - clone.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); - clone.name = original.name + " (Mirror Clone)"; - clone.SetLayerRecursive(CVRLayers.PlayerClone); - return clone; - } - - private void CleanupAvatar() - { - // set local avatar mesh to shadow off - var avatarMeshes = _avatar.GetComponentsInChildren (true); - foreach (SkinnedMeshRenderer avatarMesh in avatarMeshes) - { - avatarMesh.shadowCastingMode = ShadowCastingMode.Off; - avatarMesh.forceMatrixRecalculationPerRender = false; - } - } - - private void CleanupMirrorClone() - { - // destroy unneeded components - // only keep Animator - - var components = _mirrorClone.GetComponentsInChildren (true); - foreach (Component component in components) - { - if (component == null) - continue; - - // skip basic unity components - if (component is Animator - or Transform - or SkinnedMeshRenderer - or MeshRenderer - or MeshFilter) - continue; - - // skip basic CVR components - if (component is CVRAvatar or CVRAssetInfo) - { - (component as MonoBehaviour).enabled = false; - continue; - } - - Destroy(component); - } - } - - #endregion - - #region Job System - - private HumanPoseHandler _humanPoseHandler; - private Transform _hipTransform; - - private void SetupHumanPoseHandler() - { - _hipTransform = _mirrorAnimator.GetBoneTransform(HumanBodyBones.Hips); - - _humanPoseHandler?.Dispose(); - _humanPoseHandler = new HumanPoseHandler(_mirrorAnimator.avatar, _mirrorAnimator.transform); - } - - private void StealTransforms() - { - // copy transforms from avatar to mirror clone - // var avatarTransforms = _avatar.GetComponentsInChildren (true); - // var mirrorCloneTransforms = _mirrorClone.GetComponentsInChildren (true); - // for (int i = 0; i < avatarTransforms.Length; i++) - // { - // Transform avatarTransform = avatarTransforms[i]; - // Transform mirrorCloneTransform = mirrorCloneTransforms[i]; - // - // mirrorCloneTransform.SetLocalPositionAndRotation( - // avatarTransform.localPosition, - // avatarTransform.localRotation); - // } - - if (!IKSystem.Instance.IsAvatarCalibrated()) - return; - - IKSystem.Instance._humanPoseHandler.GetHumanPose(ref IKSystem.Instance._humanPose); - _humanPoseHandler.SetHumanPose(ref IKSystem.Instance._humanPose); - - if (!MetaPort.Instance.isUsingVr) - _mirrorAnimator.transform.SetPositionAndRotation(PlayerSetup.Instance.GetPlayerPosition(), PlayerSetup.Instance.GetPlayerRotation()); - else - _mirrorAnimator.transform.SetPositionAndRotation(_avatar.transform.position, _avatar.transform.rotation); - - _hipTransform.SetPositionAndRotation(IKSystem.Instance._hipTransform.position, IKSystem.Instance._hipTransform.rotation); - } - - #endregion -} \ No newline at end of file diff --git a/MirrorClone/ModSettings.cs b/MirrorClone/ModSettings.cs deleted file mode 100644 index 05c753a..0000000 --- a/MirrorClone/ModSettings.cs +++ /dev/null @@ -1,31 +0,0 @@ -using MelonLoader; -using UnityEngine; - -namespace NAK.BetterShadowClone; - -public static class ModSettings -{ - #region Melon Prefs - - private const string SettingsCategory = nameof(MirrorCloneMod); - - private static readonly MelonPreferences_Category Category = - MelonPreferences.CreateCategory(SettingsCategory); - - internal static readonly MelonPreferences_Entry EntryEnabled = - Category.CreateEntry("Enabled", true, - description: "Enable Mirror Clone."); - - #endregion - - internal static void Initialize() - { - foreach (MelonPreferences_Entry setting in Category.Entries) - setting.OnEntryValueChangedUntyped.Subscribe(OnSettingsChanged); - } - - internal static void OnSettingsChanged(object oldValue = null, object newValue = null) - { - - } -} \ No newline at end of file diff --git a/MirrorClone/Properties/AssemblyInfo.cs b/MirrorClone/Properties/AssemblyInfo.cs deleted file mode 100644 index 611ba51..0000000 --- a/MirrorClone/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,29 +0,0 @@ -using MelonLoader; -using NAK.BetterShadowClone.Properties; -using System.Reflection; - -[assembly: AssemblyVersion(AssemblyInfoParams.Version)] -[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] -[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] -[assembly: AssemblyTitle(nameof(NAK.BetterShadowClone))] -[assembly: AssemblyCompany(AssemblyInfoParams.Author)] -[assembly: AssemblyProduct(nameof(NAK.BetterShadowClone))] - -[assembly: MelonInfo( - typeof(NAK.BetterShadowClone.MirrorCloneMod), - nameof(NAK.BetterShadowClone), - AssemblyInfoParams.Version, - AssemblyInfoParams.Author, - downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/MirrorCloneMod" -)] - -[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")] -[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] -[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] - -namespace NAK.BetterShadowClone.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/MirrorClone/README.md b/MirrorClone/README.md deleted file mode 100644 index af9d39c..0000000 --- a/MirrorClone/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# EzCurls - -A mod that allows you to tune your finger curls to your liking. Supposedly can help with VR sign language, as raw finger curls are not that great for quick and precise gestures. - -The settings are not too coherent, it is mostly a bunch of things thrown at the wall, but it works for me. I hope it works for you too. - ---- - -Here is the block of text where I tell you this mod is not affiliated or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games - -> This mod is an independent creation and is 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/MirrorClone/format.json b/MirrorClone/format.json deleted file mode 100644 index a2374f1..0000000 --- a/MirrorClone/format.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "_id": -1, - "name": "EzCurls", - "modversion": "1.0.0", - "gameversion": "2023r173", - "loaderversion": "0.6.1", - "modtype": "Mod", - "author": "NotAKidoS", - "description": "A mod that allows you to tune your finger curls to your liking. Supposedly can help with VR sign language, as raw finger curls are not that great for quick and precise gestures.\n\nThe settings are not too coherent, it is mostly a bunch of things thrown at the wall, but it works for me. I hope it works for you too.", - "searchtags": [ - "curls", - "fingers", - "index", - "knuckles" - ], - "requirements": [ - "UIExpansionKit" - ], - "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r24/EzCurls.dll", - "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/EzCurls/", - "changelog": "- Initial CVRMG release", - "embedcolor": "7d7d7d" -} \ No newline at end of file diff --git a/NAK_CVR_Mods.sln b/NAK_CVR_Mods.sln index cf5c2e2..c602176 100644 --- a/NAK_CVR_Mods.sln +++ b/NAK_CVR_Mods.sln @@ -31,12 +31,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EzCurls", "EzCurls\EzCurls. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhysicsGunMod", "PhysicsGunMod\PhysicsGunMod.csproj", "{F94DDB73-9041-4F5C-AD43-6960701E8417}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MirrorClone", "MirrorClone\MirrorClone.csproj", "{D5E81123-9D3B-4420-9CCD-1861657BE00B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BetterShadowClone", "BetterShadowClone\BetterShadowClone.csproj", "{D0C40987-AF16-490A-9304-F99D5A5A774C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FuckCameraIndicator", "FuckCameraIndicator\FuckCameraIndicator.csproj", "{0BE10630-EA6A-40FB-B3AF-5C2018F22BD3}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nevermind", "Nevermind\Nevermind.csproj", "{AC4857DD-F6D9-436D-A3EE-D148A518E642}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShadowCloneFallback", "ShadowCloneFallback\ShadowCloneFallback.csproj", "{69AF3C10-1BB1-4746-B697-B5A81D78C8D9}" @@ -85,8 +79,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AvatarQueueSystemTweaks", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomSpawnPoint", "CustomSpawnPoint\CustomSpawnPoint.csproj", "{51CA34CA-7684-4819-AC9E-89DFAD63E9AB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NukePostPresentHandoff", "NukePostPresentHandoff\NukePostPresentHandoff.csproj", "{77F332CD-019A-472F-9269-CFDEB087B3F9}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CVRLuaToolsExtension", "CVRLuaToolsExtension\CVRLuaToolsExtension.csproj", "{FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stickers", "Stickers\Stickers.csproj", "{E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}" @@ -157,18 +149,6 @@ Global {F94DDB73-9041-4F5C-AD43-6960701E8417}.Debug|Any CPU.Build.0 = Debug|Any CPU {F94DDB73-9041-4F5C-AD43-6960701E8417}.Release|Any CPU.ActiveCfg = Release|Any CPU {F94DDB73-9041-4F5C-AD43-6960701E8417}.Release|Any CPU.Build.0 = Release|Any CPU - {D5E81123-9D3B-4420-9CCD-1861657BE00B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D5E81123-9D3B-4420-9CCD-1861657BE00B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D5E81123-9D3B-4420-9CCD-1861657BE00B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D5E81123-9D3B-4420-9CCD-1861657BE00B}.Release|Any CPU.Build.0 = Release|Any CPU - {D0C40987-AF16-490A-9304-F99D5A5A774C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D0C40987-AF16-490A-9304-F99D5A5A774C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D0C40987-AF16-490A-9304-F99D5A5A774C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D0C40987-AF16-490A-9304-F99D5A5A774C}.Release|Any CPU.Build.0 = Release|Any CPU - {0BE10630-EA6A-40FB-B3AF-5C2018F22BD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0BE10630-EA6A-40FB-B3AF-5C2018F22BD3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0BE10630-EA6A-40FB-B3AF-5C2018F22BD3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0BE10630-EA6A-40FB-B3AF-5C2018F22BD3}.Release|Any CPU.Build.0 = Release|Any CPU {AC4857DD-F6D9-436D-A3EE-D148A518E642}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AC4857DD-F6D9-436D-A3EE-D148A518E642}.Debug|Any CPU.Build.0 = Debug|Any CPU {AC4857DD-F6D9-436D-A3EE-D148A518E642}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -265,10 +245,6 @@ Global {51CA34CA-7684-4819-AC9E-89DFAD63E9AB}.Debug|Any CPU.Build.0 = Debug|Any CPU {51CA34CA-7684-4819-AC9E-89DFAD63E9AB}.Release|Any CPU.ActiveCfg = Release|Any CPU {51CA34CA-7684-4819-AC9E-89DFAD63E9AB}.Release|Any CPU.Build.0 = Release|Any CPU - {77F332CD-019A-472F-9269-CFDEB087B3F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {77F332CD-019A-472F-9269-CFDEB087B3F9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {77F332CD-019A-472F-9269-CFDEB087B3F9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {77F332CD-019A-472F-9269-CFDEB087B3F9}.Release|Any CPU.Build.0 = Release|Any CPU {FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}.Debug|Any CPU.Build.0 = Debug|Any CPU {FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}.Release|Any CPU.ActiveCfg = Release|Any CPU