This commit is contained in:
Andrej730
2025-07-28 11:48:20 +05:00
parent cdeeab4b31
commit 0cb6d9de72
10 changed files with 69 additions and 28 deletions
+2 -2
View File
@@ -366,7 +366,7 @@ BOOST_LOCATION = f"https://github.com/boostorg/boost/releases/download/boost-{BO
# Helper functions
def run_autoconf(arg1, configure_args, cwd):
def run_autoconf(arg1: str, configure_args: "list[str]", cwd: str) -> None:
configure_path = os.path.realpath(os.path.join(cwd, "..", "configure"))
if not os.path.exists(configure_path):
run(
@@ -392,7 +392,7 @@ def run_autoconf(arg1, configure_args, cwd):
)
def run_cmake(arg1, cmake_args, cmake_dir=None, cwd=None):
def run_cmake(arg1, cmake_args: "list[str]", cmake_dir: Union[str, None] = None, cwd: Union[str, None] = None):
if cmake_dir is None:
P = ".."
else:
@@ -75,7 +75,8 @@ class DemonstrateRenameProject(bpy.types.Operator, tool.Ifc.Operator):
# properties. Generally, the inputs to the core function will come from
# properties (such as an input field) or data from the scene (like the
# actively selected object).
core.demonstrate_rename_project(tool.Ifc, tool.Demo, name=bpy.context.scene.BIMDemoProperties.name)
props = tool.Demo.get_demo_props()
core.demonstrate_rename_project(tool.Ifc, tool.Demo, name=props.name)
class SendWebUiDemoMessage(bpy.types.Operator):
@@ -89,5 +90,6 @@ class SendWebUiDemoMessage(bpy.types.Operator):
# and calling the operator connect_websocket_server if we aren't connected to a Web UI
if not context.scene.WebProperties.is_connected:
bpy.ops.bim.connect_websocket_server(page="demo")
core.send_webui_demo_message(tool.Web, message=bpy.context.scene.BIMDemoProperties.webui_message)
props = tool.Demo.get_demo_props()
core.send_webui_demo_message(tool.Web, message=props.webui_message)
return {"FINISHED"}
+10
View File
@@ -30,6 +30,8 @@
# property. Properties are stored in the .blend file, so when your user closes
# their Blender session, and reopens it, things are how they left it.
from typing import TYPE_CHECKING
import bpy
from bpy.types import PropertyGroup
@@ -60,3 +62,11 @@ class BIMDemoProperties(PropertyGroup):
message: StringProperty(name="Message")
show_hints: BoolProperty(name="Show Hints", default=False)
webui_message: StringProperty(name="Web UI Message", default="Hello, Web UI!")
# Type checking block is needed
# as type checker can't understand Blender props types by default.
if TYPE_CHECKING:
name: str
message: str
show_hints: bool
webui_message: str
+3 -2
View File
@@ -27,6 +27,7 @@
# panels, buttons, labels, and input fields are laid out.
import bpy
import bonsai.tool as tool
from bonsai.bim.module.demo.data import DemoData
@@ -70,7 +71,7 @@ class BIM_PT_demo(bpy.types.Panel):
# Interface panels often show properties. For convenience, define where
# the properties are stored for the module.
self.props = context.scene.BIMDemoProperties
self.props = tool.Demo.get_demo_props()
# This defines a new "row" in our layout. When a new row is defined, the
# things on that row, like buttons, labels, and input fields, show on a
@@ -145,7 +146,7 @@ class BIM_PT_webui_demo(bpy.types.Panel):
bl_parent_id = "BIM_PT_demo"
def draw(self, context):
self.props = context.scene.BIMDemoProperties
self.props = tool.Demo.get_demo_props()
row = self.layout.row()
# we create an input field for the property webui_message
@@ -893,7 +893,7 @@ class ProductDecorator:
@classmethod
def uninstall(cls):
props = bpy.context.scene.BIMProductPreviewProperties # updated by model/polyline.py
props = tool.Model.get_product_preview_props() # updated by model/polyline.py
props.verts.clear()
props.edges.clear()
props.tris.clear()
@@ -912,9 +912,9 @@ class ProductDecorator:
shader.uniform_float("color", color)
batch.draw(shader)
def get_product_preview_data(self, context):
props = context.scene.BIMProductPreviewProperties
data = {}
def get_product_preview_data(self, context) -> dict[str, Any]:
props = tool.Model.get_product_preview_props()
data: dict[str, Any] = {}
data["verts"] = [(*v.value_3d,) for v in props.verts]
data["edges"] = [(int(e.value_2d[0]), int(e.value_2d[1])) for e in props.edges]
data["tris"] = [(int(t.value_3d[0]), int(t.value_3d[1]), int(t.value_3d[2])) for t in props.tris]
@@ -962,7 +962,7 @@ class PolylineOperator:
data = get_generic_product_preview_data(context, relating_type)
# Update properties so it can be used by the decorator
props = context.scene.BIMProductPreviewProperties
props = tool.Model.get_product_preview_props()
props.verts.clear()
props.edges.clear()
props.tris.clear()
+25 -9
View File
@@ -29,16 +29,28 @@
# Blender's property systems, IFC's data structures, the filesystem, geometry
# processing, and more.
from __future__ import annotations
import bpy
import ifcopenshell
import bonsai.core.tool
import bonsai.tool as tool
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from bonsai.bim.module.demo.prop import BIMDemoProperties
# There is always one class in each tool file, which implements the interface
# defined by `core/tool.py`.
class Demo(bonsai.core.tool.Demo):
@classmethod
def clear_name_field(cls):
def get_demo_props(cls) -> BIMDemoProperties:
assert (scene := bpy.context.scene)
return scene.BIMDemoProperties # pyright: ignore[reportAttributeAccessIssue]
@classmethod
def clear_name_field(cls) -> None:
# In this concrete implementation, we see that "clear name field"
# actually translates to "set this Blender string property to empty
# string". In this case, it's pretty simple - but even simple scenarios
@@ -47,20 +59,24 @@ class Demo(bonsai.core.tool.Demo):
# implementations separately from control flow. It also makes it easy to
# refactor and share functions, where every tool function is captured by
# a function name that describes its intention.
bpy.context.scene.BIMDemoProperties.name = ""
props = cls.get_demo_props()
props.name = ""
@classmethod
def get_project(cls):
def get_project(cls) -> ifcopenshell.entity_instance:
return tool.Ifc.get().by_type("IfcProject")[0]
@classmethod
def hide_user_hints(cls):
bpy.context.scene.BIMDemoProperties.show_hints = False
def hide_user_hints(cls) -> None:
props = cls.get_demo_props()
props.show_hints = False
@classmethod
def set_message(cls, message):
bpy.context.scene.BIMDemoProperties.message = message
def set_message(cls, message) -> None:
props = cls.get_demo_props()
props.message = message
@classmethod
def show_user_hints(cls):
bpy.context.scene.BIMDemoProperties.show_hints = True
def show_user_hints(cls) -> None:
props = cls.get_demo_props()
props.show_hints = True
+6
View File
@@ -66,6 +66,7 @@ if TYPE_CHECKING:
BIMRailingProperties,
BIMExternalParametricGeometryProperties,
BIMPolylineProperties,
BIMProductPreviewProperties,
)
@@ -107,6 +108,11 @@ class Model(bonsai.core.tool.Model):
assert (scene := bpy.context.scene)
return scene.BIMPolylineProperties # pyright: ignore[reportAttributeAccessIssue]
@classmethod
def get_product_preview_props(cls) -> BIMProductPreviewProperties:
assert (scene := bpy.context.scene)
return scene.BIMProductPreviewProperties # pyright: ignore[reportAttributeAccessIssue]
@classmethod
def convert_si_to_unit(cls, value: T) -> T:
if isinstance(value, (tuple, list)):
+12 -8
View File
@@ -55,9 +55,10 @@ class TestImplementsTool(NewFile):
# these tests.
class TestClearNameField(NewFile):
def test_run(self):
bpy.context.scene.BIMDemoProperties.name = "name"
props = tool.Demo.get_demo_props()
props.name = "name"
subject.clear_name_field()
assert bpy.context.scene.BIMDemoProperties.name == ""
assert props.name == ""
class TestGetProject(NewFile):
@@ -73,22 +74,25 @@ class TestGetProject(NewFile):
class TestHideUserHints(NewFile):
def test_run(self):
bpy.context.scene.BIMDemoProperties.show_hints = True
props = tool.Demo.get_demo_props()
props.show_hints = True
subject.hide_user_hints()
assert bpy.context.scene.BIMDemoProperties.show_hints == False
assert props.show_hints == False
class TestSetMessage(NewFile):
def test_run(self):
bpy.context.scene.BIMDemoProperties.message = ""
props = tool.Demo.get_demo_props()
props.message = ""
subject.set_message("message")
assert bpy.context.scene.BIMDemoProperties.message == "message"
assert props.message == "message"
class TestShowUserHints(NewFile):
def test_run(self):
bpy.context.scene.BIMDemoProperties.show_hints = False
props = tool.Demo.get_demo_props()
props.show_hints = False
subject.show_user_hints()
assert bpy.context.scene.BIMDemoProperties.show_hints == True
assert props.show_hints == True
"""
+2
View File
@@ -21,6 +21,7 @@ import os
import csv
import numpy as np
import ifcopenshell
import ifcopenshell.api.pset
import ifcopenshell.api.root
import ifcopenshell.api.unit
import ifcopenshell.api.style
@@ -30,6 +31,7 @@ import ifcopenshell.api.project
import ifcopenshell.api.spatial
import ifcopenshell.api.geometry
import ifcopenshell.api.aggregate
import ifcopenshell.util.shape_builder
from itertools import cycle
from ifcopenshell.util.shape_builder import V