studio_assetLayer.py 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233
  1. # THIS FILE IS A PART OF VCStudio
  2. # PYTHON 3
  3. # This a console project manager.
  4. import os
  5. import threading
  6. # GTK module ( Graphical interface
  7. import gi
  8. gi.require_version('Gtk', '3.0')
  9. from gi.repository import Gtk
  10. from gi.repository import GLib
  11. from gi.repository import Gdk
  12. import cairo
  13. # Own modules
  14. from settings import settings
  15. from settings import talk
  16. from settings import fileformats
  17. from settings import oscalls
  18. from project_manager import pm_project
  19. #UI modules
  20. from UI import UI_elements
  21. from UI import UI_color
  22. # story
  23. from studio import story
  24. from studio import checklist
  25. from studio import analytics
  26. from studio import studio_dialogs
  27. from studio import schedule
  28. from studio import history
  29. from network import http_client
  30. def layer(win):
  31. # Making the layer
  32. surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, win.current['w'],
  33. win.current['h'])
  34. layer = cairo.Context(surface)
  35. #text setting
  36. layer.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
  37. UI_color.set(layer, win, "dark_overdrop")
  38. layer.rectangle(
  39. 0,
  40. 0,
  41. win.current["w"],
  42. win.current["h"],
  43. )
  44. layer.fill()
  45. UI_color.set(layer, win, "node_background")
  46. UI_elements.roundrect(layer, win,
  47. win.current["w"]/4,
  48. 150,
  49. win.current["w"]/2,
  50. win.current["h"]-190,
  51. 10)
  52. ############################################################################
  53. # This file will be showing stuff about an asset. It's almost like a folder
  54. # / folders of the asset. But with some extendet functionality. Stuff that
  55. # will be on screen will include.
  56. # Progress Bar
  57. # Checklist
  58. # Scenes list in which the asset is mentioned
  59. # History / Schedules
  60. # It's similar to the old Blender Organizer's Asset thing. But a bit more
  61. # modern looking. I would say.
  62. ############################################################################
  63. # before we start I want to make a little safe mechanism. Just in case the
  64. # win.cur is not written properly.
  65. # Parsing the cur to get name and type
  66. name = win.cur[win.cur.rfind("/")+1:]
  67. acur = win.cur.replace(name, "").replace("/", "")
  68. if not os.path.exists(win.project+"/dev/"+win.cur) or not win.cur:
  69. def select_character(win, var):
  70. if var:
  71. win.url = "assets"
  72. win.cur = var
  73. else:
  74. win.url = "story_editor"
  75. if not acur:
  76. acur = "chr"
  77. studio_dialogs.asset_select(win, "select_asset_check", select_character, force=True, cur=acur, SEARCH=name)
  78. if not "asset_cur_folder" in win.current:
  79. win.current["asset_cur_folder"] = "blender"
  80. ####### MIDDLE PANNEL #######
  81. def do():
  82. oscalls.Open(win.project+"/dev"+win.cur)
  83. UI_elements.roundrect(layer, win,
  84. win.current["w"]/4+20,
  85. 350,
  86. 40,
  87. 40,
  88. 10,
  89. do,
  90. "folder")
  91. folds = {
  92. "blender":"blend_files_folder",
  93. "idea":"reference_folder",
  94. "texture":"tex_folder",
  95. "render":"renders_folder"
  96. }
  97. for num, cur in enumerate(folds):
  98. if win.current["asset_cur_folder"] == cur:
  99. UI_color.set(layer, win, "progress_time")
  100. UI_elements.roundrect(layer, win,
  101. win.current["w"]/4+150+(40*num),
  102. 350,
  103. 40,
  104. 40,
  105. 10)
  106. def do():
  107. win.current["asset_cur_folder"] = cur
  108. # FUNCTIONS PER THINGS
  109. # # Why?
  110. # if win.current["asset_cur_folder"] == "idea":
  111. # fl = "reference"
  112. # elif win.current["asset_cur_folder"] == "texture":
  113. # fl = "tex"
  114. # elif win.current["asset_cur_folder"] == "render":
  115. # fl = "renders"
  116. # else:
  117. # fl = ""
  118. # # Remote Server Stuff
  119. # if win.analytics["from-remote-server"]:
  120. # def after(win, var):
  121. # UI_elements.reload_images(win)
  122. # studio_dialogs.http_client_dialog(win, "http-client", after, http_client.get_files, "/dev/"+win.cur+"/"+fl)
  123. UI_elements.roundrect(layer, win,
  124. win.current["w"]/4+150+(40*num),
  125. 350,
  126. 40,
  127. 40,
  128. 10,
  129. do,
  130. cur,
  131. tip=talk.text(folds[cur]))
  132. # Little Remote Server thing
  133. if win.analytics["from-remote-server"]:
  134. if "remote-folder-data" not in win.current:
  135. win.current["remote-folder-data"] = {}
  136. if win.cur not in win.current["remote-folder-data"]:
  137. win.current["remote-folder-data"][win.cur] = {"missing":{},
  138. "changed":{}}
  139. def do():
  140. def after(win, var):
  141. UI_elements.reload_images(win)
  142. win.current["remote-folder-data"]["prompt"] = win.cur
  143. studio_dialogs.http_client_update_prompt(win, "http-client-prompt", after)
  144. UI_elements.roundrect(layer, win,
  145. win.current["w"]/4+60,
  146. 350,
  147. 40,
  148. 40,
  149. 10,
  150. do,
  151. "download",
  152. tip=talk.text("RemoteAssetUpdates"))
  153. if win.current["remote-folder-data"][win.cur]["missing"] or win.current["remote-folder-data"][win.cur]["changed"]:
  154. count = str(len(win.current["remote-folder-data"][win.cur]["missing"])+len(win.current["remote-folder-data"][win.cur]["changed"]))
  155. UI_color.set(layer, win, "progress_active")
  156. UI_elements.roundrect(layer, win,
  157. win.current["w"]/4+60+25,
  158. 350,
  159. len(count)*12+6,
  160. 25,
  161. 5)
  162. layer.fill()
  163. UI_color.set(layer, win, "text_normal")
  164. layer.set_font_size(20)
  165. layer.move_to(win.current["w"]/4+60+28,370)
  166. layer.show_text(count)
  167. # Preview
  168. # Making the layer
  169. nodesurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 300, 300)
  170. node = cairo.Context(nodesurface)
  171. node.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
  172. UI_elements.roundrect(node, win,
  173. 0,
  174. 0,
  175. 300,
  176. 300,
  177. 10,
  178. fill=False)
  179. node.clip()
  180. if os.path.exists(win.project+"/dev"+win.cur+"/renders/Preview.png"):
  181. UI_elements.image(node, win,
  182. win.project+"/dev"+win.cur+"/renders/Preview.png",
  183. 0, 0, 300, 300, cell="big_asset_previews")
  184. elif os.path.exists(win.project+"/dev"+win.cur+"/renders/Preview.jpg"):
  185. UI_elements.image(node, win,
  186. win.project+"/dev"+win.cur+"/renders/Preview.jpg",
  187. 0, 0, 300, 300, cell="big_asset_previews")
  188. else:
  189. UI_color.set(node, win, "dark_overdrop")
  190. node.rectangle(0,0,300, 300)
  191. node.fill()
  192. UI_elements.image(node, win,
  193. "settings/themes/"+win.settings["Theme"]+"/icons/"+acur+".png",
  194. 130, 130, 40, 40)
  195. def do():
  196. def after(win, var):
  197. win.current["asset_file_selected"] = ""
  198. win.images = {}
  199. if var:
  200. for t in fileformats.images:
  201. if var.endswith(t):
  202. oscalls.copy_file(
  203. win,
  204. var,
  205. "/dev"+win.cur+"/renders/",
  206. "Preview.png")
  207. break
  208. studio_dialogs.file_select(win, name+"_preview", after, force=True,
  209. IMAGE=True, BLEND=False, VIDEO=True, FILE=False, CHR=True, VEH=True,
  210. LOC=True, OBJ=True, RND=False, FOLDER=False, SEARCH=win.cur+" renders")
  211. UI_elements.roundrect(node, win,
  212. 2,
  213. 2,
  214. 296,
  215. 296,
  216. 10,
  217. button=do,
  218. fill=False,
  219. offset=[
  220. win.current["w"]/4+20,
  221. 20
  222. ]
  223. )
  224. node.stroke()
  225. # Outputting the layer
  226. layer.set_source_surface(nodesurface,
  227. win.current["w"]/4+20,
  228. 20)
  229. layer.paint()
  230. # Name of the asset
  231. UI_elements.image(layer, win,
  232. "settings/themes/"+win.settings["Theme"]+"/icons/"+acur+".png",
  233. win.current["w"]/4+360, 210, 40, 40)
  234. UI_color.set(layer, win, "text_normal")
  235. layer.set_font_size(30)
  236. layer.move_to(win.current["w"]/4+410,240)
  237. layer.show_text(name)
  238. # Fraction
  239. fraction = story.get_asset_data(win, win.cur)["fraction"]
  240. UI_color.set(layer, win, "progress_background")
  241. UI_elements.roundrect(layer, win,
  242. win.current["w"]/4+350,
  243. 270,
  244. (win.current["w"]/2-370),
  245. 0,
  246. 10)
  247. UI_color.set(layer, win, "progress_active")
  248. UI_elements.roundrect(layer, win,
  249. win.current["w"]/4+350,
  250. 270,
  251. (win.current["w"]/2-370)*fraction,
  252. 0,
  253. 10)
  254. # Before search. On the other side when you have done the asset there will
  255. # be a little configure icon. This is configuration for linking. Creating
  256. # the /ast/ blend.file and autolink.data file. So the linker could link
  257. # the files into the animation scene.
  258. #
  259. # See:
  260. # studio/studio_shot_linkLayer.py
  261. # studio/bpy_do_linking.py
  262. # studio/studio_asset_configureLayer.py
  263. def do():
  264. def after(win, var):
  265. print(var)
  266. studio_dialogs.asset_configure(win, "configuring_asset", after, win.cur)
  267. UI_elements.roundrect(layer, win,
  268. win.current["w"]/4*3-60,
  269. 210,
  270. 40,
  271. 40,
  272. 10,
  273. button=do,
  274. icon="link_configure")
  275. # Search
  276. UI_elements.image(layer, win, "settings/themes/"\
  277. +win.settings["Theme"]+"/icons/search.png",
  278. win.current["w"]-280-win.current["w"]/4,
  279. 350,
  280. 40,
  281. 40)
  282. UI_elements.text(layer, win, "in_asset",
  283. win.current["w"]-240-win.current["w"]/4,
  284. 350,
  285. 220,
  286. 40)
  287. # FILES
  288. # In case the user made the folder manually.
  289. try:
  290. os.mkdir(win.project+"/dev/"+win.cur)
  291. except:
  292. pass
  293. try:
  294. os.mkdir(win.project+"/dev/"+win.cur+"/renders")
  295. os.mkdir(win.project+"/dev/"+win.cur+"/reference")
  296. os.mkdir(win.project+"/dev/"+win.cur+"/tex")
  297. except:
  298. pass
  299. # Now let's prepare the frame
  300. width = win.current["w"]/2- 40
  301. height = win.current["h"] - 500
  302. # Making the layer
  303. nodesurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
  304. node = cairo.Context(nodesurface)
  305. node.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
  306. UI_elements.roundrect(node, win,
  307. 0,
  308. 0,
  309. width,
  310. height,
  311. 10,
  312. fill=False)
  313. node.clip()
  314. # Now let's prepare the scrooler
  315. tileX = 20
  316. current_Y = 10
  317. if "assets" not in win.scroll:
  318. win.scroll["assets"] = 0
  319. ###########################
  320. # Let's get the list of the files first.
  321. files = []
  322. newcreate = win.text["in_asset"]["text"].replace("/","_").replace(" ", "_")\
  323. .replace('"',"_").replace("(","_").replace(")","_").replace("'","_")\
  324. .replace("[","_").replace("]","_").replace("{","_").replace("}","_")
  325. foundblend = True
  326. found_in = False
  327. if win.current["asset_cur_folder"] == "blender":
  328. foundblend = False
  329. # Let's see if an asset blend file exists.
  330. if os.path.exists(win.project+"/ast"+win.cur+".blend") and not newcreate:
  331. files.append(["/ast"+win.cur+".blend", "node_asset"])
  332. foundblend = True
  333. for f in sorted(os.listdir(win.project+"/dev"+win.cur)):
  334. if not os.path.isdir(win.project+"/dev"+win.cur+"/"+f):
  335. # This is for only the blend files. So let's filter the out of all
  336. # the noise. For all files there is a folder icon.
  337. if newcreate == f:
  338. found_in = True
  339. if newcreate and newcreate.lower() not in f.lower():
  340. continue
  341. if f.endswith(".blend"):
  342. files.append(["/dev"+win.cur+"/"+f, "node_blendfile"])
  343. foundblend = True
  344. else:
  345. # This all the rest of the files.
  346. if win.current["asset_cur_folder"] == "idea":
  347. fl = "reference"
  348. elif win.current["asset_cur_folder"] == "texture":
  349. fl = "tex"
  350. elif win.current["asset_cur_folder"] == "render":
  351. fl = "renders"
  352. for f in sorted(os.listdir(win.project+"/dev"+win.cur+"/"+fl)):
  353. if not os.path.isdir(win.project+"/dev"+win.cur+"/"+fl+"/"+f):
  354. if newcreate == f:
  355. found_in = True
  356. if newcreate and newcreate.lower() not in f.lower():
  357. continue
  358. # Now it has to be image or video files. For the rest you have
  359. # the folder icon.
  360. for t in fileformats.images:
  361. if f.endswith(t):
  362. files.append(["/dev"+win.cur+"/"+fl+"/"+f, "node_imagefile"])
  363. for t in fileformats.videos:
  364. if f.endswith(t):
  365. files.append(["/dev"+win.cur+"/"+fl+"/"+f, "node_videofile"])
  366. # Let's make sure that we have at least some blendfile there.
  367. if not foundblend and not newcreate:
  368. oscalls.copy_file(
  369. win,
  370. os.getcwd()+"/new_file/"+acur+".blend",
  371. "/dev"+win.cur+"/",
  372. name+".blend")
  373. # This is executed on the first frame when you click onto an asset.
  374. if win.current["in-asset-remote-server"]:
  375. # Let's also check for updates on the file
  376. # Remote Server Stuff
  377. if win.analytics["from-remote-server"]:
  378. # Checking date [ FOLDER NAME ] [ FILES TO CHECK FOR ]
  379. check_folders = {"/dev"+win.cur : "*",
  380. "/ast/"+acur : name+"*",
  381. "/dev"+win.cur+"/renders" : "*",
  382. "/dev"+win.cur+"/reference" : "*",
  383. "/dev"+win.cur+"/tex" : "*",
  384. }
  385. check_updates = threading.Thread(target=http_client.get_folder_info,
  386. args=(win, check_folders, win.cur, ))
  387. check_updates.setDaemon(True)
  388. check_updates.start()
  389. win.current["in-asset-remote-server"] = False
  390. if "asset_file_selected" not in win.current:
  391. win.current["asset_file_selected"] = ""
  392. for filename, thecoloris in files:
  393. if int(current_Y + win.scroll["assets"]) in range(0-200, height):
  394. # Making the layer
  395. node2surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 170, 200)
  396. node2 = cairo.Context(node2surface)
  397. node2.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
  398. UI_elements.roundrect(node2, win,
  399. 0,
  400. 0,
  401. 170,
  402. 200,
  403. 10,
  404. fill=False)
  405. node2.clip()
  406. # Background
  407. UI_color.set(node2, win, "dark_overdrop")
  408. node2.rectangle(0,0,170, 200)
  409. node2.fill()
  410. # Banner
  411. UI_color.set(node2, win, thecoloris)
  412. node2.rectangle(0,0,170, 20)
  413. node2.fill()
  414. # Outputting the layer
  415. node.set_source_surface(node2surface,
  416. tileX-10,
  417. current_Y + win.scroll["assets"] )
  418. node.paint()
  419. UI_elements.image(node, win, win.project+filename,
  420. tileX,
  421. current_Y + win.scroll["assets"] + 30,
  422. 150,
  423. 150)
  424. UI_color.set(node, win, "text_normal")
  425. node.set_font_size(12)
  426. node.move_to(tileX,
  427. current_Y + win.scroll["assets"]+15)
  428. node.show_text(filename[filename.rfind("/")+1:][:22])
  429. # If selected
  430. node.set_line_width(4)
  431. if win.current["asset_file_selected"] == win.project+filename:
  432. UI_color.set(node, win, "progress_background")
  433. UI_elements.roundrect(node, win,
  434. tileX-10,
  435. current_Y + win.scroll["assets"],
  436. 170,
  437. 200,
  438. 10,
  439. fill=False)
  440. node.stroke()
  441. # Button to activate it
  442. def do():
  443. if win.current["asset_file_selected"] != win.project+filename:
  444. win.current["asset_file_selected"] = win.project+filename
  445. else:
  446. oscalls.file_open(win, win.project+filename)
  447. UI_elements.roundrect(node, win,
  448. tileX-10,
  449. current_Y + win.scroll["assets"],
  450. 170,
  451. 200,
  452. 10,
  453. button=do,
  454. tip=filename,
  455. fill=False,
  456. clip=[
  457. win.current["w"]/4+20,
  458. 400,
  459. width,
  460. height,
  461. ],
  462. offset=[
  463. win.current["w"]/4+20,
  464. 400])
  465. node.stroke()
  466. node.set_line_width(2)
  467. tileX += 200
  468. if tileX > width-180:
  469. tileX = 20
  470. current_Y += 230
  471. ###########################
  472. # Now i'd like to make things addable. For now if it's a blends selected
  473. # there will an option to add new one and an option to copy. While other
  474. # files will have an option of only copy. (At least for now. Untill I
  475. # figure out what new images will it give.)
  476. if not found_in and newcreate:
  477. if win.current["asset_cur_folder"] == "blender"\
  478. and not newcreate.endswith(".blend"):
  479. newcreate = newcreate+".blend"
  480. def do():
  481. def after(win, var):
  482. newcreate = win.text["in_asset"]["text"].replace("/","_").replace(" ", "_")\
  483. .replace('"',"_").replace("(","_").replace(")","_").replace("'","_")\
  484. .replace("[","_").replace("]","_").replace("{","_").replace("}","_")
  485. win.text["in_asset"]["text"] = ""
  486. win.current["asset_file_selected"] = ""
  487. win.images = {}
  488. if var:
  489. if win.current["asset_cur_folder"] == "blender"\
  490. and var.endswith(".blend"):
  491. if not newcreate.endswith(".blend"):
  492. newcreate = newcreate+".blend"
  493. oscalls.copy_file(
  494. win,
  495. var,
  496. "/dev"+win.cur+"/",
  497. newcreate)
  498. else:
  499. # In case the copying file is not a blend file. Let's
  500. # make sure that it's infect an image.
  501. for t in fileformats.images:
  502. if var.endswith(t):
  503. if not newcreate.endswith(t):
  504. newcreate = newcreate + "." + t
  505. if win.current["asset_cur_folder"] == "idea":
  506. fl = "reference"
  507. elif win.current["asset_cur_folder"] == "texture":
  508. fl = "tex"
  509. elif win.current["asset_cur_folder"] == "render":
  510. fl = "renders"
  511. oscalls.copy_file(
  512. win,
  513. var,
  514. "/dev"+win.cur+"/"+fl+"/",
  515. newcreate)
  516. break
  517. if win.current["asset_cur_folder"] == "blender":
  518. studio_dialogs.file_select(win, name+"_blends", after, force=True,
  519. IMAGE=False, BLEND=True, VIDEO=False, FILE=False, CHR=True, VEH=True,
  520. LOC=True, OBJ=True, RND=False, FOLDER=False)
  521. elif win.current["asset_cur_folder"] == "idea":
  522. studio_dialogs.file_select(win, name+"_reference", after, force=True,
  523. IMAGE=True, BLEND=False, VIDEO=True, FILE=False, CHR=True, VEH=True,
  524. LOC=True, OBJ=True, RND=False, FOLDER=False, SEARCH="reference")
  525. elif win.current["asset_cur_folder"] == "texture":
  526. studio_dialogs.file_select(win, name+"_reference", after, force=True,
  527. IMAGE=True, BLEND=False, VIDEO=True, FILE=False, CHR=True, VEH=True,
  528. LOC=True, OBJ=True, RND=False, FOLDER=False, SEARCH="tex")
  529. elif win.current["asset_cur_folder"] == "render":
  530. studio_dialogs.file_select(win, name+"_reference", after, force=True,
  531. IMAGE=True, BLEND=False, VIDEO=True, FILE=False, CHR=True, VEH=True,
  532. LOC=True, OBJ=True, RND=False, FOLDER=False, SEARCH="renders")
  533. UI_elements.roundrect(node, win,
  534. tileX-10,
  535. current_Y + win.scroll["assets"],
  536. 170,
  537. 200,
  538. 10,
  539. button=do,
  540. tip=talk.text("copy_file_as")+" "+newcreate,
  541. clip=[
  542. win.current["w"]/4+20,
  543. 400,
  544. width,
  545. height,
  546. ],
  547. offset=[
  548. win.current["w"]/4+20,
  549. 400])
  550. UI_color.set(node, win, "progress_background")
  551. UI_elements.roundrect(node, win,
  552. tileX-10,
  553. current_Y + win.scroll["assets"],
  554. 170,
  555. 200,
  556. 10,
  557. fill=False)
  558. node.stroke()
  559. UI_elements.image(node, win,
  560. "settings/themes/"+win.settings["Theme"]+"/icons/copy_file.png",
  561. tileX+55,
  562. current_Y + win.scroll["assets"] + 70,
  563. 40, 40)
  564. UI_color.set(node, win, "text_normal")
  565. node.set_font_size(12)
  566. node.move_to(tileX+75-len(newcreate)*4,
  567. current_Y + win.scroll["assets"]+150)
  568. node.show_text(newcreate)
  569. tileX += 200
  570. if tileX > width-180:
  571. tileX = 20
  572. current_Y += 230
  573. if not found_in and newcreate and win.current["asset_cur_folder"] == "blender":
  574. if not newcreate.endswith(".blend"):
  575. newcreate = newcreate+".blend"
  576. def do():
  577. oscalls.copy_file(
  578. win,
  579. os.getcwd()+"/new_file/"+acur+".blend",
  580. "/dev"+win.cur+"/",
  581. newcreate)
  582. win.text["in_asset"]["text"] = ""
  583. win.current["asset_file_selected"] = ""
  584. win.images = {}
  585. UI_elements.roundrect(node, win,
  586. tileX-10,
  587. current_Y + win.scroll["assets"],
  588. 170,
  589. 200,
  590. 10,
  591. button=do,
  592. tip=talk.text("create_new_blend_file")+" "+newcreate,
  593. clip=[
  594. win.current["w"]/4+20,
  595. 400,
  596. width,
  597. height,
  598. ],
  599. offset=[
  600. win.current["w"]/4+20,
  601. 400])
  602. UI_color.set(node, win, "progress_background")
  603. UI_elements.roundrect(node, win,
  604. tileX-10,
  605. current_Y + win.scroll["assets"],
  606. 170,
  607. 200,
  608. 10,
  609. fill=False)
  610. node.stroke()
  611. UI_elements.image(node, win,
  612. "settings/themes/"+win.settings["Theme"]+"/icons/new_file.png",
  613. tileX+55,
  614. current_Y + win.scroll["assets"] + 70,
  615. 40, 40)
  616. UI_color.set(node, win, "text_normal")
  617. node.set_font_size(12)
  618. node.move_to(tileX+75-len(newcreate)*4,
  619. current_Y + win.scroll["assets"]+150)
  620. node.show_text(newcreate)
  621. current_Y += 230
  622. UI_elements.scroll_area(layer, win, "assets",
  623. win.current["w"]/4+20,
  624. 400,
  625. width,
  626. height,
  627. current_Y,
  628. bar=True,
  629. mmb=True,
  630. url="assets")
  631. # Outputting the layer
  632. layer.set_source_surface(nodesurface,
  633. win.current["w"]/4+20,
  634. 400)
  635. layer.paint()
  636. ############## CHECKLIST ################
  637. if os.path.exists(win.project+"/dev/"+win.cur+"/asset.progress"):
  638. checklist.draw(layer, win, win.project+"/dev/"+win.cur+"/asset.progress", back=win.url)
  639. else:
  640. # If asset.progress does not exist in the folder it will try to create.
  641. # one. The only problem with now is language support. I have some ideas
  642. # I will need to work on it. But later.
  643. oscalls.copy_file(
  644. win,
  645. os.getcwd()+"/new_file/"+acur+".progress",
  646. "/dev"+win.cur+"/",
  647. "asset.progress")
  648. ############## LEFT PANEL ################
  649. # Here on the left panel I want to have 3 things. Which is already more then
  650. # the legacy organizer. But who are we deceiving? This is way cooler then
  651. # the legacy organizer.
  652. leftpanellist = ["scene", "schedule", "history"] # Using the names of the icons.
  653. # We need to choose the correct category based smartly on the project's
  654. # current progress. Or at least on the current progress of this asset.
  655. if "asset_left_panel" not in win.current:
  656. if fraction == 1.0: # If the asset is done
  657. win.current["asset_left_panel"] = "scene" # Then list scenes
  658. else: # Other
  659. win.current["asset_left_panel"] = "schedule" # List schedules
  660. # A little banner.
  661. UI_color.set(layer, win, "node_background")
  662. UI_elements.roundrect(layer, win,
  663. 10,
  664. 10,
  665. win.current["w"]/4-20,
  666. 50,
  667. 10)
  668. for num, thing in enumerate(leftpanellist):
  669. if win.current["asset_left_panel"] == thing:
  670. UI_color.set(layer, win, "progress_time")
  671. UI_elements.roundrect(layer, win,
  672. 20+(40*num),
  673. 15,
  674. 40,
  675. 40,
  676. 10)
  677. def do():
  678. win.current["asset_left_panel"] = thing
  679. UI_elements.roundrect(layer, win,
  680. 20+(40*num),
  681. 15,
  682. 40,
  683. 40,
  684. 10,
  685. do,
  686. thing)
  687. ### SCHEDULES ###
  688. if win.current["asset_left_panel"] == "schedule":
  689. schedule.draw(layer, win)
  690. ### HISTORY ###
  691. if win.current["asset_left_panel"] == "history":
  692. history.draw(layer, win)
  693. ### SCENES ###
  694. # Documentation entry
  695. def do():
  696. def after(win, var):
  697. pass
  698. studio_dialogs.help(win, "help", after, SEARCH=talk.text("documentation_assets"))
  699. UI_elements.roundrect(layer, win,
  700. win.current["w"]-40-win.current["w"]/4-50,
  701. win.current["h"]-80,
  702. 40,
  703. 40,
  704. 10,
  705. do,
  706. "question")
  707. # CANCEl
  708. def do():
  709. win.url = "story_editor"
  710. win.assets = {}
  711. win.current["asset_file_selected"] = ""
  712. UI_elements.roundrect(layer, win,
  713. win.current["w"]-40-win.current["w"]/4,
  714. win.current["h"]-80,
  715. 40,
  716. 40,
  717. 10,
  718. button=do,
  719. icon="cancel",
  720. tip=talk.text("cancel"))
  721. # Short cut ESC
  722. if 65307 in win.current["keys"] and not win.textactive:
  723. do()
  724. if win.current["asset_left_panel"] == "scene":
  725. # Here I want to parse the story data in pusuit of all the scenes that
  726. # have the asset. I think I'm going to make it per shot based. Like
  727. # you have the scenes. And you can open them to enter shots. Maybe with
  728. # a tiny exserp from the story.
  729. if "asset_scenes" not in win.scroll:
  730. win.scroll["asset_scenes"] = 0
  731. if "asset_scene_selected" not in win.current:
  732. win.current["asset_scene_selected"] = False
  733. x = 10
  734. y = 70
  735. width = win.current["w"] / 4 - 20
  736. height = win.current["h"] - 80
  737. UI_elements.roundrect(layer, win,
  738. x,
  739. y,
  740. width,
  741. height,
  742. 10,
  743. fill=False)
  744. layer.clip()
  745. current_Y_scenes = 0
  746. scenes = win.story["scenes"]
  747. for scene in scenes:
  748. fraction = scenes[scene]["fraction"]
  749. shots = scenes[scene]["shots"]
  750. foundinscene = []
  751. for num, block in enumerate(shots):
  752. si = 1
  753. if block[0] == "shot_block":
  754. si = 2
  755. found = []
  756. for n, stuff in enumerate(block[si]):
  757. # DIRECT LINK
  758. #print(block, si)
  759. if stuff[0] == "link" and stuff[1] == win.cur:
  760. start = ""
  761. part = stuff[-1]
  762. end = ""
  763. if n > 0:
  764. start = block[si][n-1][-1]
  765. start = start.replace("\n", " ")
  766. if n < len(block[si])-1:
  767. end = block[si][n+1][-1]
  768. end = end.replace("\n", " ")
  769. found = [start, part, end]
  770. if si == 2:
  771. foundinscene.append([block[1],found,num,n])
  772. else:
  773. foundinscene.append(["",found,num,n])
  774. # FRASE LINK
  775. if stuff[0] == "frase" and stuff[1][0] == "link" and stuff[1][1] == win.cur:
  776. start = ""
  777. part = stuff[1][-1]
  778. end = ""
  779. if n < len(block[si])-1:
  780. end = " : "+stuff[-1]
  781. found = [start, part, end]
  782. if si == 2:
  783. foundinscene.append([block[1],found,num ,n])
  784. else:
  785. foundinscene.append(["",found,num ,n])
  786. if foundinscene:
  787. UI_color.set(layer, win, "node_background")
  788. UI_elements.roundrect(layer, win,
  789. x,
  790. y+win.scroll["asset_scenes"]+current_Y_scenes,
  791. width,
  792. 70,
  793. 10)
  794. # ICON
  795. UI_elements.image(layer, win,
  796. "settings/themes/"+win.settings["Theme"]+"/icons/scene.png",
  797. 20, y+win.scroll["asset_scenes"] + current_Y_scenes+5, 40, 40)
  798. # SELECTION
  799. def do():
  800. if win.current["asset_scene_selected"] == scene:
  801. win.current["asset_scene_selected"] = False
  802. else:
  803. win.current["asset_scene_selected"] = scene
  804. UI_elements.roundrect(layer, win,
  805. x,
  806. y+win.scroll["asset_scenes"]+current_Y_scenes,
  807. width,
  808. 70,
  809. 10,
  810. button=do,
  811. fill=False)
  812. layer.stroke()
  813. # SCENE NAME
  814. UI_color.set(layer, win, "text_normal")
  815. layer.set_font_size(20)
  816. layer.move_to( x+60, y+win.scroll["asset_scenes"] + current_Y_scenes+30)
  817. layer.show_text(scene)
  818. # FRACTION
  819. UI_color.set(layer, win, "progress_background")
  820. UI_elements.roundrect(layer, win,
  821. x+10,
  822. y+50+win.scroll["asset_scenes"] + current_Y_scenes,
  823. width-20,
  824. 0,
  825. 5)
  826. UI_color.set(layer, win, "progress_active")
  827. UI_elements.roundrect(layer, win,
  828. x+10,
  829. y+50+win.scroll["asset_scenes"] + current_Y_scenes,
  830. (width-20)*fraction,
  831. 0,
  832. 5)
  833. # IF SELECTED
  834. if win.current["asset_scene_selected"] == scene:
  835. UI_color.set(layer, win, "progress_background")
  836. UI_elements.roundrect(layer, win,
  837. x,
  838. y+win.scroll["asset_scenes"]+current_Y_scenes,
  839. width,
  840. 70,
  841. 10,
  842. fill=False)
  843. layer.stroke()
  844. # Here if the current scene is selected I want to draw all
  845. # the parts of the scene. It's already a bit more complex
  846. # then what was in the Blender-Organizer legacy.
  847. current_Y_scenes = current_Y_scenes + 80
  848. for block in foundinscene:
  849. # If it's a shot let's mark in the different color.
  850. if block[0]:
  851. if "shot_colors" not in win.story:
  852. win.story["shot_colors"] = {}
  853. surl = "/"+scene+"/"+block[0]
  854. if surl not in win.story["shot_colors"]:
  855. rcolors = [
  856. "shot_1",
  857. "shot_2",
  858. "shot_3",
  859. "shot_4",
  860. "shot_5"
  861. ]
  862. win.story["shot_colors"][surl] = rcolors[len(win.story["shot_colors"]) % len(rcolors)]
  863. col = win.story["shot_colors"][surl]
  864. UI_color.set(layer, win, col)
  865. else:
  866. UI_color.set(layer, win, "node_background")
  867. UI_elements.roundrect(layer, win,
  868. x,
  869. y+win.scroll["asset_scenes"]+current_Y_scenes,
  870. width,
  871. 30,
  872. 10)
  873. # GET TO THE SCENE BUTTON
  874. def do():
  875. win.current["script_find"] = [block[2],block[3]]
  876. win.url = "script"
  877. print(scene)
  878. win.cur = "/"+scene+"/"+block[0]
  879. print(win.cur)
  880. UI_elements.roundrect(layer, win,
  881. x,
  882. y+win.scroll["asset_scenes"]+current_Y_scenes,
  883. width,
  884. 30,
  885. 10,
  886. button=do,
  887. fill=False)
  888. layer.stroke()
  889. start = block[1][0]
  890. name = block[1][1]
  891. end = block[1][2]
  892. sp = x+width/2-len(name)*12/2-len(start)*12
  893. np = x+width/2-len(name)*12/2
  894. ep = x+width/2+len(name)*12/2
  895. if sp > x+5 and x+5 + ep + len(end)*12 > width:
  896. sp = x+5
  897. np = x+5 + len(start)*12
  898. ep = x+5 + len(start)*12 + len(name)*12
  899. elif ep + len(end)*12 < width and sp < x+5:
  900. ep = width - len(end)*12
  901. np = ep - len(name)*12
  902. sp = np - len(start)*12
  903. # BEFORE NAME
  904. UI_color.set(layer, win, "text_normal")
  905. layer.set_font_size(20)
  906. layer.move_to( sp, y+win.scroll["asset_scenes"] + current_Y_scenes+20)
  907. layer.show_text(start)
  908. # NAME AS MENTIONED IN THE SCRIPT
  909. UI_color.set(layer, win, "node_asset")
  910. UI_elements.roundrect(layer, win,
  911. np-6,
  912. y+win.scroll["asset_scenes"]+current_Y_scenes+2,
  913. len(name)*12+12,
  914. 26,
  915. 10)
  916. UI_color.set(layer, win, "text_normal")
  917. layer.set_font_size(20)
  918. layer.move_to(np, y+win.scroll["asset_scenes"] + current_Y_scenes+20)
  919. layer.show_text(name)
  920. # AFTER NAME
  921. UI_color.set(layer, win, "text_normal")
  922. layer.set_font_size(20)
  923. layer.move_to( ep, y+win.scroll["asset_scenes"] + current_Y_scenes+20)
  924. layer.show_text(end)
  925. current_Y_scenes = current_Y_scenes + 40
  926. else:
  927. current_Y_scenes = current_Y_scenes + 80
  928. # Scroll
  929. UI_elements.scroll_area(layer, win, "asset_scenes",
  930. x+0,
  931. y+50,
  932. width,
  933. height-50,
  934. current_Y_scenes,
  935. bar=True,
  936. mmb=True)
  937. return surface