render_ui_animation_render.py 6.60 KiB
# SPDX-License-Identifier: GPL-2.0-or-later
import bpy
bl_info = {
"name": "UI Animation Render",
"author": "Luca Rood",
"description": "Render animations of the Blender UI.",
"blender": (2, 80, 0),
"version": (0, 1, 0),
"location": "View3D > Sidebar > View Tab and Ctrl+Shift+F12",
"warning": "",
"category": "Render"
}
km = None
def draw_ui(prefs, layout):
layout.prop(prefs, "delay")
col = layout.column(align=True)
col.label(text="Animation Highlight:")
row = col.row()
row.prop(prefs, "anim_highlight", expand=True)
if prefs.anim_highlight == "replace":
split = col.split(factor=0.2)
split.label(text="Color")
row = split.row(align=True)
row.prop(prefs, "highlight_color", text="")
row.prop(prefs, "highlight_blend", text="Blend")
class UIAnimationRenderPreferences(bpy.types.AddonPreferences):
bl_idname = __name__
delay: bpy.props.FloatProperty(
name="Capture Delay",
description="How much time to wait (seconds) before capturing each frame, to allow the viewport to clean up",
default=0.5
)
anim_highlight: bpy.props.EnumProperty(
name="Animation Highlight",
description="What to do with the animated field highlight color",
items=[("keep", "Keep", "Keep the animated field highlight", 0),
("hide", "Hide", "Hide the animated field highlight", 1),
("replace", "Replace", "Replace the animated field highlight", 2)],
default="keep"
)
highlight_color: bpy.props.FloatVectorProperty(
name="Highlight Color",
description="Color to use for animated field highlights",
subtype='COLOR',
default=(1.0, 1.0, 1.0)
)
highlight_blend: bpy.props.FloatProperty(
name="Highlight Blend",
description="How much the highlight color influences the field color",
default=0.5
)
def draw(self, context):
draw_ui(self, self.layout)
class RenderScreen(bpy.types.Operator):
bl_idname = "render.render_screen"
bl_label = "Render Screen"
bl_description = "Capture the screen for each animation frame and write to the render output path"
_timer = None
_f_initial = 1
_theme_blend = 0.0
_theme_key = (0, 0, 0)
_theme_key_sel = (0, 0, 0)
_theme_anim = (0, 0, 0)
_theme_anim_sel = (0, 0, 0)
_theme_driven = (0, 0, 0)
_theme_driven_sel = (0, 0, 0)
def modal(self, context, event):
if event.type in {'RIGHTMOUSE', 'ESC'}:
self.stop(context)
return {'CANCELLED'}
if event.type == 'TIMER':
scene = context.scene
f_curr = scene.frame_current
bpy.ops.screen.screenshot(filepath=context.scene.render.frame_path(frame=f_curr))
if f_curr < scene.frame_end:
scene.frame_set(f_curr + 1)
else:
self.stop(context)
return {'FINISHED'}
return {'RUNNING_MODAL'}
def execute(self, context):
# Adjust animation highlight (theme)
prefs = context.preferences
addon_prefs = prefs.addons[__name__].preferences
theme = prefs.themes[0].user_interface.wcol_state
if addon_prefs.anim_highlight == "hide":
self._theme_blend = theme.blend
theme.blend = 0.0
elif addon_prefs.anim_highlight == "replace":
self._theme_blend = theme.blend
self._theme_key = theme.inner_key.copy()
self._theme_key_sel = theme.inner_key_sel.copy()
self._theme_anim = theme.inner_anim.copy()
self._theme_anim_sel = theme.inner_anim_sel.copy()
self._theme_driven = theme.inner_driven.copy()
self._theme_driven_sel = theme.inner_driven_sel.copy()
theme.blend = addon_prefs.highlight_blend
theme.inner_key = addon_prefs.highlight_color
theme.inner_key_sel = addon_prefs.highlight_color
theme.inner_anim = addon_prefs.highlight_color
theme.inner_anim_sel = addon_prefs.highlight_color
theme.inner_driven = addon_prefs.highlight_color
theme.inner_driven_sel = addon_prefs.highlight_color
# Set frame
scene = context.scene
self._f_initial = scene.frame_current
scene.frame_set(scene.frame_start)
# Start timer
wm = context.window_manager
self._timer = wm.event_timer_add(addon_prefs.delay, window=context.window)
wm.modal_handler_add(self)
return {'RUNNING_MODAL'}
def stop(self, context):
# Stop timer
wm = context.window_manager
wm.event_timer_remove(self._timer)
# Reset frame
context.scene.frame_set(self._f_initial)
# Reset theme
prefs = context.preferences
addon_prefs = prefs.addons[__name__].preferences
theme = prefs.themes[0].user_interface.wcol_state
if addon_prefs.anim_highlight == "hide":
theme.blend = self._theme_blend
elif addon_prefs.anim_highlight == "replace":
theme.blend = self._theme_blend
theme.inner_key = self._theme_key
theme.inner_key_sel = self._theme_key_sel
theme.inner_anim = self._theme_anim
theme.inner_anim_sel = self._theme_anim_sel
theme.inner_driven = self._theme_driven
theme.inner_driven_sel = self._theme_driven_sel
class VIEW3D_PT_ui_animation_render(bpy.types.Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = "View"
bl_label = "UI Animation Render"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
layout.use_property_split = False
prefs = context.preferences
addon_prefs = prefs.addons[__name__].preferences
layout.operator(RenderScreen.bl_idname)
draw_ui(addon_prefs, layout)
def register():
global km
bpy.utils.register_class(UIAnimationRenderPreferences)
bpy.utils.register_class(RenderScreen)
bpy.utils.register_class(VIEW3D_PT_ui_animation_render)
wm = bpy.context.window_manager
if wm.keyconfigs.addon:
km = wm.keyconfigs.addon.keymaps.new(name='Screen', space_type='EMPTY')
km.keymap_items.new('render.render_screen', 'F12', 'PRESS', shift=True, ctrl=True)
def unregister():
global km
bpy.utils.unregister_class(UIAnimationRenderPreferences)
bpy.utils.unregister_class(RenderScreen)
bpy.utils.unregister_class(VIEW3D_PT_ui_animation_render)
if km is not None:
wm = bpy.context.window_manager
wm.keyconfigs.addon.keymaps.remove(km)
km = None