folder removed

master
Cosmin P 2022-03-04 11:47:12 +00:00
parent 1bb4d722c6
commit 10afe009fb
24 changed files with 0 additions and 1632 deletions

View File

@ -1,59 +0,0 @@
info = {
'icon' : 'LIGHT_SPOT',
'description' : 'Save as lighting file from currently opened anim file',
}
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
import datetime
C = bpy.context
D = bpy.data
scene = C.scene
def create_lighting_file():
'''Create lighting_v001 file from anim'''
# if D.is_dirty:
# print('Current file is not saved')
# return
if 'lighting' in D.filepath:
print('File already detected as lighting')
return
if not 'animation' in D.filepath:
print('Not in animation folder')
return
name = re.sub(r'anim_v\d{3}', 'lighting_v001', basename(D.filepath))
print('name: ', name)
fp = dirname(dirname(D.filepath))
print('shot path: ', fp)
fp = join(fp, 'lighting', name)
print('light filepath: ', fp)
if exists(fp):
print('lighting_v001 already exists in folder')
return
info = D.texts.get('info')
if not info:
info = D.texts.new('info')
info.write(f'\nCreated from {basename(D.filepath)} at {str( datetime.datetime.now() )}')
print('Saving current file as lighting')
bpy.ops.wm.save_as_mainfile(filepath=fp)
print('Done')
create_lighting_file()

View File

@ -1,43 +0,0 @@
info = {
'icon' : 'CHECKMARK',
'description' : 'Check objects modifiers',
}
import bpy
import os, re, shutil
from os.path import dirname, basename, join, abspath, splitext, exists, isfile, isdir
from os import listdir
import datetime
C = bpy.context
D = bpy.data
scn = scene = C.scene
## in scene syubloop ob.instance_collection.all_objects:
print(f'\n== Modifiers check {basename(D.filepath)} ==')
for ob in bpy.data.objects:
if ob.type != 'ARMATURE' and ob.hide_viewport != ob.hide_render:
print(f'/!\ {ob.name} view != render : hide_viewport {ob.hide_viewport}, hide_render {ob.hide_render}')
if ob.type in ('MESH', 'CURVE', 'TEXT') and len(ob.modifiers) > 0:
for mod in ob.modifiers:
#mod.show_viewport = True
#mod.show_render = True
if mod.type == 'SUBSURF':
# print (ob.name)
if mod.render_levels < mod.levels:
print(f'[M] {ob.name} subsurf render levels inferior to viewport : view {mod.levels} > render {mod.render_levels}')
elif mod.render_levels == 0:
print(f'[M] {ob.name} subsurf useless : render levels set to 0 : view {mod.levels} > render {mod.render_levels}')
'''
if mod.type == 'ARMATURE':
if mod.object:
print (mod.object.name)#print armatrue target
#ob.modifiers.remove(mod) #remove modifier
if mod.type == 'SOLIDIFY':
mod.thickness
mod.offset
'''
print('== check done.')

View File

@ -1,68 +0,0 @@
info = {
'icon' : 'DECORATE_LIBRARY_OVERRIDE',
'description' : 'Check available library update',
'update' : False,
'fullreport': False,
}
import bpy
import os
from os import listdir, scandir
from os.path import abspath, relpath, join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
C = bpy.context
D = bpy.data
scene = C.scene
auto_update = info['update']#False
fullreport = info['fullreport']
## 1: all execpt num, 2: num, 3:ext
rseq = re.compile('^(.*?)(\d+)(\D*)$')
print('\n--library check--')
for ob in bpy.context.scene.objects:
if not ob.type == 'EMPTY': continue
if not ob.instance_collection: continue
if not ob.instance_collection.library: continue
lib = ob.instance_collection.library
if not lib: continue
fp = lib.filepath
if not fp: continue
rel_dir = dirname(fp)
abs_lib = abspath(bpy.path.abspath(fp))
if not exists(abs_lib):
print(f'Lib not found: obj: {ob.name} > instance: {ob.instance_collection.name}\n-> {abs_lib}')
continue
lib_dir = dirname(abs_lib)
lib_name = basename(abs_lib)
#same length ? #last modified ? #last by name without #must be 90% identical ? # parts without rightmost number must be identical (good enough)
regname = rseq.search(lib_name)
if not regname:
print(f'X - {lib_name} : could not identify version using regex: {rseq.pattern}')
continue
name_base = regname.group(1)
# filelist = [f for f in scandir(lib_dir) if f.is_file() and len(f.name) == len(lib_name)]
# more strict with filename
filelist = [f for f in scandir(lib_dir) if f.is_file() and len(f.name) == len(lib_name) and rseq.search(f.name) and rseq.search(f.name).group(1) == name_base]
filelist.sort(key=lambda x : x.name)#sort in place alphabetically
last = filelist[-1]
if last.name != lib.name:
print(f'/!\ Lib update found : obj: {ob.name} > instance: {ob.instance_collection.name}\n {lib_name} >> {last.name}\n')
if auto_update:
### use relocate or do it automagically...
nfp = join(dirname(fp), last.name)
lib.filepath = nfp
continue
if fullreport: print(f'Lib OK : obj: {ob.name} > instance: {ob.instance_collection.name} > file: {lib_name}')
## make breakdown popup for addon version

View File

@ -1,121 +0,0 @@
info = {
'icon' : 'TOOL_SETTINGS',
'description' : 'Set render path for PNG - RGB out',
'stamp' : False
}
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
from time import time
C = bpy.context
D = bpy.data
scn = scene = C.scene
rd = scn.render
ev = scn.eevee
def render_anim(GL=False):
#openGl render
if GL:
bpy.ops.render.opengl(animation=True, view_context=False)#view_context False > look throughcam
else:
bpy.ops.render.render(animation=True)
def set_stamp(active_note=False):
rd.use_stamp = True
## Enable
rd.use_stamp_filename = True
rd.use_stamp_frame = True
rd.use_stamp_render_time = True
rd.use_stamp_time = True
rd.use_stamp_date = True
## Disable
rd.use_stamp_sequencer_strip = False
rd.use_stamp_marker = False
rd.use_stamp_scene = False
rd.use_stamp_lens = False
rd.use_stamp_camera = False
rd.use_stamp_hostname = False
rd.use_stamp_memory = False
rd.use_stamp_frame_range = False
## Notes
rd.use_stamp_note = active_note
if rd.use_stamp_note:
info = D.texts.get('info')
txt = ''
if info:
for l in info.lines[:2]:
if 'Created from' in l.body:
txt = l.body
if txt:
rd.stamp_note_text = txt
else:#disable notes
rd.use_stamp_note = False
def setup_render_params(use_stamp=False):
'''set dimensions, percentage, fps...'''
if use_stamp:
set_stamp(active_note=True)
else:
rd.use_stamp = False
rd.resolution_x = 1920
rd.resolution_y = 1080
rd.resolution_percentage = 100
rd.use_border = False
rd.fps = 25
rd.use_sequencer = False
#sampling
ev.taa_render_samples = 128#push up sample for shadow mainly
#AO
ev.use_gtao = True
ev.gtao_distance = 0.7
ev.gtao_factor = 0.7
ev.gtao_quality = 0.2
ev.use_gtao_bent_normals = False#bent normal makes it lighter than shadows !
#not sure...
ev.use_gtao_bounce = True#no bounce is darker... (less AO on claer object)
#setup color management
scene.view_settings.look = 'Filmic - Medium High Contrast'
#no disable auto folder opening after auto video making
if hasattr(scene, 'MVopen'):
scene.MVopen = False
def set_render_path():
setup_render_params(use_stamp=info['stamp'])
rd.image_settings.file_format = 'PNG'
rd.image_settings.color_mode = 'RGB'#A
rd.image_settings.color_depth = '8'
rd.use_file_extension = True
rd.use_overwrite = True#erase file
rd.use_placeholder = False
rd.image_settings.compression = 50#default = 15, high = slower and lighter (same quality)
filename = splitext(basename(D.filepath))[0]
# fp = join(dirname(D.filepath), 'render')
rd.filepath = join(dirname(D.filepath), 'images', filename, filename + '.')# '.####' #let a dot to separate padding number
set_render_path()
'''
start = time()
render_anim(GL=False)
print(f'elapsed {time() - start}')
'''

View File

@ -1,155 +0,0 @@
info = {
'icon' : 'TOOL_SETTINGS',
'description' : 'Set filepath and video settings for direct video out',
'stamp' : False
}
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
from time import time
C = bpy.context
D = bpy.data
scn = scene = C.scene
rd = scn.render
ev = scn.eevee
def set_stamp(active_note=False):
rd.use_stamp = True
## Enable
rd.use_stamp_filename = True
rd.use_stamp_frame = True
rd.use_stamp_render_time = True
rd.use_stamp_time = True
rd.use_stamp_date = True
## Disable
rd.use_stamp_sequencer_strip = False
rd.use_stamp_marker = False
rd.use_stamp_scene = False
rd.use_stamp_lens = False
rd.use_stamp_camera = False
rd.use_stamp_hostname = False
rd.use_stamp_memory = False
rd.use_stamp_frame_range = False
## Notes
rd.use_stamp_note = active_note
if rd.use_stamp_note:
info = D.texts.get('info')
txt = ''
if info:
for l in info.lines[:2]:
if 'Created from' in l.body:
txt = l.body
if txt:
rd.stamp_note_text = txt
else:#disable notes
rd.use_stamp_note = False
def setup_render_params(use_stamp=False):
'''set dimensions, percentage, fps...'''
if use_stamp:
set_stamp(active_note=True)
else:
rd.use_stamp = False
rd.resolution_x = 1920
rd.resolution_y = 1080
rd.resolution_percentage = 100
rd.use_border = False
rd.fps = 25
rd.use_sequencer = False
#sampling
ev.taa_render_samples = 128#push up sample for shadow mainly
#AO
ev.use_gtao = True
ev.gtao_distance = 0.7
ev.gtao_factor = 0.7
ev.gtao_quality = 0.2
ev.use_gtao_bent_normals = False#bent normal makes it lighter than shadows !
#not sure...
ev.use_gtao_bounce = True#no bounce is darker... (less AO on claer object)
#setup color management
scene.view_settings.look = 'Filmic - Medium High Contrast'
#no disable auto folder opening after auto video making
if hasattr(scene, 'MVopen'):
scene.MVopen = False
def render_anim(GL=False):
#openGl render
if GL:
bpy.ops.render.opengl(animation=True, view_context=False)#view_context False > look throughcam
else:
bpy.ops.render.render(animation=True)
def check_name(name, fp):
filelist = [splitext(f)[0] for f in os.listdir(fp)]#raw names
if not name in filelist:
return name
ct = 2
new = name + '_' + str(ct).zfill(2)
while new in filelist:
new = name + '_' + str(ct).zfill(2)
ct+=1
if ct > 99:
return None
return new
def set_video_path():
setup_render_params(use_stamp=info['stamp'])
rd.image_settings.file_format = 'FFMPEG'
rd.image_settings.color_mode = 'RGB'
rd.ffmpeg.codec = 'H264'
rd.ffmpeg.constant_rate_factor = 'HIGH'#default 'MEDIUM'
rd.ffmpeg.format = 'MPEG4'#'MKV', 'QUICKTIME'
rd.ffmpeg.ffmpeg_preset = 'GOOD'#default = 'GOOD'(compromise), BEST(light - slow), REALTIME(fat-fast)'
ext = ''
if rd.ffmpeg.format == 'MPEG4':
ext = '.mp4'
elif rd.ffmpeg.format == 'QUICKTIME':
ext = '.mov'
elif rd.ffmpeg.format == 'MKV':
ext = '.mkv'
filename = splitext(basename(D.filepath))[0]
fp = join(dirname(D.filepath), 'images')
if not exists(fp):
print(f'not found : {fp} ')
return
filename = check_name(filename, fp)
if not filename:
print('name not available')
return
rd.filepath = join(dirname(D.filepath), 'images', filename + ext)
set_video_path()
'''
start = time()
render_anim(GL=False)
print(f'elapsed {time() - start}')
'''

View File

@ -1,39 +0,0 @@
info = {
'icon' : 'RENDER_ANIMATION',
'description' : 'render timed',
}
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
from time import time
import datetime
C = bpy.context
D = bpy.data
scn = scene = C.scene
rd = scn.render
def render_anim(GL=False):
#openGl render
if GL:
bpy.ops.render.opengl(animation=True, view_context=True)#view_context False > look throughcam
else:
bpy.ops.render.render(animation=True)
start = time()
render_anim()
secs = time() - start
timesec_str = f'elapsed {secs} seconds'
time_str = str(datetime.timedelta(seconds=secs))
print(timesec_str)
print(time_str)
C.window_manager.clipboard = time_str

View File

@ -1,39 +0,0 @@
info = {
'icon' : 'RENDER_ANIMATION',
'description' : 'render this viewport openGL',
}
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
from time import time
import datetime
C = bpy.context
D = bpy.data
scn = scene = C.scene
rd = scn.render
def render_anim(GL=False):
#openGl render
if GL:
bpy.ops.render.opengl(animation=True, view_context=True)#view_context False > look throughcam
else:
bpy.ops.render.render(animation=True)
start = time()
render_anim(GL=True)
secs = time() - start
timesec_str = f'elapsed {secs} seconds'
time_str = str(datetime.timedelta(seconds=secs))
print(timesec_str)
print(time_str)
C.window_manager.clipboard = time_str

View File

@ -1,62 +0,0 @@
info = {
'icon' : 'RENDER_STILL',
'description' : 'render still image timed',
}
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
from time import time
import datetime
C = bpy.context
D = bpy.data
scn = scene = C.scene
rd = scn.render
def pad_with_current_frame(match):
return str(C.scene.frame_current).zfill(len(match.group(0)))
def add_frame_padding(name):
'''
return string padded with current blender frame
if # found, use this padding to write theframe
'''
import re
if not '#' in name: return name + str(C.scene.frame_current).zfill(4)
# return re.sub(r'\#{1,10}', pad_with_current_frame, name)# all '#...' in string
return re.sub(r'\#{1,10}(?!.*\#)', pad_with_current_frame, name)# only last '#...'
def render(anim=False, GL=False):
if GL:#openGl render
bpy.ops.render.opengl(animation=anim, write_still=True, view_context=True)#view_context False > look throughcam
else:
bpy.ops.render.render(animation=anim, write_still=True)
start = time()
orgfp = C.scene.render.filepath
C.scene.render.filepath = add_frame_padding(C.scene.render.filepath)
try:
render(anim=False)
except Exception as e:
print(e)
finally:
C.scene.render.filepath = orgfp
secs = time() - start
timesec_str = f'elapsed {secs} seconds'
time_str = str(datetime.timedelta(seconds=secs))
print(timesec_str)
print(time_str)
C.window_manager.clipboard = time_str

View File

@ -1,109 +0,0 @@
info = {
'icon' : 'PACKAGE',
'description' : 'pack all videos',
'dryrun' : False
}
import os, re, shutil
from os.path import dirname, basename, join, abspath, splitext, exists, isfile, isdir
from os import listdir
import datetime
dryrun = info['dryrun']
resid = re.compile(r'\d{2}-\d{3}-\d{2}$')
shots = '/z/___SERIE/WIND-UPS/episodes/00/shots/'
packzone = '/z/___SERIE/WIND-UPS/medias/pack'
old_folder = join(packzone, '_old')
new_list = []
warning = []
extension_filter = ('mp4', 'mov',)#, 'mkv'
exclusion_words = ('test', 'old',)#use this for loose word search
rexclude = re.compile(r'[ _-]old|test')#old if after separator (' _-') and word test anywhere (might be too loose)
for f in os.scandir(shots):
if not resid.match(f.name):continue
imgfp = f'/z/___SERIE/WIND-UPS/episodes/00/shots/{f.name}/lighting/images'
if not exists(imgfp):continue
#need to be video file type
all_videos = [v for v in os.scandir(imgfp) if v.name.lower().endswith(extension_filter) and not rexclude.search(v.name)]#any(x in v.name for x in exclusion_words)
if not all_videos:continue
print(f'\n{f.name}')
bytime = sorted(all_videos, key=lambda x: x.stat().st_mtime)
byname = sorted(all_videos, key=lambda x: x.name)
# print('bytime: ', bytime[-1].name)
# print('byname: ', byname[-1].name)
if bytime[-1] != byname[-1]:
warn = f'''/!\\ {f.name}
last by name and by modif time different in {imgfp}
by time : {bytime[-1].name} ({datetime.datetime.fromtimestamp(bytime[-1].stat().st_mtime)})
by name : {byname[-1].name} ({datetime.datetime.fromtimestamp(byname[-1].stat().st_mtime)})
'''
print(warn)
warning.append(warn)
good_file = bytime[-1]
topack = good_file.path
topackname = good_file.name
dest = join(packzone, topackname)
# run checks and copy if needed
if exists(dest):
dup = [basename(dest)]
else:
print(f"compare with {'_'.join(splitext(good_file.name)[0].split('_')[:3])}")
# ex : twu_00-008-01_lighting_v001.mp4 (split on third to)
dup = [i for i in listdir(packzone) if isfile(join(packzone, i)) and '_'.join(splitext(i)[0].split('_')[:3]) == '_'.join(splitext(good_file.name)[0].split('_')[:3])]
# check duplication against this file
if dup:
print(f'same shot already exists:{dup}')
newer = True
for i in dup:
dfp = join(packzone, i)
# print(f'{os.stat(dfp).st_mtime} VS file {good_file.stat().st_mtime}')
if os.stat(dfp).st_mtime >= good_file.stat().st_mtime:
# print(f'{i} is same or most recent')
newer = False
if not newer:
print(f'{good_file.name} is not newer, skip')
continue
#src is most recent, do the copy and erase/move older
for d in dup:
if not exists(old_folder):os.mkdir(old_folder)
old_src = join(packzone, d)
old_dest = join(old_folder, d)
if exists(old_dest):
print(f' - deleting {d} (already in _old)')
if not dryrun: os.remove(old_src)
else:
print(f' - moving {d} to _old')
if not dryrun: shutil.move(old_src, old_dest)
# if made it here, safely do the copy
print(f'- packing new file : {topack}')
if not dryrun: shutil.copy2(topack, dest)
new_list.append(f'{topackname} : {topack}')
print('DONE\n----')
if warning:
print('\nWarnings')
for w in warning: print(w)
if new_list:
print(f'\n{len(new_list)} New:')
for n in new_list: print(n)

View File

@ -1,119 +0,0 @@
info = {
'icon' : 'COPYDOWN',
'description' : 'Go in render node mode waiting for jobs in watchfolder',
'checkfiles' : False,
'stamp' : False,
'cmds' : ''
}
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re
from time import sleep
import time
import datetime
## Blender
import bpy
from mathutils import Vector, Matrix
C = bpy.context
D = bpy.data
scn = scene = C.scene
def submit_to_watchfolder(checkfiles=False):
'''submitter (with or without file_copy)'''
if D.is_dirty or not D.is_saved:
print('!!! Not submitted : File must be saved first')
return
totalframes = scn.frame_end - scn.frame_start
if not overwrite:
#check if output path exists and have file
out = scn.render.filepath
outfolder = dirname(out)
if exists(outfolder):
outname = basename(out)
refile = re.compile(outname.rstrip('#') + r'\d{4}')
outlist = [f for f in listdir(outfolder) if refile.match(f)]
if outlist:
print(f'!!! Abort submission : Overwrite is False and {len(outlist)} files already exists ({totalframes} wanted)')
return
print(f'{totalframes} frames to render')
watchfolder = '/z/___SERIE/WIND-UPS/episodes/00/watchfolder'
if not exists(watchfolder):
print(f'watchfolder not found at {watchfolder}')
watchfolder = '/mnt/admserveur/prod/___SERIE/WIND-UPS/episodes/00/watchfolder'
if not exists(watchfolder):
print(f'ABORT : watchfolder not found at {watchfolder}')
return 1
#save a copy to the file ?
the_file = D.filepath
finalname = basename(D.filepath)
'''
if use_copy:
#save a copy
head, tail = os.path.split(D.filepath)
name, ext = splitext(tail)
uid = datetime.datetime.now().strftime('_rdtemp%Y%m%d%H%M%S')
finalname = name + uid + ext
the_file = join(head, finalname)
bpy.ops.wm.save_as_mainfile(filepath=the_file, copy=True)
link = join(watchfolder, finalname)
print(f'Create symlink:\n src: {finalname}\n dest: {link}')#the_file, complete path to finalname
os.symlink(the_file, link)#impossible to create symlink... so fuck-it.
'''
noext = splitext(finalname)[0]
stby = join(watchfolder, 'stby--' + noext)# + '.txt'
todo = join(watchfolder, 'todo--' + noext)# + '.txt'
running = join(watchfolder, 'runn--' + noext)# + '.txt'
done = join(watchfolder, 'done--' + noext)# + '.txt'
bad = 0
statelist = []
if exists(stby):
statelist.append(basename(stby))
if exists(todo):
statelist.append(basename(todo))
if exists(running):
statelist.append(basename(running))
if exists(done):
statelist.append(basename(done))
for f in os.listdir(watchfolder):
if splitext(f)[0][len('stby--'):] == noext:
print('Something already exists')
if exists(todo):
bad = 1
print(f'{noext}: Job already submitted')
if len(statelist) > 1:
print('problem : job exists in multiple states')
for state in statelist:
print(state)
bad = 1
if bad:
print('skip')
return
with open(todo, 'w') as fd:
fd.write(the_file+'\n')
if info['stamp']:
fd.write('stamp\n')
if info['cmds']:
fd.write(info['cmds'])
print(f'Created job {todo}')
print(f'Submit {basename(D.filepath)}')
submit_to_watchfolder(checkfiles=info['checkfiles'])

View File

@ -1,215 +0,0 @@
info = {
'icon' : 'RENDER_RESULT',
'description' : 'Pass in render node watchmode (freeze and get job from watchfolder when a todo is available)',
}
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from math import radians, degrees
from time import sleep
import datetime
import time
import platform
# Blender
import bpy
from mathutils import Vector, Matrix
C = bpy.context
D = bpy.data
scene = C.scene
## General timer to disable ?
## How to push a key to stop the mega-loop ? (or barbaric ctrl-C in cmd)
def logit(message):
try:
print(message)
with open(log, 'a') as fd:
if not message.endswith('\n'):
message += '\n'
fd.write(message)#add trailing new line
except Exception as e:
print('Log failed', e)
def set_stamp(active_note=False):
rd = bpy.context.scene.render
rd.use_stamp = True
## Enable
rd.use_stamp_filename = True
rd.use_stamp_frame = True
rd.use_stamp_render_time = True
rd.use_stamp_time = True
rd.use_stamp_date = True
## Disable
rd.use_stamp_sequencer_strip = False
rd.use_stamp_marker = False
rd.use_stamp_scene = False
rd.use_stamp_lens = False
rd.use_stamp_camera = False
rd.use_stamp_hostname = False
rd.use_stamp_memory = False
rd.use_stamp_frame_range = False
## Notes
rd.use_stamp_note = active_note
if rd.use_stamp_note:
info = D.texts.get('info')
txt = ''
if info:
for l in info.lines[:2]:
if 'Created from' in l.body:
txt = l.body
if txt:
rd.stamp_note_text = txt
else:#disable notes
rd.use_stamp_note = False
def run(fp):
running = fp.replace('todo--', 'runn--')
stamp = False
warn = []
# Check if a running job already exists
if exists(running):
logit(f'Problem ! job already exists : {running}')
return 1
# Get blend path
with open(fp, 'r') as fd:
# blend = fd.read().strip()
lines = fd.readlines()
blend = lines[0].strip()
stamp = 'stamp' in lines
for l in lines[1:]:#skip filepath
if '=' in l:#skip simple keyword qand focus on assignation
try:
exec(l)
except Exception as e:
print(f'could not exec {l}:\n->{e}')
warn.append(f'could not exec {l}:\n->{e}')
if not blend:
logit(f'Problem reading {fp}')
return 1
# check path
logit(f'Target blend : {blend}')
if not exists(blend):
logit(f'ERROR ! job {basename(running)} give an invalid filepath')
#delete/rename running job
os.rename(running, running.replace('runn--', 'error-'))
return 1
# Pass on job mode
try:
os.rename(fp, running)
except Exception as e:
logit(f'Could not rename job to running mode : {fp} ')
return 1
# write the timestamp and launch the job
with open(running, 'a') as fd:
startmess = f'starting : {str(datetime.datetime.now())}\n'
logit(startmess)
fd.write(startmess)
# Blender time ! open, check output and render the job
start_time = time.time()# get start time
bpy.ops.wm.open_mainfile(filepath=blend)
scn = bpy.context.scene
#here change Ao/filepath/stuff if needed
if stamp:
set_stamp(active_note=True)
else:
bpy.context.scene.render.use_stamp = False
bpy.ops.render.render(animation=True)#anim render
print('Rendering done, launching make_video in 2 sec...')
## log end time and exit
elapsed_time = time.time() - start_time# seconds
full_time = str(datetime.timedelta(seconds=elapsed_time))# hh:mm:ss format
timecode = datetime.datetime.now().strftime('%m%d%H%M')#timecode format '02041139' month+day+hour+minutes
sleep(2)
#no disable auto folder opening after auto video making
if hasattr(scn, 'MVopen'):
scn.MVopen = False
bpy.ops.render.make_video()
with open(running, 'a') as fd:
endmess = f'ended : {str(datetime.datetime.now())}\nrender time: {full_time}\n'
logit(endmess)
fd.write(endmess)
if warn:
fd.write('\n'.join(warn)+'\n')
# rename and move into done folder
donename = basename(running).replace('runn--', 'done--') + f'__{timecode}'#.replace('.txt', f'__{timecode}.txt')
done = join(donefolder, donename)
try:
os.rename(running, done)
except Exception as e:
logit(f'Could not move/rename run job to done : {done} (from {running}) ')
return
print(f'Finished job {basename(running)}, Continue in 5 seconds')
sleep(5)
return 0
###================
def watchmode():
if not bpy.data.is_saved or bpy.data.is_dirty:
print('You need to start from a saved blender file (preferably empty)')
return
if not exists(watchfolder):
print(f'!!!! Abort, watchfolder ({watchfolder}) not found')
return
if not exists(logfolder):
os.mkdir(logfolder)
print('log folder created')
while True:#infinite loop
job_status = 1
todolist = [f for f in os.listdir(watchfolder) if f.startswith('todo--')]
if todolist:
first = todolist[0]
print(f'{len(todolist)} todo, starting: {first}')
fp = join(watchfolder, first)
job_status = run(fp)
print('job_status: ', job_status)
#reopen folder
bpy.ops.wm.open_mainfile(filepath=org_blend)
sleep(300)#5min wait before looping
org_blend = bpy.data.filepath
machine = platform.node().split('.')[0]
if machine:
machine = 'node_' + machine + '.txt'
if not machine:
print('Cannot find machine name')
machine = 'nodes.txt'
print(f'use machine name : {machine}')
watchfolder = '/z/___SERIE/WIND-UPS/episodes/00/watchfolder'
donefolder = join(watchfolder, 'done')
logfolder = join(watchfolder, 'logs')
log = join(logfolder, machine)
watchmode()
print('End of batch.\nEOF')

View File

@ -1,30 +0,0 @@
# coding: utf-8
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
C = bpy.context
D = bpy.data
scene = C.scene
print('====')
'''
for i in range(0, 8):
ao = i * 0.25
scene.eevee.gtao_distance = ao
scene.render.filepath = join(dirname(D.filepath), f'{splitext(basename(D.filepath))[0]}-{scene.frame_current}_AO{i}-{ao}')
bpy.ops.render.render(animation=False, write_still=True)
'''
for i in range(0, 8):
fac = 1 - i * 0.1
#scene.eevee.gtao_distance = ao
scene.eevee.gtao_factor = fac
scene.render.filepath = join(dirname(D.filepath), f'{splitext(basename(D.filepath))[0]}-{scene.frame_current}_AOfac{i}-{fac}')
bpy.ops.render.render(animation=False, write_still=True)
print('done')

View File

@ -1,37 +0,0 @@
# coding: utf-8
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
C = bpy.context
D = bpy.data
scene = C.scene
print('====')
def more_sss(val=0.04):
for mat in D.materials:
if not mat.use_nodes:continue
nodes = mat.node_tree
if not nodes: continue
nodes = nodes.nodes
for n in nodes:
if n.type == 'GROUP':
sss = n.inputs.get('Subsurface')
if not sss: continue
#print(f'{mat.name} : {sss.default_value}')
current = sss.default_value
new = current + val
print(f'{mat.name} : {current} >> {new}')
sss.default_value = new
value = 0.06
for i in range(0, 8):
scene.render.filepath = join(dirname(D.filepath), f'{splitext(basename(D.filepath))[0]}-{scene.frame_current}_sss_plus_0.{str(i*6).zfill(2)}')
bpy.ops.render.render(animation=False, write_still=True)
more_sss(value)

View File

@ -1,32 +0,0 @@
# coding: utf-8
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
C = bpy.context
D = bpy.data
scene = C.scene
print('====')
def print_sss():
for mat in D.materials:
if not mat.use_nodes:continue
nodes = mat.node_tree
if not nodes: continue
nodes = nodes.nodes
for n in nodes:
if n.type == 'GROUP':
sss = n.inputs.get('Subsurface')
if not sss: continue
print(f'{mat.name} : {sss.default_value}')
if n.type == 'BSDF_PRINCIPLED':
sss = n.inputs.get('Subsurface')
if not sss: continue
print(f'PRINCIPLED : {mat.name} : {sss.default_value}')
print_sss()

View File

@ -1,58 +0,0 @@
info = {
'icon' : 'LINENUMBERS_ON',
'description' : 'Note and render',
'render' : False,
}
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
C = bpy.context
D = bpy.data
scene = C.scene
print('====')
scene.render.use_stamp_note = True
dist = scene.eevee.gtao_distance
fac = scene.eevee.gtao_factor
print('dist: ', dist)
print('fac: ', fac)
dist = round(dist, 2)
fac = round(fac, 2)
scene.render.stamp_note_text = f'AO dist {dist} fac {fac}'
if scene.view_settings.look != 'Filmic - Medium Contrast':
scene.render.stamp_note_text += f' - {scene.view_settings.look}'
org = scene.render.filepath
print(f'filepath was : {org}')
## full filename
# scene.render.filepath = join(dirname(D.filepath), f'{splitext(basename(D.filepath))[0]}-{scene.frame_current}_AO-dist{dist}-fac{fac}')
## custom filename
ep = int(re.search(r"(\d{3})", splitext(basename(D.filepath))[0]).group(1))
print('ep: ', ep)
scene.render.filepath = join(dirname(D.filepath), f'twu_{ep}-{scene.frame_current}_AO-dist{dist}-fac{fac}')
i = 2#increment if needed
while exists(scene.render.filepath + '.png'):
scene.render.filepath = join(dirname(D.filepath), f'twu_{ep}-{scene.frame_current}_AO-dist{dist}-fac{fac}_{i}')
if info['render']:
bpy.ops.render.render(animation=False, write_still=True)
# restore old sauce ?
scene.render.filepath = org
print('done')

View File

@ -1,44 +0,0 @@
info = {
'icon' : 'FILE_TEXT',
'description' : 'explore API in console at datapath of the popup',
'data_path' : ''
}
import bpy, mathutils
exclude = (
### add lines here to exclude specific attribute
'bl_rna', 'identifier','name_property','rna_type','properties',#basic
## To avoid recursion/crash on direct object call (comment for API check on deeper props)
'data', 'edges', 'faces', 'edge_keys', 'polygons', 'loops', 'face_maps', 'original',
## Avoid some specific properties
#'matrix_local', 'matrix_parent_inverse', 'matrix_basis','location','rotation_euler', 'rotation_quaternion', 'rotation_axis_angle', 'scale', 'translation',
)
def list_attr(path, ct=0):
for attr in dir(eval(path)):
if not attr.startswith('__') and not attr in exclude:
try:
value = getattr(eval(path),attr)
except AttributeError:
value = None
if value != None:
if not callable(value):
if type(value) in ( type(0),type(0.0),type(True),type('str'),type(mathutils.Vector()),type(mathutils.Color()), type(mathutils.Matrix()) ):
print(ct*' ' + attr, value)
else:
print(ct*' ' + attr,value,type(value))
ct+=1
# print (ct*' ' + '>')
list_attr('%s.%s'%(path,attr), ct)#Comment this line to kill recursion
print('---')
# write datapath as string. ex : "bpy.data.objects['Cube'].modifiers['Softbody']"
dt = info['data_path']
if dt:
list_attr(dt)
print ('Done')
else:
print('no data path given')

View File

@ -1,56 +0,0 @@
info = {
'icon' : 'EVENT_X',
'description' : 'Delete all blend backup version (.blend1 and next backups) in passed directory',
'folderpath' : '',
'recursive' : True,
'test' : False,
}
# coding: utf-8
import bpy
import os
import re, fnmatch, glob
from pathlib import Path
import shutil
C = bpy.context
D = bpy.data
scene = C.scene
def kill_blend_backup_version(fp, recursive=True, test=False):
if not fp:
print('ERROR', 'no filepath given')
return
re_blendbackup = re.compile(r'\.blend\d+')
fpo = Path(fp)
if not fpo.exists():
print('ERROR', f'invalid path: {fp}')
return
ct = 0
print(f'Removing blend backup files in : {fpo}')
if recursive:
for root, dirs, files in os.walk(fp):
for name in files:
fo = Path(root) / name
if re_blendbackup.match(fo.suffix):
ct += 1
print(fo)
if not test:
fo.unlink()
else:
for f in os.listdir(fp):
fo = Path(fp) / f
if re_blendbackup.match(fo.suffix):
ct += 1
print(fo)
if not test:
fo.unlink()
if ct:
print('INFO', f'Deleted {ct} file(s)')
kill_blend_backup_version(info['folderpath'], recursive = info['recursive'], test = info['test'])

View File

@ -1,71 +0,0 @@
info = {
'icon' : 'LIBRARY_DATA_BROKEN',
'description' : 'Correct path (print in console, apply as option) when weirdly auto added unwanted parent directory (still break rotate order for armatures...)',
'apply' : False
}
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext, abspath
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
C = bpy.context
D = bpy.data
scene = C.scene
""" rel = D.libraries[0].filepath.replace('//','')
parent = rel.count('..')
print('parent: ', parent)
abspath(join(dirname(D.filepath), rel)) """
## relpath
def to_abs(rfp):
return abspath(bpy.path.abspath(rfp))
print('\n--- Cheking libraries filepath ---')
apply = False
apply = info['apply']#get it from info dic
folder = dirname(D.filepath)
for lib in D.libraries:
libfp = lib.filepath
if exists(to_abs(libfp)):
print('clean :', libfp)
else:
print('broken:', libfp)
pct = libfp.count('..')
for i in range(1, pct+1):
newrel = ('').join(libfp.split('../',i))
if exists(to_abs(newrel)):
print(f'found at -{i} parent folder')
print(f'-> {newrel}')
if apply:
lib.filepath = newrel
print()
break
if i == pct:
print(f'tested with {pct} folder up and nothing found')
print('Done.')
'''
## abspath technique
folder = dirname(D.filepath)
for lib in D.libraries:
curfp = abspath(bpy.path.abspath(lib.filepath))
if exists(curfp):
print('clean :', lib.filepath)
else:
print('broken:', lib.filepath)
pct = lib.filepath.count('..')
print('up folder: ', pct)
endlib = lib.filepath.lstrip(os.sep+'.')
for i in range(1, pct+1):
start = '/'.join(folder.split(os.sep)[:-i])
nfp = join(start, endlib)
if exists(nfp):
print(f'{i} parent folder VS {pct} in current')
'''

View File

@ -1,60 +0,0 @@
info = {
'icon' : 'ARMATURE_DATA',
'description' : 'run some check on proxys and armautre and print in console',
}
# coding: utf-8
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
C = bpy.context
D = bpy.data
scene = bpy.context.scene
print('\nCollection instance check -- ')
problems = []
for o in bpy.context.scene.objects:
if o.instance_collection:
for instob in o.instance_collection.objects:
badname = withproxy = withcolproxy = alert = ''
if instob.type == 'ARMATURE':
mess = f'{o.name} -> rig: {instob.name}'
arm = instob.data
# print("arm", arm.name)#Dbg
if instob.name != arm.name:
badname = 1
mess += f' != arm data: {arm.name}'
rigname = arm.name.replace('_rig','_proxy') if 'rig' in arm.name else arm.name + '_proxy'
proxy = bpy.context.scene.objects.get(rigname)
if proxy:
withproxy = 1
mess += ' ->> Proxy in scene'
if not proxy:
collec_proxy = instob.name.replace('_rig','_proxy') if 'rig' in instob.name else instob.name + '_proxy'
proxy = bpy.context.scene.objects.get(collec_proxy)
if proxy :
withcolproxy = 1
mess += ' ->> Proxy from colname in scene'
if proxy and proxy.animation_data and proxy.animation_data.action and len(proxy.animation_data.action.fcurves) > 0:
mess += ' (animated)'
if badname and withcolproxy:
alert = '!!!'
elif badname and withproxy:
alert = '!!'
elif badname:
alert = '!'
mess = f'{alert} {mess}'
if badname or withproxy or withcolproxy:
problems.append(mess)
print(mess)
print('Done')

View File

@ -1,140 +0,0 @@
info = {
'icon' : 'DRIVER',
'description' : 'create visibility on driver objects or armature selection from a bone of a rig',
'prop_rig' : 'name_of_the_rig'
'prop_name' : 'hide_something'
'prop_bone' : 'root'
}
import bpy
def add_driver(source, target, prop, dataPath, index = -1, negative = False, func = ''):
''' Add driver to source prop (at index), driven by target dataPath '''
source.driver_remove(prop, index)
if index != -1:
d = source.driver_add( prop, index ).driver
else:
d = source.driver_add( prop ).driver
v = d.variables.new()
v.targets[0].id = target
v.targets[0].data_path = dataPath
d.expression = func + "(" + v.name + ")" if func else v.name
d.expression = d.expression if not negative else "-1 * " + d.expression
def create_hide_custom_prop(src_object, prop_name, prop_bone = ''):
'''
add source propertie with boolean option
place the hide prop on src_object with name prop_name
'''
rig = bpy.data.objects.get(src_object)
if not rig:
print(f"No objects named {src_object}")
return 1
if rig.type != 'ARMATURE':
print(f"Not an armature : {src_object}")
return 1
#add target bone
if prop_bone:
holder = rig.pose.bones.get(prop_bone)
else:
holder = rig.pose.bones.get('root')
if not holder:
print(f'problem finding bone {prop_bone} (or root)')
return 1
# create
if not holder.get('_RNA_UI'):
holder['_RNA_UI'] = {}
if not prop_name in holder.keys() :
holder[prop_name] = 0
holder['_RNA_UI'][prop_name] = {"default": 0,"min":0,"max":1,"soft_min":0,"soft_max":1}
else:
print(f'{prop_name} : already exists on root key')
return
return 0
def drive_selection_visibility(rig, prop_name, prop_bone = ''):
# add driver on selection
prefixs = ('MCH','DEF','ORG', 'WGT')
rig = bpy.data.objects.get(src_object)
if not rig:
print(f"No objects named {src_object}")
return 1
if rig.type != 'ARMATURE':
print(f"Not an armature : {src_object}")
return 1
#add target bone
if not prop_bone:
prop_bone = 'root'
if not rig.pose.bones.get(prop_bone):
print(f'no bones {prop_bone} on rig {rig.name}')
return 1
meshes = [i for i in bpy.context.selected_objects if i.type in ('MESH','CURVE','TEXT') and not i.name.startswith(('WGT', 'WDGT'))]
armatures = [i for i in bpy.context.selected_objects if i.type == 'ARMATURE']
if bpy.context.mode == 'POSE':
obarm = bpy.context.active_object
for bone in bpy.context.selected_pose_bones_from_active_object:
prop = 'bones["%s"].hide'%bone.name
index = -1
layer = bone.bone.layers
protect_layer = rig.data.layers_protected
### dont check for protected, strictly use selection.
# if bone.name.startswith(prefixs) or any([i==j==1 for i,j in zip(layer,protect_layer)]) :
# print(f'Skipped : Prefixed or protected bone : {bone.name}')
# rig.data.driver_remove(prop, index)
# continue
print(f'New : Driver on bone {bone.name}')
add_driver(obarm.data, rig, prop, f'pose.bones["{prop_bone}"]["{prop_name}"]', index)
return
for ob in meshes :
print('Object : ', obarm.name)
add_driver(ob, rig, 'hide_viewport', f'pose.bones["{prop_bone}"]["{prop_name}"]', -1)
add_driver(ob, rig, 'hide_render', f'pose.bones["{prop_bone}"]["{prop_name}"]', -1)
for obarm in armatures:
print('Armature : ', obarm.name)
## mask armature object
## add_driver(obarm, rig, 'hide_viewport', f'pose.bones["{prop_bone}"]["{prop_name}"]', -1)
## bette mask pose bones since its a proxy...
for bone in obarm.pose.bones :
prop = 'bones["%s"].hide'%bone.name
index = -1
layer = bone.bone.layers
protect_layer = rig.data.layers_protected
if bone.name.startswith(prefixs) or any([i==j==1 for i,j in zip(layer,protect_layer)]) :
print(f'Skipped : Prefixed or protected bone : {bone.name}')
rig.data.driver_remove(prop, index)
else :
print(f'New : Driver on bone {bone.name}')
add_driver(obarm.data, rig, prop, f'pose.bones["{prop_bone}"]["{prop_name}"]', index)
### ----
## write the name of the rig source (will put the propertie on the root of this armature)
prop_rig = info['prop_rig']# name_of_the_rig
## write the name of the propertie to attach
prop_name = info["prop_name"]#'hide_headband'# hide_something
## prop_bone (bone holding the propertie), 'root' if left string empty.
prop_bone = info["prop_bone"]
create_hide_custom_prop(prop_rig, prop_name, prop_bone = prop_bone)
drive_selection_visibility(prop_rig, prop_name, prop_bone = prop_bone)

View File

@ -1,27 +0,0 @@
info = {
'icon' : 'ACTION_TWEAK',
'description' : 'Rename selected armature actions (with name of the rig, replacing "_rig" with "_act")',
}
# coding: utf-8
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
C = bpy.context
D = bpy.data
scene = C.scene
for o in C.selected_objects:
if o.type == 'ARMATURE':
print(o.animation_data.action.name)
if '_rig' in o.name:
action = o.animation_data.action
if action.name.replace('_act','') != o.name.replace('_rig', ''):
newname = o.name.replace('_rig', '_act')
print(f'action rename {action.name} > {newname}')
action.name = newname

View File

@ -1,21 +0,0 @@
info = {
'icon' : 'HIDE_OFF',
'description' : 'Force viewport visibility ON for objects with hide_viewport prop animated',
}
# coding: utf-8
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
C = bpy.context
D = bpy.data
scene = C.scene
import bpy
for o in bpy.context.scene.objects:
if o.animation_data and o.animation_data.action and o.animation_data.action.fcurves.find('hide_viewport'):
o.hide_viewport = False

View File

@ -1,22 +0,0 @@
info = {
'icon' : 'OUTLINER_OB_ARMATURE',
'description' : 'Hide/Unhide all rigs',
}
import bpy
C = bpy.context
D = bpy.data
scene = C.scene
#hide armature
hide = True
arms = [o for o in C.scene.objects if o.type == 'ARMATURE']
if arms:
hide = not arms[0].hide_viewport
#invert of the state of the first armature found for all of them
for o in C.scene.objects:
if o.type == 'ARMATURE':
o.hide_viewport = hide

View File

@ -1,5 +0,0 @@
import bpy
from bpy import data as D
ob = D.objects['boom_hairs_group_ref']
ob.hide_viewport = not ob.hide_viewport