Режимов выделения стало два, переключаются клавишей D и кнопкой внизу, режим показан её значком. Рамкой по клипам — как было. По времени — протяжка отмечает промежуток по всем дорожкам сразу, он остаётся виден пунктиром, и S режет все дорожки по обоим его краям. Выделенной после этого остаётся ровно середина: следующим действием её обычно удаляют, а выделение на старых клипах убрало бы не то. Курсор теперь идёт за резом: после S встаёт на место реза (в режиме по времени — на начало промежутка), после удаления куска — на место стыка, после схлопывания дыры — туда же. Раньше в это место приходилось попадать мышью заново. Рез кладётся на кадровую сетку: между кадрами времени нет, и рез на доле кадра оставлял бы в монтаже время, которого не бывает. Выделение рамкой требует настоящего перекрытия, а не касания краями: сосед, кончающийся ровно на краю рамки, попадал в выделение из-за разницы в последнем знаке дробей. Кнопка журнала и строка состояния сдвинуты вправо: переключатель выделения встал в один ряд с прилипанием и схлопыванием. Значки — icons8, набор ios-glyphs, авторство дописано в attribution.txt. Набора «ios26» на их раздаче нет (404), взят ближайший по виду к нынешним. Проверки: рез по курсору и по краям промежутка, кадровая сетка, выделение середины, курсор после удаления и после схлопывания.
139 lines
5.3 KiB
Python
139 lines
5.3 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Готовит модуль с данными значков из файлов в icons_online.
|
||
|
||
Зачем модулем, а не файлами рядом с программой: программа не должна
|
||
зависеть от того, лежит ли что-то в её каталоге. Значки маленькие, все
|
||
вместе занимают единицы килобайт.
|
||
|
||
Размер выбран под кнопку: у неё двадцать восемь точек стороны, значку
|
||
достаётся клетка двадцать четыре на двадцать четыре. Уменьшение делает
|
||
convert с обычным сглаживанием, пропорции при этом сохраняются — все
|
||
исходники квадратные, растягивать нечего.
|
||
|
||
Запуск: python3 tools/make_icons.py
|
||
"""
|
||
|
||
import subprocess
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(__file__).resolve().parent.parent
|
||
SRC = ROOT / 'icons_online'
|
||
OUT = ROOT / 'src' / 'uIconData.pas'
|
||
|
||
# Имя в программе -> файл исходника и сторона в точках.
|
||
# Для «схлопывания» берётся вариант на шестьдесят четыре точки: чем крупнее
|
||
# исходник, тем чище получается уменьшение.
|
||
ICONS = [
|
||
('Snap', 'icons8-магнит-30.png', 24),
|
||
('Ripple', 'icons8-merge-vertical-64.png', 24),
|
||
('Log', 'icons8-property-30.png', 24),
|
||
('Glue', 'icons8-клей-30.png', 24),
|
||
('Target', 'icons8-цель-30.png', 24),
|
||
('SelectClips', 'icons8-select-all-90.png', 24),
|
||
('SelectRange', 'icons8-width-90.png', 24),
|
||
]
|
||
|
||
# Значок самой программы: отдельно, потому что окну нужен формат ico —
|
||
# только его умеет читать TIcon в LCL.
|
||
APP_ICON = ('icons8-показ-видеокадров-30.png', 32)
|
||
|
||
|
||
def make_ico(path: Path, side: int) -> bytes:
|
||
out = subprocess.run(
|
||
['convert', str(path), '-background', 'none', '-alpha', 'on',
|
||
'-resize', '%dx%d' % (side, side), 'ico:-'],
|
||
check=True, capture_output=True)
|
||
return out.stdout
|
||
|
||
|
||
def scale(path: Path, side: int) -> bytes:
|
||
out = subprocess.run(
|
||
['convert', str(path), '-background', 'none', '-alpha', 'on',
|
||
'-resize', '%dx%d' % (side, side), 'png:-'],
|
||
check=True, capture_output=True)
|
||
return out.stdout
|
||
|
||
|
||
def pascal_bytes(data: bytes, indent: str = ' ') -> str:
|
||
parts = []
|
||
for i in range(0, len(data), 16):
|
||
chunk = ', '.join('$%02X' % b for b in data[i:i + 16])
|
||
parts.append(indent + chunk)
|
||
return ',\n'.join(parts)
|
||
|
||
|
||
def main() -> int:
|
||
if not SRC.is_dir():
|
||
print('нет каталога с исходниками:', SRC, file=sys.stderr)
|
||
return 1
|
||
|
||
blocks = []
|
||
names = []
|
||
for name, filename, side in ICONS:
|
||
path = SRC / filename
|
||
if not path.is_file():
|
||
print('нет файла:', path, file=sys.stderr)
|
||
return 1
|
||
data = scale(path, side)
|
||
names.append((name, len(data)))
|
||
blocks.append(
|
||
' { %s, %d на %d точек }\n'
|
||
' Icon%sData: array[0..%d] of Byte = (\n%s\n );'
|
||
% (filename, side, side, name, len(data) - 1, pascal_bytes(data)))
|
||
|
||
app_src, app_side = APP_ICON
|
||
app_path = SRC / app_src
|
||
if not app_path.is_file():
|
||
print('нет файла:', app_path, file=sys.stderr)
|
||
return 1
|
||
app_data = make_ico(app_path, app_side)
|
||
names.append(('App (ico)', len(app_data)))
|
||
blocks.append(
|
||
' { %s, значок окна, %d на %d точек, формат ico }\n'
|
||
' IconAppData: array[0..%d] of Byte = (\n%s\n );'
|
||
% (app_src, app_side, app_side, len(app_data) - 1,
|
||
pascal_bytes(app_data)))
|
||
|
||
text = '''{
|
||
uIconData — значки, вшитые в программу.
|
||
|
||
Собран из файлов в icons_online командой:
|
||
|
||
python3 tools/make_icons.py
|
||
|
||
Правится не он, а исходные картинки: этот файл переписывается целиком.
|
||
|
||
Значки взяты у Icons8 и требуют указания авторства — оно есть в окне
|
||
«О программе», вкладка «Библиотеки и авторство». Ссылки на каждый значок
|
||
лежат в icons_online/attribution.txt.
|
||
|
||
Картинки чёрные на прозрачном фоне. Цвет им задаётся при отрисовке:
|
||
берётся прозрачность точки, а цвет — тот, каким сейчас рисуется кнопка.
|
||
Поэтому один и тот же значок годится и для тёмной кнопки, и для
|
||
оранжевой.
|
||
}
|
||
unit uIconData;
|
||
|
||
{$mode objfpc}{$H+}
|
||
|
||
interface
|
||
|
||
const
|
||
%s
|
||
|
||
implementation
|
||
|
||
end.
|
||
''' % ('\n\n'.join(blocks))
|
||
|
||
OUT.write_text(text, encoding='utf-8')
|
||
print('записан', OUT)
|
||
for name, size in names:
|
||
print(' %-8s %d байт' % (name, size))
|
||
return 0
|
||
|
||
|
||
if __name__ == '__main__':
|
||
sys.exit(main())
|