ArchipackObject

ArchipackObject base class provide functions to support “copy to selected” and easy access to datablock.

  • filter(o) : return boolean, ensure object contains your datablock eg : archipack_window.filter(o) may use it in poll

  • datablock(o) : return datablock or None, ensure object contains your datablock eg : d = archipack_window.datablock(o)

  • find_in_selection(context, auto_update=True) : store context and find current instance in selection. return object or None. Wont store context and always return None if auto_update is False

  • restore_context(context) : restore context - active + selection

Implementation

  • PropertyGroup MUST inherits from ArchipackObject

  • PropertyGroup MUST use archipack_ prefix and you MUST use the same name for bpy.types.Mesh.property

  • PropertyGroup MUST be registered as bpy.types.Mesh property to handle alt + d

Base object PropertyGroup

class archipack_door(ArchipackObject, Manipulable, PropertyGroup):
        ...
        def update(self, context):

                o = self.find_in_selection(context, self.auto_update)

                if o is None:
                        return

                # update object's mesh (see bmesh_utils as reference)
                bmed.buildmesh(context, o, self.verts, self.faces)

                # restore context
                self.resore_context(context)

Register module

def register():
   bpy.utils.register_class(archipack_door)
   Mesh.archipack_door = CollectionProperty(type=archipack_door)

Ui Panel

@classmethod
def poll(cls, context):
    return archipack_door.filter(context.active_object)

def draw(self, context):
    o = context.active_object
    if not archipack_door.filter(o):
        return
    layout = self.layout
    layout.operator('archipack.door_manipulate', icon='HAND')
    props = archipack_door.datablock(o)

Manipulate Operator

class ARCHIPACK_OT_door_manipulate(Operator):
        bl_idname = "archipack.door_manipulate"
        bl_label = "Manipulate"
        bl_description = "Manipulate"
        bl_options = {'REGISTER', 'UNDO'}

        @classmethod
        def poll(self, context):
                return archipack_door.filter(context.active_object)

        def invoke(self, context, event):
                d = archipack_door.datablock(context.active_object)
                d.manipulable_invoke(context)
                return {'FINISHED'}

Create Operator

class ARCHIPACK_OT_truss(ArchipackCreateTool, Operator):
        bl_idname = "archipack.truss"
        bl_label = "Truss"
        bl_description = "Create Truss"
        bl_category = 'Archipack'
        bl_options = {'REGISTER', 'UNDO'}

        def create(self, context):
                m = bpy.data.meshes.new("Truss")
                o = bpy.data.objects.new("Truss", m)

                # add propertyGroup to mesh
                d = m.archipack_truss.add()

                context.scene.objects.link(o)
                o.select = True
                context.scene.objects.active = o
                self.load_preset(d)
                self.add_material(o)
                m.auto_smooth_angle = 1.15
                return o

        def execute(self, context):
                if context.mode == "OBJECT":
                        bpy.ops.object.select_all(action="DESELECT")
                        o = self.create(context)
                        o.location = bpy.context.scene.cursor_location
                        o.select = True
                        context.scene.objects.active = o
                        self.manipulate()
                        return {'FINISHED'}
                else:
                        self.report({'WARNING'}, "Archipack: Option only valid in Object mode")
                        return {'CANCELLED'}