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:
Dion Moult
2023-07-09 16:01:16 +10:00
parent 43fd012a4c
commit cc59929cfd
6 changed files with 158 additions and 65 deletions
@@ -24,13 +24,14 @@ classes = (
operator.ActivateDrawingStyle,
operator.ActivateModel,
operator.AddAnnotation,
operator.AddAnnotationType,
operator.AddDrawing,
operator.AddDrawingStyle,
operator.AddDrawingStyleAttribute,
operator.AddDrawingToSheet,
operator.AddReferenceToSheet,
operator.AddSchedule,
operator.AddScheduleToSheet,
operator.AddReferenceToSheet,
operator.AddSheet,
operator.AddTextLiteral,
operator.BuildSchedule,
@@ -38,6 +39,7 @@ classes = (
operator.ContractSheet,
operator.CreateDrawing,
operator.CreateSheets,
operator.DisableAddAnnotationType,
operator.DisableEditingAssignedProduct,
operator.DisableEditingDrawings,
operator.DisableEditingSchedules,
@@ -47,6 +49,7 @@ classes = (
operator.EditAssignedProduct,
operator.EditSheet,
operator.EditText,
operator.EnableAddAnnotationType,
operator.EditTextPopup,
operator.EnableEditingAssignedProduct,
operator.EnableEditingText,
@@ -102,6 +105,7 @@ classes = (
gizmos.DimensionLabelGizmo,
gizmos.ExtrusionGuidesGizmo,
gizmos.ExtrusionWidget,
workspace.LaunchAnnotationTypeManager,
workspace.Hotkey,
)
@@ -335,18 +335,31 @@ class AnnotationData:
def load(cls):
cls.is_loaded = True
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
def get_relating_types(cls):
def relating_type_id(cls):
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(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
enum_items.insert(0, ("0", "-", ""))
return enum_items
@classmethod
def relating_types(cls):
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"}
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):
bl_idname = "bim.add_drawing"
bl_label = "Add Drawing"
@@ -499,7 +499,7 @@ ANNOTATION_TYPES_DATA = {
"PLAN_LEVEL": ("Level (Plan)", "", "SORTBYEXT", "curve"),
"SECTION_LEVEL": ("Level (Section)", "", "TRIA_DOWN", "curve"),
"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"),
"REVISION_CLOUD":("Revision Cloud", "Add revision cloud", "VOLUME_DATA", "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)]
def get_annotation_data_prop(prop_name):
def function(self, context):
if not AnnotationData.is_loaded:
AnnotationData.load()
return AnnotationData.data[prop_name]
return function
def get_relating_type_id(self, context):
if not AnnotationData.is_loaded:
AnnotationData.load()
return AnnotationData.data["relating_type_id"]
def update_annotation_object_type(self, context):
@@ -533,12 +530,12 @@ class BIMAnnotationProperties(PropertyGroup):
object_type: bpy.props.EnumProperty(
name="Annotation Object Type", items=annotation_classes, default="TEXT", update=update_annotation_object_type
)
relating_type_id: bpy.props.EnumProperty(
name="Relating Annotation Type", items=get_annotation_data_prop("relating_types")
)
relating_type_id: bpy.props.EnumProperty(name="Relating Annotation Type", items=get_relating_type_id)
create_representation_for_type: bpy.props.BoolProperty(
name="Create Representation For Type",
default=False,
description='Whether "Add type" should define a representation for the type \n'
"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
# declaring it here to avoid circular import problems
# TODO: Fix circular import.
# Declaring it here to avoid circular import problems
class Operator:
def execute(self, context):
IfcStore.execute_ifc_operator(self, context)
@@ -38,6 +39,76 @@ class Operator:
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):
bl_space_type = "VIEW_3D"
bl_context_mode = "OBJECT"
@@ -89,42 +160,8 @@ def add_layout_hotkey_operator(layout, text, hotkey, description):
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
def create_annotation_occurence(context):
# object_type = context.scene.BIMAnnotationProperties.object_type
props = context.scene.BIMAnnotationProperties
relating_type = tool.Ifc.get().by_id(int(props.relating_type_id))
object_type = props.object_type
@@ -171,6 +208,11 @@ class AnnotationToolUI:
row.label(text="No IFC Project", icon="ERROR")
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:
AnnotationData.load()
@@ -182,11 +224,6 @@ class AnnotationToolUI:
@classmethod
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.prop(bpy.context.scene.DocProperties, "should_draw_decorations", text="Viewport Annotations")
@@ -207,10 +244,9 @@ class AnnotationToolUI:
row = cls.layout.row(align=True)
row.label(text="", icon="FILE_3D")
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"
label = "Add Type Occurence" if create_type_occurence else "Add Annotation"
add_layout_hotkey_operator(cls.layout, label, "S_A", "Create a new annotation")
add_layout_hotkey_operator(cls.layout, "Add", "S_A", "Create a new annotation")
if object_type in ("TEXT", "STAIR_ARROW"):
add_layout_hotkey_operator(
@@ -284,6 +320,3 @@ class Hotkey(bpy.types.Operator, Operator):
related_object = tool.Ifc.get_object(related_product)
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):
bl_idname = "bim.add_type"
bl_label = "Add Type"
bl_options = {"REGISTER"}
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
props = context.scene.BIMModelProperties