From 489e566047d8dab906ceceec4e73ab3d59f9830c Mon Sep 17 00:00:00 2001 From: Stephen Leger Date: Sun, 18 Nov 2018 14:06:37 +0100 Subject: archipack 2.8 compatibility (step2) --- archipack/__init__.py | 30 +++----------------- archipack/archipack_autoboolean.py | 19 ++++--------- archipack/archipack_cutter.py | 10 +++---- archipack/archipack_door.py | 42 +++++++++++++-------------- archipack/archipack_fence.py | 24 +++++----------- archipack/archipack_floor.py | 10 +++---- archipack/archipack_handle.py | 3 +- archipack/archipack_manipulator.py | 7 +++-- archipack/archipack_material.py | 49 ++++++++++++++++---------------- archipack/archipack_object.py | 22 ++++++++++++-- archipack/archipack_preset.py | 2 -- archipack/archipack_reference_point.py | 7 +++-- archipack/archipack_roof.py | 18 ++++++------ archipack/archipack_slab.py | 18 ++++++------ archipack/archipack_snap.py | 2 +- archipack/archipack_stair.py | 10 +++---- archipack/archipack_truss.py | 2 +- archipack/archipack_wall2.py | 10 +++---- archipack/archipack_window.py | 52 +++++++++++++++++----------------- 19 files changed, 155 insertions(+), 182 deletions(-) diff --git a/archipack/__init__.py b/archipack/__init__.py index 74f4f761..6c30d218 100644 --- a/archipack/__init__.py +++ b/archipack/__init__.py @@ -301,30 +301,9 @@ class Archipack_Pref(AddonPreferences): col.prop(self, "constant_handle_size") # ---------------------------------------------------- -# Archipack panels +# Archipack panel # ---------------------------------------------------- - -class TOOLS_PT_Archipack_Tools(Panel): - bl_label = "Archipack Tools" - bl_idname = "TOOLS_PT_Archipack_Tools" - bl_space_type = "VIEW_3D" - bl_region_type = "TOOLS" - # bl_category = "Tools" - bl_context = "objectmode" - - @classmethod - def poll(self, context): - return True - - def draw(self, context): - wm = context.window_manager - layout = self.layout - box = layout.box() - box.label(text="Auto boolean") - box.operator("archipack.auto_boolean", text="AutoBoolean", icon='AUTO').mode = 'HYBRID' - - class TOOLS_PT_Archipack_Create(Panel): bl_label = "Archipack" bl_idname = "TOOLS_PT_Archipack_Create" @@ -342,9 +321,11 @@ class TOOLS_PT_Archipack_Create(Panel): icons = icons_collection["main"] layout = self.layout + box = layout.box() + box.operator("archipack.auto_boolean", text="Boolean", icon='AUTO').mode = 'HYBRID' row = layout.row(align=True) box = row.box() - box.label(text="Objects") + box.label(text="Create") row = box.row(align=True) row.operator("archipack.window_preset_menu", text="Window", @@ -508,7 +489,6 @@ def register(): archipack_floor.register() archipack_rendering.register() bpy.utils.register_class(Archipack_Pref) - bpy.utils.register_class(TOOLS_PT_Archipack_Tools) bpy.utils.register_class(TOOLS_PT_Archipack_Create) bpy.utils.register_class(ARCHIPACK_MT_create) bpy.types.VIEW3D_MT_mesh_add.append(menu_func) @@ -518,8 +498,6 @@ def unregister(): global icons_collection bpy.types.VIEW3D_MT_mesh_add.remove(menu_func) bpy.utils.unregister_class(ARCHIPACK_MT_create) - - bpy.utils.unregister_class(TOOLS_PT_Archipack_Tools) bpy.utils.unregister_class(TOOLS_PT_Archipack_Create) bpy.utils.unregister_class(Archipack_Pref) archipack_material.unregister() diff --git a/archipack/archipack_autoboolean.py b/archipack/archipack_autoboolean.py index ad0e28d8..8e4df558 100644 --- a/archipack/archipack_autoboolean.py +++ b/archipack/archipack_autoboolean.py @@ -28,9 +28,9 @@ import bpy from bpy.types import Operator from bpy.props import EnumProperty from mathutils import Vector +from . archipack_object import ArchipackCollectionManager - -class ArchipackBoolManager(): +class ArchipackBoolManager(ArchipackCollectionManager): """ Handle three methods for booleans - interactive: one modifier for each hole right on wall @@ -196,7 +196,7 @@ class ArchipackBoolManager(): m.object = None o.modifiers.remove(m) if h is not None: - context.scene.collection.objects.unlink(h) + self.unlink_object_from_scene(h) bpy.data.objects.remove(h, do_unlink=True) # Mixed @@ -204,7 +204,7 @@ class ArchipackBoolManager(): # print("create_merge_basis") h = bpy.data.meshes.new("AutoBoolean") hole_obj = bpy.data.objects.new("AutoBoolean", h) - context.scene.collection.objects.link(hole_obj) + self.link_object_to_scene(context, hole_obj) hole_obj['archipack_hybridhole'] = True if wall.parent is not None: hole_obj.parent = wall.parent @@ -299,7 +299,7 @@ class ArchipackBoolManager(): to_delete.append([m, h]) # remove modifier and holes not found in new list self.remove_modif_and_object(context, hole_obj, to_delete) - # context.scene.collection.objects.unlink(hole_obj) + self.unlink_object_from_scene(hole_obj) bpy.data.objects.remove(hole_obj, do_unlink=True) to_delete = [] @@ -546,14 +546,6 @@ class ARCHIPACK_OT_single_boolean(Operator): ), default='HYBRID' ) - solver_mode : EnumProperty( - name="Solver", - items=( - ('CARVE', 'CARVE', 'Slow but robust (could be slow in hybrid mode with many holes)', 0), - ('BMESH', 'BMESH', 'Fast but more prone to errors', 1) - ), - default='BMESH' - ) """ Wall must be active object window or door must be selected @@ -609,7 +601,6 @@ class ARCHIPACK_OT_auto_boolean(Operator): layout = self.layout row = layout.row() row.prop(self, 'mode') - row.prop(self, 'solver_mode') def execute(self, context): if context.mode == "OBJECT": diff --git a/archipack/archipack_cutter.py b/archipack/archipack_cutter.py index d46dd58f..3b9f424d 100644 --- a/archipack/archipack_cutter.py +++ b/archipack/archipack_cutter.py @@ -655,11 +655,8 @@ class ArchipackCutter(): parts_expand : BoolProperty( default=False ) - closed : BoolProperty( - description="keep closed to be wall snap manipulator compatible", - options={'SKIP_SAVE'}, - default=True - ) + + closed = True def draw(self, layout, context): box = layout.box() @@ -849,7 +846,8 @@ class ArchipackCutter(): self.update_parent(context, o) def update_path(self, context): - user_def_path = context.scene.objects.get(self.user_defined_path) + + user_def_path = context.scene.objects.get(self.user_defined_path.strip()) if user_def_path is not None and user_def_path.type == 'CURVE': self.from_spline(context, user_def_path.matrix_world, diff --git a/archipack/archipack_door.py b/archipack/archipack_door.py index 9c63082b..03e3d5e1 100644 --- a/archipack/archipack_door.py +++ b/archipack/archipack_door.py @@ -40,7 +40,7 @@ from .panel import Panel as DoorPanel from .archipack_handle import create_handle, door_handle_horizontal_01 from .archipack_manipulator import Manipulable from .archipack_preset import ArchipackPreset, PresetMenuOperator -from .archipack_object import ArchipackObject, ArchipackCreateTool, ArchipackDrawTool +from .archipack_object import ArchipackObject, ArchipackCreateTool, ArchipackDrawTool, ArchipackCollectionManager from .archipack_gl import FeedbackPanel from .archipack_keymaps import Keymaps @@ -559,7 +559,7 @@ class archipack_door_panel(ArchipackObject, PropertyGroup): def remove_handle(self, context, o): handle = self.find_handle(o) if handle is not None: - context.scene.collection.objects.unlink(handle) + self.unlink_object_from_scene(handle) bpy.data.objects.remove(handle, do_unlink=True) def update(self, context): @@ -600,7 +600,7 @@ class ARCHIPACK_PT_door_panel(Panel): # ------------------------------------------------------------------ -class ARCHIPACK_OT_door_panel(Operator): +class ARCHIPACK_OT_door_panel(ArchipackCollectionManager, Operator): bl_idname = "archipack.door_panel" bl_label = "Door model 1" bl_description = "Door model 1" @@ -727,7 +727,7 @@ class ARCHIPACK_OT_door_panel(Operator): d.panels_x = self.panels_x d.panels_y = self.panels_y d.handle = self.handle - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) o.lock_location[0] = True o.lock_location[1] = True o.lock_location[2] = True @@ -1032,13 +1032,13 @@ class archipack_door(ArchipackObject, Manipulable, PropertyGroup): if archipack_door_panel.filter(child): self.remove_handle(context, child) to_remove -= 1 - context.scene.collection.objects.unlink(child) + self.unlink_object_from_scene(child) bpy.data.objects.remove(child, do_unlink=True) def remove_handle(self, context, o): handle = self.find_handle(o) if handle is not None: - context.scene.collection.objects.unlink(handle) + self.unlink_object_from_scene(handle) bpy.data.objects.remove(handle, do_unlink=True) def create_childs(self, context, o): @@ -1112,7 +1112,7 @@ class archipack_door(ArchipackObject, Manipulable, PropertyGroup): id = c_names.index(c.data.name) except: self.remove_handle(context, c) - context.scene.collection.objects.unlink(c) + self.unlink_object_from_scene(c) bpy.data.objects.remove(c, do_unlink=True) # children ordering may not be the same, so get the right l_childs order @@ -1130,7 +1130,7 @@ class archipack_door(ArchipackObject, Manipulable, PropertyGroup): for i, child in enumerate(childs): if order[i] < 0: p = bpy.data.objects.new("DoorPanel", child.data) - context.scene.collection.objects.link(p) + self.link_object_to_scene(context, p) p.lock_location[0] = True p.lock_location[1] = True p.lock_location[2] = True @@ -1158,7 +1158,7 @@ class archipack_door(ArchipackObject, Manipulable, PropertyGroup): # MaterialUtils.add_handle_materials(h) h.location = handle.location.copy() elif h is not None: - context.scene.collection.objects.unlink(h) + self.unlink_object_from_scene(h) bpy.data.objects.remove(h, do_unlink=True) def _synch_hole(self, context, linked, hole): @@ -1166,7 +1166,7 @@ class archipack_door(ArchipackObject, Manipulable, PropertyGroup): if l_hole is None: l_hole = bpy.data.objects.new("hole", hole.data) l_hole['archipack_hole'] = True - context.scene.collection.objects.link(l_hole) + self.link_object_to_scene(context, l_hole) l_hole.parent = linked l_hole.matrix_world = linked.matrix_world.copy() l_hole.location = hole.location.copy() @@ -1314,7 +1314,7 @@ class archipack_door(ArchipackObject, Manipulable, PropertyGroup): if hole_obj is None: m = bpy.data.meshes.new("hole") hole_obj = bpy.data.objects.new("hole", m) - context.scene.collection.objects.link(hole_obj) + self.link_object_to_scene(context, hole_obj) hole_obj['archipack_hole'] = True hole_obj.parent = o hole_obj.matrix_world = o.matrix_world.copy() @@ -1339,7 +1339,7 @@ class archipack_door(ArchipackObject, Manipulable, PropertyGroup): m = bpy.data.meshes.new("hole") o = bpy.data.objects.new("hole", m) o['archipack_robusthole'] = True - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) v = Vector((0, 0, 0)) offset = Vector((0, -0.001, 0)) size = Vector((self.x + 2 * self.frame_x, self.z + self.frame_x + 0.001, self.y)) @@ -1556,7 +1556,7 @@ class ARCHIPACK_OT_door(ArchipackCreateTool, Operator): d.panels_x = self.panels_x d.panels_y = self.panels_y d.handle = self.handle - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) o.select_set(state=True) context.view_layer.objects.active = o self.add_material(o) @@ -1571,16 +1571,16 @@ class ARCHIPACK_OT_door(ArchipackCreateTool, Operator): bpy.ops.archipack.disable_manipulate() for child in o.children: if 'archipack_hole' in child: - context.scene.collection.objects.unlink(child) + self.unlink_object_from_scene(child) bpy.data.objects.remove(child, do_unlink=True) elif child.data is not None and 'archipack_door_panel' in child.data: for handle in child.children: if 'archipack_handle' in handle: - context.scene.collection.objects.unlink(handle) + self.unlink_object_from_scene(handle) bpy.data.objects.remove(handle, do_unlink=True) - context.scene.collection.objects.unlink(child) + self.unlink_object_from_scene(child) bpy.data.objects.remove(child, do_unlink=True) - context.scene.collection.objects.unlink(o) + self.unlink_object_from_scene(o) bpy.data.objects.remove(o, do_unlink=True) def update(self, context): @@ -1678,20 +1678,20 @@ class ARCHIPACK_OT_door_draw(ArchipackDrawTool, Operator): new_w = o.copy() new_w.data = o.data - context.scene.collection.objects.link(new_w) + self.link_object_to_scene(context, new_w) # instance subs for child in o.children: if "archipack_hole" not in child: new_c = child.copy() new_c.data = child.data new_c.parent = new_w - context.scene.collection.objects.link(new_c) + self.link_object_to_scene(context, new_c) # dup handle if any for c in child.children: new_h = c.copy() new_h.data = c.data new_h.parent = new_c - context.scene.collection.objects.link(new_h) + self.link_object_to_scene(context, new_h) o = new_w o.select_set(state=True) @@ -1710,7 +1710,7 @@ class ARCHIPACK_OT_door_draw(ArchipackDrawTool, Operator): def modal(self, context, event): context.area.tag_redraw() - o = context.scene.objects.get(self.object_name) + o = context.scene.objects.get(self.object_name.strip()) if o is None: return {'FINISHED'} diff --git a/archipack/archipack_fence.py b/archipack/archipack_fence.py index 0196aac8..376f90e6 100644 --- a/archipack/archipack_fence.py +++ b/archipack/archipack_fence.py @@ -751,7 +751,7 @@ class archipack_fence_part(PropertyGroup): find witch selected object this instance belongs to provide support for "copy to selected" """ - selected = [o for o in context.selected_objects] + selected = context.selected_objects[:] for o in selected: props = archipack_fence.datablock(o) if props is not None: @@ -1226,9 +1226,7 @@ class archipack_fence(ArchipackObject, Manipulable, PropertyGroup): # add parts for i in range(len(self.parts), self.n_parts): self.parts.add() - print("setup_manipulators") self.setup_manipulators() - print("update_parts.done") def interpolate_bezier(self, pts, wM, p0, p1, resolution): # straight segment, worth testing here @@ -1309,7 +1307,7 @@ class archipack_fence(ArchipackObject, Manipulable, PropertyGroup): o.matrix_world = tM @ Matrix.Translation(pt) def update_path(self, context): - path = context.scene.objects.get(self.user_defined_path) + path = context.scene.objects.get(self.user_defined_path.strip()) if path is not None and path.type == 'CURVE': splines = path.data.splines if len(splines) > self.user_defined_spline: @@ -1331,7 +1329,6 @@ class archipack_fence(ArchipackObject, Manipulable, PropertyGroup): return g def update(self, context, manipulable_refresh=False): - print("update") o = self.find_in_selection(context, self.auto_update) if o is None: @@ -1340,7 +1337,7 @@ class archipack_fence(ArchipackObject, Manipulable, PropertyGroup): # clean up manipulators before any data model change if manipulable_refresh: self.manipulable_disable(context) - print("update_parts") + self.update_parts() verts = [] @@ -1355,7 +1352,7 @@ class archipack_fence(ArchipackObject, Manipulable, PropertyGroup): if self.user_defined_post_enable: # user defined posts - user_def_post = context.scene.objects.get(self.user_defined_post) + user_def_post = context.scene.objects.get(self.user_defined_post.strip()) if user_def_post is not None and user_def_post.type == 'MESH': g.setup_user_defined_post(user_def_post, self.post_x, self.post_y, self.post_z) @@ -1369,7 +1366,7 @@ class archipack_fence(ArchipackObject, Manipulable, PropertyGroup): # user defined subs if self.user_defined_subs_enable: - user_def_subs = context.scene.objects.get(self.user_defined_subs) + user_def_subs = context.scene.objects.get(self.user_defined_subs.strip()) if user_def_subs is not None and user_def_subs.type == 'MESH': g.setup_user_defined_post(user_def_subs, self.subs_x, self.subs_y, self.subs_z) @@ -1615,35 +1612,28 @@ class ARCHIPACK_OT_fence(ArchipackCreateTool, Operator): bl_options = {'REGISTER', 'UNDO'} def create(self, context): - print("Create") + m = bpy.data.meshes.new("Fence") o = bpy.data.objects.new("Fence", m) d = m.archipack_fence.add() # make manipulators selectable - print("manipulable_selectable") d.manipulable_selectable = True - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) o.select_set(state=True) context.view_layer.objects.active = o - print("load_preset") self.load_preset(d) - print("add_material") self.add_material(o) return o def execute(self, context): if context.mode == "OBJECT": - print("select_all") bpy.ops.object.select_all(action="DESELECT") o = self.create(context) - print("select_all") o.location = context.scene.cursor_location o.select_set(state=True) context.view_layer.objects.active = o - print("manipulate") - self.manipulate() return {'FINISHED'} else: diff --git a/archipack/archipack_floor.py b/archipack/archipack_floor.py index f53a78d7..82c1f000 100644 --- a/archipack/archipack_floor.py +++ b/archipack/archipack_floor.py @@ -1400,7 +1400,7 @@ class archipack_floor(ArchipackObject, Manipulable, PropertyGroup): self.auto_update = True def update_path(self, context): - user_def_path = context.scene.objects.get(self.user_defined_path) + user_def_path = context.scene.objects.get(self.user_defined_path.strip()) if user_def_path is not None and user_def_path.type == 'CURVE': self.from_spline( context, @@ -1576,7 +1576,7 @@ class archipack_floor_cutter_segment(ArchipackCutterPart, PropertyGroup): ) def find_in_selection(self, context): - selected = [o for o in context.selected_objects] + selected = context.selected_objects[:] for o in selected: d = archipack_floor_cutter.datablock(o) if d: @@ -1819,7 +1819,7 @@ class ARCHIPACK_OT_floor(ArchipackCreateTool, Operator): p.a0 = angle_90 p.length = x d.n_parts = 4 - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) o.select_set(state=True) context.view_layer.objects.active = o self.load_preset(d) @@ -1949,7 +1949,7 @@ class ARCHIPACK_OT_floor_cutter(ArchipackCreateTool, Operator): m = bpy.data.meshes.new("Floor Cutter") o = bpy.data.objects.new("Floor Cutter", m) d = m.archipack_floor_cutter.add() - parent = context.scene.objects.get(self.parent) + parent = context.scene.objects.get(self.parent.strip()) if parent is not None: o.parent = parent bbox = parent.bound_box @@ -1981,7 +1981,7 @@ class ARCHIPACK_OT_floor_cutter(ArchipackCreateTool, Operator): o.location = context.scene.cursor_location # make manipulators selectable d.manipulable_selectable = True - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) o.select_set(state=True) context.view_layer.objects.active = o # self.add_material(o) diff --git a/archipack/archipack_handle.py b/archipack/archipack_handle.py index d27603b0..27da6b0b 100644 --- a/archipack/archipack_handle.py +++ b/archipack/archipack_handle.py @@ -26,13 +26,14 @@ # ---------------------------------------------------------- import bpy +from .archipack_object import ArchipackCollectionManager def create_handle(context, parent, mesh): old = context.active_object handle = bpy.data.objects.new("Handle", mesh) handle['archipack_handle'] = True - context.scene.collection.objects.link(handle) + ArchipackCollectionManager.link_object_to_scene(context, handle) modif = handle.modifiers.new('Subsurf', 'SUBSURF') modif.render_levels = 4 modif.levels = 1 diff --git a/archipack/archipack_manipulator.py b/archipack/archipack_manipulator.py index 976ae632..be6c2ef2 100644 --- a/archipack/archipack_manipulator.py +++ b/archipack/archipack_manipulator.py @@ -690,7 +690,7 @@ class WallSnapManipulator(Manipulator): # update properties from generator idx = 0 - + d.auto_update = False for p0, p1, selected in gl_pts3d: if selected: @@ -738,7 +738,9 @@ class WallSnapManipulator(Manipulator): idx += 1 self.mouse_release(context, event) - d.relocate_childs(context, o, g) + if hasattr(d, "relocate_childs"): + d.relocate_childs(context, o, g) + d.auto_update = True d.update(context) if state == 'CANCEL': @@ -2124,7 +2126,6 @@ class Manipulable(): self.manipulable_end_point = Vector((0, 0)) o = context.active_object - if o is not None: self.manipulable_exit_selectmode(context) remove_manipulable(o.name) diff --git a/archipack/archipack_material.py b/archipack/archipack_material.py index 2bcd3e40..cbec80cd 100644 --- a/archipack/archipack_material.py +++ b/archipack/archipack_material.py @@ -225,6 +225,8 @@ class MaterialSetManager(): self.objects = {} # hold reference of dynamic enumerator self.enums = {} + self.default_enum = [('DEFAULT', 'Default', '', 0)] + def get_filename(self, object_type): @@ -262,9 +264,9 @@ class MaterialSetManager(): material_sets = {} # create file object, and set open mode - if os.path.exists(filename): - try: - f = open(filename, 'r') + + try: + with open(filename, 'r') as f: lines = f.readlines() for line in lines: @@ -272,17 +274,15 @@ class MaterialSetManager(): if str(s_key) not in material_sets.keys(): material_sets[s_key] = [] material_sets[s_key].append(mat_name.strip()) - except: - print("Archipack: An error occurred while loading {}".format(filename)) - pass - finally: - f.close() + except: + print("Archipack: material preset for {} not found".format(object_type)) + pass - s_keys = material_sets.keys() - for s_key in s_keys: - self.register_set(object_type, s_key, material_sets[s_key]) + s_keys = material_sets.keys() + for s_key in s_keys: + self.register_set(object_type, s_key, material_sets[s_key]) - self.make_enum(object_type, s_keys) + self.make_enum(object_type, s_keys) def save(self, object_type): # always save in user prefs @@ -330,17 +330,15 @@ class MaterialSetManager(): if object_type not in self.objects.keys(): self.load(object_type) if object_type not in self.objects.keys(): - print("Archipack: Unknown object type {}".format(object_type)) + # print("Archipack: Unknown object type {}".format(object_type)) return None if set_name not in self.objects[object_type].keys(): - print("Archipack: set {} not found".format(set_name)) + # print("Archipack: set {} not found".format(set_name)) return None return self.objects[object_type][set_name] def make_enum(self, object_type, s_keys): - if len(s_keys) < 1: - self.enums[object_type] = [('DEFAULT', 'Default', '', 0)] - else: + if len(s_keys) > 0: self.enums[object_type] = [(s.upper(), s.capitalize(), '', i) for i, s in enumerate(s_keys)] def get_enum(self, object_type): @@ -351,7 +349,10 @@ class MaterialSetManager(): if object_type not in self.objects.keys(): self.objects[object_type] = {} - return self.enums[object_type] + if object_type in self.enums: + return self.enums[object_type] + + return self.default_enum def material_enum(self, context): @@ -411,7 +412,7 @@ class archipack_material(PropertyGroup): mats = setman.get_materials(self.category, self.material) - if mats is None: + if mats is None or len(mats) < 1: return False for ob in sel: @@ -484,13 +485,11 @@ class ARCHIPACK_OT_material(Operator): res = False pass - if res: - # print("ARCHIPACK_OT_material.apply {} {}".format(self.category, self.material)) - return {'FINISHED'} - else: + if not res: print("Archipack: unable to add material {} for {}".format(self.material, self.category)) - self.report({'WARNING'}, 'Material {} for {} not found'.format(self.material, self.category)) - return {'CANCELLED'} + # self.report({'WARNING'}, 'Material {} for {} not found'.format(self.material, self.category)) + + return {'FINISHED'} class ARCHIPACK_OT_material_add(Operator): diff --git a/archipack/archipack_object.py b/archipack/archipack_object.py index 10da5be1..8c908214 100644 --- a/archipack/archipack_object.py +++ b/archipack/archipack_object.py @@ -38,7 +38,23 @@ from bpy_extras.view3d_utils import ( ) -class ArchipackObject(): +class ArchipackCollectionManager(): + + @staticmethod + def link_object_to_scene(context, o): + coll_main = context.scene.collection.children.get("Archipack") + if coll_main is None: + coll_main = bpy.data.collections.new(name="Archipack") + context.scene.collection.children.link(coll_main) + coll_main.objects.link(o) + + @staticmethod + def unlink_object_from_scene(o): + for coll in o.users_collection: + coll.objects.unlink(o) + + +class ArchipackObject(ArchipackCollectionManager): """ Shared property of archipack's objects PropertyGroup provide basic support for copy to selected @@ -138,7 +154,7 @@ class ArchipackObject(): o.matrix_world.translation = p -class ArchipackCreateTool(): +class ArchipackCreateTool(ArchipackCollectionManager): """ Shared property of archipack's create tool Operator """ @@ -212,7 +228,7 @@ class ArchipackCreateTool(): pass -class ArchipackDrawTool(): +class ArchipackDrawTool(ArchipackCollectionManager): """ Draw tools """ diff --git a/archipack/archipack_preset.py b/archipack/archipack_preset.py index 42668bb9..8f1468b2 100644 --- a/archipack/archipack_preset.py +++ b/archipack/archipack_preset.py @@ -230,7 +230,6 @@ class PresetMenu(): self.border = GlPolyline((0.7, 0.7, 0.7, 1), d=2) self.keywords = SeekBox() self.keywords.colour_normal = (1, 1, 1, 1) - self.border.closed = True self.set_pos(context) @@ -555,7 +554,6 @@ class ArchipackPreset(AddPresetBase): "cls:" + cls, "preset:" + preset ] - # print(repr(cmd)) subprocess.Popen(cmd) diff --git a/archipack/archipack_reference_point.py b/archipack/archipack_reference_point.py index fe27b224..0b0c0348 100644 --- a/archipack/archipack_reference_point.py +++ b/archipack/archipack_reference_point.py @@ -34,6 +34,7 @@ from bpy.props import ( ) from mathutils import Vector from .bmesh_utils import BmeshEdit as bmed +from .archipack_object import ArchipackCollectionManager def update(self, context): @@ -199,7 +200,7 @@ class ARCHIPACK_PT_reference_point(Panel): layout.operator('archipack.apply_holes') -class ARCHIPACK_OT_reference_point(Operator): +class ARCHIPACK_OT_reference_point(ArchipackCollectionManager, Operator): """Add reference point""" bl_idname = "archipack.reference_point" bl_label = "Reference point" @@ -234,7 +235,7 @@ class ARCHIPACK_OT_reference_point(Operator): m = bpy.data.meshes.new(name="Reference") o = bpy.data.objects.new("Reference", m) o.location = Vector((x, y, 0)) - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) d = o.archipack_reference_point.add() d.location_2d = Vector((x, y, 0)) d.location_3d = self.location_3d @@ -412,7 +413,7 @@ class ARCHIPACK_OT_move_2d_reference_to_cursor(Operator): for child in o.children: child.select_set(state=True) bpy.ops.archipack.parent_to_reference() - context.scene.collection.objects.unlink(o) + self.unlink_object_from_scene(o) return {'FINISHED'} else: self.report({'WARNING'}, "Archipack: Option only valid in Object mode") diff --git a/archipack/archipack_roof.py b/archipack/archipack_roof.py index 5ab21a38..02bb01e8 100644 --- a/archipack/archipack_roof.py +++ b/archipack/archipack_roof.py @@ -3671,7 +3671,7 @@ class archipack_roof_segment(ArchipackSegment, PropertyGroup): find witch selected object this instance belongs to provide support for "copy to selected" """ - selected = [o for o in context.selected_objects] + selected = context.selected_objects[:] for o in selected: d = archipack_roof.datablock(o) if d: @@ -4387,7 +4387,7 @@ class archipack_roof(ArchipackLines, ArchipackObject, Manipulable, PropertyGroup bm.free() def find_parent(self, context): - o = context.scene.objects.get(self.t_parent) + o = context.scene.objects.get(self.t_parent.strip()) return o, archipack_roof.datablock(o) def intersection_angle(self, t_slope, t_width, p_slope, angle): @@ -4742,7 +4742,7 @@ class archipack_roof_cutter_segment(ArchipackCutterPart, PropertyGroup): ) def find_in_selection(self, context): - selected = [o for o in context.selected_objects] + selected = context.selected_objects[:] for o in selected: d = archipack_roof_cutter.datablock(o) if d: @@ -5029,7 +5029,7 @@ class ARCHIPACK_OT_roof(ArchipackCreateTool, Operator): d = m.archipack_roof.add() # make manipulators selectable d.manipulable_selectable = True - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) o.select_set(state=True) context.view_layer.objects.active = o self.add_material(o) @@ -5072,7 +5072,7 @@ class ARCHIPACK_OT_roof_cutter(ArchipackCreateTool, Operator): m = bpy.data.meshes.new("Roof Cutter") o = bpy.data.objects.new("Roof Cutter", m) d = m.archipack_roof_cutter.add() - parent = context.scene.objects.get(self.parent) + parent = context.scene.objects.get(self.parent.strip()) if parent is not None: o.parent = parent bbox = parent.bound_box @@ -5104,7 +5104,7 @@ class ARCHIPACK_OT_roof_cutter(ArchipackCreateTool, Operator): o.location = context.scene.cursor_location # make manipulators selectable d.manipulable_selectable = True - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) o.select_set(state=True) context.view_layer.objects.active = o self.add_material(o) @@ -5133,7 +5133,7 @@ class ARCHIPACK_OT_roof_cutter(ArchipackCreateTool, Operator): # ------------------------------------------------------------------ -class ARCHIPACK_OT_roof_from_curve(Operator): +class ARCHIPACK_OT_roof_from_curve(ArchipackCreateTool, Operator): bl_idname = "archipack.roof_from_curve" bl_label = "Roof curve" bl_description = "Create a roof from a curve" @@ -5159,7 +5159,7 @@ class ARCHIPACK_OT_roof_from_curve(Operator): # make manipulators selectable d.manipulable_selectable = True d.user_defined_path = curve.name - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) o.select_set(state=True) context.view_layer.objects.active = o d.update_path(context) @@ -5318,7 +5318,7 @@ class ARCHIPACK_OT_roof_throttle_update(Operator): if self.name in throttle_handlers.keys(): if throttle_handlers[self.name].modal(context, event): act = context.active_object - o = context.scene.objects.get(self.name) + o = context.scene.objects.get(self.name.strip()) # print("delay update of %s" % (self.name)) if o is not None: selected = o.select_get() diff --git a/archipack/archipack_slab.py b/archipack/archipack_slab.py index f4112b08..38150094 100644 --- a/archipack/archipack_slab.py +++ b/archipack/archipack_slab.py @@ -282,7 +282,7 @@ class SlabGenerator(CutAblePolygon, CutAbleGenerator): use_dissolve_boundaries=False, verts=bm.verts, edges=bm.edges, - delimit=1) + delimit={'MATERIAL'}) bm.to_mesh(o.data) bm.free() @@ -330,7 +330,7 @@ class archipack_slab_material(PropertyGroup): find witch selected object this instance belongs to provide support for "copy to selected" """ - selected = [o for o in context.selected_objects] + selected = context.selected_objects[:] for o in selected: props = archipack_slab.datablock(o) if props: @@ -354,7 +354,7 @@ class archipack_slab_child(PropertyGroup): def get_child(self, context): d = None - child = context.scene.objects.get(self.child_name) + child = context.scene.objects.get(self.child_name.strip()) if child is not None and child.data is not None: if 'archipack_fence' in child.data: d = child.data.archipack_fence[0] @@ -531,7 +531,7 @@ class archipack_slab_part(ArchipackSegment, PropertyGroup): find witch selected object this instance belongs to provide support for "copy to selected" """ - selected = [o for o in context.selected_objects] + selected = context.selected_objects[:] for o in selected: props = archipack_slab.datablock(o) if props: @@ -584,7 +584,7 @@ class archipack_slab(ArchipackObject, Manipulable, PropertyGroup): # Global slab offset # will only affect slab parts sharing a wall - childs = CollectionProperty(type=archipack_slab_child) + childs : CollectionProperty(type=archipack_slab_child) # Flag to prevent mesh update while making bulk changes over variables # use : # .auto_update = False @@ -1260,7 +1260,7 @@ class archipack_slab_cutter_segment(ArchipackCutterPart, PropertyGroup): ) def find_in_selection(self, context): - selected = [o for o in context.selected_objects] + selected = context.selected_objects[:] for o in selected: d = archipack_slab_cutter.datablock(o) if d: @@ -1452,7 +1452,7 @@ class ARCHIPACK_OT_slab(ArchipackCreateTool, Operator): d = m.archipack_slab.add() # make manipulators selectable d.manipulable_selectable = True - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) o.select_set(state=True) context.view_layer.objects.active = o self.load_preset(d) @@ -1622,7 +1622,7 @@ class ARCHIPACK_OT_slab_cutter(ArchipackCreateTool, Operator): m = bpy.data.meshes.new("Slab Cutter") o = bpy.data.objects.new("Slab Cutter", m) d = m.archipack_slab_cutter.add() - parent = context.scene.objects.get(self.parent) + parent = context.scene.objects.get(self.parent.strip()) if parent is not None: o.parent = parent bbox = parent.bound_box @@ -1654,7 +1654,7 @@ class ARCHIPACK_OT_slab_cutter(ArchipackCreateTool, Operator): o.location = context.scene.cursor_location # make manipulators selectable d.manipulable_selectable = True - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) o.select_set(state=True) context.view_layer.objects.active = o # self.add_material(o) diff --git a/archipack/archipack_snap.py b/archipack/archipack_snap.py index 33a59041..92d6ae24 100644 --- a/archipack/archipack_snap.py +++ b/archipack/archipack_snap.py @@ -231,7 +231,7 @@ class ArchipackSnapBase(): print("helper found") if context.scene.objects.get('Archipack_snap_helper') is None: print("link helper") - # context.scene.collection.objects.link(helper) + # self.link_object_to_scene(context, helper) context.scene.collection.objects.link(helper) else: print("create helper") diff --git a/archipack/archipack_stair.py b/archipack/archipack_stair.py index 8d512a65..578208f5 100644 --- a/archipack/archipack_stair.py +++ b/archipack/archipack_stair.py @@ -1557,7 +1557,7 @@ class archipack_stair_material(PropertyGroup): find witch selected object this instance belongs to provide support for "copy to selected" """ - selected = [o for o in context.selected_objects] + selected = context.selected_objects[:] for o in selected: props = archipack_stair.datablock(o) if props: @@ -1630,7 +1630,7 @@ class archipack_stair_part(PropertyGroup): find witch selected object this instance belongs to provide support for "copy to selected" """ - selected = [o for o in context.selected_objects] + selected = context.selected_objects[:] for o in selected: props = archipack_stair.datablock(o) if props: @@ -2389,7 +2389,7 @@ class archipack_stair(ArchipackObject, Manipulable, PropertyGroup): if self.user_defined_post_enable: # user defined posts - user_def_post = context.scene.objects.get(self.user_defined_post) + user_def_post = context.scene.objects.get(self.user_defined_post.strip()) if user_def_post is not None and user_def_post.type == 'MESH': g.setup_user_defined_post(user_def_post, self.post_x, self.post_y, self.post_z) @@ -2408,7 +2408,7 @@ class archipack_stair(ArchipackObject, Manipulable, PropertyGroup): # user defined subs if self.user_defined_subs_enable: - user_def_subs = context.scene.objects.get(self.user_defined_subs) + user_def_subs = context.scene.objects.get(self.user_defined_subs.strip()) if user_def_subs is not None and user_def_subs.type == 'MESH': g.setup_user_defined_post(user_def_subs, self.subs_x, self.subs_y, self.subs_z) @@ -2753,7 +2753,7 @@ class ARCHIPACK_OT_stair(ArchipackCreateTool, Operator): m = bpy.data.meshes.new("Stair") o = bpy.data.objects.new("Stair", m) d = m.archipack_stair.add() - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) o.select_set(state=True) context.view_layer.objects.active = o self.load_preset(d) diff --git a/archipack/archipack_truss.py b/archipack/archipack_truss.py index c8fe8768..2931717a 100644 --- a/archipack/archipack_truss.py +++ b/archipack/archipack_truss.py @@ -318,7 +318,7 @@ class ARCHIPACK_OT_truss(ArchipackCreateTool, Operator): d = m.archipack_truss.add() # make manipulators selectable # d.manipulable_selectable = True - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) o.select_set(state=True) context.view_layer.objects.active = o self.load_preset(d) diff --git a/archipack/archipack_wall2.py b/archipack/archipack_wall2.py index 09836780..1916f32d 100644 --- a/archipack/archipack_wall2.py +++ b/archipack/archipack_wall2.py @@ -422,7 +422,7 @@ def update_t_part(self, context): if o is not None: # w is parent wall - w = context.scene.objects.get(self.t_part) + w = context.scene.objects.get(self.t_part.strip()) wd = archipack_wall2.datablock(w) if wd is not None: @@ -718,7 +718,7 @@ class archipack_wall2_part(PropertyGroup): find witch selected object this instance belongs to provide support for "copy to selected" """ - selected = [o for o in context.selected_objects] + selected = context.selected_objects[:] for o in selected: props = archipack_wall2.datablock(o) if props: @@ -777,7 +777,7 @@ class archipack_wall2_child(PropertyGroup): def get_child(self, context): d = None - child = context.scene.objects.get(self.child_name) + child = context.scene.objects.get(self.child_name.strip()) if child is not None and child.data is not None: cd = child.data if 'archipack_window' in cd: @@ -1670,7 +1670,7 @@ class ARCHIPACK_OT_wall2_throttle_update(Operator): # cant rely on TIMER event as another timer may run if time.time() - throttle_start > throttle_delay: update_timer_updating = True - o = context.scene.objects.get(self.name) + o = context.scene.objects.get(self.name.strip()) if o is not None: m = o.modifiers.get("AutoBoolean") if m is not None: @@ -1768,7 +1768,7 @@ class ARCHIPACK_OT_wall2(ArchipackCreateTool, Operator): o = bpy.data.objects.new("Wall", m) d = m.archipack_wall2.add() d.manipulable_selectable = True - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) o.select_set(state=True) # around 12 degree m.auto_smooth_angle = 0.20944 diff --git a/archipack/archipack_window.py b/archipack/archipack_window.py index 618344b4..f79005e4 100644 --- a/archipack/archipack_window.py +++ b/archipack/archipack_window.py @@ -41,7 +41,7 @@ from .archipack_handle import create_handle, window_handle_vertical_01, window_h from .archipack_manipulator import Manipulable from .archipack_preset import ArchipackPreset, PresetMenuOperator from .archipack_gl import FeedbackPanel -from .archipack_object import ArchipackObject, ArchipackCreateTool, ArchipackDrawTool +from .archipack_object import ArchipackObject, ArchipackCreateTool, ArchipackDrawTool, ArchipackCollectionManager from .archipack_keymaps import Keymaps @@ -156,7 +156,7 @@ class archipack_window_panelrow(PropertyGroup): find witch selected object this instance belongs to provide support for "copy to selected" """ - selected = [o for o in context.selected_objects] + selected = context.selected_objects[:] for o in selected: props = archipack_window.datablock(o) if props: @@ -404,7 +404,7 @@ class archipack_window_panel(ArchipackObject, PropertyGroup): def remove_handle(self, context, o): handle = self.find_handle(o) if handle is not None: - context.scene.collection.objects.unlink(handle) + self.unlink_object_from_scene(handle) bpy.data.objects.remove(handle, do_unlink=True) def update(self, context): @@ -1002,7 +1002,7 @@ class archipack_window(ArchipackObject, Manipulable, PropertyGroup): lamp = self.find_portal(o) if self.portal: if lamp is None: - bpy.ops.object.lamp_add(type='AREA') + bpy.ops.object.light_add(type='AREA') lamp = context.active_object lamp.name = "Portal" lamp.parent = o @@ -1023,7 +1023,7 @@ class archipack_window(ArchipackObject, Manipulable, PropertyGroup): elif lamp is not None: d = lamp.data - context.scene.collection.objects.unlink(lamp) + self.unlink_object_from_scene(lamp) bpy.data.objects.remove(lamp) bpy.data.lights.remove(d) @@ -1054,13 +1054,13 @@ class archipack_window(ArchipackObject, Manipulable, PropertyGroup): if archipack_window_panel.filter(child): to_remove -= 1 self.remove_handle(context, child) - context.scene.collection.objects.unlink(child) + self.unlink_object_from_scene(child) bpy.data.objects.remove(child, do_unlink=True) def remove_handle(self, context, o): handle = self.find_handle(o) if handle is not None: - context.scene.collection.objects.unlink(handle) + self.unlink_object_from_scene(handle) bpy.data.objects.remove(handle, do_unlink=True) def update_rows(self, context, o): @@ -1127,7 +1127,7 @@ class archipack_window(ArchipackObject, Manipulable, PropertyGroup): id = c_names.index(c.data.name) except: self.remove_handle(context, c) - context.scene.collection.objects.unlink(c) + self.unlink_object_from_scene(c) bpy.data.objects.remove(c, do_unlink=True) # children ordering may not be the same, so get the right l_childs order @@ -1145,7 +1145,7 @@ class archipack_window(ArchipackObject, Manipulable, PropertyGroup): for i, child in enumerate(childs): if order[i] < 0: p = bpy.data.objects.new("Panel", child.data) - context.scene.collection.objects.link(p) + self.link_object_to_scene(context, p) p.lock_location[0] = True p.lock_location[1] = True p.lock_location[2] = True @@ -1169,7 +1169,7 @@ class archipack_window(ArchipackObject, Manipulable, PropertyGroup): h = create_handle(context, p, handle.data) h.location = handle.location.copy() elif h is not None: - context.scene.collection.objects.unlink(h) + self.unlink_object_from_scene(h) bpy.data.objects.remove(h, do_unlink=True) p.location = child.location.copy() @@ -1182,7 +1182,7 @@ class archipack_window(ArchipackObject, Manipulable, PropertyGroup): if l_hole is None: l_hole = bpy.data.objects.new("hole", hole.data) l_hole['archipack_hole'] = True - context.scene.collection.objects.link(l_hole) + self.link_object_to_scene(context, l_hole) for mat in hole.data.materials: l_hole.data.materials.append(mat) l_hole.parent = linked @@ -1442,7 +1442,7 @@ class archipack_window(ArchipackObject, Manipulable, PropertyGroup): if hole_obj is None: m = bpy.data.meshes.new("hole") hole_obj = bpy.data.objects.new("hole", m) - context.scene.collection.objects.link(hole_obj) + self.link_object_to_scene(context, hole_obj) hole_obj['archipack_hole'] = True hole_obj.parent = o hole_obj.matrix_world = o.matrix_world.copy() @@ -1496,7 +1496,7 @@ class archipack_window(ArchipackObject, Manipulable, PropertyGroup): m = bpy.data.meshes.new("hole") o = bpy.data.objects.new("hole", m) o['archipack_robusthole'] = True - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) verts = hole.vertices(self.curve_steps, Vector((0, self.altitude, 0)), center, origin, size, radius, self.angle_y, 0, shape_z=shape_z, path_type=self.shape) @@ -1736,7 +1736,7 @@ class ARCHIPACK_OT_window(ArchipackCreateTool, Operator): d.y = self.y d.z = self.z d.altitude = self.altitude - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) o.select_set(state=True) context.view_layer.objects.active = o self.add_material(o) @@ -1753,20 +1753,20 @@ class ARCHIPACK_OT_window(ArchipackCreateTool, Operator): for child in o.children: if child.type == 'LIGHT': d = child.data - context.scene.collection.objects.unlink(child) + self.unlink_object_from_scene(child) bpy.data.objects.remove(child) bpy.data.lights.remove(d) elif 'archipack_hole' in child: - context.scene.collection.objects.unlink(child) + self.unlink_object_from_scene(child) bpy.data.objects.remove(child, do_unlink=True) elif child.data is not None and 'archipack_window_panel' in child.data: for handle in child.children: if 'archipack_handle' in handle: - context.scene.collection.objects.unlink(handle) + self.unlink_object_from_scene(handle) bpy.data.objects.remove(handle, do_unlink=True) - context.scene.collection.objects.unlink(child) + self.unlink_object_from_scene(child) bpy.data.objects.remove(child, do_unlink=True) - context.scene.collection.objects.unlink(o) + self.unlink_object_from_scene(o) bpy.data.objects.remove(o, do_unlink=True) def update(self, context): @@ -1785,7 +1785,7 @@ class ARCHIPACK_OT_window(ArchipackCreateTool, Operator): def unique(self, context): act = context.active_object - sel = [o for o in context.selected_objects] + sel = context.selected_objects[:] bpy.ops.object.select_all(action="DESELECT") for o in sel: if archipack_window.filter(o): @@ -1871,19 +1871,19 @@ class ARCHIPACK_OT_window_draw(ArchipackDrawTool, Operator): # instance subs new_w = o.copy() new_w.data = o.data - context.scene.collection.objects.link(new_w) + self.link_object_to_scene(context, new_w) for child in o.children: if "archipack_hole" not in child: new_c = child.copy() new_c.data = child.data new_c.parent = new_w - context.scene.collection.objects.link(new_c) + self.link_object_to_scene(context, new_c) # dup handle if any for c in child.children: new_h = c.copy() new_h.data = c.data new_h.parent = new_c - context.scene.collection.objects.link(new_h) + self.link_object_to_scene(context, new_h) o = new_w o.select_set(state=True) @@ -1902,7 +1902,7 @@ class ARCHIPACK_OT_window_draw(ArchipackDrawTool, Operator): def modal(self, context, event): context.area.tag_redraw() - o = context.scene.objects.get(self.object_name) + o = context.scene.objects.get(self.object_name.strip()) if o is None: return {'FINISHED'} @@ -2035,7 +2035,7 @@ class ARCHIPACK_OT_window_portals(Operator): # ------------------------------------------------------------------ -class ARCHIPACK_OT_window_panel(Operator): +class ARCHIPACK_OT_window_panel(ArchipackCollectionManager, Operator): bl_idname = "archipack.window_panel" bl_label = "Window panel" bl_description = "Window panel" @@ -2161,7 +2161,7 @@ class ARCHIPACK_OT_window_panel(Operator): d.handle_model = self.handle_model d.handle_altitude = self.handle_altitude d.enable_glass = self.enable_glass - context.scene.collection.objects.link(o) + self.link_object_to_scene(context, o) o.select_set(state=True) context.view_layer.objects.active = o m = o.archipack_material.add() -- cgit v1.2.3