partial autobuild
1.1.0 - added: `autobuild` button (partial auto-buildfor now) - added: make sent object selected
This commit is contained in:
		
							parent
							
								
									e086eb4050
								
							
						
					
					
						commit
						10c279c315
					
				| @ -2,7 +2,7 @@ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| <!-- TODO | <!-- TODO | ||||||
| - need to let use choose output settings | - need to let user choose output settings | ||||||
| 
 | 
 | ||||||
| if objects has multiple user without being linked in render scene : | if objects has multiple user without being linked in render scene : | ||||||
|     duplicate the object insteat of linking |     duplicate the object insteat of linking | ||||||
| @ -14,6 +14,11 @@ Activate / deactivate layer opacity according to prefix | |||||||
| Activate / deactivate all masks using MA layers | Activate / deactivate all masks using MA layers | ||||||
| --> | --> | ||||||
| 
 | 
 | ||||||
|  | 1.1.0 | ||||||
|  | 
 | ||||||
|  | - added: `autobuild` button (partial auto-buildfor now) | ||||||
|  | - added: make sent object selected | ||||||
|  | 
 | ||||||
| 1.0.3 | 1.0.3 | ||||||
| 
 | 
 | ||||||
| - fixed: Send to render layer compatibility with blender 3.4 | - fixed: Send to render layer compatibility with blender 3.4 | ||||||
|  | |||||||
| @ -75,17 +75,19 @@ class GPEXP_OT_render_auto_build(bpy.types.Operator): | |||||||
|             if (render_wkspace := bpy.data.workspaces.get('GP Render')): |             if (render_wkspace := bpy.data.workspaces.get('GP Render')): | ||||||
|                 context.window.workspace = render_wkspace |                 context.window.workspace = render_wkspace | ||||||
|             else: |             else: | ||||||
|                 render_wkspace_filepath = Path(bpy.utils.user_resource('SCRIPTS'), 'startup', 'GP', 'startup.blend') |                 render_wkspace_filepath = Path(bpy.utils.user_resource('SCRIPTS'), 'startup', 'bl_app_templates_user', 'GP', 'startup.blend') | ||||||
|  |                 print('render workspace', render_wkspace_filepath.exists()) | ||||||
|                 ret = bpy.ops.workspace.append_activate(idname='GP Render', filepath=str(render_wkspace_filepath)) |                 ret = bpy.ops.workspace.append_activate(idname='GP Render', filepath=str(render_wkspace_filepath)) | ||||||
|  |                 print('ret: ', ret) | ||||||
|                 if ret != {'FINISHED'}: |                 if ret != {'FINISHED'}: | ||||||
|                     # Fallback to workspace template shipped with addon (TODO : add template blend file in addon) |                     # Fallback to workspace template shipped with addon (TODO : add template blend file in addon) | ||||||
|                     render_wkspace_filepath = Path(__file__).parent / 'workspaces' / 'startup.blend' |                     render_wkspace_filepath = Path(__file__).parent / 'workspaces' / 'startup.blend' | ||||||
|                     ret = bpy.ops.workspace.append_activate(idname='GP Render', filepath=str(render_wkspace_filepath)) |                     ret = bpy.ops.workspace.append_activate(idname='GP Render', filepath=str(render_wkspace_filepath)) | ||||||
| 
 |                 if ret != {'FINISHED'}: | ||||||
|  |                     print('No GP render workspace available') | ||||||
| 
 | 
 | ||||||
|         ## Group all adjacent layer type |         ## Group all adjacent layer type | ||||||
|          |          | ||||||
|          |  | ||||||
| 
 | 
 | ||||||
|         ## Renumber File outputs |         ## Renumber File outputs | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -114,6 +114,73 @@ def merge_layers(rlayers, obname=None, active=None, disconnect=True, color=None) | |||||||
| 
 | 
 | ||||||
|     return ng, out |     return ng, out | ||||||
| 
 | 
 | ||||||
|  | def merge_gplayer_viewlayers(ob, act=None, layers=None): | ||||||
|  |     if act is None: | ||||||
|  |         act = ob.data.layers.active | ||||||
|  |     if layers is None: | ||||||
|  |         layers = [l for l in ob.data.layers if l.select and l != act] | ||||||
|  | 
 | ||||||
|  |     rd_scn = bpy.data.scenes.get('Render') | ||||||
|  |     if not rd_scn: | ||||||
|  |         return ({'ERROR'}, 'Viewlayers needs to be generated first!') | ||||||
|  |      | ||||||
|  |     if not act.viewlayer_render: | ||||||
|  |         return ({'ERROR'}, f'Active layer {act.info} has no viewlayer assigned') | ||||||
|  | 
 | ||||||
|  |     # list layers and viewlayers | ||||||
|  |     vls = [rd_scn.view_layers.get(l.viewlayer_render) for l in layers | ||||||
|  |         if l.viewlayer_render and l.viewlayer_render != act.viewlayer_render and rd_scn.view_layers.get(l.viewlayer_render)] | ||||||
|  | 
 | ||||||
|  |     vl_names = [v.name for v in vls] | ||||||
|  | 
 | ||||||
|  |     for n in reversed(rd_scn.node_tree.nodes): | ||||||
|  |         if n.type == 'R_LAYERS' and n.layer in vl_names: | ||||||
|  |             for lnk in n.outputs[0].links: | ||||||
|  |                 grp = lnk.to_node | ||||||
|  |                 if grp.type != 'GROUP': | ||||||
|  |                     continue | ||||||
|  |                 if not grp.name.startswith('NG'): | ||||||
|  |                     continue | ||||||
|  |                 sockin = lnk.to_socket | ||||||
|  |                 sockout = grp.outputs.get(sockin.name) | ||||||
|  |                 if not sockout: | ||||||
|  |                     continue | ||||||
|  |                  | ||||||
|  |                 for grplink in sockout.links: | ||||||
|  |                     if grplink.to_node.type != 'OUTPUT_FILE': | ||||||
|  |                         continue | ||||||
|  |                     fo_socket = grplink.to_socket | ||||||
|  |                     fo = grplink.to_node | ||||||
|  |                     fo.file_slots.remove(fo_socket) | ||||||
|  |                  | ||||||
|  |                 # remove input and output from group | ||||||
|  |                 # grp.inputs.remove(sockin) # do not clear inside !! | ||||||
|  |                 # grp.outputs.remove(sockout) # do not clear inside !! | ||||||
|  |                 ngroup = grp.node_tree | ||||||
|  |                 for i in range(len(grp.inputs))[::-1]: | ||||||
|  |                     if grp.inputs[i].name == sockin.name: | ||||||
|  |                         ngroup.inputs.remove(ngroup.inputs[i]) | ||||||
|  |                         break | ||||||
|  |                 for i in range(len(grp.outputs))[::-1]: | ||||||
|  |                     if grp.outputs[i].name == sockout.name: | ||||||
|  |                         ngroup.outputs.remove(ngroup.outputs[i]) | ||||||
|  |                         break | ||||||
|  |              | ||||||
|  |             # remove render_layer node | ||||||
|  |             rd_scn.node_tree.nodes.remove(n) | ||||||
|  |      | ||||||
|  |     # assign view layer from active to selected | ||||||
|  |     for l in layers: | ||||||
|  |         l.viewlayer_render = act.viewlayer_render | ||||||
|  | 
 | ||||||
|  |     ## delete unused_vl | ||||||
|  | 
 | ||||||
|  |     # used_vl_name = [n.layer for n in rd_scn.node_tree.nodes if n.type == 'R_LAYERS' and n.layer]         | ||||||
|  |     for vl in vls: | ||||||
|  |         rd_scn.view_layers.remove(vl)             | ||||||
|  |         # if not vl.name in used_vl_name: | ||||||
|  |             # rd_scn.view_layers.remove(vl) | ||||||
|  | 
 | ||||||
| class GPEXP_OT_merge_viewlayers_to_active(bpy.types.Operator): | class GPEXP_OT_merge_viewlayers_to_active(bpy.types.Operator): | ||||||
|     bl_idname = "gp.merge_viewlayers_to_active" |     bl_idname = "gp.merge_viewlayers_to_active" | ||||||
|     bl_label = "Merge selected layers view_layers" |     bl_label = "Merge selected layers view_layers" | ||||||
| @ -130,69 +197,19 @@ class GPEXP_OT_merge_viewlayers_to_active(bpy.types.Operator): | |||||||
|         act = ob.data.layers.active |         act = ob.data.layers.active | ||||||
|         layers = [l for l in ob.data.layers if l.select and l != act] |         layers = [l for l in ob.data.layers if l.select and l != act] | ||||||
| 
 | 
 | ||||||
|         if not act.viewlayer_render: |         ## Tested in func | ||||||
|             self.report({'ERROR'}, f'Active layer {act.info} has no viewlayer assigned') |         # rd_scn = bpy.data.scenes.get('Render') | ||||||
|             return {'CANCELLED'} |         # if not rd_scn: | ||||||
|  |         #     self.report({'ERROR'}, 'Viewlayers needs to be generated first!') | ||||||
|  |         #     return {'CANCELLED'} | ||||||
| 
 | 
 | ||||||
|         rd_scn = bpy.data.scenes.get('Render') |         # if not act.viewlayer_render: | ||||||
|         if not rd_scn: |         #     self.report({'ERROR'}, f'Active layer {act.info} has no viewlayer assigned') | ||||||
|             self.report({'ERROR'}, 'Viewlayers needs to be generated first!') |         #     return {'CANCELLED'} | ||||||
|             return {'CANCELLED'} |  | ||||||
| 
 |  | ||||||
|         # list layers and viewlayers |  | ||||||
|         vls = [rd_scn.view_layers.get(l.viewlayer_render) for l in layers |  | ||||||
|             if l.viewlayer_render and l.viewlayer_render != act.viewlayer_render and rd_scn.view_layers.get(l.viewlayer_render)] |  | ||||||
| 
 |  | ||||||
|         vl_names = [v.name for v in vls] |  | ||||||
| 
 |  | ||||||
|         for n in reversed(rd_scn.node_tree.nodes): |  | ||||||
|             if n.type == 'R_LAYERS' and n.layer in vl_names: |  | ||||||
|                 for lnk in n.outputs[0].links: |  | ||||||
|                     grp = lnk.to_node |  | ||||||
|                     if grp.type != 'GROUP': |  | ||||||
|                         continue |  | ||||||
|                     if not grp.name.startswith('NG'): |  | ||||||
|                         continue |  | ||||||
|                     sockin = lnk.to_socket |  | ||||||
|                     sockout = grp.outputs.get(sockin.name) |  | ||||||
|                     if not sockout: |  | ||||||
|                         continue |  | ||||||
|                      |  | ||||||
|                     for grplink in sockout.links: |  | ||||||
|                         if grplink.to_node.type != 'OUTPUT_FILE': |  | ||||||
|                             continue |  | ||||||
|                         fo_socket = grplink.to_socket |  | ||||||
|                         fo = grplink.to_node |  | ||||||
|                         fo.file_slots.remove(fo_socket) |  | ||||||
|                      |  | ||||||
|                     # remove input and output from group |  | ||||||
|                     # grp.inputs.remove(sockin) # do not clear inside !! |  | ||||||
|                     # grp.outputs.remove(sockout) # do not clear inside !! |  | ||||||
|                     ngroup = grp.node_tree |  | ||||||
|                     for i in range(len(grp.inputs))[::-1]: |  | ||||||
|                         if grp.inputs[i].name == sockin.name: |  | ||||||
|                             ngroup.inputs.remove(ngroup.inputs[i]) |  | ||||||
|                             break |  | ||||||
|                     for i in range(len(grp.outputs))[::-1]: |  | ||||||
|                         if grp.outputs[i].name == sockout.name: |  | ||||||
|                             ngroup.outputs.remove(ngroup.outputs[i]) |  | ||||||
|                             break |  | ||||||
|                  |  | ||||||
|                 # remove render_layer node |  | ||||||
|                 rd_scn.node_tree.nodes.remove(n) |  | ||||||
|          |          | ||||||
|         # assign view layer from active to selected |         ret = merge_gplayer_viewlayers(ob, act=act, layers=layers) | ||||||
|         for l in layers: |         if isinstance(ret, tuple): | ||||||
|             l.viewlayer_render = act.viewlayer_render |             self.report(*ret) | ||||||
| 
 |  | ||||||
|         ## delete unused_vl |  | ||||||
| 
 |  | ||||||
|         # used_vl_name = [n.layer for n in rd_scn.node_tree.nodes if n.type == 'R_LAYERS' and n.layer]         |  | ||||||
|         for vl in vls: |  | ||||||
|             rd_scn.view_layers.remove(vl)             |  | ||||||
|             # if not vl.name in used_vl_name: |  | ||||||
|                 # rd_scn.view_layers.remove(vl) |  | ||||||
| 
 |  | ||||||
|         return {"FINISHED"} |         return {"FINISHED"} | ||||||
| 
 | 
 | ||||||
| class GPEXP_OT_merge_selected_dopesheet_layers(bpy.types.Operator): | class GPEXP_OT_merge_selected_dopesheet_layers(bpy.types.Operator): | ||||||
|  | |||||||
| @ -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": (1, 0, 2), |     "version": (1, 1, 0), | ||||||
|     "blender": (2, 93, 0), |     "blender": (2, 93, 0), | ||||||
|     "location": "View3D", |     "location": "View3D", | ||||||
|     "warning": "", |     "warning": "", | ||||||
|  | |||||||
| @ -234,7 +234,17 @@ def get_set_viewlayer_from_gp(ob, l, scene=None): | |||||||
|             # ob.data = ob.data.copy() # create duplicate (this will also affect the one in original scene !!!) |             # ob.data = ob.data.copy() # create duplicate (this will also affect the one in original scene !!!) | ||||||
|         scene.collection.objects.link(ob) |         scene.collection.objects.link(ob) | ||||||
|         ob.hide_viewport = ob.hide_render = False |         ob.hide_viewport = ob.hide_render = False | ||||||
|      |          | ||||||
|  |         ## set object active in default viewlayer | ||||||
|  |          | ||||||
|  |         # if (avl := scene.view_layers.get('ViewLayer')): | ||||||
|  |         #     # This select the object in source scene | ||||||
|  |         #     avl.objects.active = ob | ||||||
|  |         #     # avl.objects.active.select_set(True) | ||||||
|  |         nob = scene.collection.objects.get(ob.name) | ||||||
|  |         if nob: | ||||||
|  |             nob.select_set(True) | ||||||
|  | 
 | ||||||
|     # create viewlayer |     # create viewlayer | ||||||
|     vl_name = f'{ob.name} / {l.info}' |     vl_name = f'{ob.name} / {l.info}' | ||||||
|     vl = fn.get_view_layer(vl_name, scene=scene) |     vl = fn.get_view_layer(vl_name, scene=scene) | ||||||
|  | |||||||
							
								
								
									
										3
									
								
								ui.py
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								ui.py
									
									
									
									
									
								
							| @ -174,8 +174,7 @@ class GPEXP_PT_gp_dopesheet_ui(Panel): | |||||||
|     def draw(self, context): |     def draw(self, context): | ||||||
|         layout = self.layout |         layout = self.layout | ||||||
| 
 | 
 | ||||||
|         ## TODO: add auto-build |         layout.operator('gp_export.render_auto_build') | ||||||
|         # layout.operator('gp_export.render_auto_build') |  | ||||||
|         if context.object: |         if context.object: | ||||||
|             layout.label(text=f'Object: {context.object.name}') |             layout.label(text=f'Object: {context.object.name}') | ||||||
|             if context.object.data.users > 1: |             if context.object.data.users > 1: | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user