-
-
Save simonw/ef35bb9e6c514d1d596dac9227da482b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import sys | |
| sys.path.insert(0, '/mnt/skills/examples/slack-gif-creator') | |
| from PIL import Image, ImageDraw, ImageFont | |
| from core.gif_builder import GIFBuilder | |
| from core.typography import draw_text_with_outline, TYPOGRAPHY_SCALE | |
| from core.easing import interpolate | |
| from core.visual_effects import ParticleSystem, create_impact_flash | |
| from core.frame_composer import create_gradient_background, draw_emoji_enhanced | |
| from core.color_palettes import get_palette | |
| from core.validators import check_slack_size | |
| import math | |
| # Create a message GIF (480x480, larger and more detailed) | |
| width, height = 480, 480 | |
| fps = 20 | |
| num_frames = 60 # 3 seconds | |
| builder = GIFBuilder(width, height, fps) | |
| # Get a vibrant palette | |
| palette = get_palette('vibrant') | |
| bg_start = (25, 25, 50) # Dark blue | |
| bg_end = (50, 25, 60) # Dark purple | |
| # Animation phases: | |
| # 0-15: MCP side appears (left) | |
| # 16-30: Skills side appears (right) with more flair | |
| # 31-45: Skills gets bigger/more dramatic | |
| # 46-60: Final state with emphasis | |
| for i in range(num_frames): | |
| frame = create_gradient_background(width, height, bg_start, bg_end) | |
| draw = ImageDraw.Draw(frame) | |
| # Divider line in middle | |
| if i > 15: | |
| draw.line([(240, 0), (240, height)], fill=(100, 100, 100), width=3) | |
| # LEFT SIDE - MCPs (appears first, less exciting) | |
| if i >= 5: | |
| t_mcp = min((i - 5) / 10, 1.0) | |
| mcp_y = interpolate(-100, 150, t_mcp, 'ease_out') | |
| # MCP emoji and text (smaller, less impressive) | |
| draw_emoji_enhanced(frame, '🔌', position=(60, int(mcp_y)), size=60, shadow=False) | |
| if i >= 10: | |
| draw_text_with_outline( | |
| frame, "MCPs", | |
| position=(120, int(mcp_y + 30)), | |
| font_size=32, | |
| text_color=(180, 180, 200), | |
| outline_color=(0, 0, 0), | |
| outline_width=2, | |
| centered=True | |
| ) | |
| # Some basic bullets about MCPs | |
| if i >= 15: | |
| mcp_text = [ | |
| "• Basic tools", | |
| "• Limited scope", | |
| "• OK I guess..." | |
| ] | |
| y_pos = 260 | |
| for line in mcp_text: | |
| draw_text_with_outline( | |
| frame, line, | |
| position=(120, y_pos), | |
| font_size=18, | |
| text_color=(160, 160, 180), | |
| outline_color=(0, 0, 0), | |
| outline_width=1, | |
| centered=True | |
| ) | |
| y_pos += 30 | |
| # RIGHT SIDE - Skills (appears second, WAY COOLER) | |
| if i >= 16: | |
| t_skills = min((i - 16) / 10, 1.0) | |
| # Skills bounces in with elastic effect | |
| skills_y = interpolate(-100, 150, t_skills, 'elastic_out') | |
| # Extra pulsing in final phase | |
| pulse_scale = 1.0 | |
| if i >= 31: | |
| pulse_t = (i - 31) / 29 | |
| pulse_scale = 1.0 + math.sin(pulse_t * math.pi * 4) * 0.15 | |
| # Skills emoji (bigger and cooler) | |
| emoji_size = int(80 * pulse_scale) | |
| draw_emoji_enhanced(frame, '⚡', position=(360 - emoji_size//2, int(skills_y)), | |
| size=emoji_size, shadow=True) | |
| if i >= 20: | |
| # Add sparkle particles around Skills | |
| if i >= 31 and i % 4 == 0: | |
| particles = ParticleSystem() | |
| particles.emit_sparkles(x=360, y=int(skills_y + 40), count=3) | |
| particles.render(frame) | |
| text_scale = pulse_scale if i >= 31 else 1.0 | |
| font_size = int(40 * text_scale) | |
| draw_text_with_outline( | |
| frame, "Skills", | |
| position=(360, int(skills_y + 90)), | |
| font_size=font_size, | |
| text_color=(255, 215, 0), # Gold | |
| outline_color=(0, 0, 0), | |
| outline_width=3, | |
| centered=True | |
| ) | |
| # Awesome bullets about Skills | |
| if i >= 25: | |
| skills_text = [ | |
| "✨ Pro features", | |
| "✨ Best practices", | |
| "✨ AMAZING!" | |
| ] | |
| y_pos = 260 | |
| for line in skills_text: | |
| alpha = min((i - 25) / 10, 1.0) | |
| text_color = (255, int(215 * alpha), int(0 * alpha)) | |
| draw_text_with_outline( | |
| frame, line, | |
| position=(360, y_pos), | |
| font_size=20, | |
| text_color=text_color, | |
| outline_color=(0, 0, 0), | |
| outline_width=2, | |
| centered=True | |
| ) | |
| y_pos += 35 | |
| # Flash effect when Skills gets emphasized | |
| if i == 31: | |
| frame = create_impact_flash(frame, (360, 150), radius=150, intensity=0.5) | |
| # Final emphasis - "Skills > MCPs" text at bottom | |
| if i >= 45: | |
| t_final = (i - 45) / 15 | |
| final_y = interpolate(height + 50, 420, t_final, 'ease_out') | |
| draw_text_with_outline( | |
| frame, "Skills > MCPs", | |
| position=(240, int(final_y)), | |
| font_size=45, | |
| text_color=(255, 100, 255), # Hot pink | |
| outline_color=(0, 0, 0), | |
| outline_width=4, | |
| centered=True | |
| ) | |
| builder.add_frame(frame) | |
| # Save the GIF | |
| info = builder.save('/mnt/user-data/outputs/skills_vs_mcps.gif', | |
| num_colors=128, | |
| optimize_for_emoji=False) | |
| print(f"GIF created successfully!") | |
| print(f"Size: {info['size_kb']:.1f} KB ({info['size_mb']:.2f} MB)") | |
| print(f"Frames: {info['frame_count']}") | |
| print(f"Duration: {info['duration_seconds']:.1f}s") | |
| # Validate for Slack | |
| passes, check_info = check_slack_size('/mnt/user-data/outputs/skills_vs_mcps.gif', is_emoji=False) | |
| if passes: | |
| print("✓ Ready for Slack!") | |
| else: | |
| print(f"⚠ File size: {check_info['size_kb']:.1f} KB (limit: {check_info['limit_kb']} KB)") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment