Blender-Pipeline/studio/studio_nodes.py
Jeison Yehuda Amihud (Blender Dumbass) 92533b7236 Cursors
Cursors change based on content
2021-01-11 20:52:00 +00:00

1559 lines
52 KiB
Python

# THIS FILE IS A PART OF VCStudio
# PYTHON 3
import os
import datetime
# GTK module ( Graphical interface
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import cairo
# Own modules
from settings import settings
from settings import talk
from settings import fileformats
from settings import oscalls
# Studio
from studio import story
from studio import analytics
from studio import studio_dialogs
from studio import checklist
# UI modules
from UI import UI_testing
from UI import UI_color
from UI import UI_elements
from UI import UI_math
def node_dot(layer, win, x, y, direction="in", entry="end"):
# This function will draw a dot to which various nodes are connected. And
# from which connections going off.
# This is a very alpha version of the dot thing
raw_entry = entry
if type(entry) == list:
entry = entry[0]+":"+entry[1]
if entry.startswith("scene:") or entry in ["start", "end"]:
UI_color.set(layer, win, "node_script")
elif entry.startswith("blend:"):
UI_color.set(layer, win, "node_blendfile")
else:
UI_color.set(layer, win, "node_imagefile")
UI_elements.roundrect(layer, win,
x,
y,
0,
0,
6)
if int(win.current["mx"]) in range(int(x), int(x+12))\
and int(win.current["my"]) in range(int(y), int(y+12)):
UI_color.set(layer, win, "text_normal")
UI_elements.roundrect(layer, win,
x,
y,
0,
0,
6,
fill=False)
layer.stroke()
win.current["cursor"] = win.cursors["arrow"]
# Start drawing the line
if not win.previous["LMB"] and win.current["LMB"] and direction != "in":
# Out point
win.current["tool"] = "connect"
win.current["draw_dot"] = raw_entry
elif not win.previous["LMB"] and win.current["LMB"] and direction == "in" and win.current["tool"] != "connect":
# Take out of the in point
try:
found = False
win.current["tool"] = "connect"
for arrow in win.story["arrows"]:
if raw_entry == arrow[1]:
win.current["draw_dot"] = arrow[0]#.copy()
found = arrow
break
if found:
win.story["arrows"].remove(found)
else:
win.current["draw_dot"] = "end"
except:
pass
# Refrashing analytics
story.save(win.project, win.story)
win.analytics = analytics.load(win.project)
analytics.save(win.project, win.analytics)
# Connecting the line
if win.current["tool"] == "connect" and direction == "in" and not win.current["LMB"]:
# Connecting the scenes together
if raw_entry[0] not in ["file", "blend"] and win.current["draw_dot"][0] not in ["file", "blend"]:
new_arrow = [
win.current["draw_dot"],
raw_entry
]
if new_arrow not in win.story["arrows"]:
win.story["arrows"].append(new_arrow)
# Copying images to places
elif raw_entry[0] == "asset" and win.current["draw_dot"][0] == "file":
new = oscalls.copy_file(
win,
win.current["draw_dot"][1],
"dev"+raw_entry[1])
win.story["links"].append([
"file", new, [
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]
elif raw_entry[0] == "blend" and win.current["draw_dot"][0] == "blend":
new = oscalls.copy_file(
win,
win.current["draw_dot"][1],
"dev"+raw_entry[1])
win.story["links"].append([
"file", new, [
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]
UI_math.filter_arrows(win)
# Refrashing analytics
story.save(win.project, win.story)
win.analytics = analytics.load(win.project)
analytics.save(win.project, win.analytics)
if direction != "in":
win.out_dots[entry] = [x+6, y+6]
elif entry.startswith("scene:") or entry in ["start", "end"]:
for arrow in win.story["arrows"]:
if raw_entry == arrow[1]:
fr = arrow[0]
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(x+6, y+6)
layer.stroke()
except:
pass
elif entry.startswith("asset:"):
for link in win.story["links"]:
if link[0] == "file":
link = link[1]
fr = "file:"+link
if entry[entry.find(":")+1:] in link:
try:
UI_color.set(layer, win, "node_imagefile")
layer.move_to(
win.out_dots[fr][0],
win.out_dots[fr][1]
)
layer.line_to(x+6, y+6)
layer.stroke()
except:
pass
elif entry.startswith("blend:"):
for link in win.story["links"]:
if link[0] == "file":
link = link[1]
fr = "blend:"+link
if entry[entry.find(":")+1:]+"/" in link or entry[entry.find(":")+1:]+"." in link:
try:
UI_color.set(layer, win, "node_blendfile")
layer.move_to(
win.out_dots[fr][0],
win.out_dots[fr][1]
)
layer.line_to(x+6, y+6)
layer.stroke()
except:
pass
def start_node(outlayer, win, x, y, width, height):
# This function will draw a start node in the top left corner of the story
# editor. This is where the story begins.
# Making the layer
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
layer = cairo.Context(surface)
# Clip
UI_elements.roundrect(layer, win,
0,
0,
width,
height,
10,
fill=False)
layer.clip()
# Background
UI_color.set(layer, win, "dark_overdrop")
layer.rectangle(0,0,width, height)
layer.fill()
# top banner
UI_color.set(layer, win, "node_badfile")
layer.rectangle(0,0,width, 20)
layer.fill()
# Text saying START
UI_color.set(layer, win, "text_normal")
layer.set_font_size(15)
layer.move_to(width/2-len(talk.text("Start"))*9/2,15)
layer.show_text(talk.text("Start"))
# Outputting the layer
outlayer.set_source_surface(surface, x, y)
outlayer.paint()
# Dot
node_dot(outlayer, win, x+width-7, y+height-12, direction="out", entry="start")
def end_node(outlayer, win, x, y, width, height):
# This function will draw a end node in the bottom right corner of the story
# editor. This is where the story ends.
# Making the layer
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
layer = cairo.Context(surface)
# Clip
UI_elements.roundrect(layer, win,
0,
0,
width,
height,
10,
fill=False)
layer.clip()
# Background
UI_color.set(layer, win, "dark_overdrop")
layer.rectangle(0,0,width, height)
layer.fill()
# top banner
UI_color.set(layer, win, "node_badfile")
layer.rectangle(0,0,width, 20)
layer.fill()
# Text saying END
UI_color.set(layer, win, "text_normal")
layer.set_font_size(15)
layer.move_to(width/2-len(talk.text("End"))*9/2,15)
layer.show_text(talk.text("End"))
# Outputting the layer
outlayer.set_source_surface(surface, x, y)
outlayer.paint()
# Dot
node_dot(outlayer, win, x-2, y+height-12)
def scene_node(outlayer, win, x, y, width, height, name="Unknown", fraction=0.0):
# This function will draw scene nodes.
entry = ['scene', name]
width = max(width,20)
height = max(height,20)
doparent = True
if int(x) in range(int(0-width), int(win.current["w"]))\
and int(y) in range(int(0-height), int(win.current["h"])):
# Making the layer
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
layer = cairo.Context(surface)
selected = False
if win.url == "story_editor"\
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)):
if win.current["LMB"] and entry in win.story["selected"]:
if int(win.current["LMB"][0]) in range(int(x), int(x+width))\
and int(win.current["LMB"][1]) in range(int(y), int(y+height))\
and win.current["tool"] == "selection":
win.current["tool"] = "grab"
win.story["active"] = entry
# Launching the item
if int(win.current["mx"]) in range(int(x), int(x+width))\
and int(win.current["my"]) in range(int(y), int(y+height)):
win.current["cursor"] = win.cursors["hand"]
if not win.current["LMB"] and win.previous["LMB"]\
and entry in win.story["selected"]\
and int(win.current["mx"]) == int(win.previous["LMB"][0])\
and int(win.current["my"]) == int(win.previous["LMB"][1]):
win.url = "script"
win.cur = "/"+name
win.current["tool"] = "selection"
if win.current["LMB"] and win.current["tool"] == "selection":
# If mouse over. But way more complex. Because we might select more then
# 1 scene at ones.
mx = win.current["mx"]
my = win.current["my"]
pmx = win.current["LMB"][0]
pmy = win.current["LMB"][1]
intersect = UI_math.rectangle_overlap(
[mx, my, pmx-mx, pmy-my],
[x,y,width, height])
# Now let's make a higlight
if intersect:
selected = True
elif win.previous["LMB"] and win.previous["tool"] == "selection":
# If you released the mouse while selecting. Then do selecting. I guess.
mx = win.previous["mx"]
my = win.previous["my"]
pmx = win.previous["LMB"][0]
pmy = win.previous["LMB"][1]
intersect = UI_math.rectangle_overlap(
[mx, my, pmx-mx, pmy-my],
[x,y,width, height])
# Now let's make a selection
if intersect:
if entry not in win.story["selected"]:
win.story["selected"].append(entry)
if win.story["active"] not in win.story["selected"]:
win.story["active"] = entry
if entry in win.story["selected"]:
selected = True
if selected:
if win.current["tool"] == "selection":
UI_math.rectangle_surround(win, "selection",
win.szone[0], win.szone[1],
[x,y], [width, height]
)
# Now let's make the stratching thing do it's stratching. It's the
# circle in the bottom, right corner of the selection.
if win.current["tool"] == "scale" and win.current["LMB"] and win.previous["LMB"]:
# let's get the points of the selection zone.
zx = win.szone[0][0]
zy = win.szone[0][1]
zsx = win.previous["LMB"][0]
zsy = win.previous["LMB"][1]
if win.current["mx"] > zx and win.current["my"] > zy:
# now let's get the motion fraction.
mvx = (x - zx) / (zsx - zx)
mvy = (y - zy) / (zsy - zy)
svx = (win.current["mx"]- zx) / (win.previous["mx"]-zx)
svy = (win.current["my"]- zy) / (win.previous["my"]-zy)
# now let's apply these
win.story["scenes"][name]["position"][0]\
+= (win.current["mx"] - win.previous["mx"])*mvx
win.story["scenes"][name]["position"][1]\
+= (win.current["my"] - win.previous["my"])*mvy
win.story["scenes"][name]["size"][0]\
= max(win.story["scenes"][name]["size"][0] * svx, 40)
win.story["scenes"][name]["size"][1]\
= max(win.story["scenes"][name]["size"][1] * svy, 40)
# Now let's do the simple grab tool.
if win.current["tool"] == "grab":
# If you press shift, You take things out of events
if 65505 in win.current["keys"]:
doparent = False
try:
if win.current["LMB"]:
x += win.current["mx"] - win.current["LMB"][0]
y += win.current["my"] - win.current["LMB"][1]
elif win.previous["LMB"]:
win.story["scenes"][name]["position"][0]\
+= win.previous["mx"] - win.previous["LMB"][0]
win.story["scenes"][name]["position"][1]\
+= win.previous["my"] - win.previous["LMB"][1]
x += win.previous["mx"] - win.previous["LMB"][0]
y += win.previous["my"] - win.previous["LMB"][1]
# Parent removing / assigning
if not doparent:
win.story["scenes"][name]["parent"] = ""
elif not win.story["scenes"][name]["parent"]:
for event in win.story["events"]:
mx, my = win.story["events"][event]["position"]
pmx, pmy = win.story["events"][event]["size"]
if UI_math.rectangle_overlap(
[mx, my, pmx, pmy],
[x,y,width, height]):
win.story["scenes"][name]["parent"] = event
break
elif win.current["tool"] != "connect":
win.current["tool"] = "selection"
except:
raise()
# The selected outline
UI_color.set(outlayer, win, "progress_background")
if win.story["active"] == entry:
UI_color.set(outlayer, win, "text_normal")
outlayer.set_line_width(4)
UI_elements.roundrect(outlayer, win,
x,
y,
width,
height,
10,
fill=False)
outlayer.stroke()
outlayer.set_line_width(2)
# Clip
UI_elements.roundrect(layer, win,
0,
0,
width,
height,
10,
fill=False)
layer.clip()
# Tooltip
if int(win.current["mx"]) in range(int(x), int(x+width))\
and int(win.current["my"]) in range(int(y), int(y+height)):
UI_elements.tooltip(win, name)
# Background
UI_color.set(layer, win, "dark_overdrop")
layer.rectangle(0,0,width, height)
layer.fill()
# top banner
UI_color.set(layer, win, "node_script")
layer.rectangle(0,0,width, 20)
layer.fill()
# Text saying The name of the scene
UI_color.set(layer, win, "text_normal")
layer.set_font_size(15)
layer.move_to(15,15)
layer.show_text(name)
# Fraction
UI_color.set(layer, win, "progress_background")
UI_elements.roundrect(layer, win,
10,
height-20,
width-20,
0,
5)
UI_color.set(layer, win, "progress_active")
UI_elements.roundrect(layer, win,
10,
height-20,
(width-20)*fraction,
0,
5)
# Outputting the layer
outlayer.set_source_surface(surface, x, y)
outlayer.paint()
# In case there is a parent event in the scene.
if win.story["scenes"][name]["parent"] and doparent:
parent = win.story["scenes"][name]["parent"]
UI_math.rectangle_surround(win, parent,
win.story["events"][parent]["position"],
win.story["events"][parent]["size"],
[x,y], [width, height]
)
# Dots
node_dot(outlayer, win, x-5, y+25, entry=entry)
node_dot(outlayer, win, x+width-7, y+25, direction="out",entry=entry)
def event_node(outlayer, win, x, y, width, height, name="Unknown"):
# This function draws events.
x = x - 20
y = y - 20
width = width + 40
height = height + 40
entry = ['event', name]
# Making sure the size is alright
if width < 100:
width = 100
if height < 100:
height = 100
# Making the layer
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
layer = cairo.Context(surface)
# Clip
UI_elements.roundrect(layer, win,
0,
0,
width,
height,
10,
fill=False)
layer.clip()
# Background
UI_color.set(layer, win, "dark_overdrop")
layer.rectangle(0,0,width, height)
layer.fill()
# Here should be the event name thing. But I thought that it wasn't
# important for a simple framing thing.
# Outputting the layer
outlayer.set_source_surface(surface, x, y)
outlayer.paint()
def link_node(outlayer, win, x, y, width=150, height=150, name="", num=0, linktype="file"):
filetype = ""
# This node will output links to files.
if linktype == "asset":
width += 50
height += 80
else:
# Let's find out what type of file is it.
for f in fileformats.images:
if name.endswith(f):
filetype = "image"
if not filetype:
for f in fileformats.videos:
if name.endswith(f):
filetype = "video"
doparent = True
if int(x) in range(int(0-width), int(win.current["w"]))\
and int(y) in range(int(0-height), int(win.current["h"])):
# Making the layer
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
layer = cairo.Context(surface)
entry = [linktype, num]
selected = False
if win.url == "story_editor"\
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)):
if win.current["LMB"] and entry in win.story["selected"]:
if int(win.current["LMB"][0]) in range(int(x), int(x+width))\
and int(win.current["LMB"][1]) in range(int(y), int(y+height))\
and win.current["tool"] == "selection":
win.current["tool"] = "grab"
win.story["active"] = entry
# Launching the item
if int(win.current["mx"]) in range(int(x), int(x+width))\
and int(win.current["my"]) in range(int(y), int(y+height)):
win.current["cursor"] = win.cursors["hand"]
if not win.current["LMB"] and win.previous["LMB"]\
and entry in win.story["selected"]\
and int(win.current["mx"]) == int(win.previous["LMB"][0])\
and int(win.current["my"]) == int(win.previous["LMB"][1]):
if linktype == "file":
oscalls.file_open(win, name)
elif int(win.current["mx"]) > x+40: # This is a hack. But whatever.
win.url = "assets"
win.cur = name
win.current["tool"] = "selection"
win.previous["LMB"] = False
if win.current["LMB"] and win.current["tool"] == "selection":
# If mouse over. But way more complex. Because we might select more then
# 1 scene at ones.
mx = win.current["mx"]
my = win.current["my"]
pmx = win.current["LMB"][0]
pmy = win.current["LMB"][1]
intersect = UI_math.rectangle_overlap(
[mx, my, pmx-mx, pmy-my],
[x,y,width, height])
# Now let's make a higlight
if intersect:
selected = True
elif win.previous["LMB"] and win.previous["tool"] == "selection":
# If you released the mouse while selecting. Then do selecting. I guess.
mx = win.previous["mx"]
my = win.previous["my"]
pmx = win.previous["LMB"][0]
pmy = win.previous["LMB"][1]
intersect = UI_math.rectangle_overlap(
[mx, my, pmx-mx, pmy-my],
[x,y,width, height])
# Now let's make a selection
if intersect:
if entry not in win.story["selected"]:
win.story["selected"].append(entry)
# Making it active.
if win.story["active"] not in win.story["selected"]:
win.story["active"] = entry
if entry in win.story["selected"]:
selected = True
if selected:
if win.current["tool"] == "selection":
UI_math.rectangle_surround(win, "selection",
win.szone[0], win.szone[1],
[x,y], [width, height]
)
# Now let's make the stratching thing do it's stratching. It's the
# circle in the bottom, right corner of the selection.
if win.current["tool"] == "scale" and win.current["LMB"] and win.previous["LMB"]:
# let's get the points of the selection zone.
zx = win.szone[0][0]
zy = win.szone[0][1]
zsx = win.previous["LMB"][0]
zsy = win.previous["LMB"][1]
if win.current["mx"] > zx and win.current["my"] > zy:
# now let's get the motion fraction.
mvx = (x - zx) / (zsx - zx)
mvy = (y - zy) / (zsy - zy)
# now let's apply these
win.story["links"][num][2][0]\
+= (win.current["mx"] - win.previous["mx"])*mvx
win.story["links"][num][2][1]\
+= (win.current["my"] - win.previous["my"])*mvy
if win.current["tool"] == "grab":
# If you press shift, You take things out of events
if 65505 in win.current["keys"]:
doparent = False
try:
if win.current["LMB"]:
x += win.current["mx"] - win.current["LMB"][0]
y += win.current["my"] - win.current["LMB"][1]
elif win.previous["LMB"]:
win.story["links"][num][2][0]\
+= win.previous["mx"] - win.previous["LMB"][0]
win.story["links"][num][2][1]\
+= win.previous["my"] - win.previous["LMB"][1]
x += win.previous["mx"] - win.previous["LMB"][0]
y += win.previous["my"] - win.previous["LMB"][1]
# Parent removing / assigning
if not doparent:
win.story["links"][num][3] = ""
elif not win.story["links"][num][3]:
for event in win.story["events"]:
mx, my = win.story["events"][event]["position"]
pmx, pmy = win.story["events"][event]["size"]
if UI_math.rectangle_overlap(
[mx, my, pmx, pmy],
[x,y,width, height]):
win.story["links"][num][3] = event
break
elif win.current["tool"] != "connect":
win.current["tool"] = "selection"
except:
raise()
# The selected outline
UI_color.set(outlayer, win, "progress_background")
if win.story["active"] == entry:
UI_color.set(outlayer, win, "text_normal")
outlayer.set_line_width(4)
UI_elements.roundrect(outlayer, win,
x,
y,
width,
height,
10,
fill=False)
outlayer.stroke()
outlayer.set_line_width(2)
# Clip
UI_elements.roundrect(layer, win,
0,
0,
width,
height,
10,
fill=False)
layer.clip()
# Background
UI_color.set(layer, win, "dark_overdrop")
layer.rectangle(0,0,width, height)
layer.fill()
if linktype == "asset":
assettype = name[:name.rfind("/")].replace("/", "")
if os.path.exists(win.project+"/dev"+name+"/renders/Preview.png"):
UI_elements.image(layer, win,
win.project+"/dev"+name+"/renders/Preview.png",
0, 0, width, height, cell="story_asset_previews")
elif os.path.exists(win.project+"/dev"+name+"/renders/Preview.jpg"):
UI_elements.image(layer, win,
win.project+"/dev"+name+"/renders/Preview.jpg",
0, 0, width, height, cell="story_asset_previews")
else:
UI_elements.image(layer, win,
"settings/themes/"+win.settings["Theme"]+"/icons/"+assettype+".png",
width/2-20, height/2-20, 40, 40)
# Here I want to add some buttons for accessing the various folder of
# the asset. And also to link stuff into those folders using nodes.
if int(win.current["mx"]) in range(int(x), int(x+width))\
and int(win.current["my"]) in range(int(y), int(y+height)):
# Darkening thing.
UI_color.set(layer, win, "dark_overdrop")
layer.rectangle(0,0,50, height)
layer.fill()
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
],
""
])
# 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]
# Blendfiles
def do():
studio_dialogs.file_select(win, name+"_blends", after, force=True,
IMAGE=False, BLEND=True, VIDEO=False, FILE=False, CHR=True, VEH=True,
LOC=True, OBJ=True, RND=False, FOLDER=False, SEARCH=name)
UI_elements.roundrect(layer, win,
5,
25,
40,
40,
10,
do,
"blender",
talk.text("blend_files_folder"),
url="story_editor",
offset=[x,y])
# References
def do():
studio_dialogs.file_select(win, name+"_reference", after, force=True,
IMAGE=True, BLEND=False, VIDEO=True, FILE=False, CHR=True, VEH=True,
LOC=True, OBJ=True, RND=False, FOLDER=False, SEARCH=name+"/reference")
UI_elements.roundrect(layer, win,
5,
75,
40,
40,
10,
do,
"idea",
talk.text("reference_folder"),
url="story_editor",
offset=[x,y])
# Textures
def do():
studio_dialogs.file_select(win, name+"_textures", after, force=True,
IMAGE=True, BLEND=False, VIDEO=True, FILE=False, CHR=True, VEH=True,
LOC=True, OBJ=True, RND=False, FOLDER=False, SEARCH=name+"/tex")
UI_elements.roundrect(layer, win,
5,
125,
40,
40,
10,
do,
"texture",
talk.text("tex_folder"),
url="story_editor",
offset=[x,y])
# Renders
def do():
studio_dialogs.file_select(win, name+"_renders", after, force=True,
IMAGE=True, BLEND=False, VIDEO=True, FILE=False, CHR=True, VEH=True,
LOC=True, OBJ=True, RND=False, FOLDER=False, SEARCH=name+"/renders")
UI_elements.roundrect(layer, win,
5,
175,
40,
40,
10,
do,
"render",
talk.text("renders_folder"),
url="story_editor",
offset=[x,y])
# Fraction
fraction = story.get_asset_data(win, name)["fraction"]
UI_color.set(layer, win, "progress_background")
UI_elements.roundrect(layer, win,
65,
height-20,
width-85,
0,
5)
UI_color.set(layer, win, "progress_active")
UI_elements.roundrect(layer, win,
65,
height-20,
(width-85)*fraction,
0,
5)
else:
# Fraction
fraction = story.get_asset_data(win, name)["fraction"]
UI_color.set(layer, win, "progress_background")
UI_elements.roundrect(layer, win,
10,
height-20,
width-20,
0,
5)
UI_color.set(layer, win, "progress_active")
UI_elements.roundrect(layer, win,
10,
height-20,
(width-20)*fraction,
0,
5)
UI_color.set(layer, win, "node_asset")
# Tooltip
if int(win.current["mx"]) in range(int(x+40), int(x+width))\
and int(win.current["my"]) in range(int(y), int(y+height)):
UI_elements.tooltip(win, name)
else:
if os.path.exists(win.project+"/"+name):
UI_elements.image(layer, win,
win.project+"/"+name,
0, 0, width, height)
else:
UI_elements.image(layer, win,
name,
0, 0, width, height)
if name.endswith(".progress"):
fraction = checklist.get_fraction(win, name)
UI_color.set(layer, win, "progress_background")
UI_elements.roundrect(layer, win,
10,
height-20,
width-20,
0,
5)
UI_color.set(layer, win, "progress_active")
UI_elements.roundrect(layer, win,
10,
height-20,
(width-20)*fraction,
0,
5)
if name.endswith(".blend"):
UI_color.set(layer, win, "node_blendfile")
if "ast/" in name:
UI_color.set(layer, win, "node_asset")
elif filetype == "image":
UI_color.set(layer, win, "node_imagefile")
elif filetype == "video":
UI_color.set(layer, win, "node_videofile")
else:
UI_color.set(layer, win, "node_script")
# Tooltip
if int(win.current["mx"]) in range(int(x), int(x+width))\
and int(win.current["my"]) in range(int(y), int(y+height)):
UI_elements.tooltip(win, name)
# top banner
layer.rectangle(0,0,width, 20)
layer.fill()
# Text saying The name of the event
UI_color.set(layer, win, "text_normal")
layer.set_font_size(15)
layer.move_to(15,15)
layer.show_text(name[name.rfind("/")+1:])
# Outputting the layer
outlayer.set_source_surface(surface, x, y)
outlayer.paint()
if linktype == "asset":
node_dot(outlayer, win, x-6, y+25+14, entry=["blend", name])
node_dot(outlayer, win, x-6, y+75+14, entry=["asset", name+"/reference"])
node_dot(outlayer, win, x-6, y+125+14, entry=["asset", name+"/tex"])
node_dot(outlayer, win, x-6, y+175+14, entry=["asset", name+"/renders"])
else:
if name.endswith(".blend"):
node_dot(outlayer, win, x+width-6, y+120, entry=["blend", name], direction="out")
elif filetype in ["image", "video"]:
node_dot(outlayer, win, x+width-6, y+120, entry=["file", name], direction="out")
else: # If not in the frame
if linktype == "file":
try:
if name.endswith(".blend"):
del win.out_dots["blend:"+name]
else:
del win.out_dots["file:"+name]
except:
pass
# In case there is a parent event in the scene.
if win.story["links"][num][3] and doparent:
parent = win.story["links"][num][3]
UI_math.rectangle_surround(win, parent,
win.story["events"][parent]["position"],
win.story["events"][parent]["size"],
[x,y], [width, height]
)
def marker(outlayer, win, name ,x, y ):
# This function will draw markers to the screen. They are like shortcuts in
# a story editor space.
if int(x) in range(int(60), int(win.current["w"]-100))\
and int(y) in range(int(60), int(win.current["h"]-80)):
width = 200
height = 40
inscreen = True
else:
x = min(max(x, 60), win.current["w"]-100)
y = min(max(y, 60), win.current["h"]-80)
width = 40
height = 40
inscreen = False
# Making the layer
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
layer = cairo.Context(surface)
entry = ["marker", name]
if inscreen:
doparent = True
selected = False
if win.url == "story_editor"\
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)):
if win.current["LMB"] and entry in win.story["selected"]:
if int(win.current["LMB"][0]) in range(int(x), int(x+40))\
and int(win.current["LMB"][1]) in range(int(y), int(y+height))\
and win.current["tool"] == "selection":
win.current["tool"] = "grab"
win.story["active"] = entry
if win.current["LMB"] and win.current["tool"] == "selection":
# If mouse over. But way more complex. Because we might select more then
# 1 scene at ones.
mx = win.current["mx"]
my = win.current["my"]
pmx = win.current["LMB"][0]
pmy = win.current["LMB"][1]
intersect = UI_math.rectangle_overlap(
[mx, my, pmx-mx, pmy-my],
[x,y,width, height])
# Now let's make a higlight
if intersect:
selected = True
elif win.previous["LMB"] and win.previous["tool"] == "selection":
# If you released the mouse while selecting. Then do selecting. I guess.
mx = win.previous["mx"]
my = win.previous["my"]
pmx = win.previous["LMB"][0]
pmy = win.previous["LMB"][1]
intersect = UI_math.rectangle_overlap(
[mx, my, pmx-mx, pmy-my],
[x,y,width, height])
# Now let's make a selection
if intersect:
if entry not in win.story["selected"]:
win.story["selected"].append(entry)
# Making it active.
if win.story["active"] not in win.story["selected"]:
win.story["active"] = entry
if entry in win.story["selected"]:
selected = True
if selected:
if win.current["tool"] == "selection":
UI_math.rectangle_surround(win, "selection",
win.szone[0], win.szone[1],
[x,y], [width, height]
)
# Now let's make the stratching thing do it's stratching. It's the
# circle in the bottom, right corner of the selection.
if win.current["tool"] == "scale" and win.current["LMB"] and win.previous["LMB"]:
# let's get the points of the selection zone.
zx = win.szone[0][0]
zy = win.szone[0][1]
zsx = win.previous["LMB"][0]
zsy = win.previous["LMB"][1]
if win.current["mx"] > zx and win.current["my"] > zy:
# now let's get the motion fraction.
mvx = (x - zx) / (zsx - zx)
mvy = (y - zy) / (zsy - zy)
# now let's apply these
win.story["markers"][name][0]\
+= (win.current["mx"] - win.previous["mx"])*mvx
win.story["markers"][name][1]\
+= (win.current["my"] - win.previous["my"])*mvy
if win.current["tool"] == "grab":
# If you press shift, You take things out of events
if 65505 in win.current["keys"]:
doparent = False
try:
if win.current["LMB"]:
x += win.current["mx"] - win.current["LMB"][0]
y += win.current["my"] - win.current["LMB"][1]
elif win.previous["LMB"]:
win.story["markers"][name][0]\
+= win.previous["mx"] - win.previous["LMB"][0]
win.story["markers"][name][1]\
+= win.previous["my"] - win.previous["LMB"][1]
x += win.previous["mx"] - win.previous["LMB"][0]
y += win.previous["my"] - win.previous["LMB"][1]
# Parent removing / assigning
if not doparent:
win.story["markers"][name][2] = ""
elif not win.story["markers"][name][2] :
for event in win.story["events"]:
mx, my = win.story["events"][event]["position"]
pmx, pmy = win.story["events"][event]["size"]
if UI_math.rectangle_overlap(
[mx, my, pmx, pmy],
[x,y,width, height]):
win.story["markers"][name][2] = event
print(event)
break
elif win.current["tool"] != "connect":
win.current["tool"] = "selection"
except:
raise()
# The selected outline
UI_color.set(outlayer, win, "progress_background")
if win.story["active"] == entry:
UI_color.set(outlayer, win, "text_normal")
outlayer.set_line_width(4)
UI_elements.roundrect(outlayer, win,
x,
y,
width,
height,
10,
fill=False)
outlayer.stroke()
outlayer.set_line_width(2)
# Clip
UI_elements.roundrect(layer, win,
0,
0,
width,
height,
10,
fill=False)
layer.clip()
# Background
UI_color.set(layer, win, "dark_overdrop")
layer.rectangle(0,0,width, height)
layer.fill()
# Pin Icon
UI_elements.image(layer, win,
"settings/themes/"+win.settings["Theme"]+"/icons/pin.png",
0, 0, 40, 40)
# Outputting the layer
outlayer.set_source_surface(surface, x, y)
outlayer.paint()
if inscreen:
# Text editor for the marker's name.
UI_elements.text(outlayer, win, name+"_marker",
x+40,
y,
width-40,
40,
set_text=name)
if name != win.text[name+"_marker"]["text"] and win.text[name+"_marker"]["text"]:
def do():
win.story["selected"] = []
win.story["markers"][win.text[name+"_marker"]["text"]] = [
x - win.story["camera"][0],
y - win.story["camera"][1],
win.story["markers"][name][2]
]
win.textactive = ""
del win.story["markers"][name]
UI_elements.roundrect(outlayer, win,
x+width-40,
y,
40,
40,
10,
button=do,
icon="ok",
tip=talk.text("checked"))
if 65293 in win.current["keys"]:
do()
# In case there is a parent event in the scene.
if win.story["markers"][name][2] and doparent:
parent = win.story["markers"][name][2]
UI_math.rectangle_surround(win, parent,
win.story["events"][parent]["position"],
win.story["events"][parent]["size"],
[x,y], [width, height]
)
else:
if win.textactive == name+"_marker":
win.textactive = ""
def do():
nex = 0-win.story["markers"][name][0] + win.current["w"]/2
ney = 0-win.story["markers"][name][1] + win.current["h"]/2
UI_elements.animate("cameraX", win, win.story["camera"][0],nex, time=20, force=True)
UI_elements.animate("cameraY", win, win.story["camera"][1],ney, time=20, force=True)
UI_elements.roundrect(outlayer, win,
x+width-40,
y,
40,
40,
10,
button=do,
tip=name,
fill=False)
outlayer.stroke()
def user(outlayer, win, name ,x, y, user):
# This function will draw users from multiuser to the screen.
if int(x) in range(int(60), int(win.current["w"]-100))\
and int(y) in range(int(60), int(win.current["h"]-80)):
width = 200
height = 40
inscreen = True
else:
x = min(max(x, 60), win.current["w"]-100)
y = min(max(y, 60), win.current["h"]-80)
width = 40
height = 40
inscreen = False
# Making the layer
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
layer = cairo.Context(surface)
# Clip
UI_elements.roundrect(layer, win,
0,
0,
width,
height,
10,
fill=False)
layer.clip()
# Background
UI_color.set(layer, win, "dark_overdrop")
layer.rectangle(0,0,width, height)
layer.fill()
# Pin Icon
UI_elements.image(layer, win,
"settings/themes/"+win.settings["Theme"]+"/icons/user.png",
0, 0, 40, 40)
# Outputting the layer
outlayer.set_source_surface(surface, x, y)
outlayer.paint()
if inscreen:
# Text editor for the marker's name.
UI_elements.text(outlayer, win, name+"_user",
x+40,
y,
width-40,
40,
set_text=name,
editable=False)
else:
# Going to the other user with 1 click
def do():
nex = win.multiuser["users"][user]["camera"][0]
ney = win.multiuser["users"][user]["camera"][1]
UI_elements.animate("cameraX", win, win.story["camera"][0],nex, time=20, force=True)
UI_elements.animate("cameraY", win, win.story["camera"][1],ney, time=20, force=True)
UI_elements.roundrect(outlayer, win,
x+width-40,
y,
40,
40,
10,
button=do,
tip=name,
fill=False)
outlayer.stroke()