You can now specify a target view when creating a new drawing. See #1153.

This commit is contained in:
Dion Moult
2022-01-29 21:11:23 +11:00
parent 46e1a46dd2
commit 074fe0d3a6
7 changed files with 95 additions and 57 deletions
@@ -65,66 +65,14 @@ class Operator:
return {"FINISHED"}
class AddDrawing(bpy.types.Operator):
class AddDrawing(bpy.types.Operator, Operator):
bl_idname = "bim.add_drawing"
bl_label = "Add Drawing"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return IfcStore.get_file()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
self.file = IfcStore.get_file()
drawing_name = tool.Drawing.ensure_unique_drawing_name("UNTITLED")
if not bpy.data.collections.get("Views"):
context.scene.collection.children.link(bpy.data.collections.new("Views"))
views_collection = bpy.data.collections.get("Views")
view_collection = bpy.data.collections.new("IfcGroup/" + drawing_name)
views_collection.children.link(view_collection)
camera = bpy.data.objects.new(drawing_name, bpy.data.cameras.new(drawing_name))
camera.location = (0, 0, 1.5) # The view shall be 1.5m above the origin
camera.data.type = "ORTHO"
camera.data.ortho_scale = 50 # The default of 6m is too small
camera.data.clip_end = 10 # A slightly more reasonable default
if context.scene.unit_settings.system == "IMPERIAL":
camera.data.BIMCameraProperties.diagram_scale = '1/8"=1\'-0"|1/96'
else:
camera.data.BIMCameraProperties.diagram_scale = "1:100|1/100"
context.scene.camera = camera
view_collection.objects.link(camera)
area = next(area for area in context.screen.areas if area.type == "VIEW_3D")
area.spaces[0].region_3d.view_perspective = "CAMERA"
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()
group = self.file.by_id(sorted(GroupData.groups.keys())[-1])
ifcopenshell.api.run("group.edit_group", self.file, **{"group": group, "attributes": {"Name": drawing_name}})
bpy.ops.bim.assign_group(product=camera.name, group=group.id())
pset = ifcopenshell.api.run(
"pset.add_pset",
self.file,
**{
"product": self.file.by_id(camera.BIMObjectProperties.ifc_definition_id),
"name": "EPset_Drawing",
},
)
ifcopenshell.api.run(
"pset.edit_pset",
self.file,
**{
"pset": pset,
"properties": {"TargetView": "PLAN_VIEW", "Scale": "1/100"},
"pset_template": blenderbim.bim.schema.ifc.psetqto.get_by_name("EPset_Drawing"),
},
)
PsetData.load(IfcStore.get_file(), camera.BIMObjectProperties.ifc_definition_id)
tool.Drawing.import_drawings()
return {"FINISHED"}
self.props = context.scene.DocProperties
core.add_drawing(tool.Ifc, tool.Collector, tool.Drawing, target_view=self.props.target_view, location_hint=None)
class CreateDrawing(bpy.types.Operator):
@@ -143,6 +91,7 @@ class CreateDrawing(bpy.types.Operator):
camera = context.scene.camera
return (
IfcStore.get_file()
and camera
and camera.type == "CAMERA"
and camera.data.type == "ORTHO"
and camera.BIMObjectProperties.ifc_definition_id
@@ -180,8 +180,11 @@ class BIM_PT_drawings(Panel):
op.view = self.props.active_drawing.name
op = row.operator("bim.activate_view", icon="OUTLINER_OB_CAMERA", text="")
op.drawing = self.props.active_drawing.ifc_definition_id
row.operator("bim.create_drawing", text="", icon="OUTPUT")
row.operator("bim.remove_drawing", icon="X", text="").index = self.props.active_drawing_index
self.layout.template_list("BIM_UL_drawinglist", "", self.props, "drawings", self.props, "active_drawing_index")
self.layout.template_list(
"BIM_UL_drawinglist", "", self.props, "drawings", self.props, "active_drawing_index"
)
# Commented out until federated drawing generation is rebuilt
# row = self.layout.row()
+15
View File
@@ -96,3 +96,18 @@ def load_drawings(drawing):
def disable_editing_drawings(drawing):
drawing.disable_editing_drawings()
def add_drawing(ifc, collector, drawing, target_view=None, location_hint=None):
drawing_name = drawing.ensure_unique_drawing_name("UNTITLED")
drawing_matrix = drawing.generate_drawing_matrix(target_view, location_hint)
camera = drawing.create_camera(drawing_name, drawing_matrix)
# Not yet refactored
element = drawing.run_assign_class_operator(obj=camera, ifc_class="IfcAnnotation", predefined_type="DRAWING")
group = ifc.run("group.add_group")
ifc.run("group.edit_group", group=group, attributes={"Name": drawing_name})
ifc.run("group.assign_group", group=group, product=element)
collector.assign(camera)
pset = ifc.run("pset.add_pset", product=element, name="EPset_Drawing")
ifc.run("pset.edit_pset", pset=pset, properties={"TargetView": target_view, "Scale": "1/100"})
drawing.import_drawings()
+4
View File
@@ -135,6 +135,7 @@ class Debug:
@interface
class Drawing:
def create_camera(cls, name, matrix): pass
def create_svg_sheet(cls, document, titleblock): pass
def disable_editing_drawings(cls): pass
def disable_editing_sheets(cls): pass
@@ -144,8 +145,10 @@ class Drawing:
def enable_editing_sheets(cls): pass
def enable_editing_text(cls, obj): pass
def enable_editing_text_product(cls, obj): pass
def ensure_unique_drawing_name(cls, name): pass
def ensure_unique_identification(cls, identification): pass
def export_text_literal_attributes(cls, obj): pass
def generate_drawing_matrix(cls, target_view, location_hint): pass
def generate_sheet_identification(cls): pass
def get_sheet_filename(cls, document): pass
def get_text_literal(cls, obj): pass
@@ -155,6 +158,7 @@ class Drawing:
def import_text_attributes(cls, obj): pass
def import_text_product(cls, obj): pass
def open_svg(cls, filepath): pass
def run_assign_class_operator(cls, obj=None, ifc_class=None, predefined_type=None): pass
def update_text_value(cls, obj): pass
+25
View File
@@ -19,6 +19,7 @@
import os
import re
import bpy
import mathutils
import webbrowser
import blenderbim.core.tool
import blenderbim.tool as tool
@@ -27,6 +28,21 @@ import blenderbim.bim.module.drawing.sheeter as sheeter
class Drawing(blenderbim.core.tool.Drawing):
@classmethod
def create_camera(cls, name, matrix):
camera = bpy.data.objects.new(name, bpy.data.cameras.new(name))
camera.location = (0, 0, 1.5) # The view shall be 1.5m above the origin
camera.data.type = "ORTHO"
camera.data.ortho_scale = 50 # The default of 6m is too small
camera.data.clip_end = 10 # A slightly more reasonable default
if bpy.context.scene.unit_settings.system == "IMPERIAL":
camera.data.BIMCameraProperties.diagram_scale = '1/8"=1\'-0"|1/96'
else:
camera.data.BIMCameraProperties.diagram_scale = "1:100|1/100"
camera.matrix_world = matrix
bpy.context.scene.collection.objects.link(camera)
return camera
@classmethod
def create_svg_sheet(cls, document, titleblock):
sheet_builder = sheeter.SheetBuilder()
@@ -97,6 +113,10 @@ class Drawing(blenderbim.core.tool.Drawing):
name += " - " + document.Name or "Unnamed"
return name
@classmethod
def generate_drawing_matrix(cls, target_view, location_hint):
return mathutils.Matrix()
@classmethod
def generate_sheet_identification(cls):
number = len([d for d in tool.Ifc.get().by_type("IfcDocumentInformation") if d.Scope == "DOCUMENTATION"])
@@ -174,6 +194,11 @@ class Drawing(blenderbim.core.tool.Drawing):
os.path.join(bpy.context.scene.BIMProperties.data_dir, "sheets", filename + ".svg"),
)
@classmethod
def run_assign_class_operator(cls, obj=None, ifc_class=None, predefined_type=None):
bpy.ops.bim.assign_class(obj=obj.name, ifc_class=ifc_class, predefined_type=predefined_type)
return tool.Ifc.get_entity(obj)
@classmethod
def update_text_value(cls, obj):
element = cls.get_text_literal(obj)
+21 -1
View File
@@ -17,7 +17,7 @@
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import blenderbim.core.drawing as subject
from test.core.bootstrap import ifc, drawing
from test.core.bootstrap import ifc, drawing, collector
class TestEnableEditingText:
@@ -137,3 +137,23 @@ class TestDisableEditingDrawings:
def test_run(self, drawing):
drawing.disable_editing_drawings().should_be_called()
subject.disable_editing_drawings(drawing)
class TestAddDrawing:
def test_run(self, ifc, collector, drawing):
drawing.ensure_unique_drawing_name("UNTITLED").should_be_called().will_return("name")
drawing.generate_drawing_matrix("target_view", "location_hint").should_be_called().will_return("matrix")
drawing.create_camera("name", "matrix").should_be_called().will_return("obj")
drawing.run_assign_class_operator(
obj="obj", ifc_class="IfcAnnotation", predefined_type="DRAWING"
).should_be_called().will_return("element")
ifc.run("group.add_group").should_be_called().will_return("group")
ifc.run("group.edit_group", group="group", attributes={"Name": "name"}).should_be_called()
ifc.run("group.assign_group", group="group", product="element").should_be_called()
collector.assign("obj").should_be_called()
ifc.run("pset.add_pset", product="element", name="EPset_Drawing").should_be_called().will_return("pset")
ifc.run(
"pset.edit_pset", pset="pset", properties={"TargetView": "target_view", "Scale": "1/100"}
).should_be_called()
drawing.import_drawings().should_be_called()
subject.add_drawing(ifc, collector, drawing, target_view="target_view", location_hint="location_hint")
+22
View File
@@ -18,6 +18,7 @@
import os
import bpy
import mathutils
import ifcopenshell
import blenderbim.core.tool
import blenderbim.tool as tool
@@ -30,6 +31,17 @@ class TestImplementsTool(NewFile):
assert isinstance(subject(), blenderbim.core.tool.Drawing)
class TestCreateCamera(NewFile):
def test_run(self):
obj = subject.create_camera("Name", mathutils.Matrix())
assert obj.name == "Name"
assert obj.matrix_world == mathutils.Matrix()
assert obj.data.type == "ORTHO"
assert obj.data.ortho_scale == 50
assert obj.data.clip_end == 10
assert obj.users_collection[0] == bpy.context.scene.collection
class TestCreateSvgSheet(NewFile):
def test_run(self):
ifc = ifcopenshell.file()
@@ -149,6 +161,11 @@ class TestGetSheetFilename(NewFile):
subject.get_sheet_filename(document) == "X - FOOBAR"
class TestGenerateDrawingMatrix(NewFile):
def test_returning_the_origin_as_a_fallback(self):
assert subject.generate_drawing_matrix("PLAN_VIEW", None) == mathutils.Matrix()
class TestGenerateSheetIdentification(NewFile):
def test_run(self):
ifc = ifcopenshell.file()
@@ -266,6 +283,11 @@ class TestOpenSvg(NewFile):
pass
class TestRunAssignClassOperator(NewFile):
def test_nothing(self):
pass
class TestUpdateTextValue(NewFile):
def test_updating_arbitrary_strings(self):
TestGetTextLiteral().test_run()