From c87c29596ecfaef3cf18b25829f6c1e49ee3e266 Mon Sep 17 00:00:00 2001 From: pullusb Date: Tue, 22 Jul 2025 15:38:09 +0200 Subject: [PATCH] initial code for simplify conflict check --- operators/simplify_conflicts.py | 224 ++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 operators/simplify_conflicts.py diff --git a/operators/simplify_conflicts.py b/operators/simplify_conflicts.py new file mode 100644 index 0000000..0ab00a0 --- /dev/null +++ b/operators/simplify_conflicts.py @@ -0,0 +1,224 @@ +import bpy + +from bpy.types import Operator +from bpy.props import (BoolProperty, + EnumProperty, + PointerProperty, + CollectionProperty, + StringProperty) + +class RT_OT_list_object_affected_by_simplify(Operator): + bl_idname = "rt.list_object_affected_by_simplify" + bl_label = "List Objects Affected By Simplify" + bl_description = "List objects that are affected by the Simplify settings, either in viewport or render" + bl_options = {"REGISTER"} + + def invoke(self, context, event): + self.ob_list = [] + + # Get simplify settings + render = context.scene.render + simplify_viewport = render.simplify_subdivision + simplify_render = render.simplify_subdivision_render + max_child_particles = render.simplify_child_particles + volume_limit_resolution = render.simplify_volumes + + for obj in context.scene.objects: + affected_data = [] + + if hasattr(obj, 'modifiers'): + # Check subdivision surface modifiers + for modifier in obj.modifiers: + if modifier.type == 'SUBSURF': + viewport_limited = modifier.levels > simplify_viewport + render_limited = modifier.render_levels > simplify_render + + if viewport_limited or render_limited: + affected_data.append({ + 'type': 'SUBSURF', + 'modifier': modifier, + 'viewport_current': modifier.levels, + 'viewport_limited': min(modifier.levels, simplify_viewport), + 'render_current': modifier.render_levels, + 'render_limited': min(modifier.render_levels, simplify_render), + 'is_limited': viewport_limited or render_limited + }) + + # Check multires modifiers + if modifier.type == 'MULTIRES': + viewport_limited = modifier.levels > simplify_viewport + render_limited = modifier.render_levels > simplify_render + + if viewport_limited or render_limited: + affected_data.append({ + 'type': 'MULTIRES', + 'modifier': modifier, + 'viewport_current': modifier.levels, + 'viewport_limited': min(modifier.levels, simplify_viewport), + 'render_current': modifier.render_levels, + 'render_limited': min(modifier.render_levels, simplify_render), + 'is_limited': viewport_limited or render_limited + }) + + # # Check particle systems + if hasattr(obj, 'particle_systems') and len(obj.particle_systems) > 0 and max_child_particles < 1.0: + for psys in obj.particle_systems: + if psys.settings.type in ['EMITTER', 'HAIR']: + affected_data.append({ + 'type': 'PARTICLE', + 'particle_system': psys, + 'particle_type': psys.settings.type, + 'count': psys.settings.count + }) + + # Check materials for subsurface scattering and volumes + # material_affected = False + # if obj.material_slots: + # for slot in obj.material_slots: + # if slot.material and slot.material.node_tree: + # nodes = slot.material.node_tree.nodes + # for node in nodes: + # if node.type == 'BSDF_PRINCIPLED': + # if hasattr(node.inputs['Subsurface'], 'default_value'): + # if node.inputs['Subsurface'].default_value > 0: + # affected_data.append({ + # 'type': 'SUBSURFACE', + # 'material': slot.material, + # 'subsurface_value': node.inputs['Subsurface'].default_value + # }) + # material_affected = True + # break + # elif node.type == 'VOLUME_PRINCIPLED': + # affected_data.append({ + # 'type': 'VOLUME_MAT', + # 'material': slot.material + # }) + # material_affected = True + # break + # if material_affected: + # break + + # Check for volume objects + if obj.type == 'VOLUME' and volume_limit_resolution < 1.0: + affected_data.append({ + 'type': 'VOLUME_OBJ' + }) + + # If object has affected data, add it to the list + if affected_data: + self.ob_list.append([obj, affected_data, "OUTLINER_OB_" + obj.type]) + + # Sort by object type, then by name + self.ob_list.sort(key=lambda x: (x[2], x[0].name)) + + return context.window_manager.invoke_props_dialog(self, width=450) + + def draw(self, context): + layout = self.layout + render = context.scene.render + ## Show simplify settings + # layout.label(text="Simplify Settings:") + + layout.label(text="Viewport:") + bpy.types.RENDER_PT_simplify_viewport.draw(self, context) + + layout.label(text="Render:") + bpy.types.RENDER_PT_simplify_render.draw(self, context) + # row = box.row() + # row.label(text="Current Simplify Settings:", icon='SETTINGS') + + # col = box.column(align=True) + # row = col.row() + # # row.label(text=f"Enabled: {render.use_simplify}") + # row.prop(render, "use_simplify") # Enabled + # row = col.row() + # # row.label(text=f"Viewport Subdivision: {render.simplify_subdivision}") + # row.prop(render, "simplify_subdivision") # Viewport + # row = col.row() + # # row.label(text=f"Render Subdivision: {render.simplify_subdivision_render}") + # row.prop(render, "simplify_subdivision_render") # Render + + layout.separator() + + if not self.ob_list: + layout.label(text='No objects affected by Simplify settings', icon='CHECKMARK') + return + + col = layout.column(align=False) + + for ct, obj_data in enumerate(self.ob_list): + if ct > 0: + col.separator() + + obj, affected_data, icon = obj_data + + for i, data in enumerate(affected_data): + row = col.row() + + if i == 0: + # Show object name and icon for first item + op = row.operator('rt.select_object_by_name', text=obj.name, icon=icon, emboss=False) + op.object_name = obj.name + else: + # Subsequent rows, show empty space + row.label(text=' ', icon='BLANK1') + + # Show the specific affected feature + if data['type'] == 'SUBSURF': + mod = data['modifier'] + row.label(text=f"SubSurf: {mod.name}", icon='MOD_SUBSURF') + + # Show viewport levels + sub_row = row.row(align=True) + sub_row.label(text=f"V: {data['viewport_current']}→{data['viewport_limited']}") + + + # Show render levels + sub_row = row.row(align=True) + sub_row.label(text=f"R: {data['render_current']}→{data['render_limited']}") + + elif data['type'] == 'MULTIRES': + mod = data['modifier'] + row.label(text=f"Multires: {mod.name}", icon='MOD_MULTIRES') + + # Show viewport levels + sub_row = row.row(align=True) + sub_row.label(text=f"V: {data['viewport_current']}→{data['viewport_limited']}") + + # Show render levels + sub_row = row.row(align=True) + sub_row.label(text=f"R: {data['render_current']}→{data['render_limited']}") + + elif data['type'] == 'PARTICLE': + psys = data['particle_system'] + row.label(text=f"Particles: {psys.name}", icon='PARTICLES') + row.label(text=f"Type: {data['particle_type']}") + row.label(text=f"Count: {data['count']}") + + elif data['type'] == 'HAIR': + mod = data['modifier'] + row.label(text=f"Hair: {mod.name}", icon='HAIR') + row.label(text=f"Node Group: {data['node_group']}") + + elif data['type'] == 'SUBSURFACE': + mat = data['material'] + row.label(text=f"Material: {mat.name}", icon='MATERIAL') + row.label(text=f"Subsurface: {data['subsurface_value']:.3f}") + + elif data['type'] == 'VOLUME_MAT': + mat = data['material'] + row.label(text=f"Volume Material: {mat.name}", icon='MATERIAL') + + elif data['type'] == 'VOLUME_OBJ': + row.label(text="Volume Object", icon='VOLUME_DATA') + + def execute(self, context): + return {'FINISHED'} + + +def register(): + bpy.utils.register_class(RT_OT_list_object_affected_by_simplify) + + +def unregister(): + bpy.utils.unregister_class(RT_OT_list_object_affected_by_simplify)