Skip to content
Snippets Groups Projects
Commit c1ab9b4b authored by Stephen Leger's avatar Stephen Leger
Browse files

archipack: T52120 release to official

parent 5638a878
No related branches found
No related tags found
No related merge requests found
Showing
with 20162 additions and 0 deletions
# -*- coding:utf-8 -*-
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# ----------------------------------------------------------
# Author: Stephen Leger (s-leger)
#
# ----------------------------------------------------------
bl_info = {
'name': 'Archipack',
'description': 'Architectural objects and 2d polygons detection from unordered splines',
'author': 's-leger',
'license': 'GPL',
'deps': 'shapely',
'version': (1, 2, 6),
'blender': (2, 7, 8),
'location': 'View3D > Tools > Create > Archipack',
'warning': '',
'wiki_url': 'https://github.com/s-leger/archipack/wiki',
'tracker_url': 'https://github.com/s-leger/archipack/issues',
'link': 'https://github.com/s-leger/archipack',
'support': 'COMMUNITY',
'category': 'Add Mesh'
}
import os
if "bpy" in locals():
import importlib as imp
imp.reload(archipack_snap)
imp.reload(archipack_manipulator)
imp.reload(archipack_reference_point)
imp.reload(archipack_autoboolean)
imp.reload(archipack_door)
imp.reload(archipack_window)
imp.reload(archipack_stair)
imp.reload(archipack_wall)
imp.reload(archipack_wall2)
imp.reload(archipack_slab)
imp.reload(archipack_fence)
imp.reload(archipack_truss)
imp.reload(archipack_floor)
imp.reload(archipack_rendering)
try:
imp.reload(archipack_polylib)
HAS_POLYLIB = True
except:
HAS_POLYLIB = False
pass
print("archipack: reload ready")
else:
from . import archipack_snap
from . import archipack_manipulator
from . import archipack_reference_point
from . import archipack_autoboolean
from . import archipack_door
from . import archipack_window
from . import archipack_stair
from . import archipack_wall
from . import archipack_wall2
from . import archipack_slab
from . import archipack_fence
from . import archipack_truss
from . import archipack_floor
from . import archipack_rendering
try:
"""
polylib depends on shapely
raise ImportError when not meet
"""
from . import archipack_polylib
HAS_POLYLIB = True
except:
print("archipack: shapely not found, using built in modules only")
HAS_POLYLIB = False
pass
print("archipack: ready")
# noinspection PyUnresolvedReferences
import bpy
# noinspection PyUnresolvedReferences
from bpy.types import (
Panel, WindowManager, PropertyGroup,
AddonPreferences, Menu
)
from bpy.props import (
EnumProperty, PointerProperty,
StringProperty, BoolProperty,
IntProperty, FloatProperty, FloatVectorProperty
)
from bpy.utils import previews
icons_collection = {}
# ----------------------------------------------------
# Addon preferences
# ----------------------------------------------------
def update_panel(self, context):
try:
bpy.utils.unregister_class(TOOLS_PT_Archipack_PolyLib)
bpy.utils.unregister_class(TOOLS_PT_Archipack_Tools)
bpy.utils.unregister_class(TOOLS_PT_Archipack_Create)
except:
pass
prefs = context.user_preferences.addons[__name__].preferences
TOOLS_PT_Archipack_PolyLib.bl_category = prefs.tools_category
bpy.utils.register_class(TOOLS_PT_Archipack_PolyLib)
TOOLS_PT_Archipack_Tools.bl_category = prefs.tools_category
bpy.utils.register_class(TOOLS_PT_Archipack_Tools)
TOOLS_PT_Archipack_Create.bl_category = prefs.create_category
bpy.utils.register_class(TOOLS_PT_Archipack_Create)
class Archipack_Pref(AddonPreferences):
bl_idname = __name__
tools_category = StringProperty(
name="Tools",
description="Choose a name for the category of the Tools panel",
default="Tools",
update=update_panel
)
create_category = StringProperty(
name="Create",
description="Choose a name for the category of the Create panel",
default="Create",
update=update_panel
)
create_submenu = BoolProperty(
name="Use Sub-menu",
description="Put Achipack's object into a sub menu (shift+a)",
default=True
)
max_style_draw_tool = BoolProperty(
name="Draw a wall use 3dsmax style",
description="Reverse clic / release cycle for Draw a wall",
default=True
)
# Arrow sizes (world units)
arrow_size = FloatProperty(
name="Arrow",
description="Manipulators arrow size (blender units)",
default=0.05
)
# Handle area size (pixels)
handle_size = IntProperty(
name="Handle",
description="Manipulators handle sensitive area size (pixels)",
min=2,
default=10
)
# Font sizes and basic colour scheme
feedback_size_main = IntProperty(
name="Main",
description="Main title font size (pixels)",
min=2,
default=16
)
feedback_size_title = IntProperty(
name="Title",
description="Tool name font size (pixels)",
min=2,
default=14
)
feedback_size_shortcut = IntProperty(
name="Shortcut",
description="Shortcuts font size (pixels)",
min=2,
default=11
)
feedback_shortcut_area = FloatVectorProperty(
name="Background Shortcut",
description="Shortcut area background color",
subtype='COLOR_GAMMA',
default=(0, 0.4, 0.6, 0.2),
size=4,
min=0, max=1
)
feedback_title_area = FloatVectorProperty(
name="Background Main",
description="Title area background color",
subtype='COLOR_GAMMA',
default=(0, 0.4, 0.6, 0.5),
size=4,
min=0, max=1
)
feedback_colour_main = FloatVectorProperty(
name="Font Main",
description="Title color",
subtype='COLOR_GAMMA',
default=(0.95, 0.95, 0.95, 1.0),
size=4,
min=0, max=1
)
feedback_colour_key = FloatVectorProperty(
name="Font Shortcut key",
description="KEY label color",
subtype='COLOR_GAMMA',
default=(0.67, 0.67, 0.67, 1.0),
size=4,
min=0, max=1
)
feedback_colour_shortcut = FloatVectorProperty(
name="Font Shortcut hint",
description="Shortcuts text color",
subtype='COLOR_GAMMA',
default=(0.51, 0.51, 0.51, 1.0),
size=4,
min=0, max=1
)
def draw(self, context):
layout = self.layout
box = layout.box()
row = box.row()
col = row.column()
col.label(text="Tab Category:")
col.prop(self, "tools_category")
col.prop(self, "create_category")
col.prop(self, "create_submenu")
col.prop(self, "max_style_draw_tool")
box = layout.box()
row = box.row()
split = row.split(percentage=0.5)
col = split.column()
col.label(text="Colors:")
row = col.row(align=True)
row.prop(self, "feedback_title_area")
row = col.row(align=True)
row.prop(self, "feedback_shortcut_area")
row = col.row(align=True)
row.prop(self, "feedback_colour_main")
row = col.row(align=True)
row.prop(self, "feedback_colour_key")
row = col.row(align=True)
row.prop(self, "feedback_colour_shortcut")
col = split.column()
col.label(text="Font size:")
col.prop(self, "feedback_size_main")
col.prop(self, "feedback_size_title")
col.prop(self, "feedback_size_shortcut")
col.label(text="Manipulators:")
col.prop(self, "arrow_size")
col.prop(self, "handle_size")
# ----------------------------------------------------
# Archipack panels
# ----------------------------------------------------
class TOOLS_PT_Archipack_PolyLib(Panel):
bl_label = "Archipack 2d to 3d"
bl_idname = "TOOLS_PT_Archipack_PolyLib"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_category = "Tools"
bl_context = "objectmode"
@classmethod
def poll(self, context):
global archipack_polylib
return HAS_POLYLIB and ((archipack_polylib.vars_dict['select_polygons'] is not None) or
(context.object is not None and context.object.type == 'CURVE'))
def draw(self, context):
global icons_collection
icons = icons_collection["main"]
layout = self.layout
row = layout.row(align=True)
box = row.box()
row = box.row(align=True)
row.operator(
"archipack.polylib_detect",
icon_value=icons["detect"].icon_id,
text='Detect'
).extend = context.window_manager.archipack_polylib.extend
row.prop(context.window_manager.archipack_polylib, "extend")
row = box.row(align=True)
row.prop(context.window_manager.archipack_polylib, "resolution")
row = box.row(align=True)
row.label(text="Polygons")
row = box.row(align=True)
row.operator(
"archipack.polylib_pick_2d_polygons",
icon_value=icons["selection"].icon_id,
text='Select'
).action = 'select'
row.operator(
"archipack.polylib_pick_2d_polygons",
icon_value=icons["union"].icon_id,
text='Union'
).action = 'union'
row.operator(
"archipack.polylib_output_polygons",
icon_value=icons["polygons"].icon_id,
text='All')
row = box.row(align=True)
row.operator(
"archipack.polylib_pick_2d_polygons",
text='Wall',
icon_value=icons["wall"].icon_id).action = 'wall'
row.prop(context.window_manager.archipack_polylib, "solidify_thickness")
row = box.row(align=True)
row.operator("archipack.polylib_pick_2d_polygons",
text='Window',
icon_value=icons["window"].icon_id).action = 'window'
row.operator("archipack.polylib_pick_2d_polygons",
text='Door',
icon_value=icons["door"].icon_id).action = 'door'
row.operator("archipack.polylib_pick_2d_polygons", text='Rectangle').action = 'rectangle'
row = box.row(align=True)
row.label(text="Lines")
row = box.row(align=True)
row.operator(
"archipack.polylib_pick_2d_lines",
icon_value=icons["selection"].icon_id,
text='Lines').action = 'select'
row.operator(
"archipack.polylib_pick_2d_lines",
icon_value=icons["union"].icon_id,
text='Union').action = 'union'
row.operator(
"archipack.polylib_output_lines",
icon_value=icons["polygons"].icon_id,
text='All')
row = box.row(align=True)
row.label(text="Points")
row = box.row(align=True)
row.operator(
"archipack.polylib_pick_2d_points",
icon_value=icons["selection"].icon_id,
text='Points').action = 'select'
row = layout.row(align=True)
box = row.box()
row = box.row(align=True)
row.operator("archipack.polylib_simplify")
row.prop(context.window_manager.archipack_polylib, "simplify_tolerance")
row = box.row(align=True)
row.prop(context.window_manager.archipack_polylib, "simplify_preserve_topology")
row = layout.row(align=True)
box = row.box()
row = box.row(align=True)
row.operator("archipack.polylib_offset")
row = box.row(align=True)
row.prop(context.window_manager.archipack_polylib, "offset_distance")
row = box.row(align=True)
row.prop(context.window_manager.archipack_polylib, "offset_side")
row = box.row(align=True)
row.prop(context.window_manager.archipack_polylib, "offset_resolution")
row = box.row(align=True)
row.prop(context.window_manager.archipack_polylib, "offset_join_style")
row = box.row(align=True)
row.prop(context.window_manager.archipack_polylib, "offset_mitre_limit")
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
row = layout.row(align=True)
box = row.box()
box.label("Auto boolean")
row = box.row(align=True)
row.operator("archipack.auto_boolean", text="AutoBoolean", icon='AUTO').mode = 'HYBRID'
row = layout.row(align=True)
box = row.box()
box.label("Rendering")
row = box.row(align=True)
row.prop(wm.archipack, 'render_type', text="")
row = box.row(align=True)
row.operator("archipack.render", icon='RENDER_STILL')
class TOOLS_PT_Archipack_Create(Panel):
bl_label = "Add Archipack"
bl_idname = "TOOLS_PT_Archipack_Create"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_category = "Create"
bl_context = "objectmode"
@classmethod
def poll(self, context):
return True
def draw(self, context):
global icons_collection
icons = icons_collection["main"]
layout = self.layout
row = layout.row(align=True)
box = row.box()
box.label("Objects")
row = box.row(align=True)
row.operator("archipack.window_preset_menu",
text="Window",
icon_value=icons["window"].icon_id
).preset_operator = "archipack.window"
row.operator("archipack.window_preset_menu",
text="",
icon='GREASEPENCIL'
).preset_operator = "archipack.window_draw"
row = box.row(align=True)
row.operator("archipack.door_preset_menu",
text="Door",
icon_value=icons["door"].icon_id
).preset_operator = "archipack.door"
row.operator("archipack.door_preset_menu",
text="",
icon='GREASEPENCIL'
).preset_operator = "archipack.door_draw"
row = box.row(align=True)
row.operator("archipack.stair_preset_menu",
text="Stair",
icon_value=icons["stair"].icon_id
).preset_operator = "archipack.stair"
row = box.row(align=True)
row.operator("archipack.wall2",
icon_value=icons["wall"].icon_id
)
row.operator("archipack.wall2_draw", text="Draw", icon='GREASEPENCIL')
row.operator("archipack.wall2_from_curve", text="", icon='CURVE_DATA')
row = box.row(align=True)
row.operator("archipack.fence_preset_menu",
text="Fence",
icon_value=icons["fence"].icon_id
).preset_operator = "archipack.fence"
row.operator("archipack.fence_from_curve", text="", icon='CURVE_DATA')
row = box.row(align=True)
row.operator("archipack.truss",
icon_value=icons["truss"].icon_id
)
row = box.row(align=True)
row.operator("archipack.slab_from_curve",
icon_value=icons["slab"].icon_id
)
row = box.row(align=True)
row.operator("archipack.wall2_from_slab",
icon_value=icons["wall"].icon_id)
row.operator("archipack.slab_from_wall",
icon_value=icons["slab"].icon_id
).ceiling = False
row.operator("archipack.slab_from_wall",
text="->Ceiling",
icon_value=icons["slab"].icon_id
).ceiling = True
row = box.row(align=True)
row.operator("archipack.floor_preset_menu",
text="Floor",
icon_value=icons["floor"].icon_id
).preset_operator = "archipack.floor"
# ----------------------------------------------------
# ALT + A menu
# ----------------------------------------------------
def draw_menu(self, context):
global icons_collection
icons = icons_collection["main"]
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("archipack.wall2",
text="Wall",
icon_value=icons["wall"].icon_id
)
layout.operator("archipack.window_preset_menu",
text="Window",
icon_value=icons["window"].icon_id
).preset_operator = "archipack.window"
layout.operator("archipack.door_preset_menu",
text="Door",
icon_value=icons["door"].icon_id
).preset_operator = "archipack.door"
layout.operator("archipack.stair_preset_menu",
text="Stair",
icon_value=icons["stair"].icon_id
).preset_operator = "archipack.stair"
layout.operator("archipack.fence_preset_menu",
text="Fence",
icon_value=icons["fence"].icon_id
).preset_operator = "archipack.fence"
layout.operator("archipack.truss",
text="Truss",
icon_value=icons["truss"].icon_id
)
layout.operator("archipack.floor_preset_menu",
text="Floor",
icon_value=icons["floor"].icon_id
)
class ARCHIPACK_create_menu(Menu):
bl_label = 'Archipack'
bl_idname = 'ARCHIPACK_create_menu'
bl_context = "objectmode"
def draw(self, context):
draw_menu(self, context)
def menu_func(self, context):
layout = self.layout
layout.separator()
global icons_collection
icons = icons_collection["main"]
# either draw sub menu or right at end of this one
if context.user_preferences.addons[__name__].preferences.create_submenu:
layout.operator_context = 'INVOKE_REGION_WIN'
layout.menu("ARCHIPACK_create_menu", icon_value=icons["archipack"].icon_id)
else:
draw_menu(self, context)
# ----------------------------------------------------
# Datablock to store global addon variables
# ----------------------------------------------------
class archipack_data(PropertyGroup):
render_type = EnumProperty(
items=(
('1', "Draw over", "Draw over last rendered image"),
('2', "OpenGL", ""),
('3', "Animation OpenGL", ""),
('4', "Image", "Render image and draw over"),
('5', "Animation", "Draw on each frame")
),
name="Render type",
description="Render method"
)
def register():
global icons_collection
icons = previews.new()
icons_dir = os.path.join(os.path.dirname(__file__), "icons")
for icon in os.listdir(icons_dir):
name, ext = os.path.splitext(icon)
icons.load(name, os.path.join(icons_dir, icon), 'IMAGE')
icons_collection["main"] = icons
archipack_snap.register()
archipack_manipulator.register()
archipack_reference_point.register()
archipack_autoboolean.register()
archipack_door.register()
archipack_window.register()
archipack_stair.register()
archipack_wall.register()
archipack_wall2.register()
archipack_slab.register()
archipack_fence.register()
archipack_truss.register()
archipack_floor.register()
archipack_rendering.register()
if HAS_POLYLIB:
archipack_polylib.register()
bpy.utils.register_class(archipack_data)
WindowManager.archipack = PointerProperty(type=archipack_data)
bpy.utils.register_class(Archipack_Pref)
update_panel(None, bpy.context)
bpy.utils.register_class(ARCHIPACK_create_menu)
bpy.types.INFO_MT_mesh_add.append(menu_func)
def unregister():
global icons_collection
bpy.types.INFO_MT_mesh_add.remove(menu_func)
bpy.utils.unregister_class(ARCHIPACK_create_menu)
bpy.utils.unregister_class(TOOLS_PT_Archipack_PolyLib)
bpy.utils.unregister_class(TOOLS_PT_Archipack_Tools)
bpy.utils.unregister_class(TOOLS_PT_Archipack_Create)
bpy.utils.unregister_class(Archipack_Pref)
# unregister subs
archipack_snap.unregister()
archipack_manipulator.unregister()
archipack_reference_point.unregister()
archipack_autoboolean.unregister()
archipack_door.unregister()
archipack_window.unregister()
archipack_stair.unregister()
archipack_wall.unregister()
archipack_wall2.unregister()
archipack_slab.unregister()
archipack_fence.unregister()
archipack_truss.unregister()
archipack_floor.unregister()
archipack_rendering.unregister()
if HAS_POLYLIB:
archipack_polylib.unregister()
bpy.utils.unregister_class(archipack_data)
del WindowManager.archipack
for icons in icons_collection.values():
previews.remove(icons)
icons_collection.clear()
if __name__ == "__main__":
register()
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
# -*- coding:utf-8 -*-
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# ----------------------------------------------------------
# Author: Stephen Leger (s-leger)
#
# ----------------------------------------------------------
import bpy
def create_handle(context, parent, mesh):
handle = bpy.data.objects.new("Handle", mesh)
handle['archipack_handle'] = True
context.scene.objects.link(handle)
modif = handle.modifiers.new('Subsurf', 'SUBSURF')
modif.render_levels = 4
modif.levels = 1
handle.parent = parent
handle.matrix_world = parent.matrix_world.copy()
return handle
def door_handle_horizontal_01(direction, side, offset=0):
"""
side 1 -> inside
"""
verts = [(0.015, -0.003, -0.107), (0.008, -0.002, -0.007), (0.015, -0.002, -0.107),
(0.019, -0.002, -0.026), (-0.015, -0.003, -0.107), (-0.007, -0.002, -0.007),
(-0.015, -0.002, -0.107), (-0.018, -0.002, -0.026), (0.008, -0.002, 0.007),
(0.019, -0.002, 0.034), (-0.018, -0.002, 0.034), (-0.007, -0.002, 0.007),
(-0.018, -0.003, -0.026), (0.019, -0.003, -0.026), (-0.018, -0.003, 0.034),
(0.019, -0.003, 0.034), (-0.007, -0.042, -0.007), (0.008, -0.042, -0.007),
(-0.007, -0.042, 0.007), (0.008, -0.042, 0.007), (-0.007, -0.047, -0.016),
(0.008, -0.048, -0.018), (-0.007, -0.047, 0.016), (0.008, -0.048, 0.018),
(-0.025, -0.041, 0.013), (-0.025, -0.041, -0.012), (-0.025, -0.048, 0.013),
(-0.025, -0.048, -0.012), (0.019, -0.0, -0.026), (0.015, -0.0, -0.107),
(-0.015, -0.0, -0.107), (-0.018, -0.0, -0.026), (0.019, 0.0, 0.034),
(-0.018, 0.0, 0.034), (-0.107, -0.041, 0.013), (-0.107, -0.041, -0.012),
(-0.107, -0.048, 0.013), (-0.107, -0.048, -0.012), (-0.12, -0.041, 0.013),
(-0.12, -0.041, -0.012), (-0.12, -0.048, 0.013), (-0.12, -0.048, -0.012),
(0.008, -0.005, -0.007), (0.008, -0.005, 0.007), (-0.007, -0.005, 0.007),
(-0.007, -0.005, -0.007), (0.008, -0.041, -0.007), (0.008, -0.041, 0.007),
(-0.007, -0.041, 0.007), (-0.007, -0.041, -0.007), (0.015, -0.003, -0.091),
(0.015, -0.002, -0.091), (-0.015, -0.002, -0.091), (-0.015, -0.003, -0.091),
(0.015, -0.0, -0.091), (-0.015, -0.0, -0.091), (0.015, -0.003, 0.044),
(0.015, -0.002, 0.044), (-0.015, -0.002, 0.044), (-0.015, -0.003, 0.044),
(0.015, 0.0, 0.044), (-0.015, 0.0, 0.044)]
faces = [(50, 51, 3, 13), (52, 55, 30, 6), (52, 53, 12, 7), (53, 50, 13, 12),
(2, 0, 4, 6), (10, 33, 31, 7), (15, 56, 59, 14), (12, 14, 10, 7),
(3, 9, 15, 13), (47, 19, 17, 46), (5, 12, 13, 1), (8, 15, 14, 11),
(11, 14, 12, 5), (1, 13, 15, 8), (22, 26, 27, 20), (48, 18, 19, 47),
(49, 16, 18, 48), (46, 17, 16, 49), (21, 23, 22, 20), (17, 21, 20, 16),
(19, 23, 21, 17), (18, 22, 23, 19), (24, 34, 36, 26), (16, 25, 24, 18),
(20, 27, 25, 16), (18, 24, 26, 22), (4, 0, 50, 53), (2, 29, 54, 51),
(6, 30, 29, 2), (10, 58, 61, 33), (3, 28, 32, 9), (51, 54, 28, 3),
(34, 38, 40, 36), (25, 35, 34, 24), (27, 37, 35, 25), (26, 36, 37, 27),
(39, 41, 40, 38), (35, 39, 38, 34), (37, 41, 39, 35), (36, 40, 41, 37),
(1, 42, 45, 5), (5, 45, 44, 11), (11, 44, 43, 8), (8, 43, 42, 1),
(42, 46, 49, 45), (45, 49, 48, 44), (44, 48, 47, 43), (43, 47, 46, 42),
(6, 4, 53, 52), (7, 31, 55, 52), (0, 2, 51, 50), (58, 59, 56, 57),
(57, 60, 61, 58), (32, 60, 57, 9), (14, 59, 58, 10), (9, 57, 56, 15)]
if side == 1:
if direction == 1:
verts = [(-v[0], -v[1], v[2]) for v in verts]
else:
verts = [(v[0], -v[1], v[2]) for v in verts]
faces = [tuple(reversed(f)) for f in faces]
else:
if direction == 1:
verts = [(-v[0], v[1], v[2]) for v in verts]
faces = [tuple(reversed(f)) for f in faces]
if offset > 0:
faces = [tuple([i + offset for i in f]) for f in faces]
return verts, faces
def window_handle_vertical_01(side):
"""
side 1 -> inside
short handle for flat window
"""
verts = [(-0.01, 0.003, 0.011), (-0.013, 0.0, -0.042), (-0.018, 0.003, 0.03), (-0.01, 0.003, -0.01),
(-0.018, 0.003, -0.038), (0.01, 0.003, 0.011), (0.018, 0.003, 0.03), (0.018, 0.003, -0.038),
(0.01, 0.003, -0.01), (-0.018, 0.004, -0.038), (-0.018, 0.004, 0.03), (0.018, 0.004, -0.038),
(0.018, 0.004, 0.03), (-0.01, 0.039, -0.01), (-0.01, 0.025, 0.011), (0.01, 0.036, -0.01),
(0.01, 0.025, 0.011), (-0.017, 0.049, -0.01), (-0.01, 0.034, 0.011), (0.017, 0.049, -0.01),
(0.01, 0.034, 0.011), (0.0, 0.041, -0.048), (0.013, 0.003, 0.033), (0.019, 0.057, -0.048),
(-0.019, 0.057, -0.048), (-0.018, 0.0, 0.03), (0.013, 0.0, -0.042), (0.013, 0.004, -0.042),
(-0.018, 0.0, -0.038), (0.018, 0.0, 0.03), (0.018, 0.0, -0.038), (0.001, 0.041, -0.126),
(-0.013, 0.004, 0.033), (0.019, 0.056, -0.126), (-0.019, 0.056, -0.126), (0.001, 0.036, -0.16),
(-0.013, 0.003, 0.033), (0.019, 0.051, -0.16), (-0.019, 0.051, -0.16), (-0.01, 0.006, 0.011),
(0.01, 0.006, 0.011), (0.01, 0.006, -0.01), (-0.01, 0.006, -0.01), (-0.01, 0.025, 0.011),
(0.01, 0.025, 0.011), (0.01, 0.035, -0.01), (-0.01, 0.038, -0.01), (0.013, 0.003, -0.042),
(-0.013, 0.0, 0.033), (-0.013, 0.004, -0.042), (-0.013, 0.003, -0.042), (0.013, 0.004, 0.033),
(0.013, 0.0, 0.033)]
faces = [(4, 2, 10, 9), (6, 12, 51, 22), (10, 2, 36, 32), (2, 25, 48, 36),
(27, 47, 50, 49), (7, 30, 26, 47), (28, 4, 50, 1), (12, 10, 32, 51),
(16, 14, 43, 44), (9, 10, 0, 3), (12, 11, 8, 5), (11, 9, 3, 8),
(10, 12, 5, 0), (23, 24, 17, 19), (15, 16, 44, 45), (13, 15, 45, 46),
(14, 13, 46, 43), (20, 19, 17, 18), (18, 17, 13, 14), (20, 18, 14, 16),
(19, 20, 16, 15), (31, 33, 23, 21), (21, 15, 13), (24, 21, 13, 17),
(21, 23, 19, 15), (9, 11, 27, 49), (26, 1, 50, 47), (4, 9, 49, 50),
(29, 6, 22, 52), (35, 37, 33, 31), (48, 52, 22, 36), (34, 31, 21, 24),
(33, 34, 24, 23), (38, 37, 35), (22, 51, 32, 36), (38, 35, 31, 34),
(37, 38, 34, 33), (39, 42, 3, 0), (42, 41, 8, 3), (41, 40, 5, 8),
(40, 39, 0, 5), (43, 46, 42, 39), (46, 45, 41, 42), (45, 44, 40, 41),
(44, 43, 39, 40), (28, 25, 2, 4), (12, 6, 7, 11), (7, 6, 29, 30),
(11, 7, 47, 27)]
if side == 0:
verts = [(v[0], -v[1], v[2]) for v in verts]
faces = [tuple(reversed(f)) for f in faces]
return verts, faces
def window_handle_vertical_02(side):
"""
side 1 -> inside
long handle for rail windows
"""
verts = [(-0.01, 0.003, 0.011), (-0.013, 0.0, -0.042), (-0.018, 0.003, 0.03), (-0.01, 0.003, -0.01),
(-0.018, 0.003, -0.038), (0.01, 0.003, 0.011), (0.018, 0.003, 0.03), (0.018, 0.003, -0.038),
(0.01, 0.003, -0.01), (-0.018, 0.004, -0.038), (-0.018, 0.004, 0.03), (0.018, 0.004, -0.038),
(0.018, 0.004, 0.03), (-0.01, 0.041, -0.01), (-0.01, 0.027, 0.011), (0.01, 0.038, -0.01),
(0.01, 0.027, 0.011), (-0.017, 0.054, -0.01), (-0.01, 0.039, 0.011), (0.017, 0.054, -0.01),
(0.01, 0.039, 0.011), (0.0, 0.041, -0.048), (0.013, 0.003, 0.033), (0.019, 0.059, -0.048),
(-0.019, 0.059, -0.048), (-0.018, 0.0, 0.03), (0.013, 0.0, -0.042), (0.013, 0.004, -0.042),
(-0.018, 0.0, -0.038), (0.018, 0.0, 0.03), (0.018, 0.0, -0.038), (0.001, 0.041, -0.322),
(-0.013, 0.004, 0.033), (0.019, 0.058, -0.322), (-0.019, 0.058, -0.322), (0.001, 0.036, -0.356),
(-0.013, 0.003, 0.033), (0.019, 0.053, -0.356), (-0.019, 0.053, -0.356), (-0.01, 0.006, 0.011),
(0.01, 0.006, 0.011), (0.01, 0.006, -0.01), (-0.01, 0.006, -0.01), (-0.01, 0.027, 0.011),
(0.01, 0.027, 0.011), (0.01, 0.037, -0.01), (-0.01, 0.04, -0.01), (0.013, 0.003, -0.042),
(-0.013, 0.0, 0.033), (-0.013, 0.004, -0.042), (-0.013, 0.003, -0.042), (0.013, 0.004, 0.033),
(0.013, 0.0, 0.033)]
faces = [(4, 2, 10, 9), (6, 12, 51, 22), (10, 2, 36, 32), (2, 25, 48, 36),
(27, 47, 50, 49), (7, 30, 26, 47), (28, 4, 50, 1), (12, 10, 32, 51),
(16, 14, 43, 44), (9, 10, 0, 3), (12, 11, 8, 5), (11, 9, 3, 8),
(10, 12, 5, 0), (23, 24, 17, 19), (15, 16, 44, 45), (13, 15, 45, 46),
(14, 13, 46, 43), (20, 19, 17, 18), (18, 17, 13, 14), (20, 18, 14, 16),
(19, 20, 16, 15), (31, 33, 23, 21), (21, 15, 13), (24, 21, 13, 17),
(21, 23, 19, 15), (9, 11, 27, 49), (26, 1, 50, 47), (4, 9, 49, 50),
(29, 6, 22, 52), (35, 37, 33, 31), (48, 52, 22, 36), (34, 31, 21, 24),
(33, 34, 24, 23), (38, 37, 35), (22, 51, 32, 36), (38, 35, 31, 34),
(37, 38, 34, 33), (39, 42, 3, 0), (42, 41, 8, 3), (41, 40, 5, 8),
(40, 39, 0, 5), (43, 46, 42, 39), (46, 45, 41, 42), (45, 44, 40, 41),
(44, 43, 39, 40), (28, 25, 2, 4), (12, 6, 7, 11), (7, 6, 29, 30),
(11, 7, 47, 27)]
if side == 0:
verts = [(v[0], -v[1], v[2]) for v in verts]
faces = [tuple(reversed(f)) for f in faces]
return verts, faces
# -*- coding:utf-8 -*-
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110- 1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# ----------------------------------------------------------
# Author: Stephen Leger (s-leger)
#
# ----------------------------------------------------------
class Keymaps:
"""
Expose user defined keymaps as event
so in modal operator we are able to
identify like
if (event == keymap.undo.event):
and in feedback panels:
keymap.undo.key
keymap.undo.name
"""
def __init__(self, context):
"""
Init keymaps properties
"""
# undo event
self.undo = self.get_event(context, 'Screen', 'ed.undo')
# delete event
self.delete = self.get_event(context, 'Object Mode', 'object.delete')
"""
# provide abstration between user and addon
# with different select mouse side
mouse_right = context.user_preferences.inputs.select_mouse
if mouse_right == 'LEFT':
mouse_left = 'RIGHT'
mouse_right_side = 'Left'
mouse_left_side = 'Right'
else:
mouse_left = 'LEFT'
mouse_right_side = 'Right'
mouse_left_side = 'Left'
self.leftmouse = mouse_left + 'MOUSE'
self.rightmouse = mouse_right + 'MOUSE'
"""
def check(self, event, against):
return against['event'] == (event.alt, event.ctrl, event.shift, event.type, event.value)
def get_event(self, context, keyconfig, keymap_item):
"""
Return simple keymaps event signature as dict
NOTE:
this won't work for complex keymaps such as select_all
using properties to call operator in different manner
type: keyboard main type
name: event name as defined in user preferences
event: simple event signature to compare like :
if event == keymap.undo.event:
"""
ev = context.window_manager.keyconfigs.user.keymaps[keyconfig].keymap_items[keymap_item]
key = ev.type
if ev.ctrl:
key += '+CTRL'
if ev.alt:
key += '+ALT'
if ev.shift:
key += '+SHIFT'
return {'type': key, 'name': ev.name, 'event': (ev.alt, ev.ctrl, ev.shift, ev.type, ev.value)}
def dump_keys(self, context, filename="c:\\tmp\\keymap.txt"):
"""
Utility for developpers :
Dump all keymaps to a file
filename : string a file path to dump keymaps
"""
str = ""
km = context.window_manager.keyconfigs.user.keymaps
for key in km.keys():
str += "\n\n#--------------------------------\n{}:\n#--------------------------------\n\n".format(key)
for sub in km[key].keymap_items.keys():
k = km[key].keymap_items[sub]
str += "alt:{} ctrl:{} shift:{} type:{} value:{} idname:{} name:{}\n".format(
k.alt, k.ctrl, k.shift, k.type, k.value, sub, k.name)
file = open(filename, "w")
file.write(str)
file.close()
This diff is collapsed.
# -*- coding:utf-8 -*-
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110- 1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# ----------------------------------------------------------
# Author: Stephen Leger (s-leger)
#
# ----------------------------------------------------------
# noinspection PyUnresolvedReferences
import bpy
# noinspection PyUnresolvedReferences
from bpy.props import BoolProperty, StringProperty
from mathutils import Vector, Matrix
from mathutils.geometry import (
intersect_line_plane
)
from bpy_extras.view3d_utils import (
region_2d_to_origin_3d,
region_2d_to_vector_3d
)
from .materialutils import MaterialUtils
class ArchipackObject():
"""
Shared property of archipack's objects PropertyGroup
provide basic support for copy to selected
and datablock access / filtering by object
"""
def iskindof(self, o, typ):
"""
return true if object contains databloc of typ name
"""
return o.data is not None and typ in o.data
@classmethod
def filter(cls, o):
"""
Filter object with this class in data
return
True when object contains this datablock
False otherwhise
usage:
class_name.filter(object) from outside world
self.__class__.filter(object) from instance
"""
try:
return cls.__name__ in o.data
except:
pass
return False
@classmethod
def datablock(cls, o):
"""
Retrieve datablock from base object
return
datablock when found
None when not found
usage:
class_name.datablock(object) from outside world
self.__class__.datablock(object) from instance
"""
try:
return getattr(o.data, cls.__name__)[0]
except:
pass
return None
def find_in_selection(self, context, auto_update=True):
"""
find witch selected object this datablock instance belongs to
store context to be able to restore after oops
provide support for "copy to selected"
return
object or None when instance not found in selected objects
"""
if auto_update is False:
return None
active = context.active_object
selected = [o for o in context.selected_objects]
for o in selected:
if self.__class__.datablock(o) == self:
self.previously_selected = selected
self.previously_active = active
return o
return None
def restore_context(self, context):
# restore context
bpy.ops.object.select_all(action="DESELECT")
try:
for o in self.previously_selected:
o.select = True
except:
pass
self.previously_active.select = True
context.scene.objects.active = self.previously_active
self.previously_selected = None
self.previously_active = None
class ArchipackCreateTool():
"""
Shared property of archipack's create tool Operator
"""
auto_manipulate = BoolProperty(
name="Auto manipulate",
description="Enable object's manipulators after create",
options={'SKIP_SAVE'},
default=True
)
filepath = StringProperty(
options={'SKIP_SAVE'},
name="Preset",
description="Full filename of python preset to load at create time",
default=""
)
@property
def archipack_category(self):
"""
return target object name from ARCHIPACK_OT_object_name
"""
return self.bl_idname[13:]
def load_preset(self, d):
"""
Load python preset
preset: full filename.py with path
"""
d.auto_update = False
if self.filepath != "":
try:
# print("Archipack loading preset: %s" % d.auto_update)
bpy.ops.script.python_file_run(filepath=self.filepath)
# print("Archipack preset loaded auto_update: %s" % d.auto_update)
except:
print("Archipack unable to load preset file : %s" % (self.filepath))
pass
d.auto_update = True
def add_material(self, o):
try:
getattr(MaterialUtils, "add_" + self.archipack_category + "_materials")(o)
except:
print("Archipack MaterialUtils.add_%s_materials not found" % (self.archipack_category))
pass
def manipulate(self):
if self.auto_manipulate:
try:
op = getattr(bpy.ops.archipack, self.archipack_category + "_manipulate")
if op.poll():
op('INVOKE_DEFAULT')
except:
print("Archipack bpy.ops.archipack.%s_manipulate not found" % (self.archipack_category))
pass
class ArchpackDrawTool():
"""
Draw tools
"""
def mouse_to_plane(self, context, event, origin=Vector((0, 0, 0)), normal=Vector((0, 0, 1))):
"""
convert mouse pos to 3d point over plane defined by origin and normal
"""
region = context.region
rv3d = context.region_data
co2d = (event.mouse_region_x, event.mouse_region_y)
view_vector_mouse = region_2d_to_vector_3d(region, rv3d, co2d)
ray_origin_mouse = region_2d_to_origin_3d(region, rv3d, co2d)
pt = intersect_line_plane(ray_origin_mouse, ray_origin_mouse + view_vector_mouse,
origin, normal, False)
# fix issue with parallel plane
if pt is None:
pt = intersect_line_plane(ray_origin_mouse, ray_origin_mouse + view_vector_mouse,
origin, view_vector_mouse, False)
return pt
def mouse_to_scene_raycast(self, context, event):
"""
convert mouse pos to 3d point over plane defined by origin and normal
"""
region = context.region
rv3d = context.region_data
co2d = (event.mouse_region_x, event.mouse_region_y)
view_vector_mouse = region_2d_to_vector_3d(region, rv3d, co2d)
ray_origin_mouse = region_2d_to_origin_3d(region, rv3d, co2d)
res, pos, normal, face_index, object, matrix_world = context.scene.ray_cast(
ray_origin_mouse,
view_vector_mouse)
return res, pos, normal, face_index, object, matrix_world
def mouse_hover_wall(self, context, event):
"""
convert mouse pos to matrix at bottom of surrounded wall, y oriented outside wall
"""
res, pt, y, i, o, tM = self.mouse_to_scene_raycast(context, event)
if res and o.data is not None and 'archipack_wall2' in o.data:
z = Vector((0, 0, 1))
d = o.data.archipack_wall2[0]
y = -y
pt += (0.5 * d.width) * y.normalized()
x = y.cross(z)
return True, Matrix([
[x.x, y.x, z.x, pt.x],
[x.y, y.y, z.y, pt.y],
[x.z, y.z, z.z, o.matrix_world.translation.z],
[0, 0, 0, 1]
]), o, y
return False, Matrix(), None, Vector()
This diff is collapsed.
This diff is collapsed.
# -*- coding:utf-8 -*-
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110- 1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# ----------------------------------------------------------
# Author: Stephen Leger (s-leger)
#
# ----------------------------------------------------------
import bpy
from bpy.types import Operator, PropertyGroup, Object, Panel
from bpy.props import (
FloatVectorProperty,
CollectionProperty,
FloatProperty
)
from mathutils import Vector
from .bmesh_utils import BmeshEdit as bmed
def update(self, context):
self.update(context)
class archipack_reference_point(PropertyGroup):
location_2d = FloatVectorProperty(
subtype='XYZ',
name="position 2d",
default=Vector((0, 0, 0))
)
location_3d = FloatVectorProperty(
subtype='XYZ',
name="position 3d",
default=Vector((0, 0, 0))
)
symbol_scale = FloatProperty(
name="Screen scale",
default=1,
min=0.01,
update=update)
@classmethod
def filter(cls, o):
"""
Filter object with this class in data
return
True when object contains this datablock
False otherwhise
usage:
class_name.filter(object) from outside world
self.__class__.filter(object) from instance
"""
try:
return cls.__name__ in o
except:
pass
return False
@classmethod
def datablock(cls, o):
"""
Retrieve datablock from base object
return
datablock when found
None when not found
usage:
class_name.datablock(object) from outside world
self.__class__.datablock(object) from instance
"""
try:
return getattr(o, cls.__name__)[0]
except:
pass
return None
def update(self, context):
o = context.active_object
if self.datablock(o) != self:
return
s = self.symbol_scale
verts = [(s * x, s * y, s * z) for x, y, z in [
(-0.25, 0.25, 0.0), (0.25, 0.25, 0.0), (-0.25, -0.25, 0.0), (0.25, -0.25, 0.0),
(0.0, 0.0, 0.487), (-0.107, 0.107, 0.216), (0.108, 0.107, 0.216), (-0.107, -0.107, 0.216),
(0.108, -0.107, 0.216), (-0.05, 0.05, 0.5), (0.05, 0.05, 0.5), (0.05, -0.05, 0.5),
(-0.05, -0.05, 0.5), (-0.193, 0.193, 0.0), (0.193, 0.193, 0.0), (0.193, -0.193, 0.0),
(-0.193, -0.193, 0.0), (0.0, 0.0, 0.8), (0.0, 0.8, -0.0), (0.0, 0.0, -0.0),
(0.0, 0.0, 0.0), (0.05, 0.05, 0.674), (-0.05, 0.674, -0.05), (0.0, 0.8, -0.0),
(-0.05, -0.05, 0.674), (-0.05, 0.674, 0.05), (0.05, 0.674, -0.05), (-0.129, 0.129, 0.162),
(0.129, 0.129, 0.162), (-0.129, -0.129, 0.162), (0.129, -0.129, 0.162), (0.0, 0.0, 0.8),
(-0.05, 0.05, 0.674), (0.05, -0.05, 0.674), (0.05, 0.674, 0.05), (0.8, -0.0, -0.0),
(0.0, -0.0, -0.0), (0.674, 0.05, -0.05), (0.8, -0.0, -0.0), (0.674, 0.05, 0.05),
(0.674, -0.05, -0.05), (0.674, -0.05, 0.05)]]
edges = [(1, 0), (0, 9), (9, 10), (10, 1), (3, 1), (10, 11),
(11, 3), (2, 3), (11, 12), (12, 2), (0, 2), (12, 9),
(6, 5), (8, 6), (7, 8), (5, 7), (17, 24), (17, 20),
(18, 25), (18, 19), (13, 14), (14, 15), (15, 16), (16, 13),
(4, 6), (15, 30), (17, 21), (26, 22), (23, 22), (23, 34),
(18, 26), (28, 27), (30, 28), (29, 30), (27, 29), (14, 28),
(13, 27), (16, 29), (4, 7), (4, 8), (4, 5), (31, 33),
(31, 32), (21, 32), (24, 32), (24, 33), (21, 33), (25, 22),
(25, 34), (26, 34), (35, 39), (35, 36), (40, 37), (38, 37),
(38, 41), (35, 40), (39, 37), (39, 41), (40, 41)]
bm = bmed._start(context, o)
bm.clear()
for v in verts:
bm.verts.new(v)
bm.verts.ensure_lookup_table()
for ed in edges:
bm.edges.new((bm.verts[ed[0]], bm.verts[ed[1]]))
bmed._end(bm, o)
class ARCHIPACK_PT_reference_point(Panel):
bl_idname = "ARCHIPACK_PT_reference_point"
bl_label = "Reference point"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = 'ArchiPack'
@classmethod
def poll(cls, context):
return archipack_reference_point.filter(context.active_object)
def draw(self, context):
o = context.active_object
props = archipack_reference_point.datablock(o)
if props is None:
return
layout = self.layout
if (o.location - props.location_2d).length < 0.01:
layout.operator('archipack.move_to_3d')
layout.operator('archipack.move_2d_reference_to_cursor')
else:
layout.operator('archipack.move_to_2d')
layout.prop(props, 'symbol_scale')
class ARCHIPACK_OT_reference_point(Operator):
"""Add reference point"""
bl_idname = "archipack.reference_point"
bl_label = "Reference point"
bl_description = "Add reference point"
bl_category = 'Archipack'
bl_options = {'REGISTER', 'UNDO'}
location_3d = FloatVectorProperty(
subtype='XYZ',
name="position 3d",
default=Vector((0, 0, 0))
)
@classmethod
def poll(cls, context):
return context.active_object is not None
def draw(self, context):
layout = self.layout
row = layout.row()
row.label("Use Properties panel (N) to define parms", icon='INFO')
def create(self, context):
x, y, z = context.scene.cursor_location
# bpy.ops.object.empty_add(type='ARROWS', radius=0.5, location=Vector((x, y, 0)))
m = bpy.data.meshes.new(name="Reference")
o = bpy.data.objects.new("Reference", m)
o.location = Vector((x, y, 0))
context.scene.objects.link(o)
d = o.archipack_reference_point.add()
d.location_2d = Vector((x, y, 0))
d.location_3d = self.location_3d
o.select = True
context.scene.objects.active = o
d.update(context)
return o
def execute(self, context):
if context.mode == "OBJECT":
o = self.create(context)
o.select = True
context.scene.objects.active = o
return {'FINISHED'}
else:
self.report({'WARNING'}, "Archipack: Option only valid in Object mode")
return {'CANCELLED'}
class ARCHIPACK_OT_move_to_3d(Operator):
bl_idname = "archipack.move_to_3d"
bl_label = "Move to 3d"
bl_description = "Move point to 3d position"
bl_category = 'Archipack'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return archipack_reference_point.filter(context.active_object)
def execute(self, context):
if context.mode == "OBJECT":
o = context.active_object
props = archipack_reference_point.datablock(o)
if props is None:
return {'CANCELLED'}
o.location = props.location_3d
return {'FINISHED'}
else:
self.report({'WARNING'}, "Archipack: Option only valid in Object mode")
return {'CANCELLED'}
class ARCHIPACK_OT_move_to_2d(Operator):
bl_idname = "archipack.move_to_2d"
bl_label = "Move to 2d"
bl_description = "Move point to 2d position"
bl_category = 'Archipack'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return archipack_reference_point.filter(context.active_object)
def execute(self, context):
if context.mode == "OBJECT":
o = context.active_object
props = archipack_reference_point.datablock(o)
if props is None:
return {'CANCELLED'}
props.location_3d = o.location
o.location = props.location_2d
return {'FINISHED'}
else:
self.report({'WARNING'}, "Archipack: Option only valid in Object mode")
return {'CANCELLED'}
class ARCHIPACK_OT_store_2d_reference(Operator):
bl_idname = "archipack.store_2d_reference"
bl_label = "Set 2d"
bl_description = "Set 2d reference position"
bl_category = 'Archipack'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return archipack_reference_point.filter(context.active_object)
def execute(self, context):
if context.mode == "OBJECT":
o = context.active_object
props = archipack_reference_point.datablock(o)
if props is None:
return {'CANCELLED'}
x, y, z = o.location
props.location_2d = Vector((x, y, 0))
return {'FINISHED'}
else:
self.report({'WARNING'}, "Archipack: Option only valid in Object mode")
return {'CANCELLED'}
class ARCHIPACK_OT_move_2d_reference_to_cursor(Operator):
bl_idname = "archipack.move_2d_reference_to_cursor"
bl_label = "Change 2d"
bl_description = "Change 2d reference position to cursor location without moving childs"
bl_category = 'Archipack'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return archipack_reference_point.filter(context.active_object)
def execute(self, context):
if context.mode == "OBJECT":
o = context.active_object
props = archipack_reference_point.datablock(o)
if props is None:
return {'CANCELLED'}
bpy.ops.object.select_all(action="DESELECT")
bpy.ops.archipack.reference_point(location_3d=props.location_3d)
for child in o.children:
child.select = True
bpy.ops.archipack.parent_to_reference()
context.scene.objects.unlink(o)
return {'FINISHED'}
else:
self.report({'WARNING'}, "Archipack: Option only valid in Object mode")
return {'CANCELLED'}
class ARCHIPACK_OT_parent_to_reference(Operator):
bl_idname = "archipack.parent_to_reference"
bl_label = "Parent"
bl_description = "Make selected object childs of parent reference point"
bl_category = 'Archipack'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return archipack_reference_point.filter(context.active_object)
def execute(self, context):
if context.mode == "OBJECT":
o = context.active_object
props = archipack_reference_point.datablock(o)
if props is None:
return {'CANCELLED'}
sel = [obj for obj in context.selected_objects if obj != o and obj.parent != o]
itM = o.matrix_world.inverted()
# print("parent_to_reference parenting:%s objects" % (len(sel)))
for child in sel:
rs = child.matrix_world.to_3x3().to_4x4()
loc = itM * child.matrix_world.translation
child.parent = None
child.matrix_parent_inverse.identity()
child.location = Vector((0, 0, 0))
child.parent = o
child.matrix_world = rs
child.location = loc
return {'FINISHED'}
else:
self.report({'WARNING'}, "Archipack: Option only valid in Object mode")
return {'CANCELLED'}
def register():
bpy.utils.register_class(archipack_reference_point)
Object.archipack_reference_point = CollectionProperty(type=archipack_reference_point)
bpy.utils.register_class(ARCHIPACK_PT_reference_point)
bpy.utils.register_class(ARCHIPACK_OT_reference_point)
bpy.utils.register_class(ARCHIPACK_OT_move_to_3d)
bpy.utils.register_class(ARCHIPACK_OT_move_to_2d)
bpy.utils.register_class(ARCHIPACK_OT_store_2d_reference)
bpy.utils.register_class(ARCHIPACK_OT_move_2d_reference_to_cursor)
bpy.utils.register_class(ARCHIPACK_OT_parent_to_reference)
def unregister():
bpy.utils.unregister_class(archipack_reference_point)
del Object.archipack_reference_point
bpy.utils.unregister_class(ARCHIPACK_PT_reference_point)
bpy.utils.unregister_class(ARCHIPACK_OT_reference_point)
bpy.utils.unregister_class(ARCHIPACK_OT_move_to_3d)
bpy.utils.unregister_class(ARCHIPACK_OT_move_to_2d)
bpy.utils.unregister_class(ARCHIPACK_OT_store_2d_reference)
bpy.utils.unregister_class(ARCHIPACK_OT_move_2d_reference_to_cursor)
bpy.utils.unregister_class(ARCHIPACK_OT_parent_to_reference)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment