fix batch

0.6.4

- ui: render selected scene has hints on popup panekl like gen batch
- changed: always re-export crop info when using render all scene and generate batch
- changed: batch file has minutes at the end of the name
- fix: windows dynamic batch problem
main
Pullusb 2021-10-29 16:42:35 +02:00
parent 1f551da12e
commit 2a0c173048
5 changed files with 89 additions and 57 deletions

View File

@ -14,6 +14,13 @@ Activate / deactivate layer opaticty according to prefix
Activate / deactivate all masks using MA layers Activate / deactivate all masks using MA layers
--> -->
0.6.4
- ui: render selected scene has hints on popup panekl like gen batch
- changed: always re-export crop info when using render all scene and generate batch
- changed: batch file has minutes at the end of the name
- fix: windows dynamic batch problem
0.6.3 0.6.3
- fix: show in ui when there is an active dopesheet layer that is not in active object - fix: show in ui when there is an active dopesheet layer that is not in active object

View File

@ -37,7 +37,9 @@ class GPEXP_OT_export_crop_coord_to_json(bpy.types.Operator):
# if not scn.render.use_border or not scn.render.use_crop_to_border: # if not scn.render.use_border or not scn.render.use_crop_to_border:
# self.report({'ERROR'}, 'Current scene have cropping disabled or use crop_to_border disabled!') # self.report({'ERROR'}, 'Current scene have cropping disabled or use crop_to_border disabled!')
# return {'CANCELLED'} # return {'CANCELLED'}
fn.export_crop_to_json() crop_dic = fn.export_crop_to_json()
if not crop_dic:
self.report({'ERROR'}, 'No crop to export (Border might be deactivated in all scenes)')
return {"FINISHED"} return {"FINISHED"}

View File

@ -47,6 +47,47 @@ class GPEXP_OT_render_all_scenes(bpy.types.Operator):
class GPEXP_scene_select_prop(PropertyGroup): class GPEXP_scene_select_prop(PropertyGroup):
name : StringProperty() name : StringProperty()
select: BoolProperty() select: BoolProperty()
def scene_render_popup_ui(self, context):
layout = self.layout
col = layout.column()
for si in context.scene.scenes_list:
row = col.row()
row.prop(si, 'select',text='')
row.label(text=si.name)
## Display warnings
scn = bpy.data.scenes.get(si.name)
# compare to existing Rlayers (overkill ?)
# vls = [scn.view_layers.get(n.layer) for n in rlayers_nodes if scn.view_layers.get(n.layer)]
vls = [vl for vl in scn.view_layers if vl.name != 'View Layer']
if vls:
exclude_count = len([vl for vl in vls if not vl.use])
if exclude_count:
row.label(text=f'{exclude_count}/{len(vls)} excluded viewlayers', icon='ERROR')
if not scn.use_nodes:
row.label(text='use_node deactivated', icon='ERROR')
continue
outfiles = [n for n in scn.node_tree.nodes if n.type == 'OUTPUT_FILE']
if not outfiles:
row.label(text='No output files nodes', icon='ERROR')
continue
outnum = len(outfiles)
muted = len([x for x in outfiles if x.mute])
if muted == outnum:
row.label(text='All output file are muted', icon='ERROR')
continue
elif muted:
row.label(text=f'{muted}/{outnum} output file muted', icon='ERROR')
continue
class GPEXP_OT_render_selected_scene(bpy.types.Operator): class GPEXP_OT_render_selected_scene(bpy.types.Operator):
bl_idname = "gp.render_selected_scenes" bl_idname = "gp.render_selected_scenes"
bl_label = "Render Selected Scenes" bl_label = "Render Selected Scenes"
@ -55,9 +96,12 @@ class GPEXP_OT_render_selected_scene(bpy.types.Operator):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
return True return bpy.data.is_saved
def invoke(self, context, event): def invoke(self, context, event):
# if not bpy.data.is_saved:
# self.report({'ERROR'}, 'File needs to be saved')
# return {'CANCELLED'}
context.scene.scenes_list.clear() context.scene.scenes_list.clear()
for s in bpy.data.scenes: for s in bpy.data.scenes:
scn_item = context.scene.scenes_list.add() scn_item = context.scene.scenes_list.add()
@ -67,16 +111,22 @@ class GPEXP_OT_render_selected_scene(bpy.types.Operator):
return context.window_manager.invoke_props_dialog(self, width=250) return context.window_manager.invoke_props_dialog(self, width=250)
def draw(self, context): def draw(self, context):
layout = self.layout ## Basic (without hints)
col = layout.column() # layout = self.layout
for si in context.scene.scenes_list: # col = layout.column()
row = col.row() # for si in context.scene.scenes_list:
row.label(text=si.name) # row = col.row()
row.prop(si, 'select',text='') # row.label(text=si.name)
# row.prop(si, 'select',text='')
scene_render_popup_ui(self, context)
def execute(self, context): def execute(self, context):
scn_to_render = [si.name for si in context.scene.scenes_list if si.select] d = fn.export_crop_to_json()
if not d:
print('No crop to export, border disabled in all scenes')
scn_to_render = [si.name for si in context.scene.scenes_list if si.select]
start = time() start = time()
ct = 0 ct = 0
for scn_name in scn_to_render: for scn_name in scn_to_render:
@ -111,7 +161,7 @@ class GPEXP_OT_bg_render_script_selected_scene(bpy.types.Operator):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
return True return bpy.data.is_saved
def invoke(self, context, event): def invoke(self, context, event):
context.scene.scenes_list.clear() context.scene.scenes_list.clear()
@ -123,52 +173,20 @@ class GPEXP_OT_bg_render_script_selected_scene(bpy.types.Operator):
return context.window_manager.invoke_props_dialog(self, width=500) return context.window_manager.invoke_props_dialog(self, width=500)
def draw(self, context): def draw(self, context):
layout = self.layout scene_render_popup_ui(self, context)
col = layout.column()
for si in context.scene.scenes_list:
row = col.row()
row.prop(si, 'select',text='')
row.label(text=si.name)
## Display warnings
scn = bpy.data.scenes.get(si.name)
# compare to existing Rlayers (overkill ?)
# vls = [scn.view_layers.get(n.layer) for n in rlayers_nodes if scn.view_layers.get(n.layer)]
vls = [vl for vl in scn.view_layers if vl.name != 'View Layer']
if vls:
exclude_count = len([vl for vl in vls if not vl.use])
if exclude_count:
row.label(text=f'{exclude_count}/{len(vls)} excluded viewlayers', icon='ERROR')
if not scn.use_nodes:
row.label(text='use_node deactivated', icon='ERROR')
continue
outfiles = [n for n in scn.node_tree.nodes if n.type == 'OUTPUT_FILE']
if not outfiles:
row.label(text='No output files nodes', icon='ERROR')
continue
outnum = len(outfiles)
muted = len([x for x in outfiles if x.mute])
if muted == outnum:
row.label(text='All output file are muted', icon='ERROR')
continue
elif muted:
row.label(text=f'{muted}/{outnum} output file muted', icon='ERROR')
continue
def execute(self, context): def execute(self, context):
d = fn.export_crop_to_json()
if not d:
print('No crop to export, border disabled in all scenes')
platform = sys.platform platform = sys.platform
blend = Path(bpy.data.filepath) blend = Path(bpy.data.filepath)
scn_to_render = [si.name for si in context.scene.scenes_list if si.select] scn_to_render = [si.name for si in context.scene.scenes_list if si.select]
batch_file = blend.parent / f'{blend.stem}--{len(scn_to_render)}batch_{strftime("%m-%d-%H")}.sh' batch_file = blend.parent / f'{blend.stem}--{len(scn_to_render)}batch_{strftime("%m-%d_%H-%M")}.sh'
if platform.startswith('win'): if platform.startswith('win'):
script_text = ['@ECHO OFF'] script_text = ['@ECHO OFF']
@ -177,27 +195,31 @@ class GPEXP_OT_bg_render_script_selected_scene(bpy.types.Operator):
script_text = ['#!/bin/bash'] script_text = ['#!/bin/bash']
print('batch_file: ', batch_file) print('batch_file: ', batch_file)
bin_path = bpy.app.binary_path
for scn_name in scn_to_render: for scn_name in scn_to_render:
if platform.startswith('win'): if platform.startswith('win'):
import re import re
pattern = r'users[\/\\](.*?)[\/\\]softs' # or point to user dit with %UserProfile% pattern = r'users[\/\\](.*?)[\/\\]softs' # or point to user dit with %UserProfile%
re_user = re.search(pattern, bpy.app.binary_path) re_user = re.search(pattern, bin_path, re.I)
if not re_user: if not re_user:
cmd = f'"{bpy.app.binary_path}" -b "{bpy.data.filepath}" -S "{scn_name}" -a' cmd = f'"{bin_path}" -b "{bpy.data.filepath}" -S "{scn_name}" -a'
else: else:
bin_path = bpy.app.binary_path.replace(re_user.group(1), '%USERNAME%') bin_path = bin_path.replace(re_user.group(1), '%USERNAME%')
cmd = f'"{bin_path}" -b "{bpy.data.filepath}" -S "{scn_name}" -a' cmd = f'"{bin_path}" -b "{bpy.data.filepath}" -S "{scn_name}" -a'
else: # Unix : point same for each user else: # Unix : point same for each user
cmd = f'"{bpy.app.binary_path}" -b "{bpy.data.filepath}" -S "{scn_name}" -a' cmd = f'"{bin_path}" -b "{bpy.data.filepath}" -S "{scn_name}" -a'
script_text.append(cmd) script_text.append(cmd)
script_text.append('echo --- END BATCH ---') script_text.append('echo --- END BATCH ---')
script_text.append('pause') script_text.append('pause')
with batch_file.open('w') as fd: with batch_file.open('w') as fd:
fd.write('\n'.join(script_text)) fd.write('\n'.join(script_text))
print(f'Using following binary path: {bin_path}')
self.report({'INFO'}, f'Batch script generated: {batch_file}') self.report({'INFO'}, f'Batch script generated: {batch_file}')
return {"FINISHED"} return {"FINISHED"}

View File

@ -2,7 +2,7 @@ bl_info = {
"name": "GP Render", "name": "GP Render",
"description": "Organise export of gp layers through compositor output", "description": "Organise export of gp layers through compositor output",
"author": "Samuel Bernou", "author": "Samuel Bernou",
"version": (0, 6, 3), "version": (0, 6, 4),
"blender": (2, 93, 0), "blender": (2, 93, 0),
"location": "View3D", "location": "View3D",
"warning": "", "warning": "",

9
fn.py
View File

@ -828,11 +828,12 @@ def export_crop_to_json():
for ob in [o for o in scn.objects if o.type == 'GPENCIL']: for ob in [o for o in scn.objects if o.type == 'GPENCIL']:
coord_dic[ob.name] = scn_border coord_dic[ob.name] = scn_border
# save bbox if coord_dic:
with json_path.open('w') as fd: # save bbox
json.dump(coord_dic, fd, indent='\t') with json_path.open('w') as fd:
json.dump(coord_dic, fd, indent='\t')
print(f'coord saved at: {json_path}') print(f'coord saved at: {json_path}')
return coord_dic return coord_dic
def set_border_region_from_coord(coords, scn=None, margin=30, export_json=True): def set_border_region_from_coord(coords, scn=None, margin=30, export_json=True):