Create your first Blender add-on

2»

Comments

  • @Coen you can use the update function to run once a change has been made. See https://docs.blender.org/api/current/bpy.props.html#update-example

    Coen
  • edited December 2021

    it is common to, instead of defining the properties in the UI, define properties as a separate PropertyGroup. This property group is, when installing the add-on, registered on a certain namespace (for example the 'scene'), so you can access it globally. So for you that could be:

    from bpy.props import BoolProperty, StringProperty, IntProperty, EnumProperty
    from bpy.types import PropertyGroup
    
    class ExcelProperties(PropertyGroup):
        ifc_product: BoolProperty(name="IfcProduct", default=False)
        ifc_building_story: BoolProperty(name="IfcBuildingStory", default=False)
        name: BoolProperty(name="Name", default=False)
        excel_path: stringProperty(name="Excel path", subtype='FILE_PATH')
    

    Afterwards you register the property in some namespace:

    def register():
        bpy.types.Scene.excel_properties = bpy.props.PointerProperty(type=ExcelProperties)
    

    Now, in the UI or in the Operator, you can access the properties in the execute/draw functions:

    UI:

    def draw(self, context):
        excel_properties = context.scene.excel_properties
        row = layout.row(align=True)
        row.prop(excel_properties, "ifc_product")
    

    Operator:

    def execute(self, context):
        excel_properties = context.scene.excel_properties
        if excel_properties.ifc_product:
            do_something()
    

    It's quite nice because you can separate the properties from the ui and from the functions. BlenderBIM does this nicely (I use this too for my own add-ons, it might also be the standard structure, I don't know), by making the following structure for each package:
    package_name:

    • ui.py
    • prop.py
    • operator.py
    • __init__.py (for registering all the classes from the three python files.

    You can for example look at the GIS package in the BlenderBIM add-on: https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.7.0/src/blenderbim/blenderbim/bim/module/gis (the other packages are built the same way but more extensive so this is a simple example)

    GorgiousCoenMassimo
  • @LaurensJN
    @vpajic

    Thanks for the help.
    I use this method now, in the BlenderBIMXLSXPanel in the draw method put a row and colums for the ui

    class BlenderBIMXLSXPanel(bpy.types.Panel):
        """Creates a Panel in the Object properties window"""
        bl_label = "BlenderBIM .xlsx"
        bl_idname = "OBJECT_PT_blenderbiMxlsxpanel"  # this is not strictly necessary
        bl_space_type = "VIEW_3D"
        bl_region_type = "UI"
        bl_category = "Tools"
    
        def draw(self, context):
    
            scene = context.scene
            layout = self.layout
            col = layout.column(align=True)
            row = col.row(align=True)
    
    
    
            col.prop(scene, "my_ifcproduct")
    
    

    then in register

    def register():
    
    
        bpy.types.Scene.my_ifcproduct = bpy.props.BoolProperty(name="IfcProduct",description="Export IfcProduct",default = True)
    
    

    then in the WritetoXLSX class I can call the checkbox.

    if context.scene.my_ifcproduct == True:
                ifc_dictionary['IfcProduct'] = ifc_product_type_list
    

    I think I need to group some of them, start to get a bit crowdy. And I hardcoded the sum formulas in the header, they don't work anymore. Because the colums move when the user decides to check and uncheck some of the exports needed. Need to find a method for this.

  • I like this layout, any suggestions for a good intuive UI are very welcome. GUI is not my strong suit.

  • My two cents, @Coen i think last ui is nice, with the possibility of hiding the checkboxes of the same group

    Coen
  • edited December 2021

    You can create sub-panels :

    See the last part of that answer : https://blender.stackexchange.com/a/155517/86891 or the very minimal amount of code there : https://wiki.blender.org/wiki/Reference/Release_Notes/2.80/Python_API/UI_API#Sub_Panels

    note you can add a class attribute bl_order = 0/1/2/3 etc if you want to force the ordering of the sub-panels. see https://docs.blender.org/api/current/bpy.types.Panel.html#bpy.types.Panel.bl_order

    And use
    bl_options = {'DEFAULT_CLOSED'} for the sub panels to be folded by default

    You can try to add layout.prop(scene, "my_prop", toggle=True) if it's a boolean to display as a toggle rather than a checkbox. Matter of taste https://blender.stackexchange.com/a/117791/86891

    Coen
  • How do you bundle a Blender BIM add-on in a zip if the add-on has third party python dependencies?

  • Hmm I've actually never done that. Theoretically it should be as easy as copy / pasting the third party module and all its dependencies in a folder in the zip, and then access it like you would any other module you created in the addon folder. Blenderbim does that in libs/site/packages

    Coen
  • These are the dependencies as where they are stored:

    openpyxl 3.0.9 C:\Program Files\Blender Foundation\Blender 3.0\3.0\python\lib\openpyxl\__init__.py
    pandas 1.3.5 C:\Program Files\Blender Foundation\Blender 3.0\3.0\python\lib\pandas\__init__.py
    xlsxwriter 3.0.2 C:\Program Files\Blender Foundation\Blender 3.0\3.0\python\lib\xlsxwriter\__init__.py
    

    I found this SO post that there are numerous ways of importing dependencies.

    I copied pasted the modules openpyxl, pandas and xlsxwriter to a new relative folder
    BlenderBIMOpenOfficeXML\lib\site\packages

    Now I started reading that thread on Stack Overflow.

    and I got completely lost...

  • edited January 7

    You should be able to use from BlenderBIMOpenOfficeXML.lib.site.packages import openpyxl.
    Note python modules should be named in lower case, and I think it's not mandatory but you can use snake_case like you would regular python modules.

    Coen
  • I have never done that either, but the BlenderBIM add-on does that with a great deal of packages:
    See https://github.com/IfcOpenShell/IfcOpenShell/blob/v0.7.0/src/blenderbim/blenderbim/init.py
    If you open any BlenderBIM add-on folder, you see all packages can be found under /libs/site/packages. Therefore this line probably does the trick:

    import site
    site.addsitedir(os.path.join(os.path.dirname(os.path.realpath(__file__)), "libs", "site", "packages"))
    

    If I am wrong, probably @Moult can explain this better :)

    MeetlatCoen
  • edited January 7

    I used the method @LaurensJN described.
    I added this to my script

    import site
    site.addsitedir(os.path.join(os.path.dirname(os.path.realpath(__file__)), "libs", "site", "packages"))
    

    Then copy pasted the modules from the python site-packages to my own folder called with the following folder struture libs>sites>packages ( I have a vague memory of reading this somewhere in Blender documentation too)
    I placed the openpyxl, pandas and xlsxwriter modules in there
    did a clean install of Blender 3.0 and BlenderBIM on my old brick laptop.

    validated where the imports were coming from with [module_name_here].__file__ to see where they are located.
    And it works! :-D
    They are now placed in

    C:\Users\C.C.J. Claus\AppData\Roaming\Blender Foundation\Blender\3.0\scripts\addons\libs\site\packages\openpyxl\__init__.py
    C:\Users\C.C.J. Claus\AppData\Roaming\Blender Foundation\Blender\3.0\scripts\addons\libs\site\packages\pandas\__init__.py
    C:\Users\C.C.J. Claus\AppData\Roaming\Blender Foundation\Blender\3.0\scripts\addons\blenderbim\libs\site\packages\xlsxwriter\__init__.py
    

    When I try to install the add-on Linux Ubuntu I get a specific pandas error. Going to look at that another time.

    LaurensJNGorgious
Sign In or Register to comment.