Skip to content

Commit 9ade974

Browse files
committed
Fix positioning issues if avatar root isn't at the origin
1 parent 9dbd30a commit 9ade974

File tree

7 files changed

+66
-64
lines changed

7 files changed

+66
-64
lines changed

Source/CustomAvatar/Avatar/AvatarIK.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ protected void Start()
151151
protected void OnDisable()
152152
{
153153
_vrik.enabled = false;
154-
_vrik.references.root.SetLocalPositionAndRotation(_defaultRootPose.position, _defaultRootPose.rotation);
154+
_vrik.references.root.SetLocalPose(_defaultRootPose);
155155
_vrik.solver.FixTransforms();
156156

157157
foreach (TwistRelaxerV2 twistRelaxer in _twistRelaxersV2)
@@ -208,13 +208,16 @@ private void OnPostUpdate()
208208

209209
private void UpdateLocomotion()
210210
{
211-
if (!_vrik || !vrikManager) return;
211+
if (_vrik == null || vrikManager == null)
212+
{
213+
return;
214+
}
212215

213216
_vrik.solver.locomotion.weight = _isLocomotionEnabled ? vrikManager.solver_locomotion_weight : 0;
214217

215-
if (_vrik.references.root)
218+
if (!_isLocomotionEnabled && _vrik.references.root != null)
216219
{
217-
_vrik.references.root.transform.localPosition = Vector3.zero;
220+
_vrik.references.root.SetLocalPose(_defaultRootPose);
218221
}
219222
}
220223

Source/CustomAvatar/Avatar/SpawnedAvatar.cs

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1616

1717
extern alias BeatSaberFinalIK;
18-
19-
using System;
2018
using CustomAvatar.Logging;
2119
using CustomAvatar.Tracking;
2220
using UnityEngine;
@@ -40,30 +38,6 @@ public class SpawnedAvatar : MonoBehaviour
4038
/// </summary>
4139
public IAvatarInput input { get; private set; }
4240

43-
/// <summary>
44-
/// The avatar's scale as a ratio of it's exported scale (i.e. it is initially 1 even if the avatar was exported with a different scale).
45-
/// </summary>
46-
public float scale
47-
{
48-
get => transform.localScale.y / _initialLocalScale.y;
49-
set
50-
{
51-
if (value <= 0) throw new InvalidOperationException("Scale must be greater than 0");
52-
if (float.IsInfinity(value)) throw new InvalidOperationException("Scale cannot be infinity");
53-
54-
transform.localScale = _initialLocalScale * value;
55-
}
56-
}
57-
58-
public float scaledEyeHeight
59-
{
60-
get => prefab.eyeHeight * scale;
61-
set
62-
{
63-
scale = value / prefab.eyeHeight;
64-
}
65-
}
66-
6741
public Transform head { get; private set; }
6842
public Transform body { get; private set; }
6943
public Transform leftHand { get; private set; }
@@ -82,9 +56,6 @@ public float scaledEyeHeight
8256
private FirstPersonExclusion[] _firstPersonExclusions;
8357
private Renderer[] _renderers;
8458

85-
private Vector3 _initialLocalPosition;
86-
private Vector3 _initialLocalScale;
87-
8859
public void SetFirstPersonVisibility(FirstPersonVisibility visibility)
8960
{
9061
switch (visibility)
@@ -109,9 +80,6 @@ public void SetFirstPersonVisibility(FirstPersonVisibility visibility)
10980

11081
protected void Awake()
11182
{
112-
_initialLocalPosition = transform.localPosition;
113-
_initialLocalScale = transform.localScale;
114-
11583
_firstPersonExclusions = GetComponentsInChildren<FirstPersonExclusion>();
11684
_renderers = GetComponentsInChildren<Renderer>();
11785

@@ -135,18 +103,9 @@ private void Construct(ILoggerFactory loggerFactory, AvatarPrefab avatarPrefab,
135103
{
136104
prefab = avatarPrefab;
137105
input = avatarInput;
138-
139-
_logger = loggerFactory.CreateLogger<SpawnedAvatar>(prefab.descriptor.name);
140-
}
141-
142-
protected void Start()
143-
{
144106
name = $"SpawnedAvatar({prefab.descriptor.name})";
145107

146-
if (_initialLocalPosition.sqrMagnitude > 0)
147-
{
148-
_logger.LogWarning("Avatar root position is not at origin; resizing by height and floor adjust may not work properly.");
149-
}
108+
_logger = loggerFactory.CreateLogger<SpawnedAvatar>(prefab.descriptor.name);
150109
}
151110

152111
protected void OnDestroy()

Source/CustomAvatar/Configuration/ObservableValue.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1616

1717
using System;
18+
using System.Collections.Generic;
1819

1920
namespace CustomAvatar.Configuration
2021
{
@@ -27,8 +28,11 @@ public T value
2728
get => _value;
2829
set
2930
{
30-
_value = value;
31-
changed?.Invoke(value);
31+
if (!EqualityComparer<T>.Default.Equals(_value, value))
32+
{
33+
_value = value;
34+
changed?.Invoke(value);
35+
}
3236
}
3337
}
3438

Source/CustomAvatar/Player/PlayerAvatarManager.cs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,21 @@ public class PlayerAvatarManager : MonoBehaviour
5454
/// </summary>
5555
public SpawnedAvatar currentlySpawnedAvatar { get; private set; }
5656

57+
/// <summary>
58+
/// The current avatar's scale.
59+
/// </summary>
60+
61+
public float scale
62+
{
63+
get => _scaleConstraint.scaleOffset;
64+
private set => _scaleConstraint.scaleOffset = value;
65+
}
66+
67+
/// <summary>
68+
/// The current avatar's scaled eye height.
69+
/// </summary>
70+
public float scaledEyeHeight => currentlySpawnedAvatar != null ? scale * currentlySpawnedAvatar.prefab.eyeHeight : BeatSaberUtilities.kDefaultPlayerEyeHeight;
71+
5772
internal Settings.AvatarSpecificSettings currentAvatarSettings { get; private set; }
5873

5974
internal CalibrationData.FullBodyCalibration currentManualCalibration { get; private set; }
@@ -384,7 +399,7 @@ internal float GetFloorOffset(float eyeHeight)
384399
return 0;
385400
}
386401

387-
float offset = eyeHeight - currentlySpawnedAvatar.scaledEyeHeight;
402+
float offset = eyeHeight - scaledEyeHeight;
388403

389404
if (_settings.moveFloorWithRoomAdjust)
390405
{
@@ -452,12 +467,18 @@ internal void ResizeCurrentAvatar()
452467
return;
453468
}
454469

455-
float scale = ResizeCurrentAvatar(_settings.playerEyeHeight);
470+
ResizeCurrentAvatar(_settings.playerEyeHeight);
471+
}
472+
473+
internal void ResizeCurrentAvatar(float playerEyeHeight)
474+
{
475+
scale = CalculateAvatarScale(playerEyeHeight);
476+
UpdateAvatarVerticalPosition(playerEyeHeight);
456477
_logger.LogInformation("Resized avatar with scale: " + scale);
457478
avatarScaleChanged?.Invoke(scale);
458479
}
459480

460-
internal float ResizeCurrentAvatar(float playerEyeHeight)
481+
private float CalculateAvatarScale(float playerEyeHeight)
461482
{
462483
if (currentlySpawnedAvatar == null)
463484
{
@@ -508,10 +529,6 @@ internal float ResizeCurrentAvatar(float playerEyeHeight)
508529
scale = 1.0f;
509530
}
510531

511-
currentlySpawnedAvatar.scale = scale;
512-
513-
UpdateAvatarVerticalPosition(playerEyeHeight);
514-
515532
return scale;
516533
}
517534

@@ -567,7 +584,10 @@ private void OnPlayerArmSpanChanged(float armSpan)
567584

568585
private void UpdateAvatarVerticalPosition(float eyeHeight)
569586
{
570-
_parentConstraint.translationOffsets = [new Vector3(0, GetFloorOffset(eyeHeight), 0)];
587+
if (_parentConstraint.sourceCount > 0)
588+
{
589+
_parentConstraint.SetTranslationOffset(0, new Vector3(0, GetFloorOffset(eyeHeight), 0));
590+
}
571591
}
572592
}
573593
}

Source/CustomAvatar/Tracking/TrackingRig.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -464,16 +464,16 @@ private void UpdateOffsets()
464464

465465
_logger.LogTrace("Updating offsets");
466466

467-
UpdateOffset(leftHand.offset, spawnedAvatar.prefab.leftHandOffset, spawnedAvatar.scale);
468-
UpdateOffset(rightHand.offset, spawnedAvatar.prefab.rightHandOffset, spawnedAvatar.scale);
467+
UpdateOffset(leftHand.offset, spawnedAvatar.prefab.leftHandOffset, _playerAvatarManager.scale);
468+
UpdateOffset(rightHand.offset, spawnedAvatar.prefab.rightHandOffset, _playerAvatarManager.scale);
469469

470-
float fullBodyScale = _playerAvatarManager.currentlySpawnedAvatar.scaledEyeHeight / _settings.playerEyeHeight;
471-
float trackerScale = spawnedAvatar.scale / fullBodyScale;
470+
float fullBodyScale = _playerAvatarManager.scaledEyeHeight / _settings.playerEyeHeight;
471+
float trackerScale = _playerAvatarManager.scale / fullBodyScale;
472472

473473
CalibrationData.FullBodyCalibration automaticCalibration = _calibrationData.automaticCalibration;
474474
CalibrationData.FullBodyCalibration manualCalibration = _playerAvatarManager.currentManualCalibration;
475475

476-
UpdateOffset(head.offset, spawnedAvatar.prefab.headOffset, spawnedAvatar.prefab.headCalibrationOffset, spawnedAvatar.scale, manualCalibration.head, automaticCalibration.head);
476+
UpdateOffset(head.offset, spawnedAvatar.prefab.headOffset, spawnedAvatar.prefab.headCalibrationOffset, _playerAvatarManager.scale, manualCalibration.head, automaticCalibration.head);
477477
UpdateOffset(pelvis.offset, spawnedAvatar.prefab.pelvisOffset, spawnedAvatar.prefab.pelvisCalibrationOffset, trackerScale, manualCalibration.waist, automaticCalibration.waist);
478478
UpdateOffset(leftFoot.offset, spawnedAvatar.prefab.leftLegOffset, spawnedAvatar.prefab.leftFootCalibrationOffset, trackerScale, manualCalibration.leftFoot, automaticCalibration.leftFoot);
479479
UpdateOffset(rightFoot.offset, spawnedAvatar.prefab.rightLegOffset, spawnedAvatar.prefab.rightFootCalibrationOffset, trackerScale, manualCalibration.rightFoot, automaticCalibration.rightFoot);
@@ -493,7 +493,7 @@ private void UpdateOffsets()
493493
break;
494494
}
495495

496-
fullBodyTracking.localPosition = new Vector3(0, _settings.playerEyeHeight - _playerAvatarManager.currentlySpawnedAvatar.scaledEyeHeight, 0);
496+
fullBodyTracking.localPosition = new Vector3(0, _settings.playerEyeHeight - _playerAvatarManager.scaledEyeHeight, 0);
497497
fullBodyTracking.localScale = new Vector3(1, fullBodyScale, 1);
498498
}
499499

Source/CustomAvatar/Utilities/LossyScaleConstraint.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ namespace CustomAvatar.Utilities
2525
/// </summary>
2626
internal class LossyScaleConstraint : MonoBehaviour
2727
{
28+
public float scaleOffset
29+
{
30+
get => _scaleOffset;
31+
set => _scaleOffset = value;
32+
}
33+
34+
[SerializeField]
35+
private float _scaleOffset = 1;
36+
2837
[SerializeField]
2938
private Transform _sourceTransform;
3039

@@ -49,7 +58,7 @@ protected void OnEnable()
4958

5059
protected void Update()
5160
{
52-
transform.localScale = sourceTransform.lossyScale;
61+
transform.localScale = sourceTransform.lossyScale * _scaleOffset;
5362
}
5463
}
5564
}
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
using System.Linq;
22
using System.Runtime.CompilerServices;
3+
using UnityEngine;
34

45
namespace CustomAvatar.Utilities
56
{
67
internal static class UnityUtilities
78
{
89
[MethodImpl(MethodImplOptions.AggressiveInlining)]
9-
internal static T FirstNonNullUnityObject<T>(params T[] objects) where T : UnityEngine.Object => objects.FirstOrDefault(o => o != null);
10+
internal static T FirstNonNullUnityObject<T>(params T[] objects) where T : Object => objects.FirstOrDefault(o => o != null);
11+
12+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
13+
internal static void SetLocalPose(this Transform transform, Pose pose)
14+
{
15+
transform.SetLocalPositionAndRotation(pose.position, pose.rotation);
16+
}
1017
}
1118
}

0 commit comments

Comments
 (0)