0

When you select couple of objects in the viewport and click on New Selection Set the uilist gets populated and clicking on the Hide from Render icon, the objects get hidden from render but the icon in the uilist stays the same and there is my roadblock.

I have been reading about how to do it, but sadly the lack of tutorials or guides or examples on how to do in on a uilist is almost non-existant. I was checking the topic How to create a custom UI? but there is no a section related to uilist matters, maybe that section could be updated with that as well?

enter image description here

import bpy
import bpy_extras
import os
import collections
import json
import random
import copy
from bpy.types import (Operator,
                       Panel,
                       PropertyGroup,
                       IntProperty,
                       CollectionProperty,
                       BoolProperty,
                       UIList)

from bpy.props import (StringProperty, BoolProperty, IntProperty, FloatProperty, FloatVectorProperty, EnumProperty, PointerProperty, CollectionProperty, BoolVectorProperty, )

def select_current_selset(self, context): r"""Selection""" if len(context.scene.sj_sel_set_items) is 0: return None

index = int(self.selection_set_dplist)
obj_list = json.loads(
    context.scene.sj_sel_set_items[self.index].object_list,
    object_pairs_hook=collections.OrderedDict)

if len(obj_list) is 0:
    return None

bpy.ops.object.select_all(action='DESELECT')
for obj in obj_list:
    if bpy.context.scene.objects.get(obj):
        bpy.data.objects[obj].select_set(True)

if bpy.context.scene.objects.get(obj_list[0]):
    context.view_layer.objects.active = bpy.data.objects[obj_list[0]]
return None


def get_selection_list_items(scene, context): r"""Get a list of selection sets""" items = [] for i, item in enumerate(context.scene.sj_sel_set_items, 0): items.append((str(i), item.set_name, ''))

if len(items) is 0:
    items.append(('0', 'Selection Set Empty.', ''))

return items


def get_sel_set_item_name(self): return self["set_name"]

def set_sel_set_item_name(self, value): self["set_name"] = value current_names = [i.set_name for i in bpy.context.scene.sj_sel_set_items] current_names.remove(value) new_name = value cnt = 1 while new_name in current_names: new_name = '{}.{:03d}'.format(new_name.split('.')[0], cnt) cnt = cnt + 1 self["set_name"] = new_name return None

class SJSelectionSetAddItem(bpy.types.Operator): r"""Add new selection set""" bl_idname = "sj_selection_set.add_selset" bl_label = "" bl_description = "Add new Selection Set from selected objects" bl_options = {'REGISTER', 'UNDO'}

@classmethod
def poll(cls, context):
    r""""""
    return True

def execute(self, context):
    r""""""
    if len(bpy.context.selected_objects) is 0:
        msg = 'Please Select any object.'
        def draw(self, context):
            self.layout.label(text=msg)
        bpy.context.window_manager.popup_menu(draw, title="Info", icon="INFO")
        self.report({'INFO'}, msg)
        return {'FINISHED'}
    new_item = context.scene.sj_sel_set_items.add()

    current_names = [i.set_name for i in context.scene.sj_sel_set_items]
    new_name = 'SelectionSet'
    cnt = 1
    while new_name in current_names:
        new_name = 'SelectionSet.{:03d}'.format(cnt)
        cnt = cnt + 1
    new_item.set_name = new_name

    index = len(context.scene.sj_sel_set_items) - 1
    context.scene.sj_sel_set_item_index = index
    context.scene.sj_sel_set_props.selection_set_dplist = str(index)

    obj_list = [obj.name for obj in bpy.context.selected_objects]
    new_item.object_list = json.dumps(obj_list)

    get_selection_list_items(self, context)
    bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
    return {'FINISHED'}


class SJSelectionSetRender(bpy.types.Operator): r"""Select objects in selected set""" bl_idname = "sj_selection_set.render" bl_label = "" bl_description = "Select objects in selected set" index: bpy.props.IntProperty(name="Objects in set", default=0)

@classmethod
def poll(cls, context):
    return context.scene.sj_sel_set_items


def execute(self, context):
    r""""""
    index = context.scene.sj_sel_set_item_index
    obj_list = json.loads(
        context.scene.sj_sel_set_items[self.index].object_list,
        object_pairs_hook=collections.OrderedDict)

    if len(obj_list) is 0:
        return {'FINISHED'}

    bpy.ops.object.select_all(action='DESELECT')

    for obj in obj_list:
        if bpy.context.scene.objects.get(obj):
            bpy.data.objects[obj].select_set(True)

    if context.scene.objects.get(obj_list[0]):
        context.view_layer.objects.active = bpy.data.objects[obj_list[0]]

    for objs in bpy.context.selected_objects:
        if objs.hide_render == True:
            objs.hide_render = False
        else:
            objs.hide_render = True     


    return {'FINISHED'}


class SJSelectionSetEditList(bpy.types.UIList): r"""""" def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): custom_icon = 'OBJECT_HIDDEN' ob = context.object

    if self.layout_type in {'DEFAULT', 'COMPACT'}:

        c = layout.column()
        row = c.row()
        split = row.split(factor=0.01)
        c = split.column()
        split = split.split()
        c = split.column()
        c.prop(item, "set_name", text="", emboss=False, icon=custom_icon)

        show = layout.row(align=True)
        show.scale_x = 1
        show.operator(SJSelectionSetRender.bl_idname, icon = "RESTRICT_RENDER_OFF").index = index

    elif self.layout_type in {'GRID'}:
        layout.alignment = 'CENTER'
        layout.label(text="", icon=custom_icon)


class SJSelectionSetListPanel(bpy.types.Panel): r"""UI""" bl_label = "Selection Set List" bl_space_type = "VIEW_3D" bl_region_type = "UI" bl_context = "objectmode" bl_category = "Selection Set" bl_options = {'DEFAULT_CLOSED'}

def draw(self, context):
    layout = self.layout

    sjss = context.scene.sj_sel_set_props
    scn = context.scene
    ob = context.object

    row = layout.row()
    sub_row = row.row(align=True)
    sub_row.operator("sj_selection_set.add_selset", text="New Selection Set")
    layout.separator(factor=0.5)

    row = layout.row()
    row.template_list("SJSelectionSetEditList", "Sel Set List", context.scene, "sj_sel_set_items", context.scene, "sj_sel_set_item_index", rows=1)

    if len(context.scene.sj_sel_set_items) is 0:
        return None


classes = ( SJSelectionSetEditList, SJSelectionSetAddItem, SJSelectionSetListPanel, SJSelectionSetRender, )

def register(): for cls in classes: bpy.utils.register_class(cls) bpy.types.Scene.sj_sel_set_item_index = bpy.props.IntProperty(name="Objects in set")

def unregister(): for cls in classes: bpy.utils.unregister_class(cls) del bpy.types.Scene.sj_sel_set_props del bpy.types.Object.action_list_index del bpy.types.Scene.my_test bpy.types.VIEW3D_HT_tool_header.remove(SJSelectionSetPanel.draw)

if name == "main": register()

Duarte Farrajota Ramos
  • 59,425
  • 39
  • 130
  • 187
pekkuskär
  • 307
  • 2
  • 11
  • Hello, the question is a bit too broad for this site but the culprit is on that line : show.operator(SJSelectionSetRender.bl_idname, icon = "RESTRICT_RENDER_OFF").index = index since it's an operator and not a direct reference to an item's attribute you may want for instance to change the icon depending on the show_render state of the first object in the set. icon="RESTRICT_RENDER_ON" if context.scene.sj_sel_set_items[0].hide_render else "RESTRICT_RENDER_OFF" or something like that – Gorgious Nov 16 '21 at 08:19
  • Also, it seems unnecessary to select objects before disabling or enabling rendering, you don't need to do that. And you can invert render state with obj.hide_render = not obj.hide_render instead of your if/else lines – Gorgious Nov 16 '21 at 08:23
  • Thank you, sadly I'm unable to make it work, when I add the line you suggested the console says: AttributeError: 'SJSelectionSetItem' object has no attribute 'hide_render' – pekkuskär Nov 16 '21 at 08:34
  • You need to access a blender object. try context.scene.sj_sel_set_items[0].object_list[0] idk since it's a bit convoluted and you didn't include the contents of sj_sel_set_items btw instead of json serialization you should use CollectionProperty to store multiple objects references. or reference by name since it's as reliable and less complicated ^^ – Gorgious Nov 16 '21 at 08:38
  • Thank you for your suggestion, regarding the CollectionProperty I will take a look :) I'm really puzzle on how hard can be to change and icon depending on its state in the uilist, I have read even some devs had to make their own draw method since the uilist is a pain.

    No matter what I try it refuses to work :(

    – pekkuskär Nov 16 '21 at 08:50

0 Answers0