mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2026-01-04 15:00:09 +01:00
Examples about (multi)touch events
This commit is contained in:
151
misc/multitouch_cubes/CubeScene.tscn
Normal file
151
misc/multitouch_cubes/CubeScene.tscn
Normal file
@@ -0,0 +1,151 @@
|
||||
[gd_scene load_steps=3 format=1]
|
||||
|
||||
[sub_resource type="FixedMaterial" id=1]
|
||||
|
||||
flags/visible = true
|
||||
flags/double_sided = false
|
||||
flags/invert_faces = false
|
||||
flags/unshaded = false
|
||||
flags/on_top = false
|
||||
flags/lightmap_on_uv2 = true
|
||||
flags/colarray_is_srgb = true
|
||||
params/blend_mode = 0
|
||||
params/depth_draw = 1
|
||||
params/line_width = 0.0
|
||||
fixed_flags/use_alpha = false
|
||||
fixed_flags/use_color_array = false
|
||||
fixed_flags/use_point_size = false
|
||||
fixed_flags/discard_alpha = false
|
||||
fixed_flags/use_xy_normalmap = false
|
||||
params/diffuse = Color( 0.259476, 0.699219, 0.379718, 1 )
|
||||
params/specular = Color( 1, 1, 1, 1 )
|
||||
params/emission = Color( 0, 0, 0, 1 )
|
||||
params/specular_exp = 40
|
||||
params/detail_mix = 1.0
|
||||
params/normal_depth = 1
|
||||
params/shader = 0
|
||||
params/shader_param = 0.5
|
||||
params/glow = 0
|
||||
params/point_size = 1.0
|
||||
uv_xform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
textures/diffuse_tc = 0
|
||||
textures/detail_tc = 0
|
||||
textures/specular_tc = 0
|
||||
textures/emission_tc = 0
|
||||
textures/specular_exp_tc = 0
|
||||
textures/glow_tc = 0
|
||||
textures/normal_tc = 0
|
||||
textures/shade_param_tc = 0
|
||||
|
||||
[sub_resource type="Environment" id=2]
|
||||
|
||||
ambient_light/enabled = true
|
||||
ambient_light/color = Color( 0.601563, 0.696429, 1, 1 )
|
||||
ambient_light/energy = 0.5
|
||||
fxaa/enabled = true
|
||||
background/mode = 1
|
||||
background/color = Color( 0, 0, 0, 1 )
|
||||
background/energy = 1.0
|
||||
background/scale = 1.0
|
||||
background/glow = 0.0
|
||||
background/canvas_max_layer = null
|
||||
glow/enabled = false
|
||||
glow/blur_passes = 1
|
||||
glow/blur_scale = 1
|
||||
glow/blur_strength = 1
|
||||
glow/blur_blend_mode = null
|
||||
glow/bloom = 0.0
|
||||
glow/bloom_treshold = 0.5
|
||||
dof_blur/enabled = false
|
||||
dof_blur/blur_passes = 1
|
||||
dof_blur/begin = 100.0
|
||||
dof_blur/range = 10.0
|
||||
hdr/enabled = false
|
||||
hdr/tonemapper = 0
|
||||
hdr/exposure = 0.4
|
||||
hdr/white = 1.0
|
||||
hdr/glow_treshold = 0.95
|
||||
hdr/glow_scale = 0.2
|
||||
hdr/min_luminance = 0.4
|
||||
hdr/max_luminance = 8.0
|
||||
hdr/exposure_adj_speed = 0.5
|
||||
fog/enabled = false
|
||||
fog/begin = 100.0
|
||||
fog/begin_color = Color( 0, 0, 0, 1 )
|
||||
fog/end_color = Color( 0, 0, 0, 1 )
|
||||
fog/attenuation = 1.0
|
||||
fog/bg = true
|
||||
bcs/enabled = false
|
||||
bcs/brightness = 1.0
|
||||
bcs/contrast = 1.0
|
||||
bcs/saturation = 1.0
|
||||
srgb/enabled = false
|
||||
|
||||
[node name="Spatial" type="Spatial"]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
|
||||
[node name="TestCube" type="TestCube" parent="."]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
transform/local = Transform( 0.707107, 0, -0.707107, -0.353553, 0.866025, -0.353553, 0.612372, 0.5, 0.612372, 0, 0, 0 )
|
||||
layers = 1
|
||||
geometry/visible = true
|
||||
geometry/material_override = SubResource( 1 )
|
||||
geometry/cast_shadow = 1
|
||||
geometry/receive_shadows = true
|
||||
geometry/range_begin = 0.0
|
||||
geometry/range_end = 0.0
|
||||
geometry/extra_cull_margin = 0.0
|
||||
geometry/billboard = false
|
||||
geometry/billboard_y = false
|
||||
geometry/depth_scale = false
|
||||
geometry/visible_in_all_rooms = false
|
||||
geometry/use_baked_light = false
|
||||
geometry/baked_light_tex_id = 0
|
||||
|
||||
[node name="Camera" type="Camera" parent="."]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
transform/local = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 7.09558 )
|
||||
projection = 0
|
||||
fov = 50.0
|
||||
near = 0.1
|
||||
far = 100.0
|
||||
keep_aspect = 1
|
||||
current = false
|
||||
visible_layers = 1048575
|
||||
environment = null
|
||||
h_offset = 0.0
|
||||
v_offset = 0.0
|
||||
|
||||
[node name="DirectionalLight" type="DirectionalLight" parent="."]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
transform/local = Transform( 0.926535, 0.11439, -0.358396, 0.199614, 0.658013, 0.726067, 0.318884, -0.744267, 0.586839, 0, 4.14991, 0 )
|
||||
layers = 1
|
||||
params/enabled = true
|
||||
params/editor_only = false
|
||||
params/bake_mode = 0
|
||||
params/energy = 1.0
|
||||
colors/diffuse = Color( 1, 1, 1, 1 )
|
||||
colors/specular = Color( 1, 1, 1, 1 )
|
||||
shadow/shadow = false
|
||||
shadow/darkening = 0.0
|
||||
shadow/z_offset = 0.05
|
||||
shadow/z_slope_scale = 0.0
|
||||
shadow/esm_multiplier = 60.0
|
||||
shadow/blur_passes = 1.0
|
||||
projector = null
|
||||
operator = 0
|
||||
shadow/mode = 0
|
||||
shadow/max_distance = 0.0
|
||||
shadow/split_weight = 0.5
|
||||
shadow/zoffset_scale = 2.0
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
environment = SubResource( 2 )
|
||||
|
||||
|
||||
133
misc/multitouch_cubes/GestureArea.gd
Normal file
133
misc/multitouch_cubes/GestureArea.gd
Normal file
@@ -0,0 +1,133 @@
|
||||
extends Control
|
||||
|
||||
export(NodePath) var target
|
||||
export var min_scale = 0.1
|
||||
export var max_scale = 3.0
|
||||
export var one_finger_rot_x = true
|
||||
export var one_finger_rot_y = true
|
||||
export var two_fingers_rot_z = true
|
||||
export var two_fingers_zoom = true
|
||||
|
||||
var base_state
|
||||
var curr_state
|
||||
|
||||
var target_node
|
||||
|
||||
# We keep here a copy of the state before the number of fingers changed to avoid accumulation errors
|
||||
var base_xform
|
||||
|
||||
func _ready():
|
||||
base_state = {}
|
||||
curr_state = {}
|
||||
target_node = get_node(target)
|
||||
set_process_unhandled_input(true)
|
||||
|
||||
# Using unhandled input since it's the method that has empirically proven to work the best
|
||||
func _unhandled_input(event):
|
||||
# We must start touching inside, but we can drag or unpress outside
|
||||
if !(event.type == InputEvent.SCREEN_DRAG ||
|
||||
(event.type == InputEvent.SCREEN_TOUCH && (!event.pressed || get_global_rect().has_point(Vector2(event.x, event.y))))):
|
||||
return
|
||||
|
||||
var finger_count_changed = false
|
||||
var finger_count = base_state.size()
|
||||
|
||||
if finger_count == 0:
|
||||
# No fingers => Accept press
|
||||
|
||||
if event.type == InputEvent.SCREEN_TOUCH:
|
||||
if event.pressed:
|
||||
# A finger started touching
|
||||
|
||||
base_state = {
|
||||
event.index: Vector2(event.x, event.y),
|
||||
}
|
||||
|
||||
elif finger_count == 1:
|
||||
# One finger => For rotating around X and Y
|
||||
# Accept one more press, unpress or drag
|
||||
|
||||
if event.type == InputEvent.SCREEN_TOUCH:
|
||||
if event.pressed:
|
||||
# One more finger started touching
|
||||
|
||||
# Reset the base state to the only current and the new fingers
|
||||
base_state = {
|
||||
curr_state.keys()[0]: curr_state.values()[0],
|
||||
event.index: Vector2(event.x, event.y),
|
||||
}
|
||||
else:
|
||||
if base_state.has(event.index):
|
||||
# Only touching finger released
|
||||
|
||||
base_state.clear()
|
||||
|
||||
elif event.type == InputEvent.SCREEN_DRAG:
|
||||
if curr_state.has(event.index):
|
||||
# Touching finger dragged
|
||||
|
||||
var unit_drag = _px2unit(base_state[base_state.keys()[0]] - Vector2(event.x, event.y))
|
||||
if one_finger_rot_x:
|
||||
target_node.global_rotate(Vector3(0, 1, 0), deg2rad(180.0 * unit_drag.x))
|
||||
if one_finger_rot_y:
|
||||
target_node.global_rotate(Vector3(1, 0, 0), deg2rad(180.0 * unit_drag.y))
|
||||
# Since rotating around two axes, we have to reset the base constantly
|
||||
curr_state[event.index] = Vector2(event.x, event.y)
|
||||
base_state[event.index] = Vector2(event.x, event.y)
|
||||
base_xform = target_node.get_transform()
|
||||
|
||||
elif finger_count == 2:
|
||||
# Two fingers => To pinch-zoom and rotate around Z
|
||||
# Accept unpress or drag
|
||||
|
||||
if event.type == InputEvent.SCREEN_TOUCH:
|
||||
if !event.pressed && base_state.has(event.index):
|
||||
# Some known touching finger released
|
||||
|
||||
# Remove released finger from the base state
|
||||
base_state.erase(event.index)
|
||||
# Reset the base state to the now only toyching finger
|
||||
base_state = {
|
||||
curr_state.keys()[0]: curr_state.values()[0],
|
||||
}
|
||||
|
||||
elif event.type == InputEvent.SCREEN_DRAG:
|
||||
if curr_state.has(event.index):
|
||||
# Some known touching finger dragged
|
||||
|
||||
# Update
|
||||
curr_state[event.index] = Vector2(event.x, event.y)
|
||||
|
||||
# Compute base and current inter-finger vectors
|
||||
var base_segment = base_state[base_state.keys()[0]] - base_state[base_state.keys()[1]]
|
||||
var new_segment = curr_state[curr_state.keys()[0]] - curr_state[curr_state.keys()[1]]
|
||||
|
||||
# Get the base scale from the base matrix
|
||||
var base_scale = Vector3(base_xform.basis.x.x, base_xform.basis.y.y, base_xform.basis.z.z).length()
|
||||
|
||||
if two_fingers_zoom:
|
||||
# Compute the new scale limiting it and taking into account the base scale
|
||||
var new_scale = clamp(base_scale * (new_segment.length() / base_segment.length()), min_scale, max_scale) / base_scale
|
||||
target_node.set_transform(base_xform.scaled(new_scale * Vector3(1, 1, 1)))
|
||||
else:
|
||||
target_node.set_transform(base_xform)
|
||||
|
||||
if two_fingers_rot_z:
|
||||
# Apply rotation between base inter-finger vector and the current one
|
||||
var rot = new_segment.angle_to(base_segment)
|
||||
target_node.global_rotate(Vector3(0, 0, 1), rot)
|
||||
|
||||
# Finger count changed?
|
||||
if base_state.size() != finger_count:
|
||||
# Copy new base state to the current state
|
||||
curr_state = {}
|
||||
for idx in base_state.keys():
|
||||
curr_state[idx] = base_state[idx]
|
||||
# Remember the base transform
|
||||
base_xform = target_node.get_transform()
|
||||
|
||||
# Converts a vector in pixels to a unitary magnitude,
|
||||
# considering the number of pixels of the shorter axis is the unit
|
||||
func _px2unit(v):
|
||||
var shortest = min(get_size().x, get_size().y)
|
||||
return v * (1.0 / shortest)
|
||||
256
misc/multitouch_cubes/Main.tscn
Normal file
256
misc/multitouch_cubes/Main.tscn
Normal file
@@ -0,0 +1,256 @@
|
||||
[gd_scene load_steps=3 format=1]
|
||||
|
||||
[ext_resource path="res://GestureArea.gd" type="Script" id=1]
|
||||
[ext_resource path="res://CubeScene.tscn" type="PackedScene" id=2]
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer"]
|
||||
|
||||
anchor/right = 1
|
||||
anchor/bottom = 1
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 0.0
|
||||
margin/bottom = 0.0
|
||||
alignment = 0
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 512.0
|
||||
margin/bottom = 254.0
|
||||
alignment = 0
|
||||
|
||||
[node name="GestureArea" type="Control" parent="HBoxContainer"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 254.0
|
||||
margin/bottom = 254.0
|
||||
script/script = ExtResource( 1 )
|
||||
target = NodePath("Viewport/Spatial/TestCube")
|
||||
min_scale = 0.1
|
||||
max_scale = 3.0
|
||||
one_finger_rot_x = true
|
||||
one_finger_rot_y = false
|
||||
two_fingers_rot_z = false
|
||||
two_fingers_zoom = false
|
||||
|
||||
[node name="Viewport" type="Viewport" parent="HBoxContainer/GestureArea"]
|
||||
|
||||
rect = Rect2( 0, 0, 254, 254 )
|
||||
own_world = true
|
||||
world = null
|
||||
transparent_bg = false
|
||||
render_target/enabled = false
|
||||
render_target/v_flip = false
|
||||
render_target/clear_on_new_frame = true
|
||||
render_target/filter = false
|
||||
render_target/gen_mipmaps = false
|
||||
render_target/update_mode = 2
|
||||
audio_listener/enable_2d = false
|
||||
audio_listener/enable_3d = false
|
||||
physics/object_picking = false
|
||||
gui/disable_input = false
|
||||
|
||||
[node name="Spatial" parent="HBoxContainer/GestureArea/Viewport" instance=ExtResource( 2 )]
|
||||
|
||||
[node name="Label" type="Label" parent="HBoxContainer/GestureArea"]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 7.0
|
||||
margin/top = 6.0
|
||||
margin/right = 157.0
|
||||
margin/bottom = 20.0
|
||||
text = "One-finger rot around X"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="GestureArea_1" type="Control" parent="HBoxContainer"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 258.0
|
||||
margin/top = 0.0
|
||||
margin/right = 512.0
|
||||
margin/bottom = 254.0
|
||||
script/script = ExtResource( 1 )
|
||||
target = NodePath("Viewport/Spatial/TestCube")
|
||||
min_scale = 0.1
|
||||
max_scale = 3.0
|
||||
one_finger_rot_x = true
|
||||
one_finger_rot_y = true
|
||||
two_fingers_rot_z = false
|
||||
two_fingers_zoom = false
|
||||
|
||||
[node name="Viewport" type="Viewport" parent="HBoxContainer/GestureArea_1"]
|
||||
|
||||
rect = Rect2( 0, 0, 254, 254 )
|
||||
own_world = true
|
||||
world = null
|
||||
transparent_bg = false
|
||||
render_target/enabled = false
|
||||
render_target/v_flip = false
|
||||
render_target/clear_on_new_frame = true
|
||||
render_target/filter = false
|
||||
render_target/gen_mipmaps = false
|
||||
render_target/update_mode = 2
|
||||
audio_listener/enable_2d = false
|
||||
audio_listener/enable_3d = false
|
||||
physics/object_picking = false
|
||||
gui/disable_input = false
|
||||
|
||||
[node name="Spatial" parent="HBoxContainer/GestureArea_1/Viewport" instance=ExtResource( 2 )]
|
||||
|
||||
[node name="Label2" type="Label" parent="HBoxContainer/GestureArea_1"]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 15.0
|
||||
margin/top = 6.0
|
||||
margin/right = 55.0
|
||||
margin/bottom = 20.0
|
||||
text = "One-finger rot around X and Y"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="HBoxContainer_1" type="HBoxContainer" parent="."]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 258.0
|
||||
margin/right = 512.0
|
||||
margin/bottom = 512.0
|
||||
alignment = 0
|
||||
|
||||
[node name="GestureArea" type="Control" parent="HBoxContainer_1"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 254.0
|
||||
margin/bottom = 254.0
|
||||
script/script = ExtResource( 1 )
|
||||
target = NodePath("Viewport/Spatial/TestCube")
|
||||
min_scale = 0.1
|
||||
max_scale = 3.0
|
||||
one_finger_rot_x = true
|
||||
one_finger_rot_y = true
|
||||
two_fingers_rot_z = true
|
||||
two_fingers_zoom = false
|
||||
|
||||
[node name="Viewport" type="Viewport" parent="HBoxContainer_1/GestureArea"]
|
||||
|
||||
rect = Rect2( 0, 0, 254, 254 )
|
||||
own_world = true
|
||||
world = null
|
||||
transparent_bg = false
|
||||
render_target/enabled = false
|
||||
render_target/v_flip = false
|
||||
render_target/clear_on_new_frame = true
|
||||
render_target/filter = false
|
||||
render_target/gen_mipmaps = false
|
||||
render_target/update_mode = 2
|
||||
audio_listener/enable_2d = false
|
||||
audio_listener/enable_3d = false
|
||||
physics/object_picking = false
|
||||
gui/disable_input = false
|
||||
|
||||
[node name="Spatial" parent="HBoxContainer_1/GestureArea/Viewport" instance=ExtResource( 2 )]
|
||||
|
||||
[node name="Label2" type="Label" parent="HBoxContainer_1/GestureArea"]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 7.0
|
||||
margin/top = 12.0
|
||||
margin/right = 47.0
|
||||
margin/bottom = 26.0
|
||||
text = "One-finger X/Y rot + two-finger Z rot"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="GestureArea_1" type="Control" parent="HBoxContainer_1"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 258.0
|
||||
margin/top = 0.0
|
||||
margin/right = 512.0
|
||||
margin/bottom = 254.0
|
||||
script/script = ExtResource( 1 )
|
||||
target = NodePath("Viewport/Spatial/TestCube")
|
||||
min_scale = 0.1
|
||||
max_scale = 3.0
|
||||
one_finger_rot_x = true
|
||||
one_finger_rot_y = true
|
||||
two_fingers_rot_z = true
|
||||
two_fingers_zoom = true
|
||||
|
||||
[node name="Viewport" type="Viewport" parent="HBoxContainer_1/GestureArea_1"]
|
||||
|
||||
rect = Rect2( 0, 0, 254, 254 )
|
||||
own_world = true
|
||||
world = null
|
||||
transparent_bg = false
|
||||
render_target/enabled = false
|
||||
render_target/v_flip = false
|
||||
render_target/clear_on_new_frame = true
|
||||
render_target/filter = false
|
||||
render_target/gen_mipmaps = false
|
||||
render_target/update_mode = 2
|
||||
audio_listener/enable_2d = false
|
||||
audio_listener/enable_3d = false
|
||||
physics/object_picking = false
|
||||
gui/disable_input = false
|
||||
|
||||
[node name="Spatial" parent="HBoxContainer_1/GestureArea_1/Viewport" instance=ExtResource( 2 )]
|
||||
|
||||
[node name="Label3" type="Label" parent="HBoxContainer_1/GestureArea_1"]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 15.0
|
||||
margin/top = 12.0
|
||||
margin/right = 55.0
|
||||
margin/bottom = 26.0
|
||||
text = "One-finger X/Y, two-finger Z + pinch"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
|
||||
18
misc/multitouch_cubes/engine.cfg
Normal file
18
misc/multitouch_cubes/engine.cfg
Normal file
@@ -0,0 +1,18 @@
|
||||
[application]
|
||||
|
||||
name="InteractiveCubes"
|
||||
main_scene="res://Main.tscn"
|
||||
icon="res://icon.png"
|
||||
|
||||
[display]
|
||||
|
||||
width=512
|
||||
height=512
|
||||
|
||||
[physics_2d]
|
||||
|
||||
motion_fix_enabled=true
|
||||
|
||||
[render]
|
||||
|
||||
default_clear_color=#ff1d2232
|
||||
BIN
misc/multitouch_cubes/icon.png
Normal file
BIN
misc/multitouch_cubes/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
1
misc/multitouch_cubes/icon.png.flags
Normal file
1
misc/multitouch_cubes/icon.png.flags
Normal file
@@ -0,0 +1 @@
|
||||
gen_mipmaps=false
|
||||
23
misc/multitouch_view/Main.gd
Normal file
23
misc/multitouch_view/Main.gd
Normal file
@@ -0,0 +1,23 @@
|
||||
extends Node2D
|
||||
|
||||
func _ready():
|
||||
set_process(true)
|
||||
|
||||
func _process(delta):
|
||||
# To keep redrawing on every frame
|
||||
update()
|
||||
|
||||
func _draw():
|
||||
# Get the touch helper singleton
|
||||
var touch_helper = get_node("/root/TouchHelper")
|
||||
# Draw every pointer as a circle
|
||||
for ptr_id in touch_helper.state.keys():
|
||||
var pos = touch_helper.state[ptr_id]
|
||||
var color = _get_color_for_ptr_id(ptr_id)
|
||||
color.a = 0.75
|
||||
draw_circle(pos, 40.0, color)
|
||||
|
||||
# Just a way of getting different colors
|
||||
func _get_color_for_ptr_id(id):
|
||||
var x = (id % 7) + 1
|
||||
return Color(float(bool(x & 1)), float(bool(x & 2)), float(bool(x & 4)))
|
||||
10
misc/multitouch_view/Main.tscn
Normal file
10
misc/multitouch_view/Main.tscn
Normal file
@@ -0,0 +1,10 @@
|
||||
[gd_scene load_steps=2 format=1]
|
||||
|
||||
[ext_resource path="res://Main.gd" type="Script" id=1]
|
||||
|
||||
[node name="Main" type="Node2D"]
|
||||
|
||||
visibility/blend_mode = 1
|
||||
script/script = ExtResource( 1 )
|
||||
|
||||
|
||||
45
misc/multitouch_view/TouchHelper.gd
Normal file
45
misc/multitouch_view/TouchHelper.gd
Normal file
@@ -0,0 +1,45 @@
|
||||
# This will track the position of every pointer in its public `state` property, which is a
|
||||
# Dictionary, in which each key is a pointer id (integer) and each value its position (Vector2).
|
||||
# It works by listening to input events not handled by other means.
|
||||
# It also remaps the pointer indices coming from the OS to the lowest available to be friendlier.
|
||||
# It can be conveniently setup as a singleton.
|
||||
|
||||
extends Node
|
||||
|
||||
var state = {}
|
||||
var _os2own = {}
|
||||
|
||||
func _ready():
|
||||
set_process_unhandled_input(true)
|
||||
|
||||
func _unhandled_input(event):
|
||||
if event.type == InputEvent.SCREEN_TOUCH:
|
||||
if event.pressed:
|
||||
# Down
|
||||
if !_os2own.has(event.index): # Defensively discard index if already known
|
||||
var ptr_id = _find_free_pointer_id()
|
||||
state[ptr_id] = Vector2(event.x, event.y)
|
||||
_os2own[event.index] = ptr_id
|
||||
else:
|
||||
# Up
|
||||
if _os2own.has(event.index): # Defensively discard index if not known
|
||||
var ptr_id = _os2own[event.index]
|
||||
state.erase(ptr_id)
|
||||
_os2own.erase(event.index)
|
||||
return true
|
||||
|
||||
elif event.type == InputEvent.SCREEN_DRAG:
|
||||
# Move
|
||||
if _os2own.has(event.index): # Defensively discard index if not known
|
||||
var ptr_id = _os2own[event.index]
|
||||
state[ptr_id] = Vector2(event.x, event.y)
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func _find_free_pointer_id():
|
||||
var used = state.keys()
|
||||
var i = 0
|
||||
while i in used:
|
||||
i += 1
|
||||
return i
|
||||
17
misc/multitouch_view/engine.cfg
Normal file
17
misc/multitouch_view/engine.cfg
Normal file
@@ -0,0 +1,17 @@
|
||||
[application]
|
||||
|
||||
name="TouchesView"
|
||||
main_scene="res://Main.tscn"
|
||||
icon="res://icon.png"
|
||||
|
||||
[autoload]
|
||||
|
||||
TouchHelper="*res://TouchHelper.gd"
|
||||
|
||||
[physics_2d]
|
||||
|
||||
motion_fix_enabled=true
|
||||
|
||||
[render]
|
||||
|
||||
default_clear_color=#ff1d2232
|
||||
BIN
misc/multitouch_view/icon.png
Normal file
BIN
misc/multitouch_view/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
1
misc/multitouch_view/icon.png.flags
Normal file
1
misc/multitouch_view/icon.png.flags
Normal file
@@ -0,0 +1 @@
|
||||
gen_mipmaps=false
|
||||
Reference in New Issue
Block a user