|
@@ -0,0 +1,171 @@
|
|
|
+class_name Show
|
|
|
+extends Node2D
|
|
|
+# Manage slide cycling
|
|
|
+
|
|
|
+
|
|
|
+signal new_focus(pos: Vector2, scale: float, trans: Focus.Transit)
|
|
|
+
|
|
|
+const VOID_SLIDE_ID := -1
|
|
|
+
|
|
|
+@export_group("Slide management")
|
|
|
+@export var start_slide := 0
|
|
|
+@export var hide_slides := false
|
|
|
+
|
|
|
+@export_group("Input setup", "action_")
|
|
|
+@export var action_finish_slide := "ui_accept"
|
|
|
+@export var action_skip_slide := "ui_right"
|
|
|
+@export var action_previous_slide := "ui_left"
|
|
|
+@export var action_home_slide := "ui_cancel"
|
|
|
+
|
|
|
+var current_id := VOID_SLIDE_ID
|
|
|
+var current_slide: Slide
|
|
|
+
|
|
|
+@onready var slides: Array = get_children()
|
|
|
+
|
|
|
+
|
|
|
+func _ready() -> void:
|
|
|
+ _enforce()
|
|
|
+ print("The show contains %s slides" % slides.size())
|
|
|
+
|
|
|
+ if hide_slides:
|
|
|
+ _hide_every_slide()
|
|
|
+
|
|
|
+ _global_slide_setup()
|
|
|
+
|
|
|
+ go_slowly_to_next_slide()
|
|
|
+
|
|
|
+
|
|
|
+func go_slowly_to_next_slide() -> void:
|
|
|
+ next_slide(Focus.Transit.SMOOTH)
|
|
|
+
|
|
|
+
|
|
|
+func go_fast_to_next_slide() -> void:
|
|
|
+ next_slide(Focus.Transit.BEAM)
|
|
|
+
|
|
|
+
|
|
|
+func go_fast_to_previous_slide() -> void:
|
|
|
+ next_slide_at(_previous_id(), Focus.Transit.BEAM)
|
|
|
+
|
|
|
+
|
|
|
+func next_slide(trans: Focus.Transit) -> void:
|
|
|
+ next_slide_at(_next_id(), trans)
|
|
|
+
|
|
|
+
|
|
|
+func next_slide_at(next_id: int, trans: Focus.Transit) -> void:
|
|
|
+ _disable_current_slide()
|
|
|
+ current_id = next_id
|
|
|
+ current_slide = _focus_slide(current_id, trans)
|
|
|
+ _enable_current_slide()
|
|
|
+
|
|
|
+
|
|
|
+func _focus_slide(id: int, trans: Focus.Transit) -> Slide:
|
|
|
+ var slide: Slide = slides[id]
|
|
|
+ new_focus.emit(slide.get_center(), slide.get_scale().x, trans)
|
|
|
+ return slide
|
|
|
+
|
|
|
+
|
|
|
+func _hide_every_slide() -> void:
|
|
|
+ for slide in slides:
|
|
|
+ slide.gently_hide()
|
|
|
+
|
|
|
+
|
|
|
+func _global_slide_setup() -> void:
|
|
|
+ for slide in slides:
|
|
|
+ slide.set_action_finish(action_finish_slide)
|
|
|
+
|
|
|
+
|
|
|
+func _disable_current_slide() -> void:
|
|
|
+ if current_slide != null:
|
|
|
+ current_slide.disable()
|
|
|
+ current_slide.finished.disconnect(_on_current_slide_finished)
|
|
|
+
|
|
|
+
|
|
|
+func _enable_current_slide() -> void:
|
|
|
+ current_slide.enable()
|
|
|
+ current_slide.finished.connect(_on_current_slide_finished)
|
|
|
+
|
|
|
+
|
|
|
+func _enforce() -> void:
|
|
|
+ _enforce_parameters()
|
|
|
+ _enforce_children()
|
|
|
+
|
|
|
+
|
|
|
+func _enforce_parameters() -> void:
|
|
|
+ assert(start_slide >= 0,
|
|
|
+ "Negative index is not supported for start_slide")
|
|
|
+ assert(start_slide < slides.size(),
|
|
|
+ "start_slide index is out of bound (max is %s)" % (slides.size() - 1))
|
|
|
+
|
|
|
+
|
|
|
+func _enforce_children() -> void:
|
|
|
+ assert(!slides.is_empty(), "A slideshow must contain slides")
|
|
|
+ for slide in slides:
|
|
|
+ assert(slide is Slide, "A slideshow can only contain slides")
|
|
|
+
|
|
|
+
|
|
|
+func _next_id() -> int:
|
|
|
+ if current_id == VOID_SLIDE_ID:
|
|
|
+ return start_slide
|
|
|
+
|
|
|
+ var next_id: int = current_id + 1
|
|
|
+
|
|
|
+ if next_id >= slides.size():
|
|
|
+ return 0
|
|
|
+
|
|
|
+ return next_id
|
|
|
+
|
|
|
+
|
|
|
+func _previous_id() -> int:
|
|
|
+ var next_id: int = current_id - 1
|
|
|
+
|
|
|
+ if next_id < 0:
|
|
|
+ return slides.size() - 1
|
|
|
+
|
|
|
+ return next_id
|
|
|
+
|
|
|
+
|
|
|
+func _reset_id() -> void:
|
|
|
+ current_id = VOID_SLIDE_ID
|
|
|
+
|
|
|
+
|
|
|
+func _unhandled_key_input(event: InputEvent) -> void:
|
|
|
+ if !event.is_pressed():
|
|
|
+ return
|
|
|
+
|
|
|
+ if event.is_action(action_skip_slide):
|
|
|
+ get_viewport().set_input_as_handled()
|
|
|
+ go_fast_to_next_slide()
|
|
|
+ elif event.is_action(action_previous_slide):
|
|
|
+ get_viewport().set_input_as_handled()
|
|
|
+ go_fast_to_previous_slide()
|
|
|
+ elif event.is_action(action_home_slide):
|
|
|
+ get_viewport().set_input_as_handled()
|
|
|
+ _reset_id()
|
|
|
+ go_slowly_to_next_slide()
|
|
|
+
|
|
|
+
|
|
|
+func _unhandled_input(event: InputEvent) -> void:
|
|
|
+ if event is InputEventMouseButton and event.is_pressed():
|
|
|
+ _focus_nearest_slide_from(get_global_mouse_position())
|
|
|
+
|
|
|
+
|
|
|
+func _focus_nearest_slide_from(target_pos: Vector2) -> void:
|
|
|
+ var next_slide = _search_nearest_slide_from(target_pos)
|
|
|
+ var next_id = slides.find(next_slide)
|
|
|
+ next_slide_at(next_id, Focus.Transit.SMOOTH)
|
|
|
+
|
|
|
+
|
|
|
+func _search_nearest_slide_from(target_pos: Vector2) -> Slide:
|
|
|
+ var nearest_slide = current_slide
|
|
|
+ var shortest_distance = target_pos.distance_squared_to(nearest_slide.get_center())
|
|
|
+ for current_slide in slides:
|
|
|
+ var current_distance = target_pos.distance_squared_to(current_slide.get_center())
|
|
|
+ if current_distance < shortest_distance:
|
|
|
+ nearest_slide = current_slide
|
|
|
+ shortest_distance = current_distance
|
|
|
+
|
|
|
+ return nearest_slide
|
|
|
+
|
|
|
+
|
|
|
+func _on_current_slide_finished() -> void:
|
|
|
+ go_slowly_to_next_slide()
|