add render as pdf
0.4.0 - feat: render as pdf - ui: advanced options (prefs, disabled by default) - feat: check numbers of muted outputs - code: added addon prefsmain
parent
a0a1647bf9
commit
257fb557ac
|
@ -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.4.0
|
||||||
|
|
||||||
|
- feat: render as pdf
|
||||||
|
- ui: advanced options (prefs, disabled by default)
|
||||||
|
- feat: check numbers of muted outputs
|
||||||
|
- code: added addon prefs
|
||||||
|
|
||||||
0.3.7
|
0.3.7
|
||||||
|
|
||||||
- fix: set render scene res at 100% at creation
|
- fix: set render scene res at 100% at creation
|
||||||
|
|
|
@ -0,0 +1,272 @@
|
||||||
|
import bpy
|
||||||
|
from . import fn
|
||||||
|
from pathlib import Path
|
||||||
|
from itertools import groupby
|
||||||
|
from pprint import pprint as pp
|
||||||
|
from time import time, strftime
|
||||||
|
|
||||||
|
def export_all_selected_frame_as_svg():
|
||||||
|
'''Export All frames (only where there is a frame) of selected layer as svg'''
|
||||||
|
### Export operator parameters description
|
||||||
|
# use_fill (boolean, (optional)) – Fill, Export strokes with fill enabled
|
||||||
|
|
||||||
|
# selected_object_type (enum in ['ACTIVE', 'SELECTED', 'VISIBLE'], (optional)) –
|
||||||
|
|
||||||
|
# Object, Which objects to include in the export
|
||||||
|
# ACTIVE Active, Include only the active object.
|
||||||
|
# SELECTED Selected, Include selected objects.
|
||||||
|
# VISIBLE Visible, Include all visible objects.
|
||||||
|
#
|
||||||
|
# stroke_sample (float in [0, 100], (optional)) – Sampling, Precision of stroke sampling. Low values mean a more precise result, and zero disables sampling
|
||||||
|
# use_normalized_thickness (boolean, (optional)) – Normalize, Export strokes with constant thickness
|
||||||
|
# use_clip_camera (boolean, (optional)) – Clip Camera, Clip drawings to camera size when export in camera view
|
||||||
|
|
||||||
|
|
||||||
|
## Write an ouput name (folder and image will use this name)
|
||||||
|
## if left empty, will use name of active object with 'svg_' prefix
|
||||||
|
name = ''
|
||||||
|
only_frames = 1 # put 0 to export whole frame range
|
||||||
|
## ----
|
||||||
|
|
||||||
|
o = bpy.context.object
|
||||||
|
assert o.type == 'GPENCIL', 'Active object should be GP'
|
||||||
|
|
||||||
|
if only_frames:
|
||||||
|
frames = []
|
||||||
|
for ob in bpy.context.selected_objects:
|
||||||
|
if ob.type != 'GPENCIL':
|
||||||
|
continue
|
||||||
|
frames += [f.frame_number for l in ob.data.layers if not l.hide for f in l.frames if len(f.strokes)]
|
||||||
|
|
||||||
|
if frames:
|
||||||
|
frames = sorted(list(set(frames)))
|
||||||
|
else:
|
||||||
|
frames = [f for f in range(bpy.context.scene.frame_start, bpy.context.scene.frame_end + 1)]
|
||||||
|
|
||||||
|
print(len(frames), 'frames to export')
|
||||||
|
pass_name = name if name else f'svg_{o.name}'
|
||||||
|
|
||||||
|
|
||||||
|
blend = Path(bpy.data.filepath)
|
||||||
|
|
||||||
|
for fnum in frames:
|
||||||
|
out = f'{pass_name}_{fnum:04d}.svg'
|
||||||
|
print(out)
|
||||||
|
folder = blend.parent / 'render' / pass_name
|
||||||
|
folder.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
fp = folder / out
|
||||||
|
if fp.exists():
|
||||||
|
print(f' already exists: {fp}')
|
||||||
|
continue
|
||||||
|
|
||||||
|
bpy.context.scene.frame_current = fnum
|
||||||
|
bpy.ops.wm.gpencil_export_svg(filepath=str(fp),
|
||||||
|
check_existing=True,
|
||||||
|
use_fill=True, selected_object_type='SELECTED', # ACTIVE, VISIBLE
|
||||||
|
stroke_sample=0.0,
|
||||||
|
use_normalized_thickness=False,
|
||||||
|
use_clip_camera=True) # False by defaut
|
||||||
|
|
||||||
|
print('Done')
|
||||||
|
|
||||||
|
|
||||||
|
def pdf_render(fp):
|
||||||
|
scn = bpy.context.scene
|
||||||
|
fp.parent.mkdir(parents=True, exist_ok=True) # mode=0o777
|
||||||
|
for fnum in range(scn.frame_start, scn.frame_end + 1):
|
||||||
|
# print('fnum: ', fnum)
|
||||||
|
scn.frame_current = fnum
|
||||||
|
# bpy.ops.wm.gpencil_export_svg(filepath=str(fp),
|
||||||
|
# check_existing=True,
|
||||||
|
# use_fill=True, selected_object_type='SELECTED', # ACTIVE, VISIBLE
|
||||||
|
# stroke_sample=0.0,
|
||||||
|
# use_normalized_thickness=False,
|
||||||
|
# use_clip_camera=True) # False by defaut
|
||||||
|
|
||||||
|
# bpy.ops.wm.gpencil_export_pdf(filepath=f'{bpy.path.abspath(str(fp)).rstrip("/")}{fnum:04d}.pdf',
|
||||||
|
bpy.ops.wm.gpencil_export_pdf(filepath=f'{fp}{fnum:04d}.pdf',
|
||||||
|
check_existing=False, # True by default
|
||||||
|
use_fill=True,
|
||||||
|
selected_object_type='ACTIVE', # VISIBLE, SELECTED
|
||||||
|
stroke_sample=0,
|
||||||
|
use_normalized_thickness=False,
|
||||||
|
frame_mode='ACTIVE')
|
||||||
|
|
||||||
|
class GPEXP_OT_export_as_pdf(bpy.types.Operator):
|
||||||
|
bl_idname = "gp.export_as_pdf"
|
||||||
|
bl_label = "export_as_pdf"
|
||||||
|
bl_description = "Export current layers as pdf"
|
||||||
|
bl_options = {"REGISTER"}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
# rd_scn = bpy.data.scenes.get('Render')
|
||||||
|
# if not rd_scn:
|
||||||
|
# self.report({'ERROR'}, 'Viewlayers needs to be generated first!')
|
||||||
|
# return {'CANCELLED'}
|
||||||
|
|
||||||
|
|
||||||
|
### store
|
||||||
|
## dict all visible objects as key with value : sub dict {layer : hide_bool}
|
||||||
|
|
||||||
|
# obj_vis = [[o, o.hide_viewport, o.hide_render] for o in context.scene.objects if o.type == 'GPENCIL' and not (o.hide_get() or o.hide_viewport)]
|
||||||
|
t0 = time()
|
||||||
|
|
||||||
|
store = {o: {l: l.hide for l in o.data.layers} for o in context.scene.objects if o.type == 'GPENCIL' and not (o.hide_get() or o.hide_viewport)}
|
||||||
|
# pp(store)
|
||||||
|
act = context.object if context.object else None
|
||||||
|
selection = [o for o in context.selected_objects]
|
||||||
|
|
||||||
|
messages = []
|
||||||
|
|
||||||
|
## adaptative resampling on all concerned objects
|
||||||
|
for ob in store.keys():
|
||||||
|
mod = ob.grease_pencil_modifiers.get('resample')
|
||||||
|
if not mod:
|
||||||
|
mod = ob.grease_pencil_modifiers.new('resample', 'GP_SIMPLIFY')
|
||||||
|
mod.mode = 'ADAPTIVE'
|
||||||
|
mod.factor = 0.001
|
||||||
|
|
||||||
|
# for ob in context.scene.objects:
|
||||||
|
for ob in store.keys():
|
||||||
|
if ob.type != 'GPENCIL':
|
||||||
|
continue
|
||||||
|
|
||||||
|
mess = f'--- {ob.name}:'
|
||||||
|
print(mess)
|
||||||
|
messages.append(mess)
|
||||||
|
|
||||||
|
## swap hide other GP object (or just swap select)
|
||||||
|
# for so in store.keys():
|
||||||
|
# so.hide_viewport = True
|
||||||
|
# ob.hide_viewport = False
|
||||||
|
|
||||||
|
context.view_layer.objects.active = ob # render active only mode
|
||||||
|
# for o in context.scene.objects:
|
||||||
|
# o.hide_viewport = True
|
||||||
|
# ob.hide_viewport = False
|
||||||
|
|
||||||
|
## manage layers
|
||||||
|
gpl = ob.data.layers
|
||||||
|
vl_dicts = {vl_name: list(layer_grp) for vl_name, layer_grp in groupby(gpl, lambda x: x.viewlayer_render)}
|
||||||
|
for vl_name, layer_list in vl_dicts.items():
|
||||||
|
vl = context.scene.view_layers.get(vl_name)
|
||||||
|
if not vl:
|
||||||
|
mess = f'/!\ {vl_name} viewlayer not exists : skipped {[l.info for l in layer_list]}'
|
||||||
|
print(mess)
|
||||||
|
messages.append(mess)
|
||||||
|
continue
|
||||||
|
if vl_name in {'exclude', 'View Layer'}:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not vl.use:
|
||||||
|
mess = f'{vl_name} viewlayer disabled'
|
||||||
|
print(mess)
|
||||||
|
messages.append(mess)
|
||||||
|
continue
|
||||||
|
|
||||||
|
|
||||||
|
# Case of initially masked layer !
|
||||||
|
hide_ct = 0
|
||||||
|
total = len(layer_list)
|
||||||
|
for l in layer_list:
|
||||||
|
if store[ob][l]: # get original hide bool
|
||||||
|
hide_ct += 1
|
||||||
|
|
||||||
|
if hide_ct == total:
|
||||||
|
mess = f'/!\ Skip {vl_name}: {hide_ct}/{total} are hided'
|
||||||
|
print(mess)
|
||||||
|
messages.append(mess)
|
||||||
|
continue
|
||||||
|
elif hide_ct > 0:
|
||||||
|
mess = f'Warning: {vl_name}: {hide_ct}/{total} are hided'
|
||||||
|
print(mess)
|
||||||
|
messages.append(mess)
|
||||||
|
|
||||||
|
# check connections in compositor
|
||||||
|
ng_name = f'NG_{ob.name}'
|
||||||
|
ng = context.scene.node_tree.nodes.get(ng_name)
|
||||||
|
if not ng:
|
||||||
|
mess = f'Skip {vl_name}: Not found nodegroup {ng_name}'
|
||||||
|
print(mess)
|
||||||
|
messages.append(mess)
|
||||||
|
continue
|
||||||
|
|
||||||
|
ng_socket = ng.outputs.get(vl_name)
|
||||||
|
|
||||||
|
if not ng_socket:
|
||||||
|
mess = f'Skip {vl_name}: Not found in nodegroup {ng_name} sockets'
|
||||||
|
print(mess)
|
||||||
|
messages.append(mess)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not len(ng_socket.links):
|
||||||
|
mess = f' socket is disconnected in {ng_name} nodegroup'
|
||||||
|
print(mess)
|
||||||
|
messages.append(mess)
|
||||||
|
continue
|
||||||
|
|
||||||
|
fo_node = ng_socket.links[0].to_node
|
||||||
|
fo_socket = ng_socket.links[0].to_socket
|
||||||
|
|
||||||
|
if fo_node.type != 'OUTPUT_FILE':
|
||||||
|
mess = f'Skip {vl_name}: node is not an output_file {fo_node.name}'
|
||||||
|
print(mess)
|
||||||
|
messages.append(mess)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# fo_socket.name isn't right
|
||||||
|
|
||||||
|
idx = [i for i in fo_node.inputs].index(fo_socket)
|
||||||
|
subpath = fo_node.file_slots[idx].path
|
||||||
|
fp = Path(fo_node.base_path.rstrip('/')) / subpath
|
||||||
|
fp = Path(bpy.path.abspath(str(fp)).rstrip("/"))
|
||||||
|
|
||||||
|
print(f'render {total} layers at: {fp.parent}') #Dbg
|
||||||
|
|
||||||
|
# hide all layer that are: not associated with VL (not in layer_list) or hided initially (store[ob][l])
|
||||||
|
for l in gpl:
|
||||||
|
l.hide = l not in layer_list or store[ob][l]
|
||||||
|
|
||||||
|
for l in gpl:
|
||||||
|
if not l.hide:
|
||||||
|
print(f'-> {l.info}') #Dbg
|
||||||
|
|
||||||
|
pdf_render(fp)
|
||||||
|
print()
|
||||||
|
|
||||||
|
### restore
|
||||||
|
for ob, layer_dic in store.items():
|
||||||
|
# ob.hide_viewport = False # no need
|
||||||
|
for l, h in layer_dic.items():
|
||||||
|
l.hide = h
|
||||||
|
|
||||||
|
for o in selection:
|
||||||
|
o.select_set(True)
|
||||||
|
if act:
|
||||||
|
context.view_layer.objects.active = act
|
||||||
|
|
||||||
|
# for oviz in obj_vis:
|
||||||
|
# oviz[0].hide_viewport = oviz[1]
|
||||||
|
|
||||||
|
|
||||||
|
self.report({'INFO'}, f'Done ({time()-t0:.1f}s)')
|
||||||
|
fn.show_message_box(_message=messages, _title='PDF render report')
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
classes=(
|
||||||
|
GPEXP_OT_export_as_pdf,
|
||||||
|
)
|
||||||
|
|
||||||
|
def register():
|
||||||
|
for cls in classes:
|
||||||
|
bpy.utils.register_class(cls)
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
for cls in reversed(classes):
|
||||||
|
bpy.utils.unregister_class(cls)
|
11
README.md
11
README.md
|
@ -3,9 +3,12 @@
|
||||||
|
|
||||||
## Todo
|
## Todo
|
||||||
|
|
||||||
|
- on renaming, correct also names in GP modifiers !!!
|
||||||
|
- opt: multi-merge : also merge merged NG automatically disabling AA without group (or externalise AA node ?)
|
||||||
|
- opt : How to disable main output
|
||||||
|
|
||||||
|
|
||||||
|
## Done
|
||||||
- set exlude VL on non-used layers
|
- set exlude VL on non-used layers
|
||||||
- set real AA nodegroup
|
- set real AA nodegroup
|
||||||
|
- disable all masks (with filter)
|
||||||
- multi-merge : also merge merged NG automatically disabling AA without group (or externalise AA node ?)
|
|
||||||
- opt : How to disable main output
|
|
||||||
- disable all masks
|
|
|
@ -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, 3, 7),
|
"version": (0, 4, 0),
|
||||||
"blender": (2, 93, 0),
|
"blender": (2, 93, 0),
|
||||||
"location": "View3D",
|
"location": "View3D",
|
||||||
"warning": "",
|
"warning": "",
|
||||||
|
@ -18,6 +18,8 @@ from . import OP_connect_toggle
|
||||||
from . import OP_manage_outputs
|
from . import OP_manage_outputs
|
||||||
from . import OP_scene_switch
|
from . import OP_scene_switch
|
||||||
# from . import OP_check_layer_status
|
# from . import OP_check_layer_status
|
||||||
|
from . import OP_render_pdf
|
||||||
|
from . import prefs
|
||||||
from . import OP_setup_layers
|
from . import OP_setup_layers
|
||||||
from . import ui
|
from . import ui
|
||||||
|
|
||||||
|
@ -27,6 +29,7 @@ def register():
|
||||||
if bpy.app.background:
|
if bpy.app.background:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
prefs.register()
|
||||||
OP_add_layer.register()
|
OP_add_layer.register()
|
||||||
OP_clear.register()
|
OP_clear.register()
|
||||||
OP_clean.register()
|
OP_clean.register()
|
||||||
|
@ -35,6 +38,7 @@ def register():
|
||||||
OP_manage_outputs.register()
|
OP_manage_outputs.register()
|
||||||
OP_scene_switch.register()
|
OP_scene_switch.register()
|
||||||
# OP_check_layer_status.register()
|
# OP_check_layer_status.register()
|
||||||
|
OP_render_pdf.register()
|
||||||
OP_setup_layers.register()
|
OP_setup_layers.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)
|
||||||
|
@ -46,6 +50,7 @@ def unregister():
|
||||||
ui.unregister()
|
ui.unregister()
|
||||||
OP_setup_layers.unregister()
|
OP_setup_layers.unregister()
|
||||||
# OP_check_layer_status.unregister()
|
# OP_check_layer_status.unregister()
|
||||||
|
OP_render_pdf.unregister()
|
||||||
OP_scene_switch.unregister()
|
OP_scene_switch.unregister()
|
||||||
OP_manage_outputs.unregister()
|
OP_manage_outputs.unregister()
|
||||||
OP_merge_layers.unregister()
|
OP_merge_layers.unregister()
|
||||||
|
@ -53,6 +58,7 @@ def unregister():
|
||||||
OP_clean.unregister()
|
OP_clean.unregister()
|
||||||
OP_clear.unregister()
|
OP_clear.unregister()
|
||||||
OP_add_layer.unregister()
|
OP_add_layer.unregister()
|
||||||
|
prefs.unregister()
|
||||||
|
|
||||||
# del bpy.types.Scene.pgroup_name
|
# del bpy.types.Scene.pgroup_name
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
class gp_render_prefs(bpy.types.AddonPreferences):
|
||||||
|
bl_idname = __name__.split('.')[0]
|
||||||
|
|
||||||
|
# resample_otf : bpy.props.BoolProperty(
|
||||||
|
# name='Resample on the fly',
|
||||||
|
# description="Allow smoother stroke when using pinch\nnote that stroke using textured materials will not be resampled",
|
||||||
|
# default=True)
|
||||||
|
|
||||||
|
advanced : bpy.props.BoolProperty(
|
||||||
|
name='Advanced Options', # Reproject On Guessed Plane
|
||||||
|
description="Display advanced options",
|
||||||
|
default=False)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.prop(self, "advanced")
|
||||||
|
|
||||||
|
def get_addon_prefs():
|
||||||
|
'''
|
||||||
|
function to read current addon preferences properties
|
||||||
|
access with : get_addon_prefs().super_special_option
|
||||||
|
'''
|
||||||
|
import os
|
||||||
|
addon_name = os.path.splitext(__name__)[0]
|
||||||
|
preferences = bpy.context.preferences
|
||||||
|
addon_prefs = preferences.addons[addon_name].preferences
|
||||||
|
return (addon_prefs)
|
||||||
|
|
||||||
|
|
||||||
|
classes=(
|
||||||
|
gp_render_prefs,
|
||||||
|
)
|
||||||
|
|
||||||
|
def register():
|
||||||
|
for cls in classes:
|
||||||
|
bpy.utils.register_class(cls)
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
for cls in reversed(classes):
|
||||||
|
bpy.utils.unregister_class(cls)
|
36
ui.py
36
ui.py
|
@ -1,5 +1,6 @@
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Panel
|
from bpy.types import Panel
|
||||||
|
from .prefs import get_addon_prefs
|
||||||
# from .preferences import get_addon_prefs
|
# from .preferences import get_addon_prefs
|
||||||
|
|
||||||
# Node view panel
|
# Node view panel
|
||||||
|
@ -11,6 +12,8 @@ class GPEXP_PT_gp_node_ui(Panel):
|
||||||
bl_label = "Gpencil Render Manager"
|
bl_label = "Gpencil Render Manager"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
|
prefs = get_addon_prefs()
|
||||||
|
advanced = prefs.advanced
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.operator('gp.render_scene_switch', icon='SCENE_DATA', text='Switch Scene')
|
layout.operator('gp.render_scene_switch', icon='SCENE_DATA', text='Switch Scene')
|
||||||
|
|
||||||
|
@ -38,12 +41,15 @@ class GPEXP_PT_gp_node_ui(Panel):
|
||||||
# layout.label(text=f'{exclude_count} Excluded View Layers !')
|
# layout.label(text=f'{exclude_count} Excluded View Layers !')
|
||||||
layout.operator('gp.enable_all_viewlayers', text=f'Reactivate {exclude_count} Excluded View Layers')
|
layout.operator('gp.enable_all_viewlayers', text=f'Reactivate {exclude_count} Excluded View Layers')
|
||||||
|
|
||||||
|
|
||||||
if not scn.use_nodes or not scn.node_tree:
|
if not scn.use_nodes or not scn.node_tree:
|
||||||
return
|
return
|
||||||
|
|
||||||
layout.separator()
|
disabled_output = [n for n in scn.node_tree.nodes if n.type == 'OUTPUT_FILE' and n.mute]
|
||||||
# TODO : add advanced bool checkbox to hide some options from the user
|
if disabled_output:
|
||||||
|
layout.label(text=f'{len(disabled_output)} Output Muted', icon='INFO')
|
||||||
|
|
||||||
|
layout.separator()
|
||||||
|
|
||||||
layout.label(text='View layers:')
|
layout.label(text='View layers:')
|
||||||
ct = len([n for n in context.scene.node_tree.nodes if n.type == 'R_LAYERS' and n.select])
|
ct = len([n for n in context.scene.node_tree.nodes if n.type == 'R_LAYERS' and n.select])
|
||||||
|
@ -52,12 +58,12 @@ class GPEXP_PT_gp_node_ui(Panel):
|
||||||
col.operator('gp.activate_only_selected_layers', text=f'Activate Only {ct} Layer Nodes')
|
col.operator('gp.activate_only_selected_layers', text=f'Activate Only {ct} Layer Nodes')
|
||||||
col.enabled = ct > 0
|
col.enabled = ct > 0
|
||||||
|
|
||||||
col = layout.column(align=True)
|
if advanced:
|
||||||
|
col = layout.column(align=True)
|
||||||
txt = f'Merge {ct} Layer Nodes'
|
txt = f'Merge {ct} Layer Nodes'
|
||||||
col.operator('gp.merge_selected_viewlayer_nodes', icon='NODETREE', text=txt).disconnect = True
|
col.operator('gp.merge_selected_viewlayer_nodes', icon='NODETREE', text=txt).disconnect = True
|
||||||
col.operator('gp.merge_selected_viewlayer_nodes', icon='NODETREE', text='Merge (keep connect)').disconnect = False
|
col.operator('gp.merge_selected_viewlayer_nodes', icon='NODETREE', text='Merge (keep connect)').disconnect = False
|
||||||
col.enabled = ct > 1
|
col.enabled = ct > 1
|
||||||
|
|
||||||
layout.separator()
|
layout.separator()
|
||||||
col = layout.column()
|
col = layout.column()
|
||||||
|
@ -100,16 +106,19 @@ class GPEXP_PT_gp_node_ui(Panel):
|
||||||
# subcol.operator('gp.normalize_outnames', icon='SYNTAX_OFF', text=f'Normalize Paths {ct} Selected Ouptut') # not ready
|
# subcol.operator('gp.normalize_outnames', icon='SYNTAX_OFF', text=f'Normalize Paths {ct} Selected Ouptut') # not ready
|
||||||
# col.operator('gp.number_outputs', icon='LINENUMBERS_ON', text='Renumber all outputs').mode = 'ALL'
|
# col.operator('gp.number_outputs', icon='LINENUMBERS_ON', text='Renumber all outputs').mode = 'ALL'
|
||||||
|
|
||||||
subcol.operator('gp.set_output_node_format', icon='OUTPUT', text='Copy Active Output Format')
|
if advanced:
|
||||||
|
subcol.operator('gp.set_output_node_format', icon='OUTPUT', text='Copy Active Output Format')
|
||||||
|
|
||||||
|
|
||||||
layout.separator()
|
layout.separator()
|
||||||
|
|
||||||
col=layout.column()
|
col=layout.column()
|
||||||
col.label(text='Delete Options:')
|
col.label(text='Delete Options:')
|
||||||
col.operator('gp.clear_render_tree', icon='X', text='Clear Framed Nodes')
|
if advanced:
|
||||||
|
col.operator('gp.clear_render_tree', icon='X', text='Clear Framed Nodes')
|
||||||
col.operator('gp.clear_render_tree', icon='X', text='Clear & Delete Render Scene').mode = "COMPLETE"
|
col.operator('gp.clear_render_tree', icon='X', text='Clear & Delete Render Scene').mode = "COMPLETE"
|
||||||
|
|
||||||
|
layout.prop(prefs, 'advanced', text='Show Advanced Options')
|
||||||
# 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'
|
||||||
|
|
||||||
|
@ -171,6 +180,13 @@ class GPEXP_PT_gp_dopesheet_ui(Panel):
|
||||||
# row = layout.row()
|
# row = layout.row()
|
||||||
layout.prop(bpy.context.preferences.edit, 'use_anim_channel_group_colors')
|
layout.prop(bpy.context.preferences.edit, 'use_anim_channel_group_colors')
|
||||||
|
|
||||||
|
layout.separator()
|
||||||
|
|
||||||
|
row = layout.row()
|
||||||
|
row.operator('gp.export_as_pdf', icon='RENDER_STILL', text='Render All to PDF Sequences')
|
||||||
|
if bpy.app.version < (3,0,0):
|
||||||
|
row.label(text='Not Blender 3.0.0')
|
||||||
|
|
||||||
|
|
||||||
class GPEXP_MT_multi_user_doc(bpy.types.Menu):
|
class GPEXP_MT_multi_user_doc(bpy.types.Menu):
|
||||||
# bl_idname = "OBJECT_MT_custom_menu"
|
# bl_idname = "OBJECT_MT_custom_menu"
|
||||||
|
|
Loading…
Reference in New Issue