Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions Basis/Packages/com.basis.framework/BasisUI/BasisMenuMover.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ public struct RootModeOffset
private bool _hasLocalMoveEvent;

private const float MIN_Z_SCALE = 0.01f;
// MIN_TMP_RENDER_SCALE is empirical: TMP rendered block glyphs on the main menu below roughly 0.05328 world scale during OSC tiny-avatar testing.
private const float MIN_TMP_RENDER_SCALE = 0.055f;

// --- PlaySpaceStable state (from v1) ---
private bool _stableHasAnchor;
Expand Down Expand Up @@ -254,8 +256,7 @@ private void SetRootOffset(RootModeOffset offset)
offsetScale.z = Mathf.Max(MIN_Z_SCALE, offsetScale.z);
GroupOffset.localScale = offsetScale;

// Root is avatar-compensated
transform.localScale = Vector3.one * playerHeight;
transform.localScale = Vector3.one * GetRenderSafeMenuScale(playerHeight);
}

private void SetEyeOffset(float scaleFactor)
Expand All @@ -269,7 +270,7 @@ private void SetEyeOffset(float scaleFactor)
offsetScale.z = Mathf.Max(MIN_Z_SCALE, offsetScale.z);
GroupOffset.localScale = offsetScale;

transform.localScale = Vector3.one * playerHeight;
transform.localScale = Vector3.one * GetRenderSafeMenuScale(playerHeight);
}

/// <summary>
Expand All @@ -290,8 +291,18 @@ private void ApplyScaleOnly()
offsetScale.z = Mathf.Max(MIN_Z_SCALE, offsetScale.z);
GroupOffset.localScale = offsetScale;

// 2) Root scale (avatar-to-default compensation)
transform.localScale = Vector3.one * BasisHeightDriver.AvatarToDefaultRatioScaledWithAvatarScale;
transform.localScale = Vector3.one * GetRenderSafeMenuScale(BasisHeightDriver.AvatarToDefaultRatioScaledWithAvatarScale);
}

private static float GetRenderSafeMenuScale(float avatarRelativeScale)
{
// TextMeshPro renders block glyphs at extremely small world scales; keep menu rendering stable without clamping avatar scale.
if (float.IsNaN(avatarRelativeScale) || float.IsInfinity(avatarRelativeScale) || avatarRelativeScale <= 0f)
{
return MIN_TMP_RENDER_SCALE;
}

return Mathf.Max(avatarRelativeScale, MIN_TMP_RENDER_SCALE);
}

private void UpdateUILocation()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ public static class BasisSettingsDefaults
/// </summary>
public static BasisSettingsBinding<bool> DisableAnimationsInFBT = new("disableanimationsinfbt", new BasisPlatformDefault<bool>(false));

/// <summary>
/// When enabled, avatar scale affects locomotion blend velocity so small avatars
/// animate faster and large avatars animate slower without changing movement speed.
/// </summary>
public static BasisSettingsBinding<bool> ScaleAffectsLocomotionSpeed = new("scaleaffectslocomotionspeed", new BasisPlatformDefault<bool>(false));

/// <summary>
/// Master switch for full-body tracking. When disabled, hip/chest/foot/knee
/// trackers are ignored and the avatar falls back to head + hands + procedural
Expand Down Expand Up @@ -1252,6 +1258,7 @@ public static void LoadAll()
EnableEyeTracking.LoadBindingValue();
FootIKEnabled.LoadBindingValue();
DisableAnimationsInFBT.LoadBindingValue();
ScaleAffectsLocomotionSpeed.LoadBindingValue();
LocalHeadBlendShapes.LoadBindingValue();

// Rendering / Graphics
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@
{ "key": "menu.individualPlayer.avatar", "value": "الأفاتار" },
{ "key": "menu.individualPlayer.avatar.description", "value": "مفاتيح الإظهار والتفاعل." },
{ "key": "menu.individualPlayer.avatarLoadError", "value": "خطأ في تحميل الأفاتار" },
{ "key": "menu.individualPlayer.matchEyeHeight", "value": "مطابقة ارتفاع العين" },
{ "key": "menu.individualPlayer.matchEyeHeight.description", "value": "غيّر مقياس أفاتارك ليطابق مقياس جسم هذا اللاعب الحالي ({0:0.###} م كارتفاع عين مستهدف)." },
{ "key": "menu.individualPlayer.matchEyeHeight.unavailable", "value": "ارتفاع عين أفاتار هذا اللاعب الحالي غير متاح بعد." },
{ "key": "menu.individualPlayer.hideAvatar", "value": "إخفاء الأفاتار" },
{ "key": "menu.individualPlayer.showAvatar", "value": "إظهار الأفاتار" },
{ "key": "menu.individualPlayer.toggleAvatar.description", "value": "تفعيل/تعطيل عرض أفاتار هذا اللاعب على جهازك." },
Expand Down Expand Up @@ -632,6 +635,8 @@
{ "key": "settings.bodyTracking.eyeTracking.description", "value": "تشغيل عظام عيون أفاتارك من بيانات تتبع العين. النظر الطبيعي للعين يستمر عند التعطيل." },
{ "key": "settings.bodyTracking.footIk.description", "value": "يفعّل وضع القدم الإجرائي عند الوقوف ساكناً بدون متتبعات قدم." },
{ "key": "settings.bodyTracking.disableAnimFbt.description", "value": "يكبح حركات القفز والهبوط وانخفاض الورك عند الهبوط أثناء معايرة متتبعات الجسم الكامل." },
{ "key": "settings.bodyTracking.scaleAffectsLocomotion", "value": "يؤثر المقياس في سرعة التنقل" },
{ "key": "settings.bodyTracking.scaleAffectsLocomotion.description", "value": "يضبط سرعة رسوم التنقل المتحركة وفقًا لمقياس الأفاتار دون تغيير سرعة الحركة الفعلية." },

{ "key": "settings.bodyTracking.collisionsEnabled.description", "value": "يفعّل تصادم الكبسولات الافتراضية بين المرفقين والصدر لمنع اختراق الذراع للجسم." },
{ "key": "settings.bodyTracking.protectElbow.title", "value": "حماية المرفق" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@
{ "key": "menu.individualPlayer.avatar", "value": "অবতার" },
{ "key": "menu.individualPlayer.avatar.description", "value": "দৃশ্যমানতা এবং ইন্টারঅ্যাকশন টগল।" },
{ "key": "menu.individualPlayer.avatarLoadError", "value": "অবতার লোড ত্রুটি" },
{ "key": "menu.individualPlayer.matchEyeHeight", "value": "চোখের উচ্চতা মেলান" },
{ "key": "menu.individualPlayer.matchEyeHeight.description", "value": "এই খেলোয়াড়ের বর্তমান শরীরের স্কেলের সাথে আপনার অবতার স্কেল করুন ({0:0.###} মি লক্ষ্য চোখের উচ্চতা)।" },
{ "key": "menu.individualPlayer.matchEyeHeight.unavailable", "value": "এই খেলোয়াড়ের বর্তমান অবতার চোখের উচ্চতা এখনো উপলভ্য নয়।" },
{ "key": "menu.individualPlayer.hideAvatar", "value": "অবতার লুকান" },
{ "key": "menu.individualPlayer.showAvatar", "value": "অবতার দেখান" },
{ "key": "menu.individualPlayer.toggleAvatar.description", "value": "আপনার ক্লায়েন্টে এই খেলোয়াড়ের অবতারের রেন্ডারিং টগল করে।" },
Expand Down Expand Up @@ -632,6 +635,8 @@
{ "key": "settings.bodyTracking.eyeTracking.description", "value": "চোখ ট্র্যাকিং ডেটা থেকে আপনার অবতারের চোখের হাড় চালান। অক্ষম থাকলে স্বাভাবিক চোখের লুক চলতে থাকে।" },
{ "key": "settings.bodyTracking.footIk.description", "value": "পা ট্র্যাকার ছাড়া স্থির দাঁড়িয়ে থাকার সময় পদ্ধতিগত পা স্থাপনা সক্ষম করে।" },
{ "key": "settings.bodyTracking.disableAnimFbt.description", "value": "সম্পূর্ণ-শরীর ট্র্যাকার ক্যালিব্রেট থাকাকালীন জাম্প এবং ল্যান্ডিং অ্যানিমেশন এবং ল্যান্ডিং হিপ ডিপ দমন করে।" },
{ "key": "settings.bodyTracking.scaleAffectsLocomotion", "value": "স্কেল লোকোমোশনের গতিকে প্রভাবিত করে" },
{ "key": "settings.bodyTracking.scaleAffectsLocomotion.description", "value": "শারীরিক চলাচলের গতি না বদলে, অবতারের স্কেল অনুযায়ী লোকোমোশন অ্যানিমেশনের গতি সমন্বয় করে।" },

{ "key": "settings.bodyTracking.collisionsEnabled.description", "value": "শরীরের ভিতর দিয়ে বাহু ক্লিপিং প্রতিরোধ করতে কনুই এবং বুকের মধ্যে ভার্চুয়াল ক্যাপসুল সংঘর্ষ সক্ষম করে।" },
{ "key": "settings.bodyTracking.protectElbow.title", "value": "কনুই রক্ষা করুন" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@
{ "key": "menu.individualPlayer.avatar", "value": "Avatar" },
{ "key": "menu.individualPlayer.avatar.description", "value": "Sichtbarkeits- und Interaktions-Schalter." },
{ "key": "menu.individualPlayer.avatarLoadError", "value": "Avatar-Ladefehler" },
{ "key": "menu.individualPlayer.matchEyeHeight", "value": "Augenhöhe anpassen" },
{ "key": "menu.individualPlayer.matchEyeHeight.description", "value": "Skaliert deinen Avatar auf die aktuelle Körpergröße dieses Spielers ({0:0.###} m Ziel-Augenhöhe)." },
{ "key": "menu.individualPlayer.matchEyeHeight.unavailable", "value": "Die aktuelle Avatar-Augenhöhe dieses Spielers ist noch nicht verfügbar." },
{ "key": "menu.individualPlayer.hideAvatar", "value": "Avatar ausblenden" },
{ "key": "menu.individualPlayer.showAvatar", "value": "Avatar anzeigen" },
{ "key": "menu.individualPlayer.toggleAvatar.description", "value": "Schaltet das Rendern des Avatars dieses Spielers auf deinem Client um." },
Expand Down Expand Up @@ -632,6 +635,8 @@
{ "key": "settings.bodyTracking.eyeTracking.description", "value": "Steuert die Augenknochen deines Avatars über Eye-Tracking-Daten. Der natürliche Augenblick läuft weiter, wenn deaktiviert." },
{ "key": "settings.bodyTracking.footIk.description", "value": "Aktiviert prozedurales Fußplatzieren beim ruhigen Stehen ohne Fuß-Tracker." },
{ "key": "settings.bodyTracking.disableAnimFbt.description", "value": "Unterdrückt Sprung- und Lande-Animationen sowie das Hüftabsenken bei der Landung, solange Full-Body-Tracker kalibriert sind." },
{ "key": "settings.bodyTracking.scaleAffectsLocomotion", "value": "Skalierung beeinflusst Fortbewegungsgeschwindigkeit" },
{ "key": "settings.bodyTracking.scaleAffectsLocomotion.description", "value": "Passt die Geschwindigkeit der Geh-/Laufanimation an die Avatar-Skalierung an, ohne die tatsächliche Bewegungsgeschwindigkeit zu verändern." },

{ "key": "settings.bodyTracking.collisionsEnabled.description", "value": "Aktiviert die virtuelle Kapsel-Kollision zwischen Ellenbogen und Brust, um zu verhindern, dass Arme durch den Körper schneiden." },
{ "key": "settings.bodyTracking.protectElbow.title", "value": "Ellenbogen schützen" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,18 @@
"key": "menu.individualPlayer.avatarLoadError",
"value": "Avatar Load Error"
},
{
"key": "menu.individualPlayer.matchEyeHeight",
"value": "Match Eye Height"
},
{
"key": "menu.individualPlayer.matchEyeHeight.description",
"value": "Scale your avatar to match this player's current body scale ({0:0.###} m target eye height)."
},
{
"key": "menu.individualPlayer.matchEyeHeight.unavailable",
"value": "This player's current avatar eye height is not available yet."
},
{
"key": "menu.individualPlayer.hideAvatar",
"value": "Hide Avatar"
Expand Down Expand Up @@ -2722,6 +2734,14 @@
"key": "settings.bodyTracking.eyeTracking.description",
"value": "Drive your avatar's eye bones from eye tracking data. The natural eye look keeps running when disabled."
},
{
"key": "settings.bodyTracking.scaleAffectsLocomotion",
"value": "Scale Affects Locomotion Speed"
},
{
"key": "settings.bodyTracking.scaleAffectsLocomotion.description",
"value": "Adjusts locomotion animation velocity by avatar scale without changing physical movement speed."
},
{
"key": "settings.bodyTracking.footIk.description",
"value": "Enables procedural foot placement when standing still without foot trackers."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@
{ "key": "menu.individualPlayer.avatar", "value": "Avatar" },
{ "key": "menu.individualPlayer.avatar.description", "value": "Visibilidad y opciones de interacción." },
{ "key": "menu.individualPlayer.avatarLoadError", "value": "Error al cargar el avatar" },
{ "key": "menu.individualPlayer.matchEyeHeight", "value": "Igualar altura de ojos" },
{ "key": "menu.individualPlayer.matchEyeHeight.description", "value": "Escala tu avatar para igualar la escala corporal actual de este jugador ({0:0.###} m de altura de ojos objetivo)." },
{ "key": "menu.individualPlayer.matchEyeHeight.unavailable", "value": "La altura de ojos actual del avatar de este jugador aún no está disponible." },
{ "key": "menu.individualPlayer.hideAvatar", "value": "Ocultar avatar" },
{ "key": "menu.individualPlayer.showAvatar", "value": "Mostrar avatar" },
{ "key": "menu.individualPlayer.toggleAvatar.description", "value": "Activa o desactiva el renderizado del avatar de este jugador en tu cliente." },
Expand Down Expand Up @@ -632,6 +635,8 @@
{ "key": "settings.bodyTracking.eyeTracking.description", "value": "Controla los huesos de los ojos de tu avatar a partir de datos de rastreo ocular. La mirada natural sigue funcionando cuando está desactivado." },
{ "key": "settings.bodyTracking.footIk.description", "value": "Activa la colocación procedural de los pies al estar quieto sin trackers de pies." },
{ "key": "settings.bodyTracking.disableAnimFbt.description", "value": "Suprime las animaciones de salto y aterrizaje y la caída de cadera al aterrizar mientras los trackers de cuerpo completo estén calibrados." },
{ "key": "settings.bodyTracking.scaleAffectsLocomotion", "value": "La escala afecta la velocidad de locomoción" },
{ "key": "settings.bodyTracking.scaleAffectsLocomotion.description", "value": "Ajusta la velocidad de la animación de locomoción según la escala del avatar sin cambiar la velocidad de movimiento físico." },

{ "key": "settings.bodyTracking.collisionsEnabled.description", "value": "Activa la colisión de cápsulas virtuales entre los codos y el pecho para evitar que los brazos atraviesen el cuerpo." },
{ "key": "settings.bodyTracking.protectElbow.title", "value": "Proteger codo" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@
{ "key": "menu.individualPlayer.avatar", "value": "Avatar" },
{ "key": "menu.individualPlayer.avatar.description", "value": "Visibilidad y opciones de interacción." },
{ "key": "menu.individualPlayer.avatarLoadError", "value": "Error al cargar el avatar" },
{ "key": "menu.individualPlayer.matchEyeHeight", "value": "Igualar altura de ojos" },
{ "key": "menu.individualPlayer.matchEyeHeight.description", "value": "Escala tu avatar para igualar la escala corporal actual de este jugador ({0:0.###} m de altura de ojos objetivo)." },
{ "key": "menu.individualPlayer.matchEyeHeight.unavailable", "value": "La altura de ojos actual del avatar de este jugador aún no está disponible." },
{ "key": "menu.individualPlayer.hideAvatar", "value": "Ocultar avatar" },
{ "key": "menu.individualPlayer.showAvatar", "value": "Mostrar avatar" },
{ "key": "menu.individualPlayer.toggleAvatar.description", "value": "Activa o desactiva el renderizado del avatar de este jugador en tu cliente." },
Expand Down Expand Up @@ -632,6 +635,8 @@
{ "key": "settings.bodyTracking.eyeTracking.description", "value": "Acciona los huesos de los ojos de tu avatar a partir de los datos de seguimiento ocular. La mirada natural sigue funcionando cuando está desactivado." },
{ "key": "settings.bodyTracking.footIk.description", "value": "Activa la colocación procedural de los pies cuando estás quieto sin trackers de pies." },
{ "key": "settings.bodyTracking.disableAnimFbt.description", "value": "Suprime las animaciones de salto y aterrizaje y la flexión de cadera al aterrizar mientras los trackers de cuerpo completo estén calibrados." },
{ "key": "settings.bodyTracking.scaleAffectsLocomotion", "value": "La escala afecta la velocidad de locomoción" },
{ "key": "settings.bodyTracking.scaleAffectsLocomotion.description", "value": "Ajusta la velocidad de la animación de locomoción según la escala del avatar sin cambiar la velocidad física de movimiento." },

{ "key": "settings.bodyTracking.collisionsEnabled.description", "value": "Activa la colisión por cápsula virtual entre los codos y el pecho para evitar que los brazos atraviesen el cuerpo." },
{ "key": "settings.bodyTracking.protectElbow.title", "value": "Proteger codo" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@
{ "key": "menu.individualPlayer.avatar", "value": "Avatar" },
{ "key": "menu.individualPlayer.avatar.description", "value": "Options de visibilité et d'interaction." },
{ "key": "menu.individualPlayer.avatarLoadError", "value": "Erreur de chargement d'avatar" },
{ "key": "menu.individualPlayer.matchEyeHeight", "value": "Adapter la hauteur des yeux" },
{ "key": "menu.individualPlayer.matchEyeHeight.description", "value": "Redimensionne votre avatar pour correspondre à l'échelle corporelle actuelle de ce joueur ({0:0.###} m de hauteur des yeux cible)." },
{ "key": "menu.individualPlayer.matchEyeHeight.unavailable", "value": "La hauteur actuelle des yeux de l'avatar de ce joueur n'est pas encore disponible." },
{ "key": "menu.individualPlayer.hideAvatar", "value": "Masquer l'avatar" },
{ "key": "menu.individualPlayer.showAvatar", "value": "Afficher l'avatar" },
{ "key": "menu.individualPlayer.toggleAvatar.description", "value": "Bascule le rendu de l'avatar de ce joueur sur votre client." },
Expand Down Expand Up @@ -632,6 +635,8 @@
{ "key": "settings.bodyTracking.eyeTracking.description", "value": "Pilote les os des yeux de votre avatar à partir des données de suivi oculaire. Le regard naturel des yeux continue de fonctionner lorsqu'il est désactivé." },
{ "key": "settings.bodyTracking.footIk.description", "value": "Active le placement procédural des pieds en position immobile sans trackers de pieds." },
{ "key": "settings.bodyTracking.disableAnimFbt.description", "value": "Supprime les animations de saut et d'atterrissage ainsi que la flexion des hanches à l'atterrissage tant que les trackers corps complet sont calibrés." },
{ "key": "settings.bodyTracking.scaleAffectsLocomotion", "value": "L'échelle affecte la vitesse de locomotion" },
{ "key": "settings.bodyTracking.scaleAffectsLocomotion.description", "value": "Ajuste la vitesse de l'animation de locomotion selon l'échelle de l'avatar sans modifier la vitesse de déplacement physique." },

{ "key": "settings.bodyTracking.collisionsEnabled.description", "value": "Active la collision par capsule virtuelle entre les coudes et le torse pour empêcher les bras de traverser le corps." },
{ "key": "settings.bodyTracking.protectElbow.title", "value": "Protéger le coude" },
Expand Down
Loading
Loading