-
Notifications
You must be signed in to change notification settings - Fork 0
/
Slideshow.gd
196 lines (151 loc) · 5.34 KB
/
Slideshow.gd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
extends Control
class_name Slideshow
@onready var button_next := %Next
@onready var button_previous := %Previous
@onready var content := %Content
@onready var frame := %Frame
@export var transition_duration := 0.5
@export var time_per_slide := 5.0
@export var enable_timed_slides := true
@export var enable_slide_inputs := true
var _current_slide_index := 0
var _slide_reset_time := 0.0
var _block_inputs := false
func add_content(new_content: Control) -> void:
content.add_child(new_content)
if content.get_child_count() > 1:
_show_buttons(true)
func _ready() -> void:
_initialize()
func _physics_process(delta: float) -> void:
if enable_timed_slides:
time_per_slide -= delta
# time's up so go to next slide and reset time
if time_per_slide <= 0:
_cycle_next()
time_per_slide = _slide_reset_time
func _initialize() -> void:
button_next.pressed.connect(_cycle_next)
button_previous.pressed.connect(_cycle_previous)
content.gui_input.connect(_handle_input)
# set the temporary variable to hold the value
_slide_reset_time = time_per_slide
# move all slides off screen and fit to content frame (if not ignoring sizes)
_content_fit_size()
_content_reset_positions()
# set the initial slide position if it exists
if content.get_child_count() > 0:
var initial_slide := content.get_child(_current_slide_index)
initial_slide.set_position(content.get_position())
# hide the next/previous buttons if slides <= 1
if content.get_child_count() <= 1:
_show_buttons(false)
func _show_buttons(is_visible: bool) -> void:
button_next.set_visible(is_visible)
button_previous.set_visible(is_visible)
func _content_fit_size() -> void:
for slide in content.get_children():
slide.set_size(content.get_size())
func _content_reset_positions() -> void:
# move all slides off the screen to the left
for slide in content.get_children():
slide.set_position(
Vector2(
frame.get_position().x - frame.get_size().x,
frame.get_position().y
)
)
func _set_to_frame_left(slide: Control) -> void:
slide.set_position(
Vector2(
frame.get_position().x - frame.get_size().x,
slide.get_position().y
)
)
func _set_to_frame_right(slide: Control) -> void:
slide.set_position(
Vector2(
frame.get_position().x + frame.get_size().x,
slide.get_position().y
)
)
func _set_slide() -> void:
# TODO: add a way to go directly to slide in deck
pass
func _cycle_next() -> void:
# if there's only one node or less or inputs are blocked, do nothing
var slide_count := content.get_child_count()
if slide_count <= 1 or _block_inputs:
return
# set variable to block trying to cycle to next/previous slide
_block_inputs = true
# get the index of the next node
var next_index := _current_slide_index + 1
if next_index >= slide_count:
next_index = 0
# set the initial position of next slide to the left of content before moving
var next_slide := content.get_child(next_index)
_set_to_frame_left(next_slide)
# slide the current and next nodes to the right simultaneously
var current_slide := content.get_child(_current_slide_index)
var tween := get_tree().create_tween().set_parallel(true)
tween.tween_property(
current_slide,
"position:x",
frame.get_position().x + frame.get_size().x, # at end of frame
transition_duration
).set_trans(Tween.TRANS_CUBIC)
tween.tween_property(
next_slide,
"position:x",
frame.get_position().x, # target position
transition_duration
).set_trans(Tween.TRANS_CUBIC)
tween.chain().tween_callback(func() -> void: _block_inputs = false)
# set the current index to the next one
_current_slide_index = next_index
time_per_slide = _slide_reset_time
func _cycle_previous() -> void:
# if there's only one node or less or inputs are blocked, do nothing
var slide_count := content.get_child_count()
if slide_count <= 1 or _block_inputs:
return
# set variable to block trying to cycle to next/previous slide
_block_inputs = true
# get the index of the previous node
var previous_index := _current_slide_index - 1
if previous_index < 0:
previous_index = slide_count - 1
# set the initial position of previous slide to the right of content before moving
var previous_slide := content.get_child(previous_index)
_set_to_frame_right(previous_slide)
# slide the current and previous nodes to the left simultaneously
var current_slide := content.get_child(_current_slide_index)
var tween := get_tree().create_tween().set_parallel(true)
tween.tween_property(
current_slide,
"position:x",
frame.get_position().x - frame.get_size().x, # at left of frame
transition_duration
).set_trans(Tween.TRANS_CUBIC)
tween.tween_property(
previous_slide,
"position:x",
frame.get_position().x, # target position
transition_duration
).set_trans(Tween.TRANS_CUBIC)
tween.chain().tween_callback(func() -> void: _block_inputs = false)
# set the current index to the previous one and reset timer
_current_slide_index = previous_index
time_per_slide = _slide_reset_time
func _handle_input(event: InputEvent) -> void:
# handle inputs if enabled
if !enable_slide_inputs:
return
# handle left and mouse clicks from mouse buttons only
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_LEFT and event.is_released():
_cycle_next()
if event.button_index == MOUSE_BUTTON_RIGHT and event.is_released():
_cycle_previous()
# TODO: handle events from touch screen