# Part of VCStudio # GPLv3 or later # This file will visualize the rendering process import os import sys import json import time if len(sys.argv) == 1: project = input("Project: ") else: project = sys.argv[1] def get_runtime_data(project): # This will read a specific .json file from the system. template = {"to_render":True, "current_progress":"Fra: 69 | Mem: 420 |Sample: 69/420"} try: with open(project+"/render_runtime.json") as json_file: data = json.load(json_file) except: data = template.copy() return data def save_runtime_data(data, project): with open(project+"/render_runtime.json", 'w') as fp: json.dump(data, fp, indent=4) # Colors are used to make the clr = { "norm":"\033[00m", # Reset to normal "bold":"\033[01m", # Bold Text "ital":"\033[03m", # Italic Text "undr":"\033[04m", # Underlined "blnk":"\033[05m", # Blinking # Text "tdbl":"\033[30m", # Dark Black "tdrd":"\033[31m", # Dark Red "tdgr":"\033[32m", # Dark Green "tdyl":"\033[33m", # Dark Yellow "tdbu":"\033[34m", # Dark Blue "tdma":"\033[35m", # Dark Magenta "tdcy":"\033[36m", # Dark Cyan "tdwh":"\033[37m", # Dark White "tbbl":"\033[90m", # Bright Black "tbrd":"\033[91m", # Bright Red "tbgr":"\033[92m", # Bright Green "tbyl":"\033[93m", # Bright Yellow "tbbu":"\033[94m", # Bright Blue "tbma":"\033[95m", # Bright Magenta "tbcy":"\033[96m", # Bright Cyan "tbwh":"\033[97m", # Bright White # Background "bdbl":"\033[40m", # Dark Black "bdrd":"\033[41m", # Dark Red "bdgr":"\033[42m", # Dark Green "bdyl":"\033[43m", # Dark Yellow "bdbu":"\033[44m", # Dark Blue "bdma":"\033[45m", # Dark Magenta "bdcy":"\033[46m", # Dark Cyan "bdwh":"\033[47m", # Dark White "bbbl":"\033[100m", # Bright Black "bbrd":"\033[101m", # Bright Red "bbgr":"\033[102m", # Bright Green "bbyl":"\033[103m", # Bright Yellow "bbbu":"\033[104m", # Bright Blue "bbma":"\033[105m", # Bright Magenta "bbcy":"\033[106m", # Bright Cyan "bbwh":"\033[108m" # Bright White } # A function that insures a specific width of the printed part def wdth(x, n): # Convert Data to String mode = "normal" if type(x) == bool and x == True: x = "V" mode = "bdgr" elif type(x) == bool and x == False: x = "X" mode = "bdrd" else: x = str(x) # Turn emogis #x = emote(x) # Some characters are too wide. They do not obey the # monospace of the terminal, thus making it not pretty. # This is the string of characters which are checked to good = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'’()*+,-./:;<=>?@[\]^_`{|}~ йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮёЁ" # let's filter the string y = x x = "" for i in y: if i in good: x = x + i else: x = x + "▓" # Now let's print what we've got. if len(y) < n: fac = n-len(y) fac1 = int(round(fac/2)) fac2 = fac1 while fac1 + fac2 > fac: fac2 -=1 while fac1 + fac2 < fac: fac2 +=1 x = (" "*fac1)+x+(" "*fac2) elif len(y) > n: if n > 10: x = x[:n-3]+"..." else: x = x[:n] if mode == "normal": return x else: return clr[mode]+clr["bold"]+x+clr["norm"] def tsize(): # This funtion will get the size of the terminal and # return it to the variables provided width, height # On some systems this may not work. So there is a # try function. try: # Getting the size of the terminal import os w, h = os.get_terminal_size() # Sometimes when the terminal width is either # even or odd. It breaks code for some other # thing written differenly. For example: # You may have an even width ( like 84 ) when # writing a function. And then it works on different # widths as well like 62 and 80 and 48. All of them # are still even. Then you scale the terminal to be # something off like 63 and the function breaks. You # have one character too much or one character too little. # This is why I do not want to have a difference. And # force width to be one less, if it's not divisible by 2. if not w % 2: w = w - 1 return w, h except: # If, by any reason the terminal can't get it's size. # We want to return some size regardless. w = 60 h = 20 return w, h def table(data, number=True): # This function will present data in a pretty table thing. # So let's first of all get the size of the terminal w, h = tsize() if number: w = w - 4 # Then let's draw the categories for this we need to extract # it's sizes. If there is no 'size' variable the sizes of # each category will be spread equally. size = [] # Here the size will go as pure character value. if "size" in data: for i in data["size"]: size.append(int(( w - 10 ) / sum(data["size"]) * i)) while sum(size) < w - 10: size[-1] += 1 # printing categories nb = "" if number: nb = " " s = " "+clr["bdma"]+" "+clr["tbwh"]+nb for n, item in enumerate(data["categories"]): s = s + wdth(item.upper(), size[n]) print(s+clr["bdma"]+" "+clr["norm"]) size[-1] += 1 # printing items for b, i in enumerate(data["data"]): # dark bright sequence thingy if b % 2: d = "b" else: d = "d" nb = "" if number: nb = clr["tbwh"]+wdth(b,4) s = " "+clr["bdma"]+" "+nb+clr["norm"]+clr["b"+d+"bu"]#+clr["tbwh"] for n, item in enumerate(i): s = s +clr["b"+d+"bu"]+ clr["tbwh"]+wdth(item, size[n]-1)+clr["bdma"]+" " print(s+clr["norm"]) def center(line, c="bdma", blink=False): # This funtiocn will bring a given string of text # in the center of the terminal with a nice backgroud # around it. w, h = tsize() if blink: blink = clr["blnk"] else: blink = "" if len(line) % 2: line = line + " " if len(line) < w - 11: print(" "+clr[c], wdth(" ", int((w-10)/2 - (len(line)/2))), clr["bold"]+clr["tbwh"]+blink+line, wdth(" ", int((w-10)/2 - (len(line)/2))-1), clr["norm"]) else: print(" "+clr[c], clr["bold"]+clr["tbwh"]+blink+wdth(line,w-10), clr["norm"]) running_for = 0 lastframe = 0 maxtime = 1000000 while True: running_for = running_for + 1 runtime = get_runtime_data(project) if not runtime.get("to_render"): break x,y = tsize() if y > 8: print("\n\n") process = runtime.get("current_progress", "").split(" | ") try: del runtime["current_progress"] except: pass data_print = {"categories":list(runtime.keys()), "size":[1]*(len(runtime)), "data":[list(runtime.values())]} table(data_print, False) data_print = {"categories":[""]*(len(process)), "size":[1]*(len(process)), "data":[process]} table(data_print, False) center("") # Latest frames data filename = runtime.get("current_file", "") folder = filename[:filename.rfind("/")]+"/extra" savefile = folder+filename[filename.rfind("/"):]+".json" try: with open(project+savefile) as json_file: data = json.load(json_file) except: data = {} listoftimesx = data.get("analytics", {}).get(data.get("save_folder", ""), []) listoftimes = {} minframe = data.get("start_frame", 0) for i in listoftimesx: try: listoftimes[int(i)] = listoftimesx[i] except: pass try: maxframe = max(list(listoftimes.keys())) if maxframe > lastframe: lastframe = maxframe running_for = 0 maxtime = max(list(listoftimes.values())) maxtime = max(maxtime, running_for*1000000) print() for i in range(max(minframe,maxframe-y+16), maxframe+1): amount = int((x-14)/(maxtime-minframe)*(listoftimes[i]-minframe)) print(" ",wdth(i, 4), "▒"*amount) except Exception as e: #print(e) maxframe = 0 #maxtime = 1 lastframe = maxframe running_for = 0 amount = int((x-14)/maxtime*running_for*1000000) print(" " , wdth(maxframe+1, 4), "█"*amount) amount = int((x-14)/(data.get("end_frame", maxframe+1)-minframe)*(maxframe+1-minframe)) print() print(" "+clr["tbma"]+wdth(data.get("end_frame", maxframe+1), 4)+" "+("█"*amount)+clr["norm"]) time.sleep(1) os.system("clear")