This commit is contained in:
sharpoff
2026-01-14 13:01:37 +09:00
commit 49d7e22132
660 changed files with 41243 additions and 0 deletions

View File

@@ -0,0 +1,121 @@
@tool
class_name XRToolsHoldButton
extends Node3D
signal pressed
# Enable our button
@export var enabled : bool = false: set = set_enabled
@export var activate_action : String = "trigger_click"
@export var activate_action_desktop : String = "ui_accept"
# Countdown
@export var hold_time : float = 2.0
# Color our our visualisation
@export var color : Color = Color(1.0, 1.0, 1.0, 1.0): set = set_color
# Size
@export var size : Vector2 = Vector2(1.0, 1.0): set = set_size
var time_held = 0.0
var material : ShaderMaterial
var xr_start_node : XRToolsStartXR
# Add support for is_xr_class on XRTools classes
func is_xr_class(xr_name: String) -> bool:
return xr_name == "XRToolsHoldButton"
# Called when the node enters the scene tree for the first time.
func _ready():
material = $Visualise.get_surface_override_material(0)
xr_start_node = XRTools.find_xr_child(
XRTools.find_xr_ancestor(self,
"*Staging",
"XRToolsStaging"),"StartXR","Node")
if !Engine.is_editor_hint():
_set_time_held(0.0)
_update_size()
_update_color()
_update_enabled()
func _process(delta):
if Engine.is_editor_hint():
return
var button_pressed = false
# we check all trackers
var controllers = XRServer.get_trackers(XRServer.TRACKER_CONTROLLER)
for name in controllers:
var tracker : XRPositionalTracker = controllers[name]
if tracker.get_input(activate_action):
button_pressed = true
if !xr_start_node.is_xr_active():
if Input.is_action_pressed("ui_accept") or Input.is_action_pressed(activate_action_desktop):
button_pressed = true
if button_pressed:
_set_time_held(time_held + delta)
if time_held > hold_time:
# done, disable this
set_enabled(false)
emit_signal("pressed")
else:
_set_time_held(max(0.0, time_held - delta))
func set_enabled(p_enabled: bool):
enabled = p_enabled
_update_enabled()
func _update_enabled():
if is_inside_tree() and !Engine.is_editor_hint():
_set_time_held(0.0)
set_process(enabled)
func _set_time_held(p_time_held):
time_held = p_time_held
if material:
$Visualise.visible = time_held > 0.0
material.set_shader_parameter("value", time_held/hold_time)
func set_size(p_size: Vector2):
size = p_size
_update_size()
func _update_size():
if material: # Note, material won't be set until after we setup our scene
var mesh : QuadMesh = $Visualise.mesh
if mesh.size != size:
mesh.size = size
# updating the size will unset our material, so reset it
$Visualise.set_surface_override_material(0, material)
func set_color(p_color: Color):
color = p_color
_update_color()
func _update_color():
if material:
material.set_shader_parameter("albedo", color)

View File

@@ -0,0 +1 @@
uid://cwvolliuv8nuy

View File

@@ -0,0 +1,23 @@
[gd_scene load_steps=5 format=3 uid="uid://cymteydkxagpp"]
[ext_resource type="Script" uid="uid://cwvolliuv8nuy" path="res://addons/godot-xr-tools/misc/hold_button.gd" id="1"]
[ext_resource type="Shader" uid="uid://c6okm2ay0fkjf" path="res://addons/godot-xr-tools/misc/hold_button_visualshader.tres" id="2"]
[sub_resource type="QuadMesh" id="1"]
resource_local_to_scene = true
[sub_resource type="ShaderMaterial" id="ShaderMaterial_tkbhq"]
render_priority = 0
shader = ExtResource("2")
shader_parameter/albedo = Color(1, 1, 1, 1)
shader_parameter/value = 0.2
shader_parameter/fade = 0.05
shader_parameter/radius = 0.8
shader_parameter/width = 0.2
[node name="HoldButton" type="Node3D"]
script = ExtResource("1")
[node name="Visualise" type="MeshInstance3D" parent="."]
mesh = SubResource("1")
surface_material_override/0 = SubResource("ShaderMaterial_tkbhq")

View File

@@ -0,0 +1,313 @@
[gd_resource type="VisualShader" load_steps=28 format=3 uid="uid://dncfip67nl2sf"]
[sub_resource type="VisualShaderNodeFloatOp" id="1"]
output_port_for_preview = 0
default_input_values = [0, 0.0, 1, 0.1]
operator = 3
[sub_resource type="VisualShaderNodeFloatParameter" id="2"]
parameter_name = "width"
[sub_resource type="VisualShaderNodeFloatOp" id="11"]
output_port_for_preview = 0
default_input_values = [0, 1.0, 1, 0.0]
operator = 1
[sub_resource type="VisualShaderNodeFloatOp" id="12"]
output_port_for_preview = 0
operator = 1
[sub_resource type="VisualShaderNodeFloatParameter" id="13"]
parameter_name = "fade"
[sub_resource type="VisualShaderNodeFloatOp" id="14"]
default_input_values = [0, 0.0, 1, 2.0]
operator = 3
[sub_resource type="VisualShaderNodeVectorFunc" id="15"]
output_port_for_preview = 0
[sub_resource type="VisualShaderNodeDotProduct" id="16"]
default_input_values = [0, Vector3(0, 0, 0), 1, Vector3(0, -1, 0)]
[sub_resource type="VisualShaderNodeVectorOp" id="17"]
default_input_values = [0, Vector3(0, 0, 0), 1, Vector3(0, -1, 0)]
operator = 8
[sub_resource type="VisualShaderNodeColorParameter" id="3"]
parameter_name = "albedo"
[sub_resource type="VisualShaderNodeVectorDecompose" id="18"]
[sub_resource type="VisualShaderNodeIf" id="19"]
[sub_resource type="VisualShaderNodeFloatOp" id="20"]
default_input_values = [0, 6.28319, 1, 0.0]
operator = 1
[sub_resource type="VisualShaderNodeFloatFunc" id="21"]
output_port_for_preview = 0
function = 4
[sub_resource type="VisualShaderNodeFloatOp" id="22"]
output_port_for_preview = 0
default_input_values = [0, 0.0, 1, 6.28319]
operator = 3
[sub_resource type="VisualShaderNodeFloatParameter" id="23"]
parameter_name = "value"
[sub_resource type="VisualShaderNodeFloatOp" id="24"]
output_port_for_preview = 0
operator = 1
[sub_resource type="VisualShaderNodeFloatOp" id="25"]
output_port_for_preview = 0
operator = 3
[sub_resource type="VisualShaderNodeFloatOp" id="26"]
output_port_for_preview = 0
operator = 6
[sub_resource type="VisualShaderNodeInput" id="4"]
output_port_for_preview = 0
input_name = "uv"
[sub_resource type="VisualShaderNodeFloatOp" id="27"]
default_input_values = [0, 0.0, 1, 6.28319]
operator = 3
[sub_resource type="VisualShaderNodeVectorOp" id="5"]
output_port_for_preview = 0
default_input_values = [0, Vector3(0, 0, 0), 1, Vector3(2, 2, 0)]
operator = 2
[sub_resource type="VisualShaderNodeVectorOp" id="6"]
output_port_for_preview = 0
default_input_values = [0, Vector3(0, 0, 0), 1, Vector3(-1, -1, 0)]
[sub_resource type="VisualShaderNodeVectorLen" id="7"]
output_port_for_preview = 0
[sub_resource type="VisualShaderNodeFloatOp" id="8"]
output_port_for_preview = 0
operator = 1
[sub_resource type="VisualShaderNodeFloatParameter" id="9"]
parameter_name = "radius"
[sub_resource type="VisualShaderNodeFloatFunc" id="10"]
output_port_for_preview = 0
function = 12
[resource]
code = "shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_lambert, specular_schlick_ggx, depth_test_disabled, unshaded;
uniform vec4 albedo : source_color;
uniform float value;
uniform float fade;
uniform float radius;
uniform float width;
void fragment() {
// ColorParameter:2
vec4 n_out2p0 = albedo;
// Input:3
vec2 n_out3p0 = UV;
// VectorOp:4
vec3 n_in4p1 = vec3(2.00000, 2.00000, 0.00000);
vec3 n_out4p0 = vec3(n_out3p0, 0.0) * n_in4p1;
// VectorOp:5
vec3 n_in5p1 = vec3(-1.00000, -1.00000, 0.00000);
vec3 n_out5p0 = n_out4p0 + n_in5p1;
// VectorFunc:17
vec3 n_out17p0 = normalize(n_out5p0);
// VectorOp:19
vec3 n_in19p1 = vec3(0.00000, -1.00000, 0.00000);
vec3 n_out19p0 = cross(n_out17p0, n_in19p1);
// VectorDecompose:20
float n_out20p0 = n_out19p0.x;
float n_out20p1 = n_out19p0.y;
float n_out20p2 = n_out19p0.z;
// DotProduct:18
vec3 n_in18p1 = vec3(0.00000, -1.00000, 0.00000);
float n_out18p0 = dot(n_out17p0, n_in18p1);
// FloatFunc:24
float n_out24p0 = acos(n_out18p0);
// FloatOp:23
float n_in23p0 = 6.28319;
float n_out23p0 = n_in23p0 - n_out24p0;
vec3 n_out22p0;
// If:22
float n_in22p1 = 0.00000;
float n_in22p2 = 0.00001;
if(abs(n_out20p2 - n_in22p1) < n_in22p2)
{
n_out22p0 = vec3(n_out24p0);
}
else if(n_out20p2 < n_in22p1)
{
n_out22p0 = vec3(n_out24p0);
}
else
{
n_out22p0 = vec3(n_out23p0);
}
// FloatOp:25
float n_in25p1 = 6.28319;
float n_out25p0 = n_out22p0.x / n_in25p1;
// FloatParameter:26
float n_out26p0 = value;
// FloatOp:27
float n_out27p0 = n_out25p0 - n_out26p0;
// FloatParameter:14
float n_out14p0 = fade;
// FloatOp:30
float n_in30p1 = 6.28319;
float n_out30p0 = n_out14p0 / n_in30p1;
// FloatOp:28
float n_out28p0 = n_out27p0 / n_out30p0;
// VectorLen:6
float n_out6p0 = length(n_out5p0);
// FloatParameter:8
float n_out8p0 = radius;
// FloatOp:7
float n_out7p0 = n_out6p0 - n_out8p0;
// FloatFunc:9
float n_out9p0 = abs(n_out7p0);
// FloatParameter:11
float n_out11p0 = width;
// FloatOp:15
float n_in15p1 = 2.00000;
float n_out15p0 = n_out11p0 / n_in15p1;
// FloatOp:13
float n_out13p0 = n_out9p0 - n_out15p0;
// FloatOp:10
float n_out10p0 = n_out13p0 / n_out14p0;
// FloatOp:29
float n_out29p0 = max(n_out28p0, n_out10p0);
// FloatOp:12
float n_in12p0 = 1.00000;
float n_out12p0 = n_in12p0 - n_out29p0;
// Output:0
ALBEDO = vec3(n_out2p0.xyz);
ALPHA = n_out12p0;
}
"
flags/depth_test_disabled = true
flags/unshaded = true
nodes/fragment/0/position = Vector2(1800, -40)
nodes/fragment/2/node = SubResource("3")
nodes/fragment/2/position = Vector2(1480, -200)
nodes/fragment/3/node = SubResource("4")
nodes/fragment/3/position = Vector2(-220, 200)
nodes/fragment/4/node = SubResource("5")
nodes/fragment/4/position = Vector2(-20, 200)
nodes/fragment/5/node = SubResource("6")
nodes/fragment/5/position = Vector2(180, 200)
nodes/fragment/6/node = SubResource("7")
nodes/fragment/6/position = Vector2(380, 200)
nodes/fragment/7/node = SubResource("8")
nodes/fragment/7/position = Vector2(580, 200)
nodes/fragment/8/node = SubResource("9")
nodes/fragment/8/position = Vector2(260, 440)
nodes/fragment/9/node = SubResource("10")
nodes/fragment/9/position = Vector2(780, 200)
nodes/fragment/10/node = SubResource("1")
nodes/fragment/10/position = Vector2(1200, 200)
nodes/fragment/11/node = SubResource("2")
nodes/fragment/11/position = Vector2(260, 600)
nodes/fragment/12/node = SubResource("11")
nodes/fragment/12/position = Vector2(1600, 60)
nodes/fragment/13/node = SubResource("12")
nodes/fragment/13/position = Vector2(1000, 200)
nodes/fragment/14/node = SubResource("13")
nodes/fragment/14/position = Vector2(260, 780)
nodes/fragment/15/node = SubResource("14")
nodes/fragment/15/position = Vector2(560, 600)
nodes/fragment/17/node = SubResource("15")
nodes/fragment/17/position = Vector2(-380, -100)
nodes/fragment/18/node = SubResource("16")
nodes/fragment/18/position = Vector2(-120, -40)
nodes/fragment/19/node = SubResource("17")
nodes/fragment/19/position = Vector2(-120, -180)
nodes/fragment/20/node = SubResource("18")
nodes/fragment/20/position = Vector2(60, -180)
nodes/fragment/22/node = SubResource("19")
nodes/fragment/22/position = Vector2(620, -100)
nodes/fragment/23/node = SubResource("20")
nodes/fragment/23/position = Vector2(360, 40)
nodes/fragment/24/node = SubResource("21")
nodes/fragment/24/position = Vector2(60, -40)
nodes/fragment/25/node = SubResource("22")
nodes/fragment/25/position = Vector2(800, -100)
nodes/fragment/26/node = SubResource("23")
nodes/fragment/26/position = Vector2(660, -360)
nodes/fragment/27/node = SubResource("24")
nodes/fragment/27/position = Vector2(1000, -100)
nodes/fragment/28/node = SubResource("25")
nodes/fragment/28/position = Vector2(1200, -100)
nodes/fragment/29/node = SubResource("26")
nodes/fragment/29/position = Vector2(1400, 60)
nodes/fragment/30/node = SubResource("27")
nodes/fragment/30/position = Vector2(1000, -240)
nodes/fragment/connections = PackedInt32Array(2, 0, 0, 0, 3, 0, 4, 0, 4, 0, 5, 0, 5, 0, 6, 0, 6, 0, 7, 0, 8, 0, 7, 1, 7, 0, 9, 0, 12, 0, 0, 1, 9, 0, 13, 0, 13, 0, 10, 0, 14, 0, 10, 1, 11, 0, 15, 0, 15, 0, 13, 1, 5, 0, 17, 0, 17, 0, 18, 0, 17, 0, 19, 0, 19, 0, 20, 0, 18, 0, 24, 0, 24, 0, 23, 1, 22, 0, 25, 0, 20, 2, 22, 0, 24, 0, 22, 3, 23, 0, 22, 4, 24, 0, 22, 5, 25, 0, 27, 0, 26, 0, 27, 1, 27, 0, 28, 0, 28, 0, 29, 0, 10, 0, 29, 1, 29, 0, 12, 1, 14, 0, 30, 0, 30, 0, 28, 1)

View File

@@ -0,0 +1,313 @@
[gd_resource type="VisualShader" load_steps=28 format=3 uid="uid://c6okm2ay0fkjf"]
[sub_resource type="VisualShaderNodeFloatOp" id="1"]
output_port_for_preview = 0
default_input_values = [0, 0.0, 1, 0.1]
operator = 3
[sub_resource type="VisualShaderNodeFloatParameter" id="2"]
parameter_name = "width"
[sub_resource type="VisualShaderNodeFloatOp" id="11"]
output_port_for_preview = 0
default_input_values = [0, 1.0, 1, 0.0]
operator = 1
[sub_resource type="VisualShaderNodeFloatOp" id="12"]
output_port_for_preview = 0
operator = 1
[sub_resource type="VisualShaderNodeFloatParameter" id="13"]
parameter_name = "fade"
[sub_resource type="VisualShaderNodeFloatOp" id="14"]
default_input_values = [0, 0.0, 1, 2.0]
operator = 3
[sub_resource type="VisualShaderNodeVectorFunc" id="15"]
output_port_for_preview = 0
[sub_resource type="VisualShaderNodeDotProduct" id="16"]
default_input_values = [0, Vector3(0, 0, 0), 1, Vector3(0, -1, 0)]
[sub_resource type="VisualShaderNodeVectorOp" id="17"]
default_input_values = [0, Vector3(0, 0, 0), 1, Vector3(0, -1, 0)]
operator = 8
[sub_resource type="VisualShaderNodeColorParameter" id="3"]
parameter_name = "albedo"
[sub_resource type="VisualShaderNodeVectorDecompose" id="18"]
[sub_resource type="VisualShaderNodeIf" id="19"]
[sub_resource type="VisualShaderNodeFloatOp" id="20"]
default_input_values = [0, 6.28319, 1, 0.0]
operator = 1
[sub_resource type="VisualShaderNodeFloatFunc" id="21"]
output_port_for_preview = 0
function = 4
[sub_resource type="VisualShaderNodeFloatOp" id="22"]
output_port_for_preview = 0
default_input_values = [0, 0.0, 1, 6.28319]
operator = 3
[sub_resource type="VisualShaderNodeFloatParameter" id="23"]
parameter_name = "value"
[sub_resource type="VisualShaderNodeFloatOp" id="24"]
output_port_for_preview = 0
operator = 1
[sub_resource type="VisualShaderNodeFloatOp" id="25"]
output_port_for_preview = 0
operator = 3
[sub_resource type="VisualShaderNodeFloatOp" id="26"]
output_port_for_preview = 0
operator = 6
[sub_resource type="VisualShaderNodeInput" id="4"]
output_port_for_preview = 0
input_name = "uv"
[sub_resource type="VisualShaderNodeFloatOp" id="27"]
default_input_values = [0, 0.0, 1, 6.28319]
operator = 3
[sub_resource type="VisualShaderNodeVectorOp" id="5"]
output_port_for_preview = 0
default_input_values = [0, Vector3(0, 0, 0), 1, Vector3(2, 2, 0)]
operator = 2
[sub_resource type="VisualShaderNodeVectorOp" id="6"]
output_port_for_preview = 0
default_input_values = [0, Vector3(0, 0, 0), 1, Vector3(-1, -1, 0)]
[sub_resource type="VisualShaderNodeVectorLen" id="7"]
output_port_for_preview = 0
[sub_resource type="VisualShaderNodeFloatOp" id="8"]
output_port_for_preview = 0
operator = 1
[sub_resource type="VisualShaderNodeFloatParameter" id="9"]
parameter_name = "radius"
[sub_resource type="VisualShaderNodeFloatFunc" id="10"]
output_port_for_preview = 0
function = 12
[resource]
code = "shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_lambert, specular_schlick_ggx, unshaded;
uniform vec4 albedo : source_color;
uniform float value;
uniform float fade;
uniform float radius;
uniform float width;
void fragment() {
// ColorParameter:2
vec4 n_out2p0 = albedo;
// Input:3
vec2 n_out3p0 = UV;
// VectorOp:4
vec3 n_in4p1 = vec3(2.00000, 2.00000, 0.00000);
vec3 n_out4p0 = vec3(n_out3p0, 0.0) * n_in4p1;
// VectorOp:5
vec3 n_in5p1 = vec3(-1.00000, -1.00000, 0.00000);
vec3 n_out5p0 = n_out4p0 + n_in5p1;
// VectorFunc:17
vec3 n_out17p0 = normalize(n_out5p0);
// VectorOp:19
vec3 n_in19p1 = vec3(0.00000, -1.00000, 0.00000);
vec3 n_out19p0 = cross(n_out17p0, n_in19p1);
// VectorDecompose:20
float n_out20p0 = n_out19p0.x;
float n_out20p1 = n_out19p0.y;
float n_out20p2 = n_out19p0.z;
// DotProduct:18
vec3 n_in18p1 = vec3(0.00000, -1.00000, 0.00000);
float n_out18p0 = dot(n_out17p0, n_in18p1);
// FloatFunc:24
float n_out24p0 = acos(n_out18p0);
// FloatOp:23
float n_in23p0 = 6.28319;
float n_out23p0 = n_in23p0 - n_out24p0;
vec3 n_out22p0;
// If:22
float n_in22p1 = 0.00000;
float n_in22p2 = 0.00001;
if(abs(n_out20p2 - n_in22p1) < n_in22p2)
{
n_out22p0 = vec3(n_out24p0);
}
else if(n_out20p2 < n_in22p1)
{
n_out22p0 = vec3(n_out24p0);
}
else
{
n_out22p0 = vec3(n_out23p0);
}
// FloatOp:25
float n_in25p1 = 6.28319;
float n_out25p0 = n_out22p0.x / n_in25p1;
// FloatParameter:26
float n_out26p0 = value;
// FloatOp:27
float n_out27p0 = n_out25p0 - n_out26p0;
// FloatParameter:14
float n_out14p0 = fade;
// FloatOp:30
float n_in30p1 = 6.28319;
float n_out30p0 = n_out14p0 / n_in30p1;
// FloatOp:28
float n_out28p0 = n_out27p0 / n_out30p0;
// VectorLen:6
float n_out6p0 = length(n_out5p0);
// FloatParameter:8
float n_out8p0 = radius;
// FloatOp:7
float n_out7p0 = n_out6p0 - n_out8p0;
// FloatFunc:9
float n_out9p0 = abs(n_out7p0);
// FloatParameter:11
float n_out11p0 = width;
// FloatOp:15
float n_in15p1 = 2.00000;
float n_out15p0 = n_out11p0 / n_in15p1;
// FloatOp:13
float n_out13p0 = n_out9p0 - n_out15p0;
// FloatOp:10
float n_out10p0 = n_out13p0 / n_out14p0;
// FloatOp:29
float n_out29p0 = max(n_out28p0, n_out10p0);
// FloatOp:12
float n_in12p0 = 1.00000;
float n_out12p0 = n_in12p0 - n_out29p0;
// Output:0
ALBEDO = vec3(n_out2p0.xyz);
ALPHA = n_out12p0;
}
"
graph_offset = Vector2(652.664, 119.317)
flags/unshaded = true
nodes/fragment/0/position = Vector2(1800, -40)
nodes/fragment/2/node = SubResource("3")
nodes/fragment/2/position = Vector2(1480, -200)
nodes/fragment/3/node = SubResource("4")
nodes/fragment/3/position = Vector2(-220, 200)
nodes/fragment/4/node = SubResource("5")
nodes/fragment/4/position = Vector2(-20, 200)
nodes/fragment/5/node = SubResource("6")
nodes/fragment/5/position = Vector2(180, 200)
nodes/fragment/6/node = SubResource("7")
nodes/fragment/6/position = Vector2(380, 200)
nodes/fragment/7/node = SubResource("8")
nodes/fragment/7/position = Vector2(580, 200)
nodes/fragment/8/node = SubResource("9")
nodes/fragment/8/position = Vector2(260, 440)
nodes/fragment/9/node = SubResource("10")
nodes/fragment/9/position = Vector2(780, 200)
nodes/fragment/10/node = SubResource("1")
nodes/fragment/10/position = Vector2(1200, 200)
nodes/fragment/11/node = SubResource("2")
nodes/fragment/11/position = Vector2(260, 600)
nodes/fragment/12/node = SubResource("11")
nodes/fragment/12/position = Vector2(1600, 60)
nodes/fragment/13/node = SubResource("12")
nodes/fragment/13/position = Vector2(1000, 200)
nodes/fragment/14/node = SubResource("13")
nodes/fragment/14/position = Vector2(260, 780)
nodes/fragment/15/node = SubResource("14")
nodes/fragment/15/position = Vector2(560, 600)
nodes/fragment/17/node = SubResource("15")
nodes/fragment/17/position = Vector2(-380, -100)
nodes/fragment/18/node = SubResource("16")
nodes/fragment/18/position = Vector2(-120, -40)
nodes/fragment/19/node = SubResource("17")
nodes/fragment/19/position = Vector2(-120, -180)
nodes/fragment/20/node = SubResource("18")
nodes/fragment/20/position = Vector2(60, -180)
nodes/fragment/22/node = SubResource("19")
nodes/fragment/22/position = Vector2(620, -100)
nodes/fragment/23/node = SubResource("20")
nodes/fragment/23/position = Vector2(360, 40)
nodes/fragment/24/node = SubResource("21")
nodes/fragment/24/position = Vector2(60, -40)
nodes/fragment/25/node = SubResource("22")
nodes/fragment/25/position = Vector2(800, -100)
nodes/fragment/26/node = SubResource("23")
nodes/fragment/26/position = Vector2(660, -360)
nodes/fragment/27/node = SubResource("24")
nodes/fragment/27/position = Vector2(1000, -100)
nodes/fragment/28/node = SubResource("25")
nodes/fragment/28/position = Vector2(1200, -100)
nodes/fragment/29/node = SubResource("26")
nodes/fragment/29/position = Vector2(1400, 60)
nodes/fragment/30/node = SubResource("27")
nodes/fragment/30/position = Vector2(1000, -240)
nodes/fragment/connections = PackedInt32Array(2, 0, 0, 0, 3, 0, 4, 0, 4, 0, 5, 0, 5, 0, 6, 0, 6, 0, 7, 0, 8, 0, 7, 1, 7, 0, 9, 0, 12, 0, 0, 1, 9, 0, 13, 0, 13, 0, 10, 0, 14, 0, 10, 1, 11, 0, 15, 0, 15, 0, 13, 1, 5, 0, 17, 0, 17, 0, 18, 0, 17, 0, 19, 0, 19, 0, 20, 0, 18, 0, 24, 0, 24, 0, 23, 1, 22, 0, 25, 0, 20, 2, 22, 0, 24, 0, 22, 3, 23, 0, 22, 4, 24, 0, 22, 5, 25, 0, 27, 0, 26, 0, 27, 1, 27, 0, 28, 0, 28, 0, 29, 0, 10, 0, 29, 1, 29, 0, 12, 1, 14, 0, 30, 0, 30, 0, 28, 1)

View File

@@ -0,0 +1,92 @@
class_name XRToolsMoveTo
extends Node
## XR Tools Move To Node
##
## This node moves a control node to the specified target node at a
## requested speed.
## Signal invoked when the move finishes
signal move_complete
# Spatial to control
var _control: Node3D
# Spatial representing the target
var _target: Node3D
# Starting transform
var _start: Transform3D
# Target offset
var _offset: Transform3D
# Move duration
var _duration: float
# Move time
var _time: float = 0.0
# Add support for is_xr_class on XRTools classes
func is_xr_class(xr_name: String) -> bool:
return xr_name == "XRToolsMoveTo"
## Initialize the XRToolsMoveTo
func _init():
# Disable processing until needed
set_process(false)
## Process the movement
func _process(delta: float) -> void:
# Calculate the destination
var destination := _target.global_transform * _offset
# Update the move time
_time += delta
# Detect end of move
if _time > _duration:
# Disable processing
set_process(false)
# Move to the target
_control.global_transform = destination
# Report the move as complete
emit_signal("move_complete")
return
# Interpolate to the target
_control.global_transform = _start.interpolate_with(
destination,
_time / _duration)
## Start the move
func start(control: Node3D, target: Node3D, offset: Transform3D, speed: float) -> void:
# Save the control and target
_control = control
_target = target
_offset = offset
# Save the starting transform
_start = control.global_transform
# Calculate the duration
var destination := _target.global_transform * _offset
var distance := (destination.origin - _start.origin).length()
_duration = distance / speed
# Start processing
set_process(true)
## Stop the move
func stop() -> void:
set_process(false)

View File

@@ -0,0 +1 @@
uid://dxe230iiqbkwe

View File

@@ -0,0 +1,130 @@
class_name XRToolsVelocityAverager
## XR Tools Velocity Averager class
##
## This class assists in calculating the velocity (both linear and angular)
## of an object. It accepts the following types of input:
## - Periodic distances
## - Periodic transforms (for the origin position)
##
## It provides the average velocity calculated from the total distance
## divided by the total time.
# Count of averages to perform
var _count: int
# Array of time deltas (in float seconds)
var _time_deltas := Array()
# Array of linear distances (Vector3 Castesian Distances)
var _linear_distances := Array()
# Array of angular distances (Vector3 Euler Distances)
var _angular_distances := Array()
# Last transform
var _last_transform := Transform3D()
# Has last transform flag
var _has_last_transform := false
## Initialize the XRToolsVelocityAverager with an averaging count
func _init(count: int):
_count = count
## Clear the averages
func clear():
_time_deltas.clear()
_linear_distances.clear()
_angular_distances.clear()
_has_last_transform = false
## Add linear and angular distances to the averager
func add_distance(delta: float, linear_distance: Vector3, angular_distance: Vector3):
# Sanity check
assert(delta > 0, "Velocity averager requires positive time-deltas")
# Add data averaging arrays
_time_deltas.push_back(delta)
_linear_distances.push_back(linear_distance)
_angular_distances.push_back(angular_distance)
# Keep the number of samples down to the requested count
if _time_deltas.size() > _count:
_time_deltas.pop_front()
_linear_distances.pop_front()
_angular_distances.pop_front()
## Add a transform to the averager
func add_transform(delta: float, transform: Transform3D):
# Handle saving the first transform
if !_has_last_transform:
_last_transform = transform
_has_last_transform = true
return
# Calculate the linear cartesian distance
var linear_distance := transform.origin - _last_transform.origin
# Calculate the euler angular distance
var angular_distance := (transform.basis * _last_transform.basis.inverse()).get_euler()
# Update the last transform
_last_transform = transform
# Add distances
add_distance(delta, linear_distance, angular_distance)
## Calculate the average linear velocity
func linear_velocity() -> Vector3:
# Skip if no averages
if _time_deltas.size() == 0:
return Vector3.ZERO
# Calculate the total time in the average window
var total_time := 0.0
for dt in _time_deltas:
total_time += dt
# Sum the cartesian distances in the average window
var total_linear := Vector3.ZERO
for dd in _linear_distances:
total_linear += dd
# Return the average cartesian-velocity
return total_linear / total_time
## Calculate the average angular velocity as a Vector3 euler-velocity
func angular_velocity() -> Vector3:
# Skip if no averages
if _time_deltas.size() == 0:
return Vector3.ZERO
# Calculate the total time in the average window
var total_time := 0.0
for dt in _time_deltas:
total_time += dt
# At first glance the following operations may look incorrect as they appear
# to involve scaling of euler angles which isn't a valid operation.
#
# They are actually correct due to the value being a euler-velocity rather
# than a euler-angle. The difference is that physics engines process euler
# velocities by converting them to axis-angle form by:
# - Angle-velocity: euler-velocity vector magnitude
# - Axis: euler-velocity normalized and axis evaluated on 1-radian rotation
#
# The result of this interpretation is that scaling the euler-velocity
# by arbitrary amounts only results in the angle-velocity changing without
# impacting the axis of rotation.
# Sum the euler-velocities in the average window
var total_angular := Vector3.ZERO
for dd in _angular_distances:
total_angular += dd
# Calculate the average euler-velocity
return total_angular / total_time

View File

@@ -0,0 +1 @@
uid://7m8n6u54iq2f

View File

@@ -0,0 +1,91 @@
class_name XRToolsVelocityAveragerLinear
## XR Tools Linear Velocity Averager class
##
## This class assists in calculating the average linear velocity of an
## object. It accepts the following types of input:
## - Periodic distances
## - Periodic velocities
## - Periodic transforms (for the origin position)
##
## It provides the average velocity calculated from the total distance
## divided by the total time.
# Count of averages to perform
var _count: int
# Array of time deltas (in float seconds)
var _time_deltas := Array()
# Array of linear distances (in Vector3)
var _linear_distances := Array()
# Last transform
var _last_transform := Transform3D()
# Has last transform flag
var _has_last_transform := false
## Initialize the VelocityAverager with an averaging count
func _init(count: int):
_count = count
## Clear the averages
func clear():
_time_deltas.clear()
_linear_distances.clear()
_has_last_transform = false
## Add a linear distance to the averager
func add_distance(delta: float, linear_distance: Vector3):
# Add data averaging arrays
_time_deltas.push_back(delta)
_linear_distances.push_back(linear_distance)
# Keep the number of samples down to the requested count
if _time_deltas.size() > _count:
_time_deltas.pop_front()
_linear_distances.pop_front()
## Add a linear velocity to the averager
func add_velocity(delta: float, linear_velocity: Vector3):
add_distance(delta, linear_velocity * delta)
## Add a transform to the averager
func add_transform(delta: float, transform: Transform3D):
# Handle saving the first transform
if !_has_last_transform:
_last_transform = transform
_has_last_transform = true
return
# Calculate the linear distances
var linear_distance := transform.origin - _last_transform.origin
# Update the last transform
_last_transform = transform
# Add distance
add_distance(delta, linear_distance)
## Calculate the average linear velocity
func velocity() -> Vector3:
# Calculate the total time
var total_time := 0.0
for dt in _time_deltas:
total_time += dt
# Safety check to prevent division by zero
if total_time <= 0.0:
return Vector3.ZERO
# Calculate the total distance
var total_linear := Vector3.ZERO
for dd in _linear_distances:
total_linear += dd
# Return the average
return total_linear / total_time

View File

@@ -0,0 +1 @@
uid://cv4gbwersefaf

View File

@@ -0,0 +1,14 @@
extends Node3D
signal cooldown_finished
var countdown = 2
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
countdown = countdown - 1
if countdown == 0:
visible = false
set_process(false)
emit_signal("cooldown_finished")

View File

@@ -0,0 +1 @@
uid://cd5c70rxux4kg

View File

@@ -0,0 +1,39 @@
[gd_scene load_steps=8 format=3 uid="uid://btknduttnmoxf"]
[ext_resource type="Script" uid="uid://cd5c70rxux4kg" path="res://addons/godot-xr-tools/misc/vr_common_shader_cache.gd" id="1"]
[ext_resource type="Material" uid="uid://bk72wfw25ff0v" path="res://addons/godot-xr-tools/materials/teleport.tres" id="2_6822k"]
[ext_resource type="Material" path="res://addons/godot-xr-tools/materials/target.tres" id="3_agvdv"]
[ext_resource type="Material" path="res://addons/godot-xr-tools/materials/capsule.tres" id="4_gxjsg"]
[ext_resource type="Material" path="res://addons/godot-xr-tools/materials/pointer.tres" id="5_12251"]
[ext_resource type="Material" uid="uid://dyuaw57o8y3i" path="res://addons/godot-xr-tools/materials/highlight.tres" id="6_ld6la"]
[sub_resource type="PlaneMesh" id="1"]
size = Vector2(0.001, 0.001)
[node name="VRCommonShaderCache" type="Node3D"]
script = ExtResource("1")
[node name="teleport" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -2)
mesh = SubResource("1")
surface_material_override/0 = ExtResource("2_6822k")
[node name="target" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -2)
mesh = SubResource("1")
surface_material_override/0 = ExtResource("3_agvdv")
[node name="capsule" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -2)
mesh = SubResource("1")
surface_material_override/0 = ExtResource("4_gxjsg")
[node name="pointer" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -2)
mesh = SubResource("1")
surface_material_override/0 = ExtResource("5_12251")
[node name="highlight" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -2)
mesh = SubResource("1")
surface_material_override/0 = ExtResource("6_ld6la")

View File

@@ -0,0 +1,136 @@
@tool
class_name XRHelpers
## XR Tools Helper Rountines
##
## This script contains static functions to help find XR player nodes.
##
## As these functions are static, the caller must pass in a node located
## somewhere under the players [XROrigin3D].
## Find the [XROrigin3D] node.
##
## This function searches for the [XROrigin3D] from the provided node.
## The caller may provide an optional path (relative to the node) to the
## [XROrigin3D] to support out-of-tree searches.
##
## The search is performed assuming the node is under the [XROrigin3D].
static func get_xr_origin(node: Node, path: NodePath = NodePath()) -> XROrigin3D:
var origin: XROrigin3D
# Try using the node path first
if path:
origin = node.get_node(path) as XROrigin3D
if origin:
return origin
# Walk up the tree from the provided node looking for the origin
origin = XRTools.find_xr_ancestor(node, "*", "XROrigin3D")
if origin:
return origin
# We check our children but only one level
origin = XRTools.find_xr_child(node, "*", "XROrigin3D", false)
if origin:
return origin
# Could not find origin
return null
## Find the [XRCamera3D] node.
##
## This function searches for the [XRCamera3D] from the provided node.
## The caller may provide an optional path (relative to the node) to the
## [XRCamera3D] to support out-of-tree searches.
##
## The search is performed assuming the node is under the [XROrigin3D].
static func get_xr_camera(node: Node, path: NodePath = NodePath()) -> XRCamera3D:
var camera: XRCamera3D
# Try using the node path first
if path:
camera = node.get_node(path) as XRCamera3D
if camera:
return camera
# Get the origin
var origin := get_xr_origin(node)
if !origin:
return null
# Attempt to get by the default name
camera = origin.get_node_or_null("Camera") as XRCamera3D
if camera:
return camera
# Search all children of the origin for the camera
camera = XRTools.find_xr_child(origin, "*", "XRCamera3D", false)
if camera:
return camera
# Could not find camera
return null
## Find the [XRController3D] node.
##
## This function searches for the [XRController3D] from the provided node.
## The caller may provide an optional path (relative to the node) to the
## [XRController3D] to support out-of-tree searches.
##
## The search is performed assuming the node is under the [XRController3D].
static func get_xr_controller(node: Node, path: NodePath = NodePath()) -> XRController3D:
var controller: XRController3D
# Try using the node path first
if path:
controller = node.get_node(path) as XRController3D
if controller:
return controller
# Search up from the node for the controller
return XRTools.find_xr_ancestor(node, "*", "XRController3D") as XRController3D
## Find the Left Hand [XRController3D] from a player node and an optional path
static func get_left_controller(node: Node, path: NodePath = NodePath()) -> XRController3D:
return _get_controller(node, "LeftHandController", "left_hand", path)
## Find the Right Hand [XRController3D] from a player node and an optional path
static func get_right_controller(node: Node, path: NodePath = NodePath()) -> XRController3D:
return _get_controller(node, "RightHandController", "right_hand", path)
## Find an [XRController3D] given some search parameters
static func _get_controller(
node: Node,
default_name: String,
tracker: String,
path: NodePath) -> XRController3D:
var controller: XRController3D
# Try using the node path first
if path:
controller = node.get_node(path) as XRController3D
if controller:
return controller
# Get the origin
var origin := get_xr_origin(node)
if !origin:
return null
# Attempt to get by the default name
controller = origin.get_node_or_null(default_name) as XRController3D
if controller:
return controller
# Search all children of the origin for the controller
for child in origin.get_children():
controller = child as XRController3D
if controller and controller.tracker == tracker:
return controller
# Could not find the controller
return null

View File

@@ -0,0 +1 @@
uid://cprfiap0fogt0