44import csv
55import argparse
66import pygame
7+ import math
78import random
89import platform
910from pygame .locals import *
@@ -212,6 +213,10 @@ def choose_effect(selected: str):
212213 "Domino" ,
213214 "Dice" ,
214215 "Balls" ,
216+ "Pie" ,
217+ "Salmi" ,
218+ "Puzzle" ,
219+ "Wipe" ,
215220 ]
216221 if selected == "Random" :
217222 return random .choice (effects )
@@ -326,7 +331,6 @@ def draw_flip_transition(screen, screen_size, current_image, next_image, alpha,
326331 original_w , original_h = current_image .get_width (), current_image .get_height ()
327332 new_w = max (1 , int (original_w * (1.0 - frac )))
328333 scaled = pygame .transform .scale (current_image , (new_w , original_h ))
329- scaled = pygame .transform .flip (scaled , True , False )
330334 scaled .set_alpha (int (255 * (1.0 - frac )))
331335 screen .blit (scaled , scaled .get_rect (center = (w_center , h_center )))
332336 else :
@@ -335,8 +339,6 @@ def draw_flip_transition(screen, screen_size, current_image, next_image, alpha,
335339 original_w , original_h = next_image .get_width (), next_image .get_height ()
336340 new_w = max (1 , int (original_w * frac ))
337341 scaled = pygame .transform .scale (next_image , (new_w , original_h ))
338- if new_w < original_w :
339- scaled = pygame .transform .flip (scaled , True , False )
340342 scaled .set_alpha (int (255 * frac ))
341343 screen .blit (scaled , scaled .get_rect (center = (w_center , h_center )))
342344
@@ -457,7 +459,7 @@ def subdivide(x, y, w, h, d):
457459
458460def draw_fractal_transition (screen , screen_size , current_image , next_image , alpha , transition_cache ):
459461 if 'fractal_blocks' not in transition_cache :
460- transition_cache ['fractal_blocks' ] = generate_fractal_blocks (screen_size , depth = 5 )
462+ transition_cache ['fractal_blocks' ] = generate_fractal_blocks (screen_size , depth = 6 )
461463 blocks = transition_cache ['fractal_blocks' ]
462464 total_blocks = len (blocks )
463465 revealed_count = int (total_blocks * alpha )
@@ -522,6 +524,170 @@ def draw_balls_transition(screen, screen_size, current_image, next_image, alpha,
522524 screen .blit (next_copy , next_copy .get_rect (center = (w_center , h_center )))
523525
524526
527+ def draw_pie_transition (screen , screen_size , current_image , next_image , alpha , transition_cache ):
528+ w_center , h_center = screen_size [0 ] // 2 , screen_size [1 ] // 2
529+ if current_image :
530+ temp_current = current_image .copy ()
531+ temp_current .set_alpha (int (255 * (1.0 - alpha )))
532+ screen .blit (temp_current , temp_current .get_rect (center = (w_center , h_center )))
533+ if next_image :
534+ if 'pie_slices' not in transition_cache :
535+ transition_cache ['pie_slices' ] = 8
536+ slices = transition_cache ['pie_slices' ]
537+ progress = alpha * slices
538+ mask = pygame .Surface (next_image .get_size (), pygame .SRCALPHA )
539+ mask .fill ((0 , 0 , 0 , 0 ))
540+ center_x = next_image .get_width () / 2
541+ center_y = next_image .get_height () / 2
542+ radius = max (next_image .get_width (), next_image .get_height ()) / 2
543+ for i in range (slices ):
544+ visible = progress - i
545+ if visible <= 0 :
546+ continue
547+ if visible > 1 :
548+ visible = 1
549+ start_angle = (2 * math .pi / slices ) * i
550+ end_angle = start_angle + (2 * math .pi / slices ) * visible
551+ points = [(center_x , center_y )]
552+ steps = max (int (20 * visible ), 1 )
553+ for j in range (steps + 1 ):
554+ angle = start_angle + (end_angle - start_angle ) * (j / steps )
555+ x = center_x + radius * math .cos (angle )
556+ y = center_y + radius * math .sin (angle )
557+ points .append ((x , y ))
558+ pygame .draw .polygon (mask , (255 , 255 , 255 , 255 ), points )
559+ next_copy = next_image .copy ()
560+ next_copy .blit (mask , (0 , 0 ), special_flags = pygame .BLEND_RGBA_MULT )
561+ next_copy .set_alpha (int (255 * alpha ))
562+ screen .blit (next_copy , next_copy .get_rect (center = (w_center , h_center )))
563+
564+
565+ def draw_salmi_transition (screen , screen_size , current_image , next_image , alpha , transition_cache ):
566+ w_center , h_center = screen_size [0 ] // 2 , screen_size [1 ] // 2
567+ if current_image :
568+ temp_current = current_image .copy ()
569+ temp_current .set_alpha (int (255 * (1.0 - alpha )))
570+ screen .blit (temp_current , temp_current .get_rect (center = (w_center , h_center )))
571+ if next_image :
572+ img_w , img_h = next_image .get_width (), next_image .get_height ()
573+ if 'salmi_shapes' not in transition_cache :
574+ shapes = []
575+ count = max (20 , (img_w * img_h ) // (150 * 150 ))
576+ for _ in range (count ):
577+ x = random .randint (0 , img_w )
578+ y = random .randint (0 , img_h )
579+ w = random .randint (img_w // 20 , img_w // 8 )
580+ h = random .randint (img_h // 20 , img_h // 8 )
581+ angle = random .uniform (0 , 360 )
582+ shapes .append ((x , y , w , h , angle ))
583+ transition_cache ['salmi_shapes' ] = shapes
584+ shapes = transition_cache ['salmi_shapes' ]
585+ total = len (shapes )
586+ reveal_count = int (total * alpha )
587+ mask = pygame .Surface (next_image .get_size (), pygame .SRCALPHA )
588+ mask .fill ((0 , 0 , 0 , 0 ))
589+ for i in range (reveal_count ):
590+ cx , cy , w , h , angle = shapes [i ]
591+ ellipse_surf = pygame .Surface ((w , h ), pygame .SRCALPHA )
592+ pygame .draw .ellipse (ellipse_surf , (255 , 255 , 255 , 255 ), (0 , 0 , w , h ))
593+ rotated = pygame .transform .rotate (ellipse_surf , angle )
594+ rect = rotated .get_rect (center = (cx , cy ))
595+ mask .blit (rotated , rect )
596+ next_copy = next_image .copy ()
597+ next_copy .blit (mask , (0 , 0 ), special_flags = pygame .BLEND_RGBA_MULT )
598+ next_copy .set_alpha (int (255 * alpha ))
599+ screen .blit (next_copy , next_copy .get_rect (center = (w_center , h_center )))
600+
601+
602+ def draw_puzzle_transition (screen , screen_size , current_image , next_image , alpha , transition_cache ):
603+ w_center , h_center = screen_size [0 ] // 2 , screen_size [1 ] // 2
604+ if current_image :
605+ temp_current = current_image .copy ()
606+ temp_current .set_alpha (int (255 * (1.0 - alpha )))
607+ screen .blit (temp_current , temp_current .get_rect (center = (w_center , h_center )))
608+ if next_image :
609+ img_w , img_h = next_image .get_width (), next_image .get_height ()
610+ grid_rows = 4
611+ grid_cols = 4
612+ tile_w = img_w // grid_cols
613+ tile_h = img_h // grid_rows
614+ if 'puzzle_tiles' not in transition_cache :
615+ tiles = []
616+ for row in range (grid_rows ):
617+ for col in range (grid_cols ):
618+ x_src = col * tile_w
619+ y_src = row * tile_h
620+ if col < grid_cols - 1 :
621+ w = tile_w
622+ else :
623+ w = img_w - tile_w * col
624+ if row < grid_rows - 1 :
625+ h = tile_h
626+ else :
627+ h = img_h - tile_h * row
628+ dest_x = x_src
629+ dest_y = y_src
630+ start_x = random .randint (- img_w // 2 , img_w + img_w // 2 )
631+ start_y = random .randint (- img_h // 2 , img_h + img_h // 2 )
632+ tiles .append ((x_src , y_src , w , h , start_x , start_y , dest_x , dest_y ))
633+ transition_cache ['puzzle_tiles' ] = tiles
634+ tiles = transition_cache ['puzzle_tiles' ]
635+ for (x_src , y_src , w , h , sx , sy , dx , dy ) in tiles :
636+ cur_x = sx + (dx - sx ) * alpha
637+ cur_y = sy + (dy - sy ) * alpha
638+ tile_surf = next_image .subsurface ((x_src , y_src , w , h )).copy ()
639+ tile_surf .set_alpha (int (255 * alpha ))
640+ screen_x = w_center - img_w // 2 + cur_x
641+ screen_y = h_center - img_h // 2 + cur_y
642+ screen .blit (tile_surf , (screen_x , screen_y ))
643+
644+
645+ def draw_wipe_transition (screen , screen_size , current_image , next_image , alpha , transition_cache ):
646+ screen_width , screen_height = screen_size
647+ w_center , h_center = screen_width // 2 , screen_height // 2
648+ if current_image :
649+ temp_current = current_image .copy ()
650+ temp_current .set_alpha (int (255 * (1.0 - alpha )))
651+ screen .blit (temp_current , temp_current .get_rect (center = (w_center , h_center )))
652+ if next_image :
653+ if 'wipe_orient' not in transition_cache :
654+ transition_cache ['wipe_orient' ] = random .choice (["LR" , "RL" , "UD" , "DU" ])
655+ orient = transition_cache ['wipe_orient' ]
656+ img_w , img_h = next_image .get_width (), next_image .get_height ()
657+ offset_x = w_center - img_w // 2
658+ offset_y = h_center - img_h // 2
659+ if orient == "LR" :
660+ width_portion = int (img_w * alpha )
661+ if width_portion > 0 :
662+ part = next_image .subsurface ((0 , 0 , width_portion , img_h ))
663+ part_copy = part .copy ()
664+ part_copy .set_alpha (int (255 * alpha ))
665+ screen .blit (part_copy , (offset_x , offset_y ))
666+ elif orient == "RL" :
667+ width_portion = int (img_w * alpha )
668+ if width_portion > 0 :
669+ x_src = img_w - width_portion
670+ part = next_image .subsurface ((x_src , 0 , width_portion , img_h ))
671+ part_copy = part .copy ()
672+ part_copy .set_alpha (int (255 * alpha ))
673+ screen .blit (part_copy , (offset_x + x_src , offset_y ))
674+ elif orient == "UD" :
675+ height_portion = int (img_h * alpha )
676+ if height_portion > 0 :
677+ part = next_image .subsurface ((0 , 0 , img_w , height_portion ))
678+ part_copy = part .copy ()
679+ part_copy .set_alpha (int (255 * alpha ))
680+ screen .blit (part_copy , (offset_x , offset_y ))
681+ elif orient == "DU" :
682+ height_portion = int (img_h * alpha )
683+ if height_portion > 0 :
684+ y_src = img_h - height_portion
685+ part = next_image .subsurface ((0 , y_src , img_w , height_portion ))
686+ part_copy = part .copy ()
687+ part_copy .set_alpha (int (255 * alpha ))
688+ screen .blit (part_copy , (offset_x , offset_y + y_src ))
689+
690+
525691def draw_domino_transition (screen , screen_size , current_image , next_image , alpha , transition_cache ):
526692 screen_width , screen_height = screen_size
527693 w_center , h_center = screen_width // 2 , screen_height // 2
@@ -560,8 +726,8 @@ def draw_dice_transition(screen, screen_size, current_image, next_image, alpha,
560726 temp_current .set_alpha (int (255 * (1.0 - alpha )))
561727 screen .blit (temp_current , temp_current .get_rect (center = (w_center , h_center )))
562728 if next_image :
563- grid_rows = 3
564- grid_cols = 3
729+ grid_rows = 5
730+ grid_cols = 5
565731 total_cells = grid_rows * grid_cols
566732 cells_to_reveal = int (total_cells * alpha )
567733 cell_w = next_image .get_width () // grid_cols
@@ -652,6 +818,14 @@ def draw_transition(screen, screen_size, current_image, next_image, alpha, effec
652818 draw_domino_transition (screen , screen_size , current_image , next_image , alpha , transition_cache )
653819 elif effect == 'Dice' :
654820 draw_dice_transition (screen , screen_size , current_image , next_image , alpha , transition_cache )
821+ elif effect == 'Pie' :
822+ draw_pie_transition (screen , screen_size , current_image , next_image , alpha , transition_cache )
823+ elif effect == 'Salmi' :
824+ draw_salmi_transition (screen , screen_size , current_image , next_image , alpha , transition_cache )
825+ elif effect == 'Puzzle' :
826+ draw_puzzle_transition (screen , screen_size , current_image , next_image , alpha , transition_cache )
827+ elif effect == 'Wipe' :
828+ draw_wipe_transition (screen , screen_size , current_image , next_image , alpha , transition_cache )
655829 elif effect == 'Balls' :
656830 draw_balls_transition (screen , screen_size , current_image , next_image , alpha , transition_cache )
657831 else :
@@ -1149,6 +1323,14 @@ def apply_preset():
11491323 ignore_transition_effect_var .set (False )
11501324 shuffle_var .set (False )
11511325 effect_var .set ("Balls" )
1326+ try :
1327+ globals ()['check_interval_var' ] = float (interval_entry .get ())
1328+ except Exception :
1329+ pass
1330+ try :
1331+ globals ()['transition_duration_var' ] = float (transition_entry .get ())
1332+ except Exception :
1333+ pass
11521334 preset_default = tk .Radiobutton (preset_frame , text = "default values" , variable = preset_var , value = "default" , command = apply_preset )
11531335 preset_slideshow = tk .Radiobutton (preset_frame , text = "Slideshow" , variable = preset_var , value = "slideshow" , command = apply_preset )
11541336 preset_sd_fum = tk .Radiobutton (preset_frame , text = "SD-FUM animation" , variable = preset_var , value = "sd_fum" , command = apply_preset )
@@ -1187,6 +1369,10 @@ def apply_preset():
11871369 "Domino" ,
11881370 "Dice" ,
11891371 "Balls" ,
1372+ "Pie" ,
1373+ "Salmi" ,
1374+ "Puzzle" ,
1375+ "Wipe" ,
11901376 "Random" ,
11911377 ]
11921378 if selected_effect not in effect_options :
0 commit comments