Skip to content

Commit

Permalink
Improve snap turning logic
Browse files Browse the repository at this point in the history
- Add defaults in Project Settings
- Add user settings system to save user preference
- By default have turn movement adhere to user/system settings
- Add user setting for player height adjustment
  • Loading branch information
BastiaanOlij committed Oct 26, 2022
1 parent 6a9390f commit b01e7f6
Show file tree
Hide file tree
Showing 14 changed files with 466 additions and 16 deletions.
1 change: 1 addition & 0 deletions VERSIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- Improved pointer demo supporting left hand with switching
- Enhanced pointer laser visibility options for colliding with targets.
- Implement poke feature (finger interaction)
- Improvements to snap turning

# 3.0.0
- Included demo project with test scenes to evaluate features
Expand Down
2 changes: 1 addition & 1 deletion addons/godot-xr-tools/assets/player_body.gd
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ func override_player_height(key, value: float = -1.0):
func _update_body_under_camera():
# 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,
camera_node.transform.origin.y + player_head_height + player_height_offset + XRToolsUserSettings.player_height_adjust,
player_height_min * ARVRServer.world_scale,
player_height_max * ARVRServer.world_scale)

Expand Down
25 changes: 21 additions & 4 deletions addons/godot-xr-tools/functions/movement_turn.gd
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@ extends XRToolsMovementProvider
## Movement provider order
export var order : int = 5

## Use smooth rotation (may cause motion sickness)
export var smooth_rotation : bool = false
## Movement mode
enum TurnMode {
DEFAULT,
SNAP,
SMOOTH
}

export (TurnMode) var turn_mode = TurnMode.DEFAULT

## Smooth turn speed in radians per second
export var smooth_turn_speed : float = 2.0
Expand All @@ -38,22 +44,33 @@ var _turn_step : float = 0.0
# Controller node
onready var _controller : ARVRController = get_parent()

func _snap_turning():
if turn_mode == TurnMode.SNAP:
return true
elif turn_mode == TurnMode.SMOOTH:
return false
else:
return XRToolsUserSettings.snap_turning

# Perform jump movement
func physics_movement(delta: float, player_body: XRToolsPlayerBody, _disabled: bool):
# Skip if the controller isn't active
if !_controller.get_is_active():
return

var deadzone = 0.1
if _snap_turning():
deadzone = XRTools.get_snap_turning_deadzone()

# Read the left/right joystick axis
var left_right := _controller.get_joystick_axis(XRTools.Axis.VR_PRIMARY_X_AXIS)
if abs(left_right) <= 0.1:
if abs(left_right) <= deadzone:
# Not turning
_turn_step = 0.0
return

# Handle smooth rotation
if smooth_rotation:
if !_snap_turning():
_rotate_player(player_body, smooth_turn_speed * delta * left_right)
return

Expand Down
71 changes: 66 additions & 5 deletions addons/godot-xr-tools/plugin.gd
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ enum Buttons {

static func get_grip_threshold() -> float:
# can return null which is not a float, so don't type this!
var threshold = ProjectSettings.get_setting("godot_xr_tools/input/grip_threshold")
var threshold = 0.7

if ProjectSettings.has_setting("godot_xr_tools/input/grip_threshold"):
threshold = ProjectSettings.get_setting("godot_xr_tools/input/grip_threshold")

if threshold == null:
# plugin disabled or setting not saved, return our default.
threshold = 0.7
if !(threshold >= 0.2 and threshold <= 0.8):
# out of bounds? reset to default
threshold = 0.7

return threshold

static func set_grip_threshold(p_threshold : float) -> void:
Expand All @@ -55,6 +55,61 @@ static func set_grip_threshold(p_threshold : float) -> void:

ProjectSettings.set_setting("godot_xr_tools/input/grip_threshold", p_threshold)


static func get_snap_turning_deadzone() -> float:
# can return null which is not a float, so don't type this!
var deadzone = 0.25

if ProjectSettings.has_setting("godot_xr_tools/input/snap_turning_deadzone"):
deadzone = ProjectSettings.get_setting("godot_xr_tools/input/snap_turning_deadzone")

if !(deadzone >= 0.0 and deadzone <= 0.5):
# out of bounds? reset to default
deadzone = 0.25

return deadzone

static func set_snap_turning_deadzone(p_deadzone : float) -> void:
if !(p_deadzone >= 0.0 and p_deadzone <= 0.5):
print("Deadzone out of bounds")
return

ProjectSettings.set_setting("godot_xr_tools/input/snap_turning_deadzone", p_deadzone)


static func get_default_snap_turning() -> bool:
var default = true

if ProjectSettings.has_setting("godot_xr_tools/input/default_snap_turning"):
default = ProjectSettings.get_setting("godot_xr_tools/input/default_snap_turning")

# default may not be bool, so JIC
return default == true

static func set_default_snap_turning(p_default : bool) -> void:
ProjectSettings.set_setting("godot_xr_tools/input/default_snap_turning", p_default)


static func get_player_standard_height() -> float:
var standard_height = 1.85

if ProjectSettings.has_setting("godot_xr_tools/player/standard_height"):
standard_height = ProjectSettings.get_setting("godot_xr_tools/player/standard_height")

if !(standard_height >= 1.0 and standard_height <= 2.5):
# out of bounds? reset to default
standard_height = 1.85

return standard_height

static func set_player_standard_height(p_height : float) -> void:
if !(p_height >= 1.0 and p_height <= 2.5):
print("Standard height out of bounds")
return

ProjectSettings.set_setting("godot_xr_tools/player/standard_height", p_height)


func _define_project_setting(p_name : String, p_type : int, p_hint : int = PROPERTY_HINT_NONE , p_hint_string : String = "", p_default_val = "") -> void:
# p_default_val can be any type!!

Expand All @@ -77,7 +132,13 @@ func _enter_tree():

# provide meta data for our project settings
_define_project_setting("godot_xr_tools/input/grip_threshold", TYPE_REAL, PROPERTY_HINT_RANGE, "0.2,0.8,0.05", 0.7)
_define_project_setting("godot_xr_tools/input/snap_turning_deadzone", TYPE_REAL, PROPERTY_HINT_RANGE, "0.0,0.5,0.05", 0.25)
_define_project_setting("godot_xr_tools/input/default_snap_turning", TYPE_BOOL, PROPERTY_HINT_NONE, "", true)

_define_project_setting("godot_xr_tools/player/standard_height", TYPE_REAL, PROPERTY_HINT_RANGE, "1.0,2.5,0.1", 1.85)

# register our autoload user settings object
add_autoload_singleton("XRToolsUserSettings", "res://addons/godot-xr-tools/user_settings/user_settings.gd")

func _exit_tree():
# our plugin is turned off
Expand Down
63 changes: 63 additions & 0 deletions addons/godot-xr-tools/user_settings/user_settings.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
extends Node

# our settings
export var snap_turning : bool = true
export var player_height_adjust : float = 0.0 setget set_player_height_adjust

var settings_file_name = "user://xtools_user_settings.json"

func set_player_height_adjust(new_value : float) -> void:
player_height_adjust = clamp(new_value, -1.0, 1.0)


func reset_to_defaults():
# Reset to defaults
snap_turning = XRTools.get_default_snap_turning()
player_height_adjust = 0.0


func _load():
# First reset our values
reset_to_defaults()

# Now attempt to load our settings file
var file = File.new()
if !file.file_exists(settings_file_name):
return

if file.open(settings_file_name, File.READ):
var text = file.get_as_text()
file.close()

var data : Dictionary = parse_json(text)

# Parse our input settings
if data.has("input"):
var input : Dictionary = data["input"]
if input.has("default_snap_turning"):
snap_turning = input["default_snap_turning"]

# Parse our player settings
if data.has("player"):
var player : Dictionary = data["player"]
if player.has("height_adjust"):
player_height_adjust = player["height_adjust"]

func save():
var data = {
"input" : {
"default_snap_turning" : snap_turning
},
"player" : {
"height_adjust" : player_height_adjust
}
}

var file = File.new()
if file.open(settings_file_name, File.WRITE):
file.store_line(to_json(data))
file.close()

# Called when the node enters the scene tree for the first time.
func _ready():
_load()
54 changes: 54 additions & 0 deletions addons/godot-xr-tools/user_settings/user_settings_ui.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
extends TabContainer

export (NodePath) var camera
export var player_head_height : float = 0.1

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

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

# Called when the node enters the scene tree for the first time.
func _ready():
if XRToolsUserSettings:
_update()
else:
$Save/Button.disabled = true


func _on_Save_pressed():
if XRToolsUserSettings:
# Save
XRToolsUserSettings.save()


func _on_Reset_pressed():
if XRToolsUserSettings:
XRToolsUserSettings.reset_to_defaults()
_update()

# Input settings changed
func _on_SnapTurningCB_pressed():
XRToolsUserSettings.snap_turning = $Input/SnapTurning/SnapTurningCB.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:
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


Loading

0 comments on commit b01e7f6

Please sign in to comment.