The recording sampled a red brick wall and moved the sliders by three units, which at GIF size is a click that does nothing. The scene now drags the frame cold first and picks a white air conditioner, so the correction is visible and the picker's being absolute - set from the photograph, not from where the sliders were - is what the picture shows. The text says so, and says a blown highlight is refused.
325 lines
8.9 KiB
Python
Executable File
325 lines
8.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""The manual's scenes: `scenes.py OUT_DIR scene [scene...]`, or `all`.
|
||
|
||
Each scene drives the running app through `drive.py` and leaves a PNG or an
|
||
MP4 in OUT_DIR, named after itself. `record.sh` runs them in order and turns
|
||
the MP4s into GIFs.
|
||
|
||
Coordinates are window pixels for a 1600×1100 window over the manual's own
|
||
library (see record.sh): which cell holds which photograph is part of the
|
||
scene, so a different library needs the numbers looked at again. Panel
|
||
coordinates hold for any library.
|
||
"""
|
||
import os
|
||
import sys
|
||
import time
|
||
|
||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||
import drive as dr # noqa: E402
|
||
|
||
OUT = sys.argv[1] if len(sys.argv) > 1 else '.'
|
||
|
||
|
||
def shot(name):
|
||
dr.shot(f'{OUT}/{name}.png')
|
||
|
||
|
||
def rec(name):
|
||
dr.rec_start(f'{OUT}/{name}.mp4')
|
||
|
||
|
||
def cut():
|
||
dr.rec_stop()
|
||
|
||
|
||
def pause(s):
|
||
time.sleep(s)
|
||
|
||
|
||
def hold(px, py, seconds):
|
||
dr.move(px, py)
|
||
pause(0.15)
|
||
dr.x('mousedown', 1)
|
||
pause(seconds)
|
||
dr.x('mouseup', 1)
|
||
|
||
|
||
def wheel(n, px, py):
|
||
dr.move(px, py)
|
||
dr.x('click', '--repeat', abs(n), '--delay', 40, 5 if n > 0 else 4)
|
||
|
||
|
||
def ctrl_wheel(n, px, py):
|
||
dr.move(px, py)
|
||
dr.x('keydown', 'ctrl')
|
||
for _ in range(abs(n)):
|
||
dr.x('click', 5 if n > 0 else 4)
|
||
pause(0.35)
|
||
dr.x('keyup', 'ctrl')
|
||
|
||
|
||
# --- places on the screen ---------------------------------------------------
|
||
LIBRARY = (55, 22) # ‹ Library, in the develop header
|
||
SELECT = (942, 22) # Select / Done, in the library header
|
||
SETTINGS_LIB = (1543, 22)
|
||
SETTINGS_DEV = (1343, 22)
|
||
EXPORT = (720, 22)
|
||
BACK = (60, 22) # ‹ Back, on the settings page
|
||
RAIL = {'photo': (30, 75), 'compose': (30, 130), 'local': (30, 185), 'repair': (30, 240)}
|
||
GROUPS = {'all': 1269, 'optics': 1313, 'light': 1359, 'colour': 1406, 'effects': 1457, 'detail': 1506}
|
||
BEFORE = (210, 1045)
|
||
RESET_ADJUST = (1565, 741) # "reset" in the Adjust heading, All group, scrolled to top
|
||
CELL_TEAPOT = (424, 165)
|
||
CELL_PANO_FIRST = (1264, 165)
|
||
CELL_CHINATOWN = (963, 525)
|
||
CELL_NY_LAST = (1502, 525)
|
||
COLLECTION_ROW = (60, 90)
|
||
|
||
|
||
def group(name):
|
||
dr.click(GROUPS[name], 67)
|
||
pause(0.9)
|
||
|
||
|
||
def to_library():
|
||
dr.click(*LIBRARY)
|
||
pause(2)
|
||
|
||
|
||
def open_chinatown():
|
||
dr.click(*CELL_CHINATOWN)
|
||
pause(6)
|
||
|
||
|
||
def reset_edit():
|
||
group('all')
|
||
wheel(-60, 1420, 700)
|
||
dr.click(*RESET_ADJUST)
|
||
pause(1)
|
||
|
||
|
||
# --- library ----------------------------------------------------------------
|
||
def library():
|
||
shot('library')
|
||
|
||
|
||
def library_rating():
|
||
rec('library-rating')
|
||
dr.move(424, 900); pause(1.0)
|
||
dr.click(444, 939); pause(1.2)
|
||
dr.move(604, 900); pause(0.8)
|
||
dr.click(644, 939); pause(1.2)
|
||
dr.move(800, 700); pause(0.6)
|
||
dr.click(665, 61); pause(1.5) # 3+
|
||
dr.click(384, 61); pause(1.2) # All
|
||
cut()
|
||
|
||
|
||
def library_timeline():
|
||
rec('library-timeline')
|
||
dr.drag(300, 200, 300, 900, 40); pause(1.0)
|
||
dr.drag(300, 900, 300, 150, 40); pause(1.0)
|
||
cut()
|
||
|
||
|
||
def library_thumbsize():
|
||
rec('library-thumbsize')
|
||
ctrl_wheel(-4, 900, 500); pause(0.8)
|
||
ctrl_wheel(4, 900, 500); pause(0.8)
|
||
cut()
|
||
|
||
|
||
def library_selection():
|
||
dr.click(*SELECT); pause(0.5)
|
||
dr.click(*CELL_PANO_FIRST); pause(0.3)
|
||
dr.x('keydown', 'shift'); dr.click(*CELL_NY_LAST); dr.x('keyup', 'shift'); pause(0.8)
|
||
for x in (963, 1143, 1323, 1502):
|
||
dr.x('keydown', 'ctrl'); dr.click(x, 525); dr.x('keyup', 'ctrl'); pause(0.3)
|
||
pause(0.5)
|
||
shot('library-selection')
|
||
|
||
|
||
def library_keywords():
|
||
# Continues from library_selection: twelve frames selected.
|
||
rec('library-keywords')
|
||
dr.click(1117, 1079); pause(1.2)
|
||
for word in ('alps', 'panorama', 'summer'):
|
||
dr.x('type', '--delay', 90, word); dr.x('key', 'Return'); pause(0.7)
|
||
pause(0.8)
|
||
dr.click(800, 673); pause(1.0) # Done
|
||
cut()
|
||
dr.click(*SELECT); pause(0.5) # leave selecting
|
||
|
||
|
||
def library_collections():
|
||
dr.click(212, 22); pause(0.3) # + in the collections header
|
||
dr.x('type', '--delay', 90, 'Alps'); dr.x('key', 'Return'); pause(1.2)
|
||
rec('library-collections')
|
||
dr.drag(*CELL_PANO_FIRST, *COLLECTION_ROW, 40); pause(1.5)
|
||
dr.click(*SELECT); pause(0.5)
|
||
dr.click(424, 350); pause(0.3)
|
||
dr.x('keydown', 'shift'); dr.click(1502, 350); dr.x('keyup', 'shift'); pause(0.8)
|
||
dr.drag(963, 350, *COLLECTION_ROW, 40); pause(1.5)
|
||
dr.click(*SELECT); pause(0.5)
|
||
dr.click(*COLLECTION_ROW); pause(1.5)
|
||
cut()
|
||
shot('library-collection')
|
||
dr.click(60, 48); pause(1.2) # All photographs
|
||
|
||
|
||
# --- develop ----------------------------------------------------------------
|
||
def develop():
|
||
open_chinatown()
|
||
group('all')
|
||
shot('develop')
|
||
|
||
|
||
def develop_groups():
|
||
rec('develop-groups')
|
||
for g in ['optics', 'light', 'colour', 'effects', 'detail', 'all']:
|
||
group(g); pause(0.6)
|
||
cut()
|
||
|
||
|
||
def develop_light():
|
||
group('light')
|
||
rec('develop-light')
|
||
pause(0.5)
|
||
dr.drag(1398, 792, 1422, 792, 25); pause(0.8) # exposure up
|
||
dr.drag(1398, 918, 1320, 918, 25); pause(0.8) # highlights down
|
||
dr.drag(1398, 964, 1450, 964, 25); pause(0.8) # shadows up
|
||
hold(*BEFORE, 1.6); pause(1.0)
|
||
cut()
|
||
reset_edit()
|
||
|
||
|
||
def develop_zoom():
|
||
rec('develop-zoom')
|
||
dr.move(650, 500); pause(0.3)
|
||
dr.x('click', '--repeat', 2, '--delay', 80, 1); pause(1.5)
|
||
dr.drag(650, 500, 900, 700, 30); pause(0.8)
|
||
dr.drag(900, 700, 500, 450, 30); pause(0.8)
|
||
dr.x('click', '--repeat', 2, '--delay', 80, 1); pause(1.2)
|
||
cut()
|
||
|
||
|
||
def develop_wb():
|
||
group('colour')
|
||
rec('develop-wb')
|
||
pause(0.4)
|
||
dr.drag(1398, 826, 1330, 826, 25); pause(1.2) # temperature cold
|
||
dr.click(1487, 776); pause(0.8) # pick
|
||
dr.click(995, 635); pause(1.5) # the white air conditioner
|
||
hold(*BEFORE, 1.4); pause(0.8)
|
||
cut()
|
||
reset_edit()
|
||
|
||
|
||
def compose():
|
||
dr.click(*RAIL['compose']); pause(1.2)
|
||
rec('compose')
|
||
pause(0.4)
|
||
dr.drag(66, 182, 260, 330, 30); pause(0.8)
|
||
dr.drag(1236, 964, 1100, 900, 25); pause(0.8)
|
||
dr.drag(1420, 593, 1448, 593, 20); pause(1.0) # straighten
|
||
dr.click(1466, 647); pause(1.2) # 1:1
|
||
dr.click(1378, 647); pause(1.0) # Original
|
||
dr.click(132, 1045); pause(1.2) # Done composing
|
||
cut()
|
||
shot('compose-done')
|
||
dr.click(1567, 510); pause(1.0) # reset compose
|
||
dr.click(115, 1045); pause(1.0) # refit
|
||
|
||
|
||
def local_segment():
|
||
dr.click(*RAIL['local']); pause(1.2)
|
||
dr.click(1420, 435); pause(14) # Find subjects
|
||
shot('local-categories')
|
||
dr.click(1266, 646); pause(2.5) # Sky
|
||
shot('local-segment')
|
||
|
||
|
||
def local_paint():
|
||
# Continues from local_segment: the sky mask selected and shown.
|
||
rec('local-paint')
|
||
wheel(12, 1420, 800); pause(0.8)
|
||
shot('local-mask-row')
|
||
cut()
|
||
|
||
|
||
def local_done():
|
||
dr.click(62, 1045); pause(1.0) # Done masking
|
||
reset_edit()
|
||
|
||
|
||
def repair():
|
||
dr.click(*RAIL['repair']); pause(1.2)
|
||
rec('repair')
|
||
pause(0.4)
|
||
dr.click(700, 620); pause(3)
|
||
dr.drag(1264, 460, 1330, 460, 20); pause(1.5) # size
|
||
hold(*BEFORE, 1.4); pause(0.8)
|
||
cut()
|
||
dr.click(125, 1045); pause(1.0) # Done repairing
|
||
reset_edit()
|
||
|
||
|
||
def film():
|
||
group('all')
|
||
rec('film')
|
||
dr.click(1420, 779); pause(1.5) # Film ▸
|
||
dr.click(1420, 953); pause(3) # Velvia 100
|
||
hold(*BEFORE, 1.4); pause(0.8)
|
||
cut()
|
||
reset_edit()
|
||
|
||
|
||
def presets():
|
||
dr.click(1420, 692); pause(1.5)
|
||
shot('presets')
|
||
dr.click(800, 783); pause(1.0) # Done
|
||
|
||
|
||
def develop_export():
|
||
dr.click(*EXPORT); pause(8)
|
||
shot('export-done')
|
||
|
||
|
||
# --- panorama ---------------------------------------------------------------
|
||
def panorama():
|
||
to_library()
|
||
library_selection()
|
||
rec('panorama')
|
||
dr.click(1325, 1079); pause(40) # Merge to panorama
|
||
dr.click(184, 637); pause(45) # Fill the border
|
||
dr.click(1543, 22); pause(60) # Merge
|
||
cut()
|
||
shot('panorama-done')
|
||
dr.click(*BACK); pause(2)
|
||
|
||
|
||
# --- settings ---------------------------------------------------------------
|
||
def settings():
|
||
dr.click(*SETTINGS_LIB); pause(2)
|
||
shot('settings')
|
||
wheel(30, 700, 600); pause(1)
|
||
shot('settings-export')
|
||
dr.click(*BACK); pause(1.5)
|
||
|
||
|
||
ALL = [
|
||
'library', 'library_rating', 'library_timeline', 'library_thumbsize',
|
||
'library_selection', 'library_keywords', 'library_collections',
|
||
'develop', 'develop_groups', 'develop_light', 'develop_zoom', 'develop_wb',
|
||
'compose', 'local_segment', 'local_paint', 'local_done', 'repair', 'film',
|
||
'presets', 'panorama', 'settings',
|
||
]
|
||
|
||
if __name__ == '__main__':
|
||
names = sys.argv[2:]
|
||
if names == ['all']:
|
||
names = ALL
|
||
for name in names:
|
||
print(f'-- {name}', flush=True)
|
||
globals()[name]()
|