Jeison Yehuda Amihud (Blender Dumbass)
d067b6c64c
These are the UI and studio system part of The implementation
1264 lines
38 KiB
Python
1264 lines
38 KiB
Python
# 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
|
|
|