This commit is contained in:
Andrej730
2025-05-08 15:56:15 +05:00
parent a20002ecca
commit def9352ade
5 changed files with 93 additions and 66 deletions
+1 -1
View File
@@ -118,7 +118,7 @@ class DrawingsData:
return len([e for e in tool.Ifc.get().by_type("IfcAnnotation") if e.ObjectType == "DRAWING"])
@classmethod
def location_hint(cls):
def location_hint(cls) -> list[tuple[tool.Drawing.LocationHintType, str, str]]:
props = tool.Drawing.get_document_props()
if props.target_view in ["PLAN_VIEW", "REFLECTED_PLAN_VIEW"]:
results = [("0", "Origin", "")]
@@ -143,6 +143,8 @@ class AddDrawing(bpy.types.Operator, tool.Ifc.Operator):
hint = props.location_hint
if props.target_view in ["PLAN_VIEW", "REFLECTED_PLAN_VIEW"]:
hint = int(hint)
else:
assert hint in tool.Drawing.LOCATION_HINT_LITERALS
core.add_drawing(
tool.Ifc,
tool.Collector,
@@ -167,7 +169,6 @@ class DuplicateDrawing(bpy.types.Operator, tool.Ifc.Operator):
@classmethod
def poll(cls, context):
props = tool.Drawing.get_document_props()
if not tool.Drawing.get_active_drawing_item():
cls.poll_message_set("No drawing selected.")
return False
+1 -1
View File
@@ -465,7 +465,7 @@ class DocProperties(PropertyGroup):
is_editing_schedules: bool
is_editing_references: bool
target_view: Literal["PLAN_VIEW", "ELEVATION_VIEW", "SECTION_VIEW", "REFLECTED_PLAN_VIEW", "MODEL_VIEW"]
location_hint: str
location_hint: tool.Drawing.LocationHintType
drawings: bpy.types.bpy_prop_collection_idprop[Drawing]
active_drawing_id: int
active_drawing_index: int
+63 -45
View File
@@ -27,16 +27,16 @@ if TYPE_CHECKING:
import bonsai.tool as tool
def enable_editing_text(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
def enable_editing_text(drawing: type[tool.Drawing], obj: bpy.types.Object) -> None:
drawing.enable_editing_text(obj)
drawing.import_text_attributes(obj)
def disable_editing_text(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
def disable_editing_text(drawing: type[tool.Drawing], obj: bpy.types.Object) -> None:
drawing.disable_editing_text(obj)
def edit_text(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
def edit_text(drawing: type[tool.Drawing], obj: bpy.types.Object) -> None:
drawing.synchronise_ifc_and_text_attributes(obj)
drawing.update_text_size_pset(obj)
drawing.update_newline_at(obj)
@@ -44,17 +44,20 @@ def edit_text(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
drawing.disable_editing_text(obj)
def enable_editing_assigned_product(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
def enable_editing_assigned_product(drawing: type[tool.Drawing], obj: bpy.types.Object) -> None:
drawing.enable_editing_assigned_product(obj)
drawing.import_assigned_product(obj)
def disable_editing_assigned_product(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
def disable_editing_assigned_product(drawing: type[tool.Drawing], obj: bpy.types.Object) -> None:
drawing.disable_editing_assigned_product(obj)
def edit_assigned_product(
ifc: tool.Ifc, drawing: tool.Drawing, obj: bpy.types.Object, product: Optional[ifcopenshell.entity_instance] = None
ifc: type[tool.Ifc],
drawing: type[tool.Drawing],
obj: bpy.types.Object,
product: Optional[ifcopenshell.entity_instance] = None,
) -> None:
element = ifc.get_entity(obj)
assert element
@@ -70,16 +73,16 @@ def edit_assigned_product(
drawing.disable_editing_assigned_product(obj)
def load_sheets(drawing: tool.Drawing) -> None:
def load_sheets(drawing: type[tool.Drawing]) -> None:
drawing.import_sheets()
drawing.enable_editing_sheets()
def disable_editing_sheets(drawing: tool.Drawing) -> None:
def disable_editing_sheets(drawing: type[tool.Drawing]) -> None:
drawing.disable_editing_sheets()
def add_sheet(ifc: tool.Ifc, drawing: tool.Drawing, titleblock: ifcopenshell.entity_instance) -> None:
def add_sheet(ifc: type[tool.Ifc], drawing: type[tool.Drawing], titleblock: ifcopenshell.entity_instance) -> None:
sheet = ifc.run("document.add_information")
layout = ifc.run("document.add_reference", information=sheet)
titleblock_reference = ifc.run("document.add_reference", information=sheet)
@@ -105,7 +108,7 @@ def add_sheet(ifc: tool.Ifc, drawing: tool.Drawing, titleblock: ifcopenshell.ent
drawing.import_sheets()
def regenerate_sheet(drawing: tool.Drawing, sheet: ifcopenshell.entity_instance) -> None:
def regenerate_sheet(drawing: type[tool.Drawing], sheet: ifcopenshell.entity_instance) -> None:
titleblock_uri = drawing.get_document_uri(sheet, "TITLEBLOCK")
drawing.create_svg_sheet(sheet, drawing.sanitise_filename(Path(titleblock_uri).stem))
try:
@@ -116,11 +119,11 @@ def regenerate_sheet(drawing: tool.Drawing, sheet: ifcopenshell.entity_instance)
drawing.delete_file(path_layout)
def open_layout(drawing: tool.Drawing, sheet: ifcopenshell.entity_instance) -> None:
def open_layout(drawing: type[tool.Drawing], sheet: ifcopenshell.entity_instance) -> None:
drawing.open_layout_svg(drawing.get_document_uri(sheet, "LAYOUT"))
def remove_sheet(ifc: tool.Ifc, drawing: tool.Drawing, sheet: ifcopenshell.entity_instance) -> None:
def remove_sheet(ifc: type[tool.Ifc], drawing: type[tool.Drawing], sheet: ifcopenshell.entity_instance) -> None:
for reference in drawing.get_document_references(sheet):
if drawing.get_reference_description(reference) in ("LAYOUT", "SHEET", "REVISION", "RASTER"):
uri = ifc.resolve_uri(drawing.get_document_uri(reference))
@@ -131,7 +134,11 @@ def remove_sheet(ifc: tool.Ifc, drawing: tool.Drawing, sheet: ifcopenshell.entit
def rename_sheet(
ifc: tool.Ifc, drawing: tool.Drawing, sheet: ifcopenshell.entity_instance, identification: str, name: str
ifc: type[tool.Ifc],
drawing: type[tool.Drawing],
sheet: ifcopenshell.entity_instance,
identification: str,
name: str,
) -> None:
if ifc.get_schema() == "IFC2X3":
attributes = {"DocumentId": identification, "Name": name}
@@ -159,31 +166,33 @@ def rename_sheet(
def rename_reference(
ifc: tool.Ifc, drawing: tool.Drawing, reference: ifcopenshell.entity_instance, identification: str
ifc: type[tool.Ifc], drawing: type[tool.Drawing], reference: ifcopenshell.entity_instance, identification: str
) -> None:
attributes = drawing.generate_reference_attributes(reference, Identification=identification)
ifc.run("document.edit_reference", reference=reference, attributes=attributes)
def load_schedules(drawing: tool.Drawing) -> None:
def load_schedules(drawing: type[tool.Drawing]) -> None:
drawing.import_documents("SCHEDULE")
drawing.enable_editing_schedules()
def load_references(drawing: tool.Drawing) -> None:
def load_references(drawing: type[tool.Drawing]) -> None:
drawing.import_documents("REFERENCE")
drawing.enable_editing_references()
def disable_editing_schedules(drawing: tool.Drawing) -> None:
def disable_editing_schedules(drawing: type[tool.Drawing]) -> None:
drawing.disable_editing_schedules()
def disable_editing_references(drawing: tool.Drawing) -> None:
def disable_editing_references(drawing: type[tool.Drawing]) -> None:
drawing.disable_editing_references()
def add_document(ifc: tool.Ifc, drawing: tool.Drawing, document_type: tool.Drawing.DOCUMENT_TYPE, uri: str) -> None:
def add_document(
ifc: type[tool.Ifc], drawing: type[tool.Drawing], document_type: type[tool.Drawing].DOCUMENT_TYPE, uri: str
) -> None:
document = ifc.run("document.add_information")
reference = ifc.run("document.add_reference", information=document)
name = drawing.get_path_filename(uri)
@@ -197,46 +206,47 @@ def add_document(ifc: tool.Ifc, drawing: tool.Drawing, document_type: tool.Drawi
def remove_document(
ifc: tool.Ifc,
drawing: tool.Drawing,
document_type: tool.Drawing.DOCUMENT_TYPE,
ifc: type[tool.Ifc],
drawing: type[tool.Drawing],
document_type: type[tool.Drawing].DOCUMENT_TYPE,
document: ifcopenshell.entity_instance,
) -> None:
ifc.run("document.remove_information", information=document)
drawing.import_documents(document_type)
def open_schedule(drawing: tool.Drawing, schedule: ifcopenshell.entity_instance) -> None:
def open_schedule(drawing: type[tool.Drawing], schedule: ifcopenshell.entity_instance) -> None:
drawing.open_spreadsheet(drawing.get_document_uri(schedule))
def open_reference(drawing: tool.Drawing, reference: ifcopenshell.entity_instance) -> None:
def open_reference(drawing: type[tool.Drawing], reference: ifcopenshell.entity_instance) -> None:
drawing.open_svg(drawing.get_document_uri(reference))
def update_document_name(
ifc: tool.Ifc, drawing: tool.Drawing, document: ifcopenshell.entity_instance, name=None
ifc: type[tool.Ifc], drawing: type[tool.Drawing], document: ifcopenshell.entity_instance, name=None
) -> None:
if drawing.get_name(document) != name:
ifc.run("document.edit_information", information=document, attributes={"Name": name})
def load_drawings(drawing: tool.Drawing) -> None:
def load_drawings(drawing: type[tool.Drawing]) -> None:
drawing.import_drawings()
drawing.enable_editing_drawings()
def disable_editing_drawings(drawing: tool.Drawing) -> None:
def disable_editing_drawings(drawing: type[tool.Drawing]) -> None:
drawing.disable_editing_drawings()
def add_drawing(
ifc: tool.Ifc,
collector: tool.Collector,
drawing: tool.Drawing,
target_view: Union[ifcopenshell.util.representation.TARGET_VIEW, None] = None,
location_hint: Union[str, None] = None,
ifc: type[tool.Ifc],
collector: type[tool.Collector],
drawing: type[tool.Drawing],
target_view: ifcopenshell.util.representation.TARGET_VIEW,
location_hint: Union[tool.Drawing.LocationHintLiteral, int],
) -> None:
assert location_hint is not None
drawing_name = drawing.ensure_unique_drawing_name(drawing.generate_drawing_name(target_view, location_hint))
drawing_matrix = drawing.generate_drawing_matrix(target_view, location_hint)
camera = drawing.create_camera(drawing_name, drawing_matrix, location_hint)
@@ -295,10 +305,10 @@ def add_drawing(
def duplicate_drawing(
ifc: tool.Ifc,
blender: tool.Blender,
drawing_tool: tool.Drawing,
geometry: tool.Geometry,
ifc: type[tool.Ifc],
blender: type[tool.Blender],
drawing_tool: type[tool.Drawing],
geometry: type[tool.Geometry],
drawing: ifcopenshell.entity_instance,
should_duplicate_annotations: bool = False,
) -> ifcopenshell.entity_instance:
@@ -341,7 +351,9 @@ def duplicate_drawing(
return new_drawing
def remove_drawing(ifc: tool.Ifc, drawing_tool: tool.Drawing, drawing: ifcopenshell.entity_instance) -> None:
def remove_drawing(
ifc: type[tool.Ifc], drawing_tool: type[tool.Drawing], drawing: ifcopenshell.entity_instance
) -> None:
if drawing_tool.is_active_drawing(drawing):
drawing_tool.run_drawing_activate_model()
@@ -370,7 +382,7 @@ def remove_drawing(ifc: tool.Ifc, drawing_tool: tool.Drawing, drawing: ifcopensh
def update_drawing_name(
ifc: tool.Ifc, drawing_tool: tool.Drawing, drawing: ifcopenshell.entity_instance, name: str
ifc: type[tool.Ifc], drawing_tool: type[tool.Drawing], drawing: ifcopenshell.entity_instance, name: str
) -> None:
if drawing_tool.get_name(drawing) != name:
ifc.run("attribute.edit_attributes", product=drawing, attributes={"Name": name})
@@ -406,9 +418,9 @@ def update_drawing_name(
def add_annotation(
ifc: tool.Ifc,
collector: tool.Collector,
drawing_tool: tool.Drawing,
ifc: type[tool.Ifc],
collector: type[tool.Collector],
drawing_tool: type[tool.Drawing],
drawing: ifcopenshell.entity_instance,
object_type: str,
relating_type: ifcopenshell.entity_instance,
@@ -444,13 +456,16 @@ def add_annotation(
return obj
def build_schedule(drawing: tool.Drawing, schedule: ifcopenshell.entity_instance) -> None:
def build_schedule(drawing: type[tool.Drawing], schedule: ifcopenshell.entity_instance) -> None:
drawing.create_svg_schedule(schedule)
drawing.open_svg(drawing.get_path_with_ext(drawing.get_document_uri(schedule), "svg"))
def sync_references(
ifc: tool.Ifc, collector: tool.Collector, drawing_tool: tool.Drawing, drawing: ifcopenshell.entity_instance
ifc: type[tool.Ifc],
collector: type[tool.Collector],
drawing_tool: type[tool.Drawing],
drawing: ifcopenshell.entity_instance,
) -> None:
if not drawing_tool.has_annotation(drawing):
return
@@ -496,12 +511,15 @@ def sync_references(
drawing_tool.sync_object_representation(reference_obj)
def select_assigned_product(drawing: tool.Drawing, context: bpy.types.Context) -> None:
def select_assigned_product(drawing: type[tool.Drawing], context: bpy.types.Context) -> None:
drawing.select_assigned_product(context)
def activate_drawing_view(
ifc: tool.Ifc, blender: tool.Blender, drawing_tool: tool.Drawing, drawing: ifcopenshell.entity_instance
ifc: type[tool.Ifc],
blender: type[tool.Blender],
drawing_tool: type[tool.Drawing],
drawing: ifcopenshell.entity_instance,
) -> None:
camera = ifc.get_object(drawing)
if not camera:
+26 -18
View File
@@ -51,7 +51,7 @@ from shapely.ops import unary_union
from lxml import etree
from mathutils import Vector, Matrix
from fractions import Fraction
from typing import Optional, Union, Iterable, Any, Literal, Sequence, TYPE_CHECKING, NamedTuple
from typing import Optional, Union, Iterable, Any, Literal, Sequence, TYPE_CHECKING, NamedTuple, get_args
from pathlib import Path
if TYPE_CHECKING:
@@ -68,6 +68,9 @@ if TYPE_CHECKING:
class Drawing(bonsai.core.tool.Drawing):
ANNOTATION_DATA_TYPE = Literal["empty", "curve", "mesh"]
DOCUMENT_TYPE = Literal["SCHEDULE", "REFERENCE"]
LocationHintLiteral = Literal["PERSPECTIVE", "ORTHOGRAPHIC", "NORTH", "SOUTH", "EAST", "WEST"]
LOCATION_HINT_LITERALS = ("PERSPECTIVE", "ORTHOGRAPHIC", "NORTH", "SOUTH", "EAST", "WEST")
LocationHintType = Union[LocationHintLiteral, str]
# ObjectType: annotation_name, description, icon, data_type
# fmt: off
@@ -296,7 +299,7 @@ class Drawing(bonsai.core.tool.Drawing):
@classmethod
def create_camera(
cls, name: str, matrix: Matrix, location_hint: Literal["PERSPECTIVE", "ORTHOGRAPHIC"]
cls, name: str, matrix: Matrix, location_hint: Union[LocationHintLiteral, int]
) -> bpy.types.Object:
camera = bpy.data.objects.new(name, (camera_data := bpy.data.cameras.new(name)))
props = cls.get_camera_props(camera_data)
@@ -590,20 +593,21 @@ class Drawing(bonsai.core.tool.Drawing):
@classmethod
def generate_drawing_matrix(
cls, target_view: ifcopenshell.util.representation.TARGET_VIEW, location_hint: str
cls,
target_view: ifcopenshell.util.representation.TARGET_VIEW,
location_hint: Union[LocationHintLiteral, int],
) -> Matrix:
x, y, z = (0, 0, 0) if location_hint == 0 else bpy.context.scene.cursor.matrix.translation
if target_view == "PLAN_VIEW":
if isinstance(location_hint, int):
if location_hint:
z = tool.Ifc.get_object(tool.Ifc.get().by_id(location_hint)).matrix_world.translation.z
return mathutils.Matrix(((1, 0, 0, x), (0, 1, 0, y), (0, 0, 1, z + 1.6), (0, 0, 0, 1)))
elif target_view == "REFLECTED_PLAN_VIEW":
if location_hint:
z = tool.Ifc.get_object(tool.Ifc.get().by_id(location_hint)).matrix_world.translation.z
m = mathutils.Matrix()
m[2][2] = -1
m.translation = (x, y, z + 1.6)
return m
if target_view == "PLAN_VIEW":
return mathutils.Matrix(((1, 0, 0, x), (0, 1, 0, y), (0, 0, 1, z + 1.6), (0, 0, 0, 1)))
elif target_view == "REFLECTED_PLAN_VIEW":
m = mathutils.Matrix()
m[2][2] = -1
m.translation = (x, y, z + 1.6)
return m
return mathutils.Matrix(((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, -1, 0), (0, 0, 0, 1)))
elif target_view == "ELEVATION_VIEW":
if location_hint == "NORTH":
@@ -1174,13 +1178,17 @@ class Drawing(bonsai.core.tool.Drawing):
@classmethod
def generate_drawing_name(
cls, target_view: ifcopenshell.util.representation.TARGET_VIEW, location_hint: str
cls,
target_view: ifcopenshell.util.representation.TARGET_VIEW,
location_hint: Union[LocationHintLiteral, int],
) -> str:
if target_view in ("PLAN_VIEW", "REFLECTED_PLAN_VIEW") and location_hint:
location = tool.Ifc.get().by_id(location_hint)
if target_view == "REFLECTED_PLAN_VIEW":
target_view = "RCP_VIEW"
return (location.Name or "UNNAMED").upper() + " " + target_view.split("_")[0]
if isinstance(location_hint, int):
if location_hint:
location = tool.Ifc.get().by_id(location_hint)
target_view_ = target_view
if target_view == "REFLECTED_PLAN_VIEW":
target_view_ = "RCP_VIEW"
return (location.Name or "UNNAMED").upper() + " " + target_view_.split("_")[0]
elif target_view in ("SECTION_VIEW", "ELEVATION_VIEW") and location_hint:
return location_hint + " " + target_view.split("_")[0]
elif target_view == "MODEL_VIEW" and location_hint: