Skip to content

Commit

Permalink
Refactor player height adjustment
Browse files Browse the repository at this point in the history
  • Loading branch information
BastiaanOlij committed Jul 2, 2023
1 parent f09354a commit b1bcf86
Show file tree
Hide file tree
Showing 10 changed files with 162 additions and 125 deletions.
24 changes: 21 additions & 3 deletions addons/godot-xr-tools/player/player_body.gd
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ const NEAR_GROUND_DISTANCE := 1.0
@export var enabled : bool = true: set = set_enabled

@export_group("Player setup")

## Automatically calibrate player body on next frame
@export var player_calibrate_height : bool = true

## Radius of the player body collider
@export var player_radius : float = 0.2: set = set_player_radius

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

## Maximum player height
@export var player_height_max : float = 2.2
@export var player_height_max : float = 2.5

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


func set_enabled(new_value) -> void:
enabled = new_value
if is_inside_tree():
Expand Down Expand Up @@ -414,6 +419,13 @@ func slew_up(up: Vector3, slew: float) -> void:
# Update the origin
origin_node.global_transform = new_origin

## This method calibrates the players height on the assumption
## the player is in rest position
func calibrate_player_height():
var base_height = camera_node.transform.origin.y + (player_head_height * XRServer.world_scale)
var player_height = XRToolsUserSettings.player_height * XRServer.world_scale
player_height_offset = (player_height - base_height) / XRServer.world_scale

## This method sets or clears a named height override
func override_player_height(key, value: float = -1.0):
# Clear or set the override
Expand Down Expand Up @@ -462,10 +474,16 @@ func _estimate_body_forward_dir() -> Vector3:

# This method updates the player body to match the player position
func _update_body_under_camera():
# Initially calibration of player height
if player_calibrate_height:
calibrate_player_height()
player_calibrate_height = false

# Calculate the player height based on the camera position in the origin and the calibration
var player_height: float = clamp(
camera_node.transform.origin.y + player_head_height +
player_height_offset + XRToolsUserSettings.player_height_adjust,
camera_node.transform.origin.y
+ (player_head_height * XRServer.world_scale)
+ (player_height_offset * XRServer.world_scale),
player_height_min * XRServer.world_scale,
player_height_max * XRServer.world_scale)

Expand Down
27 changes: 17 additions & 10 deletions addons/godot-xr-tools/user_settings/user_settings.gd
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@ enum WebXRPrimary {
}


@export_group("Input")

## User setting for snap-turn
@export var snap_turning : bool = true

## User setting for player height adjust
@export var player_height_adjust : float = 0.0: set = set_player_height_adjust
@export_group("Player")

## User setting for player height
@export var player_height : float = 1.85: set = set_player_height

@export_group("WebXR")

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

## Reset to default values
func reset_to_defaults() -> void:
# Reset to defaults
# Reset to defaults.
# Where applicable we obtain our project settings
snap_turning = XRTools.get_default_snap_turning()
player_height_adjust = 0.0
player_height = XRTools.get_player_standard_height()
webxr_primary = WebXRPrimary.AUTO
webxr_auto_primary = 0


## Set the player height adjust property
func set_player_height_adjust(new_value : float) -> void:
player_height_adjust = clamp(new_value, -1.0, 1.0)
## Set the player height property
func set_player_height(new_value : float) -> void:
player_height = clamp(new_value, 1.0, 2.5)


## Set the WebXR primary
Expand Down Expand Up @@ -80,7 +87,7 @@ func save() -> void:
"default_snap_turning" : snap_turning
},
"player" : {
"height_adjust" : player_height_adjust
"height" : player_height
},
"webxr" : {
"webxr_primary" : webxr_primary,
Expand Down Expand Up @@ -149,8 +156,8 @@ func _load() -> void:
# Parse our player settings
if settings.has("player"):
var player : Dictionary = settings["player"]
if player.has("height_adjust"):
player_height_adjust = player["height_adjust"]
if player.has("height"):
player_height = player["height"]

# Parse our WebXR settings
if settings.has("webxr"):
Expand Down
33 changes: 11 additions & 22 deletions addons/godot-xr-tools/user_settings/user_settings_ui.gd
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
extends TabContainer

@export_node_path("XRCamera3D") var camera
signal player_height_changed(new_height)

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

func _update():
# Input
$Input/SnapTurning/SnapTurningCB.button_pressed = XRToolsUserSettings.snap_turning
snap_turning_button.button_pressed = XRToolsUserSettings.snap_turning

# Player
$Player/PlayerHeight/PlayerHeightSlider.value = XRToolsUserSettings.player_height_adjust
player_height_slider.value = XRToolsUserSettings.player_height

# WebXR
$WebXR/WebXR/WebXRPrimary.selected = XRToolsUserSettings.webxr_primary
webxr_primary_button.selected = XRToolsUserSettings.webxr_primary


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

# Input settings changed
func _on_SnapTurningCB_pressed():
XRToolsUserSettings.snap_turning = $Input/SnapTurning/SnapTurningCB.button_pressed
XRToolsUserSettings.snap_turning = snap_turning_button.button_pressed

# Player settings changed
func _on_PlayerHeightSlider_drag_ended(_value_changed):
XRToolsUserSettings.player_height_adjust = $Player/PlayerHeight/PlayerHeightSlider.value


func _on_PlayerHeightStandard_pressed():
if camera.is_empty():
return

var camera_node = get_node_or_null(camera)
if !camera_node:
return

var base_height = camera_node.transform.origin.y + player_head_height
var height_adjust = XRTools.get_player_standard_height() - base_height
XRToolsUserSettings.player_height_adjust = height_adjust
$Player/PlayerHeight/PlayerHeightSlider.value = XRToolsUserSettings.player_height_adjust

XRToolsUserSettings.player_height = player_height_slider.value
emit_signal("player_height_changed", XRToolsUserSettings.player_height)

func _on_web_xr_primary_item_selected(index: int) -> void:
XRToolsUserSettings.webxr_primary = index
107 changes: 58 additions & 49 deletions addons/godot-xr-tools/user_settings/user_settings_ui.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -10,98 +10,108 @@ size_flags_vertical = 3
theme_override_font_sizes/font_size = 12
script = ExtResource("1")

[node name="Input" type="VBoxContainer" parent="."]
[node name="Input" type="MarginContainer" parent="."]
layout_mode = 2
theme_override_constants/margin_left = 5
theme_override_constants/margin_top = 5
theme_override_constants/margin_right = 5
theme_override_constants/margin_bottom = 5

[node name="SnapTurning" type="HBoxContainer" parent="Input"]
[node name="InputVBox" type="VBoxContainer" parent="Input"]
layout_mode = 2

[node name="Label" type="Label" parent="Input/SnapTurning"]
[node name="SnapTurning" type="HBoxContainer" parent="Input/InputVBox"]
layout_mode = 2

[node name="Label" type="Label" parent="Input/InputVBox/SnapTurning"]
layout_mode = 2
theme_override_font_sizes/font_size = 12
text = "Snap turning:"

[node name="SnapTurningCB" type="CheckBox" parent="Input/SnapTurning"]
[node name="SnapTurningCB" type="CheckBox" parent="Input/InputVBox/SnapTurning"]
layout_mode = 2

[node name="HSeparator" type="HSeparator" parent="Input"]
[node name="HSeparator" type="HSeparator" parent="Input/InputVBox"]
layout_mode = 2

[node name="Buttons" type="HBoxContainer" parent="Input"]
[node name="Buttons" type="HBoxContainer" parent="Input/InputVBox"]
layout_mode = 2
alignment = 1

[node name="Save" type="Button" parent="Input/Buttons"]
[node name="Save" type="Button" parent="Input/InputVBox/Buttons"]
layout_mode = 2
theme_override_font_sizes/font_size = 12
text = "Apply"

[node name="Reset" type="Button" parent="Input/Buttons"]
[node name="Reset" type="Button" parent="Input/InputVBox/Buttons"]
layout_mode = 2
theme_override_font_sizes/font_size = 12
text = "Reset"

[node name="Player" type="VBoxContainer" parent="."]
[node name="Player" type="MarginContainer" parent="."]
visible = false
layout_mode = 2
theme_override_constants/margin_left = 5
theme_override_constants/margin_top = 5
theme_override_constants/margin_right = 5
theme_override_constants/margin_bottom = 5

[node name="PlayerHeight" type="HBoxContainer" parent="Player"]
layout_mode = 2

[node name="Label" type="Label" parent="Player/PlayerHeight"]
layout_mode = 2
theme_override_font_sizes/font_size = 12
text = "Height adjust:"

[node name="PlayerHeightSlider" type="HSlider" parent="Player/PlayerHeight"]
[node name="PlayerVBox" type="VBoxContainer" parent="Player"]
layout_mode = 2
size_flags_horizontal = 3
min_value = -1.0
max_value = 1.0
step = 0.1

[node name="PlayerHeightCalc" type="HBoxContainer" parent="Player"]
[node name="PlayerHeight" type="HBoxContainer" parent="Player/PlayerVBox"]
layout_mode = 2

[node name="Label" type="Label" parent="Player/PlayerHeightCalc"]
[node name="Label" type="Label" parent="Player/PlayerVBox/PlayerHeight"]
layout_mode = 2
theme_override_font_sizes/font_size = 12
text = "Height adjust:"

[node name="PlayerHeightStandard" type="Button" parent="Player/PlayerHeightCalc"]
[node name="PlayerHeightSlider" type="HSlider" parent="Player/PlayerVBox/PlayerHeight"]
layout_mode = 2
theme_override_font_sizes/font_size = 12
text = "Set to standard"
size_flags_horizontal = 3
min_value = 1.0
max_value = 2.5
step = 0.05
value = 1.0

[node name="HSeparator" type="HSeparator" parent="Player"]
[node name="HSeparator" type="HSeparator" parent="Player/PlayerVBox"]
layout_mode = 2

[node name="Buttons" type="HBoxContainer" parent="Player"]
[node name="Buttons" type="HBoxContainer" parent="Player/PlayerVBox"]
layout_mode = 2
alignment = 1

[node name="Save" type="Button" parent="Player/Buttons"]
[node name="Save" type="Button" parent="Player/PlayerVBox/Buttons"]
layout_mode = 2
theme_override_font_sizes/font_size = 12
text = "Apply"

[node name="Reset" type="Button" parent="Player/Buttons"]
[node name="Reset" type="Button" parent="Player/PlayerVBox/Buttons"]
layout_mode = 2
theme_override_font_sizes/font_size = 12
text = "Reset"

[node name="WebXR" type="VBoxContainer" parent="."]
[node name="WebXR" type="MarginContainer" parent="."]
visible = false
layout_mode = 2
theme_override_constants/margin_left = 5
theme_override_constants/margin_top = 5
theme_override_constants/margin_right = 5
theme_override_constants/margin_bottom = 5

[node name="WebXRVBox" type="VBoxContainer" parent="WebXR"]
layout_mode = 2

[node name="WebXR" type="HBoxContainer" parent="WebXR"]
[node name="WebXR" type="HBoxContainer" parent="WebXR/WebXRVBox"]
layout_mode = 2

[node name="Label" type="Label" parent="WebXR/WebXR"]
[node name="Label" type="Label" parent="WebXR/WebXRVBox/WebXR"]
layout_mode = 2
theme_override_font_sizes/font_size = 12
text = "WebXR primary:"

[node name="WebXRPrimary" type="OptionButton" parent="WebXR/WebXR"]
[node name="WebXRPrimary" type="OptionButton" parent="WebXR/WebXRVBox/WebXR"]
layout_mode = 2
theme_override_font_sizes/font_size = 12
item_count = 3
Expand All @@ -113,30 +123,29 @@ popup/item_1/id = 1
popup/item_2/text = "Trackpad"
popup/item_2/id = 2

[node name="HSeparator" type="HSeparator" parent="WebXR"]
[node name="HSeparator" type="HSeparator" parent="WebXR/WebXRVBox"]
layout_mode = 2

[node name="Buttons" type="HBoxContainer" parent="WebXR"]
[node name="Buttons" type="HBoxContainer" parent="WebXR/WebXRVBox"]
layout_mode = 2
alignment = 1

[node name="Save" type="Button" parent="WebXR/Buttons"]
[node name="Save" type="Button" parent="WebXR/WebXRVBox/Buttons"]
layout_mode = 2
theme_override_font_sizes/font_size = 12
text = "Apply"

[node name="Reset" type="Button" parent="WebXR/Buttons"]
[node name="Reset" type="Button" parent="WebXR/WebXRVBox/Buttons"]
layout_mode = 2
theme_override_font_sizes/font_size = 12
text = "Reset"

[connection signal="pressed" from="Input/SnapTurning/SnapTurningCB" to="." method="_on_SnapTurningCB_pressed"]
[connection signal="pressed" from="Input/Buttons/Save" to="." method="_on_Save_pressed"]
[connection signal="pressed" from="Input/Buttons/Reset" to="." method="_on_Reset_pressed"]
[connection signal="drag_ended" from="Player/PlayerHeight/PlayerHeightSlider" to="." method="_on_PlayerHeightSlider_drag_ended"]
[connection signal="pressed" from="Player/PlayerHeightCalc/PlayerHeightStandard" to="." method="_on_PlayerHeightStandard_pressed"]
[connection signal="pressed" from="Player/Buttons/Save" to="." method="_on_Save_pressed"]
[connection signal="pressed" from="Player/Buttons/Reset" to="." method="_on_Reset_pressed"]
[connection signal="item_selected" from="WebXR/WebXR/WebXRPrimary" to="." method="_on_web_xr_primary_item_selected"]
[connection signal="pressed" from="WebXR/Buttons/Save" to="." method="_on_Save_pressed"]
[connection signal="pressed" from="WebXR/Buttons/Reset" to="." method="_on_Reset_pressed"]
[connection signal="pressed" from="Input/InputVBox/SnapTurning/SnapTurningCB" to="." method="_on_SnapTurningCB_pressed"]
[connection signal="pressed" from="Input/InputVBox/Buttons/Save" to="." method="_on_Save_pressed"]
[connection signal="pressed" from="Input/InputVBox/Buttons/Reset" to="." method="_on_Reset_pressed"]
[connection signal="drag_ended" from="Player/PlayerVBox/PlayerHeight/PlayerHeightSlider" to="." method="_on_PlayerHeightSlider_drag_ended"]
[connection signal="pressed" from="Player/PlayerVBox/Buttons/Save" to="." method="_on_Save_pressed"]
[connection signal="pressed" from="Player/PlayerVBox/Buttons/Reset" to="." method="_on_Reset_pressed"]
[connection signal="item_selected" from="WebXR/WebXRVBox/WebXR/WebXRPrimary" to="." method="_on_PlayerHeightSlider_drag_ended"]
[connection signal="pressed" from="WebXR/WebXRVBox/Buttons/Save" to="." method="_on_Save_pressed"]
[connection signal="pressed" from="WebXR/WebXRVBox/Buttons/Reset" to="." method="_on_Reset_pressed"]
4 changes: 4 additions & 0 deletions addons/godot-xr-tools/xr_tools.gd
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
class_name XRTools
extends Node

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

static func get_grip_threshold() -> float:
# can return null which is not a float, so don't type this!
Expand Down
4 changes: 4 additions & 0 deletions scenes/main_menu/main_menu_level.gd
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,7 @@ func _on_Demos_child_entered_tree(_node):

func _on_Demos_child_exiting_tree(_node):
_update_demo_positions()


func _on_settings_ui_player_height_changed(new_height):
$XROrigin3D/PlayerBody.calibrate_player_height()
Loading

0 comments on commit b1bcf86

Please sign in to comment.