UI update and fixes
0.1.1 - ui: show number of selected obj - ui: show panels in dopesheet and node windows
This commit is contained in:
		
							parent
							
								
									38481de18d
								
							
						
					
					
						commit
						47baf97822
					
				
							
								
								
									
										14
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@ -1,5 +1,19 @@
 | 
				
			|||||||
# Changelog
 | 
					# Changelog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- TODO
 | 
				
			||||||
 | 
					if objects has multiple user without being linked in render scene :
 | 
				
			||||||
 | 
					    duplicate the object insteat of linking
 | 
				
			||||||
 | 
					OR always duplicate (safe but heavy scenes...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if duplicate, need to "connect" with namespace ('_duprender') or something
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					0.1.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- ui: show number of selected obj
 | 
				
			||||||
 | 
					- ui: show panels in dopesheet and node windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
0.1.0
 | 
					0.1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
first WIP usable version
 | 
					first WIP usable version
 | 
				
			||||||
@ -69,7 +69,7 @@ class GPEXP_OT_add_objects_to_render(bpy.types.Operator):
 | 
				
			|||||||
            if not scn:
 | 
					            if not scn:
 | 
				
			||||||
                self.report({'ERROR'}, 'Could not found default scene')
 | 
					                self.report({'ERROR'}, 'Could not found default scene')
 | 
				
			||||||
                return {"CANCELLED"}
 | 
					                return {"CANCELLED"}
 | 
				
			||||||
            export_gp_objects([o for o in scn.objects if o.type == 'GPENCIL'])
 | 
					            export_gp_objects([o for o in scn.objects if o.type == 'GPENCIL' and not o.hide_get()])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return {"FINISHED"}
 | 
					        return {"FINISHED"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										19
									
								
								OP_clear.py
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								OP_clear.py
									
									
									
									
									
								
							@ -11,7 +11,7 @@ class GPEXP_OT_clear_render_tree(bpy.types.Operator):
 | 
				
			|||||||
    def poll(cls, context):
 | 
					    def poll(cls, context):
 | 
				
			||||||
        return True
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mode : bpy.props.StringProperty(options={'SKIP_SAVE'})
 | 
					    mode : bpy.props.StringProperty(default='NORMAL', options={'SKIP_SAVE'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def execute(self, context):
 | 
					    def execute(self, context):
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
@ -19,13 +19,25 @@ class GPEXP_OT_clear_render_tree(bpy.types.Operator):
 | 
				
			|||||||
        if not render:
 | 
					        if not render:
 | 
				
			||||||
            print('SKIP, no Render scene')
 | 
					            print('SKIP, no Render scene')
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # clear all nodes
 | 
					        # clear all nodes in frames
 | 
				
			||||||
        if render.use_nodes:
 | 
					        if render.use_nodes:
 | 
				
			||||||
            for i in range(len(render.node_tree.nodes))[::-1]:
 | 
					            for i in range(len(render.node_tree.nodes))[::-1]:
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                # skip frames to delete later
 | 
				
			||||||
 | 
					                if render.node_tree.nodes[i].type == 'FRAME':
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                # skip unparented nodes
 | 
				
			||||||
                if not render.node_tree.nodes[i].parent:
 | 
					                if not render.node_tree.nodes[i].parent:
 | 
				
			||||||
                    continue
 | 
					                    continue
 | 
				
			||||||
                render.node_tree.nodes.remove(render.node_tree.nodes[i])
 | 
					                render.node_tree.nodes.remove(render.node_tree.nodes[i])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # delete all framesWorki
 | 
				
			||||||
 | 
					        if render.use_nodes:
 | 
				
			||||||
 | 
					            for i in range(len(render.node_tree.nodes))[::-1]:
 | 
				
			||||||
 | 
					                if render.node_tree.nodes[i].type == 'FRAME':
 | 
				
			||||||
 | 
					                    render.node_tree.nodes.remove(render.node_tree.nodes[i])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # clear all view_layers
 | 
					        # clear all view_layers
 | 
				
			||||||
        for vl in reversed(render.view_layers):
 | 
					        for vl in reversed(render.view_layers):
 | 
				
			||||||
            if ' / ' in vl.name:
 | 
					            if ' / ' in vl.name:
 | 
				
			||||||
@ -37,6 +49,9 @@ class GPEXP_OT_clear_render_tree(bpy.types.Operator):
 | 
				
			|||||||
                ng.use_fake_user = False
 | 
					                ng.use_fake_user = False
 | 
				
			||||||
                bpy.data.node_groups.remove(ng)
 | 
					                bpy.data.node_groups.remove(ng)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.mode == 'COMPLETE':
 | 
				
			||||||
 | 
					            bpy.data.scenes.remove(render)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return {"FINISHED"}
 | 
					        return {"FINISHED"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
classes=(
 | 
					classes=(
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										35
									
								
								OP_manage_outputs.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								OP_manage_outputs.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					import bpy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GPEXP_OT_mute_toggle_output_nodes(bpy.types.Operator):
 | 
				
			||||||
 | 
					    bl_idname = "gp.mute_toggle_output_nodes"
 | 
				
			||||||
 | 
					    bl_label = "Mute Toggle output nodes"
 | 
				
			||||||
 | 
					    bl_description = "Mute / Unmute all output nodes"
 | 
				
			||||||
 | 
					    bl_options = {"REGISTER"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mute : bpy.props.BoolProperty(default=True, options={'SKIP_SAVE'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def execute(self, context):
 | 
				
			||||||
 | 
					        # scene = bpy.data.scenes.get('Render')
 | 
				
			||||||
 | 
					        ct = 0
 | 
				
			||||||
 | 
					        for n in context.scene.node_tree.nodes:
 | 
				
			||||||
 | 
					            if n.type != 'OUTPUT_FILE':
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					            n.mute = self.mute
 | 
				
			||||||
 | 
					            ct += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        state = 'muted' if self.mute else 'unmuted'
 | 
				
			||||||
 | 
					        self.report({"INFO"}, f'{ct} nodes {state}')
 | 
				
			||||||
 | 
					        return {"FINISHED"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					classes=(
 | 
				
			||||||
 | 
					GPEXP_OT_mute_toggle_output_nodes,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def register(): 
 | 
				
			||||||
 | 
					    for cls in classes:
 | 
				
			||||||
 | 
					        bpy.utils.register_class(cls)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def unregister():
 | 
				
			||||||
 | 
					    for cls in reversed(classes):
 | 
				
			||||||
 | 
					        bpy.utils.unregister_class(cls)
 | 
				
			||||||
@ -1,7 +1,8 @@
 | 
				
			|||||||
import bpy
 | 
					import bpy
 | 
				
			||||||
 | 
					from . import fn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def merge_layers(rlayers, obname=None, active=None):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def merge_layers(rlayers, obname=None):
 | 
					 | 
				
			||||||
    print(f'Merging {len(rlayers)} layers')
 | 
					    print(f'Merging {len(rlayers)} layers')
 | 
				
			||||||
    print('->', [r.layer for r in rlayers])
 | 
					    print('->', [r.layer for r in rlayers])
 | 
				
			||||||
    print()
 | 
					    print()
 | 
				
			||||||
@ -9,24 +10,59 @@ def merge_layers(rlayers, obname=None):
 | 
				
			|||||||
    if not rlayers:
 | 
					    if not rlayers:
 | 
				
			||||||
        return ('ERROR', 'No render layer sent to merge')
 | 
					        return ('ERROR', 'No render layer sent to merge')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ng = rlayers[0].outputs[0].links[0].to_node
 | 
					    # get node group
 | 
				
			||||||
    rlayers.sort(key=lambda x: x.location.y, reverse=True)
 | 
					    # ng = rlayers[0].outputs[0].links[0].to_node
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # sort RL descending    
 | 
				
			||||||
 | 
					    rlayers.sort(key=lambda n: fn.real_loc(n).y, reverse=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vl_name = active.layer
 | 
				
			||||||
 | 
					    if not vl_name:
 | 
				
			||||||
 | 
					        vl_name = rlayers[0].layer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # change colors of those nodes
 | 
					    # change colors of those nodes
 | 
				
			||||||
    color = random_color()
 | 
					    color = fn.random_color()
 | 
				
			||||||
    for n in rlayers:
 | 
					    for n in rlayers:
 | 
				
			||||||
        n.use_custom_color = True
 | 
					        n.use_custom_color = True
 | 
				
			||||||
        n.color = color
 | 
					        n.color = color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    obname, lname = vl_name.split(' / ')
 | 
				
			||||||
 | 
					    lname = bpy.path.clean_name(lname)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    # get inside socket (group input) from outside socket list (should be already ordered)
 | 
					    ng_name = f'merge_NG_{obname}' # only object name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ## by name
 | 
					 | 
				
			||||||
    # for i, inp in enumerate(ng.node_tree.inputs):
 | 
					 | 
				
			||||||
    #     if inp.name == 
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # by connection order
 | 
					    ## clear nodes groups duplication (.00?)
 | 
				
			||||||
 | 
					    fn.clear_nodegroup(ng_name, full_clear=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # get set nodegroup from vlayer name
 | 
				
			||||||
 | 
					    if not ng:
 | 
				
			||||||
 | 
					        ng = nodes.get(ng_name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if not ng:
 | 
				
			||||||
 | 
					        ngroup = bpy.data.node_groups.get(ng_name)
 | 
				
			||||||
 | 
					        # full clear True if exists but not used
 | 
				
			||||||
 | 
					        if ngroup and ngroup.users == 0:
 | 
				
			||||||
 | 
					            ngroup = None
 | 
				
			||||||
 | 
					            fn.clear_nodegroup(ng_name, full_clear=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not ngroup:
 | 
				
			||||||
 | 
					            # delete and recreate ?
 | 
				
			||||||
 | 
					            print(f'create nodegroup {ng_name}')
 | 
				
			||||||
 | 
					            ngroup = bpy.data.node_groups.new(ng_name, 'CompositorNodeTree')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ng = fn.create_node('CompositorNodeGroup', tree=scene.node_tree, location=(fn.real_loc(rlayer)[0] + 600, fn.real_loc(rlayer)[1]), width=400) # (rlayer.location[0] + 600, rlayer.location[1])
 | 
				
			||||||
 | 
					        if frame:
 | 
				
			||||||
 | 
					            ng.parent= frame
 | 
				
			||||||
 | 
					        ng.node_tree = ngroup
 | 
				
			||||||
 | 
					        ng.name = ngroup.name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ng_in = fn.create_node('NodeGroupInput', tree=ngroup, location=(-600,0))
 | 
				
			||||||
 | 
					        ng_out = fn.create_node('NodeGroupOutput', tree=ngroup, location=(600,0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    """ 
 | 
				
			||||||
    socket_list = []
 | 
					    socket_list = []
 | 
				
			||||||
    grp_sockets = []
 | 
					    grp_sockets = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -48,65 +84,95 @@ def merge_layers(rlayers, obname=None):
 | 
				
			|||||||
        if inp.name != grps.name:
 | 
					        if inp.name != grps.name:
 | 
				
			||||||
            print(f'\n! Problem ! : {inp.name}, {grps.name}')
 | 
					            print(f'\n! Problem ! : {inp.name}, {grps.name}')
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ## 
 | 
					    ## 
 | 
				
			||||||
    # JUST CREATE ANOTHER GROUP NODE FOR THE MERGE !
 | 
					    # JUST CREATE ANOTHER GROUP NODE FOR THE MERGE !
 | 
				
			||||||
    ##
 | 
					    ##
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GPEXP_OT_merge_selected_dopesheet_layers(bpy.types.Operator):
 | 
				
			||||||
 | 
					    bl_idname = "gp.merge_selected_dopesheet_layers"
 | 
				
			||||||
 | 
					    bl_label = "Merge selected layers view_layers "
 | 
				
			||||||
 | 
					    bl_description = "Merge view layers of selected gp layers to a new dedicated file output"
 | 
				
			||||||
 | 
					    bl_options = {"REGISTER"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def merge_selected_layers():
 | 
					    @classmethod
 | 
				
			||||||
    '''Merge command from selected GP layers'''
 | 
					    def poll(cls, context):
 | 
				
			||||||
    ob = bpy.context.object
 | 
					        return context.object and context.object.type == 'GPENCIL'
 | 
				
			||||||
    layer_names = [l.info for l in ob.data.layers if l.select and not l.hide]
 | 
					 | 
				
			||||||
    print("layer_names", layer_names)#Dbg
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if len(layer_names) < 2:
 | 
					    def execute(self, context):
 | 
				
			||||||
        print(f'Should select multiple layers for merging')
 | 
					        # merge_selected_layers() # function to merge from GP dopesheet
 | 
				
			||||||
        return
 | 
					        ob = bpy.context.object
 | 
				
			||||||
 | 
					        layer_names = [l.info for l in ob.data.layers if l.select and not l.hide]
 | 
				
			||||||
 | 
					        print("layer_names", layer_names)#Dbg
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if len(layer_names) < 2:
 | 
				
			||||||
 | 
					            print(f'Should select multiple layers for merging')
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        render = bpy.data.scenes.get('Render')
 | 
				
			||||||
 | 
					        if render:
 | 
				
			||||||
 | 
					            nodes = render.node_tree.nodes
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        clean_ob_name = bpy.path.clean_name(ob.name)
 | 
				
			||||||
 | 
					        rlayers = []
 | 
				
			||||||
 | 
					        for l in layer_names:
 | 
				
			||||||
 | 
					            ## identifier is clean_name(ob.name).layer_name
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            idname = f'{clean_ob_name}.{l}'
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            # check the render layer that have a parent frame
 | 
				
			||||||
 | 
					            rlayer = [n for n in nodes if n.type == 'R_LAYERS' and n.layer == idname and n.parent]
 | 
				
			||||||
 | 
					            if not rlayer:
 | 
				
			||||||
 | 
					                # send to function to generate the rlayer and connect
 | 
				
			||||||
 | 
					                # rlayer = creation
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            rlayers.append(rlayer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        merge_layers(rlayers, obname=clean_ob_name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return {"FINISHED"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GPEXP_OT_merge_selected_viewlayer_nodes(bpy.types.Operator):
 | 
				
			||||||
 | 
					    bl_idname = "gp.merge_selected_viewlayer_nodes"
 | 
				
			||||||
 | 
					    bl_label = "Merge selected view_layers "
 | 
				
			||||||
 | 
					    bl_description = "Merge selected view layers to a new dedicated file output"
 | 
				
			||||||
 | 
					    bl_options = {"REGISTER"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def execute(self, context):
 | 
				
			||||||
 | 
					        render = bpy.data.scenes.get('Render')
 | 
				
			||||||
 | 
					        if not render:
 | 
				
			||||||
 | 
					            print('No render scene')
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render = bpy.data.scenes.get('Render')
 | 
					 | 
				
			||||||
    if render:
 | 
					 | 
				
			||||||
        nodes = render.node_tree.nodes
 | 
					        nodes = render.node_tree.nodes
 | 
				
			||||||
 | 
					        selection = [n for n in nodes if n.select and n.type == 'R_LAYERS']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    clean_ob_name = bpy.path.clean_name(ob.name)
 | 
					        if not nodes.active in selection:
 | 
				
			||||||
    rlayers = []
 | 
					            self.report({'ERROR'}, 'The active node not within the render layer selection (used to define out name)')
 | 
				
			||||||
    for l in layer_names:
 | 
					            return {'CANCELLED'}
 | 
				
			||||||
        ## identifier is clean_name(ob.name).layer_name
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        idname = f'{clean_ob_name}.{l}'
 | 
					        # should be from the same object:
 | 
				
			||||||
 | 
					        if not all(selection[0].layer.split('.')[0] == n.layer.split('.')[0] for n in selection):
 | 
				
			||||||
 | 
					            print('Merge -> Not every nodes start with the same object')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # check the render layer that have a parent frame
 | 
					        # obname = selection[0].layer.split('.')[0]
 | 
				
			||||||
        rlayer = [n for n in nodes if n.type == 'R_LAYERS' and n.layer == idname and n.parent]
 | 
					        merge_layers(selection, nodes.active)
 | 
				
			||||||
        if not rlayer:
 | 
					 | 
				
			||||||
            # send to function to generate the rlayer and connect
 | 
					 | 
				
			||||||
            # rlayer = creation
 | 
					 | 
				
			||||||
            continue
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        rlayers.append(rlayer)
 | 
					        return {"FINISHED"}
 | 
				
			||||||
 | 
					 | 
				
			||||||
    merge_layers(rlayers, obname=clean_ob_name)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def merge_selected_render_layers():
 | 
					classes=(
 | 
				
			||||||
    '''Merge command from selected render layers nodes'''
 | 
					GPEXP_OT_merge_selected_dopesheet_layers,
 | 
				
			||||||
    render = bpy.data.scenes.get('Render')
 | 
					GPEXP_OT_merge_selected_viewlayer_nodes,
 | 
				
			||||||
    if not render:
 | 
					)
 | 
				
			||||||
        print('No render scene')
 | 
					 | 
				
			||||||
        return
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    nodes = render.node_tree.nodes
 | 
					def register(): 
 | 
				
			||||||
    selection = [n for n in nodes if n.select and n.type == 'R_LAYERS']
 | 
					    for cls in classes:
 | 
				
			||||||
    
 | 
					        bpy.utils.register_class(cls)
 | 
				
			||||||
    # should be from the same object:
 | 
					 | 
				
			||||||
    assert all(selection[0].layer.split('.')[0] == n.layer.split('.')[0] for n in selection), 'Not every nodes start with the same object'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # obname = selection[0].layer.split('.')[0]
 | 
					 | 
				
			||||||
    merge_layers(selection)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# merge_selected_layers() # function to merge from GP dopesheet
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
merge_selected_render_layers() # function to merge from nodegroup
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def unregister():
 | 
				
			||||||
 | 
					    for cls in reversed(classes):
 | 
				
			||||||
 | 
					        bpy.utils.unregister_class(cls)
 | 
				
			||||||
@ -2,7 +2,7 @@ bl_info = {
 | 
				
			|||||||
    "name": "GP exporter",
 | 
					    "name": "GP exporter",
 | 
				
			||||||
    "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, 1, 0),
 | 
					    "version": (0, 1, 1),
 | 
				
			||||||
    "blender": (2, 93, 0),
 | 
					    "blender": (2, 93, 0),
 | 
				
			||||||
    "location": "View3D",
 | 
					    "location": "View3D",
 | 
				
			||||||
    "warning": "",
 | 
					    "warning": "",
 | 
				
			||||||
@ -11,7 +11,9 @@ bl_info = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from . import OP_add_layer
 | 
					from . import OP_add_layer
 | 
				
			||||||
 | 
					from . import OP_merge_layers
 | 
				
			||||||
from . import OP_clear
 | 
					from . import OP_clear
 | 
				
			||||||
 | 
					from . import OP_manage_outputs
 | 
				
			||||||
from . import ui
 | 
					from . import ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import bpy
 | 
					import bpy
 | 
				
			||||||
@ -22,6 +24,8 @@ def register():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    OP_add_layer.register()
 | 
					    OP_add_layer.register()
 | 
				
			||||||
    OP_clear.register()
 | 
					    OP_clear.register()
 | 
				
			||||||
 | 
					    OP_merge_layers.register()
 | 
				
			||||||
 | 
					    OP_manage_outputs.register()
 | 
				
			||||||
    ui.register()
 | 
					    ui.register()
 | 
				
			||||||
    # bpy.types.Scene.pgroup_name = bpy.props.PointerProperty(type = PROJ_PGT_settings)
 | 
					    # bpy.types.Scene.pgroup_name = bpy.props.PointerProperty(type = PROJ_PGT_settings)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -30,6 +34,8 @@ def unregister():
 | 
				
			|||||||
        return
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ui.unregister()
 | 
					    ui.unregister()
 | 
				
			||||||
 | 
					    OP_manage_outputs.unregister()
 | 
				
			||||||
 | 
					    OP_merge_layers.unregister()
 | 
				
			||||||
    OP_clear.unregister()
 | 
					    OP_clear.unregister()
 | 
				
			||||||
    OP_add_layer.unregister()
 | 
					    OP_add_layer.unregister()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										16
									
								
								fn.py
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								fn.py
									
									
									
									
									
								
							@ -35,13 +35,21 @@ def set_settings(scene=None):
 | 
				
			|||||||
    scene = bpy.context.scene
 | 
					    scene = bpy.context.scene
 | 
				
			||||||
    scene.eevee.taa_render_samples = 1
 | 
					    scene.eevee.taa_render_samples = 1
 | 
				
			||||||
    scene.grease_pencil_settings.antialias_threshold = 0
 | 
					    scene.grease_pencil_settings.antialias_threshold = 0
 | 
				
			||||||
 | 
					    # add transparent toggle on ?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_render_scene():
 | 
					def get_render_scene():
 | 
				
			||||||
    '''Get / Create a scene named Render'''
 | 
					    '''Get / Create a scene named Render'''
 | 
				
			||||||
    render = bpy.data.scenes.get('Render')
 | 
					    render = bpy.data.scenes.get('Render')
 | 
				
			||||||
    if not render:
 | 
					    if not render:
 | 
				
			||||||
        render = bpy.data.scenes.new('Render')
 | 
					        render = bpy.data.scenes.new('Render')
 | 
				
			||||||
        set_settings(render) # setup specific settings
 | 
					        
 | 
				
			||||||
 | 
					        ## link cameras (and lights ?)
 | 
				
			||||||
 | 
					        for ob in bpy.context.scene.objects:
 | 
				
			||||||
 | 
					            if ob.type in ('CAMERA', 'LIGHT'):
 | 
				
			||||||
 | 
					                render.collection.objects.link(ob)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # set adapted render settings (no AA)
 | 
				
			||||||
 | 
					        set_settings(render)
 | 
				
			||||||
    render.use_nodes = True
 | 
					    render.use_nodes = True
 | 
				
			||||||
    return render
 | 
					    return render
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -253,3 +261,9 @@ def connect_to_group_input(n):
 | 
				
			|||||||
            if val:
 | 
					            if val:
 | 
				
			||||||
                return val
 | 
					                return val
 | 
				
			||||||
    return False
 | 
					    return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def random_color(alpha=False):
 | 
				
			||||||
 | 
					    import random
 | 
				
			||||||
 | 
					    if alpha:
 | 
				
			||||||
 | 
					        return (random.uniform(0,1), random.uniform(0,1), random.uniform(0,1), 1)
 | 
				
			||||||
 | 
					    return (random.uniform(0,1), random.uniform(0,1), random.uniform(0,1))
 | 
				
			||||||
@ -229,7 +229,7 @@ def get_set_viewlayer_from_gp(ob, l, scene=None):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    # get frame object and their contents
 | 
					    # get frame object and their contents
 | 
				
			||||||
    # dict like : {objname : [layer_nodeA, layer_nodeB,...]}
 | 
					    # dict like : {objname : [layer_nodeA, layer_nodeB,...]}
 | 
				
			||||||
    frame_dic = {f.label: [n for n in nodes if n.type == 'R_LAYERS' and n.parent and n.parent.name == f.name and n.layer != 'View Layer']
 | 
					    frame_dic = {f.label: [n for n in nodes if n.type == 'R_LAYERS' and n.parent and n.parent.name == f.name and '/' in n.layer] # n.layer != 'View Layer'
 | 
				
			||||||
        for f in nodes if f.type == 'FRAME'}
 | 
					        for f in nodes if f.type == 'FRAME'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # debug print
 | 
					    # debug print
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										57
									
								
								ui.py
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								ui.py
									
									
									
									
									
								
							@ -3,38 +3,82 @@ from bpy.types import Panel
 | 
				
			|||||||
# from .preferences import get_addon_prefs
 | 
					# from .preferences import get_addon_prefs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# 3D view panel
 | 
					# Node view panel
 | 
				
			||||||
class GPEXP_PT_gp_node_ui(Panel):
 | 
					class GPEXP_PT_gp_node_ui(Panel):
 | 
				
			||||||
    bl_space_type = "NODE_EDITOR" # "VIEW_3D"
 | 
					    bl_space_type = "NODE_EDITOR" # "VIEW_3D"
 | 
				
			||||||
    bl_region_type = "UI"
 | 
					    bl_region_type = "UI"
 | 
				
			||||||
    bl_category = "Item"
 | 
					    bl_category = "View"
 | 
				
			||||||
    bl_label = "Gpencil Render Manager"
 | 
					    bl_label = "Gpencil Render Manager"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def draw(self, context):
 | 
					    def draw(self, context):
 | 
				
			||||||
        layout = self.layout
 | 
					        layout = self.layout
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        layout.operator('gp.clear_render_tree', icon='X', text='Full Clear Render Tree')
 | 
					        row = layout.row()
 | 
				
			||||||
 | 
					        ct = len([n for n in context.scene.node_tree.nodes if n.type == 'R_LAYERS' and n.select])
 | 
				
			||||||
 | 
					        txt = f'Merge {ct} Layer Nodes'
 | 
				
			||||||
 | 
					        row.operator('gp.merge_selected_viewlayer_nodes', icon='NODETREE', text=txt)
 | 
				
			||||||
 | 
					        row.enabled = ct > 1
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        layout.separator()
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        row=layout.row()
 | 
				
			||||||
 | 
					        row.operator('gp.mute_toggle_output_nodes', icon='NODE_INSERT_ON', text='Mute').mute = True
 | 
				
			||||||
 | 
					        row.operator('gp.mute_toggle_output_nodes', icon='NODE_INSERT_OFF', text='Unmute').mute = False
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        layout.separator()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        col=layout.column()
 | 
				
			||||||
 | 
					        col.operator('gp.clear_render_tree', icon='X', text='Clear Render Tree')
 | 
				
			||||||
 | 
					        col.operator('gp.clear_render_tree', icon='X', text='Clear Delete Render Scene').mode = "COMPLETE"
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # layout.operator('gp.add_object_to_render', icon='RENDERLAYERS', text='Layer To Render').mode = 'ALL'
 | 
					        # layout.operator('gp.add_object_to_render', icon='RENDERLAYERS', text='Layer To Render').mode = 'ALL'
 | 
				
			||||||
        # layout.operator('gp.add_object_to_render', icon='RENDERLAYERS', text='Layer To Render').mode = 'SELECTED'
 | 
					        # layout.operator('gp.add_object_to_render', icon='RENDERLAYERS', text='Layer To Render').mode = 'SELECTED'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # layout.operator('gp.merge_layers', icon='X', text='Merge selected nodes')
 | 
					        # layout.operator('gp.merge_layers', icon='X', text='Merge selected nodes')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GPEXP_PT_gp_dopesheet_ui(Panel):
 | 
				
			||||||
 | 
					    bl_space_type = 'DOPESHEET_EDITOR'
 | 
				
			||||||
 | 
					    bl_region_type = 'UI'
 | 
				
			||||||
 | 
					    # bl_category = "Item"
 | 
				
			||||||
 | 
					    bl_parent_id='DOPESHEET_PT_gpencil_mode'
 | 
				
			||||||
 | 
					    bl_label = "Gpencil Render Manager"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def poll(cls, context):
 | 
				
			||||||
 | 
					        return context.object and context.object.type == 'GPENCIL'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def draw(self, context):
 | 
				
			||||||
 | 
					        layout = self.layout
 | 
				
			||||||
 | 
					        layout.label(text=context.object.name)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        ct = len([l for l in context.object.data.layers if l.select])
 | 
				
			||||||
 | 
					        txt = f'Merge {ct} layers'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # merge layers from dopesheet
 | 
				
			||||||
 | 
					        layout.operator('gp.merge_selected_dopesheet_layers', text=txt, )
 | 
				
			||||||
 | 
					        layout.enabled= ct > 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def manager_ui(self, context):
 | 
					def manager_ui(self, context):
 | 
				
			||||||
    '''appended to DATA_PT_gpencil_layers'''
 | 
					    '''appended to DATA_PT_gpencil_layers'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    layout = self.layout
 | 
					    layout = self.layout
 | 
				
			||||||
    # on layers
 | 
					
 | 
				
			||||||
 | 
					    ## On layers
 | 
				
			||||||
    if context.object and context.object.type == 'GPENCIL':
 | 
					    if context.object and context.object.type == 'GPENCIL':
 | 
				
			||||||
        txt = f'{len([l for l in context.object.data.layers if l.select])} Layer(s) To Render'
 | 
					        txt = f'{len([l for l in context.object.data.layers if l.select])} Layer(s) To Render'
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        txt = 'Layer To Render'
 | 
					        txt = 'Layer To Render'
 | 
				
			||||||
    layout.operator('gp.add_layer_to_render', icon='RENDERLAYERS', text=txt)
 | 
					    layout.operator('gp.add_layer_to_render', icon='RENDERLAYERS', text=txt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # on objects
 | 
					    ## On objects
 | 
				
			||||||
    layout.operator('gp.add_object_to_render', icon='RENDERLAYERS', text='Selected Object To Render').mode='SELECTED'
 | 
					    # txt = 'Selected Object To Render'
 | 
				
			||||||
 | 
					    if context.scene.name != 'Render':
 | 
				
			||||||
 | 
					        txt = f'{len([o for o in context.selected_objects if o.type == "GPENCIL" and o.select_get()])} Selected Object(s) To Render'
 | 
				
			||||||
 | 
					        layout.operator('gp.add_object_to_render', icon='RENDERLAYERS', text=txt).mode='SELECTED'
 | 
				
			||||||
    layout.operator('gp.add_object_to_render', icon='RENDERLAYERS', text='All GP at once').mode='ALL'
 | 
					    layout.operator('gp.add_object_to_render', icon='RENDERLAYERS', text='All GP at once').mode='ALL'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# ## function to append in a menu
 | 
					# ## function to append in a menu
 | 
				
			||||||
# def palette_manager_menu(self, context):
 | 
					# def palette_manager_menu(self, context):
 | 
				
			||||||
#     """Palette menu to append in existing menu"""
 | 
					#     """Palette menu to append in existing menu"""
 | 
				
			||||||
@ -50,6 +94,7 @@ def manager_ui(self, context):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
classes=(
 | 
					classes=(
 | 
				
			||||||
GPEXP_PT_gp_node_ui,
 | 
					GPEXP_PT_gp_node_ui,
 | 
				
			||||||
 | 
					GPEXP_PT_gp_dopesheet_ui,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def register(): 
 | 
					def register(): 
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user