mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Add instructions to IFCTester in Blender (#7195)
* add instructions to blender ui * add requirement instructions to html * black .
This commit is contained in:
@@ -484,6 +484,7 @@ class SelectRequirement(bpy.types.Operator):
|
||||
props.n_entities = len(failed_entities)
|
||||
props.has_entities = True if props.n_entities > 0 else False
|
||||
props.failed_entities.clear()
|
||||
props.active_requirement_index = self.req_index
|
||||
|
||||
for e in failed_entities:
|
||||
new_entity = props.failed_entities.add()
|
||||
|
||||
@@ -71,6 +71,8 @@ class IfcTesterProperties(PropertyGroup):
|
||||
generate_ods_report: BoolProperty(default=False, name="Generate ODS report", options=set())
|
||||
flag: BoolProperty(default=False, name="Flag Failed Entities", options=set())
|
||||
active_specification_index: IntProperty(name="Active Specification Index", update=update_active_specification_index)
|
||||
active_requirement_index: IntProperty(name="Active Requirement Index")
|
||||
|
||||
old_index: IntProperty(name="", default=0)
|
||||
active_failed_entity_index: IntProperty(name="Active Failed Entity Index")
|
||||
specifications: CollectionProperty(name="Specifications", type=Specification)
|
||||
@@ -89,6 +91,7 @@ class IfcTesterProperties(PropertyGroup):
|
||||
generate_ods_report: bool
|
||||
flag: bool
|
||||
active_specification_index: int
|
||||
active_requirement_index: int
|
||||
old_index: int
|
||||
active_failed_entity_index: int
|
||||
specifications: bpy.types.bpy_prop_collection_idprop[Specification]
|
||||
|
||||
@@ -20,6 +20,8 @@ from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from bonsai.bim.ui import draw_multiline_text
|
||||
|
||||
import bpy
|
||||
from bpy.types import Panel, UIList
|
||||
import bonsai.tool as tool
|
||||
@@ -95,11 +97,11 @@ class BIM_PT_tester(Panel):
|
||||
"active_specification_index",
|
||||
)
|
||||
|
||||
self.draw_editable_ui()
|
||||
self.draw_editable_ui(context)
|
||||
row = self.layout.row()
|
||||
row.operator("bim.export_bcf", text="Export BCF", icon="EXPORT")
|
||||
|
||||
def draw_editable_ui(self) -> None:
|
||||
def draw_editable_ui(self, context: bpy.types.Context) -> None:
|
||||
props = tool.Tester.get_tester_props()
|
||||
specification = TesterData.data["specification"]
|
||||
|
||||
@@ -110,6 +112,13 @@ class BIM_PT_tester(Panel):
|
||||
row.label(
|
||||
text=f'Passed: {specification["total_checks_pass"]}/{specification["total_checks"]} ({specification["percent_checks_pass"]}%)'
|
||||
)
|
||||
row = self.layout.row()
|
||||
if specification.get("instructions"):
|
||||
row.label(text="Instructions:")
|
||||
box = self.layout.box()
|
||||
column = box.column(align=True)
|
||||
draw_multiline_text(column, specification.get("instructions"), context=context)
|
||||
|
||||
row = self.layout.row()
|
||||
row.label(text=f"Requirements ({n_requirements}):")
|
||||
if props.flag:
|
||||
@@ -132,6 +141,16 @@ class BIM_PT_tester(Panel):
|
||||
and props.n_entities > 0
|
||||
and len(props.failed_entities) > 0
|
||||
):
|
||||
|
||||
requirement = specification["requirements"][props.active_requirement_index]
|
||||
metadata = requirement.get("metadata")
|
||||
if metadata and metadata.get("@instructions"):
|
||||
row = self.layout.row()
|
||||
row.label(text="Instructions:")
|
||||
box = self.layout.box()
|
||||
column = box.column(align=True)
|
||||
draw_multiline_text(column, metadata.get("@instructions"), context=context)
|
||||
|
||||
row = self.layout.row()
|
||||
row.label(text=f"Failed entities [{props.n_entities}]:")
|
||||
self.layout.template_list(
|
||||
|
||||
@@ -40,6 +40,7 @@ from bonsai.bim.module.bsdd.prop import BIMBSDDProperties, BSDDProperty
|
||||
from bonsai.bim.module.pset.prop import IfcProperty
|
||||
from typing import Optional, TYPE_CHECKING, Literal
|
||||
from natsort import natsorted
|
||||
import textwrap
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -1491,6 +1492,31 @@ def draw_custom_context_menu(self: bpy.types.Menu, context: bpy.types.Context) -
|
||||
url_op.uri = url
|
||||
|
||||
|
||||
def draw_multiline_text(
|
||||
layout: bpy.types.UILayout,
|
||||
text: str,
|
||||
*,
|
||||
context: bpy.types.Context | None = None,
|
||||
) -> None:
|
||||
"""Render a read-only text box that wraps long text."""
|
||||
assert layout
|
||||
|
||||
region_width = 200
|
||||
if context and context.region:
|
||||
region_width = context.region.width
|
||||
|
||||
approximate_char_width = 7 # Empirical average width for Blender UI font (px)
|
||||
wrap_width = max(20, int(region_width / approximate_char_width))
|
||||
|
||||
for paragraph in text.splitlines():
|
||||
if not paragraph:
|
||||
layout.label(text="")
|
||||
continue
|
||||
|
||||
for line in textwrap.wrap(paragraph, width=wrap_width):
|
||||
layout.label(text=line)
|
||||
|
||||
|
||||
class BIM_PT_decorators_overlay(Panel):
|
||||
bl_space_type = "VIEW_3D"
|
||||
bl_region_type = "HEADER"
|
||||
|
||||
@@ -459,7 +459,8 @@ class Html(Json):
|
||||
requirement["total_passed_entities"] = total_passed_entities
|
||||
requirement["total_omitted_passes"] = total_passed_entities - self.entity_limit
|
||||
requirement["has_omitted_passes"] = total_passed_entities > self.entity_limit
|
||||
|
||||
requirement["instructions"] = requirement["metadata"].get("@instructions")
|
||||
|
||||
def limit_entities(self, entities):
|
||||
if len(entities) > self.entity_limit:
|
||||
if entities[0]["element_type"]:
|
||||
|
||||
@@ -157,6 +157,14 @@
|
||||
<summary>
|
||||
{{description}}
|
||||
</summary>
|
||||
{{#instructions}}
|
||||
<div class="instructions">
|
||||
<p>
|
||||
<strong>Instructions</strong>
|
||||
</p>
|
||||
{{instructions}}
|
||||
</div>
|
||||
{{/instructions}}
|
||||
{{#total_ckecks}}
|
||||
<table class="skipped">
|
||||
<thead>
|
||||
|
||||
Reference in New Issue
Block a user