UI update and fixes
0.1.1 - ui: show number of selected obj - ui: show panels in dopesheet and node windowsmain
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=(
|
||||||
|
|
|
@ -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(' / ')
|
||||||
# get inside socket (group input) from outside socket list (should be already ordered)
|
lname = bpy.path.clean_name(lname)
|
||||||
|
|
||||||
## by name
|
ng_name = f'merge_NG_{obname}' # only object 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
|
def execute(self, context):
|
||||||
|
# merge_selected_layers() # function to merge from GP dopesheet
|
||||||
if len(layer_names) < 2:
|
ob = bpy.context.object
|
||||||
print(f'Should select multiple layers for merging')
|
layer_names = [l.info for l in ob.data.layers if l.select and not l.hide]
|
||||||
return
|
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)
|
|
||||||
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)
|
if not nodes.active in selection:
|
||||||
|
self.report({'ERROR'}, 'The active node not within the render layer selection (used to define out name)')
|
||||||
|
return {'CANCELLED'}
|
||||||
|
|
||||||
merge_layers(rlayers, obname=clean_ob_name)
|
# 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')
|
||||||
|
|
||||||
|
# obname = selection[0].layer.split('.')[0]
|
||||||
|
merge_layers(selection, nodes.active)
|
||||||
|
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
selection = [n for n in nodes if n.select and n.type == 'R_LAYERS']
|
|
||||||
|
|
||||||
# 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]
|
def register():
|
||||||
merge_layers(selection)
|
for cls in classes:
|
||||||
|
bpy.utils.register_class(cls)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 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()
|
||||||
|
|
||||||
|
|
18
fn.py
18
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
|
||||||
|
|
||||||
|
@ -252,4 +260,10 @@ def connect_to_group_input(n):
|
||||||
val = connect_to_group_input(i.links[0].from_node)
|
val = connect_to_group_input(i.links[0].from_node)
|
||||||
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
|
||||||
|
|
59
ui.py
59
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
|
||||||
|
|
||||||
|
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.clear_render_tree', icon='X', text='Full Clear Render Tree')
|
|
||||||
# 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…
Reference in New Issue