Files

216 lines
11 KiB
Python

"""Bars 88-112: the last drop (key lift) and the outro."""
import math
import os
from anim import *
from kit import *
from devices import *
from engine import LW, LH, hexc
from sc_drop1 import logo, hook_word
# what the frames were drawn with; render.py fills this in from the GL renderer string
RENDERED_WITH = {'line': None}
def cube_rain(E, f, lb0, n=10, floor=1010, step=0.5):
"""A row of little glue blobs; a block drops into each in turn."""
items = []
for k in range(n):
land = lb0 + k * step
x = 140 + (k * 173) % 1640
sz = 50 + 20 * rnd('cs', k)
u = (f.lbeat - land) * S.BEAT
items.append((x, floor - sz, sz, 0.0, 0.1 * f.kick, 0.4, rnd('tint', k) * 0.5, 1.0, u))
cubes(E, f, items)
MONTAGE = [ # local beat, word, plate, painter
(8, 'ANDROID', 'ink'), (12, 'LINUX', 'mint'), (16, 'WINDOWS', 'ink'), (20, 'MACOS', 'glue'),
(24, 'VULKAN', 'ink'), (28, 'OPENGL ES', 'mint'), (32, 'ANY MACHINE', 'ink'), (36, 'OPEN SOURCE', 'glue'),
]
def montage(E, f, i, lb0):
word, kind = MONTAGE[i][1], MONTAGE[i][2]
u = f.lbeat - lb0
b, fg = plate(E, f, kind, grid=True, drift=(40, 0))
size = fit_size(E, word, 1700, cap=330)
screen_cam(E, f, zoom=1 + 0.02 * f.kick + 0.01 * u, shake=12 * math.exp(-u * 4))
faces = FACE_DARK if kind == 'ink' else FACE_LIGHT
line = OUTL if kind == 'ink' else hexc('#2f7d2a')
if word == 'ANDROID':
iso = Iso(1450, 1000, 62)
phone(E, iso, f, faces=faces, screen=screen_layer(E, 'f_phone', 265, 550, paint_voxels, f), line=line)
elif word == 'LINUX':
iso = Iso(1380, 1010, 56)
monitor(E, iso, f, faces=faces, screen=screen_layer(E, 'f_desk', 760, 440, paint_desktop, f), line=line)
elif word == 'WINDOWS':
y = lerp(-200, 820, out_back(clamp01(u / 0.6), 1.2))
file_card(E, 1520, y, 230, 280, 'opengl32', '.dll', rot=0.05)
elif word == 'MACOS':
iso = Iso(1420, 960, 58)
laptop(E, iso, f, y=2.0, faces=FACE_DARK, screen=screen_layer(E, 'f_mac', 600, 380, paint_mac, f),
line=hexc('#0d2213'))
elif word == 'VULKAN':
cubes(E, f, [(1500, 830, 150, f.lt * 1.2, 0.2 * f.kick, 0.4 * f.kick, 0.0, 1.0)],
deep=hexc('#0a2a10'))
E.text('Magma', 1500, 1030, 34, GLUE, font='mono', wght=800)
elif word == 'OPENGL ES':
cubes(E, f, [(1500, 830, 150, -f.lt * 1.2, 0.2 * f.kick, 0.4 * f.kick, 0.0, 1.0)],
deep=hexc('#2e6e2f'))
E.text('Espryt', 1500, 1030, 34, MOSS, font='mono', wght=800)
elif word == 'ANY MACHINE':
pts = [(260 + k * 120, 820 + 40 * math.sin(k * 0.8 + f.lt * 3)) for k in range(13)]
caps = [(p[0], p[1], q[0], q[1], 14, 14) for p, q in zip(pts, pts[1:])]
goo(E, [(pts[0][0], pts[0][1], 50), (pts[-1][0], pts[-1][1], 50)], caps, k=30, bevel=18)
for k in range(6):
ph = (u * 2 + k / 6) % 1
x = lerp(pts[0][0], pts[-1][0], ph)
E.rect(x, 820 + 40 * math.sin((x - 260) / 120 * 0.8 + f.lt * 3), 30, 22, scale_rgb(PALE, 1.5), r=5)
else: # OPEN SOURCE
chip(E, 960, 820, 'LGPL-3.0', 54, GLUE, INK, font='archivo', wght=900, sc=out_back(u / 0.4))
chip(E, 960, 940, 'github.com/MobileGL-Dev/MobileGL', 32, INK, BONE, sc=out_back((u - 0.5) / 0.4))
slam(E, f, word, 960, 330, f.t - u * S.BEAT, size, fg if kind != 'ink' else BONE, punch=0.2)
QUICK = [('ANDROID', 'ink'), ('LINUX', 'glue'), ('WINDOWS', 'ink'), ('MACOS', 'mint'), ('VULKAN', 'ink'),
('OPENGL ES', 'glue'), ('LOCAL', 'ink'), ('REMOTE', 'mint')]
FEATS = ['4.6 CORE', 'SPIR-V', 'VULKAN', 'GLES', 'ANDROID', 'LINUX', 'WINDOWS', 'MACOS', 'EGL', 'GLX', 'WGL', 'CGL',
'INPROC', 'SPAWN', 'TCP', 'OPEN SOURCE']
def final_drop(E, f):
"""Last drop, accelerating: logo, 2-beat montage, 1-beat words, 8th-note features, multiplying hook, collapse."""
lb = f.lbeat
P = {'bloom': 0.6, 'grain': 0.032, 'ca': 0.5 * f.kick}
tb_ = lambda b: f.t - (lb - b) * S.BEAT
if lb < 4: # biggest logo hit + jelly rain
plate(E, f, 'ink', grid=False)
rot = -f.lt * 0.3
for k in range(18):
ang = rot + k * math.pi / 9
E.poly([(960, 330), (960 + 2200 * math.cos(ang - 0.07), 330 + 2200 * math.sin(ang - 0.07)),
(960 + 2200 * math.cos(ang + 0.07), 330 + 2200 * math.sin(ang + 0.07))], a(MOSS, 0.45))
screen_cam(E, f, zoom=1.0 + 0.015 * f.kick + 0.04 * lb / 4, shake=30 * math.exp(-lb * 2.0))
cube_rain(E, f, 0.25, 10, step=0.3)
logo(E, f, 0, 960, 500, scale=1.1)
P['flash'] = (*GLUE[:3], 0.95 * math.exp(-lb * S.BEAT / 0.12))
P['bloom'] = 0.75
elif lb < 20: # montage, 2 beats each
i = int((lb - 4) // 2)
montage(E, f, i, 4 + 2 * i)
elif lb < 28: # one word a beat
k = int(lb - 20)
word, kind = QUICK[k]
b, fg = plate(E, f, kind, grid=False)
screen_cam(E, f, zoom=1 + 0.06 * (lb % 1) + 0.02 * f.kick, rot=(0.02 if k % 2 else -0.02))
speedlines(E, f, 0.35, a(fg, 0.45), seed=k + 80)
slam(E, f, word, 960, 540, tb_(20 + k), fit_size(E, word, 1650, cap=460), fg if kind != 'ink' else NEON,
punch=0.25)
elif lb < 36: # sixteen features on 8ths; the plate still changes only once a beat
kind, k = beat_plate(f, ['glue', 'ink', 'mint', 'ink'], 28)
b, fg = plate(E, f, kind, grid=False)
j = int((lb - 28) * 2)
w = FEATS[j % 16]
c = climax(f, 28, 36)
screen_cam(E, f, zoom=1 + 0.06 * ((lb * 2) % 1) + 0.03 * f.kick, shake=3 + 6 * c)
speedlines(E, f, 0.4 + 0.3 * c, a(fg, 0.45), seed=j + 90)
slam(E, f, w, 960, 500, tb_(28 + j * 0.5), fit_size(E, w, 1550, cap=440), fg if kind != 'ink' else NEON,
punch=0.25)
check(E, 960, 820, 60, fg if kind != 'ink' else GLUE, 16, ((lb * 2) % 1) / 0.4)
E.text(f'{j + 1:2d} / 16', 1750, 1010, 30, a(fg, 0.8), font='mono', wght=800, align='right')
elif lb < 52: # hub: MobileGL in the middle, glue strands shoot out to everything it runs on
plate(E, f, 'ink')
SAT = ['ANDROID', 'LINUX', 'WINDOWS', 'MACOS', 'VULKAN', 'OPENGL ES', 'EGL · GLX · WGL · CGL', 'TCP']
c = climax(f, 44, 52)
spin = 0.15 * (lb - 36) + 2.2 * c * c
screen_cam(E, f, zoom=1.0 + 0.03 * f.kick + 0.12 * c, rot=0.03 * c * math.sin(f.lt * 7), shake=2 + 10 * c)
if lb >= 44:
speedlines(E, f, 0.3 + 0.6 * c, a(GLUE, 0.5), n=80, seed=17)
balls = [(960, 540, 130 + 14 * f.kick)]
caps, pos = [], []
for k, name in enumerate(SAT):
bk = 36 + k
if lb < bk:
continue
ang = k * 2 * math.pi / 8 + spin - math.pi / 2
shoot = out_expo(clamp01((lb - bk) / 0.3))
pull = in_cubic(clamp01((lb - 50) / 2)) # reeled back in at the end
R = (1 - pull) * shoot
x, y = 960 + math.cos(ang) * 640 * R, 540 + math.sin(ang) * 360 * R
caps.append((960, 540, x, y, 14, 10))
balls.append((x, y, 26))
pos.append((x, y, name, shoot * (1 - pull), k))
goo(E, balls, caps, k=40, glow=0.2 + 0.3 * c)
# packets racing out along the strands: 8ths, then 16ths
rate = 2 if lb < 48 else 4
for x, y, name, sh, k in pos:
if sh < 0.95:
continue
ph = (lb * rate + k * 0.37) % 1
E.rect(lerp(960, x, ph), lerp(540, y, ph), 22, 16, scale_rgb(PALE, 1.6), r=4)
for x, y, name, sh, k in pos:
if sh <= 0.05:
continue
fresh = math.exp(-max(0.0, lb - (36 + k)) * 4)
chip(E, x, y, name, 40, INK, scale_rgb(GLUE, 1.0 + 0.8 * fresh), font='archivo', wght=900, sc=sh * (1 + 0.3 * fresh))
E.text('MobileGL', 960, 540, 46 * (1 + 0.05 * f.kick), INK, wght=900)
P['ca'] = 0.4 * f.kick + 1.2 * c
P['bloom'] = 0.6 + 0.3 * c
else: # collapse into one glue drop, faster and faster
plate(E, f, 'ink')
u = in_cubic(clamp01((lb - 52) / 11.0))
c = climax(f, 52, 63)
speedlines(E, f, 0.3 + 0.7 * c, a(GLUE, 0.8), n=110, seed=13)
screen_cam(E, f, zoom=1 + 0.5 * c + 0.03 * f.kick, rot=0.05 * c, shake=3 + 14 * c)
balls = []
for k in range(32):
ang = k * 2 * math.pi / 32 + f.lt * (1.5 + 6 * c) + 3.0 * (lb - 52) / 11
R = 900 * (1 - u) * (0.6 + 0.4 * rnd('cv', k))
balls.append((960 + math.cos(ang) * R, 540 + math.sin(ang) * R * 0.6, 40 + 30 * u))
balls.append((960, 540, 60 + 180 * u))
goo(E, balls, k=60 + 60 * u, glow=0.2 + 0.6 * u)
E.cam = (LW / 2, LH / 2, 1.0 + 0.04 * f.kick, 0.0)
E.text('DESKTOP OPENGL.', 960, 160, 110, a(BONE, 1 - 0.3 * u), wght=900, wdth=100 + 25 * c)
E.text('ANYWHERE.', 960, 930, 130, a(NEON, 1 - 0.3 * u), wght=900, wdth=100 + 25 * c)
P['bloom'] = 0.6 + 0.5 * u
P['ca'] = 0.5 + 1.8 * c
return P
def outro(E, f):
lb = f.lbeat
P = {'bloom': 0.55, 'grain': 0.035}
plate(E, f, 'ink', drift=(3, 0))
fade_out = clamp01((lb - 26) / 5.0)
if lb < 16:
if lb < 0.3:
P['flash'] = (*GLUE[:3], 0.7 * (1 - lb / 0.3))
logo(E, f, 0, 960, 430, splat=True, scale=0.9)
chips_ = [('OpenGL 4.6 Core', GLUE), ('Vulkan', MINT), ('OpenGL ES', MINT), ('LGPL-3.0', PALE)]
total = sum(E.measure(s_, 'mono', 30, 700) + 36 for s_, _ in chips_) + 24 * (len(chips_) - 1)
x = 960 - total / 2
for k, (s, c) in enumerate(chips_):
if lb >= 2 + k * 0.5:
w = chip(E, x, 760, s, 30, INK, c, align='left', sc=out_back((lb - 2 - k * 0.5) / 0.35))
x += w + 24
if lb >= 5:
u = clamp01((lb - 5) / 0.5)
E.text('github.com/MobileGL-Dev/MobileGL', 960, 880, 44, a(BONE, u), font='mono', wght=700)
else:
u = clamp01((lb - 16) / 0.4)
if lb < 16.3:
P['flash'] = (*BONE[:3], 0.5 * (1 - (lb - 16) / 0.3))
cubes(E, f, [(960, 360, 120, f.lt * 0.4, 0.0, 0.0, 0.0, 1.0 - fade_out)])
line = RENDERED_WITH['line']
if line:
E.text('every frame you just saw', 960, 600, 70, a(BONE, u * (1 - fade_out)), wght=800)
E.text('was rendered through MobileGL.', 960, 690, 70, a(NEON, u * (1 - fade_out)), wght=900)
E.text(line, 960, 800, 28, a(BONE, 0.65 * u * (1 - fade_out)), font='mono', wght=600)
else:
E.text('desktop OpenGL. anywhere.', 960, 640, 80, a(BONE, u * (1 - fade_out)), wght=900)
E.text('github.com/MobileGL-Dev/MobileGL', 960, 920, 34, a(GLUE, u * (1 - fade_out)), font='mono', wght=700)
if lb >= 28:
code_line(E, '', 900, 540, 34, chars=0, cursor=True, f=f, alpha=clamp01((lb - 28) / 0.5))
P['fade'] = clamp01((lb - 32) / 1.2)
return P