mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
Adding drawings now creates groups and psets. Also very basic operator added to call IfcConvert from UI. See #1153.
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user