''' Copyright (C) 2020 Akaneyu This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ''' import time import bpy import bgl import blf import gpu from gpu_extras.batch import batch_for_shader from mathutils import Matrix import numpy as np default_vertex_shader = ''' uniform mat4 ModelViewProjectionMatrix; in vec2 pos; void main() { gl_Position = ModelViewProjectionMatrix * vec4(pos, 0, 1.0); } ''' default_fragment_shader = ''' uniform vec4 color; out vec4 fragColor; void main() { fragColor = color; } ''' dotted_line_vertex_shader = ''' uniform mat4 ModelViewProjectionMatrix; in vec2 pos; in float arcLength; out float arcLengthInter; void main() { arcLengthInter = arcLength; gl_Position = ModelViewProjectionMatrix * vec4(pos, 0, 1.0); } ''' dotted_line_fragment_shader = ''' uniform float scale; uniform float offset; uniform vec4 color1; uniform vec4 color2; in float arcLengthInter; out vec4 fragColor; void main() { if (step(sin((arcLengthInter + offset) * scale), 0.5) == 1) { fragColor = color1; } else { fragColor = color2; } } ''' class UIRenderer: def __init__(self): self.default_shader = gpu.types.GPUShader(default_vertex_shader, default_fragment_shader) self.default_shader_u_color = self.default_shader.uniform_from_name("color") self.dotted_line_shader = gpu.types.GPUShader(dotted_line_vertex_shader, dotted_line_fragment_shader) self.dotted_line_shader_u_color1 = self.dotted_line_shader.uniform_from_name("color1") self.dotted_line_shader_u_color2 = self.dotted_line_shader.uniform_from_name("color2") def render_border(self, pos1, pos2): bgl.glEnable(bgl.GL_BLEND) bgl.glLineWidth(1.0) batch = batch_for_shader(self.default_shader, 'LINES', {"pos": [pos1, pos2]}) self.default_shader.bind() self.default_shader.uniform_vector_float(self.default_shader_u_color, np.array([1.0, 0.0, 1.0, 1.0], 'f'), 4) batch.draw(self.default_shader) err = bgl.glGetError() if err != bgl.GL_NO_ERROR: print('render_border') print('OpenGL error:', err) def render_arrow(self, center, angle): bgl.glEnable(bgl.GL_BLEND) bgl.glLineWidth(1.0) gpu.matrix.load_identity() with gpu.matrix.push_pop(): gpu.matrix.translate(center) gpu.matrix.multiply_matrix( Matrix.Rotation(angle, 4, 'Z')) verts = [ (0, -50), (100, -50), (0, 50), (100, 50), (100, 0), (200, 0), (100, 100), (100, -100) ] indices = [ (0, 1, 2), (2, 1, 3), (4, 5, 6), (4, 5, 7) ] batch = batch_for_shader(self.default_shader, 'TRIS', {"pos": verts}, indices=indices) self.default_shader.bind() self.default_shader.uniform_vector_float(self.default_shader_u_color, np.array([1.0, 1.0, 1.0, 0.5], 'f'), 4) batch.draw(self.default_shader) err = bgl.glGetError() if err != bgl.GL_NO_ERROR: print('render_arrow') print('OpenGL error:', err) def render_brush_frame(self, pos, radius): bgl.glEnable(bgl.GL_BLEND) bgl.glLineWidth(2.0) verts = self.create_brush_frame_vertices(pos, radius) arc_lengths = [0] for a, b in zip(verts[:-1], verts[1:]): arc_lengths.append(arc_lengths[-1] + np.linalg.norm(a - b)) batch = batch_for_shader(self.dotted_line_shader, 'LINE_STRIP', {"pos": verts, "arcLength": arc_lengths}) self.dotted_line_shader.bind() self.dotted_line_shader.uniform_float("scale", 0.6) self.dotted_line_shader.uniform_float("offset", 0) self.dotted_line_shader.uniform_vector_float(self.dotted_line_shader_u_color1, np.array([1.0, 1.0, 1.0, 0.5], 'f'), 4) self.dotted_line_shader.uniform_vector_float(self.dotted_line_shader_u_color2, np.array([0.0, 0.0, 0.0, 0.5], 'f'), 4) batch.draw(self.dotted_line_shader) err = bgl.glGetError() if err != bgl.GL_NO_ERROR: print('render_brush_frame') print('OpenGL error:', err) def create_brush_frame_vertices(self, pos, radius): segs = 32 theta = 2.0 * np.pi / segs c = np.cos(theta) s = np.sin(theta) x = radius y = 0 verts = [] for i in range(segs): verts.append((x + pos[0], y + pos[1])) t = x x = c * x - s * y y = s * t + c * y verts.append(verts[0]) return np.array(verts, 'f')