mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
typing
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user