-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAnimateSnare.py
130 lines (103 loc) · 3.24 KB
/
AnimateSnare.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# -*- coding: utf-8 -*-
import os
import glob
import FreeCAD
from PIL import Image
from pathlib import Path
from PySide import QtCore
timer = QtCore.QTimer()
def msg(message):
App.Console.PrintMessage(str(message) + '\n')
def log(message):
App.Console.PrintLog(str(message) + '\n')
def get_spreadsheet(spreadsheet_label):
return App.ActiveDocument.getObjectsByLabel(spreadsheet_label)[0]
def get_spreadsheet_value(spreadsheet_label, cell_key):
return get_spreadsheet(spreadsheet_label).get(cell_key)
def update_spreadsheet_value(spreadsheet_label, cell_key, cell_value):
sheet = get_spreadsheet(spreadsheet_label)
sheet.set(cell_key, str(cell_value))
sheet.recompute()
App.ActiveDocument.recompute()
if not gif_mode:
Gui.updateGui()
def rotate_snare_knob(angle):
log('rotating snare knob to: ' + str(angle))
update_spreadsheet_value('snare common', 'KnobCamAngle', angle)
def resolve_image_path(suffix = ''):
project_path = Path(App.ActiveDocument.FileName)
return project_path.parent.joinpath(
'export', 'frames', (str(project_path.stem) + suffix + '.png')
)
def capture_image(path):
view = Gui.activeDocument().activeView()
view.saveImage(
str(path), 1562, 958, 'Current'
)
def create_animation_frames(frames_dir):
log('using frame images directory: ' + str(frames_dir))
frames = []
# collect all pngs from the frame images directory
imgs = glob.glob(str(frames_dir / '*.png'))
# append two lists - for backward and forward motion, to make a loopable gif
imgs = sorted(imgs) + sorted(imgs, reverse=True)
log('using frame images:')
log(imgs)
for i in imgs:
new_frame = Image.open(i)
frames.append(new_frame)
return frames
def to_animated_gif(frames_dir):
msg('creating an aminated gif...')
frames = create_animation_frames(frames_dir)
output_file = str(frames_dir.parent / 'cajon-snare-mechanism.gif')
log('saving animated gif to: ' + str(output_file))
frames[0].save(
output_file,
format='GIF',
append_images=frames[1:],
save_all=True,
duration=40, # 40ms = 25fps
loop=0, # loop forever
)
msg('animated gif saved to: ' + str(output_file))
def sig_int():
if FreeCAD.ActiveDocument.Comment == 'p':
msg('snare animation paused')
return 1
if FreeCAD.ActiveDocument.Comment == 's':
timer.stop()
msg('snare animation stopped')
return 2
return 0
def tick():
global angle, gif_mode
if sig_int():
return
snare_knob_angle = 360 - abs(angle - rotation_range)
rotate_snare_knob(snare_knob_angle)
if (gif_mode):
snare_frame_image_path = resolve_image_path('-snare-frame-' + str(snare_knob_angle))
capture_image(snare_frame_image_path)
if (snare_knob_angle == 360):
to_animated_gif(snare_frame_image_path.parent)
timer.stop()
angle = (angle + 10) % (rotation_range * 2)
def init_timer():
timer.timeout.connect(tick)
timer.start(40)
msg('snare animation started')
def prepare_env():
global angle, rotation_range, gif_mode
gif_mode = False
rotation_range = 240
angle = get_spreadsheet_value('snare common', 'KnobCamAngle')
if FreeCAD.ActiveDocument.Comment == 'gif':
msg('gif mode')
gif_mode = True
angle = 0
FreeCAD.ActiveDocument.Comment = ''
def main():
prepare_env()
init_timer()
main()