Migrate from bcfplugin to new bcf library in the BlenderBIM Add-on

This commit is contained in:
Dion Moult
2020-12-18 16:28:17 +11:00
parent d08da0a61d
commit 7dd40149aa
8 changed files with 292 additions and 506 deletions
+115 -131
View File
@@ -20,7 +20,7 @@ from . import svgwriter
from . import sheeter
from . import scheduler
from . import schema
from . import bcf
from . import bcfstore
from . import ifc
from . import annotation
from . import helper
@@ -512,16 +512,9 @@ class NewBcfProject(bpy.types.Operator):
bl_label = "New BCF Project"
def execute(self, context):
import bcfplugin
bcfplugin.newProject("New BCF Project")
bcf.BcfStore.topics = bcfplugin.getTopics()
bpy.context.scene.BCFProperties.is_editable = False
bpy.context.scene.BCFProperties.name = bcfplugin.getProjectName()
while len(bpy.context.scene.BCFProperties.topics) > 0:
bpy.context.scene.BCFProperties.topics.remove(0)
bpy.context.scene.BCFProperties.is_editable = True
bpy.context.scene.BCFProperties.directory = bcfplugin.util.getBcfDir()
bpy.context.scene.BCFProperties.is_loaded = True
bcfxml = bcfstore.BcfStore.get_bcfxml()
bcfxml.new_project()
bpy.ops.bim.load_bcf_project()
return {"FINISHED"}
@@ -531,18 +524,12 @@ class LoadBcfProject(bpy.types.Operator):
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
def execute(self, context):
import bcfplugin
bcfplugin.openProject(self.filepath)
bcf.BcfStore.topics = bcfplugin.getTopics()
bcfxml = bcfstore.BcfStore.get_bcfxml()
if self.filepath:
bcfxml.get_project(self.filepath)
bpy.context.scene.BCFProperties.is_editable = False
bpy.context.scene.BCFProperties.name = bcfplugin.getProjectName()
while len(bpy.context.scene.BCFProperties.topics) > 0:
bpy.context.scene.BCFProperties.topics.remove(0)
for topic in bcf.BcfStore.topics:
new = bpy.context.scene.BCFProperties.topics.add()
new.name = topic[0]
bpy.context.scene.BCFProperties.is_editable = True
bpy.context.scene.BCFProperties.name = bcfxml.project.name
bpy.ops.bim.load_bcf_topics()
bpy.context.scene.BCFProperties.is_loaded = True
return {"FINISHED"}
@@ -551,14 +538,76 @@ class LoadBcfProject(bpy.types.Operator):
return {"RUNNING_MODAL"}
class LoadBcfTopics(bpy.types.Operator):
bl_idname = "bim.load_bcf_topics"
bl_label = "Load BCF Topics"
def execute(self, context):
bcfxml = bcfstore.BcfStore.get_bcfxml()
bcfxml.get_topics()
while len(bpy.context.scene.BCFProperties.topics) > 0:
bpy.context.scene.BCFProperties.topics.remove(0)
for topic in bcfxml.topics.values():
new = bpy.context.scene.BCFProperties.topics.add()
data_map = {
"name": topic.title,
"guid": topic.guid,
"type": topic.topic_type,
"status": topic.topic_status,
"priority": topic.priority,
"stage": topic.stage,
"creation_date": topic.creation_date,
"creation_author": topic.creation_author,
"modified_date": topic.modified_date,
"modified_author": topic.modified_author,
"assigned_to": topic.assigned_to,
"due_date": topic.due_date,
"description": topic.description
}
for key, value in data_map.items():
if value is not None:
setattr(new, key, str(value))
for reference_link in topic.reference_links:
new2 = new.reference_links.add()
new2.name = reference_link
for label in topic.labels:
new2 = new.labels.add()
new2.name = label
if topic.bim_snippet:
data_map = {
"type": topic.bim_snippet.snippet_type,
"is_external": topic.bim_snippet.is_external,
"reference": topic.bim_snippet.reference,
"schema": topic.bim_snippet.reference_schema
}
for key, value in data_map.items():
if value is not None:
setattr(new.bim_snippet, key, value)
for doc in topic.document_references:
new2 = new.document_references.add()
data_map = {
"reference": doc.referenced_document,
"description": doc.description,
"guid": doc.guid,
"is_external": doc.is_external
}
for key, value in data_map.items():
if value is not None:
setattr(new2, key, value)
for related_topic in topic.related_topics:
new2 = new.related_topics.add()
new2.name = related_topic.guid
return {"FINISHED"}
class SaveBcfProject(bpy.types.Operator):
bl_idname = "bim.save_bcf_project"
bl_label = "Save BCF Project"
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
def execute(self, context):
import bcfplugin
bcfplugin.saveProject(self.filepath)
bcfxml = bcfstore.BcfStore.get_bcfxml()
bcfxml.save_project(self.filepath)
return {"FINISHED"}
def invoke(self, context, event):
@@ -571,13 +620,11 @@ class AddBcfTopic(bpy.types.Operator):
bl_label = "Add BCF Topic"
def execute(self, context):
import bcfplugin
bcfplugin.addTopic("New Topic", bpy.context.scene.BCFProperties.author)
bpy.context.scene.BCFProperties.is_editable = False
bcfxml = bcfstore.BcfStore.get_bcfxml()
bcfxml.add_topic()
new = bpy.context.scene.BCFProperties.topics.add()
new.name = "New Topic"
bcf.BcfStore.topics = bcfplugin.getTopics()
bpy.context.scene.BCFProperties.is_editable = True
bpy.ops.bim.load_bcf_topics()
return {"FINISHED"}
@@ -587,8 +634,8 @@ class ViewBcfTopic(bpy.types.Operator):
topic_guid: bpy.props.StringProperty()
def execute(self, context):
for index, topic in enumerate(bcf.BcfStore.topics):
if str(topic[1].xmlId) == self.topic_guid:
for index, topic in enumerate(bpy.context.scene.BCFProperties.topics):
if topic.guid.lower() == self.topic_guid.lower():
bpy.context.scene.BCFProperties.active_topic_index = index
return {"FINISHED"}
@@ -598,18 +645,15 @@ class ActivateBcfViewpoint(bpy.types.Operator):
bl_label = "Activate BCF Viewpoint"
def execute(self, context):
import bcfplugin
topics = bcf.BcfStore.topics
if not topics:
bcfxml = bcfstore.BcfStore.get_bcfxml()
props = bpy.context.scene.BCFProperties
blender_topic = props.topics[props.active_topic_index]
topic = bcfxml.topics[blender_topic.guid]
if not topic.viewpoints:
return {"FINISHED"}
topic = topics[bpy.context.scene.BCFProperties.active_topic_index][1]
viewpoints = bcf.BcfStore.viewpoints
if not viewpoints:
return {"FINISHED"}
viewpoint_reference = viewpoints[int(bpy.context.scene.BCFProperties.viewpoints)][1]
viewpoint = viewpoint_reference.viewpoint
viewpoint_guid = blender_topic.viewpoints
viewpoint = topic.viewpoints[viewpoint_guid]
obj = bpy.data.objects.get("Viewpoint")
if not obj:
obj = bpy.data.objects.new("Viewpoint", bpy.data.cameras.new("Viewpoint"))
@@ -620,13 +664,13 @@ class ActivateBcfViewpoint(bpy.types.Operator):
cam_height = bpy.context.scene.render.resolution_y
cam_aspect = cam_width / cam_height
if viewpoint_reference.snapshot:
if viewpoint.snapshot:
obj.data.show_background_images = True
while len(obj.data.background_images) > 0:
obj.data.background_images.remove(obj.data.background_images[0])
background = obj.data.background_images.new()
background.image = bpy.data.images.load(
os.path.join(bcfplugin.util.getBcfDir(), str(topic.xmlId), viewpoint_reference.snapshot.uri)
os.path.join(bcfxml.filepath, topic.guid, viewpoint.snapshot)
)
src_width = background.image.size[0]
src_height = background.image.size[1]
@@ -640,18 +684,18 @@ class ActivateBcfViewpoint(bpy.types.Operator):
area = next(area for area in bpy.context.screen.areas if area.type == "VIEW_3D")
area.spaces[0].region_3d.view_perspective = "CAMERA"
if viewpoint.oCamera:
camera = viewpoint.oCamera
if viewpoint.orthogonal_camera:
camera = viewpoint.orthogonal_camera
obj.data.type = "ORTHO"
obj.data.ortho_scale = viewpoint.oCamera.viewWorldScale
elif viewpoint.pCamera:
camera = viewpoint.pCamera
obj.data.ortho_scale = viewpoint.orthogonal_camera.view_to_world_scale
elif viewpoint.perspective_camera:
camera = viewpoint.perspective_camera
obj.data.type = "PERSP"
if cam_aspect >= 1:
obj.data.angle = radians(camera.fieldOfView)
obj.data.angle = radians(camera.field_of_view)
else:
# https://blender.stackexchange.com/questions/23431/how-to-set-camera-horizontal-and-vertical-fov
obj.data.angle = 2 * atan((0.5 * cam_height) / (0.5 * cam_width / tan(radians(camera.fieldOfView) / 2)))
obj.data.angle = 2 * atan((0.5 * cam_height) / (0.5 * cam_width / tan(radians(camera.field_of_view) / 2)))
self.set_viewpoint_components(viewpoint)
@@ -662,37 +706,37 @@ class ActivateBcfViewpoint(bpy.types.Operator):
self.draw_lines(viewpoint)
self.delete_clipping_planes()
if viewpoint.clippingPlanes:
if viewpoint.clipping_planes:
self.create_clipping_planes(viewpoint)
self.delete_bitmaps()
if viewpoint.bitmaps:
self.create_bitmaps(viewpoint)
self.create_bitmaps(bcfxml, viewpoint, topic)
z_axis = Vector((-camera.direction.x, -camera.direction.y, -camera.direction.z)).normalized()
y_axis = Vector((camera.upVector.x, camera.upVector.y, camera.upVector.z)).normalized()
z_axis = Vector((-camera.camera_direction.x, -camera.camera_direction.y, -camera.camera_direction.z)).normalized()
y_axis = Vector((camera.camera_up_vector.x, camera.camera_up_vector.y, camera.camera_up_vector.z)).normalized()
x_axis = y_axis.cross(z_axis).normalized()
rotation = Matrix((x_axis, y_axis, z_axis))
rotation.invert()
location = Vector((camera.viewPoint.x, camera.viewPoint.y, camera.viewPoint.z))
location = Vector((camera.camera_view_point.x, camera.camera_view_point.y, camera.camera_view_point.z))
obj.matrix_world = rotation.to_4x4()
obj.location = location
return {"FINISHED"}
def set_viewpoint_components(self, viewpoint):
selected_global_ids = [s.ifcId for s in viewpoint.components.selection]
exception_global_ids = [v.ifcId for v in viewpoint.components.visibilityExceptions]
selected_global_ids = [s.ifc_guid for s in viewpoint.components.selection]
exception_global_ids = [v.ifc_guid for v in viewpoint.components.visibility.exceptions]
global_id_colours = {}
for colouring in viewpoint.components.colouring:
for component in colouring.components:
global_id_colours.setdefault(component.ifcId, colouring.colour)
for coloring in viewpoint.components.coloring:
for component in coloring.components:
global_id_colours.setdefault(component.ifc_guid, coloring.color)
for obj in bpy.data.objects:
global_id = obj.BIMObjectProperties.attributes.get("GlobalId")
if not global_id:
continue
global_id = global_id.string_value
is_visible = viewpoint.components.visibilityDefault
is_visible = viewpoint.components.visibility.default_visibility
if global_id in exception_global_ids:
is_visible = not is_visible
if not is_visible:
@@ -723,12 +767,12 @@ class ActivateBcfViewpoint(bpy.types.Operator):
stroke.points.add(len(viewpoint.lines) * 2)
coords = []
for l in viewpoint.lines:
coords.extend([l.start.x, l.start.y, l.start.z, l.end.x, l.end.y, l.end.z])
coords.extend([l.start_point.x, l.start_point.y, l.start_point.z, l.end_point.x, l.end_point.y, l.end_point.z])
stroke.points.foreach_set("co", coords)
def create_clipping_planes(self, viewpoint):
n = 0
for plane in viewpoint.clippingPlanes:
for plane in viewpoint.clipping_planes:
bpy.ops.bim.add_section_plane()
if n == 0:
obj = bpy.data.objects["Section"]
@@ -757,18 +801,14 @@ class ActivateBcfViewpoint(bpy.types.Operator):
for bitmap in collection.objects:
bpy.data.objects.remove(bitmap)
def create_bitmaps(self, viewpoint):
import bcfplugin
topics = bcf.BcfStore.topics
topic = topics[bpy.context.scene.BCFProperties.active_topic_index][1]
def create_bitmaps(self, bcfxml, viewpoint, topic):
collection = bpy.data.collections.get("Bitmaps")
if not collection:
collection = bpy.data.collections.new("Bitmaps")
for bitmap in viewpoint.bitmaps:
obj = bpy.data.objects.new("Bitmap", None)
obj.empty_display_type = "IMAGE"
image = bpy.data.images.load(os.path.join(bcfplugin.util.getBcfDir(), str(topic.xmlId), bitmap.reference))
image = bpy.data.images.load(os.path.join(bcfxml.filepath, topic.guid, bitmap.reference))
src_width = image.size[0]
src_height = image.size[1]
if src_height > src_width:
@@ -776,7 +816,7 @@ class ActivateBcfViewpoint(bpy.types.Operator):
else:
obj.empty_display_size = bitmap.height * (src_width / src_height)
obj.data = image
y = Vector((bitmap.upVector.x, bitmap.upVector.y, bitmap.upVector.z))
y = Vector((bitmap.up.x, bitmap.up.y, bitmap.up.z))
z = Vector((bitmap.normal.x, bitmap.normal.y, bitmap.normal.z))
x = y.cross(z)
obj.matrix_world = Matrix(
@@ -792,22 +832,13 @@ class ActivateBcfViewpoint(bpy.types.Operator):
return [t[0] / 255.0, t[1] / 255.0, t[2] / 255.0, 1]
class OpenBcfFileReference(bpy.types.Operator):
bl_idname = "bim.open_bcf_file_reference"
bl_label = "Open BCF File Reference"
data: bpy.props.StringProperty()
class OpenUri(bpy.types.Operator):
bl_idname = "bim.open_uri"
bl_label = "Open URI"
uri: bpy.props.StringProperty()
def execute(self, context):
if "/" not in self.data:
webbrowser.open(bpy.context.scene.BCFProperties.topic_files[int(self.data)].reference)
return {"FINISHED"}
import bcfplugin
topic_guid, index = self.data.split("/")
path = os.path.join(bcfplugin.util.getBcfDir(), topic_guid)
# bpy.context.scene.BCFProperties.topic_files[int(index)].reference)
# TODO - maybe allow immediate importing?
webbrowser.open(path)
webbrowser.open(self.uri)
return {"FINISHED"}
@@ -821,53 +852,6 @@ class OpenBcfReferenceLink(bpy.types.Operator):
return {"FINISHED"}
class OpenBcfBimSnippetSchema(bpy.types.Operator):
bl_idname = "bim.open_bcf_bim_snippet_schema"
bl_label = "Open BCF BIM Snippet Schema"
def execute(self, context):
webbrowser.open(bpy.context.scene.BCFProperties.topic_snippet_schema)
return {"FINISHED"}
class OpenBcfBimSnippetReference(bpy.types.Operator):
bl_idname = "bim.open_bcf_bim_snippet_reference"
bl_label = "Open BCF BIM Snippet Reference"
topic_guid: bpy.props.StringProperty()
def execute(self, context):
import bcfplugin
if bpy.context.scene.BCFProperties.topic_snippet_is_external:
webbrowser.open(bpy.context.scene.BCFProperties.topic_snippet_reference)
return {"FINISHED"}
webbrowser.open(
"file://"
+ os.path.join(
bcfplugin.util.getBcfDir(), self.topic_guid, bpy.context.scene.BCFProperties.topic_snippet_reference
)
)
return {"FINISHED"}
class OpenBcfDocumentReference(bpy.types.Operator):
bl_idname = "bim.open_bcf_document_reference"
bl_label = "Open BCF Document Reference"
data: bpy.props.StringProperty()
def execute(self, context):
import bcfplugin
topic_guid, index = self.data.split("/")
doc = bpy.context.scene.BCFProperties.topic_document_references[int(index)]
uri = doc.name
if doc.is_external:
webbrowser.open(uri)
return {"FINISHED"}
webbrowser.open("file://" + os.path.join(bcfplugin.util.getBcfDir(), topic_guid, uri))
return {"FINISHED"}
class SelectAudited(bpy.types.Operator):
bl_idname = "bim.select_audited"
bl_label = "Select Audited"