I asked a similar question quite a while ago but I'm still having trouble with this. For those that didn't see my last question, basically I want to replicate what the background image system does, or at least the panel. I want to have an add button and an X button, and when the add button is pressed by the user, a section is added to the panel and that can be done as many times as the user is willing to click it. Then added to each one of those sections is the X button, and when that X button is clicked, it removes that section, just like the background images. I have this code so far, I've only added the parts of that should concern:

class IgnitProperties(bpy.types.PropertyGroup):

    collapse = BoolProperty(
        name = "Collapse",
        description = "Allows the MacBook Controller to be collapsable",
        default = True,
        update = lambda self, context: common_update(self, context, 'collapse')

class AddMacBook(bpy.types.Operator):
    bl_label = "Add MacBook"
    bl_idname = "macbook_controller.add_macbook"

    def execute(self, context):
        item = context.scene.ignit_panel.add()
        def unique_name(names):
            # from wm.py
            prop = "MacBook"
            prop_new = prop
            i = 1
            while prop_new in names:
                prop_new = prop + str(i)
                i += 1

            return prop_new
        item.title = unique_name([i.title for i in context.scene.ignit_panel])

class RemoveMacBook(bpy.types.Operator):
    bl_label = "Remove MacBook"
    bl_idname = "macbook_controler.remove_macbook"

    del_item = bpy.props.IntProperty(name='item index to remove')

    def execute(self, context):

class IGLayoutDemoPanel(bpy.types.Panel):
    """Creates a Panel in the scene context of the properties editor"""
    bl_label = "MacBook Controller"
    bl_idname = "macbook_controller.macbook_controller"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

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

        scene = context.scene
        split = layout.split()
        scene = context.scene
        camera = scene.camera.data
        obj = context.object

        # Add
        row = layout.row(align=True)

        for idx,ignit_options in enumerate(scene.ignit_panel):
            # Box
            box = layout.box()
            row = box.row()

        # Collapsable Menu
        collapse = scene.ignit_panel.collapse

        if collapse == True:
            row.prop(scene.ignit_panel, "collapse",
                icon_only=True, emboss=False
            row.prop(scene.ignit_panel, "collapse",
            icon_only=True, emboss=False

        # Title (per object)
        row.label(text = "MacBook")

        row.operator("macbook_controler.remove_macbook", text="", icon = "X", emboss = False).del_item = idx

        # Collapsing everything inside the box
        if not ignit_options.collapse:
            #This is the section that I want to be drawn every time the add button is clicked

def register():
    bpy.types.Scene.ignit_panel = bpy.props.PointerProperty(type=IgnitProperties)

def unregister():
    del bpy.types.Scene.ignit_panel

if __name__ == "__main__":

No errors in the console at first, but as soon as I try to click one of those buttons, it tells me this:

Traceback (most recent call last):
File "/Users....../macbook_controller.py", line 1202 in execute
AttributeError: 'IgnitProperties' object has no attribute 'add'
  • 1
    $\begingroup$ in the register func it should be bpy.types.Scene.ignit_panel = bpy.props.CollectionProperty() so you can call add() ( it has to be collection prop not a pointer ) $\endgroup$
    – Chebhou
    Jan 7, 2016 at 21:04
  • $\begingroup$ Ok, thanks, I now have another error, I added that to my description, but the good news is that I see my box appearing as expected, there's just nothing in it. $\endgroup$
    – mr-matt
    Jan 7, 2016 at 21:07
  • $\begingroup$ as it says IgnitProperties type has only a boolean variable, there is no title inside IgnitProperties, you can add a stringPropety inside if you want and call it title $\endgroup$
    – Chebhou
    Jan 7, 2016 at 21:15
  • $\begingroup$ Well if I comment that part out it doesn't give errors, but the boxes are still empty, I'll add an image to the description. $\endgroup$
    – mr-matt
    Jan 7, 2016 at 21:18
  • $\begingroup$ this collapse = ignit_options.collapse should be this collapse = ignit_options.collapse and change it to this row.prop(ignit_options, .......) or this row.prop(ignit_options.collapse, .......) I can't test on my current system now sorry $\endgroup$
    – Chebhou
    Jan 7, 2016 at 21:25

1 Answer 1


Ok so there were a whole lot of small errors that contributed to fixing this. Here were the steps required to fix it.

1) Change bpy.types.Scene.ignit_panel = bpy.props.PointerProperty(type=IgnitProperties) to bpy.types.Scene.ignit_panel = bpy.props.CollectionProperty(type=IgnitProperties) (PointerProperty to CollectionProperty)

2) All of the scene.ignit_panel in the draw function had to be changed to ignit_options

3) The last for loop had to be removed (this was not actually shown in the code above, but it was after if not ignit_options.collapse:)

4) The collapsible menu if statement had to be moved into the for loop just above it


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.