gp layers state check and set
0.2.7 - feat: check layer states (check use light, opacity, blend mode) and correct if needed - ui: added chennel group color switch - feat: added color from active layer on merge opsmain
parent
160a957007
commit
364b45e473
|
@ -12,6 +12,12 @@ Activate / deactivate layer opaticty according to prefix
|
||||||
Activate / deactivate all masks using MA layers
|
Activate / deactivate all masks using MA layers
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
0.2.7
|
||||||
|
|
||||||
|
- feat: check layer states (check use light, opacity, blend mode) and correct if needed
|
||||||
|
- ui: added chennel group color switch
|
||||||
|
- feat: added color from active layer on merge ops
|
||||||
|
|
||||||
0.2.6
|
0.2.6
|
||||||
|
|
||||||
- ui: name changes
|
- ui: name changes
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import bpy
|
import bpy
|
||||||
from . import fn
|
from . import fn
|
||||||
|
|
||||||
## direct use (Pop up menu version below)
|
## not used, replaced by "setup_layers.py"
|
||||||
|
|
||||||
|
|
||||||
class GPEXP_OT_check_layers_state(bpy.types.Operator):
|
class GPEXP_OT_check_layers_state(bpy.types.Operator):
|
||||||
bl_idname = "gp.check_layers_state"
|
bl_idname = "gp.check_layers_state"
|
||||||
bl_label = "Check Layers State"
|
bl_label = "Check Layers State"
|
||||||
|
@ -21,6 +19,7 @@ class GPEXP_OT_check_layers_state(bpy.types.Operator):
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
self.ctrl=event.ctrl
|
self.ctrl=event.ctrl
|
||||||
self.alt=event.alt
|
self.alt=event.alt
|
||||||
|
return self.execute(context)
|
||||||
return context.window_manager.invoke_props_dialog(self)
|
return context.window_manager.invoke_props_dialog(self)
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
|
@ -53,8 +52,8 @@ class GPEXP_OT_check_layers_state(bpy.types.Operator):
|
||||||
print(f'-> opacity {l.opacity}')
|
print(f'-> opacity {l.opacity}')
|
||||||
used = True
|
used = True
|
||||||
|
|
||||||
if l.use_light:
|
if l.use_lights:
|
||||||
print(f'-> use light !')
|
print(f'-> use lights !')
|
||||||
used = True
|
used = True
|
||||||
if l.blend_mode != 'REGULAR':
|
if l.blend_mode != 'REGULAR':
|
||||||
print(f'-> blend mode "{l.blend_mode}" !')
|
print(f'-> blend mode "{l.blend_mode}" !')
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
import bpy
|
import bpy
|
||||||
import re
|
import re
|
||||||
|
from math import isclose
|
||||||
from . import fn
|
from . import fn
|
||||||
from . import gen_vlayer
|
from . import gen_vlayer
|
||||||
|
|
||||||
def merge_layers(rlayers, obname=None, active=None, disconnect=True):
|
# TODO : make a merge compatible with already merged nodegroup (or even other node type)
|
||||||
|
# --> need to delete/mute AA internal node
|
||||||
|
|
||||||
|
def merge_layers(rlayers, obname=None, active=None, disconnect=True, color=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])
|
||||||
|
@ -41,6 +45,7 @@ def merge_layers(rlayers, obname=None, active=None, disconnect=True):
|
||||||
|
|
||||||
# change colors of those nodes
|
# change colors of those nodes
|
||||||
disconnected_groups = []
|
disconnected_groups = []
|
||||||
|
if not color:
|
||||||
color = fn.random_color()
|
color = fn.random_color()
|
||||||
for n in rlayers:
|
for n in rlayers:
|
||||||
n.use_custom_color = True
|
n.use_custom_color = True
|
||||||
|
@ -161,7 +166,10 @@ class GPEXP_OT_merge_selected_dopesheet_layers(bpy.types.Operator):
|
||||||
|
|
||||||
rlayers.append(rl)
|
rlayers.append(rl)
|
||||||
|
|
||||||
merge_layers(rlayers, disconnect=self.disconnect)
|
color = None
|
||||||
|
if not any(isclose(i, 0.2, abs_tol=0.0001) for i in act.channel_color): # and bpy.context.preferences.edit.use_anim_channel_group_colors
|
||||||
|
color = act.channel_color
|
||||||
|
merge_layers(rlayers, disconnect=self.disconnect, color=color)
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
import bpy
|
||||||
|
from bpy.props import (FloatProperty,
|
||||||
|
BoolProperty,
|
||||||
|
EnumProperty,
|
||||||
|
StringProperty,
|
||||||
|
IntProperty)
|
||||||
|
from . import fn
|
||||||
|
|
||||||
|
class GPEXP_OT_layers_state(bpy.types.Operator):
|
||||||
|
bl_idname = "gp.layers_state"
|
||||||
|
bl_label = "Set Layers State"
|
||||||
|
bl_description = "Display state of layer that migh need adjustement"
|
||||||
|
bl_options = {"REGISTER"} # , "UNDO"
|
||||||
|
|
||||||
|
# clear_unused_view_layers :BoolProperty(name="Clear unused view layers",
|
||||||
|
# description="Delete view layer that aren't used in the nodetree anymore",
|
||||||
|
# default=True)
|
||||||
|
|
||||||
|
# TODO : (optional) export layer opacity to json and/or text
|
||||||
|
# (that way compo artists can re-affect opacity quickly or at least have a reminder)
|
||||||
|
|
||||||
|
all_objects : BoolProperty(name='On All Object',
|
||||||
|
default=False, description='On All object, else use selected objects') # , options={'SKIP_SAVE'}
|
||||||
|
|
||||||
|
set_full_opacity : BoolProperty(name='Set Full Opacity',
|
||||||
|
default=True, description='Check/Set full opacity') # , options={'SKIP_SAVE'}
|
||||||
|
|
||||||
|
set_use_lights : BoolProperty(name='Disable Use Light',
|
||||||
|
default=True, description='Check/Set use lights disabling') # , options={'SKIP_SAVE'}
|
||||||
|
|
||||||
|
set_blend_mode : BoolProperty(name='Set Regular Blend Mode',
|
||||||
|
default=True, description='Check/Set blend mode to regular') # , options={'SKIP_SAVE'}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return context.object and context.object.type == 'GPENCIL'
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
# self.ctrl=event.ctrl
|
||||||
|
# self.alt=event.alt
|
||||||
|
if event.alt:
|
||||||
|
self.all_objects=True
|
||||||
|
# return self.execute(context)
|
||||||
|
return context.window_manager.invoke_props_dialog(self)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.prop(self, 'all_objects')
|
||||||
|
layout.separator()
|
||||||
|
layout.label(text='Set (or only perform a check):')
|
||||||
|
layout.prop(self, 'set_full_opacity')
|
||||||
|
layout.prop(self, 'set_use_lights')
|
||||||
|
layout.prop(self, 'set_blend_mode')
|
||||||
|
# layout.prop(self, 'clear_unused_view_layers')
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
if self.all_objects:
|
||||||
|
pool = [o for o in context.scene.objects if o.type == 'GPENCIL']
|
||||||
|
else:
|
||||||
|
pool = [o for o in context.selected_objects if o.type == 'GPENCIL']
|
||||||
|
# pool = [context.object]
|
||||||
|
|
||||||
|
changes = []
|
||||||
|
for ob in pool:
|
||||||
|
changes.append(f'>> {ob.name}')
|
||||||
|
layers = ob.data.layers
|
||||||
|
for l in layers:
|
||||||
|
used = False
|
||||||
|
|
||||||
|
## mask check
|
||||||
|
# if l.mask_layers:
|
||||||
|
# print(f'-> masks')
|
||||||
|
# state = '' if l.use_mask_layer else ' (disabled)'
|
||||||
|
# print(f'{ob.name} > {l.info}{state}:')
|
||||||
|
# used = True
|
||||||
|
# for ml in l.mask_layers:
|
||||||
|
# mlstate = ' (disabled)' if ml.hide else ''
|
||||||
|
# mlinvert = ' <>' if ml.invert else ''
|
||||||
|
# print(f'{ml.info}{mlstate}{mlinvert}')
|
||||||
|
|
||||||
|
if l.opacity != 1:
|
||||||
|
|
||||||
|
full_opacity_state = '' if self.set_full_opacity else ' (check only)'
|
||||||
|
mess = f'{l.info} : opacity {l.opacity:.2f} >> 1.0{full_opacity_state}'
|
||||||
|
print(mess)
|
||||||
|
changes.append(mess)
|
||||||
|
if self.set_full_opacity:
|
||||||
|
l.opacity = 1.0
|
||||||
|
used = True
|
||||||
|
|
||||||
|
if l.use_lights:
|
||||||
|
|
||||||
|
use_lights_state = '' if self.set_use_lights else ' (check only)'
|
||||||
|
mess = f'{l.info} : disable use lights{use_lights_state}'
|
||||||
|
print(mess)
|
||||||
|
changes.append(mess)
|
||||||
|
if self.set_use_lights:
|
||||||
|
l.use_lights = False
|
||||||
|
used = True
|
||||||
|
|
||||||
|
if l.blend_mode != 'REGULAR':
|
||||||
|
blend_mode_state = '' if self.set_blend_mode else ' (check only)'
|
||||||
|
mess = f'{l.info} : blend mode "{l.blend_mode}" >> regular{blend_mode_state}'
|
||||||
|
print(mess)
|
||||||
|
changes.append(mess)
|
||||||
|
if self.set_blend_mode:
|
||||||
|
l.blend_mode = 'REGULAR'
|
||||||
|
used = True
|
||||||
|
|
||||||
|
if used:
|
||||||
|
print()
|
||||||
|
if changes:
|
||||||
|
changes.append('')
|
||||||
|
|
||||||
|
fn.show_message_box(_message=changes, _title="Layers Check Report", _icon='INFO')
|
||||||
|
|
||||||
|
# render = bpy.data.scenes.get('Render')
|
||||||
|
# if not render:
|
||||||
|
# print('SKIP, no Render scene')
|
||||||
|
# return {"CANCELLED"}
|
||||||
|
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
classes=(
|
||||||
|
GPEXP_OT_layers_state,
|
||||||
|
)
|
||||||
|
|
||||||
|
def register():
|
||||||
|
for cls in classes:
|
||||||
|
bpy.utils.register_class(cls)
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
for cls in reversed(classes):
|
||||||
|
bpy.utils.unregister_class(cls)
|
|
@ -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, 2, 6),
|
"version": (0, 2, 7),
|
||||||
"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_number_outputs
|
from . import OP_number_outputs
|
||||||
from . import OP_scene_switch
|
from . import OP_scene_switch
|
||||||
|
# from . import OP_check_layer_status
|
||||||
|
from . import OP_setup_layers
|
||||||
from . import ui
|
from . import ui
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
@ -34,6 +36,8 @@ def register():
|
||||||
OP_manage_outputs.register()
|
OP_manage_outputs.register()
|
||||||
OP_number_outputs.register()
|
OP_number_outputs.register()
|
||||||
OP_scene_switch.register()
|
OP_scene_switch.register()
|
||||||
|
# OP_check_layer_status.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)
|
||||||
|
|
||||||
|
@ -42,6 +46,8 @@ def unregister():
|
||||||
return
|
return
|
||||||
|
|
||||||
ui.unregister()
|
ui.unregister()
|
||||||
|
OP_setup_layers.unregister()
|
||||||
|
# OP_check_layer_status.unregister()
|
||||||
OP_scene_switch.unregister()
|
OP_scene_switch.unregister()
|
||||||
OP_number_outputs.unregister()
|
OP_number_outputs.unregister()
|
||||||
OP_manage_outputs.unregister()
|
OP_manage_outputs.unregister()
|
||||||
|
|
14
fn.py
14
fn.py
|
@ -521,3 +521,17 @@ def renumber_keep_existing(fo, offset=10):
|
||||||
# first check if it has a number (if not bas)
|
# first check if it has a number (if not bas)
|
||||||
prev = fs
|
prev = fs
|
||||||
ct += offset
|
ct += offset
|
||||||
|
|
||||||
|
|
||||||
|
## confirm pop-up message:
|
||||||
|
def show_message_box(_message = "", _title = "Message Box", _icon = 'INFO'):
|
||||||
|
def draw(self, context):
|
||||||
|
for l in _message:
|
||||||
|
if isinstance(l, str):
|
||||||
|
self.layout.label(text=l)
|
||||||
|
else:
|
||||||
|
self.layout.label(text=l[0], icon=l[1])
|
||||||
|
|
||||||
|
if isinstance(_message, str):
|
||||||
|
_message = [_message]
|
||||||
|
bpy.context.window_manager.popup_menu(draw, title = _title, icon = _icon)
|
9
ui.py
9
ui.py
|
@ -67,7 +67,6 @@ class GPEXP_PT_gp_node_ui(Panel):
|
||||||
col.operator('gp.clear_render_tree', icon='X', text='Clear Framed Nodes')
|
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.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'
|
||||||
|
|
||||||
|
@ -112,12 +111,20 @@ class GPEXP_PT_gp_dopesheet_ui(Panel):
|
||||||
|
|
||||||
## all and objects
|
## all and objects
|
||||||
layout.separator()
|
layout.separator()
|
||||||
|
|
||||||
layout.label(text='Whole objects:')
|
layout.label(text='Whole objects:')
|
||||||
if context.scene.name != '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'
|
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=txt).mode='SELECTED'
|
||||||
layout.operator('gp.add_object_to_render', icon='RENDERLAYERS', text='All Visible GP To Render').mode='ALL'
|
layout.operator('gp.add_object_to_render', icon='RENDERLAYERS', text='All Visible GP To Render').mode='ALL'
|
||||||
|
|
||||||
|
layout.separator()
|
||||||
|
|
||||||
|
layout.operator('gp.layers_state', icon='CHECKMARK', text='Check layers')
|
||||||
|
|
||||||
|
# row = layout.row()
|
||||||
|
layout.prop(bpy.context.preferences.edit, 'use_anim_channel_group_colors')
|
||||||
|
|
||||||
|
|
||||||
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