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 problemmain
parent
1f551da12e
commit
2a0c173048
|
@ -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
|
||||||
|
|
|
@ -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"}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -47,82 +47,9 @@ 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()
|
||||||
class GPEXP_OT_render_selected_scene(bpy.types.Operator):
|
|
||||||
bl_idname = "gp.render_selected_scenes"
|
|
||||||
bl_label = "Render Selected Scenes"
|
|
||||||
bl_description = "Launch render of selected scenes with a selection popup"
|
|
||||||
bl_options = {"REGISTER"}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
return True
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
|
||||||
context.scene.scenes_list.clear()
|
|
||||||
for s in bpy.data.scenes:
|
|
||||||
scn_item = context.scene.scenes_list.add()
|
|
||||||
scn_item.name = s.name
|
|
||||||
scn_item.select = s.name != 'Scene'
|
|
||||||
|
|
||||||
return context.window_manager.invoke_props_dialog(self, width=250)
|
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
layout = self.layout
|
|
||||||
col = layout.column()
|
|
||||||
for si in context.scene.scenes_list:
|
|
||||||
row = col.row()
|
|
||||||
row.label(text=si.name)
|
|
||||||
row.prop(si, 'select',text='')
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
scn_to_render = [si.name for si in context.scene.scenes_list if si.select]
|
|
||||||
|
|
||||||
start = time()
|
|
||||||
ct = 0
|
|
||||||
for scn_name in scn_to_render:
|
|
||||||
scn = bpy.data.scenes.get(scn_name)
|
|
||||||
if not scn.use_nodes:
|
|
||||||
print(f'{scn.name} has use node deactivated')
|
|
||||||
continue
|
|
||||||
|
|
||||||
outfiles = [n for n in scn.node_tree.nodes if n.type == 'OUTPUT_FILE']
|
|
||||||
if not outfiles:
|
|
||||||
print(f'\n -!-> Skip {scn.name}, No output files')
|
|
||||||
continue
|
|
||||||
|
|
||||||
if all(x.mute for x in outfiles):
|
|
||||||
print(f'\n -!-> Skip {scn.name}, All output file are muted')
|
|
||||||
continue
|
|
||||||
|
|
||||||
print(f'\n --> Rendering {scn.name}')
|
|
||||||
# bpy.context.window.scene = scn # no need
|
|
||||||
bpy.ops.render.render(animation=True, scene=scn.name)
|
|
||||||
ct += 1
|
|
||||||
|
|
||||||
print(f'\nDone. {ct} scenes rendered in {time()-start:.2f}s')
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class GPEXP_OT_bg_render_script_selected_scene(bpy.types.Operator):
|
def scene_render_popup_ui(self, context):
|
||||||
bl_idname = "gp.bg_render_script_selected_scenes"
|
|
||||||
bl_label = "Create Selected Scene Render Batch "
|
|
||||||
bl_description = "Create a batch script to render all selected scenes in a selection popup"
|
|
||||||
bl_options = {"REGISTER"}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
return True
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
|
||||||
context.scene.scenes_list.clear()
|
|
||||||
for s in bpy.data.scenes:
|
|
||||||
scn_item = context.scene.scenes_list.add()
|
|
||||||
scn_item.name = s.name
|
|
||||||
scn_item.select = s.name != 'Scene'
|
|
||||||
|
|
||||||
return context.window_manager.invoke_props_dialog(self, width=500)
|
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
col = layout.column()
|
col = layout.column()
|
||||||
for si in context.scene.scenes_list:
|
for si in context.scene.scenes_list:
|
||||||
|
@ -161,14 +88,105 @@ class GPEXP_OT_bg_render_script_selected_scene(bpy.types.Operator):
|
||||||
row.label(text=f'{muted}/{outnum} output file muted', icon='ERROR')
|
row.label(text=f'{muted}/{outnum} output file muted', icon='ERROR')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
class GPEXP_OT_render_selected_scene(bpy.types.Operator):
|
||||||
|
bl_idname = "gp.render_selected_scenes"
|
||||||
|
bl_label = "Render Selected Scenes"
|
||||||
|
bl_description = "Launch render of selected scenes with a selection popup"
|
||||||
|
bl_options = {"REGISTER"}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return bpy.data.is_saved
|
||||||
|
|
||||||
|
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()
|
||||||
|
for s in bpy.data.scenes:
|
||||||
|
scn_item = context.scene.scenes_list.add()
|
||||||
|
scn_item.name = s.name
|
||||||
|
scn_item.select = s.name != 'Scene'
|
||||||
|
|
||||||
|
return context.window_manager.invoke_props_dialog(self, width=250)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
## Basic (without hints)
|
||||||
|
# layout = self.layout
|
||||||
|
# col = layout.column()
|
||||||
|
# for si in context.scene.scenes_list:
|
||||||
|
# row = col.row()
|
||||||
|
# row.label(text=si.name)
|
||||||
|
# row.prop(si, 'select',text='')
|
||||||
|
|
||||||
|
scene_render_popup_ui(self, context)
|
||||||
|
|
||||||
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')
|
||||||
|
|
||||||
|
scn_to_render = [si.name for si in context.scene.scenes_list if si.select]
|
||||||
|
start = time()
|
||||||
|
ct = 0
|
||||||
|
for scn_name in scn_to_render:
|
||||||
|
scn = bpy.data.scenes.get(scn_name)
|
||||||
|
if not scn.use_nodes:
|
||||||
|
print(f'{scn.name} has use node deactivated')
|
||||||
|
continue
|
||||||
|
|
||||||
|
outfiles = [n for n in scn.node_tree.nodes if n.type == 'OUTPUT_FILE']
|
||||||
|
if not outfiles:
|
||||||
|
print(f'\n -!-> Skip {scn.name}, No output files')
|
||||||
|
continue
|
||||||
|
|
||||||
|
if all(x.mute for x in outfiles):
|
||||||
|
print(f'\n -!-> Skip {scn.name}, All output file are muted')
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f'\n --> Rendering {scn.name}')
|
||||||
|
# bpy.context.window.scene = scn # no need
|
||||||
|
bpy.ops.render.render(animation=True, scene=scn.name)
|
||||||
|
ct += 1
|
||||||
|
|
||||||
|
print(f'\nDone. {ct} scenes rendered in {time()-start:.2f}s')
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class GPEXP_OT_bg_render_script_selected_scene(bpy.types.Operator):
|
||||||
|
bl_idname = "gp.bg_render_script_selected_scenes"
|
||||||
|
bl_label = "Create Selected Scene Render Batch "
|
||||||
|
bl_description = "Create a batch script to render all selected scenes in a selection popup"
|
||||||
|
bl_options = {"REGISTER"}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return bpy.data.is_saved
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
context.scene.scenes_list.clear()
|
||||||
|
for s in bpy.data.scenes:
|
||||||
|
scn_item = context.scene.scenes_list.add()
|
||||||
|
scn_item.name = s.name
|
||||||
|
scn_item.select = s.name != 'Scene'
|
||||||
|
|
||||||
|
return context.window_manager.invoke_props_dialog(self, width=500)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
scene_render_popup_ui(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"}
|
||||||
|
|
||||||
|
|
|
@ -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": "",
|
||||||
|
|
1
fn.py
1
fn.py
|
@ -828,6 +828,7 @@ 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
|
||||||
|
|
||||||
|
if coord_dic:
|
||||||
# save bbox
|
# save bbox
|
||||||
with json_path.open('w') as fd:
|
with json_path.open('w') as fd:
|
||||||
json.dump(coord_dic, fd, indent='\t')
|
json.dump(coord_dic, fd, indent='\t')
|
||||||
|
|
Loading…
Reference in New Issue