editor-new.js 170 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806
  1. "use strict";
  2. // Copyright 2012 United States Government, as represented by the Secretary of Defense, Under
  3. // Secretary of Defense (Personnel & Readiness).
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
  6. // in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed under the License
  11. // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
  12. // or implied. See the License for the specific language governing permissions and limitations under
  13. // the License.
  14. /// vwf/view/editor creates a view interface for editor functions.
  15. ///
  16. /// @module vwf/view/editor
  17. /// @requires version
  18. /// @requires vwf/view
  19. /// @requires vwf/utility
  20. define([
  21. "module",
  22. "version",
  23. "vwf/view",
  24. "vwf/utility",
  25. "vwf/view/lib/ace/ace",
  26. "vwf/view/lib/colorpicker/colorpicker.min",
  27. "vwf/view/widgets"
  28. ], function (module, version, view, utility, ace, colorpicker, widgets) {
  29. var self;
  30. return view.load(module, {
  31. // == Module Definition ====================================================================
  32. initialize: function () {
  33. self = this;
  34. this.ace = window.ace;
  35. this.widgets = widgets;
  36. this.nodes = {};
  37. this.scenes = {};
  38. this.allScripts = {};
  39. //$(document.head).append('<style type="text/css" media="screen"> #editorlive { height: 500px; width: 800px; } </style>');
  40. document.querySelector('head').innerHTML += '<style type="text/css" media="screen"> #editorlive { height: 500px; width: 800px; } </style>';
  41. document.querySelector('head').innerHTML += '<link rel="stylesheet" href="vwf/view/lib/editorLive.css">';
  42. //document.querySelector('head').innerHTML += '<script type="text/javascript" src="vwf/view/lib/colorpicker/colorpicker.min.js">';
  43. document.querySelector('head').innerHTML += '<link rel="stylesheet" href="vwf/view/lib/colorpicker/themes.css">';
  44. //$(document.head).append('<meta name="viewport" content="width=device-width, initial-scale=1">');
  45. document.querySelector('head').innerHTML += '<meta name="viewport" content="width=device-width, initial-scale=1">';
  46. // $('body').append('<script>mdc.autoInit()</script>');
  47. this.removeProps = (obj) => {
  48. Object.keys(obj).forEach(key =>
  49. (key === 'id' || key === 'patches' || key === 'random' || key === 'sequence') && delete obj[key] ||
  50. (obj[key] && typeof obj[key] === 'object') && this.removeProps(obj[key])
  51. );
  52. return obj;
  53. };
  54. this.getNodeDef = function (nodeID) {
  55. let node = vwf.getNode(nodeID, true);
  56. let nodeDef = self.removeProps(node);
  57. return nodeDef
  58. }
  59. this.GUID = function () {
  60. var S4 = function () {
  61. return Math.floor(
  62. Math.random() * 0x10000 /* 65536 */
  63. ).toString(16);
  64. };
  65. return (
  66. S4() + S4() + "-" +
  67. S4() + "-" +
  68. S4() + "-" +
  69. S4() + "-" +
  70. S4() + S4() + S4()
  71. );
  72. }
  73. this.getRoot = function () {
  74. var app = window.location.pathname;
  75. var pathSplit = app.split('/');
  76. if (pathSplit[0] == "") {
  77. pathSplit.shift();
  78. }
  79. if (pathSplit[pathSplit.length - 1] == "") {
  80. pathSplit.pop();
  81. }
  82. var instIndex = pathSplit.length - 1;
  83. if (pathSplit.length > 2) {
  84. if (pathSplit[pathSplit.length - 2] == "load") {
  85. instIndex = pathSplit.length - 3;
  86. }
  87. }
  88. if (pathSplit.length > 3) {
  89. if (pathSplit[pathSplit.length - 3] == "load") {
  90. instIndex = pathSplit.length - 4;
  91. }
  92. }
  93. var root = "";
  94. for (var i = 0; i < instIndex; i++) {
  95. if (root != "") {
  96. root = root + "/";
  97. }
  98. root = root + pathSplit[i];
  99. }
  100. if (root.indexOf('.vwf') != -1) root = root.substring(0, root.lastIndexOf('/'));
  101. return root
  102. };
  103. this.getRandomInt = function (min, max) {
  104. min = Math.ceil(min);
  105. max = Math.floor(max);
  106. return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
  107. };
  108. ["drawer", "toolbar", "sideBar", "propWindow", "clientsWindow", "codeEditorWindow", "propEditorWindow", "viewSceneProps"].forEach(item => {
  109. let el = document.createElement("div");
  110. el.setAttribute("id", item);
  111. document.body.appendChild(el);
  112. }
  113. );
  114. this.avatarCardDef = function (src, desc, onclickfunc) {
  115. return {
  116. $cell: true,
  117. $type: "div",
  118. class: "mdc-card avatar-card",
  119. $init: function () {
  120. this.style.backgroundImage = 'linear-gradient(0deg, rgba(0, 0, 0, 0.0), rgba(0, 0, 0, 0.0) ), url(' + src + ')'
  121. },
  122. onclick: onclickfunc,
  123. $components: [
  124. {
  125. $type: "section",
  126. class: "mdc-card__primary",
  127. $components: [
  128. {
  129. $type: "h1",
  130. class: "mdc-card__title mdc-card__title--large",
  131. $text: desc.subtitle
  132. },
  133. {
  134. $type: "h2",
  135. class: "mdc-card__subtitle",
  136. $text: desc.title
  137. }
  138. ]
  139. },
  140. {
  141. $type: "section",
  142. class: "mdc-card__actions",
  143. $components: [
  144. {
  145. $type: "button",
  146. class: "mdc-button mdc-button--compact mdc-card__action",
  147. //$text: "Use it",
  148. onclick: onclickfunc
  149. }
  150. ]
  151. }
  152. ]
  153. }
  154. }
  155. let createSettings =
  156. {
  157. $cell: true,
  158. $type: "div",
  159. class: "propGrid max-width mdc-layout-grid mdc-layout-grid--align-left",
  160. $components: [
  161. {
  162. $cell: true,
  163. $type: "div",
  164. class: "mdc-layout-grid__inner",
  165. $components: [
  166. {
  167. $cell: true,
  168. $type: "div",
  169. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-4",
  170. $components: [
  171. widgets.simpleCard(
  172. {
  173. "imgSrc": "vwf/view/lib/images/ui/cube_normal.png",
  174. "imgHeight": "100px",
  175. "addonClass": "create-card",
  176. "text": "Cube",
  177. "onclickfunc": function(){
  178. let avatarID = 'avatar-' + vwf.moniker_;
  179. //let cubeName = self.GUID();
  180. vwf_view.kernel.callMethod(vwf.application(), "createPrimitive", ["cube", avatarID])
  181. }
  182. }
  183. )
  184. ]
  185. },
  186. {
  187. $cell: true,
  188. $type: "div",
  189. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-4",
  190. $components: [
  191. widgets.simpleCard(
  192. {
  193. "imgSrc": "vwf/view/lib/images/ui/sphere_normal.png",
  194. "imgHeight": "100px",
  195. "addonClass": "create-card",
  196. "text": "Sphere",
  197. "onclickfunc": function(){
  198. let avatarID = 'avatar-' + vwf.moniker_;
  199. //let cubeName = self.GUID();
  200. vwf_view.kernel.callMethod(vwf.application(), "createPrimitive", ["sphere", avatarID])
  201. }
  202. }
  203. )
  204. ]
  205. },
  206. // {
  207. // $cell: true,
  208. // $type: "div",
  209. // class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-4",
  210. // $components: [
  211. // widgets.simpleCard(
  212. // {
  213. // "imgSrc": "vwf/view/lib/images/ui/cylinder_normal.png",
  214. // "imgHeight": "100px",
  215. // "text": "Cylinder"
  216. // }
  217. // )
  218. // ]
  219. // }
  220. ]
  221. }
  222. ]
  223. }
  224. let avatarSettings =
  225. {
  226. $cell: true,
  227. $type: "div",
  228. class: "propGrid max-width mdc-layout-grid mdc-layout-grid--align-left",
  229. $components: [
  230. {
  231. $cell: true,
  232. $type: "div",
  233. class: "mdc-layout-grid__inner",
  234. $components: [
  235. {
  236. $cell: true,
  237. $type: "div",
  238. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  239. $components: [
  240. widgets.buttonStroked(
  241. {
  242. "label": "Go forward",
  243. "onclick": function (e) {
  244. function getMovementVector(el) {
  245. var directionVector = new THREE.Vector3(0, 0, 0);
  246. var rotationEuler = new THREE.Euler(0, 0, 0, 'YXZ');
  247. var rotation = el.getAttribute('rotation');
  248. var velocity = new THREE.Vector3(0, 0, -0.5);
  249. var xRotation;
  250. directionVector.copy(velocity);
  251. directionVector.multiplyScalar(1.0);
  252. // Absolute.
  253. if (!rotation) { return directionVector; }
  254. xRotation = 0;
  255. // Transform direction relative to heading.
  256. rotationEuler.set(THREE.Math.degToRad(xRotation), THREE.Math.degToRad(rotation.y), 0);
  257. directionVector.applyEuler(rotationEuler);
  258. return directionVector;
  259. }
  260. let el = document.querySelector('#avatarControl');
  261. let currentPosition = el.getAttribute('position');
  262. let movementVector = getMovementVector(el);
  263. let position = {};
  264. position.x = currentPosition.x + movementVector.x;
  265. position.y = currentPosition.y + movementVector.y;
  266. position.z = currentPosition.z + movementVector.z;
  267. el.setAttribute('position', position);
  268. }
  269. })
  270. ]
  271. },
  272. {
  273. $cell: true,
  274. $type: "div",
  275. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  276. $components: [
  277. widgets.buttonStroked(
  278. {
  279. "label": "Reset camera view",
  280. "onclick": function (e) {
  281. //document.querySelector('#' + 'viewSettings').style.visibility = 'hidden';
  282. let controlEl = document.querySelector('#avatarControl');
  283. controlEl.setAttribute('camera', 'active', true);
  284. }
  285. }),
  286. widgets.buttonStroked(
  287. {
  288. "label": "Hide cursor",
  289. "onclick": function (e) {
  290. //document.querySelector('#' + 'viewSettings').style.visibility = 'hidden';
  291. let avatarID = 'avatar-' + self.kernel.moniker();
  292. let cursorID = 'myCursor-' + avatarID;
  293. let controlEl = document.querySelector("[id='" + cursorID + "']");
  294. let vis = controlEl.getAttribute('visible');
  295. this.$text = vis ? 'Show cursor' : 'Hide cursor';
  296. vwf_view.kernel.callMethod(avatarID, "showHideCursor", [!vis]);
  297. //controlEl.setAttribute('visible', !vis);
  298. }
  299. }),
  300. widgets.buttonStroked(
  301. {
  302. "label": "Hide Avatar",
  303. "onclick": function (e) {
  304. //document.querySelector('#' + 'viewSettings').style.visibility = 'hidden';
  305. let avatarID = 'avatar-' + self.kernel.moniker();
  306. //let cursorID = 'myCursor-' + avatarID;
  307. let controlEl = document.querySelector("[id='" + avatarID + "']");
  308. let vis = controlEl.getAttribute('visible');
  309. this.$text = vis ? 'Show Avatar' : 'Show Avatar';
  310. vwf_view.kernel.callMethod(avatarID, "showHideAvatar", [!vis]);
  311. //controlEl.setAttribute('visible', !vis);
  312. }
  313. }
  314. )
  315. ]
  316. },
  317. {
  318. $cell: true,
  319. $type: "div",
  320. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  321. $components: [
  322. {
  323. $type: "div",
  324. class: "mdc-layout-grid",
  325. $components: [
  326. {
  327. $type: "div",
  328. class: "mdc-layout-grid__inner",
  329. $components: [
  330. {
  331. $cell: true,
  332. $type: "div",
  333. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  334. $components: [
  335. self.avatarCardDef("/../assets/avatars/ico/simple.jpg", { title: "Simple", subtitle: "Cube" },
  336. function (e) {
  337. let avatarID = 'avatar-' + self.kernel.moniker();
  338. vwf_view.kernel.callMethod(avatarID, "createSimpleAvatar");
  339. }
  340. )
  341. ]
  342. },
  343. {
  344. $cell: true,
  345. $type: "div",
  346. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  347. $components: [
  348. self.avatarCardDef("/../assets/avatars/ico/female.jpg", { title: "Human", subtitle: "Female" },
  349. function (e) {
  350. let avatarID = 'avatar-' + self.kernel.moniker();
  351. vwf_view.kernel.callMethod(avatarID, "createAvatarFromGLTF", ["/../assets/avatars/female/avatar1.gltf"]);
  352. }
  353. )]
  354. },
  355. {
  356. $cell: true,
  357. $type: "div",
  358. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  359. $components: [
  360. self.avatarCardDef("/../assets/avatars/ico/male.jpg", { title: "Human", subtitle: "Male" },
  361. function (e) {
  362. let avatarID = 'avatar-' + self.kernel.moniker();
  363. vwf_view.kernel.callMethod(avatarID, "createAvatarFromGLTF", ["/../assets/avatars/male/avatar1.gltf"]);
  364. }
  365. )]
  366. }
  367. ]
  368. }
  369. ]
  370. }
  371. ]
  372. },
  373. {
  374. $cell: true,
  375. $type: "div",
  376. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  377. $components: [
  378. widgets.buttonStroked(
  379. {
  380. "label": "Wide",
  381. "onclick": function (e) {
  382. let avatarID = 'avatar-'+vwf.moniker_;
  383. vwf_view.kernel.callMethod(avatarID, "setBigVideoHead", []);
  384. }
  385. }),
  386. widgets.buttonStroked(
  387. {
  388. "label": "Small",
  389. "onclick": function (e) {
  390. let avatarID = 'avatar-'+vwf.moniker_;
  391. vwf_view.kernel.callMethod(avatarID, "setSmallVideoHead", []);
  392. }
  393. })
  394. ]
  395. }
  396. ]
  397. }
  398. ]
  399. }
  400. let viewSettings =
  401. {
  402. $cell: true,
  403. $type: "div",
  404. class: "propGrid max-width mdc-layout-grid mdc-layout-grid--align-left",
  405. $components: [
  406. {
  407. $cell: true,
  408. $type: "div",
  409. class: "mdc-layout-grid__inner",
  410. $components: [
  411. {
  412. $cell: true,
  413. $type: "div",
  414. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  415. $components: [
  416. widgets.buttonStroked(
  417. {
  418. "label": "OSC Settings",
  419. "onclick": function (e) {
  420. let sideBar = document.querySelector('#sideBar');
  421. sideBar._sideBarComponent = oscSettings;
  422. //document.querySelector('#' + 'viewSettings').style.visibility = 'hidden';
  423. }
  424. })
  425. ]
  426. }
  427. ]
  428. }
  429. ]
  430. }
  431. let savedStateEl = function (item) {
  432. return {
  433. $type: "li",
  434. class: "mdc-list-item",
  435. role: "option",
  436. $components: [
  437. {
  438. $text: "Saved world"
  439. }
  440. ]
  441. }
  442. }
  443. let stateListElement = function (item) {
  444. let liEl = {
  445. $type: "li",
  446. class: "mdc-list-item",
  447. role: "option",
  448. id: "",
  449. tabindex: "0",
  450. applicationpath: "",
  451. $components: [
  452. {
  453. $text: "no saves"
  454. }
  455. ]
  456. }
  457. let applicationName = item.applicationpath.split("/");
  458. if (applicationName == "") {
  459. return liEl
  460. }
  461. if (applicationName.length > 0) {
  462. applicationName = applicationName[applicationName.length - 1];
  463. }
  464. if (applicationName.length > 0) {
  465. applicationName = applicationName.charAt(0).toUpperCase() + applicationName.slice(1);
  466. }
  467. if (item.latestsave) {
  468. liEl = {
  469. $type: "li",
  470. class: "mdc-list-item",
  471. role: "option",
  472. tabindex: "0",
  473. id: item.savename,
  474. applicationpath: item.applicationpath,
  475. $components: [
  476. {
  477. $text: applicationName + ": " + item.savename
  478. }
  479. ]
  480. }
  481. }
  482. else {
  483. liEl = {
  484. $type: "li",
  485. class: "mdc-list-item",
  486. role: "option",
  487. tabindex: "0",
  488. id: item.savename,
  489. revision: item.revision,
  490. applicationpath: item.applicationpath,
  491. $components: [
  492. {
  493. $text: applicationName + ": " + item.savename + " Rev(" + item.revision + ")"
  494. }
  495. ]
  496. }
  497. }
  498. return liEl
  499. }
  500. let oscSettings =
  501. {
  502. $cell: true,
  503. $type: "div",
  504. id: "oscSettings",
  505. class: "propGrid max-width mdc-layout-grid mdc-layout-grid--align-left",
  506. _oscHost: '',
  507. _oscPort: '',
  508. _oscStatus: '',
  509. _updateStatus: function () {
  510. this._oscStatus = window._OSCManager.getStatus()
  511. },
  512. $init: function () {
  513. if (window._OSCManager) {
  514. this._oscHost = window._OSCManager.hostValue;
  515. this._oscPort = window._OSCManager.portValue;
  516. this._oscStatus = window._OSCManager.getStatus();
  517. // var t = this;
  518. // setInterval(function () {
  519. // t._updateStatus();
  520. // }, 1000);
  521. }
  522. },
  523. $update: function () {
  524. let that = this
  525. var buttonText = "Connect";
  526. var buttonFunc = function (e) {
  527. }
  528. if (this._oscStatus == 1) {
  529. buttonText = "Disconnect";
  530. buttonFunc = function (e) {
  531. window._OSCManager.disconnect();
  532. }
  533. } else {
  534. var buttonFunc = function (e) {
  535. window._OSCManager.connect();
  536. window._OSCManager.port.on("open", function () {
  537. that._oscStatus = window._OSCManager.getStatus();
  538. console.log("connected");
  539. });
  540. window._OSCManager.port.on("close", function () {
  541. that._oscStatus = window._OSCManager.getStatus();
  542. console.log("disconnected");
  543. });
  544. }
  545. }
  546. this.$components = [
  547. {
  548. $cell: true,
  549. $type: "div",
  550. class: "mdc-layout-grid__inner",
  551. $components: [
  552. {
  553. $cell: true,
  554. $type: "div",
  555. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  556. $components: [
  557. {
  558. $type: "span",
  559. $text: "Host: "
  560. },
  561. {
  562. class: "mdc-text-field",
  563. $cell: true,
  564. $type: "span",
  565. $components: [
  566. {
  567. class: "mdc-text-field__input prop-text-field-input",
  568. id: "oscHost",
  569. $cell: true,
  570. $type: "input",
  571. type: "text",
  572. value: this._oscHost,
  573. onchange: function (e) {
  574. this._oscHost = this.value;
  575. window._OSCManager.setOSCHostAndPort(this._oscHost, this._oscPort);
  576. }
  577. }
  578. ]
  579. }
  580. ]
  581. },
  582. {
  583. $cell: true,
  584. $type: "div",
  585. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  586. $components: [
  587. {
  588. $type: "span",
  589. $text: "Port: "
  590. },
  591. {
  592. class: "mdc-text-field",
  593. $cell: true,
  594. $type: "span",
  595. $components: [
  596. {
  597. class: "mdc-text-field__input prop-text-field-input",
  598. id: "oscPort",
  599. $cell: true,
  600. $type: "input",
  601. type: "text",
  602. value: this._oscPort,
  603. onchange: function (e) {
  604. this._oscPort = this.value;
  605. window._OSCManager.setOSCHostAndPort(this._oscHost, this._oscPort);
  606. }
  607. }
  608. ]
  609. }
  610. ]
  611. },
  612. {
  613. $cell: true,
  614. $type: "div",
  615. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  616. $components: [
  617. widgets.buttonStroked(
  618. {
  619. "label": buttonText,
  620. "onclick": buttonFunc
  621. })
  622. ]
  623. }
  624. ]
  625. }
  626. ]
  627. }
  628. }
  629. let loadSaveSettings =
  630. {
  631. $cell: true,
  632. $type: "div",
  633. id: "loadSaveSettings",
  634. class: "propGrid max-width mdc-layout-grid mdc-layout-grid--align-left",
  635. _saveStates: [],
  636. _getStates: async function () {
  637. let response = await fetch("/" + self.getRoot() + "/listallsaves");
  638. let data = await response.json();
  639. //this._saveStates = data;
  640. //let appName = self.getRoot();
  641. //console.log(data.filter(item => item.applicationpath.split("/")[1] == appName));
  642. let filterData = data.filter(item => item.applicationpath.split("/")[1] == self.getRoot());
  643. if (filterData.length !== 0) {
  644. this._saveStates = filterData
  645. //return filterData
  646. } else {
  647. this._saveStates = [{
  648. savename: "",
  649. latestsave: "",
  650. revision: "",
  651. applicationpath: "",
  652. url: ""
  653. }]
  654. }
  655. // this._saveStates.filter(item => item.applicationpath.split("/")[1] == self.getRoot()).map(stateListElement)
  656. //return data
  657. //console.log(data);
  658. return this._saveStates
  659. },
  660. $init: function () {
  661. this._getStates();
  662. },
  663. $update: function () {
  664. this.$components =
  665. [
  666. {
  667. $cell: true,
  668. $type: "div",
  669. class: "mdc-layout-grid__inner",
  670. $components: [
  671. {
  672. $cell: true,
  673. $type: "div",
  674. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  675. $components: [
  676. {
  677. class: "mdc-text-field",
  678. $cell: true,
  679. $type: "span",
  680. $components: [
  681. {
  682. class: "mdc-text-field__input prop-text-field-input",
  683. id: "fileName",
  684. $cell: true,
  685. $type: "input",
  686. type: "text",
  687. value: self.getRoot()
  688. }]
  689. }
  690. ]
  691. },
  692. {
  693. $cell: true,
  694. $type: "div",
  695. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  696. $components: [
  697. widgets.buttonStroked(
  698. {
  699. "label": "Save",
  700. "onclick": function (e) {
  701. let fileName = document.querySelector('#fileName')
  702. saveStateAsFile.call(self, fileName.value);
  703. document.querySelector("#fileName").value = '';
  704. //document.querySelector('#' + 'viewSettings').style.visibility = 'hidden';
  705. }
  706. })
  707. ]
  708. },
  709. {
  710. $cell: true,
  711. $type: "div",
  712. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  713. $components: [
  714. {
  715. $cell: true,
  716. $type: "div",
  717. class: "mdc-select",
  718. tabindex: "0",
  719. role: "listbox",
  720. id: "loadselect",
  721. $init: function () {
  722. setTimeout(function() {
  723. var MDCSelect = mdc.select.MDCSelect;
  724. let selector = document.querySelector('#loadselect');
  725. let select = new MDCSelect(selector);
  726. selector.addEventListener('MDCSelect:change', () => {
  727. //this._selectedState = select.value;
  728. document.querySelector('#loadStateButton')._selectedState = select.selectedOptions[0];
  729. //console.log(select.value);
  730. //.selectedOptions[0]
  731. });
  732. }, 300);
  733. },
  734. $components: [
  735. {
  736. $type: "div",
  737. class: "mdc-select__surface mdc-ripple-upgraded",
  738. $components: [
  739. {
  740. $type: "div",
  741. class: "mdc-select__label",
  742. $text: "Select..."
  743. },
  744. {
  745. $type: "div",
  746. class: "mdc-select__selected-text"
  747. },
  748. {
  749. $type: "div",
  750. class: "mdc-select__bottom-line"
  751. }
  752. ]
  753. },
  754. {
  755. $type: "div",
  756. class: "mdc-simple-menu mdc-select__menu",
  757. $components: [
  758. {
  759. $type: "ul",
  760. class: "mdc-list mdc-simple-menu__items",
  761. $components: this._saveStates.map(stateListElement)
  762. }
  763. ]
  764. }
  765. ]
  766. }
  767. ]
  768. },
  769. {
  770. $cell: true,
  771. $type: "div",
  772. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  773. $components: [
  774. {
  775. $cell: true,
  776. $type: "button",
  777. _selectedState: {},
  778. id: "loadStateButton",
  779. class: "mdc-button mdc-button--raised",
  780. $text: "Load",
  781. onclick: function (e) {
  782. loadSavedState.call(self, this._selectedState.getAttribute('id'), this._selectedState.getAttribute('applicationpath'), this._selectedState.getAttribute('revision'));
  783. //document.querySelector('#' + 'viewSettings').style.visibility = 'hidden';
  784. }
  785. }
  786. ]
  787. }
  788. ]
  789. }
  790. ]
  791. }
  792. }
  793. let protoPropertiesCell = function (m) {
  794. return {
  795. $type: "div",
  796. class: "mdc-layout-grid__inner",
  797. _prop: {},
  798. $init: function () {
  799. let prop = m[1].prop;
  800. if (prop.value == undefined && this._currentNode !== undefined) {
  801. prop.value = JSON.stringify(utility.transform(vwf.getProperty(this._currentNode, prop.name, []), utility.transforms.transit));
  802. }
  803. this._prop = prop
  804. },
  805. $update: function () {
  806. this.$components = [
  807. {
  808. $type: "div",
  809. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-3",
  810. $components: [
  811. { $text: this._prop.name }
  812. ]
  813. },
  814. {
  815. $type: "div",
  816. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-2",
  817. },
  818. {
  819. $type: "div",
  820. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-7",
  821. $components: [
  822. {
  823. class: "mdc-text-field",
  824. $cell: true,
  825. $type: "div",
  826. $components: [{
  827. class: "mdc-text-field__input prop-text-field-input",
  828. $cell: true,
  829. $type: "input",
  830. type: "text",
  831. value: this._prop.value,
  832. onchange: function (e) {
  833. let propValue = this.value;
  834. try {
  835. propValue = JSON.parse(propValue);
  836. self.kernel.setProperty(this._currentNode, this._prop.name, propValue);
  837. } catch (e) {
  838. // restore the original value on error
  839. this.value = propValue;
  840. }
  841. }
  842. }]
  843. }
  844. ]
  845. }
  846. ]
  847. }
  848. }
  849. }
  850. let propertiesCell = function (m) {
  851. var editComponents = [{}, {}];
  852. // fullWidth:
  853. // fullHeight:
  854. // xoffset:
  855. // yoffset:
  856. // width:
  857. // height:
  858. let sliderPropNames = ['width', 'height', 'depth', 'fullWidth', 'fullHeight', 'xoffset', 'yoffset', 'subcamWidth', 'subcamHeight'];
  859. let sliderProps = {
  860. 'width': {
  861. min: 0,
  862. max: 30
  863. },
  864. 'height': {
  865. min: 0,
  866. max: 30
  867. },
  868. 'depth': {
  869. min: 0,
  870. max: 30
  871. },
  872. 'fullWidth': {
  873. min: 0,
  874. max: 5000,
  875. step:10
  876. },
  877. 'fullHeight': {
  878. min: 0,
  879. max: 5000,
  880. step:10
  881. },
  882. 'xoffset': {
  883. min: -10000,
  884. max: 10000,
  885. step: 10
  886. },
  887. 'yoffset': {
  888. min: -10000,
  889. max: 10000,
  890. step: 10
  891. },
  892. 'subcamWidth': {
  893. min: 0,
  894. max: 5000,
  895. step:10
  896. },
  897. 'subcamHeight': {
  898. min: 0,
  899. max: 5000,
  900. step:10
  901. }
  902. }
  903. if (sliderPropNames.includes(m.name)){
  904. let currenValue = JSON.parse(m.getValue());
  905. var sliderComponent = widgets.sliderContinuous({
  906. 'id': 'prop-slider-' + m.name,
  907. 'label': 'Slider',
  908. 'min': sliderProps[m.name].min,
  909. 'max': sliderProps[m.name].max,
  910. 'step': sliderProps[m.name].step ? sliderProps[m.name].step: 0.1,
  911. 'value': currenValue,
  912. 'init': function(){
  913. const myEl = this;
  914. var continuousSlider = new mdc.slider.MDCSlider(myEl);
  915. this._comp = continuousSlider;
  916. continuousSlider.listen('MDCSlider:input', function(e) {
  917. console.log(continuousSlider.value)
  918. let myEl = e.currentTarget;
  919. // let prop = myEl._prop.body;
  920. //document.querySelector('#propAceEditor').env.editor.setValue(prop);
  921. self.kernel.setProperty(myEl._currentNode, m.name, continuousSlider.value);
  922. //continuousValue.textContent = continuousSlider.value;
  923. });
  924. continuousSlider.listen('MDCSlider:change', function(e) {
  925. console.log(continuousSlider.value);
  926. let myEl = e.currentTarget;
  927. // let prop = myEl._prop.body;
  928. //document.querySelector('#propAceEditor').env.editor.setValue(prop);
  929. self.kernel.setProperty(myEl._currentNode, m.name, continuousSlider.value);
  930. //continuousCommittedValue.textContent = continuousSlider.value;
  931. })
  932. }
  933. })
  934. } else {
  935. sliderComponent = {}
  936. }
  937. if (m.name.indexOf("semantics") > -1) { }
  938. else if (m.name.indexOf("grammar") > -1) { }
  939. else if (m.name.indexOf("ohm") > -1) {
  940. editComponents = [
  941. {
  942. $type: "div",
  943. $cell: true,
  944. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-6",
  945. $components: [
  946. {
  947. $cell: true,
  948. $type: "button",
  949. class: "mdc-button",
  950. $text: "Edit", //edit grammar
  951. onclick: function (e) {
  952. var currentNode = document.querySelector('#currentNode')._currentNode;
  953. if (currentNode == '') {
  954. currentNode = vwf_view.kernel.find("", "/")[0];
  955. }
  956. let editor = document.querySelector('#livePropEditor');
  957. editor._setNode(currentNode);
  958. editor._propName = m.name;
  959. editor._prop = { body: m.rawValue, type: 'complex' }
  960. document.querySelector('#propEditorWindow').style.visibility = 'visible';
  961. }
  962. }
  963. ]
  964. },
  965. {
  966. $type: "div",
  967. $cell: true,
  968. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-1",
  969. $components: []
  970. }
  971. ]
  972. } else {
  973. editComponents = [
  974. {
  975. $type: "div",
  976. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-6",
  977. $components: [
  978. sliderComponent,
  979. {
  980. class: "mdc-text-field prop-mdc-text-field mdc-ripple-upgraded",
  981. $cell: true,
  982. $type: "div",
  983. $components: [
  984. {
  985. class: "mdc-text-field__input prop-text-field-input",
  986. id: "prop-" + m.name,
  987. $cell: true,
  988. $type: "input",
  989. type: "text",
  990. value: m.getValue(),
  991. onchange: function (e) {
  992. let propValue = this.value;
  993. try {
  994. propValue = JSON.parse(propValue);
  995. self.kernel.setProperty(this._currentNode, m.name, propValue);
  996. } catch (e) {
  997. // restore the original value on error
  998. this.value = propValue;
  999. }
  1000. }
  1001. }
  1002. ]
  1003. }
  1004. ]
  1005. },
  1006. {
  1007. $type: "div",
  1008. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-1",
  1009. $components: [
  1010. {
  1011. $cell: true,
  1012. $type: "button",
  1013. class: "mdc-button mdc-button--compact",
  1014. $text: "^", //edit grammar
  1015. onclick: function (e) {
  1016. var currentNode = document.querySelector('#currentNode')._currentNode;
  1017. if (currentNode == '') {
  1018. currentNode = vwf_view.kernel.find("", "/")[0];
  1019. }
  1020. let editor = document.querySelector('#livePropEditor');
  1021. editor._setNode(currentNode);
  1022. editor._propName = m.name;
  1023. editor._prop = { body: m.getValue(), type: 'simple' }
  1024. document.querySelector('#propEditorWindow').style.visibility = 'visible';
  1025. }
  1026. }
  1027. ]
  1028. }
  1029. ];
  1030. }
  1031. return {
  1032. $type: "div",
  1033. class: "mdc-layout-grid__inner",
  1034. $components: [
  1035. {
  1036. $type: "div",
  1037. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-3",
  1038. $components: [
  1039. { $text: m.name }
  1040. ]
  1041. },
  1042. {
  1043. $type: "div",
  1044. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-2",
  1045. },
  1046. editComponents[0],
  1047. editComponents[1]
  1048. ]
  1049. }
  1050. }
  1051. let nodeLink = function (m) {
  1052. var myClass = "nodeItem";
  1053. let myAvatarName = 'avatar-' + self.kernel.moniker();
  1054. (myAvatarName == m.name) ? (myClass = "avatarName mdc-typography--subheading2") :
  1055. myClass = "nodeItem"
  1056. var nodeName = m.name;
  1057. let displayName = vwf.getProperty(m.ID, 'displayName');
  1058. if (displayName)
  1059. {
  1060. nodeName = displayName
  1061. }
  1062. return {
  1063. $type: "li",
  1064. class: "mdc-list-item",
  1065. $components: [{
  1066. $type: "a",
  1067. class: "mdc-list-item",
  1068. $href: "#",
  1069. $components: [{
  1070. $type: 'span',
  1071. class: myClass,
  1072. $text: nodeName
  1073. }
  1074. ],
  1075. onclick: function (e) {
  1076. //self.currentNodeID = m.ID;
  1077. document.querySelector('#currentNode')._setNode(m.ID);
  1078. // document.querySelector('#liveCodeEditor')._editorNode = m.ID;
  1079. // createAceEditor(self, m.ID);
  1080. }
  1081. }]
  1082. }
  1083. };
  1084. let listDivider = {
  1085. $cell: true,
  1086. $type: "hr",
  1087. class: "mdc-list-divider",
  1088. }
  1089. let webrtcGUI = {
  1090. $type: "div",
  1091. class: "propGrid mdc-layout-grid max-width mdc-layout-grid--align-left",
  1092. $components: [
  1093. {
  1094. $type: "div",
  1095. class: "mdc-layout-grid__inner",
  1096. $components: [
  1097. {
  1098. $type: "div",
  1099. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-3",
  1100. $components: [
  1101. {
  1102. $type: "span",
  1103. $text: "Chat"
  1104. }
  1105. ]
  1106. },
  1107. {
  1108. $type: "div",
  1109. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-3",
  1110. $components: [
  1111. widgets.icontoggle({
  1112. 'id': "webrtcswitch",
  1113. 'label': 'visibility',
  1114. 'on': JSON.stringify({"content": "visibility", "label": "Turn On Mic"}),
  1115. 'off': JSON.stringify({"content": "visibility_off", "label": "Turn Off Mic"}),
  1116. 'state': false,
  1117. 'init': function(){
  1118. this._driver = vwf.views["vwf/view/webrtc"];
  1119. if (!this._driver) {
  1120. this.classList.add('mdc-icon-toggle--disabled');
  1121. }
  1122. this.addEventListener('MDCIconToggle:change', (e) => {
  1123. let driver = e.target._driver;
  1124. let chkAttr = e.detail.isOn;
  1125. let avatarID = 'avatar-' + self.kernel.moniker();
  1126. let micToggle = document.querySelector('#webrtcaudio');
  1127. let camToggle = document.querySelector('#webrtcvideo');
  1128. if (chkAttr) {
  1129. driver.startWebRTC(avatarID);
  1130. micToggle.classList.remove('mdc-icon-toggle--disabled');
  1131. camToggle.classList.remove('mdc-icon-toggle--disabled');
  1132. console.log("on")
  1133. } else {
  1134. driver.stopWebRTC(avatarID);
  1135. micToggle.classList.add('mdc-icon-toggle--disabled');
  1136. camToggle.classList.add('mdc-icon-toggle--disabled');
  1137. console.log("off")
  1138. }
  1139. //console.log(e, detail)
  1140. //status.textContent = `Icon Toggle is ${detail.isOn ? 'on' : 'off'}`;
  1141. });
  1142. }
  1143. })
  1144. ]
  1145. },
  1146. {
  1147. $type: "div",
  1148. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-3",
  1149. $components: [
  1150. widgets.icontoggle({
  1151. 'id': "webrtcaudio",
  1152. 'label': 'mic',
  1153. 'on': JSON.stringify({"content": "mic", "label": "Turn On Mic"}),
  1154. 'off': JSON.stringify({"content": "mic_off", "label": "Turn Off Mic"}),
  1155. 'state': false,
  1156. 'init': function(){
  1157. this._driver = vwf.views["vwf/view/webrtc"];
  1158. let webrtcswitch = document.querySelector('#webrtcswitch');
  1159. if (!this._driver) {
  1160. this.classList.add('mdc-icon-toggle--disabled');
  1161. }
  1162. this.classList.add('mdc-icon-toggle--disabled');
  1163. this.addEventListener('MDCIconToggle:change', (e) => {
  1164. let driver = e.target._driver;
  1165. let chkAttr = e.detail.isOn;
  1166. if (chkAttr) {
  1167. driver.muteAudio(chkAttr);
  1168. console.log("on")
  1169. } else {
  1170. driver.muteAudio(chkAttr);
  1171. console.log("off")
  1172. }
  1173. //console.log(e, detail)
  1174. //status.textContent = `Icon Toggle is ${detail.isOn ? 'on' : 'off'}`;
  1175. });
  1176. }
  1177. })
  1178. ]
  1179. },
  1180. {
  1181. $type: "div",
  1182. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-3",
  1183. $components: [
  1184. widgets.icontoggle({
  1185. 'id': "webrtcvideo",
  1186. 'label': 'videocam',
  1187. 'on': JSON.stringify({"content": "videocam", "label": "Turn On Video"}),
  1188. 'off': JSON.stringify({"content": "videocam_off", "label": "Turn Off Video"}),
  1189. 'state': false,
  1190. 'init': function(){
  1191. this._driver = vwf.views["vwf/view/webrtc"];
  1192. if (!this._driver) {
  1193. this.classList.add('mdc-icon-toggle--disabled');
  1194. }
  1195. this.classList.add('mdc-icon-toggle--disabled');
  1196. this.addEventListener('MDCIconToggle:change', (e) => {
  1197. let driver = e.target._driver;
  1198. let chkAttr = e.detail.isOn;
  1199. if (chkAttr) {
  1200. driver.muteVideo(chkAttr);
  1201. console.log("on")
  1202. } else {
  1203. driver.muteVideo(chkAttr);
  1204. console.log("off")
  1205. }
  1206. //console.log(e, detail)
  1207. //status.textContent = `Icon Toggle is ${detail.isOn ? 'on' : 'off'}`;
  1208. });
  1209. }
  1210. })
  1211. ]
  1212. }
  1213. ]
  1214. }
  1215. ]
  1216. }
  1217. let gizmoEdit = {
  1218. $type: "div",
  1219. class: "propGrid mdc-layout-grid max-width mdc-layout-grid--align-left",
  1220. $components: [
  1221. {
  1222. $type: "div",
  1223. class: "mdc-layout-grid__inner",
  1224. $components: [
  1225. {
  1226. $type: "div",
  1227. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-2",
  1228. $components: [
  1229. {
  1230. $cell: true,
  1231. $type: "span",
  1232. $text: "Edit: ",
  1233. }
  1234. ]
  1235. },
  1236. {
  1237. $type: "div",
  1238. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-7",
  1239. $components: [
  1240. widgets.switch({
  1241. 'id': 'editnode',
  1242. 'init': function(){
  1243. vwf_view.kernel.getProperty(this._currentNode, 'edit');
  1244. },
  1245. 'onchange': function(e){
  1246. var nodeID = document.querySelector('#currentNode')._currentNode;
  1247. let chkAttr = this.getAttribute('checked');
  1248. if (chkAttr == "") {
  1249. self.kernel.setProperty(this._currentNode, 'edit', false);
  1250. } else {
  1251. self.kernel.setProperty(this._currentNode, 'edit', true);
  1252. }
  1253. vwf_view.kernel.callMethod(nodeID, "showCloseGizmo");
  1254. }
  1255. }
  1256. )
  1257. ]
  1258. },
  1259. {
  1260. $type: "div",
  1261. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-1",
  1262. $components: [
  1263. {
  1264. $cell: true,
  1265. $type: "a",
  1266. class: "gizmomode",
  1267. $text: "T",
  1268. onclick: function (e) {
  1269. vwf_view.kernel.callMethod(this._currentNode, "setGizmoMode", ['translate'])
  1270. }
  1271. }
  1272. ]
  1273. },
  1274. {
  1275. $type: "div",
  1276. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-1",
  1277. $components: [
  1278. {
  1279. $cell: true,
  1280. $type: "a",
  1281. class: "gizmomode",
  1282. $text: "R",
  1283. onclick: function (e) {
  1284. vwf_view.kernel.callMethod(this._currentNode, "setGizmoMode", ['rotate'])
  1285. }
  1286. }
  1287. ]
  1288. },
  1289. {
  1290. $type: "div",
  1291. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-1",
  1292. $components: [
  1293. {
  1294. $cell: true,
  1295. $type: "a",
  1296. class: "gizmomode",
  1297. $text: "S",
  1298. onclick: function (e) {
  1299. vwf_view.kernel.callMethod(this._currentNode, "setGizmoMode", ['scale'])
  1300. }
  1301. }
  1302. ]
  1303. }
  1304. ]
  1305. }
  1306. ]
  1307. }
  1308. let nodesCell = {
  1309. $cell: true,
  1310. $type: "div",
  1311. id: "currentNode",
  1312. _childNodes: [],
  1313. _currentNode: '',
  1314. _displayedProperties: {},
  1315. _setNode: function (aNode) {
  1316. this._currentNode = aNode;
  1317. document.querySelector('#sideBar')._sideCurrentNode = this._currentNode
  1318. },
  1319. $init: function () {
  1320. this._currentNode = document.querySelector('#sideBar')._sideCurrentNode
  1321. //this._currentNode = vwf_view.kernel.find("", "/")[0];
  1322. //this._currentNode = '3333';
  1323. },
  1324. _getChildNodes: function () {
  1325. this._childNodes = self.nodes[this._currentNode];
  1326. if (this._childNodes !== undefined) {
  1327. return this._childNodes.children
  1328. } else {
  1329. return []
  1330. }
  1331. //let nodeIDAlpha = he.encode(this._currentNode);
  1332. },
  1333. // _getNodeComplexProperties: function () {
  1334. // let node = self.nodes[this._currentNode];
  1335. // let props = this._getNodeProperties();
  1336. // let filterFunction = function (prop) {
  1337. // return (prop.name == 'ohmLang')
  1338. // };
  1339. // let complexProps = props.filter(filterFunction.bind(this));
  1340. // return complexProps
  1341. // },
  1342. _getNodeProperties: function () {
  1343. let node = self.nodes[this._currentNode];
  1344. this._displayedProperties = {};
  1345. let filterFunction = function (prop) {
  1346. return (!this._displayedProperties[prop.name] && prop.name.indexOf('$') === -1) ? (this._displayedProperties[prop.name] = "instance", true) : (false);
  1347. };
  1348. let props = node.properties.filter(filterFunction.bind(this));
  1349. return props
  1350. },
  1351. _getNodeProtoProperties: function () {
  1352. let node = self.nodes[this._currentNode];
  1353. let filterFunction = function (prop) {
  1354. return (!this._displayedProperties[prop[1].prop.name]) ? (this._displayedProperties[prop[1].prop.name] = prop[1].prototype, true) : (false);
  1355. };
  1356. let props = Object.entries(getProperties.call(self, self.kernel, node.extendsID)).filter(filterFunction.bind(this));
  1357. return props
  1358. },
  1359. $update: function () {
  1360. //this.$text = this._currentNode;
  1361. let node = self.nodes[this._currentNode];
  1362. let nodeProtos = getPrototypes(self.kernel, node.extendsID);
  1363. var viewerProps = {};
  1364. var viewerPropsCell = {};
  1365. var gizmoCell = {};
  1366. if (this._currentNode !== self.kernel.application()) {
  1367. if (nodeProtos.includes('http://vwf.example.com/aframe/componentNode.vwf')) {
  1368. //gizmoCell = {};
  1369. } else {
  1370. gizmoCell = gizmoEdit
  1371. }
  1372. }
  1373. if (node !== undefined) {
  1374. if (node.extendsID == "http://vwf.example.com/aframe/acamera.vwf") {
  1375. viewerProps = {
  1376. $type: "li",
  1377. class: "mdc-list-item",
  1378. $components: [
  1379. {
  1380. $text: "Viewer properties",
  1381. $type: "span",
  1382. class: "mdc-list-item__text mdc-typography--button"
  1383. }
  1384. ]
  1385. }
  1386. viewerPropsCell = {
  1387. $cell: true,
  1388. $type: "div",
  1389. class: "propGrid mdc-layout-grid max-width mdc-layout-grid--align-left",
  1390. $components: [
  1391. {
  1392. $cell: true,
  1393. $type: "div",
  1394. class: "mdc-layout-grid__inner",
  1395. $components: [
  1396. {
  1397. $cell: true,
  1398. $type: "div",
  1399. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  1400. $components: [
  1401. widgets.buttonStroked(
  1402. {
  1403. "label": "Active",
  1404. "onclick": function (e) {
  1405. //let camera = document.querySelector('#' + this._currentNode);
  1406. vwf_view.kernel.callMethod(this._currentNode, "setCameraToActive", [vwf.moniker_]);
  1407. //camera.setAttribute('camera', 'active', true);
  1408. }
  1409. })
  1410. ]
  1411. }
  1412. ]
  1413. }
  1414. ]
  1415. //$components: this._getNodeProtoProperties().map(protoPropertiesCell)
  1416. }
  1417. } else {
  1418. viewerProps = {};
  1419. viewerPropsCell = {};
  1420. }
  1421. }
  1422. this.$components = [
  1423. {
  1424. $cell: true,
  1425. $type: "ul",
  1426. class: "mdc-list",
  1427. $components: [
  1428. widgets.buttonStroked(
  1429. {
  1430. "label": "<--",
  1431. "onclick": function (e) {
  1432. let node = self.nodes[this._currentNode];
  1433. if (node.parentID !== 0) {
  1434. //self.currentNodeID = node.parentID,
  1435. document.querySelector('#currentNode')._setNode(node.parentID)
  1436. }
  1437. }
  1438. }),
  1439. {
  1440. $type: "li",
  1441. class: "mdc-list-item",
  1442. $components: [
  1443. {
  1444. $text: "name",
  1445. $type: "span",
  1446. $init: function () {
  1447. let node = self.nodes[this._currentNode];
  1448. if (node) {
  1449. let displayName = vwf.getProperty(node.ID, 'displayName');
  1450. if (displayName)
  1451. {
  1452. this.$text = displayName
  1453. } else {
  1454. this.$text = node.name;
  1455. }
  1456. }
  1457. //console.log(node.properties.displayName)
  1458. },
  1459. class: "mdc-list-item__text mdc-typography--headline"
  1460. //<h1 class="mdc-typography--display4">Big header</h1>
  1461. }]
  1462. }, listDivider,
  1463. {
  1464. // $cell: true,
  1465. // $type: "ul",
  1466. // class: "mdc-list",
  1467. $type: "div",
  1468. class: "propGrid mdc-layout-grid max-width mdc-layout-grid--align-left",
  1469. $components: [
  1470. {
  1471. $type: "div",
  1472. class: "mdc-layout-grid__inner",
  1473. $components: [
  1474. {
  1475. $type: "div",
  1476. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  1477. $components: [
  1478. widgets.buttonStroked(
  1479. {
  1480. "label": "Methods browser",
  1481. "onclick": function (e) {
  1482. var currentNode = document.querySelector('#currentNode')._currentNode;
  1483. if (currentNode == '') {
  1484. currentNode = vwf_view.kernel.find("", "/")[0];
  1485. }
  1486. document.querySelector('#liveCodeEditor')._setNode(currentNode);
  1487. //createAceEditor(self, currentNode);
  1488. document.querySelector('#codeEditorWindow').style.visibility = 'visible';
  1489. }
  1490. })
  1491. ]
  1492. }
  1493. ]
  1494. }
  1495. ]
  1496. },
  1497. gizmoCell,
  1498. listDivider,
  1499. {
  1500. $type: "li",
  1501. class: "mdc-list-item",
  1502. $components: [
  1503. {
  1504. $text: "Children",
  1505. $type: "span",
  1506. class: "mdc-list-item__text mdc-typography--button"
  1507. }]
  1508. },
  1509. {
  1510. $cell: true,
  1511. $type: "ul",
  1512. class: "mdc-list",
  1513. $components: this._getChildNodes().map(nodeLink)
  1514. }, listDivider, {
  1515. $type: "li",
  1516. class: "mdc-list-item",
  1517. $components: [
  1518. {
  1519. $text: "Properties",
  1520. $type: "span",
  1521. class: "mdc-list-item__text mdc-typography--button"
  1522. //<h1 class="mdc-typography--display4">Big header</h1>
  1523. }]
  1524. },
  1525. {
  1526. // $cell: true,
  1527. // $type: "ul",
  1528. // class: "mdc-list",
  1529. $type: "div",
  1530. class: "propGrid mdc-layout-grid max-width mdc-layout-grid--align-left",
  1531. $components: this._getNodeProperties().map(propertiesCell)
  1532. },
  1533. listDivider,
  1534. {
  1535. $type: "li",
  1536. class: "mdc-list-item",
  1537. $components: [
  1538. {
  1539. $text: "Proto properties",
  1540. $type: "span",
  1541. class: "mdc-list-item__text mdc-typography--button"
  1542. }]
  1543. },
  1544. {
  1545. $cell: true,
  1546. $type: "div",
  1547. class: "propGrid mdc-layout-grid max-width mdc-layout-grid--align-left",
  1548. $components: this._getNodeProtoProperties().map(protoPropertiesCell)
  1549. }, listDivider,
  1550. viewerProps,
  1551. viewerPropsCell
  1552. ]
  1553. }
  1554. ]
  1555. }
  1556. }
  1557. let numberSliderComponent = {
  1558. $cell: true,
  1559. $type: "div",
  1560. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-4",
  1561. $init: function () {
  1562. },
  1563. $components: [
  1564. {
  1565. $cell: true,
  1566. $type: "div",
  1567. style: "padding: 0 16px;",
  1568. $components:[
  1569. {}
  1570. ]
  1571. }
  1572. ]
  1573. }
  1574. let colorPickerComponent = {
  1575. $cell: true,
  1576. $type: "div",
  1577. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-4",
  1578. $init: function () {
  1579. let myEl = this;
  1580. let cp = ColorPicker(
  1581. document.getElementById('slide'),
  1582. document.getElementById('picker'),
  1583. function (hex, hsv, rgb, mousePicker, mouseSlide) {
  1584. ColorPicker.positionIndicators(
  1585. document.getElementById('slide-indicator'),
  1586. document.getElementById('picker-indicator'),
  1587. mouseSlide, mousePicker
  1588. );
  1589. if (myEl._propName == 'color') {
  1590. // console.log(hex);
  1591. document.querySelector('#propAceEditor').env.editor.setValue(JSON.stringify(hex));
  1592. self.kernel.setProperty(myEl._editorNode, myEl._propName, hex);
  1593. }
  1594. });
  1595. if (myEl._propName == 'color') {
  1596. cp.setHex(JSON.parse(myEl._prop.body));
  1597. }
  1598. },
  1599. $components: [
  1600. {
  1601. $cell: true,
  1602. $type: "div",
  1603. id: "color-picker",
  1604. class: "cp-default",
  1605. $components: [
  1606. {
  1607. $cell: true,
  1608. $type: "div",
  1609. class: "picker-wrapper",
  1610. $components: [
  1611. {
  1612. $cell: true,
  1613. $type: "div",
  1614. id: "picker",
  1615. class: "picker",
  1616. style: "width: 130px; height: 130px"
  1617. },
  1618. {
  1619. $cell: true,
  1620. $type: "div",
  1621. id: "picker-indicator",
  1622. class: "picker-indicator"
  1623. }
  1624. ]
  1625. },
  1626. {
  1627. $cell: true,
  1628. $type: "div",
  1629. class: "slide-wrapper",
  1630. $components: [
  1631. {
  1632. $cell: true,
  1633. $type: "div",
  1634. id: "slide",
  1635. class: "slide",
  1636. style: "width: 30px; height: 130px"
  1637. },
  1638. {
  1639. $cell: true,
  1640. $type: "div",
  1641. id: "slide-indicator",
  1642. class: "slide-indicator"
  1643. }
  1644. ]
  1645. }
  1646. ]
  1647. }
  1648. // {
  1649. // $cell: true,
  1650. // $type: "div",
  1651. // id: "color-picker",
  1652. // $init: function () {
  1653. // }
  1654. // }
  1655. ]
  1656. }
  1657. let propEditorWindow = {
  1658. $cell: true,
  1659. $type: "div",
  1660. _editorNode: '',
  1661. _prop: { body: '', type: 'simple' },
  1662. _propName: '',
  1663. id: "livePropEditor",
  1664. _setNode: function (node) {
  1665. this._editorNode = node;
  1666. this._prop.body = ''
  1667. },
  1668. class: "propEditorGrid mdc-layout-grid max-width mdc-layout-grid--align-left",
  1669. $update: function () {
  1670. var editorClass = "mdc-layout-grid__cell mdc-layout-grid__cell--span-8"
  1671. var livePropertyComponent = {}
  1672. if (this._prop.type == 'simple') {
  1673. if (this._propName == 'color') {
  1674. livePropertyComponent = colorPickerComponent
  1675. }
  1676. } else {
  1677. editorClass = "mdc-layout-grid__cell mdc-layout-grid__cell--span-12"
  1678. }
  1679. this.$components = [
  1680. {
  1681. $cell: true,
  1682. $type: "div",
  1683. class: "mdc-layout-grid__inner",
  1684. $components: [
  1685. {
  1686. $cell: true,
  1687. $type: "div",
  1688. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-2",
  1689. $components: [
  1690. widgets.buttonStroked(
  1691. {
  1692. "label": "Update",
  1693. "onclick": function (e) {
  1694. let editor = document.querySelector("#propAceEditor").env.editor;
  1695. let value = editor.getValue();
  1696. try {
  1697. let propValue = (this._prop.type == 'simple') ? (JSON.parse(value)) : (value)
  1698. //propValue = JSON.parse(value);
  1699. self.kernel.setProperty(this._editorNode, this._propName, propValue);
  1700. } catch (e) {
  1701. // restore the original value on error
  1702. this.value = propValue;
  1703. }
  1704. }
  1705. }
  1706. )]
  1707. },
  1708. {
  1709. $cell: true,
  1710. $type: "div",
  1711. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-5",
  1712. $components: [
  1713. {
  1714. $type: "h3",
  1715. class: "mdc-list-group__subheader mdc-list-item__text mdc-typography--subheading1",
  1716. $text: this._editorNode
  1717. }
  1718. ]
  1719. },
  1720. {
  1721. $cell: true,
  1722. $type: "div",
  1723. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-5",
  1724. $components: [
  1725. {
  1726. $type: "h3",
  1727. class: "mdc-list-group__subheader mdc-list-item__text mdc-typography--subheading1",
  1728. $text: this._propName
  1729. }
  1730. ]
  1731. }
  1732. ]
  1733. },
  1734. {
  1735. $cell: true,
  1736. $type: "div",
  1737. class: "mdc-layout-grid__inner",
  1738. $components: [
  1739. {
  1740. $cell: true,
  1741. $type: "div",
  1742. class: editorClass,
  1743. $components: [
  1744. {
  1745. $cell: true,
  1746. class: "aceEditor",
  1747. id: "propAceEditor",
  1748. $type: "div",
  1749. $text: this._prop.body,
  1750. $init: function () {
  1751. createAceEditor(self, this._editorNode, "propAceEditor");
  1752. this.env.editor.$blockScrolling = Infinity
  1753. }
  1754. }
  1755. ]
  1756. }, livePropertyComponent
  1757. // {
  1758. // $cell: true,
  1759. // $type: "div",
  1760. // class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-2",
  1761. // $components: []
  1762. // },
  1763. ]
  1764. }
  1765. ]
  1766. //$components:
  1767. }
  1768. }
  1769. let codeEditorWindow = {
  1770. $cell: true,
  1771. $type: "div",
  1772. _editorNode: '',
  1773. _method: { body: '' },
  1774. _methodName: '',
  1775. _getNodeMethods: function () {
  1776. let node = self.nodes[this._editorNode];
  1777. return node.methods
  1778. },
  1779. _getProtoNodeMethods: function () {
  1780. let node = self.nodes[this._editorNode];
  1781. let prototypeMethods = getMethods.call(self, self.kernel, node.extendsID);
  1782. return prototypeMethods
  1783. },
  1784. id: "liveCodeEditor",
  1785. _setNode: function (node) {
  1786. this._editorNode = node;
  1787. this._method.body = ''
  1788. },
  1789. class: "codeEditorGrid mdc-layout-grid max-width mdc-layout-grid--align-left",
  1790. // _getComplexProps: function(){
  1791. // let node = self.nodes[this._editorNode];
  1792. // let currentNode = document.querySelector('#currentNode');
  1793. // var props = {}
  1794. // if (currentNode !== null) {
  1795. // props = currentNode._getNodeComplexProperties();
  1796. // }
  1797. // return props
  1798. // },
  1799. // _listPropertyElement: function (m) {
  1800. // return {
  1801. // $type: "li",
  1802. // class: "mdc-list-item",
  1803. // $components: [{
  1804. // $type: "a",
  1805. // class: "mdc-list-item",
  1806. // $href: "#",
  1807. // $text: m[1].name,
  1808. // onclick: function (e) {
  1809. // this._method = {};
  1810. // this._methodName = m[1].name;
  1811. // this._method.body = m[1].rawValue
  1812. // this._method.type = "complexProperty"
  1813. // }
  1814. // }]
  1815. // }
  1816. // },
  1817. _listElement: function (m) {
  1818. return {
  1819. $type: "li",
  1820. class: "mdc-list-item",
  1821. $components: [{
  1822. $type: "a",
  1823. class: "mdc-list-item",
  1824. $href: "#",
  1825. $text: m[0],
  1826. onclick: function (e) {
  1827. let method = vwf.getMethod(this._editorNode, m[0]);
  1828. //document.querySelector('#aceEditor').
  1829. this._method = method;
  1830. this._methodName = m[0];
  1831. //self.currentNodeID = m.ID;
  1832. //document.querySelector('#currentNode')._setNode(m.ID);
  1833. }
  1834. }]
  1835. }
  1836. },
  1837. $update: function () {
  1838. this.$components = [
  1839. {
  1840. $cell: true,
  1841. $type: "div",
  1842. class: "mdc-layout-grid__inner",
  1843. $components: [
  1844. {
  1845. $cell: true,
  1846. $type: "div",
  1847. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-3",
  1848. $components: [
  1849. {
  1850. $type: "h3",
  1851. class: "mdc-list-group__subheader mdc-list-item__text mdc-typography--subheading1",
  1852. $text: this._editorNode
  1853. }
  1854. ]
  1855. },
  1856. {
  1857. $cell: true,
  1858. $type: "div",
  1859. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-2",
  1860. $components: [
  1861. widgets.buttonStroked(
  1862. {
  1863. "label": "Update",
  1864. "onclick": function (e) {
  1865. let editor = document.querySelector("#aceEditor").env.editor;
  1866. let evalText = editor.getValue();
  1867. // if (this._method.type == 'complexProperty') {
  1868. // let propValue = evalText;
  1869. // try {
  1870. // //propValue = JSON.parse(propValue);
  1871. // self.kernel.setProperty(this._editorNode, this._methodName, propValue);
  1872. // } catch (e) {
  1873. // // restore the original value on error
  1874. // this.value = propValue;
  1875. // }
  1876. // } else {
  1877. // }
  1878. self.kernel.setMethod(this._editorNode, this._methodName,
  1879. { body: evalText, type: "application/javascript", parameters: this._method.parameters });
  1880. }
  1881. }
  1882. )]
  1883. },
  1884. {
  1885. $cell: true,
  1886. $type: "div",
  1887. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-2",
  1888. $components: [
  1889. widgets.buttonStroked(
  1890. {
  1891. "label": "Call",
  1892. "onclick": function (e) {
  1893. var params = [];
  1894. if (this._method.parameters) {
  1895. let paramsLength = this._method.parameters.length
  1896. if (paramsLength >= 1) {
  1897. let paramsVal = document.querySelector("#methodParams").value;
  1898. try {
  1899. params = JSON.parse(paramsVal);
  1900. //params.push(prmtr);
  1901. } catch (e) {
  1902. self.logger.error('Invalid Value');
  1903. }
  1904. }
  1905. };
  1906. self.kernel.callMethod(this._editorNode, this._methodName, params);
  1907. }
  1908. })
  1909. ]
  1910. },
  1911. {
  1912. $cell: true,
  1913. $type: "div",
  1914. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-2",
  1915. $components: [
  1916. widgets.buttonStroked(
  1917. {
  1918. "label": "Do It",
  1919. "onclick": function (e) {
  1920. let editor = document.querySelector("#aceEditor").env.editor;
  1921. codeEditorDoit.call(self, editor, this._editorNode);
  1922. }
  1923. })
  1924. ]
  1925. },
  1926. {
  1927. $cell: true,
  1928. $type: "div",
  1929. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-3",
  1930. $components: [
  1931. widgets.buttonStroked(
  1932. {
  1933. "label": "Print It",
  1934. "onclick": function (e) {
  1935. let editor = document.querySelector("#aceEditor").env.editor;
  1936. codeEditorPrintit.call(self, editor, this._editorNode);
  1937. }
  1938. })
  1939. ]
  1940. }
  1941. ]
  1942. },
  1943. {
  1944. $cell: true,
  1945. $type: "div",
  1946. class: "mdc-layout-grid__inner",
  1947. $components: [
  1948. {
  1949. $cell: true,
  1950. $type: "div",
  1951. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-3",
  1952. style: "overflow-y: scroll; max-height: 400px;",
  1953. $components: [
  1954. {
  1955. $cell: true,
  1956. $type: "div",
  1957. class: "mdc-list-group",
  1958. $components: [
  1959. {
  1960. $type: "h3",
  1961. class: "mdc-list-group__subheader mdc-list-item__text mdc-typography--button",
  1962. $text: "Node methods"
  1963. },
  1964. {
  1965. $cell: true,
  1966. $type: "ul",
  1967. class: "mdc-list",
  1968. $components: Object.entries(this._getNodeMethods()).map(this._listElement)
  1969. }, listDivider,
  1970. {
  1971. $type: "h3",
  1972. class: "mdc-list-group__subheader mdc-list-item__text mdc-typography--button",
  1973. $text: "Proto methods"
  1974. },
  1975. {
  1976. $cell: true,
  1977. $type: "ul",
  1978. class: "mdc-list",
  1979. $components: Object.entries(this._getProtoNodeMethods()).map(this._listElement)
  1980. }, listDivider,
  1981. {
  1982. $type: "h3",
  1983. class: "mdc-list-group__subheader mdc-list-item__text mdc-typography--button",
  1984. $text: "Events"
  1985. }
  1986. // {
  1987. // $cell: true,
  1988. // $type: "ul",
  1989. // class: "mdc-list",
  1990. // $components: Object.entries(this._getComplexProps()).map(this._listPropertyElement)
  1991. // }
  1992. ]
  1993. }
  1994. ]
  1995. },
  1996. {
  1997. $cell: true,
  1998. $type: "div",
  1999. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-9",
  2000. $components: [
  2001. {
  2002. $cell: true,
  2003. class: "aceEditor",
  2004. id: "aceEditor",
  2005. $type: "div",
  2006. $text: this._method.body,
  2007. $init: function () {
  2008. createAceEditor(self, this._editorNode, "aceEditor");
  2009. }
  2010. }
  2011. ]
  2012. }
  2013. ]
  2014. },
  2015. {
  2016. $cell: true,
  2017. $type: "div",
  2018. class: "mdc-layout-grid__inner",
  2019. $components: [
  2020. {
  2021. $cell: true,
  2022. $type: "div",
  2023. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  2024. $components: [
  2025. {
  2026. $type: "span",
  2027. $text: "*"
  2028. }
  2029. ]
  2030. }
  2031. ]
  2032. },
  2033. { //params input
  2034. $cell: true,
  2035. $type: "div",
  2036. class: "mdc-layout-grid__inner",
  2037. $components: [
  2038. {
  2039. $cell: true,
  2040. $type: "div",
  2041. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-3",
  2042. $components: [
  2043. {
  2044. class: "mdc-text-field",
  2045. $cell: true,
  2046. $type: "div",
  2047. $components: [{
  2048. class: "mdc-text-field__input prop-text-field-input",
  2049. id: "methodName",
  2050. $cell: true,
  2051. $type: "input",
  2052. type: "text",
  2053. value: "newMethodName",
  2054. onchange: function (e) {
  2055. let propValue = this.value;
  2056. try {
  2057. } catch (e) {
  2058. // restore the original value on error
  2059. }
  2060. }
  2061. }]
  2062. }
  2063. ]
  2064. },
  2065. {
  2066. $cell: true,
  2067. $type: "div",
  2068. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-7",
  2069. $components: [
  2070. {
  2071. class: "mdc-text-field params-text-field-input",
  2072. $cell: true,
  2073. $type: "div",
  2074. $components: [{
  2075. class: "mdc-text-field__input prop-text-field-input",
  2076. id: "methodParams",
  2077. $cell: true,
  2078. $type: "input",
  2079. type: "text",
  2080. value: JSON.stringify(this._method.parameters),
  2081. onchange: function (e) {
  2082. let propValue = this.value;
  2083. try {
  2084. } catch (e) {
  2085. // restore the original value on error
  2086. }
  2087. }
  2088. }]
  2089. }
  2090. ]
  2091. },
  2092. {
  2093. $cell: true,
  2094. $type: "div",
  2095. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-2",
  2096. $components: [
  2097. widgets.buttonStroked(
  2098. {
  2099. "label": "Create",
  2100. "onclick": function (e) {
  2101. let methodName = document.querySelector('#methodName').value;
  2102. //let methodParams = document.querySelector('#methodParams');
  2103. var params = [];
  2104. let body = '';
  2105. let paramsVal = document.querySelector("#methodParams").value;
  2106. if (paramsVal !== '') {
  2107. try {
  2108. params = JSON.parse(paramsVal);
  2109. //params.push(prmtr);
  2110. } catch (e) {
  2111. self.logger.error('Invalid Value');
  2112. }
  2113. }
  2114. self.kernel.createMethod(this._editorNode, methodName, params, body);
  2115. this._setNode(this._editorNode);
  2116. // let editor = document.querySelector("#aceEditor").env.editor;
  2117. // codeEditorDoit.call(self, editor, this._editorNode);
  2118. }
  2119. })
  2120. ]
  2121. }
  2122. ]
  2123. }
  2124. ]
  2125. //$components:
  2126. }
  2127. }
  2128. let propWindow = {
  2129. $cell: true,
  2130. $type: "div",
  2131. class: "propGrid mdc-layout-grid max-width mdc-layout-grid--align-left",
  2132. style: "overflow-y: scroll; max-height: 800px;",
  2133. $components: [
  2134. {
  2135. $type: "div",
  2136. class: "mdc-layout-grid__inner",
  2137. $components: [
  2138. {
  2139. $cell: true,
  2140. $type: "div",
  2141. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  2142. $components: [
  2143. nodesCell
  2144. ]
  2145. }
  2146. ]
  2147. }
  2148. // <button class="mdc-button">
  2149. // Flat button
  2150. // </button>
  2151. ]
  2152. }
  2153. let clientListCell = {
  2154. $cell: true,
  2155. $type: "div",
  2156. class: "mdc-list",
  2157. id: "clientsList",
  2158. _watchNodes: [],
  2159. _listElement: function (m) {
  2160. return {
  2161. $type: "a",
  2162. class: "mdc-list-item",
  2163. $href: "#",
  2164. $text: m.name,
  2165. onclick: function (e) {
  2166. //self.currentNodeID = m.ID;
  2167. //document.querySelector('#currentNode')._setNode(m.ID);
  2168. }
  2169. }
  2170. },
  2171. $init: function () {
  2172. var t = this;
  2173. setInterval(function () {
  2174. t._updateMe();
  2175. }, 1000);
  2176. },
  2177. _updateMe: function () {
  2178. this._watchNodes = self.nodes["http://vwf.example.com/clients.vwf"].children.slice()
  2179. },
  2180. $update: function () {
  2181. //this._clientNodes
  2182. this.$components = this._watchNodes.map(this._listElement)
  2183. }
  2184. }
  2185. //createCellWindow("clientsWindow", clientListCell, "Clients");
  2186. //createCellWindow("propWindow", propWindow, "Scene");
  2187. createCellWindow("codeEditorWindow", codeEditorWindow, "Code editor");
  2188. createCellWindow("propEditorWindow", propEditorWindow, "Prop editor");
  2189. let viewSceneProps = {
  2190. $cell: true,
  2191. $type: "div",
  2192. class: "propGrid mdc-layout-grid mdc-layout-grid--align-left",
  2193. //style: "overflow-y: scroll; max-height: 500px; overflow-x: hidden;",
  2194. $components: [
  2195. {
  2196. $type: "div",
  2197. class: "mdc-layout-grid__inner",
  2198. $components: [
  2199. {
  2200. $cell: true,
  2201. $type: "div",
  2202. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  2203. $components: [
  2204. nodesCell
  2205. ]
  2206. }
  2207. ]
  2208. }
  2209. ]
  2210. }
  2211. let sideBar = {
  2212. $cell: true,
  2213. $type: "div",
  2214. id: 'sideBar',
  2215. class: "sideBar mdc-toolbar-fixed-adjust",
  2216. _sideBarComponent: {},
  2217. _sideCurrentNode: '',
  2218. $init: function () {
  2219. this.style.visibility = 'hidden';
  2220. this._importScript("/" + self.getRoot() + "/appui.js");
  2221. },
  2222. _importScript: function (sSrc, fOnload) {
  2223. var oScript = document.createElement("script");
  2224. oScript.type = "text\/javascript";
  2225. oScript.async = false;
  2226. //oScript.onerror = loadError;
  2227. if (fOnload) { oScript.onload = fOnload; }
  2228. oScript.src = sSrc;
  2229. //let sideBar = document.querySelector('#sideBar');
  2230. this.appendChild(oScript);
  2231. },
  2232. _getAppDef: async function () {
  2233. let response = await fetch("/" + self.getRoot() + "/appui.js");
  2234. let data = await response.text();
  2235. //console.log(data)
  2236. return data
  2237. },
  2238. $update: function () {
  2239. this.$components = [
  2240. {
  2241. $cell: true,
  2242. $type: "button",
  2243. class: "mdc-button mdc-button--compact",
  2244. $text: "X",
  2245. onclick: function (e) {
  2246. document.querySelector('#sideBar').style.visibility = 'hidden';
  2247. }
  2248. },
  2249. this._sideBarComponent
  2250. ]
  2251. }
  2252. //$components: [this._sideComponents]
  2253. }
  2254. document.querySelector('#' + 'sideBar').$cell(sideBar)
  2255. let defaultApp = function () {
  2256. return {
  2257. $cell: true,
  2258. $type: "div",
  2259. class: "propGrid max-width mdc-layout-grid mdc-layout-grid--align-left",
  2260. $components: [
  2261. {
  2262. $cell: true,
  2263. $type: "div",
  2264. class: "mdc-layout-grid__inner",
  2265. $components: [
  2266. {
  2267. $cell: true,
  2268. $type: "div",
  2269. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  2270. $components: [
  2271. {
  2272. $cell: true,
  2273. $type: "h3",
  2274. class: "mdc-typography--headline",
  2275. $text: "Application",
  2276. }
  2277. ]
  2278. }
  2279. ]
  2280. }
  2281. ]
  2282. }
  2283. }
  2284. let drawerCell = {
  2285. $cell: true,
  2286. $type: "nav",
  2287. class: "mdc-temporary-drawer__drawer",
  2288. $components: [
  2289. {
  2290. $cell: true,
  2291. $type: "header",
  2292. class: "mdc-temporary-drawer__header",
  2293. $components: [
  2294. {
  2295. $cell: true,
  2296. $type: "div",
  2297. class: "mdc-temporary-drawer__header-content mdc-theme--primary-bg mdc-theme--text-primary-on-primary",
  2298. $text: "Home"
  2299. }
  2300. ]
  2301. },
  2302. {
  2303. $cell: true,
  2304. $type: "nav",
  2305. class: "mdc-temporary-drawer__content mdc-list-group",
  2306. $components: [
  2307. {
  2308. $cell: true,
  2309. $type: "div",
  2310. class: "mdc-list",
  2311. $components: [
  2312. {
  2313. $cell: true,
  2314. $type: "a",
  2315. class: "mdc-list-item",
  2316. $href: "#",
  2317. onclick: function (e) {
  2318. let sideBar = document.querySelector('#sideBar');
  2319. try {
  2320. sideBar._sideBarComponent = createApp.call(self);
  2321. } catch (e) {
  2322. sideBar._sideBarComponent = defaultApp();
  2323. }
  2324. drawer.open = !drawer.open
  2325. document.querySelector('#sideBar').style.visibility = 'visible';
  2326. },
  2327. $components: [{
  2328. $type: "i",
  2329. class: "material-icons mdc-list-item__start-detail",
  2330. 'aria-hidden': "true",
  2331. $text: "play_arrow"
  2332. },
  2333. {
  2334. $text: "App"
  2335. }]
  2336. },
  2337. {
  2338. $cell: true,
  2339. $type: "a",
  2340. class: "mdc-list-item",
  2341. $href: "#",
  2342. onclick: function (e) {
  2343. let sideBar = document.querySelector('#sideBar');
  2344. sideBar._sideBarComponent = viewSceneProps;
  2345. let currentNode = document.querySelector('#sideBar')._sideCurrentNode;
  2346. currentNode == '' ? document.querySelector('#sideBar')._sideCurrentNode = (vwf_view.kernel.find("", "/")[0]) :
  2347. document.querySelector('#sideBar')._sideCurrentNode = currentNode;
  2348. document.querySelector('#sideBar').style.visibility = 'visible';
  2349. drawer.open = !drawer.open
  2350. // let currentNode = document.querySelector('#currentNode')._currentNode;
  2351. // currentNode == '' ? document.querySelector('#currentNode')._setNode(vwf_view.kernel.find("", "/")[0]) :
  2352. // document.querySelector('#currentNode')._setNode(currentNode);
  2353. },
  2354. $components: [{
  2355. $cell: true,
  2356. $type: "i",
  2357. class: "material-icons mdc-list-item__start-detail",
  2358. $text: "description"
  2359. },
  2360. {
  2361. $text: "Scene"
  2362. }
  2363. ]
  2364. },
  2365. {
  2366. $cell: true,
  2367. $type: "a",
  2368. class: "mdc-list-item",
  2369. $href: "#",
  2370. onclick: function (e) {
  2371. //self.currentNodeID = m.ID;
  2372. // document.querySelector('#clientsList')._setClientNodes(self.nodes["http://vwf.example.com/clients.vwf"]);
  2373. // document.querySelector('#clientsWindow').style.visibility = 'visible';
  2374. let sideBar = document.querySelector('#sideBar');
  2375. sideBar._sideBarComponent = createSettings;
  2376. drawer.open = !drawer.open
  2377. document.querySelector('#sideBar').style.visibility = 'visible';
  2378. },
  2379. $components: [{
  2380. $type: "i",
  2381. class: "material-icons mdc-list-item__start-detail",
  2382. 'aria-hidden': "true",
  2383. $text: "create"
  2384. },
  2385. {
  2386. $text: "Create"
  2387. }]
  2388. },
  2389. {
  2390. $cell: true,
  2391. $type: "a",
  2392. class: "mdc-list-item",
  2393. $href: "#",
  2394. onclick: function (e) {
  2395. // var currentNode = document.querySelector('#currentNode')._currentNode;
  2396. // if (currentNode == '') {
  2397. // currentNode = vwf_view.kernel.find("", "/")[0];
  2398. // }
  2399. document.querySelector('#liveCodeEditor')._setNode(vwf_view.kernel.find("", "/")[0]);
  2400. //createAceEditor(self, currentNode);
  2401. document.querySelector('#codeEditorWindow').style.visibility = 'visible';
  2402. },
  2403. $components: [{
  2404. $type: "i",
  2405. class: "material-icons mdc-list-item__start-detail",
  2406. 'aria-hidden': "true",
  2407. $text: "code"
  2408. },
  2409. {
  2410. $text: "Code editor"
  2411. }]
  2412. },
  2413. {
  2414. $cell: true,
  2415. $type: "a",
  2416. class: "mdc-list-item",
  2417. $href: "#",
  2418. onclick: function (e) {
  2419. //self.currentNodeID = m.ID;
  2420. // document.querySelector('#clientsList')._setClientNodes(self.nodes["http://vwf.example.com/clients.vwf"]);
  2421. // document.querySelector('#clientsWindow').style.visibility = 'visible';
  2422. let sideBar = document.querySelector('#sideBar');
  2423. sideBar._sideBarComponent = avatarSettings;
  2424. drawer.open = !drawer.open
  2425. document.querySelector('#sideBar').style.visibility = 'visible';
  2426. },
  2427. $components: [{
  2428. $type: "i",
  2429. class: "material-icons mdc-list-item__start-detail",
  2430. 'aria-hidden': "true",
  2431. $text: "account_circle"
  2432. },
  2433. {
  2434. $text: "My Avatar"
  2435. }]
  2436. },
  2437. {
  2438. $cell: true,
  2439. $type: "a",
  2440. class: "mdc-list-item",
  2441. $href: "#",
  2442. onclick: function (e) {
  2443. //self.currentNodeID = m.ID;
  2444. // document.querySelector('#clientsList')._setClientNodes(self.nodes["http://vwf.example.com/clients.vwf"]);
  2445. let sideBar = document.querySelector('#sideBar');
  2446. sideBar._sideBarComponent = viewSettings;
  2447. drawer.open = !drawer.open
  2448. document.querySelector('#sideBar').style.visibility = 'visible';
  2449. },
  2450. $components: [{
  2451. $type: "i",
  2452. class: "material-icons mdc-list-item__start-detail",
  2453. 'aria-hidden': "true",
  2454. $text: "settings"
  2455. },
  2456. {
  2457. $text: "Settings"
  2458. }]
  2459. },
  2460. {
  2461. $cell: true,
  2462. $type: "a",
  2463. class: "mdc-list-item",
  2464. $href: "#",
  2465. onclick: function (e) {
  2466. //self.currentNodeID = m.ID;
  2467. // document.querySelector('#clientsList')._setClientNodes(self.nodes["http://vwf.example.com/clients.vwf"]);
  2468. let sideBar = document.querySelector('#sideBar');
  2469. sideBar._sideBarComponent = loadSaveSettings;
  2470. if (document.querySelector('#loadSaveSettings')) {
  2471. document.querySelector('#loadSaveSettings')._getStates();
  2472. }
  2473. //sideBar._sideBarComponent._getStates();
  2474. drawer.open = !drawer.open
  2475. document.querySelector('#sideBar').style.visibility = 'visible';
  2476. },
  2477. $components: [{
  2478. $type: "i",
  2479. class: "material-icons mdc-list-item__start-detail",
  2480. 'aria-hidden': "true",
  2481. $text: "save"
  2482. },
  2483. {
  2484. $text: "Load/Save"
  2485. }]
  2486. }
  2487. ]
  2488. },
  2489. widgets.divider,
  2490. webrtcGUI,
  2491. widgets.divider,
  2492. widgets.headerH3("h3", "Users online", "userList mdc-list-group__subheader"),
  2493. clientListCell
  2494. //widgets.headerH3("h3", "WebRTC", "userList mdc-list-group__subheader"),
  2495. ]
  2496. }
  2497. // {
  2498. // $cell: true,
  2499. // $type: "div",
  2500. // class: "mdc-persistent-drawer__toolbar-spacer",
  2501. // },
  2502. // {
  2503. // $cell: true,
  2504. // $type: "div",
  2505. // class: "mdc-list-group",
  2506. // $components: [{
  2507. // $cell: true,
  2508. // $type: "nav",
  2509. // class: "mdc-list",
  2510. // $components: [
  2511. // ]
  2512. // }]
  2513. // }
  2514. ]
  2515. };
  2516. // <div class="mdc-form-field">
  2517. // <input type="checkbox" id="input">
  2518. // <label for="input">Input Label</label>
  2519. // </div>
  2520. document.querySelector("#drawer").$cell({
  2521. $cell: true,
  2522. $type: "aside",
  2523. class: "mdc-temporary-drawer",
  2524. $components: [drawerCell]
  2525. }
  2526. );
  2527. let toolbar = {
  2528. $cell: true,
  2529. $type: "div",
  2530. class: "mdc-toolbar__row",
  2531. $components: [{
  2532. $type: "section",
  2533. class: "mdc-toolbar__section mdc-toolbar__section--align-start",
  2534. $components: [
  2535. {
  2536. $type: "button",
  2537. class: "demo-menu material-icons mdc-toolbar__menu-icon",
  2538. $text: "menu"
  2539. },
  2540. {
  2541. $type: "span",
  2542. class: "mdc-toolbar__title catalog-title",
  2543. $text: "LiveCoding.space"
  2544. },
  2545. {
  2546. $type: "a",
  2547. href: "#",
  2548. class: "material-icons mdc-toolbar__icon toggleCreate",
  2549. $text: "apps",
  2550. 'aria-label': "More"
  2551. },
  2552. {
  2553. $type: "div",
  2554. class: "mdc-menu-anchor",
  2555. $components: [
  2556. {
  2557. $type: "div",
  2558. class: "mdc-simple-menu",
  2559. "tabindex": "-1",
  2560. id: "create-menu",
  2561. $init: function(){
  2562. //var menuEl = document.querySelector('#demo-menu');
  2563. var menu = new mdc.menu.MDCSimpleMenu(this);
  2564. var toggle = document.querySelector('.toggleCreate');
  2565. toggle.addEventListener('click', function() {
  2566. menu.open = !menu.open;
  2567. });
  2568. },
  2569. style: "transform-origin: right top 0px; right: 0px; top: 0px; transform: scale(0, 0);",
  2570. $components: [
  2571. {
  2572. $type: "ul",
  2573. class: "mdc-simple-menu__items mdc-list",
  2574. role: "menu",
  2575. 'aria-hidden': "true",
  2576. style: "transform: scale(1, 1);",
  2577. $components: [
  2578. {
  2579. $type: "li",
  2580. class: "mdc-list-item",
  2581. role: "menuitem",
  2582. tabindex: "0",
  2583. $text: "Apps"
  2584. }
  2585. ]
  2586. }
  2587. ]
  2588. }
  2589. ]
  2590. },
  2591. widgets.icontoggle({
  2592. 'styleClass': "mdc-toolbar__icon",
  2593. 'id': "selectNodeSwitch",
  2594. 'label': 'select',
  2595. 'on': JSON.stringify({"content": "radio_button_checked", "label": "Select"}),
  2596. 'off': JSON.stringify({"content": "radio_button_unchecked", "label": "Unselect"}),
  2597. 'state': false,
  2598. 'init': function(){
  2599. this.addEventListener('MDCIconToggle:change', (e) => {
  2600. let avatarID = 'avatar-'+ vwf.moniker_;
  2601. let avatarNode = self.nodes['avatar-'+ vwf.moniker_];
  2602. let mode = JSON.parse(avatarNode.properties.selectMode.getValue());
  2603. if (mode) {
  2604. console.log("unselect");
  2605. vwf_view.kernel.setProperty(avatarID, "selectMode", false);
  2606. } else {
  2607. console.log("select")
  2608. vwf_view.kernel.setProperty(avatarID, "selectMode", true);
  2609. }
  2610. });
  2611. }
  2612. })
  2613. ]
  2614. },
  2615. {
  2616. $type: "section",
  2617. class: "mdc-toolbar__section mdc-toolbar__section--align-end",
  2618. $components: [
  2619. {
  2620. $type: "a",
  2621. href: "#",
  2622. class: "material-icons mdc-toolbar__icon toggle",
  2623. $text: "help",
  2624. 'aria-label': "Help"
  2625. }
  2626. ]
  2627. }
  2628. ]
  2629. };
  2630. document.querySelector("#toolbar").$cell({
  2631. $cell: true,
  2632. $type: "div",
  2633. class: "mdc-toolbar mdc-toolbar--fixed",
  2634. $components: [toolbar]
  2635. }
  2636. );
  2637. // let drawer = new mdc.drawer.MDCTemporaryDrawer(document.querySelector('.mdc-temporary-drawer'));
  2638. // document.querySelector('.menu').addEventListener('click', () => drawer.open = true);
  2639. var toggleNodes = document.querySelectorAll('.mdc-icon-toggle');
  2640. toggleNodes.forEach( el => {
  2641. mdc.iconToggle.MDCIconToggle.attachTo(el);
  2642. });
  2643. var drawerEl = document.querySelector('.mdc-temporary-drawer');
  2644. var MDCTemporaryDrawer = mdc.drawer.MDCTemporaryDrawer;
  2645. var drawer = new MDCTemporaryDrawer(drawerEl);
  2646. document.querySelector('.demo-menu').addEventListener('click', function () {
  2647. //self.currentNodeID = (self.currentNodeID == '') ? (vwf_view.kernel.find("", "/")[0]) : self.currentNodeID;
  2648. // let currentNode = document.querySelector('#currentNode')._currentNode;
  2649. // currentNode == '' ? document.querySelector('#currentNode')._setNode(vwf_view.kernel.find("", "/")[0]) :
  2650. // document.querySelector('#currentNode')._setNode(currentNode);
  2651. //document.querySelector('#currentNode')._setNode(self.currentNodeID);
  2652. drawer.open = !drawer.open;
  2653. });
  2654. drawerEl.addEventListener('MDCTemporaryDrawer:open', function () {
  2655. //console.log('Received MDCPersistentDrawer:open');
  2656. });
  2657. drawerEl.addEventListener('MDCTemporaryDrawer:close', function () {
  2658. //console.log('Received MDCPersistentDrawer:close');
  2659. });
  2660. //==============
  2661. },
  2662. createdNode: function (nodeID, childID, childExtendsID, childImplementsIDs,
  2663. childSource, childType, childIndex, childName, callback /* ( ready ) */) {
  2664. var nodeIDAttribute = $.encoder.encodeForHTMLAttribute("id", nodeID, true);
  2665. var childIDAttribute = $.encoder.encodeForHTMLAttribute("id", childID, true);
  2666. var childIDAlpha = $.encoder.encodeForAlphaNumeric(childID);
  2667. var kernel = this.kernel;
  2668. var self = this;
  2669. var parent = this.nodes[nodeID];
  2670. var node = this.nodes[childID] = {
  2671. children: [],
  2672. properties: [],
  2673. events: {},
  2674. methods: {},
  2675. parent: parent,
  2676. parentID: nodeID,
  2677. ID: childID,
  2678. extendsID: childExtendsID,
  2679. implementsIDs: childImplementsIDs,
  2680. source: childSource,
  2681. name: childName,
  2682. };
  2683. if (parent) {
  2684. parent.children.push(node);
  2685. }
  2686. if (childID == vwf_view.kernel.find("", "/")[0] && childExtendsID && this.kernel.test(childExtendsID,
  2687. "self::element(*,'http://vwf.example.com/aframe/ascene.vwf')", childExtendsID)) {
  2688. this.scenes[childID] = node;
  2689. }
  2690. let nodeCell = document.querySelector("#currentNode");
  2691. if (nodeCell !== null) {
  2692. if (nodeCell._currentNode === nodeID) {
  2693. nodeCell._getChildNodes();
  2694. }
  2695. }
  2696. if (nodeID === this.kernel.application()) {
  2697. // document.querySelector('a-scene').classList.add("mdc-toolbar-fixed-adjust");
  2698. document.querySelector('body').classList.add("editor-body");
  2699. }
  2700. },
  2701. createdProperty: function (nodeID, propertyName, propertyValue) {
  2702. return this.initializedProperty(nodeID, propertyName, propertyValue);
  2703. },
  2704. initializedProperty: function (nodeID, propertyName, propertyValue) {
  2705. var node = this.nodes[nodeID];
  2706. if (!node) return; // TODO: patch until full-graph sync is working; drivers should be able to assume that nodeIDs refer to valid objects
  2707. var property = node.properties[propertyName] = createProperty.call(this, node, propertyName, propertyValue);
  2708. node.properties.push(property);
  2709. },
  2710. deletedNode: function (nodeID) {
  2711. var node = this.nodes[nodeID];
  2712. node.parent.children.splice(node.parent.children.indexOf(node), 1);
  2713. delete this.nodes[nodeID];
  2714. let nodeCell = document.querySelector("#currentNode");
  2715. if (nodeCell) {
  2716. if (nodeCell._currentNode !== "") {
  2717. if (nodeCell._currentNode !== nodeID) {
  2718. //&& (this.nodes[nodeID] !== undefined)
  2719. nodeCell._getChildNodes();
  2720. } else {
  2721. nodeCell._setNode(vwf_view.kernel.find("", "/")[0]);
  2722. nodeCell._getChildNodes();
  2723. }
  2724. }
  2725. }
  2726. },
  2727. //addedChild: [ /* nodeID, childID, childName */ ],
  2728. //removedChild: [ /* nodeID, childID */ ],
  2729. satProperty: function (nodeID, propertyName, propertyValue) {
  2730. var node = this.nodes[nodeID];
  2731. if (!node) return; // TODO: patch until full-graph sync is working; drivers should be able to assume that nodeIDs refer to valid objects
  2732. // It is possible for a property to have satProperty called for it without ever getting an
  2733. // initializedProperty (if that property delegated to itself or another on replication)
  2734. // Catch that case here and create the property
  2735. if (!node.properties[propertyName]) {
  2736. var property = node.properties[propertyName] = createProperty.call(this, node, propertyName, propertyValue);
  2737. node.properties.push(property);
  2738. }
  2739. try {
  2740. propertyValue = utility.transform(propertyValue, utility.transforms.transit);
  2741. node.properties[propertyName].value = JSON.stringify(propertyValue);
  2742. node.properties[propertyName].rawValue = propertyValue;
  2743. } catch (e) {
  2744. this.logger.warnx("satProperty", nodeID, propertyName, propertyValue,
  2745. "stringify error:", e.message);
  2746. node.properties[propertyName].value = propertyValue;
  2747. }
  2748. let nodeCell = document.querySelector('#currentNode');
  2749. if (nodeCell !== null) {
  2750. if (nodeCell._currentNode == nodeID && propertyName == 'edit') {
  2751. console.log('EDIT !!!')
  2752. }
  2753. }
  2754. let propCell = document.querySelector("#currentNode #prop-" + propertyName);
  2755. let propSlider = document.querySelector("#currentNode #prop-slider-" + propertyName);
  2756. if (propCell !== null) {
  2757. if (propCell._currentNode == nodeID) {
  2758. propCell.value = node.properties[propertyName].getValue();
  2759. }
  2760. }
  2761. if (propSlider !== null) {
  2762. if (propSlider._currentNode == nodeID) {
  2763. //const propSliderComp = new new mdc.slider.MDCSlider(propSlider);
  2764. propSlider._comp.value = node.properties[propertyName].getValue();
  2765. }
  2766. }
  2767. },
  2768. //gotProperty: [ /* nodeID, propertyName, propertyValue */ ],
  2769. gotProperty: function (nodeID, propertyName, propertyValue) {
  2770. var node = this.nodes[nodeID];
  2771. if (!node) return; // TODO: patch until full-graph sync is working; drivers should be able to assume that nodeIDs refer to valid objects
  2772. let nodeCell = document.querySelector('#currentNode');
  2773. if (nodeCell !== null) {
  2774. if (nodeCell._currentNode == nodeID && propertyName == 'edit') {
  2775. let editCheckBox = document.querySelector("#currentNode #editnode");
  2776. if (editCheckBox) {
  2777. if (propertyValue) {
  2778. editCheckBox.setAttribute('checked', '');
  2779. } else {
  2780. let checkAttr = editCheckBox.getAttribute('checked');
  2781. if (checkAttr) editCheckBox.removeAttribute('checked');
  2782. }
  2783. }
  2784. console.log('EDIT !!! is ' + propertyValue)
  2785. }
  2786. }
  2787. },
  2788. createdMethod: function (nodeID, methodName, methodParameters, methodBody) {
  2789. var node = this.nodes[nodeID];
  2790. if (node) {
  2791. node.methods[methodName] = methodParameters;
  2792. }
  2793. },
  2794. //calledMethod: function( nodeID, methodName, methodParameters, methodValue ) {
  2795. //},
  2796. createdEvent: function (nodeID, eventName, eventParameters) {
  2797. var node = this.nodes[nodeID];
  2798. if (node) {
  2799. node.events[eventName] = eventParameters;
  2800. }
  2801. },
  2802. firedEvent: function (nodeID, eventName, eventParameters) {
  2803. },
  2804. executed: function (nodeID, scriptText, scriptType) {
  2805. // var nodeScript = {
  2806. // text: scriptText,
  2807. // type: scriptType,
  2808. // };
  2809. // if ( !this.allScripts[ nodeID ] ) {
  2810. // var nodeScripts = new Array();
  2811. // nodeScripts.push(nodeScript);
  2812. // this.allScripts[ nodeID ] = nodeScripts;
  2813. // }
  2814. // else {
  2815. // this.allScripts[ nodeID ].push(nodeScript);
  2816. // }
  2817. },
  2818. //ticked: [ /* time */ ],
  2819. });
  2820. function createCellWindow(elementID, cellNode, title) {
  2821. document.querySelector('#' + elementID).$cell({
  2822. $cell: true,
  2823. $type: "div",
  2824. id: elementID,
  2825. class: 'draggable',
  2826. $init: function () {
  2827. // let draggie = new Draggabilly('.draggable', {
  2828. // handle: '.handle',
  2829. // containment: true
  2830. // });
  2831. // get all draggie elements
  2832. var draggableElems = document.querySelectorAll('.draggable');
  2833. // array of Draggabillies
  2834. var draggies = []
  2835. // init Draggabillies
  2836. for (var i = 0, len = draggableElems.length; i < len; i++) {
  2837. var draggableElem = draggableElems[i];
  2838. var draggie = new Draggabilly(draggableElem, {
  2839. handle: '.handle',
  2840. containment: true
  2841. });
  2842. draggies.push(draggie);
  2843. }
  2844. this.style.visibility = 'hidden';
  2845. },
  2846. $components: [
  2847. {
  2848. $cell: true,
  2849. $type: "div",
  2850. class: "handle"
  2851. },
  2852. {
  2853. $cell: true,
  2854. $type: "button",
  2855. class: "mdc-button mdc-button--compact",
  2856. $text: "X",
  2857. onclick: function (e) {
  2858. //self.currentNodeID = m.ID;
  2859. document.querySelector('#' + elementID).style.visibility = 'hidden';
  2860. }
  2861. },
  2862. {
  2863. $cell: true,
  2864. $type: "span",
  2865. class: "mdc-typography--button",
  2866. $text: title
  2867. },
  2868. cellNode,
  2869. {
  2870. $cell: true,
  2871. $type: "div",
  2872. class: "handle",
  2873. style: "height: 10px; width: inherit;",
  2874. //$text: "sdfsdf"
  2875. }
  2876. // { $text: "23423"}
  2877. ]
  2878. }
  2879. );
  2880. }
  2881. // -- getChildByName --------------------------------------------------------------------
  2882. function getChildByName(node, childName) {
  2883. var childNode = undefined;
  2884. for (var i = 0; i < node.children.length && childNode === undefined; i++) {
  2885. if (node.children[i].name == childName) {
  2886. childNode = node.children[i];
  2887. }
  2888. }
  2889. return childNode;
  2890. };
  2891. // -- viewScript ------------------------------------------------------------------------
  2892. function createAceEditor(view, nodeID, elID) {
  2893. var editor = view.ace.edit(elID);
  2894. editor.setTheme("ace/theme/monokai");
  2895. editor.setFontSize(16);
  2896. editor.getSession().setMode("ace/mode/javascript");
  2897. editor.commands.addCommand({
  2898. name: "doit",
  2899. bindKey: { win: "Ctrl-e", mac: "Command-e" },
  2900. exec: function () {
  2901. codeEditorDoit(editor, nodeID);
  2902. }
  2903. });
  2904. editor.commands.addCommand({
  2905. name: "printit",
  2906. bindKey: { win: "Ctrl-b", mac: "Command-b" },
  2907. exec: function () {
  2908. codeEditorPrintit(editor, nodeID);
  2909. }
  2910. });
  2911. return editor;
  2912. }
  2913. function getPrototypes(kernel, extendsID) {
  2914. var prototypes = [];
  2915. var id = extendsID;
  2916. while (id !== undefined) {
  2917. prototypes.push(id);
  2918. id = kernel.prototype(id);
  2919. }
  2920. return prototypes;
  2921. }
  2922. function getPrototypes(kernel, extendsID) {
  2923. var prototypes = [];
  2924. var id = extendsID;
  2925. while (id !== undefined) {
  2926. prototypes.push(id);
  2927. id = kernel.prototype(id);
  2928. }
  2929. return prototypes;
  2930. }
  2931. function createProperty(node, propertyName, propertyValue) {
  2932. var property = {
  2933. name: propertyName,
  2934. rawValue: propertyValue,
  2935. value: undefined,
  2936. getValue: function () {
  2937. var propertyValue;
  2938. if (this.value == undefined) {
  2939. try {
  2940. propertyValue = utility.transform(this.rawValue, utility.transforms.transit);
  2941. this.value = JSON.stringify(propertyValue);
  2942. } catch (e) {
  2943. this.logger.warnx("createdProperty", nodeID, this.propertyName, this.rawValue,
  2944. "stringify error:", e.message);
  2945. this.value = this.rawValue;
  2946. }
  2947. }
  2948. return this.value;
  2949. }
  2950. };
  2951. return property;
  2952. }
  2953. function getProperties(kernel, extendsID) {
  2954. var pTypes = getPrototypes(kernel, extendsID);
  2955. var pProperties = {};
  2956. if (pTypes) {
  2957. for (var i = 0; i < pTypes.length; i++) {
  2958. var nd = this.nodes[pTypes[i]];
  2959. if (nd && nd.properties) {
  2960. for (var key in nd.properties) {
  2961. pProperties[key] = { "prop": nd.properties[key], "prototype": pTypes[i] };
  2962. }
  2963. }
  2964. }
  2965. }
  2966. return pProperties;
  2967. }
  2968. function getChildren(kernel, extendsID) {
  2969. var pTypes = getPrototypes(kernel, extendsID);
  2970. var pChildren = {};
  2971. if (pTypes) {
  2972. for (var i = 0; i < pTypes.length; i++) {
  2973. var nd = this.nodes[pTypes[i]];
  2974. if (nd && nd.children) {
  2975. for (var key in nd.children) {
  2976. pChildren[key] = nd.children[key];
  2977. }
  2978. }
  2979. }
  2980. }
  2981. return pChildren;
  2982. }
  2983. function getEvents(kernel, extendsID) {
  2984. var pTypes = getPrototypes(kernel, extendsID);
  2985. var events = {};
  2986. if (pTypes) {
  2987. for (var i = 0; i < pTypes.length; i++) {
  2988. var nd = this.nodes[pTypes[i]];
  2989. if (nd && nd.events) {
  2990. for (var key in nd.events) {
  2991. events[key] = nd.events[key];
  2992. }
  2993. }
  2994. }
  2995. }
  2996. return events;
  2997. }
  2998. function getMethods(kernel, extendsID) {
  2999. var pTypes = getPrototypes(kernel, extendsID);
  3000. var methods = {};
  3001. if (pTypes) {
  3002. for (var i = 0; i < pTypes.length; i++) {
  3003. var nd = this.nodes[pTypes[i]];
  3004. if (nd && nd.methods) {
  3005. for (var key in nd.methods) {
  3006. methods[key] = nd.methods[key];
  3007. }
  3008. }
  3009. }
  3010. }
  3011. return methods;
  3012. }
  3013. // -- Show Code Editor tab
  3014. function codeEditorDoit(editor, nodeID) {
  3015. var selectedText = editor.getSession().doc.getTextRange(editor.selection.getRange());
  3016. if (selectedText == "") {
  3017. var currline = editor.getSelectionRange().start.row;
  3018. var selectedText = editor.session.getLine(currline);
  3019. }
  3020. //console.log(selectedText);
  3021. //var sceneID = self.kernel.application();
  3022. vwf_view.kernel.execute(nodeID, selectedText);
  3023. }
  3024. function codeEditorPrintit(editor, nodeID) {
  3025. var selectedText = editor.getSession().doc.getTextRange(editor.selection.getRange());
  3026. if (selectedText == "") {
  3027. var currline = editor.getSelectionRange().start.row;
  3028. var selectedText = editor.session.getLine(currline);
  3029. }
  3030. //console.log(selectedText);
  3031. //var sceneID = self.kernel.application();
  3032. let scriptText = 'console.log(' + selectedText + ');'
  3033. self.kernel.execute(nodeID, scriptText);
  3034. }
  3035. function saveStateAsFile(filename) // invoke with the view as "this"
  3036. {
  3037. this.logger.info("Saving: " + filename);
  3038. var clients = this.nodes["http://vwf.example.com/clients.vwf"];
  3039. if (supportAjaxUploadWithProgress.call(this)) {
  3040. var xhr = new XMLHttpRequest();
  3041. // Save State Information
  3042. var state = vwf.getState();
  3043. state.nodes[0].children = {};
  3044. var timestamp = state["queue"].time;
  3045. timestamp = Math.round(timestamp * 1000);
  3046. var objectIsTypedArray = function (candidate) {
  3047. var typedArrayTypes = [
  3048. Int8Array,
  3049. Uint8Array,
  3050. // Uint8ClampedArray,
  3051. Int16Array,
  3052. Uint16Array,
  3053. Int32Array,
  3054. Uint32Array,
  3055. Float32Array,
  3056. Float64Array
  3057. ];
  3058. var isTypedArray = false;
  3059. if (typeof candidate == "object" && candidate != null) {
  3060. typedArrayTypes.forEach(function (typedArrayType) {
  3061. isTypedArray = isTypedArray || candidate instanceof typedArrayType;
  3062. });
  3063. }
  3064. return isTypedArray;
  3065. };
  3066. var transitTransformation = function (object) {
  3067. return objectIsTypedArray(object) ?
  3068. Array.prototype.slice.call(object) : object;
  3069. };
  3070. var json = JSON.stringify(
  3071. require("vwf/utility").transform(
  3072. state, transitTransformation
  3073. )
  3074. );
  3075. json = $.encoder.encodeForURL(json);
  3076. var path = window.location.pathname;
  3077. var pathSplit = path.split('/');
  3078. if (pathSplit[0] == "") {
  3079. pathSplit.shift();
  3080. }
  3081. if (pathSplit[pathSplit.length - 1] == "") {
  3082. pathSplit.pop();
  3083. }
  3084. var inst = undefined;
  3085. var instIndex = pathSplit.length - 1;
  3086. if (pathSplit.length > 2) {
  3087. if (pathSplit[pathSplit.length - 2] == "load") {
  3088. instIndex = pathSplit.length - 3;
  3089. }
  3090. }
  3091. if (pathSplit.length > 3) {
  3092. if (pathSplit[pathSplit.length - 3] == "load") {
  3093. instIndex = pathSplit.length - 4;
  3094. }
  3095. }
  3096. inst = pathSplit[instIndex];
  3097. var root = "";
  3098. for (var i = 0; i < instIndex; i++) {
  3099. if (root != "") {
  3100. root = root + "/";
  3101. }
  3102. root = root + pathSplit[i];
  3103. }
  3104. if (filename == '') filename = inst;
  3105. if (root.indexOf('.vwf') != -1) root = root.substring(0, root.lastIndexOf('/'));
  3106. xhr.open("POST", "/" + root + "/save/" + filename, true);
  3107. xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  3108. xhr.send("root=" + root + "/" + filename + "&filename=saveState&inst=" + inst + "&timestamp=" + timestamp + "&extension=.vwf.json" + "&jsonState=" + json);
  3109. // Save Config Information
  3110. var config = { "info": {}, "model": {}, "view": {} };
  3111. // Save browser title
  3112. config["info"]["title"] = document.title//$('title').html();
  3113. // Save model drivers
  3114. Object.keys(vwf_view.kernel.kernel.models).forEach(function (modelDriver) {
  3115. if (modelDriver.indexOf('vwf/model/') != -1) config["model"][modelDriver] = "";
  3116. });
  3117. // If neither glge or threejs model drivers are defined, specify nodriver
  3118. if (config["model"]["vwf/model/glge"] === undefined && config["model"]["vwf/model/threejs"] === undefined) config["model"]["nodriver"] = "";
  3119. // Save view drivers and associated parameters, if any
  3120. Object.keys(vwf_view.kernel.kernel.views).forEach(function (viewDriver) {
  3121. if (viewDriver.indexOf('vwf/view/') != -1) {
  3122. if (vwf_view.kernel.kernel.views[viewDriver].parameters) {
  3123. config["view"][viewDriver] = vwf_view.kernel.kernel.views[viewDriver].parameters;
  3124. }
  3125. else config["view"][viewDriver] = "";
  3126. }
  3127. });
  3128. var jsonConfig = $.encoder.encodeForURL(JSON.stringify(config));
  3129. // Save config file to server
  3130. var xhrConfig = new XMLHttpRequest();
  3131. xhrConfig.open("POST", "/" + root + "/save/" + filename, true);
  3132. xhrConfig.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  3133. xhrConfig.send("root=" + root + "/" + filename + "&filename=saveState&inst=" + inst + "&timestamp=" + timestamp + "&extension=.vwf.config.json" + "&jsonState=" + jsonConfig);
  3134. }
  3135. else {
  3136. console.error("Unable to save state.");
  3137. }
  3138. }
  3139. // -- LoadSavedState --------------------------------------------------------------------------
  3140. function loadSavedState(filename, applicationpath, revision) {
  3141. this.logger.info("Loading: " + filename);
  3142. // Redirect until setState ID conflict is resolved
  3143. var path = window.location.pathname;
  3144. var inst = path.substring(path.length - 17, path.length - 1);
  3145. var pathSplit = path.split('/');
  3146. if (pathSplit[0] == "") {
  3147. pathSplit.shift();
  3148. }
  3149. if (pathSplit[pathSplit.length - 1] == "") {
  3150. pathSplit.pop();
  3151. }
  3152. var inst = undefined;
  3153. var instIndex = pathSplit.length - 1;
  3154. if (pathSplit.length > 2) {
  3155. if (pathSplit[pathSplit.length - 2] == "load") {
  3156. instIndex = pathSplit.length - 3;
  3157. }
  3158. }
  3159. if (pathSplit.length > 3) {
  3160. if (pathSplit[pathSplit.length - 3] == "load") {
  3161. instIndex = pathSplit.length - 4;
  3162. }
  3163. }
  3164. inst = pathSplit[instIndex];
  3165. if (revision) {
  3166. window.location.pathname = applicationpath + "/" + inst + '/load/' + filename + '/' + revision + '/';
  3167. }
  3168. else {
  3169. window.location.pathname = applicationpath + "/" + inst + '/load/' + filename + '/';
  3170. }
  3171. // $.get(filename,function(data,status){
  3172. // vwf.setState(data);
  3173. // });
  3174. }
  3175. // -- SupportAjax -----------------------------------------------------------------------------
  3176. function supportAjaxUploadWithProgress() {
  3177. return supportAjaxUploadProgressEvents();
  3178. function supportAjaxUploadProgressEvents() {
  3179. var xhr = new XMLHttpRequest();
  3180. return !!(xhr && ('upload' in xhr) && ('onprogress' in xhr.upload));
  3181. }
  3182. }
  3183. });