diff --git a/studio/studio_assetLayer.py b/studio/studio_assetLayer.py index 7bcd244..eef5ad3 100644 --- a/studio/studio_assetLayer.py +++ b/studio/studio_assetLayer.py @@ -971,9 +971,28 @@ def layer(win): # If it's a shot let's mark in the different color. if block[0]: - UI_color.set(layer, win, "node_badfile") + if "shot_colors" not in win.story: + win.story["shot_colors"] = {} + + surl = "/"+scene+"/"+block[0] + + 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] + UI_color.set(layer, win, col) else: - UI_color.set(layer, win, "dark_overdrop") + UI_color.set(layer, win, "node_background") UI_elements.roundrect(layer, win, x, y+win.scroll["asset_scenes"]+current_Y_scenes, diff --git a/studio/studio_gtk.py b/studio/studio_gtk.py index 031c46f..f18799d 100644 --- a/studio/studio_gtk.py +++ b/studio/studio_gtk.py @@ -93,6 +93,7 @@ def run(project, win): win.calllayer = False win.layercashe = {} # Here I gonna store layers that are inactive to speed up stuff win.checklists = {} + win.blink = False # Cursor blinking thing. if pm_project.is_legacy(project): win.story = story.get_legacy(project) @@ -173,6 +174,10 @@ def pmdrawing(pmdrawing, main_layer, win): # FPS counter win.fFPS = datetime.datetime.now() win.tFPS = win.fFPS - win.sFPS + + if win.current["frame"] % 5 == 0: + win.blink = not win.blink # Iterating the blink + if win.current["frame"] % 10 == 0: win.FPS = int ( 1.0 / ( win.tFPS.microseconds /1000000)) diff --git a/studio/studio_scriptLayer.py b/studio/studio_scriptLayer.py index 446e939..6d61198 100644 --- a/studio/studio_scriptLayer.py +++ b/studio/studio_scriptLayer.py @@ -25,6 +25,7 @@ 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 @@ -109,7 +110,7 @@ def layer(win): # MARK SHOT def do(): - print("Mark Shot") + win.current["key_letter"] = chr(19) UI_elements.roundrect(layer, win, win.current["w"]/4+5, @@ -119,11 +120,11 @@ def layer(win): 10, do, "shot_new", - talk.text("add_shot_tooltip")) + talk.text("add_shot_tooltip")+"\n\n[Ctrl - S]") # MARK ASSET def do(): - print("Mark ASSET") + win.current["key_letter"] = chr(12) UI_elements.roundrect(layer, win, win.current["w"]/4+55, @@ -133,11 +134,16 @@ def layer(win): 10, do, "obj_link", - talk.text("add_shot_tooltip")) + talk.text("add_asset_tooltip")+"\n\n[Ctrl - L]") # Do DIALOGUE def do(): - print("Mark Phrase") + + # 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, @@ -147,11 +153,11 @@ def layer(win): 10, do, "frase_new", - talk.text("add_phrase_tooltip")) + talk.text("add_phrase_tooltip")+"\n\n[Ctrl - D]") # ADD IMAGE def do(): - print("Add Image") + win.current["key_letter"] = chr(9) UI_elements.roundrect(layer, win, win.current["w"]/4+155, @@ -161,7 +167,7 @@ def layer(win): 10, do, "image_link", - talk.text("add_image_script_tooltip")) + 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 @@ -332,6 +338,10 @@ def layer(win): 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 @@ -343,31 +353,52 @@ def layer(win): 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(shots, win, "node_background") - shots.rectangle(0,0,width, height) - shots.fill() + 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 + # 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"] = "" - pointer = [0,0] # The editing cursor - point = 0 # The current place in the scene - if scene in win.story["pointers"]: - pointer = win.story["pointers"][scene] + # 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. - # Removing highlight + 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): @@ -375,16 +406,23 @@ def layer(win): win.current["script_shot_higlight"] = "" - # Okay I guess let's itterrate over the scene and see what's going to happen + # 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. - shotpart = 0 - shotis = "" + # Same idea for the selection cursor. + ss = 0 # The pixel where to start drawing the selection cursor. + smx = ss - ss = 0 # THE START OF SELECTION BOX - + # Another one of these for the rectangles under frases. This one is Y location + # instead. frasepart = 0 - # Okay so nothing is in the scene we want to create a text block of 1 character + # This is the scroll when typing. + + putscroll = 0 + + # 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. @@ -392,55 +430,143 @@ def layer(win): win.story["scenes"][scene]["shots"] = [[ "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', []] + # while text has just 2. ['text_block', []]. 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 NOTHING IN THE PART + + # 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 NOTHING IN THE PART + # 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] - p = point - count_newlines = t.count("\n") + # 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": - if ss: - UI_color.set(text, win, "progress_background") - text.rectangle( - ss, - win.scroll["script"] + current_Y, - mt-ss, - 30) - text.stroke() - + + + # 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, @@ -449,45 +575,63 @@ def layer(win): 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, "progress_background") + + 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+6, + win.scroll["script"] + current_Y+30, len(part[1][-1])*12+12, - 28, - 10, - fill=False) + 0, + 3) - assets.stroke() + # 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. - # So here I want to put a button for editing the name of the phrase. if "current_name_frase_editing" not in win.current: win.current["current_name_frase_editing"] = False - - def do(): - - if not win.previous["current_name_frase_editing"]: - print(part[1][-1]) - win.current["current_name_frase_editing"] = [num, n] - if "current_name_frase_editing" in win.text: - win.text["current_name_frase_editing"]["text"] = part[1][-1] - UI_elements.roundrect(assets, win, - 200, - win.scroll["script"] + current_Y+6, - width-400, - 28, - 10, - button=do, - offset=[x,y]) + win.previous["current_name_frase_editing"] = False - # Now let's drawa little text editor with in a text editor. IK wild. + # 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]: @@ -505,29 +649,84 @@ def layer(win): # First let's make the apply button. And I guess the enter key. - if win.text["current_name_frase_editing"]["text"] != part[1][-1]: - def do(): - part[1][-1] = win.text["current_name_frase_editing"]["text"] - win.current["current_name_frase_editing"] = False - win.current["LMB"] = False - win.previous["LMB"] = False - win.textactive = False - win.current["key_letter"] = "" - - UI_elements.roundrect(text, win, - width-280, - win.scroll["script"] + current_Y-5, - 40, - 40, - 10, - button=do, - icon="ok", - offset=[x,y]) + def linking(): + print("linking") - if 65293 in win.current["keys"]: - do() - win.current["keys"] = [] + 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( @@ -536,24 +735,34 @@ def layer(win): ) text.show_text(part[1][-1]) + # Giving it a new line. - - - - #point = point + len(part[1][-1]) #################### <<<<<< POINT 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(assets, win, "dark_overdrop") - UI_elements.roundrect(assets, win, + UI_color.set(frases, win, "dark_overdrop") + UI_elements.roundrect(frases, win, 200, win.scroll["script"] + frasepart, width-400, @@ -561,13 +770,44 @@ def layer(win): 10) frasepart = 0 - - + # MAKING A NEW LINE - #### IMAGE ### + 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): @@ -585,23 +825,93 @@ def layer(win): 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 + 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 ############### - ### 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): - count_spaces = t.count(" ") + # 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 + #point = point + 1 #################### <<<<<< POINT if assetpart: @@ -610,49 +920,72 @@ def layer(win): shotpart = xb if ss: - UI_color.set(text, win, "progress_background") - text.rectangle( - ss, - win.scroll["script"] + current_Y, - mt-ss, - 30) - text.stroke() + 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 - continue + + + 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): - # IF TOO MUCH. DO NEXT 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(text, win, "progress_background") - text.rectangle( + + UI_color.set(assets, win, "node_blendfile") + UI_elements.roundrect(assets, win, ss, - win.scroll["script"] + current_Y, - mt-ss, - 30) + win.scroll["script"] + current_Y+5, + smx-ss, + 26, + 10) text.stroke() ss = xb + current_Y = current_Y + 30 - - - + - # DRAWING ASSET HIGLIGHT + # This is logic to draw ASSETS higlights. if part[0] == "link" and part[1] != assetis and not assetpart: assetpart = tileX @@ -679,16 +1012,13 @@ def layer(win): win.current["script_asset_higlight"] = assetis if assetis == win.current["script_asset_higlight"]: - UI_color.set(assets, win, "progress_background") + UI_color.set(assets, win, "text_normal") UI_elements.roundrect(assets, win, - assetpart-5, - win.scroll["script"] + current_Y+8, + assetpart-6, + win.scroll["script"] + current_Y+26, tileX - assetpart + len(word)*12+12, - 22, - 10, - fill=False) - - assets.stroke() + 0, + 3) assetpart = tileX @@ -698,29 +1028,40 @@ def layer(win): assetpart = 0 assetis = "" - ## HIGLIGHTING SHOTS ## + # 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. + # show. But not too much. Let's actually write the colors into the story + # data. Why not. - rcolors = [ - "node_imagefile", - "node_videofile", - "darker_parts", - "node_blendfile", - "node_badfile", - "progress_time" - ] + if "shot_colors" not in win.story: + win.story["shot_colors"] = {} - col = rcolors[num % len(rcolors)] + 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)) : @@ -728,8 +1069,6 @@ def layer(win): win.current["script_shot_higlight"] = shotis UI_color.set(shots, win, col) - if shotis == win.current["script_shot_higlight"] or shot == shotis: - UI_color.set(shots, win, "node_script") UI_elements.roundrect(shots, win, shotpart-6, win.scroll["script"] + current_Y+5, @@ -737,8 +1076,25 @@ def layer(win): 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] @@ -748,9 +1104,12 @@ def layer(win): - # This is our word + # 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, @@ -758,43 +1117,51 @@ def layer(win): ) text.show_text(word) - # DRAWING SELECTION ALPHA - if 65363 in win.current["keys"]: - pointer[0] = pointer[0]+1 - if not 65506 in win.current["keys"]: - pointer[1] = pointer[0] - win.current["keys"].remove(65363) - - - if 65361 in win.current["keys"]: - pointer[0] = pointer[0]-1 - if not 65506 in win.current["keys"]: - pointer[1] = pointer[0] - win.current["keys"].remove(65361) - - - if 65362 in win.current["keys"]: # UP - pointer[0] = pointer[0]-min(len(line), int((mt-12)/12)) # STILL BUGGY - if not 65506 in win.current["keys"]: - pointer[1] = pointer[0] - win.current["keys"].remove(65362) - - if 65364 in win.current["keys"]: # DOWN - pointer[0] = pointer[0]+min(len(line), int((mt-12)/12)) # STILL BUGGY - if not 65506 in win.current["keys"]: - pointer[1] = pointer[0] - win.current["keys"].remove(65364) - + # 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. - # PRESSING A KEY TO TYPE I GUESS - if min(pointer[1], pointer[0]) in range(point, point+len(word)+1) and not ss: + 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 + + # 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 max(pointer[1], pointer[0]) in range(point, point+len(word)+1): + 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. - # DEVELOPING WHERE THE POINTER IS OMG 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] @@ -805,127 +1172,415 @@ def layer(win): UI_color.set(text, win, "text_normal") text.set_font_size(10) text.move_to( - tileX+(max(pointer[1], pointer[0])-point)*12-26, + tileX+(pointer[0]-point)*12-26, win.scroll["script"] + current_Y+35, ) - text.show_text(str(pointer[0])+"["+c+"]"+str(pointer[1])) - if ss: - UI_color.set(text, win, "progress_background") - text.rectangle( - ss, - win.scroll["script"] + current_Y, - tileX+(max(pointer[1], pointer[0])-point)*12-ss, - 30) - text.stroke() - - ss = 0 - - if win.current["key_letter"] and not win.textactive: + text.show_text(str(pointer[0])+"["+c+"]") + + # Now doing it again for the second pointer. If you + # remeber, We have 2. try: - ORD = ord(win.current["key_letter"]) + c = part[-1][pointer[1]-p] except: - ORD = 0 - print(ORD) + c = "!!" - win.scroll["script"] = min(0 - current_Y + width/2, win.scroll["script"]) - if ORD not in range(32) or ORD in range(127, 160): - part[-1] = \ - part[-1][:min(pointer[1], pointer[0])-p]+\ - win.current["key_letter"]+\ - part[-1][max(pointer[1], pointer[0])-p:] - - pointer[0] = pointer[0] + 1 - pointer[1] = pointer[0] + 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 ORD == 13: # ENTER - if part[-1][min(pointer[1], pointer[0])-p-1] == "\n" and part[0] != "text": - - block[-1].insert(n+1, - ["text", "\n"] - ) - block[-1].insert(n+2, - ["text", part[-1][max(pointer[1], pointer[0])-p:]] - ) - - part[-1] = \ - part[-1][:min(pointer[1], pointer[0])-p-1] - - else: - part[-1] = \ - part[-1][:min(pointer[1], pointer[0])-p]+\ - "\n"+\ - part[-1][max(pointer[1], pointer[0])-p:] - - pointer[0] = pointer[0] + 1 - pointer[1] = pointer[0] + if 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 ORD == 4: # CTRL D ( FOR SOME REASON) - - block[-1].insert(n+1, - ["frase", ["text", " "], " "] - ) - block[-1].insert(n+2, - ["text", part[-1][max(pointer[1], pointer[0])-p:]] - ) - - part[-1] = \ - part[-1][:min(pointer[1], pointer[0])-p] - pointer[0] = pointer[0] + 1 - pointer[1] = pointer[0] - - # Activating the editing of the name automatically - if "current_name_frase_editing" in win.text: - win.text["current_name_frase_editing"]["text"] = "" - if "current_name_frase_editing" not in win.current: - win.current["current_name_frase_editing"] = False - win.current["current_name_frase_editing"] = [num, n+1] - win.textactive = "current_name_frase_editing" + if ss: - if ORD == 8: # BACKSPACE - if pointer[1] == pointer[0]: - part[-1] = \ - part[-1][:min(pointer[1], pointer[0])-p-1]+\ - part[-1][max(pointer[1], pointer[0])-p:] - - pointer[0] = pointer[0] - 1 - pointer[1] = pointer[0] - else: - part[-1] = \ - part[-1][:min(pointer[1], pointer[0])-p]+\ - part[-1][max(pointer[1], pointer[0])-p:] - - pointer[0] = min(pointer[1], pointer[0]) - pointer[1] = pointer[0] - - if ORD == 127: # DELETE (FORWARD) - part[-1] = \ - part[-1][:min(pointer[1], pointer[0])-p]+\ - part[-1][max(pointer[1], pointer[0])-p+1:] - - + 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) - win.current["key_letter"] = "" + 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() - print(block) - print() - - - - # Now let's move the tileX + # 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 - #if count_spaces: - # point = point + 1 #################### <<<<<< POINT - # tileX = tileX + 12 - # count_spaces = count_spaces - 1 + # 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) + + # 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: + + #print("------{ BEFORE }--------") + #print(win.story["scenes"][scene]["shots"]) + #print("------{ }------") + #print() + + + #print() # For testing + + for u, stuff in enumerate(selecwords): + part, p, num, n = stuff + + block = win.story["scenes"][scene]["shots"][num] + + 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() + + + + 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 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]: + 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]: + 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 @@ -938,8 +1593,8 @@ def layer(win): else: pointer[0] = min(pointer[0], point) pointer[1] = min(pointer[1], point) - pointer[0] = max(pointer[0], 0) - pointer[1] = max(pointer[1], 0) + pointer[0] = max(pointer[0], 1) + pointer[1] = max(pointer[1], 1) win.story["pointers"][scene] = pointer # Selecting the shot @@ -949,6 +1604,7 @@ def layer(win): 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"] @@ -967,6 +1623,10 @@ def layer(win): # 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() @@ -1018,6 +1678,7 @@ def layer(win): win.scroll["script"] = 0 win.cur = "/"+left win.url = "script" + del win.text["scene_name"] UI_elements.roundrect(layer, win, win.current["w"]/2-45, @@ -1033,6 +1694,7 @@ def layer(win): win.scroll["script"] = 0 win.cur = "/"+right win.url = "script" + del win.text["scene_name"] UI_elements.roundrect(layer, win, win.current["w"]/2+5, @@ -1129,7 +1791,518 @@ def layer(win): 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) + + 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"]]) + + 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)): + 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. + + ######### VERSION 20.125 I'm tired. I gonna finish it next time. + + + 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+50, + width, + height-50, + current_Y_shots, + bar=True, + mmb=True)