From 45cad6756f10eb708d1a17dae4a70723accc1928 Mon Sep 17 00:00:00 2001 From: Stephen Leger Date: Tue, 1 Aug 2017 03:48:42 +0200 Subject: archipack: update to 1.2.8 add roof and freeform floors --- archipack/archipack_autoboolean.py | 97 ++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 31 deletions(-) (limited to 'archipack/archipack_autoboolean.py') diff --git a/archipack/archipack_autoboolean.py b/archipack/archipack_autoboolean.py index a171532c..f304ced0 100644 --- a/archipack/archipack_autoboolean.py +++ b/archipack/archipack_autoboolean.py @@ -28,16 +28,16 @@ import bpy from bpy.types import Operator from bpy.props import EnumProperty from mathutils import Vector -from .materialutils import MaterialUtils - -from os import path +""" +from os import path def debug_using_gl(context, filename): context.scene.update() temp_path = "C:\\tmp\\" context.scene.render.filepath = path.join(temp_path, filename + ".png") bpy.ops.render.opengl(write_still=True) +""" class ArchipackBoolManager(): @@ -95,7 +95,7 @@ class ArchipackBoolManager(): 'archipack_robusthole' in wall or 'archipack_handle' in wall) - def datablock(self, o): + def datablock(self, o, basis='WALL'): """ get datablock from windows and doors return @@ -104,10 +104,14 @@ class ArchipackBoolManager(): """ d = None if o.data: - if "archipack_window" in o.data: - d = o.data.archipack_window[0] - elif "archipack_door" in o.data: - d = o.data.archipack_door[0] + if basis == 'WALL': + if "archipack_window" in o.data: + d = o.data.archipack_window[0] + elif "archipack_door" in o.data: + d = o.data.archipack_door[0] + elif basis == 'ROOF': + if "archipack_roof" in o.data: + d = o.data.archipack_roof[0] return d def prepare_hole(self, hole): @@ -131,7 +135,7 @@ class ArchipackBoolManager(): return hole return None - def _generate_hole(self, context, o): + def _generate_hole(self, context, o, basis='WALL'): # use existing one if self.mode != 'ROBUST': hole = self.get_child_hole(o) @@ -139,7 +143,7 @@ class ArchipackBoolManager(): # print("_generate_hole Use existing hole %s" % (hole.name)) return hole # generate single hole from archipack primitives - d = self.datablock(o) + d = self.datablock(o, basis) hole = None if d is not None: if (self.itM is not None and ( @@ -224,7 +228,9 @@ class ArchipackBoolManager(): if wall.parent is not None: hole_obj.parent = wall.parent hole_obj.matrix_world = wall.matrix_world.copy() - MaterialUtils.add_wall2_materials(hole_obj) + for mat in wall.data.materials: + hole_obj.data.materials.append(mat) + # MaterialUtils.add_wall2_materials(hole_obj) return hole_obj def update_hybrid(self, context, wall, childs, holes): @@ -268,10 +274,10 @@ class ArchipackBoolManager(): hole_obj = self.create_merge_basis(context, wall) else: hole_obj = m.object - # debug_using_gl(context, "260") + m.object = hole_obj self.prepare_hole(hole_obj) - # debug_using_gl(context, "263") + to_delete = [] # mixed-> mixed @@ -284,12 +290,11 @@ class ArchipackBoolManager(): # remove modifier and holes not found in new list self.remove_modif_and_object(context, hole_obj, to_delete) - # debug_using_gl(context, "276") + # add modifier and holes not found in existing for h in holes: if h not in existing: self.union(hole_obj, h) - # debug_using_gl(context, "281") # Interactive def update_interactive(self, context, wall, childs, holes): @@ -385,6 +390,16 @@ class ArchipackBoolManager(): elif modif is not None: wall.modifiers.remove(modif) + def get_basis_type(self, o): + if o.data is not None: + if "archipack_wall2" in o.data: + return 'WALL' + elif "archipack_roof" in o.data: + return 'ROOF' + elif "archipack_wall" in o.data: + return 'WALL' + return 'DEFAULT' + def autoboolean(self, context, wall): """ Entry point for multi-boolean operations like @@ -397,19 +412,26 @@ class ArchipackBoolManager(): # get wall bounds to find what's inside self._get_bounding_box(wall) + # filter roofs when wall is roof + basis = self.get_basis_type(wall) + # either generate hole or get existing one for o in context.scene.objects: - h = self._generate_hole(context, o) + h = self._generate_hole(context, o, basis) if h is not None: holes.append(h) childs.append(o) - # debug_using_gl(context, "395") + self.sort_holes(wall, holes) # hole(s) are selected and active after this one for hole in holes: + # copy wall material to hole + hole.data.materials.clear() + for mat in wall.data.materials: + hole.data.materials.append(mat) + self.prepare_hole(hole) - # debug_using_gl(context, "401") # update / remove / add boolean modifier if self.mode == 'INTERACTIVE': @@ -430,20 +452,18 @@ class ArchipackBoolManager(): else: wall.parent.select = True context.scene.objects.active = wall.parent - # debug_using_gl(context, "422") + wall.select = True for o in childs: if 'archipack_robusthole' in o: o.hide_select = False o.select = True - # debug_using_gl(context, "428") bpy.ops.archipack.parent_to_reference() for o in childs: if 'archipack_robusthole' in o: o.hide_select = True - # debug_using_gl(context, "435") def detect_mode(self, context, wall): for m in wall.modifiers: @@ -461,9 +481,12 @@ class ArchipackBoolManager(): in use in draw door and windows over wall o is either a window or a door """ + # generate holes for crossing window and doors self.itM = wall.matrix_world.inverted() - d = self.datablock(o) + basis = self.get_basis_type(wall) + d = self.datablock(o, basis) + hole = None hole_obj = None # default mode defined by __init__ @@ -477,6 +500,10 @@ class ArchipackBoolManager(): if hole is None: return + hole.data.materials.clear() + for mat in wall.data.materials: + hole.data.materials.append(mat) + self.prepare_hole(hole) if self.mode == 'INTERACTIVE': @@ -518,11 +545,13 @@ class ArchipackBoolManager(): bpy.ops.archipack.parent_to_reference() wall.select = True context.scene.objects.active = wall - d = wall.data.archipack_wall2[0] - g = d.get_generator() - d.setup_childs(wall, g) - d.relocate_childs(context, wall, g) - + if "archipack_wall2" in wall.data: + d = wall.data.archipack_wall2[0] + g = d.get_generator() + d.setup_childs(wall, g) + d.relocate_childs(context, wall, g) + elif "archipack_roof" in wall.data: + pass if hole_obj is not None: self.prepare_hole(hole_obj) @@ -559,7 +588,9 @@ class ARCHIPACK_OT_single_boolean(Operator): def poll(cls, context): w = context.active_object return (w.data is not None and - "archipack_wall2" in w.data and + ("archipack_wall2" in w.data or + "archipack_wall" in w.data or + "archipack_roof" in w.data) and len(context.selected_objects) == 2 ) @@ -648,14 +679,18 @@ class ARCHIPACK_OT_generate_hole(Operator): if context.mode == "OBJECT": manager = ArchipackBoolManager(mode='HYBRID') o = context.active_object - d = manager.datablock(o) + + # filter roofs when o is roof + basis = manager.get_basis_type(o) + + d = manager.datablock(o, basis) if d is None: - self.report({'WARNING'}, "Archipack: active object must be a door or a window") + self.report({'WARNING'}, "Archipack: active object must be a door, a window or a roof") return {'CANCELLED'} bpy.ops.object.select_all(action='DESELECT') o.select = True context.scene.objects.active = o - hole = manager._generate_hole(context, o) + hole = manager._generate_hole(context, o, basis) manager.prepare_hole(hole) hole.select = False o.select = True -- cgit v1.2.3