folder removed
parent
1bb4d722c6
commit
10afe009fb
|
@ -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()
|
|
@ -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.')
|
|
@ -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
|
||||
|
|
@ -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}')
|
||||
'''
|
|
@ -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}')
|
||||
'''
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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)
|
|
@ -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'])
|
|
@ -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')
|
|
@ -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')
|
|
@ -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)
|
||||
|
|
@ -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()
|
|
@ -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')
|
||||
|
|
@ -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')
|
|
@ -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'])
|
|
@ -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')
|
||||
'''
|
|
@ -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')
|
|
@ -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)
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
Loading…
Reference in New Issue