2022-01-26 16:32:33 +01:00
|
|
|
import bpy, re
|
2021-09-22 18:35:52 +02:00
|
|
|
from . import fn
|
|
|
|
|
2022-01-26 16:32:33 +01:00
|
|
|
def check_broken_modifier_target(pool=None, reports=None):
|
|
|
|
if not reports:
|
|
|
|
reports = []
|
|
|
|
if not pool:
|
|
|
|
pool = [o for o in bpy.context.scene.objects if o.type == 'GPENCIL']
|
|
|
|
|
|
|
|
for o in pool:
|
|
|
|
lay_name_list = [l.info for l in o.data.layers]
|
|
|
|
for m in o.grease_pencil_modifiers:
|
|
|
|
if not hasattr(m, 'layer'):
|
|
|
|
continue
|
2023-06-07 11:59:26 +02:00
|
|
|
if not m.layer:
|
|
|
|
continue
|
2022-01-26 16:32:33 +01:00
|
|
|
if not m.layer in lay_name_list:
|
|
|
|
reports.append(f'Broken modifier target :{o.name} > {m.name} > {m.layer}')
|
|
|
|
# else:
|
|
|
|
# print(f'Modifier target :{o.name} > {m.name} > ok')
|
|
|
|
|
|
|
|
return reports
|
|
|
|
|
|
|
|
def check_layer_state(pool=None, reports=None):
|
|
|
|
if not reports:
|
|
|
|
reports = []
|
|
|
|
if not pool:
|
|
|
|
pool = [o for o in bpy.context.scene.objects if o.type == 'GPENCIL']
|
|
|
|
for ob in pool:
|
|
|
|
layers = ob.data.layers
|
|
|
|
for l in layers:
|
|
|
|
# if l.mask_layers:
|
|
|
|
# if not any(not x.hide for x in l.mask_layers):
|
|
|
|
# # all masks disable
|
|
|
|
# pass
|
|
|
|
|
2023-01-18 14:28:27 +01:00
|
|
|
## just list masks
|
|
|
|
# state = '' if l.use_mask_layer else ' (disabled)'
|
2022-01-26 16:32:33 +01:00
|
|
|
# reports.append(f'{ob.name} > {l.info} masks{state}:')
|
|
|
|
# for ml in l.mask_layers:
|
|
|
|
# mlstate = ' (disabled)' if ml.hide else ''
|
|
|
|
# mlinvert = ' <>' if ml.invert else ''
|
|
|
|
# reports.append(f' - {ml.name}{mlstate}{mlinvert}')
|
|
|
|
|
2022-01-27 18:08:24 +01:00
|
|
|
if l.opacity != 1 and not l.info.startswith('MA_'):
|
2022-01-26 16:32:33 +01:00
|
|
|
reports.append(f'{ob.name} > {l.info} > opacity {l.opacity}')
|
|
|
|
|
|
|
|
# if l.use_lights:
|
|
|
|
# reports.append(f'-> use lights !')
|
|
|
|
|
|
|
|
if l.blend_mode != 'REGULAR':
|
|
|
|
reports.append(f'{ob.name} > {l.info} > blend mode "{l.blend_mode}" !')
|
|
|
|
|
|
|
|
return reports
|
|
|
|
|
|
|
|
def check_file_output_numbering(reports=None):
|
|
|
|
if not reports:
|
|
|
|
reports = []
|
|
|
|
prenum = re.compile(r'\d{3}_')
|
|
|
|
file_outs = []
|
|
|
|
for S in bpy.data.scenes:
|
|
|
|
if S.name == 'Scene' or not S.node_tree or not S.use_nodes:
|
|
|
|
continue
|
|
|
|
file_outs += [n for n in S.node_tree.nodes if n.type == 'OUTPUT_FILE']
|
2023-01-18 14:28:27 +01:00
|
|
|
|
2022-01-26 16:32:33 +01:00
|
|
|
if not file_outs:
|
|
|
|
reports.append('No file output nodes found')
|
|
|
|
return reports
|
|
|
|
|
|
|
|
for fo in file_outs:
|
|
|
|
if not prenum.match(fo.base_path.split('/')[-1]):
|
|
|
|
reports.append(f'No object numbering : node {fo.name}')
|
|
|
|
pct = 0
|
2024-04-16 18:01:10 +02:00
|
|
|
if fo.format.file_format == 'OPEN_EXR_MULTILAYER':
|
|
|
|
## multilayer use layer_slots > slot.name
|
|
|
|
slots = fo.layer_slots
|
|
|
|
for fs in slots:
|
|
|
|
if not prenum.match(fs.name.split('/')[0]):
|
|
|
|
pct += 1
|
|
|
|
else:
|
|
|
|
## classic use file_slots > path
|
|
|
|
slots = fo.file_slots
|
|
|
|
for fs in slots:
|
|
|
|
if not prenum.match(fs.path.split('/')[0]):
|
|
|
|
pct += 1
|
|
|
|
|
2022-01-26 16:32:33 +01:00
|
|
|
if pct:
|
2024-02-22 17:29:41 +01:00
|
|
|
reports.append(f'{pct}/{len(slots)} slots not numbered: node {fo.name}')
|
2022-01-26 16:32:33 +01:00
|
|
|
|
|
|
|
return reports
|
2021-09-22 18:35:52 +02:00
|
|
|
class GPEXP_OT_check_render_scene(bpy.types.Operator):
|
|
|
|
bl_idname = "gp.check_render_scene"
|
|
|
|
bl_label = "Check render scene"
|
|
|
|
bl_description = "Auto check render scene"
|
|
|
|
bl_options = {"REGISTER"} # , "UNDO"
|
|
|
|
|
2023-01-18 14:28:27 +01:00
|
|
|
# clear_unused_view_layers : bpy.props.BoolProperty(name="Clear unused view layers",
|
2021-09-22 18:35:52 +02:00
|
|
|
# description="Delete view layer that aren't used in the nodetree anymore",
|
|
|
|
# default=True)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def poll(cls, context):
|
|
|
|
return True
|
|
|
|
|
|
|
|
def invoke(self, context, event):
|
|
|
|
return self.execute(context)
|
2024-04-16 18:01:10 +02:00
|
|
|
# return context.window_manager.invoke_props_dialog(self)
|
2021-09-22 18:35:52 +02:00
|
|
|
|
2024-04-16 18:01:10 +02:00
|
|
|
# def draw(self, context):
|
|
|
|
# layout = self.layout
|
|
|
|
# # layout.prop(self, 'clear_unused_view_layers')
|
2021-09-22 18:35:52 +02:00
|
|
|
|
2023-01-18 14:28:27 +01:00
|
|
|
def execute(self, context):
|
2022-01-26 16:32:33 +01:00
|
|
|
reports = []
|
|
|
|
# check gp modifiers
|
|
|
|
broken_mods = check_broken_modifier_target()
|
|
|
|
if broken_mods:
|
|
|
|
reports.append('GP modifiers targets:')
|
|
|
|
reports += broken_mods
|
|
|
|
|
2023-01-18 14:28:27 +01:00
|
|
|
# check layers
|
2022-01-26 16:32:33 +01:00
|
|
|
layer_state = check_layer_state()
|
|
|
|
if layer_state:
|
|
|
|
if reports: reports.append('')
|
|
|
|
reports.append('Layers State:')
|
|
|
|
reports += layer_state
|
|
|
|
|
|
|
|
# check file output numbering
|
|
|
|
numbering_problems = check_file_output_numbering()
|
|
|
|
if numbering_problems:
|
|
|
|
if reports: reports.append('')
|
|
|
|
reports.append('File output numbering:')
|
|
|
|
reports += numbering_problems
|
|
|
|
|
|
|
|
if not reports:
|
|
|
|
self.report({'INFO'}, 'All OK !')
|
2022-01-27 18:08:24 +01:00
|
|
|
reports.append('Everything Ok !')
|
2021-09-22 18:35:52 +02:00
|
|
|
|
2022-01-27 18:08:24 +01:00
|
|
|
if hasattr(bpy.types, 'GP_OT_file_checker'):
|
|
|
|
# propose to run toolbox checker if exists
|
|
|
|
reports.append(['gp.file_checker', 'Run GP_toolbox File Checker', 'SCENE_DATA'])
|
|
|
|
|
|
|
|
fn.show_message_box(_message=reports, _title='Potential Problems list')
|
2022-01-26 16:32:33 +01:00
|
|
|
return {"FINISHED"}
|
2021-09-22 18:35:52 +02:00
|
|
|
|
|
|
|
classes=(
|
|
|
|
GPEXP_OT_check_render_scene,
|
|
|
|
)
|
|
|
|
|
2023-01-18 14:28:27 +01:00
|
|
|
def register():
|
2021-09-22 18:35:52 +02:00
|
|
|
for cls in classes:
|
|
|
|
bpy.utils.register_class(cls)
|
|
|
|
|
|
|
|
def unregister():
|
|
|
|
for cls in reversed(classes):
|
|
|
|
bpy.utils.unregister_class(cls)
|