mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Viewport annotation decorations now scale based on paper size. See #1153.
This commit is contained in:
@@ -16,22 +16,22 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Viewport decorations"""
|
||||
import os
|
||||
import gpu
|
||||
import bpy
|
||||
import blf
|
||||
import bgl
|
||||
import math
|
||||
import bmesh
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.bim.module.drawing.helper as helper
|
||||
from functools import reduce
|
||||
from itertools import chain
|
||||
|
||||
from bpy.types import SpaceView3D
|
||||
from mathutils import Vector, Matrix
|
||||
import bpy
|
||||
import bmesh
|
||||
import blf
|
||||
from bpy_extras.view3d_utils import location_3d_to_region_2d
|
||||
import gpu
|
||||
import bgl
|
||||
from gpu.types import GPUShader, GPUBatch, GPUIndexBuf, GPUVertBuf, GPUVertFormat
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
import blenderbim.bim.module.drawing.helper as helper
|
||||
|
||||
|
||||
class BaseDecorator:
|
||||
@@ -40,8 +40,8 @@ class BaseDecorator:
|
||||
|
||||
DEF_GLSL = """
|
||||
#define PI 3.141592653589793
|
||||
#define MAX_POINTS 64
|
||||
#define CIRCLE_SEGS 24
|
||||
#define MAX_POINTS 32
|
||||
#define CIRCLE_SEGS 12
|
||||
"""
|
||||
|
||||
LIB_GLSL = """
|
||||
@@ -90,6 +90,7 @@ class BaseDecorator:
|
||||
|
||||
GEOM_GLSL = """
|
||||
uniform vec2 winsize;
|
||||
uniform float viewportDrawingScale;
|
||||
|
||||
layout(lines) in;
|
||||
layout(line_strip, max_vertices=2) out;
|
||||
@@ -134,6 +135,34 @@ class BaseDecorator:
|
||||
defines=self.DEF_GLSL,
|
||||
)
|
||||
|
||||
# Horrific prototype code to ensure bgl draws at drawing scales
|
||||
# https://blender.stackexchange.com/questions/16493/is-there-a-way-to-fit-the-viewport-to-the-current-field-of-view
|
||||
def is_landscape(render):
|
||||
return render.resolution_x > render.resolution_y
|
||||
|
||||
def get_scale(camera):
|
||||
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("/")
|
||||
return float(numerator) / float(denominator)
|
||||
|
||||
camera = bpy.context.scene.camera
|
||||
render = bpy.context.scene.render
|
||||
if is_landscape(render):
|
||||
camera_width_model = camera.data.ortho_scale
|
||||
else:
|
||||
camera_width_model = camera.data.ortho_scale / render.resolution_y * render.resolution_x
|
||||
self.camera_width_mm = get_scale(camera) * camera_width_model
|
||||
|
||||
self.font_id = blf.load(
|
||||
os.path.join(bpy.context.scene.BIMProperties.data_dir, "fonts", "OpenGost Type B TT.ttf")
|
||||
)
|
||||
|
||||
def camera_zoom_to_factor(self, zoom):
|
||||
return math.pow(((zoom / 50) + math.sqrt(2)) / 2, 2)
|
||||
|
||||
def get_objects(self, collection):
|
||||
"""find relevant objects
|
||||
using class.objecttype
|
||||
@@ -248,6 +277,15 @@ class BaseDecorator:
|
||||
self.shader.uniform_float("winsize", (region.width, region.height))
|
||||
self.shader.uniform_float("color", color)
|
||||
|
||||
# Horrific prototype code
|
||||
factor = self.camera_zoom_to_factor(context.space_data.region_3d.view_camera_zoom)
|
||||
camera_width_px = factor * context.region.width
|
||||
mm_to_px = camera_width_px / self.camera_width_mm
|
||||
# 0.00025 is a magic constant number I visually discovered to get the right number.
|
||||
# It probably should be dynamically calculated using system.dpi or something.
|
||||
viewport_drawing_scale = 0.00025 * mm_to_px
|
||||
self.shader.uniform_float("viewportDrawingScale", viewport_drawing_scale)
|
||||
|
||||
batch.draw(self.shader)
|
||||
|
||||
def draw_label(self, context, text, pos, dir, gap=4, center=True, vcenter=False):
|
||||
@@ -258,8 +296,9 @@ class BaseDecorator:
|
||||
|
||||
aligned and centered at segment middle
|
||||
"""
|
||||
font_id = 0
|
||||
font_size = 16
|
||||
# 0 is the default font, but we're fancier than that
|
||||
font_id = self.font_id
|
||||
|
||||
dpi = context.preferences.system.dpi
|
||||
|
||||
color = context.scene.DocProperties.decorations_colour
|
||||
@@ -268,6 +307,16 @@ class BaseDecorator:
|
||||
cos = math.cos(ang)
|
||||
sin = math.sin(ang)
|
||||
|
||||
# Horrific prototype code
|
||||
factor = self.camera_zoom_to_factor(context.space_data.region_3d.view_camera_zoom)
|
||||
camera_width_px = factor * context.region.width
|
||||
mm_to_px = camera_width_px / self.camera_width_mm
|
||||
# 0.004118616 is a magic constant number I visually discovered to get the right number.
|
||||
# In particular it works only for the OpenGOST font and produces a 2.5mm font size.
|
||||
# It probably should be dynamically calculated using system.dpi or something.
|
||||
# font_size = 16 <-- this is a good default
|
||||
font_size = int(0.004118616 * mm_to_px)
|
||||
|
||||
blf.size(font_id, font_size, dpi)
|
||||
|
||||
w, h = 0, 0
|
||||
@@ -330,6 +379,7 @@ class DimensionDecorator(BaseDecorator):
|
||||
|
||||
GEOM_GLSL = """
|
||||
uniform vec2 winsize;
|
||||
uniform float viewportDrawingScale;
|
||||
|
||||
layout(lines) in;
|
||||
layout(line_strip, max_vertices=MAX_POINTS) out;
|
||||
@@ -346,7 +396,7 @@ class DimensionDecorator(BaseDecorator):
|
||||
vec4 p;
|
||||
|
||||
vec4 head[3];
|
||||
arrow_head(dir, ARROW_SIZE, ARROW_ANGLE, head);
|
||||
arrow_head(dir, viewportDrawingScale * ARROW_SIZE, ARROW_ANGLE, head);
|
||||
|
||||
// start edge arrow
|
||||
gl_Position = p0;
|
||||
@@ -446,6 +496,7 @@ class LeaderDecorator(BaseDecorator):
|
||||
|
||||
GEOM_GLSL = """
|
||||
uniform vec2 winsize;
|
||||
uniform float viewportDrawingScale;
|
||||
|
||||
layout(lines) in;
|
||||
layout(line_strip, max_vertices=MAX_POINTS) out;
|
||||
@@ -467,7 +518,7 @@ class LeaderDecorator(BaseDecorator):
|
||||
// end edge arrow for last segment
|
||||
if (t1 == 2u) {
|
||||
vec4 head[3];
|
||||
arrow_head(dir, ARROW_SIZE, ARROW_ANGLE, head);
|
||||
arrow_head(dir, viewportDrawingScale * ARROW_SIZE, ARROW_ANGLE, head);
|
||||
|
||||
gl_Position = p1;
|
||||
EmitVertex();
|
||||
@@ -481,7 +532,7 @@ class LeaderDecorator(BaseDecorator):
|
||||
EmitVertex();
|
||||
EndPrimitive();
|
||||
|
||||
gap1 = dir * ARROW_SIZE;
|
||||
gap1 = dir * viewportDrawingScale * ARROW_SIZE;
|
||||
}
|
||||
|
||||
// stem, adjusted for and arrow
|
||||
@@ -494,9 +545,24 @@ class LeaderDecorator(BaseDecorator):
|
||||
}
|
||||
"""
|
||||
|
||||
def get_spline_end(self, obj):
|
||||
spline = obj.data.splines[0]
|
||||
spline_points = spline.bezier_points if spline.bezier_points else spline.points
|
||||
if not spline_points:
|
||||
return Vector((0, 0, 0))
|
||||
return obj.matrix_world @ spline_points[0].co
|
||||
|
||||
def decorate(self, context, obj):
|
||||
verts, idxs, topo = self.get_path_geom(obj)
|
||||
self.draw_lines(context, obj, verts, idxs, topo)
|
||||
self.draw_labels(context, obj)
|
||||
|
||||
def draw_labels(self, context, obj):
|
||||
region = context.region
|
||||
region3d = context.region_data
|
||||
dir = Vector((1, 0))
|
||||
pos = location_3d_to_region_2d(region, region3d, self.get_spline_end(obj))
|
||||
self.draw_label(context, obj.BIMTextProperties.value, pos, dir, gap=0, center=False, vcenter=False)
|
||||
|
||||
|
||||
class StairDecorator(BaseDecorator):
|
||||
@@ -519,6 +585,7 @@ class StairDecorator(BaseDecorator):
|
||||
|
||||
GEOM_GLSL = """
|
||||
uniform vec2 winsize;
|
||||
uniform float viewportDrawingScale;
|
||||
|
||||
layout(lines) in;
|
||||
layout(line_strip, max_vertices=MAX_POINTS) out;
|
||||
@@ -601,6 +668,7 @@ class HiddenDecorator(BaseDecorator):
|
||||
|
||||
GEOM_GLSL = """
|
||||
uniform vec2 winsize;
|
||||
uniform float viewportDrawingScale;
|
||||
|
||||
layout(lines) in;
|
||||
layout(line_strip, max_vertices=MAX_POINTS) out;
|
||||
@@ -695,6 +763,7 @@ class PlanLevelDecorator(LevelDecorator):
|
||||
|
||||
GEOM_GLSL = """
|
||||
uniform vec2 winsize;
|
||||
uniform float viewportDrawingScale;
|
||||
|
||||
layout(lines) in;
|
||||
layout(line_strip, max_vertices=MAX_POINTS) out;
|
||||
@@ -780,6 +849,7 @@ class SectionLevelDecorator(LevelDecorator):
|
||||
|
||||
GEOM_GLSL = """
|
||||
uniform vec2 winsize;
|
||||
uniform float viewportDrawingScale;
|
||||
|
||||
layout(lines) in;
|
||||
layout(line_strip, max_vertices=MAX_POINTS) out;
|
||||
@@ -868,6 +938,7 @@ class BreakDecorator(BaseDecorator):
|
||||
|
||||
GEOM_GLSL = """
|
||||
uniform vec2 winsize;
|
||||
uniform float viewportDrawingScale;
|
||||
|
||||
layout(lines) in;
|
||||
layout(line_strip, max_vertices=MAX_POINTS) out;
|
||||
@@ -947,6 +1018,7 @@ class GridDecorator(BaseDecorator):
|
||||
|
||||
GEOM_GLSL = """
|
||||
uniform vec2 winsize;
|
||||
uniform float viewportDrawingScale;
|
||||
|
||||
layout(lines) in;
|
||||
layout(line_strip, max_vertices=MAX_POINTS) out;
|
||||
@@ -961,12 +1033,12 @@ class GridDecorator(BaseDecorator):
|
||||
|
||||
vec4 p0w = CLIP2WIN(p0), p1w = CLIP2WIN(p1);
|
||||
vec4 edge = p1w - p0w, dir = normalize(edge);
|
||||
vec4 gap = dir * CIRCLE_SIZE;
|
||||
vec4 gap = dir * CIRCLE_SIZE * viewportDrawingScale;
|
||||
|
||||
vec4 p;
|
||||
|
||||
vec4 head[CIRCLE_SEGS];
|
||||
circle_head(CIRCLE_SIZE, head);
|
||||
circle_head(CIRCLE_SIZE * viewportDrawingScale, head);
|
||||
|
||||
dist = 0;
|
||||
|
||||
@@ -1064,6 +1136,7 @@ class SectionViewDecorator(LevelDecorator):
|
||||
|
||||
GEOM_GLSL = """
|
||||
uniform vec2 winsize;
|
||||
uniform float viewportDrawingScale;
|
||||
|
||||
layout(lines) in;
|
||||
layout(line_strip, max_vertices=MAX_POINTS) out;
|
||||
|
||||
@@ -284,7 +284,7 @@ class DocProperties(PropertyGroup):
|
||||
drawing_styles: CollectionProperty(name="Drawing Styles", type=DrawingStyle)
|
||||
should_draw_decorations: BoolProperty(name="Should Draw Decorations", update=toggleDecorations)
|
||||
decorations_colour: FloatVectorProperty(
|
||||
name="Decorations Colour", subtype="COLOR", default=(1, 0, 0, 1), min=0.0, max=1.0, size=4
|
||||
name="Decorations Colour", subtype="COLOR", default=(1, 0.5, 0, 1), min=0.0, max=1.0, size=4
|
||||
)
|
||||
|
||||
@property
|
||||
|
||||
@@ -289,41 +289,42 @@ class BIM_PT_annotation_utilities(Panel):
|
||||
|
||||
row = layout.row(align=True)
|
||||
op = row.operator("bim.add_annotation", text="Dim", icon="ARROW_LEFTRIGHT")
|
||||
op.obj_name = "Dimension"
|
||||
op.object_type = "DIMENSION"
|
||||
op.data_type = "curve"
|
||||
op = row.operator("bim.add_annotation", text="Dim (Eq)", icon="ARROW_LEFTRIGHT")
|
||||
op.obj_name = "Equal"
|
||||
op.object_type = "EQUAL_DIMENSION"
|
||||
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.object_type = "TEXT"
|
||||
op.data_type = "empty"
|
||||
op = row.operator("bim.add_annotation", text="Leader", icon="TRACKING_BACKWARDS")
|
||||
op.obj_name = "Leader"
|
||||
op.object_type = "TEXT_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.object_type = "STAIR_ARROW"
|
||||
op.data_type = "curve"
|
||||
op = row.operator("bim.add_annotation", text="Hidden", icon="CON_TRACKTO")
|
||||
op.obj_name = "Hidden"
|
||||
op.object_type = "HIDDEN_LINE"
|
||||
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.object_type = "PLAN_LEVEL"
|
||||
op.data_type = "curve"
|
||||
op = row.operator("bim.add_annotation", text="Level (Section)", icon="TRIA_DOWN")
|
||||
op.obj_name = "Section Level"
|
||||
op.object_type = "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.object_type = "BREAKLINE"
|
||||
op.data_type = "mesh"
|
||||
op = row.operator("bim.add_annotation", text="Misc", icon="MESH_MONKEY")
|
||||
op.obj_name = "Misc"
|
||||
op.object_type = "MISC"
|
||||
op.data_type = "mesh"
|
||||
|
||||
props = context.scene.DocProperties
|
||||
|
||||
Reference in New Issue
Block a user