No new functionality. Just throwing all drawing code in the drawing module. See #1153.

This commit is contained in:
Dion Moult
2021-05-17 15:15:25 +10:00
parent aeead1c011
commit d3bb895c9d
12 changed files with 1509 additions and 1398 deletions
+5 -50
View File
@@ -6,7 +6,7 @@ bpy = sys.modules.get("bpy")
if bpy is not None:
import bpy
import importlib
from . import handler, ui, prop, operator, gizmos
from . import handler, ui, prop, operator
modules = {
"project": None,
@@ -63,50 +63,18 @@ if bpy is not None:
operator.SelectExternalMaterialDir,
operator.FetchExternalMaterial,
operator.FetchObjectPassport,
operator.CutSection,
operator.AddSheet,
operator.OpenSheet,
operator.AddDrawingToSheet,
operator.CreateSheets,
operator.OpenView,
operator.OpenViewCamera,
operator.ActivateView,
operator.OpenUpstream,
operator.AddSectionPlane,
operator.RemoveSectionPlane,
operator.ReloadIfcFile,
operator.AddIfcFile,
operator.RemoveIfcFile,
operator.SelectDocIfcFile,
operator.GenerateReferences,
operator.ResizeText,
operator.AddVariable,
operator.RemoveVariable,
operator.PropagateTextData,
operator.SetOverrideColour,
operator.RemoveDrawing,
operator.AddDrawingStyle,
operator.RemoveDrawingStyle,
operator.SaveDrawingStyle,
operator.ActivateDrawingStyle,
operator.EditVectorStyle,
operator.RemoveSheet,
operator.AddSchedule,
operator.RemoveSchedule,
operator.SelectScheduleFile,
operator.BuildSchedule,
operator.AddScheduleToSheet,
operator.SetViewportShadowFromSun,
operator.AddDrawingStyleAttribute,
operator.RemoveDrawingStyleAttribute,
operator.CopyPropertyToSelection,
operator.CopyAttributeToSelection,
operator.RefreshDrawingList,
operator.CleanWireframes,
operator.LinkIfc,
operator.SnapSpacesTogether,
operator.CopyGrid,
operator.AddSectionsAnnotations,
prop.StrProperty,
prop.Attribute,
prop.BIMProperties,
@@ -118,21 +86,10 @@ if bpy is not None:
prop.ItemSlotMap,
prop.BIMMeshProperties,
ui.BIM_PT_section_plane,
ui.BIM_PT_drawings,
ui.BIM_PT_schedules,
ui.BIM_PT_sheets,
ui.BIM_PT_text,
ui.BIM_PT_annotation_utilities,
ui.BIM_PT_misc_utilities,
ui.BIM_UL_generic,
ui.BIM_UL_drawinglist,
ui.BIM_UL_topics,
ui.BIM_ADDON_preferences,
gizmos.UglyDotGizmo,
gizmos.DotGizmo,
gizmos.DimensionLabelGizmo,
gizmos.ExtrusionGuidesGizmo,
gizmos.ExtrusionWidget
]
for module in modules.values():
@@ -160,7 +117,9 @@ if bpy is not None:
bpy.types.Scene.BIMProperties = bpy.props.PointerProperty(type=prop.BIMProperties)
bpy.types.Object.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
bpy.types.Material.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
bpy.types.Collection.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties) # Check if we need this
bpy.types.Collection.BIMObjectProperties = bpy.props.PointerProperty(
type=prop.BIMObjectProperties
) # Check if we need this
bpy.types.Material.BIMMaterialProperties = bpy.props.PointerProperty(type=prop.BIMMaterialProperties)
bpy.types.Mesh.BIMMeshProperties = bpy.props.PointerProperty(type=prop.BIMMeshProperties)
bpy.types.Curve.BIMMeshProperties = bpy.props.PointerProperty(type=prop.BIMMeshProperties)
@@ -170,8 +129,6 @@ if bpy is not None:
for module in modules.values():
module.register()
bpy.app.handlers.depsgraph_update_pre.append(operator.depsgraph_update_pre_handler)
def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
@@ -183,7 +140,7 @@ if bpy is not None:
del bpy.types.Scene.BIMProperties
del bpy.types.Object.BIMObjectProperties
del bpy.types.Material.BIMObjectProperties
del bpy.types.Collection.BIMObjectProperties # Check if we need this
del bpy.types.Collection.BIMObjectProperties # Check if we need this
del bpy.types.Material.BIMMaterialProperties
del bpy.types.Mesh.BIMMeshProperties
del bpy.types.Curve.BIMMeshProperties
@@ -192,5 +149,3 @@ if bpy is not None:
for module in reversed(list(modules.values())):
module.unregister()
bpy.app.handlers.depsgraph_update_pre.remove(operator.depsgraph_update_pre_handler)
@@ -1,10 +1,42 @@
import bpy
from . import ui, prop, operator, handler
from . import ui, prop, operator, handler, gizmos
classes = (
operator.AddDrawing,
operator.CreateDrawing,
operator.AddAnnotation,
operator.CutSection, # TODO: To deprecate
operator.AddSheet,
operator.OpenSheet,
operator.AddDrawingToSheet,
operator.CreateSheets,
operator.OpenView,
operator.OpenViewCamera,
operator.ActivateView,
operator.SelectDocIfcFile,
operator.GenerateReferences,
operator.ResizeText,
operator.AddVariable,
operator.RemoveVariable,
operator.PropagateTextData,
operator.RemoveDrawing,
operator.AddDrawingStyle,
operator.RemoveDrawingStyle,
operator.SaveDrawingStyle,
operator.ActivateDrawingStyle,
operator.EditVectorStyle,
operator.RemoveSheet,
operator.AddSchedule,
operator.RemoveSchedule,
operator.SelectScheduleFile,
operator.BuildSchedule,
operator.AddScheduleToSheet,
operator.AddDrawingStyleAttribute,
operator.RemoveDrawingStyleAttribute,
operator.RefreshDrawingList,
operator.CleanWireframes,
operator.CopyGrid,
operator.AddSectionsAnnotations,
prop.Variable,
prop.Drawing,
prop.Schedule,
@@ -14,6 +46,17 @@ classes = (
prop.BIMCameraProperties,
prop.BIMTextProperties,
ui.BIM_PT_camera,
ui.BIM_PT_drawings,
ui.BIM_PT_schedules,
ui.BIM_PT_sheets,
ui.BIM_PT_text,
ui.BIM_PT_annotation_utilities,
ui.BIM_UL_drawinglist,
gizmos.UglyDotGizmo,
gizmos.DotGizmo,
gizmos.DimensionLabelGizmo,
gizmos.ExtrusionGuidesGizmo,
gizmos.ExtrusionWidget,
)
@@ -22,6 +65,7 @@ def register():
bpy.types.Camera.BIMCameraProperties = bpy.props.PointerProperty(type=prop.BIMCameraProperties)
bpy.types.TextCurve.BIMTextProperties = bpy.props.PointerProperty(type=prop.BIMTextProperties)
bpy.app.handlers.load_post.append(handler.toggleDecorationsOnLoad)
bpy.app.handlers.depsgraph_update_pre.append(handler.depsgraph_update_pre_handler)
def unregister():
@@ -29,3 +73,4 @@ def unregister():
del bpy.types.Camera.BIMCameraProperties
del bpy.types.TextCurve.BIMTextProperties
bpy.app.handlers.load_post.remove(handler.toggleDecorationsOnLoad)
bpy.app.handlers.depsgraph_update_pre.remove(handler.depsgraph_update_pre_handler)
@@ -1,14 +1,12 @@
import bpy
import blf
from bpy import types
import math
import gpu, bgl
from bpy import types
from mathutils import Vector, Matrix
from mathutils import geometry
import gpu, bgl
from bpy_extras import view3d_utils
from .shaders import DotsGizmoShader, ExtrusionGuidesShader, BaseLinesShader
from blenderbim.bim.module.drawing.shaders import DotsGizmoShader, ExtrusionGuidesShader, BaseLinesShader
"""Gizmos under the hood
@@ -43,76 +41,196 @@ draw_select -- fake-draw of selection geometry for gpu-side cursor tracking
# some geometries for Gizmo.custom_shape shaders
CUBE = (
(+1, +1, +1), (-1, +1, +1), (+1, -1, +1), # top
(+1, -1, +1), (-1, +1, +1), (-1, -1, +1),
(+1, +1, +1), (+1, -1, +1), (+1, +1, -1), # right
(+1, +1, -1), (+1, -1, +1), (+1, -1, -1),
(+1, +1, +1), (+1, +1, -1), (-1, +1, +1), # back
(-1, +1, +1), (+1, +1, -1), (-1, +1, -1),
(-1, -1, -1), (-1, +1, -1), (+1, -1, -1), # bot
(+1, -1, -1), (-1, +1, -1), (+1, +1, -1),
(-1, -1, -1), (-1, -1, +1), (-1, +1, -1), # left
(-1, +1, -1), (-1, -1, +1), (-1, +1, +1),
(-1, -1, -1), (+1, -1, -1), (-1, -1, +1), # front
(-1, -1, +1), (+1, -1, -1), (+1, -1, +1)
(+1, +1, +1),
(-1, +1, +1),
(+1, -1, +1), # top
(+1, -1, +1),
(-1, +1, +1),
(-1, -1, +1),
(+1, +1, +1),
(+1, -1, +1),
(+1, +1, -1), # right
(+1, +1, -1),
(+1, -1, +1),
(+1, -1, -1),
(+1, +1, +1),
(+1, +1, -1),
(-1, +1, +1), # back
(-1, +1, +1),
(+1, +1, -1),
(-1, +1, -1),
(-1, -1, -1),
(-1, +1, -1),
(+1, -1, -1), # bot
(+1, -1, -1),
(-1, +1, -1),
(+1, +1, -1),
(-1, -1, -1),
(-1, -1, +1),
(-1, +1, -1), # left
(-1, +1, -1),
(-1, -1, +1),
(-1, +1, +1),
(-1, -1, -1),
(+1, -1, -1),
(-1, -1, +1), # front
(-1, -1, +1),
(+1, -1, -1),
(+1, -1, +1),
)
DISC = (
(0.0, 0.0, 0.0), (1.0, 0.0, 0), (0.8660254037844387, 0.49999999999999994, 0),
(0.0, 0.0, 0.0), (0.8660254037844387, 0.49999999999999994, 0), (0.5000000000000001, 0.8660254037844386, 0),
(0.0, 0.0, 0.0), (0.5000000000000001, 0.8660254037844386, 0), (6.123233995736766e-17, 1.0, 0),
(0.0, 0.0, 0.0), (6.123233995736766e-17, 1.0, 0), (-0.4999999999999998, 0.8660254037844387, 0),
(0.0, 0.0, 0.0), (-0.4999999999999998, 0.8660254037844387, 0), (-0.8660254037844385, 0.5000000000000003, 0),
(0.0, 0.0, 0.0), (-0.8660254037844385, 0.5000000000000003, 0), (-1.0, 1.2246467991473532e-16, 0),
(0.0, 0.0, 0.0), (-1.0, 1.2246467991473532e-16, 0), (-0.8660254037844388, -0.4999999999999997, 0),
(0.0, 0.0, 0.0), (-0.8660254037844388, -0.4999999999999997, 0), (-0.5000000000000004, -0.8660254037844384, 0),
(0.0, 0.0, 0.0), (-0.5000000000000004, -0.8660254037844384, 0), (-1.8369701987210297e-16, -1.0, 0),
(0.0, 0.0, 0.0), (-1.8369701987210297e-16, -1.0, 0), (0.49999999999999933, -0.866025403784439, 0),
(0.0, 0.0, 0.0), (0.49999999999999933, -0.866025403784439, 0), (0.8660254037844384, -0.5000000000000004, 0),
(0.0, 0.0, 0.0), (0.8660254037844384, -0.5000000000000004, 0), (1.0, 0.0, 0),
(0.0, 0.0, 0.0),
(1.0, 0.0, 0),
(0.8660254037844387, 0.49999999999999994, 0),
(0.0, 0.0, 0.0),
(0.8660254037844387, 0.49999999999999994, 0),
(0.5000000000000001, 0.8660254037844386, 0),
(0.0, 0.0, 0.0),
(0.5000000000000001, 0.8660254037844386, 0),
(6.123233995736766e-17, 1.0, 0),
(0.0, 0.0, 0.0),
(6.123233995736766e-17, 1.0, 0),
(-0.4999999999999998, 0.8660254037844387, 0),
(0.0, 0.0, 0.0),
(-0.4999999999999998, 0.8660254037844387, 0),
(-0.8660254037844385, 0.5000000000000003, 0),
(0.0, 0.0, 0.0),
(-0.8660254037844385, 0.5000000000000003, 0),
(-1.0, 1.2246467991473532e-16, 0),
(0.0, 0.0, 0.0),
(-1.0, 1.2246467991473532e-16, 0),
(-0.8660254037844388, -0.4999999999999997, 0),
(0.0, 0.0, 0.0),
(-0.8660254037844388, -0.4999999999999997, 0),
(-0.5000000000000004, -0.8660254037844384, 0),
(0.0, 0.0, 0.0),
(-0.5000000000000004, -0.8660254037844384, 0),
(-1.8369701987210297e-16, -1.0, 0),
(0.0, 0.0, 0.0),
(-1.8369701987210297e-16, -1.0, 0),
(0.49999999999999933, -0.866025403784439, 0),
(0.0, 0.0, 0.0),
(0.49999999999999933, -0.866025403784439, 0),
(0.8660254037844384, -0.5000000000000004, 0),
(0.0, 0.0, 0.0),
(0.8660254037844384, -0.5000000000000004, 0),
(1.0, 0.0, 0),
)
X3DISC = (
(0.0, 0.0, 0.0), (1.0, 0.0, 0), (0.8660254037844387, 0.49999999999999994, 0),
(0.0, 0.0, 0.0), (0.8660254037844387, 0.49999999999999994, 0), (0.5000000000000001, 0.8660254037844386, 0),
(0.0, 0.0, 0.0), (0.5000000000000001, 0.8660254037844386, 0), (6.123233995736766e-17, 1.0, 0),
(0.0, 0.0, 0.0), (6.123233995736766e-17, 1.0, 0), (-0.4999999999999998, 0.8660254037844387, 0),
(0.0, 0.0, 0.0), (-0.4999999999999998, 0.8660254037844387, 0), (-0.8660254037844385, 0.5000000000000003, 0),
(0.0, 0.0, 0.0), (-0.8660254037844385, 0.5000000000000003, 0), (-1.0, 1.2246467991473532e-16, 0),
(0.0, 0.0, 0.0), (-1.0, 1.2246467991473532e-16, 0), (-0.8660254037844388, -0.4999999999999997, 0),
(0.0, 0.0, 0.0), (-0.8660254037844388, -0.4999999999999997, 0), (-0.5000000000000004, -0.8660254037844384, 0),
(0.0, 0.0, 0.0), (-0.5000000000000004, -0.8660254037844384, 0), (-1.8369701987210297e-16, -1.0, 0),
(0.0, 0.0, 0.0), (-1.8369701987210297e-16, -1.0, 0), (0.49999999999999933, -0.866025403784439, 0),
(0.0, 0.0, 0.0), (0.49999999999999933, -0.866025403784439, 0), (0.8660254037844384, -0.5000000000000004, 0),
(0.0, 0.0, 0.0), (0.8660254037844384, -0.5000000000000004, 0), (1.0, 0.0, 0),
(0.0, 0.0, 0.0), (0, 1.0, 0.0), (0, 0.8660254037844387, 0.49999999999999994),
(0.0, 0.0, 0.0), (0, 0.8660254037844387, 0.49999999999999994), (0, 0.5000000000000001, 0.8660254037844386),
(0.0, 0.0, 0.0), (0, 0.5000000000000001, 0.8660254037844386), (0, 6.123233995736766e-17, 1.0),
(0.0, 0.0, 0.0), (0, 6.123233995736766e-17, 1.0), (0, -0.4999999999999998, 0.8660254037844387),
(0.0, 0.0, 0.0), (0, -0.4999999999999998, 0.8660254037844387), (0, -0.8660254037844385, 0.5000000000000003),
(0.0, 0.0, 0.0), (0, -0.8660254037844385, 0.5000000000000003), (0, -1.0, 1.2246467991473532e-16),
(0.0, 0.0, 0.0), (0, -1.0, 1.2246467991473532e-16), (0, -0.8660254037844388, -0.4999999999999997),
(0.0, 0.0, 0.0), (0, -0.8660254037844388, -0.4999999999999997), (0, -0.5000000000000004, -0.8660254037844384),
(0.0, 0.0, 0.0), (0, -0.5000000000000004, -0.8660254037844384), (0, -1.8369701987210297e-16, -1.0),
(0.0, 0.0, 0.0), (0, -1.8369701987210297e-16, -1.0), (0, 0.49999999999999933, -0.866025403784439),
(0.0, 0.0, 0.0), (0, 0.49999999999999933, -0.866025403784439), (0, 0.8660254037844384, -0.5000000000000004),
(0.0, 0.0, 0.0), (0, 0.8660254037844384, -0.5000000000000004), (0, 1.0, 0.0),
(0.0, 0.0, 0.0), (0.0, 0, 1.0), (0.49999999999999994, 0, 0.8660254037844387),
(0.0, 0.0, 0.0), (0.49999999999999994, 0, 0.8660254037844387), (0.8660254037844386, 0, 0.5000000000000001),
(0.0, 0.0, 0.0), (0.8660254037844386, 0, 0.5000000000000001), (1.0, 0, 6.123233995736766e-17),
(0.0, 0.0, 0.0), (1.0, 0, 6.123233995736766e-17), (0.8660254037844387, 0, -0.4999999999999998),
(0.0, 0.0, 0.0), (0.8660254037844387, 0, -0.4999999999999998), (0.5000000000000003, 0, -0.8660254037844385),
(0.0, 0.0, 0.0), (0.5000000000000003, 0, -0.8660254037844385), (1.2246467991473532e-16, 0, -1.0),
(0.0, 0.0, 0.0), (1.2246467991473532e-16, 0, -1.0), (-0.4999999999999997, 0, -0.8660254037844388),
(0.0, 0.0, 0.0), (-0.4999999999999997, 0, -0.8660254037844388), (-0.8660254037844384, 0, -0.5000000000000004),
(0.0, 0.0, 0.0), (-0.8660254037844384, 0, -0.5000000000000004), (-1.0, 0, -1.8369701987210297e-16),
(0.0, 0.0, 0.0), (-1.0, 0, -1.8369701987210297e-16), (-0.866025403784439, 0, 0.49999999999999933),
(0.0, 0.0, 0.0), (-0.866025403784439, 0, 0.49999999999999933), (-0.5000000000000004, 0, 0.8660254037844384),
(0.0, 0.0, 0.0), (-0.5000000000000004, 0, 0.8660254037844384), (0.0, 0, 1.0),
(0.0, 0.0, 0.0),
(1.0, 0.0, 0),
(0.8660254037844387, 0.49999999999999994, 0),
(0.0, 0.0, 0.0),
(0.8660254037844387, 0.49999999999999994, 0),
(0.5000000000000001, 0.8660254037844386, 0),
(0.0, 0.0, 0.0),
(0.5000000000000001, 0.8660254037844386, 0),
(6.123233995736766e-17, 1.0, 0),
(0.0, 0.0, 0.0),
(6.123233995736766e-17, 1.0, 0),
(-0.4999999999999998, 0.8660254037844387, 0),
(0.0, 0.0, 0.0),
(-0.4999999999999998, 0.8660254037844387, 0),
(-0.8660254037844385, 0.5000000000000003, 0),
(0.0, 0.0, 0.0),
(-0.8660254037844385, 0.5000000000000003, 0),
(-1.0, 1.2246467991473532e-16, 0),
(0.0, 0.0, 0.0),
(-1.0, 1.2246467991473532e-16, 0),
(-0.8660254037844388, -0.4999999999999997, 0),
(0.0, 0.0, 0.0),
(-0.8660254037844388, -0.4999999999999997, 0),
(-0.5000000000000004, -0.8660254037844384, 0),
(0.0, 0.0, 0.0),
(-0.5000000000000004, -0.8660254037844384, 0),
(-1.8369701987210297e-16, -1.0, 0),
(0.0, 0.0, 0.0),
(-1.8369701987210297e-16, -1.0, 0),
(0.49999999999999933, -0.866025403784439, 0),
(0.0, 0.0, 0.0),
(0.49999999999999933, -0.866025403784439, 0),
(0.8660254037844384, -0.5000000000000004, 0),
(0.0, 0.0, 0.0),
(0.8660254037844384, -0.5000000000000004, 0),
(1.0, 0.0, 0),
(0.0, 0.0, 0.0),
(0, 1.0, 0.0),
(0, 0.8660254037844387, 0.49999999999999994),
(0.0, 0.0, 0.0),
(0, 0.8660254037844387, 0.49999999999999994),
(0, 0.5000000000000001, 0.8660254037844386),
(0.0, 0.0, 0.0),
(0, 0.5000000000000001, 0.8660254037844386),
(0, 6.123233995736766e-17, 1.0),
(0.0, 0.0, 0.0),
(0, 6.123233995736766e-17, 1.0),
(0, -0.4999999999999998, 0.8660254037844387),
(0.0, 0.0, 0.0),
(0, -0.4999999999999998, 0.8660254037844387),
(0, -0.8660254037844385, 0.5000000000000003),
(0.0, 0.0, 0.0),
(0, -0.8660254037844385, 0.5000000000000003),
(0, -1.0, 1.2246467991473532e-16),
(0.0, 0.0, 0.0),
(0, -1.0, 1.2246467991473532e-16),
(0, -0.8660254037844388, -0.4999999999999997),
(0.0, 0.0, 0.0),
(0, -0.8660254037844388, -0.4999999999999997),
(0, -0.5000000000000004, -0.8660254037844384),
(0.0, 0.0, 0.0),
(0, -0.5000000000000004, -0.8660254037844384),
(0, -1.8369701987210297e-16, -1.0),
(0.0, 0.0, 0.0),
(0, -1.8369701987210297e-16, -1.0),
(0, 0.49999999999999933, -0.866025403784439),
(0.0, 0.0, 0.0),
(0, 0.49999999999999933, -0.866025403784439),
(0, 0.8660254037844384, -0.5000000000000004),
(0.0, 0.0, 0.0),
(0, 0.8660254037844384, -0.5000000000000004),
(0, 1.0, 0.0),
(0.0, 0.0, 0.0),
(0.0, 0, 1.0),
(0.49999999999999994, 0, 0.8660254037844387),
(0.0, 0.0, 0.0),
(0.49999999999999994, 0, 0.8660254037844387),
(0.8660254037844386, 0, 0.5000000000000001),
(0.0, 0.0, 0.0),
(0.8660254037844386, 0, 0.5000000000000001),
(1.0, 0, 6.123233995736766e-17),
(0.0, 0.0, 0.0),
(1.0, 0, 6.123233995736766e-17),
(0.8660254037844387, 0, -0.4999999999999998),
(0.0, 0.0, 0.0),
(0.8660254037844387, 0, -0.4999999999999998),
(0.5000000000000003, 0, -0.8660254037844385),
(0.0, 0.0, 0.0),
(0.5000000000000003, 0, -0.8660254037844385),
(1.2246467991473532e-16, 0, -1.0),
(0.0, 0.0, 0.0),
(1.2246467991473532e-16, 0, -1.0),
(-0.4999999999999997, 0, -0.8660254037844388),
(0.0, 0.0, 0.0),
(-0.4999999999999997, 0, -0.8660254037844388),
(-0.8660254037844384, 0, -0.5000000000000004),
(0.0, 0.0, 0.0),
(-0.8660254037844384, 0, -0.5000000000000004),
(-1.0, 0, -1.8369701987210297e-16),
(0.0, 0.0, 0.0),
(-1.0, 0, -1.8369701987210297e-16),
(-0.866025403784439, 0, 0.49999999999999933),
(0.0, 0.0, 0.0),
(-0.866025403784439, 0, 0.49999999999999933),
(-0.5000000000000004, 0, 0.8660254037844384),
(0.0, 0.0, 0.0),
(-0.5000000000000004, 0, 0.8660254037844384),
(0.0, 0, 1.0),
)
class CustomGizmo():
class CustomGizmo:
# FIXME: highliting/selection doesnt work
def draw_very_custom_shape(self, ctx, custom_shape, select_id=None):
# similar to draw_custom_shape
@@ -127,7 +245,7 @@ class CustomGizmo():
color = (*self.color_highlight, self.alpha_highlight)
else:
color = (*self.color, self.alpha)
shader.uniform_float('color', color)
shader.uniform_float("color", color)
shape.glenable()
shape.uniform_region(ctx)
@@ -139,31 +257,32 @@ class CustomGizmo():
bgl.glDisable(bgl.GL_BLEND)
class OffsetHandle():
class OffsetHandle:
"""Handling mouse to offset gizmo from base along Z axis"""
# FIXME: works a bit weird for rotated objects
def invoke(self, ctx, event):
self.init_value = self.target_get_value('offset') / self.scale_value
self.init_value = self.target_get_value("offset") / self.scale_value
coordz = self.project_mouse(ctx, event)
if coordz is None:
return {'CANCELLED'}
return {"CANCELLED"}
self.init_coordz = coordz
return {'RUNNING_MODAL'}
return {"RUNNING_MODAL"}
def modal(self, ctx, event, tweak):
coordz = self.project_mouse(ctx, event)
if coordz is None:
return {'CANCELLED'}
return {"CANCELLED"}
delta = coordz - self.init_coordz
if 'PRECISE' in tweak:
if "PRECISE" in tweak:
delta /= 10.0
value = max(0, self.init_value + delta)
value *= self.scale_value
# ctx.area.header_text_set(f"coords: {self.init_coordz} - {coordz}, delta: {delta}, value: {value}")
ctx.area.header_text_set(f"Depth: {value}")
self.target_set_value('offset', value)
return {'RUNNING_MODAL'}
self.target_set_value("offset", value)
return {"RUNNING_MODAL"}
def project_mouse(self, ctx, event):
"""Projecting mouse coords to local axis Z"""
@@ -189,30 +308,29 @@ class OffsetHandle():
def exit(self, ctx, cancel):
if cancel:
self.target_set_value('offset', self.init_value)
self.target_set_value("offset", self.init_value)
else:
self.group.update(ctx)
class UglyDotGizmo(OffsetHandle, types.Gizmo):
"""three orthogonal circles"""
bl_idname = "BIM_GT_uglydot_3d"
bl_target_properties = (
{'id': 'offset', 'type': 'FLOAT', 'array_length': 1},
)
bl_target_properties = ({"id": "offset", "type": "FLOAT", "array_length": 1},)
__slots__ = (
'scale_value',
'custom_shape',
'init_value',
'init_coordz',
"scale_value",
"custom_shape",
"init_value",
"init_coordz",
)
def setup(self):
self.custom_shape = self.new_custom_shape(type='TRIS', verts=X3DISC)
self.custom_shape = self.new_custom_shape(type="TRIS", verts=X3DISC)
def refresh(self):
offset = self.target_get_value('offset') / self.scale_value
offset = self.target_get_value("offset") / self.scale_value
self.matrix_offset.col[3][2] = offset # z-shift
def draw(self, ctx):
@@ -226,15 +344,14 @@ class UglyDotGizmo(OffsetHandle, types.Gizmo):
class DotGizmo(CustomGizmo, OffsetHandle, types.Gizmo):
"""Single dot viewport-aligned"""
# FIXME: make it selectable
bl_idname = "BIM_GT_dot_2d"
bl_target_properties = (
{'id': 'offset', 'type': 'FLOAT', 'array_length': 1},
)
bl_target_properties = ({"id": "offset", "type": "FLOAT", "array_length": 1},)
__slots__ = (
'scale_value',
'custom_shape',
"scale_value",
"custom_shape",
)
def setup(self):
@@ -243,7 +360,7 @@ class DotGizmo(CustomGizmo, OffsetHandle, types.Gizmo):
self.use_draw_scale = False
def refresh(self):
offset = self.target_get_value('offset') / self.scale_value
offset = self.target_get_value("offset") / self.scale_value
self.matrix_offset.col[3][2] = offset # z-shifted
def draw(self, ctx):
@@ -265,15 +382,11 @@ class ExtrusionGuidesGizmo(CustomGizmo, types.Gizmo):
Noninteractive gizmo to indicate extrusion depth and planes.
Draws main segment and orthogonal cross at endpoints.
"""
bl_idname = "BIM_GT_extrusion_guides"
bl_target_properties = (
{'id': 'depth', 'type': 'FLOAT', 'array_length': 1},
)
__slots__ = (
'scale_value',
'custom_shape'
)
bl_idname = "BIM_GT_extrusion_guides"
bl_target_properties = ({"id": "depth", "type": "FLOAT", "array_length": 1},)
__slots__ = ("scale_value", "custom_shape")
def setup(self):
shader = ExtrusionGuidesShader()
@@ -281,7 +394,7 @@ class ExtrusionGuidesGizmo(CustomGizmo, types.Gizmo):
self.use_draw_scale = False
def refresh(self):
depth = self.target_get_value('depth') / self.scale_value
depth = self.target_get_value("depth") / self.scale_value
self.matrix_offset.col[2][2] = depth # z-scaled
def draw(self, ctx):
@@ -291,25 +404,22 @@ class ExtrusionGuidesGizmo(CustomGizmo, types.Gizmo):
class DimensionLabelGizmo(types.Gizmo):
"""Text label for a dimension"""
# does not work properly, fonts are totally screwed up
bl_idname = "BIM_GT_dimension_label"
bl_target_properties = (
{'id': 'value', 'type': 'FLOAT', 'array_length': 1},
)
bl_target_properties = ({"id": "value", "type": "FLOAT", "array_length": 1},)
__slots__ = (
'text_label'
)
__slots__ = "text_label"
def setup(self):
pass
def refresh(self, ctx):
value = self.target_get_value('value')
self.matrix_offset.col[3][2] = value * .5
value = self.target_get_value("value")
self.matrix_offset.col[3][2] = value * 0.5
unit_system = ctx.scene.unit_settings.system
self.text_label = bpy.utils.units.to_string(unit_system, 'LENGTH', value, 3, split_unit=False)
self.text_label = bpy.utils.units.to_string(unit_system, "LENGTH", value, 3, split_unit=False)
def draw(self, ctx):
self.refresh(ctx)
@@ -337,41 +447,44 @@ class DimensionLabelGizmo(types.Gizmo):
class ExtrusionWidget(types.GizmoGroup):
bl_idname = "bim.extrusion_widget"
bl_label = "Extrusion Gizmos"
bl_space_type = 'VIEW_3D'
bl_region_type = 'WINDOW'
bl_options = {'3D', 'PERSISTENT', 'SHOW_MODAL_ALL'}
bl_space_type = "VIEW_3D"
bl_region_type = "WINDOW"
bl_options = {"3D", "PERSISTENT", "SHOW_MODAL_ALL"}
# FIXME: use proper scale from ifc value to blender units
@classmethod
def poll(cls, ctx):
obj = ctx.object
return (obj and obj.type == 'MESH'
and obj.data.BIMMeshProperties.ifc_parameters.get('IfcExtrudedAreaSolid/Depth') is not None)
return (
obj
and obj.type == "MESH"
and obj.data.BIMMeshProperties.ifc_parameters.get("IfcExtrudedAreaSolid/Depth") is not None
)
def setup(self, ctx):
target = ctx.object
prop = target.data.BIMMeshProperties.ifc_parameters.get('IfcExtrudedAreaSolid/Depth')
prop = target.data.BIMMeshProperties.ifc_parameters.get("IfcExtrudedAreaSolid/Depth")
basis = target.matrix_world.normalized()
theme = ctx.preferences.themes[0].user_interface
gz = self.handle = self.gizmos.new('BIM_GT_uglydot_3d')
gz = self.handle = self.gizmos.new("BIM_GT_uglydot_3d")
gz.matrix_basis = basis
gz.scale_basis = 0.1
gz.color = gz.color_highlight = tuple(theme.gizmo_primary)
gz.alpha = 0.5
gz.alpha_highlight = 1.0
gz.use_draw_modal = True
gz.target_set_prop('offset', prop, 'value')
gz.target_set_prop("offset", prop, "value")
gz.scale_value = 1000
gz = self.guides = self.gizmos.new('BIM_GT_extrusion_guides')
gz = self.guides = self.gizmos.new("BIM_GT_extrusion_guides")
gz.matrix_basis = basis
gz.color = gz.color_highlight = tuple(theme.gizmo_secondary)
gz.alpha = gz.alpha_highlight = 0.5
gz.use_draw_modal = True
gz.target_set_prop('depth', prop, 'value')
gz.target_set_prop("depth", prop, "value")
gz.scale_value = 1000
# gz = self.label = self.gizmos.new('GIZMO_GT_dimension_label')
@@ -395,6 +508,6 @@ class ExtrusionWidget(types.GizmoGroup):
# need to retrieve and rebind them again
bpy.ops.bim.get_representation_ifc_parameters()
target = ctx.object
prop = target.data.BIMMeshProperties.ifc_parameters.get('IfcExtrudedAreaSolid/Depth')
self.handle.target_set_prop('offset', prop, 'value')
self.guides.target_set_prop('depth', prop, 'value')
prop = target.data.BIMMeshProperties.ifc_parameters.get("IfcExtrudedAreaSolid/Depth")
self.handle.target_set_prop("offset", prop, "value")
self.guides.target_set_prop("depth", prop, "value")
@@ -10,3 +10,23 @@ def toggleDecorationsOnLoad(*args):
decoration.DecorationsHandler.install(bpy.context)
else:
decoration.DecorationsHandler.uninstall()
@persistent
def depsgraph_update_pre_handler(scene):
set_active_camera_resolution(scene)
def set_active_camera_resolution(scene):
if not scene.camera or "/" not in scene.camera.name or not scene.DocProperties.drawings:
return
if (
scene.render.resolution_x != scene.camera.data.BIMCameraProperties.raster_x
or scene.render.resolution_y != scene.camera.data.BIMCameraProperties.raster_y
):
scene.render.resolution_x = scene.camera.data.BIMCameraProperties.raster_x
scene.render.resolution_y = scene.camera.data.BIMCameraProperties.raster_y
current_drawing = scene.DocProperties.drawings[scene.DocProperties.current_drawing_index]
if scene.camera != current_drawing.camera:
scene.DocProperties.current_drawing_index = scene.DocProperties.drawings.find(scene.camera.name.split("/")[1])
bpy.ops.bim.activate_view(drawing_index=scene.DocProperties.current_drawing_index)
@@ -1,11 +1,16 @@
import os
import bpy
import json
import bmesh
import subprocess
import webbrowser
import ifcopenshell.util.selector
import ifcopenshell.util.representation
import blenderbim.bim.module.drawing.svgwriter as svgwriter
import blenderbim.bim.module.drawing.annotation as annotation
import blenderbim.bim.module.drawing.cut_ifc as cut_ifc # TODO: deprecate
import blenderbim.bim.module.drawing.sheeter as sheeter
import blenderbim.bim.module.drawing.scheduler as scheduler
from mathutils import Vector, Matrix, Euler, geometry
from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.group.data import Data as GroupData
@@ -245,3 +250,955 @@ class AddAnnotation(bpy.types.Operator):
obj.select_set(True)
bpy.ops.object.mode_set(mode="EDIT")
return {"FINISHED"}
class CutSection(bpy.types.Operator):
bl_idname = "bim.cut_section"
bl_label = "Cut Section"
def execute(self, context):
self.file = ifc.IfcStore.get_file()
camera = bpy.context.scene.camera
if not (camera.type == "CAMERA" and camera.data.type == "ORTHO"):
return {"FINISHED"}
if not bpy.context.scene.DocProperties.ifc_files and bpy.context.scene.BIMProperties.ifc_file:
new = bpy.context.scene.DocProperties.ifc_files.add()
new.name = bpy.context.scene.BIMProperties.ifc_file
bpy.ops.bim.activate_view(
drawing_index=bpy.context.scene.DocProperties.drawings.find(camera.name.split("/")[1])
)
drawing_style = bpy.context.scene.DocProperties.drawing_styles[
camera.data.BIMCameraProperties.active_drawing_style_index
]
self.diagram_name = camera.name.split("/")[1]
bpy.context.scene.render.filepath = os.path.join(
bpy.context.scene.BIMProperties.data_dir, "diagrams", "{}.png".format(self.diagram_name)
)
self.create_raster(camera, drawing_style)
location = camera.location
render = bpy.context.scene.render
if self.is_landscape():
width = camera.data.ortho_scale
height = width / render.resolution_x * render.resolution_y
else:
height = camera.data.ortho_scale
width = height / render.resolution_y * render.resolution_x
depth = camera.data.clip_end
projection = camera.matrix_world.to_quaternion() @ Vector((0, 0, -1))
x_axis = camera.matrix_world.to_quaternion() @ Vector((1, 0, 0))
y_axis = camera.matrix_world.to_quaternion() @ Vector((0, -1, 0))
top_left_corner = location - (width / 2 * x_axis) - (height / 2 * y_axis)
ifc_cutter = cut_ifc.IfcCutter()
ifc_cutter.ifc_filenames = [i.name for i in bpy.context.scene.DocProperties.ifc_files]
ifc_cutter.data_dir = bpy.context.scene.BIMProperties.data_dir
ifc_cutter.vector_style = drawing_style.vector_style
ifc_cutter.diagram_name = self.diagram_name
ifc_cutter.background_image = bpy.context.scene.render.filepath
if camera.data.BIMCameraProperties.cut_objects == "CUSTOM":
ifc_cutter.cut_objects = camera.data.BIMCameraProperties.cut_objects_custom
else:
ifc_cutter.cut_objects = camera.data.BIMCameraProperties.cut_objects
ifc_cutter.leader_obj = None
ifc_cutter.stair_obj = None
ifc_cutter.dimension_objs = []
ifc_cutter.break_obj = None
ifc_cutter.equal_objs = []
ifc_cutter.hidden_objs = []
ifc_cutter.solid_objs = []
ifc_cutter.plan_level_obj = None
ifc_cutter.section_level_obj = None
ifc_cutter.grid_objs = []
ifc_cutter.text_objs = []
ifc_cutter.misc_objs = []
ifc_cutter.attributes = [a.name for a in drawing_style.attributes]
for obj in camera.users_collection[0].objects:
if "IfcGrid" in obj.name:
ifc_cutter.grid_objs.append(obj)
elif "IfcGroup" in obj.name and obj.type == "CAMERA":
ifc_cutter.camera_obj = obj
if "IfcAnnotation/" not in obj.name:
continue
if "Leader" in obj.name:
ifc_cutter.leader_obj = (obj, obj.data)
elif "Stair" in obj.name:
ifc_cutter.stair_obj = obj
elif "Equal" in obj.name:
ifc_cutter.equal_objs.append(obj)
elif "Dimension" in obj.name:
ifc_cutter.dimension_objs.append(obj)
elif "Break" in obj.name:
ifc_cutter.break_obj = obj
elif "Hidden" in obj.name:
ifc_cutter.hidden_objs.append((obj, obj.data))
elif "Solid" in obj.name:
ifc_cutter.solid_objs.append((obj, obj.data))
elif "Plan Level" in obj.name:
ifc_cutter.plan_level_obj = obj
elif "Section Level" in obj.name:
ifc_cutter.section_level_obj = obj
elif obj.type == "FONT":
ifc_cutter.text_objs.append(obj)
else:
ifc_cutter.misc_objs.append(obj)
ifc_cutter.section_box = {
"projection": tuple(projection),
"x_axis": tuple(x_axis),
"y_axis": tuple(y_axis),
"top_left_corner": tuple(top_left_corner),
"x": width,
"y": height,
"z": depth,
"shape": None,
"face": None,
}
ifc_cutter.cut_pickle_file = os.path.join(ifc_cutter.data_dir, "{}-cut.pickle".format(self.diagram_name))
ifc_cutter.text_pickle_file = os.path.join(ifc_cutter.data_dir, "{}-text.pickle".format(self.diagram_name))
ifc_cutter.metadata_pickle_file = os.path.join(
ifc_cutter.data_dir, "{}-metadata.pickle".format(self.diagram_name)
)
ifc_cutter.should_recut = bpy.context.scene.DocProperties.should_recut
ifc_cutter.should_recut_selected = bpy.context.scene.DocProperties.should_recut_selected
selected_global_ids = []
for obj in bpy.context.selected_objects:
if "Ifc" not in obj.name:
continue
for attribute in obj.BIMObjectProperties.attributes:
if attribute.name == "GlobalId":
selected_global_ids.append(attribute.string_value)
break
ifc_cutter.selected_global_ids = selected_global_ids
ifc_cutter.should_extract = bpy.context.scene.DocProperties.should_extract
svg_writer = svgwriter.SvgWriter(ifc_cutter)
if camera.data.BIMCameraProperties.diagram_scale == "CUSTOM":
human_scale, fraction = camera.data.BIMCameraProperties.custom_diagram_scale.split("|")
else:
human_scale, fraction = camera.data.BIMCameraProperties.diagram_scale.split("|")
numerator, denominator = fraction.split("/")
if camera.data.BIMCameraProperties.is_nts:
svg_writer.human_scale = "NTS"
else:
svg_writer.human_scale = human_scale
svg_writer.scale = float(numerator) / float(denominator)
ifc_cutter.cut()
svg_writer.write()
bpy.ops.bim.open_view(view=self.diagram_name)
return {"FINISHED"}
def create_raster(self, camera, drawing_style):
if drawing_style.render_type == "NONE":
return
if drawing_style.render_type == "DEFAULT":
return bpy.ops.render.render(write_still=True)
previous_visibility = {}
for obj in camera.users_collection[0].objects:
previous_visibility[obj.name] = obj.hide_get()
obj.hide_set(True)
for obj in bpy.context.visible_objects:
if (
(not obj.data and not obj.instance_collection)
or isinstance(obj.data, bpy.types.Camera)
or "IfcGrid/" in obj.name
or "IfcGridAxis/" in obj.name
or "IfcOpeningElement/" in obj.name
or self.does_obj_have_target_view_representation(obj, camera)
):
previous_visibility[obj.name] = obj.hide_get()
obj.hide_set(True)
space = self.get_view_3d()
previous_shading = space.shading.type
previous_format = bpy.context.scene.render.image_settings.file_format
space.shading.type = "RENDERED"
bpy.context.scene.render.image_settings.file_format = "PNG"
bpy.ops.render.opengl(write_still=True)
space.shading.type = previous_shading
bpy.context.scene.render.image_settings.file_format = previous_format
for name, value in previous_visibility.items():
bpy.data.objects[name].hide_set(value)
def does_obj_have_target_view_representation(self, obj, camera):
if not obj.BIMObjectProperties.ifc_definition_id:
return False
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
if not element.Representation:
return False
for representation in element.Representation.Representations:
if ifcopenshell.util.representation.is_representation_of_context(
representation, "Plan", "Annotation", camera.data.BIMCameraProperties.target_view
):
return True
def is_landscape(self):
return bpy.context.scene.render.resolution_x > bpy.context.scene.render.resolution_y
def get_view_3d(self):
for area in bpy.context.screen.areas:
if area.type != "VIEW_3D":
continue
for space in area.spaces:
if space.type != "VIEW_3D":
continue
return space
class AddSheet(bpy.types.Operator):
bl_idname = "bim.add_sheet"
bl_label = "Add Sheet"
def execute(self, context):
new = bpy.context.scene.DocProperties.sheets.add()
new.name = "{} - SHEET".format(len(bpy.context.scene.DocProperties.sheets))
sheet_builder = sheeter.SheetBuilder()
sheet_builder.data_dir = bpy.context.scene.BIMProperties.data_dir
sheet_builder.create(new.name, bpy.context.scene.DocProperties.titleblock)
return {"FINISHED"}
class OpenSheet(bpy.types.Operator):
bl_idname = "bim.open_sheet"
bl_label = "Open Sheet"
def execute(self, context):
props = bpy.context.scene.DocProperties
open_with_user_command(
bpy.context.preferences.addons["blenderbim"].preferences.svg_command,
os.path.join(
bpy.context.scene.BIMProperties.data_dir, "sheets", props.sheets[props.active_sheet_index].name + ".svg"
),
)
return {"FINISHED"}
class AddDrawingToSheet(bpy.types.Operator):
bl_idname = "bim.add_drawing_to_sheet"
bl_label = "Add Drawing To Sheet"
def execute(self, context):
props = bpy.context.scene.DocProperties
sheet_builder = sheeter.SheetBuilder()
sheet_builder.data_dir = bpy.context.scene.BIMProperties.data_dir
try:
sheet_builder.add_drawing(
props.drawings[props.active_drawing_index].name, props.sheets[props.active_sheet_index].name
)
except:
self.report({"ERROR"}, "Drawings need to be created before being added to a sheet")
return {"FINISHED"}
class CreateSheets(bpy.types.Operator):
bl_idname = "bim.create_sheets"
bl_label = "Create Sheets"
def execute(self, context):
props = bpy.context.scene.DocProperties
name = props.sheets[props.active_sheet_index].name
sheet_builder = sheeter.SheetBuilder()
sheet_builder.data_dir = bpy.context.scene.BIMProperties.data_dir
sheet_builder.build(name)
svg2pdf_command = bpy.context.preferences.addons["blenderbim"].preferences.svg2pdf_command
svg2dxf_command = bpy.context.preferences.addons["blenderbim"].preferences.svg2dxf_command
if svg2pdf_command:
path = os.path.join(bpy.context.scene.BIMProperties.data_dir, "build", name)
svg = os.path.join(path, name + ".svg")
pdf = os.path.join(path, name + ".pdf")
# With great power comes great responsibility. Example:
# [['inkscape', svg, '-o', pdf]]
commands = eval(svg2pdf_command)
for command in commands:
subprocess.run(command)
if svg2dxf_command:
path = os.path.join(bpy.context.scene.BIMProperties.data_dir, "build", name)
svg = os.path.join(path, name + ".svg")
eps = os.path.join(path, name + ".eps")
dxf = os.path.join(path, name + ".dxf")
base = os.path.join(path, name)
# With great power comes great responsibility. Example:
# [['inkscape', svg, '-o', eps], ['pstoedit', '-dt', '-f', 'dxf:-polyaslines -mm', eps, dxf, '-psarg', '-dNOSAFER']]
commands = eval(svg2dxf_command)
for command in commands:
subprocess.run(command)
if svg2pdf_command:
open_with_user_command(bpy.context.preferences.addons["blenderbim"].preferences.pdf_command, pdf)
else:
open_with_user_command(
bpy.context.preferences.addons["blenderbim"].preferences.svg_command,
os.path.join(bpy.context.scene.BIMProperties.data_dir, "build", name, name + ".svg"),
)
return {"FINISHED"}
class OpenView(bpy.types.Operator):
bl_idname = "bim.open_view"
bl_label = "Open View"
view: bpy.props.StringProperty()
def execute(self, context):
open_with_user_command(
bpy.context.preferences.addons["blenderbim"].preferences.svg_command,
os.path.join(bpy.context.scene.BIMProperties.data_dir, "diagrams", self.view + ".svg"),
)
return {"FINISHED"}
class OpenViewCamera(bpy.types.Operator):
bl_idname = "bim.open_view_camera"
bl_label = "Open View Camera"
view_name: bpy.props.StringProperty()
def execute(self, context):
new_drawing_index = bpy.context.scene.DocProperties.drawings.find(self.view_name)
bpy.context.scene.DocProperties.active_drawing_index = new_drawing_index
drawing = bpy.context.scene.DocProperties.drawings[new_drawing_index]
bpy.context.view_layer.objects.active = drawing.camera
bpy.ops.object.select_all(action="DESELECT")
drawing.camera.select_set(True)
for area in bpy.context.screen.areas:
if area.ui_type == "PROPERTIES":
for space in area.spaces:
space.context = "DATA"
return {"FINISHED"}
class ActivateView(bpy.types.Operator):
bl_idname = "bim.activate_view"
bl_label = "Activate View"
drawing_index: bpy.props.IntProperty()
def execute(self, context):
camera = bpy.context.scene.DocProperties.drawings[self.drawing_index].camera
if not camera:
return {"FINISHED"}
bpy.context.scene.camera = camera
area = next(area for area in bpy.context.screen.areas if area.type == "VIEW_3D")
area.spaces[0].region_3d.view_perspective = "CAMERA"
views_collection = bpy.data.collections.get("Views")
for collection in views_collection.children:
# We assume the project collection is at the top level
for project_collection in bpy.context.view_layer.layer_collection.children:
# We assume a convention that the 'Views' collection is directly
# in the project collection
if (
"Views" in project_collection.children
and collection.name in project_collection.children["Views"].children
):
project_collection.children["Views"].children[collection.name].hide_viewport = True
bpy.data.collections.get(collection.name).hide_render = True
bpy.context.view_layer.layer_collection.children["Views"].children[
camera.users_collection[0].name
].hide_viewport = False
bpy.data.collections.get(camera.users_collection[0].name).hide_render = False
bpy.ops.bim.activate_drawing_style()
return {"FINISHED"}
class SelectDocIfcFile(bpy.types.Operator):
bl_idname = "bim.select_doc_ifc_file"
bl_label = "Select Documentation IFC File"
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.scene.DocProperties.ifc_files[self.index].name = self.filepath
return {"FINISHED"}
def invoke(self, context, event):
context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"}
class GenerateReferences(bpy.types.Operator):
bl_idname = "bim.generate_references"
bl_label = "Generate References"
def execute(self, context):
self.camera = bpy.context.scene.camera
self.filter_potential_references()
if self.camera.data.BIMCameraProperties.target_view == "PLAN_VIEW":
self.generate_grids()
if self.camera.data.BIMCameraProperties.target_view == "ELEVATION_VIEW":
self.generate_grids()
self.generate_levels()
if self.camera.data.BIMCameraProperties.target_view == "SECTION_VIEW":
self.generate_grids()
self.generate_levels()
return {"FINISHED"}
def filter_potential_references(self):
for name in ["grids", "levels"]:
setattr(self, name, [])
for obj in bpy.data.objects:
if "IfcGridAxis/" in obj.name:
self.grids.append(obj)
if "IfcBuildingStorey/" in obj.name:
self.levels.append(obj)
def generate_grids(self):
# TODO
pass
def generate_levels(self):
if self.camera.data.BIMCameraProperties.raster_x > self.camera.data.BIMCameraProperties.raster_y:
width = self.camera.data.ortho_scale
height = (
width / self.camera.data.BIMCameraProperties.raster_x * self.camera.data.BIMCameraProperties.raster_y
)
else:
height = self.camera.data.ortho_scale
width = (
height / self.camera.data.BIMCameraProperties.raster_y * self.camera.data.BIMCameraProperties.raster_x
)
level_obj = annotation.Annotator.get_annotation_obj("Section Level", "curve")
width_in_mm = width * 1000
if self.camera.data.BIMCameraProperties.diagram_scale == "CUSTOM":
human_scale, fraction = self.camera.data.BIMCameraProperties.custom_diagram_scale.split("|")
else:
human_scale, fraction = self.camera.data.BIMCameraProperties.diagram_scale.split("|")
numerator, denominator = fraction.split("/")
scale = float(numerator) / float(denominator)
real_world_width_in_mm = width_in_mm * scale
offset_in_mm = 20
offset_percentage = offset_in_mm / real_world_width_in_mm
for obj in self.levels:
projection = self.project_point_onto_camera(obj.location)
co1 = self.camera.matrix_world @ Vector((width / 2 - (offset_percentage * width), projection[1], -1))
co2 = self.camera.matrix_world @ Vector((-(width / 2), projection[1], -1))
annotation.Annotator.add_line_to_annotation(level_obj, co1, co2)
def project_point_onto_camera(self, point):
projection = self.camera.matrix_world.to_quaternion() @ Vector((0, 0, -1))
return self.camera.matrix_world.inverted() @ geometry.intersect_line_plane(
point.xyz, point.xyz - projection, self.camera.location, projection
)
class ResizeText(bpy.types.Operator):
bl_idname = "bim.resize_text"
bl_label = "Resize Text"
def execute(self, context):
for obj in bpy.context.scene.camera.users_collection[0].objects:
if isinstance(obj.data, bpy.types.TextCurve):
annotation.Annotator.resize_text(obj)
return {"FINISHED"}
class AddVariable(bpy.types.Operator):
bl_idname = "bim.add_variable"
bl_label = "Add Variable"
def execute(self, context):
bpy.context.active_object.data.BIMTextProperties.variables.add()
return {"FINISHED"}
class RemoveVariable(bpy.types.Operator):
bl_idname = "bim.remove_variable"
bl_label = "Remove Variable"
index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.active_object.data.BIMTextProperties.variables.remove(self.index)
return {"FINISHED"}
class PropagateTextData(bpy.types.Operator):
bl_idname = "bim.propagate_text_data"
bl_label = "Propagate Text Data"
def execute(self, context):
source = bpy.context.active_object
for obj in bpy.context.selected_objects:
if obj == source:
continue
obj.data.body = source.data.body
obj.data.align_x = source.data.align_x
obj.data.align_y = source.data.align_y
obj.data.BIMTextProperties.font_size = source.data.BIMTextProperties.font_size
obj.data.BIMTextProperties.symbol = source.data.BIMTextProperties.symbol
while len(obj.data.BIMTextProperties.variables) > 0:
obj.data.BIMTextProperties.variables.remove(0)
for variable in source.data.BIMTextProperties.variables:
new_variable = obj.data.BIMTextProperties.variables.add()
new_variable.name = variable.name
new_variable.prop_key = variable.prop_key
return {"FINISHED"}
class RemoveDrawing(bpy.types.Operator):
bl_idname = "bim.remove_drawing"
bl_label = "Remove Drawing"
index: bpy.props.IntProperty()
def execute(self, context):
props = bpy.context.scene.DocProperties
camera = props.drawings[self.index].camera
collection = camera.users_collection[0]
for obj in collection.objects:
bpy.data.objects.remove(obj)
bpy.data.collections.remove(collection, do_unlink=True)
props.drawings.remove(self.index)
return {"FINISHED"}
class AddDrawingStyle(bpy.types.Operator):
bl_idname = "bim.add_drawing_style"
bl_label = "Add Drawing Style"
def execute(self, context):
new = bpy.context.scene.DocProperties.drawing_styles.add()
new.name = "New Drawing Style"
return {"FINISHED"}
class RemoveDrawingStyle(bpy.types.Operator):
bl_idname = "bim.remove_drawing_style"
bl_label = "Remove Drawing Style"
index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.scene.DocProperties.drawing_styles.remove(self.index)
return {"FINISHED"}
class SaveDrawingStyle(bpy.types.Operator):
bl_idname = "bim.save_drawing_style"
bl_label = "Save Drawing Style"
index: bpy.props.StringProperty()
def execute(self, context):
space = self.get_view_3d()
style = {
"bpy.data.worlds[0].color": tuple(bpy.data.worlds[0].color),
"bpy.context.scene.render.engine": bpy.context.scene.render.engine,
"bpy.context.scene.render.film_transparent": bpy.context.scene.render.film_transparent,
"bpy.context.scene.display.shading.show_object_outline": bpy.context.scene.display.shading.show_object_outline,
"bpy.context.scene.display.shading.show_cavity": bpy.context.scene.display.shading.show_cavity,
"bpy.context.scene.display.shading.cavity_type": bpy.context.scene.display.shading.cavity_type,
"bpy.context.scene.display.shading.curvature_ridge_factor": bpy.context.scene.display.shading.curvature_ridge_factor,
"bpy.context.scene.display.shading.curvature_valley_factor": bpy.context.scene.display.shading.curvature_valley_factor,
"bpy.context.scene.view_settings.view_transform": bpy.context.scene.view_settings.view_transform,
"bpy.context.scene.display.shading.light": bpy.context.scene.display.shading.light,
"bpy.context.scene.display.shading.color_type": bpy.context.scene.display.shading.color_type,
"bpy.context.scene.display.shading.single_color": tuple(bpy.context.scene.display.shading.single_color),
"bpy.context.scene.display.shading.show_shadows": bpy.context.scene.display.shading.show_shadows,
"bpy.context.scene.display.shading.shadow_intensity": bpy.context.scene.display.shading.shadow_intensity,
"bpy.context.scene.display.light_direction": tuple(bpy.context.scene.display.light_direction),
"bpy.context.scene.view_settings.use_curve_mapping": bpy.context.scene.view_settings.use_curve_mapping,
"space.overlay.show_wireframes": space.overlay.show_wireframes,
"space.overlay.wireframe_threshold": space.overlay.wireframe_threshold,
"space.overlay.show_floor": space.overlay.show_floor,
"space.overlay.show_axis_x": space.overlay.show_axis_x,
"space.overlay.show_axis_y": space.overlay.show_axis_y,
"space.overlay.show_axis_z": space.overlay.show_axis_z,
"space.overlay.show_object_origins": space.overlay.show_object_origins,
"space.overlay.show_relationship_lines": space.overlay.show_relationship_lines,
}
if self.index:
index = int(self.index)
else:
index = bpy.context.active_object.data.BIMCameraProperties.active_drawing_style_index
bpy.context.scene.DocProperties.drawing_styles[index].raster_style = json.dumps(style)
return {"FINISHED"}
def get_view_3d(self):
for area in bpy.context.screen.areas:
if area.type != "VIEW_3D":
continue
for space in area.spaces:
if space.type != "VIEW_3D":
continue
return space
class ActivateDrawingStyle(bpy.types.Operator):
bl_idname = "bim.activate_drawing_style"
bl_label = "Activate Drawing Style"
def execute(self, context):
if context.scene.camera.data.BIMCameraProperties.active_drawing_style_index < len(
bpy.context.scene.DocProperties.drawing_styles
):
self.drawing_style = bpy.context.scene.DocProperties.drawing_styles[
context.scene.camera.data.BIMCameraProperties.active_drawing_style_index
]
self.set_raster_style()
self.set_query()
return {"FINISHED"}
def set_raster_style(self):
space = self.get_view_3d()
style = json.loads(self.drawing_style.raster_style)
bpy.data.worlds[0].color = style["bpy.data.worlds[0].color"]
bpy.context.scene.render.engine = style["bpy.context.scene.render.engine"]
bpy.context.scene.render.film_transparent = style["bpy.context.scene.render.film_transparent"]
bpy.context.scene.display.shading.show_object_outline = style[
"bpy.context.scene.display.shading.show_object_outline"
]
bpy.context.scene.display.shading.show_cavity = style["bpy.context.scene.display.shading.show_cavity"]
bpy.context.scene.display.shading.cavity_type = style["bpy.context.scene.display.shading.cavity_type"]
bpy.context.scene.display.shading.curvature_ridge_factor = style[
"bpy.context.scene.display.shading.curvature_ridge_factor"
]
bpy.context.scene.display.shading.curvature_valley_factor = style[
"bpy.context.scene.display.shading.curvature_valley_factor"
]
bpy.context.scene.view_settings.view_transform = style["bpy.context.scene.view_settings.view_transform"]
bpy.context.scene.display.shading.light = style["bpy.context.scene.display.shading.light"]
bpy.context.scene.display.shading.color_type = style["bpy.context.scene.display.shading.color_type"]
bpy.context.scene.display.shading.single_color = style["bpy.context.scene.display.shading.single_color"]
bpy.context.scene.display.shading.show_shadows = style["bpy.context.scene.display.shading.show_shadows"]
bpy.context.scene.display.shading.shadow_intensity = style["bpy.context.scene.display.shading.shadow_intensity"]
bpy.context.scene.display.light_direction = style["bpy.context.scene.display.light_direction"]
bpy.context.scene.view_settings.use_curve_mapping = style["bpy.context.scene.view_settings.use_curve_mapping"]
space.overlay.show_wireframes = style["space.overlay.show_wireframes"]
space.overlay.wireframe_threshold = style["space.overlay.wireframe_threshold"]
space.overlay.show_floor = style["space.overlay.show_floor"]
space.overlay.show_axis_x = style["space.overlay.show_axis_x"]
space.overlay.show_axis_y = style["space.overlay.show_axis_y"]
space.overlay.show_axis_z = style["space.overlay.show_axis_z"]
space.overlay.show_object_origins = style["space.overlay.show_object_origins"]
space.overlay.show_relationship_lines = style["space.overlay.show_relationship_lines"]
def set_query(self):
self.selector = ifcopenshell.util.selector.Selector()
self.include_global_ids = []
self.exclude_global_ids = []
for ifc_file in bpy.context.scene.DocProperties.ifc_files:
try:
ifc = ifcopenshell.open(ifc_file.name)
except:
continue
if self.drawing_style.include_query:
results = self.selector.parse(ifc, self.drawing_style.include_query)
self.include_global_ids.extend([e.GlobalId for e in results])
if self.drawing_style.exclude_query:
results = self.selector.parse(ifc, self.drawing_style.exclude_query)
self.exclude_global_ids.extend([e.GlobalId for e in results])
if self.drawing_style.include_query:
self.parse_filter_query("INCLUDE")
if self.drawing_style.exclude_query:
self.parse_filter_query("EXCLUDE")
def parse_filter_query(self, mode):
if mode == "INCLUDE":
objects = bpy.context.scene.objects
elif mode == "EXCLUDE":
objects = bpy.context.visible_objects
for obj in objects:
if mode == "INCLUDE":
obj.hide_viewport = False # Note: this breaks alt-H
global_id = obj.BIMObjectProperties.attributes.get("GlobalId")
if not global_id:
continue
global_id = global_id.string_value
if mode == "INCLUDE":
if global_id not in self.include_global_ids:
obj.hide_viewport = True # Note: this breaks alt-H
elif mode == "EXCLUDE":
if global_id in self.exclude_global_ids:
obj.hide_viewport = True # Note: this breaks alt-H
def get_view_3d(self):
for area in bpy.context.screen.areas:
if area.type != "VIEW_3D":
continue
for space in area.spaces:
if space.type != "VIEW_3D":
continue
return space
class EditVectorStyle(bpy.types.Operator):
bl_idname = "bim.edit_vector_style"
bl_label = "Edit Vector Style"
def execute(self, context):
camera = context.scene.camera
vector_style = context.scene.DocProperties.drawing_styles[
camera.data.BIMCameraProperties.active_drawing_style_index
].vector_style
bpy.data.texts.load(os.path.join(context.scene.BIMProperties.data_dir, "styles", vector_style + ".css"))
return {"FINISHED"}
class RemoveSheet(bpy.types.Operator):
bl_idname = "bim.remove_sheet"
bl_label = "Remove Sheet"
index: bpy.props.IntProperty()
def execute(self, context):
props = bpy.context.scene.DocProperties
props.sheets.remove(self.index)
return {"FINISHED"}
class AddSchedule(bpy.types.Operator):
bl_idname = "bim.add_schedule"
bl_label = "Add Schedule"
def execute(self, context):
new = bpy.context.scene.DocProperties.schedules.add()
new.name = "SCHEDULE {}".format(len(bpy.context.scene.DocProperties.schedules))
return {"FINISHED"}
class RemoveSchedule(bpy.types.Operator):
bl_idname = "bim.remove_schedule"
bl_label = "Remove Schedule"
index: bpy.props.IntProperty()
def execute(self, context):
props = bpy.context.scene.DocProperties
props.schedules.remove(self.index)
return {"FINISHED"}
class SelectScheduleFile(bpy.types.Operator):
bl_idname = "bim.select_schedule_file"
bl_label = "Select Documentation IFC File"
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
filter_glob: bpy.props.StringProperty(default="*.ods", options={"HIDDEN"})
index: bpy.props.IntProperty()
def execute(self, context):
props = bpy.context.scene.DocProperties
props.schedules[props.active_schedule_index].file = self.filepath
return {"FINISHED"}
def invoke(self, context, event):
context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"}
class BuildSchedule(bpy.types.Operator):
bl_idname = "bim.build_schedule"
bl_label = "Build Schedule"
def execute(self, context):
props = bpy.context.scene.DocProperties
schedule = props.schedules[props.active_schedule_index]
schedule_creator = scheduler.Scheduler()
outfile = os.path.join(bpy.context.scene.BIMProperties.data_dir, "schedules", schedule.name + ".svg")
schedule_creator.schedule(schedule.file, outfile)
open_with_user_command(bpy.context.preferences.addons["blenderbim"].preferences.svg_command, outfile)
return {"FINISHED"}
class AddScheduleToSheet(bpy.types.Operator):
bl_idname = "bim.add_schedule_to_sheet"
bl_label = "Add Schedule To Sheet"
def execute(self, context):
props = bpy.context.scene.DocProperties
sheet_builder = sheeter.SheetBuilder()
sheet_builder.data_dir = bpy.context.scene.BIMProperties.data_dir
sheet_builder.add_schedule(
props.schedules[props.active_schedule_index].name, props.sheets[props.active_sheet_index].name
)
return {"FINISHED"}
class AddDrawingStyleAttribute(bpy.types.Operator):
bl_idname = "bim.add_drawing_style_attribute"
bl_label = "Add Drawing Style Attribute"
def execute(self, context):
props = bpy.context.scene.camera.data.BIMCameraProperties
context.scene.DocProperties.drawing_styles[props.active_drawing_style_index].attributes.add()
return {"FINISHED"}
class RemoveDrawingStyleAttribute(bpy.types.Operator):
bl_idname = "bim.remove_drawing_style_attribute"
bl_label = "Remove Drawing Style Attribute"
index: bpy.props.IntProperty()
def execute(self, context):
props = bpy.context.scene.camera.data.BIMCameraProperties
context.scene.DocProperties.drawing_styles[props.active_drawing_style_index].attributes.remove(self.index)
return {"FINISHED"}
class RefreshDrawingList(bpy.types.Operator):
bl_idname = "bim.refresh_drawing_list"
bl_label = "Refresh Drawing List"
def execute(self, context):
while len(bpy.context.scene.DocProperties.drawings) > 0:
bpy.context.scene.DocProperties.drawings.remove(0)
for obj in bpy.context.scene.objects:
if not isinstance(obj.data, bpy.types.Camera):
continue
if "IfcAnnotation/" in obj.name and obj.users_collection[0].name == obj.name:
new = bpy.context.scene.DocProperties.drawings.add()
new.name = obj.name.split("/")[1]
new.camera = obj
return {"FINISHED"}
class CleanWireframes(bpy.types.Operator):
bl_idname = "bim.clean_wireframes"
bl_label = "Clean Wireframes"
def execute(self, context):
objects = bpy.data.objects
if bpy.context.selected_objects:
objects = bpy.context.selected_objects
for obj in objects:
if not isinstance(obj.data, bpy.types.Mesh):
continue
# TODO: probably breaks i18n
if not obj.modifiers.get("EdgeSplit"):
obj.modifiers.new("EdgeSplit", "EDGE_SPLIT")
return {"FINISHED"}
class CopyGrid(bpy.types.Operator):
bl_idname = "bim.add_grid"
bl_label = "Add Grid"
bl_options = {"UNDO"}
def execute(self, context):
proj_coll = helper.get_project_collection(context.scene)
view_coll, camera = helper.get_active_drawing(context.scene)
if view_coll is None:
return {"CANCELLED"}
is_ortho = camera.data.type == "ORTHO"
bounds = helper.ortho_view_frame(camera.data) if is_ortho else None
clipping = is_ortho and camera.data.BIMCameraProperties.target_view in ("PLAN_VIEW", "REFLECTED_PLAN_VIEW")
elevating = is_ortho and camera.data.BIMCameraProperties.target_view in ("ELEVATION_VIEW", "SECTION_VIEW")
def grep(coll):
return [obj for obj in coll.all_objects if obj.name.startswith("IfcGridAxis")]
def clone(src):
dst = src.copy()
dst.data = dst.data.copy()
return dst
def disassemble(obj):
mesh = bmesh.new()
mesh.verts.ensure_lookup_table()
mesh.from_mesh(obj.data)
return obj, mesh
def assemble(obj, mesh):
mesh.to_mesh(obj.data)
return obj
def localize(obj, mesh):
# convert to camera coords
mesh.transform(camera.matrix_world.inverted() @ obj.matrix_world)
obj.matrix_world = camera.matrix_world
return obj, mesh
def clip(mesh):
# clip segment against camera view bounds
mesh.verts.ensure_lookup_table()
points = [v.co for v in mesh.verts[0:2]]
points = helper.clip_segment(bounds, points)
if points is None:
return None
mesh.verts[0].co = points[0]
mesh.verts[1].co = points[1]
return mesh
def elev(mesh):
# put camera-perpendicular segments vertically
mesh.verts.ensure_lookup_table()
points = [v.co for v in mesh.verts[0:2]]
points = helper.elevate_segment(bounds, points)
if points is None:
return None
points = helper.clip_segment(bounds, points)
if points is None:
return None
mesh.verts[0].co = points[0]
mesh.verts[1].co = points[1]
return mesh
for obj in grep(view_coll):
view_coll.objects.unlink(obj)
grid = [localize(*disassemble(clone(obj))) for obj in grep(proj_coll)]
if clipping:
grid = [(obj, clip(mesh)) for obj, mesh in grid]
elif elevating:
grid = [(obj, elev(mesh)) for obj, mesh in grid]
for obj, mesh in grid:
if mesh is not None:
view_coll.objects.link(assemble(obj, mesh))
return {"FINISHED"}
class AddSectionsAnnotations(bpy.types.Operator):
bl_idname = "bim.add_sections_annotations"
bl_label = "Add Sections"
bl_options = {"UNDO"}
def execute(self, context):
scene = context.scene
view_coll, camera = helper.get_active_drawing(scene)
is_ortho = camera.data.type == "ORTHO"
if not is_ortho:
return {"CANCELLED"}
bounds = helper.ortho_view_frame(camera.data) if is_ortho else None
drawings = [
d
for d in scene.DocProperties.drawings
if (
d.camera is not camera
and d.camera.data.type == "ORTHO"
and d.camera.data.BIMCameraProperties.target_view == "SECTION_VIEW"
)
]
def sideview(cam):
# leftmost and righmost points of camera view area, local coords
xmin, xmax, _, _, _, _ = helper.ortho_view_frame(cam.data, margin=0)
proj = camera.matrix_world.inverted() @ cam.matrix_world
p_l = proj @ Vector((xmin, 0, 0))
p_r = proj @ Vector((xmax, 0, 0))
return helper.clip_segment(bounds, (p_l, p_r))
def annotation(drawing, points):
# object with path geometry
name = drawing.name
curve = bpy.data.curves.new(f"Section/{name}", "CURVE")
spline = curve.splines.new("POLY") # has 1 initial point
spline.points.add(1)
p1, p2 = points
z = bounds[4] - 1e-5 # zmin
spline.points[0].co = (p1.x, p1.y, z, 1)
spline.points[1].co = (p2.x, p2.y, z, 1)
obj = bpy.data.objects.new(f"IfcAnnotation/Section/{name}", curve)
obj.matrix_world = camera.matrix_world
return obj
for d in drawings:
points = sideview(d.camera)
if points is None:
continue
obj = annotation(d, points)
view_coll.objects.link(obj)
return {"FINISHED"}
@@ -1,10 +1,10 @@
from mathutils import Matrix
import bgl
from mathutils import Matrix
from gpu.types import GPUShader
from gpu_extras.batch import batch_for_shader
class BaseShader():
class BaseShader:
"""Wrapepr for GPUShader
To use for viewport decorations with geometry generated on GPU side.
@@ -85,14 +85,15 @@ class BaseShader():
def __init__(self):
# NB: libcode arg doesn't work
self.prog = GPUShader(vertexcode=self.VERT_GLSL,
fragcode=self.FRAG_GLSL,
geocode=self.LIB_GLSL + self.GEOM_GLSL,
defines=self.DEF_GLSL)
self.prog = GPUShader(
vertexcode=self.VERT_GLSL,
fragcode=self.FRAG_GLSL,
geocode=self.LIB_GLSL + self.GEOM_GLSL,
defines=self.DEF_GLSL,
)
def batch(self, indices=None, **data):
"""Returns automatic GPUBatch filled with provided parameters
"""
"""Returns automatic GPUBatch filled with provided parameters"""
batch = batch_for_shader(self.prog, self.TYPE, data, indices=indices)
batch.program_set(self.prog)
return batch
@@ -113,23 +114,26 @@ class BaseShader():
region = ctx.region
region3d = ctx.region_data
try:
self.prog.uniform_float('viewMatrix', region3d.perspective_matrix)
self.prog.uniform_float("viewMatrix", region3d.perspective_matrix)
except ValueError: # unused uniform
pass
try:
self.prog.uniform_float('winSize', (region.width / 2, region.height / 2))
self.prog.uniform_float("winSize", (region.width / 2, region.height / 2))
except ValueError: # unused uniform
pass
class BaseLinesShader(BaseShader):
"""Draws line segments with gaps around vertices at endpoints
"""
TYPE = 'LINES'
"""Draws line segments with gaps around vertices at endpoints"""
DEF_GLSL = BaseShader.DEF_GLSL + """
TYPE = "LINES"
DEF_GLSL = (
BaseShader.DEF_GLSL
+ """
#define GAP_SIZE {gap_size}
"""
)
GEOM_GLSL = """
layout(lines) in;
@@ -171,6 +175,7 @@ class GizmoShader(BaseShader):
Scaling to match viewport is partially controlled by user preferences and gizmo code.
"""
# TODO: add some magic to respect gizmo settings/params
VERT_GLSL = """
@@ -187,12 +192,15 @@ class GizmoShader(BaseShader):
class DotsGizmoShader(GizmoShader):
"""Draws circles of radius 1 around points"""
TYPE = 'POINTS'
TYPE = "POINTS"
DEF_GLSL = BaseShader.DEF_GLSL + """
DEF_GLSL = (
BaseShader.DEF_GLSL
+ """
#define CIRCLE_SEGMENTS 12
#define CIRCLE_RADIUS 8
"""
)
GEOM_GLSL = """
layout(points) in;
@@ -235,11 +243,14 @@ class DotsGizmoShader(GizmoShader):
class ExtrusionGuidesShader(GizmoShader):
"""Draws lines and add cross in XY plane at endpoints"""
TYPE = 'LINES'
TYPE = "LINES"
DEF_GLSL = BaseShader.DEF_GLSL + """
DEF_GLSL = (
BaseShader.DEF_GLSL
+ """
#define CROSS_SIZE .5
"""
)
GEOM_GLSL = """
uniform mat4 ModelViewProjectionMatrix;
@@ -110,3 +110,213 @@ class BIM_PT_camera(Panel):
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]
class BIM_PT_drawings(Panel):
bl_label = "SVG Drawings"
bl_idname = "BIM_PT_drawings"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "output"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
props = bpy.context.scene.DocProperties
row = layout.row(align=True)
row.operator("bim.add_drawing")
row.operator("bim.refresh_drawing_list", icon="FILE_REFRESH", text="")
if props.drawings:
if props.active_drawing_index < len(props.drawings):
op = row.operator("bim.open_view", icon="URL", text="")
op.view = props.drawings[props.active_drawing_index].name
row.operator("bim.remove_drawing", icon="X", text="").index = props.active_drawing_index
layout.template_list("BIM_UL_generic", "", props, "drawings", props, "active_drawing_index")
row = layout.row()
row.operator("bim.add_ifc_file")
for index, ifc_file in enumerate(props.ifc_files):
row = layout.row(align=True)
row.prop(ifc_file, "name", text="IFC #{}".format(index + 1))
row.operator("bim.select_doc_ifc_file", icon="FILE_FOLDER", text="").index = index
row.operator("bim.remove_ifc_file", icon="X", text="").index = index
class BIM_PT_schedules(Panel):
bl_label = "ODS Schedules"
bl_idname = "BIM_PT_schedules"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "output"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
props = bpy.context.scene.DocProperties
row = layout.row(align=True)
row.operator("bim.add_schedule")
if props.schedules:
row.operator("bim.build_schedule", icon="LINENUMBERS_ON", text="")
row.operator("bim.remove_schedule", icon="X", text="").index = props.active_schedule_index
layout.template_list("BIM_UL_generic", "", props, "schedules", props, "active_schedule_index")
row = layout.row()
row.prop(props.schedules[props.active_schedule_index], "file")
row.operator("bim.select_schedule_file", icon="FILE_FOLDER", text="")
class BIM_PT_sheets(Panel):
bl_label = "SVG Sheets"
bl_idname = "BIM_PT_sheets"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "output"
def draw(self, context):
layout = self.layout
props = bpy.context.scene.DocProperties
row = layout.row(align=True)
row.prop(props, "titleblock", text="")
row.operator("bim.add_sheet")
if props.sheets:
row.operator("bim.open_sheet", icon="URL", text="")
row.operator("bim.remove_sheet", icon="X", text="").index = props.active_sheet_index
layout.template_list("BIM_UL_generic", "", props, "sheets", props, "active_sheet_index")
row = layout.row(align=True)
row.operator("bim.add_drawing_to_sheet")
row.operator("bim.add_schedule_to_sheet")
row = layout.row()
row.operator("bim.create_sheets")
class BIM_PT_text(Panel):
bl_label = "Text Paper Space"
bl_idname = "BIM_PT_text"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "data"
@classmethod
def poll(cls, context):
return type(context.curve) is bpy.types.TextCurve
def draw(self, context):
layout = self.layout
layout.use_property_split = True
props = context.active_object.data.BIMTextProperties
row = layout.row()
row.operator("bim.propagate_text_data")
row = layout.row()
row.prop(props, "font_size")
row = layout.row()
row.prop(props, "symbol")
row = layout.row()
row.prop(props, "related_element")
row = layout.row()
row.operator("bim.add_variable")
for index, variable in enumerate(props.variables):
row = layout.row(align=True)
row.prop(variable, "name")
row.operator("bim.remove_variable", icon="X", text="").index = index
row = layout.row()
row.prop(variable, "prop_key")
class BIM_PT_annotation_utilities(Panel):
bl_idname = "BIM_PT_annotation_utilities"
bl_label = "Annotation"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "BlenderBIM"
def draw(self, context):
layout = self.layout
row = layout.row(align=True)
row.operator("bim.clean_wireframes")
row = layout.row(align=True)
row.operator("bim.link_ifc")
row = layout.row(align=True)
row.operator("bim.add_grid")
row = layout.row(align=True)
row.operator("bim.add_sections_annotations")
row = layout.row(align=True)
op = row.operator("bim.add_annotation", text="Dim", icon="ARROW_LEFTRIGHT")
op.obj_name = "Dimension"
op.data_type = "curve"
op = row.operator("bim.add_annotation", text="Dim (Eq)", icon="ARROW_LEFTRIGHT")
op.obj_name = "Equal"
op.data_type = "curve"
row = layout.row(align=True)
op = row.operator("bim.add_annotation", text="Text", icon="SMALL_CAPS")
op.data_type = "text"
op = row.operator("bim.add_annotation", text="Leader", icon="TRACKING_BACKWARDS")
op.obj_name = "Leader"
op.data_type = "curve"
row = layout.row(align=True)
op = row.operator("bim.add_annotation", text="Stair Arrow", icon="SCREEN_BACK")
op.obj_name = "Stair"
op.data_type = "curve"
op = row.operator("bim.add_annotation", text="Hidden", icon="CON_TRACKTO")
op.obj_name = "Hidden"
op.data_type = "mesh"
row = layout.row(align=True)
op = row.operator("bim.add_annotation", text="Level (Plan)", icon="SORTBYEXT")
op.obj_name = "Plan Level"
op.data_type = "curve"
op = row.operator("bim.add_annotation", text="Level (Section)", icon="TRIA_DOWN")
op.obj_name = "Section Level"
op.data_type = "curve"
row = layout.row(align=True)
op = row.operator("bim.add_annotation", text="Breakline", icon="FCURVE")
op.obj_name = "Break"
op.data_type = "mesh"
op = row.operator("bim.add_annotation", text="Misc", icon="MESH_MONKEY")
op.obj_name = "Misc"
op.data_type = "mesh"
props = bpy.context.scene.DocProperties
row = layout.row(align=True)
row.operator("bim.add_drawing")
row.operator("bim.refresh_drawing_list", icon="FILE_REFRESH", text="")
if props.drawings:
if props.active_drawing_index < len(props.drawings):
op = row.operator("bim.open_view", icon="URL", text="")
op.view = props.drawings[props.active_drawing_index].name
row.operator("bim.remove_drawing", icon="X", text="").index = props.active_drawing_index
layout.template_list("BIM_UL_drawinglist", "", props, "drawings", props, "active_drawing_index")
layout.prop(props, "should_draw_decorations")
layout.prop(props, "decorations_colour")
class BIM_UL_drawinglist(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
if item:
row = layout.row(align=True)
row.prop(item, "name", text="", emboss=False)
op = row.operator("bim.open_view_camera", icon="OUTLINER_OB_CAMERA", text="")
op.view_name = item.name
else:
layout.label(text="", translate=False)
File diff suppressed because it is too large Load Diff
-210
View File
@@ -5,93 +5,6 @@ from bpy.types import Panel
from bpy.props import StringProperty, BoolProperty
class BIM_PT_drawings(Panel):
bl_label = "SVG Drawings"
bl_idname = "BIM_PT_drawings"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "output"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
props = bpy.context.scene.DocProperties
row = layout.row(align=True)
row.operator("bim.add_drawing")
row.operator("bim.refresh_drawing_list", icon="FILE_REFRESH", text="")
if props.drawings:
if props.active_drawing_index < len(props.drawings):
op = row.operator("bim.open_view", icon="URL", text="")
op.view = props.drawings[props.active_drawing_index].name
row.operator("bim.remove_drawing", icon="X", text="").index = props.active_drawing_index
layout.template_list("BIM_UL_generic", "", props, "drawings", props, "active_drawing_index")
row = layout.row()
row.operator("bim.add_ifc_file")
for index, ifc_file in enumerate(props.ifc_files):
row = layout.row(align=True)
row.prop(ifc_file, "name", text="IFC #{}".format(index + 1))
row.operator("bim.select_doc_ifc_file", icon="FILE_FOLDER", text="").index = index
row.operator("bim.remove_ifc_file", icon="X", text="").index = index
class BIM_PT_schedules(Panel):
bl_label = "ODS Schedules"
bl_idname = "BIM_PT_schedules"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "output"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
props = bpy.context.scene.DocProperties
row = layout.row(align=True)
row.operator("bim.add_schedule")
if props.schedules:
row.operator("bim.build_schedule", icon="LINENUMBERS_ON", text="")
row.operator("bim.remove_schedule", icon="X", text="").index = props.active_schedule_index
layout.template_list("BIM_UL_generic", "", props, "schedules", props, "active_schedule_index")
row = layout.row()
row.prop(props.schedules[props.active_schedule_index], "file")
row.operator("bim.select_schedule_file", icon="FILE_FOLDER", text="")
class BIM_PT_sheets(Panel):
bl_label = "SVG Sheets"
bl_idname = "BIM_PT_sheets"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "output"
def draw(self, context):
layout = self.layout
props = bpy.context.scene.DocProperties
row = layout.row(align=True)
row.prop(props, "titleblock", text="")
row.operator("bim.add_sheet")
if props.sheets:
row.operator("bim.open_sheet", icon="URL", text="")
row.operator("bim.remove_sheet", icon="X", text="").index = props.active_sheet_index
layout.template_list("BIM_UL_generic", "", props, "sheets", props, "active_sheet_index")
row = layout.row(align=True)
row.operator("bim.add_drawing_to_sheet")
row.operator("bim.add_schedule_to_sheet")
row = layout.row()
row.operator("bim.create_sheets")
class BIM_PT_section_plane(Panel):
bl_label = "Temporary Section Cutaways"
bl_idname = "BIM_PT_section_plane"
@@ -115,43 +28,6 @@ class BIM_PT_section_plane(Panel):
row.operator("bim.remove_section_plane")
class BIM_PT_text(Panel):
bl_label = "Text Paper Space"
bl_idname = "BIM_PT_text"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "data"
@classmethod
def poll(cls, context):
return type(context.curve) is bpy.types.TextCurve
def draw(self, context):
layout = self.layout
layout.use_property_split = True
props = context.active_object.data.BIMTextProperties
row = layout.row()
row.operator("bim.propagate_text_data")
row = layout.row()
row.prop(props, "font_size")
row = layout.row()
row.prop(props, "symbol")
row = layout.row()
row.prop(props, "related_element")
row = layout.row()
row.operator("bim.add_variable")
for index, variable in enumerate(props.variables):
row = layout.row(align=True)
row.prop(variable, "name")
row.operator("bim.remove_variable", icon="X", text="").index = index
row = layout.row()
row.prop(variable, "prop_key")
class BIM_UL_generic(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
if item:
@@ -160,17 +36,6 @@ class BIM_UL_generic(bpy.types.UIList):
layout.label(text="", translate=False)
class BIM_UL_drawinglist(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
if item:
row = layout.row(align=True)
row.prop(item, "name", text="", emboss=False)
op = row.operator("bim.open_view_camera", icon="OUTLINER_OB_CAMERA", text="")
op.view_name = item.name
else:
layout.label(text="", translate=False)
class BIM_UL_topics(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
ob = data
@@ -224,81 +89,6 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences):
row.prop(self, "should_hide_empty_props")
class BIM_PT_annotation_utilities(Panel):
bl_idname = "BIM_PT_annotation_utilities"
bl_label = "Annotation"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "BlenderBIM"
def draw(self, context):
layout = self.layout
row = layout.row(align=True)
row.operator("bim.clean_wireframes")
row = layout.row(align=True)
row.operator("bim.link_ifc")
row = layout.row(align=True)
row.operator("bim.add_grid")
row = layout.row(align=True)
row.operator("bim.add_sections_annotations")
row = layout.row(align=True)
op = row.operator("bim.add_annotation", text="Dim", icon="ARROW_LEFTRIGHT")
op.obj_name = "Dimension"
op.data_type = "curve"
op = row.operator("bim.add_annotation", text="Dim (Eq)", icon="ARROW_LEFTRIGHT")
op.obj_name = "Equal"
op.data_type = "curve"
row = layout.row(align=True)
op = row.operator("bim.add_annotation", text="Text", icon="SMALL_CAPS")
op.data_type = "text"
op = row.operator("bim.add_annotation", text="Leader", icon="TRACKING_BACKWARDS")
op.obj_name = "Leader"
op.data_type = "curve"
row = layout.row(align=True)
op = row.operator("bim.add_annotation", text="Stair Arrow", icon="SCREEN_BACK")
op.obj_name = "Stair"
op.data_type = "curve"
op = row.operator("bim.add_annotation", text="Hidden", icon="CON_TRACKTO")
op.obj_name = "Hidden"
op.data_type = "mesh"
row = layout.row(align=True)
op = row.operator("bim.add_annotation", text="Level (Plan)", icon="SORTBYEXT")
op.obj_name = "Plan Level"
op.data_type = "curve"
op = row.operator("bim.add_annotation", text="Level (Section)", icon="TRIA_DOWN")
op.obj_name = "Section Level"
op.data_type = "curve"
row = layout.row(align=True)
op = row.operator("bim.add_annotation", text="Breakline", icon="FCURVE")
op.obj_name = "Break"
op.data_type = "mesh"
op = row.operator("bim.add_annotation", text="Misc", icon="MESH_MONKEY")
op.obj_name = "Misc"
op.data_type = "mesh"
props = bpy.context.scene.DocProperties
row = layout.row(align=True)
row.operator("bim.add_drawing")
row.operator("bim.refresh_drawing_list", icon="FILE_REFRESH", text="")
if props.drawings:
if props.active_drawing_index < len(props.drawings):
op = row.operator("bim.open_view", icon="URL", text="")
op.view = props.drawings[props.active_drawing_index].name
row.operator("bim.remove_drawing", icon="X", text="").index = props.active_drawing_index
layout.template_list("BIM_UL_drawinglist", "", props, "drawings", props, "active_drawing_index")
layout.prop(props, "should_draw_decorations")
layout.prop(props, "decorations_colour")
class BIM_PT_misc_utilities(Panel):
bl_idname = "BIM_PT_misc_utilities"
bl_label = "Miscellaneous"