parent
8a21101b35
commit
96b13df4d0
25 changed files with 568 additions and 3 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
|
@ -0,0 +1,262 @@ |
||||
import math as _m, random as _r |
||||
|
||||
_FLOAT=0; _GATHER=1; _LINES=2; _LFADE=3; _EXPAND=4; _ELLIPSE=5 |
||||
_CHAR_W_LATIN=10.0; _CHAR_W_CJK=18.0; _SLOTS_PER_LBL=20 |
||||
|
||||
def _cjk(ch): return '\u4e00'<=ch<='\u9fff' |
||||
|
||||
def _tier(): |
||||
x=_r.random() |
||||
return 0 if x<0.3 else (1 if x<0.7 else 2) |
||||
|
||||
def _spd(t,s1,s2,s3): |
||||
if t==0: return _r.uniform(s1*.8,s1*1.2) |
||||
if t==1: return _r.uniform(s2*.8,s2*1.2) |
||||
return _r.uniform(s3*.8,s3*1.2) |
||||
|
||||
def _dir(): return -1 if _r.random()>0.1 else 1 |
||||
|
||||
def _cpos(i,W,H): |
||||
a=i/18*2*_m.pi-_m.pi/2 |
||||
r=min(W,H)*.28 |
||||
return W/2+r*_m.cos(a), H/2+r*_m.sin(a) |
||||
|
||||
def _epos(i,W,H): |
||||
a=i/18*2*_m.pi-_m.pi/2 |
||||
return W/2+W*.47*_m.cos(a), H/2+H*.43*_m.sin(a) |
||||
|
||||
def _ease(t): |
||||
t=max(0.,min(1.,t)) |
||||
return 2*t*t if t<.5 else -1+(4-2*t)*t |
||||
|
||||
def _init_bg(W,H,s1,s2,s3): |
||||
out=[] |
||||
for i in range(80): |
||||
t=_tier() |
||||
out.append({'x':_r.uniform(0,W),'y':i/80*H,'speed':_spd(t,s1,s2,s3)*_dir()}) |
||||
return out |
||||
|
||||
def _init_cd(W,H,s1,s2,s3,cw): |
||||
out=[] |
||||
for i,w in enumerate(cw): |
||||
t=_tier() |
||||
out.append({'x':_r.uniform(0,W),'y':_r.uniform(0,H),'speed':_spd(t,s1,s2,s3)*_dir(),'idx':i,'word':w}) |
||||
return out |
||||
|
||||
def _build_rows(nr,rs,wpr,W,H,aw,s1,s2,s3): |
||||
fs=max(12,min(80,int(W*.85/max(1,wpr*12)/(10/18)*18))) |
||||
cw=fs*.6; out=[] |
||||
for i in range(nr): |
||||
t=_tier(); sp=_spd(t,s1,s2,s3)*_dir() |
||||
sel=_r.choices(aw,k=wpr) if aw else [] |
||||
gaps=[_r.uniform(60,140) for _ in range(max(0,wpr-1))] |
||||
wws=[max(40,len(w.get('english',''))*cw) for w in sel] |
||||
tw=sum(wws)+sum(gaps) |
||||
sx=_r.uniform(-tw*.5,W-tw*.3) |
||||
wr=[]; x=sx |
||||
for j,w in enumerate(sel): |
||||
wr.append({'id':w['id'],'text':w['english'],'x':x,'width':wws[j]}) |
||||
x+=wws[j]+(gaps[j] if j<len(gaps) else 0) |
||||
out.append({'words':wr,'y':120+i*rs,'speed':sp,'total_w':tw}) |
||||
return out |
||||
|
||||
def frameEnd(frame): |
||||
try: _run(frame) |
||||
except Exception as e: print('FE err:',e) |
||||
|
||||
def _run(frame): |
||||
root=op('/project1/deep_sound') |
||||
W=root.par.Resw.val; H=root.par.Resh.val; dt=1 |
||||
s1=root.par.Speedslow.val; s2=root.par.Speedmid.val; s3=root.par.Speedfast.val |
||||
wpr=int(root.par.Wordsperrow.val) |
||||
es=root.par.Expandspd.val; ds=root.par.Drawspd.val; ms=root.par.Marqueespd.val |
||||
gw=root.par.Gatherwait.val; lp=root.par.Linepause.val; fo=root.par.Fadeout.val |
||||
mcs=root.par.Marqueecharspacing.val; mcsz=root.par.Marqueesize.val |
||||
|
||||
# Read state from stored dict |
||||
_DEF={'appState':_FLOAT,'textAlpha':1.,'gatherTimer':-1.,'pauseTimer':-1., |
||||
'dissolving':0,'ellipseAlpha':1.,'currentSeg':0,'labelFadeProgress':0., |
||||
'expandT':0.,'ellipseDrawT':0.,'marqueeAngle':0.,'marqueeAlpha':0., |
||||
'lineAlpha':0.,'pid0':0,'pid1':0,'pid2':0,'pid3':0} |
||||
st=root.fetch('state_dict', None) |
||||
if st is None: st=dict(_DEF) |
||||
|
||||
ast=int(round(st['appState'])) |
||||
ta=float(st['textAlpha']); gt=float(st['gatherTimer']); pt=float(st['pauseTimer']) |
||||
dv=int(round(st['dissolving'])); ea=float(st['ellipseAlpha']); cs=int(round(st['currentSeg'])) |
||||
lfp=float(st['labelFadeProgress']); et=float(st['expandT']); edt=float(st['ellipseDrawT']) |
||||
mang=float(st['marqueeAngle']); malp=float(st['marqueeAlpha']) |
||||
pid0=int(round(st['pid0'])); pid1=int(round(st['pid1'])) |
||||
pid2=int(round(st['pid2'])); pid3=int(round(st['pid3'])) |
||||
pids=[pid0,pid1,pid2,pid3] |
||||
|
||||
bg=root.fetch('bg_dots',None); cd=root.fetch('circle_dots',None) |
||||
rows=root.fetch('rows',None); segs=root.fetch('line_segs',[]) |
||||
las=root.fetch('label_alphas',[0.,0.,0.,0.]) |
||||
|
||||
wdat=op('words_table'); aw=[]; cw=[] |
||||
for r in range(1,wdat.numRows): |
||||
w={'id':int(wdat[r,'id'].val),'english':str(wdat[r,'english'].val), |
||||
'chinese':str(wdat[r,'chinese'].val),'circle':int(wdat[r,'circle'].val)} |
||||
aw.append(w) |
||||
if w['circle']==1: cw.append(w) |
||||
|
||||
ts_div=[1,2,3][min(2,max(0,root.par.Textsize.menuIndex))] |
||||
fs=max(12,min(80,int(W*.85/max(1,wpr*12)/(10/18)*18)))//ts_div |
||||
nr=max(8,int((H-120)/max(1,fs*1.6))); rs2=(H-120)/max(1,nr-1) |
||||
|
||||
pw=root.fetch('prev_wpr',-1); ps=root.fetch('prev_s1',-999.); pts=root.fetch('prev_ts',-1) |
||||
if bg is None or rows is None or cd is None or pw!=wpr or abs(ps-s1)>.001 or pts!=ts_div: |
||||
bg=_init_bg(W,H,s1,s2,s3) |
||||
cd=_init_cd(W,H,s1,s2,s3,cw) |
||||
rows=_build_rows(nr,rs2,wpr,W,H,aw,s1,s2,s3) |
||||
root.store('prev_wpr',wpr); root.store('prev_s1',s1); root.store('prev_ts',ts_div); root.store('font_size',fs) |
||||
|
||||
fi_spd=root.par.Fadein.val; fo_spd=root.par.Fadeoutspd.val |
||||
ta=max(0.,ta-fo_spd) if ast!=_FLOAT else min(1.,ta+fi_spd) |
||||
|
||||
for row in rows: |
||||
for wd in row['words']: wd['x']+=row['speed']*dt |
||||
if row['words']: |
||||
lft=min(wd['x'] for wd in row['words']) |
||||
rgt=max(wd['x']+wd['width'] for wd in row['words']) |
||||
sh=W+row['total_w']+160 |
||||
if row['speed']<0 and rgt<-80: |
||||
for wd in row['words']: wd['x']+=sh |
||||
elif row['speed']>0 and lft>W+80: |
||||
for wd in row['words']: wd['x']-=sh |
||||
|
||||
for d in bg: |
||||
d['x']+=d['speed']*dt |
||||
if d['speed']<0 and d['x']<-80: d['x']+=W+160 |
||||
elif d['speed']>0 and d['x']>W+80: d['x']-=W+160 |
||||
|
||||
for i,d in enumerate(cd): |
||||
if ast==_FLOAT: |
||||
d['x']+=d['speed']*dt |
||||
if d['speed']<0 and d['x']<-80: d['x']+=W+160 |
||||
elif d['speed']>0 and d['x']>W+80: d['x']-=W+160 |
||||
elif ast in (_GATHER,_LINES,_LFADE): |
||||
tx,ty=_cpos(i,W,H) |
||||
d['x']+=(tx-d['x'])*.04*dt; d['y']+=(ty-d['y'])*.04*dt |
||||
elif ast==_EXPAND: |
||||
tx,ty=_cpos(i,W,H); ex,ey=_epos(i,W,H); t=_ease(et) |
||||
d['x']=tx+(ex-tx)*t; d['y']=ty+(ey-ty)*t |
||||
elif ast==_ELLIPSE: |
||||
ex,ey=_epos(i,W,H); d['x']=ex; d['y']=ey |
||||
|
||||
if ast==_GATHER: |
||||
gt-=dt/60. |
||||
if gt<=0: |
||||
p=sorted(_r.sample(range(18),4)); pid0,pid1,pid2,pid3=p; pids=p |
||||
segs=[{'from_idx':p[k],'to_idx':p[k+1],'progress':0.,'done':False} for k in range(3)] |
||||
las=[0.,0.,0.,0.]; cs=0; ast=_LINES |
||||
elif ast==_LINES: |
||||
if cs<len(segs): |
||||
segs[cs]['progress']=min(1.,segs[cs]['progress']+.012*dt) |
||||
if segs[cs]['progress']>=1. and not segs[cs]['done']: |
||||
segs[cs]['done']=True; cs+=1 |
||||
las[0]=min(1.,las[0]+.02*dt) |
||||
if len(segs)>0 and segs[0]['done']: las[1]=min(1.,las[1]+.02*dt) |
||||
if len(segs)>1 and segs[1]['done']: las[2]=min(1.,las[2]+.02*dt) |
||||
if len(segs)>2 and segs[2]['done']: las[3]=min(1.,las[3]+.02*dt) |
||||
if all(s['done'] for s in segs) and all(a>=1. for a in las) and pt<0: |
||||
pt=lp |
||||
if pt>=0: |
||||
pt-=dt/60. |
||||
if pt<=0: pt=-1; ast=_LFADE; lfp=0. |
||||
elif ast==_LFADE: |
||||
lfp=min(1.,lfp+.015*dt) |
||||
if lfp>=1.: ast=_EXPAND; et=0. |
||||
elif ast==_EXPAND: |
||||
et=min(1.,et+es*dt) |
||||
if et>=1.: ast=_ELLIPSE |
||||
elif ast==_ELLIPSE: |
||||
edt=min(1.,edt+ds*dt) |
||||
mang-=ms*dt |
||||
if edt>=1.: malp=min(1.,malp+.012*dt) |
||||
|
||||
if dv: |
||||
ea=max(0.,ea-dt/max(.001,fo*60.)) |
||||
if ea<=0.: |
||||
ast=_FLOAT; dv=0; ea=1.; edt=0.; mang=0.; malp=0.; ta=0. |
||||
et=0.; lfp=0.; gt=-1.; pt=-1.; pids=[0,0,0,0]; segs=[]; las=[0.,0.,0.,0.]; cs=0 |
||||
pid0=pid1=pid2=pid3=0 |
||||
bg=_init_bg(W,H,s1,s2,s3); cd=_init_cd(W,H,s1,s2,s3,cw) |
||||
|
||||
prox=[] |
||||
if ast==_FLOAT: |
||||
for i in range(len(bg)): |
||||
for j in range(i+1,len(bg)): |
||||
dx=bg[i]['x']-bg[j]['x']; dy=bg[i]['y']-bg[j]['y'] |
||||
dist=_m.sqrt(dx*dx+dy*dy) |
||||
if dist<90: prox.append((dist,i,j)) |
||||
prox.sort(); prox=prox[:int(root.par.Maxlinks.val)] |
||||
|
||||
# Line alpha for Level TOP (no Python alpha math in render) |
||||
line_alpha=1. if ast==_LINES else (1.-lfp if ast==_LFADE else 0.) |
||||
|
||||
# Update line-label Text TOPs |
||||
for i in range(4): |
||||
did=pids[i] if i<len(pids) else 0 |
||||
chi=''; eng='' |
||||
if 0<=did<len(cd): |
||||
w=cd[did].get('word',{}); chi=w.get('chinese',''); eng=w.get('english','') |
||||
ch_t=root.op(f'lbl_ch_{i}'); en_t=root.op(f'lbl_en_{i}') |
||||
if ch_t: ch_t.par.text=chi |
||||
if en_t: en_t.par.text=eng |
||||
|
||||
# Update chr_sop fontsizex if Marqueesize changed |
||||
pmcsz=root.fetch('prev_mcsz',-1.) |
||||
if abs(pmcsz-mcsz)>0.1: |
||||
for idx in range(80): |
||||
s=root.op(f'marq_geo/chr_sop_{idx:02d}') |
||||
if s: s.par.fontsizex=mcsz |
||||
root.store('prev_mcsz',mcsz) |
||||
|
||||
# Per-character marquee placement along ellipse |
||||
rx_m=W*0.47-34; ry_m=H*0.43-24 |
||||
for qi in range(4): |
||||
ang=mang+qi*_m.pi/2 |
||||
did_q=pids[qi] if qi<len(pids) else 0 |
||||
lbl='' |
||||
if 0<=did_q<len(cd): |
||||
w=cd[did_q].get('word',{}); chi=w.get('chinese',''); eng=w.get('english','') |
||||
lbl=f'{chi} {eng}'.strip() if chi else eng |
||||
t=ang; base_slot=qi*_SLOTS_PER_LBL |
||||
cw_lat=mcsz*0.56; cw_cjk=mcsz |
||||
for ci in range(_SLOTS_PER_LBL): |
||||
idx=base_slot+ci |
||||
sop=root.op(f'marq_geo/chr_sop_{idx:02d}') |
||||
tf=root.op(f'marq_geo/chr_tf_{idx:02d}') |
||||
if ci<len(lbl): |
||||
ch=lbl[ci] |
||||
cw=cw_cjk if _cjk(ch) else cw_lat |
||||
x=rx_m*_m.cos(t); y=ry_m*_m.sin(t) |
||||
rot=_m.degrees(_m.atan2(ry_m*_m.cos(t),-rx_m*_m.sin(t))) |
||||
if sop: sop.par.text=ch |
||||
if tf: tf.par.tx=round(x,3); tf.par.ty=round(y,3); tf.par.rz=round(rot,3) |
||||
ds_dt=_m.sqrt((rx_m*_m.sin(t))**2+(ry_m*_m.cos(t))**2) |
||||
t+=(cw+2)*mcs/max(1.,ds_dt) |
||||
else: |
||||
if sop: sop.par.text='' |
||||
if tf: tf.par.tx=0.; tf.par.ty=0.; tf.par.rz=0. |
||||
|
||||
# Update custom params for Level TOP opacity drivers |
||||
root.par.Textalpha=round(ta,4) |
||||
root.par.Marqalpha=round(malp*ea,4) |
||||
root.par.Linealpha=round(line_alpha,4) |
||||
|
||||
# Write all state back to dict (picked up by state_chop Script CHOP each frame) |
||||
root.store('state_dict',{'appState':ast,'textAlpha':ta,'gatherTimer':gt,'pauseTimer':pt, |
||||
'dissolving':dv,'ellipseAlpha':ea,'currentSeg':cs,'labelFadeProgress':lfp, |
||||
'expandT':et,'ellipseDrawT':edt,'marqueeAngle':mang,'marqueeAlpha':malp, |
||||
'lineAlpha':line_alpha,'marqAlpha':malp*ea, |
||||
'pid0':pid0,'pid1':pid1,'pid2':pid2,'pid3':pid3}) |
||||
root.store('bg_dots',bg); root.store('circle_dots',cd); root.store('rows',rows) |
||||
root.store('line_segs',segs); root.store('label_alphas',las) |
||||
root.store('prox_pairs',prox) |
||||
|
||||
def onStart(): pass |
||||
def onCreate(): pass |
||||
def onExit(): pass |
||||
@ -0,0 +1,47 @@ |
||||
import numpy as _np |
||||
import math as _m |
||||
|
||||
_FLOAT=0; _GATHER=1; _LINES=2; _LFADE=3; _EXPAND=4; _ELLIPSE=5 |
||||
|
||||
def onSetupParameters(scriptOp): pass |
||||
|
||||
def onCook(scriptOp): |
||||
try: |
||||
_do_render(scriptOp) |
||||
except Exception as e: |
||||
import traceback; traceback.print_exc() |
||||
|
||||
def _do_render(scriptOp): |
||||
from PIL import Image, ImageDraw |
||||
import sys |
||||
#PIL_PATH = r'C:\Users\user\AppData\Roaming\Python\Python311\site-packages' |
||||
PIL_PATH=r'C:\Users\tech\AppData\Local\Programs\Python\Python311\site-packages' |
||||
|
||||
if PIL_PATH not in sys.path: |
||||
sys.path.insert(0, PIL_PATH) |
||||
|
||||
root = op('/project1/deep_sound') |
||||
W = int(root.par.Resw.val); H = int(root.par.Resh.val) |
||||
|
||||
st = root.fetch('state_dict', None) or {} |
||||
ast = int(round(st.get('appState', _FLOAT))) |
||||
cd = root.fetch('circle_dots', []) |
||||
segs = root.fetch('line_segs', []) |
||||
|
||||
img = Image.new('RGBA', (W, H), (0, 0, 0, 0)) |
||||
|
||||
if ast in (_LINES, _LFADE) and segs and cd: |
||||
draw = ImageDraw.Draw(img) |
||||
for seg in segs: |
||||
fi = seg.get('from_idx', 0); ti = seg.get('to_idx', 0) |
||||
prog = float(seg.get('progress', 0.)) |
||||
if prog <= 0 or fi >= len(cd) or ti >= len(cd): continue |
||||
x0 = cd[fi]['x']; y0 = cd[fi]['y'] |
||||
x1 = cd[ti]['x']; y1 = cd[ti]['y'] |
||||
# Interpolate endpoint by progress |
||||
ex = x0 + (x1 - x0) * prog |
||||
ey = y0 + (y1 - y0) * prog |
||||
draw.line([(x0, y0), (ex, ey)], fill=(255, 255, 255, 255), width=2) |
||||
|
||||
arr = _np.ascontiguousarray(_np.flipud(_np.array(img, dtype=_np.float32) / 255.)) |
||||
scriptOp.copyNumpyArray(arr) |
||||
@ -0,0 +1,127 @@ |
||||
import numpy as _np |
||||
import math as _m |
||||
import sys as _sys |
||||
|
||||
#_PIL_PATH = r'C:\Users\user\AppData\Roaming\Python\Python311\site-packages' |
||||
_PIL_PATH=r'C:\Users\tech\AppData\Local\Programs\Python\Python311\site-packages' |
||||
_LATIN = 'C:/Windows/Fonts/SpaceMono-Regular.ttf' |
||||
_CJK = 'C:/Windows/Fonts/NotoSansCJKtc-Regular.otf' |
||||
_FC = {} |
||||
_FLOAT=0; _GATHER=1; _LINES=2; _LFADE=3; _EXPAND=4; _ELLIPSE=5 |
||||
|
||||
def _font(cjk, sz): |
||||
from PIL import ImageFont |
||||
sz=max(8,int(sz)); k=(cjk,sz) |
||||
if k not in _FC: |
||||
try: _FC[k]=ImageFont.truetype(_CJK if cjk else _LATIN,sz) |
||||
except: _FC[k]=ImageFont.load_default() |
||||
return _FC[k] |
||||
|
||||
def _cjk(ch): return '\u4e00'<=ch<='\u9fff' |
||||
|
||||
def _blit_top(img, arr, x, y, alpha, H): |
||||
from PIL import Image as _Img |
||||
th, tw = arr.shape[:2] |
||||
arr_f = _np.flipud(arr) |
||||
lum = arr_f[:,:,0] |
||||
cols = _np.where(lum.max(axis=0) > 0.05)[0] |
||||
if len(cols) == 0: return x |
||||
arr_f = arr_f[:, :int(cols[-1])+1, :] |
||||
lum_rows = arr_f[:,:,0] |
||||
row_mask = _np.where(lum_rows.max(axis=1) > 0.05)[0] |
||||
if len(row_mask) == 0: return x |
||||
arr_f = arr_f[int(row_mask[0]):int(row_mask[-1])+1, :] |
||||
th, tw = arr_f.shape[:2] |
||||
mask_arr = (arr_f[:,:,0] * alpha * 255).clip(0,255).astype(_np.uint8) |
||||
from PIL import Image as _Img2 |
||||
mask = _Img2.fromarray(mask_arr, 'L') |
||||
white = _Img2.new('RGBA', (tw, th), (255,255,255,255)) |
||||
px=max(0,x); py=max(0, y - th//2) |
||||
if px >= img.width or py >= img.height: return x + tw |
||||
cw=min(tw, img.width-px); ch2=min(th, img.height-py) |
||||
if cw>0 and ch2>0: |
||||
img.paste(white.crop((0,0,cw,ch2)), (px,py), mask.crop((0,0,cw,ch2))) |
||||
return x + tw |
||||
|
||||
def onSetupParameters(scriptOp): pass |
||||
|
||||
def onCook(scriptOp): |
||||
try: |
||||
if _PIL_PATH not in _sys.path: |
||||
_sys.path.insert(0,_PIL_PATH) |
||||
_do_render(scriptOp) |
||||
except Exception as e: |
||||
import traceback; traceback.print_exc() |
||||
|
||||
def _do_render(scriptOp): |
||||
from PIL import Image, ImageDraw |
||||
root=op('/project1/deep_sound') |
||||
W=int(root.par.Resw.val); H=int(root.par.Resh.val) |
||||
|
||||
st=root.fetch('state_dict',None) or {} |
||||
ast=int(round(st.get('appState',_FLOAT))) |
||||
ea=float(st.get('ellipseAlpha',1.)) |
||||
lfp=float(st.get('labelFadeProgress',0.)) |
||||
edt=float(st.get('ellipseDrawT',0.)) |
||||
pids=[int(round(st.get(f'pid{i}',0))) for i in range(4)] |
||||
|
||||
ds=max(1.,root.par.Dotsize.val) |
||||
bg=root.fetch('bg_dots',[]); cd=root.fetch('circle_dots',[]) |
||||
segs=root.fetch('line_segs',[]); las=root.fetch('label_alphas',[0,0,0,0]) |
||||
prox=root.fetch('prox_pairs',[]) |
||||
|
||||
img=Image.new('RGBA',(W,H),(0,0,0,255)) |
||||
draw=ImageDraw.Draw(img) |
||||
|
||||
# 1. BG lines + dots (floating only) |
||||
if ast==_FLOAT: |
||||
for dist,i,j in prox: |
||||
a=int((1-dist/90)*.6*255) |
||||
draw.line([(bg[i]['x'],bg[i]['y']),(bg[j]['x'],bg[j]['y'])], |
||||
fill=(255,255,255,a),width=1) |
||||
for d in bg: |
||||
x,y=d['x'],d['y'] |
||||
draw.ellipse([x-ds,y-ds,x+ds,y+ds],fill=(255,255,255,200)) |
||||
|
||||
# 2. Circle dots (not in ellipse states) |
||||
if ast not in (_EXPAND,_ELLIPSE): |
||||
for d in cd: |
||||
x,y=d['x'],d['y'] |
||||
draw.ellipse([x-ds,y-ds,x+ds,y+ds],fill=(255,255,255,255)) |
||||
|
||||
# Connecting lines handled by line_render Script TOP + line_level Level TOP |
||||
|
||||
# 3. Line labels (Chinese via lbl_ch_N, English via lbl_en_N) |
||||
if ast in (_LINES,_LFADE) and pids: |
||||
fade=1. if ast==_LINES else 1.-lfp |
||||
for i,did in enumerate(pids): |
||||
if i>=len(las): break |
||||
ca=las[i]*fade |
||||
if ca>0.01 and did<len(cd): |
||||
d=cd[did] |
||||
bx=int(d['x']+10); by=int(d['y']-6) |
||||
ch_top=root.op(f'lbl_ch_{i}'); en_top=root.op(f'lbl_en_{i}') |
||||
cx=bx |
||||
if ch_top: |
||||
ch_arr=ch_top.numpyArray(delayed=False) |
||||
if ch_arr is not None: cx=_blit_top(img,ch_arr,cx,by,ca,H) |
||||
if en_top: |
||||
en_arr=en_top.numpyArray(delayed=False) |
||||
if en_arr is not None: _blit_top(img,en_arr,cx+4,by,ca,H) |
||||
|
||||
# 4. Ellipse dots |
||||
if ast in (_EXPAND,_ELLIPSE): |
||||
ei=int(ea*255) |
||||
for d in cd: |
||||
x,y=d['x'],d['y'] |
||||
draw.ellipse([x-ds,y-ds,x+ds,y+ds],fill=(255,255,255,ei)) |
||||
|
||||
# 5. Ellipse outline |
||||
if ast==_ELLIPSE and edt>0: |
||||
ei=int(ea*.5*255); n=200; dn=int(n*edt) |
||||
pts=[(W/2+W*.47*_m.cos(s/n*2*_m.pi-_m.pi/2), |
||||
H/2+H*.43*_m.sin(s/n*2*_m.pi-_m.pi/2)) for s in range(dn+1)] |
||||
if len(pts)>1: draw.line(pts,fill=(255,255,255,ei),width=1) |
||||
|
||||
arr=_np.ascontiguousarray(_np.flipud(_np.array(img,dtype=_np.float32)/255.)) |
||||
scriptOp.copyNumpyArray(arr) |
||||
@ -0,0 +1,27 @@ |
||||
_FLOAT=0; _GATHER=1; _LINES=2; _LFADE=3; _EXPAND=4; _ELLIPSE=5 |
||||
|
||||
def _toggle(): |
||||
root=op('/project1/deep_sound') |
||||
st=root.fetch('state_dict', None) |
||||
if st is None: return |
||||
ast=int(round(st.get('appState',_FLOAT))) |
||||
if ast==_FLOAT: |
||||
st['appState']=_GATHER |
||||
st['gatherTimer']=root.par.Gatherwait.val |
||||
elif ast in (_EXPAND,_ELLIPSE): |
||||
st['dissolving']=1 |
||||
else: |
||||
st.update({'appState':_FLOAT,'dissolving':0,'ellipseAlpha':1.,'ellipseDrawT':0., |
||||
'marqueeAngle':0.,'marqueeAlpha':0.,'expandT':0.,'labelFadeProgress':0., |
||||
'gatherTimer':-1.,'pauseTimer':-1.,'pid0':0,'pid1':0,'pid2':0,'pid3':0, |
||||
'currentSeg':0,'textAlpha':1.,'lineAlpha':0.,'marqAlpha':0.}) |
||||
root.store('line_segs',[]) |
||||
root.store('label_alphas',[0.,0.,0.,0.]) |
||||
root.store('state_dict', st) |
||||
root.par.Textalpha=float(st.get('textAlpha',1.)) |
||||
|
||||
def onOffToOn(channel,sampleIndex,val,prev): _toggle() |
||||
def onOnToOff(channel,sampleIndex,val,prev): pass |
||||
def onValueChange(channel,sampleIndex,val,prev): pass |
||||
def onWhileOn(channel,sampleIndex,val,prev): pass |
||||
def onWhileOff(channel,sampleIndex,val,prev): pass |
||||
@ -0,0 +1,48 @@ |
||||
import numpy as _np |
||||
import sys as _sys |
||||
|
||||
#_PIL_PATH = r'C:\Users\user\AppData\Roaming\Python\Python311\site-packages' |
||||
_PIL_PATH=r'C:\Users\tech\AppData\Local\Programs\Python\Python311\site-packages' |
||||
|
||||
_LATIN = 'C:/Windows/Fonts/SpaceMono-Regular.ttf' |
||||
_CJK = 'C:/Windows/Fonts/NotoSansCJKtc-Regular.otf' |
||||
_FC = {} |
||||
|
||||
def _font(cjk, sz): |
||||
from PIL import ImageFont |
||||
sz=max(8,int(sz)); k=(cjk,sz) |
||||
if k not in _FC: |
||||
try: _FC[k]=ImageFont.truetype(_CJK if cjk else _LATIN,sz) |
||||
except: _FC[k]=ImageFont.load_default() |
||||
return _FC[k] |
||||
|
||||
def _cjk(ch): return '\u4e00'<=ch<='\u9fff' |
||||
|
||||
def _dtxt(draw, text, x, y, sz, col): |
||||
cx=float(x) |
||||
for ch in text: |
||||
f=_font(_cjk(ch),sz) |
||||
try: |
||||
bb=draw.textbbox((0,0),ch,font=f) |
||||
draw.text((cx,y-sz*.55),ch,font=f,fill=col) |
||||
cx+=bb[2]-bb[0] |
||||
except: cx+=sz*.6 |
||||
|
||||
def onSetupParameters(scriptOp): pass |
||||
|
||||
def onCook(scriptOp): |
||||
try: |
||||
if _PIL_PATH not in _sys.path: _sys.path.insert(0,_PIL_PATH) |
||||
from PIL import Image, ImageDraw |
||||
root=op('/project1/deep_sound') |
||||
W=int(root.par.Resw.val); H=int(root.par.Resh.val) |
||||
rows=root.fetch('rows',[]); fs=root.fetch('font_size',18) |
||||
img=Image.new('RGBA',(W,H),(0,0,0,0)) # transparent background |
||||
draw=ImageDraw.Draw(img) |
||||
for row in rows: |
||||
for wrd in row['words']: |
||||
_dtxt(draw,wrd['text'],wrd['x'],row['y'],fs,(255,255,255,255)) |
||||
arr=_np.ascontiguousarray(_np.flipud(_np.array(img,dtype=_np.float32)/255.)) |
||||
scriptOp.copyNumpyArray(arr) |
||||
except Exception as e: |
||||
import traceback; traceback.print_exc() |
||||
Binary file not shown.
Loading…
Reference in new issue