diff --git a/controller/mouse_actions.gd b/controller/mouse_actions.gd
index 90de043..8b02732 100644
--- a/controller/mouse_actions.gd
+++ b/controller/mouse_actions.gd
@@ -37,6 +37,13 @@ var _resize_snapshot: Dictionary # { Vertex -> Vector2 } positions at drag sta
var _edge_mode_pending_id: int = Globals.NOT_FOUND
var _edge_mode_pending_click_pos: Vector2 = Vector2.ZERO
+# Mobile
+@export var long_press_duration := 0.5
+@export var drag_deadzone := 15.0
+var _is_touching := false
+var _touch_time := 0.0
+var _touch_start_pos: Vector2
+
# ----------------------------------------------------------------------------
# Input routing
# ----------------------------------------------------------------------------
@@ -65,6 +72,29 @@ func _ready() -> void:
Globals.app_state_changed.connect(_refresh_canvas_cursor_after_tool_change)
_sync_eraser_cursor()
+func _process(delta: float) -> void:
+ # Checking for long press
+ if _is_touching and not Globals.current_state == Globals.State.PAN:
+ _touch_time += delta
+ if _touch_time >= long_press_duration:
+ _is_touching = false
+ _trigger_right_click_event(_touch_start_pos)
+
+## Triggers a right click press & release in the godot input pipeline.
+## This allows the code to handle the action as it would normally.
+func _trigger_right_click_event(pos: Vector2):
+ var right_click = InputEventMouseButton.new()
+ right_click.button_index = MOUSE_BUTTON_RIGHT
+ right_click.pressed = true
+ right_click.position = pos
+ right_click.global_position = pos
+
+ get_viewport().push_input(right_click,true)
+
+ var right_release = right_click.duplicate()
+ right_release.pressed = false
+ get_viewport().push_input(right_release, true)
+
func _on_ctrl_action_released(event: InputEvent) -> void:
if Globals.current_state == Globals.State.EDGE and not controller.link_ctrl_chain:
@@ -73,6 +103,18 @@ func _on_ctrl_action_released(event: InputEvent) -> void:
func _unhandled_input(event: InputEvent) -> void:
+ # Handling Mobile right click as long press
+ if event is InputEventScreenTouch:
+ if event.pressed:
+ _is_touching = true
+ _touch_time = 0.0
+ _touch_start_pos = event.position
+ else:
+ _is_touching = false
+ elif event is InputEventScreenDrag and _is_touching:
+ if event.position.distance_to(_touch_start_pos) > drag_deadzone:
+ _is_touching = false
+
if event is InputEventKey and event.is_action_pressed("ui_cancel") and _eraser.active:
_eraser.cancel_to_selection()
get_viewport().set_input_as_handled()
diff --git a/export_presets.cfg b/export_presets.cfg
index 1543a4f..e178e75 100644
--- a/export_presets.cfg
+++ b/export_presets.cfg
@@ -3,7 +3,6 @@
name="Web"
platform="Web"
runnable=true
-advanced_options=false
dedicated_server=false
custom_features=""
export_filter="all_resources"
@@ -11,6 +10,11 @@ include_filter=""
exclude_filter=""
export_path="export/Graphos.html"
patches=PackedStringArray()
+patch_delta_encoding=false
+patch_delta_compression_level_zstd=19
+patch_delta_min_reduction=0.1
+patch_delta_include_filters="*"
+patch_delta_exclude_filters=""
encryption_include_filters=""
encryption_exclude_filters=""
seed=0
@@ -28,7 +32,8 @@ vram_texture_compression/for_desktop=true
vram_texture_compression/for_mobile=false
html/export_icon=true
html/custom_html_shell=""
-html/head_include="\n"
+html/head_include="
+"
html/canvas_resize_policy=2
html/focus_canvas_on_start=true
html/experimental_virtual_keyboard=false
diff --git a/scenes/algorithm_controls/algorithm_controls.gd b/scenes/algorithm_controls/algorithm_controls.gd
index ff1d9dc..04c38cd 100644
--- a/scenes/algorithm_controls/algorithm_controls.gd
+++ b/scenes/algorithm_controls/algorithm_controls.gd
@@ -49,10 +49,19 @@ func _resolve_progress_fill() -> ProgressBar:
func _snap_to_bottom_center() -> void:
await get_tree().process_frame
var vp := get_viewport().get_visible_rect().size
- position = Vector2(
- roundf(vp.x / 2.0 - size.x / 2.0),
- vp.y - size.y - 24.0
- )
+ if _is_mobile_web:
+ position = Vector2(
+ roundf(vp.x / 2.0 - size.x / 2.0),
+ vp.y - size.y - 150
+ )
+ else:
+ position = Vector2(
+ roundf(vp.x / 2.0 - size.x / 2.0),
+ vp.y - size.y - 24.0
+ )
+
+func _is_mobile_web() -> bool:
+ return OS.has_feature("web_android") or OS.has_feature("web_ios")
# ──────────────────────────────────────────────────────────
diff --git a/scenes/algorithm_player/algorithm_player.gd b/scenes/algorithm_player/algorithm_player.gd
index 83d4ce7..d3da113 100644
--- a/scenes/algorithm_player/algorithm_player.gd
+++ b/scenes/algorithm_player/algorithm_player.gd
@@ -284,10 +284,19 @@ func _expose_visualizer() -> void:
func _place_visualizer_bottom_left() -> void:
var viewport_size: Vector2 = get_viewport().get_visible_rect().size
var panel_size: Vector2 = pseudo_visualizer.size
- pseudo_visualizer.position = Vector2(
- PSEUDO_MARGIN,
- viewport_size.y - panel_size.y - PSEUDO_MARGIN
- )
+ if _is_mobile_web():
+ pseudo_visualizer.position = Vector2(
+ PSEUDO_MARGIN,
+ viewport_size.y - panel_size.y - PSEUDO_MARGIN - 150
+ )
+ else:
+ pseudo_visualizer.position = Vector2(
+ PSEUDO_MARGIN,
+ viewport_size.y - panel_size.y - PSEUDO_MARGIN
+ )
+
+func _is_mobile_web() -> bool:
+ return OS.has_feature("web_android") or OS.has_feature("web_ios")
# Animation to show player controls.
func _expose_controls() -> void:
diff --git a/scenes/camera/camera.gd b/scenes/camera/camera.gd
index 5f306b5..51794c2 100644
--- a/scenes/camera/camera.gd
+++ b/scenes/camera/camera.gd
@@ -79,10 +79,15 @@ func _input(event: InputEvent) -> void:
view_changed.emit()
_update_cursor_shape()
- if event is InputEventMouseMotion and _is_dragging:
+ if event is InputEventScreenDrag and _is_dragging:
+ position += event.relative / zoom.x
+ get_viewport().set_input_as_handled()
+ elif event is InputEventMouseMotion and _is_dragging and not _is_mobile_web():
position -= event.relative / zoom.x
_update_cursor_shape()
+func _is_mobile_web() -> bool:
+ return OS.has_feature("web_android") or OS.has_feature("web_ios")
## factor multiplies the current zoom; it is clamped to [min_zoom, max_zoom].
## If center_on_mouse is true, the point under the cursor stays fixed (wheel).
diff --git a/scenes/feedback/feedback.tscn b/scenes/feedback/feedback.tscn
index fc0aa05..085d171 100644
--- a/scenes/feedback/feedback.tscn
+++ b/scenes/feedback/feedback.tscn
@@ -29,7 +29,6 @@ text = "Send Feedback"
[node name="Popup" type="Popup" parent="." unique_id=938699655]
oversampling_override = 1.0
size = Vector2i(502, 215)
-visible = true
[node name="PanelRoot" type="PanelContainer" parent="Popup" unique_id=113360399]
anchors_preset = 15
diff --git a/scenes/main/main.tscn b/scenes/main/main.tscn
index d187d14..1584838 100644
--- a/scenes/main/main.tscn
+++ b/scenes/main/main.tscn
@@ -20,6 +20,7 @@
[ext_resource type="PackedScene" uid="uid://ccka0nd856cca" path="res://scenes/sharing/share_panel.tscn" id="17_share_panel"]
[ext_resource type="Script" uid="uid://bcy61pj3dte0g" path="res://scenes/tool_bar/tool_hint.gd" id="18_tool_hint"]
[ext_resource type="PackedScene" uid="uid://ce8vasy4hj2x7" path="res://scenes/welcome/welcome_overlay.tscn" id="19_welcome"]
+[ext_resource type="Script" uid="uid://ciqi4vmyemqmu" path="res://scenes/main/resolution_manager.gd" id="21_pg34l"]
[node name="Main" type="Node2D" unique_id=446252932]
script = ExtResource("1_yyfjg")
@@ -106,3 +107,6 @@ camera = NodePath("../Camera")
grid_background = NodePath("../MathGridBackground")
popup_menu_a = NodePath("../GraphController/PopupMenu")
popup_menu_b = NodePath("../CanvasLayer/PopupMenuLayer")
+
+[node name="ResolutionManager" type="Node" parent="." unique_id=1257491223]
+script = ExtResource("21_pg34l")
diff --git a/scenes/main/resolution_manager.gd b/scenes/main/resolution_manager.gd
new file mode 100644
index 0000000..879aaa7
--- /dev/null
+++ b/scenes/main/resolution_manager.gd
@@ -0,0 +1,12 @@
+extends Node
+
+
+func _ready() -> void:
+ _adjust_ui_scale()
+
+func _is_mobile_web() -> bool:
+ return OS.has_feature("web_android") or OS.has_feature("web_ios")
+
+func _adjust_ui_scale() -> void:
+ if _is_mobile_web():
+ get_window().content_scale_factor = 2.0
diff --git a/scenes/main/resolution_manager.gd.uid b/scenes/main/resolution_manager.gd.uid
new file mode 100644
index 0000000..c9ae651
--- /dev/null
+++ b/scenes/main/resolution_manager.gd.uid
@@ -0,0 +1 @@
+uid://ciqi4vmyemqmu