# THIS FILE IS A PART OF VCStudio # PYTHON 3 ############################################################################## # Not all users have the ability or the desire to run a complex Graphical UI # to do simple tasks in the project. For example Windows users have no ability # to run Gtk applications in general. Even tho I dislike Window and do not # condone the use of it. I don't want to make VCStudio completilly unusable # for them. For example let's say somebody will distribute a story.vcss file. # I want to give Windows users at least the ability to read the text of the # scene. # Also the console mode could be used for the rendering servers of big # studios. Where running a GUI is just not practical. They usually have a # terminal only installation. And so some kind of way of working with project # should be possible from the terminal. ############################################################################## import os import re import datetime import threading # Let's get a terminal size for prettier rendering. try: w, h = os.get_terminal_size() except: w, h, = 50,50 from settings import settings from settings import talk from settings import oscalls from project_manager import pm_project from project_manager import pm_console # Studio from studio import analytics from studio import story from studio import studio_storyDeletionLayer from studio import studio_storyLayer from studio import studio_settingsLayer from studio import studio_assetLayer from studio import studio_analyticsLayer from studio import studio_scriptLayer from studio import studio_multiuserLayer # UI modules from UI import UI_testing from UI import UI_color from UI import UI_elements # Network from network import network_renders from network import network_multiuser from network import multiuser_terminal commands1 = [ "help",# - returns this help "asset",# - choose and asset "assets",# - list existsing assets "scene",# - read a scene "scenes",# - lists available scenes "scenes_main_chain",# - list only scenes from the main chain "shot",# - choose a shot "shots",# - list shots of a given scene "file",# - open a file from a given asset or shot "files",# - list all files from a given asset or shot "multiuser_start",# - starts multiuser server for this project "multiuser_stop",# - stops multiuser "multiuser_users",# - list of users connected to multiuser "multiuser_message",# - message users on multiuser "vse",# - starts a vse file "vses",# - lists all vse files "render",# - render a given file from a shot "render_server",# - become a render server for users on multiuser "render_not_server",# - stop being a render server for users "eval", # - run a python expression "exit" ] pm_console.commands = commands1.copy() def cls(): #cleaning the terminal os.system("clear") class make_win: # In order to make it work with all the standard functions build for the GUI # experience. Like export, multiuser and such. Yes multiuser will be supported # here fully. We have to be able to access the win. object. BUT # there is a rub. The win object is not really accesable from non Gtk system. # Because I had this genious idea to use already created Gtk.Window and just # add a bunch stuff to it in order to have a kind of global dictionary thing. def __init__(self, project): self.project = project def previous(win): win.previous = {} for i in win.current: if type(win.current[i]) == list or type(win.current[i]) is dict: win.previous[i] = win.current[i].copy() else: win.previous[i] = win.current[i] def run(project): win = make_win(project) # Setting up the global variables. (kinda) win.animations = {} win.previous = {} win.current = {} win.images = {} win.imageload = 0 win.text = {} win.textactive = "" win.scroll = {} win.FPS = 0 win.url = "story_editor" win.cur = "" # This will be used to get precicelly what asset / scene / shot we are in win.update = {"versions":{}} win.project = project win.out_dots = {} win.assets = {} win.szone = [[100,100],[100,100]] # Square drawn if selected more then one node. win.surround = { # And this is the list of the squares. Because it's not "frame":0, # as easy to do. See UI / UI_math / rectangle_surround() "rects":[] # for details of this implementation. } win.calllayer = False win.layercashe = {} # Here I gonna store layers that are inactive to speed up stuff win.checklists = {} win.blink = False # Cursor blinking thing. win.renders = {} # List of current active renders. win.undo_history = [] win.undo_index = 0 win.multiuser = { "server":False, # Whether we are connected to the server. And the server ID "userid":"", # The id of current user in the server "last_request": "", # The last request send to the server. ( for stopping bloat ) "curs":{}, # The information about various items on other users machines. "request":[["story"]], # Requests done in UI space "users":{}, # List of users information Names, IPs etc. "messages":[], # List of messages "unread":0 , # Amount of unread messages "terminal":[], # The outputs from the server "asset_list_check":False, # Whether the initial update happened when connecting to the server "story_check":False, # Whether the first story check was done. "analytics_check":False } if pm_project.is_legacy(project): win.story = story.get_legacy(project) win.analytics = analytics.get_legacy(project) else: win.story = story.load(project) win.analytics = analytics.load(project) # Cashed tables win.color = UI_color.get_table() win.settings = settings.load_all() # Default values win.current["frame"] = 0 win.current["testing"] = False win.current["LMB"] = False win.current["MMB"] = False win.current["RMB"] = False win.current["keys"] = [] win.current["key_letter"] = "" win.current["scroll"] = [0,0] win.current["project"] = "" win.current["tool"] = "selection" win.current["draw_dot"] = "end" win.current["calls"] = {} # Calls. See sutdio/studio_dialogs.py win.current["script_find"] = [0,0] win.current["camera_arrived"] = False if "pointers" not in win.story: win.story["pointers"] = {} # List of text pointers per scene new_date_format = "%Y/%m/%d" today = datetime.datetime.strftime(datetime.datetime.today(), new_date_format) win.current["date"] = today # Don't even ask. I'm litteraly tired already. previous(win) # Version of the software win.version = 0.0 try: vfile = open("settings/update.data") vfile = vfile.read() vfile = vfile.split("\n") for line in vfile: if line.startswith("VERSION "): win.version = float(line.replace("VERSION ", "")) break except: win.version = 0.0 # FPS win.sFPS = datetime.datetime.now() cls() # The title thing in the top print("\033[1;33m\n "+win.analytics["name"]+"") print("\033[1;33m "+win.analytics["director"]+"") print("\033[1;33m "+win.analytics["status"]+" \n") progress_bar(win.analytics["fraction"]) print() while True: # making sure Tab is doing autocomlete to the right functions pm_console.commands = commands1.copy() command = input("\033[1;35m : \033[1;m") ############## if command == "exit": cls() exit() ###### HELP ###### elif command == "help": print("\033[1;32m"+talk.text("sc_help")+"\n") ##### ASSETS LIST #### elif command == "assets": for asset in network_multiuser.list_all_assets(win): print("\033[1;35m "+asset) ##### ASSET ACCESS ##### elif command == "asset": pm_console.commands = pm_project.get_list() n = input("\033[1;33m : ") if os.path.exists(win.project+"/dev"+n) and n.count("/") == 2: win.cur = n t, cur, name = n.split("/") print("\033[1;33m\n "+talk.text(cur)+": "+name) progress_bar(story.get_asset_data(win, n)["fraction"]) print() else: print("\033[1;31m"+talk.text("failed")) #### SCENES LIST #### elif command == "scenes": for scene in win.story["scenes"]: print("\033[1;35m "+scene) #### SCENES MAIN CHAIN LIST #### elif command == "scenes_main_chain": lastarrow = 'start' for i in win.story["arrows"]: if lastarrow == "end": break for arrow in win.story["arrows"]: if arrow[0] == lastarrow: lastarrow = arrow[1] if arrow[1] != "end": print("\033[1;35m "+arrow[1][1]) ##### READ SCENE TEXT ##### elif command == "scene": pm_console.commands = list(win.story["scenes"].keys()) n = input("\033[1;33m : ") if n in win.story["scenes"]: win.cur = "/"+n # I want to have the full scene written to the terminal at this # point. Good that most terminals already support tiling. I don't # need to care about that. So let's do that. scene = win.story["scenes"][n]["shots"] buf = "\033[1;0m" lines = 0 for block in scene: # For just text parts. if block[0] == "text_block": style = "\033[1;40m" else: # If It's a shot. I want the shot color marking shotis = block[1] rcolors = { "shot_1":"\033[1;41m", "shot_2":"\033[1;43m", "shot_3":"\033[1;46m", "shot_4":"\033[1;44m", "shot_5":"\033[1;42m" } # Getting the color. It's not always works. if "shot_colors" not in win.story: win.story["shot_colors"] = {} surl = "/"+n+"/"+shotis if surl not in win.story["shot_colors"]: win.story["shot_colors"][surl] = list(rcolors.keys())[len(win.story["shot_colors"]) % len(rcolors)] style = rcolors[win.story["shot_colors"][surl]] for text in block[-1]: # For just regular parts we have our regular text if text[0] == "text" or text[0] == "link": for line in re.split("(\n)",text[-1]): if line == "\n": while buf: print(buf[:w]) buf = buf[w:] lines = lines + 1 if lines + 8 > h: input("... "+talk.text("press_to_continue")+" ...") lines = 0 buf = "\033[1;0m" else: if text[0] == "text": buf = buf + style + line + "\033[1;0m" else: buf = buf + "\033[1;45m" + line + "\033[1;0m" elif text[0] == "frase": while buf: print(buf[:w]) buf = buf[w:] lines = lines + 1 if lines + 8 > h: input("... "+talk.text("press_to_continue")+" ...") lines = 0 buf = "\033[1;0m" if text[1][0] == "text": print(" "*int(w/2-len(text[1][-1])/2)+"\033[1;40m"+text[1][-1]) else: print(" "*int(w/2-len(text[1][-1])/2)+"\033[1;45m"+text[1][-1]+"\033[1;40m") for line in re.split("(\n)",text[-1]): if line == "\n": print(line) else: while line: print(" "*int(w/3)+style+line[:int(w/3)]) line = line[int(w/3):] lines = lines + 1 if lines + 8 > h: input("... "+talk.text("press_to_continue")+" ...") lines = 0 while buf: print(buf[:w]) buf = buf[w:] lines = lines + 1 if lines + 8 > h: input("... "+talk.text("press_to_continue")+" ...") lines = 0 print() print("\033[1;33m\n "+n) progress_bar(win.story["scenes"][n]["fraction"]) print() else: print("\033[1;31m"+talk.text("failed")) ### FILES ### elif command == "files": prefix = "/rnd" for i in ["/chr", "/veh", "/obj","/loc"]: if win.cur.startswith(i): prefix = "/dev" for i in network_multiuser.get_give_folder_list(win.project, prefix+win.cur): print("\033[1;35m "+i[0]) elif command == "file": n = input("\033[1;33m : ") oscalls.Open(win.project+n) ### EVAL ### elif command == "eval": n = input("\033[1;33m : ") try: print("\033[1;33m"+str(eval(n))) except Exception as e: print("\033[1;31m"+talk.text("failed")+" : "+str(e)) #### NOT IMPLEMENTED YET #### elif command in pm_console.commands: print("\033[1;31m"+talk.text("failed")+" : Not Implemented Yet") ## FAIL ## elif command != "": print("\033[1;31m"+talk.text("failed")) def progress_bar(f): # This function will print out a progress bar similar to # [ ############################.................................. ] bw = w-6 pw = int(round(bw*f)) lw = bw - pw print(" [ "+"#"*pw+"."*lw+" ] ")