Skip to content

Commit b1bcf86

Browse files
committed
Refactor player height adjustment
1 parent f09354a commit b1bcf86

File tree

10 files changed

+162
-125
lines changed

10 files changed

+162
-125
lines changed

addons/godot-xr-tools/player/player_body.gd

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ const NEAR_GROUND_DISTANCE := 1.0
4646
@export var enabled : bool = true: set = set_enabled
4747

4848
@export_group("Player setup")
49+
50+
## Automatically calibrate player body on next frame
51+
@export var player_calibrate_height : bool = true
52+
4953
## Radius of the player body collider
5054
@export var player_radius : float = 0.2: set = set_player_radius
5155

@@ -56,7 +60,7 @@ const NEAR_GROUND_DISTANCE := 1.0
5660
@export var player_height_min : float = 0.6
5761

5862
## Maximum player height
59-
@export var player_height_max : float = 2.2
63+
@export var player_height_max : float = 2.5
6064

6165
## Eyes forward offset from center of body in player_radius units
6266
@export_range(0.0, 1.0) var eye_forward_offset : float = 0.5
@@ -200,6 +204,7 @@ func _ready():
200204
_update_enabled()
201205
_update_player_radius()
202206

207+
203208
func set_enabled(new_value) -> void:
204209
enabled = new_value
205210
if is_inside_tree():
@@ -414,6 +419,13 @@ func slew_up(up: Vector3, slew: float) -> void:
414419
# Update the origin
415420
origin_node.global_transform = new_origin
416421

422+
## This method calibrates the players height on the assumption
423+
## the player is in rest position
424+
func calibrate_player_height():
425+
var base_height = camera_node.transform.origin.y + (player_head_height * XRServer.world_scale)
426+
var player_height = XRToolsUserSettings.player_height * XRServer.world_scale
427+
player_height_offset = (player_height - base_height) / XRServer.world_scale
428+
417429
## This method sets or clears a named height override
418430
func override_player_height(key, value: float = -1.0):
419431
# Clear or set the override
@@ -462,10 +474,16 @@ func _estimate_body_forward_dir() -> Vector3:
462474

463475
# This method updates the player body to match the player position
464476
func _update_body_under_camera():
477+
# Initially calibration of player height
478+
if player_calibrate_height:
479+
calibrate_player_height()
480+
player_calibrate_height = false
481+
465482
# Calculate the player height based on the camera position in the origin and the calibration
466483
var player_height: float = clamp(
467-
camera_node.transform.origin.y + player_head_height +
468-
player_height_offset + XRToolsUserSettings.player_height_adjust,
484+
camera_node.transform.origin.y
485+
+ (player_head_height * XRServer.world_scale)
486+
+ (player_height_offset * XRServer.world_scale),
469487
player_height_min * XRServer.world_scale,
470488
player_height_max * XRServer.world_scale)
471489

addons/godot-xr-tools/user_settings/user_settings.gd

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,17 @@ enum WebXRPrimary {
1212
}
1313

1414

15+
@export_group("Input")
16+
1517
## User setting for snap-turn
1618
@export var snap_turning : bool = true
1719

18-
## User setting for player height adjust
19-
@export var player_height_adjust : float = 0.0: set = set_player_height_adjust
20+
@export_group("Player")
21+
22+
## User setting for player height
23+
@export var player_height : float = 1.85: set = set_player_height
24+
25+
@export_group("WebXR")
2026

2127
## User setting for WebXR primary
2228
@export var webxr_primary : WebXRPrimary = WebXRPrimary.AUTO: set = set_webxr_primary
@@ -40,16 +46,17 @@ func _ready():
4046

4147
## Reset to default values
4248
func reset_to_defaults() -> void:
43-
# Reset to defaults
49+
# Reset to defaults.
50+
# Where applicable we obtain our project settings
4451
snap_turning = XRTools.get_default_snap_turning()
45-
player_height_adjust = 0.0
52+
player_height = XRTools.get_player_standard_height()
4653
webxr_primary = WebXRPrimary.AUTO
4754
webxr_auto_primary = 0
4855

4956

50-
## Set the player height adjust property
51-
func set_player_height_adjust(new_value : float) -> void:
52-
player_height_adjust = clamp(new_value, -1.0, 1.0)
57+
## Set the player height property
58+
func set_player_height(new_value : float) -> void:
59+
player_height = clamp(new_value, 1.0, 2.5)
5360

5461

5562
## Set the WebXR primary
@@ -80,7 +87,7 @@ func save() -> void:
8087
"default_snap_turning" : snap_turning
8188
},
8289
"player" : {
83-
"height_adjust" : player_height_adjust
90+
"height" : player_height
8491
},
8592
"webxr" : {
8693
"webxr_primary" : webxr_primary,
@@ -149,8 +156,8 @@ func _load() -> void:
149156
# Parse our player settings
150157
if settings.has("player"):
151158
var player : Dictionary = settings["player"]
152-
if player.has("height_adjust"):
153-
player_height_adjust = player["height_adjust"]
159+
if player.has("height"):
160+
player_height = player["height"]
154161

155162
# Parse our WebXR settings
156163
if settings.has("webxr"):
Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
extends TabContainer
22

3-
@export_node_path("XRCamera3D") var camera
3+
signal player_height_changed(new_height)
44

5-
@export var player_head_height : float = 0.1
5+
@onready var snap_turning_button = $Input/InputVBox/SnapTurning/SnapTurningCB
6+
@onready var player_height_slider = $Player/PlayerVBox/PlayerHeight/PlayerHeightSlider
7+
@onready var webxr_primary_button = $WebXR/WebXRVBox/WebXR/WebXRPrimary
68

79
func _update():
810
# Input
9-
$Input/SnapTurning/SnapTurningCB.button_pressed = XRToolsUserSettings.snap_turning
11+
snap_turning_button.button_pressed = XRToolsUserSettings.snap_turning
1012

1113
# Player
12-
$Player/PlayerHeight/PlayerHeightSlider.value = XRToolsUserSettings.player_height_adjust
14+
player_height_slider.value = XRToolsUserSettings.player_height
1315

1416
# WebXR
15-
$WebXR/WebXR/WebXRPrimary.selected = XRToolsUserSettings.webxr_primary
17+
webxr_primary_button.selected = XRToolsUserSettings.webxr_primary
1618

1719

1820
# Called when the node enters the scene tree for the first time.
@@ -36,29 +38,16 @@ func _on_Reset_pressed():
3638
if XRToolsUserSettings:
3739
XRToolsUserSettings.reset_to_defaults()
3840
_update()
41+
emit_signal("player_height_changed", XRToolsUserSettings.player_height)
3942

4043
# Input settings changed
4144
func _on_SnapTurningCB_pressed():
42-
XRToolsUserSettings.snap_turning = $Input/SnapTurning/SnapTurningCB.button_pressed
45+
XRToolsUserSettings.snap_turning = snap_turning_button.button_pressed
4346

4447
# Player settings changed
4548
func _on_PlayerHeightSlider_drag_ended(_value_changed):
46-
XRToolsUserSettings.player_height_adjust = $Player/PlayerHeight/PlayerHeightSlider.value
47-
48-
49-
func _on_PlayerHeightStandard_pressed():
50-
if camera.is_empty():
51-
return
52-
53-
var camera_node = get_node_or_null(camera)
54-
if !camera_node:
55-
return
56-
57-
var base_height = camera_node.transform.origin.y + player_head_height
58-
var height_adjust = XRTools.get_player_standard_height() - base_height
59-
XRToolsUserSettings.player_height_adjust = height_adjust
60-
$Player/PlayerHeight/PlayerHeightSlider.value = XRToolsUserSettings.player_height_adjust
61-
49+
XRToolsUserSettings.player_height = player_height_slider.value
50+
emit_signal("player_height_changed", XRToolsUserSettings.player_height)
6251

6352
func _on_web_xr_primary_item_selected(index: int) -> void:
6453
XRToolsUserSettings.webxr_primary = index

addons/godot-xr-tools/user_settings/user_settings_ui.tscn

Lines changed: 58 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -10,98 +10,108 @@ size_flags_vertical = 3
1010
theme_override_font_sizes/font_size = 12
1111
script = ExtResource("1")
1212

13-
[node name="Input" type="VBoxContainer" parent="."]
13+
[node name="Input" type="MarginContainer" parent="."]
1414
layout_mode = 2
15+
theme_override_constants/margin_left = 5
16+
theme_override_constants/margin_top = 5
17+
theme_override_constants/margin_right = 5
18+
theme_override_constants/margin_bottom = 5
1519

16-
[node name="SnapTurning" type="HBoxContainer" parent="Input"]
20+
[node name="InputVBox" type="VBoxContainer" parent="Input"]
1721
layout_mode = 2
1822

19-
[node name="Label" type="Label" parent="Input/SnapTurning"]
23+
[node name="SnapTurning" type="HBoxContainer" parent="Input/InputVBox"]
24+
layout_mode = 2
25+
26+
[node name="Label" type="Label" parent="Input/InputVBox/SnapTurning"]
2027
layout_mode = 2
2128
theme_override_font_sizes/font_size = 12
2229
text = "Snap turning:"
2330

24-
[node name="SnapTurningCB" type="CheckBox" parent="Input/SnapTurning"]
31+
[node name="SnapTurningCB" type="CheckBox" parent="Input/InputVBox/SnapTurning"]
2532
layout_mode = 2
2633

27-
[node name="HSeparator" type="HSeparator" parent="Input"]
34+
[node name="HSeparator" type="HSeparator" parent="Input/InputVBox"]
2835
layout_mode = 2
2936

30-
[node name="Buttons" type="HBoxContainer" parent="Input"]
37+
[node name="Buttons" type="HBoxContainer" parent="Input/InputVBox"]
3138
layout_mode = 2
3239
alignment = 1
3340

34-
[node name="Save" type="Button" parent="Input/Buttons"]
41+
[node name="Save" type="Button" parent="Input/InputVBox/Buttons"]
3542
layout_mode = 2
3643
theme_override_font_sizes/font_size = 12
3744
text = "Apply"
3845

39-
[node name="Reset" type="Button" parent="Input/Buttons"]
46+
[node name="Reset" type="Button" parent="Input/InputVBox/Buttons"]
4047
layout_mode = 2
4148
theme_override_font_sizes/font_size = 12
4249
text = "Reset"
4350

44-
[node name="Player" type="VBoxContainer" parent="."]
51+
[node name="Player" type="MarginContainer" parent="."]
4552
visible = false
4653
layout_mode = 2
54+
theme_override_constants/margin_left = 5
55+
theme_override_constants/margin_top = 5
56+
theme_override_constants/margin_right = 5
57+
theme_override_constants/margin_bottom = 5
4758

48-
[node name="PlayerHeight" type="HBoxContainer" parent="Player"]
49-
layout_mode = 2
50-
51-
[node name="Label" type="Label" parent="Player/PlayerHeight"]
52-
layout_mode = 2
53-
theme_override_font_sizes/font_size = 12
54-
text = "Height adjust:"
55-
56-
[node name="PlayerHeightSlider" type="HSlider" parent="Player/PlayerHeight"]
59+
[node name="PlayerVBox" type="VBoxContainer" parent="Player"]
5760
layout_mode = 2
58-
size_flags_horizontal = 3
59-
min_value = -1.0
60-
max_value = 1.0
61-
step = 0.1
6261

63-
[node name="PlayerHeightCalc" type="HBoxContainer" parent="Player"]
62+
[node name="PlayerHeight" type="HBoxContainer" parent="Player/PlayerVBox"]
6463
layout_mode = 2
6564

66-
[node name="Label" type="Label" parent="Player/PlayerHeightCalc"]
65+
[node name="Label" type="Label" parent="Player/PlayerVBox/PlayerHeight"]
6766
layout_mode = 2
6867
theme_override_font_sizes/font_size = 12
68+
text = "Height adjust:"
6969

70-
[node name="PlayerHeightStandard" type="Button" parent="Player/PlayerHeightCalc"]
70+
[node name="PlayerHeightSlider" type="HSlider" parent="Player/PlayerVBox/PlayerHeight"]
7171
layout_mode = 2
72-
theme_override_font_sizes/font_size = 12
73-
text = "Set to standard"
72+
size_flags_horizontal = 3
73+
min_value = 1.0
74+
max_value = 2.5
75+
step = 0.05
76+
value = 1.0
7477

75-
[node name="HSeparator" type="HSeparator" parent="Player"]
78+
[node name="HSeparator" type="HSeparator" parent="Player/PlayerVBox"]
7679
layout_mode = 2
7780

78-
[node name="Buttons" type="HBoxContainer" parent="Player"]
81+
[node name="Buttons" type="HBoxContainer" parent="Player/PlayerVBox"]
7982
layout_mode = 2
8083
alignment = 1
8184

82-
[node name="Save" type="Button" parent="Player/Buttons"]
85+
[node name="Save" type="Button" parent="Player/PlayerVBox/Buttons"]
8386
layout_mode = 2
8487
theme_override_font_sizes/font_size = 12
8588
text = "Apply"
8689

87-
[node name="Reset" type="Button" parent="Player/Buttons"]
90+
[node name="Reset" type="Button" parent="Player/PlayerVBox/Buttons"]
8891
layout_mode = 2
8992
theme_override_font_sizes/font_size = 12
9093
text = "Reset"
9194

92-
[node name="WebXR" type="VBoxContainer" parent="."]
95+
[node name="WebXR" type="MarginContainer" parent="."]
9396
visible = false
9497
layout_mode = 2
98+
theme_override_constants/margin_left = 5
99+
theme_override_constants/margin_top = 5
100+
theme_override_constants/margin_right = 5
101+
theme_override_constants/margin_bottom = 5
102+
103+
[node name="WebXRVBox" type="VBoxContainer" parent="WebXR"]
104+
layout_mode = 2
95105

96-
[node name="WebXR" type="HBoxContainer" parent="WebXR"]
106+
[node name="WebXR" type="HBoxContainer" parent="WebXR/WebXRVBox"]
97107
layout_mode = 2
98108

99-
[node name="Label" type="Label" parent="WebXR/WebXR"]
109+
[node name="Label" type="Label" parent="WebXR/WebXRVBox/WebXR"]
100110
layout_mode = 2
101111
theme_override_font_sizes/font_size = 12
102112
text = "WebXR primary:"
103113

104-
[node name="WebXRPrimary" type="OptionButton" parent="WebXR/WebXR"]
114+
[node name="WebXRPrimary" type="OptionButton" parent="WebXR/WebXRVBox/WebXR"]
105115
layout_mode = 2
106116
theme_override_font_sizes/font_size = 12
107117
item_count = 3
@@ -113,30 +123,29 @@ popup/item_1/id = 1
113123
popup/item_2/text = "Trackpad"
114124
popup/item_2/id = 2
115125

116-
[node name="HSeparator" type="HSeparator" parent="WebXR"]
126+
[node name="HSeparator" type="HSeparator" parent="WebXR/WebXRVBox"]
117127
layout_mode = 2
118128

119-
[node name="Buttons" type="HBoxContainer" parent="WebXR"]
129+
[node name="Buttons" type="HBoxContainer" parent="WebXR/WebXRVBox"]
120130
layout_mode = 2
121131
alignment = 1
122132

123-
[node name="Save" type="Button" parent="WebXR/Buttons"]
133+
[node name="Save" type="Button" parent="WebXR/WebXRVBox/Buttons"]
124134
layout_mode = 2
125135
theme_override_font_sizes/font_size = 12
126136
text = "Apply"
127137

128-
[node name="Reset" type="Button" parent="WebXR/Buttons"]
138+
[node name="Reset" type="Button" parent="WebXR/WebXRVBox/Buttons"]
129139
layout_mode = 2
130140
theme_override_font_sizes/font_size = 12
131141
text = "Reset"
132142

133-
[connection signal="pressed" from="Input/SnapTurning/SnapTurningCB" to="." method="_on_SnapTurningCB_pressed"]
134-
[connection signal="pressed" from="Input/Buttons/Save" to="." method="_on_Save_pressed"]
135-
[connection signal="pressed" from="Input/Buttons/Reset" to="." method="_on_Reset_pressed"]
136-
[connection signal="drag_ended" from="Player/PlayerHeight/PlayerHeightSlider" to="." method="_on_PlayerHeightSlider_drag_ended"]
137-
[connection signal="pressed" from="Player/PlayerHeightCalc/PlayerHeightStandard" to="." method="_on_PlayerHeightStandard_pressed"]
138-
[connection signal="pressed" from="Player/Buttons/Save" to="." method="_on_Save_pressed"]
139-
[connection signal="pressed" from="Player/Buttons/Reset" to="." method="_on_Reset_pressed"]
140-
[connection signal="item_selected" from="WebXR/WebXR/WebXRPrimary" to="." method="_on_web_xr_primary_item_selected"]
141-
[connection signal="pressed" from="WebXR/Buttons/Save" to="." method="_on_Save_pressed"]
142-
[connection signal="pressed" from="WebXR/Buttons/Reset" to="." method="_on_Reset_pressed"]
143+
[connection signal="pressed" from="Input/InputVBox/SnapTurning/SnapTurningCB" to="." method="_on_SnapTurningCB_pressed"]
144+
[connection signal="pressed" from="Input/InputVBox/Buttons/Save" to="." method="_on_Save_pressed"]
145+
[connection signal="pressed" from="Input/InputVBox/Buttons/Reset" to="." method="_on_Reset_pressed"]
146+
[connection signal="drag_ended" from="Player/PlayerVBox/PlayerHeight/PlayerHeightSlider" to="." method="_on_PlayerHeightSlider_drag_ended"]
147+
[connection signal="pressed" from="Player/PlayerVBox/Buttons/Save" to="." method="_on_Save_pressed"]
148+
[connection signal="pressed" from="Player/PlayerVBox/Buttons/Reset" to="." method="_on_Reset_pressed"]
149+
[connection signal="item_selected" from="WebXR/WebXRVBox/WebXR/WebXRPrimary" to="." method="_on_PlayerHeightSlider_drag_ended"]
150+
[connection signal="pressed" from="WebXR/WebXRVBox/Buttons/Save" to="." method="_on_Save_pressed"]
151+
[connection signal="pressed" from="WebXR/WebXRVBox/Buttons/Reset" to="." method="_on_Reset_pressed"]

addons/godot-xr-tools/xr_tools.gd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
class_name XRTools
22
extends Node
33

4+
## Below are helper functions to obtain various project settings that drive
5+
## the default behavior of XR Tools. The project settings themselves are
6+
## registered in plugin.gd.
7+
## Some of these settings can be overridden by the user through user settings.
48

59
static func get_grip_threshold() -> float:
610
# can return null which is not a float, so don't type this!

scenes/main_menu/main_menu_level.gd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,7 @@ func _on_Demos_child_entered_tree(_node):
3636

3737
func _on_Demos_child_exiting_tree(_node):
3838
_update_demo_positions()
39+
40+
41+
func _on_settings_ui_player_height_changed(new_height):
42+
$XROrigin3D/PlayerBody.calibrate_player_height()

0 commit comments

Comments
 (0)