Last active
September 29, 2019 20:36
-
-
Save tin2tin/ad23f414a97d67748cac0aca3798d833 to your computer and use it in GitHub Desktop.
Draws keyframes in Graph Editor for ex. editing volume levels on VSE strips(only poc).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Start Draw Volume Keyframes operator from the Graph Editor using F3 | |
import bpy | |
import bgl | |
import blf | |
import gpu | |
from gpu_extras.batch import batch_for_shader | |
def draw_callback_px(self, context): | |
#print("mouse points", len(self.mouse_path)) | |
font_id = 0 # XXX, need to find out how best to get this. | |
# draw some text | |
#blf.position(font_id, 15, 30, 0) | |
#blf.size(font_id, 20, 72) | |
#blf.draw(font_id, "Hello Word " + str((self.mouse_path[0]))) | |
shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR') | |
bgl.glEnable(bgl.GL_BLEND) | |
bgl.glLineWidth(2) | |
batch = batch_for_shader(shader, 'LINE_STRIP', {"pos": self.mouse_path}) | |
shader.bind() | |
shader.uniform_float("color", (1.0, 1.0, 1.0, 0.1)) | |
batch.draw(shader) | |
# restore opengl defaults | |
bgl.glLineWidth(1) | |
bgl.glDisable(bgl.GL_BLEND) | |
#influence | |
class ModalDrawOperator(bpy.types.Operator): | |
"""Draw a line with the mouse""" | |
bl_idname = "graph.modal_operator" | |
bl_label = "Draw Volume Keyframes" | |
def modal(self, context, event): | |
context.area.tag_redraw() | |
if event.type == 'MOUSEMOVE': | |
region = context.region | |
x = event.mouse_region_x# - offset_x | |
y = event.mouse_region_y# - offset_y | |
x, y = region.view2d.region_to_view(x, y) | |
#bpy.context.scene.sequence_editor.sequences_all["test.mp3"].volume = y | |
context.scene.frame_current = x | |
if event.value == 'PRESS': | |
#bpy.ops.graph.select_all(action='SELECT') | |
#elif event.value == 'PRESS': | |
self.mouse_path.append((event.mouse_region_x, event.mouse_region_y)) | |
# Mouse position | |
width = context.region.width | |
height = context.region.height | |
rv1 = context.region.view2d.region_to_view(0, 0) | |
rv2 = context.region.view2d.region_to_view(width, height) | |
region = context.region | |
x = event.mouse_region_x# - offset_x | |
y = event.mouse_region_y# - offset_y | |
x, y = region.view2d.region_to_view(x, y) | |
sequence = context.scene.sequence_editor | |
scene = context.scene | |
strip = sequence.active_strip | |
bpy.context.scene.sequence_editor.sequences_all[strip.name].volume = y | |
context.scene.frame_current = x | |
bpy.ops.graph.keyframe_insert(type='SEL') | |
# bpy.ops.graph.select_all(action='DESELECT') | |
# bpy.ops.graph.select_column(mode='CFRA') | |
# bpy.ops.graph.select_more() | |
# #bpy.ops.graph.select_more() | |
# #bpy.ops.graph.select_more() | |
# bpy.ops.graph.smooth() #uncomment this for fun! | |
# bpy.ops.graph.select_all(action='SELECT') | |
elif event.value == 'CLICK_DRAG': | |
self.mouse_path.append((event.mouse_region_x, event.mouse_region_y)) | |
elif event.type == 'RELEASE': | |
bpy.types.SpaceGraphEditor.draw_handler_remove(self._handle, 'WINDOW') | |
return {'FINISHED'} | |
elif event.type in {'RIGHTMOUSE', 'ESC'}: | |
bpy.types.SpaceGraphEditor.draw_handler_remove(self._handle, 'WINDOW') | |
return {'CANCELLED'} | |
return {'RUNNING_MODAL'} | |
def invoke(self, context, event): | |
# We must create a scene action first if there's none | |
scene = context.scene | |
if not scene.animation_data: | |
scene.animation_data_create() | |
if not scene.animation_data.action: | |
action = bpy.data.actions.new(scene.name + "Action") | |
scene.animation_data.action = action | |
sequence = context.scene.sequence_editor | |
scene = context.scene | |
strip = sequence.active_strip | |
#tmp_current_frame = context.scene.frame_current | |
animated_property = "volume" if hasattr(strip, "volume") else "blend_alpha" | |
fade_fcurve = fade_find_or_create_fcurve(context, strip, animated_property) | |
if context.area.type == 'GRAPH_EDITOR': | |
# the arguments we pass the the callback | |
args = (self, context) | |
# Add the region OpenGL drawing callback | |
# draw in view space with 'POST_VIEW' and 'PRE_VIEW' | |
self._handle = bpy.types.SpaceGraphEditor.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_PIXEL') | |
self.mouse_path = [] | |
context.window_manager.modal_handler_add(self) | |
return {'RUNNING_MODAL'} | |
else: | |
self.report({'WARNING'}, "GRAPH_EDITOR not found, cannot run operator") | |
return {'CANCELLED'} | |
def fade_find_or_create_fcurve(context, sequence, animated_property): | |
""" | |
Iterates over all the fcurves until it finds an fcurve with a data path | |
that corresponds to the sequence. | |
Returns the matching FCurve or creates a new one if the function can't find a match. | |
""" | |
fade_fcurve = None | |
fcurves = context.scene.animation_data.action.fcurves | |
searched_data_path = sequence.path_from_id(animated_property) | |
for fcurve in fcurves: | |
if fcurve.data_path == searched_data_path: | |
fade_fcurve = fcurve | |
break | |
if not fade_fcurve: | |
fade_fcurve = fcurves.new(data_path=searched_data_path) | |
keyframe_points = fade_fcurve.keyframe_points | |
keyframe_points.insert(frame=0, value=1, options={"FAST"}) | |
fade_fcurve.update() | |
# The graph editor and the audio waveforms only redraw upon "moving" a keyframe | |
keyframe_points[-1].co = keyframe_points[-1].co | |
return fade_fcurve | |
def register(): | |
bpy.utils.register_class(ModalDrawOperator) | |
def unregister(): | |
bpy.utils.unregister_class(ModalDrawOperator) | |
if __name__ == "__main__": | |
register() | |
#unregister |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment