@caddis/cli 0.4.10 → 0.4.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/bundles/antigravity-plugin/plugin.json +1 -1
  2. package/bundles/antigravity-plugin/scripts/caddis_spawn.py +60 -6
  3. package/bundles/antigravity-plugin/scripts/setup_project_ai.py +10 -0
  4. package/bundles/antigravity-plugin/skills/_registry.md +0 -1
  5. package/bundles/antigravity-plugin/skills/brainstorming/SKILL.md +2 -2
  6. package/bundles/antigravity-plugin/skills/explainer-doc/SKILL.md +1 -1
  7. package/bundles/antigravity-plugin/skills/ship-pr/SKILL.md +1 -1
  8. package/bundles/antigravity-plugin/skills/spawn-session/SKILL.md +15 -0
  9. package/bundles/antigravity-plugin/skills/ui-brief/SKILL.md +6 -1
  10. package/bundles/antigravity-plugin-extras/plugin.json +1 -1
  11. package/bundles/antigravity-plugin-extras/skills/_registry.md +1 -19
  12. package/bundles/codex/.codex/skills/docs/explainer-doc/SKILL.md +1 -1
  13. package/bundles/codex/.codex/skills/workflow/brainstorming/SKILL.md +2 -2
  14. package/bundles/manifest.json +3 -3
  15. package/package.json +1 -1
  16. package/bundles/antigravity-plugin-extras/skills/competitive-ads-extractor/SKILL.md +0 -294
  17. package/bundles/antigravity-plugin-extras/skills/content-research-writer/SKILL.md +0 -539
  18. package/bundles/antigravity-plugin-extras/skills/domain-name-brainstormer/SKILL.md +0 -213
  19. package/bundles/antigravity-plugin-extras/skills/humanizer/SKILL.md +0 -194
  20. package/bundles/antigravity-plugin-extras/skills/image-enhancer/SKILL.md +0 -100
  21. package/bundles/antigravity-plugin-extras/skills/invoice-organizer/SKILL.md +0 -447
  22. package/bundles/antigravity-plugin-extras/skills/job-application/SKILL.md +0 -188
  23. package/bundles/antigravity-plugin-extras/skills/lead-research-assistant/SKILL.md +0 -200
  24. package/bundles/antigravity-plugin-extras/skills/meeting-insights-analyzer/SKILL.md +0 -328
  25. package/bundles/antigravity-plugin-extras/skills/notebooklm/AUTHENTICATION.md +0 -154
  26. package/bundles/antigravity-plugin-extras/skills/notebooklm/SKILL.md +0 -270
  27. package/bundles/antigravity-plugin-extras/skills/notebooklm/references/api_reference.md +0 -309
  28. package/bundles/antigravity-plugin-extras/skills/notebooklm/references/troubleshooting.md +0 -376
  29. package/bundles/antigravity-plugin-extras/skills/notebooklm/references/usage_patterns.md +0 -338
  30. package/bundles/antigravity-plugin-extras/skills/notebooklm/scripts/__init__.py +0 -81
  31. package/bundles/antigravity-plugin-extras/skills/notebooklm/scripts/ask_question.py +0 -256
  32. package/bundles/antigravity-plugin-extras/skills/notebooklm/scripts/auth_manager.py +0 -358
  33. package/bundles/antigravity-plugin-extras/skills/notebooklm/scripts/browser_session.py +0 -255
  34. package/bundles/antigravity-plugin-extras/skills/notebooklm/scripts/browser_utils.py +0 -107
  35. package/bundles/antigravity-plugin-extras/skills/notebooklm/scripts/cleanup_manager.py +0 -302
  36. package/bundles/antigravity-plugin-extras/skills/notebooklm/scripts/config.py +0 -44
  37. package/bundles/antigravity-plugin-extras/skills/notebooklm/scripts/notebook_manager.py +0 -410
  38. package/bundles/antigravity-plugin-extras/skills/notebooklm/scripts/run.py +0 -102
  39. package/bundles/antigravity-plugin-extras/skills/notebooklm/scripts/setup_environment.py +0 -204
  40. package/bundles/antigravity-plugin-extras/skills/onboard-project/SKILL.md +0 -192
  41. package/bundles/antigravity-plugin-extras/skills/pipeline-state/SKILL.md +0 -208
  42. package/bundles/antigravity-plugin-extras/skills/raffle-winner-picker/SKILL.md +0 -159
  43. package/bundles/antigravity-plugin-extras/skills/relay/SKILL.md +0 -246
  44. package/bundles/antigravity-plugin-extras/skills/requesting-code-review/SKILL.md +0 -105
  45. package/bundles/antigravity-plugin-extras/skills/requesting-code-review/code-reviewer.md +0 -146
  46. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/LICENSE.txt +0 -202
  47. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/SKILL.md +0 -646
  48. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/core/color_palettes.py +0 -302
  49. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/core/easing.py +0 -230
  50. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/core/frame_composer.py +0 -469
  51. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/core/gif_builder.py +0 -246
  52. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/core/typography.py +0 -357
  53. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/core/validators.py +0 -264
  54. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/core/visual_effects.py +0 -494
  55. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/requirements.txt +0 -4
  56. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/templates/bounce.py +0 -106
  57. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/templates/explode.py +0 -331
  58. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/templates/fade.py +0 -329
  59. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/templates/flip.py +0 -291
  60. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/templates/kaleidoscope.py +0 -211
  61. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/templates/morph.py +0 -329
  62. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/templates/move.py +0 -293
  63. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/templates/pulse.py +0 -268
  64. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/templates/shake.py +0 -127
  65. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/templates/slide.py +0 -291
  66. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/templates/spin.py +0 -269
  67. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/templates/wiggle.py +0 -300
  68. package/bundles/antigravity-plugin-extras/skills/slack-gif-creator/templates/zoom.py +0 -312
  69. package/bundles/antigravity-plugin-extras/skills/state-tracking/SKILL.md +0 -131
  70. package/bundles/antigravity-plugin-extras/skills/video-downloader/SKILL.md +0 -107
  71. package/bundles/antigravity-plugin-extras/skills/youtube-transcript/SKILL.md +0 -416
  72. package/bundles/codex/.codex/skills/workflow/golden-plan/SKILL.md +0 -586
  73. /package/bundles/{antigravity-plugin → antigravity-plugin-extras}/skills/golden-plan/SKILL.md +0 -0
@@ -1,291 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Flip Animation - 3D-style card flip and rotation effects.
4
-
5
- Creates horizontal and vertical flips with perspective.
6
- """
7
-
8
- import sys
9
- from pathlib import Path
10
- import math
11
-
12
- sys.path.append(str(Path(__file__).parent.parent))
13
-
14
- from PIL import Image
15
- from core.gif_builder import GIFBuilder
16
- from core.frame_composer import create_blank_frame, draw_emoji_enhanced
17
- from core.easing import interpolate
18
-
19
-
20
- def create_flip_animation(
21
- object1_data: dict,
22
- object2_data: dict | None = None,
23
- num_frames: int = 30,
24
- flip_axis: str = 'horizontal', # 'horizontal', 'vertical'
25
- easing: str = 'ease_in_out',
26
- object_type: str = 'emoji',
27
- center_pos: tuple[int, int] = (240, 240),
28
- frame_width: int = 480,
29
- frame_height: int = 480,
30
- bg_color: tuple[int, int, int] = (255, 255, 255)
31
- ) -> list[Image.Image]:
32
- """
33
- Create 3D-style flip animation.
34
-
35
- Args:
36
- object1_data: First object (front side)
37
- object2_data: Second object (back side, None = same as front)
38
- num_frames: Number of frames
39
- flip_axis: Axis to flip around
40
- easing: Easing function
41
- object_type: Type of objects
42
- center_pos: Center position
43
- frame_width: Frame width
44
- frame_height: Frame height
45
- bg_color: Background color
46
-
47
- Returns:
48
- List of frames
49
- """
50
- frames = []
51
-
52
- if object2_data is None:
53
- object2_data = object1_data
54
-
55
- for i in range(num_frames):
56
- t = i / (num_frames - 1) if num_frames > 1 else 0
57
- frame = create_blank_frame(frame_width, frame_height, bg_color)
58
-
59
- # Calculate rotation angle (0 to 180 degrees)
60
- angle = interpolate(0, 180, t, easing)
61
-
62
- # Determine which side is visible and calculate scale
63
- if angle < 90:
64
- # Front side visible
65
- current_object = object1_data
66
- scale_factor = math.cos(math.radians(angle))
67
- else:
68
- # Back side visible
69
- current_object = object2_data
70
- scale_factor = abs(math.cos(math.radians(angle)))
71
-
72
- # Don't draw when edge-on (very thin)
73
- if scale_factor < 0.05:
74
- frames.append(frame)
75
- continue
76
-
77
- if object_type == 'emoji':
78
- size = current_object['size']
79
-
80
- # Create emoji on canvas
81
- canvas_size = size * 2
82
- emoji_canvas = Image.new('RGBA', (canvas_size, canvas_size), (0, 0, 0, 0))
83
-
84
- draw_emoji_enhanced(
85
- emoji_canvas,
86
- emoji=current_object['emoji'],
87
- position=(canvas_size // 2 - size // 2, canvas_size // 2 - size // 2),
88
- size=size,
89
- shadow=False
90
- )
91
-
92
- # Apply flip scaling
93
- if flip_axis == 'horizontal':
94
- # Scale horizontally for horizontal flip
95
- new_width = max(1, int(canvas_size * scale_factor))
96
- new_height = canvas_size
97
- else:
98
- # Scale vertically for vertical flip
99
- new_width = canvas_size
100
- new_height = max(1, int(canvas_size * scale_factor))
101
-
102
- # Resize to simulate 3D rotation
103
- emoji_scaled = emoji_canvas.resize((new_width, new_height), Image.LANCZOS)
104
-
105
- # Position centered
106
- paste_x = center_pos[0] - new_width // 2
107
- paste_y = center_pos[1] - new_height // 2
108
-
109
- # Composite onto frame
110
- frame_rgba = frame.convert('RGBA')
111
- frame_rgba.paste(emoji_scaled, (paste_x, paste_y), emoji_scaled)
112
- frame = frame_rgba.convert('RGB')
113
-
114
- elif object_type == 'text':
115
- from core.typography import draw_text_with_outline
116
-
117
- # Create text on canvas
118
- text = current_object.get('text', 'FLIP')
119
- font_size = current_object.get('font_size', 50)
120
-
121
- canvas_size = max(frame_width, frame_height)
122
- text_canvas = Image.new('RGBA', (canvas_size, canvas_size), (0, 0, 0, 0))
123
-
124
- # Draw on RGB for text rendering
125
- text_canvas_rgb = text_canvas.convert('RGB')
126
- text_canvas_rgb.paste(bg_color, (0, 0, canvas_size, canvas_size))
127
-
128
- draw_text_with_outline(
129
- text_canvas_rgb,
130
- text=text,
131
- position=(canvas_size // 2, canvas_size // 2),
132
- font_size=font_size,
133
- text_color=current_object.get('text_color', (0, 0, 0)),
134
- outline_color=current_object.get('outline_color', (255, 255, 255)),
135
- outline_width=3,
136
- centered=True
137
- )
138
-
139
- # Make background transparent
140
- text_canvas = text_canvas_rgb.convert('RGBA')
141
- data = text_canvas.getdata()
142
- new_data = []
143
- for item in data:
144
- if item[:3] == bg_color:
145
- new_data.append((255, 255, 255, 0))
146
- else:
147
- new_data.append(item)
148
- text_canvas.putdata(new_data)
149
-
150
- # Apply flip scaling
151
- if flip_axis == 'horizontal':
152
- new_width = max(1, int(canvas_size * scale_factor))
153
- new_height = canvas_size
154
- else:
155
- new_width = canvas_size
156
- new_height = max(1, int(canvas_size * scale_factor))
157
-
158
- text_scaled = text_canvas.resize((new_width, new_height), Image.LANCZOS)
159
-
160
- # Center and crop
161
- if flip_axis == 'horizontal':
162
- left = (new_width - frame_width) // 2 if new_width > frame_width else 0
163
- top = (canvas_size - frame_height) // 2
164
- paste_x = center_pos[0] - min(new_width, frame_width) // 2
165
- paste_y = 0
166
-
167
- text_cropped = text_scaled.crop((
168
- left,
169
- top,
170
- left + min(new_width, frame_width),
171
- top + frame_height
172
- ))
173
- else:
174
- left = (canvas_size - frame_width) // 2
175
- top = (new_height - frame_height) // 2 if new_height > frame_height else 0
176
- paste_x = 0
177
- paste_y = center_pos[1] - min(new_height, frame_height) // 2
178
-
179
- text_cropped = text_scaled.crop((
180
- left,
181
- top,
182
- left + frame_width,
183
- top + min(new_height, frame_height)
184
- ))
185
-
186
- frame_rgba = frame.convert('RGBA')
187
- frame_rgba.paste(text_cropped, (paste_x, paste_y), text_cropped)
188
- frame = frame_rgba.convert('RGB')
189
-
190
- frames.append(frame)
191
-
192
- return frames
193
-
194
-
195
- def create_quick_flip(
196
- emoji_front: str,
197
- emoji_back: str,
198
- num_frames: int = 20,
199
- frame_size: int = 128
200
- ) -> list[Image.Image]:
201
- """
202
- Create quick flip for emoji GIFs.
203
-
204
- Args:
205
- emoji_front: Front emoji
206
- emoji_back: Back emoji
207
- num_frames: Number of frames
208
- frame_size: Frame size (square)
209
-
210
- Returns:
211
- List of frames
212
- """
213
- return create_flip_animation(
214
- object1_data={'emoji': emoji_front, 'size': 80},
215
- object2_data={'emoji': emoji_back, 'size': 80},
216
- num_frames=num_frames,
217
- flip_axis='horizontal',
218
- easing='ease_in_out',
219
- object_type='emoji',
220
- center_pos=(frame_size // 2, frame_size // 2),
221
- frame_width=frame_size,
222
- frame_height=frame_size,
223
- bg_color=(255, 255, 255)
224
- )
225
-
226
-
227
- def create_nope_flip(
228
- num_frames: int = 25,
229
- frame_width: int = 480,
230
- frame_height: int = 480
231
- ) -> list[Image.Image]:
232
- """
233
- Create "nope" reaction flip (like flipping table).
234
-
235
- Args:
236
- num_frames: Number of frames
237
- frame_width: Frame width
238
- frame_height: Frame height
239
-
240
- Returns:
241
- List of frames
242
- """
243
- return create_flip_animation(
244
- object1_data={'text': 'NOPE', 'font_size': 80, 'text_color': (255, 50, 50)},
245
- object2_data={'text': 'NOPE', 'font_size': 80, 'text_color': (255, 50, 50)},
246
- num_frames=num_frames,
247
- flip_axis='horizontal',
248
- easing='ease_out',
249
- object_type='text',
250
- frame_width=frame_width,
251
- frame_height=frame_height,
252
- bg_color=(255, 255, 255)
253
- )
254
-
255
-
256
- # Example usage
257
- if __name__ == '__main__':
258
- print("Creating flip animations...")
259
-
260
- builder = GIFBuilder(width=480, height=480, fps=20)
261
-
262
- # Example 1: Emoji flip
263
- frames = create_flip_animation(
264
- object1_data={'emoji': '😊', 'size': 120},
265
- object2_data={'emoji': '😂', 'size': 120},
266
- num_frames=30,
267
- flip_axis='horizontal',
268
- object_type='emoji'
269
- )
270
- builder.add_frames(frames)
271
- builder.save('flip_emoji.gif', num_colors=128)
272
-
273
- # Example 2: Text flip
274
- builder.clear()
275
- frames = create_flip_animation(
276
- object1_data={'text': 'YES', 'font_size': 80, 'text_color': (100, 200, 100)},
277
- object2_data={'text': 'NO', 'font_size': 80, 'text_color': (200, 100, 100)},
278
- num_frames=30,
279
- flip_axis='vertical',
280
- object_type='text'
281
- )
282
- builder.add_frames(frames)
283
- builder.save('flip_text.gif', num_colors=128)
284
-
285
- # Example 3: Quick flip (emoji size)
286
- builder = GIFBuilder(width=128, height=128, fps=15)
287
- frames = create_quick_flip('👍', '👎', num_frames=20)
288
- builder.add_frames(frames)
289
- builder.save('flip_quick.gif', num_colors=48, optimize_for_emoji=True)
290
-
291
- print("Created flip animations!")
@@ -1,211 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Kaleidoscope Effect - Create mirror/rotation effects.
4
-
5
- Apply kaleidoscope effects to frames or objects for psychedelic visuals.
6
- """
7
-
8
- import sys
9
- from pathlib import Path
10
- import math
11
-
12
- sys.path.append(str(Path(__file__).parent.parent))
13
-
14
- from PIL import Image, ImageOps, ImageDraw
15
- import numpy as np
16
-
17
-
18
- def apply_kaleidoscope(frame: Image.Image, segments: int = 8,
19
- center: tuple[int, int] | None = None) -> Image.Image:
20
- """
21
- Apply kaleidoscope effect by mirroring/rotating frame sections.
22
-
23
- Args:
24
- frame: Input frame
25
- segments: Number of mirror segments (4, 6, 8, 12 work well)
26
- center: Center point for effect (None = frame center)
27
-
28
- Returns:
29
- Frame with kaleidoscope effect
30
- """
31
- width, height = frame.size
32
-
33
- if center is None:
34
- center = (width // 2, height // 2)
35
-
36
- # Create output frame
37
- output = Image.new('RGB', (width, height))
38
-
39
- # Calculate angle per segment
40
- angle_per_segment = 360 / segments
41
-
42
- # For simplicity, we'll create a radial mirror effect
43
- # A full implementation would rotate and mirror properly
44
- # This is a simplified version that creates interesting patterns
45
-
46
- # Convert to numpy for easier manipulation
47
- frame_array = np.array(frame)
48
- output_array = np.zeros_like(frame_array)
49
-
50
- center_x, center_y = center
51
-
52
- # Create wedge mask and mirror it
53
- for y in range(height):
54
- for x in range(width):
55
- # Calculate angle from center
56
- dx = x - center_x
57
- dy = y - center_y
58
-
59
- angle = (math.degrees(math.atan2(dy, dx)) + 180) % 360
60
- distance = math.sqrt(dx * dx + dy * dy)
61
-
62
- # Which segment does this pixel belong to?
63
- segment = int(angle / angle_per_segment)
64
-
65
- # Mirror angle within segment
66
- segment_angle = angle % angle_per_segment
67
- if segment % 2 == 1: # Mirror every other segment
68
- segment_angle = angle_per_segment - segment_angle
69
-
70
- # Calculate source position
71
- source_angle = segment_angle + (segment // 2) * angle_per_segment * 2
72
- source_angle_rad = math.radians(source_angle - 180)
73
-
74
- source_x = int(center_x + distance * math.cos(source_angle_rad))
75
- source_y = int(center_y + distance * math.sin(source_angle_rad))
76
-
77
- # Bounds check
78
- if 0 <= source_x < width and 0 <= source_y < height:
79
- output_array[y, x] = frame_array[source_y, source_x]
80
- else:
81
- output_array[y, x] = frame_array[y, x]
82
-
83
- return Image.fromarray(output_array)
84
-
85
-
86
- def apply_simple_mirror(frame: Image.Image, mode: str = 'quad') -> Image.Image:
87
- """
88
- Apply simple mirror effect (faster than full kaleidoscope).
89
-
90
- Args:
91
- frame: Input frame
92
- mode: 'horizontal', 'vertical', 'quad' (4-way), 'radial'
93
-
94
- Returns:
95
- Mirrored frame
96
- """
97
- width, height = frame.size
98
- center_x, center_y = width // 2, height // 2
99
-
100
- if mode == 'horizontal':
101
- # Mirror left half to right
102
- left_half = frame.crop((0, 0, center_x, height))
103
- left_flipped = ImageOps.mirror(left_half)
104
- result = frame.copy()
105
- result.paste(left_flipped, (center_x, 0))
106
- return result
107
-
108
- elif mode == 'vertical':
109
- # Mirror top half to bottom
110
- top_half = frame.crop((0, 0, width, center_y))
111
- top_flipped = ImageOps.flip(top_half)
112
- result = frame.copy()
113
- result.paste(top_flipped, (0, center_y))
114
- return result
115
-
116
- elif mode == 'quad':
117
- # 4-way mirror (top-left quadrant mirrored to all)
118
- quad = frame.crop((0, 0, center_x, center_y))
119
-
120
- result = Image.new('RGB', (width, height))
121
-
122
- # Top-left (original)
123
- result.paste(quad, (0, 0))
124
-
125
- # Top-right (horizontal mirror)
126
- result.paste(ImageOps.mirror(quad), (center_x, 0))
127
-
128
- # Bottom-left (vertical mirror)
129
- result.paste(ImageOps.flip(quad), (0, center_y))
130
-
131
- # Bottom-right (both mirrors)
132
- result.paste(ImageOps.flip(ImageOps.mirror(quad)), (center_x, center_y))
133
-
134
- return result
135
-
136
- else:
137
- return frame
138
-
139
-
140
- def create_kaleidoscope_animation(
141
- base_frame: Image.Image | None = None,
142
- num_frames: int = 30,
143
- segments: int = 8,
144
- rotation_speed: float = 1.0,
145
- width: int = 480,
146
- height: int = 480
147
- ) -> list[Image.Image]:
148
- """
149
- Create animated kaleidoscope effect.
150
-
151
- Args:
152
- base_frame: Frame to apply effect to (or None for demo pattern)
153
- num_frames: Number of frames
154
- segments: Kaleidoscope segments
155
- rotation_speed: How fast pattern rotates (0.5-2.0)
156
- width: Frame width if generating demo
157
- height: Frame height if generating demo
158
-
159
- Returns:
160
- List of frames with kaleidoscope effect
161
- """
162
- frames = []
163
-
164
- # Create demo pattern if no base frame
165
- if base_frame is None:
166
- base_frame = Image.new('RGB', (width, height), (255, 255, 255))
167
- draw = ImageDraw.Draw(base_frame)
168
-
169
- # Draw some colored shapes
170
- from core.color_palettes import get_palette
171
- palette = get_palette('vibrant')
172
-
173
- colors = [palette['primary'], palette['secondary'], palette['accent']]
174
-
175
- for i, color in enumerate(colors):
176
- x = width // 2 + int(100 * math.cos(i * 2 * math.pi / 3))
177
- y = height // 2 + int(100 * math.sin(i * 2 * math.pi / 3))
178
- draw.ellipse([x - 40, y - 40, x + 40, y + 40], fill=color)
179
-
180
- # Rotate base frame and apply kaleidoscope
181
- for i in range(num_frames):
182
- angle = (i / num_frames) * 360 * rotation_speed
183
-
184
- # Rotate base frame
185
- rotated = base_frame.rotate(angle, resample=Image.BICUBIC)
186
-
187
- # Apply kaleidoscope
188
- kaleido_frame = apply_kaleidoscope(rotated, segments=segments)
189
-
190
- frames.append(kaleido_frame)
191
-
192
- return frames
193
-
194
-
195
- # Example usage
196
- if __name__ == '__main__':
197
- from core.gif_builder import GIFBuilder
198
-
199
- print("Creating kaleidoscope GIF...")
200
-
201
- builder = GIFBuilder(width=480, height=480, fps=20)
202
-
203
- # Create kaleidoscope animation
204
- frames = create_kaleidoscope_animation(
205
- num_frames=40,
206
- segments=8,
207
- rotation_speed=0.5
208
- )
209
-
210
- builder.add_frames(frames)
211
- builder.save('kaleidoscope_test.gif', num_colors=128)