1
$\begingroup$

I have a panel setup to do a whole bunch of stuff for a laptop model. I want it to have a system where you can add/remove a 'controller' as you would background images. I have the UI setup with the add controller button and a remove button, with all the content inside a box. How can I set this up to add a new box with all the content when the add button is pressed, and remove one when the remove button is pressed, the same way the background image system works?

Here's what I've got:

enter image description here

Here a small section of my code, I think it's all that should be needed:

class IgnitProperties(bpy.types.PropertyGroup):
    user_items = CollectionProperty(
        type = UserItems
    )


class UserItems(bpy.types.PropertyGroup):
    user_str = bpy.props.StringProperty()
    user_int = bpy.props.IntProperty()



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

    def execute(self, context):
        item = bpy.context.scene.user_items.add()
        item.user_int = 5
        item.user_str = 'custom value'
        return{'FINISHED'}

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):
        context.scene.user_items.remove(self.del_item)
        return{'FINISHED'}

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)
        layout.operator("macbook_controller.add_macbook")

        # Box
        box = layout.box()
        row = box.row(align=True)

        # Collapsable Menu
        collapse = scene.ignit_panel.collapse

        if collapse == True:
            row.prop(scene.ignit_panel, "collapse",
                icon="TRIA_DOWN",
                icon_only=True, emboss=False
            )
        else:
            row.prop(scene.ignit_panel, "collapse",
            icon="TRIA_RIGHT",
            icon_only=True, emboss=False
        )

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

        # Remove
        row.operator("macbook_controler.remove_macbook", text="", icon = "X", emboss = False)

        # Collapsing everything inside the box
        if collapse == True:
        # Main Features
            row = box.row(align=True)
            row.label(text = "Main Features:")

            row = box.row(align=True)
            row.prop(scene.ignit_panel, "isight_camera_indicator")

            row = box.row(align=True)
            row.prop(scene.ignit_panel, "menubar_and_dock")

            row = box.row(align=True)
            row.prop(scene.ignit_panel, "backlit_keys")

            row = box.row(align=True)
            row.prop(scene.ignit_panel, "screen_brightness")

            row = box.row(align=True)
            row.prop(scene.ignit_panel, "dirt_and_dust_factor")

            # Screen Icons
            row = box.row(align=True)
            row.label(text = "Screen Icons:")

            row = box.row(align=True)
            row.prop(scene.ignit_panel, "screen_icons", text = "Screen Icon Brightness")

            row = box.row(align=True)
            row.prop(scene.ignit_panel, "icons", expand = True)

            icons = scene.ignit_panel.icons

            row = box.row(align=True)
            if icons == 'Brightness':
                row.prop(scene.ignit_panel, "icon_factor", text = "Brightness Icon")
            elif icons == 'Backlit Keys':
                row.prop(scene.ignit_panel, "icon_factor", text = "Backlit Keys Icon")
            elif icons == 'Volume':
                row.prop(scene.ignit_panel, "icon_factor", text = "Volume Icon")

            # Screen Rotation
            row = box.row(align=True)
            row.label(text = "Screen Rotation:")
            row = box.row(align=True)
            row.prop(scene.ignit_panel, "screen_rotation")

            # Screen Texture
            row = box.row(align=True)
            row.label(text = "Screen Texture:")

            row = box.row(align=True)
            row.prop(scene.ignit_panel, "screen_path")
            row.operator("macbook_controller.identifier_file_selector", text="", icon='FILESEL')

            # MacBook Colors
            row = box.row(align=True)
            row.label(text = "MacBook Color:")

            row = box.row(align=True)
            row.prop(scene.ignit_panel, "colors", expand = True)

            for idx, item in enumerate(scene.ignit_panel.user_items):
                    row = col.row()
                    row.prop(item,'user_str')
                    row.operator(UserDelOptions.bl_idname, text='',
                                icon='X').del_item = idx
                    row = col.row()
                    row.prop(item,'user_int')



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

def unregister():
    bpy.utils.unregister__module(__name__)
    del bpy.types.Scene.ignit_panel
$\endgroup$
  • $\begingroup$ Pretty unclear to me what you are looking to accomplish. Some images would help explain your intention. $\endgroup$ – hawkenfox Jan 1 '16 at 6:33
  • $\begingroup$ Ok, I've added an image of what I've got. Basically, I want it to make a new box (everything inside the grey box, underneath the 'Add MacBook' button) when the 'Add MacBook' button is pressed. Then I want that panel to be removed when the 'X' is pressed. $\endgroup$ – mr-matt Jan 1 '16 at 8:39
1
$\begingroup$

You can test any condition to choose whether various properties are displayed. You can add as many custom bpy.props.BoolProperty items as you need to keep track of any options you want to track.

A bpy.props.CollectionProperty can be used to hold the list of user added items, then you loop through them to display each one and use two operators to add and delete items from the collection.

import bpy

class UserItems(bpy.types.PropertyGroup):
    user_str = bpy.props.StringProperty()
    user_int = bpy.props.IntProperty()

class UserAddOptions(bpy.types.Operator):
    """Add a user item"""
    bl_idname = "object.add_user_items"
    bl_label = "Add custom user items"

    def execute(self, context):
        item = bpy.context.scene.user_items.add()
        item.user_int = 5
        item.user_str = 'custom value'
        return{'FINISHED'}

class UserDelOptions(bpy.types.Operator):
    """remove a user item"""
    bl_idname = "object.del_user_item"
    bl_label = "Remove a custom user item"

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

    def execute(self, context):
        context.scene.user_items.remove(self.del_item)
        return{'FINISHED'}

class OptionsPanel(bpy.types.Panel):
    """testing panel in the 3dview properties region"""
    bl_label = 'Optional data Panel'
    bl_idname = 'OBJECT_PT_options'
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_context = 'object'

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

        col = layout.column()
        row = col.row()
        row.prop(scn, 'option01')
        row = col.row()
        row.prop(scn, 'option02')

        box = col.box()
        col = box.column()
        row = col.row()
        if scn.show_my_options:
            row.prop(scn, "show_my_options", icon="DOWNARROW_HLT", text="", emboss=False)
        else:
            row.prop(scn, "show_my_options", icon="RIGHTARROW", text="", emboss=False)

        row.label('My options here')

        if scn.show_my_options:
            row = col.row()
            col = row.column(align=True)
            col.prop(scn.render, 'resolution_x', text='X')
            col.prop(scn.render, 'resolution_y', text='Y')
            if scn.option01:
                row = col.row()
                row.label('extra options go here')
                row = col.row()
                row.label('and more rows for other data')

            if scn.option02:
                row = col.row()
                row.label('dynamic options go here')
                row = col.row()
                row.operator(UserAddOptions.bl_idname)
                for idx, item in enumerate(scn.user_items):
                    row = col.row()
                    row.prop(item,'user_str')
                    row.operator(UserDelOptions.bl_idname, text='',
                                icon='X').del_item = idx
                    row = col.row()
                    row.prop(item,'user_int')

def register():
    bpy.utils.register_module(__name__)
    bpy.types.Scene.show_my_options = bpy.props.BoolProperty(name='Show Custom Props', default=False)
    bpy.types.Scene.option01 = bpy.props.BoolProperty(name='First options', default=False)
    bpy.types.Scene.option02 = bpy.props.BoolProperty(name='Dynamic options', default=False)
    bpy.types.Scene.user_items = bpy.props.CollectionProperty(type=UserItems)

def unregister():
    del bpy.types.Scene.show_my_options
    del bpy.types.Scene.option01
    del bpy.types.Scene.option02
    del bpy.types.Scene.user_items
    bpy.utils.unregister_module(__name__)
$\endgroup$
  • $\begingroup$ Just testing out your code, where does is it actually putting the menu/panel? $\endgroup$ – mr-matt Jan 1 '16 at 22:22
  • $\begingroup$ The properties region of the 3dview - press N $\endgroup$ – sambler Jan 2 '16 at 7:27
  • $\begingroup$ Its not showing up... $\endgroup$ – mr-matt Jan 2 '16 at 10:07
  • $\begingroup$ Could you take a look at my code? I'm getting errors, it's saying that UserItems is not defined.. $\endgroup$ – mr-matt Jan 3 '16 at 23:22
  • 1
    $\begingroup$ I think this is getting close to what you want. $\endgroup$ – sambler Jan 4 '16 at 3:59

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.