mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 22:33:33 +00:00
Visual clean up of annotation tool to only activate when a drawing is active and have a type manager similar to the BIM tool.
This commit is contained in:
@@ -24,13 +24,14 @@ classes = (
|
|||||||
operator.ActivateDrawingStyle,
|
operator.ActivateDrawingStyle,
|
||||||
operator.ActivateModel,
|
operator.ActivateModel,
|
||||||
operator.AddAnnotation,
|
operator.AddAnnotation,
|
||||||
|
operator.AddAnnotationType,
|
||||||
operator.AddDrawing,
|
operator.AddDrawing,
|
||||||
operator.AddDrawingStyle,
|
operator.AddDrawingStyle,
|
||||||
operator.AddDrawingStyleAttribute,
|
operator.AddDrawingStyleAttribute,
|
||||||
operator.AddDrawingToSheet,
|
operator.AddDrawingToSheet,
|
||||||
|
operator.AddReferenceToSheet,
|
||||||
operator.AddSchedule,
|
operator.AddSchedule,
|
||||||
operator.AddScheduleToSheet,
|
operator.AddScheduleToSheet,
|
||||||
operator.AddReferenceToSheet,
|
|
||||||
operator.AddSheet,
|
operator.AddSheet,
|
||||||
operator.AddTextLiteral,
|
operator.AddTextLiteral,
|
||||||
operator.BuildSchedule,
|
operator.BuildSchedule,
|
||||||
@@ -38,6 +39,7 @@ classes = (
|
|||||||
operator.ContractSheet,
|
operator.ContractSheet,
|
||||||
operator.CreateDrawing,
|
operator.CreateDrawing,
|
||||||
operator.CreateSheets,
|
operator.CreateSheets,
|
||||||
|
operator.DisableAddAnnotationType,
|
||||||
operator.DisableEditingAssignedProduct,
|
operator.DisableEditingAssignedProduct,
|
||||||
operator.DisableEditingDrawings,
|
operator.DisableEditingDrawings,
|
||||||
operator.DisableEditingSchedules,
|
operator.DisableEditingSchedules,
|
||||||
@@ -47,6 +49,7 @@ classes = (
|
|||||||
operator.EditAssignedProduct,
|
operator.EditAssignedProduct,
|
||||||
operator.EditSheet,
|
operator.EditSheet,
|
||||||
operator.EditText,
|
operator.EditText,
|
||||||
|
operator.EnableAddAnnotationType,
|
||||||
operator.EditTextPopup,
|
operator.EditTextPopup,
|
||||||
operator.EnableEditingAssignedProduct,
|
operator.EnableEditingAssignedProduct,
|
||||||
operator.EnableEditingText,
|
operator.EnableEditingText,
|
||||||
@@ -102,6 +105,7 @@ classes = (
|
|||||||
gizmos.DimensionLabelGizmo,
|
gizmos.DimensionLabelGizmo,
|
||||||
gizmos.ExtrusionGuidesGizmo,
|
gizmos.ExtrusionGuidesGizmo,
|
||||||
gizmos.ExtrusionWidget,
|
gizmos.ExtrusionWidget,
|
||||||
|
workspace.LaunchAnnotationTypeManager,
|
||||||
workspace.Hotkey,
|
workspace.Hotkey,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -335,18 +335,31 @@ class AnnotationData:
|
|||||||
def load(cls):
|
def load(cls):
|
||||||
cls.is_loaded = True
|
cls.is_loaded = True
|
||||||
cls.props = bpy.context.scene.BIMAnnotationProperties
|
cls.props = bpy.context.scene.BIMAnnotationProperties
|
||||||
cls.data["relating_types"] = cls.get_relating_types()
|
cls.data["relating_type_id"] = cls.relating_type_id()
|
||||||
|
cls.data["relating_types"] = cls.relating_types()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_relating_types(cls):
|
def relating_type_id(cls):
|
||||||
object_type = cls.props.object_type
|
object_type = cls.props.object_type
|
||||||
relating_types = []
|
relating_types = []
|
||||||
for relating_type in tool.Ifc.get().by_type("IfcTypeProduct"):
|
for relating_type in tool.Ifc.get().by_type("IfcTypeProduct"):
|
||||||
if tool.Drawing.is_annotation_object_type(relating_type, object_type):
|
if tool.Drawing.is_annotation_object_type(relating_type, object_type):
|
||||||
relating_types.append(relating_type)
|
relating_types.append(relating_type)
|
||||||
|
|
||||||
enum_items = [(str(e.id()), e.Name or "Unnamed", e.Description or "") for e in relating_types]
|
results = [("0", "Untyped", "")]
|
||||||
|
results.extend([(str(e.id()), e.Name or "Unnamed", e.Description or "") for e in relating_types])
|
||||||
|
return results
|
||||||
|
|
||||||
# item to create anootations without relating types
|
@classmethod
|
||||||
enum_items.insert(0, ("0", "-", ""))
|
def relating_types(cls):
|
||||||
return enum_items
|
object_type = cls.props.object_type
|
||||||
|
relating_types = []
|
||||||
|
for relating_type in tool.Ifc.get().by_type("IfcTypeProduct"):
|
||||||
|
if tool.Drawing.is_annotation_object_type(relating_type, object_type):
|
||||||
|
relating_types.append({
|
||||||
|
"id": relating_type.id(),
|
||||||
|
"name": relating_type.Name or "Unnamed",
|
||||||
|
"description": relating_type.Description or "No Description",
|
||||||
|
})
|
||||||
|
|
||||||
|
return sorted(relating_types, key=lambda x: x["name"])
|
||||||
|
|||||||
@@ -84,6 +84,52 @@ class Operator:
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class AddAnnotationType(bpy.types.Operator, Operator):
|
||||||
|
bl_idname = "bim.add_annotation_type"
|
||||||
|
bl_label = "Add Annotation Type"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
props = context.scene.BIMAnnotationProperties
|
||||||
|
object_type = props.object_type
|
||||||
|
has_representation = props.create_representation_for_type
|
||||||
|
drawing = tool.Ifc.get_entity(bpy.context.scene.camera)
|
||||||
|
|
||||||
|
if props.create_representation_for_type:
|
||||||
|
obj = tool.Drawing.create_annotation_object(drawing, object_type)
|
||||||
|
else:
|
||||||
|
obj = bpy.data.objects.new(object_type, None)
|
||||||
|
|
||||||
|
obj.name = props.type_name
|
||||||
|
element = tool.Drawing.run_root_assign_class(
|
||||||
|
obj=obj,
|
||||||
|
ifc_class="IfcTypeProduct",
|
||||||
|
predefined_type=object_type,
|
||||||
|
should_add_representation=has_representation,
|
||||||
|
context=ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Annotation", "MODEL_VIEW"),
|
||||||
|
ifc_representation_class=tool.Drawing.get_ifc_representation_class(object_type),
|
||||||
|
)
|
||||||
|
element.ApplicableOccurrence = f"IfcAnnotation/{object_type}"
|
||||||
|
|
||||||
|
|
||||||
|
class EnableAddAnnotationType(bpy.types.Operator, Operator):
|
||||||
|
bl_idname = "bim.enable_add_annotation_type"
|
||||||
|
bl_label = "Enable Add Annotation Type"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
bpy.context.scene.BIMAnnotationProperties.is_adding_type = True
|
||||||
|
|
||||||
|
|
||||||
|
class DisableAddAnnotationType(bpy.types.Operator, Operator):
|
||||||
|
bl_idname = "bim.disable_add_annotation_type"
|
||||||
|
bl_label = "Disable Add Annotation Type"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
bpy.context.scene.BIMAnnotationProperties.is_adding_type = False
|
||||||
|
|
||||||
|
|
||||||
class AddDrawing(bpy.types.Operator, Operator):
|
class AddDrawing(bpy.types.Operator, Operator):
|
||||||
bl_idname = "bim.add_drawing"
|
bl_idname = "bim.add_drawing"
|
||||||
bl_label = "Add Drawing"
|
bl_label = "Add Drawing"
|
||||||
|
|||||||
@@ -499,7 +499,7 @@ ANNOTATION_TYPES_DATA = {
|
|||||||
"PLAN_LEVEL": ("Level (Plan)", "", "SORTBYEXT", "curve"),
|
"PLAN_LEVEL": ("Level (Plan)", "", "SORTBYEXT", "curve"),
|
||||||
"SECTION_LEVEL": ("Level (Section)", "", "TRIA_DOWN", "curve"),
|
"SECTION_LEVEL": ("Level (Section)", "", "TRIA_DOWN", "curve"),
|
||||||
"BREAKLINE": ("Breakline", "", "FCURVE", "mesh"),
|
"BREAKLINE": ("Breakline", "", "FCURVE", "mesh"),
|
||||||
"LINEWORK": ("Line", "", "MESH_MONKEY", "mesh"),
|
"LINEWORK": ("Line", "", "SNAP_MIDPOINT", "mesh"),
|
||||||
"BATTING": ("Batting", "Add batting annotation.\nThickness could be changed through Thickness property of BBIM_Batting property set", "FORCE_FORCE", "mesh"),
|
"BATTING": ("Batting", "Add batting annotation.\nThickness could be changed through Thickness property of BBIM_Batting property set", "FORCE_FORCE", "mesh"),
|
||||||
"REVISION_CLOUD":("Revision Cloud", "Add revision cloud", "VOLUME_DATA", "mesh"),
|
"REVISION_CLOUD":("Revision Cloud", "Add revision cloud", "VOLUME_DATA", "mesh"),
|
||||||
"FILL_AREA": ("Fill Area", "", "NODE_TEXTURE", "mesh"),
|
"FILL_AREA": ("Fill Area", "", "NODE_TEXTURE", "mesh"),
|
||||||
@@ -510,13 +510,10 @@ ANNOTATION_TYPES_DATA = {
|
|||||||
annotation_classes = [(x, *ANNOTATION_TYPES_DATA[x][:3], i) for i, x in enumerate(ANNOTATION_TYPES_DATA)]
|
annotation_classes = [(x, *ANNOTATION_TYPES_DATA[x][:3], i) for i, x in enumerate(ANNOTATION_TYPES_DATA)]
|
||||||
|
|
||||||
|
|
||||||
def get_annotation_data_prop(prop_name):
|
def get_relating_type_id(self, context):
|
||||||
def function(self, context):
|
if not AnnotationData.is_loaded:
|
||||||
if not AnnotationData.is_loaded:
|
AnnotationData.load()
|
||||||
AnnotationData.load()
|
return AnnotationData.data["relating_type_id"]
|
||||||
return AnnotationData.data[prop_name]
|
|
||||||
|
|
||||||
return function
|
|
||||||
|
|
||||||
|
|
||||||
def update_annotation_object_type(self, context):
|
def update_annotation_object_type(self, context):
|
||||||
@@ -533,12 +530,12 @@ class BIMAnnotationProperties(PropertyGroup):
|
|||||||
object_type: bpy.props.EnumProperty(
|
object_type: bpy.props.EnumProperty(
|
||||||
name="Annotation Object Type", items=annotation_classes, default="TEXT", update=update_annotation_object_type
|
name="Annotation Object Type", items=annotation_classes, default="TEXT", update=update_annotation_object_type
|
||||||
)
|
)
|
||||||
relating_type_id: bpy.props.EnumProperty(
|
relating_type_id: bpy.props.EnumProperty(name="Relating Annotation Type", items=get_relating_type_id)
|
||||||
name="Relating Annotation Type", items=get_annotation_data_prop("relating_types")
|
|
||||||
)
|
|
||||||
create_representation_for_type: bpy.props.BoolProperty(
|
create_representation_for_type: bpy.props.BoolProperty(
|
||||||
name="Create Representation For Type",
|
name="Create Representation For Type",
|
||||||
default=False,
|
default=False,
|
||||||
description='Whether "Add type" should define a representation for the type \n'
|
description='Whether "Add type" should define a representation for the type \n'
|
||||||
"or allow occurences to have their own",
|
"or allow occurences to have their own",
|
||||||
)
|
)
|
||||||
|
is_adding_type: bpy.props.BoolProperty(default=False)
|
||||||
|
type_name: bpy.props.StringProperty(name="Name", default="TYPEX")
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ from blenderbim.bim.ifc import IfcStore
|
|||||||
import blenderbim.bim.handler
|
import blenderbim.bim.handler
|
||||||
|
|
||||||
|
|
||||||
# declaring it here to avoid circular import problems
|
# TODO: Fix circular import.
|
||||||
|
# Declaring it here to avoid circular import problems
|
||||||
class Operator:
|
class Operator:
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
IfcStore.execute_ifc_operator(self, context)
|
IfcStore.execute_ifc_operator(self, context)
|
||||||
@@ -38,6 +39,76 @@ class Operator:
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class LaunchAnnotationTypeManager(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.launch_annotation_type_manager"
|
||||||
|
bl_label = "Launch Annotation Type Manager"
|
||||||
|
bl_options = {"REGISTER"}
|
||||||
|
bl_description = "Manage annotation types and templates"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
return context.window_manager.invoke_popup(self, width=550)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
if not AnnotationData.is_loaded:
|
||||||
|
AnnotationData.load()
|
||||||
|
|
||||||
|
props = context.scene.BIMAnnotationProperties
|
||||||
|
|
||||||
|
columns = self.layout.column_flow(columns=3)
|
||||||
|
row = columns.row()
|
||||||
|
row.alignment = "LEFT"
|
||||||
|
row.label(text=f"{len(AnnotationData.data['relating_types'])} Types", icon="FILE_VOLUME")
|
||||||
|
|
||||||
|
row = columns.row(align=True)
|
||||||
|
row.alignment = "CENTER"
|
||||||
|
# In case you want something here in the future
|
||||||
|
|
||||||
|
row = columns.row(align=True)
|
||||||
|
row.alignment = "RIGHT"
|
||||||
|
# In case you want something here in the future
|
||||||
|
|
||||||
|
if props.is_adding_type:
|
||||||
|
row = self.layout.row()
|
||||||
|
box = row.box()
|
||||||
|
row = box.row()
|
||||||
|
row.prop(props, "type_name")
|
||||||
|
row = box.row()
|
||||||
|
row.prop(props, "create_representation_for_type", text="Geometric Type")
|
||||||
|
row = box.row(align=True)
|
||||||
|
row.operator("bim.add_annotation_type", icon="CHECKMARK", text="Save New Type")
|
||||||
|
row.operator("bim.disable_add_annotation_type", icon="CANCEL", text="")
|
||||||
|
else:
|
||||||
|
row = self.layout.row()
|
||||||
|
row.operator("bim.enable_add_annotation_type", icon="ADD", text="Create New Type")
|
||||||
|
|
||||||
|
flow = self.layout.grid_flow(row_major=True, columns=3, even_columns=True, even_rows=True, align=True)
|
||||||
|
|
||||||
|
for relating_type in AnnotationData.data["relating_types"]:
|
||||||
|
outer_col = flow.column()
|
||||||
|
box = outer_col.box()
|
||||||
|
|
||||||
|
row = box.row()
|
||||||
|
row.alignment = "CENTER"
|
||||||
|
row.label(text=relating_type["name"], icon="FILE_3D")
|
||||||
|
|
||||||
|
row = box.row()
|
||||||
|
row.alignment = "CENTER"
|
||||||
|
row.label(text=relating_type["description"])
|
||||||
|
|
||||||
|
row = box.row(align=True)
|
||||||
|
|
||||||
|
op = row.operator("bim.select_type", icon="OBJECT_DATA")
|
||||||
|
op.relating_type = relating_type["id"]
|
||||||
|
op = row.operator("bim.duplicate_type", icon="DUPLICATE", text="")
|
||||||
|
op.element = relating_type["id"]
|
||||||
|
op = row.operator("bim.remove_type", icon="X", text="")
|
||||||
|
op.element = relating_type["id"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class AnnotationTool(WorkSpaceTool):
|
class AnnotationTool(WorkSpaceTool):
|
||||||
bl_space_type = "VIEW_3D"
|
bl_space_type = "VIEW_3D"
|
||||||
bl_context_mode = "OBJECT"
|
bl_context_mode = "OBJECT"
|
||||||
@@ -89,42 +160,8 @@ def add_layout_hotkey_operator(layout, text, hotkey, description):
|
|||||||
return op, row
|
return op, row
|
||||||
|
|
||||||
|
|
||||||
# TODO: move to operator
|
|
||||||
def create_annotation_type(context):
|
|
||||||
# just empty to store parameters
|
|
||||||
props = context.scene.BIMAnnotationProperties
|
|
||||||
object_type = props.object_type
|
|
||||||
create_representation = props.create_representation_for_type
|
|
||||||
drawing = tool.Ifc.get_entity(bpy.context.scene.camera)
|
|
||||||
|
|
||||||
if props.create_representation_for_type:
|
|
||||||
obj = tool.Drawing.create_annotation_object(drawing, object_type)
|
|
||||||
else:
|
|
||||||
obj = bpy.data.objects.new(object_type, None)
|
|
||||||
|
|
||||||
obj.name = f"{object_type}_TYPE"
|
|
||||||
obj.location = context.scene.cursor.location
|
|
||||||
tool.Drawing.ensure_annotation_in_drawing_plane(obj)
|
|
||||||
|
|
||||||
drawing = tool.Ifc.get_entity(context.scene.camera)
|
|
||||||
ifc_context = tool.Drawing.get_annotation_context(tool.Drawing.get_drawing_target_view(drawing), object_type)
|
|
||||||
|
|
||||||
element = tool.Drawing.run_root_assign_class(
|
|
||||||
obj=obj,
|
|
||||||
ifc_class="IfcTypeProduct",
|
|
||||||
predefined_type=object_type,
|
|
||||||
should_add_representation=create_representation,
|
|
||||||
context=ifc_context,
|
|
||||||
ifc_representation_class=tool.Drawing.get_ifc_representation_class(object_type),
|
|
||||||
)
|
|
||||||
element.ApplicableOccurrence = f"IfcAnnotation/{object_type}"
|
|
||||||
|
|
||||||
tool.Blender.select_and_activate_single_object(context, obj)
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: move to operator
|
# TODO: move to operator
|
||||||
def create_annotation_occurence(context):
|
def create_annotation_occurence(context):
|
||||||
# object_type = context.scene.BIMAnnotationProperties.object_type
|
|
||||||
props = context.scene.BIMAnnotationProperties
|
props = context.scene.BIMAnnotationProperties
|
||||||
relating_type = tool.Ifc.get().by_id(int(props.relating_type_id))
|
relating_type = tool.Ifc.get().by_id(int(props.relating_type_id))
|
||||||
object_type = props.object_type
|
object_type = props.object_type
|
||||||
@@ -171,6 +208,11 @@ class AnnotationToolUI:
|
|||||||
row.label(text="No IFC Project", icon="ERROR")
|
row.label(text="No IFC Project", icon="ERROR")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
drawing = tool.Ifc.get_entity(context.scene.camera)
|
||||||
|
if not drawing:
|
||||||
|
row.label(text="No Active Drawing", icon="ERROR")
|
||||||
|
return
|
||||||
|
|
||||||
if not AnnotationData.is_loaded:
|
if not AnnotationData.is_loaded:
|
||||||
AnnotationData.load()
|
AnnotationData.load()
|
||||||
|
|
||||||
@@ -182,11 +224,6 @@ class AnnotationToolUI:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def draw_create_object_interface(cls):
|
def draw_create_object_interface(cls):
|
||||||
row = cls.layout.row(align=True)
|
|
||||||
op, row = add_layout_hotkey_operator(cls.layout, "Add Type", "S_C", "Create a new annotation type")
|
|
||||||
selected_icon = "CHECKBOX_HLT" if cls.props.create_representation_for_type else "CHECKBOX_DEHLT"
|
|
||||||
row.prop(cls.props, "create_representation_for_type", text="", icon=selected_icon)
|
|
||||||
|
|
||||||
row = cls.layout.row(align=True)
|
row = cls.layout.row(align=True)
|
||||||
row.prop(bpy.context.scene.DocProperties, "should_draw_decorations", text="Viewport Annotations")
|
row.prop(bpy.context.scene.DocProperties, "should_draw_decorations", text="Viewport Annotations")
|
||||||
|
|
||||||
@@ -207,10 +244,9 @@ class AnnotationToolUI:
|
|||||||
row = cls.layout.row(align=True)
|
row = cls.layout.row(align=True)
|
||||||
row.label(text="", icon="FILE_3D")
|
row.label(text="", icon="FILE_3D")
|
||||||
prop_with_search(row, cls.props, "relating_type_id", text="")
|
prop_with_search(row, cls.props, "relating_type_id", text="")
|
||||||
|
row.operator("bim.launch_annotation_type_manager", icon="LIGHTPROBE_GRID", text="")
|
||||||
|
|
||||||
create_type_occurence = cls.props.relating_type_id != "0"
|
add_layout_hotkey_operator(cls.layout, "Add", "S_A", "Create a new annotation")
|
||||||
label = "Add Type Occurence" if create_type_occurence else "Add Annotation"
|
|
||||||
add_layout_hotkey_operator(cls.layout, label, "S_A", "Create a new annotation")
|
|
||||||
|
|
||||||
if object_type in ("TEXT", "STAIR_ARROW"):
|
if object_type in ("TEXT", "STAIR_ARROW"):
|
||||||
add_layout_hotkey_operator(
|
add_layout_hotkey_operator(
|
||||||
@@ -284,6 +320,3 @@ class Hotkey(bpy.types.Operator, Operator):
|
|||||||
related_object = tool.Ifc.get_object(related_product)
|
related_object = tool.Ifc.get_object(related_product)
|
||||||
|
|
||||||
tool.Drawing.setup_annotation_object(obj, element.ObjectType, related_object)
|
tool.Drawing.setup_annotation_object(obj, element.ObjectType, related_object)
|
||||||
|
|
||||||
def hotkey_S_C(self):
|
|
||||||
create_annotation_type(bpy.context)
|
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ class SelectTypeObjects(bpy.types.Operator):
|
|||||||
class AddType(bpy.types.Operator, tool.Ifc.Operator):
|
class AddType(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.add_type"
|
bl_idname = "bim.add_type"
|
||||||
bl_label = "Add Type"
|
bl_label = "Add Type"
|
||||||
bl_options = {"REGISTER"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
props = context.scene.BIMModelProperties
|
props = context.scene.BIMModelProperties
|
||||||
|
|||||||
Reference in New Issue
Block a user