-
Notifications
You must be signed in to change notification settings - Fork 0
/
RenderModal.py
143 lines (107 loc) · 4.71 KB
/
RenderModal.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import bpy
from datetime import datetime
class RYK_OP_RenderAllScenes(bpy.types.Operator):
bl_idname = "render.allscenes"
bl_label = "Render Selected Scenes"
UIRenderStatus = None
cancel_render = None
rendering = None
render_queue = None
timer_event = None
total = 0
TIMERStartTime = datetime.now()
def render_init(self, scene, depsgraph):
scene.rykbatchrender.IsRendering = True
def render_complete(self, scene, depsgraph):
self.render_queue.pop(0)
self.rendering = False
def render_cancel(self, scene, depsgraph):
self.cancel_render = True
print("RENDER CANCEL")
scene.rykbatchrender.IsRendering = False
def render_post(self, scene, despgraph):
# Get the current frame that we're in, and report the current progress from that.
curFrame = scene.frame_current
curFrameInSequence = (curFrame - self.render_queue[0]['startFrame'])
lastFrameInSequence = (self.render_queue[0]['endFrame'] - self.render_queue[0]['startFrame'])
scene.rykbatchrender.UIcurRenderProgress = ( curFrameInSequence/lastFrameInSequence )
scene.rykbatchrender.UIcurStatus = "Rendering frame {} of {} ({:3.2f}%)".format(
curFrameInSequence+1, lastFrameInSequence+1, ( curFrameInSequence/lastFrameInSequence ) * 100
)
def execute(self, context):
self.cancel_render = False
self.rendering = False
self.render_queue = []
## Update UI Info
self.TIMERStartTime = datetime.now()
context.scene.rykbatchrender.UIcurRenderProgress = 0.0
context.scene.rykbatchrender.UIcurScene = ""
context.scene.rykbatchrender.UIcurStatus = ""
context.scene.rykbatchrender.UITotalTimeSpent = ""
context.scene.rykbatchrender.CurJob = -1
#################################
## Time to fill in the data.
for scene in context.scene.ScenesDB:
print(scene['enabled'])
if scene['enabled']:
self.render_queue.append(scene)
self.total = len(self.render_queue)
context.scene.rykbatchrender.TotalJobs = self.total
#################################
# Register callback functions
bpy.app.handlers.render_init.clear()
bpy.app.handlers.render_init.append(self.render_init)
bpy.app.handlers.render_complete.clear()
bpy.app.handlers.render_complete.append(self.render_complete)
bpy.app.handlers.render_cancel.clear()
bpy.app.handlers.render_cancel.append(self.render_cancel)
bpy.app.handlers.render_post.clear()
bpy.app.handlers.render_post.append(self.render_post)
# Lock interface
bpy.types.RenderSettings.use_lock_interface = True
# Create timer event that runs every second to check if render render_queue needs to be updated
self.timer_event = context.window_manager.event_timer_add(1.0, window=context.window)
# register this as running in background
context.window_manager.modal_handler_add(self)
return {"RUNNING_MODAL"}
def modal(self, context, event):
if event.type == 'ESC':
bpy.types.RenderSettings.use_lock_interface = False
context.scene.rykbatchrender.IsRendering = False
print("CANCELLED")
return {'CANCELLED'}
elif event.type == 'TIMER':
## Update the total time.
context.scene.rykbatchrender.UITotalTimeSpent = str(datetime.now() - self.TIMERStartTime)
if len(self.render_queue) == 0 or self.cancel_render is True:
# Remove render callbacks
bpy.app.handlers.render_init.clear()
bpy.app.handlers.render_complete.clear()
bpy.app.handlers.render_cancel.clear()
bpy.app.handlers.render_post.clear()
# Remove timer
context.window_manager.event_timer_remove(self.timer_event)
bpy.types.RenderSettings.use_lock_interface = False
context.scene.rykbatchrender.IsRendering = False
print("FINISHED")
return {'FINISHED'}
# Nothing is rendering...
elif self.rendering is False:
sc=bpy.context.scene
currentscene = self.render_queue[0]
# Change the start and end frames.
sc.frame_start = currentscene['startFrame']
sc.frame_end = currentscene['endFrame']
# Change the render file path to the correct location.
bpy.context.scene.render.filepath = "{0}{1}\\".format(context.scene.rykbatchrender.OutputFolderLocation,currentscene['name'])
timestart = str(currentscene['startFrame'])
timeend = str(currentscene['endFrame'])
scenename = currentscene['name']
## Update UI Info
sc.rykbatchrender.UIcurScene = scenename
sc.rykbatchrender.CurJob = (self.total - len(self.render_queue)) / self.total
sc.rykbatchrender.JobsLeft = "{} {} completed of {}.".format(self.total - len(self.render_queue), "job" if (self.total - len(self.render_queue)) == 1 else "jobs" , self.total)
print(sc.rykbatchrender.CurJob)
# And now, render!
bpy.ops.render.render('INVOKE_DEFAULT', animation=True, write_still=True)
return {"PASS_THROUGH"}