closed panels by default
[blender-addons-contrib.git] / render_time.py
1 # ***** BEGIN GPL LICENSE BLOCK *****
2 #
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 #
18 # ***** END GPL LICENCE BLOCK *****
19
20
21 bl_info = {
22     "name": "Render Time Estimation",
23     "author": "Jason van Gumster (Fweeb)",
24     "version": (0, 5, 1),
25     "blender": (2, 62, 1),
26     "location": "UV/Image Editor > Properties > Image",
27     "description": "Estimates the time to complete rendering on animations",
28     "warning": "Does not work on OpenGL renders",
29     "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Render/Render_Time_Estimation",
30     "tracker_url": "http://projects.blender.org/tracker/index.php?func=detail&aid=30452&group_id=153&atid=467",
31     "category": "Render"}
32
33
34 import bpy, time
35 from bpy.app.handlers import persistent
36 from datetime import timedelta
37 import blf
38
39
40 timer = {"average": 0.0, "total": 0.0, "time_start": 0.0, "is_rendering": False, "hud": False}
41
42 def set_rendering(scene):
43     timer["is_rendering"] = True
44
45 @persistent
46 def unset_rendering(scene):
47     timer["is_rendering"] = False
48
49 @persistent
50 def start_timer(scene):
51     set_rendering(scene)
52
53     if scene.frame_current == scene.frame_start:
54         timer["average"] = 0.0
55         timer["total"] = 0.0
56
57     timer["time_start"] = time.time()
58
59 @persistent
60 def end_timer(scene):
61     render_time = time.time() - timer["time_start"]
62     timer["total"] += render_time
63     if scene.frame_current == scene.frame_start:
64         timer["average"] = render_time
65     else:
66         timer["average"] = (timer["average"] + render_time) / 2
67
68     print("Total render time: " + str(timedelta(seconds = timer["total"])))
69     print("Estimated completion: " + str(timedelta(seconds = (timer["average"] * (scene.frame_end - scene.frame_current)))))
70
71
72 # UI
73
74 def image_panel_rendertime(self, context):
75     scene = context.scene
76     layout = self.layout
77
78     if context.space_data.image is not None and context.space_data.image.type == 'RENDER_RESULT':
79         layout.label(text = "Total render time: " + str(timedelta(seconds = timer["total"])))
80
81         if timer["is_rendering"] and scene.frame_current != scene.frame_start:
82             layout.label(text = "Estimated completion: " + str(timedelta(seconds = (timer["average"] * (scene.frame_end - scene.frame_current)))))
83
84 def draw_callback_px(self, context):
85     scene = context.scene
86
87     font_id = 0  # XXX, need to find out how best to get this.
88
89     # draw some text
90     blf.position(font_id, 15, 30, 0)
91     blf.size(font_id, 18, 72)
92     blf.enable(font_id, blf.SHADOW)
93     blf.shadow(font_id, 5, 0.0, 0.0, 0.0, 1.0)
94
95     blf.draw(font_id, "Total render time " + str(timedelta(seconds = timer["total"])))
96     if timer["is_rendering"] and scene.frame_current != scene.frame_start:
97         blf.position(font_id, 15, 12, 0)
98         blf.draw(font_id, "Estimated completion: " + str(timedelta(seconds = (timer["average"] * (scene.frame_end - scene.frame_current)))))
99
100     # restore defaults
101     blf.disable(font_id, blf.SHADOW)
102
103 class RenderTimeHUD(bpy.types.Operator):
104     bl_idname = "view2d.rendertime_hud"
105     bl_label = "Display Render Times"
106     last_activity = 'NONE'
107
108     def modal(self, context, event):
109         if context.area:
110             context.area.tag_redraw()
111
112         #if event.type in {'ESC'}:
113         if timer["hud"] == False:
114             context.region.callback_remove(self._handle)
115             return {'CANCELLED'}
116
117         return {'PASS_THROUGH'}
118
119     def invoke(self, context, event):
120         if context.area.type == 'IMAGE_EDITOR':
121             if timer["hud"] == False:
122                 # Add the region OpenGL drawing callback
123                 self._handle = context.region.callback_add(draw_callback_px, (self, context), 'POST_PIXEL')
124                 timer["hud"] = True
125
126                 context.window_manager.modal_handler_add(self)
127                 return {'RUNNING_MODAL'}
128             else:
129                 timer["hud"] = False
130                 return {'CANCELLED'}
131         else:
132             self.report({'WARNING'}, "UV/Image Editor not found, cannot run operator")
133             return {'CANCELLED'}
134
135 def display_hud(self, context):
136     scene = context.scene
137     layout = self.layout
138     layout.operator("view2d.rendertime_hud")
139
140
141 # Registration
142
143 def register():
144     bpy.app.handlers.render_complete.append(unset_rendering)
145     bpy.app.handlers.render_cancel.append(unset_rendering)
146     bpy.app.handlers.render_pre.append(start_timer)
147     bpy.app.handlers.render_post.append(end_timer)
148     bpy.types.IMAGE_PT_image_properties.append(image_panel_rendertime)
149     bpy.utils.register_class(RenderTimeHUD)
150     bpy.types.IMAGE_HT_header.append(display_hud)
151
152     # Keymapping      XXX TODO - This doesn't work for some reason
153     #kc = bpy.context.window_manager.keyconfigs.addon
154     #km = kc.keymaps.new(name = "View 2D", space_type = 'IMAGE_EDITOR')
155     #kmi = km.keymap_items.new("view2d.rendertime_hud", 'E', 'PRESS')
156     #kmi.active = True
157
158 def unregister():
159     #kc = bpy.context.window_manager.keyconfigs.addon
160     #km = kc.keymaps["View 2D"]
161     #km.keymap_items.remove(km.keymap_items["view2d.rendertime_hud"])
162
163     bpy.types.IMAGE_HT_header.remove(display_hud)
164     bpy.utils.unregister_class(RenderTimeHUD)
165     bpy.app.handlers.render_pre.remove(start_timer)
166     bpy.app.handlers.render_post.remove(end_timer)
167     bpy.app.handlers.render_cancel.remove(unset_rendering)
168     bpy.app.handlers.render_complete.remove(unset_rendering)
169     bpy.types.IMAGE_PT_image_properties.remove(image_panel_rendertime)
170
171 if __name__ == '__main__':
172     register()