Merge branch 'blender-v4.0-release'
[blender-addons.git] / render_ui_animation_render.py
blob706b7e8d4597f21dc9883eca3f9d53a0457f0f03
1 # SPDX-FileCopyrightText: 2020-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 import bpy
7 bl_info = {
8 "name": "UI Animation Render",
9 "author": "Luca Rood",
10 "description": "Render animations of the Blender UI.",
11 "blender": (2, 80, 0),
12 "version": (0, 1, 0),
13 "location": "View3D > Sidebar > View Tab and Ctrl+Shift+F12",
14 "warning": "",
15 "category": "Render"
18 km = None
21 def draw_ui(prefs, layout):
22 layout.prop(prefs, "delay")
24 col = layout.column(align=True)
25 col.label(text="Animation Highlight:")
27 row = col.row()
28 row.prop(prefs, "anim_highlight", expand=True)
30 if prefs.anim_highlight == "replace":
31 split = col.split(factor=0.2)
32 split.label(text="Color")
33 row = split.row(align=True)
34 row.prop(prefs, "highlight_color", text="")
35 row.prop(prefs, "highlight_blend", text="Blend")
38 class UIAnimationRenderPreferences(bpy.types.AddonPreferences):
39 bl_idname = __name__
41 delay: bpy.props.FloatProperty(
42 name="Capture Delay",
43 description="How much time to wait (seconds) before capturing each frame, to allow the viewport to clean up",
44 default=0.5
47 anim_highlight: bpy.props.EnumProperty(
48 name="Animation Highlight",
49 description="What to do with the animated field highlight color",
50 items=[("keep", "Keep", "Keep the animated field highlight", 0),
51 ("hide", "Hide", "Hide the animated field highlight", 1),
52 ("replace", "Replace", "Replace the animated field highlight", 2)],
53 default="keep"
56 highlight_color: bpy.props.FloatVectorProperty(
57 name="Highlight Color",
58 description="Color to use for animated field highlights",
59 subtype='COLOR',
60 default=(1.0, 1.0, 1.0)
63 highlight_blend: bpy.props.FloatProperty(
64 name="Highlight Blend",
65 description="How much the highlight color influences the field color",
66 default=0.5
69 def draw(self, context):
70 draw_ui(self, self.layout)
73 class RenderScreen(bpy.types.Operator):
74 bl_idname = "render.render_screen"
75 bl_label = "Render Screen"
76 bl_description = "Capture the screen for each animation frame and write to the render output path"
78 _timer = None
79 _f_initial = 1
80 _theme_blend = 0.0
81 _theme_key = (0, 0, 0)
82 _theme_key_sel = (0, 0, 0)
83 _theme_anim = (0, 0, 0)
84 _theme_anim_sel = (0, 0, 0)
85 _theme_driven = (0, 0, 0)
86 _theme_driven_sel = (0, 0, 0)
88 def modal(self, context, event):
89 if event.type in {'RIGHTMOUSE', 'ESC'}:
90 self.stop(context)
91 return {'CANCELLED'}
93 if event.type == 'TIMER':
94 scene = context.scene
95 f_curr = scene.frame_current
97 bpy.ops.screen.screenshot(filepath=context.scene.render.frame_path(frame=f_curr))
99 if f_curr < scene.frame_end:
100 scene.frame_set(f_curr + 1)
101 else:
102 self.stop(context)
103 return {'FINISHED'}
105 return {'RUNNING_MODAL'}
107 def execute(self, context):
108 # Adjust animation highlight (theme)
109 prefs = context.preferences
110 addon_prefs = prefs.addons[__name__].preferences
111 theme = prefs.themes[0].user_interface.wcol_state
113 if addon_prefs.anim_highlight == "hide":
114 self._theme_blend = theme.blend
115 theme.blend = 0.0
116 elif addon_prefs.anim_highlight == "replace":
117 self._theme_blend = theme.blend
118 self._theme_key = theme.inner_key.copy()
119 self._theme_key_sel = theme.inner_key_sel.copy()
120 self._theme_anim = theme.inner_anim.copy()
121 self._theme_anim_sel = theme.inner_anim_sel.copy()
122 self._theme_driven = theme.inner_driven.copy()
123 self._theme_driven_sel = theme.inner_driven_sel.copy()
125 theme.blend = addon_prefs.highlight_blend
126 theme.inner_key = addon_prefs.highlight_color
127 theme.inner_key_sel = addon_prefs.highlight_color
128 theme.inner_anim = addon_prefs.highlight_color
129 theme.inner_anim_sel = addon_prefs.highlight_color
130 theme.inner_driven = addon_prefs.highlight_color
131 theme.inner_driven_sel = addon_prefs.highlight_color
133 # Set frame
134 scene = context.scene
135 self._f_initial = scene.frame_current
136 scene.frame_set(scene.frame_start)
138 # Start timer
139 wm = context.window_manager
140 self._timer = wm.event_timer_add(addon_prefs.delay, window=context.window)
141 wm.modal_handler_add(self)
142 return {'RUNNING_MODAL'}
144 def stop(self, context):
145 # Stop timer
146 wm = context.window_manager
147 wm.event_timer_remove(self._timer)
149 # Reset frame
150 context.scene.frame_set(self._f_initial)
152 # Reset theme
153 prefs = context.preferences
154 addon_prefs = prefs.addons[__name__].preferences
155 theme = prefs.themes[0].user_interface.wcol_state
157 if addon_prefs.anim_highlight == "hide":
158 theme.blend = self._theme_blend
159 elif addon_prefs.anim_highlight == "replace":
160 theme.blend = self._theme_blend
161 theme.inner_key = self._theme_key
162 theme.inner_key_sel = self._theme_key_sel
163 theme.inner_anim = self._theme_anim
164 theme.inner_anim_sel = self._theme_anim_sel
165 theme.inner_driven = self._theme_driven
166 theme.inner_driven_sel = self._theme_driven_sel
169 class VIEW3D_PT_ui_animation_render(bpy.types.Panel):
170 bl_space_type = 'VIEW_3D'
171 bl_region_type = 'UI'
172 bl_category = "View"
173 bl_label = "UI Animation Render"
174 bl_options = {'DEFAULT_CLOSED'}
176 def draw(self, context):
177 layout = self.layout
178 layout.use_property_split = False
180 prefs = context.preferences
181 addon_prefs = prefs.addons[__name__].preferences
183 layout.operator(RenderScreen.bl_idname)
184 draw_ui(addon_prefs, layout)
187 def register():
188 global km
190 bpy.utils.register_class(UIAnimationRenderPreferences)
191 bpy.utils.register_class(RenderScreen)
192 bpy.utils.register_class(VIEW3D_PT_ui_animation_render)
194 wm = bpy.context.window_manager
196 if wm.keyconfigs.addon:
197 km = wm.keyconfigs.addon.keymaps.new(name='Screen', space_type='EMPTY')
198 km.keymap_items.new('render.render_screen', 'F12', 'PRESS', shift=True, ctrl=True)
201 def unregister():
202 global km
204 bpy.utils.unregister_class(UIAnimationRenderPreferences)
205 bpy.utils.unregister_class(RenderScreen)
206 bpy.utils.unregister_class(VIEW3D_PT_ui_animation_render)
208 if km is not None:
209 wm = bpy.context.window_manager
210 wm.keyconfigs.addon.keymaps.remove(km)
211 km = None