# THIS FILE IS A PART OF VCStudio # PYTHON 3 import os import datetime import threading # GTK module ( Graphical interface import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk from gi.repository import GLib from gi.repository import Gdk import cairo # Own modules from settings import settings from settings import oscalls from settings import talk from project_manager import pm_project from studio import analytics from studio import studio_nodes from studio import studio_dialogs from studio import story from studio import analytics from studio import schedule #UI modules from UI import UI_elements from UI import UI_color def layer(win): ########### TIMES RECORDING FOR PERFONMANCE MEASURING ############# stf = datetime.datetime.now() perfStat = [] ################################################################### # Making the layer surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, win.current['w'], win.current['h']) layer = cairo.Context(surface) #text setting layer.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) ########### TIMES RECORDING FOR PERFONMANCE MEASURING ############# fif = datetime.datetime.now() mil = fif - stf perfStat.append([ "Setup", mil.microseconds ]) stf = datetime.datetime.now() ################################################################### UI_color.set(layer, win, "darker_parts") UI_elements.roundrect(layer, win, 50, 50, win.current["w"] - 100, win.current["h"] - 80, 30) # Little verion thing in the bottom corner UI_color.set(layer, win, "testing_banner") layer.set_font_size(15) layer.move_to(win.current["w"]-80, win.current["h"] - 7) layer.show_text(str(win.version)) # Hude analytics button on the top def do(): win.cur = "" win.url = "analytics" UI_elements.roundrect(layer, win, 5, 5, win.current["w"]-(win.current["w"]/3)+45, 40, 10, do, "analytics", talk.text("analytics_tooltip"), url="story_editor") # Progressbar UI_color.set(layer, win, "progress_background") UI_elements.roundrect(layer, win, 55, 15, win.current["w"]/3*2-10, 20, 10) timepassed = 0.0 projectdone = 0.0 try: timepassed = win.analytics["timepassed"] projectdone = win.analytics["fraction"] except: pass # Timepassed UI_color.set(layer, win, "progress_time") UI_elements.roundrect(layer, win, 55, 15, (win.current["w"]/3*2-10)*timepassed, 20, 10) # Project Done UI_color.set(layer, win, "progress_active") UI_elements.roundrect(layer, win, 55, 15, (win.current["w"]/3*2-10)*projectdone, 20, 10) # Separator UI_color.set(layer, win, "node_background") layer.move_to(win.current["w"]/3*2+55, 5) layer.line_to(win.current["w"]/3*2+55, 45) layer.stroke() ############ CURRENT TASK SCHEDULED ############# # FIRST WE NEED TO GET A LIST OF TASKS # This is going to be a simplified version of the same stuff as in the # scheduling. But since we don't care what date we are in and trying to # get the oldest unchecked task. Here we go. schedules = schedule.get_schedules(win.analytics["dates"]) new_date_format = "%Y/%m/%d" today = datetime.datetime.strftime(datetime.datetime.today(), new_date_format) slist = [] for date in schedules: for item in schedules[date]: if win.cur == item or not win.cur: slist.append([date, item, schedules[date][item]]) # Now that we have our list we can start paring it the same way as in the # scheduling. Only removing some unnesesary stuff. foundtask = False taskname = "" taskurl = "" taskcur = "" for entry in slist: if not foundtask: for thing in entry[2]: if thing[0][3] == "[Checked]": continue # We do not care about those who are checked here. elif thing[0][-1] != win.settings["Username"]: continue # We do not care if it's not for us else: foundtask = True # Here we are going to take out some data about this task # First if it's not for today let's get a color for it if entry[0] != "1997/07/30": draw = False if entry[0] < today: UI_color.set(layer, win, "node_badfile") # The Red draw = True elif entry[0] > today: UI_color.set(layer, win, "node_asset") # The Purple draw = True if draw: UI_elements.roundrect(layer, win, win.current["w"]/3*2+60, 5, (win.current["w"]/3-65), 40, 10) name = entry[1][entry[1].rfind("/")+1:] acur = entry[1].replace(name, "").replace("/", "") fullurl = "" for e in thing[0][4][:-1]: fullurl = fullurl+e+" > " if acur in ["chr", "veh", "loc", "obj"]: assetname = talk.text(acur)+": "+name else: assetname = entry[1] # ASSINGING TEXT VALUES taskname = thing[0][4][-1] taskurl = fullurl taskcur = assetname # AND A TINY BUTTON TO ENTER WHAT EVER YOU ARE DOING goto = "analytics" if acur in ["chr", "veh", "loc","obj"]: goto = "assets" itemtype = "assets" elif not acur: itemtype = "files" else: goto = "script" itemtype = "scenes" def do(): win.url = goto win.cur = entry[1] win.current["asset_left_panel"] = "schedule" UI_elements.roundrect(layer, win, win.current["w"]/3*2+60, 5, (win.current["w"]/3-65), 40, 10, button=do) break else: break # Schedule if taskname: UI_elements.image(layer, win, "settings/themes/"\ +win.settings["Theme"]+"/icons/schedule.png", win.current["w"]/3*2+60, 5, 40, 40) UI_color.set(layer, win, "text_normal") layer.set_font_size(20) layer.move_to(win.current["w"]/3*2+120, 25) layer.show_text(taskname) layer.set_font_size(12) layer.move_to(win.current["w"]/3*2+130+len(taskname)*12, 25) layer.show_text(taskurl) layer.set_font_size(12) layer.move_to(win.current["w"]/3*2+120, 40) layer.show_text(taskcur) ########### TIMES RECORDING FOR PERFONMANCE MEASURING ############# fif = datetime.datetime.now() mil = fif - stf perfStat.append([ "Analytics", mil.microseconds ]) stf = datetime.datetime.now() ################################################################### ###### LEFT PANNEL ####### # New Scene def do(): # Okay let's make the adding the scene possible. # First we need to know what scenes are there. So we don't overwrite # any existing scene. scenename = "Scene" count = 2 while scenename in win.story["scenes"]: scenename = "Scene_"+str(count) count = count + 1 # Now that we have an empty name. Let's add a scene. win.story["scenes"][scenename] = { "fraction":0.0, # Percentage "position":[ win.current["mx"]-win.story["camera"][0]-50, win.current["my"]-win.story["camera"][1]-30 ], "size":[100, 60], "parent":"", # For when it's in a Frame (Event) "shots":[[ "text_block",[["text", '']] ]] } # Auto select the new scene win.story["selected"] = [["scene", scenename]] win.current["tool"] = "grab" # A hack I guess. I don't know what I'm doing. I'm trying to force # the motion on click. win.current["LMB"] = [win.current["mx"], win.current["my"], True] # In studio/studio_gtk.py there is a command that recognizes the length # of the LMB. And it's more then 2 it does some magic to make stuff move # without pressing the actuall key. It's slightly too clever even for me # so yeah. UI_elements.roundrect(layer, win, 5, 105, 40, 40, 10, do, "scene_new", talk.text("new_scene_tooltip")+"\n[N]", url="story_editor") # Shortcut if 110 in win.current["keys"] and not win.textactive: do() win.current["keys"] = [] # Link Asset def do(): def after(win, var): print (var) if var: win.story["links"].append([ "asset", var, [ win.current["mx"]-win.story["camera"][0]-75, win.current["my"]-win.story["camera"][1]-75 ], "" # Parent ]) # Now let's select and move the thing win.story["selected"] = [["asset", len(win.story["links"])-1]] win.current["tool"] = "grab" win.current["LMB"] = [win.current["mx"], win.current["my"], True] studio_dialogs.asset_select(win, "new_asset_story", after) UI_elements.roundrect(layer, win, 5, 155, 40, 40, 10, do, "obj_link", talk.text("link_asset_tooltip")+"\n[L]", url="story_editor") # Shortcut if 108 in win.current["keys"] and not win.textactive: do() win.current["keys"] = [] # Link File def do(): def after(win, var): if var: win.story["links"].append([ "file", var, [ win.current["mx"]-win.story["camera"][0]-75, win.current["my"]-win.story["camera"][1]-75 ], "" # Parent ]) # Now let's select and move the thing win.story["selected"] = [["file", len(win.story["links"])-1]] win.current["tool"] = "grab" win.current["LMB"] = [win.current["mx"], win.current["my"], True] studio_dialogs.file_select(win, "new_file_story", after, force=True) UI_elements.roundrect(layer, win, 5, 205, 40, 40, 10, do, "file_link", talk.text("link_file_tooltip")+"\n[I]", url="story_editor") # Shortcut if 105 in win.current["keys"] and not win.textactive: do() win.current["keys"] = [] # Marker def do(): markername = "Marker" count = 2 while markername in win.story["markers"]: markername = "Marker_"+str(count) count = count + 1 win.story["markers"][markername] = [ win.current["mx"]-win.story["camera"][0]+50, win.current["my"]-win.story["camera"][1]-20, "" # Parent ] win.textactive = markername+"_marker" win.text[markername+"_marker"] = { "text" :markername, # Actuall text you are editing. "cursor":[len(str(markername)),len(str(markername))], # Cursor "insert":False, # Whether the insert mode is on "scroll":"markername_scroll" # If multiline. The pointer for the scroll value. } win.story["selected"] = [["marker", markername]] win.current["tool"] = "grab" win.current["LMB"] = [win.current["mx"], win.current["my"], True] UI_elements.roundrect(layer, win, 5, 255, 40, 40, 10, do, "pin", talk.text("marker_tooltip")+"\n[M]", url="story_editor") # Shortcut if 109 in win.current["keys"] and not win.textactive: do() win.current["keys"] = [] if win.story["selected"]: # Event def do(): eventname = "Event" count = 2 while eventname in win.story["events"]: eventname = "Event_"+str(count) count = count + 1 win.story["events"][eventname] = { "position":[0,0], "size":[0,0] } # Even going to delete it self if there will be noone who parenting # it. for thing in win.story["selected"]: if thing[0] == "scene": win.story["scenes"][thing[1]]["parent"] = eventname elif thing[0] in ["file", "asset"]: win.story["links"][thing[1]][3] = eventname elif thing[0] == "marker": win.story["markers"][thing[1]][2] = eventname UI_elements.roundrect(layer, win, 5, 305, 40, 40, 10, do, "event", talk.text("event_tooltip")+"\n[E]", url="story_editor") # Shortcut if 101 in win.current["keys"] and not win.textactive: do() win.current["keys"] = [] # Renders def do(): def after(win, var): pass studio_dialogs.render(win, "current_renders", after) UI_elements.roundrect(layer, win, 5, 405, 40, 40, 10, do, "render", talk.text("render_lists_tooltip"), url="story_editor") # Let's draw on top of this button a little indicator of how many renders # are currently setup. if win.renders: count = str(len(win.renders)) UI_color.set(layer, win, "node_background") UI_elements.roundrect(layer, win, 30, 405, len(count)*12+6, 25, 5) layer.fill() UI_color.set(layer, win, "text_normal") layer.set_font_size(20) layer.move_to(33,425) layer.show_text(count) # Edit Video def do(): def after(win, var): if var: print(var) oscalls.file_open(win, var) studio_dialogs.vse(win, "VSEs", after) UI_elements.roundrect(layer, win, 5, 455, 40, 40, 10, do, "vse", talk.text("vse_tooltip"), url="story_editor") # Bottom # Multiuser def do(): win.url = "multiuser" UI_elements.roundrect(layer, win, 5, win.current["h"]-95, 40, 40, 10, do, "multiuser", talk.text("multiuser_tooltip"), url="story_editor") if win.multiuser["unread"]: count = str(win.multiuser["unread"]) UI_color.set(layer, win, "node_background") UI_elements.roundrect(layer, win, 30, win.current["h"]-100, len(count)*12+6, 25, 5) layer.fill() UI_color.set(layer, win, "text_normal") layer.set_font_size(20) layer.move_to(33,win.current["h"]-83) layer.show_text(count) # Settings def do(): win.url = "settings_layer" UI_elements.roundrect(layer, win, 5, win.current["h"]-45, 40, 40, 10, do, "settings", talk.text("Settings"), url="story_editor") ########### TIMES RECORDING FOR PERFONMANCE MEASURING ############# fif = datetime.datetime.now() mil = fif - stf perfStat.append([ "Left Panel", mil.microseconds ]) stf = datetime.datetime.now() ################################################################### ###### RIGHT PANNEL ####### def select_character(win, var): if var: win.url = "assets" win.cur = var win.current["tool"] = "selection" # Characters def do(): studio_dialogs.asset_select(win, "new_asset_story", select_character, force=True, cur="chr") UI_elements.roundrect(layer, win, win.current["w"]-45, 105, 40, 40, 10, do, "chr", talk.text("chr")+"\n[Shift-C]", url="story_editor") # Shortcut if 67 in win.current["keys"] and not win.textactive: do() win.current["keys"] = [] # Vehicles def do(): studio_dialogs.asset_select(win, "new_asset_story", select_character, force=True, cur="veh") UI_elements.roundrect(layer, win, win.current["w"]-45, 155, 40, 40, 10, do, "veh", talk.text("veh")+"\n[Shift-V]", url="story_editor") # Shortcut if 86 in win.current["keys"] and not win.textactive: do() win.current["keys"] = [] # Locations def do(): studio_dialogs.asset_select(win, "new_asset_story", select_character, force=True, cur="loc") UI_elements.roundrect(layer, win, win.current["w"]-45, 205, 40, 40, 10, do, "loc", talk.text("loc")+"\n[Shift-L]", url="story_editor") # Shortcut if 76 in win.current["keys"] and not win.textactive: do() win.current["keys"] = [] # Other (obj) def do(): studio_dialogs.asset_select(win, "new_asset_story", select_character, force=True, cur="obj") UI_elements.roundrect(layer, win, win.current["w"]-45, 255, 40, 40, 10, do, "obj", talk.text("obj")+"\n[Shift-O]", url="story_editor") # Shortcut if 79 in win.current["keys"] and not win.textactive: do() win.current["keys"] = [] # Sounds / Music def do(): os.system("xdg-open "+win.project+"/mus") UI_elements.roundrect(layer, win, win.current["w"]-45, 355, 40, 40, 10, do, "mus", talk.text("mus"), url="story_editor") # Help def do(): def after(win, var): pass studio_dialogs.help(win, "help", after, SEARCH=talk.text("documentation_story_editor")) UI_elements.roundrect(layer, win, win.current["w"]-45, win.current["h"]-125, 40, 40, 10, do, "question", url="story_editor") # Folder def do(): os.system("xdg-open "+win.project) UI_elements.roundrect(layer, win, win.current["w"]-45, win.current["h"]-75, 40, 40, 10, do, "folder", talk.text("project_folder"), url="story_editor") ########### TIMES RECORDING FOR PERFONMANCE MEASURING ############# fif = datetime.datetime.now() mil = fif - stf perfStat.append([ "Right Pannel", mil.microseconds ]) stf = datetime.datetime.now() ################################################################### ####### NODES ####### # Clipping so it wont draw beyon the frame UI_elements.roundrect(layer, win, 50, 50, win.current["w"] - 100, win.current["h"] - 80, 30, fill=False) layer.clip() # Background Image if os.path.exists(win.project+"/set/banner.png"): UI_elements.image(layer, win, win.project+"/set/banner.png", 50, 50, win.current["w"] - 100, win.current["h"] - 80, cell="background") elif os.path.exists(win.project+"/py_data/banner.png"): UI_elements.image(layer, win, win.project+"/py_data/banner.png", 50, 50, win.current["w"] - 100, win.current["h"] - 80, cell="background") else: UI_elements.image(layer, win, "icon.png", 50, 50, win.current["w"] - 100, win.current["h"] - 80, cell="background") UI_color.set(layer, win, "node_background") layer.rectangle(0,0,win.current["w"], win.current["h"]) layer.fill() ########### TIMES RECORDING FOR PERFONMANCE MEASURING ############# fif = datetime.datetime.now() mil = fif - stf perfStat.append([ "Background Image", mil.microseconds ]) stf = datetime.datetime.now() ################################################################### # You probably intersted where is the scroll function for this part. Well # see there is a thing. It's easier to write one from screach here. Because # you geassed it we are starting to draw story editor. # Let's prepare the camera first. # Animation win.story["camera"][0] = UI_elements.animate("cameraX", win, 0, win.story["camera"][0]) win.story["camera"][1] = UI_elements.animate("cameraY", win, 0, win.story["camera"][1]) cx, cy = win.story["camera"] if win.url == "story_editor": if win.current["MMB"]: win.story["camera"][0] += ( win.current["mx"]-win.previous["mx"]) win.story["camera"][1] += ( win.current["my"]-win.previous["my"]) win.story["camera"][0] -= win.current["scroll"][0]*50 win.story["camera"][1] -= win.current["scroll"][1]*50 if cx != win.story["camera"][0] or cy != win.story["camera"][1]: UI_elements.animate("cameraX", win, win.story["camera"][0], force=True) UI_elements.animate("cameraY", win, win.story["camera"][1], force=True) ########### TIMES RECORDING FOR PERFONMANCE MEASURING ############# fif = datetime.datetime.now() mil = fif - stf perfStat.append([ "Camera position", mil.microseconds ]) stf = datetime.datetime.now() ################################################################### # EVENTS (Frames) try: for event in win.story["events"]: # Loaction sx, sy = win.story["events"][event]["position"] # Scale ssx, ssy = win.story["events"][event]["size"] #Draw studio_nodes.event_node(layer, win, sx, sy, ssx, ssy, name=event) # Let's now check if the event even has anybody inside. It's a bit # not the best way to implement it yet. Because I will need to look # through all items. But we can make it simpler if we find that it has # we can just break out of a thing. found = False for scene in win.story["scenes"]: if event == win.story["scenes"][scene]["parent"]: found = True break if not found: for link in win.story["links"]: if event == link[3]: found = True break if not found: for marker in win.story["markers"]: if event == win.story["markers"][marker][2]: found = True break # If nobody is inside. Delete the bastard. if not found: del win.story["events"][event] except: pass ########### TIMES RECORDING FOR PERFONMANCE MEASURING ############# fif = datetime.datetime.now() mil = fif - stf perfStat.append([ "Events", mil.microseconds ]) stf = datetime.datetime.now() ################################################################### # SCENES try: for scene in win.story["scenes"]: # Loaction sx, sy = win.story["scenes"][scene]["position"] sx = sx + cx sy = sy + cy # Scale ssx, ssy = win.story["scenes"][scene]["size"] #Fraction sf = win.story["scenes"][scene]["fraction"] #Draw studio_nodes.scene_node(layer, win, sx, sy, ssx, ssy, name=scene, fraction=sf) except: pass ########### TIMES RECORDING FOR PERFONMANCE MEASURING ############# fif = datetime.datetime.now() mil = fif - stf perfStat.append([ "Scenes", mil.microseconds ]) stf = datetime.datetime.now() ################################################################### # LINKS (Images, Stuff) for num, link in enumerate(win.story["links"]): linktype = link[0] linkname = link[1] lx = link[2][0] + cx ly = link[2][1] + cy # For the one inside the project. They should be always relative # so even if the project is in a complitely different location # on another machine. Where we have our Multiuser data. It should # be able to load these. if win.project in link[1]: link[1] = link[1].replace(win.project, "") studio_nodes.link_node(layer, win, lx, ly, name=linkname, num=num, linktype=linktype ) ########### TIMES RECORDING FOR PERFONMANCE MEASURING ############# fif = datetime.datetime.now() mil = fif - stf perfStat.append([ "Files / Assets", mil.microseconds ]) stf = datetime.datetime.now() ################################################################### # Let's put in the start and the end nodes. These are drawn on top of # everything. studio_nodes.start_node(layer, win, 60,60,100,40) studio_nodes.end_node(layer, win, win.current["w"] - 160, win.current["h"] - 80, 100,40) ########### TIMES RECORDING FOR PERFONMANCE MEASURING ############# fif = datetime.datetime.now() mil = fif - stf perfStat.append([ "Start / End Nodes", mil.microseconds ]) stf = datetime.datetime.now() ################################################################### # MARKERS try: for marker in win.story["markers"]: mx = win.story["markers"][marker][0] + cx my = win.story["markers"][marker][1] + cy studio_nodes.marker(layer, win, marker, mx, my) except: pass # MARKERS try: for user in win.multiuser["users"]: if user != win.multiuser["userid"]: mx = 0-win.multiuser["users"][user]["camera"][0] +cx + win.current["w"]/2 my = 0-win.multiuser["users"][user]["camera"][1] +cy + win.current["h"]/2 studio_nodes.user(layer, win, win.multiuser["users"][user]["username"], mx, my) except Exception as e: print(e, "USER RENDERING") ########### TIMES RECORDING FOR PERFONMANCE MEASURING ############# fif = datetime.datetime.now() mil = fif - stf perfStat.append([ "Markers", mil.microseconds ]) stf = datetime.datetime.now() ################################################################### # In case there is a selection bug if not win.story["selected"] and win.current["tool"] != "connect": win.current["tool"] = "selection" # Selector visualization if win.current["LMB"] and win.current["tool"] == "selection" and win.url == "story_editor": # Draw selection box UI_color.set(layer, win, "progress_background") layer.rectangle( win.current["mx"], win.current["my"], win.current["LMB"][0] - win.current["mx"], win.current["LMB"][1] - win.current["my"] ) layer.stroke() # Now let's draw the cool AF multi selection zone thingy # Draw selection box if len(win.story["selected"]) > 1 and win.current["tool"] == "selection": UI_color.set(layer, win, "progress_background") layer.rectangle( win.szone[0][0]-10, win.szone[0][1]-10, win.szone[1][0]+20, win.szone[1][1]+20 ) layer.stroke() # Now I want to make a tiny widget that will resize the stuff. if win.story["selected"]: if win.current["tool"] == "selection": draw_circle = True if len(win.story["selected"]) == 1: if win.story["selected"][0][0] != "scene": draw_circle = False if draw_circle: UI_color.set(layer, win, "node_badfile") UI_elements.roundrect(layer, win, win.szone[0][0]+win.szone[1][0], win.szone[0][1]+win.szone[1][1], 0, 0, 10) UI_color.set(layer, win, "progress_background") UI_elements.roundrect(layer, win, win.szone[0][0]+win.szone[1][0], win.szone[0][1]+win.szone[1][1], 0, 0, 10, fill=False) layer.stroke() elif win.current["tool"] == "scale": UI_color.set(layer, win, "node_badfile") UI_elements.roundrect(layer, win, win.current["mx"]-10, win.current["my"]-10, 0, 0, 10) UI_color.set(layer, win, "progress_background") UI_elements.roundrect(layer, win, win.current["mx"]-10, win.current["my"]-10, 0, 0, 10, fill=False) layer.stroke() if int(win.current["mx"]) in range(int(win.szone[0][0]+win.szone[1][0]), int(win.szone[0][0]+win.szone[1][0]+20))\ and int(win.current["my"]) in range(int(win.szone[0][1]+win.szone[1][1]), int(win.szone[0][1]+win.szone[1][1]+20))\ and win.current["tool"] == "selection": UI_color.set(layer, win, "text_normal") UI_elements.roundrect(layer, win, win.szone[0][0]+win.szone[1][0], win.szone[0][1]+win.szone[1][1], 0, 0, 10, fill=False) layer.stroke() if win.current["LMB"] and not win.previous["LMB"]: win.current["tool"] = "scale" if win.current["tool"] == "scale" and not win.current["LMB"]: win.current["tool"] = "selection" # Canceling seletion. I move it here so it would not interfire with the # the rest of the program. if win.current["LMB"] and win.current["tool"] == "selection" and win.url == "story_editor": # Undo selection if int(win.current["LMB"][0] - win.current["mx"]) in range(-10, 10)\ and int(win.current["LMB"][1] - win.current["my"])in range(-10, 10)\ and int(win.current["mx"]) in range(50, int(win.current["w"]-50)) \ and int(win.current["my"]) in range(50, int(win.current["h"]-30))\ and 65505 not in win.current["keys"]: win.story["selected"] = [] win.textactive = "" # Let's draw the line while connecting 2 scenes together. if win.current["tool"] == "connect": if not win.current["LMB"]: win.current["tool"] = "selection" fr = win.current["draw_dot"] if type(fr) == list: fr = fr[0]+":"+fr[1] try: UI_color.set(layer, win, "node_script") layer.move_to( win.out_dots[fr][0], win.out_dots[fr][1] ) layer.line_to(win.current["mx"], win.current["my"]) layer.stroke() except: pass ########### TIMES RECORDING FOR PERFONMANCE MEASURING ############# fif = datetime.datetime.now() mil = fif - stf perfStat.append([ "Selection", mil.microseconds ]) stf = datetime.datetime.now() ################################################################### # The undo history is quite a new adition so the limit setting might # not exists. So let's make it if so. if "Undo_Limit" not in win.settings: win.settings["Undo_Limit"] = 32 settings.write("Undo_Limit", 32) # Save story. I'm going to do it the same way as in the old Blender-Organizer if win.url == "story_editor": savenow = False if win.previous["LMB"] and not win.current["LMB"]: savenow = True elif win.previous["RMB"] and not win.current["RMB"]: savenow = True elif win.previous["MMB"] and not win.current["MMB"]: savenow = True elif win.previous["keys"] and not win.current["keys"]: savenow = True if savenow: # Now let's run the history record. story.undo_record(win) story.save(win.project, win.story) analytics.save(win.project, win.analytics) # Need to reload the story to reload the fractions of the scenes. win.story = story.load(win.project) # Multiuser sycning win.multiuser["request"] = "story" ########### TIMES RECORDING FOR PERFONMANCE MEASURING ############# fif = datetime.datetime.now() mil = fif - stf perfStat.append([ "File Saving", mil.microseconds ]) stf = datetime.datetime.now() ################################################################### # To selected if 65454 in win.current["keys"] and win.story["selected"] and not win.textactive: nex = cx-win.szone[0][0] - win.szone[1][0]/2 + win.current["w"]/2 ney = cy-win.szone[0][1] - win.szone[1][1]/2 + win.current["h"]/2 UI_elements.animate("cameraX", win, win.story["camera"][0],nex, force=True) UI_elements.animate("cameraY", win, win.story["camera"][1],ney, force=True) # Undo if 65507 in win.current["keys"] and 122 in win.current["keys"] and not win.textactive: story.undo(win) win.current["keys"] = [] # Redo if 65507 in win.current["keys"] and 121 in win.current["keys"] and not win.textactive: story.redo(win) win.current["keys"] = [] # Grab if 103 in win.current["keys"] and win.story["selected"] and not win.textactive: win.current["tool"] = "grab" win.current["LMB"] = [win.current["mx"], win.current["my"], True] # Scale if 115 in win.current["keys"] and win.story["selected"] and not win.textactive: win.current["tool"] = "scale" win.current["LMB"] = [win.current["mx"], win.current["my"], True] # Deletion if 65535 in win.current["keys"] and win.current["tool"] == "selection"\ and win.url == "story_editor" and win.story["selected"] and not win.textactive: win.url = "story_deletion_dialog" ########### TIMES RECORDING FOR PERFONMANCE MEASURING ############# fif = datetime.datetime.now() mil = fif - stf perfStat.append([ "Short Cuts", mil.microseconds ]) stf = datetime.datetime.now() ################################################################### ############### PERFORMCE TESTING GROUND ############## if win.current["testing"]: h = win.current["h"]+200 w = win.current["w"] UI_color.set(layer, win, "darker_parts") UI_elements.roundrect(layer, win,100, h-(len(perfStat)*15)-30-300, 500,len(perfStat)*15+30, 10) l = 0 s = 0 for i in perfStat: if int(i[1]) > l: l = int(i[1]) s = s + int(i[1]) for n, i in enumerate(perfStat): #UI_color.set(layer, win, "progress_background") #UI_elements.roundrect(layer, win, 110 + 270, h-(len(perfStat)*15)-20+10+15*n-300, 200,10, 5) layer.set_source_rgb(1,1,1) if int(i[1]) == l: layer.set_source_rgb(1,0,0) elif int(i[1]) < 1000: layer.set_source_rgb(0,1,0) layer.set_font_size(10) layer.move_to( 110, h-(len(perfStat)*15)+15*n-300) p = float(i[1]) / s *100 layer.show_text(str(i[0])+" - "+str(i[1])+" MCRS "+str(int(round(p)))+"%") #UI_color.set(layer, win, "progress_active") UI_elements.roundrect(layer, win, 110 + 270, h-(len(perfStat)*15)-20+10+15*n-300, int(round(p))*2,10, 5) return surface