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
This commit is contained in:
		
							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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user