123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757 |
- # THIS FILE IS A PART OF VCStudio
- # PYTHON 3
- import os
- import datetime
- from subprocess import *
- # 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
- # Studio
- from studio import studio_dialogs
- from studio import analytics
- from studio import story
- from studio import history
- def layer(win, call):
-
- ##########################################################################
-
- # This file will do the asset configuration for linking assets into anima-
- # tion files. The ways it's going to be performed is following:
-
- # 0. User creates the asset. The /dev/ folder for the asset is created.
- # 1. User finished the asset and the checklists is now 100%.
- # 2. User Clicks on a configure button which launches this UI.
- # 3. User choses the main blendfile. It is copied to the /ast/ folder.
- # 4. User choses the collection and the rig with in the file. and it's
- # saved into autolink.data
- # 5. User creates a shot in the script editor. And creates a blend-file.
- # 6. Use presses the link button on the blend file. And it loads the assets
- # mentioned in the script.
- # 7. User presses the okay button and a script is running inside blender
- # that will read autolink.data files. And open /ast/ blend files. From
- # which it will loaded the right collection and make library override or
- # proxy to the rig. Both specified here by the user.
-
- # See:
- # studio/studio_shot_linkLayer.py
- # studio/bpy_do_linking.py
- # studio/studio_assetLayer.py
-
- # The way this file going to work will be like a step by step wizzard.
-
- # This file will be able to be openned from studio_shot_linkLayer dialog so
- # there will be 3 different UIs in this file.
-
- # 0. If checklist is not yet 100%. There will be a message to finish the
- # asset first.
- # 1. When the checklist is 100%. There will UI to select / copy /ast/file
- # 2. When that's done. The program going to launch a script to read data
- # from the newly created /ast/ file. And will present the user with
- # selection of collections and objects from the collections. So to
- # what to link and what to proxy.
-
- ##########################################################################
-
-
- # 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()
-
-
- UI_color.set(layer, win, "node_background")
- UI_elements.roundrect(layer, win,
- win.current["w"]/2-250,
- 100,
- 500,
- win.current["h"]-200,
- 10)
-
- # Documentation entry
- def do():
- def after(win, var):
- pass
-
- studio_dialogs.help(win, "help", after, SEARCH=talk.text("documentation_link_assets"))
-
- UI_elements.roundrect(layer, win,
- win.current["w"]/2-250,
- win.current["h"]-140,
- 40,
- 40,
- 10,
- do,
- "question")
-
-
- # Exit button
- def do():
- win.current["calls"][call]["var"] = False
-
-
- UI_elements.roundrect(layer, win,
- win.current["w"]/2+210,
- win.current["h"]-140,
- 40,
- 40,
- 10,
- button=do,
- icon="cancel",
- tip=talk.text("cancel"))
-
-
- # Okay so before we going to clip everything. Let's make a little widget.
- # this will be similar to the thing on top of shots. With the little round
- # icons. And a some kind of progress bar with fat points. But this one
- # will have only 3 points.
-
- # Let's simplify the process a little bit
-
- x = win.current["w"]/2-250
- y = 100
- width = 500
- height = win.current["h"]-200
-
- # Okay. let's draw the icons.
-
- threeicons = {
- "edit_mode":False,
- "blender":False,
- "link_configure":False
- }
-
- for numb, icon in enumerate(threeicons):
- UI_elements.image(layer, win,"settings/themes/"\
- +win.settings["Theme"]+"/icons/"+icon+".png",
- x+(width/4)*numb+(width/8)+40,
- y+20,
- 40,
- 40)
-
- # Before we can do progress bar and or progress dots we need to check
- # a few things about the asset.
-
- # First is whether it's done.
- threeicons["edit_mode"] = story.get_asset_data(win, win.current["asset_configure"]["asset"])["fraction"] == 1
- # Then whether the ast exists.
- threeicons["blender"] = os.path.exists(win.project+"/ast"+win.current["asset_configure"]["asset"]+".blend")
- # Then whether the autolink.data exists.
- threeicons["link_configure"] = os.path.exists(win.project+"/dev"+win.current["asset_configure"]["asset"]+"/autolink.data")
-
- # Now let's manually make the fraction.
- fraction = 0.0
- if threeicons["edit_mode"]:
- fraction = 0.33
- if threeicons["blender"]:
- fraction = 0.66
- if threeicons["link_configure"]:
- fraction = 1
-
- UI_color.set(layer, win, "progress_background")
- UI_elements.roundrect(layer, win,
- x+20,
- y+80,
- width-40,
- 0,
- 5)
- UI_color.set(layer, win, "progress_active")
- UI_elements.roundrect(layer, win,
- x+20,
- y+80,
- (width-40)*fraction,
- 0,
- 5)
-
- # And the 3 dots
-
- for numb, icon in enumerate(threeicons):
-
- UI_color.set(layer, win, "progress_background")
- if threeicons[icon]: # If this folder has any files.
- UI_color.set(layer, win, "progress_active")
- UI_elements.roundrect(layer, win,
- x+(width/4)*numb+(width/8)+50,
- y+75,
- 0,
- 0,
- 10)
-
- # Now let's do 3 UIs.
-
-
- ################## STEP 1: MAKE ASSET ######################
-
- if not threeicons["edit_mode"]:
-
- fraction = story.get_asset_data(win, win.current["asset_configure"]["asset"])["fraction"]
-
- UI_elements.text(layer, win, "asset_configuration_step",
- x,
- y+150,
- width,
- 30,
- 10,
- fill=False,
- centered=True,
- editable=False)
- win.text["asset_configuration_step"]["text"] = talk.text("asset_configuration_step_1")
-
- UI_elements.text(layer, win, "asset_configuration_step1",
- x,
- y+200,
- width,
- 30,
- 10,
- fill=False,
- centered=True,
- editable=False)
- win.text["asset_configuration_step1"]["text"] = str(int(round(fraction*100)))+"%"
-
- UI_color.set(layer, win, "progress_background")
- UI_elements.roundrect(layer, win,
- x+20,
- y+250,
- width-40,
- 0,
- 5)
- UI_color.set(layer, win, "progress_active")
- UI_elements.roundrect(layer, win,
- x+20,
- y+250,
- (width-40)*fraction,
- 0,
- 5)
-
- ####################### STEP 2 : COPY BLEND-FILE TO AST ####################
-
-
-
-
- # Setting up the scroll
- if "asset_configure" not in win.scroll:
- win.scroll["asset_configure"] = 0
-
- current_Y = 310 # The max scroll value
-
- if threeicons["edit_mode"] and not threeicons["blender"]:
-
- UI_elements.text(layer, win, "asset_configuration_step",
- x,
- y+150,
- width,
- 30,
- 10,
- fill=False,
- centered=True,
- editable=False)
- win.text["asset_configuration_step"]["text"] = talk.text("asset_configuration_step_2")
-
- # So if the file is selected I want to have an apply button.
-
- if win.current["asset_configure"]["blend_to_copy"]:
-
- UI_color.set(layer, win, "text_normal")
- layer.set_font_size(20)
- layer.move_to(x+40,
- y+height-20)
- layer.show_text(win.current["asset_configure"]["blend_to_copy"])
-
- def do():
- copy_from = win.project+"/dev"+win.current["asset_configure"]["asset"]+"/"+win.current["asset_configure"]["blend_to_copy"]
- copy_to = win.project+"/ast"+win.current["asset_configure"]["asset"]+".blend"
-
- newname = copy_to[copy_to.rfind("/")+1:]
- copy_to = copy_to[:copy_to.rfind("/")]
-
- oscalls.copy_file(
- win,
- copy_from,
- copy_to,
- newname)
-
- UI_elements.roundrect(layer, win,
- win.current["w"]/2+170,
- win.current["h"]-140,
- 40,
- 40,
- 10,
- button=do,
- icon="ok",
- tip=talk.text("checked"))
-
-
-
- # Here I want to draw a whole window with blend file selection and stuff.
- # so here we go.
-
- # Clipping everything
- UI_elements.roundrect(layer, win,
- win.current["w"]/2-250,
- 300,
- 500,
- win.current["h"]-460,
- 10,
- fill=False)
- layer.clip()
-
- clip = [
- win.current["w"]/2-250,
- 300,
- 500,
- win.current["h"]-460]
-
- # Background
- #UI_color.set(layer, win, "dark_overdrop")
- #layer.rectangle(x, y,width,height)
- #layer.fill()
-
- # Now we draw all the blend files of the file. I know it's redundant but
- # I want to be able to configure an asset from the linking window.
-
- tileX = x+70
-
- for filename in sorted(os.listdir(win.project+"/dev"+win.current["asset_configure"]["asset"])):
-
- if filename.endswith(".blend"):
-
- if int(current_Y + win.scroll["asset_configure"]) in range(0-200, height):
-
- # Making the layer
- node2surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 170, 200)
- node2 = cairo.Context(node2surface)
- node2.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
-
-
- UI_elements.roundrect(node2, win,
- 0,
- 0,
- 170,
- 200,
- 10,
- fill=False)
-
- node2.clip()
-
- # Background
- UI_color.set(node2, win, "dark_overdrop")
- node2.rectangle(0,0,170, 200)
- node2.fill()
-
- # Banner
- UI_color.set(node2, win, "node_blendfile")
- node2.rectangle(0,0,170, 20)
- node2.fill()
-
- # Outputting the layer
- layer.set_source_surface(node2surface,
- tileX-10,
- current_Y + win.scroll["asset_configure"] )
- layer.paint()
-
- UI_elements.image(layer, win, win.project+"/dev"+win.current["asset_configure"]["asset"]+"/"+filename,
- tileX,
- current_Y + win.scroll["asset_configure"] + 30,
- 150,
- 150)
-
- UI_color.set(layer, win, "text_normal")
- layer.set_font_size(12)
- layer.move_to(tileX,
- current_Y + win.scroll["asset_configure"]+15)
- layer.show_text(filename[filename.rfind("/")+1:][:22])
-
- # If selected
- layer.set_line_width(4)
- if win.current["asset_configure"]["blend_to_copy"] == filename:
- UI_color.set(layer, win, "progress_background")
- UI_elements.roundrect(layer, win,
- tileX-10,
- current_Y + win.scroll["asset_configure"],
- 170,
- 200,
- 10,
- fill=False)
- layer.stroke()
-
- # Button to activate it
- def do():
- win.current["asset_configure"]["blend_to_copy"] = filename
-
-
-
- UI_elements.roundrect(layer, win,
- tileX-10,
- current_Y + win.scroll["asset_configure"],
- 170,
- 200,
- 10,
- button=do,
- tip=filename,
- fill=False,
- clip=clip)
-
- layer.stroke()
- layer.set_line_width(2)
-
- tileX += 200
-
- if tileX > 1000:
- tileX = x+70
- current_Y += 230
-
- ####################### STEP 3 : CONFIGURE AUTOLINK.DATA ####################
-
- if threeicons["edit_mode"] and threeicons["blender"]:
-
- UI_elements.text(layer, win, "asset_configuration_step",
- x,
- y+150,
- width,
- 30,
- 10,
- fill=False,
- centered=True,
- editable=False)
- win.text["asset_configuration_step"]["text"] = talk.text("asset_configuration_step_3")
-
- if win.current["asset_configure"]["apply"]:
-
- def do():
- # Here I'm going to actually write stuff to the file. It's not hard.
-
- autolink = open(win.project+"/dev"+win.current["asset_configure"]["asset"]+"/autolink.data", "w")
-
- cols = win.current["asset_configure"]["collections"]
- for col in cols:
-
- # If the collection is selected we write it.
-
- if cols[col]["selected"]:
- autolink.write("Link : "+col+"\n")
-
- # Also we need to then look throught the collection to
- # see if there are any proxy objects. Aramtures...
-
- objs = cols[col]["objects"]
-
- for obj in objs:
-
- # Same thing if it's selected. Then write it to file.
-
- if objs[obj]["selected"]:
- autolink.write("Proxy : "+obj+"\n")
- autolink.close()
-
- # And a history entry real quick
- history.record(win, "/dev"+win.current["asset_configure"]["asset"]+"/autolink.data", "[Updated]")
-
- # And we need to quit the window. So...
- win.current["calls"][call]["var"] = False
-
- UI_elements.roundrect(layer, win,
- win.current["w"]/2+170,
- win.current["h"]-140,
- 40,
- 40,
- 10,
- button=do,
- icon="ok",
- tip=talk.text("checked"))
-
-
- # For this step I can't just copy stuff from assed layer and pretend that everything
- # is good. Because this part requires a whole new script to write and test.
-
- # See:
- # studio/bpy_get_blend_content.py
-
- # Now let's actually run this script quickly. Basically we need to get data out of
- # the asset blend file. But of course not on every frame. It's a bit too much. So
- # here is how we do it.
-
- if not win.current["asset_configure"]["collections"]:
-
- # If in the current data the data about the file still doesn't exists we load
- # it.
-
- blenderpath = oscalls.get_current_blender(win)
- assetblend = win.project+"/ast"+win.current["asset_configure"]["asset"]+".blend"
-
- checkframes = Popen([blenderpath, "-b", assetblend , "-P",
- os.getcwd()+"/studio/bpy_get_blend_content.py"],stdout=PIPE, universal_newlines=True)
- checkframes.wait()
- checkstring = checkframes.stdout.read()
-
- # Let's also see if the file autolink.data already there. Meaning I can get
- # data that is already saved there.
-
- linkcols = []
- linkobjs = []
-
- if threeicons["link_configure"]:
- autolink = open(win.project+"/dev"+win.current["asset_configure"]["asset"]+"/autolink.data")
- autolink = autolink.read()
- autolink = autolink.split("\n")
-
- for line in autolink:
- if line.startswith("Link : "):
- linkcols.append(line[7:])
-
- elif line.startswith("Proxy : "):
- linkobjs.append(line[8:])
- else:
- # If there is no file. I want to start the applying process already:
- win.current["asset_configure"]["apply"] = True
-
- # Now let's parse this crazy stuff that we've got from the blender script.
-
- for line in checkstring.split("\n"):
- if line.startswith(">>> "):
- line = line[4:]
- if "<==" in line:
- col = line[:line.find(" <==")]
- obj = line[line.find(" <==")+5:].split(" <== ")
-
- else:
- col = line
- obj = False
-
-
- selected = False
- if col in win.current["asset_configure"]["asset"] and not threeicons["link_configure"]:
- selected = True
- elif col in linkcols:
- selected = True
-
- # So we found a collection. Let's write it in
- if col not in win.current["asset_configure"]["collections"]:
- win.current["asset_configure"]["collections"][col] = {
- "selected":selected,
- "objects":{}
- }
-
- # We also got the object. Let's put it inside the collection.
- # But first. If it's an armature we want it to be selected.
- if obj:
- selected = False
- if "Armature" in obj[1] and not threeicons["link_configure"]:
- selected = True
- elif obj[0] in linkobjs:
- selected = True
-
- win.current["asset_configure"]["collections"][col]["objects"][obj[0]] = {
- "selected":selected,
- "type":obj[1]
- }
-
- # Now let's draw the findings to the screen. But first we need
- # buttons to see in what catergory are we.
-
- buttons = ["collection", "rig"]
-
-
-
- for num, button in enumerate(buttons):
-
- if win.current["asset_configure"]["step3_button"] == button:
-
- UI_color.set(layer, win, "progress_time")
- UI_elements.roundrect(layer, win,
- x+10+(40*num),
- y+200,
- 40,
- 40,
- 10)
-
- def do():
- win.current["asset_configure"]["step3_button"] = button
-
- UI_elements.roundrect(layer, win,
- x+10+(40*num),
- y+200,
- 40,
- 40,
- 10,
- do,
- button)
-
-
- # Now we can clip the bastard
-
- UI_elements.roundrect(layer, win,
- win.current["w"]/2-250,
- 350,
- 500,
- win.current["h"]-510,
- 10,
- fill=False)
- layer.clip()
-
- clip = [
- win.current["w"]/2-250,
- 350,
- 500,
- win.current["h"]-510]
-
- # Background
- #UI_color.set(layer, win, "dark_overdrop")
- #layer.rectangle(x, y,width,height)
- #layer.fill()
-
- # Let's start by drawing the collections first since it's the first thing
- # that the user will be doing. Is selecting the collections.
-
- current_Y = current_Y - 50
-
- if win.current["asset_configure"]["step3_button"] == "collection":
-
- for collection in win.current["asset_configure"]["collections"]:
-
- # We are going to draw a little collection icon. And put a text
- # with it's name.
-
- UI_elements.image(layer, win,
- "settings/themes/"+win.settings["Theme"]+"/icons/collection.png",
- x+60, y+current_Y+win.scroll["asset_configure"], 40, 40)
-
- UI_color.set(layer, win, "text_normal")
- layer.set_font_size(20)
- layer.move_to(x+120,
- y+current_Y + win.scroll["asset_configure"]+30)
- layer.show_text(collection)
-
- # Now let's make a checkbox button beside each collection.
- # Mimicing the Blender UI so to speak.
-
- icon = "unchecked"
- if win.current["asset_configure"]["collections"][collection]["selected"]:
- icon = "checked"
-
- def do():
- win.current["asset_configure"]["collections"][collection]["selected"]\
- = not win.current["asset_configure"]["collections"][collection]["selected"]
- win.current["asset_configure"]["apply"] = True
-
- UI_elements.roundrect(layer, win,
- x+10,
- y+current_Y + win.scroll["asset_configure"],
- 40,
- 40,
- 10,
- do,
- icon)
-
-
- current_Y = current_Y + 50
-
- else:
-
- # If we are not doing the collection but instead we are selecting the
- # rigs. We need to draw different stuff.
-
- for collection in win.current["asset_configure"]["collections"]:
-
- # But we want to draw only objects that are in selected colllections
- # so here what we do.
-
- if win.current["asset_configure"]["collections"][collection]["selected"]:
-
- for obj in win.current["asset_configure"]["collections"][collection]["objects"]:
-
- name = obj
- obj = win.current["asset_configure"]["collections"][collection]["objects"][obj]
-
- # Now first thing is we need to find an icon to represent
- # this object.
-
- icon = "obj"
- if "Mesh" in obj["type"]:
- icon = "mesh"
- elif "Armature" in obj["type"]:
- icon = "rig"
- elif "Camera" in obj["type"]:
- icon = "shot"
-
- UI_elements.image(layer, win,
- "settings/themes/"+win.settings["Theme"]+"/icons/"+icon+".png",
- x+60, y+current_Y+win.scroll["asset_configure"], 40, 40)
-
- UI_color.set(layer, win, "text_normal")
- layer.set_font_size(20)
- layer.move_to(x+120,
- y+current_Y + win.scroll["asset_configure"]+30)
- layer.show_text(name)
-
- icon = "link"
- if obj["selected"]:
- icon = "override"
-
- def do():
- obj["selected"]\
- = not obj["selected"]
- win.current["asset_configure"]["apply"] = True
-
- UI_elements.roundrect(layer, win,
- x+10,
- y+current_Y + win.scroll["asset_configure"],
- 40,
- 40,
- 10,
- do,
- icon)
-
-
- current_Y = current_Y + 50
-
- current_Y = current_Y - 300
-
- ###########################
-
- UI_elements.scroll_area(layer, win, "asset_configure",
- x,
- y+300,
- width,
- height-400,
- current_Y,
- bar=True,
- mmb=True,
- url="asset_configure"
- )
-
-
- return surface
|