This commit is contained in:
Andrej730
2025-03-07 20:38:01 +05:00
parent 3886c79a2c
commit c4b57eb903
9 changed files with 73 additions and 44 deletions
+2 -2
View File
@@ -284,8 +284,8 @@ class BIMStylesProperties(PropertyGroup):
active_style_index: IntProperty(name="Active Style Index") active_style_index: IntProperty(name="Active Style Index")
@property @property
def active_style(self): def active_style(self) -> Union[Style, None]:
return self.styles[self.active_style_index] if 0 <= self.active_style_index < len(self.styles) else None return tool.Blender.get_active_uilist_element(self.styles, self.active_style_index)
active_style_type: EnumProperty( active_style_type: EnumProperty(
name="Active Style Type", name="Active Style Type",
@@ -41,7 +41,8 @@ def transparent_color(color, alpha=0.1):
@persistent @persistent
def toggle_decorations_on_load(*args): def toggle_decorations_on_load(*args):
if bpy.context.scene.BIMSystemProperties.should_draw_decorations: props = tool.System.get_system_props()
if props.should_draw_decorations:
SystemDecorator.install(bpy.context) SystemDecorator.install(bpy.context)
else: else:
SystemDecorator.uninstall() SystemDecorator.uninstall()
@@ -50,7 +50,8 @@ class AddSystem(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
def _execute(self, context): def _execute(self, context):
core.add_system(tool.Ifc, tool.System, ifc_class=context.scene.BIMSystemProperties.system_class) props = tool.System.get_system_props()
core.add_system(tool.Ifc, tool.System, ifc_class=props.system_class)
class EditSystem(bpy.types.Operator, tool.Ifc.Operator): class EditSystem(bpy.types.Operator, tool.Ifc.Operator):
@@ -59,9 +60,8 @@ class EditSystem(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
def _execute(self, context): def _execute(self, context):
core.edit_system( props = tool.System.get_system_props()
tool.Ifc, tool.System, system=tool.Ifc.get().by_id(context.scene.BIMSystemProperties.edited_system_id) core.edit_system(tool.Ifc, tool.System, system=tool.Ifc.get().by_id(props.edited_system_id))
)
class RemoveSystem(bpy.types.Operator, tool.Ifc.Operator): class RemoveSystem(bpy.types.Operator, tool.Ifc.Operator):
+9 -2
View File
@@ -34,7 +34,7 @@ from bpy.props import (
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
def get_system_class(self, context): def get_system_class(self: "BIMSystemProperties", context: bpy.types.Context) -> list[tuple[str, str, str]]:
if not SystemData.is_loaded: if not SystemData.is_loaded:
SystemData.load() SystemData.load()
return SystemData.data["system_class"] return SystemData.data["system_class"]
@@ -45,13 +45,20 @@ class System(PropertyGroup):
ifc_class: StringProperty(name="IFC Class") ifc_class: StringProperty(name="IFC Class")
ifc_definition_id: IntProperty(name="IFC Definition ID") ifc_definition_id: IntProperty(name="IFC Definition ID")
if TYPE_CHECKING:
ifc_class: str
ifc_definition_id: int
class Zone(PropertyGroup): class Zone(PropertyGroup):
name: StringProperty(name="Name") name: StringProperty(name="Name")
ifc_definition_id: IntProperty(name="IFC Definition ID") ifc_definition_id: IntProperty(name="IFC Definition ID")
if TYPE_CHECKING:
ifc_definition_id: int
def toggle_decorations(self, context):
def toggle_decorations(self: "BIMSystemProperties", context: bpy.types.Context) -> None:
toggle = self.should_draw_decorations toggle = self.should_draw_decorations
if toggle: if toggle:
decorator.SystemDecorator.install(context) decorator.SystemDecorator.install(context)
+36 -11
View File
@@ -16,12 +16,17 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
import bpy import bpy
import bonsai.bim.helper import bonsai.bim.helper
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.helper import prop_with_search, draw_attributes from bonsai.bim.helper import prop_with_search, draw_attributes
from bpy.types import Panel, UIList from bpy.types import Panel, UIList
from bonsai.bim.module.system.data import SystemData, ZonesData, ActiveObjectZonesData, ObjectSystemData, PortData from bonsai.bim.module.system.data import SystemData, ZonesData, ActiveObjectZonesData, ObjectSystemData, PortData
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from bonsai.bim.module.system.prop import BIMSystemProperties, System, BIMZoneProperties, Zone
FLOW_DIRECTION_TO_ICON = { FLOW_DIRECTION_TO_ICON = {
@@ -69,7 +74,7 @@ class BIM_PT_systems(Panel):
op = row.operator("bim.unassign_system", text="", icon="X") op = row.operator("bim.unassign_system", text="", icon="X")
op.system = system_id op.system = system_id
self.props = context.scene.BIMSystemProperties self.props = tool.System.get_system_props()
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(self.props, "should_draw_decorations") row.prop(self.props, "should_draw_decorations")
@@ -142,7 +147,8 @@ class BIM_PT_ports(Panel):
def draw(self, context): def draw(self, context):
if not PortData.is_loaded: if not PortData.is_loaded:
PortData.load() PortData.load()
self.props = context.scene.BIMSystemProperties
self.props = tool.System.get_system_props()
row = self.layout.row(align=True) row = self.layout.row(align=True)
total_ports = PortData.data["total_ports"] total_ports = PortData.data["total_ports"]
@@ -217,7 +223,7 @@ class BIM_PT_port(Panel):
return True return True
def draw(self, context): def draw(self, context):
self.props = context.scene.BIMSystemProperties self.props = tool.System.get_system_props()
layout = self.layout layout = self.layout
row = layout.row(align=True) row = layout.row(align=True)
@@ -295,7 +301,7 @@ class BIM_PT_flow_controls(Panel):
if not ObjectSystemData.is_loaded: if not ObjectSystemData.is_loaded:
ObjectSystemData.load() ObjectSystemData.load()
def display_element(control_id, flow_element_id, displayed_object_name): def display_element(control_id: int, flow_element_id: int, displayed_object_name: str) -> None:
displayed_object = bpy.data.objects[displayed_object_name] displayed_object = bpy.data.objects[displayed_object_name]
row = self.layout.row(align=True) row = self.layout.row(align=True)
op = row.operator("bim.assign_unassign_flow_control", text="", icon="X") op = row.operator("bim.assign_unassign_flow_control", text="", icon="X")
@@ -355,13 +361,14 @@ class BIM_PT_zones(Panel):
row.operator("bim.load_zones", text="", icon="IMPORT") row.operator("bim.load_zones", text="", icon="IMPORT")
return return
row.operator("bim.add_zone", text="", icon="ADD")
row.operator("bim.unload_zones", text="", icon="CANCEL") row.operator("bim.unload_zones", text="", icon="CANCEL")
row = self.layout.row(align=True)
row.alignment = "RIGHT"
row.operator("bim.add_zone", text="", icon="ADD")
if self.props.zones and self.props.active_zone_index < len(self.props.zones): if self.props.zones and self.props.active_zone_index < len(self.props.zones):
row = self.layout.row(align=True)
ifc_definition_id = self.props.zones[self.props.active_zone_index].ifc_definition_id ifc_definition_id = self.props.zones[self.props.active_zone_index].ifc_definition_id
row.operator("bim.enable_editing_zone", text="Edit Zone", icon="GREASEPENCIL").zone = ifc_definition_id row.operator("bim.enable_editing_zone", text="", icon="GREASEPENCIL").zone = ifc_definition_id
row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF").system = ifc_definition_id row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF").system = ifc_definition_id
row.operator("bim.assign_system", text="", icon="KEYFRAME_HLT").system = ifc_definition_id row.operator("bim.assign_system", text="", icon="KEYFRAME_HLT").system = ifc_definition_id
row.operator("bim.unassign_system", text="", icon="KEYFRAME").system = ifc_definition_id row.operator("bim.unassign_system", text="", icon="KEYFRAME").system = ifc_definition_id
@@ -403,18 +410,27 @@ class BIM_PT_active_object_zones(Panel):
class BIM_UL_systems(UIList): class BIM_UL_systems(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname): def draw_item(
self,
context,
layout: bpy.types.UILayout,
data: BIMSystemProperties,
item: System,
icon,
active_data,
active_propname,
):
if item: if item:
row = layout.row(align=True) row = layout.row(align=True)
row.label(text=item.name, icon=SYSTEM_ICONS[item.ifc_class]) row.label(text=item.name, icon=SYSTEM_ICONS[item.ifc_class])
system_id = item.ifc_definition_id system_id = item.ifc_definition_id
row.operator("bim.assign_system", text="", icon="ADD").system = item.ifc_definition_id row.operator("bim.assign_system", text="", icon="ADD").system = item.ifc_definition_id
if context.scene.BIMSystemProperties.edited_system_id == system_id: if data.edited_system_id == system_id:
op = row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF") op = row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF")
op.system = system_id op.system = system_id
row.operator("bim.edit_system", text="", icon="CHECKMARK") row.operator("bim.edit_system", text="", icon="CHECKMARK")
row.operator("bim.disable_editing_system", text="", icon="CANCEL") row.operator("bim.disable_editing_system", text="", icon="CANCEL")
elif context.scene.BIMSystemProperties.edited_system_id: elif data.edited_system_id:
op = row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF") op = row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF")
op.system = system_id op.system = system_id
op = row.operator("bim.remove_system", text="", icon="X") op = row.operator("bim.remove_system", text="", icon="X")
@@ -429,7 +445,16 @@ class BIM_UL_systems(UIList):
class BIM_UL_zones(UIList): class BIM_UL_zones(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname): def draw_item(
self,
context,
layout: bpy.types.UILayout,
data: BIMZoneProperties,
item: Zone,
icon,
active_data,
active_propname,
):
if item: if item:
row = layout.row(align=True) row = layout.row(align=True)
row.label(text=item.name) row.label(text=item.name)
+1 -2
View File
@@ -30,12 +30,11 @@ import re
from math import pi, cos, sin from math import pi, cos, sin
from mathutils import Matrix, Vector from mathutils import Matrix, Vector
from bonsai.bim.module.system.data import ObjectSystemData, SystemDecorationData from bonsai.bim.module.system.data import ObjectSystemData, SystemDecorationData
from bonsai.bim.module.drawing.decoration import profile_consequential
from enum import Enum from enum import Enum
from typing import TYPE_CHECKING, Optional, Any, Union from typing import TYPE_CHECKING, Optional, Any, Union
if TYPE_CHECKING: if TYPE_CHECKING:
from bonsai.bim.module.system.prop import BIMSystemProperties, BIMZoneProperties from bonsai.bim.module.system.prop import BIMSystemProperties, BIMZoneProperties, BIMZoneProperties
class System(bonsai.core.tool.System): class System(bonsai.core.tool.System):
+5 -4
View File
@@ -75,7 +75,7 @@ class Message:
translations: Optional[Dict[str, str]] = field(default_factory=dict) translations: Optional[Dict[str, str]] = field(default_factory=dict)
def bonsai_strings_parse(addon_directory=None, po_directory=None): def bonsai_strings_parse(addon_directory: Optional[Path] = None, po_directory: Optional[Path] = None):
# NOTE: we decided to use our own parser due bug in Blender parser # NOTE: we decided to use our own parser due bug in Blender parser
# as it tends to pick up strings from other addons and other Blender parts # as it tends to pick up strings from other addons and other Blender parts
# and this bug probably would be to low of a priority for Blender to fix # and this bug probably would be to low of a priority for Blender to fix
@@ -153,7 +153,7 @@ def bonsai_strings_parse(addon_directory=None, po_directory=None):
def update_translations_from_po(po_directory: Path, translations_module: Path): def update_translations_from_po(po_directory: Path, translations_module: Path):
translation_data: Dict[str, Message] = dict() translation_data: Dict[str, Message] = dict()
def process_po_entry(language, current_chunk: list[str]): def process_po_entry(language: str, current_chunk: list[str]) -> None:
sources = [] sources = []
msgid = None msgid = None
msgstr = None msgstr = None
@@ -171,6 +171,7 @@ def update_translations_from_po(po_directory: Path, translations_module: Path):
elif line.startswith("#:"): elif line.startswith("#:"):
sources.append(line.removeprefix("# ").strip()) sources.append(line.removeprefix("# ").strip())
assert msgid is not None and msgstr is not None
msg = translation_data.get(msgid) msg = translation_data.get(msgid)
if msg is None: if msg is None:
msg = Message(msgid, msgctxt, sources, {language: msgstr}) msg = Message(msgid, msgctxt, sources, {language: msgstr})
@@ -179,8 +180,8 @@ def update_translations_from_po(po_directory: Path, translations_module: Path):
msg.sources.extend(sources) msg.sources.extend(sources)
msg.translations[language] = msgstr msg.translations[language] = msgstr
# load data from .po files # load data from .po files to translation_data.
langs = set() langs: set[str] = set()
for po_file_path in po_directory.glob("**/*.po"): for po_file_path in po_directory.glob("**/*.po"):
lang = po_file_path.stem lang = po_file_path.stem
langs.add(lang) langs.add(lang)
+13 -9
View File
@@ -112,22 +112,25 @@ class TestDeleteElementObjects(NewFile):
class TestDisableEditingSystem(NewFile): class TestDisableEditingSystem(NewFile):
def test_run(self): def test_run(self):
bpy.context.scene.BIMSystemProperties.edited_system_id = 10 props = tool.System.get_system_props()
props.edited_system_id = 10
subject.disable_editing_system() subject.disable_editing_system()
assert bpy.context.scene.BIMSystemProperties.edited_system_id == 0 assert props.edited_system_id == 0
class TestDisableSystemEditingUI(NewFile): class TestDisableSystemEditingUI(NewFile):
def test_run(self): def test_run(self):
subject.enable_system_editing_ui() subject.enable_system_editing_ui()
subject.disable_system_editing_ui() subject.disable_system_editing_ui()
assert bpy.context.scene.BIMSystemProperties.is_editing is False props = tool.System.get_system_props()
assert props.is_editing is False
class TestEnableSystemEditingUI(NewFile): class TestEnableSystemEditingUI(NewFile):
def test_run(self): def test_run(self):
subject.enable_system_editing_ui() subject.enable_system_editing_ui()
assert bpy.context.scene.BIMSystemProperties.is_editing is True props = tool.System.get_system_props()
assert props.is_editing is True
class TestExportSystemAttributes(NewFile): class TestExportSystemAttributes(NewFile):
@@ -171,7 +174,7 @@ class TestImportSystemAttributes(NewFile):
system.Description = "Description" system.Description = "Description"
system.ObjectType = "ObjectType" system.ObjectType = "ObjectType"
subject().import_system_attributes(system) subject().import_system_attributes(system)
props = bpy.context.scene.BIMSystemProperties props = tool.System.get_system_props()
assert props.system_attributes.get("GlobalId").string_value == "GlobalId" assert props.system_attributes.get("GlobalId").string_value == "GlobalId"
assert props.system_attributes.get("Name").string_value == "Name" assert props.system_attributes.get("Name").string_value == "Name"
assert props.system_attributes.get("Description").string_value == "Description" assert props.system_attributes.get("Description").string_value == "Description"
@@ -188,7 +191,7 @@ class TestImportSystemAttributes(NewFile):
system.PredefinedType = "SHADING" system.PredefinedType = "SHADING"
system.LongName = "LongName" system.LongName = "LongName"
subject().import_system_attributes(system) subject().import_system_attributes(system)
props = bpy.context.scene.BIMSystemProperties props = tool.System.get_system_props()
assert props.system_attributes.get("GlobalId").string_value == "GlobalId" assert props.system_attributes.get("GlobalId").string_value == "GlobalId"
assert props.system_attributes.get("Name").string_value == "Name" assert props.system_attributes.get("Name").string_value == "Name"
assert props.system_attributes.get("Description").string_value == "Description" assert props.system_attributes.get("Description").string_value == "Description"
@@ -207,7 +210,7 @@ class TestImportSystemAttributes(NewFile):
system.PredefinedType = "ELECTRICAL" system.PredefinedType = "ELECTRICAL"
system.LongName = "LongName" system.LongName = "LongName"
subject().import_system_attributes(system) subject().import_system_attributes(system)
props = bpy.context.scene.BIMSystemProperties props = tool.System.get_system_props()
assert props.system_attributes.get("GlobalId").string_value == "GlobalId" assert props.system_attributes.get("GlobalId").string_value == "GlobalId"
assert props.system_attributes.get("Name").string_value == "Name" assert props.system_attributes.get("Name").string_value == "Name"
assert props.system_attributes.get("Description").string_value == "Description" assert props.system_attributes.get("Description").string_value == "Description"
@@ -223,7 +226,7 @@ class TestImportSystems(NewFile):
system = ifc.createIfcDistributionSystem() system = ifc.createIfcDistributionSystem()
zone = ifc.createIfcZone() zone = ifc.createIfcZone()
subject.import_systems() subject.import_systems()
props = bpy.context.scene.BIMSystemProperties props = tool.System.get_system_props()
assert len(props.systems) == 2 assert len(props.systems) == 2
assert props.systems[0].ifc_definition_id == system.id() assert props.systems[0].ifc_definition_id == system.id()
assert props.systems[0].name == "Unnamed" assert props.systems[0].name == "Unnamed"
@@ -277,7 +280,8 @@ class TestSetActiveSystem(NewFile):
tool.Ifc().set(ifc) tool.Ifc().set(ifc)
system = ifcopenshell.api.run("system.add_system", ifc, ifc_class="IfcSystem") system = ifcopenshell.api.run("system.add_system", ifc, ifc_class="IfcSystem")
subject.set_active_edited_system(system) subject.set_active_edited_system(system)
assert bpy.context.scene.BIMSystemProperties.edited_system_id == system.id() props = tool.System.get_system_props()
assert props.edited_system_id == system.id()
class TestFlowElementAndControls(NewFile): class TestFlowElementAndControls(NewFile):
@@ -29,11 +29,8 @@ def unassign_system(
"""Unassigns list of products from a system """Unassigns list of products from a system
:param products: The list of IfcDistributionElements to unassign from the system. :param products: The list of IfcDistributionElements to unassign from the system.
:type products: list[ifcopenshell.entity_instance]
:param system: The IfcSystem you want to unassign the element from. :param system: The IfcSystem you want to unassign the element from.
:type system: ifcopenshell.entity_instance
:return: None :return: None
:rtype: None
Example: Example:
@@ -52,9 +49,4 @@ def unassign_system(
# Not anymore! # Not anymore!
ifcopenshell.api.system.unassign_system(model, products=[duct], system=system) ifcopenshell.api.system.unassign_system(model, products=[duct], system=system)
""" """
settings = { ifcopenshell.api.group.unassign_group(file, products=products, group=system)
"products": products,
"system": system,
}
ifcopenshell.api.group.unassign_group(file, products=settings["products"], group=settings["system"])