Skip to content

Commit 2b3bee4

Browse files
authored
Merge pull request #3482 from Lt-knb/Transition-fixes
Fix Mosaic and Wave, and other transition issues
2 parents 21c8985 + e827009 commit 2b3bee4

1 file changed

Lines changed: 78 additions & 76 deletions

File tree

src/transition.cpp

Lines changed: 78 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,14 @@ int Transition::GetDefaultFrames(Transition::Type type)
4242
switch (type) {
4343
case TransitionFadeIn:
4444
case TransitionFadeOut:
45-
return 32;
45+
return 35;
4646
case TransitionCutIn:
4747
case TransitionCutOut:
48+
return 1;
4849
case TransitionNone:
4950
return 0;
5051
default:
51-
return 40;
52+
return 41;
5253
}
5354
return 0;
5455
}
@@ -80,7 +81,8 @@ void Transition::Init(Type type, Scene *linked_scene, int duration, bool next_er
8081
transition_type = type;
8182
scene = linked_scene;
8283

83-
current_frame = 0;
84+
// Don't skip Frame 0 (Update is called before Draw).
85+
current_frame = -1;
8486
flash = {};
8587
flash_power = 0;
8688
flash_iterations = 0;
@@ -173,10 +175,8 @@ void Transition::SetAttributesTransitions() {
173175
case TransitionMosaicIn:
174176
case TransitionMosaicOut:
175177
for (int i = 0; i < total_frames; ++i) {
176-
const int initial_scale = 2;
177-
const int excl_interval = -1;
178-
// by default i 0..39 for scale 2..41
179-
mosaic_random_offset[i] = Rand::GetRandomNumber(0, i + initial_scale - excl_interval);
178+
// by default i 0..40 for scale 1..41
179+
mosaic_random_offset[i] = Rand::GetRandomNumber(0, i);
180180
}
181181
break;
182182
default:
@@ -190,7 +190,7 @@ void Transition::Draw(Bitmap& dst) {
190190
return;
191191

192192
std::vector<int> z_pos(2), z_size(2), z_length(2);
193-
int z_min, z_max, z_percent, z_fixed_pos, z_fixed_size;
193+
int z_min, z_max, z_frame, z_fixed_pos, z_fixed_size;
194194
uint8_t m_r, m_g, m_b, m_a;
195195
uint32_t *m_pointer, blocks_to_print;
196196
int m_size;
@@ -204,19 +204,19 @@ void Transition::Draw(Bitmap& dst) {
204204
dst.BlendBlit(0, 0, *screen1, screen1->GetRect(), color, 255);
205205
return;
206206
}
207-
208-
int percentage = (current_frame) * 100 / (total_frames);
207+
208+
int tf_off = total_frames - 1;
209209

210210
switch (transition_type) {
211211
case TransitionFadeIn:
212212
case TransitionFadeOut:
213213
dst.Blit(0, 0, *screen1, screen1->GetRect(), 255);
214-
dst.Blit(0, 0, *screen2, screen2->GetRect(), 255 * percentage / 100);
214+
dst.Blit(0, 0, *screen2, screen2->GetRect(), 255 * (current_frame + 1) / (total_frames - 2));
215215
break;
216216
case TransitionRandomBlocks:
217217
case TransitionRandomBlocksDown:
218218
case TransitionRandomBlocksUp:
219-
blocks_to_print = random_blocks.size() * percentage / 100;
219+
blocks_to_print = random_blocks.size() * (current_frame + 1) / tf_off;
220220

221221
for (uint32_t i = current_blocks_print; i < blocks_to_print; i++) {
222222
random_block_transition->Blit(random_blocks[i] % (w / size_random_blocks) * size_random_blocks,
@@ -230,151 +230,152 @@ void Transition::Draw(Bitmap& dst) {
230230
break;
231231
case TransitionBlindOpen:
232232
for (int i = 0; i < h / 8; i++) {
233-
dst.Blit(0, i * 8, *screen1, Rect(0, i * 8, w, 8 - 8 * percentage / 100), 255);
234-
dst.Blit(0, i * 8 + 8 - 8 * percentage / 100, *screen2, Rect(0, i * 8 + 8 - 8 * percentage / 100, w, 8 * percentage / 100), 255);
233+
dst.Blit(0, i * 8, *screen1, Rect(0, i * 8, w, 8 - (current_frame + 5) / 5), 255);
234+
dst.Blit(0, i * 8 + 8 - (current_frame + 5) / 5, *screen2, Rect(0, i * 8 + 8 - (current_frame + 5) / 5, w, (current_frame + 5) / 5), 255);
235235
}
236236
break;
237237
case TransitionBlindClose:
238238
for (int i = 0; i < h / 8; i++) {
239-
dst.Blit(0, i * 8 + 8 * percentage / 100, *screen1, Rect(0, i * 8 + 8 * percentage / 100, w, 8 - 8 * percentage / 100), 255);
240-
dst.Blit(0, i * 8, *screen2, Rect(0, i * 8, w, 8 * percentage / 100), 255);
239+
dst.Blit(0, i * 8 + (current_frame + 5) / 5, *screen1, Rect(0, i * 8 + (current_frame + 5) / 5, w, 8 - (current_frame + 5) / 5), 255);
240+
dst.Blit(0, i * 8, *screen2, Rect(0, i * 8, w, (current_frame + 5) / 5), 255);
241241
}
242242
break;
243243
case TransitionVerticalStripesIn:
244244
case TransitionVerticalStripesOut:
245-
for (int i = 0; i < h / 6 + 1 - h / 6 * percentage / 100; i++) {
245+
for (int i = 0; i < tf_off - (current_frame + 1); i++) {
246246
dst.Blit(0, i * 6 + 3, *screen1, Rect(0, i * 6 + 3, w, 3), 255);
247247
dst.Blit(0, h - i * 6, *screen1, Rect(0, h - i * 6, w, 3), 255);
248248
}
249-
for (int i = 0; i < h / 6 * percentage / 100; i++) {
249+
for (int i = 0; i < current_frame + 1; i++) {
250250
dst.Blit(0, i * 6, *screen2, Rect(0, i * 6, w, 3), 255);
251251
dst.Blit(0, h - 3 - i * 6, *screen2, Rect(0, h - 3 - i * 6, w, 3), 255);
252252
}
253253
break;
254254
case TransitionHorizontalStripesIn:
255255
case TransitionHorizontalStripesOut:
256-
for (int i = 0; i < w / 8 + 1 - w / 8 * percentage / 100; i++) {
256+
for (int i = 0; i < tf_off - (current_frame + 1); i++) {
257257
dst.Blit(i * 8 + 4, 0, *screen1, Rect(i * 8 + 4, 0, 4, h), 255);
258258
dst.Blit(w - i * 8, 0, *screen1, Rect(w - i * 8, 0, 4, h), 255);
259259
}
260-
for (int i = 0; i < w / 8 * percentage / 100; i++) {
260+
for (int i = 0; i < current_frame + 1; i++) {
261261
dst.Blit(i * 8, 0, *screen2, Rect(i * 8, 0, 4, h), 255);
262262
dst.Blit(w - 4 - i * 8, 0, *screen2, Rect(w - 4 - i * 8, 0, 4, h), 255);
263263
}
264264
break;
265265
case TransitionBorderToCenterIn:
266266
case TransitionBorderToCenterOut:
267267
dst.Blit(0, 0, *screen2, screen2->GetRect(), 255);
268-
dst.Blit((w / 2) * percentage / 100, (h / 2) * percentage / 100, *screen1, Rect((w / 2) * percentage / 100, (h / 2) * percentage / 100, w - w * percentage / 100, h - h * percentage / 100), 255);
268+
dst.Blit((w / 2) * current_frame / tf_off, (h / 2) * current_frame / tf_off, *screen1, Rect((w / 2) * current_frame / tf_off, (h / 2) * current_frame / tf_off, w - w * current_frame / tf_off, h - h * current_frame / tf_off), 255);
269269
break;
270270
case TransitionCenterToBorderIn:
271271
case TransitionCenterToBorderOut:
272272
dst.Blit(0, 0, *screen1, screen1->GetRect(), 255);
273-
dst.Blit(w / 2 - (w / 2) * percentage / 100, h / 2 - (h / 2) * percentage / 100, *screen2, Rect(w / 2 - (w / 2) * percentage / 100, h / 2 - (h / 2) * percentage / 100, w * percentage / 100, h * percentage / 100), 255);
273+
dst.Blit(w / 2 - (w / 2) * current_frame / tf_off, h / 2 - (h / 2) * current_frame / tf_off, *screen2, Rect(w / 2 - (w / 2) * current_frame / tf_off, h / 2 - (h / 2) * current_frame / tf_off, w * current_frame / tf_off, h * current_frame / tf_off), 255);
274274
break;
275275
case TransitionScrollUpIn:
276276
case TransitionScrollUpOut:
277-
dst.Blit(0, -h * percentage / 100, *screen1, screen1->GetRect(), 255);
278-
dst.Blit(0, h - h * percentage / 100, *screen2, screen2->GetRect(), 255);
277+
dst.Blit(0, -h * current_frame / tf_off, *screen1, screen1->GetRect(), 255);
278+
dst.Blit(0, h - h * current_frame / tf_off, *screen2, screen2->GetRect(), 255);
279279
break;
280280
case TransitionScrollDownIn:
281281
case TransitionScrollDownOut:
282-
dst.Blit(0, h * percentage / 100, *screen1, screen1->GetRect(), 255);
283-
dst.Blit(0, -h + h * percentage / 100, *screen2, screen2->GetRect(), 255);
282+
dst.Blit(0, h * current_frame / tf_off, *screen1, screen1->GetRect(), 255);
283+
dst.Blit(0, -h + h * current_frame / tf_off, *screen2, screen2->GetRect(), 255);
284284
break;
285285
case TransitionScrollLeftIn:
286286
case TransitionScrollLeftOut:
287-
dst.Blit(-w * percentage / 100, 0, *screen1, screen1->GetRect(), 255);
288-
dst.Blit(w - w * percentage / 100, 0, *screen2, screen2->GetRect(), 255);
287+
dst.Blit(-w * current_frame / tf_off, 0, *screen1, screen1->GetRect(), 255);
288+
dst.Blit(w - w * current_frame / tf_off, 0, *screen2, screen2->GetRect(), 255);
289289
break;
290290
case TransitionScrollRightIn:
291291
case TransitionScrollRightOut:
292-
dst.Blit(w * percentage / 100, 0, *screen1, screen1->GetRect(), 255);
293-
dst.Blit(-w + w * percentage / 100, 0, *screen2, screen2->GetRect(), 255);
292+
dst.Blit(w * current_frame / tf_off, 0, *screen1, screen1->GetRect(), 255);
293+
dst.Blit(-w + w * current_frame / tf_off, 0, *screen2, screen2->GetRect(), 255);
294294
break;
295295
case TransitionVerticalCombine:
296-
case TransitionVerticalDivision:
297-
// If TransitionVerticalCombine, invert percentage and screen:
298-
if (transition_type == TransitionVerticalCombine) { percentage = 100 - percentage; }
296+
case TransitionVerticalDivision: {
297+
// If TransitionVerticalCombine, invert current_frame and screen:
298+
int ver_cf = transition_type == TransitionVerticalCombine ? tf_off - current_frame : current_frame;
299299
screen_pointer1 = transition_type == TransitionVerticalCombine ? screen2 : screen1;
300300
screen_pointer2 = transition_type == TransitionVerticalCombine ? screen1 : screen2;
301301

302-
dst.Blit(0, -(h / 2) * percentage / 100, *screen_pointer1, Rect(0, 0, w, h / 2), 255);
303-
dst.Blit(0, h / 2 + (h / 2) * percentage / 100, *screen_pointer1, Rect(0, h / 2, w, h / 2), 255);
304-
dst.Blit(0, h / 2 - (h / 2) * percentage / 100, *screen_pointer2, Rect(0, h / 2 - (h / 2) * percentage / 100, w, h * percentage / 100), 255);
302+
dst.Blit(0, -(h / 2) * ver_cf / tf_off, *screen_pointer1, Rect(0, 0, w, h / 2), 255);
303+
dst.Blit(0, h / 2 + (h / 2) * ver_cf / tf_off, *screen_pointer1, Rect(0, h / 2, w, h / 2), 255);
304+
dst.Blit(0, h / 2 - (h / 2) * ver_cf / tf_off, *screen_pointer2, Rect(0, h / 2 - (h / 2) * ver_cf / tf_off, w, h * ver_cf / tf_off), 255);
305305
break;
306+
}
306307
case TransitionHorizontalCombine:
307-
case TransitionHorizontalDivision:
308-
// If TransitionHorizontalCombine, invert percentage and screen:
309-
if (transition_type == TransitionHorizontalCombine) { percentage = 100 - percentage; }
308+
case TransitionHorizontalDivision: {
309+
// If TransitionHorizontalCombine, invert current_frame and screen:
310+
int hor_cf = transition_type == TransitionHorizontalCombine ? tf_off - current_frame : current_frame;
310311
screen_pointer1 = transition_type == TransitionHorizontalCombine ? screen2 : screen1;
311312
screen_pointer2 = transition_type == TransitionHorizontalCombine ? screen1 : screen2;
312313

313-
dst.Blit(-(w / 2) * percentage / 100, 0, *screen_pointer1, Rect(0, 0, w / 2, h), 255);
314-
dst.Blit(w / 2 + (w / 2) * percentage / 100, 0, *screen_pointer1, Rect(w / 2, 0, w / 2, h), 255);
315-
dst.Blit(w / 2 - (w / 2) * percentage / 100, 0, *screen_pointer2, Rect(w / 2 - (w / 2) * percentage / 100, 0, w * percentage / 100, h), 255);
314+
dst.Blit(-(w / 2) * hor_cf / tf_off, 0, *screen_pointer1, Rect(0, 0, w / 2, h), 255);
315+
dst.Blit(w / 2 + (w / 2) * hor_cf / tf_off, 0, *screen_pointer1, Rect(w / 2, 0, w / 2, h), 255);
316+
dst.Blit(w / 2 - (w / 2) * hor_cf / tf_off, 0, *screen_pointer2, Rect(w / 2 - (w / 2) * hor_cf / tf_off, 0, w * hor_cf / tf_off, h), 255);
316317
break;
318+
}
317319
case TransitionCrossCombine:
318-
case TransitionCrossDivision:
319-
// If TransitionCrossCombine, invert percentage and screen:
320-
if (transition_type == TransitionCrossCombine) { percentage = 100 - percentage; }
320+
case TransitionCrossDivision: {
321+
// If TransitionCrossCombine, invert current_frame and screen:
322+
int cross_cf = transition_type == TransitionCrossCombine ? tf_off - current_frame : current_frame;
321323
screen_pointer1 = transition_type == TransitionCrossCombine ? screen2 : screen1;
322324
screen_pointer2 = transition_type == TransitionCrossCombine ? screen1 : screen2;
323325

324-
dst.Blit(-(w / 2) * percentage / 100, -(h / 2) * percentage / 100, *screen_pointer1, Rect(0, 0, w / 2, h / 2), 255);
325-
dst.Blit(w / 2 + (w / 2) * percentage / 100, -(h / 2) * percentage / 100, *screen_pointer1, Rect(w / 2, 0, w / 2, h / 2), 255);
326-
dst.Blit(w / 2 + (w / 2) * percentage / 100, h / 2 + (h / 2) * percentage / 100, *screen_pointer1, Rect(w / 2, h / 2, w / 2, h / 2), 255);
327-
dst.Blit(-(w / 2) * percentage / 100, h / 2 + (h / 2) * percentage / 100, *screen_pointer1, Rect(0, h / 2, w / 2, h / 2), 255);
328-
dst.Blit(w / 2 - (w / 2) * percentage / 100, 0, *screen_pointer2, Rect(w / 2 - (w / 2) * percentage / 100, 0, w * percentage / 100, h / 2 - (h / 2) * percentage / 100), 255);
329-
dst.Blit(w / 2 - (w / 2) * percentage / 100, h / 2 + (h / 2) * percentage / 100, *screen_pointer2, Rect(w / 2 - (w / 2) * percentage / 100, h / 2 + (h / 2) * percentage / 100, w * percentage / 100, h / 2 + (h / 2) * percentage / 100), 255);
330-
dst.Blit(0, h / 2 - (h / 2) * percentage / 100, *screen_pointer2, Rect(0, h / 2 - (h / 2) * percentage / 100, w, h * percentage / 100), 255);
326+
dst.Blit(-(w / 2) * cross_cf / tf_off, -(h / 2) * cross_cf / tf_off, *screen_pointer1, Rect(0, 0, w / 2, h / 2), 255);
327+
dst.Blit(w / 2 + (w / 2) * cross_cf / tf_off, -(h / 2) * cross_cf / tf_off, *screen_pointer1, Rect(w / 2, 0, w / 2, h / 2), 255);
328+
dst.Blit(w / 2 + (w / 2) * cross_cf / tf_off, h / 2 + (h / 2) * cross_cf / tf_off, *screen_pointer1, Rect(w / 2, h / 2, w / 2, h / 2), 255);
329+
dst.Blit(-(w / 2) * cross_cf / tf_off, h / 2 + (h / 2) * cross_cf / tf_off, *screen_pointer1, Rect(0, h / 2, w / 2, h / 2), 255);
330+
dst.Blit(w / 2 - (w / 2) * cross_cf / tf_off, 0, *screen_pointer2, Rect(w / 2 - (w / 2) * cross_cf / tf_off, 0, w * cross_cf / tf_off, h / 2 - (h / 2) * cross_cf / tf_off), 255);
331+
dst.Blit(w / 2 - (w / 2) * cross_cf / tf_off, h / 2 + (h / 2) * cross_cf / tf_off, *screen_pointer2, Rect(w / 2 - (w / 2) * cross_cf / tf_off, h / 2 + (h / 2) * cross_cf / tf_off, w * cross_cf / tf_off, h / 2 + (h / 2) * cross_cf / tf_off), 255);
332+
dst.Blit(0, h / 2 - (h / 2) * cross_cf / tf_off, *screen_pointer2, Rect(0, h / 2 - (h / 2) * cross_cf / tf_off, w, h * cross_cf / tf_off), 255);
331333
break;
334+
}
332335
case TransitionZoomIn:
333-
case TransitionZoomOut:
334-
// If TransitionZoomOut, invert percentage and screen:
335-
if (transition_type == TransitionZoomOut) { percentage = 100 - percentage; }
336+
case TransitionZoomOut: {
337+
// If TransitionZoomOut, invert current_frame and screen:
338+
int z_cf = transition_type == TransitionZoomOut ? tf_off - current_frame : current_frame;
336339
screen_pointer1 = transition_type == TransitionZoomOut ? screen2 : screen1;
337340

338341
// X Coordinate: [0] Y Coordinate: [1]
339342
z_length[0] = w;
340343
z_length[1] = h;
341-
percentage = percentage <= 97 ? percentage : 97;
344+
z_cf = z_cf <= total_frames - 2 ? z_cf : total_frames - 2;
342345

343346
for (int i = 0; i < 2; i++) {
344347
z_min = z_length[i] / 4;
345348
z_max = z_length[i] * 3 / 4;
346-
z_pos[i] = std::max(z_min, std::min((int)zoom_position[i], z_max)) * percentage / 100;
347-
z_size[i] = z_length[i] * (100 - percentage) / 100;
349+
z_pos[i] = std::max(z_min, std::min((int)zoom_position[i], z_max)) * z_cf / tf_off;
350+
z_size[i] = z_length[i] * (tf_off - z_cf) / tf_off;
348351

349-
z_percent = (zoom_position[i] < z_min) ? (100 * zoom_position[i] / z_min - 100) :
350-
(zoom_position[i] > z_max) ? (100 * (zoom_position[i] - z_max) / (z_length[i] - z_max)) : 0;
352+
z_frame = (zoom_position[i] < z_min) ? (tf_off * zoom_position[i] / z_min - tf_off) :
353+
(zoom_position[i] > z_max) ? (tf_off * (zoom_position[i] - z_max) / (z_length[i] - z_max)) : 0;
351354

352-
if (z_percent != 0 && percentage > 0) {
353-
z_fixed_pos = z_pos[i] * std::abs(z_percent) / percentage;
354-
z_fixed_size = z_length[i] * (100 - std::abs(z_percent)) / 100;
355-
z_pos[i] += percentage < std::abs(z_percent) ? (z_percent > 0 ? 1 : 0) * (z_length[i] - z_size[i]) - z_pos[i] :
356-
(z_percent > 0 ? z_length[i] - z_fixed_pos - z_fixed_size : -z_fixed_pos);
355+
if (z_frame != 0 && z_cf > 0) {
356+
z_fixed_pos = z_pos[i] * std::abs(z_frame) / z_cf;
357+
z_fixed_size = z_length[i] * (tf_off - std::abs(z_frame)) / tf_off;
358+
z_pos[i] += z_cf < std::abs(z_frame) ? (z_frame > 0 ? 1 : 0) * (z_length[i] - z_size[i]) - z_pos[i] :
359+
(z_frame > 0 ? z_length[i] - z_fixed_pos - z_fixed_size : -z_fixed_pos);
357360
}
358361
}
359362

360363
dst.StretchBlit(Rect(0, 0, w, h), *screen_pointer1, Rect(z_pos[0], z_pos[1], z_size[0], z_size[1]), 255);
361364
break;
365+
}
362366
case TransitionMosaicIn:
363367
case TransitionMosaicOut: {
364-
// Goes from scale 2 to 41 (current_frame is 0 - 39)
365-
// FIXME: current_frame starts at 1 (off-by-one error?)
368+
// Goes from scale 1 to 41 (current_frame is 0 - 40)
366369
// If TransitionMosaicIn, invert scale and screen:
367370
int32_t rand;
368371
if (transition_type == TransitionMosaicIn) {
369-
m_size = total_frames + 1 - current_frame;
372+
m_size = total_frames - current_frame;
370373
screen_pointer1 = screen2;
371374
rand = mosaic_random_offset[total_frames - current_frame - 1];
372375
} else {
373-
// remove when off-by-one error is fixed
374-
const int off_one_fix = -1;
375-
m_size = current_frame + 2 + off_one_fix;
376+
m_size = current_frame + 1;
376377
screen_pointer1 = screen1;
377-
rand = mosaic_random_offset[current_frame + off_one_fix];
378+
rand = mosaic_random_offset[current_frame];
378379
}
379380

380381
// The offset defines where at (X,Y) the pixel is picked for scaling (nearest neighbour)
@@ -399,11 +400,12 @@ void Transition::Draw(Bitmap& dst) {
399400
case TransitionWaveIn:
400401
case TransitionWaveOut:
401402
{
402-
// If TransitionWaveIn, invert percentage and screen:
403-
auto p = (transition_type == TransitionWaveIn) ? 100 - percentage : percentage;
403+
// If TransitionWaveIn, invert depth, phase and screen:
404+
auto p = (transition_type == TransitionWaveIn) ? total_frames - current_frame : current_frame + 1;
404405
auto& screen = (transition_type == TransitionWaveIn) ? *screen2 : *screen1;
405-
auto depth = p * 40 / 100;
406-
auto phase = p * 5 * M_PI / 100.0 + M_PI;
406+
auto depth = p;
407+
auto phase = p * 5 * M_PI / tf_off + M_PI;
408+
dst.FillRect(Rect(0, 0, w, h), Color(0, 0, 0, 255));
407409
dst.WaverBlit(0, 0, 1, 1, screen, screen.GetRect(), depth, phase, Opacity::Opaque());
408410
}
409411
break;

0 commit comments

Comments
 (0)