refectored decorations.

fixed #1241 somehow
This commit is contained in:
QwiglyDee
2021-01-06 03:52:40 +07:00
parent db5418cbfe
commit 02b01b2a44
2 changed files with 131 additions and 137 deletions
+128 -131
View File
@@ -21,7 +21,6 @@ class BaseDecorator():
DEF_GLSL = """ DEF_GLSL = """
#define PI 3.141592653589793 #define PI 3.141592653589793
#define COLOR vec4({color[0]}, {color[1]}, {color[2]}, {color[3]})
#define MAX_POINTS 64 #define MAX_POINTS 64
#define CIRCLE_SEGS 24 #define CIRCLE_SEGS 24
""" """
@@ -99,63 +98,28 @@ class BaseDecorator():
""" """
FRAG_GLSL = """ FRAG_GLSL = """
uniform vec4 color;
out vec4 fragColor; out vec4 fragColor;
void main() { void main() {
fragColor = COLOR; fragColor = color;
} }
""" """
# class var for single handler def __init__(self):
installed = None
@classmethod
def install(cls, *args, **kwargs):
if cls.installed:
cls.uninstall()
handler = cls(*args, **kwargs)
cls.installed = SpaceView3D.draw_handler_add(handler, (), 'WINDOW', 'POST_PIXEL')
@classmethod
def uninstall(cls):
try:
SpaceView3D.draw_handler_remove(cls.installed, 'WINDOW')
except ValueError:
pass
cls.installed = None
def __init__(self, props, context):
self.context = context
self.props = props
self.shader = self.create_shader()
self.font_id = 0
self.font_size = 16
self.dpi = context.preferences.system.dpi
def create_shader(self):
defines = self.DEF_GLSL.format(color=self.props.decorations_colour)
# NB: libcode param doesn't work # NB: libcode param doesn't work
return GPUShader(vertexcode=self.VERT_GLSL, self.shader = GPUShader(vertexcode=self.VERT_GLSL,
fragcode=self.FRAG_GLSL, fragcode=self.FRAG_GLSL,
geocode=self.LIB_GLSL + self.GEOM_GLSL, geocode=self.LIB_GLSL + self.GEOM_GLSL,
defines=defines) defines=self.DEF_GLSL)
def __call__(self): def get_objects(self, collection):
if self.props.active_drawing_index is None or len(self.props.drawings) == 0:
return
for obj in self.get_objects():
self.decorate(obj)
def get_objects(self):
"""find relevant objects """find relevant objects
using class.basename using class.basename
returns: iterable of blender objects returns: iterable of blender objects
""" """
drawing = self.props.drawings[self.props.active_drawing_index] return filter(lambda o: self.basename in o.name, collection.all_objects)
collection = bpy.data.collections.get("IfcGroup/" + drawing.name)
return filter(lambda o: self.basename in o.name, collection.objects)
def get_path_geom(self, obj, topo=True): def get_path_geom(self, obj, topo=True):
"""Parses path geometry into line segments """Parses path geometry into line segments
@@ -223,13 +187,14 @@ class BaseDecorator():
return vertices, indices return vertices, indices
def decorate(self, object): def decorate(self, context, object):
"""perform actuall drawing stuff""" """perform actuall drawing stuff"""
raise NotImplementedError() raise NotImplementedError()
def draw_lines(self, obj, vertices, indices, topology=None): def draw_lines(self, context, obj, vertices, indices, topology=None):
region = self.context.region region = context.region
region3d = self.context.region_data region3d = context.region_data
color = context.scene.DocProperties.decorations_colour
fmt = GPUVertFormat() fmt = GPUVertFormat()
fmt.attr_add(id="pos", comp_type='F32', len=3, fetch_mode='FLOAT') fmt.attr_add(id="pos", comp_type='F32', len=3, fetch_mode='FLOAT')
@@ -245,18 +210,20 @@ class BaseDecorator():
batch = GPUBatch(type='LINES', buf=vbo, elem=ibo) batch = GPUBatch(type='LINES', buf=vbo, elem=ibo)
self.shader.bind()
self.shader.uniform_float
self.shader.uniform_float("viewMatrix", region3d.perspective_matrix)
self.shader.uniform_float("winsize", (region.width, region.height))
bgl.glEnable(bgl.GL_LINE_SMOOTH) bgl.glEnable(bgl.GL_LINE_SMOOTH)
bgl.glHint(bgl.GL_LINE_SMOOTH_HINT, bgl.GL_NICEST) bgl.glHint(bgl.GL_LINE_SMOOTH_HINT, bgl.GL_NICEST)
bgl.glEnable(bgl.GL_BLEND) bgl.glEnable(bgl.GL_BLEND)
bgl.glBlendFunc(bgl.GL_SRC_ALPHA, bgl.GL_ONE_MINUS_SRC_ALPHA) bgl.glBlendFunc(bgl.GL_SRC_ALPHA, bgl.GL_ONE_MINUS_SRC_ALPHA)
self.shader.bind()
self.shader.uniform_float
self.shader.uniform_float("viewMatrix", region3d.perspective_matrix)
self.shader.uniform_float("winsize", (region.width, region.height))
self.shader.uniform_float("color", color)
batch.draw(self.shader) batch.draw(self.shader)
def draw_label(self, text, pos, dir, gap=4, center=True, vcenter=False): def draw_label(self, context, text, pos, dir, gap=4, center=True, vcenter=False):
"""Draw text label """Draw text label
Args: Args:
@@ -264,15 +231,21 @@ class BaseDecorator():
aligned and centered at segment middle aligned and centered at segment middle
""" """
font_id = 0
font_size = 16
dpi = context.preferences.system.dpi
color = context.scene.DocProperties.decorations_colour
ang = -Vector((1, 0)).angle_signed(dir) ang = -Vector((1, 0)).angle_signed(dir)
cos = math.cos(ang) cos = math.cos(ang)
sin = math.sin(ang) sin = math.sin(ang)
blf.size(self.font_id, self.font_size, self.dpi) blf.size(font_id, font_size, dpi)
w, h = 0, 0 w, h = 0, 0
if center or vcenter: if center or vcenter:
w, h = blf.dimensions(self.font_id, text) w, h = blf.dimensions(font_id, text)
if center: if center:
# horizontal centering # horizontal centering
@@ -286,18 +259,18 @@ class BaseDecorator():
# side-shifting # side-shifting
pos += Vector((-sin, cos)) * gap pos += Vector((-sin, cos)) * gap
blf.enable(self.font_id, blf.ROTATION) blf.enable(font_id, blf.ROTATION)
blf.position(self.font_id, pos.x, pos.y, 0) blf.position(font_id, pos.x, pos.y, 0)
blf.rotation(self.font_id, ang) blf.rotation(font_id, ang)
blf.color(self.font_id, *self.props.decorations_colour) blf.color(font_id, *color)
blf.draw(self.font_id, text) blf.draw(font_id, text)
blf.disable(self.font_id, blf.ROTATION) blf.disable(font_id, blf.ROTATION)
def format_value(self, value): def format_value(self, context, value):
unit_system = bpy.context.scene.unit_settings.system unit_system = context.scene.unit_settings.system
if unit_system == 'IMPERIAL': if unit_system == 'IMPERIAL':
precision = bpy.context.scene.BIMProperties.imperial_precision precision = context.scene.BIMProperties.imperial_precision
if precision == "NONE": if precision == "NONE":
precision = 256 precision = 256
elif precision == "1": elif precision == "1":
@@ -318,7 +291,6 @@ class DimensionDecorator(BaseDecorator):
- puts metric text next to each segment - puts metric text next to each segment
""" """
basename = "IfcAnnotation/Dimension" basename = "IfcAnnotation/Dimension"
installed = None
DEF_GLSL = BaseDecorator.DEF_GLSL + """ DEF_GLSL = BaseDecorator.DEF_GLSL + """
#define ARROW_ANGLE PI / 12.0 #define ARROW_ANGLE PI / 12.0
@@ -382,14 +354,14 @@ class DimensionDecorator(BaseDecorator):
} }
""" """
def decorate(self, obj): def decorate(self, context, obj):
verts, idxs, _ = self.get_path_geom(obj, topo=False) verts, idxs, _ = self.get_path_geom(obj, topo=False)
self.draw_lines(obj, verts, idxs) self.draw_lines(context, obj, verts, idxs)
self.draw_labels(obj, verts, idxs) self.draw_labels(context, obj, verts, idxs)
def draw_labels(self, obj, vertices, indices): def draw_labels(self, context, obj, vertices, indices):
region = self.context.region region = context.region
region3d = self.context.region_data region3d = context.region_data
for i0, i1 in indices: for i0, i1 in indices:
v0 = Vector(vertices[i0]) v0 = Vector(vertices[i0])
v1 = Vector(vertices[i1]) v1 = Vector(vertices[i1])
@@ -399,8 +371,8 @@ class DimensionDecorator(BaseDecorator):
if dir.length < 1: if dir.length < 1:
continue continue
length = (v1 - v0).length length = (v1 - v0).length
text = self.format_value(length) text = self.format_value(context, length)
self.draw_label(text, p0 + (dir) * .5, dir) self.draw_label(context, text, p0 + (dir) * .5, dir)
class EqualityDecorator(DimensionDecorator): class EqualityDecorator(DimensionDecorator):
@@ -410,11 +382,10 @@ class EqualityDecorator(DimensionDecorator):
- puts 'EQ' label - puts 'EQ' label
""" """
basename = "IfcAnnotation/Equal" basename = "IfcAnnotation/Equal"
installed = None
def draw_labels(self, obj, vertices, indices): def draw_labels(self, context, obj, vertices, indices):
region = self.context.region region = context.region
region3d = self.context.region_data region3d = context.region_data
for i0, i1 in indices: for i0, i1 in indices:
v0 = Vector(vertices[i0]) v0 = Vector(vertices[i0])
v1 = Vector(vertices[i1]) v1 = Vector(vertices[i1])
@@ -423,7 +394,7 @@ class EqualityDecorator(DimensionDecorator):
dir = p1 - p0 dir = p1 - p0
if dir.length < 1: if dir.length < 1:
continue continue
self.draw_label("EQ", p0 + (dir) * .5, dir) self.draw_label(context, "EQ", p0 + (dir) * .5, dir)
class LeaderDecorator(BaseDecorator): class LeaderDecorator(BaseDecorator):
@@ -432,7 +403,6 @@ class LeaderDecorator(BaseDecorator):
- middle points w/out decorations - middle points w/out decorations
""" """
basename = "IfcAnnotation/Leader" basename = "IfcAnnotation/Leader"
installed = None
DEF_GLSL = BaseDecorator.DEF_GLSL + """ DEF_GLSL = BaseDecorator.DEF_GLSL + """
#define ARROW_ANGLE PI / 12.0 #define ARROW_ANGLE PI / 12.0
@@ -489,9 +459,9 @@ class LeaderDecorator(BaseDecorator):
} }
""" """
def decorate(self, obj): def decorate(self, context, obj):
verts, idxs, topo = self.get_path_geom(obj) verts, idxs, topo = self.get_path_geom(obj)
self.draw_lines(obj, verts, idxs, topo) self.draw_lines(context, obj, verts, idxs, topo)
class StairDecorator(BaseDecorator): class StairDecorator(BaseDecorator):
@@ -501,7 +471,6 @@ class StairDecorator(BaseDecorator):
- middle points w/out decorations - middle points w/out decorations
""" """
basename = "IfcAnnotation/Stair" basename = "IfcAnnotation/Stair"
installed = None
DEF_GLSL = BaseDecorator.DEF_GLSL + """ DEF_GLSL = BaseDecorator.DEF_GLSL + """
#define CIRCLE_SIZE 8.0 #define CIRCLE_SIZE 8.0
@@ -575,14 +544,13 @@ class StairDecorator(BaseDecorator):
} }
""" """
def decorate(self, obj): def decorate(self, context, obj):
verts, idxs, topo = self.get_path_geom(obj) verts, idxs, topo = self.get_path_geom(obj)
self.draw_lines(obj, verts, idxs, topo) self.draw_lines(context, obj, verts, idxs, topo)
class HiddenDecorator(BaseDecorator): class HiddenDecorator(BaseDecorator):
basename = "IfcAnnotation/Hidden" basename = "IfcAnnotation/Hidden"
installed = None
DEF_GLSL = BaseDecorator.DEF_GLSL + """ DEF_GLSL = BaseDecorator.DEF_GLSL + """
#define DASH_SIZE 16.0 #define DASH_SIZE 16.0
@@ -624,6 +592,7 @@ class HiddenDecorator(BaseDecorator):
""" """
FRAG_GLSL = """ FRAG_GLSL = """
uniform vec4 color;
in vec2 gl_FragCoord; in vec2 gl_FragCoord;
in float dist; in float dist;
out vec4 fragColor; out vec4 fragColor;
@@ -631,21 +600,20 @@ class HiddenDecorator(BaseDecorator):
void main() { void main() {
uint bit = uint(fract(dist / DASH_SIZE) * 32); uint bit = uint(fract(dist / DASH_SIZE) * 32);
if ((DASH_PATTERN & (1U<<bit)) == 0U) discard; if ((DASH_PATTERN & (1U<<bit)) == 0U) discard;
fragColor = COLOR; fragColor = color;
} }
""" """
def decorate(self, obj): def decorate(self, context, obj):
if obj.data.is_editmode: if obj.data.is_editmode:
verts, idxs = self.get_editmesh_geom(obj) verts, idxs = self.get_editmesh_geom(obj)
else: else:
verts, idxs = self.get_mesh_geom(obj) verts, idxs = self.get_mesh_geom(obj)
self.draw_lines(obj, verts, idxs) self.draw_lines(context, obj, verts, idxs)
class MiscDecorator(HiddenDecorator): class MiscDecorator(HiddenDecorator):
basename = "IfcAnnotation/Misc" basename = "IfcAnnotation/Misc"
installed = None
FRAG_GLSL = BaseDecorator.FRAG_GLSL FRAG_GLSL = BaseDecorator.FRAG_GLSL
@@ -666,16 +634,15 @@ class LevelDecorator(BaseDecorator):
continue continue
yield [obj.matrix_world @ p.co for p in spline_points] yield [obj.matrix_world @ p.co for p in spline_points]
def decorate(self, obj): def decorate(self, context, obj):
verts, idxs, topo = self.get_path_geom(obj) verts, idxs, topo = self.get_path_geom(obj)
self.draw_lines(obj, verts, idxs, topo) self.draw_lines(context, obj, verts, idxs, topo)
splines = self.get_splines(obj) splines = self.get_splines(obj)
self.draw_labels(obj, splines) self.draw_labels(context, obj, splines)
class PlanDecorator(LevelDecorator): class PlanDecorator(LevelDecorator):
basename = "IfcAnnotation/Plan Level" basename = "IfcAnnotation/Plan Level"
installed = None
DEF_GLSL = BaseDecorator.DEF_GLSL + """ DEF_GLSL = BaseDecorator.DEF_GLSL + """
#define CIRCLE_SIZE 8.0 #define CIRCLE_SIZE 8.0
@@ -741,9 +708,9 @@ class PlanDecorator(LevelDecorator):
} }
""" """
def draw_labels(self, obj, splines): def draw_labels(self, context, obj, splines):
region = self.context.region region = context.region
region3d = self.context.region_data region3d = context.region_data
for verts in splines: for verts in splines:
v0 = verts[0] v0 = verts[0]
v1 = verts[1] v1 = verts[1]
@@ -752,13 +719,12 @@ class PlanDecorator(LevelDecorator):
dir = p1 - p0 dir = p1 - p0
if dir.length < 1: if dir.length < 1:
continue continue
text = "RL " + self.format_value(verts[-1].z) text = "RL " + self.format_value(context, verts[-1].z)
self.draw_label(text, p0, dir, gap=8, center=False) self.draw_label(context, text, p0, dir, gap=8, center=False)
class SectionDecorator(LevelDecorator): class SectionDecorator(LevelDecorator):
basename = "IfcAnnotation/Section Level" basename = "IfcAnnotation/Section Level"
installed = None
DEF_GLSL = BaseDecorator.DEF_GLSL + """ DEF_GLSL = BaseDecorator.DEF_GLSL + """
#define CALLOUT_GAP 8.0 #define CALLOUT_GAP 8.0
@@ -821,9 +787,9 @@ class SectionDecorator(LevelDecorator):
} }
""" """
def draw_labels(self, obj, splines): def draw_labels(self, context, obj, splines):
region = self.context.region region = context.region
region3d = self.context.region_data region3d = context.region_data
for verts in splines: for verts in splines:
v0 = verts[0] v0 = verts[0]
v1 = verts[1] v1 = verts[1]
@@ -832,8 +798,8 @@ class SectionDecorator(LevelDecorator):
dir = p1 - p0 dir = p1 - p0
if dir.length < 1: if dir.length < 1:
continue continue
text = "RL " + self.format_value(verts[-1].z) text = "RL " + self.format_value(context, verts[-1].z)
self.draw_label(text, p0 + dir.normalized() * 16, -dir, gap=16, center=False) self.draw_label(context, text, p0 + dir.normalized() * 16, -dir, gap=16, center=False)
class BreakDecorator(BaseDecorator): class BreakDecorator(BaseDecorator):
@@ -843,7 +809,6 @@ class BreakDecorator(BaseDecorator):
Uses first two vertices in verts list. Uses first two vertices in verts list.
""" """
basename = "IfcAnnotation/Break" basename = "IfcAnnotation/Break"
installed = None
DEF_GLSL = BaseDecorator.DEF_GLSL + """ DEF_GLSL = BaseDecorator.DEF_GLSL + """
#define BREAK_LENGTH 32.0 #define BREAK_LENGTH 32.0
@@ -898,12 +863,12 @@ class BreakDecorator(BaseDecorator):
} }
""" """
def decorate(self, obj): def decorate(self, context, obj):
if obj.data.is_editmode: if obj.data.is_editmode:
verts = self.get_editmesh_geom(obj) verts = self.get_editmesh_geom(obj)
else: else:
verts = self.get_mesh_geom(obj) verts = self.get_mesh_geom(obj)
self.draw_lines(obj, verts, [(0, 1)]) self.draw_lines(context, obj, verts, [(0, 1)])
def get_mesh_geom(self, obj): def get_mesh_geom(self, obj):
# first vertices only # first vertices only
@@ -919,7 +884,6 @@ class BreakDecorator(BaseDecorator):
class GridDecorator(BaseDecorator): class GridDecorator(BaseDecorator):
basename = "IfcGridAxis/" basename = "IfcGridAxis/"
installed = None
DEF_GLSL = BaseDecorator.DEF_GLSL + """ DEF_GLSL = BaseDecorator.DEF_GLSL + """
#define CIRCLE_SIZE 16.0 #define CIRCLE_SIZE 16.0
@@ -988,6 +952,7 @@ class GridDecorator(BaseDecorator):
""" """
FRAG_GLSL = """ FRAG_GLSL = """
uniform vec4 color;
in vec2 gl_FragCoord; in vec2 gl_FragCoord;
in float dist; in float dist;
out vec4 fragColor; out vec4 fragColor;
@@ -995,7 +960,7 @@ class GridDecorator(BaseDecorator):
void main() { void main() {
uint bit = uint(fract(dist / DASH_SIZE) * 32); uint bit = uint(fract(dist / DASH_SIZE) * 32);
if ((DASH_PATTERN & (1U<<bit)) == 0U) discard; if ((DASH_PATTERN & (1U<<bit)) == 0U) discard;
fragColor = COLOR; fragColor = color;
} }
""" """
@@ -1010,36 +975,68 @@ class GridDecorator(BaseDecorator):
vertices = [obj.matrix_world @ v.co for v in mesh.edges[0].verts] vertices = [obj.matrix_world @ v.co for v in mesh.edges[0].verts]
return vertices return vertices
def decorate(self, obj): def decorate(self, context, obj):
if obj.data.is_editmode: if obj.data.is_editmode:
verts = self.get_editmesh_geom(obj) verts = self.get_editmesh_geom(obj)
else: else:
verts = self.get_mesh_geom(obj) verts = self.get_mesh_geom(obj)
self.draw_lines(obj, verts, [(0, 1)]) self.draw_lines(context, obj, verts, [(0, 1)])
self.draw_labels(obj, verts) self.draw_labels(context, obj, verts)
def draw_labels(self, obj, vertices): def draw_labels(self, context, obj, vertices):
region = self.context.region region = context.region
region3d = self.context.region_data region3d = context.region_data
v0 = Vector(vertices[0]) v0 = Vector(vertices[0])
v1 = Vector(vertices[1]) v1 = Vector(vertices[1])
p0 = location_3d_to_region_2d(region, region3d, v0) p0 = location_3d_to_region_2d(region, region3d, v0)
p1 = location_3d_to_region_2d(region, region3d, v1) p1 = location_3d_to_region_2d(region, region3d, v1)
dir = Vector((1, 0)) dir = Vector((1, 0))
text = obj.BIMObjectProperties.attributes['AxisTag'].string_value text = obj.BIMObjectProperties.attributes['AxisTag'].string_value
self.draw_label(text, p0, dir, vcenter=True, gap=0) self.draw_label(context, text, p0, dir, vcenter=True, gap=0)
self.draw_label(text, p1, dir, vcenter=True, gap=0) self.draw_label(context, text, p1, dir, vcenter=True, gap=0)
all_decorators = [ class DecorationsHandler():
DimensionDecorator, decorators_classes = [
EqualityDecorator, DimensionDecorator,
GridDecorator, EqualityDecorator,
HiddenDecorator, GridDecorator,
LeaderDecorator, HiddenDecorator,
MiscDecorator, LeaderDecorator,
PlanDecorator, MiscDecorator,
SectionDecorator, PlanDecorator,
StairDecorator, SectionDecorator,
BreakDecorator StairDecorator,
] BreakDecorator
]
installed = None
@classmethod
def install(cls, context):
if cls.installed:
cls.uninstall()
handler = cls()
cls.installed = SpaceView3D.draw_handler_add(handler, (context,), 'WINDOW', 'POST_PIXEL')
@classmethod
def uninstall(cls):
try:
SpaceView3D.draw_handler_remove(cls.installed, 'WINDOW')
except ValueError:
pass
cls.installed = None
def __init__(self):
self.decorators = [cls() for cls in self.decorators_classes]
def __call__(self, context):
props = context.scene.DocProperties
if props.active_drawing_index is None or len(props.drawings) == 0:
return
drawing = props.drawings[props.active_drawing_index]
collection = bpy.data.collections.get("IfcGroup/" + drawing.name)
for decorator in self.decorators:
for obj in decorator.get_objects(collection):
decorator.decorate(context, obj)
+3 -6
View File
@@ -348,11 +348,9 @@ def refreshTitleblocks(self, context):
def toggleDecorations(self, context): def toggleDecorations(self, context):
toggle = self.should_draw_decorations toggle = self.should_draw_decorations
if toggle: if toggle:
for dec in decoration.all_decorators: decoration.DecorationsHandler.install(context)
dec.install(self, context)
else: else:
for dec in decoration.all_decorators: decoration.DecorationsHandler.uninstall()
dec.uninstall()
def getScenarios(self, context): def getScenarios(self, context):
@@ -657,8 +655,7 @@ class DocProperties(PropertyGroup):
drawing_styles: CollectionProperty(name="Drawing Styles", type=DrawingStyle) drawing_styles: CollectionProperty(name="Drawing Styles", type=DrawingStyle)
should_draw_decorations: BoolProperty(name="Should Draw Decorations", update=toggleDecorations) should_draw_decorations: BoolProperty(name="Should Draw Decorations", update=toggleDecorations)
decorations_colour: FloatVectorProperty(name="Decorations Colour", subtype="COLOR", default=(1, 0, 0, 1), decorations_colour: FloatVectorProperty(name="Decorations Colour", subtype="COLOR", default=(1, 0, 0, 1),
min=0.0, max=1.0, size=4, min=0.0, max=1.0, size=4)
update=toggleDecorations)
class BIMCameraProperties(PropertyGroup): class BIMCameraProperties(PropertyGroup):