Hips following option

`Moving` parameter
This commit is contained in:
SDraw 2022-11-04 02:13:40 +03:00
parent 8ef25664df
commit a3b4f461d1
No known key found for this signature in database
GPG key ID: BB95B4DAB2BB8BB5
7 changed files with 84 additions and 6 deletions

View file

@ -45,6 +45,7 @@ namespace ml_amt
m_localTweaker.SetIKOverrideFly(Settings.IKOverrideFly);
m_localTweaker.SetIKOverrideJump(Settings.IKOverrideJump);
m_localTweaker.SetDetectEmotes(Settings.DetectEmotes);
m_localTweaker.SetFollowHips(Settings.FollowHips);
}
public override void OnDeinitializeMelon()

View file

@ -18,7 +18,8 @@ namespace ml_amt
enum ParameterType
{
Upright,
GroundedRaw
GroundedRaw,
Moving
}
enum ParameterSyncType
@ -49,6 +50,7 @@ namespace ml_amt
float m_ikWeight = 1f; // Original weight
float m_locomotionWeight = 1f; // Original weight
float m_avatarScale = 1f; // Instantiated scale
Transform m_avatarHips = null;
bool m_avatarReady = false;
bool m_compatibleAvatar = false;
@ -56,6 +58,7 @@ namespace ml_amt
PoseState m_poseState = PoseState.Standing;
bool m_grounded = false;
bool m_groundedRaw = false;
bool m_moving = false;
bool m_ikOverrideCrouch = true;
float m_crouchLimit = 0.65f;
@ -76,6 +79,9 @@ namespace ml_amt
bool m_detectEmotes = true;
bool m_emoteActive = false;
bool m_followHips = true;
Vector3 m_hipsToPlayer = Vector3.zero;
readonly List<AdditionalParameterInfo> m_parameters = null;
public MotionTweaker()
@ -94,6 +100,7 @@ namespace ml_amt
Settings.IKOverrideFlyChange += this.SetIKOverrideFly;
Settings.IKOverrideJumpChange += this.SetIKOverrideJump;
Settings.DetectEmotesChange += this.SetDetectEmotes;
Settings.FollowHipsChange += this.SetFollowHips;
}
void OnDestroy()
@ -107,6 +114,7 @@ namespace ml_amt
Settings.IKOverrideFlyChange -= this.SetIKOverrideFly;
Settings.IKOverrideJumpChange -= this.SetIKOverrideJump;
Settings.DetectEmotesChange -= this.SetDetectEmotes;
Settings.FollowHipsChange -= this.SetFollowHips;
}
void Update()
@ -115,6 +123,7 @@ namespace ml_amt
{
m_grounded = (bool)ms_grounded.GetValue(MovementSystem.Instance);
m_groundedRaw = (bool)ms_groundedRaw.GetValue(MovementSystem.Instance);
m_moving = !Mathf.Approximately(MovementSystem.Instance.movementVector.magnitude, 0f);
// Update upright
Matrix4x4 l_hmdMatrix = PlayerSetup.Instance.transform.GetMatrix().inverse * (PlayerSetup.Instance._inVr ? PlayerSetup.Instance.vrHeadTracker.transform.GetMatrix() : PlayerSetup.Instance.desktopCameraRig.transform.GetMatrix());
@ -124,6 +133,12 @@ namespace ml_amt
m_upright = Mathf.Clamp(((l_avatarViewHeight > 0f) ? (l_currentHeight / l_avatarViewHeight) : 0f), 0f, 1f);
PoseState l_poseState = (m_upright <= m_proneLimit) ? PoseState.Proning : ((m_upright <= m_crouchLimit) ? PoseState.Crouching : PoseState.Standing);
if(m_followHips && (m_avatarHips != null))
{
Vector4 l_hipsToPlayer = (PlayerSetup.Instance.transform.GetMatrix().inverse * m_avatarHips.GetMatrix()) * ms_pointVector;
m_hipsToPlayer.Set(l_hipsToPlayer.x, 0f, l_hipsToPlayer.z);
}
if(PlayerSetup.Instance._inVr && (m_vrIk != null) && m_vrIk.enabled)
{
if(m_poseState != l_poseState)
@ -196,6 +211,20 @@ namespace ml_amt
}
}
break;
case ParameterType.Moving:
{
switch(l_param.m_sync)
{
case ParameterSyncType.Local:
PlayerSetup.Instance._animator.SetBool(l_param.m_hash, m_moving);
break;
case ParameterSyncType.Synced:
PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool(l_param.m_name, m_moving);
break;
}
}
break;
}
}
}
@ -217,6 +246,9 @@ namespace ml_amt
m_locomotionOffset = Vector3.zero;
m_avatarScale = 1f;
m_emoteActive = false;
m_moving = false;
m_hipsToPlayer = Vector3.zero;
m_avatarHips = null;
m_parameters.Clear();
}
@ -224,6 +256,7 @@ namespace ml_amt
{
m_vrIk = PlayerSetup.Instance._avatar.GetComponent<VRIK>();
m_locomotionLayer = PlayerSetup.Instance._animator.GetLayerIndex("Locomotion/Emotes");
m_avatarHips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips);
// Parse animator parameters
AnimatorControllerParameter[] l_params = PlayerSetup.Instance._animator.parameters;
@ -280,6 +313,8 @@ namespace ml_amt
void OnIKPreUpdate()
{
bool l_overrided = false;
m_ikWeight = m_vrIk.solver.IKPositionWeight;
m_locomotionWeight = m_vrIk.solver.locomotion.weight;
@ -290,14 +325,26 @@ namespace ml_amt
if(PlayerSetup.Instance._inVr)
{
if((m_ikOverrideCrouch && (m_poseState != PoseState.Standing)) || (m_ikOverrideProne && (m_poseState == PoseState.Proning)))
{
m_vrIk.solver.locomotion.weight = 0f;
l_overrided = true;
}
if(m_ikOverrideFly && MovementSystem.Instance.flying)
{
m_vrIk.solver.locomotion.weight = 0f;
l_overrided = true;
}
}
// But not this
if(m_ikOverrideJump && !m_grounded && !MovementSystem.Instance.flying)
{
m_vrIk.solver.locomotion.weight = 0f;
l_overrided = true;
}
if(l_overrided && m_followHips && !m_moving)
PlayerSetup.Instance._avatar.transform.localPosition = m_hipsToPlayer;
}
void OnIKPostUpdate()
@ -356,5 +403,9 @@ namespace ml_amt
{
m_detectEmotes = p_state;
}
public void SetFollowHips(bool p_state)
{
m_followHips = p_state;
}
}
}

View file

@ -1,10 +1,10 @@
using System.Reflection;
[assembly: AssemblyTitle("AvatarMotionTweaker")]
[assembly: AssemblyVersion("1.1.7")]
[assembly: AssemblyFileVersion("1.1.7")]
[assembly: AssemblyVersion("1.1.8")]
[assembly: AssemblyFileVersion("1.1.8")]
[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.1.7", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.1.8", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)]

View file

@ -18,6 +18,7 @@ Available mod's settings in `Settings - Implementation - Avatar Motion Tweaker`:
* Note: Can be overrided by avatar. For this avatar has to have child gameobject with name `ProneLimit`, its Y-axis location will be used as limit, should be in range [0.0, 1.0].
* **IK override while flying:** disables legs locomotion/autostep in fly mode; default value - `true`.
* **IK override while jumping:** disables legs locomotion/autostep in jump; default value - `true`.
* **Follow hips on IK override:** adjust avatar position to overcome animation snapping on IK override; default value - `true`.
* **Pose transitions:** allows regular avatars animator to transit in crouch/prone states; default value - `true`.
* Note: Avatar is considered as regular if its AAS animator doesn't have `Upright` parameter.
* **Adjusted pose movement speed:** scales movement speed upon crouching/proning; default value - `true`.
@ -31,6 +32,8 @@ Available additional parameters for AAS animator:
* Note: Can't be used for transitions between poses in desktop mode. In desktop mode its value is driven by avatar animations. Use `CVR Parameter Stream` for detecting desktop/VR modes and change AAS animator transitions accordingly.
* **`GroundedRaw`:** defines instant grounding state of player instead of delayed default parameter `Grounded`.
* Note: Can be set as local-only (not synced) if starts with `#` character.
* **`Moving`:** defines movement state of player
* Note: Can be set as local-only (not synced) if starts with `#` character.
Additional avatars tweaks:
* If avatar has child object with name `LocomotionOffset` its local position will be used for offsetting VRIK locomotion mass center.

View file

@ -17,7 +17,8 @@ namespace ml_amt
AdjustedMovement,
IKOverrideFly,
IKOverrideJump,
DetectEmotes
DetectEmotes,
FollowHips
};
static bool ms_ikOverrideCrouch = true;
@ -29,6 +30,7 @@ namespace ml_amt
static bool ms_ikOverrideFly = true;
static bool ms_ikOverrideJump = true;
static bool ms_detectEmotes = true;
static bool ms_followHips = true;
static MelonLoader.MelonPreferences_Category ms_category = null;
static List<MelonLoader.MelonPreferences_Entry> ms_entries = null;
@ -42,6 +44,7 @@ namespace ml_amt
static public event Action<bool> IKOverrideFlyChange;
static public event Action<bool> IKOverrideJumpChange;
static public event Action<bool> DetectEmotesChange;
static public event Action<bool> FollowHipsChange;
public static void Init()
{
@ -57,6 +60,7 @@ namespace ml_amt
ms_entries.Add(ms_category.CreateEntry(ModSetting.IKOverrideFly.ToString(), true));
ms_entries.Add(ms_category.CreateEntry(ModSetting.IKOverrideJump.ToString(), true));
ms_entries.Add(ms_category.CreateEntry(ModSetting.DetectEmotes.ToString(), true));
ms_entries.Add(ms_category.CreateEntry(ModSetting.FollowHips.ToString(), true));
Load();
@ -96,6 +100,7 @@ namespace ml_amt
ms_ikOverrideFly = (bool)ms_entries[(int)ModSetting.IKOverrideFly].BoxedValue;
ms_ikOverrideJump = (bool)ms_entries[(int)ModSetting.IKOverrideJump].BoxedValue;
ms_detectEmotes = (bool)ms_entries[(int)ModSetting.DetectEmotes].BoxedValue;
ms_followHips = (bool)ms_entries[(int)ModSetting.FollowHips].BoxedValue;
}
static void OnSliderUpdate(string p_name, string p_value)
@ -177,6 +182,13 @@ namespace ml_amt
DetectEmotesChange?.Invoke(ms_detectEmotes);
}
break;
case ModSetting.FollowHips:
{
ms_followHips = bool.Parse(p_value);
FollowHipsChange?.Invoke(ms_followHips);
}
break;
}
ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value);
@ -219,5 +231,9 @@ namespace ml_amt
{
get => ms_detectEmotes;
}
public static bool FollowHips
{
get => ms_followHips;
}
}
}

View file

@ -221,6 +221,13 @@ function inp_toggle_mod_amt(_obj, _callbackName) {
<div id="IKOverrideJump" class ="inp_toggle no-scroll" data-current="true"></div>
</div>
</div>
<div class ="row-wrapper">
<div class ="option-caption">Follow hips on IK override: </div>
<div class ="option-input">
<div id="FollowHips" class ="inp_toggle no-scroll" data-current="true"></div>
</div>
</div>
<div class ="row-wrapper">
<div class ="option-caption">Pose transitions: </div>