This commit is contained in:
Andrej730
2025-07-24 19:14:26 +05:00
parent cfd5d2a4eb
commit 05a8824019
22 changed files with 258 additions and 139 deletions
+21 -13
View File
@@ -381,7 +381,7 @@ class PolylineDecorator:
start = self.polyline_points[0]
if len(self.polyline_points) == 1:
end = context.scene.BIMPolylineProperties.snap_mouse_point[0]
end = tool.Model.get_polyline_props().snap_mouse_point[0]
else:
end = self.polyline_points[1]
@@ -632,14 +632,16 @@ class PolylineDecorator:
self.draw_batch("LINES", polyline_verts, self.decorator_color_special, polyline_edges)
def get_polylines_data(self, context):
self.measure_type = context.scene.MeasureToolSettings.measurement_type
self.polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
self.measure_data = context.scene.BIMPolylineProperties.measurement_polyline
self.measure_type = tool.Project.get_measure_tool_settings().measurement_type
polyline_props = tool.Model.get_polyline_props()
self.polyline_data = polyline_props.insertion_polyline
self.measure_data = polyline_props.measurement_polyline
def select_and_draw_measurements_text(self, context):
self.get_polylines_data(context)
if self.polyline_data:
self.polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
polyline_props = tool.Model.get_polyline_props()
self.polyline_data = polyline_props.insertion_polyline[0]
self.polyline_points = self.polyline_data.polyline_points
self.draw_measurements_text(context)
@@ -653,7 +655,8 @@ class PolylineDecorator:
def select_and_draw_measurements_poly(self, context):
self.get_polylines_data(context)
if self.polyline_data:
self.polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
polyline_props = tool.Model.get_polyline_props()
self.polyline_data = polyline_props.insertion_polyline[0]
self.polyline_points = self.polyline_data.polyline_points
self.draw_measurements_poly(context)
@@ -676,11 +679,12 @@ class PolylineDecorator:
region = context.region
rv3d = region.data
snap_prop = context.scene.BIMPolylineProperties.snap_mouse_point[0]
polyline_props = tool.Model.get_polyline_props()
snap_prop = polyline_props.snap_mouse_point[0]
mouse_point = Vector((snap_prop.x, snap_prop.y, snap_prop.z))
try:
snap_prop = context.scene.BIMPolylineProperties.snap_mouse_ref[0]
snap_prop = polyline_props.snap_mouse_ref[0]
mouse_point = Vector((snap_prop.x, snap_prop.y, snap_prop.z))
except:
pass
@@ -742,7 +746,8 @@ class PolylineDecorator:
self.shader = gpu.shader.from_builtin("UNIFORM_COLOR")
gpu.state.point_size_set(6)
snap_prop = context.scene.BIMPolylineProperties.snap_mouse_point[0]
polyline_props = tool.Model.get_polyline_props()
snap_prop = polyline_props.snap_mouse_point[0]
# Point related to the mouse
mouse_point = [Vector((snap_prop.x, snap_prop.y, snap_prop.z))]
@@ -815,9 +820,10 @@ class PolylineDecorator:
self.draw_batch("LINES", axis2, highlight_color(axis_color2), [(0, 1)])
# Create polyline with selected points
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
if polyline_data:
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
polyline_data = polyline_props.insertion_polyline[0]
polyline_points = polyline_data.polyline_points
else:
polyline_points = []
@@ -927,7 +933,8 @@ class ProductDecorator:
self.shader = gpu.shader.from_builtin("UNIFORM_COLOR")
self.line_shader.uniform_float("lineWidth", 2.0)
decorator_color = self.addon_prefs.decorator_color_special
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
self.relating_type = None
@@ -1114,7 +1121,8 @@ class FaceAreaDecorator:
gpu.state.blend_set("ALPHA")
decorator_color = self.addon_prefs.decorator_color_special
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
for i, polyline in enumerate(polyline_data):
vertices = []
for point in polyline.polyline_points:
+15 -8
View File
@@ -92,7 +92,8 @@ def get_wall_preview_data(context, relating_type):
# Verts
polyline_vertices = []
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
if len(polyline_points) < 2:
data = []
@@ -212,7 +213,8 @@ def get_slab_preview_data(context, relating_type):
data["verts"] = []
# Verts
polyline_vertices = []
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
if len(polyline_points) < 3:
data = []
@@ -340,7 +342,8 @@ def get_vertical_profile_preview_data(
tris = [[loop.vert.index for loop in triangles] for triangles in bm.calc_loop_triangles()]
# Calculate rotation, mouse position, angle and cardinal point
snap_prop = context.scene.BIMPolylineProperties.snap_mouse_point[0]
polyline_props = tool.Model.get_polyline_props()
snap_prop = polyline_props.snap_mouse_point[0]
mouse_point = Vector((snap_prop.x, snap_prop.y, snap_prop.z))
data = {}
@@ -384,7 +387,8 @@ def get_horizontal_profile_preview_data(
cardinal_point = model_props.cardinal_point
polyline_verts = []
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
if len(polyline_points) < 2:
return {}
@@ -530,7 +534,8 @@ def get_generic_product_preview_data(context, relating_type):
rl = float(model_props.rl2)
else:
rl = 0
snap_prop = context.scene.BIMPolylineProperties.snap_mouse_point[0]
polyline_props = tool.Model.get_polyline_props()
snap_prop = polyline_props.snap_mouse_point[0]
default_container_elevation = tool.Root.get_default_container_elevation()
mouse_point = Vector((snap_prop.x, snap_prop.y, default_container_elevation))
snap_obj = bpy.data.objects.get(snap_prop.snap_object)
@@ -646,7 +651,8 @@ class PolylineOperator:
def choose_plane(self, event: bpy.types.Event, x: bool = True, y: bool = True, z: bool = True) -> None:
def get_plane_origin():
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
if len(polyline_points) > 0:
reference_point = polyline_points[-1]
@@ -824,7 +830,8 @@ class PolylineOperator:
if event.value == "PRESS" and event.type == "C":
# Get the first point coordinates to close the polyline
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
if len(polyline_points) > 2:
first_point = polyline_points[0]
@@ -832,7 +839,7 @@ class PolylineOperator:
if not (
first_point.x == last_point.x and first_point.y == last_point.y and first_point.z == last_point.z
):
mouse_point = context.scene.BIMPolylineProperties.snap_mouse_point[0]
mouse_point = polyline_props.snap_mouse_point[0]
mouse_point.x = first_point.x
mouse_point.y = first_point.y
if self.input_ui.get_number_value("Z") is not None:
@@ -180,7 +180,8 @@ class DrawOccurrence(bpy.types.Operator, PolylineOperator, tool.Ifc.Operator):
# TODO: when this workflow matures a bit, recode it so it doesn't rely on selection and cursor
# Select snapped object so we can insert doors and windows
snap_prop = context.scene.BIMPolylineProperties.snap_mouse_point[0]
polyline_props = tool.Model.get_polyline_props()
snap_prop = polyline_props.snap_mouse_point[0]
snap_obj = bpy.data.objects.get(snap_prop.snap_object)
if snap_obj:
try:
@@ -193,7 +194,7 @@ class DrawOccurrence(bpy.types.Operator, PolylineOperator, tool.Ifc.Operator):
except:
pass
point = context.scene.BIMPolylineProperties.insertion_polyline[0].polyline_points[0]
point = polyline_props.insertion_polyline[0].polyline_points[0]
context.scene.cursor.location = Vector((point.x, point.y, point.z))
tool.Polyline.clear_polyline()
@@ -545,7 +546,10 @@ class ChangeTypePage(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.change_type_page"
bl_label = "Change Type Page"
bl_options = {"REGISTER"}
page: bpy.props.IntProperty()
page: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
if TYPE_CHECKING:
page: int
def _execute(self, context):
props = tool.Model.get_model_props()
+20 -11
View File
@@ -40,7 +40,10 @@ from math import pi, degrees, atan2
from mathutils import Vector, Matrix
from bonsai.bim.module.model.decorator import ProfileDecorator, PolylineDecorator, ProductDecorator
from bonsai.bim.module.model.polyline import PolylineOperator
from typing import Union, Any, Optional
from typing import Union, Any, Optional, Literal
ProfileFrom2PointsReturn = Union[dict[str, Any], None]
class DumbProfileGenerator:
@@ -48,7 +51,9 @@ class DumbProfileGenerator:
self.relating_type = relating_type
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
def generate(self, insertion_type="CURSOR"):
def generate(
self, insertion_type: Literal["CURSOR", "POLYLINE"] = "CURSOR"
) -> Union[tuple[list[ProfileFrom2PointsReturn], bool], bpy.types.Object, None]:
self.insertion_type = insertion_type
self.file = tool.Ifc.get()
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
@@ -77,8 +82,9 @@ class DumbProfileGenerator:
elif self.insertion_type == "CURSOR":
return self.derive_from_cursor()
def derive_from_polyline(self) -> tuple[list[Union[dict[str, Any], None]], bool]:
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
def derive_from_polyline(self) -> tuple[list[ProfileFrom2PointsReturn], bool]:
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
is_polyline_closed = False
if len(polyline_points) > 3:
@@ -87,7 +93,7 @@ class DumbProfileGenerator:
if first_vec == last_vec:
is_polyline_closed = True
profiles = []
profiles: list[ProfileFrom2PointsReturn] = []
for i in range(len(polyline_points) - 1):
vec1 = Vector((polyline_points[i].x, polyline_points[i].y, polyline_points[i].z))
vec2 = Vector((polyline_points[i + 1].x, polyline_points[i + 1].y, polyline_points[i + 1].z))
@@ -95,11 +101,12 @@ class DumbProfileGenerator:
profiles.append(self.create_profile_from_2_points(coords))
return profiles, is_polyline_closed
def derive_from_cursor(self):
def derive_from_cursor(self) -> bpy.types.Object:
assert bpy.context.scene
self.location = bpy.context.scene.cursor.location
return self.create_profile()
def create_profile(self):
def create_profile(self) -> bpy.types.Object:
ifc_classes = ifcopenshell.util.type.get_applicable_entities(self.relating_type.is_a(), self.file.schema)
# Standard cases are deprecated, so let's cull them
ifc_class = next(c for c in ifc_classes if "StandardCase" not in c)
@@ -109,7 +116,7 @@ class DumbProfileGenerator:
matrix_world = Matrix()
if self.relating_type.is_a() not in ("IfcColumnType", "IfcPileType"):
if self.insertion_type not in {"POLYLINE"}:
if self.insertion_type != "POLYLINE":
matrix_world = Matrix.Rotation(pi / 2, 4, "Z") @ Matrix.Rotation(pi / 2, 4, "X") @ matrix_world
matrix_world = Matrix.Rotation(self.rotation, 4, "Z") @ matrix_world
else:
@@ -117,7 +124,7 @@ class DumbProfileGenerator:
matrix_world = rotation_matrix.to_matrix().to_4x4() @ matrix_world
matrix_world.translation = self.location
if self.insertion_type not in {"POLYLINE"} and self.container_obj:
if self.insertion_type != "POLYLINE" and self.container_obj:
matrix_world.translation.z = self.container_obj.location.z
element = bonsai.core.root.assign_class(
tool.Ifc,
@@ -171,12 +178,14 @@ class DumbProfileGenerator:
return obj
def create_profile_from_2_points(self, coords, should_round=False) -> Union[dict[str, Any], None]:
def create_profile_from_2_points(
self, coords: tuple[Vector, Vector], should_round: bool = False
) -> ProfileFrom2PointsReturn:
self.direction = coords[1] - coords[0]
length = self.direction.length
if round(length, 4) < 0.1:
return
data = {"coords": coords}
data: dict[str, Any] = {"coords": coords}
self.depth = length
self.rotation = atan2(self.direction[1], self.direction[0])
@@ -323,6 +323,13 @@ class BIMModelProperties(PropertyGroup):
show_wall_axis: bool
show_slab_direction: bool
prev_transform_orientation_slot_type: str
prev_show_gizmo_object_translate: bool
show_bounding_box: bool
show_cut_decorator: bool
show_cut_decorator_fill: bool
class BIMArrayProperties(PropertyGroup):
is_editing: bpy.props.IntProperty(
@@ -1157,6 +1164,13 @@ class SnapMousePoint(PropertyGroup):
snap_type: bpy.props.StringProperty(name="Snap Type")
snap_object: bpy.props.StringProperty(name="Object Name")
if TYPE_CHECKING:
x: float
y: float
z: float
snap_type: str
snap_object: str
class PolylinePoint(PropertyGroup):
x: bpy.props.FloatProperty(name="X")
@@ -1166,6 +1180,14 @@ class PolylinePoint(PropertyGroup):
angle: bpy.props.StringProperty(name="Angle")
position: bpy.props.FloatVectorProperty(name="Decorator Position", size=3)
if TYPE_CHECKING:
x: float
y: float
z: float
dim: str
angle: str
position: tuple[float, float, float]
class Polyline(PropertyGroup):
id: bpy.props.StringProperty(name="Id")
@@ -1174,6 +1196,13 @@ class Polyline(PropertyGroup):
area: bpy.props.StringProperty(name="Measured Area")
total_length: bpy.props.StringProperty(name="Total Length")
if TYPE_CHECKING:
id: str
polyline_points: bpy.types.bpy_prop_collection_idprop[PolylinePoint]
measurement_type: str
area: str
total_length: str
class BIMPolylineProperties(PropertyGroup):
snap_mouse_point: bpy.props.CollectionProperty(type=SnapMousePoint)
@@ -1181,17 +1210,32 @@ class BIMPolylineProperties(PropertyGroup):
insertion_polyline: bpy.props.CollectionProperty(type=Polyline)
measurement_polyline: bpy.props.CollectionProperty(type=Polyline)
if TYPE_CHECKING:
snap_mouse_point: bpy.types.bpy_prop_collection_idprop[SnapMousePoint]
snap_mouse_ref: bpy.types.bpy_prop_collection_idprop[SnapMousePoint]
insertion_polyline: bpy.types.bpy_prop_collection_idprop[Polyline]
measurement_polyline: bpy.types.bpy_prop_collection_idprop[Polyline]
class ProductPreviewItem(PropertyGroup):
value_3d: bpy.props.FloatVectorProperty()
value_2d: bpy.props.FloatVectorProperty(size=2)
if TYPE_CHECKING:
value_3d: tuple[float, float, float]
value_2d: tuple[float, float]
class BIMProductPreviewProperties(PropertyGroup):
verts: bpy.props.CollectionProperty(type=ProductPreviewItem)
edges: bpy.props.CollectionProperty(type=ProductPreviewItem)
tris: bpy.props.CollectionProperty(type=ProductPreviewItem)
if TYPE_CHECKING:
verts: bpy.types.bpy_prop_collection_idprop[ProductPreviewItem]
edges: bpy.types.bpy_prop_collection_idprop[ProductPreviewItem]
tris: bpy.types.bpy_prop_collection_idprop[ProductPreviewItem]
def update_is_editing(self: "BIMExternalParametricGeometryProperties", context: bpy.types.Context) -> None:
if self.is_editing:
+2 -1
View File
@@ -88,7 +88,8 @@ class DumbSlabGenerator:
return self.derive_from_cursor()
def derive_from_polyline(self):
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
self.location = Vector((polyline_points[0].x, polyline_points[0].y, self.container_obj.location.z))
self.polyline = [tuple(Vector((p.x, p.y, 0.0)) - self.location) for p in polyline_points]
+7 -4
View File
@@ -163,7 +163,8 @@ class ExtendWallsToPolylinePoint(bpy.types.Operator, PolylineOperator, tool.Ifc.
PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0])
tool.Blender.update_viewport()
# Point related to the mouse
snap_prop = context.scene.BIMPolylineProperties.snap_mouse_point[0]
polyline_props = tool.Model.get_polyline_props()
snap_prop = polyline_props.snap_mouse_point[0]
mouse_point = Vector((snap_prop.x, snap_prop.y, snap_prop.z))
angle = atan2(direcion.y, direcion.x)
@@ -214,13 +215,14 @@ class ExtendWallsToPolylinePoint(bpy.types.Operator, PolylineOperator, tool.Ifc.
if result:
self.report({"WARNING"}, result)
snap_prop = context.scene.BIMPolylineProperties.snap_mouse_point[0]
polyline_props = tool.Model.get_polyline_props()
snap_prop = polyline_props.snap_mouse_point[0]
snap_obj = bpy.data.objects.get(snap_prop.snap_object)
if snap_obj and tool.Ifc.get_entity(snap_obj).is_a("IfcWall"):
tool.Blender.set_active_object(snap_obj)
ExtendWallsToWall._execute(self, context)
else:
point = context.scene.BIMPolylineProperties.insertion_polyline[0].polyline_points[1]
point = polyline_props.insertion_polyline[0].polyline_points[1]
core.extend_walls(
tool.Ifc,
tool.Blender,
@@ -867,7 +869,8 @@ class DumbWallGenerator:
return self.derive_from_cursor()
def derive_from_polyline(self) -> tuple[list[Union[dict[str, Any], None]], bool]:
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
is_polyline_closed = False
if len(polyline_points) > 3:
@@ -2625,11 +2625,11 @@ class MeasureTool(bpy.types.Operator, PolylineOperator):
self.handle_snap_selection(context, event)
single_mode = False
polyline_props = tool.Model.get_polyline_props()
if (
self.measure_type == "SINGLE"
and context.scene.BIMPolylineProperties.insertion_polyline
and len(context.scene.BIMPolylineProperties.insertion_polyline[0].polyline_points) >= 2
and polyline_props.insertion_polyline
and len(polyline_props.insertion_polyline[0].polyline_points) >= 2
):
single_mode = True
@@ -2652,19 +2652,19 @@ class MeasureTool(bpy.types.Operator, PolylineOperator):
self.handle_inserting_polyline(context, event)
# Add measurement type to the insertion polyline
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
polyline_data = polyline_props.insertion_polyline
if not polyline_data:
pass
else:
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
measurement_type = bpy.context.scene.MeasureToolSettings.measurement_type
polyline_data = polyline_props.insertion_polyline[0]
measurement_type = tool.Project.get_measure_tool_settings().measurement_type
if not polyline_data.measurement_type:
polyline_data.measurement_type = measurement_type
tool.Polyline.calculate_area(context, self.input_ui)
if event.type == "E":
context.scene.BIMPolylineProperties.measurement_polyline.clear()
polyline_props.measurement_polyline.clear()
MeasureDecorator.uninstall()
tool.Blender.update_viewport()
@@ -2727,6 +2727,7 @@ class MeasureFaceAreaTool(bpy.types.Operator, PolylineOperator):
return {"PASS_THROUGH"}
self.handle_mouse_move(context, event)
polyline_props = tool.Model.get_polyline_props()
if event.value == "PRESS" and event.type == "LEFTMOUSE":
tool.Blender.update_viewport()
@@ -2737,7 +2738,7 @@ class MeasureFaceAreaTool(bpy.types.Operator, PolylineOperator):
self.clicked_faces.append(obj.data.polygons[face_index])
self.total_area += obj.data.polygons[face_index].area
self.input_ui.set_value("AREA", self.total_area)
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline.add()
polyline_data = polyline_props.insertion_polyline.add()
polyline_data.id = obj.name + str(face_index)
for v_id in obj.data.polygons[face_index].vertices:
vertex = obj.matrix_world @ obj.data.vertices[v_id].co
@@ -2755,14 +2756,14 @@ class MeasureFaceAreaTool(bpy.types.Operator, PolylineOperator):
self.clicked_faces.remove(obj.data.polygons[face_index])
self.total_area -= obj.data.polygons[face_index].area
self.input_ui.set_value("AREA", self.total_area)
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_data = polyline_props.insertion_polyline
for i, polyline in enumerate(polyline_data):
if polyline.id == obj.name + str(face_index):
polyline_data.remove(i)
tool.Blender.update_viewport()
if event.value == "RELEASE" and event.type in {"ESC", "RIGHTMOUSE"}:
bpy.context.scene.BIMPolylineProperties.insertion_polyline.clear()
polyline_props.insertion_polyline.clear()
context.workspace.status_text_set(text=None)
PolylineDecorator.uninstall()
FaceAreaDecorator.uninstall()
@@ -2786,10 +2787,12 @@ class ClearMeasurement(bpy.types.Operator):
@classmethod
def poll(cls, context):
return len(context.scene.BIMPolylineProperties.measurement_polyline) > 0
polyline_props = tool.Model.get_polyline_props()
return len(polyline_props.measurement_polyline) > 0
def execute(self, context):
context.scene.BIMPolylineProperties.measurement_polyline.clear()
polyline_props = tool.Model.get_polyline_props()
polyline_props.measurement_polyline.clear()
MeasureDecorator.uninstall()
tool.Blender.update_viewport()
return {"FINISHED"}
@@ -59,7 +59,7 @@ class ExploreTool(bpy.types.WorkSpaceTool):
row.label(text="", icon="EVENT_ALT")
row.label(text="Disable Culling" if LinksData.enable_culling else "Enable Culling", icon="EVENT_C")
prop = context.scene.MeasureToolSettings
prop = tool.Project.get_measure_tool_settings()
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_M")
@@ -105,7 +105,7 @@ class ExploreHotkey(bpy.types.Operator):
def hotkey_S_M(self):
for obj in tool.Blender.get_selected_objects():
obj.select_set(False)
measure_type = bpy.context.scene.MeasureToolSettings.measurement_type
measure_type = tool.Project.get_measure_tool_settings().measurement_type
if measure_type == "FACE_AREA":
bpy.ops.bim.measure_face_area_tool("INVOKE_DEFAULT")
else:
@@ -646,10 +646,11 @@ class EditWorkCalendar(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
props = tool.Sequence.get_work_calendar_props()
core.edit_work_calendar(
tool.Ifc,
tool.Sequence,
work_calendar=tool.Ifc.get().by_id(context.scene.BIMWorkCalendarProperties.active_work_calendar_id),
work_calendar=tool.Ifc.get().by_id(props.active_work_calendar_id),
)
+3 -1
View File
@@ -1021,11 +1021,13 @@ class BIM_PT_work_calendars(Panel):
file = tool.Ifc.get()
return file and hasattr(file, "schema") and file.schema != "IFC2X3"
layout: bpy.types.UILayout
def draw(self, context):
if not SequenceData.is_loaded:
SequenceData.load()
self.props = context.scene.BIMWorkCalendarProperties
self.props = tool.Sequence.get_work_calendar_props()
row = self.layout.row()
if SequenceData.data["has_work_calendars"]:
row.label(
+6
View File
@@ -65,6 +65,7 @@ if TYPE_CHECKING:
BIMStairProperties,
BIMRailingProperties,
BIMExternalParametricGeometryProperties,
BIMPolylineProperties,
)
@@ -101,6 +102,11 @@ class Model(bonsai.core.tool.Model):
def get_epg_props(cls, obj: bpy.types.Object) -> BIMExternalParametricGeometryProperties:
return obj.BIMExternalParametricGeometryProperties
@classmethod
def get_polyline_props(cls) -> BIMPolylineProperties:
assert (scene := bpy.context.scene)
return scene.BIMPolylineProperties # pyright: ignore[reportAttributeAccessIssue]
@classmethod
def convert_si_to_unit(cls, value: T) -> T:
if isinstance(value, (tuple, list)):
+22 -14
View File
@@ -106,7 +106,8 @@ class Polyline(bonsai.core.tool.Polyline):
cls, context: bpy.types.Context, input_ui: PolylineUI, tool_state: ToolState, should_round: bool = False
) -> None:
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
if len(polyline_data) > 0:
polyline_data = polyline_data[0]
polyline_points = polyline_data.polyline_points
@@ -123,7 +124,7 @@ class Polyline(bonsai.core.tool.Polyline):
else:
default_container_elevation = 0
mouse_point = context.scene.BIMPolylineProperties.snap_mouse_point[0]
mouse_point = polyline_props.snap_mouse_point[0]
if last_point_data:
last_point = Vector((last_point_data.x, last_point_data.y, last_point_data.z))
@@ -202,8 +203,9 @@ class Polyline(bonsai.core.tool.Polyline):
@classmethod
def calculate_area(cls, context: bpy.types.Context, input_ui: PolylineUI) -> Union[PolylineUI, None]:
polyline_props = tool.Model.get_polyline_props()
try:
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
polyline_data = polyline_props.insertion_polyline[0]
polyline_points = polyline_data.polyline_points
except:
return input_ui
@@ -251,9 +253,10 @@ class Polyline(bonsai.core.tool.Polyline):
@classmethod
def calculate_x_y_and_z(cls, context: bpy.types.Context, input_ui: PolylineUI, tool_state: ToolState) -> None:
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
if len(polyline_data) > 0:
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
polyline_data = polyline_props.insertion_polyline[0]
polyline_points = polyline_data.polyline_points
if len(polyline_points) > 0:
last_point_data = polyline_points[len(polyline_points) - 1]
@@ -269,7 +272,7 @@ class Polyline(bonsai.core.tool.Polyline):
else:
default_container_elevation = 0
snap_prop = context.scene.BIMPolylineProperties.snap_mouse_point[0]
snap_prop = polyline_props.snap_mouse_point[0]
snap_vector = Vector((snap_prop.x, snap_prop.y, snap_prop.z))
if tool_state.is_input_on:
@@ -501,11 +504,13 @@ class Polyline(bonsai.core.tool.Polyline):
d = input_ui.get_formatted_value("D")
a = input_ui.get_formatted_value("A")
snap_vertex = bpy.context.scene.BIMPolylineProperties.snap_mouse_point[0]
polyline_props = tool.Model.get_polyline_props()
snap_vertex = polyline_props.snap_mouse_point[0]
if tool_state and tool_state.use_default_container:
z = tool.Root.get_default_container_elevation()
# Lock one dimension when in plane method
assert tool_state
if tool_state.plane_origin:
if tool_state.plane_method == "XY":
z = tool_state.plane_origin.z
@@ -519,9 +524,9 @@ class Polyline(bonsai.core.tool.Polyline):
y = snap_vertex.y
z = snap_vertex.z
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_data = polyline_props.insertion_polyline
if not polyline_data:
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline.add()
polyline_data = polyline_props.insertion_polyline.add()
else:
polyline_data = polyline_data[0]
polyline_points = polyline_data.polyline_points
@@ -560,20 +565,23 @@ class Polyline(bonsai.core.tool.Polyline):
@classmethod
def clear_polyline(cls) -> None:
bpy.context.scene.BIMPolylineProperties.insertion_polyline.clear()
polyline_props = tool.Model.get_polyline_props()
polyline_props.insertion_polyline.clear()
@classmethod
def remove_last_polyline_point(cls) -> None:
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
polyline_points.remove(len(polyline_points) - 1)
@classmethod
def move_polyline_to_measure(cls, context: bpy.types.Context, input_ui: PolylineUI) -> None:
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
measurement_data = bpy.context.scene.BIMPolylineProperties.measurement_polyline.add()
measurement_type = bpy.context.scene.MeasureToolSettings.measurement_type
measurement_data = polyline_props.measurement_polyline.add()
measurement_type = tool.Project.get_measure_tool_settings().measurement_type
measurement_data.measurement_type = measurement_type
if measurement_type == "AREA" and len(polyline_points) < 3:
return
+6 -1
View File
@@ -38,7 +38,7 @@ from pathlib import Path
from typing import Optional, Union, TYPE_CHECKING
if TYPE_CHECKING:
from bonsai.bim.module.project.prop import BIMProjectProperties
from bonsai.bim.module.project.prop import BIMProjectProperties, MeasureToolSettings
HiearchyDict = dict[ifcopenshell.entity_instance, "HiearchyDict"]
@@ -48,6 +48,11 @@ class Project(bonsai.core.tool.Project):
def get_project_props(cls) -> BIMProjectProperties:
return bpy.context.scene.BIMProjectProperties
@classmethod
def get_measure_tool_settings(cls) -> MeasureToolSettings:
assert (scene := bpy.context.scene)
return scene.MeasureToolSettings # pyright: ignore[reportAttributeAccessIssue]
@classmethod
def append_all_types_from_template(cls, template: str) -> None:
# TODO refactor
+2 -1
View File
@@ -316,7 +316,8 @@ class Raycast(bonsai.core.tool.Raycast):
except:
loc = Vector((0, 0, 0))
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline[0]
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline[0]
polyline_points = polyline_data.polyline_points
polyline_points = polyline_points[
: len(polyline_points) - 1
+27 -15
View File
@@ -49,6 +49,7 @@ if TYPE_CHECKING:
BIMAnimationProperties,
BIMStatusProperties,
BIMTaskTreeProperties,
BIMWorkCalendarProperties,
BIMWorkPlanProperties,
BIMWorkScheduleProperties,
)
@@ -83,6 +84,11 @@ class Sequence(bonsai.core.tool.Sequence):
assert (scene := bpy.context.scene)
return scene.BIMWorkPlanProperties # pyright: ignore[reportAttributeAccessIssue]
@classmethod
def get_work_calendar_props(cls) -> BIMWorkCalendarProperties:
assert (scene := bpy.context.scene)
return scene.BIMWorkCalendarProperties # pyright: ignore[reportAttributeAccessIssue]
@classmethod
def get_work_plan_attributes(cls) -> dict[str, Any]:
import bonsai.bim.module.sequence.helper as helper
@@ -411,7 +417,8 @@ class Sequence(bonsai.core.tool.Sequence):
@classmethod
def get_active_work_time(cls) -> ifcopenshell.entity_instance:
return tool.Ifc.get().by_id(bpy.context.scene.BIMWorkCalendarProperties.active_work_time_id)
props = cls.get_work_calendar_props()
return tool.Ifc.get().by_id(props.active_work_time_id)
@classmethod
def get_task_time(cls, task: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
@@ -571,32 +578,35 @@ class Sequence(bonsai.core.tool.Sequence):
@classmethod
def enable_editing_work_calendar_times(cls, work_calendar: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMWorkCalendarProperties
props = cls.get_work_calendar_props()
props.active_work_calendar_id = work_calendar.id()
props.editing_type = "WORKTIMES"
@classmethod
def load_work_calendar_attributes(cls, work_calendar: ifcopenshell.entity_instance) -> dict[str, Any]:
props = bpy.context.scene.BIMWorkCalendarProperties
props = cls.get_work_calendar_props()
props.work_calendar_attributes.clear()
return bonsai.bim.helper.import_attributes(work_calendar, props.work_calendar_attributes)
@classmethod
def enable_editing_work_calendar(cls, work_calendar: ifcopenshell.entity_instance) -> None:
bpy.context.scene.BIMWorkCalendarProperties.active_work_calendar_id = work_calendar.id()
bpy.context.scene.BIMWorkCalendarProperties.editing_type = "ATTRIBUTES"
props = cls.get_work_calendar_props()
props.active_work_calendar_id = work_calendar.id()
props.editing_type = "ATTRIBUTES"
@classmethod
def disable_editing_work_calendar(cls) -> None:
bpy.context.scene.BIMWorkCalendarProperties.active_work_calendar_id = 0
props = cls.get_work_calendar_props()
props.active_work_calendar_id = 0
@classmethod
def get_work_calendar_attributes(cls) -> dict[str, Any]:
return bonsai.bim.helper.export_attributes(bpy.context.scene.BIMWorkCalendarProperties.work_calendar_attributes)
props = cls.get_work_calendar_props()
return bonsai.bim.helper.export_attributes(props.work_calendar_attributes)
@classmethod
def load_work_time_attributes(cls, work_time: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMWorkCalendarProperties
props = cls.get_work_calendar_props()
props.work_time_attributes.clear()
bonsai.bim.helper.import_attributes(work_time, props.work_time_attributes)
@@ -642,7 +652,7 @@ class Sequence(bonsai.core.tool.Sequence):
for component in recurrence_pattern.MonthComponent or []:
props.month_components[component - 1].is_specified = True
props = bpy.context.scene.BIMWorkCalendarProperties
props = cls.get_work_calendar_props()
initialise_recurrence_components(props)
load_recurrence_pattern_data(work_time, props)
props.active_work_time_id = work_time.id()
@@ -661,12 +671,12 @@ class Sequence(bonsai.core.tool.Sequence):
return True
return False
props = bpy.context.scene.BIMWorkCalendarProperties
props = cls.get_work_calendar_props()
return bonsai.bim.helper.export_attributes(props.work_time_attributes, callback)
@classmethod
def get_recurrence_pattern_attributes(cls, recurrence_pattern):
props = bpy.context.scene.BIMWorkCalendarProperties
props = props = cls.get_work_calendar_props()
attributes = {
"Interval": props.interval if props.interval > 0 else None,
"Occurrences": props.occurrences if props.occurrences > 0 else None,
@@ -693,11 +703,12 @@ class Sequence(bonsai.core.tool.Sequence):
@classmethod
def disable_editing_work_time(cls) -> None:
bpy.context.scene.BIMWorkCalendarProperties.active_work_time_id = 0
props = cls.get_work_calendar_props()
props.active_work_time_id = 0
@classmethod
def get_recurrence_pattern_times(cls) -> Union[tuple[datetime, datetime], None]:
props = bpy.context.scene.BIMWorkCalendarProperties
props = props = cls.get_work_calendar_props()
try:
start_time = parser.parse(props.start_time)
end_time = parser.parse(props.end_time)
@@ -707,8 +718,9 @@ class Sequence(bonsai.core.tool.Sequence):
@classmethod
def reset_time_period(cls) -> None:
bpy.context.scene.BIMWorkCalendarProperties.start_time = ""
bpy.context.scene.BIMWorkCalendarProperties.end_time = ""
props = cls.get_work_calendar_props()
props.start_time = ""
props.end_time = ""
@classmethod
def enable_editing_task_calendar(cls, task: ifcopenshell.entity_instance) -> None:
+17 -10
View File
@@ -111,10 +111,11 @@ class Snap(bonsai.core.tool.Snap):
@classmethod
def update_snapping_point(cls, snap_point, snap_type, snap_obj=None):
polyline_props = tool.Model.get_polyline_props()
try:
snap_vertex = bpy.context.scene.BIMPolylineProperties.snap_mouse_point[0]
snap_vertex = polyline_props.snap_mouse_point[0]
except:
snap_vertex = bpy.context.scene.BIMPolylineProperties.snap_mouse_point.add()
snap_vertex = polyline_props.snap_mouse_point.add()
snap_vertex.x = snap_point[0]
snap_vertex.y = snap_point[1]
@@ -127,14 +128,16 @@ class Snap(bonsai.core.tool.Snap):
@classmethod
def clear_snapping_point(cls):
bpy.context.scene.BIMPolylineProperties.snap_mouse_point.clear()
polyline_props = tool.Model.get_polyline_props()
polyline_props.snap_mouse_point.clear()
@classmethod
def update_snapping_ref(cls, snap_point, snap_type):
polyline_props = tool.Model.get_polyline_props()
try:
snap_vertex = bpy.context.scene.BIMPolylineProperties.snap_mouse_ref[0]
snap_vertex = polyline_props.snap_mouse_ref[0]
except:
snap_vertex = bpy.context.scene.BIMPolylineProperties.snap_mouse_ref.add()
snap_vertex = polyline_props.snap_mouse_ref.add()
snap_vertex.x = snap_point[0]
snap_vertex.y = snap_point[1]
@@ -143,7 +146,8 @@ class Snap(bonsai.core.tool.Snap):
@classmethod
def clear_snapping_ref(cls):
bpy.context.scene.BIMPolylineProperties.snap_mouse_ref.clear()
polyline_props = tool.Model.get_polyline_props()
polyline_props.snap_mouse_ref.clear()
@classmethod
def snap_on_axis(cls, intersection, tool_state):
@@ -167,7 +171,8 @@ class Snap(bonsai.core.tool.Snap):
default_container_elevation = tool.Root.get_default_container_elevation()
else:
default_container_elevation = 0.0
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
if polyline_points:
last_point_data = polyline_points[-1]
@@ -263,7 +268,8 @@ class Snap(bonsai.core.tool.Snap):
intersections.append(tool.Cad.intersect_edge_plane(axis_start, axis_end, snap_point["point"], y_axis))
intersections.append(tool.Cad.intersect_edge_plane(axis_start, axis_end, snap_point["point"], z_axis))
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
if polyline_points:
last_point_data = polyline_points[-1]
@@ -329,8 +335,9 @@ class Snap(bonsai.core.tool.Snap):
return plane_origin, plane_normal
# Polyline
polyline_props = tool.Model.get_polyline_props()
try:
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline[0]
polyline_data = polyline_props.insertion_polyline[0]
polyline_points = polyline_data.polyline_points
last_polyline_point = polyline_points[len(polyline_points) - 1]
except:
@@ -344,7 +351,7 @@ class Snap(bonsai.core.tool.Snap):
detected_snaps.append(point)
# Measure
measure_data = context.scene.BIMPolylineProperties.measurement_polyline
measure_data = polyline_props.measurement_polyline
for measure in measure_data:
measure_points = measure.polyline_points
snap_points = tool.Raycast.ray_cast_to_measure(context, event, measure_points)