3838root .grid_columnconfigure (1 , weight = 100 )
3939
4040
41- root .resizable (False , False )
42-
41+ root .resizable (True , True )
42+
43+ # Global variables to track rendered frames
44+ frame_range_list = []
45+ completed_frames = set ()
46+
47+ def parse_frame_range (frame_range_str ):
48+ frames = set ()
49+ for part in frame_range_str .split (',' ):
50+ if '-' in part :
51+ start , end = map (int , part .split ('-' ))
52+ frames .update (range (start , end + 1 ))
53+ else :
54+ frames .add (int (part ))
55+ return frames
4356
4457def render_frames ():
4558 global render_process
4659 global progressbar # Make sure progressbar is a global variable
4760 global render_thread # Declare render_thread as a global variable
4861 global command # Use the global command variable
62+ global frame_range_list
63+ global completed_frames
4964
5065 katana_file = entry_katana_file .get ()
5166 frame_range = entry_frame_range .get ()
5267 render_node = entry_render_node .get ()
5368 # Reset progress bar
5469 progressbar .set (0 )
70+ completed_frames .clear ()
5571 if not katana_file or not frame_range :
5672 #result_label.configure(text="Please provide Katana File and Frame Range.")
5773 result_label .configure (state = tk .NORMAL ) # Enable the CTkTextbox for editing
5874 result_label .delete (1.0 , tk .END ) # Clear existing text
5975 result_label .insert (tk .END , "Please provide Katana File and Frame Range." )
6076 result_label .configure (state = tk .DISABLED ) # Disable the CTkTextbox
6177 return
62-
78+
79+ frame_range_list = parse_frame_range (frame_range )
6380 command = f'"{ katana_bin } " --batch --katana-file="{ katana_file } " -t { frame_range } '
6481
6582 if render_node :
@@ -70,18 +87,20 @@ def render_frames():
7087 name , value = gsv [0 ].get (), gsv [1 ].get ()
7188 if name and value :
7289 command += f' --var { name } ={ value } '
90+
91+
7392
7493 try :
94+ render_process = subprocess .Popen (command , shell = True , stdout = subprocess .PIPE , stderr = subprocess .PIPE , text = True , bufsize = 1 , universal_newlines = True ) # Update this line
7595 # Redirect the output to a pipe to capture it
76- if render_process is None or render_process .poll () is not None :
77- render_process = subprocess .Popen (command , shell = True , stdout = subprocess .PIPE , stderr = subprocess .PIPE , text = True , bufsize = 1 , universal_newlines = True )
78- stop_render_button .configure (state = tk .NORMAL )
79- threading .Thread (target = monitor_render_output , args = (render_process .stdout ,)).start ()
80- threading .Thread (target = update_progress_from_process , args = (render_process , progressbar )).start ()
81-
96+ if render_process :
8297 stop_render_button .configure (state = tk .NORMAL )
98+ render_thread = threading .Thread (target = monitor_render_output , args = (render_process ,))
99+ render_thread .start ()
100+ # threading.Thread(target=update_progress_from_process, args=(render_process, progressbar)).start()
83101 render_button .configure (state = tk .DISABLED )
84-
102+ else :
103+ raise RuntimeError ("Failed to start render process." )
85104
86105
87106 except Exception as e :
@@ -131,29 +150,100 @@ def render_frames_thread():
131150 stop_render_event .set ()
132151 stop_render_button .configure (state = tk .DISABLED )
133152
134- def monitor_render_output (output_stream ):
135- try :
136- for line in iter (partial (output_stream .readline , 4096 ), '' ):
137- output_text .insert (tk .END , line )
138- output_text .yview (tk .END )
139- update_progress (line , progressbar )
153+ def monitor_render_output (process ):
154+ # def monitor_render_output(output_stream):
155+ global render_process
156+ global progressbar
157+ global stop_render_event
158+ global frame_range_list
159+ def read_output (pipe , output_func ):
160+ for line in iter (pipe .readline , '' ):
161+ output_func (line )
162+ stdout_thread = threading .Thread (target = read_output , args = (process .stdout , handle_stdout ))
163+ stderr_thread = threading .Thread (target = read_output , args = (process .stderr , handle_stderr ))
164+ stdout_thread .start ()
165+ stderr_thread .start ()
166+ stdout_thread .join ()
167+ stderr_thread .join ()
168+
169+ process .stdout .close ()
170+ process .stderr .close ()
171+
172+ stop_render_event .set ()
173+ render_button .configure (state = tk .NORMAL )
174+ stop_render_button .configure (state = tk .DISABLED )
175+ result_label .configure (state = tk .NORMAL )
176+ result_label .delete (1.0 , tk .END )
177+ result_label .insert (tk .END , "Rendering Done!" )
178+ result_label .configure (state = tk .DISABLED )
179+
180+ # try:
181+ # for line in iter(partial(output_stream.readline, 4096), ''):
182+ # # print(line.strip()) # Debug: Print each line of output
183+ # output_text.insert(tk.END, line)
184+ # output_text.yview(tk.END)
185+ # update_progress(line, progressbar)
186+ # check_frame_completion(line)
187+
188+ # if completed_frames >= frame_range_list:
189+ # stop_render_event.set()
190+
191+ # # Terminate the render process if it's still running
192+ # if render_process and render_process.poll() is None:
193+ # render_process.terminate()
194+ # render_process.wait() # Wait for the process to finish
195+ # render_button.configure(state=tk.NORMAL)
196+ # stop_render_button.configure(state=tk.DISABLED)
197+ # result_label.configure(state=tk.NORMAL) # Enable the CTkTextbox for editing
198+ # result_label.delete(1.0, tk.END)
199+ # result_label.insert(tk.END, "Rendering Done!")
200+ # result_label.configure(state=tk.DISABLED) # Disable the CTkTextbox
140201
141202
142203
143- except Exception as e :
144- print (f"Error reading output: { e } " )
145- finally :
146- if not output_stream .closed :
147- output_stream .close ()
204+ # except Exception as e:
205+ # print(f"Error reading output: {e}")
206+ # finally:
207+ # if not output_stream.closed:
208+ # output_stream.close()
209+
210+ # # if completed_frames >= frame_range_list:
211+ # stop_render_event.set()
212+ # render_button.configure(state=tk.NORMAL)
213+ # stop_render_button.configure(state=tk.DISABLED)
214+ # result_label.configure(state=tk.NORMAL) # Enable the CTkTextbox for editing
215+ # result_label.delete(1.0, tk.END)
216+ # result_label.insert(tk.END, "Rendering Done!")
217+ # result_label.configure(state=tk.DISABLED) # Disable the CTkTextbox
218+
219+ def handle_stdout (line ):
220+ output_text .insert (tk .END , line )
221+ output_text .yview (tk .END )
222+ update_progress (line , progressbar )
223+ check_frame_completion (line )
148224
149- stop_render_event .set ()
150- render_button .configure (state = tk .NORMAL )
151- stop_render_button .configure (state = tk .DISABLED )
225+ def handle_stderr (line ):
226+ output_text .insert (tk .END , line )
227+ output_text .yview (tk .END )
228+
229+ def check_frame_completion (output_line ):
230+ match = re .search (r"Frame (\d+) completed" , output_line )
231+ if match :
232+ frame = int (match .group (1 ))
233+ completed_frames .add (frame )
152234 result_label .configure (state = tk .NORMAL ) # Enable the CTkTextbox for editing
153235 result_label .delete (1.0 , tk .END )
154- result_label .insert (tk .END , "Rendering Done! " )
236+ result_label .insert (tk .END , f"Frame { frame } completed " )
155237 result_label .configure (state = tk .DISABLED ) # Disable the CTkTextbox
156-
238+ update_result_label ()
239+ def update_result_label ():
240+ completed_frames_str = ", " .join (map (str , sorted (completed_frames )))
241+ #result_label.configure(text=f"Completed frames: {completed_frames_str}")
242+ result_label .configure (state = tk .NORMAL ) # Enable the CTkTextbox for editing
243+ result_label .delete (1.0 , tk .END )
244+ result_label .insert (tk .END , f"Frame { completed_frames_str } completed" )
245+ result_label .configure (state = tk .DISABLED )
246+
157247def update_ui (output_queue ):
158248 try :
159249 while True :
@@ -286,7 +376,37 @@ def stop_render():
286376 stop_render_event .set ()
287377
288378def monitor_render_process (process ):
379+ global render_process
380+ global progressbar
289381 global stop_render_event
382+
383+
384+ # while True:
385+ # if stop_render_event.is_set():
386+ # break
387+
388+ # line = process.stdout.readline()
389+ # if line:
390+ # render_output_queue.put(line)
391+ # root.after(100, update_output_text, line)
392+ # check_frame_completion(line)
393+ # else:
394+ # break
395+ # # After processing all output, check if all frames are completed
396+ # if completed_frames >= frame_range_list:
397+ # stop_render_event.set() # Signal to stop rendering
398+ # render_button.configure(state=tk.NORMAL) # Enable render button
399+ # stop_render_button.configure(state=tk.DISABLED) # Disable stop render button
400+ # result_label.configure(state=tk.NORMAL) # Enable result label
401+ # result_label.delete(1.0, tk.END) # Clear existing text
402+ # result_label.insert(tk.END, "Rendering Done!") # Update rendering status
403+ # result_label.configure(state=tk.DISABLED) # Disable result label
404+
405+ # # After checking completion, close the output stream
406+ # process.stdout.close()
407+
408+
409+ #global stop_render_event
290410 process .communicate () # Wait for the process to finish
291411 stop_render_event .set () # Signal that the rendering process has finished
292412 stop_render_button .configure (state = tk .DISABLED ) # Disable the stop render button
@@ -462,7 +582,7 @@ def change_appearance_mode_event(new_appearance_mode: str):
462582# root.resizable(False, False)
463583
464584# Set custom icon
465- icon_path = "jomilojuArnold222 .ico" # Replace with the path to your .ico file
585+ icon_path = "WindowsIcon .ico" # Replace with the path to your .ico file
466586root .iconbitmap (icon_path )
467587
468588# # load and create background image
@@ -478,9 +598,9 @@ def change_appearance_mode_event(new_appearance_mode: str):
478598sidebar_frame .grid_rowconfigure (0 , weight = 1 )
479599sidebar_frame .grid_columnconfigure (1 , weight = 1 )
480600
481- my_image = customtkinter .CTkImage (light_image = Image .open ("jomilojuArnold222.jpg " ),
482- dark_image = Image .open ("jomilojuArnold222.jpg " ),
483- size = (100 , 60 ))
601+ my_image = customtkinter .CTkImage (light_image = Image .open ("WindowsIcon.ico " ),
602+ dark_image = Image .open ("WindowsIcon.ico " ),
603+ size = (60 , 60 ))
484604
485605image_label = customtkinter .CTkLabel (sidebar_frame , image = my_image , text = "" ,) # display image with a CTkLabel
486606image_label .grid (row = 0 , column = 0 , pady = 30 ,padx = 10 , sticky = "NW" )
0 commit comments