This commit is contained in:
Andrej730
2024-12-20 18:30:43 +05:00
parent 579628fcb1
commit a79c4b1ace
9 changed files with 63 additions and 45 deletions
+5 -3
View File
@@ -25,6 +25,7 @@ import bonsai.tool as tool
from mathutils import Vector, Matrix
from math import pi, radians, sin, cos, sqrt
import ifcopenshell.util.unit
from typing import Union
messages = {
@@ -622,7 +623,7 @@ class AddIfcArcIndexFillet(bpy.types.Operator):
bl_idname = "bim.add_ifcarcindex_fillet"
bl_label = "Add Arc Index Fillet"
bl_options = {"REGISTER", "UNDO"}
radius: bpy.props.FloatProperty(name="Radius", default=0.1)
radius: bpy.props.FloatProperty(name="Radius", default=0.1, subtype="DISTANCE")
@classmethod
def poll(cls, context):
@@ -644,7 +645,7 @@ class AddIfcArcIndexFillet(bpy.types.Operator):
self.create_arc(context)
return {"FINISHED"}
def has_selected_existing_arc(self, context):
def has_selected_existing_arc(self, context: bpy.types.Context) -> bool:
obj = context.active_object
bm = bmesh.from_edit_mesh(obj.data)
verts = [v for v in bm.verts if v.select and not v.hide]
@@ -662,8 +663,9 @@ class AddIfcArcIndexFillet(bpy.types.Operator):
return True
except:
pass # Potentially fail if the vert has been removed in the previous operation
return False
def change_radius(self, context):
def change_radius(self, context: bpy.types.Context) -> None:
obj = context.active_object
bm = bmesh.from_edit_mesh(obj.data)
edges = [e for e in bm.edges if e.select and not e.hide]
@@ -23,6 +23,7 @@ import bonsai.bim.module.type.prop as type_prop
import ifcopenshell.util.unit
from bpy.types import WorkSpaceTool
from bonsai.bim.module.model.data import AuthoringData, RailingData, RoofData
from typing import Union
# TODO duplicate code in cad/workspace and model/workspace
@@ -329,7 +330,9 @@ def add_header_apply_button(layout, text, apply_operator, cancel_operator, ui_co
row.label(text="Tools")
def add_layout_hotkey_operator(layout, text, hotkey, description, ui_context=""):
def add_layout_hotkey_operator(
layout: bpy.types.UILayout, text: str, hotkey: str, description: Union[str, None], ui_context: str = ""
) -> bpy.types.OperatorProperties:
parts = hotkey.split("_")
modifier, key = parts
op_text = "" if ui_context == "TOOL_HEADER" else text
@@ -24,6 +24,7 @@ import bonsai.tool as tool
from bonsai.bim.module.drawing.data import DecoratorData, AnnotationData
from bonsai.bim.helper import prop_with_search
from bpy.types import WorkSpaceTool
from typing import Union
class LaunchAnnotationTypeManager(bpy.types.Operator):
@@ -131,7 +132,9 @@ class AnnotationTool(WorkSpaceTool):
AnnotationToolUI.draw(context, layout)
def add_layout_hotkey_operator(layout, text, hotkey, description):
def add_layout_hotkey_operator(
layout: bpy.types.UILayout, text: str, hotkey: str, description: Union[str, None]
) -> tuple[bpy.types.OperatorProperties, bpy.types.UILayout]:
modifiers = {
"A": "EVENT_ALT",
"S": "EVENT_SHIFT",
+18 -14
View File
@@ -38,7 +38,7 @@ from math import pi, sin, cos, degrees
from mathutils import Vector, Matrix
from bonsai.bim.module.model.opening import FilledOpeningGenerator
from bonsai.bim.module.model.decorator import PolylineDecorator
from typing import Optional
from typing import Optional, Union, Literal
from lark import Lark, Transformer
@@ -47,7 +47,7 @@ class PolylineOperator:
""" """
@classmethod
def poll(cls, context):
def poll(cls, context: bpy.types.Context) -> bool:
return context.space_data.type == "VIEW_3D"
def __init__(self):
@@ -103,7 +103,7 @@ class PolylineOperator:
self.tool_state = tool.Polyline.create_tool_state()
def recalculate_inputs(self, context):
def recalculate_inputs(self, context: bpy.types.Context) -> Union[bool, None]:
if self.number_input:
is_valid, self.number_output = tool.Polyline.validate_input(self.number_output, self.input_type)
self.input_ui.set_value(self.input_type, self.number_output)
@@ -121,7 +121,7 @@ class PolylineOperator:
tool.Blender.update_viewport()
return is_valid
def choose_axis(self, event, x=True, y=True, z=False):
def choose_axis(self, event: bpy.types.Event, x: bool = True, y: bool = True, z: bool = False) -> None:
if x:
if not event.shift and event.value == "PRESS" and event.type == "X":
self.tool_state.axis_method = "X" if self.tool_state.axis_method != event.type else None
@@ -142,7 +142,7 @@ class PolylineOperator:
PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0])
tool.Blender.update_viewport()
def choose_plane(self, event, x=True, y=True, z=True):
def choose_plane(self, event: bpy.types.Event, x: bool = True, y: bool = True, z: bool = True) -> None:
if x:
if event.shift and event.value == "PRESS" and event.type == "X":
self.tool_state.use_default_container = False
@@ -164,7 +164,7 @@ class PolylineOperator:
self.tool_state.axis_method = None
tool.Blender.update_viewport()
def handle_instructions(self, context, custom_instructions=""):
def handle_instructions(self, context: bpy.types.Context, custom_instructions: str = "") -> None:
self.snap_info = f"""|
Axis: {self.tool_state.axis_method}
Plane: {self.tool_state.plane_method}
@@ -172,7 +172,7 @@ class PolylineOperator:
"""
context.workspace.status_text_set(self.instructions + custom_instructions + self.snap_info)
def handle_lock_axis(self, context, event):
def handle_lock_axis(self, context: bpy.types.Context, event: bpy.types.Event) -> None:
if event.value == "PRESS" and event.type == "A":
self.tool_state.lock_axis = False if self.tool_state.lock_axis else True
self.tool_state.snap_angle = self.input_ui.get_number_value("WORLD_ANGLE")
@@ -191,7 +191,7 @@ class PolylineOperator:
PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0])
tool.Blender.update_viewport()
def handle_keyboard_input(self, context, event):
def handle_keyboard_input(self, context: bpy.types.Context, event: bpy.types.Event) -> None:
if self.tool_state.is_input_on and event.value == "PRESS" and event.type == "TAB":
self.recalculate_inputs(context)
@@ -269,7 +269,7 @@ class PolylineOperator:
PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0])
tool.Blender.update_viewport()
def handle_inserting_polyline(self, context, event):
def handle_inserting_polyline(self, context: bpy.types.Context, event: bpy.types.Event) -> None:
if not self.tool_state.is_input_on and event.value == "RELEASE" and event.type == "LEFTMOUSE":
result = tool.Polyline.insert_polyline_point(self.input_ui, self.tool_state)
if result:
@@ -301,7 +301,7 @@ class PolylineOperator:
PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0])
tool.Blender.update_viewport()
def handle_snap_selection(self, context, event):
def handle_snap_selection(self, context: bpy.types.Context, event: bpy.types.Event) -> None:
if event.value == "PRESS" and event.type == "M":
self.snapping_points = tool.Snap.modify_snapping_point_selection(
self.snapping_points, lock_axis=self.tool_state.lock_axis
@@ -310,7 +310,9 @@ class PolylineOperator:
PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0])
tool.Blender.update_viewport()
def handle_cancelation(self, context, event):
def handle_cancelation(
self, context: bpy.types.Context, event: bpy.types.Event
) -> Union[None, set[Literal["CANCELLED"]]]:
if self.tool_state.is_input_on:
if event.value == "RELEASE" and event.type in {"ESC"}:
self.recalculate_inputs(context)
@@ -329,7 +331,9 @@ class PolylineOperator:
tool.Blender.update_viewport()
return {"CANCELLED"}
def handle_mouse_move(self, context, event, should_round=False):
def handle_mouse_move(
self, context: bpy.types.Context, event: bpy.types.Event, should_round: bool = False
) -> Union[None, set[Literal["RUNNING_MODAL"]]]:
if not self.tool_state.is_input_on:
if event.type == "MOUSEMOVE" or event.type == "INBETWEEN_MOUSEMOVE":
self.mousemove_count += 1
@@ -368,13 +372,13 @@ class PolylineOperator:
tool.Polyline.remove_last_polyline_point()
tool.Blender.update_viewport()
def modal(self, context, event):
def modal(self, context: bpy.types.Context, event: bpy.types.Event) -> Union[set[str], None]:
PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0])
tool.Blender.update_viewport()
if event.type in {"MIDDLEMOUSE", "WHEELUPMOUSE", "WHEELDOWNMOUSE"}:
return {"PASS_THROUGH"}
def invoke(self, context, event):
def invoke(self, context: bpy.types.Context, event: bpy.types.Event) -> None:
PolylineDecorator.install(context)
tool.Snap.clear_snapping_point()
@@ -29,7 +29,7 @@ from bpy.types import WorkSpaceTool, Menu
from bonsai.bim.module.model.data import AuthoringData, ItemData
from bonsai.bim.module.system.data import PortData
from bonsai.bim.module.model.prop import get_ifc_class
from typing import Optional
from typing import Optional, Union
# TODO duplicate code in cad/workspace and model/workspace
@@ -234,7 +234,9 @@ class CableTool(BimTool):
ifc_element_type = "IfcCableSegmentType"
def add_layout_hotkey_operator(layout, text, hotkey, description, ui_context=""):
def add_layout_hotkey_operator(
layout: bpy.types.UILayout, text: str, hotkey: str, description: Union[str, None], ui_context: str = ""
) -> bpy.types.OperatorProperties:
parts = hotkey.split("_") if hotkey else []
modifier, key = (parts + ["", ""])[:2]
+10 -5
View File
@@ -26,10 +26,12 @@ import numpy as np
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.pset
import ifcopenshell.geom
import ifcopenshell.util.element
import ifcopenshell.util.unit
import ifcopenshell.util.placement
import ifcopenshell.util.representation
import ifcopenshell.util.shape
import ifcopenshell.util.unit
import bonsai.core.geometry
import bonsai.core.tool
import bonsai.tool as tool
@@ -1739,6 +1741,7 @@ class Model(bonsai.core.tool.Model):
if position is None:
position = Matrix()
position_i = position.inverted()
assert isinstance(position_i, Matrix)
groups = {"IFCARCINDEX": [], "IFCCIRCLE": []}
for i, group in enumerate(obj.vertex_groups):
@@ -1781,7 +1784,7 @@ class Model(bonsai.core.tool.Model):
loop_edges = list(bm.edges)
# Create loops from edges
loops = []
loops: list[list[bmesh.types.BMEdge]] = []
while loop_edges:
edge = loop_edges.pop()
loop = [edge]
@@ -1802,7 +1805,7 @@ class Model(bonsai.core.tool.Model):
tmp = ifcopenshell.file(schema=tool.Ifc.get().schema)
def is_in_group(v, group_name):
def is_in_group(v: bmesh.types.BMVert, group_name: str) -> bool:
for group_index in groups[group_name]:
if group_index in v[deform_layer]:
return True
@@ -1827,7 +1830,7 @@ class Model(bonsai.core.tool.Model):
tmp.createIfcCircle(tmp.createIfcAxis2Placement2D(tmp.createIfcCartesianPoint(list(mid))), radius)
)
else:
loop_verts = []
loop_verts: list[bmesh.types.BMVert] = []
for i, edge in enumerate(loop):
if i == 0 and len(loop) == 1:
loop_verts.append(edge.verts[0])
@@ -1861,7 +1864,9 @@ class Model(bonsai.core.tool.Model):
if tmp.schema != "IFC2X3" and any([is_in_group(v, "IFCARCINDEX") for v in loop_verts]):
# We need to specify segments
coord_list = [list((position_i @ (v.co / unit_scale)).to_2d()) for v in loop_verts]
coord_list: list[list[float]] = [
list((position_i @ (v.co / unit_scale)).to_2d()) for v in loop_verts
]
points = tmp.createIfcCartesianPointList2D(coord_list)
i = 0
segments = []
+15 -13
View File
@@ -26,7 +26,7 @@ from dataclasses import dataclass
from lark import Lark, Transformer
from math import degrees, radians, sin, cos, tan
from mathutils import Vector, Matrix
from typing import Optional
from typing import Optional, Union
class Polyline(bonsai.core.tool.Polyline):
@@ -98,15 +98,17 @@ class Polyline(bonsai.core.tool.Polyline):
input_type: str = None
@classmethod
def create_input_ui(cls, init_z=False, init_area=False):
def create_input_ui(cls, init_z: bool = False, init_area: bool = False) -> PolylineUI:
return cls.PolylineUI(init_z=init_z, init_area=init_area)
@classmethod
def create_tool_state(cls):
def create_tool_state(cls) -> ToolState:
return cls.ToolState()
@classmethod
def calculate_distance_and_angle(cls, context, input_ui, tool_state, should_round=False):
def calculate_distance_and_angle(
cls, context: bpy.types.Context, input_ui: PolylineUI, tool_state: ToolState, should_round: bool = False
) -> None:
try:
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
@@ -192,7 +194,7 @@ class Polyline(bonsai.core.tool.Polyline):
return
@classmethod
def calculate_area(cls, context, input_ui):
def calculate_area(cls, context: bpy.types.Context, input_ui: PolylineUI) -> Union[PolylineUI, None]:
try:
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
polyline_points = polyline_data.polyline_points
@@ -241,7 +243,7 @@ class Polyline(bonsai.core.tool.Polyline):
return
@classmethod
def calculate_x_y_and_z(cls, context, input_ui, tool_state):
def calculate_x_y_and_z(cls, context: bpy.types.Context, input_ui: PolylineUI, tool_state: ToolState) -> None:
try:
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
polyline_points = polyline_data.polyline_points
@@ -305,7 +307,7 @@ class Polyline(bonsai.core.tool.Polyline):
return
@classmethod
def validate_input(cls, input_number, input_type):
def validate_input(cls, input_number, input_type) -> tuple[bool, str]:
grammar_imperial = """
start: (FORMULA dim expr) | dim
@@ -433,7 +435,7 @@ class Polyline(bonsai.core.tool.Polyline):
return False, "0"
@classmethod
def format_input_ui_units(cls, value, is_area=False):
def format_input_ui_units(cls, value: float, is_area: bool = False) -> str:
unit_system = tool.Drawing.get_unit_system()
if unit_system == "IMPERIAL":
precision = bpy.context.scene.DocProperties.imperial_precision
@@ -454,7 +456,7 @@ class Polyline(bonsai.core.tool.Polyline):
)
@classmethod
def insert_polyline_point(cls, input_ui, tool_state=None):
def insert_polyline_point(cls, input_ui: PolylineUI, tool_state: Optional[ToolState] = None) -> Union[str, None]:
x = input_ui.get_number_value("X")
y = input_ui.get_number_value("Y")
if input_ui.get_number_value("Z") is not None:
@@ -521,7 +523,7 @@ class Polyline(bonsai.core.tool.Polyline):
polyline_data.total_length = total_length
@classmethod
def close_polyline(cls):
def close_polyline(cls) -> None:
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
if len(polyline_points) > 2:
@@ -537,17 +539,17 @@ class Polyline(bonsai.core.tool.Polyline):
polyline_point.position = first_point.position
@classmethod
def clear_polyline(cls):
def clear_polyline(cls) -> None:
bpy.context.scene.BIMPolylineProperties.insertion_polyline.clear()
@classmethod
def remove_last_polyline_point(cls):
def remove_last_polyline_point(cls) -> None:
polyline_data = bpy.context.scene.BIMPolylineProperties.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, input_ui):
def move_polyline_to_measure(cls, context: bpy.types.Context, input_ui: PolylineUI) -> None:
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
measurement_data = bpy.context.scene.BIMPolylineProperties.measurement_polyline.add()
@@ -18,9 +18,10 @@
import datetime
import ifcopenshell
import ifcopenshell.util.schema
def create_file(version: str = "IFC4") -> ifcopenshell.file:
def create_file(version: ifcopenshell.util.schema.IFC_SCHEMA = "IFC4") -> ifcopenshell.file:
"""Create a blank IFC model file object
Create a new IFC file object based on the nominated schema version. The
@@ -34,9 +35,7 @@ def create_file(version: str = "IFC4") -> ifcopenshell.file:
:param version: The schema version of the IFC file. Choose from
"IFC2X3", "IFC4", or "IFC4X3". If you have loaded in a custom
schema, you may specify that schema identifier here too.
:type version: str, optional
:return: The created IFC file object.
:rtype: ifcopenshell.file
Example:
+1 -3
View File
@@ -222,7 +222,7 @@ class file:
def __init__(
self,
f: Optional[ifcopenshell_wrapper.file] = None,
schema: Optional[str] = None,
schema: Optional[ifcopenshell.util.schema.IFC_SCHEMA] = None,
schema_version: Optional[tuple[int, int, int, int]] = None,
):
"""Create a new blank IFC model
@@ -239,7 +239,6 @@ class file:
or "IFC4X3". These refer to the ISO approved versions of IFC.
Defaults to "IFC4" if not specified, which is currently recommended
for all new projects.
:type schema: string
:param schema_version: If you want to specify an exact version of IFC
that may not be an ISO approved version, use this argument instead
of ``schema``. IFC versions on technical.buildingsmart.org are
@@ -248,7 +247,6 @@ class file:
ADD2 TC1, which is the official version approved by ISO when people
refer to "IFC4". Generally you should not use this argument unless
you are testing non-ISO IFC releases.
:type schema_version: tuple[int, int, int, int]
Example: