caat.js 602 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941
  1. /*
  2. The MIT License
  3. Copyright (c) 2010-2011-2012-2013-2014-2015 Abdul.R.Alargha [alargha1970@gmail.com]
  4. Permission is hereby granted, free of charge, to any person obtaining a copy
  5. of this software and associated documentation files (the "Software"), to deal
  6. in the Software without restriction, including without limitation the rights
  7. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. copies of the Software, and to permit persons to whom the Software is
  9. furnished to do so, subject to the following conditions:
  10. The above copyright notice and this permission notice shall be included in
  11. all copies or substantial portions of the Software.
  12. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  18. THE SOFTWARE.
  19. Version: 0.4 build: 68
  20. Created on:
  21. DATE: 2015-04-01
  22. TIME: 01:03:47
  23. */
  24. /**
  25. * See LICENSE file.
  26. *
  27. * Library namespace.
  28. * CAAT stands for: Canvas Advanced Animation Toolkit.
  29. */
  30. /**
  31. * @namespace
  32. */
  33. var CAAT= CAAT || {};
  34. /**
  35. * Common bind function. Allows to set an object's function as callback. Set for every function in the
  36. * javascript context.
  37. */
  38. Function.prototype.bind= Function.prototype.bind || function() {
  39. var fn= this; // the function
  40. var args= Array.prototype.slice.call(arguments); // copy the arguments.
  41. var obj= args.shift(); // first parameter will be context 'this'
  42. return function() {
  43. return fn.apply(
  44. obj,
  45. args.concat(Array.prototype.slice.call(arguments)));
  46. }
  47. };
  48. isArray= function(input) { return typeof(input)=='object'&&(input instanceof Array); };
  49. isString= function(input){ return typeof(input)=='string'; };
  50. /**
  51. * See LICENSE file.
  52. *
  53. * Extend a prototype with another to form a classical OOP inheritance procedure.
  54. *
  55. * @param subc {object} Prototype to define the base class
  56. * @param superc {object} Prototype to be extended (derived class).
  57. */
  58. function extend(subc, superc) {
  59. var subcp = subc.prototype;
  60. // Class pattern.
  61. var F = function() {
  62. };
  63. F.prototype = superc.prototype;
  64. subc.prototype = new F(); // chain prototypes.
  65. subc.superclass = superc.prototype;
  66. subc.prototype.constructor = subc;
  67. // Reset constructor. See Object Oriented Javascript for an in-depth explanation of this.
  68. if (superc.prototype.constructor === Object.prototype.constructor) {
  69. superc.prototype.constructor = superc;
  70. }
  71. // los metodos de superc, que no esten en esta clase, crear un metodo que
  72. // llama al metodo de superc.
  73. for (var method in subcp) {
  74. if (subcp.hasOwnProperty(method)) {
  75. subc.prototype[method] = subcp[method];
  76. /**
  77. * Sintactic sugar to add a __super attribute on every overriden method.
  78. * Despite comvenient, it slows things down by 5fps.
  79. *
  80. * Uncomment at your own risk.
  81. *
  82. // tenemos en super un metodo con igual nombre.
  83. if ( superc.prototype[method]) {
  84. subc.prototype[method]= (function(fn, fnsuper) {
  85. return function() {
  86. var prevMethod= this.__super;
  87. this.__super= fnsuper;
  88. var retValue= fn.apply(
  89. this,
  90. Array.prototype.slice.call(arguments) );
  91. this.__super= prevMethod;
  92. return retValue;
  93. };
  94. })(subc.prototype[method], superc.prototype[method]);
  95. }
  96. */
  97. }
  98. }
  99. }
  100. /**
  101. * Dynamic Proxy for an object or wrap/decorate a function.
  102. *
  103. * @param object
  104. * @param preMethod
  105. * @param postMethod
  106. * @param errorMethod
  107. */
  108. function proxy(object, preMethod, postMethod, errorMethod) {
  109. // proxy a function
  110. if ( typeof object==='function' ) {
  111. if ( object.__isProxy ) {
  112. return object;
  113. }
  114. return (function(fn) {
  115. var proxyfn= function() {
  116. if ( preMethod ) {
  117. preMethod({
  118. fn: fn,
  119. arguments: Array.prototype.slice.call(arguments)} );
  120. }
  121. var retValue= null;
  122. try {
  123. // apply original function call with itself as context
  124. retValue= fn.apply(fn, Array.prototype.slice.call(arguments));
  125. // everything went right on function call, then call
  126. // post-method hook if present
  127. if ( postMethod ) {
  128. retValue= postMethod({
  129. fn: fn,
  130. arguments: Array.prototype.slice.call(arguments)} );
  131. }
  132. } catch(e) {
  133. // an exeception was thrown, call exception-method hook if
  134. // present and return its result as execution result.
  135. if( errorMethod ) {
  136. retValue= errorMethod({
  137. fn: fn,
  138. arguments: Array.prototype.slice.call(arguments),
  139. exception: e} );
  140. } else {
  141. // since there's no error hook, just throw the exception
  142. throw e;
  143. }
  144. }
  145. // return original returned value to the caller.
  146. return retValue;
  147. };
  148. proxyfn.__isProxy= true;
  149. for( var method in fn ) {
  150. if ( typeof fn[method]!=="function" ) {
  151. if (method!=="__object" && method!=="__isProxy") {
  152. (function(proxyfn, fn) {
  153. proxyfn.__defineGetter__( method, function() {
  154. return fn[method];
  155. });
  156. proxyfn.__defineSetter__( method, function(vale) {
  157. fn[method]= vale;
  158. });
  159. })(proxyfn, fn);
  160. }
  161. }
  162. }
  163. return proxyfn;
  164. })(object);
  165. }
  166. /**
  167. * If not a function then only non privitive objects can be proxied.
  168. * If it is a previously created proxy, return the proxy itself.
  169. */
  170. if ( !typeof object==='object' ||
  171. isArray(object) ||
  172. isString(object) ||
  173. object.__isProxy ) {
  174. return object;
  175. }
  176. // Our proxy object class.
  177. var cproxy= function() {};
  178. // A new proxy instance.
  179. var proxy= new cproxy();
  180. // hold the proxied object as member. Needed to assign proper
  181. // context on proxy method call.
  182. proxy.__object= object;
  183. proxy.__isProxy= true;
  184. // For every element in the object to be proxied
  185. for( var method in object ) {
  186. // only function members
  187. if ( typeof object[method]==='function' ) {
  188. // add to the proxy object a method of equal signature to the
  189. // method present at the object to be proxied.
  190. // cache references of object, function and function name.
  191. proxy[method]= (function(proxy,fn,method) {
  192. return function() {
  193. // call pre-method hook if present.
  194. if ( preMethod ) {
  195. preMethod({
  196. object: proxy.__object,
  197. method: method,
  198. arguments: Array.prototype.slice.call(arguments)} );
  199. }
  200. var retValue= null;
  201. try {
  202. // apply original object call with proxied object as
  203. // function context.
  204. retValue= fn.apply( proxy.__object, arguments );
  205. // everything went right on function call, the call
  206. // post-method hook if present
  207. if ( postMethod ) {
  208. postMethod({
  209. object: proxy.__object,
  210. method: method,
  211. arguments: Array.prototype.slice.call(arguments)} );
  212. }
  213. } catch(e) {
  214. // an exeception was thrown, call exception-method hook if
  215. // present and return its result as execution result.
  216. if( errorMethod ) {
  217. retValue= errorMethod({
  218. object: proxy.__object,
  219. method: method,
  220. arguments: Array.prototype.slice.call(arguments),
  221. exception: e} );
  222. } else {
  223. // since there's no error hook, just throw the exception
  224. throw e;
  225. }
  226. }
  227. // return original returned value to the caller.
  228. return retValue;
  229. };
  230. })(proxy,object[method],method);
  231. } else {
  232. if (method!=="__object" && method!=="__isProxy") {
  233. (function(proxy, method) {
  234. proxy.__defineGetter__( method, function() {
  235. return proxy.__object[method];
  236. });
  237. proxy.__defineSetter__( method, function(vale) {
  238. proxy.__object[method]= vale;
  239. });
  240. })(proxy, method);
  241. }
  242. }
  243. }
  244. // return our newly created and populated of functions proxy object.
  245. return proxy;
  246. }
  247. /** proxy sample usage
  248. var c0= new Meetup.C1(5);
  249. var cp1= proxy(
  250. c1,
  251. function() {
  252. console.log('pre method on object: ',
  253. arguments[0].object.toString(),
  254. arguments[0].method,
  255. arguments[0].arguments );
  256. },
  257. function() {
  258. console.log('post method on object: ',
  259. arguments[0].object.toString(),
  260. arguments[0].method,
  261. arguments[0].arguments );
  262. },
  263. function() {
  264. console.log('exception on object: ',
  265. arguments[0].object.toString(),
  266. arguments[0].method,
  267. arguments[0].arguments,
  268. arguments[0].exception);
  269. return -1;
  270. });
  271. **/
  272. function proxify( ns, preMethod, postMethod, errorMethod, getter, setter ) {
  273. var nns= "__"+ns+"__";
  274. var obj= window;
  275. var path= ns.split(".");
  276. while( path.length>1) {
  277. obj= obj[ path.shift() ];
  278. }
  279. window[nns] = obj[path];
  280. (function(obj,path, nns,ns) {
  281. var newC= function() {
  282. console.log("Creating object of type proxy["+ns+"]");
  283. var obj= new window[nns]( Array.prototype.slice.call(arguments) );
  284. obj.____name= ns;
  285. return proxyObject( obj, preMethod, postMethod, errorMethod, getter, setter );
  286. };
  287. // set new constructor function prototype as previous one.
  288. newC.prototype= window[nns].prototype;
  289. for( var method in obj[path] ) {
  290. if ( typeof obj[path][method]!=="function" ) {
  291. if (method!=="__object" && method!=="__isProxy") {
  292. (function(prevConstructor, method, newC) {
  293. newC.__defineGetter__( method, function() {
  294. return prevConstructor[method];
  295. });
  296. newC.__defineSetter__( method, function(vale) {
  297. prevConstructor[method]= vale;
  298. });
  299. })(obj[path],method,newC);
  300. }
  301. }
  302. }
  303. obj[path]= newC;
  304. })(obj,path,nns,ns);
  305. }
  306. function proxyObject(object, preMethod, postMethod, errorMethod, getter, setter) {
  307. /**
  308. * If not a function then only non privitive objects can be proxied.
  309. * If it is a previously created proxy, return the proxy itself.
  310. */
  311. if ( !typeof object==='object' ||
  312. isArray(object) ||
  313. isString(object) ||
  314. object.__isProxy ) {
  315. return object;
  316. }
  317. // hold the proxied object as member. Needed to assign proper
  318. // context on proxy method call.
  319. object.$proxy__isProxy= true;
  320. // For every element in the object to be proxied
  321. for( var method in object ) {
  322. if ( method==="constructor" ) {
  323. continue;
  324. }
  325. // only function members
  326. if ( typeof object[method]==='function' ) {
  327. var fn= object[method];
  328. object["$proxy__"+method]= fn;
  329. object[method]= (function(object,fn,fnname) {
  330. return function() {
  331. var args= Array.prototype.slice.call(arguments);
  332. // call pre-method hook if present.
  333. if ( preMethod ) {
  334. preMethod({
  335. object: object,
  336. objectName: object.____name,
  337. method: fnname,
  338. arguments: args } );
  339. }
  340. var retValue= null;
  341. try {
  342. // apply original object call with proxied object as
  343. // function context.
  344. retValue= fn.apply( object, args );
  345. // everything went right on function call, the call
  346. // post-method hook if present
  347. if ( postMethod ) {
  348. var rr= postMethod({
  349. object: object,
  350. objectName: object.____name,
  351. method: fnname,
  352. arguments: args } );
  353. if ( typeof rr!=="undefined" ) {
  354. //retValue= rr;
  355. }
  356. }
  357. } catch(e) {
  358. // an exeception was thrown, call exception-method hook if
  359. // present and return its result as execution result.
  360. if( errorMethod ) {
  361. retValue= errorMethod({
  362. object: object,
  363. objectName: object.____name,
  364. method: fnname,
  365. arguments: args,
  366. exception: e} );
  367. } else {
  368. // since there's no error hook, just throw the exception
  369. throw e;
  370. }
  371. }
  372. // return original returned value to the caller.
  373. return retValue;
  374. };
  375. })(object,fn,method);
  376. } else {
  377. if ( method!=="____name" ) {
  378. (function(object, attribute, getter, setter) {
  379. object["$proxy__"+attribute]= object[attribute];
  380. object.__defineGetter__( attribute, function() {
  381. if ( getter) {
  382. getter( object.____name, attribute );
  383. }
  384. return object["$proxy__"+attribute];
  385. });
  386. object.__defineSetter__( attribute, function (value) {
  387. object["$proxy__"+attribute] = value;
  388. if ( setter ) {
  389. setter( object.____name, attribute, value );
  390. }
  391. });
  392. })( object, method, getter, setter );
  393. }
  394. }
  395. }
  396. // return our newly created and populated with functions proxied object.
  397. return object;
  398. }/**
  399. * See LICENSE file.
  400. *
  401. * Manages every Actor affine transformations.
  402. * Take into account that Canvas' renderingContext computes postive rotation clockwise, so hacks
  403. * to handle it properly are hardcoded.
  404. *
  405. * Contained classes are CAAT.Matrix and CAAT.MatrixStack.
  406. *
  407. **/
  408. (function() {
  409. /**
  410. *
  411. * Define a matrix to hold three dimensional affine transforms.
  412. *
  413. * @constructor
  414. */
  415. CAAT.Matrix3= function() {
  416. this.matrix= [
  417. [1,0,0,0],
  418. [0,1,0,0],
  419. [0,0,1,0],
  420. [0,0,0,1]
  421. ];
  422. this.fmatrix= [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];
  423. return this;
  424. };
  425. CAAT.Matrix3.prototype= {
  426. matrix: null,
  427. fmatrix:null,
  428. transformCoord : function(point) {
  429. var x= point.x;
  430. var y= point.y;
  431. var z= point.z;
  432. point.x= x*this.matrix[0][0] + y*this.matrix[0][1] + z*this.matrix[0][2] + this.matrix[0][3];
  433. point.y= x*this.matrix[1][0] + y*this.matrix[1][1] + z*this.matrix[1][2] + this.matrix[1][3];
  434. point.z= x*this.matrix[2][0] + y*this.matrix[2][1] + z*this.matrix[2][2] + this.matrix[2][3];
  435. return point;
  436. },
  437. initialize : function( x0,y0,z0, x1,y1,z1, x2,y2,z2 ) {
  438. this.identity( );
  439. this.matrix[0][0]= x0;
  440. this.matrix[0][1]= y0;
  441. this.matrix[0][2]= z0;
  442. this.matrix[1][0]= x1;
  443. this.matrix[1][1]= y1;
  444. this.matrix[1][2]= z1;
  445. this.matrix[2][0]= x2;
  446. this.matrix[2][1]= y2;
  447. this.matrix[2][2]= z2;
  448. return this;
  449. },
  450. initWithMatrix : function(matrixData) {
  451. this.matrix= matrixData;
  452. return this;
  453. },
  454. flatten : function() {
  455. var d= this.fmatrix;
  456. var s= this.matrix;
  457. d[ 0]= s[0][0];
  458. d[ 1]= s[1][0];
  459. d[ 2]= s[2][0];
  460. d[ 3]= s[3][0];
  461. d[ 4]= s[0][1];
  462. d[ 5]= s[1][1];
  463. d[ 6]= s[2][1];
  464. d[ 7]= s[2][1];
  465. d[ 8]= s[0][2];
  466. d[ 9]= s[1][2];
  467. d[10]= s[2][2];
  468. d[11]= s[3][2];
  469. d[12]= s[0][3];
  470. d[13]= s[1][3];
  471. d[14]= s[2][3];
  472. d[15]= s[3][3];
  473. return this.fmatrix;
  474. },
  475. /**
  476. * Set this matrix to identity matrix.
  477. * @return this
  478. */
  479. identity : function() {
  480. for( var i=0; i<4; i++ ) {
  481. for( var j=0; j<4; j++ ) {
  482. this.matrix[i][j]= (i===j) ? 1.0 : 0.0;
  483. }
  484. }
  485. return this;
  486. },
  487. /**
  488. * Get this matri'x internal representation data. The bakced structure is a 4x4 array of number.
  489. */
  490. getMatrix : function() {
  491. return this.matrix;
  492. },
  493. /**
  494. * Multiply this matrix by a created rotation matrix. The rotation matrix is set up to rotate around
  495. * xy axis.
  496. *
  497. * @param xy {Number} radians to rotate.
  498. *
  499. * @return this
  500. */
  501. rotateXY : function( xy ) {
  502. return this.rotate( xy, 0, 0 );
  503. },
  504. /**
  505. * Multiply this matrix by a created rotation matrix. The rotation matrix is set up to rotate around
  506. * xz axis.
  507. *
  508. * @param xz {Number} radians to rotate.
  509. *
  510. * @return this
  511. */
  512. rotateXZ : function( xz ) {
  513. return this.rotate( 0, xz, 0 );
  514. },
  515. /**
  516. * Multiply this matrix by a created rotation matrix. The rotation matrix is set up to rotate aroind
  517. * yz axis.
  518. *
  519. * @param yz {Number} radians to rotate.
  520. *
  521. * @return this
  522. */
  523. rotateYZ : function( yz ) {
  524. return this.rotate( 0, 0, yz );
  525. },
  526. /**
  527. *
  528. * @param xy
  529. * @param xz
  530. * @param yz
  531. */
  532. setRotate : function( xy, xz, yz ) {
  533. var m= this.rotate(xy,xz,yz);
  534. this.copy(m);
  535. return this;
  536. },
  537. /**
  538. * Creates a matrix to represent arbitrary rotations around the given planes.
  539. * @param xy {number} radians to rotate around xy plane.
  540. * @param xz {number} radians to rotate around xz plane.
  541. * @param yz {number} radians to rotate around yz plane.
  542. *
  543. * @return {CAAT.Matrix3} a newly allocated matrix.
  544. * @static
  545. */
  546. rotate : function( xy, xz, yz ) {
  547. var res=new CAAT.Matrix3();
  548. var s,c,m;
  549. if (xy!==0) {
  550. m =new CAAT.Matrix3( );
  551. s=Math.sin(xy);
  552. c=Math.cos(xy);
  553. m.matrix[1][1]=c;
  554. m.matrix[1][2]=-s;
  555. m.matrix[2][1]=s;
  556. m.matrix[2][2]=c;
  557. res.multiply(m);
  558. }
  559. if (xz!==0) {
  560. m =new CAAT.Matrix3( );
  561. s=Math.sin(xz);
  562. c=Math.cos(xz);
  563. m.matrix[0][0]=c;
  564. m.matrix[0][2]=-s;
  565. m.matrix[2][0]=s;
  566. m.matrix[2][2]=c;
  567. res.multiply(m);
  568. }
  569. if (yz!==0) {
  570. m =new CAAT.Matrix3( );
  571. s=Math.sin(yz);
  572. c=Math.cos(yz);
  573. m.matrix[0][0]=c;
  574. m.matrix[0][1]=-s;
  575. m.matrix[1][0]=s;
  576. m.matrix[1][1]=c;
  577. res.multiply(m);
  578. }
  579. return res;
  580. },
  581. /**
  582. * Creates a new matrix being a copy of this matrix.
  583. * @return {CAAT.Matrix3} a newly allocated matrix object.
  584. */
  585. getClone : function() {
  586. var m= new CAAT.Matrix3( );
  587. m.copy(this);
  588. return m;
  589. },
  590. /**
  591. * Multiplies this matrix by another matrix.
  592. *
  593. * @param n {CAAT.Matrix3} a CAAT.Matrix3 object.
  594. * @return this
  595. */
  596. multiply : function( m ) {
  597. var n= this.getClone( );
  598. var nm= n.matrix;
  599. var n00= nm[0][0];
  600. var n01= nm[0][1];
  601. var n02= nm[0][2];
  602. var n03= nm[0][3];
  603. var n10= nm[1][0];
  604. var n11= nm[1][1];
  605. var n12= nm[1][2];
  606. var n13= nm[1][3];
  607. var n20= nm[2][0];
  608. var n21= nm[2][1];
  609. var n22= nm[2][2];
  610. var n23= nm[2][3];
  611. var n30= nm[3][0];
  612. var n31= nm[3][1];
  613. var n32= nm[3][2];
  614. var n33= nm[3][3];
  615. var mm= m.matrix;
  616. var m00= mm[0][0];
  617. var m01= mm[0][1];
  618. var m02= mm[0][2];
  619. var m03= mm[0][3];
  620. var m10= mm[1][0];
  621. var m11= mm[1][1];
  622. var m12= mm[1][2];
  623. var m13= mm[1][3];
  624. var m20= mm[2][0];
  625. var m21= mm[2][1];
  626. var m22= mm[2][2];
  627. var m23= mm[2][3];
  628. var m30= mm[3][0];
  629. var m31= mm[3][1];
  630. var m32= mm[3][2];
  631. var m33= mm[3][3];
  632. this.matrix[0][0] = n00*m00 + n01*m10 + n02*m20 + n03*m30;
  633. this.matrix[0][1] = n00*m01 + n01*m11 + n02*m21 + n03*m31;
  634. this.matrix[0][2] = n00*m02 + n01*m12 + n02*m22 + n03*m32;
  635. this.matrix[0][3] = n00*m03 + n01*m13 + n02*m23 + n03*m33;
  636. this.matrix[1][0] = n10*m00 + n11*m10 + n12*m20 + n13*m30;
  637. this.matrix[1][1] = n10*m01 + n11*m11 + n12*m21 + n13*m31;
  638. this.matrix[1][2] = n10*m02 + n11*m12 + n12*m22 + n13*m32;
  639. this.matrix[1][3] = n10*m03 + n11*m13 + n12*m23 + n13*m33;
  640. this.matrix[2][0] = n20*m00 + n21*m10 + n22*m20 + n23*m30;
  641. this.matrix[2][1] = n20*m01 + n21*m11 + n22*m21 + n23*m31;
  642. this.matrix[2][2] = n20*m02 + n21*m12 + n22*m22 + n23*m32;
  643. this.matrix[2][3] = n20*m03 + n21*m13 + n22*m23 + n23*m33;
  644. return this;
  645. },
  646. /**
  647. * Pre multiplies this matrix by a given matrix.
  648. *
  649. * @param m {CAAT.Matrix3} a CAAT.Matrix3 object.
  650. *
  651. * @return this
  652. */
  653. premultiply : function(m) {
  654. var n= this.getClone( );
  655. var nm= n.matrix;
  656. var n00= nm[0][0];
  657. var n01= nm[0][1];
  658. var n02= nm[0][2];
  659. var n03= nm[0][3];
  660. var n10= nm[1][0];
  661. var n11= nm[1][1];
  662. var n12= nm[1][2];
  663. var n13= nm[1][3];
  664. var n20= nm[2][0];
  665. var n21= nm[2][1];
  666. var n22= nm[2][2];
  667. var n23= nm[2][3];
  668. var n30= nm[3][0];
  669. var n31= nm[3][1];
  670. var n32= nm[3][2];
  671. var n33= nm[3][3];
  672. var mm= m.matrix;
  673. var m00= mm[0][0];
  674. var m01= mm[0][1];
  675. var m02= mm[0][2];
  676. var m03= mm[0][3];
  677. var m10= mm[1][0];
  678. var m11= mm[1][1];
  679. var m12= mm[1][2];
  680. var m13= mm[1][3];
  681. var m20= mm[2][0];
  682. var m21= mm[2][1];
  683. var m22= mm[2][2];
  684. var m23= mm[2][3];
  685. var m30= mm[3][0];
  686. var m31= mm[3][1];
  687. var m32= mm[3][2];
  688. var m33= mm[3][3];
  689. this.matrix[0][0] = n00*m00 + n01*m10 + n02*m20;
  690. this.matrix[0][1] = n00*m01 + n01*m11 + n02*m21;
  691. this.matrix[0][2] = n00*m02 + n01*m12 + n02*m22;
  692. this.matrix[0][3] = n00*m03 + n01*m13 + n02*m23 + n03;
  693. this.matrix[1][0] = n10*m00 + n11*m10 + n12*m20;
  694. this.matrix[1][1] = n10*m01 + n11*m11 + n12*m21;
  695. this.matrix[1][2] = n10*m02 + n11*m12 + n12*m22;
  696. this.matrix[1][3] = n10*m03 + n11*m13 + n12*m23 + n13;
  697. this.matrix[2][0] = n20*m00 + n21*m10 + n22*m20;
  698. this.matrix[2][1] = n20*m01 + n21*m11 + n22*m21;
  699. this.matrix[2][2] = n20*m02 + n21*m12 + n22*m22;
  700. this.matrix[2][3] = n20*m03 + n21*m13 + n22*m23 + n23;
  701. return this;
  702. },
  703. /**
  704. * Set this matrix translation values to be the given parameters.
  705. *
  706. * @param x {number} x component of translation point.
  707. * @param y {number} y component of translation point.
  708. * @param z {number} z component of translation point.
  709. *
  710. * @return this
  711. */
  712. setTranslate : function(x,y,z) {
  713. this.identity();
  714. this.matrix[0][3]=x;
  715. this.matrix[1][3]=y;
  716. this.matrix[2][3]=z;
  717. return this;
  718. },
  719. /**
  720. * Create a translation matrix.
  721. * @param x {number}
  722. * @param y {number}
  723. * @param z {number}
  724. * @return {CAAT.Matrix3} a new matrix.
  725. */
  726. translate : function( x,y,z ) {
  727. var m= new CAAT.Matrix3();
  728. m.setTranslate( x,y,z );
  729. return m;
  730. },
  731. setScale : function( sx, sy, sz ) {
  732. this.identity();
  733. this.matrix[0][0]= sx;
  734. this.matrix[1][1]= sy;
  735. this.matrix[2][2]= sz;
  736. return this;
  737. },
  738. scale : function( sx, sy, sz ) {
  739. var m= new CAAT.Matrix3();
  740. m.setScale(sx,sy,sz);
  741. return m;
  742. },
  743. /**
  744. * Set this matrix as the rotation matrix around the given axes.
  745. * @param xy {number} radians of rotation around z axis.
  746. * @param xz {number} radians of rotation around y axis.
  747. * @param yz {number} radians of rotation around x axis.
  748. *
  749. * @return this
  750. */
  751. rotateModelView : function( xy, xz, yz ) {
  752. var sxy= Math.sin( xy );
  753. var sxz= Math.sin( xz );
  754. var syz= Math.sin( yz );
  755. var cxy= Math.cos( xy );
  756. var cxz= Math.cos( xz );
  757. var cyz= Math.cos( yz );
  758. this.matrix[0][0]= cxz*cxy;
  759. this.matrix[0][1]= -cxz*sxy;
  760. this.matrix[0][2]= sxz;
  761. this.matrix[0][3]= 0;
  762. this.matrix[1][0]= syz*sxz*cxy+sxy*cyz;
  763. this.matrix[1][1]= cyz*cxy-syz*sxz*sxy;
  764. this.matrix[1][2]= -syz*cxz;
  765. this.matrix[1][3]= 0;
  766. this.matrix[2][0]= syz*sxy-cyz*sxz*cxy;
  767. this.matrix[2][1]= cyz*sxz*sxy+syz*cxy;
  768. this.matrix[2][2]= cyz*cxz;
  769. this.matrix[2][3]= 0;
  770. this.matrix[3][0]= 0;
  771. this.matrix[3][1]= 0;
  772. this.matrix[3][2]= 0;
  773. this.matrix[3][3]= 1;
  774. return this;
  775. },
  776. /**
  777. * Copy a given matrix values into this one's.
  778. * @param m {CAAT.Matrix} a matrix
  779. *
  780. * @return this
  781. */
  782. copy : function( m ) {
  783. for( var i=0; i<4; i++ ) {
  784. for( var j=0; j<4; j++ ) {
  785. this.matrix[i][j]= m.matrix[i][j];
  786. }
  787. }
  788. return this;
  789. },
  790. /**
  791. * Calculate this matrix's determinant.
  792. * @return {number} matrix determinant.
  793. */
  794. calculateDeterminant: function () {
  795. var mm= this.matrix;
  796. var m11= mm[0][0], m12= mm[0][1], m13= mm[0][2], m14= mm[0][3],
  797. m21= mm[1][0], m22= mm[1][1], m23= mm[1][2], m24= mm[1][3],
  798. m31= mm[2][0], m32= mm[2][1], m33= mm[2][2], m34= mm[2][3],
  799. m41= mm[3][0], m42= mm[3][1], m43= mm[3][2], m44= mm[3][3];
  800. return m14 * m22 * m33 * m41 +
  801. m12 * m24 * m33 * m41 +
  802. m14 * m23 * m31 * m42 +
  803. m13 * m24 * m31 * m42 +
  804. m13 * m21 * m34 * m42 +
  805. m11 * m23 * m34 * m42 +
  806. m14 * m21 * m32 * m43 +
  807. m11 * m24 * m32 * m43 +
  808. m13 * m22 * m31 * m44 +
  809. m12 * m23 * m31 * m44 +
  810. m12 * m21 * m33 * m44 +
  811. m11 * m22 * m33 * m44 +
  812. m14 * m23 * m32 * m41 -
  813. m13 * m24 * m32 * m41 -
  814. m13 * m22 * m34 * m41 -
  815. m12 * m23 * m34 * m41 -
  816. m14 * m21 * m33 * m42 -
  817. m11 * m24 * m33 * m42 -
  818. m14 * m22 * m31 * m43 -
  819. m12 * m24 * m31 * m43 -
  820. m12 * m21 * m34 * m43 -
  821. m11 * m22 * m34 * m43 -
  822. m13 * m21 * m32 * m44 -
  823. m11 * m23 * m32 * m44;
  824. },
  825. /**
  826. * Return a new matrix which is this matrix's inverse matrix.
  827. * @return {CAAT.Matrix3} a new matrix.
  828. */
  829. getInverse : function() {
  830. var mm= this.matrix;
  831. var m11 = mm[0][0], m12 = mm[0][1], m13 = mm[0][2], m14 = mm[0][3],
  832. m21 = mm[1][0], m22 = mm[1][1], m23 = mm[1][2], m24 = mm[1][3],
  833. m31 = mm[2][0], m32 = mm[2][1], m33 = mm[2][2], m34 = mm[2][3],
  834. m41 = mm[3][0], m42 = mm[3][1], m43 = mm[3][2], m44 = mm[3][3];
  835. var m2= new CAAT.Matrix3();
  836. m2.matrix[0][0]= m23*m34*m42 + m24*m32*m43 + m22*m33*m44 - m24*m33*m42 - m22*m34*m43 - m23*m32*m44;
  837. m2.matrix[0][1]= m14*m33*m42 + m12*m34*m43 + m13*m32*m44 - m12*m33*m44 - m13*m34*m42 - m14*m32*m43;
  838. m2.matrix[0][2]= m13*m24*m42 + m12*m23*m44 + m14*m22*m43 - m12*m24*m43 - m13*m22*m44 - m14*m23*m42;
  839. m2.matrix[0][3]= m14*m23*m32 + m12*m24*m33 + m13*m22*m34 - m13*m24*m32 - m14*m22*m33 - m12*m23*m34;
  840. m2.matrix[1][0]= m24*m33*m41 + m21*m34*m43 + m23*m31*m44 - m23*m34*m41 - m24*m31*m43 - m21*m33*m44;
  841. m2.matrix[1][1]= m13*m34*m41 + m14*m31*m43 + m11*m33*m44 - m14*m33*m41 - m11*m34*m43 - m13*m31*m44;
  842. m2.matrix[1][2]= m14*m23*m41 + m11*m24*m43 + m13*m21*m44 - m13*m24*m41 - m14*m21*m43 - m11*m23*m44;
  843. m2.matrix[1][3]= m13*m24*m31 + m14*m21*m33 + m11*m23*m34 - m14*m23*m31 - m11*m24*m33 - m13*m21*m34;
  844. m2.matrix[2][0]= m22*m34*m41 + m24*m31*m42 + m21*m32*m44 - m24*m32*m41 - m21*m34*m42 - m22*m31*m44;
  845. m2.matrix[2][1]= m14*m32*m41 + m11*m34*m42 + m12*m31*m44 - m11*m32*m44 - m12*m34*m41 - m14*m31*m42;
  846. m2.matrix[2][2]= m13*m24*m41 + m14*m21*m42 + m11*m22*m44 - m14*m22*m41 - m11*m24*m42 - m12*m21*m44;
  847. m2.matrix[2][3]= m14*m22*m31 + m11*m24*m32 + m12*m21*m34 - m11*m22*m34 - m12*m24*m31 - m14*m21*m32;
  848. m2.matrix[3][0]= m23*m32*m41 + m21*m33*m42 + m22*m31*m43 - m22*m33*m41 - m23*m31*m42 - m21*m32*m43;
  849. m2.matrix[3][1]= m12*m33*m41 + m13*m31*m42 + m11*m32*m43 - m13*m32*m41 - m11*m33*m42 - m12*m31*m43;
  850. m2.matrix[3][2]= m13*m22*m41 + m11*m23*m42 + m12*m21*m43 - m11*m22*m43 - m12*m23*m41 - m13*m21*m42;
  851. m2.matrix[3][3]= m12*m23*m31 + m13*m21*m32 + m11*m22*m33 - m13*m22*m31 - m11*m23*m32 - m12*m21*m33;
  852. return m2.multiplyScalar( 1/this.calculateDeterminant() );
  853. },
  854. /**
  855. * Multiply this matrix by a scalar.
  856. * @param scalar {number} scalar value
  857. *
  858. * @return this
  859. */
  860. multiplyScalar : function( scalar ) {
  861. var i,j;
  862. for( i=0; i<4; i++ ) {
  863. for( j=0; j<4; j++ ) {
  864. this.matrix[i][j]*=scalar;
  865. }
  866. }
  867. return this;
  868. }
  869. };
  870. })();
  871. (function() {
  872. /**
  873. * 2D affinetransform matrix represeantation.
  874. * It includes matrices for
  875. * <ul>
  876. * <li>Rotation by any anchor point
  877. * <li>translation
  878. * <li>scale by any anchor point
  879. * </ul>
  880. *
  881. */
  882. CAAT.Matrix = function() {
  883. this.matrix= [
  884. 1.0,0.0,0.0,
  885. 0.0,1.0,0.0, 0.0,0.0,1.0 ];
  886. if ( Float32Array ) {
  887. this.matrix= new Float32Array(this.matrix);
  888. }
  889. return this;
  890. };
  891. CAAT.Matrix.prototype= {
  892. matrix: null,
  893. /**
  894. * Transform a point by this matrix. The parameter point will be modified with the transformation values.
  895. * @param point {CAAT.Point}.
  896. * @return {CAAT.Point} the parameter point.
  897. */
  898. transformCoord : function(point) {
  899. var x= point.x;
  900. var y= point.y;
  901. var tm= this.matrix;
  902. point.x= x*tm[0] + y*tm[1] + tm[2];
  903. point.y= x*tm[3] + y*tm[4] + tm[5];
  904. return point;
  905. },
  906. /**
  907. * Create a new rotation matrix and set it up for the specified angle in radians.
  908. * @param angle {number}
  909. * @return {CAAT.Matrix} a matrix object.
  910. *
  911. * @static
  912. */
  913. rotate : function(angle) {
  914. var m= new CAAT.Matrix();
  915. m.setRotation(angle);
  916. return m;
  917. },
  918. setRotation : function( angle ) {
  919. this.identity();
  920. var tm= this.matrix;
  921. var c= Math.cos( angle );
  922. var s= Math.sin( angle );
  923. tm[0]= c;
  924. tm[1]= -s;
  925. tm[3]= s;
  926. tm[4]= c;
  927. return this;
  928. },
  929. /**
  930. * Create a scale matrix.
  931. * @param scalex {number} x scale magnitude.
  932. * @param scaley {number} y scale magnitude.
  933. *
  934. * @return {CAAT.Matrix} a matrix object.
  935. *
  936. * @static
  937. */
  938. scale : function(scalex, scaley) {
  939. var m= new CAAT.Matrix();
  940. m.matrix[0]= scalex;
  941. m.matrix[4]= scaley;
  942. return m;
  943. },
  944. setScale : function(scalex, scaley) {
  945. this.identity();
  946. this.matrix[0]= scalex;
  947. this.matrix[4]= scaley;
  948. return this;
  949. },
  950. /**
  951. * Create a translation matrix.
  952. * @param x {number} x translation magnitude.
  953. * @param y {number} y translation magnitude.
  954. *
  955. * @return {CAAT.Matrix} a matrix object.
  956. * @static
  957. *
  958. */
  959. translate : function( x, y ) {
  960. var m= new CAAT.Matrix();
  961. m.matrix[2]= x;
  962. m.matrix[5]= y;
  963. return m;
  964. },
  965. /**
  966. * Sets this matrix as a translation matrix.
  967. * @param x
  968. * @param y
  969. */
  970. setTranslate : function( x, y ) {
  971. this.identity();
  972. this.matrix[2]= x;
  973. this.matrix[5]= y;
  974. return this;
  975. },
  976. /**
  977. * Copy into this matrix the given matrix values.
  978. * @param matrix {CAAT.Matrix}
  979. * @return this
  980. */
  981. copy : function( matrix ) {
  982. matrix= matrix.matrix;
  983. var tmatrix= this.matrix;
  984. tmatrix[0]= matrix[0];
  985. tmatrix[1]= matrix[1];
  986. tmatrix[2]= matrix[2];
  987. tmatrix[3]= matrix[3];
  988. tmatrix[4]= matrix[4];
  989. tmatrix[5]= matrix[5];
  990. tmatrix[6]= matrix[6];
  991. tmatrix[7]= matrix[7];
  992. tmatrix[8]= matrix[8];
  993. return this;
  994. },
  995. /**
  996. * Set this matrix to the identity matrix.
  997. * @return this
  998. */
  999. identity : function() {
  1000. var m= this.matrix;
  1001. m[0]= 1.0;
  1002. m[1]= 0.0;
  1003. m[2]= 0.0;
  1004. m[3]= 0.0;
  1005. m[4]= 1.0;
  1006. m[5]= 0.0;
  1007. m[6]= 0.0;
  1008. m[7]= 0.0;
  1009. m[8]= 1.0;
  1010. return this;
  1011. },
  1012. /**
  1013. * Multiply this matrix by a given matrix.
  1014. * @param m {CAAT.Matrix}
  1015. * @return this
  1016. */
  1017. multiply : function( m ) {
  1018. var tm= this.matrix;
  1019. var mm= m.matrix;
  1020. var tm0= tm[0];
  1021. var tm1= tm[1];
  1022. var tm2= tm[2];
  1023. var tm3= tm[3];
  1024. var tm4= tm[4];
  1025. var tm5= tm[5];
  1026. var tm6= tm[6];
  1027. var tm7= tm[7];
  1028. var tm8= tm[8];
  1029. var mm0= mm[0];
  1030. var mm1= mm[1];
  1031. var mm2= mm[2];
  1032. var mm3= mm[3];
  1033. var mm4= mm[4];
  1034. var mm5= mm[5];
  1035. var mm6= mm[6];
  1036. var mm7= mm[7];
  1037. var mm8= mm[8];
  1038. tm[0]= tm0*mm0 + tm1*mm3 + tm2*mm6;
  1039. tm[1]= tm0*mm1 + tm1*mm4 + tm2*mm7;
  1040. tm[2]= tm0*mm2 + tm1*mm5 + tm2*mm8;
  1041. tm[3]= tm3*mm0 + tm4*mm3 + tm5*mm6;
  1042. tm[4]= tm3*mm1 + tm4*mm4 + tm5*mm7;
  1043. tm[5]= tm3*mm2 + tm4*mm5 + tm5*mm8;
  1044. tm[6]= tm6*mm0 + tm7*mm3 + tm8*mm6;
  1045. tm[7]= tm6*mm1 + tm7*mm4 + tm8*mm7;
  1046. tm[8]= tm6*mm2 + tm7*mm5 + tm8*mm8;
  1047. return this;
  1048. },
  1049. /**
  1050. * Premultiply this matrix by a given matrix.
  1051. * @param m {CAAT.Matrix}
  1052. * @return this
  1053. */
  1054. premultiply : function(m) {
  1055. var m00= m.matrix[0]*this.matrix[0] + m.matrix[1]*this.matrix[3] + m.matrix[2]*this.matrix[6];
  1056. var m01= m.matrix[0]*this.matrix[1] + m.matrix[1]*this.matrix[4] + m.matrix[2]*this.matrix[7];
  1057. var m02= m.matrix[0]*this.matrix[2] + m.matrix[1]*this.matrix[5] + m.matrix[2]*this.matrix[8];
  1058. var m10= m.matrix[3]*this.matrix[0] + m.matrix[4]*this.matrix[3] + m.matrix[5]*this.matrix[6];
  1059. var m11= m.matrix[3]*this.matrix[1] + m.matrix[4]*this.matrix[4] + m.matrix[5]*this.matrix[7];
  1060. var m12= m.matrix[3]*this.matrix[2] + m.matrix[4]*this.matrix[5] + m.matrix[5]*this.matrix[8];
  1061. var m20= m.matrix[6]*this.matrix[0] + m.matrix[7]*this.matrix[3] + m.matrix[8]*this.matrix[6];
  1062. var m21= m.matrix[6]*this.matrix[1] + m.matrix[7]*this.matrix[4] + m.matrix[8]*this.matrix[7];
  1063. var m22= m.matrix[6]*this.matrix[2] + m.matrix[7]*this.matrix[5] + m.matrix[8]*this.matrix[8];
  1064. this.matrix[0]= m00;
  1065. this.matrix[1]= m01;
  1066. this.matrix[2]= m02;
  1067. this.matrix[3]= m10;
  1068. this.matrix[4]= m11;
  1069. this.matrix[5]= m12;
  1070. this.matrix[6]= m20;
  1071. this.matrix[7]= m21;
  1072. this.matrix[8]= m22;
  1073. return this;
  1074. },
  1075. /**
  1076. * Creates a new inverse matrix from this matrix.
  1077. * @return {CAAT.Matrix} an inverse matrix.
  1078. */
  1079. getInverse : function() {
  1080. var tm= this.matrix;
  1081. var m00= tm[0];
  1082. var m01= tm[1];
  1083. var m02= tm[2];
  1084. var m10= tm[3];
  1085. var m11= tm[4];
  1086. var m12= tm[5];
  1087. var m20= tm[6];
  1088. var m21= tm[7];
  1089. var m22= tm[8];
  1090. var newMatrix= new CAAT.Matrix();
  1091. var determinant= m00* (m11*m22 - m21*m12) - m10*(m01*m22 - m21*m02) + m20 * (m01*m12 - m11*m02);
  1092. if ( determinant===0 ) {
  1093. return null;
  1094. }
  1095. var m= newMatrix.matrix;
  1096. m[0]= m11*m22-m12*m21;
  1097. m[1]= m02*m21-m01*m22;
  1098. m[2]= m01*m12-m02*m11;
  1099. m[3]= m12*m20-m10*m22;
  1100. m[4]= m00*m22-m02*m20;
  1101. m[5]= m02*m10-m00*m12;
  1102. m[6]= m10*m21-m11*m20;
  1103. m[7]= m01*m20-m00*m21;
  1104. m[8]= m00*m11-m01*m10;
  1105. newMatrix.multiplyScalar( 1/determinant );
  1106. return newMatrix;
  1107. },
  1108. /**
  1109. * Multiply this matrix by a scalar.
  1110. * @param scalar {number} scalar value
  1111. *
  1112. * @return this
  1113. */
  1114. multiplyScalar : function( scalar ) {
  1115. var i;
  1116. for( i=0; i<9; i++ ) {
  1117. this.matrix[i]*=scalar;
  1118. }
  1119. return this;
  1120. },
  1121. transformRenderingContextSet : null,
  1122. transformRenderingContext : null,
  1123. /**
  1124. *
  1125. * @param ctx
  1126. */
  1127. transformRenderingContextSet_NoClamp : function(ctx) {
  1128. var m= this.matrix;
  1129. ctx.setTransform( m[0], m[3], m[1], m[4], m[2], m[5] );
  1130. return this;
  1131. },
  1132. /**
  1133. *
  1134. * @param ctx
  1135. */
  1136. transformRenderingContext_NoClamp : function(ctx) {
  1137. var m= this.matrix;
  1138. ctx.transform( m[0], m[3], m[1], m[4], m[2], m[5] );
  1139. return this;
  1140. },
  1141. /**
  1142. *
  1143. * @param ctx
  1144. */
  1145. transformRenderingContextSet_Clamp : function(ctx) {
  1146. var m= this.matrix;
  1147. ctx.setTransform( m[0], m[3], m[1], m[4], m[2]>>0, m[5]>>0 );
  1148. return this;
  1149. },
  1150. /**
  1151. *
  1152. * @param ctx
  1153. */
  1154. transformRenderingContext_Clamp : function(ctx) {
  1155. var m= this.matrix;
  1156. ctx.transform( m[0], m[3], m[1], m[4], m[2]>>0, m[5]>>0 );
  1157. return this;
  1158. }
  1159. };
  1160. CAAT.Matrix.prototype.transformRenderingContext= CAAT.Matrix.prototype.transformRenderingContext_Clamp;
  1161. CAAT.Matrix.prototype.transformRenderingContextSet= CAAT.Matrix.prototype.transformRenderingContextSet_Clamp;
  1162. })();
  1163. (function() {
  1164. /**
  1165. * Implementation of a matrix stack. Each CAAT.Actor instance contains a MatrixStack to hold of its affine
  1166. * transformations. The Canvas rendering context will be fed with this matrix stack values to keep a homogeneous
  1167. * transformation process.
  1168. *
  1169. * @constructor
  1170. */
  1171. CAAT.MatrixStack= function() {
  1172. this.stack= [];
  1173. this.saved= [];
  1174. return this;
  1175. };
  1176. CAAT.MatrixStack.prototype= {
  1177. stack: null,
  1178. saved: null,
  1179. /**
  1180. * Add a matrix to the transformation stack.
  1181. * @return this
  1182. */
  1183. pushMatrix : function(matrix) {
  1184. this.stack.push(matrix);
  1185. return this;
  1186. },
  1187. /**
  1188. * Remove the last matrix from this stack.
  1189. * @return {CAAT.Matrix} the poped matrix.
  1190. */
  1191. popMatrix : function() {
  1192. return this.stack.pop();
  1193. },
  1194. /**
  1195. * Create a restoration point of pushed matrices.
  1196. * @return this
  1197. */
  1198. save : function() {
  1199. this.saved.push(this.stack.length);
  1200. return this;
  1201. },
  1202. /**
  1203. * Restore from the last restoration point set.
  1204. * @return this
  1205. */
  1206. restore : function() {
  1207. var pos= this.saved.pop();
  1208. while( this.stack.length!==pos ) {
  1209. this.popMatrix();
  1210. }
  1211. return this;
  1212. },
  1213. /**
  1214. * Return the concatenation (multiplication) matrix of all the matrices contained in this stack.
  1215. * @return {CAAT.Matrix} a new matrix.
  1216. */
  1217. getMatrix : function() {
  1218. var matrix= new CAAT.Matrix();
  1219. for( var i=0; i<this.stack.length; i++ ) {
  1220. var matrixStack= this.stack[i];
  1221. matrix.multiply( matrixStack );
  1222. }
  1223. return matrix;
  1224. }
  1225. };
  1226. })();/**
  1227. * See LICENSE file.
  1228. *
  1229. * @author: Mario Gonzalez (@onedayitwilltake) and Ibon Tolosana (@hyperandroid)
  1230. *
  1231. * Helper classes for color manipulation.
  1232. *
  1233. **/
  1234. (function() {
  1235. /**
  1236. * Class with color utilities.
  1237. *
  1238. * @constructor
  1239. */
  1240. CAAT.Color = function() {
  1241. return this;
  1242. };
  1243. CAAT.Color.prototype= {
  1244. /**
  1245. * HSV to RGB color conversion
  1246. * <p>
  1247. * H runs from 0 to 360 degrees<br>
  1248. * S and V run from 0 to 100
  1249. * <p>
  1250. * Ported from the excellent java algorithm by Eugene Vishnevsky at:
  1251. * http://www.cs.rit.edu/~ncs/color/t_convert.html
  1252. *
  1253. * @static
  1254. */
  1255. hsvToRgb: function(h, s, v)
  1256. {
  1257. var r, g, b;
  1258. var i;
  1259. var f, p, q, t;
  1260. // Make sure our arguments stay in-range
  1261. h = Math.max(0, Math.min(360, h));
  1262. s = Math.max(0, Math.min(100, s));
  1263. v = Math.max(0, Math.min(100, v));
  1264. // We accept saturation and value arguments from 0 to 100 because that's
  1265. // how Photoshop represents those values. Internally, however, the
  1266. // saturation and value are calculated from a range of 0 to 1. We make
  1267. // That conversion here.
  1268. s /= 100;
  1269. v /= 100;
  1270. if(s === 0) {
  1271. // Achromatic (grey)
  1272. r = g = b = v;
  1273. return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
  1274. }
  1275. h /= 60; // sector 0 to 5
  1276. i = Math.floor(h);
  1277. f = h - i; // factorial part of h
  1278. p = v * (1 - s);
  1279. q = v * (1 - s * f);
  1280. t = v * (1 - s * (1 - f));
  1281. switch(i) {
  1282. case 0:
  1283. r = v;
  1284. g = t;
  1285. b = p;
  1286. break;
  1287. case 1:
  1288. r = q;
  1289. g = v;
  1290. b = p;
  1291. break;
  1292. case 2:
  1293. r = p;
  1294. g = v;
  1295. b = t;
  1296. break;
  1297. case 3:
  1298. r = p;
  1299. g = q;
  1300. b = v;
  1301. break;
  1302. case 4:
  1303. r = t;
  1304. g = p;
  1305. b = v;
  1306. break;
  1307. default: // case 5:
  1308. r = v;
  1309. g = p;
  1310. b = q;
  1311. }
  1312. return new CAAT.Color.RGB(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255));
  1313. },
  1314. /**
  1315. * Enumeration to define types of color ramps.
  1316. * @enum {number}
  1317. */
  1318. RampEnumeration : {
  1319. RAMP_RGBA: 0,
  1320. RAMP_RGB: 1,
  1321. RAMP_CHANNEL_RGB: 2,
  1322. RAMP_CHANNEL_RGBA: 3,
  1323. RAMP_CHANNEL_RGB_ARRAY: 4,
  1324. RAMP_CHANNEL_RGBA_ARRAY:5
  1325. },
  1326. /**
  1327. * Interpolate the color between two given colors. The return value will be a calculated color
  1328. * among the two given initial colors which corresponds to the 'step'th color of the 'nsteps'
  1329. * calculated colors.
  1330. * @param r0 {number} initial color red component.
  1331. * @param g0 {number} initial color green component.
  1332. * @param b0 {number} initial color blue component.
  1333. * @param r1 {number} final color red component.
  1334. * @param g1 {number} final color green component.
  1335. * @param b1 {number} final color blue component.
  1336. * @param nsteps {number} number of colors to calculate including the two given colors. If 16 is passed as value,
  1337. * 14 colors plus the two initial ones will be calculated.
  1338. * @param step {number} return this color index of all the calculated colors.
  1339. *
  1340. * @return { r{number}, g{number}, b{number} } return an object with the new calculated color components.
  1341. * @static
  1342. */
  1343. interpolate : function( r0, g0, b0, r1, g1, b1, nsteps, step) {
  1344. if ( step<=0 ) {
  1345. return {
  1346. r:r0,
  1347. g:g0,
  1348. b:b0
  1349. };
  1350. } else if ( step>=nsteps ) {
  1351. return {
  1352. r:r1,
  1353. g:g1,
  1354. b:b1
  1355. };
  1356. }
  1357. var r= (r0+ (r1-r0)/nsteps*step)>>0;
  1358. var g= (g0+ (g1-g0)/nsteps*step)>>0;
  1359. var b= (b0+ (b1-b0)/nsteps*step)>>0;
  1360. if ( r>255 ) {r=255;} else if (r<0) {r=0;}
  1361. if ( g>255 ) {g=255;} else if (g<0) {g=0;}
  1362. if ( b>255 ) {b=255;} else if (b<0) {b=0;}
  1363. return {
  1364. r:r,
  1365. g:g,
  1366. b:b
  1367. };
  1368. },
  1369. /**
  1370. * Generate a ramp of colors from an array of given colors.
  1371. * @param fromColorsArray {[number]} an array of colors. each color is defined by an integer number from which
  1372. * color components will be extracted. Be aware of the alpha component since it will also be interpolated for
  1373. * new colors.
  1374. * @param rampSize {number} number of colors to produce.
  1375. * @param returnType {CAAT.ColorUtils.RampEnumeration} a value of CAAT.ColorUtils.RampEnumeration enumeration.
  1376. *
  1377. * @return { [{number},{number},{number},{number}] } an array of integers each of which represents a color of
  1378. * the calculated color ramp.
  1379. *
  1380. * @static
  1381. */
  1382. makeRGBColorRamp : function( fromColorsArray, rampSize, returnType ) {
  1383. var ramp= [];
  1384. var nc= fromColorsArray.length-1;
  1385. var chunk= rampSize/nc;
  1386. for( var i=0; i<nc; i++ ) {
  1387. var c= fromColorsArray[i];
  1388. var a0= (c>>24)&0xff;
  1389. var r0= (c&0xff0000)>>16;
  1390. var g0= (c&0xff00)>>8;
  1391. var b0= c&0xff;
  1392. var c1= fromColorsArray[i+1];
  1393. var a1= (c1>>24)&0xff;
  1394. var r1= (c1&0xff0000)>>16;
  1395. var g1= (c1&0xff00)>>8;
  1396. var b1= c1&0xff;
  1397. var da= (a1-a0)/chunk;
  1398. var dr= (r1-r0)/chunk;
  1399. var dg= (g1-g0)/chunk;
  1400. var db= (b1-b0)/chunk;
  1401. for( var j=0; j<chunk; j++ ) {
  1402. var na= (a0+da*j)>>0;
  1403. var nr= (r0+dr*j)>>0;
  1404. var ng= (g0+dg*j)>>0;
  1405. var nb= (b0+db*j)>>0;
  1406. switch( returnType ) {
  1407. case this.RampEnumeration.RAMP_RGBA:
  1408. ramp.push( 'argb('+na+','+nr+','+ng+','+nb+')' );
  1409. break;
  1410. case this.RampEnumeration.RAMP_RGB:
  1411. ramp.push( 'rgb('+nr+','+ng+','+nb+')' );
  1412. break;
  1413. case this.RampEnumeration.RAMP_CHANNEL_RGB:
  1414. ramp.push( 0xff000000 | nr<<16 | ng<<8 | nb );
  1415. break;
  1416. case this.RampEnumeration.RAMP_CHANNEL_RGBA:
  1417. ramp.push( na<<24 | nr<<16 | ng<<8 | nb );
  1418. break;
  1419. case this.RampEnumeration.RAMP_CHANNEL_RGBA_ARRAY:
  1420. ramp.push([ nr, ng, nb, na ]);
  1421. break;
  1422. case this.RampEnumeration.RAMP_CHANNEL_RGB_ARRAY:
  1423. ramp.push([ nr, ng, nb ]);
  1424. break;
  1425. }
  1426. }
  1427. }
  1428. return ramp;
  1429. }
  1430. };
  1431. })();
  1432. (function() {
  1433. /**
  1434. * RGB color implementation
  1435. * @param r {number} an integer in the range 0..255
  1436. * @param g {number} an integer in the range 0..255
  1437. * @param b {number} an integer in the range 0..255
  1438. *
  1439. * @constructor
  1440. */
  1441. CAAT.Color.RGB = function(r, g, b) {
  1442. this.r = r || 255;
  1443. this.g = g || 255;
  1444. this.b = b || 255;
  1445. return this;
  1446. };
  1447. CAAT.Color.RGB.prototype= {
  1448. r: 255,
  1449. g: 255,
  1450. b: 255,
  1451. /**
  1452. * Get color hexadecimal representation.
  1453. * @return {string} a string with color hexadecimal representation.
  1454. */
  1455. toHex: function() {
  1456. // See: http://jsperf.com/rgb-decimal-to-hex/5
  1457. return ('000000' + ((this.r << 16) + (this.g << 8) + this.b).toString(16)).slice(-6);
  1458. }
  1459. };
  1460. })();
  1461. /**
  1462. * See LICENSE file.
  1463. *
  1464. * Rectangle Class.
  1465. * Needed to compute Curve bounding box.
  1466. * Needed to compute Actor affected area on change.
  1467. *
  1468. **/
  1469. (function() {
  1470. /**
  1471. * A Rectangle implementation, which defines an area positioned somewhere.
  1472. *
  1473. * @constructor
  1474. */
  1475. CAAT.Rectangle= function() {
  1476. return this;
  1477. };
  1478. CAAT.Rectangle.prototype= {
  1479. x: 0,
  1480. y: 0,
  1481. x1: 0,
  1482. y1: 0,
  1483. width: -1,
  1484. height: -1,
  1485. setEmpty : function() {
  1486. this.width= -1;
  1487. this.height= -1;
  1488. this.x= 0;
  1489. this.y= 0;
  1490. this.x1= 0;
  1491. this.y1= 0;
  1492. return this;
  1493. },
  1494. /**
  1495. * Set this rectangle's location.
  1496. * @param x {number}
  1497. * @param y {number}
  1498. */
  1499. setLocation: function( x,y ) {
  1500. this.x= x;
  1501. this.y= y;
  1502. this.x1= this.x+this.width;
  1503. this.y1= this.y+this.height;
  1504. return this;
  1505. },
  1506. /**
  1507. * Set this rectangle's dimension.
  1508. * @param w {number}
  1509. * @param h {number}
  1510. */
  1511. setDimension : function( w,h ) {
  1512. this.width= w;
  1513. this.height= h;
  1514. this.x1= this.x+this.width;
  1515. this.y1= this.y+this.height;
  1516. return this;
  1517. },
  1518. setBounds : function( x,y,w,h ) {
  1519. this.setLocation( x, y )
  1520. this.setDimension( w, h );
  1521. return this;
  1522. },
  1523. /**
  1524. * Return whether the coordinate is inside this rectangle.
  1525. * @param px {number}
  1526. * @param py {number}
  1527. *
  1528. * @return {boolean}
  1529. */
  1530. contains : function(px,py) {
  1531. return px>=0 && px<this.width && py>=0 && py<this.height;
  1532. },
  1533. /**
  1534. * Return whether this rectangle is empty, that is, has zero dimension.
  1535. * @return {boolean}
  1536. */
  1537. isEmpty : function() {
  1538. return this.width===-1 && this.height===-1;
  1539. },
  1540. /**
  1541. * Set this rectangle as the union of this rectangle and the given point.
  1542. * @param px {number}
  1543. * @param py {number}
  1544. */
  1545. union : function(px,py) {
  1546. if ( this.isEmpty() ) {
  1547. this.x= px;
  1548. this.x1= px;
  1549. this.y= py;
  1550. this.y1= py;
  1551. this.width=0;
  1552. this.height=0;
  1553. return;
  1554. }
  1555. this.x1= this.x+this.width;
  1556. this.y1= this.y+this.height;
  1557. if ( py<this.y ) {
  1558. this.y= py;
  1559. }
  1560. if ( px<this.x ) {
  1561. this.x= px;
  1562. }
  1563. if ( py>this.y1 ) {
  1564. this.y1= py;
  1565. }
  1566. if ( px>this.x1 ){
  1567. this.x1= px;
  1568. }
  1569. this.width= this.x1-this.x;
  1570. this.height= this.y1-this.y;
  1571. },
  1572. unionRectangle : function( rectangle ) {
  1573. this.union( rectangle.x , rectangle.y );
  1574. this.union( rectangle.x1, rectangle.y );
  1575. this.union( rectangle.x, rectangle.y1 );
  1576. this.union( rectangle.x1, rectangle.y1 );
  1577. return this;
  1578. },
  1579. intersects : function( r ) {
  1580. if ( r.isEmpty() || this.isEmpty() ) {
  1581. return false;
  1582. }
  1583. if ( r.x1<= this.x ) {
  1584. return false;
  1585. }
  1586. if ( r.x >= this.x1 ) {
  1587. return false;
  1588. }
  1589. if ( r.y1<= this.y ) {
  1590. return false;
  1591. }
  1592. if ( r.y>= this.y1 ) {
  1593. return false;
  1594. }
  1595. return true;
  1596. },
  1597. intersectsRect : function( x,y,w,h ) {
  1598. if ( -1===w || -1===h ) {
  1599. return false;
  1600. }
  1601. var x1= x+w-1;
  1602. var y1= y+h-1;
  1603. if ( x1< this.x ) {
  1604. return false;
  1605. }
  1606. if ( x > this.x1 ) {
  1607. return false;
  1608. }
  1609. if ( y1< this.y ) {
  1610. return false;
  1611. }
  1612. if ( y> this.y1 ) {
  1613. return false;
  1614. }
  1615. return true;
  1616. },
  1617. intersect : function( i, r ) {
  1618. if ( typeof r==='undefined' ) {
  1619. r= new CAAT.Rectangle();
  1620. }
  1621. r.x= Math.max( this.x, i.x );
  1622. r.y= Math.max( this.y, i.y );
  1623. r.x1=Math.min( this.x1, i.x1 );
  1624. r.y1=Math.min( this.y1, i.y1 );
  1625. r.width= r.x1-r.x;
  1626. r.height=r.y1-r.y;
  1627. return r;
  1628. }
  1629. };
  1630. })();/**
  1631. * See LICENSE file.
  1632. *
  1633. * Classes to solve and draw curves.
  1634. * Curve is the superclass of
  1635. * + Bezier (quadric and cubic)
  1636. * + CatmullRom
  1637. *
  1638. *
  1639. **/
  1640. (function() {
  1641. /**
  1642. *
  1643. * Curve class is the base for all curve solvers available in CAAT.
  1644. *
  1645. * @constructor
  1646. */
  1647. CAAT.Curve= function() {
  1648. return this;
  1649. };
  1650. CAAT.Curve.prototype= {
  1651. coordlist: null,
  1652. k: 0.05,
  1653. length: -1,
  1654. interpolator: false,
  1655. HANDLE_SIZE: 20,
  1656. drawHandles: true,
  1657. /**
  1658. * Paint the curve control points.
  1659. * @param director {CAAT.Director}
  1660. */
  1661. paint: function(director) {
  1662. if ( false===this.drawHandles ) {
  1663. return;
  1664. }
  1665. var cl= this.coordlist;
  1666. var ctx= director.ctx;
  1667. // control points
  1668. ctx.save();
  1669. ctx.beginPath();
  1670. ctx.strokeStyle='#a0a0a0';
  1671. ctx.moveTo( cl[0].x, cl[0].y );
  1672. ctx.lineTo( cl[1].x, cl[1].y );
  1673. ctx.stroke();
  1674. if ( this.cubic ) {
  1675. ctx.moveTo( cl[2].x, cl[2].y );
  1676. ctx.lineTo( cl[3].x, cl[3].y );
  1677. ctx.stroke();
  1678. }
  1679. ctx.globalAlpha=0.5;
  1680. for( var i=0; i<this.coordlist.length; i++ ) {
  1681. ctx.fillStyle='#7f7f00';
  1682. var w= CAAT.Curve.prototype.HANDLE_SIZE/2;
  1683. ctx.fillRect( cl[i].x-w, cl[i].y-w, w*2, w*2 );
  1684. }
  1685. ctx.restore();
  1686. },
  1687. /**
  1688. * Signal the curve has been modified and recalculate curve length.
  1689. */
  1690. update : function() {
  1691. this.calcLength();
  1692. },
  1693. /**
  1694. * This method must be overriden by subclasses. It is called whenever the curve must be solved for some time=t.
  1695. * The t parameter must be in the range 0..1
  1696. * @param point {CAAT.Point} to store curve solution for t.
  1697. * @param t {number}
  1698. * @return {CAAT.Point} the point parameter.
  1699. */
  1700. solve: function(point,t) {
  1701. },
  1702. /**
  1703. * Get an array of points defining the curve contour.
  1704. * @param numSamples {number} number of segments to get.
  1705. */
  1706. getContour : function(numSamples) {
  1707. var contour= [], i;
  1708. for( i=0; i<=numSamples; i++ ) {
  1709. var point= new CAAT.Point();
  1710. this.solve( point, i/numSamples );
  1711. contour.push(point);
  1712. }
  1713. return contour;
  1714. },
  1715. /**
  1716. * Calculates a curve bounding box.
  1717. *
  1718. * @param rectangle {CAAT.Rectangle} a rectangle to hold the bounding box.
  1719. * @return {CAAT.Rectangle} the rectangle parameter.
  1720. */
  1721. getBoundingBox : function(rectangle) {
  1722. if ( !rectangle ) {
  1723. rectangle= new CAAT.Rectangle();
  1724. }
  1725. // thanks yodesoft.com for spotting the first point is out of the BB
  1726. rectangle.setEmpty();
  1727. rectangle.union( this.coordlist[0].x, this.coordlist[0].y );
  1728. var pt= new CAAT.Point();
  1729. for(var t=this.k;t<=1+this.k;t+=this.k){
  1730. this.solve(pt,t);
  1731. rectangle.union( pt.x, pt.y );
  1732. }
  1733. return rectangle;
  1734. },
  1735. /**
  1736. * Calculate the curve length by incrementally solving the curve every substep=CAAT.Curve.k. This value defaults
  1737. * to .05 so at least 20 iterations will be performed.
  1738. *
  1739. * @return {number} the approximate curve length.
  1740. */
  1741. calcLength : function() {
  1742. var x1,y1;
  1743. x1 = this.coordlist[0].x;
  1744. y1 = this.coordlist[0].y;
  1745. var llength=0;
  1746. var pt= new CAAT.Point();
  1747. for(var t=this.k;t<=1+this.k;t+=this.k){
  1748. this.solve(pt,t);
  1749. llength+= Math.sqrt( (pt.x-x1)*(pt.x-x1) + (pt.y-y1)*(pt.y-y1) );
  1750. x1=pt.x;
  1751. y1=pt.y;
  1752. }
  1753. this.length= llength;
  1754. return llength;
  1755. },
  1756. /**
  1757. * Return the cached curve length.
  1758. * @return {number} the cached curve length.
  1759. */
  1760. getLength : function() {
  1761. return this.length;
  1762. },
  1763. /**
  1764. * Return the first curve control point.
  1765. * @return {CAAT.Point}
  1766. */
  1767. endCurvePosition : function() {
  1768. return this.coordlist[ this.coordlist.length-1 ];
  1769. },
  1770. /**
  1771. * Return the last curve control point.
  1772. * @return {CAAT.Point}
  1773. */
  1774. startCurvePosition : function() {
  1775. return this.coordlist[ 0 ];
  1776. },
  1777. setPoints : function( points ) {
  1778. },
  1779. setPoint : function( point, index ) {
  1780. if ( index>=0 && index<this.coordlist.length ) {
  1781. this.coordlist[index]= point;
  1782. }
  1783. },
  1784. /**
  1785. *
  1786. * @param director <=CAAT.Director>
  1787. */
  1788. applyAsPath : function( director ) {
  1789. }
  1790. };
  1791. })();
  1792. (function() {
  1793. /**
  1794. * Bezier quadric and cubic curves implementation.
  1795. *
  1796. * @constructor
  1797. * @extends CAAT.Curve
  1798. */
  1799. CAAT.Bezier= function() {
  1800. CAAT.Bezier.superclass.constructor.call(this);
  1801. return this;
  1802. };
  1803. CAAT.Bezier.prototype= {
  1804. cubic: false,
  1805. applyAsPath : function( director ) {
  1806. var cc= this.coordlist;
  1807. if ( this.cubic ) {
  1808. director.ctx.bezierCurveTo(
  1809. cc[1].x,
  1810. cc[1].y,
  1811. cc[2].x,
  1812. cc[2].y,
  1813. cc[3].x,
  1814. cc[3].y
  1815. );
  1816. } else {
  1817. director.ctx.quadraticCurveTo(
  1818. cc[1].x,
  1819. cc[1].y,
  1820. cc[2].x,
  1821. cc[2].y
  1822. );
  1823. }
  1824. return this;
  1825. },
  1826. isQuadric : function() {
  1827. return !this.cubic;
  1828. },
  1829. isCubic : function() {
  1830. return this.cubic;
  1831. },
  1832. /**
  1833. * Set this curve as a cubic bezier defined by the given four control points.
  1834. * @param cp0x {number}
  1835. * @param cp0y {number}
  1836. * @param cp1x {number}
  1837. * @param cp1y {number}
  1838. * @param cp2x {number}
  1839. * @param cp2y {number}
  1840. * @param cp3x {number}
  1841. * @param cp3y {number}
  1842. */
  1843. setCubic : function( cp0x,cp0y, cp1x,cp1y, cp2x,cp2y, cp3x,cp3y ) {
  1844. this.coordlist= [];
  1845. this.coordlist.push( new CAAT.Point().set(cp0x, cp0y ) );
  1846. this.coordlist.push( new CAAT.Point().set(cp1x, cp1y ) );
  1847. this.coordlist.push( new CAAT.Point().set(cp2x, cp2y ) );
  1848. this.coordlist.push( new CAAT.Point().set(cp3x, cp3y ) );
  1849. this.cubic= true;
  1850. this.update();
  1851. return this;
  1852. },
  1853. /**
  1854. * Set this curve as a quadric bezier defined by the three control points.
  1855. * @param cp0x {number}
  1856. * @param cp0y {number}
  1857. * @param cp1x {number}
  1858. * @param cp1y {number}
  1859. * @param cp2x {number}
  1860. * @param cp2y {number}
  1861. */
  1862. setQuadric : function(cp0x,cp0y, cp1x,cp1y, cp2x,cp2y ) {
  1863. this.coordlist= [];
  1864. this.coordlist.push( new CAAT.Point().set(cp0x, cp0y ) );
  1865. this.coordlist.push( new CAAT.Point().set(cp1x, cp1y ) );
  1866. this.coordlist.push( new CAAT.Point().set(cp2x, cp2y ) );
  1867. this.cubic= false;
  1868. this.update();
  1869. return this;
  1870. },
  1871. setPoints : function( points ) {
  1872. if ( points.length===3 ) {
  1873. this.coordlist= points;
  1874. this.cubic= false;
  1875. this.update();
  1876. } else if (points.length===4 ) {
  1877. this.coordlist= points;
  1878. this.cubic= true;
  1879. this.update();
  1880. } else {
  1881. throw 'points must be an array of 3 or 4 CAAT.Point instances.'
  1882. }
  1883. return this;
  1884. },
  1885. /**
  1886. * Paint this curve.
  1887. * @param director {CAAT.Director}
  1888. */
  1889. paint : function( director ) {
  1890. if ( this.cubic ) {
  1891. this.paintCubic(director);
  1892. } else {
  1893. this.paintCuadric( director );
  1894. }
  1895. CAAT.Bezier.superclass.paint.call(this,director);
  1896. },
  1897. /**
  1898. * Paint this quadric Bezier curve. Each time the curve is drawn it will be solved again from 0 to 1 with
  1899. * CAAT.Bezier.k increments.
  1900. *
  1901. * @param director {CAAT.Director}
  1902. * @private
  1903. */
  1904. paintCuadric : function( director ) {
  1905. var x1,y1;
  1906. x1 = this.coordlist[0].x;
  1907. y1 = this.coordlist[0].y;
  1908. var ctx= director.ctx;
  1909. ctx.save();
  1910. ctx.beginPath();
  1911. ctx.moveTo(x1,y1);
  1912. var point= new CAAT.Point();
  1913. for(var t=this.k;t<=1+this.k;t+=this.k){
  1914. this.solve(point,t);
  1915. ctx.lineTo(point.x, point.y );
  1916. }
  1917. ctx.stroke();
  1918. ctx.restore();
  1919. },
  1920. /**
  1921. * Paint this cubic Bezier curve. Each time the curve is drawn it will be solved again from 0 to 1 with
  1922. * CAAT.Bezier.k increments.
  1923. *
  1924. * @param director {CAAT.Director}
  1925. * @private
  1926. */
  1927. paintCubic : function( director ) {
  1928. var x1,y1;
  1929. x1 = this.coordlist[0].x;
  1930. y1 = this.coordlist[0].y;
  1931. var ctx= director.ctx;
  1932. ctx.save();
  1933. ctx.beginPath();
  1934. ctx.moveTo(x1,y1);
  1935. var point= new CAAT.Point();
  1936. for(var t=this.k;t<=1+this.k;t+=this.k){
  1937. this.solve(point,t);
  1938. ctx.lineTo(point.x, point.y );
  1939. }
  1940. ctx.stroke();
  1941. ctx.restore();
  1942. },
  1943. /**
  1944. * Solves the curve for any given parameter t.
  1945. * @param point {CAAT.Point} the point to store the solved value on the curve.
  1946. * @param t {number} a number in the range 0..1
  1947. */
  1948. solve : function(point,t) {
  1949. if ( this.cubic ) {
  1950. return this.solveCubic(point,t);
  1951. } else {
  1952. return this.solveQuadric(point,t);
  1953. }
  1954. },
  1955. /**
  1956. * Solves a cubic Bezier.
  1957. * @param point {CAAT.Point} the point to store the solved value on the curve.
  1958. * @param t {number} the value to solve the curve for.
  1959. */
  1960. solveCubic : function(point,t) {
  1961. var t2= t*t;
  1962. var t3= t*t2;
  1963. var cl= this.coordlist;
  1964. var cl0= cl[0];
  1965. var cl1= cl[1];
  1966. var cl2= cl[2];
  1967. var cl3= cl[3];
  1968. point.x=(
  1969. cl0.x + t * (-cl0.x * 3 + t * (3 * cl0.x-
  1970. cl0.x*t)))+t*(3*cl1.x+t*(-6*cl1.x+
  1971. cl1.x*3*t))+t2*(cl2.x*3-cl2.x*3*t)+
  1972. cl3.x * t3;
  1973. point.y=(
  1974. cl0.y+t*(-cl0.y*3+t*(3*cl0.y-
  1975. cl0.y*t)))+t*(3*cl1.y+t*(-6*cl1.y+
  1976. cl1.y*3*t))+t2*(cl2.y*3-cl2.y*3*t)+
  1977. cl3.y * t3;
  1978. return point;
  1979. },
  1980. /**
  1981. * Solves a quadric Bezier.
  1982. * @param point {CAAT.Point} the point to store the solved value on the curve.
  1983. * @param t {number} the value to solve the curve for.
  1984. */
  1985. solveQuadric : function(point,t) {
  1986. var cl= this.coordlist;
  1987. var cl0= cl[0];
  1988. var cl1= cl[1];
  1989. var cl2= cl[2];
  1990. var t1= 1-t;
  1991. point.x= t1*t1*cl0.x + 2*t1*t*cl1.x + t*t*cl2.x;
  1992. point.y= t1*t1*cl0.y + 2*t1*t*cl1.y + t*t*cl2.y;
  1993. return point;
  1994. }
  1995. };
  1996. extend(CAAT.Bezier, CAAT.Curve, null);
  1997. })();
  1998. (function() {
  1999. /**
  2000. * CatmullRom curves solver implementation.
  2001. * <p>
  2002. * This object manages one single catmull rom segment, that is 4 points.
  2003. * A complete spline should be managed with CAAT.Path.setCatmullRom with a complete list of points.
  2004. *
  2005. * @constructor
  2006. * @extends CAAT.Curve
  2007. */
  2008. CAAT.CatmullRom = function() {
  2009. CAAT.CatmullRom.superclass.constructor.call(this);
  2010. return this;
  2011. };
  2012. CAAT.CatmullRom.prototype= {
  2013. /**
  2014. * Set curve control points.
  2015. * @param p0 <CAAT.Point>
  2016. * @param p1 <CAAT.Point>
  2017. * @param p2 <CAAT.Point>
  2018. * @param p3 <CAAT.Point>
  2019. */
  2020. setCurve : function( p0, p1, p2, p3 ) {
  2021. this.coordlist= [];
  2022. this.coordlist.push( p0 );
  2023. this.coordlist.push( p1 );
  2024. this.coordlist.push( p2 );
  2025. this.coordlist.push( p3 );
  2026. this.update();
  2027. return this;
  2028. },
  2029. /**
  2030. * Paint the contour by solving again the entire curve.
  2031. * @param director {CAAT.Director}
  2032. */
  2033. paint: function(director) {
  2034. var x1,y1;
  2035. // Catmull rom solves from point 1 !!!
  2036. x1 = this.coordlist[1].x;
  2037. y1 = this.coordlist[1].y;
  2038. var ctx= director.ctx;
  2039. ctx.save();
  2040. ctx.beginPath();
  2041. ctx.moveTo(x1,y1);
  2042. var point= new CAAT.Point();
  2043. for(var t=this.k;t<=1+this.k;t+=this.k){
  2044. this.solve(point,t);
  2045. ctx.lineTo(point.x,point.y);
  2046. }
  2047. ctx.stroke();
  2048. ctx.restore();
  2049. CAAT.CatmullRom.superclass.paint.call(this,director);
  2050. },
  2051. /**
  2052. * Solves the curve for any given parameter t.
  2053. * @param point {CAAT.Point} the point to store the solved value on the curve.
  2054. * @param t {number} a number in the range 0..1
  2055. */
  2056. solve: function(point,t) {
  2057. var c= this.coordlist;
  2058. // Handy from CAKE. Thanks.
  2059. var af = ((-t+2)*t-1)*t*0.5
  2060. var bf = (((3*t-5)*t)*t+2)*0.5
  2061. var cf = ((-3*t+4)*t+1)*t*0.5
  2062. var df = ((t-1)*t*t)*0.5
  2063. point.x= c[0].x * af + c[1].x * bf + c[2].x * cf + c[3].x * df;
  2064. point.y= c[0].y * af + c[1].y * bf + c[2].y * cf + c[3].y * df;
  2065. return point;
  2066. },
  2067. applyAsPath : function( director ) {
  2068. var ctx= director.ctx;
  2069. var point= new CAAT.Point();
  2070. for(var t=this.k;t<=1+this.k;t+=this.k){
  2071. this.solve(point,t);
  2072. ctx.lineTo(point.x,point.y);
  2073. }
  2074. return this;
  2075. },
  2076. /**
  2077. * Return the first curve control point.
  2078. * @return {CAAT.Point}
  2079. */
  2080. endCurvePosition : function() {
  2081. return this.coordlist[ this.coordlist.length-2 ];
  2082. },
  2083. /**
  2084. * Return the last curve control point.
  2085. * @return {CAAT.Point}
  2086. */
  2087. startCurvePosition : function() {
  2088. return this.coordlist[ 1 ];
  2089. }
  2090. };
  2091. extend(CAAT.CatmullRom, CAAT.Curve, null);
  2092. })();/**
  2093. * See LICENSE file.
  2094. *
  2095. * Hold a 2D point information.
  2096. * Think about the possibility of turning CAAT.Point into {x:,y:}.
  2097. *
  2098. **/
  2099. (function() {
  2100. /**
  2101. *
  2102. * A point defined by two coordinates.
  2103. *
  2104. * @param xpos {number}
  2105. * @param ypos {number}
  2106. *
  2107. * @constructor
  2108. */
  2109. CAAT.Point= function(xpos, ypos, zpos) {
  2110. this.x= xpos;
  2111. this.y= ypos;
  2112. this.z= zpos||0;
  2113. return this;
  2114. };
  2115. CAAT.Point.prototype= {
  2116. x: 0,
  2117. y: 0,
  2118. z: 0,
  2119. /**
  2120. * Sets this point coordinates.
  2121. * @param x {number}
  2122. * @param y {number}
  2123. *
  2124. * @return this
  2125. */
  2126. set : function(x,y,z) {
  2127. this.x= x;
  2128. this.y= y;
  2129. this.z= z||0;
  2130. return this;
  2131. },
  2132. /**
  2133. * Create a new CAAT.Point equal to this one.
  2134. * @return {CAAT.Point}
  2135. */
  2136. clone : function() {
  2137. var p= new CAAT.Point(this.x, this.y, this.z );
  2138. return p;
  2139. },
  2140. /**
  2141. * Translate this point to another position. The final point will be (point.x+x, point.y+y)
  2142. * @param x {number}
  2143. * @param y {number}
  2144. *
  2145. * @return this
  2146. */
  2147. translate : function(x,y,z) {
  2148. this.x+= x;
  2149. this.y+= y;
  2150. this.z+= z;
  2151. return this;
  2152. },
  2153. /**
  2154. * Translate this point to another point.
  2155. * @param aPoint {CAAT.Point}
  2156. * @return this
  2157. */
  2158. translatePoint: function(aPoint) {
  2159. this.x += aPoint.x;
  2160. this.y += aPoint.y;
  2161. this.z += aPoint.z;
  2162. return this;
  2163. },
  2164. /**
  2165. * Substract a point from this one.
  2166. * @param aPoint {CAAT.Point}
  2167. * @return this
  2168. */
  2169. subtract: function(aPoint) {
  2170. this.x -= aPoint.x;
  2171. this.y -= aPoint.y;
  2172. this.z -= aPoint.z;
  2173. return this;
  2174. },
  2175. /**
  2176. * Multiply this point by a scalar.
  2177. * @param factor {number}
  2178. * @return this
  2179. */
  2180. multiply: function(factor) {
  2181. this.x *= factor;
  2182. this.y *= factor;
  2183. this.z *= factor;
  2184. return this;
  2185. },
  2186. /**
  2187. * Rotate this point by an angle. The rotation is held by (0,0) coordinate as center.
  2188. * @param angle {number}
  2189. * @return this
  2190. */
  2191. rotate: function(angle) {
  2192. var x = this.x, y = this.y;
  2193. this.x = x * Math.cos(angle) - Math.sin(angle) * y;
  2194. this.y = x * Math.sin(angle) + Math.cos(angle) * y;
  2195. this.z = 0;
  2196. return this;
  2197. },
  2198. /**
  2199. *
  2200. * @param angle {number}
  2201. * @return this
  2202. */
  2203. setAngle: function(angle) {
  2204. var len = this.getLength();
  2205. this.x = Math.cos(angle) * len;
  2206. this.y = Math.sin(angle) * len;
  2207. this.z = 0;
  2208. return this;
  2209. },
  2210. /**
  2211. *
  2212. * @param length {number}
  2213. * @return this
  2214. */
  2215. setLength: function(length) {
  2216. var len = this.getLength();
  2217. if (len)this.multiply(length / len);
  2218. else this.x = this.y = this.z = length;
  2219. return this;
  2220. },
  2221. /**
  2222. * Normalize this point, that is, both set coordinates proportionally to values raning 0..1
  2223. * @return this
  2224. */
  2225. normalize: function() {
  2226. var len = this.getLength();
  2227. this.x /= len;
  2228. this.y /= len;
  2229. this.z /= len;
  2230. return this;
  2231. },
  2232. /**
  2233. * Return the angle from -Pi to Pi of this point.
  2234. * @return {number}
  2235. */
  2236. getAngle: function() {
  2237. return Math.atan2(this.y, this.x);
  2238. },
  2239. /**
  2240. * Set this point coordinates proportinally to a maximum value.
  2241. * @param max {number}
  2242. * @return this
  2243. */
  2244. limit: function(max) {
  2245. var aLenthSquared = this.getLengthSquared();
  2246. if(aLenthSquared+0.01 > max*max)
  2247. {
  2248. var aLength = Math.sqrt(aLenthSquared);
  2249. this.x= (this.x/aLength) * max;
  2250. this.y= (this.y/aLength) * max;
  2251. this.z= (this.z/aLength) * max;
  2252. }
  2253. return this;
  2254. },
  2255. /**
  2256. * Get this point's lenght.
  2257. * @return {number}
  2258. */
  2259. getLength: function() {
  2260. var length = Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z);
  2261. if ( length < 0.005 && length > -0.005) return 0.000001;
  2262. return length;
  2263. },
  2264. /**
  2265. * Get this point's squared length.
  2266. * @return {number}
  2267. */
  2268. getLengthSquared: function() {
  2269. var lengthSquared = this.x*this.x + this.y*this.y + this.z*this.z;
  2270. if ( lengthSquared < 0.005 && lengthSquared > -0.005) return 0;
  2271. return lengthSquared;
  2272. },
  2273. /**
  2274. * Get the distance between two points.
  2275. * @param point {CAAT.Point}
  2276. * @return {number}
  2277. */
  2278. getDistance: function(point) {
  2279. var deltaX = this.x - point.x;
  2280. var deltaY = this.y - point.y;
  2281. var deltaZ = this.z - point.z;
  2282. return Math.sqrt( deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ );
  2283. },
  2284. /**
  2285. * Get the squared distance between two points.
  2286. * @param point {CAAT.Point}
  2287. * @return {number}
  2288. */
  2289. getDistanceSquared: function(point) {
  2290. var deltaX = this.x - point.x;
  2291. var deltaY = this.y - point.y;
  2292. var deltaZ = this.z - point.z;
  2293. return deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ;
  2294. },
  2295. /**
  2296. * Get a string representation.
  2297. * @return {string}
  2298. */
  2299. toString: function() {
  2300. return "(CAAT.Point)" +
  2301. " x:" + String(Math.round(Math.floor(this.x*10))/10) +
  2302. " y:" + String(Math.round(Math.floor(this.y*10))/10) +
  2303. " z:" + String(Math.round(Math.floor(this.z*10))/10);
  2304. }
  2305. };
  2306. })();/**
  2307. * See LICENSE file.
  2308. *
  2309. * This file contains the definition for objects QuadTree and HashMap.
  2310. * Quadtree offers an exact list of collisioning areas, while HashMap offers a list of potentially colliding elements.
  2311. *
  2312. **/
  2313. (function() {
  2314. CAAT.QuadTree= function() {
  2315. return this;
  2316. };
  2317. var QT_MAX_ELEMENTS= 1;
  2318. var QT_MIN_WIDTH= 32;
  2319. CAAT.QuadTree.prototype= {
  2320. bgActors : null,
  2321. quadData : null,
  2322. create : function( l,t, r,b, backgroundElements, minWidth, maxElements ) {
  2323. if ( typeof minWidth==='undefined' ) {
  2324. minWidth= QT_MIN_WIDTH;
  2325. }
  2326. if ( typeof maxElements==='undefined' ) {
  2327. maxElements= QT_MAX_ELEMENTS;
  2328. }
  2329. var cx= (l+r)/2;
  2330. var cy= (t+b)/2;
  2331. this.x= l;
  2332. this.y= t;
  2333. this.x1= r;
  2334. this.y1= b;
  2335. this.width= r-l;
  2336. this.height= b-t;
  2337. this.bgActors= this.__getOverlappingActorList( backgroundElements );
  2338. if ( this.bgActors.length <= maxElements || this.width <= minWidth ) {
  2339. return this;
  2340. }
  2341. this.quadData= new Array(4);
  2342. this.quadData[0]= new CAAT.QuadTree().create( l,t,cx,cy, this.bgActors ); // TL
  2343. this.quadData[1]= new CAAT.QuadTree().create( cx,t,r,cy, this.bgActors ); // TR
  2344. this.quadData[2]= new CAAT.QuadTree().create( l,cy,cx,b, this.bgActors ); // BL
  2345. this.quadData[3]= new CAAT.QuadTree().create( cx,cy,r,b, this.bgActors );
  2346. return this;
  2347. },
  2348. __getOverlappingActorList : function( actorList ) {
  2349. var tmpList= [];
  2350. for( var i=0, l=actorList.length; i<l; i++ ) {
  2351. var actor= actorList[i];
  2352. if ( this.intersects( actor.AABB ) ) {
  2353. tmpList.push( actor );
  2354. }
  2355. }
  2356. return tmpList;
  2357. },
  2358. getOverlappingActors : function( rectangle ) {
  2359. var i,j,l;
  2360. var overlappingActors= [];
  2361. var qoverlappingActors;
  2362. var actors= this.bgActors;
  2363. var actor;
  2364. if ( this.quadData ) {
  2365. for( i=0; i<4; i++ ) {
  2366. if ( this.quadData[i].intersects( rectangle ) ) {
  2367. qoverlappingActors= this.quadData[i].getOverlappingActors(rectangle);
  2368. for( j=0,l=qoverlappingActors.length; j<l; j++ ) {
  2369. overlappingActors.push( qoverlappingActors[j] );
  2370. }
  2371. }
  2372. }
  2373. } else {
  2374. for( i=0, l=actors.length; i<l; i++ ) {
  2375. actor= actors[i];
  2376. if ( rectangle.intersects( actor.AABB ) ) {
  2377. overlappingActors.push( actor );
  2378. }
  2379. }
  2380. }
  2381. return overlappingActors;
  2382. }
  2383. };
  2384. extend( CAAT.QuadTree, CAAT.Rectangle );
  2385. })();
  2386. (function() {
  2387. CAAT.SpatialHash= function() {
  2388. return this;
  2389. };
  2390. CAAT.SpatialHash.prototype= {
  2391. elements : null,
  2392. width : null,
  2393. height : null,
  2394. rows : null,
  2395. columns : null,
  2396. xcache : null,
  2397. ycache : null,
  2398. xycache : null,
  2399. rectangle : null,
  2400. r0 : null,
  2401. r1 : null,
  2402. initialize : function( w,h, rows,columns ) {
  2403. var i, j;
  2404. this.elements= [];
  2405. for( i=0; i<rows*columns; i++ ) {
  2406. this.elements.push( [] );
  2407. }
  2408. this.width= w;
  2409. this.height= h;
  2410. this.rows= rows;
  2411. this.columns= columns;
  2412. this.xcache= [];
  2413. for( i=0; i<w; i++ ) {
  2414. this.xcache.push( (i/(w/columns))>>0 );
  2415. }
  2416. this.ycache= [];
  2417. for( i=0; i<h; i++ ) {
  2418. this.ycache.push( (i/(h/rows))>>0 );
  2419. }
  2420. this.xycache=[];
  2421. for( i=0; i<this.rows; i++ ) {
  2422. this.xycache.push( [] );
  2423. for( j=0; j<this.columns; j++ ) {
  2424. this.xycache[i].push( j + i*columns );
  2425. }
  2426. }
  2427. this.rectangle= new CAAT.Rectangle().setBounds( 0, 0, w, h );
  2428. this.r0= new CAAT.Rectangle();
  2429. this.r1= new CAAT.Rectangle();
  2430. return this;
  2431. },
  2432. clearObject : function() {
  2433. var i;
  2434. for( i=0; i<this.rows*this.columns; i++ ) {
  2435. this.elements[i]= [];
  2436. }
  2437. return this;
  2438. },
  2439. /**
  2440. * Add an element of the form { id, x,y,width,height, rectangular }
  2441. */
  2442. addObject : function( obj ) {
  2443. var x= obj.x|0;
  2444. var y= obj.y|0;
  2445. var width= obj.width|0;
  2446. var height= obj.height|0;
  2447. var cells= this.__getCells( x,y,width,height );
  2448. for( var i=0; i<cells.length; i++ ) {
  2449. this.elements[ cells[i] ].push( obj );
  2450. }
  2451. },
  2452. __getCells : function( x,y,width,height ) {
  2453. var cells= [];
  2454. var i;
  2455. if ( this.rectangle.contains(x,y) ) {
  2456. cells.push( this.xycache[ this.ycache[y] ][ this.xcache[x] ] );
  2457. }
  2458. /**
  2459. * if both squares lay inside the same cell, it is not crossing a boundary.
  2460. */
  2461. if ( this.rectangle.contains(x+width-1,y+height-1) ) {
  2462. var c= this.xycache[ this.ycache[y+height-1] ][ this.xcache[x+width-1] ];
  2463. if ( c===cells[0] ) {
  2464. return cells;
  2465. }
  2466. cells.push( c );
  2467. }
  2468. /**
  2469. * the other two AABB points lie inside the screen as well.
  2470. */
  2471. if ( this.rectangle.contains(x+width-1,y) ) {
  2472. var c= this.xycache[ this.ycache[y] ][ this.xcache[x+width-1] ];
  2473. if ( c===cells[0] || c===cells[1] ) {
  2474. return cells;
  2475. }
  2476. cells.push(c);
  2477. }
  2478. // worst case, touching 4 screen cells.
  2479. if ( this.rectangle.contains(x+width-1,y+height-1) ) {
  2480. var c= this.xycache[ this.ycache[y+height-1] ][ this.xcache[x] ];
  2481. cells.push(c);
  2482. }
  2483. return cells;
  2484. },
  2485. solveCollision : function( callback ) {
  2486. var i,j,k;
  2487. for( i=0; i<this.elements.length; i++ ) {
  2488. var cell= this.elements[i];
  2489. if ( cell.length>1 ) { // at least 2 elements could collide
  2490. this._solveCollisionCell( cell, callback );
  2491. }
  2492. }
  2493. },
  2494. _solveCollisionCell : function( cell, callback ) {
  2495. var i,j;
  2496. for( i=0; i<cell.length; i++ ) {
  2497. var pivot= cell[i];
  2498. this.r0.setBounds( pivot.x, pivot.y, pivot.width, pivot.height );
  2499. for( j=i+1; j<cell.length; j++ ) {
  2500. var c= cell[j];
  2501. if ( this.r0.intersects( this.r1.setBounds( c.x, c.y, c.width, c.height ) ) ) {
  2502. callback( pivot, c );
  2503. }
  2504. }
  2505. }
  2506. },
  2507. /**
  2508. *
  2509. * @param x
  2510. * @param y
  2511. * @param w
  2512. * @param h
  2513. * @param oncollide function that returns boolean. if returns true, stop testing collision.
  2514. */
  2515. collide : function( x,y,w,h, oncollide ) {
  2516. x|=0;
  2517. y|=0;
  2518. w|=0;
  2519. h|=0;
  2520. var cells= this.__getCells( x,y,w,h );
  2521. var i,j,l;
  2522. var el= this.elements;
  2523. this.r0.setBounds( x,y,w,h );
  2524. for( i=0; i<cells.length; i++ ) {
  2525. var cell= cells[i];
  2526. var elcell= el[cell];
  2527. for( j=0, l=elcell.length; j<l; j++ ) {
  2528. var obj= elcell[j];
  2529. this.r1.setBounds( obj.x, obj.y, obj.width, obj.height );
  2530. // collides
  2531. if ( this.r0.intersects( this.r1 ) ) {
  2532. if ( oncollide(obj) ) {
  2533. return;
  2534. }
  2535. }
  2536. }
  2537. }
  2538. }
  2539. };
  2540. })();/**
  2541. * See LICENSE file.
  2542. *
  2543. * Generate interpolator.
  2544. *
  2545. * Partially based on Robert Penner easing equations.
  2546. * http://www.robertpenner.com/easing/
  2547. *
  2548. *
  2549. **/
  2550. (function() {
  2551. /**
  2552. * a CAAT.Interpolator is a function which transforms a value into another but with some constraints:
  2553. *
  2554. * <ul>
  2555. * <li>The input values must be between 0 and 1.
  2556. * <li>Output values will be between 0 and 1.
  2557. * <li>Every Interpolator has at least an entering boolean parameter called pingpong. if set to true, the Interpolator
  2558. * will set values from 0..1 and back from 1..0. So half the time for each range.
  2559. * </ul>
  2560. *
  2561. * <p>
  2562. * CAAt.Interpolator is defined by a createXXXX method which sets up an internal getPosition(time)
  2563. * function. You could set as an Interpolator up any object which exposes a method getPosition(time)
  2564. * and returns a CAAT.Point or an object of the form {x:{number}, y:{number}}.
  2565. * <p>
  2566. * In the return value, the x attribute's value will be the same value as that of the time parameter,
  2567. * and y attribute will hold a value between 0 and 1 with the resulting value of applying the
  2568. * interpolation function for the time parameter.
  2569. *
  2570. * <p>
  2571. * For am exponential interpolation, the getPosition function would look like this:
  2572. * <code>function getPosition(time) { return { x:time, y: Math.pow(time,2) }�}</code>.
  2573. * meaning that for time=0.5, a value of 0,5*0,5 should use instead.
  2574. *
  2575. * <p>
  2576. * For a visual understanding of interpolators see tutorial 4 interpolators, or play with technical
  2577. * demo 1 where a SpriteActor moves along a path and the way it does can be modified by every
  2578. * out-of-the-box interpolator.
  2579. *
  2580. * @constructor
  2581. *
  2582. */
  2583. CAAT.Interpolator = function() {
  2584. this.interpolated= new CAAT.Point(0,0,0);
  2585. return this;
  2586. };
  2587. CAAT.Interpolator.prototype= {
  2588. interpolated: null, // a coordinate holder for not building a new CAAT.Point for each interpolation call.
  2589. paintScale: 90, // the size of the interpolation draw on screen in pixels.
  2590. /**
  2591. * Set a linear interpolation function.
  2592. *
  2593. * @param bPingPong {boolean}
  2594. * @param bInverse {boolean} will values will be from 1 to 0 instead of 0 to 1 ?.
  2595. */
  2596. createLinearInterpolator : function(bPingPong, bInverse) {
  2597. /**
  2598. * Linear and inverse linear interpolation function.
  2599. * @param time {number}
  2600. */
  2601. this.getPosition= function getPosition(time) {
  2602. var orgTime= time;
  2603. if ( bPingPong ) {
  2604. if ( time<0.5 ) {
  2605. time*=2;
  2606. } else {
  2607. time= 1-(time-0.5)*2;
  2608. }
  2609. }
  2610. if ( bInverse!==null && bInverse ) {
  2611. time= 1-time;
  2612. }
  2613. return this.interpolated.set(orgTime,time);
  2614. };
  2615. return this;
  2616. },
  2617. createBackOutInterpolator : function(bPingPong) {
  2618. this.getPosition= function getPosition(time) {
  2619. var orgTime= time;
  2620. if ( bPingPong ) {
  2621. if ( time<0.5 ) {
  2622. time*=2;
  2623. } else {
  2624. time= 1-(time-0.5)*2;
  2625. }
  2626. }
  2627. time = time - 1;
  2628. var overshoot= 1.70158;
  2629. return this.interpolated.set(
  2630. orgTime,
  2631. time * time * ((overshoot + 1) * time + overshoot) + 1);
  2632. };
  2633. return this;
  2634. },
  2635. /**
  2636. * Set an exponential interpolator function. The function to apply will be Math.pow(time,exponent).
  2637. * This function starts with 0 and ends in values of 1.
  2638. *
  2639. * @param exponent {number} exponent of the function.
  2640. * @param bPingPong {boolean}
  2641. */
  2642. createExponentialInInterpolator : function(exponent, bPingPong) {
  2643. this.getPosition= function getPosition(time) {
  2644. var orgTime= time;
  2645. if ( bPingPong ) {
  2646. if ( time<0.5 ) {
  2647. time*=2;
  2648. } else {
  2649. time= 1-(time-0.5)*2;
  2650. }
  2651. }
  2652. return this.interpolated.set(orgTime,Math.pow(time,exponent));
  2653. };
  2654. return this;
  2655. },
  2656. /**
  2657. * Set an exponential interpolator function. The function to apply will be 1-Math.pow(time,exponent).
  2658. * This function starts with 1 and ends in values of 0.
  2659. *
  2660. * @param exponent {number} exponent of the function.
  2661. * @param bPingPong {boolean}
  2662. */
  2663. createExponentialOutInterpolator : function(exponent, bPingPong) {
  2664. this.getPosition= function getPosition(time) {
  2665. var orgTime= time;
  2666. if ( bPingPong ) {
  2667. if ( time<0.5 ) {
  2668. time*=2;
  2669. } else {
  2670. time= 1-(time-0.5)*2;
  2671. }
  2672. }
  2673. return this.interpolated.set(orgTime,1-Math.pow(1-time,exponent));
  2674. };
  2675. return this;
  2676. },
  2677. /**
  2678. * Set an exponential interpolator function. Two functions will apply:
  2679. * Math.pow(time*2,exponent)/2 for the first half of the function (t<0.5) and
  2680. * 1-Math.abs(Math.pow(time*2-2,exponent))/2 for the second half (t>=.5)
  2681. * This function starts with 0 and goes to values of 1 and ends with values of 0.
  2682. *
  2683. * @param exponent {number} exponent of the function.
  2684. * @param bPingPong {boolean}
  2685. */
  2686. createExponentialInOutInterpolator : function(exponent, bPingPong) {
  2687. this.getPosition= function getPosition(time) {
  2688. var orgTime= time;
  2689. if ( bPingPong ) {
  2690. if ( time<0.5 ) {
  2691. time*=2;
  2692. } else {
  2693. time= 1-(time-0.5)*2;
  2694. }
  2695. }
  2696. if ( time*2<1 ) {
  2697. return this.interpolated.set(orgTime,Math.pow(time*2,exponent)/2);
  2698. }
  2699. return this.interpolated.set(orgTime,1-Math.abs(Math.pow(time*2-2,exponent))/2);
  2700. };
  2701. return this;
  2702. },
  2703. /**
  2704. * Creates a Quadric bezier curbe as interpolator.
  2705. *
  2706. * @param p0 {CAAT.Point} a CAAT.Point instance.
  2707. * @param p1 {CAAT.Point} a CAAT.Point instance.
  2708. * @param p2 {CAAT.Point} a CAAT.Point instance.
  2709. * @param bPingPong {boolean} a boolean indicating if the interpolator must ping-pong.
  2710. */
  2711. createQuadricBezierInterpolator : function(p0,p1,p2,bPingPong) {
  2712. this.getPosition= function getPosition(time) {
  2713. var orgTime= time;
  2714. if ( bPingPong ) {
  2715. if ( time<0.5 ) {
  2716. time*=2;
  2717. } else {
  2718. time= 1-(time-0.5)*2;
  2719. }
  2720. }
  2721. time= (1-time)*(1-time)*p0.y + 2*(1-time)*time*p1.y + time*time*p2.y;
  2722. return this.interpolated.set( orgTime, time );
  2723. };
  2724. return this;
  2725. },
  2726. /**
  2727. * Creates a Cubic bezier curbe as interpolator.
  2728. *
  2729. * @param p0 {CAAT.Point} a CAAT.Point instance.
  2730. * @param p1 {CAAT.Point} a CAAT.Point instance.
  2731. * @param p2 {CAAT.Point} a CAAT.Point instance.
  2732. * @param p3 {CAAT.Point} a CAAT.Point instance.
  2733. * @param bPingPong {boolean} a boolean indicating if the interpolator must ping-pong.
  2734. */
  2735. createCubicBezierInterpolator : function(p0,p1,p2,p3,bPingPong) {
  2736. this.getPosition= function getPosition(time) {
  2737. var orgTime= time;
  2738. if ( bPingPong ) {
  2739. if ( time<0.5 ) {
  2740. time*=2;
  2741. } else {
  2742. time= 1-(time-0.5)*2;
  2743. }
  2744. }
  2745. var t2= time*time;
  2746. var t3= time*t2;
  2747. time = (p0.y + time * (-p0.y * 3 + time * (3 * p0.y -
  2748. p0.y * time))) + time * (3 * p1.y + time * (-6 * p1.y +
  2749. p1.y * 3 * time)) + t2 * (p2.y * 3 - p2.y * 3 * time) +
  2750. p3.y * t3;
  2751. return this.interpolated.set( orgTime, time );
  2752. };
  2753. return this;
  2754. },
  2755. createElasticOutInterpolator : function(amplitude,p,bPingPong) {
  2756. this.getPosition= function getPosition(time) {
  2757. if ( bPingPong ) {
  2758. if ( time<0.5 ) {
  2759. time*=2;
  2760. } else {
  2761. time= 1-(time-0.5)*2;
  2762. }
  2763. }
  2764. if (time === 0) {
  2765. return {x:0,y:0};
  2766. }
  2767. if (time === 1) {
  2768. return {x:1,y:1};
  2769. }
  2770. var s = p/(2*Math.PI) * Math.asin (1/amplitude);
  2771. return this.interpolated.set(
  2772. time,
  2773. (amplitude*Math.pow(2,-10*time) * Math.sin( (time-s)*(2*Math.PI)/p ) + 1 ) );
  2774. };
  2775. return this;
  2776. },
  2777. createElasticInInterpolator : function(amplitude,p,bPingPong) {
  2778. this.getPosition= function getPosition(time) {
  2779. if ( bPingPong ) {
  2780. if ( time<0.5 ) {
  2781. time*=2;
  2782. } else {
  2783. time= 1-(time-0.5)*2;
  2784. }
  2785. }
  2786. if (time === 0) {
  2787. return {x:0,y:0};
  2788. }
  2789. if (time === 1) {
  2790. return {x:1,y:1};
  2791. }
  2792. var s = p/(2*Math.PI) * Math.asin (1/amplitude);
  2793. return this.interpolated.set(
  2794. time,
  2795. -(amplitude*Math.pow(2,10*(time-=1)) * Math.sin( (time-s)*(2*Math.PI)/p ) ) );
  2796. };
  2797. return this;
  2798. },
  2799. createElasticInOutInterpolator : function(amplitude,p,bPingPong) {
  2800. this.getPosition= function getPosition(time) {
  2801. if ( bPingPong ) {
  2802. if ( time<0.5 ) {
  2803. time*=2;
  2804. } else {
  2805. time= 1-(time-0.5)*2;
  2806. }
  2807. }
  2808. var s = p/(2*Math.PI) * Math.asin (1/amplitude);
  2809. time*=2;
  2810. if ( time<=1 ) {
  2811. return this.interpolated.set(
  2812. time,
  2813. -0.5*(amplitude*Math.pow(2,10*(time-=1)) * Math.sin( (time-s)*(2*Math.PI)/p )));
  2814. }
  2815. return this.interpolated.set(
  2816. time,
  2817. 1+0.5*(amplitude*Math.pow(2,-10*(time-=1)) * Math.sin( (time-s)*(2*Math.PI)/p )));
  2818. };
  2819. return this;
  2820. },
  2821. /**
  2822. * @param time {number}
  2823. * @private
  2824. */
  2825. bounce : function(time) {
  2826. if ((time /= 1) < (1 / 2.75)) {
  2827. return {x:time, y:7.5625 * time * time};
  2828. } else if (time < (2 / 2.75)) {
  2829. return {x:time, y:7.5625 * (time -= (1.5 / 2.75)) * time + 0.75};
  2830. } else if (time < (2.5 / 2.75)) {
  2831. return {x:time, y:7.5625 * (time -= (2.25 / 2.75)) * time + 0.9375};
  2832. } else {
  2833. return {x:time, y:7.5625*(time-=(2.625/2.75))*time+0.984375};
  2834. }
  2835. },
  2836. createBounceOutInterpolator : function(bPingPong) {
  2837. this.getPosition= function getPosition(time) {
  2838. if ( bPingPong ) {
  2839. if ( time<0.5 ) {
  2840. time*=2;
  2841. } else {
  2842. time= 1-(time-0.5)*2;
  2843. }
  2844. }
  2845. return this.bounce(time);
  2846. };
  2847. return this;
  2848. },
  2849. createBounceInInterpolator : function(bPingPong) {
  2850. this.getPosition= function getPosition(time) {
  2851. if ( bPingPong ) {
  2852. if ( time<0.5 ) {
  2853. time*=2;
  2854. } else {
  2855. time= 1-(time-0.5)*2;
  2856. }
  2857. }
  2858. var r= this.bounce(1-time);
  2859. r.y= 1-r.y;
  2860. return r;
  2861. };
  2862. return this;
  2863. },
  2864. createBounceInOutInterpolator : function(bPingPong) {
  2865. this.getPosition= function getPosition(time) {
  2866. if ( bPingPong ) {
  2867. if ( time<0.5 ) {
  2868. time*=2;
  2869. } else {
  2870. time= 1-(time-0.5)*2;
  2871. }
  2872. }
  2873. var r;
  2874. if (time < 0.5) {
  2875. r= this.bounce(1 - time * 2);
  2876. r.y= (1 - r.y)* 0.5;
  2877. return r;
  2878. }
  2879. r= this.bounce(time * 2 - 1,bPingPong);
  2880. r.y= r.y* 0.5 + 0.5;
  2881. return r;
  2882. };
  2883. return this;
  2884. },
  2885. /**
  2886. * Paints an interpolator on screen.
  2887. * @param director {CAAT.Director} a CAAT.Director instance.
  2888. * @param time {number} an integer indicating the scene time the Interpolator will be drawn at. This value is useless.
  2889. */
  2890. paint : function(director,time) {
  2891. var canvas= director.crc;
  2892. canvas.save();
  2893. canvas.beginPath();
  2894. canvas.moveTo( 0, this.getPosition(0).y * this.paintScale );
  2895. for( var i=0; i<=this.paintScale; i++ ) {
  2896. canvas.lineTo( i, this.getPosition(i/this.paintScale).y * this.paintScale );
  2897. }
  2898. canvas.strokeStyle='black';
  2899. canvas.stroke();
  2900. canvas.restore();
  2901. },
  2902. /**
  2903. * Gets an array of coordinates which define the polyline of the intepolator's curve contour.
  2904. * Values for both coordinates range from 0 to 1.
  2905. * @param iSize {number} an integer indicating the number of contour segments.
  2906. * @return array {[CAAT.Point]} of object of the form {x:float, y:float}.
  2907. */
  2908. getContour : function(iSize) {
  2909. var contour=[];
  2910. for( var i=0; i<=iSize; i++ ) {
  2911. contour.push( {x: i/iSize, y: this.getPosition(i/iSize).y} );
  2912. }
  2913. return contour;
  2914. },
  2915. /**
  2916. *
  2917. */
  2918. enumerateInterpolators : function() {
  2919. return [
  2920. new CAAT.Interpolator().createLinearInterpolator(false, false), 'Linear pingpong=false, inverse=false',
  2921. new CAAT.Interpolator().createLinearInterpolator(true, false), 'Linear pingpong=true, inverse=false',
  2922. new CAAT.Interpolator().createLinearInterpolator(false, true), 'Linear pingpong=false, inverse=true',
  2923. new CAAT.Interpolator().createLinearInterpolator(true, true), 'Linear pingpong=true, inverse=true',
  2924. new CAAT.Interpolator().createExponentialInInterpolator( 2, false), 'ExponentialIn pingpong=false, exponent=2',
  2925. new CAAT.Interpolator().createExponentialOutInterpolator( 2, false), 'ExponentialOut pingpong=false, exponent=2',
  2926. new CAAT.Interpolator().createExponentialInOutInterpolator( 2, false), 'ExponentialInOut pingpong=false, exponent=2',
  2927. new CAAT.Interpolator().createExponentialInInterpolator( 2, true), 'ExponentialIn pingpong=true, exponent=2',
  2928. new CAAT.Interpolator().createExponentialOutInterpolator( 2, true), 'ExponentialOut pingpong=true, exponent=2',
  2929. new CAAT.Interpolator().createExponentialInOutInterpolator( 2, true), 'ExponentialInOut pingpong=true, exponent=2',
  2930. new CAAT.Interpolator().createExponentialInInterpolator( 4, false), 'ExponentialIn pingpong=false, exponent=4',
  2931. new CAAT.Interpolator().createExponentialOutInterpolator( 4, false), 'ExponentialOut pingpong=false, exponent=4',
  2932. new CAAT.Interpolator().createExponentialInOutInterpolator( 4, false), 'ExponentialInOut pingpong=false, exponent=4',
  2933. new CAAT.Interpolator().createExponentialInInterpolator( 4, true), 'ExponentialIn pingpong=true, exponent=4',
  2934. new CAAT.Interpolator().createExponentialOutInterpolator( 4, true), 'ExponentialOut pingpong=true, exponent=4',
  2935. new CAAT.Interpolator().createExponentialInOutInterpolator( 4, true), 'ExponentialInOut pingpong=true, exponent=4',
  2936. new CAAT.Interpolator().createExponentialInInterpolator( 6, false), 'ExponentialIn pingpong=false, exponent=6',
  2937. new CAAT.Interpolator().createExponentialOutInterpolator( 6, false), 'ExponentialOut pingpong=false, exponent=6',
  2938. new CAAT.Interpolator().createExponentialInOutInterpolator( 6, false), 'ExponentialInOut pingpong=false, exponent=6',
  2939. new CAAT.Interpolator().createExponentialInInterpolator( 6, true), 'ExponentialIn pingpong=true, exponent=6',
  2940. new CAAT.Interpolator().createExponentialOutInterpolator( 6, true), 'ExponentialOut pingpong=true, exponent=6',
  2941. new CAAT.Interpolator().createExponentialInOutInterpolator( 6, true), 'ExponentialInOut pingpong=true, exponent=6',
  2942. new CAAT.Interpolator().createBounceInInterpolator(false), 'BounceIn pingpong=false',
  2943. new CAAT.Interpolator().createBounceOutInterpolator(false), 'BounceOut pingpong=false',
  2944. new CAAT.Interpolator().createBounceInOutInterpolator(false), 'BounceInOut pingpong=false',
  2945. new CAAT.Interpolator().createBounceInInterpolator(true), 'BounceIn pingpong=true',
  2946. new CAAT.Interpolator().createBounceOutInterpolator(true), 'BounceOut pingpong=true',
  2947. new CAAT.Interpolator().createBounceInOutInterpolator(true), 'BounceInOut pingpong=true',
  2948. new CAAT.Interpolator().createElasticInInterpolator( 1.1, 0.4, false), 'ElasticIn pingpong=false, amp=1.1, d=.4',
  2949. new CAAT.Interpolator().createElasticOutInterpolator( 1.1, 0.4, false), 'ElasticOut pingpong=false, amp=1.1, d=.4',
  2950. new CAAT.Interpolator().createElasticInOutInterpolator( 1.1, 0.4, false), 'ElasticInOut pingpong=false, amp=1.1, d=.4',
  2951. new CAAT.Interpolator().createElasticInInterpolator( 1.1, 0.4, true), 'ElasticIn pingpong=true, amp=1.1, d=.4',
  2952. new CAAT.Interpolator().createElasticOutInterpolator( 1.1, 0.4, true), 'ElasticOut pingpong=true, amp=1.1, d=.4',
  2953. new CAAT.Interpolator().createElasticInOutInterpolator( 1.1, 0.4, true), 'ElasticInOut pingpong=true, amp=1.1, d=.4',
  2954. new CAAT.Interpolator().createElasticInInterpolator( 1.0, 0.2, false), 'ElasticIn pingpong=false, amp=1.0, d=.2',
  2955. new CAAT.Interpolator().createElasticOutInterpolator( 1.0, 0.2, false), 'ElasticOut pingpong=false, amp=1.0, d=.2',
  2956. new CAAT.Interpolator().createElasticInOutInterpolator( 1.0, 0.2, false), 'ElasticInOut pingpong=false, amp=1.0, d=.2',
  2957. new CAAT.Interpolator().createElasticInInterpolator( 1.0, 0.2, true), 'ElasticIn pingpong=true, amp=1.0, d=.2',
  2958. new CAAT.Interpolator().createElasticOutInterpolator( 1.0, 0.2, true), 'ElasticOut pingpong=true, amp=1.0, d=.2',
  2959. new CAAT.Interpolator().createElasticInOutInterpolator( 1.0, 0.2, true), 'ElasticInOut pingpong=true, amp=1.0, d=.2'
  2960. ];
  2961. }
  2962. };
  2963. })();
  2964. /**
  2965. * See LICENSE file.
  2966. *
  2967. * Behaviors are keyframing elements.
  2968. * By using a BehaviorContainer, you can specify different actions on any animation Actor.
  2969. * An undefined number of Behaviors can be defined for each Actor.
  2970. *
  2971. * There're the following Behaviors:
  2972. * + AlphaBehavior: controls container/actor global alpha.
  2973. * + RotateBehavior: takes control of rotation affine transform.
  2974. * + ScaleBehavior: takes control of scaling on x/y axis affine transform.
  2975. * + PathBehavior: takes control of translating an Actor/ActorContainer across a path [ie. pathSegment collection].
  2976. * + GenericBehavior: applies a behavior to any given target object's property, or notifies a callback.
  2977. *
  2978. *
  2979. **/
  2980. (function() {
  2981. /**
  2982. * Behavior base class.
  2983. *
  2984. * <p>
  2985. * A behavior is defined by a frame time (behavior duration) and a behavior application function called interpolator.
  2986. * In its default form, a behaviour is applied linearly, that is, the same amount of behavior is applied every same
  2987. * time interval.
  2988. * <p>
  2989. * A concrete Behavior, a rotateBehavior in example, will change a concrete Actor's rotationAngle during the specified
  2990. * period.
  2991. * <p>
  2992. * A behavior is guaranteed to notify (if any observer is registered) on behavior expiration.
  2993. * <p>
  2994. * A behavior can keep an unlimited observers. Observers are objects of the form:
  2995. * <p>
  2996. * <code>
  2997. * {
  2998. * behaviorExpired : function( behavior, time, actor);
  2999. * behaviorApplied : function( behavior, time, normalizedTime, actor, value);
  3000. * }
  3001. * </code>
  3002. * <p>
  3003. * <strong>behaviorExpired</strong>: function( behavior, time, actor). This method will be called for any registered observer when
  3004. * the scene time is greater than behavior's startTime+duration. This method will be called regardless of the time
  3005. * granurality.
  3006. * <p>
  3007. * <strong>behaviorApplied</strong> : function( behavior, time, normalizedTime, actor, value). This method will be called once per
  3008. * frame while the behavior is not expired and is in frame time (behavior startTime>=scene time). This method can be
  3009. * called multiple times.
  3010. * <p>
  3011. * Every behavior is applied to a concrete Actor.
  3012. * Every actor must at least define an start and end value. The behavior will set start-value at behaviorStartTime and
  3013. * is guaranteed to apply end-value when scene time= behaviorStartTime+behaviorDuration.
  3014. * <p>
  3015. * You can set behaviors to apply forever that is cyclically. When a behavior is cycle=true, won't notify
  3016. * behaviorExpired to its registered observers.
  3017. * <p>
  3018. * Other Behaviors simply must supply with the method <code>setForTime(time, actor)</code> overriden.
  3019. *
  3020. * @constructor
  3021. */
  3022. CAAT.Behavior= function() {
  3023. this.lifecycleListenerList=[];
  3024. this.setDefaultInterpolator();
  3025. return this;
  3026. };
  3027. /**
  3028. * @enum
  3029. */
  3030. CAAT.Behavior.Status= {
  3031. NOT_STARTED: 0,
  3032. STARTED: 1,
  3033. EXPIRED: 2
  3034. };
  3035. var DefaultInterpolator= new CAAT.Interpolator().createLinearInterpolator(false);
  3036. var DefaultPPInterpolator= new CAAT.Interpolator().createLinearInterpolator(true);
  3037. CAAT.Behavior.prototype= {
  3038. lifecycleListenerList: null, // observer list.
  3039. behaviorStartTime: -1, // scene time to start applying the behavior
  3040. behaviorDuration: -1, // behavior duration in ms.
  3041. cycleBehavior: false, // apply forever ?
  3042. status: CAAT.Behavior.NOT_STARTED,
  3043. interpolator: null, // behavior application function. linear by default.
  3044. actor: null, // actor the Behavior acts on.
  3045. id: 0, // an integer id suitable to identify this behavior by number.
  3046. timeOffset: 0,
  3047. doValueApplication: true,
  3048. solved : true,
  3049. setValueApplication : function( apply ) {
  3050. this.doValueApplication= apply;
  3051. return this;
  3052. },
  3053. setTimeOffset : function( offset ) {
  3054. this.timeOffset= offset;
  3055. return this;
  3056. },
  3057. /**
  3058. * Sets this behavior id.
  3059. * @param id an integer.
  3060. *
  3061. */
  3062. setId : function( id ) {
  3063. this.id= id;
  3064. return this;
  3065. },
  3066. /**
  3067. * Sets the default interpolator to a linear ramp, that is, behavior will be applied linearly.
  3068. * @return this
  3069. */
  3070. setDefaultInterpolator : function() {
  3071. this.interpolator= DefaultInterpolator;
  3072. return this;
  3073. },
  3074. /**
  3075. * Sets default interpolator to be linear from 0..1 and from 1..0.
  3076. * @return this
  3077. */
  3078. setPingPong : function() {
  3079. this.interpolator= DefaultPPInterpolator;
  3080. return this;
  3081. },
  3082. /**
  3083. *
  3084. * @param status {CAAT.Behavior.Status}
  3085. */
  3086. setStatus : function(status) {
  3087. this.status= status;
  3088. },
  3089. /**
  3090. * Sets behavior start time and duration.
  3091. * Scene time will be the time of the scene the behavior actor is bound to.
  3092. * @param startTime {number} an integer indicating behavior start time in scene time in ms..
  3093. * @param duration {number} an integer indicating behavior duration in ms.
  3094. */
  3095. setFrameTime : function( startTime, duration ) {
  3096. this.behaviorStartTime= startTime;
  3097. this.behaviorDuration= duration;
  3098. this.setStatus( CAAT.Behavior.Status.NOT_STARTED );
  3099. return this;
  3100. },
  3101. /**
  3102. * Sets behavior start time and duration but instead as setFrameTime which sets initial time as absolute time
  3103. * regarding scene's time, it uses a relative time offset from current scene time.
  3104. * a call to
  3105. * setFrameTime( scene.time, duration ) is equivalent to
  3106. * setDelayTime( 0, duration )
  3107. * @param delay {number}
  3108. * @param duration {number}
  3109. */
  3110. setDelayTime : function( delay, duration ) {
  3111. this.behaviorStartTime= delay;
  3112. this.behaviorDuration= duration;
  3113. this.setStatus( CAAT.Behavior.Status.NOT_STARTED );
  3114. this.solved= false;
  3115. return this;
  3116. },
  3117. setOutOfFrameTime : function() {
  3118. this.setStatus( CAAT.Behavior.Status.EXPIRED );
  3119. this.behaviorStartTime= Number.MAX_VALUE;
  3120. this.behaviorDuration= 0;
  3121. return this;
  3122. },
  3123. /**
  3124. * Changes behavior default interpolator to another instance of CAAT.Interpolator.
  3125. * If the behavior is not defined by CAAT.Interpolator factory methods, the interpolation function must return
  3126. * its values in the range 0..1. The behavior will only apply for such value range.
  3127. * @param interpolator a CAAT.Interpolator instance.
  3128. */
  3129. setInterpolator : function(interpolator) {
  3130. this.interpolator= interpolator;
  3131. return this;
  3132. },
  3133. /**
  3134. * This method must no be called directly.
  3135. * The director loop will call this method in orther to apply actor behaviors.
  3136. * @param time the scene time the behaviro is being applied at.
  3137. * @param actor a CAAT.Actor instance the behavior is being applied to.
  3138. */
  3139. apply : function( time, actor ) {
  3140. if ( !this.solved ) {
  3141. this.behaviorStartTime+= time;
  3142. this.solved= true;
  3143. }
  3144. time+= this.timeOffset*this.behaviorDuration;
  3145. var orgTime= time;
  3146. if ( this.isBehaviorInTime(time,actor) ) {
  3147. time= this.normalizeTime(time);
  3148. this.fireBehaviorAppliedEvent(
  3149. actor,
  3150. orgTime,
  3151. time,
  3152. this.setForTime( time, actor ) );
  3153. }
  3154. },
  3155. /**
  3156. * Sets the behavior to cycle, ie apply forever.
  3157. * @param bool a boolean indicating whether the behavior is cycle.
  3158. */
  3159. setCycle : function(bool) {
  3160. this.cycleBehavior= bool;
  3161. return this;
  3162. },
  3163. /**
  3164. * Adds an observer to this behavior.
  3165. * @param behaviorListener an observer instance.
  3166. */
  3167. addListener : function( behaviorListener ) {
  3168. this.lifecycleListenerList.push(behaviorListener);
  3169. return this;
  3170. },
  3171. /**
  3172. * Remove all registered listeners to the behavior.
  3173. */
  3174. emptyListenerList : function() {
  3175. this.lifecycleListenerList= [];
  3176. return this;
  3177. },
  3178. /**
  3179. * @return an integer indicating the behavior start time in ms..
  3180. */
  3181. getStartTime : function() {
  3182. return this.behaviorStartTime;
  3183. },
  3184. /**
  3185. * @return an integer indicating the behavior duration time in ms.
  3186. */
  3187. getDuration : function() {
  3188. return this.behaviorDuration;
  3189. },
  3190. /**
  3191. * Chekcs whether the behaviour is in scene time.
  3192. * In case it gets out of scene time, and has not been tagged as expired, the behavior is expired and observers
  3193. * are notified about that fact.
  3194. * @param time the scene time to check the behavior against.
  3195. * @param actor the actor the behavior is being applied to.
  3196. * @return a boolean indicating whether the behavior is in scene time.
  3197. */
  3198. isBehaviorInTime : function(time,actor) {
  3199. var S= CAAT.Behavior.Status;
  3200. if ( this.status===S.EXPIRED || this.behaviorStartTime<0 ) {
  3201. return false;
  3202. }
  3203. if ( this.cycleBehavior ) {
  3204. if ( time>=this.behaviorStartTime ) {
  3205. time= (time-this.behaviorStartTime)%this.behaviorDuration + this.behaviorStartTime;
  3206. }
  3207. }
  3208. if ( time>this.behaviorStartTime+this.behaviorDuration ) {
  3209. if ( this.status!==S.EXPIRED ) {
  3210. this.setExpired(actor,time);
  3211. }
  3212. return false;
  3213. }
  3214. if ( this.status===S.NOT_STARTED ) {
  3215. this.status=S.STARTED;
  3216. this.fireBehaviorStartedEvent(actor,time);
  3217. }
  3218. return this.behaviorStartTime<=time; // && time<this.behaviorStartTime+this.behaviorDuration;
  3219. },
  3220. fireBehaviorStartedEvent : function(actor,time) {
  3221. for( var i=0; i<this.lifecycleListenerList.length; i++ ) {
  3222. if ( this.lifecycleListenerList[i].behaviorStarted ) {
  3223. this.lifecycleListenerList[i].behaviorStarted(this,time,actor);
  3224. }
  3225. }
  3226. },
  3227. /**
  3228. * Notify observers about expiration event.
  3229. * @param actor a CAAT.Actor instance
  3230. * @param time an integer with the scene time the behavior was expired at.
  3231. */
  3232. fireBehaviorExpiredEvent : function(actor,time) {
  3233. for( var i=0; i<this.lifecycleListenerList.length; i++ ) {
  3234. this.lifecycleListenerList[i].behaviorExpired(this,time,actor);
  3235. }
  3236. },
  3237. /**
  3238. * Notify observers about behavior being applied.
  3239. * @param actor a CAAT.Actor instance the behavior is being applied to.
  3240. * @param time the scene time of behavior application.
  3241. * @param normalizedTime the normalized time (0..1) considering 0 behavior start time and 1
  3242. * behaviorStartTime+behaviorDuration.
  3243. * @param value the value being set for actor properties. each behavior will supply with its own value version.
  3244. */
  3245. fireBehaviorAppliedEvent : function(actor,time,normalizedTime,value) {
  3246. for( var i=0; i<this.lifecycleListenerList.length; i++ ) {
  3247. if (this.lifecycleListenerList[i].behaviorApplied) {
  3248. this.lifecycleListenerList[i].behaviorApplied(this,time,normalizedTime,actor,value);
  3249. }
  3250. }
  3251. },
  3252. /**
  3253. * Convert scene time into something more manageable for the behavior.
  3254. * behaviorStartTime will be 0 and behaviorStartTime+behaviorDuration will be 1.
  3255. * the time parameter will be proportional to those values.
  3256. * @param time the scene time to be normalized. an integer.
  3257. */
  3258. normalizeTime : function(time) {
  3259. time= time-this.behaviorStartTime;
  3260. if ( this.cycleBehavior ) {
  3261. time%=this.behaviorDuration;
  3262. }
  3263. return this.interpolator.getPosition(time/this.behaviorDuration).y;
  3264. },
  3265. /**
  3266. * Sets the behavior as expired.
  3267. * This method must not be called directly. It is an auxiliary method to isBehaviorInTime method.
  3268. * @param actor {CAAT.Actor}
  3269. * @param time {integer} the scene time.
  3270. *
  3271. * @private
  3272. */
  3273. setExpired : function(actor,time) {
  3274. // set for final interpolator value.
  3275. this.status= CAAT.Behavior.Status.EXPIRED;
  3276. this.setForTime(this.interpolator.getPosition(1).y,actor);
  3277. this.fireBehaviorExpiredEvent(actor,time);
  3278. },
  3279. /**
  3280. * This method must be overriden for every Behavior breed.
  3281. * Must not be called directly.
  3282. * @param actor {CAAT.Actor} a CAAT.Actor instance.
  3283. * @param time {number} an integer with the scene time.
  3284. *
  3285. * @private
  3286. */
  3287. setForTime : function( time, actor ) {
  3288. },
  3289. /**
  3290. * @param overrides
  3291. */
  3292. initialize : function(overrides) {
  3293. if (overrides) {
  3294. for (var i in overrides) {
  3295. this[i] = overrides[i];
  3296. }
  3297. }
  3298. return this;
  3299. },
  3300. getPropertyName : function() {
  3301. return "";
  3302. }
  3303. };
  3304. })();
  3305. (function() {
  3306. /**
  3307. * <p>
  3308. * A ContainerBehavior is a holder to sum up different behaviors.
  3309. * <p>
  3310. * It imposes some constraints to contained Behaviors:
  3311. * <ul>
  3312. * <li>The time of every contained behavior will be zero based, so the frame time set for each behavior will
  3313. * be referred to the container's behaviorStartTime and not scene time as usual.
  3314. * <li>Cycling a ContainerBehavior means cycling every contained behavior.
  3315. * <li>The container will not impose any Interpolator, so calling the method <code>setInterpolator(CAAT.Interpolator)
  3316. * </code> will be useless.
  3317. * <li>The Behavior application time will be bounded to the Container's frame time. I.E. if we set a container duration
  3318. * to 10 seconds, setting a contained behavior's duration to 15 seconds will be useless since the container will stop
  3319. * applying the behavior after 10 seconds have elapsed.
  3320. * <li>Every ContainerBehavior adds itself as an observer for its contained Behaviors. The main reason is because
  3321. * ContainerBehaviors modify cycling properties of its contained Behaviors. When a contained
  3322. * Behavior is expired, if the Container has isCycle=true, will unexpire the contained Behavior, otherwise, it won't be
  3323. * applied in the next frame. It is left up to the developer to manage correctly the logic of other posible contained
  3324. * behaviors observers.
  3325. * </ul>
  3326. *
  3327. * <p>
  3328. * A ContainerBehavior can contain other ContainerBehaviors at will.
  3329. * <p>
  3330. * A ContainerBehavior will not apply any CAAT.Actor property change by itself, but will instrument its contained
  3331. * Behaviors to do so.
  3332. *
  3333. * @constructor
  3334. * @extends CAAT.Behavior
  3335. */
  3336. CAAT.ContainerBehavior= function() {
  3337. CAAT.ContainerBehavior.superclass.constructor.call(this);
  3338. this.behaviors= [];
  3339. return this;
  3340. };
  3341. CAAT.ContainerBehavior.prototype= {
  3342. behaviors: null, // contained behaviors array
  3343. /**
  3344. * Proportionally change this container duration to its children.
  3345. * @param duration {number} new duration in ms.
  3346. * @return this;
  3347. */
  3348. conformToDuration : function( duration ) {
  3349. this.duration= duration;
  3350. var f= duration/this.duration;
  3351. var bh;
  3352. for( var i=0; i<this.behavior.length; i++ ) {
  3353. bh= this.behavior[i];
  3354. bh.setFrameTime( bh.getStartTime()*f, bh.getDuration()*f );
  3355. }
  3356. return this;
  3357. },
  3358. /**
  3359. * Adds a new behavior to the container.
  3360. * @param behavior
  3361. *
  3362. * @override
  3363. */
  3364. addBehavior : function(behavior) {
  3365. this.behaviors.push(behavior);
  3366. behavior.addListener(this);
  3367. return this;
  3368. },
  3369. /**
  3370. * Applies every contained Behaviors.
  3371. * The application time the contained behaviors will receive will be ContainerBehavior related and not the
  3372. * received time.
  3373. * @param time an integer indicating the time to apply the contained behaviors at.
  3374. * @param actor a CAAT.Actor instance indicating the actor to apply the behaviors for.
  3375. */
  3376. apply : function(time, actor) {
  3377. time+= this.timeOffset*this.behaviorDuration;
  3378. if ( this.isBehaviorInTime(time,actor) ) {
  3379. time-= this.getStartTime();
  3380. if ( this.cycleBehavior ){
  3381. time%= this.getDuration();
  3382. }
  3383. var bh= this.behaviors;
  3384. for( var i=0; i<bh.length; i++ ) {
  3385. bh[i].apply(time, actor);
  3386. }
  3387. }
  3388. },
  3389. /**
  3390. * This method is the observer implementation for every contained behavior.
  3391. * If a container is Cycle=true, won't allow its contained behaviors to be expired.
  3392. * @param behavior a CAAT.Behavior instance which has been expired.
  3393. * @param time an integer indicating the time at which has become expired.
  3394. * @param actor a CAAT.Actor the expired behavior is being applied to.
  3395. */
  3396. behaviorExpired : function(behavior,time,actor) {
  3397. if ( this.cycleBehavior ) {
  3398. behavior.setStatus( CAAT.Behavior.Status.STARTED );
  3399. }
  3400. },
  3401. /**
  3402. * Implementation method of the behavior.
  3403. * Just call implementation method for its contained behaviors.
  3404. * @param time an intenger indicating the time the behavior is being applied at.
  3405. * @param actor a CAAT.Actor the behavior is being applied to.
  3406. */
  3407. setForTime : function(time, actor) {
  3408. var bh= this.behaviors;
  3409. for( var i=0; i<bh.length; i++ ) {
  3410. bh[i].setForTime( time, actor );
  3411. }
  3412. return null;
  3413. },
  3414. setExpired : function(actor,time) {
  3415. CAAT.ContainerBehavior.superclass.setExpired.call(this,actor,time);
  3416. var bh= this.behaviors;
  3417. // set for final interpolator value.
  3418. for( var i=0; i<bh.length; i++ ) {
  3419. var bb= bh[i];
  3420. if ( /*!bb.expired*/ bb.status!==CAAT.Behavior.Status.EXPIRED ) {
  3421. bb.setExpired(actor,time-this.behaviorStartTime);
  3422. }
  3423. }
  3424. // already notified in base class.
  3425. // this.fireBehaviorExpiredEvent(actor,time);
  3426. return this;
  3427. },
  3428. setFrameTime : function( start, duration ) {
  3429. CAAT.ContainerBehavior.superclass.setFrameTime.call(this,start,duration);
  3430. var bh= this.behaviors;
  3431. for( var i=0; i<bh.length; i++ ) {
  3432. //bh[i].expired= false;
  3433. bh[i].setStatus( CAAT.Behavior.Status.NOT_STARTED );
  3434. }
  3435. return this;
  3436. },
  3437. calculateKeyFrameData : function(referenceTime, prefix, prevValues ) {
  3438. var i;
  3439. var bh;
  3440. var retValue= {};
  3441. var time;
  3442. var cssRuleValue;
  3443. var cssProperty;
  3444. var property;
  3445. for( i=0; i<this.behaviors.length; i++ ) {
  3446. bh= this.behaviors[i];
  3447. if ( /*!bh.expired*/ bh.status!==CAAT.Behavior.Status.EXPIRED && !(bh instanceof CAAT.GenericBehavior) ) {
  3448. // ajustar tiempos:
  3449. // time es tiempo normalizado a duracion de comportamiento contenedor.
  3450. // 1.- desnormalizar
  3451. time= referenceTime * this.behaviorDuration;
  3452. // 2.- calcular tiempo relativo de comportamiento respecto a contenedor
  3453. if ( bh.behaviorStartTime<=time && bh.behaviorStartTime+bh.behaviorDuration>=time ) {
  3454. // 3.- renormalizar tiempo reltivo a comportamiento.
  3455. time= (time-bh.behaviorStartTime)/bh.behaviorDuration;
  3456. // 4.- obtener valor de comportamiento para tiempo normalizado relativo a contenedor
  3457. cssRuleValue= bh.calculateKeyFrameData(time);
  3458. cssProperty= bh.getPropertyName(prefix);
  3459. if ( typeof retValue[cssProperty] ==='undefined' ) {
  3460. retValue[cssProperty]= "";
  3461. }
  3462. // 5.- asignar a objeto, par de propiedad/valor css
  3463. retValue[cssProperty]+= cssRuleValue+" ";
  3464. }
  3465. }
  3466. }
  3467. var tr="";
  3468. var pv;
  3469. function xx(pr) {
  3470. if ( retValue[pr] ) {
  3471. tr+= retValue[pr];
  3472. } else {
  3473. if ( prevValues ) {
  3474. pv= prevValues[pr];
  3475. if ( pv ) {
  3476. tr+= pv;
  3477. retValue[pr]= pv;
  3478. }
  3479. }
  3480. }
  3481. }
  3482. xx('translate');
  3483. xx('rotate');
  3484. xx('scale');
  3485. var keyFrameRule= "";
  3486. if ( tr ) {
  3487. keyFrameRule='-'+prefix+'-transform: '+tr+';';
  3488. }
  3489. tr="";
  3490. xx('opacity');
  3491. if( tr ) {
  3492. keyFrameRule+= ' opacity: '+tr+';';
  3493. }
  3494. return {
  3495. rules: keyFrameRule,
  3496. ret: retValue
  3497. };
  3498. },
  3499. /**
  3500. *
  3501. * @param prefix
  3502. * @param name
  3503. * @param keyframessize
  3504. */
  3505. calculateKeyFramesData : function(prefix, name, keyframessize) {
  3506. if ( this.duration===Number.MAX_VALUE ) {
  3507. return "";
  3508. }
  3509. if ( typeof keyframessize==='undefined' ) {
  3510. keyframessize=100;
  3511. }
  3512. var i;
  3513. var prevValues= null;
  3514. var kfd= "@-"+prefix+"-keyframes "+name+" {";
  3515. var ret;
  3516. var time;
  3517. var kfr;
  3518. for( i=0; i<=keyframessize; i++ ) {
  3519. time= this.interpolator.getPosition(i/keyframessize).y;
  3520. ret= this.calculateKeyFrameData(time, prefix, prevValues);
  3521. kfr= "" +
  3522. (i/keyframessize*100) + "%" + // percentage
  3523. "{" + ret.rules + "}\n";
  3524. prevValues= ret.ret;
  3525. kfd+= kfr;
  3526. }
  3527. kfd+= "}";
  3528. return kfd;
  3529. }
  3530. };
  3531. extend( CAAT.ContainerBehavior, CAAT.Behavior, null );
  3532. })();
  3533. (function() {
  3534. /**
  3535. * This class applies a rotation to a CAAt.Actor instance.
  3536. * StartAngle, EndAngle must be supplied. Angles are in radians.
  3537. * The RotationAnchor, if not supplied, will be ANCHOR_CENTER.
  3538. *
  3539. * An example os use will be
  3540. *
  3541. * var rb= new CAAT.RotateBehavior().
  3542. * setValues(0,2*Math.PI).
  3543. * setFrameTime(0,2500);
  3544. *
  3545. * @see CAAT.Actor.
  3546. *
  3547. * @constructor
  3548. * @extends CAAT.Behavior
  3549. *
  3550. */
  3551. CAAT.RotateBehavior= function() {
  3552. CAAT.RotateBehavior.superclass.constructor.call(this);
  3553. this.anchor= CAAT.Actor.prototype.ANCHOR_CENTER;
  3554. return this;
  3555. };
  3556. CAAT.RotateBehavior.prototype= {
  3557. startAngle: 0, // behavior start angle
  3558. endAngle: 0, // behavior end angle
  3559. anchorX: .50, // rotation center x.
  3560. anchorY: .50, // rotation center y.
  3561. getPropertyName : function() {
  3562. return "rotate";
  3563. },
  3564. /**
  3565. * Behavior application function.
  3566. * Do not call directly.
  3567. * @param time an integer indicating the application time.
  3568. * @param actor a CAAT.Actor the behavior will be applied to.
  3569. * @return the set angle.
  3570. */
  3571. setForTime : function(time,actor) {
  3572. var angle= this.startAngle + time*(this.endAngle-this.startAngle);
  3573. if ( this.doValueApplication ) {
  3574. actor.setRotationAnchored(angle, this.anchorX, this.anchorY);
  3575. }
  3576. return angle;
  3577. },
  3578. /**
  3579. * Set behavior bound values.
  3580. * if no anchorx,anchory values are supplied, the behavior will assume
  3581. * 50% for both values, that is, the actor's center.
  3582. *
  3583. * Be aware the anchor values are supplied in <b>RELATIVE PERCENT</b> to
  3584. * actor's size.
  3585. *
  3586. * @param startAngle {float} indicating the starting angle.
  3587. * @param endAngle {float} indicating the ending angle.
  3588. * @param anchorx {float} the percent position for anchorX
  3589. * @param anchory {float} the percent position for anchorY
  3590. */
  3591. setValues : function( startAngle, endAngle, anchorx, anchory ) {
  3592. this.startAngle= startAngle;
  3593. this.endAngle= endAngle;
  3594. if ( typeof anchorx!=='undefined' && typeof anchory!=='undefined' ) {
  3595. this.anchorX= anchorx;
  3596. this.anchorY= anchory;
  3597. }
  3598. return this;
  3599. },
  3600. /**
  3601. * @deprecated
  3602. * Use setValues instead
  3603. * @param start
  3604. * @param end
  3605. */
  3606. setAngles : function( start, end ) {
  3607. return this.setValues(start,end);
  3608. },
  3609. /**
  3610. * Set the behavior rotation anchor. Use this method when setting an exact percent
  3611. * by calling setValues is complicated.
  3612. * @see CAAT.Actor
  3613. * @param anchor any of CAAT.Actor.prototype.ANCHOR_* constants.
  3614. *
  3615. * These parameters are to set a custom rotation anchor point. if <code>anchor==CAAT.Actor.prototype.ANCHOR_CUSTOM
  3616. * </code> the custom rotation point is set.
  3617. * @param rx
  3618. * @param ry
  3619. *
  3620. */
  3621. setAnchor : function( actor, rx, ry ) {
  3622. this.anchorX= rx/actor.width;
  3623. this.anchorY= ry/actor.height;
  3624. return this;
  3625. },
  3626. calculateKeyFrameData : function( time ) {
  3627. time= this.interpolator.getPosition(time).y;
  3628. return "rotate(" + (this.startAngle + time*(this.endAngle-this.startAngle)) +"rad)";
  3629. },
  3630. /**
  3631. * @param prefix {string} browser vendor prefix
  3632. * @param name {string} keyframes animation name
  3633. * @param keyframessize {integer} number of keyframes to generate
  3634. * @override
  3635. */
  3636. calculateKeyFramesData : function(prefix, name, keyframessize) {
  3637. if ( typeof keyframessize==='undefined' ) {
  3638. keyframessize= 100;
  3639. }
  3640. keyframessize>>=0;
  3641. var i;
  3642. var kfr;
  3643. var kfd= "@-"+prefix+"-keyframes "+name+" {";
  3644. for( i=0; i<=keyframessize; i++ ) {
  3645. kfr= "" +
  3646. (i/keyframessize*100) + "%" + // percentage
  3647. "{" +
  3648. "-"+prefix+"-transform:" + this.calculateKeyFrameData(i/keyframessize) +
  3649. "}\n";
  3650. kfd+= kfr;
  3651. }
  3652. kfd+="}";
  3653. return kfd;
  3654. }
  3655. };
  3656. extend( CAAT.RotateBehavior, CAAT.Behavior, null);
  3657. })();
  3658. (function() {
  3659. /**
  3660. * <p>
  3661. * A generic behavior is supposed to be extended to create new behaviors when the out-of-the-box
  3662. * ones are not sufficient. It applies the behavior result to a given target object in two ways:
  3663. *
  3664. * <ol>
  3665. * <li>defining the property parameter: the toolkit will perform target_object[property]= calculated_value_for_time.
  3666. * <li>defining a callback function. Sometimes setting of a property is not enough. In example,
  3667. * for a give property in a DOM element, it is needed to set object.style['left']= '70px';
  3668. * With the property approach, you won't be able to add de 'px' suffix to the value, and hence won't
  3669. * work correctly. The function callback will allow to take control by receiving as parameters the
  3670. * target object, and the calculated value to apply by the behavior for the given time.
  3671. * </ol>
  3672. *
  3673. * <p>
  3674. * For example, this code will move a dom element from 0 to 400 px on x during 1 second:
  3675. * <code>
  3676. * <p>
  3677. * var enterBehavior= new CAAT.GenericBehavior(). <br>
  3678. * &nbsp;&nbsp;setFrameTime( scene.time, 1000 ). <br>
  3679. * &nbsp;&nbsp;setValues( <br>
  3680. * &nbsp;&nbsp;&nbsp;&nbsp;0, <br>
  3681. * &nbsp;&nbsp;&nbsp;&nbsp;400, <br>
  3682. * &nbsp;&nbsp;&nbsp;&nbsp;domElement, <br>
  3683. * &nbsp;&nbsp;&nbsp;&nbsp;null, <br>
  3684. * &nbsp;&nbsp;&nbsp;&nbsp;function( currentValue, target ) { <br>
  3685. * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target.style['left']= currentValue+'px'; <br>
  3686. * &nbsp;&nbsp;&nbsp;&nbsp;} <br>
  3687. * &nbsp;&nbsp;); <br>
  3688. * </code>
  3689. *
  3690. * @constructor
  3691. * @extends CAAT.Behavior
  3692. *
  3693. */
  3694. CAAT.GenericBehavior= function() {
  3695. CAAT.GenericBehavior.superclass.constructor.call(this);
  3696. return this;
  3697. };
  3698. CAAT.GenericBehavior.prototype= {
  3699. start: 0,
  3700. end: 0,
  3701. target: null,
  3702. property: null,
  3703. callback: null,
  3704. /**
  3705. * Sets the target objects property to the corresponding value for the given time.
  3706. * If a callback function is defined, it is called as well.
  3707. *
  3708. * @param time {number} the scene time to apply the behavior at.
  3709. * @param actor {CAAT.Actor} a CAAT.Actor object instance.
  3710. */
  3711. setForTime : function(time, actor) {
  3712. var value= this.start+ time*(this.end-this.start);
  3713. if ( this.callback ) {
  3714. this.callback( value, this.target, actor );
  3715. }
  3716. if ( this.property ) {
  3717. this.target[this.property]= value;
  3718. }
  3719. },
  3720. /**
  3721. * Defines the values to apply this behavior.
  3722. *
  3723. * @param start {number} initial behavior value.
  3724. * @param end {number} final behavior value.
  3725. * @param target {object} an object. Usually a CAAT.Actor.
  3726. * @param property {string} target object's property to set value to.
  3727. * @param callback {function} a function of the form <code>function( target, value )</code>.
  3728. */
  3729. setValues : function( start, end, target, property, callback ) {
  3730. this.start= start;
  3731. this.end= end;
  3732. this.target= target;
  3733. this.property= property;
  3734. this.callback= callback;
  3735. return this;
  3736. }
  3737. };
  3738. extend( CAAT.GenericBehavior, CAAT.Behavior, null);
  3739. })();
  3740. (function() {
  3741. /**
  3742. * ScaleBehavior applies scale affine transforms in both axis.
  3743. * StartScale and EndScale must be supplied for each axis. This method takes care of a FF bug in which if a Scale is
  3744. * set to 0, the animation will fail playing.
  3745. *
  3746. * This behavior specifies anchors in values ranges 0..1
  3747. *
  3748. * @constructor
  3749. * @extends CAAT.Behavior
  3750. *
  3751. */
  3752. CAAT.ScaleBehavior= function() {
  3753. CAAT.ScaleBehavior.superclass.constructor.call(this);
  3754. this.anchor= CAAT.Actor.prototype.ANCHOR_CENTER;
  3755. return this;
  3756. };
  3757. CAAT.ScaleBehavior.prototype= {
  3758. startScaleX: 1,
  3759. endScaleX: 1,
  3760. startScaleY: 1,
  3761. endScaleY: 1,
  3762. anchorX: .50,
  3763. anchorY: .50,
  3764. getPropertyName : function() {
  3765. return "scale";
  3766. },
  3767. /**
  3768. * Applies corresponding scale values for a given time.
  3769. *
  3770. * @param time the time to apply the scale for.
  3771. * @param actor the target actor to Scale.
  3772. * @return {object} an object of the form <code>{ scaleX: {float}, scaleY: {float}�}</code>
  3773. */
  3774. setForTime : function(time,actor) {
  3775. var scaleX= this.startScaleX + time*(this.endScaleX-this.startScaleX);
  3776. var scaleY= this.startScaleY + time*(this.endScaleY-this.startScaleY);
  3777. // Firefox 3.x & 4, will crash animation if either scaleX or scaleY equals 0.
  3778. if (0===scaleX ) {
  3779. scaleX=0.01;
  3780. }
  3781. if (0===scaleY ) {
  3782. scaleY=0.01;
  3783. }
  3784. if ( this.doValueApplication ) {
  3785. actor.setScaleAnchored( scaleX, scaleY, this.anchorX, this.anchorY );
  3786. }
  3787. return { scaleX: scaleX, scaleY: scaleY };
  3788. },
  3789. /**
  3790. * Define this scale behaviors values.
  3791. *
  3792. * Be aware the anchor values are supplied in <b>RELATIVE PERCENT</b> to
  3793. * actor's size.
  3794. *
  3795. * @param startX {number} initial X axis scale value.
  3796. * @param endX {number} final X axis scale value.
  3797. * @param startY {number} initial Y axis scale value.
  3798. * @param endY {number} final Y axis scale value.
  3799. * @param anchorx {float} the percent position for anchorX
  3800. * @param anchory {float} the percent position for anchorY
  3801. *
  3802. * @return this.
  3803. */
  3804. setValues : function( startX, endX, startY, endY, anchorx, anchory ) {
  3805. this.startScaleX= startX;
  3806. this.endScaleX= endX;
  3807. this.startScaleY= startY;
  3808. this.endScaleY= endY;
  3809. if ( typeof anchorx!=='undefined' && typeof anchory!=='undefined' ) {
  3810. this.anchorX= anchorx;
  3811. this.anchorY= anchory;
  3812. }
  3813. return this;
  3814. },
  3815. /**
  3816. * Set an exact position scale anchor. Use this method when it is hard to
  3817. * set a thorough anchor position expressed in percentage.
  3818. * @param actor
  3819. * @param x
  3820. * @param y
  3821. */
  3822. setAnchor : function( actor, x, y ) {
  3823. this.anchorX= x/actor.width;
  3824. this.anchorY= y/actor.height;
  3825. return this;
  3826. },
  3827. calculateKeyFrameData : function( time ) {
  3828. var scaleX;
  3829. var scaleY;
  3830. time= this.interpolator.getPosition(time).y;
  3831. scaleX= this.startScaleX + time*(this.endScaleX-this.startScaleX);
  3832. scaleY= this.startScaleY + time*(this.endScaleY-this.startScaleY);
  3833. return "scaleX("+scaleX+") scaleY("+scaleY+")";
  3834. },
  3835. calculateKeyFramesData : function(prefix, name, keyframessize) {
  3836. if ( typeof keyframessize==='undefined' ) {
  3837. keyframessize= 100;
  3838. }
  3839. keyframessize>>=0;
  3840. var i;
  3841. var kfr;
  3842. var kfd= "@-"+prefix+"-keyframes "+name+" {";
  3843. for( i=0; i<=keyframessize; i++ ) {
  3844. kfr= "" +
  3845. (i/keyframessize*100) + "%" + // percentage
  3846. "{" +
  3847. "-"+prefix+"-transform:" + this.calculateKeyFrameData(i/keyframessize) +
  3848. "}";
  3849. kfd+= kfr;
  3850. }
  3851. kfd+="}";
  3852. return kfd;
  3853. }
  3854. };
  3855. extend( CAAT.ScaleBehavior, CAAT.Behavior, null);
  3856. })();
  3857. (function() {
  3858. /**
  3859. * AlphaBehavior modifies alpha composition property for an actor.
  3860. *
  3861. * @constructor
  3862. * @extends CAAT.Behavior
  3863. */
  3864. CAAT.AlphaBehavior= function() {
  3865. CAAT.AlphaBehavior.superclass.constructor.call(this);
  3866. return this;
  3867. };
  3868. CAAT.AlphaBehavior.prototype= {
  3869. startAlpha: 0,
  3870. endAlpha: 0,
  3871. getPropertyName : function() {
  3872. return "opacity";
  3873. },
  3874. /**
  3875. * Applies corresponding alpha transparency value for a given time.
  3876. *
  3877. * @param time the time to apply the scale for.
  3878. * @param actor the target actor to set transparency for.
  3879. * @return {number} the alpha value set. Normalized from 0 (total transparency) to 1 (total opacity)
  3880. */
  3881. setForTime : function(time,actor) {
  3882. var alpha= (this.startAlpha+time*(this.endAlpha-this.startAlpha));
  3883. if ( this.doValueApplication ) {
  3884. actor.setAlpha( alpha );
  3885. }
  3886. return alpha;
  3887. },
  3888. /**
  3889. * Set alpha transparency minimum and maximum value.
  3890. * This value can be coerced by Actor's property isGloblAlpha.
  3891. *
  3892. * @param start {number} a float indicating the starting alpha value.
  3893. * @param end {number} a float indicating the ending alpha value.
  3894. */
  3895. setValues : function( start, end ) {
  3896. this.startAlpha= start;
  3897. this.endAlpha= end;
  3898. return this;
  3899. },
  3900. calculateKeyFrameData : function( time ) {
  3901. time= this.interpolator.getPosition(time).y;
  3902. return (this.startAlpha+time*(this.endAlpha-this.startAlpha));
  3903. },
  3904. /**
  3905. * @param prefix {string} browser vendor prefix
  3906. * @param name {string} keyframes animation name
  3907. * @param keyframessize {integer} number of keyframes to generate
  3908. * @override
  3909. */
  3910. calculateKeyFramesData : function(prefix, name, keyframessize) {
  3911. if ( typeof keyframessize==='undefined' ) {
  3912. keyframessize= 100;
  3913. }
  3914. keyframessize>>=0;
  3915. var i;
  3916. var kfr;
  3917. var kfd= "@-"+prefix+"-keyframes "+name+" {";
  3918. for( i=0; i<=keyframessize; i++ ) {
  3919. kfr= "" +
  3920. (i/keyframessize*100) + "%" + // percentage
  3921. "{" +
  3922. "opacity: " + this.calculateKeyFrameData( i / keyframessize ) +
  3923. "}";
  3924. kfd+= kfr;
  3925. }
  3926. kfd+="}";
  3927. return kfd;
  3928. }
  3929. };
  3930. extend( CAAT.AlphaBehavior, CAAT.Behavior, null);
  3931. })();
  3932. (function() {
  3933. /**
  3934. * CAAT.PathBehavior modifies the position of a CAAT.Actor along the path represented by an
  3935. * instance of <code>CAAT.Path</code>.
  3936. *
  3937. * @constructor
  3938. * @extends CAAT.Behavior
  3939. *
  3940. */
  3941. CAAT.PathBehavior= function() {
  3942. CAAT.PathBehavior.superclass.constructor.call(this);
  3943. return this;
  3944. };
  3945. /**
  3946. * @enum
  3947. */
  3948. CAAT.PathBehavior.autorotate = {
  3949. LEFT_TO_RIGHT: 0, // fix left_to_right direction
  3950. RIGHT_TO_LEFT: 1, // fix right_to_left
  3951. FREE: 2 // do not apply correction
  3952. };
  3953. CAAT.PathBehavior.prototype= {
  3954. path: null, // the path to traverse
  3955. autoRotate : false, // set whether the actor must be rotated tangentially to the path.
  3956. prevX: -1, // private, do not use.
  3957. prevY: -1, // private, do not use.
  3958. autoRotateOp: CAAT.PathBehavior.autorotate.FREE,
  3959. getPropertyName : function() {
  3960. return "translate";
  3961. },
  3962. /**
  3963. * Sets an actor rotation to be heading from past to current path's point.
  3964. * Take into account that this will be incompatible with rotation Behaviors
  3965. * since they will set their own rotation configuration.
  3966. * @param autorotate {boolean}
  3967. * @param autorotateOp {CAAT.PathBehavior.autorotate} whether the sprite is drawn heading to the right.
  3968. * @return this.
  3969. */
  3970. setAutoRotate : function( autorotate, autorotateOp ) {
  3971. this.autoRotate= autorotate;
  3972. if (autorotateOp!==undefined) {
  3973. this.autoRotateOp= autorotateOp;
  3974. }
  3975. return this;
  3976. },
  3977. /**
  3978. * Set the behavior path.
  3979. * The path can be any length, and will take behaviorDuration time to be traversed.
  3980. * @param {CAAT.Path}
  3981. *
  3982. * @deprecated
  3983. */
  3984. setPath : function(path) {
  3985. this.path= path;
  3986. return this;
  3987. },
  3988. /**
  3989. * Set the behavior path.
  3990. * The path can be any length, and will take behaviorDuration time to be traversed.
  3991. * @param {CAAT.Path}
  3992. * @return this
  3993. */
  3994. setValues : function(path) {
  3995. return this.setPath(path);
  3996. },
  3997. /**
  3998. * @see Acotr.setPositionAcchor
  3999. * @deprecated
  4000. * @param tx a float with xoffset.
  4001. * @param ty a float with yoffset.
  4002. */
  4003. setTranslation : function( tx, ty ) {
  4004. return this;
  4005. },
  4006. calculateKeyFrameData : function( time ) {
  4007. time= this.interpolator.getPosition(time).y;
  4008. var point= this.path.getPosition(time);
  4009. return "translateX("+point.x+"px) translateY("+point.y+"px)" ;
  4010. },
  4011. calculateKeyFramesData : function(prefix, name, keyframessize) {
  4012. if ( typeof keyframessize==='undefined' ) {
  4013. keyframessize= 100;
  4014. }
  4015. keyframessize>>=0;
  4016. var i;
  4017. var kfr;
  4018. var time;
  4019. var kfd= "@-"+prefix+"-keyframes "+name+" {";
  4020. for( i=0; i<=keyframessize; i++ ) {
  4021. kfr= "" +
  4022. (i/keyframessize*100) + "%" + // percentage
  4023. "{" +
  4024. "-"+prefix+"-transform:" + this.calculateKeyFrameData(i/keyframessize) +
  4025. "}";
  4026. kfd+= kfr;
  4027. }
  4028. kfd+="}";
  4029. return kfd;
  4030. },
  4031. /**
  4032. * Translates the Actor to the corresponding time path position.
  4033. * If autoRotate=true, the actor is rotated as well. The rotation anchor will (if set) always be ANCHOR_CENTER.
  4034. * @param time an integer indicating the time the behavior is being applied at.
  4035. * @param actor a CAAT.Actor instance to be translated.
  4036. * @return {object} an object of the form <code>{ x: {float}, y: {float}�}</code>.
  4037. */
  4038. setForTime : function(time,actor) {
  4039. if ( !this.path ) {
  4040. return {
  4041. x: actor.x,
  4042. y: actor.y
  4043. };
  4044. }
  4045. var point= this.path.getPosition(time);
  4046. if ( this.autoRotate ) {
  4047. if ( -1===this.prevX && -1===this.prevY ) {
  4048. this.prevX= point.x;
  4049. this.prevY= point.y;
  4050. }
  4051. var ax= point.x-this.prevX;
  4052. var ay= point.y-this.prevY;
  4053. if ( ax===0 && ay===0 ) {
  4054. actor.setLocation( point.x, point.y );
  4055. return { x: actor.x, y: actor.y };
  4056. }
  4057. var angle= Math.atan2( ay, ax );
  4058. var si= CAAT.SpriteImage.prototype;
  4059. var pba= CAAT.PathBehavior.autorotate;
  4060. // actor is heading left to right
  4061. if ( this.autoRotateOp===pba.LEFT_TO_RIGHT ) {
  4062. if ( this.prevX<=point.x ) {
  4063. actor.setImageTransformation( si.TR_NONE );
  4064. }
  4065. else {
  4066. actor.setImageTransformation( si.TR_FLIP_HORIZONTAL );
  4067. angle+=Math.PI;
  4068. }
  4069. } else if ( this.autoRotateOp===pba.RIGHT_TO_LEFT ) {
  4070. if ( this.prevX<=point.x ) {
  4071. actor.setImageTransformation( si.TR_FLIP_HORIZONTAL );
  4072. }
  4073. else {
  4074. actor.setImageTransformation( si.TR_NONE );
  4075. angle-=Math.PI;
  4076. }
  4077. }
  4078. actor.setRotation(angle);
  4079. this.prevX= point.x;
  4080. this.prevY= point.y;
  4081. var modulo= Math.sqrt(ax*ax+ay*ay);
  4082. ax/=modulo;
  4083. ay/=modulo;
  4084. }
  4085. if ( this.doValueApplication ) {
  4086. actor.setLocation( point.x, point.y );
  4087. return { x: actor.x, y: actor.y };
  4088. } else {
  4089. return {
  4090. x: point.x,
  4091. y: point.y
  4092. };
  4093. }
  4094. },
  4095. /**
  4096. * Get a point on the path.
  4097. * If the time to get the point at is in behaviors frame time, a point on the path will be returned, otherwise
  4098. * a default {x:-1, y:-1} point will be returned.
  4099. *
  4100. * @param time {number} the time at which the point will be taken from the path.
  4101. * @return {object} an object of the form {x:float y:float}
  4102. */
  4103. positionOnTime : function(time) {
  4104. if ( this.isBehaviorInTime(time,null) ) {
  4105. time= this.normalizeTime(time);
  4106. return this.path.getPosition( time );
  4107. }
  4108. return {x:-1, y:-1};
  4109. }
  4110. };
  4111. extend( CAAT.PathBehavior, CAAT.Behavior );
  4112. })();
  4113. (function() {
  4114. /**
  4115. * ColorBehavior interpolates between two given colors.
  4116. * @constructor
  4117. */
  4118. CAAT.ColorBehavior= function() {
  4119. return this;
  4120. };
  4121. CAAT.ColorBehavior.prototype= {
  4122. };
  4123. extend( CAAT.ColorBehavior, CAAT.Behavior );
  4124. })();
  4125. (function() {
  4126. /**
  4127. *
  4128. * Scale only X or Y axis, instead both at the same time as ScaleBehavior.
  4129. *
  4130. * @constructor
  4131. */
  4132. CAAT.Scale1Behavior= function() {
  4133. CAAT.Scale1Behavior.superclass.constructor.call(this);
  4134. this.anchor= CAAT.Actor.prototype.ANCHOR_CENTER;
  4135. return this;
  4136. };
  4137. CAAT.Scale1Behavior.prototype= {
  4138. startScale: 1,
  4139. endScale: 1,
  4140. anchorX: .50,
  4141. anchorY: .50,
  4142. sx : 1,
  4143. sy : 1,
  4144. applyOnX : true,
  4145. getPropertyName : function() {
  4146. return "scale";
  4147. },
  4148. /**
  4149. * Applies corresponding scale values for a given time.
  4150. *
  4151. * @param time the time to apply the scale for.
  4152. * @param actor the target actor to Scale.
  4153. * @return {object} an object of the form <code>{ scaleX: {float}, scaleY: {float}�}</code>
  4154. */
  4155. setForTime : function(time,actor) {
  4156. var scale= this.startScale + time*(this.endScale-this.startScale);
  4157. // Firefox 3.x & 4, will crash animation if either scaleX or scaleY equals 0.
  4158. if (0===scale ) {
  4159. scale=0.01;
  4160. }
  4161. if ( this.doValueApplication ) {
  4162. if ( this.applyOnX ) {
  4163. actor.setScaleAnchored( scale, actor.scaleY, this.anchorX, this.anchorY );
  4164. } else {
  4165. actor.setScaleAnchored( actor.scaleX, scale, this.anchorX, this.anchorY );
  4166. }
  4167. }
  4168. return scale;
  4169. },
  4170. /**
  4171. * Define this scale behaviors values.
  4172. *
  4173. * Be aware the anchor values are supplied in <b>RELATIVE PERCENT</b> to
  4174. * actor's size.
  4175. *
  4176. * @param start {number} initial X axis scale value.
  4177. * @param end {number} final X axis scale value.
  4178. * @param anchorx {float} the percent position for anchorX
  4179. * @param anchory {float} the percent position for anchorY
  4180. *
  4181. * @return this.
  4182. */
  4183. setValues : function( start, end, applyOnX, anchorx, anchory ) {
  4184. this.startScale= start;
  4185. this.endScale= end;
  4186. this.applyOnX= !!applyOnX;
  4187. if ( typeof anchorx!=='undefined' && typeof anchory!=='undefined' ) {
  4188. this.anchorX= anchorx;
  4189. this.anchorY= anchory;
  4190. }
  4191. return this;
  4192. },
  4193. /**
  4194. * Set an exact position scale anchor. Use this method when it is hard to
  4195. * set a thorough anchor position expressed in percentage.
  4196. * @param actor
  4197. * @param x
  4198. * @param y
  4199. */
  4200. setAnchor : function( actor, x, y ) {
  4201. this.anchorX= x/actor.width;
  4202. this.anchorY= y/actor.height;
  4203. return this;
  4204. },
  4205. calculateKeyFrameData : function( time ) {
  4206. var scale;
  4207. time= this.interpolator.getPosition(time).y;
  4208. scale= this.startScale + time*(this.endScale-this.startScale);
  4209. return this.applyOnX ? "scaleX("+scale+")" : "scaleY("+scale+")";
  4210. },
  4211. calculateKeyFramesData : function(prefix, name, keyframessize) {
  4212. if ( typeof keyframessize==='undefined' ) {
  4213. keyframessize= 100;
  4214. }
  4215. keyframessize>>=0;
  4216. var i;
  4217. var kfr;
  4218. var kfd= "@-"+prefix+"-keyframes "+name+" {";
  4219. for( i=0; i<=keyframessize; i++ ) {
  4220. kfr= "" +
  4221. (i/keyframessize*100) + "%" + // percentage
  4222. "{" +
  4223. "-"+prefix+"-transform:" + this.calculateKeyFrameData(i/keyframessize) +
  4224. "}";
  4225. kfd+= kfr;
  4226. }
  4227. kfd+="}";
  4228. return kfd;
  4229. }
  4230. };
  4231. extend( CAAT.Scale1Behavior, CAAT.Behavior );
  4232. })();/**
  4233. * See LICENSE file.
  4234. *
  4235. * This object manages CSS3 transitions reflecting applying behaviors.
  4236. *
  4237. **/
  4238. (function() {
  4239. CAAT.CSS= {};
  4240. CAAT.CSS.PREFIX= (function() {
  4241. var prefix = "";
  4242. var prefixes = ['WebKit', 'Moz', 'O'];
  4243. var keyframes= "";
  4244. // guess this browser vendor prefix.
  4245. for (var i = 0; i < prefixes.length; i++) {
  4246. if (window[prefixes[i] + 'CSSKeyframeRule']) {
  4247. prefix = prefixes[i].toLowerCase();
  4248. break;
  4249. }
  4250. }
  4251. CAAT.CSS.PROP_ANIMATION= '-'+prefix+'-animation';
  4252. return prefix;
  4253. })();
  4254. CAAT.CSS.applyKeyframe= function( domElement, name, secs, forever ) {
  4255. domElement.style[CAAT.CSS.PROP_ANIMATION]= name+' '+(secs/1000)+'s linear both '+(forever ? 'infinite' : '') ;
  4256. };
  4257. CAAT.CSS.unregisterKeyframes= function( name ) {
  4258. var index= CAAT.CSS.getCSSKeyframesIndex(name);
  4259. if ( -1!==index ) {
  4260. document.styleSheets[0].deleteRule( index );
  4261. }
  4262. };
  4263. /**
  4264. *
  4265. * @param kfDescriptor {object{ name{string}, behavior{CAAT.Behavior}, size{!number}, overwrite{boolean}}
  4266. */
  4267. CAAT.CSS.registerKeyframes= function( kfDescriptor ) {
  4268. var name= kfDescriptor.name;
  4269. var behavior= kfDescriptor.behavior;
  4270. var size= kfDescriptor.size;
  4271. var overwrite= kfDescriptor.overwrite;
  4272. if ( typeof name==='undefined' || typeof behavior==='undefined' ) {
  4273. throw 'Keyframes must be defined by a name and a CAAT.Behavior instance.';
  4274. }
  4275. if ( typeof size==='undefined' ) {
  4276. size= 100;
  4277. }
  4278. if ( typeof overwrite==='undefined' ) {
  4279. overwrite= false;
  4280. }
  4281. // find if keyframes has already a name set.
  4282. var cssRulesIndex= CAAT.CSS.getCSSKeyframesIndex(name);
  4283. if (-1!==cssRulesIndex && !overwrite) {
  4284. return;
  4285. }
  4286. var keyframesRule= behavior.calculateKeyframesData(CAAT.CSS.PREFIX, name, size );
  4287. if (document.styleSheets) {
  4288. if ( !document.styleSheets.length) {
  4289. var s = document.createElement('style');
  4290. s.type="text/css";
  4291. document.getElementsByTagName('head')[ 0 ].appendChild(s);
  4292. }
  4293. if ( -1!==cssRulesIndex ) {
  4294. document.styleSheets[0].deleteRule( cssRulesIndex );
  4295. }
  4296. document.styleSheets[0].insertRule( keyframesRule, 0 );
  4297. }
  4298. };
  4299. CAAT.CSS.getCSSKeyframesIndex= function(name) {
  4300. var ss = document.styleSheets;
  4301. for (var i = ss.length - 1; i >= 0; i--) {
  4302. try {
  4303. var s = ss[i],
  4304. rs = s.cssRules ? s.cssRules :
  4305. s.rules ? s.rules :
  4306. [];
  4307. for (var j = rs.length - 1; j >= 0; j--) {
  4308. if ( ( rs[j].type === window.CSSRule.WEBKIT_KEYFRAMES_RULE ||
  4309. rs[j].type === window.CSSRule.MOZ_KEYFRAMES_RULE ) && rs[j].name === name) {
  4310. return j;
  4311. }
  4312. }
  4313. } catch(e) {
  4314. }
  4315. }
  4316. return -1;
  4317. };
  4318. CAAT.CSS.getCSSKeyframes= function(name) {
  4319. var ss = document.styleSheets;
  4320. for (var i = ss.length - 1; i >= 0; i--) {
  4321. try {
  4322. var s = ss[i],
  4323. rs = s.cssRules ? s.cssRules :
  4324. s.rules ? s.rules :
  4325. [];
  4326. for (var j = rs.length - 1; j >= 0; j--) {
  4327. if ( ( rs[j].type === window.CSSRule.WEBKIT_KEYFRAMES_RULE ||
  4328. rs[j].type === window.CSSRule.MOZ_KEYFRAMES_RULE ) && rs[j].name === name) {
  4329. return rs[j];
  4330. }
  4331. }
  4332. }
  4333. catch(e) {
  4334. }
  4335. }
  4336. return null;
  4337. };
  4338. })();/**
  4339. *
  4340. * taken from: http://www.quirksmode.org/js/detect.html
  4341. *
  4342. * 20101008 Hyperandroid. IE9 seems to identify himself as Explorer and stopped calling himself MSIE.
  4343. * Added Explorer description to browser list. Thanks @alteredq for this tip.
  4344. *
  4345. */
  4346. (function() {
  4347. CAAT.BrowserDetect = function() {
  4348. this.init();
  4349. return this;
  4350. };
  4351. CAAT.BrowserDetect.prototype = {
  4352. browser: '',
  4353. version: 0,
  4354. OS: '',
  4355. init: function()
  4356. {
  4357. this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
  4358. this.version = this.searchVersion(navigator.userAgent) ||
  4359. this.searchVersion(navigator.appVersion) ||
  4360. "an unknown version";
  4361. this.OS = this.searchString(this.dataOS) || "an unknown OS";
  4362. },
  4363. searchString: function (data) {
  4364. for (var i=0;i<data.length;i++) {
  4365. var dataString = data[i].string;
  4366. var dataProp = data[i].prop;
  4367. this.versionSearchString = data[i].versionSearch || data[i].identity;
  4368. if (dataString) {
  4369. if (dataString.indexOf(data[i].subString) !== -1)
  4370. return data[i].identity;
  4371. }
  4372. else if (dataProp)
  4373. return data[i].identity;
  4374. }
  4375. },
  4376. searchVersion: function (dataString) {
  4377. var index = dataString.indexOf(this.versionSearchString);
  4378. if (index === -1) return;
  4379. return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
  4380. },
  4381. dataBrowser: [
  4382. {
  4383. string: navigator.userAgent,
  4384. subString: "Chrome",
  4385. identity: "Chrome"
  4386. },
  4387. { string: navigator.userAgent,
  4388. subString: "OmniWeb",
  4389. versionSearch: "OmniWeb/",
  4390. identity: "OmniWeb"
  4391. },
  4392. {
  4393. string: navigator.vendor,
  4394. subString: "Apple",
  4395. identity: "Safari",
  4396. versionSearch: "Version"
  4397. },
  4398. {
  4399. prop: window.opera,
  4400. identity: "Opera"
  4401. },
  4402. {
  4403. string: navigator.vendor,
  4404. subString: "iCab",
  4405. identity: "iCab"
  4406. },
  4407. {
  4408. string: navigator.vendor,
  4409. subString: "KDE",
  4410. identity: "Konqueror"
  4411. },
  4412. {
  4413. string: navigator.userAgent,
  4414. subString: "Firefox",
  4415. identity: "Firefox"
  4416. },
  4417. {
  4418. string: navigator.vendor,
  4419. subString: "Camino",
  4420. identity: "Camino"
  4421. },
  4422. { // for newer Netscapes (6+)
  4423. string: navigator.userAgent,
  4424. subString: "Netscape",
  4425. identity: "Netscape"
  4426. },
  4427. {
  4428. string: navigator.userAgent,
  4429. subString: "MSIE",
  4430. identity: "Explorer",
  4431. versionSearch: "MSIE"
  4432. },
  4433. {
  4434. string: navigator.userAgent,
  4435. subString: "Explorer",
  4436. identity: "Explorer",
  4437. versionSearch: "Explorer"
  4438. },
  4439. {
  4440. string: navigator.userAgent,
  4441. subString: "Gecko",
  4442. identity: "Mozilla",
  4443. versionSearch: "rv"
  4444. },
  4445. { // for older Netscapes (4-)
  4446. string: navigator.userAgent,
  4447. subString: "Mozilla",
  4448. identity: "Netscape",
  4449. versionSearch: "Mozilla"
  4450. }
  4451. ],
  4452. dataOS : [
  4453. {
  4454. string: navigator.platform,
  4455. subString: "Win",
  4456. identity: "Windows"
  4457. },
  4458. {
  4459. string: navigator.platform,
  4460. subString: "Mac",
  4461. identity: "Mac"
  4462. },
  4463. {
  4464. string: navigator.userAgent,
  4465. subString: "iPhone",
  4466. identity: "iPhone/iPod"
  4467. },
  4468. {
  4469. string: navigator.platform,
  4470. subString: "Linux",
  4471. identity: "Linux"
  4472. }
  4473. ]
  4474. };
  4475. })();/**
  4476. * See LICENSE file.
  4477. *
  4478. * Get realtime Debug information of CAAT's activity.
  4479. * Set CAAT.DEBUG=1 before any CAAT.Director object creation.
  4480. * This class creates a DOM node called 'caat-debug' and associated styles
  4481. * The debug panel is minimized by default and shows short information. It can be expanded and minimized again by clicking on it
  4482. *
  4483. */
  4484. (function() {
  4485. CAAT.Debug= function() {
  4486. return this;
  4487. };
  4488. CAAT.Debug.prototype= {
  4489. width: 0,
  4490. height: 0,
  4491. canvas: null,
  4492. ctx: null,
  4493. statistics: null,
  4494. framerate: null,
  4495. textContainer: null,
  4496. textFPS: null,
  4497. textEntitiesTotal: null,
  4498. textEntitiesActive: null,
  4499. textDraws: null,
  4500. textDrawTime: null,
  4501. textRAFTime: null,
  4502. textDirtyRects: null,
  4503. frameTimeAcc : 0,
  4504. frameRAFAcc : 0,
  4505. canDebug: false,
  4506. SCALE: 60,
  4507. debugTpl:
  4508. " <style type=\"text/css\">"+
  4509. " #caat-debug {"+
  4510. " z-index: 10000;"+
  4511. " position:fixed;"+
  4512. " bottom:0;"+
  4513. " left:0;"+
  4514. " width:100%;"+
  4515. " background-color: rgba(0,0,0,0.8);"+
  4516. " }"+
  4517. " #caat-debug.caat_debug_max {"+
  4518. " margin-bottom: 0px;"+
  4519. " }"+
  4520. " .caat_debug_bullet {"+
  4521. " display:inline-block;"+
  4522. " background-color:#f00;"+
  4523. " width:8px;"+
  4524. " height:8px;"+
  4525. " border-radius: 4px;"+
  4526. " margin-left:10px;"+
  4527. " margin-right:2px;"+
  4528. " }"+
  4529. " .caat_debug_description {"+
  4530. " font-size:11px;"+
  4531. " font-family: helvetica, arial;"+
  4532. " color: #aaa;"+
  4533. " display: inline-block;"+
  4534. " }"+
  4535. " .caat_debug_value {"+
  4536. " font-size:11px;"+
  4537. " font-family: helvetica, arial;"+
  4538. " color: #fff;"+
  4539. " width:25px;"+
  4540. " text-align: right;"+
  4541. " display: inline-block;"+
  4542. " margin-right: .3em;"+
  4543. " }"+
  4544. " .caat_debug_indicator {"+
  4545. " float: right;"+
  4546. " }"+
  4547. " #debug_tabs {"+
  4548. " border-top: 1px solid #888;"+
  4549. " height:25px;"+
  4550. " }"+
  4551. " .tab_max_min {"+
  4552. " font-family: helvetica, arial;"+
  4553. " font-size: 12px;"+
  4554. " font-weight: bold;"+
  4555. " color: #888;"+
  4556. " border-right: 1px solid #888;"+
  4557. " float: left;"+
  4558. " cursor: pointer;"+
  4559. " padding-left: 5px;"+
  4560. " padding-right: 5px;"+
  4561. " padding-top: 5px;"+
  4562. " height: 20px;"+
  4563. " }"+
  4564. " .debug_tabs_content_hidden {"+
  4565. " display: none;"+
  4566. " width: 100%;"+
  4567. " }"+
  4568. " .debug_tabs_content_visible {"+
  4569. " display: block;"+
  4570. " width: 100%;"+
  4571. " }"+
  4572. " .checkbox_enabled {"+
  4573. " display:inline-block;"+
  4574. " background-color:#eee;"+
  4575. " border: 1px solid #eee;"+
  4576. " width:6px;"+
  4577. " height:8px;"+
  4578. " margin-left:12px;"+
  4579. " margin-right:2px;"+
  4580. " cursor: pointer;"+
  4581. " }"+
  4582. " .checkbox_disabled {"+
  4583. " display:inline-block;"+
  4584. " width:6px;"+
  4585. " height:8px;"+
  4586. " background-color: #333;"+
  4587. " border: 1px solid #eee;"+
  4588. " margin-left:12px;"+
  4589. " margin-right:2px;"+
  4590. " cursor: pointer;"+
  4591. " }"+
  4592. " .checkbox_description {"+
  4593. " font-size:11px;"+
  4594. " font-family: helvetica, arial;"+
  4595. " color: #fff;"+
  4596. " }"+
  4597. " .debug_tab {"+
  4598. " font-family: helvetica, arial;"+
  4599. " font-size: 12px;"+
  4600. " color: #fff;"+
  4601. " border-right: 1px solid #888;"+
  4602. " float: left;"+
  4603. " padding-left: 5px;"+
  4604. " padding-right: 5px;"+
  4605. " height: 20px;"+
  4606. " padding-top: 5px;"+
  4607. " cursor: default;"+
  4608. " }"+
  4609. " .debug_tab_selected {"+
  4610. " background-color: #444;"+
  4611. " cursor: default;"+
  4612. " }"+
  4613. " .debug_tab_not_selected {"+
  4614. " background-color: #000;"+
  4615. " cursor: pointer;"+
  4616. " }"+
  4617. " </style>"+
  4618. " <div id=\"caat-debug\">"+
  4619. " <div id=\"debug_tabs\">"+
  4620. " <span class=\"tab_max_min\" onCLick=\"javascript: var debug = document.getElementById('debug_tabs_content');if (debug.className === 'debug_tabs_content_visible') {debug.className = 'debug_tabs_content_hidden'} else {debug.className = 'debug_tabs_content_visible'}\"> CAAT Debug panel </span>"+
  4621. " <span id=\"caat-debug-tab0\" class=\"debug_tab debug_tab_selected\">Performance</span>"+
  4622. " <span id=\"caat-debug-tab1\" class=\"debug_tab debug_tab_not_selected\">Controls</span>"+
  4623. " <span class=\"caat_debug_indicator\">"+
  4624. " <span class=\"caat_debug_bullet\" style=\"background-color:#0f0;\"></span>"+
  4625. " <span class=\"caat_debug_description\">Draw Time: </span>"+
  4626. " <span class=\"caat_debug_value\" id=\"textDrawTime\">5.46</span>"+
  4627. " <span class=\"caat_debug_description\">ms.</span>"+
  4628. " </span>"+
  4629. " <span class=\"caat_debug_indicator\">"+
  4630. " <span class=\"caat_debug_bullet\" style=\"background-color:#f00;\"></span>"+
  4631. " <span class=\"caat_debug_description\">FPS: </span>"+
  4632. " <span class=\"caat_debug_value\" id=\"textFPS\">48</span>"+
  4633. " </span>"+
  4634. " </div>"+
  4635. " <div id=\"debug_tabs_content\" class=\"debug_tabs_content_hidden\">"+
  4636. " <div id=\"caat-debug-tab0-content\">"+
  4637. " <canvas id=\"caat-debug-canvas\" height=\"60\"></canvas>"+
  4638. " <div>"+
  4639. " <span>"+
  4640. " <span class=\"caat_debug_bullet\" style=\"background-color:#0f0;\"></span>"+
  4641. " <span class=\"caat_debug_description\">RAF Time:</span>"+
  4642. " <span class=\"caat_debug_value\" id=\"textRAFTime\">20.76</span>"+
  4643. " <span class=\"caat_debug_description\">ms.</span>"+
  4644. " </span>"+
  4645. " <span>"+
  4646. " <span class=\"caat_debug_bullet\" style=\"background-color:#0ff;\"></span>"+
  4647. " <span class=\"caat_debug_description\">Entities Total: </span>"+
  4648. " <span class=\"caat_debug_value\" id=\"textEntitiesTotal\">41</span>"+
  4649. " </span>"+
  4650. " <span>"+
  4651. " <span class=\"caat_debug_bullet\" style=\"background-color:#0ff;\"></span>"+
  4652. " <span class=\"caat_debug_description\">Entities Active: </span>"+
  4653. " <span class=\"caat_debug_value\" id=\"textEntitiesActive\">37</span>"+
  4654. " </span>"+
  4655. " <span>"+
  4656. " <span class=\"caat_debug_bullet\" style=\"background-color:#00f;\"></span>"+
  4657. " <span class=\"caat_debug_description\">Draws: </span>"+
  4658. " <span class=\"caat_debug_value\" id=\"textDraws\">0</span>"+
  4659. " </span>"+
  4660. " <span>"+
  4661. " <span class=\"caat_debug_bullet\" style=\"background-color:#00f;\"></span>"+
  4662. " <span class=\"caat_debug_description\">DirtyRects: </span>"+
  4663. " <span class=\"caat_debug_value\" id=\"textDirtyRects\">0</span>"+
  4664. " </span>"+
  4665. " </div>"+
  4666. " </div>"+
  4667. " <div id=\"caat-debug-tab1-content\">"+
  4668. " <div>"+
  4669. " <div>"+
  4670. " <span id=\"control-sound\"></span>"+
  4671. " <span class=\"checkbox_description\">Sound</span>"+
  4672. " </div>"+
  4673. " <div>"+
  4674. " <span id=\"control-music\"></span>"+
  4675. " <span class=\"checkbox_description\">Music</span>"+
  4676. " </div>"+
  4677. " <div>"+
  4678. " <span id=\"control-aabb\"></span>"+
  4679. " <span class=\"checkbox_description\">AA Bounding Boxes</span>"+
  4680. " </div>"+
  4681. " <div>"+
  4682. " <span id=\"control-bb\"></span>"+
  4683. " <span class=\"checkbox_description\">Bounding Boxes</span>"+
  4684. " </div>"+
  4685. " <div>"+
  4686. " <span id=\"control-dr\"></span>"+
  4687. " <span class=\"checkbox_description\">Dirty Rects</span>"+
  4688. " </div>"+
  4689. " </div>"+
  4690. " </div>"+
  4691. " </div>"+
  4692. " </div>",
  4693. setScale : function(s) {
  4694. this.scale= s;
  4695. return this;
  4696. },
  4697. initialize: function(w,h) {
  4698. w= window.innerWidth;
  4699. this.width= w;
  4700. this.height= h;
  4701. this.framerate = {
  4702. refreshInterval: CAAT.FPS_REFRESH || 500, // refresh every ? ms, updating too quickly gives too large rounding errors
  4703. frames: 0, // number offrames since last refresh
  4704. timeLastRefresh: 0, // When was the framerate counter refreshed last
  4705. fps: 0, // current framerate
  4706. prevFps: -1, // previously drawn FPS
  4707. fpsMin: 1000, // minimum measured framerate
  4708. fpsMax: 0 // maximum measured framerate
  4709. };
  4710. var debugContainer= document.getElementById('caat-debug');
  4711. if (!debugContainer) {
  4712. var wrap = document.createElement('div');
  4713. wrap.innerHTML=this.debugTpl;
  4714. document.body.appendChild(wrap);
  4715. eval( ""+
  4716. " function initCheck( name, bool, callback ) {"+
  4717. " var elem= document.getElementById(name);"+
  4718. " if ( elem ) {"+
  4719. " elem.className= (bool) ? \"checkbox_enabled\" : \"checkbox_disabled\";"+
  4720. " if ( callback ) {"+
  4721. " elem.addEventListener( \"click\", (function(elem, callback) {"+
  4722. " return function(e) {"+
  4723. " elem.__value= !elem.__value;"+
  4724. " elem.className= (elem.__value) ? \"checkbox_enabled\" : \"checkbox_disabled\";"+
  4725. " callback(e,elem.__value);"+
  4726. " }"+
  4727. " })(elem, callback), false );"+
  4728. " }"+
  4729. " elem.__value= bool;"+
  4730. " }"+
  4731. " }"+
  4732. " function setupTabs() {"+
  4733. " var numTabs=0;"+
  4734. " var elem;"+
  4735. " var elemContent;"+
  4736. " do {"+
  4737. " elem= document.getElementById(\"caat-debug-tab\"+numTabs);"+
  4738. " if ( elem ) {"+
  4739. " elemContent= document.getElementById(\"caat-debug-tab\"+numTabs+\"-content\");"+
  4740. " if ( elemContent ) {"+
  4741. " elemContent.style.display= numTabs===0 ? 'block' : 'none';"+
  4742. " elem.className= numTabs===0 ? \"debug_tab debug_tab_selected\" : \"debug_tab debug_tab_not_selected\";"+
  4743. " elem.addEventListener( \"click\", (function(tabIndex) {"+
  4744. " return function(e) {"+
  4745. " for( var i=0; i<numTabs; i++ ) {"+
  4746. " var _elem= document.getElementById(\"caat-debug-tab\"+i);"+
  4747. " var _elemContent= document.getElementById(\"caat-debug-tab\"+i+\"-content\");"+
  4748. " _elemContent.style.display= i===tabIndex ? 'block' : 'none';"+
  4749. " _elem.className= i===tabIndex ? \"debug_tab debug_tab_selected\" : \"debug_tab debug_tab_not_selected\";"+
  4750. " }"+
  4751. " }"+
  4752. " })(numTabs), false );"+
  4753. " }"+
  4754. " numTabs++;"+
  4755. " }"+
  4756. " } while( elem );"+
  4757. " }"+
  4758. " initCheck( \"control-sound\", CAAT.director[0].isSoundEffectsEnabled(), function(e, bool) {"+
  4759. " CAAT.director[0].setSoundEffectsEnabled(bool);"+
  4760. " } );"+
  4761. " initCheck( \"control-music\", CAAT.director[0].isMusicEnabled(), function(e, bool) {"+
  4762. " CAAT.director[0].setMusicEnabled(bool);"+
  4763. " } );"+
  4764. " initCheck( \"control-aabb\", CAAT.DEBUGBB, function(e,bool) {"+
  4765. " CAAT.DEBUGAABB= bool;"+
  4766. " CAAT.director[0].currentScene.dirty= true;"+
  4767. " } );"+
  4768. " initCheck( \"control-bb\", CAAT.DEBUGBB, function(e,bool) {"+
  4769. " CAAT.DEBUGBB= bool;"+
  4770. " if ( bool ) {"+
  4771. " CAAT.DEBUGAABB= true;"+
  4772. " }"+
  4773. " CAAT.director[0].currentScene.dirty= true;"+
  4774. " } );"+
  4775. " initCheck( \"control-dr\", CAAT.DEBUG_DIRTYRECTS , function( e,bool ) {"+
  4776. " CAAT.DEBUG_DIRTYRECTS= bool;"+
  4777. " });"+
  4778. " setupTabs();" );
  4779. }
  4780. this.canvas= document.getElementById('caat-debug-canvas');
  4781. if ( null===this.canvas ) {
  4782. this.canDebug= false;
  4783. return;
  4784. }
  4785. this.canvas.width= w;
  4786. this.canvas.height=h;
  4787. this.ctx= this.canvas.getContext('2d');
  4788. this.ctx.fillStyle= '#000';
  4789. this.ctx.fillRect(0,0,this.width,this.height);
  4790. this.textFPS= document.getElementById("textFPS");
  4791. this.textDrawTime= document.getElementById("textDrawTime");
  4792. this.textRAFTime= document.getElementById("textRAFTime");
  4793. this.textEntitiesTotal= document.getElementById("textEntitiesTotal");
  4794. this.textEntitiesActive= document.getElementById("textEntitiesActive");
  4795. this.textDraws= document.getElementById("textDraws");
  4796. this.textDirtyRects= document.getElementById("textDirtyRects");
  4797. this.canDebug= true;
  4798. return this;
  4799. },
  4800. debugInfo : function( statistics ) {
  4801. this.statistics= statistics;
  4802. this.frameTimeAcc+= CAAT.FRAME_TIME;
  4803. this.frameRAFAcc+= CAAT.REQUEST_ANIMATION_FRAME_TIME;
  4804. /* Update the framerate counter */
  4805. this.framerate.frames++;
  4806. if ( CAAT.RAF > this.framerate.timeLastRefresh + this.framerate.refreshInterval ) {
  4807. this.framerate.fps = ( ( this.framerate.frames * 1000 ) / ( CAAT.RAF - this.framerate.timeLastRefresh ) ) | 0;
  4808. this.framerate.fpsMin = this.framerate.frames > 0 ? Math.min( this.framerate.fpsMin, this.framerate.fps ) : this.framerate.fpsMin;
  4809. this.framerate.fpsMax = Math.max( this.framerate.fpsMax, this.framerate.fps );
  4810. this.textFPS.innerHTML= this.framerate.fps;
  4811. var value= ((this.frameTimeAcc*100/this.framerate.frames)|0)/100;
  4812. this.frameTimeAcc=0;
  4813. this.textDrawTime.innerHTML= value;
  4814. var value2= ((this.frameRAFAcc*100/this.framerate.frames)|0)/100;
  4815. this.frameRAFAcc=0;
  4816. this.textRAFTime.innerHTML= value2;
  4817. this.framerate.timeLastRefresh = CAAT.RAF;
  4818. this.framerate.frames = 0;
  4819. this.paint(value2);
  4820. }
  4821. this.textEntitiesTotal.innerHTML= this.statistics.size_total;
  4822. this.textEntitiesActive.innerHTML= this.statistics.size_active;
  4823. this.textDirtyRects.innerHTML= this.statistics.size_dirtyRects;
  4824. this.textDraws.innerHTML= this.statistics.draws;
  4825. },
  4826. paint : function( rafValue ) {
  4827. var ctx= this.ctx;
  4828. var t=0;
  4829. ctx.drawImage(
  4830. this.canvas,
  4831. 1, 0, this.width-1, this.height,
  4832. 0, 0, this.width-1, this.height );
  4833. ctx.strokeStyle= 'black';
  4834. ctx.beginPath();
  4835. ctx.moveTo( this.width-.5, 0 );
  4836. ctx.lineTo( this.width-.5, this.height );
  4837. ctx.stroke();
  4838. ctx.strokeStyle= '#a22';
  4839. ctx.beginPath();
  4840. t= this.height-((20/this.SCALE*this.height)>>0)-.5;
  4841. ctx.moveTo( .5, t );
  4842. ctx.lineTo( this.width+.5, t );
  4843. ctx.stroke();
  4844. ctx.strokeStyle= '#aa2';
  4845. ctx.beginPath();
  4846. t= this.height-((30/this.SCALE*this.height)>>0)-.5;
  4847. ctx.moveTo( .5, t );
  4848. ctx.lineTo( this.width+.5, t );
  4849. ctx.stroke();
  4850. var fps = Math.min( this.height-(this.framerate.fps/this.SCALE*this.height), 59 );
  4851. if (-1===this.framerate.prevFps) {
  4852. this.framerate.prevFps= fps|0;
  4853. }
  4854. ctx.strokeStyle= '#0ff';//this.framerate.fps<15 ? 'red' : this.framerate.fps<30 ? 'yellow' : 'green';
  4855. ctx.beginPath();
  4856. ctx.moveTo( this.width, (fps|0)-.5 );
  4857. ctx.lineTo( this.width, this.framerate.prevFps-.5 );
  4858. ctx.stroke();
  4859. this.framerate.prevFps= fps;
  4860. var t1= ((this.height-(rafValue/this.SCALE*this.height))>>0)-.5;
  4861. ctx.strokeStyle= '#ff0';
  4862. ctx.beginPath();
  4863. ctx.moveTo( this.width, t1 );
  4864. ctx.lineTo( this.width, t1 );
  4865. ctx.stroke();
  4866. }
  4867. };
  4868. })();/**
  4869. * See LICENSE file.
  4870. *
  4871. * Classes to define animable elements.
  4872. * Actor is the superclass of every animable element in the scene graph. It handles the whole
  4873. * affine transformation MatrixStack, rotation, translation, globalAlpha and Behaviours. It also
  4874. * defines input methods.
  4875. * TODO: add text presentation/animation effects.
  4876. **/
  4877. (function() {
  4878. /**
  4879. * This class is the base for all animable entities in CAAT.
  4880. * It defines an entity able to:
  4881. *
  4882. * <ul>
  4883. * <li>Position itself on screen.
  4884. * <li>Able to modify its presentation aspect via affine transforms.
  4885. * <li>Take control of parent/child relationship.
  4886. * <li>Take track of behaviors (@see CAAT.Behavior).
  4887. * <li>Define a region on screen.
  4888. * <li>Define alpha composition scope.
  4889. * <li>Expose lifecycle.
  4890. * <li>Manage itself in/out scene time.
  4891. * <li>etc.
  4892. * </ul>
  4893. *
  4894. * @constructor
  4895. */
  4896. CAAT.Actor = function() {
  4897. this.behaviorList= [];
  4898. // this.keyframesList= [];
  4899. this.lifecycleListenerList= [];
  4900. this.AABB= new CAAT.Rectangle();
  4901. this.viewVertices= [
  4902. new CAAT.Point(0,0,0),
  4903. new CAAT.Point(0,0,0),
  4904. new CAAT.Point(0,0,0),
  4905. new CAAT.Point(0,0,0)
  4906. ];
  4907. this.scaleAnchor= this.ANCHOR_CENTER;
  4908. this.modelViewMatrix= new CAAT.Matrix();
  4909. this.worldModelViewMatrix= new CAAT.Matrix();
  4910. this.resetTransform();
  4911. this.setScale(1,1);
  4912. this.setRotation(0);
  4913. return this;
  4914. };
  4915. /**
  4916. * Reflection information needed to use the inspector.
  4917. * Each key defined identifies an object field. For each field, it could be specified:
  4918. * + get : accessor function or field name. if ended with () a function will be assumed.
  4919. * + set : mutator function or field name. if ended with () a function will be assumed.
  4920. * + type : field or accessor function return type.
  4921. *
  4922. * If not get or set method is defined, the inspector will assume either the field can't be read and/or set.
  4923. * If neither get and set are defined, the property will be avoided.
  4924. *
  4925. * The key can contain a set of comma separated values. This means these properties must be set/modified
  4926. * at once in the inspector editor field (if any). The way these functions will be set will be by calling
  4927. * the set method (must be a method) as previously defined.
  4928. */
  4929. CAAT.Actor.__reflectionInfo= {
  4930. "x" : "set:setX(), get:x, type:number",
  4931. "cached" : "get:isCached(), type:boolean",
  4932. "scaleX,scaleY" : "set:setScale(), type:number"
  4933. /*
  4934. "y" : "setY,w",
  4935. "width" : "setWidth,w",
  4936. "height" : "setHeight,w",
  4937. "start_time" : "setStartTime,w",
  4938. "duration" : "setDuration,w",
  4939. "clip" : "setClip,w",
  4940. "rotationAngle" : "setRotation,w",
  4941. "alpha" : "setAlpha,w",
  4942. "isGlobalAlpha" : "isGlobalAlpha,w",
  4943. "visible" : "isVisible",
  4944. "id" : "getId",
  4945. "backgroundImage" : ""*/
  4946. };
  4947. CAAT.Actor.ANCHOR_CENTER= 0; // constant values to determine different affine transform
  4948. CAAT.Actor.ANCHOR_TOP= 1; // anchors.
  4949. CAAT.Actor.ANCHOR_BOTTOM= 2;
  4950. CAAT.Actor.ANCHOR_LEFT= 3;
  4951. CAAT.Actor.ANCHOR_RIGHT= 4;
  4952. CAAT.Actor.ANCHOR_TOP_LEFT= 5;
  4953. CAAT.Actor.ANCHOR_TOP_RIGHT= 6;
  4954. CAAT.Actor.ANCHOR_BOTTOM_LEFT= 7;
  4955. CAAT.Actor.ANCHOR_BOTTOM_RIGHT= 8;
  4956. CAAT.Actor.ANCHOR_CUSTOM= 9;
  4957. CAAT.Actor.CACHE_SIMPLE= 1;
  4958. CAAT.Actor.CACHE_DEEP= 2;
  4959. CAAT.Actor.prototype= {
  4960. lifecycleListenerList: null, // Array of life cycle listener
  4961. behaviorList: null, // Array of behaviors to apply to the Actor
  4962. parent: null, // Parent of this Actor. May be Scene.
  4963. x: 0, // x position on parent. In parent's local coord. system.
  4964. y: 0, // y position on parent. In parent's local coord. system.
  4965. width: 0, // Actor's width. In parent's local coord. system.
  4966. height: 0, // Actor's height. In parent's local coord. system.
  4967. start_time: 0, // Start time in Scene time.
  4968. duration: Number.MAX_VALUE, // Actor duration in Scene time
  4969. clip: false, // should clip the Actor's content against its contour.
  4970. clipPath: null,
  4971. tAnchorX : 0,
  4972. tAnchorY : 0,
  4973. scaleX: 0, // transformation. width scale parameter
  4974. scaleY: 0, // transformation. height scale parameter
  4975. scaleTX: .50, // transformation. scale anchor x position
  4976. scaleTY: .50, // transformation. scale anchor y position
  4977. scaleAnchor: 0, // transformation. scale anchor
  4978. rotationAngle: 0, // transformation. rotation angle in radians
  4979. rotationY: .50, // transformation. rotation center y
  4980. alpha: 1, // alpha transparency value
  4981. rotationX: .50, // transformation. rotation center x
  4982. isGlobalAlpha: false, // is this a global alpha
  4983. frameAlpha: 1, // hierarchically calculated alpha for this Actor.
  4984. expired: false, // set when the actor has been expired
  4985. discardable: false, // set when you want this actor to be removed if expired
  4986. pointed: false, // is the mouse pointer inside this actor
  4987. mouseEnabled: true, // events enabled ?
  4988. visible: true,
  4989. ANCHOR_CENTER: 0, // constant values to determine different affine transform
  4990. ANCHOR_TOP: 1, // anchors.
  4991. ANCHOR_BOTTOM: 2,
  4992. ANCHOR_LEFT: 3,
  4993. ANCHOR_RIGHT: 4,
  4994. ANCHOR_TOP_LEFT: 5,
  4995. ANCHOR_TOP_RIGHT: 6,
  4996. ANCHOR_BOTTOM_LEFT: 7,
  4997. ANCHOR_BOTTOM_RIGHT: 8,
  4998. ANCHOR_CUSTOM: 9,
  4999. fillStyle: null, // any canvas rendering valid fill style.
  5000. strokeStyle: null, // any canvas rendering valid stroke style.
  5001. time: 0, // Cache Scene time.
  5002. AABB: null, // CAAT.Rectangle
  5003. viewVertices: null, // model to view transformed vertices.
  5004. inFrame: false, // boolean indicating whether this Actor was present on last frame.
  5005. dirty: true, // model view is dirty ?
  5006. wdirty: true, // world model view is dirty ?
  5007. oldX: -1,
  5008. oldY: -1,
  5009. modelViewMatrix: null, // model view matrix.
  5010. worldModelViewMatrix: null, // world model view matrix.
  5011. modelViewMatrixI: null, // model view matrix.
  5012. worldModelViewMatrixI: null, // world model view matrix.
  5013. glEnabled: false,
  5014. backgroundImage: null,
  5015. id: null,
  5016. size_active: 1, // number of animated children
  5017. size_total: 1,
  5018. __next: null,
  5019. __d_ax: -1, // for drag-enabled actors.
  5020. __d_ay: -1,
  5021. gestureEnabled: false,
  5022. invalid : true,
  5023. cached : 0, // 0 no, CACHE_SIMPLE | CACHE_DEEP
  5024. collides : false,
  5025. collidesAsRect : true,
  5026. isAA : true, // is this actor/container Axis aligned ? if so, much faster inverse matrices
  5027. // can be calculated.
  5028. isVisible : function() {
  5029. return this.isVisible;
  5030. },
  5031. setupCollission : function( collides, isCircular ) {
  5032. this.collides= collides;
  5033. this.collidesAsRect= !isCircular;
  5034. },
  5035. invalidate : function() {
  5036. this.invalid= true;
  5037. },
  5038. setGestureEnabled : function( enable ) {
  5039. this.gestureEnabled= !!enable;
  5040. },
  5041. isGestureEnabled : function() {
  5042. return this.gestureEnabled;
  5043. },
  5044. getId : function() {
  5045. return this.id;
  5046. },
  5047. setId : function(id) {
  5048. this.id= id;
  5049. return this;
  5050. },
  5051. /**
  5052. * Set this actor's parent.
  5053. * @param parent {CAAT.ActorContainer}
  5054. * @return this
  5055. */
  5056. setParent : function(parent) {
  5057. this.parent= parent;
  5058. return this;
  5059. },
  5060. /**
  5061. * Set this actor's background image.
  5062. * The need of a background image is to kept compatibility with the new CSSDirector class.
  5063. * The image parameter can be either an Image/Canvas or a CAAT.SpriteImage instance. If an image
  5064. * is supplied, it will be wrapped into a CAAT.SriteImage instance of 1 row by 1 column.
  5065. * If the actor has set an image in the background, the paint method will draw the image, otherwise
  5066. * and if set, will fill its background with a solid color.
  5067. * If adjust_size_to_image is true, the host actor will be redimensioned to the size of one
  5068. * single image from the SpriteImage (either supplied or generated because of passing an Image or
  5069. * Canvas to the function). That means the size will be set to [width:SpriteImage.singleWidth,
  5070. * height:singleHeight].
  5071. *
  5072. * WARN: if using a CSS renderer, the image supplied MUST be a HTMLImageElement instance.
  5073. *
  5074. * @see CAAT.SpriteImage
  5075. *
  5076. * @param image {Image|HTMLCanvasElement|CAAT.SpriteImage}
  5077. * @param adjust_size_to_image {boolean} whether to set this actor's size based on image parameter.
  5078. *
  5079. * @return this
  5080. */
  5081. setBackgroundImage : function(image, adjust_size_to_image ) {
  5082. if ( image ) {
  5083. if ( !(image instanceof CAAT.SpriteImage) ) {
  5084. image= new CAAT.SpriteImage().initialize(image,1,1);
  5085. }
  5086. image.setOwner(this);
  5087. this.backgroundImage= image;
  5088. if ( typeof adjust_size_to_image==='undefined' || adjust_size_to_image ) {
  5089. this.width= image.getWidth();
  5090. this.height= image.getHeight();
  5091. }
  5092. this.glEnabled= true;
  5093. } else {
  5094. this.backgroundImage= null;
  5095. }
  5096. return this;
  5097. },
  5098. /**
  5099. * Set the actor's SpriteImage index from animation sheet.
  5100. * @see CAAT.SpriteImage
  5101. * @param index {number}
  5102. *
  5103. * @return this
  5104. */
  5105. setSpriteIndex: function(index) {
  5106. if ( this.backgroundImage ) {
  5107. this.backgroundImage.setSpriteIndex(index);
  5108. this.invalidate();
  5109. }
  5110. return this;
  5111. },
  5112. /**
  5113. * Set this actor's background SpriteImage offset displacement.
  5114. * The values can be either positive or negative meaning the texture space of this background
  5115. * image does not start at (0,0) but at the desired position.
  5116. * @see CAAT.SpriteImage
  5117. * @param ox {number} horizontal offset
  5118. * @param oy {number} vertical offset
  5119. *
  5120. * @return this
  5121. */
  5122. setBackgroundImageOffset : function( ox, oy ) {
  5123. if ( this.backgroundImage ) {
  5124. this.backgroundImage.setOffset(ox,oy);
  5125. }
  5126. return this;
  5127. },
  5128. /**
  5129. * Set this actor's background SpriteImage its animation sequence.
  5130. * In its simplet's form a SpriteImage treats a given image as an array of rows by columns
  5131. * subimages. If you define d Sprite Image of 2x2, you'll be able to draw any of the 4 subimages.
  5132. * This method defines the animation sequence so that it could be set [0,2,1,3,2,1] as the
  5133. * animation sequence
  5134. * @param ii {Array<number>} an array of integers.
  5135. */
  5136. setAnimationImageIndex : function( ii ) {
  5137. if ( this.backgroundImage ) {
  5138. this.backgroundImage.setAnimationImageIndex(ii);
  5139. }
  5140. return this;
  5141. },
  5142. resetAnimationTime : function() {
  5143. if ( this.backgroundImage ) {
  5144. this.backgroundImage.resetAnimationTime();
  5145. }
  5146. return this;
  5147. },
  5148. setChangeFPS : function(time) {
  5149. if ( this.backgroundImage ) {
  5150. this.backgroundImage.setChangeFPS(time);
  5151. }
  5152. return this;
  5153. },
  5154. /**
  5155. * Set this background image transformation.
  5156. * If GL is enabled, this parameter has no effect.
  5157. * @param it any value from CAAT.SpriteImage.TR_*
  5158. * @return this
  5159. */
  5160. setImageTransformation : function( it ) {
  5161. if ( this.backgroundImage ) {
  5162. this.backgroundImage.setSpriteTransformation(it);
  5163. }
  5164. return this;
  5165. },
  5166. /**
  5167. * Center this actor at position (x,y).
  5168. * @param x {number} x position
  5169. * @param y {number} y position
  5170. *
  5171. * @return this
  5172. * @deprecated
  5173. */
  5174. centerOn : function( x,y ) {
  5175. this.setLocation( x-this.width/2, y-this.height/2 );
  5176. return this;
  5177. },
  5178. /**
  5179. * Center this actor at position (x,y).
  5180. * @param x {number} x position
  5181. * @param y {number} y position
  5182. *
  5183. * @return this
  5184. */
  5185. centerAt : function(x,y) {
  5186. return this.centerOn(x,y);
  5187. },
  5188. /**
  5189. * If GL is enables, get this background image's texture page, otherwise it will fail.
  5190. * @return {CAAT.GLTexturePage}
  5191. */
  5192. getTextureGLPage : function() {
  5193. return this.backgroundImage.image.__texturePage;
  5194. },
  5195. /**
  5196. * Set this actor invisible.
  5197. * The actor is animated but not visible.
  5198. * A container won't show any of its children if set visible to false.
  5199. *
  5200. * @param visible {boolean} set this actor visible or not.
  5201. * @return this
  5202. */
  5203. setVisible : function(visible) {
  5204. this.visible= visible;
  5205. return this;
  5206. },
  5207. /**
  5208. * Puts an Actor out of time line, that is, won't be transformed nor rendered.
  5209. * @return this
  5210. */
  5211. setOutOfFrameTime : function() {
  5212. this.setFrameTime(-1,0);
  5213. return this;
  5214. },
  5215. /**
  5216. * Adds an Actor's life cycle listener.
  5217. * The developer must ensure the actorListener is not already a listener, otherwise
  5218. * it will notified more than once.
  5219. * @param actorListener {object} an object with at least a method of the form:
  5220. * <code>actorLyfeCycleEvent( actor, string_event_type, long_time )</code>
  5221. */
  5222. addListener : function( actorListener ) {
  5223. this.lifecycleListenerList.push(actorListener);
  5224. return this;
  5225. },
  5226. /**
  5227. * Removes an Actor's life cycle listener.
  5228. * It will only remove the first occurrence of the given actorListener.
  5229. * @param actorListener {object} an Actor's life cycle listener.
  5230. */
  5231. removeListener : function( actorListener ) {
  5232. var n= this.lifecycleListenerList.length;
  5233. while(n--) {
  5234. if ( this.lifecycleListenerList[n]===actorListener ) {
  5235. // remove the nth element.
  5236. this.lifecycleListenerList.splice(n,1);
  5237. return;
  5238. }
  5239. }
  5240. },
  5241. /**
  5242. * Set alpha composition scope. global will mean this alpha value will be its children maximum.
  5243. * If set to false, only this actor will have this alpha value.
  5244. * @param global {boolean} whether the alpha value should be propagated to children.
  5245. */
  5246. setGlobalAlpha : function( global ) {
  5247. this.isGlobalAlpha= global;
  5248. return this;
  5249. },
  5250. /**
  5251. * Notifies the registered Actor's life cycle listener about some event.
  5252. * @param sEventType an string indicating the type of event being notified.
  5253. * @param time an integer indicating the time related to Scene's timeline when the event
  5254. * is being notified.
  5255. */
  5256. fireEvent : function(sEventType, time) {
  5257. for( var i=0; i<this.lifecycleListenerList.length; i++ ) {
  5258. this.lifecycleListenerList[i].actorLifeCycleEvent(this, sEventType, time);
  5259. }
  5260. },
  5261. /**
  5262. * Sets this Actor as Expired.
  5263. * If this is a Container, all the contained Actors won't be nor drawn nor will receive
  5264. * any event. That is, expiring an Actor means totally taking it out the Scene's timeline.
  5265. * @param time {number} an integer indicating the time the Actor was expired at.
  5266. * @return this.
  5267. */
  5268. setExpired : function(time) {
  5269. this.expired= true;
  5270. this.fireEvent('expired',time);
  5271. return this;
  5272. },
  5273. /**
  5274. * Enable or disable the event bubbling for this Actor.
  5275. * @param enable {boolean} a boolean indicating whether the event bubbling is enabled.
  5276. * @return this
  5277. */
  5278. enableEvents : function( enable ) {
  5279. this.mouseEnabled= enable;
  5280. return this;
  5281. },
  5282. /**
  5283. * Removes all behaviors from an Actor.
  5284. * @return this
  5285. */
  5286. emptyBehaviorList : function() {
  5287. this.behaviorList=[];
  5288. return this;
  5289. },
  5290. /**
  5291. * Caches a fillStyle in the Actor.
  5292. * @param style a valid Canvas rendering context fillStyle.
  5293. * @return this
  5294. */
  5295. setFillStyle : function( style ) {
  5296. this.fillStyle= style;
  5297. return this;
  5298. },
  5299. /**
  5300. * Caches a stroke style in the Actor.
  5301. * @param style a valid canvas rendering context stroke style.
  5302. * @return this
  5303. */
  5304. setStrokeStyle : function( style ) {
  5305. this.strokeStyle= style;
  5306. return this;
  5307. },
  5308. /**
  5309. * @deprecated
  5310. * @param paint
  5311. */
  5312. setPaint : function( paint ) {
  5313. return this.setFillStyle(paint);
  5314. },
  5315. /**
  5316. * Stablishes the Alpha transparency for the Actor.
  5317. * If it globalAlpha enabled, this alpha will the maximum alpha for every contained actors.
  5318. * The alpha must be between 0 and 1.
  5319. * @param alpha a float indicating the alpha value.
  5320. * @return this
  5321. */
  5322. setAlpha : function( alpha ) {
  5323. this.alpha= alpha;
  5324. this.invalidate();
  5325. return this;
  5326. },
  5327. /**
  5328. * Remove all transformation values for the Actor.
  5329. * @return this
  5330. */
  5331. resetTransform : function () {
  5332. this.rotationAngle=0;
  5333. this.rotationX=.5;
  5334. this.rotationY=.5;
  5335. this.scaleX=1;
  5336. this.scaleY=1;
  5337. this.scaleTX=.5;
  5338. this.scaleTY=.5;
  5339. this.scaleAnchor=0;
  5340. this.oldX=-1;
  5341. this.oldY=-1;
  5342. this.dirty= true;
  5343. return this;
  5344. },
  5345. /**
  5346. * Sets the time life cycle for an Actor.
  5347. * These values are related to Scene time.
  5348. * @param startTime an integer indicating the time until which the Actor won't be visible on the Scene.
  5349. * @param duration an integer indicating how much the Actor will last once visible.
  5350. * @return this
  5351. */
  5352. setFrameTime : function( startTime, duration ) {
  5353. this.start_time= startTime;
  5354. this.duration= duration;
  5355. this.expired= false;
  5356. this.dirty= true;
  5357. return this;
  5358. },
  5359. /**
  5360. * This method should me overriden by every custom Actor.
  5361. * It will be the drawing routine called by the Director to show every Actor.
  5362. * @param director the CAAT.Director instance that contains the Scene the Actor is in.
  5363. * @param time an integer indicating the Scene time in which the drawing is performed.
  5364. */
  5365. paint : function(director, time) {
  5366. if ( this.backgroundImage ) {
  5367. this.backgroundImage.paint(director,time,0,0);
  5368. } else if ( this.fillStyle ) {
  5369. var ctx= director.crc;
  5370. ctx.fillStyle= this.fillStyle;
  5371. ctx.fillRect(0,0,this.width,this.height );
  5372. }
  5373. },
  5374. /**
  5375. * A helper method to setScaleAnchored with an anchor of ANCHOR_CENTER
  5376. *
  5377. * @see setScaleAnchored
  5378. *
  5379. * @param sx a float indicating a width size multiplier.
  5380. * @param sy a float indicating a height size multiplier.
  5381. * @return this
  5382. */
  5383. setScale : function( sx, sy ) {
  5384. this.scaleX=sx;
  5385. this.scaleY=sy;
  5386. this.dirty= true;
  5387. return this;
  5388. },
  5389. getAnchorPercent : function( anchor ) {
  5390. var anchors=[
  5391. .50,.50, .50,0, .50,1.00,
  5392. 0,.50, 1.00,.50, 0,0,
  5393. 1.00,0, 0,1.00, 1.00,1.00
  5394. ];
  5395. return { x: anchors[anchor*2], y: anchors[anchor*2+1] };
  5396. },
  5397. /**
  5398. * Private.
  5399. * Gets a given anchor position referred to the Actor.
  5400. * @param anchor
  5401. * @return an object of the form { x: float, y: float }
  5402. */
  5403. getAnchor : function( anchor ) {
  5404. var tx=0, ty=0;
  5405. switch( anchor ) {
  5406. case this.ANCHOR_CENTER:
  5407. tx= .5;
  5408. ty= .5;
  5409. break;
  5410. case this.ANCHOR_TOP:
  5411. tx= .5;
  5412. ty= 0;
  5413. break;
  5414. case this.ANCHOR_BOTTOM:
  5415. tx= .5;
  5416. ty= 1;
  5417. break;
  5418. case this.ANCHOR_LEFT:
  5419. tx= 0;
  5420. ty= .5;
  5421. break;
  5422. case this.ANCHOR_RIGHT:
  5423. tx= 1;
  5424. ty= .5;
  5425. break;
  5426. case this.ANCHOR_TOP_RIGHT:
  5427. tx= 1;
  5428. ty= 0;
  5429. break;
  5430. case this.ANCHOR_BOTTOM_LEFT:
  5431. tx= 0;
  5432. ty= 1;
  5433. break;
  5434. case this.ANCHOR_BOTTOM_RIGHT:
  5435. tx= 1;
  5436. ty= 1;
  5437. break;
  5438. case this.ANCHOR_TOP_LEFT:
  5439. tx= 0;
  5440. ty= 0;
  5441. break;
  5442. }
  5443. return {x: tx, y: ty};
  5444. },
  5445. setGlobalAnchor : function( ax, ay ) {
  5446. this.tAnchorX= ax;
  5447. this.rotationX= ax;
  5448. this.scaleTX= ax;
  5449. this.tAnchorY= ay;
  5450. this.rotationY= ay;
  5451. this.scaleTY= ay;
  5452. this.dirty= true;
  5453. return this;
  5454. },
  5455. setScaleAnchor : function( sax, say ) {
  5456. this.scaleTX= sax;
  5457. this.scaleTY= say;
  5458. this.dirty= true;
  5459. return this;
  5460. },
  5461. /**
  5462. * Modify the dimensions on an Actor.
  5463. * The dimension will not affect the local coordinates system in opposition
  5464. * to setSize or setBounds.
  5465. *
  5466. * @param sx {number} width scale.
  5467. * @param sy {number} height scale.
  5468. * @param anchorx {number} x anchor to perform the Scale operation.
  5469. * @param anchory {number} y anchor to perform the Scale operation.
  5470. *
  5471. * @return this;
  5472. */
  5473. setScaleAnchored : function( sx, sy, anchorx, anchory ) {
  5474. this.scaleTX= anchorx;
  5475. this.scaleTY= anchory;
  5476. this.scaleX=sx;
  5477. this.scaleY=sy;
  5478. this.dirty= true;
  5479. return this;
  5480. },
  5481. setRotationAnchor : function( rax, ray ) {
  5482. this.rotationX= ray;
  5483. this.rotationY= rax;
  5484. this.dirty= true;
  5485. return this;
  5486. },
  5487. /**
  5488. * A helper method for setRotationAnchored. This methods stablishes the center
  5489. * of rotation to be the center of the Actor.
  5490. *
  5491. * @param angle a float indicating the angle in radians to rotate the Actor.
  5492. * @return this
  5493. */
  5494. setRotation : function( angle ) {
  5495. this.rotationAngle= angle;
  5496. this.dirty= true;
  5497. return this;
  5498. },
  5499. /**
  5500. * This method sets Actor rotation around a given position.
  5501. * @param angle {number} indicating the angle in radians to rotate the Actor.
  5502. * @param rx {number} value in the range 0..1
  5503. * @param ry {number} value in the range 0..1
  5504. * @return this;
  5505. */
  5506. setRotationAnchored : function( angle, rx, ry ) {
  5507. this.rotationAngle= angle;
  5508. this.rotationX= rx;
  5509. this.rotationY= ry;
  5510. this.dirty= true;
  5511. return this;
  5512. },
  5513. /**
  5514. * Sets an Actor's dimension
  5515. * @param w a float indicating Actor's width.
  5516. * @param h a float indicating Actor's height.
  5517. * @return this
  5518. */
  5519. setSize : function( w, h ) {
  5520. this.width= w|0;
  5521. this.height= h|0;
  5522. this.dirty= true;
  5523. return this;
  5524. },
  5525. /**
  5526. * Set location and dimension of an Actor at once.
  5527. *
  5528. * @param x{number} a float indicating Actor's x position.
  5529. * @param y{number} a float indicating Actor's y position
  5530. * @param w{number} a float indicating Actor's width
  5531. * @param h{number} a float indicating Actor's height
  5532. * @return this
  5533. */
  5534. setBounds : function(x, y, w, h) {
  5535. /*
  5536. this.x= x|0;
  5537. this.y= y|0;
  5538. this.width= w|0;
  5539. this.height= h|0;
  5540. */
  5541. this.x= x;
  5542. this.y= y;
  5543. this.width= w;
  5544. this.height= h;
  5545. this.dirty= true;
  5546. return this;
  5547. },
  5548. /**
  5549. * This method sets the position of an Actor inside its parent.
  5550. *
  5551. * @param x{number} a float indicating Actor's x position
  5552. * @param y{number} a float indicating Actor's y position
  5553. * @return this
  5554. *
  5555. * @deprecated
  5556. */
  5557. setLocation : function( x, y ) {
  5558. this.x= x;
  5559. this.y= y;
  5560. this.oldX= x;
  5561. this.oldY= y;
  5562. this.dirty= true;
  5563. return this;
  5564. },
  5565. setPosition : function( x,y ) {
  5566. return this.setLocation( x,y );
  5567. },
  5568. setPositionAnchor : function( pax, pay ) {
  5569. this.tAnchorX= pax;
  5570. this.tAnchorY= pay;
  5571. return this;
  5572. },
  5573. setPositionAnchored : function( x,y,pax,pay ) {
  5574. this.setLocation( x,y );
  5575. this.tAnchorX= pax;
  5576. this.tAnchorY= pay;
  5577. return this;
  5578. },
  5579. /**
  5580. * This method is called by the Director to know whether the actor is on Scene time.
  5581. * In case it was necessary, this method will notify any life cycle behaviors about
  5582. * an Actor expiration.
  5583. * @param time {number} time indicating the Scene time.
  5584. *
  5585. * @private
  5586. *
  5587. */
  5588. isInAnimationFrame : function(time) {
  5589. if ( this.expired ) {
  5590. return false;
  5591. }
  5592. if ( this.duration===Number.MAX_VALUE ) {
  5593. return this.start_time<=time;
  5594. }
  5595. if ( time>=this.start_time+this.duration ) {
  5596. if ( !this.expired ) {
  5597. this.setExpired(time);
  5598. }
  5599. return false;
  5600. }
  5601. return this.start_time<=time && time<this.start_time+this.duration;
  5602. },
  5603. /**
  5604. * Checks whether a coordinate is inside the Actor's bounding box.
  5605. * @param x {number} a float
  5606. * @param y {number} a float
  5607. *
  5608. * @return boolean indicating whether it is inside.
  5609. */
  5610. contains : function(x, y) {
  5611. return x>=0 && y>=0 && x<this.width && y<this.height;
  5612. },
  5613. /**
  5614. * This method must be called explicitly by every CAAT Actor.
  5615. * Making the life cycle explicitly initiated has always been a good idea.
  5616. *
  5617. * @return this
  5618. * @deprecated no longer needed.
  5619. */
  5620. create : function() {
  5621. return this;
  5622. },
  5623. /**
  5624. * Add a Behavior to the Actor.
  5625. * An Actor accepts an undefined number of Behaviors.
  5626. *
  5627. * @param behavior {CAAT.Behavior} a CAAT.Behavior instance
  5628. * @return this
  5629. *
  5630. * @deprecated
  5631. */
  5632. addBehavior : function( behavior ) {
  5633. this.behaviorList.push(behavior);
  5634. return this;
  5635. },
  5636. /**
  5637. * Remove a Behavior from the Actor.
  5638. * If the Behavior is not present at the actor behavior collection nothing happends.
  5639. *
  5640. * @param behavior {CAAT.Behavior} a CAAT.Behavior instance.
  5641. */
  5642. removeBehaviour : function( behavior ) {
  5643. var c= this.behaviorList;
  5644. var n= c.length-1;
  5645. while(n) {
  5646. if ( c[n]===behavior ) {
  5647. c.splice(n,1);
  5648. return this;
  5649. }
  5650. }
  5651. return this;
  5652. },
  5653. /**
  5654. * Remove a Behavior with id param as behavior identifier from this actor.
  5655. * This function will remove ALL behavior instances with the given id.
  5656. *
  5657. * @param id {number} an integer.
  5658. * return this;
  5659. */
  5660. removeBehaviorById : function( id ) {
  5661. var c= this.behaviorList;
  5662. for( var n=0; n<c.length; n++ ) {
  5663. if ( c[n].id===id) {
  5664. c.splice(n,1);
  5665. }
  5666. }
  5667. return this;
  5668. },
  5669. getBehavior : function(id) {
  5670. var c= this.behaviorList;
  5671. for( var n=0; n<c.length; n++ ) {
  5672. var cc= c[n];
  5673. if ( cc.id===id) {
  5674. return cc;
  5675. }
  5676. }
  5677. return null;
  5678. },
  5679. /**
  5680. * Set discardable property. If an actor is discardable, upon expiration will be removed from
  5681. * scene graph and hence deleted.
  5682. * @param discardable {boolean} a boolean indicating whether the Actor is discardable.
  5683. * @return this
  5684. */
  5685. setDiscardable : function( discardable ) {
  5686. this.discardable= discardable;
  5687. return this;
  5688. },
  5689. /**
  5690. * This method will be called internally by CAAT when an Actor is expired, and at the
  5691. * same time, is flagged as discardable.
  5692. * It notifies the Actor life cycle listeners about the destruction event.
  5693. *
  5694. * @param time an integer indicating the time at wich the Actor has been destroyed.
  5695. *
  5696. * @private
  5697. *
  5698. */
  5699. destroy : function(time) {
  5700. if ( this.parent ) {
  5701. this.parent.removeChild(this);
  5702. }
  5703. this.fireEvent('destroyed',time);
  5704. },
  5705. /**
  5706. * Transform a point or array of points in model space to view space.
  5707. *
  5708. * @param point {CAAT.Point|Array} an object of the form {x : float, y: float}
  5709. *
  5710. * @return the source transformed elements.
  5711. *
  5712. * @private
  5713. *
  5714. */
  5715. modelToView : function(point) {
  5716. if ( this.dirty ) {
  5717. this.setModelViewMatrix();
  5718. }
  5719. var tm= this.worldModelViewMatrix.matrix;
  5720. if ( point instanceof Array ) {
  5721. for( var i=0; i<point.length; i++ ) {
  5722. //this.worldModelViewMatrix.transformCoord(point[i]);
  5723. var pt= point[i];
  5724. var x= pt.x;
  5725. var y= pt.y;
  5726. pt.x= x*tm[0] + y*tm[1] + tm[2];
  5727. pt.y= x*tm[3] + y*tm[4] + tm[5];
  5728. }
  5729. }
  5730. else {
  5731. // this.worldModelViewMatrix.transformCoord(point);
  5732. var x= point.x;
  5733. var y= point.y;
  5734. point.x= x*tm[0] + y*tm[1] + tm[2];
  5735. point.y= x*tm[3] + y*tm[4] + tm[5];
  5736. }
  5737. return point;
  5738. },
  5739. /**
  5740. * Transform a local coordinate point on this Actor's coordinate system into
  5741. * another point in otherActor's coordinate system.
  5742. * @param point {CAAT.Point}
  5743. * @param otherActor {CAAT.Actor}
  5744. */
  5745. modelToModel : function( point, otherActor ) {
  5746. if ( this.dirty ) {
  5747. this.setModelViewMatrix();
  5748. }
  5749. return otherActor.viewToModel( this.modelToView( point ) );
  5750. },
  5751. /**
  5752. * Transform a point from model to view space.
  5753. * <p>
  5754. * WARNING: every call to this method calculates
  5755. * actor's world model view matrix.
  5756. *
  5757. * @param point {CAAT.Point} a point in screen space to be transformed to model space.
  5758. *
  5759. * @return the source point object
  5760. *
  5761. *
  5762. */
  5763. viewToModel : function(point) {
  5764. if ( this.dirty ) {
  5765. this.setModelViewMatrix();
  5766. }
  5767. this.worldModelViewMatrixI= this.worldModelViewMatrix.getInverse();
  5768. this.worldModelViewMatrixI.transformCoord(point);
  5769. return point;
  5770. },
  5771. /**
  5772. * Private
  5773. * This method does the needed point transformations across an Actor hierarchy to devise
  5774. * whether the parameter point coordinate lies inside the Actor.
  5775. * @param point {CAAT.Point}
  5776. *
  5777. * @return null if the point is not inside the Actor. The Actor otherwise.
  5778. */
  5779. findActorAtPosition : function(point) {
  5780. if ( !this.visible || !this.mouseEnabled || !this.isInAnimationFrame(this.time) ) {
  5781. return null;
  5782. }
  5783. this.modelViewMatrixI= this.modelViewMatrix.getInverse();
  5784. this.modelViewMatrixI.transformCoord(point);
  5785. return this.contains(point.x, point.y) ? this :null;
  5786. },
  5787. /**
  5788. * Enables a default dragging routine for the Actor.
  5789. * This default dragging routine allows to:
  5790. * <li>scale the Actor by pressing shift+drag
  5791. * <li>rotate the Actor by pressing control+drag
  5792. * <li>scale non uniformly by pressing alt+shift+drag
  5793. *
  5794. * @return this
  5795. */
  5796. enableDrag : function() {
  5797. var me= this;
  5798. this.ax= 0;
  5799. this.ay= 0;
  5800. this.mx= 0;
  5801. this.my= 0;
  5802. this.asx=1;
  5803. this.asy=1;
  5804. this.ara=0;
  5805. this.screenx=0;
  5806. this.screeny=0;
  5807. /**
  5808. * Mouse enter handler for default drag behavior.
  5809. * @param mouseEvent {CAAT.MouseEvent}
  5810. *
  5811. * @ignore
  5812. */
  5813. this.mouseEnter= function(mouseEvent) {
  5814. this.__d_ax= -1;
  5815. this.__d_ay= -1;
  5816. this.pointed= true;
  5817. CAAT.setCursor('move');
  5818. };
  5819. /**
  5820. * Mouse exit handler for default drag behavior.
  5821. * @param mouseEvent {CAAT.MouseEvent}
  5822. *
  5823. * @ignore
  5824. */
  5825. this.mouseExit = function(mouseEvent) {
  5826. this.__d_ax = -1;
  5827. this.__d_ay = -1;
  5828. this.pointed = false;
  5829. CAAT.setCursor('default');
  5830. };
  5831. /**
  5832. * Mouse move handler for default drag behavior.
  5833. * @param mouseEvent {CAAT.MouseEvent}
  5834. *
  5835. * @ignore
  5836. */
  5837. this.mouseMove = function(mouseEvent) {
  5838. };
  5839. /**
  5840. * Mouse up handler for default drag behavior.
  5841. * @param mouseEvent {CAAT.MouseEvent}
  5842. *
  5843. * @ignore
  5844. */
  5845. this.mouseUp = function(mouseEvent) {
  5846. this.__d_ax = -1;
  5847. this.__d_ay = -1;
  5848. };
  5849. /**
  5850. * Mouse drag handler for default drag behavior.
  5851. * @param mouseEvent {CAAT.MouseEvent}
  5852. *
  5853. * @ignore
  5854. */
  5855. this.mouseDrag = function(mouseEvent) {
  5856. var pt;
  5857. pt= this.modelToView( new CAAT.Point(mouseEvent.x, mouseEvent.y ) );
  5858. this.parent.viewToModel( pt );
  5859. if (this.__d_ax === -1 || this.__d_ay === -1) {
  5860. this.__d_ax = pt.x;
  5861. this.__d_ay = pt.y;
  5862. this.__d_asx = this.scaleX;
  5863. this.__d_asy = this.scaleY;
  5864. this.__d_ara = this.rotationAngle;
  5865. this.__d_screenx = mouseEvent.screenPoint.x;
  5866. this.__d_screeny = mouseEvent.screenPoint.y;
  5867. }
  5868. if (mouseEvent.isShiftDown()) {
  5869. var scx = (mouseEvent.screenPoint.x - this.__d_screenx) / 100;
  5870. var scy = (mouseEvent.screenPoint.y - this.__d_screeny) / 100;
  5871. if (!mouseEvent.isAltDown()) {
  5872. var sc = Math.max(scx, scy);
  5873. scx = sc;
  5874. scy = sc;
  5875. }
  5876. this.setScale(scx + this.__d_asx, scy + this.__d_asy);
  5877. } else if (mouseEvent.isControlDown()) {
  5878. var vx = mouseEvent.screenPoint.x - this.__d_screenx;
  5879. var vy = mouseEvent.screenPoint.y - this.__d_screeny;
  5880. this.setRotation(-Math.atan2(vx, vy) + this.__d_ara);
  5881. } else {
  5882. this.x += pt.x-this.__d_ax;
  5883. this.y += pt.y-this.__d_ay;
  5884. }
  5885. this.__d_ax= pt.x;
  5886. this.__d_ay= pt.y;
  5887. };
  5888. return this;
  5889. },
  5890. /**
  5891. * Default mouseClick handler.
  5892. * Mouse click events are received after a call to mouseUp method if no dragging was in progress.
  5893. *
  5894. * @param mouseEvent {CAAT.MouseEvent}
  5895. */
  5896. mouseClick : function(mouseEvent) {
  5897. },
  5898. /**
  5899. * Default double click handler
  5900. *
  5901. * @param mouseEvent {CAAT.MouseEvent}
  5902. */
  5903. mouseDblClick : function(mouseEvent) {
  5904. },
  5905. /**
  5906. * Default mouse enter on Actor handler.
  5907. * @param mouseEvent {CAAT.MouseEvent}
  5908. */
  5909. mouseEnter : function(mouseEvent) {
  5910. this.pointed= true;
  5911. },
  5912. /**
  5913. * Default mouse exit on Actor handler.
  5914. *
  5915. * @param mouseEvent {CAAT.MouseEvent}
  5916. */
  5917. mouseExit : function(mouseEvent) {
  5918. this.pointed= false;
  5919. },
  5920. /**
  5921. * Default mouse move inside Actor handler.
  5922. *
  5923. * @param mouseEvent {CAAT.MouseEvent}
  5924. */
  5925. mouseMove : function(mouseEvent) {
  5926. },
  5927. /**
  5928. * default mouse press in Actor handler.
  5929. *
  5930. * @param mouseEvent {CAAT.MouseEvent}
  5931. */
  5932. mouseDown : function(mouseEvent) {
  5933. },
  5934. /**
  5935. * default mouse release in Actor handler.
  5936. *
  5937. * @param mouseEvent {CAAT.MouseEvent}
  5938. */
  5939. mouseUp : function(mouseEvent) {
  5940. },
  5941. mouseOut : function(mouseEvent) {
  5942. },
  5943. mouseOver : function(mouseEvent) {
  5944. },
  5945. /**
  5946. * default Actor mouse drag handler.
  5947. *
  5948. * @param mouseEvent {CAAT.MouseEvent}
  5949. */
  5950. mouseDrag : function(mouseEvent) {
  5951. },
  5952. /**
  5953. * Draw a bounding box with on-screen coordinates regardless of the transformations
  5954. * applied to the Actor.
  5955. *
  5956. * @param director {CAAT.Director} object instance that contains the Scene the Actor is in.
  5957. * @param time {number} integer indicating the Scene time when the bounding box is to be drawn.
  5958. */
  5959. drawScreenBoundingBox : function( director, time ) {
  5960. if ( null!==this.AABB && this.inFrame ) {
  5961. var s= this.AABB;
  5962. var ctx= director.ctx;
  5963. ctx.strokeStyle= CAAT.DEBUGAABBCOLOR;
  5964. ctx.strokeRect( .5+(s.x|0), .5+(s.y|0), s.width|0, s.height|0 );
  5965. if ( CAAT.DEBUGBB ) {
  5966. var vv= this.viewVertices;
  5967. ctx.beginPath( );
  5968. ctx.lineTo( vv[0].x, vv[0].y );
  5969. ctx.lineTo( vv[1].x, vv[1].y );
  5970. ctx.lineTo( vv[2].x, vv[2].y );
  5971. ctx.lineTo( vv[3].x, vv[3].y );
  5972. ctx.closePath();
  5973. ctx.strokeStyle= CAAT.DEBUGBBCOLOR;
  5974. ctx.stroke();
  5975. }
  5976. }
  5977. },
  5978. /**
  5979. * Private
  5980. * This method is called by the Director instance.
  5981. * It applies the list of behaviors the Actor has registered.
  5982. *
  5983. * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
  5984. * @param time an integer indicating the Scene time when the bounding box is to be drawn.
  5985. */
  5986. animate : function(director, time) {
  5987. var i;
  5988. if ( !this.isInAnimationFrame(time) ) {
  5989. this.inFrame= false;
  5990. this.dirty= true;
  5991. return false;
  5992. }
  5993. if ( this.x!==this.oldX || this.y!==this.oldY ) {
  5994. this.dirty= true;
  5995. this.oldX= this.x;
  5996. this.oldY= this.y;
  5997. }
  5998. for( i=0; i<this.behaviorList.length; i++ ) {
  5999. this.behaviorList[i].apply(time,this);
  6000. }
  6001. if ( this.clipPath ) {
  6002. this.clipPath.applyBehaviors(time);
  6003. }
  6004. // transformation stuff.
  6005. this.setModelViewMatrix();
  6006. if ( this.dirty || this.wdirty || this.invalid ) {
  6007. if ( director.dirtyRectsEnabled ) {
  6008. director.addDirtyRect( this.AABB );
  6009. }
  6010. this.setScreenBounds();
  6011. if ( director.dirtyRectsEnabled ) {
  6012. director.addDirtyRect( this.AABB );
  6013. }
  6014. }
  6015. this.dirty= false;
  6016. this.invalid= false;
  6017. this.inFrame= true;
  6018. return this.AABB.intersects( director.AABB );
  6019. //return true;
  6020. },
  6021. /**
  6022. * Set this model view matrix if the actor is Dirty.
  6023. *
  6024. mm[2]+= this.x;
  6025. mm[5]+= this.y;
  6026. if ( this.rotationAngle ) {
  6027. this.modelViewMatrix.multiply( m.setTranslate( this.rotationX, this.rotationY) );
  6028. this.modelViewMatrix.multiply( m.setRotation( this.rotationAngle ) );
  6029. this.modelViewMatrix.multiply( m.setTranslate( -this.rotationX, -this.rotationY) ); c= Math.cos( this.rotationAngle );
  6030. }
  6031. if ( this.scaleX!=1 || this.scaleY!=1 && (this.scaleTX || this.scaleTY )) {
  6032. this.modelViewMatrix.multiply( m.setTranslate( this.scaleTX , this.scaleTY ) );
  6033. this.modelViewMatrix.multiply( m.setScale( this.scaleX, this.scaleY ) );
  6034. this.modelViewMatrix.multiply( m.setTranslate( -this.scaleTX , -this.scaleTY ) );
  6035. }
  6036. *
  6037. * @return this
  6038. */
  6039. setModelViewMatrix : function() {
  6040. var c,s,_m00,_m01,_m10,_m11;
  6041. var mm0, mm1, mm2, mm3, mm4, mm5;
  6042. var mm;
  6043. this.wdirty= false;
  6044. mm= this.modelViewMatrix.matrix;
  6045. if ( this.dirty ) {
  6046. mm0= 1;
  6047. mm1= 0;
  6048. //mm2= mm[2];
  6049. mm3= 0;
  6050. mm4= 1;
  6051. //mm5= mm[5];
  6052. mm2= this.x - this.tAnchorX * this.width ;
  6053. mm5= this.y - this.tAnchorY * this.height;
  6054. if ( this.rotationAngle ) {
  6055. var rx= this.rotationX*this.width;
  6056. var ry= this.rotationY*this.height;
  6057. mm2+= mm0*rx + mm1*ry;
  6058. mm5+= mm3*rx + mm4*ry;
  6059. c= Math.cos( this.rotationAngle );
  6060. s= Math.sin( this.rotationAngle );
  6061. _m00= mm0;
  6062. _m01= mm1;
  6063. _m10= mm3;
  6064. _m11= mm4;
  6065. mm0= _m00*c + _m01*s;
  6066. mm1= -_m00*s + _m01*c;
  6067. mm3= _m10*c + _m11*s;
  6068. mm4= -_m10*s + _m11*c;
  6069. mm2+= -mm0*rx - mm1*ry;
  6070. mm5+= -mm3*rx - mm4*ry;
  6071. }
  6072. if ( this.scaleX!=1 || this.scaleY!=1 ) {
  6073. var sx= this.scaleTX*this.width;
  6074. var sy= this.scaleTY*this.height;
  6075. mm2+= mm0*sx + mm1*sy;
  6076. mm5+= mm3*sx + mm4*sy;
  6077. mm0= mm0*this.scaleX;
  6078. mm1= mm1*this.scaleY;
  6079. mm3= mm3*this.scaleX;
  6080. mm4= mm4*this.scaleY;
  6081. mm2+= -mm0*sx - mm1*sy;
  6082. mm5+= -mm3*sx - mm4*sy;
  6083. }
  6084. mm[0]= mm0;
  6085. mm[1]= mm1;
  6086. mm[2]= mm2;
  6087. mm[3]= mm3;
  6088. mm[4]= mm4;
  6089. mm[5]= mm5;
  6090. }
  6091. if ( this.parent ) {
  6092. this.isAA= this.rotationAngle===0 && this.scaleX===1 && this.scaleY===1 && this.parent.isAA;
  6093. if ( this.dirty || this.parent.wdirty ) {
  6094. this.worldModelViewMatrix.copy( this.parent.worldModelViewMatrix );
  6095. if ( this.isAA ) {
  6096. var mmm= this.worldModelViewMatrix.matrix;
  6097. mmm[2]+= mm[2];
  6098. mmm[5]+= mm[5];
  6099. } else {
  6100. this.worldModelViewMatrix.multiply( this.modelViewMatrix );
  6101. }
  6102. this.wdirty= true;
  6103. }
  6104. } else {
  6105. if ( this.dirty ) {
  6106. this.wdirty= true;
  6107. }
  6108. this.worldModelViewMatrix.identity();
  6109. this.isAA= this.rotationAngle===0 && this.scaleX===1 && this.scaleY===1;
  6110. }
  6111. //if ( (CAAT.DEBUGAABB || glEnabled) && (this.dirty || this.wdirty ) ) {
  6112. // screen bounding boxes will always be calculated.
  6113. /*
  6114. if ( this.dirty || this.wdirty || this.invalid ) {
  6115. if ( director.dirtyRectsEnabled ) {
  6116. director.addDirtyRect( this.AABB );
  6117. }
  6118. this.setScreenBounds();
  6119. if ( director.dirtyRectsEnabled ) {
  6120. director.addDirtyRect( this.AABB );
  6121. }
  6122. }
  6123. this.dirty= false;
  6124. this.invalid= false;
  6125. */
  6126. },
  6127. /**
  6128. * Calculates the 2D bounding box in canvas coordinates of the Actor.
  6129. * This bounding box takes into account the transformations applied hierarchically for
  6130. * each Scene Actor.
  6131. *
  6132. * @private
  6133. *
  6134. */
  6135. setScreenBounds : function() {
  6136. var AABB= this.AABB;
  6137. var vv= this.viewVertices;
  6138. if ( this.isAA ) {
  6139. var m= this.worldModelViewMatrix.matrix;
  6140. var x= m[2];
  6141. var y= m[5];
  6142. var w= this.width;
  6143. var h= this.height;
  6144. AABB.x= x;
  6145. AABB.y= y;
  6146. AABB.x1= x + w;
  6147. AABB.y1= y + h;
  6148. AABB.width= w;
  6149. AABB.height= h;
  6150. if ( CAAT.GLRENDER ) {
  6151. var vvv;
  6152. vvv= vv[0];
  6153. vvv.x=x;
  6154. vvv.y=y;
  6155. vvv= vv[1];
  6156. vvv.x=x+w;
  6157. vvv.y=y;
  6158. vvv= vv[2];
  6159. vvv.x=x+w;
  6160. vvv.y=y+h;
  6161. vvv= vv[3];
  6162. vvv.x=x;
  6163. vvv.y=y+h;
  6164. }
  6165. return this;
  6166. }
  6167. var vvv;
  6168. vvv= vv[0];
  6169. vvv.x=0;
  6170. vvv.y=0;
  6171. vvv= vv[1];
  6172. vvv.x=this.width;
  6173. vvv.y=0;
  6174. vvv= vv[2];
  6175. vvv.x=this.width;
  6176. vvv.y=this.height;
  6177. vvv= vv[3];
  6178. vvv.x=0;
  6179. vvv.y=this.height;
  6180. this.modelToView( this.viewVertices );
  6181. var xmin= Number.MAX_VALUE, xmax=-Number.MAX_VALUE;
  6182. var ymin= Number.MAX_VALUE, ymax=-Number.MAX_VALUE;
  6183. vvv= vv[0];
  6184. if ( vvv.x < xmin ) {
  6185. xmin=vvv.x;
  6186. }
  6187. if ( vvv.x > xmax ) {
  6188. xmax=vvv.x;
  6189. }
  6190. if ( vvv.y < ymin ) {
  6191. ymin=vvv.y;
  6192. }
  6193. if ( vvv.y > ymax ) {
  6194. ymax=vvv.y;
  6195. }
  6196. var vvv= vv[1];
  6197. if ( vvv.x < xmin ) {
  6198. xmin=vvv.x;
  6199. }
  6200. if ( vvv.x > xmax ) {
  6201. xmax=vvv.x;
  6202. }
  6203. if ( vvv.y < ymin ) {
  6204. ymin=vvv.y;
  6205. }
  6206. if ( vvv.y > ymax ) {
  6207. ymax=vvv.y;
  6208. }
  6209. var vvv= vv[2];
  6210. if ( vvv.x < xmin ) {
  6211. xmin=vvv.x;
  6212. }
  6213. if ( vvv.x > xmax ) {
  6214. xmax=vvv.x;
  6215. }
  6216. if ( vvv.y < ymin ) {
  6217. ymin=vvv.y;
  6218. }
  6219. if ( vvv.y > ymax ) {
  6220. ymax=vvv.y;
  6221. }
  6222. var vvv= vv[3];
  6223. if ( vvv.x < xmin ) {
  6224. xmin=vvv.x;
  6225. }
  6226. if ( vvv.x > xmax ) {
  6227. xmax=vvv.x;
  6228. }
  6229. if ( vvv.y < ymin ) {
  6230. ymin=vvv.y;
  6231. }
  6232. if ( vvv.y > ymax ) {
  6233. ymax=vvv.y;
  6234. }
  6235. AABB.x= xmin;
  6236. AABB.y= ymin;
  6237. AABB.x1= xmax;
  6238. AABB.y1= ymax;
  6239. AABB.width= (xmax-xmin);
  6240. AABB.height= (ymax-ymin);
  6241. return this;
  6242. },
  6243. /**
  6244. * @private.
  6245. * This method will be called by the Director to set the whole Actor pre-render process.
  6246. *
  6247. * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
  6248. * @param time an integer indicating the Scene time when the bounding box is to be drawn.
  6249. *
  6250. * @return boolean indicating whether the Actor isInFrameTime
  6251. */
  6252. paintActor : function(director, time) {
  6253. if (!this.visible) {
  6254. return true;
  6255. }
  6256. var ctx= director.ctx;
  6257. this.frameAlpha= this.parent ? this.parent.frameAlpha*this.alpha : 1;
  6258. ctx.globalAlpha= this.frameAlpha;
  6259. director.modelViewMatrix.transformRenderingContextSet( ctx );
  6260. this.worldModelViewMatrix.transformRenderingContext(ctx);
  6261. if ( this.clip ) {
  6262. ctx.beginPath();
  6263. if (!this.clipPath ) {
  6264. ctx.rect(0,0,this.width,this.height);
  6265. } else {
  6266. this.clipPath.applyAsPath(director);
  6267. }
  6268. ctx.clip();
  6269. }
  6270. this.paint(director, time);
  6271. return true;
  6272. },
  6273. /**
  6274. * for js2native
  6275. * @param director
  6276. * @param time
  6277. */
  6278. __paintActor : function(director, time) {
  6279. if (!this.visible) {
  6280. return true;
  6281. }
  6282. var ctx= director.ctx;
  6283. // global opt: set alpha as owns alpha, not take globalAlpha procedure.
  6284. this.frameAlpha= this.alpha;
  6285. var m= this.worldModelViewMatrix.matrix;
  6286. ctx.setTransform( m[0], m[3], m[1], m[4], m[2], m[5], this.frameAlpha );
  6287. this.paint(director, time);
  6288. return true;
  6289. },
  6290. /**
  6291. * Set coordinates and uv values for this actor.
  6292. * This function uses Director's coords and indexCoords values.
  6293. * @param director
  6294. * @param time
  6295. */
  6296. paintActorGL : function(director,time) {
  6297. this.frameAlpha= this.parent.frameAlpha*this.alpha;
  6298. if ( !this.glEnabled || !this.visible) {
  6299. return;
  6300. }
  6301. if ( this.glNeedsFlush(director) ) {
  6302. director.glFlush();
  6303. this.glSetShader(director);
  6304. if ( !this.__uv ) {
  6305. this.__uv= new Float32Array(8);
  6306. }
  6307. if ( !this.__vv ) {
  6308. this.__vv= new Float32Array(12);
  6309. }
  6310. this.setGLCoords( this.__vv, 0 );
  6311. this.setUV( this.__uv, 0 );
  6312. director.glRender(this.__vv, 12, this.__uv);
  6313. return;
  6314. }
  6315. var glCoords= director.coords;
  6316. var glCoordsIndex= director.coordsIndex;
  6317. ////////////////// XYZ
  6318. this.setGLCoords(glCoords, glCoordsIndex);
  6319. director.coordsIndex= glCoordsIndex+12;
  6320. ////////////////// UV
  6321. this.setUV( director.uv, director.uvIndex );
  6322. director.uvIndex+= 8;
  6323. },
  6324. /**
  6325. * TODO: set GLcoords for different image transformations.
  6326. * @param glCoords
  6327. * @param glCoordsIndex
  6328. * @param z
  6329. */
  6330. setGLCoords : function( glCoords, glCoordsIndex ) {
  6331. var vv= this.viewVertices;
  6332. glCoords[glCoordsIndex++]= vv[0].x;
  6333. glCoords[glCoordsIndex++]= vv[0].y;
  6334. glCoords[glCoordsIndex++]= 0;
  6335. glCoords[glCoordsIndex++]= vv[1].x;
  6336. glCoords[glCoordsIndex++]= vv[1].y;
  6337. glCoords[glCoordsIndex++]= 0;
  6338. glCoords[glCoordsIndex++]= vv[2].x;
  6339. glCoords[glCoordsIndex++]= vv[2].y;
  6340. glCoords[glCoordsIndex++]= 0;
  6341. glCoords[glCoordsIndex++]= vv[3].x;
  6342. glCoords[glCoordsIndex++]= vv[3].y;
  6343. glCoords[glCoordsIndex++]= 0;
  6344. },
  6345. /**
  6346. * Set UV for this actor's quad.
  6347. *
  6348. * @param uvBuffer {Float32Array}
  6349. * @param uvIndex {number}
  6350. */
  6351. setUV : function( uvBuffer, uvIndex ) {
  6352. this.backgroundImage.setUV(uvBuffer, uvIndex);
  6353. },
  6354. /**
  6355. * Test for compulsory gl flushing:
  6356. * 1.- opacity has changed.
  6357. * 2.- texture page has changed.
  6358. *
  6359. */
  6360. glNeedsFlush : function(director) {
  6361. if ( this.getTextureGLPage()!==director.currentTexturePage ) {
  6362. return true;
  6363. }
  6364. if ( this.frameAlpha!==director.currentOpacity ) {
  6365. return true;
  6366. }
  6367. return false;
  6368. },
  6369. /**
  6370. * Change texture shader program parameters.
  6371. * @param director
  6372. */
  6373. glSetShader : function(director) {
  6374. var tp= this.getTextureGLPage();
  6375. if ( tp!==director.currentTexturePage ) {
  6376. director.setGLTexturePage(tp);
  6377. }
  6378. if ( this.frameAlpha!==director.currentOpacity ) {
  6379. director.setGLCurrentOpacity(this.frameAlpha);
  6380. }
  6381. },
  6382. /**
  6383. * @private.
  6384. * This method is called after the Director has transformed and drawn a whole frame.
  6385. *
  6386. * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
  6387. * @param time an integer indicating the Scene time when the bounding box is to be drawn.
  6388. * @return this
  6389. *
  6390. * @deprecated
  6391. */
  6392. endAnimate : function(director,time) {
  6393. return this;
  6394. },
  6395. initialize : function(overrides) {
  6396. if (overrides) {
  6397. for (var i in overrides) {
  6398. this[i] = overrides[i];
  6399. }
  6400. }
  6401. return this;
  6402. },
  6403. /**
  6404. * Set this Actor's clipping area.
  6405. * @param enable {boolean} enable clip area.
  6406. * @param clipPath {CAAT.Path=} An optional path to apply clip with. If enabled and clipPath is not set,
  6407. * a rectangle will be used.
  6408. */
  6409. setClip : function( enable, clipPath ) {
  6410. this.clip= enable;
  6411. this.clipPath= clipPath;
  6412. return this;
  6413. },
  6414. /**
  6415. *
  6416. * @param time {Number=}
  6417. * @param stragegy {CAAT.Actor.CACHE_SIMPLE | CAAT.Actor.CACHE_DEEP}
  6418. * @return this
  6419. */
  6420. cacheAsBitmap : function(time, strategy) {
  6421. time= time||0;
  6422. var canvas= document.createElement('canvas');
  6423. canvas.width= this.width;
  6424. canvas.height= this.height;
  6425. var ctx= canvas.getContext('2d');
  6426. var director= {
  6427. ctx: ctx,
  6428. crc: ctx,
  6429. modelViewMatrix: new CAAT.Matrix()
  6430. };
  6431. this.cached= false;
  6432. this.paintActor(director,time);
  6433. this.setBackgroundImage(canvas);
  6434. this.cached= strategy ? strategy : CAAT.Actor.CACHE_SIMPLE;
  6435. return this;
  6436. },
  6437. /**
  6438. * Set this actor behavior as if it were a Button. The actor size will be set as SpriteImage's
  6439. * single size.
  6440. *
  6441. * @param buttonImage {CAAT.SpriteImage} sprite image with button's state images.
  6442. * @param _iNormal {number} button's normal state image index
  6443. * @param _iOver {number} button's mouse over state image index
  6444. * @param _iPress {number} button's pressed state image index
  6445. * @param _iDisabled {number} button's disabled state image index
  6446. * @param fn {function(button{CAAT.Actor})} callback function
  6447. */
  6448. setAsButton : function( buttonImage, iNormal, iOver, iPress, iDisabled, fn ) {
  6449. var me= this;
  6450. this.setBackgroundImage(buttonImage, true);
  6451. this.iNormal= iNormal || 0;
  6452. this.iOver= iOver || iNormal;
  6453. this.iPress= iPress || iNormal;
  6454. this.iDisabled= iDisabled || iNormal;
  6455. this.fnOnClick= fn;
  6456. this.enabled= true;
  6457. this.setSpriteIndex( iNormal );
  6458. /**
  6459. * Enable or disable the button.
  6460. * @param enabled {boolean}
  6461. * @ignore
  6462. */
  6463. this.setEnabled= function( enabled ) {
  6464. this.enabled= enabled;
  6465. this.setSpriteIndex( this.enabled ? this.iNormal : this.iDisabled );
  6466. return this;
  6467. };
  6468. /**
  6469. * This method will be called by CAAT *before* the mouseUp event is fired.
  6470. * @param event {CAAT.MouseEvent}
  6471. * @ignore
  6472. */
  6473. this.actionPerformed= function(event) {
  6474. if ( this.enabled && null!==this.fnOnClick ) {
  6475. this.fnOnClick(this);
  6476. }
  6477. };
  6478. /**
  6479. * Button's mouse enter handler. It makes the button provide visual feedback
  6480. * @param mouseEvent {CAAT.MouseEvent}
  6481. * @ignore
  6482. */
  6483. this.mouseEnter= function(mouseEvent) {
  6484. if ( !this.enabled ) {
  6485. return;
  6486. }
  6487. if ( this.dragging ) {
  6488. this.setSpriteIndex( this.iPress );
  6489. } else {
  6490. this.setSpriteIndex( this.iOver );
  6491. }
  6492. CAAT.setCursor('pointer');
  6493. };
  6494. /**
  6495. * Button's mouse exit handler. Release visual apperance.
  6496. * @param mouseEvent {CAAT.MouseEvent}
  6497. * @ignore
  6498. */
  6499. this.mouseExit= function(mouseEvent) {
  6500. if ( !this.enabled ) {
  6501. return;
  6502. }
  6503. this.setSpriteIndex( this.iNormal );
  6504. CAAT.setCursor('default');
  6505. };
  6506. /**
  6507. * Button's mouse down handler.
  6508. * @param mouseEvent {CAAT.MouseEvent}
  6509. * @ignore
  6510. */
  6511. this.mouseDown= function(mouseEvent) {
  6512. if ( !this.enabled ) {
  6513. return;
  6514. }
  6515. this.setSpriteIndex( this.iPress );
  6516. };
  6517. /**
  6518. * Button's mouse up handler.
  6519. * @param mouseEvent {CAAT.MouseEvent}
  6520. * @ignore
  6521. */
  6522. this.mouseUp= function(mouseEvent) {
  6523. if ( !this.enabled ) {
  6524. return;
  6525. }
  6526. this.setSpriteIndex( this.iNormal );
  6527. this.dragging= false;
  6528. };
  6529. /**
  6530. * Button's mouse click handler. Do nothing by default. This event handler will be
  6531. * called ONLY if it has not been drag on the button.
  6532. * @param mouseEvent {CAAT.MouseEvent}
  6533. * @ignore
  6534. */
  6535. this.mouseClick= function(mouseEvent) {
  6536. };
  6537. /**
  6538. * Button's mouse drag handler.
  6539. * @param mouseEvent {CAAT.MouseEvent}
  6540. * @ignore
  6541. */
  6542. this.mouseDrag= function(mouseEvent) {
  6543. if ( !this.enabled ) {
  6544. return;
  6545. }
  6546. this.dragging= true;
  6547. };
  6548. this.setButtonImageIndex= function(_normal, _over, _press, _disabled ) {
  6549. this.iNormal= _normal;
  6550. this.iOver= _over;
  6551. this.iPress= _press;
  6552. this.iDisabled= _disabled;
  6553. this.setSpriteIndex( this.iNormal );
  6554. return this;
  6555. };
  6556. return this;
  6557. }
  6558. };
  6559. /*
  6560. if ( CAAT.NO_PERF ) {
  6561. CAAT.Actor.prototype.paintActor= CAAT.Actor.prototype.__paintActor;
  6562. }
  6563. */
  6564. })();
  6565. (function() {
  6566. var __CD= 2;
  6567. /**
  6568. * This class is a general container of CAAT.Actor instances. It extends the concept of an Actor
  6569. * from a single entity on screen to a set of entities with a parent/children relationship among
  6570. * them.
  6571. * <p>
  6572. * This mainly overrides default behavior of a single entity and exposes methods to manage its children
  6573. * collection.
  6574. *
  6575. * @constructor
  6576. * @extends CAAT.Actor
  6577. */
  6578. CAAT.ActorContainer= function(hint) {
  6579. CAAT.ActorContainer.superclass.constructor.call(this);
  6580. this.childrenList= [];
  6581. this.pendingChildrenList= [];
  6582. if ( typeof hint!=='undefined' ) {
  6583. this.addHint= hint;
  6584. this.boundingBox= new CAAT.Rectangle();
  6585. }
  6586. return this;
  6587. };
  6588. CAAT.ActorContainer.AddHint= {
  6589. CONFORM : 1
  6590. };
  6591. CAAT.ActorContainer.prototype= {
  6592. childrenList : null, // the list of children contained.
  6593. activeChildren : null,
  6594. pendingChildrenList : null,
  6595. addHint : 0,
  6596. boundingBox : null,
  6597. runion : new CAAT.Rectangle(), // Watch out. one for every container.
  6598. /**
  6599. * Draws this ActorContainer and all of its children screen bounding box.
  6600. *
  6601. * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
  6602. * @param time an integer indicating the Scene time when the bounding box is to be drawn.
  6603. */
  6604. drawScreenBoundingBox : function( director, time ) {
  6605. if (!this.inFrame) {
  6606. return;
  6607. }
  6608. var cl= this.childrenList;
  6609. for( var i=0; i<cl.length; i++ ) {
  6610. cl[i].drawScreenBoundingBox(director,time);
  6611. }
  6612. CAAT.ActorContainer.superclass.drawScreenBoundingBox.call(this,director,time);
  6613. },
  6614. /**
  6615. * Removes all children from this ActorContainer.
  6616. *
  6617. * @return this
  6618. */
  6619. emptyChildren : function() {
  6620. this.childrenList= [];
  6621. return this;
  6622. },
  6623. /**
  6624. * Private
  6625. * Paints this container and every contained children.
  6626. *
  6627. * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
  6628. * @param time an integer indicating the Scene time when the bounding box is to be drawn.
  6629. */
  6630. paintActor : function(director, time ) {
  6631. if (!this.visible) {
  6632. return true;
  6633. }
  6634. var ctx= director.ctx;
  6635. ctx.save();
  6636. CAAT.ActorContainer.superclass.paintActor.call(this,director,time);
  6637. if ( this.cached===__CD ) {
  6638. return;
  6639. }
  6640. if ( !this.isGlobalAlpha ) {
  6641. this.frameAlpha= this.parent ? this.parent.frameAlpha : 1;
  6642. }
  6643. for( var actor= this.activeChildren; actor; actor=actor.__next ) {
  6644. if ( actor.visible ) {
  6645. ctx.save();
  6646. actor.paintActor(director,time);
  6647. ctx.restore();
  6648. }
  6649. }
  6650. ctx.restore();
  6651. return true;
  6652. },
  6653. __paintActor : function(director, time ) {
  6654. if (!this.visible) {
  6655. return true;
  6656. }
  6657. var ctx= director.ctx;
  6658. this.frameAlpha= this.parent ? this.parent.frameAlpha*this.alpha : 1;
  6659. var m= this.worldModelViewMatrix.matrix;
  6660. ctx.setTransform( m[0], m[3], m[1], m[4], m[2], m[5], this.frameAlpha );
  6661. this.paint(director, time);
  6662. if ( !this.isGlobalAlpha ) {
  6663. this.frameAlpha= this.parent ? this.parent.frameAlpha : 1;
  6664. }
  6665. for( var actor= this.activeChildren; actor; actor=actor.__next ) {
  6666. actor.paintActor(director,time);
  6667. }
  6668. return true;
  6669. },
  6670. paintActorGL : function(director,time) {
  6671. var i, c;
  6672. if (!this.visible) {
  6673. return true;
  6674. }
  6675. CAAT.ActorContainer.superclass.paintActorGL.call(this,director,time);
  6676. if ( !this.isGlobalAlpha ) {
  6677. this.frameAlpha= this.parent.frameAlpha;
  6678. }
  6679. for( c= this.activeChildren; c; c=c.__next ) {
  6680. c.paintActorGL(director,time);
  6681. }
  6682. },
  6683. /**
  6684. * Private.
  6685. * Performs the animate method for this ActorContainer and every contained Actor.
  6686. *
  6687. * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
  6688. * @param time an integer indicating the Scene time when the bounding box is to be drawn.
  6689. *
  6690. * @return {boolean} is this actor in active children list ??
  6691. */
  6692. animate : function(director,time) {
  6693. this.activeChildren= null;
  6694. var last= null;
  6695. if (false===CAAT.ActorContainer.superclass.animate.call(this,director,time)) {
  6696. return false;
  6697. }
  6698. if ( this.cached===__CD ) {
  6699. return true;
  6700. }
  6701. var i,l;
  6702. /**
  6703. * Incluir los actores pendientes.
  6704. * El momento es ahora, antes de procesar ninguno del contenedor.
  6705. */
  6706. var pcl= this.pendingChildrenList;
  6707. for( i=0; i<pcl.length; i++ ) {
  6708. var child= pcl[i];
  6709. this.addChild(child);
  6710. }
  6711. this.pendingChildrenList= [];
  6712. var markDelete= [];
  6713. var cl= this.childrenList;
  6714. this.size_active= 1;
  6715. this.size_total= 1;
  6716. for( i=0; i<cl.length; i++ ) {
  6717. var actor= cl[i];
  6718. actor.time= time;
  6719. this.size_total+= actor.size_total;
  6720. if ( actor.animate(director, time) ) {
  6721. if ( !this.activeChildren ) {
  6722. this.activeChildren= actor;
  6723. actor.__next= null;
  6724. last= actor;
  6725. } else {
  6726. actor.__next= null;
  6727. last.__next= actor;
  6728. last= actor;
  6729. }
  6730. this.size_active+= actor.size_active;
  6731. } else {
  6732. if ( actor.expired && actor.discardable ) {
  6733. markDelete.push(actor);
  6734. }
  6735. }
  6736. }
  6737. for( i=0, l=markDelete.length; i<l; i++ ) {
  6738. var md= markDelete[i];
  6739. md.destroy(time);
  6740. if ( director.dirtyRectsEnabled ) {
  6741. director.addDirtyRect( md.AABB );
  6742. }
  6743. }
  6744. return true;
  6745. },
  6746. /**
  6747. * Removes Actors from this ActorContainer which are expired and flagged as Discardable.
  6748. *
  6749. * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
  6750. * @param time an integer indicating the Scene time when the bounding box is to be drawn.
  6751. *
  6752. * @deprecated
  6753. */
  6754. endAnimate : function(director,time) {
  6755. },
  6756. /**
  6757. * Adds an Actor to this Container.
  6758. * The Actor will be added ON METHOD CALL, despite the rendering pipeline stage being executed at
  6759. * the time of method call.
  6760. *
  6761. * This method is only used by CAAT.Director's transitionScene.
  6762. *
  6763. * @param child a CAAT.Actor instance.
  6764. * @return this.
  6765. */
  6766. addChildImmediately : function(child) {
  6767. return this.addChild(child);
  6768. },
  6769. /**
  6770. * Adds an Actor to this ActorContainer.
  6771. * The Actor will be added to the container AFTER frame animation, and not on method call time.
  6772. * Except the Director and in orther to avoid visual artifacts, the developer SHOULD NOT call this
  6773. * method directly.
  6774. *
  6775. * If the container has addingHint as CAAT.ActorContainer.AddHint.CONFORM, new continer size will be
  6776. * calculated by summing up the union of every client actor bounding box.
  6777. * This method will not take into acount actor's affine transformations, so the bounding box will be
  6778. * AABB.
  6779. *
  6780. * @param child a CAAT.Actor object instance.
  6781. * @return this
  6782. */
  6783. addChild : function(child) {
  6784. if ( child.parent!=null ) {
  6785. throw('adding to a container an element with parent.');
  6786. }
  6787. child.parent= this;
  6788. this.childrenList.push(child);
  6789. child.dirty= true;
  6790. /**
  6791. * if Conforming size, recalc new bountainer size.
  6792. */
  6793. if ( this.addHint===CAAT.ActorContainer.AddHint.CONFORM ) {
  6794. this.recalcSize();
  6795. }
  6796. return this;
  6797. },
  6798. /**
  6799. * Recalc this container size by computing the union of every children bounding box.
  6800. */
  6801. recalcSize : function() {
  6802. var bb= this.boundingBox;
  6803. bb.setEmpty();
  6804. var cl= this.childrenList;
  6805. var ac;
  6806. for( var i=0; i<cl.length; i++ ) {
  6807. ac= cl[i];
  6808. this.runion.setBounds(
  6809. ac.x<0 ? 0 : ac.x,
  6810. ac.y<0 ? 0 : ac.y,
  6811. ac.width,
  6812. ac.height );
  6813. bb.unionRectangle( this.runion );
  6814. }
  6815. this.setSize( bb.x1, bb.y1 );
  6816. return this;
  6817. },
  6818. /**
  6819. * Add a child element and make it active in the next frame.
  6820. * @param child {CAAT.Actor}
  6821. */
  6822. addChildDelayed : function(child) {
  6823. this.pendingChildrenList.push(child);
  6824. return this;
  6825. },
  6826. /**
  6827. * Adds an Actor to this ActorContainer.
  6828. *
  6829. * @param child a CAAT.Actor object instance.
  6830. *
  6831. * @return this
  6832. */
  6833. addChildAt : function(child, index) {
  6834. if( index <= 0 ) {
  6835. child.parent= this;
  6836. child.dirty= true;
  6837. //this.childrenList.unshift(child); // unshift unsupported on IE
  6838. this.childrenList.splice( 0, 0, child );
  6839. return this;
  6840. } else {
  6841. if ( index>=this.childrenList.length ) {
  6842. index= this.childrenList.length;
  6843. }
  6844. }
  6845. child.parent= this;
  6846. child.dirty= true;
  6847. this.childrenList.splice(index, 0, child);
  6848. return this;
  6849. },
  6850. /**
  6851. * Find the first actor with the supplied ID.
  6852. * This method is not recommended to be used since executes a linear search.
  6853. * @param id
  6854. */
  6855. findActorById : function(id) {
  6856. var cl= this.childrenList;
  6857. for( var i=0, l=cl.length; i<l; i++ ) {
  6858. if ( cl[i].id===id ) {
  6859. return cl[i];
  6860. }
  6861. }
  6862. return null;
  6863. },
  6864. /**
  6865. * Private
  6866. * Gets a contained Actor z-index on this ActorContainer.
  6867. *
  6868. * @param child a CAAT.Actor object instance.
  6869. *
  6870. * @return an integer indicating the Actor's z-order.
  6871. */
  6872. findChild : function(child) {
  6873. var cl= this.childrenList;
  6874. var i=0;
  6875. var len = cl.length;
  6876. for( i=0; i<len; i++ ) {
  6877. if ( cl[i]===child ) {
  6878. return i;
  6879. }
  6880. }
  6881. return -1;
  6882. },
  6883. /**
  6884. * Removed an Actor form this ActorContainer.
  6885. * If the Actor is not contained into this Container, nothing happends.
  6886. *
  6887. * @param child a CAAT.Actor object instance.
  6888. *
  6889. * @return this
  6890. */
  6891. removeChild : function(child) {
  6892. var pos= this.findChild(child);
  6893. var cl= this.childrenList;
  6894. if ( -1!==pos ) {
  6895. cl[pos].setParent(null);
  6896. cl.splice(pos,1);
  6897. }
  6898. return this;
  6899. },
  6900. removeFirstChild : function() {
  6901. var first= this.childrenList.shift();
  6902. first.parent= null;
  6903. return first;
  6904. },
  6905. /**
  6906. * @private
  6907. *
  6908. * Gets the Actor inside this ActorContainer at a given Screen coordinate.
  6909. *
  6910. * @param point an object of the form { x: float, y: float }
  6911. *
  6912. * @return the Actor contained inside this ActorContainer if found, or the ActorContainer itself.
  6913. */
  6914. findActorAtPosition : function(point) {
  6915. if( null===CAAT.ActorContainer.superclass.findActorAtPosition.call(this,point) ) {
  6916. return null;
  6917. }
  6918. // z-order
  6919. var cl= this.childrenList;
  6920. for( var i=cl.length-1; i>=0; i-- ) {
  6921. var child= this.childrenList[i];
  6922. var np= new CAAT.Point( point.x, point.y, 0 );
  6923. var contained= child.findActorAtPosition( np );
  6924. if ( null!==contained ) {
  6925. return contained;
  6926. }
  6927. }
  6928. return this;
  6929. },
  6930. /**
  6931. * Destroys this ActorContainer.
  6932. * The process falls down recursively for each contained Actor into this ActorContainer.
  6933. *
  6934. * @return this
  6935. */
  6936. destroy : function() {
  6937. var cl= this.childrenList;
  6938. for( var i=cl.length-1; i>=0; i-- ) {
  6939. cl[i].destroy();
  6940. }
  6941. CAAT.ActorContainer.superclass.destroy.call(this);
  6942. return this;
  6943. },
  6944. /**
  6945. * Get number of Actors into this container.
  6946. * @return integer indicating the number of children.
  6947. */
  6948. getNumChildren : function() {
  6949. return this.childrenList.length;
  6950. },
  6951. getNumActiveChildren : function() {
  6952. return this.activeChildren.length;
  6953. },
  6954. /**
  6955. * Returns the Actor at the iPosition(th) position.
  6956. * @param iPosition an integer indicating the position array.
  6957. * @return the CAAT.Actor object at position.
  6958. */
  6959. getChildAt : function( iPosition ) {
  6960. return this.childrenList[ iPosition ];
  6961. },
  6962. /**
  6963. * Changes an actor's ZOrder.
  6964. * @param actor the actor to change ZOrder for
  6965. * @param index an integer indicating the new ZOrder. a value greater than children list size means to be the
  6966. * last ZOrder Actor.
  6967. */
  6968. setZOrder : function( actor, index ) {
  6969. var actorPos= this.findChild(actor);
  6970. // the actor is present
  6971. if ( -1!==actorPos ) {
  6972. var cl= this.childrenList;
  6973. // trivial reject.
  6974. if ( index===actorPos ) {
  6975. return;
  6976. }
  6977. if ( index>=cl.length ) {
  6978. cl.splice(actorPos,1);
  6979. cl.push(actor);
  6980. } else {
  6981. var nActor= cl.splice(actorPos,1);
  6982. if ( index<0 ) {
  6983. index=0;
  6984. } else if ( index>cl.length ) {
  6985. index= cl.length;
  6986. }
  6987. cl.splice( index, 0, nActor[0] );
  6988. }
  6989. }
  6990. }
  6991. };
  6992. /*
  6993. if ( CAAT.NO_PERF ) {
  6994. CAAT.ActorContainer.prototype.paintActor= CAAT.ActorContainer.prototype.__paintActor;
  6995. }
  6996. */
  6997. extend( CAAT.ActorContainer, CAAT.Actor, null);
  6998. })();
  6999. (function() {
  7000. /**
  7001. * TextActor draws text on screen. The text can be drawn directly on screen or make if follow a
  7002. * path defined by an instance of <code>CAAT.Path</code>.
  7003. *
  7004. * @constructor
  7005. * @extends CAAT.ActorContainer
  7006. *
  7007. */
  7008. CAAT.TextActor = function() {
  7009. CAAT.TextActor.superclass.constructor.call(this);
  7010. this.font= "10px sans-serif";
  7011. this.textAlign= "left";
  7012. this.textBaseline= "top";
  7013. this.outlineColor= "black";
  7014. this.clip= false;
  7015. return this;
  7016. };
  7017. CAAT.TextActor.TRAVERSE_PATH_FORWARD= 1;
  7018. CAAT.TextActor.TRAVERSE_PATH_BACKWARD= -1;
  7019. CAAT.TextActor.prototype= {
  7020. font: null, // a valid canvas rendering context font description. Default font
  7021. // will be "10px sans-serif".
  7022. textAlign: null, // a valid canvas rendering context textAlign string. Any of:
  7023. // start, end, left, right, center.
  7024. // defaults to "left".
  7025. textBaseline: null, // a valid canvas rendering context textBaseLine string. Any of:
  7026. // top, hanging, middle, alphabetic, ideographic, bottom.
  7027. // defaults to "top".
  7028. fill: true, // a boolean indicating whether the text should be filled.
  7029. textFillStyle : '#eee', // text fill color
  7030. text: null, // a string with the text to draw.
  7031. textWidth: 0, // an integer indicating text width in pixels.
  7032. textHeight: 0, // an integer indicating text height in pixels.
  7033. outline: false, // a boolean indicating whether the text should be outlined.
  7034. // not all browsers support it.
  7035. outlineColor: null, // a valid color description string.
  7036. path: null, // a CAAT.Path which will be traversed by the text. [Optional]
  7037. pathInterpolator: null, // a CAAT.Interpolator to apply to the path traversing.
  7038. pathDuration: 10000, // an integer indicating the time to be taken to traverse the path. ms.
  7039. sign: 1, // traverse the path forward or backwards.
  7040. /**
  7041. * Set the text to be filled. The default Filling style will be set by calling setFillStyle method.
  7042. * Default value is true.
  7043. * @param fill {boolean} a boolean indicating whether the text will be filled.
  7044. * @return this;
  7045. */
  7046. setFill : function( fill ) {
  7047. this.fill= fill;
  7048. return this;
  7049. },
  7050. setTextFillStyle : function( style ) {
  7051. this.textFillStyle= style;
  7052. return this;
  7053. },
  7054. /**
  7055. * Sets whether the text will be outlined.
  7056. * @param outline {boolean} a boolean indicating whether the text will be outlined.
  7057. * @return this;
  7058. */
  7059. setOutline : function( outline ) {
  7060. this.outline= outline;
  7061. return this;
  7062. },
  7063. setPathTraverseDirection : function(direction) {
  7064. this.sign= direction;
  7065. return this;
  7066. },
  7067. /**
  7068. * Defines text's outline color.
  7069. *
  7070. * @param color {string} sets a valid canvas context color.
  7071. * @return this.
  7072. */
  7073. setOutlineColor : function( color ) {
  7074. this.outlineColor= color;
  7075. return this;
  7076. },
  7077. /**
  7078. * Set the text to be shown by the actor.
  7079. * @param sText a string with the text to be shwon.
  7080. * @return this
  7081. */
  7082. setText : function( sText ) {
  7083. this.text= sText;
  7084. if ( null===this.text || this.text==="" ) {
  7085. this.width= this.height= 0;
  7086. }
  7087. this.calcTextSize( CAAT.director[0] );
  7088. return this;
  7089. },
  7090. setTextAlign : function( align ) {
  7091. this.textAlign= align;
  7092. return this;
  7093. },
  7094. /**
  7095. * Sets text alignment
  7096. * @param align
  7097. * @deprecated use setTextAlign
  7098. */
  7099. setAlign : function( align ) {
  7100. return this.setTextAlign(align);
  7101. },
  7102. /**
  7103. * Set text baseline.
  7104. * @param baseline
  7105. */
  7106. setTextBaseline : function( baseline ) {
  7107. this.textBaseline= baseline;
  7108. return this;
  7109. },
  7110. setBaseline : function( baseline ) {
  7111. return this.setTextBaseline(baseline);
  7112. },
  7113. /**
  7114. * Sets the font to be applied for the text.
  7115. * @param font a string with a valid canvas rendering context font description.
  7116. * @return this
  7117. */
  7118. setFont : function(font) {
  7119. if ( !font ) {
  7120. font= "10px sans-serif";
  7121. }
  7122. this.font= font;
  7123. this.calcTextSize( CAAT.director[0] );
  7124. return this;
  7125. },
  7126. /**
  7127. * Calculates the text dimension in pixels and stores the values in textWidth and textHeight
  7128. * attributes.
  7129. * If Actor's width and height were not set, the Actor's dimension will be set to these values.
  7130. * @param director a CAAT.Director instance.
  7131. * @return this
  7132. */
  7133. calcTextSize : function(director) {
  7134. if ( typeof this.text==='undefined' || null===this.text || ""===this.text ) {
  7135. this.textWidth= 0;
  7136. this.textHeight= 0;
  7137. return this;
  7138. }
  7139. if ( director.glEnabled ) {
  7140. return this;
  7141. }
  7142. if ( this.font instanceof CAAT.SpriteImage ) {
  7143. this.textWidth= this.font.stringWidth( this.text );
  7144. this.textHeight=this.font.stringHeight();
  7145. this.width= this.textWidth;
  7146. this.height= this.textHeight;
  7147. return this;
  7148. }
  7149. var ctx= director.ctx;
  7150. ctx.save();
  7151. ctx.font= this.font;
  7152. this.textWidth= ctx.measureText( this.text ).width;
  7153. if (this.width===0) {
  7154. this.width= this.textWidth;
  7155. }
  7156. try {
  7157. var pos= this.font.indexOf("px");
  7158. var s = this.font.substring(0, pos );
  7159. this.textHeight= parseInt(s,10);
  7160. // needed to calculate the descent.
  7161. // no context.getDescent(font) WTF !!!
  7162. this.textHeight+= (this.textHeight/4)>>0;
  7163. } catch(e) {
  7164. this.textHeight=20; // default height;
  7165. }
  7166. if ( this.height===0 ) {
  7167. this.height= this.textHeight;
  7168. }
  7169. ctx.restore();
  7170. return this;
  7171. },
  7172. /**
  7173. * Custom paint method for TextActor instances.
  7174. * If the path attribute is set, the text will be drawn traversing the path.
  7175. *
  7176. * @param director a valid CAAT.Director instance.
  7177. * @param time an integer with the Scene time the Actor is being drawn.
  7178. */
  7179. paint : function(director, time) {
  7180. CAAT.TextActor.superclass.paint.call(this, director, time );
  7181. if ( this.cached ) {
  7182. // cacheAsBitmap sets this actor's background image as a representation of itself.
  7183. // So if after drawing the background it was cached, we're done.
  7184. return;
  7185. }
  7186. if ( null===this.text) {
  7187. return;
  7188. }
  7189. if ( this.textWidth===0 || this.textHeight===0 ) {
  7190. this.calcTextSize(director);
  7191. }
  7192. var ctx= director.ctx;
  7193. if ( this.font instanceof CAAT.SpriteImage ) {
  7194. return this.drawSpriteText(director,time);
  7195. }
  7196. if( null!==this.font ) {
  7197. ctx.font= this.font;
  7198. }
  7199. if ( null!==this.textAlign ) {
  7200. ctx.textAlign= this.textAlign;
  7201. }
  7202. if ( null!==this.textBaseline ) {
  7203. ctx.textBaseline= this.textBaseline;
  7204. }
  7205. if ( this.fill && null!==this.textFillStyle ) {
  7206. ctx.fillStyle= this.textFillStyle;
  7207. }
  7208. if ( this.outline && null!==this.outlineColor ) {
  7209. ctx.strokeStyle= this.outlineColor;
  7210. }
  7211. if (null===this.path) {
  7212. var tx=0;
  7213. if ( this.textAlign==='center') {
  7214. tx= (this.width/2)|0;
  7215. } else if ( this.textAlign==='right' ) {
  7216. tx= this.width;
  7217. }
  7218. if ( this.fill ) {
  7219. ctx.fillText( this.text, tx, 0 );
  7220. if ( this.outline ) {
  7221. // firefox necesita beginPath, si no, dibujara ademas el cuadrado del
  7222. // contenedor de los textos.
  7223. // if ( null!==this.outlineColor ) {
  7224. // ctx.strokeStyle= this.outlineColor;
  7225. // }
  7226. ctx.beginPath();
  7227. ctx.strokeText( this.text, tx, 0 );
  7228. }
  7229. } else {
  7230. if ( null!==this.outlineColor ) {
  7231. ctx.strokeStyle= this.outlineColor;
  7232. }
  7233. ctx.beginPath();
  7234. ctx.strokeText( this.text, tx, 0 );
  7235. }
  7236. }
  7237. else {
  7238. this.drawOnPath(director,time);
  7239. }
  7240. },
  7241. /**
  7242. * Private.
  7243. * Draw the text traversing a path.
  7244. * @param director a valid CAAT.Director instance.
  7245. * @param time an integer with the Scene time the Actor is being drawn.
  7246. */
  7247. drawOnPath : function(director, time) {
  7248. var ctx= director.ctx;
  7249. var textWidth=this.sign * this.pathInterpolator.getPosition(
  7250. (time%this.pathDuration)/this.pathDuration ).y * this.path.getLength() ;
  7251. var p0= new CAAT.Point(0,0,0);
  7252. var p1= new CAAT.Point(0,0,0);
  7253. for( var i=0; i<this.text.length; i++ ) {
  7254. var caracter= this.text[i].toString();
  7255. var charWidth= ctx.measureText( caracter ).width;
  7256. // guonjien: remove "+charWidth/2" since it destroys the kerning. and he's right!!!. thanks.
  7257. var currentCurveLength= textWidth;
  7258. p0= this.path.getPositionFromLength(currentCurveLength).clone();
  7259. p1= this.path.getPositionFromLength(currentCurveLength-0.1).clone();
  7260. var angle= Math.atan2( p0.y-p1.y, p0.x-p1.x );
  7261. ctx.save();
  7262. ctx.translate( p0.x>>0, p0.y>>0 );
  7263. ctx.rotate( angle );
  7264. if ( this.fill ) {
  7265. ctx.fillText(caracter,0,0);
  7266. }
  7267. if ( this.outline ) {
  7268. // ctx.strokeStyle= this.outlineColor;
  7269. ctx.strokeText(caracter,0,0);
  7270. }
  7271. ctx.restore();
  7272. textWidth+= charWidth;
  7273. }
  7274. },
  7275. /**
  7276. * Private.
  7277. * Draw the text using a sprited font instead of a canvas font.
  7278. * @param director a valid CAAT.Director instance.
  7279. * @param time an integer with the Scene time the Actor is being drawn.
  7280. */
  7281. drawSpriteText: function(director, time) {
  7282. if (null===this.path) {
  7283. this.font.drawString( director.ctx, this.text, 0, 0);
  7284. } else {
  7285. this.drawSpriteTextOnPath(director, time);
  7286. }
  7287. },
  7288. /**
  7289. * Private.
  7290. * Draw the text traversing a path using a sprited font.
  7291. * @param director a valid CAAT.Director instance.
  7292. * @param time an integer with the Scene time the Actor is being drawn.
  7293. */
  7294. drawSpriteTextOnPath: function(director, time) {
  7295. var context= director.ctx;
  7296. var textWidth=this.sign * this.pathInterpolator.getPosition(
  7297. (time%this.pathDuration)/this.pathDuration ).y * this.path.getLength() ;
  7298. var p0= new CAAT.Point(0,0,0);
  7299. var p1= new CAAT.Point(0,0,0);
  7300. for( var i=0; i<this.text.length; i++ ) {
  7301. var character= this.text[i].toString();
  7302. var charWidth= this.font.stringWidth(character); //context.measureText( caracter ).width;
  7303. var pathLength= this.path.getLength();
  7304. var currentCurveLength= charWidth/2 + textWidth;
  7305. p0= this.path.getPositionFromLength(currentCurveLength).clone();
  7306. p1= this.path.getPositionFromLength(currentCurveLength-0.1).clone();
  7307. var angle= Math.atan2( p0.y-p1.y, p0.x-p1.x );
  7308. context.save();
  7309. context.translate( p0.x|0, p0.y|0 );
  7310. context.rotate( angle );
  7311. var y = this.textBaseline === "bottom" ? 0 - this.font.height : 0;
  7312. this.font.drawString(context,character, 0, y);
  7313. context.restore();
  7314. textWidth+= charWidth;
  7315. }
  7316. },
  7317. /**
  7318. * Set the path, interpolator and duration to draw the text on.
  7319. * @param path a valid CAAT.Path instance.
  7320. * @param interpolator a CAAT.Interpolator object. If not set, a Linear Interpolator will be used.
  7321. * @param duration an integer indicating the time to take to traverse the path. Optional. 10000 ms
  7322. * by default.
  7323. */
  7324. setPath : function( path, interpolator, duration ) {
  7325. this.path= path;
  7326. this.pathInterpolator= interpolator || new CAAT.Interpolator().createLinearInterpolator();
  7327. this.pathDuration= duration || 10000;
  7328. /*
  7329. parent could not be set by the time this method is called.
  7330. so the actors bounds set is removed.
  7331. the developer must ensure to call setbounds properly on actor.
  7332. */
  7333. this.mouseEnabled= false;
  7334. return this;
  7335. }
  7336. };
  7337. extend( CAAT.TextActor, CAAT.Actor, null);
  7338. })();
  7339. (function() {
  7340. /**
  7341. * This Actor draws common shapes, concretely Circles and rectangles.
  7342. *
  7343. * @constructor
  7344. * @extends CAAT.ActorContainer
  7345. */
  7346. CAAT.ShapeActor = function() {
  7347. CAAT.ShapeActor.superclass.constructor.call(this);
  7348. this.compositeOp= 'source-over';
  7349. /**
  7350. * Thanks Svend Dutz and Thomas Karolski for noticing this call was not performed by default,
  7351. * so if no explicit call to setShape was made, nothing would be drawn.
  7352. */
  7353. this.setShape( this.SHAPE_CIRCLE );
  7354. return this;
  7355. };
  7356. CAAT.ShapeActor.prototype= {
  7357. shape: 0, // shape type. One of the constant SHAPE_* values
  7358. compositeOp: null, // a valid canvas rendering context string describing compositeOps.
  7359. lineWidth: 1,
  7360. lineCap: null,
  7361. lineJoin: null,
  7362. miterLimit: null,
  7363. SHAPE_CIRCLE: 0, // Constants to describe different shapes.
  7364. SHAPE_RECTANGLE:1,
  7365. /**
  7366. *
  7367. * @param l {number>0}
  7368. */
  7369. setLineWidth : function(l) {
  7370. this.lineWidth= l;
  7371. return this;
  7372. },
  7373. /**
  7374. *
  7375. * @param lc {string{butt|round|square}}
  7376. */
  7377. setLineCap : function(lc) {
  7378. this.lineCap= lc;
  7379. return this;
  7380. },
  7381. /**
  7382. *
  7383. * @param lj {string{bevel|round|miter}}
  7384. */
  7385. setLineJoin : function(lj) {
  7386. this.lineJoin= lj;
  7387. return this;
  7388. },
  7389. /**
  7390. *
  7391. * @param ml {integer>0}
  7392. */
  7393. setMiterLimit : function(ml) {
  7394. this.miterLimit= ml;
  7395. return this;
  7396. },
  7397. getLineCap : function() {
  7398. return this.lineCap;
  7399. },
  7400. getLineJoin : function() {
  7401. return this.lineJoin;
  7402. },
  7403. getMiterLimit : function() {
  7404. return this.miterLimit;
  7405. },
  7406. getLineWidth : function() {
  7407. return this.lineWidth;
  7408. },
  7409. /**
  7410. * Sets shape type.
  7411. * No check for parameter validity is performed.
  7412. * Set paint method according to the shape.
  7413. * @param iShape an integer with any of the SHAPE_* constants.
  7414. * @return this
  7415. */
  7416. setShape : function(iShape) {
  7417. this.shape= iShape;
  7418. this.paint= this.shape===this.SHAPE_CIRCLE ?
  7419. this.paintCircle :
  7420. this.paintRectangle;
  7421. return this;
  7422. },
  7423. /**
  7424. * Sets the composite operation to apply on shape drawing.
  7425. * @param compositeOp an string with a valid canvas rendering context string describing compositeOps.
  7426. * @return this
  7427. */
  7428. setCompositeOp : function(compositeOp){
  7429. this.compositeOp= compositeOp;
  7430. return this;
  7431. },
  7432. /**
  7433. * Draws the shape.
  7434. * Applies the values of fillStype, strokeStyle, compositeOp, etc.
  7435. *
  7436. * @param director a valid CAAT.Director instance.
  7437. * @param time an integer with the Scene time the Actor is being drawn.
  7438. */
  7439. paint : function(director,time) {
  7440. },
  7441. /**
  7442. * @private
  7443. * Draws a circle.
  7444. * @param director a valid CAAT.Director instance.
  7445. * @param time an integer with the Scene time the Actor is being drawn.
  7446. */
  7447. paintCircle : function(director,time) {
  7448. var ctx= director.crc;
  7449. ctx.lineWidth= this.lineWidth;
  7450. ctx.globalCompositeOperation= this.compositeOp;
  7451. if ( null!==this.fillStyle ) {
  7452. ctx.fillStyle= this.fillStyle;
  7453. ctx.beginPath();
  7454. ctx.arc( this.width/2, this.height/2, Math.min(this.width,this.height)/2, 0, 2*Math.PI, false );
  7455. ctx.fill();
  7456. }
  7457. if ( null!==this.strokeStyle ) {
  7458. ctx.strokeStyle= this.strokeStyle;
  7459. ctx.beginPath();
  7460. ctx.arc( this.width/2, this.height/2, Math.min(this.width,this.height)/2, 0, 2*Math.PI, false );
  7461. ctx.stroke();
  7462. }
  7463. },
  7464. /**
  7465. *
  7466. * Private
  7467. * Draws a Rectangle.
  7468. *
  7469. * @param director a valid CAAT.Director instance.
  7470. * @param time an integer with the Scene time the Actor is being drawn.
  7471. */
  7472. paintRectangle : function(director,time) {
  7473. var ctx= director.crc;
  7474. ctx.lineWidth= this.lineWidth;
  7475. if ( this.lineCap ) {
  7476. ctx.lineCap= this.lineCap;
  7477. }
  7478. if ( this.lineJoin ) {
  7479. ctx.lineJoin= this.lineJoin;
  7480. }
  7481. if ( this.miterLimit ) {
  7482. ctx.miterLimit= this.miterLimit;
  7483. }
  7484. ctx.globalCompositeOperation= this.compositeOp;
  7485. if ( null!==this.fillStyle ) {
  7486. ctx.fillStyle= this.fillStyle;
  7487. ctx.beginPath();
  7488. ctx.fillRect(0,0,this.width,this.height);
  7489. ctx.fill();
  7490. }
  7491. if ( null!==this.strokeStyle ) {
  7492. ctx.strokeStyle= this.strokeStyle;
  7493. ctx.beginPath();
  7494. ctx.strokeRect(0,0,this.width,this.height);
  7495. ctx.stroke();
  7496. }
  7497. }
  7498. };
  7499. extend( CAAT.ShapeActor, CAAT.ActorContainer, null);
  7500. })();
  7501. (function() {
  7502. /**
  7503. * This actor draws stars.
  7504. *
  7505. * @constructor
  7506. * @extends CAAT.ActorContainer
  7507. */
  7508. CAAT.StarActor= function() {
  7509. CAAT.StarActor.superclass.constructor.call(this);
  7510. this.compositeOp= 'source-over';
  7511. return this;
  7512. };
  7513. CAAT.StarActor.prototype= {
  7514. nPeaks: 0,
  7515. maxRadius: 0,
  7516. minRadius: 0,
  7517. initialAngle: 0,
  7518. compositeOp: null,
  7519. lineWidth: 1,
  7520. lineCap: null,
  7521. lineJoin: null,
  7522. miterLimit: null,
  7523. /**
  7524. *
  7525. * @param l {number>0}
  7526. */
  7527. setLineWidth : function(l) {
  7528. this.lineWidth= l;
  7529. return this;
  7530. },
  7531. /**
  7532. *
  7533. * @param lc {string{butt|round|square}}
  7534. */
  7535. setLineCap : function(lc) {
  7536. this.lineCap= lc;
  7537. return this;
  7538. },
  7539. /**
  7540. *
  7541. * @param lj {string{bevel|round|miter}}
  7542. */
  7543. setLineJoin : function(lj) {
  7544. this.lineJoin= lj;
  7545. return this;
  7546. },
  7547. /**
  7548. *
  7549. * @param ml {integer>0}
  7550. */
  7551. setMiterLimit : function(ml) {
  7552. this.miterLimit= ml;
  7553. return this;
  7554. },
  7555. getLineCap : function() {
  7556. return this.lineCap;
  7557. },
  7558. getLineJoin : function() {
  7559. return this.lineJoin;
  7560. },
  7561. getMiterLimit : function() {
  7562. return this.miterLimit;
  7563. },
  7564. getLineWidth : function() {
  7565. return this.lineWidth;
  7566. },
  7567. /**
  7568. * Sets whether the star will be color filled.
  7569. * @param filled {boolean}
  7570. * @deprecated
  7571. */
  7572. setFilled : function( filled ) {
  7573. return this;
  7574. },
  7575. /**
  7576. * Sets whether the star will be outlined.
  7577. * @param outlined {boolean}
  7578. * @deprecated
  7579. */
  7580. setOutlined : function( outlined ) {
  7581. return this;
  7582. },
  7583. /**
  7584. * Sets the composite operation to apply on shape drawing.
  7585. * @param compositeOp an string with a valid canvas rendering context string describing compositeOps.
  7586. * @return this
  7587. */
  7588. setCompositeOp : function(compositeOp){
  7589. this.compositeOp= compositeOp;
  7590. return this;
  7591. },
  7592. /**
  7593. *
  7594. * @param angle {number} number in radians.
  7595. */
  7596. setInitialAngle : function(angle) {
  7597. this.initialAngle= angle;
  7598. return this;
  7599. },
  7600. /**
  7601. * Initialize the star values.
  7602. * <p>
  7603. * The star actor will be of size 2*maxRadius.
  7604. *
  7605. * @param nPeaks {number} number of star points.
  7606. * @param maxRadius {number} maximum star radius
  7607. * @param minRadius {number} minimum star radius
  7608. *
  7609. * @return this
  7610. */
  7611. initialize : function(nPeaks, maxRadius, minRadius) {
  7612. this.setSize( 2*maxRadius, 2*maxRadius );
  7613. this.nPeaks= nPeaks;
  7614. this.maxRadius= maxRadius;
  7615. this.minRadius= minRadius;
  7616. return this;
  7617. },
  7618. /**
  7619. * Paint the star.
  7620. *
  7621. * @param director {CAAT.Director}
  7622. * @param timer {number}
  7623. */
  7624. paint : function(director, timer) {
  7625. var ctx= director.ctx;
  7626. var centerX= this.width/2;
  7627. var centerY= this.height/2;
  7628. var r1= this.maxRadius;
  7629. var r2= this.minRadius;
  7630. var ix= centerX + r1*Math.cos(this.initialAngle);
  7631. var iy= centerY + r1*Math.sin(this.initialAngle);
  7632. ctx.lineWidth= this.lineWidth;
  7633. if ( this.lineCap ) {
  7634. ctx.lineCap= this.lineCap;
  7635. }
  7636. if ( this.lineJoin ) {
  7637. ctx.lineJoin= this.lineJoin;
  7638. }
  7639. if ( this.miterLimit ) {
  7640. ctx.miterLimit= this.miterLimit;
  7641. }
  7642. ctx.globalCompositeOperation= this.compositeOp;
  7643. ctx.beginPath();
  7644. ctx.moveTo(ix,iy);
  7645. for( var i=1; i<this.nPeaks*2; i++ ) {
  7646. var angleStar= Math.PI/this.nPeaks * i + this.initialAngle;
  7647. var rr= (i%2===0) ? r1 : r2;
  7648. var x= centerX + rr*Math.cos(angleStar);
  7649. var y= centerY + rr*Math.sin(angleStar);
  7650. ctx.lineTo(x,y);
  7651. }
  7652. ctx.lineTo(
  7653. centerX + r1*Math.cos(this.initialAngle),
  7654. centerY + r1*Math.sin(this.initialAngle) );
  7655. ctx.closePath();
  7656. if ( this.fillStyle ) {
  7657. ctx.fillStyle= this.fillStyle;
  7658. ctx.fill();
  7659. }
  7660. if ( this.strokeStyle ) {
  7661. ctx.strokeStyle= this.strokeStyle;
  7662. ctx.stroke();
  7663. }
  7664. }
  7665. };
  7666. extend(CAAT.StarActor, CAAT.ActorContainer, null);
  7667. })();
  7668. /**
  7669. * An actor suitable to draw an ImageProcessor instance.
  7670. */
  7671. (function() {
  7672. /**
  7673. * This Actor will show the result of an image processing operation.
  7674. *
  7675. * @constructor
  7676. * @extends CAAT.ActorContainer
  7677. */
  7678. CAAT.IMActor= function() {
  7679. CAAT.IMActor.superclass.constructor.call(this);
  7680. return this;
  7681. };
  7682. CAAT.IMActor.prototype= {
  7683. imageProcessor: null,
  7684. changeTime: 100,
  7685. lastApplicationTime: -1,
  7686. /**
  7687. * Set the image processor.
  7688. *
  7689. * @param im {CAAT.ImageProcessor} a CAAT.ImageProcessor instance.
  7690. */
  7691. setImageProcessor : function(im) {
  7692. this.imageProcessor= im;
  7693. return this;
  7694. },
  7695. /**
  7696. * Call image processor to update image every time milliseconds.
  7697. * @param time an integer indicating milliseconds to elapse before updating the frame.
  7698. */
  7699. setImageProcessingTime : function( time ) {
  7700. this.changeTime= time;
  7701. return this;
  7702. },
  7703. paint : function( director, time ) {
  7704. if ( time-this.lastApplicationTime>this.changeTime ) {
  7705. this.imageProcessor.apply( director, time );
  7706. this.lastApplicationTime= time;
  7707. }
  7708. var ctx= director.ctx;
  7709. this.imageProcessor.paint( director, time );
  7710. }
  7711. };
  7712. extend( CAAT.IMActor, CAAT.ActorContainer, null);
  7713. })();/**
  7714. * See LICENSE file.
  7715. *
  7716. * Sound implementation.
  7717. */
  7718. (function() {
  7719. /**
  7720. * This class is a sound manager implementation which can play at least 'numChannels' sounds at the same time.
  7721. * By default, CAAT.Director instances will set eight channels to play sound.
  7722. * <p>
  7723. * If more than 'numChannels' sounds want to be played at the same time the requests will be dropped,
  7724. * so no more than 'numChannels' sounds can be concurrently played.
  7725. * <p>
  7726. * Available sounds to be played must be supplied to every CAAT.Director instance by calling <code>addSound</code>
  7727. * method. The default implementation will accept a URL/URI or a HTMLAudioElement as source.
  7728. * <p>
  7729. * The cached elements can be played, or looped. The <code>loop</code> method will return a handler to
  7730. * give the opportunity of cancelling the sound.
  7731. * <p>
  7732. * Be aware of Audio.canPlay, is able to return 'yes', 'no', 'maybe', ..., so anything different from
  7733. * '' and 'no' will do.
  7734. *
  7735. * @constructor
  7736. *
  7737. */
  7738. CAAT.AudioManager= function() {
  7739. this.browserInfo= new CAAT.BrowserDetect();
  7740. return this;
  7741. };
  7742. CAAT.AudioManager.prototype= {
  7743. browserInfo: null,
  7744. musicEnabled: true,
  7745. fxEnabled: true,
  7746. audioCache: null, // audio elements.
  7747. channels: null, // available playing channels.
  7748. workingChannels: null, // currently playing channels.
  7749. loopingChannels: [],
  7750. audioTypes: { // supported audio formats. Don't remember where i took them from :S
  7751. 'mp3': 'audio/mpeg;',
  7752. 'ogg': 'audio/ogg; codecs="vorbis"',
  7753. 'wav': 'audio/wav; codecs="1"',
  7754. 'mp4': 'audio/mp4; codecs="mp4a.40.2"'
  7755. },
  7756. /**
  7757. * Initializes the sound subsystem by creating a fixed number of Audio channels.
  7758. * Every channel registers a handler for sound playing finalization. If a callback is set, the
  7759. * callback function will be called with the associated sound id in the cache.
  7760. *
  7761. * @param numChannels {number} number of channels to pre-create. 8 by default.
  7762. *
  7763. * @return this.
  7764. */
  7765. initialize : function(numChannels) {
  7766. this.audioCache= [];
  7767. this.channels= [];
  7768. this.workingChannels= [];
  7769. for( var i=0; i<numChannels; i++ ) {
  7770. var channel= document.createElement('audio');
  7771. if ( null!==channel ) {
  7772. channel.finished= -1;
  7773. this.channels.push( channel );
  7774. var me= this;
  7775. channel.addEventListener(
  7776. 'ended',
  7777. // on sound end, set channel to available channels list.
  7778. function(audioEvent) {
  7779. var target= audioEvent.target;
  7780. var i;
  7781. // remove from workingChannels
  7782. for( i=0; i<me.workingChannels.length; i++ ) {
  7783. if (me.workingChannels[i]===target ) {
  7784. me.workingChannels.splice(i,1);
  7785. break;
  7786. }
  7787. }
  7788. if ( target.caat_callback ) {
  7789. target.caat_callback(target.caat_id);
  7790. }
  7791. // set back to channels.
  7792. me.channels.push(target);
  7793. },
  7794. false
  7795. );
  7796. }
  7797. }
  7798. return this;
  7799. },
  7800. /**
  7801. * Tries to add an audio tag to the available list of valid audios. The audio is described by a url.
  7802. * @param id {object} an object to associate the audio element (if suitable to be played).
  7803. * @param url {string} a string describing an url.
  7804. * @param endplaying_callback {function} callback to be called upon sound end.
  7805. *
  7806. * @return {boolean} a boolean indicating whether the browser can play this resource.
  7807. *
  7808. * @private
  7809. */
  7810. addAudioFromURL : function( id, url, endplaying_callback ) {
  7811. var extension= null;
  7812. var audio= document.createElement('audio');
  7813. if ( null!==audio ) {
  7814. if(!audio.canPlayType) {
  7815. return false;
  7816. }
  7817. extension= url.substr(url.lastIndexOf('.')+1);
  7818. var canplay= audio.canPlayType(this.audioTypes[extension]);
  7819. if(canplay!=="" && canplay!=="no") {
  7820. audio.src= url;
  7821. audio.preload = "auto";
  7822. audio.load();
  7823. if ( endplaying_callback ) {
  7824. audio.caat_callback= endplaying_callback;
  7825. audio.caat_id= id;
  7826. }
  7827. this.audioCache.push( { id:id, audio:audio } );
  7828. return true;
  7829. }
  7830. }
  7831. return false;
  7832. },
  7833. /**
  7834. * Tries to add an audio tag to the available list of valid audios. The audio element comes from
  7835. * an HTMLAudioElement.
  7836. * @param id {object} an object to associate the audio element (if suitable to be played).
  7837. * @param audio {HTMLAudioElement} a DOM audio node.
  7838. * @param endplaying_callback {function} callback to be called upon sound end.
  7839. *
  7840. * @return {boolean} a boolean indicating whether the browser can play this resource.
  7841. *
  7842. * @private
  7843. */
  7844. addAudioFromDomNode : function( id, audio, endplaying_callback ) {
  7845. var extension= audio.src.substr(audio.src.lastIndexOf('.')+1);
  7846. if ( audio.canPlayType(this.audioTypes[extension]) ) {
  7847. if ( endplaying_callback ) {
  7848. audio.caat_callback= endplaying_callback;
  7849. audio.caat_id= id;
  7850. }
  7851. this.audioCache.push( { id:id, audio:audio } );
  7852. return true;
  7853. }
  7854. return false;
  7855. },
  7856. /**
  7857. * Adds an elements to the audio cache.
  7858. * @param id {object} an object to associate the audio element (if suitable to be played).
  7859. * @param element {URL|HTMLElement} an url or html audio tag.
  7860. * @param endplaying_callback {function} callback to be called upon sound end.
  7861. *
  7862. * @return {boolean} a boolean indicating whether the browser can play this resource.
  7863. *
  7864. * @private
  7865. */
  7866. addAudioElement : function( id, element, endplaying_callback ) {
  7867. if ( typeof element === "string" ) {
  7868. return this.addAudioFromURL( id, element, endplaying_callback );
  7869. } else {
  7870. try {
  7871. if ( element instanceof HTMLAudioElement ) {
  7872. return this.addAudioFromDomNode( id, element, endplaying_callback );
  7873. }
  7874. }
  7875. catch(e) {
  7876. }
  7877. }
  7878. return false;
  7879. },
  7880. /**
  7881. * creates an Audio object and adds it to the audio cache.
  7882. * This function expects audio data described by two elements, an id and an object which will
  7883. * describe an audio element to be associated with the id. The object will be of the form
  7884. * array, dom node or a url string.
  7885. *
  7886. * <p>
  7887. * The audio element can be one of the two forms:
  7888. *
  7889. * <ol>
  7890. * <li>Either an HTMLAudioElement/Audio object or a string url.
  7891. * <li>An array of elements of the previous form.
  7892. * </ol>
  7893. *
  7894. * <p>
  7895. * When the audio attribute is an array, this function will iterate throught the array elements
  7896. * until a suitable audio element to be played is found. When this is the case, the other array
  7897. * elements won't be taken into account. The valid form of using this addAudio method will be:
  7898. *
  7899. * <p>
  7900. * 1.<br>
  7901. * addAudio( id, url } ). In this case, if the resource pointed by url is
  7902. * not suitable to be played (i.e. a call to the Audio element's canPlayType method return 'no')
  7903. * no resource will be added under such id, so no sound will be played when invoking the play(id)
  7904. * method.
  7905. * <p>
  7906. * 2.<br>
  7907. * addAudio( id, dom_audio_tag ). In this case, the same logic than previous case is applied, but
  7908. * this time, the parameter url is expected to be an audio tag present in the html file.
  7909. * <p>
  7910. * 3.<br>
  7911. * addAudio( id, [array_of_url_or_domaudiotag] ). In this case, the function tries to locate a valid
  7912. * resource to be played in any of the elements contained in the array. The array element's can
  7913. * be any type of case 1 and 2. As soon as a valid resource is found, it will be associated to the
  7914. * id in the valid audio resources to be played list.
  7915. *
  7916. * @return this
  7917. */
  7918. addAudio : function( id, array_of_url_or_domnodes, endplaying_callback ) {
  7919. if ( array_of_url_or_domnodes instanceof Array ) {
  7920. /*
  7921. iterate throught array elements until we can safely add an audio element.
  7922. */
  7923. for( var i=0; i<array_of_url_or_domnodes.length; i++ ) {
  7924. if ( this.addAudioElement(id, array_of_url_or_domnodes[i], endplaying_callback) ) {
  7925. break;
  7926. }
  7927. }
  7928. } else {
  7929. this.addAudioElement(id, array_of_url_or_domnodes, endplaying_callback);
  7930. }
  7931. return this;
  7932. },
  7933. /**
  7934. * Returns an audio object.
  7935. * @param aId {object} the id associated to the target Audio object.
  7936. * @return {object} the HTMLAudioElement addociated to the given id.
  7937. */
  7938. getAudio : function(aId) {
  7939. for( var i=0; i<this.audioCache.length; i++ ) {
  7940. if ( this.audioCache[i].id===aId ) {
  7941. return this.audioCache[i].audio;
  7942. }
  7943. }
  7944. return null;
  7945. },
  7946. /**
  7947. * Set an audio object volume.
  7948. * @param id {object} an audio Id
  7949. * @param volume {number} volume to set. The volume value is not checked.
  7950. *
  7951. * @return this
  7952. */
  7953. setVolume : function( id, volume ) {
  7954. var audio= this.getAudio(id);
  7955. if ( null!=audio ) {
  7956. audio.volume= volume;
  7957. }
  7958. return this;
  7959. },
  7960. /**
  7961. * Plays an audio file from the cache if any sound channel is available.
  7962. * The playing sound will occupy a sound channel and when ends playing will leave
  7963. * the channel free for any other sound to be played in.
  7964. * @param id {object} an object identifying a sound in the sound cache.
  7965. * @return this.
  7966. */
  7967. play : function( id ) {
  7968. if ( !this.fxEnabled ) {
  7969. return this;
  7970. }
  7971. var audio= this.getAudio(id);
  7972. // existe el audio, y ademas hay un canal de audio disponible.
  7973. if ( null!==audio && this.channels.length>0 ) {
  7974. var channel= this.channels.shift();
  7975. channel.src= audio.src;
  7976. channel.load();
  7977. channel.volume= audio.volume;
  7978. channel.play();
  7979. this.workingChannels.push(channel);
  7980. }
  7981. return this;
  7982. },
  7983. /**
  7984. * This method creates a new AudioChannel to loop the sound with.
  7985. * It returns an Audio object so that the developer can cancel the sound loop at will.
  7986. * The user must call <code>pause()</code> method to stop playing a loop.
  7987. * <p>
  7988. * Firefox does not honor the loop property, so looping is performed by attending end playing
  7989. * event on audio elements.
  7990. *
  7991. * @return {HTMLElement} an Audio instance if a valid sound id is supplied. Null otherwise
  7992. */
  7993. loop : function( id ) {
  7994. if (!this.musicEnabled) {
  7995. return this;
  7996. }
  7997. var audio_in_cache= this.getAudio(id);
  7998. // existe el audio, y ademas hay un canal de audio disponible.
  7999. if ( null!==audio_in_cache ) {
  8000. var audio= document.createElement('audio');
  8001. if ( null!==audio ) {
  8002. audio.src= audio_in_cache.src;
  8003. audio.preload = "auto";
  8004. if ( this.browserInfo.browser==='Firefox') {
  8005. audio.addEventListener(
  8006. 'ended',
  8007. // on sound end, set channel to available channels list.
  8008. function(audioEvent) {
  8009. var target= audioEvent.target;
  8010. target.currentTime=0;
  8011. },
  8012. false
  8013. );
  8014. } else {
  8015. audio.loop= true;
  8016. }
  8017. audio.load();
  8018. audio.play();
  8019. this.loopingChannels.push(audio);
  8020. return audio;
  8021. }
  8022. }
  8023. return null;
  8024. },
  8025. /**
  8026. * Cancel all playing audio channels
  8027. * Get back the playing channels to available channel list.
  8028. *
  8029. * @return this
  8030. */
  8031. endSound : function() {
  8032. var i;
  8033. for( i=0; i<this.workingChannels.length; i++ ) {
  8034. this.workingChannels[i].pause();
  8035. this.channels.push( this.workingChannels[i] );
  8036. }
  8037. for( i=0; i<this.loopingChannels.length; i++ ) {
  8038. this.loopingChannels[i].pause();
  8039. }
  8040. return this;
  8041. },
  8042. setSoundEffectsEnabled : function( enable ) {
  8043. this.fxEnabled= enable;
  8044. return this;
  8045. },
  8046. isSoundEffectsEnabled : function() {
  8047. return this.fxEnabled;
  8048. },
  8049. setMusicEnabled : function( enable ) {
  8050. this.musicEnabled= enable;
  8051. for( var i=0; i<this.loopingChannels.length; i++ ) {
  8052. if ( enable ) {
  8053. this.loopingChannels[i].play();
  8054. } else {
  8055. this.loopingChannels[i].pause();
  8056. }
  8057. }
  8058. return this;
  8059. },
  8060. isMusicEnabled : function() {
  8061. return this.musicEnabled;
  8062. }
  8063. };
  8064. })();/**
  8065. * See LICENSE file.
  8066. *
  8067. * In this file we'll be adding every useful Actor that is specific for certain purpose.
  8068. *
  8069. * + CAAT.Dock: a docking container that zooms in/out its actors.
  8070. *
  8071. */
  8072. (function() {
  8073. /**
  8074. * This actor simulates a mac os-x docking component.
  8075. * Every contained actor will be laid out in a row in the desired orientation.
  8076. */
  8077. CAAT.Dock = function() {
  8078. CAAT.Dock.superclass.constructor.call(this);
  8079. return this;
  8080. };
  8081. CAAT.Dock.prototype= {
  8082. scene: null, // scene the actor is in.
  8083. ttask: null, // resetting dimension timer.
  8084. minSize: 0, // min contained actor size
  8085. maxSize: 0, // max contained actor size
  8086. range: 2, // aproximated number of elements affected.
  8087. layoutOp: 0,
  8088. OP_LAYOUT_BOTTOM: 0,
  8089. OP_LAYOUT_TOP: 1,
  8090. OP_LAYOUT_LEFT: 2,
  8091. OP_LAYOUT_RIGHT: 3,
  8092. initialize : function(scene) {
  8093. this.scene= scene;
  8094. return this;
  8095. },
  8096. /**
  8097. * Set the number of elements that will be affected (zoomed) when the mouse is inside the component.
  8098. * @param range {number} a number. Defaults to 2.
  8099. */
  8100. setApplicationRange : function( range ) {
  8101. this.range= range;
  8102. return this;
  8103. },
  8104. /**
  8105. * Set layout orientation. Choose from
  8106. * <ul>
  8107. * <li>CAAT.Dock.prototype.OP_LAYOUT_BOTTOM
  8108. * <li>CAAT.Dock.prototype.OP_LAYOUT_TOP
  8109. * <li>CAAT.Dock.prototype.OP_LAYOUT_BOTTOM
  8110. * <li>CAAT.Dock.prototype.OP_LAYOUT_RIGHT
  8111. * </ul>
  8112. * By default, the layou operation is OP_LAYOUT_BOTTOM, that is, elements zoom bottom anchored.
  8113. *
  8114. * @param lo {number} one of CAAT.Dock.OP_LAYOUT_BOTTOM, CAAT.Dock.OP_LAYOUT_TOP,
  8115. * CAAT.Dock.OP_LAYOUT_BOTTOM, CAAT.Dock.OP_LAYOUT_RIGHT.
  8116. *
  8117. * @return this
  8118. */
  8119. setLayoutOp : function( lo ) {
  8120. this.layoutOp= lo;
  8121. return this;
  8122. },
  8123. /**
  8124. *
  8125. * Set maximum and minimum size of docked elements. By default, every contained actor will be
  8126. * of 'min' size, and will be scaled up to 'max' size.
  8127. *
  8128. * @param min {number}
  8129. * @param max {number}
  8130. * @return this
  8131. */
  8132. setSizes : function( min, max ) {
  8133. this.minSize= min;
  8134. this.maxSize= max;
  8135. for( var i=0; i<this.childrenList.length; i++ ) {
  8136. this.childrenList[i].width= min;
  8137. this.childrenList[i].height= min;
  8138. }
  8139. return this;
  8140. },
  8141. /**
  8142. * Lay out the docking elements. The lay out will be a row with the orientation set by calling
  8143. * the method <code>setLayoutOp</code>.
  8144. *
  8145. * @private
  8146. */
  8147. layout : function() {
  8148. var i,actor;
  8149. if ( this.layoutOp===this.OP_LAYOUT_BOTTOM || this.layoutOp===this.OP_LAYOUT_TOP ) {
  8150. var currentWidth=0, currentX=0;
  8151. for( i=0; i<this.getNumChildren(); i++ ) {
  8152. currentWidth+= this.getChildAt(i).width;
  8153. }
  8154. currentX= (this.width-currentWidth)/2;
  8155. for( i=0; i<this.getNumChildren(); i++ ) {
  8156. actor= this.getChildAt(i);
  8157. actor.x= currentX;
  8158. currentX+= actor.width;
  8159. if ( this.layoutOp===this.OP_LAYOUT_BOTTOM ) {
  8160. actor.y= this.maxSize- actor.height;
  8161. } else {
  8162. actor.y= 0;
  8163. }
  8164. }
  8165. } else {
  8166. var currentHeight=0, currentY=0;
  8167. for( i=0; i<this.getNumChildren(); i++ ) {
  8168. currentHeight+= this.getChildAt(i).height;
  8169. }
  8170. currentY= (this.height-currentHeight)/2;
  8171. for( i=0; i<this.getNumChildren(); i++ ) {
  8172. actor= this.getChildAt(i);
  8173. actor.y= currentY;
  8174. currentY+= actor.height;
  8175. if ( this.layoutOp===this.OP_LAYOUT_LEFT ) {
  8176. actor.x= 0;
  8177. } else {
  8178. actor.x= this.width - actor.width;
  8179. }
  8180. }
  8181. }
  8182. },
  8183. mouseMove : function(mouseEvent) {
  8184. this.actorNotPointed();
  8185. },
  8186. mouseExit : function(mouseEvent) {
  8187. this.actorNotPointed();
  8188. },
  8189. /**
  8190. * Performs operation when the mouse is not in the dock element.
  8191. *
  8192. * @private
  8193. */
  8194. actorNotPointed : function() {
  8195. var i;
  8196. var me= this;
  8197. for( i=0; i<this.getNumChildren(); i++ ) {
  8198. var actor= this.getChildAt(i);
  8199. actor.emptyBehaviorList();
  8200. actor.addBehavior(
  8201. new CAAT.GenericBehavior().
  8202. setValues( actor.width, this.minSize, actor, 'width' ).
  8203. setFrameTime( this.scene.time, 250 ) ).
  8204. addBehavior(
  8205. new CAAT.GenericBehavior().
  8206. setValues( actor.height, this.minSize, actor, 'height' ).
  8207. setFrameTime( this.scene.time, 250 ) );
  8208. if ( i===this.getNumChildren()-1 ) {
  8209. actor.behaviorList[0].addListener(
  8210. {
  8211. behaviorApplied : function(behavior,time,normalizedTime,targetActor,value) {
  8212. targetActor.parent.layout();
  8213. },
  8214. behaviorExpired : function(behavior,time,targetActor) {
  8215. for( i=0; i<me.getNumChildren(); i++ ) {
  8216. actor= me.getChildAt(i);
  8217. actor.width = me.minSize;
  8218. actor.height = me.minSize;
  8219. }
  8220. targetActor.parent.layout();
  8221. }
  8222. });
  8223. }
  8224. }
  8225. },
  8226. /**
  8227. *
  8228. * Perform the process of pointing a docking actor.
  8229. *
  8230. * @param x {number}
  8231. * @param y {number}
  8232. * @param pointedActor {CAAT.Actor}
  8233. *
  8234. * @private
  8235. */
  8236. actorPointed : function(x, y, pointedActor) {
  8237. var index= this.findChild(pointedActor);
  8238. var across= 0;
  8239. if ( this.layoutOp===this.OP_LAYOUT_BOTTOM || this.layoutOp===this.OP_LAYOUT_TOP ) {
  8240. across= x / pointedActor.width;
  8241. } else {
  8242. across= y / pointedActor.height;
  8243. }
  8244. var i;
  8245. for( i=0; i<this.childrenList.length; i++ ) {
  8246. var actor= this.childrenList[i];
  8247. actor.emptyBehaviorList();
  8248. var wwidth=0;
  8249. if (i < index - this.range || i > index + this.range) {
  8250. wwidth = this.minSize;
  8251. } else if (i === index) {
  8252. wwidth = this.maxSize;
  8253. } else if (i < index) {
  8254. wwidth=
  8255. this.minSize +
  8256. (this.maxSize-this.minSize) *
  8257. (Math.cos((i - index - across + 1) / this.range * Math.PI) + 1) /
  8258. 2;
  8259. } else {
  8260. wwidth=
  8261. this.minSize +
  8262. (this.maxSize-this.minSize)*
  8263. (Math.cos( (i - index - across) / this.range * Math.PI) + 1) /
  8264. 2;
  8265. }
  8266. actor.height= wwidth;
  8267. actor.width= wwidth;
  8268. }
  8269. this.layout();
  8270. },
  8271. /**
  8272. * Perform the process of exiting the docking element, that is, animate elements to the minimum
  8273. * size.
  8274. *
  8275. * @param mouseEvent {CAAT.MouseEvent} a CAAT.MouseEvent object.
  8276. *
  8277. * @private
  8278. */
  8279. actorMouseExit : function(mouseEvent) {
  8280. if ( null!==this.ttask ) {
  8281. this.ttask.cancel();
  8282. }
  8283. var me= this;
  8284. this.ttask= this.scene.createTimer(
  8285. this.scene.time,
  8286. 100,
  8287. function timeout(sceneTime, time, timerTask) {
  8288. me.actorNotPointed();
  8289. },
  8290. null,
  8291. null);
  8292. },
  8293. /**
  8294. * Perform the beginning of docking elements.
  8295. * @param mouseEvent {CAAT.MouseEvent} a CAAT.MouseEvent object.
  8296. *
  8297. * @private
  8298. */
  8299. actorMouseEnter : function(mouseEvent) {
  8300. if ( null!==this.ttask ) {
  8301. this.ttask.cancel();
  8302. this.ttask= null;
  8303. }
  8304. },
  8305. /**
  8306. * Adds an actor to Dock.
  8307. * <p>
  8308. * Be aware that actor mouse functions must be set prior to calling this method. The Dock actor
  8309. * needs set his own actor input events functions for mouseEnter, mouseExit and mouseMove and
  8310. * will then chain to the original methods set by the developer.
  8311. *
  8312. * @param actor {CAAT.Actor} a CAAT.Actor instance.
  8313. *
  8314. * @return this
  8315. */
  8316. addChild : function(actor) {
  8317. var me= this;
  8318. actor.__Dock_mouseEnter= actor.mouseEnter;
  8319. actor.__Dock_mouseExit= actor.mouseExit;
  8320. actor.__Dock_mouseMove= actor.mouseMove;
  8321. /**
  8322. * @ignore
  8323. * @param mouseEvent
  8324. */
  8325. actor.mouseEnter= function(mouseEvent) {
  8326. me.actorMouseEnter(mouseEvent);
  8327. this.__Dock_mouseEnter(mouseEvent);
  8328. };
  8329. /**
  8330. * @ignore
  8331. * @param mouseEvent
  8332. */
  8333. actor.mouseExit= function(mouseEvent) {
  8334. me.actorMouseExit(mouseEvent);
  8335. this.__Dock_mouseExit(mouseEvent);
  8336. };
  8337. /**
  8338. * @ignore
  8339. * @param mouseEvent
  8340. */
  8341. actor.mouseMove= function(mouseEvent) {
  8342. me.actorPointed( mouseEvent.point.x, mouseEvent.point.y, mouseEvent.source );
  8343. this.__Dock_mouseMove(mouseEvent);
  8344. };
  8345. actor.width= this.minSize;
  8346. actor.height= this.minSize;
  8347. return CAAT.Dock.superclass.addChild.call(this,actor);
  8348. }
  8349. };
  8350. extend( CAAT.Dock, CAAT.ActorContainer, null);
  8351. })();
  8352. /**
  8353. * See LICENSE file.
  8354. *
  8355. **/
  8356. (function() {
  8357. /**
  8358. * Director is the animator scene graph manager.
  8359. * <p>
  8360. * The director elements is an ActorContainer itself with the main responsibility of managing
  8361. * different Scenes.
  8362. * <p>
  8363. * It is responsible for:
  8364. * <ul>
  8365. * <li>scene changes.
  8366. * <li>route input to the appropriate scene graph actor.
  8367. * <li>be the central point for resource caching.
  8368. * <li>manage the timeline.
  8369. * <li>manage frame rate.
  8370. * <li>etc.
  8371. * </ul>
  8372. *
  8373. * <p>
  8374. * One document can contain different CAAT.Director instances which will be kept together in CAAT
  8375. * function.
  8376. *
  8377. * @constructor
  8378. * @extends CAAT.ActorContainer
  8379. */
  8380. CAAT.Director = function() {
  8381. CAAT.Director.superclass.constructor.call(this);
  8382. this.browserInfo = new CAAT.BrowserDetect();
  8383. this.audioManager = new CAAT.AudioManager().initialize(8);
  8384. this.scenes = [];
  8385. // input related variables initialization
  8386. this.mousePoint = new CAAT.Point(0, 0, 0);
  8387. this.prevMousePoint = new CAAT.Point(0, 0, 0);
  8388. this.screenMousePoint = new CAAT.Point(0, 0, 0);
  8389. this.isMouseDown = false;
  8390. this.lastSelectedActor = null;
  8391. this.dragging = false;
  8392. this.cDirtyRects= [];
  8393. this.dirtyRects= [];
  8394. for( var i=0; i<64; i++ ) {
  8395. this.dirtyRects.push( new CAAT.Rectangle() );
  8396. }
  8397. this.dirtyRectsIndex= 0;
  8398. return this;
  8399. };
  8400. CAAT.Director.CLEAR_DIRTY_RECTS= 1;
  8401. CAAT.Director.CLEAR_ALL= true;
  8402. CAAT.Director.CLEAR_NONE= false;
  8403. CAAT.Director.prototype = {
  8404. debug: false, // flag indicating debug mode. It will draw affedted screen areas.
  8405. onRenderStart: null,
  8406. onRenderEnd: null,
  8407. // input related attributes
  8408. mousePoint: null, // mouse coordinate related to canvas 0,0 coord.
  8409. prevMousePoint: null, // previous mouse position cache. Needed for drag events.
  8410. screenMousePoint: null, // screen mouse coordinates.
  8411. isMouseDown: false, // is the left mouse button pressed ?
  8412. lastSelectedActor: null, // director's last actor receiving input.
  8413. dragging: false, // is in drag mode ?
  8414. // other attributes
  8415. scenes: null, // Scenes collection. An array.
  8416. currentScene: null, // The current Scene. This and only this will receive events.
  8417. canvas: null, // The canvas the Director draws on.
  8418. crc: null, // @deprecated. canvas rendering context
  8419. ctx: null, // refactoring crc for a more convenient name
  8420. time: 0, // virtual actor time.
  8421. timeline: 0, // global director timeline.
  8422. imagesCache: null, // An array of JSON elements of the form { id:string, image:Image }
  8423. audioManager: null,
  8424. clear: true, // clear background before drawing scenes ??
  8425. transitionScene: null,
  8426. browserInfo: null,
  8427. gl: null,
  8428. glEnabled: false,
  8429. glTextureManager: null,
  8430. glTtextureProgram: null,
  8431. glColorProgram: null,
  8432. pMatrix: null, // projection matrix
  8433. coords: null, // Float32Array
  8434. coordsIndex: 0,
  8435. uv: null,
  8436. uvIndex: 0,
  8437. front_to_back: false,
  8438. statistics: {
  8439. size_total: 0,
  8440. size_active: 0,
  8441. size_dirtyRects: 0,
  8442. draws: 0
  8443. },
  8444. currentTexturePage: 0,
  8445. currentOpacity: 1,
  8446. intervalId: null,
  8447. frameCounter: 0,
  8448. RESIZE_NONE: 1,
  8449. RESIZE_WIDTH: 2,
  8450. RESIZE_HEIGHT: 4,
  8451. RESIZE_BOTH: 8,
  8452. RESIZE_PROPORTIONAL:16,
  8453. resize: 1,
  8454. onResizeCallback : null,
  8455. __gestureScale : 0,
  8456. __gestureRotation : 0,
  8457. dirtyRects : null,
  8458. cDirtyRects : null,
  8459. dirtyRectsIndex : 0,
  8460. dirtyRectsEnabled : false,
  8461. nDirtyRects : 0,
  8462. stopped : false, // is stopped, this director will do nothing.
  8463. checkDebug : function() {
  8464. if ( CAAT.DEBUG ) {
  8465. var dd= new CAAT.Debug().initialize( this.width, 60 );
  8466. this.debugInfo= dd.debugInfo.bind(dd);
  8467. }
  8468. },
  8469. getRenderType : function() {
  8470. return this.glEnabled ? 'WEBGL' : 'CANVAS';
  8471. },
  8472. windowResized : function(w, h) {
  8473. switch (this.resize) {
  8474. case this.RESIZE_WIDTH:
  8475. this.setBounds(0, 0, w, this.height);
  8476. break;
  8477. case this.RESIZE_HEIGHT:
  8478. this.setBounds(0, 0, this.width, h);
  8479. break;
  8480. case this.RESIZE_BOTH:
  8481. this.setScaleBoth(w,h);
  8482. break;
  8483. case this.RESIZE_PROPORTIONAL:
  8484. this.setScaleProportional(w,h);
  8485. break;
  8486. }
  8487. if ( this.glEnabled ) {
  8488. this.glReset();
  8489. }
  8490. if ( this.onResizeCallback ) {
  8491. this.onResizeCallback( this, w, h );
  8492. }
  8493. },setScaleBoth : function(w,h) {
  8494. // var factor= Math.min(w/this.referenceWidth, h/this.referenceHeight);
  8495. var wf = w/this.referenceWidth;
  8496. var hf = h/this.referenceHeight
  8497. this.setScaleAnchored( wf, hf, 0, 0 );
  8498. this.canvas.width = this.referenceWidth*wf;
  8499. this.canvas.height = this.referenceHeight*hf;
  8500. this.ctx = this.canvas.getContext(this.glEnabled ? 'experimental-webgl' : '2d' );
  8501. this.crc = this.ctx;
  8502. if ( this.glEnabled ) {
  8503. this.glReset();
  8504. }
  8505. },
  8506. setScaleProportional : function(w,h) {
  8507. var factor= Math.min(w/this.referenceWidth, h/this.referenceHeight);
  8508. this.setScaleAnchored( factor, factor, 0, 0 );
  8509. this.canvas.width = this.referenceWidth*factor;
  8510. this.canvas.height = this.referenceHeight*factor;
  8511. this.ctx = this.canvas.getContext(this.glEnabled ? 'experimental-webgl' : '2d' );
  8512. this.crc = this.ctx;
  8513. if ( this.glEnabled ) {
  8514. this.glReset();
  8515. }
  8516. },
  8517. /**
  8518. * Enable window resize events and set redimension policy. A callback functio could be supplied
  8519. * to be notified on a Director redimension event. This is necessary in the case you set a redim
  8520. * policy not equal to RESIZE_PROPORTIONAL. In those redimension modes, director's area and their
  8521. * children scenes are resized to fit the new area. But scenes content is not resized, and have
  8522. * no option of knowing so uless an onResizeCallback function is supplied.
  8523. *
  8524. * @param mode {number} RESIZE_BOTH, RESIZE_WIDTH, RESIZE_HEIGHT, RESIZE_NONE.
  8525. * @param onResizeCallback {function(director{CAAT.Director}, width{integer}, height{integer})} a callback
  8526. * to notify on canvas resize.
  8527. */
  8528. enableResizeEvents : function(mode, onResizeCallback) {
  8529. if (mode === this.RESIZE_BOTH || mode === this.RESIZE_WIDTH || mode === this.RESIZE_HEIGHT || mode===this.RESIZE_PROPORTIONAL) {
  8530. this.referenceWidth= this.width;
  8531. this.referenceHeight=this.height;
  8532. this.resize = mode;
  8533. CAAT.registerResizeListener(this);
  8534. this.onResizeCallback= onResizeCallback;
  8535. this.windowResized( window.innerWidth, window.innerHeight );
  8536. } else {
  8537. CAAT.unregisterResizeListener(this);
  8538. this.onResizeCallback= null;
  8539. }
  8540. },
  8541. /**
  8542. * Set this director's bounds as well as its contained scenes.
  8543. * @param x {number} ignored, will be 0.
  8544. * @param y {number} ignored, will be 0.
  8545. * @param w {number} director width.
  8546. * @param h {number} director height.
  8547. *
  8548. * @return this
  8549. */
  8550. setBounds : function(x, y, w, h) {
  8551. CAAT.Director.superclass.setBounds.call(this, x, y, w, h);
  8552. this.canvas.width = w;
  8553. this.canvas.height = h;
  8554. this.ctx = this.canvas.getContext(this.glEnabled ? 'experimental-webgl' : '2d');
  8555. this.crc = this.ctx;
  8556. for (var i = 0; i < this.scenes.length; i++) {
  8557. this.scenes[i].setBounds(0, 0, w, h);
  8558. }
  8559. if ( this.glEnabled ) {
  8560. this.glReset();
  8561. }
  8562. return this;
  8563. },
  8564. /**
  8565. * This method performs Director initialization. Must be called once.
  8566. * If the canvas parameter is not set, it will create a Canvas itself,
  8567. * and the developer must explicitly add the canvas to the desired DOM position.
  8568. * This method will also set the Canvas dimension to the specified values
  8569. * by width and height parameters.
  8570. *
  8571. * @param width {number} a canvas width
  8572. * @param height {number} a canvas height
  8573. * @param canvas {HTMLCanvasElement=} An optional Canvas object.
  8574. * @param proxy {HTMLElement} this object can be an event proxy in case you'd like to layer different elements
  8575. * and want events delivered to the correct element.
  8576. *
  8577. * @return this
  8578. */
  8579. initialize : function(width, height, canvas, proxy) {
  8580. if ( !canvas ) {
  8581. canvas= document.createElement('canvas');
  8582. document.body.appendChild(canvas);
  8583. }
  8584. this.canvas = canvas;
  8585. if ( typeof proxy==='undefined' ) {
  8586. proxy= canvas;
  8587. }
  8588. this.setBounds(0, 0, width, height);
  8589. this.create();
  8590. this.enableEvents(proxy);
  8591. this.timeline = new Date().getTime();
  8592. // transition scene
  8593. this.transitionScene = new CAAT.Scene().setBounds(0, 0, width, height);
  8594. var transitionCanvas = document.createElement('canvas');
  8595. transitionCanvas.width = width;
  8596. transitionCanvas.height = height;
  8597. var transitionImageActor = new CAAT.Actor().setBackgroundImage(transitionCanvas);
  8598. this.transitionScene.ctx = transitionCanvas.getContext('2d');
  8599. this.transitionScene.addChildImmediately(transitionImageActor);
  8600. this.transitionScene.setEaseListener(this);
  8601. this.checkDebug();
  8602. return this;
  8603. },
  8604. glReset : function() {
  8605. this.pMatrix= makeOrtho( 0, this.referenceWidth, this.referenceHeight, 0, -1, 1 );
  8606. this.gl.viewport(0,0,this.canvas.width,this.canvas.height);
  8607. this.glColorProgram.setMatrixUniform(this.pMatrix);
  8608. this.glTextureProgram.setMatrixUniform(this.pMatrix);
  8609. this.gl.viewportWidth = this.canvas.width;
  8610. this.gl.viewportHeight = this.canvas.height;
  8611. },
  8612. /**
  8613. * Experimental.
  8614. * Initialize a gl enabled director.
  8615. * @param width
  8616. * @param height
  8617. * @param canvas
  8618. */
  8619. initializeGL : function(width, height, canvas, proxy) {
  8620. if ( !canvas ) {
  8621. canvas= document.createElement('canvas');
  8622. document.body.appendChild(canvas);
  8623. }
  8624. canvas.width = width;
  8625. canvas.height = height;
  8626. if ( typeof proxy==='undefined' ) {
  8627. proxy= canvas;
  8628. }
  8629. this.referenceWidth= width;
  8630. this.referenceHeight=height;
  8631. var i;
  8632. try {
  8633. this.gl = canvas.getContext("experimental-webgl"/*, {antialias: false}*/);
  8634. this.gl.viewportWidth = width;
  8635. this.gl.viewportHeight = height;
  8636. CAAT.GLRENDER= true;
  8637. } catch(e) {
  8638. }
  8639. if (this.gl) {
  8640. this.canvas = canvas;
  8641. this.create();
  8642. this.setBounds(0, 0, width, height);
  8643. this.crc = this.ctx;
  8644. this.enableEvents(canvas);
  8645. this.timeline = new Date().getTime();
  8646. this.glColorProgram = new CAAT.ColorProgram(this.gl).create().initialize();
  8647. this.glTextureProgram = new CAAT.TextureProgram(this.gl).create().initialize();
  8648. this.glTextureProgram.useProgram();
  8649. this.glReset();
  8650. var maxTris = 512;
  8651. this.coords = new Float32Array(maxTris * 12);
  8652. this.uv = new Float32Array(maxTris * 8);
  8653. this.gl.clearColor(0.0, 0.0, 0.0, 255);
  8654. if (this.front_to_back) {
  8655. this.gl.clearDepth(1.0);
  8656. this.gl.enable(this.gl.DEPTH_TEST);
  8657. this.gl.depthFunc(this.gl.LESS);
  8658. } else {
  8659. this.gl.disable(this.gl.DEPTH_TEST);
  8660. }
  8661. this.gl.enable(this.gl.BLEND);
  8662. // Fix FF this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
  8663. this.gl.blendFunc(this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);
  8664. this.glEnabled = true;
  8665. this.checkDebug();
  8666. } else {
  8667. // fallback to non gl enabled canvas.
  8668. return this.initialize(width, height, canvas);
  8669. }
  8670. return this;
  8671. },
  8672. /**
  8673. * Creates an initializes a Scene object.
  8674. * @return {CAAT.Scene}
  8675. */
  8676. createScene : function() {
  8677. var scene = new CAAT.Scene().create();
  8678. this.addScene(scene);
  8679. return scene;
  8680. },
  8681. setImagesCache : function(imagesCache, tpW, tpH) {
  8682. var i;
  8683. if (null !== this.glTextureManager) {
  8684. this.glTextureManager.deletePages();
  8685. this.glTextureManager = null;
  8686. }
  8687. // delete previous image identifiers
  8688. if ( this.imagesCache ) {
  8689. var ids= [];
  8690. for ( i = 0; i < this.imagesCache.length; i++) {
  8691. ids.push( this.imagesCache[i].id );
  8692. }
  8693. for( i=0; i<ids.length; i++ ) {
  8694. delete this.imagesCache[ ids[i] ];
  8695. }
  8696. }
  8697. this.imagesCache = imagesCache;
  8698. if ( imagesCache ) {
  8699. for ( i = 0; i < imagesCache.length; i++) {
  8700. this.imagesCache[ imagesCache[i].id ] = imagesCache[i].image;
  8701. }
  8702. }
  8703. this.tpW = tpW || 2048;
  8704. this.tpH = tpH || 2048;
  8705. this.updateGLPages();
  8706. return this;
  8707. },
  8708. updateGLPages : function() {
  8709. if (this.glEnabled) {
  8710. this.glTextureManager = new CAAT.GLTexturePageManager();
  8711. this.glTextureManager.createPages(this.gl, this.tpW, this.tpH, this.imagesCache);
  8712. this.currentTexturePage = this.glTextureManager.pages[0];
  8713. this.glTextureProgram.setTexture(this.currentTexturePage.texture);
  8714. }
  8715. },
  8716. setGLTexturePage : function( tp ) {
  8717. this.currentTexturePage = tp;
  8718. this.glTextureProgram.setTexture(tp.texture);
  8719. return this;
  8720. },
  8721. /**
  8722. * Add a new image to director's image cache. If gl is enabled and the 'noUpdateGL' is not set to true this
  8723. * function will try to recreate the whole GL texture pages.
  8724. * If many handcrafted images are to be added to the director, some performance can be achieved by calling
  8725. * <code>director.addImage(id,image,false)</code> many times and a final call with
  8726. * <code>director.addImage(id,image,true)</code> to finally command the director to create texture pages.
  8727. *
  8728. * @param id {string|object} an identitifier to retrieve the image with
  8729. * @param image {Image|HTMLCanvasElement} image to add to cache
  8730. * @param noUpdateGL {!boolean} unless otherwise stated, the director will
  8731. * try to recreate the texture pages.
  8732. */
  8733. addImage : function( id, image, noUpdateGL ) {
  8734. if ( this.getImage(id) ) {
  8735. for (var i = 0; i < this.imagesCache.length; i++) {
  8736. if (this.imagesCache[i].id === id) {
  8737. this.imagesCache[i].image = image;
  8738. break;
  8739. }
  8740. }
  8741. this.imagesCache[ id ] = image;
  8742. } else {
  8743. this.imagesCache.push( { id: id, image: image } );
  8744. this.imagesCache[id]= image;
  8745. }
  8746. if ( !!!noUpdateGL ) {
  8747. this.updateGLPages( );
  8748. }
  8749. },
  8750. deleteImage : function( id, noUpdateGL ) {
  8751. for (var i = 0; i < this.imagesCache.length; i++) {
  8752. if (this.imagesCache[i].id === id) {
  8753. delete this.imagesCache[id];
  8754. this.imagesCache.splice(i,1);
  8755. break;
  8756. }
  8757. }
  8758. if ( !!!noUpdateGL ) {
  8759. this.updateGLPages();
  8760. }
  8761. },
  8762. setGLCurrentOpacity : function(opacity) {
  8763. this.currentOpacity = opacity;
  8764. this.glTextureProgram.setAlpha(opacity);
  8765. },
  8766. /**
  8767. * Render buffered elements.
  8768. * @param vertex
  8769. * @param coordsIndex
  8770. * @param uv
  8771. */
  8772. glRender : function(vertex, coordsIndex, uv) {
  8773. vertex = vertex || this.coords;
  8774. uv = uv || this.uv;
  8775. coordsIndex = coordsIndex || this.coordsIndex;
  8776. var gl = this.gl;
  8777. var numTris = coordsIndex / 12 * 2;
  8778. var numVertices = coordsIndex / 3;
  8779. this.glTextureProgram.updateVertexBuffer(vertex);
  8780. this.glTextureProgram.updateUVBuffer(uv);
  8781. gl.drawElements(gl.TRIANGLES, 3 * numTris, gl.UNSIGNED_SHORT, 0);
  8782. },
  8783. glFlush : function() {
  8784. if (this.coordsIndex !== 0) {
  8785. this.glRender(this.coords, this.coordsIndex, this.uv);
  8786. }
  8787. this.coordsIndex = 0;
  8788. this.uvIndex = 0;
  8789. this.statistics.draws++;
  8790. },
  8791. findActorAtPosition : function(point) {
  8792. // z-order
  8793. var cl= this.childrenList;
  8794. for( var i=cl.length-1; i>=0; i-- ) {
  8795. var child= this.childrenList[i];
  8796. var np= new CAAT.Point( point.x, point.y, 0 );
  8797. var contained= child.findActorAtPosition( np );
  8798. if ( null!==contained ) {
  8799. return contained;
  8800. }
  8801. }
  8802. return this;
  8803. },
  8804. /**
  8805. *
  8806. * Reset statistics information.
  8807. *
  8808. * @private
  8809. */
  8810. resetStats : function() {
  8811. this.statistics.size_total= 0;
  8812. this.statistics.size_active=0;
  8813. this.statistics.draws= 0;
  8814. },
  8815. /**
  8816. * This is the entry point for the animation system of the Director.
  8817. * The director is fed with the elapsed time value to maintain a virtual timeline.
  8818. * This virtual timeline will provide each Scene with its own virtual timeline, and will only
  8819. * feed time when the Scene is the current Scene, or is being switched.
  8820. *
  8821. * If dirty rectangles are enabled and canvas is used for rendering, the dirty rectangles will be
  8822. * set up as a single clip area.
  8823. *
  8824. * @param time {number} integer indicating the elapsed time between two consecutive frames of the
  8825. * Director.
  8826. */
  8827. render : function(time) {
  8828. this.time += time;
  8829. this.animate(this,time);
  8830. if ( CAAT.DEBUG ) {
  8831. this.resetStats();
  8832. }
  8833. /**
  8834. * draw director active scenes.
  8835. */
  8836. var ne = this.childrenList.length;
  8837. var i, tt, c;
  8838. var ctx= this.ctx;
  8839. if (this.glEnabled) {
  8840. this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
  8841. this.coordsIndex = 0;
  8842. this.uvIndex = 0;
  8843. for (i = 0; i < ne; i++) {
  8844. c = this.childrenList[i];
  8845. if (c.isInAnimationFrame(this.time)) {
  8846. tt = c.time - c.start_time;
  8847. if ( c.onRenderStart ) {
  8848. c.onRenderStart(tt);
  8849. }
  8850. c.paintActorGL(this, tt);
  8851. if ( c.onRenderEnd ) {
  8852. c.onRenderEnd(tt);
  8853. }
  8854. if ( !c.isPaused() ) {
  8855. c.time += time;
  8856. }
  8857. if ( CAAT.DEBUG ) {
  8858. this.statistics.size_total+= c.size_total;
  8859. this.statistics.size_active+= c.size_active;
  8860. }
  8861. }
  8862. }
  8863. this.glFlush();
  8864. } else {
  8865. ctx.globalAlpha = 1;
  8866. ctx.globalCompositeOperation = 'source-over';
  8867. ctx.save();
  8868. if ( this.dirtyRectsEnabled ) {
  8869. this.modelViewMatrix.transformRenderingContext( ctx );
  8870. if ( !CAAT.DEBUG_DIRTYRECTS ) {
  8871. ctx.beginPath();
  8872. this.nDirtyRects=0;
  8873. var dr= this.cDirtyRects;
  8874. for( i=0; i<dr.length; i++ ) {
  8875. var drr= dr[i];
  8876. if ( !drr.isEmpty() ) {
  8877. ctx.rect( drr.x|0, drr.y|0, 1+(drr.width|0), 1+(drr.height|0) );
  8878. this.nDirtyRects++;
  8879. }
  8880. }
  8881. ctx.clip();
  8882. } else {
  8883. ctx.clearRect(0, 0, this.width, this.height);
  8884. }
  8885. } else if (this.clear===true ) {
  8886. ctx.clearRect(0, 0, this.width, this.height);
  8887. }
  8888. for (i = 0; i < ne; i++) {
  8889. c= this.childrenList[i];
  8890. if (c.isInAnimationFrame(this.time)) {
  8891. tt = c.time - c.start_time;
  8892. ctx.save();
  8893. if ( c.onRenderStart ) {
  8894. c.onRenderStart(tt);
  8895. }
  8896. if ( !CAAT.DEBUG_DIRTYRECTS && this.dirtyRectsEnabled ) {
  8897. if ( this.nDirtyRects ) {
  8898. c.paintActor(this, tt);
  8899. }
  8900. } else {
  8901. c.paintActor(this, tt);
  8902. }
  8903. if ( c.onRenderEnd ) {
  8904. c.onRenderEnd(tt);
  8905. }
  8906. ctx.restore();
  8907. if (CAAT.DEBUGAABB) {
  8908. ctx.globalAlpha= 1;
  8909. ctx.globalCompositeOperation= 'source-over';
  8910. this.modelViewMatrix.transformRenderingContextSet( ctx );
  8911. c.drawScreenBoundingBox(this, tt);
  8912. }
  8913. if ( !c.isPaused() ) {
  8914. c.time += time;
  8915. }
  8916. if ( CAAT.DEBUG ) {
  8917. this.statistics.size_total+= c.size_total;
  8918. this.statistics.size_active+= c.size_active;
  8919. this.statistics.size_dirtyRects= this.nDirtyRects;
  8920. }
  8921. }
  8922. }
  8923. if ( this.nDirtyRects>0 && CAAT.DEBUG && CAAT.DEBUG_DIRTYRECTS ) {
  8924. ctx.beginPath();
  8925. this.nDirtyRects=0;
  8926. var dr= this.cDirtyRects;
  8927. for( i=0; i<dr.length; i++ ) {
  8928. var drr= dr[i];
  8929. if ( !drr.isEmpty() ) {
  8930. ctx.rect( drr.x|0, drr.y|0, 1+(drr.width|0), 1+(drr.height|0) );
  8931. this.nDirtyRects++;
  8932. }
  8933. }
  8934. ctx.clip();
  8935. ctx.fillStyle='rgba(160,255,150,.4)';
  8936. ctx.fillRect(0,0,this.width, this.height);
  8937. }
  8938. ctx.restore();
  8939. }
  8940. this.frameCounter++;
  8941. },
  8942. /**
  8943. * A director is a very special kind of actor.
  8944. * Its animation routine simple sets its modelViewMatrix in case some transformation's been
  8945. * applied.
  8946. * No behaviors are allowed for Director instances.
  8947. * @param director {CAAT.Director} redundant reference to CAAT.Director itself
  8948. * @param time {number} director time.
  8949. */
  8950. animate : function(director, time) {
  8951. this.setModelViewMatrix(this);
  8952. this.modelViewMatrixI= this.modelViewMatrix.getInverse();
  8953. this.setScreenBounds();
  8954. this.dirty= false;
  8955. this.invalid= false;
  8956. this.dirtyRectsIndex= -1;
  8957. this.cDirtyRects= [];
  8958. var cl= this.childrenList;
  8959. var cli;
  8960. for (var i = 0; i < cl.length; i++) {
  8961. cli= cl[i];
  8962. var tt = cli.time - cli.start_time;
  8963. cli.animate(this, tt);
  8964. }
  8965. return this;
  8966. },
  8967. /**
  8968. * Add a rectangle to the list of dirty screen areas which should be redrawn.
  8969. * This is the opposite method to clear the whole screen and repaint everything again.
  8970. * Despite i'm not very fond of dirty rectangles because it needs some extra calculations, this
  8971. * procedure has shown to be speeding things up under certain situations. Nevertheless it doesn't or
  8972. * even lowers performance under others, so it is a developer choice to activate them via a call to
  8973. * setClear( CAAT.Director.CLEAR_DIRTY_RECTS ).
  8974. *
  8975. * This function, not only tracks a list of dirty rectangles, but tries to optimize the list. Overlapping
  8976. * rectangles will be removed and intersecting ones will be unioned.
  8977. *
  8978. * Before calling this method, check if this.dirtyRectsEnabled is true.
  8979. *
  8980. * @param rectangle {CAAT.Rectangle}
  8981. */
  8982. addDirtyRect : function( rectangle ) {
  8983. if ( rectangle.isEmpty() ) {
  8984. return;
  8985. }
  8986. var i, dr, j, drj;
  8987. var cdr= this.cDirtyRects;
  8988. for( i=0; i<cdr.length; i++ ) {
  8989. dr= cdr[i];
  8990. if ( !dr.isEmpty() && dr.intersects( rectangle ) ) {
  8991. var intersected= true;
  8992. while( intersected ) {
  8993. dr.unionRectangle( rectangle );
  8994. for( j=0; j<cdr.length; j++ ) {
  8995. if ( j!==i ) {
  8996. drj= cdr[j];
  8997. if ( !drj.isEmpty() && drj.intersects( dr ) ) {
  8998. dr.unionRectangle( drj );
  8999. drj.setEmpty();
  9000. break;
  9001. }
  9002. }
  9003. }
  9004. if ( j==cdr.length ) {
  9005. intersected= false;
  9006. }
  9007. }
  9008. for( j=0; j<cdr.length; j++ ) {
  9009. if ( cdr[j].isEmpty() ) {
  9010. cdr.splice( j, 1 );
  9011. }
  9012. }
  9013. return;
  9014. }
  9015. }
  9016. this.dirtyRectsIndex++;
  9017. if ( this.dirtyRectsIndex>=this.dirtyRects.length ) {
  9018. for( i=0; i<32; i++ ) {
  9019. this.dirtyRects.push( new CAAT.Rectangle() );
  9020. }
  9021. }
  9022. var r= this.dirtyRects[ this.dirtyRectsIndex ];
  9023. r.x= rectangle.x;
  9024. r.y= rectangle.y;
  9025. r.x1= rectangle.x1;
  9026. r.y1= rectangle.y1;
  9027. r.width= rectangle.width;
  9028. r.height= rectangle.height;
  9029. this.cDirtyRects.push( r );
  9030. },
  9031. /**
  9032. * This method draws an Scene to an offscreen canvas. This offscreen canvas is also a child of
  9033. * another Scene (transitionScene). So instead of drawing two scenes while transitioning from
  9034. * one to another, first of all an scene is drawn to offscreen, and that image is translated.
  9035. * <p>
  9036. * Until the creation of this method, both scenes where drawn while transitioning with
  9037. * its performance penalty since drawing two scenes could be twice as expensive than drawing
  9038. * only one.
  9039. * <p>
  9040. * Though a high performance increase, we should keep an eye on memory consumption.
  9041. *
  9042. * @param ctx a <code>canvas.getContext('2d')</code> instnce.
  9043. * @param scene {CAAT.Scene} the scene to draw offscreen.
  9044. */
  9045. renderToContext : function(ctx, scene) {
  9046. /**
  9047. * draw actors on scene.
  9048. */
  9049. if (scene.isInAnimationFrame(this.time)) {
  9050. ctx.setTransform(1,0,0,1, 0,0);
  9051. ctx.globalAlpha = 1;
  9052. ctx.globalCompositeOperation = 'source-over';
  9053. ctx.clearRect(0, 0, this.width, this.height);
  9054. var octx = this.ctx;
  9055. var ocrc = this.crc;
  9056. this.ctx = ctx;
  9057. this.crc = ctx;
  9058. ctx.save();
  9059. /**
  9060. * to draw an scene to an offscreen canvas, we have to:
  9061. * 1.- save diector's world model view matrix
  9062. * 2.- set no transformation on director since we want the offscreen to
  9063. * be drawn 1:1.
  9064. * 3.- set world dirty flag, so that the scene will recalculate its matrices
  9065. * 4.- animate the scene
  9066. * 5.- paint the scene
  9067. * 6.- restore world model view matrix.
  9068. */
  9069. var matmv= this.modelViewMatrix;
  9070. var matwmv= this.worldModelViewMatrix;
  9071. this.worldModelViewMatrix= new CAAT.Matrix();
  9072. this.modelViewMatrix= this.worldModelViewMatrix;
  9073. this.wdirty= true;
  9074. scene.animate(this, scene.time);
  9075. if ( scene.onRenderStart ) {
  9076. scene.onRenderStart(scene.time);
  9077. }
  9078. scene.paintActor(this, scene.time);
  9079. if ( scene.onRenderEnd ) {
  9080. scene.onRenderEnd(scene.time);
  9081. }
  9082. this.worldModelViewMatrix = matwmv;
  9083. this.modelViewMatrix= matmv;
  9084. ctx.restore();
  9085. this.ctx = octx;
  9086. this.crc = ocrc;
  9087. }
  9088. },
  9089. /**
  9090. * Add a new Scene to Director's Scene list. By adding a Scene to the Director
  9091. * does not mean it will be immediately visible, you should explicitly call either
  9092. * <ul>
  9093. * <li>easeIn
  9094. * <li>easeInOut
  9095. * <li>easeInOutRandom
  9096. * <li>setScene
  9097. * <li>or any of the scene switching methods
  9098. * </ul>
  9099. *
  9100. * @param scene {CAAT.Scene} an CAAT.Scene object.
  9101. */
  9102. addScene : function(scene) {
  9103. scene.setBounds(0, 0, this.width, this.height);
  9104. this.scenes.push(scene);
  9105. scene.setEaseListener(this);
  9106. if (null === this.currentScene) {
  9107. this.setScene(0);
  9108. }
  9109. },
  9110. /**
  9111. * Get the number of scenes contained in the Director.
  9112. * @return {number} the number of scenes contained in the Director.
  9113. */
  9114. getNumScenes : function() {
  9115. return this.scenes.length;
  9116. },
  9117. /**
  9118. * This method offers full control over the process of switching between any given two Scenes.
  9119. * To apply this method, you must specify the type of transition to apply for each Scene and
  9120. * the anchor to keep the Scene pinned at.
  9121. * <p>
  9122. * The type of transition will be one of the following values defined in CAAT.Scene.prototype:
  9123. * <ul>
  9124. * <li>EASE_ROTATION
  9125. * <li>EASE_SCALE
  9126. * <li>EASE_TRANSLATION
  9127. * </ul>
  9128. *
  9129. * <p>
  9130. * The anchor will be any of these values defined in CAAT.Actor.prototype:
  9131. * <ul>
  9132. * <li>ANCHOR_CENTER
  9133. * <li>ANCHOR_TOP
  9134. * <li>ANCHOR_BOTTOM
  9135. * <li>ANCHOR_LEFT
  9136. * <li>ANCHOR_RIGHT
  9137. * <li>ANCHOR_TOP_LEFT
  9138. * <li>ANCHOR_TOP_RIGHT
  9139. * <li>ANCHOR_BOTTOM_LEFT
  9140. * <li>ANCHOR_BOTTOM_RIGHT
  9141. * </ul>
  9142. *
  9143. * <p>
  9144. * In example, for an entering scene performing a EASE_SCALE transition, the anchor is the
  9145. * point by which the scene will scaled.
  9146. *
  9147. * @param inSceneIndex integer indicating the Scene index to bring in to the Director.
  9148. * @param typein integer indicating the type of transition to apply to the bringing in Scene.
  9149. * @param anchorin integer indicating the anchor of the bringing in Scene.
  9150. * @param outSceneIndex integer indicating the Scene index to take away from the Director.
  9151. * @param typeout integer indicating the type of transition to apply to the taking away in Scene.
  9152. * @param anchorout integer indicating the anchor of the taking away Scene.
  9153. * @param time inteter indicating the time to perform the process of switchihg between Scene object
  9154. * in milliseconds.
  9155. * @param alpha boolean boolean indicating whether alpha transparency fading will be applied to
  9156. * the scenes.
  9157. * @param interpolatorIn CAAT.Interpolator object to apply to entering scene.
  9158. * @param interpolatorOut CAAT.Interpolator object to apply to exiting scene.
  9159. */
  9160. easeInOut : function(inSceneIndex, typein, anchorin, outSceneIndex, typeout, anchorout, time, alpha, interpolatorIn, interpolatorOut) {
  9161. if (inSceneIndex === this.getCurrentSceneIndex()) {
  9162. return;
  9163. }
  9164. var ssin = this.scenes[ inSceneIndex ];
  9165. var sout = this.scenes[ outSceneIndex ];
  9166. if ( !CAAT.__CSS__ && !this.glEnabled ) {
  9167. this.renderToContext(this.transitionScene.ctx, sout);
  9168. sout = this.transitionScene;
  9169. }
  9170. ssin.setExpired(false);
  9171. sout.setExpired(false);
  9172. ssin.mouseEnabled = false;
  9173. sout.mouseEnabled = false;
  9174. ssin.resetTransform();
  9175. sout.resetTransform();
  9176. ssin.setLocation(0, 0);
  9177. sout.setLocation(0, 0);
  9178. ssin.alpha = 1;
  9179. sout.alpha = 1;
  9180. if (typein === CAAT.Scene.prototype.EASE_ROTATION) {
  9181. ssin.easeRotationIn(time, alpha, anchorin, interpolatorIn);
  9182. } else if (typein === CAAT.Scene.prototype.EASE_SCALE) {
  9183. ssin.easeScaleIn(0, time, alpha, anchorin, interpolatorIn);
  9184. } else {
  9185. ssin.easeTranslationIn(time, alpha, anchorin, interpolatorIn);
  9186. }
  9187. if (typeout === CAAT.Scene.prototype.EASE_ROTATION) {
  9188. sout.easeRotationOut(time, alpha, anchorout, interpolatorOut);
  9189. } else if (typeout === CAAT.Scene.prototype.EASE_SCALE) {
  9190. sout.easeScaleOut(0, time, alpha, anchorout, interpolatorOut);
  9191. } else {
  9192. sout.easeTranslationOut(time, alpha, anchorout, interpolatorOut);
  9193. }
  9194. this.childrenList = [];
  9195. this.addChild(sout);
  9196. this.addChild(ssin);
  9197. },
  9198. /**
  9199. * This method will switch between two given Scene indexes (ie, take away scene number 2,
  9200. * and bring in scene number 5).
  9201. * <p>
  9202. * It will randomly choose for each Scene the type of transition to apply and the anchor
  9203. * point of each transition type.
  9204. * <p>
  9205. * It will also set for different kind of transitions the following interpolators:
  9206. * <ul>
  9207. * <li>EASE_ROTATION -> ExponentialInOutInterpolator, exponent 4.
  9208. * <li>EASE_SCALE -> ElasticOutInterpolator, 1.1 and .4
  9209. * <li>EASE_TRANSLATION -> BounceOutInterpolator
  9210. * </ul>
  9211. *
  9212. * <p>
  9213. * These are the default values, and could not be changed by now.
  9214. * This method in final instance delegates the process to easeInOutMethod.
  9215. *
  9216. * @see easeInOutMethod.
  9217. *
  9218. * @param inIndex integer indicating the entering scene index.
  9219. * @param outIndex integer indicating the exiting scene index.
  9220. * @param time integer indicating the time to take for the process of Scene in/out in milliseconds.
  9221. * @param alpha boolean indicating whether alpha transparency fading should be applied to transitions.
  9222. */
  9223. easeInOutRandom : function(inIndex, outIndex, time, alpha) {
  9224. var pin = Math.random();
  9225. var pout = Math.random();
  9226. var typeIn;
  9227. var interpolatorIn;
  9228. if (pin < 0.33) {
  9229. typeIn = CAAT.Scene.prototype.EASE_ROTATION;
  9230. interpolatorIn = new CAAT.Interpolator().createExponentialInOutInterpolator(4);
  9231. } else if (pin < 0.66) {
  9232. typeIn = CAAT.Scene.prototype.EASE_SCALE;
  9233. interpolatorIn = new CAAT.Interpolator().createElasticOutInterpolator(1.1, 0.4);
  9234. } else {
  9235. typeIn = CAAT.Scene.prototype.EASE_TRANSLATE;
  9236. interpolatorIn = new CAAT.Interpolator().createBounceOutInterpolator();
  9237. }
  9238. var typeOut;
  9239. var interpolatorOut;
  9240. if (pout < 0.33) {
  9241. typeOut = CAAT.Scene.prototype.EASE_ROTATION;
  9242. interpolatorOut = new CAAT.Interpolator().createExponentialInOutInterpolator(4);
  9243. } else if (pout < 0.66) {
  9244. typeOut = CAAT.Scene.prototype.EASE_SCALE;
  9245. interpolatorOut = new CAAT.Interpolator().createExponentialOutInterpolator(4);
  9246. } else {
  9247. typeOut = CAAT.Scene.prototype.EASE_TRANSLATE;
  9248. interpolatorOut = new CAAT.Interpolator().createBounceOutInterpolator();
  9249. }
  9250. this.easeInOut(
  9251. inIndex,
  9252. typeIn,
  9253. (Math.random() * 8.99) >> 0,
  9254. outIndex,
  9255. typeOut,
  9256. (Math.random() * 8.99) >> 0,
  9257. time,
  9258. alpha,
  9259. interpolatorIn,
  9260. interpolatorOut);
  9261. },
  9262. /**
  9263. * This method changes Director's current Scene to the scene index indicated by
  9264. * inSceneIndex parameter. The Scene running in the director won't be eased out.
  9265. *
  9266. * @see {CAAT.Interpolator}
  9267. * @see {CAAT.Actor}
  9268. * @see {CAAT.Scene}
  9269. *
  9270. * @param inSceneIndex integer indicating the new Scene to set as current.
  9271. * @param type integer indicating the type of transition to apply to bring the new current
  9272. * Scene to the Director. The values will be one of: CAAT.Scene.prototype.EASE_ROTATION,
  9273. * CAAT.Scene.prototype.EASE_SCALE, CAAT.Scene.prototype.EASE_TRANSLATION.
  9274. * @param time integer indicating how much time in milliseconds the Scene entrance will take.
  9275. * @param alpha boolean indicating whether alpha transparency fading will be applied to the
  9276. * entereing Scene.
  9277. * @param anchor integer indicating the anchor to fix for Scene transition. It will be any of
  9278. * CAAT.Actor.prototype.ANCHOR_* values.
  9279. * @param interpolator an CAAT.Interpolator object indicating the interpolation function to
  9280. * apply.
  9281. */
  9282. easeIn : function(inSceneIndex, type, time, alpha, anchor, interpolator) {
  9283. var sin = this.scenes[ inSceneIndex ];
  9284. if (type === CAAT.Scene.prototype.EASE_ROTATION) {
  9285. sin.easeRotationIn(time, alpha, anchor, interpolator);
  9286. } else if (type === CAAT.Scene.prototype.EASE_SCALE) {
  9287. sin.easeScaleIn(0, time, alpha, anchor, interpolator);
  9288. } else {
  9289. sin.easeTranslationIn(time, alpha, anchor, interpolator);
  9290. }
  9291. this.childrenList = [];
  9292. this.addChild(sin);
  9293. sin.resetTransform();
  9294. sin.setLocation(0, 0);
  9295. sin.alpha = 1;
  9296. sin.mouseEnabled = false;
  9297. sin.setExpired(false);
  9298. },
  9299. /**
  9300. * Changes (or sets) the current Director scene to the index
  9301. * parameter. There will be no transition on scene change.
  9302. * @param sceneIndex {number} an integer indicating the index of the target Scene
  9303. * to be shown.
  9304. */
  9305. setScene : function(sceneIndex) {
  9306. var sin = this.scenes[ sceneIndex ];
  9307. this.childrenList = [];
  9308. this.addChild(sin);
  9309. this.currentScene = sin;
  9310. sin.setExpired(false);
  9311. sin.mouseEnabled = true;
  9312. sin.resetTransform();
  9313. sin.setLocation(0, 0);
  9314. sin.alpha = 1;
  9315. sin.activated();
  9316. },
  9317. /**
  9318. * This method will change the current Scene by the Scene indicated as parameter.
  9319. * It will apply random values for anchor and transition type.
  9320. * @see easeInOutRandom
  9321. *
  9322. * @param iNewSceneIndex {number} an integer indicating the index of the new scene to run on the Director.
  9323. * @param time {number} an integer indicating the time the Scene transition will take.
  9324. * @param alpha {boolean} a boolean indicating whether Scene transition should be fading.
  9325. * @param transition {boolean} a boolean indicating whether the scene change must smoothly animated.
  9326. */
  9327. switchToScene : function(iNewSceneIndex, time, alpha, transition) {
  9328. var currentSceneIndex = this.getSceneIndex(this.currentScene);
  9329. if (!transition) {
  9330. this.setScene(iNewSceneIndex);
  9331. }
  9332. else {
  9333. this.easeInOutRandom(iNewSceneIndex, currentSceneIndex, time, alpha);
  9334. }
  9335. },
  9336. /**
  9337. * Sets the previous Scene in sequence as the current Scene.
  9338. * @see switchToScene.
  9339. *
  9340. * @param time {number} integer indicating the time the Scene transition will take.
  9341. * @param alpha {boolean} a boolean indicating whether Scene transition should be fading.
  9342. * @param transition {boolean} a boolean indicating whether the scene change must smoothly animated.
  9343. */
  9344. switchToPrevScene : function(time, alpha, transition) {
  9345. var currentSceneIndex = this.getSceneIndex(this.currentScene);
  9346. if (this.getNumScenes() <= 1 || currentSceneIndex === 0) {
  9347. return;
  9348. }
  9349. if (!transition) {
  9350. this.setScene(currentSceneIndex - 1);
  9351. }
  9352. else {
  9353. this.easeInOutRandom(currentSceneIndex - 1, currentSceneIndex, time, alpha);
  9354. }
  9355. },
  9356. /**
  9357. * Sets the previous Scene in sequence as the current Scene.
  9358. * @see switchToScene.
  9359. *
  9360. * @param time {number} integer indicating the time the Scene transition will take.
  9361. * @param alpha {boolean} a boolean indicating whether Scene transition should be fading.
  9362. * @param transition {boolean} a boolean indicating whether the scene change must smoothly animated.
  9363. */
  9364. switchToNextScene: function(time, alpha, transition) {
  9365. var currentSceneIndex = this.getSceneIndex(this.currentScene);
  9366. if (this.getNumScenes() <= 1 || currentSceneIndex === this.getNumScenes() - 1) {
  9367. return;
  9368. }
  9369. if (!transition) {
  9370. this.setScene(currentSceneIndex + 1);
  9371. }
  9372. else {
  9373. this.easeInOutRandom(currentSceneIndex + 1, currentSceneIndex, time, alpha);
  9374. }
  9375. },
  9376. mouseEnter : function(mouseEvent) {
  9377. },
  9378. mouseExit : function(mouseEvent) {
  9379. },
  9380. mouseMove : function(mouseEvent) {
  9381. },
  9382. mouseDown : function(mouseEvent) {
  9383. },
  9384. mouseUp : function(mouseEvent) {
  9385. },
  9386. mouseDrag : function(mouseEvent) {
  9387. },
  9388. /**
  9389. * Scene easing listener. Notifies scenes when they're about to be activated (set as current
  9390. * director's scene).
  9391. *
  9392. * @param scene {CAAT.Scene} the scene that has just been brought in or taken out of the director.
  9393. * @param b_easeIn {boolean} scene enters or exits ?
  9394. */
  9395. easeEnd : function(scene, b_easeIn) {
  9396. // scene is going out
  9397. if (!b_easeIn) {
  9398. scene.setExpired(true);
  9399. } else {
  9400. this.currentScene = scene;
  9401. this.currentScene.activated();
  9402. }
  9403. scene.mouseEnabled = true;
  9404. scene.emptyBehaviorList();
  9405. },
  9406. /**
  9407. * Return the index for a given Scene object contained in the Director.
  9408. * @param scene {CAAT.Scene}
  9409. */
  9410. getSceneIndex : function(scene) {
  9411. for (var i = 0; i < this.scenes.length; i++) {
  9412. if (this.scenes[i] === scene) {
  9413. return i;
  9414. }
  9415. }
  9416. return -1;
  9417. },
  9418. /**
  9419. * Get a concrete director's scene.
  9420. * @param index {number} an integer indicating the scene index.
  9421. * @return {CAAT.Scene} a CAAT.Scene object instance or null if the index is oob.
  9422. */
  9423. getScene : function(index) {
  9424. return this.scenes[index];
  9425. },
  9426. /**
  9427. * Return the index of the current scene in the Director's scene list.
  9428. * @return {number} the current scene's index.
  9429. */
  9430. getCurrentSceneIndex : function() {
  9431. return this.getSceneIndex(this.currentScene);
  9432. },
  9433. /**
  9434. * Return the running browser name.
  9435. * @return {string} the browser name.
  9436. */
  9437. getBrowserName : function() {
  9438. return this.browserInfo.browser;
  9439. },
  9440. /**
  9441. * Return the running browser version.
  9442. * @return {string} the browser version.
  9443. */
  9444. getBrowserVersion : function() {
  9445. return this.browserInfo.version;
  9446. },
  9447. /**
  9448. * Return the operating system name.
  9449. * @return {string} the os name.
  9450. */
  9451. getOSName : function() {
  9452. return this.browserInfo.OS;
  9453. },
  9454. /**
  9455. * Gets the resource with the specified resource name.
  9456. * The Director holds a collection called <code>imagesCache</code>
  9457. * where you can store a JSON of the form
  9458. * <code>[ { id: imageId, image: imageObject } ]</code>.
  9459. * This structure will be used as a resources cache.
  9460. * There's a CAAT.ImagePreloader class to preload resources and
  9461. * generate this structure on loading finalization.
  9462. *
  9463. * @param sId {object} an String identifying a resource.
  9464. */
  9465. getImage : function(sId) {
  9466. var ret = this.imagesCache[sId];
  9467. if (ret) {
  9468. return ret;
  9469. }
  9470. for (var i = 0; i < this.imagesCache.length; i++) {
  9471. if (this.imagesCache[i].id === sId) {
  9472. return this.imagesCache[i].image;
  9473. }
  9474. }
  9475. return null;
  9476. },
  9477. /**
  9478. * Adds an audio to the cache.
  9479. *
  9480. * @see CAAT.AudioManager.addAudio
  9481. * @return this
  9482. */
  9483. addAudio : function(id, url) {
  9484. this.audioManager.addAudio(id, url);
  9485. return this;
  9486. },
  9487. /**
  9488. * Plays the audio instance identified by the id.
  9489. * @param id {object} the object used to store a sound in the audioCache.
  9490. */
  9491. audioPlay : function(id) {
  9492. this.audioManager.play(id);
  9493. },
  9494. /**
  9495. * Loops an audio instance identified by the id.
  9496. * @param id {object} the object used to store a sound in the audioCache.
  9497. *
  9498. * @return {HTMLElement|null} the value from audioManager.loop
  9499. */
  9500. audioLoop : function(id) {
  9501. return this.audioManager.loop(id);
  9502. },
  9503. endSound : function() {
  9504. return this.audioManager.endSound();
  9505. },
  9506. setSoundEffectsEnabled : function(enabled) {
  9507. return this.audioManager.setSoundEffectsEnabled(enabled);
  9508. },
  9509. setMusicEnabled : function(enabled) {
  9510. return this.audioManager.setMusicEnabled(enabled);
  9511. },
  9512. isMusicEnabled : function() {
  9513. return this.audioManager.isMusicEnabled();
  9514. },
  9515. isSoundEffectsEnabled : function() {
  9516. return this.audioManager.isSoundEffectsEnabled();
  9517. },
  9518. setVolume : function( id, volume ) {
  9519. return this.audioManager.setVolume( id, volume );
  9520. },
  9521. /**
  9522. * Removes Director's scenes.
  9523. */
  9524. emptyScenes : function() {
  9525. this.scenes = [];
  9526. },
  9527. /**
  9528. * Adds an scene to this Director.
  9529. * @param scene {CAAT.Scene} a scene object.
  9530. */
  9531. addChild : function(scene) {
  9532. scene.parent = this;
  9533. this.childrenList.push(scene);
  9534. },
  9535. /**
  9536. * @Deprecated use CAAT.loop instead.
  9537. * @param fps
  9538. * @param callback
  9539. * @param callback2
  9540. */
  9541. loop : function(fps,callback,callback2) {
  9542. if ( callback2 ) {
  9543. this.onRenderStart= callback;
  9544. this.onRenderEnd= callback2;
  9545. } else if (callback) {
  9546. this.onRenderEnd= callback;
  9547. }
  9548. CAAT.loop();
  9549. },
  9550. /**
  9551. * Starts the director animation.If no scene is explicitly selected, the current Scene will
  9552. * be the first scene added to the Director.
  9553. * <p>
  9554. * The fps parameter will set the animation quality. Higher values,
  9555. * means CAAT will try to render more frames in the same second (at the
  9556. * expense of cpu power at least until hardware accelerated canvas rendering
  9557. * context are available). A value of 60 is a high frame rate and should not be exceeded.
  9558. *
  9559. * @param fps {number} integer value indicating the target frames per second to run
  9560. * the animation at.
  9561. */
  9562. renderFrame : function(fps, callback) {
  9563. if (this.stopped) {
  9564. return;
  9565. }
  9566. var t = new Date().getTime(),
  9567. delta = t - this.timeline;
  9568. /*
  9569. check for massive frame time. if for example the current browser tab is minified or taken out of
  9570. foreground, the system will account for a bit time interval. minify that impact by lowering down
  9571. the elapsed time (virtual timelines FTW)
  9572. */
  9573. if ( delta > 500 ) {
  9574. delta= 500;
  9575. }
  9576. if ( this.onRenderStart ) {
  9577. this.onRenderStart(delta);
  9578. }
  9579. this.render(delta);
  9580. if ( this.debugInfo ) {
  9581. this.debugInfo(this.statistics);
  9582. }
  9583. this.timeline = t;
  9584. if (this.onRenderEnd) {
  9585. this.onRenderEnd(delta);
  9586. }
  9587. },
  9588. endLoop : function () {
  9589. },
  9590. /**
  9591. * This method states whether the director must clear background before rendering
  9592. * each frame.
  9593. *
  9594. * The clearing method could be:
  9595. * + CAAT.Director.CLEAR_ALL. previous to draw anything on screen the canvas will have clearRect called on it.
  9596. * + CAAT.Director.CLEAR_DIRTY_RECTS. Actors marked as invalid, or which have been moved, rotated or scaled
  9597. * will have their areas redrawn.
  9598. * + CAAT.Director.CLEAR_NONE. clears nothing.
  9599. *
  9600. * @param clear {CAAT.Director.CLEAR_ALL |�CAAT.Director.CLEAR_NONE | CAAT.Director.CLEAR_DIRTY_RECTS}
  9601. * @return this.
  9602. */
  9603. setClear : function(clear) {
  9604. this.clear = clear;
  9605. if ( this.clear===CAAT.Director.CLEAR_DIRTY_RECTS ) {
  9606. this.dirtyRectsEnabled= true;
  9607. }
  9608. return this;
  9609. },
  9610. /**
  9611. * Get this Director's AudioManager instance.
  9612. * @return {CAAT.AudioManager} the AudioManager instance.
  9613. */
  9614. getAudioManager : function() {
  9615. return this.audioManager;
  9616. },
  9617. /**
  9618. * Acculumate dom elements position to properly offset on-screen mouse/touch events.
  9619. * @param node
  9620. */
  9621. cumulateOffset : function(node, parent, prop) {
  9622. var left= prop+'Left';
  9623. var top= prop+'Top';
  9624. var x=0, y=0, style;
  9625. while( navigator.browser!=='iOS' && node && node.style ) {
  9626. if ( node.currentStyle ) {
  9627. style= node.currentStyle['position'];
  9628. } else {
  9629. style= (node.ownerDocument.defaultView || node.ownerDocument.parentWindow).getComputedStyle(node, null);
  9630. style= style ? style.getPropertyValue('position') : null;
  9631. }
  9632. // if (!/^(relative|absolute|fixed)$/.test(style)) {
  9633. if (!/^(fixed)$/.test(style)) {
  9634. x += node[left];
  9635. y+= node[top];
  9636. node = node[parent];
  9637. } else {
  9638. break;
  9639. }
  9640. }
  9641. return {
  9642. x: x,
  9643. y: y,
  9644. style: style
  9645. };
  9646. },
  9647. getOffset : function( node ) {
  9648. var res= this.cumulateOffset(node, 'offsetParent', 'offset');
  9649. if ( res.style==='fixed' ) {
  9650. var res2= this.cumulateOffset(node, node.parentNode ? 'parentNode' : 'parentElement', 'scroll');
  9651. return {
  9652. x: res.x + res2.x,
  9653. y: res.y + res2.y
  9654. };
  9655. }
  9656. return {
  9657. x: res.x,
  9658. y: res.y
  9659. };
  9660. },
  9661. /**
  9662. * Normalize input event coordinates to be related to (0,0) canvas position.
  9663. * @param point {CAAT.Point} a CAAT.Point instance to hold the canvas coordinate.
  9664. * @param e {MouseEvent} a mouse event from an input event.
  9665. */
  9666. getCanvasCoord : function(point, e) {
  9667. var pt= new CAAT.Point( );
  9668. var posx = 0;
  9669. var posy = 0;
  9670. if (!e) e = window.event;
  9671. if (e.pageX || e.pageY) {
  9672. posx = e.pageX;
  9673. posy = e.pageY;
  9674. }
  9675. else if (e.clientX || e.clientY) {
  9676. posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
  9677. posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
  9678. }
  9679. var offset= this.getOffset(this.canvas);
  9680. posx-= offset.x;
  9681. posy-= offset.y;
  9682. //////////////
  9683. // transformar coordenada inversamente con affine transform de director.
  9684. pt.x= posx;
  9685. pt.y= posy;
  9686. if ( !this.modelViewMatrixI ) {
  9687. this.modelViewMatrixI= this.modelViewMatrix.getInverse();
  9688. }
  9689. this.modelViewMatrixI.transformCoord(pt);
  9690. posx= pt.x;
  9691. posy= pt.y
  9692. point.set(posx, posy);
  9693. this.screenMousePoint.set(posx, posy);
  9694. },
  9695. __mouseDownHandler : function(e) {
  9696. /*
  9697. was dragging and mousedown detected, can only mean a mouseOut's been performed and on mouseOver, no
  9698. button was presses. Then, send a mouseUp for the previos actor, and return;
  9699. */
  9700. if ( this.dragging && this.lastSelectedActor ) {
  9701. this.__mouseUpHandler(e);
  9702. return;
  9703. }
  9704. this.getCanvasCoord(this.mousePoint, e);
  9705. this.isMouseDown = true;
  9706. var lactor = this.findActorAtPosition(this.mousePoint);
  9707. if (null !== lactor) {
  9708. var pos = lactor.viewToModel(
  9709. new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
  9710. lactor.mouseDown(
  9711. new CAAT.MouseEvent().init(
  9712. pos.x,
  9713. pos.y,
  9714. e,
  9715. lactor,
  9716. new CAAT.Point(
  9717. this.screenMousePoint.x,
  9718. this.screenMousePoint.y )));
  9719. }
  9720. this.lastSelectedActor= lactor;
  9721. },
  9722. __mouseUpHandler : function(e) {
  9723. this.isMouseDown = false;
  9724. this.getCanvasCoord(this.mousePoint, e);
  9725. var pos= null;
  9726. var lactor= this.lastSelectedActor;
  9727. if (null !== lactor) {
  9728. pos = lactor.viewToModel(
  9729. new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
  9730. if ( lactor.actionPerformed && lactor.contains(pos.x, pos.y) ) {
  9731. lactor.actionPerformed(e)
  9732. }
  9733. lactor.mouseUp(
  9734. new CAAT.MouseEvent().init(
  9735. pos.x,
  9736. pos.y,
  9737. e,
  9738. lactor,
  9739. this.screenMousePoint,
  9740. this.currentScene.time));
  9741. }
  9742. if (!this.dragging && null !== lactor) {
  9743. if (lactor.contains(pos.x, pos.y)) {
  9744. lactor.mouseClick(
  9745. new CAAT.MouseEvent().init(
  9746. pos.x,
  9747. pos.y,
  9748. e,
  9749. lactor,
  9750. this.screenMousePoint,
  9751. this.currentScene.time));
  9752. }
  9753. }
  9754. this.dragging = false;
  9755. this.in_= false;
  9756. // CAAT.setCursor('default');
  9757. },
  9758. __mouseMoveHandler : function(e) {
  9759. //this.getCanvasCoord(this.mousePoint, e);
  9760. var lactor;
  9761. var pos;
  9762. var ct= this.currentScene ? this.currentScene.time : 0;
  9763. // drag
  9764. if (this.isMouseDown && null !== this.lastSelectedActor) {
  9765. lactor = this.lastSelectedActor;
  9766. pos = lactor.viewToModel(
  9767. new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
  9768. // check for mouse move threshold.
  9769. if (!this.dragging) {
  9770. if (Math.abs(this.prevMousePoint.x - pos.x) < CAAT.DRAG_THRESHOLD_X &&
  9771. Math.abs(this.prevMousePoint.y - pos.y) < CAAT.DRAG_THRESHOLD_Y) {
  9772. return;
  9773. }
  9774. }
  9775. this.dragging = true;
  9776. var px= lactor.x;
  9777. var py= lactor.y;
  9778. lactor.mouseDrag(
  9779. new CAAT.MouseEvent().init(
  9780. pos.x,
  9781. pos.y,
  9782. e,
  9783. lactor,
  9784. new CAAT.Point(
  9785. this.screenMousePoint.x,
  9786. this.screenMousePoint.y),
  9787. ct));
  9788. this.prevMousePoint.x= pos.x;
  9789. this.prevMousePoint.y= pos.y;
  9790. /**
  9791. * Element has not moved after drag, so treat it as a button.
  9792. */
  9793. if ( px===lactor.x && py===lactor.y ) {
  9794. var contains= lactor.contains(pos.x, pos.y);
  9795. if (this.in_ && !contains) {
  9796. lactor.mouseExit(
  9797. new CAAT.MouseEvent().init(
  9798. pos.x,
  9799. pos.y,
  9800. e,
  9801. lactor,
  9802. this.screenMousePoint,
  9803. ct));
  9804. this.in_ = false;
  9805. }
  9806. if (!this.in_ && contains ) {
  9807. lactor.mouseEnter(
  9808. new CAAT.MouseEvent().init(
  9809. pos.x,
  9810. pos.y,
  9811. e,
  9812. lactor,
  9813. this.screenMousePoint,
  9814. ct));
  9815. this.in_ = true;
  9816. }
  9817. }
  9818. return;
  9819. }
  9820. // mouse move.
  9821. this.in_= true;
  9822. lactor = this.findActorAtPosition(this.mousePoint);
  9823. // cambiamos de actor.
  9824. if (lactor !== this.lastSelectedActor) {
  9825. if (null !== this.lastSelectedActor) {
  9826. pos = this.lastSelectedActor.viewToModel(
  9827. new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
  9828. this.lastSelectedActor.mouseExit(
  9829. new CAAT.MouseEvent().init(
  9830. pos.x,
  9831. pos.y,
  9832. e,
  9833. this.lastSelectedActor,
  9834. this.screenMousePoint,
  9835. ct));
  9836. }
  9837. if (null !== lactor) {
  9838. pos = lactor.viewToModel(
  9839. new CAAT.Point( this.screenMousePoint.x, this.screenMousePoint.y, 0));
  9840. lactor.mouseEnter(
  9841. new CAAT.MouseEvent().init(
  9842. pos.x,
  9843. pos.y,
  9844. e,
  9845. lactor,
  9846. this.screenMousePoint,
  9847. ct));
  9848. }
  9849. }
  9850. pos = lactor.viewToModel(
  9851. new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
  9852. if (null !== lactor) {
  9853. lactor.mouseMove(
  9854. new CAAT.MouseEvent().init(
  9855. pos.x,
  9856. pos.y,
  9857. e,
  9858. lactor,
  9859. this.screenMousePoint,
  9860. ct));
  9861. }
  9862. this.prevMousePoint.x= pos.x;
  9863. this.prevMousePoint.y= pos.y;
  9864. this.lastSelectedActor = lactor;
  9865. },
  9866. __mouseOutHandler : function(e) {
  9867. if ( this.dragging ) {
  9868. return;
  9869. }
  9870. if (null !== this.lastSelectedActor ) {
  9871. this.getCanvasCoord(this.mousePoint, e);
  9872. var pos = new CAAT.Point(this.mousePoint.x, this.mousePoint.y, 0);
  9873. this.lastSelectedActor.viewToModel(pos);
  9874. var ev= new CAAT.MouseEvent().init(
  9875. pos.x,
  9876. pos.y,
  9877. e,
  9878. this.lastSelectedActor,
  9879. this.screenMousePoint,
  9880. this.currentScene.time);
  9881. this.lastSelectedActor.mouseExit(ev);
  9882. this.lastSelectedActor.mouseOut(ev);
  9883. if ( !this.dragging ) {
  9884. this.lastSelectedActor = null;
  9885. }
  9886. } else {
  9887. this.isMouseDown = false;
  9888. this.in_ = false;
  9889. }
  9890. },
  9891. __mouseOverHandler : function(e) {
  9892. if (this.dragging ) {
  9893. return;
  9894. }
  9895. var lactor;
  9896. var pos, ev;
  9897. if ( null==this.lastSelectedActor ) {
  9898. lactor= this.findActorAtPosition( this.mousePoint );
  9899. if (null !== lactor) {
  9900. pos = lactor.viewToModel(
  9901. new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
  9902. ev= new CAAT.MouseEvent().init(
  9903. pos.x,
  9904. pos.y,
  9905. e,
  9906. lactor,
  9907. this.screenMousePoint,
  9908. this.currentScene ? this.currentScene.time : 0);
  9909. lactor.mouseOver(ev);
  9910. lactor.mouseEnter(ev);
  9911. }
  9912. this.lastSelectedActor= lactor;
  9913. } else {
  9914. lactor= this.lastSelectedActor;
  9915. pos = lactor.viewToModel(
  9916. new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
  9917. ev= new CAAT.MouseEvent().init(
  9918. pos.x,
  9919. pos.y,
  9920. e,
  9921. lactor,
  9922. this.screenMousePoint,
  9923. this.currentScene.time);
  9924. lactor.mouseOver(ev);
  9925. lactor.mouseEnter(ev);
  9926. }
  9927. },
  9928. __mouseDBLClickHandler : function(e) {
  9929. this.getCanvasCoord(this.mousePoint, e);
  9930. if (null !== this.lastSelectedActor) {
  9931. /*
  9932. var pos = this.lastSelectedActor.viewToModel(
  9933. new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
  9934. */
  9935. this.lastSelectedActor.mouseDblClick(
  9936. new CAAT.MouseEvent().init(
  9937. this.mousePoint.x,
  9938. this.mousePoint.y,
  9939. e,
  9940. this.lastSelectedActor,
  9941. this.screenMousePoint,
  9942. this.currentScene.time));
  9943. }
  9944. },
  9945. /**
  9946. * Same as mouseDown but not preventing event.
  9947. * Will only take care of first touch.
  9948. * @param e
  9949. */
  9950. __touchStartHandler : function(e) {
  9951. if ( e.target===this.canvas ) {
  9952. e.preventDefault();
  9953. e= e.targetTouches[0];
  9954. var mp= this.mousePoint;
  9955. this.getCanvasCoord(mp, e);
  9956. if ( mp.x<0 || mp.y<0 || mp.x>=this.width || mp.y>=this.height ) {
  9957. return;
  9958. }
  9959. this.touching= true;
  9960. this.__mouseDownHandler(e);
  9961. }
  9962. },
  9963. __touchEndHandler : function(e) {
  9964. if ( this.touching ) {
  9965. e.preventDefault();
  9966. e= e.changedTouches[0];
  9967. var mp= this.mousePoint;
  9968. this.getCanvasCoord(mp, e);
  9969. this.touching= false;
  9970. this.__mouseUpHandler(e);
  9971. }
  9972. },
  9973. __touchMoveHandler : function(e) {
  9974. if ( this.touching ) {
  9975. e.preventDefault();
  9976. if ( this.gesturing ) {
  9977. return;
  9978. }
  9979. for( var i=0; i<e.targetTouches.length; i++ ) {
  9980. var ee= e.targetTouches[i];
  9981. var mp= this.mousePoint;
  9982. this.getCanvasCoord(mp, ee);
  9983. this.__mouseMoveHandler(ee);
  9984. }
  9985. }
  9986. },
  9987. __gestureStart : function( scale, rotation ) {
  9988. this.gesturing= true;
  9989. this.__gestureRotation= this.lastSelectedActor.rotationAngle;
  9990. this.__gestureSX= this.lastSelectedActor.scaleX - 1;
  9991. this.__gestureSY= this.lastSelectedActor.scaleY - 1;
  9992. },
  9993. __gestureChange : function( scale, rotation ) {
  9994. if ( typeof scale==='undefined' || typeof rotation==='undefined' ) {
  9995. return;
  9996. }
  9997. if ( this.lastSelectedActor!==null && this.lastSelectedActor.isGestureEnabled() ) {
  9998. this.lastSelectedActor.setRotation( rotation*Math.PI/180 + this.__gestureRotation );
  9999. this.lastSelectedActor.setScale(
  10000. this.__gestureSX + scale,
  10001. this.__gestureSY + scale );
  10002. }
  10003. },
  10004. __gestureEnd : function( scale, rotation ) {
  10005. this.gesturing= false;
  10006. this.__gestureRotation= 0;
  10007. this.__gestureScale= 0;
  10008. },
  10009. addHandlers: function(canvas) {
  10010. var me= this;
  10011. window.addEventListener('mouseup', function(e) {
  10012. if ( me.touching ) {
  10013. e.preventDefault();
  10014. e.cancelBubble = true;
  10015. if (e.stopPropagation) e.stopPropagation();
  10016. var mp= me.mousePoint;
  10017. me.getCanvasCoord(mp, e);
  10018. me.__mouseUpHandler(e);
  10019. me.touching= false;
  10020. }
  10021. }, false );
  10022. window.addEventListener('mousedown', function(e) {
  10023. if ( e.target===canvas ) {
  10024. e.preventDefault();
  10025. e.cancelBubble = true;
  10026. if (e.stopPropagation) e.stopPropagation();
  10027. var mp= me.mousePoint;
  10028. me.getCanvasCoord(mp, e);
  10029. if ( mp.x<0 || mp.y<0 || mp.x>=me.width || mp.y>=me.height ) {
  10030. return;
  10031. }
  10032. me.touching= true;
  10033. me.__mouseDownHandler(e);
  10034. }
  10035. }, false );
  10036. window.addEventListener('mouseover',function(e) {
  10037. if ( e.target===canvas && !me.dragging ) {
  10038. e.preventDefault();
  10039. e.cancelBubble = true;
  10040. if (e.stopPropagation) e.stopPropagation();
  10041. var mp= me.mousePoint;
  10042. me.getCanvasCoord(mp, e);
  10043. if ( mp.x<0 || mp.y<0 || mp.x>=me.width || mp.y>=me.height ) {
  10044. return;
  10045. }
  10046. me.__mouseOverHandler(e);
  10047. }
  10048. }, false);
  10049. window.addEventListener('mouseout',function(e) {
  10050. if ( e.target===canvas && !me.dragging ) {
  10051. e.preventDefault();
  10052. e.cancelBubble = true;
  10053. if (e.stopPropagation) e.stopPropagation();
  10054. var mp= me.mousePoint;
  10055. me.getCanvasCoord(mp, e);
  10056. me.__mouseOutHandler(e);
  10057. }
  10058. }, false);
  10059. window.addEventListener('mousemove',
  10060. function(e) {
  10061. e.preventDefault();
  10062. e.cancelBubble = true;
  10063. if (e.stopPropagation) e.stopPropagation();
  10064. var mp= me.mousePoint;
  10065. me.getCanvasCoord(mp, e);
  10066. if ( !me.dragging && ( mp.x<0 || mp.y<0 || mp.x>=me.width || mp.y>=me.height ) ) {
  10067. return;
  10068. }
  10069. me.__mouseMoveHandler(e);
  10070. },
  10071. false);
  10072. window.addEventListener("dblclick", function(e) {
  10073. if ( e.target===canvas ) {
  10074. e.preventDefault();
  10075. e.cancelBubble = true;
  10076. if (e.stopPropagation) e.stopPropagation();
  10077. var mp= me.mousePoint;
  10078. me.getCanvasCoord(mp, e);
  10079. if ( mp.x<0 || mp.y<0 || mp.x>=me.width || mp.y>=me.height ) {
  10080. return;
  10081. }
  10082. me.__mouseDBLClickHandler(e);
  10083. }
  10084. }, false);
  10085. window.addEventListener("touchstart", this.__touchStartHandler.bind(this), false);
  10086. window.addEventListener("touchmove", this.__touchMoveHandler.bind(this), false);
  10087. window.addEventListener("touchend", this.__touchEndHandler.bind(this), false);
  10088. window.addEventListener("gesturestart", function(e) {
  10089. if ( e.target===canvas ) {
  10090. e.preventDefault();
  10091. me.__gestureStart( e.scale, e.rotation );
  10092. }
  10093. }, false );
  10094. window.addEventListener("gestureend", function(e) {
  10095. if ( e.target===canvas ) {
  10096. e.preventDefault();
  10097. me.__gestureEnd( e.scale, e.rotation );
  10098. }
  10099. }, false );
  10100. window.addEventListener("gesturechange", function(e) {
  10101. if ( e.target===canvas ) {
  10102. e.preventDefault();
  10103. me.__gestureChange( e.scale, e.rotation );
  10104. }
  10105. }, false );
  10106. },
  10107. enableEvents : function( onElement ) {
  10108. CAAT.RegisterDirector(this);
  10109. this.in_ = false;
  10110. this.createEventHandler( onElement );
  10111. },
  10112. createEventHandler : function( onElement ) {
  10113. //var canvas= this.canvas;
  10114. this.in_ = false;
  10115. //this.addHandlers(canvas);
  10116. this.addHandlers( onElement );
  10117. }
  10118. };
  10119. if (CAAT.__CSS__) {
  10120. CAAT.Director.prototype.clip= true;
  10121. CAAT.Director.prototype.glEnabled= false;
  10122. CAAT.Director.prototype.getRenderType= function() {
  10123. return 'CSS';
  10124. };
  10125. CAAT.Director.prototype.setScaleProportional= function(w,h) {
  10126. var factor= Math.min(w/this.referenceWidth, h/this.referenceHeight);
  10127. this.setScaleAnchored( factor, factor, 0, 0 );
  10128. this.eventHandler.style.width= ''+this.referenceWidth +'px';
  10129. this.eventHandler.style.height= ''+this.referenceHeight+'px';
  10130. };
  10131. CAAT.Director.prototype.setBounds= function(x, y, w, h) {
  10132. CAAT.Director.superclass.setBounds.call(this, x, y, w, h);
  10133. for (var i = 0; i < this.scenes.length; i++) {
  10134. this.scenes[i].setBounds(0, 0, w, h);
  10135. }
  10136. this.eventHandler.style.width= w+'px';
  10137. this.eventHandler.style.height= h+'px';
  10138. return this;
  10139. };
  10140. /**
  10141. * In this DOM/CSS implementation, proxy is not taken into account since the event router is a top most
  10142. * div in the document hierarchy (z-index 999999).
  10143. * @param width
  10144. * @param height
  10145. * @param domElement
  10146. * @param proxy
  10147. */
  10148. CAAT.Director.prototype.initialize= function(width, height, domElement, proxy) {
  10149. this.timeline = new Date().getTime();
  10150. this.domElement= domElement;
  10151. this.style('position','absolute');
  10152. this.style('width',''+width+'px');
  10153. this.style('height',''+height+'px');
  10154. this.style('overflow', 'hidden' );
  10155. this.enableEvents(domElement);
  10156. this.setBounds(0, 0, width, height);
  10157. this.checkDebug();
  10158. return this;
  10159. };
  10160. CAAT.Director.prototype.render= function(time) {
  10161. this.time += time;
  10162. this.animate(this,time);
  10163. /**
  10164. * draw director active scenes.
  10165. */
  10166. var i, l, tt;
  10167. if ( CAAT.DEBUG ) {
  10168. this.resetStats();
  10169. }
  10170. for (i = 0, l=this.childrenList.length; i < l; i++) {
  10171. var c= this.childrenList[i];
  10172. if (c.isInAnimationFrame(this.time)) {
  10173. tt = c.time - c.start_time;
  10174. if ( c.onRenderStart ) {
  10175. c.onRenderStart(tt);
  10176. }
  10177. c.paintActor(this, tt);
  10178. if ( c.onRenderEnd ) {
  10179. c.onRenderEnd(tt);
  10180. }
  10181. if (!c.isPaused()) {
  10182. c.time += time;
  10183. }
  10184. if ( CAAT.DEBUG ) {
  10185. this.statistics.size_total+= c.size_total;
  10186. this.statistics.size_active+= c.size_active;
  10187. this.statistics.size_dirtyRects= this.nDirtyRects;
  10188. }
  10189. }
  10190. }
  10191. this.frameCounter++;
  10192. };
  10193. CAAT.Director.prototype.addScene= function(scene) {
  10194. scene.setVisible(true);
  10195. scene.setBounds(0, 0, this.width, this.height);
  10196. this.scenes.push(scene);
  10197. scene.setEaseListener(this);
  10198. if (null === this.currentScene) {
  10199. this.setScene(0);
  10200. }
  10201. this.domElement.appendChild( scene.domElement );
  10202. };
  10203. CAAT.Director.prototype.emptyScenes= function() {
  10204. this.scenes = [];
  10205. this.domElement.innerHTML='';
  10206. this.createEventHandler();
  10207. };
  10208. CAAT.Director.prototype.setClear= function(clear) {
  10209. return this;
  10210. };
  10211. CAAT.Director.prototype.createEventHandler= function() {
  10212. this.eventHandler= document.createElement('div');
  10213. this.domElement.appendChild(this.eventHandler);
  10214. this.eventHandler.style.position= 'absolute';
  10215. this.eventHandler.style.left= '0';
  10216. this.eventHandler.style.top= '0';
  10217. this.eventHandler.style.zIndex= 999999;
  10218. this.eventHandler.style.width= ''+this.width+'px';
  10219. this.eventHandler.style.height= ''+this.height+'px';
  10220. var canvas= this.eventHandler;
  10221. this.in_ = false;
  10222. this.addHandlers(canvas);
  10223. };
  10224. }
  10225. extend(CAAT.Director, CAAT.ActorContainer, null);
  10226. })();
  10227. /**
  10228. * See LICENSE file.
  10229. *
  10230. * MouseEvent is a class to hold necessary information of every mouse event related to concrete
  10231. * scene graph Actors.
  10232. *
  10233. * Here it is also the logic to on mouse events, pump the correct event to the appropiate scene
  10234. * graph Actor.
  10235. *
  10236. * TODO: add events for event pumping:
  10237. * + cancelBubling
  10238. *
  10239. **/
  10240. (function() {
  10241. /**
  10242. * This function creates a mouse event that represents a touch or mouse event.
  10243. * @constructor
  10244. */
  10245. CAAT.MouseEvent = function() {
  10246. this.point= new CAAT.Point(0,0,0);
  10247. this.screenPoint= new CAAT.Point(0,0,0);
  10248. return this;
  10249. };
  10250. CAAT.MouseEvent.prototype= {
  10251. screenPoint: null,
  10252. point: null,
  10253. time: 0,
  10254. source: null,
  10255. shift: false,
  10256. control: false,
  10257. alt: false,
  10258. meta: false,
  10259. sourceEvent: null,
  10260. init : function( x,y,sourceEvent,source,screenPoint,time ) {
  10261. this.point.set(x,y);
  10262. this.source= source;
  10263. this.screenPoint= screenPoint;
  10264. this.alt = sourceEvent.altKey;
  10265. this.control = sourceEvent.ctrlKey;
  10266. this.shift = sourceEvent.shiftKey;
  10267. this.meta = sourceEvent.metaKey;
  10268. this.sourceEvent= sourceEvent;
  10269. this.x= x;
  10270. this.y= y;
  10271. this.time= time;
  10272. return this;
  10273. },
  10274. isAltDown : function() {
  10275. return this.alt;
  10276. },
  10277. isControlDown : function() {
  10278. return this.control;
  10279. },
  10280. isShiftDown : function() {
  10281. return this.shift;
  10282. },
  10283. isMetaDown: function() {
  10284. return this.meta;
  10285. },
  10286. getSourceEvent : function() {
  10287. return this.sourceEvent;
  10288. }
  10289. };
  10290. })();
  10291. CAAT.setCoordinateClamping= function( clamp ) {
  10292. if ( clamp ) {
  10293. CAAT.Matrix.prototype.transformRenderingContext= CAAT.Matrix.prototype.transformRenderingContext_Clamp;
  10294. CAAT.Matrix.prototype.transformRenderingContextSet= CAAT.Matrix.prototype.transformRenderingContextSet_Clamp;
  10295. } else {
  10296. CAAT.Matrix.prototype.transformRenderingContext= CAAT.Matrix.prototype.transformRenderingContext_NoClamp;
  10297. CAAT.Matrix.prototype.transformRenderingContextSet= CAAT.Matrix.prototype.transformRenderingContextSet_NoClamp;
  10298. }
  10299. };
  10300. CAAT.RENDER_MODE_CONTINUOUS= 1; // redraw every frame
  10301. CAAT.RENDER_MODE_DIRTY= 2; // suitable for evented CAAT.
  10302. CAAT.RENDER_MODE= CAAT.RENDER_MODE_CONTINUOUS;
  10303. /**
  10304. * Box2D point meter conversion ratio.
  10305. */
  10306. CAAT.PMR= 64;
  10307. CAAT.GLRENDER= false;
  10308. /**
  10309. * Allow visual debugging artifacts.
  10310. */
  10311. CAAT.DEBUG= false;
  10312. CAAT.DEBUGBB= false;
  10313. CAAT.DEBUGBBBCOLOR='#00f';
  10314. CAAT.DEBUGAABB= false; // debug bounding boxes.
  10315. CAAT.DEBUGAABBCOLOR='#f00';
  10316. CAAT.DEBUG_DIRTYRECTS=false;
  10317. /**
  10318. * Log function which deals with window's Console object.
  10319. */
  10320. CAAT.log= function() {
  10321. if(window.console){
  10322. window.console.log( Array.prototype.slice.call(arguments) );
  10323. }
  10324. };
  10325. CAAT.FRAME_TIME= 0;
  10326. /**
  10327. * Flag to signal whether events are enabled for CAAT.
  10328. */
  10329. CAAT.GlobalEventsEnabled= false;
  10330. /**
  10331. * Accelerometer related data.
  10332. */
  10333. CAAT.prevOnDeviceMotion= null; // previous accelerometer callback function.
  10334. CAAT.onDeviceMotion= null; // current accelerometer callback set for CAAT.
  10335. CAAT.accelerationIncludingGravity= { x:0, y:0, z:0 }; // acceleration data.
  10336. CAAT.rotationRate= { alpha: 0, beta:0, gamma: 0 }; // angles data.
  10337. /**
  10338. * Do not consider mouse drag gesture at least until you have dragged
  10339. * 5 pixels in any direction.
  10340. */
  10341. CAAT.DRAG_THRESHOLD_X= 5;
  10342. CAAT.DRAG_THRESHOLD_Y= 5;
  10343. // has the animation loop began ?
  10344. CAAT.renderEnabled= false;
  10345. CAAT.FPS= 60;
  10346. /**
  10347. * On resize event listener
  10348. */
  10349. CAAT.windowResizeListeners= [];
  10350. /**
  10351. * Register an object as resize callback.
  10352. * @param f { function( windowResized(width{number},height{number})} ) }
  10353. */
  10354. CAAT.registerResizeListener= function(f) {
  10355. CAAT.windowResizeListeners.push(f);
  10356. };
  10357. /**
  10358. * Unregister a resize listener.
  10359. * @param director {CAAT.Director}
  10360. */
  10361. CAAT.unregisterResizeListener= function(director) {
  10362. for( var i=0; i<CAAT.windowResizeListeners.length; i++ ) {
  10363. if ( director===CAAT.windowResizeListeners[i] ) {
  10364. CAAT.windowResizeListeners.splice(i,1);
  10365. return;
  10366. }
  10367. }
  10368. };
  10369. /**
  10370. * Pressed key codes.
  10371. */
  10372. CAAT.keyListeners= [];
  10373. /**
  10374. * Register key events notification function.
  10375. * @param f {function(key {integer}, action {'down'|'up'})}
  10376. */
  10377. CAAT.registerKeyListener= function(f) {
  10378. CAAT.keyListeners.push(f);
  10379. };
  10380. CAAT.Keys = {
  10381. ENTER:13,
  10382. BACKSPACE:8,
  10383. TAB:9,
  10384. SHIFT:16,
  10385. CTRL:17,
  10386. ALT:18,
  10387. PAUSE:19,
  10388. CAPSLOCK:20,
  10389. ESCAPE:27,
  10390. // SPACE:32,
  10391. PAGEUP:33,
  10392. PAGEDOWN:34,
  10393. END:35,
  10394. HOME:36,
  10395. LEFT:37,
  10396. UP:38,
  10397. RIGHT:39,
  10398. DOWN:40,
  10399. INSERT:45,
  10400. DELETE:46,
  10401. 0:48,
  10402. 1:49,
  10403. 2:50,
  10404. 3:51,
  10405. 4:52,
  10406. 5:53,
  10407. 6:54,
  10408. 7:55,
  10409. 8:56,
  10410. 9:57,
  10411. a:65,
  10412. b:66,
  10413. c:67,
  10414. d:68,
  10415. e:69,
  10416. f:70,
  10417. g:71,
  10418. h:72,
  10419. i:73,
  10420. j:74,
  10421. k:75,
  10422. l:76,
  10423. m:77,
  10424. n:78,
  10425. o:79,
  10426. p:80,
  10427. q:81,
  10428. r:82,
  10429. s:83,
  10430. t:84,
  10431. u:85,
  10432. v:86,
  10433. w:87,
  10434. x:88,
  10435. y:89,
  10436. z:90,
  10437. SELECT:93,
  10438. NUMPAD0:96,
  10439. NUMPAD1:97,
  10440. NUMPAD2:98,
  10441. NUMPAD3:99,
  10442. NUMPAD4:100,
  10443. NUMPAD5:101,
  10444. NUMPAD6:102,
  10445. NUMPAD7:103,
  10446. NUMPAD8:104,
  10447. NUMPAD9:105,
  10448. MULTIPLY:106,
  10449. ADD:107,
  10450. SUBTRACT:109,
  10451. DECIMALPOINT:110,
  10452. DIVIDE:111,
  10453. F1:112,
  10454. F2:113,
  10455. F3:114,
  10456. F4:115,
  10457. F5:116,
  10458. F6:117,
  10459. F7:118,
  10460. F8:119,
  10461. F9:120,
  10462. F10:121,
  10463. F11:122,
  10464. F12:123,
  10465. NUMLOCK:144,
  10466. SCROLLLOCK:145,
  10467. SEMICOLON:186,
  10468. EQUALSIGN:187,
  10469. COMMA:188,
  10470. DASH:189,
  10471. PERIOD:190,
  10472. FORWARDSLASH:191,
  10473. GRAVEACCENT:192,
  10474. OPENBRACKET:219,
  10475. BACKSLASH:220,
  10476. CLOSEBRAKET:221,
  10477. SINGLEQUOTE:222
  10478. };
  10479. CAAT.SHIFT_KEY= 16;
  10480. CAAT.CONTROL_KEY= 17;
  10481. CAAT.ALT_KEY= 18;
  10482. CAAT.ENTER_KEY= 13;
  10483. /**
  10484. * Event modifiers.
  10485. */
  10486. CAAT.KEY_MODIFIERS= {
  10487. alt: false,
  10488. control: false,
  10489. shift: false
  10490. };
  10491. /**
  10492. * Define a key event.
  10493. * @constructor
  10494. * @param keyCode
  10495. * @param up_or_down
  10496. * @param modifiers
  10497. * @param originalEvent
  10498. */
  10499. CAAT.KeyEvent= function( keyCode, up_or_down, modifiers, originalEvent ) {
  10500. this.keyCode= keyCode;
  10501. this.action= up_or_down;
  10502. this.modifiers= modifiers;
  10503. this.sourceEvent= originalEvent;
  10504. this.preventDefault= function() {
  10505. this.sourceEvent.preventDefault();
  10506. }
  10507. this.getKeyCode= function() {
  10508. return this.keyCode;
  10509. };
  10510. this.getAction= function() {
  10511. return this.action;
  10512. };
  10513. this.modifiers= function() {
  10514. return this.modifiers;
  10515. };
  10516. this.isShiftPressed= function() {
  10517. return this.modifiers.shift;
  10518. };
  10519. this.isControlPressed= function() {
  10520. return this.modifiers.control;
  10521. };
  10522. this.isAltPressed= function() {
  10523. return this.modifiers.alt;
  10524. };
  10525. this.getSourceEvent= function() {
  10526. return this.sourceEvent;
  10527. };
  10528. };
  10529. /**
  10530. * Enable window level input events, keys and redimension.
  10531. */
  10532. CAAT.GlobalEnableEvents= function __GlobalEnableEvents() {
  10533. if ( CAAT.GlobalEventsEnabled ) {
  10534. return;
  10535. }
  10536. this.GlobalEventsEnabled= true;
  10537. window.addEventListener('keydown',
  10538. function(evt) {
  10539. var key = (evt.which) ? evt.which : evt.keyCode;
  10540. if ( key===CAAT.SHIFT_KEY ) {
  10541. CAAT.KEY_MODIFIERS.shift= true;
  10542. } else if ( key===CAAT.CONTROL_KEY ) {
  10543. CAAT.KEY_MODIFIERS.control= true;
  10544. } else if ( key===CAAT.ALT_KEY ) {
  10545. CAAT.KEY_MODIFIERS.alt= true;
  10546. } else {
  10547. for( var i=0; i<CAAT.keyListeners.length; i++ ) {
  10548. CAAT.keyListeners[i]( new CAAT.KeyEvent(
  10549. key,
  10550. 'down',
  10551. {
  10552. alt: CAAT.KEY_MODIFIERS.alt,
  10553. control: CAAT.KEY_MODIFIERS.control,
  10554. shift: CAAT.KEY_MODIFIERS.shift
  10555. },
  10556. evt)) ;
  10557. }
  10558. }
  10559. },
  10560. false);
  10561. window.addEventListener('keyup',
  10562. function(evt) {
  10563. var key = (evt.which) ? evt.which : evt.keyCode;
  10564. if ( key===CAAT.SHIFT_KEY ) {
  10565. CAAT.KEY_MODIFIERS.shift= false;
  10566. } else if ( key===CAAT.CONTROL_KEY ) {
  10567. CAAT.KEY_MODIFIERS.control= false;
  10568. } else if ( key===CAAT.ALT_KEY ) {
  10569. CAAT.KEY_MODIFIERS.alt= false;
  10570. } else {
  10571. for( var i=0; i<CAAT.keyListeners.length; i++ ) {
  10572. CAAT.keyListeners[i]( new CAAT.KeyEvent(
  10573. key,
  10574. 'up',
  10575. {
  10576. alt: CAAT.KEY_MODIFIERS.alt,
  10577. control: CAAT.KEY_MODIFIERS.control,
  10578. shift: CAAT.KEY_MODIFIERS.shift
  10579. },
  10580. evt));
  10581. }
  10582. }
  10583. },
  10584. false );
  10585. window.addEventListener('resize',
  10586. function(evt) {
  10587. for( var i=0; i<CAAT.windowResizeListeners.length; i++ ) {
  10588. CAAT.windowResizeListeners[i].windowResized(
  10589. window.innerWidth,
  10590. window.innerHeight);
  10591. }
  10592. },
  10593. false);
  10594. };
  10595. /**
  10596. * Polyfill for requestAnimationFrame.
  10597. */
  10598. window.requestAnimFrame = (function(){
  10599. return window.requestAnimationFrame ||
  10600. window.webkitRequestAnimationFrame ||
  10601. window.mozRequestAnimationFrame ||
  10602. window.oRequestAnimationFrame ||
  10603. window.msRequestAnimationFrame ||
  10604. function raf(/* function */ callback, /* DOMElement */ element){
  10605. window.setTimeout(callback, 1000 / CAAT.FPS);
  10606. };
  10607. })();
  10608. CAAT.SET_INTERVAL=0;
  10609. /**
  10610. * Main animation loop entry point.
  10611. * @param fps {number} desired fps. This parameter makes no sense unless requestAnimationFrame function
  10612. * is not present in the system.
  10613. */
  10614. CAAT.loop= function(fps) {
  10615. if (CAAT.renderEnabled) {
  10616. return;
  10617. }
  10618. CAAT.FPS= fps || 60;
  10619. CAAT.renderEnabled= true;
  10620. if (CAAT.NO_RAF) {
  10621. setInterval(
  10622. function() {
  10623. var t= new Date().getTime();
  10624. for (var i = 0, l = CAAT.director.length; i < l; i++) {
  10625. CAAT.director[i].renderFrame();
  10626. }
  10627. //t= new Date().getTime()-t;
  10628. CAAT.FRAME_TIME= t - CAAT.SET_INTERVAL;
  10629. CAAT.SET_INTERVAL= t;
  10630. },
  10631. 1000 / CAAT.FPS
  10632. );
  10633. } else {
  10634. CAAT.renderFrame();
  10635. }
  10636. }
  10637. CAAT.FPS_REFRESH= 500; // debug panel update time.
  10638. CAAT.RAF= 0; // requestAnimationFrame time reference.
  10639. CAAT.REQUEST_ANIMATION_FRAME_TIME= 0;
  10640. /**
  10641. * Make a frame for each director instance present in the system.
  10642. */
  10643. CAAT.renderFrame= function() {
  10644. var t= new Date().getTime();
  10645. for( var i=0, l=CAAT.director.length; i<l; i++ ) {
  10646. CAAT.director[i].renderFrame();
  10647. }
  10648. t= new Date().getTime()-t;
  10649. CAAT.FRAME_TIME= t;
  10650. if (CAAT.RAF) {
  10651. CAAT.REQUEST_ANIMATION_FRAME_TIME= new Date().getTime()-CAAT.RAF;
  10652. }
  10653. CAAT.RAF= new Date().getTime();
  10654. window.requestAnimFrame(CAAT.renderFrame, 0 );
  10655. }
  10656. /**
  10657. * Set browser cursor. The preferred method for cursor change is this method.
  10658. * @param cursor
  10659. */
  10660. CAAT.setCursor= function(cursor) {
  10661. if ( navigator.browser!=='iOS' ) {
  10662. document.body.style.cursor= cursor;
  10663. }
  10664. };
  10665. /**
  10666. * Register and keep track of every CAAT.Director instance in the document.
  10667. */
  10668. CAAT.RegisterDirector= function __CAATGlobal_RegisterDirector(director) {
  10669. if ( !CAAT.director ) {
  10670. CAAT.director=[];
  10671. }
  10672. CAAT.director.push(director);
  10673. CAAT.GlobalEnableEvents();
  10674. };
  10675. /**
  10676. * Enable at window level accelerometer events.
  10677. */
  10678. (function() {
  10679. function tilt(data) {
  10680. CAAT.rotationRate= {
  10681. alpha : 0,
  10682. beta : data[0],
  10683. gamma : data[1]
  10684. };
  10685. }
  10686. if (window.DeviceOrientationEvent) {
  10687. window.addEventListener("deviceorientation", function (event) {
  10688. tilt([event.beta, event.gamma]);
  10689. }, true);
  10690. } else if (window.DeviceMotionEvent) {
  10691. window.addEventListener('devicemotion', function (event) {
  10692. tilt([event.acceleration.x * 2, event.acceleration.y * 2]);
  10693. }, true);
  10694. } else {
  10695. window.addEventListener("MozOrientation", function (event) {
  10696. tilt([-event.y * 45, event.x * 45]);
  10697. }, true);
  10698. }
  10699. })();/**
  10700. * See LICENSE file.
  10701. *
  10702. * TODO: allow set of margins, spacing, etc. to define subimages.
  10703. *
  10704. **/
  10705. (function() {
  10706. CAAT.SpriteImageHelper= function(x,y,w,h, iw, ih) {
  10707. this.x= x;
  10708. this.y= y;
  10709. this.width= w;
  10710. this.height= h;
  10711. this.setGL( x/iw, y/ih, (x+w-1)/iw, (y+h-1)/ih );
  10712. return this;
  10713. };
  10714. CAAT.SpriteImageHelper.prototype= {
  10715. x : 0,
  10716. y : 0,
  10717. width : 0,
  10718. height : 0,
  10719. u : 0,
  10720. v : 0,
  10721. u1 : 0,
  10722. v1 : 0,
  10723. setGL : function( u,v,u1,v1 ) {
  10724. this.u= u;
  10725. this.v= v;
  10726. this.u1= u1;
  10727. this.v1= v1;
  10728. return this;
  10729. }
  10730. };
  10731. })();
  10732. (function() {
  10733. /**
  10734. *
  10735. * This class is used by CAAT.Actor to draw images. It differs from CAAT.CompoundImage in that it
  10736. * manages the subimage change based on time and a list of animation sub-image indexes.
  10737. * A common use of this class will be:
  10738. *
  10739. * <code>
  10740. * var si= new CAAT.SpriteImage().
  10741. * initialize( an_image_instance, rows, columns ).
  10742. * setAnimationImageIndex( [2,1,0,1] ). // cycle throwout image with these indexes
  10743. * setChangeFPS( 200 ). // change sprite every 200 ms.
  10744. * setSpriteTransformation( CAAT.SpriteImage.TR_xx); // optionally draw images inverted, ...
  10745. * </code>
  10746. *
  10747. * A SpriteImage is an sprite sheet. It encapsulates an Image and treates and references it as a two
  10748. * dimensional array of row by columns sub-images. The access form will be sequential so if defined a
  10749. * CompoundImage of more than one row, the subimages will be referenced by an index ranging from 0 to
  10750. * rows*columns-1. Each sumimage will be of size (image.width/columns) by (image.height/rows).
  10751. *
  10752. * <p>
  10753. * It is able to draw its sub-images in the following ways:
  10754. * <ul>
  10755. * <li>no transformed (default)
  10756. * <li>flipped horizontally
  10757. * <li>flipped vertically
  10758. * <li>flipped both vertical and horizontally
  10759. * </ul>
  10760. *
  10761. * <p>
  10762. * It is supposed to be used in conjunction with <code>CAAT.SpriteActor</code> instances.
  10763. *
  10764. * @constructor
  10765. *
  10766. */
  10767. CAAT.SpriteImage = function() {
  10768. this.paint= this.paintN;
  10769. this.setAnimationImageIndex([0]);
  10770. this.mapInfo= {};
  10771. return this;
  10772. };
  10773. CAAT.SpriteImage.prototype = {
  10774. animationImageIndex: null, // an Array defining the sprite frame sequence
  10775. prevAnimationTime: -1,
  10776. changeFPS: 1000, // how much Scene time to take before changing an Sprite frame.
  10777. transformation: 0, // any of the TR_* constants.
  10778. spriteIndex: 0, // the current sprite frame
  10779. TR_NONE: 0, // constants used to determine how to draw the sprite image,
  10780. TR_FLIP_HORIZONTAL: 1,
  10781. TR_FLIP_VERTICAL: 2,
  10782. TR_FLIP_ALL: 3,
  10783. TR_FIXED_TO_SIZE: 4,
  10784. TR_TILE: 5,
  10785. image: null,
  10786. rows: 1,
  10787. columns: 1,
  10788. width: 0,
  10789. height: 0,
  10790. singleWidth: 0,
  10791. singleHeight: 0,
  10792. scaleX: 1,
  10793. scaleY: 1,
  10794. offsetX: 0,
  10795. offsetY: 0,
  10796. ownerActor: null,
  10797. mapInfo : null,
  10798. map : null,
  10799. setOwner : function(actor) {
  10800. this.ownerActor= actor;
  10801. return this;
  10802. },
  10803. getRows: function() {
  10804. return this.rows;
  10805. },
  10806. getColumns : function() {
  10807. return this.columns;
  10808. },
  10809. getWidth : function() {
  10810. var el= this.mapInfo[this.spriteIndex];
  10811. return el.width;
  10812. },
  10813. getHeight : function() {
  10814. var el= this.mapInfo[this.spriteIndex];
  10815. return el.height;
  10816. },
  10817. /**
  10818. * Get a reference to the same image information (rows, columns, image and uv cache) of this
  10819. * SpriteImage. This means that re-initializing this objects image info (that is, calling initialize
  10820. * method) will change all reference's image information at the same time.
  10821. */
  10822. getRef : function() {
  10823. var ret= new CAAT.SpriteImage();
  10824. ret.image= this.image;
  10825. ret.rows= this.rows;
  10826. ret.columns= this.columns;
  10827. ret.width= this.width;
  10828. ret.height= this.height;
  10829. ret.singleWidth= this.singleWidth;
  10830. ret.singleHeight= this.singleHeight;
  10831. ret.mapInfo= this.mapInfo;
  10832. ret.offsetX= this.offsetX;
  10833. ret.offsetY= this.offsetY;
  10834. ret.scaleX= this.scaleX;
  10835. ret.scaleY= this.scaleY;
  10836. return ret;
  10837. },
  10838. /**
  10839. * Set horizontal displacement to draw image. Positive values means drawing the image more to the
  10840. * right.
  10841. * @param x {number}
  10842. * @return this
  10843. */
  10844. setOffsetX : function(x) {
  10845. this.offsetX= x;
  10846. return this;
  10847. },
  10848. /**
  10849. * Set vertical displacement to draw image. Positive values means drawing the image more to the
  10850. * bottom.
  10851. * @param y {number}
  10852. * @return this
  10853. */
  10854. setOffsetY : function(y) {
  10855. this.offsetY= y;
  10856. return this;
  10857. },
  10858. setOffset : function( x,y ) {
  10859. this.offsetX= x;
  10860. this.offsetY= y;
  10861. return this;
  10862. },
  10863. /**
  10864. * Initialize a grid of subimages out of a given image.
  10865. * @param image {HTMLImageElement|Image} an image object.
  10866. * @param rows {number} number of rows.
  10867. * @param columns {number} number of columns
  10868. *
  10869. * @return this
  10870. */
  10871. initialize : function(image, rows, columns) {
  10872. this.image = image;
  10873. this.rows = rows;
  10874. this.columns = columns;
  10875. this.width = image.width;
  10876. this.height = image.height;
  10877. this.singleWidth = Math.floor(this.width / columns);
  10878. this.singleHeight = Math.floor(this.height / rows);
  10879. this.mapInfo= {};
  10880. var i,sx0,sy0;
  10881. var helper;
  10882. if (image.__texturePage) {
  10883. image.__du = this.singleWidth / image.__texturePage.width;
  10884. image.__dv = this.singleHeight / image.__texturePage.height;
  10885. var w = this.singleWidth;
  10886. var h = this.singleHeight;
  10887. var mod = this.columns;
  10888. if (image.inverted) {
  10889. var t = w;
  10890. w = h;
  10891. h = t;
  10892. mod = this.rows;
  10893. }
  10894. var xt = this.image.__tx;
  10895. var yt = this.image.__ty;
  10896. var tp = this.image.__texturePage;
  10897. for (i = 0; i < rows * columns; i++) {
  10898. var c = ((i % mod) >> 0);
  10899. var r = ((i / mod) >> 0);
  10900. var u = xt + c * w; // esquina izq x
  10901. var v = yt + r * h;
  10902. var u1 = u + w;
  10903. var v1 = v + h;
  10904. helper= new CAAT.SpriteImageHelper(u,v,(u1-u),(v1-v),tp.width,tp.height).setGL(
  10905. u / tp.width,
  10906. v / tp.height,
  10907. u1 / tp.width,
  10908. v1 / tp.height );
  10909. this.mapInfo[i]= helper;
  10910. }
  10911. } else {
  10912. for (i = 0; i < rows * columns; i++) {
  10913. sx0 = ((i % this.columns) | 0) * this.singleWidth;
  10914. sy0 = ((i / this.columns) | 0) * this.singleHeight;
  10915. helper= new CAAT.SpriteImageHelper( sx0, sy0, this.singleWidth, this.singleHeight, image.width, image.height );
  10916. this.mapInfo[i]= helper;
  10917. }
  10918. }
  10919. return this;
  10920. },
  10921. /**
  10922. * Must be used to draw actor background and the actor should have setClip(true) so that the image tiles
  10923. * properly.
  10924. * @param director
  10925. * @param time
  10926. * @param x
  10927. * @param y
  10928. */
  10929. paintTiled : function( director, time, x, y ) {
  10930. this.setSpriteIndexAtTime(time);
  10931. var el= this.mapInfo[this.spriteIndex];
  10932. var r= new CAAT.Rectangle();
  10933. this.ownerActor.AABB.intersect( director.AABB, r );
  10934. var w= this.getWidth();
  10935. var h= this.getHeight();
  10936. var xoff= (this.offsetX-this.ownerActor.x) % w;
  10937. if ( xoff> 0 ) {
  10938. xoff= xoff-w;
  10939. }
  10940. var yoff= (this.offsetY-this.ownerActor.y) % h;
  10941. if ( yoff> 0 ) {
  10942. yoff= yoff-h;
  10943. }
  10944. var nw= (((r.width-xoff)/w)>>0)+1;
  10945. var nh= (((r.height-yoff)/h)>>0)+1;
  10946. var i,j;
  10947. var ctx= director.ctx;
  10948. for( i=0; i<nh; i++ ) {
  10949. for( j=0; j<nw; j++ ) {
  10950. ctx.drawImage(
  10951. this.image,
  10952. el.x, el.y,
  10953. el.width, el.height,
  10954. (r.x-this.ownerActor.x+xoff+j*el.width)>>0, (r.y-this.ownerActor.y+yoff+i*el.height)>>0,
  10955. el.width, el.height);
  10956. }
  10957. }
  10958. },
  10959. /**
  10960. * Draws the subimage pointed by imageIndex horizontally inverted.
  10961. * @param canvas a canvas context.
  10962. * @param imageIndex {number} a subimage index.
  10963. * @param x {number} x position in canvas to draw the image.
  10964. * @param y {number} y position in canvas to draw the image.
  10965. *
  10966. * @return this
  10967. */
  10968. paintInvertedH : function(director, time, x, y) {
  10969. this.setSpriteIndexAtTime(time);
  10970. var el= this.mapInfo[this.spriteIndex];
  10971. var ctx= director.ctx;
  10972. ctx.save();
  10973. //ctx.translate(((0.5 + x) | 0) + el.width, (0.5 + y) | 0);
  10974. ctx.translate( (x|0) + el.width, y|0 );
  10975. ctx.scale(-1, 1);
  10976. ctx.drawImage(
  10977. this.image,
  10978. el.x, el.y,
  10979. el.width, el.height,
  10980. this.offsetX>>0, this.offsetY>>0,
  10981. el.width, el.height );
  10982. ctx.restore();
  10983. return this;
  10984. },
  10985. /**
  10986. * Draws the subimage pointed by imageIndex vertically inverted.
  10987. * @param canvas a canvas context.
  10988. * @param imageIndex {number} a subimage index.
  10989. * @param x {number} x position in canvas to draw the image.
  10990. * @param y {number} y position in canvas to draw the image.
  10991. *
  10992. * @return this
  10993. */
  10994. paintInvertedV : function(director, time, x, y) {
  10995. this.setSpriteIndexAtTime(time);
  10996. var el= this.mapInfo[this.spriteIndex];
  10997. var ctx= director.ctx;
  10998. ctx.save();
  10999. //ctx.translate((x + 0.5) | 0, (0.5 + y + el.height) | 0);
  11000. ctx.translate( x|0, (y + el.height) | 0);
  11001. ctx.scale(1, -1);
  11002. ctx.drawImage(
  11003. this.image,
  11004. el.x, el.y,
  11005. el.width, el.height,
  11006. this.offsetX>>0,this.offsetY>>0,
  11007. el.width, el.height);
  11008. ctx.restore();
  11009. return this;
  11010. },
  11011. /**
  11012. * Draws the subimage pointed by imageIndex both horizontal and vertically inverted.
  11013. * @param canvas a canvas context.
  11014. * @param imageIndex {number} a subimage index.
  11015. * @param x {number} x position in canvas to draw the image.
  11016. * @param y {number} y position in canvas to draw the image.
  11017. *
  11018. * @return this
  11019. */
  11020. paintInvertedHV : function(director, time, x, y) {
  11021. this.setSpriteIndexAtTime(time);
  11022. var el= this.mapInfo[this.spriteIndex];
  11023. var ctx= director.ctx;
  11024. ctx.save();
  11025. //ctx.translate((x + 0.5) | 0, (0.5 + y + el.height) | 0);
  11026. ctx.translate( x | 0, (y + el.height) | 0);
  11027. ctx.scale(1, -1);
  11028. ctx.translate(el.width, 0);
  11029. ctx.scale(-1, 1);
  11030. ctx.drawImage(
  11031. this.image,
  11032. el.x, el.y,
  11033. el.width, el.height,
  11034. this.offsetX>>0, this.offsetY>>0,
  11035. el.width, el.height);
  11036. ctx.restore();
  11037. return this;
  11038. },
  11039. /**
  11040. * Draws the subimage pointed by imageIndex.
  11041. * @param canvas a canvas context.
  11042. * @param imageIndex {number} a subimage index.
  11043. * @param x {number} x position in canvas to draw the image.
  11044. * @param y {number} y position in canvas to draw the image.
  11045. *
  11046. * @return this
  11047. */
  11048. paintN : function(director, time, x, y) {
  11049. this.setSpriteIndexAtTime(time);
  11050. var el= this.mapInfo[this.spriteIndex];
  11051. director.ctx.drawImage(
  11052. this.image,
  11053. el.x, el.y,
  11054. el.width, el.height,
  11055. (this.offsetX+x)>>0, (this.offsetY+y)>>0,
  11056. el.width, el.height);
  11057. return this;
  11058. },
  11059. paintChunk : function( ctx, dx,dy, x, y, w, h ) {
  11060. ctx.drawImage( this.image, x,y,w,h, dx,dy,w,h );
  11061. },
  11062. paintTile : function(ctx, index, x, y) {
  11063. var el= this.mapInfo[index];
  11064. ctx.drawImage(
  11065. this.image,
  11066. el.x, el.y,
  11067. el.width, el.height,
  11068. (this.offsetX+x)>>0, (this.offsetY+y)>>0,
  11069. el.width, el.height);
  11070. return this;
  11071. },
  11072. /**
  11073. * Draws the subimage pointed by imageIndex scaled to the size of w and h.
  11074. * @param canvas a canvas context.
  11075. * @param imageIndex {number} a subimage index.
  11076. * @param x {number} x position in canvas to draw the image.
  11077. * @param y {number} y position in canvas to draw the image.
  11078. * @param w {number} new width of the subimage.
  11079. * @param h {number} new height of the subimage.
  11080. *
  11081. * @return this
  11082. */
  11083. paintScaled : function(director, time, x, y) {
  11084. this.setSpriteIndexAtTime(time);
  11085. var el= this.mapInfo[this.spriteIndex];
  11086. director.ctx.drawImage(
  11087. this.image,
  11088. el.x, el.y,
  11089. el.width, el.height,
  11090. (this.offsetX+x)>>0, (this.offsetY+y)>>0,
  11091. this.ownerActor.width, this.ownerActor.height );
  11092. return this;
  11093. },
  11094. getCurrentSpriteImageCSSPosition : function() {
  11095. var el= this.mapInfo[this.spriteIndex];
  11096. var x= -(el.x-this.offsetX);
  11097. var y= -(el.y-this.offsetY);
  11098. return ''+x+'px '+
  11099. y+'px '+
  11100. (this.ownerActor.transformation===this.TR_TILE ? 'repeat' : 'no-repeat');
  11101. },
  11102. /**
  11103. * Get the number of subimages in this compoundImage
  11104. * @return {number}
  11105. */
  11106. getNumImages : function() {
  11107. return this.rows * this.columns;
  11108. },
  11109. /**
  11110. * TODO: set mapping coordinates for different transformations.
  11111. * @param imageIndex
  11112. * @param uvBuffer
  11113. * @param uvIndex
  11114. */
  11115. setUV : function(uvBuffer, uvIndex) {
  11116. var im = this.image;
  11117. if (!im.__texturePage) {
  11118. return;
  11119. }
  11120. var index = uvIndex;
  11121. var sIndex= this.spriteIndex;
  11122. var el= this.mapInfo[this.spriteIndex];
  11123. var u= el.u;
  11124. var v= el.v;
  11125. var u1= el.u1;
  11126. var v1= el.v1;
  11127. if ( this.offsetX || this.offsetY ) {
  11128. var w= this.ownerActor.width;
  11129. var h= this.ownerActor.height;
  11130. var tp= im.__texturePage;
  11131. var _u= -this.offsetX / tp.width;
  11132. var _v= -this.offsetY / tp.height;
  11133. var _u1=(w-this.offsetX) / tp.width;
  11134. var _v1=(h-this.offsetY) / tp.height;
  11135. u= _u + im.__u;
  11136. v= _v + im.__v;
  11137. u1= _u1 + im.__u;
  11138. v1= _v1 + im.__v;
  11139. }
  11140. if (im.inverted) {
  11141. uvBuffer[index++] = u1;
  11142. uvBuffer[index++] = v;
  11143. uvBuffer[index++] = u1;
  11144. uvBuffer[index++] = v1;
  11145. uvBuffer[index++] = u;
  11146. uvBuffer[index++] = v1;
  11147. uvBuffer[index++] = u;
  11148. uvBuffer[index++] = v;
  11149. } else {
  11150. uvBuffer[index++] = u;
  11151. uvBuffer[index++] = v;
  11152. uvBuffer[index++] = u1;
  11153. uvBuffer[index++] = v;
  11154. uvBuffer[index++] = u1;
  11155. uvBuffer[index++] = v1;
  11156. uvBuffer[index++] = u;
  11157. uvBuffer[index++] = v1;
  11158. }
  11159. },
  11160. /**
  11161. * Set the elapsed time needed to change the image index.
  11162. * @param fps an integer indicating the time in milliseconds to change.
  11163. * @return this
  11164. */
  11165. setChangeFPS : function(fps) {
  11166. this.changeFPS= fps;
  11167. return this;
  11168. },
  11169. /**
  11170. * Set the transformation to apply to the Sprite image.
  11171. * Any value of
  11172. * <li>TR_NONE
  11173. * <li>TR_FLIP_HORIZONTAL
  11174. * <li>TR_FLIP_VERTICAL
  11175. * <li>TR_FLIP_ALL
  11176. *
  11177. * @param transformation an integer indicating one of the previous values.
  11178. * @return this
  11179. */
  11180. setSpriteTransformation : function( transformation ) {
  11181. this.transformation= transformation;
  11182. switch(transformation) {
  11183. case this.TR_FLIP_HORIZONTAL:
  11184. this.paint= this.paintInvertedH;
  11185. break;
  11186. case this.TR_FLIP_VERTICAL:
  11187. this.paint= this.paintInvertedV;
  11188. break;
  11189. case this.TR_FLIP_ALL:
  11190. this.paint= this.paintInvertedHV;
  11191. break;
  11192. case this.TR_FIXED_TO_SIZE:
  11193. this.paint= this.paintScaled;
  11194. break;
  11195. case this.TR_TILE:
  11196. this.paint= this.paintTiled;
  11197. break;
  11198. default:
  11199. this.paint= this.paintN;
  11200. }
  11201. return this;
  11202. },
  11203. resetAnimationTime : function() {
  11204. this.prevAnimationTime= -1;
  11205. return this;
  11206. },
  11207. /**
  11208. * Set the sprite animation images index. This method accepts an array of objects which define indexes to
  11209. * subimages inside this sprite image.
  11210. * If the SpriteImage is instantiated by calling the method initialize( image, rows, cols ), the value of
  11211. * aAnimationImageIndex should be an array of numbers, which define the indexes into an array of subimages
  11212. * with size rows*columns.
  11213. * If the method InitializeFromMap( image, map ) is called, the value for aAnimationImageIndex is expected
  11214. * to be an array of strings which are the names of the subobjects contained in the map object.
  11215. *
  11216. * @param aAnimationImageIndex an array indicating the Sprite's frames.
  11217. */
  11218. setAnimationImageIndex : function( aAnimationImageIndex ) {
  11219. this.animationImageIndex= aAnimationImageIndex;
  11220. this.spriteIndex= aAnimationImageIndex[0];
  11221. this.prevAnimationTime= -1;
  11222. return this;
  11223. },
  11224. setSpriteIndex : function(index) {
  11225. this.spriteIndex= index;
  11226. return this;
  11227. },
  11228. /**
  11229. * Draws the sprite image calculated and stored in spriteIndex.
  11230. *
  11231. * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
  11232. * @param time an integer indicating the Scene time when the bounding box is to be drawn.
  11233. */
  11234. setSpriteIndexAtTime : function(time) {
  11235. if ( this.animationImageIndex.length>1 ) {
  11236. if ( this.prevAnimationTime===-1 ) {
  11237. this.prevAnimationTime= time;
  11238. this.spriteIndex=0;
  11239. }
  11240. else {
  11241. var ttime= time;
  11242. ttime-= this.prevAnimationTime;
  11243. ttime/= this.changeFPS;
  11244. ttime%= this.animationImageIndex.length;
  11245. this.spriteIndex= this.animationImageIndex[Math.floor(ttime)];
  11246. }
  11247. }
  11248. },
  11249. getMapInfo : function( index ) {
  11250. return this.mapInfo[ index ];
  11251. },
  11252. /**
  11253. * This method takes the output generated from the tool at http://labs.hyperandroid.com/static/texture/spriter.html
  11254. * and creates a map into that image.
  11255. * @param image {Image|HTMLImageElement|Canvas} an image
  11256. * @param map {object} the map into the image to define subimages.
  11257. */
  11258. initializeFromMap : function( image, map ) {
  11259. this.initialize( image, 1, 1 );
  11260. var key;
  11261. var helper;
  11262. var count=0;
  11263. for( key in map ) {
  11264. var value= map[key];
  11265. helper= new CAAT.SpriteImageHelper(
  11266. value.x,
  11267. value.y,
  11268. value.width,
  11269. value.height,
  11270. image.width,
  11271. image.height
  11272. );
  11273. this.mapInfo[key]= helper;
  11274. // set a default spriteIndex
  11275. if ( !count ) {
  11276. this.setAnimationImageIndex( [key] );
  11277. }
  11278. count++;
  11279. }
  11280. return this;
  11281. },
  11282. /**
  11283. *
  11284. * @param image {Image|HTMLImageElement|Canvas}
  11285. * @param map object with pairs "<a char>" : {
  11286. * id : {number},
  11287. * height : {number},
  11288. * xoffset : {number},
  11289. * letter : {string},
  11290. * yoffset : {number},
  11291. * width : {number},
  11292. * xadvance: {number},
  11293. * y : {number},
  11294. * x : {number}
  11295. * }
  11296. */
  11297. initializeAsGlyphDesigner : function( image, map ) {
  11298. this.initialize( image, 1, 1 );
  11299. var key;
  11300. var helper;
  11301. var count=0;
  11302. for( key in map ) {
  11303. var value= map[key];
  11304. helper= new CAAT.SpriteImageHelper(
  11305. value.x,
  11306. value.y,
  11307. value.width,
  11308. value.height,
  11309. image.width,
  11310. image.height
  11311. );
  11312. helper.xoffset= typeof value.xoffset==='undefined' ? 0 : value.xoffset;
  11313. helper.yoffset= typeof value.yoffset==='undefined' ? 0 : value.yoffset;
  11314. helper.xadvance= typeof value.xadvance==='undefined' ? value.width : value.xadvance;
  11315. this.mapInfo[key]= helper;
  11316. // set a default spriteIndex
  11317. if ( !count ) {
  11318. this.setAnimationImageIndex( [key] );
  11319. }
  11320. count++;
  11321. }
  11322. return this;
  11323. },
  11324. /**
  11325. *
  11326. * @param image
  11327. * @param map: Array<{c: "a", width: 40}>
  11328. */
  11329. initializeAsFontMap : function( image, chars ) {
  11330. this.initialize( image, 1, 1 );
  11331. var helper;
  11332. var x=0;
  11333. for( var i=0;i<chars.length;i++ ) {
  11334. var value= chars[i];
  11335. helper= new CAAT.SpriteImageHelper(
  11336. x,
  11337. 0,
  11338. value.width,
  11339. image.height,
  11340. image.width,
  11341. image.height
  11342. );
  11343. helper.xoffset= 0;
  11344. helper.yoffset= 0;
  11345. helper.xadvance= value.width;
  11346. x += value.width;
  11347. this.mapInfo[chars[i].c]= helper;
  11348. // set a default spriteIndex
  11349. if ( !i ) {
  11350. this.setAnimationImageIndex( [chars[i].c] );
  11351. }
  11352. }
  11353. return this;
  11354. },
  11355. /**
  11356. * This method creates a font sprite image based on a proportional font
  11357. * It assumes the font is evenly spaced in the image
  11358. * Example:
  11359. * var font = new CAAT.SpriteImage().initializeAsMonoTypeFontMap(
  11360. * director.getImage('numbers'),
  11361. * "0123456789"
  11362. * );
  11363. */
  11364. initializeAsMonoTypeFontMap : function( image, chars ) {
  11365. var map = [];
  11366. var charArr = chars.split("");
  11367. var w = image.width / charArr.length >> 0;
  11368. for( var i=0;i<charArr.length;i++ ) {
  11369. map.push({c: charArr[i], width: w });
  11370. }
  11371. return this.initializeAsFontMap(image,map);
  11372. },
  11373. stringWidth : function( str ) {
  11374. var i,l,w=0,charInfo;
  11375. for( i=0, l=str.length; i<l; i++ ) {
  11376. charInfo= this.mapInfo[ str.charAt(i) ];
  11377. if ( charInfo ) {
  11378. w+= charInfo.xadvance;
  11379. }
  11380. }
  11381. return w;
  11382. },
  11383. stringHeight : function() {
  11384. if ( this.fontHeight ) {
  11385. return this.fontHeight;
  11386. }
  11387. var y= 0;
  11388. for( var i in this.mapInfo ) {
  11389. var mi= this.mapInfo[i];
  11390. var h= mi.height+mi.yoffset;
  11391. if ( h>y ) {
  11392. y=h;
  11393. }
  11394. }
  11395. this.fontHeight= y;
  11396. return this.fontHeight;
  11397. },
  11398. drawString : function( ctx, str, x, y ) {
  11399. var i, l, charInfo, w;
  11400. var charArr = str.split("");
  11401. for( i=0; i<charArr.length; i++ ) {
  11402. charInfo= this.mapInfo[ charArr[i] ];
  11403. if ( charInfo ) {
  11404. w= charInfo.width;
  11405. ctx.drawImage(
  11406. this.image,
  11407. charInfo.x, charInfo.y,
  11408. w, charInfo.height,
  11409. x + charInfo.xoffset, y + charInfo.yoffset,
  11410. w, charInfo.height );
  11411. x+= charInfo.xadvance;
  11412. }
  11413. }
  11414. }
  11415. };
  11416. })();
  11417. /**
  11418. * See LICENSE file.
  11419. *
  11420. * Image/Resource preloader.
  11421. *
  11422. *
  11423. **/
  11424. (function() {
  11425. /**
  11426. * This class is a image resource loader. It accepts an object of the form:
  11427. *
  11428. * {
  11429. * id1: string_url1,
  11430. * id2: string_url2,
  11431. * id3: string_url3,
  11432. * ...
  11433. * }
  11434. *
  11435. * and on resources loaded correctly, will return an object of the form:
  11436. *
  11437. * {
  11438. * id1: HTMLImageElement,
  11439. * id2: HTMLImageElement,
  11440. * id3: HTMLImageElement,
  11441. * ...
  11442. * }
  11443. *
  11444. * @constructor
  11445. */
  11446. CAAT.ImagePreloader = function() {
  11447. this.images = [];
  11448. return this;
  11449. };
  11450. CAAT.ImagePreloader.prototype = {
  11451. images: null, // a list of elements to load
  11452. notificationCallback: null, // notification callback invoked for each image loaded.
  11453. imageCounter: 0, // elements counter.
  11454. /**
  11455. * Start images loading asynchronous process. This method will notify every image loaded event
  11456. * and is responsibility of the caller to count the number of loaded images to see if it fits his
  11457. * needs.
  11458. *
  11459. * @param aImages {{ id:{url}, id2:{url}, ...} an object with id/url pairs.
  11460. * @param callback_loaded_one_image {function( imageloader {CAAT.ImagePreloader}, counter {number}, images {{ id:{string}, image: {Image}}} )}
  11461. * function to call on every image load.
  11462. */
  11463. loadImages: function( aImages, callback_loaded_one_image, callback_error ) {
  11464. if (!aImages) {
  11465. if (callback_loaded_one_image ) {
  11466. callback_loaded_one_image(0,[]);
  11467. }
  11468. }
  11469. var me= this, i;
  11470. this.notificationCallback = callback_loaded_one_image;
  11471. this.images= [];
  11472. for( i=0; i<aImages.length; i++ ) {
  11473. this.images.push( {id:aImages[i].id, image: new Image() } );
  11474. }
  11475. for( i=0; i<aImages.length; i++ ) {
  11476. this.images[i].image.onload = function imageLoaded() {
  11477. me.imageCounter++;
  11478. me.notificationCallback(me.imageCounter, me.images);
  11479. };
  11480. this.images[i].image.onerror= (function(index) {
  11481. return function(e) {
  11482. if ( callback_error ) {
  11483. callback_error( e, index );
  11484. }
  11485. }
  11486. })(i);
  11487. this.images[i].image.src= aImages[i].url;
  11488. }
  11489. if ( aImages.length===0 ) {
  11490. callback_loaded_one_image(0,[]);
  11491. }
  11492. }
  11493. };
  11494. })();/**
  11495. * See LICENSE file.
  11496. */
  11497. (function() {
  11498. /**
  11499. * This class defines a timer action which is constrained to Scene time, so every Scene has the
  11500. * abbility to create its own TimerTask objects. They must not be created by calling scene's
  11501. * createTime method.
  11502. *
  11503. * <p>
  11504. * A TimerTask is defined at least by:
  11505. * <ul>
  11506. * <li>startTime: since when the timer will be active
  11507. * <li>duration: from startTime to startTime+duration, the timerTask will be notifying (if set) the callback callback_tick.
  11508. * </ul>
  11509. * <p>
  11510. * Upon TimerTask expiration, the TimerTask will notify (if set) the callback function callback_timeout.
  11511. * Upon a call to the method cancel, the timer will be set expired, and (if set) the callback to callback_cancel will be
  11512. * invoked.
  11513. * <p>
  11514. * Timer notifications will be performed <strong>BEFORE<strong> scene loop.
  11515. *
  11516. * @constructor
  11517. *
  11518. */
  11519. CAAT.TimerTask= function() {
  11520. return this;
  11521. };
  11522. CAAT.TimerTask.prototype= {
  11523. startTime: 0,
  11524. duration: 0,
  11525. callback_timeout: null,
  11526. callback_tick: null,
  11527. callback_cancel: null,
  11528. scene: null,
  11529. taskId: 0,
  11530. remove: false,
  11531. /**
  11532. * Create a TimerTask.
  11533. * The taskId will be set by the scene.
  11534. * @param startTime {number} an integer indicating TimerTask enable time.
  11535. * @param duration {number} an integer indicating TimerTask duration.
  11536. * @param callback_timeout {function( sceneTime {number}, timertaskTime{number}, timertask {CAAT.TimerTask} )} on timeout callback function.
  11537. * @param callback_tick {function( sceneTime {number}, timertaskTime{number}, timertask {CAAT.TimerTask} )} on tick callback function.
  11538. * @param callback_cancel {function( sceneTime {number}, timertaskTime{number}, timertask {CAAT.TimerTask} )} on cancel callback function.
  11539. *
  11540. * @return this
  11541. */
  11542. create: function( startTime, duration, callback_timeout, callback_tick, callback_cancel ) {
  11543. this.startTime= startTime;
  11544. this.duration= duration;
  11545. this.callback_timeout= callback_timeout;
  11546. this.callback_tick= callback_tick;
  11547. this.callback_cancel= callback_cancel;
  11548. return this;
  11549. },
  11550. /**
  11551. * Performs TimerTask operation. The task will check whether it is in frame time, and will
  11552. * either notify callback_timeout or callback_tick.
  11553. *
  11554. * @param time {number} an integer indicating scene time.
  11555. * @return this
  11556. *
  11557. * @protected
  11558. *
  11559. */
  11560. checkTask : function(time) {
  11561. var ttime= time;
  11562. ttime-= this.startTime;
  11563. if ( ttime>=this.duration ) {
  11564. this.remove= true;
  11565. if( this.callback_timeout ) {
  11566. this.callback_timeout( time, ttime, this );
  11567. }
  11568. } else {
  11569. if ( this.callback_tick ) {
  11570. this.callback_tick( time, ttime, this );
  11571. }
  11572. }
  11573. return this;
  11574. },
  11575. /**
  11576. * Reschedules this TimerTask by changing its startTime to current scene's time.
  11577. * @param time {number} an integer indicating scene time.
  11578. * @return this
  11579. */
  11580. reset : function( time ) {
  11581. this.remove= false;
  11582. this.startTime= time;
  11583. this.scene.ensureTimerTask(this);
  11584. return this;
  11585. },
  11586. /**
  11587. * Cancels this timer by removing it on scene's next frame. The function callback_cancel will
  11588. * be called.
  11589. * @return this
  11590. */
  11591. cancel : function() {
  11592. this.remove= true;
  11593. if ( null!=this.callback_cancel ) {
  11594. this.callback_cancel( this.scene.time, this.scene.time-this.startTime, this );
  11595. }
  11596. return this;
  11597. }
  11598. };
  11599. })();
  11600. /**
  11601. * See LICENSE file.
  11602. *
  11603. */
  11604. (function() {
  11605. /**
  11606. * Scene is the top level ActorContainer of the Director at any given time.
  11607. * The only time when 2 scenes could be active will be during scene change.
  11608. * An scene controls the way it enters/exits the scene graph. It is also the entry point for all
  11609. * input related and timed related events to every actor on screen.
  11610. *
  11611. * @constructor
  11612. * @extends CAAT.ActorContainer
  11613. *
  11614. */
  11615. CAAT.Scene= function() {
  11616. CAAT.Scene.superclass.constructor.call(this);
  11617. this.timerList= [];
  11618. this.fillStyle= null;
  11619. return this;
  11620. };
  11621. CAAT.Scene.prototype= {
  11622. easeContainerBehaviour: null, // Behavior container used uniquely for Scene switching.
  11623. easeContainerBehaviourListener: null, // who to notify about container behaviour events. Array.
  11624. easeIn: false, // When Scene switching, this boolean identifies whether the
  11625. // Scene is being brought in, or taken away.
  11626. EASE_ROTATION: 1, // Constant values to identify the type of Scene transition
  11627. EASE_SCALE: 2, // to perform on Scene switching by the Director.
  11628. EASE_TRANSLATE: 3,
  11629. timerList: null, // collection of CAAT.TimerTask objects.
  11630. timerSequence: 0, // incremental CAAT.TimerTask id.
  11631. paused: false,
  11632. isPaused : function() {
  11633. return this.paused;
  11634. },
  11635. setPaused : function( paused ) {
  11636. this.paused= paused;
  11637. },
  11638. /**
  11639. * Check and apply timers in frame time.
  11640. * @param time {number} the current Scene time.
  11641. */
  11642. checkTimers : function(time) {
  11643. var tl= this.timerList;
  11644. var i=tl.length-1;
  11645. while( i>=0 ) {
  11646. if ( !tl[i].remove ) {
  11647. tl[i].checkTask(time);
  11648. }
  11649. i--;
  11650. }
  11651. },
  11652. /**
  11653. * Make sure the timertask is contained in the timer task list by adding it to the list in case it
  11654. * is not contained.
  11655. * @param timertask {CAAT.TimerTask} a CAAT.TimerTask object.
  11656. * @return this
  11657. */
  11658. ensureTimerTask : function( timertask ) {
  11659. if ( !this.hasTimer(timertask) ) {
  11660. this.timerList.push(timertask);
  11661. }
  11662. return this;
  11663. },
  11664. /**
  11665. * Check whether the timertask is in this scene's timer task list.
  11666. * @param timertask {CAAT.TimerTask} a CAAT.TimerTask object.
  11667. * @return {boolean} a boolean indicating whether the timertask is in this scene or not.
  11668. */
  11669. hasTimer : function( timertask ) {
  11670. var tl= this.timerList;
  11671. var i=tl.length-1;
  11672. while( i>=0 ) {
  11673. if ( tl[i]===timertask ) {
  11674. return true;
  11675. }
  11676. i--;
  11677. }
  11678. return false;
  11679. },
  11680. /**
  11681. * Creates a timer task. Timertask object live and are related to scene's time, so when an Scene
  11682. * is taken out of the Director the timer task is paused, and resumed on Scene restoration.
  11683. *
  11684. * @param startTime {number} an integer indicating the scene time this task must start executing at.
  11685. * @param duration {number} an integer indicating the timerTask duration.
  11686. * @param callback_timeout {function} timer on timeout callback function.
  11687. * @param callback_tick {function} timer on tick callback function.
  11688. * @param callback_cancel {function} timer on cancel callback function.
  11689. *
  11690. * @return {CAAT.TimerTask} a CAAT.TimerTask class instance.
  11691. */
  11692. createTimer : function( startTime, duration, callback_timeout, callback_tick, callback_cancel ) {
  11693. var tt= new CAAT.TimerTask().create(
  11694. startTime,
  11695. duration,
  11696. callback_timeout,
  11697. callback_tick,
  11698. callback_cancel );
  11699. tt.taskId= this.timerSequence++;
  11700. tt.sceneTime = this.time;
  11701. tt.scene= this;
  11702. this.timerList.push( tt );
  11703. return tt;
  11704. },
  11705. /**
  11706. * Removes expired timers. This method must not be called directly.
  11707. */
  11708. removeExpiredTimers : function() {
  11709. var i;
  11710. var tl= this.timerList;
  11711. for( i=0; i<tl.length; i++ ) {
  11712. if ( tl[i].remove ) {
  11713. tl.splice(i,1);
  11714. }
  11715. }
  11716. },
  11717. /**
  11718. * Scene animation method.
  11719. * It extends Container's base behavior by adding timer control.
  11720. * @param director {CAAT.Director} a CAAT.Director instance.
  11721. * @param time {number} an integer indicating the Scene time the animation is being performed at.
  11722. */
  11723. animate : function(director, time) {
  11724. this.checkTimers(time);
  11725. CAAT.Scene.superclass.animate.call(this,director,time);
  11726. this.removeExpiredTimers();
  11727. },
  11728. /**
  11729. * Helper method to manage alpha transparency fading on Scene switch by the Director.
  11730. * @param time {number} integer indicating the time in milliseconds the fading will take.
  11731. * @param isIn {boolean} boolean indicating whether this Scene in the switch process is
  11732. * being brought in.
  11733. *
  11734. * @private
  11735. */
  11736. createAlphaBehaviour: function(time, isIn) {
  11737. var ab= new CAAT.AlphaBehavior();
  11738. ab.setFrameTime( 0, time );
  11739. ab.startAlpha= isIn ? 0 : 1;
  11740. ab.endAlpha= isIn ? 1 : 0;
  11741. this.easeContainerBehaviour.addBehavior(ab);
  11742. },
  11743. /**
  11744. * Called from CAAT.Director to bring in an Scene.
  11745. * A helper method for easeTranslation.
  11746. * @param time integer indicating time in milliseconds for the Scene to be brought in.
  11747. * @param alpha boolean indicating whether fading will be applied to the Scene.
  11748. * @param anchor integer indicating the Scene switch anchor.
  11749. * @param interpolator CAAT.Interpolator to apply to the Scene transition.
  11750. */
  11751. easeTranslationIn : function( time, alpha, anchor, interpolator ) {
  11752. this.easeTranslation( time, alpha, anchor, true, interpolator );
  11753. },
  11754. /**
  11755. * Called from CAAT.Director to bring in an Scene.
  11756. * A helper method for easeTranslation.
  11757. * @param time integer indicating time in milliseconds for the Scene to be taken away.
  11758. * @param alpha boolean indicating whether fading will be applied to the Scene.
  11759. * @param anchor integer indicating the Scene switch anchor.
  11760. * @param interpolator CAAT.Interpolator to apply to the Scene transition.
  11761. */
  11762. easeTranslationOut : function( time, alpha, anchor, interpolator ) {
  11763. this.easeTranslation( time, alpha, anchor, false, interpolator );
  11764. },
  11765. /**
  11766. * This method will setup Scene behaviours to switch an Scene via a translation.
  11767. * The anchor value can only be
  11768. * <li>CAAT.Actor.prototype.ANCHOR_LEFT
  11769. * <li>CAAT.Actor.prototype.ANCHOR_RIGHT
  11770. * <li>CAAT.Actor.prototype.ANCHOR_TOP
  11771. * <li>CAAT.Actor.prototype.ANCHOR_BOTTOM
  11772. * if any other value is specified, any of the previous ones will be applied.
  11773. *
  11774. * @param time integer indicating time in milliseconds for the Scene.
  11775. * @param alpha boolean indicating whether fading will be applied to the Scene.
  11776. * @param anchor integer indicating the Scene switch anchor.
  11777. * @param isIn boolean indicating whether the scene will be brought in.
  11778. * @param interpolator {CAAT.Interpolator} a CAAT.Interpolator to apply to the Scene transition.
  11779. */
  11780. easeTranslation : function( time, alpha, anchor, isIn, interpolator ) {
  11781. this.easeContainerBehaviour= new CAAT.ContainerBehavior();
  11782. this.easeIn= isIn;
  11783. var pb= new CAAT.PathBehavior();
  11784. if ( interpolator ) {
  11785. pb.setInterpolator( interpolator );
  11786. }
  11787. pb.setFrameTime( 0, time );
  11788. // BUGBUG anchors: 1..4
  11789. if ( anchor<1 ) {
  11790. anchor=1;
  11791. } else if ( anchor>4 ) {
  11792. anchor= 4;
  11793. }
  11794. switch(anchor) {
  11795. case CAAT.Actor.prototype.ANCHOR_TOP:
  11796. if ( isIn ) {
  11797. pb.setPath( new CAAT.Path().setLinear( 0, -this.height, 0, 0) );
  11798. } else {
  11799. pb.setPath( new CAAT.Path().setLinear( 0, 0, 0, -this.height) );
  11800. }
  11801. break;
  11802. case CAAT.Actor.prototype.ANCHOR_BOTTOM:
  11803. if ( isIn ) {
  11804. pb.setPath( new CAAT.Path().setLinear( 0, this.height, 0, 0) );
  11805. } else {
  11806. pb.setPath( new CAAT.Path().setLinear( 0, 0, 0, this.height) );
  11807. }
  11808. break;
  11809. case CAAT.Actor.prototype.ANCHOR_LEFT:
  11810. if ( isIn ) {
  11811. pb.setPath( new CAAT.Path().setLinear( -this.width, 0, 0, 0) );
  11812. } else {
  11813. pb.setPath( new CAAT.Path().setLinear( 0, 0, -this.width, 0) );
  11814. }
  11815. break;
  11816. case CAAT.Actor.prototype.ANCHOR_RIGHT:
  11817. if ( isIn ) {
  11818. pb.setPath( new CAAT.Path().setLinear( this.width, 0, 0, 0) );
  11819. } else {
  11820. pb.setPath( new CAAT.Path().setLinear( 0, 0, this.width, 0) );
  11821. }
  11822. break;
  11823. }
  11824. if (alpha) {
  11825. this.createAlphaBehaviour(time,isIn);
  11826. }
  11827. this.easeContainerBehaviour.addBehavior(pb);
  11828. this.easeContainerBehaviour.setFrameTime( this.time, time );
  11829. this.easeContainerBehaviour.addListener(this);
  11830. this.emptyBehaviorList();
  11831. CAAT.Scene.superclass.addBehavior.call( this, this.easeContainerBehaviour );
  11832. },
  11833. /**
  11834. * Called from CAAT.Director to bring in a Scene.
  11835. * A helper method for easeScale.
  11836. * @param time integer indicating time in milliseconds for the Scene to be brought in.
  11837. * @param alpha boolean indicating whether fading will be applied to the Scene.
  11838. * @param anchor integer indicating the Scene switch anchor.
  11839. * @param interpolator {CAAT.Interpolator} a CAAT.Interpolator to apply to the Scene transition.
  11840. * @param starttime integer indicating in milliseconds from which scene time the behavior will be applied.
  11841. */
  11842. easeScaleIn : function(starttime,time,alpha,anchor,interpolator) {
  11843. this.easeScale(starttime,time,alpha,anchor,true,interpolator);
  11844. this.easeIn= true;
  11845. },
  11846. /**
  11847. * Called from CAAT.Director to take away a Scene.
  11848. * A helper method for easeScale.
  11849. * @param time integer indicating time in milliseconds for the Scene to be taken away.
  11850. * @param alpha boolean indicating whether fading will be applied to the Scene.
  11851. * @param anchor integer indicating the Scene switch anchor.
  11852. * @param interpolator {CAAT.Interpolator} a CAAT.Interpolator instance to apply to the Scene transition.
  11853. * @param starttime integer indicating in milliseconds from which scene time the behavior will be applied.
  11854. */
  11855. easeScaleOut : function(starttime,time,alpha,anchor,interpolator) {
  11856. this.easeScale(starttime,time,alpha,anchor,false,interpolator);
  11857. this.easeIn= false;
  11858. },
  11859. /**
  11860. * Called from CAAT.Director to bring in ot take away an Scene.
  11861. * @param time integer indicating time in milliseconds for the Scene to be taken away.
  11862. * @param alpha boolean indicating whether fading will be applied to the Scene.
  11863. * @param anchor integer indicating the Scene switch anchor.
  11864. * @param interpolator {CAAT.Interpolator} a CAAT.Interpolator to apply to the Scene transition.
  11865. * @param starttime integer indicating in milliseconds from which scene time the behavior will be applied.
  11866. * @param isIn boolean indicating whether the Scene is being brought in.
  11867. */
  11868. easeScale : function(starttime,time,alpha,anchor,isIn,interpolator) {
  11869. this.easeContainerBehaviour= new CAAT.ContainerBehavior();
  11870. var x=0;
  11871. var y=0;
  11872. var x2=0;
  11873. var y2=0;
  11874. switch(anchor) {
  11875. case CAAT.Actor.prototype.ANCHOR_TOP_LEFT:
  11876. case CAAT.Actor.prototype.ANCHOR_TOP_RIGHT:
  11877. case CAAT.Actor.prototype.ANCHOR_BOTTOM_LEFT:
  11878. case CAAT.Actor.prototype.ANCHOR_BOTTOM_RIGHT:
  11879. case CAAT.Actor.prototype.ANCHOR_CENTER:
  11880. x2=1;
  11881. y2=1;
  11882. break;
  11883. case CAAT.Actor.prototype.ANCHOR_TOP:
  11884. case CAAT.Actor.prototype.ANCHOR_BOTTOM:
  11885. x=1;
  11886. x2=1;
  11887. y=0;
  11888. y2=1;
  11889. break;
  11890. case CAAT.Actor.prototype.ANCHOR_LEFT:
  11891. case CAAT.Actor.prototype.ANCHOR_RIGHT:
  11892. y=1;
  11893. y2=1;
  11894. x=0;
  11895. x2=1;
  11896. break;
  11897. default:
  11898. alert('scale anchor ?? '+anchor);
  11899. }
  11900. if ( !isIn ) {
  11901. var tmp;
  11902. tmp= x;
  11903. x= x2;
  11904. x2= tmp;
  11905. tmp= y;
  11906. y= y2;
  11907. y2= tmp;
  11908. }
  11909. if (alpha) {
  11910. this.createAlphaBehaviour(time,isIn);
  11911. }
  11912. var anchorPercent= this.getAnchorPercent(anchor);
  11913. var sb= new CAAT.ScaleBehavior().
  11914. setFrameTime( starttime, time ).
  11915. setValues(x,x2,y,y2, anchorPercent.x, anchorPercent.y);
  11916. if ( interpolator ) {
  11917. sb.setInterpolator(interpolator);
  11918. }
  11919. this.easeContainerBehaviour.addBehavior(sb);
  11920. this.easeContainerBehaviour.setFrameTime( this.time, time );
  11921. this.easeContainerBehaviour.addListener(this);
  11922. this.emptyBehaviorList();
  11923. CAAT.Scene.superclass.addBehavior.call( this, this.easeContainerBehaviour );
  11924. },
  11925. /**
  11926. * Overriden method to disallow default behavior.
  11927. * Do not use directly.
  11928. */
  11929. addBehavior : function(behaviour) {
  11930. return this;
  11931. },
  11932. /**
  11933. * Called from CAAT.Director to use Rotations for bringing in.
  11934. * This method is a Helper for the method easeRotation.
  11935. * @param time integer indicating time in milliseconds for the Scene to be brought in.
  11936. * @param alpha boolean indicating whether fading will be applied to the Scene.
  11937. * @param anchor integer indicating the Scene switch anchor.
  11938. * @param interpolator {CAAT.Interpolator} a CAAT.Interpolator to apply to the Scene transition.
  11939. */
  11940. easeRotationIn : function(time,alpha,anchor,interpolator) {
  11941. this.easeRotation(time,alpha,anchor,true, interpolator);
  11942. this.easeIn= true;
  11943. },
  11944. /**
  11945. * Called from CAAT.Director to use Rotations for taking Scenes away.
  11946. * This method is a Helper for the method easeRotation.
  11947. * @param time integer indicating time in milliseconds for the Scene to be taken away.
  11948. * @param alpha boolean indicating whether fading will be applied to the Scene.
  11949. * @param anchor integer indicating the Scene switch anchor.
  11950. * @param interpolator {CAAT.Interpolator} a CAAT.Interpolator to apply to the Scene transition.
  11951. */
  11952. easeRotationOut : function(time,alpha,anchor,interpolator) {
  11953. this.easeRotation(time,alpha,anchor,false,interpolator);
  11954. this.easeIn= false;
  11955. },
  11956. /**
  11957. * Called from CAAT.Director to use Rotations for taking away or bringing Scenes in.
  11958. * @param time integer indicating time in milliseconds for the Scene to be taken away or brought in.
  11959. * @param alpha boolean indicating whether fading will be applied to the Scene.
  11960. * @param anchor integer indicating the Scene switch anchor.
  11961. * @param interpolator {CAAT.Interpolator} a CAAT.Interpolator to apply to the Scene transition.
  11962. * @param isIn boolean indicating whehter the Scene is brought in.
  11963. */
  11964. easeRotation : function(time,alpha,anchor,isIn,interpolator) {
  11965. this.easeContainerBehaviour= new CAAT.ContainerBehavior();
  11966. var start=0;
  11967. var end=0;
  11968. if (anchor==CAAT.Actor.prototype.ANCHOR_CENTER ) {
  11969. anchor= CAAT.Actor.prototype.ANCHOR_TOP;
  11970. }
  11971. switch(anchor) {
  11972. case CAAT.Actor.prototype.ANCHOR_TOP:
  11973. case CAAT.Actor.prototype.ANCHOR_BOTTOM:
  11974. case CAAT.Actor.prototype.ANCHOR_LEFT:
  11975. case CAAT.Actor.prototype.ANCHOR_RIGHT:
  11976. start= Math.PI * (Math.random()<0.5 ? 1 : -1);
  11977. break;
  11978. case CAAT.Actor.prototype.ANCHOR_TOP_LEFT:
  11979. case CAAT.Actor.prototype.ANCHOR_TOP_RIGHT:
  11980. case CAAT.Actor.prototype.ANCHOR_BOTTOM_LEFT:
  11981. case CAAT.Actor.prototype.ANCHOR_BOTTOM_RIGHT:
  11982. start= Math.PI/2 * (Math.random()<0.5 ? 1 : -1);
  11983. break;
  11984. default:
  11985. alert('rot anchor ?? '+anchor);
  11986. }
  11987. if ( false===isIn ) {
  11988. var tmp= start;
  11989. start=end;
  11990. end= tmp;
  11991. }
  11992. if ( alpha ) {
  11993. this.createAlphaBehaviour(time,isIn);
  11994. }
  11995. var anchorPercent= this.getAnchorPercent(anchor);
  11996. var rb= new CAAT.RotateBehavior().
  11997. setFrameTime( 0, time ).
  11998. setValues( start, end, anchorPercent.x, anchorPercent.y );
  11999. if ( interpolator ) {
  12000. rb.setInterpolator(interpolator);
  12001. }
  12002. this.easeContainerBehaviour.addBehavior(rb);
  12003. this.easeContainerBehaviour.setFrameTime( this.time, time );
  12004. this.easeContainerBehaviour.addListener(this);
  12005. this.emptyBehaviorList();
  12006. CAAT.Scene.superclass.addBehavior.call( this, this.easeContainerBehaviour );
  12007. },
  12008. /**
  12009. * Registers a listener for listen for transitions events.
  12010. * Al least, the Director registers himself as Scene easing transition listener.
  12011. * When the transition is done, it restores the Scene's capability of receiving events.
  12012. * @param listener {function(caat_behavior,time,actor)} an object which contains a method of the form <code>
  12013. * behaviorExpired( caat_behaviour, time, actor);
  12014. */
  12015. setEaseListener : function( listener ) {
  12016. this.easeContainerBehaviourListener=listener;
  12017. },
  12018. /**
  12019. * Private.
  12020. * listener for the Scene's easeContainerBehaviour.
  12021. * @param actor
  12022. */
  12023. behaviorExpired : function(actor) {
  12024. this.easeContainerBehaviourListener.easeEnd(this, this.easeIn);
  12025. },
  12026. /**
  12027. * This method should be overriden in case the developer wants to do some special actions when
  12028. * the scene has just been brought in.
  12029. */
  12030. activated : function() {
  12031. },
  12032. /**
  12033. * Scenes, do not expire the same way Actors do.
  12034. * It simply will be set expired=true, but the frameTime won't be modified.
  12035. */
  12036. setExpired : function(bExpired) {
  12037. this.expired= bExpired;
  12038. },
  12039. /**
  12040. * An scene by default does not paint anything because has not fillStyle set.
  12041. * @param director
  12042. * @param time
  12043. */
  12044. paint : function(director, time) {
  12045. if ( this.fillStyle ) {
  12046. var ctx= director.crc;
  12047. ctx.fillStyle= this.fillStyle;
  12048. ctx.fillRect(0,0,this.width,this.height );
  12049. }
  12050. },
  12051. /**
  12052. * Find a pointed actor at position point.
  12053. * This method tries lo find the correctly pointed actor in two different ways.
  12054. * + first of all, if inputList is defined, it will look for an actor in it.
  12055. * + if no inputList is defined, it will traverse the scene graph trying to find a pointed actor.
  12056. * @param point <CAAT.Point>
  12057. */
  12058. findActorAtPosition : function(point) {
  12059. var i,j;
  12060. var p= new CAAT.Point();
  12061. if ( this.inputList ) {
  12062. var il= this.inputList;
  12063. for( i=0; i<il.length; i++ ) {
  12064. var ill= il[i];
  12065. for( j=0; j<ill.length; j++ ) {
  12066. p.set(point.x, point.y);
  12067. var modelViewMatrixI= ill[j].worldModelViewMatrix.getInverse();
  12068. modelViewMatrixI.transformCoord(p);
  12069. if ( ill[j].contains(p.x, p.y) ) {
  12070. return ill[j];
  12071. }
  12072. }
  12073. }
  12074. }
  12075. p.set(point.x, point.y);
  12076. return CAAT.Scene.superclass.findActorAtPosition.call(this,p);
  12077. },
  12078. /**
  12079. * Enable a number of input lists.
  12080. * These lists are set in case the developer doesn't want the to traverse the scene graph to find the pointed
  12081. * actor. The lists are a shortcut whete the developer can set what actors to look for input at first instance.
  12082. * The system will traverse the whole lists in order trying to find a pointed actor.
  12083. *
  12084. * Elements are added to each list either in head or tail.
  12085. *
  12086. * @param size <number> number of lists.
  12087. */
  12088. enableInputList : function( size ) {
  12089. this.inputList= [];
  12090. for( var i=0; i<size; i++ ) {
  12091. this.inputList.push([]);
  12092. }
  12093. return this;
  12094. },
  12095. /**
  12096. * Add an actor to a given inputList.
  12097. * @param actor <CAAT.Actor> an actor instance
  12098. * @param index <number> the inputList index to add the actor to. This value will be clamped to the number of
  12099. * available lists.
  12100. * @param position <number> the position on the selected inputList to add the actor at. This value will be
  12101. * clamped to the number of available lists.
  12102. */
  12103. addActorToInputList : function( actor, index, position ) {
  12104. if ( index<0 ) index=0; else if ( index>=this.inputList.length ) index= this.inputList.length-1;
  12105. var il= this.inputList[index];
  12106. if ( typeof position==="undefined" || position>=il.length ) {
  12107. il.push( actor );
  12108. } else if (position<=0) {
  12109. il.unshift( actor );
  12110. } else {
  12111. il.splice( position, 0, actor );
  12112. }
  12113. return this;
  12114. },
  12115. /**
  12116. * Remove all elements from an input list.
  12117. * @param index <number> the inputList index to add the actor to. This value will be clamped to the number of
  12118. * available lists so take care when emptying a non existant inputList index since you could end up emptying
  12119. * an undesired input list.
  12120. */
  12121. emptyInputList : function( index ) {
  12122. if ( index<0 ) index=0; else if ( index>=this.inputList.length ) index= this.inputList.length-1;
  12123. this.inputList[index]= [];
  12124. return this;
  12125. },
  12126. /**
  12127. * remove an actor from a given input list index.
  12128. * If no index is supplied, the actor will be removed from every input list.
  12129. * @param actor <CAAT.Actor>
  12130. * @param index <!number> an optional input list index. This value will be clamped to the number of
  12131. * available lists.
  12132. */
  12133. removeActorFromInputList : function( actor, index ) {
  12134. if ( typeof index==="undefined" ) {
  12135. var i,j;
  12136. for( i=0; i<this.inputList.length; i++ ) {
  12137. var il= this.inputList[i];
  12138. for( j=0; j<il.length; j++ ) {
  12139. if ( il[j]==actor ) {
  12140. il.splice( j,1 );
  12141. }
  12142. }
  12143. }
  12144. return this;
  12145. }
  12146. if ( index<0 ) index=0; else if ( index>=this.inputList.length ) index= this.inputList.length-1;
  12147. var il= this.inputList[index];
  12148. for( j=0; j<il.length; j++ ) {
  12149. if ( il[j]==actor ) {
  12150. il.splice( j,1 );
  12151. }
  12152. }
  12153. return this;
  12154. }
  12155. };
  12156. extend( CAAT.Scene, CAAT.ActorContainer );
  12157. })();/**
  12158. * See LICENSE file.
  12159. *
  12160. * @author Mario Gonzalez || http://onedayitwillmake.com
  12161. *
  12162. **/
  12163. /**
  12164. * @namespace
  12165. */
  12166. CAAT.modules = CAAT.modules || {};
  12167. /**
  12168. * @namespace
  12169. */
  12170. CAAT.modules.CircleManager = CAAT.modules.CircleManager || {};/**
  12171. * See LICENSE file.
  12172. *
  12173. #### ##### ##### #### ### # # ###### ###### ## ## ##### # # ######## ## # # #####
  12174. # # # # ### # # ##### ### ## ## ## # ## # # # # ## # ##### ### ###
  12175. ### # # ##### #### # # # ###### ## ######### ##### ##### ##### # ## # # # # # #####
  12176. -
  12177. File:
  12178. PackedCircle.js
  12179. Created By:
  12180. Mario Gonzalez
  12181. Project :
  12182. None
  12183. Abstract:
  12184. A single packed circle.
  12185. Contains a reference to it's div, and information pertaining to it state.
  12186. Basic Usage:
  12187. http://onedayitwillmake.com/CirclePackJS/
  12188. */
  12189. (function() {
  12190. /**
  12191. * @constructor
  12192. */
  12193. CAAT.modules.CircleManager.PackedCircle= function()
  12194. {
  12195. this.boundsRule = CAAT.modules.CircleManager.PackedCircle.BOUNDS_RULE_IGNORE;
  12196. this.position = new CAAT.Point(0,0,0);
  12197. this.offset = new CAAT.Point(0,0,0);
  12198. this.targetPosition = new CAAT.Point(0,0,0);
  12199. return this;
  12200. };
  12201. CAAT.modules.CircleManager.PackedCircle.prototype = {
  12202. id: 0,
  12203. delegate: null,
  12204. position: new CAAT.Point(0,0,0),
  12205. offset: new CAAT.Point(0,0,0), // Offset from delegates position by this much
  12206. targetPosition: null, // Where it wants to go
  12207. targetChaseSpeed: 0.02,
  12208. isFixed: false,
  12209. boundsRule: 0,
  12210. collisionMask: 0,
  12211. collisionGroup: 0,
  12212. BOUNDS_RULE_WRAP: 1, // Wrap to otherside
  12213. BOUNDS_RULE_CONSTRAINT: 2, // Constrain within bounds
  12214. BOUNDS_RULE_DESTROY: 4, // Destroy when it reaches the edge
  12215. BOUNDS_RULE_IGNORE: 8, // Ignore when reaching bounds
  12216. containsPoint: function(aPoint)
  12217. {
  12218. var distanceSquared = this.position.getDistanceSquared(aPoint);
  12219. return distanceSquared < this.radiusSquared;
  12220. },
  12221. getDistanceSquaredFromPosition: function(aPosition)
  12222. {
  12223. var distanceSquared = this.position.getDistanceSquared(aPosition);
  12224. // if it's shorter than either radius, we intersect
  12225. return distanceSquared < this.radiusSquared;
  12226. },
  12227. intersects: function(aCircle)
  12228. {
  12229. var distanceSquared = this.position.getDistanceSquared(aCircle.position);
  12230. return (distanceSquared < this.radiusSquared || distanceSquared < aCircle.radiusSquared);
  12231. },
  12232. /**
  12233. * ACCESSORS
  12234. */
  12235. setPosition: function(aPosition)
  12236. {
  12237. this.position = aPosition;
  12238. return this;
  12239. },
  12240. setDelegate: function(aDelegate)
  12241. {
  12242. this.delegate = aDelegate;
  12243. return this;
  12244. },
  12245. setOffset: function(aPosition)
  12246. {
  12247. this.offset = aPosition;
  12248. return this;
  12249. },
  12250. setTargetPosition: function(aTargetPosition)
  12251. {
  12252. this.targetPosition = aTargetPosition;
  12253. return this;
  12254. },
  12255. setTargetChaseSpeed: function(aTargetChaseSpeed)
  12256. {
  12257. this.targetChaseSpeed = aTargetChaseSpeed;
  12258. return this;
  12259. },
  12260. setIsFixed: function(value)
  12261. {
  12262. this.isFixed = value;
  12263. return this;
  12264. },
  12265. setCollisionMask: function(aCollisionMask)
  12266. {
  12267. this.collisionMask = aCollisionMask;
  12268. return this;
  12269. },
  12270. setCollisionGroup: function(aCollisionGroup)
  12271. {
  12272. this.collisionGroup = aCollisionGroup;
  12273. return this;
  12274. },
  12275. setRadius: function(aRadius)
  12276. {
  12277. this.radius = aRadius;
  12278. this.radiusSquared = this.radius*this.radius;
  12279. return this;
  12280. },
  12281. initialize : function(overrides)
  12282. {
  12283. if (overrides)
  12284. {
  12285. for (var i in overrides)
  12286. {
  12287. this[i] = overrides[i];
  12288. }
  12289. }
  12290. return this;
  12291. },
  12292. dealloc: function()
  12293. {
  12294. this.position = null;
  12295. this.offset = null;
  12296. this.delegate = null;
  12297. this.targetPosition = null;
  12298. }
  12299. };
  12300. })();/**
  12301. *
  12302. * See LICENSE file.
  12303. *
  12304. #### ##### ##### #### ### # # ###### ###### ## ## ##### # # ######## ## # # #####
  12305. # # # # ### # # ##### ### ## ## ## # ## # # # # ## # ##### ### ###
  12306. ### # # ##### #### # # # ###### ## ######### ##### ##### ##### # ## # # # # # #####
  12307. -
  12308. File:
  12309. PackedCircle.js
  12310. Created By:
  12311. Mario Gonzalez
  12312. Project :
  12313. None
  12314. Abstract:
  12315. A single packed circle.
  12316. Contains a reference to it's div, and information pertaining to it state.
  12317. Basic Usage:
  12318. http://onedayitwillmake.com/CirclePackJS/
  12319. */
  12320. (function()
  12321. {
  12322. /**
  12323. * @constructor
  12324. */
  12325. CAAT.modules.CircleManager.PackedCircleManager= function()
  12326. {
  12327. return this;
  12328. };
  12329. CAAT.modules.CircleManager.PackedCircleManager.prototype = {
  12330. allCircles: [],
  12331. numberOfCollisionPasses: 1,
  12332. numberOfTargetingPasses: 0,
  12333. bounds: new CAAT.Rectangle(),
  12334. /**
  12335. * Adds a circle to the simulation
  12336. * @param aCircle
  12337. */
  12338. addCircle: function(aCircle)
  12339. {
  12340. aCircle.id = this.allCircles.length;
  12341. this.allCircles.push(aCircle);
  12342. return this;
  12343. },
  12344. /**
  12345. * Removes a circle from the simulations
  12346. * @param aCircle Circle to remove
  12347. */
  12348. removeCircle: function(aCircle)
  12349. {
  12350. var index = 0,
  12351. found = false,
  12352. len = this.allCircles.length;
  12353. if(len === 0) {
  12354. throw "Error: (PackedCircleManager) attempting to remove circle, and allCircles.length === 0!!";
  12355. }
  12356. while (len--) {
  12357. if(this.allCircles[len] === aCircle) {
  12358. found = true;
  12359. index = len;
  12360. break;
  12361. }
  12362. }
  12363. if(!found) {
  12364. throw "Could not locate circle in allCircles array!";
  12365. }
  12366. // Remove
  12367. this.allCircles[index].dealloc();
  12368. this.allCircles[index] = null;
  12369. return this;
  12370. },
  12371. /**
  12372. * Forces all circles to move to where their delegate position is
  12373. * Assumes all targets have a 'position' property!
  12374. */
  12375. forceCirclesToMatchDelegatePositions: function()
  12376. {
  12377. var len = this.allCircles.length;
  12378. // push toward target position
  12379. for(var n = 0; n < len; n++)
  12380. {
  12381. var aCircle = this.allCircles[n];
  12382. if(!aCircle || !aCircle.delegate) {
  12383. continue;
  12384. }
  12385. aCircle.position.set(aCircle.delegate.x + aCircle.offset.x,
  12386. aCircle.delegate.y + aCircle.offset.y);
  12387. }
  12388. },
  12389. pushAllCirclesTowardTarget: function(aTarget)
  12390. {
  12391. var v = new CAAT.Point(0,0,0),
  12392. circleList = this.allCircles,
  12393. len = circleList.length;
  12394. // push toward target position
  12395. for(var n = 0; n < this.numberOfTargetingPasses; n++)
  12396. {
  12397. for(var i = 0; i < len; i++)
  12398. {
  12399. var c = circleList[i];
  12400. if(c.isFixed) continue;
  12401. v.x = c.position.x - (c.targetPosition.x+c.offset.x);
  12402. v.y = c.position.y - (c.targetPosition.y+c.offset.y);
  12403. v.multiply(c.targetChaseSpeed);
  12404. c.position.x -= v.x;
  12405. c.position.y -= v.y;
  12406. }
  12407. }
  12408. },
  12409. /**
  12410. * Packs the circles towards the center of the bounds.
  12411. * Each circle will have it's own 'targetPosition' later on
  12412. */
  12413. handleCollisions: function()
  12414. {
  12415. this.removeExpiredElements();
  12416. var v = new CAAT.Point(0,0, 0),
  12417. circleList = this.allCircles,
  12418. len = circleList.length;
  12419. // Collide circles
  12420. for(var n = 0; n < this.numberOfCollisionPasses; n++)
  12421. {
  12422. for(var i = 0; i < len; i++)
  12423. {
  12424. var ci = circleList[i];
  12425. for (var j = i + 1; j< len; j++)
  12426. {
  12427. var cj = circleList[j];
  12428. if( !this.circlesCanCollide(ci, cj) ) continue; // It's us!
  12429. var dx = cj.position.x - ci.position.x,
  12430. dy = cj.position.y - ci.position.y;
  12431. // The distance between the two circles radii, but we're also gonna pad it a tiny bit
  12432. var r = (ci.radius + cj.radius) * 1.08,
  12433. d = ci.position.getDistanceSquared(cj.position);
  12434. /**
  12435. * Collision detected!
  12436. */
  12437. if (d < (r * r) - 0.02 )
  12438. {
  12439. v.x = dx;
  12440. v.y = dy;
  12441. v.normalize();
  12442. var inverseForce = (r - Math.sqrt(d)) * 0.5;
  12443. v.multiply(inverseForce);
  12444. // Move cj opposite of the collision as long as its not fixed
  12445. if(!cj.isFixed)
  12446. {
  12447. if(ci.isFixed)
  12448. v.multiply(2.2); // Double inverse force to make up for the fact that the other object is fixed
  12449. // ADD the velocity
  12450. cj.position.translatePoint(v);
  12451. }
  12452. // Move ci opposite of the collision as long as its not fixed
  12453. if(!ci.isFixed)
  12454. {
  12455. if(cj.isFixed)
  12456. v.multiply(2.2); // Double inverse force to make up for the fact that the other object is fixed
  12457. // SUBTRACT the velocity
  12458. ci.position.subtract(v);
  12459. }
  12460. // Emit the collision event from each circle, with itself as the first parameter
  12461. // if(this.dispatchCollisionEvents && n == this.numberOfCollisionPasses-1)
  12462. // {
  12463. // this.eventEmitter.emit('collision', cj, ci, v);
  12464. // }
  12465. }
  12466. }
  12467. }
  12468. }
  12469. },
  12470. handleBoundaryForCircle: function(aCircle, boundsRule)
  12471. {
  12472. // if(aCircle.boundsRule === true) return; // Ignore if being dragged
  12473. var xpos = aCircle.position.x;
  12474. var ypos = aCircle.position.y;
  12475. var radius = aCircle.radius;
  12476. var diameter = radius*2;
  12477. // Toggle these on and off,
  12478. // Wrap and bounce, are opposite behaviors so pick one or the other for each axis, or bad things will happen.
  12479. var wrapXMask = 1 << 0;
  12480. var wrapYMask = 1 << 2;
  12481. var constrainXMask = 1 << 3;
  12482. var constrainYMask = 1 << 4;
  12483. var emitEvent = 1 << 5;
  12484. // TODO: Promote to member variable
  12485. // Convert to bitmask - Uncomment the one you want, or concact your own :)
  12486. // boundsRule = wrapY; // Wrap only Y axis
  12487. // boundsRule = wrapX; // Wrap only X axis
  12488. // boundsRule = wrapXMask | wrapYMask; // Wrap both X and Y axis
  12489. boundsRule = wrapYMask | constrainXMask; // Wrap Y axis, but constrain horizontally
  12490. // Wrap X
  12491. if(boundsRule & wrapXMask && xpos-diameter > this.bounds.right) {
  12492. aCircle.position.x = this.bounds.left + radius;
  12493. } else if(boundsRule & wrapXMask && xpos+diameter < this.bounds.left) {
  12494. aCircle.position.x = this.bounds.right - radius;
  12495. }
  12496. // Wrap Y
  12497. if(boundsRule & wrapYMask && ypos-diameter > this.bounds.bottom) {
  12498. aCircle.position.y = this.bounds.top - radius;
  12499. } else if(boundsRule & wrapYMask && ypos+diameter < this.bounds.top) {
  12500. aCircle.position.y = this.bounds.bottom + radius;
  12501. }
  12502. // Constrain X
  12503. if(boundsRule & constrainXMask && xpos+radius >= this.bounds.right) {
  12504. aCircle.position.x = aCircle.position.x = this.bounds.right-radius;
  12505. } else if(boundsRule & constrainXMask && xpos-radius < this.bounds.left) {
  12506. aCircle.position.x = this.bounds.left + radius;
  12507. }
  12508. // Constrain Y
  12509. if(boundsRule & constrainYMask && ypos+radius > this.bounds.bottom) {
  12510. aCircle.position.y = this.bounds.bottom - radius;
  12511. } else if(boundsRule & constrainYMask && ypos-radius < this.bounds.top) {
  12512. aCircle.position.y = this.bounds.top + radius;
  12513. }
  12514. },
  12515. /**
  12516. * Given an x,y position finds circle underneath and sets it to the currently grabbed circle
  12517. * @param {Number} xpos An x position
  12518. * @param {Number} ypos A y position
  12519. * @param {Number} buffer A radiusSquared around the point in question where something is considered to match
  12520. */
  12521. getCircleAt: function(xpos, ypos, buffer)
  12522. {
  12523. var circleList = this.allCircles;
  12524. var len = circleList.length;
  12525. var grabVector = new CAAT.Point(xpos, ypos, 0);
  12526. // These are set every time a better match i found
  12527. var closestCircle = null;
  12528. var closestDistance = Number.MAX_VALUE;
  12529. // Loop thru and find the closest match
  12530. for(var i = 0; i < len; i++)
  12531. {
  12532. var aCircle = circleList[i];
  12533. if(!aCircle) continue;
  12534. var distanceSquared = aCircle.position.getDistanceSquared(grabVector);
  12535. if(distanceSquared < closestDistance && distanceSquared < aCircle.radiusSquared + buffer)
  12536. {
  12537. closestDistance = distanceSquared;
  12538. closestCircle = aCircle;
  12539. }
  12540. }
  12541. return closestCircle;
  12542. },
  12543. circlesCanCollide: function(circleA, circleB)
  12544. {
  12545. if(!circleA || !circleB || circleA===circleB) return false; // one is null (will be deleted next loop), or both point to same obj.
  12546. // if(circleA.delegate == null || circleB.delegate == null) return false; // This circle will be removed next loop, it's entity is already removed
  12547. // if(circleA.isFixed & circleB.isFixed) return false;
  12548. // if(circleA.delegate .clientID === circleB.delegate.clientID) return false; // Don't let something collide with stuff it owns
  12549. // They dont want to collide
  12550. // if((circleA.collisionGroup & circleB.collisionMask) == 0) return false;
  12551. // if((circleB.collisionGroup & circleA.collisionMask) == 0) return false;
  12552. return true;
  12553. },
  12554. /**
  12555. * Accessors
  12556. */
  12557. setBounds: function(x, y, w, h)
  12558. {
  12559. this.bounds.x = x;
  12560. this.bounds.y = y;
  12561. this.bounds.width = w;
  12562. this.bounds.height = h;
  12563. },
  12564. setNumberOfCollisionPasses: function(value)
  12565. {
  12566. this.numberOfCollisionPasses = value;
  12567. return this;
  12568. },
  12569. setNumberOfTargetingPasses: function(value)
  12570. {
  12571. this.numberOfTargetingPasses = value;
  12572. return this;
  12573. },
  12574. /**
  12575. * Helpers
  12576. */
  12577. sortOnDistanceToTarget: function(circleA, circleB)
  12578. {
  12579. var valueA = circleA.getDistanceSquaredFromPosition(circleA.targetPosition);
  12580. var valueB = circleB.getDistanceSquaredFromPosition(circleA.targetPosition);
  12581. var comparisonResult = 0;
  12582. if(valueA > valueB) comparisonResult = -1;
  12583. else if(valueA < valueB) comparisonResult = 1;
  12584. return comparisonResult;
  12585. },
  12586. /**
  12587. * Memory Management
  12588. */
  12589. removeExpiredElements: function()
  12590. {
  12591. // remove null elements
  12592. for (var k = this.allCircles.length; k >= 0; k--) {
  12593. if (this.allCircles[k] === null)
  12594. this.allCircles.splice(k, 1);
  12595. }
  12596. },
  12597. initialize : function(overrides)
  12598. {
  12599. if (overrides)
  12600. {
  12601. for (var i in overrides)
  12602. {
  12603. this[i] = overrides[i];
  12604. }
  12605. }
  12606. return this;
  12607. }
  12608. };
  12609. })();/**
  12610. * See LICENSE file.
  12611. *
  12612. **/
  12613. (function() {
  12614. /**
  12615. * Local storage management.
  12616. * @constructor
  12617. */
  12618. CAAT.modules.LocalStorage= function() {
  12619. return this;
  12620. };
  12621. CAAT.modules.LocalStorage.prototype= {
  12622. /**
  12623. * Stores an object in local storage. The data will be saved as JSON.stringify.
  12624. * @param key {string} key to store data under.
  12625. * @param data {object} an object.
  12626. * @return this
  12627. *
  12628. * @static
  12629. */
  12630. save : function( key, data ) {
  12631. try {
  12632. localStorage.setItem( key, JSON.stringify(data) );
  12633. } catch(e) {
  12634. // eat it
  12635. }
  12636. return this;
  12637. },
  12638. /**
  12639. * Retrieve a value from local storage.
  12640. * @param key {string} the key to retrieve.
  12641. * @return {object} object stored under the key parameter.
  12642. *
  12643. * @static
  12644. */
  12645. load : function( key ) {
  12646. try {
  12647. return JSON.parse(localStorage.getItem( key ));
  12648. } catch(e) {
  12649. return null;
  12650. }
  12651. },
  12652. /**
  12653. * Removes a value stored in local storage.
  12654. * @param key {string}
  12655. * @return this
  12656. *
  12657. * @static
  12658. */
  12659. remove : function( key ) {
  12660. try {
  12661. localStorage.removeItem(key);
  12662. } catch(e) {
  12663. // eat it
  12664. }
  12665. return this;
  12666. }
  12667. };
  12668. })();
  12669. /**
  12670. * See LICENSE file.
  12671. */
  12672. (function() {
  12673. CAAT.modules.ImageUtil= {};
  12674. CAAT.modules.ImageUtil.createAlphaSpriteSheet= function(maxAlpha, minAlpha, sheetSize, image, bg_fill_style ) {
  12675. if ( maxAlpha<minAlpha ) {
  12676. var t= maxAlpha;
  12677. maxAlpha= minAlpha;
  12678. minAlpha= t;
  12679. }
  12680. var canvas= document.createElement('canvas');
  12681. canvas.width= image.width;
  12682. canvas.height= image.height*sheetSize;
  12683. var ctx= canvas.getContext('2d');
  12684. ctx.fillStyle = bg_fill_style ? bg_fill_style : 'rgba(255,255,255,0)';
  12685. ctx.fillRect(0,0,image.width,image.height*sheetSize);
  12686. var i;
  12687. for( i=0; i<sheetSize; i++ ) {
  12688. ctx.globalAlpha= 1-(maxAlpha-minAlpha)/sheetSize*(i+1);
  12689. ctx.drawImage(image, 0, i*image.height);
  12690. }
  12691. return canvas;
  12692. };
  12693. /**
  12694. * Creates a rotated canvas image element.
  12695. * @param img
  12696. */
  12697. CAAT.modules.ImageUtil.rotate= function( image, angle ) {
  12698. angle= angle||0;
  12699. if ( !angle ) {
  12700. return image;
  12701. }
  12702. var canvas= document.createElement("canvas");
  12703. canvas.width= image.height;
  12704. canvas.height= image.width;
  12705. var ctx= canvas.getContext('2d');
  12706. ctx.globalAlpha= 1;
  12707. ctx.fillStyle='rgba(0,0,0,0)';
  12708. ctx.clearRect(0,0,canvas.width,canvas.height);
  12709. var m= new CAAT.Matrix();
  12710. m.multiply( new CAAT.Matrix().setTranslate( canvas.width/2, canvas.width/2 ) );
  12711. m.multiply( new CAAT.Matrix().setRotation( angle*Math.PI/180 ) );
  12712. m.multiply( new CAAT.Matrix().setTranslate( -canvas.width/2, -canvas.width/2 ) );
  12713. m.transformRenderingContext(ctx);
  12714. ctx.drawImage(image,0,0);
  12715. return canvas;
  12716. };
  12717. /**
  12718. * Remove an image's padding transparent border.
  12719. * Transparent means that every scan pixel is alpha=0.
  12720. * @param image
  12721. * @param threshold {integer} any value below or equal to this will be optimized.
  12722. * @param !areas { object{ top<boolean>, bottom<boolean>, left<boolean, right<boolean> }�}
  12723. */
  12724. CAAT.modules.ImageUtil.optimize= function(image, threshold, areas ) {
  12725. threshold>>=0;
  12726. var atop= true;
  12727. var abottom= true;
  12728. var aleft= true;
  12729. var aright= true;
  12730. if ( typeof areas!=='undefined' ) {
  12731. if ( typeof areas.top!=='undefined' ) {
  12732. atop= areas.top;
  12733. }
  12734. if ( typeof areas.bottom!=='undefined' ) {
  12735. abottom= areas.bottom;
  12736. }
  12737. if ( typeof areas.left!=='undefined' ) {
  12738. aleft= areas.left;
  12739. }
  12740. if ( typeof areas.right!=='undefined' ) {
  12741. aright= areas.right;
  12742. }
  12743. }
  12744. var canvas= document.createElement('canvas');
  12745. canvas.width= image.width;
  12746. canvas.height=image.height;
  12747. var ctx= canvas.getContext('2d');
  12748. ctx.fillStyle='rgba(0,0,0,0)';
  12749. ctx.fillRect(0,0,image.width,image.height);
  12750. ctx.drawImage( image, 0, 0 );
  12751. var imageData= ctx.getImageData(0,0,image.width,image.height);
  12752. var data= imageData.data;
  12753. var i,j;
  12754. var miny= 0, maxy=canvas.height-1;
  12755. var minx= 0, maxx=canvas.width-1;
  12756. var alpha= false;
  12757. if ( atop ) {
  12758. for( i=0; i<canvas.height; i++ ) {
  12759. for( j=0; j<canvas.width; j++ ) {
  12760. if ( data[i*canvas.width*4 + 3+j*4]>threshold ) {
  12761. alpha= true;
  12762. break;
  12763. }
  12764. }
  12765. if ( alpha ) {
  12766. break;
  12767. }
  12768. }
  12769. // i contiene el indice del ultimo scan que no es transparente total.
  12770. miny= i;
  12771. }
  12772. if ( abottom ) {
  12773. alpha= false;
  12774. for( i=canvas.height-1; i>=miny; i-- ) {
  12775. for( j=0; j<canvas.width; j++ ) {
  12776. if ( data[i*canvas.width*4 + 3+j*4]>threshold ) {
  12777. alpha= true;
  12778. break;
  12779. }
  12780. }
  12781. if ( alpha ) {
  12782. break;
  12783. }
  12784. }
  12785. maxy= i;
  12786. }
  12787. if ( aleft ) {
  12788. alpha= false;
  12789. for( j=0; j<canvas.width; j++ ) {
  12790. for( i=miny; i<=maxy; i++ ) {
  12791. if ( data[i*canvas.width*4 + 3+j*4 ]>threshold ) {
  12792. alpha= true;
  12793. break;
  12794. }
  12795. }
  12796. if ( alpha ) {
  12797. break;
  12798. }
  12799. }
  12800. minx= j;
  12801. }
  12802. if ( aright ) {
  12803. alpha= false;
  12804. for( j=canvas.width-1; j>=minx; j-- ) {
  12805. for( i=miny; i<=maxy; i++ ) {
  12806. if ( data[i*canvas.width*4 + 3+j*4 ]>threshold ) {
  12807. alpha= true;
  12808. break;
  12809. }
  12810. }
  12811. if ( alpha ) {
  12812. break;
  12813. }
  12814. }
  12815. maxx= j;
  12816. }
  12817. if ( 0===minx && 0===miny && canvas.width-1===maxx && canvas.height-1===maxy ) {
  12818. return canvas;
  12819. }
  12820. var width= maxx-minx+1;
  12821. var height=maxy-miny+1;
  12822. var id2= ctx.getImageData( minx, miny, width, height );
  12823. canvas.width= width;
  12824. canvas.height= height;
  12825. ctx= canvas.getContext('2d');
  12826. ctx.putImageData( id2, 0, 0 );
  12827. return canvas;
  12828. };
  12829. CAAT.modules.ImageUtil.createThumb= function(image, w, h, best_fit) {
  12830. w= w||24;
  12831. h= h||24;
  12832. var canvas= document.createElement('canvas');
  12833. canvas.width= w;
  12834. canvas.height= h;
  12835. var ctx= canvas.getContext('2d');
  12836. if ( best_fit ) {
  12837. var max= Math.max( image.width, image.height );
  12838. var ww= image.width/max*w;
  12839. var hh= image.height/max*h;
  12840. ctx.drawImage( image, (w-ww)/2,(h-hh)/2,ww,hh );
  12841. } else {
  12842. ctx.drawImage( image, 0, 0, w, h );
  12843. }
  12844. return canvas;
  12845. }
  12846. })();/**
  12847. * See LICENSE file.
  12848. */
  12849. (function() {
  12850. CAAT.modules.LayoutUtils= {};
  12851. CAAT.modules.LayoutUtils.row= function( dst, what_to_layout_array, constraint_object ) {
  12852. var width= dst.width;
  12853. var x=0, y=0, i=0, l=0;
  12854. var actor_max_h= -Number.MAX_VALUE, actor_max_w= Number.MAX_VALUE;
  12855. // compute max/min actor list size.
  12856. for( i=what_to_layout_array.length-1; i; i-=1 ) {
  12857. if ( actor_max_w<what_to_layout_array[i].width ) {
  12858. actor_max_w= what_to_layout_array[i].width;
  12859. }
  12860. if ( actor_max_h<what_to_layout_array[i].height ) {
  12861. actor_max_h= what_to_layout_array[i].height;
  12862. }
  12863. }
  12864. if ( constraint_object.padding_left ) {
  12865. x= constraint_object.padding_left;
  12866. width-= x;
  12867. }
  12868. if ( constraint_object.padding_right ) {
  12869. width-= constraint_object.padding_right;
  12870. }
  12871. if ( constraint_object.top ) {
  12872. var top= parseInt(constraint_object.top, 10);
  12873. if ( !isNaN(top) ) {
  12874. y= top;
  12875. } else {
  12876. // not number
  12877. switch(constraint_object.top) {
  12878. case 'center':
  12879. y= (dst.height-actor_max_h)/2;
  12880. break;
  12881. case 'top':
  12882. y=0;
  12883. break;
  12884. case 'bottom':
  12885. y= dst.height-actor_max_h;
  12886. break;
  12887. default:
  12888. y= 0;
  12889. }
  12890. }
  12891. }
  12892. // space for each actor
  12893. var actor_area= width / what_to_layout_array.length;
  12894. for( i=0, l=what_to_layout_array.length; i<l; i++ ) {
  12895. what_to_layout_array[i].setLocation(
  12896. x + i * actor_area + (actor_area - what_to_layout_array[i].width) / 2,
  12897. y);
  12898. }
  12899. };
  12900. })();/**
  12901. * See LICENSE file.
  12902. *
  12903. * This class generates an in-memory image with the representation of a drawn list of characters.
  12904. *
  12905. **/
  12906. (function() {
  12907. /**
  12908. * @constructor
  12909. */
  12910. CAAT.Font= function( ) {
  12911. return this;
  12912. };
  12913. var UNKNOWN_CHAR_WIDTH= 10;
  12914. CAAT.Font.prototype= {
  12915. fontSize : 10,
  12916. fontSizeUnit: "px",
  12917. font : 'Sans-Serif',
  12918. fontStyle : '',
  12919. fillStyle : '#fff',
  12920. strokeStyle : null,
  12921. padding : 0,
  12922. image : null,
  12923. charMap : null,
  12924. height : 0,
  12925. setPadding : function( padding ) {
  12926. this.padding= padding;
  12927. return this;
  12928. },
  12929. setFontStyle : function( style ) {
  12930. this.fontStyle= style;
  12931. return this;
  12932. },
  12933. setFontSize : function( fontSize ) {
  12934. this.fontSize= fontSize;
  12935. this.fontSizeUnit= 'px';
  12936. return this;
  12937. },
  12938. setFont : function( font ) {
  12939. this.font= font;
  12940. return this;
  12941. },
  12942. setFillStyle : function( style ) {
  12943. this.fillStyle= style;
  12944. return this;
  12945. },
  12946. setStrokeStyle : function( style ) {
  12947. this.strokeStyle= style;
  12948. return this;
  12949. },
  12950. createDefault : function( padding ) {
  12951. var str="";
  12952. for( var i=32; i<128; i++ ) {
  12953. str= str+String.fromCharCode(i);
  12954. }
  12955. return this.create( str, padding );
  12956. },
  12957. create : function( chars, padding ) {
  12958. padding= padding | 0;
  12959. this.padding= padding;
  12960. var canvas= document.createElement('canvas');
  12961. canvas.width= 1;
  12962. canvas.height= 1;
  12963. var ctx= canvas.getContext('2d');
  12964. ctx.textBaseline= 'top';
  12965. ctx.font= this.fontStyle+' '+this.fontSize+""+this.fontSizeUnit+" "+ this.font;
  12966. var textWidth= 0;
  12967. var charWidth= [];
  12968. var i;
  12969. var x;
  12970. var cchar;
  12971. for( i=0; i<chars.length; i++ ) {
  12972. var cw= Math.max( 1, (ctx.measureText( chars.charAt(i) ).width>>0)+1 ) + 2 * padding ;
  12973. charWidth.push(cw);
  12974. textWidth+= cw;
  12975. }
  12976. canvas.width= textWidth;
  12977. canvas.height= (this.fontSize*1.5)>>0;
  12978. ctx= canvas.getContext('2d');
  12979. ctx.textBaseline= 'top';
  12980. ctx.font= this.fontStyle+' '+this.fontSize+""+this.fontSizeUnit+" "+ this.font;
  12981. ctx.fillStyle= this.fillStyle;
  12982. ctx.strokeStyle= this.strokeStyle;
  12983. this.charMap= {};
  12984. x=0;
  12985. for( i=0; i<chars.length; i++ ) {
  12986. cchar= chars.charAt(i);
  12987. ctx.fillText( cchar, x+padding, 0 );
  12988. if ( this.strokeStyle ) {
  12989. ctx.beginPath();
  12990. ctx.strokeText( cchar, x+padding, 0 );
  12991. }
  12992. this.charMap[cchar]= {
  12993. x: x,
  12994. width: charWidth[i]
  12995. };
  12996. x+= charWidth[i];
  12997. }
  12998. this.image= CAAT.modules.ImageUtil.optimize( canvas, 32, { top: true, bottom: true, left: false, right: false } );
  12999. this.height= this.image.height;
  13000. return this;
  13001. },
  13002. setAsSpriteImage : function() {
  13003. var cm= [];
  13004. var _index= 0;
  13005. for( var i in this.charMap ) {
  13006. var _char= i;
  13007. var charData= this.charMap[i];
  13008. cm[i]={
  13009. id: _index++,
  13010. height: this.height,
  13011. xoffset: 0,
  13012. letter: _char,
  13013. yoffset: 0,
  13014. width: charData.width,
  13015. xadvance: charData.width,
  13016. x: charData.x,
  13017. y: 0
  13018. };
  13019. }
  13020. return new CAAT.SpriteImage().initializeAsGlyphDesigner( this.image, cm );
  13021. },
  13022. stringWidth : function( str ) {
  13023. var i, l, w=0, c;
  13024. for( i=0, l=str.length; i<l; i++ ) {
  13025. c= this.charMap[ str.charAt(i) ];
  13026. if ( c ) {
  13027. w+= c.width;
  13028. } else {
  13029. w+= UNKNOWN_CHAR_WIDTH;
  13030. }
  13031. }
  13032. return w;
  13033. },
  13034. drawText : function( str, ctx, x, y ) {
  13035. var i,l,charInfo,w;
  13036. var height= this.image.height;
  13037. for( i=0, l=str.length; i<l; i++ ) {
  13038. charInfo= this.charMap[ str.charAt(i) ];
  13039. if ( charInfo ) {
  13040. w= charInfo.width;
  13041. ctx.drawImage(
  13042. this.image,
  13043. charInfo.x, 0,
  13044. w, height,
  13045. x, y,
  13046. w, height);
  13047. x+= w;
  13048. } else {
  13049. ctx.strokeStyle='#f00';
  13050. ctx.strokeRect( x,y,UNKNOWN_CHAR_WIDTH,height );
  13051. x+= UNKNOWN_CHAR_WIDTH;
  13052. }
  13053. }
  13054. },
  13055. save : function() {
  13056. var str= "image/png";
  13057. var strData= this.image.toDataURL(str);
  13058. document.location.href= strData.replace( str, "image/octet-stream" );
  13059. }
  13060. };
  13061. })();
  13062. /**
  13063. * See LICENSE file.
  13064. *
  13065. *
  13066. *
  13067. */
  13068. /*
  13069. (function() {
  13070. CAAT.modules.Inspector= function() {
  13071. return this;
  13072. };
  13073. CAAT.modules.Inspector.prototype= {
  13074. initialize : function(root) {
  13075. if ( !root ) {
  13076. root= CAAT;
  13077. }
  13078. CAAT.log("Analyzing "+root.toString()+" for reflection info.");
  13079. for( var clazz in root ) {
  13080. if ( root[clazz].__reflectionInfo ) {
  13081. CAAT.log(" Extracting reflection info for: "+root[clazz] );
  13082. this.extractReflectionInfo( root[clazz] );
  13083. }
  13084. }
  13085. },
  13086. extractReflectionInfo : function( object ) {
  13087. var ri= object.__reflectionInfo;
  13088. var key;
  13089. var i;
  13090. var __removeEmpty= function( el, index, array ) {
  13091. array[index]= array[index].trim();
  13092. if ( array[index]==="" ) array.splice(index,1);
  13093. };
  13094. for( key in ri ) {
  13095. var metadata= ri[key];
  13096. CAAT.log(" reflection info for: "+key+"="+metadata );
  13097. var ks= key.split(",");
  13098. var data= metadata.split(",");
  13099. ks.forEach( __removeEmpty );
  13100. data.forEach( __removeEmpty );
  13101. if ( ks.length===1 ) { // one property.
  13102. data.forEach( function( el, index, array ) {
  13103. // el is each metadata definition of the form: key:value
  13104. var operation= el.split(":");
  13105. operation.forEach( __removeEmpty );
  13106. if ( operation.length!=2 ) {
  13107. CAAT.log(" ERR. operation: "+el+" wrong format");
  13108. } else {
  13109. if ( operation[0]==="set" ) {
  13110. CAAT.log("set="+operation[1]);
  13111. } else if ( operation[0]==="get" ) {
  13112. CAAT.log("get="+operation[1]);
  13113. } else if ( operation[0]==="type" ) {
  13114. CAAT.log("type="+operation[1]);
  13115. }
  13116. }
  13117. });
  13118. }
  13119. }
  13120. }
  13121. };
  13122. })();
  13123. */
  13124. /**
  13125. * See LICENSE file.
  13126. *
  13127. * Interpolator actor will draw interpolators on screen.
  13128. *
  13129. **/
  13130. (function() {
  13131. /**
  13132. * This actor class draws an interpolator function by caching an interpolator contour as a polyline.
  13133. *
  13134. * @constructor
  13135. * @extends CAAT.ActorContainer
  13136. */
  13137. CAAT.InterpolatorActor = function() {
  13138. CAAT.InterpolatorActor.superclass.constructor.call(this);
  13139. return this;
  13140. };
  13141. CAAT.InterpolatorActor.prototype= {
  13142. interpolator: null, // CAAT.Interpolator instance.
  13143. contour: null, // interpolator contour cache
  13144. S: 50, // contour samples.
  13145. gap: 5, // border size in pixels.
  13146. /**
  13147. * Sets a padding border size. By default is 5 pixels.
  13148. * @param gap {number} border size in pixels.
  13149. * @return this
  13150. */
  13151. setGap : function( gap ) {
  13152. this.gap= gap;
  13153. return this;
  13154. },
  13155. /**
  13156. * Sets the CAAT.Interpolator instance to draw.
  13157. *
  13158. * @param interpolator a CAAT.Interpolator instance.
  13159. * @param size an integer indicating the number of polyline segments so draw to show the CAAT.Interpolator
  13160. * instance.
  13161. *
  13162. * @return this
  13163. */
  13164. setInterpolator : function( interpolator, size ) {
  13165. this.interpolator= interpolator;
  13166. this.contour= interpolator.getContour(size || this.S);
  13167. return this;
  13168. },
  13169. /**
  13170. * Paint this actor.
  13171. * @param director {CAAT.Director}
  13172. * @param time {number} scene time.
  13173. */
  13174. paint : function( director, time ) {
  13175. CAAT.InterpolatorActor.superclass.paint.call(this,director,time);
  13176. if ( this.backgroundImage ) {
  13177. return this;
  13178. }
  13179. if ( this.interpolator ) {
  13180. var canvas= director.crc;
  13181. var xs= (this.width-2*this.gap);
  13182. var ys= (this.height-2*this.gap);
  13183. canvas.beginPath();
  13184. canvas.moveTo(
  13185. this.gap + xs*this.contour[0].x,
  13186. -this.gap + this.height - ys*this.contour[0].y);
  13187. for( var i=1; i<this.contour.length; i++ ) {
  13188. canvas.lineTo(
  13189. this.gap + xs*this.contour[i].x,
  13190. -this.gap + this.height - ys*this.contour[i].y);
  13191. }
  13192. canvas.strokeStyle= this.strokeStyle;
  13193. canvas.stroke();
  13194. }
  13195. },
  13196. /**
  13197. * Return the represented interpolator.
  13198. * @return {CAAT.Interpolator}
  13199. */
  13200. getInterpolator : function() {
  13201. return this.interpolator;
  13202. }
  13203. };
  13204. extend( CAAT.InterpolatorActor, CAAT.ActorContainer, null);
  13205. })();/**
  13206. * See LICENSE file.
  13207. *
  13208. * These classes encapsulate different kinds of paths.
  13209. * LinearPath, defines an straight line path, just 2 points.
  13210. * CurvePath, defines a path based on a Curve. Curves can be bezier quadric/cubic and catmull-rom.
  13211. * Path, is a general purpose class, which composes a path of different path segments (Linear or Curve paths).
  13212. *
  13213. * A path, has an interpolator which stablishes the way the path is traversed (accelerating, by
  13214. * easing functions, etc.). Normally, interpolators will be defined by CAAT,Interpolator instances, but
  13215. * general Paths could be used as well.
  13216. *
  13217. **/
  13218. (function() {
  13219. /**
  13220. * This is the abstract class that every path segment must conform to.
  13221. * <p>
  13222. * It is implemented by all path segment types, ie:
  13223. * <ul>
  13224. * <li>LinearPath
  13225. * <li>CurvePath, base for all curves: quadric and cubic bezier.
  13226. * <li>Path. A path built of different PathSegment implementations.
  13227. * </ul>
  13228. *
  13229. * @constructor
  13230. */
  13231. CAAT.PathSegment = function() {
  13232. this.bbox= new CAAT.Rectangle();
  13233. return this;
  13234. };
  13235. CAAT.PathSegment.prototype = {
  13236. color: '#000',
  13237. length: 0,
  13238. bbox: null,
  13239. parent: null,
  13240. /**
  13241. * Set a PathSegment's parent
  13242. * @param parent
  13243. */
  13244. setParent : function(parent) {
  13245. this.parent= parent;
  13246. return this;
  13247. },
  13248. setColor : function(color) {
  13249. if ( color ) {
  13250. this.color= color;
  13251. }
  13252. return this;
  13253. },
  13254. /**
  13255. * Get path's last coordinate.
  13256. * @return {CAAT.Point}
  13257. */
  13258. endCurvePosition : function() { },
  13259. /**
  13260. * Get path's starting coordinate.
  13261. * @return {CAAT.Point}
  13262. */
  13263. startCurvePosition : function() { },
  13264. /**
  13265. * Set this path segment's points information.
  13266. * @param points {Array<CAAT.Point>}
  13267. */
  13268. setPoints : function( points ) { },
  13269. /**
  13270. * Set a point from this path segment.
  13271. * @param point {CAAT.Point}
  13272. * @param index {integer} a point index.
  13273. */
  13274. setPoint : function( point, index ) { },
  13275. /**
  13276. * Get a coordinate on path.
  13277. * The parameter time is normalized, that is, its values range from zero to one.
  13278. * zero will mean <code>startCurvePosition</code> and one will be <code>endCurvePosition</code>. Other values
  13279. * will be a position on the path relative to the path length. if the value is greater that 1, if will be set
  13280. * to modulus 1.
  13281. * @param time a float with a value between zero and 1 inclusive both.
  13282. *
  13283. * @return {CAAT.Point}
  13284. */
  13285. getPosition : function(time) { },
  13286. /**
  13287. * Gets Path length.
  13288. * @return {number}
  13289. */
  13290. getLength : function() {
  13291. return this.length;
  13292. },
  13293. /**
  13294. * Gets the path bounding box (or the rectangle that contains the whole path).
  13295. * @param rectangle a CAAT.Rectangle instance with the bounding box.
  13296. * @return {CAAT.Rectangle}
  13297. */
  13298. getBoundingBox : function() {
  13299. return this.bbox;
  13300. },
  13301. /**
  13302. * Gets the number of control points needed to create the path.
  13303. * Each PathSegment type can have different control points.
  13304. * @return {number} an integer with the number of control points.
  13305. */
  13306. numControlPoints : function() { },
  13307. /**
  13308. * Gets CAAT.Point instance with the 2d position of a control point.
  13309. * @param index an integer indicating the desired control point coordinate.
  13310. * @return {CAAT.Point}
  13311. */
  13312. getControlPoint: function(index) { },
  13313. /**
  13314. * Instruments the path has finished building, and that no more segments will be added to it.
  13315. * You could later add more PathSegments and <code>endPath</code> must be called again.
  13316. */
  13317. endPath : function() {},
  13318. /**
  13319. * Gets a polyline describing the path contour. The contour will be defined by as mush as iSize segments.
  13320. * @param iSize an integer indicating the number of segments of the contour polyline.
  13321. *
  13322. * @return {[CAAT.Point]}
  13323. */
  13324. getContour : function(iSize) {},
  13325. /**
  13326. * Recalculate internal path structures.
  13327. */
  13328. updatePath : function(point) {},
  13329. /**
  13330. * Draw this path using RenderingContext2D drawing primitives.
  13331. * The intention is to set a path or pathsegment as a clipping region.
  13332. *
  13333. * @param ctx {RenderingContext2D}
  13334. */
  13335. applyAsPath : function(director) {},
  13336. /**
  13337. * Transform this path with the given affinetransform matrix.
  13338. * @param matrix
  13339. */
  13340. transform : function(matrix) {},
  13341. drawHandle : function( ctx, x, y ) {
  13342. var w= CAAT.Curve.prototype.HANDLE_SIZE/2;
  13343. ctx.fillRect( x-w, y-w, w*2, w*2 );
  13344. /*
  13345. ctx.arc(
  13346. this.points[0].x,
  13347. this.points[0].y,
  13348. CAAT.Curve.prototype.HANDLE_SIZE/2,
  13349. 0,
  13350. 2*Math.PI,
  13351. false) ;
  13352. */
  13353. }
  13354. };
  13355. })();
  13356. (function() {
  13357. /**
  13358. * Straight line segment path between two given points.
  13359. *
  13360. * @constructor
  13361. * @extends CAAT.PathSegment
  13362. */
  13363. CAAT.LinearPath = function() {
  13364. CAAT.LinearPath.superclass.constructor.call(this);
  13365. this.points= [];
  13366. this.points.push( new CAAT.Point() );
  13367. this.points.push( new CAAT.Point() );
  13368. this.newPosition= new CAAT.Point(0,0,0);
  13369. return this;
  13370. };
  13371. CAAT.LinearPath.prototype= {
  13372. points: null,
  13373. newPosition: null, // spare holder for getPosition coordinate return.
  13374. applyAsPath : function(director) {
  13375. director.ctx.lineTo( this.points[0].x, this.points[1].y );
  13376. },
  13377. setPoint : function( point, index ) {
  13378. if ( index===0 ) {
  13379. this.points[0]= point;
  13380. } else if ( index===1 ) {
  13381. this.points[1]= point;
  13382. }
  13383. },
  13384. /**
  13385. * Update this segments length and bounding box info.
  13386. */
  13387. updatePath : function(point) {
  13388. var x= this.points[1].x - this.points[0].x;
  13389. var y= this.points[1].y - this.points[0].y;
  13390. this.length= Math.sqrt( x*x+y*y );
  13391. this.bbox.setEmpty();
  13392. this.bbox.union( this.points[0].x, this.points[0].y );
  13393. this.bbox.union( this.points[1].x, this.points[1].y );
  13394. return this;
  13395. },
  13396. setPoints : function( points ) {
  13397. this.points[0]= points[0];
  13398. this.points[1]= points[1];
  13399. this.updatePath();
  13400. return this;
  13401. },
  13402. /**
  13403. * Set this path segment's starting position.
  13404. * @param x {number}
  13405. * @param y {number}
  13406. */
  13407. setInitialPosition : function( x, y ) {
  13408. this.points[0].x= x;
  13409. this.points[0].y= y;
  13410. this.newPosition.set(x,y);
  13411. return this;
  13412. },
  13413. /**
  13414. * Set this path segment's ending position.
  13415. * @param finalX {number}
  13416. * @param finalY {number}
  13417. */
  13418. setFinalPosition : function( finalX, finalY ) {
  13419. this.points[1].x= finalX;
  13420. this.points[1].y= finalY;
  13421. return this;
  13422. },
  13423. /**
  13424. * @inheritDoc
  13425. */
  13426. endCurvePosition : function() {
  13427. return this.points[1];
  13428. },
  13429. /**
  13430. * @inheritsDoc
  13431. */
  13432. startCurvePosition : function() {
  13433. return this.points[0];
  13434. },
  13435. /**
  13436. * @inheritsDoc
  13437. */
  13438. getPosition : function(time) {
  13439. if ( time>1 || time<0 ) {
  13440. time%=1;
  13441. }
  13442. if ( time<0 ) {
  13443. time= 1+time;
  13444. }
  13445. this.newPosition.set(
  13446. (this.points[0].x+(this.points[1].x-this.points[0].x)*time),
  13447. (this.points[0].y+(this.points[1].y-this.points[0].y)*time) );
  13448. return this.newPosition;
  13449. },
  13450. getPositionFromLength : function( len ) {
  13451. return this.getPosition( len/this.length );
  13452. },
  13453. /**
  13454. * Returns initial path segment point's x coordinate.
  13455. * @return {number}
  13456. */
  13457. initialPositionX : function() {
  13458. return this.points[0].x;
  13459. },
  13460. /**
  13461. * Returns final path segment point's x coordinate.
  13462. * @return {number}
  13463. */
  13464. finalPositionX : function() {
  13465. return this.points[1].x;
  13466. },
  13467. /**
  13468. * Draws this path segment on screen. Optionally it can draw handles for every control point, in
  13469. * this case, start and ending path segment points.
  13470. * @param director {CAAT.Director}
  13471. * @param bDrawHandles {boolean}
  13472. */
  13473. paint : function(director, bDrawHandles) {
  13474. var ctx= director.ctx;
  13475. ctx.save();
  13476. ctx.strokeStyle= this.color;
  13477. ctx.beginPath();
  13478. ctx.moveTo( this.points[0].x, this.points[0].y );
  13479. ctx.lineTo( this.points[1].x, this.points[1].y );
  13480. ctx.stroke();
  13481. if ( bDrawHandles ) {
  13482. ctx.globalAlpha=0.5;
  13483. ctx.fillStyle='#7f7f00';
  13484. ctx.beginPath();
  13485. this.drawHandle( ctx, this.points[0].x, this.points[0].y );
  13486. this.drawHandle( ctx, this.points[1].x, this.points[1].y );
  13487. /*
  13488. canvas.arc(
  13489. this.points[0].x,
  13490. this.points[0].y,
  13491. CAAT.Curve.prototype.HANDLE_SIZE/2,
  13492. 0,
  13493. 2*Math.PI,
  13494. false) ;
  13495. canvas.arc(
  13496. this.points[1].x,
  13497. this.points[1].y,
  13498. CAAT.Curve.prototype.HANDLE_SIZE/2,
  13499. 0,
  13500. 2*Math.PI,
  13501. false) ;
  13502. canvas.fill();
  13503. */
  13504. }
  13505. ctx.restore();
  13506. },
  13507. /**
  13508. * Get the number of control points. For this type of path segment, start and
  13509. * ending path segment points. Defaults to 2.
  13510. * @return {number}
  13511. */
  13512. numControlPoints : function() {
  13513. return 2;
  13514. },
  13515. /**
  13516. * @inheritsDoc
  13517. */
  13518. getControlPoint: function(index) {
  13519. if ( 0===index ) {
  13520. return this.points[0];
  13521. } else if (1===index) {
  13522. return this.points[1];
  13523. }
  13524. },
  13525. /**
  13526. * @inheritsDoc
  13527. */
  13528. getContour : function(iSize) {
  13529. var contour= [];
  13530. contour.push( this.getPosition(0).clone() );
  13531. contour.push( this.getPosition(1).clone() );
  13532. return contour;
  13533. }
  13534. };
  13535. extend( CAAT.LinearPath, CAAT.PathSegment );
  13536. })();
  13537. (function() {
  13538. /**
  13539. * This class defines a Bezier cubic or quadric path segment.
  13540. *
  13541. * @constructor
  13542. * @extends CAAT.PathSegment
  13543. */
  13544. CAAT.CurvePath = function() {
  13545. CAAT.CurvePath.superclass.constructor.call(this);
  13546. this.newPosition= new CAAT.Point(0,0,0);
  13547. return this;
  13548. };
  13549. CAAT.CurvePath.prototype= {
  13550. curve: null, // a CAAT.Bezier instance.
  13551. newPosition: null, // spare holder for getPosition coordinate return.
  13552. applyAsPath : function(director) {
  13553. this.curve.applyAsPath(director);
  13554. return this;
  13555. },
  13556. setPoint : function( point, index ) {
  13557. if ( this.curve ) {
  13558. this.curve.setPoint(point,index);
  13559. }
  13560. },
  13561. /**
  13562. * Set this curve segment's points.
  13563. * @param points {Array<CAAT.Point>}
  13564. */
  13565. setPoints : function( points ) {
  13566. var curve = new CAAT.Bezier();
  13567. curve.setPoints(points);
  13568. this.curve = curve;
  13569. return this;
  13570. },
  13571. /**
  13572. * Set the pathSegment as a CAAT.Bezier quadric instance.
  13573. * Parameters are quadric coordinates control points.
  13574. *
  13575. * @param p0x {number}
  13576. * @param p0y {number}
  13577. * @param p1x {number}
  13578. * @param p1y {number}
  13579. * @param p2x {number}
  13580. * @param p2y {number}
  13581. * @return this
  13582. */
  13583. setQuadric : function(p0x,p0y, p1x,p1y, p2x,p2y) {
  13584. var curve = new CAAT.Bezier();
  13585. curve.setQuadric(p0x,p0y, p1x,p1y, p2x,p2y);
  13586. this.curve = curve;
  13587. this.updatePath();
  13588. return this;
  13589. },
  13590. /**
  13591. * Set the pathSegment as a CAAT.Bezier cubic instance.
  13592. * Parameters are cubic coordinates control points.
  13593. * @param p0x {number}
  13594. * @param p0y {number}
  13595. * @param p1x {number}
  13596. * @param p1y {number}
  13597. * @param p2x {number}
  13598. * @param p2y {number}
  13599. * @param p3x {number}
  13600. * @param p3y {number}
  13601. * @return this
  13602. */
  13603. setCubic : function(p0x,p0y, p1x,p1y, p2x,p2y, p3x,p3y) {
  13604. var curve = new CAAT.Bezier();
  13605. curve.setCubic(p0x,p0y, p1x,p1y, p2x,p2y, p3x,p3y);
  13606. this.curve = curve;
  13607. this.updatePath();
  13608. return this;
  13609. },
  13610. /**
  13611. * @inheritDoc
  13612. */
  13613. updatePath : function(point) {
  13614. this.curve.update();
  13615. this.length= this.curve.getLength();
  13616. this.curve.getBoundingBox(this.bbox);
  13617. return this;
  13618. },
  13619. /**
  13620. * @inheritDoc
  13621. */
  13622. getPosition : function(time) {
  13623. if ( time>1 || time<0 ) {
  13624. time%=1;
  13625. }
  13626. if ( time<0 ) {
  13627. time= 1+time;
  13628. }
  13629. this.curve.solve(this.newPosition, time);
  13630. return this.newPosition;
  13631. },
  13632. /**
  13633. * Gets the coordinate on the path relative to the path length.
  13634. * @param iLength {number} the length at which the coordinate will be taken from.
  13635. * @return {CAAT.Point} a CAAT.Point instance with the coordinate on the path corresponding to the
  13636. * iLenght parameter relative to segment's length.
  13637. */
  13638. getPositionFromLength : function(iLength) {
  13639. this.curve.solve( this.newPosition, iLength/this.length );
  13640. return this.newPosition;
  13641. },
  13642. /**
  13643. * Get path segment's first point's x coordinate.
  13644. * @return {number}
  13645. */
  13646. initialPositionX : function() {
  13647. return this.curve.coordlist[0].x;
  13648. },
  13649. /**
  13650. * Get path segment's last point's y coordinate.
  13651. * @return {number}
  13652. */
  13653. finalPositionX : function() {
  13654. return this.curve.coordlist[this.curve.coordlist.length-1].x;
  13655. },
  13656. /**
  13657. * @inheritDoc
  13658. * @param director {CAAT.Director}
  13659. * @param bDrawHandles {boolean}
  13660. */
  13661. paint : function( director,bDrawHandles ) {
  13662. this.curve.drawHandles= bDrawHandles;
  13663. director.ctx.strokeStyle= this.color;
  13664. this.curve.paint(director,bDrawHandles);
  13665. },
  13666. /**
  13667. * @inheritDoc
  13668. */
  13669. numControlPoints : function() {
  13670. return this.curve.coordlist.length;
  13671. },
  13672. /**
  13673. * @inheritDoc
  13674. * @param index
  13675. */
  13676. getControlPoint : function(index) {
  13677. return this.curve.coordlist[index];
  13678. },
  13679. /**
  13680. * @inheritDoc
  13681. */
  13682. endCurvePosition : function() {
  13683. return this.curve.endCurvePosition();
  13684. },
  13685. /**
  13686. * @inheritDoc
  13687. */
  13688. startCurvePosition : function() {
  13689. return this.curve.startCurvePosition();
  13690. },
  13691. /**
  13692. * @inheritDoc
  13693. * @param iSize
  13694. */
  13695. getContour : function(iSize) {
  13696. var contour=[];
  13697. for( var i=0; i<=iSize; i++ ) {
  13698. contour.push( {x: i/iSize, y: this.getPosition(i/iSize).y} );
  13699. }
  13700. return contour;
  13701. }
  13702. };
  13703. extend( CAAT.CurvePath, CAAT.PathSegment, null);
  13704. })();
  13705. (function() {
  13706. CAAT.ShapePath= function() {
  13707. CAAT.ShapePath.superclass.constructor.call(this);
  13708. this.points= [];
  13709. this.points.push( new CAAT.Point() );
  13710. this.points.push( new CAAT.Point() );
  13711. this.points.push( new CAAT.Point() );
  13712. this.points.push( new CAAT.Point() );
  13713. this.points.push( new CAAT.Point() );
  13714. this.newPosition= new CAAT.Point();
  13715. return this;
  13716. };
  13717. CAAT.ShapePath.prototype= {
  13718. points: null,
  13719. length: -1,
  13720. cw: true, // should be clock wise traversed ?
  13721. bbox: null,
  13722. newPosition: null, // spare point for calculations
  13723. applyAsPath : function(director) {
  13724. var ctx= director.ctx;
  13725. //ctx.rect( this.bbox.x, this.bbox.y, this.bbox.width, this.bbox.height );
  13726. if ( this.cw ) {
  13727. ctx.lineTo( this.points[0].x, this.points[0].y );
  13728. ctx.lineTo( this.points[1].x, this.points[1].y );
  13729. ctx.lineTo( this.points[2].x, this.points[2].y );
  13730. ctx.lineTo( this.points[3].x, this.points[3].y );
  13731. ctx.lineTo( this.points[4].x, this.points[4].y );
  13732. } else {
  13733. ctx.lineTo( this.points[4].x, this.points[4].y );
  13734. ctx.lineTo( this.points[3].x, this.points[3].y );
  13735. ctx.lineTo( this.points[2].x, this.points[2].y );
  13736. ctx.lineTo( this.points[1].x, this.points[1].y );
  13737. ctx.lineTo( this.points[0].x, this.points[0].y );
  13738. }
  13739. return this;
  13740. },
  13741. setPoint : function( point, index ) {
  13742. if ( index>=0 && index<this.points.length ) {
  13743. this.points[index]= point;
  13744. }
  13745. },
  13746. /**
  13747. * An array of {CAAT.Point} composed of two points.
  13748. * @param points {Array<CAAT.Point>}
  13749. */
  13750. setPoints : function( points ) {
  13751. this.points= [];
  13752. this.points.push( points[0] );
  13753. this.points.push( new CAAT.Point().set(points[1].x, points[0].y) );
  13754. this.points.push( points[1] );
  13755. this.points.push( new CAAT.Point().set(points[0].x, points[1].y) );
  13756. this.points.push( points[0].clone() );
  13757. this.updatePath();
  13758. return this;
  13759. },
  13760. setClockWise : function(cw) {
  13761. this.cw= cw!==undefined ? cw : true;
  13762. return this;
  13763. },
  13764. isClockWise : function() {
  13765. return this.cw;
  13766. },
  13767. /**
  13768. * Set this path segment's starting position.
  13769. * This method should not be called again after setFinalPosition has been called.
  13770. * @param x {number}
  13771. * @param y {number}
  13772. */
  13773. setInitialPosition : function( x, y ) {
  13774. for( var i=0, l= this.points.length; i<l; i++ ) {
  13775. this.points[i].x= x;
  13776. this.points[i].y= y;
  13777. }
  13778. return this;
  13779. },
  13780. /**
  13781. * Set a rectangle from points[0] to (finalX, finalY)
  13782. * @param finalX {number}
  13783. * @param finalY {number}
  13784. */
  13785. setFinalPosition : function( finalX, finalY ) {
  13786. this.points[2].x= finalX;
  13787. this.points[2].y= finalY;
  13788. this.points[1].x= finalX;
  13789. this.points[1].y= this.points[0].y;
  13790. this.points[3].x= this.points[0].x;
  13791. this.points[3].y= finalY;
  13792. this.points[4].x= this.points[0].x;
  13793. this.points[4].y= this.points[0].y;
  13794. this.updatePath();
  13795. return this;
  13796. },
  13797. /**
  13798. * @inheritDoc
  13799. */
  13800. endCurvePosition : function() {
  13801. return this.points[4];
  13802. },
  13803. /**
  13804. * @inheritsDoc
  13805. */
  13806. startCurvePosition : function() {
  13807. return this.points[0];
  13808. },
  13809. /**
  13810. * @inheritsDoc
  13811. */
  13812. getPosition : function(time) {
  13813. if ( time>1 || time<0 ) {
  13814. time%=1;
  13815. }
  13816. if ( time<0 ) {
  13817. time= 1+time;
  13818. }
  13819. if ( -1===this.length ) {
  13820. this.newPosition.set(0,0);
  13821. } else {
  13822. var w= this.bbox.width / this.length;
  13823. var h= this.bbox.height / this.length;
  13824. var accTime= 0;
  13825. var times;
  13826. var segments;
  13827. var index= 0;
  13828. if ( this.cw ) {
  13829. segments= [0,1,2,3,4];
  13830. times= [w,h,w,h];
  13831. } else {
  13832. segments= [4,3,2,1,0];
  13833. times= [h,w,h,w];
  13834. }
  13835. while( index<times.length ) {
  13836. if ( accTime+times[index]<time ) {
  13837. accTime+= times[index];
  13838. index++;
  13839. } else {
  13840. break;
  13841. }
  13842. }
  13843. time-=accTime;
  13844. var p0= segments[index];
  13845. var p1= segments[index+1];
  13846. // index tiene el indice del segmento en tiempo.
  13847. this.newPosition.set(
  13848. (this.points[p0].x + (this.points[p1].x - this.points[p0].x)*time/times[index]),
  13849. (this.points[p0].y + (this.points[p1].y - this.points[p0].y)*time/times[index]) );
  13850. }
  13851. return this.newPosition;
  13852. },
  13853. /**
  13854. * Returns initial path segment point's x coordinate.
  13855. * @return {number}
  13856. */
  13857. initialPositionX : function() {
  13858. return this.points[0].x;
  13859. },
  13860. /**
  13861. * Returns final path segment point's x coordinate.
  13862. * @return {number}
  13863. */
  13864. finalPositionX : function() {
  13865. return this.points[2].x;
  13866. },
  13867. /**
  13868. * Draws this path segment on screen. Optionally it can draw handles for every control point, in
  13869. * this case, start and ending path segment points.
  13870. * @param director {CAAT.Director}
  13871. * @param bDrawHandles {boolean}
  13872. */
  13873. paint : function(director, bDrawHandles) {
  13874. var ctx= director.ctx;
  13875. ctx.save();
  13876. ctx.strokeStyle= this.color;
  13877. ctx.beginPath();
  13878. ctx.strokeRect(
  13879. this.bbox.x, this.bbox.y,
  13880. this.bbox.width, this.bbox.height );
  13881. if ( bDrawHandles ) {
  13882. ctx.globalAlpha=0.5;
  13883. ctx.fillStyle='#7f7f00';
  13884. for( var i=0; i<this.points.length; i++ ) {
  13885. this.drawHandle( ctx, this.points[i].x, this.points[i].y );
  13886. /*
  13887. canvas.beginPath();
  13888. canvas.arc(
  13889. this.points[i].x,
  13890. this.points[i].y,
  13891. CAAT.Curve.prototype.HANDLE_SIZE/2,
  13892. 0,
  13893. 2*Math.PI,
  13894. false) ;
  13895. canvas.fill();
  13896. */
  13897. }
  13898. }
  13899. ctx.restore();
  13900. },
  13901. /**
  13902. * Get the number of control points. For this type of path segment, start and
  13903. * ending path segment points. Defaults to 2.
  13904. * @return {number}
  13905. */
  13906. numControlPoints : function() {
  13907. return this.points.length;
  13908. },
  13909. /**
  13910. * @inheritsDoc
  13911. */
  13912. getControlPoint: function(index) {
  13913. return this.points[index];
  13914. },
  13915. /**
  13916. * @inheritsDoc
  13917. */
  13918. getContour : function(iSize) {
  13919. var contour= [];
  13920. for( var i=0; i<this.points.length; i++ ) {
  13921. contour.push( this.points[i] );
  13922. }
  13923. return contour;
  13924. },
  13925. updatePath : function(point) {
  13926. if ( point ) {
  13927. if ( point===this.points[0] ) {
  13928. this.points[1].y= point.y;
  13929. this.points[3].x= point.x;
  13930. } else if ( point===this.points[1] ) {
  13931. this.points[0].y= point.y;
  13932. this.points[2].x= point.x;
  13933. } else if ( point===this.points[2] ) {
  13934. this.points[3].y= point.y;
  13935. this.points[1].x= point.x;
  13936. } else if ( point===this.points[3] ) {
  13937. this.points[0].x= point.x;
  13938. this.points[2].y= point.y;
  13939. }
  13940. this.points[4].x= this.points[0].x;
  13941. this.points[4].y= this.points[0].y;
  13942. }
  13943. this.bbox.setEmpty();
  13944. var minx= Number.MAX_VALUE, miny= Number.MAX_VALUE, maxx= -Number.MAX_VALUE, maxy= -Number.MAX_VALUE;
  13945. for( var i=0; i<4; i++ ) {
  13946. this.bbox.union( this.points[i].x, this.points[i].y );
  13947. }
  13948. this.length= 2*this.bbox.width + 2*this.bbox.height;
  13949. this.points[0].x= this.bbox.x;
  13950. this.points[0].y= this.bbox.y;
  13951. this.points[1].x= this.bbox.x+this.bbox.width;
  13952. this.points[1].y= this.bbox.y;
  13953. this.points[2].x= this.bbox.x + this.bbox.width;
  13954. this.points[2].y= this.bbox.y + this.bbox.height;
  13955. this.points[3].x= this.bbox.x;
  13956. this.points[3].y= this.bbox.y + this.bbox.height;
  13957. this.points[4].x= this.bbox.x;
  13958. this.points[4].y= this.bbox.y;
  13959. return this;
  13960. }
  13961. }
  13962. extend( CAAT.ShapePath, CAAT.PathSegment );
  13963. })();
  13964. (function() {
  13965. /**
  13966. * This class the top most abstraction of path related classes in CAAT. It defines a path composes un
  13967. * an unlimited number of path segments including CAAT.Path instances.
  13968. * <p>
  13969. * Every operation of the CAAT.PathSegment interface is performed for every path segment. In example,
  13970. * the method <code>getLength</code> will contain the sum of every path segment's length.
  13971. * <p>
  13972. * An example of CAAT.Path will be as follows:
  13973. * <code>
  13974. * path.beginPath(x,y).<br>
  13975. * &nbsp;&nbsp;addLineTo(x1,y1).<br>
  13976. * &nbsp;&nbsp;addLineTo(x2,y2).<br>
  13977. * &nbsp;&nbsp;addQuadricTo(...).<br>
  13978. * &nbsp;&nbsp;addCubicTo(...).<br>
  13979. * &nbsp;&nbsp;endPath();<br>
  13980. * </code>
  13981. * <p>
  13982. * This code creates a path composed of four chained segments, starting at (x,y) and having each
  13983. * segment starting where the previous one ended.
  13984. * <p>
  13985. * This class is intended to wrap the other kind of path segment classes when just a one segmented
  13986. * path is to be defined. The methods <code>setLinear, setCubic and setQuadrid</code> will make
  13987. * a CAAT.Path instance to be defined by just one segment.
  13988. *
  13989. * @constructor
  13990. * @extends CAAT.PathSegment
  13991. */
  13992. CAAT.Path= function() {
  13993. CAAT.Path.superclass.constructor.call(this);
  13994. this.newPosition= new CAAT.Point(0,0,0);
  13995. this.pathSegments= [];
  13996. this.behaviorList= [];
  13997. this.matrix= new CAAT.Matrix();
  13998. this.tmpMatrix= new CAAT.Matrix();
  13999. return this;
  14000. };
  14001. CAAT.Path.prototype= {
  14002. pathSegments: null, // a collection of CAAT.PathSegment instances.
  14003. pathSegmentDurationTime: null, // precomputed segment duration relative to segment legnth/path length
  14004. pathSegmentStartTime: null, // precomputed segment start time relative to segment legnth/path length and duration.
  14005. newPosition: null, // spare CAAT.Point.
  14006. pathLength: -1, // path length (sum of every segment length)
  14007. /*
  14008. starting path position
  14009. */
  14010. beginPathX: -1,
  14011. beginPathY: -1,
  14012. /*
  14013. last path coordinates position (using when building the path).
  14014. */
  14015. trackPathX: -1,
  14016. trackPathY: -1,
  14017. /*
  14018. needed to drag control points.
  14019. */
  14020. ax: -1,
  14021. ay: -1,
  14022. point: [],
  14023. interactive: true,
  14024. behaviorList: null,
  14025. /** rotation behavior info **/
  14026. rb_angle: 0,
  14027. rb_rotateAnchorX: .5,
  14028. rb_rotateAnchorY: .5,
  14029. /** scale behavior info **/
  14030. sb_scaleX: 1,
  14031. sb_scaleY: 1,
  14032. sb_scaleAnchorX: .5,
  14033. sb_scaleAnchorY: .5,
  14034. tAnchorX: 0,
  14035. tAnchorY: 0,
  14036. /** translate behavior info **/
  14037. tb_x: 0,
  14038. tb_y: 0,
  14039. /** behavior affine transformation matrix **/
  14040. matrix: null,
  14041. tmpMatrix: null,
  14042. /** if behaviors are to be applied, save original path points **/
  14043. pathPoints: null,
  14044. /** path width and height **/
  14045. width: 0,
  14046. height: 0,
  14047. clipOffsetX : 0,
  14048. clipOffsetY : 0,
  14049. applyAsPath : function(director) {
  14050. var ctx= director.ctx;
  14051. director.modelViewMatrix.transformRenderingContext( ctx );
  14052. ctx.beginPath();
  14053. ctx.globalCompositeOperation= 'source-out';
  14054. ctx.moveTo(
  14055. this.getFirstPathSegment().startCurvePosition().x,
  14056. this.getFirstPathSegment().startCurvePosition().y
  14057. );
  14058. for( var i=0; i<this.pathSegments.length; i++ ) {
  14059. this.pathSegments[i].applyAsPath(director);
  14060. }
  14061. ctx.globalCompositeOperation= 'source-over';
  14062. return this;
  14063. },
  14064. /**
  14065. * Set whether this path should paint handles for every control point.
  14066. * @param interactive {boolean}.
  14067. */
  14068. setInteractive : function(interactive) {
  14069. this.interactive= interactive;
  14070. return this;
  14071. },
  14072. getFirstPathSegment : function() {
  14073. return this.pathSegments.length ?
  14074. this.pathSegments[0] :
  14075. null;
  14076. },
  14077. getLastPathSegment : function() {
  14078. return this.pathSegments.length ?
  14079. this.pathSegments[ this.pathSegments.length-1 ] :
  14080. null;
  14081. },
  14082. /**
  14083. * Return the last point of the last path segment of this compound path.
  14084. * @return {CAAT.Point}
  14085. */
  14086. endCurvePosition : function() {
  14087. if ( this.pathSegments.length ) {
  14088. return this.pathSegments[ this.pathSegments.length-1 ].endCurvePosition();
  14089. } else {
  14090. return new CAAT.Point().set( this.beginPathX, this.beginPathY );
  14091. }
  14092. },
  14093. /**
  14094. * Return the first point of the first path segment of this compound path.
  14095. * @return {CAAT.Point}
  14096. */
  14097. startCurvePosition : function() {
  14098. return this.pathSegments[ 0 ].startCurvePosition();
  14099. },
  14100. /**
  14101. * Return the last path segment added to this path.
  14102. * @return {CAAT.PathSegment}
  14103. */
  14104. getCurrentPathSegment : function() {
  14105. return this.pathSegments[ this.pathSegments.length-1 ];
  14106. },
  14107. /**
  14108. * Set the path to be composed by a single LinearPath segment.
  14109. * @param x0 {number}
  14110. * @param y0 {number}
  14111. * @param x1 {number}
  14112. * @param y1 {number}
  14113. * @return this
  14114. */
  14115. setLinear : function(x0,y0,x1,y1) {
  14116. this.beginPath(x0,y0);
  14117. this.addLineTo(x1,y1);
  14118. this.endPath();
  14119. return this;
  14120. },
  14121. /**
  14122. * Set this path to be composed by a single Quadric Bezier path segment.
  14123. * @param x0 {number}
  14124. * @param y0 {number}
  14125. * @param x1 {number}
  14126. * @param y1 {number}
  14127. * @param x2 {number}
  14128. * @param y2 {number}
  14129. * @return this
  14130. */
  14131. setQuadric : function(x0,y0,x1,y1,x2,y2) {
  14132. this.beginPath(x0,y0);
  14133. this.addQuadricTo(x1,y1,x2,y2);
  14134. this.endPath();
  14135. return this;
  14136. },
  14137. /**
  14138. * Sets this path to be composed by a single Cubic Bezier path segment.
  14139. * @param x0 {number}
  14140. * @param y0 {number}
  14141. * @param x1 {number}
  14142. * @param y1 {number}
  14143. * @param x2 {number}
  14144. * @param y2 {number}
  14145. * @param x3 {number}
  14146. * @param y3 {number}
  14147. *
  14148. * @return this
  14149. */
  14150. setCubic : function(x0,y0,x1,y1,x2,y2,x3,y3) {
  14151. this.beginPath(x0,y0);
  14152. this.addCubicTo(x1,y1,x2,y2,x3,y3);
  14153. this.endPath();
  14154. return this;
  14155. },
  14156. setRectangle : function(x0,y0, x1,y1) {
  14157. this.beginPath(x0,y0);
  14158. this.addRectangleTo(x1,y1);
  14159. this.endPath();
  14160. return this;
  14161. },
  14162. setCatmullRom : function( points, closed ) {
  14163. if ( closed ) {
  14164. points = points.slice(0)
  14165. points.unshift(points[points.length-1])
  14166. points.push(points[1])
  14167. points.push(points[2])
  14168. }
  14169. for( var i=1; i<points.length-2; i++ ) {
  14170. var segment= new CAAT.CurvePath().setColor("#000").setParent(this);
  14171. var cm= new CAAT.CatmullRom().setCurve(
  14172. points[ i-1 ],
  14173. points[ i ],
  14174. points[ i+1 ],
  14175. points[ i+2 ]
  14176. );
  14177. segment.curve= cm;
  14178. this.pathSegments.push(segment);
  14179. }
  14180. return this;
  14181. },
  14182. /**
  14183. * Add a CAAT.PathSegment instance to this path.
  14184. * @param pathSegment {CAAT.PathSegment}
  14185. * @return this
  14186. *
  14187. * @deprecated
  14188. */
  14189. addSegment : function(pathSegment) {
  14190. pathSegment.setParent(this);
  14191. this.pathSegments.push(pathSegment);
  14192. return this;
  14193. },
  14194. addRectangleTo : function( x1,y1, cw, color ) {
  14195. var r= new CAAT.ShapePath();
  14196. r.setPoints([
  14197. this.endCurvePosition(),
  14198. new CAAT.Point().set(x1,y1)
  14199. ]);
  14200. r.setClockWise(cw);
  14201. r.setColor(color);
  14202. r.setParent(this);
  14203. this.pathSegments.push(r);
  14204. return this;
  14205. },
  14206. /**
  14207. * Add a Quadric Bezier path segment to this path.
  14208. * The segment starts in the current last path coordinate.
  14209. * @param px1 {number}
  14210. * @param py1 {number}
  14211. * @param px2 {number}
  14212. * @param py2 {number}
  14213. * @param color {color=}. optional parameter. determines the color to draw the segment with (if
  14214. * being drawn by a CAAT.PathActor).
  14215. *
  14216. * @return this
  14217. */
  14218. addQuadricTo : function( px1,py1, px2,py2, color ) {
  14219. var bezier= new CAAT.Bezier();
  14220. bezier.setPoints(
  14221. [
  14222. this.endCurvePosition(),
  14223. new CAAT.Point().set(px1,py1),
  14224. new CAAT.Point().set(px2,py2)
  14225. ]);
  14226. this.trackPathX= px2;
  14227. this.trackPathY= py2;
  14228. var segment= new CAAT.CurvePath().setColor(color).setParent(this);
  14229. segment.curve= bezier;
  14230. this.pathSegments.push(segment);
  14231. return this;
  14232. },
  14233. /**
  14234. * Add a Cubic Bezier segment to this path.
  14235. * The segment starts in the current last path coordinate.
  14236. * @param px1 {number}
  14237. * @param py1 {number}
  14238. * @param px2 {number}
  14239. * @param py2 {number}
  14240. * @param px3 {number}
  14241. * @param py3 {number}
  14242. * @param color {color=}. optional parameter. determines the color to draw the segment with (if
  14243. * being drawn by a CAAT.PathActor).
  14244. *
  14245. * @return this
  14246. */
  14247. addCubicTo : function( px1,py1, px2,py2, px3,py3, color ) {
  14248. var bezier= new CAAT.Bezier();
  14249. bezier.setPoints(
  14250. [
  14251. this.endCurvePosition(),
  14252. new CAAT.Point().set(px1,py1),
  14253. new CAAT.Point().set(px2,py2),
  14254. new CAAT.Point().set(px3,py3)
  14255. ]);
  14256. this.trackPathX= px3;
  14257. this.trackPathY= py3;
  14258. var segment= new CAAT.CurvePath().setColor(color).setParent(this);
  14259. segment.curve= bezier;
  14260. this.pathSegments.push(segment);
  14261. return this;
  14262. },
  14263. /**
  14264. * Add a Catmull-Rom segment to this path.
  14265. * The segment starts in the current last path coordinate.
  14266. * @param px1 {number}
  14267. * @param py1 {number}
  14268. * @param px2 {number}
  14269. * @param py2 {number}
  14270. * @param px3 {number}
  14271. * @param py3 {number}
  14272. * @param color {color=}. optional parameter. determines the color to draw the segment with (if
  14273. * being drawn by a CAAT.PathActor).
  14274. *
  14275. * @return this
  14276. */
  14277. addCatmullTo : function( px1,py1, px2,py2, px3,py3, color ) {
  14278. var curve= new CAAT.CatmullRom().setColor(color);
  14279. curve.setCurve(this.trackPathX,this.trackPathY, px1,py1, px2,py2, px3,py3);
  14280. this.trackPathX= px3;
  14281. this.trackPathY= py3;
  14282. var segment= new CAAT.CurvePath().setParent(this);
  14283. segment.curve= curve;
  14284. this.pathSegments.push(segment);
  14285. return this;
  14286. },
  14287. /**
  14288. * Adds a line segment to this path.
  14289. * The segment starts in the current last path coordinate.
  14290. * @param px1 {number}
  14291. * @param py1 {number}
  14292. * @param color {color=}. optional parameter. determines the color to draw the segment with (if
  14293. * being drawn by a CAAT.PathActor).
  14294. *
  14295. * @return this
  14296. */
  14297. addLineTo : function( px1,py1, color ) {
  14298. var segment= new CAAT.LinearPath().setColor(color);
  14299. segment.setPoints( [
  14300. this.endCurvePosition(),
  14301. new CAAT.Point().set(px1,py1)
  14302. ]);
  14303. segment.setParent(this);
  14304. this.trackPathX= px1;
  14305. this.trackPathY= py1;
  14306. this.pathSegments.push(segment);
  14307. return this;
  14308. },
  14309. /**
  14310. * Set the path's starting point. The method startCurvePosition will return this coordinate.
  14311. * <p>
  14312. * If a call to any method of the form <code>add<Segment>To</code> is called before this calling
  14313. * this method, they will assume to start at -1,-1 and probably you'll get the wrong path.
  14314. * @param px0 {number}
  14315. * @param py0 {number}
  14316. *
  14317. * @return this
  14318. */
  14319. beginPath : function( px0, py0 ) {
  14320. this.trackPathX= px0;
  14321. this.trackPathY= py0;
  14322. this.beginPathX= px0;
  14323. this.beginPathY= py0;
  14324. return this;
  14325. },
  14326. /**
  14327. * <del>Close the path by adding a line path segment from the current last path
  14328. * coordinate to startCurvePosition coordinate</del>.
  14329. * <p>
  14330. * This method closes a path by setting its last path segment's last control point
  14331. * to be the first path segment's first control point.
  14332. * <p>
  14333. * This method also sets the path as finished, and calculates all path's information
  14334. * such as length and bounding box.
  14335. *
  14336. * @return this
  14337. */
  14338. closePath : function() {
  14339. this.getLastPathSegment().setPoint(
  14340. this.getFirstPathSegment().startCurvePosition(),
  14341. this.getLastPathSegment().numControlPoints()-1 );
  14342. this.trackPathX= this.beginPathX;
  14343. this.trackPathY= this.beginPathY;
  14344. this.endPath();
  14345. return this;
  14346. },
  14347. /**
  14348. * Finishes the process of building the path. It involves calculating each path segments length
  14349. * and proportional length related to a normalized path length of 1.
  14350. * It also sets current paths length.
  14351. * These calculi are needed to traverse the path appropriately.
  14352. * <p>
  14353. * This method must be called explicitly, except when closing a path (that is, calling the
  14354. * method closePath) which calls this method as well.
  14355. *
  14356. * @return this
  14357. */
  14358. endPath : function() {
  14359. this.pathSegmentStartTime=[];
  14360. this.pathSegmentDurationTime= [];
  14361. this.updatePath();
  14362. return this;
  14363. },
  14364. /**
  14365. * This method, returns a CAAT.Point instance indicating a coordinate in the path.
  14366. * The returned coordinate is the corresponding to normalizing the path's length to 1,
  14367. * and then finding what path segment and what coordinate in that path segment corresponds
  14368. * for the input time parameter.
  14369. * <p>
  14370. * The parameter time must be a value ranging 0..1.
  14371. * If not constrained to these values, the parameter will be modulus 1, and then, if less
  14372. * than 0, be normalized to 1+time, so that the value always ranges from 0 to 1.
  14373. * <p>
  14374. * This method is needed when traversing the path throughout a CAAT.Interpolator instance.
  14375. *
  14376. * @param time a value between 0 and 1 both inclusive. 0 will return path's starting coordinate.
  14377. * 1 will return path's end coordinate.
  14378. *
  14379. * @return {CAAT.Point}
  14380. */
  14381. getPosition : function(time) {
  14382. if ( time>1 || time<0 ) {
  14383. time%=1;
  14384. }
  14385. if ( time<0 ) {
  14386. time= 1+time;
  14387. }
  14388. /*
  14389. var found= false;
  14390. for( var i=0; i<this.pathSegments.length; i++ ) {
  14391. if (this.pathSegmentStartTime[i]<=time && time<=this.pathSegmentStartTime[i]+this.pathSegmentDurationTime[i]) {
  14392. time= this.pathSegmentDurationTime[i] ?
  14393. (time-this.pathSegmentStartTime[i])/this.pathSegmentDurationTime[i] :
  14394. 0;
  14395. var pointInPath= this.pathSegments[i].getPosition(time);
  14396. this.newPosition.x= pointInPath.x;
  14397. this.newPosition.y= pointInPath.y;
  14398. found= true;
  14399. break;
  14400. }
  14401. }
  14402. return found ? this.newPosition : this.endCurvePosition();
  14403. */
  14404. var ps= this.pathSegments;
  14405. var psst= this.pathSegmentStartTime;
  14406. var psdt= this.pathSegmentDurationTime;
  14407. var l= 0;
  14408. var r= ps.length;
  14409. var m;
  14410. var np= this.newPosition;
  14411. var psstv;
  14412. while( l!==r ) {
  14413. m= ((r+l)/2)|0;
  14414. psstv= psst[m];
  14415. if ( psstv<=time && time<=psstv+psdt[m]) {
  14416. time= psdt[m] ?
  14417. (time-psstv)/psdt[m] :
  14418. 0;
  14419. var pointInPath= ps[m].getPosition(time);
  14420. np.x= pointInPath.x;
  14421. np.y= pointInPath.y;
  14422. return np;
  14423. } else if ( time<psstv ) {
  14424. r= m;
  14425. } else /*if ( time>=psstv )*/ {
  14426. l= m+1;
  14427. }
  14428. }
  14429. return this.endCurvePosition();
  14430. },
  14431. /**
  14432. * Analogously to the method getPosition, this method returns a CAAT.Point instance with
  14433. * the coordinate on the path that corresponds to the given length. The input length is
  14434. * related to path's length.
  14435. *
  14436. * @param iLength {number} a float with the target length.
  14437. * @return {CAAT.Point}
  14438. */
  14439. getPositionFromLength : function(iLength) {
  14440. iLength%=this.getLength();
  14441. if (iLength<0 ) {
  14442. iLength+= this.getLength();
  14443. }
  14444. var accLength=0;
  14445. for( var i=0; i<this.pathSegments.length; i++ ) {
  14446. if (accLength<=iLength && iLength<=this.pathSegments[i].getLength()+accLength) {
  14447. iLength-= accLength;
  14448. var pointInPath= this.pathSegments[i].getPositionFromLength(iLength);
  14449. this.newPosition.x= pointInPath.x;
  14450. this.newPosition.y= pointInPath.y;
  14451. break;
  14452. }
  14453. accLength+= this.pathSegments[i].getLength();
  14454. }
  14455. return this.newPosition;
  14456. },
  14457. /**
  14458. * Paints the path.
  14459. * This method is called by CAAT.PathActor instances.
  14460. * If the path is set as interactive (by default) path segment will draw curve modification
  14461. * handles as well.
  14462. *
  14463. * @param director {CAAT.Director} a CAAT.Director instance.
  14464. */
  14465. paint : function( director ) {
  14466. for( var i=0; i<this.pathSegments.length; i++ ) {
  14467. this.pathSegments[i].paint(director,this.interactive);
  14468. }
  14469. },
  14470. /**
  14471. * Method invoked when a CAAT.PathActor stops dragging a control point.
  14472. */
  14473. release : function() {
  14474. this.ax= -1;
  14475. this.ay= -1;
  14476. },
  14477. /**
  14478. * Returns an integer with the number of path segments that conform this path.
  14479. * @return {number}
  14480. */
  14481. getNumSegments : function() {
  14482. return this.pathSegments.length;
  14483. },
  14484. /**
  14485. * Gets a CAAT.PathSegment instance.
  14486. * @param index {number} the index of the desired CAAT.PathSegment.
  14487. * @return CAAT.PathSegment
  14488. */
  14489. getSegment : function(index) {
  14490. return this.pathSegments[index];
  14491. },
  14492. numControlPoints : function() {
  14493. return this.points.length;
  14494. },
  14495. getControlPoint : function(index) {
  14496. return this.points[index];
  14497. },
  14498. /**
  14499. * Indicates that some path control point has changed, and that the path must recalculate
  14500. * its internal data, ie: length and bbox.
  14501. */
  14502. updatePath : function(point, callback) {
  14503. var i,j;
  14504. this.length=0;
  14505. this.bbox.setEmpty();
  14506. this.points= [];
  14507. var xmin= Number.MAX_VALUE, ymin= Number.MAX_VALUE;
  14508. for( i=0; i<this.pathSegments.length; i++ ) {
  14509. this.pathSegments[i].updatePath(point);
  14510. this.length+= this.pathSegments[i].getLength();
  14511. this.bbox.unionRectangle( this.pathSegments[i].bbox );
  14512. for( j=0; j<this.pathSegments[i].numControlPoints(); j++ ) {
  14513. var pt= this.pathSegments[i].getControlPoint( j );
  14514. this.points.push( pt );
  14515. if ( pt.x < xmin ) {
  14516. xmin= pt.x;
  14517. }
  14518. if ( pt.y < ymin ) {
  14519. ymin= pt.y;
  14520. }
  14521. }
  14522. }
  14523. this.clipOffsetX= -xmin;
  14524. this.clipOffsetY= -ymin;
  14525. this.width= this.bbox.width;
  14526. this.height= this.bbox.height;
  14527. this.setLocation( this.bbox.x, this.bbox.y );
  14528. this.bbox.x= 0;
  14529. this.bbox.y= 0;
  14530. this.bbox.x1= this.width;
  14531. this.bbox.y1= this.height;
  14532. this.pathSegmentStartTime= [];
  14533. this.pathSegmentDurationTime= [];
  14534. var i;
  14535. for( i=0; i<this.pathSegments.length; i++) {
  14536. this.pathSegmentStartTime.push(0);
  14537. this.pathSegmentDurationTime.push(0);
  14538. }
  14539. for( i=0; i<this.pathSegments.length; i++) {
  14540. this.pathSegmentDurationTime[i]= this.getLength() ? this.pathSegments[i].getLength()/this.getLength() : 0;
  14541. if ( i>0 ) {
  14542. this.pathSegmentStartTime[i]= this.pathSegmentStartTime[i-1]+this.pathSegmentDurationTime[i-1];
  14543. } else {
  14544. this.pathSegmentStartTime[0]= 0;
  14545. }
  14546. this.pathSegments[i].endPath();
  14547. }
  14548. this.extractPathPoints();
  14549. if ( typeof callback!=='undefined' ) {
  14550. callback(this);
  14551. }
  14552. return this;
  14553. },
  14554. /**
  14555. * Sent by a CAAT.PathActor instance object to try to drag a path's control point.
  14556. * @param x {number}
  14557. * @param y {number}
  14558. */
  14559. press: function(x,y) {
  14560. if (!this.interactive) {
  14561. return;
  14562. }
  14563. var HS= CAAT.Curve.prototype.HANDLE_SIZE/2;
  14564. for( var i=0; i<this.pathSegments.length; i++ ) {
  14565. for( var j=0; j<this.pathSegments[i].numControlPoints(); j++ ) {
  14566. var point= this.pathSegments[i].getControlPoint(j);
  14567. if ( x>=point.x-HS &&
  14568. y>=point.y-HS &&
  14569. x<point.x+HS &&
  14570. y<point.y+HS ) {
  14571. this.point= point;
  14572. return;
  14573. }
  14574. }
  14575. }
  14576. this.point= null;
  14577. },
  14578. /**
  14579. * Drags a path's control point.
  14580. * If the method press has not set needed internal data to drag a control point, this
  14581. * method will do nothing, regardless the user is dragging on the CAAT.PathActor delegate.
  14582. * @param x {number}
  14583. * @param y {number}
  14584. */
  14585. drag : function(x,y,callback) {
  14586. if (!this.interactive) {
  14587. return;
  14588. }
  14589. if ( null===this.point ) {
  14590. return;
  14591. }
  14592. if ( -1===this.ax || -1===this.ay ) {
  14593. this.ax= x;
  14594. this.ay= y;
  14595. }
  14596. this.point.x+= x-this.ax;
  14597. this.point.y+= y-this.ay;
  14598. this.ax= x;
  14599. this.ay= y;
  14600. this.updatePath(this.point,callback);
  14601. },
  14602. /**
  14603. * Returns a collection of CAAT.Point objects which conform a path's contour.
  14604. * @param iSize {number}. Number of samples for each path segment.
  14605. * @return {[CAAT.Point]}
  14606. */
  14607. getContour : function(iSize) {
  14608. var contour=[];
  14609. for( var i=0; i<=iSize; i++ ) {
  14610. contour.push( new CAAT.Point().set( i/iSize, this.getPosition(i/iSize).y, 0 ) );
  14611. }
  14612. return contour;
  14613. },
  14614. /**
  14615. * Reposition this path points.
  14616. * This operation will only take place if the supplied points array equals in size to
  14617. * this path's already set points.
  14618. * @param points {Array<CAAT.Point>}
  14619. */
  14620. setPoints : function( points ) {
  14621. if ( this.points.length===points.length ) {
  14622. for( var i=0; i<points.length; i++ ) {
  14623. this.points[i].x= points[i].x;
  14624. this.points[i].y= points[i].y;
  14625. }
  14626. }
  14627. return this;
  14628. },
  14629. /**
  14630. * Set a point from this path.
  14631. * @param point {CAAT.Point}
  14632. * @param index {integer} a point index.
  14633. */
  14634. setPoint : function( point, index ) {
  14635. if ( index>=0 && index<this.points.length ) {
  14636. this.points[index].x= point.x;
  14637. this.points[index].y= point.y;
  14638. }
  14639. return this;
  14640. },
  14641. /**
  14642. * Removes all behaviors from an Actor.
  14643. * @return this
  14644. */
  14645. emptyBehaviorList : function() {
  14646. this.behaviorList=[];
  14647. return this;
  14648. },
  14649. extractPathPoints : function() {
  14650. if ( !this.pathPoints ) {
  14651. var i;
  14652. this.pathPoints= [];
  14653. for ( i=0; i<this.numControlPoints(); i++ ) {
  14654. this.pathPoints.push( this.getControlPoint(i).clone() );
  14655. }
  14656. }
  14657. return this;
  14658. },
  14659. /**
  14660. * Add a Behavior to the Actor.
  14661. * An Actor accepts an undefined number of Behaviors.
  14662. *
  14663. * @param behavior {CAAT.Behavior} a CAAT.Behavior instance
  14664. * @return this
  14665. */
  14666. addBehavior : function( behavior ) {
  14667. this.behaviorList.push(behavior);
  14668. // this.extractPathPoints();
  14669. return this;
  14670. },
  14671. /**
  14672. * Remove a Behavior from the Actor.
  14673. * If the Behavior is not present at the actor behavior collection nothing happends.
  14674. *
  14675. * @param behavior {CAAT.Behavior} a CAAT.Behavior instance.
  14676. */
  14677. removeBehaviour : function( behavior ) {
  14678. var n= this.behaviorList.length-1;
  14679. while(n) {
  14680. if ( this.behaviorList[n]===behavior ) {
  14681. this.behaviorList.splice(n,1);
  14682. return this;
  14683. }
  14684. }
  14685. return this;
  14686. },
  14687. /**
  14688. * Remove a Behavior with id param as behavior identifier from this actor.
  14689. * This function will remove ALL behavior instances with the given id.
  14690. *
  14691. * @param id {number} an integer.
  14692. * return this;
  14693. */
  14694. removeBehaviorById : function( id ) {
  14695. for( var n=0; n<this.behaviorList.length; n++ ) {
  14696. if ( this.behaviorList[n].id===id) {
  14697. this.behaviorList.splice(n,1);
  14698. }
  14699. }
  14700. return this;
  14701. },
  14702. applyBehaviors : function(time) {
  14703. // if (this.behaviorList.length) {
  14704. for( var i=0; i<this.behaviorList.length; i++ ) {
  14705. this.behaviorList[i].apply(time,this);
  14706. }
  14707. /** calculate behavior affine transform matrix **/
  14708. this.setATMatrix();
  14709. for (i = 0; i < this.numControlPoints(); i++) {
  14710. this.setPoint(
  14711. this.matrix.transformCoord(
  14712. this.pathPoints[i].clone().translate( this.clipOffsetX, this.clipOffsetY )), i);
  14713. }
  14714. // }
  14715. return this;
  14716. },
  14717. setATMatrix : function() {
  14718. this.matrix.identity();
  14719. var m= this.tmpMatrix.identity();
  14720. var mm= this.matrix.matrix;
  14721. var c,s,_m00,_m01,_m10,_m11;
  14722. var mm0, mm1, mm2, mm3, mm4, mm5;
  14723. var bbox= this.bbox;
  14724. var bbw= bbox.width ;
  14725. var bbh= bbox.height ;
  14726. var bbx= bbox.x;
  14727. var bby= bbox.y
  14728. mm0= 1;
  14729. mm1= 0;
  14730. mm3= 0;
  14731. mm4= 1;
  14732. mm2= this.tb_x - bbx - this.tAnchorX * bbw;
  14733. mm5= this.tb_y - bby - this.tAnchorY * bbh;
  14734. if ( this.rb_angle ) {
  14735. var rbx= (this.rb_rotateAnchorX*bbw + bbx);
  14736. var rby= (this.rb_rotateAnchorY*bbh + bby);
  14737. mm2+= mm0*rbx + mm1*rby;
  14738. mm5+= mm3*rbx + mm4*rby;
  14739. c= Math.cos( this.rb_angle );
  14740. s= Math.sin( this.rb_angle);
  14741. _m00= mm0;
  14742. _m01= mm1;
  14743. _m10= mm3;
  14744. _m11= mm4;
  14745. mm0= _m00*c + _m01*s;
  14746. mm1= -_m00*s + _m01*c;
  14747. mm3= _m10*c + _m11*s;
  14748. mm4= -_m10*s + _m11*c;
  14749. mm2+= -mm0*rbx - mm1*rby;
  14750. mm5+= -mm3*rbx - mm4*rby;
  14751. }
  14752. if ( this.sb_scaleX!=1 || this.sb_scaleY!=1 ) {
  14753. var sbx= (this.sb_scaleAnchorX*bbw + bbx);
  14754. var sby= (this.sb_scaleAnchorY*bbh + bby);
  14755. mm2+= mm0*sbx + mm1*sby;
  14756. mm5+= mm3*sbx + mm4*sby;
  14757. mm0= mm0*this.sb_scaleX;
  14758. mm1= mm1*this.sb_scaleY;
  14759. mm3= mm3*this.sb_scaleX;
  14760. mm4= mm4*this.sb_scaleY;
  14761. mm2+= -mm0*sbx - mm1*sby;
  14762. mm5+= -mm3*sbx - mm4*sby;
  14763. }
  14764. mm[0]= mm0;
  14765. mm[1]= mm1;
  14766. mm[2]= mm2;
  14767. mm[3]= mm3;
  14768. mm[4]= mm4;
  14769. mm[5]= mm5;
  14770. return this;
  14771. },
  14772. setRotationAnchored : function( angle, rx, ry ) {
  14773. this.rb_angle= angle;
  14774. this.rb_rotateAnchorX= rx;
  14775. this.rb_rotateAnchorY= ry;
  14776. return this;
  14777. },
  14778. setRotationAnchor : function( ax, ay ) {
  14779. this.rb_rotateAnchorX= ax;
  14780. this.rb_rotateAnchorY= ay;
  14781. },
  14782. setRotation : function( angle ) {
  14783. this.rb_angle= angle;
  14784. },
  14785. setScaleAnchored : function( scaleX, scaleY, sx, sy ) {
  14786. this.sb_scaleX= scaleX;
  14787. this.sb_scaleAnchorX= sx;
  14788. this.sb_scaleY= scaleY;
  14789. this.sb_scaleAnchorY= sy;
  14790. return this;
  14791. },
  14792. setScale : function( sx, sy ) {
  14793. this.sb_scaleX= sx;
  14794. this.sb_scaleY= sy;
  14795. return this;
  14796. },
  14797. setScaleAnchor : function( ax, ay ) {
  14798. this.sb_scaleAnchorX= ax;
  14799. this.sb_scaleAnchorY= ay;
  14800. return this;
  14801. },
  14802. setPositionAnchor : function( ax, ay ) {
  14803. this.tAnchorX= ax;
  14804. this.tAnchorY= ay;
  14805. return this;
  14806. },
  14807. setPositionAnchored : function( x,y,ax,ay ) {
  14808. this.tb_x= x;
  14809. this.tb_y= y;
  14810. this.tAnchorX= ax;
  14811. this.tAnchorY= ay;
  14812. return this;
  14813. },
  14814. setPosition : function( x,y ) {
  14815. this.tb_x= x;
  14816. this.tb_y= y;
  14817. return this;
  14818. },
  14819. setLocation : function( x, y ) {
  14820. this.tb_x= x;
  14821. this.tb_y= y;
  14822. return this;
  14823. },
  14824. flatten : function( npatches, closed ) {
  14825. var point= this.getPositionFromLength(0);
  14826. var path= new CAAT.Path().beginPath( point.x, point.y );
  14827. for( var i=0; i<npatches; i++ ) {
  14828. point= this.getPositionFromLength(i/npatches*this.length);
  14829. path.addLineTo( point.x, point.y );
  14830. }
  14831. if ( closed) {
  14832. path.closePath();
  14833. } else {
  14834. path.endPath();
  14835. }
  14836. return path;
  14837. }
  14838. };
  14839. extend( CAAT.Path, CAAT.PathSegment, null);
  14840. })();/**
  14841. * See LICENSE file.
  14842. *
  14843. * An actor to show the path and its handles in the scene graph.
  14844. *
  14845. **/
  14846. (function() {
  14847. /**
  14848. * This class paints and handles the interactive behavior of a path.
  14849. *
  14850. * @constructor
  14851. * @extends CAAT.ActorContainer
  14852. */
  14853. CAAT.PathActor= function() {
  14854. CAAT.PathActor.superclass.constructor.call(this);
  14855. return this;
  14856. };
  14857. CAAT.PathActor.prototype= {
  14858. path : null,
  14859. pathBoundingRectangle : null,
  14860. bOutline : false,
  14861. outlineColor : 'black',
  14862. onUpdateCallback : null,
  14863. interactive : false,
  14864. /**
  14865. * Return the contained path.
  14866. * @return {CAAT.Path}
  14867. */
  14868. getPath : function() {
  14869. return this.path;
  14870. },
  14871. /**
  14872. * Sets the path to manage.
  14873. * @param path {CAAT.PathSegment}
  14874. * @return this
  14875. */
  14876. setPath : function(path) {
  14877. this.path= path;
  14878. if ( path!=null ) {
  14879. this.pathBoundingRectangle= path.getBoundingBox();
  14880. this.setInteractive( this.interactive );
  14881. }
  14882. return this;
  14883. },
  14884. /**
  14885. * Paint this actor.
  14886. * @param director {CAAT.Director}
  14887. * @param time {number}. Scene time.
  14888. */
  14889. paint : function(director, time) {
  14890. CAAT.PathActor.superclass.paint.call( this, director, time );
  14891. if ( !this.path ) {
  14892. return;
  14893. }
  14894. var ctx= director.ctx;
  14895. ctx.strokeStyle='#000';
  14896. this.path.paint(director, this.interactive);
  14897. if ( this.bOutline ) {
  14898. ctx.strokeStyle= this.outlineColor;
  14899. ctx.strokeRect(0,0,this.width,this.height);
  14900. }
  14901. },
  14902. /**
  14903. * Enables/disables drawing of the contained path's bounding box.
  14904. * @param show {boolean} whether to show the bounding box
  14905. * @param color {=string} optional parameter defining the path's bounding box stroke style.
  14906. */
  14907. showBoundingBox : function(show, color) {
  14908. this.bOutline= show;
  14909. if ( show && color ) {
  14910. this.outlineColor= color;
  14911. }
  14912. },
  14913. /**
  14914. * Set the contained path as interactive. This means it can be changed on the fly by manipulation
  14915. * of its control points.
  14916. * @param interactive
  14917. */
  14918. setInteractive : function(interactive) {
  14919. this.interactive= interactive;
  14920. if ( this.path ) {
  14921. this.path.setInteractive(interactive);
  14922. }
  14923. return this;
  14924. },
  14925. setOnUpdateCallback : function( fn ) {
  14926. this.onUpdateCallback= fn;
  14927. return this;
  14928. },
  14929. /**
  14930. * Route mouse dragging functionality to the contained path.
  14931. * @param mouseEvent {CAAT.MouseEvent}
  14932. */
  14933. mouseDrag : function(mouseEvent) {
  14934. this.path.drag(mouseEvent.point.x, mouseEvent.point.y, this.onUpdateCallback);
  14935. },
  14936. /**
  14937. * Route mouse down functionality to the contained path.
  14938. * @param mouseEvent {CAAT.MouseEvent}
  14939. */
  14940. mouseDown : function(mouseEvent) {
  14941. this.path.press(mouseEvent.point.x, mouseEvent.point.y);
  14942. },
  14943. /**
  14944. * Route mouse up functionality to the contained path.
  14945. * @param mouseEvent {CAAT.MouseEvent}
  14946. */
  14947. mouseUp : function(mouseEvent) {
  14948. this.path.release();
  14949. }
  14950. };
  14951. extend( CAAT.PathActor, CAAT.ActorContainer, null);
  14952. })();/**
  14953. * See LICENSE file.
  14954. *
  14955. * This file contains some image processing effects.
  14956. * Currently contains the following out-of-the-box effects:
  14957. *
  14958. * + IMPlasma: creates a plasma texture. The plasma is generated out of a color ramp (see color.js file)
  14959. * + IMBump: creates a realtime bump-mapping from a given image. It supports multiple light sources
  14960. * as well as different light colors.
  14961. * + IMRotoZoom: produces a roto zoom effect out of a given square sized image. Image must be 2^n in size.
  14962. *
  14963. * This class must be used as fillStyle for an actor or any element that will be painted in a canvas context.
  14964. *
  14965. */
  14966. (function() {
  14967. /**
  14968. * ImageProcessor is a class to encapsulate image processing operations. These image processing
  14969. * manipulates individual image pixels and from an array of pixels builds an image which can
  14970. * be used as a pattern or image.
  14971. * <p>
  14972. * This class pre-creates a canvas of the given dimensions and extracts an imageData object to
  14973. * hold the pixel manipulation.
  14974. *
  14975. * @constructor
  14976. */
  14977. CAAT.ImageProcessor= function() {
  14978. return this;
  14979. };
  14980. CAAT.ImageProcessor.prototype= {
  14981. canvas: null,
  14982. ctx: null,
  14983. width: 0,
  14984. height: 0,
  14985. imageData: null,
  14986. bufferImage:null,
  14987. /**
  14988. * Grabs an image pixels.
  14989. *
  14990. * @param image {HTMLImageElement}
  14991. * @return {ImageData} returns an ImageData object with the image representation or null in
  14992. * case the pixels can not be grabbed.
  14993. *
  14994. * @static
  14995. */
  14996. grabPixels : function(image) {
  14997. var canvas= document.createElement('canvas');
  14998. if ( canvas!==null ) {
  14999. canvas.width= image.width;
  15000. canvas.height= image.height;
  15001. var ctx= canvas.getContext('2d');
  15002. ctx.drawImage(image,0,0);
  15003. try {
  15004. var imageData= ctx.getImageData(0,0,canvas.width,canvas.height);
  15005. return imageData;
  15006. }
  15007. catch(e) {
  15008. CAAT.log('error pixelgrabbing.', image);
  15009. return null;
  15010. }
  15011. }
  15012. return null;
  15013. },
  15014. /**
  15015. * Helper method to create an array.
  15016. *
  15017. * @param size {number} integer number of elements in the array.
  15018. * @param initValue {number} initial array values.
  15019. *
  15020. * @return {[]} an array of 'initialValue' elements.
  15021. *
  15022. * @static
  15023. */
  15024. makeArray : function(size, initValue) {
  15025. var a= [];
  15026. for(var i=0; i<size; i++ ) {
  15027. a.push( initValue );
  15028. }
  15029. return a;
  15030. },
  15031. /**
  15032. * Helper method to create a bidimensional array.
  15033. *
  15034. * @param size {number} number of array rows.
  15035. * @param size2 {number} number of array columns.
  15036. * @param initvalue array initial values.
  15037. *
  15038. * @return {[]} a bidimensional array of 'initvalue' elements.
  15039. *
  15040. * @static
  15041. *
  15042. */
  15043. makeArray2D : function (size, size2, initvalue) {
  15044. var a= [];
  15045. for( var i=0; i<size; i++ ) {
  15046. a.push( this.makeArray(size2,initvalue) );
  15047. }
  15048. return a;
  15049. },
  15050. /**
  15051. * Initializes and creates an offscreen Canvas object. It also creates an ImageData object and
  15052. * initializes the internal bufferImage attribute to imageData's data.
  15053. * @param width {number} canvas width.
  15054. * @param height {number} canvas height.
  15055. * @return this
  15056. */
  15057. initialize : function(width,height) {
  15058. this.width= width;
  15059. this.height= height;
  15060. this.canvas= document.createElement('canvas');
  15061. if ( this.canvas!==null ) {
  15062. this.canvas.width= width;
  15063. this.canvas.height= height;
  15064. this.ctx= this.canvas.getContext('2d');
  15065. this.imageData= this.ctx.getImageData(0,0,width,height);
  15066. this.bufferImage= this.imageData.data;
  15067. }
  15068. return this;
  15069. },
  15070. /**
  15071. * Clear this ImageData object to the given color components.
  15072. * @param r {number} red color component 0..255.
  15073. * @param g {number} green color component 0..255.
  15074. * @param b {number} blue color component 0..255.
  15075. * @param a {number} alpha color component 0..255.
  15076. * @return this
  15077. */
  15078. clear : function( r,g,b,a ) {
  15079. if ( null===this.imageData ) {
  15080. return this;
  15081. }
  15082. var data= this.imageData.data;
  15083. for( var i=0; i<this.width*this.height; i++ ) {
  15084. data[i*4+0]= r;
  15085. data[i*4+1]= g;
  15086. data[i*4+2]= b;
  15087. data[i*4+3]= a;
  15088. }
  15089. this.imageData.data= data;
  15090. return this;
  15091. },
  15092. /**
  15093. * Get this ImageData.
  15094. * @return {ImageData}
  15095. */
  15096. getImageData : function() {
  15097. return this.ctx.getImageData(0,0,this.width,this.height);
  15098. },
  15099. /**
  15100. * Sets canvas pixels to be the applied effect. After process pixels, this method must be called
  15101. * to show the result of such processing.
  15102. * @param director {CAAT.Director}
  15103. * @param time {number}
  15104. * @return this
  15105. */
  15106. apply : function(director, time) {
  15107. if ( null!==this.imageData ) {
  15108. this.imageData.data= this.bufferImage;
  15109. this.ctx.putImageData(this.imageData, 0, 0);
  15110. }
  15111. return this;
  15112. },
  15113. /**
  15114. * Returns the offscreen canvas.
  15115. * @return {HTMLCanvasElement}
  15116. */
  15117. getCanvas : function() {
  15118. return this.canvas;
  15119. },
  15120. /**
  15121. * Creates a pattern that will make this ImageProcessor object suitable as a fillStyle value.
  15122. * This effect can be drawn too as an image by calling: canvas_context.drawImage methods.
  15123. * @param type {string} the pattern type. if no value is supplied 'repeat' will be used.
  15124. * @return CanvasPattern.
  15125. */
  15126. createPattern : function( type ) {
  15127. return this.ctx.createPattern(this.canvas,type ? type : 'repeat');
  15128. },
  15129. /**
  15130. * Paint this ImageProcessor object result.
  15131. * @param director {CAAT.Director}.
  15132. * @param time {number} scene time.
  15133. */
  15134. paint : function( director, time ) {
  15135. if ( null!==this.canvas ) {
  15136. var ctx= director.ctx;
  15137. ctx.drawImage( this.getCanvas(), 0, 0 );
  15138. }
  15139. }
  15140. };
  15141. })();
  15142. (function() {
  15143. /**
  15144. * Creates an additive plasma wave image.
  15145. *
  15146. * @constructor
  15147. * @extends CAAT.ImageProcessor
  15148. *
  15149. */
  15150. CAAT.IMPlasma= function() {
  15151. CAAT.IMPlasma.superclass.constructor.call(this);
  15152. return this;
  15153. };
  15154. CAAT.IMPlasma.prototype= {
  15155. wavetable: null,
  15156. m_colorMap: null,
  15157. spd1: 1,
  15158. spd2: 2,
  15159. spd3: 3,
  15160. spd4: 4,
  15161. pos1: 0,
  15162. pos2: 0,
  15163. pos3: 0,
  15164. pos4: 0,
  15165. tpos1: 0,
  15166. tpos2: 0,
  15167. tpos3: 0,
  15168. tpos4: 0,
  15169. m_colorMapSize: 256,
  15170. i1: 0,
  15171. i2: 0,
  15172. i3: 0,
  15173. i4: 0,
  15174. b1: false,
  15175. b2: false,
  15176. b3: false,
  15177. b4: false,
  15178. color: [0xffffffff, 0xffff00ff, 0xffffff00, 0xff00ff00, 0xffff0000, 0xff0000ff, 0xff000000],
  15179. /**
  15180. * Initialize the plasma image processor.
  15181. * <p>
  15182. * This image processor creates a color ramp of 256 elements from the colors of the parameter 'colors'.
  15183. * Be aware of color definition since the alpha values count to create the ramp.
  15184. *
  15185. * @param width {number}
  15186. * @param height {number}
  15187. * @param colors {Array.<number>} an array of color values.
  15188. *
  15189. * @return this
  15190. */
  15191. initialize : function(width,height,colors) {
  15192. CAAT.IMPlasma.superclass.initialize.call(this,width,height);
  15193. this.wavetable= [];
  15194. for (var x=0; x<256; x++) {
  15195. this.wavetable.push( Math.floor(32 * (1 + Math.cos(x*2 * Math.PI / 256))) );
  15196. }
  15197. this.pos1=Math.floor(255*Math.random());
  15198. this.pos2=Math.floor(255*Math.random());
  15199. this.pos3=Math.floor(255*Math.random());
  15200. this.pos4=Math.floor(255*Math.random());
  15201. this.m_colorMap= CAAT.Color.prototype.makeRGBColorRamp(
  15202. colors!==null ? colors : this.color,
  15203. 256,
  15204. CAAT.Color.prototype.RampEnumeration.RAMP_CHANNEL_RGBA_ARRAY );
  15205. this.setB();
  15206. return this;
  15207. },
  15208. /**
  15209. * Initialize internal plasma structures. Calling repeatedly this method will make the plasma
  15210. * look different.
  15211. */
  15212. setB : function() {
  15213. this.b1= Math.random()>0.5;
  15214. this.b2= Math.random()>0.5;
  15215. this.b3= Math.random()>0.5;
  15216. this.b4= Math.random()>0.5;
  15217. this.spd1= Math.floor((Math.random()*3+1)*(Math.random()<0.5?1:-1));
  15218. this.spd2= Math.floor((Math.random()*3+1)*(Math.random()<0.5?1:-1));
  15219. this.spd3= Math.floor((Math.random()*3+1)*(Math.random()<0.5?1:-1));
  15220. this.spd4= Math.floor((Math.random()*3+1)*(Math.random()<0.5?1:-1));
  15221. this.i1= Math.floor((Math.random()*2.4+1)*(Math.random()<0.5?1:-1));
  15222. this.i2= Math.floor((Math.random()*2.4+1)*(Math.random()<0.5?1:-1));
  15223. this.i3= Math.floor((Math.random()*2.4+1)*(Math.random()<0.5?1:-1));
  15224. this.i4= Math.floor((Math.random()*2.4+1)*(Math.random()<0.5?1:-1));
  15225. },
  15226. /**
  15227. * Apply image processing to create the plasma and call superclass's apply to make the result
  15228. * visible.
  15229. * @param director {CAAT.Director}
  15230. * @param time {number}
  15231. *
  15232. * @return this
  15233. */
  15234. apply : function(director,time) {
  15235. var v = 0;
  15236. this.tpos1 = this.pos1;
  15237. this.tpos2 = this.pos2;
  15238. var bi= this.bufferImage;
  15239. var cm= this.m_colorMap;
  15240. var wt= this.wavetable;
  15241. var z;
  15242. var cmz;
  15243. for (var x=0; x<this.height; x++) {
  15244. this.tpos3 = this.pos3;
  15245. this.tpos4 = this.pos4;
  15246. for(var y=0; y<this.width; y++) {
  15247. // mix at will, or at your own risk.
  15248. var o1= this.tpos1+this.tpos2+this.tpos3;
  15249. var o2= this.tpos2+this.tpos3-this.tpos1;
  15250. var o3= this.tpos3+this.tpos4-this.tpos2;
  15251. var o4= this.tpos4+this.tpos1-this.tpos2;
  15252. // set different directions. again, change at will.
  15253. if ( this.b1 ) o1= -o1;
  15254. if ( this.b2 ) o2= -o2;
  15255. if ( this.b3 ) o3= -o3;
  15256. if ( this.b4 ) o4= -o4;
  15257. z = Math.floor( wt[o1&255] + wt[o2&255] + wt[o3&255] + wt[o4&255] );
  15258. cmz= cm[z];
  15259. bi[ v++ ]= cmz[0];
  15260. bi[ v++ ]= cmz[1];
  15261. bi[ v++ ]= cmz[2];
  15262. bi[ v++ ]= cmz[3];
  15263. this.tpos3 += this.i1;
  15264. this.tpos3&=255;
  15265. this.tpos4 += this.i2;
  15266. this.tpos4&=255;
  15267. }
  15268. this.tpos1 += this.i3;
  15269. this.tpos1&=255;
  15270. this.tpos2 += this.i4;
  15271. this.tpos2&=255;
  15272. }
  15273. this.pos1 += this.spd1;
  15274. this.pos2 -= this.spd2;
  15275. this.pos3 += this.spd3;
  15276. this.pos4 -= this.spd4;
  15277. this.pos1&=255;
  15278. this.pos3&=255;
  15279. this.pos2&=255;
  15280. this.pos4&=255;
  15281. return CAAT.IMPlasma.superclass.apply.call(this,director,time);
  15282. }
  15283. };
  15284. extend( CAAT.IMPlasma, CAAT.ImageProcessor, null);
  15285. })();
  15286. (function() {
  15287. /**
  15288. * This class creates a bumpy effect from a given image. The effect can be applied by different lights
  15289. * each of which can bump the image with a different color. The lights will have an additive color
  15290. * effect on affected pixels.
  15291. *
  15292. * @constructor
  15293. * @extends CAAT.ImageProcessor
  15294. */
  15295. CAAT.IMBump=function() {
  15296. CAAT.IMBump.superclass.constructor.call(this);
  15297. return this;
  15298. };
  15299. CAAT.IMBump.prototype= {
  15300. // bump
  15301. m_avgX: null,
  15302. m_avgY: null,
  15303. m_tt: null,
  15304. phong: null,
  15305. m_radius: 75,
  15306. m_lightcolor: null,
  15307. bcolor: false,
  15308. lightPosition: [],
  15309. /**
  15310. * Initializes internal bump effect data.
  15311. *
  15312. * @param image {HTMLImageElement}
  15313. * @param radius {number} lights radius.
  15314. *
  15315. * @private
  15316. */
  15317. prepareBump : function(image, radius) {
  15318. var i,j;
  15319. this.m_radius= (radius ? radius : 75);
  15320. var imageData= this.grabPixels(image);
  15321. this.m_tt= this.makeArray(this.height,0);
  15322. for( i=0; i<this.height; i++ ){
  15323. this.m_tt[ i ]=this.width*i;
  15324. }
  15325. this.m_avgX= this.makeArray2D(this.height,this.width,0);
  15326. this.m_avgY= this.makeArray2D(this.height,this.width,0);
  15327. var bump=this.makeArray2D(this.height,this.width,0);
  15328. if ( null===imageData ) {
  15329. return;
  15330. }
  15331. var sourceImagePixels= imageData.data;
  15332. for (i=0;i<this.height;i++) {
  15333. for (j=0;j<this.width;j++) {
  15334. var pos= (i*this.width+j)*4;
  15335. bump[i][j]=
  15336. sourceImagePixels[pos ]+
  15337. sourceImagePixels[pos+1]+
  15338. sourceImagePixels[pos+2];
  15339. }
  15340. }
  15341. bump= this.soften( bump );
  15342. for (var x=1;x<this.width-1;x++) {
  15343. for (var y=1;y<this.height-1;y++) {
  15344. this.m_avgX[y][x]=Math.floor(bump[y][x+1]-bump[y][x-1]);
  15345. this.m_avgY[y][x]=Math.floor(bump[y+1][x]-bump[y-1][x]);
  15346. }
  15347. }
  15348. bump=null;
  15349. },
  15350. /**
  15351. * Soften source images extracted data on prepareBump method.
  15352. * @param bump bidimensional array of black and white source image version.
  15353. * @return bidimensional array with softened version of source image's b&w representation.
  15354. */
  15355. soften : function( bump ) {
  15356. var temp;
  15357. var sbump=this.makeArray2D( this.height,this.width, 0);
  15358. for (var j=0;j<this.width;j++) {
  15359. for (var i=0;i<this.height;i++) {
  15360. temp=(bump[i][j]);
  15361. temp+=(bump[(i+1)%this.height][j]);
  15362. temp+=(bump[(i+this.height-1)%this.height][j]);
  15363. temp+=(bump[i][(j+1)%this.width]);
  15364. temp+=(bump[i][(j+this.width-1)%this.width]);
  15365. temp+=(bump[(i+1)%this.height][(j+1)%this.width]);
  15366. temp+=(bump[(i+this.height-1)%this.height][(j+this.width-1)%this.width]);
  15367. temp+=(bump[(i+this.height-1)%this.height][(j+1)%this.width]);
  15368. temp+=(bump[(i+1)%this.height][(j+this.width-1)%this.width]);
  15369. temp/=9;
  15370. sbump[i][j]=temp/3;
  15371. }
  15372. }
  15373. return sbump;
  15374. },
  15375. /**
  15376. * Create a phong image to apply bump effect.
  15377. * @private
  15378. */
  15379. calculatePhong : function( ) {
  15380. this.phong= this.makeArray2D(this.m_radius,this.m_radius,0);
  15381. var i,j,z;
  15382. for( i=0; i<this.m_radius; i++ ) {
  15383. for( j=0; j<this.m_radius; j++ ) {
  15384. var x= j/this.m_radius;
  15385. var y= i/this.m_radius;
  15386. z= (1-Math.sqrt(x*x+y*y))*0.8;
  15387. if ( z<0 ) {
  15388. z=0;
  15389. }
  15390. this.phong[ i ][ j ]= Math.floor(z*255);
  15391. }
  15392. }
  15393. },
  15394. /**
  15395. * Generates a bump image.
  15396. * @param dstPixels {ImageData.data} destinarion pixel array to store the calculated image.
  15397. */
  15398. drawColored : function(dstPixels) {
  15399. var i,j,k;
  15400. for( i=0; i<this.height; i++ ) {
  15401. for( j=0; j<this.width; j++ ){
  15402. var rrr=0;
  15403. var ggg=0;
  15404. var bbb=0;
  15405. for( k=0; k<this.m_lightcolor.length; k++ ) {
  15406. var lx= this.lightPosition[k].x;
  15407. var ly= this.lightPosition[k].y;
  15408. var dx=Math.floor(Math.abs(this.m_avgX[i][j]-j+lx));
  15409. var dy=Math.floor(Math.abs(this.m_avgY[i][j]-i+ly));
  15410. if (dx>=this.m_radius) {
  15411. dx=this.m_radius-1;
  15412. }
  15413. if (dy>=this.m_radius) {
  15414. dy=this.m_radius-1;
  15415. }
  15416. var c= this.phong[ dx ] [ dy ];
  15417. var r=0;
  15418. var g=0;
  15419. var b=0;
  15420. if ( c>=0 ) {// oscurecer
  15421. r= (this.m_lightcolor[k][0]*c/128);
  15422. g= (this.m_lightcolor[k][1]*c/128);
  15423. b= (this.m_lightcolor[k][2]*c/128);
  15424. }
  15425. else { // blanquear.
  15426. c=128+c;
  15427. var rr= (this.m_lightcolor[k][0]);
  15428. var gg= (this.m_lightcolor[k][1]);
  15429. var bb= (this.m_lightcolor[k][2]);
  15430. r= Math.floor(rr+ (255-rr)*c/128);
  15431. g= Math.floor(gg+ (255-gg)*c/128);
  15432. b= Math.floor(bb+ (255-bb)*c/128);
  15433. }
  15434. rrr+=r;
  15435. ggg+=g;
  15436. bbb+=b;
  15437. }
  15438. if ( rrr>255 ) {
  15439. rrr=255;
  15440. }
  15441. if ( ggg>255 ) {
  15442. ggg=255;
  15443. }
  15444. if ( bbb>255 ) {
  15445. bbb=255;
  15446. }
  15447. var pos= (j+this.m_tt[i])*4;
  15448. dstPixels[pos ]= rrr;
  15449. dstPixels[pos+1]= ggg;
  15450. dstPixels[pos+2]= bbb;
  15451. dstPixels[pos+3]= 255;
  15452. }
  15453. }
  15454. },
  15455. /**
  15456. * Sets lights color.
  15457. * @param colors_rgb_array an array of arrays. Each internal array has three integers defining an RGB color.
  15458. * ie:
  15459. * [
  15460. * [ 255,0,0 ],
  15461. * [ 0,255,0 ]
  15462. * ]
  15463. * @return this
  15464. */
  15465. setLightColors : function( colors_rgb_array ) {
  15466. this.m_lightcolor= colors_rgb_array;
  15467. this.lightPosition= [];
  15468. for( var i=0; i<this.m_lightcolor.length; i++ ) {
  15469. var x= this.width*Math.random();
  15470. var y= this.height*Math.random();
  15471. this.lightPosition.push( new CAAT.Point().set(x,y) );
  15472. }
  15473. return this;
  15474. },
  15475. /**
  15476. * Initialize the bump image processor.
  15477. * @param image {HTMLImageElement} source image to bump.
  15478. * @param radius {number} light radius.
  15479. */
  15480. initialize : function(image,radius) {
  15481. CAAT.IMBump.superclass.initialize.call(this,image.width,image.height);
  15482. this.setLightColors(
  15483. [
  15484. [255,128,0],
  15485. [0,0,255]
  15486. ]);
  15487. this.prepareBump(image,radius);
  15488. this.calculatePhong();
  15489. return this;
  15490. },
  15491. /**
  15492. * Set a light position.
  15493. * @param lightIndex {number} light index to position.
  15494. * @param x {number} light x coordinate.
  15495. * @param y {number} light y coordinate.
  15496. * @return this
  15497. */
  15498. setLightPosition : function( lightIndex, x, y ) {
  15499. this.lightPosition[lightIndex].set(x,y);
  15500. return this;
  15501. },
  15502. /**
  15503. * Applies the bump effect and makes it visible on the canvas surface.
  15504. * @param director {CAAT.Director}
  15505. * @param time {number}
  15506. */
  15507. apply : function(director,time) {
  15508. this.drawColored(this.bufferImage);
  15509. return CAAT.IMBump.superclass.apply.call(this,director,time);
  15510. }
  15511. };
  15512. extend( CAAT.IMBump, CAAT.ImageProcessor, null);
  15513. })();
  15514. (function() {
  15515. /**
  15516. * This class creates an image processing Rotozoom effect.
  15517. *
  15518. * @constructor
  15519. * @extends CAAT.ImageProcessor
  15520. */
  15521. CAAT.IMRotoZoom= function() {
  15522. CAAT.IMRotoZoom.superclass.constructor.call(this);
  15523. return this;
  15524. };
  15525. CAAT.IMRotoZoom.prototype= {
  15526. m_alignv: 1,
  15527. m_alignh: 1,
  15528. distortion: 2,
  15529. mask: 0,
  15530. shift: 0,
  15531. sourceImageData:null, // pattern to fill area with.
  15532. /**
  15533. * Initialize the rotozoom.
  15534. * @param width {number}
  15535. * @param height {number}
  15536. * @param patternImage {HTMLImageElement} image to tile with.
  15537. *
  15538. * @return this
  15539. */
  15540. initialize : function( width, height, patternImage ) {
  15541. CAAT.IMRotoZoom.superclass.initialize.call(this,width,height);
  15542. this.clear( 255,128,0, 255 );
  15543. this.sourceImageData= this.grabPixels(patternImage);
  15544. if ( null!==this.sourceImageData ) {
  15545. // patternImage must be 2^n sized.
  15546. switch( this.sourceImageData.width ) {
  15547. case 1024:
  15548. this.mask=1023;
  15549. this.shift=10;
  15550. break;
  15551. case 512:
  15552. this.mask=511;
  15553. this.shift=9;
  15554. break;
  15555. case 256:
  15556. this.mask=255;
  15557. this.shift=8;
  15558. break;
  15559. case 128:
  15560. this.mask=127;
  15561. this.shift=7;
  15562. break;
  15563. case 64:
  15564. this.mask=63;
  15565. this.shift=6;
  15566. break;
  15567. case 32:
  15568. this.mask=31;
  15569. this.shift=5;
  15570. break;
  15571. case 16:
  15572. this.mask=15;
  15573. this.shift=4;
  15574. break;
  15575. case 8:
  15576. this.mask=7;
  15577. this.shift=3;
  15578. break;
  15579. }
  15580. }
  15581. this.setCenter();
  15582. return this;
  15583. },
  15584. /**
  15585. * Performs the process of tiling rotozoom.
  15586. * @param director {CAAT.Director}
  15587. * @param time {number}
  15588. *
  15589. * @private
  15590. */
  15591. rotoZoom: function(director,time) {
  15592. var timer = new Date().getTime();
  15593. var angle=Math.PI*2 * Math.cos(timer * 0.0001);
  15594. var distance= 600+ 550*Math.sin(timer*0.0002);
  15595. var dist= this.distortion;
  15596. var off=0;
  15597. var ddx=Math.floor(Math.cos(angle)*distance);
  15598. var ddy=Math.floor(Math.sin(angle)*distance);
  15599. var hh=0, ww=0;
  15600. switch( this.m_alignh ) {
  15601. case 0:
  15602. hh = 0;
  15603. break;
  15604. case 1:
  15605. hh = (this.height >> 1);
  15606. break;
  15607. case 2:
  15608. hh = this.height - 1;
  15609. break;
  15610. }
  15611. switch (this.m_alignv) {
  15612. case 0:
  15613. ww = 0;
  15614. break;
  15615. case 1:
  15616. ww = (this.width >> 1);
  15617. break;
  15618. case 2:
  15619. ww = this.width - 1;
  15620. break;
  15621. }
  15622. var i = (((this.width >> 1) << 8) - ddx * ww + ddy * hh)&0xffff;
  15623. var j = (((this.height >> 1) << 8) - ddy * ww - ddx * hh) & 0xffff;
  15624. var srcwidth= this.sourceImageData.width;
  15625. var srcheight= this.sourceImageData.height;
  15626. var srcdata= this.sourceImageData.data;
  15627. var bi= this.bufferImage;
  15628. var dstoff;
  15629. var addx;
  15630. var addy;
  15631. while (off < this.width * this.height * 4) {
  15632. addx = i;
  15633. addy = j;
  15634. for (var m = 0; m < this.width; m++) {
  15635. dstoff = ((addy >> this.shift) & this.mask) * srcwidth + ((addx >> this.shift) & this.mask);
  15636. dstoff <<= 2;
  15637. bi[ off++ ] = srcdata[ dstoff++ ];
  15638. bi[ off++ ] = srcdata[ dstoff++ ];
  15639. bi[ off++ ] = srcdata[ dstoff++ ];
  15640. bi[ off++ ] = srcdata[ dstoff++ ];
  15641. addx += ddx;
  15642. addy += ddy;
  15643. }
  15644. dist += this.distortion;
  15645. i -= ddy;
  15646. j += ddx - dist;
  15647. }
  15648. },
  15649. /**
  15650. * Perform and apply the rotozoom effect.
  15651. * @param director {CAAT.Director}
  15652. * @param time {number}
  15653. * @return this
  15654. */
  15655. apply : function(director,time) {
  15656. if ( null!==this.sourceImageData ) {
  15657. this.rotoZoom(director,time);
  15658. }
  15659. return CAAT.IMRotoZoom.superclass.apply.call(this,director,time);
  15660. },
  15661. /**
  15662. * Change the effect's rotation anchor. Call this method repeatedly to make the effect look
  15663. * different.
  15664. */
  15665. setCenter: function() {
  15666. var d = Math.random();
  15667. if (d < 0.33) {
  15668. this.m_alignv = 0;
  15669. } else if (d < 0.66) {
  15670. this.m_alignv = 1;
  15671. } else {
  15672. this.m_alignv = 2;
  15673. }
  15674. d = Math.random();
  15675. if (d < 0.33) {
  15676. this.m_alignh = 0;
  15677. } else if (d < 0.66) {
  15678. this.m_alignh = 1;
  15679. } else {
  15680. this.m_alignh = 2;
  15681. }
  15682. }
  15683. };
  15684. extend( CAAT.IMRotoZoom, CAAT.ImageProcessor, null);
  15685. })();/**
  15686. * See LICENSE file.
  15687. */
  15688. (function() {
  15689. CAAT.Program= function(gl) {
  15690. this.gl= gl;
  15691. return this;
  15692. };
  15693. CAAT.Program.prototype= {
  15694. shaderProgram: null,
  15695. gl: null,
  15696. /**
  15697. * Set fragment shader's alpha composite value.
  15698. * @param alpha {number} float value 0..1.
  15699. */
  15700. setAlpha : function( alpha ) {
  15701. },
  15702. getShader : function (gl,type,str) {
  15703. var shader;
  15704. if (type === "x-shader/x-fragment") {
  15705. shader = gl.createShader(gl.FRAGMENT_SHADER);
  15706. } else if (type === "x-shader/x-vertex") {
  15707. shader = gl.createShader(gl.VERTEX_SHADER);
  15708. } else {
  15709. return null;
  15710. }
  15711. gl.shaderSource(shader, str);
  15712. gl.compileShader(shader);
  15713. if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
  15714. alert(gl.getShaderInfoLog(shader));
  15715. return null;
  15716. }
  15717. return shader;
  15718. },
  15719. getDomShader : function(gl, id) {
  15720. var shaderScript = document.getElementById(id);
  15721. if (!shaderScript) {
  15722. return null;
  15723. }
  15724. var str = "";
  15725. var k = shaderScript.firstChild;
  15726. while (k) {
  15727. if (k.nodeType === 3) {
  15728. str += k.textContent;
  15729. }
  15730. k = k.nextSibling;
  15731. }
  15732. var shader;
  15733. if (shaderScript.type === "x-shader/x-fragment") {
  15734. shader = gl.createShader(gl.FRAGMENT_SHADER);
  15735. } else if (shaderScript.type === "x-shader/x-vertex") {
  15736. shader = gl.createShader(gl.VERTEX_SHADER);
  15737. } else {
  15738. return null;
  15739. }
  15740. gl.shaderSource(shader, str);
  15741. gl.compileShader(shader);
  15742. if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
  15743. alert(gl.getShaderInfoLog(shader));
  15744. return null;
  15745. }
  15746. return shader;
  15747. },
  15748. initialize : function() {
  15749. return this;
  15750. },
  15751. getFragmentShader : function() {
  15752. return null;
  15753. },
  15754. getVertexShader : function() {
  15755. return null;
  15756. },
  15757. create : function() {
  15758. var gl= this.gl;
  15759. this.shaderProgram = gl.createProgram();
  15760. gl.attachShader(this.shaderProgram, this.getVertexShader());
  15761. gl.attachShader(this.shaderProgram, this.getFragmentShader());
  15762. gl.linkProgram(this.shaderProgram);
  15763. gl.useProgram(this.shaderProgram);
  15764. return this;
  15765. },
  15766. setMatrixUniform : function( caatMatrix4 ) {
  15767. this.gl.uniformMatrix4fv(
  15768. this.shaderProgram.pMatrixUniform,
  15769. false,
  15770. new Float32Array(caatMatrix4.flatten()));
  15771. },
  15772. useProgram : function() {
  15773. this.gl.useProgram(this.shaderProgram);
  15774. return this;
  15775. }
  15776. };
  15777. })();
  15778. (function() {
  15779. CAAT.ColorProgram= function(gl) {
  15780. CAAT.ColorProgram.superclass.constructor.call(this,gl);
  15781. return this;
  15782. };
  15783. CAAT.ColorProgram.prototype= {
  15784. colorBuffer: null,
  15785. vertexPositionBuffer: null,
  15786. vertexPositionArray: null,
  15787. getFragmentShader : function() {
  15788. return this.getShader(this.gl, "x-shader/x-fragment",
  15789. "#ifdef GL_ES \n"+
  15790. "precision highp float; \n"+
  15791. "#endif \n"+
  15792. "varying vec4 color; \n"+
  15793. "void main(void) { \n"+
  15794. " gl_FragColor = color;\n"+
  15795. "}\n"
  15796. );
  15797. },
  15798. getVertexShader : function() {
  15799. return this.getShader(this.gl, "x-shader/x-vertex",
  15800. "attribute vec3 aVertexPosition; \n"+
  15801. "attribute vec4 aColor; \n"+
  15802. "uniform mat4 uPMatrix; \n"+
  15803. "varying vec4 color; \n"+
  15804. "void main(void) { \n"+
  15805. "gl_Position = uPMatrix * vec4(aVertexPosition, 1.0); \n"+
  15806. "color= aColor; \n"+
  15807. "}\n"
  15808. );
  15809. },
  15810. initialize : function() {
  15811. this.shaderProgram.vertexPositionAttribute =
  15812. this.gl.getAttribLocation(this.shaderProgram, "aVertexPosition");
  15813. this.gl.enableVertexAttribArray(
  15814. this.shaderProgram.vertexPositionAttribute);
  15815. this.shaderProgram.vertexColorAttribute =
  15816. this.gl.getAttribLocation(this.shaderProgram, "aColor");
  15817. this.gl.enableVertexAttribArray(
  15818. this.shaderProgram.vertexColorAttribute);
  15819. this.shaderProgram.pMatrixUniform =
  15820. this.gl.getUniformLocation(this.shaderProgram, "uPMatrix");
  15821. this.useProgram();
  15822. this.colorBuffer= this.gl.createBuffer();
  15823. this.setColor( [1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1] );
  15824. var maxTris=512, i;
  15825. /// set vertex data
  15826. this.vertexPositionBuffer = this.gl.createBuffer();
  15827. this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexPositionBuffer );
  15828. this.vertexPositionArray= new Float32Array(maxTris*12);
  15829. this.gl.bufferData(this.gl.ARRAY_BUFFER, this.vertexPositionArray, this.gl.DYNAMIC_DRAW);
  15830. this.gl.vertexAttribPointer(this.shaderProgram.vertexPositionAttribute, 3, this.gl.FLOAT, false, 0, 0);
  15831. return CAAT.ColorProgram.superclass.initialize.call(this);
  15832. },
  15833. setColor : function( colorArray ) {
  15834. this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.colorBuffer );
  15835. this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(colorArray), this.gl.STATIC_DRAW);
  15836. this.gl.vertexAttribPointer(
  15837. this.shaderProgram.vertexColorAttribute,
  15838. this.colorBuffer,
  15839. this.gl.FLOAT,
  15840. false,
  15841. 0,
  15842. 0);
  15843. }
  15844. };
  15845. extend(CAAT.ColorProgram, CAAT.Program, null );
  15846. })();
  15847. (function() {
  15848. CAAT.TextureProgram= function(gl) {
  15849. CAAT.TextureProgram.superclass.constructor.call(this,gl);
  15850. return this;
  15851. };
  15852. CAAT.TextureProgram.prototype= {
  15853. vertexPositionBuffer: null,
  15854. vertexPositionArray: null,
  15855. vertexUVBuffer: null,
  15856. vertexUVArray: null,
  15857. vertexIndexBuffer: null,
  15858. linesBuffer: null,
  15859. prevAlpha: -1,
  15860. prevR: -1,
  15861. prevG: -1,
  15862. prevB: -1,
  15863. prevA: -1,
  15864. prevTexture: null,
  15865. getFragmentShader : function() {
  15866. return this.getShader( this.gl, "x-shader/x-fragment",
  15867. "#ifdef GL_ES \n"+
  15868. "precision highp float; \n"+
  15869. "#endif \n"+
  15870. "varying vec2 vTextureCoord; \n"+
  15871. "uniform sampler2D uSampler; \n"+
  15872. "uniform float alpha; \n"+
  15873. "uniform bool uUseColor;\n"+
  15874. "uniform vec4 uColor;\n"+
  15875. "void main(void) { \n"+
  15876. "if ( uUseColor ) {\n"+
  15877. " gl_FragColor= vec4(uColor.r*alpha, uColor.g*alpha, uColor.b*alpha, uColor.a*alpha);\n"+
  15878. "} else { \n"+
  15879. " vec4 textureColor= texture2D(uSampler, vec2(vTextureCoord)); \n"+
  15880. // Fix FF " gl_FragColor = vec4(textureColor.rgb, textureColor.a * alpha); \n"+
  15881. " gl_FragColor = vec4(textureColor.r*alpha, textureColor.g*alpha, textureColor.b*alpha, textureColor.a * alpha ); \n"+
  15882. "}\n"+
  15883. "}\n"
  15884. );
  15885. },
  15886. getVertexShader : function() {
  15887. return this.getShader(this.gl, "x-shader/x-vertex",
  15888. "attribute vec3 aVertexPosition; \n"+
  15889. "attribute vec2 aTextureCoord; \n"+
  15890. "uniform mat4 uPMatrix; \n"+
  15891. "varying vec2 vTextureCoord; \n"+
  15892. "void main(void) { \n"+
  15893. "gl_Position = uPMatrix * vec4(aVertexPosition, 1.0); \n"+
  15894. "vTextureCoord = aTextureCoord;\n"+
  15895. "}\n"
  15896. );
  15897. },
  15898. useProgram : function() {
  15899. CAAT.TextureProgram.superclass.useProgram.call(this);
  15900. this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexPositionBuffer );
  15901. this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexUVBuffer);
  15902. this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
  15903. },
  15904. initialize : function() {
  15905. var i;
  15906. this.linesBuffer= this.gl.createBuffer();
  15907. this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.linesBuffer );
  15908. var arr= [];
  15909. for( i=0; i<1024; i++ ) {
  15910. arr[i]= i;
  15911. }
  15912. this.linesBufferArray= new Uint16Array(arr);
  15913. this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, this.linesBufferArray, this.gl.DYNAMIC_DRAW);
  15914. this.shaderProgram.vertexPositionAttribute =
  15915. this.gl.getAttribLocation(this.shaderProgram, "aVertexPosition");
  15916. this.gl.enableVertexAttribArray(
  15917. this.shaderProgram.vertexPositionAttribute);
  15918. this.shaderProgram.textureCoordAttribute =
  15919. this.gl.getAttribLocation(this.shaderProgram, "aTextureCoord");
  15920. this.gl.enableVertexAttribArray(
  15921. this.shaderProgram.textureCoordAttribute);
  15922. this.shaderProgram.pMatrixUniform =
  15923. this.gl.getUniformLocation(this.shaderProgram, "uPMatrix");
  15924. this.shaderProgram.samplerUniform =
  15925. this.gl.getUniformLocation(this.shaderProgram, "uSampler");
  15926. this.shaderProgram.alphaUniform =
  15927. this.gl.getUniformLocation(this.shaderProgram, "alpha");
  15928. this.shaderProgram.useColor =
  15929. this.gl.getUniformLocation(this.shaderProgram, "uUseColor");
  15930. this.shaderProgram.color =
  15931. this.gl.getUniformLocation(this.shaderProgram, "uColor");
  15932. this.setAlpha(1);
  15933. this.setUseColor(false);
  15934. var maxTris=4096;
  15935. /// set vertex data
  15936. this.vertexPositionBuffer = this.gl.createBuffer();
  15937. this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexPositionBuffer );
  15938. this.vertexPositionArray= new Float32Array(maxTris*12);
  15939. this.gl.bufferData(this.gl.ARRAY_BUFFER, this.vertexPositionArray, this.gl.DYNAMIC_DRAW);
  15940. this.gl.vertexAttribPointer(this.shaderProgram.vertexPositionAttribute, 3, this.gl.FLOAT, false, 0, 0);
  15941. // uv info
  15942. this.vertexUVBuffer= this.gl.createBuffer();
  15943. this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexUVBuffer);
  15944. this.vertexUVArray= new Float32Array(maxTris*8);
  15945. this.gl.bufferData(this.gl.ARRAY_BUFFER, this.vertexUVArray, this.gl.DYNAMIC_DRAW);
  15946. this.gl.vertexAttribPointer(this.shaderProgram.textureCoordAttribute, 2, this.gl.FLOAT, false, 0, 0);
  15947. // vertex index
  15948. this.vertexIndexBuffer = this.gl.createBuffer();
  15949. this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
  15950. var vertexIndex = [];
  15951. for( i=0; i<maxTris; i++ ) {
  15952. vertexIndex.push(0 + i*4); vertexIndex.push(1 + i*4); vertexIndex.push(2 + i*4);
  15953. vertexIndex.push(0 + i*4); vertexIndex.push(2 + i*4); vertexIndex.push(3 + i*4);
  15954. }
  15955. this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(vertexIndex), this.gl.DYNAMIC_DRAW);
  15956. return CAAT.TextureProgram.superclass.initialize.call(this);
  15957. },
  15958. setUseColor : function( use,r,g,b,a ) {
  15959. this.gl.uniform1i(this.shaderProgram.useColor, use?1:0);
  15960. if ( use ) {
  15961. if ( this.prevA!==a || this.prevR!==r || this.prevG!==g || this.prevB!==b ) {
  15962. this.gl.uniform4f(this.shaderProgram.color, r,g,b,a );
  15963. this.prevA= a;
  15964. this.prevR= r;
  15965. this.prevG= g;
  15966. this.prevB= b;
  15967. }
  15968. }
  15969. },
  15970. setTexture : function( glTexture ) {
  15971. if ( this.prevTexture!==glTexture ) {
  15972. var gl= this.gl;
  15973. gl.activeTexture(gl.TEXTURE0);
  15974. gl.bindTexture(gl.TEXTURE_2D, glTexture);
  15975. gl.uniform1i(this.shaderProgram.samplerUniform, 0);
  15976. this.prevTexture= glTexture;
  15977. }
  15978. return this;
  15979. },
  15980. updateVertexBuffer : function(vertexArray) {
  15981. var gl= this.gl;
  15982. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexPositionBuffer );
  15983. gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertexArray);
  15984. return this;
  15985. },
  15986. updateUVBuffer : function(uvArray) {
  15987. var gl= this.gl;
  15988. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexUVBuffer );
  15989. gl.bufferSubData(gl.ARRAY_BUFFER, 0, uvArray);
  15990. return this;
  15991. },
  15992. setAlpha : function(alpha) {
  15993. if ( this.prevAlpha !== alpha ) {
  15994. this.gl.uniform1f(
  15995. this.shaderProgram.alphaUniform, alpha);
  15996. this.prevAlpha= alpha;
  15997. }
  15998. return this;
  15999. },
  16000. /**
  16001. *
  16002. * @param lines_data {Float32Array} array of number with x,y,z coords for each line point.
  16003. * @param size {number} number of lines to draw.
  16004. * @param r
  16005. * @param g
  16006. * @param b
  16007. * @param a
  16008. * @param lineWidth {number} drawing line size.
  16009. */
  16010. drawLines : function( lines_data, size, r,g,b,a, lineWidth ) {
  16011. var gl= this.gl;
  16012. this.setAlpha( a );
  16013. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.linesBuffer );
  16014. gl.lineWidth(lineWidth);
  16015. this.updateVertexBuffer(lines_data);
  16016. this.setUseColor(true, r,g,b,1 );
  16017. gl.drawElements(gl.LINES, size, gl.UNSIGNED_SHORT, 0);
  16018. /// restore
  16019. this.setAlpha( 1 );
  16020. this.setUseColor(false);
  16021. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
  16022. },
  16023. /**
  16024. *
  16025. * @param polyline_data
  16026. * @param size
  16027. * @param r
  16028. * @param g
  16029. * @param b
  16030. * @param a
  16031. * @param lineWidth
  16032. */
  16033. drawPolylines : function( polyline_data, size, r,g,b,a, lineWidth ) {
  16034. var gl= this.gl;
  16035. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.linesBuffer );
  16036. gl.lineWidth(lineWidth);
  16037. this.setAlpha(a);
  16038. this.updateVertexBuffer(polyline_data);
  16039. this.setUseColor(true, r,g,b,1 );
  16040. gl.drawElements(gl.LINE_STRIP, size, gl.UNSIGNED_SHORT, 0);
  16041. /// restore
  16042. this.setAlpha( 1 );
  16043. this.setUseColor(false);
  16044. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
  16045. }
  16046. };
  16047. extend( CAAT.TextureProgram, CAAT.Program, null );
  16048. })();/**
  16049. * See LICENSE file.
  16050. *
  16051. */
  16052. //
  16053. // gluPerspective
  16054. //
  16055. function makePerspective(fovy, aspect, znear, zfar, viewportHeight) {
  16056. var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
  16057. var ymin = -ymax;
  16058. var xmin = ymin * aspect;
  16059. var xmax = ymax * aspect;
  16060. return makeFrustum(xmin, xmax, ymin, ymax, znear, zfar, viewportHeight);
  16061. }
  16062. //
  16063. // glFrustum
  16064. //
  16065. function makeFrustum(left, right, bottom, top, znear, zfar, viewportHeight) {
  16066. var X = 2*znear/(right-left);
  16067. var Y = 2*znear/(top-bottom);
  16068. var A = (right+left)/(right-left);
  16069. var B = (top+bottom)/(top-bottom);
  16070. var C = -(zfar+znear)/(zfar-znear);
  16071. var D = -2*zfar*znear/(zfar-znear);
  16072. return new CAAT.Matrix3().initWithMatrix(
  16073. [
  16074. [X, 0, A, -viewportHeight/2 ],
  16075. [0, -Y, B, viewportHeight/2 ],
  16076. [0, 0, C, D ],
  16077. [0, 0, -1, 0 ]
  16078. ]);
  16079. }
  16080. function makeOrtho(left, right, bottom, top, znear, zfar) {
  16081. var tx = - (right + left) / (right - left) ;
  16082. var ty = - (top + bottom) / (top - bottom) ;
  16083. var tz = - (zfar + znear) / (zfar - znear);
  16084. return new CAAT.Matrix3().initWithMatrix(
  16085. [
  16086. [2 / (right - left), 0, 0, tx ],
  16087. [0, 2 / (top - bottom), 0, ty ],
  16088. [0, 0, -2 / (zfar- znear), tz ],
  16089. [0, 0, 0, 1 ]
  16090. ]);
  16091. }
  16092. /**
  16093. * See LICENSE file.
  16094. */
  16095. (function() {
  16096. CAAT.GLTextureElement = function() {
  16097. return this;
  16098. };
  16099. CAAT.GLTextureElement.prototype= {
  16100. inverted: false,
  16101. image: null,
  16102. u: 0,
  16103. v: 0,
  16104. glTexture: null
  16105. };
  16106. })();
  16107. (function() {
  16108. CAAT.GLTextureScan= function(w) {
  16109. this.freeChunks=[ {position:0, size:w||1024} ];
  16110. return this;
  16111. };
  16112. CAAT.GLTextureScan.prototype= {
  16113. freeChunks: null,
  16114. /**
  16115. * return an array of values where a chunk of width size fits in this scan.
  16116. * @param width
  16117. */
  16118. findWhereFits : function( width ) {
  16119. if ( this.freeChunks.length===0 ) {
  16120. return [];
  16121. }
  16122. var fitsOnPosition= [];
  16123. var i;
  16124. for( i=0; i<this.freeChunks.length; i++ ) {
  16125. var pos= 0;
  16126. while( pos+width<= this.freeChunks[i].size ) {
  16127. fitsOnPosition.push( pos+this.freeChunks[i].position );
  16128. pos+= width;
  16129. }
  16130. }
  16131. return fitsOnPosition;
  16132. },
  16133. fits : function( position, size ) {
  16134. var i=0;
  16135. for( i=0; i<this.freeChunks.length; i++ ) {
  16136. var fc= this.freeChunks[i];
  16137. if ( fc.position<=position && position+size<=fc.position+fc.size ) {
  16138. return true;
  16139. }
  16140. }
  16141. return false;
  16142. },
  16143. substract : function( position, size ) {
  16144. var i=0;
  16145. for( i=0; i<this.freeChunks.length; i++ ) {
  16146. var fc= this.freeChunks[i];
  16147. if ( fc.position<=position && position+size<=fc.position+fc.size ) {
  16148. var lp=0;
  16149. var ls=0;
  16150. var rp=0;
  16151. var rs=0;
  16152. lp= fc.position;
  16153. ls= position-fc.position;
  16154. rp= position+size;
  16155. rs= fc.position+fc.size - rp;
  16156. this.freeChunks.splice(i,1);
  16157. if ( ls>0 ) {
  16158. this.freeChunks.splice( i++,0,{position: lp, size:ls} );
  16159. }
  16160. if ( rs>0 ) {
  16161. this.freeChunks.splice( i,0,{position: rp, size:rs} );
  16162. }
  16163. return true;
  16164. }
  16165. }
  16166. return false;
  16167. },
  16168. log : function(index) {
  16169. if ( 0===this.freeChunks.length ) {
  16170. CAAT.log('index '+index+' empty');
  16171. } else {
  16172. var str='index '+index;
  16173. for( var i=0; i<this.freeChunks.length; i++ ) {
  16174. var fc= this.freeChunks[i];
  16175. str+='['+fc.position+","+fc.size+"]";
  16176. }
  16177. CAAT.log(str);
  16178. }
  16179. }
  16180. };
  16181. })();
  16182. (function() {
  16183. CAAT.GLTextureScanMap= function(w,h) {
  16184. this.scanMapHeight= h;
  16185. this.scanMapWidth= w;
  16186. this.scanMap= [];
  16187. for( var i=0; i<this.scanMapHeight; i++ ) {
  16188. this.scanMap.push( new CAAT.GLTextureScan(this.scanMapWidth) );
  16189. }
  16190. return this;
  16191. };
  16192. CAAT.GLTextureScanMap.prototype= {
  16193. scanMap: null,
  16194. scanMapWidth: 0,
  16195. scanMapHeight: 0,
  16196. /**
  16197. * Always try to fit a chunk of size width*height pixels from left-top.
  16198. * @param width
  16199. * @param height
  16200. */
  16201. whereFitsChunk : function( width, height ) {
  16202. // trivial rejection:
  16203. if ( width>this.width||height>this.height) {
  16204. return null;
  16205. }
  16206. // find first fitting point
  16207. var i,j,initialPosition= 0;
  16208. while( initialPosition<=this.scanMapHeight-height) {
  16209. // para buscar sitio se buscara un sitio hasta el tamano de alto del trozo.
  16210. // mas abajo no va a caber.
  16211. // fitHorizontalPosition es un array con todas las posiciones de este scan donde
  16212. // cabe un chunk de tamano width.
  16213. var fitHorizontalPositions= null;
  16214. var foundPositionOnScan= false;
  16215. for( ; initialPosition<=this.scanMapHeight-height; initialPosition++ ) {
  16216. fitHorizontalPositions= this.scanMap[ initialPosition ].findWhereFits( width );
  16217. // si no es nulo el array de resultados, quiere decir que en alguno de los puntos
  16218. // nos cabe un trozo de tamano width.
  16219. if ( null!==fitHorizontalPositions && fitHorizontalPositions.length>0 ) {
  16220. foundPositionOnScan= true;
  16221. break;
  16222. }
  16223. }
  16224. if ( foundPositionOnScan ) {
  16225. // j es el scan donde cabe un trozo de tamano width.
  16226. // comprobamos desde este scan que en todos los scan verticales cabe el trozo.
  16227. // se comprueba que cabe en alguno de los tamanos que la rutina de busqueda horizontal
  16228. // nos ha devuelto antes.
  16229. var minInitialPosition=Number.MAX_VALUE;
  16230. for( j=0; j<fitHorizontalPositions.length; j++ ) {
  16231. var fits= true;
  16232. for( i=initialPosition; i<initialPosition+height; i++ ) {
  16233. // hay un trozo que no cabe
  16234. if ( !this.scanMap[i].fits( fitHorizontalPositions[j], width ) ) {
  16235. fits= false;
  16236. break;
  16237. }
  16238. }
  16239. // se ha encontrado un trozo donde la imagen entra.
  16240. // d.p.m. incluirla en posicion, y seguir con otra.
  16241. if ( fits ) {
  16242. return { x: fitHorizontalPositions[j], y: initialPosition };
  16243. }
  16244. }
  16245. initialPosition++;
  16246. } else {
  16247. // no hay sitio en ningun scan.
  16248. return null;
  16249. }
  16250. }
  16251. // no se ha podido encontrar un area en la textura para un trozo de tamano width*height
  16252. return null;
  16253. },
  16254. substract : function( x,y, width, height ) {
  16255. for( var i=0; i<height; i++ ) {
  16256. if ( !this.scanMap[i+y].substract(x,width) ) {
  16257. CAAT.log('Error: removing chunk ',width,height,' at ',x,y);
  16258. }
  16259. }
  16260. },
  16261. log : function() {
  16262. for( var i=0; i<this.scanMapHeight; i++ ) {
  16263. this.scanMap[i].log(i);
  16264. }
  16265. }
  16266. };
  16267. })();
  16268. (function() {
  16269. CAAT.GLTexturePage= function(w,h) {
  16270. this.width= w || 1024;
  16271. this.height= h || 1024;
  16272. this.images= [];
  16273. return this;
  16274. };
  16275. CAAT.GLTexturePage.prototype= {
  16276. width: 1024,
  16277. height: 1024,
  16278. gl: null,
  16279. texture: null,
  16280. allowImagesInvertion: false,
  16281. padding: 4,
  16282. scan: null,
  16283. images: null,
  16284. criteria: 'area',
  16285. initialize : function(gl) {
  16286. this.gl= gl;
  16287. // Fix firefox.
  16288. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
  16289. this.texture = gl.createTexture();
  16290. gl.bindTexture(gl.TEXTURE_2D, this.texture);
  16291. gl.enable( gl.BLEND );
  16292. gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
  16293. var uarr= new Uint8Array(this.width*this.height*4);
  16294. for (var jj = 0; jj < 4*this.width*this.height; ) {
  16295. uarr[jj++]=0;
  16296. uarr[jj++]=0;
  16297. uarr[jj++]=0;
  16298. uarr[jj++]=0;
  16299. }
  16300. gl.texImage2D(
  16301. gl.TEXTURE_2D,
  16302. 0,
  16303. gl.RGBA,
  16304. this.width,
  16305. this.height,
  16306. 0,
  16307. gl.RGBA,
  16308. gl.UNSIGNED_BYTE,
  16309. uarr);
  16310. gl.enable( gl.BLEND );
  16311. for( var i=0; i<this.images.length; i++ ) {
  16312. var img= this.images[i];
  16313. if ( img.inverted ) {
  16314. img= CAAT.modules.ImageUtil.prototype.rotate( img, -90 );
  16315. }
  16316. gl.texSubImage2D(
  16317. gl.TEXTURE_2D,
  16318. 0,
  16319. this.images[i].__tx, this.images[i].__ty,
  16320. gl.RGBA,
  16321. gl.UNSIGNED_BYTE,
  16322. img );
  16323. }
  16324. },
  16325. create: function(imagesCache) {
  16326. var images= [];
  16327. for( var i=0; i<imagesCache.length; i++ ) {
  16328. var img= imagesCache[i].image;
  16329. if ( !img.__texturePage ) {
  16330. images.push( img );
  16331. }
  16332. }
  16333. this.createFromImages(images);
  16334. },
  16335. clear : function() {
  16336. this.createFromImages([]);
  16337. },
  16338. update : function(invert,padding,width,height) {
  16339. this.allowImagesInvertion= invert;
  16340. this.padding= padding;
  16341. if ( width<100 ) {
  16342. width= 100;
  16343. }
  16344. if ( height<100 ) {
  16345. height= 100;
  16346. }
  16347. this.width= width;
  16348. this.height= height;
  16349. this.createFromImages(this.images);
  16350. },
  16351. createFromImages : function( images ) {
  16352. var i;
  16353. this.scan= new CAAT.GLTextureScanMap( this.width, this.height );
  16354. this.images= [];
  16355. if ( this.allowImagesInvertion ) {
  16356. for( i=0; i<images.length; i++ ) {
  16357. images[i].inverted= this.allowImagesInvertion && images[i].height<images[i].width;
  16358. }
  16359. }
  16360. var me= this;
  16361. images.sort( function(a,b) {
  16362. var aarea= a.width*a.height;
  16363. var barea= b.width*b.height;
  16364. if ( me.criteria==='width' ) {
  16365. return a.width<b.width ? 1 : a.width>b.width ? -1 : 0;
  16366. } else if ( me.criteria==='height' ) {
  16367. return a.height<b.height ? 1 : a.height>b.height ? -1 : 0;
  16368. }
  16369. return aarea<barea ? 1 : aarea>barea ? -1 : 0;
  16370. });
  16371. for( i=0; i<images.length; i++ ) {
  16372. var img= images[i];
  16373. this.packImage(img);
  16374. }
  16375. },
  16376. addImage : function( image, invert, padding ) {
  16377. this.allowImagesInvertion= invert;
  16378. this.padding= padding;
  16379. this.images.push(image);
  16380. this.createFromImages(Array.prototype.slice.call(this.images));
  16381. },
  16382. endCreation : function() {
  16383. var gl= this.gl;
  16384. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  16385. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
  16386. gl.generateMipmap(gl.TEXTURE_2D);
  16387. },
  16388. deletePage : function() {
  16389. for( var i=0; i<this.images.length; i++ ) {
  16390. delete this.images[i].__texturePage;
  16391. delete this.images[i].__u;
  16392. delete this.images[i].__v;
  16393. }
  16394. this.gl.deleteTexture( this.texture );
  16395. },
  16396. toCanvas : function(canvass, outline) {
  16397. canvass= canvass || document.createElement('canvas');
  16398. canvass.width= this.width;
  16399. canvass.height= this.height;
  16400. var ctxx= canvass.getContext('2d');
  16401. ctxx.fillStyle= 'rgba(0,0,0,0)';
  16402. ctxx.fillRect(0,0,this.width,this.height);
  16403. for( var i=0; i<this.images.length; i++ ) {
  16404. ctxx.drawImage(
  16405. !this.images[i].inverted ?
  16406. this.images[i] :
  16407. CAAT.modules.ImageUtil.prototype.rotate( this.images[i], 90 ),
  16408. this.images[i].__tx,
  16409. this.images[i].__ty );
  16410. if ( outline ) {
  16411. ctxx.strokeStyle= 'red';
  16412. ctxx.strokeRect(
  16413. this.images[i].__tx,
  16414. this.images[i].__ty,
  16415. this.images[i].__w,
  16416. this.images[i].__h );
  16417. }
  16418. }
  16419. if (outline) {
  16420. ctxx.strokeStyle= 'red';
  16421. ctxx.strokeRect(0,0,this.width,this.height);
  16422. }
  16423. return canvass;
  16424. },
  16425. packImage : function(img) {
  16426. var newWidth, newHeight;
  16427. if ( img.inverted ) {
  16428. newWidth= img.height;
  16429. newHeight= img.width;
  16430. } else {
  16431. newWidth= img.width;
  16432. newHeight= img.height;
  16433. }
  16434. var w= newWidth;
  16435. var h= newHeight;
  16436. var mod;
  16437. // dejamos un poco de espacio para que las texturas no se pisen.
  16438. // coordenadas normalizadas 0..1 dan problemas cuando las texturas no estan
  16439. // alineadas a posicion mod 4,8...
  16440. if ( w && this.padding ) {
  16441. mod= this.padding;
  16442. if ( w+mod<=this.width ) {
  16443. w+=mod;
  16444. }
  16445. }
  16446. if ( h && this.padding ) {
  16447. mod= this.padding;
  16448. if ( h+mod<=this.height ) {
  16449. h+=mod;
  16450. }
  16451. }
  16452. var where= this.scan.whereFitsChunk( w, h );
  16453. if ( null!==where ) {
  16454. this.images.push( img );
  16455. img.__tx= where.x;
  16456. img.__ty= where.y;
  16457. img.__u= where.x / this.width;
  16458. img.__v= where.y / this.height;
  16459. img.__u1= (where.x+newWidth) / this.width;
  16460. img.__v1= (where.y+newHeight) / this.height;
  16461. img.__texturePage= this;
  16462. img.__w= newWidth;
  16463. img.__h= newHeight;
  16464. this.scan.substract(where.x,where.y,w,h);
  16465. } else {
  16466. CAAT.log('Imagen ',img.src,' de tamano ',img.width,img.height,' no cabe.');
  16467. }
  16468. },
  16469. changeHeuristic : function(criteria) {
  16470. this.criteria= criteria;
  16471. }
  16472. };
  16473. })();
  16474. (function() {
  16475. CAAT.GLTexturePageManager= function() {
  16476. this.pages= [];
  16477. return this;
  16478. };
  16479. CAAT.GLTexturePageManager.prototype= {
  16480. pages: null,
  16481. createPages: function(gl,width,height,imagesCache) {
  16482. var end= false;
  16483. while( !end ) {
  16484. var page= new CAAT.GLTexturePage(width,height);
  16485. page.create(imagesCache);
  16486. page.initialize(gl);
  16487. page.endCreation();
  16488. this.pages.push(page);
  16489. end= true;
  16490. for( var i=0; i<imagesCache.length; i++ ) {
  16491. // imagen sin asociacion de textura
  16492. if ( !imagesCache[i].image.__texturePage ) {
  16493. // cabe en la pagina ?? continua con otras paginas.
  16494. if ( imagesCache[i].image.width<=width && imagesCache[i].image.height<=height ) {
  16495. end= false;
  16496. }
  16497. break;
  16498. }
  16499. }
  16500. }
  16501. },
  16502. deletePages : function() {
  16503. for( var i=0; i<this.pages.length; i++ ) {
  16504. this.pages[i].deletePage();
  16505. }
  16506. this.pages= null;
  16507. }
  16508. };
  16509. })();