0
$\begingroup$

is there a way to have an equivalent of a list/tuple as a scene property?
something similar to c++ like "array< classname >* object list"

the operator i'm working with hides any object that is not within user selection, one issue is consistency between what's hidden and what's revealed, without a reference to the previously hidden objects sometimes everything gets hidden stopping the operator from being able to reveal anything

a list within the operator is not possible as all the tests i've done end up with a "referenced before assignment" error and CollectionProperty() can't be used either as i it stops me from writing to any property within it (read only)

the code i'm stuck on, the commented out section is alternatives that are less reliable
Addon code here for reference: Release is out of date v0.5.0 stage 4 is the latest

class Alx_OT_Scene_VisibilityIsolator(bpy.types.Operator):
    """"""

    bl_label = ""
    bl_idname = "alx.operator_scene_visibility_isolator"
    bl_options = {"INTERNAL"}

    TargetVisibility : bpy.props.BoolProperty(name="", default=False, options={"HIDDEN"})
    UseObject : bpy.props.BoolProperty(name="", default=False, options={"HIDDEN"})
    UseCollection : bpy.props.BoolProperty(name="", default=False, options={"HIDDEN"})

    @classmethod
    def poll(self, context):
        return context.area.type == "VIEW_3D"

    def execute(self, context):
        if (len(context.scene.alx_addon_properties.SceneIsolatorVisibilityTarget) != 0):
            TargetType = set(Target for Target in context.scene.alx_addon_properties.SceneIsolatorVisibilityTarget)
            TemporaryList = set(Object for Object in context.scene.objects if ((Object is not None) and (len(context.selected_objects) != 0) and (Object not in context.selected_objects)))

            if (len(TemporaryList) != 0):
                SafeList = TemporaryList

                if (len(TemporaryList) == 0):
                    for Object in SafeList:
                        if (Object is not None):
                            if ("VIEWPORT" in TargetType):
                                Object.hide_viewport = not self.TargetVisibility
                            if ("RENDER" in TargetType):
                                Object.hide_render = not self.TargetVisibility

                if (len(TemporaryList) != 0):
                    for Object in TemporaryList:
                        if (Object is not None):
                            if ("VIEWPORT" in TargetType):
                                Object.hide_viewport = not self.TargetVisibility
                            if ("RENDER" in TargetType):
                                Object.hide_render = not self.TargetVisibility


        return {"FINISHED"}

what i did for CollectionProperty
the PropertyGroup definition:

class AlxIsolatorObject(bpy.types.PropertyGroup):
    IsolatorObjectName : bpy.props.StringProperty(name="", default="", options={"HIDDEN"})

alternative register with the same IsolatorObject class (which gives the read only error)

class AlxAddonProperties(bpy.types.PropertyGroup):
    """"""
    
    SceneIsolatorVisibilityTarget : bpy.props.EnumProperty(name="SceneIsolatorVisibilityTarget", options={'ENUM_FLAG'}, items=[("VIEWPORT", "Viewport", "", 1), ("RENDER", "Render", "", 2)])
    SceneIsolatorVisibilityList : bpy.props.CollectionProperty(type=AlxPreferences.AlxIsolatorObject)

registered with this inside the register() function, it fails to create the property as the property group fails to register even tho it's in the correct order:

bpy.types.Scene.alx_scene_isolator_visibility_list = bpy.props.CollectionProperty(type=AlxIsolatorObject)
$\endgroup$
3
  • $\begingroup$ You can use collection property $\endgroup$
    – Crantisz
    Dec 28, 2023 at 18:59
  • $\begingroup$ Collection property is the way to go, what you describe is you trying to modify the pointer which is indeed not possible, I am sure you can do what you want by using the collection property in the way it is intended, would you mind posting the things you tried with collection property that resulted in this error message ? $\endgroup$
    – Gorgious
    Dec 29, 2023 at 8:29
  • $\begingroup$ reguarding collection properties, i'm aware of the read only pointers, the weird thing is having it gives the same error with strings, i hope it's not due to the fact it's multifile addon, the read only is sparked from the scene pointer to a property group i will update the post with everything i've tried with collection props $\endgroup$
    – ValyArhal
    Dec 29, 2023 at 18:46

1 Answer 1

0
$\begingroup$

Collection Properties were not the way to go at all, i need to be able to access indexes but due to the fact CollectionProperties are created as a set by default, it made me unable to access indexes

Here is how is solved this issue, good practice or not it gave me the exact results i needed with no errors or side-effects

How i defined the Scene property

i simply put this in the register function

bpy.types.Scene.alx_scene_isolator_visibility_list = []

How i handled the operator

class Alx_OT_Scene_VisibilityIsolator(bpy.types.Operator):
    """"""

    bl_label = ""
    bl_idname = "alx.operator_scene_visibility_isolator"
    bl_options = {"INTERNAL"}

    TargetVisibility : bpy.props.BoolProperty(name="", default=False, options={"HIDDEN"})
    UseObject : bpy.props.BoolProperty(name="", default=False, options={"HIDDEN"})
    UseCollection : bpy.props.BoolProperty(name="", default=False, options={"HIDDEN"})

    @classmethod
    def poll(self, context):
        return context.area.type == "VIEW_3D"

    def execute(self, context):
        if (len(context.scene.alx_addon_properties.SceneIsolatorVisibilityTarget) != 0):
            TargetType = set(Target for Target in context.scene.alx_addon_properties.SceneIsolatorVisibilityTarget)
            IsolatorSelectionSet = [Object for Object in context.scene.objects if ((Object is not None) and (len(context.selected_objects) != 0) and (Object not in context.selected_objects))]

            try:
                IsolatorSelectionSet[0]
                bpy.types.Scene.alx_scene_isolator_visibility_list = IsolatorSelectionSet
                for Object in IsolatorSelectionSet:
                    if (Object is not None):
                        if ("VIEWPORT" in TargetType):
                            Object.hide_viewport = not self.TargetVisibility
                        if ("RENDER" in TargetType):
                            Object.hide_render = not self.TargetVisibility
            except:
                try:
                    context.scene.alx_scene_isolator_visibility_list[0]
                    for Object in context.scene.alx_scene_isolator_visibility_list:
                        if (Object is not None):
                            if ("VIEWPORT" in TargetType):
                                Object.hide_viewport = not self.TargetVisibility
                            if ("RENDER" in TargetType):
                                Object.hide_render = not self.TargetVisibility
                except:
                    pass

the reason i needed something similar to arrays is indexes to shorten how much time sanity checks take, running len() every 2 lines was causing severe freezes the higher the number of objects in the scene regardless of poly-count, i only needed to know whether it has at least one object not the whole length

a scene with 200 objects was taking a whole 5-10 seconds to recover from a freeze which CollectionProperties would have only worsened as i would need to access and do a context.scene.objects.get(objectnamefromcollection) for every item in that scene property

having a try: except: that attempts to access index 0 is going to be faster and not be affected by the length of the list from my understanding as whether that list has 500 object or 10, accessing a index takes the same speed at the same depth
don't quote me on that, i found that from testing and might be completely wrong

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .