mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 10:33:20 +00:00
typing
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -27,29 +27,28 @@ def assign_representation(
|
||||
) -> None:
|
||||
usecase = Usecase()
|
||||
usecase.file = file
|
||||
usecase.settings = {"product": product, "representation": representation}
|
||||
return usecase.execute()
|
||||
return usecase.execute(product, representation)
|
||||
|
||||
|
||||
class Usecase:
|
||||
file: ifcopenshell.file
|
||||
settings: dict[str, Any]
|
||||
|
||||
def execute(self) -> None:
|
||||
if self.settings["product"].is_a("IfcProduct"):
|
||||
product_type = ifcopenshell.util.element.get_type(self.settings["product"])
|
||||
def execute(self, product: ifcopenshell.entity_instance, representation: ifcopenshell.entity_instance) -> None:
|
||||
if product.is_a("IfcProduct"):
|
||||
product_type = ifcopenshell.util.element.get_type(product)
|
||||
if (
|
||||
product_type
|
||||
and product_type.RepresentationMaps
|
||||
and self.settings["representation"].RepresentationType != "MappedRepresentation"
|
||||
and representation.RepresentationType != "MappedRepresentation"
|
||||
):
|
||||
self.settings["product"] = product_type
|
||||
product = product_type
|
||||
|
||||
if self.settings["product"].is_a("IfcProduct"):
|
||||
self.assign_product_representation(self.settings["product"], self.settings["representation"])
|
||||
elif self.settings["product"].is_a("IfcTypeProduct"):
|
||||
if self.settings["product"].RepresentationMaps:
|
||||
maps = list(self.settings["product"].RepresentationMaps)
|
||||
if product.is_a("IfcProduct"):
|
||||
self.assign_product_representation(product, representation)
|
||||
elif product.is_a("IfcTypeProduct"):
|
||||
if product.RepresentationMaps:
|
||||
maps = list(product.RepresentationMaps)
|
||||
else:
|
||||
maps = []
|
||||
self.zero = self.file.createIfcCartesianPoint((0.0, 0.0, 0.0))
|
||||
@@ -60,22 +59,22 @@ class Usecase:
|
||||
"IfcRepresentationMap",
|
||||
**{
|
||||
"MappingOrigin": self.file.createIfcAxis2Placement3D(self.zero, self.z_axis, self.x_axis),
|
||||
"MappedRepresentation": self.settings["representation"],
|
||||
"MappedRepresentation": representation,
|
||||
}
|
||||
)
|
||||
)
|
||||
self.settings["product"].RepresentationMaps = maps
|
||||
product.RepresentationMaps = maps
|
||||
if self.file.schema == "IFC2X3":
|
||||
types = self.settings["product"].ObjectTypeOf
|
||||
types = product.ObjectTypeOf
|
||||
else:
|
||||
types = self.settings["product"].Types
|
||||
types = product.Types
|
||||
if types:
|
||||
for element in types[0].RelatedObjects:
|
||||
mapped_representation = ifcopenshell.api.geometry.map_representation(
|
||||
self.file, representation=self.settings["representation"]
|
||||
self.file, representation=representation
|
||||
)
|
||||
self.assign_product_representation(element, mapped_representation)
|
||||
ifcopenshell.api.owner.update_owner_history(self.file, element=self.settings["product"])
|
||||
ifcopenshell.api.owner.update_owner_history(self.file, element=product)
|
||||
|
||||
def assign_product_representation(
|
||||
self, product: ifcopenshell.entity_instance, representation: ifcopenshell.entity_instance
|
||||
|
||||
@@ -30,6 +30,8 @@ def assign_declaration(
|
||||
) -> Union[ifcopenshell.entity_instance, None]:
|
||||
"""Declares the list of elements to the project
|
||||
|
||||
Feature was added in IFC4.
|
||||
|
||||
All data in a model must be directly or indirectly related to the
|
||||
project. Most data is indirectly related, existing instead within the
|
||||
spatial decomposition tree. Other data, such as types, may be declared
|
||||
@@ -82,21 +84,16 @@ def assign_declaration(
|
||||
# All done, just for fun let's save our asset library to disk for later use.
|
||||
library.write("/path/to/my-library.ifc")
|
||||
"""
|
||||
settings = {
|
||||
"definitions": definitions,
|
||||
"relating_context": relating_context,
|
||||
}
|
||||
|
||||
relating_context = settings["relating_context"]
|
||||
all_declares = relating_context.Declares
|
||||
definitions = set(settings["definitions"])
|
||||
definitions_set = set(definitions)
|
||||
|
||||
previous_declares_rels: set[ifcopenshell.entity_instance] = set()
|
||||
objects_without_contexts: list[ifcopenshell.entity_instance] = []
|
||||
objects_with_contexts: list[ifcopenshell.entity_instance] = []
|
||||
|
||||
# check if there is anything to change
|
||||
for definition in definitions:
|
||||
for definition in definitions_set:
|
||||
has_context = getattr(definition, "HasContext", None)
|
||||
if has_context is None:
|
||||
continue
|
||||
|
||||
@@ -20,7 +20,6 @@ import ifcopenshell.api.control
|
||||
import ifcopenshell.api.root
|
||||
import ifcopenshell.api.nest
|
||||
import ifcopenshell
|
||||
import ifcopenshell.guid
|
||||
from typing import Optional
|
||||
|
||||
|
||||
|
||||
@@ -23,14 +23,12 @@ import ifcopenshell.api.owner
|
||||
import ifcopenshell.api.sequence
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.sequence
|
||||
from typing import Union, Any
|
||||
|
||||
|
||||
# TODO: inconsistent name with other copy_xxx api methods.
|
||||
def duplicate_task(
|
||||
file: ifcopenshell.file, task: ifcopenshell.entity_instance
|
||||
) -> Union[ifcopenshell.entity_instance, list[ifcopenshell.entity_instance]]:
|
||||
) -> tuple[list[ifcopenshell.entity_instance], list[ifcopenshell.entity_instance]]:
|
||||
"""Duplicates a task in the project
|
||||
|
||||
The following relationships are also duplicated:
|
||||
@@ -53,24 +51,27 @@ def duplicate_task(
|
||||
"""
|
||||
usecase = Usecase()
|
||||
usecase.file = file
|
||||
usecase.settings = {"task": task}
|
||||
return usecase.execute()
|
||||
return usecase.execute(task)
|
||||
|
||||
|
||||
class Usecase:
|
||||
file: ifcopenshell.file
|
||||
settings: dict[str, list[ifcopenshell.entity_instance]]
|
||||
current: list[ifcopenshell.entity_instance]
|
||||
duplicate: list[ifcopenshell.entity_instance]
|
||||
|
||||
def execute(self):
|
||||
self.tracker = {"current": [], "duplicate": []}
|
||||
self.duplicate_task(self.settings["task"])
|
||||
self.copy_sequence_relationship(self.tracker["current"], self.tracker["duplicate"])
|
||||
return self.tracker["current"], self.tracker["duplicate"]
|
||||
def execute(
|
||||
self, task: ifcopenshell.entity_instance
|
||||
) -> tuple[list[ifcopenshell.entity_instance], list[ifcopenshell.entity_instance]]:
|
||||
self.current = []
|
||||
self.duplicate = []
|
||||
self.duplicate_task(task)
|
||||
self.copy_sequence_relationship()
|
||||
return self.current, self.duplicate
|
||||
|
||||
def duplicate_task(self, task: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
|
||||
new_task = ifcopenshell.util.element.copy_deep(self.file, task)
|
||||
self.tracker["current"].append(task)
|
||||
self.tracker["duplicate"].append(new_task)
|
||||
self.current.append(task)
|
||||
self.duplicate.append(new_task)
|
||||
self.copy_indirect_attributes(task, new_task)
|
||||
return new_task
|
||||
|
||||
@@ -118,7 +119,9 @@ class Usecase:
|
||||
new_value.append(to_element)
|
||||
inverse[i] = new_value
|
||||
|
||||
def copy_sequence_relationship(self, original_tasks, duplicated_tasks):
|
||||
def copy_sequence_relationship(self) -> None:
|
||||
original_tasks = self.current
|
||||
duplicated_tasks = self.duplicate
|
||||
for i, original_task in enumerate(original_tasks):
|
||||
for inverse in self.file.get_inverse(original_task):
|
||||
if inverse.is_a("IfcRelSequence") and (
|
||||
|
||||
@@ -202,7 +202,7 @@ def get_root_cost_items(cost_schedule: ifcopenshell.entity_instance) -> list[ifc
|
||||
|
||||
def get_all_nested_cost_items(
|
||||
cost_item: ifcopenshell.entity_instance,
|
||||
) -> Generator[ifcopenshell.entity_instance, None, None]:
|
||||
) -> Generator[ifcopenshell.entity_instance]:
|
||||
for cost_item in get_nested_cost_items(cost_item):
|
||||
yield cost_item
|
||||
yield from get_all_nested_cost_items(cost_item)
|
||||
@@ -217,7 +217,7 @@ def get_nested_cost_items(cost_item: ifcopenshell.entity_instance, is_deep=False
|
||||
|
||||
def get_schedule_cost_items(
|
||||
cost_schedule: ifcopenshell.entity_instance,
|
||||
) -> Generator[ifcopenshell.entity_instance, None, None]:
|
||||
) -> Generator[ifcopenshell.entity_instance]:
|
||||
"""Get all cost schedule cost items, including the nested ones."""
|
||||
for cost_item in get_root_cost_items(cost_schedule):
|
||||
yield cost_item
|
||||
|
||||
Reference in New Issue
Block a user