mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-02 14:29:25 +00:00
[AvatarScaleMod] Refactor & Avatar Parameters
This commit is contained in:
parent
5b7b586298
commit
acacc21050
5 changed files with 322 additions and 162 deletions
|
@ -1,26 +1,28 @@
|
|||
using UnityEngine;
|
||||
using ABI_RC.Core.Savior;
|
||||
using ABI_RC.Core.Savior;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NAK.AvatarScaleMod;
|
||||
|
||||
public static class AvatarScaleGesture
|
||||
{
|
||||
// Toggle for scale gesture
|
||||
public static bool GestureEnabled;
|
||||
|
||||
// Require triggers to be down while doing fist? - Exteratta
|
||||
public static bool RequireTriggers = true;
|
||||
public static float InitialModifier = 1f;
|
||||
public static float InitialTargetHeight = 1.8f;
|
||||
|
||||
// Initial values when scale gesture is started
|
||||
public static float InitialModifier;
|
||||
public static float InitialTargetHeight;
|
||||
|
||||
public static void OnScaleStart(float modifier, Transform transform1, Transform transform2)
|
||||
{
|
||||
// AvatarScaleMod.Logger.Msg("OnScaleStart!");
|
||||
if (!GestureEnabled)
|
||||
return;
|
||||
|
||||
// you can start the scale, but cant interact with it without holding triggers
|
||||
|
||||
if (AvatarScaleManager.LocalAvatar != null)
|
||||
{
|
||||
// store initial modifier
|
||||
// Store initial modifier so we can get difference later
|
||||
InitialModifier = modifier;
|
||||
InitialTargetHeight = AvatarScaleManager.LocalAvatar.TargetHeight;
|
||||
}
|
||||
|
@ -28,16 +30,21 @@ public static class AvatarScaleGesture
|
|||
|
||||
public static void OnScaleStay(float modifier, Transform transform1, Transform transform2)
|
||||
{
|
||||
// AvatarScaleMod.Logger.Msg("OnScaleStay!");
|
||||
if (!GestureEnabled)
|
||||
return;
|
||||
|
||||
if (RequireTriggers && !IsBothTriggersDown())
|
||||
// Allow user to release triggers to reset "world grip"
|
||||
if (RequireTriggers && !AreBothTriggersDown())
|
||||
{
|
||||
InitialModifier = modifier;
|
||||
InitialTargetHeight = AvatarScaleManager.LocalAvatar.TargetHeight;
|
||||
return;
|
||||
}
|
||||
|
||||
if (AvatarScaleManager.LocalAvatar != null)
|
||||
{
|
||||
float modifierRatio = modifier / InitialModifier;
|
||||
// Invert so the gesture is more of a world squish instead of happy hug
|
||||
float modifierRatio = 1f / (modifier / InitialModifier);
|
||||
|
||||
// Determine the adjustment factor for the height, this will be >1 if scaling up, <1 if scaling down.
|
||||
float heightAdjustmentFactor = (modifierRatio > 1) ? 1 + (modifierRatio - 1) : 1 - (1 - modifierRatio);
|
||||
|
@ -46,14 +53,15 @@ public static class AvatarScaleGesture
|
|||
AvatarScaleManager.LocalAvatar.SetTargetHeight(InitialTargetHeight * heightAdjustmentFactor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void OnScaleEnd(float modifier, Transform transform1, Transform transform2)
|
||||
{
|
||||
// AvatarScaleMod.Logger.Msg("OnScaleEnd!");
|
||||
// Unused, needed for mod network?
|
||||
}
|
||||
|
||||
public static bool IsBothTriggersDown()
|
||||
|
||||
// Maybe it should be one trigger? Imagine XSOverlay scaling but for player.
|
||||
public static bool AreBothTriggersDown()
|
||||
{
|
||||
return CVRInputManager.Instance.interactLeftValue > 0.75f && CVRInputManager.Instance.interactRightValue > 0.75f;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using ABI.CCK.Components;
|
||||
using ABI_RC.Core.Player;
|
||||
using NAK.AvatarScaleMod.ScaledComponents;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
@ -8,66 +9,143 @@ namespace NAK.AvatarScaleMod;
|
|||
|
||||
public class AvatarScaleManager : MonoBehaviour
|
||||
{
|
||||
public static AvatarScaleManager LocalAvatar { get; private set; }
|
||||
// Constants
|
||||
public const float MinHeight = 0.1f; // TODO: Make into Setting
|
||||
public const float MaxHeight = 10f; // TODO: Make into Setting
|
||||
public const string ScaleFactorParameterName = "ScaleFactor";
|
||||
public const string ScaleFactorParameterNameLocal = "#ScaleFactor";
|
||||
|
||||
// List of component types to be collected and scaled
|
||||
private static readonly System.Type[] scaleComponentTypes = new System.Type[]
|
||||
private static readonly System.Type[] scalableComponentTypes =
|
||||
{
|
||||
typeof(Light),
|
||||
typeof(AudioSource),
|
||||
typeof(ParticleSystem),
|
||||
typeof(ParentConstraint),
|
||||
typeof(PositionConstraint),
|
||||
typeof(ScaleConstraint),
|
||||
typeof(ScaleConstraint)
|
||||
};
|
||||
|
||||
public const float MinimumHeight = 0.1f;
|
||||
public const float MaximumHeight = 10f;
|
||||
|
||||
// Scalable Components
|
||||
private List<ScaledLight> _lights = new List<ScaledLight>();
|
||||
private List<ScaledAudioSource> _audioSources = new List<ScaledAudioSource>();
|
||||
//private List<ScaledComponent<ParticleSystem>> _particleSystems = new List<ScaledComponent<ParticleSystem>>();
|
||||
private List<ScaledParentConstraint> _parentConstraints = new List<ScaledParentConstraint>();
|
||||
private List<ScaledPositionConstraint> _positionConstraints = new List<ScaledPositionConstraint>();
|
||||
private List<ScaledScaleConstraint> _scaleConstraints = new List<ScaledScaleConstraint>();
|
||||
// Public properties
|
||||
public static bool GlobalEnabled { get; set; }
|
||||
public static AvatarScaleManager LocalAvatar { get; private set; }
|
||||
|
||||
public float TargetHeight { get; private set; }
|
||||
public float InitialHeight { get; private set; }
|
||||
public Vector3 InitialScale { get; private set; }
|
||||
public float ScaleFactor { get; private set; }
|
||||
|
||||
public void Initialize(float initialHeight, Vector3 initialScale)
|
||||
// Private properties
|
||||
private bool _isLocalAvatar;
|
||||
private Animator _animator;
|
||||
private CVRAvatar _avatar;
|
||||
|
||||
private List<ScaledLight> _scaledLights = new List<ScaledLight>();
|
||||
private List<ScaledAudioSource> _scaledAudioSources = new List<ScaledAudioSource>();
|
||||
private List<ScaledParentConstraint> _scaledParentConstraints = new List<ScaledParentConstraint>();
|
||||
private List<ScaledPositionConstraint> _scaledPositionConstraints = new List<ScaledPositionConstraint>();
|
||||
private List<ScaledScaleConstraint> _scaledScaleConstraints = new List<ScaledScaleConstraint>();
|
||||
|
||||
public void Initialize(float initialHeight, Vector3 initialScale, bool isLocalAvatar)
|
||||
{
|
||||
// Check for zero height
|
||||
if (Math.Abs(initialHeight) < 1E-6)
|
||||
{
|
||||
AvatarScaleMod.Logger.Warning("Cannot initialize with a height of zero!");
|
||||
return;
|
||||
}
|
||||
|
||||
this.TargetHeight = 1f;
|
||||
if (isLocalAvatar && LocalAvatar == null)
|
||||
{
|
||||
_isLocalAvatar = true;
|
||||
LocalAvatar = this;
|
||||
}
|
||||
|
||||
this.TargetHeight = initialHeight;
|
||||
this.InitialHeight = initialHeight;
|
||||
this.InitialScale = initialScale;
|
||||
UpdateScaleFactor();
|
||||
this.ScaleFactor = 1f;
|
||||
}
|
||||
|
||||
private async void Start()
|
||||
{
|
||||
_avatar = GetComponent<CVRAvatar>();
|
||||
|
||||
if (_avatar == null)
|
||||
{
|
||||
AvatarScaleMod.Logger.Error("AvatarScaleManager should be attached to a GameObject with a CVRAvatar component.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_isLocalAvatar)
|
||||
{
|
||||
_animator = GetComponent<Animator>();
|
||||
}
|
||||
|
||||
// I am unsure if this reduces the hitch or not.
|
||||
// I do not want to patch where the game already does scanning though.
|
||||
await FindComponentsOfTypeAsync(scalableComponentTypes);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
// TODO: Test with Avatar Distance Hider
|
||||
ResetAllToInitialScale();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
ClearLists();
|
||||
|
||||
if (LocalAvatar == this)
|
||||
{
|
||||
LocalAvatar = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearLists()
|
||||
{
|
||||
_scaledAudioSources.Clear();
|
||||
_scaledLights.Clear();
|
||||
_scaledParentConstraints.Clear();
|
||||
_scaledPositionConstraints.Clear();
|
||||
_scaledScaleConstraints.Clear();
|
||||
}
|
||||
|
||||
public void SetTargetHeight(float newHeight)
|
||||
{
|
||||
TargetHeight = Mathf.Clamp(newHeight, MinimumHeight, MaximumHeight);
|
||||
TargetHeight = Mathf.Clamp(newHeight, MinHeight, MaxHeight);
|
||||
UpdateScaleFactor();
|
||||
UpdateAnimatorParameter();
|
||||
}
|
||||
|
||||
public void UpdateScaleFactor()
|
||||
public void SetTargetHeightOverTime(float newHeight, float duration)
|
||||
{
|
||||
StartCoroutine(SetTargetHeightOverTimeCoroutine(newHeight, duration));
|
||||
}
|
||||
|
||||
private void UpdateScaleFactor()
|
||||
{
|
||||
// Check for zero
|
||||
if (Math.Abs(InitialHeight) < 1E-6)
|
||||
{
|
||||
AvatarScaleMod.Logger.Warning("InitialHeight is zero, cannot calculate ScaleFactor.");
|
||||
return;
|
||||
}
|
||||
|
||||
this.ScaleFactor = TargetHeight / InitialHeight;
|
||||
ScaleFactor = TargetHeight / InitialHeight;
|
||||
}
|
||||
|
||||
private void UpdateAnimatorParameter()
|
||||
{
|
||||
if (_isLocalAvatar)
|
||||
{
|
||||
// Set synced and local parameters for Local Player
|
||||
PlayerSetup.Instance.animatorManager.SetAnimatorParameter(ScaleFactorParameterName, ScaleFactor);
|
||||
PlayerSetup.Instance.animatorManager.SetAnimatorParameter(ScaleFactorParameterNameLocal, ScaleFactor);
|
||||
}
|
||||
else if (_animator != null)
|
||||
{
|
||||
// Set local parameter for Remote Player
|
||||
_animator.SetFloat(ScaleFactorParameterNameLocal, ScaleFactor);
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3 CalculateNewScale()
|
||||
|
@ -75,68 +153,70 @@ public class AvatarScaleManager : MonoBehaviour
|
|||
return InitialScale * ScaleFactor;
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
private IEnumerator SetTargetHeightOverTimeCoroutine(float newHeight, float duration)
|
||||
{
|
||||
// why am i caching the avatar
|
||||
CVRAvatar avatar = GetComponent<CVRAvatar>();
|
||||
if (avatar == null)
|
||||
float startTime = Time.time;
|
||||
float startHeight = TargetHeight;
|
||||
|
||||
// Clamping the newHeight to be between MinHeight and MaxHeight
|
||||
newHeight = Mathf.Clamp(newHeight, MinHeight, MaxHeight);
|
||||
|
||||
while (Time.time < startTime + duration)
|
||||
{
|
||||
AvatarScaleMod.Logger.Error("AvatarScaleManager should be attached to a GameObject with a CVRAvatar component.");
|
||||
return;
|
||||
float t = (Time.time - startTime) / duration;
|
||||
TargetHeight = Mathf.Lerp(startHeight, newHeight, t);
|
||||
UpdateScaleFactor();
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// i cant believe i would stoop this low
|
||||
if (gameObject.layer == 8 && LocalAvatar == null)
|
||||
LocalAvatar = this;
|
||||
|
||||
FindComponentsOfType(scaleComponentTypes);
|
||||
// Final setting of the TargetHeight after the loop is done.
|
||||
TargetHeight = newHeight;
|
||||
UpdateScaleFactor();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
// TODO: actually profile this
|
||||
private async Task FindComponentsOfTypeAsync(Type[] types)
|
||||
{
|
||||
_audioSources.Clear();
|
||||
_lights.Clear();
|
||||
//_particleSystems.Clear(); // fuck no
|
||||
_parentConstraints.Clear();
|
||||
_positionConstraints.Clear();
|
||||
_scaleConstraints.Clear();
|
||||
var tasks = new List<Task>();
|
||||
var components = GetComponentsInChildren<Component>(true);
|
||||
|
||||
// local player manager
|
||||
if (LocalAvatar == this)
|
||||
LocalAvatar = null;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
ResetAllToInitialScale();
|
||||
}
|
||||
|
||||
private void FindComponentsOfType(params System.Type[] types)
|
||||
{
|
||||
foreach (var type in types)
|
||||
foreach (var component in components)
|
||||
{
|
||||
var components = gameObject.GetComponentsInChildren(type, true);
|
||||
foreach (var component in components)
|
||||
if (this == null) break;
|
||||
if (component == null) continue;
|
||||
|
||||
tasks.Add(Task.Run(() =>
|
||||
{
|
||||
switch (component)
|
||||
var componentType = component.GetType();
|
||||
if (types.Contains(componentType))
|
||||
{
|
||||
case AudioSource audioSource:
|
||||
_audioSources.Add(new ScaledAudioSource(audioSource));
|
||||
break;
|
||||
case Light light:
|
||||
_lights.Add(new ScaledLight(light));
|
||||
break;
|
||||
case ParentConstraint parentConstraint:
|
||||
_parentConstraints.Add(new ScaledParentConstraint(parentConstraint));
|
||||
break;
|
||||
case PositionConstraint positionConstraint:
|
||||
_positionConstraints.Add(new ScaledPositionConstraint(positionConstraint));
|
||||
break;
|
||||
case ScaleConstraint scaleConstraint:
|
||||
_scaleConstraints.Add(new ScaledScaleConstraint(scaleConstraint));
|
||||
break;
|
||||
AddScaledComponent(componentType, component);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
private void AddScaledComponent(Type type, Component component)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Type _ when type == typeof(AudioSource):
|
||||
_scaledAudioSources.Add(new ScaledAudioSource((AudioSource)component));
|
||||
break;
|
||||
case Type _ when type == typeof(Light):
|
||||
_scaledLights.Add(new ScaledLight((Light)component));
|
||||
break;
|
||||
case Type _ when type == typeof(ParentConstraint):
|
||||
_scaledParentConstraints.Add(new ScaledParentConstraint((ParentConstraint)component));
|
||||
break;
|
||||
case Type _ when type == typeof(PositionConstraint):
|
||||
_scaledPositionConstraints.Add(new ScaledPositionConstraint((PositionConstraint)component));
|
||||
break;
|
||||
case Type _ when type == typeof(ScaleConstraint):
|
||||
_scaledScaleConstraints.Add(new ScaledScaleConstraint((ScaleConstraint)component));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,11 +234,17 @@ public class AvatarScaleManager : MonoBehaviour
|
|||
|
||||
private void ApplyAvatarScaling()
|
||||
{
|
||||
if (!GlobalEnabled)
|
||||
return;
|
||||
|
||||
transform.localScale = CalculateNewScale();
|
||||
}
|
||||
|
||||
private void ApplyComponentScaling()
|
||||
{
|
||||
if (!GlobalEnabled)
|
||||
return;
|
||||
|
||||
UpdateLightScales();
|
||||
UpdateAudioSourceScales();
|
||||
UpdateParentConstraintScales();
|
||||
|
@ -168,103 +254,89 @@ public class AvatarScaleManager : MonoBehaviour
|
|||
|
||||
private void UpdateLightScales()
|
||||
{
|
||||
foreach (var scaledLight in _lights)
|
||||
// Update range of each light component
|
||||
foreach (var light in _scaledLights)
|
||||
{
|
||||
scaledLight.Component.range = scaledLight.InitialRange * ScaleFactor;
|
||||
light.Component.range = light.InitialRange * ScaleFactor;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAudioSourceScales()
|
||||
{
|
||||
foreach (var scaledAudioSource in _audioSources)
|
||||
// Update min and max distance of each audio source component
|
||||
foreach (var audioSource in _scaledAudioSources)
|
||||
{
|
||||
scaledAudioSource.Component.minDistance = scaledAudioSource.InitialMinDistance * ScaleFactor;
|
||||
scaledAudioSource.Component.maxDistance = scaledAudioSource.InitialMaxDistance * ScaleFactor;
|
||||
audioSource.Component.minDistance = audioSource.InitialMinDistance * ScaleFactor;
|
||||
audioSource.Component.maxDistance = audioSource.InitialMaxDistance * ScaleFactor;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateParentConstraintScales()
|
||||
{
|
||||
foreach (var scaledParentConstraint in _parentConstraints)
|
||||
// Update translationAtRest and translationOffsets of each parent constraint component
|
||||
foreach (var parentConstraint in _scaledParentConstraints)
|
||||
{
|
||||
scaledParentConstraint.Component.translationAtRest = scaledParentConstraint.InitialTranslationAtRest * ScaleFactor;
|
||||
parentConstraint.Component.translationAtRest = parentConstraint.InitialTranslationAtRest * ScaleFactor;
|
||||
|
||||
for (int i = 0; i < scaledParentConstraint.InitialTranslationOffsets.Count; i++)
|
||||
for (int i = 0; i < parentConstraint.InitialTranslationOffsets.Count; i++)
|
||||
{
|
||||
scaledParentConstraint.Component.translationOffsets[i] = scaledParentConstraint.InitialTranslationOffsets[i] * ScaleFactor;
|
||||
parentConstraint.Component.translationOffsets[i] = parentConstraint.InitialTranslationOffsets[i] * ScaleFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePositionConstraintScales()
|
||||
{
|
||||
foreach (var scaledPositionConstraint in _positionConstraints)
|
||||
// Update translationAtRest and translationOffset of each position constraint component
|
||||
foreach (var positionConstraint in _scaledPositionConstraints)
|
||||
{
|
||||
scaledPositionConstraint.Component.translationAtRest = scaledPositionConstraint.InitialTranslationAtRest * ScaleFactor;
|
||||
scaledPositionConstraint.Component.translationOffset = scaledPositionConstraint.InitialTranslationOffset * ScaleFactor;
|
||||
positionConstraint.Component.translationAtRest = positionConstraint.InitialTranslationAtRest * ScaleFactor;
|
||||
positionConstraint.Component.translationOffset = positionConstraint.InitialTranslationOffset * ScaleFactor;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateScaleConstraintScales()
|
||||
{
|
||||
foreach (var scaledScaleConstraint in _scaleConstraints)
|
||||
// Update scaleAtRest and scaleOffset of each scale constraint component
|
||||
foreach (var scaleConstraint in _scaledScaleConstraints)
|
||||
{
|
||||
scaledScaleConstraint.Component.scaleAtRest = scaledScaleConstraint.InitialScaleAtRest * ScaleFactor;
|
||||
scaledScaleConstraint.Component.scaleOffset = scaledScaleConstraint.InitialScaleOffset * ScaleFactor;
|
||||
scaleConstraint.Component.scaleAtRest = scaleConstraint.InitialScaleAtRest * ScaleFactor;
|
||||
scaleConstraint.Component.scaleOffset = scaleConstraint.InitialScaleOffset * ScaleFactor;
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetAllToInitialScale()
|
||||
{
|
||||
// quick n lazy for right now
|
||||
// Reset transform scale and each component to their initial scales
|
||||
transform.localScale = InitialScale;
|
||||
|
||||
foreach (var scaledLight in _lights)
|
||||
foreach (var light in _scaledLights)
|
||||
{
|
||||
scaledLight.Component.range = scaledLight.InitialRange;
|
||||
light.Component.range = light.InitialRange;
|
||||
}
|
||||
foreach (var scaledAudioSource in _audioSources)
|
||||
foreach (var audioSource in _scaledAudioSources)
|
||||
{
|
||||
scaledAudioSource.Component.minDistance = scaledAudioSource.InitialMinDistance;
|
||||
scaledAudioSource.Component.maxDistance = scaledAudioSource.InitialMaxDistance;
|
||||
audioSource.Component.minDistance = audioSource.InitialMinDistance;
|
||||
audioSource.Component.maxDistance = audioSource.InitialMaxDistance;
|
||||
}
|
||||
foreach (var scaledParentConstraint in _parentConstraints)
|
||||
foreach (var parentConstraint in _scaledParentConstraints)
|
||||
{
|
||||
scaledParentConstraint.Component.translationAtRest = scaledParentConstraint.InitialTranslationAtRest;
|
||||
parentConstraint.Component.translationAtRest = parentConstraint.InitialTranslationAtRest;
|
||||
|
||||
for (int i = 0; i < scaledParentConstraint.InitialTranslationOffsets.Count; i++)
|
||||
for (int i = 0; i < parentConstraint.InitialTranslationOffsets.Count; i++)
|
||||
{
|
||||
scaledParentConstraint.Component.translationOffsets[i] = scaledParentConstraint.InitialTranslationOffsets[i];
|
||||
parentConstraint.Component.translationOffsets[i] = parentConstraint.InitialTranslationOffsets[i];
|
||||
}
|
||||
}
|
||||
foreach (var scaledPositionConstraint in _positionConstraints)
|
||||
foreach (var positionConstraint in _scaledPositionConstraints)
|
||||
{
|
||||
scaledPositionConstraint.Component.translationAtRest = scaledPositionConstraint.InitialTranslationAtRest;
|
||||
scaledPositionConstraint.Component.translationOffset = scaledPositionConstraint.InitialTranslationOffset;
|
||||
positionConstraint.Component.translationAtRest = positionConstraint.InitialTranslationAtRest;
|
||||
positionConstraint.Component.translationOffset = positionConstraint.InitialTranslationOffset;
|
||||
}
|
||||
foreach (var scaledScaleConstraint in _scaleConstraints)
|
||||
foreach (var scaleConstraint in _scaledScaleConstraints)
|
||||
{
|
||||
scaledScaleConstraint.Component.scaleAtRest = scaledScaleConstraint.InitialScaleAtRest;
|
||||
scaledScaleConstraint.Component.scaleOffset = scaledScaleConstraint.InitialScaleOffset;
|
||||
scaleConstraint.Component.scaleAtRest = scaleConstraint.InitialScaleAtRest;
|
||||
scaleConstraint.Component.scaleOffset = scaleConstraint.InitialScaleOffset;
|
||||
}
|
||||
}
|
||||
|
||||
// use for slow transition between avatars initial height & saved height>>>??????????????
|
||||
public IEnumerator SetTargetHeightOverTime(float newHeight, float duration)
|
||||
{
|
||||
float startTime = Time.time;
|
||||
float startHeight = TargetHeight;
|
||||
newHeight = Mathf.Clamp(newHeight, MinimumHeight, MaximumHeight);
|
||||
|
||||
while (Time.time < startTime + duration)
|
||||
{
|
||||
float t = (Time.time - startTime) / duration;
|
||||
TargetHeight = Mathf.Lerp(startHeight, newHeight, t);
|
||||
UpdateScaleFactor();
|
||||
yield return null;
|
||||
}
|
||||
|
||||
TargetHeight = newHeight;
|
||||
UpdateScaleFactor();
|
||||
}
|
||||
}
|
|
@ -3,6 +3,8 @@ using ABI_RC.Core.Savior;
|
|||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using ABI_RC.Systems.IK;
|
||||
using RootMotion.FinalIK;
|
||||
|
||||
namespace NAK.AvatarScaleMod.HarmonyPatches;
|
||||
|
||||
|
@ -14,7 +16,8 @@ class PlayerSetupPatches
|
|||
{
|
||||
try
|
||||
{
|
||||
__instance._avatar.AddComponent<AvatarScaleManager>().Initialize(__instance._initialAvatarHeight, __instance.initialScale);
|
||||
__instance._avatar.AddComponent<AvatarScaleManager>().Initialize(__instance._initialAvatarHeight, __instance.initialScale, true);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -22,6 +25,54 @@ class PlayerSetupPatches
|
|||
AvatarScaleMod.Logger.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
static Vector3 originalPosition;
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(PlayerSetup), nameof(PlayerSetup.SetPlaySpaceScale))]
|
||||
static void Prefix_PlayerSetup_SetPlaySpaceScale(ref PlayerSetup __instance)
|
||||
{
|
||||
originalPosition = __instance.vrCamera.transform.position;
|
||||
originalPosition.y = __instance.transform.position.y;
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(PlayerSetup), nameof(PlayerSetup.SetPlaySpaceScale))]
|
||||
static void Postfix_PlayerSetup_SetPlaySpaceScale(ref PlayerSetup __instance)
|
||||
{
|
||||
Vector3 newPosition = __instance.vrCamera.transform.position;
|
||||
newPosition.y = __instance.transform.position.y;
|
||||
|
||||
Vector3 offset = newPosition - originalPosition;
|
||||
|
||||
// Apply the offset to the VR camera rig's position
|
||||
__instance.transform.position -= offset;
|
||||
|
||||
//if (IKSystem.vrik != null)
|
||||
//{
|
||||
// IKSystem.vrik.solver.locomotion.AddDeltaPosition(offset * 2);
|
||||
// IKSystem.vrik.solver.raycastOriginPelvis += offset * 2;
|
||||
// IKSystem.vrik.solver.Reset();
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
class PuppetMasterPatches
|
||||
{
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(PuppetMaster), nameof(PuppetMaster.AvatarInstantiated))]
|
||||
static void Postfix_PuppetMaster_AvatarInstantiated(ref PuppetMaster __instance)
|
||||
{
|
||||
try
|
||||
{
|
||||
__instance.avatarObject.AddComponent<AvatarScaleManager>().Initialize(__instance._initialAvatarHeight, __instance.initialAvatarScale, false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
AvatarScaleMod.Logger.Error($"Error during the patched method {nameof(Postfix_PuppetMaster_AvatarInstantiated)}");
|
||||
AvatarScaleMod.Logger.Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GesturePlaneTestPatches
|
||||
|
@ -33,24 +84,45 @@ class GesturePlaneTestPatches
|
|||
try
|
||||
{
|
||||
// nicked from Kafe >:))))
|
||||
|
||||
// This requires arms far outward- pull inward with fist and triggers.
|
||||
// Release triggers while still holding fist to readjust.
|
||||
|
||||
var gesture = new CVRGesture
|
||||
{
|
||||
name = "avatarScale",
|
||||
name = "avatarScaleIn",
|
||||
type = CVRGesture.GestureType.Hold,
|
||||
};
|
||||
// TODO: Expose these settings in-game and tune till they feel right
|
||||
gesture.steps.Add(new CVRGestureStep
|
||||
{
|
||||
firstGesture = CVRGestureStep.Gesture.Fist,
|
||||
secondGesture = CVRGestureStep.Gesture.Fist,
|
||||
startDistance = 0.5f,
|
||||
endDistance = 0.4f,
|
||||
startDistance = 1f,
|
||||
endDistance = 0.25f,
|
||||
direction = CVRGestureStep.GestureDirection.MovingIn,
|
||||
});
|
||||
gesture.onStart.AddListener(new UnityAction<float, Transform, Transform>(AvatarScaleGesture.OnScaleStart));
|
||||
gesture.onStay.AddListener(new UnityAction<float, Transform, Transform>(AvatarScaleGesture.OnScaleStay));
|
||||
gesture.onEnd.AddListener(new UnityAction<float, Transform, Transform>(AvatarScaleGesture.OnScaleEnd));
|
||||
CVRGestureRecognizer.Instance.gestures.Add(gesture);
|
||||
|
||||
gesture = new CVRGesture
|
||||
{
|
||||
name = "avatarScaleOut",
|
||||
type = CVRGesture.GestureType.Hold,
|
||||
};
|
||||
gesture.steps.Add(new CVRGestureStep
|
||||
{
|
||||
firstGesture = CVRGestureStep.Gesture.Fist,
|
||||
secondGesture = CVRGestureStep.Gesture.Fist,
|
||||
startDistance = 0.25f,
|
||||
endDistance = 1f,
|
||||
direction = CVRGestureStep.GestureDirection.MovingOut,
|
||||
});
|
||||
gesture.onStart.AddListener(new UnityAction<float, Transform, Transform>(AvatarScaleGesture.OnScaleStart));
|
||||
gesture.onStay.AddListener(new UnityAction<float, Transform, Transform>(AvatarScaleGesture.OnScaleStay));
|
||||
gesture.onEnd.AddListener(new UnityAction<float, Transform, Transform>(AvatarScaleGesture.OnScaleEnd));
|
||||
CVRGestureRecognizer.Instance.gestures.Add(gesture);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -6,21 +6,13 @@ public class AvatarScaleMod : MelonMod
|
|||
{
|
||||
internal static MelonLogger.Instance Logger;
|
||||
|
||||
public static readonly MelonPreferences_Category Category =
|
||||
MelonPreferences.CreateCategory(nameof(AvatarScaleMod));
|
||||
|
||||
public static readonly MelonPreferences_Entry<bool> EntryEnabled =
|
||||
Category.CreateEntry("Enabled", true, description: "Toggle AvatarScaleMod entirely.");
|
||||
|
||||
public static readonly MelonPreferences_Entry<bool> EntryUseScaleGesture =
|
||||
Category.CreateEntry("Scale Gesture", false, description: "Use two fists to scale yourself easily.");
|
||||
|
||||
public override void OnInitializeMelon()
|
||||
{
|
||||
Logger = LoggerInstance;
|
||||
|
||||
ModSettings.InitializeModSettings();
|
||||
ApplyPatches(typeof(HarmonyPatches.PlayerSetupPatches));
|
||||
//ApplyPatches(typeof(HarmonyPatches.PuppetMasterPatches));
|
||||
ApplyPatches(typeof(HarmonyPatches.GesturePlaneTestPatches));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,23 +1,39 @@
|
|||
namespace NAK.AvatarScaleMod;
|
||||
using MelonLoader;
|
||||
|
||||
namespace NAK.AvatarScaleMod;
|
||||
|
||||
// i like this
|
||||
|
||||
// Another thing i stole from Kafe, this organizes stuff so much moreee
|
||||
// Should I move the entries here too?
|
||||
static class ModSettings
|
||||
{
|
||||
public static readonly MelonPreferences_Category Category =
|
||||
MelonPreferences.CreateCategory(nameof(AvatarScaleMod));
|
||||
|
||||
public static readonly MelonPreferences_Entry<bool> EntryEnabled =
|
||||
Category.CreateEntry("Enabled", true, description: "Toggle AvatarScaleMod entirely for Local user. Kinda.");
|
||||
|
||||
public static readonly MelonPreferences_Entry<bool> EntryUseScaleGesture =
|
||||
Category.CreateEntry("Scale Gesture", false, description: "Use two fists to scale yourself easily.");
|
||||
|
||||
static ModSettings()
|
||||
{
|
||||
EntryEnabled.OnEntryValueChanged.Subscribe(OnEntryEnabledChanged);
|
||||
EntryUseScaleGesture.OnEntryValueChanged.Subscribe(OnEntryUseScaleGestureChanged);
|
||||
}
|
||||
|
||||
public static void InitializeModSettings()
|
||||
{
|
||||
AvatarScaleMod.EntryEnabled.OnEntryValueChanged.Subscribe(OnEntryEnabledChanged);
|
||||
AvatarScaleMod.EntryUseScaleGesture.OnEntryValueChanged.Subscribe(OnEntryUseScaleGestureChanged);
|
||||
AvatarScaleManager.GlobalEnabled = EntryEnabled.Value;
|
||||
AvatarScaleGesture.GestureEnabled = EntryUseScaleGesture.Value;
|
||||
}
|
||||
|
||||
static void OnEntryEnabledChanged(bool oldVal, bool newVal)
|
||||
static void OnEntryEnabledChanged(bool oldValue, bool newValue)
|
||||
{
|
||||
if (AvatarScaleManager.LocalAvatar != null)
|
||||
AvatarScaleManager.LocalAvatar.enabled = newVal;
|
||||
AvatarScaleManager.GlobalEnabled = newValue;
|
||||
}
|
||||
|
||||
static void OnEntryUseScaleGestureChanged(bool oldVal, bool newVal)
|
||||
static void OnEntryUseScaleGestureChanged(bool oldValue, bool newValue)
|
||||
{
|
||||
AvatarScaleGesture.GestureEnabled = newVal;
|
||||
AvatarScaleGesture.GestureEnabled = newValue;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue