studio_storyLayer.py 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304
  1. # THIS FILE IS A PART OF VCStudio
  2. # PYTHON 3
  3. import os
  4. import datetime
  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 oscalls
  16. from settings import talk
  17. from project_manager import pm_project
  18. from studio import analytics
  19. from studio import studio_nodes
  20. from studio import studio_dialogs
  21. from studio import story
  22. from studio import analytics
  23. from studio import schedule
  24. #UI modules
  25. from UI import UI_elements
  26. from UI import UI_color
  27. def layer(win):
  28. ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
  29. stf = datetime.datetime.now()
  30. perfStat = []
  31. ###################################################################
  32. # Making the layer
  33. surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, win.current['w'],
  34. win.current['h'])
  35. layer = cairo.Context(surface)
  36. #text setting
  37. layer.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
  38. ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
  39. fif = datetime.datetime.now()
  40. mil = fif - stf
  41. perfStat.append([ "Setup", mil.microseconds ])
  42. stf = datetime.datetime.now()
  43. ###################################################################
  44. UI_color.set(layer, win, "darker_parts")
  45. UI_elements.roundrect(layer, win,
  46. 50,
  47. 50,
  48. win.current["w"] - 100,
  49. win.current["h"] - 80,
  50. 30)
  51. # Little verion thing in the bottom corner
  52. UI_color.set(layer, win, "testing_banner")
  53. layer.set_font_size(15)
  54. layer.move_to(win.current["w"]-80, win.current["h"] - 7)
  55. layer.show_text(str(win.version))
  56. # Hude analytics button on the top
  57. def do():
  58. win.cur = "/set"
  59. win.url = "analytics"
  60. UI_elements.roundrect(layer, win,
  61. 5,
  62. 5,
  63. win.current["w"]-(win.current["w"]/3)+45,
  64. 40,
  65. 10,
  66. do,
  67. "analytics",
  68. talk.text("analytics_tooltip"),
  69. url="story_editor")
  70. # Progressbar
  71. UI_color.set(layer, win, "progress_background")
  72. UI_elements.roundrect(layer, win,
  73. 55,
  74. 15,
  75. win.current["w"]/3*2-10,
  76. 20,
  77. 10)
  78. timepassed = 0.0
  79. projectdone = 0.0
  80. try:
  81. timepassed = win.analytics["timepassed"]
  82. projectdone = win.analytics["fraction"]
  83. except:
  84. pass
  85. # Timepassed
  86. UI_color.set(layer, win, "progress_time")
  87. UI_elements.roundrect(layer, win,
  88. 55,
  89. 15,
  90. (win.current["w"]/3*2-10)*timepassed,
  91. 20,
  92. 10)
  93. # Project Done
  94. UI_color.set(layer, win, "progress_active")
  95. UI_elements.roundrect(layer, win,
  96. 55,
  97. 15,
  98. (win.current["w"]/3*2-10)*projectdone,
  99. 20,
  100. 10)
  101. # Separator
  102. UI_color.set(layer, win, "node_background")
  103. layer.move_to(win.current["w"]/3*2+55, 5)
  104. layer.line_to(win.current["w"]/3*2+55, 45)
  105. layer.stroke()
  106. ############ CURRENT TASK SCHEDULED #############
  107. # FIRST WE NEED TO GET A LIST OF TASKS
  108. # This is going to be a simplified version of the same stuff as in the
  109. # scheduling. But since we don't care what date we are in and trying to
  110. # get the oldest unchecked task. Here we go.
  111. schedules = schedule.get_schedules(win.analytics["dates"])
  112. new_date_format = "%Y/%m/%d"
  113. today = datetime.datetime.strftime(datetime.datetime.today(), new_date_format)
  114. slist = []
  115. for date in schedules:
  116. for item in schedules[date]:
  117. if win.cur == item or not win.cur == "/set":
  118. slist.append([date, item, schedules[date][item]])
  119. # Now that we have our list we can start parsing it the same way as in the
  120. # scheduling. Only removing some unnesesary stuff.
  121. foundtask = False
  122. taskname = ""
  123. taskurl = ""
  124. taskcur = ""
  125. for entry in slist:
  126. if not foundtask:
  127. for thing in entry[2]:
  128. if thing[0][3] == "[Checked]":
  129. continue # We do not care about those who are checked here.
  130. elif thing[0][-1] != win.settings["Username"]:
  131. continue # We do not care if it's not for us
  132. else:
  133. foundtask = True
  134. # Here we are going to take out some data about this task
  135. # First if it's not for today let's get a color for it
  136. if entry[0] != "1997/07/30":
  137. draw = False
  138. if entry[0] < today:
  139. UI_color.set(layer, win, "node_badfile") # The Red
  140. draw = True
  141. elif entry[0] > today:
  142. UI_color.set(layer, win, "node_asset") # The Purple
  143. draw = True
  144. if draw:
  145. UI_elements.roundrect(layer, win,
  146. win.current["w"]/3*2+60,
  147. 5,
  148. (win.current["w"]/3-65),
  149. 40,
  150. 10)
  151. name = entry[1][entry[1].rfind("/")+1:]
  152. acur = entry[1].replace(name, "").replace("/", "")
  153. fullurl = ""
  154. for e in thing[0][4][:-1]:
  155. fullurl = fullurl+e+" > "
  156. if acur in ["chr", "veh", "loc", "obj"]:
  157. assetname = talk.text(acur)+": "+name
  158. else:
  159. assetname = entry[1]
  160. # ASSINGING TEXT VALUES
  161. taskname = thing[0][4][-1]
  162. taskurl = fullurl
  163. taskcur = assetname.replace("/set","")
  164. # AND A TINY BUTTON TO ENTER WHAT EVER YOU ARE DOING
  165. goto = "analytics"
  166. if acur in ["chr", "veh", "loc","obj"]:
  167. goto = "assets"
  168. itemtype = "assets"
  169. elif not acur:
  170. itemtype = "files"
  171. else:
  172. goto = "script"
  173. itemtype = "scenes"
  174. def do():
  175. win.url = goto
  176. win.cur = entry[1]
  177. win.current["asset_left_panel"] = "schedule"
  178. UI_elements.roundrect(layer, win,
  179. win.current["w"]/3*2+60,
  180. 5,
  181. (win.current["w"]/3-65),
  182. 40,
  183. 10,
  184. button=do)
  185. break
  186. else:
  187. break
  188. # Schedule
  189. if taskname:
  190. UI_elements.image(layer, win, "settings/themes/"\
  191. +win.settings["Theme"]+"/icons/schedule.png",
  192. win.current["w"]/3*2+60,
  193. 5,
  194. 40,
  195. 40)
  196. UI_color.set(layer, win, "text_normal")
  197. layer.set_font_size(20)
  198. layer.move_to(win.current["w"]/3*2+120, 25)
  199. layer.show_text(taskname)
  200. layer.set_font_size(12)
  201. layer.move_to(win.current["w"]/3*2+130+len(taskname)*12, 25)
  202. layer.show_text(taskurl)
  203. layer.set_font_size(12)
  204. layer.move_to(win.current["w"]/3*2+120, 40)
  205. layer.show_text(taskcur)
  206. ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
  207. fif = datetime.datetime.now()
  208. mil = fif - stf
  209. perfStat.append([ "Analytics", mil.microseconds ])
  210. stf = datetime.datetime.now()
  211. ###################################################################
  212. ###### LEFT PANNEL #######
  213. # New Scene
  214. def do():
  215. # Okay let's make the adding the scene possible.
  216. # First we need to know what scenes are there. So we don't overwrite
  217. # any existing scene.
  218. scenename = "Scene"
  219. count = 2
  220. while scenename in win.story["scenes"]:
  221. scenename = "Scene_"+str(count)
  222. count = count + 1
  223. # Now that we have an empty name. Let's add a scene.
  224. win.story["scenes"][scenename] = {
  225. "fraction":0.0, # Percentage
  226. "position":[
  227. win.current["mx"]-win.story["camera"][0]-50,
  228. win.current["my"]-win.story["camera"][1]-30
  229. ],
  230. "size":[100, 60],
  231. "parent":"", # For when it's in a Frame (Event)
  232. "shots":[[
  233. "text_block",[["text", '']]
  234. ]]
  235. }
  236. # Auto select the new scene
  237. win.story["selected"] = [["scene", scenename]]
  238. win.current["tool"] = "grab"
  239. # A hack I guess. I don't know what I'm doing. I'm trying to force
  240. # the motion on click.
  241. win.current["LMB"] = [win.current["mx"], win.current["my"], True]
  242. # In studio/studio_gtk.py there is a command that recognizes the length
  243. # of the LMB. And it's more then 2 it does some magic to make stuff move
  244. # without pressing the actuall key. It's slightly too clever even for me
  245. # so yeah.
  246. UI_elements.roundrect(layer, win,
  247. 5,
  248. 105,
  249. 40,
  250. 40,
  251. 10,
  252. do,
  253. "scene_new",
  254. talk.text("new_scene_tooltip")+"\n[N]",
  255. url="story_editor")
  256. # Shortcut
  257. if 110 in win.current["keys"] and not win.textactive:
  258. do()
  259. win.current["keys"] = []
  260. # Link Asset
  261. def do():
  262. def after(win, var):
  263. print (var)
  264. if var:
  265. win.story["links"].append([
  266. "asset", var, [
  267. win.current["mx"]-win.story["camera"][0]-75,
  268. win.current["my"]-win.story["camera"][1]-75
  269. ],
  270. "" # Parent
  271. ])
  272. # Now let's select and move the thing
  273. win.story["selected"] = [["asset", len(win.story["links"])-1]]
  274. win.current["tool"] = "grab"
  275. win.current["LMB"] = [win.current["mx"], win.current["my"], True]
  276. studio_dialogs.asset_select(win, "new_asset_story", after)
  277. UI_elements.roundrect(layer, win,
  278. 5,
  279. 155,
  280. 40,
  281. 40,
  282. 10,
  283. do,
  284. "obj_link",
  285. talk.text("link_asset_tooltip")+"\n[L]",
  286. url="story_editor")
  287. # Shortcut
  288. if 108 in win.current["keys"] and not win.textactive:
  289. do()
  290. win.current["keys"] = []
  291. # Link File
  292. def do():
  293. def after(win, var):
  294. if var:
  295. win.story["links"].append([
  296. "file", var, [
  297. win.current["mx"]-win.story["camera"][0]-75,
  298. win.current["my"]-win.story["camera"][1]-75
  299. ],
  300. "" # Parent
  301. ])
  302. # Now let's select and move the thing
  303. win.story["selected"] = [["file", len(win.story["links"])-1]]
  304. win.current["tool"] = "grab"
  305. win.current["LMB"] = [win.current["mx"], win.current["my"], True]
  306. studio_dialogs.file_select(win, "new_file_story", after, force=True)
  307. UI_elements.roundrect(layer, win,
  308. 5,
  309. 205,
  310. 40,
  311. 40,
  312. 10,
  313. do,
  314. "file_link",
  315. talk.text("link_file_tooltip")+"\n[I]",
  316. url="story_editor")
  317. # Shortcut
  318. if 105 in win.current["keys"] and not win.textactive:
  319. do()
  320. win.current["keys"] = []
  321. # Marker
  322. def do():
  323. markername = "Marker"
  324. count = 2
  325. while markername in win.story["markers"]:
  326. markername = "Marker_"+str(count)
  327. count = count + 1
  328. win.story["markers"][markername] = [
  329. win.current["mx"]-win.story["camera"][0]+50,
  330. win.current["my"]-win.story["camera"][1]-20,
  331. "" # Parent
  332. ]
  333. win.textactive = markername+"_marker"
  334. win.text[markername+"_marker"] = {
  335. "text" :markername, # Actuall text you are editing.
  336. "cursor":[len(str(markername)),len(str(markername))], # Cursor
  337. "insert":False, # Whether the insert mode is on
  338. "scroll":"markername_scroll" # If multiline. The pointer for the scroll value.
  339. }
  340. win.story["selected"] = [["marker", markername]]
  341. win.current["tool"] = "grab"
  342. win.current["LMB"] = [win.current["mx"], win.current["my"], True]
  343. UI_elements.roundrect(layer, win,
  344. 5,
  345. 255,
  346. 40,
  347. 40,
  348. 10,
  349. do,
  350. "pin",
  351. talk.text("marker_tooltip")+"\n[M]",
  352. url="story_editor")
  353. # Shortcut
  354. if 109 in win.current["keys"] and not win.textactive:
  355. do()
  356. win.current["keys"] = []
  357. if win.story["selected"]:
  358. # Event
  359. def do():
  360. eventname = "Event"
  361. count = 2
  362. while eventname in win.story["events"]:
  363. eventname = "Event_"+str(count)
  364. count = count + 1
  365. win.story["events"][eventname] = {
  366. "position":[0,0],
  367. "size":[0,0]
  368. }
  369. # Even going to delete it self if there will be noone who parenting
  370. # it.
  371. for thing in win.story["selected"]:
  372. if thing[0] == "scene":
  373. win.story["scenes"][thing[1]]["parent"] = eventname
  374. elif thing[0] in ["file", "asset"]:
  375. win.story["links"][thing[1]][3] = eventname
  376. elif thing[0] == "marker":
  377. win.story["markers"][thing[1]][2] = eventname
  378. UI_elements.roundrect(layer, win,
  379. 5,
  380. 305,
  381. 40,
  382. 40,
  383. 10,
  384. do,
  385. "event",
  386. talk.text("event_tooltip")+"\n[E]",
  387. url="story_editor")
  388. # Shortcut
  389. if 101 in win.current["keys"] and not win.textactive:
  390. do()
  391. win.current["keys"] = []
  392. # Renders
  393. def do():
  394. def after(win, var):
  395. pass
  396. studio_dialogs.render(win, "current_renders", after)
  397. UI_elements.roundrect(layer, win,
  398. 5,
  399. 405,
  400. 40,
  401. 40,
  402. 10,
  403. do,
  404. "render",
  405. talk.text("render_lists_tooltip"),
  406. url="story_editor")
  407. # Let's draw on top of this button a little indicator of how many renders
  408. # are currently setup.
  409. if win.renders:
  410. count = str(len(win.renders))
  411. UI_color.set(layer, win, "node_background")
  412. UI_elements.roundrect(layer, win,
  413. 30,
  414. 405,
  415. len(count)*12+6,
  416. 25,
  417. 5)
  418. layer.fill()
  419. UI_color.set(layer, win, "text_normal")
  420. layer.set_font_size(20)
  421. layer.move_to(33,425)
  422. layer.show_text(count)
  423. # Edit Video
  424. def do():
  425. def after(win, var):
  426. if var:
  427. print(var)
  428. oscalls.file_open(win, var)
  429. studio_dialogs.vse(win, "VSEs", after)
  430. UI_elements.roundrect(layer, win,
  431. 5,
  432. 455,
  433. 40,
  434. 40,
  435. 10,
  436. do,
  437. "vse",
  438. talk.text("vse_tooltip"),
  439. url="story_editor")
  440. # Export to ODT
  441. def do():
  442. story.export_to_odt(win)
  443. UI_elements.roundrect(layer, win,
  444. 5,
  445. 555,
  446. 40,
  447. 40,
  448. 10,
  449. do,
  450. "export",
  451. talk.text("export_tooltip"),
  452. url="story_editor")
  453. # Bottom
  454. # Multiuser
  455. def do():
  456. win.url = "multiuser"
  457. UI_elements.roundrect(layer, win,
  458. 5,
  459. win.current["h"]-95,
  460. 40,
  461. 40,
  462. 10,
  463. do,
  464. "multiuser",
  465. talk.text("multiuser_tooltip"),
  466. url="story_editor")
  467. if win.multiuser["unread"]:
  468. count = str(win.multiuser["unread"])
  469. UI_color.set(layer, win, "node_background")
  470. UI_elements.roundrect(layer, win,
  471. 30,
  472. win.current["h"]-100,
  473. len(count)*12+6,
  474. 25,
  475. 5)
  476. layer.fill()
  477. UI_color.set(layer, win, "text_normal")
  478. layer.set_font_size(20)
  479. layer.move_to(33,win.current["h"]-83)
  480. layer.show_text(count)
  481. # Settings
  482. def do():
  483. win.url = "settings_layer"
  484. UI_elements.roundrect(layer, win,
  485. 5,
  486. win.current["h"]-45,
  487. 40,
  488. 40,
  489. 10,
  490. do,
  491. "settings",
  492. talk.text("Settings"),
  493. url="story_editor")
  494. ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
  495. fif = datetime.datetime.now()
  496. mil = fif - stf
  497. perfStat.append([ "Left Panel", mil.microseconds ])
  498. stf = datetime.datetime.now()
  499. ###################################################################
  500. ###### RIGHT PANNEL #######
  501. def select_character(win, var):
  502. if var:
  503. win.url = "assets"
  504. win.cur = var
  505. win.current["tool"] = "selection"
  506. # Characters
  507. def do():
  508. studio_dialogs.asset_select(win, "new_asset_story", select_character, force=True, cur="chr")
  509. UI_elements.roundrect(layer, win,
  510. win.current["w"]-45,
  511. 105,
  512. 40,
  513. 40,
  514. 10,
  515. do,
  516. "chr",
  517. talk.text("chr")+"\n[Shift-C]",
  518. url="story_editor")
  519. # Shortcut
  520. if 67 in win.current["keys"] and not win.textactive:
  521. do()
  522. win.current["keys"] = []
  523. # Vehicles
  524. def do():
  525. studio_dialogs.asset_select(win, "new_asset_story", select_character, force=True, cur="veh")
  526. UI_elements.roundrect(layer, win,
  527. win.current["w"]-45,
  528. 155,
  529. 40,
  530. 40,
  531. 10,
  532. do,
  533. "veh",
  534. talk.text("veh")+"\n[Shift-V]",
  535. url="story_editor")
  536. # Shortcut
  537. if 86 in win.current["keys"] and not win.textactive:
  538. do()
  539. win.current["keys"] = []
  540. # Locations
  541. def do():
  542. studio_dialogs.asset_select(win, "new_asset_story", select_character, force=True, cur="loc")
  543. UI_elements.roundrect(layer, win,
  544. win.current["w"]-45,
  545. 205,
  546. 40,
  547. 40,
  548. 10,
  549. do,
  550. "loc",
  551. talk.text("loc")+"\n[Shift-L]",
  552. url="story_editor")
  553. # Shortcut
  554. if 76 in win.current["keys"] and not win.textactive:
  555. do()
  556. win.current["keys"] = []
  557. # Other (obj)
  558. def do():
  559. studio_dialogs.asset_select(win, "new_asset_story", select_character, force=True, cur="obj")
  560. UI_elements.roundrect(layer, win,
  561. win.current["w"]-45,
  562. 255,
  563. 40,
  564. 40,
  565. 10,
  566. do,
  567. "obj",
  568. talk.text("obj")+"\n[Shift-O]",
  569. url="story_editor")
  570. # Shortcut
  571. if 79 in win.current["keys"] and not win.textactive:
  572. do()
  573. win.current["keys"] = []
  574. # Sounds / Music
  575. def do():
  576. os.system("xdg-open "+win.project+"/mus")
  577. UI_elements.roundrect(layer, win,
  578. win.current["w"]-45,
  579. 355,
  580. 40,
  581. 40,
  582. 10,
  583. do,
  584. "mus",
  585. talk.text("mus"),
  586. url="story_editor")
  587. # Help
  588. def do():
  589. def after(win, var):
  590. pass
  591. studio_dialogs.help(win, "help", after, SEARCH=talk.text("documentation_story_editor"))
  592. UI_elements.roundrect(layer, win,
  593. win.current["w"]-45,
  594. win.current["h"]-125,
  595. 40,
  596. 40,
  597. 10,
  598. do,
  599. "question",
  600. url="story_editor")
  601. # Folder
  602. def do():
  603. os.system("xdg-open "+win.project)
  604. UI_elements.roundrect(layer, win,
  605. win.current["w"]-45,
  606. win.current["h"]-75,
  607. 40,
  608. 40,
  609. 10,
  610. do,
  611. "folder",
  612. talk.text("project_folder"),
  613. url="story_editor")
  614. ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
  615. fif = datetime.datetime.now()
  616. mil = fif - stf
  617. perfStat.append([ "Right Pannel", mil.microseconds ])
  618. stf = datetime.datetime.now()
  619. ###################################################################
  620. if win.url == "story_editor"\
  621. and int(win.current["mx"]) in range(50, int(win.current["w"]-50)) \
  622. and int(win.current["my"]) in range(50, int(win.current["h"]-30)):
  623. # The cross cursor
  624. win.current["cursor"] = win.cursors["cross"]
  625. ####### NODES #######
  626. # Clipping so it wont draw beyon the frame
  627. UI_elements.roundrect(layer, win,
  628. 50,
  629. 50,
  630. win.current["w"] - 100,
  631. win.current["h"] - 80,
  632. 30,
  633. fill=False)
  634. layer.clip()
  635. # Background Image
  636. if os.path.exists(win.project+"/set/banner.png"):
  637. UI_elements.image(layer, win, win.project+"/set/banner.png",
  638. 50,
  639. 50,
  640. win.current["w"] - 100,
  641. win.current["h"] - 80,
  642. cell="background")
  643. elif os.path.exists(win.project+"/py_data/banner.png"):
  644. UI_elements.image(layer, win, win.project+"/py_data/banner.png",
  645. 50,
  646. 50,
  647. win.current["w"] - 100,
  648. win.current["h"] - 80,
  649. cell="background")
  650. else:
  651. UI_elements.image(layer, win, "icon.png",
  652. 50,
  653. 50,
  654. win.current["w"] - 100,
  655. win.current["h"] - 80,
  656. cell="background")
  657. UI_color.set(layer, win, "node_background")
  658. layer.rectangle(0,0,win.current["w"], win.current["h"])
  659. layer.fill()
  660. ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
  661. fif = datetime.datetime.now()
  662. mil = fif - stf
  663. perfStat.append([ "Background Image", mil.microseconds ])
  664. stf = datetime.datetime.now()
  665. ###################################################################
  666. # You probably intersted where is the scroll function for this part. Well
  667. # see there is a thing. It's easier to write one from screach here. Because
  668. # you geassed it we are starting to draw story editor.
  669. # Let's prepare the camera first.
  670. # Animation
  671. win.story["camera"][0] = UI_elements.animate("cameraX", win, 0, win.story["camera"][0])
  672. win.story["camera"][1] = UI_elements.animate("cameraY", win, 0, win.story["camera"][1])
  673. cx, cy = win.story["camera"]
  674. if win.url == "story_editor":
  675. if win.current["MMB"]:
  676. win.story["camera"][0] += ( win.current["mx"]-win.previous["mx"])
  677. win.story["camera"][1] += ( win.current["my"]-win.previous["my"])
  678. win.story["camera"][0] -= win.current["scroll"][0]*50
  679. win.story["camera"][1] -= win.current["scroll"][1]*50
  680. if cx != win.story["camera"][0] or cy != win.story["camera"][1]:
  681. UI_elements.animate("cameraX", win, win.story["camera"][0], force=True)
  682. UI_elements.animate("cameraY", win, win.story["camera"][1], force=True)
  683. ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
  684. fif = datetime.datetime.now()
  685. mil = fif - stf
  686. perfStat.append([ "Camera position", mil.microseconds ])
  687. stf = datetime.datetime.now()
  688. ###################################################################
  689. # EVENTS (Frames)
  690. try:
  691. for event in win.story["events"]:
  692. # Loaction
  693. sx, sy = win.story["events"][event]["position"]
  694. # Scale
  695. ssx, ssy = win.story["events"][event]["size"]
  696. #Draw
  697. studio_nodes.event_node(layer, win, sx, sy, ssx, ssy, name=event)
  698. # Let's now check if the event even has anybody inside. It's a bit
  699. # not the best way to implement it yet. Because I will need to look
  700. # through all items. But we can make it simpler if we find that it has
  701. # we can just break out of a thing.
  702. found = False
  703. for scene in win.story["scenes"]:
  704. if event == win.story["scenes"][scene]["parent"]:
  705. found = True
  706. break
  707. if not found:
  708. for link in win.story["links"]:
  709. if event == link[3]:
  710. found = True
  711. break
  712. if not found:
  713. for marker in win.story["markers"]:
  714. if event == win.story["markers"][marker][2]:
  715. found = True
  716. break
  717. # If nobody is inside. Delete the bastard.
  718. if not found:
  719. del win.story["events"][event]
  720. except:
  721. pass
  722. ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
  723. fif = datetime.datetime.now()
  724. mil = fif - stf
  725. perfStat.append([ "Events", mil.microseconds ])
  726. stf = datetime.datetime.now()
  727. ###################################################################
  728. # SCENES
  729. try:
  730. for scene in win.story["scenes"]:
  731. # Loaction
  732. sx, sy = win.story["scenes"][scene]["position"]
  733. sx = sx + cx
  734. sy = sy + cy
  735. # Scale
  736. ssx, ssy = win.story["scenes"][scene]["size"]
  737. #Fraction
  738. sf = win.story["scenes"][scene]["fraction"]
  739. #Draw
  740. studio_nodes.scene_node(layer, win, sx, sy, ssx, ssy, name=scene, fraction=sf)
  741. except:
  742. pass
  743. ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
  744. fif = datetime.datetime.now()
  745. mil = fif - stf
  746. perfStat.append([ "Scenes", mil.microseconds ])
  747. stf = datetime.datetime.now()
  748. ###################################################################
  749. # LINKS (Images, Stuff)
  750. for num, link in enumerate(win.story["links"]):
  751. linktype = link[0]
  752. linkname = link[1]
  753. lx = link[2][0] + cx
  754. ly = link[2][1] + cy
  755. # For the one inside the project. They should be always relative
  756. # so even if the project is in a complitely different location
  757. # on another machine. Where we have our Multiuser data. It should
  758. # be able to load these.
  759. if win.project in link[1]:
  760. link[1] = link[1].replace(win.project, "")
  761. studio_nodes.link_node(layer, win, lx, ly, name=linkname, num=num, linktype=linktype )
  762. ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
  763. fif = datetime.datetime.now()
  764. mil = fif - stf
  765. perfStat.append([ "Files / Assets", mil.microseconds ])
  766. stf = datetime.datetime.now()
  767. ###################################################################
  768. # Let's put in the start and the end nodes. These are drawn on top of
  769. # everything.
  770. studio_nodes.start_node(layer, win, 60,60,100,40)
  771. studio_nodes.end_node(layer, win, win.current["w"] - 160,
  772. win.current["h"] - 80,
  773. 100,40)
  774. ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
  775. fif = datetime.datetime.now()
  776. mil = fif - stf
  777. perfStat.append([ "Start / End Nodes", mil.microseconds ])
  778. stf = datetime.datetime.now()
  779. ###################################################################
  780. # MARKERS
  781. try:
  782. for marker in win.story["markers"]:
  783. mx = win.story["markers"][marker][0] + cx
  784. my = win.story["markers"][marker][1] + cy
  785. studio_nodes.marker(layer, win, marker, mx, my)
  786. except:
  787. pass
  788. # MARKERS
  789. try:
  790. for user in win.multiuser["users"]:
  791. if user != win.multiuser["userid"]:
  792. mx = 0-win.multiuser["users"][user]["camera"][0] +cx + win.current["w"]/2
  793. my = 0-win.multiuser["users"][user]["camera"][1] +cy + win.current["h"]/2
  794. studio_nodes.user(layer, win, win.multiuser["users"][user]["username"], mx, my, user)
  795. except Exception as e:
  796. print(e, "USER RENDERING")
  797. ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
  798. fif = datetime.datetime.now()
  799. mil = fif - stf
  800. perfStat.append([ "Markers", mil.microseconds ])
  801. stf = datetime.datetime.now()
  802. ###################################################################
  803. # In case there is a selection bug
  804. if not win.story["selected"] and win.current["tool"] != "connect":
  805. win.current["tool"] = "selection"
  806. # Selector visualization
  807. if win.current["LMB"] and win.current["tool"] == "selection" and win.url == "story_editor":
  808. # Draw selection box
  809. UI_color.set(layer, win, "progress_background")
  810. layer.rectangle(
  811. win.current["mx"],
  812. win.current["my"],
  813. win.current["LMB"][0] - win.current["mx"],
  814. win.current["LMB"][1] - win.current["my"]
  815. )
  816. layer.stroke()
  817. # Now let's draw the cool AF multi selection zone thingy
  818. # Draw selection box
  819. if len(win.story["selected"]) > 1 and win.current["tool"] == "selection":
  820. UI_color.set(layer, win, "progress_background")
  821. layer.rectangle(
  822. win.szone[0][0]-10,
  823. win.szone[0][1]-10,
  824. win.szone[1][0]+20,
  825. win.szone[1][1]+20
  826. )
  827. layer.stroke()
  828. # Now I want to make a tiny widget that will resize the stuff.
  829. if win.story["selected"]:
  830. if win.current["tool"] == "selection":
  831. draw_circle = True
  832. if len(win.story["selected"]) == 1:
  833. if win.story["selected"][0][0] != "scene":
  834. draw_circle = False
  835. if draw_circle:
  836. UI_color.set(layer, win, "node_badfile")
  837. UI_elements.roundrect(layer, win,
  838. win.szone[0][0]+win.szone[1][0],
  839. win.szone[0][1]+win.szone[1][1],
  840. 0,
  841. 0,
  842. 10)
  843. UI_color.set(layer, win, "progress_background")
  844. UI_elements.roundrect(layer, win,
  845. win.szone[0][0]+win.szone[1][0],
  846. win.szone[0][1]+win.szone[1][1],
  847. 0,
  848. 0,
  849. 10,
  850. fill=False)
  851. layer.stroke()
  852. elif win.current["tool"] == "scale":
  853. UI_color.set(layer, win, "node_badfile")
  854. UI_elements.roundrect(layer, win,
  855. win.current["mx"]-10,
  856. win.current["my"]-10,
  857. 0,
  858. 0,
  859. 10)
  860. UI_color.set(layer, win, "progress_background")
  861. UI_elements.roundrect(layer, win,
  862. win.current["mx"]-10,
  863. win.current["my"]-10,
  864. 0,
  865. 0,
  866. 10,
  867. fill=False)
  868. layer.stroke()
  869. if int(win.current["mx"]) in range(int(win.szone[0][0]+win.szone[1][0]), int(win.szone[0][0]+win.szone[1][0]+20))\
  870. and int(win.current["my"]) in range(int(win.szone[0][1]+win.szone[1][1]), int(win.szone[0][1]+win.szone[1][1]+20))\
  871. and win.current["tool"] == "selection":
  872. UI_color.set(layer, win, "text_normal")
  873. UI_elements.roundrect(layer, win,
  874. win.szone[0][0]+win.szone[1][0],
  875. win.szone[0][1]+win.szone[1][1],
  876. 0,
  877. 0,
  878. 10,
  879. fill=False)
  880. layer.stroke()
  881. win.current["cursor"] = win.cursors["arrow"]
  882. if win.current["LMB"] and not win.previous["LMB"]:
  883. win.current["tool"] = "scale"
  884. if win.current["tool"] == "scale" and not win.current["LMB"]:
  885. win.current["tool"] = "selection"
  886. # Canceling seletion. I move it here so it would not interfire with the
  887. # the rest of the program.
  888. if win.current["LMB"] and win.current["tool"] == "selection" and win.url == "story_editor":
  889. # Undo selection
  890. if int(win.current["LMB"][0] - win.current["mx"]) in range(-10, 10)\
  891. and int(win.current["LMB"][1] - win.current["my"])in range(-10, 10)\
  892. and int(win.current["mx"]) in range(50, int(win.current["w"]-50)) \
  893. and int(win.current["my"]) in range(50, int(win.current["h"]-30))\
  894. and 65505 not in win.current["keys"]:
  895. win.story["selected"] = []
  896. win.textactive = ""
  897. # Let's draw the line while connecting 2 scenes together.
  898. if win.current["tool"] == "connect":
  899. win.current["cursor"] = win.cursors["arrow"]
  900. if not win.current["LMB"]:
  901. win.current["tool"] = "selection"
  902. fr = win.current["draw_dot"]
  903. if type(fr) == list:
  904. fr = fr[0]+":"+fr[1]
  905. try:
  906. UI_color.set(layer, win, "node_script")
  907. layer.move_to(
  908. win.out_dots[fr][0],
  909. win.out_dots[fr][1]
  910. )
  911. layer.line_to(win.current["mx"], win.current["my"])
  912. layer.stroke()
  913. except:
  914. pass
  915. ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
  916. fif = datetime.datetime.now()
  917. mil = fif - stf
  918. perfStat.append([ "Selection", mil.microseconds ])
  919. stf = datetime.datetime.now()
  920. ###################################################################
  921. # The undo history is quite a new adition so the limit setting might
  922. # not exists. So let's make it if so.
  923. if "Undo_Limit" not in win.settings:
  924. win.settings["Undo_Limit"] = 32
  925. settings.write("Undo_Limit", 32)
  926. if win.animations["cameraX"][1] == cx:
  927. win.current["camera_arrived"] = True
  928. else:
  929. win.current["camera_arrived"] = False
  930. # Save story. I'm going to do it the same way as in the old Blender-Organizer
  931. if win.url == "story_editor":
  932. savenow = False
  933. if win.previous["LMB"] and not win.current["LMB"]:
  934. savenow = True
  935. elif win.previous["RMB"] and not win.current["RMB"]:
  936. savenow = True
  937. elif win.previous["MMB"] and not win.current["MMB"]:
  938. savenow = True
  939. elif win.previous["keys"] and not win.current["keys"]:
  940. savenow = True
  941. elif win.current["camera_arrived"] and not win.previous["camera_arrived"]:
  942. savenow = True
  943. if savenow:
  944. win.current["cursor"] = win.cursors["watch"]
  945. # Now let's run the history record.
  946. story.undo_record(win)
  947. story.save(win.project, win.story)
  948. analytics.save(win.project, win.analytics)
  949. # Need to reload the story to reload the fractions of the scenes.
  950. win.story = story.load(win.project)
  951. # Multiuser sycning
  952. win.multiuser["request"] = "story"
  953. ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
  954. fif = datetime.datetime.now()
  955. mil = fif - stf
  956. perfStat.append([ "File Saving", mil.microseconds ])
  957. stf = datetime.datetime.now()
  958. ###################################################################
  959. # To selected
  960. if 65454 in win.current["keys"] and win.story["selected"] and not win.textactive:
  961. nex = cx-win.szone[0][0] - win.szone[1][0]/2 + win.current["w"]/2
  962. ney = cy-win.szone[0][1] - win.szone[1][1]/2 + win.current["h"]/2
  963. UI_elements.animate("cameraX", win, win.story["camera"][0],nex, force=True)
  964. UI_elements.animate("cameraY", win, win.story["camera"][1],ney, force=True)
  965. # Undo
  966. if 65507 in win.current["keys"] and 122 in win.current["keys"] and not win.textactive:
  967. story.undo(win)
  968. win.current["keys"] = []
  969. # Redo
  970. if 65507 in win.current["keys"] and 121 in win.current["keys"] and not win.textactive:
  971. story.redo(win)
  972. win.current["keys"] = []
  973. # Grab
  974. if 103 in win.current["keys"] and win.story["selected"] and not win.textactive:
  975. win.current["tool"] = "grab"
  976. win.current["LMB"] = [win.current["mx"], win.current["my"], True]
  977. # Scale
  978. if 115 in win.current["keys"] and win.story["selected"] and not win.textactive:
  979. win.current["tool"] = "scale"
  980. win.current["LMB"] = [win.current["mx"], win.current["my"], True]
  981. # Deletion
  982. if 65535 in win.current["keys"] and win.current["tool"] == "selection"\
  983. and win.url == "story_editor" and win.story["selected"] and not win.textactive:
  984. win.url = "story_deletion_dialog"
  985. ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
  986. fif = datetime.datetime.now()
  987. mil = fif - stf
  988. perfStat.append([ "Short Cuts", mil.microseconds ])
  989. stf = datetime.datetime.now()
  990. ###################################################################
  991. ############### PERFORMCE TESTING GROUND ##############
  992. if win.current["testing"]:
  993. h = win.current["h"]+200
  994. w = win.current["w"]
  995. UI_color.set(layer, win, "darker_parts")
  996. UI_elements.roundrect(layer, win,100, h-(len(perfStat)*15)-30-300, 500,len(perfStat)*15+30, 10)
  997. l = 0
  998. s = 0
  999. for i in perfStat:
  1000. if int(i[1]) > l:
  1001. l = int(i[1])
  1002. s = s + int(i[1])
  1003. for n, i in enumerate(perfStat):
  1004. #UI_color.set(layer, win, "progress_background")
  1005. #UI_elements.roundrect(layer, win, 110 + 270, h-(len(perfStat)*15)-20+10+15*n-300, 200,10, 5)
  1006. layer.set_source_rgb(1,1,1)
  1007. if int(i[1]) == l:
  1008. layer.set_source_rgb(1,0,0)
  1009. elif int(i[1]) < 1000:
  1010. layer.set_source_rgb(0,1,0)
  1011. layer.set_font_size(10)
  1012. layer.move_to( 110, h-(len(perfStat)*15)+15*n-300)
  1013. p = float(i[1]) / s *100
  1014. layer.show_text(str(i[0])+" - "+str(i[1])+" MCRS "+str(int(round(p)))+"%")
  1015. #UI_color.set(layer, win, "progress_active")
  1016. UI_elements.roundrect(layer, win, 110 + 270, h-(len(perfStat)*15)-20+10+15*n-300, int(round(p))*2,10, 5)
  1017. return surface