# THIS FILE IS A PART OF VCStudio
# PYTHON 3

import os
import datetime
import re
import json

# 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
from UI import UI_math

# 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():
        win.current["key_letter"] = chr(19)
    
    UI_elements.roundrect(layer, win,
        win.current["w"]/4+5,
        15, 
        40,
        40,
        10,
        do,
        "shot_new",
        talk.text("add_shot_tooltip")+"\n\n[Ctrl - S]")  
    
    # MARK ASSET
    def do():
        win.current["key_letter"] = chr(12)
    
    UI_elements.roundrect(layer, win,
        win.current["w"]/4+55,
        15, 
        40,
        40,
        10,
        do,
        "obj_link",
        talk.text("add_asset_tooltip")+"\n\n[Ctrl - L]")  
    
    # Do DIALOGUE
    def do():
    
        # Later on I'm doing the Ctrl - D combination to add a frase part
        # and this gives me a character of 00000011 or in other words a 4.
        # So i guess making it thing that I pressed Ctrl-D is fine.
        
        win.current["key_letter"] = chr(4)
    
    UI_elements.roundrect(layer, win,
        win.current["w"]/4+105,
        15, 
        40,
        40,
        10,
        do,
        "frase_new",
        talk.text("add_phrase_tooltip")+"\n\n[Ctrl - D]")  
    
    # ADD IMAGE
    def do():
        win.current["key_letter"] = chr(9)
    
    UI_elements.roundrect(layer, win,
        win.current["w"]/4+155,
        15, 
        40,
        40,
        10,
        do,
        "image_link",
        talk.text("add_image_script_tooltip")+"\n\n[Ctrl - I]")  
    
    # 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)
    
    frasesurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
    frases = cairo.Context(frasesurface)
    frases.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()
    UI_elements.roundrect(frases, win, 0,0,width, height, 10,fill=False)
    frases.clip()
    
    # Background
    UI_color.set(frases, win, "node_background")
    frases.rectangle(0,0,width, height)
    frases.fill()
    
    # Scroll stuff
    if "script" not in win.scroll:
        win.scroll["script"] = 0
    
    tileX     = 12
    current_Y = 0
    
    # For highlights of assets and shots. Basically when mouse is over a given
    # asset it will record itself into the higlight. And be read on the next
    # frame by those above it which are links to the same asset / shot. 
    # This is done like so, so I could make multiline drawing of markings.
    
    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"] = ""
    
    
    # Next. For editing the text we need a cursor on the screen. A kind of pointer
    # that will be our selection. The only problem is that we are trying to make
    # usefull text editor where you can select a part of text. And do things to it
    # like let's say mark a shot or an asset. This is why there are actually 2 
    # points which are souce of quite heavy head auks later on.
    
    pointer = [0,0] # The editing cursor
    point   = 0     # The current place in the text of the scene.
    if scene in win.story["pointers"]:           # Also I thought sinec we are
         pointer = win.story["pointers"][scene]  # saving selection in story 
                                                 # editor. Why not save also 
                                                 # The text pointers. 
    
    # Coming back to the previous thing. If I mouse over the part the part get's
    # highlighted. But simply removing the mouse is not enough. Because I'm
    # writting that it's higlighted into a global dictionary. So I want to clean.
    # it ones in a while. And for now ( It does cause some visual noise ) I chose
    # to remove the selection if the mouse cursor moved over 1 pixel from it's
    # previous frame. So if you move the cursor very slowly, there will be no
    # change.
    
    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"] = ""
    
        
    # This 2 fellas will be responsible for drawing the shot marking.
    shotpart = 0 # This is a pixel where to start the rounded rectangle. 
    shotis = ""  # this is a current drawing shot's name.
    
    # Same idea for the selection cursor.
    ss = 0 # The pixel where to start drawing the selection cursor.
    smx = ss
    
    # Another one of these for the rectangles under frases. This one is Y location
    # instead.     
    frasepart = 0
    
    # This is the scroll when typing. 
    
    putscroll = 0
    
    
    # Before we start. Let's bullet proof this. So if the scene does not exist
    # we will be transferred back to story editor and not stuck.
    
    try:
        win.story["scenes"][scene]["shots"]
    except:
        win.url = "story_editor"
        win.cur = ""
        return surface
    
    # Okay if 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"]\
    or win.story["scenes"][scene]["shots"][-1][0] == "shot_block":
        win.story["scenes"][scene]["shots"].append([
                "text_block",[["text", ' ']]
                ])

    
    # This is a list of parts that are inside the selection. I will populate it
    # as I itterate trough text. The problem with this text is that it's not a
    # long string. It's a list of blocks. Each of them has a string. But also 
    # each of them has some aditional metadata. Like is it a shot, or not. Is it
    # a frase. Is it a link to an asset. This kind a thing. So in order to edit it
    # I need to get all selected peaces into a big thing.  
    
    selecwords = []
    
    # And a little thing for the left panel. Since we already itterating through.
    # the shots. Why not get a quick list of them
    
    shot_list = {}
    
    # Okay so let's begin itterating the scene blocks. There are 2 types of scene
    # blocks. (At least for now.) Those are shot_block and text_block. Text is a
    # normal text parts. Shot is everything with in a shot. Shot has one more item
    # in the list. It's the name of the shot. ['shot_block', 'shot_name', [<text>]]
    # while text has just 2. ['text_block', [<text>]]. So you can see me refencing
    # the block[-1] a lot. To get the text parts of the block.
    
    
    
    for num, block in enumerate(win.story["scenes"][scene]["shots"]):
        
        
        # If shot block is empty Let's get rig of it, so not to collect garbage in
        # our story file. Each empty srting is still a string. That requires some 
        # characters to write it to file. So let's get rid of it here.
        
        if not block[-1]:
            del win.story["scenes"][scene]["shots"][num]
        
        # Here I want to make another type of filtering. So there will not be
        # 1 million blocks each 1 character long. I want to make it next.
        # If the previous block has the same metadata as this one. Join them.
        
        if num > 0 and win.story["scenes"][scene]["shots"][num-1][0] == "text_block" and block[0] == "text_block":
            win.story["scenes"][scene]["shots"][num-1][-1] = win.story["scenes"][scene]["shots"][num-1][-1] + block[-1]
            del win.story["scenes"][scene]["shots"][num]
        
        
        # THIS ONE IS NOT TESTED YET, BUT I MIGHT ALSO FORGET TO DELETE THE COMMENT.
        elif num > 0 and win.story["scenes"][scene]["shots"][num-1][0] == "shot_block" and block[0] == "shot_block"\
        and win.story["scenes"][scene]["shots"][num-1][1] == block[1]:
            win.story["scenes"][scene]["shots"][num-1][-1] = win.story["scenes"][scene]["shots"][num-1][-1] + block[-1]
            del win.story["scenes"][scene]["shots"][num]
        
        if block[0] == "shot_block" and block[1] not in shot_list:
            shot_list[block[1]] = block
            
                    
        # Now other windows might want to reference the script. Like assets for 
        # example. So this script_find is for other windows to set. So while in
        # the script it would automatically scroll to that part. And so if set
        # only shot. Here is out shot finder, auto-scroller thingy.
        
        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
        
        # Now let's itterate over parts of the text. Now you probably asking wasn't
        # blocks just strings with some metadata? Yes and know. Every text block has
        # blocks with in it. So I could mark items and images and frases with in text
        # across or without a shot. Basically there is our simple Hello-World thing
        # written inside a scene data. ['text_block', ['text','Hello-World']]
        # This are similar. The actual sting is always in the very end. So to find it
        # I'm using part[-1]
        
        for n, part in enumerate(block[-1]):
            
            # If you remember me deleting every empty block. Not this is the same 
            # but with empty parts. So you could delete a frase for example. While
            # just backspacing. 
            
            if not part[-1]:
                del block[-1][n]
            
            # Here I want to make another type of filtering. So there will not be
            # 1 million blocks each 1 character long. I want to make it next.
            # If the previous block has the same metadata as this one. Join them.
            
            if n > 0 and block[-1][n-1][0] == "text" and part[0] == "text":
                block[-1][n-1][-1] = block[-1][n-1][-1]+part[-1]
                part[-1] = ""      
            
            # Now this is our search finder auto-scroller again. But if a part
            # also specified.
            
            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
            
            # Now t and p. Well t is simply a shortcut to the string it self. Tho 
            # I found it not really usefull since it's not a link to the data. Like
            # in the case of part[-1]. But for rendering it will be okay.
            
            t = part[-1]

            # Now p is a bit more complicated to explain. Basically I always need
            # an index number from all character in the whole scene in relation to
            # this particular part. See i will have a selection across the blocks
            # and across the parts. And in order to edit them at the right place
            # I need a reference point of where in the whole, this part starts. 

            p = point
            
            # Now xb and mt you could see as margins of the text. Sometimes you
            # want the whole width to be text. And sometimes. Like in frases you
            # will want the text closer to the center.
            
            xb = 12    # Where is the start of the line
            mt = width # Where is the maximum width
            
            ##### FRASE #####
            
            # Now let's make an example of xb and mt. Here is a frase. So when
            # it's a frase. You want the text be closer to the center.
            
            if part[0] == "frase":
                
                
                # Give it some space. It's a rendering of a frase. You don't
                # want to be a part of the rest of the text.
                    
                current_Y = current_Y + 30
                
                # Now frase metadata has another part. Which could be either
                # text or link. This is the name of our character. The little
                # part at the top, in the center. If it's a link we want to 
                # draw it accordingly
                
                if part[1][0] == "link":
                    
                    # First we draw a little purple rectangle. To show us that
                    # it's a link to an item. 
                    
                    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)
                    
                    # Then we make a selection by hovering with the mouse. So if
                    # you click later. You will be transferred to the thing.
                    
                    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]
                    
                    # And if the mouse is over the item's link. No matter if the
                    # link is this one. But if mouse is over any other mention of
                    # the same asset. We want to draw another rectangle. To give
                    # the user a feedback.
                    
                    if part[1][1] == win.current["script_asset_higlight"]:    
                        
                        UI_color.set(assets, win, "text_normal")
                        UI_elements.roundrect(assets, win,
                            width/2-len(part[1][-1])*6-6,
                            win.scroll["script"] + current_Y+30, 
                            len(part[1][-1])*12+12,
                            0,
                            3)
                        
                
                # Next we will want to do it make a little button to edit the 
                # name of the character. Because I guess I'm not smart enough
                # to figure out how to make this a part of the script. And this
                # implementation is not that terrible. I have a chance to put a
                # single line entry into a multiline text. This is something.
                
                if "current_name_frase_editing" not in win.current:
                    win.current["current_name_frase_editing"] = False
                    win.previous["current_name_frase_editing"] = False
                
                # So we put a selection variable. And set up the button.
                
                if not win.current["current_name_frase_editing"]:  
                    def do():
                        
                        win.current["LMB"] = False
                        win.previous["LMB"] = False
                        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]
                            win.textactive = "current_name_frase_editing"
                    UI_elements.roundrect(frases, win,
                        0,
                        win.scroll["script"] + current_Y+6, 
                        width,
                        28,
                        10,
                        button=do,
                        offset=[x,y])
                
                # Now let's draw a 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.
                    
                    def linking():
                        print("linking")
                        
                        if "linking_asset_operation_metadata" not in win.current:
                            win.current["linking_asset_operation_metadata"] = []
                        
                        win.current["linking_asset_operation_metadata"] = part
                        
                        def after(win, var):
                            print(var)
                            if var:
                                
                                part  = win.current["linking_asset_operation_metadata"]
                                
                                
                                print(part)
                                part[1] = ["link", var, part[1][-1]]
                            
                        
                        studio_dialogs.asset_select(win, "link_asset_script_frase", after, 
                        SEARCH=win.text["current_name_frase_editing"]["text"])
                            
                        
                    UI_elements.roundrect(text, win,
                        width-240,
                        win.scroll["script"] + current_Y-5, 
                        40,
                        40,
                        10,
                        button=linking,
                        icon="obj_link",
                        offset=[x,y])
                    
                    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])
                    
                    # Enter key.
                    
                    if 65293 in win.current["keys"]:
                        do()
                        
                        # If you press Ctrl-Enter instead of Enter. I want it
                        # to apply and also give you automatically to select
                        # the asset to link in the frase header.
                        
                        if 65507 in win.current["keys"]:
                            linking()
                        
                        win.current["keys"] = []
                    
                    # Canceling the editing. If we don't do that the entry thing
                    # will still be on the screen. And it's not something that
                    # I want to have there.
                    
                    if not win.textactive:
                        win.current["current_name_frase_editing"] = False
                        win.current["key_letter"] = ""
                else:
                    
                    # And if we are not editing the name currently
                    # let's just draw the name in the center of the
                    # screen.
                    
                    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])
                
                # Giving it a new line.
                
                current_Y = current_Y + 35
                
                # Putting the line into the frasepart so to draw a rectangle 
                # later under the whole thing.
                
                frasepart = current_Y
                
                # And here we are editing the margins. Because actuall text will
                # be done in a different place.
                
                xb = 212
                mt = width - 200
                tileX = xb
                
                # And passing the current starting position to selection drawing
                # so it too will start where it should.
                
                if ss:
                    ss = xb
            
            # Now if we are not in the frase. Let's draw the damn rectangle under
            # it finally. # THIS IS STILL BUGGY.
                
            if frasepart and part[0] != "frase":
                UI_color.set(frases, win, "dark_overdrop")
                UI_elements.roundrect(frases, win,
                    200,
                    win.scroll["script"] + frasepart, 
                    width-400,
                    current_Y - frasepart+40,
                    10)
                frasepart = 0
                
                # MAKING A NEW LINE
                
                smx = tileX
                tileX = xb
                
                if assetpart:
                    assetpart = xb
                if shotpart:
                    shotpart = xb
                
                if ss:
                    
                    UI_color.set(assets, win, "node_blendfile")
                    UI_elements.roundrect(assets, win,
                        ss,
                        win.scroll["script"] + current_Y+5,
                        smx-ss,
                        26,
                        10)
                    smx = ss
                    ss = xb
                
                current_Y = current_Y + 30  
                
                
                
            # Now let's draw our images. If they are in the scene. # THIS IS STILL BUGGY
                
            if part[0] == "image":
                
                if UI_math.line_overlap([pointer[1], pointer[0]],[point, point+1]):
                    if win.current["key_letter"] and not win.textactive:
                        
                        # Let's make it possible to delete images by just 
                        # deleting near them.
                        
                        part[-1] = ""
                        
                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")
                
                # Now I guess to simplify the matters let's create a selection
                # button. Double clicking which will open the file.
                
                # So we need a selection dialog. I think I'm going to hack into
                # my own program right now because I'm lazy to implement anything
                # normal. This image thing. Will need more love later on. Now it's
                # thrown together quite in a rush. I would say.
                
                def do():
                    if t != win.textactive:
                        win.textactive = t
                    else:
                        oscalls.file_open(win, t)
                UI_elements.roundrect(text, win,
                    100,
                    win.scroll["script"] + current_Y,
                    int(width)-200,
                    380,
                    10,
                    button=do,
                    fill=False,
                    offset=[x,y])
                text.stroke()
                
                # Selection drawing
                
                if t == win.textactive:
                    
                    UI_color.set(text, win, "text_normal")
                    UI_elements.roundrect(text, win,
                        100,
                        win.scroll["script"] + current_Y,
                        int(width)-200,
                        380,
                        10,
                        fill=False)
                    text.stroke()
                    
                    # Removing it from the selection using ESC
                    
                    if 65307 in win.current["keys"]:
                        win.textactive = ""
                        win.current["keys"] = []
                        win.current["key_letter"] = ""
                    
                    # Deleting the image if pressing Delete or Backspace
                    
                    if 65288 in win.current["keys"] or 65535 in win.current["keys"]:
                        win.textactive = ""
                        part[-1] = ""
                        win.current["keys"] = []
                        win.current["key_letter"] = ""
                
                current_Y = current_Y + 400
                
                continue # we don't want to image url in the text it self.
            
            # Do you remember I was doing the starting positions of shots and
            # selection? These 2 are the same concept but to links to assets.
            
            assetpart = 0
            assetis = ""

            ############## TEXT IT SELF ###############
            
            # Here we go and render the text. Now you can see I iterate over
            # lines using re.split rather then built in split(). It's because
            # I need all characters still be present. Since I'm counting every
            # each character.
                            
            for line in re.split("(\n)",t):
                
                # Now if the line says '\n' (new_line) then I just want to
                # draw the next line. Note that I'm also drawing the selection
                # box here. And moving all assetpart, shotpart and ss. So on
                # the next line those rectangles would start their drawing from 
                # the begining of the line. 
                
                # Also not the large comment with a POINT in it. It's I'm counting
                # this character in for to know where I'm editing. 
                
                if line == "\n":
                    
                    smx = tileX
                       
                    tileX = xb
                    #point = point + 1   #################### <<<<<< POINT
                    
                    
                    if assetpart:
                        assetpart = xb
                    if shotpart:
                        shotpart = xb
                    
                    if ss:
                        
                        UI_color.set(assets, win, "node_blendfile")
                        UI_elements.roundrect(assets, win,
                            ss,
                            win.scroll["script"] + current_Y+5,
                            smx-ss,
                            26,
                            10)
                        text.stroke()
                        smx = ss
                        ss = xb
                    
                    current_Y = current_Y + 30    
                    
                    
                    line = " "
                    #continue # And this is since I don't want weird rectangles
                             # on the screen. And just new lines.
                    
                # Now let's itterate over each and every word. Since we want
                # text wrapping. So if a certain word goes off screen I want
                # to declare a next line. NOTE: I'm still using re.split() 
                # becuase we are counting charaters still. 
                    
                for word in re.split("( )", line):
                    
                    # Now let's do the actuall text wrapping. For size 20 which
                    # is what I'm using. With monospace font. Width of each
                    # character is 12 pixels. ( More or less. Good enough for
                    # what we are doing ). So if lenght of word times 12, plus 
                    # current place on X is more then the width of our screen,
                    # with all the margins. We want to start a new line.
                    
                    if tileX + len(word)*12 > mt:
                        
                        smx = tileX
                        
                        tileX = xb
                        
                        # And do not forget about all the asset, shot and selection
                        # rendering too.
                        
                        if assetpart:
                            assetpart = xb      
                        if shotpart:
                            shotpart = xb
                        
                        
                        if ss:
                    
                            UI_color.set(assets, win, "node_blendfile")
                            UI_elements.roundrect(assets, win,
                                ss,
                                win.scroll["script"] + current_Y+5,
                                smx-ss,
                                26,
                                10)
                            text.stroke()
                            
                            ss = xb
                            
                        current_Y = current_Y + 30
                        

                        
                    # This is logic to draw ASSETS higlights.
                    
                    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, "text_normal")
                                UI_elements.roundrect(assets, win,
                                    assetpart-6,
                                    win.scroll["script"] + current_Y+26, 
                                    tileX - assetpart + len(word)*12+12,
                                    0,
                                    3)
                                
                                
                        assetpart = tileX
                        assetis = part[1]
                        
                    if part[0] != "link":
                        assetpart = 0
                        assetis = ""
                    
                    # And this is logic to draw SHOTS higlights.
                    
                    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. But not too much. Let's actually write the colors into the story
                            # data. Why not.
                            
                            if "shot_colors" not in win.story:
                                win.story["shot_colors"] = {}
                            
                            surl = "/"+scene+"/"+shotis
                            
                            if surl not in win.story["shot_colors"]:
                                
                            
                                rcolors = [
                                    "shot_1",
                                    "shot_2",
                                    "shot_3",
                                    "shot_4",
                                    "shot_5"
                                    ]
                                
                                win.story["shot_colors"][surl] = rcolors[len(win.story["shot_colors"]) % len(rcolors)]
                            
                            col = win.story["shot_colors"][surl]
                            
                            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)
                            UI_elements.roundrect(shots, win,
                                shotpart-6,
                                win.scroll["script"] + current_Y+5, 
                                tileX - shotpart + len(word)*12+12,
                                28,
                                10)
                            
                            # This is a bit of a hack because I was lazy to
                            # figure out how to make shot markings as good
                            # as I made the selection. So drawing a thing around it
                            # would not really work that well. But a line under the
                            # text looks quite alright. I like the look of it. 
                            # Maybe I will polish this in future and give people
                            # an option to draw it differently. I don't know yet.
                            
                            if shotis == win.current["script_shot_higlight"] or shot == shotis:    
                                UI_color.set(shots, win, "text_normal")
                                UI_elements.roundrect(shots, win,
                                    shotpart-6,
                                    win.scroll["script"] + current_Y+30, 
                                    tileX - shotpart + len(word)*12+12,
                                    0,
                                    3)
                                
                            
                            
                        shotpart = tileX
                        shotis = block[1]
                        
                    if block[0] != "shot_block":
                        shotpart = 0
                        shotis = ""
                    
                    
                        
                    # Now let's draw our word. Simple really. What's so special
                    # about it? Why is this comment 2 lines high?
                    
                    UI_color.set(text, win, "text_normal")
                    #if win.current["script_shot_higlight"] == block[1] or shot == block[1]:
                    #    UI_color.set(text, win, "darker_parts")
                    text.set_font_size(20)
                    text.move_to(
                        tileX,
                        win.scroll["script"] + current_Y+25,
                        )
                    text.show_text(word)
                    
                    # Here I want to make a selection using a mouse. I think it's quite important
                    # since using a Shift key and pressing sideways is not cool 
                    # and I want it to be cool.
                    
                    if win.current["LMB"]:
                        if int(win.current["LMB"][1]) in range(int(y+win.scroll["script"] + current_Y), int(y+win.scroll["script"] + current_Y)+25)\
                        and int(win.current["LMB"][0]-x) in range(tileX, tileX+len(word)*12+12):
                            pointer[0] = int(point - (tileX+len(word)*12 - int(win.current["LMB"][0]-x))/12 + len(word))
                        
                        if int(win.current["my"]) in range(int(y+win.scroll["script"] + current_Y), int(y+win.scroll["script"] + current_Y)+25)\
                        and int(win.current["mx"]-x) in range(tileX, tileX+len(word)*12+12):
                            pointer[1] = int(point - (tileX+len(word)*12 - int(win.current["mx"]-x))/12 + len(word))
                        
                            win.cur = "/"+scene
                            win.textactive = ""
                    
                    if int(win.current["my"]) in range(int(y+win.scroll["script"] + current_Y), int(y+win.scroll["script"] + current_Y)+25)\
                    and int(win.current["mx"]-x) in range(tileX, tileX+len(word)*12+12):
                        
                        win.current["cursor"] = win.cursors["text"]
                        
                    # This is the logic to draw our selection and logic that 
                    # come with the selection. 
                    
                    if UI_math.line_overlap([pointer[1], pointer[0]],[point, point+len(word)+1]) and not ss:
                        ss = tileX+(min(pointer[1], pointer[0])-point)*12
                        smx = ss
                    
                    # If current word is inside the selection. It means that 
                    # current text part is also inside the selection. And this
                    # means this part should be edited if I press a button.
                        
                    if UI_math.line_overlap([pointer[1], pointer[0]],[point, point+len(word)+1]):
                        
                        # So we need to add this part and some data about this
                        # part like amount of characters it's away from the
                        # begining of the scene into a list that I could reference
                        # later in the writting logic. 
                        
                        if [part, p, num, n] not in selecwords:
                            selecwords.append([part, p, num, n])
                        
                        # Let's make something for me to understand what is going
                        # on. If I will enter the testing mode. Let it draw the 
                        # current number of characters. And the current characrter.
                        
                        if win.current["testing"]:
                           
                            # This is our character. It's not always available.
                            # sometimes you migt be on the edge of something and
                            # something else. So !! will mean seomthing is wrong.
                            
                            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+(pointer[0]-point)*12-26,
                                win.scroll["script"] + current_Y+35,
                                )
                            text.show_text(str(pointer[0])+"["+c+"]")
                            
                            # Now doing it again for the second pointer. If you
                            # remeber, We have 2.
                            
                            try:
                                c = part[-1][pointer[1]-p]
                            except:
                                c = "!!"
                            
                            
                            UI_color.set(text, win, "text_normal")
                            text.set_font_size(10)
                            text.move_to(
                                tileX+(pointer[1]-point)*12-26,
                                win.scroll["script"] + current_Y+35,
                                )
                            text.show_text(str(pointer[1])+"["+c+"]")
                            
                    if max(pointer[1], pointer[0]) in range(point, point+len(word)+1):
                        # This is some more drawing of the selection. This is
                        # if the selection is ending mid way through the line.
                            
                        if ss:
                            
                            if pointer[0] != pointer[1] :
                                UI_color.set(assets, win, "node_blendfile")
                                UI_elements.roundrect(assets, win,
                                    max(ss, xb),
                                    win.scroll["script"] + current_Y+5,
                                    min(tileX+(max(pointer[1], pointer[0])-point)*12-max(ss, xb), mt-max(ss, xb)),
                                    26,
                                    10)
                            
                            elif not win.textactive and win.blink:
                                UI_color.set(text, win, "node_blendfile")
                                text.rectangle(
                                    max(ss, xb),
                                    win.scroll["script"] + current_Y+5,
                                    min(tileX+(max(pointer[1], pointer[0])-point)*12-max(ss, xb), mt-max(ss, xb)),
                                    26)
                                text.stroke()
                            
                            #    win.scroll["script"] + current_Y,
                            #    min(mt-max(ss,xb), mt-xb),
                        
                        ss = 0
                        #smx = 0
                        
                        if win.current["keys"] and not win.textactive and not putscroll:
                            putscroll = min(0 - current_Y + width/2, win.scroll["script"])
                        

                    # Now in the end of our word. We are counting it's lenght
                    # and moving the tileX so the next word draws after this
                    # one and not on top of this one. I think it's important.
                    
                    point = point + len(word)   #################### <<<<<< POINT
                    tileX = tileX + len(word)*12
                    
                    # Also what you probably want to happen is when you type the script
                    # will scroll down. Yeah. It's not coming by default. Even on standart
                    # GTK text parts. So here is a little thing.
                    
                    
                    
    if putscroll:
        win.scroll["script"] = putscroll            
                    
    ############# LOGIC ###############
    
    # So I'm doing the logic of typing separatelly from rendering of the text. 
    # because it kind a seems right to do so. I'm still figuring it out at this
    # point. I have no idea what could go wrong. Maybe I will reddo the whole
    # thing. Maybe few times. IDK.
    
    
                    
    if 65363 in win.current["keys"]:  # RIGHT
        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"]:  # LEFT
        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)  
    
    # In order for history to work properly I don't want to save history on
    # each button press. But rather ones every time the scene is edited. So
    
    if "scene_edited_already" not in win.current:
        win.current["scene_edited_already"] = False
    
    
    # I'm going to implement some basic clipboard. It will need love in future.
    # I just need for now something that will "work" so to speak. See where I
    # use the clipboard variable later to learn how it all works.
    
    clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) # This is a clipboard object
    
    
    # If there is a key press that contains a string. Like anything on a keyboard
    # where you can actually type. Let's do something with it.
    
    def clean():
        # This is an empty function. Placeholder for a clean operation after
        # a given key press. Because we are dealing with multiple blocks of
        # text that look like 1 block for the user.
        pass
    
    # To make shot I want to write a little list of text parts that will come
    # into that shot.
    
    new_shot_list = []
    after_shot_list = []
    new_shot = []
    
    if win.current["key_letter"] and not win.textactive:
        
        # Here I'm going to implement history
        if not win.current["scene_edited_already"]:
            win.current["scene_edited_already"] = True
            history.record(win, "/rnd"+win.cur, "[Edited]")
        
        
        #print("------{ BEFORE }--------")
        #print(win.story["scenes"][scene]["shots"])
        #print("------{        }------") 
        #print()
        
        
        #print() # For testing
        
        for u, stuff in enumerate(selecwords):
            part, p, num, n = stuff
            
            try:
                block = win.story["scenes"][scene]["shots"][num]    
            except:
                break
                
            try:
                ORD =  ord(win.current["key_letter"])
            except:
                ORD = 0
            
            print(ORD, "ORD") # Output the value of the button.
            
            # Now some of the ORDs I found to be weird characters. Like on 
            # CTRL - C or CTRL - V. So I want to filter them out. So there
            # wont be a bunch of rectangles every time you type.
            
            # Now I need the minimum and maximum parts. So there will not be
            # scips of content I guess. 
           
            MIN = min(len(part[-1]), max(0, min(pointer[1], pointer[0])-p))
            MAX = max(0, min(len(part[-1]), max(pointer[1], pointer[0])-p))
            
            #print(pointer,"POINTER")
            #print(p, "P")
            #print(len(part[-1]), "LENGHT", [part[-1]])
            #print(MIN, "MIN")
            #print(MAX, "MAX")
            #print()
            
            # Here I want to record undo history for the script writer. I am going
            # to ignore the letters. And only forcus on other simbols such as
            # spacebars and various commands. 
            
            nonhistory = "1234567890qwertyuiopasdfghjklzxcvbnnmQWERTYUIOPASDFGHJKLZXCVBNM"
            
            if win.current["key_letter"] not in nonhistory and ORD not in [26, 25]:
                story.undo_record(win)
                # Multiuser sycning
                win.multiuser["request"] = "story"
            
            # Now let's retrive out data.
            
            # UNDO
            if ORD == 26:
                story.undo(win)
            
            # REDO
            if ORD == 25:
                story.redo(win)
            
            
            if u == 0:
                
                if ORD not in range(32) or ORD in range(127, 160):
                    
                    # Typing logic
                    
                    part[-1] = \
                    part[-1][:MIN]+\
                    win.current["key_letter"]+\
                    part[-1][MAX:]
                    
                    def clean():
                        pointer[0] = pointer[0] + 1
                        pointer[1] = pointer[0]
                    point = point + 1
                
                if ORD == 22: # Paste ( Ctrl - V )
                
                    cliptext = str(clipboard.wait_for_text()) 
                    
                    part[-1] = \
                    part[-1][:MIN]+\
                    cliptext+\
                    part[-1][MAX:]   
                    
                    def clean():
                        pointer[0] = pointer[0] + len(cliptext)
                        pointer[1] = pointer[0]
                    
                    point = point + len(cliptext)
                
                if ORD == 3: # Copy ( Ctrl - C )
 
                    clipboard.set_text( part[-1][MIN:MAX] , -1) # VERY BASIC
                
                # If ord 13 it means you pressed enter. And it should be a new line.
                # but for some reason it's ord 13. Maybe it is a new line. Who knows
                # Anyway. It does not return \n but returns a weird rectangle. So
                # here is a little solution.
                
                if ORD == 13: # ENTER
                    
                    # Only I want to use new line to exit from all kind of things.
                    # Like double enter will exit the frase. Ans stuff like this. 
                    
                    if part[-1][MIN-1] == "\n" and part[0] != "text":
                        
                        block[-1].insert(n+1,
                            ["text", "\n"]
                            )
                        block[-1].insert(n+2,
                            ["text", part[-1][MAX:]+" "]
                            )
                        
                        part[-1] = \
                        part[-1][:MIN-1]
                             
                    else:
                        part[-1] = \
                        part[-1][:MIN]+\
                        "\n"+\
                        part[-1][MAX:]
                    
                    def clean():
                        pointer[0] = pointer[0] + 1
                        pointer[1] = pointer[0]
                    point = point + 1
                
                if ORD == 4: # CTRL D ( FOR SOME REASON)
                    
                    block[-1].insert(n+1,
                        ["frase", ["text", " "], " "]
                        )
                    block[-1].insert(n+2,
                        ["text", part[-1][MAX:]]
                        )
                    
                    part[-1] = \
                    part[-1][:MIN]
                    def clean():
                        pointer[0] = pointer[0] + 1
                        pointer[1] = pointer[0]
                    point = point + 1
                    
                    # 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-1]+\
                        part[-1][MAX:]
                        def clean():
                            pointer[0] = pointer[0] - 1
                            pointer[1] = pointer[0]
                        point = point - 1
                    else:
                        part[-1] = \
                        part[-1][:MIN]+\
                        part[-1][MAX:]
                        def clean():
                            pointer[0] = min(pointer[0], pointer[1])
                            pointer[1] = pointer[0]
                    
                if ORD == 127: # DELETE (FORWARD)
                    part[-1] = \
                    part[-1][:MIN]+\
                    part[-1][MAX+1:]
                    def clean():
                        pointer[0] = pointer[0]
                        pointer[1] = pointer[0]
                
                if ORD == 19: # NEW SHOT ( CTRL - S ) 
                    app = part.copy()
                    app[-1] = part[-1][MIN:MAX]
                    new_shot_list.append(app)
                    new_shot = [num , n]
                    
                    after_shot_list = block.copy()
                    after_shot_list[-1] = []
                    
                    app2 = part.copy()
                    app2[-1] = part[-1][MAX:] 
                    after_shot_list[-1].append(app2)
                    
                    part[-1] = part[-1][:MIN] 
                
                if ORD == 12 and part[0] == "text" and pointer[1] != pointer[0]: # Asset higlight
                    
                    if "linking_asset_operation_metadata" not in win.current:
                        win.current["linking_asset_operation_metadata"] = []
                        
                    win.current["linking_asset_operation_metadata"] = [part , block, MIN, MAX]
                    
                    def after(win, var):
                        print(var)
                        if var:
                            
                            part , block, MIN, MAX  = win.current["linking_asset_operation_metadata"]
                            
                            block[-1].insert(n+1,
                                ["link", var, part[-1][MIN:MAX]]
                                )
                            block[-1].insert(n+2,
                                ["text", part[-1][MAX:]]
                                )
                            
                            part[-1] = \
                            part[-1][:MIN]
                        win.current["key_letter"] = "" 
                    
                    studio_dialogs.asset_select(win, "link_asset_script_frase", after, 
                    SEARCH=part[-1][MIN:MAX])
                
                if ORD == 9 and part[0] == "text" and pointer[1] == pointer[0]: # Insert image
                    
                    if "linking_asset_operation_metadata" not in win.current:
                        win.current["linking_asset_operation_metadata"] = []
                        
                    win.current["linking_asset_operation_metadata"] = [part , block, MIN, MAX]
                    
                    def after(win, var):
                        print(var)
                        if var:
                            
                            part , block, MIN, MAX  = win.current["linking_asset_operation_metadata"]
                            
                            block[-1].insert(n+1,
                                ["image", var]
                                )
                            block[-1].insert(n+2,
                                ["text", part[-1][MAX:]]
                                )
                            
                            part[-1] = \
                            part[-1][:MIN]
                        win.current["key_letter"] = "" 
                    
                    studio_dialogs.file_select(win, "link_asset_script_frase", after, 
                    SEARCH=part[-1][MIN:MAX])
                    
                    
                
            # Making stuff happen
            elif u < len(selecwords)-1:
                if ORD not in [12, 19, 3, 22, 26, 25]: # 3 = Crtl - C, 22 = Ctrl - V
                    part[-1] = ""
                
                if ORD == 19:
                   app = part.copy()
                   new_shot_list.append(app)
                   
                   part[-1] = ""
                
            else:
                
                MIN = min(len(part[-1])-1, max(0, min(pointer[1], pointer[0])-p))
                MAX = max(0, min(len(part[-1])-1, max(pointer[1], pointer[0])-p))
                
                if ORD not in [12, 19, 3, 22, 26, 25]:
                    part[-1] = part[-1][MAX:]
                
                if ORD == 19:
                    app = part.copy()
                    app[-1] = part[-1][MIN:]
                    new_shot_list.append(app)
                    
                    
                    part[-1] = ""
        
        # Saving to the file
        story.save(win.project, win.story)        
        win.current["key_letter"] = ""                       
    
    # Let's get all the rest of the parts from that block so I could insert them
    # as a separate thing later. Because we basically splitting 1 block into 3
    # making the selection. Middle one our new shot_block. And the rest. Should
    # stay the same.
    
    if new_shot:
        num , n = new_shot
        for l, part in enumerate(win.story["scenes"][scene]["shots"][num][-1]):
            if l > n:
                app = part.copy()
                after_shot_list[-1].append(app)
                part[-1] = ""
                if after_shot_list[0] == "shot_block"\
                and win.story["scenes"][scene]["shots"][num][0] == "shot_block":
                    after_shot_list[1] = win.story["scenes"][scene]["shots"][num][1]
    
    if new_shot_list:
        
        #print("NEW: ", new_shot_list)
        #print("KEEP: ", after_shot_list)
        
        nename = "Shot_1"
        count = 1
        while nename in shot_list:
            count = count + 1
            nename = "Shot_"+str(count)
        
        
        num , n = new_shot
        win.story["scenes"][scene]["shots"].insert(num+1, 
        ["shot_block", nename, new_shot_list])
        
        win.story["scenes"][scene]["shots"].insert(num+2, 
        after_shot_list)
        
        # Saving to the file
        story.save(win.project, win.story)  
        
        #print()
        #print("------{ AFTER }--------")
        #print(win.story["scenes"][scene]["shots"])
        #print("------{        }------") 
                    
    clean()           
                
    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], 1)
        pointer[1] = max(pointer[1], 1)
        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:
            del win.text["scene_name"]
            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(frasesurface, x, y)
    layer.paint()
    
    # 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)
    
    # Documentation entry
    def do():
        def after(win, var):
           pass
        
        studio_dialogs.help(win, "help", after, SEARCH=talk.text("documentation_script_writer"))
    
    UI_elements.roundrect(layer, win,
        win.current["w"]/4,
        win.current["h"]-50, 
        40,
        40,
        10,
        do,
        "question")
    
    # 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"
            try:
                del win.text["scene_name"]
            except:
                pass
            
        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"
            try:
                del win.text["scene_name"]
            except:
                pass
            
        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 = {}
        try:
            del win.text["scene_name"]
        except:
            pass
        win.story["selected"] = []
        win.scroll["script"] = 0
        win.current["scene_edited_already"] = False
        
    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 #################
    
    # Here I want to have some checklists. Now... I have 4 types of new check-
    # lists prepared for shots and scene. There are 3 types of checklists for
    # a shot. So I can't just simply generate one on the fly. Since I don't
    # know whether this shot is a simple shot, animated or VFX. And also I
    # don't want to generate folders when they are not nessesary. So I want to
    # implement a kind of selection thingy when if a checklists does not exist.
    
    # Now let's first of all display our checklists properly.
    
    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)
    elif os.path.exists(win.project+"/rnd"+win.cur+"/scene.progress") and not shot:
        checklist.draw(layer, win, win.project+"/rnd"+win.cur+"/scene.progress", back=win.url)
    
    else:
        
        # Now if we have no checklist what so ever. We want to give user a way
        # to choose to generate one.
        
        x = win.current["w"] / 4 * 3 + 10
        y = 10
        width = win.current["w"] / 4 - 20
        height = win.current["h"] - 20
        
        
        if shot:
            
            # If we are in a shot I want to give different option to choose from
            # then if we are just simply in a scene.
            
            shot_options = {
                "shot":"add_shot_live_checklist",
                "shot_anim":"add_shot_anim_checklist",   # First name of new_file then text on screen 
                "shot_vfx":"add_shot_vfx_checklist"
                }
            
            for num, option in enumerate(shot_options):
                
                # We want to draw a button, a rectangle arround it and the text
                # tooltip. 
                
                def do():
                    
                    # First let's make sure that the folder exists. Because
                    # it might not exists. I think doing it automatically
                    # makes sense.
                    
                    try:
                        os.makedirs(win.project+"/rnd"+win.cur)
                    except:
                        pass
                    
                    # Then we copy the file.
                    
                    oscalls.copy_file(
                        win,
                        os.getcwd()+"/new_file/"+option+".progress",
                        "/rnd"+win.cur+"/",
                        "shot.progress")
                    
                
                UI_elements.roundrect(layer, win, 
                    x,
                    y+(50*num),
                    width,
                    40,
                    10,
                    button=do,
                    icon="checklist_new")
                
                UI_color.set(layer, win, "progress_background")
                UI_elements.roundrect(layer, win, 
                    x,
                    y+(50*num),
                    width,
                    40,
                    10,
                    fill=False)
                layer.stroke()
                
                UI_color.set(layer, win, "text_normal")
                layer.set_font_size(20)
                layer.move_to( x+50, y+(50*num)+25)
                layer.show_text(talk.text(shot_options[option]))
                
        else:   
            
            # Now... If it's not a shot. We can do it in one line.
            # It's pretty simple. 
            
            def do():
                    
                # First let's make sure that the folder exists. Because
                # it might not exists. I think doing it automatically
                # makes sense.
                
                try:
                    os.makedirs(win.project+"/rnd"+win.cur)
                except:
                    pass
                
                # Then we copy the file.
                
                oscalls.copy_file(
                    win,
                    os.getcwd()+"/new_file/scene.progress",
                    "/rnd"+win.cur+"/",
                    "scene.progress")
                
            
            UI_elements.roundrect(layer, win, 
                x,
                y,
                width,
                40,
                10,
                button=do,
                icon="checklist_new")
            
            UI_color.set(layer, win, "progress_background")
            UI_elements.roundrect(layer, win, 
                x,
                y,
                width,
                40,
                10,
                fill=False)
            layer.stroke()
            
            UI_color.set(layer, win, "text_normal")
            layer.set_font_size(20)
            layer.move_to( x+50, y+25)
            layer.show_text(talk.text("add_scene_checklist"))
    
    
    ############## 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)
    
    
    #### SHOTS ####
    
    if win.current["script_left_panel"] == "shot":
        
        # Here I want to draw the left panel full of shots and stuff. So you 
        # could access the animation Blend-Files, render them and see analytics
        # or rendering. 
        
        # Since it's the last thing I'm drawing to this layer. I guess we can clip it.
        
        x = 10
        y = 70
        width = win.current["w"] / 4 - 20
        height = win.current["h"] - 80
        
        
        UI_elements.roundrect(layer, win,
            x,
            y, 
            width,
            height,
            10,
            fill=False)
        layer.clip()
        
        
        if "script_shots" not in win.scroll:
            win.scroll["script_shots"] = 0
        
        current_Y_shots = 0
        
        rcolors = [
            "shot_1",
            "shot_2",
            "shot_3",
            "shot_4",
            "shot_5"
            ]
        
        # So let's itterate over a lit of shots we've got from the textview.
        
        for shotis in shot_list:
            
            # Getting the color. It's not always works.
            
            if "shot_colors" not in win.story:
                win.story["shot_colors"] = {}
            
            surl = "/"+scene+"/"+shotis
            
            if surl not in win.story["shot_colors"]:
             
                win.story["shot_colors"][surl] = rcolors[len(win.story["shot_colors"]) % len(rcolors)]
            
            col = win.story["shot_colors"][surl]
            
            UI_color.set(layer, win, "node_background")
            UI_elements.roundrect(layer, win,
                x,
                y+win.scroll["script_shots"]+current_Y_shots, 
                width,
                50,
                10)
            UI_color.set(layer, win, col)
            UI_elements.roundrect(layer, win,
                x+60,
                y+win.scroll["script_shots"]+current_Y_shots+15, 
                10,
                10,
                10)
            
            # SHOT NAME
            UI_color.set(layer, win, "text_normal")
            layer.set_font_size(20)
            layer.move_to( x+90, y+win.scroll["script_shots"] + current_Y_shots+30)
            layer.show_text(shotis)
            
            # ICON
            UI_elements.image(layer, win, 
                "settings/themes/"+win.settings["Theme"]+"/icons/shot.png",
                20, y+win.scroll["script_shots"] + current_Y_shots+5, 40, 40)
            
            # The selection will be badically the current win.cur value. SO...
            
            if surl == win.cur:
                
                UI_color.set(layer, win, "text_normal")
                UI_elements.roundrect(layer, win,
                    x,
                    y+win.scroll["script_shots"]+current_Y_shots, 
                    width,
                    50,
                    10,
                    fill=False)
                layer.stroke()
                
                # If this shot has a folder already. Unfortunatly it's not wise
                # to make it editable. But I already talk about it in the 
                # beggining of this file.
                
                # But a folder button could be cool.
                
                if os.path.exists(win.project+"/rnd"+win.cur):
                    def do():
                        oscalls.Open(win.project+"/rnd"+win.cur)
                    
                    UI_elements.roundrect(layer, win,
                        width-45,
                        y+win.scroll["script_shots"]+current_Y_shots+5, 
                        40,
                        40,
                        10,
                        do,
                        "folder",
                        tip="/rnd"+win.cur ) 
                else:
                    
                    # If there is no folder I want to give people an ability
                    # to edit it. I think let's do it like with checklists.
                    # like a little second button. That if you click it. You
                    # create a text entry. I know. Quite a lot of text entries.
                    # There will be more.
                    
                    if "current_shot_name_editor" not in win.current:
                        win.current["current_shot_name_editor"] = ""
                    

                    # Now if the button is clicked. There will be an editor
                    # let's make one.
                    
                    if win.current["current_shot_name_editor"] == shotis and win.textactive == "shot_name":
                        
                        UI_elements.text(layer, win, "shot_name",
                            x+85,
                            y+win.scroll["script_shots"]+current_Y_shots+5, 
                            width-90,
                            40,
                            set_text=shotis)
                        
                        # Now let's make it applyable. But first we need to filter
                        # the name. So there will not be any weird stuff. So the 
                        # folder when it's created will not make problems.
                         
                        newname = win.text["shot_name"]["text"].replace("/","_").replace(" ", "_")\
                        .replace('"',"_").replace("(","_").replace(")","_").replace("'","_")\
                        .replace("[","_").replace("]","_").replace("{","_").replace("}","_")     
                    
                        if newname not in shot_list:
                            
                            def do():
                                win.current["key_letter"] = ""
                                
                                shot_list[shotis][1] = newname
                                win.cur = "/"+scene+"/"+newname
                                
                                # Saving to the file
                                story.save(win.project, win.story)
                            
                            UI_elements.roundrect(layer, win,
                                width-45,
                                y+win.scroll["script_shots"]+current_Y_shots+5, 
                                40,
                                40,
                                10,
                                button=do,
                                icon="ok")
                           
                    else:
                        
                        # A button to activate the editing I guess.
                        
                        def do():
                            win.current["current_shot_name_editor"] = shotis
                            try:
                                del win.text["shot_name"]
                            except:
                                pass
                            
                            win.textactive = "shot_name"
                            
                        UI_elements.roundrect(layer, win,
                            x+85,
                            y+win.scroll["script_shots"]+current_Y_shots+5, 
                            width-90,
                            40,
                            10,
                            button=do,
                            fill=False)
                        layer.stroke()            
                     
                
                current_Y_shots = current_Y_shots + 60
                
                # Let's make the color selectiong thing. Because I know people
                # gonna eat me alive if the software does everything for them.
                # Especially when it's something that customazible.
                
                for num, col in enumerate(rcolors):
                    
                    if win.story["shot_colors"][surl] == col:
                        
                        # If the current color is the color of the shot then
                        # let's draw a little white thing around it.
                        
                        UI_color.set(layer, win, "text_normal")
                        UI_elements.roundrect(layer, win,
                            x+(width/len(rcolors)*num),
                            y+win.scroll["script_shots"]+current_Y_shots-2, 
                            width/len(rcolors),
                            10,
                            12)
                    
                    UI_color.set(layer, win, col)
                    UI_elements.roundrect(layer, win,
                        x+(width/len(rcolors)*num)+2,
                        y+win.scroll["script_shots"]+current_Y_shots, 
                        width/len(rcolors)-4,
                        10,
                        10)
                    
                    # Also let's make a button that the user can click to change
                    # the color.
                    
                    def do():
                        win.story["shot_colors"][surl] = col
                    UI_elements.roundrect(layer, win,
                        x+(width/len(rcolors)*num),
                        y+win.scroll["script_shots"]+current_Y_shots-2, 
                        width/len(rcolors),
                        20,
                        12,
                        button=do,
                        fill=False)
                    layer.stroke()
                
                current_Y_shots = current_Y_shots + 30
                
                # Now let's draw 4 main folders of the shot. 
                
                # storyboard
                # opengl
                # test_rnd
                # rendered
                
                # There is also an extra folder created always.
                # but since it's very technical let's not include it here. 
                # let's focus on those 4 because for the user these 4 will
                # be our progress bar.
                
                         #####       #####        #####      #####
                ##########   #########   ##########   ########   ##########  
                         #####       #####        #####      #####
                
                # Like 4 links in a chain or something. I think it's a good
                # representation. 
                
                fouricons = {
                    "storyboard":[],
                    "opengl":[],
                    "test_rnd":[],
                    "rendered":[]                    
                    }
                
                fraction = 0.0
                
                # Let's create a variable for the current selected folder.
                
                if shotis+"_active_folder" not in win.current:
                    win.current[shotis+"_active_folder"] = "Pending"
                
                for numb, icon in enumerate(fouricons):
                    
                    # While we are drawing them. Let's find out whether there
                    # are any images inside. If yes. We add this to the over
                    # all percentage.
                    
                    files = []
                    try:
                        files = sorted(os.listdir(win.project+"/rnd"+win.cur+"/"+icon))
                    except:
                        pass
                    
                    fouricons[icon] = files
                    
                    if files:
                        fraction = 0.25*(numb+1)
                   
                    # If the icon is currently selected.
                   
                    if win.current[shotis+"_active_folder"] == icon:
                        UI_color.set(layer, win, "progress_time")
                        UI_elements.roundrect(layer, win,
                            x+(width/5)*numb+(width/10)+20,
                            y+win.scroll["script_shots"]+current_Y_shots-2, 
                            40,
                            40,
                            20)
                    
                    def do():
                        win.current[shotis+"_active_folder"] = icon
                    
                    UI_elements.roundrect(layer, win,
                        x+(width/5)*numb+(width/10)+20,
                        y+win.scroll["script_shots"]+current_Y_shots-2, 
                        40,
                        40,
                        20,
                        button=do,
                        icon=icon,
                        tip=icon)
                
                
                current_Y_shots = current_Y_shots + 50
                
                # Let's find out which one is going to be selected.
                
                if win.current[shotis+"_active_folder"] == "Pending":
                    if fouricons["rendered"]:
                        win.current[shotis+"_active_folder"] = "rendered"
                    elif fouricons["test_rnd"]:
                        win.current[shotis+"_active_folder"] = "test_rnd"
                    elif fouricons["opengl"]:
                        win.current[shotis+"_active_folder"] = "opengl"
                    else:
                        win.current[shotis+"_active_folder"] = "storyboard"
                
                
                # Now let's draw a line that will act almost like a progress
                # bar of a kind.
                
                # It will be made of 4 circles stading on a line. 
                
                UI_color.set(layer, win, "progress_background")
                UI_elements.roundrect(layer, win,
                    x+20,
                    y+win.scroll["script_shots"]+current_Y_shots-2, 
                    width-40,
                    0,
                    5)
                
                UI_color.set(layer, win, "progress_active")
                UI_elements.roundrect(layer, win,
                    x+20,
                    y+win.scroll["script_shots"]+current_Y_shots-2, 
                    (width-40)*fraction,
                    0,
                    5)
                
                # Now the 4 circles. 
                
                for numb, icon in enumerate(fouricons):
                    
                    
                    UI_color.set(layer, win, "progress_background")
                    if fouricons[icon]: # If this folder has any files.
                        UI_color.set(layer, win, "progress_active")
                    UI_elements.roundrect(layer, win,
                        x+(width/5)*numb+(width/10)+30,
                        y+win.scroll["script_shots"]+current_Y_shots-7, 
                        0,
                        0,
                        10)
                
                current_Y_shots = current_Y_shots + 50
                
                # Now after we have the progress bar / selection type thingy.
                # let's do a preview of the render. Usually. When rendering
                # using Blender-Organizer legacy ( or blender console ) it makes
                # files like 0001.png, 0002.png, 0003.png and so on. Now
                # user might any type of stuff in that folder. And I don't want
                # a broken program if stuff like this happens. So.
                
                if shotis+"_active_folder_item" not in win.current:
                    win.current[shotis+"_active_folder_item"] = 0
                
                # Making sure that we never going to select something beyond selectable.
                if win.current[shotis+"_active_folder_item"] > len(fouricons[win.current[shotis+"_active_folder"]])-1:
                    win.current[shotis+"_active_folder_item"] = len(fouricons[win.current[shotis+"_active_folder"]])-1
                
                
                # This will be the user selected file inside the folder.
                
                
                # The frame. In case image fails to load.
                
                UI_color.set(layer, win, "progress_background")
                UI_elements.roundrect(layer, win,
                    x+5,
                    y+win.scroll["script_shots"]+current_Y_shots-7, 
                    width-10,
                    200,
                    10,
                    fill=False)
                layer.stroke()
                
                # Image it self.
                if fouricons[win.current[shotis+"_active_folder"]]:
                    
                    imageurl = win.project+"/rnd"+win.cur+"/"+win.current[shotis+"_active_folder"]+"/"+fouricons[win.current[shotis+"_active_folder"]][win.current[shotis+"_active_folder_item"]]
                    
                    UI_elements.image(layer, win, 
                        imageurl,
                        x+10,
                        y+win.scroll["script_shots"]+current_Y_shots-2,
                        int(width-20),
                        int(190),
                        cell="shot_renders")
                    
                    # Well how to live without a clickable openable thingy.
                    
                    def do():
                        oscalls.file_open(win, imageurl)
                    UI_elements.roundrect(layer, win,
                        x+5,
                        y+win.scroll["script_shots"]+current_Y_shots-7, 
                        width-10,
                        200,
                        10,
                        button=do,
                        fill=False)
                    layer.stroke()
            
                
                current_Y_shots = current_Y_shots + 210
                
                # After we drew our image. Let's draw a little timeline thing.
                # so the user could select which frame from the animation they
                # want to see. Basically a little bar. I guess. IDK. Like 
                # Blender's timeline I guess. But later I will draw a time
                # graph on it. So it's not as simple as that.
                
                UI_color.set(layer, win, "dark_overdrop")
                layer.rectangle(
                    x+5,
                    y+win.scroll["script_shots"]+current_Y_shots, 
                    width-10,
                    100)
                layer.fill()
                
                numofis = len(fouricons[win.current[shotis+"_active_folder"]])
                
                # Here as you can see I made the the rectangle a 100 pixels high
                # this is for 1 simple reason. To be able to draw analytics.
                
                # But.
                
                # There are like one million problems with it. Let's go over them.
                
                # * There are multiple blend files each one with analytics data.
                
                # * Reading JSON files and drawing graphs is not a trivial thing
                #   requiring cashing of the image. Such as in Analytics window.
                #   Bull will see.
                
                # * During rendeing the DATA changes. And I want to see the up
                #   to date data at all times.
                
                # Let's try to implement it the simple way. Reading everything
                # live. I've done that in Blender-Organizer. But the data was
                # way simpler.
                
                alldata = {}
                largest = 1
                
                # WAIT extra might not exists.
                
                try:
                    for filename in os.listdir(win.project+"/rnd"+win.cur+"/extra"):
                        if filename.endswith(".blend.json"):
                            
                            # I want to now open JSON FILE for each one and parse
                            # it. Actually when I think about it. It's not supposed
                            # to be that bad. But this computer has an SSD. LOL.
                            
                            data = {}
                            try:
                                with open(win.project+"/rnd"+win.cur+"/extra/"+filename) as json_file: 
                                    data = json.load(json_file)
                                
                                # Since I'm inside try I can do some wild stuff here.
                                data = data["analytics"][win.current[shotis+"_active_folder"]]
                                
                                alldata[filename.replace(".json", "")] = data
                                
                                for i in data:
                                    if data[i] > largest:
                                        largest = data[i]
                                
                            except:
                                pass
                except:
                    pass
                    
                # So let's now read through all the data that we have
                for n, blend in enumerate(alldata):
                    
                    data = alldata[blend]
                    
                    # I want each new file to have it's own color. So
                    
                    UI_color.set(layer, win, rcolors[n % len(rcolors)])
                    layer.move_to(
                        x+5,
                        y+win.scroll["script_shots"]+current_Y_shots+100
                        )
                    
                    # Now let's draw everything.
                    for numb, fil in enumerate(fouricons[win.current[shotis+"_active_folder"]]):
                        
                        if str(numb+1) in data:
                            layer.line_to(
                                x+5+(width-10)/numofis*(numb+0.5),
                                (y+win.scroll["script_shots"]+current_Y_shots+100)-(100/largest*data[str(numb+1)])
                                )
                    layer.stroke()
                
                # Funny that it didn't really stuck too much like this. Please 
                # let me know if on your machine this way of doing it is hell 
                # a slow. 
                    
                for numb, fil in enumerate(fouricons[win.current[shotis+"_active_folder"]]):
                    
                    
                    # Here I'm going to put some logic. That will enable me to
                    # scroll trough the images. In a way that allows me to 
                    # preview the animation. Simple button wouldn't work since
                    # it's waiting for the user to release the button to be
                    # activated. This one will be activated by just dragging
                    # across.
                    
                    # Also my roundrect buttons are not ideal when you have little
                    # space and 10000 frames. 
                    
                    fill = False
                    
                    if int(win.current["mx"]) in range(int(x+5+(width-10)/numofis*numb),int(x+5+(width-10)/numofis*numb+(width-10)/numofis))\
                    and int(win.current["my"]) in range(int(y+win.scroll["script_shots"]+current_Y_shots), int(y+win.scroll["script_shots"]+current_Y_shots+100)):
                        
                        # Before we are doing the logic. I want to give user a
                        # tooltip about render analytics. So let's do this.
                        
                        tip = ""
                        for n, blend in enumerate(alldata):
                            data = alldata[blend]
                            if str(numb+1) in data:
                                tip = tip + blend+" "+UI_math.timestring(data[str(numb+1)]/1000000)+"\n"
                        if tip:
                            tip = tip[:-1] # Removing the last \n 
                            UI_elements.tooltip(win, tip)
                            
                        # Now let's do the fill and other stuff
                        
                        fill = True
                        
                        if win.current["LMB"]:
                            
                            win.current[shotis+"_active_folder_item"] = numb
                    
                    if fill or win.current[shotis+"_active_folder_item"] == numb:
                        
                        UI_color.set(layer, win, "progress_time")
                        layer.rectangle(
                            x+5+(width-10)/numofis*numb,
                            y+win.scroll["script_shots"]+current_Y_shots, 
                            (width-10)/numofis,
                            100)
                        layer.fill()
                    
                
                current_Y_shots = current_Y_shots + 110
                
                # Okay let's put blend file from the shot. So you could actually
                # do work on it. 
                
                # But first. I want to add a seach promt. So I could add new ones
                # the same way I do it in any other window. By searching. I think
                # it's important to keep the workflow similar. 
                
                # I think that if we have no blend files at all. It might give you
                # to make a new one with the name of the shot. And all the rest will
                # be done by searching. Yeah. Makes sense. Wait. I can put the name of
                # the shot in the search. Hm... Okay. Let's make the seach icon first.
                
                UI_elements.image(layer, win, 
                    "settings/themes/"+win.settings["Theme"]+"/icons/search.png",
                    x+10,
                    y+win.scroll["script_shots"]+current_Y_shots,
                    40,
                    40)
                
                # Now beside it will be out text entry.
                
                UI_elements.text(layer, win, "shot_search",
                    x+50,
                    y+win.scroll["script_shots"]+current_Y_shots, 
                    width-55,
                    40)
                
                current_Y_shots = current_Y_shots + 50
                
                # Now let's get the blend file list. It's going to take a few 
                # stept. First we are going to try getting all the files in the
                # folder. Then filter them by .blend in the end. We do not want
                # to show you the .blend1 files. We don't want to show you
                # anything. 
                
                blendfiles = []
                
                try:
                    for blend in os.listdir(win.project+"/rnd"+win.cur):
                        if blend.endswith(".blend"):
                            blendfiles.append(blend)
                except:
                    pass
                
                # Now since we've got our blendfiles list. We can now draw them.
                # But I want to preserve the countinuity with the rest of the 
                # software. So I will need to draw a little Blendfile node each
                # time. For which I'm going to create a node. But this time it's
                # going to have 2 icons at the bottom.
                
                        ##############    ##############    ##############
                        #  01.blend  #    #  02.blend  #    #  03.blend  #
                        ##############    ##############    ##############
                        #    ____    #    #    ____    #    #    ____    #
                        #  ( 0  0 )  #    #  ( 0  0 )  #    #  ( 0  0 )  #
                        #    )  (    #    #    )  (    #    #    )  (    #
                        #    \__/    #    #    \__/    #    #    \__/    #
                        #            #    #            #    #            #
                        ##############    ##############    ##############
                        #  0  #  0   #    #  0   #  0  #    #  0   #  0  #
                        ##############    ##############    ##############
                
                # Those 2 icons in the bottom of each will be buttons for render
                # and linking. The linking is what you do to put assets inside
                # animation files. A new dialog should be developped for this.
                
                # The rendering will resemble rendering of Blender-Organizer with
                # render times analytics and stuff. But will be way more extended.
                # For example with an ability to open a render task on another
                # computer. So groups of people could work together.
                
                tileX = 5
                
                searchis = win.text["shot_search"]["text"].replace("/","_").replace(" ", "_")\
                        .replace('"',"_").replace("(","_").replace(")","_").replace("'","_")\
                        .replace("[","_").replace("]","_").replace("{","_").replace("}","_") 
                
                for bn,  blend in enumerate(blendfiles):
                    
                    # Each one will be drawn in it's own little layer. Because
                    # I want the top bar to have a nice rounded corner and also
                    # the image to be cut.
                    
                    # Each one here will 128 pixels wide. ( Because this is the
                    # resolution of blender-thumbnailer.py thumbnails. And I 
                    # want to save horizontal resolution as much as possible
                    
                    # But before I render a Blend. I want to exclude it if it's
                    # not in a search.
                    
                    if searchis and searchis.lower() not in blend.lower():
                        continue
                    
                    # Making the layer
                    nodesurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 128, 198)
                    node = cairo.Context(nodesurface)
                    node.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
                    
                    UI_elements.roundrect(node, win, 
                        0,
                        0,
                        128, 
                        198,
                        10,
                        fill=False)
                    
                    node.clip()
                    
                    # Background
                    UI_color.set(node, win, "dark_overdrop")
                    node.rectangle(0,0,128, 198)
                    node.fill()
                    
                    # Blender icon
                    
                    UI_elements.image(node, win, 
                        win.project+"/rnd"+win.cur+"/"+blend,
                        0,
                        20,
                        128,
                        128, cell="shot_blends")
                    
                    # Banner
                    UI_color.set(node, win, "node_blendfile") 
                    node.rectangle(0,0,128, 20)
                    node.fill()
                    
                    # Filename
                    UI_color.set(node, win, "text_normal")
                    node.set_font_size(12)
                    node.move_to(5, 15)
                    node.show_text(blend)
                    
                    # Outputting the layer
                    layer.set_source_surface(nodesurface, 
                            x+tileX,
                            y+win.scroll["script_shots"]+current_Y_shots)
                    layer.paint()
                    
                    # Here we gonna out 3 buttons:
                    
                    # 1. Launch the Blend-File
                    # 2. Link into Blend-File
                    # 3. Render Blend-File
                    
                    # Launch the Blend file:
                    def do():
                        oscalls.file_open(win, win.project+"/rnd"+win.cur+"/"+blend)
                    
                    UI_elements.roundrect(layer, win,
                        x+tileX,
                        y+win.scroll["script_shots"]+current_Y_shots, 
                        128,
                        148,
                        10,
                        button=do,
                        fill=False,
                        tip=blend)
                    layer.stroke()
                    
                    # Link things into Blend-File
                    def do():
                        
                        # I'm using a dialog here. Because I want to return back
                        # to the shot we were in. But I don't really want to do
                        # anything after the dialog is closed. So there is this
                        # empty function.
                        
                        def after(win, var):
                            pass
                        
                        studio_dialogs.asset_link(win, "asset_linking", after, "/rnd"+win.cur+"/"+blend)
                    
                    UI_elements.roundrect(layer, win,
                        x+tileX+20,
                        y+win.scroll["script_shots"]+current_Y_shots+152, 
                        40,
                        40,
                        10,
                        icon="obj_link",
                        button=do,
                        tip=talk.text("link_shot_blend_tooltip")+blend)
                    
                    # Render
                    def do():
                        def after(win, var):
                            pass
                        
                        studio_dialogs.render(win, "render_setup", after, "/rnd"+win.cur+"/"+blend)
                    
                    UI_elements.roundrect(layer, win,
                        x+tileX+65,
                        y+win.scroll["script_shots"]+current_Y_shots+152, 
                        40,
                        40,
                        10,
                        icon="render",
                        button=do,
                        tip=talk.text("render_shot_blend_tooltip")+blend)
                    
                    tileX = tileX + 150
                    if tileX + 128 > width - 10 and bn != len(blendfiles)-1:
                        tileX = 5
                        current_Y_shots = current_Y_shots + 205
                
                
                # Now before we are finished. We want to able to add new files
                # by typing the names in the search.
                
                if not blendfiles and not searchis:
                    searchis = shotis
                
                if not searchis.endswith(".blend"):
                    searchis = searchis + ".blend"
                
                if searchis != ".blend" and searchis not in blendfiles:
                    
                    # There will be 2 buttons. To add a brand new file and to
                    # copy one from a different shot. In Blender-Oraniger it
                    # had a copy-paste kind of system for this. But since we
                    # have a file selector. I'm going to use it instead. Tho
                    # tell me if a copy-paste for files is a cool idea.
                    
                    if tileX + 128 > width - 10:
                        tileX = 5
                        current_Y_shots = current_Y_shots + 205
                    
                    # ADD NEW BLEND
                    
                    def do():
                        
                        # First let's make sure that the folder exists. Because
                        # it might not exists. I think doing it automatically
                        # makes sense.
                        
                        try:
                            os.makedirs(win.project+"/rnd"+win.cur)
                        except:
                            pass
                        
                        # Then we copy the file.
                        
                        oscalls.copy_file(
                            win,
                            os.getcwd()+"/new_file/rnd.blend",
                            "/rnd"+win.cur+"/",
                            searchis)
                        
                        # And clear the search
                        
                        win.text["shot_search"]["text"] = ""
                        win.images = {}
                        
                    UI_elements.roundrect(layer, win,
                        x+tileX,
                        y+win.scroll["script_shots"]+current_Y_shots, 
                        128,
                        198,
                        10,
                        button=do)
                    
                    # A little surrounding thing.
                    
                    UI_color.set(layer, win, "progress_background")
                    UI_elements.roundrect(layer, win,
                        x+tileX,
                        y+win.scroll["script_shots"]+current_Y_shots, 
                        128,
                        198,
                        10,
                        fill=False)
                    layer.stroke()
                    
                    # Icon
                    
                    UI_elements.image(layer, win, 
                        "settings/themes/"+win.settings["Theme"]+"/icons/new_file.png",
                        x+tileX+44,
                        y+win.scroll["script_shots"]+current_Y_shots + 70,
                        40, 40)
                    
                    # preiew
                    
                    UI_color.set(layer, win, "text_normal")
                    layer.set_font_size(12)
                    layer.move_to(x+tileX+64-len(searchis)*4,
                        y+win.scroll["script_shots"]+current_Y_shots+150)
                    layer.show_text(searchis)
                    
                    tileX = tileX + 150
                    if tileX + 128 > width - 10:
                        tileX = 5
                        current_Y_shots = current_Y_shots + 205
                    
                    # And a copy file here too
                    
                    # COPY BLEND
                    
                    def do():
                        
                        # Now the copy function going to be a tiny bit harder
                        # since we will need to launch a dialog for you to
                        # select the file. I think you gonna look for files 
                        # from this scene more often. So let's do that.
                        
                        def after(win, var):
                            if var:
                                try:
                                    os.makedirs(win.project+"/rnd"+win.cur)
                                except:
                                    pass
                                
                                # Then we copy the file.
                                
                                oscalls.copy_file(
                                    win,var,
                                    "/rnd"+win.cur+"/",
                                    searchis)
                                
                                # And clear the search
                                
                                win.text["shot_search"]["text"] = ""
                                win.images = {}
                          
                        studio_dialogs.file_select(win, shotis+"_blends", after, force=True, 
                            IMAGE=False, BLEND=True, VIDEO=False, FILE=False, CHR=False, VEH=False, 
                            LOC=False, OBJ=False, RND=True, FOLDER=False, SEARCH=scene)
                    
                    UI_elements.roundrect(layer, win,
                        x+tileX,
                        y+win.scroll["script_shots"]+current_Y_shots, 
                        128,
                        198,
                        10,
                        button=do)
                    
                    # A little surrounding thing.
                    
                    UI_color.set(layer, win, "progress_background")
                    UI_elements.roundrect(layer, win,
                        x+tileX,
                        y+win.scroll["script_shots"]+current_Y_shots, 
                        128,
                        198,
                        10,
                        fill=False)
                    layer.stroke()
                    
                    # Icon
                    
                    UI_elements.image(layer, win, 
                        "settings/themes/"+win.settings["Theme"]+"/icons/copy_file.png",
                        x+tileX+44,
                        y+win.scroll["script_shots"]+current_Y_shots + 70,
                        40, 40)
                    
                    # preiew
                    
                    UI_color.set(layer, win, "text_normal")
                    layer.set_font_size(12)
                    layer.move_to(x+tileX+64-len(searchis)*4,
                        y+win.scroll["script_shots"]+current_Y_shots+150)
                    layer.show_text(searchis)
                    
                    
                    
                current_Y_shots = current_Y_shots + 205
                
            else:
                
                # If the shot is not selected I want to be able to select it
                # even if I can't find it in the text of the script.
                def do():
                    win.cur = surl
                    
                
                UI_elements.roundrect(layer, win,
                    x,
                    y+win.scroll["script_shots"]+current_Y_shots, 
                    width,
                    50,
                    10,
                    button=do,
                    fill=False)
                layer.stroke()
                
                
            
                current_Y_shots = current_Y_shots + 60
    
        # Scroll
        UI_elements.scroll_area(layer, win, "script_shots", 
            x+0,
            y+0,
            width, 
            height,
            current_Y_shots,
            bar=True,
            mmb=True)
    
    
    
    return surface
