import bpy from bpy.types import Operator from .. import fn from .simplify_conflicts import list_simplify_affected_objects from .visibility_conflicts import get_viewlayer_collections_with_visiblity_conflict ## WIP : checker operator to perform all check at once (sometimes a limited version of the check) to expose useful solving operators. # region Scene check class RT_OT_scene_checker(Operator): bl_idname = "rt.scene_checker" bl_label = "Check Scene For Render Issues" bl_description = "Check / correct some aspect of the scene and objects, properties, etc. and report" bl_options = {"REGISTER"} ## checkes and possible actions calls : # list_object_visibility_conflicts # list_modifier_visibility # list_collection_visibility_conflicts # list_object_affected_by_simplify # apply_fixes : bpy.props.BoolProperty(name="Apply Fixes", default=False, # description="Apply possible fixes instead of just listing (pop the list again in fix mode)", # options={'SKIP_SAVE'}) def invoke(self, context, event): self.ctrl = event.ctrl return self.execute(context) def execute(self, context): problems = [] print('-- Scene Checks --') ## Old method : Apply fixes based on pref (inverted by ctrl key) # # If Ctrl is pressed, invert behavior (invert boolean) # apply ^= self.ctrl # apply = self.apply_fixes # if self.ctrl: # apply = True ## Object visibility conflict viz_ct = 0 for o in context.scene.objects: if not (o.hide_get() == o.hide_viewport == o.hide_render): hv = 'No' if o.hide_get() else 'Yes' vp = 'No' if o.hide_viewport else 'Yes' rd = 'No' if o.hide_render else 'Yes' viz_ct += 1 print(f'{o.name} : viewlayer {hv} - viewport {vp} - render {rd}') if viz_ct: problems.append(['rt.list_object_visibility_conflicts', f'{viz_ct} objects visibility conflicts', 'OBJECT_DATAMODE']) ## GP modifiers visibility conflict mod_viz_ct = 0 for o in context.scene.objects: for m in o.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: problems.append(['rt.list_modifier_visibility', f'{mod_viz_ct} modifiers visibility conflicts', 'MODIFIER_DATA']) ## Collection if conflicts := get_viewlayer_collections_with_visiblity_conflict(context): print('\nCollection visibility conflicts:') for vc in conflicts: vl = 'Yes' if vc.hide_viewport else 'No' vp = 'Yes' if vc.collection.hide_viewport else 'No' rd = 'Yes' if vc.collection.hide_render else 'No' print(f'{vc.name}: viewlayer {vl} - viewport {vp} - render {rd}') problems.append(['rt.list_collection_visibility_conflicts', f'{len(conflicts)} collections visibility conflicts', 'GROUP']) ## Simplify affected object if context.scene.render.use_simplify and (conflicts := list_simplify_affected_objects(context)): print('\nSimplify affected objects:') # Conflict list model : [[obj, [{type: "SUBSURF", ..}, {..}], icon], ..] for item_l in conflicts: print(f'{item_l[0].name} : {[m.get("type", "issue") for m in item_l[1]]}') problems.append(['rt.list_object_affected_by_simplify', f'{len(conflicts)} objects affected by simplify', 'MOD_SIMPLIFY']) #### --- print fix/problems report if problems: print('===File check===') ## List checks # for p in problems: # if isinstance(p, str): # print(p) # else: # print(p[0]) # if not self.apply_fixes: # ## button to call the operator again with apply_fixes set to True # problems.append(['OPERATOR', 'gp.file_checker', 'Apply Fixes', 'FORWARD', {'apply_fixes': True}]) # Show in viewport # title = "Changed Settings" if apply else "Checked Settings (nothing changed)" title = "Visibility checks report (details in console)" fn.show_message_box(problems, _title = title, _icon = 'INFO') else: self.report({'INFO'}, 'All good') return {'FINISHED'} # endregion def register(): bpy.utils.register_class(RT_OT_scene_checker) def unregister(): bpy.utils.unregister_class(RT_OT_scene_checker)