Adding drawings now creates groups and psets. Also very basic operator added to call IfcConvert from UI. See #1153.

This commit is contained in:
Dion Moult
2021-03-10 17:47:36 +11:00
parent 1a7ea1ea05
commit 4afcca8550
8 changed files with 253 additions and 158 deletions
@@ -138,7 +138,6 @@ if bpy is not None:
ui.BIM_PT_drawings,
ui.BIM_PT_schedules,
ui.BIM_PT_sheets,
ui.BIM_PT_camera,
ui.BIM_PT_text,
ui.BIM_PT_annotation_utilities,
ui.BIM_PT_misc_utilities,
@@ -1,8 +1,10 @@
import bpy
from . import operator
from . import ui, operator
classes = (
operator.AddDrawing,
operator.CreateDrawing,
ui.BIM_PT_camera,
)
@@ -1,6 +1,14 @@
import os
import bpy
import json
import subprocess
import webbrowser
from blenderbim.bim.operator import open_with_user_command
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.module.group.data import Data as GroupData
from blenderbim.bim.module.pset.data import Data as PsetData
cwd = os.path.dirname(os.path.realpath(__file__))
class AddDrawing(bpy.types.Operator):
bl_idname = "bim.add_drawing"
@@ -28,6 +36,54 @@ class AddDrawing(bpy.types.Operator):
area = next(area for area in context.screen.areas if area.type == "VIEW_3D")
area.spaces[0].region_3d.view_perspective = "CAMERA"
new.camera = camera
bpy.ops.bim.assign_class(obj=camera.name, ifc_class="IfcAnnotation")
bpy.ops.bim.assign_class(obj=camera.name, ifc_class="IfcAnnotation", predefined_type="DRAWING")
bpy.ops.bim.activate_drawing_style()
bpy.ops.bim.add_group()
bpy.ops.bim.assign_group(product=camera.name, group=sorted(GroupData.groups.keys())[-1])
bpy.ops.bim.add_pset(obj=camera.name, obj_type="Object", pset_name="EPset_Drawing")
pset_id = sorted(PsetData.products[camera.BIMObjectProperties.ifc_definition_id]["psets"])[-1]
bpy.ops.bim.edit_pset(
obj=camera.name,
obj_type="Object",
pset_id=pset_id,
properties=json.dumps({"TargetView": "PLAN_VIEW", "Scale": "1/100"}),
)
return {"FINISHED"}
class CreateDrawing(bpy.types.Operator):
bl_idname = "bim.create_drawing"
bl_label = "Create Drawing"
def execute(self, context):
ifcconvert_path = os.path.join(cwd, "..", "..", "..", "libs", "IfcConvert")
subprocess.run(
[
ifcconvert_path,
context.scene.BIMProperties.ifc_file,
"-yv",
context.scene.BIMProperties.ifc_file[0:-4] + ".svg",
"--plan",
"--model",
"--section-height-from-storeys",
"--section-height=1.2",
"--door-arcs",
"--print-space-names",
"--print-space-areas",
"--bounds=1024x1024",
"--elevation-ref=DRAWING",
"--svg-xmlns",
"--svg-project",
"--svg-poly",
"--exclude",
"entities",
"IfcSpace",
"IfcOpeningElement",
]
)
open_with_user_command(
bpy.context.preferences.addons["blenderbim"].preferences.svg_command,
context.scene.BIMProperties.ifc_file[0:-4] + ".svg",
)
return {"FINISHED"}
@@ -0,0 +1,108 @@
import os
import bpy
from bpy.types import Panel
from bpy.props import StringProperty, BoolProperty
class BIM_PT_camera(Panel):
bl_label = "Drawing Generation"
bl_idname = "BIM_PT_camera"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "data"
@classmethod
def poll(cls, context):
engine = context.engine
return context.camera and hasattr(context.active_object.data, "BIMCameraProperties")
def draw(self, context):
layout = self.layout
if "/" not in context.active_object.name:
layout.label(text="This is not a BIM camera.")
return
layout.use_property_split = True
dprops = bpy.context.scene.DocProperties
props = context.active_object.data.BIMCameraProperties
layout.label(text="Generation Options:")
row = layout.row()
row.prop(dprops, "should_recut")
row = layout.row()
row.prop(dprops, "should_recut_selected")
row = layout.row()
row.prop(dprops, "should_extract")
row = layout.row()
row.prop(props, "is_nts")
row = layout.row()
row.operator("bim.generate_references")
row = layout.row()
row.operator("bim.resize_text")
row = layout.row()
row.prop(props, "target_view")
row = layout.row()
row.prop(props, "cut_objects")
if props.cut_objects == "CUSTOM":
row = layout.row()
row.prop(props, "cut_objects_custom")
row = layout.row()
row.prop(props, "raster_x")
row = layout.row()
row.prop(props, "raster_y")
row = layout.row()
row.prop(props, "diagram_scale")
if props.diagram_scale == "CUSTOM":
row = layout.row()
row.prop(props, "custom_diagram_scale")
layout.label(text="Drawing Styles:")
row = layout.row(align=True)
row.operator("bim.add_drawing_style")
if dprops.drawing_styles:
layout.template_list("BIM_UL_generic", "", dprops, "drawing_styles", props, "active_drawing_style_index")
if props.active_drawing_style_index < len(dprops.drawing_styles):
drawing_style = dprops.drawing_styles[props.active_drawing_style_index]
row = layout.row(align=True)
row.prop(drawing_style, "name")
row.operator("bim.remove_drawing_style", icon="X", text="").index = props.active_drawing_style_index
row = layout.row()
row.prop(drawing_style, "render_type")
row = layout.row(align=True)
row.prop(drawing_style, "vector_style")
row.operator("bim.edit_vector_style", text="", icon="GREASEPENCIL")
row = layout.row(align=True)
row.prop(drawing_style, "include_query")
row = layout.row(align=True)
row.prop(drawing_style, "exclude_query")
row = layout.row()
row.operator("bim.add_drawing_style_attribute")
for index, attribute in enumerate(drawing_style.attributes):
row = layout.row(align=True)
row.prop(attribute, "name", text="")
row.operator("bim.remove_drawing_style_attribute", icon="X", text="").index = index
row = layout.row(align=True)
row.operator("bim.save_drawing_style")
row.operator("bim.activate_drawing_style")
row = layout.row(align=True)
row.operator("bim.cut_section", text="Create Drawing")
row.operator("bim.create_drawing", text="Create Drawing 2.0")
op = row.operator("bim.open_view", icon="URL", text="")
op.view = context.active_object.name.split("/")[1]
@@ -51,7 +51,7 @@ class EnablePsetEditing(bpy.types.Operator):
elif prop["type"] == "integer":
new.int_value = prop["value"] or 0
elif prop["type"] == "float":
new.float_value = prop["value"] or 0.
new.float_value = prop["value"] or 0.0
elif prop["type"] == "boolean":
new.bool_value = prop["value"] or False
elif prop["type"] == "enum":
@@ -84,6 +84,8 @@ class EditPset(bpy.types.Operator):
bl_label = "Edit Pset"
obj: bpy.props.StringProperty()
obj_type: bpy.props.StringProperty()
pset_id: bpy.props.IntProperty()
properties: bpy.props.StringProperty()
def execute(self, context):
self.file = IfcStore.get_file()
@@ -94,35 +96,47 @@ class EditPset(bpy.types.Operator):
oprops = obj.BIMObjectProperties
props = obj.PsetProperties
properties = {}
data = Data.psets if props.active_pset_id in Data.psets else Data.qtos
for prop in data[props.active_pset_id]["Properties"]:
blender_prop = props.properties.get(prop["Name"])
if not blender_prop:
continue
if blender_prop.is_null:
properties[prop["Name"]] = None
elif prop["type"] == "string":
properties[prop["Name"]] = blender_prop.string_value
elif prop["type"] == "boolean":
properties[prop["Name"]] = blender_prop.bool_value
elif prop["type"] == "integer":
properties[prop["Name"]] = blender_prop.int_value
elif prop["type"] == "float":
properties[prop["Name"]] = blender_prop.float_value
elif prop["type"] == "enum":
properties[prop["Name"]] = blender_prop.enum_value
if props.active_pset_id in Data.psets:
edit_pset.Usecase(self.file, {
"pset": self.file.by_id(props.active_pset_id),
"Name": props.active_pset_name,
"Properties": properties
}).execute()
pset_id = self.pset_id or props.active_pset_id
if self.properties:
properties = json.loads(self.properties)
else:
edit_qto.Usecase(self.file, {
"qto": self.file.by_id(props.active_pset_id),
"Name": props.active_pset_name,
"Properties": properties
}).execute()
data = Data.psets if pset_id in Data.psets else Data.qtos
for prop in data[pset_id]["Properties"]:
blender_prop = props.properties.get(prop["Name"])
if not blender_prop:
continue
if blender_prop.is_null:
properties[prop["Name"]] = None
elif prop["type"] == "string":
properties[prop["Name"]] = blender_prop.string_value
elif prop["type"] == "boolean":
properties[prop["Name"]] = blender_prop.bool_value
elif prop["type"] == "integer":
properties[prop["Name"]] = blender_prop.int_value
elif prop["type"] == "float":
properties[prop["Name"]] = blender_prop.float_value
elif prop["type"] == "enum":
properties[prop["Name"]] = blender_prop.enum_value
if pset_id in Data.psets:
edit_pset.Usecase(
self.file,
{
"pset": self.file.by_id(pset_id),
"Name": props.active_pset_name,
"Properties": properties,
},
).execute()
else:
edit_qto.Usecase(
self.file,
{
"qto": self.file.by_id(pset_id),
"Name": props.active_pset_name,
"Properties": properties,
},
).execute()
Data.load(oprops.ifc_definition_id)
bpy.ops.bim.disable_pset_editing(obj=self.obj, obj_type=self.obj_type)
return {"FINISHED"}
@@ -142,10 +156,13 @@ class RemovePset(bpy.types.Operator):
elif self.obj_type == "Material":
obj = bpy.data.materials.get(self.obj)
props = obj.BIMObjectProperties
remove_pset.Usecase(self.file, {
"product": self.file.by_id(props.ifc_definition_id),
"pset": self.file.by_id(self.pset_id),
}).execute()
remove_pset.Usecase(
self.file,
{
"product": self.file.by_id(props.ifc_definition_id),
"pset": self.file.by_id(self.pset_id),
},
).execute()
Data.load(props.ifc_definition_id)
return {"FINISHED"}
@@ -155,6 +172,7 @@ class AddPset(bpy.types.Operator):
bl_label = "Add Pset"
obj: bpy.props.StringProperty()
obj_type: bpy.props.StringProperty()
pset_name: bpy.props.StringProperty()
def execute(self, context):
self.file = IfcStore.get_file()
@@ -164,10 +182,21 @@ class AddPset(bpy.types.Operator):
obj = bpy.data.materials.get(self.obj)
oprops = obj.BIMObjectProperties
props = obj.PsetProperties
add_pset.Usecase(self.file, {
"product": self.file.by_id(oprops.ifc_definition_id),
"Name": props.pset_name if self.obj_type == "Object" else props.material_pset_name,
}).execute()
if self.pset_name:
pset_name = self.pset_name
elif self.obj_type == "Object":
pset_name = props.pset_name
elif self.obj_type == "Material":
pset_name = props.material_pset_name
add_pset.Usecase(
self.file,
{
"product": self.file.by_id(oprops.ifc_definition_id),
"Name": pset_name,
},
).execute()
Data.load(oprops.ifc_definition_id)
return {"FINISHED"}
@@ -181,10 +210,13 @@ class AddQto(bpy.types.Operator):
obj = bpy.context.active_object
oprops = obj.BIMObjectProperties
props = obj.PsetProperties
add_qto.Usecase(self.file, {
"product": self.file.by_id(oprops.ifc_definition_id),
"Name": props.qto_name,
}).execute()
add_qto.Usecase(
self.file,
{
"product": self.file.by_id(oprops.ifc_definition_id),
"Name": props.qto_name,
},
).execute()
Data.load(oprops.ifc_definition_id)
return {"FINISHED"}
@@ -19,10 +19,13 @@ class Usecase:
"OwnerHistory": create_owner_history()
})
element.Name = self.settings["name"] or None
if self.settings["predefined_type"] and hasattr(element, "PredefinedType"):
try:
element.PredefinedType = self.settings["predefined_type"]
except:
element.PredefinedType = "USERDEFINED"
if self.settings["predefined_type"]:
if hasattr(element, "PredefinedType"):
try:
element.PredefinedType = self.settings["predefined_type"]
except:
element.PredefinedType = "USERDEFINED"
element.ObjectType = self.settings["predefined_type"]
elif hasattr(element, "ObjectType"):
element.ObjectType = self.settings["predefined_type"]
return element
@@ -326,6 +326,8 @@ class SvgWriter:
# We have to decide whether this should come from Blender or from IFC.
# For the moment, for convenience of experimenting with ideas, it comes
# from Blender. In the future, it should probably come from IFC.
if not isinstance(obj.data, bpy.types.Mesh):
return
classes.extend(self.get_attribute_classes(obj))
if len(obj.data.polygons) == 0:
self.draw_edge_annotation(obj, classes)
@@ -350,12 +352,8 @@ class SvgWriter:
for slot in obj.material_slots:
if slot.material:
classes.append("material-{}".format(re.sub("[^0-9a-zA-Z]+", "", slot.material.name)))
result = obj.BIMObjectProperties.attributes.get("GlobalId")
if not result:
result = obj.BIMObjectProperties.attributes.add()
result.name = "GlobalId"
result.string_value = ifcopenshell.guid.new()
classes.append("globalid-{}".format(result.string_value))
global_id = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id).GlobalId
classes.append("globalid-{}".format(global_id))
for attribute in self.ifc_cutter.attributes:
result = self.get_obj_value(obj, attribute)
if result:
-103
View File
@@ -115,109 +115,6 @@ class BIM_PT_section_plane(Panel):
row.operator("bim.remove_section_plane")
class BIM_PT_camera(Panel):
bl_label = "Drawing Generation"
bl_idname = "BIM_PT_camera"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "data"
@classmethod
def poll(cls, context):
engine = context.engine
return context.camera and hasattr(context.active_object.data, "BIMCameraProperties")
def draw(self, context):
layout = self.layout
if "/" not in context.active_object.name:
layout.label(text="This is not a BIM camera.")
return
layout.use_property_split = True
dprops = bpy.context.scene.DocProperties
props = context.active_object.data.BIMCameraProperties
layout.label(text="Generation Options:")
row = layout.row()
row.prop(dprops, "should_recut")
row = layout.row()
row.prop(dprops, "should_recut_selected")
row = layout.row()
row.prop(dprops, "should_extract")
row = layout.row()
row.prop(props, "is_nts")
row = layout.row()
row.operator("bim.generate_references")
row = layout.row()
row.operator("bim.resize_text")
row = layout.row()
row.prop(props, "target_view")
row = layout.row()
row.prop(props, "cut_objects")
if props.cut_objects == "CUSTOM":
row = layout.row()
row.prop(props, "cut_objects_custom")
row = layout.row()
row.prop(props, "raster_x")
row = layout.row()
row.prop(props, "raster_y")
row = layout.row()
row.prop(props, "diagram_scale")
if props.diagram_scale == "CUSTOM":
row = layout.row()
row.prop(props, "custom_diagram_scale")
layout.label(text="Drawing Styles:")
row = layout.row(align=True)
row.operator("bim.add_drawing_style")
if dprops.drawing_styles:
layout.template_list("BIM_UL_generic", "", dprops, "drawing_styles", props, "active_drawing_style_index")
if props.active_drawing_style_index < len(dprops.drawing_styles):
drawing_style = dprops.drawing_styles[props.active_drawing_style_index]
row = layout.row(align=True)
row.prop(drawing_style, "name")
row.operator("bim.remove_drawing_style", icon="X", text="").index = props.active_drawing_style_index
row = layout.row()
row.prop(drawing_style, "render_type")
row = layout.row(align=True)
row.prop(drawing_style, "vector_style")
row.operator("bim.edit_vector_style", text="", icon="GREASEPENCIL")
row = layout.row(align=True)
row.prop(drawing_style, "include_query")
row = layout.row(align=True)
row.prop(drawing_style, "exclude_query")
row = layout.row()
row.operator("bim.add_drawing_style_attribute")
for index, attribute in enumerate(drawing_style.attributes):
row = layout.row(align=True)
row.prop(attribute, "name", text="")
row.operator("bim.remove_drawing_style_attribute", icon="X", text="").index = index
row = layout.row(align=True)
row.operator("bim.save_drawing_style")
row.operator("bim.activate_drawing_style")
row = layout.row(align=True)
row.operator("bim.cut_section", text="Create Drawing")
op = row.operator("bim.open_view", icon="URL", text="")
op.view = context.active_object.name.split("/")[1]
class BIM_PT_text(Panel):
bl_label = "Text Paper Space"
bl_idname = "BIM_PT_text"