Check file visibility conflicts check
1.7.2 - added: `Object visibility conflict` in file check - print in console when object have render activated but not viewport (& vice-versa) - Standalone ops "List Object Visibility Conflicts" (`gp.list_object_visibility`) - added: `GP Modifier visibility conflict` in file check. - print in console when gp modifiers have render activated but not viewport (& vice-versa) - Standalone ops "List GP Modifiers Visibility Conflicts" (`gp.list_modifier_visibility`) - code: show_message_box utils can now receive operator in sublist (if 3 element)gpv2
parent
b62a23858c
commit
4c6bd20b60
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -1,5 +1,15 @@
|
|||
# Changelog
|
||||
|
||||
1.7.2
|
||||
|
||||
- added: `Object visibility conflict` in file check
|
||||
- print in console when object have render activated but not viewport (& vice-versa)
|
||||
- Standalone ops "List Object Visibility Conflicts" (`gp.list_object_visibility`)
|
||||
- added: `GP Modifier visibility conflict` in file check.
|
||||
- print in console when gp modifiers have render activated but not viewport (& vice-versa)
|
||||
- Standalone ops "List GP Modifiers Visibility Conflicts" (`gp.list_modifier_visibility`)
|
||||
- code: show_message_box utils can now receive operator in sublist (if 3 element)
|
||||
|
||||
1.7.1
|
||||
|
||||
- feat: Improved `Create Empty Frames` operator with mutliple filters to choose source layers
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
import bpy
|
||||
import os
|
||||
from pathlib import Path
|
||||
from .utils import show_message_box, get_addon_prefs
|
||||
from . import utils
|
||||
|
||||
class GPTB_OT_file_checker(bpy.types.Operator):
|
||||
bl_idname = "gp.file_checker"
|
||||
bl_label = "File check"
|
||||
bl_label = "Check File"
|
||||
bl_description = "Check / correct some aspect of the file, properties and such and report"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
# @classmethod
|
||||
# def poll(cls, context):
|
||||
# return context.region_data.view_perspective == 'CAMERA'
|
||||
|
||||
## list of action :
|
||||
# Lock main cam:
|
||||
|
@ -23,16 +19,19 @@ class GPTB_OT_file_checker(bpy.types.Operator):
|
|||
# GP use additive drawing (else creating a frame in dopesheet makes it blank...)
|
||||
# GP stroke placement/projection check
|
||||
# Disabled animation
|
||||
# Object visibility conflict
|
||||
# GP modifiers visibility conflict
|
||||
# Set onion skin filter to 'All type'
|
||||
# Set filepath type
|
||||
# Set Lock object mode state
|
||||
|
||||
def invoke(self, context, event):
|
||||
# need some self-control (I had to...)
|
||||
self.ctrl = event.ctrl
|
||||
return self.execute(context)
|
||||
|
||||
def execute(self, context):
|
||||
prefs = get_addon_prefs()
|
||||
prefs = utils.get_addon_prefs()
|
||||
fix = prefs.fixprops
|
||||
problems = []
|
||||
|
||||
|
@ -128,7 +127,37 @@ class GPTB_OT_file_checker(bpy.types.Operator):
|
|||
fcu_ct += 1
|
||||
print(f"muted: {act.name} > {fcu.data_path}")
|
||||
if fcu_ct:
|
||||
problems.append(f'{fcu_ct} anim channel disabled (details -> console)')
|
||||
problems.append(f'{fcu_ct} anim channel disabled (details in console)')
|
||||
|
||||
## Object visibility conflict
|
||||
if fix.list_obj_vis_conflict:
|
||||
viz_ct = 0
|
||||
for o in context.scene.objects:
|
||||
if o.hide_viewport != o.hide_render:
|
||||
vp = 'No' if o.hide_viewport else 'Yes'
|
||||
rd = 'No' if o.hide_render else 'Yes'
|
||||
viz_ct += 1
|
||||
print(f'{o.name} : viewport {vp} != render {rd}')
|
||||
if viz_ct:
|
||||
## warn only : problems.append(f'{viz_ct} objects visibility conflicts (details in console)')
|
||||
problems.append(['gp.list_object_visibility', f'{viz_ct} objects visibility conflicts (details in console)', 'OBJECT_DATAMODE'])
|
||||
|
||||
## GP modifiers visibility conflict
|
||||
if fix.list_gp_mod_vis_conflict:
|
||||
mod_viz_ct = 0
|
||||
for o in context.scene.objects:
|
||||
if o.type != 'GPENCIL':
|
||||
continue
|
||||
for m in o.grease_pencil_modifiers:
|
||||
if m.show_viewport != m.show_render:
|
||||
vp = 'Yes' if m.show_viewport else 'No'
|
||||
rd = 'Yes' if m.show_render else 'No'
|
||||
mod_viz_ct += 1
|
||||
print(f'{o.name} - modifier {m.name}: viewport {vp} != render {rd}')
|
||||
if mod_viz_ct:
|
||||
## warn only : problems.append(f'{mod_viz_ct} visibility conflicts in Gp object modifiers (details in console)')
|
||||
problems.append(['gp.list_modifier_visibility', f'{mod_viz_ct} visibility conflicts in Gp object modifiers (details in console)', 'MODIFIER_DATA'])
|
||||
|
||||
|
||||
## Use median point
|
||||
if fix.set_pivot_median_point:
|
||||
|
@ -205,47 +234,12 @@ class GPTB_OT_file_checker(bpy.types.Operator):
|
|||
|
||||
# Show in viewport
|
||||
title = "Changed Settings" if apply else "Checked Settings (dry run, nothing changed)"
|
||||
show_message_box(problems, _title = title, _icon = 'INFO')
|
||||
utils.show_message_box(problems, _title = title, _icon = 'INFO')
|
||||
else:
|
||||
self.report({'INFO'}, 'All good')
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
""" OLD links checker with show_message_box
|
||||
class GPTB_OT_links_checker(bpy.types.Operator):
|
||||
bl_idname = "gp.links_checker"
|
||||
bl_label = "Links check"
|
||||
bl_description = "Check states of file direct links"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
def execute(self, context):
|
||||
all_lnks = []
|
||||
has_broken_link = False
|
||||
## check for broken links
|
||||
for current, lib in zip(bpy.utils.blend_paths(local=True), bpy.utils.blend_paths(absolute=True, local=True)):
|
||||
lfp = Path(lib)
|
||||
realib = Path(current)
|
||||
if not lfp.exists():
|
||||
has_broken_link = True
|
||||
all_lnks.append( (f"Broken link: {realib.as_posix()}", 'LIBRARY_DATA_BROKEN') )#lfp.as_posix()
|
||||
else:
|
||||
if realib.as_posix().startswith('//'):
|
||||
all_lnks.append( (f"Link: {realib.as_posix()}", 'LINKED') )#lfp.as_posix()
|
||||
else:
|
||||
all_lnks.append( (f"Link: {realib.as_posix()}", 'LIBRARY_DATA_INDIRECT') )#lfp.as_posix()
|
||||
|
||||
all_lnks.sort(key=lambda x: x[1], reverse=True)
|
||||
if all_lnks:
|
||||
print('===File check===')
|
||||
for p in all_lnks:
|
||||
if isinstance(p, str):
|
||||
print(p)
|
||||
else:
|
||||
print(p[0])
|
||||
# Show in viewport
|
||||
show_message_box(all_lnks, _title = "Links", _icon = 'INFO')
|
||||
return {"FINISHED"} """
|
||||
|
||||
|
||||
class GPTB_OT_links_checker(bpy.types.Operator):
|
||||
bl_idname = "gp.links_checker"
|
||||
|
@ -332,6 +326,144 @@ class GPTB_OT_links_checker(bpy.types.Operator):
|
|||
self.proj = None
|
||||
return context.window_manager.invoke_props_dialog(self, width=800)
|
||||
|
||||
""" OLD links checker with show_message_box
|
||||
class GPTB_OT_links_checker(bpy.types.Operator):
|
||||
bl_idname = "gp.links_checker"
|
||||
bl_label = "Links check"
|
||||
bl_description = "Check states of file direct links"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
def execute(self, context):
|
||||
all_lnks = []
|
||||
has_broken_link = False
|
||||
## check for broken links
|
||||
for current, lib in zip(bpy.utils.blend_paths(local=True), bpy.utils.blend_paths(absolute=True, local=True)):
|
||||
lfp = Path(lib)
|
||||
realib = Path(current)
|
||||
if not lfp.exists():
|
||||
has_broken_link = True
|
||||
all_lnks.append( (f"Broken link: {realib.as_posix()}", 'LIBRARY_DATA_BROKEN') )#lfp.as_posix()
|
||||
else:
|
||||
if realib.as_posix().startswith('//'):
|
||||
all_lnks.append( (f"Link: {realib.as_posix()}", 'LINKED') )#lfp.as_posix()
|
||||
else:
|
||||
all_lnks.append( (f"Link: {realib.as_posix()}", 'LIBRARY_DATA_INDIRECT') )#lfp.as_posix()
|
||||
|
||||
all_lnks.sort(key=lambda x: x[1], reverse=True)
|
||||
if all_lnks:
|
||||
print('===File check===')
|
||||
for p in all_lnks:
|
||||
if isinstance(p, str):
|
||||
print(p)
|
||||
else:
|
||||
print(p[0])
|
||||
# Show in viewport
|
||||
utils.show_message_box(all_lnks, _title = "Links", _icon = 'INFO')
|
||||
return {"FINISHED"} """
|
||||
|
||||
|
||||
class GPTB_OT_list_object_visibility(bpy.types.Operator):
|
||||
bl_idname = "gp.list_object_visibility"
|
||||
bl_label = "List Object Visibility Conflicts"
|
||||
bl_description = "List objects visibility conflicts, when viewport and render have different values"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
self.ob_list = [o for o in context.scene.objects if o.hide_viewport != o.hide_render]
|
||||
return context.window_manager.invoke_props_dialog(self, width=250)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
for o in self.ob_list:
|
||||
row = layout.row()
|
||||
row.label(text=o.name)
|
||||
row.prop(o, 'hide_viewport', text='', emboss=False) # invert_checkbox=True
|
||||
row.prop(o, 'hide_render', text='', emboss=False) # invert_checkbox=True
|
||||
|
||||
def execute(self, context):
|
||||
return {'FINISHED'}
|
||||
## basic listing as message box # all in invoke now
|
||||
# li = []
|
||||
# viz_ct = 0
|
||||
# for o in context.scene.objects:
|
||||
# if o.hide_viewport != o.hide_render:
|
||||
# vp = 'No' if o.hide_viewport else 'Yes'
|
||||
# rd = 'No' if o.hide_render else 'Yes'
|
||||
# viz_ct += 1
|
||||
# li.append(f'{o.name} : viewport {vp} != render {rd}')
|
||||
# if li:
|
||||
# utils.show_message_box(_message=li, _title=f'{viz_ct} visibility conflicts found')
|
||||
# else:
|
||||
# self.report({'INFO'}, f"No Object visibility conflict on current scene")
|
||||
# return {'FINISHED'}
|
||||
|
||||
|
||||
## not exposed in UI, Check is performed in Check file (can be called in popped menu)
|
||||
class GPTB_OT_list_modifier_visibility(bpy.types.Operator):
|
||||
bl_idname = "gp.list_modifier_visibility"
|
||||
bl_label = "List GP Modifiers Visibility Conflicts"
|
||||
bl_description = "List Modifier visibility conflicts, when viewport and render have different values"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
self.ob_list = []
|
||||
for o in context.scene.objects:
|
||||
if o.type != 'GPENCIL':
|
||||
continue
|
||||
if not len(o.grease_pencil_modifiers):
|
||||
continue
|
||||
|
||||
mods = []
|
||||
for m in o.grease_pencil_modifiers:
|
||||
if m.show_viewport != m.show_render:
|
||||
if not mods:
|
||||
self.ob_list.append([o, mods])
|
||||
mods.append(m)
|
||||
return context.window_manager.invoke_props_dialog(self, width=250)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
for o in self.ob_list:
|
||||
layout.label(text=o[0].name, icon='OUTLINER_OB_GREASEPENCIL')
|
||||
for m in o[1]:
|
||||
row = layout.row()
|
||||
row.label(text='')
|
||||
row.label(text=m.name, icon='MODIFIER_ON')
|
||||
row.prop(m, 'show_viewport', text='', emboss=False) # invert_checkbox=True
|
||||
row.prop(m, 'show_render', text='', emboss=False) # invert_checkbox=True
|
||||
|
||||
def execute(self, context):
|
||||
return {'FINISHED'}
|
||||
## basic listing as message box # all in invoke now
|
||||
# li = []
|
||||
# oblist = []
|
||||
# if self.selection:
|
||||
# pool = context.selected_objects
|
||||
# else:
|
||||
# pool = context.scene.objects
|
||||
|
||||
# for o in pool:
|
||||
# if o.type != 'GPENCIL':
|
||||
# continue
|
||||
# for m in o.grease_pencil_modifiers:
|
||||
# if m.show_viewport != m.show_render:
|
||||
# if o not in oblist:
|
||||
# oblist.append(o)
|
||||
# li.append(o.name) # just name first time to list mods after
|
||||
|
||||
# vp = 1 if m.show_viewport else 0
|
||||
# rd = 1 if m.show_render else 0
|
||||
|
||||
# mess = f' - modifier {m.name}: viewport {vp} != render {rd}'
|
||||
# # mess = f'{o.name} - modifier {m.name}: viewport {vp} != render {rd}'
|
||||
# li.append(mess)
|
||||
# if li:
|
||||
# utils.show_message_box(li)
|
||||
# else:
|
||||
# self.report({'INFO'}, f"No Gp modifier visibility conflict on {'selection' if self.selection else 'scene'}")
|
||||
# return {'FINISHED'}
|
||||
|
||||
|
||||
'''### OLD
|
||||
class GPTB_OT_check_scene(bpy.types.Operator):
|
||||
bl_idname = "gp.scene_check"
|
||||
|
@ -367,6 +499,8 @@ class GPTB_OT_check_scene(bpy.types.Operator):
|
|||
|
||||
classes = (
|
||||
# GPTB_OT_check_scene,
|
||||
GPTB_OT_list_object_visibility,
|
||||
GPTB_OT_list_modifier_visibility,
|
||||
GPTB_OT_file_checker,
|
||||
GPTB_OT_links_checker,
|
||||
)
|
||||
|
|
|
@ -351,7 +351,7 @@ class GPTB_OT_toggle_mute_animation(bpy.types.Operator):
|
|||
|
||||
class GPTB_OT_list_disabled_anims(bpy.types.Operator):
|
||||
bl_idname = "gp.list_disabled_anims"
|
||||
bl_label = "List disabled anims"
|
||||
bl_label = "List Disabled Anims"
|
||||
bl_description = "List disabled animations channels in scene. (shit+clic to list only on seleciton)"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ bl_info = {
|
|||
"name": "GP toolbox",
|
||||
"description": "Set of tools for Grease Pencil in animation production",
|
||||
"author": "Samuel Bernou, Christophe Seux",
|
||||
"version": (1, 7, 1),
|
||||
"version": (1, 7, 2),
|
||||
"blender": (2, 91, 0),
|
||||
"location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
|
||||
"warning": "",
|
||||
|
@ -465,6 +465,8 @@ class GPTB_prefs(bpy.types.AddonPreferences):
|
|||
col.prop(self.fixprops, 'set_pivot_median_point')
|
||||
col.prop(self.fixprops, 'disable_guide')
|
||||
col.prop(self.fixprops, 'list_disabled_anim')
|
||||
col.prop(self.fixprops, 'list_obj_vis_conflict')
|
||||
col.prop(self.fixprops, 'list_gp_mod_vis_conflict')
|
||||
col.prop(self.fixprops, 'autokey_add_n_replace')
|
||||
#-# col.prop(self.fixprops, 'set_cursor_type')
|
||||
col.prop(self.fixprops, "select_active_tool", icon='RESTRICT_SELECT_OFF')
|
||||
|
|
|
@ -84,6 +84,16 @@ class GP_PG_FixSettings(bpy.types.PropertyGroup):
|
|||
name="List Disabled Animation",
|
||||
description="Alert if there are disabled animations",
|
||||
default=True, options={'HIDDEN'})
|
||||
|
||||
list_obj_vis_conflict : BoolProperty(
|
||||
name="List Object Visibility Conflicts",
|
||||
description="Alert if some objects have different hide viewport and hide render values",
|
||||
default=True, options={'HIDDEN'})
|
||||
|
||||
list_gp_mod_vis_conflict : BoolProperty(
|
||||
name="List GP Object Modifiers Visibility Conflicts",
|
||||
description="Alert if some GP modifier have different show viewport and show render values",
|
||||
default=True, options={'HIDDEN'})
|
||||
|
||||
autokey_add_n_replace : BoolProperty(
|
||||
name="Autokey Mode Add and Replace",
|
||||
|
|
19
utils.py
19
utils.py
|
@ -715,12 +715,29 @@ def convert_attr(Attr):
|
|||
|
||||
## confirm pop-up message:
|
||||
def show_message_box(_message = "", _title = "Message Box", _icon = 'INFO'):
|
||||
'''Show message box with element passed as string or list
|
||||
if _message if a list of lists:
|
||||
if sublist have 2 element:
|
||||
considered a label [text,icon]
|
||||
if sublist have 3 element:
|
||||
considered as an operator [ops_id_name, text, icon]
|
||||
'''
|
||||
|
||||
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 len(l) == 2: # label with icon
|
||||
self.layout.label(text=l[0], icon=l[1])
|
||||
elif len(l) == 3: # ops
|
||||
self.layout.operator_context = "INVOKE_DEFAULT"
|
||||
self.layout.operator(l[0], text=l[1], icon=l[2], emboss=False) # <- highligh the entry
|
||||
|
||||
## offset pnale when using row...
|
||||
# row = self.layout.row()
|
||||
# row.label(text=l[1])
|
||||
# row.operator(l[0], icon=l[2])
|
||||
|
||||
if isinstance(_message, str):
|
||||
_message = [_message]
|
||||
|
|
Loading…
Reference in New Issue