import bpy from bpy.types import Operator from bpy.props import (BoolProperty, EnumProperty, PointerProperty, CollectionProperty, StringProperty) def list_simplify_affected_objects(context): """Return a list of object affected by simplify return : [[obj, [{type: "SUBSURF", ..}, {..}], icon], ..] """ ob_list = [] # Get simplify settings render = context.scene.render simplify_viewport = render.simplify_subdivision simplify_render = render.simplify_subdivision_render max_child_particles = min(render.simplify_child_particles, render.simplify_child_particles_render) 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: ob_list.append([obj, affected_data, "OUTLINER_OB_" + obj.type]) return ob_list 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 = [] self.ob_list = list_simplify_affected_objects(context) # 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 layout.use_property_decorate = False layout.use_property_split = True render = context.scene.render row = layout.row() row.prop(render, "use_simplify", text="Use Simplify") if not render.use_simplify: row.label(text="Simplify is Disabled", icon='INFO') # Get current simplify settings simplify_viewport = render.simplify_subdivision simplify_render = render.simplify_subdivision_render max_child_particles = min(render.simplify_child_particles, render.simplify_child_particles_render) volume_limit_resolution = render.simplify_volumes ## 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) 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): # Show the specific affected feature if data['type'] == 'SUBSURF': mod = data['modifier'] # Check if currently affected by simplify viewport_limited = mod.levels > simplify_viewport render_limited = mod.render_levels > simplify_render is_currently_affected = viewport_limited or render_limited # Modifier name row row = col.row() row.active = is_currently_affected 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') # Modifier name as operator + Viewport levels on same row op = row.operator('rt.select_object_by_name', text=mod.name, icon='MOD_SUBSURF', emboss=False) op.object_name = obj.name op.modifier_name = mod.name row.label(text="Viewport:") # Create subrow for viewport setting subrow = row.row() subrow.active = viewport_limited subrow.prop(mod, "levels", text="") # Render levels row (indented) row = col.row() row.active = is_currently_affected # Indent to match row.label(text=' ', icon='BLANK1') row.label(text=' ', icon='BLANK1') row.label(text="Render:") # Create subrow for render setting subrow = row.row() subrow.active = render_limited subrow.prop(mod, "render_levels", text="") elif data['type'] == 'MULTIRES': mod = data['modifier'] # Check if currently affected by simplify viewport_limited = mod.levels > simplify_viewport render_limited = mod.render_levels > simplify_render is_currently_affected = viewport_limited or render_limited # Modifier name row row = col.row() row.active = is_currently_affected 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') # Modifier name as operator + Viewport levels on same row op = row.operator('rt.select_object_by_name', text=mod.name, icon='MOD_MULTIRES', emboss=False) op.object_name = obj.name op.modifier_name = mod.name row.label(text="Viewport:") # Create subrow for viewport setting subrow = row.row() subrow.active = viewport_limited subrow.prop(mod, "levels", text="") # Render levels row (indented) row = col.row() row.active = is_currently_affected # Indent to match row.label(text=' ', icon='BLANK1') row.label(text=' ', icon='BLANK1') row.label(text="Render:") # Create subrow for render setting subrow = row.row() subrow.active = render_limited subrow.prop(mod, "render_levels", text="") elif data['type'] == 'PARTICLE': # Check if currently affected by simplify is_currently_affected = max_child_particles < 1.0 row = col.row() row.active = is_currently_affected 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') psys = data['particle_system'] # Create subrow for particle info subrow = row.row() subrow.label(text=f"Particles: {psys.name}", icon='PARTICLES') subrow.label(text=f"Type: {data['particle_type']}") subrow.label(text=f"Count: {data['count']}") elif data['type'] == 'HAIR': 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') mod = data['modifier'] # Create subrow for hair info subrow = row.row() subrow.label(text=f"Hair: {mod.name}", icon='HAIR') subrow.label(text=f"Node Group: {data['node_group']}") elif data['type'] == 'SUBSURFACE': 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') mat = data['material'] # Create subrow for material info subrow = row.row() subrow.label(text=f"Material: {mat.name}", icon='MATERIAL') subrow.label(text=f"Subsurface: {data['subsurface_value']:.3f}") elif data['type'] == 'VOLUME_MAT': 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') mat = data['material'] # Create subrow for volume material info subrow = row.row() subrow.label(text=f"Volume Material: {mat.name}", icon='MATERIAL') elif data['type'] == 'VOLUME_OBJ': # Check if currently affected by simplify is_currently_affected = volume_limit_resolution < 1.0 row = col.row() row.active = is_currently_affected 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') # Create subrow for volume object info subrow = row.row() subrow.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)