Attract: draw using the GPU module
The drawing is rather primitive, but it works.
This commit is contained in:
parent
57aadc1817
commit
62c1c966f6
@ -18,9 +18,12 @@
|
|||||||
|
|
||||||
# <pep8 compliant>
|
# <pep8 compliant>
|
||||||
|
|
||||||
import bpy
|
|
||||||
import logging
|
import logging
|
||||||
import collections
|
import typing
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import bgl
|
||||||
|
import gpu
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -34,10 +37,74 @@ strip_status_colour = {
|
|||||||
'todo': (1.0, 0.5019607843137255, 0.5019607843137255)
|
'todo': (1.0, 0.5019607843137255, 0.5019607843137255)
|
||||||
}
|
}
|
||||||
|
|
||||||
CONFLICT_COLOUR = (0.576, 0.118, 0.035) # RGB tuple
|
CONFLICT_COLOUR = (0.576, 0.118, 0.035, 1.0) # RGBA tuple
|
||||||
|
|
||||||
|
gpu_vertex_shader = '''
|
||||||
|
uniform mat4 ModelViewProjectionMatrix;
|
||||||
|
|
||||||
|
layout (location = 0) in vec2 pos;
|
||||||
|
layout (location = 1) in vec4 color;
|
||||||
|
|
||||||
|
out vec4 lineColor; // output to the fragment shader
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = ModelViewProjectionMatrix * vec4(pos.x, pos.y, 0.0, 1.0);
|
||||||
|
lineColor = color;
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
gpu_fragment_shader = '''
|
||||||
|
out vec4 fragColor;
|
||||||
|
in vec4 lineColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
fragColor = lineColor;
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
Float2 = typing.Tuple[float, float]
|
||||||
|
Float3 = typing.Tuple[float, float, float]
|
||||||
|
Float4 = typing.Tuple[float, float, float, float]
|
||||||
|
|
||||||
|
|
||||||
def get_strip_rectf(strip):
|
class AttractLineDrawer:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._format = gpu.types.GPUVertFormat()
|
||||||
|
self._pos_id = self._format.attr_add(
|
||||||
|
id="pos",
|
||||||
|
comp_type="F32",
|
||||||
|
len=2,
|
||||||
|
fetch_mode="FLOAT")
|
||||||
|
self._color_id = self._format.attr_add(
|
||||||
|
id="color",
|
||||||
|
comp_type="F32",
|
||||||
|
len=4,
|
||||||
|
fetch_mode="FLOAT")
|
||||||
|
|
||||||
|
self.shader = gpu.types.GPUShader(gpu_vertex_shader, gpu_fragment_shader)
|
||||||
|
|
||||||
|
def draw(self,
|
||||||
|
coords: typing.List[Float2],
|
||||||
|
colors: typing.List[Float4]):
|
||||||
|
if not coords:
|
||||||
|
return
|
||||||
|
|
||||||
|
bgl.glEnable(bgl.GL_BLEND)
|
||||||
|
bgl.glLineWidth(2.0)
|
||||||
|
|
||||||
|
vbo = gpu.types.GPUVertBuf(len=len(coords), format=self._format)
|
||||||
|
vbo.attr_fill(id=self._pos_id, data=coords)
|
||||||
|
vbo.attr_fill(id=self._color_id, data=colors)
|
||||||
|
|
||||||
|
batch = gpu.types.GPUBatch(type="LINES", buf=vbo)
|
||||||
|
batch.program_set(self.shader)
|
||||||
|
batch.draw()
|
||||||
|
|
||||||
|
|
||||||
|
def get_strip_rectf(strip) -> Float4:
|
||||||
# Get x and y in terms of the grid's frames and channels
|
# Get x and y in terms of the grid's frames and channels
|
||||||
x1 = strip.frame_final_start
|
x1 = strip.frame_final_start
|
||||||
x2 = strip.frame_final_end
|
x2 = strip.frame_final_end
|
||||||
@ -47,59 +114,56 @@ def get_strip_rectf(strip):
|
|||||||
return x1, y1, x2, y2
|
return x1, y1, x2, y2
|
||||||
|
|
||||||
|
|
||||||
def draw_underline_in_strip(strip_coords, pixel_size_x, color):
|
def underline_in_strip(strip_coords: Float4,
|
||||||
from bgl import glColor4f, glRectf, glEnable, glDisable, GL_BLEND
|
pixel_size_x: float,
|
||||||
import bgl
|
color: Float4,
|
||||||
|
out_coords: typing.List[Float2],
|
||||||
context = bpy.context
|
out_colors: typing.List[Float4]):
|
||||||
|
|
||||||
# Strip coords
|
# Strip coords
|
||||||
s_x1, s_y1, s_x2, s_y2 = strip_coords
|
s_x1, s_y1, s_x2, s_y2 = strip_coords
|
||||||
|
|
||||||
# be careful not to draw over the current frame line
|
# be careful not to draw over the current frame line
|
||||||
cf_x = context.scene.frame_current_final
|
cf_x = bpy.context.scene.frame_current_final
|
||||||
|
|
||||||
bgl.glPushAttrib(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_LINE_BIT)
|
# TODO(Sybren): figure out how to pass one colour per line,
|
||||||
|
# instead of one colour per vertex.
|
||||||
|
out_coords.append((s_x1, s_y1))
|
||||||
|
out_colors.append(color)
|
||||||
|
|
||||||
glColor4f(*color)
|
|
||||||
glEnable(GL_BLEND)
|
|
||||||
bgl.glLineWidth(2)
|
|
||||||
bgl.glBegin(bgl.GL_LINES)
|
|
||||||
|
|
||||||
bgl.glVertex2f(s_x1, s_y1)
|
|
||||||
if s_x1 < cf_x < s_x2:
|
if s_x1 < cf_x < s_x2:
|
||||||
# Bad luck, the line passes our strip
|
# Bad luck, the line passes our strip, so draw two lines.
|
||||||
bgl.glVertex2f(cf_x - pixel_size_x, s_y1)
|
out_coords.append((cf_x - pixel_size_x, s_y1))
|
||||||
bgl.glVertex2f(cf_x + pixel_size_x, s_y1)
|
out_colors.append(color)
|
||||||
bgl.glVertex2f(s_x2, s_y1)
|
|
||||||
|
|
||||||
bgl.glEnd()
|
out_coords.append((cf_x + pixel_size_x, s_y1))
|
||||||
bgl.glPopAttrib()
|
out_colors.append(color)
|
||||||
|
|
||||||
|
out_coords.append((s_x2, s_y1))
|
||||||
|
out_colors.append(color)
|
||||||
|
|
||||||
|
|
||||||
def draw_strip_conflict(strip_coords, pixel_size_x):
|
def strip_conflict(strip_coords: Float4,
|
||||||
|
out_coords: typing.List[Float2],
|
||||||
|
out_colors: typing.List[Float4]):
|
||||||
"""Draws conflicting states between strips."""
|
"""Draws conflicting states between strips."""
|
||||||
|
|
||||||
import bgl
|
|
||||||
|
|
||||||
s_x1, s_y1, s_x2, s_y2 = strip_coords
|
s_x1, s_y1, s_x2, s_y2 = strip_coords
|
||||||
bgl.glPushAttrib(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_LINE_BIT)
|
|
||||||
|
|
||||||
# Always draw the full rectangle, the conflict should be resolved and thus stand out.
|
# TODO(Sybren): draw a rectangle instead of a line.
|
||||||
bgl.glColor3f(*CONFLICT_COLOUR)
|
out_coords.append((s_x1, s_y2))
|
||||||
bgl.glLineWidth(2)
|
out_colors.append(CONFLICT_COLOUR)
|
||||||
|
|
||||||
bgl.glBegin(bgl.GL_LINE_LOOP)
|
out_coords.append((s_x2, s_y1))
|
||||||
bgl.glVertex2f(s_x1, s_y1)
|
out_colors.append(CONFLICT_COLOUR)
|
||||||
bgl.glVertex2f(s_x2, s_y1)
|
|
||||||
bgl.glVertex2f(s_x2, s_y2)
|
|
||||||
bgl.glVertex2f(s_x1, s_y2)
|
|
||||||
bgl.glEnd()
|
|
||||||
|
|
||||||
bgl.glPopAttrib()
|
out_coords.append((s_x2, s_y2))
|
||||||
|
out_colors.append(CONFLICT_COLOUR)
|
||||||
|
|
||||||
|
out_coords.append((s_x1, s_y1))
|
||||||
|
out_colors.append(CONFLICT_COLOUR)
|
||||||
|
|
||||||
|
|
||||||
def draw_callback_px():
|
def draw_callback_px(line_drawer: AttractLineDrawer):
|
||||||
context = bpy.context
|
context = bpy.context
|
||||||
|
|
||||||
if not context.scene.sequence_editor:
|
if not context.scene.sequence_editor:
|
||||||
@ -115,6 +179,10 @@ def draw_callback_px():
|
|||||||
|
|
||||||
strips = shown_strips(context)
|
strips = shown_strips(context)
|
||||||
|
|
||||||
|
coords: typing.List[Float2] = []
|
||||||
|
colors: typing.List[Float4] = []
|
||||||
|
|
||||||
|
# Collect all the lines (vertex coords + vertex colours) to draw.
|
||||||
for strip in strips:
|
for strip in strips:
|
||||||
if not strip.atc_object_id:
|
if not strip.atc_object_id:
|
||||||
continue
|
continue
|
||||||
@ -136,9 +204,11 @@ def draw_callback_px():
|
|||||||
|
|
||||||
alpha = 1.0 if strip.atc_is_synced else 0.5
|
alpha = 1.0 if strip.atc_is_synced else 0.5
|
||||||
|
|
||||||
draw_underline_in_strip(strip_coords, pixel_size_x, color + (alpha,))
|
underline_in_strip(strip_coords, pixel_size_x, color + (alpha,), coords, colors)
|
||||||
if strip.atc_is_synced and strip.atc_object_id_conflict:
|
if strip.atc_is_synced and strip.atc_object_id_conflict:
|
||||||
draw_strip_conflict(strip_coords, pixel_size_x)
|
strip_conflict(strip_coords, coords, colors)
|
||||||
|
|
||||||
|
line_drawer.draw(coords, colors)
|
||||||
|
|
||||||
|
|
||||||
def tag_redraw_all_sequencer_editors():
|
def tag_redraw_all_sequencer_editors():
|
||||||
@ -162,8 +232,9 @@ def callback_enable():
|
|||||||
if cb_handle:
|
if cb_handle:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
line_drawer = AttractLineDrawer()
|
||||||
cb_handle[:] = bpy.types.SpaceSequenceEditor.draw_handler_add(
|
cb_handle[:] = bpy.types.SpaceSequenceEditor.draw_handler_add(
|
||||||
draw_callback_px, (), 'WINDOW', 'POST_VIEW'),
|
draw_callback_px, (line_drawer,), 'WINDOW', 'POST_VIEW'),
|
||||||
|
|
||||||
tag_redraw_all_sequencer_editors()
|
tag_redraw_all_sequencer_editors()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user