diff --git a/studio_console/sc_main.py b/studio_console/sc_main.py new file mode 100644 index 0000000..3a51b56 --- /dev/null +++ b/studio_console/sc_main.py @@ -0,0 +1,483 @@ +# 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+" ] ") + +