1136 lines
41 KiB
Python
1136 lines
41 KiB
Python
# THIS FILE IS A PART OF VCStudio
|
|
# PYTHON 3
|
|
|
|
# This a console project manager.
|
|
|
|
import os
|
|
import datetime
|
|
import re
|
|
|
|
# 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 talk
|
|
from settings import fileformats
|
|
from settings import oscalls
|
|
from project_manager import pm_project
|
|
|
|
#UI modules
|
|
from UI import UI_elements
|
|
from UI import UI_color
|
|
|
|
# story
|
|
from studio import story
|
|
from studio import checklist
|
|
from studio import analytics
|
|
from studio import studio_dialogs
|
|
from studio import schedule
|
|
from studio import history
|
|
|
|
def layer(win):
|
|
|
|
|
|
# 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)
|
|
|
|
UI_color.set(layer, win, "dark_overdrop")
|
|
layer.rectangle(
|
|
0,
|
|
0,
|
|
win.current["w"],
|
|
win.current["h"],
|
|
)
|
|
layer.fill()
|
|
|
|
|
|
############################################################################
|
|
|
|
# This is a file that will draw the text editor of VCStudio. The idea is that
|
|
# you not only work on making the movie in VCStudio, but the script to the
|
|
# movie is also written in VCStudio. This was already implemented in Blender-
|
|
# Organizer legacy. And already implemented partially in VCStudio. As there
|
|
# is story editor in place where you can add empty scenes. Or deal with
|
|
# scenes that are converted from legacy.
|
|
|
|
# But as you may guess by the time I'm writting it there is no way of editing
|
|
# those scene's contents. Or read them in full. ( You can see peaces in the
|
|
# assets )
|
|
|
|
# The implementation of the editor will be different from Blender-Organizer's
|
|
# where I used an off the shelf GTK text writting widget.
|
|
|
|
# The problem was that I could not really do much with that widget appart from
|
|
# text. Don't get me wrong it was good for text. But I could not make for
|
|
# example custom ways of drawing particular parts. Like what if I want a
|
|
# round-rectangle arround each frase that the crachater's say. Or what if I
|
|
# want to draw some custom UI buttons somewhere in the text. Stuff like this.
|
|
|
|
# Which resulted in a weird workflow. I had a pretty script preview thing.
|
|
# and another non-pretty script preview thing. And a script writer thing where
|
|
# you type in code to mark thing. Very non pretty. Non user-friendly. And
|
|
# you had to learn the code. And stuff. Yeah...
|
|
|
|
# So here I want to make more of traditional editor. Where you see what you are
|
|
# editing as you editing it. Hopefully it's going to work.
|
|
|
|
############################################################################
|
|
|
|
####### TOP PANEL #########
|
|
|
|
UI_color.set(layer, win, "node_background")
|
|
UI_elements.roundrect(layer, win,
|
|
win.current["w"]/4,
|
|
10,
|
|
win.current["w"]/2,
|
|
50,
|
|
10)
|
|
|
|
|
|
# Let's add the toolbar. There is not a lot of tools we need. Since it's
|
|
# a program only for writting a script.
|
|
|
|
# Mark Shot
|
|
# Mark Asset
|
|
# Start Dialogue
|
|
# Link Image
|
|
|
|
# MARK SHOT
|
|
def do():
|
|
print("Mark Shot")
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
win.current["w"]/4+5,
|
|
15,
|
|
40,
|
|
40,
|
|
10,
|
|
do,
|
|
"shot_new",
|
|
talk.text("add_shot_tooltip"))
|
|
|
|
# MARK ASSET
|
|
def do():
|
|
print("Mark ASSET")
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
win.current["w"]/4+55,
|
|
15,
|
|
40,
|
|
40,
|
|
10,
|
|
do,
|
|
"obj_link",
|
|
talk.text("add_shot_tooltip"))
|
|
|
|
# Do DIALOGUE
|
|
def do():
|
|
print("Mark Phrase")
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
win.current["w"]/4+105,
|
|
15,
|
|
40,
|
|
40,
|
|
10,
|
|
do,
|
|
"frase_new",
|
|
talk.text("add_phrase_tooltip"))
|
|
|
|
# ADD IMAGE
|
|
def do():
|
|
print("Add Image")
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
win.current["w"]/4+155,
|
|
15,
|
|
40,
|
|
40,
|
|
10,
|
|
do,
|
|
"image_link",
|
|
talk.text("add_image_script_tooltip"))
|
|
|
|
# Next part is to add the scene name editor. It's not as easy as you might
|
|
# thing. Since every scene's shot might contain an actuall folder on the
|
|
# operating system after you create a first blend file to animate the shot.
|
|
|
|
# So there will be a folder for the scene with many folders for shots inside.
|
|
# And if you change the name of the scene in the story you probably want to
|
|
# change the name of the scene in the folder as well. BUT. Since there could
|
|
# be countless blend files inside. And some names just could be already taken
|
|
# and stuff like that, I will block the editing of the scene if a folder exists.
|
|
# And will give a folder icon.
|
|
|
|
# Technically it's going to be possible to rename the scene. By renaming the
|
|
# folder first. But this is a kind of breaking everything operation i don't
|
|
# want to implement inside the VCStudio it self. I give constant folder links
|
|
# so editing of files could be done by the user at any time.
|
|
|
|
# But I don't want it to feel easy. Since stuff like deleting assets or
|
|
# editing names could break things in a different place in the program. That's
|
|
# why I don't provide easy to use functions for it. The user should really
|
|
# decide to make a change like this. To the point of breaking the convinience
|
|
# of VCStudio.
|
|
|
|
# Parsing the url
|
|
if win.cur.count("/") > 1:
|
|
tmp = win.cur.replace("/","",1).split("/")
|
|
scene, shot = tmp[0], tmp[1]
|
|
else:
|
|
scene = win.cur[win.cur.rfind("/")+1:]
|
|
shot = ""
|
|
|
|
|
|
|
|
# Let's find out if a folder exists.
|
|
|
|
if os.path.exists(win.project+"/rnd/"+scene):
|
|
editable = False
|
|
minus = 50
|
|
|
|
# The minus is the width of the folder button
|
|
|
|
def do():
|
|
oscalls.Open(win.project+"/rnd/"+scene)
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
win.current["w"]/4*3-45,
|
|
15,
|
|
40,
|
|
40,
|
|
10,
|
|
do,
|
|
"folder",
|
|
tip="/rnd/"+scene)
|
|
|
|
|
|
|
|
else:
|
|
editable = True
|
|
minus = 0
|
|
|
|
UI_elements.text(layer, win, "scene_name",
|
|
win.current["w"]/4+205,
|
|
15,
|
|
win.current["w"]/2-210-minus,
|
|
40,
|
|
set_text=scene,
|
|
editable=editable,
|
|
fill=False)
|
|
|
|
# Now let's do the actual edititing part. What we want to look for is whether
|
|
# the key already exists in the scenes, if not allow it to be applied. Now
|
|
# you are probably asking yourself. But the current scene exists there? So
|
|
# how could you apply it. Easy. If you change anything. It already doesn't
|
|
# exist there. And if you didn't change anything. What's the point of applying
|
|
# anyway? So here what we are going to do.
|
|
|
|
newname = win.text["scene_name"]["text"].replace("/","_").replace(" ", "_")\
|
|
.replace('"',"_").replace("(","_").replace(")","_").replace("'","_")\
|
|
.replace("[","_").replace("]","_").replace("{","_").replace("}","_")
|
|
|
|
if newname not in win.story["scenes"]:
|
|
|
|
def do():
|
|
|
|
win.story["scenes"][newname] = win.story["scenes"].pop(scene)
|
|
win.text["scene_name"]["text"] = newname
|
|
win.cur = newname
|
|
|
|
|
|
|
|
# There is one more rub. Scenes could be connected together.
|
|
# so now we need to preserve the connections as well. This is
|
|
# not that hard.
|
|
|
|
for arrow in win.story["arrows"]:
|
|
if arrow[0][1] == scene:
|
|
arrow[0][1] = newname
|
|
if arrow[1][1] == scene:
|
|
arrow[1][1] = newname
|
|
|
|
# Easy. I like how if it's a list. it's a link to the list.
|
|
# so there will not be memory overdrives. So I can itterate
|
|
# over a list of lists and assing values of to the itteration
|
|
# and not trying to get the main list. LOVELY.
|
|
|
|
|
|
|
|
# Saving to the file
|
|
story.save(win.project, win.story)
|
|
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
win.current["w"]/4*3-45,
|
|
15,
|
|
40,
|
|
40,
|
|
10,
|
|
do,
|
|
"ok",
|
|
tip=talk.text("checked"))
|
|
|
|
# Just in case parsing the url again
|
|
if win.cur.count("/") > 1:
|
|
tmp = win.cur.replace("/","",1).split("/")
|
|
scene, shot = tmp[0], tmp[1]
|
|
else:
|
|
scene = win.cur[win.cur.rfind("/")+1:]
|
|
shot = ""
|
|
|
|
######### MAIN PART ###########
|
|
|
|
# Oh dear. I have no idea how hard it's going to be. But let's try. I don't
|
|
# thing it's going to be that insane. But I need to take in consideration
|
|
# a couple of things. Mainly text warping. Meaning I'm probably rendering
|
|
# each word as an individual object. Now this creates a challenge.
|
|
|
|
# How do I mark parts of the text having more then 1 word it it? I probably
|
|
# will need to draw a couple layers at ones.
|
|
|
|
# TEXT LAYER
|
|
# SHOTS MARKING LAYER
|
|
# ASSET MARKING LAYER
|
|
|
|
# And then combine them in a different order
|
|
|
|
# SHOT MARKING LAYER
|
|
# ASSET MARKING LAYER (on top)
|
|
# TEXT LAYER (on top of everything)
|
|
|
|
# So let's make those 3 layers.
|
|
|
|
x = win.current["w"]/4
|
|
y = 70
|
|
width = win.current["w"]/2 -30
|
|
height = win.current["h"]-130
|
|
|
|
# Good that at least all layers have the same size.
|
|
|
|
textsurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
|
|
text = cairo.Context(textsurface)
|
|
text.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
|
|
|
|
shotsurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
|
|
shots = cairo.Context(shotsurface)
|
|
shots.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
|
|
|
|
assetsurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
|
|
assets = cairo.Context(assetsurface)
|
|
assets.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
|
|
|
|
###########################
|
|
|
|
# Oh dear
|
|
|
|
# Clips:
|
|
UI_elements.roundrect(text, win, 0,0,width, height, 10,fill=False)
|
|
text.clip()
|
|
UI_elements.roundrect(shots, win, 0,0,width, height, 10,fill=False)
|
|
shots.clip()
|
|
UI_elements.roundrect(assets, win, 0,0,width, height, 10,fill=False)
|
|
assets.clip()
|
|
|
|
# Background
|
|
UI_color.set(shots, win, "node_background")
|
|
shots.rectangle(0,0,width, height)
|
|
shots.fill()
|
|
|
|
if "script" not in win.scroll:
|
|
win.scroll["script"] = 0
|
|
|
|
tileX = 12
|
|
current_Y = 0
|
|
|
|
# For highlights
|
|
if "script_asset_higlight" not in win.current:
|
|
win.current["script_asset_higlight"] = ""
|
|
if "script_shot_higlight" not in win.current:
|
|
win.current["script_shot_higlight"] = ""
|
|
|
|
|
|
pointer = [0,0] # The editing cursor
|
|
point = 0 # The current place in the scene
|
|
if scene in win.story["pointers"]:
|
|
pointer = win.story["pointers"][scene]
|
|
|
|
# Removing highlight
|
|
|
|
if int(win.current["mx"]) not in range(int(win.previous["mx"])-1, int(win.previous["mx"])+1)\
|
|
and int(win.current["my"]) not in range(int(win.previous["my"])-1, int(win.previous["my"])+1):
|
|
win.current["script_asset_higlight"] = ""
|
|
win.current["script_shot_higlight"] = ""
|
|
|
|
|
|
# Okay I guess let's itterrate over the scene and see what's going to happen
|
|
|
|
shotpart = 0
|
|
shotis = ""
|
|
|
|
ss = 0 # THE START OF SELECTION BOX
|
|
|
|
frasepart = 0
|
|
|
|
# Okay so nothing is in the scene we want to create a text block of 1 character
|
|
# into the scene. Because if it will have 0 characters it will be automatically
|
|
# deleted.
|
|
|
|
if not win.story["scenes"][scene]["shots"]:
|
|
win.story["scenes"][scene]["shots"] = [[
|
|
"text_block",[["text", ' ']]
|
|
]]
|
|
|
|
for num, block in enumerate(win.story["scenes"][scene]["shots"]):
|
|
|
|
# IF NOTHING IN THE PART
|
|
if not block[-1]:
|
|
del win.story["scenes"][scene]["shots"][num]
|
|
|
|
|
|
|
|
if win.current["script_find"][0] and win.current["script_find"][0] == num:
|
|
win.scroll["script"] = 0-current_Y+height/2
|
|
win.current["script_find"][0] = 0
|
|
|
|
for n, part in enumerate(block[-1]):
|
|
|
|
# IF NOTHING IN THE PART
|
|
if not part[-1]:
|
|
del block[-1][n]
|
|
|
|
if win.current["script_find"][1] and win.current["script_find"][1] == n:
|
|
win.scroll["script"] = 0-current_Y+height/2
|
|
win.current["script_find"][1] = 0
|
|
|
|
t = part[-1]
|
|
p = point
|
|
|
|
count_newlines = t.count("\n")
|
|
|
|
xb = 12 # Where is the start of the line
|
|
mt = width # Where is the maximum width
|
|
|
|
##### FRASE #####
|
|
|
|
if part[0] == "frase":
|
|
if ss:
|
|
UI_color.set(text, win, "progress_background")
|
|
text.rectangle(
|
|
ss,
|
|
win.scroll["script"] + current_Y,
|
|
mt-ss,
|
|
30)
|
|
text.stroke()
|
|
|
|
|
|
current_Y = current_Y + 30
|
|
|
|
|
|
|
|
if part[1][0] == "link":
|
|
UI_color.set(assets, win, "node_asset")
|
|
UI_elements.roundrect(assets, win,
|
|
width/2-len(part[1][-1])*6-6,
|
|
win.scroll["script"] + current_Y+6,
|
|
len(part[1][-1])*12+12,
|
|
28,
|
|
10)
|
|
|
|
if int(win.current['mx']) in range(int(x+width/2-len(part[1][-1])*6-6), int(x+width/2-len(part[1][-1])*6-6+len(part[1][-1])*12+12)) \
|
|
and int(win.current['my']) in range(int(y+win.scroll["script"] + current_Y+8), int(y+win.scroll["script"] + current_Y+8+22)) :
|
|
|
|
win.current["script_asset_higlight"] = part[1][1]
|
|
|
|
if part[1][1] == win.current["script_asset_higlight"]:
|
|
UI_color.set(assets, win, "progress_background")
|
|
UI_elements.roundrect(assets, win,
|
|
width/2-len(part[1][-1])*6-6,
|
|
win.scroll["script"] + current_Y+6,
|
|
len(part[1][-1])*12+12,
|
|
28,
|
|
10,
|
|
fill=False)
|
|
|
|
assets.stroke()
|
|
|
|
|
|
# So here I want to put a button for editing the name of the phrase.
|
|
if "current_name_frase_editing" not in win.current:
|
|
win.current["current_name_frase_editing"] = False
|
|
|
|
def do():
|
|
|
|
if not win.previous["current_name_frase_editing"]:
|
|
print(part[1][-1])
|
|
win.current["current_name_frase_editing"] = [num, n]
|
|
if "current_name_frase_editing" in win.text:
|
|
win.text["current_name_frase_editing"]["text"] = part[1][-1]
|
|
UI_elements.roundrect(assets, win,
|
|
200,
|
|
win.scroll["script"] + current_Y+6,
|
|
width-400,
|
|
28,
|
|
10,
|
|
button=do,
|
|
offset=[x,y])
|
|
|
|
# Now let's drawa little text editor with in a text editor. IK wild.
|
|
# but since everything is custom I can do wild things.
|
|
|
|
if win.current["current_name_frase_editing"] == [num, n]:
|
|
|
|
UI_elements.text(text, win, "current_name_frase_editing",
|
|
200,
|
|
win.scroll["script"] + current_Y-5,
|
|
width-400,
|
|
40,
|
|
set_text=part[1][-1],
|
|
offset=[x,y])
|
|
|
|
# Here I will add some logic to this little editor with in
|
|
# editor. OMG WHAT AM I DOING?
|
|
|
|
# First let's make the apply button. And I guess the enter key.
|
|
|
|
if win.text["current_name_frase_editing"]["text"] != part[1][-1]:
|
|
def do():
|
|
part[1][-1] = win.text["current_name_frase_editing"]["text"]
|
|
win.current["current_name_frase_editing"] = False
|
|
win.current["LMB"] = False
|
|
win.previous["LMB"] = False
|
|
win.textactive = False
|
|
win.current["key_letter"] = ""
|
|
|
|
UI_elements.roundrect(text, win,
|
|
width-280,
|
|
win.scroll["script"] + current_Y-5,
|
|
40,
|
|
40,
|
|
10,
|
|
button=do,
|
|
icon="ok",
|
|
offset=[x,y])
|
|
|
|
if 65293 in win.current["keys"]:
|
|
do()
|
|
win.current["keys"] = []
|
|
else:
|
|
UI_color.set(text, win, "text_normal")
|
|
text.set_font_size(20)
|
|
text.move_to(
|
|
width/2-len(part[1][-1])*6,
|
|
win.scroll["script"] + current_Y+25,
|
|
)
|
|
text.show_text(part[1][-1])
|
|
|
|
|
|
|
|
|
|
|
|
#point = point + len(part[1][-1]) #################### <<<<<< POINT
|
|
current_Y = current_Y + 35
|
|
|
|
frasepart = current_Y
|
|
|
|
xb = 212
|
|
mt = width - 200
|
|
tileX = xb
|
|
if ss:
|
|
ss = xb
|
|
|
|
if frasepart and part[0] != "frase":
|
|
UI_color.set(assets, win, "dark_overdrop")
|
|
UI_elements.roundrect(assets, win,
|
|
200,
|
|
win.scroll["script"] + frasepart,
|
|
width-400,
|
|
current_Y - frasepart+40,
|
|
10)
|
|
frasepart = 0
|
|
|
|
|
|
|
|
|
|
#### IMAGE ###
|
|
|
|
if part[0] == "image":
|
|
|
|
current_Y = current_Y + 30
|
|
|
|
if os.path.exists(win.project+t):
|
|
UI_elements.image(text, win, win.project+t,
|
|
100,
|
|
win.scroll["script"] + current_Y,
|
|
int(width)-200,
|
|
380,
|
|
cell="script_images")
|
|
else:
|
|
UI_elements.image(text, win, t,
|
|
100,
|
|
win.scroll["script"] + current_Y,
|
|
int(width)-200,
|
|
380,
|
|
cell="script_images")
|
|
|
|
current_Y = current_Y + 400
|
|
|
|
continue
|
|
|
|
assetpart = 0
|
|
assetis = ""
|
|
|
|
### TEXT IT SELF ###
|
|
|
|
for line in re.split("(\n)",t):
|
|
|
|
count_spaces = t.count(" ")
|
|
|
|
if line == "\n":
|
|
|
|
tileX = xb
|
|
point = point + 1 #################### <<<<<< POINT
|
|
|
|
|
|
if assetpart:
|
|
assetpart = xb
|
|
if shotpart:
|
|
shotpart = xb
|
|
|
|
if ss:
|
|
UI_color.set(text, win, "progress_background")
|
|
text.rectangle(
|
|
ss,
|
|
win.scroll["script"] + current_Y,
|
|
mt-ss,
|
|
30)
|
|
text.stroke()
|
|
|
|
ss = xb
|
|
|
|
current_Y = current_Y + 30
|
|
continue
|
|
|
|
for word in re.split("( )", line):
|
|
|
|
# IF TOO MUCH. DO NEXT LINE
|
|
|
|
if tileX + len(word)*12 > mt:
|
|
tileX = xb
|
|
|
|
|
|
if assetpart:
|
|
assetpart = xb
|
|
if shotpart:
|
|
shotpart = xb
|
|
|
|
if ss:
|
|
UI_color.set(text, win, "progress_background")
|
|
text.rectangle(
|
|
ss,
|
|
win.scroll["script"] + current_Y,
|
|
mt-ss,
|
|
30)
|
|
text.stroke()
|
|
|
|
ss = xb
|
|
current_Y = current_Y + 30
|
|
|
|
|
|
|
|
|
|
|
|
# DRAWING ASSET HIGLIGHT
|
|
|
|
if part[0] == "link" and part[1] != assetis and not assetpart:
|
|
assetpart = tileX
|
|
assetis = part[1]
|
|
|
|
if assetpart:
|
|
|
|
if word:
|
|
UI_color.set(assets, win, "node_asset")
|
|
UI_elements.roundrect(assets, win,
|
|
assetpart-5,
|
|
win.scroll["script"] + current_Y+8,
|
|
tileX - assetpart + len(word)*12+12,
|
|
22,
|
|
10)
|
|
|
|
# Selectiong asset. ( Not actually.) But making a
|
|
# highlight of the asset. And if clicked. Going
|
|
# to the asset.
|
|
|
|
if int(win.current['mx']) in range(int(x+assetpart-5), int(x+tileX + len(word)*12+12)) \
|
|
and int(win.current['my']) in range(int(y+win.scroll["script"] + current_Y+8), int(y+win.scroll["script"] + current_Y+8+22)) :
|
|
|
|
win.current["script_asset_higlight"] = assetis
|
|
|
|
if assetis == win.current["script_asset_higlight"]:
|
|
UI_color.set(assets, win, "progress_background")
|
|
UI_elements.roundrect(assets, win,
|
|
assetpart-5,
|
|
win.scroll["script"] + current_Y+8,
|
|
tileX - assetpart + len(word)*12+12,
|
|
22,
|
|
10,
|
|
fill=False)
|
|
|
|
assets.stroke()
|
|
|
|
|
|
assetpart = tileX
|
|
assetis = part[1]
|
|
|
|
if part[0] != "link":
|
|
assetpart = 0
|
|
assetis = ""
|
|
|
|
## HIGLIGHTING SHOTS ##
|
|
|
|
if block[0] == "shot_block" and block[1] != shotis and not shotpart:
|
|
shotpart = tileX
|
|
shotis = block[1]
|
|
|
|
if shotpart:
|
|
|
|
if word:
|
|
|
|
# I want to randomize the shots colors. But I don't it to be an epileptic
|
|
# show.
|
|
|
|
rcolors = [
|
|
"node_imagefile",
|
|
"node_videofile",
|
|
"darker_parts",
|
|
"node_blendfile",
|
|
"node_badfile",
|
|
"progress_time"
|
|
]
|
|
|
|
col = rcolors[num % len(rcolors)]
|
|
|
|
if int(win.current['mx']) in range(int(x+shotpart-5), int(x+tileX + len(word)*12+12)) \
|
|
and int(win.current['my']) in range(int(y+win.scroll["script"] + current_Y+8), int(y+win.scroll["script"] + current_Y+8+22)) :
|
|
|
|
win.current["script_shot_higlight"] = shotis
|
|
|
|
UI_color.set(shots, win, col)
|
|
if shotis == win.current["script_shot_higlight"] or shot == shotis:
|
|
UI_color.set(shots, win, "node_script")
|
|
UI_elements.roundrect(shots, win,
|
|
shotpart-6,
|
|
win.scroll["script"] + current_Y+5,
|
|
tileX - shotpart + len(word)*12+12,
|
|
28,
|
|
10)
|
|
|
|
|
|
|
|
shotpart = tileX
|
|
shotis = block[1]
|
|
|
|
if block[0] != "shot_block":
|
|
shotpart = 0
|
|
shotis = ""
|
|
|
|
|
|
|
|
# This is our word
|
|
|
|
UI_color.set(text, win, "text_normal")
|
|
text.set_font_size(20)
|
|
text.move_to(
|
|
tileX,
|
|
win.scroll["script"] + current_Y+25,
|
|
)
|
|
text.show_text(word)
|
|
|
|
# DRAWING SELECTION ALPHA
|
|
if 65363 in win.current["keys"]:
|
|
pointer[0] = pointer[0]+1
|
|
if not 65506 in win.current["keys"]:
|
|
pointer[1] = pointer[0]
|
|
win.current["keys"].remove(65363)
|
|
|
|
|
|
if 65361 in win.current["keys"]:
|
|
pointer[0] = pointer[0]-1
|
|
if not 65506 in win.current["keys"]:
|
|
pointer[1] = pointer[0]
|
|
win.current["keys"].remove(65361)
|
|
|
|
|
|
if 65362 in win.current["keys"]: # UP
|
|
pointer[0] = pointer[0]-min(len(line), int((mt-12)/12)) # STILL BUGGY
|
|
if not 65506 in win.current["keys"]:
|
|
pointer[1] = pointer[0]
|
|
win.current["keys"].remove(65362)
|
|
|
|
if 65364 in win.current["keys"]: # DOWN
|
|
pointer[0] = pointer[0]+min(len(line), int((mt-12)/12)) # STILL BUGGY
|
|
if not 65506 in win.current["keys"]:
|
|
pointer[1] = pointer[0]
|
|
win.current["keys"].remove(65364)
|
|
|
|
|
|
# PRESSING A KEY TO TYPE I GUESS
|
|
if min(pointer[1], pointer[0]) in range(point, point+len(word)+1) and not ss:
|
|
|
|
ss = tileX+(min(pointer[1], pointer[0])-point)*12
|
|
|
|
if max(pointer[1], pointer[0]) in range(point, point+len(word)+1):
|
|
|
|
# DEVELOPING WHERE THE POINTER IS OMG
|
|
if win.current["testing"]:
|
|
|
|
try:
|
|
c = part[-1][pointer[0]-p]
|
|
except:
|
|
c = "!!"
|
|
|
|
|
|
UI_color.set(text, win, "text_normal")
|
|
text.set_font_size(10)
|
|
text.move_to(
|
|
tileX+(max(pointer[1], pointer[0])-point)*12-26,
|
|
win.scroll["script"] + current_Y+35,
|
|
)
|
|
text.show_text(str(pointer[0])+"["+c+"]"+str(pointer[1]))
|
|
if ss:
|
|
UI_color.set(text, win, "progress_background")
|
|
text.rectangle(
|
|
ss,
|
|
win.scroll["script"] + current_Y,
|
|
tileX+(max(pointer[1], pointer[0])-point)*12-ss,
|
|
30)
|
|
text.stroke()
|
|
|
|
ss = 0
|
|
|
|
if win.current["key_letter"] and not win.textactive:
|
|
|
|
try:
|
|
ORD = ord(win.current["key_letter"])
|
|
except:
|
|
ORD = 0
|
|
print(ORD)
|
|
|
|
win.scroll["script"] = min(0 - current_Y + width/2, win.scroll["script"])
|
|
|
|
if ORD not in range(32) or ORD in range(127, 160):
|
|
part[-1] = \
|
|
part[-1][:min(pointer[1], pointer[0])-p]+\
|
|
win.current["key_letter"]+\
|
|
part[-1][max(pointer[1], pointer[0])-p:]
|
|
|
|
pointer[0] = pointer[0] + 1
|
|
pointer[1] = pointer[0]
|
|
|
|
if ORD == 13: # ENTER
|
|
if part[-1][min(pointer[1], pointer[0])-p-1] == "\n" and part[0] != "text":
|
|
|
|
block[-1].insert(n+1,
|
|
["text", "\n"]
|
|
)
|
|
block[-1].insert(n+2,
|
|
["text", part[-1][max(pointer[1], pointer[0])-p:]]
|
|
)
|
|
|
|
part[-1] = \
|
|
part[-1][:min(pointer[1], pointer[0])-p-1]
|
|
|
|
else:
|
|
part[-1] = \
|
|
part[-1][:min(pointer[1], pointer[0])-p]+\
|
|
"\n"+\
|
|
part[-1][max(pointer[1], pointer[0])-p:]
|
|
|
|
pointer[0] = pointer[0] + 1
|
|
pointer[1] = pointer[0]
|
|
|
|
if ORD == 4: # CTRL D ( FOR SOME REASON)
|
|
|
|
block[-1].insert(n+1,
|
|
["frase", ["text", " "], " "]
|
|
)
|
|
block[-1].insert(n+2,
|
|
["text", part[-1][max(pointer[1], pointer[0])-p:]]
|
|
)
|
|
|
|
part[-1] = \
|
|
part[-1][:min(pointer[1], pointer[0])-p]
|
|
pointer[0] = pointer[0] + 1
|
|
pointer[1] = pointer[0]
|
|
|
|
# Activating the editing of the name automatically
|
|
if "current_name_frase_editing" in win.text:
|
|
win.text["current_name_frase_editing"]["text"] = ""
|
|
if "current_name_frase_editing" not in win.current:
|
|
win.current["current_name_frase_editing"] = False
|
|
win.current["current_name_frase_editing"] = [num, n+1]
|
|
win.textactive = "current_name_frase_editing"
|
|
|
|
if ORD == 8: # BACKSPACE
|
|
if pointer[1] == pointer[0]:
|
|
part[-1] = \
|
|
part[-1][:min(pointer[1], pointer[0])-p-1]+\
|
|
part[-1][max(pointer[1], pointer[0])-p:]
|
|
|
|
pointer[0] = pointer[0] - 1
|
|
pointer[1] = pointer[0]
|
|
else:
|
|
part[-1] = \
|
|
part[-1][:min(pointer[1], pointer[0])-p]+\
|
|
part[-1][max(pointer[1], pointer[0])-p:]
|
|
|
|
pointer[0] = min(pointer[1], pointer[0])
|
|
pointer[1] = pointer[0]
|
|
|
|
if ORD == 127: # DELETE (FORWARD)
|
|
part[-1] = \
|
|
part[-1][:min(pointer[1], pointer[0])-p]+\
|
|
part[-1][max(pointer[1], pointer[0])-p+1:]
|
|
|
|
|
|
|
|
win.current["key_letter"] = ""
|
|
|
|
print(block)
|
|
print()
|
|
|
|
|
|
|
|
# Now let's move the tileX
|
|
|
|
point = point + len(word) #################### <<<<<< POINT
|
|
tileX = tileX + len(word)*12
|
|
|
|
#if count_spaces:
|
|
# point = point + 1 #################### <<<<<< POINT
|
|
# tileX = tileX + 12
|
|
# count_spaces = count_spaces - 1
|
|
|
|
|
|
|
|
|
|
|
|
current_Y = current_Y + 30
|
|
|
|
|
|
|
|
|
|
if scene not in win.story["pointers"]:
|
|
pointer = [point, point]
|
|
win.story["pointers"][scene] = pointer
|
|
else:
|
|
pointer[0] = min(pointer[0], point)
|
|
pointer[1] = min(pointer[1], point)
|
|
pointer[0] = max(pointer[0], 0)
|
|
pointer[1] = max(pointer[1], 0)
|
|
win.story["pointers"][scene] = pointer
|
|
|
|
# Selecting the shot
|
|
if win.current["script_shot_higlight"] and win.previous["LMB"] and not win.current["LMB"]:
|
|
win.cur = "/"+scene+"/"+win.current["script_shot_higlight"]
|
|
# Going to that asset
|
|
|
|
if win.current["script_asset_higlight"] and win.previous["LMB"] and not win.current["LMB"]:
|
|
try:
|
|
win.previous["script_asset_higlight"]
|
|
win.url = "assets"
|
|
win.cur = win.current["script_asset_higlight"]
|
|
win.current["asset_scene_selected"] = scene
|
|
win.current["asset_left_panel"] = "scene"
|
|
del win.current["script_asset_higlight"]
|
|
# Saving to the file
|
|
story.save(win.project, win.story)
|
|
except:
|
|
pass
|
|
|
|
|
|
|
|
|
|
###########################
|
|
|
|
# And finally combine the layers
|
|
|
|
# Outputting the layer
|
|
layer.set_source_surface(shotsurface, x, y)
|
|
layer.paint()
|
|
|
|
# Outputting the layer
|
|
layer.set_source_surface(assetsurface, x, y)
|
|
layer.paint()
|
|
|
|
# Outputting the layer
|
|
layer.set_source_surface(textsurface, x, y)
|
|
layer.paint()
|
|
|
|
# Scroll
|
|
UI_elements.scroll_area(layer, win, "script",
|
|
x+0,
|
|
y+0,
|
|
width+30,
|
|
height-0,
|
|
current_Y,
|
|
bar=True,
|
|
mmb=True,
|
|
bar_always=True)
|
|
|
|
####### BOTTOM PANEL #########
|
|
|
|
UI_color.set(layer, win, "node_background")
|
|
UI_elements.roundrect(layer, win,
|
|
win.current["w"]/4,
|
|
win.current["h"]-50,
|
|
win.current["w"]/2,
|
|
40,
|
|
10)
|
|
|
|
# Here in the bottom I want to introduce little things to go between scenes
|
|
# back and forth.
|
|
|
|
left = ""
|
|
right = ""
|
|
|
|
for arrow in win.story["arrows"]:
|
|
if arrow[0][1] == scene and arrow[1] != "end":
|
|
right = arrow[1][1]
|
|
if arrow[1][1] == scene and arrow[0] != "start":
|
|
left = arrow[0][1]
|
|
|
|
|
|
if left:
|
|
def do():
|
|
win.scroll["script"] = 0
|
|
win.cur = "/"+left
|
|
win.url = "script"
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
win.current["w"]/2-45,
|
|
win.current["h"]-50,
|
|
40,
|
|
40,
|
|
10,
|
|
button=do,
|
|
icon="left")
|
|
|
|
if right:
|
|
def do():
|
|
win.scroll["script"] = 0
|
|
win.cur = "/"+right
|
|
win.url = "script"
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
win.current["w"]/2+5,
|
|
win.current["h"]-50,
|
|
40,
|
|
40,
|
|
10,
|
|
button=do,
|
|
icon="right")
|
|
|
|
|
|
# CANCEl
|
|
|
|
def do():
|
|
win.url = "story_editor"
|
|
win.assets = {}
|
|
del win.text["scene_name"]
|
|
win.story["selected"] = []
|
|
win.scroll["script"] = 0
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
win.current["w"]-40-win.current["w"]/4,
|
|
win.current["h"]-50,
|
|
40,
|
|
40,
|
|
10,
|
|
button=do,
|
|
icon="cancel",
|
|
tip=talk.text("cancel"))
|
|
|
|
# Short cut ESC
|
|
if 65307 in win.current["keys"] and not win.textactive:
|
|
do()
|
|
|
|
############# CHECKLIST #################
|
|
|
|
if os.path.exists(win.project+"/rnd"+win.cur+"/shot.progress"):
|
|
checklist.draw(layer, win, win.project+"/rnd"+win.cur+"/shot.progress", back=win.url)
|
|
|
|
|
|
|
|
############## LEFT PANEL #####################
|
|
|
|
leftpanellist = ["shot", "schedule", "history"] # Using the names of the icons.
|
|
|
|
# We need to choose the correct category based smartly on the project's
|
|
# current progress. Or at least on the current progress of this asset.
|
|
|
|
if "script_left_panel" not in win.current:
|
|
|
|
win.current["script_left_panel"] = "shot"
|
|
|
|
# A little banner.
|
|
|
|
UI_color.set(layer, win, "node_background")
|
|
UI_elements.roundrect(layer, win,
|
|
10,
|
|
10,
|
|
win.current["w"]/4-20,
|
|
50,
|
|
10)
|
|
|
|
for num, thing in enumerate(leftpanellist):
|
|
if win.current["script_left_panel"] == thing:
|
|
|
|
UI_color.set(layer, win, "progress_time")
|
|
UI_elements.roundrect(layer, win,
|
|
20+(40*num),
|
|
15,
|
|
40,
|
|
40,
|
|
10)
|
|
|
|
def do():
|
|
win.current["script_left_panel"] = thing
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
20+(40*num),
|
|
15,
|
|
40,
|
|
40,
|
|
10,
|
|
do,
|
|
thing)
|
|
|
|
### SCHEDULES ###
|
|
|
|
if win.current["script_left_panel"] == "schedule":
|
|
schedule.draw(layer, win)
|
|
|
|
### HISTORY ###
|
|
|
|
if win.current["script_left_panel"] == "history":
|
|
history.draw(layer, win)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return surface
|