diff --git a/VERSIONS.md b/VERSIONS.md index 8f594d7f..f80b4cc3 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -12,7 +12,9 @@ - Added "UI Objects" layer 23 for viewports to support interaction by pointer and poking - Fixed player scaling issues with crouching and poke - **minor-breakage** Added support for passing user data between staged scenes with default handling for spawn-points - +- Change pointer event dispatching +- Added multi-touch on 2D in 3D viewports and virtual-keyboard +- Added option to disable laser-pointers when close to specific bodies/areas # 4.1.0 - Enhanced grappling to support collision and target layers diff --git a/addons/godot-xr-tools/events/pointer_event.gd b/addons/godot-xr-tools/events/pointer_event.gd new file mode 100644 index 00000000..09410002 --- /dev/null +++ b/addons/godot-xr-tools/events/pointer_event.gd @@ -0,0 +1,134 @@ +class_name XRToolsPointerEvent + +## Types of pointer events +enum Type { + ## Pointer entered target + ENTERED, + + ## Pointer exited target + EXITED, + + ## Pointer pressed target + PRESSED, + + ## Pointer released target + RELEASED, + + ## Pointer moved on target + MOVED +} + +## Type of pointer event +var event_type : Type + +## Pointer generating event +var pointer : Node3D + +## Target of pointer +var target : Node3D + +## Point position +var position : Vector3 + +## Last point position +var last_position : Vector3 + + +## Initialize a new instance of the XRToolsPointerEvent class +func _init( + p_event_type : Type, + p_pointer : Node3D, + p_target : Node3D, + p_position : Vector3, + p_last_position : Vector3) -> void: + event_type = p_event_type + pointer = p_pointer + target = p_target + position = p_position + last_position = p_last_position + + +## Report a pointer entered event +static func entered( + pointer : Node3D, + target : Node3D, + at : Vector3) -> void: + report( + XRToolsPointerEvent.new( + Type.ENTERED, + pointer, + target, + at, + at)) + + +## Report pointer moved event +static func moved( + pointer : Node3D, + target : Node3D, + to : Vector3, + from : Vector3) -> void: + report( + XRToolsPointerEvent.new( + Type.MOVED, + pointer, + target, + to, + from)) + + +## Report pointer pressed event +static func pressed( + pointer : Node3D, + target : Node3D, + at : Vector3) -> void: + report( + XRToolsPointerEvent.new( + Type.PRESSED, + pointer, + target, + at, + at)) + + +## Report pointer released event +static func released( + pointer : Node3D, + target : Node3D, + at : Vector3) -> void: + report( + XRToolsPointerEvent.new( + Type.RELEASED, + pointer, + target, + at, + at)) + + +## Report a pointer exited event +static func exited( + pointer : Node3D, + target : Node3D, + last : Vector3) -> void: + report( + XRToolsPointerEvent.new( + Type.EXITED, + pointer, + target, + last, + last)) + + +## Report a pointer event +static func report(event : XRToolsPointerEvent) -> void: + # Fire event on pointer + if is_instance_valid(event.pointer): + if event.pointer.has_signal("pointing_event"): + event.pointer.emit_signal("pointing_event", event) + + # Fire event/method on the target if it's valid + if is_instance_valid(event.target): + if event.target.has_signal("pointer_event"): + event.target.emit_signal("pointer_event", event) + elif event.target.has_method("pointer_event"): + event.target.pointer_event(event) diff --git a/addons/godot-xr-tools/functions/function_pointer.gd b/addons/godot-xr-tools/functions/function_pointer.gd index be58d25a..536eb097 100644 --- a/addons/godot-xr-tools/functions/function_pointer.gd +++ b/addons/godot-xr-tools/functions/function_pointer.gd @@ -14,20 +14,8 @@ extends Node3D ## [XRToolsInteractableBody]. -## Signal emitted when the pointer enters the target -signal pointer_entered(target) - -## Signal emitted when the pointer moves on the target -signal pointer_moved(target, from, to) - -## Signal emitted when the pointer is pressed on the target -signal pointer_pressed(target, at) - -## Signal emitted when the pointer is released on the target -signal pointer_released(target, at) - -## Signal emitted when the pointer exits the target collision object -signal pointer_exited(target) +## Signal emitted when this object points at another object +signal pointing_event(event) ## Enumeration of laser show modes @@ -47,6 +35,9 @@ enum LaserLength { ## Default pointer collision mask of 21:pointable and 23:ui-objects const DEFAULT_MASK := 0b0000_0000_0101_0000_0000_0000_0000_0000 +## Default pointer collision mask of 23:ui-objects +const SUPPRESS_MASK := 0b0000_0000_0100_0000_0000_0000_0000_0000 + @export_group("General") @@ -54,7 +45,7 @@ const DEFAULT_MASK := 0b0000_0000_0101_0000_0000_0000_0000_0000 @export var enabled : bool = true: set = set_enabled ## Y Offset for pointer -@export var y_offset : float = -0.05: set = set_y_offset +@export var y_offset : float = -0.013: set = set_y_offset ## Pointer distance @export var distance : float = 10: set = set_distance @@ -98,6 +89,14 @@ const DEFAULT_MASK := 0b0000_0000_0101_0000_0000_0000_0000_0000 ## Enable pointer collision with areas @export var collide_with_areas : bool = false: set = set_collide_with_areas +@export_group("Suppression") + +## Suppress radius +@export var suppress_radius : float = 0.2: set = set_suppress_radius + +## Suppress mask +@export_flags_3d_physics var suppress_mask : int = SUPPRESS_MASK: set = set_suppress_mask + ## Current target node var target : Node3D = null @@ -174,6 +173,8 @@ func _ready(): _update_collision_mask() _update_collide_with_bodies() _update_collide_with_areas() + _update_suppress_radius() + _update_suppress_mask() # Called on each frame to update the pickup @@ -195,7 +196,11 @@ func _process(_delta): # Find the new pointer target var new_target : Node3D var new_at : Vector3 - if enabled and $RayCast.is_colliding(): + var suppress_area := $SuppressArea + if (enabled and + not $SuppressArea.has_overlapping_bodies() and + not $SuppressArea.has_overlapping_areas() and + $RayCast.is_colliding()): new_at = $RayCast.get_collision_point() if target: # Locked to 'target' even if we're colliding with something else @@ -211,34 +216,34 @@ func _process(_delta): # Handle pointer changes if new_target and not last_target: # Pointer entered new_target - _report_entered(new_target) + XRToolsPointerEvent.entered(self, new_target, new_at) - # Pointer moved on new_target - _report_moved(new_target, new_at, new_at) + # Pointer moved on new_target for the first time + XRToolsPointerEvent.moved(self, new_target, new_at, new_at) # Update visible artifacts for hit _visible_hit(new_at) elif not new_target and last_target: # Pointer exited last_target - _report_exited(last_target) + XRToolsPointerEvent.exited(self, last_target, last_collided_at) # Update visible artifacts for miss _visible_miss() elif new_target != last_target: # Pointer exited last_target - _report_exited(last_target) + XRToolsPointerEvent.exited(self, last_target, last_collided_at) # Pointer entered new_target - _report_entered(new_target) + XRToolsPointerEvent.entered(self, new_target, new_at) # Pointer moved on new_target - _report_moved(new_target, last_collided_at, new_at) + XRToolsPointerEvent.moved(self, new_target, new_at, new_at) # Move visible artifacts _visible_move(new_at) elif new_at != last_collided_at: # Pointer moved on new_target - _report_moved(new_target, last_collided_at, new_at) + XRToolsPointerEvent.moved(self, new_target, new_at, last_collided_at) # Move visible artifacts _visible_move(new_at) @@ -339,6 +344,19 @@ func set_collide_with_areas(p_new_value : bool) -> void: _update_collide_with_areas() +# Set suppress radius property +func set_suppress_radius(p_suppress_radius : float) -> void: + suppress_radius = p_suppress_radius + if is_inside_tree(): + _update_suppress_radius() + + +func set_suppress_mask(p_suppress_mask : int) -> void: + suppress_mask = p_suppress_mask + if is_inside_tree(): + _update_suppress_mask() + + # Pointer Y offset update handler func _update_y_offset() -> void: $Laser.position.y = y_offset * _world_scale @@ -377,6 +395,16 @@ func _update_collide_with_areas() -> void: $RayCast.collide_with_areas = collide_with_areas +# Pointer suppress_radius update handler +func _update_suppress_radius() -> void: + $SuppressArea/CollisionShape3D.shape.radius = suppress_radius + + +# Pointer suppress_mask update handler +func _update_suppress_mask() -> void: + $SuppressArea.collision_mask = suppress_mask + + # Pointer visible artifacts update handler func _update_pointer() -> void: if enabled and last_target: @@ -391,14 +419,14 @@ func _button_pressed() -> void: # Report pressed target = $RayCast.get_collider() last_collided_at = $RayCast.get_collision_point() - _report_pressed(target, last_collided_at) + XRToolsPointerEvent.pressed(self, target, last_collided_at) # Pointer-activation button released handler func _button_released() -> void: if target: # Report release - _report_released(target, last_collided_at) + XRToolsPointerEvent.released(self, target, last_collided_at) target = null last_collided_at = Vector3(0, 0, 0) @@ -426,71 +454,6 @@ func _update_laser_active_material(hit : bool) -> void: $Laser.set_surface_override_material(0, laser_material) -# Report events for pointer entering collision object -func _report_entered(node : Node3D) -> void: - # Fire entered event - pointer_entered.emit(node) - - # Fire event/method on the node if it's valid - if is_instance_valid(node): - if node.has_signal("pointer_entered"): - node.emit_signal("pointer_entered") - elif node.has_method("pointer_entered"): - node.pointer_entered() - - -# Report events for pointer moved on node -func _report_moved(node : Node3D, from : Vector3, to : Vector3) -> void: - # Fire moved event - pointer_moved.emit(node, from, to) - - # Fire event/method on the node if it's valid - if is_instance_valid(node): - if node.has_signal("pointer_moved"): - node.emit_signal("pointer_moved", from, to) - elif node.has_method("pointer_moved"): - node.pointer_moved(from, to) - - -# Report events for pointer pressed on 'node' -func _report_pressed(node : Node3D, at : Vector3) -> void: - # Fire pressed event - pointer_pressed.emit(node, at) - - # Fire event/method on the node if it's valid - if is_instance_valid(node): - if node.has_signal("pointer_pressed"): - node.emit_signal("pointer_pressed", at) - elif node.has_method("pointer_pressed"): - node.pointer_pressed(at) - - -# Report events for pointer released on 'node' -func _report_released(node : Node3D, at : Vector3) -> void: - # Fire released event - pointer_released.emit(node, at) - - # Fire event/method on the node if it's valid - if is_instance_valid(node): - if node.has_signal("pointer_released"): - node.emit_signal("pointer_released", at) - elif node.has_method("pointer_released"): - node.pointer_released(at) - - -# Report events for pointer exiting node -func _report_exited(node : Node3D) -> void: - # Fire exited event - pointer_exited.emit(node) - - # Fire event/method on the node if it's valid - if is_instance_valid(node): - if node.has_signal("pointer_exited"): - node.emit_signal("pointer_exited") - elif node.has_method("pointer_exited"): - node.pointer_exited() - - # Update the visible artifacts to show a hit func _visible_hit(at : Vector3) -> void: # Show target if enabled diff --git a/addons/godot-xr-tools/functions/function_pointer.tscn b/addons/godot-xr-tools/functions/function_pointer.tscn index fbc3fde4..969da9b6 100644 --- a/addons/godot-xr-tools/functions/function_pointer.tscn +++ b/addons/godot-xr-tools/functions/function_pointer.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=5 format=3 uid="uid://cqhw276realc"] +[gd_scene load_steps=6 format=3 uid="uid://cqhw276realc"] [ext_resource type="Material" path="res://addons/godot-xr-tools/materials/pointer.tres" id="1"] [ext_resource type="Script" path="res://addons/godot-xr-tools/functions/function_pointer.gd" id="2"] @@ -16,19 +16,29 @@ height = 0.1 radial_segments = 16 rings = 8 +[sub_resource type="SphereShape3D" id="SphereShape3D_k3gfm"] +radius = 0.2 + [node name="FunctionPointer" type="Node3D"] script = ExtResource("2") [node name="RayCast" type="RayCast3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.013, 0) target_position = Vector3(0, 0, -10) collision_mask = 5242880 [node name="Laser" type="MeshInstance3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, -5) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.013, -5) cast_shadow = 0 mesh = SubResource("1") [node name="Target" type="MeshInstance3D" parent="."] visible = false mesh = SubResource("2") + +[node name="SuppressArea" type="Area3D" parent="."] +collision_layer = 0 +collision_mask = 4194304 + +[node name="CollisionShape3D" type="CollisionShape3D" parent="SuppressArea"] +shape = SubResource("SphereShape3D_k3gfm") diff --git a/addons/godot-xr-tools/objects/interactable_area.gd b/addons/godot-xr-tools/objects/interactable_area.gd index f31c171f..167cf228 100644 --- a/addons/godot-xr-tools/objects/interactable_area.gd +++ b/addons/godot-xr-tools/objects/interactable_area.gd @@ -3,11 +3,8 @@ class_name XRToolsInteractableArea extends Area3D -signal pointer_pressed(at) -signal pointer_released(at) -signal pointer_moved(from, to) -signal pointer_entered() -signal pointer_exited() +## Signal when pointer event occurs on area +signal pointer_event(event) # Add support for is_xr_class on XRTools classes diff --git a/addons/godot-xr-tools/objects/interactable_body.gd b/addons/godot-xr-tools/objects/interactable_body.gd index 21e211d6..1202bf7f 100644 --- a/addons/godot-xr-tools/objects/interactable_body.gd +++ b/addons/godot-xr-tools/objects/interactable_body.gd @@ -3,8 +3,5 @@ extends Node3D # This should extend from PhysicsBody3D but https://github.com/godotengine/godot/issues/46073 -signal pointer_pressed(at) -signal pointer_released(at) -signal pointer_moved(from, to) -signal pointer_entered() -signal pointer_exited() +## Signal when pointer event occurs on body +signal pointer_event(event) diff --git a/addons/godot-xr-tools/objects/keyboard/virtual_key.gd b/addons/godot-xr-tools/objects/keyboard/virtual_key.gd index 70793ddc..70c5bd84 100644 --- a/addons/godot-xr-tools/objects/keyboard/virtual_key.gd +++ b/addons/godot-xr-tools/objects/keyboard/virtual_key.gd @@ -1,33 +1,150 @@ -extends Button +@tool +class_name XRToolsVirtualKey +extends Node2D -## Godot scan-code text -@export var scan_code_text := "" +## Key pressed event +signal pressed -## Unicode character -@export var unicode := 0 +## Key released event +signal released -## Shift modifier -@export var shift_modifier := false +## Key location +@export var key_size := Vector2(32, 32) : set = _set_key_size +## Key text +@export var key_text := "" : set = _set_key_text + +## Key normal color +@export var key_normal := Color(0.1, 0.1, 0.1) : set = _set_key_normal + +## Key highlight color +@export var key_highlight := Color(0.2, 0.2, 0.2) : set = _set_key_highlight + +## Text normal color +@export var text_normal := Color(1.0, 1.0, 1.0) : set = _set_text_normal + +## Text highlight color +@export var text_highlight := Color(0.0, 0.0, 0.0) : set = _set_text_highlight + +## Key highlighted +@export var highlighted := false : set = _set_highlighted + + +# TouchScreenButton node +var _button : TouchScreenButton + +# ColorRect node +var _color : ColorRect + +# Label node +var _label : Label + + +# Called when the node enters the scene tree for the first time. func _ready(): - # Find the VirtualKeyboard parent - var keyboard = _get_virtual_keyboard() - if keyboard: - button_down.connect(keyboard.on_key_pressed.bind(scan_code_text, unicode, shift_modifier)) - -# Get our virtual keyboard parent -func _get_virtual_keyboard() -> XRToolsVirtualKeyboard2D: - # Get parent node and start walking up the tree - var node = get_parent() - while node: - # Check if the node is the keyboard - if node is XRToolsVirtualKeyboard2D: - return node - - # Step up the tree - node = node.get_parent() - - # No virtual keyboard found - return null + # Construct the ColorRect node + _color = ColorRect.new() + + # Construct the Label node + _label = Label.new() + _label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + _label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + + # Construct the TouchScreenButton node + _button = TouchScreenButton.new() + _button.shape = RectangleShape2D.new() + + # Attach the nodes + _color.add_child(_label) + _button.add_child(_color) + add_child(_button) + + # Handle button presses + _button.pressed.connect(_on_button_pressed) + _button.released.connect(_on_button_released) + + # Apply initial updates + _update_key_size() + _update_key_text() + _update_highlighted() + + +func _on_button_pressed() -> void: + pressed.emit() + + +func _on_button_released() -> void: + released.emit() + + +func _set_key_size(p_key_size : Vector2) -> void: + key_size = p_key_size + if is_inside_tree(): + _update_key_size() + + +func _set_key_text(p_key_text : String) -> void: + key_text = p_key_text + if is_inside_tree(): + _update_key_text() + + +func _set_key_normal(p_key_normal : Color) -> void: + key_normal = p_key_normal + if is_inside_tree(): + _update_highlighted() + + +func _set_key_highlight(p_key_highlight : Color) -> void: + key_highlight = p_key_highlight + if is_inside_tree(): + _update_highlighted() + + +func _set_text_normal(p_text_normal : Color) -> void: + text_normal = p_text_normal + if is_inside_tree(): + _update_highlighted() + + +func _set_text_highlight(p_text_highlight : Color) -> void: + text_highlight = p_text_highlight + if is_inside_tree(): + _update_highlighted() + + +func _set_highlighted(p_highlighted : bool) -> void: + highlighted = p_highlighted + if is_inside_tree(): + _update_highlighted() + + +func _update_key_size() -> void: + var half_size := key_size / 2 + + # Set the TouchScreenButton position and shape size + _button.position = half_size + _button.shape.size = key_size + + # Size and position the ColorRect + _color.size = key_size + _color.position = -half_size + + # Size the label + _label.size = key_size + + +func _update_key_text() -> void: + _label.text = key_text + + +func _update_highlighted() -> void: + # Pick colors + var key := key_highlight if highlighted else key_normal + var text := text_highlight if highlighted else text_normal + + # Set colors + _color.color = key + _label.add_theme_color_override("font_color", text) diff --git a/addons/godot-xr-tools/objects/keyboard/virtual_key.tscn b/addons/godot-xr-tools/objects/keyboard/virtual_key.tscn deleted file mode 100644 index b182fcbc..00000000 --- a/addons/godot-xr-tools/objects/keyboard/virtual_key.tscn +++ /dev/null @@ -1,10 +0,0 @@ -[gd_scene load_steps=2 format=2] - -[ext_resource path="res://addons/godot-xr-tools/objects/keyboard/virtual_key.gd" type="Script" id=1] - -[node name="VirtualKey" type="Button"] -offset_right = 30.0 -offset_bottom = 25.0 -focus_mode = 0 -focus_mode = 0 -script = ExtResource( 1 ) diff --git a/addons/godot-xr-tools/objects/keyboard/virtual_key_char.gd b/addons/godot-xr-tools/objects/keyboard/virtual_key_char.gd new file mode 100644 index 00000000..38ec255c --- /dev/null +++ b/addons/godot-xr-tools/objects/keyboard/virtual_key_char.gd @@ -0,0 +1,45 @@ +@tool +class_name XRToolsVirtualKeyChar +extends XRToolsVirtualKey + + +## Godot scan-code text +@export var scan_code_text := "" + +## Unicode character +@export var unicode := 0 + +## Shift modifier +@export var shift_modifier := false + + +# Keyboard associated with this button +var _keyboard : XRToolsVirtualKeyboard2D + + +# Called when the node enters the scene tree for the first time. +func _ready(): + # Call the base + super() + + # Find the keyboard + _keyboard = XRTools.find_xr_ancestor( + self, + "*", + "XRToolsVirtualKeyboard2D") + + # Handle button presses + pressed.connect(_on_pressed) + released.connect(_on_released) + + +# Handler for button pressed +func _on_pressed() -> void: + highlighted = true + if _keyboard: + _keyboard.on_key_pressed(scan_code_text, unicode, shift_modifier) + + +# Handler for button released +func _on_released() -> void: + highlighted = false diff --git a/addons/godot-xr-tools/objects/keyboard/virtual_keyboard_2d.gd b/addons/godot-xr-tools/objects/keyboard/virtual_keyboard_2d.gd index b8af1803..a1d22fd5 100644 --- a/addons/godot-xr-tools/objects/keyboard/virtual_keyboard_2d.gd +++ b/addons/godot-xr-tools/objects/keyboard/virtual_keyboard_2d.gd @@ -47,40 +47,41 @@ func on_key_pressed(scan_code_text: String, unicode: int, shift: bool): # Pop any temporary shift key if _shift_down: - $Background/Standard/ToggleShift.set_pressed_no_signal(false) _shift_down = false _update_visible() -func on_shift_toggle(button_pressed): + +func _on_toggle_shift_pressed() -> void: # Update toggle keys - $Background/Standard/ToggleCaps.set_pressed_no_signal(false) - $Background/Standard/ToggleAlt.set_pressed_no_signal(false) - _shift_down = button_pressed + _shift_down = not _shift_down _caps_down = false _alt_down = false _update_visible() -# Handle caps-lock toggle -func on_caps_toggle(button_pressed): + +func _on_toggle_caps_pressed() -> void: # Update toggle keys - $Background/Standard/ToggleShift.set_pressed_no_signal(false) - $Background/Standard/ToggleAlt.set_pressed_no_signal(false) + _caps_down = not _caps_down _shift_down = false - _caps_down = button_pressed _alt_down = false _update_visible() -func on_alt_toggle(button_pressed): + +func _on_toggle_alt_pressed() -> void: # Update toggle keys - $Background/Standard/ToggleShift.set_pressed_no_signal(false) - $Background/Standard/ToggleCaps.set_pressed_no_signal(false) + _alt_down = not _alt_down _shift_down = false _caps_down = false - _alt_down = button_pressed _update_visible() + # Update switching the visible case keys -func _update_visible(): +func _update_visible() -> void: + # Ensure the control buttons are set correctly + $Background/Standard/ToggleShift.highlighted = _shift_down + $Background/Standard/ToggleCaps.highlighted = _caps_down + $Background/Standard/ToggleAlt.highlighted = _alt_down + # Evaluate the new mode var new_mode: int if _alt_down: diff --git a/addons/godot-xr-tools/objects/keyboard/virtual_keyboard_2d.tscn b/addons/godot-xr-tools/objects/keyboard/virtual_keyboard_2d.tscn index 53f85748..5e478ba4 100644 --- a/addons/godot-xr-tools/objects/keyboard/virtual_keyboard_2d.tscn +++ b/addons/godot-xr-tools/objects/keyboard/virtual_keyboard_2d.tscn @@ -1,841 +1,724 @@ -[gd_scene load_steps=3 format=3 uid="uid://lauwp8okd1vh"] +[gd_scene load_steps=4 format=3 uid="uid://lauwp8okd1vh"] [ext_resource type="Script" path="res://addons/godot-xr-tools/objects/keyboard/virtual_keyboard_2d.gd" id="1"] -[ext_resource type="PackedScene" path="res://addons/godot-xr-tools/objects/keyboard/virtual_key.tscn" id="2"] +[ext_resource type="Script" path="res://addons/godot-xr-tools/objects/keyboard/virtual_key_char.gd" id="2_n0nlg"] +[ext_resource type="Script" path="res://addons/godot-xr-tools/objects/keyboard/virtual_key.gd" id="3_h05ve"] [node name="VirtualKeyboard2D" type="CanvasLayer"] script = ExtResource("1") [node name="Background" type="ColorRect" parent="."] -offset_right = 390.0 -offset_bottom = 145.0 +offset_right = 400.0 +offset_bottom = 200.0 color = Color(0.12549, 0.12549, 0.12549, 0.752941) [node name="Standard" type="Control" parent="Background"] layout_mode = 1 anchors_preset = 0 -offset_right = 390.0 -offset_bottom = 145.0 +offset_left = 4.0 +offset_top = 4.0 +offset_right = 394.0 +offset_bottom = 149.0 -[node name="VirtualKey1" parent="Background/Standard" instance=ExtResource("2")] -layout_mode = 0 -text = "1" +[node name="VirtualKey1" type="Node2D" parent="Background/Standard"] +script = ExtResource("2_n0nlg") scan_code_text = "1" unicode = 49 +key_text = "1" -[node name="VirtualKey2" parent="Background/Standard" instance=ExtResource("2")] -layout_mode = 0 -offset_left = 40.0 -offset_right = 70.0 -text = "2" +[node name="VirtualKey2" type="Node2D" parent="Background/Standard"] +position = Vector2(40, 0) +script = ExtResource("2_n0nlg") scan_code_text = "2" unicode = 50 +key_text = "2" -[node name="VirtualKey3" parent="Background/Standard" instance=ExtResource("2")] -layout_mode = 0 -offset_left = 80.0 -offset_right = 110.0 -text = "3" +[node name="VirtualKey3" type="Node2D" parent="Background/Standard"] +position = Vector2(80, 0) +script = ExtResource("2_n0nlg") scan_code_text = "3" unicode = 51 +key_text = "3" -[node name="VirtualKey4" parent="Background/Standard" instance=ExtResource("2")] -layout_mode = 0 -offset_left = 120.0 -offset_right = 150.0 -text = "4" +[node name="VirtualKey4" type="Node2D" parent="Background/Standard"] +position = Vector2(120, 0) +script = ExtResource("2_n0nlg") scan_code_text = "4" unicode = 52 +key_text = "4" -[node name="VirtualKey5" parent="Background/Standard" instance=ExtResource("2")] -layout_mode = 0 -offset_left = 160.0 -offset_right = 190.0 -text = "5" +[node name="VirtualKey5" type="Node2D" parent="Background/Standard"] +position = Vector2(160, 0) +script = ExtResource("2_n0nlg") scan_code_text = "5" unicode = 53 +key_text = "5" -[node name="VirtualKey6" parent="Background/Standard" instance=ExtResource("2")] -layout_mode = 0 -offset_left = 200.0 -offset_right = 230.0 -text = "6" +[node name="VirtualKey6" type="Node2D" parent="Background/Standard"] +position = Vector2(200, 0) +script = ExtResource("2_n0nlg") scan_code_text = "6" unicode = 54 +key_text = "6" -[node name="VirtualKey7" parent="Background/Standard" instance=ExtResource("2")] -layout_mode = 0 -offset_left = 240.0 -offset_right = 270.0 -text = "7" +[node name="VirtualKey7" type="Node2D" parent="Background/Standard"] +position = Vector2(240, 0) +script = ExtResource("2_n0nlg") scan_code_text = "7" unicode = 55 +key_text = "7" -[node name="VirtualKey8" parent="Background/Standard" instance=ExtResource("2")] -layout_mode = 0 -offset_left = 280.0 -offset_right = 310.0 -text = "8" +[node name="VirtualKey8" type="Node2D" parent="Background/Standard"] +position = Vector2(280, 0) +script = ExtResource("2_n0nlg") scan_code_text = "8" unicode = 56 +key_text = "8" -[node name="VirtualKey9" parent="Background/Standard" instance=ExtResource("2")] -layout_mode = 0 -offset_left = 320.0 -offset_right = 350.0 -text = "9" +[node name="VirtualKey9" type="Node2D" parent="Background/Standard"] +position = Vector2(320, 0) +script = ExtResource("2_n0nlg") scan_code_text = "9" unicode = 57 +key_text = "9" -[node name="VirtualKey0" parent="Background/Standard" instance=ExtResource("2")] -layout_mode = 0 -offset_left = 360.0 -offset_right = 390.0 -text = "0" +[node name="VirtualKey0" type="Node2D" parent="Background/Standard"] +position = Vector2(360, 0) +script = ExtResource("2_n0nlg") scan_code_text = "0" unicode = 48 - -[node name="ToggleShift" type="Button" parent="Background/Standard"] -layout_mode = 0 -offset_top = 90.0 -offset_right = 50.0 -offset_bottom = 115.0 -focus_mode = 0 -toggle_mode = true -text = "SHIFT" - -[node name="ToggleCaps" type="Button" parent="Background/Standard"] -layout_mode = 0 -offset_top = 120.0 -offset_right = 45.0 -offset_bottom = 145.0 -focus_mode = 0 -toggle_mode = true -text = "CAPS" - -[node name="ToggleAlt" type="Button" parent="Background/Standard"] -layout_mode = 0 -offset_left = 55.0 -offset_top = 120.0 -offset_right = 90.0 -offset_bottom = 145.0 -focus_mode = 0 -toggle_mode = true -text = "ALT" - -[node name="VirtualKeyBackspace" parent="Background/Standard" instance=ExtResource("2")] -layout_mode = 0 -offset_left = 340.0 -offset_top = 90.0 -offset_right = 390.0 -offset_bottom = 115.0 -text = "BKSP" +key_text = "0" + +[node name="ToggleShift" type="Node2D" parent="Background/Standard"] +position = Vector2(0, 120) +script = ExtResource("3_h05ve") +key_size = Vector2(50, 32) +key_text = "SHIFT" +key_highlight = Color(1, 1, 1, 1) + +[node name="ToggleCaps" type="Node2D" parent="Background/Standard"] +position = Vector2(0, 160) +script = ExtResource("3_h05ve") +key_size = Vector2(45, 32) +key_text = "CAPS" +key_highlight = Color(1, 1, 1, 1) + +[node name="ToggleAlt" type="Node2D" parent="Background/Standard"] +position = Vector2(55, 160) +script = ExtResource("3_h05ve") +key_size = Vector2(35, 32) +key_text = "ALT" +key_highlight = Color(1, 1, 1, 1) + +[node name="VirtualKeyBackspace" type="Node2D" parent="Background/Standard"] +position = Vector2(340, 120) +script = ExtResource("2_n0nlg") scan_code_text = "BackSpace" +key_size = Vector2(52, 32) +key_text = "BKSP" -[node name="VirtualKeySpace" parent="Background/Standard" instance=ExtResource("2")] -layout_mode = 0 -offset_left = 100.0 -offset_top = 120.0 -offset_right = 290.0 -offset_bottom = 145.0 -text = "Space" +[node name="VirtualKeySpace" type="Node2D" parent="Background/Standard"] +position = Vector2(100, 160) +script = ExtResource("2_n0nlg") scan_code_text = "Space" unicode = 32 +key_size = Vector2(190, 32) +key_text = "Space" -[node name="VirtualKeyPeriod" parent="Background/Standard" instance=ExtResource("2")] -layout_mode = 0 -offset_left = 300.0 -offset_top = 120.0 -offset_right = 330.0 -offset_bottom = 145.0 -text = "." +[node name="VirtualKeyPeriod" type="Node2D" parent="Background/Standard"] +position = Vector2(300, 160) +script = ExtResource("2_n0nlg") scan_code_text = "Period" unicode = 46 +key_text = "." -[node name="VirtualKeyEnter" parent="Background/Standard" instance=ExtResource("2")] -layout_mode = 0 -offset_left = 340.0 -offset_top = 120.0 -offset_right = 390.0 -offset_bottom = 145.0 -text = "Enter" +[node name="VirtualKeyEnter" type="Node2D" parent="Background/Standard"] +position = Vector2(340, 160) +script = ExtResource("2_n0nlg") scan_code_text = "Enter" +key_size = Vector2(52, 32) +key_text = "Enter" [node name="LowerCase" type="Node2D" parent="Background"] -position = Vector2(0, 30) +position = Vector2(4, 44) -[node name="VirtualKeyLowerQ" parent="Background/LowerCase" instance=ExtResource("2")] -text = "q" +[node name="VirtualKeyLowerQ" type="Node2D" parent="Background/LowerCase"] +script = ExtResource("2_n0nlg") scan_code_text = "Q" unicode = 113 +key_text = "q" -[node name="VirtualKeyLowerW" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 40.0 -offset_right = 70.0 -text = "w" +[node name="VirtualKeyLowerW" type="Node2D" parent="Background/LowerCase"] +position = Vector2(40, 0) +script = ExtResource("2_n0nlg") scan_code_text = "W" unicode = 119 +key_text = "w" -[node name="VirtualKeyLowerE" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 80.0 -offset_right = 110.0 -text = "e" +[node name="VirtualKeyLowerE" type="Node2D" parent="Background/LowerCase"] +position = Vector2(80, 0) +script = ExtResource("2_n0nlg") scan_code_text = "E" unicode = 101 +key_text = "e" -[node name="VirtualKeyLowerR" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 120.0 -offset_right = 150.0 -text = "r" +[node name="VirtualKeyLowerR" type="Node2D" parent="Background/LowerCase"] +position = Vector2(120, 0) +script = ExtResource("2_n0nlg") scan_code_text = "R" unicode = 114 +key_text = "r" -[node name="VirtualKeyLowerT" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 160.0 -offset_right = 190.0 -text = "t" +[node name="VirtualKeyLowerT" type="Node2D" parent="Background/LowerCase"] +position = Vector2(160, 0) +script = ExtResource("2_n0nlg") scan_code_text = "T" unicode = 116 +key_text = "t" -[node name="VirtualKeyLowerY" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 200.0 -offset_right = 230.0 -text = "y" +[node name="VirtualKeyLowerY" type="Node2D" parent="Background/LowerCase"] +position = Vector2(200, 0) +script = ExtResource("2_n0nlg") scan_code_text = "Y" unicode = 121 +key_text = "y" -[node name="VirtualKeyLowerU" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 240.0 -offset_right = 270.0 -text = "u" +[node name="VirtualKeyLowerU" type="Node2D" parent="Background/LowerCase"] +position = Vector2(240, 0) +script = ExtResource("2_n0nlg") scan_code_text = "U" unicode = 117 +key_text = "u" -[node name="VirtualKeyLowerI" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 280.0 -offset_right = 310.0 -text = "i" +[node name="VirtualKeyLowerI" type="Node2D" parent="Background/LowerCase"] +position = Vector2(280, 0) +script = ExtResource("2_n0nlg") scan_code_text = "I" unicode = 105 +key_text = "i" -[node name="VirtualKeyLowerO" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 320.0 -offset_right = 350.0 -text = "o" +[node name="VirtualKeyLowerO" type="Node2D" parent="Background/LowerCase"] +position = Vector2(320, 0) +script = ExtResource("2_n0nlg") scan_code_text = "O" unicode = 111 +key_text = "o" -[node name="VirtualKeyLowerP" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 360.0 -offset_right = 390.0 -text = "p" +[node name="VirtualKeyLowerP" type="Node2D" parent="Background/LowerCase"] +position = Vector2(360, 0) +script = ExtResource("2_n0nlg") scan_code_text = "P" unicode = 112 +key_text = "p" -[node name="VirtualKeyLowerA" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 20.0 -offset_top = 30.0 -offset_right = 50.0 -offset_bottom = 55.0 -text = "a" +[node name="VirtualKeyLowerA" type="Node2D" parent="Background/LowerCase"] +position = Vector2(20, 40) +script = ExtResource("2_n0nlg") scan_code_text = "A" unicode = 97 +key_text = "a" -[node name="VirtualKeyLowerS" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 60.0 -offset_top = 30.0 -offset_right = 90.0 -offset_bottom = 55.0 -text = "s" +[node name="VirtualKeyLowerS" type="Node2D" parent="Background/LowerCase"] +position = Vector2(60, 40) +script = ExtResource("2_n0nlg") scan_code_text = "S" unicode = 115 +key_text = "s" -[node name="VirtualKeyLowerD" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 100.0 -offset_top = 30.0 -offset_right = 130.0 -offset_bottom = 55.0 -text = "d" +[node name="VirtualKeyLowerD" type="Node2D" parent="Background/LowerCase"] +position = Vector2(100, 40) +script = ExtResource("2_n0nlg") scan_code_text = "D" unicode = 100 +key_text = "d" -[node name="VirtualKeyLowerF" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 140.0 -offset_top = 30.0 -offset_right = 170.0 -offset_bottom = 55.0 -text = "f" +[node name="VirtualKeyLowerF" type="Node2D" parent="Background/LowerCase"] +position = Vector2(140, 40) +script = ExtResource("2_n0nlg") scan_code_text = "F" unicode = 102 +key_text = "f" -[node name="VirtualKeyLowerG" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 180.0 -offset_top = 30.0 -offset_right = 210.0 -offset_bottom = 55.0 -text = "g" +[node name="VirtualKeyLowerG" type="Node2D" parent="Background/LowerCase"] +position = Vector2(180, 40) +script = ExtResource("2_n0nlg") scan_code_text = "G" unicode = 103 +key_text = "g" -[node name="VirtualKeyLowerH" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 220.0 -offset_top = 30.0 -offset_right = 250.0 -offset_bottom = 55.0 -text = "h" +[node name="VirtualKeyLowerH" type="Node2D" parent="Background/LowerCase"] +position = Vector2(220, 40) +script = ExtResource("2_n0nlg") scan_code_text = "H" unicode = 104 +key_text = "h" -[node name="VirtualKeyLowerJ" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 260.0 -offset_top = 30.0 -offset_right = 290.0 -offset_bottom = 55.0 -text = "j" +[node name="VirtualKeyLowerJ" type="Node2D" parent="Background/LowerCase"] +position = Vector2(260, 40) +script = ExtResource("2_n0nlg") scan_code_text = "J" unicode = 106 +key_text = "j" -[node name="VirtualKeyLowerK" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 300.0 -offset_top = 30.0 -offset_right = 330.0 -offset_bottom = 55.0 -text = "k" +[node name="VirtualKeyLowerK" type="Node2D" parent="Background/LowerCase"] +position = Vector2(300, 40) +script = ExtResource("2_n0nlg") scan_code_text = "K" unicode = 107 +key_text = "k" -[node name="VirtualKeyLowerL" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 340.0 -offset_top = 30.0 -offset_right = 370.0 -offset_bottom = 55.0 -text = "l" +[node name="VirtualKeyLowerL" type="Node2D" parent="Background/LowerCase"] +position = Vector2(340, 40) +script = ExtResource("2_n0nlg") scan_code_text = "L" unicode = 108 +key_text = "l" -[node name="VirtualKeyLowerZ" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 60.0 -offset_top = 60.0 -offset_right = 90.0 -offset_bottom = 85.0 -text = "z" +[node name="VirtualKeyLowerZ" type="Node2D" parent="Background/LowerCase"] +position = Vector2(60, 80) +script = ExtResource("2_n0nlg") scan_code_text = "Z" unicode = 122 +key_text = "z" -[node name="VirtualKeyLowerX" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 100.0 -offset_top = 60.0 -offset_right = 130.0 -offset_bottom = 85.0 -text = "x" +[node name="VirtualKeyLowerX" type="Node2D" parent="Background/LowerCase"] +position = Vector2(100, 80) +script = ExtResource("2_n0nlg") scan_code_text = "X" unicode = 120 +key_text = "x" -[node name="VirtualKeyLowerC" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 140.0 -offset_top = 60.0 -offset_right = 170.0 -offset_bottom = 85.0 -text = "c" +[node name="VirtualKeyLowerC" type="Node2D" parent="Background/LowerCase"] +position = Vector2(140, 80) +script = ExtResource("2_n0nlg") scan_code_text = "C" unicode = 99 +key_text = "c" -[node name="VirtualKeyLowerV" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 180.0 -offset_top = 60.0 -offset_right = 210.0 -offset_bottom = 85.0 -text = "v" +[node name="VirtualKeyLowerV" type="Node2D" parent="Background/LowerCase"] +position = Vector2(180, 80) +script = ExtResource("2_n0nlg") scan_code_text = "V" unicode = 118 +key_text = "v" -[node name="VirtualKeyLowerB" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 220.0 -offset_top = 60.0 -offset_right = 250.0 -offset_bottom = 85.0 -text = "b" +[node name="VirtualKeyLowerB" type="Node2D" parent="Background/LowerCase"] +position = Vector2(220, 80) +script = ExtResource("2_n0nlg") scan_code_text = "B" unicode = 98 +key_text = "b" -[node name="VirtualKeyLowerN" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 260.0 -offset_top = 60.0 -offset_right = 290.0 -offset_bottom = 85.0 -text = "n" +[node name="VirtualKeyLowerN" type="Node2D" parent="Background/LowerCase"] +position = Vector2(260, 80) +script = ExtResource("2_n0nlg") scan_code_text = "N" unicode = 110 +key_text = "n" -[node name="VirtualKeyLowerM" parent="Background/LowerCase" instance=ExtResource("2")] -offset_left = 300.0 -offset_top = 60.0 -offset_right = 330.0 -offset_bottom = 85.0 -text = "m" +[node name="VirtualKeyLowerM" type="Node2D" parent="Background/LowerCase"] +position = Vector2(300, 80) +script = ExtResource("2_n0nlg") scan_code_text = "M" unicode = 109 +key_text = "m" [node name="UpperCase" type="Node2D" parent="Background"] visible = false -position = Vector2(0, 30) +position = Vector2(4, 44) -[node name="VirtualKeyUpperQ" parent="Background/UpperCase" instance=ExtResource("2")] -text = "Q" +[node name="VirtualKeyUpperQ" type="Node2D" parent="Background/UpperCase"] +script = ExtResource("2_n0nlg") scan_code_text = "Q" unicode = 81 shift_modifier = true +key_text = "Q" -[node name="VirtualKeyUpperW" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 40.0 -offset_right = 70.0 -text = "W" +[node name="VirtualKeyUpperW" type="Node2D" parent="Background/UpperCase"] +position = Vector2(40, 0) +script = ExtResource("2_n0nlg") scan_code_text = "W" unicode = 87 shift_modifier = true +key_text = "W" -[node name="VirtualKeyUpperE" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 80.0 -offset_right = 110.0 -text = "E" +[node name="VirtualKeyUpperE" type="Node2D" parent="Background/UpperCase"] +position = Vector2(80, 0) +script = ExtResource("2_n0nlg") scan_code_text = "E" unicode = 69 shift_modifier = true +key_text = "E" -[node name="VirtualKeyUpperR" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 120.0 -offset_right = 150.0 -text = "R" +[node name="VirtualKeyUpperR" type="Node2D" parent="Background/UpperCase"] +position = Vector2(120, 0) +script = ExtResource("2_n0nlg") scan_code_text = "R" unicode = 82 shift_modifier = true +key_text = "R" -[node name="VirtualKeyUpperT" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 160.0 -offset_right = 190.0 -text = "T" +[node name="VirtualKeyUpperT" type="Node2D" parent="Background/UpperCase"] +position = Vector2(160, 0) +script = ExtResource("2_n0nlg") scan_code_text = "T" unicode = 84 shift_modifier = true +key_text = "T" -[node name="VirtualKeyUpperY" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 200.0 -offset_right = 230.0 -text = "Y" +[node name="VirtualKeyUpperY" type="Node2D" parent="Background/UpperCase"] +position = Vector2(200, 0) +script = ExtResource("2_n0nlg") scan_code_text = "Y" unicode = 89 shift_modifier = true +key_text = "Y" -[node name="VirtualKeyUpperU" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 240.0 -offset_right = 270.0 -text = "U" +[node name="VirtualKeyUpperU" type="Node2D" parent="Background/UpperCase"] +position = Vector2(240, 0) +script = ExtResource("2_n0nlg") scan_code_text = "U" unicode = 85 shift_modifier = true +key_text = "U" -[node name="VirtualKeyUpperI" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 280.0 -offset_right = 310.0 -text = "I" +[node name="VirtualKeyUpperI" type="Node2D" parent="Background/UpperCase"] +position = Vector2(280, 0) +script = ExtResource("2_n0nlg") scan_code_text = "I" unicode = 73 shift_modifier = true +key_text = "I" -[node name="VirtualKeyUpperO" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 320.0 -offset_right = 350.0 -text = "O" +[node name="VirtualKeyUpperO" type="Node2D" parent="Background/UpperCase"] +position = Vector2(320, 0) +script = ExtResource("2_n0nlg") scan_code_text = "O" unicode = 79 shift_modifier = true +key_text = "O" -[node name="VirtualKeyUpperP" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 360.0 -offset_right = 390.0 -text = "P" +[node name="VirtualKeyUpperP" type="Node2D" parent="Background/UpperCase"] +position = Vector2(360, 0) +script = ExtResource("2_n0nlg") scan_code_text = "P" unicode = 80 shift_modifier = true +key_text = "P" -[node name="VirtualKeyUpperA" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 20.0 -offset_top = 30.0 -offset_right = 50.0 -offset_bottom = 55.0 -text = "A" +[node name="VirtualKeyUpperA" type="Node2D" parent="Background/UpperCase"] +position = Vector2(20, 40) +script = ExtResource("2_n0nlg") scan_code_text = "A" unicode = 65 shift_modifier = true +key_text = "A" -[node name="VirtualKeyUpperS" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 60.0 -offset_top = 30.0 -offset_right = 90.0 -offset_bottom = 55.0 -text = "S" +[node name="VirtualKeyUpperS" type="Node2D" parent="Background/UpperCase"] +position = Vector2(60, 40) +script = ExtResource("2_n0nlg") scan_code_text = "S" unicode = 83 shift_modifier = true +key_text = "S" -[node name="VirtualKeyUpperD" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 100.0 -offset_top = 30.0 -offset_right = 130.0 -offset_bottom = 55.0 -text = "D" +[node name="VirtualKeyUpperD" type="Node2D" parent="Background/UpperCase"] +position = Vector2(100, 40) +script = ExtResource("2_n0nlg") scan_code_text = "D" unicode = 68 shift_modifier = true +key_text = "D" -[node name="VirtualKeyUpperF" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 140.0 -offset_top = 30.0 -offset_right = 170.0 -offset_bottom = 55.0 -text = "F" +[node name="VirtualKeyUpperF" type="Node2D" parent="Background/UpperCase"] +position = Vector2(140, 40) +script = ExtResource("2_n0nlg") scan_code_text = "F" unicode = 70 shift_modifier = true +key_text = "F" -[node name="VirtualKeyUpperG" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 180.0 -offset_top = 30.0 -offset_right = 210.0 -offset_bottom = 55.0 -text = "G" +[node name="VirtualKeyUpperG" type="Node2D" parent="Background/UpperCase"] +position = Vector2(180, 40) +script = ExtResource("2_n0nlg") scan_code_text = "G" unicode = 71 shift_modifier = true +key_text = "G" -[node name="VirtualKeyUpperH" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 220.0 -offset_top = 30.0 -offset_right = 250.0 -offset_bottom = 55.0 -text = "H" +[node name="VirtualKeyUpperH" type="Node2D" parent="Background/UpperCase"] +position = Vector2(220, 40) +script = ExtResource("2_n0nlg") scan_code_text = "H" unicode = 72 shift_modifier = true +key_text = "H" -[node name="VirtualKeyUpperJ" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 260.0 -offset_top = 30.0 -offset_right = 290.0 -offset_bottom = 55.0 -text = "J" +[node name="VirtualKeyUpperJ" type="Node2D" parent="Background/UpperCase"] +position = Vector2(260, 40) +script = ExtResource("2_n0nlg") scan_code_text = "J" unicode = 74 shift_modifier = true +key_text = "J" -[node name="VirtualKeyUpperK" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 300.0 -offset_top = 30.0 -offset_right = 330.0 -offset_bottom = 55.0 -text = "K" +[node name="VirtualKeyUpperK" type="Node2D" parent="Background/UpperCase"] +position = Vector2(300, 40) +script = ExtResource("2_n0nlg") scan_code_text = "K" unicode = 75 shift_modifier = true +key_text = "K" -[node name="VirtualKeyUpperL" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 340.0 -offset_top = 30.0 -offset_right = 370.0 -offset_bottom = 55.0 -text = "L" +[node name="VirtualKeyUpperL" type="Node2D" parent="Background/UpperCase"] +position = Vector2(340, 40) +script = ExtResource("2_n0nlg") scan_code_text = "L" unicode = 76 shift_modifier = true +key_text = "L" -[node name="VirtualKeyUpperZ" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 60.0 -offset_top = 60.0 -offset_right = 90.0 -offset_bottom = 85.0 -text = "Z" +[node name="VirtualKeyUpperZ" type="Node2D" parent="Background/UpperCase"] +position = Vector2(60, 80) +script = ExtResource("2_n0nlg") scan_code_text = "Z" unicode = 90 shift_modifier = true +key_text = "Z" -[node name="VirtualKeyUpperX" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 100.0 -offset_top = 60.0 -offset_right = 130.0 -offset_bottom = 85.0 -text = "X" +[node name="VirtualKeyUpperX" type="Node2D" parent="Background/UpperCase"] +position = Vector2(100, 80) +script = ExtResource("2_n0nlg") scan_code_text = "X" unicode = 88 shift_modifier = true +key_text = "X" -[node name="VirtualKeyUpperC" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 140.0 -offset_top = 60.0 -offset_right = 170.0 -offset_bottom = 85.0 -text = "C" +[node name="VirtualKeyUpperC" type="Node2D" parent="Background/UpperCase"] +position = Vector2(140, 80) +script = ExtResource("2_n0nlg") scan_code_text = "C" unicode = 67 shift_modifier = true +key_text = "C" -[node name="VirtualKeyUpperV" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 180.0 -offset_top = 60.0 -offset_right = 210.0 -offset_bottom = 85.0 -text = "V" +[node name="VirtualKeyUpperV" type="Node2D" parent="Background/UpperCase"] +position = Vector2(180, 80) +script = ExtResource("2_n0nlg") scan_code_text = "V" unicode = 86 shift_modifier = true +key_text = "V" -[node name="VirtualKeyUpperB" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 220.0 -offset_top = 60.0 -offset_right = 250.0 -offset_bottom = 85.0 -text = "B" +[node name="VirtualKeyUpperB" type="Node2D" parent="Background/UpperCase"] +position = Vector2(220, 80) +script = ExtResource("2_n0nlg") scan_code_text = "B" unicode = 66 shift_modifier = true +key_text = "B" -[node name="VirtualKeyUpperN" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 260.0 -offset_top = 60.0 -offset_right = 290.0 -offset_bottom = 85.0 -text = "N" +[node name="VirtualKeyUpperN" type="Node2D" parent="Background/UpperCase"] +position = Vector2(260, 80) +script = ExtResource("2_n0nlg") scan_code_text = "N" unicode = 78 shift_modifier = true +key_text = "N" -[node name="VirtualKeyUpperM" parent="Background/UpperCase" instance=ExtResource("2")] -offset_left = 300.0 -offset_top = 60.0 -offset_right = 330.0 -offset_bottom = 85.0 -text = "M" +[node name="VirtualKeyUpperM" type="Node2D" parent="Background/UpperCase"] +position = Vector2(300, 80) +script = ExtResource("2_n0nlg") scan_code_text = "M" unicode = 77 shift_modifier = true +key_text = "M" [node name="Alternate" type="Node2D" parent="Background"] visible = false -position = Vector2(0, 30) +position = Vector2(4, 44) -[node name="VirtualKeyPlus" parent="Background/Alternate" instance=ExtResource("2")] -text = "+" +[node name="VirtualKeyPlus" type="Node2D" parent="Background/Alternate"] +script = ExtResource("2_n0nlg") scan_code_text = "Plus" unicode = 43 +key_text = "+" -[node name="VirtualKeyAsterisk" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 40.0 -offset_right = 70.0 -text = "*" +[node name="VirtualKeyAsterisk" type="Node2D" parent="Background/Alternate"] +position = Vector2(40, 0) +script = ExtResource("2_n0nlg") scan_code_text = "Asterisk" unicode = 42 +key_text = "*" -[node name="VirtualKeyDivision" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 80.0 -offset_right = 110.0 -text = "÷" +[node name="VirtualKeyDivision" type="Node2D" parent="Background/Alternate"] +position = Vector2(80, 0) +script = ExtResource("2_n0nlg") scan_code_text = "Division" unicode = 247 +key_text = "÷" -[node name="VirtualKeyEqual" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 120.0 -offset_right = 150.0 -text = "=" +[node name="VirtualKeyEqual" type="Node2D" parent="Background/Alternate"] +position = Vector2(120, 0) +script = ExtResource("2_n0nlg") scan_code_text = "Equal" unicode = 61 +key_text = "=" -[node name="VirtualKeySlash" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 160.0 -offset_right = 190.0 -text = "/" +[node name="VirtualKeySlash" type="Node2D" parent="Background/Alternate"] +position = Vector2(160, 0) +script = ExtResource("2_n0nlg") scan_code_text = "Slash" unicode = 47 +key_text = "/" -[node name="VirtualKeyUnderScore" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 200.0 -offset_right = 230.0 -text = "_" +[node name="VirtualKeyUnderScore" type="Node2D" parent="Background/Alternate"] +position = Vector2(200, 0) +script = ExtResource("2_n0nlg") scan_code_text = "UnderScore" unicode = 95 +key_text = "_" -[node name="VirtualKeyLess" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 240.0 -offset_right = 270.0 -text = "<" +[node name="VirtualKeyLess" type="Node2D" parent="Background/Alternate"] +position = Vector2(240, 0) +script = ExtResource("2_n0nlg") scan_code_text = "Less" unicode = 60 -shift_modifier = true +key_text = "<" -[node name="VirtualKeyGreater" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 280.0 -offset_right = 310.0 -text = ">" +[node name="VirtualKeyGreater" type="Node2D" parent="Background/Alternate"] +position = Vector2(280, 0) +script = ExtResource("2_n0nlg") scan_code_text = "Greater" unicode = 62 +key_text = ">" -[node name="VirtualKeyBracketLeft" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 320.0 -offset_right = 350.0 -text = "[" +[node name="VirtualKeyBracketLeft" type="Node2D" parent="Background/Alternate"] +position = Vector2(320, 0) +script = ExtResource("2_n0nlg") scan_code_text = "BracketLeft" unicode = 91 -shift_modifier = true +key_text = "[" -[node name="VirtualKeyBracketRight" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 360.0 -offset_right = 390.0 -text = "]" +[node name="VirtualKeyBracketRight" type="Node2D" parent="Background/Alternate"] +position = Vector2(360, 0) +script = ExtResource("2_n0nlg") scan_code_text = "BracketRight" unicode = 93 +key_text = "]" -[node name="VirtualKeyExclam" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 20.0 -offset_top = 30.0 -offset_right = 50.0 -offset_bottom = 55.0 -text = "!" +[node name="VirtualKeyExclam" type="Node2D" parent="Background/Alternate"] +position = Vector2(20, 40) +script = ExtResource("2_n0nlg") scan_code_text = "Exclam" unicode = 33 +key_text = "!" -[node name="VirtualKeyAt" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 60.0 -offset_top = 30.0 -offset_right = 90.0 -offset_bottom = 55.0 -text = "@" +[node name="VirtualKeyAt" type="Node2D" parent="Background/Alternate"] +position = Vector2(60, 40) +script = ExtResource("2_n0nlg") scan_code_text = "At" unicode = 64 +key_text = "@" -[node name="VirtualKeyNumberSign" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 100.0 -offset_top = 30.0 -offset_right = 130.0 -offset_bottom = 55.0 -text = "#" +[node name="VirtualKeyNumberSign" type="Node2D" parent="Background/Alternate"] +position = Vector2(100, 40) +script = ExtResource("2_n0nlg") scan_code_text = "NumberSign" unicode = 35 +key_text = "#" -[node name="VirtualKeyDollar" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 140.0 -offset_top = 30.0 -offset_right = 170.0 -offset_bottom = 55.0 -text = "$" +[node name="VirtualKeyDollar" type="Node2D" parent="Background/Alternate"] +position = Vector2(140, 40) +script = ExtResource("2_n0nlg") scan_code_text = "Dollar" unicode = 36 +key_text = "$" -[node name="VirtualKeyPercent" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 180.0 -offset_top = 30.0 -offset_right = 210.0 -offset_bottom = 55.0 -text = "%" +[node name="VirtualKeyPercent" type="Node2D" parent="Background/Alternate"] +position = Vector2(180, 40) +script = ExtResource("2_n0nlg") scan_code_text = "Percent" unicode = 37 +key_text = "%" -[node name="VirtualKeyCircumflex" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 220.0 -offset_top = 30.0 -offset_right = 250.0 -offset_bottom = 55.0 -text = "^" +[node name="VirtualKeyCircumflex" type="Node2D" parent="Background/Alternate"] +position = Vector2(220, 40) +script = ExtResource("2_n0nlg") scan_code_text = "AsciiCircum" unicode = 94 +key_text = "^" -[node name="VirtualKeyAmpersand" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 260.0 -offset_top = 30.0 -offset_right = 290.0 -offset_bottom = 55.0 -text = "&" +[node name="VirtualKeyAmpersand" type="Node2D" parent="Background/Alternate"] +position = Vector2(260, 40) +script = ExtResource("2_n0nlg") scan_code_text = "Ampersand" unicode = 38 +key_text = "&" -[node name="VirtualKeyParenLeft" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 300.0 -offset_top = 30.0 -offset_right = 330.0 -offset_bottom = 55.0 -text = "(" +[node name="VirtualKeyParenLeft" type="Node2D" parent="Background/Alternate"] +position = Vector2(300, 40) +script = ExtResource("2_n0nlg") scan_code_text = "ParenLeft" unicode = 40 +key_text = "(" -[node name="VirtualKeyParenRight" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 340.0 -offset_top = 30.0 -offset_right = 370.0 -offset_bottom = 55.0 -text = ")" +[node name="VirtualKeyParenRight" type="Node2D" parent="Background/Alternate"] +position = Vector2(340, 40) +script = ExtResource("2_n0nlg") scan_code_text = "ParenRight" unicode = 41 +key_text = ")" -[node name="VirtualKeyMinus" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 60.0 -offset_top = 60.0 -offset_right = 90.0 -offset_bottom = 85.0 -text = "-" +[node name="VirtualKeyMinus" type="Node2D" parent="Background/Alternate"] +position = Vector2(60, 80) +script = ExtResource("2_n0nlg") scan_code_text = "Minus" unicode = 45 +key_text = "-" -[node name="VirtualKeyApostrophe" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 100.0 -offset_top = 60.0 -offset_right = 130.0 -offset_bottom = 85.0 -text = "'" +[node name="VirtualKeyApostrophe" type="Node2D" parent="Background/Alternate"] +position = Vector2(100, 80) +script = ExtResource("2_n0nlg") scan_code_text = "Apostrophe" unicode = 39 +key_text = "'" -[node name="VirtualKeyQuoteDbl" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 140.0 -offset_top = 60.0 -offset_right = 170.0 -offset_bottom = 85.0 -text = "\"" +[node name="VirtualKeyQuoteDbl" type="Node2D" parent="Background/Alternate"] +position = Vector2(140, 80) +script = ExtResource("2_n0nlg") scan_code_text = "QuoteDbl" unicode = 34 +key_text = "\"" -[node name="VirtualKeyColon" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 180.0 -offset_top = 60.0 -offset_right = 210.0 -offset_bottom = 85.0 -text = ":" +[node name="VirtualKeyColon" type="Node2D" parent="Background/Alternate"] +position = Vector2(180, 80) +script = ExtResource("2_n0nlg") scan_code_text = "Colon" unicode = 58 +key_text = ":" -[node name="VirtualKeySemicolon" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 220.0 -offset_top = 60.0 -offset_right = 250.0 -offset_bottom = 85.0 -text = ";" +[node name="VirtualKeySemicolon" type="Node2D" parent="Background/Alternate"] +position = Vector2(220, 80) +script = ExtResource("2_n0nlg") scan_code_text = "Semicolon" unicode = 59 +key_text = ";" -[node name="VirtualKeyComma" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 260.0 -offset_top = 60.0 -offset_right = 290.0 -offset_bottom = 85.0 -text = "," +[node name="VirtualKeyComma" type="Node2D" parent="Background/Alternate"] +position = Vector2(260, 80) +script = ExtResource("2_n0nlg") scan_code_text = "Comma" unicode = 44 +key_text = "," -[node name="VirtualKeyQuestion" parent="Background/Alternate" instance=ExtResource("2")] -offset_left = 300.0 -offset_top = 60.0 -offset_right = 330.0 -offset_bottom = 85.0 -text = "?" +[node name="VirtualKeyQuestion" type="Node2D" parent="Background/Alternate"] +position = Vector2(300, 80) +script = ExtResource("2_n0nlg") scan_code_text = "Question" unicode = 63 +key_text = "?" -[connection signal="toggled" from="Background/Standard/ToggleShift" to="." method="on_shift_toggle"] -[connection signal="toggled" from="Background/Standard/ToggleCaps" to="." method="on_caps_toggle"] -[connection signal="toggled" from="Background/Standard/ToggleAlt" to="." method="on_alt_toggle"] +[connection signal="pressed" from="Background/Standard/ToggleShift" to="." method="_on_toggle_shift_pressed"] +[connection signal="pressed" from="Background/Standard/ToggleCaps" to="." method="_on_toggle_caps_pressed"] +[connection signal="pressed" from="Background/Standard/ToggleAlt" to="." method="_on_toggle_alt_pressed"] diff --git a/addons/godot-xr-tools/objects/viewport_2d_in_3d.gd b/addons/godot-xr-tools/objects/viewport_2d_in_3d.gd index 62034b97..6386cabf 100644 --- a/addons/godot-xr-tools/objects/viewport_2d_in_3d.gd +++ b/addons/godot-xr-tools/objects/viewport_2d_in_3d.gd @@ -9,8 +9,8 @@ extends Node3D ## Pointer and keyboard input are mapped into the 2D scene. -signal pointer_entered -signal pointer_exited +## Signal for pointer events +signal pointer_event(event) ## Transparent property @@ -111,6 +111,9 @@ var _dirty := _DIRTY_ALL func _ready(): is_ready = true + # Listen for pointer events on the screen body + $StaticBody3D.connect("pointer_event", _on_pointer_event) + # Apply physics properties _update_screen_size() _update_enabled() @@ -189,14 +192,9 @@ func connect_scene_signal(which : String, callback : Callable, flags : int = 0): scene_node.connect(which, callback, flags) -# Handler for pointer entered -func _on_pointer_entered(): - emit_signal("pointer_entered") - - -# Handler for pointer exited -func _on_pointer_exited(): - emit_signal("pointer_exited") +# Handle pointer event from screen-body +func _on_pointer_event(event : XRToolsPointerEvent) -> void: + pointer_event.emit(event) # Handler for input eventsd diff --git a/addons/godot-xr-tools/objects/viewport_2d_in_3d.tscn b/addons/godot-xr-tools/objects/viewport_2d_in_3d.tscn index 285c01ea..cf0531c4 100644 --- a/addons/godot-xr-tools/objects/viewport_2d_in_3d.tscn +++ b/addons/godot-xr-tools/objects/viewport_2d_in_3d.tscn @@ -7,12 +7,12 @@ resource_local_to_scene = true size = Vector2(3, 2) -[sub_resource type="ViewportTexture" id="ViewportTexture_0vyuj"] +[sub_resource type="ViewportTexture" id="ViewportTexture_ufe4n"] -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ney1s"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_fvml0"] transparency = 1 cull_mode = 2 -albedo_texture = SubResource("ViewportTexture_0vyuj") +albedo_texture = SubResource("ViewportTexture_ufe4n") texture_filter = 1 [sub_resource type="BoxShape3D" id="4"] @@ -34,7 +34,7 @@ render_target_update_mode = 1 [node name="Screen" type="MeshInstance3D" parent="."] mesh = SubResource("1") -surface_material_override/0 = SubResource("StandardMaterial3D_ney1s") +surface_material_override/0 = SubResource("StandardMaterial3D_fvml0") [node name="StaticBody3D" type="StaticBody3D" parent="."] collision_layer = 5242881 @@ -45,9 +45,3 @@ viewport_size = Vector2(300, 200) [node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.01) shape = SubResource("4") - -[connection signal="pointer_entered" from="StaticBody3D" to="." method="_on_pointer_entered"] -[connection signal="pointer_exited" from="StaticBody3D" to="." method="_on_pointer_exited"] -[connection signal="pointer_moved" from="StaticBody3D" to="StaticBody3D" method="_on_pointer_moved"] -[connection signal="pointer_pressed" from="StaticBody3D" to="StaticBody3D" method="_on_pointer_pressed"] -[connection signal="pointer_released" from="StaticBody3D" to="StaticBody3D" method="_on_pointer_released"] diff --git a/addons/godot-xr-tools/objects/viewport_2d_in_3d_body.gd b/addons/godot-xr-tools/objects/viewport_2d_in_3d_body.gd index 17dc4e24..c41a0ab2 100644 --- a/addons/godot-xr-tools/objects/viewport_2d_in_3d_body.gd +++ b/addons/godot-xr-tools/objects/viewport_2d_in_3d_body.gd @@ -1,17 +1,45 @@ extends XRToolsInteractableBody + +## Screen size @export var screen_size = Vector2(3.0, 2.0) + +## Viewport size @export var viewport_size = Vector2(100.0, 100.0) -var vp = null -var mouse_mask = 0 -# Called when the node enters the scene tree for the first time. +# Current mouse mask +var _mouse_mask := 0 + +# Viewport node +var _viewport : Viewport + +# Dictionary of pointers to touch-index +var _touches := {} + +# Dictionary of pressed pointers +var _presses := {} + +# Dominant pointer (index == 0) +var _dominant : Node3D + +# Mouse pointer +var _mouse : Node3D + +# Last mouse position +var _mouse_last := Vector2.ZERO + + func _ready(): - vp = get_node("../Viewport") + # Get viewport node + _viewport = get_node("../Viewport") + + # Subscribe to pointer events + pointer_event.connect(_on_pointer_event) + -# Convert intersection point to screen coordinate -func global_to_viewport(p_at): +## Convert intersection point to screen coordinate +func global_to_viewport(p_at : Vector3) -> Vector2: var t = $CollisionShape3D.global_transform var at = t.affine_inverse() * p_at @@ -21,48 +49,169 @@ func global_to_viewport(p_at): return Vector2(at.x, at.y) -func _on_pointer_moved(from, to): - var local_from = global_to_viewport(from) - var local_to = global_to_viewport(to) - - # Let's mimic a mouse - var event = InputEventMouseMotion.new() - event.set_position(local_to) - event.set_global_position(local_to) - event.set_relative(local_to - local_from) # should this be scaled/warped? - event.set_button_mask(mouse_mask) - event.set_pressure(mouse_mask) - - if vp: - vp.push_input(event) - -func _on_pointer_pressed(at): - var local_at = global_to_viewport(at) - - # Let's mimic a mouse - mouse_mask = 1 - var event = InputEventMouseButton.new() - event.set_button_index(1) - event.set_pressed(true) - event.set_position(local_at) - event.set_global_position(local_at) - event.set_button_mask(mouse_mask) - - if vp: - vp.push_input(event) - -func _on_pointer_released(at): - var local_at = global_to_viewport(at) - - # Let's mimic a mouse - mouse_mask = 0 - var event = InputEventMouseButton.new() - event.set_button_index(1) - event.set_pressed(false) - event.set_position(local_at) - event.set_global_position(local_at) - event.set_button_mask(mouse_mask) - - if vp: - vp.push_input(event) +# Pointer event handler +func _on_pointer_event(event : XRToolsPointerEvent) -> void: + # Ignore if we have no viewport + if not is_instance_valid(_viewport): + return + + # Get the pointer and event type + var pointer := event.pointer + var type := event.event_type + + # Get the touch-index [0..] + var index : int = _touches.get(pointer, -1) + + # Create a new touch-index if necessary + if index < 0 or type == XRToolsPointerEvent.Type.ENTERED: + # Clear any stale pointer information + _touches.erase(pointer) + _presses.erase(pointer) + + # Assign a new touch-index for the pointer + index = _next_touch_index() + _touches[pointer] = index + + # Detect dominant pointer + if index == 0: + _dominant = pointer + + # Get the viewport positions + var at := global_to_viewport(event.position) + var last := global_to_viewport(event.last_position) + + # Get/update pressed state + var pressed : bool + match type: + XRToolsPointerEvent.Type.PRESSED: + _presses[pointer] = true + pressed = true + + XRToolsPointerEvent.Type.RELEASED: + _presses.erase(pointer) + pressed = false + + _: + pressed = _presses.has(pointer) + + # Dispatch touch events + match type: + XRToolsPointerEvent.Type.PRESSED: + _report_touch_down(index, at) + + XRToolsPointerEvent.Type.RELEASED: + _report_touch_up(index, at) + + XRToolsPointerEvent.Type.MOVED: + _report_touch_move(index, pressed, last, at) + + # If the current mouse isn't pressed then consider switching to a new one + if not _presses.has(_mouse): + if type == XRToolsPointerEvent.Type.PRESSED and pointer is XRToolsFunctionPointer: + # Switch to pressed laser-pointer + _mouse = pointer + elif type == XRToolsPointerEvent.Type.EXITED and pointer == _mouse: + # Current mouse leaving, switch to dominant + _mouse = _dominant + elif not _mouse and _dominant: + # No mouse, pick the dominant + _mouse = _dominant + + # Fire mouse events + if pointer == _mouse: + match type: + XRToolsPointerEvent.Type.PRESSED: + _report_mouse_down(at) + + XRToolsPointerEvent.Type.RELEASED: + _report_mouse_up( at) + + XRToolsPointerEvent.Type.MOVED: + _report_mouse_move(pressed, last, at) + + # Clear pointer information on exit + if type == XRToolsPointerEvent.Type.EXITED: + # Clear pointer information + _touches.erase(pointer) + _presses.erase(pointer) + if pointer == _dominant: + _dominant = null + if pointer == _mouse: + _mouse = null + + +# Report touch-down event +func _report_touch_down(index : int, at : Vector2) -> void: + var event := InputEventScreenTouch.new() + event.index = index + event.position = at + event.pressed = true + _viewport.push_input(event) + + +# Report touch-up event +func _report_touch_up(index : int, at : Vector2) -> void: + var event := InputEventScreenTouch.new() + event.index = index + event.position = at + event.pressed = false + _viewport.push_input(event) + + +# Report touch-move event +func _report_touch_move(index : int, pressed : bool, from : Vector2, to : Vector2) -> void: + var event := InputEventScreenDrag.new() + event.index = index + event.position = to + event.pressure = 1.0 if pressed else 0.0 + event.relative = to - from + _viewport.push_input(event) + + +# Report mouse-down event +func _report_mouse_down(at : Vector2) -> void: + var event := InputEventMouseButton.new() + event.button_index = 1 + event.pressed = true + event.position = at + event.global_position = at + event.button_mask = 1 + _viewport.push_input(event) + + +# Report mouse-up event +func _report_mouse_up(at : Vector2) -> void: + var event := InputEventMouseButton.new() + event.button_index = 1 + event.pressed = false + event.position = at + event.global_position = at + event.button_mask = 0 + _viewport.push_input(event) + + +# Report mouse-move event +func _report_mouse_move(pressed : bool, from : Vector2, to : Vector2) -> void: + var event := InputEventMouseMotion.new() + event.position = to + event.global_position = to + event.relative = to - from + event.button_mask = 1 if pressed else 0 + event.pressure = 1.0 if pressed else 0.0 + _viewport.push_input(event) + + +# Find the next free touch index +func _next_touch_index() -> int: + # Get the current touches + var current := _touches.values() + current.sort() + + # Look for a hole + for touch in current.size(): + if current[touch] != touch: + return touch + + # No hole so add to end + return current.size() diff --git a/addons/godot-xr-tools/objects/virtual_keyboard.tscn b/addons/godot-xr-tools/objects/virtual_keyboard.tscn index 3dcb6957..c9864583 100644 --- a/addons/godot-xr-tools/objects/virtual_keyboard.tscn +++ b/addons/godot-xr-tools/objects/virtual_keyboard.tscn @@ -5,42 +5,40 @@ [sub_resource type="QuadMesh" id="QuadMesh_iets3"] resource_local_to_scene = true -size = Vector2(1.5, 0.558) +size = Vector2(1.5, 0.75) -[sub_resource type="ViewportTexture" id="ViewportTexture_r67jr"] +[sub_resource type="ViewportTexture" id="ViewportTexture_ncnoj"] -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_4r2sk"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_kjc12"] cull_mode = 2 shading_mode = 0 -albedo_texture = SubResource("ViewportTexture_r67jr") +albedo_texture = SubResource("ViewportTexture_ncnoj") texture_filter = 1 [sub_resource type="BoxShape3D" id="BoxShape3D_twvoe"] resource_local_to_scene = true -size = Vector3(1.5, 0.558, 0.02) +size = Vector3(1.5, 0.75, 0.02) [node name="VirtualKeyboard" instance=ExtResource("1")] -screen_size = Vector2(1.5, 0.558) +screen_size = Vector2(1.5, 0.75) scene = ExtResource("2") -viewport_size = Vector2(390, 145) +viewport_size = Vector2(400, 200) update_mode = 2 throttle_fps = 15.0 transparent = 0 -alpha_scissor_threshold = 0.25 unshaded = true -filter = true [node name="Viewport" parent="." index="0"] transparent_bg = false -size = Vector2i(390, 145) +size = Vector2i(400, 200) [node name="Screen" parent="." index="1"] mesh = SubResource("QuadMesh_iets3") -surface_material_override/0 = SubResource("StandardMaterial3D_4r2sk") +surface_material_override/0 = SubResource("StandardMaterial3D_kjc12") [node name="StaticBody3D" parent="." index="2"] -screen_size = Vector2(1.5, 0.558) -viewport_size = Vector2(390, 145) +screen_size = Vector2(1.5, 0.75) +viewport_size = Vector2(400, 200) [node name="CollisionShape3D" parent="StaticBody3D" index="0"] shape = SubResource("BoxShape3D_twvoe") diff --git a/addons/godot-xr-tools/player/poke/poke.gd b/addons/godot-xr-tools/player/poke/poke.gd index b10c76ee..e005e347 100644 --- a/addons/godot-xr-tools/player/poke/poke.gd +++ b/addons/godot-xr-tools/player/poke/poke.gd @@ -12,6 +12,10 @@ extends Node3D ## bodies. +## Signal emitted when this object pokes another object +signal pointing_event(event) + + # Default layer of 18:player-hands const DEFAULT_LAYER := 0b0000_0000_0000_0010_0000_0000_0000_0000 @@ -176,17 +180,15 @@ func _ready(): func _process(_delta): - if is_instance_valid(target): - var new_at = $PokeBody.global_transform.origin - - if target.has_signal("pointer_moved"): - target.emit_signal("pointer_moved", last_collided_at, new_at) - elif target.has_method("pointer_moved"): - target.pointer_moved(last_collided_at, new_at) - - last_collided_at = new_at - else: + # If no target then disable processing + if not is_instance_valid(target): set_process(false) + return + + # Update moving on the target + var new_at : Vector3 = $PokeBody.global_transform.origin + XRToolsPointerEvent.moved(self, target, new_at, last_collided_at) + last_collided_at = new_at func _on_hand_scale_changed(_scale : float) -> void: @@ -199,24 +201,22 @@ func _on_PokeBody_body_contact_start(body): # This will be slightly above the object but since this # mostly targets Viewport2Din3D, this will work - if body.has_signal("pointer_pressed"): - target = body - last_collided_at = $PokeBody.global_transform.origin - target.emit_signal("pointer_pressed", last_collided_at) - elif body.has_method("pointer_pressed"): - target = body - last_collided_at = $PokeBody.global_transform.origin - target.pointer_pressed(last_collided_at) + # Report body pressed + target = body + last_collided_at = $PokeBody.global_transform.origin + XRToolsPointerEvent.entered(self, body, last_collided_at) + XRToolsPointerEvent.pressed(self, body, last_collided_at) + + # Enable processing to track movement + set_process(true) - if target: - set_process(true) func _on_PokeBody_body_contact_end(body): - if body.has_signal("pointer_released"): - body.emit_signal("pointer_released", last_collided_at) - elif body.has_method("pointer_released"): - body.pointer_released(last_collided_at) - - # if we were tracking this target, clear it - if target == body: - target = null + # Skip if not current target + if body != target: + return + + # Report release + XRToolsPointerEvent.released(self, target, last_collided_at) + XRToolsPointerEvent.exited(self, target, last_collided_at) + target = null diff --git a/scenes/main_menu/objects/settings_ui.tscn b/scenes/main_menu/objects/settings_ui.tscn index 4008be38..0aaee7c0 100644 --- a/scenes/main_menu/objects/settings_ui.tscn +++ b/scenes/main_menu/objects/settings_ui.tscn @@ -12,7 +12,7 @@ size = Vector3(0.7, 0.7, 0.02) [sub_resource type="BoxShape3D" id="BoxShape3D_7u64y"] -size = Vector3(0.65, 0.2, 0.5) +size = Vector3(0.65, 0.2, 0.650062) [node name="SettingsUI" type="Node3D"] script = ExtResource("3") @@ -25,8 +25,8 @@ surface_material_override/0 = ExtResource("2_jyjdc") [node name="Viewport2Din3D" parent="Screen" instance=ExtResource("1")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.015) screen_size = Vector2(0.625, 0.625) -viewport_size = Vector2(250, 250) scene = ExtResource("2") +viewport_size = Vector2(250, 250) [node name="CSGCylinder" type="CSGCylinder3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.9, 0) diff --git a/scenes/pickable_demo/objects/snap_tray.gd b/scenes/pickable_demo/objects/snap_tray.gd index 2d452e8f..52d47303 100644 --- a/scenes/pickable_demo/objects/snap_tray.gd +++ b/scenes/pickable_demo/objects/snap_tray.gd @@ -1,9 +1,6 @@ extends XRToolsPickable -signal pointer_pressed(at) - - ## Snap-tray active state @export var tray_active : bool = true: set = _set_tray_active @@ -16,20 +13,18 @@ signal pointer_pressed(at) ## Called when the node enters the scene tree for the first time. func _ready(): - # Connect to the pointer pressed signal - pointer_pressed.connect(_on_pointer_pressed) - # Update the tray_active state _update_tray_active() -## Handler for snap tray being pressed by pointer -func _on_pointer_pressed(_at : Vector3) -> void: - # Toggle tray_active - _set_tray_active(not tray_active) +# Handle pointer events +func pointer_event(event : XRToolsPointerEvent) -> void: + # When pressed, toggle the tray active + if event.event_type == XRToolsPointerEvent.Type.PRESSED: + _set_tray_active(not tray_active) -## Handler for tray_active property change +# Handler for tray_active property change func _set_tray_active(new_value : bool) -> void: tray_active = new_value if is_inside_tree(): diff --git a/scenes/pointer_demo/objects/color_change_cube.gd b/scenes/pointer_demo/objects/color_change_cube.gd index 67ea046c..6095f744 100644 --- a/scenes/pointer_demo/objects/color_change_cube.gd +++ b/scenes/pointer_demo/objects/color_change_cube.gd @@ -1,17 +1,11 @@ extends RigidBody3D -signal pointer_pressed(at) - - var _material := StandardMaterial3D.new() # Called when the node enters the scene tree for the first time. func _ready(): - # Connect pointer_pressed signals - connect("pointer_pressed",Callable(self,"_on_pointer_pressed")) - # Generate a random material color _set_random_color() @@ -19,10 +13,11 @@ func _ready(): $MeshInstance3D.material_override = _material -# Called when a user clicks on the cube using the pointer -func _on_pointer_pressed(_at: Vector3): - # Randomize the color - _set_random_color() +# Handle pointer events +func pointer_event(event : XRToolsPointerEvent) -> void: + # When pressed, randomize the color + if event.event_type == XRToolsPointerEvent.Type.PRESSED: + _set_random_color() # Sets a random color on the material diff --git a/scenes/pointer_demo/objects/color_change_cube.tscn b/scenes/pointer_demo/objects/color_change_cube.tscn index 21d1d94b..17e827a1 100644 --- a/scenes/pointer_demo/objects/color_change_cube.tscn +++ b/scenes/pointer_demo/objects/color_change_cube.tscn @@ -9,7 +9,7 @@ size = Vector3(0.5, 0.5, 0.5) size = Vector3(0.5, 0.5, 0.5) [node name="ColorChangeCube" type="RigidBody3D"] -collision_layer = 1048577 +collision_layer = 5242881 collision_mask = 0 freeze = true script = ExtResource("1") diff --git a/scenes/pointer_demo/objects/pointer_laser_hit_material.tres b/scenes/pointer_demo/objects/pointer_laser_hit_material.tres new file mode 100644 index 00000000..f38fe59a --- /dev/null +++ b/scenes/pointer_demo/objects/pointer_laser_hit_material.tres @@ -0,0 +1,6 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://dejjsphfajcg0"] + +[resource] +transparency = 1 +shading_mode = 0 +albedo_color = Color(0.12549, 0.12549, 1, 0.501961) diff --git a/scenes/pointer_demo/objects/pointer_laser_material.tres b/scenes/pointer_demo/objects/pointer_laser_material.tres new file mode 100644 index 00000000..51c2f4a3 --- /dev/null +++ b/scenes/pointer_demo/objects/pointer_laser_material.tres @@ -0,0 +1,5 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://cir8vmhqar2mo"] + +[resource] +shading_mode = 0 +albedo_color = Color(0, 0, 0.501961, 1) diff --git a/scenes/pointer_demo/objects/pointer_target_material.tres b/scenes/pointer_demo/objects/pointer_target_material.tres new file mode 100644 index 00000000..85ed1516 --- /dev/null +++ b/scenes/pointer_demo/objects/pointer_target_material.tres @@ -0,0 +1,6 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://djwuqg7105fg"] + +[resource] +transparency = 1 +shading_mode = 0 +albedo_color = Color(0.752941, 0.752941, 1, 0.501961) diff --git a/scenes/pointer_demo/pointer_demo.tscn b/scenes/pointer_demo/pointer_demo.tscn index 52be305c..97d0f3b9 100644 --- a/scenes/pointer_demo/pointer_demo.tscn +++ b/scenes/pointer_demo/pointer_demo.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=33 format=3 uid="uid://bfw18y0j2blo4"] +[gd_scene load_steps=34 format=3 uid="uid://bfw18y0j2blo4"] [ext_resource type="PackedScene" uid="uid://qbmx03iibuuu" path="res://addons/godot-xr-tools/staging/scene_base.tscn" id="1"] [ext_resource type="PackedScene" uid="uid://3a6wjr3a13vd" path="res://assets/meshes/teleport/teleport.tscn" id="2"] @@ -11,85 +11,79 @@ [ext_resource type="PackedScene" uid="uid://l2n30mpbkdyw" path="res://addons/godot-xr-tools/hands/scenes/lowpoly/right_hand_low.tscn" id="6_rnrhb"] [ext_resource type="PackedScene" uid="uid://bl2nuu3qhlb5k" path="res://addons/godot-xr-tools/functions/movement_direct.tscn" id="7"] [ext_resource type="PackedScene" uid="uid://diyu06cw06syv" path="res://addons/godot-xr-tools/player/player_body.tscn" id="8"] +[ext_resource type="Material" uid="uid://cir8vmhqar2mo" path="res://scenes/pointer_demo/objects/pointer_laser_material.tres" id="8_8kxbu"] [ext_resource type="PackedScene" uid="uid://b6bk2pj8vbj28" path="res://addons/godot-xr-tools/functions/movement_turn.tscn" id="9"] +[ext_resource type="Material" uid="uid://dejjsphfajcg0" path="res://scenes/pointer_demo/objects/pointer_laser_hit_material.tres" id="9_8ft5o"] [ext_resource type="PackedScene" uid="uid://deyk5frilshws" path="res://assets/meshes/control_pad/control_pad_location_right.tscn" id="9_qbaa8"] +[ext_resource type="Material" uid="uid://djwuqg7105fg" path="res://scenes/pointer_demo/objects/pointer_target_material.tres" id="10_fxi5i"] [ext_resource type="PackedScene" uid="uid://ca6c2h3xsflxf" path="res://assets/maps/holodeck_map.tscn" id="10_qlbta"] [ext_resource type="PackedScene" uid="uid://dgdb1texynduw" path="res://addons/godot-xr-tools/objects/virtual_keyboard.tscn" id="11"] [ext_resource type="PackedScene" uid="uid://nnse6wsxsjeo" path="res://scenes/pointer_demo/objects/display.tscn" id="12"] [ext_resource type="PackedScene" uid="uid://ct3p5sgwvkmva" path="res://assets/meshes/control_pad/control_pad.tscn" id="12_yae1p"] [ext_resource type="PackedScene" uid="uid://bk34216s7eynw" path="res://scenes/pointer_demo/objects/color_change_cube.tscn" id="15"] -[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_xm78w"] +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_8hr6n"] animation = &"Grip" -[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_gifwh"] +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_ybqq3"] animation = &"Grip" -[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_sjb06"] +[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_yf56w"] filter_enabled = true filters = ["Armature/Skeleton3D:Little_Distal_L", "Armature/Skeleton3D:Little_Intermediate_L", "Armature/Skeleton3D:Little_Metacarpal_L", "Armature/Skeleton3D:Little_Proximal_L", "Armature/Skeleton3D:Middle_Distal_L", "Armature/Skeleton3D:Middle_Intermediate_L", "Armature/Skeleton3D:Middle_Metacarpal_L", "Armature/Skeleton3D:Middle_Proximal_L", "Armature/Skeleton3D:Ring_Distal_L", "Armature/Skeleton3D:Ring_Intermediate_L", "Armature/Skeleton3D:Ring_Metacarpal_L", "Armature/Skeleton3D:Ring_Proximal_L", "Armature/Skeleton3D:Thumb_Distal_L", "Armature/Skeleton3D:Thumb_Metacarpal_L", "Armature/Skeleton3D:Thumb_Proximal_L", "Armature/Skeleton:Little_Distal_L", "Armature/Skeleton:Little_Intermediate_L", "Armature/Skeleton:Little_Proximal_L", "Armature/Skeleton:Middle_Distal_L", "Armature/Skeleton:Middle_Intermediate_L", "Armature/Skeleton:Middle_Proximal_L", "Armature/Skeleton:Ring_Distal_L", "Armature/Skeleton:Ring_Intermediate_L", "Armature/Skeleton:Ring_Proximal_L", "Armature/Skeleton:Thumb_Distal_L", "Armature/Skeleton:Thumb_Proximal_L"] -[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_uwvgp"] +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_c2siu"] animation = &"Grip 5" -[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_2q313"] +[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_tw4wh"] filter_enabled = true filters = ["Armature/Skeleton3D:Index_Distal_L", "Armature/Skeleton3D:Index_Intermediate_L", "Armature/Skeleton3D:Index_Metacarpal_L", "Armature/Skeleton3D:Index_Proximal_L", "Armature/Skeleton:Index_Distal_L", "Armature/Skeleton:Index_Intermediate_L", "Armature/Skeleton:Index_Proximal_L"] -[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_x3p60"] +[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_4l1td"] graph_offset = Vector2(-536, 11) -nodes/ClosedHand1/node = SubResource("AnimationNodeAnimation_xm78w") +nodes/ClosedHand1/node = SubResource("AnimationNodeAnimation_8hr6n") nodes/ClosedHand1/position = Vector2(-600, 300) -nodes/ClosedHand2/node = SubResource("AnimationNodeAnimation_gifwh") +nodes/ClosedHand2/node = SubResource("AnimationNodeAnimation_ybqq3") nodes/ClosedHand2/position = Vector2(-360, 300) -nodes/Grip/node = SubResource("AnimationNodeBlend2_sjb06") +nodes/Grip/node = SubResource("AnimationNodeBlend2_yf56w") nodes/Grip/position = Vector2(0, 20) -nodes/OpenHand/node = SubResource("AnimationNodeAnimation_uwvgp") +nodes/OpenHand/node = SubResource("AnimationNodeAnimation_c2siu") nodes/OpenHand/position = Vector2(-600, 100) -nodes/Trigger/node = SubResource("AnimationNodeBlend2_2q313") +nodes/Trigger/node = SubResource("AnimationNodeBlend2_tw4wh") nodes/Trigger/position = Vector2(-360, 20) node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"] -[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_v4bvk"] +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_e5hqe"] animation = &"Grip" -[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_c6gl0"] +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_3sod0"] animation = &"Grip" -[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_m833o"] +[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_ennjd"] filter_enabled = true filters = ["Armature/Skeleton3D:Little_Distal_R", "Armature/Skeleton3D:Little_Intermediate_R", "Armature/Skeleton3D:Little_Metacarpal_R", "Armature/Skeleton3D:Little_Proximal_R", "Armature/Skeleton3D:Middle_Distal_R", "Armature/Skeleton3D:Middle_Intermediate_R", "Armature/Skeleton3D:Middle_Metacarpal_R", "Armature/Skeleton3D:Middle_Proximal_R", "Armature/Skeleton3D:Ring_Distal_R", "Armature/Skeleton3D:Ring_Intermediate_R", "Armature/Skeleton3D:Ring_Metacarpal_R", "Armature/Skeleton3D:Ring_Proximal_R", "Armature/Skeleton3D:Thumb_Distal_R", "Armature/Skeleton3D:Thumb_Metacarpal_R", "Armature/Skeleton3D:Thumb_Proximal_R", "Armature/Skeleton:Little_Distal_R", "Armature/Skeleton:Little_Intermediate_R", "Armature/Skeleton:Little_Proximal_R", "Armature/Skeleton:Middle_Distal_R", "Armature/Skeleton:Middle_Intermediate_R", "Armature/Skeleton:Middle_Proximal_R", "Armature/Skeleton:Ring_Distal_R", "Armature/Skeleton:Ring_Intermediate_R", "Armature/Skeleton:Ring_Proximal_R", "Armature/Skeleton:Thumb_Distal_R", "Armature/Skeleton:Thumb_Proximal_R"] -[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_v53to"] +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_xnghj"] animation = &"Grip 5" -[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_nt003"] +[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_umwmp"] filter_enabled = true filters = ["Armature/Skeleton3D:Index_Distal_R", "Armature/Skeleton3D:Index_Intermediate_R", "Armature/Skeleton3D:Index_Metacarpal_R", "Armature/Skeleton3D:Index_Proximal_R", "Armature/Skeleton:Index_Distal_R", "Armature/Skeleton:Index_Intermediate_R", "Armature/Skeleton:Index_Proximal_R"] -[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_vttd2"] +[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_ylpnl"] graph_offset = Vector2(-552.664, 107.301) -nodes/ClosedHand1/node = SubResource("AnimationNodeAnimation_v4bvk") +nodes/ClosedHand1/node = SubResource("AnimationNodeAnimation_e5hqe") nodes/ClosedHand1/position = Vector2(-600, 300) -nodes/ClosedHand2/node = SubResource("AnimationNodeAnimation_c6gl0") +nodes/ClosedHand2/node = SubResource("AnimationNodeAnimation_3sod0") nodes/ClosedHand2/position = Vector2(-360, 300) -nodes/Grip/node = SubResource("AnimationNodeBlend2_m833o") +nodes/Grip/node = SubResource("AnimationNodeBlend2_ennjd") nodes/Grip/position = Vector2(0, 40) -nodes/OpenHand/node = SubResource("AnimationNodeAnimation_v53to") +nodes/OpenHand/node = SubResource("AnimationNodeAnimation_xnghj") nodes/OpenHand/position = Vector2(-600, 100) -nodes/Trigger/node = SubResource("AnimationNodeBlend2_nt003") +nodes/Trigger/node = SubResource("AnimationNodeBlend2_umwmp") nodes/Trigger/position = Vector2(-360, 40) node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"] -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_87ic1"] -shading_mode = 0 -albedo_color = Color(0, 0, 0.501961, 1) - -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_gdrki"] -transparency = 1 -shading_mode = 0 -albedo_color = Color(0.12549, 0.12549, 1, 0.501961) - [node name="PointerDemo" instance=ExtResource("1")] script = ExtResource("2_pbiwr") @@ -127,13 +121,22 @@ mask = 4194304 push_bodies = false [node name="AnimationTree" parent="XROrigin3D/LeftHand/LeftHand" index="1"] -tree_root = SubResource("AnimationNodeBlendTree_x3p60") +tree_root = SubResource("AnimationNodeBlendTree_4l1td") [node name="MovementDirect" parent="XROrigin3D/LeftHand" index="1" instance=ExtResource("7")] strafe = true [node name="ControlPadLocationLeft" parent="XROrigin3D/LeftHand" index="2" instance=ExtResource("6_omyut")] +[node name="FunctionPointer" parent="XROrigin3D/LeftHand" index="3" instance=ExtResource("5")] +show_laser = 2 +laser_length = 1 +laser_material = ExtResource("8_8kxbu") +laser_hit_material = ExtResource("9_8ft5o") +show_target = true +target_radius = 0.01 +target_material = ExtResource("10_fxi5i") + [node name="RightHand" parent="XROrigin3D/RightHand" index="0" instance=ExtResource("6_rnrhb")] [node name="Skeleton3D" parent="XROrigin3D/RightHand/RightHand/Hand_Nails_low_R/Armature" index="0"] @@ -168,7 +171,7 @@ mask = 4194304 push_bodies = false [node name="AnimationTree" parent="XROrigin3D/RightHand/RightHand" index="1"] -tree_root = SubResource("AnimationNodeBlendTree_vttd2") +tree_root = SubResource("AnimationNodeBlendTree_ylpnl") [node name="MovementDirect" parent="XROrigin3D/RightHand" index="1" instance=ExtResource("7")] @@ -176,17 +179,18 @@ tree_root = SubResource("AnimationNodeBlendTree_vttd2") [node name="ControlPadLocationRight" parent="XROrigin3D/RightHand" index="3" instance=ExtResource("9_qbaa8")] -[node name="PlayerBody" parent="XROrigin3D" index="3" instance=ExtResource("8")] - -[node name="FunctionPointer" parent="XROrigin3D" index="4" instance=ExtResource("5")] +[node name="FunctionPointer" parent="XROrigin3D/RightHand" index="4" instance=ExtResource("5")] +show_laser = 2 laser_length = 1 -laser_material = SubResource("StandardMaterial3D_87ic1") -laser_hit_material = SubResource("StandardMaterial3D_gdrki") +laser_material = ExtResource("8_8kxbu") +laser_hit_material = ExtResource("9_8ft5o") show_target = true -target_radius = 0.02 -target_material = SubResource("StandardMaterial3D_gdrki") +target_radius = 0.01 +target_material = ExtResource("10_fxi5i") + +[node name="PlayerBody" parent="XROrigin3D" index="3" instance=ExtResource("8")] -[node name="ControlPad" parent="XROrigin3D" index="5" instance=ExtResource("12_yae1p")] +[node name="ControlPad" parent="XROrigin3D" index="4" instance=ExtResource("12_yae1p")] [node name="HolodeckMap" parent="." index="1" instance=ExtResource("10_qlbta")] @@ -199,7 +203,8 @@ title = ExtResource("4") transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, -3) [node name="VirtualKeyboard" parent="." index="4" instance=ExtResource("11")] -transform = Transform3D(1, 0, 0, 0, 0.965926, 0.258819, 0, -0.258819, 0.965926, 0, 1, -2) +transform = Transform3D(1, 0, 0, 0, 0.5, 0.866025, 0, -0.866025, 0.5, 0, 0.9, -2) +screen_size = Vector2(0.5, 0.244) [node name="ColorChangeCube1" parent="." index="5" instance=ExtResource("15")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 2.5, -3)