Skip to content
This repository was archived by the owner on Nov 24, 2024. It is now read-only.

Commit cc5f34a

Browse files
qwiglydeeMoult
authored andcommitted
text drawing
1 parent 33bf705 commit cc5f34a

1 file changed

Lines changed: 73 additions & 11 deletions

File tree

Lines changed: 73 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
"""Viewport decorations"""
2+
import math
23
from bpy.types import SpaceView3D
4+
from mathutils import Vector
35
import bpy
46
import blf
7+
from bpy_extras.view3d_utils import location_3d_to_region_2d
58

69

710
class ViewDecorator(object):
@@ -15,7 +18,10 @@ def install(cls, *args, **kwargs):
1518

1619
@classmethod
1720
def uninstall(cls):
18-
SpaceView3D.draw_handler_remove(cls.installed, 'WINDOW')
21+
try:
22+
SpaceView3D.draw_handler_remove(cls.installed, 'WINDOW')
23+
except ValueError:
24+
pass
1925
cls.installed = None
2026

2127

@@ -25,23 +31,79 @@ class DimensionDecorator(ViewDecorator):
2531
- puts metric text next to each segment
2632
"""
2733

28-
def __init__(self, scene, context):
29-
self.scene = scene
34+
def __init__(self, props, context):
3035
self.context = context
31-
self.font_id = 0
36+
self.props = props
37+
self.font_id = 0 # TODO: take font from styles
3238
self.dpi = context.preferences.system.dpi
33-
print("Created decorator", scene)
3439

3540
def __call__(self):
3641
# get active drawing, if any
37-
if self.scene.active_drawing_index is None or len(self.scene.drawings) == 0:
42+
if self.props.active_drawing_index is None or len(self.props.drawings) == 0:
3843
return
39-
drawing = self.scene.drawings[self.scene.active_drawing_index]
44+
drawing = self.props.drawings[self.props.active_drawing_index]
4045
collection = bpy.data.collections.get("IfcGroup/" + drawing.name)
46+
# get curve object
4147
if 'IfcAnnotation/Dimension' not in collection.all_objects:
4248
return
43-
curve = collection.all_objects['IfcAnnotation/Dimension'].data
44-
text = repr(curve)
45-
blf.position(self.font_id, 100, 100, 0)
46-
blf.size(self.font_id, 10, self.dpi)
49+
curve = collection.all_objects['IfcAnnotation/Dimension']
50+
51+
for segm in self.iter_segments(curve):
52+
self.draw_label(segm)
53+
self.draw_arrow(segm)
54+
55+
def iter_segments(self, curve):
56+
"""Yields each segment converted to world coords
57+
(v0, v1, length)
58+
"""
59+
for spline in curve.data.splines:
60+
points = [curve.matrix_world @ p.co for p in spline.points]
61+
for i in range(len(points)-1):
62+
p0 = points[i]
63+
p1 = points[i+1]
64+
length = (p1 - p0).length
65+
yield (p0, p1, length)
66+
67+
def draw_label(self, segm):
68+
"""Draw text of segment length
69+
aligned and centered at segment middle
70+
"""
71+
p0, p1, length = segm
72+
73+
# convert to view coords
74+
region = self.context.region
75+
region3d = self.context.region_data
76+
p0 = location_3d_to_region_2d(region, region3d, p0)
77+
p1 = location_3d_to_region_2d(region, region3d, p1)
78+
79+
text = f"{length:.2f}"
80+
81+
ang = -Vector((1, 0)).angle_signed(p1 - p0)
82+
cos = math.cos(ang)
83+
sin = math.sin(ang)
84+
85+
# midpoint
86+
pos = p0 + (p1 - p0) * .5
87+
88+
# TODO: take font size from styles
89+
blf.size(self.font_id, 16, self.dpi)
90+
w, h = blf.dimensions(self.font_id, text)
91+
92+
# align centered
93+
pos -= Vector((cos, sin)) * w * 0.5
94+
95+
# add padding
96+
# TODO: take padding from styles and adjust to line width
97+
pos += Vector((-sin, cos)) * 4
98+
99+
# TODO: handle overlapping of text with arrows for narrow segments
100+
101+
blf.enable(self.font_id, blf.ROTATION)
102+
blf.position(self.font_id, pos.x, pos.y, 0)
103+
104+
blf.rotation(self.font_id, ang)
47105
blf.draw(self.font_id, text)
106+
blf.disable(self.font_id, blf.ROTATION)
107+
108+
def draw_arrow(self, segm):
109+
pass

0 commit comments

Comments
 (0)