babylon.canvas2d.max.js 709 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581
  1. var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  2. var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  3. if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  4. else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  5. return c > 3 && r && Object.defineProperty(target, key, r), r;
  6. };
  7. var __extends = (this && this.__extends) || function (d, b) {
  8. for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
  9. function __() { this.constructor = d; }
  10. __.prototype = b.prototype;
  11. d.prototype = new __();
  12. };
  13. var BABYLON;
  14. (function (BABYLON) {
  15. var PropertyChangedInfo = (function () {
  16. function PropertyChangedInfo() {
  17. }
  18. return PropertyChangedInfo;
  19. }());
  20. BABYLON.PropertyChangedInfo = PropertyChangedInfo;
  21. /**
  22. * The purpose of this class is to provide a base implementation of the IPropertyChanged interface for the user to avoid rewriting a code needlessly.
  23. * Typical use of this class is to check for equality in a property set(), then call the onPropertyChanged method if values are different after the new value is set. The protected method will notify observers of the change.
  24. * Remark: onPropertyChanged detects reentrant code and acts in a way to make sure everything is fine, fast and allocation friendly (when there no reentrant code which should be 99% of the time)
  25. */
  26. var PropertyChangedBase = (function () {
  27. function PropertyChangedBase() {
  28. this._propertyChanged = null;
  29. }
  30. /**
  31. * Protected method to call when there's a change of value in a property set
  32. * @param propName the name of the concerned property
  33. * @param oldValue its old value
  34. * @param newValue its new value
  35. * @param mask an optional observable mask
  36. */
  37. PropertyChangedBase.prototype.onPropertyChanged = function (propName, oldValue, newValue, mask) {
  38. if (this.propertyChanged.hasObservers()) {
  39. var pci = PropertyChangedBase.calling ? new PropertyChangedInfo() : PropertyChangedBase.pci;
  40. pci.oldValue = oldValue;
  41. pci.newValue = newValue;
  42. pci.propertyName = propName;
  43. try {
  44. PropertyChangedBase.calling = true;
  45. this.propertyChanged.notifyObservers(pci, mask);
  46. }
  47. finally {
  48. PropertyChangedBase.calling = false;
  49. }
  50. }
  51. };
  52. Object.defineProperty(PropertyChangedBase.prototype, "propertyChanged", {
  53. /**
  54. * An observable that is triggered when a property (using of the XXXXLevelProperty decorator) has its value changing.
  55. * You can add an observer that will be triggered only for a given set of Properties using the Mask feature of the Observable and the corresponding Prim2DPropInfo.flagid value (e.g. Prim2DBase.positionProperty.flagid|Prim2DBase.rotationProperty.flagid to be notified only about position or rotation change)
  56. */
  57. get: function () {
  58. if (!this._propertyChanged) {
  59. this._propertyChanged = new BABYLON.Observable();
  60. }
  61. return this._propertyChanged;
  62. },
  63. enumerable: true,
  64. configurable: true
  65. });
  66. PropertyChangedBase.pci = new PropertyChangedInfo();
  67. PropertyChangedBase.calling = false;
  68. return PropertyChangedBase;
  69. }());
  70. BABYLON.PropertyChangedBase = PropertyChangedBase;
  71. })(BABYLON || (BABYLON = {}));
  72. var BABYLON;
  73. (function (BABYLON) {
  74. /**
  75. * Class for the ObservableArray.onArrayChanged observable
  76. */
  77. var ArrayChanged = (function () {
  78. function ArrayChanged() {
  79. this.action = 0;
  80. this.newItems = new Array();
  81. this.removedItems = new Array();
  82. this.changedItems = new Array();
  83. this.newStartingIndex = -1;
  84. this.removedStartingIndex = -1;
  85. }
  86. Object.defineProperty(ArrayChanged, "clearAction", {
  87. /**
  88. * The content of the array was totally cleared
  89. */
  90. get: function () {
  91. return ArrayChanged._clearAction;
  92. },
  93. enumerable: true,
  94. configurable: true
  95. });
  96. Object.defineProperty(ArrayChanged, "newItemsAction", {
  97. /**
  98. * A new item was added, the newItems field contains the key/value pairs
  99. */
  100. get: function () {
  101. return ArrayChanged._newItemsAction;
  102. },
  103. enumerable: true,
  104. configurable: true
  105. });
  106. Object.defineProperty(ArrayChanged, "removedItemsAction", {
  107. /**
  108. * An existing item was removed, the removedKey field contains its key
  109. */
  110. get: function () {
  111. return ArrayChanged._removedItemsAction;
  112. },
  113. enumerable: true,
  114. configurable: true
  115. });
  116. Object.defineProperty(ArrayChanged, "changedItemAction", {
  117. /**
  118. * One or many items in the array were changed, the
  119. */
  120. get: function () {
  121. return ArrayChanged._changedItemAction;
  122. },
  123. enumerable: true,
  124. configurable: true
  125. });
  126. Object.defineProperty(ArrayChanged, "replacedArrayAction", {
  127. /**
  128. * The array's content was totally changed
  129. * Depending on the method that used this mode the ChangedArray object may contains more information
  130. */
  131. get: function () {
  132. return ArrayChanged._replacedArrayAction;
  133. },
  134. enumerable: true,
  135. configurable: true
  136. });
  137. Object.defineProperty(ArrayChanged, "lengthChangedAction", {
  138. /**
  139. * The length of the array changed
  140. */
  141. get: function () {
  142. return ArrayChanged._lengthChangedAction;
  143. },
  144. enumerable: true,
  145. configurable: true
  146. });
  147. ArrayChanged.prototype.clear = function () {
  148. this.action = 0;
  149. this.newItems.splice(0);
  150. this.removedItems.splice(0);
  151. this.changedItems.splice(0);
  152. this.removedStartingIndex = this.removedStartingIndex = this.changedStartingIndex = 0;
  153. };
  154. ArrayChanged._clearAction = 0x1;
  155. ArrayChanged._newItemsAction = 0x2;
  156. ArrayChanged._removedItemsAction = 0x4;
  157. ArrayChanged._replacedArrayAction = 0x8;
  158. ArrayChanged._lengthChangedAction = 0x10;
  159. ArrayChanged._changedItemAction = 0x20;
  160. return ArrayChanged;
  161. }());
  162. BABYLON.ArrayChanged = ArrayChanged;
  163. var OAWatchedObjectChangedInfo = (function () {
  164. function OAWatchedObjectChangedInfo() {
  165. }
  166. return OAWatchedObjectChangedInfo;
  167. }());
  168. BABYLON.OAWatchedObjectChangedInfo = OAWatchedObjectChangedInfo;
  169. /**
  170. * This class mimics the Javascript Array and TypeScript Array<T> classes, adding new features concerning the Observable pattern.
  171. *
  172. */
  173. var ObservableArray = (function (_super) {
  174. __extends(ObservableArray, _super);
  175. /**
  176. * Create an Observable Array.
  177. * @param watchObjectsPropertyChange
  178. * @param array and optional array that will be encapsulated by this ObservableArray instance. That's right, it's NOT a copy!
  179. */
  180. function ObservableArray(watchObjectsPropertyChange, array) {
  181. _super.call(this);
  182. this.dci = new ArrayChanged();
  183. this._callingArrayChanged = false;
  184. this._array = (array != null) ? array : new Array();
  185. this.dci = new ArrayChanged();
  186. this._callingArrayChanged = false;
  187. this._arrayChanged = null;
  188. this._callingWatchedObjectChanged = false;
  189. this._watchObjectsPropertyChange = watchObjectsPropertyChange;
  190. this._watchedObjectList = this._watchObjectsPropertyChange ? new BABYLON.StringDictionary() : null;
  191. this._woci = new OAWatchedObjectChangedInfo();
  192. }
  193. Object.defineProperty(ObservableArray.prototype, "length", {
  194. /**
  195. * Gets or sets the length of the array. This is a number one higher than the highest element defined in an array.
  196. */
  197. get: function () {
  198. return this._array.length;
  199. },
  200. set: function (value) {
  201. if (value === this._array.length) {
  202. return;
  203. }
  204. var oldLength = this._array.length;
  205. this._array.length = value;
  206. this.onPropertyChanged("length", oldLength, this._array.length);
  207. },
  208. enumerable: true,
  209. configurable: true
  210. });
  211. ObservableArray.prototype.getAt = function (index) {
  212. return this._array[index];
  213. };
  214. ObservableArray.prototype.setAt = function (index, value) {
  215. if (index < 0) {
  216. return false;
  217. }
  218. var insertion = (index >= this._array.length) || this._array[index] === undefined;
  219. var oldLength = 0;
  220. if (insertion) {
  221. oldLength = this._array.length;
  222. }
  223. else if (this._watchObjectsPropertyChange) {
  224. this._removeWatchedElement(this._array[index]);
  225. }
  226. this._array[index] = value;
  227. if (this._watchObjectsPropertyChange) {
  228. this._addWatchedElement(value);
  229. }
  230. if (insertion) {
  231. this.onPropertyChanged("length", oldLength, this._array.length);
  232. }
  233. var ac = this.getArrayChangedObject();
  234. if (ac) {
  235. ac.action = insertion ? ArrayChanged.newItemsAction : ArrayChanged.changedItemAction;
  236. if (insertion) {
  237. ac.newItems.splice(0, ac.newItems.length, { index: index, value: value });
  238. ac.newStartingIndex = index;
  239. ac.changedItems.splice(0);
  240. }
  241. else {
  242. ac.newItems.splice(0);
  243. ac.changedStartingIndex = index;
  244. ac.changedItems.splice(0, ac.changedItems.length, { index: index, value: value });
  245. }
  246. ac.removedItems.splice(0);
  247. ac.removedStartingIndex = -1;
  248. this.callArrayChanged(ac);
  249. }
  250. };
  251. /**
  252. * Returns a string representation of an array.
  253. */
  254. ObservableArray.prototype.toString = function () {
  255. return this._array.toString();
  256. };
  257. ObservableArray.prototype.toLocaleString = function () {
  258. return this._array.toLocaleString();
  259. };
  260. /**
  261. * Appends new elements to an array, and returns the new length of the array.
  262. * @param items New elements of the Array.
  263. */
  264. ObservableArray.prototype.push = function () {
  265. var items = [];
  266. for (var _i = 0; _i < arguments.length; _i++) {
  267. items[_i - 0] = arguments[_i];
  268. }
  269. var oldLength = this._array.length;
  270. var n = (_a = this._array).push.apply(_a, items);
  271. if (this._watchObjectsPropertyChange) {
  272. this._addWatchedElement.apply(this, items);
  273. }
  274. this.onPropertyChanged("length", oldLength, this._array.length);
  275. var ac = this.getArrayChangedObject();
  276. if (ac) {
  277. ac.action = ArrayChanged.newItemsAction;
  278. ac.newStartingIndex = oldLength;
  279. this.feedNotifArray.apply(this, [ac.newItems, oldLength].concat(items));
  280. this.callArrayChanged(ac);
  281. }
  282. return n;
  283. var _a;
  284. };
  285. /**
  286. * Removes the last element from an array and returns it.
  287. */
  288. ObservableArray.prototype.pop = function () {
  289. var firstRemove = this._array.length - 1;
  290. var res = this._array.pop();
  291. if (res && this._watchObjectsPropertyChange) {
  292. this._removeWatchedElement(res);
  293. }
  294. if (firstRemove !== -1) {
  295. this.onPropertyChanged("length", this._array.length + 1, this._array.length);
  296. var ac = this.getArrayChangedObject();
  297. if (ac) {
  298. ac.action = ArrayChanged.removedItemsAction;
  299. ac.removedStartingIndex = firstRemove;
  300. this.feedNotifArray(ac.removedItems, firstRemove, res);
  301. }
  302. }
  303. return res;
  304. };
  305. /**
  306. * Combines two or more arrays.
  307. * @param items Additional items to add to the end of array1.
  308. */
  309. ObservableArray.prototype.concat = function () {
  310. var items = [];
  311. for (var _i = 0; _i < arguments.length; _i++) {
  312. items[_i - 0] = arguments[_i];
  313. }
  314. return new ObservableArray(this._watchObjectsPropertyChange, (_a = this._array).concat.apply(_a, items));
  315. var _a;
  316. };
  317. /**
  318. * Adds all the elements of an array separated by the specified separator string.
  319. * @param separator A string used to separate one element of an array from the next in the resulting String. If omitted, the array elements are separated with a comma.
  320. */
  321. ObservableArray.prototype.join = function (separator) {
  322. return this._array.join(separator);
  323. };
  324. /**
  325. * Reverses the elements in an Array.
  326. * The arrayChanged action is
  327. */
  328. ObservableArray.prototype.reverse = function () {
  329. var res = this._array.reverse();
  330. var ac = this.getArrayChangedObject();
  331. ac.action = ArrayChanged.replacedArrayAction;
  332. return res;
  333. };
  334. /**
  335. * Removes the first element from an array and returns it, shift all subsequents element one element before.
  336. * The ArrayChange action is replacedArrayAction, the whole array changes and must be reevaluate as such, the removed element is in removedItems.
  337. *
  338. */
  339. ObservableArray.prototype.shift = function () {
  340. var oldLength = this._array.length;
  341. var res = this._array.shift();
  342. if (this._watchedObjectChanged && res != null) {
  343. this._removeWatchedElement(res);
  344. }
  345. if (oldLength !== 0) {
  346. this.onPropertyChanged("length", oldLength, this._array.length);
  347. var ac = this.getArrayChangedObject();
  348. if (ac) {
  349. ac.action = ArrayChanged.replacedArrayAction;
  350. ac.removedItems.splice(0, ac.removedItems.length, { index: 0, value: res });
  351. ac.newItems.splice(0);
  352. ac.changedItems.splice(0);
  353. ac.removedStartingIndex = 0;
  354. this.callArrayChanged(ac);
  355. }
  356. }
  357. return res;
  358. };
  359. /**
  360. * Returns a section of an array.
  361. * @param start The beginning of the specified portion of the array.
  362. * @param end The end of the specified portion of the array.
  363. */
  364. ObservableArray.prototype.slice = function (start, end) {
  365. return new ObservableArray(this._watchObjectsPropertyChange, this._array.slice(start, end));
  366. };
  367. /**
  368. * Sorts an array.
  369. * @param compareFn The name of the function used to determine the order of the elements. If omitted, the elements are sorted in ascending, ASCII character order.
  370. * On the contrary of the Javascript Array's implementation, this method returns nothing
  371. */
  372. ObservableArray.prototype.sort = function (compareFn) {
  373. var oldLength = this._array.length;
  374. this._array.sort(compareFn);
  375. if (oldLength !== 0) {
  376. var ac = this.getArrayChangedObject();
  377. if (ac) {
  378. ac.clear();
  379. ac.action = ArrayChanged.replacedArrayAction;
  380. this.callArrayChanged(ac);
  381. }
  382. }
  383. };
  384. /**
  385. * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
  386. * @param start The zero-based location in the array from which to start removing elements.
  387. * @param deleteCount The number of elements to remove.
  388. * @param items Elements to insert into the array in place of the deleted elements.
  389. */
  390. ObservableArray.prototype.splice = function (start, deleteCount) {
  391. var items = [];
  392. for (var _i = 2; _i < arguments.length; _i++) {
  393. items[_i - 2] = arguments[_i];
  394. }
  395. var oldLength = this._array.length;
  396. if (this._watchObjectsPropertyChange) {
  397. for (var i = start; i < start + deleteCount; i++) {
  398. var val = this._array[i];
  399. if (this._watchObjectsPropertyChange && val != null) {
  400. this._removeWatchedElement(val);
  401. }
  402. }
  403. }
  404. var res = (_a = this._array).splice.apply(_a, [start, deleteCount].concat(items));
  405. if (this._watchObjectsPropertyChange) {
  406. this._addWatchedElement.apply(this, items);
  407. }
  408. if (oldLength !== this._array.length) {
  409. this.onPropertyChanged("length", oldLength, this._array.length);
  410. }
  411. var ac = this.getArrayChangedObject();
  412. if (ac) {
  413. ac.clear();
  414. ac.action = ArrayChanged.replacedArrayAction;
  415. this.callArrayChanged(ac);
  416. }
  417. return res;
  418. var _a;
  419. };
  420. /**
  421. * Inserts new elements at the start of an array.
  422. * @param items Elements to insert at the start of the Array.
  423. * The ChangedArray action is replacedArrayAction, newItems contains the list of the added items
  424. */
  425. ObservableArray.prototype.unshift = function () {
  426. var items = [];
  427. for (var _i = 0; _i < arguments.length; _i++) {
  428. items[_i - 0] = arguments[_i];
  429. }
  430. var oldLength = this._array.length;
  431. var res = (_a = this._array).unshift.apply(_a, items);
  432. if (this._watchObjectsPropertyChange) {
  433. this._addWatchedElement.apply(this, items);
  434. }
  435. this.onPropertyChanged("length", oldLength, this._array.length);
  436. var ac = this.getArrayChangedObject();
  437. if (ac) {
  438. ac.clear();
  439. ac.action = ArrayChanged.replacedArrayAction;
  440. ac.newStartingIndex = 0,
  441. this.feedNotifArray.apply(this, [ac.newItems, 0].concat(items));
  442. this.callArrayChanged(ac);
  443. }
  444. return res;
  445. var _a;
  446. };
  447. /**
  448. * Returns the index of the first occurrence of a value in an array.
  449. * @param searchElement The value to locate in the array.
  450. * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
  451. */
  452. ObservableArray.prototype.indexOf = function (searchElement, fromIndex) {
  453. return this._array.indexOf(searchElement, fromIndex);
  454. };
  455. /**
  456. * Returns the index of the last occurrence of a specified value in an array.
  457. * @param searchElement The value to locate in the array.
  458. * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at the last index in the array.
  459. */
  460. ObservableArray.prototype.lastIndexOf = function (searchElement, fromIndex) {
  461. return this._array.lastIndexOf(searchElement, fromIndex);
  462. };
  463. /**
  464. * Determines whether all the members of an array satisfy the specified test.
  465. * @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array.
  466. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
  467. */
  468. ObservableArray.prototype.every = function (callbackfn, thisArg) {
  469. return this._array.every(callbackfn, thisArg);
  470. };
  471. /**
  472. * Determines whether the specified callback function returns true for any element of an array.
  473. * @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array.
  474. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
  475. */
  476. ObservableArray.prototype.some = function (callbackfn, thisArg) {
  477. return this._array.some(callbackfn, thisArg);
  478. };
  479. /**
  480. * Performs the specified action for each element in an array.
  481. * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
  482. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
  483. */
  484. ObservableArray.prototype.forEach = function (callbackfn, thisArg) {
  485. return this._array.forEach(callbackfn, thisArg);
  486. };
  487. /**
  488. * Calls a defined callback function on each element of an array, and returns an array that contains the results.
  489. * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
  490. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
  491. */
  492. ObservableArray.prototype.map = function (callbackfn, thisArg) {
  493. return this._array.map(callbackfn, thisArg);
  494. };
  495. /**
  496. * Returns the elements of an array that meet the condition specified in a callback function.
  497. * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.
  498. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
  499. */
  500. ObservableArray.prototype.filter = function (callbackfn, thisArg) {
  501. return this._array.filter(callbackfn, thisArg);
  502. };
  503. /**
  504. * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
  505. * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
  506. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
  507. */
  508. ObservableArray.prototype.reduce = function (callbackfn, initialValue) {
  509. return this._array.reduce(callbackfn);
  510. };
  511. /**
  512. * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
  513. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
  514. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
  515. */
  516. ObservableArray.prototype.reduceRight = function (callbackfn, initialValue) {
  517. return this._array.reduceRight(callbackfn);
  518. };
  519. Object.defineProperty(ObservableArray.prototype, "arrayChanged", {
  520. get: function () {
  521. if (!this._arrayChanged) {
  522. this._arrayChanged = new BABYLON.Observable();
  523. }
  524. return this._arrayChanged;
  525. },
  526. enumerable: true,
  527. configurable: true
  528. });
  529. ObservableArray.prototype.getArrayChangedObject = function () {
  530. if (this._arrayChanged && this._arrayChanged.hasObservers()) {
  531. var ac = this._callingArrayChanged ? new ArrayChanged() : this.dci;
  532. return ac;
  533. }
  534. return null;
  535. };
  536. ObservableArray.prototype.feedNotifArray = function (array, startindIndex) {
  537. var items = [];
  538. for (var _i = 2; _i < arguments.length; _i++) {
  539. items[_i - 2] = arguments[_i];
  540. }
  541. array.splice(0);
  542. for (var i = 0; i < items.length; i++) {
  543. var value = this._array[i + startindIndex];
  544. if (value !== undefined) {
  545. array.push({ index: i + startindIndex, value: value });
  546. }
  547. }
  548. };
  549. ObservableArray.prototype.callArrayChanged = function (ac) {
  550. try {
  551. this._callingArrayChanged = true;
  552. this.arrayChanged.notifyObservers(ac, ac.action);
  553. }
  554. finally {
  555. this._callingArrayChanged = false;
  556. }
  557. };
  558. Object.defineProperty(ObservableArray.prototype, "watchedObjectChanged", {
  559. get: function () {
  560. if (!this._watchedObjectChanged) {
  561. this._watchedObjectChanged = new BABYLON.Observable();
  562. }
  563. return this._watchedObjectChanged;
  564. },
  565. enumerable: true,
  566. configurable: true
  567. });
  568. ObservableArray.prototype._addWatchedElement = function () {
  569. var _this = this;
  570. var items = [];
  571. for (var _i = 0; _i < arguments.length; _i++) {
  572. items[_i - 0] = arguments[_i];
  573. }
  574. var _loop_1 = function(curItem) {
  575. if (curItem["propertyChanged"]) {
  576. var key_1 = curItem["__ObsArrayObjID__"];
  577. // The object may already be part of another ObsArray, so there already be a valid ID
  578. if (!key_1) {
  579. key_1 = BABYLON.Tools.RandomId();
  580. curItem["__ObsArrayObjID__"] = key_1;
  581. }
  582. this_1._watchedObjectList.add(key_1, curItem.propertyChanged.add(function (e, d) {
  583. _this.onWatchedObjectChanged(key_1, curItem, e);
  584. }));
  585. }
  586. };
  587. var this_1 = this;
  588. for (var _a = 0, items_1 = items; _a < items_1.length; _a++) {
  589. var curItem = items_1[_a];
  590. _loop_1(curItem);
  591. }
  592. };
  593. ObservableArray.prototype._removeWatchedElement = function () {
  594. var items = [];
  595. for (var _i = 0; _i < arguments.length; _i++) {
  596. items[_i - 0] = arguments[_i];
  597. }
  598. for (var _a = 0, items_2 = items; _a < items_2.length; _a++) {
  599. var curItem = items_2[_a];
  600. var key = curItem["__ObsArrayObjID__"];
  601. if (key != null) {
  602. var observer = this._watchedObjectList.getAndRemove(key);
  603. curItem.propertyChanged.remove(observer);
  604. }
  605. }
  606. };
  607. ObservableArray.prototype.onWatchedObjectChanged = function (key, object, propChanged) {
  608. if (this._watchedObjectChanged && this._watchedObjectChanged.hasObservers()) {
  609. var woci = this._callingWatchedObjectChanged ? new OAWatchedObjectChangedInfo() : this._woci;
  610. woci.object = object;
  611. woci.propertyChanged = propChanged;
  612. try {
  613. this._callingWatchedObjectChanged = true;
  614. this.watchedObjectChanged.notifyObservers(woci);
  615. }
  616. finally {
  617. this._callingWatchedObjectChanged = false;
  618. }
  619. }
  620. };
  621. return ObservableArray;
  622. }(BABYLON.PropertyChangedBase));
  623. BABYLON.ObservableArray = ObservableArray;
  624. })(BABYLON || (BABYLON = {}));
  625. var BABYLON;
  626. (function (BABYLON) {
  627. /**
  628. * Class for the ObservableStringDictionary.onDictionaryChanged observable
  629. */
  630. var DictionaryChanged = (function () {
  631. function DictionaryChanged() {
  632. }
  633. Object.defineProperty(DictionaryChanged, "clearAction", {
  634. /**
  635. * The content of the dictionary was totally cleared
  636. */
  637. get: function () {
  638. return DictionaryChanged._clearAction;
  639. },
  640. enumerable: true,
  641. configurable: true
  642. });
  643. Object.defineProperty(DictionaryChanged, "newItemAction", {
  644. /**
  645. * A new item was added, the newItem field contains the key/value pair
  646. */
  647. get: function () {
  648. return DictionaryChanged._newItemAction;
  649. },
  650. enumerable: true,
  651. configurable: true
  652. });
  653. Object.defineProperty(DictionaryChanged, "removedItemAction", {
  654. /**
  655. * An existing item was removed, the removedKey field contains its key
  656. */
  657. get: function () {
  658. return DictionaryChanged._removedItemAction;
  659. },
  660. enumerable: true,
  661. configurable: true
  662. });
  663. Object.defineProperty(DictionaryChanged, "itemValueChangedAction", {
  664. /**
  665. * An existing item had a value change, the changedItem field contains the key/value
  666. */
  667. get: function () {
  668. return DictionaryChanged._itemValueChangedAction;
  669. },
  670. enumerable: true,
  671. configurable: true
  672. });
  673. Object.defineProperty(DictionaryChanged, "replacedAction", {
  674. /**
  675. * The dictionary's content was reset and replaced by the content of another dictionary.
  676. * DictionaryChanged<T> contains no further information about this action
  677. */
  678. get: function () {
  679. return DictionaryChanged._replacedAction;
  680. },
  681. enumerable: true,
  682. configurable: true
  683. });
  684. DictionaryChanged._clearAction = 0x1;
  685. DictionaryChanged._newItemAction = 0x2;
  686. DictionaryChanged._removedItemAction = 0x4;
  687. DictionaryChanged._itemValueChangedAction = 0x8;
  688. DictionaryChanged._replacedAction = 0x10;
  689. return DictionaryChanged;
  690. }());
  691. BABYLON.DictionaryChanged = DictionaryChanged;
  692. var OSDWatchedObjectChangedInfo = (function () {
  693. function OSDWatchedObjectChangedInfo() {
  694. }
  695. return OSDWatchedObjectChangedInfo;
  696. }());
  697. BABYLON.OSDWatchedObjectChangedInfo = OSDWatchedObjectChangedInfo;
  698. var ObservableStringDictionary = (function (_super) {
  699. __extends(ObservableStringDictionary, _super);
  700. function ObservableStringDictionary(watchObjectsPropertyChange) {
  701. _super.call(this);
  702. this._propertyChanged = null;
  703. this._dictionaryChanged = null;
  704. this.dci = new DictionaryChanged();
  705. this._callingDicChanged = false;
  706. this._watchedObjectChanged = null;
  707. this._callingWatchedObjectChanged = false;
  708. this._woci = new OSDWatchedObjectChangedInfo();
  709. this._watchObjectsPropertyChange = watchObjectsPropertyChange;
  710. this._watchedObjectList = this._watchObjectsPropertyChange ? new BABYLON.StringDictionary() : null;
  711. }
  712. /**
  713. * This will clear this dictionary and copy the content from the 'source' one.
  714. * If the T value is a custom object, it won't be copied/cloned, the same object will be used
  715. * @param source the dictionary to take the content from and copy to this dictionary
  716. */
  717. ObservableStringDictionary.prototype.copyFrom = function (source) {
  718. var _this = this;
  719. var oldCount = this.count;
  720. // Don't rely on this class' implementation for clear/add otherwise tons of notification will be thrown
  721. _super.prototype.clear.call(this);
  722. source.forEach(function (t, v) { return _this._add(t, v, false, _this._watchObjectsPropertyChange); });
  723. this.onDictionaryChanged(DictionaryChanged.replacedAction, null, null, null);
  724. this.onPropertyChanged("count", oldCount, this.count);
  725. };
  726. /**
  727. * Get a value from its key or add it if it doesn't exist.
  728. * This method will ensure you that a given key/data will be present in the dictionary.
  729. * @param key the given key to get the matching value from
  730. * @param factory the factory that will create the value if the key is not present in the dictionary.
  731. * The factory will only be invoked if there's no data for the given key.
  732. * @return the value corresponding to the key.
  733. */
  734. ObservableStringDictionary.prototype.getOrAddWithFactory = function (key, factory) {
  735. var _this = this;
  736. var val = _super.prototype.getOrAddWithFactory.call(this, key, function (k) {
  737. var v = factory(key);
  738. _this._add(key, v, true, _this._watchObjectsPropertyChange);
  739. return v;
  740. });
  741. return val;
  742. };
  743. /**
  744. * Add a new key and its corresponding value
  745. * @param key the key to add
  746. * @param value the value corresponding to the key
  747. * @return true if the operation completed successfully, false if we couldn't insert the key/value because there was already this key in the dictionary
  748. */
  749. ObservableStringDictionary.prototype.add = function (key, value) {
  750. return this._add(key, value, true, true);
  751. };
  752. ObservableStringDictionary.prototype.getAndRemove = function (key) {
  753. var val = _super.prototype.get.call(this, key);
  754. this._remove(key, true, val);
  755. return val;
  756. };
  757. ObservableStringDictionary.prototype._add = function (key, value, fireNotif, registerWatcher) {
  758. if (_super.prototype.add.call(this, key, value)) {
  759. if (fireNotif) {
  760. this.onDictionaryChanged(DictionaryChanged.newItemAction, { key: key, value: value }, null, null);
  761. this.onPropertyChanged("count", this.count - 1, this.count);
  762. }
  763. if (registerWatcher) {
  764. this._addWatchedElement(key, value);
  765. }
  766. return true;
  767. }
  768. return false;
  769. };
  770. ObservableStringDictionary.prototype._addWatchedElement = function (key, el) {
  771. var _this = this;
  772. if (el["propertyChanged"]) {
  773. this._watchedObjectList.add(key, el.propertyChanged.add(function (e, d) {
  774. _this.onWatchedObjectChanged(key, el, e);
  775. }));
  776. }
  777. };
  778. ObservableStringDictionary.prototype._removeWatchedElement = function (key, el) {
  779. var observer = this._watchedObjectList.getAndRemove(key);
  780. el.propertyChanged.remove(observer);
  781. };
  782. ObservableStringDictionary.prototype.set = function (key, value) {
  783. var oldValue = this.get(key);
  784. if (this._watchObjectsPropertyChange) {
  785. this._removeWatchedElement(key, oldValue);
  786. }
  787. if (_super.prototype.set.call(this, key, value)) {
  788. this.onDictionaryChanged(DictionaryChanged.itemValueChangedAction, null, null, { key: key, oldValue: oldValue, newValue: value });
  789. this._addWatchedElement(key, value);
  790. return true;
  791. }
  792. return false;
  793. };
  794. /**
  795. * Remove a key/value from the dictionary.
  796. * @param key the key to remove
  797. * @return true if the item was successfully deleted, false if no item with such key exist in the dictionary
  798. */
  799. ObservableStringDictionary.prototype.remove = function (key) {
  800. return this._remove(key, true);
  801. };
  802. ObservableStringDictionary.prototype._remove = function (key, fireNotif, element) {
  803. if (!element) {
  804. element = this.get(key);
  805. }
  806. if (!element) {
  807. return false;
  808. }
  809. if (_super.prototype.remove.call(this, key) === undefined) {
  810. return false;
  811. }
  812. this.onDictionaryChanged(DictionaryChanged.removedItemAction, null, key, null);
  813. this.onPropertyChanged("count", this.count + 1, this.count);
  814. if (this._watchObjectsPropertyChange) {
  815. this._removeWatchedElement(key, element);
  816. }
  817. return true;
  818. };
  819. /**
  820. * Clear the whole content of the dictionary
  821. */
  822. ObservableStringDictionary.prototype.clear = function () {
  823. var _this = this;
  824. this._watchedObjectList.forEach(function (k, v) {
  825. var el = _this.get(k);
  826. _this._removeWatchedElement(k, el);
  827. });
  828. this._watchedObjectList.clear();
  829. var oldCount = this.count;
  830. _super.prototype.clear.call(this);
  831. this.onDictionaryChanged(DictionaryChanged.clearAction, null, null, null);
  832. this.onPropertyChanged("count", oldCount, 0);
  833. };
  834. Object.defineProperty(ObservableStringDictionary.prototype, "propertyChanged", {
  835. get: function () {
  836. if (!this._propertyChanged) {
  837. this._propertyChanged = new BABYLON.Observable();
  838. }
  839. return this._propertyChanged;
  840. },
  841. enumerable: true,
  842. configurable: true
  843. });
  844. ObservableStringDictionary.prototype.onPropertyChanged = function (propName, oldValue, newValue, mask) {
  845. if (this._propertyChanged && this._propertyChanged.hasObservers()) {
  846. var pci = ObservableStringDictionary.callingPropChanged ? new BABYLON.PropertyChangedInfo() : ObservableStringDictionary.pci;
  847. pci.oldValue = oldValue;
  848. pci.newValue = newValue;
  849. pci.propertyName = propName;
  850. try {
  851. ObservableStringDictionary.callingPropChanged = true;
  852. this.propertyChanged.notifyObservers(pci, mask);
  853. }
  854. finally {
  855. ObservableStringDictionary.callingPropChanged = false;
  856. }
  857. }
  858. };
  859. Object.defineProperty(ObservableStringDictionary.prototype, "dictionaryChanged", {
  860. get: function () {
  861. if (!this._dictionaryChanged) {
  862. this._dictionaryChanged = new BABYLON.Observable();
  863. }
  864. return this._dictionaryChanged;
  865. },
  866. enumerable: true,
  867. configurable: true
  868. });
  869. ObservableStringDictionary.prototype.onDictionaryChanged = function (action, newItem, removedKey, changedItem) {
  870. if (this._dictionaryChanged && this._dictionaryChanged.hasObservers()) {
  871. var dci = this._callingDicChanged ? new DictionaryChanged() : this.dci;
  872. dci.action = action;
  873. dci.newItem = newItem;
  874. dci.removedKey = removedKey;
  875. dci.changedItem = changedItem;
  876. try {
  877. this._callingDicChanged = true;
  878. this.dictionaryChanged.notifyObservers(dci, action);
  879. }
  880. finally {
  881. this._callingDicChanged = false;
  882. }
  883. }
  884. };
  885. Object.defineProperty(ObservableStringDictionary.prototype, "watchedObjectChanged", {
  886. get: function () {
  887. if (!this._watchedObjectChanged) {
  888. this._watchedObjectChanged = new BABYLON.Observable();
  889. }
  890. return this._watchedObjectChanged;
  891. },
  892. enumerable: true,
  893. configurable: true
  894. });
  895. ObservableStringDictionary.prototype.onWatchedObjectChanged = function (key, object, propChanged) {
  896. if (this._watchedObjectChanged && this._watchedObjectChanged.hasObservers()) {
  897. var woci = this._callingWatchedObjectChanged ? new OSDWatchedObjectChangedInfo() : this._woci;
  898. woci.key = key;
  899. woci.object = object;
  900. woci.propertyChanged = propChanged;
  901. try {
  902. this._callingWatchedObjectChanged = true;
  903. this.watchedObjectChanged.notifyObservers(woci);
  904. }
  905. finally {
  906. this._callingWatchedObjectChanged = false;
  907. }
  908. }
  909. };
  910. ObservableStringDictionary.pci = new BABYLON.PropertyChangedInfo();
  911. ObservableStringDictionary.callingPropChanged = false;
  912. return ObservableStringDictionary;
  913. }(BABYLON.StringDictionary));
  914. BABYLON.ObservableStringDictionary = ObservableStringDictionary;
  915. })(BABYLON || (BABYLON = {}));
  916. var BABYLON;
  917. (function (BABYLON) {
  918. /**
  919. * Stores 2D Bounding Information.
  920. * This class handles a circle area and a bounding rectangle one.
  921. */
  922. var BoundingInfo2D = (function () {
  923. function BoundingInfo2D() {
  924. this.radius = 0;
  925. this.center = BABYLON.Vector2.Zero();
  926. this.extent = BABYLON.Vector2.Zero();
  927. }
  928. /**
  929. * Create a BoundingInfo2D object from a given size
  930. * @param size the size that will be used to set the extend, radius will be computed from it.
  931. */
  932. BoundingInfo2D.CreateFromSize = function (size) {
  933. var r = new BoundingInfo2D();
  934. BoundingInfo2D.CreateFromSizeToRef(size, r);
  935. return r;
  936. };
  937. /**
  938. * Create a BoundingInfo2D object from a given radius
  939. * @param radius the radius to use, the extent will be computed from it.
  940. */
  941. BoundingInfo2D.CreateFromRadius = function (radius) {
  942. var r = new BoundingInfo2D();
  943. BoundingInfo2D.CreateFromRadiusToRef(radius, r);
  944. return r;
  945. };
  946. /**
  947. * Create a BoundingInfo2D object from a list of points.
  948. * The resulted object will be the smallest bounding area that includes all the given points.
  949. * @param points an array of points to compute the bounding object from.
  950. */
  951. BoundingInfo2D.CreateFromPoints = function (points) {
  952. var r = new BoundingInfo2D();
  953. BoundingInfo2D.CreateFromPointsToRef(points, r);
  954. return r;
  955. };
  956. /**
  957. * Update a BoundingInfo2D object using the given Size as input
  958. * @param size the bounding data will be computed from this size.
  959. * @param b must be a valid/allocated object, it will contain the result of the operation
  960. */
  961. BoundingInfo2D.CreateFromSizeToRef = function (size, b) {
  962. if (!size) {
  963. size = BABYLON.Size.Zero();
  964. }
  965. b.center.x = +size.width / 2;
  966. b.center.y = +size.height / 2;
  967. b.extent.x = b.center.x;
  968. b.extent.y = b.center.y;
  969. b.radius = b.extent.length();
  970. };
  971. /**
  972. * Update a BoundingInfo2D object using the given radius as input
  973. * @param radius the bounding data will be computed from this radius
  974. * @param b must be a valid/allocated object, it will contain the result of the operation
  975. */
  976. BoundingInfo2D.CreateFromRadiusToRef = function (radius, b) {
  977. b.center.x = b.center.y = 0;
  978. var r = +radius;
  979. b.extent.x = r;
  980. b.extent.y = r;
  981. b.radius = r;
  982. };
  983. /**
  984. * Update a BoundingInfo2D object using the given points array as input
  985. * @param points the point array to use to update the bounding data
  986. * @param b must be a valid/allocated object, it will contain the result of the operation
  987. */
  988. BoundingInfo2D.CreateFromPointsToRef = function (points, b) {
  989. var xmin = Number.MAX_VALUE, ymin = Number.MAX_VALUE, xmax = Number.MIN_VALUE, ymax = Number.MIN_VALUE;
  990. for (var _i = 0, points_1 = points; _i < points_1.length; _i++) {
  991. var p = points_1[_i];
  992. xmin = Math.min(p.x, xmin);
  993. xmax = Math.max(p.x, xmax);
  994. ymin = Math.min(p.y, ymin);
  995. ymax = Math.max(p.y, ymax);
  996. }
  997. BoundingInfo2D.CreateFromMinMaxToRef(xmin, xmax, ymin, ymax, b);
  998. };
  999. /**
  1000. * Update a BoundingInfo2D object using the given min/max values as input
  1001. * @param xmin the smallest x coordinate
  1002. * @param xmax the biggest x coordinate
  1003. * @param ymin the smallest y coordinate
  1004. * @param ymax the buggest y coordinate
  1005. * @param b must be a valid/allocated object, it will contain the result of the operation
  1006. */
  1007. BoundingInfo2D.CreateFromMinMaxToRef = function (xmin, xmax, ymin, ymax, b) {
  1008. var w = xmax - xmin;
  1009. var h = ymax - ymin;
  1010. b.center = new BABYLON.Vector2(xmin + w / 2, ymin + h / 2);
  1011. b.extent = new BABYLON.Vector2(xmax - b.center.x, ymax - b.center.y);
  1012. b.radius = b.extent.length();
  1013. };
  1014. /**
  1015. * Duplicate this instance and return a new one
  1016. * @return the duplicated instance
  1017. */
  1018. BoundingInfo2D.prototype.clone = function () {
  1019. var r = new BoundingInfo2D();
  1020. r.center = this.center.clone();
  1021. r.radius = this.radius;
  1022. r.extent = this.extent.clone();
  1023. return r;
  1024. };
  1025. BoundingInfo2D.prototype.clear = function () {
  1026. this.center.copyFromFloats(0, 0);
  1027. this.radius = 0;
  1028. this.extent.copyFromFloats(0, 0);
  1029. };
  1030. BoundingInfo2D.prototype.copyFrom = function (src) {
  1031. this.center.copyFrom(src.center);
  1032. this.radius = src.radius;
  1033. this.extent.copyFrom(src.extent);
  1034. };
  1035. /**
  1036. * return the max extend of the bounding info
  1037. */
  1038. BoundingInfo2D.prototype.max = function () {
  1039. var r = BABYLON.Vector2.Zero();
  1040. this.maxToRef(r);
  1041. return r;
  1042. };
  1043. /**
  1044. * Update a vector2 with the max extend of the bounding info
  1045. * @param result must be a valid/allocated vector2 that will contain the result of the operation
  1046. */
  1047. BoundingInfo2D.prototype.maxToRef = function (result) {
  1048. result.x = this.center.x + this.extent.x;
  1049. result.y = this.center.y + this.extent.y;
  1050. };
  1051. /**
  1052. * Apply a transformation matrix to this BoundingInfo2D and return a new instance containing the result
  1053. * @param matrix the transformation matrix to apply
  1054. * @return the new instance containing the result of the transformation applied on this BoundingInfo2D
  1055. */
  1056. BoundingInfo2D.prototype.transform = function (matrix) {
  1057. var r = new BoundingInfo2D();
  1058. this.transformToRef(matrix, r);
  1059. return r;
  1060. };
  1061. /**
  1062. * Compute the union of this BoundingInfo2D with a given one, returns a new BoundingInfo2D as a result
  1063. * @param other the second BoundingInfo2D to compute the union with this one
  1064. * @return a new instance containing the result of the union
  1065. */
  1066. BoundingInfo2D.prototype.union = function (other) {
  1067. var r = new BoundingInfo2D();
  1068. this.unionToRef(other, r);
  1069. return r;
  1070. };
  1071. /**
  1072. * Transform this BoundingInfo2D with a given matrix and store the result in an existing BoundingInfo2D instance.
  1073. * This is a GC friendly version, try to use it as much as possible, specially if your transformation is inside a loop, allocate the result object once for good outside of the loop and use it every time.
  1074. * @param matrix The matrix to use to compute the transformation
  1075. * @param result A VALID (i.e. allocated) BoundingInfo2D object where the result will be stored
  1076. */
  1077. BoundingInfo2D.prototype.transformToRef = function (matrix, result) {
  1078. // Construct a bounding box based on the extent values
  1079. var p = BoundingInfo2D._transform;
  1080. p[0].x = this.center.x + this.extent.x;
  1081. p[0].y = this.center.y + this.extent.y;
  1082. p[1].x = this.center.x + this.extent.x;
  1083. p[1].y = this.center.y - this.extent.y;
  1084. p[2].x = this.center.x - this.extent.x;
  1085. p[2].y = this.center.y - this.extent.y;
  1086. p[3].x = this.center.x - this.extent.x;
  1087. p[3].y = this.center.y + this.extent.y;
  1088. // Transform the four points of the bounding box with the matrix
  1089. for (var i = 0; i < 4; i++) {
  1090. BABYLON.Vector2.TransformToRef(p[i], matrix, p[i]);
  1091. }
  1092. BoundingInfo2D.CreateFromPointsToRef(p, result);
  1093. };
  1094. /**
  1095. * Compute the union of this BoundingInfo2D with another one and store the result in a third valid BoundingInfo2D object
  1096. * This is a GC friendly version, try to use it as much as possible, specially if your transformation is inside a loop, allocate the result object once for good outside of the loop and use it every time.
  1097. * @param other the second object used to compute the union
  1098. * @param result a VALID BoundingInfo2D instance (i.e. allocated) where the result will be stored
  1099. */
  1100. BoundingInfo2D.prototype.unionToRef = function (other, result) {
  1101. var xmax = Math.max(this.center.x + this.extent.x, other.center.x + other.extent.x);
  1102. var ymax = Math.max(this.center.y + this.extent.y, other.center.y + other.extent.y);
  1103. var xmin = Math.min(this.center.x - this.extent.x, other.center.x - other.extent.x);
  1104. var ymin = Math.min(this.center.y - this.extent.y, other.center.y - other.extent.y);
  1105. BoundingInfo2D.CreateFromMinMaxToRef(xmin, xmax, ymin, ymax, result);
  1106. };
  1107. /**
  1108. * Check if the given point is inside the BoundingInfo.
  1109. * The test is first made on the radius, then inside the rectangle described by the extent
  1110. * @param pickPosition the position to test
  1111. * @return true if the point is inside, false otherwise
  1112. */
  1113. BoundingInfo2D.prototype.doesIntersect = function (pickPosition) {
  1114. // is it inside the radius?
  1115. var pickLocal = pickPosition.subtract(this.center);
  1116. if (pickLocal.lengthSquared() <= (this.radius * this.radius)) {
  1117. // is it inside the rectangle?
  1118. return ((Math.abs(pickLocal.x) <= this.extent.x) && (Math.abs(pickLocal.y) <= this.extent.y));
  1119. }
  1120. return false;
  1121. };
  1122. BoundingInfo2D._transform = new Array(BABYLON.Vector2.Zero(), BABYLON.Vector2.Zero(), BABYLON.Vector2.Zero(), BABYLON.Vector2.Zero());
  1123. return BoundingInfo2D;
  1124. }());
  1125. BABYLON.BoundingInfo2D = BoundingInfo2D;
  1126. })(BABYLON || (BABYLON = {}));
  1127. var BABYLON;
  1128. (function (BABYLON) {
  1129. var LayoutEngineBase = (function () {
  1130. function LayoutEngineBase() {
  1131. this.layoutDirtyOnPropertyChangedMask = 0;
  1132. }
  1133. LayoutEngineBase.prototype.updateLayout = function (prim) {
  1134. };
  1135. Object.defineProperty(LayoutEngineBase.prototype, "isChildPositionAllowed", {
  1136. get: function () {
  1137. return false;
  1138. },
  1139. enumerable: true,
  1140. configurable: true
  1141. });
  1142. LayoutEngineBase.prototype.isLocked = function () {
  1143. return this._isLocked;
  1144. };
  1145. LayoutEngineBase.prototype.lock = function () {
  1146. if (this._isLocked) {
  1147. return false;
  1148. }
  1149. this._isLocked = true;
  1150. return true;
  1151. };
  1152. LayoutEngineBase = __decorate([
  1153. BABYLON.className("LayoutEngineBase", "BABYLON")
  1154. ], LayoutEngineBase);
  1155. return LayoutEngineBase;
  1156. }());
  1157. BABYLON.LayoutEngineBase = LayoutEngineBase;
  1158. var CanvasLayoutEngine = (function (_super) {
  1159. __extends(CanvasLayoutEngine, _super);
  1160. function CanvasLayoutEngine() {
  1161. _super.apply(this, arguments);
  1162. }
  1163. // A very simple (no) layout computing...
  1164. // The Canvas and its direct children gets the Canvas' size as Layout Area
  1165. // Indirect children have their Layout Area to the actualSize (margin area) of their parent
  1166. CanvasLayoutEngine.prototype.updateLayout = function (prim) {
  1167. // If this prim is layoutDiry we update its layoutArea and also the one of its direct children
  1168. if (prim._isFlagSet(BABYLON.SmartPropertyPrim.flagLayoutDirty)) {
  1169. for (var _i = 0, _a = prim.children; _i < _a.length; _i++) {
  1170. var child = _a[_i];
  1171. this._doUpdate(child);
  1172. }
  1173. prim._clearFlags(BABYLON.SmartPropertyPrim.flagLayoutDirty);
  1174. }
  1175. };
  1176. CanvasLayoutEngine.prototype._doUpdate = function (prim) {
  1177. // Canvas ?
  1178. if (prim instanceof BABYLON.Canvas2D) {
  1179. prim.layoutArea = prim.actualSize;
  1180. }
  1181. else if (prim.parent instanceof BABYLON.Canvas2D) {
  1182. prim.layoutArea = prim.owner.actualSize;
  1183. }
  1184. else {
  1185. prim.layoutArea = prim.parent.contentArea;
  1186. }
  1187. };
  1188. Object.defineProperty(CanvasLayoutEngine.prototype, "isChildPositionAllowed", {
  1189. get: function () {
  1190. return true;
  1191. },
  1192. enumerable: true,
  1193. configurable: true
  1194. });
  1195. CanvasLayoutEngine.Singleton = new CanvasLayoutEngine();
  1196. CanvasLayoutEngine = __decorate([
  1197. BABYLON.className("CanvasLayoutEngine", "BABYLON")
  1198. ], CanvasLayoutEngine);
  1199. return CanvasLayoutEngine;
  1200. }(LayoutEngineBase));
  1201. BABYLON.CanvasLayoutEngine = CanvasLayoutEngine;
  1202. var StackPanelLayoutEngine = (function (_super) {
  1203. __extends(StackPanelLayoutEngine, _super);
  1204. function StackPanelLayoutEngine() {
  1205. _super.call(this);
  1206. this._isHorizontal = true;
  1207. this.layoutDirtyOnPropertyChangedMask = BABYLON.Prim2DBase.sizeProperty.flagId;
  1208. }
  1209. Object.defineProperty(StackPanelLayoutEngine, "Horizontal", {
  1210. get: function () {
  1211. if (!StackPanelLayoutEngine._horizontal) {
  1212. StackPanelLayoutEngine._horizontal = new StackPanelLayoutEngine();
  1213. StackPanelLayoutEngine._horizontal.isHorizontal = true;
  1214. StackPanelLayoutEngine._horizontal.lock();
  1215. }
  1216. return StackPanelLayoutEngine._horizontal;
  1217. },
  1218. enumerable: true,
  1219. configurable: true
  1220. });
  1221. Object.defineProperty(StackPanelLayoutEngine, "Vertical", {
  1222. get: function () {
  1223. if (!StackPanelLayoutEngine._vertical) {
  1224. StackPanelLayoutEngine._vertical = new StackPanelLayoutEngine();
  1225. StackPanelLayoutEngine._vertical.isHorizontal = false;
  1226. StackPanelLayoutEngine._vertical.lock();
  1227. }
  1228. return StackPanelLayoutEngine._vertical;
  1229. },
  1230. enumerable: true,
  1231. configurable: true
  1232. });
  1233. Object.defineProperty(StackPanelLayoutEngine.prototype, "isHorizontal", {
  1234. get: function () {
  1235. return this._isHorizontal;
  1236. },
  1237. set: function (val) {
  1238. if (this.isLocked()) {
  1239. return;
  1240. }
  1241. this._isHorizontal = val;
  1242. },
  1243. enumerable: true,
  1244. configurable: true
  1245. });
  1246. StackPanelLayoutEngine.prototype.updateLayout = function (prim) {
  1247. if (prim._isFlagSet(BABYLON.SmartPropertyPrim.flagLayoutDirty)) {
  1248. var x = 0;
  1249. var y = 0;
  1250. var h = this.isHorizontal;
  1251. var max = 0;
  1252. for (var _i = 0, _a = prim.children; _i < _a.length; _i++) {
  1253. var child = _a[_i];
  1254. if (child._isFlagSet(BABYLON.SmartPropertyPrim.flagNoPartOfLayout)) {
  1255. continue;
  1256. }
  1257. var layoutArea = void 0;
  1258. if (child._hasMargin) {
  1259. child.margin.computeWithAlignment(prim.layoutArea, child.actualSize, child.marginAlignment, StackPanelLayoutEngine.dstOffset, StackPanelLayoutEngine.dstArea, true);
  1260. layoutArea = StackPanelLayoutEngine.dstArea.clone();
  1261. child.layoutArea = layoutArea;
  1262. }
  1263. else {
  1264. layoutArea = child.layoutArea;
  1265. child.margin.computeArea(child.actualSize, layoutArea);
  1266. }
  1267. max = Math.max(max, h ? layoutArea.height : layoutArea.width);
  1268. }
  1269. for (var _b = 0, _c = prim.children; _b < _c.length; _b++) {
  1270. var child = _c[_b];
  1271. if (child._isFlagSet(BABYLON.SmartPropertyPrim.flagNoPartOfLayout)) {
  1272. continue;
  1273. }
  1274. child.layoutAreaPos = new BABYLON.Vector2(x, y);
  1275. var layoutArea = child.layoutArea;
  1276. if (h) {
  1277. x += layoutArea.width;
  1278. child.layoutArea = new BABYLON.Size(layoutArea.width, max);
  1279. }
  1280. else {
  1281. y += layoutArea.height;
  1282. child.layoutArea = new BABYLON.Size(max, layoutArea.height);
  1283. }
  1284. }
  1285. prim._clearFlags(BABYLON.SmartPropertyPrim.flagLayoutDirty);
  1286. }
  1287. };
  1288. Object.defineProperty(StackPanelLayoutEngine.prototype, "isChildPositionAllowed", {
  1289. get: function () {
  1290. return false;
  1291. },
  1292. enumerable: true,
  1293. configurable: true
  1294. });
  1295. StackPanelLayoutEngine._horizontal = null;
  1296. StackPanelLayoutEngine._vertical = null;
  1297. StackPanelLayoutEngine.dstOffset = BABYLON.Vector4.Zero();
  1298. StackPanelLayoutEngine.dstArea = BABYLON.Size.Zero();
  1299. StackPanelLayoutEngine = __decorate([
  1300. BABYLON.className("StackPanelLayoutEngine", "BABYLON")
  1301. ], StackPanelLayoutEngine);
  1302. return StackPanelLayoutEngine;
  1303. }(LayoutEngineBase));
  1304. BABYLON.StackPanelLayoutEngine = StackPanelLayoutEngine;
  1305. })(BABYLON || (BABYLON = {}));
  1306. var BABYLON;
  1307. (function (BABYLON) {
  1308. /**
  1309. * Base class implementing the ILocable interface.
  1310. * The particularity of this class is to call the protected onLock() method when the instance is about to be locked for good.
  1311. */
  1312. var LockableBase = (function () {
  1313. function LockableBase() {
  1314. }
  1315. LockableBase.prototype.isLocked = function () {
  1316. return this._isLocked;
  1317. };
  1318. LockableBase.prototype.lock = function () {
  1319. if (this._isLocked) {
  1320. return true;
  1321. }
  1322. this.onLock();
  1323. this._isLocked = true;
  1324. return false;
  1325. };
  1326. /**
  1327. * Protected handler that will be called when the instance is about to be locked.
  1328. */
  1329. LockableBase.prototype.onLock = function () {
  1330. };
  1331. return LockableBase;
  1332. }());
  1333. BABYLON.LockableBase = LockableBase;
  1334. var SolidColorBrush2D = (function (_super) {
  1335. __extends(SolidColorBrush2D, _super);
  1336. function SolidColorBrush2D(color, lock) {
  1337. if (lock === void 0) { lock = false; }
  1338. _super.call(this);
  1339. this._color = color;
  1340. if (lock) {
  1341. {
  1342. this.lock();
  1343. }
  1344. }
  1345. }
  1346. /**
  1347. * Return true if the brush is transparent, false if it's totally opaque
  1348. */
  1349. SolidColorBrush2D.prototype.isTransparent = function () {
  1350. return this._color && this._color.a < 1.0;
  1351. };
  1352. Object.defineProperty(SolidColorBrush2D.prototype, "color", {
  1353. /**
  1354. * The color used by this instance to render
  1355. * @returns the color object. Note that it's not a clone of the actual object stored in the instance so you MUST NOT modify it, otherwise unexpected behavior might occurs.
  1356. */
  1357. get: function () {
  1358. return this._color;
  1359. },
  1360. set: function (value) {
  1361. if (this.isLocked()) {
  1362. return;
  1363. }
  1364. this._color = value;
  1365. },
  1366. enumerable: true,
  1367. configurable: true
  1368. });
  1369. /**
  1370. * Return a unique identifier of the instance, which is simply the hexadecimal representation (CSS Style) of the solid color.
  1371. */
  1372. SolidColorBrush2D.prototype.toString = function () {
  1373. return this._color.toHexString();
  1374. };
  1375. SolidColorBrush2D = __decorate([
  1376. BABYLON.className("SolidColorBrush2D", "BABYLON")
  1377. ], SolidColorBrush2D);
  1378. return SolidColorBrush2D;
  1379. }(LockableBase));
  1380. BABYLON.SolidColorBrush2D = SolidColorBrush2D;
  1381. var GradientColorBrush2D = (function (_super) {
  1382. __extends(GradientColorBrush2D, _super);
  1383. function GradientColorBrush2D(color1, color2, translation, rotation, scale, lock) {
  1384. if (translation === void 0) { translation = BABYLON.Vector2.Zero(); }
  1385. if (rotation === void 0) { rotation = 0; }
  1386. if (scale === void 0) { scale = 1; }
  1387. if (lock === void 0) { lock = false; }
  1388. _super.call(this);
  1389. this._color1 = color1;
  1390. this._color2 = color2;
  1391. this._translation = translation;
  1392. this._rotation = rotation;
  1393. this._scale = scale;
  1394. if (lock) {
  1395. this.lock();
  1396. }
  1397. }
  1398. /**
  1399. * Return true if the brush is transparent, false if it's totally opaque
  1400. */
  1401. GradientColorBrush2D.prototype.isTransparent = function () {
  1402. return (this._color1 && this._color1.a < 1.0) || (this._color2 && this._color2.a < 1.0);
  1403. };
  1404. Object.defineProperty(GradientColorBrush2D.prototype, "color1", {
  1405. /**
  1406. * First color, the blend will start from this color
  1407. */
  1408. get: function () {
  1409. return this._color1;
  1410. },
  1411. set: function (value) {
  1412. if (this.isLocked()) {
  1413. return;
  1414. }
  1415. this._color1 = value;
  1416. },
  1417. enumerable: true,
  1418. configurable: true
  1419. });
  1420. Object.defineProperty(GradientColorBrush2D.prototype, "color2", {
  1421. /**
  1422. * Second color, the blend will end to this color
  1423. */
  1424. get: function () {
  1425. return this._color2;
  1426. },
  1427. set: function (value) {
  1428. if (this.isLocked()) {
  1429. return;
  1430. }
  1431. this._color2 = value;
  1432. },
  1433. enumerable: true,
  1434. configurable: true
  1435. });
  1436. Object.defineProperty(GradientColorBrush2D.prototype, "translation", {
  1437. /**
  1438. * Translation vector to apply on the blend
  1439. * Default is [0;0]
  1440. */
  1441. get: function () {
  1442. return this._translation;
  1443. },
  1444. set: function (value) {
  1445. if (this.isLocked()) {
  1446. return;
  1447. }
  1448. this._translation = value;
  1449. },
  1450. enumerable: true,
  1451. configurable: true
  1452. });
  1453. Object.defineProperty(GradientColorBrush2D.prototype, "rotation", {
  1454. /**
  1455. * Rotation in radian to apply to the brush
  1456. * Default direction of the brush is vertical, you can change this using this property.
  1457. * Default is 0.
  1458. */
  1459. get: function () {
  1460. return this._rotation;
  1461. },
  1462. set: function (value) {
  1463. if (this.isLocked()) {
  1464. return;
  1465. }
  1466. this._rotation = value;
  1467. },
  1468. enumerable: true,
  1469. configurable: true
  1470. });
  1471. Object.defineProperty(GradientColorBrush2D.prototype, "scale", {
  1472. /**
  1473. * Scale factor to apply to the gradient.
  1474. * Default is 1: no scale.
  1475. */
  1476. get: function () {
  1477. return this._scale;
  1478. },
  1479. set: function (value) {
  1480. if (this.isLocked()) {
  1481. return;
  1482. }
  1483. this._scale = value;
  1484. },
  1485. enumerable: true,
  1486. configurable: true
  1487. });
  1488. /**
  1489. * Return a string describing the brush
  1490. */
  1491. GradientColorBrush2D.prototype.toString = function () {
  1492. return "C1:" + this._color1 + ";C2:" + this._color2 + ";T:" + this._translation.toString() + ";R:" + this._rotation + ";S:" + this._scale + ";";
  1493. };
  1494. /**
  1495. * Build a unique key string for the given parameters
  1496. */
  1497. GradientColorBrush2D.BuildKey = function (color1, color2, translation, rotation, scale) {
  1498. return "C1:" + color1 + ";C2:" + color2 + ";T:" + translation.toString() + ";R:" + rotation + ";S:" + scale + ";";
  1499. };
  1500. GradientColorBrush2D = __decorate([
  1501. BABYLON.className("GradientColorBrush2D", "BABYLON")
  1502. ], GradientColorBrush2D);
  1503. return GradientColorBrush2D;
  1504. }(LockableBase));
  1505. BABYLON.GradientColorBrush2D = GradientColorBrush2D;
  1506. })(BABYLON || (BABYLON = {}));
  1507. var BABYLON;
  1508. (function (BABYLON) {
  1509. var Prim2DClassInfo = (function () {
  1510. function Prim2DClassInfo() {
  1511. }
  1512. return Prim2DClassInfo;
  1513. }());
  1514. BABYLON.Prim2DClassInfo = Prim2DClassInfo;
  1515. var Prim2DPropInfo = (function () {
  1516. function Prim2DPropInfo() {
  1517. }
  1518. Prim2DPropInfo.PROPKIND_MODEL = 1;
  1519. Prim2DPropInfo.PROPKIND_INSTANCE = 2;
  1520. Prim2DPropInfo.PROPKIND_DYNAMIC = 3;
  1521. return Prim2DPropInfo;
  1522. }());
  1523. BABYLON.Prim2DPropInfo = Prim2DPropInfo;
  1524. var ClassTreeInfo = (function () {
  1525. function ClassTreeInfo(baseClass, type, classContentFactory) {
  1526. this._baseClass = baseClass;
  1527. this._type = type;
  1528. this._subClasses = new Array();
  1529. this._levelContent = new BABYLON.StringDictionary();
  1530. this._classContentFactory = classContentFactory;
  1531. }
  1532. Object.defineProperty(ClassTreeInfo.prototype, "classContent", {
  1533. get: function () {
  1534. if (!this._classContent) {
  1535. this._classContent = this._classContentFactory(this._baseClass ? this._baseClass.classContent : null);
  1536. }
  1537. return this._classContent;
  1538. },
  1539. enumerable: true,
  1540. configurable: true
  1541. });
  1542. Object.defineProperty(ClassTreeInfo.prototype, "type", {
  1543. get: function () {
  1544. return this._type;
  1545. },
  1546. enumerable: true,
  1547. configurable: true
  1548. });
  1549. Object.defineProperty(ClassTreeInfo.prototype, "levelContent", {
  1550. get: function () {
  1551. return this._levelContent;
  1552. },
  1553. enumerable: true,
  1554. configurable: true
  1555. });
  1556. Object.defineProperty(ClassTreeInfo.prototype, "fullContent", {
  1557. get: function () {
  1558. if (!this._fullContent) {
  1559. var dic_1 = new BABYLON.StringDictionary();
  1560. var curLevel = this;
  1561. while (curLevel) {
  1562. curLevel.levelContent.forEach(function (k, v) { return dic_1.add(k, v); });
  1563. curLevel = curLevel._baseClass;
  1564. }
  1565. this._fullContent = dic_1;
  1566. }
  1567. return this._fullContent;
  1568. },
  1569. enumerable: true,
  1570. configurable: true
  1571. });
  1572. ClassTreeInfo.prototype.getLevelOf = function (type) {
  1573. // Are we already there?
  1574. if (type === this._type) {
  1575. return this;
  1576. }
  1577. var baseProto = Object.getPrototypeOf(type);
  1578. var curProtoContent = this.getOrAddType(Object.getPrototypeOf(baseProto), baseProto);
  1579. if (!curProtoContent) {
  1580. this.getLevelOf(baseProto);
  1581. }
  1582. return this.getOrAddType(baseProto, type);
  1583. };
  1584. ClassTreeInfo.prototype.getOrAddType = function (baseType, type) {
  1585. // Are we at the level corresponding to the baseType?
  1586. // If so, get or add the level we're looking for
  1587. if (baseType === this._type) {
  1588. for (var _i = 0, _a = this._subClasses; _i < _a.length; _i++) {
  1589. var subType = _a[_i];
  1590. if (subType.type === type) {
  1591. return subType.node;
  1592. }
  1593. }
  1594. var node = new ClassTreeInfo(this, type, this._classContentFactory);
  1595. var info = { type: type, node: node };
  1596. this._subClasses.push(info);
  1597. return info.node;
  1598. }
  1599. // Recurse down to keep looking for the node corresponding to the baseTypeName
  1600. for (var _b = 0, _c = this._subClasses; _b < _c.length; _b++) {
  1601. var subType = _c[_b];
  1602. var info = subType.node.getOrAddType(baseType, type);
  1603. if (info) {
  1604. return info;
  1605. }
  1606. }
  1607. return null;
  1608. };
  1609. ClassTreeInfo.get = function (type) {
  1610. var dic = type["__classTreeInfo"];
  1611. if (!dic) {
  1612. return null;
  1613. }
  1614. return dic.getLevelOf(type);
  1615. };
  1616. ClassTreeInfo.getOrRegister = function (type, classContentFactory) {
  1617. var dic = type["__classTreeInfo"];
  1618. if (!dic) {
  1619. dic = new ClassTreeInfo(null, type, classContentFactory);
  1620. type["__classTreeInfo"] = dic;
  1621. }
  1622. return dic;
  1623. };
  1624. return ClassTreeInfo;
  1625. }());
  1626. BABYLON.ClassTreeInfo = ClassTreeInfo;
  1627. var DataBinding = (function () {
  1628. function DataBinding() {
  1629. this._converter = null;
  1630. this._mode = DataBinding.MODE_DEFAULT;
  1631. this._uiElementId = null;
  1632. this._dataSource = null;
  1633. this._currentDataSource = null;
  1634. this._propertyPathName = null;
  1635. this._stringFormat = null;
  1636. this._updateSourceTrigger = DataBinding.UPDATESOURCETRIGGER_PROPERTYCHANGED;
  1637. this._boundTo = null;
  1638. this._owner = null;
  1639. this._updateCounter = 0;
  1640. }
  1641. Object.defineProperty(DataBinding.prototype, "converter", {
  1642. /**
  1643. * Provide a callback that will convert the value obtained by the Data Binding to the type of the SmartProperty it's bound to.
  1644. * If no value are set, then it's assumed that the sourceValue is of the same type as the SmartProperty's one.
  1645. * If the SmartProperty type is a basic data type (string, boolean or number) and no converter is specified but the sourceValue is of a different type, the conversion will be implicitly made, if possible.
  1646. * @param sourceValue the source object retrieve by the Data Binding mechanism
  1647. * @returns the object of a compatible type with the SmartProperty it's bound to
  1648. */
  1649. get: function () {
  1650. return this._converter;
  1651. },
  1652. set: function (value) {
  1653. if (this._converter === value) {
  1654. return;
  1655. }
  1656. this._converter = value;
  1657. },
  1658. enumerable: true,
  1659. configurable: true
  1660. });
  1661. Object.defineProperty(DataBinding.prototype, "mode", {
  1662. /**
  1663. * Set the mode to use for the data flow in the binding. Set one of the MODE_xxx static member of this class. If not specified then MODE_DEFAULT will be used
  1664. */
  1665. get: function () {
  1666. if (this._mode === DataBinding.MODE_DEFAULT) {
  1667. return this._boundTo.bindingMode;
  1668. }
  1669. return this._mode;
  1670. },
  1671. set: function (value) {
  1672. if (this._mode === value) {
  1673. return;
  1674. }
  1675. this._mode = value;
  1676. },
  1677. enumerable: true,
  1678. configurable: true
  1679. });
  1680. Object.defineProperty(DataBinding.prototype, "uiElementId", {
  1681. /**
  1682. * You can override the Data Source object with this member which is the Id of a uiElement existing in the UI Logical tree.
  1683. * If not set and source no set too, then the dataSource property will be used.
  1684. */
  1685. get: function () {
  1686. return this._uiElementId;
  1687. },
  1688. set: function (value) {
  1689. if (this._uiElementId === value) {
  1690. return;
  1691. }
  1692. this._uiElementId = value;
  1693. },
  1694. enumerable: true,
  1695. configurable: true
  1696. });
  1697. Object.defineProperty(DataBinding.prototype, "dataSource", {
  1698. /**
  1699. * You can override the Data Source object with this member which is the source object to use directly.
  1700. * If not set and uiElement no set too, then the dataSource property of the SmartPropertyBase object will be used.
  1701. */
  1702. get: function () {
  1703. return this._dataSource;
  1704. },
  1705. set: function (value) {
  1706. if (this._dataSource === value) {
  1707. return;
  1708. }
  1709. this._dataSource = value;
  1710. },
  1711. enumerable: true,
  1712. configurable: true
  1713. });
  1714. Object.defineProperty(DataBinding.prototype, "propertyPathName", {
  1715. /**
  1716. * The path & name of the property to get from the source object.
  1717. * Once the Source object is evaluated (it's either the one got from uiElementId, source or dataSource) you can specify which property of this object is the value to bind to the smartProperty.
  1718. * If nothing is set then the source object will be used.
  1719. * You can specify an indirect property using the format "firstProperty.indirectProperty" like "address.postalCode" if the source is a Customer object which contains an address property and the Address class contains a postalCode property.
  1720. * If the property is an Array and you want to address a particular element then use the 'arrayProperty[index]' notation. For example "phoneNumbers[0]" to get the first element of the phoneNumber property which is an array.
  1721. */
  1722. get: function () {
  1723. return this._propertyPathName;
  1724. },
  1725. set: function (value) {
  1726. if (this._propertyPathName === value) {
  1727. return;
  1728. }
  1729. if (this._owner) {
  1730. }
  1731. this._propertyPathName = value;
  1732. if (this._owner) {
  1733. }
  1734. },
  1735. enumerable: true,
  1736. configurable: true
  1737. });
  1738. Object.defineProperty(DataBinding.prototype, "stringFormat", {
  1739. /**
  1740. * If the Smart Property is of the string type, you can use the string interpolation notation to provide how the sourceValue will be formatted, reference to the source value must be made via the token: ${value}. For instance `Customer Name: ${value}`
  1741. */
  1742. get: function () {
  1743. return this._stringFormat;
  1744. },
  1745. set: function (value) {
  1746. if (this._stringFormat === value) {
  1747. return;
  1748. }
  1749. this._stringFormat = value;
  1750. },
  1751. enumerable: true,
  1752. configurable: true
  1753. });
  1754. Object.defineProperty(DataBinding.prototype, "updateSourceTrigger", {
  1755. /**
  1756. * Specify how the source should be updated, use one of the UPDATESOURCETRIGGER_xxx member of this class, if not specified then UPDATESOURCETRIGGER_DEFAULT will be used.
  1757. */
  1758. get: function () {
  1759. return this._updateSourceTrigger;
  1760. },
  1761. set: function (value) {
  1762. if (this._updateSourceTrigger === value) {
  1763. return;
  1764. }
  1765. this._updateSourceTrigger = value;
  1766. },
  1767. enumerable: true,
  1768. configurable: true
  1769. });
  1770. DataBinding.prototype.canUpdateTarget = function (resetUpdateCounter) {
  1771. if (resetUpdateCounter) {
  1772. this._updateCounter = 0;
  1773. }
  1774. var mode = this.mode;
  1775. if (mode === DataBinding.MODE_ONETIME) {
  1776. return this._updateCounter === 0;
  1777. }
  1778. if (mode === DataBinding.MODE_ONEWAYTOSOURCE) {
  1779. return false;
  1780. }
  1781. return true;
  1782. };
  1783. DataBinding.prototype.updateTarget = function () {
  1784. var value = this._getActualDataSource();
  1785. var properties = this.propertyPathName.split(".");
  1786. for (var _i = 0, properties_1 = properties; _i < properties_1.length; _i++) {
  1787. var propertyName = properties_1[_i];
  1788. value = value[propertyName];
  1789. }
  1790. this._storeBoundValue(this._owner, value);
  1791. };
  1792. DataBinding.prototype._storeBoundValue = function (watcher, value) {
  1793. if ((++this._updateCounter > 1) && (this.mode === DataBinding.MODE_ONETIME)) {
  1794. return;
  1795. }
  1796. var newValue = value;
  1797. if (this._converter) {
  1798. newValue = this._converter(value);
  1799. }
  1800. if (this._stringFormat) {
  1801. newValue = this._stringFormat(newValue);
  1802. }
  1803. watcher[this._boundTo.name] = newValue;
  1804. };
  1805. DataBinding.prototype._getActualDataSource = function () {
  1806. if (this.dataSource) {
  1807. return this.dataSource;
  1808. }
  1809. if (this.uiElementId) {
  1810. // TODO Find UIElement
  1811. return null;
  1812. }
  1813. return this._owner.dataSource;
  1814. };
  1815. DataBinding.prototype._registerDataSource = function (updateTarget) {
  1816. var ds = this._getActualDataSource();
  1817. if (ds === this._currentDataSource) {
  1818. return;
  1819. }
  1820. if (this._currentDataSource) {
  1821. BindingHelper.unregisterDataSource(this._currentDataSource, this, 0);
  1822. }
  1823. if (ds) {
  1824. BindingHelper.registerDataSource(ds, this);
  1825. if (updateTarget && this.canUpdateTarget(true)) {
  1826. this.updateTarget();
  1827. }
  1828. }
  1829. this._currentDataSource = ds;
  1830. };
  1831. DataBinding.prototype._unregisterDataSource = function () {
  1832. var ds = this._getActualDataSource();
  1833. if (ds) {
  1834. BindingHelper.unregisterDataSource(ds, this, 0);
  1835. }
  1836. };
  1837. /**
  1838. * Use the mode specified in the SmartProperty declaration
  1839. */
  1840. DataBinding.MODE_DEFAULT = 1;
  1841. /**
  1842. * Update the binding target only once when the Smart Property's value is first accessed
  1843. */
  1844. DataBinding.MODE_ONETIME = 2;
  1845. /**
  1846. * Update the smart property when the source changes.
  1847. * The source won't be updated if the smart property value is set.
  1848. */
  1849. DataBinding.MODE_ONEWAY = 3;
  1850. /**
  1851. * Only update the source when the target's data is changing.
  1852. */
  1853. DataBinding.MODE_ONEWAYTOSOURCE = 4;
  1854. /**
  1855. * Update the bind target when the source changes and update the source when the Smart Property value is set.
  1856. */
  1857. DataBinding.MODE_TWOWAY = 5;
  1858. /**
  1859. * Use the Update Source Trigger defined in the SmartProperty declaration
  1860. */
  1861. DataBinding.UPDATESOURCETRIGGER_DEFAULT = 1;
  1862. /**
  1863. * Update the source as soon as the Smart Property has a value change
  1864. */
  1865. DataBinding.UPDATESOURCETRIGGER_PROPERTYCHANGED = 2;
  1866. /**
  1867. * Update the source when the binding target loses focus
  1868. */
  1869. DataBinding.UPDATESOURCETRIGGER_LOSTFOCUS = 3;
  1870. /**
  1871. * Update the source will be made by explicitly calling the UpdateFromDataSource method
  1872. */
  1873. DataBinding.UPDATESOURCETRIGGER_EXPLICIT = 4;
  1874. DataBinding = __decorate([
  1875. BABYLON.className("DataBinding", "BABYLON")
  1876. ], DataBinding);
  1877. return DataBinding;
  1878. }());
  1879. BABYLON.DataBinding = DataBinding;
  1880. var SmartPropertyBase = (function (_super) {
  1881. __extends(SmartPropertyBase, _super);
  1882. function SmartPropertyBase() {
  1883. _super.call(this);
  1884. this._dataSource = null;
  1885. this._dataSourceObserver = null;
  1886. this._instanceDirtyFlags = 0;
  1887. this._isDisposed = false;
  1888. this._bindings = null;
  1889. this._hasBinding = 0;
  1890. this._bindingSourceChanged = 0;
  1891. this._disposeObservable = null;
  1892. }
  1893. Object.defineProperty(SmartPropertyBase.prototype, "disposeObservable", {
  1894. get: function () {
  1895. if (!this._disposeObservable) {
  1896. this._disposeObservable = new BABYLON.Observable();
  1897. }
  1898. return this._disposeObservable;
  1899. },
  1900. enumerable: true,
  1901. configurable: true
  1902. });
  1903. Object.defineProperty(SmartPropertyBase.prototype, "isDisposed", {
  1904. /**
  1905. * Check if the object is disposed or not.
  1906. * @returns true if the object is dispose, false otherwise.
  1907. */
  1908. get: function () {
  1909. return this._isDisposed;
  1910. },
  1911. enumerable: true,
  1912. configurable: true
  1913. });
  1914. /**
  1915. * Disposable pattern, this method must be overloaded by derived types in order to clean up hardware related resources.
  1916. * @returns false if the object is already dispose, true otherwise. Your implementation must call super.dispose() and check for a false return and return immediately if it's the case.
  1917. */
  1918. SmartPropertyBase.prototype.dispose = function () {
  1919. if (this.isDisposed) {
  1920. return false;
  1921. }
  1922. if (this._disposeObservable && this._disposeObservable.hasObservers()) {
  1923. this._disposeObservable.notifyObservers(this);
  1924. }
  1925. this._isDisposed = true;
  1926. return true;
  1927. };
  1928. /**
  1929. * Check if a given set of properties are dirty or not.
  1930. * @param flags a ORed combination of Prim2DPropInfo.flagId values
  1931. * @return true if at least one property is dirty, false if none of them are.
  1932. */
  1933. SmartPropertyBase.prototype.checkPropertiesDirty = function (flags) {
  1934. return (this._instanceDirtyFlags & flags) !== 0;
  1935. };
  1936. /**
  1937. * Clear a given set of properties.
  1938. * @param flags a ORed combination of Prim2DPropInfo.flagId values
  1939. * @return the new set of property still marked as dirty
  1940. */
  1941. SmartPropertyBase.prototype.clearPropertiesDirty = function (flags) {
  1942. this._instanceDirtyFlags &= ~flags;
  1943. return this._instanceDirtyFlags;
  1944. };
  1945. SmartPropertyBase.prototype._resetPropertiesDirty = function () {
  1946. this._instanceDirtyFlags = 0;
  1947. };
  1948. /**
  1949. * Add an externally attached data from its key.
  1950. * This method call will fail and return false, if such key already exists.
  1951. * If you don't care and just want to get the data no matter what, use the more convenient getOrAddExternalDataWithFactory() method.
  1952. * @param key the unique key that identifies the data
  1953. * @param data the data object to associate to the key for this Engine instance
  1954. * @return true if no such key were already present and the data was added successfully, false otherwise
  1955. */
  1956. SmartPropertyBase.prototype.addExternalData = function (key, data) {
  1957. if (!this._externalData) {
  1958. this._externalData = new BABYLON.StringDictionary();
  1959. }
  1960. return this._externalData.add(key, data);
  1961. };
  1962. /**
  1963. * Get an externally attached data from its key
  1964. * @param key the unique key that identifies the data
  1965. * @return the associated data, if present (can be null), or undefined if not present
  1966. */
  1967. SmartPropertyBase.prototype.getExternalData = function (key) {
  1968. if (!this._externalData) {
  1969. return null;
  1970. }
  1971. return this._externalData.get(key);
  1972. };
  1973. /**
  1974. * Get an externally attached data from its key, create it using a factory if it's not already present
  1975. * @param key the unique key that identifies the data
  1976. * @param factory the factory that will be called to create the instance if and only if it doesn't exists
  1977. * @return the associated data, can be null if the factory returned null.
  1978. */
  1979. SmartPropertyBase.prototype.getOrAddExternalDataWithFactory = function (key, factory) {
  1980. if (!this._externalData) {
  1981. this._externalData = new BABYLON.StringDictionary();
  1982. }
  1983. return this._externalData.getOrAddWithFactory(key, factory);
  1984. };
  1985. /**
  1986. * Remove an externally attached data from the Engine instance
  1987. * @param key the unique key that identifies the data
  1988. * @return true if the data was successfully removed, false if it doesn't exist
  1989. */
  1990. SmartPropertyBase.prototype.removeExternalData = function (key) {
  1991. if (!this._externalData) {
  1992. return false;
  1993. }
  1994. return this._externalData.remove(key);
  1995. };
  1996. SmartPropertyBase._hookProperty = function (propId, piStore, kind, settings) {
  1997. return function (target, propName, descriptor) {
  1998. if (!settings) {
  1999. settings = {};
  2000. }
  2001. var propInfo = SmartPropertyBase._createPropInfo(target, propName, propId, kind, settings);
  2002. if (piStore) {
  2003. piStore(propInfo);
  2004. }
  2005. var getter = descriptor.get, setter = descriptor.set;
  2006. var typeLevelCompare = (settings.typeLevelCompare !== undefined) ? settings.typeLevelCompare : false;
  2007. // Overload the property setter implementation to add our own logic
  2008. descriptor.set = function (val) {
  2009. if (!setter) {
  2010. throw Error("Property '" + propInfo.name + "' of type '" + BABYLON.Tools.getFullClassName(this) + "' has no setter defined but was invoked as if it had one.");
  2011. }
  2012. // check for disposed first, do nothing
  2013. if (this.isDisposed) {
  2014. return;
  2015. }
  2016. var curVal = getter.call(this);
  2017. if (SmartPropertyBase._checkUnchanged(curVal, val)) {
  2018. return;
  2019. }
  2020. // Cast the object we're working one
  2021. var prim = this;
  2022. // Change the value
  2023. setter.call(this, val);
  2024. // Notify change, dirty flags update
  2025. prim._handlePropChanged(curVal, val, propName, propInfo, typeLevelCompare);
  2026. };
  2027. };
  2028. };
  2029. SmartPropertyBase._createPropInfo = function (target, propName, propId, kind, settings) {
  2030. var dic = ClassTreeInfo.getOrRegister(target, function () { return new Prim2DClassInfo(); });
  2031. var node = dic.getLevelOf(target);
  2032. var propInfo = node.levelContent.get(propId.toString());
  2033. if (propInfo) {
  2034. throw new Error("The ID " + propId + " is already taken by another property declaration named: " + propInfo.name);
  2035. }
  2036. // Create, setup and add the PropInfo object to our prop dictionary
  2037. propInfo = new Prim2DPropInfo();
  2038. propInfo.id = propId;
  2039. propInfo.flagId = Math.pow(2, propId);
  2040. propInfo.kind = kind;
  2041. propInfo.name = propName;
  2042. propInfo.bindingMode = (settings.bindingMode !== undefined) ? settings.bindingMode : DataBinding.MODE_TWOWAY;
  2043. propInfo.bindingUpdateSourceTrigger = (settings.bindingUpdateSourceTrigger !== undefined) ? settings.bindingUpdateSourceTrigger : DataBinding.UPDATESOURCETRIGGER_PROPERTYCHANGED;
  2044. propInfo.dirtyBoundingInfo = (settings.dirtyBoundingInfo !== undefined) ? settings.dirtyBoundingInfo : false;
  2045. propInfo.dirtyParentBoundingInfo = (settings.dirtyParentBoundingBox !== undefined) ? settings.dirtyParentBoundingBox : false;
  2046. propInfo.typeLevelCompare = (settings.typeLevelCompare !== undefined) ? settings.typeLevelCompare : false;
  2047. node.levelContent.add(propName, propInfo);
  2048. return propInfo;
  2049. };
  2050. Object.defineProperty(SmartPropertyBase.prototype, "propDic", {
  2051. /**
  2052. * Access the dictionary of properties metadata. Only properties decorated with XXXXLevelProperty are concerned
  2053. * @returns the dictionary, the key is the property name as declared in Javascript, the value is the metadata object
  2054. */
  2055. get: function () {
  2056. if (!this._propInfo) {
  2057. var cti = ClassTreeInfo.get(Object.getPrototypeOf(this));
  2058. if (!cti) {
  2059. throw new Error("Can't access the propDic member in class definition, is this class SmartPropertyPrim based?");
  2060. }
  2061. this._propInfo = cti.fullContent;
  2062. }
  2063. return this._propInfo;
  2064. },
  2065. enumerable: true,
  2066. configurable: true
  2067. });
  2068. SmartPropertyBase._checkUnchanged = function (curValue, newValue) {
  2069. // Nothing to nothing: nothing to do!
  2070. if ((curValue === null && newValue === null) || (curValue === undefined && newValue === undefined)) {
  2071. return true;
  2072. }
  2073. // Check value unchanged
  2074. if ((curValue != null) && (newValue != null)) {
  2075. if (typeof (curValue.equals) == "function") {
  2076. if (curValue.equals(newValue)) {
  2077. return true;
  2078. }
  2079. }
  2080. else {
  2081. if (curValue === newValue) {
  2082. return true;
  2083. }
  2084. }
  2085. }
  2086. return false;
  2087. };
  2088. SmartPropertyBase.prototype._handlePropChanged = function (curValue, newValue, propName, propInfo, typeLevelCompare) {
  2089. // Trigger property changed
  2090. var info = SmartPropertyBase.propChangeGuarding ? new BABYLON.PropertyChangedInfo() : SmartPropertyPrim.propChangedInfo;
  2091. info.oldValue = curValue;
  2092. info.newValue = newValue;
  2093. info.propertyName = propName;
  2094. var propMask = propInfo ? propInfo.flagId : -1;
  2095. try {
  2096. SmartPropertyBase.propChangeGuarding = true;
  2097. this.propertyChanged.notifyObservers(info, propMask);
  2098. }
  2099. finally {
  2100. SmartPropertyBase.propChangeGuarding = false;
  2101. }
  2102. };
  2103. SmartPropertyBase.prototype._triggerPropertyChanged = function (propInfo, newValue) {
  2104. if (this.isDisposed) {
  2105. return;
  2106. }
  2107. if (!propInfo) {
  2108. return;
  2109. }
  2110. this._handlePropChanged(undefined, newValue, propInfo.name, propInfo, propInfo.typeLevelCompare);
  2111. };
  2112. Object.defineProperty(SmartPropertyBase.prototype, "dataSource", {
  2113. /**
  2114. * Set the object from which Smart Properties using Binding will take/update their data from/to.
  2115. * When the object is part of a graph (with parent/children relationship) if the dataSource of a given instance is not specified, then the parent's one is used.
  2116. */
  2117. get: function () {
  2118. // Don't access to _dataSource directly but via a call to the _getDataSource method which can be overloaded in inherited classes
  2119. return this._getDataSource();
  2120. },
  2121. set: function (value) {
  2122. if (this._dataSource === value) {
  2123. return;
  2124. }
  2125. var oldValue = this._dataSource;
  2126. this._dataSource = value;
  2127. if (this._bindings && value != null) {
  2128. // Register the bindings
  2129. for (var _i = 0, _a = this._bindings; _i < _a.length; _i++) {
  2130. var binding = _a[_i];
  2131. if (binding != null) {
  2132. binding._registerDataSource(true);
  2133. }
  2134. }
  2135. }
  2136. this.onPropertyChanged("dataSource", oldValue, value);
  2137. },
  2138. enumerable: true,
  2139. configurable: true
  2140. });
  2141. // Inheriting classes can overload this method to provides additional logic for dataSource access
  2142. SmartPropertyBase.prototype._getDataSource = function () {
  2143. return this._dataSource;
  2144. };
  2145. SmartPropertyBase.prototype.createSimpleDataBinding = function (propInfo, propertyPathName, mode) {
  2146. if (mode === void 0) { mode = DataBinding.MODE_DEFAULT; }
  2147. var binding = new DataBinding();
  2148. binding.propertyPathName = propertyPathName;
  2149. binding.mode = mode;
  2150. return this.createDataBinding(propInfo, binding);
  2151. };
  2152. SmartPropertyBase.prototype.createDataBinding = function (propInfo, binding) {
  2153. if (!this._bindings) {
  2154. this._bindings = new Array();
  2155. }
  2156. if (!binding || binding._owner != null) {
  2157. throw Error("A valid/unused Binding must be passed.");
  2158. }
  2159. // Unregister a potentially existing binding for this property
  2160. this.removeDataBinding(propInfo);
  2161. // register the binding
  2162. binding._owner = this;
  2163. binding._boundTo = propInfo;
  2164. this._bindings[propInfo.id] = binding;
  2165. this._hasBinding |= propInfo.flagId;
  2166. binding._registerDataSource(true);
  2167. return binding;
  2168. };
  2169. SmartPropertyBase.prototype.removeDataBinding = function (propInfo) {
  2170. if ((this._hasBinding & propInfo.flagId) === 0) {
  2171. return false;
  2172. }
  2173. var curBinding = this._bindings[propInfo.id];
  2174. curBinding._unregisterDataSource();
  2175. this._bindings[propInfo.id] = null;
  2176. this._hasBinding &= ~propInfo.flagId;
  2177. return true;
  2178. };
  2179. SmartPropertyBase.prototype.updateFromDataSource = function () {
  2180. for (var _i = 0, _a = this._bindings; _i < _a.length; _i++) {
  2181. var binding = _a[_i];
  2182. if (binding) {
  2183. }
  2184. }
  2185. };
  2186. SmartPropertyBase.propChangedInfo = new BABYLON.PropertyChangedInfo();
  2187. SmartPropertyBase.propChangeGuarding = false;
  2188. SmartPropertyBase = __decorate([
  2189. BABYLON.className("SmartPropertyBase", "BABYLON")
  2190. ], SmartPropertyBase);
  2191. return SmartPropertyBase;
  2192. }(BABYLON.PropertyChangedBase));
  2193. BABYLON.SmartPropertyBase = SmartPropertyBase;
  2194. var BindingInfo = (function () {
  2195. function BindingInfo(binding, level, isLast) {
  2196. this.binding = binding;
  2197. this.level = level;
  2198. this.isLast = isLast;
  2199. }
  2200. return BindingInfo;
  2201. }());
  2202. var MonitoredObjectData = (function () {
  2203. function MonitoredObjectData(monitoredObject) {
  2204. var _this = this;
  2205. this.monitoredObject = monitoredObject;
  2206. this.monitoredIntermediateProperties = new BABYLON.StringDictionary();
  2207. this.observer = this.monitoredObject.propertyChanged.add(function (e, s) { _this.propertyChangedHandler(e.propertyName, e.oldValue, e.newValue); });
  2208. this.boundProperties = new BABYLON.StringDictionary();
  2209. this.monitoredIntermediateMask = 0;
  2210. this.boundPropertiesMask = 0;
  2211. }
  2212. MonitoredObjectData.prototype.propertyChangedHandler = function (propName, oldValue, newValue) {
  2213. var propId = BindingHelper._getPropertyID(this.monitoredObject, propName);
  2214. var propIdStr = propId.toString();
  2215. // Loop through all the registered bindings for this property that had a value change
  2216. if ((this.boundPropertiesMask & propId) !== 0) {
  2217. var bindingInfos = this.boundProperties.get(propIdStr);
  2218. for (var _i = 0, bindingInfos_1 = bindingInfos; _i < bindingInfos_1.length; _i++) {
  2219. var bi = bindingInfos_1[_i];
  2220. if (!bi.isLast) {
  2221. BindingHelper.unregisterDataSource(this.monitoredObject, bi.binding, bi.level);
  2222. BindingHelper.registerDataSource(bi.binding._currentDataSource, bi.binding);
  2223. }
  2224. if (bi.binding.canUpdateTarget(false)) {
  2225. bi.binding.updateTarget();
  2226. }
  2227. }
  2228. }
  2229. };
  2230. return MonitoredObjectData;
  2231. }());
  2232. var BindingHelper = (function () {
  2233. function BindingHelper() {
  2234. }
  2235. BindingHelper.registerDataSource = function (dataSource, binding) {
  2236. var properties = binding.propertyPathName.split(".");
  2237. var ownerMod = null;
  2238. var ownerInterPropId = 0;
  2239. var propertyOwner = dataSource;
  2240. var _loop_1 = function(i) {
  2241. var propName = properties[i];
  2242. var propId = BindingHelper._getPropertyID(propertyOwner, propName);
  2243. var propIdStr = propId.toString();
  2244. var mod = void 0;
  2245. if (ownerMod) {
  2246. var o_1 = ownerMod;
  2247. var po_1 = propertyOwner;
  2248. var oii_1 = ownerInterPropId;
  2249. mod = ownerMod.monitoredIntermediateProperties.getOrAddWithFactory(oii_1.toString(), function (k) {
  2250. o_1.monitoredIntermediateMask |= oii_1;
  2251. return BindingHelper._getMonitoredObjectData(po_1);
  2252. });
  2253. }
  2254. else {
  2255. mod = BindingHelper._getMonitoredObjectData(propertyOwner);
  2256. }
  2257. var m = mod;
  2258. var bindingInfos = mod.boundProperties.getOrAddWithFactory(propIdStr, function (k) {
  2259. m.boundPropertiesMask |= propId;
  2260. return new Array();
  2261. });
  2262. var bi = BABYLON.Tools.first(bindingInfos, function (cbi) { return cbi.binding === binding; });
  2263. if (!bi) {
  2264. bindingInfos.push(new BindingInfo(binding, i, (i + 1) === properties.length));
  2265. }
  2266. ownerMod = mod;
  2267. ownerInterPropId = propId;
  2268. propertyOwner = propertyOwner[propName];
  2269. };
  2270. for (var i = 0; i < properties.length; i++) {
  2271. _loop_1(i);
  2272. }
  2273. };
  2274. BindingHelper.unregisterDataSource = function (dataSource, binding, level) {
  2275. var properties = binding.propertyPathName.split(".");
  2276. var propertyOwner = dataSource;
  2277. var mod = BindingHelper._getMonitoredObjectData(propertyOwner);
  2278. for (var i = 0; i < properties.length; i++) {
  2279. var propName = properties[i];
  2280. var propId = BindingHelper._getPropertyID(propertyOwner, propName);
  2281. var propIdStr = propId.toString();
  2282. if (i >= level) {
  2283. mod = BindingHelper._unregisterBinding(mod, propId, binding);
  2284. }
  2285. else {
  2286. mod = mod.monitoredIntermediateProperties.get(propIdStr);
  2287. }
  2288. propertyOwner = propertyOwner[propName];
  2289. }
  2290. };
  2291. BindingHelper._unregisterBinding = function (mod, propertyID, binding) {
  2292. var propertyIDStr = propertyID.toString();
  2293. var res = null;
  2294. // Check if the property is registered as an intermediate and remove it
  2295. if ((mod.monitoredIntermediateMask & propertyID) !== 0) {
  2296. res = mod.monitoredIntermediateProperties.get(propertyIDStr);
  2297. mod.monitoredIntermediateProperties.remove(propertyIDStr);
  2298. // Update the mask
  2299. mod.monitoredIntermediateMask &= ~propertyID;
  2300. }
  2301. // Check if the property is registered as a final property and remove it
  2302. if ((mod.boundPropertiesMask & propertyID) !== 0) {
  2303. var bindingInfos = mod.boundProperties.get(propertyIDStr);
  2304. // Find the binding and remove it
  2305. var bi = BABYLON.Tools.first(bindingInfos, function (cbi) { return cbi.binding === binding; });
  2306. if (bi) {
  2307. var bii = bindingInfos.indexOf(bi);
  2308. bindingInfos.splice(bii, 1);
  2309. }
  2310. // If the array is empty, update the mask
  2311. if (bindingInfos.length === 0) {
  2312. mod.boundPropertiesMask &= ~propertyID;
  2313. }
  2314. }
  2315. // Check if the MOD is empty and unregister the observer and remove it from the list of MODs
  2316. if (mod.boundPropertiesMask === 0 && mod.monitoredIntermediateMask === 0) {
  2317. // Unregister the observer on Property Change
  2318. mod.monitoredObject.propertyChanged.remove(mod.observer);
  2319. // Remove the MOD from the dic
  2320. var objectId = BindingHelper._getObjectId(mod.monitoredObject);
  2321. BindingHelper._monitoredObjects.remove(objectId);
  2322. }
  2323. return res;
  2324. };
  2325. BindingHelper._getMonitoredObjectData = function (object) {
  2326. var objectId = BindingHelper._getObjectId(object);
  2327. var mod = BindingHelper._monitoredObjects.getOrAddWithFactory(objectId, function (k) { return new MonitoredObjectData(object); });
  2328. return mod;
  2329. };
  2330. BindingHelper._getObjectId = function (obj) {
  2331. var id = obj["__bindingHelperObjectId__"];
  2332. if (id == null) {
  2333. id = BABYLON.Tools.RandomId();
  2334. obj["__bindingHelperObjectId__"] = id;
  2335. return id;
  2336. }
  2337. return id;
  2338. };
  2339. BindingHelper._getObjectTypePropertyIDs = function (obj) {
  2340. var fullName = BABYLON.Tools.getFullClassName(obj);
  2341. if (!fullName) {
  2342. throw Error("Types involved in Data Binding must be decorated with the @className decorator");
  2343. }
  2344. var d = BindingHelper._propertiesID.getOrAddWithFactory(fullName, function () { return new BABYLON.StringDictionary(); });
  2345. return d;
  2346. };
  2347. BindingHelper._getPropertyID = function (object, propName) {
  2348. var otd = BindingHelper._getObjectTypePropertyIDs(object);
  2349. // Make sure we have a WatchedPropertyData for this property of this object type. This will contains the flagIg of the watched property.
  2350. // We use this flagId to flag for each watched instance which properties are watched, as final or intermediate and which directions are used
  2351. var propData = otd.getOrAddWithFactory(propName, function (k) { return 1 << otd.count; });
  2352. return propData;
  2353. };
  2354. BindingHelper._propertiesID = new BABYLON.StringDictionary();
  2355. BindingHelper._monitoredObjects = new BABYLON.StringDictionary();
  2356. return BindingHelper;
  2357. }());
  2358. var SmartPropertyPrim = (function (_super) {
  2359. __extends(SmartPropertyPrim, _super);
  2360. function SmartPropertyPrim() {
  2361. _super.call(this);
  2362. this._flags = 0;
  2363. this._modelKey = null;
  2364. this._levelBoundingInfo = new BABYLON.BoundingInfo2D();
  2365. this._boundingInfo = new BABYLON.BoundingInfo2D();
  2366. this.animations = new Array();
  2367. }
  2368. /**
  2369. * Disposable pattern, this method must be overloaded by derived types in order to clean up hardware related resources.
  2370. * @returns false if the object is already dispose, true otherwise. Your implementation must call super.dispose() and check for a false return and return immediately if it's the case.
  2371. */
  2372. SmartPropertyPrim.prototype.dispose = function () {
  2373. if (this.isDisposed) {
  2374. return false;
  2375. }
  2376. _super.prototype.dispose.call(this);
  2377. // Don't set to null, it may upset somebody...
  2378. this.animations.splice(0);
  2379. return true;
  2380. };
  2381. /**
  2382. * Returns as a new array populated with the Animatable used by the primitive. Must be overloaded by derived primitives.
  2383. * Look at Sprite2D for more information
  2384. */
  2385. SmartPropertyPrim.prototype.getAnimatables = function () {
  2386. return new Array();
  2387. };
  2388. Object.defineProperty(SmartPropertyPrim.prototype, "modelKey", {
  2389. /**
  2390. * Property giving the Model Key associated to the property.
  2391. * This value is constructed from the type of the primitive and all the name/value of its properties declared with the modelLevelProperty decorator
  2392. * @returns the model key string.
  2393. */
  2394. get: function () {
  2395. var _this = this;
  2396. // No need to compute it?
  2397. if (!this._isFlagSet(SmartPropertyPrim.flagModelDirty) && this._modelKey) {
  2398. return this._modelKey;
  2399. }
  2400. var modelKey = "Class:" + BABYLON.Tools.getClassName(this) + ";";
  2401. var propDic = this.propDic;
  2402. propDic.forEach(function (k, v) {
  2403. if (v.kind === Prim2DPropInfo.PROPKIND_MODEL) {
  2404. var propVal = _this[v.name];
  2405. // Special case, array, this WON'T WORK IN ALL CASES, all entries have to be of the same type and it must be a BJS well known one
  2406. if (propVal && propVal.constructor === Array) {
  2407. var firstVal = propVal[0];
  2408. if (!firstVal) {
  2409. propVal = 0;
  2410. }
  2411. else {
  2412. propVal = BABYLON.Tools.hashCodeFromStream(BABYLON.Tools.arrayOrStringFeeder(propVal));
  2413. }
  2414. }
  2415. modelKey += v.name + ":" + ((propVal != null) ? ((v.typeLevelCompare) ? BABYLON.Tools.getClassName(propVal) : propVal.toString()) : "[null]") + ";";
  2416. }
  2417. });
  2418. this._clearFlags(SmartPropertyPrim.flagModelDirty);
  2419. this._modelKey = modelKey;
  2420. return modelKey;
  2421. },
  2422. enumerable: true,
  2423. configurable: true
  2424. });
  2425. Object.defineProperty(SmartPropertyPrim.prototype, "isDirty", {
  2426. /**
  2427. * States if the Primitive is dirty and should be rendered again next time.
  2428. * @returns true is dirty, false otherwise
  2429. */
  2430. get: function () {
  2431. return (this._instanceDirtyFlags !== 0) || this._areSomeFlagsSet(SmartPropertyPrim.flagModelDirty | SmartPropertyPrim.flagPositioningDirty | SmartPropertyPrim.flagLayoutDirty);
  2432. },
  2433. enumerable: true,
  2434. configurable: true
  2435. });
  2436. SmartPropertyPrim.prototype._boundingBoxDirty = function () {
  2437. this._setFlags(SmartPropertyPrim.flagLevelBoundingInfoDirty);
  2438. // Escalate the dirty flag in the instance hierarchy, stop when a renderable group is found or at the end
  2439. if (this instanceof BABYLON.Prim2DBase) {
  2440. var curprim = this;
  2441. while (curprim) {
  2442. curprim._setFlags(SmartPropertyPrim.flagBoundingInfoDirty);
  2443. if (curprim.isSizeAuto) {
  2444. curprim.onPrimitivePropertyDirty(BABYLON.Prim2DBase.sizeProperty.flagId);
  2445. curprim._setFlags(SmartPropertyPrim.flagPositioningDirty);
  2446. }
  2447. if (curprim instanceof BABYLON.Group2D) {
  2448. if (curprim.isRenderableGroup) {
  2449. break;
  2450. }
  2451. }
  2452. curprim = curprim.parent;
  2453. }
  2454. }
  2455. };
  2456. SmartPropertyPrim.prototype._handlePropChanged = function (curValue, newValue, propName, propInfo, typeLevelCompare) {
  2457. _super.prototype._handlePropChanged.call(this, curValue, newValue, propName, propInfo, typeLevelCompare);
  2458. // If the property change also dirty the boundingInfo, update the boundingInfo dirty flags
  2459. if (propInfo.dirtyBoundingInfo) {
  2460. this._boundingBoxDirty();
  2461. }
  2462. else if (propInfo.dirtyParentBoundingInfo) {
  2463. var p = this._parent;
  2464. if (p != null) {
  2465. p._boundingBoxDirty();
  2466. }
  2467. }
  2468. // If the property belong to a group, check if it's a cached one, and dirty its render sprite accordingly
  2469. if (this instanceof BABYLON.Group2D) {
  2470. this.handleGroupChanged(propInfo);
  2471. }
  2472. // Check for parent layout dirty
  2473. if (this instanceof BABYLON.Prim2DBase) {
  2474. var p = this._parent;
  2475. if (p != null && p.layoutEngine && (p.layoutEngine.layoutDirtyOnPropertyChangedMask & propInfo.flagId) !== 0) {
  2476. p._setLayoutDirty();
  2477. }
  2478. }
  2479. // For type level compare, if there's a change of type it's a change of model, otherwise we issue an instance change
  2480. var instanceDirty = false;
  2481. if (typeLevelCompare && curValue != null && newValue != null) {
  2482. var cvProto = curValue.__proto__;
  2483. var nvProto = newValue.__proto__;
  2484. instanceDirty = (cvProto === nvProto);
  2485. }
  2486. // Set the dirty flags
  2487. if (!instanceDirty && (propInfo.kind === Prim2DPropInfo.PROPKIND_MODEL)) {
  2488. if (!this.isDirty) {
  2489. this._setFlags(SmartPropertyPrim.flagModelDirty);
  2490. }
  2491. }
  2492. else if (instanceDirty || (propInfo.kind === Prim2DPropInfo.PROPKIND_INSTANCE) || (propInfo.kind === Prim2DPropInfo.PROPKIND_DYNAMIC)) {
  2493. var propMask = propInfo.flagId;
  2494. this.onPrimitivePropertyDirty(propMask);
  2495. }
  2496. };
  2497. SmartPropertyPrim.prototype.onPrimitivePropertyDirty = function (propFlagId) {
  2498. this.onPrimBecomesDirty();
  2499. this._instanceDirtyFlags |= propFlagId;
  2500. };
  2501. SmartPropertyPrim.prototype.handleGroupChanged = function (prop) {
  2502. };
  2503. SmartPropertyPrim.prototype._resetPropertiesDirty = function () {
  2504. _super.prototype._resetPropertiesDirty.call(this);
  2505. this._clearFlags(SmartPropertyPrim.flagPrimInDirtyList | SmartPropertyPrim.flagNeedRefresh);
  2506. };
  2507. Object.defineProperty(SmartPropertyPrim.prototype, "levelBoundingInfo", {
  2508. /**
  2509. * Retrieve the boundingInfo for this Primitive, computed based on the primitive itself and NOT its children
  2510. */
  2511. get: function () {
  2512. if (this._isFlagSet(SmartPropertyPrim.flagLevelBoundingInfoDirty)) {
  2513. this.updateLevelBoundingInfo();
  2514. this._clearFlags(SmartPropertyPrim.flagLevelBoundingInfoDirty);
  2515. }
  2516. return this._levelBoundingInfo;
  2517. },
  2518. enumerable: true,
  2519. configurable: true
  2520. });
  2521. /**
  2522. * This method must be overridden by a given Primitive implementation to compute its boundingInfo
  2523. */
  2524. SmartPropertyPrim.prototype.updateLevelBoundingInfo = function () {
  2525. };
  2526. /**
  2527. * Property method called when the Primitive becomes dirty
  2528. */
  2529. SmartPropertyPrim.prototype.onPrimBecomesDirty = function () {
  2530. };
  2531. /**
  2532. * Check if a given flag is set
  2533. * @param flag the flag value
  2534. * @return true if set, false otherwise
  2535. */
  2536. SmartPropertyPrim.prototype._isFlagSet = function (flag) {
  2537. return (this._flags & flag) !== 0;
  2538. };
  2539. /**
  2540. * Check if all given flags are set
  2541. * @param flags the flags ORed
  2542. * @return true if all the flags are set, false otherwise
  2543. */
  2544. SmartPropertyPrim.prototype._areAllFlagsSet = function (flags) {
  2545. return (this._flags & flags) === flags;
  2546. };
  2547. /**
  2548. * Check if at least one flag of the given flags is set
  2549. * @param flags the flags ORed
  2550. * @return true if at least one flag is set, false otherwise
  2551. */
  2552. SmartPropertyPrim.prototype._areSomeFlagsSet = function (flags) {
  2553. return (this._flags & flags) !== 0;
  2554. };
  2555. /**
  2556. * Clear the given flags
  2557. * @param flags the flags to clear
  2558. */
  2559. SmartPropertyPrim.prototype._clearFlags = function (flags) {
  2560. this._flags &= ~flags;
  2561. };
  2562. /**
  2563. * Set the given flags to true state
  2564. * @param flags the flags ORed to set
  2565. * @return the flags state before this call
  2566. */
  2567. SmartPropertyPrim.prototype._setFlags = function (flags) {
  2568. var cur = this._flags;
  2569. this._flags |= flags;
  2570. return cur;
  2571. };
  2572. /**
  2573. * Change the state of the given flags
  2574. * @param flags the flags ORed to change
  2575. * @param state true to set them, false to clear them
  2576. */
  2577. SmartPropertyPrim.prototype._changeFlags = function (flags, state) {
  2578. if (state) {
  2579. this._flags |= flags;
  2580. }
  2581. else {
  2582. this._flags &= ~flags;
  2583. }
  2584. };
  2585. SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT = 0;
  2586. SmartPropertyPrim.flagNoPartOfLayout = 0x0000001; // set if the primitive's position/size must not be computed by Layout Engine
  2587. SmartPropertyPrim.flagLevelBoundingInfoDirty = 0x0000002; // set if the primitive's level bounding box (not including children) is dirty
  2588. SmartPropertyPrim.flagModelDirty = 0x0000004; // set if the model must be changed
  2589. SmartPropertyPrim.flagLayoutDirty = 0x0000008; // set if the layout must be computed
  2590. SmartPropertyPrim.flagLevelVisible = 0x0000010; // set if the primitive is set as visible for its level only
  2591. SmartPropertyPrim.flagBoundingInfoDirty = 0x0000020; // set if the primitive's overall bounding box (including children) is dirty
  2592. SmartPropertyPrim.flagIsPickable = 0x0000040; // set if the primitive can be picked during interaction
  2593. SmartPropertyPrim.flagIsVisible = 0x0000080; // set if the primitive is concretely visible (use the levelVisible of parents)
  2594. SmartPropertyPrim.flagVisibilityChanged = 0x0000100; // set if there was a transition between visible/hidden status
  2595. SmartPropertyPrim.flagPositioningDirty = 0x0000200; // set if the primitive positioning must be computed
  2596. SmartPropertyPrim.flagTrackedGroup = 0x0000400; // set if the group2D is tracking a scene node
  2597. SmartPropertyPrim.flagWorldCacheChanged = 0x0000800; // set if the cached bitmap of a world space canvas changed
  2598. SmartPropertyPrim.flagChildrenFlatZOrder = 0x0001000; // set if all the children (direct and indirect) will share the same Z-Order
  2599. SmartPropertyPrim.flagZOrderDirty = 0x0002000; // set if the Z-Order for this prim and its children must be recomputed
  2600. SmartPropertyPrim.flagActualOpacityDirty = 0x0004000; // set if the actualOpactity should be recomputed
  2601. SmartPropertyPrim.flagPrimInDirtyList = 0x0008000; // set if the primitive is in the primDirtyList
  2602. SmartPropertyPrim.flagIsContainer = 0x0010000; // set if the primitive is a container
  2603. SmartPropertyPrim.flagNeedRefresh = 0x0020000; // set if the primitive wasn't successful at refresh
  2604. SmartPropertyPrim.flagActualScaleDirty = 0x0040000; // set if the actualScale property needs to be recomputed
  2605. SmartPropertyPrim.flagDontInheritParentScale = 0x0080000; // set if the actualScale must not use its parent's scale to be computed
  2606. SmartPropertyPrim.flagGlobalTransformDirty = 0x0100000; // set if the global transform must be recomputed due to a local transform change
  2607. SmartPropertyPrim.flagLayoutBoundingInfoDirty = 0x0200000; // set if the layout bounding info is dirty
  2608. SmartPropertyPrim.flagAllow3DEventsBelowCanvas = 0x0400000; // set if pointer events should be sent to 3D Engine when the pointer is over the Canvas
  2609. SmartPropertyPrim = __decorate([
  2610. BABYLON.className("SmartPropertyPrim", "BABYLON")
  2611. ], SmartPropertyPrim);
  2612. return SmartPropertyPrim;
  2613. }(SmartPropertyBase));
  2614. BABYLON.SmartPropertyPrim = SmartPropertyPrim;
  2615. function dependencyProperty(propId, piStore, mode, updateSourceTrigger) {
  2616. if (mode === void 0) { mode = DataBinding.MODE_TWOWAY; }
  2617. if (updateSourceTrigger === void 0) { updateSourceTrigger = DataBinding.UPDATESOURCETRIGGER_PROPERTYCHANGED; }
  2618. return SmartPropertyBase._hookProperty(propId, piStore, Prim2DPropInfo.PROPKIND_DYNAMIC, { bindingMode: mode, bindingUpdateSourceTrigger: updateSourceTrigger });
  2619. }
  2620. BABYLON.dependencyProperty = dependencyProperty;
  2621. function modelLevelProperty(propId, piStore, typeLevelCompare, dirtyBoundingInfo, dirtyParentBoundingBox) {
  2622. if (typeLevelCompare === void 0) { typeLevelCompare = false; }
  2623. if (dirtyBoundingInfo === void 0) { dirtyBoundingInfo = false; }
  2624. if (dirtyParentBoundingBox === void 0) { dirtyParentBoundingBox = false; }
  2625. return SmartPropertyBase._hookProperty(propId, piStore, Prim2DPropInfo.PROPKIND_MODEL, { typeLevelCompare: typeLevelCompare, dirtyBoundingInfo: dirtyBoundingInfo, dirtyParentBoundingBox: dirtyParentBoundingBox });
  2626. }
  2627. BABYLON.modelLevelProperty = modelLevelProperty;
  2628. function instanceLevelProperty(propId, piStore, typeLevelCompare, dirtyBoundingInfo, dirtyParentBoundingBox) {
  2629. if (typeLevelCompare === void 0) { typeLevelCompare = false; }
  2630. if (dirtyBoundingInfo === void 0) { dirtyBoundingInfo = false; }
  2631. if (dirtyParentBoundingBox === void 0) { dirtyParentBoundingBox = false; }
  2632. return SmartPropertyBase._hookProperty(propId, piStore, Prim2DPropInfo.PROPKIND_INSTANCE, { typeLevelCompare: typeLevelCompare, dirtyBoundingInfo: dirtyBoundingInfo, dirtyParentBoundingBox: dirtyParentBoundingBox });
  2633. }
  2634. BABYLON.instanceLevelProperty = instanceLevelProperty;
  2635. function dynamicLevelProperty(propId, piStore, typeLevelCompare, dirtyBoundingInfo, dirtyParentBoundingBox) {
  2636. if (typeLevelCompare === void 0) { typeLevelCompare = false; }
  2637. if (dirtyBoundingInfo === void 0) { dirtyBoundingInfo = false; }
  2638. if (dirtyParentBoundingBox === void 0) { dirtyParentBoundingBox = false; }
  2639. return SmartPropertyBase._hookProperty(propId, piStore, Prim2DPropInfo.PROPKIND_DYNAMIC, { typeLevelCompare: typeLevelCompare, dirtyBoundingInfo: dirtyBoundingInfo, dirtyParentBoundingBox: dirtyParentBoundingBox });
  2640. }
  2641. BABYLON.dynamicLevelProperty = dynamicLevelProperty;
  2642. })(BABYLON || (BABYLON = {}));
  2643. var BABYLON;
  2644. (function (BABYLON) {
  2645. var PrepareRender2DContext = (function () {
  2646. function PrepareRender2DContext() {
  2647. this.forceRefreshPrimitive = false;
  2648. }
  2649. return PrepareRender2DContext;
  2650. }());
  2651. BABYLON.PrepareRender2DContext = PrepareRender2DContext;
  2652. var Render2DContext = (function () {
  2653. function Render2DContext(renderMode) {
  2654. this._renderMode = renderMode;
  2655. this.useInstancing = false;
  2656. this.groupInfoPartData = null;
  2657. this.partDataStartIndex = this.partDataEndIndex = null;
  2658. this.instancedBuffers = null;
  2659. }
  2660. Object.defineProperty(Render2DContext.prototype, "renderMode", {
  2661. /**
  2662. * Define which render Mode should be used to render the primitive: one of Render2DContext.RenderModeXxxx property
  2663. */
  2664. get: function () {
  2665. return this._renderMode;
  2666. },
  2667. enumerable: true,
  2668. configurable: true
  2669. });
  2670. Object.defineProperty(Render2DContext, "RenderModeOpaque", {
  2671. /**
  2672. * The set of primitives to render is opaque.
  2673. * This is the first rendering pass. All Opaque primitives are rendered. Depth Compare and Write are both enabled.
  2674. */
  2675. get: function () {
  2676. return Render2DContext._renderModeOpaque;
  2677. },
  2678. enumerable: true,
  2679. configurable: true
  2680. });
  2681. Object.defineProperty(Render2DContext, "RenderModeAlphaTest", {
  2682. /**
  2683. * The set of primitives to render is using Alpha Test (aka masking).
  2684. * Alpha Blend is enabled, the AlphaMode must be manually set, the render occurs after the RenderModeOpaque and is depth independent (i.e. primitives are not sorted by depth). Depth Compare and Write are both enabled.
  2685. */
  2686. get: function () {
  2687. return Render2DContext._renderModeAlphaTest;
  2688. },
  2689. enumerable: true,
  2690. configurable: true
  2691. });
  2692. Object.defineProperty(Render2DContext, "RenderModeTransparent", {
  2693. /**
  2694. * The set of primitives to render is transparent.
  2695. * Alpha Blend is enabled, the AlphaMode must be manually set, the render occurs after the RenderModeAlphaTest and is depth dependent (i.e. primitives are stored by depth and rendered back to front). Depth Compare is on, but Depth write is Off.
  2696. */
  2697. get: function () {
  2698. return Render2DContext._renderModeTransparent;
  2699. },
  2700. enumerable: true,
  2701. configurable: true
  2702. });
  2703. Render2DContext._renderModeOpaque = 1;
  2704. Render2DContext._renderModeAlphaTest = 2;
  2705. Render2DContext._renderModeTransparent = 3;
  2706. return Render2DContext;
  2707. }());
  2708. BABYLON.Render2DContext = Render2DContext;
  2709. /**
  2710. * This class store information for the pointerEventObservable Observable.
  2711. * The Observable is divided into many sub events (using the Mask feature of the Observable pattern): PointerOver, PointerEnter, PointerDown, PointerMouseWheel, PointerMove, PointerUp, PointerDown, PointerLeave, PointerGotCapture and PointerLostCapture.
  2712. */
  2713. var PrimitivePointerInfo = (function () {
  2714. function PrimitivePointerInfo() {
  2715. this.primitivePointerPos = BABYLON.Vector2.Zero();
  2716. this.tilt = BABYLON.Vector2.Zero();
  2717. this.cancelBubble = false;
  2718. }
  2719. Object.defineProperty(PrimitivePointerInfo, "PointerOver", {
  2720. // The behavior is based on the HTML specifications of the Pointer Events (https://www.w3.org/TR/pointerevents/#list-of-pointer-events). This is not 100% compliant and not meant to be, but still, it's based on these specs for most use cases to be programmed the same way (as closest as possible) as it would have been in HTML.
  2721. /**
  2722. * This event type is raised when a pointing device is moved into the hit test boundaries of a primitive.
  2723. * Bubbles: yes
  2724. */
  2725. get: function () {
  2726. return PrimitivePointerInfo._pointerOver;
  2727. },
  2728. enumerable: true,
  2729. configurable: true
  2730. });
  2731. Object.defineProperty(PrimitivePointerInfo, "PointerEnter", {
  2732. /**
  2733. * This event type is raised when a pointing device is moved into the hit test boundaries of a primitive or one of its descendants.
  2734. * Bubbles: no
  2735. */
  2736. get: function () {
  2737. return PrimitivePointerInfo._pointerEnter;
  2738. },
  2739. enumerable: true,
  2740. configurable: true
  2741. });
  2742. Object.defineProperty(PrimitivePointerInfo, "PointerDown", {
  2743. /**
  2744. * This event type is raised when a pointer enters the active button state (non-zero value in the buttons property). For mouse it's when the device transitions from no buttons depressed to at least one button depressed. For touch/pen this is when a physical contact is made.
  2745. * Bubbles: yes
  2746. */
  2747. get: function () {
  2748. return PrimitivePointerInfo._pointerDown;
  2749. },
  2750. enumerable: true,
  2751. configurable: true
  2752. });
  2753. Object.defineProperty(PrimitivePointerInfo, "PointerMouseWheel", {
  2754. /**
  2755. * This event type is raised when the pointer is a mouse and it's wheel is rolling
  2756. * Bubbles: yes
  2757. */
  2758. get: function () {
  2759. return PrimitivePointerInfo._pointerMouseWheel;
  2760. },
  2761. enumerable: true,
  2762. configurable: true
  2763. });
  2764. Object.defineProperty(PrimitivePointerInfo, "PointerMove", {
  2765. /**
  2766. * This event type is raised when a pointer change coordinates or when a pointer changes button state, pressure, tilt, or contact geometry and the circumstances produce no other pointers events.
  2767. * Bubbles: yes
  2768. */
  2769. get: function () {
  2770. return PrimitivePointerInfo._pointerMove;
  2771. },
  2772. enumerable: true,
  2773. configurable: true
  2774. });
  2775. Object.defineProperty(PrimitivePointerInfo, "PointerUp", {
  2776. /**
  2777. * This event type is raised when the pointer leaves the active buttons states (zero value in the buttons property). For mouse, this is when the device transitions from at least one button depressed to no buttons depressed. For touch/pen, this is when physical contact is removed.
  2778. * Bubbles: yes
  2779. */
  2780. get: function () {
  2781. return PrimitivePointerInfo._pointerUp;
  2782. },
  2783. enumerable: true,
  2784. configurable: true
  2785. });
  2786. Object.defineProperty(PrimitivePointerInfo, "PointerOut", {
  2787. /**
  2788. * This event type is raised when a pointing device is moved out of the hit test the boundaries of a primitive.
  2789. * Bubbles: yes
  2790. */
  2791. get: function () {
  2792. return PrimitivePointerInfo._pointerOut;
  2793. },
  2794. enumerable: true,
  2795. configurable: true
  2796. });
  2797. Object.defineProperty(PrimitivePointerInfo, "PointerLeave", {
  2798. /**
  2799. * This event type is raised when a pointing device is moved out of the hit test boundaries of a primitive and all its descendants.
  2800. * Bubbles: no
  2801. */
  2802. get: function () {
  2803. return PrimitivePointerInfo._pointerLeave;
  2804. },
  2805. enumerable: true,
  2806. configurable: true
  2807. });
  2808. Object.defineProperty(PrimitivePointerInfo, "PointerGotCapture", {
  2809. /**
  2810. * This event type is raised when a primitive receives the pointer capture. This event is fired at the element that is receiving pointer capture. Subsequent events for that pointer will be fired at this element.
  2811. * Bubbles: yes
  2812. */
  2813. get: function () {
  2814. return PrimitivePointerInfo._pointerGotCapture;
  2815. },
  2816. enumerable: true,
  2817. configurable: true
  2818. });
  2819. Object.defineProperty(PrimitivePointerInfo, "PointerLostCapture", {
  2820. /**
  2821. * This event type is raised after pointer capture is released for a pointer.
  2822. * Bubbles: yes
  2823. */
  2824. get: function () {
  2825. return PrimitivePointerInfo._pointerLostCapture;
  2826. },
  2827. enumerable: true,
  2828. configurable: true
  2829. });
  2830. Object.defineProperty(PrimitivePointerInfo, "MouseWheelPrecision", {
  2831. get: function () {
  2832. return PrimitivePointerInfo._mouseWheelPrecision;
  2833. },
  2834. enumerable: true,
  2835. configurable: true
  2836. });
  2837. PrimitivePointerInfo.prototype.updateRelatedTarget = function (prim, primPointerPos) {
  2838. this.relatedTarget = prim;
  2839. this.relatedTargetPointerPos = primPointerPos;
  2840. };
  2841. PrimitivePointerInfo.getEventTypeName = function (mask) {
  2842. switch (mask) {
  2843. case PrimitivePointerInfo.PointerOver: return "PointerOver";
  2844. case PrimitivePointerInfo.PointerEnter: return "PointerEnter";
  2845. case PrimitivePointerInfo.PointerDown: return "PointerDown";
  2846. case PrimitivePointerInfo.PointerMouseWheel: return "PointerMouseWheel";
  2847. case PrimitivePointerInfo.PointerMove: return "PointerMove";
  2848. case PrimitivePointerInfo.PointerUp: return "PointerUp";
  2849. case PrimitivePointerInfo.PointerOut: return "PointerOut";
  2850. case PrimitivePointerInfo.PointerLeave: return "PointerLeave";
  2851. case PrimitivePointerInfo.PointerGotCapture: return "PointerGotCapture";
  2852. case PrimitivePointerInfo.PointerLostCapture: return "PointerLostCapture";
  2853. }
  2854. };
  2855. PrimitivePointerInfo._pointerOver = 0x0001;
  2856. PrimitivePointerInfo._pointerEnter = 0x0002;
  2857. PrimitivePointerInfo._pointerDown = 0x0004;
  2858. PrimitivePointerInfo._pointerMouseWheel = 0x0008;
  2859. PrimitivePointerInfo._pointerMove = 0x0010;
  2860. PrimitivePointerInfo._pointerUp = 0x0020;
  2861. PrimitivePointerInfo._pointerOut = 0x0040;
  2862. PrimitivePointerInfo._pointerLeave = 0x0080;
  2863. PrimitivePointerInfo._pointerGotCapture = 0x0100;
  2864. PrimitivePointerInfo._pointerLostCapture = 0x0200;
  2865. PrimitivePointerInfo._mouseWheelPrecision = 3.0;
  2866. return PrimitivePointerInfo;
  2867. }());
  2868. BABYLON.PrimitivePointerInfo = PrimitivePointerInfo;
  2869. /**
  2870. * Defines the horizontal and vertical alignment information for a Primitive.
  2871. */
  2872. var PrimitiveAlignment = (function () {
  2873. function PrimitiveAlignment(changeCallback) {
  2874. this._changedCallback = changeCallback;
  2875. this._horizontal = PrimitiveAlignment.AlignLeft;
  2876. this._vertical = PrimitiveAlignment.AlignBottom;
  2877. }
  2878. Object.defineProperty(PrimitiveAlignment, "AlignLeft", {
  2879. /**
  2880. * Alignment is made relative to the left edge of the Primitive. Valid for horizontal alignment only.
  2881. */
  2882. get: function () { return PrimitiveAlignment._AlignLeft; },
  2883. enumerable: true,
  2884. configurable: true
  2885. });
  2886. Object.defineProperty(PrimitiveAlignment, "AlignTop", {
  2887. /**
  2888. * Alignment is made relative to the top edge of the Primitive. Valid for vertical alignment only.
  2889. */
  2890. get: function () { return PrimitiveAlignment._AlignTop; },
  2891. enumerable: true,
  2892. configurable: true
  2893. });
  2894. Object.defineProperty(PrimitiveAlignment, "AlignRight", {
  2895. /**
  2896. * Alignment is made relative to the right edge of the Primitive. Valid for horizontal alignment only.
  2897. */
  2898. get: function () { return PrimitiveAlignment._AlignRight; },
  2899. enumerable: true,
  2900. configurable: true
  2901. });
  2902. Object.defineProperty(PrimitiveAlignment, "AlignBottom", {
  2903. /**
  2904. * Alignment is made relative to the bottom edge of the Primitive. Valid for vertical alignment only.
  2905. */
  2906. get: function () { return PrimitiveAlignment._AlignBottom; },
  2907. enumerable: true,
  2908. configurable: true
  2909. });
  2910. Object.defineProperty(PrimitiveAlignment, "AlignCenter", {
  2911. /**
  2912. * Alignment is made to center the content from equal distance to the opposite edges of the Primitive
  2913. */
  2914. get: function () { return PrimitiveAlignment._AlignCenter; },
  2915. enumerable: true,
  2916. configurable: true
  2917. });
  2918. Object.defineProperty(PrimitiveAlignment, "AlignStretch", {
  2919. /**
  2920. * The content is stretched toward the opposite edges of the Primitive
  2921. */
  2922. get: function () { return PrimitiveAlignment._AlignStretch; },
  2923. enumerable: true,
  2924. configurable: true
  2925. });
  2926. Object.defineProperty(PrimitiveAlignment.prototype, "horizontal", {
  2927. /**
  2928. * Get/set the horizontal alignment. Use one of the AlignXXX static properties of this class
  2929. */
  2930. get: function () {
  2931. return this._horizontal;
  2932. },
  2933. set: function (value) {
  2934. if (this._horizontal === value) {
  2935. return;
  2936. }
  2937. this._horizontal = value;
  2938. this.onChangeCallback();
  2939. },
  2940. enumerable: true,
  2941. configurable: true
  2942. });
  2943. Object.defineProperty(PrimitiveAlignment.prototype, "vertical", {
  2944. /**
  2945. * Get/set the vertical alignment. Use one of the AlignXXX static properties of this class
  2946. */
  2947. get: function () {
  2948. return this._vertical;
  2949. },
  2950. set: function (value) {
  2951. if (this._vertical === value) {
  2952. return;
  2953. }
  2954. this._vertical = value;
  2955. this.onChangeCallback();
  2956. },
  2957. enumerable: true,
  2958. configurable: true
  2959. });
  2960. PrimitiveAlignment.prototype.onChangeCallback = function () {
  2961. if (this._changedCallback) {
  2962. this._changedCallback();
  2963. }
  2964. };
  2965. /**
  2966. * Set the horizontal alignment from a string value.
  2967. * @param text can be either: 'left','right','center','stretch'
  2968. */
  2969. PrimitiveAlignment.prototype.setHorizontal = function (text) {
  2970. var v = text.trim().toLocaleLowerCase();
  2971. switch (v) {
  2972. case "left":
  2973. this.horizontal = PrimitiveAlignment.AlignLeft;
  2974. return;
  2975. case "right":
  2976. this.horizontal = PrimitiveAlignment.AlignRight;
  2977. return;
  2978. case "center":
  2979. this.horizontal = PrimitiveAlignment.AlignCenter;
  2980. return;
  2981. case "stretch":
  2982. this.horizontal = PrimitiveAlignment.AlignStretch;
  2983. return;
  2984. }
  2985. };
  2986. /**
  2987. * Set the vertical alignment from a string value.
  2988. * @param text can be either: 'top','bottom','center','stretch'
  2989. */
  2990. PrimitiveAlignment.prototype.setVertical = function (text) {
  2991. var v = text.trim().toLocaleLowerCase();
  2992. switch (v) {
  2993. case "top":
  2994. this.vertical = PrimitiveAlignment.AlignTop;
  2995. return;
  2996. case "bottom":
  2997. this.vertical = PrimitiveAlignment.AlignBottom;
  2998. return;
  2999. case "center":
  3000. this.vertical = PrimitiveAlignment.AlignCenter;
  3001. return;
  3002. case "stretch":
  3003. this.vertical = PrimitiveAlignment.AlignStretch;
  3004. return;
  3005. }
  3006. };
  3007. /**
  3008. * Set the horizontal and or vertical alignments from a string value.
  3009. * @param text can be: [<h:|horizontal:><left|right|center|stretch>], [<v:|vertical:><top|bottom|center|stretch>]
  3010. */
  3011. PrimitiveAlignment.prototype.fromString = function (value) {
  3012. var m = value.trim().split(",");
  3013. if (m.length === 1) {
  3014. this.setHorizontal(m[0]);
  3015. this.setVertical(m[0]);
  3016. }
  3017. else {
  3018. for (var _i = 0, m_1 = m; _i < m_1.length; _i++) {
  3019. var v = m_1[_i];
  3020. v = v.toLocaleLowerCase().trim();
  3021. // Horizontal
  3022. var i = v.indexOf("h:");
  3023. if (i === -1) {
  3024. i = v.indexOf("horizontal:");
  3025. }
  3026. if (i !== -1) {
  3027. v = v.substr(v.indexOf(":") + 1);
  3028. this.setHorizontal(v);
  3029. continue;
  3030. }
  3031. // Vertical
  3032. i = v.indexOf("v:");
  3033. if (i === -1) {
  3034. i = v.indexOf("vertical:");
  3035. }
  3036. if (i !== -1) {
  3037. v = v.substr(v.indexOf(":") + 1);
  3038. this.setVertical(v);
  3039. continue;
  3040. }
  3041. }
  3042. }
  3043. };
  3044. PrimitiveAlignment.prototype.copyFrom = function (pa) {
  3045. this._horizontal = pa._horizontal;
  3046. this._vertical = pa._vertical;
  3047. this.onChangeCallback();
  3048. };
  3049. Object.defineProperty(PrimitiveAlignment.prototype, "isDefault", {
  3050. get: function () {
  3051. return this.horizontal === PrimitiveAlignment.AlignLeft && this.vertical === PrimitiveAlignment.AlignBottom;
  3052. },
  3053. enumerable: true,
  3054. configurable: true
  3055. });
  3056. PrimitiveAlignment._AlignLeft = 1;
  3057. PrimitiveAlignment._AlignTop = 1; // Same as left
  3058. PrimitiveAlignment._AlignRight = 2;
  3059. PrimitiveAlignment._AlignBottom = 2; // Same as right
  3060. PrimitiveAlignment._AlignCenter = 3;
  3061. PrimitiveAlignment._AlignStretch = 4;
  3062. PrimitiveAlignment = __decorate([
  3063. BABYLON.className("PrimitiveAlignment", "BABYLON")
  3064. ], PrimitiveAlignment);
  3065. return PrimitiveAlignment;
  3066. }());
  3067. BABYLON.PrimitiveAlignment = PrimitiveAlignment;
  3068. /**
  3069. * Stores information about a Primitive that was intersected
  3070. */
  3071. var PrimitiveIntersectedInfo = (function () {
  3072. function PrimitiveIntersectedInfo(prim, intersectionLocation) {
  3073. this.prim = prim;
  3074. this.intersectionLocation = intersectionLocation;
  3075. }
  3076. return PrimitiveIntersectedInfo;
  3077. }());
  3078. BABYLON.PrimitiveIntersectedInfo = PrimitiveIntersectedInfo;
  3079. /**
  3080. * Define a thickness toward every edges of a Primitive to allow margin and padding.
  3081. * The thickness can be expressed as pixels, percentages, inherit the value of the parent primitive or be auto.
  3082. */
  3083. var PrimitiveThickness = (function () {
  3084. function PrimitiveThickness(parentAccess, changedCallback) {
  3085. this._parentAccess = parentAccess;
  3086. this._changedCallback = changedCallback;
  3087. this._pixels = new Array(4);
  3088. this._percentages = new Array(4);
  3089. this._setType(0, PrimitiveThickness.Auto);
  3090. this._setType(1, PrimitiveThickness.Auto);
  3091. this._setType(2, PrimitiveThickness.Auto);
  3092. this._setType(3, PrimitiveThickness.Auto);
  3093. this._pixels[0] = 0;
  3094. this._pixels[1] = 0;
  3095. this._pixels[2] = 0;
  3096. this._pixels[3] = 0;
  3097. }
  3098. /**
  3099. * Set the thickness from a string value
  3100. * @param thickness format is "top: <value>, left:<value>, right:<value>, bottom:<value>" or "<value>" (same for all edges) each are optional, auto will be set if it's omitted.
  3101. * Values are: 'auto', 'inherit', 'XX%' for percentage, 'XXpx' or 'XX' for pixels.
  3102. */
  3103. PrimitiveThickness.prototype.fromString = function (thickness) {
  3104. this._clear();
  3105. var m = thickness.trim().split(",");
  3106. // Special case, one value to apply to all edges
  3107. if (m.length === 1 && thickness.indexOf(":") === -1) {
  3108. this._setStringValue(m[0], 0, false);
  3109. this._setStringValue(m[0], 1, false);
  3110. this._setStringValue(m[0], 2, false);
  3111. this._setStringValue(m[0], 3, false);
  3112. this.onChangeCallback();
  3113. return;
  3114. }
  3115. var res = false;
  3116. for (var _i = 0, m_2 = m; _i < m_2.length; _i++) {
  3117. var cm = m_2[_i];
  3118. res = this._extractString(cm, false) || res;
  3119. }
  3120. if (!res) {
  3121. throw new Error("Can't parse the string to create a PrimitiveMargin object, format must be: 'top: <value>, left:<value>, right:<value>, bottom:<value>");
  3122. }
  3123. // Check the margin that weren't set and set them in auto
  3124. if ((this._flags & 0x000F) === 0)
  3125. this._flags |= PrimitiveThickness.Pixel << 0;
  3126. if ((this._flags & 0x00F0) === 0)
  3127. this._flags |= PrimitiveThickness.Pixel << 4;
  3128. if ((this._flags & 0x0F00) === 0)
  3129. this._flags |= PrimitiveThickness.Pixel << 8;
  3130. if ((this._flags & 0xF000) === 0)
  3131. this._flags |= PrimitiveThickness.Pixel << 12;
  3132. this.onChangeCallback();
  3133. };
  3134. /**
  3135. * Set the thickness from multiple string
  3136. * Possible values are: 'auto', 'inherit', 'XX%' for percentage, 'XXpx' or 'XX' for pixels.
  3137. * @param top the top thickness to set
  3138. * @param left the left thickness to set
  3139. * @param right the right thickness to set
  3140. * @param bottom the bottom thickness to set
  3141. */
  3142. PrimitiveThickness.prototype.fromStrings = function (top, left, right, bottom) {
  3143. this._clear();
  3144. this._setStringValue(top, 0, false);
  3145. this._setStringValue(left, 1, false);
  3146. this._setStringValue(right, 2, false);
  3147. this._setStringValue(bottom, 3, false);
  3148. this.onChangeCallback();
  3149. return this;
  3150. };
  3151. /**
  3152. * Set the thickness from pixel values
  3153. * @param top the top thickness in pixels to set
  3154. * @param left the left thickness in pixels to set
  3155. * @param right the right thickness in pixels to set
  3156. * @param bottom the bottom thickness in pixels to set
  3157. */
  3158. PrimitiveThickness.prototype.fromPixels = function (top, left, right, bottom) {
  3159. this._clear();
  3160. this._pixels[0] = top;
  3161. this._pixels[1] = left;
  3162. this._pixels[2] = right;
  3163. this._pixels[3] = bottom;
  3164. this.onChangeCallback();
  3165. return this;
  3166. };
  3167. /**
  3168. * Apply the same pixel value to all edges
  3169. * @param margin the value to set, in pixels.
  3170. */
  3171. PrimitiveThickness.prototype.fromUniformPixels = function (margin) {
  3172. this._clear();
  3173. this._pixels[0] = margin;
  3174. this._pixels[1] = margin;
  3175. this._pixels[2] = margin;
  3176. this._pixels[3] = margin;
  3177. this.onChangeCallback();
  3178. return this;
  3179. };
  3180. PrimitiveThickness.prototype.copyFrom = function (pt) {
  3181. this._clear();
  3182. for (var i = 0; i < 4; i++) {
  3183. this._pixels[i] = pt._pixels[i];
  3184. this._percentages[i] = pt._percentages[i];
  3185. }
  3186. this._flags = pt._flags;
  3187. this.onChangeCallback();
  3188. };
  3189. /**
  3190. * Set all edges in auto
  3191. */
  3192. PrimitiveThickness.prototype.auto = function () {
  3193. this._clear();
  3194. this._flags = (PrimitiveThickness.Auto << 0) | (PrimitiveThickness.Auto << 4) | (PrimitiveThickness.Auto << 8) | (PrimitiveThickness.Auto << 12);
  3195. this._pixels[0] = 0;
  3196. this._pixels[1] = 0;
  3197. this._pixels[2] = 0;
  3198. this._pixels[3] = 0;
  3199. this.onChangeCallback();
  3200. return this;
  3201. };
  3202. PrimitiveThickness.prototype._clear = function () {
  3203. this._flags = 0;
  3204. this._pixels[0] = 0;
  3205. this._pixels[1] = 0;
  3206. this._pixels[2] = 0;
  3207. this._pixels[3] = 0;
  3208. this._percentages[0] = null;
  3209. this._percentages[1] = null;
  3210. this._percentages[2] = null;
  3211. this._percentages[3] = null;
  3212. };
  3213. PrimitiveThickness.prototype._extractString = function (value, emitChanged) {
  3214. var v = value.trim().toLocaleLowerCase();
  3215. if (v.indexOf("top:") === 0) {
  3216. v = v.substr(4).trim();
  3217. return this._setStringValue(v, 0, emitChanged);
  3218. }
  3219. if (v.indexOf("left:") === 0) {
  3220. v = v.substr(5).trim();
  3221. return this._setStringValue(v, 1, emitChanged);
  3222. }
  3223. if (v.indexOf("right:") === 0) {
  3224. v = v.substr(6).trim();
  3225. return this._setStringValue(v, 2, emitChanged);
  3226. }
  3227. if (v.indexOf("bottom:") === 0) {
  3228. v = v.substr(7).trim();
  3229. return this._setStringValue(v, 3, emitChanged);
  3230. }
  3231. return false;
  3232. };
  3233. PrimitiveThickness.prototype._setStringValue = function (value, index, emitChanged) {
  3234. // Check for auto
  3235. var v = value.trim().toLocaleLowerCase();
  3236. if (v === "auto") {
  3237. if (this._isType(index, PrimitiveThickness.Auto)) {
  3238. return true;
  3239. }
  3240. this._setType(index, PrimitiveThickness.Auto);
  3241. this._pixels[index] = 0;
  3242. if (emitChanged) {
  3243. this.onChangeCallback();
  3244. }
  3245. }
  3246. else if (v === "inherit") {
  3247. if (this._isType(index, PrimitiveThickness.Inherit)) {
  3248. return true;
  3249. }
  3250. this._setType(index, PrimitiveThickness.Inherit);
  3251. this._pixels[index] = null;
  3252. if (emitChanged) {
  3253. this.onChangeCallback();
  3254. }
  3255. }
  3256. else {
  3257. var pI = v.indexOf("%");
  3258. // Check for percentage
  3259. if (pI !== -1) {
  3260. var n_1 = v.substr(0, pI);
  3261. var number_1 = Math.round(Number(n_1)) / 100; // Normalize the percentage to [0;1] with a 0.01 precision
  3262. if (this._isType(index, PrimitiveThickness.Percentage) && (this._percentages[index] === number_1)) {
  3263. return true;
  3264. }
  3265. this._setType(index, PrimitiveThickness.Percentage);
  3266. if (isNaN(number_1)) {
  3267. return false;
  3268. }
  3269. this._percentages[index] = number_1;
  3270. if (emitChanged) {
  3271. this.onChangeCallback();
  3272. }
  3273. return true;
  3274. }
  3275. // Check for pixel
  3276. var n = void 0;
  3277. pI = v.indexOf("px");
  3278. if (pI !== -1) {
  3279. n = v.substr(0, pI).trim();
  3280. }
  3281. else {
  3282. n = v;
  3283. }
  3284. var number = Number(n);
  3285. if (this._isType(index, PrimitiveThickness.Pixel) && (this._pixels[index] === number)) {
  3286. return true;
  3287. }
  3288. if (isNaN(number)) {
  3289. return false;
  3290. }
  3291. this._pixels[index] = number;
  3292. this._setType(index, PrimitiveThickness.Pixel);
  3293. if (emitChanged) {
  3294. this.onChangeCallback();
  3295. }
  3296. return true;
  3297. }
  3298. };
  3299. PrimitiveThickness.prototype._setPixels = function (value, index, emitChanged) {
  3300. // Round the value because, well, it's the thing to do! Otherwise we'll have sub-pixel stuff, and the no change comparison just below will almost never work for PrimitiveThickness values inside a hierarchy of Primitives
  3301. value = Math.round(value);
  3302. if (this._isType(index, PrimitiveThickness.Pixel) && this._pixels[index] === value) {
  3303. return;
  3304. }
  3305. this._setType(index, PrimitiveThickness.Pixel);
  3306. this._pixels[index] = value;
  3307. if (emitChanged) {
  3308. this.onChangeCallback();
  3309. }
  3310. };
  3311. PrimitiveThickness.prototype._setPercentage = function (value, index, emitChanged) {
  3312. // Clip Value to bounds
  3313. value = Math.min(1, value);
  3314. value = Math.max(0, value);
  3315. value = Math.round(value * 100) / 100; // 0.01 precision
  3316. if (this._isType(index, PrimitiveThickness.Percentage) && this._percentages[index] === value) {
  3317. return;
  3318. }
  3319. this._setType(index, PrimitiveThickness.Percentage);
  3320. this._percentages[index] = value;
  3321. if (emitChanged) {
  3322. this.onChangeCallback();
  3323. }
  3324. };
  3325. PrimitiveThickness.prototype._getStringValue = function (index) {
  3326. var f = (this._flags >> (index * 4)) & 0xF;
  3327. switch (f) {
  3328. case PrimitiveThickness.Auto:
  3329. return "auto";
  3330. case PrimitiveThickness.Pixel:
  3331. return this._pixels[index] + "px";
  3332. case PrimitiveThickness.Percentage:
  3333. return this._percentages[index] * 100 + "%";
  3334. case PrimitiveThickness.Inherit:
  3335. return "inherit";
  3336. }
  3337. return "";
  3338. };
  3339. PrimitiveThickness.prototype._isType = function (index, type) {
  3340. var f = (this._flags >> (index * 4)) & 0xF;
  3341. return f === type;
  3342. };
  3343. PrimitiveThickness.prototype._getType = function (index, processInherit) {
  3344. var t = (this._flags >> (index * 4)) & 0xF;
  3345. if (processInherit && (t === PrimitiveThickness.Inherit)) {
  3346. var p = this._parentAccess();
  3347. if (p) {
  3348. return p._getType(index, true);
  3349. }
  3350. return PrimitiveThickness.Auto;
  3351. }
  3352. return t;
  3353. };
  3354. PrimitiveThickness.prototype._setType = function (index, type) {
  3355. this._flags &= ~(0xF << (index * 4));
  3356. this._flags |= type << (index * 4);
  3357. };
  3358. PrimitiveThickness.prototype.setTop = function (value) {
  3359. if (typeof value === "string") {
  3360. this._setStringValue(value, 0, true);
  3361. }
  3362. else {
  3363. this.topPixels = value;
  3364. }
  3365. };
  3366. PrimitiveThickness.prototype.setLeft = function (value) {
  3367. if (typeof value === "string") {
  3368. this._setStringValue(value, 1, true);
  3369. }
  3370. else {
  3371. this.leftPixels = value;
  3372. }
  3373. };
  3374. PrimitiveThickness.prototype.setRight = function (value) {
  3375. if (typeof value === "string") {
  3376. this._setStringValue(value, 2, true);
  3377. }
  3378. else {
  3379. this.rightPixels = value;
  3380. }
  3381. };
  3382. PrimitiveThickness.prototype.setBottom = function (value) {
  3383. if (typeof value === "string") {
  3384. this._setStringValue(value, 3, true);
  3385. }
  3386. else {
  3387. this.bottomPixels = value;
  3388. }
  3389. };
  3390. Object.defineProperty(PrimitiveThickness.prototype, "top", {
  3391. /**
  3392. * Get/set the top thickness. Possible values are: 'auto', 'inherit', 'XX%' for percentage, 'XXpx' or 'XX' for pixels.
  3393. */
  3394. get: function () {
  3395. return this._getStringValue(0);
  3396. },
  3397. set: function (value) {
  3398. this._setStringValue(value, 0, true);
  3399. },
  3400. enumerable: true,
  3401. configurable: true
  3402. });
  3403. Object.defineProperty(PrimitiveThickness.prototype, "left", {
  3404. /**
  3405. * Get/set the left thickness. Possible values are: 'auto', 'inherit', 'XX%' for percentage, 'XXpx' or 'XX' for pixels.
  3406. */
  3407. get: function () {
  3408. return this._getStringValue(1);
  3409. },
  3410. set: function (value) {
  3411. this._setStringValue(value, 1, true);
  3412. },
  3413. enumerable: true,
  3414. configurable: true
  3415. });
  3416. Object.defineProperty(PrimitiveThickness.prototype, "right", {
  3417. /**
  3418. * Get/set the right thickness. Possible values are: 'auto', 'inherit', 'XX%' for percentage, 'XXpx' or 'XX' for pixels.
  3419. */
  3420. get: function () {
  3421. return this._getStringValue(2);
  3422. },
  3423. set: function (value) {
  3424. this._setStringValue(value, 2, true);
  3425. },
  3426. enumerable: true,
  3427. configurable: true
  3428. });
  3429. Object.defineProperty(PrimitiveThickness.prototype, "bottom", {
  3430. /**
  3431. * Get/set the bottom thickness. Possible values are: 'auto', 'inherit', 'XX%' for percentage, 'XXpx' or 'XX' for pixels.
  3432. */
  3433. get: function () {
  3434. return this._getStringValue(3);
  3435. },
  3436. set: function (value) {
  3437. this._setStringValue(value, 3, true);
  3438. },
  3439. enumerable: true,
  3440. configurable: true
  3441. });
  3442. Object.defineProperty(PrimitiveThickness.prototype, "topPixels", {
  3443. /**
  3444. * Get/set the top thickness in pixel.
  3445. */
  3446. get: function () {
  3447. return this._pixels[0];
  3448. },
  3449. set: function (value) {
  3450. this._setPixels(value, 0, true);
  3451. },
  3452. enumerable: true,
  3453. configurable: true
  3454. });
  3455. Object.defineProperty(PrimitiveThickness.prototype, "leftPixels", {
  3456. /**
  3457. * Get/set the left thickness in pixel.
  3458. */
  3459. get: function () {
  3460. return this._pixels[1];
  3461. },
  3462. set: function (value) {
  3463. this._setPixels(value, 1, true);
  3464. },
  3465. enumerable: true,
  3466. configurable: true
  3467. });
  3468. Object.defineProperty(PrimitiveThickness.prototype, "rightPixels", {
  3469. /**
  3470. * Get/set the right thickness in pixel.
  3471. */
  3472. get: function () {
  3473. return this._pixels[2];
  3474. },
  3475. set: function (value) {
  3476. this._setPixels(value, 2, true);
  3477. },
  3478. enumerable: true,
  3479. configurable: true
  3480. });
  3481. Object.defineProperty(PrimitiveThickness.prototype, "bottomPixels", {
  3482. /**
  3483. * Get/set the bottom thickness in pixel.
  3484. */
  3485. get: function () {
  3486. return this._pixels[3];
  3487. },
  3488. set: function (value) {
  3489. this._setPixels(value, 3, true);
  3490. },
  3491. enumerable: true,
  3492. configurable: true
  3493. });
  3494. Object.defineProperty(PrimitiveThickness.prototype, "topPercentage", {
  3495. /**
  3496. * Get/set the top thickness in percentage.
  3497. * The get will return a valid value only if the edge type is percentage.
  3498. * The Set will change the edge mode if needed
  3499. */
  3500. get: function () {
  3501. return this._percentages[0];
  3502. },
  3503. set: function (value) {
  3504. this._setPercentage(value, 0, true);
  3505. },
  3506. enumerable: true,
  3507. configurable: true
  3508. });
  3509. Object.defineProperty(PrimitiveThickness.prototype, "leftPercentage", {
  3510. /**
  3511. * Get/set the left thickness in percentage.
  3512. * The get will return a valid value only if the edge mode is percentage.
  3513. * The Set will change the edge mode if needed
  3514. */
  3515. get: function () {
  3516. return this._percentages[1];
  3517. },
  3518. set: function (value) {
  3519. this._setPercentage(value, 1, true);
  3520. },
  3521. enumerable: true,
  3522. configurable: true
  3523. });
  3524. Object.defineProperty(PrimitiveThickness.prototype, "rightPercentage", {
  3525. /**
  3526. * Get/set the right thickness in percentage.
  3527. * The get will return a valid value only if the edge mode is percentage.
  3528. * The Set will change the edge mode if needed
  3529. */
  3530. get: function () {
  3531. return this._percentages[2];
  3532. },
  3533. set: function (value) {
  3534. this._setPercentage(value, 2, true);
  3535. },
  3536. enumerable: true,
  3537. configurable: true
  3538. });
  3539. Object.defineProperty(PrimitiveThickness.prototype, "bottomPercentage", {
  3540. /**
  3541. * Get/set the bottom thickness in percentage.
  3542. * The get will return a valid value only if the edge mode is percentage.
  3543. * The Set will change the edge mode if needed
  3544. */
  3545. get: function () {
  3546. return this._percentages[3];
  3547. },
  3548. set: function (value) {
  3549. this._setPercentage(value, 3, true);
  3550. },
  3551. enumerable: true,
  3552. configurable: true
  3553. });
  3554. Object.defineProperty(PrimitiveThickness.prototype, "topMode", {
  3555. /**
  3556. * Get/set the top mode. The setter shouldn't be used, other setters with value should be preferred
  3557. */
  3558. get: function () {
  3559. return this._getType(0, false);
  3560. },
  3561. set: function (mode) {
  3562. this._setType(0, mode);
  3563. },
  3564. enumerable: true,
  3565. configurable: true
  3566. });
  3567. Object.defineProperty(PrimitiveThickness.prototype, "leftMode", {
  3568. /**
  3569. * Get/set the left mode. The setter shouldn't be used, other setters with value should be preferred
  3570. */
  3571. get: function () {
  3572. return this._getType(1, false);
  3573. },
  3574. set: function (mode) {
  3575. this._setType(1, mode);
  3576. },
  3577. enumerable: true,
  3578. configurable: true
  3579. });
  3580. Object.defineProperty(PrimitiveThickness.prototype, "rightMode", {
  3581. /**
  3582. * Get/set the right mode. The setter shouldn't be used, other setters with value should be preferred
  3583. */
  3584. get: function () {
  3585. return this._getType(2, false);
  3586. },
  3587. set: function (mode) {
  3588. this._setType(2, mode);
  3589. },
  3590. enumerable: true,
  3591. configurable: true
  3592. });
  3593. Object.defineProperty(PrimitiveThickness.prototype, "bottomMode", {
  3594. /**
  3595. * Get/set the bottom mode. The setter shouldn't be used, other setters with value should be preferred
  3596. */
  3597. get: function () {
  3598. return this._getType(3, false);
  3599. },
  3600. set: function (mode) {
  3601. this._setType(3, mode);
  3602. },
  3603. enumerable: true,
  3604. configurable: true
  3605. });
  3606. Object.defineProperty(PrimitiveThickness.prototype, "isDefault", {
  3607. get: function () {
  3608. return this._flags === 0x1111;
  3609. },
  3610. enumerable: true,
  3611. configurable: true
  3612. });
  3613. PrimitiveThickness.prototype._computePixels = function (index, sourceArea, emitChanged) {
  3614. var type = this._getType(index, false);
  3615. if (type === PrimitiveThickness.Inherit) {
  3616. this._parentAccess()._computePixels(index, sourceArea, emitChanged);
  3617. return;
  3618. }
  3619. if (type !== PrimitiveThickness.Percentage) {
  3620. return;
  3621. }
  3622. var pixels = ((index === 0 || index === 3) ? sourceArea.height : sourceArea.width) * this._percentages[index];
  3623. this._pixels[index] = pixels;
  3624. if (emitChanged) {
  3625. this.onChangeCallback();
  3626. }
  3627. };
  3628. PrimitiveThickness.prototype.onChangeCallback = function () {
  3629. if (this._changedCallback) {
  3630. this._changedCallback();
  3631. }
  3632. };
  3633. /**
  3634. * Compute the positioning/size of an area considering the thickness of this object and a given alignment
  3635. * @param sourceArea the source area where the content must be sized/positioned
  3636. * @param contentSize the content size to position/resize
  3637. * @param alignment the alignment setting
  3638. * @param dstOffset the position of the content, x, y, z, w are left, bottom, right, top
  3639. * @param dstArea the new size of the content
  3640. */
  3641. PrimitiveThickness.prototype.computeWithAlignment = function (sourceArea, contentSize, alignment, dstOffset, dstArea, computeLayoutArea) {
  3642. if (computeLayoutArea === void 0) { computeLayoutArea = false; }
  3643. // Fetch some data
  3644. var topType = this._getType(0, true);
  3645. var leftType = this._getType(1, true);
  3646. var rightType = this._getType(2, true);
  3647. var bottomType = this._getType(3, true);
  3648. var hasWidth = contentSize && (contentSize.width != null);
  3649. var hasHeight = contentSize && (contentSize.height != null);
  3650. var width = hasWidth ? contentSize.width : 0;
  3651. var height = hasHeight ? contentSize.height : 0;
  3652. var isTopAuto = topType === PrimitiveThickness.Auto;
  3653. var isLeftAuto = leftType === PrimitiveThickness.Auto;
  3654. var isRightAuto = rightType === PrimitiveThickness.Auto;
  3655. var isBottomAuto = bottomType === PrimitiveThickness.Auto;
  3656. switch (alignment.horizontal) {
  3657. case PrimitiveAlignment.AlignLeft:
  3658. {
  3659. if (isLeftAuto) {
  3660. dstOffset.x = 0;
  3661. }
  3662. else {
  3663. this._computePixels(1, sourceArea, true);
  3664. dstOffset.x = this.leftPixels;
  3665. }
  3666. dstArea.width = width;
  3667. if (computeLayoutArea) {
  3668. dstArea.width += this.leftPixels;
  3669. }
  3670. dstOffset.z = sourceArea.width - (dstOffset.x + width);
  3671. break;
  3672. }
  3673. case PrimitiveAlignment.AlignRight:
  3674. {
  3675. if (isRightAuto) {
  3676. dstOffset.x = Math.round(sourceArea.width - width);
  3677. }
  3678. else {
  3679. this._computePixels(2, sourceArea, true);
  3680. dstOffset.x = Math.round(sourceArea.width - (width + this.rightPixels));
  3681. }
  3682. dstArea.width = width;
  3683. if (computeLayoutArea) {
  3684. dstArea.width += this.rightPixels;
  3685. }
  3686. dstOffset.z = this.rightPixels;
  3687. break;
  3688. }
  3689. case PrimitiveAlignment.AlignStretch:
  3690. {
  3691. if (isLeftAuto) {
  3692. dstOffset.x = 0;
  3693. }
  3694. else {
  3695. this._computePixels(1, sourceArea, true);
  3696. dstOffset.x = this.leftPixels;
  3697. }
  3698. var right = 0;
  3699. if (!isRightAuto) {
  3700. this._computePixels(2, sourceArea, true);
  3701. right = this.rightPixels;
  3702. }
  3703. dstArea.width = sourceArea.width - (dstOffset.x + right);
  3704. dstOffset.z = this.rightPixels;
  3705. break;
  3706. }
  3707. case PrimitiveAlignment.AlignCenter:
  3708. {
  3709. if (!isLeftAuto) {
  3710. this._computePixels(1, sourceArea, true);
  3711. }
  3712. if (!isRightAuto) {
  3713. this._computePixels(2, sourceArea, true);
  3714. }
  3715. var offset = (isLeftAuto ? 0 : this.leftPixels) - (isRightAuto ? 0 : this.rightPixels);
  3716. dstOffset.x = Math.round(((sourceArea.width - width) / 2) + offset);
  3717. dstArea.width = width;
  3718. dstOffset.z = sourceArea.width - (dstOffset.x + width);
  3719. break;
  3720. }
  3721. }
  3722. switch (alignment.vertical) {
  3723. case PrimitiveAlignment.AlignTop:
  3724. {
  3725. if (isTopAuto) {
  3726. dstOffset.y = sourceArea.height - height;
  3727. }
  3728. else {
  3729. this._computePixels(0, sourceArea, true);
  3730. dstOffset.y = Math.round(sourceArea.height - (height + this.topPixels));
  3731. }
  3732. dstArea.height = height;
  3733. if (computeLayoutArea) {
  3734. dstArea.height += this.topPixels;
  3735. }
  3736. dstOffset.w = this.topPixels;
  3737. break;
  3738. }
  3739. case PrimitiveAlignment.AlignBottom:
  3740. {
  3741. if (isBottomAuto) {
  3742. dstOffset.y = 0;
  3743. }
  3744. else {
  3745. this._computePixels(3, sourceArea, true);
  3746. dstOffset.y = this.bottomPixels;
  3747. }
  3748. dstArea.height = height;
  3749. if (computeLayoutArea) {
  3750. dstArea.height += this.bottomPixels;
  3751. }
  3752. dstOffset.w = sourceArea.height - (dstOffset.y + height);
  3753. break;
  3754. }
  3755. case PrimitiveAlignment.AlignStretch:
  3756. {
  3757. if (isBottomAuto) {
  3758. dstOffset.y = 0;
  3759. }
  3760. else {
  3761. this._computePixels(3, sourceArea, true);
  3762. dstOffset.y = this.bottomPixels;
  3763. }
  3764. var top_1 = 0;
  3765. if (!isTopAuto) {
  3766. this._computePixels(0, sourceArea, true);
  3767. top_1 = this.topPixels;
  3768. }
  3769. dstArea.height = sourceArea.height - (dstOffset.y + top_1);
  3770. dstOffset.w = this.topPixels;
  3771. break;
  3772. }
  3773. case PrimitiveAlignment.AlignCenter:
  3774. {
  3775. if (!isTopAuto) {
  3776. this._computePixels(0, sourceArea, true);
  3777. }
  3778. if (!isBottomAuto) {
  3779. this._computePixels(3, sourceArea, true);
  3780. }
  3781. var offset = (isBottomAuto ? 0 : this.bottomPixels) - (isTopAuto ? 0 : this.topPixels);
  3782. dstOffset.y = Math.round(((sourceArea.height - height) / 2) + offset);
  3783. dstArea.height = height;
  3784. dstOffset.w = sourceArea.height - (dstOffset.y + height);
  3785. break;
  3786. }
  3787. }
  3788. };
  3789. /**
  3790. * Compute an area and its position considering this thickness properties based on a given source area
  3791. * @param sourceArea the source area
  3792. * @param dstOffset the position of the resulting area
  3793. * @param dstArea the size of the resulting area
  3794. */
  3795. PrimitiveThickness.prototype.compute = function (sourceArea, dstOffset, dstArea) {
  3796. this._computePixels(0, sourceArea, true);
  3797. this._computePixels(1, sourceArea, true);
  3798. this._computePixels(2, sourceArea, true);
  3799. this._computePixels(3, sourceArea, true);
  3800. dstOffset.x = this.leftPixels;
  3801. dstArea.width = sourceArea.width - (dstOffset.x + this.rightPixels);
  3802. dstOffset.y = this.bottomPixels;
  3803. dstArea.height = sourceArea.height - (dstOffset.y + this.topPixels);
  3804. };
  3805. /**
  3806. * Compute an area considering this thickness properties based on a given source area
  3807. * @param sourceArea the source area
  3808. * @param result the resulting area
  3809. */
  3810. PrimitiveThickness.prototype.computeArea = function (sourceArea, result) {
  3811. this._computePixels(0, sourceArea, true);
  3812. this._computePixels(1, sourceArea, true);
  3813. this._computePixels(2, sourceArea, true);
  3814. this._computePixels(3, sourceArea, true);
  3815. result.width = this.leftPixels + sourceArea.width + this.rightPixels;
  3816. result.height = this.bottomPixels + sourceArea.height + this.topPixels;
  3817. };
  3818. PrimitiveThickness.prototype.enlarge = function (sourceArea, dstOffset, enlargedArea) {
  3819. this._computePixels(0, sourceArea, true);
  3820. this._computePixels(1, sourceArea, true);
  3821. this._computePixels(2, sourceArea, true);
  3822. this._computePixels(3, sourceArea, true);
  3823. dstOffset.x = this.leftPixels;
  3824. enlargedArea.width = sourceArea.width + (dstOffset.x + this.rightPixels);
  3825. dstOffset.y = this.bottomPixels;
  3826. enlargedArea.height = sourceArea.height + (dstOffset.y + this.topPixels);
  3827. };
  3828. PrimitiveThickness.Auto = 0x1;
  3829. PrimitiveThickness.Inherit = 0x2;
  3830. PrimitiveThickness.Percentage = 0x4;
  3831. PrimitiveThickness.Pixel = 0x8;
  3832. PrimitiveThickness = __decorate([
  3833. BABYLON.className("PrimitiveThickness", "BABYLON")
  3834. ], PrimitiveThickness);
  3835. return PrimitiveThickness;
  3836. }());
  3837. BABYLON.PrimitiveThickness = PrimitiveThickness;
  3838. /**
  3839. * Main class used for the Primitive Intersection API
  3840. */
  3841. var IntersectInfo2D = (function () {
  3842. function IntersectInfo2D() {
  3843. this.findFirstOnly = false;
  3844. this.intersectHidden = false;
  3845. this.pickPosition = BABYLON.Vector2.Zero();
  3846. }
  3847. Object.defineProperty(IntersectInfo2D.prototype, "isIntersected", {
  3848. /**
  3849. * true if at least one primitive intersected during the test
  3850. */
  3851. get: function () {
  3852. return this.intersectedPrimitives && this.intersectedPrimitives.length > 0;
  3853. },
  3854. enumerable: true,
  3855. configurable: true
  3856. });
  3857. IntersectInfo2D.prototype.isPrimIntersected = function (prim) {
  3858. for (var _i = 0, _a = this.intersectedPrimitives; _i < _a.length; _i++) {
  3859. var cur = _a[_i];
  3860. if (cur.prim === prim) {
  3861. return cur.intersectionLocation;
  3862. }
  3863. }
  3864. return null;
  3865. };
  3866. // Internals, don't use
  3867. IntersectInfo2D.prototype._exit = function (firstLevel) {
  3868. if (firstLevel) {
  3869. this._globalPickPosition = null;
  3870. }
  3871. };
  3872. return IntersectInfo2D;
  3873. }());
  3874. BABYLON.IntersectInfo2D = IntersectInfo2D;
  3875. var Prim2DBase = (function (_super) {
  3876. __extends(Prim2DBase, _super);
  3877. function Prim2DBase(settings) {
  3878. // Avoid checking every time if the object exists
  3879. if (settings == null) {
  3880. settings = {};
  3881. }
  3882. // BASE CLASS CALL
  3883. _super.call(this);
  3884. // Fetch the owner, parent. There're many ways to do it and we can end up with nothing for both
  3885. var owner;
  3886. var parent;
  3887. if (Prim2DBase._isCanvasInit) {
  3888. owner = this;
  3889. parent = null;
  3890. this._canvasPreInit(settings);
  3891. }
  3892. else {
  3893. if (settings.parent != null) {
  3894. parent = settings.parent;
  3895. owner = settings.parent.owner;
  3896. if (!owner) {
  3897. throw new Error("Parent " + parent.id + " of " + settings.id + " doesn't have a valid owner!");
  3898. }
  3899. if (!(this instanceof BABYLON.Group2D) && !(this instanceof BABYLON.Sprite2D && settings.id != null && settings.id.indexOf("__cachedSpriteOfGroup__") === 0) && (owner.cachingStrategy === BABYLON.Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS) && (parent === owner)) {
  3900. throw new Error("Can't create a primitive with the canvas as direct parent when the caching strategy is TOPLEVELGROUPS. You need to create a Group below the canvas and use it as the parent for the primitive");
  3901. }
  3902. }
  3903. }
  3904. // Fields initialization
  3905. this._layoutEngine = BABYLON.CanvasLayoutEngine.Singleton;
  3906. this._size = null; //Size.Zero();
  3907. this._scale = new BABYLON.Vector2(1, 1);
  3908. this._actualSize = null;
  3909. this._boundingSize = BABYLON.Size.Zero();
  3910. this._layoutArea = BABYLON.Size.Zero();
  3911. this._layoutAreaPos = null;
  3912. this._layoutBoundingInfo = null;
  3913. this._marginOffset = BABYLON.Vector4.Zero();
  3914. this._paddingOffset = BABYLON.Vector4.Zero();
  3915. this._parentPaddingOffset = BABYLON.Vector2.Zero();
  3916. this._parentContentArea = BABYLON.Size.Zero();
  3917. this._lastAutoSizeArea = BABYLON.Size.Zero();
  3918. this._contentArea = new BABYLON.Size(null, null);
  3919. this._pointerEventObservable = new BABYLON.Observable();
  3920. this._boundingInfo = new BABYLON.BoundingInfo2D();
  3921. this._owner = owner;
  3922. this._parent = null;
  3923. this._margin = null;
  3924. this._padding = null;
  3925. this._marginAlignment = null;
  3926. this._id = settings.id;
  3927. this._children = new Array();
  3928. this._localTransform = new BABYLON.Matrix();
  3929. this._globalTransform = null;
  3930. this._invGlobalTransform = null;
  3931. this._globalTransformProcessStep = 0;
  3932. this._globalTransformStep = 0;
  3933. this._renderGroup = null;
  3934. this._primLinearPosition = 0;
  3935. this._manualZOrder = null;
  3936. this._zOrder = 0;
  3937. this._zMax = 0;
  3938. this._firstZDirtyIndex = Prim2DBase._bigInt;
  3939. this._actualOpacity = 0;
  3940. this._actualScale = BABYLON.Vector2.Zero();
  3941. this._displayDebugAreas = false;
  3942. this._debugAreaGroup = null;
  3943. var isPickable = true;
  3944. var isContainer = true;
  3945. if (settings.isPickable !== undefined) {
  3946. isPickable = settings.isPickable;
  3947. }
  3948. if (settings.isContainer !== undefined) {
  3949. isContainer = settings.isContainer;
  3950. }
  3951. if (settings.dontInheritParentScale) {
  3952. this._setFlags(BABYLON.SmartPropertyPrim.flagDontInheritParentScale);
  3953. }
  3954. this._setFlags((isPickable ? BABYLON.SmartPropertyPrim.flagIsPickable : 0) | BABYLON.SmartPropertyPrim.flagBoundingInfoDirty | BABYLON.SmartPropertyPrim.flagActualOpacityDirty | (isContainer ? BABYLON.SmartPropertyPrim.flagIsContainer : 0) | BABYLON.SmartPropertyPrim.flagActualScaleDirty | BABYLON.SmartPropertyPrim.flagLayoutBoundingInfoDirty);
  3955. if (settings.opacity != null) {
  3956. this._opacity = settings.opacity;
  3957. }
  3958. else {
  3959. this._opacity = 1;
  3960. }
  3961. this._updateRenderMode();
  3962. if (settings.childrenFlatZOrder) {
  3963. this._setFlags(BABYLON.SmartPropertyPrim.flagChildrenFlatZOrder);
  3964. }
  3965. // If the parent is given, initialize the hierarchy/owner related data
  3966. if (parent != null) {
  3967. parent.addChild(this);
  3968. this._hierarchyDepth = parent._hierarchyDepth + 1;
  3969. this._patchHierarchy(parent.owner);
  3970. }
  3971. // If it's a group, detect its own states
  3972. if (this.owner && this instanceof BABYLON.Group2D) {
  3973. var group = this;
  3974. group.detectGroupStates();
  3975. }
  3976. // Time to insert children if some are specified
  3977. if (settings.children != null) {
  3978. for (var _i = 0, _a = settings.children; _i < _a.length; _i++) {
  3979. var child = _a[_i];
  3980. this.addChild(child);
  3981. // Good time to patch the hierarchy, it won't go very far if there's no need to
  3982. if (this.owner != null) {
  3983. child._patchHierarchy(this.owner);
  3984. }
  3985. }
  3986. }
  3987. if (settings.zOrder != null) {
  3988. this.zOrder = settings.zOrder;
  3989. }
  3990. // Set the model related properties
  3991. if (settings.position != null) {
  3992. this.position = settings.position;
  3993. }
  3994. else if (settings.x != null || settings.y != null) {
  3995. this.position = new BABYLON.Vector2(settings.x || 0, settings.y || 0);
  3996. }
  3997. else {
  3998. this._position = null;
  3999. }
  4000. this.rotation = (settings.rotation == null) ? 0 : settings.rotation;
  4001. if (settings.scale != null) {
  4002. this.scale = settings.scale;
  4003. }
  4004. else {
  4005. if (settings.scaleX != null) {
  4006. this.scaleX = settings.scaleX;
  4007. }
  4008. if (settings.scaleY != null) {
  4009. this.scaleY = settings.scaleY;
  4010. }
  4011. }
  4012. this.levelVisible = (settings.isVisible == null) ? true : settings.isVisible;
  4013. this.origin = settings.origin || new BABYLON.Vector2(0.5, 0.5);
  4014. // Layout Engine
  4015. if (settings.layoutEngine != null) {
  4016. if (typeof settings.layoutEngine === "string") {
  4017. var name_1 = settings.layoutEngine.toLocaleLowerCase().trim();
  4018. if (name_1 === "canvas" || name_1 === "canvaslayoutengine") {
  4019. this.layoutEngine = BABYLON.CanvasLayoutEngine.Singleton;
  4020. }
  4021. else if (name_1.indexOf("stackpanel") === 0 || name_1.indexOf("horizontalstackpanel") === 0) {
  4022. this.layoutEngine = BABYLON.StackPanelLayoutEngine.Horizontal;
  4023. }
  4024. else if (name_1.indexOf("verticalstackpanel") === 0) {
  4025. this.layoutEngine = BABYLON.StackPanelLayoutEngine.Vertical;
  4026. }
  4027. }
  4028. else if (settings.layoutEngine instanceof BABYLON.LayoutEngineBase) {
  4029. this.layoutEngine = settings.layoutEngine;
  4030. }
  4031. }
  4032. // Set the layout/margin stuffs
  4033. if (settings.marginTop) {
  4034. this.margin.setTop(settings.marginTop);
  4035. }
  4036. if (settings.marginLeft) {
  4037. this.margin.setLeft(settings.marginLeft);
  4038. }
  4039. if (settings.marginRight) {
  4040. this.margin.setRight(settings.marginRight);
  4041. }
  4042. if (settings.marginBottom) {
  4043. this.margin.setBottom(settings.marginBottom);
  4044. }
  4045. if (settings.margin) {
  4046. if (typeof settings.margin === "string") {
  4047. this.margin.fromString(settings.margin);
  4048. }
  4049. else {
  4050. this.margin.fromUniformPixels(settings.margin);
  4051. }
  4052. }
  4053. if (settings.marginHAlignment) {
  4054. this.marginAlignment.horizontal = settings.marginHAlignment;
  4055. }
  4056. if (settings.marginVAlignment) {
  4057. this.marginAlignment.vertical = settings.marginVAlignment;
  4058. }
  4059. if (settings.marginAlignment) {
  4060. this.marginAlignment.fromString(settings.marginAlignment);
  4061. }
  4062. if (settings.paddingTop) {
  4063. this.padding.setTop(settings.paddingTop);
  4064. }
  4065. if (settings.paddingLeft) {
  4066. this.padding.setLeft(settings.paddingLeft);
  4067. }
  4068. if (settings.paddingRight) {
  4069. this.padding.setRight(settings.paddingRight);
  4070. }
  4071. if (settings.paddingBottom) {
  4072. this.padding.setBottom(settings.paddingBottom);
  4073. }
  4074. if (settings.padding) {
  4075. this.padding.fromString(settings.padding);
  4076. }
  4077. // Dirty layout and positioning
  4078. this._parentLayoutDirty();
  4079. this._positioningDirty();
  4080. }
  4081. Object.defineProperty(Prim2DBase.prototype, "actionManager", {
  4082. get: function () {
  4083. if (!this._actionManager) {
  4084. this._actionManager = new BABYLON.ActionManager(this.owner.scene);
  4085. }
  4086. return this._actionManager;
  4087. },
  4088. enumerable: true,
  4089. configurable: true
  4090. });
  4091. /**
  4092. * From 'this' primitive, traverse up (from parent to parent) until the given predicate is true
  4093. * @param predicate the predicate to test on each parent
  4094. * @return the first primitive where the predicate was successful
  4095. */
  4096. Prim2DBase.prototype.traverseUp = function (predicate) {
  4097. var p = this;
  4098. while (p != null) {
  4099. if (predicate(p)) {
  4100. return p;
  4101. }
  4102. p = p._parent;
  4103. }
  4104. return null;
  4105. };
  4106. Object.defineProperty(Prim2DBase.prototype, "owner", {
  4107. /**
  4108. * Retrieve the owner Canvas2D
  4109. */
  4110. get: function () {
  4111. return this._owner;
  4112. },
  4113. enumerable: true,
  4114. configurable: true
  4115. });
  4116. Object.defineProperty(Prim2DBase.prototype, "parent", {
  4117. /**
  4118. * Get the parent primitive (can be the Canvas, only the Canvas has no parent)
  4119. */
  4120. get: function () {
  4121. return this._parent;
  4122. },
  4123. enumerable: true,
  4124. configurable: true
  4125. });
  4126. Object.defineProperty(Prim2DBase.prototype, "children", {
  4127. /**
  4128. * The array of direct children primitives
  4129. */
  4130. get: function () {
  4131. return this._children;
  4132. },
  4133. enumerable: true,
  4134. configurable: true
  4135. });
  4136. Object.defineProperty(Prim2DBase.prototype, "id", {
  4137. /**
  4138. * The identifier of this primitive, may not be unique, it's for information purpose only
  4139. */
  4140. get: function () {
  4141. return this._id;
  4142. },
  4143. enumerable: true,
  4144. configurable: true
  4145. });
  4146. Object.defineProperty(Prim2DBase.prototype, "actualPosition", {
  4147. get: function () {
  4148. if (this._actualPosition != null) {
  4149. return this._actualPosition;
  4150. }
  4151. if (this._position != null) {
  4152. return this._position;
  4153. }
  4154. // At least return 0,0, we can't return null on actualPosition
  4155. return Prim2DBase._nullPosition;
  4156. },
  4157. /**
  4158. * DO NOT INVOKE for internal purpose only
  4159. */
  4160. set: function (val) {
  4161. this._actualPosition = val;
  4162. },
  4163. enumerable: true,
  4164. configurable: true
  4165. });
  4166. Object.defineProperty(Prim2DBase.prototype, "actualX", {
  4167. /**
  4168. * Shortcut to actualPosition.x
  4169. */
  4170. get: function () {
  4171. return this.actualPosition.x;
  4172. },
  4173. set: function (val) {
  4174. this._actualPosition.x = val;
  4175. this._triggerPropertyChanged(Prim2DBase.actualPositionProperty, this._actualPosition);
  4176. },
  4177. enumerable: true,
  4178. configurable: true
  4179. });
  4180. Object.defineProperty(Prim2DBase.prototype, "actualY", {
  4181. /**
  4182. * Shortcut to actualPosition.y
  4183. */
  4184. get: function () {
  4185. return this.actualPosition.y;
  4186. },
  4187. set: function (val) {
  4188. this._actualPosition.y = val;
  4189. this._triggerPropertyChanged(Prim2DBase.actualPositionProperty, this._actualPosition);
  4190. },
  4191. enumerable: true,
  4192. configurable: true
  4193. });
  4194. Object.defineProperty(Prim2DBase.prototype, "position", {
  4195. /**
  4196. * Position of the primitive, relative to its parent.
  4197. * BEWARE: if you change only position.x or y it won't trigger a property change and you won't have the expected behavior.
  4198. * Use this property to set a new Vector2 object, otherwise to change only the x/y use Prim2DBase.x or y properties.
  4199. * Setting this property may have no effect is specific alignment are in effect.
  4200. */
  4201. get: function () {
  4202. if (!this._position) {
  4203. this._position = BABYLON.Vector2.Zero();
  4204. }
  4205. return this._position;
  4206. },
  4207. set: function (value) {
  4208. if (!this._checkPositionChange()) {
  4209. return;
  4210. }
  4211. this._position = value;
  4212. this._triggerPropertyChanged(Prim2DBase.actualPositionProperty, value);
  4213. },
  4214. enumerable: true,
  4215. configurable: true
  4216. });
  4217. Object.defineProperty(Prim2DBase.prototype, "x", {
  4218. /**
  4219. * Direct access to the position.x value of the primitive
  4220. * Use this property when you only want to change one component of the position property
  4221. */
  4222. get: function () {
  4223. if (!this._position) {
  4224. return null;
  4225. }
  4226. return this._position.x;
  4227. },
  4228. set: function (value) {
  4229. if (!this._checkPositionChange()) {
  4230. return;
  4231. }
  4232. if (!this._position) {
  4233. this._position = BABYLON.Vector2.Zero();
  4234. }
  4235. if (this._position.x === value) {
  4236. return;
  4237. }
  4238. this._position.x = value;
  4239. this._triggerPropertyChanged(Prim2DBase.positionProperty, value);
  4240. this._triggerPropertyChanged(Prim2DBase.actualPositionProperty, value);
  4241. },
  4242. enumerable: true,
  4243. configurable: true
  4244. });
  4245. Object.defineProperty(Prim2DBase.prototype, "y", {
  4246. /**
  4247. * Direct access to the position.y value of the primitive
  4248. * Use this property when you only want to change one component of the position property
  4249. */
  4250. get: function () {
  4251. if (!this._position) {
  4252. return null;
  4253. }
  4254. return this._position.y;
  4255. },
  4256. set: function (value) {
  4257. if (!this._checkPositionChange()) {
  4258. return;
  4259. }
  4260. if (!this._position) {
  4261. this._position = BABYLON.Vector2.Zero();
  4262. }
  4263. if (this._position.y === value) {
  4264. return;
  4265. }
  4266. this._position.y = value;
  4267. this._triggerPropertyChanged(Prim2DBase.positionProperty, value);
  4268. this._triggerPropertyChanged(Prim2DBase.actualPositionProperty, value);
  4269. },
  4270. enumerable: true,
  4271. configurable: true
  4272. });
  4273. Object.defineProperty(Prim2DBase.prototype, "size", {
  4274. /**
  4275. * Size of the primitive or its bounding area
  4276. * BEWARE: if you change only size.width or height it won't trigger a property change and you won't have the expected behavior.
  4277. * Use this property to set a new Size object, otherwise to change only the width/height use Prim2DBase.width or height properties.
  4278. */
  4279. get: function () {
  4280. if (!this._size || this._size.width == null || this._size.height == null) {
  4281. if (Prim2DBase.boundinbBoxReentrency) {
  4282. return Prim2DBase.nullSize;
  4283. }
  4284. if (!this._isFlagSet(BABYLON.SmartPropertyPrim.flagBoundingInfoDirty)) {
  4285. return this._boundingSize;
  4286. }
  4287. Prim2DBase.boundinbBoxReentrency = true;
  4288. var b = this.boundingInfo;
  4289. Prim2DBase.boundinbBoxReentrency = false;
  4290. return this._boundingSize;
  4291. }
  4292. return this._size;
  4293. },
  4294. set: function (value) {
  4295. this._size = value;
  4296. },
  4297. enumerable: true,
  4298. configurable: true
  4299. });
  4300. Object.defineProperty(Prim2DBase.prototype, "width", {
  4301. /**
  4302. * Direct access to the size.width value of the primitive
  4303. * Use this property when you only want to change one component of the size property
  4304. */
  4305. get: function () {
  4306. if (!this.size) {
  4307. return null;
  4308. }
  4309. return this.size.width;
  4310. },
  4311. set: function (value) {
  4312. if (this.size && this.size.width === value) {
  4313. return;
  4314. }
  4315. if (!this.size) {
  4316. this.size = new BABYLON.Size(value, 0);
  4317. }
  4318. else {
  4319. this.size.width = value;
  4320. }
  4321. this._triggerPropertyChanged(Prim2DBase.sizeProperty, value);
  4322. this._positioningDirty();
  4323. },
  4324. enumerable: true,
  4325. configurable: true
  4326. });
  4327. Object.defineProperty(Prim2DBase.prototype, "height", {
  4328. /**
  4329. * Direct access to the size.height value of the primitive
  4330. * Use this property when you only want to change one component of the size property
  4331. */
  4332. get: function () {
  4333. if (!this.size) {
  4334. return null;
  4335. }
  4336. return this.size.height;
  4337. },
  4338. set: function (value) {
  4339. if (this.size && this.size.height === value) {
  4340. return;
  4341. }
  4342. if (!this.size) {
  4343. this.size = new BABYLON.Size(0, value);
  4344. }
  4345. else {
  4346. this.size.height = value;
  4347. }
  4348. this._triggerPropertyChanged(Prim2DBase.sizeProperty, value);
  4349. this._positioningDirty();
  4350. },
  4351. enumerable: true,
  4352. configurable: true
  4353. });
  4354. Object.defineProperty(Prim2DBase.prototype, "rotation", {
  4355. get: function () {
  4356. return this._rotation;
  4357. },
  4358. set: function (value) {
  4359. this._rotation = value;
  4360. },
  4361. enumerable: true,
  4362. configurable: true
  4363. });
  4364. Object.defineProperty(Prim2DBase.prototype, "scale", {
  4365. get: function () {
  4366. return this._scale.x;
  4367. },
  4368. set: function (value) {
  4369. this._scale.x = this._scale.y = value;
  4370. this._setFlags(BABYLON.SmartPropertyPrim.flagActualScaleDirty);
  4371. this._spreadActualScaleDirty();
  4372. },
  4373. enumerable: true,
  4374. configurable: true
  4375. });
  4376. Object.defineProperty(Prim2DBase.prototype, "actualSize", {
  4377. /**
  4378. * Return the size of the primitive as it's being rendered into the target.
  4379. * This value may be different of the size property when layout/alignment is used or specific primitive types can implement a custom logic through this property.
  4380. * BEWARE: don't use the setter, it's for internal purpose only
  4381. * Note to implementers: you have to override this property and declare if necessary a @xxxxInstanceLevel decorator
  4382. */
  4383. get: function () {
  4384. if (this._actualSize) {
  4385. return this._actualSize;
  4386. }
  4387. return this._size;
  4388. },
  4389. set: function (value) {
  4390. if (this._actualSize.equals(value)) {
  4391. return;
  4392. }
  4393. this._actualSize = value;
  4394. },
  4395. enumerable: true,
  4396. configurable: true
  4397. });
  4398. Object.defineProperty(Prim2DBase.prototype, "actualWidth", {
  4399. /**
  4400. * Shortcut to actualSize.width
  4401. */
  4402. get: function () {
  4403. return this.actualSize.width;
  4404. },
  4405. set: function (val) {
  4406. this._actualSize.width = val;
  4407. this._triggerPropertyChanged(Prim2DBase.actualSizeProperty, this._actualSize);
  4408. },
  4409. enumerable: true,
  4410. configurable: true
  4411. });
  4412. Object.defineProperty(Prim2DBase.prototype, "actualHeight", {
  4413. /**
  4414. * Shortcut to actualPosition.height
  4415. */
  4416. get: function () {
  4417. return this.actualSize.width;
  4418. },
  4419. set: function (val) {
  4420. this._actualSize.height = val;
  4421. this._triggerPropertyChanged(Prim2DBase.actualPositionProperty, this._actualSize);
  4422. },
  4423. enumerable: true,
  4424. configurable: true
  4425. });
  4426. Object.defineProperty(Prim2DBase.prototype, "actualZOffset", {
  4427. get: function () {
  4428. if (this._manualZOrder != null) {
  4429. return this._manualZOrder;
  4430. }
  4431. if (this._isFlagSet(BABYLON.SmartPropertyPrim.flagZOrderDirty)) {
  4432. this._updateZOrder();
  4433. }
  4434. return (1 - this._zOrder);
  4435. },
  4436. enumerable: true,
  4437. configurable: true
  4438. });
  4439. Object.defineProperty(Prim2DBase.prototype, "minSize", {
  4440. /**
  4441. * Get or set the minimal size the Layout Engine should respect when computing the primitive's actualSize.
  4442. * The Primitive's size won't be less than specified.
  4443. * The default value depends of the Primitive type
  4444. */
  4445. get: function () {
  4446. return this._minSize;
  4447. },
  4448. set: function (value) {
  4449. if (this._minSize && value && this._minSize.equals(value)) {
  4450. return;
  4451. }
  4452. this._minSize = value;
  4453. this._parentLayoutDirty();
  4454. },
  4455. enumerable: true,
  4456. configurable: true
  4457. });
  4458. Object.defineProperty(Prim2DBase.prototype, "maxSize", {
  4459. /**
  4460. * Get or set the maximal size the Layout Engine should respect when computing the primitive's actualSize.
  4461. * The Primitive's size won't be more than specified.
  4462. * The default value depends of the Primitive type
  4463. */
  4464. get: function () {
  4465. return this._maxSize;
  4466. },
  4467. set: function (value) {
  4468. if (this._maxSize && value && this._maxSize.equals(value)) {
  4469. return;
  4470. }
  4471. this._maxSize = value;
  4472. this._parentLayoutDirty();
  4473. },
  4474. enumerable: true,
  4475. configurable: true
  4476. });
  4477. Object.defineProperty(Prim2DBase.prototype, "origin", {
  4478. /**
  4479. * The origin defines the normalized coordinate of the center of the primitive, from the bottom/left corner.
  4480. * The origin is used only to compute transformation of the primitive, it has no meaning in the primitive local frame of reference
  4481. * For instance:
  4482. * 0,0 means the center is bottom/left. Which is the default for Canvas2D instances
  4483. * 0.5,0.5 means the center is at the center of the primitive, which is default of all types of Primitives
  4484. * 0,1 means the center is top/left
  4485. * @returns The normalized center.
  4486. */
  4487. get: function () {
  4488. return this._origin;
  4489. },
  4490. set: function (value) {
  4491. this._origin = value;
  4492. },
  4493. enumerable: true,
  4494. configurable: true
  4495. });
  4496. Object.defineProperty(Prim2DBase.prototype, "levelVisible", {
  4497. get: function () {
  4498. return this._isFlagSet(BABYLON.SmartPropertyPrim.flagLevelVisible);
  4499. },
  4500. set: function (value) {
  4501. this._changeFlags(BABYLON.SmartPropertyPrim.flagLevelVisible, value);
  4502. },
  4503. enumerable: true,
  4504. configurable: true
  4505. });
  4506. Object.defineProperty(Prim2DBase.prototype, "isVisible", {
  4507. get: function () {
  4508. return this._isFlagSet(BABYLON.SmartPropertyPrim.flagIsVisible);
  4509. },
  4510. set: function (value) {
  4511. this._changeFlags(BABYLON.SmartPropertyPrim.flagIsVisible, value);
  4512. },
  4513. enumerable: true,
  4514. configurable: true
  4515. });
  4516. Object.defineProperty(Prim2DBase.prototype, "zOrder", {
  4517. get: function () {
  4518. return this._manualZOrder;
  4519. },
  4520. set: function (value) {
  4521. if (this._manualZOrder === value) {
  4522. return;
  4523. }
  4524. this._manualZOrder = value;
  4525. this.onZOrderChanged();
  4526. if (this._actualZOrderChangedObservable && this._actualZOrderChangedObservable.hasObservers()) {
  4527. this._actualZOrderChangedObservable.notifyObservers(value);
  4528. }
  4529. },
  4530. enumerable: true,
  4531. configurable: true
  4532. });
  4533. Object.defineProperty(Prim2DBase.prototype, "isManualZOrder", {
  4534. get: function () {
  4535. return this._manualZOrder != null;
  4536. },
  4537. enumerable: true,
  4538. configurable: true
  4539. });
  4540. Object.defineProperty(Prim2DBase.prototype, "margin", {
  4541. get: function () {
  4542. var _this = this;
  4543. if (!this._margin) {
  4544. this._margin = new PrimitiveThickness(function () {
  4545. if (!_this.parent) {
  4546. return null;
  4547. }
  4548. return _this.parent.margin;
  4549. }, function () { return _this._positioningDirty(); });
  4550. }
  4551. return this._margin;
  4552. },
  4553. set: function (value) {
  4554. this.margin.copyFrom(value);
  4555. },
  4556. enumerable: true,
  4557. configurable: true
  4558. });
  4559. Object.defineProperty(Prim2DBase.prototype, "_hasMargin", {
  4560. /**
  4561. * Check for both margin and marginAlignment, return true if at least one of them is specified with a non default value
  4562. */
  4563. get: function () {
  4564. return (this._margin !== null && !this._margin.isDefault) || (this._marginAlignment !== null && !this._marginAlignment.isDefault);
  4565. },
  4566. enumerable: true,
  4567. configurable: true
  4568. });
  4569. Object.defineProperty(Prim2DBase.prototype, "padding", {
  4570. get: function () {
  4571. var _this = this;
  4572. if (!this._padding) {
  4573. this._padding = new PrimitiveThickness(function () {
  4574. if (!_this.parent) {
  4575. return null;
  4576. }
  4577. return _this.parent.padding;
  4578. }, function () { return _this._positioningDirty(); });
  4579. }
  4580. return this._padding;
  4581. },
  4582. set: function (value) {
  4583. this.padding.copyFrom(value);
  4584. },
  4585. enumerable: true,
  4586. configurable: true
  4587. });
  4588. Object.defineProperty(Prim2DBase.prototype, "_hasPadding", {
  4589. get: function () {
  4590. return this._padding !== null && !this._padding.isDefault;
  4591. },
  4592. enumerable: true,
  4593. configurable: true
  4594. });
  4595. Object.defineProperty(Prim2DBase.prototype, "marginAlignment", {
  4596. get: function () {
  4597. var _this = this;
  4598. if (!this._marginAlignment) {
  4599. this._marginAlignment = new PrimitiveAlignment(function () { return _this._positioningDirty(); });
  4600. }
  4601. return this._marginAlignment;
  4602. },
  4603. set: function (value) {
  4604. this.marginAlignment.copyFrom(value);
  4605. },
  4606. enumerable: true,
  4607. configurable: true
  4608. });
  4609. Object.defineProperty(Prim2DBase.prototype, "_hasMarginAlignment", {
  4610. /**
  4611. * Check if there a marginAlignment specified (non null and not default)
  4612. */
  4613. get: function () {
  4614. return (this._marginAlignment !== null && !this._marginAlignment.isDefault);
  4615. },
  4616. enumerable: true,
  4617. configurable: true
  4618. });
  4619. Object.defineProperty(Prim2DBase.prototype, "opacity", {
  4620. get: function () {
  4621. return this._opacity;
  4622. },
  4623. set: function (value) {
  4624. if (value < 0) {
  4625. value = 0;
  4626. }
  4627. else if (value > 1) {
  4628. value = 1;
  4629. }
  4630. if (this._opacity === value) {
  4631. return;
  4632. }
  4633. this._opacity = value;
  4634. this._setFlags(BABYLON.SmartPropertyPrim.flagActualOpacityDirty);
  4635. this._spreadActualOpacityChanged();
  4636. this._updateRenderMode();
  4637. },
  4638. enumerable: true,
  4639. configurable: true
  4640. });
  4641. Object.defineProperty(Prim2DBase.prototype, "scaleX", {
  4642. get: function () {
  4643. return this._scale.x;
  4644. },
  4645. set: function (value) {
  4646. this._scale.x = value;
  4647. this._setFlags(BABYLON.SmartPropertyPrim.flagActualScaleDirty);
  4648. this._spreadActualScaleDirty();
  4649. },
  4650. enumerable: true,
  4651. configurable: true
  4652. });
  4653. Object.defineProperty(Prim2DBase.prototype, "scaleY", {
  4654. get: function () {
  4655. return this._scale.y;
  4656. },
  4657. set: function (value) {
  4658. this._scale.y = value;
  4659. this._setFlags(BABYLON.SmartPropertyPrim.flagActualScaleDirty);
  4660. this._spreadActualScaleDirty();
  4661. },
  4662. enumerable: true,
  4663. configurable: true
  4664. });
  4665. Prim2DBase.prototype._spreadActualScaleDirty = function () {
  4666. for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
  4667. var child = _a[_i];
  4668. child._setFlags(BABYLON.SmartPropertyPrim.flagActualScaleDirty);
  4669. child._spreadActualScaleDirty();
  4670. }
  4671. };
  4672. Object.defineProperty(Prim2DBase.prototype, "actualScale", {
  4673. /**
  4674. * Returns the actual scale of this Primitive, the value is computed from the scale property of this primitive, multiplied by the actualScale of its parent one (if any). The Vector2 object returned contains the scale for both X and Y axis
  4675. */
  4676. get: function () {
  4677. if (this._isFlagSet(BABYLON.SmartPropertyPrim.flagActualScaleDirty)) {
  4678. var cur = this._isFlagSet(BABYLON.SmartPropertyPrim.flagDontInheritParentScale) ? null : this.parent;
  4679. var sx = this.scaleX;
  4680. var sy = this.scaleY;
  4681. while (cur) {
  4682. sx *= cur.scaleX;
  4683. sy *= cur.scaleY;
  4684. cur = cur._isFlagSet(BABYLON.SmartPropertyPrim.flagDontInheritParentScale) ? null : cur.parent;
  4685. }
  4686. this._actualScale.copyFromFloats(sx, sy);
  4687. this._clearFlags(BABYLON.SmartPropertyPrim.flagActualScaleDirty);
  4688. }
  4689. return this._actualScale;
  4690. },
  4691. enumerable: true,
  4692. configurable: true
  4693. });
  4694. Object.defineProperty(Prim2DBase.prototype, "actualScaleX", {
  4695. /**
  4696. * Get the actual Scale of the X axis, shortcut for this.actualScale.x
  4697. */
  4698. get: function () {
  4699. return this.actualScale.x;
  4700. },
  4701. enumerable: true,
  4702. configurable: true
  4703. });
  4704. Object.defineProperty(Prim2DBase.prototype, "actualScaleY", {
  4705. /**
  4706. * Get the actual Scale of the Y axis, shortcut for this.actualScale.y
  4707. */
  4708. get: function () {
  4709. return this.actualScale.y;
  4710. },
  4711. enumerable: true,
  4712. configurable: true
  4713. });
  4714. Object.defineProperty(Prim2DBase.prototype, "actualOpacity", {
  4715. /**
  4716. * Get the actual opacity level, this property is computed from the opacity property, multiplied by the actualOpacity of its parent (if any)
  4717. */
  4718. get: function () {
  4719. if (this._isFlagSet(BABYLON.SmartPropertyPrim.flagActualOpacityDirty)) {
  4720. var cur = this.parent;
  4721. var op = this.opacity;
  4722. while (cur) {
  4723. op *= cur.opacity;
  4724. cur = cur.parent;
  4725. }
  4726. this._actualOpacity = op;
  4727. this._clearFlags(BABYLON.SmartPropertyPrim.flagActualOpacityDirty);
  4728. }
  4729. return this._actualOpacity;
  4730. },
  4731. enumerable: true,
  4732. configurable: true
  4733. });
  4734. Object.defineProperty(Prim2DBase.prototype, "layoutEngine", {
  4735. /**
  4736. * Get/set the layout engine to use for this primitive.
  4737. * The default layout engine is the CanvasLayoutEngine.
  4738. */
  4739. get: function () {
  4740. if (!this._layoutEngine) {
  4741. this._layoutEngine = BABYLON.CanvasLayoutEngine.Singleton;
  4742. }
  4743. return this._layoutEngine;
  4744. },
  4745. set: function (value) {
  4746. if (this._layoutEngine === value) {
  4747. return;
  4748. }
  4749. this._changeLayoutEngine(value);
  4750. },
  4751. enumerable: true,
  4752. configurable: true
  4753. });
  4754. Object.defineProperty(Prim2DBase.prototype, "layoutArea", {
  4755. /**
  4756. * Get/set the layout are of this primitive.
  4757. * The Layout area is the zone allocated by the Layout Engine for this particular primitive. Margins/Alignment will be computed based on this area.
  4758. * The setter should only be called by a Layout Engine class.
  4759. */
  4760. get: function () {
  4761. return this._layoutArea;
  4762. },
  4763. set: function (val) {
  4764. if (this._layoutArea.equals(val)) {
  4765. return;
  4766. }
  4767. this._positioningDirty();
  4768. if (this.parent) {
  4769. this.parent._setFlags(BABYLON.SmartPropertyPrim.flagLayoutBoundingInfoDirty);
  4770. }
  4771. this._layoutArea = val;
  4772. },
  4773. enumerable: true,
  4774. configurable: true
  4775. });
  4776. Object.defineProperty(Prim2DBase.prototype, "layoutAreaPos", {
  4777. /**
  4778. * Get/set the layout area position (relative to the parent primitive).
  4779. * The setter should only be called by a Layout Engine class.
  4780. */
  4781. get: function () {
  4782. if (!this._layoutAreaPos) {
  4783. this._layoutAreaPos = BABYLON.Vector2.Zero();
  4784. }
  4785. return this._layoutAreaPos;
  4786. },
  4787. set: function (val) {
  4788. if (this._layoutAreaPos && this._layoutAreaPos.equals(val)) {
  4789. return;
  4790. }
  4791. if (this.parent) {
  4792. this.parent._setFlags(BABYLON.SmartPropertyPrim.flagLayoutBoundingInfoDirty);
  4793. }
  4794. this._positioningDirty();
  4795. this._layoutAreaPos = val;
  4796. },
  4797. enumerable: true,
  4798. configurable: true
  4799. });
  4800. Object.defineProperty(Prim2DBase.prototype, "isPickable", {
  4801. /**
  4802. * Define if the Primitive can be subject to intersection test or not (default is true)
  4803. */
  4804. get: function () {
  4805. return this._isFlagSet(BABYLON.SmartPropertyPrim.flagIsPickable);
  4806. },
  4807. set: function (value) {
  4808. this._changeFlags(BABYLON.SmartPropertyPrim.flagIsPickable, value);
  4809. },
  4810. enumerable: true,
  4811. configurable: true
  4812. });
  4813. Object.defineProperty(Prim2DBase.prototype, "isContainer", {
  4814. /**
  4815. * Define if the Primitive acts as a container or not
  4816. * A container will encapsulate its children for interaction event.
  4817. * If it's not a container events will be process down to children if the primitive is not pickable.
  4818. * Default value is true
  4819. */
  4820. get: function () {
  4821. return this._isFlagSet(BABYLON.SmartPropertyPrim.flagIsContainer);
  4822. },
  4823. set: function (value) {
  4824. this._changeFlags(BABYLON.SmartPropertyPrim.flagIsContainer, value);
  4825. },
  4826. enumerable: true,
  4827. configurable: true
  4828. });
  4829. Object.defineProperty(Prim2DBase.prototype, "hierarchyDepth", {
  4830. /**
  4831. * Return the depth level of the Primitive into the Canvas' Graph. A Canvas will be 0, its direct children 1, and so on.
  4832. */
  4833. get: function () {
  4834. return this._hierarchyDepth;
  4835. },
  4836. enumerable: true,
  4837. configurable: true
  4838. });
  4839. Object.defineProperty(Prim2DBase.prototype, "renderGroup", {
  4840. /**
  4841. * Retrieve the Group that is responsible to render this primitive
  4842. */
  4843. get: function () {
  4844. return this._renderGroup;
  4845. },
  4846. enumerable: true,
  4847. configurable: true
  4848. });
  4849. Object.defineProperty(Prim2DBase.prototype, "globalTransform", {
  4850. /**
  4851. * Get the global transformation matrix of the primitive
  4852. */
  4853. get: function () {
  4854. this._updateLocalTransform();
  4855. return this._globalTransform;
  4856. },
  4857. enumerable: true,
  4858. configurable: true
  4859. });
  4860. /**
  4861. * return the global position of the primitive, relative to its canvas
  4862. */
  4863. Prim2DBase.prototype.getGlobalPosition = function () {
  4864. var v = new BABYLON.Vector2(0, 0);
  4865. this.getGlobalPositionByRef(v);
  4866. return v;
  4867. };
  4868. /**
  4869. * return the global position of the primitive, relative to its canvas
  4870. * @param v the valid Vector2 object where the global position will be stored
  4871. */
  4872. Prim2DBase.prototype.getGlobalPositionByRef = function (v) {
  4873. v.x = this.globalTransform.m[12];
  4874. v.y = this.globalTransform.m[13];
  4875. };
  4876. Object.defineProperty(Prim2DBase.prototype, "invGlobalTransform", {
  4877. /**
  4878. * Get invert of the global transformation matrix of the primitive
  4879. */
  4880. get: function () {
  4881. this._updateLocalTransform();
  4882. return this._invGlobalTransform;
  4883. },
  4884. enumerable: true,
  4885. configurable: true
  4886. });
  4887. Object.defineProperty(Prim2DBase.prototype, "localTransform", {
  4888. /**
  4889. * Get the local transformation of the primitive
  4890. */
  4891. get: function () {
  4892. this._updateLocalTransform();
  4893. return this._localTransform;
  4894. },
  4895. enumerable: true,
  4896. configurable: true
  4897. });
  4898. Object.defineProperty(Prim2DBase.prototype, "boundingInfo", {
  4899. /**
  4900. * Get the boundingInfo associated to the primitive and its children.
  4901. * The value is supposed to be always up to date
  4902. */
  4903. get: function () {
  4904. if (this._isFlagSet(BABYLON.SmartPropertyPrim.flagBoundingInfoDirty)) {
  4905. if (this.owner) {
  4906. this.owner.boundingInfoRecomputeCounter.addCount(1, false);
  4907. }
  4908. if (this.isSizedByContent) {
  4909. this._boundingInfo.clear();
  4910. }
  4911. else {
  4912. this._boundingInfo.copyFrom(this.levelBoundingInfo);
  4913. }
  4914. var bi = this._boundingInfo;
  4915. var tps = new BABYLON.BoundingInfo2D();
  4916. for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
  4917. var curChild = _a[_i];
  4918. var bb = curChild.boundingInfo;
  4919. bb.transformToRef(curChild.localTransform, tps);
  4920. bi.unionToRef(tps, bi);
  4921. }
  4922. this._boundingInfo.maxToRef(Prim2DBase._bMax);
  4923. this._boundingSize.copyFromFloats((!this._size || this._size.width == null) ? Math.ceil(Prim2DBase._bMax.x) : this._size.width, (!this._size || this._size.height == null) ? Math.ceil(Prim2DBase._bMax.y) : this._size.height);
  4924. this._clearFlags(BABYLON.SmartPropertyPrim.flagBoundingInfoDirty);
  4925. }
  4926. return this._boundingInfo;
  4927. },
  4928. enumerable: true,
  4929. configurable: true
  4930. });
  4931. Object.defineProperty(Prim2DBase.prototype, "layoutBoundingInfo", {
  4932. /**
  4933. * Get the boundingInfo of the primitive's content arranged by a layout Engine
  4934. * If a particular child is not arranged by layout, it's boundingInfo is used instead to produce something as accurate as possible
  4935. */
  4936. get: function () {
  4937. if (this._isFlagSet(BABYLON.SmartPropertyPrim.flagLayoutBoundingInfoDirty)) {
  4938. if (!this._layoutBoundingInfo) {
  4939. this._layoutBoundingInfo = new BABYLON.BoundingInfo2D();
  4940. }
  4941. if (this.isSizedByContent) {
  4942. this._layoutBoundingInfo.clear();
  4943. }
  4944. else {
  4945. this._layoutBoundingInfo.copyFrom(this.levelBoundingInfo);
  4946. }
  4947. var bi = this._layoutBoundingInfo;
  4948. var tps = new BABYLON.BoundingInfo2D();
  4949. for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
  4950. var curChild = _a[_i];
  4951. var bb = void 0;
  4952. if (curChild._layoutAreaPos) {
  4953. var s = curChild._layoutArea;
  4954. BABYLON.BoundingInfo2D.CreateFromMinMaxToRef(0, s.width, 0, s.height, Prim2DBase._tpsBB);
  4955. bb = Prim2DBase._tpsBB;
  4956. }
  4957. else {
  4958. bb = curChild.boundingInfo;
  4959. }
  4960. bb.transformToRef(curChild.localTransform, tps);
  4961. bi.unionToRef(tps, bi);
  4962. }
  4963. this._clearFlags(BABYLON.SmartPropertyPrim.flagLayoutBoundingInfoDirty);
  4964. }
  4965. return this._layoutBoundingInfo;
  4966. },
  4967. enumerable: true,
  4968. configurable: true
  4969. });
  4970. Object.defineProperty(Prim2DBase.prototype, "isSizeAuto", {
  4971. /**
  4972. * Determine if the size is automatically computed or fixed because manually specified.
  4973. * Use the actualSize property to get the final/real size of the primitive
  4974. * @returns true if the size is automatically computed, false if it were manually specified.
  4975. */
  4976. get: function () {
  4977. return this._size == null;
  4978. },
  4979. enumerable: true,
  4980. configurable: true
  4981. });
  4982. Object.defineProperty(Prim2DBase.prototype, "isSizedByContent", {
  4983. /**
  4984. * Return true if this prim has an auto size which is set by the children's global bounding box
  4985. */
  4986. get: function () {
  4987. return (this._size == null) && (this._children.length > 0);
  4988. },
  4989. enumerable: true,
  4990. configurable: true
  4991. });
  4992. Object.defineProperty(Prim2DBase.prototype, "isPositionAuto", {
  4993. /**
  4994. * Determine if the position is automatically computed or fixed because manually specified.
  4995. * Use the actualPosition property to get the final/real position of the primitive
  4996. * @returns true if the position is automatically computed, false if it were manually specified.
  4997. */
  4998. get: function () {
  4999. return this._position == null;
  5000. },
  5001. enumerable: true,
  5002. configurable: true
  5003. });
  5004. Object.defineProperty(Prim2DBase.prototype, "pointerEventObservable", {
  5005. /**
  5006. * Interaction with the primitive can be create using this Observable. See the PrimitivePointerInfo class for more information
  5007. */
  5008. get: function () {
  5009. return this._pointerEventObservable;
  5010. },
  5011. enumerable: true,
  5012. configurable: true
  5013. });
  5014. Object.defineProperty(Prim2DBase.prototype, "zActualOrderChangedObservable", {
  5015. get: function () {
  5016. if (!this._actualZOrderChangedObservable) {
  5017. this._actualZOrderChangedObservable = new BABYLON.Observable();
  5018. }
  5019. return this._actualZOrderChangedObservable;
  5020. },
  5021. enumerable: true,
  5022. configurable: true
  5023. });
  5024. Object.defineProperty(Prim2DBase.prototype, "displayDebugAreas", {
  5025. get: function () {
  5026. return this._displayDebugAreas;
  5027. },
  5028. set: function (value) {
  5029. if (this._displayDebugAreas === value) {
  5030. return;
  5031. }
  5032. if (value === false) {
  5033. this._debugAreaGroup.dispose();
  5034. this._debugAreaGroup = null;
  5035. }
  5036. else {
  5037. var layoutFill = "#F0808040"; // Red - Layout area
  5038. var layoutBorder = "#F08080FF";
  5039. var marginFill = "#F0F04040"; // Yellow - Margin area
  5040. var marginBorder = "#F0F040FF";
  5041. var paddingFill = "#F040F040"; // Magenta - Padding Area
  5042. var paddingBorder = "#F040F0FF";
  5043. var contentFill = "#40F0F040"; // Cyan - Content area
  5044. var contentBorder = "#40F0F0FF";
  5045. var s = new BABYLON.Size(10, 10);
  5046. var p = BABYLON.Vector2.Zero();
  5047. this._debugAreaGroup = new BABYLON.Group2D({
  5048. parent: (this.parent != null) ? this.parent : this, id: "###DEBUG AREA GROUP###", children: [
  5049. new BABYLON.Group2D({
  5050. id: "###Layout Area###", position: p, size: s, children: [
  5051. new BABYLON.Rectangle2D({ id: "###Layout Frame###", position: BABYLON.Vector2.Zero(), size: s, fill: null, border: layoutBorder }),
  5052. new BABYLON.Rectangle2D({ id: "###Layout Top###", position: BABYLON.Vector2.Zero(), size: s, fill: layoutFill }),
  5053. new BABYLON.Rectangle2D({ id: "###Layout Left###", position: BABYLON.Vector2.Zero(), size: s, fill: layoutFill }),
  5054. new BABYLON.Rectangle2D({ id: "###Layout Right###", position: BABYLON.Vector2.Zero(), size: s, fill: layoutFill }),
  5055. new BABYLON.Rectangle2D({ id: "###Layout Bottom###", position: BABYLON.Vector2.Zero(), size: s, fill: layoutFill })
  5056. ]
  5057. }),
  5058. new BABYLON.Group2D({
  5059. id: "###Margin Area###", position: p, size: s, children: [
  5060. new BABYLON.Rectangle2D({ id: "###Margin Frame###", position: BABYLON.Vector2.Zero(), size: s, fill: null, border: marginBorder }),
  5061. new BABYLON.Rectangle2D({ id: "###Margin Top###", position: BABYLON.Vector2.Zero(), size: s, fill: marginFill }),
  5062. new BABYLON.Rectangle2D({ id: "###Margin Left###", position: BABYLON.Vector2.Zero(), size: s, fill: marginFill }),
  5063. new BABYLON.Rectangle2D({ id: "###Margin Right###", position: BABYLON.Vector2.Zero(), size: s, fill: marginFill }),
  5064. new BABYLON.Rectangle2D({ id: "###Margin Bottom###", position: BABYLON.Vector2.Zero(), size: s, fill: marginFill })
  5065. ]
  5066. }),
  5067. new BABYLON.Group2D({
  5068. id: "###Padding Area###", position: p, size: s, children: [
  5069. new BABYLON.Rectangle2D({ id: "###Padding Frame###", position: BABYLON.Vector2.Zero(), size: s, fill: null, border: paddingBorder }),
  5070. new BABYLON.Rectangle2D({ id: "###Padding Top###", position: BABYLON.Vector2.Zero(), size: s, fill: paddingFill }),
  5071. new BABYLON.Rectangle2D({ id: "###Padding Left###", position: BABYLON.Vector2.Zero(), size: s, fill: paddingFill }),
  5072. new BABYLON.Rectangle2D({ id: "###Padding Right###", position: BABYLON.Vector2.Zero(), size: s, fill: paddingFill }),
  5073. new BABYLON.Rectangle2D({ id: "###Padding Bottom###", position: BABYLON.Vector2.Zero(), size: s, fill: paddingFill })
  5074. ]
  5075. }),
  5076. new BABYLON.Group2D({
  5077. id: "###Content Area###", position: p, size: s, children: [
  5078. new BABYLON.Rectangle2D({ id: "###Content Frame###", position: BABYLON.Vector2.Zero(), size: s, fill: null, border: contentBorder }),
  5079. new BABYLON.Rectangle2D({ id: "###Content Top###", position: BABYLON.Vector2.Zero(), size: s, fill: contentFill }),
  5080. new BABYLON.Rectangle2D({ id: "###Content Left###", position: BABYLON.Vector2.Zero(), size: s, fill: contentFill }),
  5081. new BABYLON.Rectangle2D({ id: "###Content Right###", position: BABYLON.Vector2.Zero(), size: s, fill: contentFill }),
  5082. new BABYLON.Rectangle2D({ id: "###Content Bottom###", position: BABYLON.Vector2.Zero(), size: s, fill: contentFill })
  5083. ]
  5084. })
  5085. ]
  5086. });
  5087. this._debugAreaGroup._setFlags(BABYLON.SmartPropertyPrim.flagNoPartOfLayout);
  5088. this._updateDebugArea();
  5089. }
  5090. this._displayDebugAreas = value;
  5091. },
  5092. enumerable: true,
  5093. configurable: true
  5094. });
  5095. Prim2DBase.prototype._updateDebugArea = function () {
  5096. var areaNames = ["Layout", "Margin", "Padding", "Content"];
  5097. var areaZones = ["Area", "Frame", "Top", "Left", "Right", "Bottom"];
  5098. var prims = new Array(4);
  5099. // Get all the primitives used to display the areas
  5100. for (var i = 0; i < 4; i++) {
  5101. prims[i] = new Array(6);
  5102. for (var j = 0; j < 6; j++) {
  5103. prims[i][j] = this._debugAreaGroup.findById("###" + areaNames[i] + " " + areaZones[j] + "###");
  5104. if (j > 1) {
  5105. prims[i][j].levelVisible = false;
  5106. }
  5107. }
  5108. }
  5109. // Update the visibility status of layout/margin/padding
  5110. var hasLayout = this._layoutAreaPos != null;
  5111. var hasPos = (this.actualPosition.x !== 0) || (this.actualPosition.y !== 0);
  5112. var hasMargin = this._hasMargin;
  5113. var hasPadding = this._hasPadding;
  5114. prims[0][0].levelVisible = hasLayout;
  5115. prims[1][0].levelVisible = hasMargin;
  5116. prims[2][0].levelVisible = hasPadding;
  5117. prims[3][0].levelVisible = true;
  5118. // Current offset
  5119. var curOffset = BABYLON.Vector2.Zero();
  5120. // Store the area info of the layout area
  5121. var curAreaIndex = 0;
  5122. // Store data about each area
  5123. var areaInfo = new Array(4);
  5124. var storeAreaInfo = function (pos, size) {
  5125. var min = pos.clone();
  5126. var max = pos.clone();
  5127. if (size.width > 0) {
  5128. max.x += size.width;
  5129. }
  5130. if (size.height > 0) {
  5131. max.y += size.height;
  5132. }
  5133. areaInfo[curAreaIndex++] = { off: pos, size: size, min: min, max: max };
  5134. };
  5135. var marginH = this._marginOffset.x + this._marginOffset.z;
  5136. var marginV = this._marginOffset.y + this._marginOffset.w;
  5137. var w = hasLayout ? (this.layoutAreaPos.x + this.layoutArea.width) : (marginH + this.actualSize.width);
  5138. var h = hasLayout ? (this.layoutAreaPos.y + this.layoutArea.height) : (marginV + this.actualSize.height);
  5139. var pos = (!hasLayout && !hasMargin && !hasPadding && hasPos) ? this.actualPosition : BABYLON.Vector2.Zero();
  5140. storeAreaInfo(pos, new BABYLON.Size(w, h));
  5141. // Compute the layout related data
  5142. if (hasLayout) {
  5143. var layoutOffset = this.layoutAreaPos.clone();
  5144. storeAreaInfo(layoutOffset, (hasMargin || hasPadding) ? this.layoutArea.clone() : this.actualSize.clone());
  5145. curOffset = layoutOffset.clone();
  5146. }
  5147. // Compute margin data
  5148. if (hasMargin) {
  5149. var marginOffset = curOffset.clone();
  5150. marginOffset.x += this._marginOffset.x;
  5151. marginOffset.y += this._marginOffset.y;
  5152. var marginArea = this.actualSize;
  5153. storeAreaInfo(marginOffset, marginArea);
  5154. curOffset = marginOffset.clone();
  5155. }
  5156. if (hasPadding) {
  5157. var contentOffset = curOffset.clone();
  5158. contentOffset.x += this._paddingOffset.x;
  5159. contentOffset.y += this._paddingOffset.y;
  5160. var contentArea = this.contentArea;
  5161. storeAreaInfo(contentOffset, contentArea);
  5162. curOffset = curOffset.add(contentOffset);
  5163. }
  5164. // Helper function that set the pos and size of a given prim
  5165. var setArea = function (i, j, pos, size) {
  5166. prims[i][j].position = pos;
  5167. prims[i][j].size = size;
  5168. };
  5169. var setFullRect = function (i, pos, size) {
  5170. var plist = prims[i];
  5171. plist[2].levelVisible = true;
  5172. plist[3].levelVisible = false;
  5173. plist[4].levelVisible = false;
  5174. plist[5].levelVisible = false;
  5175. setArea(i, 1, pos, size);
  5176. setArea(i, 2, pos, size);
  5177. };
  5178. var setQuadRect = function (i, areaIndex) {
  5179. var plist = prims[i];
  5180. plist[2].levelVisible = true;
  5181. plist[3].levelVisible = true;
  5182. plist[4].levelVisible = true;
  5183. plist[5].levelVisible = true;
  5184. var ca = areaInfo[areaIndex];
  5185. var na = areaInfo[areaIndex + 1];
  5186. var tp = new BABYLON.Vector2(ca.min.x, na.max.y);
  5187. var ts = new BABYLON.Size(ca.size.width, ca.max.y - tp.y);
  5188. var lp = new BABYLON.Vector2(ca.min.x, na.min.y);
  5189. var ls = new BABYLON.Size(na.min.x - ca.min.x, na.max.y - na.min.y);
  5190. var rp = new BABYLON.Vector2(na.max.x, na.min.y);
  5191. var rs = new BABYLON.Size(ca.max.x - na.max.x, na.max.y - na.min.y);
  5192. var bp = new BABYLON.Vector2(ca.min.x, ca.min.y);
  5193. var bs = new BABYLON.Size(ca.size.width, na.min.y - ca.min.y);
  5194. // Frame
  5195. plist[1].position = ca.off;
  5196. plist[1].size = ca.size;
  5197. // Top rect
  5198. plist[2].position = tp;
  5199. plist[2].size = ts;
  5200. // Left rect
  5201. plist[3].position = lp;
  5202. plist[3].size = ls;
  5203. // Right rect
  5204. plist[4].position = rp;
  5205. plist[4].size = rs;
  5206. // Bottom rect
  5207. plist[5].position = bp;
  5208. plist[5].size = bs;
  5209. };
  5210. var areaCount = curAreaIndex;
  5211. curAreaIndex = 0;
  5212. // Available zones
  5213. var availableZones = [false, hasLayout, hasMargin, hasPadding, true];
  5214. for (var k = 1; k < 5; k++) {
  5215. if (availableZones[k]) {
  5216. var ai = areaInfo[curAreaIndex];
  5217. setArea(k - 1, 0, BABYLON.Vector2.Zero(), ai.size);
  5218. // setArea(k-1, 1, Vector2.Zero(), ai.size);
  5219. if (k === 4) {
  5220. setFullRect(k - 1, ai.off, ai.size);
  5221. }
  5222. else {
  5223. setQuadRect(k - 1, curAreaIndex);
  5224. }
  5225. ++curAreaIndex;
  5226. }
  5227. }
  5228. };
  5229. Prim2DBase.prototype.findById = function (id) {
  5230. if (this._id === id) {
  5231. return this;
  5232. }
  5233. for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
  5234. var child = _a[_i];
  5235. var r = child.findById(id);
  5236. if (r != null) {
  5237. return r;
  5238. }
  5239. }
  5240. };
  5241. Prim2DBase.prototype.onZOrderChanged = function () {
  5242. };
  5243. Prim2DBase.prototype.levelIntersect = function (intersectInfo) {
  5244. return false;
  5245. };
  5246. /**
  5247. * Capture all the Events of the given PointerId for this primitive.
  5248. * Don't forget to call releasePointerEventsCapture when done.
  5249. * @param pointerId the Id of the pointer to capture the events from.
  5250. */
  5251. Prim2DBase.prototype.setPointerEventCapture = function (pointerId) {
  5252. return this.owner._setPointerCapture(pointerId, this);
  5253. };
  5254. /**
  5255. * Release a captured pointer made with setPointerEventCapture.
  5256. * @param pointerId the Id of the pointer to release the capture from.
  5257. */
  5258. Prim2DBase.prototype.releasePointerEventsCapture = function (pointerId) {
  5259. return this.owner._releasePointerCapture(pointerId, this);
  5260. };
  5261. /**
  5262. * Make an intersection test with the primitive, all inputs/outputs are stored in the IntersectInfo2D class, see its documentation for more information.
  5263. * @param intersectInfo contains the settings of the intersection to perform, to setup before calling this method as well as the result, available after a call to this method.
  5264. */
  5265. Prim2DBase.prototype.intersect = function (intersectInfo) {
  5266. if (!intersectInfo) {
  5267. return false;
  5268. }
  5269. // If this is null it means this method is call for the first level, initialize stuffs
  5270. var firstLevel = !intersectInfo._globalPickPosition;
  5271. if (firstLevel) {
  5272. // Compute the pickPosition in global space and use it to find the local position for each level down, always relative from the world to get the maximum accuracy (and speed). The other way would have been to compute in local every level down relative to its parent's local, which wouldn't be as accurate (even if javascript number is 80bits accurate).
  5273. intersectInfo._globalPickPosition = BABYLON.Vector2.Zero();
  5274. BABYLON.Vector2.TransformToRef(intersectInfo.pickPosition, this.globalTransform, intersectInfo._globalPickPosition);
  5275. intersectInfo._localPickPosition = intersectInfo.pickPosition.clone();
  5276. intersectInfo.intersectedPrimitives = new Array();
  5277. intersectInfo.topMostIntersectedPrimitive = null;
  5278. }
  5279. if (!intersectInfo.intersectHidden && !this.isVisible) {
  5280. return false;
  5281. }
  5282. var id = this.id;
  5283. if (id != null && id.indexOf("__cachedSpriteOfGroup__") === 0) {
  5284. var ownerGroup = this.getExternalData("__cachedGroup__");
  5285. return ownerGroup.intersect(intersectInfo);
  5286. }
  5287. // If we're testing a cachedGroup, we must reject pointer outside its levelBoundingInfo because children primitives could be partially clipped outside so we must not accept them as intersected when it's the case (because they're not visually visible).
  5288. var isIntersectionTest = false;
  5289. if (this instanceof BABYLON.Group2D) {
  5290. var g = this;
  5291. isIntersectionTest = g.isCachedGroup;
  5292. }
  5293. if (isIntersectionTest && !this.levelBoundingInfo.doesIntersect(intersectInfo._localPickPosition)) {
  5294. // Important to call this before each return to allow a good recursion next time this intersectInfo is reused
  5295. intersectInfo._exit(firstLevel);
  5296. return false;
  5297. }
  5298. // Fast rejection test with boundingInfo
  5299. if (this.isPickable && !this.boundingInfo.doesIntersect(intersectInfo._localPickPosition)) {
  5300. // Important to call this before each return to allow a good recursion next time this intersectInfo is reused
  5301. intersectInfo._exit(firstLevel);
  5302. return false;
  5303. }
  5304. // We hit the boundingInfo that bounds this primitive and its children, now we have to test on the primitive of this level
  5305. var levelIntersectRes = false;
  5306. if (this.isPickable) {
  5307. levelIntersectRes = this.levelIntersect(intersectInfo);
  5308. if (levelIntersectRes) {
  5309. var pii = new PrimitiveIntersectedInfo(this, intersectInfo._localPickPosition.clone());
  5310. intersectInfo.intersectedPrimitives.push(pii);
  5311. if (!intersectInfo.topMostIntersectedPrimitive || (intersectInfo.topMostIntersectedPrimitive.prim.actualZOffset > pii.prim.actualZOffset)) {
  5312. intersectInfo.topMostIntersectedPrimitive = pii;
  5313. }
  5314. // If we must stop at the first intersection, we're done, quit!
  5315. if (intersectInfo.findFirstOnly) {
  5316. intersectInfo._exit(firstLevel);
  5317. return true;
  5318. }
  5319. }
  5320. }
  5321. // Recurse to children if needed
  5322. if (!levelIntersectRes || !intersectInfo.findFirstOnly) {
  5323. for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
  5324. var curChild = _a[_i];
  5325. // Don't test primitive not pick able or if it's hidden and we don't test hidden ones
  5326. if ((!curChild.isPickable && curChild.isContainer) || (!intersectInfo.intersectHidden && !curChild.isVisible)) {
  5327. continue;
  5328. }
  5329. // Must compute the localPickLocation for the children level
  5330. BABYLON.Vector2.TransformToRef(intersectInfo._globalPickPosition, curChild.invGlobalTransform, intersectInfo._localPickPosition);
  5331. // If we got an intersection with the child and we only need to find the first one, quit!
  5332. if (curChild.intersect(intersectInfo) && intersectInfo.findFirstOnly) {
  5333. intersectInfo._exit(firstLevel);
  5334. return true;
  5335. }
  5336. }
  5337. }
  5338. intersectInfo._exit(firstLevel);
  5339. return intersectInfo.isIntersected;
  5340. };
  5341. /**
  5342. * Move a child object into a new position regarding its siblings to change its rendering order.
  5343. * You can also use the shortcut methods to move top/bottom: moveChildToTop, moveChildToBottom, moveToTop, moveToBottom.
  5344. * @param child the object to move
  5345. * @param previous the object which will be before "child", if child has to be the first among sibling, set "previous" to null.
  5346. */
  5347. Prim2DBase.prototype.moveChild = function (child, previous) {
  5348. if (child.parent !== this) {
  5349. return false;
  5350. }
  5351. var childIndex = this._children.indexOf(child);
  5352. var prevIndex = previous ? this._children.indexOf(previous) : -1;
  5353. if (!this._isFlagSet(BABYLON.SmartPropertyPrim.flagChildrenFlatZOrder)) {
  5354. this._setFlags(BABYLON.SmartPropertyPrim.flagZOrderDirty);
  5355. this._firstZDirtyIndex = Math.min(this._firstZDirtyIndex, prevIndex + 1);
  5356. }
  5357. this._children.splice(prevIndex + 1, 0, this._children.splice(childIndex, 1)[0]);
  5358. return true;
  5359. };
  5360. /**
  5361. * Move the given child so it's displayed on the top of all its siblings
  5362. * @param child the primitive to move to the top
  5363. */
  5364. Prim2DBase.prototype.moveChildToTop = function (child) {
  5365. return this.moveChild(child, this._children[this._children.length - 1]);
  5366. };
  5367. /**
  5368. * Move the given child so it's displayed on the bottom of all its siblings
  5369. * @param child the primitive to move to the top
  5370. */
  5371. Prim2DBase.prototype.moveChildToBottom = function (child) {
  5372. return this.moveChild(child, null);
  5373. };
  5374. /**
  5375. * Move this primitive to be at the top among all its sibling
  5376. */
  5377. Prim2DBase.prototype.moveToTop = function () {
  5378. if (this.parent == null) {
  5379. return false;
  5380. }
  5381. return this.parent.moveChildToTop(this);
  5382. };
  5383. /**
  5384. * Move this primitive to be at the bottom among all its sibling
  5385. */
  5386. Prim2DBase.prototype.moveToBottom = function () {
  5387. if (this.parent == null) {
  5388. return false;
  5389. }
  5390. return this.parent.moveChildToBottom(this);
  5391. };
  5392. Prim2DBase.prototype.addChild = function (child) {
  5393. child._parent = this;
  5394. this._boundingBoxDirty();
  5395. var flat = this._isFlagSet(BABYLON.SmartPropertyPrim.flagChildrenFlatZOrder);
  5396. if (flat) {
  5397. child._setFlags(BABYLON.SmartPropertyPrim.flagChildrenFlatZOrder);
  5398. child._setZOrder(this._zOrder, true);
  5399. child._zMax = this._zOrder;
  5400. }
  5401. else {
  5402. this._setFlags(BABYLON.SmartPropertyPrim.flagZOrderDirty);
  5403. }
  5404. var length = this._children.push(child);
  5405. this._firstZDirtyIndex = Math.min(this._firstZDirtyIndex, length - 1);
  5406. };
  5407. /**
  5408. * Dispose the primitive, remove it from its parent.
  5409. */
  5410. Prim2DBase.prototype.dispose = function () {
  5411. if (!_super.prototype.dispose.call(this)) {
  5412. return false;
  5413. }
  5414. if (this._actionManager) {
  5415. this._actionManager.dispose();
  5416. this._actionManager = null;
  5417. }
  5418. // If there's a parent, remove this object from its parent list
  5419. if (this._parent) {
  5420. if (this instanceof BABYLON.Group2D) {
  5421. var g = this;
  5422. if (g.isRenderableGroup) {
  5423. var parentRenderable = this.parent.traverseUp(function (p) { return (p instanceof BABYLON.Group2D && p.isRenderableGroup); });
  5424. if (parentRenderable != null) {
  5425. var l = parentRenderable._renderableData._childrenRenderableGroups;
  5426. var i_1 = l.indexOf(g);
  5427. if (i_1 !== -1) {
  5428. l.splice(i_1, 1);
  5429. }
  5430. }
  5431. }
  5432. }
  5433. var i = this._parent._children.indexOf(this);
  5434. if (i !== undefined) {
  5435. this._parent._children.splice(i, 1);
  5436. }
  5437. this._parent = null;
  5438. }
  5439. // Recurse dispose to children
  5440. if (this._children) {
  5441. while (this._children.length > 0) {
  5442. this._children[this._children.length - 1].dispose();
  5443. }
  5444. }
  5445. return true;
  5446. };
  5447. Prim2DBase.prototype.onPrimBecomesDirty = function () {
  5448. if (this._renderGroup && !this._isFlagSet(BABYLON.SmartPropertyPrim.flagPrimInDirtyList)) {
  5449. this._renderGroup._addPrimToDirtyList(this);
  5450. this._setFlags(BABYLON.SmartPropertyPrim.flagPrimInDirtyList);
  5451. }
  5452. };
  5453. Prim2DBase.prototype._needPrepare = function () {
  5454. return this._areSomeFlagsSet(BABYLON.SmartPropertyPrim.flagVisibilityChanged | BABYLON.SmartPropertyPrim.flagModelDirty | BABYLON.SmartPropertyPrim.flagNeedRefresh) || (this._instanceDirtyFlags !== 0) || (this._globalTransformProcessStep !== this._globalTransformStep);
  5455. };
  5456. Prim2DBase.prototype._prepareRender = function (context) {
  5457. this._prepareRenderPre(context);
  5458. this._prepareRenderPost(context);
  5459. };
  5460. Prim2DBase.prototype._prepareRenderPre = function (context) {
  5461. };
  5462. Prim2DBase.prototype._prepareRenderPost = function (context) {
  5463. // Don't recurse if it's a renderable group, the content will be processed by the group itself
  5464. if (this instanceof BABYLON.Group2D) {
  5465. var self = this;
  5466. if (self.isRenderableGroup) {
  5467. return;
  5468. }
  5469. }
  5470. // Check if we need to recurse the prepare to children primitives
  5471. // - must have children
  5472. // - the global transform of this level have changed, or
  5473. // - the visible state of primitive has changed
  5474. if (this._children.length > 0 && ((this._globalTransformProcessStep !== this._globalTransformStep) ||
  5475. this.checkPropertiesDirty(Prim2DBase.isVisibleProperty.flagId))) {
  5476. this._children.forEach(function (c) {
  5477. // As usual stop the recursion if we meet a renderable group
  5478. if (!(c instanceof BABYLON.Group2D && c.isRenderableGroup)) {
  5479. c._prepareRender(context);
  5480. }
  5481. });
  5482. }
  5483. // Finally reset the dirty flags as we've processed everything
  5484. this._clearFlags(BABYLON.SmartPropertyPrim.flagModelDirty);
  5485. this._instanceDirtyFlags = 0;
  5486. };
  5487. Prim2DBase.prototype._canvasPreInit = function (settings) {
  5488. };
  5489. Prim2DBase.CheckParent = function (parent) {
  5490. //if (!Prim2DBase._isCanvasInit && !parent) {
  5491. // throw new Error("A Primitive needs a valid Parent, it can be any kind of Primitives based types, even the Canvas (with the exception that only Group2D can be direct child of a Canvas if the cache strategy used is TOPLEVELGROUPS)");
  5492. //}
  5493. };
  5494. Prim2DBase.prototype.updateCachedStatesOf = function (list, recurse) {
  5495. for (var _i = 0, list_1 = list; _i < list_1.length; _i++) {
  5496. var cur = list_1[_i];
  5497. cur.updateCachedStates(recurse);
  5498. }
  5499. };
  5500. Prim2DBase.prototype._parentLayoutDirty = function () {
  5501. if (!this._parent || this._parent.isDisposed) {
  5502. return;
  5503. }
  5504. this._parent._setLayoutDirty();
  5505. };
  5506. Prim2DBase.prototype._setLayoutDirty = function () {
  5507. this.onPrimBecomesDirty();
  5508. this._setFlags(BABYLON.SmartPropertyPrim.flagLayoutDirty);
  5509. };
  5510. Prim2DBase.prototype._checkPositionChange = function () {
  5511. if (this.parent && this.parent.layoutEngine.isChildPositionAllowed === false) {
  5512. console.log("Can't manually set the position of " + this.id + ", the Layout Engine of its parent doesn't allow it");
  5513. return false;
  5514. }
  5515. return true;
  5516. };
  5517. Prim2DBase.prototype._positioningDirty = function () {
  5518. this.onPrimBecomesDirty();
  5519. this._setFlags(BABYLON.SmartPropertyPrim.flagPositioningDirty);
  5520. };
  5521. Prim2DBase.prototype._spreadActualOpacityChanged = function () {
  5522. for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
  5523. var child = _a[_i];
  5524. child._setFlags(BABYLON.SmartPropertyPrim.flagActualOpacityDirty);
  5525. child._updateRenderMode();
  5526. child.onPrimBecomesDirty();
  5527. child._spreadActualOpacityChanged();
  5528. }
  5529. };
  5530. Prim2DBase.prototype._changeLayoutEngine = function (engine) {
  5531. this._layoutEngine = engine;
  5532. };
  5533. Prim2DBase.prototype._updateLocalTransform = function () {
  5534. var tflags = Prim2DBase.actualPositionProperty.flagId | Prim2DBase.rotationProperty.flagId | Prim2DBase.scaleProperty.flagId | Prim2DBase.scaleXProperty.flagId | Prim2DBase.scaleYProperty.flagId | Prim2DBase.originProperty.flagId;
  5535. if (this.checkPropertiesDirty(tflags)) {
  5536. if (this.owner) {
  5537. this.owner.addupdateLocalTransformCounter(1);
  5538. }
  5539. var rot = BABYLON.Quaternion.RotationAxis(new BABYLON.Vector3(0, 0, 1), this._rotation);
  5540. var local;
  5541. var pos = this._position ? this.position : this.layoutAreaPos;
  5542. if (this._origin.x === 0 && this._origin.y === 0) {
  5543. local = BABYLON.Matrix.Compose(new BABYLON.Vector3(this._scale.x, this._scale.y, 1), rot, new BABYLON.Vector3(pos.x + this._marginOffset.x, pos.y + this._marginOffset.y, 0));
  5544. this._localTransform = local;
  5545. }
  5546. else {
  5547. // -Origin offset
  5548. var as = this.actualSize;
  5549. BABYLON.Matrix.TranslationToRef((-as.width * this._origin.x), (-as.height * this._origin.y), 0, Prim2DBase._t0);
  5550. // -Origin * rotation
  5551. rot.toRotationMatrix(Prim2DBase._t1);
  5552. Prim2DBase._t0.multiplyToRef(Prim2DBase._t1, Prim2DBase._t2);
  5553. // -Origin * rotation * scale
  5554. BABYLON.Matrix.ScalingToRef(this._scale.x, this._scale.y, 1, Prim2DBase._t0);
  5555. Prim2DBase._t2.multiplyToRef(Prim2DBase._t0, Prim2DBase._t1);
  5556. // -Origin * rotation * scale * (Origin + Position)
  5557. BABYLON.Matrix.TranslationToRef((as.width * this._origin.x) + pos.x + this._marginOffset.x, (as.height * this._origin.y) + pos.y + this._marginOffset.y, 0, Prim2DBase._t2);
  5558. Prim2DBase._t1.multiplyToRef(Prim2DBase._t2, this._localTransform);
  5559. }
  5560. this.clearPropertiesDirty(tflags);
  5561. this._setFlags(BABYLON.SmartPropertyPrim.flagGlobalTransformDirty);
  5562. return true;
  5563. }
  5564. return false;
  5565. };
  5566. Prim2DBase.prototype.updateCachedStates = function (recurse) {
  5567. if (this.isDisposed) {
  5568. return;
  5569. }
  5570. this.owner.addCachedGroupRenderCounter(1);
  5571. // Check if the parent is synced
  5572. if (this._parent && ((this._parent._globalTransformProcessStep !== this.owner._globalTransformProcessStep) || this._parent._areSomeFlagsSet(BABYLON.SmartPropertyPrim.flagLayoutDirty | BABYLON.SmartPropertyPrim.flagPositioningDirty | BABYLON.SmartPropertyPrim.flagZOrderDirty))) {
  5573. this._parent.updateCachedStates(false);
  5574. }
  5575. // Update Z-Order if needed
  5576. if (this._isFlagSet(BABYLON.SmartPropertyPrim.flagZOrderDirty)) {
  5577. this._updateZOrder();
  5578. }
  5579. // Update actualSize only if there' not positioning to recompute and the size changed
  5580. // Otherwise positioning will take care of it.
  5581. var sizeDirty = this.checkPropertiesDirty(Prim2DBase.sizeProperty.flagId);
  5582. if (!this._isFlagSet(BABYLON.SmartPropertyPrim.flagLayoutDirty) && !this._isFlagSet(BABYLON.SmartPropertyPrim.flagPositioningDirty) && sizeDirty) {
  5583. var size = this.size;
  5584. if (size) {
  5585. if (this.size.width != null) {
  5586. this.actualSize.width = this.size.width;
  5587. }
  5588. if (this.size.height != null) {
  5589. this.actualSize.height = this.size.height;
  5590. }
  5591. this.clearPropertiesDirty(Prim2DBase.sizeProperty.flagId);
  5592. }
  5593. }
  5594. var positioningDirty = this._isFlagSet(BABYLON.SmartPropertyPrim.flagPositioningDirty);
  5595. var positioningComputed = positioningDirty && !this._isFlagSet(BABYLON.SmartPropertyPrim.flagPositioningDirty);
  5596. // Check for layout update
  5597. if (this._isFlagSet(BABYLON.SmartPropertyPrim.flagLayoutDirty)) {
  5598. this.owner.addUpdateLayoutCounter(1);
  5599. this._layoutEngine.updateLayout(this);
  5600. this._clearFlags(BABYLON.SmartPropertyPrim.flagLayoutDirty);
  5601. }
  5602. var autoContentChanged = false;
  5603. if (this.isSizeAuto) {
  5604. if (!this._lastAutoSizeArea) {
  5605. autoContentChanged = this.actualSize !== null;
  5606. }
  5607. else {
  5608. autoContentChanged = (!this._lastAutoSizeArea.equals(this.actualSize));
  5609. }
  5610. }
  5611. // Check for positioning update
  5612. if (!positioningComputed && (autoContentChanged || sizeDirty || this._isFlagSet(BABYLON.SmartPropertyPrim.flagPositioningDirty) || (this._parent && !this._parent.contentArea.equals(this._parentContentArea)))) {
  5613. this._updatePositioning();
  5614. this._clearFlags(BABYLON.SmartPropertyPrim.flagPositioningDirty);
  5615. if (sizeDirty) {
  5616. this.clearPropertiesDirty(Prim2DBase.sizeProperty.flagId);
  5617. }
  5618. positioningComputed = true;
  5619. }
  5620. if (positioningComputed && this._parent) {
  5621. this._parentContentArea.copyFrom(this._parent.contentArea);
  5622. }
  5623. // Check if we must update this prim
  5624. if (this === this.owner || this._globalTransformProcessStep !== this.owner._globalTransformProcessStep) {
  5625. this.owner.addUpdateGlobalTransformCounter(1);
  5626. var curVisibleState = this.isVisible;
  5627. this.isVisible = (!this._parent || this._parent.isVisible) && this.levelVisible;
  5628. // Detect a change of visibility
  5629. this._changeFlags(BABYLON.SmartPropertyPrim.flagVisibilityChanged, curVisibleState !== this.isVisible);
  5630. // Get/compute the localTransform
  5631. var localDirty = this._updateLocalTransform();
  5632. var parentPaddingChanged = false;
  5633. var parentPaddingOffset = Prim2DBase._v0;
  5634. if (this._parent) {
  5635. parentPaddingOffset = new BABYLON.Vector2(this._parent._paddingOffset.x, this._parent._paddingOffset.y);
  5636. parentPaddingChanged = !parentPaddingOffset.equals(this._parentPaddingOffset);
  5637. }
  5638. // Check if there are changes in the parent that will force us to update the global matrix
  5639. var parentDirty = (this._parent != null) ? (this._parent._globalTransformStep !== this._parentTransformStep) : false;
  5640. // Check if we have to update the globalTransform
  5641. if (!this._globalTransform || localDirty || parentDirty || parentPaddingChanged || this._areSomeFlagsSet(BABYLON.SmartPropertyPrim.flagGlobalTransformDirty)) {
  5642. var globalTransform = this._parent ? this._parent._globalTransform : null;
  5643. var localTransform = void 0;
  5644. Prim2DBase._transMtx.copyFrom(this._localTransform);
  5645. Prim2DBase._transMtx.m[12] += parentPaddingOffset.x;
  5646. Prim2DBase._transMtx.m[13] += parentPaddingOffset.y;
  5647. localTransform = Prim2DBase._transMtx;
  5648. this._globalTransform = this._parent ? localTransform.multiply(globalTransform) : localTransform.clone();
  5649. this._invGlobalTransform = BABYLON.Matrix.Invert(this._globalTransform);
  5650. this._globalTransformStep = this.owner._globalTransformProcessStep + 1;
  5651. this._parentTransformStep = this._parent ? this._parent._globalTransformStep : 0;
  5652. this._clearFlags(BABYLON.SmartPropertyPrim.flagGlobalTransformDirty);
  5653. }
  5654. this._globalTransformProcessStep = this.owner._globalTransformProcessStep;
  5655. }
  5656. if (recurse) {
  5657. for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
  5658. var child = _a[_i];
  5659. // Stop the recursion if we meet a renderable group
  5660. child.updateCachedStates(!(child instanceof BABYLON.Group2D && child.isRenderableGroup));
  5661. }
  5662. }
  5663. };
  5664. Prim2DBase.prototype._updatePositioning = function () {
  5665. if (this.owner) {
  5666. this.owner.addUpdatePositioningCounter(1);
  5667. }
  5668. // From this point we assume that the primitive layoutArea is computed and up to date.
  5669. // We know have to :
  5670. // 1. Determine the PaddingArea and the ActualPosition based on the margin/marginAlignment properties, which will also set the size property of the primitive
  5671. // 2. Determine the contentArea based on the padding property.
  5672. var isSizeAuto = this.isSizeAuto;
  5673. // Auto Create PaddingArea if there's no actualSize on width&|height to allocate the whole content available to the paddingArea where the actualSize is null
  5674. if (!this._hasMarginAlignment && (isSizeAuto || (this.actualSize.width == null || this.actualSize.height == null))) {
  5675. if (isSizeAuto || this.actualSize.width == null) {
  5676. this.marginAlignment.horizontal = PrimitiveAlignment.AlignStretch;
  5677. }
  5678. if (isSizeAuto || this.actualSize.height == null) {
  5679. this.marginAlignment.vertical = PrimitiveAlignment.AlignStretch;
  5680. }
  5681. }
  5682. // Apply margin
  5683. if (this._hasMargin) {
  5684. this.margin.computeWithAlignment(this.layoutArea, this.size || this.actualSize, this.marginAlignment, this._marginOffset, Prim2DBase._size);
  5685. this.actualSize = Prim2DBase._size.clone();
  5686. }
  5687. var po = new BABYLON.Vector2(this._paddingOffset.x, this._paddingOffset.y);
  5688. if (this._hasPadding) {
  5689. // Two cases from here: the size of the Primitive is Auto, its content can't be shrink, so me resize the primitive itself
  5690. if (isSizeAuto) {
  5691. var content = this.size.clone();
  5692. this._getActualSizeFromContentToRef(content, Prim2DBase._icArea);
  5693. this.padding.enlarge(Prim2DBase._icArea, po, Prim2DBase._size);
  5694. this._contentArea.copyFrom(content);
  5695. this.actualSize = Prim2DBase._size.clone();
  5696. // Changing the padding has resize the prim, which forces us to recompute margin again
  5697. if (this._hasMargin) {
  5698. this.margin.computeWithAlignment(this.layoutArea, Prim2DBase._size, this.marginAlignment, this._marginOffset, Prim2DBase._size);
  5699. }
  5700. }
  5701. else {
  5702. this._getInitialContentAreaToRef(this.actualSize, Prim2DBase._icZone, Prim2DBase._icArea);
  5703. Prim2DBase._icArea.width = Math.max(0, Prim2DBase._icArea.width);
  5704. Prim2DBase._icArea.height = Math.max(0, Prim2DBase._icArea.height);
  5705. this.padding.compute(Prim2DBase._icArea, po, Prim2DBase._size);
  5706. this._paddingOffset.x = po.x;
  5707. this._paddingOffset.y = po.y;
  5708. this._paddingOffset.x += Prim2DBase._icZone.x;
  5709. this._paddingOffset.y += Prim2DBase._icZone.y;
  5710. this._paddingOffset.z -= Prim2DBase._icZone.z;
  5711. this._paddingOffset.w -= Prim2DBase._icZone.w;
  5712. this._contentArea.copyFrom(Prim2DBase._size);
  5713. }
  5714. }
  5715. else {
  5716. this._getInitialContentAreaToRef(this.actualSize, Prim2DBase._icZone, Prim2DBase._icArea);
  5717. Prim2DBase._icArea.width = Math.max(0, Prim2DBase._icArea.width);
  5718. Prim2DBase._icArea.height = Math.max(0, Prim2DBase._icArea.height);
  5719. this._paddingOffset.x = Prim2DBase._icZone.x;
  5720. this._paddingOffset.y = Prim2DBase._icZone.y;
  5721. this._paddingOffset.z = Prim2DBase._icZone.z;
  5722. this._paddingOffset.w = Prim2DBase._icZone.z;
  5723. this._contentArea.copyFrom(Prim2DBase._icArea);
  5724. }
  5725. if (!this._position) {
  5726. var aPos = new BABYLON.Vector2(this.layoutAreaPos.x + this._marginOffset.x, this.layoutAreaPos.y + this._marginOffset.y);
  5727. this.actualPosition = aPos;
  5728. }
  5729. if (isSizeAuto) {
  5730. this._lastAutoSizeArea = this.actualSize;
  5731. }
  5732. if (this.displayDebugAreas) {
  5733. this._updateDebugArea();
  5734. }
  5735. };
  5736. Object.defineProperty(Prim2DBase.prototype, "contentArea", {
  5737. /**
  5738. * Get the content are of this primitive, this area is computed using the padding property and also possibly the primitive type itself.
  5739. * Children of this primitive will be positioned relative to the bottom/left corner of this area.
  5740. */
  5741. get: function () {
  5742. // Check for positioning update
  5743. if (this._isFlagSet(BABYLON.SmartPropertyPrim.flagPositioningDirty)) {
  5744. this._updatePositioning();
  5745. this._clearFlags(BABYLON.SmartPropertyPrim.flagPositioningDirty);
  5746. }
  5747. return this._contentArea;
  5748. },
  5749. enumerable: true,
  5750. configurable: true
  5751. });
  5752. Prim2DBase.prototype._patchHierarchy = function (owner) {
  5753. this._owner = owner;
  5754. // The only place we initialize the _renderGroup is this method, if it's set, we already been there, no need to execute more
  5755. if (this._renderGroup != null) {
  5756. return;
  5757. }
  5758. if (this instanceof BABYLON.Group2D) {
  5759. var group = this;
  5760. group.detectGroupStates();
  5761. if (group._trackedNode && !group._isFlagSet(BABYLON.SmartPropertyPrim.flagTrackedGroup)) {
  5762. group.owner._registerTrackedNode(this);
  5763. }
  5764. }
  5765. this._renderGroup = this.traverseUp(function (p) { return p instanceof BABYLON.Group2D && p.isRenderableGroup; });
  5766. if (this._parent) {
  5767. this._parentLayoutDirty();
  5768. }
  5769. // Make sure the prim is in the dirtyList if it should be
  5770. if (this._renderGroup && this.isDirty) {
  5771. var list = this._renderGroup._renderableData._primDirtyList;
  5772. var i = list.indexOf(this);
  5773. if (i === -1) {
  5774. list.push(this);
  5775. }
  5776. }
  5777. // Recurse
  5778. for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
  5779. var child = _a[_i];
  5780. child._hierarchyDepth = this._hierarchyDepth + 1;
  5781. child._patchHierarchy(owner);
  5782. }
  5783. };
  5784. Prim2DBase.prototype._updateZOrder = function () {
  5785. var prevLinPos = this._primLinearPosition;
  5786. var startI = 0;
  5787. var startZ = this._zOrder;
  5788. // We must start rebuilding Z-Order from the Prim before the first one that changed, because we know its Z-Order is correct, so are its children, but it's better to recompute everything from this point instead of finding the last valid children
  5789. var childrenCount = this._children.length;
  5790. if (this._firstZDirtyIndex > 0) {
  5791. if ((this._firstZDirtyIndex - 1) < childrenCount) {
  5792. var prevPrim = this._children[this._firstZDirtyIndex - 1];
  5793. prevLinPos = prevPrim._primLinearPosition;
  5794. startI = this._firstZDirtyIndex - 1;
  5795. startZ = prevPrim._zOrder;
  5796. }
  5797. }
  5798. var startPos = prevLinPos;
  5799. // Update the linear position of the primitive from the first one to the last inside this primitive, compute the total number of prim traversed
  5800. Prim2DBase._totalCount = 0;
  5801. for (var i = startI; i < childrenCount; i++) {
  5802. var child = this._children[i];
  5803. prevLinPos = child._updatePrimitiveLinearPosition(prevLinPos);
  5804. }
  5805. // Compute the new Z-Order for all the primitives
  5806. // Add 20% to the current total count to reserve space for future insertions, except if we're rebuilding due to a zMinDelta reached
  5807. var zDelta = (this._zMax - startZ) / (Prim2DBase._totalCount * (Prim2DBase._zRebuildReentrency ? 1 : 1.2));
  5808. // If the computed delta is less than the smallest allowed by the depth buffer, we rebuild the Z-Order from the very beginning of the primitive's children (that is, the first) to redistribute uniformly the Z.
  5809. if (zDelta < BABYLON.Canvas2D._zMinDelta) {
  5810. // Check for re-entrance, if the flag is true we already attempted a rebuild but couldn't get a better zDelta, go up in the hierarchy to rebuilt one level up, hoping to get this time a decent delta, otherwise, recurse until we got it or when no parent is reached, which would mean the canvas would have more than 16 millions of primitives...
  5811. if (Prim2DBase._zRebuildReentrency) {
  5812. var p = this._parent;
  5813. if (p == null) {
  5814. // Can't find a good Z delta and we're in the canvas, which mean we're dealing with too many objects (which should never happen, but well...)
  5815. console.log("Can't compute Z-Order for " + this.id + "'s children, zDelta is too small, Z-Order is now in an unstable state");
  5816. Prim2DBase._zRebuildReentrency = false;
  5817. return;
  5818. }
  5819. p._firstZDirtyIndex = 0;
  5820. return p._updateZOrder();
  5821. }
  5822. Prim2DBase._zRebuildReentrency = true;
  5823. this._firstZDirtyIndex = 0;
  5824. this._updateZOrder();
  5825. Prim2DBase._zRebuildReentrency = false;
  5826. }
  5827. for (var i = startI; i < childrenCount; i++) {
  5828. var child = this._children[i];
  5829. child._updatePrimitiveZOrder(startPos, startZ, zDelta);
  5830. }
  5831. // Notify the Observers that we found during the Z change (we do it after to avoid any kind of re-entrance)
  5832. for (var _i = 0, _a = Prim2DBase._zOrderChangedNotifList; _i < _a.length; _i++) {
  5833. var p = _a[_i];
  5834. p._actualZOrderChangedObservable.notifyObservers(p.actualZOffset);
  5835. }
  5836. Prim2DBase._zOrderChangedNotifList.splice(0);
  5837. this._firstZDirtyIndex = Prim2DBase._bigInt;
  5838. this._clearFlags(BABYLON.SmartPropertyPrim.flagZOrderDirty);
  5839. };
  5840. Prim2DBase.prototype._updatePrimitiveLinearPosition = function (prevLinPos) {
  5841. if (this.isManualZOrder) {
  5842. return prevLinPos;
  5843. }
  5844. this._primLinearPosition = ++prevLinPos;
  5845. Prim2DBase._totalCount++;
  5846. // Check for the FlatZOrder, which means the children won't have a dedicated Z-Order but will all share the same (unique) one.
  5847. if (!this._isFlagSet(BABYLON.SmartPropertyPrim.flagChildrenFlatZOrder)) {
  5848. for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
  5849. var child = _a[_i];
  5850. prevLinPos = child._updatePrimitiveLinearPosition(prevLinPos);
  5851. }
  5852. }
  5853. return prevLinPos;
  5854. };
  5855. Prim2DBase.prototype._updatePrimitiveZOrder = function (startPos, startZ, deltaZ) {
  5856. if (this.isManualZOrder) {
  5857. return null;
  5858. }
  5859. var newZ = startZ + ((this._primLinearPosition - startPos) * deltaZ);
  5860. var isFlat = this._isFlagSet(BABYLON.SmartPropertyPrim.flagChildrenFlatZOrder);
  5861. this._setZOrder(newZ, false);
  5862. if (this._isFlagSet(BABYLON.SmartPropertyPrim.flagZOrderDirty)) {
  5863. this._firstZDirtyIndex = Prim2DBase._bigInt;
  5864. this._clearFlags(BABYLON.SmartPropertyPrim.flagZOrderDirty);
  5865. }
  5866. var curZ = newZ;
  5867. // Check for the FlatZOrder, which means the children won't have a dedicated Z-Order but will all share the same (unique) one.
  5868. if (isFlat) {
  5869. if (this._children.length > 0) {
  5870. //let childrenZOrder = startZ + ((this._children[0]._primLinearPosition - startPos) * deltaZ);
  5871. for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
  5872. var child = _a[_i];
  5873. child._updatePrimitiveFlatZOrder(this._zOrder);
  5874. }
  5875. }
  5876. }
  5877. else {
  5878. for (var _b = 0, _c = this._children; _b < _c.length; _b++) {
  5879. var child = _c[_b];
  5880. var r = child._updatePrimitiveZOrder(startPos, startZ, deltaZ);
  5881. if (r != null) {
  5882. curZ = r;
  5883. }
  5884. }
  5885. }
  5886. this._zMax = isFlat ? newZ : (curZ + deltaZ);
  5887. return curZ;
  5888. };
  5889. Prim2DBase.prototype._updatePrimitiveFlatZOrder = function (newZ) {
  5890. if (this.isManualZOrder) {
  5891. return;
  5892. }
  5893. this._setZOrder(newZ, false);
  5894. this._zMax = newZ;
  5895. if (this._isFlagSet(BABYLON.SmartPropertyPrim.flagZOrderDirty)) {
  5896. this._firstZDirtyIndex = Prim2DBase._bigInt;
  5897. this._clearFlags(BABYLON.SmartPropertyPrim.flagZOrderDirty);
  5898. }
  5899. for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
  5900. var child = _a[_i];
  5901. child._updatePrimitiveFlatZOrder(newZ);
  5902. }
  5903. };
  5904. Prim2DBase.prototype._setZOrder = function (newZ, directEmit) {
  5905. if (newZ !== this._zOrder) {
  5906. this._zOrder = newZ;
  5907. this.onPrimBecomesDirty();
  5908. this.onZOrderChanged();
  5909. if (this._actualZOrderChangedObservable && this._actualZOrderChangedObservable.hasObservers()) {
  5910. if (directEmit) {
  5911. this._actualZOrderChangedObservable.notifyObservers(newZ);
  5912. }
  5913. else {
  5914. Prim2DBase._zOrderChangedNotifList.push(this);
  5915. }
  5916. }
  5917. }
  5918. };
  5919. Prim2DBase.prototype._updateRenderMode = function () {
  5920. };
  5921. /**
  5922. * This method is used to alter the contentArea of the Primitive before margin is applied.
  5923. * In most of the case you won't need to override this method, but it can prove some usefulness, check the Rectangle2D class for a concrete application.
  5924. * @param primSize the current size of the primitive
  5925. * @param initialContentPosition the position of the initial content area to compute, a valid object is passed, you have to set its properties. PLEASE ROUND the values, we're talking about pixels and fraction of them is not a good thing! x, y, z, w area left, bottom, right, top
  5926. * @param initialContentArea the size of the initial content area to compute, a valid object is passed, you have to set its properties. PLEASE ROUND the values, we're talking about pixels and fraction of them is not a good thing!
  5927. */
  5928. Prim2DBase.prototype._getInitialContentAreaToRef = function (primSize, initialContentPosition, initialContentArea) {
  5929. initialContentArea.copyFrom(primSize);
  5930. initialContentPosition.x = initialContentPosition.y = initialContentPosition.z = initialContentPosition.w = 0;
  5931. };
  5932. /**
  5933. * This method is used to calculate the new size of the primitive based on the content which must stay the same
  5934. * Check the Rectangle2D implementation for a concrete application.
  5935. * @param primSize the current size of the primitive
  5936. * @param newPrimSize the new size of the primitive. PLEASE ROUND THE values, we're talking about pixels and fraction of them are not our friends!
  5937. */
  5938. Prim2DBase.prototype._getActualSizeFromContentToRef = function (primSize, newPrimSize) {
  5939. newPrimSize.copyFrom(primSize);
  5940. };
  5941. Prim2DBase.PRIM2DBASE_PROPCOUNT = 24;
  5942. Prim2DBase._bigInt = Math.pow(2, 30);
  5943. Prim2DBase._nullPosition = BABYLON.Vector2.Zero();
  5944. Prim2DBase.boundinbBoxReentrency = false;
  5945. Prim2DBase.nullSize = BABYLON.Size.Zero();
  5946. Prim2DBase._bMax = BABYLON.Vector2.Zero();
  5947. Prim2DBase._tpsBB = new BABYLON.BoundingInfo2D();
  5948. Prim2DBase._isCanvasInit = false;
  5949. Prim2DBase._t0 = new BABYLON.Matrix();
  5950. Prim2DBase._t1 = new BABYLON.Matrix();
  5951. Prim2DBase._t2 = new BABYLON.Matrix();
  5952. Prim2DBase._v0 = BABYLON.Vector2.Zero(); // Must stay with the value 0,0
  5953. Prim2DBase._transMtx = BABYLON.Matrix.Zero();
  5954. Prim2DBase._icPos = BABYLON.Vector2.Zero();
  5955. Prim2DBase._icZone = BABYLON.Vector4.Zero();
  5956. Prim2DBase._icArea = BABYLON.Size.Zero();
  5957. Prim2DBase._size = BABYLON.Size.Zero();
  5958. Prim2DBase._zOrderChangedNotifList = new Array();
  5959. Prim2DBase._zRebuildReentrency = false;
  5960. Prim2DBase._totalCount = 0;
  5961. __decorate([
  5962. BABYLON.instanceLevelProperty(1, function (pi) { return Prim2DBase.actualPositionProperty = pi; }, false, false, true)
  5963. ], Prim2DBase.prototype, "actualPosition", null);
  5964. __decorate([
  5965. BABYLON.instanceLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 1, function (pi) { return Prim2DBase.actualXProperty = pi; }, false, false, true)
  5966. ], Prim2DBase.prototype, "actualX", null);
  5967. __decorate([
  5968. BABYLON.instanceLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 2, function (pi) { return Prim2DBase.actualYProperty = pi; }, false, false, true)
  5969. ], Prim2DBase.prototype, "actualY", null);
  5970. __decorate([
  5971. BABYLON.dynamicLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 3, function (pi) { return Prim2DBase.positionProperty = pi; }, false, false, true)
  5972. ], Prim2DBase.prototype, "position", null);
  5973. __decorate([
  5974. BABYLON.dynamicLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 4, function (pi) { return Prim2DBase.xProperty = pi; }, false, false, true)
  5975. ], Prim2DBase.prototype, "x", null);
  5976. __decorate([
  5977. BABYLON.dynamicLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 5, function (pi) { return Prim2DBase.yProperty = pi; }, false, false, true)
  5978. ], Prim2DBase.prototype, "y", null);
  5979. __decorate([
  5980. BABYLON.dynamicLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 6, function (pi) { return Prim2DBase.sizeProperty = pi; }, false, true)
  5981. ], Prim2DBase.prototype, "size", null);
  5982. __decorate([
  5983. BABYLON.dynamicLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 7, function (pi) { return Prim2DBase.widthProperty = pi; }, false, true)
  5984. ], Prim2DBase.prototype, "width", null);
  5985. __decorate([
  5986. BABYLON.dynamicLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 8, function (pi) { return Prim2DBase.heightProperty = pi; }, false, true)
  5987. ], Prim2DBase.prototype, "height", null);
  5988. __decorate([
  5989. BABYLON.instanceLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 9, function (pi) { return Prim2DBase.rotationProperty = pi; }, false, true)
  5990. ], Prim2DBase.prototype, "rotation", null);
  5991. __decorate([
  5992. BABYLON.instanceLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 10, function (pi) { return Prim2DBase.scaleProperty = pi; }, false, true)
  5993. ], Prim2DBase.prototype, "scale", null);
  5994. __decorate([
  5995. BABYLON.dynamicLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 11, function (pi) { return Prim2DBase.actualSizeProperty = pi; }, false, true)
  5996. ], Prim2DBase.prototype, "actualSize", null);
  5997. __decorate([
  5998. BABYLON.dynamicLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 12, function (pi) { return Prim2DBase.actualWidthProperty = pi; }, false, true)
  5999. ], Prim2DBase.prototype, "actualWidth", null);
  6000. __decorate([
  6001. BABYLON.dynamicLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 13, function (pi) { return Prim2DBase.actualHeightProperty = pi; }, false, true)
  6002. ], Prim2DBase.prototype, "actualHeight", null);
  6003. __decorate([
  6004. BABYLON.dynamicLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 14, function (pi) { return Prim2DBase.originProperty = pi; }, false, true)
  6005. ], Prim2DBase.prototype, "origin", null);
  6006. __decorate([
  6007. BABYLON.dynamicLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 15, function (pi) { return Prim2DBase.levelVisibleProperty = pi; })
  6008. ], Prim2DBase.prototype, "levelVisible", null);
  6009. __decorate([
  6010. BABYLON.instanceLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 16, function (pi) { return Prim2DBase.isVisibleProperty = pi; })
  6011. ], Prim2DBase.prototype, "isVisible", null);
  6012. __decorate([
  6013. BABYLON.instanceLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 17, function (pi) { return Prim2DBase.zOrderProperty = pi; })
  6014. ], Prim2DBase.prototype, "zOrder", null);
  6015. __decorate([
  6016. BABYLON.dynamicLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 18, function (pi) { return Prim2DBase.marginProperty = pi; })
  6017. ], Prim2DBase.prototype, "margin", null);
  6018. __decorate([
  6019. BABYLON.dynamicLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 19, function (pi) { return Prim2DBase.paddingProperty = pi; })
  6020. ], Prim2DBase.prototype, "padding", null);
  6021. __decorate([
  6022. BABYLON.dynamicLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 20, function (pi) { return Prim2DBase.marginAlignmentProperty = pi; })
  6023. ], Prim2DBase.prototype, "marginAlignment", null);
  6024. __decorate([
  6025. BABYLON.instanceLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 21, function (pi) { return Prim2DBase.opacityProperty = pi; })
  6026. ], Prim2DBase.prototype, "opacity", null);
  6027. __decorate([
  6028. BABYLON.instanceLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 22, function (pi) { return Prim2DBase.scaleXProperty = pi; }, false, true)
  6029. ], Prim2DBase.prototype, "scaleX", null);
  6030. __decorate([
  6031. BABYLON.instanceLevelProperty(BABYLON.SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 23, function (pi) { return Prim2DBase.scaleYProperty = pi; }, false, true)
  6032. ], Prim2DBase.prototype, "scaleY", null);
  6033. Prim2DBase = __decorate([
  6034. BABYLON.className("Prim2DBase", "BABYLON")
  6035. ], Prim2DBase);
  6036. return Prim2DBase;
  6037. }(BABYLON.SmartPropertyPrim));
  6038. BABYLON.Prim2DBase = Prim2DBase;
  6039. })(BABYLON || (BABYLON = {}));
  6040. var BABYLON;
  6041. (function (BABYLON) {
  6042. var GroupInstanceInfo = (function () {
  6043. function GroupInstanceInfo(owner, mrc, partCount) {
  6044. this._partCount = partCount;
  6045. this.owner = owner;
  6046. this.modelRenderCache = mrc;
  6047. this.modelRenderCache.addRef();
  6048. this.partIndexFromId = new BABYLON.StringDictionary();
  6049. this._usedShaderCategories = new Array(partCount);
  6050. this._strides = new Array(partCount);
  6051. this._opaqueData = null;
  6052. this._alphaTestData = null;
  6053. this._transparentData = null;
  6054. this.opaqueDirty = this.alphaTestDirty = this.transparentDirty = this.transparentOrderDirty = false;
  6055. }
  6056. GroupInstanceInfo.prototype.dispose = function () {
  6057. if (this._isDisposed) {
  6058. return false;
  6059. }
  6060. if (this.modelRenderCache) {
  6061. this.modelRenderCache.dispose();
  6062. this.modelRenderCache = null;
  6063. }
  6064. var engine = this.owner.owner.engine;
  6065. if (this._opaqueData) {
  6066. this._opaqueData.forEach(function (d) { return d.dispose(engine); });
  6067. this._opaqueData = null;
  6068. }
  6069. if (this._alphaTestData) {
  6070. this._alphaTestData.forEach(function (d) { return d.dispose(engine); });
  6071. this._alphaTestData = null;
  6072. }
  6073. if (this._transparentData) {
  6074. this._transparentData.forEach(function (d) { return d.dispose(engine); });
  6075. this._transparentData = null;
  6076. }
  6077. this.partIndexFromId = null;
  6078. this._isDisposed = true;
  6079. return true;
  6080. };
  6081. Object.defineProperty(GroupInstanceInfo.prototype, "hasOpaqueData", {
  6082. get: function () {
  6083. return this._opaqueData != null;
  6084. },
  6085. enumerable: true,
  6086. configurable: true
  6087. });
  6088. Object.defineProperty(GroupInstanceInfo.prototype, "hasAlphaTestData", {
  6089. get: function () {
  6090. return this._alphaTestData != null;
  6091. },
  6092. enumerable: true,
  6093. configurable: true
  6094. });
  6095. Object.defineProperty(GroupInstanceInfo.prototype, "hasTransparentData", {
  6096. get: function () {
  6097. return this._transparentData != null;
  6098. },
  6099. enumerable: true,
  6100. configurable: true
  6101. });
  6102. Object.defineProperty(GroupInstanceInfo.prototype, "opaqueData", {
  6103. get: function () {
  6104. if (!this._opaqueData) {
  6105. this._opaqueData = new Array(this._partCount);
  6106. for (var i = 0; i < this._partCount; i++) {
  6107. this._opaqueData[i] = new GroupInfoPartData(this._strides[i]);
  6108. }
  6109. }
  6110. return this._opaqueData;
  6111. },
  6112. enumerable: true,
  6113. configurable: true
  6114. });
  6115. Object.defineProperty(GroupInstanceInfo.prototype, "alphaTestData", {
  6116. get: function () {
  6117. if (!this._alphaTestData) {
  6118. this._alphaTestData = new Array(this._partCount);
  6119. for (var i = 0; i < this._partCount; i++) {
  6120. this._alphaTestData[i] = new GroupInfoPartData(this._strides[i]);
  6121. }
  6122. }
  6123. return this._alphaTestData;
  6124. },
  6125. enumerable: true,
  6126. configurable: true
  6127. });
  6128. Object.defineProperty(GroupInstanceInfo.prototype, "transparentData", {
  6129. get: function () {
  6130. if (!this._transparentData) {
  6131. this._transparentData = new Array(this._partCount);
  6132. for (var i = 0; i < this._partCount; i++) {
  6133. var zoff = this.modelRenderCache._partData[i]._zBiasOffset;
  6134. this._transparentData[i] = new TransparentGroupInfoPartData(this._strides[i], zoff);
  6135. }
  6136. }
  6137. return this._transparentData;
  6138. },
  6139. enumerable: true,
  6140. configurable: true
  6141. });
  6142. GroupInstanceInfo.prototype.sortTransparentData = function () {
  6143. if (!this.transparentOrderDirty) {
  6144. return;
  6145. }
  6146. for (var i = 0; i < this._transparentData.length; i++) {
  6147. var td = this._transparentData[i];
  6148. td._partData.sort();
  6149. }
  6150. this.transparentOrderDirty = false;
  6151. };
  6152. Object.defineProperty(GroupInstanceInfo.prototype, "usedShaderCategories", {
  6153. get: function () {
  6154. return this._usedShaderCategories;
  6155. },
  6156. enumerable: true,
  6157. configurable: true
  6158. });
  6159. Object.defineProperty(GroupInstanceInfo.prototype, "strides", {
  6160. get: function () {
  6161. return this._strides;
  6162. },
  6163. enumerable: true,
  6164. configurable: true
  6165. });
  6166. return GroupInstanceInfo;
  6167. }());
  6168. BABYLON.GroupInstanceInfo = GroupInstanceInfo;
  6169. var TransparentSegment = (function () {
  6170. function TransparentSegment() {
  6171. this.groupInsanceInfo = null;
  6172. this.startZ = 0;
  6173. this.endZ = 0;
  6174. this.startDataIndex = BABYLON.Prim2DBase._bigInt;
  6175. this.endDataIndex = 0;
  6176. this.partBuffers = null;
  6177. }
  6178. TransparentSegment.prototype.dispose = function (engine) {
  6179. if (this.partBuffers) {
  6180. this.partBuffers.forEach(function (b) { return engine._releaseBuffer(b); });
  6181. this.partBuffers.splice(0);
  6182. this.partBuffers = null;
  6183. }
  6184. };
  6185. return TransparentSegment;
  6186. }());
  6187. BABYLON.TransparentSegment = TransparentSegment;
  6188. var GroupInfoPartData = (function () {
  6189. function GroupInfoPartData(stride) {
  6190. this._partData = null;
  6191. this._partBuffer = null;
  6192. this._partBufferSize = 0;
  6193. this._partData = new BABYLON.DynamicFloatArray(stride / 4, 50);
  6194. this._isDisposed = false;
  6195. }
  6196. GroupInfoPartData.prototype.dispose = function (engine) {
  6197. if (this._isDisposed) {
  6198. return false;
  6199. }
  6200. if (this._partBuffer) {
  6201. engine._releaseBuffer(this._partBuffer);
  6202. this._partBuffer = null;
  6203. }
  6204. this._partData = null;
  6205. this._isDisposed = true;
  6206. };
  6207. return GroupInfoPartData;
  6208. }());
  6209. BABYLON.GroupInfoPartData = GroupInfoPartData;
  6210. var TransparentGroupInfoPartData = (function (_super) {
  6211. __extends(TransparentGroupInfoPartData, _super);
  6212. function TransparentGroupInfoPartData(stride, zoff) {
  6213. _super.call(this, stride);
  6214. this._partData.compareValueOffset = zoff;
  6215. this._partData.sortingAscending = false;
  6216. }
  6217. return TransparentGroupInfoPartData;
  6218. }(GroupInfoPartData));
  6219. BABYLON.TransparentGroupInfoPartData = TransparentGroupInfoPartData;
  6220. var ModelRenderCache = (function () {
  6221. function ModelRenderCache(engine, modelKey) {
  6222. this._engine = engine;
  6223. this._modelKey = modelKey;
  6224. this._nextKey = 1;
  6225. this._refCounter = 1;
  6226. this._partData = null;
  6227. }
  6228. ModelRenderCache.prototype.dispose = function () {
  6229. if (--this._refCounter !== 0) {
  6230. return false;
  6231. }
  6232. // Remove the Model Render Cache from the global dictionary
  6233. var edata = this._engine.getExternalData("__BJSCANVAS2D__");
  6234. if (edata) {
  6235. edata.DisposeModelRenderCache(this);
  6236. }
  6237. return true;
  6238. };
  6239. Object.defineProperty(ModelRenderCache.prototype, "isDisposed", {
  6240. get: function () {
  6241. return this._refCounter <= 0;
  6242. },
  6243. enumerable: true,
  6244. configurable: true
  6245. });
  6246. ModelRenderCache.prototype.addRef = function () {
  6247. return ++this._refCounter;
  6248. };
  6249. Object.defineProperty(ModelRenderCache.prototype, "modelKey", {
  6250. get: function () {
  6251. return this._modelKey;
  6252. },
  6253. enumerable: true,
  6254. configurable: true
  6255. });
  6256. /**
  6257. * Render the model instances
  6258. * @param instanceInfo
  6259. * @param context
  6260. * @return must return true is the rendering succeed, false if the rendering couldn't be done (asset's not yet ready, like Effect)
  6261. */
  6262. ModelRenderCache.prototype.render = function (instanceInfo, context) {
  6263. return true;
  6264. };
  6265. ModelRenderCache.prototype.getPartIndexFromId = function (partId) {
  6266. for (var i = 0; i < this._partData.length; i++) {
  6267. if (this._partData[i]._partId === partId) {
  6268. return i;
  6269. }
  6270. }
  6271. return null;
  6272. };
  6273. ModelRenderCache.prototype.loadInstancingAttributes = function (partId, effect) {
  6274. var i = this.getPartIndexFromId(partId);
  6275. if (i === null) {
  6276. return null;
  6277. }
  6278. var ci = this._partsClassInfo[i];
  6279. var categories = this._partData[i]._partUsedCategories;
  6280. var res = ci.classContent.getInstancingAttributeInfos(effect, categories);
  6281. return res;
  6282. };
  6283. ModelRenderCache.prototype.setupUniforms = function (effect, partIndex, data, elementCount) {
  6284. var pd = this._partData[partIndex];
  6285. var offset = (pd._partDataStride / 4) * elementCount;
  6286. var pci = this._partsClassInfo[partIndex];
  6287. var self = this;
  6288. pci.fullContent.forEach(function (k, v) {
  6289. if (!v.category || pd._partUsedCategories.indexOf(v.category) !== -1) {
  6290. switch (v.dataType) {
  6291. case 4 /* float */:
  6292. {
  6293. var attribOffset = v.instanceOffset.get(pd._partJoinedUsedCategories);
  6294. effect.setFloat(v.attributeName, data.buffer[offset + attribOffset]);
  6295. break;
  6296. }
  6297. case 0 /* Vector2 */:
  6298. {
  6299. var attribOffset = v.instanceOffset.get(pd._partJoinedUsedCategories);
  6300. ModelRenderCache.v2.x = data.buffer[offset + attribOffset + 0];
  6301. ModelRenderCache.v2.y = data.buffer[offset + attribOffset + 1];
  6302. effect.setVector2(v.attributeName, ModelRenderCache.v2);
  6303. break;
  6304. }
  6305. case 5 /* Color3 */:
  6306. case 1 /* Vector3 */:
  6307. {
  6308. var attribOffset = v.instanceOffset.get(pd._partJoinedUsedCategories);
  6309. ModelRenderCache.v3.x = data.buffer[offset + attribOffset + 0];
  6310. ModelRenderCache.v3.y = data.buffer[offset + attribOffset + 1];
  6311. ModelRenderCache.v3.z = data.buffer[offset + attribOffset + 2];
  6312. effect.setVector3(v.attributeName, ModelRenderCache.v3);
  6313. break;
  6314. }
  6315. case 6 /* Color4 */:
  6316. case 2 /* Vector4 */:
  6317. {
  6318. var attribOffset = v.instanceOffset.get(pd._partJoinedUsedCategories);
  6319. ModelRenderCache.v4.x = data.buffer[offset + attribOffset + 0];
  6320. ModelRenderCache.v4.y = data.buffer[offset + attribOffset + 1];
  6321. ModelRenderCache.v4.z = data.buffer[offset + attribOffset + 2];
  6322. ModelRenderCache.v4.w = data.buffer[offset + attribOffset + 3];
  6323. effect.setVector4(v.attributeName, ModelRenderCache.v4);
  6324. break;
  6325. }
  6326. default:
  6327. }
  6328. }
  6329. });
  6330. };
  6331. //setupUniformsLocation(effect: Effect, uniforms: string[], partId: number) {
  6332. // let i = this.getPartIndexFromId(partId);
  6333. // if (i === null) {
  6334. // return null;
  6335. // }
  6336. // let pci = this._partsClassInfo[i];
  6337. // pci.fullContent.forEach((k, v) => {
  6338. // if (uniforms.indexOf(v.attributeName) !== -1) {
  6339. // v.uniformLocation = effect.getUniform(v.attributeName);
  6340. // }
  6341. // });
  6342. //}
  6343. ModelRenderCache.v2 = BABYLON.Vector2.Zero();
  6344. ModelRenderCache.v3 = BABYLON.Vector3.Zero();
  6345. ModelRenderCache.v4 = BABYLON.Vector4.Zero();
  6346. return ModelRenderCache;
  6347. }());
  6348. BABYLON.ModelRenderCache = ModelRenderCache;
  6349. var ModelRenderCachePartData = (function () {
  6350. function ModelRenderCachePartData() {
  6351. }
  6352. return ModelRenderCachePartData;
  6353. }());
  6354. BABYLON.ModelRenderCachePartData = ModelRenderCachePartData;
  6355. })(BABYLON || (BABYLON = {}));
  6356. var BABYLON;
  6357. (function (BABYLON) {
  6358. var InstanceClassInfo = (function () {
  6359. function InstanceClassInfo(base) {
  6360. this._baseInfo = base;
  6361. this._nextOffset = new BABYLON.StringDictionary();
  6362. this._attributes = new Array();
  6363. }
  6364. InstanceClassInfo.prototype.mapProperty = function (propInfo, push) {
  6365. var curOff = this._nextOffset.getOrAdd(InstanceClassInfo._CurCategories, 0);
  6366. propInfo.instanceOffset.add(InstanceClassInfo._CurCategories, this._getBaseOffset(InstanceClassInfo._CurCategories) + curOff);
  6367. //console.log(`[${InstanceClassInfo._CurCategories}] New PropInfo. Category: ${propInfo.category}, Name: ${propInfo.attributeName}, Offset: ${propInfo.instanceOffset.get(InstanceClassInfo._CurCategories)}, Size: ${propInfo.size / 4}`);
  6368. this._nextOffset.set(InstanceClassInfo._CurCategories, curOff + (propInfo.size / 4));
  6369. if (push) {
  6370. this._attributes.push(propInfo);
  6371. }
  6372. };
  6373. InstanceClassInfo.prototype.getInstancingAttributeInfos = function (effect, categories) {
  6374. var catInline = ";" + categories.join(";") + ";";
  6375. var res = new Array();
  6376. var curInfo = this;
  6377. while (curInfo) {
  6378. for (var _i = 0, _a = curInfo._attributes; _i < _a.length; _i++) {
  6379. var attrib = _a[_i];
  6380. // Only map if there's no category assigned to the instance data or if there's a category and it's in the given list
  6381. if (!attrib.category || categories.indexOf(attrib.category) !== -1) {
  6382. var index = effect.getAttributeLocationByName(attrib.attributeName);
  6383. var iai = new BABYLON.InstancingAttributeInfo();
  6384. iai.index = index;
  6385. iai.attributeSize = attrib.size / 4; // attrib.size is in byte and we need to store in "component" (i.e float is 1, vec3 is 3)
  6386. iai.offset = attrib.instanceOffset.get(catInline) * 4; // attrib.instanceOffset is in float, iai.offset must be in bytes
  6387. iai.attributeName = attrib.attributeName;
  6388. res.push(iai);
  6389. }
  6390. }
  6391. curInfo = curInfo._baseInfo;
  6392. }
  6393. return res;
  6394. };
  6395. InstanceClassInfo.prototype.getShaderAttributes = function (categories) {
  6396. var res = new Array();
  6397. var curInfo = this;
  6398. while (curInfo) {
  6399. for (var _i = 0, _a = curInfo._attributes; _i < _a.length; _i++) {
  6400. var attrib = _a[_i];
  6401. // Only map if there's no category assigned to the instance data or if there's a category and it's in the given list
  6402. if (!attrib.category || categories.indexOf(attrib.category) !== -1) {
  6403. res.push(attrib.attributeName);
  6404. }
  6405. }
  6406. curInfo = curInfo._baseInfo;
  6407. }
  6408. return res;
  6409. };
  6410. InstanceClassInfo.prototype._getBaseOffset = function (categories) {
  6411. var curOffset = 0;
  6412. var curBase = this._baseInfo;
  6413. while (curBase) {
  6414. curOffset += curBase._nextOffset.getOrAdd(categories, 0);
  6415. curBase = curBase._baseInfo;
  6416. }
  6417. return curOffset;
  6418. };
  6419. return InstanceClassInfo;
  6420. }());
  6421. BABYLON.InstanceClassInfo = InstanceClassInfo;
  6422. var InstancePropInfo = (function () {
  6423. function InstancePropInfo() {
  6424. this.instanceOffset = new BABYLON.StringDictionary();
  6425. }
  6426. InstancePropInfo.prototype.setSize = function (val) {
  6427. if (val instanceof BABYLON.Vector2) {
  6428. this.size = 8;
  6429. this.dataType = 0 /* Vector2 */;
  6430. return;
  6431. }
  6432. if (val instanceof BABYLON.Vector3) {
  6433. this.size = 12;
  6434. this.dataType = 1 /* Vector3 */;
  6435. return;
  6436. }
  6437. if (val instanceof BABYLON.Vector4) {
  6438. this.size = 16;
  6439. this.dataType = 2 /* Vector4 */;
  6440. return;
  6441. }
  6442. if (val instanceof BABYLON.Matrix) {
  6443. throw new Error("Matrix type is not supported by WebGL Instance Buffer, you have to use four Vector4 properties instead");
  6444. }
  6445. if (typeof (val) === "number") {
  6446. this.size = 4;
  6447. this.dataType = 4 /* float */;
  6448. return;
  6449. }
  6450. if (val instanceof BABYLON.Color3) {
  6451. this.size = 12;
  6452. this.dataType = 5 /* Color3 */;
  6453. return;
  6454. }
  6455. if (val instanceof BABYLON.Color4) {
  6456. this.size = 16;
  6457. this.dataType = 6 /* Color4 */;
  6458. return;
  6459. }
  6460. if (val instanceof BABYLON.Size) {
  6461. this.size = 8;
  6462. this.dataType = 7 /* Size */;
  6463. return;
  6464. }
  6465. return;
  6466. };
  6467. InstancePropInfo.prototype.writeData = function (array, offset, val) {
  6468. switch (this.dataType) {
  6469. case 0 /* Vector2 */:
  6470. {
  6471. var v = val;
  6472. array[offset + 0] = v.x;
  6473. array[offset + 1] = v.y;
  6474. break;
  6475. }
  6476. case 1 /* Vector3 */:
  6477. {
  6478. var v = val;
  6479. array[offset + 0] = v.x;
  6480. array[offset + 1] = v.y;
  6481. array[offset + 2] = v.z;
  6482. break;
  6483. }
  6484. case 2 /* Vector4 */:
  6485. {
  6486. var v = val;
  6487. array[offset + 0] = v.x;
  6488. array[offset + 1] = v.y;
  6489. array[offset + 2] = v.z;
  6490. array[offset + 3] = v.w;
  6491. break;
  6492. }
  6493. case 5 /* Color3 */:
  6494. {
  6495. var v = val;
  6496. array[offset + 0] = v.r;
  6497. array[offset + 1] = v.g;
  6498. array[offset + 2] = v.b;
  6499. break;
  6500. }
  6501. case 6 /* Color4 */:
  6502. {
  6503. var v = val;
  6504. array[offset + 0] = v.r;
  6505. array[offset + 1] = v.g;
  6506. array[offset + 2] = v.b;
  6507. array[offset + 3] = v.a;
  6508. break;
  6509. }
  6510. case 4 /* float */:
  6511. {
  6512. var v = val;
  6513. array[offset] = v;
  6514. break;
  6515. }
  6516. case 3 /* Matrix */:
  6517. {
  6518. var v = val;
  6519. for (var i = 0; i < 16; i++) {
  6520. array[offset + i] = v.m[i];
  6521. }
  6522. break;
  6523. }
  6524. case 7 /* Size */:
  6525. {
  6526. var s = val;
  6527. array[offset + 0] = s.width;
  6528. array[offset + 1] = s.height;
  6529. break;
  6530. }
  6531. }
  6532. };
  6533. return InstancePropInfo;
  6534. }());
  6535. BABYLON.InstancePropInfo = InstancePropInfo;
  6536. function instanceData(category, shaderAttributeName) {
  6537. return function (target, propName, descriptor) {
  6538. var dic = BABYLON.ClassTreeInfo.getOrRegister(target, function (base) { return new InstanceClassInfo(base); });
  6539. var node = dic.getLevelOf(target);
  6540. var instanceDataName = propName;
  6541. shaderAttributeName = shaderAttributeName || instanceDataName;
  6542. var info = node.levelContent.get(instanceDataName);
  6543. if (info) {
  6544. throw new Error("The ID " + instanceDataName + " is already taken by another instance data");
  6545. }
  6546. info = new InstancePropInfo();
  6547. info.attributeName = shaderAttributeName;
  6548. info.category = category || null;
  6549. if (info.category) {
  6550. info.delimitedCategory = ";" + info.category + ";";
  6551. }
  6552. node.levelContent.add(instanceDataName, info);
  6553. descriptor.get = function () {
  6554. return null;
  6555. };
  6556. descriptor.set = function (val) {
  6557. // Check that we're not trying to set a property that belongs to a category that is not allowed (current)
  6558. // Quit if it's the case, otherwise we could overwrite data somewhere...
  6559. if (info.category && InstanceClassInfo._CurCategories.indexOf(info.delimitedCategory) === -1) {
  6560. return;
  6561. }
  6562. if (!info.size) {
  6563. info.setSize(val);
  6564. node.classContent.mapProperty(info, true);
  6565. }
  6566. else if (!info.instanceOffset.contains(InstanceClassInfo._CurCategories)) {
  6567. node.classContent.mapProperty(info, false);
  6568. }
  6569. var obj = this;
  6570. if (obj.dataBuffer && obj.dataElements) {
  6571. var offset = obj.dataElements[obj.curElement].offset + info.instanceOffset.get(InstanceClassInfo._CurCategories);
  6572. info.writeData(obj.dataBuffer.buffer, offset, val);
  6573. }
  6574. };
  6575. };
  6576. }
  6577. BABYLON.instanceData = instanceData;
  6578. var InstanceDataBase = (function () {
  6579. function InstanceDataBase(partId, dataElementCount) {
  6580. this.id = partId;
  6581. this.curElement = 0;
  6582. this._dataElementCount = dataElementCount;
  6583. this.renderMode = 0;
  6584. this.arrayLengthChanged = false;
  6585. }
  6586. Object.defineProperty(InstanceDataBase.prototype, "zBias", {
  6587. get: function () {
  6588. return null;
  6589. },
  6590. set: function (value) {
  6591. },
  6592. enumerable: true,
  6593. configurable: true
  6594. });
  6595. Object.defineProperty(InstanceDataBase.prototype, "transformX", {
  6596. get: function () {
  6597. return null;
  6598. },
  6599. set: function (value) {
  6600. },
  6601. enumerable: true,
  6602. configurable: true
  6603. });
  6604. Object.defineProperty(InstanceDataBase.prototype, "transformY", {
  6605. get: function () {
  6606. return null;
  6607. },
  6608. set: function (value) {
  6609. },
  6610. enumerable: true,
  6611. configurable: true
  6612. });
  6613. Object.defineProperty(InstanceDataBase.prototype, "opacity", {
  6614. get: function () {
  6615. return null;
  6616. },
  6617. set: function (value) {
  6618. },
  6619. enumerable: true,
  6620. configurable: true
  6621. });
  6622. InstanceDataBase.prototype.getClassTreeInfo = function () {
  6623. if (!this.typeInfo) {
  6624. this.typeInfo = BABYLON.ClassTreeInfo.get(Object.getPrototypeOf(this));
  6625. }
  6626. return this.typeInfo;
  6627. };
  6628. InstanceDataBase.prototype.allocElements = function () {
  6629. if (!this.dataBuffer || this.dataElements) {
  6630. return;
  6631. }
  6632. var res = new Array(this.dataElementCount);
  6633. for (var i = 0; i < this.dataElementCount; i++) {
  6634. res[i] = this.dataBuffer.allocElement();
  6635. }
  6636. this.dataElements = res;
  6637. };
  6638. InstanceDataBase.prototype.freeElements = function () {
  6639. if (!this.dataElements) {
  6640. return;
  6641. }
  6642. for (var _i = 0, _a = this.dataElements; _i < _a.length; _i++) {
  6643. var ei = _a[_i];
  6644. this.dataBuffer.freeElement(ei);
  6645. }
  6646. this.dataElements = null;
  6647. };
  6648. Object.defineProperty(InstanceDataBase.prototype, "dataElementCount", {
  6649. get: function () {
  6650. return this._dataElementCount;
  6651. },
  6652. set: function (value) {
  6653. if (value === this._dataElementCount) {
  6654. return;
  6655. }
  6656. this.arrayLengthChanged = true;
  6657. this.freeElements();
  6658. this._dataElementCount = value;
  6659. this.allocElements();
  6660. },
  6661. enumerable: true,
  6662. configurable: true
  6663. });
  6664. __decorate([
  6665. instanceData()
  6666. ], InstanceDataBase.prototype, "zBias", null);
  6667. __decorate([
  6668. instanceData()
  6669. ], InstanceDataBase.prototype, "transformX", null);
  6670. __decorate([
  6671. instanceData()
  6672. ], InstanceDataBase.prototype, "transformY", null);
  6673. __decorate([
  6674. instanceData()
  6675. ], InstanceDataBase.prototype, "opacity", null);
  6676. return InstanceDataBase;
  6677. }());
  6678. BABYLON.InstanceDataBase = InstanceDataBase;
  6679. var RenderablePrim2D = (function (_super) {
  6680. __extends(RenderablePrim2D, _super);
  6681. function RenderablePrim2D(settings) {
  6682. _super.call(this, settings);
  6683. this._transparentPrimitiveInfo = null;
  6684. }
  6685. Object.defineProperty(RenderablePrim2D.prototype, "isAlphaTest", {
  6686. get: function () {
  6687. return this._useTextureAlpha() || this._isPrimAlphaTest();
  6688. },
  6689. enumerable: true,
  6690. configurable: true
  6691. });
  6692. Object.defineProperty(RenderablePrim2D.prototype, "isTransparent", {
  6693. get: function () {
  6694. return (this.actualOpacity < 1) || this._shouldUseAlphaFromTexture() || this._isPrimTransparent();
  6695. },
  6696. enumerable: true,
  6697. configurable: true
  6698. });
  6699. Object.defineProperty(RenderablePrim2D.prototype, "renderMode", {
  6700. get: function () {
  6701. return this._renderMode;
  6702. },
  6703. enumerable: true,
  6704. configurable: true
  6705. });
  6706. /**
  6707. * Dispose the primitive and its resources, remove it from its parent
  6708. */
  6709. RenderablePrim2D.prototype.dispose = function () {
  6710. if (!_super.prototype.dispose.call(this)) {
  6711. return false;
  6712. }
  6713. if (this.renderGroup) {
  6714. this.renderGroup._setCacheGroupDirty();
  6715. }
  6716. if (this._transparentPrimitiveInfo) {
  6717. this.renderGroup._renderableData.removeTransparentPrimitiveInfo(this._transparentPrimitiveInfo);
  6718. this._transparentPrimitiveInfo = null;
  6719. }
  6720. if (this._instanceDataParts) {
  6721. this._cleanupInstanceDataParts();
  6722. }
  6723. if (this._modelRenderCache) {
  6724. this._modelRenderCache.dispose();
  6725. this._modelRenderCache = null;
  6726. }
  6727. if (this._instanceDataParts) {
  6728. this._instanceDataParts.forEach(function (p) {
  6729. p.freeElements();
  6730. });
  6731. this._instanceDataParts = null;
  6732. }
  6733. return true;
  6734. };
  6735. RenderablePrim2D.prototype._cleanupInstanceDataParts = function () {
  6736. var gii = null;
  6737. for (var _i = 0, _a = this._instanceDataParts; _i < _a.length; _i++) {
  6738. var part = _a[_i];
  6739. part.freeElements();
  6740. gii = part.groupInstanceInfo;
  6741. }
  6742. if (gii) {
  6743. var usedCount = 0;
  6744. if (gii.hasOpaqueData) {
  6745. var od = gii.opaqueData[0];
  6746. usedCount += od._partData.usedElementCount;
  6747. gii.opaqueDirty = true;
  6748. }
  6749. if (gii.hasAlphaTestData) {
  6750. var atd = gii.alphaTestData[0];
  6751. usedCount += atd._partData.usedElementCount;
  6752. gii.alphaTestDirty = true;
  6753. }
  6754. if (gii.hasTransparentData) {
  6755. var td = gii.transparentData[0];
  6756. usedCount += td._partData.usedElementCount;
  6757. gii.transparentDirty = true;
  6758. }
  6759. if (usedCount === 0 && gii.modelRenderCache != null) {
  6760. this.renderGroup._renderableData._renderGroupInstancesInfo.remove(gii.modelRenderCache.modelKey);
  6761. gii.dispose();
  6762. }
  6763. if (this._modelRenderCache) {
  6764. this._modelRenderCache.dispose();
  6765. this._modelRenderCache = null;
  6766. }
  6767. }
  6768. this._instanceDataParts = null;
  6769. };
  6770. RenderablePrim2D.prototype._prepareRenderPre = function (context) {
  6771. _super.prototype._prepareRenderPre.call(this, context);
  6772. // If the model changed and we have already an instance, we must remove this instance from the obsolete model
  6773. if (this._isFlagSet(BABYLON.SmartPropertyPrim.flagModelDirty) && this._instanceDataParts) {
  6774. this._cleanupInstanceDataParts();
  6775. }
  6776. // Need to create the model?
  6777. var setupModelRenderCache = false;
  6778. if (!this._modelRenderCache || this._isFlagSet(BABYLON.SmartPropertyPrim.flagModelDirty)) {
  6779. setupModelRenderCache = this._createModelRenderCache();
  6780. }
  6781. var gii = null;
  6782. var newInstance = false;
  6783. // Need to create the instance data parts?
  6784. if (!this._instanceDataParts) {
  6785. // Yes, flag it for later, more processing will have to be done
  6786. newInstance = true;
  6787. gii = this._createModelDataParts();
  6788. }
  6789. // If the ModelRenderCache is brand new, now is the time to call the implementation's specific setup method to create the rendering resources
  6790. if (setupModelRenderCache) {
  6791. this.setupModelRenderCache(this._modelRenderCache);
  6792. }
  6793. // At this stage we have everything correctly initialized, ModelRenderCache is setup, Model Instance data are good too, they have allocated elements in the Instanced DynamicFloatArray.
  6794. // The last thing to do is check if the instanced related data must be updated because a InstanceLevel property had changed or the primitive visibility changed.
  6795. if (this._areSomeFlagsSet(BABYLON.SmartPropertyPrim.flagVisibilityChanged | BABYLON.SmartPropertyPrim.flagNeedRefresh) || context.forceRefreshPrimitive || newInstance || (this._instanceDirtyFlags !== 0) || (this._globalTransformProcessStep !== this._globalTransformStep) || this._mustUpdateInstance()) {
  6796. this._updateInstanceDataParts(gii);
  6797. }
  6798. };
  6799. RenderablePrim2D.prototype._createModelRenderCache = function () {
  6800. var _this = this;
  6801. var setupModelRenderCache = false;
  6802. if (this._modelRenderCache) {
  6803. this._modelRenderCache.dispose();
  6804. }
  6805. this._modelRenderCache = this.owner._engineData.GetOrAddModelCache(this.modelKey, function (key) {
  6806. var mrc = _this.createModelRenderCache(key);
  6807. setupModelRenderCache = true;
  6808. return mrc;
  6809. });
  6810. this._clearFlags(BABYLON.SmartPropertyPrim.flagModelDirty);
  6811. // if this is still false it means the MRC already exists, so we add a reference to it
  6812. if (!setupModelRenderCache) {
  6813. this._modelRenderCache.addRef();
  6814. }
  6815. return setupModelRenderCache;
  6816. };
  6817. RenderablePrim2D.prototype._createModelDataParts = function () {
  6818. var _this = this;
  6819. // Create the instance data parts of the primitive and store them
  6820. var parts = this.createInstanceDataParts();
  6821. this._instanceDataParts = parts;
  6822. // Check if the ModelRenderCache for this particular instance is also brand new, initialize it if it's the case
  6823. if (!this._modelRenderCache._partData) {
  6824. this._setupModelRenderCache(parts);
  6825. }
  6826. // The Rendering resources (Effect, VB, IB, Textures) are stored in the ModelRenderCache
  6827. // But it's the RenderGroup that will store all the Instanced related data to render all the primitive it owns.
  6828. // So for a given ModelKey we getOrAdd a GroupInstanceInfo that will store all these data
  6829. var gii = this.renderGroup._renderableData._renderGroupInstancesInfo.getOrAddWithFactory(this.modelKey, function (k) {
  6830. var res = new BABYLON.GroupInstanceInfo(_this.renderGroup, _this._modelRenderCache, _this._modelRenderCache._partData.length);
  6831. for (var j = 0; j < _this._modelRenderCache._partData.length; j++) {
  6832. var part = _this._instanceDataParts[j];
  6833. res.partIndexFromId.add(part.id.toString(), j);
  6834. res.usedShaderCategories[j] = ";" + _this.getUsedShaderCategories(part).join(";") + ";";
  6835. res.strides[j] = _this._modelRenderCache._partData[j]._partDataStride;
  6836. }
  6837. return res;
  6838. });
  6839. // Get the GroupInfoDataPart corresponding to the render category of the part
  6840. var rm = 0;
  6841. var gipd = null;
  6842. if (this.isTransparent) {
  6843. gipd = gii.transparentData;
  6844. rm = BABYLON.Render2DContext.RenderModeTransparent;
  6845. }
  6846. else if (this.isAlphaTest) {
  6847. gipd = gii.alphaTestData;
  6848. rm = BABYLON.Render2DContext.RenderModeAlphaTest;
  6849. }
  6850. else {
  6851. gipd = gii.opaqueData;
  6852. rm = BABYLON.Render2DContext.RenderModeOpaque;
  6853. }
  6854. // For each instance data part of the primitive, allocate the instanced element it needs for render
  6855. for (var i = 0; i < parts.length; i++) {
  6856. var part = parts[i];
  6857. part.dataBuffer = gipd[i]._partData;
  6858. part.allocElements();
  6859. part.renderMode = rm;
  6860. part.groupInstanceInfo = gii;
  6861. }
  6862. return gii;
  6863. };
  6864. RenderablePrim2D.prototype._setupModelRenderCache = function (parts) {
  6865. var ctiArray = new Array();
  6866. this._modelRenderCache._partData = new Array();
  6867. for (var _i = 0, parts_1 = parts; _i < parts_1.length; _i++) {
  6868. var dataPart = parts_1[_i];
  6869. var pd = new BABYLON.ModelRenderCachePartData();
  6870. this._modelRenderCache._partData.push(pd);
  6871. var cat = this.getUsedShaderCategories(dataPart);
  6872. var cti = dataPart.getClassTreeInfo();
  6873. // Make sure the instance is visible other the properties won't be set and their size/offset wont be computed
  6874. var curVisible = this.isVisible;
  6875. this.isVisible = true;
  6876. // We manually trigger refreshInstanceData for the only sake of evaluating each instance property size and offset in the instance data, this can only be made at runtime. Once it's done we have all the information to create the instance data buffer.
  6877. //console.log("Build Prop Layout for " + Tools.getClassName(this._instanceDataParts[0]));
  6878. var joinCat = ";" + cat.join(";") + ";";
  6879. pd._partJoinedUsedCategories = joinCat;
  6880. InstanceClassInfo._CurCategories = joinCat;
  6881. var obj = this.beforeRefreshForLayoutConstruction(dataPart);
  6882. if (!this.refreshInstanceDataPart(dataPart)) {
  6883. console.log("Layout construction for " + BABYLON.Tools.getClassName(this._instanceDataParts[0]) + " failed because refresh returned false");
  6884. }
  6885. this.afterRefreshForLayoutConstruction(dataPart, obj);
  6886. this.isVisible = curVisible;
  6887. var size = 0;
  6888. cti.fullContent.forEach(function (k, v) {
  6889. if (!v.category || cat.indexOf(v.category) !== -1) {
  6890. if (v.attributeName === "zBias") {
  6891. pd._zBiasOffset = v.instanceOffset.get(joinCat);
  6892. }
  6893. if (!v.size) {
  6894. console.log("ERROR: Couldn't detect the size of the Property " + v.attributeName + " from type " + BABYLON.Tools.getClassName(cti.type) + ". Property is ignored.");
  6895. }
  6896. else {
  6897. size += v.size;
  6898. }
  6899. }
  6900. });
  6901. pd._partDataStride = size;
  6902. pd._partUsedCategories = cat;
  6903. pd._partId = dataPart.id;
  6904. ctiArray.push(cti);
  6905. }
  6906. this._modelRenderCache._partsClassInfo = ctiArray;
  6907. };
  6908. RenderablePrim2D.prototype.onZOrderChanged = function () {
  6909. if (this.isTransparent && this._transparentPrimitiveInfo) {
  6910. this.renderGroup._renderableData.transparentPrimitiveZChanged(this._transparentPrimitiveInfo);
  6911. var gii = this.renderGroup._renderableData._renderGroupInstancesInfo.get(this.modelKey);
  6912. // Flag the transparentData dirty has will have to sort it again
  6913. gii.transparentOrderDirty = true;
  6914. }
  6915. };
  6916. RenderablePrim2D.prototype._mustUpdateInstance = function () {
  6917. return false;
  6918. };
  6919. RenderablePrim2D.prototype._useTextureAlpha = function () {
  6920. return false;
  6921. };
  6922. RenderablePrim2D.prototype._shouldUseAlphaFromTexture = function () {
  6923. return false;
  6924. };
  6925. RenderablePrim2D.prototype._isPrimAlphaTest = function () {
  6926. return false;
  6927. };
  6928. RenderablePrim2D.prototype._isPrimTransparent = function () {
  6929. return false;
  6930. };
  6931. RenderablePrim2D.prototype._updateInstanceDataParts = function (gii) {
  6932. // Fetch the GroupInstanceInfo if we don't already have it
  6933. var rd = this.renderGroup._renderableData;
  6934. if (!gii) {
  6935. gii = rd._renderGroupInstancesInfo.get(this.modelKey);
  6936. }
  6937. var isTransparent = this.isTransparent;
  6938. var isAlphaTest = this.isAlphaTest;
  6939. var wereTransparent = false;
  6940. // Check a render mode change
  6941. var rmChanged = false;
  6942. if (this._instanceDataParts.length > 0) {
  6943. var firstPart = this._instanceDataParts[0];
  6944. var partRM = firstPart.renderMode;
  6945. var curRM = this.renderMode;
  6946. if (partRM !== curRM) {
  6947. wereTransparent = partRM === BABYLON.Render2DContext.RenderModeTransparent;
  6948. rmChanged = true;
  6949. var gipd = void 0;
  6950. switch (curRM) {
  6951. case BABYLON.Render2DContext.RenderModeTransparent:
  6952. gipd = gii.transparentData;
  6953. break;
  6954. case BABYLON.Render2DContext.RenderModeAlphaTest:
  6955. gipd = gii.alphaTestData;
  6956. break;
  6957. default:
  6958. gipd = gii.opaqueData;
  6959. }
  6960. for (var i = 0; i < this._instanceDataParts.length; i++) {
  6961. var part = this._instanceDataParts[i];
  6962. part.freeElements();
  6963. part.dataBuffer = gipd[i]._partData;
  6964. part.renderMode = curRM;
  6965. }
  6966. }
  6967. }
  6968. // Handle changes related to ZOffset
  6969. var visChanged = this._isFlagSet(BABYLON.SmartPropertyPrim.flagVisibilityChanged);
  6970. if (isTransparent || wereTransparent) {
  6971. // Handle visibility change, which is also triggered when the primitive just got created
  6972. if (visChanged || rmChanged) {
  6973. if (this.isVisible && !wereTransparent) {
  6974. if (!this._transparentPrimitiveInfo) {
  6975. // Add the primitive to the list of transparent ones in the group that render is
  6976. this._transparentPrimitiveInfo = rd.addNewTransparentPrimitiveInfo(this, gii);
  6977. }
  6978. }
  6979. else {
  6980. if (this._transparentPrimitiveInfo) {
  6981. rd.removeTransparentPrimitiveInfo(this._transparentPrimitiveInfo);
  6982. this._transparentPrimitiveInfo = null;
  6983. }
  6984. }
  6985. gii.transparentOrderDirty = true;
  6986. }
  6987. }
  6988. var rebuildTrans = false;
  6989. // For each Instance Data part, refresh it to update the data in the DynamicFloatArray
  6990. for (var _i = 0, _a = this._instanceDataParts; _i < _a.length; _i++) {
  6991. var part = _a[_i];
  6992. var justAllocated = false;
  6993. // Check if we need to allocate data elements (hidden prim which becomes visible again)
  6994. if (!part.dataElements && (visChanged || rmChanged || this.isVisible)) {
  6995. part.allocElements();
  6996. justAllocated = true;
  6997. }
  6998. InstanceClassInfo._CurCategories = gii.usedShaderCategories[gii.partIndexFromId.get(part.id.toString())];
  6999. // Will return false if the instance should not be rendered (not visible or other any reasons)
  7000. part.arrayLengthChanged = false;
  7001. if (!this.refreshInstanceDataPart(part)) {
  7002. // Free the data element
  7003. if (part.dataElements) {
  7004. part.freeElements();
  7005. }
  7006. // The refresh couldn't succeed, push the primitive to be dirty again for the next render
  7007. if (this.isVisible) {
  7008. rd._primNewDirtyList.push(this);
  7009. }
  7010. }
  7011. rebuildTrans = rebuildTrans || part.arrayLengthChanged || justAllocated;
  7012. }
  7013. this._instanceDirtyFlags = 0;
  7014. // Make the appropriate data dirty
  7015. if (isTransparent) {
  7016. gii.transparentDirty = true;
  7017. if (rebuildTrans) {
  7018. rd._transparentListChanged = true;
  7019. }
  7020. }
  7021. else if (isAlphaTest) {
  7022. gii.alphaTestDirty = true;
  7023. }
  7024. else {
  7025. gii.opaqueDirty = true;
  7026. }
  7027. this._clearFlags(BABYLON.SmartPropertyPrim.flagVisibilityChanged); // Reset the flag as we've handled the case
  7028. };
  7029. RenderablePrim2D.prototype._updateTransparentSegmentIndices = function (ts) {
  7030. var minOff = BABYLON.Prim2DBase._bigInt;
  7031. var maxOff = 0;
  7032. for (var _i = 0, _a = this._instanceDataParts; _i < _a.length; _i++) {
  7033. var part = _a[_i];
  7034. if (part && part.dataElements) {
  7035. part.dataBuffer.pack();
  7036. for (var _b = 0, _c = part.dataElements; _b < _c.length; _b++) {
  7037. var el = _c[_b];
  7038. minOff = Math.min(minOff, el.offset);
  7039. maxOff = Math.max(maxOff, el.offset);
  7040. }
  7041. ts.startDataIndex = Math.min(ts.startDataIndex, minOff / part.dataBuffer.stride);
  7042. ts.endDataIndex = Math.max(ts.endDataIndex, (maxOff / part.dataBuffer.stride) + 1); // +1 for exclusive
  7043. }
  7044. }
  7045. };
  7046. // This internal method is mainly used for transparency processing
  7047. RenderablePrim2D.prototype._getNextPrimZOrder = function () {
  7048. var length = this._instanceDataParts.length;
  7049. for (var i = 0; i < length; i++) {
  7050. var part = this._instanceDataParts[i];
  7051. if (part) {
  7052. var stride = part.dataBuffer.stride;
  7053. var lastElementOffset = part.dataElements[part.dataElements.length - 1].offset;
  7054. // check if it's the last in the DFA
  7055. if (part.dataBuffer.totalElementCount * stride <= lastElementOffset) {
  7056. return null;
  7057. }
  7058. // Return the Z of the next primitive that lies in the DFA
  7059. return part.dataBuffer[lastElementOffset + stride + this.modelRenderCache._partData[i]._zBiasOffset];
  7060. }
  7061. }
  7062. return null;
  7063. };
  7064. // This internal method is mainly used for transparency processing
  7065. RenderablePrim2D.prototype._getPrevPrimZOrder = function () {
  7066. var length = this._instanceDataParts.length;
  7067. for (var i = 0; i < length; i++) {
  7068. var part = this._instanceDataParts[i];
  7069. if (part) {
  7070. var stride = part.dataBuffer.stride;
  7071. var firstElementOffset = part.dataElements[0].offset;
  7072. // check if it's the first in the DFA
  7073. if (firstElementOffset === 0) {
  7074. return null;
  7075. }
  7076. // Return the Z of the previous primitive that lies in the DFA
  7077. return part.dataBuffer[firstElementOffset - stride + this.modelRenderCache._partData[i]._zBiasOffset];
  7078. }
  7079. }
  7080. return null;
  7081. };
  7082. /**
  7083. * Transform a given point using the Primitive's origin setting.
  7084. * This method requires the Primitive's actualSize to be accurate
  7085. * @param p the point to transform
  7086. * @param originOffset an offset applied on the current origin before performing the transformation. Depending on which frame of reference your data is expressed you may have to apply a offset. (if you data is expressed from the bottom/left, no offset is required. If it's expressed from the center the a [-0.5;-0.5] offset has to be applied.
  7087. * @param res an allocated Vector2 that will receive the transformed content
  7088. */
  7089. RenderablePrim2D.prototype.transformPointWithOriginByRef = function (p, originOffset, res) {
  7090. var actualSize = this.actualSize;
  7091. res.x = p.x - ((this.origin.x + (originOffset ? originOffset.x : 0)) * actualSize.width);
  7092. res.y = p.y - ((this.origin.y + (originOffset ? originOffset.y : 0)) * actualSize.height);
  7093. };
  7094. RenderablePrim2D.prototype.transformPointWithOriginToRef = function (p, originOffset, res) {
  7095. this.transformPointWithOriginByRef(p, originOffset, res);
  7096. return res;
  7097. };
  7098. /**
  7099. * Get the info for a given effect based on the dataPart metadata
  7100. * @param dataPartId partId in part list to get the info
  7101. * @param vertexBufferAttributes vertex buffer attributes to manually add
  7102. * @param uniforms uniforms to manually add
  7103. * @param useInstanced specified if Instanced Array should be used, if null the engine caps will be used (so true if WebGL supports it, false otherwise), but you have the possibility to override the engine capability. However, if you manually set true but the engine does not support Instanced Array, this method will return null
  7104. */
  7105. RenderablePrim2D.prototype.getDataPartEffectInfo = function (dataPartId, vertexBufferAttributes, uniforms, useInstanced) {
  7106. if (uniforms === void 0) { uniforms = null; }
  7107. if (useInstanced === void 0) { useInstanced = null; }
  7108. var dataPart = BABYLON.Tools.first(this._instanceDataParts, function (i) { return i.id === dataPartId; });
  7109. if (!dataPart) {
  7110. return null;
  7111. }
  7112. var instancedArray = this.owner.supportInstancedArray;
  7113. if (useInstanced != null) {
  7114. // Check if the caller ask for Instanced Array and the engine does not support it, return null if it's the case
  7115. if (useInstanced && instancedArray === false) {
  7116. return null;
  7117. }
  7118. // Use the caller's setting
  7119. instancedArray = useInstanced;
  7120. }
  7121. var cti = dataPart.getClassTreeInfo();
  7122. var categories = this.getUsedShaderCategories(dataPart);
  7123. var att = cti.classContent.getShaderAttributes(categories);
  7124. var defines = "";
  7125. categories.forEach(function (c) { defines += "#define " + c + "\n"; });
  7126. if (instancedArray) {
  7127. defines += "#define Instanced\n";
  7128. }
  7129. return {
  7130. attributes: instancedArray ? vertexBufferAttributes.concat(att) : vertexBufferAttributes,
  7131. uniforms: instancedArray ? (uniforms != null ? uniforms : []) : ((uniforms != null) ? att.concat(uniforms) : (att != null ? att : [])),
  7132. defines: defines
  7133. };
  7134. };
  7135. Object.defineProperty(RenderablePrim2D.prototype, "modelRenderCache", {
  7136. get: function () {
  7137. return this._modelRenderCache;
  7138. },
  7139. enumerable: true,
  7140. configurable: true
  7141. });
  7142. RenderablePrim2D.prototype.createModelRenderCache = function (modelKey) {
  7143. return null;
  7144. };
  7145. RenderablePrim2D.prototype.setupModelRenderCache = function (modelRenderCache) {
  7146. };
  7147. RenderablePrim2D.prototype.createInstanceDataParts = function () {
  7148. return null;
  7149. };
  7150. RenderablePrim2D.prototype.getUsedShaderCategories = function (dataPart) {
  7151. return [];
  7152. };
  7153. RenderablePrim2D.prototype.beforeRefreshForLayoutConstruction = function (part) {
  7154. };
  7155. RenderablePrim2D.prototype.afterRefreshForLayoutConstruction = function (part, obj) {
  7156. };
  7157. RenderablePrim2D.prototype.applyActualScaleOnTransform = function () {
  7158. return true;
  7159. };
  7160. RenderablePrim2D.prototype.refreshInstanceDataPart = function (part) {
  7161. if (!this.isVisible) {
  7162. return false;
  7163. }
  7164. part.isVisible = this.isVisible;
  7165. // Which means, if there's only one data element, we're update it from this method, otherwise it is the responsibility of the derived class to call updateInstanceDataPart as many times as needed, properly (look at Text2D's implementation for more information)
  7166. if (part.dataElementCount === 1) {
  7167. part.curElement = 0;
  7168. this.updateInstanceDataPart(part);
  7169. }
  7170. return true;
  7171. };
  7172. /**
  7173. * Update the instanceDataBase level properties of a part
  7174. * @param part the part to update
  7175. * @param positionOffset to use in multi part per primitive (e.g. the Text2D has N parts for N letter to display), this give the offset to apply (e.g. the position of the letter from the bottom/left corner of the text).
  7176. */
  7177. RenderablePrim2D.prototype.updateInstanceDataPart = function (part, positionOffset) {
  7178. if (positionOffset === void 0) { positionOffset = null; }
  7179. var t = this._globalTransform.multiply(this.renderGroup.invGlobalTransform); // Compute the transformation into the renderGroup's space
  7180. var rgScale = this._areSomeFlagsSet(BABYLON.SmartPropertyPrim.flagDontInheritParentScale) ? RenderablePrim2D._uV : this.renderGroup.actualScale; // We still need to apply the scale of the renderGroup to our rendering, so get it.
  7181. var size = this.renderGroup.viewportSize;
  7182. var zBias = this.actualZOffset;
  7183. var offX = 0;
  7184. var offY = 0;
  7185. // If there's an offset, apply the global transformation matrix on it to get a global offset
  7186. if (positionOffset) {
  7187. offX = positionOffset.x * t.m[0] + positionOffset.y * t.m[4];
  7188. offY = positionOffset.x * t.m[1] + positionOffset.y * t.m[5];
  7189. }
  7190. // Have to convert the coordinates to clip space which is ranged between [-1;1] on X and Y axis, with 0,0 being the left/bottom corner
  7191. // Current coordinates are expressed in renderGroup coordinates ([0, renderGroup.actualSize.width|height]) with 0,0 being at the left/top corner
  7192. // So for X:
  7193. // - tx.x = value * 2 / width: is to switch from [0, renderGroup.width] to [0, 2]
  7194. // - tx.w = (value * 2 / width) - 1: w stores the translation in renderGroup coordinates so (value * 2 / width) to switch to a clip space translation value. - 1 is to offset the overall [0;2] to [-1;1].
  7195. // At last we don't forget to apply the actualScale of the Render Group to tx[0] and ty[1] to propagate scaling correctly
  7196. var w = size.width;
  7197. var h = size.height;
  7198. var invZBias = 1 / zBias;
  7199. var tx = new BABYLON.Vector4(t.m[0] * rgScale.x * 2 / w, t.m[4] * 2 / w, 0 /*t.m[8]*/, ((t.m[12] + offX) * rgScale.x * 2 / w) - 1);
  7200. var ty = new BABYLON.Vector4(t.m[1] * 2 / h, t.m[5] * rgScale.y * 2 / h, 0 /*t.m[9]*/, ((t.m[13] + offY) * rgScale.y * 2 / h) - 1);
  7201. if (!this.applyActualScaleOnTransform()) {
  7202. var las = this.actualScale;
  7203. tx.x /= las.x;
  7204. ty.y /= las.y;
  7205. }
  7206. part.transformX = tx;
  7207. part.transformY = ty;
  7208. part.opacity = this.actualOpacity;
  7209. // Stores zBias and it's inverse value because that's needed to compute the clip space W coordinate (which is 1/Z, so 1/zBias)
  7210. part.zBias = new BABYLON.Vector2(zBias, invZBias);
  7211. };
  7212. RenderablePrim2D.prototype._updateRenderMode = function () {
  7213. if (this.isTransparent) {
  7214. this._renderMode = BABYLON.Render2DContext.RenderModeTransparent;
  7215. }
  7216. else if (this.isAlphaTest) {
  7217. this._renderMode = BABYLON.Render2DContext.RenderModeAlphaTest;
  7218. }
  7219. else {
  7220. this._renderMode = BABYLON.Render2DContext.RenderModeOpaque;
  7221. }
  7222. };
  7223. RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT = BABYLON.Prim2DBase.PRIM2DBASE_PROPCOUNT + 5;
  7224. RenderablePrim2D._uV = new BABYLON.Vector2(1, 1);
  7225. __decorate([
  7226. BABYLON.dynamicLevelProperty(BABYLON.Prim2DBase.PRIM2DBASE_PROPCOUNT + 0, function (pi) { return RenderablePrim2D.isAlphaTestProperty = pi; })
  7227. ], RenderablePrim2D.prototype, "isAlphaTest", null);
  7228. __decorate([
  7229. BABYLON.dynamicLevelProperty(BABYLON.Prim2DBase.PRIM2DBASE_PROPCOUNT + 1, function (pi) { return RenderablePrim2D.isTransparentProperty = pi; })
  7230. ], RenderablePrim2D.prototype, "isTransparent", null);
  7231. RenderablePrim2D = __decorate([
  7232. BABYLON.className("RenderablePrim2D", "BABYLON")
  7233. ], RenderablePrim2D);
  7234. return RenderablePrim2D;
  7235. }(BABYLON.Prim2DBase));
  7236. BABYLON.RenderablePrim2D = RenderablePrim2D;
  7237. })(BABYLON || (BABYLON = {}));
  7238. var BABYLON;
  7239. (function (BABYLON) {
  7240. var Shape2D = (function (_super) {
  7241. __extends(Shape2D, _super);
  7242. function Shape2D(settings) {
  7243. _super.call(this, settings);
  7244. if (!settings) {
  7245. settings = {};
  7246. }
  7247. var borderBrush = null;
  7248. if (settings.border) {
  7249. if (typeof (settings.border) === "string") {
  7250. borderBrush = BABYLON.Canvas2D.GetBrushFromString(settings.border);
  7251. }
  7252. else {
  7253. borderBrush = settings.border;
  7254. }
  7255. }
  7256. var fillBrush = null;
  7257. if (settings.fill) {
  7258. if (typeof (settings.fill) === "string") {
  7259. fillBrush = BABYLON.Canvas2D.GetBrushFromString(settings.fill);
  7260. }
  7261. else {
  7262. fillBrush = settings.fill;
  7263. }
  7264. }
  7265. this._isTransparent = false;
  7266. this._oldTransparent = false;
  7267. this.border = borderBrush;
  7268. this.fill = fillBrush;
  7269. this._updateTransparencyStatus();
  7270. this.borderThickness = settings.borderThickness;
  7271. }
  7272. Object.defineProperty(Shape2D.prototype, "border", {
  7273. get: function () {
  7274. return this._border;
  7275. },
  7276. set: function (value) {
  7277. this._border = value;
  7278. this._updateTransparencyStatus();
  7279. },
  7280. enumerable: true,
  7281. configurable: true
  7282. });
  7283. Object.defineProperty(Shape2D.prototype, "fill", {
  7284. /**
  7285. * Get/set the brush to render the Fill part of the Primitive
  7286. */
  7287. get: function () {
  7288. return this._fill;
  7289. },
  7290. set: function (value) {
  7291. this._fill = value;
  7292. this._updateTransparencyStatus();
  7293. },
  7294. enumerable: true,
  7295. configurable: true
  7296. });
  7297. Object.defineProperty(Shape2D.prototype, "borderThickness", {
  7298. get: function () {
  7299. return this._borderThickness;
  7300. },
  7301. set: function (value) {
  7302. this._borderThickness = value;
  7303. },
  7304. enumerable: true,
  7305. configurable: true
  7306. });
  7307. Shape2D.prototype.getUsedShaderCategories = function (dataPart) {
  7308. var cat = _super.prototype.getUsedShaderCategories.call(this, dataPart);
  7309. // Fill Part
  7310. if (dataPart.id === Shape2D.SHAPE2D_FILLPARTID) {
  7311. var fill = this.fill;
  7312. if (fill instanceof BABYLON.SolidColorBrush2D) {
  7313. cat.push(Shape2D.SHAPE2D_CATEGORY_FILLSOLID);
  7314. }
  7315. if (fill instanceof BABYLON.GradientColorBrush2D) {
  7316. cat.push(Shape2D.SHAPE2D_CATEGORY_FILLGRADIENT);
  7317. }
  7318. }
  7319. // Border Part
  7320. if (dataPart.id === Shape2D.SHAPE2D_BORDERPARTID) {
  7321. cat.push(Shape2D.SHAPE2D_CATEGORY_BORDER);
  7322. var border = this.border;
  7323. if (border instanceof BABYLON.SolidColorBrush2D) {
  7324. cat.push(Shape2D.SHAPE2D_CATEGORY_BORDERSOLID);
  7325. }
  7326. if (border instanceof BABYLON.GradientColorBrush2D) {
  7327. cat.push(Shape2D.SHAPE2D_CATEGORY_BORDERGRADIENT);
  7328. }
  7329. }
  7330. return cat;
  7331. };
  7332. Shape2D.prototype.applyActualScaleOnTransform = function () {
  7333. return false;
  7334. };
  7335. Shape2D.prototype.refreshInstanceDataPart = function (part) {
  7336. if (!_super.prototype.refreshInstanceDataPart.call(this, part)) {
  7337. return false;
  7338. }
  7339. // Fill Part
  7340. if (part.id === Shape2D.SHAPE2D_FILLPARTID) {
  7341. var d = part;
  7342. if (this.fill) {
  7343. var fill = this.fill;
  7344. if (fill instanceof BABYLON.SolidColorBrush2D) {
  7345. d.fillSolidColor = fill.color;
  7346. }
  7347. else if (fill instanceof BABYLON.GradientColorBrush2D) {
  7348. d.fillGradientColor1 = fill.color1;
  7349. d.fillGradientColor2 = fill.color2;
  7350. var t = BABYLON.Matrix.Compose(new BABYLON.Vector3(fill.scale, fill.scale, fill.scale), BABYLON.Quaternion.RotationAxis(new BABYLON.Vector3(0, 0, 1), fill.rotation), new BABYLON.Vector3(fill.translation.x, fill.translation.y, 0));
  7351. var ty = new BABYLON.Vector4(t.m[1], t.m[5], t.m[9], t.m[13]);
  7352. d.fillGradientTY = ty;
  7353. }
  7354. }
  7355. }
  7356. else if (part.id === Shape2D.SHAPE2D_BORDERPARTID) {
  7357. var d = part;
  7358. if (this.border) {
  7359. d.borderThickness = this.borderThickness;
  7360. var border = this.border;
  7361. if (border instanceof BABYLON.SolidColorBrush2D) {
  7362. d.borderSolidColor = border.color;
  7363. }
  7364. else if (border instanceof BABYLON.GradientColorBrush2D) {
  7365. d.borderGradientColor1 = border.color1;
  7366. d.borderGradientColor2 = border.color2;
  7367. var t = BABYLON.Matrix.Compose(new BABYLON.Vector3(border.scale, border.scale, border.scale), BABYLON.Quaternion.RotationAxis(new BABYLON.Vector3(0, 0, 1), border.rotation), new BABYLON.Vector3(border.translation.x, border.translation.y, 0));
  7368. var ty = new BABYLON.Vector4(t.m[1], t.m[5], t.m[9], t.m[13]);
  7369. d.borderGradientTY = ty;
  7370. }
  7371. }
  7372. }
  7373. return true;
  7374. };
  7375. Shape2D.prototype._updateTransparencyStatus = function () {
  7376. this._isTransparent = (this._border && this._border.isTransparent()) || (this._fill && this._fill.isTransparent()) || (this.actualOpacity < 1);
  7377. if (this._isTransparent !== this._oldTransparent) {
  7378. this._oldTransparent = this._isTransparent;
  7379. this._updateRenderMode();
  7380. }
  7381. };
  7382. Shape2D.prototype._mustUpdateInstance = function () {
  7383. var res = this._oldTransparent !== this._isTransparent;
  7384. if (res) {
  7385. this._updateRenderMode();
  7386. this._oldTransparent = this._isTransparent;
  7387. }
  7388. return res;
  7389. };
  7390. Shape2D.prototype._isPrimTransparent = function () {
  7391. return this._isTransparent;
  7392. };
  7393. Shape2D.SHAPE2D_BORDERPARTID = 1;
  7394. Shape2D.SHAPE2D_FILLPARTID = 2;
  7395. Shape2D.SHAPE2D_CATEGORY_BORDER = "Border";
  7396. Shape2D.SHAPE2D_CATEGORY_BORDERSOLID = "BorderSolid";
  7397. Shape2D.SHAPE2D_CATEGORY_BORDERGRADIENT = "BorderGradient";
  7398. Shape2D.SHAPE2D_CATEGORY_FILLSOLID = "FillSolid";
  7399. Shape2D.SHAPE2D_CATEGORY_FILLGRADIENT = "FillGradient";
  7400. Shape2D.SHAPE2D_PROPCOUNT = BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 5;
  7401. __decorate([
  7402. BABYLON.modelLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 1, function (pi) { return Shape2D.borderProperty = pi; }, true)
  7403. ], Shape2D.prototype, "border", null);
  7404. __decorate([
  7405. BABYLON.modelLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 2, function (pi) { return Shape2D.fillProperty = pi; }, true)
  7406. ], Shape2D.prototype, "fill", null);
  7407. __decorate([
  7408. BABYLON.instanceLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 3, function (pi) { return Shape2D.borderThicknessProperty = pi; })
  7409. ], Shape2D.prototype, "borderThickness", null);
  7410. Shape2D = __decorate([
  7411. BABYLON.className("Shape2D", "BABYLON")
  7412. ], Shape2D);
  7413. return Shape2D;
  7414. }(BABYLON.RenderablePrim2D));
  7415. BABYLON.Shape2D = Shape2D;
  7416. var Shape2DInstanceData = (function (_super) {
  7417. __extends(Shape2DInstanceData, _super);
  7418. function Shape2DInstanceData() {
  7419. _super.apply(this, arguments);
  7420. }
  7421. Object.defineProperty(Shape2DInstanceData.prototype, "fillSolidColor", {
  7422. // FILL ATTRIBUTES
  7423. get: function () {
  7424. return null;
  7425. },
  7426. set: function (value) {
  7427. },
  7428. enumerable: true,
  7429. configurable: true
  7430. });
  7431. Object.defineProperty(Shape2DInstanceData.prototype, "fillGradientColor1", {
  7432. get: function () {
  7433. return null;
  7434. },
  7435. set: function (value) {
  7436. },
  7437. enumerable: true,
  7438. configurable: true
  7439. });
  7440. Object.defineProperty(Shape2DInstanceData.prototype, "fillGradientColor2", {
  7441. get: function () {
  7442. return null;
  7443. },
  7444. set: function (value) {
  7445. },
  7446. enumerable: true,
  7447. configurable: true
  7448. });
  7449. Object.defineProperty(Shape2DInstanceData.prototype, "fillGradientTY", {
  7450. get: function () {
  7451. return null;
  7452. },
  7453. set: function (value) {
  7454. },
  7455. enumerable: true,
  7456. configurable: true
  7457. });
  7458. Object.defineProperty(Shape2DInstanceData.prototype, "borderThickness", {
  7459. // BORDER ATTRIBUTES
  7460. get: function () {
  7461. return null;
  7462. },
  7463. set: function (value) {
  7464. },
  7465. enumerable: true,
  7466. configurable: true
  7467. });
  7468. Object.defineProperty(Shape2DInstanceData.prototype, "borderSolidColor", {
  7469. get: function () {
  7470. return null;
  7471. },
  7472. set: function (value) {
  7473. },
  7474. enumerable: true,
  7475. configurable: true
  7476. });
  7477. Object.defineProperty(Shape2DInstanceData.prototype, "borderGradientColor1", {
  7478. get: function () {
  7479. return null;
  7480. },
  7481. set: function (value) {
  7482. },
  7483. enumerable: true,
  7484. configurable: true
  7485. });
  7486. Object.defineProperty(Shape2DInstanceData.prototype, "borderGradientColor2", {
  7487. get: function () {
  7488. return null;
  7489. },
  7490. set: function (value) {
  7491. },
  7492. enumerable: true,
  7493. configurable: true
  7494. });
  7495. Object.defineProperty(Shape2DInstanceData.prototype, "borderGradientTY", {
  7496. get: function () {
  7497. return null;
  7498. },
  7499. set: function (value) {
  7500. },
  7501. enumerable: true,
  7502. configurable: true
  7503. });
  7504. __decorate([
  7505. BABYLON.instanceData(Shape2D.SHAPE2D_CATEGORY_FILLSOLID)
  7506. ], Shape2DInstanceData.prototype, "fillSolidColor", null);
  7507. __decorate([
  7508. BABYLON.instanceData(Shape2D.SHAPE2D_CATEGORY_FILLGRADIENT)
  7509. ], Shape2DInstanceData.prototype, "fillGradientColor1", null);
  7510. __decorate([
  7511. BABYLON.instanceData(Shape2D.SHAPE2D_CATEGORY_FILLGRADIENT)
  7512. ], Shape2DInstanceData.prototype, "fillGradientColor2", null);
  7513. __decorate([
  7514. BABYLON.instanceData(Shape2D.SHAPE2D_CATEGORY_FILLGRADIENT)
  7515. ], Shape2DInstanceData.prototype, "fillGradientTY", null);
  7516. __decorate([
  7517. BABYLON.instanceData(Shape2D.SHAPE2D_CATEGORY_BORDER)
  7518. ], Shape2DInstanceData.prototype, "borderThickness", null);
  7519. __decorate([
  7520. BABYLON.instanceData(Shape2D.SHAPE2D_CATEGORY_BORDERSOLID)
  7521. ], Shape2DInstanceData.prototype, "borderSolidColor", null);
  7522. __decorate([
  7523. BABYLON.instanceData(Shape2D.SHAPE2D_CATEGORY_BORDERGRADIENT)
  7524. ], Shape2DInstanceData.prototype, "borderGradientColor1", null);
  7525. __decorate([
  7526. BABYLON.instanceData(Shape2D.SHAPE2D_CATEGORY_BORDERGRADIENT)
  7527. ], Shape2DInstanceData.prototype, "borderGradientColor2", null);
  7528. __decorate([
  7529. BABYLON.instanceData(Shape2D.SHAPE2D_CATEGORY_BORDERGRADIENT)
  7530. ], Shape2DInstanceData.prototype, "borderGradientTY", null);
  7531. return Shape2DInstanceData;
  7532. }(BABYLON.InstanceDataBase));
  7533. BABYLON.Shape2DInstanceData = Shape2DInstanceData;
  7534. })(BABYLON || (BABYLON = {}));
  7535. var BABYLON;
  7536. (function (BABYLON) {
  7537. var Group2D = (function (_super) {
  7538. __extends(Group2D, _super);
  7539. /**
  7540. * Create an Logical or Renderable Group.
  7541. * @param settings a combination of settings, possible ones are
  7542. * - parent: the parent primitive/canvas, must be specified if the primitive is not constructed as a child of another one (i.e. as part of the children array setting)
  7543. * - children: an array of direct children
  7544. * - id a text identifier, for information purpose
  7545. * - position: the X & Y positions relative to its parent. Alternatively the x and y properties can be set. Default is [0;0]
  7546. * - rotation: the initial rotation (in radian) of the primitive. default is 0
  7547. * - scale: the initial scale of the primitive. default is 1. You can alternatively use scaleX &| scaleY to apply non uniform scale
  7548. * - dontInheritParentScale: if set the parent's scale won't be taken into consideration to compute the actualScale property
  7549. * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
  7550. * - zOrder: override the zOrder with the specified value
  7551. * - origin: define the normalized origin point location, default [0.5;0.5]
  7552. * - size: the size of the group. Alternatively the width and height properties can be set. If null the size will be computed from its content, default is null.
  7553. * - cacheBehavior: Define how the group should behave regarding the Canvas's cache strategy, default is Group2D.GROUPCACHEBEHAVIOR_FOLLOWCACHESTRATEGY
  7554. * - layoutEngine: either an instance of a layout engine based class (StackPanel.Vertical, StackPanel.Horizontal) or a string ('canvas' for Canvas layout, 'StackPanel' or 'HorizontalStackPanel' for horizontal Stack Panel layout, 'VerticalStackPanel' for vertical Stack Panel layout).
  7555. * - isVisible: true if the group must be visible, false for hidden. Default is true.
  7556. * - isPickable: if true the Primitive can be used with interaction mode and will issue Pointer Event. If false it will be ignored for interaction/intersection test. Default value is true.
  7557. * - isContainer: if true the Primitive acts as a container for interaction, if the primitive is not pickable or doesn't intersection, no further test will be perform on its children. If set to false, children will always be considered for intersection/interaction. Default value is true.
  7558. * - childrenFlatZOrder: if true all the children (direct and indirect) will share the same Z-Order. Use this when there's a lot of children which don't overlap. The drawing order IS NOT GUARANTED!
  7559. * - marginTop: top margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  7560. * - marginLeft: left margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  7561. * - marginRight: right margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  7562. * - marginBottom: bottom margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  7563. * - margin: top, left, right and bottom margin formatted as a single string (see PrimitiveThickness.fromString)
  7564. * - marginHAlignment: one value of the PrimitiveAlignment type's static properties
  7565. * - marginVAlignment: one value of the PrimitiveAlignment type's static properties
  7566. * - marginAlignment: a string defining the alignment, see PrimitiveAlignment.fromString
  7567. * - paddingTop: top padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  7568. * - paddingLeft: left padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  7569. * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  7570. * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  7571. * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
  7572. */
  7573. function Group2D(settings) {
  7574. if (settings == null) {
  7575. settings = {};
  7576. }
  7577. if (settings.origin == null) {
  7578. settings.origin = new BABYLON.Vector2(0, 0);
  7579. }
  7580. _super.call(this, settings);
  7581. var size = (!settings.size && !settings.width && !settings.height) ? null : (settings.size || (new BABYLON.Size(settings.width || 0, settings.height || 0)));
  7582. this._trackedNode = (settings.trackNode == null) ? null : settings.trackNode;
  7583. if (this._trackedNode && this.owner) {
  7584. this.owner._registerTrackedNode(this);
  7585. }
  7586. this._cacheBehavior = (settings.cacheBehavior == null) ? Group2D.GROUPCACHEBEHAVIOR_FOLLOWCACHESTRATEGY : settings.cacheBehavior;
  7587. var rd = this._renderableData;
  7588. if (rd) {
  7589. rd._noResizeOnScale = (this.cacheBehavior & Group2D.GROUPCACHEBEHAVIOR_NORESIZEONSCALE) !== 0;
  7590. }
  7591. this.size = size;
  7592. this._viewportPosition = BABYLON.Vector2.Zero();
  7593. this._viewportSize = BABYLON.Size.Zero();
  7594. }
  7595. Group2D._createCachedCanvasGroup = function (owner) {
  7596. var g = new Group2D({ parent: owner, id: "__cachedCanvasGroup__", position: BABYLON.Vector2.Zero(), origin: BABYLON.Vector2.Zero(), size: null, isVisible: true, isPickable: false, dontInheritParentScale: true });
  7597. return g;
  7598. };
  7599. Group2D.prototype.applyCachedTexture = function (vertexData, material) {
  7600. this._bindCacheTarget();
  7601. if (vertexData) {
  7602. var uv = vertexData.uvs;
  7603. var nodeuv = this._renderableData._cacheNodeUVs;
  7604. for (var i = 0; i < 4; i++) {
  7605. uv[i * 2 + 0] = nodeuv[i].x;
  7606. uv[i * 2 + 1] = nodeuv[i].y;
  7607. }
  7608. }
  7609. if (material) {
  7610. material.diffuseTexture = this._renderableData._cacheTexture;
  7611. material.emissiveColor = new BABYLON.Color3(1, 1, 1);
  7612. }
  7613. this._renderableData._cacheTexture.hasAlpha = true;
  7614. this._unbindCacheTarget();
  7615. };
  7616. Object.defineProperty(Group2D.prototype, "cachedRect", {
  7617. /**
  7618. * Allow you to access the information regarding the cached rectangle of the Group2D into the MapTexture.
  7619. * If the `noWorldSpaceNode` options was used at the creation of a WorldSpaceCanvas, the rendering of the canvas must be made by the caller, so typically you want to bind the cacheTexture property to some material/mesh and you MUST use the Group2D.cachedUVs property to get the UV coordinates to use for your quad that will display the Canvas and NOT the PackedRect.UVs property which are incorrect because the allocated surface may be bigger (due to over-provisioning or shrinking without deallocating) than what the Group is actually using.
  7620. */
  7621. get: function () {
  7622. if (!this._renderableData) {
  7623. return null;
  7624. }
  7625. return this._renderableData._cacheNode;
  7626. },
  7627. enumerable: true,
  7628. configurable: true
  7629. });
  7630. Object.defineProperty(Group2D.prototype, "cachedUVs", {
  7631. /**
  7632. * The UVs into the MapTexture that map the cached group
  7633. */
  7634. get: function () {
  7635. if (!this._renderableData) {
  7636. return null;
  7637. }
  7638. return this._renderableData._cacheNodeUVs;
  7639. },
  7640. enumerable: true,
  7641. configurable: true
  7642. });
  7643. Object.defineProperty(Group2D.prototype, "cachedUVsChanged", {
  7644. get: function () {
  7645. if (!this._renderableData) {
  7646. return null;
  7647. }
  7648. if (!this._renderableData._cacheNodeUVsChangedObservable) {
  7649. this._renderableData._cacheNodeUVsChangedObservable = new BABYLON.Observable();
  7650. }
  7651. return this._renderableData._cacheNodeUVsChangedObservable;
  7652. },
  7653. enumerable: true,
  7654. configurable: true
  7655. });
  7656. Object.defineProperty(Group2D.prototype, "cacheTexture", {
  7657. /**
  7658. * Access the texture that maintains a cached version of the Group2D.
  7659. * This is useful only if you're not using a WorldSpaceNode for your WorldSpace Canvas and therefore need to perform the rendering yourself.
  7660. */
  7661. get: function () {
  7662. if (!this._renderableData) {
  7663. return null;
  7664. }
  7665. return this._renderableData._cacheTexture;
  7666. },
  7667. enumerable: true,
  7668. configurable: true
  7669. });
  7670. /**
  7671. * Call this method to remove this Group and its children from the Canvas
  7672. */
  7673. Group2D.prototype.dispose = function () {
  7674. if (!_super.prototype.dispose.call(this)) {
  7675. return false;
  7676. }
  7677. if (this._trackedNode != null) {
  7678. this.owner._unregisterTrackedNode(this);
  7679. this._trackedNode = null;
  7680. }
  7681. if (this._renderableData) {
  7682. this._renderableData.dispose(this.owner);
  7683. this._renderableData = null;
  7684. }
  7685. return true;
  7686. };
  7687. Object.defineProperty(Group2D.prototype, "isRenderableGroup", {
  7688. /**
  7689. * @returns Returns true if the Group render content, false if it's a logical group only
  7690. */
  7691. get: function () {
  7692. return this._isRenderableGroup;
  7693. },
  7694. enumerable: true,
  7695. configurable: true
  7696. });
  7697. Object.defineProperty(Group2D.prototype, "isCachedGroup", {
  7698. /**
  7699. * @returns only meaningful for isRenderableGroup, will be true if the content of the Group is cached into a texture, false if it's rendered every time
  7700. */
  7701. get: function () {
  7702. return this._isCachedGroup;
  7703. },
  7704. enumerable: true,
  7705. configurable: true
  7706. });
  7707. Object.defineProperty(Group2D.prototype, "size", {
  7708. get: function () {
  7709. return this._size;
  7710. },
  7711. /**
  7712. * Get/Set the size of the group. If null the size of the group will be determine from its content.
  7713. * BEWARE: if the Group is a RenderableGroup and its content is cache the texture will be resized each time the group is getting bigger. For performance reason the opposite won't be true: the texture won't shrink if the group does.
  7714. */
  7715. set: function (val) {
  7716. this._size = val;
  7717. },
  7718. enumerable: true,
  7719. configurable: true
  7720. });
  7721. Object.defineProperty(Group2D.prototype, "viewportSize", {
  7722. get: function () {
  7723. return this._viewportSize;
  7724. },
  7725. enumerable: true,
  7726. configurable: true
  7727. });
  7728. Object.defineProperty(Group2D.prototype, "actualSize", {
  7729. get: function () {
  7730. // The computed size will be floor on both width and height
  7731. var actualSize;
  7732. // Return the actualSize if set
  7733. if (this._actualSize) {
  7734. return this._actualSize;
  7735. }
  7736. // Return the size if set by the user
  7737. if (this._size) {
  7738. actualSize = new BABYLON.Size(Math.ceil(this._size.width), Math.ceil(this._size.height));
  7739. }
  7740. else {
  7741. var m = this.layoutBoundingInfo.max();
  7742. actualSize = new BABYLON.Size(Math.ceil(m.x), Math.ceil(m.y));
  7743. }
  7744. // Compare the size with the one we previously had, if it differs we set the property dirty and trigger a GroupChanged to synchronize a displaySprite (if any)
  7745. if (!actualSize.equals(this._actualSize)) {
  7746. this.onPrimitivePropertyDirty(Group2D.actualSizeProperty.flagId);
  7747. this._actualSize = actualSize;
  7748. this.handleGroupChanged(Group2D.actualSizeProperty);
  7749. }
  7750. return actualSize;
  7751. },
  7752. set: function (value) {
  7753. this._actualSize = value;
  7754. },
  7755. enumerable: true,
  7756. configurable: true
  7757. });
  7758. Object.defineProperty(Group2D.prototype, "cacheBehavior", {
  7759. /**
  7760. * Get/set the Cache Behavior, used in case the Canvas Cache Strategy is set to CACHESTRATEGY_ALLGROUPS. Can be either GROUPCACHEBEHAVIOR_CACHEINPARENTGROUP, GROUPCACHEBEHAVIOR_DONTCACHEOVERRIDE or GROUPCACHEBEHAVIOR_FOLLOWCACHESTRATEGY. See their documentation for more information.
  7761. * GROUPCACHEBEHAVIOR_NORESIZEONSCALE can also be set if you set it at creation time.
  7762. * It is critical to understand than you HAVE TO play with this behavior in order to achieve a good performance/memory ratio. Caching all groups would certainly be the worst strategy of all.
  7763. */
  7764. get: function () {
  7765. return this._cacheBehavior;
  7766. },
  7767. enumerable: true,
  7768. configurable: true
  7769. });
  7770. Group2D.prototype._addPrimToDirtyList = function (prim) {
  7771. this._renderableData._primDirtyList.push(prim);
  7772. };
  7773. Group2D.prototype._renderCachedCanvas = function () {
  7774. this.owner._addGroupRenderCount(1);
  7775. this.updateCachedStates(true);
  7776. var context = new BABYLON.PrepareRender2DContext();
  7777. this._prepareGroupRender(context);
  7778. this._groupRender();
  7779. };
  7780. Object.defineProperty(Group2D.prototype, "trackedNode", {
  7781. /**
  7782. * Get/set the Scene's Node that should be tracked, the group's position will follow the projected position of the Node.
  7783. */
  7784. get: function () {
  7785. return this._trackedNode;
  7786. },
  7787. set: function (val) {
  7788. if (val != null) {
  7789. if (!this._isFlagSet(BABYLON.SmartPropertyPrim.flagTrackedGroup)) {
  7790. this.owner._registerTrackedNode(this);
  7791. }
  7792. this._trackedNode = val;
  7793. }
  7794. else {
  7795. if (this._isFlagSet(BABYLON.SmartPropertyPrim.flagTrackedGroup)) {
  7796. this.owner._unregisterTrackedNode(this);
  7797. }
  7798. this._trackedNode = null;
  7799. }
  7800. },
  7801. enumerable: true,
  7802. configurable: true
  7803. });
  7804. Group2D.prototype.levelIntersect = function (intersectInfo) {
  7805. // If we've made it so far it means the boundingInfo intersection test succeed, the Group2D is shaped the same, so we always return true
  7806. return true;
  7807. };
  7808. Group2D.prototype.updateLevelBoundingInfo = function () {
  7809. var size;
  7810. // If the size is set by the user, the boundingInfo is computed from this value
  7811. if (this.size) {
  7812. size = this.size;
  7813. }
  7814. else {
  7815. size = new BABYLON.Size(0, 0);
  7816. }
  7817. BABYLON.BoundingInfo2D.CreateFromSizeToRef(size, this._levelBoundingInfo);
  7818. };
  7819. // Method called only on renderable groups to prepare the rendering
  7820. Group2D.prototype._prepareGroupRender = function (context) {
  7821. var sortedDirtyList = null;
  7822. // Update the Global Transformation and visibility status of the changed primitives
  7823. var rd = this._renderableData;
  7824. if ((rd._primDirtyList.length > 0) || context.forceRefreshPrimitive) {
  7825. sortedDirtyList = rd._primDirtyList.sort(function (a, b) { return a.hierarchyDepth - b.hierarchyDepth; });
  7826. this.updateCachedStatesOf(sortedDirtyList, true);
  7827. }
  7828. var s = this.actualSize;
  7829. var a = this.actualScale;
  7830. var sw = Math.ceil(s.width * a.x);
  7831. var sh = Math.ceil(s.height * a.y);
  7832. // The dimension must be overridden when using the designSize feature, the ratio is maintain to compute a uniform scale, which is mandatory but if the designSize's ratio is different from the rendering surface's ratio, content will be clipped in some cases.
  7833. // So we set the width/height to the rendering's one because that's what we want for the viewport!
  7834. if (this instanceof BABYLON.Canvas2D) {
  7835. var c = this;
  7836. if (c.designSize != null) {
  7837. sw = this.owner.engine.getRenderWidth();
  7838. sh = this.owner.engine.getRenderHeight();
  7839. }
  7840. }
  7841. // Setup the size of the rendering viewport
  7842. // In non cache mode, we're rendering directly to the rendering canvas, in this case we have to detect if the canvas size changed since the previous iteration, if it's the case all primitives must be prepared again because their transformation must be recompute
  7843. if (!this._isCachedGroup) {
  7844. // Compute the WebGL viewport's location/size
  7845. var t = this._globalTransform.getTranslation();
  7846. var rs = this.owner._renderingSize;
  7847. sh = Math.min(sh, rs.height - t.y);
  7848. sw = Math.min(sw, rs.width - t.x);
  7849. var x = t.x;
  7850. var y = t.y;
  7851. // The viewport where we're rendering must be the size of the canvas if this one fit in the rendering screen or clipped to the screen dimensions if needed
  7852. this._viewportPosition.x = x;
  7853. this._viewportPosition.y = y;
  7854. }
  7855. // For a cachedGroup we also check of the group's actualSize is changing, if it's the case then the rendering zone will be change so we also have to dirty all primitives to prepare them again.
  7856. if (this._viewportSize.width !== sw || this._viewportSize.height !== sh) {
  7857. context.forceRefreshPrimitive = true;
  7858. this._viewportSize.width = sw;
  7859. this._viewportSize.height = sh;
  7860. }
  7861. if ((rd._primDirtyList.length > 0) || context.forceRefreshPrimitive) {
  7862. // If the group is cached, set the dirty flag to true because of the incoming changes
  7863. this._cacheGroupDirty = this._isCachedGroup;
  7864. rd._primNewDirtyList.splice(0);
  7865. // If it's a force refresh, prepare all the children
  7866. if (context.forceRefreshPrimitive) {
  7867. for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
  7868. var p = _a[_i];
  7869. p._prepareRender(context);
  7870. }
  7871. }
  7872. else {
  7873. // Each primitive that changed at least once was added into the primDirtyList, we have to sort this level using
  7874. // the hierarchyDepth in order to prepare primitives from top to bottom
  7875. if (!sortedDirtyList) {
  7876. sortedDirtyList = rd._primDirtyList.sort(function (a, b) { return a.hierarchyDepth - b.hierarchyDepth; });
  7877. }
  7878. sortedDirtyList.forEach(function (p) {
  7879. // We need to check if prepare is needed because even if the primitive is in the dirtyList, its parent primitive may also have been modified, then prepared, then recurse on its children primitives (this one for instance) if the changes where impacting them.
  7880. // For instance: a Rect's position change, the position of its children primitives will also change so a prepare will be call on them. If a child was in the dirtyList we will avoid a second prepare by making this check.
  7881. if (!p.isDisposed && p._needPrepare()) {
  7882. p._prepareRender(context);
  7883. }
  7884. });
  7885. }
  7886. // Everything is updated, clear the dirty list
  7887. rd._primDirtyList.forEach(function (p) {
  7888. if (rd._primNewDirtyList.indexOf(p) === -1) {
  7889. p._resetPropertiesDirty();
  7890. }
  7891. else {
  7892. p._setFlags(BABYLON.SmartPropertyPrim.flagNeedRefresh);
  7893. }
  7894. });
  7895. rd._primDirtyList.splice(0);
  7896. rd._primDirtyList = rd._primDirtyList.concat(rd._primNewDirtyList);
  7897. }
  7898. // A renderable group has a list of direct children that are also renderable groups, we recurse on them to also prepare them
  7899. rd._childrenRenderableGroups.forEach(function (g) {
  7900. g._prepareGroupRender(context);
  7901. });
  7902. };
  7903. Group2D.prototype._groupRender = function () {
  7904. var _this = this;
  7905. var engine = this.owner.engine;
  7906. var failedCount = 0;
  7907. // First recurse to children render group to render them (in their cache or on screen)
  7908. for (var _i = 0, _a = this._renderableData._childrenRenderableGroups; _i < _a.length; _i++) {
  7909. var childGroup = _a[_i];
  7910. childGroup._groupRender();
  7911. }
  7912. // Render the primitives if needed: either if we don't cache the content or if the content is cached but has changed
  7913. if (!this.isCachedGroup || this._cacheGroupDirty) {
  7914. this.owner._addGroupRenderCount(1);
  7915. if (this.isCachedGroup) {
  7916. this._bindCacheTarget();
  7917. }
  7918. else {
  7919. var curVP = engine.setDirectViewport(this._viewportPosition.x, this._viewportPosition.y, this._viewportSize.width, this._viewportSize.height);
  7920. }
  7921. var curAlphaTest = engine.getAlphaTesting() === true;
  7922. var curDepthWrite = engine.getDepthWrite() === true;
  7923. // ===================================================================
  7924. // First pass, update the InstancedArray and render Opaque primitives
  7925. // Disable Alpha Testing, Enable Depth Write
  7926. engine.setAlphaTesting(false);
  7927. engine.setDepthWrite(true);
  7928. // For each different model of primitive to render
  7929. var context_1 = new BABYLON.Render2DContext(BABYLON.Render2DContext.RenderModeOpaque);
  7930. this._renderableData._renderGroupInstancesInfo.forEach(function (k, v) {
  7931. // Prepare the context object, update the WebGL Instanced Array buffer if needed
  7932. var renderCount = _this._prepareContext(engine, context_1, v);
  7933. // If null is returned, there's no opaque data to render
  7934. if (renderCount === null) {
  7935. return;
  7936. }
  7937. // Submit render only if we have something to render (everything may be hidden and the floatarray empty)
  7938. if (!_this.owner.supportInstancedArray || renderCount > 0) {
  7939. // render all the instances of this model, if the render method returns true then our instances are no longer dirty
  7940. var renderFailed = !v.modelRenderCache.render(v, context_1);
  7941. // Update dirty flag/related
  7942. v.opaqueDirty = renderFailed;
  7943. failedCount += renderFailed ? 1 : 0;
  7944. }
  7945. });
  7946. // =======================================================================
  7947. // Second pass, update the InstancedArray and render AlphaTest primitives
  7948. // Enable Alpha Testing, Enable Depth Write
  7949. engine.setAlphaTesting(true);
  7950. engine.setDepthWrite(true);
  7951. // For each different model of primitive to render
  7952. context_1 = new BABYLON.Render2DContext(BABYLON.Render2DContext.RenderModeAlphaTest);
  7953. this._renderableData._renderGroupInstancesInfo.forEach(function (k, v) {
  7954. // Prepare the context object, update the WebGL Instanced Array buffer if needed
  7955. var renderCount = _this._prepareContext(engine, context_1, v);
  7956. // If null is returned, there's no opaque data to render
  7957. if (renderCount === null) {
  7958. return;
  7959. }
  7960. // Submit render only if we have something to render (everything may be hidden and the floatarray empty)
  7961. if (!_this.owner.supportInstancedArray || renderCount > 0) {
  7962. // render all the instances of this model, if the render method returns true then our instances are no longer dirty
  7963. var renderFailed = !v.modelRenderCache.render(v, context_1);
  7964. // Update dirty flag/related
  7965. v.opaqueDirty = renderFailed;
  7966. failedCount += renderFailed ? 1 : 0;
  7967. }
  7968. });
  7969. // =======================================================================
  7970. // Third pass, transparent primitive rendering
  7971. // Enable Alpha Testing, Disable Depth Write
  7972. engine.setAlphaTesting(true);
  7973. engine.setDepthWrite(false);
  7974. // First Check if the transparent List change so we can update the TransparentSegment and PartData (sort if needed)
  7975. if (this._renderableData._transparentListChanged) {
  7976. this._updateTransparentData();
  7977. }
  7978. // From this point on we have up to date data to render, so let's go
  7979. failedCount += this._renderTransparentData();
  7980. // =======================================================================
  7981. // Unbind target/restore viewport setting, clear dirty flag, and quit
  7982. // The group's content is no longer dirty
  7983. this._cacheGroupDirty = failedCount !== 0;
  7984. if (this.isCachedGroup) {
  7985. this._unbindCacheTarget();
  7986. }
  7987. else {
  7988. if (curVP) {
  7989. engine.setViewport(curVP);
  7990. }
  7991. }
  7992. // Restore saved states
  7993. engine.setAlphaTesting(curAlphaTest);
  7994. engine.setDepthWrite(curDepthWrite);
  7995. }
  7996. };
  7997. Group2D.prototype._setCacheGroupDirty = function () {
  7998. this._cacheGroupDirty = true;
  7999. };
  8000. Group2D.prototype._updateTransparentData = function () {
  8001. this.owner._addUpdateTransparentDataCount(1);
  8002. var rd = this._renderableData;
  8003. // Sort all the primitive from their depth, max (bottom) to min (top)
  8004. rd._transparentPrimitives.sort(function (a, b) { return b._primitive.actualZOffset - a._primitive.actualZOffset; });
  8005. var checkAndAddPrimInSegment = function (seg, tpiI) {
  8006. var tpi = rd._transparentPrimitives[tpiI];
  8007. // Fast rejection: if gii are different
  8008. if (seg.groupInsanceInfo !== tpi._groupInstanceInfo) {
  8009. return false;
  8010. }
  8011. //let tpiZ = tpi._primitive.actualZOffset;
  8012. // We've made it so far, the tpi can be part of the segment, add it
  8013. tpi._transparentSegment = seg;
  8014. tpi._primitive._updateTransparentSegmentIndices(seg);
  8015. return true;
  8016. };
  8017. // Free the existing TransparentSegments
  8018. for (var _i = 0, _a = rd._transparentSegments; _i < _a.length; _i++) {
  8019. var ts = _a[_i];
  8020. ts.dispose(this.owner.engine);
  8021. }
  8022. rd._transparentSegments.splice(0);
  8023. var prevSeg = null;
  8024. for (var tpiI = 0; tpiI < rd._transparentPrimitives.length; tpiI++) {
  8025. var tpi = rd._transparentPrimitives[tpiI];
  8026. // Check if the Data in which the primitive is stored is not sorted properly
  8027. if (tpi._groupInstanceInfo.transparentOrderDirty) {
  8028. tpi._groupInstanceInfo.sortTransparentData();
  8029. }
  8030. // Reset the segment, we have to create/rebuild it
  8031. tpi._transparentSegment = null;
  8032. // If there's a previous valid segment, check if this prim can be part of it
  8033. if (prevSeg) {
  8034. checkAndAddPrimInSegment(prevSeg, tpiI);
  8035. }
  8036. // If we couldn't insert in the adjacent segments, he have to create one
  8037. if (!tpi._transparentSegment) {
  8038. var ts = new BABYLON.TransparentSegment();
  8039. ts.groupInsanceInfo = tpi._groupInstanceInfo;
  8040. var prim = tpi._primitive;
  8041. ts.startZ = prim.actualZOffset;
  8042. prim._updateTransparentSegmentIndices(ts);
  8043. ts.endZ = ts.startZ;
  8044. tpi._transparentSegment = ts;
  8045. rd._transparentSegments.push(ts);
  8046. }
  8047. // Update prevSeg
  8048. prevSeg = tpi._transparentSegment;
  8049. }
  8050. //rd._firstChangedPrim = null;
  8051. rd._transparentListChanged = false;
  8052. };
  8053. Group2D.prototype._renderTransparentData = function () {
  8054. var failedCount = 0;
  8055. var context = new BABYLON.Render2DContext(BABYLON.Render2DContext.RenderModeTransparent);
  8056. var rd = this._renderableData;
  8057. var useInstanced = this.owner.supportInstancedArray;
  8058. var length = rd._transparentSegments.length;
  8059. for (var i = 0; i < length; i++) {
  8060. context.instancedBuffers = null;
  8061. var ts = rd._transparentSegments[i];
  8062. var gii = ts.groupInsanceInfo;
  8063. var mrc = gii.modelRenderCache;
  8064. var engine = this.owner.engine;
  8065. var count = ts.endDataIndex - ts.startDataIndex;
  8066. // Use Instanced Array if it's supported and if there's at least 5 prims to draw.
  8067. // We don't want to create an Instanced Buffer for less that 5 prims
  8068. if (useInstanced && count >= 5) {
  8069. if (!ts.partBuffers) {
  8070. var buffers = new Array();
  8071. for (var j = 0; j < gii.transparentData.length; j++) {
  8072. var gitd = gii.transparentData[j];
  8073. var dfa = gitd._partData;
  8074. var data = dfa.pack();
  8075. var stride = dfa.stride;
  8076. var neededSize = count * stride * 4;
  8077. var buffer = engine.createInstancesBuffer(neededSize); // Create + bind
  8078. var segData = data.subarray(ts.startDataIndex * stride, ts.endDataIndex * stride);
  8079. engine.updateArrayBuffer(segData);
  8080. buffers.push(buffer);
  8081. }
  8082. ts.partBuffers = buffers;
  8083. }
  8084. else if (gii.transparentDirty) {
  8085. for (var j = 0; j < gii.transparentData.length; j++) {
  8086. var gitd = gii.transparentData[j];
  8087. var dfa = gitd._partData;
  8088. var data = dfa.pack();
  8089. var stride = dfa.stride;
  8090. var buffer = ts.partBuffers[j];
  8091. var segData = data.subarray(ts.startDataIndex * stride, ts.endDataIndex * stride);
  8092. engine.bindArrayBuffer(buffer);
  8093. engine.updateArrayBuffer(segData);
  8094. }
  8095. }
  8096. context.useInstancing = true;
  8097. context.instancesCount = count;
  8098. context.instancedBuffers = ts.partBuffers;
  8099. context.groupInfoPartData = gii.transparentData;
  8100. var renderFailed = !mrc.render(gii, context);
  8101. failedCount += renderFailed ? 1 : 0;
  8102. }
  8103. else {
  8104. context.useInstancing = false;
  8105. context.partDataStartIndex = ts.startDataIndex;
  8106. context.partDataEndIndex = ts.endDataIndex;
  8107. context.groupInfoPartData = gii.transparentData;
  8108. var renderFailed = !mrc.render(gii, context);
  8109. failedCount += renderFailed ? 1 : 0;
  8110. }
  8111. }
  8112. return failedCount;
  8113. };
  8114. Group2D.prototype._prepareContext = function (engine, context, gii) {
  8115. var gipd = null;
  8116. var setDirty;
  8117. var getDirty;
  8118. // Render Mode specifics
  8119. switch (context.renderMode) {
  8120. case BABYLON.Render2DContext.RenderModeOpaque:
  8121. {
  8122. if (!gii.hasOpaqueData) {
  8123. return null;
  8124. }
  8125. setDirty = function (dirty) { gii.opaqueDirty = dirty; };
  8126. getDirty = function () { return gii.opaqueDirty; };
  8127. context.groupInfoPartData = gii.opaqueData;
  8128. gipd = gii.opaqueData;
  8129. break;
  8130. }
  8131. case BABYLON.Render2DContext.RenderModeAlphaTest:
  8132. {
  8133. if (!gii.hasAlphaTestData) {
  8134. return null;
  8135. }
  8136. setDirty = function (dirty) { gii.alphaTestDirty = dirty; };
  8137. getDirty = function () { return gii.alphaTestDirty; };
  8138. context.groupInfoPartData = gii.alphaTestData;
  8139. gipd = gii.alphaTestData;
  8140. break;
  8141. }
  8142. default:
  8143. throw new Error("_prepareContext is only for opaque or alphaTest");
  8144. }
  8145. var renderCount = 0;
  8146. // This part will pack the dynamicfloatarray and update the instanced array WebGLBufffer
  8147. // Skip it if instanced arrays are not supported
  8148. if (this.owner.supportInstancedArray) {
  8149. // Flag for instancing
  8150. context.useInstancing = true;
  8151. // Make sure all the WebGLBuffers of the Instanced Array are created/up to date for the parts to render.
  8152. for (var i = 0; i < gipd.length; i++) {
  8153. var pid = gipd[i];
  8154. // If the instances of the model was changed, pack the data
  8155. var array = pid._partData;
  8156. var instanceData_1 = array.pack();
  8157. renderCount += array.usedElementCount;
  8158. // Compute the size the instance buffer should have
  8159. var neededSize = array.usedElementCount * array.stride * 4;
  8160. // Check if we have to (re)create the instancesBuffer because there's none or the size is too small
  8161. if (!pid._partBuffer || (pid._partBufferSize < neededSize)) {
  8162. if (pid._partBuffer) {
  8163. engine.deleteInstancesBuffer(pid._partBuffer);
  8164. }
  8165. pid._partBuffer = engine.createInstancesBuffer(neededSize); // Create + bind
  8166. pid._partBufferSize = neededSize;
  8167. setDirty(false);
  8168. // Update the WebGL buffer to match the new content of the instances data
  8169. engine.updateArrayBuffer(instanceData_1);
  8170. }
  8171. else if (getDirty()) {
  8172. // Update the WebGL buffer to match the new content of the instances data
  8173. engine.bindArrayBuffer(pid._partBuffer);
  8174. engine.updateArrayBuffer(instanceData_1);
  8175. }
  8176. }
  8177. setDirty(false);
  8178. }
  8179. else {
  8180. context.partDataStartIndex = 0;
  8181. // Find the first valid object to get the count
  8182. if (context.groupInfoPartData.length > 0) {
  8183. var i = 0;
  8184. while (!context.groupInfoPartData[i]) {
  8185. i++;
  8186. }
  8187. context.partDataEndIndex = context.groupInfoPartData[i]._partData.usedElementCount;
  8188. }
  8189. }
  8190. return renderCount;
  8191. };
  8192. Group2D.prototype._setRenderingScale = function (scale) {
  8193. if (this._renderableData._renderingScale === scale) {
  8194. return;
  8195. }
  8196. this._renderableData._renderingScale = scale;
  8197. };
  8198. Group2D.prototype._bindCacheTarget = function () {
  8199. var curWidth;
  8200. var curHeight;
  8201. var rd = this._renderableData;
  8202. var rs = rd._renderingScale;
  8203. var noResizeScale = rd._noResizeOnScale;
  8204. var isCanvas = this.parent == null;
  8205. var scale;
  8206. if (noResizeScale) {
  8207. scale = isCanvas ? Group2D._uV : this.parent.actualScale;
  8208. }
  8209. else {
  8210. scale = this.actualScale;
  8211. }
  8212. Group2D._s.width = Math.ceil(this.actualSize.width * scale.x * rs);
  8213. Group2D._s.height = Math.ceil(this.actualSize.height * scale.y * rs);
  8214. var sizeChanged = !Group2D._s.equals(rd._cacheSize);
  8215. if (rd._cacheNode) {
  8216. var size = rd._cacheNode.contentSize;
  8217. // Check if we have to deallocate because the size is too small
  8218. if ((size.width < Group2D._s.width) || (size.height < Group2D._s.height)) {
  8219. // For Screen space: over-provisioning of 7% more to avoid frequent resizing for few pixels...
  8220. // For World space: no over-provisioning
  8221. var overprovisioning = this.owner.isScreenSpace ? 1.07 : 1;
  8222. curWidth = Math.floor(Group2D._s.width * overprovisioning);
  8223. curHeight = Math.floor(Group2D._s.height * overprovisioning);
  8224. //console.log(`[${this._globalTransformProcessStep}] Resize group ${this.id}, width: ${curWidth}, height: ${curHeight}`);
  8225. rd._cacheTexture.freeRect(rd._cacheNode);
  8226. rd._cacheNode = null;
  8227. }
  8228. }
  8229. if (!rd._cacheNode) {
  8230. // Check if we have to allocate a rendering zone in the global cache texture
  8231. var res = this.owner._allocateGroupCache(this, this.parent && this.parent.renderGroup, curWidth ? new BABYLON.Size(curWidth, curHeight) : null, rd._useMipMap, rd._anisotropicLevel);
  8232. rd._cacheNode = res.node;
  8233. rd._cacheTexture = res.texture;
  8234. rd._cacheRenderSprite = res.sprite;
  8235. sizeChanged = true;
  8236. }
  8237. if (sizeChanged) {
  8238. rd._cacheSize.copyFrom(Group2D._s);
  8239. rd._cacheNodeUVs = rd._cacheNode.getUVsForCustomSize(rd._cacheSize);
  8240. if (rd._cacheNodeUVsChangedObservable && rd._cacheNodeUVsChangedObservable.hasObservers()) {
  8241. rd._cacheNodeUVsChangedObservable.notifyObservers(rd._cacheNodeUVs);
  8242. }
  8243. this._setFlags(BABYLON.SmartPropertyPrim.flagWorldCacheChanged);
  8244. }
  8245. var n = rd._cacheNode;
  8246. rd._cacheTexture.bindTextureForPosSize(n.pos, Group2D._s, true);
  8247. };
  8248. Group2D.prototype._unbindCacheTarget = function () {
  8249. if (this._renderableData._cacheTexture) {
  8250. this._renderableData._cacheTexture.unbindTexture();
  8251. }
  8252. };
  8253. Group2D.prototype.handleGroupChanged = function (prop) {
  8254. // This method is only for cachedGroup
  8255. var rd = this._renderableData;
  8256. if (!rd) {
  8257. return;
  8258. }
  8259. var cachedSprite = rd._cacheRenderSprite;
  8260. if (!this.isCachedGroup || !cachedSprite) {
  8261. return;
  8262. }
  8263. // For now we only support these property changes
  8264. // TODO: add more! :)
  8265. if (prop.id === BABYLON.Prim2DBase.actualPositionProperty.id) {
  8266. cachedSprite.actualPosition = this.actualPosition.clone();
  8267. if (cachedSprite.position != null) {
  8268. cachedSprite.position = cachedSprite.actualPosition.clone();
  8269. }
  8270. }
  8271. else if (prop.id === BABYLON.Prim2DBase.rotationProperty.id) {
  8272. cachedSprite.rotation = this.rotation;
  8273. }
  8274. else if (prop.id === BABYLON.Prim2DBase.scaleProperty.id) {
  8275. cachedSprite.scale = this.scale;
  8276. }
  8277. else if (prop.id === BABYLON.Prim2DBase.originProperty.id) {
  8278. cachedSprite.origin = this.origin.clone();
  8279. }
  8280. else if (prop.id === Group2D.actualSizeProperty.id) {
  8281. cachedSprite.size = this.actualSize.clone();
  8282. }
  8283. };
  8284. Group2D.prototype.detectGroupStates = function () {
  8285. var isCanvas = this instanceof BABYLON.Canvas2D;
  8286. var canvasStrat = this.owner.cachingStrategy;
  8287. // In Don't Cache mode, only the canvas is renderable, all the other groups are logical. There are not a single cached group.
  8288. if (canvasStrat === BABYLON.Canvas2D.CACHESTRATEGY_DONTCACHE) {
  8289. this._isRenderableGroup = isCanvas;
  8290. this._isCachedGroup = false;
  8291. }
  8292. else if (canvasStrat === BABYLON.Canvas2D.CACHESTRATEGY_CANVAS) {
  8293. if (isCanvas) {
  8294. this._isRenderableGroup = true;
  8295. this._isCachedGroup = true;
  8296. }
  8297. else {
  8298. this._isRenderableGroup = this.id === "__cachedCanvasGroup__";
  8299. this._isCachedGroup = false;
  8300. }
  8301. }
  8302. else if (canvasStrat === BABYLON.Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS) {
  8303. if (isCanvas) {
  8304. this._isRenderableGroup = true;
  8305. this._isCachedGroup = false;
  8306. }
  8307. else {
  8308. if (this.hierarchyDepth === 1) {
  8309. this._isRenderableGroup = true;
  8310. this._isCachedGroup = true;
  8311. }
  8312. else {
  8313. this._isRenderableGroup = false;
  8314. this._isCachedGroup = false;
  8315. }
  8316. }
  8317. }
  8318. else if (canvasStrat === BABYLON.Canvas2D.CACHESTRATEGY_ALLGROUPS) {
  8319. var gcb = this.cacheBehavior & Group2D.GROUPCACHEBEHAVIOR_OPTIONMASK;
  8320. if ((gcb === Group2D.GROUPCACHEBEHAVIOR_DONTCACHEOVERRIDE) || (gcb === Group2D.GROUPCACHEBEHAVIOR_CACHEINPARENTGROUP)) {
  8321. this._isRenderableGroup = gcb === Group2D.GROUPCACHEBEHAVIOR_DONTCACHEOVERRIDE;
  8322. this._isCachedGroup = false;
  8323. }
  8324. if (gcb === Group2D.GROUPCACHEBEHAVIOR_FOLLOWCACHESTRATEGY) {
  8325. this._isRenderableGroup = true;
  8326. this._isCachedGroup = true;
  8327. }
  8328. }
  8329. if (this._isRenderableGroup) {
  8330. // Yes, we do need that check, trust me, unfortunately we can call _detectGroupStates many time on the same object...
  8331. if (!this._renderableData) {
  8332. this._renderableData = new RenderableGroupData();
  8333. }
  8334. }
  8335. // If the group is tagged as renderable we add it to the renderable tree
  8336. if (this._isCachedGroup) {
  8337. this._renderableData._noResizeOnScale = (this.cacheBehavior & Group2D.GROUPCACHEBEHAVIOR_NORESIZEONSCALE) !== 0;
  8338. var cur = this.parent;
  8339. while (cur) {
  8340. if (cur instanceof Group2D && cur._isRenderableGroup) {
  8341. if (cur._renderableData._childrenRenderableGroups.indexOf(this) === -1) {
  8342. cur._renderableData._childrenRenderableGroups.push(this);
  8343. }
  8344. break;
  8345. }
  8346. cur = cur.parent;
  8347. }
  8348. }
  8349. };
  8350. Group2D.GROUP2D_PROPCOUNT = BABYLON.Prim2DBase.PRIM2DBASE_PROPCOUNT + 5;
  8351. /**
  8352. * Default behavior, the group will use the caching strategy defined at the Canvas Level
  8353. */
  8354. Group2D.GROUPCACHEBEHAVIOR_FOLLOWCACHESTRATEGY = 0;
  8355. /**
  8356. * When used, this group's content won't be cached, no matter which strategy used.
  8357. * If the group is part of a WorldSpace Canvas, its content will be drawn in the Canvas cache bitmap.
  8358. */
  8359. Group2D.GROUPCACHEBEHAVIOR_DONTCACHEOVERRIDE = 1;
  8360. /**
  8361. * When used, the group's content will be cached in the nearest cached parent group/canvas
  8362. */
  8363. Group2D.GROUPCACHEBEHAVIOR_CACHEINPARENTGROUP = 2;
  8364. /**
  8365. * You can specify this behavior to any cached Group2D to indicate that you don't want the cached content to be resized when the Group's actualScale is changing. It will draw the content stretched or shrink which is faster than a resize. This setting is obviously for performance consideration, don't use it if you want the best rendering quality
  8366. */
  8367. Group2D.GROUPCACHEBEHAVIOR_NORESIZEONSCALE = 0x100;
  8368. Group2D.GROUPCACHEBEHAVIOR_OPTIONMASK = 0xFF;
  8369. Group2D._uV = new BABYLON.Vector2(1, 1);
  8370. Group2D._s = BABYLON.Size.Zero();
  8371. __decorate([
  8372. BABYLON.instanceLevelProperty(BABYLON.Prim2DBase.PRIM2DBASE_PROPCOUNT + 1, function (pi) { return Group2D.sizeProperty = pi; }, false, true)
  8373. ], Group2D.prototype, "size", null);
  8374. __decorate([
  8375. BABYLON.instanceLevelProperty(BABYLON.Prim2DBase.PRIM2DBASE_PROPCOUNT + 2, function (pi) { return Group2D.actualSizeProperty = pi; })
  8376. ], Group2D.prototype, "actualSize", null);
  8377. Group2D = __decorate([
  8378. BABYLON.className("Group2D", "BABYLON")
  8379. ], Group2D);
  8380. return Group2D;
  8381. }(BABYLON.Prim2DBase));
  8382. BABYLON.Group2D = Group2D;
  8383. var RenderableGroupData = (function () {
  8384. function RenderableGroupData() {
  8385. this._primDirtyList = new Array();
  8386. this._primNewDirtyList = new Array();
  8387. this._childrenRenderableGroups = new Array();
  8388. this._renderGroupInstancesInfo = new BABYLON.StringDictionary();
  8389. this._transparentPrimitives = new Array();
  8390. this._transparentSegments = new Array();
  8391. this._transparentListChanged = false;
  8392. this._cacheNode = null;
  8393. this._cacheTexture = null;
  8394. this._cacheRenderSprite = null;
  8395. this._renderingScale = 1;
  8396. this._cacheNodeUVs = null;
  8397. this._cacheNodeUVsChangedObservable = null;
  8398. this._cacheSize = BABYLON.Size.Zero();
  8399. this._useMipMap = false;
  8400. this._anisotropicLevel = 1;
  8401. this._noResizeOnScale = false;
  8402. }
  8403. RenderableGroupData.prototype.dispose = function (owner) {
  8404. var engine = owner.engine;
  8405. if (this._cacheRenderSprite) {
  8406. this._cacheRenderSprite.dispose();
  8407. this._cacheRenderSprite = null;
  8408. }
  8409. if (this._cacheTexture && this._cacheNode) {
  8410. this._cacheTexture.freeRect(this._cacheNode);
  8411. this._cacheTexture = null;
  8412. this._cacheNode = null;
  8413. }
  8414. if (this._primDirtyList) {
  8415. this._primDirtyList.splice(0);
  8416. this._primDirtyList = null;
  8417. }
  8418. if (this._renderGroupInstancesInfo) {
  8419. this._renderGroupInstancesInfo.forEach(function (k, v) {
  8420. v.dispose();
  8421. });
  8422. this._renderGroupInstancesInfo = null;
  8423. }
  8424. if (this._cacheNodeUVsChangedObservable) {
  8425. this._cacheNodeUVsChangedObservable.clear();
  8426. this._cacheNodeUVsChangedObservable = null;
  8427. }
  8428. if (this._transparentSegments) {
  8429. for (var _i = 0, _a = this._transparentSegments; _i < _a.length; _i++) {
  8430. var ts = _a[_i];
  8431. ts.dispose(engine);
  8432. }
  8433. this._transparentSegments.splice(0);
  8434. this._transparentSegments = null;
  8435. }
  8436. };
  8437. RenderableGroupData.prototype.addNewTransparentPrimitiveInfo = function (prim, gii) {
  8438. var tpi = new TransparentPrimitiveInfo();
  8439. tpi._primitive = prim;
  8440. tpi._groupInstanceInfo = gii;
  8441. tpi._transparentSegment = null;
  8442. this._transparentPrimitives.push(tpi);
  8443. this._transparentListChanged = true;
  8444. return tpi;
  8445. };
  8446. RenderableGroupData.prototype.removeTransparentPrimitiveInfo = function (tpi) {
  8447. var index = this._transparentPrimitives.indexOf(tpi);
  8448. if (index !== -1) {
  8449. this._transparentPrimitives.splice(index, 1);
  8450. this._transparentListChanged = true;
  8451. }
  8452. };
  8453. RenderableGroupData.prototype.transparentPrimitiveZChanged = function (tpi) {
  8454. this._transparentListChanged = true;
  8455. //this.updateSmallestZChangedPrim(tpi);
  8456. };
  8457. return RenderableGroupData;
  8458. }());
  8459. BABYLON.RenderableGroupData = RenderableGroupData;
  8460. var TransparentPrimitiveInfo = (function () {
  8461. function TransparentPrimitiveInfo() {
  8462. }
  8463. return TransparentPrimitiveInfo;
  8464. }());
  8465. BABYLON.TransparentPrimitiveInfo = TransparentPrimitiveInfo;
  8466. })(BABYLON || (BABYLON = {}));
  8467. var BABYLON;
  8468. (function (BABYLON) {
  8469. var Rectangle2DRenderCache = (function (_super) {
  8470. __extends(Rectangle2DRenderCache, _super);
  8471. function Rectangle2DRenderCache(engine, modelKey) {
  8472. _super.call(this, engine, modelKey);
  8473. this.effectsReady = false;
  8474. this.fillVB = null;
  8475. this.fillIB = null;
  8476. this.fillIndicesCount = 0;
  8477. this.instancingFillAttributes = null;
  8478. this.effectFill = null;
  8479. this.effectFillInstanced = null;
  8480. this.borderVB = null;
  8481. this.borderIB = null;
  8482. this.borderIndicesCount = 0;
  8483. this.instancingBorderAttributes = null;
  8484. this.effectBorder = null;
  8485. this.effectBorderInstanced = null;
  8486. }
  8487. Rectangle2DRenderCache.prototype.render = function (instanceInfo, context) {
  8488. // Do nothing if the shader is still loading/preparing
  8489. if (!this.effectsReady) {
  8490. if ((this.effectFill && (!this.effectFill.isReady() || (this.effectFillInstanced && !this.effectFillInstanced.isReady()))) ||
  8491. (this.effectBorder && (!this.effectBorder.isReady() || (this.effectBorderInstanced && !this.effectBorderInstanced.isReady())))) {
  8492. return false;
  8493. }
  8494. this.effectsReady = true;
  8495. }
  8496. var canvas = instanceInfo.owner.owner;
  8497. var engine = canvas.engine;
  8498. var depthFunction = 0;
  8499. if (this.effectFill && this.effectBorder) {
  8500. depthFunction = engine.getDepthFunction();
  8501. engine.setDepthFunctionToLessOrEqual();
  8502. }
  8503. var curAlphaMode = engine.getAlphaMode();
  8504. if (this.effectFill) {
  8505. var partIndex = instanceInfo.partIndexFromId.get(BABYLON.Shape2D.SHAPE2D_FILLPARTID.toString());
  8506. var pid = context.groupInfoPartData[partIndex];
  8507. if (context.renderMode !== BABYLON.Render2DContext.RenderModeOpaque) {
  8508. engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE, true);
  8509. }
  8510. var effect = context.useInstancing ? this.effectFillInstanced : this.effectFill;
  8511. engine.enableEffect(effect);
  8512. engine.bindBuffersDirectly(this.fillVB, this.fillIB, [1], 4, effect);
  8513. if (context.useInstancing) {
  8514. if (!this.instancingFillAttributes) {
  8515. this.instancingFillAttributes = this.loadInstancingAttributes(BABYLON.Shape2D.SHAPE2D_FILLPARTID, effect);
  8516. }
  8517. var glBuffer = context.instancedBuffers ? context.instancedBuffers[partIndex] : pid._partBuffer;
  8518. var count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
  8519. canvas._addDrawCallCount(1, context.renderMode);
  8520. engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingFillAttributes);
  8521. engine.draw(true, 0, this.fillIndicesCount, count);
  8522. engine.unbindInstanceAttributes();
  8523. }
  8524. else {
  8525. canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);
  8526. for (var i = context.partDataStartIndex; i < context.partDataEndIndex; i++) {
  8527. this.setupUniforms(effect, partIndex, pid._partData, i);
  8528. engine.draw(true, 0, this.fillIndicesCount);
  8529. }
  8530. }
  8531. }
  8532. if (this.effectBorder) {
  8533. var partIndex = instanceInfo.partIndexFromId.get(BABYLON.Shape2D.SHAPE2D_BORDERPARTID.toString());
  8534. var pid = context.groupInfoPartData[partIndex];
  8535. if (context.renderMode !== BABYLON.Render2DContext.RenderModeOpaque) {
  8536. engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE, true);
  8537. }
  8538. var effect = context.useInstancing ? this.effectBorderInstanced : this.effectBorder;
  8539. engine.enableEffect(effect);
  8540. engine.bindBuffersDirectly(this.borderVB, this.borderIB, [1], 4, effect);
  8541. if (context.useInstancing) {
  8542. if (!this.instancingBorderAttributes) {
  8543. this.instancingBorderAttributes = this.loadInstancingAttributes(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, effect);
  8544. }
  8545. var glBuffer = context.instancedBuffers ? context.instancedBuffers[partIndex] : pid._partBuffer;
  8546. var count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
  8547. canvas._addDrawCallCount(1, context.renderMode);
  8548. engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingBorderAttributes);
  8549. engine.draw(true, 0, this.borderIndicesCount, count);
  8550. engine.unbindInstanceAttributes();
  8551. }
  8552. else {
  8553. canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);
  8554. for (var i = context.partDataStartIndex; i < context.partDataEndIndex; i++) {
  8555. this.setupUniforms(effect, partIndex, pid._partData, i);
  8556. engine.draw(true, 0, this.borderIndicesCount);
  8557. }
  8558. }
  8559. }
  8560. engine.setAlphaMode(curAlphaMode, true);
  8561. if (this.effectFill && this.effectBorder) {
  8562. engine.setDepthFunction(depthFunction);
  8563. }
  8564. return true;
  8565. };
  8566. Rectangle2DRenderCache.prototype.dispose = function () {
  8567. if (!_super.prototype.dispose.call(this)) {
  8568. return false;
  8569. }
  8570. if (this.fillVB) {
  8571. this._engine._releaseBuffer(this.fillVB);
  8572. this.fillVB = null;
  8573. }
  8574. if (this.fillIB) {
  8575. this._engine._releaseBuffer(this.fillIB);
  8576. this.fillIB = null;
  8577. }
  8578. this.effectFill = null;
  8579. this.effectFillInstanced = null;
  8580. this.effectBorder = null;
  8581. this.effectBorderInstanced = null;
  8582. if (this.borderVB) {
  8583. this._engine._releaseBuffer(this.borderVB);
  8584. this.borderVB = null;
  8585. }
  8586. if (this.borderIB) {
  8587. this._engine._releaseBuffer(this.borderIB);
  8588. this.borderIB = null;
  8589. }
  8590. return true;
  8591. };
  8592. return Rectangle2DRenderCache;
  8593. }(BABYLON.ModelRenderCache));
  8594. BABYLON.Rectangle2DRenderCache = Rectangle2DRenderCache;
  8595. var Rectangle2DInstanceData = (function (_super) {
  8596. __extends(Rectangle2DInstanceData, _super);
  8597. function Rectangle2DInstanceData(partId) {
  8598. _super.call(this, partId, 1);
  8599. }
  8600. Object.defineProperty(Rectangle2DInstanceData.prototype, "properties", {
  8601. get: function () {
  8602. return null;
  8603. },
  8604. set: function (value) {
  8605. },
  8606. enumerable: true,
  8607. configurable: true
  8608. });
  8609. __decorate([
  8610. BABYLON.instanceData()
  8611. ], Rectangle2DInstanceData.prototype, "properties", null);
  8612. return Rectangle2DInstanceData;
  8613. }(BABYLON.Shape2DInstanceData));
  8614. BABYLON.Rectangle2DInstanceData = Rectangle2DInstanceData;
  8615. var Rectangle2D = (function (_super) {
  8616. __extends(Rectangle2D, _super);
  8617. /**
  8618. * Create an Rectangle 2D Shape primitive. May be a sharp rectangle (with sharp corners), or a rounded one.
  8619. * @param settings a combination of settings, possible ones are
  8620. * - parent: the parent primitive/canvas, must be specified if the primitive is not constructed as a child of another one (i.e. as part of the children array setting)
  8621. * - children: an array of direct children
  8622. * - id a text identifier, for information purpose
  8623. * - position: the X & Y positions relative to its parent. Alternatively the x and y settings can be set. Default is [0;0]
  8624. * - rotation: the initial rotation (in radian) of the primitive. default is 0
  8625. * - scale: the initial scale of the primitive. default is 1. You can alternatively use scaleX &| scaleY to apply non uniform scale
  8626. * - dontInheritParentScale: if set the parent's scale won't be taken into consideration to compute the actualScale property
  8627. * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
  8628. * - zOrder: override the zOrder with the specified value
  8629. * - origin: define the normalized origin point location, default [0.5;0.5]
  8630. * - size: the size of the group. Alternatively the width and height settings can be set. Default will be [10;10].
  8631. * - roundRadius: if the rectangle has rounded corner, set their radius, default is 0 (to get a sharp edges rectangle).
  8632. * - fill: the brush used to draw the fill content of the rectangle, you can set null to draw nothing (but you will have to set a border brush), default is a SolidColorBrush of plain white. can also be a string value (see Canvas2D.GetBrushFromString)
  8633. * - border: the brush used to draw the border of the rectangle, you can set null to draw nothing (but you will have to set a fill brush), default is null. can also be a string value (see Canvas2D.GetBrushFromString)
  8634. * - borderThickness: the thickness of the drawn border, default is 1.
  8635. * - isVisible: true if the primitive must be visible, false for hidden. Default is true.
  8636. * - isPickable: if true the Primitive can be used with interaction mode and will issue Pointer Event. If false it will be ignored for interaction/intersection test. Default value is true.
  8637. * - isContainer: if true the Primitive acts as a container for interaction, if the primitive is not pickable or doesn't intersection, no further test will be perform on its children. If set to false, children will always be considered for intersection/interaction. Default value is true.
  8638. * - childrenFlatZOrder: if true all the children (direct and indirect) will share the same Z-Order. Use this when there's a lot of children which don't overlap. The drawing order IS NOT GUARANTED!
  8639. * - marginTop: top margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  8640. * - marginLeft: left margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  8641. * - marginRight: right margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  8642. * - marginBottom: bottom margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  8643. * - margin: top, left, right and bottom margin formatted as a single string (see PrimitiveThickness.fromString)
  8644. * - marginHAlignment: one value of the PrimitiveAlignment type's static properties
  8645. * - marginVAlignment: one value of the PrimitiveAlignment type's static properties
  8646. * - marginAlignment: a string defining the alignment, see PrimitiveAlignment.fromString
  8647. * - paddingTop: top padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  8648. * - paddingLeft: left padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  8649. * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  8650. * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  8651. * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
  8652. */
  8653. function Rectangle2D(settings) {
  8654. // Avoid checking every time if the object exists
  8655. if (settings == null) {
  8656. settings = {};
  8657. }
  8658. _super.call(this, settings);
  8659. if (settings.size != null) {
  8660. this.size = settings.size;
  8661. }
  8662. else if (settings.width || settings.height) {
  8663. var size = new BABYLON.Size(settings.width, settings.height);
  8664. this.size = size;
  8665. }
  8666. //let size = settings.size || (new Size((settings.width === null) ? null : (settings.width || 10), (settings.height === null) ? null : (settings.height || 10)));
  8667. var roundRadius = (settings.roundRadius == null) ? 0 : settings.roundRadius;
  8668. var borderThickness = (settings.borderThickness == null) ? 1 : settings.borderThickness;
  8669. //this.size = size;
  8670. this.roundRadius = roundRadius;
  8671. this.borderThickness = borderThickness;
  8672. }
  8673. Object.defineProperty(Rectangle2D.prototype, "actualSize", {
  8674. get: function () {
  8675. if (this._actualSize) {
  8676. return this._actualSize;
  8677. }
  8678. return this.size;
  8679. },
  8680. set: function (value) {
  8681. this._actualSize = value;
  8682. },
  8683. enumerable: true,
  8684. configurable: true
  8685. });
  8686. Object.defineProperty(Rectangle2D.prototype, "notRounded", {
  8687. get: function () {
  8688. return this._notRounded;
  8689. },
  8690. set: function (value) {
  8691. this._notRounded = value;
  8692. },
  8693. enumerable: true,
  8694. configurable: true
  8695. });
  8696. Object.defineProperty(Rectangle2D.prototype, "roundRadius", {
  8697. get: function () {
  8698. return this._roundRadius;
  8699. },
  8700. set: function (value) {
  8701. this._roundRadius = value;
  8702. this.notRounded = value === 0;
  8703. this._positioningDirty();
  8704. },
  8705. enumerable: true,
  8706. configurable: true
  8707. });
  8708. Rectangle2D.prototype.levelIntersect = function (intersectInfo) {
  8709. // If we got there it mean the boundingInfo intersection succeed, if the rectangle has not roundRadius, it means it succeed!
  8710. if (this.notRounded) {
  8711. return true;
  8712. }
  8713. // If we got so far it means the bounding box at least passed, so we know it's inside the bounding rectangle, but it can be outside the roundedRectangle.
  8714. // The easiest way is to check if the point is inside on of the four corners area (a little square of roundRadius size at the four corners)
  8715. // If it's the case for one, check if the mouse is located in the quarter that we care about (the one who is visible) then finally make a distance check with the roundRadius radius to see if it's inside the circle quarter or outside.
  8716. // First let remove the origin out the equation, to have the rectangle with an origin at bottom/left
  8717. var size = this.size;
  8718. Rectangle2D._i0.x = intersectInfo._localPickPosition.x;
  8719. Rectangle2D._i0.y = intersectInfo._localPickPosition.y;
  8720. var rr = this.roundRadius;
  8721. var rrs = rr * rr;
  8722. // Check if the point is in the bottom/left quarter area
  8723. Rectangle2D._i1.x = rr;
  8724. Rectangle2D._i1.y = rr;
  8725. if (Rectangle2D._i0.x <= Rectangle2D._i1.x && Rectangle2D._i0.y <= Rectangle2D._i1.y) {
  8726. // Compute the intersection point in the quarter local space
  8727. Rectangle2D._i2.x = Rectangle2D._i0.x - Rectangle2D._i1.x;
  8728. Rectangle2D._i2.y = Rectangle2D._i0.y - Rectangle2D._i1.y;
  8729. // It's a hit if the squared distance is less/equal to the squared radius of the round circle
  8730. return Rectangle2D._i2.lengthSquared() <= rrs;
  8731. }
  8732. // Check if the point is in the top/left quarter area
  8733. Rectangle2D._i1.x = rr;
  8734. Rectangle2D._i1.y = size.height - rr;
  8735. if (Rectangle2D._i0.x <= Rectangle2D._i1.x && Rectangle2D._i0.y >= Rectangle2D._i1.y) {
  8736. // Compute the intersection point in the quarter local space
  8737. Rectangle2D._i2.x = Rectangle2D._i0.x - Rectangle2D._i1.x;
  8738. Rectangle2D._i2.y = Rectangle2D._i0.y - Rectangle2D._i1.y;
  8739. // It's a hit if the squared distance is less/equal to the squared radius of the round circle
  8740. return Rectangle2D._i2.lengthSquared() <= rrs;
  8741. }
  8742. // Check if the point is in the top/right quarter area
  8743. Rectangle2D._i1.x = size.width - rr;
  8744. Rectangle2D._i1.y = size.height - rr;
  8745. if (Rectangle2D._i0.x >= Rectangle2D._i1.x && Rectangle2D._i0.y >= Rectangle2D._i1.y) {
  8746. // Compute the intersection point in the quarter local space
  8747. Rectangle2D._i2.x = Rectangle2D._i0.x - Rectangle2D._i1.x;
  8748. Rectangle2D._i2.y = Rectangle2D._i0.y - Rectangle2D._i1.y;
  8749. // It's a hit if the squared distance is less/equal to the squared radius of the round circle
  8750. return Rectangle2D._i2.lengthSquared() <= rrs;
  8751. }
  8752. // Check if the point is in the bottom/right quarter area
  8753. Rectangle2D._i1.x = size.width - rr;
  8754. Rectangle2D._i1.y = rr;
  8755. if (Rectangle2D._i0.x >= Rectangle2D._i1.x && Rectangle2D._i0.y <= Rectangle2D._i1.y) {
  8756. // Compute the intersection point in the quarter local space
  8757. Rectangle2D._i2.x = Rectangle2D._i0.x - Rectangle2D._i1.x;
  8758. Rectangle2D._i2.y = Rectangle2D._i0.y - Rectangle2D._i1.y;
  8759. // It's a hit if the squared distance is less/equal to the squared radius of the round circle
  8760. return Rectangle2D._i2.lengthSquared() <= rrs;
  8761. }
  8762. // At any other locations the point is guarantied to be inside
  8763. return true;
  8764. };
  8765. Rectangle2D.prototype.updateLevelBoundingInfo = function () {
  8766. BABYLON.BoundingInfo2D.CreateFromSizeToRef(this.actualSize, this._levelBoundingInfo);
  8767. };
  8768. Rectangle2D.prototype.createModelRenderCache = function (modelKey) {
  8769. var renderCache = new Rectangle2DRenderCache(this.owner.engine, modelKey);
  8770. return renderCache;
  8771. };
  8772. Rectangle2D.prototype.setupModelRenderCache = function (modelRenderCache) {
  8773. var renderCache = modelRenderCache;
  8774. var engine = this.owner.engine;
  8775. // Need to create WebGL resources for fill part?
  8776. if (this.fill) {
  8777. var vbSize = ((this.notRounded ? 1 : Rectangle2D.roundSubdivisions) * 4) + 1;
  8778. var vb = new Float32Array(vbSize);
  8779. for (var i = 0; i < vbSize; i++) {
  8780. vb[i] = i;
  8781. }
  8782. renderCache.fillVB = engine.createVertexBuffer(vb);
  8783. var triCount = vbSize - 1;
  8784. var ib = new Float32Array(triCount * 3);
  8785. for (var i = 0; i < triCount; i++) {
  8786. ib[i * 3 + 0] = 0;
  8787. ib[i * 3 + 2] = i + 1;
  8788. ib[i * 3 + 1] = i + 2;
  8789. }
  8790. ib[triCount * 3 - 2] = 1;
  8791. renderCache.fillIB = engine.createIndexBuffer(ib);
  8792. renderCache.fillIndicesCount = triCount * 3;
  8793. // Get the instanced version of the effect, if the engine does not support it, null is return and we'll only draw on by one
  8794. var ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_FILLPARTID, ["index"], null, true);
  8795. if (ei) {
  8796. renderCache.effectFillInstanced = engine.createEffect("rect2d", ei.attributes, ei.uniforms, [], ei.defines, null);
  8797. }
  8798. // Get the non instanced version
  8799. ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_FILLPARTID, ["index"], null, false);
  8800. renderCache.effectFill = engine.createEffect("rect2d", ei.attributes, ei.uniforms, [], ei.defines, null);
  8801. }
  8802. // Need to create WebGL resource for border part?
  8803. if (this.border) {
  8804. var vbSize = (this.notRounded ? 1 : Rectangle2D.roundSubdivisions) * 4 * 2;
  8805. var vb = new Float32Array(vbSize);
  8806. for (var i = 0; i < vbSize; i++) {
  8807. vb[i] = i;
  8808. }
  8809. renderCache.borderVB = engine.createVertexBuffer(vb);
  8810. var triCount = vbSize;
  8811. var rs = triCount / 2;
  8812. var ib = new Float32Array(triCount * 3);
  8813. for (var i = 0; i < rs; i++) {
  8814. var r0 = i;
  8815. var r1 = (i + 1) % rs;
  8816. ib[i * 6 + 0] = rs + r1;
  8817. ib[i * 6 + 1] = rs + r0;
  8818. ib[i * 6 + 2] = r0;
  8819. ib[i * 6 + 3] = r1;
  8820. ib[i * 6 + 4] = rs + r1;
  8821. ib[i * 6 + 5] = r0;
  8822. }
  8823. renderCache.borderIB = engine.createIndexBuffer(ib);
  8824. renderCache.borderIndicesCount = triCount * 3;
  8825. // Get the instanced version of the effect, if the engine does not support it, null is return and we'll only draw on by one
  8826. var ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, ["index"], null, true);
  8827. if (ei) {
  8828. renderCache.effectBorderInstanced = engine.createEffect("rect2d", ei.attributes, ei.uniforms, [], ei.defines, null);
  8829. }
  8830. // Get the non instanced version
  8831. ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, ["index"], null, false);
  8832. renderCache.effectBorder = engine.createEffect("rect2d", ei.attributes, ei.uniforms, [], ei.defines, null);
  8833. }
  8834. return renderCache;
  8835. };
  8836. // We override this method because if there's a roundRadius set, we will reduce the initial Content Area to make sure the computed area won't intersect with the shape contour. The formula is simple: we shrink the incoming size by the amount of the roundRadius
  8837. Rectangle2D.prototype._getInitialContentAreaToRef = function (primSize, initialContentPosition, initialContentArea) {
  8838. // Fall back to default implementation if there's no round Radius
  8839. if (this._notRounded) {
  8840. _super.prototype._getInitialContentAreaToRef.call(this, primSize, initialContentPosition, initialContentArea);
  8841. }
  8842. else {
  8843. var rr = Math.round((this.roundRadius - (this.roundRadius / Math.sqrt(2))) * 1.3);
  8844. initialContentPosition.x = initialContentPosition.y = rr;
  8845. initialContentArea.width = Math.max(0, primSize.width - (rr * 2));
  8846. initialContentArea.height = Math.max(0, primSize.height - (rr * 2));
  8847. initialContentPosition.z = primSize.width - (initialContentPosition.x + initialContentArea.width);
  8848. initialContentPosition.w = primSize.height - (initialContentPosition.y + initialContentArea.height);
  8849. }
  8850. };
  8851. Rectangle2D.prototype._getActualSizeFromContentToRef = function (primSize, newPrimSize) {
  8852. // Fall back to default implementation if there's no round Radius
  8853. if (this._notRounded) {
  8854. _super.prototype._getActualSizeFromContentToRef.call(this, primSize, newPrimSize);
  8855. }
  8856. else {
  8857. var rr = Math.round((this.roundRadius - (this.roundRadius / Math.sqrt(2))) * 1.3);
  8858. newPrimSize.copyFrom(primSize);
  8859. newPrimSize.width += rr * 2;
  8860. newPrimSize.height += rr * 2;
  8861. }
  8862. };
  8863. Rectangle2D.prototype.createInstanceDataParts = function () {
  8864. var res = new Array();
  8865. if (this.border) {
  8866. res.push(new Rectangle2DInstanceData(BABYLON.Shape2D.SHAPE2D_BORDERPARTID));
  8867. }
  8868. if (this.fill) {
  8869. res.push(new Rectangle2DInstanceData(BABYLON.Shape2D.SHAPE2D_FILLPARTID));
  8870. }
  8871. return res;
  8872. };
  8873. Rectangle2D.prototype.refreshInstanceDataPart = function (part) {
  8874. if (!_super.prototype.refreshInstanceDataPart.call(this, part)) {
  8875. return false;
  8876. }
  8877. if (part.id === BABYLON.Shape2D.SHAPE2D_BORDERPARTID) {
  8878. var d = part;
  8879. var size = this.actualSize;
  8880. var s = this.actualScale;
  8881. d.properties = new BABYLON.Vector3(size.width * s.x, size.height * s.y, this.roundRadius || 0);
  8882. }
  8883. else if (part.id === BABYLON.Shape2D.SHAPE2D_FILLPARTID) {
  8884. var d = part;
  8885. var size = this.actualSize;
  8886. var s = this.actualScale;
  8887. d.properties = new BABYLON.Vector3(size.width * s.x, size.height * s.y, this.roundRadius || 0);
  8888. }
  8889. return true;
  8890. };
  8891. Rectangle2D._i0 = BABYLON.Vector2.Zero();
  8892. Rectangle2D._i1 = BABYLON.Vector2.Zero();
  8893. Rectangle2D._i2 = BABYLON.Vector2.Zero();
  8894. Rectangle2D.roundSubdivisions = 16;
  8895. __decorate([
  8896. BABYLON.instanceLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 1, function (pi) { return Rectangle2D.actualSizeProperty = pi; }, false, true)
  8897. ], Rectangle2D.prototype, "actualSize", null);
  8898. __decorate([
  8899. BABYLON.modelLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 2, function (pi) { return Rectangle2D.notRoundedProperty = pi; })
  8900. ], Rectangle2D.prototype, "notRounded", null);
  8901. __decorate([
  8902. BABYLON.instanceLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 3, function (pi) { return Rectangle2D.roundRadiusProperty = pi; })
  8903. ], Rectangle2D.prototype, "roundRadius", null);
  8904. Rectangle2D = __decorate([
  8905. BABYLON.className("Rectangle2D", "BABYLON")
  8906. ], Rectangle2D);
  8907. return Rectangle2D;
  8908. }(BABYLON.Shape2D));
  8909. BABYLON.Rectangle2D = Rectangle2D;
  8910. })(BABYLON || (BABYLON = {}));
  8911. var BABYLON;
  8912. (function (BABYLON) {
  8913. var Ellipse2DRenderCache = (function (_super) {
  8914. __extends(Ellipse2DRenderCache, _super);
  8915. function Ellipse2DRenderCache(engine, modelKey) {
  8916. _super.call(this, engine, modelKey);
  8917. this.effectsReady = false;
  8918. this.fillVB = null;
  8919. this.fillIB = null;
  8920. this.fillIndicesCount = 0;
  8921. this.instancingFillAttributes = null;
  8922. this.effectFillInstanced = null;
  8923. this.effectFill = null;
  8924. this.borderVB = null;
  8925. this.borderIB = null;
  8926. this.borderIndicesCount = 0;
  8927. this.instancingBorderAttributes = null;
  8928. this.effectBorderInstanced = null;
  8929. this.effectBorder = null;
  8930. }
  8931. Ellipse2DRenderCache.prototype.render = function (instanceInfo, context) {
  8932. // Do nothing if the shader is still loading/preparing
  8933. if (!this.effectsReady) {
  8934. if ((this.effectFill && (!this.effectFill.isReady() || (this.effectFillInstanced && !this.effectFillInstanced.isReady()))) ||
  8935. (this.effectBorder && (!this.effectBorder.isReady() || (this.effectBorderInstanced && !this.effectBorderInstanced.isReady())))) {
  8936. return false;
  8937. }
  8938. this.effectsReady = true;
  8939. }
  8940. var canvas = instanceInfo.owner.owner;
  8941. var engine = canvas.engine;
  8942. var depthFunction = 0;
  8943. if (this.effectFill && this.effectBorder) {
  8944. depthFunction = engine.getDepthFunction();
  8945. engine.setDepthFunctionToLessOrEqual();
  8946. }
  8947. var curAlphaMode = engine.getAlphaMode();
  8948. if (this.effectFill) {
  8949. var partIndex = instanceInfo.partIndexFromId.get(BABYLON.Shape2D.SHAPE2D_FILLPARTID.toString());
  8950. var pid = context.groupInfoPartData[partIndex];
  8951. if (context.renderMode !== BABYLON.Render2DContext.RenderModeOpaque) {
  8952. engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE, true);
  8953. }
  8954. var effect = context.useInstancing ? this.effectFillInstanced : this.effectFill;
  8955. engine.enableEffect(effect);
  8956. engine.bindBuffersDirectly(this.fillVB, this.fillIB, [1], 4, effect);
  8957. if (context.useInstancing) {
  8958. if (!this.instancingFillAttributes) {
  8959. this.instancingFillAttributes = this.loadInstancingAttributes(BABYLON.Shape2D.SHAPE2D_FILLPARTID, effect);
  8960. }
  8961. var glBuffer = context.instancedBuffers ? context.instancedBuffers[partIndex] : pid._partBuffer;
  8962. var count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
  8963. canvas._addDrawCallCount(1, context.renderMode);
  8964. engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingFillAttributes);
  8965. engine.draw(true, 0, this.fillIndicesCount, count);
  8966. engine.unbindInstanceAttributes();
  8967. }
  8968. else {
  8969. canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);
  8970. for (var i = context.partDataStartIndex; i < context.partDataEndIndex; i++) {
  8971. this.setupUniforms(effect, partIndex, pid._partData, i);
  8972. engine.draw(true, 0, this.fillIndicesCount);
  8973. }
  8974. }
  8975. }
  8976. if (this.effectBorder) {
  8977. var partIndex = instanceInfo.partIndexFromId.get(BABYLON.Shape2D.SHAPE2D_BORDERPARTID.toString());
  8978. var pid = context.groupInfoPartData[partIndex];
  8979. if (context.renderMode !== BABYLON.Render2DContext.RenderModeOpaque) {
  8980. engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE, true);
  8981. }
  8982. var effect = context.useInstancing ? this.effectBorderInstanced : this.effectBorder;
  8983. engine.enableEffect(effect);
  8984. engine.bindBuffersDirectly(this.borderVB, this.borderIB, [1], 4, effect);
  8985. if (context.useInstancing) {
  8986. if (!this.instancingBorderAttributes) {
  8987. this.instancingBorderAttributes = this.loadInstancingAttributes(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, effect);
  8988. }
  8989. var glBuffer = context.instancedBuffers ? context.instancedBuffers[partIndex] : pid._partBuffer;
  8990. var count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
  8991. canvas._addDrawCallCount(1, context.renderMode);
  8992. engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingBorderAttributes);
  8993. engine.draw(true, 0, this.borderIndicesCount, count);
  8994. engine.unbindInstanceAttributes();
  8995. }
  8996. else {
  8997. canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);
  8998. for (var i = context.partDataStartIndex; i < context.partDataEndIndex; i++) {
  8999. this.setupUniforms(effect, partIndex, pid._partData, i);
  9000. engine.draw(true, 0, this.borderIndicesCount);
  9001. }
  9002. }
  9003. }
  9004. engine.setAlphaMode(curAlphaMode, true);
  9005. if (this.effectFill && this.effectBorder) {
  9006. engine.setDepthFunction(depthFunction);
  9007. }
  9008. return true;
  9009. };
  9010. Ellipse2DRenderCache.prototype.dispose = function () {
  9011. if (!_super.prototype.dispose.call(this)) {
  9012. return false;
  9013. }
  9014. if (this.fillVB) {
  9015. this._engine._releaseBuffer(this.fillVB);
  9016. this.fillVB = null;
  9017. }
  9018. if (this.fillIB) {
  9019. this._engine._releaseBuffer(this.fillIB);
  9020. this.fillIB = null;
  9021. }
  9022. this.effectFill = null;
  9023. this.effectFillInstanced = null;
  9024. this.effectBorder = null;
  9025. this.effectBorderInstanced = null;
  9026. if (this.borderVB) {
  9027. this._engine._releaseBuffer(this.borderVB);
  9028. this.borderVB = null;
  9029. }
  9030. if (this.borderIB) {
  9031. this._engine._releaseBuffer(this.borderIB);
  9032. this.borderIB = null;
  9033. }
  9034. return true;
  9035. };
  9036. return Ellipse2DRenderCache;
  9037. }(BABYLON.ModelRenderCache));
  9038. BABYLON.Ellipse2DRenderCache = Ellipse2DRenderCache;
  9039. var Ellipse2DInstanceData = (function (_super) {
  9040. __extends(Ellipse2DInstanceData, _super);
  9041. function Ellipse2DInstanceData(partId) {
  9042. _super.call(this, partId, 1);
  9043. }
  9044. Object.defineProperty(Ellipse2DInstanceData.prototype, "properties", {
  9045. get: function () {
  9046. return null;
  9047. },
  9048. set: function (value) {
  9049. },
  9050. enumerable: true,
  9051. configurable: true
  9052. });
  9053. __decorate([
  9054. BABYLON.instanceData()
  9055. ], Ellipse2DInstanceData.prototype, "properties", null);
  9056. return Ellipse2DInstanceData;
  9057. }(BABYLON.Shape2DInstanceData));
  9058. BABYLON.Ellipse2DInstanceData = Ellipse2DInstanceData;
  9059. var Ellipse2D = (function (_super) {
  9060. __extends(Ellipse2D, _super);
  9061. /**
  9062. * Create an Ellipse 2D Shape primitive
  9063. * @param settings a combination of settings, possible ones are
  9064. * - parent: the parent primitive/canvas, must be specified if the primitive is not constructed as a child of another one (i.e. as part of the children array setting)
  9065. * - children: an array of direct children
  9066. * - id: a text identifier, for information purpose
  9067. * - position: the X & Y positions relative to its parent. Alternatively the x and y properties can be set. Default is [0;0]
  9068. * - rotation: the initial rotation (in radian) of the primitive. default is 0
  9069. * - scale: the initial scale of the primitive. default is 1. You can alternatively use scaleX &| scaleY to apply non uniform scale
  9070. * - dontInheritParentScale: if set the parent's scale won't be taken into consideration to compute the actualScale property
  9071. * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
  9072. * - zOrder: override the zOrder with the specified value
  9073. * - origin: define the normalized origin point location, default [0.5;0.5]
  9074. * - size: the size of the group. Alternatively the width and height properties can be set. Default will be [10;10].
  9075. * - subdivision: the number of subdivision to create the ellipse perimeter, default is 64.
  9076. * - fill: the brush used to draw the fill content of the ellipse, you can set null to draw nothing (but you will have to set a border brush), default is a SolidColorBrush of plain white. can also be a string value (see Canvas2D.GetBrushFromString)
  9077. * - border: the brush used to draw the border of the ellipse, you can set null to draw nothing (but you will have to set a fill brush), default is null. can be a string value (see Canvas2D.GetBrushFromString)
  9078. * - borderThickness: the thickness of the drawn border, default is 1.
  9079. * - isVisible: true if the group must be visible, false for hidden. Default is true.
  9080. * - isPickable: if true the Primitive can be used with interaction mode and will issue Pointer Event. If false it will be ignored for interaction/intersection test. Default value is true.
  9081. * - isContainer: if true the Primitive acts as a container for interaction, if the primitive is not pickable or doesn't intersection, no further test will be perform on its children. If set to false, children will always be considered for intersection/interaction. Default value is true.
  9082. * - childrenFlatZOrder: if true all the children (direct and indirect) will share the same Z-Order. Use this when there's a lot of children which don't overlap. The drawing order IS NOT GUARANTED!
  9083. * - marginTop: top margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9084. * - marginLeft: left margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9085. * - marginRight: right margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9086. * - marginBottom: bottom margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9087. * - margin: top, left, right and bottom margin formatted as a single string (see PrimitiveThickness.fromString)
  9088. * - marginHAlignment: one value of the PrimitiveAlignment type's static properties
  9089. * - marginVAlignment: one value of the PrimitiveAlignment type's static properties
  9090. * - marginAlignment: a string defining the alignment, see PrimitiveAlignment.fromString
  9091. * - paddingTop: top padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9092. * - paddingLeft: left padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9093. * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9094. * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9095. * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
  9096. */
  9097. function Ellipse2D(settings) {
  9098. // Avoid checking every time if the object exists
  9099. if (settings == null) {
  9100. settings = {};
  9101. }
  9102. _super.call(this, settings);
  9103. if (settings.size != null) {
  9104. this.size = settings.size;
  9105. }
  9106. else if (settings.width || settings.height) {
  9107. var size = new BABYLON.Size(settings.width, settings.height);
  9108. this.size = size;
  9109. }
  9110. var sub = (settings.subdivisions == null) ? 64 : settings.subdivisions;
  9111. this.subdivisions = sub;
  9112. }
  9113. Object.defineProperty(Ellipse2D.prototype, "actualSize", {
  9114. get: function () {
  9115. if (this._actualSize) {
  9116. return this._actualSize;
  9117. }
  9118. return this.size;
  9119. },
  9120. set: function (value) {
  9121. this._actualSize = value;
  9122. },
  9123. enumerable: true,
  9124. configurable: true
  9125. });
  9126. Object.defineProperty(Ellipse2D.prototype, "subdivisions", {
  9127. get: function () {
  9128. return this._subdivisions;
  9129. },
  9130. set: function (value) {
  9131. this._subdivisions = value;
  9132. },
  9133. enumerable: true,
  9134. configurable: true
  9135. });
  9136. Ellipse2D.prototype.levelIntersect = function (intersectInfo) {
  9137. var w = this.size.width / 2;
  9138. var h = this.size.height / 2;
  9139. var x = intersectInfo._localPickPosition.x - w;
  9140. var y = intersectInfo._localPickPosition.y - h;
  9141. return ((x * x) / (w * w) + (y * y) / (h * h)) <= 1;
  9142. };
  9143. Ellipse2D.prototype.updateLevelBoundingInfo = function () {
  9144. BABYLON.BoundingInfo2D.CreateFromSizeToRef(this.actualSize, this._levelBoundingInfo);
  9145. };
  9146. Ellipse2D.prototype.createModelRenderCache = function (modelKey) {
  9147. var renderCache = new Ellipse2DRenderCache(this.owner.engine, modelKey);
  9148. return renderCache;
  9149. };
  9150. Ellipse2D.prototype.setupModelRenderCache = function (modelRenderCache) {
  9151. var renderCache = modelRenderCache;
  9152. var engine = this.owner.engine;
  9153. // Need to create WebGL resources for fill part?
  9154. if (this.fill) {
  9155. var vbSize = this.subdivisions + 1;
  9156. var vb = new Float32Array(vbSize);
  9157. for (var i = 0; i < vbSize; i++) {
  9158. vb[i] = i;
  9159. }
  9160. renderCache.fillVB = engine.createVertexBuffer(vb);
  9161. var triCount = vbSize - 1;
  9162. var ib = new Float32Array(triCount * 3);
  9163. for (var i = 0; i < triCount; i++) {
  9164. ib[i * 3 + 0] = 0;
  9165. ib[i * 3 + 2] = i + 1;
  9166. ib[i * 3 + 1] = i + 2;
  9167. }
  9168. ib[triCount * 3 - 2] = 1;
  9169. renderCache.fillIB = engine.createIndexBuffer(ib);
  9170. renderCache.fillIndicesCount = triCount * 3;
  9171. // Get the instanced version of the effect, if the engine does not support it, null is return and we'll only draw on by one
  9172. var ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_FILLPARTID, ["index"], null, true);
  9173. if (ei) {
  9174. renderCache.effectFillInstanced = engine.createEffect({ vertex: "ellipse2d", fragment: "ellipse2d" }, ei.attributes, ei.uniforms, [], ei.defines, null);
  9175. }
  9176. // Get the non instanced version
  9177. ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_FILLPARTID, ["index"], null, false);
  9178. renderCache.effectFill = engine.createEffect({ vertex: "ellipse2d", fragment: "ellipse2d" }, ei.attributes, ei.uniforms, [], ei.defines, null);
  9179. }
  9180. // Need to create WebGL resource for border part?
  9181. if (this.border) {
  9182. var vbSize = this.subdivisions * 2;
  9183. var vb = new Float32Array(vbSize);
  9184. for (var i = 0; i < vbSize; i++) {
  9185. vb[i] = i;
  9186. }
  9187. renderCache.borderVB = engine.createVertexBuffer(vb);
  9188. var triCount = vbSize;
  9189. var rs = triCount / 2;
  9190. var ib = new Float32Array(triCount * 3);
  9191. for (var i = 0; i < rs; i++) {
  9192. var r0 = i;
  9193. var r1 = (i + 1) % rs;
  9194. ib[i * 6 + 0] = rs + r1;
  9195. ib[i * 6 + 1] = rs + r0;
  9196. ib[i * 6 + 2] = r0;
  9197. ib[i * 6 + 3] = r1;
  9198. ib[i * 6 + 4] = rs + r1;
  9199. ib[i * 6 + 5] = r0;
  9200. }
  9201. renderCache.borderIB = engine.createIndexBuffer(ib);
  9202. renderCache.borderIndicesCount = (triCount * 3);
  9203. // Get the instanced version of the effect, if the engine does not support it, null is return and we'll only draw on by one
  9204. var ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, ["index"], null, true);
  9205. if (ei) {
  9206. renderCache.effectBorderInstanced = engine.createEffect("ellipse2d", ei.attributes, ei.uniforms, [], ei.defines, null);
  9207. }
  9208. // Get the non instanced version
  9209. ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, ["index"], null, false);
  9210. renderCache.effectBorder = engine.createEffect("ellipse2d", ei.attributes, ei.uniforms, [], ei.defines, null);
  9211. }
  9212. return renderCache;
  9213. };
  9214. Ellipse2D.prototype.createInstanceDataParts = function () {
  9215. var res = new Array();
  9216. if (this.border) {
  9217. res.push(new Ellipse2DInstanceData(BABYLON.Shape2D.SHAPE2D_BORDERPARTID));
  9218. }
  9219. if (this.fill) {
  9220. res.push(new Ellipse2DInstanceData(BABYLON.Shape2D.SHAPE2D_FILLPARTID));
  9221. }
  9222. return res;
  9223. };
  9224. Ellipse2D.prototype.refreshInstanceDataPart = function (part) {
  9225. if (!_super.prototype.refreshInstanceDataPart.call(this, part)) {
  9226. return false;
  9227. }
  9228. if (part.id === BABYLON.Shape2D.SHAPE2D_BORDERPARTID) {
  9229. var d = part;
  9230. var size = this.actualSize;
  9231. var s = this.actualScale;
  9232. d.properties = new BABYLON.Vector3(size.width * s.x, size.height * s.y, this.subdivisions);
  9233. }
  9234. else if (part.id === BABYLON.Shape2D.SHAPE2D_FILLPARTID) {
  9235. var d = part;
  9236. var size = this.actualSize;
  9237. var s = this.actualScale;
  9238. d.properties = new BABYLON.Vector3(size.width * s.x, size.height * s.y, this.subdivisions);
  9239. }
  9240. return true;
  9241. };
  9242. __decorate([
  9243. BABYLON.instanceLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 1, function (pi) { return Ellipse2D.acutalSizeProperty = pi; }, false, true)
  9244. ], Ellipse2D.prototype, "actualSize", null);
  9245. __decorate([
  9246. BABYLON.modelLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 2, function (pi) { return Ellipse2D.subdivisionsProperty = pi; })
  9247. ], Ellipse2D.prototype, "subdivisions", null);
  9248. Ellipse2D = __decorate([
  9249. BABYLON.className("Ellipse2D", "BABYLON")
  9250. ], Ellipse2D);
  9251. return Ellipse2D;
  9252. }(BABYLON.Shape2D));
  9253. BABYLON.Ellipse2D = Ellipse2D;
  9254. })(BABYLON || (BABYLON = {}));
  9255. var BABYLON;
  9256. (function (BABYLON) {
  9257. var Sprite2DRenderCache = (function (_super) {
  9258. __extends(Sprite2DRenderCache, _super);
  9259. function Sprite2DRenderCache() {
  9260. _super.apply(this, arguments);
  9261. this.effectsReady = false;
  9262. this.vb = null;
  9263. this.ib = null;
  9264. this.instancingAttributes = null;
  9265. this.texture = null;
  9266. this.effect = null;
  9267. this.effectInstanced = null;
  9268. }
  9269. Sprite2DRenderCache.prototype.render = function (instanceInfo, context) {
  9270. // Do nothing if the shader is still loading/preparing
  9271. if (!this.effectsReady) {
  9272. if ((this.effect && (!this.effect.isReady() || (this.effectInstanced && !this.effectInstanced.isReady())))) {
  9273. return false;
  9274. }
  9275. this.effectsReady = true;
  9276. }
  9277. // Compute the offset locations of the attributes in the vertex shader that will be mapped to the instance buffer data
  9278. var canvas = instanceInfo.owner.owner;
  9279. var engine = canvas.engine;
  9280. var cur = engine.getAlphaMode();
  9281. var effect = context.useInstancing ? this.effectInstanced : this.effect;
  9282. engine.enableEffect(effect);
  9283. effect.setTexture("diffuseSampler", this.texture);
  9284. engine.bindBuffersDirectly(this.vb, this.ib, [1], 4, effect);
  9285. if (context.renderMode !== BABYLON.Render2DContext.RenderModeOpaque) {
  9286. engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE, true);
  9287. }
  9288. effect.setBool("alphaTest", context.renderMode === BABYLON.Render2DContext.RenderModeAlphaTest);
  9289. var pid = context.groupInfoPartData[0];
  9290. if (context.useInstancing) {
  9291. if (!this.instancingAttributes) {
  9292. this.instancingAttributes = this.loadInstancingAttributes(Sprite2D.SPRITE2D_MAINPARTID, effect);
  9293. }
  9294. var glBuffer = context.instancedBuffers ? context.instancedBuffers[0] : pid._partBuffer;
  9295. var count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
  9296. canvas._addDrawCallCount(1, context.renderMode);
  9297. engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingAttributes);
  9298. engine.draw(true, 0, 6, count);
  9299. engine.unbindInstanceAttributes();
  9300. }
  9301. else {
  9302. canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);
  9303. for (var i = context.partDataStartIndex; i < context.partDataEndIndex; i++) {
  9304. this.setupUniforms(effect, 0, pid._partData, i);
  9305. engine.draw(true, 0, 6);
  9306. }
  9307. }
  9308. engine.setAlphaMode(cur, true);
  9309. return true;
  9310. };
  9311. Sprite2DRenderCache.prototype.dispose = function () {
  9312. if (!_super.prototype.dispose.call(this)) {
  9313. return false;
  9314. }
  9315. if (this.vb) {
  9316. this._engine._releaseBuffer(this.vb);
  9317. this.vb = null;
  9318. }
  9319. if (this.ib) {
  9320. this._engine._releaseBuffer(this.ib);
  9321. this.ib = null;
  9322. }
  9323. //if (this.texture) {
  9324. // this.texture.dispose();
  9325. // this.texture = null;
  9326. //}
  9327. this.effect = null;
  9328. this.effectInstanced = null;
  9329. return true;
  9330. };
  9331. return Sprite2DRenderCache;
  9332. }(BABYLON.ModelRenderCache));
  9333. BABYLON.Sprite2DRenderCache = Sprite2DRenderCache;
  9334. var Sprite2DInstanceData = (function (_super) {
  9335. __extends(Sprite2DInstanceData, _super);
  9336. function Sprite2DInstanceData(partId) {
  9337. _super.call(this, partId, 1);
  9338. }
  9339. Object.defineProperty(Sprite2DInstanceData.prototype, "topLeftUV", {
  9340. get: function () {
  9341. return null;
  9342. },
  9343. set: function (value) {
  9344. },
  9345. enumerable: true,
  9346. configurable: true
  9347. });
  9348. Object.defineProperty(Sprite2DInstanceData.prototype, "sizeUV", {
  9349. get: function () {
  9350. return null;
  9351. },
  9352. set: function (value) {
  9353. },
  9354. enumerable: true,
  9355. configurable: true
  9356. });
  9357. Object.defineProperty(Sprite2DInstanceData.prototype, "scaleFactor", {
  9358. get: function () {
  9359. return null;
  9360. },
  9361. set: function (value) {
  9362. },
  9363. enumerable: true,
  9364. configurable: true
  9365. });
  9366. Object.defineProperty(Sprite2DInstanceData.prototype, "textureSize", {
  9367. get: function () {
  9368. return null;
  9369. },
  9370. set: function (value) {
  9371. },
  9372. enumerable: true,
  9373. configurable: true
  9374. });
  9375. Object.defineProperty(Sprite2DInstanceData.prototype, "properties", {
  9376. // 3 floats being:
  9377. // - x: frame number to display
  9378. // - y: invertY setting
  9379. // - z: alignToPixel setting
  9380. get: function () {
  9381. return null;
  9382. },
  9383. set: function (value) {
  9384. },
  9385. enumerable: true,
  9386. configurable: true
  9387. });
  9388. __decorate([
  9389. BABYLON.instanceData()
  9390. ], Sprite2DInstanceData.prototype, "topLeftUV", null);
  9391. __decorate([
  9392. BABYLON.instanceData()
  9393. ], Sprite2DInstanceData.prototype, "sizeUV", null);
  9394. __decorate([
  9395. BABYLON.instanceData()
  9396. ], Sprite2DInstanceData.prototype, "scaleFactor", null);
  9397. __decorate([
  9398. BABYLON.instanceData()
  9399. ], Sprite2DInstanceData.prototype, "textureSize", null);
  9400. __decorate([
  9401. BABYLON.instanceData()
  9402. ], Sprite2DInstanceData.prototype, "properties", null);
  9403. return Sprite2DInstanceData;
  9404. }(BABYLON.InstanceDataBase));
  9405. BABYLON.Sprite2DInstanceData = Sprite2DInstanceData;
  9406. var Sprite2D = (function (_super) {
  9407. __extends(Sprite2D, _super);
  9408. /**
  9409. * Create an 2D Sprite primitive
  9410. * @param texture the texture that stores the sprite to render
  9411. * @param settings a combination of settings, possible ones are
  9412. * - parent: the parent primitive/canvas, must be specified if the primitive is not constructed as a child of another one (i.e. as part of the children array setting)
  9413. * - children: an array of direct children
  9414. * - id a text identifier, for information purpose
  9415. * - position: the X & Y positions relative to its parent. Alternatively the x and y properties can be set. Default is [0;0]
  9416. * - rotation: the initial rotation (in radian) of the primitive. default is 0
  9417. * - scale: the initial scale of the primitive. default is 1. You can alternatively use scaleX &| scaleY to apply non uniform scale
  9418. * - dontInheritParentScale: if set the parent's scale won't be taken into consideration to compute the actualScale property
  9419. * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
  9420. * - zOrder: override the zOrder with the specified value
  9421. * - origin: define the normalized origin point location, default [0.5;0.5]
  9422. * - spriteSize: the size of the sprite (in pixels), if null the size of the given texture will be used, default is null.
  9423. * - spriteLocation: the location (in pixels) in the texture of the top/left corner of the Sprite to display, default is null (0,0)
  9424. * - spriteScaleFactor: say you want to display a sprite twice as big as its bitmap which is 64,64, you set the spriteSize to 128,128 and have to set the spriteScaleFactory to 0.5,0.5 in order to address only the 64,64 pixels of the bitmaps. Default is 1,1.
  9425. * - invertY: if true the texture Y will be inverted, default is false.
  9426. * - alignToPixel: if true the sprite's texels will be aligned to the rendering viewport pixels, ensuring the best rendering quality but slow animations won't be done as smooth as if you set false. If false a texel could lies between two pixels, being blended by the texture sampling mode you choose, the rendering result won't be as good, but very slow animation will be overall better looking. Default is true: content will be aligned.
  9427. * - isVisible: true if the sprite must be visible, false for hidden. Default is true.
  9428. * - isPickable: if true the Primitive can be used with interaction mode and will issue Pointer Event. If false it will be ignored for interaction/intersection test. Default value is true.
  9429. * - isContainer: if true the Primitive acts as a container for interaction, if the primitive is not pickable or doesn't intersection, no further test will be perform on its children. If set to false, children will always be considered for intersection/interaction. Default value is true.
  9430. * - childrenFlatZOrder: if true all the children (direct and indirect) will share the same Z-Order. Use this when there's a lot of children which don't overlap. The drawing order IS NOT GUARANTED!
  9431. * - marginTop: top margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9432. * - marginLeft: left margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9433. * - marginRight: right margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9434. * - marginBottom: bottom margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9435. * - margin: top, left, right and bottom margin formatted as a single string (see PrimitiveThickness.fromString)
  9436. * - marginHAlignment: one value of the PrimitiveAlignment type's static properties
  9437. * - marginVAlignment: one value of the PrimitiveAlignment type's static properties
  9438. * - marginAlignment: a string defining the alignment, see PrimitiveAlignment.fromString
  9439. * - paddingTop: top padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9440. * - paddingLeft: left padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9441. * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9442. * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9443. * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
  9444. */
  9445. function Sprite2D(texture, settings) {
  9446. var _this = this;
  9447. if (!settings) {
  9448. settings = {};
  9449. }
  9450. _super.call(this, settings);
  9451. this.texture = texture;
  9452. this.texture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
  9453. this.texture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
  9454. this.size = settings.spriteSize;
  9455. this.spriteLocation = settings.spriteLocation || new BABYLON.Vector2(0, 0);
  9456. this.spriteScaleFactor = settings.spriteScaleFactor || new BABYLON.Vector2(1, 1);
  9457. this.spriteFrame = 0;
  9458. this.invertY = (settings.invertY == null) ? false : settings.invertY;
  9459. this.alignToPixel = (settings.alignToPixel == null) ? true : settings.alignToPixel;
  9460. this.useAlphaFromTexture = true;
  9461. if (settings.spriteSize == null || !texture.isReady()) {
  9462. if (texture.isReady()) {
  9463. this.size = texture.getBaseSize();
  9464. }
  9465. else {
  9466. texture.onLoadObservable.add(function () {
  9467. if (settings.spriteSize == null) {
  9468. _this.size = texture.getBaseSize();
  9469. }
  9470. _this._positioningDirty();
  9471. _this._instanceDirtyFlags |= BABYLON.Prim2DBase.originProperty.flagId | Sprite2D.textureProperty.flagId; // To make sure the sprite is issued again for render
  9472. });
  9473. }
  9474. }
  9475. }
  9476. Object.defineProperty(Sprite2D.prototype, "texture", {
  9477. get: function () {
  9478. return this._texture;
  9479. },
  9480. set: function (value) {
  9481. this._texture = value;
  9482. this._oldTextureHasAlpha = this._texture && this.texture.hasAlpha;
  9483. },
  9484. enumerable: true,
  9485. configurable: true
  9486. });
  9487. Object.defineProperty(Sprite2D.prototype, "useAlphaFromTexture", {
  9488. get: function () {
  9489. return this._useAlphaFromTexture;
  9490. },
  9491. set: function (value) {
  9492. if (this._useAlphaFromTexture === value) {
  9493. return;
  9494. }
  9495. this._useAlphaFromTexture = value;
  9496. this._updateRenderMode();
  9497. },
  9498. enumerable: true,
  9499. configurable: true
  9500. });
  9501. Object.defineProperty(Sprite2D.prototype, "actualSize", {
  9502. get: function () {
  9503. if (this._actualSize) {
  9504. return this._actualSize;
  9505. }
  9506. return this.size;
  9507. },
  9508. set: function (value) {
  9509. this._actualSize = value;
  9510. },
  9511. enumerable: true,
  9512. configurable: true
  9513. });
  9514. Object.defineProperty(Sprite2D.prototype, "spriteLocation", {
  9515. get: function () {
  9516. return this._location;
  9517. },
  9518. set: function (value) {
  9519. this._location = value;
  9520. },
  9521. enumerable: true,
  9522. configurable: true
  9523. });
  9524. Object.defineProperty(Sprite2D.prototype, "spriteFrame", {
  9525. get: function () {
  9526. return this._spriteFrame;
  9527. },
  9528. set: function (value) {
  9529. this._spriteFrame = value;
  9530. },
  9531. enumerable: true,
  9532. configurable: true
  9533. });
  9534. Object.defineProperty(Sprite2D.prototype, "invertY", {
  9535. get: function () {
  9536. return this._invertY;
  9537. },
  9538. set: function (value) {
  9539. this._invertY = value;
  9540. },
  9541. enumerable: true,
  9542. configurable: true
  9543. });
  9544. Object.defineProperty(Sprite2D.prototype, "spriteScaleFactor", {
  9545. get: function () {
  9546. return this._spriteScaleFactor;
  9547. },
  9548. set: function (value) {
  9549. this._spriteScaleFactor = value;
  9550. },
  9551. enumerable: true,
  9552. configurable: true
  9553. });
  9554. /**
  9555. * Sets the scale of the sprite using a BABYLON.Size(w,h).
  9556. * Keeps proportion by taking the maximum of the two scale for x and y.
  9557. * @param {Size} size Size(width,height)
  9558. */
  9559. Sprite2D.prototype.scaleToSize = function (size) {
  9560. var baseSize = this.size;
  9561. if (baseSize == null || !this.texture.isReady()) {
  9562. // we're probably at initiation of the scene, size is not set
  9563. if (this.texture.isReady()) {
  9564. baseSize = this.texture.getBaseSize();
  9565. }
  9566. else {
  9567. // the texture is not ready, wait for it to load before calling scaleToSize again
  9568. var thisObject = this;
  9569. this.texture.onLoadObservable.add(function () {
  9570. thisObject.scaleToSize(size);
  9571. });
  9572. return;
  9573. }
  9574. }
  9575. this.scale = Math.max(size.height / baseSize.height, size.width / baseSize.width);
  9576. };
  9577. Object.defineProperty(Sprite2D.prototype, "alignToPixel", {
  9578. /**
  9579. * Get/set if the sprite rendering should be aligned to the target rendering device pixel or not
  9580. */
  9581. get: function () {
  9582. return this._alignToPixel;
  9583. },
  9584. set: function (value) {
  9585. this._alignToPixel = value;
  9586. },
  9587. enumerable: true,
  9588. configurable: true
  9589. });
  9590. Sprite2D.prototype.updateLevelBoundingInfo = function () {
  9591. BABYLON.BoundingInfo2D.CreateFromSizeToRef(this.size, this._levelBoundingInfo);
  9592. };
  9593. /**
  9594. * Get the animatable array (see http://doc.babylonjs.com/tutorials/Animations)
  9595. */
  9596. Sprite2D.prototype.getAnimatables = function () {
  9597. var res = new Array();
  9598. if (this.texture && this.texture.animations && this.texture.animations.length > 0) {
  9599. res.push(this.texture);
  9600. }
  9601. return res;
  9602. };
  9603. Sprite2D.prototype.levelIntersect = function (intersectInfo) {
  9604. // If we've made it so far it means the boundingInfo intersection test succeed, the Sprite2D is shaped the same, so we always return true
  9605. return true;
  9606. };
  9607. Sprite2D._createCachedCanvasSprite = function (owner, texture, size, pos) {
  9608. var sprite = new Sprite2D(texture, { parent: owner, id: "__cachedCanvasSprite__", position: BABYLON.Vector2.Zero(), origin: BABYLON.Vector2.Zero(), spriteSize: size, spriteLocation: pos, alignToPixel: true });
  9609. return sprite;
  9610. };
  9611. Sprite2D.prototype.createModelRenderCache = function (modelKey) {
  9612. var renderCache = new Sprite2DRenderCache(this.owner.engine, modelKey);
  9613. return renderCache;
  9614. };
  9615. Sprite2D.prototype.setupModelRenderCache = function (modelRenderCache) {
  9616. var renderCache = modelRenderCache;
  9617. var engine = this.owner.engine;
  9618. var vb = new Float32Array(4);
  9619. for (var i = 0; i < 4; i++) {
  9620. vb[i] = i;
  9621. }
  9622. renderCache.vb = engine.createVertexBuffer(vb);
  9623. var ib = new Float32Array(6);
  9624. ib[0] = 0;
  9625. ib[1] = 2;
  9626. ib[2] = 1;
  9627. ib[3] = 0;
  9628. ib[4] = 3;
  9629. ib[5] = 2;
  9630. renderCache.ib = engine.createIndexBuffer(ib);
  9631. renderCache.texture = this.texture;
  9632. // Get the instanced version of the effect, if the engine does not support it, null is return and we'll only draw on by one
  9633. var ei = this.getDataPartEffectInfo(Sprite2D.SPRITE2D_MAINPARTID, ["index"], ["alphaTest"], true);
  9634. if (ei) {
  9635. renderCache.effectInstanced = engine.createEffect("sprite2d", ei.attributes, ei.uniforms, ["diffuseSampler"], ei.defines, null);
  9636. }
  9637. ei = this.getDataPartEffectInfo(Sprite2D.SPRITE2D_MAINPARTID, ["index"], ["alphaTest"], false);
  9638. renderCache.effect = engine.createEffect("sprite2d", ei.attributes, ei.uniforms, ["diffuseSampler"], ei.defines, null);
  9639. return renderCache;
  9640. };
  9641. Sprite2D.prototype.createInstanceDataParts = function () {
  9642. return [new Sprite2DInstanceData(Sprite2D.SPRITE2D_MAINPARTID)];
  9643. };
  9644. Sprite2D.prototype.beforeRefreshForLayoutConstruction = function (part) {
  9645. Sprite2D.layoutConstructMode = true;
  9646. };
  9647. // if obj contains something, we restore the _text property
  9648. Sprite2D.prototype.afterRefreshForLayoutConstruction = function (part, obj) {
  9649. Sprite2D.layoutConstructMode = false;
  9650. };
  9651. Sprite2D.prototype.refreshInstanceDataPart = function (part) {
  9652. if (!_super.prototype.refreshInstanceDataPart.call(this, part)) {
  9653. return false;
  9654. }
  9655. if (!this.texture.isReady() && !Sprite2D.layoutConstructMode) {
  9656. return false;
  9657. }
  9658. if (part.id === Sprite2D.SPRITE2D_MAINPARTID) {
  9659. var d = this._instanceDataParts[0];
  9660. if (Sprite2D.layoutConstructMode) {
  9661. d.topLeftUV = BABYLON.Vector2.Zero();
  9662. d.sizeUV = BABYLON.Vector2.Zero();
  9663. d.properties = BABYLON.Vector3.Zero();
  9664. d.textureSize = BABYLON.Vector2.Zero();
  9665. d.scaleFactor = BABYLON.Vector2.Zero();
  9666. }
  9667. else {
  9668. var ts = this.texture.getBaseSize();
  9669. var sl = this.spriteLocation;
  9670. var ss = this.actualSize;
  9671. var ssf = this.spriteScaleFactor;
  9672. d.topLeftUV = new BABYLON.Vector2(sl.x / ts.width, sl.y / ts.height);
  9673. var suv = new BABYLON.Vector2(ss.width / ts.width, ss.height / ts.height);
  9674. d.sizeUV = suv;
  9675. d.scaleFactor = ssf;
  9676. Sprite2D._prop.x = this.spriteFrame;
  9677. Sprite2D._prop.y = this.invertY ? 1 : 0;
  9678. Sprite2D._prop.z = this.alignToPixel ? 1 : 0;
  9679. d.properties = Sprite2D._prop;
  9680. d.textureSize = new BABYLON.Vector2(ts.width, ts.height);
  9681. }
  9682. }
  9683. return true;
  9684. };
  9685. Sprite2D.prototype._mustUpdateInstance = function () {
  9686. var res = this._oldTextureHasAlpha !== (this.texture != null && this.texture.hasAlpha);
  9687. this._oldTextureHasAlpha = this.texture != null && this.texture.hasAlpha;
  9688. if (res) {
  9689. this._updateRenderMode();
  9690. }
  9691. return res;
  9692. };
  9693. Sprite2D.prototype._useTextureAlpha = function () {
  9694. return this.texture != null && this.texture.hasAlpha;
  9695. };
  9696. Sprite2D.prototype._shouldUseAlphaFromTexture = function () {
  9697. return this.texture != null && this.texture.hasAlpha && this.useAlphaFromTexture;
  9698. };
  9699. Sprite2D.SPRITE2D_MAINPARTID = 1;
  9700. Sprite2D._prop = BABYLON.Vector3.Zero();
  9701. Sprite2D.layoutConstructMode = false;
  9702. __decorate([
  9703. BABYLON.modelLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 1, function (pi) { return Sprite2D.textureProperty = pi; })
  9704. ], Sprite2D.prototype, "texture", null);
  9705. __decorate([
  9706. BABYLON.dynamicLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 2, function (pi) { return Sprite2D.useAlphaFromTextureProperty = pi; })
  9707. ], Sprite2D.prototype, "useAlphaFromTexture", null);
  9708. __decorate([
  9709. BABYLON.instanceLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 3, function (pi) { return Sprite2D.actualSizeProperty = pi; }, false, true)
  9710. ], Sprite2D.prototype, "actualSize", null);
  9711. __decorate([
  9712. BABYLON.instanceLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 4, function (pi) { return Sprite2D.spriteLocationProperty = pi; })
  9713. ], Sprite2D.prototype, "spriteLocation", null);
  9714. __decorate([
  9715. BABYLON.instanceLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 5, function (pi) { return Sprite2D.spriteFrameProperty = pi; })
  9716. ], Sprite2D.prototype, "spriteFrame", null);
  9717. __decorate([
  9718. BABYLON.instanceLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 6, function (pi) { return Sprite2D.invertYProperty = pi; })
  9719. ], Sprite2D.prototype, "invertY", null);
  9720. __decorate([
  9721. BABYLON.instanceLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 7, function (pi) { return Sprite2D.spriteScaleFactorProperty = pi; })
  9722. ], Sprite2D.prototype, "spriteScaleFactor", null);
  9723. Sprite2D = __decorate([
  9724. BABYLON.className("Sprite2D", "BABYLON")
  9725. ], Sprite2D);
  9726. return Sprite2D;
  9727. }(BABYLON.RenderablePrim2D));
  9728. BABYLON.Sprite2D = Sprite2D;
  9729. })(BABYLON || (BABYLON = {}));
  9730. var BABYLON;
  9731. (function (BABYLON) {
  9732. var Text2DRenderCache = (function (_super) {
  9733. __extends(Text2DRenderCache, _super);
  9734. function Text2DRenderCache() {
  9735. _super.apply(this, arguments);
  9736. this.effectsReady = false;
  9737. this.vb = null;
  9738. this.ib = null;
  9739. this.instancingAttributes = null;
  9740. this.fontTexture = null;
  9741. this.effect = null;
  9742. this.effectInstanced = null;
  9743. }
  9744. Text2DRenderCache.prototype.render = function (instanceInfo, context) {
  9745. // Do nothing if the shader is still loading/preparing
  9746. if (!this.effectsReady) {
  9747. if ((this.effect && (!this.effect.isReady() || (this.effectInstanced && !this.effectInstanced.isReady())))) {
  9748. return false;
  9749. }
  9750. this.effectsReady = true;
  9751. }
  9752. var canvas = instanceInfo.owner.owner;
  9753. var engine = canvas.engine;
  9754. this.fontTexture.update();
  9755. var effect = context.useInstancing ? this.effectInstanced : this.effect;
  9756. engine.enableEffect(effect);
  9757. effect.setTexture("diffuseSampler", this.fontTexture);
  9758. engine.bindBuffersDirectly(this.vb, this.ib, [1], 4, effect);
  9759. var curAlphaMode = engine.getAlphaMode();
  9760. engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE, true);
  9761. var pid = context.groupInfoPartData[0];
  9762. if (context.useInstancing) {
  9763. if (!this.instancingAttributes) {
  9764. this.instancingAttributes = this.loadInstancingAttributes(Text2D.TEXT2D_MAINPARTID, effect);
  9765. }
  9766. var glBuffer = context.instancedBuffers ? context.instancedBuffers[0] : pid._partBuffer;
  9767. var count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
  9768. canvas._addDrawCallCount(1, context.renderMode);
  9769. engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingAttributes);
  9770. engine.draw(true, 0, 6, count);
  9771. engine.unbindInstanceAttributes();
  9772. }
  9773. else {
  9774. canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);
  9775. for (var i = context.partDataStartIndex; i < context.partDataEndIndex; i++) {
  9776. this.setupUniforms(effect, 0, pid._partData, i);
  9777. engine.draw(true, 0, 6);
  9778. }
  9779. }
  9780. engine.setAlphaMode(curAlphaMode, true);
  9781. return true;
  9782. };
  9783. Text2DRenderCache.prototype.dispose = function () {
  9784. if (!_super.prototype.dispose.call(this)) {
  9785. return false;
  9786. }
  9787. if (this.vb) {
  9788. this._engine._releaseBuffer(this.vb);
  9789. this.vb = null;
  9790. }
  9791. if (this.ib) {
  9792. this._engine._releaseBuffer(this.ib);
  9793. this.ib = null;
  9794. }
  9795. if (this.fontTexture) {
  9796. this.fontTexture.decCachedFontTextureCounter();
  9797. this.fontTexture = null;
  9798. }
  9799. this.effect = null;
  9800. this.effectInstanced = null;
  9801. return true;
  9802. };
  9803. return Text2DRenderCache;
  9804. }(BABYLON.ModelRenderCache));
  9805. BABYLON.Text2DRenderCache = Text2DRenderCache;
  9806. var Text2DInstanceData = (function (_super) {
  9807. __extends(Text2DInstanceData, _super);
  9808. function Text2DInstanceData(partId, dataElementCount) {
  9809. _super.call(this, partId, dataElementCount);
  9810. }
  9811. Object.defineProperty(Text2DInstanceData.prototype, "topLeftUV", {
  9812. get: function () {
  9813. return null;
  9814. },
  9815. set: function (value) {
  9816. },
  9817. enumerable: true,
  9818. configurable: true
  9819. });
  9820. Object.defineProperty(Text2DInstanceData.prototype, "sizeUV", {
  9821. get: function () {
  9822. return null;
  9823. },
  9824. set: function (value) {
  9825. },
  9826. enumerable: true,
  9827. configurable: true
  9828. });
  9829. Object.defineProperty(Text2DInstanceData.prototype, "textureSize", {
  9830. get: function () {
  9831. return null;
  9832. },
  9833. set: function (value) {
  9834. },
  9835. enumerable: true,
  9836. configurable: true
  9837. });
  9838. Object.defineProperty(Text2DInstanceData.prototype, "color", {
  9839. get: function () {
  9840. return null;
  9841. },
  9842. set: function (value) {
  9843. },
  9844. enumerable: true,
  9845. configurable: true
  9846. });
  9847. Object.defineProperty(Text2DInstanceData.prototype, "superSampleFactor", {
  9848. get: function () {
  9849. return null;
  9850. },
  9851. set: function (value) {
  9852. },
  9853. enumerable: true,
  9854. configurable: true
  9855. });
  9856. __decorate([
  9857. BABYLON.instanceData()
  9858. ], Text2DInstanceData.prototype, "topLeftUV", null);
  9859. __decorate([
  9860. BABYLON.instanceData()
  9861. ], Text2DInstanceData.prototype, "sizeUV", null);
  9862. __decorate([
  9863. BABYLON.instanceData()
  9864. ], Text2DInstanceData.prototype, "textureSize", null);
  9865. __decorate([
  9866. BABYLON.instanceData()
  9867. ], Text2DInstanceData.prototype, "color", null);
  9868. __decorate([
  9869. BABYLON.instanceData()
  9870. ], Text2DInstanceData.prototype, "superSampleFactor", null);
  9871. return Text2DInstanceData;
  9872. }(BABYLON.InstanceDataBase));
  9873. BABYLON.Text2DInstanceData = Text2DInstanceData;
  9874. var Text2D = (function (_super) {
  9875. __extends(Text2D, _super);
  9876. /**
  9877. * Create a Text primitive
  9878. * @param text the text to display
  9879. * @param settings a combination of settings, possible ones are
  9880. * - parent: the parent primitive/canvas, must be specified if the primitive is not constructed as a child of another one (i.e. as part of the children array setting)
  9881. * - children: an array of direct children
  9882. * - id a text identifier, for information purpose
  9883. * - position: the X & Y positions relative to its parent. Alternatively the x and y properties can be set. Default is [0;0]
  9884. * - rotation: the initial rotation (in radian) of the primitive. default is 0
  9885. * - scale: the initial scale of the primitive. default is 1. You can alternatively use scaleX &| scaleY to apply non uniform scale
  9886. * - dontInheritParentScale: if set the parent's scale won't be taken into consideration to compute the actualScale property
  9887. * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
  9888. * - zOrder: override the zOrder with the specified value
  9889. * - origin: define the normalized origin point location, default [0.5;0.5]
  9890. * - fontName: the name/size/style of the font to use, following the CSS notation. Default is "12pt Arial".
  9891. * - fontSuperSample: if true the text will be rendered with a superSampled font (the font is twice the given size). Use this settings if the text lies in world space or if it's scaled in.
  9892. * - defaultFontColor: the color by default to apply on each letter of the text to display, default is plain white.
  9893. * - areaSize: the size of the area in which to display the text, default is auto-fit from text content.
  9894. * - tabulationSize: number of space character to insert when a tabulation is encountered, default is 4
  9895. * - isVisible: true if the text must be visible, false for hidden. Default is true.
  9896. * - isPickable: if true the Primitive can be used with interaction mode and will issue Pointer Event. If false it will be ignored for interaction/intersection test. Default value is true.
  9897. * - isContainer: if true the Primitive acts as a container for interaction, if the primitive is not pickable or doesn't intersection, no further test will be perform on its children. If set to false, children will always be considered for intersection/interaction. Default value is true.
  9898. * - childrenFlatZOrder: if true all the children (direct and indirect) will share the same Z-Order. Use this when there's a lot of children which don't overlap. The drawing order IS NOT GUARANTED!
  9899. * - marginTop: top margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9900. * - marginLeft: left margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9901. * - marginRight: right margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9902. * - marginBottom: bottom margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9903. * - margin: top, left, right and bottom margin formatted as a single string (see PrimitiveThickness.fromString)
  9904. * - marginHAlignment: one value of the PrimitiveAlignment type's static properties
  9905. * - marginVAlignment: one value of the PrimitiveAlignment type's static properties
  9906. * - marginAlignment: a string defining the alignment, see PrimitiveAlignment.fromString
  9907. * - paddingTop: top padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9908. * - paddingLeft: left padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9909. * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9910. * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  9911. * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
  9912. */
  9913. function Text2D(text, settings) {
  9914. if (!settings) {
  9915. settings = {};
  9916. }
  9917. _super.call(this, settings);
  9918. this.fontName = (settings.fontName == null) ? "12pt Arial" : settings.fontName;
  9919. this._fontSuperSample = (settings.fontSuperSample != null && settings.fontSuperSample);
  9920. this.defaultFontColor = (settings.defaultFontColor == null) ? new BABYLON.Color4(1, 1, 1, 1) : settings.defaultFontColor;
  9921. this._tabulationSize = (settings.tabulationSize == null) ? 4 : settings.tabulationSize;
  9922. this._textSize = null;
  9923. this.text = text;
  9924. this.size = (settings.size == null) ? null : settings.size;
  9925. this._updateRenderMode();
  9926. }
  9927. Object.defineProperty(Text2D.prototype, "fontName", {
  9928. get: function () {
  9929. return this._fontName;
  9930. },
  9931. set: function (value) {
  9932. if (this._fontName) {
  9933. throw new Error("Font Name change is not supported right now.");
  9934. }
  9935. this._fontName = value;
  9936. },
  9937. enumerable: true,
  9938. configurable: true
  9939. });
  9940. Object.defineProperty(Text2D.prototype, "defaultFontColor", {
  9941. get: function () {
  9942. return this._defaultFontColor;
  9943. },
  9944. set: function (value) {
  9945. this._defaultFontColor = value;
  9946. },
  9947. enumerable: true,
  9948. configurable: true
  9949. });
  9950. Object.defineProperty(Text2D.prototype, "text", {
  9951. get: function () {
  9952. return this._text;
  9953. },
  9954. set: function (value) {
  9955. if (!value) {
  9956. value = "";
  9957. }
  9958. this._text = value;
  9959. this._textSize = null; // A change of text will reset the TextSize which will be recomputed next time it's used
  9960. this._size = null;
  9961. this._updateCharCount();
  9962. // Trigger a textSize to for a sizeChange if necessary, which is needed for layout to recompute
  9963. var s = this.textSize;
  9964. },
  9965. enumerable: true,
  9966. configurable: true
  9967. });
  9968. Object.defineProperty(Text2D.prototype, "size", {
  9969. get: function () {
  9970. if (this._size != null) {
  9971. return this._size;
  9972. }
  9973. return this.textSize;
  9974. },
  9975. set: function (value) {
  9976. this._size = value;
  9977. },
  9978. enumerable: true,
  9979. configurable: true
  9980. });
  9981. Object.defineProperty(Text2D.prototype, "isSizeAuto", {
  9982. get: function () {
  9983. return false;
  9984. },
  9985. enumerable: true,
  9986. configurable: true
  9987. });
  9988. Object.defineProperty(Text2D.prototype, "actualSize", {
  9989. /**
  9990. * Get the actual size of the Text2D primitive
  9991. */
  9992. get: function () {
  9993. if (this._actualSize) {
  9994. return this._actualSize;
  9995. }
  9996. return this.size;
  9997. },
  9998. enumerable: true,
  9999. configurable: true
  10000. });
  10001. Object.defineProperty(Text2D.prototype, "textSize", {
  10002. /**
  10003. * Get the area that bounds the text associated to the primitive
  10004. */
  10005. get: function () {
  10006. if (!this._textSize) {
  10007. if (this.owner && this._text) {
  10008. var newSize = this.fontTexture.measureText(this._text, this._tabulationSize);
  10009. if (!newSize.equals(this._textSize)) {
  10010. this.onPrimitivePropertyDirty(BABYLON.Prim2DBase.sizeProperty.flagId);
  10011. this._positioningDirty();
  10012. }
  10013. this._textSize = newSize;
  10014. }
  10015. else {
  10016. return Text2D.nullSize;
  10017. }
  10018. }
  10019. return this._textSize;
  10020. },
  10021. enumerable: true,
  10022. configurable: true
  10023. });
  10024. Object.defineProperty(Text2D.prototype, "fontTexture", {
  10025. get: function () {
  10026. if (this._fontTexture) {
  10027. return this._fontTexture;
  10028. }
  10029. if (this.fontName == null || this.owner == null || this.owner.scene == null) {
  10030. return null;
  10031. }
  10032. this._fontTexture = BABYLON.FontTexture.GetCachedFontTexture(this.owner.scene, this.fontName, this._fontSuperSample);
  10033. return this._fontTexture;
  10034. },
  10035. enumerable: true,
  10036. configurable: true
  10037. });
  10038. /**
  10039. * Dispose the primitive, remove it from its parent
  10040. */
  10041. Text2D.prototype.dispose = function () {
  10042. if (!_super.prototype.dispose.call(this)) {
  10043. return false;
  10044. }
  10045. if (this._fontTexture) {
  10046. BABYLON.FontTexture.ReleaseCachedFontTexture(this.owner.scene, this.fontName, this._fontSuperSample);
  10047. this._fontTexture = null;
  10048. }
  10049. return true;
  10050. };
  10051. Text2D.prototype.updateLevelBoundingInfo = function () {
  10052. BABYLON.BoundingInfo2D.CreateFromSizeToRef(this.actualSize, this._levelBoundingInfo);
  10053. };
  10054. Text2D.prototype.levelIntersect = function (intersectInfo) {
  10055. // For now I can't do something better that boundingInfo is a hit, detecting an intersection on a particular letter would be possible, but do we really need it? Not for now...
  10056. return true;
  10057. };
  10058. Text2D.prototype.createModelRenderCache = function (modelKey) {
  10059. var renderCache = new Text2DRenderCache(this.owner.engine, modelKey);
  10060. return renderCache;
  10061. };
  10062. Text2D.prototype.setupModelRenderCache = function (modelRenderCache) {
  10063. var renderCache = modelRenderCache;
  10064. var engine = this.owner.engine;
  10065. renderCache.fontTexture = this.fontTexture;
  10066. renderCache.fontTexture.incCachedFontTextureCounter();
  10067. var vb = new Float32Array(4);
  10068. for (var i = 0; i < 4; i++) {
  10069. vb[i] = i;
  10070. }
  10071. renderCache.vb = engine.createVertexBuffer(vb);
  10072. var ib = new Float32Array(6);
  10073. ib[0] = 0;
  10074. ib[1] = 2;
  10075. ib[2] = 1;
  10076. ib[3] = 0;
  10077. ib[4] = 3;
  10078. ib[5] = 2;
  10079. renderCache.ib = engine.createIndexBuffer(ib);
  10080. // Get the instanced version of the effect, if the engine does not support it, null is return and we'll only draw on by one
  10081. var ei = this.getDataPartEffectInfo(Text2D.TEXT2D_MAINPARTID, ["index"], null, true);
  10082. if (ei) {
  10083. renderCache.effectInstanced = engine.createEffect("text2d", ei.attributes, ei.uniforms, ["diffuseSampler"], ei.defines, null);
  10084. }
  10085. ei = this.getDataPartEffectInfo(Text2D.TEXT2D_MAINPARTID, ["index"], null, false);
  10086. renderCache.effect = engine.createEffect("text2d", ei.attributes, ei.uniforms, ["diffuseSampler"], ei.defines, null);
  10087. return renderCache;
  10088. };
  10089. Text2D.prototype.createInstanceDataParts = function () {
  10090. return [new Text2DInstanceData(Text2D.TEXT2D_MAINPARTID, this._charCount)];
  10091. };
  10092. // Looks like a hack!? Yes! Because that's what it is!
  10093. // For the InstanceData layer to compute correctly we need to set all the properties involved, which won't be the case if there's no text
  10094. // This method is called before the layout construction for us to detect this case, set some text and return the initial one to restore it after (there can be some text without char to display, say "\t\n" for instance)
  10095. Text2D.prototype.beforeRefreshForLayoutConstruction = function (part) {
  10096. if (!this._charCount) {
  10097. var curText = this._text;
  10098. this.text = "A";
  10099. return curText;
  10100. }
  10101. };
  10102. // if obj contains something, we restore the _text property
  10103. Text2D.prototype.afterRefreshForLayoutConstruction = function (part, obj) {
  10104. if (obj !== undefined) {
  10105. this.text = obj;
  10106. }
  10107. };
  10108. Text2D.prototype.refreshInstanceDataPart = function (part) {
  10109. if (!_super.prototype.refreshInstanceDataPart.call(this, part)) {
  10110. return false;
  10111. }
  10112. if (part.id === Text2D.TEXT2D_MAINPARTID) {
  10113. var d = part;
  10114. var texture = this.fontTexture;
  10115. var superSampleFactor = texture.isSuperSampled ? 0.5 : 1;
  10116. var ts = texture.getSize();
  10117. var offset = BABYLON.Vector2.Zero();
  10118. var lh = this.fontTexture.lineHeight;
  10119. offset.y = ((this.textSize.height / lh) - 1) * lh; // Origin is bottom, not top, so the offset is starting with a y that is the top location of the text
  10120. var charxpos = 0;
  10121. d.dataElementCount = this._charCount;
  10122. d.curElement = 0;
  10123. for (var _i = 0, _a = this.text; _i < _a.length; _i++) {
  10124. var char = _a[_i];
  10125. // Line feed
  10126. if (char === "\n") {
  10127. offset.x = 0;
  10128. offset.y -= texture.lineHeight;
  10129. }
  10130. // Tabulation ?
  10131. if (char === "\t") {
  10132. var nextPos = charxpos + this._tabulationSize;
  10133. nextPos = nextPos - (nextPos % this._tabulationSize);
  10134. offset.x += (nextPos - charxpos) * texture.spaceWidth;
  10135. charxpos = nextPos;
  10136. continue;
  10137. }
  10138. if (char < " ") {
  10139. continue;
  10140. }
  10141. this.updateInstanceDataPart(d, offset);
  10142. var ci = texture.getChar(char);
  10143. offset.x += ci.charWidth;
  10144. d.topLeftUV = ci.topLeftUV;
  10145. var suv = ci.bottomRightUV.subtract(ci.topLeftUV);
  10146. d.sizeUV = suv;
  10147. d.textureSize = new BABYLON.Vector2(ts.width, ts.height);
  10148. d.color = this.defaultFontColor;
  10149. d.superSampleFactor = superSampleFactor;
  10150. ++d.curElement;
  10151. }
  10152. }
  10153. return true;
  10154. };
  10155. Text2D.prototype._updateCharCount = function () {
  10156. var count = 0;
  10157. for (var _i = 0, _a = this._text; _i < _a.length; _i++) {
  10158. var char = _a[_i];
  10159. if (char === "\r" || char === "\n" || char === "\t" || char < " ") {
  10160. continue;
  10161. }
  10162. ++count;
  10163. }
  10164. this._charCount = count;
  10165. };
  10166. Text2D.prototype._useTextureAlpha = function () {
  10167. return this.fontTexture != null && this.fontTexture.hasAlpha;
  10168. };
  10169. Text2D.prototype._shouldUseAlphaFromTexture = function () {
  10170. return true;
  10171. };
  10172. Text2D.TEXT2D_MAINPARTID = 1;
  10173. __decorate([
  10174. BABYLON.modelLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 1, function (pi) { return Text2D.fontProperty = pi; }, false, true)
  10175. ], Text2D.prototype, "fontName", null);
  10176. __decorate([
  10177. BABYLON.dynamicLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 2, function (pi) { return Text2D.defaultFontColorProperty = pi; })
  10178. ], Text2D.prototype, "defaultFontColor", null);
  10179. __decorate([
  10180. BABYLON.instanceLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 3, function (pi) { return Text2D.textProperty = pi; }, false, true)
  10181. ], Text2D.prototype, "text", null);
  10182. __decorate([
  10183. BABYLON.instanceLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 4, function (pi) { return Text2D.sizeProperty = pi; })
  10184. ], Text2D.prototype, "size", null);
  10185. Text2D = __decorate([
  10186. BABYLON.className("Text2D", "BABYLON")
  10187. ], Text2D);
  10188. return Text2D;
  10189. }(BABYLON.RenderablePrim2D));
  10190. BABYLON.Text2D = Text2D;
  10191. })(BABYLON || (BABYLON = {}));
  10192. var BABYLON;
  10193. (function (BABYLON) {
  10194. var Lines2DRenderCache = (function (_super) {
  10195. __extends(Lines2DRenderCache, _super);
  10196. function Lines2DRenderCache(engine, modelKey) {
  10197. _super.call(this, engine, modelKey);
  10198. this.effectsReady = false;
  10199. this.fillVB = null;
  10200. this.fillIB = null;
  10201. this.fillIndicesCount = 0;
  10202. this.instancingFillAttributes = null;
  10203. this.effectFill = null;
  10204. this.effectFillInstanced = null;
  10205. this.borderVB = null;
  10206. this.borderIB = null;
  10207. this.borderIndicesCount = 0;
  10208. this.instancingBorderAttributes = null;
  10209. this.effectBorder = null;
  10210. this.effectBorderInstanced = null;
  10211. }
  10212. Lines2DRenderCache.prototype.render = function (instanceInfo, context) {
  10213. // Do nothing if the shader is still loading/preparing
  10214. if (!this.effectsReady) {
  10215. if ((this.effectFill && (!this.effectFill.isReady() || (this.effectFillInstanced && !this.effectFillInstanced.isReady()))) ||
  10216. (this.effectBorder && (!this.effectBorder.isReady() || (this.effectBorderInstanced && !this.effectBorderInstanced.isReady())))) {
  10217. return false;
  10218. }
  10219. this.effectsReady = true;
  10220. }
  10221. var canvas = instanceInfo.owner.owner;
  10222. var engine = canvas.engine;
  10223. var depthFunction = 0;
  10224. if (this.effectFill && this.effectBorder) {
  10225. depthFunction = engine.getDepthFunction();
  10226. engine.setDepthFunctionToLessOrEqual();
  10227. }
  10228. var curAlphaMode = engine.getAlphaMode();
  10229. if (this.effectFill) {
  10230. var partIndex = instanceInfo.partIndexFromId.get(BABYLON.Shape2D.SHAPE2D_FILLPARTID.toString());
  10231. var pid = context.groupInfoPartData[partIndex];
  10232. if (context.renderMode !== BABYLON.Render2DContext.RenderModeOpaque) {
  10233. engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE, true);
  10234. }
  10235. var effect = context.useInstancing ? this.effectFillInstanced : this.effectFill;
  10236. engine.enableEffect(effect);
  10237. engine.bindBuffersDirectly(this.fillVB, this.fillIB, [2], 2 * 4, effect);
  10238. if (context.useInstancing) {
  10239. if (!this.instancingFillAttributes) {
  10240. this.instancingFillAttributes = this.loadInstancingAttributes(BABYLON.Shape2D.SHAPE2D_FILLPARTID, effect);
  10241. }
  10242. var glBuffer = context.instancedBuffers ? context.instancedBuffers[partIndex] : pid._partBuffer;
  10243. var count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
  10244. canvas._addDrawCallCount(1, context.renderMode);
  10245. engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingFillAttributes);
  10246. engine.draw(true, 0, this.fillIndicesCount, count);
  10247. engine.unbindInstanceAttributes();
  10248. }
  10249. else {
  10250. canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);
  10251. for (var i = context.partDataStartIndex; i < context.partDataEndIndex; i++) {
  10252. this.setupUniforms(effect, partIndex, pid._partData, i);
  10253. engine.draw(true, 0, this.fillIndicesCount);
  10254. }
  10255. }
  10256. }
  10257. if (this.effectBorder) {
  10258. var partIndex = instanceInfo.partIndexFromId.get(BABYLON.Shape2D.SHAPE2D_BORDERPARTID.toString());
  10259. var pid = context.groupInfoPartData[partIndex];
  10260. if (context.renderMode !== BABYLON.Render2DContext.RenderModeOpaque) {
  10261. engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE, true);
  10262. }
  10263. var effect = context.useInstancing ? this.effectBorderInstanced : this.effectBorder;
  10264. engine.enableEffect(effect);
  10265. engine.bindBuffersDirectly(this.borderVB, this.borderIB, [2], 2 * 4, effect);
  10266. if (context.useInstancing) {
  10267. if (!this.instancingBorderAttributes) {
  10268. this.instancingBorderAttributes = this.loadInstancingAttributes(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, effect);
  10269. }
  10270. var glBuffer = context.instancedBuffers ? context.instancedBuffers[partIndex] : pid._partBuffer;
  10271. var count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
  10272. canvas._addDrawCallCount(1, context.renderMode);
  10273. engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingBorderAttributes);
  10274. engine.draw(true, 0, this.borderIndicesCount, count);
  10275. engine.unbindInstanceAttributes();
  10276. }
  10277. else {
  10278. canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);
  10279. for (var i = context.partDataStartIndex; i < context.partDataEndIndex; i++) {
  10280. this.setupUniforms(effect, partIndex, pid._partData, i);
  10281. engine.draw(true, 0, this.borderIndicesCount);
  10282. }
  10283. }
  10284. }
  10285. engine.setAlphaMode(curAlphaMode, true);
  10286. if (this.effectFill && this.effectBorder) {
  10287. engine.setDepthFunction(depthFunction);
  10288. }
  10289. return true;
  10290. };
  10291. Lines2DRenderCache.prototype.dispose = function () {
  10292. if (!_super.prototype.dispose.call(this)) {
  10293. return false;
  10294. }
  10295. if (this.fillVB) {
  10296. this._engine._releaseBuffer(this.fillVB);
  10297. this.fillVB = null;
  10298. }
  10299. if (this.fillIB) {
  10300. this._engine._releaseBuffer(this.fillIB);
  10301. this.fillIB = null;
  10302. }
  10303. this.effectFill = null;
  10304. this.effectFillInstanced = null;
  10305. this.effectBorder = null;
  10306. this.effectBorderInstanced = null;
  10307. if (this.borderVB) {
  10308. this._engine._releaseBuffer(this.borderVB);
  10309. this.borderVB = null;
  10310. }
  10311. if (this.borderIB) {
  10312. this._engine._releaseBuffer(this.borderIB);
  10313. this.borderIB = null;
  10314. }
  10315. return true;
  10316. };
  10317. return Lines2DRenderCache;
  10318. }(BABYLON.ModelRenderCache));
  10319. BABYLON.Lines2DRenderCache = Lines2DRenderCache;
  10320. var Lines2DInstanceData = (function (_super) {
  10321. __extends(Lines2DInstanceData, _super);
  10322. function Lines2DInstanceData(partId) {
  10323. _super.call(this, partId, 1);
  10324. }
  10325. Object.defineProperty(Lines2DInstanceData.prototype, "boundingMin", {
  10326. get: function () {
  10327. return null;
  10328. },
  10329. set: function (value) {
  10330. },
  10331. enumerable: true,
  10332. configurable: true
  10333. });
  10334. Object.defineProperty(Lines2DInstanceData.prototype, "boundingMax", {
  10335. get: function () {
  10336. return null;
  10337. },
  10338. set: function (value) {
  10339. },
  10340. enumerable: true,
  10341. configurable: true
  10342. });
  10343. __decorate([
  10344. BABYLON.instanceData(BABYLON.Shape2D.SHAPE2D_CATEGORY_FILLGRADIENT)
  10345. ], Lines2DInstanceData.prototype, "boundingMin", null);
  10346. __decorate([
  10347. BABYLON.instanceData(BABYLON.Shape2D.SHAPE2D_CATEGORY_FILLGRADIENT)
  10348. ], Lines2DInstanceData.prototype, "boundingMax", null);
  10349. return Lines2DInstanceData;
  10350. }(BABYLON.Shape2DInstanceData));
  10351. BABYLON.Lines2DInstanceData = Lines2DInstanceData;
  10352. var Lines2D = (function (_super) {
  10353. __extends(Lines2D, _super);
  10354. /**
  10355. * Create an 2D Lines Shape primitive. The defined lines may be opened or closed (see below)
  10356. * @param points an array that describe the points to use to draw the line, must contain at least two entries.
  10357. * @param settings a combination of settings, possible ones are
  10358. * - parent: the parent primitive/canvas, must be specified if the primitive is not constructed as a child of another one (i.e. as part of the children array setting)
  10359. * - children: an array of direct children
  10360. * - id a text identifier, for information purpose
  10361. * - position: the X & Y positions relative to its parent. Alternatively the x and y properties can be set. Default is [0;0]
  10362. * - rotation: the initial rotation (in radian) of the primitive. default is 0
  10363. * - scale: the initial scale of the primitive. default is 1. You can alternatively use scaleX &| scaleY to apply non uniform scale
  10364. * - dontInheritParentScale: if set the parent's scale won't be taken into consideration to compute the actualScale property
  10365. * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
  10366. * - zOrder: override the zOrder with the specified value
  10367. * - origin: define the normalized origin point location, default [0.5;0.5]
  10368. * - fillThickness: the thickness of the fill part of the line, can be null to draw nothing (but a border brush must be given), default is 1.
  10369. * - closed: if false the lines are said to be opened, the first point and the latest DON'T connect. if true the lines are said to be closed, the first and last point will be connected by a line. For instance you can define the 4 points of a rectangle, if you set closed to true a 4 edges rectangle will be drawn. If you set false, only three edges will be drawn, the edge formed by the first and last point won't exist. Default is false.
  10370. * - startCap: Draw a cap of the given type at the start of the first line, you can't define a Cap if the Lines2D is closed. Default is Lines2D.NoCap.
  10371. * - endCap: Draw a cap of the given type at the end of the last line, you can't define a Cap if the Lines2D is closed. Default is Lines2D.NoCap.
  10372. * - fill: the brush used to draw the fill content of the lines, you can set null to draw nothing (but you will have to set a border brush), default is a SolidColorBrush of plain white. can be a string value (see Canvas2D.GetBrushFromString)
  10373. * - border: the brush used to draw the border of the lines, you can set null to draw nothing (but you will have to set a fill brush), default is null. can be a string value (see Canvas2D.GetBrushFromString)
  10374. * - borderThickness: the thickness of the drawn border, default is 1.
  10375. * - isVisible: true if the primitive must be visible, false for hidden. Default is true.
  10376. * - isPickable: if true the Primitive can be used with interaction mode and will issue Pointer Event. If false it will be ignored for interaction/intersection test. Default value is true.
  10377. * - isContainer: if true the Primitive acts as a container for interaction, if the primitive is not pickable or doesn't intersection, no further test will be perform on its children. If set to false, children will always be considered for intersection/interaction. Default value is true.
  10378. * - childrenFlatZOrder: if true all the children (direct and indirect) will share the same Z-Order. Use this when there's a lot of children which don't overlap. The drawing order IS NOT GUARANTED!
  10379. * - marginTop: top margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  10380. * - marginLeft: left margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  10381. * - marginRight: right margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  10382. * - marginBottom: bottom margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  10383. * - margin: top, left, right and bottom margin formatted as a single string (see PrimitiveThickness.fromString)
  10384. * - marginHAlignment: one value of the PrimitiveAlignment type's static properties
  10385. * - marginVAlignment: one value of the PrimitiveAlignment type's static properties
  10386. * - marginAlignment: a string defining the alignment, see PrimitiveAlignment.fromString
  10387. * - paddingTop: top padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  10388. * - paddingLeft: left padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  10389. * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  10390. * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  10391. * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
  10392. */
  10393. function Lines2D(points, settings) {
  10394. if (!settings) {
  10395. settings = {};
  10396. }
  10397. _super.call(this, settings);
  10398. this._fillVB = null;
  10399. this._fillIB = null;
  10400. this._borderVB = null;
  10401. this._borderIB = null;
  10402. this._size = BABYLON.Size.Zero();
  10403. this._boundingMin = null;
  10404. this._boundingMax = null;
  10405. var fillThickness = (settings.fillThickness == null) ? 1 : settings.fillThickness;
  10406. var startCap = (settings.startCap == null) ? 0 : settings.startCap;
  10407. var endCap = (settings.endCap == null) ? 0 : settings.endCap;
  10408. var closed = (settings.closed == null) ? false : settings.closed;
  10409. this.points = points;
  10410. this.fillThickness = fillThickness;
  10411. this.startCap = startCap;
  10412. this.endCap = endCap;
  10413. this.closed = closed;
  10414. }
  10415. Object.defineProperty(Lines2D, "NoCap", {
  10416. /**
  10417. * No Cap to apply on the extremity
  10418. */
  10419. get: function () { return Lines2D._noCap; },
  10420. enumerable: true,
  10421. configurable: true
  10422. });
  10423. Object.defineProperty(Lines2D, "RoundCap", {
  10424. /**
  10425. * A round cap, will use the line thickness as diameter
  10426. */
  10427. get: function () { return Lines2D._roundCap; },
  10428. enumerable: true,
  10429. configurable: true
  10430. });
  10431. Object.defineProperty(Lines2D, "TriangleCap", {
  10432. /**
  10433. * Creates a triangle at the extremity.
  10434. */
  10435. get: function () { return Lines2D._triangleCap; },
  10436. enumerable: true,
  10437. configurable: true
  10438. });
  10439. Object.defineProperty(Lines2D, "SquareAnchorCap", {
  10440. /**
  10441. * Creates a Square anchor at the extremity, the square size is twice the thickness of the line
  10442. */
  10443. get: function () { return Lines2D._squareAnchorCap; },
  10444. enumerable: true,
  10445. configurable: true
  10446. });
  10447. Object.defineProperty(Lines2D, "RoundAnchorCap", {
  10448. /**
  10449. * Creates a round anchor at the extremity, the diameter is twice the thickness of the line
  10450. */
  10451. get: function () { return Lines2D._roundAnchorCap; },
  10452. enumerable: true,
  10453. configurable: true
  10454. });
  10455. Object.defineProperty(Lines2D, "DiamondAnchorCap", {
  10456. /**
  10457. * Creates a diamond anchor at the extremity.
  10458. */
  10459. get: function () { return Lines2D._diamondAnchorCap; },
  10460. enumerable: true,
  10461. configurable: true
  10462. });
  10463. Object.defineProperty(Lines2D, "ArrowCap", {
  10464. /**
  10465. * Creates an arrow anchor at the extremity. the arrow base size is twice the thickness of the line
  10466. */
  10467. get: function () { return Lines2D._arrowCap; },
  10468. enumerable: true,
  10469. configurable: true
  10470. });
  10471. Object.defineProperty(Lines2D.prototype, "points", {
  10472. get: function () {
  10473. return this._points;
  10474. },
  10475. set: function (value) {
  10476. this._points = value;
  10477. this._contour = null;
  10478. this._boundingBoxDirty();
  10479. },
  10480. enumerable: true,
  10481. configurable: true
  10482. });
  10483. Object.defineProperty(Lines2D.prototype, "fillThickness", {
  10484. get: function () {
  10485. return this._fillThickness;
  10486. },
  10487. set: function (value) {
  10488. this._fillThickness = value;
  10489. },
  10490. enumerable: true,
  10491. configurable: true
  10492. });
  10493. Object.defineProperty(Lines2D.prototype, "closed", {
  10494. get: function () {
  10495. return this._closed;
  10496. },
  10497. set: function (value) {
  10498. this._closed = value;
  10499. },
  10500. enumerable: true,
  10501. configurable: true
  10502. });
  10503. Object.defineProperty(Lines2D.prototype, "startCap", {
  10504. get: function () {
  10505. return this._startCap;
  10506. },
  10507. set: function (value) {
  10508. this._startCap = value;
  10509. },
  10510. enumerable: true,
  10511. configurable: true
  10512. });
  10513. Object.defineProperty(Lines2D.prototype, "endCap", {
  10514. get: function () {
  10515. return this._endCap;
  10516. },
  10517. set: function (value) {
  10518. this._endCap = value;
  10519. },
  10520. enumerable: true,
  10521. configurable: true
  10522. });
  10523. Lines2D.prototype.levelIntersect = function (intersectInfo) {
  10524. var _this = this;
  10525. if (this._contour == null) {
  10526. this._computeLines2D();
  10527. }
  10528. var pl = this.points.length;
  10529. var l = this.closed ? pl + 1 : pl;
  10530. var p = intersectInfo._localPickPosition;
  10531. this.transformPointWithOriginToRef(this._contour[0], null, Lines2D._prevA);
  10532. this.transformPointWithOriginToRef(this._contour[1], null, Lines2D._prevB);
  10533. for (var i = 1; i < l; i++) {
  10534. this.transformPointWithOriginToRef(this._contour[(i % pl) * 2 + 0], null, Lines2D._curA);
  10535. this.transformPointWithOriginToRef(this._contour[(i % pl) * 2 + 1], null, Lines2D._curB);
  10536. if (BABYLON.Vector2.PointInTriangle(p, Lines2D._prevA, Lines2D._prevB, Lines2D._curA)) {
  10537. return true;
  10538. }
  10539. if (BABYLON.Vector2.PointInTriangle(p, Lines2D._curA, Lines2D._prevB, Lines2D._curB)) {
  10540. return true;
  10541. }
  10542. Lines2D._prevA.x = Lines2D._curA.x;
  10543. Lines2D._prevA.y = Lines2D._curA.y;
  10544. Lines2D._prevB.x = Lines2D._curB.x;
  10545. Lines2D._prevB.y = Lines2D._curB.y;
  10546. }
  10547. var capIntersect = function (tri, points) {
  10548. var l = tri.length;
  10549. for (var i = 0; i < l; i += 3) {
  10550. Lines2D._curA.x = points[tri[i + 0] * 2 + 0];
  10551. Lines2D._curA.y = points[tri[i + 0] * 2 + 1];
  10552. _this.transformPointWithOriginToRef(Lines2D._curA, null, Lines2D._curB);
  10553. Lines2D._curA.x = points[tri[i + 1] * 2 + 0];
  10554. Lines2D._curA.y = points[tri[i + 1] * 2 + 1];
  10555. _this.transformPointWithOriginToRef(Lines2D._curA, null, Lines2D._prevA);
  10556. Lines2D._curA.x = points[tri[i + 2] * 2 + 0];
  10557. Lines2D._curA.y = points[tri[i + 2] * 2 + 1];
  10558. _this.transformPointWithOriginToRef(Lines2D._curA, null, Lines2D._prevB);
  10559. if (BABYLON.Vector2.PointInTriangle(p, Lines2D._prevA, Lines2D._prevB, Lines2D._curB)) {
  10560. return true;
  10561. }
  10562. }
  10563. return false;
  10564. };
  10565. if (this._startCapTriIndices) {
  10566. if (this._startCapTriIndices && capIntersect(this._startCapTriIndices, this._startCapContour)) {
  10567. return true;
  10568. }
  10569. if (this._endCapTriIndices && capIntersect(this._endCapTriIndices, this._endCapContour)) {
  10570. return true;
  10571. }
  10572. }
  10573. return false;
  10574. };
  10575. Object.defineProperty(Lines2D.prototype, "boundingMin", {
  10576. get: function () {
  10577. if (!this._boundingMin) {
  10578. this._computeLines2D();
  10579. }
  10580. return this._boundingMin;
  10581. },
  10582. enumerable: true,
  10583. configurable: true
  10584. });
  10585. Object.defineProperty(Lines2D.prototype, "boundingMax", {
  10586. get: function () {
  10587. if (!this._boundingMax) {
  10588. this._computeLines2D();
  10589. }
  10590. return this._boundingMax;
  10591. },
  10592. enumerable: true,
  10593. configurable: true
  10594. });
  10595. Lines2D.prototype.getUsedShaderCategories = function (dataPart) {
  10596. var res = _super.prototype.getUsedShaderCategories.call(this, dataPart);
  10597. // Remove the BORDER category, we don't use it in the VertexShader
  10598. var i = res.indexOf(BABYLON.Shape2D.SHAPE2D_CATEGORY_BORDER);
  10599. if (i !== -1) {
  10600. res.splice(i, 1);
  10601. }
  10602. return res;
  10603. };
  10604. Lines2D.prototype.updateLevelBoundingInfo = function () {
  10605. if (!this._boundingMin) {
  10606. this._computeLines2D();
  10607. }
  10608. BABYLON.BoundingInfo2D.CreateFromMinMaxToRef(this._boundingMin.x, this._boundingMax.x, this._boundingMin.y, this._boundingMax.y, this._levelBoundingInfo);
  10609. };
  10610. Lines2D.prototype.createModelRenderCache = function (modelKey) {
  10611. var renderCache = new Lines2DRenderCache(this.owner.engine, modelKey);
  10612. return renderCache;
  10613. };
  10614. ///////////////////////////////////////////////////////////////////////////////////
  10615. // Methods for Lines building
  10616. Lines2D.prototype._perp = function (v, res) {
  10617. res.x = v.y;
  10618. res.y = -v.x;
  10619. };
  10620. ;
  10621. Lines2D.prototype._direction = function (a, b, res) {
  10622. a.subtractToRef(b, res);
  10623. res.normalize();
  10624. };
  10625. Lines2D.prototype._computeMiter = function (tangent, miter, a, b) {
  10626. a.addToRef(b, tangent);
  10627. tangent.normalize();
  10628. miter.x = -tangent.y;
  10629. miter.y = tangent.x;
  10630. Lines2D._miterTps.x = -a.y;
  10631. Lines2D._miterTps.y = a.x;
  10632. return 1 / BABYLON.Vector2.Dot(miter, Lines2D._miterTps);
  10633. };
  10634. Lines2D.prototype._intersect = function (x1, y1, x2, y2, x3, y3, x4, y4) {
  10635. var d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
  10636. if (d === 0)
  10637. return false;
  10638. var xi = ((x3 - x4) * (x1 * y2 - y1 * x2) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d; // Intersection point is xi/yi, just in case...
  10639. //let yi = ((y3 - y4) * (x1 * y2 - y1 * x2) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d; // That's why I left it commented
  10640. if (xi < Math.min(x1, x2) || xi > Math.max(x1, x2))
  10641. return false;
  10642. if (xi < Math.min(x3, x4) || xi > Math.max(x3, x4))
  10643. return false;
  10644. return true;
  10645. };
  10646. Lines2D.prototype._updateMinMax = function (array, offset) {
  10647. if (offset >= array.length) {
  10648. return;
  10649. }
  10650. this._boundingMin.x = Math.min(this._boundingMin.x, array[offset]);
  10651. this._boundingMax.x = Math.max(this._boundingMax.x, array[offset]);
  10652. this._boundingMin.y = Math.min(this._boundingMin.y, array[offset + 1]);
  10653. this._boundingMax.y = Math.max(this._boundingMax.y, array[offset + 1]);
  10654. };
  10655. Lines2D.prototype._store = function (array, contour, index, max, p, n, halfThickness, borderThickness, detectFlip) {
  10656. var borderMode = borderThickness != null && !isNaN(borderThickness);
  10657. var off = index * (borderMode ? 8 : 4);
  10658. // Mandatory because we'll be out of bound in case of closed line, for the very last point (which is a duplicate of the first that we don't store in the vb)
  10659. if (off >= array.length) {
  10660. return;
  10661. }
  10662. // Store start/end normal, we need it for the cap construction
  10663. if (index === 0) {
  10664. this._perp(n, Lines2D._startDir);
  10665. }
  10666. else if (index === max - 1) {
  10667. this._perp(n, Lines2D._endDir);
  10668. Lines2D._endDir.x *= -1;
  10669. Lines2D._endDir.y *= -1;
  10670. }
  10671. var swap = false;
  10672. array[off + 0] = p.x + n.x * halfThickness;
  10673. array[off + 1] = p.y + n.y * halfThickness;
  10674. array[off + 2] = p.x + n.x * -halfThickness;
  10675. array[off + 3] = p.y + n.y * -halfThickness;
  10676. this._updateMinMax(array, off);
  10677. this._updateMinMax(array, off + 2);
  10678. // If an index is given we check if the two segments formed between [index+0;detectFlip+0] and [index+2;detectFlip+2] intersect themselves.
  10679. // It should not be the case, they should be parallel, so if they cross, we switch the order of storage to ensure we'll have parallel lines
  10680. if (detectFlip !== undefined) {
  10681. // Flip if intersect
  10682. var flipOff = detectFlip * (borderMode ? 8 : 4);
  10683. if (this._intersect(array[off + 0], array[off + 1], array[flipOff + 0], array[flipOff + 1], array[off + 2], array[off + 3], array[flipOff + 2], array[flipOff + 3])) {
  10684. swap = true;
  10685. var tps = array[off + 0];
  10686. array[off + 0] = array[off + 2];
  10687. array[off + 2] = tps;
  10688. tps = array[off + 1];
  10689. array[off + 1] = array[off + 3];
  10690. array[off + 3] = tps;
  10691. }
  10692. }
  10693. if (borderMode) {
  10694. var t = halfThickness + borderThickness;
  10695. array[off + 4] = p.x + n.x * (swap ? -t : t);
  10696. array[off + 5] = p.y + n.y * (swap ? -t : t);
  10697. array[off + 6] = p.x + n.x * (swap ? t : -t);
  10698. array[off + 7] = p.y + n.y * (swap ? t : -t);
  10699. this._updateMinMax(array, off + 4);
  10700. this._updateMinMax(array, off + 6);
  10701. }
  10702. if (contour) {
  10703. off += borderMode ? 4 : 0;
  10704. contour.push(new BABYLON.Vector2(array[off + 0], array[off + 1]));
  10705. contour.push(new BABYLON.Vector2(array[off + 2], array[off + 3]));
  10706. }
  10707. };
  10708. Lines2D.prototype._getCapSize = function (type, border) {
  10709. if (border === void 0) { border = false; }
  10710. var sd = Lines2D._roundCapSubDiv;
  10711. // If no array given, we call this to get the size
  10712. var vbsize = 0, ibsize = 0;
  10713. switch (type) {
  10714. case Lines2D.NoCap:
  10715. {
  10716. // If the line is not close and we're computing border, we add the size to generate the edge border
  10717. if (!this.closed && border) {
  10718. vbsize = 4;
  10719. ibsize = 6;
  10720. }
  10721. else {
  10722. vbsize = ibsize = 0;
  10723. }
  10724. break;
  10725. }
  10726. case Lines2D.RoundCap:
  10727. {
  10728. if (border) {
  10729. vbsize = sd;
  10730. ibsize = (sd - 2) * 3;
  10731. }
  10732. else {
  10733. vbsize = (sd / 2) + 1;
  10734. ibsize = (sd / 2) * 3;
  10735. }
  10736. break;
  10737. }
  10738. case Lines2D.ArrowCap:
  10739. {
  10740. if (border) {
  10741. vbsize = 12;
  10742. ibsize = 24;
  10743. }
  10744. else {
  10745. vbsize = 3;
  10746. ibsize = 3;
  10747. }
  10748. break;
  10749. }
  10750. case Lines2D.TriangleCap:
  10751. {
  10752. if (border) {
  10753. vbsize = 6;
  10754. ibsize = 12;
  10755. }
  10756. else {
  10757. vbsize = 3;
  10758. ibsize = 3;
  10759. }
  10760. break;
  10761. }
  10762. case Lines2D.DiamondAnchorCap:
  10763. {
  10764. if (border) {
  10765. vbsize = 10;
  10766. ibsize = 24;
  10767. }
  10768. else {
  10769. vbsize = 5;
  10770. ibsize = 9;
  10771. }
  10772. break;
  10773. }
  10774. case Lines2D.SquareAnchorCap:
  10775. {
  10776. if (border) {
  10777. vbsize = 12;
  10778. ibsize = 30;
  10779. }
  10780. else {
  10781. vbsize = 4;
  10782. ibsize = 6;
  10783. }
  10784. break;
  10785. }
  10786. case Lines2D.RoundAnchorCap:
  10787. {
  10788. if (border) {
  10789. vbsize = sd * 2;
  10790. ibsize = (sd - 1) * 6;
  10791. }
  10792. else {
  10793. vbsize = sd + 1;
  10794. ibsize = (sd + 1) * 3;
  10795. }
  10796. break;
  10797. }
  10798. }
  10799. return { vbsize: vbsize * 2, ibsize: ibsize };
  10800. };
  10801. Lines2D.prototype._storeVertex = function (vb, baseOffset, index, basePos, rotation, vertex, contour) {
  10802. var c = Math.cos(rotation);
  10803. var s = Math.sin(rotation);
  10804. Lines2D._tpsV.x = (c * vertex.x) + (-s * vertex.y) + basePos.x;
  10805. Lines2D._tpsV.y = (s * vertex.x) + (c * vertex.y) + basePos.y;
  10806. var offset = baseOffset + (index * 2);
  10807. vb[offset + 0] = Lines2D._tpsV.x;
  10808. vb[offset + 1] = Lines2D._tpsV.y;
  10809. if (contour) {
  10810. contour.push(Lines2D._tpsV.x);
  10811. contour.push(Lines2D._tpsV.y);
  10812. }
  10813. this._updateMinMax(vb, offset);
  10814. return (baseOffset + index * 2) / 2;
  10815. };
  10816. Lines2D.prototype._storeIndex = function (ib, baseOffset, index, vertexIndex) {
  10817. ib[baseOffset + index] = vertexIndex;
  10818. };
  10819. Lines2D.prototype._buildCap = function (vb, vbi, ib, ibi, pos, thickness, borderThickness, type, capDir, contour) {
  10820. // Compute the transformation from the direction of the cap to build relative to our default orientation [1;0] (our cap are by default pointing toward right, horizontal
  10821. var sd = Lines2D._roundCapSubDiv;
  10822. var dir = new BABYLON.Vector2(1, 0);
  10823. var angle = Math.atan2(capDir.y, capDir.x) - Math.atan2(dir.y, dir.x);
  10824. var ht = thickness / 2;
  10825. var t = thickness;
  10826. var borderMode = borderThickness != null;
  10827. var bt = borderThickness;
  10828. switch (type) {
  10829. case Lines2D.NoCap:
  10830. if (borderMode && !this.closed) {
  10831. var vi = 0;
  10832. var ii = 0;
  10833. var v1 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(0, ht + bt), contour);
  10834. var v2 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(bt, ht + bt), contour);
  10835. var v3 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(bt, -(ht + bt)), contour);
  10836. var v4 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(0, -(ht + bt)), contour);
  10837. this._storeIndex(ib, ibi, ii++, v1);
  10838. this._storeIndex(ib, ibi, ii++, v2);
  10839. this._storeIndex(ib, ibi, ii++, v3);
  10840. this._storeIndex(ib, ibi, ii++, v1);
  10841. this._storeIndex(ib, ibi, ii++, v3);
  10842. this._storeIndex(ib, ibi, ii++, v4);
  10843. }
  10844. break;
  10845. case Lines2D.ArrowCap:
  10846. ht *= 2;
  10847. case Lines2D.TriangleCap:
  10848. {
  10849. if (borderMode) {
  10850. var f = type === Lines2D.TriangleCap ? bt : Math.sqrt(bt * bt * 2);
  10851. var v1 = this._storeVertex(vb, vbi, 0, pos, angle, new BABYLON.Vector2(0, ht), null);
  10852. var v2 = this._storeVertex(vb, vbi, 1, pos, angle, new BABYLON.Vector2(ht, 0), null);
  10853. var v3 = this._storeVertex(vb, vbi, 2, pos, angle, new BABYLON.Vector2(0, -ht), null);
  10854. var v4 = this._storeVertex(vb, vbi, 3, pos, angle, new BABYLON.Vector2(0, ht + f), contour);
  10855. var v5 = this._storeVertex(vb, vbi, 4, pos, angle, new BABYLON.Vector2(ht + f, 0), contour);
  10856. var v6 = this._storeVertex(vb, vbi, 5, pos, angle, new BABYLON.Vector2(0, -(ht + f)), contour);
  10857. var ii = 0;
  10858. this._storeIndex(ib, ibi, ii++, v1);
  10859. this._storeIndex(ib, ibi, ii++, v4);
  10860. this._storeIndex(ib, ibi, ii++, v5);
  10861. this._storeIndex(ib, ibi, ii++, v1);
  10862. this._storeIndex(ib, ibi, ii++, v5);
  10863. this._storeIndex(ib, ibi, ii++, v2);
  10864. this._storeIndex(ib, ibi, ii++, v6);
  10865. this._storeIndex(ib, ibi, ii++, v3);
  10866. this._storeIndex(ib, ibi, ii++, v2);
  10867. this._storeIndex(ib, ibi, ii++, v6);
  10868. this._storeIndex(ib, ibi, ii++, v2);
  10869. this._storeIndex(ib, ibi, ii++, v5);
  10870. if (type === Lines2D.ArrowCap) {
  10871. var rht = thickness / 2;
  10872. var v10 = this._storeVertex(vb, vbi, 9, pos, angle, new BABYLON.Vector2(0, -(rht + bt)), null);
  10873. var v12 = this._storeVertex(vb, vbi, 11, pos, angle, new BABYLON.Vector2(-bt, -(ht + f)), contour);
  10874. var v11 = this._storeVertex(vb, vbi, 10, pos, angle, new BABYLON.Vector2(-bt, -(rht + bt)), contour);
  10875. var v7 = this._storeVertex(vb, vbi, 6, pos, angle, new BABYLON.Vector2(0, rht + bt), null);
  10876. var v8 = this._storeVertex(vb, vbi, 7, pos, angle, new BABYLON.Vector2(-bt, rht + bt), contour);
  10877. var v9 = this._storeVertex(vb, vbi, 8, pos, angle, new BABYLON.Vector2(-bt, ht + f), contour);
  10878. this._storeIndex(ib, ibi, ii++, v7);
  10879. this._storeIndex(ib, ibi, ii++, v8);
  10880. this._storeIndex(ib, ibi, ii++, v9);
  10881. this._storeIndex(ib, ibi, ii++, v7);
  10882. this._storeIndex(ib, ibi, ii++, v9);
  10883. this._storeIndex(ib, ibi, ii++, v4);
  10884. this._storeIndex(ib, ibi, ii++, v10);
  10885. this._storeIndex(ib, ibi, ii++, v12);
  10886. this._storeIndex(ib, ibi, ii++, v11);
  10887. this._storeIndex(ib, ibi, ii++, v10);
  10888. this._storeIndex(ib, ibi, ii++, v6);
  10889. this._storeIndex(ib, ibi, ii++, v12);
  10890. }
  10891. }
  10892. else {
  10893. var v1 = this._storeVertex(vb, vbi, 0, pos, angle, new BABYLON.Vector2(0, ht), contour);
  10894. var v2 = this._storeVertex(vb, vbi, 1, pos, angle, new BABYLON.Vector2(ht, 0), contour);
  10895. var v3 = this._storeVertex(vb, vbi, 2, pos, angle, new BABYLON.Vector2(0, -ht), contour);
  10896. this._storeIndex(ib, ibi, 0, v1);
  10897. this._storeIndex(ib, ibi, 1, v2);
  10898. this._storeIndex(ib, ibi, 2, v3);
  10899. }
  10900. break;
  10901. }
  10902. case Lines2D.RoundCap:
  10903. {
  10904. if (borderMode) {
  10905. var curA = -Math.PI / 2;
  10906. var incA = Math.PI / (sd / 2 - 1);
  10907. var ii = 0;
  10908. for (var i = 0; i < (sd / 2); i++) {
  10909. var v1 = this._storeVertex(vb, vbi, i * 2 + 0, pos, angle, new BABYLON.Vector2(Math.cos(curA) * ht, Math.sin(curA) * ht), null);
  10910. var v2 = this._storeVertex(vb, vbi, i * 2 + 1, pos, angle, new BABYLON.Vector2(Math.cos(curA) * (ht + bt), Math.sin(curA) * (ht + bt)), contour);
  10911. if (i > 0) {
  10912. this._storeIndex(ib, ibi, ii++, v1 - 2);
  10913. this._storeIndex(ib, ibi, ii++, v2 - 2);
  10914. this._storeIndex(ib, ibi, ii++, v2);
  10915. this._storeIndex(ib, ibi, ii++, v1 - 2);
  10916. this._storeIndex(ib, ibi, ii++, v2);
  10917. this._storeIndex(ib, ibi, ii++, v1);
  10918. }
  10919. curA += incA;
  10920. }
  10921. }
  10922. else {
  10923. var c = this._storeVertex(vb, vbi, 0, pos, angle, new BABYLON.Vector2(0, 0), null);
  10924. var curA = -Math.PI / 2;
  10925. var incA = Math.PI / (sd / 2 - 1);
  10926. this._storeVertex(vb, vbi, 1, pos, angle, new BABYLON.Vector2(Math.cos(curA) * ht, Math.sin(curA) * ht), null);
  10927. curA += incA;
  10928. for (var i = 1; i < (sd / 2); i++) {
  10929. var v2 = this._storeVertex(vb, vbi, i + 1, pos, angle, new BABYLON.Vector2(Math.cos(curA) * ht, Math.sin(curA) * ht), contour);
  10930. this._storeIndex(ib, ibi, i * 3 + 0, c);
  10931. this._storeIndex(ib, ibi, i * 3 + 1, v2 - 1);
  10932. this._storeIndex(ib, ibi, i * 3 + 2, v2);
  10933. curA += incA;
  10934. }
  10935. }
  10936. break;
  10937. }
  10938. case Lines2D.SquareAnchorCap:
  10939. {
  10940. var vi = 0;
  10941. var c = borderMode ? null : contour;
  10942. var v1 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(0, t), c);
  10943. var v2 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(t * 2, t), c);
  10944. var v3 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(t * 2, -t), c);
  10945. var v4 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(0, -t), c);
  10946. if (borderMode) {
  10947. var v5 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(0, ht + bt), null);
  10948. var v6 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(-bt, ht + bt), contour);
  10949. var v7 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(-bt, t + bt), contour);
  10950. var v8 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(t * 2 + bt, t + bt), contour);
  10951. var v9 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(t * 2 + bt, -(t + bt)), contour);
  10952. var v10 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(-bt, -(t + bt)), contour);
  10953. var v11 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(-bt, -(ht + bt)), contour);
  10954. var v12 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(0, -(ht + bt)), null);
  10955. var ii = 0;
  10956. this._storeIndex(ib, ibi, ii++, v6);
  10957. this._storeIndex(ib, ibi, ii++, v1);
  10958. this._storeIndex(ib, ibi, ii++, v5);
  10959. this._storeIndex(ib, ibi, ii++, v6);
  10960. this._storeIndex(ib, ibi, ii++, v7);
  10961. this._storeIndex(ib, ibi, ii++, v1);
  10962. this._storeIndex(ib, ibi, ii++, v1);
  10963. this._storeIndex(ib, ibi, ii++, v7);
  10964. this._storeIndex(ib, ibi, ii++, v8);
  10965. this._storeIndex(ib, ibi, ii++, v1);
  10966. this._storeIndex(ib, ibi, ii++, v8);
  10967. this._storeIndex(ib, ibi, ii++, v2);
  10968. this._storeIndex(ib, ibi, ii++, v2);
  10969. this._storeIndex(ib, ibi, ii++, v8);
  10970. this._storeIndex(ib, ibi, ii++, v9);
  10971. this._storeIndex(ib, ibi, ii++, v2);
  10972. this._storeIndex(ib, ibi, ii++, v9);
  10973. this._storeIndex(ib, ibi, ii++, v3);
  10974. this._storeIndex(ib, ibi, ii++, v3);
  10975. this._storeIndex(ib, ibi, ii++, v9);
  10976. this._storeIndex(ib, ibi, ii++, v10);
  10977. this._storeIndex(ib, ibi, ii++, v3);
  10978. this._storeIndex(ib, ibi, ii++, v10);
  10979. this._storeIndex(ib, ibi, ii++, v4);
  10980. this._storeIndex(ib, ibi, ii++, v10);
  10981. this._storeIndex(ib, ibi, ii++, v11);
  10982. this._storeIndex(ib, ibi, ii++, v4);
  10983. this._storeIndex(ib, ibi, ii++, v11);
  10984. this._storeIndex(ib, ibi, ii++, v12);
  10985. this._storeIndex(ib, ibi, ii++, v4);
  10986. }
  10987. else {
  10988. this._storeIndex(ib, ibi, 0, v1);
  10989. this._storeIndex(ib, ibi, 1, v2);
  10990. this._storeIndex(ib, ibi, 2, v3);
  10991. this._storeIndex(ib, ibi, 3, v1);
  10992. this._storeIndex(ib, ibi, 4, v3);
  10993. this._storeIndex(ib, ibi, 5, v4);
  10994. }
  10995. break;
  10996. }
  10997. case Lines2D.RoundAnchorCap:
  10998. {
  10999. var cpos = Math.sqrt(t * t - ht * ht);
  11000. var center = new BABYLON.Vector2(cpos, 0);
  11001. var curA = BABYLON.Tools.ToRadians(-150);
  11002. var incA = BABYLON.Tools.ToRadians(300) / (sd - 1);
  11003. if (borderMode) {
  11004. var ii = 0;
  11005. for (var i = 0; i < sd; i++) {
  11006. var v1 = this._storeVertex(vb, vbi, i * 2 + 0, pos, angle, new BABYLON.Vector2(cpos + Math.cos(curA) * t, Math.sin(curA) * t), null);
  11007. var v2 = this._storeVertex(vb, vbi, i * 2 + 1, pos, angle, new BABYLON.Vector2(cpos + Math.cos(curA) * (t + bt), Math.sin(curA) * (t + bt)), contour);
  11008. if (i > 0) {
  11009. this._storeIndex(ib, ibi, ii++, v1 - 2);
  11010. this._storeIndex(ib, ibi, ii++, v2 - 2);
  11011. this._storeIndex(ib, ibi, ii++, v2);
  11012. this._storeIndex(ib, ibi, ii++, v1 - 2);
  11013. this._storeIndex(ib, ibi, ii++, v2);
  11014. this._storeIndex(ib, ibi, ii++, v1);
  11015. }
  11016. curA += incA;
  11017. }
  11018. }
  11019. else {
  11020. var c = this._storeVertex(vb, vbi, 0, pos, angle, center, null);
  11021. this._storeVertex(vb, vbi, 1, pos, angle, new BABYLON.Vector2(cpos + Math.cos(curA) * t, Math.sin(curA) * t), null);
  11022. curA += incA;
  11023. for (var i = 1; i < sd; i++) {
  11024. var v2 = this._storeVertex(vb, vbi, i + 1, pos, angle, new BABYLON.Vector2(cpos + Math.cos(curA) * t, Math.sin(curA) * t), contour);
  11025. this._storeIndex(ib, ibi, i * 3 + 0, c);
  11026. this._storeIndex(ib, ibi, i * 3 + 1, v2 - 1);
  11027. this._storeIndex(ib, ibi, i * 3 + 2, v2);
  11028. curA += incA;
  11029. }
  11030. this._storeIndex(ib, ibi, sd * 3 + 0, c);
  11031. this._storeIndex(ib, ibi, sd * 3 + 1, c + 1);
  11032. this._storeIndex(ib, ibi, sd * 3 + 2, c + sd);
  11033. }
  11034. break;
  11035. }
  11036. case Lines2D.DiamondAnchorCap:
  11037. {
  11038. var vi = 0;
  11039. var c = borderMode ? null : contour;
  11040. var v1 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(0, ht), c);
  11041. var v2 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(ht, t), c);
  11042. var v3 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(ht * 3, 0), c);
  11043. var v4 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(ht, -t), c);
  11044. var v5 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(0, -ht), c);
  11045. if (borderMode) {
  11046. var f = Math.sqrt(bt * bt * 2);
  11047. var v6 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(-f, ht), contour);
  11048. var v7 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(ht, t + f), contour);
  11049. var v8 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(ht * 3 + f, 0), contour);
  11050. var v9 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(ht, -(t + f)), contour);
  11051. var v10 = this._storeVertex(vb, vbi, vi++, pos, angle, new BABYLON.Vector2(-f, -ht), contour);
  11052. var ii = 0;
  11053. this._storeIndex(ib, ibi, ii++, v6);
  11054. this._storeIndex(ib, ibi, ii++, v7);
  11055. this._storeIndex(ib, ibi, ii++, v1);
  11056. this._storeIndex(ib, ibi, ii++, v1);
  11057. this._storeIndex(ib, ibi, ii++, v7);
  11058. this._storeIndex(ib, ibi, ii++, v2);
  11059. this._storeIndex(ib, ibi, ii++, v2);
  11060. this._storeIndex(ib, ibi, ii++, v7);
  11061. this._storeIndex(ib, ibi, ii++, v8);
  11062. this._storeIndex(ib, ibi, ii++, v2);
  11063. this._storeIndex(ib, ibi, ii++, v8);
  11064. this._storeIndex(ib, ibi, ii++, v3);
  11065. this._storeIndex(ib, ibi, ii++, v3);
  11066. this._storeIndex(ib, ibi, ii++, v8);
  11067. this._storeIndex(ib, ibi, ii++, v9);
  11068. this._storeIndex(ib, ibi, ii++, v3);
  11069. this._storeIndex(ib, ibi, ii++, v9);
  11070. this._storeIndex(ib, ibi, ii++, v4);
  11071. this._storeIndex(ib, ibi, ii++, v4);
  11072. this._storeIndex(ib, ibi, ii++, v9);
  11073. this._storeIndex(ib, ibi, ii++, v10);
  11074. this._storeIndex(ib, ibi, ii++, v4);
  11075. this._storeIndex(ib, ibi, ii++, v10);
  11076. this._storeIndex(ib, ibi, ii++, v5);
  11077. }
  11078. else {
  11079. this._storeIndex(ib, ibi, 0, v1);
  11080. this._storeIndex(ib, ibi, 1, v2);
  11081. this._storeIndex(ib, ibi, 2, v3);
  11082. this._storeIndex(ib, ibi, 3, v1);
  11083. this._storeIndex(ib, ibi, 4, v3);
  11084. this._storeIndex(ib, ibi, 5, v5);
  11085. this._storeIndex(ib, ibi, 6, v5);
  11086. this._storeIndex(ib, ibi, 7, v3);
  11087. this._storeIndex(ib, ibi, 8, v4);
  11088. }
  11089. break;
  11090. }
  11091. }
  11092. return null;
  11093. };
  11094. Lines2D.prototype._buildLine = function (vb, contour, ht, bt) {
  11095. var lineA = BABYLON.Vector2.Zero();
  11096. var lineB = BABYLON.Vector2.Zero();
  11097. var tangent = BABYLON.Vector2.Zero();
  11098. var miter = BABYLON.Vector2.Zero();
  11099. var curNormal = null;
  11100. if (this.closed) {
  11101. this.points.push(this.points[0]);
  11102. }
  11103. var total = this.points.length;
  11104. for (var i = 1; i < total; i++) {
  11105. var last = this.points[i - 1];
  11106. var cur = this.points[i];
  11107. var next = (i < (this.points.length - 1)) ? this.points[i + 1] : null;
  11108. this._direction(cur, last, lineA);
  11109. if (!curNormal) {
  11110. curNormal = BABYLON.Vector2.Zero();
  11111. this._perp(lineA, curNormal);
  11112. }
  11113. if (i === 1) {
  11114. this._store(vb, contour, 0, total, this.points[0], curNormal, ht, bt);
  11115. }
  11116. if (!next) {
  11117. this._perp(lineA, curNormal);
  11118. this._store(vb, contour, i, total, this.points[i], curNormal, ht, bt, i - 1);
  11119. }
  11120. else {
  11121. this._direction(next, cur, lineB);
  11122. var miterLen = this._computeMiter(tangent, miter, lineA, lineB);
  11123. this._store(vb, contour, i, total, this.points[i], miter, miterLen * ht, miterLen * bt, i - 1);
  11124. }
  11125. }
  11126. if (this.points.length > 2 && this.closed) {
  11127. var last2 = this.points[total - 2];
  11128. var cur2 = this.points[0];
  11129. var next2 = this.points[1];
  11130. this._direction(cur2, last2, lineA);
  11131. this._direction(next2, cur2, lineB);
  11132. this._perp(lineA, curNormal);
  11133. var miterLen2 = this._computeMiter(tangent, miter, lineA, lineB);
  11134. this._store(vb, null, 0, total, this.points[0], miter, miterLen2 * ht, miterLen2 * bt, 1);
  11135. // Patch contour
  11136. if (contour) {
  11137. var off = (bt == null) ? 0 : 4;
  11138. contour[0].x = vb[off + 0];
  11139. contour[0].y = vb[off + 1];
  11140. contour[1].x = vb[off + 2];
  11141. contour[1].y = vb[off + 3];
  11142. }
  11143. }
  11144. // Remove the point we added at the beginning
  11145. if (this.closed) {
  11146. this.points.splice(total - 1);
  11147. }
  11148. };
  11149. // Methods for Lines building
  11150. ///////////////////////////////////////////////////////////////////////////////////
  11151. Lines2D.prototype.setupModelRenderCache = function (modelRenderCache) {
  11152. var renderCache = modelRenderCache;
  11153. var engine = this.owner.engine;
  11154. if (this._fillVB === null) {
  11155. this._computeLines2D();
  11156. }
  11157. // Need to create WebGL resources for fill part?
  11158. if (this.fill) {
  11159. renderCache.fillVB = engine.createVertexBuffer(this._fillVB);
  11160. renderCache.fillIB = engine.createIndexBuffer(this._fillIB);
  11161. renderCache.fillIndicesCount = this._fillIB.length;
  11162. // Get the instanced version of the effect, if the engine does not support it, null is return and we'll only draw on by one
  11163. var ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_FILLPARTID, ["position"], null, true);
  11164. if (ei) {
  11165. renderCache.effectFillInstanced = engine.createEffect("lines2d", ei.attributes, ei.uniforms, [], ei.defines, null);
  11166. }
  11167. // Get the non instanced version
  11168. ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_FILLPARTID, ["position"], null, false);
  11169. renderCache.effectFill = engine.createEffect("lines2d", ei.attributes, ei.uniforms, [], ei.defines, null);
  11170. }
  11171. // Need to create WebGL resources for border part?
  11172. if (this.border) {
  11173. renderCache.borderVB = engine.createVertexBuffer(this._borderVB);
  11174. renderCache.borderIB = engine.createIndexBuffer(this._borderIB);
  11175. renderCache.borderIndicesCount = this._borderIB.length;
  11176. // Get the instanced version of the effect, if the engine does not support it, null is return and we'll only draw on by one
  11177. var ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, ["position"], null, true);
  11178. if (ei) {
  11179. renderCache.effectBorderInstanced = engine.createEffect({ vertex: "lines2d", fragment: "lines2d" }, ei.attributes, ei.uniforms, [], ei.defines, null);
  11180. }
  11181. // Get the non instanced version
  11182. ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, ["position"], null, false);
  11183. renderCache.effectBorder = engine.createEffect({ vertex: "lines2d", fragment: "lines2d" }, ei.attributes, ei.uniforms, [], ei.defines, null);
  11184. }
  11185. this._fillVB = null;
  11186. this._fillIB = null;
  11187. this._borderVB = null;
  11188. this._borderIB = null;
  11189. return renderCache;
  11190. };
  11191. Lines2D.prototype._computeLines2D = function () {
  11192. // Init min/max because their being computed here
  11193. this._boundingMin = new BABYLON.Vector2(Number.MAX_VALUE, Number.MAX_VALUE);
  11194. this._boundingMax = new BABYLON.Vector2(Number.MIN_VALUE, Number.MIN_VALUE);
  11195. var contour = new Array();
  11196. var startCapContour = new Array();
  11197. var endCapContour = new Array();
  11198. // Need to create WebGL resources for fill part?
  11199. if (this.fill) {
  11200. var startCapInfo = this._getCapSize(this.startCap);
  11201. var endCapInfo = this._getCapSize(this.endCap);
  11202. var count = this.points.length;
  11203. var vbSize = (count * 2 * 2) + startCapInfo.vbsize + endCapInfo.vbsize;
  11204. this._fillVB = new Float32Array(vbSize);
  11205. var vb = this._fillVB;
  11206. var ht = this.fillThickness / 2;
  11207. var total = this.points.length;
  11208. this._buildLine(vb, this.border ? null : contour, ht);
  11209. var max = total * 2;
  11210. var triCount = (count - (this.closed ? 0 : 1)) * 2;
  11211. this._fillIB = new Float32Array(triCount * 3 + startCapInfo.ibsize + endCapInfo.ibsize);
  11212. var ib = this._fillIB;
  11213. for (var i = 0; i < triCount; i += 2) {
  11214. ib[i * 3 + 0] = i + 0;
  11215. ib[i * 3 + 1] = i + 1;
  11216. ib[i * 3 + 2] = (i + 2) % max;
  11217. ib[i * 3 + 3] = i + 1;
  11218. ib[i * 3 + 4] = (i + 3) % max;
  11219. ib[i * 3 + 5] = (i + 2) % max;
  11220. }
  11221. this._buildCap(vb, count * 2 * 2, ib, triCount * 3, this.points[0], this.fillThickness, null, this.startCap, Lines2D._startDir, this.border ? null : startCapContour);
  11222. this._buildCap(vb, (count * 2 * 2) + startCapInfo.vbsize, ib, (triCount * 3) + startCapInfo.ibsize, this.points[total - 1], this.fillThickness, null, this.endCap, Lines2D._endDir, this.border ? null : startCapContour);
  11223. }
  11224. // Need to create WebGL resources for border part?
  11225. if (this.border) {
  11226. var startCapInfo = this._getCapSize(this.startCap, true);
  11227. var endCapInfo = this._getCapSize(this.endCap, true);
  11228. var count = this.points.length;
  11229. var vbSize = (count * 2 * 2 * 2) + startCapInfo.vbsize + endCapInfo.vbsize;
  11230. this._borderVB = new Float32Array(vbSize);
  11231. var vb = this._borderVB;
  11232. var ht = this.fillThickness / 2;
  11233. var bt = this.borderThickness;
  11234. var total = this.points.length;
  11235. this._buildLine(vb, contour, ht, bt);
  11236. var max = total * 2 * 2;
  11237. var triCount = (count - (this.closed ? 0 : 1)) * 2 * 2;
  11238. this._borderIB = new Float32Array(triCount * 3 + startCapInfo.ibsize + endCapInfo.ibsize);
  11239. var ib = this._borderIB;
  11240. for (var i = 0; i < triCount; i += 4) {
  11241. ib[i * 3 + 0] = i + 0;
  11242. ib[i * 3 + 1] = i + 2;
  11243. ib[i * 3 + 2] = (i + 6) % max;
  11244. ib[i * 3 + 3] = i + 0;
  11245. ib[i * 3 + 4] = (i + 6) % max;
  11246. ib[i * 3 + 5] = (i + 4) % max;
  11247. ib[i * 3 + 6] = i + 3;
  11248. ib[i * 3 + 7] = i + 1;
  11249. ib[i * 3 + 8] = (i + 5) % max;
  11250. ib[i * 3 + 9] = i + 3;
  11251. ib[i * 3 + 10] = (i + 5) % max;
  11252. ib[i * 3 + 11] = (i + 7) % max;
  11253. }
  11254. this._buildCap(vb, count * 2 * 2 * 2, ib, triCount * 3, this.points[0], this.fillThickness, this.borderThickness, this.startCap, Lines2D._startDir, startCapContour);
  11255. this._buildCap(vb, (count * 2 * 2 * 2) + startCapInfo.vbsize, ib, (triCount * 3) + startCapInfo.ibsize, this.points[total - 1], this.fillThickness, this.borderThickness, this.endCap, Lines2D._endDir, endCapContour);
  11256. }
  11257. this._contour = contour;
  11258. if (startCapContour.length > 0) {
  11259. var startCapTri = Earcut.earcut(startCapContour, null, 2);
  11260. this._startCapTriIndices = startCapTri;
  11261. this._startCapContour = startCapContour;
  11262. }
  11263. else {
  11264. this._startCapTriIndices = null;
  11265. this._startCapContour = null;
  11266. }
  11267. if (endCapContour.length > 0) {
  11268. var endCapTri = Earcut.earcut(endCapContour, null, 2);
  11269. this._endCapContour = endCapContour;
  11270. this._endCapTriIndices = endCapTri;
  11271. }
  11272. else {
  11273. this._endCapContour = null;
  11274. this._endCapTriIndices = null;
  11275. }
  11276. var bs = this._boundingMax.subtract(this._boundingMin);
  11277. this._size.width = bs.x;
  11278. this._size.height = bs.y;
  11279. };
  11280. Object.defineProperty(Lines2D.prototype, "size", {
  11281. get: function () {
  11282. if (this._size == null) {
  11283. this._computeLines2D();
  11284. }
  11285. return this._size;
  11286. },
  11287. enumerable: true,
  11288. configurable: true
  11289. });
  11290. Lines2D.prototype.createInstanceDataParts = function () {
  11291. var res = new Array();
  11292. if (this.border) {
  11293. res.push(new Lines2DInstanceData(BABYLON.Shape2D.SHAPE2D_BORDERPARTID));
  11294. }
  11295. if (this.fill) {
  11296. res.push(new Lines2DInstanceData(BABYLON.Shape2D.SHAPE2D_FILLPARTID));
  11297. }
  11298. return res;
  11299. };
  11300. Lines2D.prototype.applyActualScaleOnTransform = function () {
  11301. return true;
  11302. };
  11303. Lines2D.prototype.refreshInstanceDataPart = function (part) {
  11304. if (!_super.prototype.refreshInstanceDataPart.call(this, part)) {
  11305. return false;
  11306. }
  11307. if (part.id === BABYLON.Shape2D.SHAPE2D_BORDERPARTID) {
  11308. var d = part;
  11309. if (this.border instanceof BABYLON.GradientColorBrush2D) {
  11310. d.boundingMin = this.boundingMin;
  11311. d.boundingMax = this.boundingMax;
  11312. }
  11313. }
  11314. else if (part.id === BABYLON.Shape2D.SHAPE2D_FILLPARTID) {
  11315. var d = part;
  11316. if (this.fill instanceof BABYLON.GradientColorBrush2D) {
  11317. d.boundingMin = this.boundingMin;
  11318. d.boundingMax = this.boundingMax;
  11319. }
  11320. }
  11321. return true;
  11322. };
  11323. Lines2D._prevA = BABYLON.Vector2.Zero();
  11324. Lines2D._prevB = BABYLON.Vector2.Zero();
  11325. Lines2D._curA = BABYLON.Vector2.Zero();
  11326. Lines2D._curB = BABYLON.Vector2.Zero();
  11327. Lines2D._miterTps = BABYLON.Vector2.Zero();
  11328. Lines2D._startDir = BABYLON.Vector2.Zero();
  11329. Lines2D._endDir = BABYLON.Vector2.Zero();
  11330. Lines2D._tpsV = BABYLON.Vector2.Zero();
  11331. Lines2D._noCap = 0;
  11332. Lines2D._roundCap = 1;
  11333. Lines2D._triangleCap = 2;
  11334. Lines2D._squareAnchorCap = 3;
  11335. Lines2D._roundAnchorCap = 4;
  11336. Lines2D._diamondAnchorCap = 5;
  11337. Lines2D._arrowCap = 6;
  11338. Lines2D._roundCapSubDiv = 36;
  11339. __decorate([
  11340. BABYLON.modelLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 1, function (pi) { return Lines2D.pointsProperty = pi; })
  11341. ], Lines2D.prototype, "points", null);
  11342. __decorate([
  11343. BABYLON.modelLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 2, function (pi) { return Lines2D.fillThicknessProperty = pi; })
  11344. ], Lines2D.prototype, "fillThickness", null);
  11345. __decorate([
  11346. BABYLON.modelLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 3, function (pi) { return Lines2D.closedProperty = pi; })
  11347. ], Lines2D.prototype, "closed", null);
  11348. __decorate([
  11349. BABYLON.modelLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 4, function (pi) { return Lines2D.startCapProperty = pi; })
  11350. ], Lines2D.prototype, "startCap", null);
  11351. __decorate([
  11352. BABYLON.modelLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 5, function (pi) { return Lines2D.endCapProperty = pi; })
  11353. ], Lines2D.prototype, "endCap", null);
  11354. Lines2D = __decorate([
  11355. BABYLON.className("Lines2D", "BABYLON")
  11356. ], Lines2D);
  11357. return Lines2D;
  11358. }(BABYLON.Shape2D));
  11359. BABYLON.Lines2D = Lines2D;
  11360. })(BABYLON || (BABYLON = {}));
  11361. var BABYLON;
  11362. (function (BABYLON) {
  11363. // This class contains data that lifetime is bounding to the Babylon Engine object
  11364. var Canvas2DEngineBoundData = (function () {
  11365. function Canvas2DEngineBoundData() {
  11366. this._modelCache = new BABYLON.StringDictionary();
  11367. }
  11368. Canvas2DEngineBoundData.prototype.GetOrAddModelCache = function (key, factory) {
  11369. return this._modelCache.getOrAddWithFactory(key, factory);
  11370. };
  11371. Canvas2DEngineBoundData.prototype.DisposeModelRenderCache = function (modelRenderCache) {
  11372. if (!modelRenderCache.isDisposed) {
  11373. return false;
  11374. }
  11375. this._modelCache.remove(modelRenderCache.modelKey);
  11376. return true;
  11377. };
  11378. return Canvas2DEngineBoundData;
  11379. }());
  11380. BABYLON.Canvas2DEngineBoundData = Canvas2DEngineBoundData;
  11381. var Canvas2D = (function (_super) {
  11382. __extends(Canvas2D, _super);
  11383. function Canvas2D(scene, settings) {
  11384. var _this = this;
  11385. _super.call(this, settings);
  11386. /**
  11387. * If you set your own WorldSpaceNode to display the Canvas2D you have to provide your own implementation of this method which computes the local position in the Canvas based on the given 3D World one.
  11388. * Beware that you have to take under consideration the origin in your calculations! Good luck!
  11389. */
  11390. this.worldSpaceToNodeLocal = function (worldPos) {
  11391. var node = _this._worldSpaceNode;
  11392. if (!node) {
  11393. return;
  11394. }
  11395. var mtx = node.getWorldMatrix().clone();
  11396. mtx.invert();
  11397. var v = BABYLON.Vector3.TransformCoordinates(worldPos, mtx);
  11398. var res = new BABYLON.Vector2(v.x, v.y);
  11399. var size = _this.actualSize;
  11400. res.x += size.width * 0.5; // res is centered, make it relative to bottom/left
  11401. res.y += size.height * 0.5;
  11402. return res;
  11403. };
  11404. /**
  11405. * If you use a custom WorldSpaceCanvasNode you have to override this property to update the UV of your object to reflect the changes due to a resizing of the cached bitmap
  11406. */
  11407. this.worldSpaceCacheChanged = function () {
  11408. var plane = _this.worldSpaceCanvasNode;
  11409. var vd = BABYLON.VertexData.ExtractFromMesh(plane); //new VertexData();
  11410. vd.uvs = new Float32Array(8);
  11411. var material = plane.material;
  11412. var tex = _this._renderableData._cacheTexture;
  11413. if (material.diffuseTexture !== tex) {
  11414. material.diffuseTexture = tex;
  11415. tex.hasAlpha = true;
  11416. }
  11417. var nodeuv = _this._renderableData._cacheNodeUVs;
  11418. for (var i = 0; i < 4; i++) {
  11419. vd.uvs[i * 2 + 0] = nodeuv[i].x;
  11420. vd.uvs[i * 2 + 1] = nodeuv[i].y;
  11421. }
  11422. vd.applyToMesh(plane);
  11423. };
  11424. this._notifDebugMode = false;
  11425. this._mapCounter = 0;
  11426. this._drawCallsOpaqueCounter = new BABYLON.PerfCounter();
  11427. this._drawCallsAlphaTestCounter = new BABYLON.PerfCounter();
  11428. this._drawCallsTransparentCounter = new BABYLON.PerfCounter();
  11429. this._groupRenderCounter = new BABYLON.PerfCounter();
  11430. this._updateTransparentDataCounter = new BABYLON.PerfCounter();
  11431. this._cachedGroupRenderCounter = new BABYLON.PerfCounter();
  11432. this._updateCachedStateCounter = new BABYLON.PerfCounter();
  11433. this._updateLayoutCounter = new BABYLON.PerfCounter();
  11434. this._updatePositioningCounter = new BABYLON.PerfCounter();
  11435. this._updateLocalTransformCounter = new BABYLON.PerfCounter();
  11436. this._updateGlobalTransformCounter = new BABYLON.PerfCounter();
  11437. this._boundingInfoRecomputeCounter = new BABYLON.PerfCounter();
  11438. this._uid = null;
  11439. this._cachedCanvasGroup = null;
  11440. this._profileInfoText = null;
  11441. BABYLON.Prim2DBase._isCanvasInit = false;
  11442. if (!settings) {
  11443. settings = {};
  11444. }
  11445. if (this._cachingStrategy !== Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS) {
  11446. this._background = new BABYLON.Rectangle2D({ parent: this, id: "###CANVAS BACKGROUND###", size: settings.size }); //TODO CHECK when size is null
  11447. this._background.zOrder = 1.0;
  11448. this._background.isPickable = false;
  11449. this._background.origin = BABYLON.Vector2.Zero();
  11450. this._background.levelVisible = false;
  11451. if (settings.backgroundRoundRadius != null) {
  11452. this.backgroundRoundRadius = settings.backgroundRoundRadius;
  11453. }
  11454. if (settings.backgroundBorder != null) {
  11455. if (typeof (settings.backgroundBorder) === "string") {
  11456. this.backgroundBorder = Canvas2D.GetBrushFromString(settings.backgroundBorder);
  11457. }
  11458. else {
  11459. this.backgroundBorder = settings.backgroundBorder;
  11460. }
  11461. }
  11462. if (settings.backgroundBorderThickNess != null) {
  11463. this.backgroundBorderThickness = settings.backgroundBorderThickNess;
  11464. }
  11465. if (settings.backgroundFill != null) {
  11466. if (typeof (settings.backgroundFill) === "string") {
  11467. this.backgroundFill = Canvas2D.GetBrushFromString(settings.backgroundFill);
  11468. }
  11469. else {
  11470. this.backgroundFill = settings.backgroundFill;
  11471. }
  11472. }
  11473. // Put a handler to resize the background whenever the canvas is resizing
  11474. this.propertyChanged.add(function (e, s) {
  11475. if (e.propertyName === "size") {
  11476. _this._background.size = _this.size;
  11477. }
  11478. }, BABYLON.Group2D.sizeProperty.flagId);
  11479. this._background._patchHierarchy(this);
  11480. }
  11481. var engine = scene.getEngine();
  11482. this.__engineData = engine.getOrAddExternalDataWithFactory("__BJSCANVAS2D__", function (k) { return new Canvas2DEngineBoundData(); });
  11483. this._primPointerInfo = new BABYLON.PrimitivePointerInfo();
  11484. this._capturedPointers = new BABYLON.StringDictionary();
  11485. this._pickStartingPosition = BABYLON.Vector2.Zero();
  11486. this._hierarchyLevelMaxSiblingCount = 50;
  11487. this._hierarchyDepth = 0;
  11488. this._zOrder = 0;
  11489. this._zMax = 1;
  11490. this._scene = scene;
  11491. this._engine = engine;
  11492. this._renderingSize = new BABYLON.Size(0, 0);
  11493. this._designSize = settings.designSize || null;
  11494. this._designUseHorizAxis = settings.designUseHorizAxis === true;
  11495. this._trackedGroups = new Array();
  11496. this._maxAdaptiveWorldSpaceCanvasSize = null;
  11497. this._groupCacheMaps = new BABYLON.StringDictionary();
  11498. this._changeFlags(BABYLON.SmartPropertyPrim.flagAllow3DEventsBelowCanvas, (settings.allow3DEventBelowCanvas != null) && settings.allow3DEventBelowCanvas);
  11499. this._patchHierarchy(this);
  11500. var enableInteraction = (settings.enableInteraction == null) ? true : settings.enableInteraction;
  11501. this._fitRenderingDevice = !settings.size;
  11502. if (!settings.size) {
  11503. settings.size = new BABYLON.Size(engine.getRenderWidth(), engine.getRenderHeight());
  11504. }
  11505. // Register scene dispose to also dispose the canvas when it'll happens
  11506. scene.onDisposeObservable.add(function (d, s) {
  11507. _this.dispose();
  11508. });
  11509. if (this._isScreenSpace) {
  11510. if (settings.renderingPhase) {
  11511. if (!settings.renderingPhase.camera || settings.renderingPhase.renderingGroupID == null) {
  11512. throw Error("You have to specify a valid camera and renderingGroup");
  11513. }
  11514. this._scene.onRenderingGroupObservable.add(function (e, s) {
  11515. if (_this._scene.activeCamera === settings.renderingPhase.camera) {
  11516. _this._engine.clear(null, false, true, true);
  11517. _this._render();
  11518. }
  11519. }, Math.pow(2, settings.renderingPhase.renderingGroupID));
  11520. }
  11521. else {
  11522. this._afterRenderObserver = this._scene.onAfterRenderObservable.add(function (d, s) {
  11523. _this._engine.clear(null, false, true, true);
  11524. _this._render();
  11525. });
  11526. }
  11527. }
  11528. else {
  11529. this._beforeRenderObserver = this._scene.onBeforeRenderObservable.add(function (d, s) {
  11530. _this._render();
  11531. });
  11532. }
  11533. this._supprtInstancedArray = this._engine.getCaps().instancedArrays !== null;
  11534. //this._supprtInstancedArray = false; // TODO REMOVE!!!
  11535. this._setupInteraction(enableInteraction);
  11536. // Register this instance
  11537. Canvas2D._INSTANCES.push(this);
  11538. }
  11539. Object.defineProperty(Canvas2D.prototype, "drawCallsOpaqueCounter", {
  11540. get: function () {
  11541. return this._drawCallsOpaqueCounter;
  11542. },
  11543. enumerable: true,
  11544. configurable: true
  11545. });
  11546. Object.defineProperty(Canvas2D.prototype, "drawCallsAlphaTestCounter", {
  11547. get: function () {
  11548. return this._drawCallsAlphaTestCounter;
  11549. },
  11550. enumerable: true,
  11551. configurable: true
  11552. });
  11553. Object.defineProperty(Canvas2D.prototype, "drawCallsTransparentCounter", {
  11554. get: function () {
  11555. return this._drawCallsTransparentCounter;
  11556. },
  11557. enumerable: true,
  11558. configurable: true
  11559. });
  11560. Object.defineProperty(Canvas2D.prototype, "groupRenderCounter", {
  11561. get: function () {
  11562. return this._groupRenderCounter;
  11563. },
  11564. enumerable: true,
  11565. configurable: true
  11566. });
  11567. Object.defineProperty(Canvas2D.prototype, "updateTransparentDataCounter", {
  11568. get: function () {
  11569. return this._updateTransparentDataCounter;
  11570. },
  11571. enumerable: true,
  11572. configurable: true
  11573. });
  11574. Object.defineProperty(Canvas2D.prototype, "cachedGroupRenderCounter", {
  11575. get: function () {
  11576. return this._cachedGroupRenderCounter;
  11577. },
  11578. enumerable: true,
  11579. configurable: true
  11580. });
  11581. Object.defineProperty(Canvas2D.prototype, "updateCachedStateCounter", {
  11582. get: function () {
  11583. return this._updateCachedStateCounter;
  11584. },
  11585. enumerable: true,
  11586. configurable: true
  11587. });
  11588. Object.defineProperty(Canvas2D.prototype, "updateLayoutCounter", {
  11589. get: function () {
  11590. return this._updateLayoutCounter;
  11591. },
  11592. enumerable: true,
  11593. configurable: true
  11594. });
  11595. Object.defineProperty(Canvas2D.prototype, "updatePositioningCounter", {
  11596. get: function () {
  11597. return this._updatePositioningCounter;
  11598. },
  11599. enumerable: true,
  11600. configurable: true
  11601. });
  11602. Object.defineProperty(Canvas2D.prototype, "updateLocalTransformCounter", {
  11603. get: function () {
  11604. return this._updateLocalTransformCounter;
  11605. },
  11606. enumerable: true,
  11607. configurable: true
  11608. });
  11609. Object.defineProperty(Canvas2D.prototype, "updateGlobalTransformCounter", {
  11610. get: function () {
  11611. return this._updateGlobalTransformCounter;
  11612. },
  11613. enumerable: true,
  11614. configurable: true
  11615. });
  11616. Object.defineProperty(Canvas2D.prototype, "boundingInfoRecomputeCounter", {
  11617. get: function () {
  11618. return this._boundingInfoRecomputeCounter;
  11619. },
  11620. enumerable: true,
  11621. configurable: true
  11622. });
  11623. Object.defineProperty(Canvas2D, "instances", {
  11624. get: function () {
  11625. return Canvas2D._INSTANCES;
  11626. },
  11627. enumerable: true,
  11628. configurable: true
  11629. });
  11630. Canvas2D.prototype._canvasPreInit = function (settings) {
  11631. var cachingStrategy = (settings.cachingStrategy == null) ? Canvas2D.CACHESTRATEGY_DONTCACHE : settings.cachingStrategy;
  11632. this._cachingStrategy = cachingStrategy;
  11633. this._isScreenSpace = (settings.isScreenSpace == null) ? true : settings.isScreenSpace;
  11634. };
  11635. Canvas2D.prototype._setupInteraction = function (enable) {
  11636. var _this = this;
  11637. // No change detection
  11638. if (enable === this._interactionEnabled) {
  11639. return;
  11640. }
  11641. // Set the new state
  11642. this._interactionEnabled = enable;
  11643. // ScreenSpace mode
  11644. if (this._isScreenSpace) {
  11645. // Disable interaction
  11646. if (!enable) {
  11647. if (this._scenePrePointerObserver) {
  11648. this.scene.onPrePointerObservable.remove(this._scenePrePointerObserver);
  11649. this._scenePrePointerObserver = null;
  11650. }
  11651. return;
  11652. }
  11653. // Enable Interaction
  11654. // Register the observable
  11655. this._scenePrePointerObserver = this.scene.onPrePointerObservable.add(function (e, s) {
  11656. if (_this.isVisible === false) {
  11657. return;
  11658. }
  11659. var hs = 1 / _this.engine.getHardwareScalingLevel();
  11660. var localPos = e.localPosition.multiplyByFloats(hs, hs);
  11661. _this._handlePointerEventForInteraction(e, localPos, s);
  11662. });
  11663. }
  11664. else {
  11665. var scene = this.scene;
  11666. if (enable) {
  11667. scene.constantlyUpdateMeshUnderPointer = true;
  11668. this._scenePointerObserver = scene.onPointerObservable.add(function (e, s) {
  11669. if (_this.isVisible === false) {
  11670. return;
  11671. }
  11672. if (e.pickInfo.hit && e.pickInfo.pickedMesh === _this._worldSpaceNode && _this.worldSpaceToNodeLocal) {
  11673. var localPos = _this.worldSpaceToNodeLocal(e.pickInfo.pickedPoint);
  11674. _this._handlePointerEventForInteraction(e, localPos, s);
  11675. }
  11676. });
  11677. }
  11678. else {
  11679. if (this._scenePointerObserver) {
  11680. this.scene.onPointerObservable.remove(this._scenePointerObserver);
  11681. this._scenePointerObserver = null;
  11682. }
  11683. }
  11684. }
  11685. };
  11686. /**
  11687. * Internal method, you should use the Prim2DBase version instead
  11688. */
  11689. Canvas2D.prototype._setPointerCapture = function (pointerId, primitive) {
  11690. if (this.isPointerCaptured(pointerId)) {
  11691. return false;
  11692. }
  11693. // Try to capture the pointer on the HTML side
  11694. try {
  11695. this.engine.getRenderingCanvas().setPointerCapture(pointerId);
  11696. }
  11697. catch (e) {
  11698. }
  11699. this._primPointerInfo.updateRelatedTarget(primitive, BABYLON.Vector2.Zero());
  11700. this._bubbleNotifyPrimPointerObserver(primitive, BABYLON.PrimitivePointerInfo.PointerGotCapture, null);
  11701. this._capturedPointers.add(pointerId.toString(), primitive);
  11702. return true;
  11703. };
  11704. /**
  11705. * Internal method, you should use the Prim2DBase version instead
  11706. */
  11707. Canvas2D.prototype._releasePointerCapture = function (pointerId, primitive) {
  11708. if (this._capturedPointers.get(pointerId.toString()) !== primitive) {
  11709. return false;
  11710. }
  11711. // Try to release the pointer on the HTML side
  11712. try {
  11713. this.engine.getRenderingCanvas().releasePointerCapture(pointerId);
  11714. }
  11715. catch (e) {
  11716. }
  11717. this._primPointerInfo.updateRelatedTarget(primitive, BABYLON.Vector2.Zero());
  11718. this._bubbleNotifyPrimPointerObserver(primitive, BABYLON.PrimitivePointerInfo.PointerLostCapture, null);
  11719. this._capturedPointers.remove(pointerId.toString());
  11720. return true;
  11721. };
  11722. /**
  11723. * Determine if the given pointer is captured or not
  11724. * @param pointerId the Id of the pointer
  11725. * @return true if it's captured, false otherwise
  11726. */
  11727. Canvas2D.prototype.isPointerCaptured = function (pointerId) {
  11728. return this._capturedPointers.contains(pointerId.toString());
  11729. };
  11730. Canvas2D.prototype.getCapturedPrimitive = function (pointerId) {
  11731. // Avoid unnecessary lookup
  11732. if (this._capturedPointers.count === 0) {
  11733. return null;
  11734. }
  11735. return this._capturedPointers.get(pointerId.toString());
  11736. };
  11737. Canvas2D.prototype._handlePointerEventForInteraction = function (eventData, localPosition, eventState) {
  11738. // Dispose check
  11739. if (this.isDisposed) {
  11740. return;
  11741. }
  11742. // Update the this._primPointerInfo structure we'll send to observers using the PointerEvent data
  11743. if (!this._updatePointerInfo(eventData, localPosition)) {
  11744. return;
  11745. }
  11746. var capturedPrim = this.getCapturedPrimitive(this._primPointerInfo.pointerId);
  11747. // Make sure the intersection list is up to date, we maintain this list either in response of a mouse event (here) or before rendering the canvas.
  11748. // Why before rendering the canvas? because some primitives may move and get away/under the mouse cursor (which is not moving). So we need to update at both location in order to always have an accurate list, which is needed for the hover state change.
  11749. this._updateIntersectionList(this._primPointerInfo.canvasPointerPos, capturedPrim !== null, true);
  11750. // Update the over status, same as above, it's could be done here or during rendering, but will be performed only once per render frame
  11751. this._updateOverStatus(true);
  11752. // Check if we have nothing to raise
  11753. if (!this._actualOverPrimitive && !capturedPrim) {
  11754. return;
  11755. }
  11756. // Update the relatedTarget info with the over primitive or the captured one (if any)
  11757. var targetPrim = capturedPrim || this._actualOverPrimitive.prim;
  11758. var targetPointerPos = capturedPrim ? this._primPointerInfo.canvasPointerPos.subtract(new BABYLON.Vector2(targetPrim.globalTransform.m[12], targetPrim.globalTransform.m[13])) : this._actualOverPrimitive.intersectionLocation;
  11759. this._primPointerInfo.updateRelatedTarget(targetPrim, targetPointerPos);
  11760. // Analyze the pointer event type and fire proper events on the primitive
  11761. var skip = false;
  11762. if (eventData.type === BABYLON.PointerEventTypes.POINTERWHEEL) {
  11763. skip = !this._bubbleNotifyPrimPointerObserver(targetPrim, BABYLON.PrimitivePointerInfo.PointerMouseWheel, eventData);
  11764. }
  11765. else if (eventData.type === BABYLON.PointerEventTypes.POINTERMOVE) {
  11766. skip = !this._bubbleNotifyPrimPointerObserver(targetPrim, BABYLON.PrimitivePointerInfo.PointerMove, eventData);
  11767. }
  11768. else if (eventData.type === BABYLON.PointerEventTypes.POINTERDOWN) {
  11769. skip = !this._bubbleNotifyPrimPointerObserver(targetPrim, BABYLON.PrimitivePointerInfo.PointerDown, eventData);
  11770. }
  11771. else if (eventData.type === BABYLON.PointerEventTypes.POINTERUP) {
  11772. skip = !this._bubbleNotifyPrimPointerObserver(targetPrim, BABYLON.PrimitivePointerInfo.PointerUp, eventData);
  11773. }
  11774. eventState.skipNextObservers = skip;
  11775. if (!skip && (this._isFlagSet(BABYLON.SmartPropertyPrim.flagAllow3DEventsBelowCanvas) === false)) {
  11776. eventState.skipNextObservers = true;
  11777. if (eventData instanceof BABYLON.PointerInfoPre) {
  11778. eventData.skipOnPointerObservable = true;
  11779. }
  11780. }
  11781. };
  11782. Canvas2D.prototype._updatePointerInfo = function (eventData, localPosition) {
  11783. var s = this.scale;
  11784. var pii = this._primPointerInfo;
  11785. if (!pii.canvasPointerPos) {
  11786. pii.canvasPointerPos = BABYLON.Vector2.Zero();
  11787. }
  11788. var camera = this._scene.cameraToUseForPointers || this._scene.activeCamera;
  11789. if (!camera || !camera.viewport) {
  11790. return false;
  11791. }
  11792. var engine = this._scene.getEngine();
  11793. if (this._isScreenSpace) {
  11794. var cameraViewport = camera.viewport;
  11795. var viewport = cameraViewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
  11796. // Moving coordinates to local viewport world
  11797. var x = localPosition.x - viewport.x;
  11798. var y = localPosition.y - viewport.y;
  11799. pii.canvasPointerPos.x = (x - this.actualPosition.x) / s;
  11800. pii.canvasPointerPos.y = (engine.getRenderHeight() - y - this.actualPosition.y) / s;
  11801. }
  11802. else {
  11803. pii.canvasPointerPos.x = localPosition.x / s;
  11804. pii.canvasPointerPos.y = localPosition.y / s;
  11805. }
  11806. //console.log(`UpdatePointerInfo for ${this.id}, X:${pii.canvasPointerPos.x}, Y:${pii.canvasPointerPos.y}`);
  11807. pii.mouseWheelDelta = 0;
  11808. if (eventData.type === BABYLON.PointerEventTypes.POINTERWHEEL) {
  11809. var event = eventData.event;
  11810. if (event.wheelDelta) {
  11811. pii.mouseWheelDelta = event.wheelDelta / (BABYLON.PrimitivePointerInfo.MouseWheelPrecision * 40);
  11812. }
  11813. else if (event.detail) {
  11814. pii.mouseWheelDelta = -event.detail / BABYLON.PrimitivePointerInfo.MouseWheelPrecision;
  11815. }
  11816. }
  11817. else {
  11818. var pe = eventData.event;
  11819. pii.ctrlKey = pe.ctrlKey;
  11820. pii.altKey = pe.altKey;
  11821. pii.shiftKey = pe.shiftKey;
  11822. pii.metaKey = pe.metaKey;
  11823. pii.button = pe.button;
  11824. pii.buttons = pe.buttons;
  11825. pii.pointerId = pe.pointerId;
  11826. pii.width = pe.width;
  11827. pii.height = pe.height;
  11828. pii.presssure = pe.pressure;
  11829. pii.tilt.x = pe.tiltX;
  11830. pii.tilt.y = pe.tiltY;
  11831. pii.isCaptured = this.getCapturedPrimitive(pe.pointerId) !== null;
  11832. }
  11833. return true;
  11834. };
  11835. Canvas2D.prototype._updateIntersectionList = function (mouseLocalPos, isCapture, force) {
  11836. if (!force && (this.scene.getRenderId() === this._intersectionRenderId)) {
  11837. return;
  11838. }
  11839. // A little safe guard, it might happens than the event is triggered before the first render and nothing is computed, this simple check will make sure everything will be fine
  11840. if (!this._globalTransform) {
  11841. this.updateCachedStates(true);
  11842. }
  11843. var ii = Canvas2D._interInfo;
  11844. ii.pickPosition.x = mouseLocalPos.x;
  11845. ii.pickPosition.y = mouseLocalPos.y;
  11846. ii.findFirstOnly = false;
  11847. // Fast rejection: test if the mouse pointer is outside the canvas's bounding Info
  11848. if (!isCapture && !this.levelBoundingInfo.doesIntersect(ii.pickPosition)) {
  11849. // Reset intersection info as we don't hit anything
  11850. ii.intersectedPrimitives = new Array();
  11851. ii.topMostIntersectedPrimitive = null;
  11852. }
  11853. else {
  11854. // The pointer is inside the Canvas, do an intersection test
  11855. this.intersect(ii);
  11856. }
  11857. {
  11858. // Update prev/actual intersection info, fire "overPrim" property change if needed
  11859. this._previousIntersectionList = this._actualIntersectionList;
  11860. this._actualIntersectionList = ii.intersectedPrimitives;
  11861. this._previousOverPrimitive = this._actualOverPrimitive;
  11862. this._actualOverPrimitive = ii.topMostIntersectedPrimitive;
  11863. var prev = (this._previousOverPrimitive != null) ? this._previousOverPrimitive.prim : null;
  11864. var actual = (this._actualOverPrimitive != null) ? this._actualOverPrimitive.prim : null;
  11865. if (prev !== actual) {
  11866. this.onPropertyChanged("overPrim", this._previousOverPrimitive ? this._previousOverPrimitive.prim : null, this._actualOverPrimitive ? this._actualOverPrimitive.prim : null);
  11867. }
  11868. }
  11869. this._intersectionRenderId = this.scene.getRenderId();
  11870. };
  11871. // Based on the previousIntersectionList and the actualInstersectionList we can determined which primitives are being hover state or loosing it
  11872. Canvas2D.prototype._updateOverStatus = function (force) {
  11873. if ((!force && (this.scene.getRenderId() === this._hoverStatusRenderId)) || !this._previousIntersectionList || !this._actualIntersectionList) {
  11874. return;
  11875. }
  11876. // Detect a change of over
  11877. var prevPrim = this._previousOverPrimitive ? this._previousOverPrimitive.prim : null;
  11878. var actualPrim = this._actualOverPrimitive ? this._actualOverPrimitive.prim : null;
  11879. if (prevPrim !== actualPrim) {
  11880. // Detect if the current pointer is captured, only fire event if they belong to the capture primitive
  11881. var capturedPrim = this.getCapturedPrimitive(this._primPointerInfo.pointerId);
  11882. // Notify the previous "over" prim that the pointer is no longer over it
  11883. if ((capturedPrim && capturedPrim === prevPrim) || (!capturedPrim && prevPrim)) {
  11884. this._primPointerInfo.updateRelatedTarget(prevPrim, this._previousOverPrimitive.intersectionLocation);
  11885. this._bubbleNotifyPrimPointerObserver(prevPrim, BABYLON.PrimitivePointerInfo.PointerOut, null);
  11886. }
  11887. // Notify the new "over" prim that the pointer is over it
  11888. if ((capturedPrim && capturedPrim === actualPrim) || (!capturedPrim && actualPrim)) {
  11889. this._primPointerInfo.updateRelatedTarget(actualPrim, this._actualOverPrimitive.intersectionLocation);
  11890. this._bubbleNotifyPrimPointerObserver(actualPrim, BABYLON.PrimitivePointerInfo.PointerOver, null);
  11891. }
  11892. }
  11893. this._hoverStatusRenderId = this.scene.getRenderId();
  11894. };
  11895. Canvas2D.prototype._updatePrimPointerPos = function (prim) {
  11896. if (this._primPointerInfo.isCaptured) {
  11897. this._primPointerInfo.primitivePointerPos = this._primPointerInfo.relatedTargetPointerPos;
  11898. }
  11899. else {
  11900. for (var _i = 0, _a = this._actualIntersectionList; _i < _a.length; _i++) {
  11901. var pii = _a[_i];
  11902. if (pii.prim === prim) {
  11903. this._primPointerInfo.primitivePointerPos = pii.intersectionLocation;
  11904. return;
  11905. }
  11906. }
  11907. }
  11908. };
  11909. Canvas2D.prototype._debugExecObserver = function (prim, mask) {
  11910. if (!this._notifDebugMode) {
  11911. return;
  11912. }
  11913. var debug = "";
  11914. for (var i = 0; i < prim.hierarchyDepth; i++) {
  11915. debug += " ";
  11916. }
  11917. var pii = this._primPointerInfo;
  11918. debug += "[RID:" + this.scene.getRenderId() + "] [" + prim.hierarchyDepth + "] event:" + BABYLON.PrimitivePointerInfo.getEventTypeName(mask) + ", id: " + prim.id + " (" + BABYLON.Tools.getClassName(prim) + "), primPos: " + pii.primitivePointerPos.toString() + ", canvasPos: " + pii.canvasPointerPos.toString();
  11919. console.log(debug);
  11920. };
  11921. Canvas2D.prototype._bubbleNotifyPrimPointerObserver = function (prim, mask, eventData) {
  11922. var ppi = this._primPointerInfo;
  11923. var event = eventData ? eventData.event : null;
  11924. // In case of PointerOver/Out we will first notify the parent with PointerEnter/Leave
  11925. if ((mask & (BABYLON.PrimitivePointerInfo.PointerOver | BABYLON.PrimitivePointerInfo.PointerOut)) !== 0) {
  11926. this._notifParents(prim, mask);
  11927. }
  11928. var bubbleCancelled = false;
  11929. var cur = prim;
  11930. while (cur) {
  11931. // Only trigger the observers if the primitive is intersected (except for out)
  11932. if (!bubbleCancelled) {
  11933. this._updatePrimPointerPos(cur);
  11934. // Exec the observers
  11935. this._debugExecObserver(cur, mask);
  11936. if (!cur._pointerEventObservable.notifyObservers(ppi, mask) && eventData instanceof BABYLON.PointerInfoPre) {
  11937. eventData.skipOnPointerObservable = true;
  11938. return false;
  11939. }
  11940. this._triggerActionManager(cur, ppi, mask, event);
  11941. // Bubble canceled? If we're not executing PointerOver or PointerOut, quit immediately
  11942. // If it's PointerOver/Out we have to trigger PointerEnter/Leave no matter what
  11943. if (ppi.cancelBubble) {
  11944. if ((mask & (BABYLON.PrimitivePointerInfo.PointerOver | BABYLON.PrimitivePointerInfo.PointerOut)) === 0) {
  11945. return false;
  11946. }
  11947. // We're dealing with PointerOver/Out, let's keep looping to fire PointerEnter/Leave, but not Over/Out anymore
  11948. bubbleCancelled = true;
  11949. }
  11950. }
  11951. // If bubble is cancel we didn't update the Primitive Pointer Pos yet, let's do it
  11952. if (bubbleCancelled) {
  11953. this._updatePrimPointerPos(cur);
  11954. }
  11955. // NOTE TO MYSELF, this is commented right now because it doesn't seemed needed but I can't figure out why I put this code in the first place
  11956. //// Trigger a PointerEnter corresponding to the PointerOver
  11957. //if (mask === PrimitivePointerInfo.PointerOver) {
  11958. // this._debugExecObserver(cur, PrimitivePointerInfo.PointerEnter);
  11959. // cur._pointerEventObservable.notifyObservers(ppi, PrimitivePointerInfo.PointerEnter);
  11960. //}
  11961. //// Trigger a PointerLeave corresponding to the PointerOut
  11962. //else if (mask === PrimitivePointerInfo.PointerOut) {
  11963. // this._debugExecObserver(cur, PrimitivePointerInfo.PointerLeave);
  11964. // cur._pointerEventObservable.notifyObservers(ppi, PrimitivePointerInfo.PointerLeave);
  11965. //}
  11966. // Loop to the parent
  11967. cur = cur.parent;
  11968. }
  11969. return true;
  11970. };
  11971. Canvas2D.prototype._triggerActionManager = function (prim, ppi, mask, eventData) {
  11972. var _this = this;
  11973. // A little safe guard, it might happens than the event is triggered before the first render and nothing is computed, this simple check will make sure everything will be fine
  11974. if (!this._globalTransform) {
  11975. this.updateCachedStates(true);
  11976. }
  11977. // Process Trigger related to PointerDown
  11978. if ((mask & BABYLON.PrimitivePointerInfo.PointerDown) !== 0) {
  11979. // On pointer down, record the current position and time to be able to trick PickTrigger and LongPressTrigger
  11980. this._pickStartingPosition = ppi.primitivePointerPos.clone();
  11981. this._pickStartingTime = new Date().getTime();
  11982. this._pickedDownPrim = null;
  11983. if (prim.actionManager) {
  11984. this._pickedDownPrim = prim;
  11985. if (prim.actionManager.hasPickTriggers) {
  11986. var actionEvent = BABYLON.ActionEvent.CreateNewFromPrimitive(prim, ppi.primitivePointerPos, eventData);
  11987. switch (eventData.button) {
  11988. case 0:
  11989. prim.actionManager.processTrigger(BABYLON.ActionManager.OnLeftPickTrigger, actionEvent);
  11990. break;
  11991. case 1:
  11992. prim.actionManager.processTrigger(BABYLON.ActionManager.OnCenterPickTrigger, actionEvent);
  11993. break;
  11994. case 2:
  11995. prim.actionManager.processTrigger(BABYLON.ActionManager.OnRightPickTrigger, actionEvent);
  11996. break;
  11997. }
  11998. prim.actionManager.processTrigger(BABYLON.ActionManager.OnPickDownTrigger, actionEvent);
  11999. }
  12000. if (prim.actionManager.hasSpecificTrigger(BABYLON.ActionManager.OnLongPressTrigger)) {
  12001. window.setTimeout(function () {
  12002. var ppi = _this._primPointerInfo;
  12003. var capturedPrim = _this.getCapturedPrimitive(ppi.pointerId);
  12004. _this._updateIntersectionList(ppi.canvasPointerPos, capturedPrim !== null, true);
  12005. _this._updateOverStatus(false);
  12006. var ii = new BABYLON.IntersectInfo2D();
  12007. ii.pickPosition = ppi.canvasPointerPos.clone();
  12008. ii.findFirstOnly = false;
  12009. _this.intersect(ii);
  12010. if (ii.isPrimIntersected(prim) !== null) {
  12011. if (prim.actionManager) {
  12012. if (_this._pickStartingTime !== 0 && ((new Date().getTime() - _this._pickStartingTime) > BABYLON.ActionManager.LongPressDelay) && (Math.abs(_this._pickStartingPosition.x - ii.pickPosition.x) < BABYLON.ActionManager.DragMovementThreshold && Math.abs(_this._pickStartingPosition.y - ii.pickPosition.y) < BABYLON.ActionManager.DragMovementThreshold)) {
  12013. _this._pickStartingTime = 0;
  12014. prim.actionManager.processTrigger(BABYLON.ActionManager.OnLongPressTrigger, BABYLON.ActionEvent.CreateNewFromPrimitive(prim, ppi.primitivePointerPos, eventData));
  12015. }
  12016. }
  12017. }
  12018. }, BABYLON.ActionManager.LongPressDelay);
  12019. }
  12020. }
  12021. }
  12022. else if ((mask & BABYLON.PrimitivePointerInfo.PointerUp) !== 0) {
  12023. this._pickStartingTime = 0;
  12024. var actionEvent = BABYLON.ActionEvent.CreateNewFromPrimitive(prim, ppi.primitivePointerPos, eventData);
  12025. if (prim.actionManager) {
  12026. // OnPickUpTrigger
  12027. prim.actionManager.processTrigger(BABYLON.ActionManager.OnPickUpTrigger, actionEvent);
  12028. // OnPickTrigger
  12029. if (Math.abs(this._pickStartingPosition.x - ppi.canvasPointerPos.x) < BABYLON.ActionManager.DragMovementThreshold && Math.abs(this._pickStartingPosition.y - ppi.canvasPointerPos.y) < BABYLON.ActionManager.DragMovementThreshold) {
  12030. prim.actionManager.processTrigger(BABYLON.ActionManager.OnPickTrigger, actionEvent);
  12031. }
  12032. }
  12033. // OnPickOutTrigger
  12034. if (this._pickedDownPrim && this._pickedDownPrim.actionManager && (this._pickedDownPrim !== prim)) {
  12035. this._pickedDownPrim.actionManager.processTrigger(BABYLON.ActionManager.OnPickOutTrigger, actionEvent);
  12036. }
  12037. }
  12038. else if ((mask & BABYLON.PrimitivePointerInfo.PointerOver) !== 0) {
  12039. if (prim.actionManager) {
  12040. var actionEvent = BABYLON.ActionEvent.CreateNewFromPrimitive(prim, ppi.primitivePointerPos, eventData);
  12041. prim.actionManager.processTrigger(BABYLON.ActionManager.OnPointerOverTrigger, actionEvent);
  12042. }
  12043. }
  12044. else if ((mask & BABYLON.PrimitivePointerInfo.PointerOut) !== 0) {
  12045. if (prim.actionManager) {
  12046. var actionEvent = BABYLON.ActionEvent.CreateNewFromPrimitive(prim, ppi.primitivePointerPos, eventData);
  12047. prim.actionManager.processTrigger(BABYLON.ActionManager.OnPointerOutTrigger, actionEvent);
  12048. }
  12049. }
  12050. };
  12051. Canvas2D.prototype._notifParents = function (prim, mask) {
  12052. var pii = this._primPointerInfo;
  12053. var curPrim = this;
  12054. while (curPrim) {
  12055. this._updatePrimPointerPos(curPrim);
  12056. // Fire the proper notification
  12057. if (mask === BABYLON.PrimitivePointerInfo.PointerOver) {
  12058. this._debugExecObserver(curPrim, BABYLON.PrimitivePointerInfo.PointerEnter);
  12059. curPrim._pointerEventObservable.notifyObservers(pii, BABYLON.PrimitivePointerInfo.PointerEnter);
  12060. }
  12061. else if (mask === BABYLON.PrimitivePointerInfo.PointerOut) {
  12062. this._debugExecObserver(curPrim, BABYLON.PrimitivePointerInfo.PointerLeave);
  12063. curPrim._pointerEventObservable.notifyObservers(pii, BABYLON.PrimitivePointerInfo.PointerLeave);
  12064. }
  12065. curPrim = curPrim.parent;
  12066. }
  12067. };
  12068. /**
  12069. * Don't forget to call the dispose method when you're done with the Canvas instance.
  12070. * But don't worry, if you dispose its scene, the canvas will be automatically disposed too.
  12071. */
  12072. Canvas2D.prototype.dispose = function () {
  12073. if (!_super.prototype.dispose.call(this)) {
  12074. return false;
  12075. }
  12076. if (this._profilingCanvas) {
  12077. this._profilingCanvas.dispose();
  12078. this._profilingCanvas = null;
  12079. }
  12080. if (this.interactionEnabled) {
  12081. this._setupInteraction(false);
  12082. }
  12083. if (this._beforeRenderObserver) {
  12084. this._scene.onBeforeRenderObservable.remove(this._beforeRenderObserver);
  12085. this._beforeRenderObserver = null;
  12086. }
  12087. if (this._afterRenderObserver) {
  12088. this._scene.onAfterRenderObservable.remove(this._afterRenderObserver);
  12089. this._afterRenderObserver = null;
  12090. }
  12091. if (this._groupCacheMaps) {
  12092. this._groupCacheMaps.forEach(function (k, m) { return m.forEach(function (e) { return e.dispose(); }); });
  12093. this._groupCacheMaps = null;
  12094. }
  12095. // Unregister this instance
  12096. var index = Canvas2D._INSTANCES.indexOf(this);
  12097. if (index > -1) {
  12098. Canvas2D._INSTANCES.splice(index, 1);
  12099. }
  12100. };
  12101. Object.defineProperty(Canvas2D.prototype, "scene", {
  12102. /**
  12103. * Accessor to the Scene that owns the Canvas
  12104. * @returns The instance of the Scene object
  12105. */
  12106. get: function () {
  12107. return this._scene;
  12108. },
  12109. enumerable: true,
  12110. configurable: true
  12111. });
  12112. Object.defineProperty(Canvas2D.prototype, "engine", {
  12113. /**
  12114. * Accessor to the Engine that drives the Scene used by this Canvas
  12115. * @returns The instance of the Engine object
  12116. */
  12117. get: function () {
  12118. return this._engine;
  12119. },
  12120. enumerable: true,
  12121. configurable: true
  12122. });
  12123. Object.defineProperty(Canvas2D.prototype, "uid", {
  12124. /**
  12125. * return a unique identifier for the Canvas2D
  12126. */
  12127. get: function () {
  12128. if (!this._uid) {
  12129. this._uid = BABYLON.Tools.RandomId();
  12130. }
  12131. return this._uid;
  12132. },
  12133. enumerable: true,
  12134. configurable: true
  12135. });
  12136. Object.defineProperty(Canvas2D.prototype, "renderObservable", {
  12137. /**
  12138. * And observable called during the Canvas rendering process.
  12139. * This observable is called twice per render, each time with a different mask:
  12140. * - 1: before render is executed
  12141. * - 2: after render is executed
  12142. */
  12143. get: function () {
  12144. if (!this._renderObservable) {
  12145. this._renderObservable = new BABYLON.Observable();
  12146. }
  12147. return this._renderObservable;
  12148. },
  12149. enumerable: true,
  12150. configurable: true
  12151. });
  12152. Object.defineProperty(Canvas2D.prototype, "cachingStrategy", {
  12153. /**
  12154. * Accessor of the Caching Strategy used by this Canvas.
  12155. * See Canvas2D.CACHESTRATEGY_xxxx static members for more information
  12156. * @returns the value corresponding to the used strategy.
  12157. */
  12158. get: function () {
  12159. return this._cachingStrategy;
  12160. },
  12161. enumerable: true,
  12162. configurable: true
  12163. });
  12164. Object.defineProperty(Canvas2D.prototype, "isScreenSpace", {
  12165. /**
  12166. * Return true if the Canvas is a Screen Space one, false if it's a World Space one.
  12167. * @returns {}
  12168. */
  12169. get: function () {
  12170. return this._isScreenSpace;
  12171. },
  12172. enumerable: true,
  12173. configurable: true
  12174. });
  12175. Object.defineProperty(Canvas2D.prototype, "worldSpaceCanvasNode", {
  12176. /**
  12177. * Only valid for World Space Canvas, returns the scene node that displays the canvas
  12178. */
  12179. get: function () {
  12180. return this._worldSpaceNode;
  12181. },
  12182. set: function (val) {
  12183. this._worldSpaceNode = val;
  12184. },
  12185. enumerable: true,
  12186. configurable: true
  12187. });
  12188. Object.defineProperty(Canvas2D.prototype, "supportInstancedArray", {
  12189. /**
  12190. * Check if the WebGL Instanced Array extension is supported or not
  12191. */
  12192. get: function () {
  12193. return this._supprtInstancedArray;
  12194. },
  12195. enumerable: true,
  12196. configurable: true
  12197. });
  12198. Object.defineProperty(Canvas2D.prototype, "backgroundFill", {
  12199. /**
  12200. * Property that defines the fill object used to draw the background of the Canvas.
  12201. * Note that Canvas with a Caching Strategy of
  12202. * @returns If the background is not set, null will be returned, otherwise a valid fill object is returned.
  12203. */
  12204. get: function () {
  12205. if (!this._background || !this._background.isVisible) {
  12206. return null;
  12207. }
  12208. return this._background.fill;
  12209. },
  12210. set: function (value) {
  12211. this.checkBackgroundAvailability();
  12212. if (value === this._background.fill) {
  12213. return;
  12214. }
  12215. this._background.fill = value;
  12216. this._background.levelVisible = true;
  12217. },
  12218. enumerable: true,
  12219. configurable: true
  12220. });
  12221. Object.defineProperty(Canvas2D.prototype, "backgroundBorder", {
  12222. /**
  12223. * Property that defines the border object used to draw the background of the Canvas.
  12224. * @returns If the background is not set, null will be returned, otherwise a valid border object is returned.
  12225. */
  12226. get: function () {
  12227. if (!this._background || !this._background.isVisible) {
  12228. return null;
  12229. }
  12230. return this._background.border;
  12231. },
  12232. set: function (value) {
  12233. this.checkBackgroundAvailability();
  12234. if (value === this._background.border) {
  12235. return;
  12236. }
  12237. this._background.border = value;
  12238. this._background.levelVisible = true;
  12239. },
  12240. enumerable: true,
  12241. configurable: true
  12242. });
  12243. Object.defineProperty(Canvas2D.prototype, "backgroundBorderThickness", {
  12244. /**
  12245. * Property that defines the thickness of the border object used to draw the background of the Canvas.
  12246. * @returns If the background is not set, null will be returned, otherwise a valid number matching the thickness is returned.
  12247. */
  12248. get: function () {
  12249. if (!this._background || !this._background.isVisible) {
  12250. return null;
  12251. }
  12252. return this._background.borderThickness;
  12253. },
  12254. set: function (value) {
  12255. this.checkBackgroundAvailability();
  12256. if (value === this._background.borderThickness) {
  12257. return;
  12258. }
  12259. this._background.borderThickness = value;
  12260. },
  12261. enumerable: true,
  12262. configurable: true
  12263. });
  12264. Object.defineProperty(Canvas2D.prototype, "backgroundRoundRadius", {
  12265. /**
  12266. * You can set the roundRadius of the background
  12267. * @returns The current roundRadius
  12268. */
  12269. get: function () {
  12270. if (!this._background || !this._background.isVisible) {
  12271. return null;
  12272. }
  12273. return this._background.roundRadius;
  12274. },
  12275. set: function (value) {
  12276. this.checkBackgroundAvailability();
  12277. if (value === this._background.roundRadius) {
  12278. return;
  12279. }
  12280. this._background.roundRadius = value;
  12281. this._background.levelVisible = true;
  12282. },
  12283. enumerable: true,
  12284. configurable: true
  12285. });
  12286. Object.defineProperty(Canvas2D.prototype, "interactionEnabled", {
  12287. /**
  12288. * Enable/Disable interaction for this Canvas
  12289. * When enabled the Prim2DBase.pointerEventObservable property will notified when appropriate events occur
  12290. */
  12291. get: function () {
  12292. return this._interactionEnabled;
  12293. },
  12294. set: function (enable) {
  12295. this._setupInteraction(enable);
  12296. },
  12297. enumerable: true,
  12298. configurable: true
  12299. });
  12300. Object.defineProperty(Canvas2D.prototype, "designSize", {
  12301. get: function () {
  12302. return this._designSize;
  12303. },
  12304. enumerable: true,
  12305. configurable: true
  12306. });
  12307. Object.defineProperty(Canvas2D.prototype, "designSizeUseHorizAxis", {
  12308. get: function () {
  12309. return this._designUseHorizAxis;
  12310. },
  12311. enumerable: true,
  12312. configurable: true
  12313. });
  12314. Object.defineProperty(Canvas2D.prototype, "overPrim", {
  12315. /**
  12316. * Return
  12317. */
  12318. get: function () {
  12319. return this._actualOverPrimitive ? this._actualOverPrimitive.prim : null;
  12320. },
  12321. enumerable: true,
  12322. configurable: true
  12323. });
  12324. Object.defineProperty(Canvas2D.prototype, "_engineData", {
  12325. /**
  12326. * Access the babylon.js' engine bound data, do not invoke this method, it's for internal purpose only
  12327. * @returns {}
  12328. */
  12329. get: function () {
  12330. return this.__engineData;
  12331. },
  12332. enumerable: true,
  12333. configurable: true
  12334. });
  12335. Object.defineProperty(Canvas2D.prototype, "allow3DEventBelowCanvas", {
  12336. /**
  12337. * If true is returned, pointerEvent occurring above the Canvas area also sent in 3D scene, if false they are not sent in the 3D Scene
  12338. */
  12339. get: function () {
  12340. return this._isFlagSet(BABYLON.SmartPropertyPrim.flagAllow3DEventsBelowCanvas);
  12341. },
  12342. /**
  12343. * Set true if you want pointerEvent occurring above the Canvas area to also be sent in the 3D scene.
  12344. * Set false if you don't want the Scene to get the events
  12345. */
  12346. set: function (value) {
  12347. this._changeFlags(BABYLON.SmartPropertyPrim.flagAllow3DEventsBelowCanvas, value);
  12348. },
  12349. enumerable: true,
  12350. configurable: true
  12351. });
  12352. Canvas2D.prototype.createCanvasProfileInfoCanvas = function () {
  12353. if (this._profilingCanvas) {
  12354. return this._profilingCanvas;
  12355. }
  12356. var canvas = new ScreenSpaceCanvas2D(this.scene, {
  12357. id: "ProfileInfoCanvas", cachingStrategy: Canvas2D.CACHESTRATEGY_DONTCACHE, children: [
  12358. new BABYLON.Rectangle2D({
  12359. id: "ProfileBorder", border: "#FFFFFFFF", borderThickness: 2, roundRadius: 5, fill: "#C04040C0", marginAlignment: "h: left, v: top", margin: "10", padding: "10", children: [
  12360. new BABYLON.Text2D("Stats", { id: "ProfileInfoText", marginAlignment: "h: left, v: top", fontName: "10pt Lucida Console" })
  12361. ]
  12362. })
  12363. ]
  12364. });
  12365. this._profileInfoText = canvas.findById("ProfileInfoText");
  12366. this._profilingCanvas = canvas;
  12367. return canvas;
  12368. };
  12369. Canvas2D.prototype.checkBackgroundAvailability = function () {
  12370. if (this._cachingStrategy === Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS) {
  12371. throw Error("Can't use Canvas Background with the caching strategy TOPLEVELGROUPS");
  12372. }
  12373. };
  12374. Canvas2D.prototype._initPerfMetrics = function () {
  12375. this._drawCallsOpaqueCounter.fetchNewFrame();
  12376. this._drawCallsAlphaTestCounter.fetchNewFrame();
  12377. this._drawCallsTransparentCounter.fetchNewFrame();
  12378. this._groupRenderCounter.fetchNewFrame();
  12379. this._updateTransparentDataCounter.fetchNewFrame();
  12380. this._cachedGroupRenderCounter.fetchNewFrame();
  12381. this._updateCachedStateCounter.fetchNewFrame();
  12382. this._updateLayoutCounter.fetchNewFrame();
  12383. this._updatePositioningCounter.fetchNewFrame();
  12384. this._updateLocalTransformCounter.fetchNewFrame();
  12385. this._updateGlobalTransformCounter.fetchNewFrame();
  12386. this._boundingInfoRecomputeCounter.fetchNewFrame();
  12387. };
  12388. Canvas2D.prototype._fetchPerfMetrics = function () {
  12389. this._drawCallsOpaqueCounter.addCount(0, true);
  12390. this._drawCallsAlphaTestCounter.addCount(0, true);
  12391. this._drawCallsTransparentCounter.addCount(0, true);
  12392. this._groupRenderCounter.addCount(0, true);
  12393. this._updateTransparentDataCounter.addCount(0, true);
  12394. this._cachedGroupRenderCounter.addCount(0, true);
  12395. this._updateCachedStateCounter.addCount(0, true);
  12396. this._updateLayoutCounter.addCount(0, true);
  12397. this._updatePositioningCounter.addCount(0, true);
  12398. this._updateLocalTransformCounter.addCount(0, true);
  12399. this._updateGlobalTransformCounter.addCount(0, true);
  12400. this._boundingInfoRecomputeCounter.addCount(0, true);
  12401. };
  12402. Canvas2D.prototype._updateProfileCanvas = function () {
  12403. if (this._profileInfoText == null) {
  12404. return;
  12405. }
  12406. var format = function (v) { return (Math.round(v * 100) / 100).toString(); };
  12407. var p = "Draw Calls:\n" +
  12408. (" - Opaque: " + format(this.drawCallsOpaqueCounter.current) + ", (avg:" + format(this.drawCallsOpaqueCounter.lastSecAverage) + ", t:" + format(this.drawCallsOpaqueCounter.total) + ")\n") +
  12409. (" - AlphaTest: " + format(this.drawCallsAlphaTestCounter.current) + ", (avg:" + format(this.drawCallsAlphaTestCounter.lastSecAverage) + ", t:" + format(this.drawCallsAlphaTestCounter.total) + ")\n") +
  12410. (" - Transparent: " + format(this.drawCallsTransparentCounter.current) + ", (avg:" + format(this.drawCallsTransparentCounter.lastSecAverage) + ", t:" + format(this.drawCallsTransparentCounter.total) + ")\n") +
  12411. ("Group Render: " + this.groupRenderCounter.current + ", (avg:" + format(this.groupRenderCounter.lastSecAverage) + ", t:" + format(this.groupRenderCounter.total) + ")\n") +
  12412. ("Update Transparent Data: " + this.updateTransparentDataCounter.current + ", (avg:" + format(this.updateTransparentDataCounter.lastSecAverage) + ", t:" + format(this.updateTransparentDataCounter.total) + ")\n") +
  12413. ("Cached Group Render: " + this.cachedGroupRenderCounter.current + ", (avg:" + format(this.cachedGroupRenderCounter.lastSecAverage) + ", t:" + format(this.cachedGroupRenderCounter.total) + ")\n") +
  12414. ("Update Cached States: " + this.updateCachedStateCounter.current + ", (avg:" + format(this.updateCachedStateCounter.lastSecAverage) + ", t:" + format(this.updateCachedStateCounter.total) + ")\n") +
  12415. (" - Update Layout: " + this.updateLayoutCounter.current + ", (avg:" + format(this.updateLayoutCounter.lastSecAverage) + ", t:" + format(this.updateLayoutCounter.total) + ")\n") +
  12416. (" - Update Positioning: " + this.updatePositioningCounter.current + ", (avg:" + format(this.updatePositioningCounter.lastSecAverage) + ", t:" + format(this.updatePositioningCounter.total) + ")\n") +
  12417. (" - Update Local Trans: " + this.updateLocalTransformCounter.current + ", (avg:" + format(this.updateLocalTransformCounter.lastSecAverage) + ", t:" + format(this.updateLocalTransformCounter.total) + ")\n") +
  12418. (" - Update Global Trans: " + this.updateGlobalTransformCounter.current + ", (avg:" + format(this.updateGlobalTransformCounter.lastSecAverage) + ", t:" + format(this.updateGlobalTransformCounter.total) + ")\n") +
  12419. (" - BoundingInfo Recompute: " + this.boundingInfoRecomputeCounter.current + ", (avg:" + format(this.boundingInfoRecomputeCounter.lastSecAverage) + ", t:" + format(this.boundingInfoRecomputeCounter.total) + ")\n");
  12420. this._profileInfoText.text = p;
  12421. };
  12422. Canvas2D.prototype._addDrawCallCount = function (count, renderMode) {
  12423. switch (renderMode) {
  12424. case BABYLON.Render2DContext.RenderModeOpaque:
  12425. this._drawCallsOpaqueCounter.addCount(count, false);
  12426. return;
  12427. case BABYLON.Render2DContext.RenderModeAlphaTest:
  12428. this._drawCallsAlphaTestCounter.addCount(count, false);
  12429. return;
  12430. case BABYLON.Render2DContext.RenderModeTransparent:
  12431. this._drawCallsTransparentCounter.addCount(count, false);
  12432. return;
  12433. }
  12434. };
  12435. Canvas2D.prototype._addGroupRenderCount = function (count) {
  12436. this._groupRenderCounter.addCount(count, false);
  12437. };
  12438. Canvas2D.prototype._addUpdateTransparentDataCount = function (count) {
  12439. this._updateTransparentDataCounter.addCount(count, false);
  12440. };
  12441. Canvas2D.prototype.addCachedGroupRenderCounter = function (count) {
  12442. this._cachedGroupRenderCounter.addCount(count, false);
  12443. };
  12444. Canvas2D.prototype.addUpdateCachedStateCounter = function (count) {
  12445. this._updateCachedStateCounter.addCount(count, false);
  12446. };
  12447. Canvas2D.prototype.addUpdateLayoutCounter = function (count) {
  12448. this._updateLayoutCounter.addCount(count, false);
  12449. };
  12450. Canvas2D.prototype.addUpdatePositioningCounter = function (count) {
  12451. this._updatePositioningCounter.addCount(count, false);
  12452. };
  12453. Canvas2D.prototype.addupdateLocalTransformCounter = function (count) {
  12454. this._updateLocalTransformCounter.addCount(count, false);
  12455. };
  12456. Canvas2D.prototype.addUpdateGlobalTransformCounter = function (count) {
  12457. this._updateGlobalTransformCounter.addCount(count, false);
  12458. };
  12459. Canvas2D.prototype._updateTrackedNodes = function () {
  12460. var cam = this.scene.cameraToUseForPointers || this.scene.activeCamera;
  12461. cam.getViewMatrix().multiplyToRef(cam.getProjectionMatrix(), Canvas2D._m);
  12462. var rh = this.engine.getRenderHeight();
  12463. var v = cam.viewport.toGlobal(this.engine.getRenderWidth(), rh);
  12464. for (var _i = 0, _a = this._trackedGroups; _i < _a.length; _i++) {
  12465. var group = _a[_i];
  12466. if (group.isDisposed || !group.isVisible) {
  12467. continue;
  12468. }
  12469. var node = group.trackedNode;
  12470. var worldMtx = node.getWorldMatrix();
  12471. var proj = BABYLON.Vector3.Project(Canvas2D._v, worldMtx, Canvas2D._m, v);
  12472. var s = this.scale;
  12473. group.x = Math.round(proj.x / s);
  12474. group.y = Math.round((rh - proj.y) / s);
  12475. }
  12476. };
  12477. /**
  12478. * Call this method change you want to have layout related data computed and up to date (layout area, primitive area, local/global transformation matrices)
  12479. */
  12480. Canvas2D.prototype.updateCanvasLayout = function (forceRecompute) {
  12481. this._updateCanvasState(forceRecompute);
  12482. };
  12483. Canvas2D.prototype._updateAdaptiveSizeWorldCanvas = function () {
  12484. if (this._globalTransformStep < 2) {
  12485. return;
  12486. }
  12487. var n = this.worldSpaceCanvasNode;
  12488. var bi = n.getBoundingInfo().boundingBox;
  12489. var v = bi.vectorsWorld;
  12490. var cam = this.scene.cameraToUseForPointers || this.scene.activeCamera;
  12491. cam.getViewMatrix().multiplyToRef(cam.getProjectionMatrix(), Canvas2D._m);
  12492. var vp = cam.viewport.toGlobal(this.engine.getRenderWidth(), this.engine.getRenderHeight());
  12493. var projPoints = new Array(4);
  12494. for (var i = 0; i < 4; i++) {
  12495. projPoints[i] = BABYLON.Vector3.Project(v[i], Canvas2D._mI, Canvas2D._m, vp);
  12496. }
  12497. var left = projPoints[3].subtract(projPoints[0]).length();
  12498. var top = projPoints[3].subtract(projPoints[1]).length();
  12499. var right = projPoints[1].subtract(projPoints[2]).length();
  12500. var bottom = projPoints[2].subtract(projPoints[0]).length();
  12501. var w = Math.round(Math.max(top, bottom));
  12502. var h = Math.round(Math.max(right, left));
  12503. var isW = w > h;
  12504. // Basically if it's under 256 we use 256, otherwise we take the biggest power of 2
  12505. var edge = Math.max(w, h);
  12506. if (edge < 256) {
  12507. edge = 256;
  12508. }
  12509. else {
  12510. edge = Math.pow(2, Math.ceil(Math.log(edge) / Math.log(2)));
  12511. }
  12512. // Clip values if needed
  12513. edge = Math.min(edge, this._maxAdaptiveWorldSpaceCanvasSize);
  12514. var newScale = edge / ((isW) ? this.size.width : this.size.height);
  12515. if (newScale !== this.scale) {
  12516. var scale = newScale;
  12517. // console.log(`New adaptive scale for Canvas ${this.id}, w: ${w}, h: ${h}, scale: ${scale}, edge: ${edge}, isW: ${isW}`);
  12518. this._setRenderingScale(scale);
  12519. }
  12520. };
  12521. Canvas2D.prototype._updateCanvasState = function (forceRecompute) {
  12522. // Check if the update has already been made for this render Frame
  12523. if (!forceRecompute && this.scene.getRenderId() === this._updateRenderId) {
  12524. return;
  12525. }
  12526. // Detect a change of rendering size
  12527. var renderingSizeChanged = false;
  12528. var newWidth = this.engine.getRenderWidth();
  12529. if (newWidth !== this._renderingSize.width) {
  12530. renderingSizeChanged = true;
  12531. }
  12532. this._renderingSize.width = newWidth;
  12533. var newHeight = this.engine.getRenderHeight();
  12534. if (newHeight !== this._renderingSize.height) {
  12535. renderingSizeChanged = true;
  12536. }
  12537. this._renderingSize.height = newHeight;
  12538. // If the canvas fit the rendering size and it changed, update
  12539. if (renderingSizeChanged && this._fitRenderingDevice) {
  12540. this._actualSize = this._renderingSize.clone();
  12541. this._size = this._renderingSize.clone();
  12542. if (this._background) {
  12543. this._background.size = this.size;
  12544. }
  12545. // Dirty the Layout at the Canvas level to recompute as the size changed
  12546. this._setLayoutDirty();
  12547. }
  12548. // If there's a design size, update the scale according to the renderingSize
  12549. if (this._designSize) {
  12550. var scale = void 0;
  12551. if (this._designUseHorizAxis) {
  12552. scale = this._renderingSize.width / this._designSize.width;
  12553. }
  12554. else {
  12555. scale = this._renderingSize.height / this._designSize.height;
  12556. }
  12557. this.size = this._designSize.clone();
  12558. this.actualSize = this._designSize.clone();
  12559. this.scale = scale;
  12560. }
  12561. var context = new BABYLON.PrepareRender2DContext();
  12562. ++this._globalTransformProcessStep;
  12563. this.updateCachedStates(false);
  12564. this._prepareGroupRender(context);
  12565. this._updateRenderId = this.scene.getRenderId();
  12566. };
  12567. /**
  12568. * Method that renders the Canvas, you should not invoke
  12569. */
  12570. Canvas2D.prototype._render = function () {
  12571. this._initPerfMetrics();
  12572. if (this._renderObservable && this._renderObservable.hasObservers()) {
  12573. this._renderObservable.notifyObservers(this, Canvas2D.RENDEROBSERVABLE_PRE);
  12574. }
  12575. this._updateCanvasState(false);
  12576. this._updateTrackedNodes();
  12577. // Nothing to do is the Canvas is not visible
  12578. if (this.isVisible === false) {
  12579. return;
  12580. }
  12581. if (!this._isScreenSpace) {
  12582. this._updateAdaptiveSizeWorldCanvas();
  12583. }
  12584. this._updateCanvasState(false);
  12585. if (this._primPointerInfo.canvasPointerPos) {
  12586. this._updateIntersectionList(this._primPointerInfo.canvasPointerPos, false, false);
  12587. this._updateOverStatus(false);
  12588. }
  12589. this.engine.setState(false);
  12590. this._groupRender();
  12591. if (!this._isScreenSpace) {
  12592. if (this._isFlagSet(BABYLON.SmartPropertyPrim.flagWorldCacheChanged)) {
  12593. this.worldSpaceCacheChanged();
  12594. this._clearFlags(BABYLON.SmartPropertyPrim.flagWorldCacheChanged);
  12595. }
  12596. }
  12597. // If the canvas is cached at canvas level, we must manually render the sprite that will display its content
  12598. if (this._cachingStrategy === Canvas2D.CACHESTRATEGY_CANVAS && this._cachedCanvasGroup) {
  12599. this._cachedCanvasGroup._renderCachedCanvas();
  12600. }
  12601. this._fetchPerfMetrics();
  12602. this._updateProfileCanvas();
  12603. if (this._renderObservable && this._renderObservable.hasObservers()) {
  12604. this._renderObservable.notifyObservers(this, Canvas2D.RENDEROBSERVABLE_POST);
  12605. }
  12606. };
  12607. /**
  12608. * Internal method that allocate a cache for the given group.
  12609. * Caching is made using a collection of MapTexture where many groups have their bitmap cache stored inside.
  12610. * @param group The group to allocate the cache of.
  12611. * @return custom type with the PackedRect instance giving information about the cache location into the texture and also the MapTexture instance that stores the cache.
  12612. */
  12613. Canvas2D.prototype._allocateGroupCache = function (group, parent, minSize, useMipMap, anisotropicLevel) {
  12614. if (useMipMap === void 0) { useMipMap = false; }
  12615. if (anisotropicLevel === void 0) { anisotropicLevel = 1; }
  12616. var key = (useMipMap ? "MipMap" : "NoMipMap") + "_" + anisotropicLevel;
  12617. var rd = group._renderableData;
  12618. var noResizeScale = rd._noResizeOnScale;
  12619. var isCanvas = parent == null;
  12620. var scale;
  12621. if (noResizeScale) {
  12622. scale = isCanvas ? Canvas2D._unS : group.parent.actualScale;
  12623. }
  12624. else {
  12625. scale = group.actualScale;
  12626. }
  12627. // Determine size
  12628. var size = group.actualSize;
  12629. size = new BABYLON.Size(Math.ceil(size.width * scale.x), Math.ceil(size.height * scale.y));
  12630. if (minSize) {
  12631. size.width = Math.max(minSize.width, size.width);
  12632. size.height = Math.max(minSize.height, size.height);
  12633. }
  12634. var mapArray = this._groupCacheMaps.getOrAddWithFactory(key, function () { return new Array(); });
  12635. // Try to find a spot in one of the cached texture
  12636. var res = null;
  12637. var map;
  12638. for (var _i = 0, mapArray_1 = mapArray; _i < mapArray_1.length; _i++) {
  12639. var _map = mapArray_1[_i];
  12640. map = _map;
  12641. var node = map.allocateRect(size);
  12642. if (node) {
  12643. res = { node: node, texture: map };
  12644. break;
  12645. }
  12646. }
  12647. // Couldn't find a map that could fit the rect, create a new map for it
  12648. if (!res) {
  12649. var mapSize = new BABYLON.Size(Canvas2D._groupTextureCacheSize, Canvas2D._groupTextureCacheSize);
  12650. // Check if the predefined size would fit, other create a custom size using the nearest bigger power of 2
  12651. if (size.width > mapSize.width || size.height > mapSize.height) {
  12652. mapSize.width = Math.pow(2, Math.ceil(Math.log(size.width) / Math.log(2)));
  12653. mapSize.height = Math.pow(2, Math.ceil(Math.log(size.height) / Math.log(2)));
  12654. }
  12655. var id = "groupsMapChache" + this._mapCounter++ + "forCanvas" + this.id;
  12656. map = new BABYLON.MapTexture(id, this._scene, mapSize, useMipMap ? BABYLON.Texture.TRILINEAR_SAMPLINGMODE : BABYLON.Texture.BILINEAR_SAMPLINGMODE, useMipMap);
  12657. map.hasAlpha = true;
  12658. map.anisotropicFilteringLevel = 4;
  12659. mapArray.splice(0, 0, map);
  12660. var node = map.allocateRect(size);
  12661. res = { node: node, texture: map };
  12662. }
  12663. // Check if we have to create a Sprite that will display the content of the Canvas which is cached.
  12664. // Don't do it in case of the group being a worldspace canvas (because its texture is bound to a WorldSpaceCanvas node)
  12665. if (group !== this || this._isScreenSpace) {
  12666. var node = res.node;
  12667. // Special case if the canvas is entirely cached: create a group that will have a single sprite it will be rendered specifically at the very end of the rendering process
  12668. var sprite = void 0;
  12669. if (this._cachingStrategy === Canvas2D.CACHESTRATEGY_CANVAS) {
  12670. this._cachedCanvasGroup = BABYLON.Group2D._createCachedCanvasGroup(this);
  12671. sprite = new BABYLON.Sprite2D(map, { parent: this._cachedCanvasGroup, id: "__cachedCanvasSprite__", spriteSize: node.contentSize, spriteLocation: node.pos });
  12672. sprite.zOrder = 1;
  12673. sprite.origin = BABYLON.Vector2.Zero();
  12674. }
  12675. else {
  12676. sprite = new BABYLON.Sprite2D(map, { parent: parent, id: "__cachedSpriteOfGroup__" + group.id, x: group.actualPosition.x, y: group.actualPosition.y, spriteSize: node.contentSize, spriteLocation: node.pos, dontInheritParentScale: true });
  12677. sprite.origin = group.origin.clone();
  12678. sprite.addExternalData("__cachedGroup__", group);
  12679. sprite.pointerEventObservable.add(function (e, s) {
  12680. if (group.pointerEventObservable !== null) {
  12681. group.pointerEventObservable.notifyObservers(e, s.mask);
  12682. }
  12683. });
  12684. res.sprite = sprite;
  12685. }
  12686. if (sprite && noResizeScale) {
  12687. var relScale = isCanvas ? group.actualScale : group.actualScale.divide(group.parent.actualScale);
  12688. sprite.scaleX = relScale.x;
  12689. sprite.scaleY = relScale.y;
  12690. }
  12691. }
  12692. return res;
  12693. };
  12694. /**
  12695. * Internal method used to register a Scene Node to track position for the given group
  12696. * Do not invoke this method, for internal purpose only.
  12697. * @param group the group to track its associated Scene Node
  12698. */
  12699. Canvas2D.prototype._registerTrackedNode = function (group) {
  12700. if (group._isFlagSet(BABYLON.SmartPropertyPrim.flagTrackedGroup)) {
  12701. return;
  12702. }
  12703. this._trackedGroups.push(group);
  12704. group._setFlags(BABYLON.SmartPropertyPrim.flagTrackedGroup);
  12705. };
  12706. /**
  12707. * Internal method used to unregister a tracked Scene Node
  12708. * Do not invoke this method, it's for internal purpose only.
  12709. * @param group the group to unregister its tracked Scene Node from.
  12710. */
  12711. Canvas2D.prototype._unregisterTrackedNode = function (group) {
  12712. if (!group._isFlagSet(BABYLON.SmartPropertyPrim.flagTrackedGroup)) {
  12713. return;
  12714. }
  12715. var i = this._trackedGroups.indexOf(group);
  12716. if (i !== -1) {
  12717. this._trackedGroups.splice(i, 1);
  12718. }
  12719. group._clearFlags(BABYLON.SmartPropertyPrim.flagTrackedGroup);
  12720. };
  12721. /**
  12722. * Get a Solid Color Brush instance matching the given color.
  12723. * @param color The color to retrieve
  12724. * @return A shared instance of the SolidColorBrush2D class that use the given color
  12725. */
  12726. Canvas2D.GetSolidColorBrush = function (color) {
  12727. return Canvas2D._solidColorBrushes.getOrAddWithFactory(color.toHexString(), function () { return new BABYLON.SolidColorBrush2D(color.clone(), true); });
  12728. };
  12729. /**
  12730. * Get a Solid Color Brush instance matching the given color expressed as a CSS formatted hexadecimal value.
  12731. * @param color The color to retrieve
  12732. * @return A shared instance of the SolidColorBrush2D class that uses the given color
  12733. */
  12734. Canvas2D.GetSolidColorBrushFromHex = function (hexValue) {
  12735. return Canvas2D._solidColorBrushes.getOrAddWithFactory(hexValue, function () { return new BABYLON.SolidColorBrush2D(BABYLON.Color4.FromHexString(hexValue), true); });
  12736. };
  12737. /**
  12738. * Get a Gradient Color Brush
  12739. * @param color1 starting color
  12740. * @param color2 engine color
  12741. * @param translation translation vector to apply. default is [0;0]
  12742. * @param rotation rotation in radian to apply to the brush, initial direction is top to bottom. rotation is counter clockwise. default is 0.
  12743. * @param scale scaling factor to apply. default is 1.
  12744. */
  12745. Canvas2D.GetGradientColorBrush = function (color1, color2, translation, rotation, scale) {
  12746. if (translation === void 0) { translation = BABYLON.Vector2.Zero(); }
  12747. if (rotation === void 0) { rotation = 0; }
  12748. if (scale === void 0) { scale = 1; }
  12749. return Canvas2D._gradientColorBrushes.getOrAddWithFactory(BABYLON.GradientColorBrush2D.BuildKey(color1, color2, translation, rotation, scale), function () { return new BABYLON.GradientColorBrush2D(color1, color2, translation, rotation, scale, true); });
  12750. };
  12751. /**
  12752. * Create a solid or gradient brush from a string value.
  12753. * @param brushString should be either
  12754. * - "solid: #RRGGBBAA" or "#RRGGBBAA"
  12755. * - "gradient: #FF808080, #FFFFFFF[, [10:20], 180, 1]" for color1, color2, translation, rotation (degree), scale. The last three are optionals, but if specified must be is this order. "gradient:" can be omitted.
  12756. */
  12757. Canvas2D.GetBrushFromString = function (brushString) {
  12758. // Note: yes, I hate/don't know RegEx.. Feel free to add your contribution to the cause!
  12759. brushString = brushString.trim();
  12760. var split = brushString.split(",");
  12761. // Solid, formatted as: "[solid:]#FF808080"
  12762. if (split.length === 1) {
  12763. var value = null;
  12764. if (brushString.indexOf("solid:") === 0) {
  12765. value = brushString.substr(6).trim();
  12766. }
  12767. else if (brushString.indexOf("#") === 0) {
  12768. value = brushString;
  12769. }
  12770. else {
  12771. return null;
  12772. }
  12773. return Canvas2D.GetSolidColorBrushFromHex(value);
  12774. }
  12775. else {
  12776. if (split[0].indexOf("gradient:") === 0) {
  12777. split[0] = split[0].substr(9).trim();
  12778. }
  12779. try {
  12780. var start = BABYLON.Color4.FromHexString(split[0].trim());
  12781. var end = BABYLON.Color4.FromHexString(split[1].trim());
  12782. var t = BABYLON.Vector2.Zero();
  12783. if (split.length > 2) {
  12784. var v = split[2].trim();
  12785. if (v.charAt(0) !== "[" || v.charAt(v.length - 1) !== "]") {
  12786. return null;
  12787. }
  12788. var sep = v.indexOf(":");
  12789. var x = parseFloat(v.substr(1, sep));
  12790. var y = parseFloat(v.substr(sep + 1, v.length - (sep + 1)));
  12791. t = new BABYLON.Vector2(x, y);
  12792. }
  12793. var r = 0;
  12794. if (split.length > 3) {
  12795. r = BABYLON.Tools.ToRadians(parseFloat(split[3].trim()));
  12796. }
  12797. var s = 1;
  12798. if (split.length > 4) {
  12799. s = parseFloat(split[4].trim());
  12800. }
  12801. return Canvas2D.GetGradientColorBrush(start, end, t, r, s);
  12802. }
  12803. catch (e) {
  12804. return null;
  12805. }
  12806. }
  12807. };
  12808. /**
  12809. * In this strategy only the direct children groups of the Canvas will be cached, their whole content (whatever the sub groups they have) into a single bitmap.
  12810. * This strategy doesn't allow primitives added directly as children of the Canvas.
  12811. * You typically want to use this strategy of a screenSpace fullscreen canvas: you don't want a bitmap cache taking the whole screen resolution but still want the main contents (say UI in the topLeft and rightBottom for instance) to be efficiently cached.
  12812. */
  12813. Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS = 1;
  12814. /**
  12815. * In this strategy each group will have its own cache bitmap (except if a given group explicitly defines the DONTCACHEOVERRIDE or CACHEINPARENTGROUP behaviors).
  12816. * This strategy is typically used if the canvas has some groups that are frequently animated. Unchanged ones will have a steady cache and the others will be refreshed when they change, reducing the redraw operation count to their content only.
  12817. * When using this strategy, group instances can rely on the DONTCACHEOVERRIDE or CACHEINPARENTGROUP behaviors to minimize the amount of cached bitmaps.
  12818. * Note that in this mode the Canvas itself is not cached, it only contains the sprites of its direct children group to render, there's no point to cache the whole canvas, sprites will be rendered pretty efficiently, the memory cost would be too great for the value of it.
  12819. */
  12820. Canvas2D.CACHESTRATEGY_ALLGROUPS = 2;
  12821. /**
  12822. * In this strategy the whole canvas is cached into a single bitmap containing every primitives it owns, at the exception of the ones that are owned by a group having the DONTCACHEOVERRIDE behavior (these primitives will be directly drawn to the viewport at each render for screenSpace Canvas or be part of the Canvas cache bitmap for worldSpace Canvas).
  12823. */
  12824. Canvas2D.CACHESTRATEGY_CANVAS = 3;
  12825. /**
  12826. * This strategy is used to recompose/redraw the canvas entirely at each viewport render.
  12827. * Use this strategy if memory is a concern above rendering performances and/or if the canvas is frequently animated (hence reducing the benefits of caching).
  12828. * Note that you can't use this strategy for WorldSpace Canvas, they need at least a top level group caching.
  12829. */
  12830. Canvas2D.CACHESTRATEGY_DONTCACHE = 4;
  12831. /**
  12832. * Observable Mask to be notified before rendering is made
  12833. */
  12834. Canvas2D.RENDEROBSERVABLE_PRE = 1;
  12835. /**
  12836. * Observable Mask to be notified after rendering is made
  12837. */
  12838. Canvas2D.RENDEROBSERVABLE_POST = 2;
  12839. Canvas2D._INSTANCES = [];
  12840. Canvas2D._zMinDelta = 1 / (Math.pow(2, 24) - 1);
  12841. Canvas2D._interInfo = new BABYLON.IntersectInfo2D();
  12842. Canvas2D._v = BABYLON.Vector3.Zero(); // Must stay zero
  12843. Canvas2D._m = BABYLON.Matrix.Identity();
  12844. Canvas2D._mI = BABYLON.Matrix.Identity(); // Must stay identity
  12845. Canvas2D._unS = new BABYLON.Vector2(1, 1);
  12846. /**
  12847. * Define the default size used for both the width and height of a MapTexture to allocate.
  12848. * Note that some MapTexture might be bigger than this size if the first node to allocate is bigger in width or height
  12849. */
  12850. Canvas2D._groupTextureCacheSize = 1024;
  12851. Canvas2D._solidColorBrushes = new BABYLON.StringDictionary();
  12852. Canvas2D._gradientColorBrushes = new BABYLON.StringDictionary();
  12853. Canvas2D = __decorate([
  12854. BABYLON.className("Canvas2D", "BABYLON")
  12855. ], Canvas2D);
  12856. return Canvas2D;
  12857. }(BABYLON.Group2D));
  12858. BABYLON.Canvas2D = Canvas2D;
  12859. var WorldSpaceCanvas2D = (function (_super) {
  12860. __extends(WorldSpaceCanvas2D, _super);
  12861. /**
  12862. * Create a new 2D WorldSpace Rendering Canvas, it is a 2D rectangle that has a size (width/height) and a world transformation information to place it in the world space.
  12863. * This kind of canvas can't have its Primitives directly drawn in the Viewport, they need to be cached in a bitmap at some point, as a consequence the DONT_CACHE strategy is unavailable. For now only CACHESTRATEGY_CANVAS is supported, but the remaining strategies will be soon.
  12864. * @param scene the Scene that owns the Canvas
  12865. * @param size the dimension of the Canvas in World Space
  12866. * @param settings a combination of settings, possible ones are
  12867. * - children: an array of direct children primitives
  12868. * - id: a text identifier, for information purpose only, default is null.
  12869. * - worldPosition the position of the Canvas in World Space, default is [0,0,0]
  12870. * - worldRotation the rotation of the Canvas in World Space, default is Quaternion.Identity()
  12871. * - sideOrientation: Unexpected behavior occur if the value is different from Mesh.DEFAULTSIDE right now, so please use this one, which is the default.
  12872. * - cachingStrategy Must be CACHESTRATEGY_CANVAS for now, which is the default.
  12873. * - enableInteraction: if true the pointer events will be listened and rerouted to the appropriate primitives of the Canvas2D through the Prim2DBase.onPointerEventObservable observable property. Default is false (the opposite of ScreenSpace).
  12874. * - isVisible: true if the canvas must be visible, false for hidden. Default is true.
  12875. * - backgroundRoundRadius: the round radius of the background, either backgroundFill or backgroundBorder must be specified.
  12876. * - backgroundFill: the brush to use to create a background fill for the canvas. can be a string value (see Canvas2D.GetBrushFromString) or a IBrush2D instance.
  12877. * - backgroundBorder: the brush to use to create a background border for the canvas. can be a string value (see Canvas2D.GetBrushFromString) or a IBrush2D instance.
  12878. * - backgroundBorderThickness: if a backgroundBorder is specified, its thickness can be set using this property
  12879. * - customWorldSpaceNode: if specified the Canvas will be rendered in this given Node. But it's the responsibility of the caller to set the "worldSpaceToNodeLocal" property to compute the hit of the mouse ray into the node (in world coordinate system) as well as rendering the cached bitmap in the node itself. The properties cachedRect and cachedTexture of Group2D will give you what you need to do that.
  12880. * - maxAdaptiveCanvasSize: set the max size (width and height) of the bitmap that will contain the cached version of the WorldSpace Canvas. Default is 1024 or less if it's not supported. In any case the value you give will be clipped by the maximum that WebGL supports on the running device. You can set any size, more than 1024 if you want, but testing proved it's a good max value for non "retina" like screens.
  12881. * - paddingTop: top padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  12882. * - paddingLeft: left padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  12883. * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  12884. * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  12885. * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
  12886. */
  12887. function WorldSpaceCanvas2D(scene, size, settings) {
  12888. var _this = this;
  12889. BABYLON.Prim2DBase._isCanvasInit = true;
  12890. var s = settings;
  12891. s.isScreenSpace = false;
  12892. s.size = size.clone();
  12893. settings.cachingStrategy = (settings.cachingStrategy == null) ? Canvas2D.CACHESTRATEGY_CANVAS : settings.cachingStrategy;
  12894. if (settings.cachingStrategy !== Canvas2D.CACHESTRATEGY_CANVAS) {
  12895. throw new Error("Right now only the CACHESTRATEGY_CANVAS cache Strategy is supported for WorldSpace Canvas. More will come soon!");
  12896. }
  12897. _super.call(this, scene, settings);
  12898. BABYLON.Prim2DBase._isCanvasInit = false;
  12899. this._renderableData._useMipMap = true;
  12900. this._renderableData._anisotropicLevel = 8;
  12901. //if (cachingStrategy === Canvas2D.CACHESTRATEGY_DONTCACHE) {
  12902. // throw new Error("CACHESTRATEGY_DONTCACHE cache Strategy can't be used for WorldSpace Canvas");
  12903. //}
  12904. var createWorldSpaceNode = !settings || (settings.customWorldSpaceNode == null);
  12905. var id = settings ? settings.id || null : null;
  12906. // Set the max size of texture allowed for the adaptive render of the world space canvas cached bitmap
  12907. var capMaxTextSize = this.engine.getCaps().maxRenderTextureSize;
  12908. var defaultTextSize = (Math.min(capMaxTextSize, 1024)); // Default is 4K if allowed otherwise the max allowed
  12909. if (settings.maxAdaptiveCanvasSize == null) {
  12910. this._maxAdaptiveWorldSpaceCanvasSize = defaultTextSize;
  12911. }
  12912. else {
  12913. // We still clip the given value with the max allowed, the user may not be aware of these limitations
  12914. this._maxAdaptiveWorldSpaceCanvasSize = Math.min(settings.maxAdaptiveCanvasSize, capMaxTextSize);
  12915. }
  12916. if (createWorldSpaceNode) {
  12917. var plane = new BABYLON.WorldSpaceCanvas2DNode(id, scene, this);
  12918. var vertexData = BABYLON.VertexData.CreatePlane({
  12919. width: size.width,
  12920. height: size.height,
  12921. sideOrientation: settings && settings.sideOrientation || BABYLON.Mesh.DEFAULTSIDE
  12922. });
  12923. var mtl = new BABYLON.StandardMaterial(id + "_Material", scene);
  12924. this.applyCachedTexture(vertexData, mtl);
  12925. vertexData.applyToMesh(plane, true);
  12926. mtl.specularColor = new BABYLON.Color3(0, 0, 0);
  12927. mtl.disableLighting = true;
  12928. mtl.useAlphaFromDiffuseTexture = true;
  12929. plane.position = settings && settings.worldPosition || BABYLON.Vector3.Zero();
  12930. plane.rotationQuaternion = settings && settings.worldRotation || BABYLON.Quaternion.Identity();
  12931. plane.material = mtl;
  12932. this._worldSpaceNode = plane;
  12933. }
  12934. else {
  12935. this._worldSpaceNode = settings.customWorldSpaceNode;
  12936. this.applyCachedTexture(null, null);
  12937. }
  12938. this.propertyChanged.add(function (e, st) {
  12939. var mesh = _this._worldSpaceNode;
  12940. if (mesh) {
  12941. mesh.isVisible = _this.isVisible;
  12942. }
  12943. }, BABYLON.Prim2DBase.isVisibleProperty.flagId);
  12944. }
  12945. WorldSpaceCanvas2D = __decorate([
  12946. BABYLON.className("WorldSpaceCanvas2D", "BABYLON")
  12947. ], WorldSpaceCanvas2D);
  12948. return WorldSpaceCanvas2D;
  12949. }(Canvas2D));
  12950. BABYLON.WorldSpaceCanvas2D = WorldSpaceCanvas2D;
  12951. var ScreenSpaceCanvas2D = (function (_super) {
  12952. __extends(ScreenSpaceCanvas2D, _super);
  12953. /**
  12954. * Create a new 2D ScreenSpace Rendering Canvas, it is a 2D rectangle that has a size (width/height) and a position relative to the bottom/left corner of the screen.
  12955. * ScreenSpace Canvas will be drawn in the Viewport as a 2D Layer lying to the top of the 3D Scene. Typically used for traditional UI.
  12956. * All caching strategies will be available.
  12957. * PLEASE NOTE: the origin of a Screen Space Canvas is set to [0;0] (bottom/left) which is different than the default origin of a Primitive which is centered [0.5;0.5]
  12958. * @param scene the Scene that owns the Canvas
  12959. * @param settings a combination of settings, possible ones are
  12960. * - children: an array of direct children primitives
  12961. * - id: a text identifier, for information purpose only
  12962. * - x: the position along the x axis (horizontal), relative to the left edge of the viewport. you can alternatively use the position setting.
  12963. * - y: the position along the y axis (vertically), relative to the bottom edge of the viewport. you can alternatively use the position setting.
  12964. * - position: the position of the canvas, relative from the bottom/left of the scene's viewport. Alternatively you can set the x and y properties directly. Default value is [0, 0]
  12965. * - width: the width of the Canvas. you can alternatively use the size setting.
  12966. * - height: the height of the Canvas. you can alternatively use the size setting.
  12967. * - size: the Size of the canvas. Alternatively the width and height properties can be set. If null two behaviors depend on the cachingStrategy: if it's CACHESTRATEGY_CACHECANVAS then it will always auto-fit the rendering device, in all the other modes it will fit the content of the Canvas
  12968. * - renderingPhase: you can specify for which camera and which renderGroup this canvas will render to enable interleaving of 3D/2D content through the use of renderinGroup. As a rendering Group is rendered for each camera, you have to specify in the scope of which camera you want the canvas' render to be made. Default behavior will render the Canvas at the very end of the render loop.
  12969. * - designSize: if you want to set the canvas content based on fixed coordinates whatever the final canvas dimension would be, set this. For instance a designSize of 360*640 will give you the possibility to specify all the children element in this frame. The Canvas' true size will be the HTMLCanvas' size: for instance it could be 720*1280, then a uniform scale of 2 will be applied on the Canvas to keep the absolute coordinates working as expecting. If the ratios of the designSize and the true Canvas size are not the same, then the scale is computed following the designUseHorizAxis member by using either the size of the horizontal axis or the vertical axis.
  12970. * - designUseHorizAxis: you can set this member if you use designSize to specify which axis is priority to compute the scale when the ratio of the canvas' size is different from the designSize's one.
  12971. * - cachingStrategy: either CACHESTRATEGY_TOPLEVELGROUPS, CACHESTRATEGY_ALLGROUPS, CACHESTRATEGY_CANVAS, CACHESTRATEGY_DONTCACHE. Please refer to their respective documentation for more information. Default is Canvas2D.CACHESTRATEGY_DONTCACHE
  12972. * - enableInteraction: if true the pointer events will be listened and rerouted to the appropriate primitives of the Canvas2D through the Prim2DBase.onPointerEventObservable observable property. Default is true.
  12973. * - allow3DEventBelowCanvas: by default pointerEvent occurring above the Canvas will prevent to be also sent in the 3D Scene. If you set this setting to true, events will be sent both for Canvas and 3D Scene
  12974. * - isVisible: true if the canvas must be visible, false for hidden. Default is true.
  12975. * - backgroundRoundRadius: the round radius of the background, either backgroundFill or backgroundBorder must be specified.
  12976. * - backgroundFill: the brush to use to create a background fill for the canvas. can be a string value (see BABYLON.Canvas2D.GetBrushFromString) or a IBrush2D instance.
  12977. * - backgroundBorder: the brush to use to create a background border for the canvas. can be a string value (see BABYLON.Canvas2D.GetBrushFromString) or a IBrush2D instance.
  12978. * - backgroundBorderThickness: if a backgroundBorder is specified, its thickness can be set using this property
  12979. * - customWorldSpaceNode: if specified the Canvas will be rendered in this given Node. But it's the responsibility of the caller to set the "worldSpaceToNodeLocal" property to compute the hit of the mouse ray into the node (in world coordinate system) as well as rendering the cached bitmap in the node itself. The properties cachedRect and cachedTexture of Group2D will give you what you need to do that.
  12980. * - paddingTop: top padding, can be a number (will be pixels) or a string (see BABYLON.PrimitiveThickness.fromString)
  12981. * - paddingLeft: left padding, can be a number (will be pixels) or a string (see BABYLON.PrimitiveThickness.fromString)
  12982. * - paddingRight: right padding, can be a number (will be pixels) or a string (see BABYLON.PrimitiveThickness.fromString)
  12983. * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see BABYLON.PrimitiveThickness.fromString)
  12984. * - padding: top, left, right and bottom padding formatted as a single string (see BABYLON.PrimitiveThickness.fromString)
  12985. */
  12986. function ScreenSpaceCanvas2D(scene, settings) {
  12987. BABYLON.Prim2DBase._isCanvasInit = true;
  12988. _super.call(this, scene, settings);
  12989. }
  12990. ScreenSpaceCanvas2D = __decorate([
  12991. BABYLON.className("ScreenSpaceCanvas2D", "BABYLON")
  12992. ], ScreenSpaceCanvas2D);
  12993. return ScreenSpaceCanvas2D;
  12994. }(Canvas2D));
  12995. BABYLON.ScreenSpaceCanvas2D = ScreenSpaceCanvas2D;
  12996. })(BABYLON || (BABYLON = {}));
  12997. var BABYLON;
  12998. (function (BABYLON) {
  12999. /**
  13000. * This is the class that is used to display a World Space Canvas into a 3D scene
  13001. */
  13002. var WorldSpaceCanvas2DNode = (function (_super) {
  13003. __extends(WorldSpaceCanvas2DNode, _super);
  13004. function WorldSpaceCanvas2DNode(name, scene, canvas) {
  13005. _super.call(this, name, scene);
  13006. this._canvas = canvas;
  13007. }
  13008. WorldSpaceCanvas2DNode.prototype.dispose = function () {
  13009. _super.prototype.dispose.call(this);
  13010. if (this._canvas) {
  13011. this._canvas.dispose();
  13012. this._canvas = null;
  13013. }
  13014. };
  13015. return WorldSpaceCanvas2DNode;
  13016. }(BABYLON.Mesh));
  13017. BABYLON.WorldSpaceCanvas2DNode = WorldSpaceCanvas2DNode;
  13018. })(BABYLON || (BABYLON = {}));
  13019. var BABYLON;
  13020. (function (BABYLON) {
  13021. var Command = (function () {
  13022. function Command(execute, canExecute) {
  13023. if (!execute) {
  13024. throw Error("At least an execute lambda must be given at Command creation time");
  13025. }
  13026. this._canExecuteChanged = null;
  13027. this._lastCanExecuteResult = null;
  13028. this.execute = execute;
  13029. this.canExecute = canExecute;
  13030. }
  13031. Command.prototype.canExecute = function (parameter) {
  13032. var res = true;
  13033. if (this._canExecute) {
  13034. res = this._canExecute(parameter);
  13035. }
  13036. if (res !== this._lastCanExecuteResult) {
  13037. if (this._canExecuteChanged && this._canExecuteChanged.hasObservers()) {
  13038. this._canExecuteChanged.notifyObservers(null);
  13039. }
  13040. this._lastCanExecuteResult = res;
  13041. }
  13042. return res;
  13043. };
  13044. Command.prototype.execute = function (parameter) {
  13045. this._execute(parameter);
  13046. };
  13047. Object.defineProperty(Command.prototype, "canExecuteChanged", {
  13048. get: function () {
  13049. if (!this._canExecuteChanged) {
  13050. this._canExecuteChanged = new BABYLON.Observable();
  13051. }
  13052. return this._canExecuteChanged;
  13053. },
  13054. enumerable: true,
  13055. configurable: true
  13056. });
  13057. return Command;
  13058. }());
  13059. BABYLON.Command = Command;
  13060. var UIElement = (function (_super) {
  13061. __extends(UIElement, _super);
  13062. function UIElement(settings) {
  13063. _super.call(this);
  13064. if (!settings) {
  13065. throw Error("A settings object must be passed with at least either a parent or owner parameter");
  13066. }
  13067. var type = BABYLON.Tools.getFullClassName(this);
  13068. this._ownerWindow = null;
  13069. this._parent = null;
  13070. this._visualPlaceholder = null;
  13071. this._visualTemplateRoot = null;
  13072. this._visualChildrenPlaceholder = null;
  13073. this._hierarchyDepth = 0;
  13074. this._style = (settings.styleName != null) ? UIElementStyleManager.getStyle(type, settings.styleName) : null;
  13075. this._flags = 0;
  13076. this._id = (settings.id != null) ? settings.id : null;
  13077. this._uid = null;
  13078. this._width = (settings.width != null) ? settings.width : null;
  13079. this._height = (settings.height != null) ? settings.height : null;
  13080. this._minWidth = (settings.minWidth != null) ? settings.minWidth : 0;
  13081. this._minHeight = (settings.minHeight != null) ? settings.minHeight : 0;
  13082. this._maxWidth = (settings.maxWidth != null) ? settings.maxWidth : Number.MAX_VALUE;
  13083. this._maxHeight = (settings.maxHeight != null) ? settings.maxHeight : Number.MAX_VALUE;
  13084. this._margin = null;
  13085. this._padding = null;
  13086. this._marginAlignment = null;
  13087. this._isEnabled = true;
  13088. this._isFocused = false;
  13089. this._isMouseOver = false;
  13090. // Default Margin Alignment for UIElement is stretch for horizontal/vertical and not left/bottom (which is the default for Canvas2D Primitives)
  13091. //this.marginAlignment.horizontal = PrimitiveAlignment.AlignStretch;
  13092. //this.marginAlignment.vertical = PrimitiveAlignment.AlignStretch;
  13093. // Set the layout/margin stuffs
  13094. if (settings.marginTop) {
  13095. this.margin.setTop(settings.marginTop);
  13096. }
  13097. if (settings.marginLeft) {
  13098. this.margin.setLeft(settings.marginLeft);
  13099. }
  13100. if (settings.marginRight) {
  13101. this.margin.setRight(settings.marginRight);
  13102. }
  13103. if (settings.marginBottom) {
  13104. this.margin.setBottom(settings.marginBottom);
  13105. }
  13106. if (settings.margin) {
  13107. if (typeof settings.margin === "string") {
  13108. this.margin.fromString(settings.margin);
  13109. }
  13110. else {
  13111. this.margin.fromUniformPixels(settings.margin);
  13112. }
  13113. }
  13114. if (settings.marginHAlignment) {
  13115. this.marginAlignment.horizontal = settings.marginHAlignment;
  13116. }
  13117. if (settings.marginVAlignment) {
  13118. this.marginAlignment.vertical = settings.marginVAlignment;
  13119. }
  13120. if (settings.marginAlignment) {
  13121. this.marginAlignment.fromString(settings.marginAlignment);
  13122. }
  13123. if (settings.paddingTop) {
  13124. this.padding.setTop(settings.paddingTop);
  13125. }
  13126. if (settings.paddingLeft) {
  13127. this.padding.setLeft(settings.paddingLeft);
  13128. }
  13129. if (settings.paddingRight) {
  13130. this.padding.setRight(settings.paddingRight);
  13131. }
  13132. if (settings.paddingBottom) {
  13133. this.padding.setBottom(settings.paddingBottom);
  13134. }
  13135. if (settings.padding) {
  13136. this.padding.fromString(settings.padding);
  13137. }
  13138. this._assignTemplate(settings.templateName);
  13139. if (settings.parent != null) {
  13140. this._parent = settings.parent;
  13141. this._hierarchyDepth = this._parent._hierarchyDepth + 1;
  13142. }
  13143. }
  13144. UIElement.prototype.dispose = function () {
  13145. if (this.isDisposed) {
  13146. return false;
  13147. }
  13148. if (this._renderingTemplate) {
  13149. this._renderingTemplate.detach();
  13150. this._renderingTemplate = null;
  13151. }
  13152. _super.prototype.dispose.call(this);
  13153. // Don't set to null, it may upset somebody...
  13154. this.animations.splice(0);
  13155. return true;
  13156. };
  13157. /**
  13158. * Returns as a new array populated with the Animatable used by the primitive. Must be overloaded by derived primitives.
  13159. * Look at Sprite2D for more information
  13160. */
  13161. UIElement.prototype.getAnimatables = function () {
  13162. return new Array();
  13163. };
  13164. Object.defineProperty(UIElement.prototype, "ownerWindows", {
  13165. // TODO
  13166. // PROPERTIES
  13167. // Style
  13168. // Id
  13169. // Parent/Children
  13170. // ActualWidth/Height, MinWidth/Height, MaxWidth/Height,
  13171. // Alignment/Margin
  13172. // Visibility, IsVisible
  13173. // IsEnabled (is false, control is disabled, no interaction and a specific render state)
  13174. // CacheMode of Visual Elements
  13175. // Focusable/IsFocused
  13176. // IsPointerCaptured, CapturePointer, IsPointerDirectlyOver, IsPointerOver. De-correlate mouse, stylus, touch?
  13177. // ContextMenu
  13178. // Cursor
  13179. // DesiredSize
  13180. // IsInputEnable ?
  13181. // Opacity, OpacityMask ?
  13182. // SnapToDevicePixels
  13183. // Tag
  13184. // ToolTip
  13185. // METHODS
  13186. // BringIntoView (for scrollable content, to move the scroll to bring the given element visible in the parent's area)
  13187. // Capture/ReleaseCapture (mouse, touch, stylus)
  13188. // Focus
  13189. // PointFrom/ToScreen to translate coordinates
  13190. // EVENTS
  13191. // ContextMenuOpening/Closing/Changed
  13192. // DragEnter/LeaveOver, Drop
  13193. // Got/LostFocus
  13194. // IsEnabledChanged
  13195. // IsPointerOver/DirectlyOverChanged
  13196. // IsVisibleChanged
  13197. // KeyDown/Up
  13198. // LayoutUpdated ?
  13199. // Pointer related events
  13200. // SizeChanged
  13201. // ToolTipOpening/Closing
  13202. get: function () {
  13203. return this._ownerWindow;
  13204. },
  13205. enumerable: true,
  13206. configurable: true
  13207. });
  13208. Object.defineProperty(UIElement.prototype, "style", {
  13209. get: function () {
  13210. if (!this.style) {
  13211. return UIElementStyleManager.DefaultStyleName;
  13212. }
  13213. return this._style.name;
  13214. },
  13215. set: function (value) {
  13216. if (this._style && (this._style.name === value)) {
  13217. return;
  13218. }
  13219. var newStyle = null;
  13220. if (value) {
  13221. newStyle = UIElementStyleManager.getStyle(BABYLON.Tools.getFullClassName(this), value);
  13222. if (!newStyle) {
  13223. throw Error("Couldn't find Style " + value + " for UIElement " + BABYLON.Tools.getFullClassName(this));
  13224. }
  13225. }
  13226. if (this._style) {
  13227. this._style.removeStyle(this);
  13228. }
  13229. if (newStyle) {
  13230. newStyle.applyStyle(this);
  13231. }
  13232. this._style = newStyle;
  13233. },
  13234. enumerable: true,
  13235. configurable: true
  13236. });
  13237. Object.defineProperty(UIElement.prototype, "id", {
  13238. /**
  13239. * A string that identifies the UIElement.
  13240. * The id is optional and there's possible collision with other UIElement's id as the uniqueness is not supported.
  13241. */
  13242. get: function () {
  13243. return this._id;
  13244. },
  13245. set: function (value) {
  13246. if (this._id === value) {
  13247. return;
  13248. }
  13249. this._id = value;
  13250. },
  13251. enumerable: true,
  13252. configurable: true
  13253. });
  13254. Object.defineProperty(UIElement.prototype, "uid", {
  13255. /**
  13256. * Return a unique id automatically generated.
  13257. * This property is mainly used for serialization to ensure a perfect way of identifying a UIElement
  13258. */
  13259. get: function () {
  13260. if (!this._uid) {
  13261. this._uid = BABYLON.Tools.RandomId();
  13262. }
  13263. return this._uid;
  13264. },
  13265. enumerable: true,
  13266. configurable: true
  13267. });
  13268. Object.defineProperty(UIElement.prototype, "hierarchyDepth", {
  13269. get: function () {
  13270. return this._hierarchyDepth;
  13271. },
  13272. enumerable: true,
  13273. configurable: true
  13274. });
  13275. Object.defineProperty(UIElement.prototype, "parent", {
  13276. get: function () {
  13277. return this._parent;
  13278. },
  13279. set: function (value) {
  13280. this._parent = value;
  13281. },
  13282. enumerable: true,
  13283. configurable: true
  13284. });
  13285. Object.defineProperty(UIElement.prototype, "width", {
  13286. get: function () {
  13287. return this._width;
  13288. },
  13289. set: function (value) {
  13290. this._width = value;
  13291. },
  13292. enumerable: true,
  13293. configurable: true
  13294. });
  13295. Object.defineProperty(UIElement.prototype, "height", {
  13296. get: function () {
  13297. return this._height;
  13298. },
  13299. set: function (value) {
  13300. this._height = value;
  13301. },
  13302. enumerable: true,
  13303. configurable: true
  13304. });
  13305. Object.defineProperty(UIElement.prototype, "minWidth", {
  13306. get: function () {
  13307. return this._minWidth;
  13308. },
  13309. set: function (value) {
  13310. this._minWidth = value;
  13311. },
  13312. enumerable: true,
  13313. configurable: true
  13314. });
  13315. Object.defineProperty(UIElement.prototype, "minHheight", {
  13316. get: function () {
  13317. return this._minHeight;
  13318. },
  13319. enumerable: true,
  13320. configurable: true
  13321. });
  13322. Object.defineProperty(UIElement.prototype, "minHeight", {
  13323. set: function (value) {
  13324. this._minHeight = value;
  13325. },
  13326. enumerable: true,
  13327. configurable: true
  13328. });
  13329. Object.defineProperty(UIElement.prototype, "maxWidth", {
  13330. get: function () {
  13331. return this._maxWidth;
  13332. },
  13333. set: function (value) {
  13334. this._maxWidth = value;
  13335. },
  13336. enumerable: true,
  13337. configurable: true
  13338. });
  13339. Object.defineProperty(UIElement.prototype, "maxHeight", {
  13340. get: function () {
  13341. return this._maxHeight;
  13342. },
  13343. set: function (value) {
  13344. this._maxHeight = value;
  13345. },
  13346. enumerable: true,
  13347. configurable: true
  13348. });
  13349. Object.defineProperty(UIElement.prototype, "actualWidth", {
  13350. get: function () {
  13351. return this._actualWidth;
  13352. },
  13353. set: function (value) {
  13354. this._actualWidth = value;
  13355. },
  13356. enumerable: true,
  13357. configurable: true
  13358. });
  13359. Object.defineProperty(UIElement.prototype, "actualHeight", {
  13360. get: function () {
  13361. return this._actualHeight;
  13362. },
  13363. set: function (value) {
  13364. this._actualHeight = value;
  13365. },
  13366. enumerable: true,
  13367. configurable: true
  13368. });
  13369. Object.defineProperty(UIElement.prototype, "margin", {
  13370. get: function () {
  13371. var _this = this;
  13372. if (!this._margin) {
  13373. this._margin = new BABYLON.PrimitiveThickness(function () {
  13374. if (!_this.parent) {
  13375. return null;
  13376. }
  13377. return _this.parent.margin;
  13378. });
  13379. }
  13380. return this._margin;
  13381. },
  13382. set: function (value) {
  13383. this.margin.copyFrom(value);
  13384. },
  13385. enumerable: true,
  13386. configurable: true
  13387. });
  13388. Object.defineProperty(UIElement.prototype, "_hasMargin", {
  13389. get: function () {
  13390. return (this._margin !== null && !this._margin.isDefault) || (this._marginAlignment !== null && !this._marginAlignment.isDefault);
  13391. },
  13392. enumerable: true,
  13393. configurable: true
  13394. });
  13395. Object.defineProperty(UIElement.prototype, "padding", {
  13396. get: function () {
  13397. var _this = this;
  13398. if (!this._padding) {
  13399. this._padding = new BABYLON.PrimitiveThickness(function () {
  13400. if (!_this.parent) {
  13401. return null;
  13402. }
  13403. return _this.parent.padding;
  13404. });
  13405. }
  13406. return this._padding;
  13407. },
  13408. set: function (value) {
  13409. this.padding.copyFrom(value);
  13410. },
  13411. enumerable: true,
  13412. configurable: true
  13413. });
  13414. Object.defineProperty(UIElement.prototype, "_hasPadding", {
  13415. get: function () {
  13416. return this._padding !== null && !this._padding.isDefault;
  13417. },
  13418. enumerable: true,
  13419. configurable: true
  13420. });
  13421. Object.defineProperty(UIElement.prototype, "marginAlignment", {
  13422. get: function () {
  13423. if (!this._marginAlignment) {
  13424. this._marginAlignment = new BABYLON.PrimitiveAlignment();
  13425. }
  13426. return this._marginAlignment;
  13427. },
  13428. set: function (value) {
  13429. this.marginAlignment.copyFrom(value);
  13430. },
  13431. enumerable: true,
  13432. configurable: true
  13433. });
  13434. Object.defineProperty(UIElement.prototype, "_hasMarginAlignment", {
  13435. /**
  13436. * Check if there a marginAlignment specified (non null and not default)
  13437. */
  13438. get: function () {
  13439. return (this._marginAlignment !== null && !this._marginAlignment.isDefault);
  13440. },
  13441. enumerable: true,
  13442. configurable: true
  13443. });
  13444. Object.defineProperty(UIElement.prototype, "isEnabled", {
  13445. get: function () {
  13446. return this._isEnabled;
  13447. },
  13448. set: function (value) {
  13449. this._isEnabled = value;
  13450. },
  13451. enumerable: true,
  13452. configurable: true
  13453. });
  13454. Object.defineProperty(UIElement.prototype, "isFocused", {
  13455. get: function () {
  13456. return this._isFocused;
  13457. },
  13458. set: function (value) {
  13459. this._isFocused = value;
  13460. },
  13461. enumerable: true,
  13462. configurable: true
  13463. });
  13464. Object.defineProperty(UIElement.prototype, "isMouseOver", {
  13465. get: function () {
  13466. return this._isMouseOver;
  13467. },
  13468. set: function (value) {
  13469. this._isMouseOver = value;
  13470. },
  13471. enumerable: true,
  13472. configurable: true
  13473. });
  13474. /**
  13475. * Check if a given flag is set
  13476. * @param flag the flag value
  13477. * @return true if set, false otherwise
  13478. */
  13479. UIElement.prototype._isFlagSet = function (flag) {
  13480. return (this._flags & flag) !== 0;
  13481. };
  13482. /**
  13483. * Check if all given flags are set
  13484. * @param flags the flags ORed
  13485. * @return true if all the flags are set, false otherwise
  13486. */
  13487. UIElement.prototype._areAllFlagsSet = function (flags) {
  13488. return (this._flags & flags) === flags;
  13489. };
  13490. /**
  13491. * Check if at least one flag of the given flags is set
  13492. * @param flags the flags ORed
  13493. * @return true if at least one flag is set, false otherwise
  13494. */
  13495. UIElement.prototype._areSomeFlagsSet = function (flags) {
  13496. return (this._flags & flags) !== 0;
  13497. };
  13498. /**
  13499. * Clear the given flags
  13500. * @param flags the flags to clear
  13501. */
  13502. UIElement.prototype._clearFlags = function (flags) {
  13503. this._flags &= ~flags;
  13504. };
  13505. /**
  13506. * Set the given flags to true state
  13507. * @param flags the flags ORed to set
  13508. * @return the flags state before this call
  13509. */
  13510. UIElement.prototype._setFlags = function (flags) {
  13511. var cur = this._flags;
  13512. this._flags |= flags;
  13513. return cur;
  13514. };
  13515. /**
  13516. * Change the state of the given flags
  13517. * @param flags the flags ORed to change
  13518. * @param state true to set them, false to clear them
  13519. */
  13520. UIElement.prototype._changeFlags = function (flags, state) {
  13521. if (state) {
  13522. this._flags |= flags;
  13523. }
  13524. else {
  13525. this._flags &= ~flags;
  13526. }
  13527. };
  13528. UIElement.prototype._assignTemplate = function (templateName) {
  13529. if (!templateName) {
  13530. templateName = UIElementRenderingTemplateManager.DefaultTemplateName;
  13531. }
  13532. var className = BABYLON.Tools.getFullClassName(this);
  13533. if (!className) {
  13534. throw Error("Couldn't access class name of this UIElement, you have to decorate the type with the className decorator");
  13535. }
  13536. var factory = UIElementRenderingTemplateManager.getRenderingTemplate(className, templateName);
  13537. if (!factory) {
  13538. throw Error("Couldn't get the renderingTemplate " + templateName + " of class " + className);
  13539. }
  13540. this._renderingTemplate = factory();
  13541. this._renderingTemplate.attach(this);
  13542. };
  13543. UIElement.prototype._createVisualTree = function () {
  13544. var parentPrim = this.ownerWindows.canvas;
  13545. if (this.parent) {
  13546. parentPrim = this.parent.visualChildrenPlaceholder;
  13547. }
  13548. this._visualPlaceholder = new BABYLON.Group2D({ parent: parentPrim, id: "GUI Visual Placeholder of " + this.id });
  13549. var p = this._visualPlaceholder;
  13550. p.addExternalData("_GUIOwnerElement_", this);
  13551. p.dataSource = this;
  13552. p.createSimpleDataBinding(BABYLON.Prim2DBase.widthProperty, "width", BABYLON.DataBinding.MODE_ONEWAY);
  13553. p.createSimpleDataBinding(BABYLON.Prim2DBase.heightProperty, "height", BABYLON.DataBinding.MODE_ONEWAY);
  13554. p.createSimpleDataBinding(BABYLON.Prim2DBase.actualWidthProperty, "actualWidth", BABYLON.DataBinding.MODE_ONEWAYTOSOURCE);
  13555. p.createSimpleDataBinding(BABYLON.Prim2DBase.actualHeightProperty, "actualHeight", BABYLON.DataBinding.MODE_ONEWAYTOSOURCE);
  13556. p.createSimpleDataBinding(BABYLON.Prim2DBase.marginProperty, "margin", BABYLON.DataBinding.MODE_ONEWAY);
  13557. p.createSimpleDataBinding(BABYLON.Prim2DBase.paddingProperty, "padding", BABYLON.DataBinding.MODE_ONEWAY);
  13558. p.createSimpleDataBinding(BABYLON.Prim2DBase.marginAlignmentProperty, "marginAlignment", BABYLON.DataBinding.MODE_ONEWAY);
  13559. this.createVisualTree();
  13560. };
  13561. UIElement.prototype._patchUIElement = function (ownerWindow, parent) {
  13562. if (ownerWindow) {
  13563. if (!this._ownerWindow) {
  13564. ownerWindow._registerVisualToBuild(this);
  13565. }
  13566. this._ownerWindow = ownerWindow;
  13567. }
  13568. this._parent = parent;
  13569. if (parent) {
  13570. this._hierarchyDepth = parent.hierarchyDepth + 1;
  13571. }
  13572. var children = this._getChildren();
  13573. if (children) {
  13574. for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
  13575. var curChild = children_1[_i];
  13576. curChild._patchUIElement(ownerWindow, this);
  13577. }
  13578. }
  13579. };
  13580. // Overload the SmartPropertyBase's method to provide the additional logic of returning the parent's dataSource if there's no dataSource specified at this level.
  13581. UIElement.prototype._getDataSource = function () {
  13582. var levelDS = _super.prototype._getDataSource.call(this);
  13583. if (levelDS != null) {
  13584. return levelDS;
  13585. }
  13586. var p = this.parent;
  13587. if (p != null) {
  13588. return p.dataSource;
  13589. }
  13590. return null;
  13591. };
  13592. UIElement.prototype.createVisualTree = function () {
  13593. var res = this._renderingTemplate.createVisualTree(this, this._visualPlaceholder);
  13594. this._visualTemplateRoot = res.root;
  13595. this._visualChildrenPlaceholder = res.contentPlaceholder;
  13596. };
  13597. Object.defineProperty(UIElement.prototype, "visualPlaceholder", {
  13598. get: function () {
  13599. return this._visualPlaceholder;
  13600. },
  13601. enumerable: true,
  13602. configurable: true
  13603. });
  13604. Object.defineProperty(UIElement.prototype, "visualTemplateRoot", {
  13605. get: function () {
  13606. return this._visualTemplateRoot;
  13607. },
  13608. enumerable: true,
  13609. configurable: true
  13610. });
  13611. Object.defineProperty(UIElement.prototype, "visualChildrenPlaceholder", {
  13612. get: function () {
  13613. return this._visualChildrenPlaceholder;
  13614. },
  13615. enumerable: true,
  13616. configurable: true
  13617. });
  13618. Object.defineProperty(UIElement.prototype, "_position", {
  13619. get: function () { return null; } // TODO use abstract keyword when TS 2.0 will be approved
  13620. ,
  13621. enumerable: true,
  13622. configurable: true
  13623. });
  13624. UIElement.UIELEMENT_PROPCOUNT = 15;
  13625. UIElement.flagVisualToBuild = 0x0000001; // set if the UIElement visual must be updated
  13626. __decorate([
  13627. BABYLON.dependencyProperty(0, function (pi) { return UIElement.parentProperty = pi; })
  13628. ], UIElement.prototype, "parent", null);
  13629. __decorate([
  13630. BABYLON.dependencyProperty(1, function (pi) { return UIElement.widthProperty = pi; })
  13631. ], UIElement.prototype, "width", null);
  13632. __decorate([
  13633. BABYLON.dependencyProperty(2, function (pi) { return UIElement.heightProperty = pi; })
  13634. ], UIElement.prototype, "height", null);
  13635. __decorate([
  13636. BABYLON.dependencyProperty(3, function (pi) { return UIElement.minWidthProperty = pi; })
  13637. ], UIElement.prototype, "minWidth", null);
  13638. __decorate([
  13639. BABYLON.dependencyProperty(4, function (pi) { return UIElement.minHeightProperty = pi; })
  13640. ], UIElement.prototype, "minHheight", null);
  13641. __decorate([
  13642. BABYLON.dependencyProperty(5, function (pi) { return UIElement.maxWidthProperty = pi; })
  13643. ], UIElement.prototype, "maxWidth", null);
  13644. __decorate([
  13645. BABYLON.dependencyProperty(6, function (pi) { return UIElement.maxHeightProperty = pi; })
  13646. ], UIElement.prototype, "maxHeight", null);
  13647. __decorate([
  13648. BABYLON.dependencyProperty(7, function (pi) { return UIElement.actualWidthProperty = pi; })
  13649. ], UIElement.prototype, "actualWidth", null);
  13650. __decorate([
  13651. BABYLON.dependencyProperty(8, function (pi) { return UIElement.actualHeightProperty = pi; })
  13652. ], UIElement.prototype, "actualHeight", null);
  13653. __decorate([
  13654. BABYLON.dynamicLevelProperty(9, function (pi) { return UIElement.marginProperty = pi; })
  13655. ], UIElement.prototype, "margin", null);
  13656. __decorate([
  13657. BABYLON.dynamicLevelProperty(10, function (pi) { return UIElement.paddingProperty = pi; })
  13658. ], UIElement.prototype, "padding", null);
  13659. __decorate([
  13660. BABYLON.dynamicLevelProperty(11, function (pi) { return UIElement.marginAlignmentProperty = pi; })
  13661. ], UIElement.prototype, "marginAlignment", null);
  13662. __decorate([
  13663. BABYLON.dynamicLevelProperty(12, function (pi) { return UIElement.isEnabledProperty = pi; })
  13664. ], UIElement.prototype, "isEnabled", null);
  13665. __decorate([
  13666. BABYLON.dynamicLevelProperty(13, function (pi) { return UIElement.isFocusedProperty = pi; })
  13667. ], UIElement.prototype, "isFocused", null);
  13668. __decorate([
  13669. BABYLON.dynamicLevelProperty(14, function (pi) { return UIElement.isMouseOverProperty = pi; })
  13670. ], UIElement.prototype, "isMouseOver", null);
  13671. return UIElement;
  13672. }(BABYLON.SmartPropertyBase));
  13673. BABYLON.UIElement = UIElement;
  13674. var UIElementStyle = (function () {
  13675. function UIElementStyle() {
  13676. }
  13677. Object.defineProperty(UIElementStyle.prototype, "name", {
  13678. get: function () { return null; } // TODO use abstract keyword when TS 2.0 will be approved
  13679. ,
  13680. enumerable: true,
  13681. configurable: true
  13682. });
  13683. return UIElementStyle;
  13684. }());
  13685. BABYLON.UIElementStyle = UIElementStyle;
  13686. var UIElementStyleManager = (function () {
  13687. function UIElementStyleManager() {
  13688. }
  13689. UIElementStyleManager.getStyle = function (uiElType, styleName) {
  13690. var styles = UIElementStyleManager.stylesByUIElement.get(uiElType);
  13691. if (!styles) {
  13692. throw Error("The type " + uiElType + " is unknown, no style were registered for it.");
  13693. }
  13694. var style = styles.get(styleName);
  13695. if (!style) {
  13696. throw Error("Couldn't find Template " + styleName + " of UIElement type " + uiElType);
  13697. }
  13698. return style;
  13699. };
  13700. UIElementStyleManager.registerStyle = function (uiElType, templateName, style) {
  13701. var templates = UIElementStyleManager.stylesByUIElement.getOrAddWithFactory(uiElType, function () { return new BABYLON.StringDictionary(); });
  13702. if (templates.contains(templateName)) {
  13703. templates[templateName] = style;
  13704. }
  13705. else {
  13706. templates.add(templateName, style);
  13707. }
  13708. };
  13709. Object.defineProperty(UIElementStyleManager, "DefaultStyleName", {
  13710. get: function () {
  13711. return UIElementStyleManager._defaultStyleName;
  13712. },
  13713. set: function (value) {
  13714. UIElementStyleManager._defaultStyleName = value;
  13715. },
  13716. enumerable: true,
  13717. configurable: true
  13718. });
  13719. UIElementStyleManager.stylesByUIElement = new BABYLON.StringDictionary();
  13720. UIElementStyleManager._defaultStyleName = "Default";
  13721. return UIElementStyleManager;
  13722. }());
  13723. BABYLON.UIElementStyleManager = UIElementStyleManager;
  13724. var UIElementRenderingTemplateManager = (function () {
  13725. function UIElementRenderingTemplateManager() {
  13726. }
  13727. UIElementRenderingTemplateManager.getRenderingTemplate = function (uiElType, templateName) {
  13728. var templates = UIElementRenderingTemplateManager.renderingTemplatesByUIElement.get(uiElType);
  13729. if (!templates) {
  13730. throw Error("The type " + uiElType + " is unknown, no Rendering Template were registered for it.");
  13731. }
  13732. var templateFactory = templates.get(templateName);
  13733. if (!templateFactory) {
  13734. throw Error("Couldn't find Template " + templateName + " of UI Element type " + uiElType);
  13735. }
  13736. return templateFactory;
  13737. };
  13738. UIElementRenderingTemplateManager.registerRenderingTemplate = function (uiElType, templateName, factory) {
  13739. var templates = UIElementRenderingTemplateManager.renderingTemplatesByUIElement.getOrAddWithFactory(uiElType, function () { return new BABYLON.StringDictionary(); });
  13740. if (templates.contains(templateName)) {
  13741. templates[templateName] = factory;
  13742. }
  13743. else {
  13744. templates.add(templateName, factory);
  13745. }
  13746. };
  13747. Object.defineProperty(UIElementRenderingTemplateManager, "DefaultTemplateName", {
  13748. get: function () {
  13749. return UIElementRenderingTemplateManager._defaultTemplateName;
  13750. },
  13751. set: function (value) {
  13752. UIElementRenderingTemplateManager._defaultTemplateName = value;
  13753. },
  13754. enumerable: true,
  13755. configurable: true
  13756. });
  13757. UIElementRenderingTemplateManager.renderingTemplatesByUIElement = new BABYLON.StringDictionary();
  13758. UIElementRenderingTemplateManager._defaultTemplateName = "Default";
  13759. return UIElementRenderingTemplateManager;
  13760. }());
  13761. BABYLON.UIElementRenderingTemplateManager = UIElementRenderingTemplateManager;
  13762. var UIElementRenderingTemplateBase = (function () {
  13763. function UIElementRenderingTemplateBase() {
  13764. }
  13765. UIElementRenderingTemplateBase.prototype.attach = function (owner) {
  13766. this._owner = owner;
  13767. };
  13768. UIElementRenderingTemplateBase.prototype.detach = function () {
  13769. };
  13770. Object.defineProperty(UIElementRenderingTemplateBase.prototype, "owner", {
  13771. get: function () {
  13772. return this._owner;
  13773. },
  13774. enumerable: true,
  13775. configurable: true
  13776. });
  13777. return UIElementRenderingTemplateBase;
  13778. }());
  13779. BABYLON.UIElementRenderingTemplateBase = UIElementRenderingTemplateBase;
  13780. function registerWindowRenderingTemplate(uiElType, templateName, factory) {
  13781. return function () {
  13782. UIElementRenderingTemplateManager.registerRenderingTemplate(uiElType, templateName, factory);
  13783. };
  13784. }
  13785. BABYLON.registerWindowRenderingTemplate = registerWindowRenderingTemplate;
  13786. })(BABYLON || (BABYLON = {}));
  13787. var BABYLON;
  13788. (function (BABYLON) {
  13789. var Control = (function (_super) {
  13790. __extends(Control, _super);
  13791. function Control(settings) {
  13792. _super.call(this, settings);
  13793. }
  13794. Object.defineProperty(Control.prototype, "background", {
  13795. get: function () {
  13796. if (!this._background) {
  13797. this._background = new BABYLON.ObservableStringDictionary(false);
  13798. }
  13799. return this._background;
  13800. },
  13801. set: function (value) {
  13802. this.background.copyFrom(value);
  13803. },
  13804. enumerable: true,
  13805. configurable: true
  13806. });
  13807. Object.defineProperty(Control.prototype, "border", {
  13808. get: function () {
  13809. return this._border;
  13810. },
  13811. set: function (value) {
  13812. this._border = value;
  13813. },
  13814. enumerable: true,
  13815. configurable: true
  13816. });
  13817. Object.defineProperty(Control.prototype, "borderThickness", {
  13818. get: function () {
  13819. return this._borderThickness;
  13820. },
  13821. set: function (value) {
  13822. this._borderThickness = value;
  13823. },
  13824. enumerable: true,
  13825. configurable: true
  13826. });
  13827. Object.defineProperty(Control.prototype, "fontName", {
  13828. get: function () {
  13829. return this._fontName;
  13830. },
  13831. set: function (value) {
  13832. this._fontName = value;
  13833. },
  13834. enumerable: true,
  13835. configurable: true
  13836. });
  13837. Object.defineProperty(Control.prototype, "foreground", {
  13838. get: function () {
  13839. return this._foreground;
  13840. },
  13841. set: function (value) {
  13842. this._foreground = value;
  13843. },
  13844. enumerable: true,
  13845. configurable: true
  13846. });
  13847. Control.CONTROL_PROPCOUNT = BABYLON.UIElement.UIELEMENT_PROPCOUNT + 5;
  13848. __decorate([
  13849. BABYLON.dependencyProperty(BABYLON.UIElement.UIELEMENT_PROPCOUNT + 0, function (pi) { return Control.backgroundProperty = pi; })
  13850. ], Control.prototype, "background", null);
  13851. __decorate([
  13852. BABYLON.dependencyProperty(BABYLON.UIElement.UIELEMENT_PROPCOUNT + 1, function (pi) { return Control.borderProperty = pi; })
  13853. ], Control.prototype, "border", null);
  13854. __decorate([
  13855. BABYLON.dependencyProperty(BABYLON.UIElement.UIELEMENT_PROPCOUNT + 2, function (pi) { return Control.borderThicknessProperty = pi; })
  13856. ], Control.prototype, "borderThickness", null);
  13857. __decorate([
  13858. BABYLON.dependencyProperty(BABYLON.UIElement.UIELEMENT_PROPCOUNT + 3, function (pi) { return Control.fontNameProperty = pi; })
  13859. ], Control.prototype, "fontName", null);
  13860. __decorate([
  13861. BABYLON.dependencyProperty(BABYLON.UIElement.UIELEMENT_PROPCOUNT + 4, function (pi) { return Control.foregroundProperty = pi; })
  13862. ], Control.prototype, "foreground", null);
  13863. Control = __decorate([
  13864. BABYLON.className("Control", "BABYLON")
  13865. ], Control);
  13866. return Control;
  13867. }(BABYLON.UIElement));
  13868. BABYLON.Control = Control;
  13869. var ContentControl = (function (_super) {
  13870. __extends(ContentControl, _super);
  13871. function ContentControl(settings) {
  13872. if (!settings) {
  13873. settings = {};
  13874. }
  13875. _super.call(this, settings);
  13876. if (settings.content != null) {
  13877. this._content = settings.content;
  13878. }
  13879. if (settings.contentAlignment != null) {
  13880. this.contentAlignment.fromString(settings.contentAlignment);
  13881. }
  13882. }
  13883. ContentControl.prototype.dispose = function () {
  13884. if (this.isDisposed) {
  13885. return false;
  13886. }
  13887. if (this.content && this.content.dispose) {
  13888. this.content.dispose();
  13889. this.content = null;
  13890. }
  13891. if (this.__contentUIElement) {
  13892. this.__contentUIElement.dispose();
  13893. this.__contentUIElement = null;
  13894. }
  13895. _super.prototype.dispose.call(this);
  13896. return true;
  13897. };
  13898. Object.defineProperty(ContentControl.prototype, "content", {
  13899. get: function () {
  13900. return this._content;
  13901. },
  13902. set: function (value) {
  13903. this._content = value;
  13904. },
  13905. enumerable: true,
  13906. configurable: true
  13907. });
  13908. Object.defineProperty(ContentControl.prototype, "contentAlignment", {
  13909. get: function () {
  13910. if (!this._contentAlignment) {
  13911. this._contentAlignment = new BABYLON.PrimitiveAlignment();
  13912. }
  13913. return this._contentAlignment;
  13914. },
  13915. set: function (value) {
  13916. this.contentAlignment.copyFrom(value);
  13917. },
  13918. enumerable: true,
  13919. configurable: true
  13920. });
  13921. Object.defineProperty(ContentControl.prototype, "_hasContentAlignment", {
  13922. /**
  13923. * Check if there a contentAlignment specified (non null and not default)
  13924. */
  13925. get: function () {
  13926. return (this._contentAlignment !== null && !this._contentAlignment.isDefault);
  13927. },
  13928. enumerable: true,
  13929. configurable: true
  13930. });
  13931. Object.defineProperty(ContentControl.prototype, "_contentUIElement", {
  13932. get: function () {
  13933. if (!this.__contentUIElement) {
  13934. this._buildContentUIElement();
  13935. }
  13936. return this.__contentUIElement;
  13937. },
  13938. enumerable: true,
  13939. configurable: true
  13940. });
  13941. ContentControl.prototype._buildContentUIElement = function () {
  13942. var c = this._content;
  13943. this.__contentUIElement = null;
  13944. // Already a UIElement
  13945. if (c instanceof BABYLON.UIElement) {
  13946. this.__contentUIElement = c;
  13947. }
  13948. else if ((typeof c === "string") || (typeof c === "boolean") || (typeof c === "number")) {
  13949. var l = new BABYLON.Label({ parent: this, id: "Content of " + this.id });
  13950. var binding = new BABYLON.DataBinding();
  13951. binding.propertyPathName = "content";
  13952. binding.stringFormat = function (v) { return ("" + v); };
  13953. binding.dataSource = this;
  13954. l.createDataBinding(BABYLON.Label.textProperty, binding);
  13955. binding = new BABYLON.DataBinding();
  13956. binding.propertyPathName = "contentAlignment";
  13957. binding.dataSource = this;
  13958. l.createDataBinding(BABYLON.Label.marginAlignmentProperty, binding);
  13959. this.__contentUIElement = l;
  13960. }
  13961. else {
  13962. }
  13963. if (this.__contentUIElement) {
  13964. this.__contentUIElement._patchUIElement(this.ownerWindows, this);
  13965. }
  13966. };
  13967. ContentControl.prototype._getChildren = function () {
  13968. var children = new Array();
  13969. if (this.content) {
  13970. children.push(this._contentUIElement);
  13971. }
  13972. return children;
  13973. };
  13974. ContentControl.CONTENTCONTROL_PROPCOUNT = Control.CONTROL_PROPCOUNT + 2;
  13975. __decorate([
  13976. BABYLON.dependencyProperty(Control.CONTROL_PROPCOUNT + 0, function (pi) { return ContentControl.contentProperty = pi; })
  13977. ], ContentControl.prototype, "content", null);
  13978. __decorate([
  13979. BABYLON.dependencyProperty(Control.CONTROL_PROPCOUNT + 1, function (pi) { return ContentControl.contentAlignmentProperty = pi; })
  13980. ], ContentControl.prototype, "contentAlignment", null);
  13981. ContentControl = __decorate([
  13982. BABYLON.className("ContentControl", "BABYLON")
  13983. ], ContentControl);
  13984. return ContentControl;
  13985. }(Control));
  13986. BABYLON.ContentControl = ContentControl;
  13987. })(BABYLON || (BABYLON = {}));
  13988. var BABYLON;
  13989. (function (BABYLON) {
  13990. var Window = (function (_super) {
  13991. __extends(Window, _super);
  13992. function Window(scene, settings) {
  13993. var _this = this;
  13994. if (!settings) {
  13995. settings = {};
  13996. }
  13997. _super.call(this, settings);
  13998. if (!this._UIElementVisualToBuildList) {
  13999. this._UIElementVisualToBuildList = new Array();
  14000. }
  14001. // Patch the owner and also the parent property through the whole tree
  14002. this._patchUIElement(this, null);
  14003. // Screen Space UI
  14004. if (!settings.worldPosition && !settings.worldRotation) {
  14005. this._canvas = Window.getScreenCanvas(scene);
  14006. this._isWorldSpaceCanvas = false;
  14007. this._left = (settings.left != null) ? settings.left : 0;
  14008. this._bottom = (settings.bottom != null) ? settings.bottom : 0;
  14009. }
  14010. else {
  14011. var w = (settings.width == null) ? 100 : settings.width;
  14012. var h = (settings.height == null) ? 100 : settings.height;
  14013. var wpos = (settings.worldPosition == null) ? BABYLON.Vector3.Zero() : settings.worldPosition;
  14014. var wrot = (settings.worldRotation == null) ? BABYLON.Quaternion.Identity() : settings.worldRotation;
  14015. this._canvas = new BABYLON.WorldSpaceCanvas2D(scene, new BABYLON.Size(w, h), { id: "GUI Canvas", cachingStrategy: BABYLON.Canvas2D.CACHESTRATEGY_DONTCACHE, worldPosition: wpos, worldRotation: wrot });
  14016. this._isWorldSpaceCanvas = true;
  14017. }
  14018. this._renderObserver = this._canvas.renderObservable.add(function (e, s) { return _this._canvasPreRender(); }, BABYLON.Canvas2D.RENDEROBSERVABLE_PRE);
  14019. this._disposeObserver = this._canvas.disposeObservable.add(function (e, s) { return _this._canvasDisposed(); });
  14020. this._canvas.propertyChanged.add(function (e, s) {
  14021. if (e.propertyName === "overPrim") {
  14022. _this._overPrimChanged(e.oldValue, e.newValue);
  14023. }
  14024. });
  14025. this._mouseOverUIElement = null;
  14026. }
  14027. Object.defineProperty(Window.prototype, "canvas", {
  14028. get: function () {
  14029. return this._canvas;
  14030. },
  14031. enumerable: true,
  14032. configurable: true
  14033. });
  14034. Object.defineProperty(Window.prototype, "left", {
  14035. get: function () {
  14036. return this._left;
  14037. },
  14038. set: function (value) {
  14039. var old = new BABYLON.Vector2(this._left, this._bottom);
  14040. this._left = value;
  14041. this.onPropertyChanged("_position", old, this._position);
  14042. },
  14043. enumerable: true,
  14044. configurable: true
  14045. });
  14046. Object.defineProperty(Window.prototype, "bottom", {
  14047. get: function () {
  14048. return this._bottom;
  14049. },
  14050. set: function (value) {
  14051. var old = new BABYLON.Vector2(this._left, this._bottom);
  14052. this._bottom = value;
  14053. this.onPropertyChanged("_position", old, this._position);
  14054. },
  14055. enumerable: true,
  14056. configurable: true
  14057. });
  14058. Object.defineProperty(Window.prototype, "position", {
  14059. get: function () {
  14060. return this._position;
  14061. },
  14062. set: function (value) {
  14063. this._left = value.x;
  14064. this._bottom = value.y;
  14065. },
  14066. enumerable: true,
  14067. configurable: true
  14068. });
  14069. Object.defineProperty(Window.prototype, "_position", {
  14070. get: function () {
  14071. return new BABYLON.Vector2(this.left, this.bottom);
  14072. },
  14073. enumerable: true,
  14074. configurable: true
  14075. });
  14076. Window.prototype.createVisualTree = function () {
  14077. _super.prototype.createVisualTree.call(this);
  14078. var p = this._visualPlaceholder;
  14079. p.createSimpleDataBinding(BABYLON.Group2D.positionProperty, "position");
  14080. };
  14081. Window.prototype._registerVisualToBuild = function (uiel) {
  14082. if (uiel._isFlagSet(BABYLON.UIElement.flagVisualToBuild)) {
  14083. return;
  14084. }
  14085. if (!this._UIElementVisualToBuildList) {
  14086. this._UIElementVisualToBuildList = new Array();
  14087. }
  14088. this._UIElementVisualToBuildList.push(uiel);
  14089. uiel._setFlags(BABYLON.UIElement.flagVisualToBuild);
  14090. };
  14091. Window.prototype._overPrimChanged = function (oldPrim, newPrim) {
  14092. var curOverEl = this._mouseOverUIElement;
  14093. var newOverEl = null;
  14094. var curGroup = newPrim ? newPrim.traverseUp(function (p) { return p instanceof BABYLON.Group2D; }) : null;
  14095. while (curGroup) {
  14096. var uiel = curGroup.getExternalData("_GUIOwnerElement_");
  14097. if (uiel) {
  14098. newOverEl = uiel;
  14099. break;
  14100. }
  14101. curGroup = curGroup.parent ? curGroup.parent.traverseUp(function (p) { return p instanceof BABYLON.Group2D; }) : null;
  14102. }
  14103. if (curOverEl === newOverEl) {
  14104. return;
  14105. }
  14106. if (curOverEl) {
  14107. curOverEl.isMouseOver = false;
  14108. }
  14109. if (newOverEl) {
  14110. newOverEl.isMouseOver = true;
  14111. }
  14112. this._mouseOverUIElement = newOverEl;
  14113. };
  14114. Window.prototype._canvasPreRender = function () {
  14115. // Check if we have visual to create
  14116. if (this._UIElementVisualToBuildList.length > 0) {
  14117. // Sort the UI Element to get the highest (so lowest hierarchy depth) in the hierarchy tree first
  14118. var sortedElementList = this._UIElementVisualToBuildList.sort(function (a, b) { return a.hierarchyDepth - b.hierarchyDepth; });
  14119. for (var _i = 0, sortedElementList_1 = sortedElementList; _i < sortedElementList_1.length; _i++) {
  14120. var el = sortedElementList_1[_i];
  14121. el._createVisualTree();
  14122. }
  14123. this._UIElementVisualToBuildList.splice(0);
  14124. }
  14125. };
  14126. Window.prototype._canvasDisposed = function () {
  14127. this._canvas.disposeObservable.remove(this._disposeObserver);
  14128. this._canvas.renderObservable.remove(this._renderObserver);
  14129. };
  14130. Window.getScreenCanvas = function (scene) {
  14131. var canvas = BABYLON.Tools.first(Window._screenCanvasList, function (c) { return c.scene === scene; });
  14132. if (canvas) {
  14133. return canvas;
  14134. }
  14135. canvas = new BABYLON.ScreenSpaceCanvas2D(scene, { id: "GUI Canvas", cachingStrategy: BABYLON.Canvas2D.CACHESTRATEGY_DONTCACHE });
  14136. Window._screenCanvasList.push(canvas);
  14137. return canvas;
  14138. };
  14139. Window.WINDOW_PROPCOUNT = BABYLON.ContentControl.CONTENTCONTROL_PROPCOUNT + 2;
  14140. Window._screenCanvasList = new Array();
  14141. __decorate([
  14142. BABYLON.dependencyProperty(BABYLON.ContentControl.CONTENTCONTROL_PROPCOUNT + 0, function (pi) { return Window.leftProperty = pi; })
  14143. ], Window.prototype, "left", null);
  14144. __decorate([
  14145. BABYLON.dependencyProperty(BABYLON.ContentControl.CONTENTCONTROL_PROPCOUNT + 1, function (pi) { return Window.bottomProperty = pi; })
  14146. ], Window.prototype, "bottom", null);
  14147. __decorate([
  14148. BABYLON.dependencyProperty(BABYLON.ContentControl.CONTENTCONTROL_PROPCOUNT + 2, function (pi) { return Window.positionProperty = pi; })
  14149. ], Window.prototype, "position", null);
  14150. Window = __decorate([
  14151. BABYLON.className("Window", "BABYLON")
  14152. ], Window);
  14153. return Window;
  14154. }(BABYLON.ContentControl));
  14155. BABYLON.Window = Window;
  14156. var DefaultWindowRenderingTemplate = (function (_super) {
  14157. __extends(DefaultWindowRenderingTemplate, _super);
  14158. function DefaultWindowRenderingTemplate() {
  14159. _super.apply(this, arguments);
  14160. }
  14161. DefaultWindowRenderingTemplate.prototype.createVisualTree = function (owner, visualPlaceholder) {
  14162. var r = new BABYLON.Rectangle2D({ parent: visualPlaceholder, fill: "#808080FF" });
  14163. return { root: r, contentPlaceholder: r };
  14164. };
  14165. DefaultWindowRenderingTemplate = __decorate([
  14166. BABYLON.registerWindowRenderingTemplate("BABYLON.Window", "Default", function () { return new DefaultWindowRenderingTemplate(); })
  14167. ], DefaultWindowRenderingTemplate);
  14168. return DefaultWindowRenderingTemplate;
  14169. }(BABYLON.UIElementRenderingTemplateBase));
  14170. BABYLON.DefaultWindowRenderingTemplate = DefaultWindowRenderingTemplate;
  14171. })(BABYLON || (BABYLON = {}));
  14172. var BABYLON;
  14173. (function (BABYLON) {
  14174. var Label = (function (_super) {
  14175. __extends(Label, _super);
  14176. function Label(settings) {
  14177. if (!settings) {
  14178. settings = {};
  14179. }
  14180. _super.call(this, settings);
  14181. if (settings.text != null) {
  14182. this.text = settings.text;
  14183. }
  14184. }
  14185. Object.defineProperty(Label.prototype, "_position", {
  14186. get: function () {
  14187. return BABYLON.Vector2.Zero();
  14188. },
  14189. enumerable: true,
  14190. configurable: true
  14191. });
  14192. Label.prototype._getChildren = function () {
  14193. return Label._emptyArray;
  14194. };
  14195. Label.prototype.createVisualTree = function () {
  14196. _super.prototype.createVisualTree.call(this);
  14197. var p = this._visualChildrenPlaceholder;
  14198. };
  14199. Object.defineProperty(Label.prototype, "text", {
  14200. get: function () {
  14201. return this._text;
  14202. },
  14203. set: function (value) {
  14204. this._text = value;
  14205. },
  14206. enumerable: true,
  14207. configurable: true
  14208. });
  14209. Label._emptyArray = new Array();
  14210. __decorate([
  14211. BABYLON.dependencyProperty(BABYLON.Control.CONTROL_PROPCOUNT + 0, function (pi) { return Label.textProperty = pi; })
  14212. ], Label.prototype, "text", null);
  14213. Label = __decorate([
  14214. BABYLON.className("Label", "BABYLON")
  14215. ], Label);
  14216. return Label;
  14217. }(BABYLON.Control));
  14218. BABYLON.Label = Label;
  14219. var DefaultLabelRenderingTemplate = (function (_super) {
  14220. __extends(DefaultLabelRenderingTemplate, _super);
  14221. function DefaultLabelRenderingTemplate() {
  14222. _super.apply(this, arguments);
  14223. }
  14224. DefaultLabelRenderingTemplate.prototype.createVisualTree = function (owner, visualPlaceholder) {
  14225. var r = new BABYLON.Text2D("", { parent: visualPlaceholder });
  14226. r.createSimpleDataBinding(BABYLON.Text2D.textProperty, "text");
  14227. r.dataSource = owner;
  14228. return { root: r, contentPlaceholder: r };
  14229. };
  14230. DefaultLabelRenderingTemplate = __decorate([
  14231. BABYLON.registerWindowRenderingTemplate("BABYLON.Label", "Default", function () { return new DefaultLabelRenderingTemplate(); })
  14232. ], DefaultLabelRenderingTemplate);
  14233. return DefaultLabelRenderingTemplate;
  14234. }(BABYLON.UIElementRenderingTemplateBase));
  14235. BABYLON.DefaultLabelRenderingTemplate = DefaultLabelRenderingTemplate;
  14236. })(BABYLON || (BABYLON = {}));
  14237. var BABYLON;
  14238. (function (BABYLON) {
  14239. var Button = (function (_super) {
  14240. __extends(Button, _super);
  14241. function Button(settings) {
  14242. if (!settings) {
  14243. settings = {};
  14244. }
  14245. _super.call(this, settings);
  14246. // For a button the default contentAlignemnt is center/center
  14247. if (settings.contentAlignment == null) {
  14248. this.contentAlignment.horizontal = BABYLON.PrimitiveAlignment.AlignCenter;
  14249. this.contentAlignment.vertical = BABYLON.PrimitiveAlignment.AlignCenter;
  14250. }
  14251. this.normalEnabledBackground = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#337AB7FF");
  14252. this.normalDisabledBackground = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#7BA9D0FF");
  14253. this.normalMouseOverBackground = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#286090FF");
  14254. this.normalPushedBackground = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#1E496EFF");
  14255. this.normalEnabledBorder = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#2E6DA4FF");
  14256. this.normalDisabledBorder = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#77A0C4FF");
  14257. this.normalMouseOverBorder = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#204D74FF");
  14258. this.normalPushedBorder = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#2E5D9EFF");
  14259. this.defaultEnabledBackground = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#FFFFFFFF");
  14260. this.defaultDisabledBackground = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#FFFFFFFF");
  14261. this.defaultMouseOverBackground = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#E6E6E6FF");
  14262. this.defaultPushedBackground = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#D4D4D4FF");
  14263. this.defaultEnabledBorder = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#CCCCCCFF");
  14264. this.defaultDisabledBorder = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#DEDEDEFF");
  14265. this.defaultMouseOverBorder = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#ADADADFF");
  14266. this.defaultPushedBorder = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#6C8EC5FF");
  14267. }
  14268. Object.defineProperty(Button.prototype, "isPushed", {
  14269. get: function () {
  14270. return this._isPushed;
  14271. },
  14272. set: function (value) {
  14273. this._isPushed = value;
  14274. },
  14275. enumerable: true,
  14276. configurable: true
  14277. });
  14278. Object.defineProperty(Button.prototype, "isDefault", {
  14279. get: function () {
  14280. return this._isDefault;
  14281. },
  14282. set: function (value) {
  14283. this._isDefault = value;
  14284. },
  14285. enumerable: true,
  14286. configurable: true
  14287. });
  14288. Object.defineProperty(Button.prototype, "isOutline", {
  14289. get: function () {
  14290. return this._isOutline;
  14291. },
  14292. set: function (value) {
  14293. this._isOutline = value;
  14294. },
  14295. enumerable: true,
  14296. configurable: true
  14297. });
  14298. Object.defineProperty(Button.prototype, "clickObservable", {
  14299. get: function () {
  14300. if (!this._clickObservable) {
  14301. this._clickObservable = new BABYLON.Observable();
  14302. }
  14303. return this._clickObservable;
  14304. },
  14305. enumerable: true,
  14306. configurable: true
  14307. });
  14308. Button.prototype._raiseClick = function () {
  14309. console.log("click");
  14310. };
  14311. Button.prototype.createVisualTree = function () {
  14312. var _this = this;
  14313. _super.prototype.createVisualTree.call(this);
  14314. var p = this._visualPlaceholder;
  14315. p.pointerEventObservable.add(function (e, s) {
  14316. // We reject an event coming from the placeholder because it means it's on an empty spot, so it's not valid.
  14317. if (e.relatedTarget === _this._visualPlaceholder) {
  14318. return;
  14319. }
  14320. if (s.mask === BABYLON.PrimitivePointerInfo.PointerUp) {
  14321. _this._raiseClick();
  14322. _this.isPushed = false;
  14323. }
  14324. else if (s.mask === BABYLON.PrimitivePointerInfo.PointerDown) {
  14325. _this.isPushed = true;
  14326. }
  14327. }, BABYLON.PrimitivePointerInfo.PointerUp | BABYLON.PrimitivePointerInfo.PointerDown);
  14328. };
  14329. Object.defineProperty(Button.prototype, "_position", {
  14330. get: function () {
  14331. return BABYLON.Vector2.Zero();
  14332. },
  14333. enumerable: true,
  14334. configurable: true
  14335. });
  14336. Button.BUTTON_PROPCOUNT = BABYLON.ContentControl.CONTENTCONTROL_PROPCOUNT + 3;
  14337. __decorate([
  14338. BABYLON.dependencyProperty(BABYLON.ContentControl.CONTROL_PROPCOUNT + 0, function (pi) { return Button.isPushedProperty = pi; })
  14339. ], Button.prototype, "isPushed", null);
  14340. __decorate([
  14341. BABYLON.dependencyProperty(BABYLON.ContentControl.CONTROL_PROPCOUNT + 1, function (pi) { return Button.isDefaultProperty = pi; })
  14342. ], Button.prototype, "isDefault", null);
  14343. __decorate([
  14344. BABYLON.dependencyProperty(BABYLON.ContentControl.CONTROL_PROPCOUNT + 2, function (pi) { return Button.isOutlineProperty = pi; })
  14345. ], Button.prototype, "isOutline", null);
  14346. Button = __decorate([
  14347. BABYLON.className("Button", "BABYLON")
  14348. ], Button);
  14349. return Button;
  14350. }(BABYLON.ContentControl));
  14351. BABYLON.Button = Button;
  14352. var DefaultButtonRenderingTemplate = (function (_super) {
  14353. __extends(DefaultButtonRenderingTemplate, _super);
  14354. function DefaultButtonRenderingTemplate() {
  14355. _super.apply(this, arguments);
  14356. }
  14357. DefaultButtonRenderingTemplate.prototype.createVisualTree = function (owner, visualPlaceholder) {
  14358. this._rect = new BABYLON.Rectangle2D({ parent: visualPlaceholder, fill: "#FF8080FF", border: "#FF8080FF", roundRadius: 10, borderThickness: 2 });
  14359. this.stateChange();
  14360. return { root: this._rect, contentPlaceholder: this._rect };
  14361. };
  14362. DefaultButtonRenderingTemplate.prototype.attach = function (owner) {
  14363. var _this = this;
  14364. _super.prototype.attach.call(this, owner);
  14365. this.owner.propertyChanged.add(function (e, s) { return _this.stateChange(); }, BABYLON.UIElement.isEnabledProperty.flagId |
  14366. BABYLON.UIElement.isFocusedProperty.flagId |
  14367. BABYLON.UIElement.isMouseOverProperty.flagId |
  14368. Button.isDefaultProperty.flagId |
  14369. Button.isOutlineProperty.flagId |
  14370. Button.isPushedProperty.flagId);
  14371. };
  14372. DefaultButtonRenderingTemplate.prototype.stateChange = function () {
  14373. var b = this.owner;
  14374. var bg = b.isDefault ? b.defaultEnabledBackground : b.normalEnabledBackground;
  14375. var bd = b.isDefault ? b.defaultEnabledBorder : b.normalEnabledBorder;
  14376. if (b.isPushed) {
  14377. if (b.isDefault) {
  14378. bg = b.defaultPushedBackground;
  14379. bd = b.defaultPushedBorder;
  14380. }
  14381. else {
  14382. bg = b.normalPushedBackground;
  14383. bd = b.normalPushedBorder;
  14384. }
  14385. }
  14386. else if (b.isMouseOver) {
  14387. console.log("MouseOver Style");
  14388. if (b.isDefault) {
  14389. bg = b.defaultMouseOverBackground;
  14390. bd = b.defaultMouseOverBorder;
  14391. }
  14392. else {
  14393. bg = b.normalMouseOverBackground;
  14394. bd = b.normalMouseOverBorder;
  14395. }
  14396. }
  14397. else if (!b.isEnabled) {
  14398. if (b.isDefault) {
  14399. bg = b.defaultDisabledBackground;
  14400. bd = b.defaultDisabledBorder;
  14401. }
  14402. else {
  14403. bg = b.normalDisabledBackground;
  14404. bd = b.normalDisabledBorder;
  14405. }
  14406. }
  14407. this._rect.fill = bg;
  14408. this._rect.border = bd;
  14409. };
  14410. DefaultButtonRenderingTemplate = __decorate([
  14411. BABYLON.registerWindowRenderingTemplate("BABYLON.Button", "Default", function () { return new DefaultButtonRenderingTemplate(); })
  14412. ], DefaultButtonRenderingTemplate);
  14413. return DefaultButtonRenderingTemplate;
  14414. }(BABYLON.UIElementRenderingTemplateBase));
  14415. BABYLON.DefaultButtonRenderingTemplate = DefaultButtonRenderingTemplate;
  14416. })(BABYLON || (BABYLON = {}));
  14417. BABYLON.Effect.ShadersStore['ellipse2dPixelShader'] = "varying vec4 vColor;\nvoid main(void) {\ngl_FragColor=vColor;\n}";
  14418. BABYLON.Effect.ShadersStore['ellipse2dVertexShader'] = "\n#ifdef Instanced\n#define att attribute\n#else\n#define att uniform\n#endif\nattribute float index;\natt vec2 zBias;\natt vec4 transformX;\natt vec4 transformY;\natt float opacity;\n#ifdef Border\natt float borderThickness;\n#endif\n#ifdef FillSolid\natt vec4 fillSolidColor;\n#endif\n#ifdef BorderSolid\natt vec4 borderSolidColor;\n#endif\n#ifdef FillGradient\natt vec4 fillGradientColor1;\natt vec4 fillGradientColor2;\natt vec4 fillGradientTY;\n#endif\n#ifdef BorderGradient\natt vec4 borderGradientColor1;\natt vec4 borderGradientColor2;\natt vec4 borderGradientTY;\n#endif\n\natt vec3 properties;\n#define TWOPI 6.28318530\n\nvarying vec2 vUV;\nvarying vec4 vColor;\nvoid main(void) {\nvec2 pos2;\n#ifdef Border\nfloat w=properties.x;\nfloat h=properties.y;\nfloat ms=properties.z;\nvec2 borderOffset=vec2(1.0,1.0);\nfloat segi=index;\nif (index<ms) {\nborderOffset=vec2(1.0-(borderThickness*2.0/w),1.0-(borderThickness*2.0/h));\n}\nelse {\nsegi-=ms;\n}\nfloat angle=TWOPI*segi/ms;\npos2.x=(cos(angle)/2.0)+0.5;\npos2.y=(sin(angle)/2.0)+0.5;\npos2.x=((pos2.x-0.5)*borderOffset.x)+0.5;\npos2.y=((pos2.y-0.5)*borderOffset.y)+0.5;\n#else\nif (index == 0.0) {\npos2=vec2(0.5,0.5);\n}\nelse {\nfloat ms=properties.z;\nfloat angle=TWOPI*(index-1.0)/ms;\npos2.x=(cos(angle)/2.0)+0.5;\npos2.y=(sin(angle)/2.0)+0.5;\n}\n#endif\n#ifdef FillSolid\nvColor=fillSolidColor;\n#endif\n#ifdef BorderSolid\nvColor=borderSolidColor;\n#endif\n#ifdef FillGradient\nfloat v=dot(vec4(pos2.xy,1,1),fillGradientTY);\nvColor=mix(fillGradientColor2,fillGradientColor1,v); \n#endif\n#ifdef BorderGradient\nfloat v=dot(vec4(pos2.xy,1,1),borderGradientTY);\nvColor=mix(borderGradientColor2,borderGradientColor1,v); \n#endif\nvColor.a*=opacity;\nvec4 pos;\npos.xy=pos2.xy*properties.xy;\npos.z=1.0;\npos.w=1.0;\ngl_Position=vec4(dot(pos,transformX),dot(pos,transformY),zBias.x,1);\n}";
  14419. BABYLON.Effect.ShadersStore['lines2dPixelShader'] = "varying vec4 vColor;\nvoid main(void) {\ngl_FragColor=vColor;\n}";
  14420. BABYLON.Effect.ShadersStore['lines2dVertexShader'] = "\n#ifdef Instanced\n#define att attribute\n#else\n#define att uniform\n#endif\nattribute vec2 position;\natt vec2 zBias;\natt vec4 transformX;\natt vec4 transformY;\natt float opacity;\n#ifdef FillSolid\natt vec4 fillSolidColor;\n#endif\n#ifdef BorderSolid\natt vec4 borderSolidColor;\n#endif\n#ifdef FillGradient\natt vec2 boundingMin;\natt vec2 boundingMax;\natt vec4 fillGradientColor1;\natt vec4 fillGradientColor2;\natt vec4 fillGradientTY;\n#endif\n#ifdef BorderGradient\natt vec4 borderGradientColor1;\natt vec4 borderGradientColor2;\natt vec4 borderGradientTY;\n#endif\n#define TWOPI 6.28318530\n\nvarying vec2 vUV;\nvarying vec4 vColor;\nvoid main(void) {\n#ifdef FillSolid\nvColor=fillSolidColor;\n#endif\n#ifdef BorderSolid\nvColor=borderSolidColor;\n#endif\n#ifdef FillGradient\nfloat v=dot(vec4((position.xy-boundingMin)/(boundingMax-boundingMin),1,1),fillGradientTY);\nvColor=mix(fillGradientColor2,fillGradientColor1,v); \n#endif\n#ifdef BorderGradient\nfloat v=dot(vec4((position.xy-boundingMin)/(boundingMax-boundingMin),1,1),borderGradientTY);\nvColor=mix(borderGradientColor2,borderGradientColor1,v); \n#endif\nvColor.a*=opacity;\nvec4 pos;\npos.xy=position.xy;\npos.z=1.0;\npos.w=1.0;\ngl_Position=vec4(dot(pos,transformX),dot(pos,transformY),zBias.x,1);\n}";
  14421. BABYLON.Effect.ShadersStore['rect2dPixelShader'] = "varying vec4 vColor;\nvoid main(void) {\ngl_FragColor=vColor;\n}";
  14422. BABYLON.Effect.ShadersStore['rect2dVertexShader'] = "\n#ifdef Instanced\n#define att attribute\n#else\n#define att uniform\n#endif\nattribute float index;\natt vec2 zBias;\natt vec4 transformX;\natt vec4 transformY;\natt float opacity;\n#ifdef Border\natt float borderThickness;\n#endif\n#ifdef FillSolid\natt vec4 fillSolidColor;\n#endif\n#ifdef BorderSolid\natt vec4 borderSolidColor;\n#endif\n#ifdef FillGradient\natt vec4 fillGradientColor1;\natt vec4 fillGradientColor2;\natt vec4 fillGradientTY;\n#endif\n#ifdef BorderGradient\natt vec4 borderGradientColor1;\natt vec4 borderGradientColor2;\natt vec4 borderGradientTY;\n#endif\n\natt vec3 properties;\n\n#define rsub0 17.0\n#define rsub1 33.0\n#define rsub2 49.0\n#define rsub3 65.0\n#define rsub 64.0\n#define TWOPI 6.28318530\n\nvarying vec2 vUV;\nvarying vec4 vColor;\nvoid main(void) {\nvec2 pos2;\n\nif (properties.z == 0.0) {\n#ifdef Border\nfloat w=properties.x;\nfloat h=properties.y;\nvec2 borderOffset=vec2(1.0,1.0);\nfloat segi=index;\nif (index<4.0) {\nborderOffset=vec2(1.0-(borderThickness*2.0/w),1.0-(borderThickness*2.0/h));\n}\nelse {\nsegi-=4.0;\n}\nif (segi == 0.0) {\npos2=vec2(1.0,1.0);\n} \nelse if (segi == 1.0) {\npos2=vec2(1.0,0.0);\n}\nelse if (segi == 2.0) {\npos2=vec2(0.0,0.0);\n} \nelse {\npos2=vec2(0.0,1.0);\n}\npos2.x=((pos2.x-0.5)*borderOffset.x)+0.5;\npos2.y=((pos2.y-0.5)*borderOffset.y)+0.5;\n#else\nif (index == 0.0) {\npos2=vec2(0.5,0.5);\n}\nelse if (index == 1.0) {\npos2=vec2(1.0,1.0);\n}\nelse if (index == 2.0) {\npos2=vec2(1.0,0.0);\n}\nelse if (index == 3.0) {\npos2=vec2(0.0,0.0);\n}\nelse {\npos2=vec2(0.0,1.0);\n}\n#endif\n}\nelse\n{\n#ifdef Border\nfloat w=properties.x;\nfloat h=properties.y;\nfloat r=properties.z;\nfloat nru=r/w;\nfloat nrv=r/h;\nvec2 borderOffset=vec2(1.0,1.0);\nfloat segi=index;\nif (index<rsub) {\nborderOffset=vec2(1.0-(borderThickness*2.0/w),1.0-(borderThickness*2.0/h));\n}\nelse {\nsegi-=rsub;\n}\n\nif (segi<rsub0) {\npos2=vec2(1.0-nru,nrv);\n}\n\nelse if (segi<rsub1) {\npos2=vec2(nru,nrv);\n}\n\nelse if (segi<rsub2) {\npos2=vec2(nru,1.0-nrv);\n}\n\nelse {\npos2=vec2(1.0-nru,1.0-nrv);\n}\nfloat angle=TWOPI-((index-1.0)*TWOPI/(rsub-0.5));\npos2.x+=cos(angle)*nru;\npos2.y+=sin(angle)*nrv;\npos2.x=((pos2.x-0.5)*borderOffset.x)+0.5;\npos2.y=((pos2.y-0.5)*borderOffset.y)+0.5;\n#else\nif (index == 0.0) {\npos2=vec2(0.5,0.5);\n}\nelse {\nfloat w=properties.x;\nfloat h=properties.y;\nfloat r=properties.z;\nfloat nru=r/w;\nfloat nrv=r/h;\n\nif (index<rsub0) {\npos2=vec2(1.0-nru,nrv);\n}\n\nelse if (index<rsub1) {\npos2=vec2(nru,nrv);\n}\n\nelse if (index<rsub2) {\npos2=vec2(nru,1.0-nrv);\n}\n\nelse {\npos2=vec2(1.0-nru,1.0-nrv);\n}\nfloat angle=TWOPI-((index-1.0)*TWOPI/(rsub-0.5));\npos2.x+=cos(angle)*nru;\npos2.y+=sin(angle)*nrv;\n}\n#endif\n}\n#ifdef FillSolid\nvColor=fillSolidColor;\n#endif\n#ifdef BorderSolid\nvColor=borderSolidColor;\n#endif\n#ifdef FillGradient\nfloat v=dot(vec4(pos2.xy,1,1),fillGradientTY);\nvColor=mix(fillGradientColor2,fillGradientColor1,v); \n#endif\n#ifdef BorderGradient\nfloat v=dot(vec4(pos2.xy,1,1),borderGradientTY);\nvColor=mix(borderGradientColor2,borderGradientColor1,v); \n#endif\nvColor.a*=opacity;\nvec4 pos;\npos.xy=pos2.xy*properties.xy;\npos.z=1.0;\npos.w=1.0;\ngl_Position=vec4(dot(pos,transformX),dot(pos,transformY),zBias.x,1);\n}";
  14423. BABYLON.Effect.ShadersStore['sprite2dPixelShader'] = "varying vec2 vUV;\nvarying float vOpacity;\nuniform bool alphaTest;\nuniform sampler2D diffuseSampler;\nvoid main(void) {\nvec4 color=texture2D(diffuseSampler,vUV);\nif (alphaTest)\n{\nif (color.a<0.95) {\ndiscard;\n}\n}\ncolor.a*=vOpacity;\ngl_FragColor=color;\n}";
  14424. BABYLON.Effect.ShadersStore['sprite2dVertexShader'] = "\n#ifdef Instanced\n#define att attribute\n#else\n#define att uniform\n#endif\n\nattribute float index;\natt vec2 topLeftUV;\natt vec2 sizeUV;\natt vec2 scaleFactor;\natt vec2 textureSize;\n\natt vec3 properties;\natt vec2 zBias;\natt vec4 transformX;\natt vec4 transformY;\natt float opacity;\n\n\nvarying vec2 vUV;\nvarying float vOpacity;\nvoid main(void) {\nvec2 pos2;\n\nvec2 off=vec2(0.0,0.0);\nvec2 sfSizeUV=sizeUV*scaleFactor;\nfloat frame=properties.x;\nfloat invertY=properties.y;\nfloat alignToPixel=properties.z;\n\nif (index == 0.0) {\npos2=vec2(0.0,0.0);\nvUV=vec2(topLeftUV.x+(frame*sfSizeUV.x)+off.x,topLeftUV.y-off.y);\n}\n\nelse if (index == 1.0) {\npos2=vec2(0.0,1.0);\nvUV=vec2(topLeftUV.x+(frame*sfSizeUV.x)+off.x,(topLeftUV.y+sfSizeUV.y));\n}\n\nelse if (index == 2.0) {\npos2=vec2( 1.0,1.0);\nvUV=vec2(topLeftUV.x+sfSizeUV.x+(frame*sfSizeUV.x),(topLeftUV.y+sfSizeUV.y));\n}\n\nelse if (index == 3.0) {\npos2=vec2( 1.0,0.0);\nvUV=vec2(topLeftUV.x+sfSizeUV.x+(frame*sfSizeUV.x),topLeftUV.y-off.y);\n}\nif (invertY == 1.0) {\nvUV.y=1.0-vUV.y;\n}\nvec4 pos;\nif (alignToPixel == 1.0)\n{\npos.xy=floor(pos2.xy*sizeUV*textureSize);\n} else {\npos.xy=pos2.xy*sizeUV*textureSize;\n}\nvOpacity=opacity;\npos.z=1.0;\npos.w=1.0;\ngl_Position=vec4(dot(pos,transformX),dot(pos,transformY),zBias.x,1);\n} ";
  14425. BABYLON.Effect.ShadersStore['text2dPixelShader'] = "varying vec4 vColor;\nvarying vec2 vUV;\n\nuniform sampler2D diffuseSampler;\nvoid main(void) {\nvec4 color=texture2D(diffuseSampler,vUV);\ngl_FragColor=color*vColor;\n}";
  14426. BABYLON.Effect.ShadersStore['text2dVertexShader'] = "\n#ifdef Instanced\n#define att attribute\n#else\n#define att uniform\n#endif\n\nattribute float index;\natt vec2 zBias;\natt vec4 transformX;\natt vec4 transformY;\natt float opacity;\natt vec2 topLeftUV;\natt vec2 sizeUV;\natt vec2 textureSize;\natt vec4 color;\natt float superSampleFactor;\n\nvarying vec2 vUV;\nvarying vec4 vColor;\nvoid main(void) {\nvec2 pos2;\n\nif (index == 0.0) {\npos2=vec2(0.0,0.0);\nvUV=vec2(topLeftUV.x,topLeftUV.y+sizeUV.y);\n}\n\nelse if (index == 1.0) {\npos2=vec2(0.0,1.0);\nvUV=vec2(topLeftUV.x,topLeftUV.y);\n}\n\nelse if (index == 2.0) {\npos2=vec2(1.0,1.0);\nvUV=vec2(topLeftUV.x+sizeUV.x,topLeftUV.y);\n}\n\nelse if (index == 3.0) {\npos2=vec2(1.0,0.0);\nvUV=vec2(topLeftUV.x+sizeUV.x,topLeftUV.y+sizeUV.y);\n}\n\nvUV=(floor(vUV*textureSize)+vec2(0.0,0.0))/textureSize;\nvColor=color;\nvColor.a*=opacity;\nvec4 pos;\npos.xy=floor(pos2.xy*superSampleFactor*sizeUV*textureSize); \npos.z=1.0;\npos.w=1.0;\ngl_Position=vec4(dot(pos,transformX),dot(pos,transformY),zBias.x,1);\n}";
  14427. if (((typeof window != "undefined" && window.module) || (typeof module != "undefined")) && typeof module.exports != "undefined") {
  14428. module.exports = BABYLON;
  14429. };