1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941 |
- /*
- The MIT License
- Copyright (c) 2010-2011-2012-2013-2014-2015 Abdul.R.Alargha [alargha1970@gmail.com]
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- Version: 0.4 build: 68
- Created on:
- DATE: 2015-04-01
- TIME: 01:03:47
- */
- /**
- * See LICENSE file.
- *
- * Library namespace.
- * CAAT stands for: Canvas Advanced Animation Toolkit.
- */
- /**
- * @namespace
- */
- var CAAT= CAAT || {};
- /**
- * Common bind function. Allows to set an object's function as callback. Set for every function in the
- * javascript context.
- */
- Function.prototype.bind= Function.prototype.bind || function() {
- var fn= this; // the function
- var args= Array.prototype.slice.call(arguments); // copy the arguments.
- var obj= args.shift(); // first parameter will be context 'this'
- return function() {
- return fn.apply(
- obj,
- args.concat(Array.prototype.slice.call(arguments)));
- }
- };
- isArray= function(input) { return typeof(input)=='object'&&(input instanceof Array); };
- isString= function(input){ return typeof(input)=='string'; };
- /**
- * See LICENSE file.
- *
- * Extend a prototype with another to form a classical OOP inheritance procedure.
- *
- * @param subc {object} Prototype to define the base class
- * @param superc {object} Prototype to be extended (derived class).
- */
- function extend(subc, superc) {
- var subcp = subc.prototype;
- // Class pattern.
- var F = function() {
- };
- F.prototype = superc.prototype;
- subc.prototype = new F(); // chain prototypes.
- subc.superclass = superc.prototype;
- subc.prototype.constructor = subc;
- // Reset constructor. See Object Oriented Javascript for an in-depth explanation of this.
- if (superc.prototype.constructor === Object.prototype.constructor) {
- superc.prototype.constructor = superc;
- }
- // los metodos de superc, que no esten en esta clase, crear un metodo que
- // llama al metodo de superc.
- for (var method in subcp) {
- if (subcp.hasOwnProperty(method)) {
- subc.prototype[method] = subcp[method];
- /**
- * Sintactic sugar to add a __super attribute on every overriden method.
- * Despite comvenient, it slows things down by 5fps.
- *
- * Uncomment at your own risk.
- *
- // tenemos en super un metodo con igual nombre.
- if ( superc.prototype[method]) {
- subc.prototype[method]= (function(fn, fnsuper) {
- return function() {
- var prevMethod= this.__super;
- this.__super= fnsuper;
- var retValue= fn.apply(
- this,
- Array.prototype.slice.call(arguments) );
- this.__super= prevMethod;
- return retValue;
- };
- })(subc.prototype[method], superc.prototype[method]);
- }
- */
- }
- }
- }
- /**
- * Dynamic Proxy for an object or wrap/decorate a function.
- *
- * @param object
- * @param preMethod
- * @param postMethod
- * @param errorMethod
- */
- function proxy(object, preMethod, postMethod, errorMethod) {
- // proxy a function
- if ( typeof object==='function' ) {
- if ( object.__isProxy ) {
- return object;
- }
- return (function(fn) {
- var proxyfn= function() {
- if ( preMethod ) {
- preMethod({
- fn: fn,
- arguments: Array.prototype.slice.call(arguments)} );
- }
- var retValue= null;
- try {
- // apply original function call with itself as context
- retValue= fn.apply(fn, Array.prototype.slice.call(arguments));
- // everything went right on function call, then call
- // post-method hook if present
- if ( postMethod ) {
- retValue= postMethod({
- fn: fn,
- arguments: Array.prototype.slice.call(arguments)} );
- }
- } catch(e) {
- // an exeception was thrown, call exception-method hook if
- // present and return its result as execution result.
- if( errorMethod ) {
- retValue= errorMethod({
- fn: fn,
- arguments: Array.prototype.slice.call(arguments),
- exception: e} );
- } else {
- // since there's no error hook, just throw the exception
- throw e;
- }
- }
- // return original returned value to the caller.
- return retValue;
- };
- proxyfn.__isProxy= true;
- for( var method in fn ) {
- if ( typeof fn[method]!=="function" ) {
- if (method!=="__object" && method!=="__isProxy") {
- (function(proxyfn, fn) {
- proxyfn.__defineGetter__( method, function() {
- return fn[method];
- });
- proxyfn.__defineSetter__( method, function(vale) {
- fn[method]= vale;
- });
- })(proxyfn, fn);
- }
- }
- }
- return proxyfn;
- })(object);
- }
- /**
- * If not a function then only non privitive objects can be proxied.
- * If it is a previously created proxy, return the proxy itself.
- */
- if ( !typeof object==='object' ||
- isArray(object) ||
- isString(object) ||
- object.__isProxy ) {
- return object;
- }
- // Our proxy object class.
- var cproxy= function() {};
- // A new proxy instance.
- var proxy= new cproxy();
- // hold the proxied object as member. Needed to assign proper
- // context on proxy method call.
- proxy.__object= object;
- proxy.__isProxy= true;
- // For every element in the object to be proxied
- for( var method in object ) {
- // only function members
- if ( typeof object[method]==='function' ) {
- // add to the proxy object a method of equal signature to the
- // method present at the object to be proxied.
- // cache references of object, function and function name.
- proxy[method]= (function(proxy,fn,method) {
- return function() {
- // call pre-method hook if present.
- if ( preMethod ) {
- preMethod({
- object: proxy.__object,
- method: method,
- arguments: Array.prototype.slice.call(arguments)} );
- }
- var retValue= null;
- try {
- // apply original object call with proxied object as
- // function context.
- retValue= fn.apply( proxy.__object, arguments );
- // everything went right on function call, the call
- // post-method hook if present
- if ( postMethod ) {
- postMethod({
- object: proxy.__object,
- method: method,
- arguments: Array.prototype.slice.call(arguments)} );
- }
- } catch(e) {
- // an exeception was thrown, call exception-method hook if
- // present and return its result as execution result.
- if( errorMethod ) {
- retValue= errorMethod({
- object: proxy.__object,
- method: method,
- arguments: Array.prototype.slice.call(arguments),
- exception: e} );
- } else {
- // since there's no error hook, just throw the exception
- throw e;
- }
- }
- // return original returned value to the caller.
- return retValue;
- };
- })(proxy,object[method],method);
- } else {
- if (method!=="__object" && method!=="__isProxy") {
- (function(proxy, method) {
- proxy.__defineGetter__( method, function() {
- return proxy.__object[method];
- });
- proxy.__defineSetter__( method, function(vale) {
- proxy.__object[method]= vale;
- });
- })(proxy, method);
- }
- }
- }
- // return our newly created and populated of functions proxy object.
- return proxy;
- }
- /** proxy sample usage
- var c0= new Meetup.C1(5);
- var cp1= proxy(
- c1,
- function() {
- console.log('pre method on object: ',
- arguments[0].object.toString(),
- arguments[0].method,
- arguments[0].arguments );
- },
- function() {
- console.log('post method on object: ',
- arguments[0].object.toString(),
- arguments[0].method,
- arguments[0].arguments );
- },
- function() {
- console.log('exception on object: ',
- arguments[0].object.toString(),
- arguments[0].method,
- arguments[0].arguments,
- arguments[0].exception);
- return -1;
- });
- **/
- function proxify( ns, preMethod, postMethod, errorMethod, getter, setter ) {
- var nns= "__"+ns+"__";
- var obj= window;
- var path= ns.split(".");
- while( path.length>1) {
- obj= obj[ path.shift() ];
- }
- window[nns] = obj[path];
- (function(obj,path, nns,ns) {
- var newC= function() {
- console.log("Creating object of type proxy["+ns+"]");
- var obj= new window[nns]( Array.prototype.slice.call(arguments) );
- obj.____name= ns;
- return proxyObject( obj, preMethod, postMethod, errorMethod, getter, setter );
- };
- // set new constructor function prototype as previous one.
- newC.prototype= window[nns].prototype;
- for( var method in obj[path] ) {
- if ( typeof obj[path][method]!=="function" ) {
- if (method!=="__object" && method!=="__isProxy") {
- (function(prevConstructor, method, newC) {
- newC.__defineGetter__( method, function() {
- return prevConstructor[method];
- });
- newC.__defineSetter__( method, function(vale) {
- prevConstructor[method]= vale;
- });
- })(obj[path],method,newC);
- }
- }
- }
- obj[path]= newC;
- })(obj,path,nns,ns);
- }
- function proxyObject(object, preMethod, postMethod, errorMethod, getter, setter) {
- /**
- * If not a function then only non privitive objects can be proxied.
- * If it is a previously created proxy, return the proxy itself.
- */
- if ( !typeof object==='object' ||
- isArray(object) ||
- isString(object) ||
- object.__isProxy ) {
- return object;
- }
- // hold the proxied object as member. Needed to assign proper
- // context on proxy method call.
- object.$proxy__isProxy= true;
- // For every element in the object to be proxied
- for( var method in object ) {
- if ( method==="constructor" ) {
- continue;
- }
- // only function members
- if ( typeof object[method]==='function' ) {
- var fn= object[method];
- object["$proxy__"+method]= fn;
- object[method]= (function(object,fn,fnname) {
- return function() {
- var args= Array.prototype.slice.call(arguments);
- // call pre-method hook if present.
- if ( preMethod ) {
- preMethod({
- object: object,
- objectName: object.____name,
- method: fnname,
- arguments: args } );
- }
- var retValue= null;
- try {
- // apply original object call with proxied object as
- // function context.
- retValue= fn.apply( object, args );
- // everything went right on function call, the call
- // post-method hook if present
- if ( postMethod ) {
- var rr= postMethod({
- object: object,
- objectName: object.____name,
- method: fnname,
- arguments: args } );
- if ( typeof rr!=="undefined" ) {
- //retValue= rr;
- }
- }
- } catch(e) {
- // an exeception was thrown, call exception-method hook if
- // present and return its result as execution result.
- if( errorMethod ) {
- retValue= errorMethod({
- object: object,
- objectName: object.____name,
- method: fnname,
- arguments: args,
- exception: e} );
- } else {
- // since there's no error hook, just throw the exception
- throw e;
- }
- }
- // return original returned value to the caller.
- return retValue;
- };
- })(object,fn,method);
- } else {
- if ( method!=="____name" ) {
- (function(object, attribute, getter, setter) {
- object["$proxy__"+attribute]= object[attribute];
- object.__defineGetter__( attribute, function() {
- if ( getter) {
- getter( object.____name, attribute );
- }
- return object["$proxy__"+attribute];
- });
- object.__defineSetter__( attribute, function (value) {
- object["$proxy__"+attribute] = value;
- if ( setter ) {
- setter( object.____name, attribute, value );
- }
- });
- })( object, method, getter, setter );
- }
- }
- }
- // return our newly created and populated with functions proxied object.
- return object;
- }/**
- * See LICENSE file.
- *
- * Manages every Actor affine transformations.
- * Take into account that Canvas' renderingContext computes postive rotation clockwise, so hacks
- * to handle it properly are hardcoded.
- *
- * Contained classes are CAAT.Matrix and CAAT.MatrixStack.
- *
- **/
- (function() {
- /**
- *
- * Define a matrix to hold three dimensional affine transforms.
- *
- * @constructor
- */
- CAAT.Matrix3= function() {
- this.matrix= [
- [1,0,0,0],
- [0,1,0,0],
- [0,0,1,0],
- [0,0,0,1]
- ];
- this.fmatrix= [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];
-
- return this;
- };
- CAAT.Matrix3.prototype= {
- matrix: null,
- fmatrix:null,
- transformCoord : function(point) {
- var x= point.x;
- var y= point.y;
- var z= point.z;
- point.x= x*this.matrix[0][0] + y*this.matrix[0][1] + z*this.matrix[0][2] + this.matrix[0][3];
- point.y= x*this.matrix[1][0] + y*this.matrix[1][1] + z*this.matrix[1][2] + this.matrix[1][3];
- point.z= x*this.matrix[2][0] + y*this.matrix[2][1] + z*this.matrix[2][2] + this.matrix[2][3];
- return point;
- },
- initialize : function( x0,y0,z0, x1,y1,z1, x2,y2,z2 ) {
- this.identity( );
- this.matrix[0][0]= x0;
- this.matrix[0][1]= y0;
- this.matrix[0][2]= z0;
- this.matrix[1][0]= x1;
- this.matrix[1][1]= y1;
- this.matrix[1][2]= z1;
- this.matrix[2][0]= x2;
- this.matrix[2][1]= y2;
- this.matrix[2][2]= z2;
- return this;
- },
- initWithMatrix : function(matrixData) {
- this.matrix= matrixData;
- return this;
- },
- flatten : function() {
- var d= this.fmatrix;
- var s= this.matrix;
- d[ 0]= s[0][0];
- d[ 1]= s[1][0];
- d[ 2]= s[2][0];
- d[ 3]= s[3][0];
- d[ 4]= s[0][1];
- d[ 5]= s[1][1];
- d[ 6]= s[2][1];
- d[ 7]= s[2][1];
- d[ 8]= s[0][2];
- d[ 9]= s[1][2];
- d[10]= s[2][2];
- d[11]= s[3][2];
- d[12]= s[0][3];
- d[13]= s[1][3];
- d[14]= s[2][3];
- d[15]= s[3][3];
-
- return this.fmatrix;
- },
- /**
- * Set this matrix to identity matrix.
- * @return this
- */
- identity : function() {
- for( var i=0; i<4; i++ ) {
- for( var j=0; j<4; j++ ) {
- this.matrix[i][j]= (i===j) ? 1.0 : 0.0;
- }
- }
- return this;
- },
- /**
- * Get this matri'x internal representation data. The bakced structure is a 4x4 array of number.
- */
- getMatrix : function() {
- return this.matrix;
- },
- /**
- * Multiply this matrix by a created rotation matrix. The rotation matrix is set up to rotate around
- * xy axis.
- *
- * @param xy {Number} radians to rotate.
- *
- * @return this
- */
- rotateXY : function( xy ) {
- return this.rotate( xy, 0, 0 );
- },
- /**
- * Multiply this matrix by a created rotation matrix. The rotation matrix is set up to rotate around
- * xz axis.
- *
- * @param xz {Number} radians to rotate.
- *
- * @return this
- */
- rotateXZ : function( xz ) {
- return this.rotate( 0, xz, 0 );
- },
- /**
- * Multiply this matrix by a created rotation matrix. The rotation matrix is set up to rotate aroind
- * yz axis.
- *
- * @param yz {Number} radians to rotate.
- *
- * @return this
- */
- rotateYZ : function( yz ) {
- return this.rotate( 0, 0, yz );
- },
- /**
- *
- * @param xy
- * @param xz
- * @param yz
- */
- setRotate : function( xy, xz, yz ) {
- var m= this.rotate(xy,xz,yz);
- this.copy(m);
- return this;
- },
- /**
- * Creates a matrix to represent arbitrary rotations around the given planes.
- * @param xy {number} radians to rotate around xy plane.
- * @param xz {number} radians to rotate around xz plane.
- * @param yz {number} radians to rotate around yz plane.
- *
- * @return {CAAT.Matrix3} a newly allocated matrix.
- * @static
- */
- rotate : function( xy, xz, yz ) {
- var res=new CAAT.Matrix3();
- var s,c,m;
- if (xy!==0) {
- m =new CAAT.Matrix3( );
- s=Math.sin(xy);
- c=Math.cos(xy);
- m.matrix[1][1]=c;
- m.matrix[1][2]=-s;
- m.matrix[2][1]=s;
- m.matrix[2][2]=c;
- res.multiply(m);
- }
- if (xz!==0) {
- m =new CAAT.Matrix3( );
- s=Math.sin(xz);
- c=Math.cos(xz);
- m.matrix[0][0]=c;
- m.matrix[0][2]=-s;
- m.matrix[2][0]=s;
- m.matrix[2][2]=c;
- res.multiply(m);
- }
- if (yz!==0) {
- m =new CAAT.Matrix3( );
- s=Math.sin(yz);
- c=Math.cos(yz);
- m.matrix[0][0]=c;
- m.matrix[0][1]=-s;
- m.matrix[1][0]=s;
- m.matrix[1][1]=c;
- res.multiply(m);
- }
- return res;
- },
- /**
- * Creates a new matrix being a copy of this matrix.
- * @return {CAAT.Matrix3} a newly allocated matrix object.
- */
- getClone : function() {
- var m= new CAAT.Matrix3( );
- m.copy(this);
- return m;
- },
- /**
- * Multiplies this matrix by another matrix.
- *
- * @param n {CAAT.Matrix3} a CAAT.Matrix3 object.
- * @return this
- */
- multiply : function( m ) {
- var n= this.getClone( );
- var nm= n.matrix;
- var n00= nm[0][0];
- var n01= nm[0][1];
- var n02= nm[0][2];
- var n03= nm[0][3];
- var n10= nm[1][0];
- var n11= nm[1][1];
- var n12= nm[1][2];
- var n13= nm[1][3];
- var n20= nm[2][0];
- var n21= nm[2][1];
- var n22= nm[2][2];
- var n23= nm[2][3];
- var n30= nm[3][0];
- var n31= nm[3][1];
- var n32= nm[3][2];
- var n33= nm[3][3];
- var mm= m.matrix;
- var m00= mm[0][0];
- var m01= mm[0][1];
- var m02= mm[0][2];
- var m03= mm[0][3];
- var m10= mm[1][0];
- var m11= mm[1][1];
- var m12= mm[1][2];
- var m13= mm[1][3];
- var m20= mm[2][0];
- var m21= mm[2][1];
- var m22= mm[2][2];
- var m23= mm[2][3];
- var m30= mm[3][0];
- var m31= mm[3][1];
- var m32= mm[3][2];
- var m33= mm[3][3];
- this.matrix[0][0] = n00*m00 + n01*m10 + n02*m20 + n03*m30;
- this.matrix[0][1] = n00*m01 + n01*m11 + n02*m21 + n03*m31;
- this.matrix[0][2] = n00*m02 + n01*m12 + n02*m22 + n03*m32;
- this.matrix[0][3] = n00*m03 + n01*m13 + n02*m23 + n03*m33;
- this.matrix[1][0] = n10*m00 + n11*m10 + n12*m20 + n13*m30;
- this.matrix[1][1] = n10*m01 + n11*m11 + n12*m21 + n13*m31;
- this.matrix[1][2] = n10*m02 + n11*m12 + n12*m22 + n13*m32;
- this.matrix[1][3] = n10*m03 + n11*m13 + n12*m23 + n13*m33;
- this.matrix[2][0] = n20*m00 + n21*m10 + n22*m20 + n23*m30;
- this.matrix[2][1] = n20*m01 + n21*m11 + n22*m21 + n23*m31;
- this.matrix[2][2] = n20*m02 + n21*m12 + n22*m22 + n23*m32;
- this.matrix[2][3] = n20*m03 + n21*m13 + n22*m23 + n23*m33;
- return this;
- },
- /**
- * Pre multiplies this matrix by a given matrix.
- *
- * @param m {CAAT.Matrix3} a CAAT.Matrix3 object.
- *
- * @return this
- */
- premultiply : function(m) {
- var n= this.getClone( );
- var nm= n.matrix;
- var n00= nm[0][0];
- var n01= nm[0][1];
- var n02= nm[0][2];
- var n03= nm[0][3];
- var n10= nm[1][0];
- var n11= nm[1][1];
- var n12= nm[1][2];
- var n13= nm[1][3];
- var n20= nm[2][0];
- var n21= nm[2][1];
- var n22= nm[2][2];
- var n23= nm[2][3];
- var n30= nm[3][0];
- var n31= nm[3][1];
- var n32= nm[3][2];
- var n33= nm[3][3];
- var mm= m.matrix;
- var m00= mm[0][0];
- var m01= mm[0][1];
- var m02= mm[0][2];
- var m03= mm[0][3];
- var m10= mm[1][0];
- var m11= mm[1][1];
- var m12= mm[1][2];
- var m13= mm[1][3];
- var m20= mm[2][0];
- var m21= mm[2][1];
- var m22= mm[2][2];
- var m23= mm[2][3];
- var m30= mm[3][0];
- var m31= mm[3][1];
- var m32= mm[3][2];
- var m33= mm[3][3];
- this.matrix[0][0] = n00*m00 + n01*m10 + n02*m20;
- this.matrix[0][1] = n00*m01 + n01*m11 + n02*m21;
- this.matrix[0][2] = n00*m02 + n01*m12 + n02*m22;
- this.matrix[0][3] = n00*m03 + n01*m13 + n02*m23 + n03;
- this.matrix[1][0] = n10*m00 + n11*m10 + n12*m20;
- this.matrix[1][1] = n10*m01 + n11*m11 + n12*m21;
- this.matrix[1][2] = n10*m02 + n11*m12 + n12*m22;
- this.matrix[1][3] = n10*m03 + n11*m13 + n12*m23 + n13;
- this.matrix[2][0] = n20*m00 + n21*m10 + n22*m20;
- this.matrix[2][1] = n20*m01 + n21*m11 + n22*m21;
- this.matrix[2][2] = n20*m02 + n21*m12 + n22*m22;
- this.matrix[2][3] = n20*m03 + n21*m13 + n22*m23 + n23;
- return this;
- },
- /**
- * Set this matrix translation values to be the given parameters.
- *
- * @param x {number} x component of translation point.
- * @param y {number} y component of translation point.
- * @param z {number} z component of translation point.
- *
- * @return this
- */
- setTranslate : function(x,y,z) {
- this.identity();
- this.matrix[0][3]=x;
- this.matrix[1][3]=y;
- this.matrix[2][3]=z;
- return this;
- },
- /**
- * Create a translation matrix.
- * @param x {number}
- * @param y {number}
- * @param z {number}
- * @return {CAAT.Matrix3} a new matrix.
- */
- translate : function( x,y,z ) {
- var m= new CAAT.Matrix3();
- m.setTranslate( x,y,z );
- return m;
- },
- setScale : function( sx, sy, sz ) {
- this.identity();
- this.matrix[0][0]= sx;
- this.matrix[1][1]= sy;
- this.matrix[2][2]= sz;
- return this;
- },
- scale : function( sx, sy, sz ) {
- var m= new CAAT.Matrix3();
- m.setScale(sx,sy,sz);
- return m;
- },
- /**
- * Set this matrix as the rotation matrix around the given axes.
- * @param xy {number} radians of rotation around z axis.
- * @param xz {number} radians of rotation around y axis.
- * @param yz {number} radians of rotation around x axis.
- *
- * @return this
- */
- rotateModelView : function( xy, xz, yz ) {
- var sxy= Math.sin( xy );
- var sxz= Math.sin( xz );
- var syz= Math.sin( yz );
- var cxy= Math.cos( xy );
- var cxz= Math.cos( xz );
- var cyz= Math.cos( yz );
- this.matrix[0][0]= cxz*cxy;
- this.matrix[0][1]= -cxz*sxy;
- this.matrix[0][2]= sxz;
- this.matrix[0][3]= 0;
- this.matrix[1][0]= syz*sxz*cxy+sxy*cyz;
- this.matrix[1][1]= cyz*cxy-syz*sxz*sxy;
- this.matrix[1][2]= -syz*cxz;
- this.matrix[1][3]= 0;
- this.matrix[2][0]= syz*sxy-cyz*sxz*cxy;
- this.matrix[2][1]= cyz*sxz*sxy+syz*cxy;
- this.matrix[2][2]= cyz*cxz;
- this.matrix[2][3]= 0;
- this.matrix[3][0]= 0;
- this.matrix[3][1]= 0;
- this.matrix[3][2]= 0;
- this.matrix[3][3]= 1;
- return this;
- },
- /**
- * Copy a given matrix values into this one's.
- * @param m {CAAT.Matrix} a matrix
- *
- * @return this
- */
- copy : function( m ) {
- for( var i=0; i<4; i++ ) {
- for( var j=0; j<4; j++ ) {
- this.matrix[i][j]= m.matrix[i][j];
- }
- }
- return this;
- },
- /**
- * Calculate this matrix's determinant.
- * @return {number} matrix determinant.
- */
- calculateDeterminant: function () {
- var mm= this.matrix;
- var m11= mm[0][0], m12= mm[0][1], m13= mm[0][2], m14= mm[0][3],
- m21= mm[1][0], m22= mm[1][1], m23= mm[1][2], m24= mm[1][3],
- m31= mm[2][0], m32= mm[2][1], m33= mm[2][2], m34= mm[2][3],
- m41= mm[3][0], m42= mm[3][1], m43= mm[3][2], m44= mm[3][3];
- return m14 * m22 * m33 * m41 +
- m12 * m24 * m33 * m41 +
- m14 * m23 * m31 * m42 +
- m13 * m24 * m31 * m42 +
- m13 * m21 * m34 * m42 +
- m11 * m23 * m34 * m42 +
- m14 * m21 * m32 * m43 +
- m11 * m24 * m32 * m43 +
- m13 * m22 * m31 * m44 +
- m12 * m23 * m31 * m44 +
- m12 * m21 * m33 * m44 +
- m11 * m22 * m33 * m44 +
- m14 * m23 * m32 * m41 -
- m13 * m24 * m32 * m41 -
- m13 * m22 * m34 * m41 -
- m12 * m23 * m34 * m41 -
- m14 * m21 * m33 * m42 -
- m11 * m24 * m33 * m42 -
- m14 * m22 * m31 * m43 -
- m12 * m24 * m31 * m43 -
- m12 * m21 * m34 * m43 -
- m11 * m22 * m34 * m43 -
- m13 * m21 * m32 * m44 -
- m11 * m23 * m32 * m44;
- },
- /**
- * Return a new matrix which is this matrix's inverse matrix.
- * @return {CAAT.Matrix3} a new matrix.
- */
- getInverse : function() {
- var mm= this.matrix;
- var m11 = mm[0][0], m12 = mm[0][1], m13 = mm[0][2], m14 = mm[0][3],
- m21 = mm[1][0], m22 = mm[1][1], m23 = mm[1][2], m24 = mm[1][3],
- m31 = mm[2][0], m32 = mm[2][1], m33 = mm[2][2], m34 = mm[2][3],
- m41 = mm[3][0], m42 = mm[3][1], m43 = mm[3][2], m44 = mm[3][3];
-
- var m2= new CAAT.Matrix3();
- m2.matrix[0][0]= m23*m34*m42 + m24*m32*m43 + m22*m33*m44 - m24*m33*m42 - m22*m34*m43 - m23*m32*m44;
- m2.matrix[0][1]= m14*m33*m42 + m12*m34*m43 + m13*m32*m44 - m12*m33*m44 - m13*m34*m42 - m14*m32*m43;
- m2.matrix[0][2]= m13*m24*m42 + m12*m23*m44 + m14*m22*m43 - m12*m24*m43 - m13*m22*m44 - m14*m23*m42;
- m2.matrix[0][3]= m14*m23*m32 + m12*m24*m33 + m13*m22*m34 - m13*m24*m32 - m14*m22*m33 - m12*m23*m34;
- m2.matrix[1][0]= m24*m33*m41 + m21*m34*m43 + m23*m31*m44 - m23*m34*m41 - m24*m31*m43 - m21*m33*m44;
- m2.matrix[1][1]= m13*m34*m41 + m14*m31*m43 + m11*m33*m44 - m14*m33*m41 - m11*m34*m43 - m13*m31*m44;
- m2.matrix[1][2]= m14*m23*m41 + m11*m24*m43 + m13*m21*m44 - m13*m24*m41 - m14*m21*m43 - m11*m23*m44;
- m2.matrix[1][3]= m13*m24*m31 + m14*m21*m33 + m11*m23*m34 - m14*m23*m31 - m11*m24*m33 - m13*m21*m34;
- m2.matrix[2][0]= m22*m34*m41 + m24*m31*m42 + m21*m32*m44 - m24*m32*m41 - m21*m34*m42 - m22*m31*m44;
- m2.matrix[2][1]= m14*m32*m41 + m11*m34*m42 + m12*m31*m44 - m11*m32*m44 - m12*m34*m41 - m14*m31*m42;
- m2.matrix[2][2]= m13*m24*m41 + m14*m21*m42 + m11*m22*m44 - m14*m22*m41 - m11*m24*m42 - m12*m21*m44;
- m2.matrix[2][3]= m14*m22*m31 + m11*m24*m32 + m12*m21*m34 - m11*m22*m34 - m12*m24*m31 - m14*m21*m32;
- m2.matrix[3][0]= m23*m32*m41 + m21*m33*m42 + m22*m31*m43 - m22*m33*m41 - m23*m31*m42 - m21*m32*m43;
- m2.matrix[3][1]= m12*m33*m41 + m13*m31*m42 + m11*m32*m43 - m13*m32*m41 - m11*m33*m42 - m12*m31*m43;
- m2.matrix[3][2]= m13*m22*m41 + m11*m23*m42 + m12*m21*m43 - m11*m22*m43 - m12*m23*m41 - m13*m21*m42;
- m2.matrix[3][3]= m12*m23*m31 + m13*m21*m32 + m11*m22*m33 - m13*m22*m31 - m11*m23*m32 - m12*m21*m33;
-
- return m2.multiplyScalar( 1/this.calculateDeterminant() );
- },
- /**
- * Multiply this matrix by a scalar.
- * @param scalar {number} scalar value
- *
- * @return this
- */
- multiplyScalar : function( scalar ) {
- var i,j;
- for( i=0; i<4; i++ ) {
- for( j=0; j<4; j++ ) {
- this.matrix[i][j]*=scalar;
- }
- }
- return this;
- }
- };
- })();
- (function() {
- /**
- * 2D affinetransform matrix represeantation.
- * It includes matrices for
- * <ul>
- * <li>Rotation by any anchor point
- * <li>translation
- * <li>scale by any anchor point
- * </ul>
- *
- */
- CAAT.Matrix = function() {
- this.matrix= [
- 1.0,0.0,0.0,
- 0.0,1.0,0.0, 0.0,0.0,1.0 ];
- if ( Float32Array ) {
- this.matrix= new Float32Array(this.matrix);
- }
- return this;
- };
-
- CAAT.Matrix.prototype= {
- matrix: null,
- /**
- * Transform a point by this matrix. The parameter point will be modified with the transformation values.
- * @param point {CAAT.Point}.
- * @return {CAAT.Point} the parameter point.
- */
- transformCoord : function(point) {
- var x= point.x;
- var y= point.y;
- var tm= this.matrix;
- point.x= x*tm[0] + y*tm[1] + tm[2];
- point.y= x*tm[3] + y*tm[4] + tm[5];
- return point;
- },
- /**
- * Create a new rotation matrix and set it up for the specified angle in radians.
- * @param angle {number}
- * @return {CAAT.Matrix} a matrix object.
- *
- * @static
- */
- rotate : function(angle) {
- var m= new CAAT.Matrix();
- m.setRotation(angle);
- return m;
- },
- setRotation : function( angle ) {
- this.identity();
- var tm= this.matrix;
- var c= Math.cos( angle );
- var s= Math.sin( angle );
- tm[0]= c;
- tm[1]= -s;
- tm[3]= s;
- tm[4]= c;
- return this;
- },
- /**
- * Create a scale matrix.
- * @param scalex {number} x scale magnitude.
- * @param scaley {number} y scale magnitude.
- *
- * @return {CAAT.Matrix} a matrix object.
- *
- * @static
- */
- scale : function(scalex, scaley) {
- var m= new CAAT.Matrix();
- m.matrix[0]= scalex;
- m.matrix[4]= scaley;
- return m;
- },
- setScale : function(scalex, scaley) {
- this.identity();
- this.matrix[0]= scalex;
- this.matrix[4]= scaley;
- return this;
- },
- /**
- * Create a translation matrix.
- * @param x {number} x translation magnitude.
- * @param y {number} y translation magnitude.
- *
- * @return {CAAT.Matrix} a matrix object.
- * @static
- *
- */
- translate : function( x, y ) {
- var m= new CAAT.Matrix();
- m.matrix[2]= x;
- m.matrix[5]= y;
- return m;
- },
- /**
- * Sets this matrix as a translation matrix.
- * @param x
- * @param y
- */
- setTranslate : function( x, y ) {
- this.identity();
- this.matrix[2]= x;
- this.matrix[5]= y;
- return this;
- },
- /**
- * Copy into this matrix the given matrix values.
- * @param matrix {CAAT.Matrix}
- * @return this
- */
- copy : function( matrix ) {
- matrix= matrix.matrix;
- var tmatrix= this.matrix;
- tmatrix[0]= matrix[0];
- tmatrix[1]= matrix[1];
- tmatrix[2]= matrix[2];
- tmatrix[3]= matrix[3];
- tmatrix[4]= matrix[4];
- tmatrix[5]= matrix[5];
- tmatrix[6]= matrix[6];
- tmatrix[7]= matrix[7];
- tmatrix[8]= matrix[8];
- return this;
- },
- /**
- * Set this matrix to the identity matrix.
- * @return this
- */
- identity : function() {
- var m= this.matrix;
- m[0]= 1.0;
- m[1]= 0.0;
- m[2]= 0.0;
- m[3]= 0.0;
- m[4]= 1.0;
- m[5]= 0.0;
- m[6]= 0.0;
- m[7]= 0.0;
- m[8]= 1.0;
- return this;
- },
- /**
- * Multiply this matrix by a given matrix.
- * @param m {CAAT.Matrix}
- * @return this
- */
- multiply : function( m ) {
- var tm= this.matrix;
- var mm= m.matrix;
- var tm0= tm[0];
- var tm1= tm[1];
- var tm2= tm[2];
- var tm3= tm[3];
- var tm4= tm[4];
- var tm5= tm[5];
- var tm6= tm[6];
- var tm7= tm[7];
- var tm8= tm[8];
- var mm0= mm[0];
- var mm1= mm[1];
- var mm2= mm[2];
- var mm3= mm[3];
- var mm4= mm[4];
- var mm5= mm[5];
- var mm6= mm[6];
- var mm7= mm[7];
- var mm8= mm[8];
- tm[0]= tm0*mm0 + tm1*mm3 + tm2*mm6;
- tm[1]= tm0*mm1 + tm1*mm4 + tm2*mm7;
- tm[2]= tm0*mm2 + tm1*mm5 + tm2*mm8;
- tm[3]= tm3*mm0 + tm4*mm3 + tm5*mm6;
- tm[4]= tm3*mm1 + tm4*mm4 + tm5*mm7;
- tm[5]= tm3*mm2 + tm4*mm5 + tm5*mm8;
- tm[6]= tm6*mm0 + tm7*mm3 + tm8*mm6;
- tm[7]= tm6*mm1 + tm7*mm4 + tm8*mm7;
- tm[8]= tm6*mm2 + tm7*mm5 + tm8*mm8;
- return this;
- },
- /**
- * Premultiply this matrix by a given matrix.
- * @param m {CAAT.Matrix}
- * @return this
- */
- premultiply : function(m) {
- var m00= m.matrix[0]*this.matrix[0] + m.matrix[1]*this.matrix[3] + m.matrix[2]*this.matrix[6];
- var m01= m.matrix[0]*this.matrix[1] + m.matrix[1]*this.matrix[4] + m.matrix[2]*this.matrix[7];
- var m02= m.matrix[0]*this.matrix[2] + m.matrix[1]*this.matrix[5] + m.matrix[2]*this.matrix[8];
- var m10= m.matrix[3]*this.matrix[0] + m.matrix[4]*this.matrix[3] + m.matrix[5]*this.matrix[6];
- var m11= m.matrix[3]*this.matrix[1] + m.matrix[4]*this.matrix[4] + m.matrix[5]*this.matrix[7];
- var m12= m.matrix[3]*this.matrix[2] + m.matrix[4]*this.matrix[5] + m.matrix[5]*this.matrix[8];
- var m20= m.matrix[6]*this.matrix[0] + m.matrix[7]*this.matrix[3] + m.matrix[8]*this.matrix[6];
- var m21= m.matrix[6]*this.matrix[1] + m.matrix[7]*this.matrix[4] + m.matrix[8]*this.matrix[7];
- var m22= m.matrix[6]*this.matrix[2] + m.matrix[7]*this.matrix[5] + m.matrix[8]*this.matrix[8];
- this.matrix[0]= m00;
- this.matrix[1]= m01;
- this.matrix[2]= m02;
- this.matrix[3]= m10;
- this.matrix[4]= m11;
- this.matrix[5]= m12;
- this.matrix[6]= m20;
- this.matrix[7]= m21;
- this.matrix[8]= m22;
- return this;
- },
- /**
- * Creates a new inverse matrix from this matrix.
- * @return {CAAT.Matrix} an inverse matrix.
- */
- getInverse : function() {
- var tm= this.matrix;
- var m00= tm[0];
- var m01= tm[1];
- var m02= tm[2];
- var m10= tm[3];
- var m11= tm[4];
- var m12= tm[5];
- var m20= tm[6];
- var m21= tm[7];
- var m22= tm[8];
- var newMatrix= new CAAT.Matrix();
- var determinant= m00* (m11*m22 - m21*m12) - m10*(m01*m22 - m21*m02) + m20 * (m01*m12 - m11*m02);
- if ( determinant===0 ) {
- return null;
- }
- var m= newMatrix.matrix;
- m[0]= m11*m22-m12*m21;
- m[1]= m02*m21-m01*m22;
- m[2]= m01*m12-m02*m11;
- m[3]= m12*m20-m10*m22;
- m[4]= m00*m22-m02*m20;
- m[5]= m02*m10-m00*m12;
- m[6]= m10*m21-m11*m20;
- m[7]= m01*m20-m00*m21;
- m[8]= m00*m11-m01*m10;
- newMatrix.multiplyScalar( 1/determinant );
- return newMatrix;
- },
- /**
- * Multiply this matrix by a scalar.
- * @param scalar {number} scalar value
- *
- * @return this
- */
- multiplyScalar : function( scalar ) {
- var i;
- for( i=0; i<9; i++ ) {
- this.matrix[i]*=scalar;
- }
- return this;
- },
- transformRenderingContextSet : null,
- transformRenderingContext : null,
- /**
- *
- * @param ctx
- */
- transformRenderingContextSet_NoClamp : function(ctx) {
- var m= this.matrix;
- ctx.setTransform( m[0], m[3], m[1], m[4], m[2], m[5] );
- return this;
- },
- /**
- *
- * @param ctx
- */
- transformRenderingContext_NoClamp : function(ctx) {
- var m= this.matrix;
- ctx.transform( m[0], m[3], m[1], m[4], m[2], m[5] );
- return this;
- },
- /**
- *
- * @param ctx
- */
- transformRenderingContextSet_Clamp : function(ctx) {
- var m= this.matrix;
- ctx.setTransform( m[0], m[3], m[1], m[4], m[2]>>0, m[5]>>0 );
- return this;
- },
- /**
- *
- * @param ctx
- */
- transformRenderingContext_Clamp : function(ctx) {
- var m= this.matrix;
- ctx.transform( m[0], m[3], m[1], m[4], m[2]>>0, m[5]>>0 );
- return this;
- }
- };
- CAAT.Matrix.prototype.transformRenderingContext= CAAT.Matrix.prototype.transformRenderingContext_Clamp;
- CAAT.Matrix.prototype.transformRenderingContextSet= CAAT.Matrix.prototype.transformRenderingContextSet_Clamp;
- })();
- (function() {
- /**
- * Implementation of a matrix stack. Each CAAT.Actor instance contains a MatrixStack to hold of its affine
- * transformations. The Canvas rendering context will be fed with this matrix stack values to keep a homogeneous
- * transformation process.
- *
- * @constructor
- */
- CAAT.MatrixStack= function() {
- this.stack= [];
- this.saved= [];
- return this;
- };
- CAAT.MatrixStack.prototype= {
- stack: null,
- saved: null,
- /**
- * Add a matrix to the transformation stack.
- * @return this
- */
- pushMatrix : function(matrix) {
- this.stack.push(matrix);
- return this;
- },
- /**
- * Remove the last matrix from this stack.
- * @return {CAAT.Matrix} the poped matrix.
- */
- popMatrix : function() {
- return this.stack.pop();
- },
- /**
- * Create a restoration point of pushed matrices.
- * @return this
- */
- save : function() {
- this.saved.push(this.stack.length);
- return this;
- },
- /**
- * Restore from the last restoration point set.
- * @return this
- */
- restore : function() {
- var pos= this.saved.pop();
- while( this.stack.length!==pos ) {
- this.popMatrix();
- }
- return this;
- },
- /**
- * Return the concatenation (multiplication) matrix of all the matrices contained in this stack.
- * @return {CAAT.Matrix} a new matrix.
- */
- getMatrix : function() {
- var matrix= new CAAT.Matrix();
- for( var i=0; i<this.stack.length; i++ ) {
- var matrixStack= this.stack[i];
- matrix.multiply( matrixStack );
- }
- return matrix;
- }
- };
- })();/**
- * See LICENSE file.
- *
- * @author: Mario Gonzalez (@onedayitwilltake) and Ibon Tolosana (@hyperandroid)
- *
- * Helper classes for color manipulation.
- *
- **/
- (function() {
- /**
- * Class with color utilities.
- *
- * @constructor
- */
- CAAT.Color = function() {
- return this;
- };
- CAAT.Color.prototype= {
- /**
- * HSV to RGB color conversion
- * <p>
- * H runs from 0 to 360 degrees<br>
- * S and V run from 0 to 100
- * <p>
- * Ported from the excellent java algorithm by Eugene Vishnevsky at:
- * http://www.cs.rit.edu/~ncs/color/t_convert.html
- *
- * @static
- */
- hsvToRgb: function(h, s, v)
- {
- var r, g, b;
- var i;
- var f, p, q, t;
- // Make sure our arguments stay in-range
- h = Math.max(0, Math.min(360, h));
- s = Math.max(0, Math.min(100, s));
- v = Math.max(0, Math.min(100, v));
- // We accept saturation and value arguments from 0 to 100 because that's
- // how Photoshop represents those values. Internally, however, the
- // saturation and value are calculated from a range of 0 to 1. We make
- // That conversion here.
- s /= 100;
- v /= 100;
- if(s === 0) {
- // Achromatic (grey)
- r = g = b = v;
- return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
- }
- h /= 60; // sector 0 to 5
- i = Math.floor(h);
- f = h - i; // factorial part of h
- p = v * (1 - s);
- q = v * (1 - s * f);
- t = v * (1 - s * (1 - f));
- switch(i) {
- case 0:
- r = v;
- g = t;
- b = p;
- break;
- case 1:
- r = q;
- g = v;
- b = p;
- break;
- case 2:
- r = p;
- g = v;
- b = t;
- break;
- case 3:
- r = p;
- g = q;
- b = v;
- break;
- case 4:
- r = t;
- g = p;
- b = v;
- break;
- default: // case 5:
- r = v;
- g = p;
- b = q;
- }
- return new CAAT.Color.RGB(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255));
- },
- /**
- * Enumeration to define types of color ramps.
- * @enum {number}
- */
- RampEnumeration : {
- RAMP_RGBA: 0,
- RAMP_RGB: 1,
- RAMP_CHANNEL_RGB: 2,
- RAMP_CHANNEL_RGBA: 3,
- RAMP_CHANNEL_RGB_ARRAY: 4,
- RAMP_CHANNEL_RGBA_ARRAY:5
- },
- /**
- * Interpolate the color between two given colors. The return value will be a calculated color
- * among the two given initial colors which corresponds to the 'step'th color of the 'nsteps'
- * calculated colors.
- * @param r0 {number} initial color red component.
- * @param g0 {number} initial color green component.
- * @param b0 {number} initial color blue component.
- * @param r1 {number} final color red component.
- * @param g1 {number} final color green component.
- * @param b1 {number} final color blue component.
- * @param nsteps {number} number of colors to calculate including the two given colors. If 16 is passed as value,
- * 14 colors plus the two initial ones will be calculated.
- * @param step {number} return this color index of all the calculated colors.
- *
- * @return { r{number}, g{number}, b{number} } return an object with the new calculated color components.
- * @static
- */
- interpolate : function( r0, g0, b0, r1, g1, b1, nsteps, step) {
- if ( step<=0 ) {
- return {
- r:r0,
- g:g0,
- b:b0
- };
- } else if ( step>=nsteps ) {
- return {
- r:r1,
- g:g1,
- b:b1
- };
- }
- var r= (r0+ (r1-r0)/nsteps*step)>>0;
- var g= (g0+ (g1-g0)/nsteps*step)>>0;
- var b= (b0+ (b1-b0)/nsteps*step)>>0;
- if ( r>255 ) {r=255;} else if (r<0) {r=0;}
- if ( g>255 ) {g=255;} else if (g<0) {g=0;}
- if ( b>255 ) {b=255;} else if (b<0) {b=0;}
- return {
- r:r,
- g:g,
- b:b
- };
- },
- /**
- * Generate a ramp of colors from an array of given colors.
- * @param fromColorsArray {[number]} an array of colors. each color is defined by an integer number from which
- * color components will be extracted. Be aware of the alpha component since it will also be interpolated for
- * new colors.
- * @param rampSize {number} number of colors to produce.
- * @param returnType {CAAT.ColorUtils.RampEnumeration} a value of CAAT.ColorUtils.RampEnumeration enumeration.
- *
- * @return { [{number},{number},{number},{number}] } an array of integers each of which represents a color of
- * the calculated color ramp.
- *
- * @static
- */
- makeRGBColorRamp : function( fromColorsArray, rampSize, returnType ) {
- var ramp= [];
- var nc= fromColorsArray.length-1;
- var chunk= rampSize/nc;
- for( var i=0; i<nc; i++ ) {
- var c= fromColorsArray[i];
- var a0= (c>>24)&0xff;
- var r0= (c&0xff0000)>>16;
- var g0= (c&0xff00)>>8;
- var b0= c&0xff;
- var c1= fromColorsArray[i+1];
- var a1= (c1>>24)&0xff;
- var r1= (c1&0xff0000)>>16;
- var g1= (c1&0xff00)>>8;
- var b1= c1&0xff;
- var da= (a1-a0)/chunk;
- var dr= (r1-r0)/chunk;
- var dg= (g1-g0)/chunk;
- var db= (b1-b0)/chunk;
- for( var j=0; j<chunk; j++ ) {
- var na= (a0+da*j)>>0;
- var nr= (r0+dr*j)>>0;
- var ng= (g0+dg*j)>>0;
- var nb= (b0+db*j)>>0;
- switch( returnType ) {
- case this.RampEnumeration.RAMP_RGBA:
- ramp.push( 'argb('+na+','+nr+','+ng+','+nb+')' );
- break;
- case this.RampEnumeration.RAMP_RGB:
- ramp.push( 'rgb('+nr+','+ng+','+nb+')' );
- break;
- case this.RampEnumeration.RAMP_CHANNEL_RGB:
- ramp.push( 0xff000000 | nr<<16 | ng<<8 | nb );
- break;
- case this.RampEnumeration.RAMP_CHANNEL_RGBA:
- ramp.push( na<<24 | nr<<16 | ng<<8 | nb );
- break;
- case this.RampEnumeration.RAMP_CHANNEL_RGBA_ARRAY:
- ramp.push([ nr, ng, nb, na ]);
- break;
- case this.RampEnumeration.RAMP_CHANNEL_RGB_ARRAY:
- ramp.push([ nr, ng, nb ]);
- break;
- }
- }
- }
- return ramp;
- }
- };
- })();
- (function() {
- /**
- * RGB color implementation
- * @param r {number} an integer in the range 0..255
- * @param g {number} an integer in the range 0..255
- * @param b {number} an integer in the range 0..255
- *
- * @constructor
- */
- CAAT.Color.RGB = function(r, g, b) {
- this.r = r || 255;
- this.g = g || 255;
- this.b = b || 255;
- return this;
- };
- CAAT.Color.RGB.prototype= {
- r: 255,
- g: 255,
- b: 255,
- /**
- * Get color hexadecimal representation.
- * @return {string} a string with color hexadecimal representation.
- */
- toHex: function() {
- // See: http://jsperf.com/rgb-decimal-to-hex/5
- return ('000000' + ((this.r << 16) + (this.g << 8) + this.b).toString(16)).slice(-6);
- }
- };
- })();
- /**
- * See LICENSE file.
- *
- * Rectangle Class.
- * Needed to compute Curve bounding box.
- * Needed to compute Actor affected area on change.
- *
- **/
- (function() {
- /**
- * A Rectangle implementation, which defines an area positioned somewhere.
- *
- * @constructor
- */
- CAAT.Rectangle= function() {
- return this;
- };
-
- CAAT.Rectangle.prototype= {
- x: 0,
- y: 0,
- x1: 0,
- y1: 0,
- width: -1,
- height: -1,
- setEmpty : function() {
- this.width= -1;
- this.height= -1;
- this.x= 0;
- this.y= 0;
- this.x1= 0;
- this.y1= 0;
- return this;
- },
- /**
- * Set this rectangle's location.
- * @param x {number}
- * @param y {number}
- */
- setLocation: function( x,y ) {
- this.x= x;
- this.y= y;
- this.x1= this.x+this.width;
- this.y1= this.y+this.height;
- return this;
- },
- /**
- * Set this rectangle's dimension.
- * @param w {number}
- * @param h {number}
- */
- setDimension : function( w,h ) {
- this.width= w;
- this.height= h;
- this.x1= this.x+this.width;
- this.y1= this.y+this.height;
- return this;
- },
- setBounds : function( x,y,w,h ) {
- this.setLocation( x, y )
- this.setDimension( w, h );
- return this;
- },
- /**
- * Return whether the coordinate is inside this rectangle.
- * @param px {number}
- * @param py {number}
- *
- * @return {boolean}
- */
- contains : function(px,py) {
- return px>=0 && px<this.width && py>=0 && py<this.height;
- },
- /**
- * Return whether this rectangle is empty, that is, has zero dimension.
- * @return {boolean}
- */
- isEmpty : function() {
- return this.width===-1 && this.height===-1;
- },
- /**
- * Set this rectangle as the union of this rectangle and the given point.
- * @param px {number}
- * @param py {number}
- */
- union : function(px,py) {
-
- if ( this.isEmpty() ) {
- this.x= px;
- this.x1= px;
- this.y= py;
- this.y1= py;
- this.width=0;
- this.height=0;
- return;
- }
-
- this.x1= this.x+this.width;
- this.y1= this.y+this.height;
-
- if ( py<this.y ) {
- this.y= py;
- }
- if ( px<this.x ) {
- this.x= px;
- }
- if ( py>this.y1 ) {
- this.y1= py;
- }
- if ( px>this.x1 ){
- this.x1= px;
- }
-
- this.width= this.x1-this.x;
- this.height= this.y1-this.y;
- },
- unionRectangle : function( rectangle ) {
- this.union( rectangle.x , rectangle.y );
- this.union( rectangle.x1, rectangle.y );
- this.union( rectangle.x, rectangle.y1 );
- this.union( rectangle.x1, rectangle.y1 );
- return this;
- },
- intersects : function( r ) {
- if ( r.isEmpty() || this.isEmpty() ) {
- return false;
- }
- if ( r.x1<= this.x ) {
- return false;
- }
- if ( r.x >= this.x1 ) {
- return false;
- }
- if ( r.y1<= this.y ) {
- return false;
- }
- if ( r.y>= this.y1 ) {
- return false;
- }
- return true;
- },
- intersectsRect : function( x,y,w,h ) {
- if ( -1===w || -1===h ) {
- return false;
- }
- var x1= x+w-1;
- var y1= y+h-1;
- if ( x1< this.x ) {
- return false;
- }
- if ( x > this.x1 ) {
- return false;
- }
- if ( y1< this.y ) {
- return false;
- }
- if ( y> this.y1 ) {
- return false;
- }
- return true;
- },
- intersect : function( i, r ) {
- if ( typeof r==='undefined' ) {
- r= new CAAT.Rectangle();
- }
- r.x= Math.max( this.x, i.x );
- r.y= Math.max( this.y, i.y );
- r.x1=Math.min( this.x1, i.x1 );
- r.y1=Math.min( this.y1, i.y1 );
- r.width= r.x1-r.x;
- r.height=r.y1-r.y;
- return r;
- }
- };
- })();/**
- * See LICENSE file.
- *
- * Classes to solve and draw curves.
- * Curve is the superclass of
- * + Bezier (quadric and cubic)
- * + CatmullRom
- *
- *
- **/
- (function() {
- /**
- *
- * Curve class is the base for all curve solvers available in CAAT.
- *
- * @constructor
- */
- CAAT.Curve= function() {
- return this;
- };
-
- CAAT.Curve.prototype= {
- coordlist: null,
- k: 0.05,
- length: -1,
- interpolator: false,
- HANDLE_SIZE: 20,
- drawHandles: true,
- /**
- * Paint the curve control points.
- * @param director {CAAT.Director}
- */
- paint: function(director) {
- if ( false===this.drawHandles ) {
- return;
- }
- var cl= this.coordlist;
- var ctx= director.ctx;
-
- // control points
- ctx.save();
- ctx.beginPath();
-
- ctx.strokeStyle='#a0a0a0';
- ctx.moveTo( cl[0].x, cl[0].y );
- ctx.lineTo( cl[1].x, cl[1].y );
- ctx.stroke();
- if ( this.cubic ) {
- ctx.moveTo( cl[2].x, cl[2].y );
- ctx.lineTo( cl[3].x, cl[3].y );
- ctx.stroke();
- }
- ctx.globalAlpha=0.5;
- for( var i=0; i<this.coordlist.length; i++ ) {
- ctx.fillStyle='#7f7f00';
- var w= CAAT.Curve.prototype.HANDLE_SIZE/2;
- ctx.fillRect( cl[i].x-w, cl[i].y-w, w*2, w*2 );
- }
- ctx.restore();
- },
- /**
- * Signal the curve has been modified and recalculate curve length.
- */
- update : function() {
- this.calcLength();
- },
- /**
- * This method must be overriden by subclasses. It is called whenever the curve must be solved for some time=t.
- * The t parameter must be in the range 0..1
- * @param point {CAAT.Point} to store curve solution for t.
- * @param t {number}
- * @return {CAAT.Point} the point parameter.
- */
- solve: function(point,t) {
- },
- /**
- * Get an array of points defining the curve contour.
- * @param numSamples {number} number of segments to get.
- */
- getContour : function(numSamples) {
- var contour= [], i;
- for( i=0; i<=numSamples; i++ ) {
- var point= new CAAT.Point();
- this.solve( point, i/numSamples );
- contour.push(point);
- }
- return contour;
- },
- /**
- * Calculates a curve bounding box.
- *
- * @param rectangle {CAAT.Rectangle} a rectangle to hold the bounding box.
- * @return {CAAT.Rectangle} the rectangle parameter.
- */
- getBoundingBox : function(rectangle) {
- if ( !rectangle ) {
- rectangle= new CAAT.Rectangle();
- }
- // thanks yodesoft.com for spotting the first point is out of the BB
- rectangle.setEmpty();
- rectangle.union( this.coordlist[0].x, this.coordlist[0].y );
- var pt= new CAAT.Point();
- for(var t=this.k;t<=1+this.k;t+=this.k){
- this.solve(pt,t);
- rectangle.union( pt.x, pt.y );
- }
-
- return rectangle;
- },
- /**
- * Calculate the curve length by incrementally solving the curve every substep=CAAT.Curve.k. This value defaults
- * to .05 so at least 20 iterations will be performed.
- *
- * @return {number} the approximate curve length.
- */
- calcLength : function() {
- var x1,y1;
- x1 = this.coordlist[0].x;
- y1 = this.coordlist[0].y;
- var llength=0;
- var pt= new CAAT.Point();
- for(var t=this.k;t<=1+this.k;t+=this.k){
- this.solve(pt,t);
- llength+= Math.sqrt( (pt.x-x1)*(pt.x-x1) + (pt.y-y1)*(pt.y-y1) );
- x1=pt.x;
- y1=pt.y;
- }
-
- this.length= llength;
- return llength;
- },
- /**
- * Return the cached curve length.
- * @return {number} the cached curve length.
- */
- getLength : function() {
- return this.length;
- },
- /**
- * Return the first curve control point.
- * @return {CAAT.Point}
- */
- endCurvePosition : function() {
- return this.coordlist[ this.coordlist.length-1 ];
- },
- /**
- * Return the last curve control point.
- * @return {CAAT.Point}
- */
- startCurvePosition : function() {
- return this.coordlist[ 0 ];
- },
- setPoints : function( points ) {
- },
- setPoint : function( point, index ) {
- if ( index>=0 && index<this.coordlist.length ) {
- this.coordlist[index]= point;
- }
- },
- /**
- *
- * @param director <=CAAT.Director>
- */
- applyAsPath : function( director ) {
- }
- };
- })();
- (function() {
- /**
- * Bezier quadric and cubic curves implementation.
- *
- * @constructor
- * @extends CAAT.Curve
- */
- CAAT.Bezier= function() {
- CAAT.Bezier.superclass.constructor.call(this);
- return this;
- };
-
- CAAT.Bezier.prototype= {
-
- cubic: false,
- applyAsPath : function( director ) {
- var cc= this.coordlist;
- if ( this.cubic ) {
- director.ctx.bezierCurveTo(
- cc[1].x,
- cc[1].y,
- cc[2].x,
- cc[2].y,
- cc[3].x,
- cc[3].y
- );
- } else {
- director.ctx.quadraticCurveTo(
- cc[1].x,
- cc[1].y,
- cc[2].x,
- cc[2].y
- );
- }
- return this;
- },
- isQuadric : function() {
- return !this.cubic;
- },
- isCubic : function() {
- return this.cubic;
- },
- /**
- * Set this curve as a cubic bezier defined by the given four control points.
- * @param cp0x {number}
- * @param cp0y {number}
- * @param cp1x {number}
- * @param cp1y {number}
- * @param cp2x {number}
- * @param cp2y {number}
- * @param cp3x {number}
- * @param cp3y {number}
- */
- setCubic : function( cp0x,cp0y, cp1x,cp1y, cp2x,cp2y, cp3x,cp3y ) {
-
- this.coordlist= [];
-
- this.coordlist.push( new CAAT.Point().set(cp0x, cp0y ) );
- this.coordlist.push( new CAAT.Point().set(cp1x, cp1y ) );
- this.coordlist.push( new CAAT.Point().set(cp2x, cp2y ) );
- this.coordlist.push( new CAAT.Point().set(cp3x, cp3y ) );
-
- this.cubic= true;
- this.update();
- return this;
- },
- /**
- * Set this curve as a quadric bezier defined by the three control points.
- * @param cp0x {number}
- * @param cp0y {number}
- * @param cp1x {number}
- * @param cp1y {number}
- * @param cp2x {number}
- * @param cp2y {number}
- */
- setQuadric : function(cp0x,cp0y, cp1x,cp1y, cp2x,cp2y ) {
-
- this.coordlist= [];
-
- this.coordlist.push( new CAAT.Point().set(cp0x, cp0y ) );
- this.coordlist.push( new CAAT.Point().set(cp1x, cp1y ) );
- this.coordlist.push( new CAAT.Point().set(cp2x, cp2y ) );
-
- this.cubic= false;
- this.update();
- return this;
- },
- setPoints : function( points ) {
- if ( points.length===3 ) {
- this.coordlist= points;
- this.cubic= false;
- this.update();
- } else if (points.length===4 ) {
- this.coordlist= points;
- this.cubic= true;
- this.update();
- } else {
- throw 'points must be an array of 3 or 4 CAAT.Point instances.'
- }
- return this;
- },
- /**
- * Paint this curve.
- * @param director {CAAT.Director}
- */
- paint : function( director ) {
- if ( this.cubic ) {
- this.paintCubic(director);
- } else {
- this.paintCuadric( director );
- }
-
- CAAT.Bezier.superclass.paint.call(this,director);
- },
- /**
- * Paint this quadric Bezier curve. Each time the curve is drawn it will be solved again from 0 to 1 with
- * CAAT.Bezier.k increments.
- *
- * @param director {CAAT.Director}
- * @private
- */
- paintCuadric : function( director ) {
- var x1,y1;
- x1 = this.coordlist[0].x;
- y1 = this.coordlist[0].y;
-
- var ctx= director.ctx;
-
- ctx.save();
- ctx.beginPath();
- ctx.moveTo(x1,y1);
-
- var point= new CAAT.Point();
- for(var t=this.k;t<=1+this.k;t+=this.k){
- this.solve(point,t);
- ctx.lineTo(point.x, point.y );
- }
-
- ctx.stroke();
- ctx.restore();
-
- },
- /**
- * Paint this cubic Bezier curve. Each time the curve is drawn it will be solved again from 0 to 1 with
- * CAAT.Bezier.k increments.
- *
- * @param director {CAAT.Director}
- * @private
- */
- paintCubic : function( director ) {
- var x1,y1;
- x1 = this.coordlist[0].x;
- y1 = this.coordlist[0].y;
-
- var ctx= director.ctx;
-
- ctx.save();
- ctx.beginPath();
- ctx.moveTo(x1,y1);
-
- var point= new CAAT.Point();
- for(var t=this.k;t<=1+this.k;t+=this.k){
- this.solve(point,t);
- ctx.lineTo(point.x, point.y );
- }
-
- ctx.stroke();
- ctx.restore();
- },
- /**
- * Solves the curve for any given parameter t.
- * @param point {CAAT.Point} the point to store the solved value on the curve.
- * @param t {number} a number in the range 0..1
- */
- solve : function(point,t) {
- if ( this.cubic ) {
- return this.solveCubic(point,t);
- } else {
- return this.solveQuadric(point,t);
- }
- },
- /**
- * Solves a cubic Bezier.
- * @param point {CAAT.Point} the point to store the solved value on the curve.
- * @param t {number} the value to solve the curve for.
- */
- solveCubic : function(point,t) {
-
- var t2= t*t;
- var t3= t*t2;
- var cl= this.coordlist;
- var cl0= cl[0];
- var cl1= cl[1];
- var cl2= cl[2];
- var cl3= cl[3];
- point.x=(
- cl0.x + t * (-cl0.x * 3 + t * (3 * cl0.x-
- cl0.x*t)))+t*(3*cl1.x+t*(-6*cl1.x+
- cl1.x*3*t))+t2*(cl2.x*3-cl2.x*3*t)+
- cl3.x * t3;
-
- point.y=(
- cl0.y+t*(-cl0.y*3+t*(3*cl0.y-
- cl0.y*t)))+t*(3*cl1.y+t*(-6*cl1.y+
- cl1.y*3*t))+t2*(cl2.y*3-cl2.y*3*t)+
- cl3.y * t3;
-
- return point;
- },
- /**
- * Solves a quadric Bezier.
- * @param point {CAAT.Point} the point to store the solved value on the curve.
- * @param t {number} the value to solve the curve for.
- */
- solveQuadric : function(point,t) {
- var cl= this.coordlist;
- var cl0= cl[0];
- var cl1= cl[1];
- var cl2= cl[2];
- var t1= 1-t;
- point.x= t1*t1*cl0.x + 2*t1*t*cl1.x + t*t*cl2.x;
- point.y= t1*t1*cl0.y + 2*t1*t*cl1.y + t*t*cl2.y;
-
- return point;
- }
- };
- extend(CAAT.Bezier, CAAT.Curve, null);
-
- })();
- (function() {
- /**
- * CatmullRom curves solver implementation.
- * <p>
- * This object manages one single catmull rom segment, that is 4 points.
- * A complete spline should be managed with CAAT.Path.setCatmullRom with a complete list of points.
- *
- * @constructor
- * @extends CAAT.Curve
- */
- CAAT.CatmullRom = function() {
- CAAT.CatmullRom.superclass.constructor.call(this);
- return this;
- };
-
- CAAT.CatmullRom.prototype= {
- /**
- * Set curve control points.
- * @param p0 <CAAT.Point>
- * @param p1 <CAAT.Point>
- * @param p2 <CAAT.Point>
- * @param p3 <CAAT.Point>
- */
- setCurve : function( p0, p1, p2, p3 ) {
- this.coordlist= [];
- this.coordlist.push( p0 );
- this.coordlist.push( p1 );
- this.coordlist.push( p2 );
- this.coordlist.push( p3 );
- this.update();
- return this;
- },
- /**
- * Paint the contour by solving again the entire curve.
- * @param director {CAAT.Director}
- */
- paint: function(director) {
-
- var x1,y1;
- // Catmull rom solves from point 1 !!!
- x1 = this.coordlist[1].x;
- y1 = this.coordlist[1].y;
-
- var ctx= director.ctx;
-
- ctx.save();
- ctx.beginPath();
- ctx.moveTo(x1,y1);
-
- var point= new CAAT.Point();
- for(var t=this.k;t<=1+this.k;t+=this.k){
- this.solve(point,t);
- ctx.lineTo(point.x,point.y);
- }
-
- ctx.stroke();
- ctx.restore();
-
- CAAT.CatmullRom.superclass.paint.call(this,director);
- },
- /**
- * Solves the curve for any given parameter t.
- * @param point {CAAT.Point} the point to store the solved value on the curve.
- * @param t {number} a number in the range 0..1
- */
- solve: function(point,t) {
- var c= this.coordlist;
- // Handy from CAKE. Thanks.
- var af = ((-t+2)*t-1)*t*0.5
- var bf = (((3*t-5)*t)*t+2)*0.5
- var cf = ((-3*t+4)*t+1)*t*0.5
- var df = ((t-1)*t*t)*0.5
- point.x= c[0].x * af + c[1].x * bf + c[2].x * cf + c[3].x * df;
- point.y= c[0].y * af + c[1].y * bf + c[2].y * cf + c[3].y * df;
- return point;
- },
- applyAsPath : function( director ) {
- var ctx= director.ctx;
- var point= new CAAT.Point();
- for(var t=this.k;t<=1+this.k;t+=this.k){
- this.solve(point,t);
- ctx.lineTo(point.x,point.y);
- }
- return this;
- },
- /**
- * Return the first curve control point.
- * @return {CAAT.Point}
- */
- endCurvePosition : function() {
- return this.coordlist[ this.coordlist.length-2 ];
- },
- /**
- * Return the last curve control point.
- * @return {CAAT.Point}
- */
- startCurvePosition : function() {
- return this.coordlist[ 1 ];
- }
- };
- extend(CAAT.CatmullRom, CAAT.Curve, null);
- })();/**
- * See LICENSE file.
- *
- * Hold a 2D point information.
- * Think about the possibility of turning CAAT.Point into {x:,y:}.
- *
- **/
- (function() {
- /**
- *
- * A point defined by two coordinates.
- *
- * @param xpos {number}
- * @param ypos {number}
- *
- * @constructor
- */
- CAAT.Point= function(xpos, ypos, zpos) {
- this.x= xpos;
- this.y= ypos;
- this.z= zpos||0;
- return this;
- };
-
- CAAT.Point.prototype= {
- x: 0,
- y: 0,
- z: 0,
- /**
- * Sets this point coordinates.
- * @param x {number}
- * @param y {number}
- *
- * @return this
- */
- set : function(x,y,z) {
- this.x= x;
- this.y= y;
- this.z= z||0;
- return this;
- },
- /**
- * Create a new CAAT.Point equal to this one.
- * @return {CAAT.Point}
- */
- clone : function() {
- var p= new CAAT.Point(this.x, this.y, this.z );
- return p;
- },
- /**
- * Translate this point to another position. The final point will be (point.x+x, point.y+y)
- * @param x {number}
- * @param y {number}
- *
- * @return this
- */
- translate : function(x,y,z) {
- this.x+= x;
- this.y+= y;
- this.z+= z;
- return this;
- },
- /**
- * Translate this point to another point.
- * @param aPoint {CAAT.Point}
- * @return this
- */
- translatePoint: function(aPoint) {
- this.x += aPoint.x;
- this.y += aPoint.y;
- this.z += aPoint.z;
- return this;
- },
- /**
- * Substract a point from this one.
- * @param aPoint {CAAT.Point}
- * @return this
- */
- subtract: function(aPoint) {
- this.x -= aPoint.x;
- this.y -= aPoint.y;
- this.z -= aPoint.z;
- return this;
- },
- /**
- * Multiply this point by a scalar.
- * @param factor {number}
- * @return this
- */
- multiply: function(factor) {
- this.x *= factor;
- this.y *= factor;
- this.z *= factor;
- return this;
- },
- /**
- * Rotate this point by an angle. The rotation is held by (0,0) coordinate as center.
- * @param angle {number}
- * @return this
- */
- rotate: function(angle) {
- var x = this.x, y = this.y;
- this.x = x * Math.cos(angle) - Math.sin(angle) * y;
- this.y = x * Math.sin(angle) + Math.cos(angle) * y;
- this.z = 0;
- return this;
- },
- /**
- *
- * @param angle {number}
- * @return this
- */
- setAngle: function(angle) {
- var len = this.getLength();
- this.x = Math.cos(angle) * len;
- this.y = Math.sin(angle) * len;
- this.z = 0;
- return this;
- },
- /**
- *
- * @param length {number}
- * @return this
- */
- setLength: function(length) {
- var len = this.getLength();
- if (len)this.multiply(length / len);
- else this.x = this.y = this.z = length;
- return this;
- },
- /**
- * Normalize this point, that is, both set coordinates proportionally to values raning 0..1
- * @return this
- */
- normalize: function() {
- var len = this.getLength();
- this.x /= len;
- this.y /= len;
- this.z /= len;
- return this;
- },
- /**
- * Return the angle from -Pi to Pi of this point.
- * @return {number}
- */
- getAngle: function() {
- return Math.atan2(this.y, this.x);
- },
- /**
- * Set this point coordinates proportinally to a maximum value.
- * @param max {number}
- * @return this
- */
- limit: function(max) {
- var aLenthSquared = this.getLengthSquared();
- if(aLenthSquared+0.01 > max*max)
- {
- var aLength = Math.sqrt(aLenthSquared);
- this.x= (this.x/aLength) * max;
- this.y= (this.y/aLength) * max;
- this.z= (this.z/aLength) * max;
- }
- return this;
- },
- /**
- * Get this point's lenght.
- * @return {number}
- */
- getLength: function() {
- var length = Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z);
- if ( length < 0.005 && length > -0.005) return 0.000001;
- return length;
- },
- /**
- * Get this point's squared length.
- * @return {number}
- */
- getLengthSquared: function() {
- var lengthSquared = this.x*this.x + this.y*this.y + this.z*this.z;
- if ( lengthSquared < 0.005 && lengthSquared > -0.005) return 0;
- return lengthSquared;
- },
- /**
- * Get the distance between two points.
- * @param point {CAAT.Point}
- * @return {number}
- */
- getDistance: function(point) {
- var deltaX = this.x - point.x;
- var deltaY = this.y - point.y;
- var deltaZ = this.z - point.z;
- return Math.sqrt( deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ );
- },
- /**
- * Get the squared distance between two points.
- * @param point {CAAT.Point}
- * @return {number}
- */
- getDistanceSquared: function(point) {
- var deltaX = this.x - point.x;
- var deltaY = this.y - point.y;
- var deltaZ = this.z - point.z;
- return deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ;
- },
- /**
- * Get a string representation.
- * @return {string}
- */
- toString: function() {
- return "(CAAT.Point)" +
- " x:" + String(Math.round(Math.floor(this.x*10))/10) +
- " y:" + String(Math.round(Math.floor(this.y*10))/10) +
- " z:" + String(Math.round(Math.floor(this.z*10))/10);
- }
- };
- })();/**
- * See LICENSE file.
- *
- * This file contains the definition for objects QuadTree and HashMap.
- * Quadtree offers an exact list of collisioning areas, while HashMap offers a list of potentially colliding elements.
- *
- **/
- (function() {
- CAAT.QuadTree= function() {
- return this;
- };
- var QT_MAX_ELEMENTS= 1;
- var QT_MIN_WIDTH= 32;
- CAAT.QuadTree.prototype= {
- bgActors : null,
- quadData : null,
- create : function( l,t, r,b, backgroundElements, minWidth, maxElements ) {
- if ( typeof minWidth==='undefined' ) {
- minWidth= QT_MIN_WIDTH;
- }
- if ( typeof maxElements==='undefined' ) {
- maxElements= QT_MAX_ELEMENTS;
- }
- var cx= (l+r)/2;
- var cy= (t+b)/2;
- this.x= l;
- this.y= t;
- this.x1= r;
- this.y1= b;
- this.width= r-l;
- this.height= b-t;
- this.bgActors= this.__getOverlappingActorList( backgroundElements );
- if ( this.bgActors.length <= maxElements || this.width <= minWidth ) {
- return this;
- }
- this.quadData= new Array(4);
- this.quadData[0]= new CAAT.QuadTree().create( l,t,cx,cy, this.bgActors ); // TL
- this.quadData[1]= new CAAT.QuadTree().create( cx,t,r,cy, this.bgActors ); // TR
- this.quadData[2]= new CAAT.QuadTree().create( l,cy,cx,b, this.bgActors ); // BL
- this.quadData[3]= new CAAT.QuadTree().create( cx,cy,r,b, this.bgActors );
- return this;
- },
- __getOverlappingActorList : function( actorList ) {
- var tmpList= [];
- for( var i=0, l=actorList.length; i<l; i++ ) {
- var actor= actorList[i];
- if ( this.intersects( actor.AABB ) ) {
- tmpList.push( actor );
- }
- }
- return tmpList;
- },
- getOverlappingActors : function( rectangle ) {
- var i,j,l;
- var overlappingActors= [];
- var qoverlappingActors;
- var actors= this.bgActors;
- var actor;
- if ( this.quadData ) {
- for( i=0; i<4; i++ ) {
- if ( this.quadData[i].intersects( rectangle ) ) {
- qoverlappingActors= this.quadData[i].getOverlappingActors(rectangle);
- for( j=0,l=qoverlappingActors.length; j<l; j++ ) {
- overlappingActors.push( qoverlappingActors[j] );
- }
- }
- }
- } else {
- for( i=0, l=actors.length; i<l; i++ ) {
- actor= actors[i];
- if ( rectangle.intersects( actor.AABB ) ) {
- overlappingActors.push( actor );
- }
- }
- }
- return overlappingActors;
- }
- };
- extend( CAAT.QuadTree, CAAT.Rectangle );
- })();
- (function() {
- CAAT.SpatialHash= function() {
- return this;
- };
- CAAT.SpatialHash.prototype= {
- elements : null,
- width : null,
- height : null,
- rows : null,
- columns : null,
- xcache : null,
- ycache : null,
- xycache : null,
- rectangle : null,
- r0 : null,
- r1 : null,
- initialize : function( w,h, rows,columns ) {
- var i, j;
- this.elements= [];
- for( i=0; i<rows*columns; i++ ) {
- this.elements.push( [] );
- }
- this.width= w;
- this.height= h;
- this.rows= rows;
- this.columns= columns;
- this.xcache= [];
- for( i=0; i<w; i++ ) {
- this.xcache.push( (i/(w/columns))>>0 );
- }
- this.ycache= [];
- for( i=0; i<h; i++ ) {
- this.ycache.push( (i/(h/rows))>>0 );
- }
- this.xycache=[];
- for( i=0; i<this.rows; i++ ) {
- this.xycache.push( [] );
- for( j=0; j<this.columns; j++ ) {
- this.xycache[i].push( j + i*columns );
- }
- }
- this.rectangle= new CAAT.Rectangle().setBounds( 0, 0, w, h );
- this.r0= new CAAT.Rectangle();
- this.r1= new CAAT.Rectangle();
- return this;
- },
- clearObject : function() {
- var i;
- for( i=0; i<this.rows*this.columns; i++ ) {
- this.elements[i]= [];
- }
- return this;
- },
- /**
- * Add an element of the form { id, x,y,width,height, rectangular }
- */
- addObject : function( obj ) {
- var x= obj.x|0;
- var y= obj.y|0;
- var width= obj.width|0;
- var height= obj.height|0;
- var cells= this.__getCells( x,y,width,height );
- for( var i=0; i<cells.length; i++ ) {
- this.elements[ cells[i] ].push( obj );
- }
- },
- __getCells : function( x,y,width,height ) {
- var cells= [];
- var i;
- if ( this.rectangle.contains(x,y) ) {
- cells.push( this.xycache[ this.ycache[y] ][ this.xcache[x] ] );
- }
- /**
- * if both squares lay inside the same cell, it is not crossing a boundary.
- */
- if ( this.rectangle.contains(x+width-1,y+height-1) ) {
- var c= this.xycache[ this.ycache[y+height-1] ][ this.xcache[x+width-1] ];
- if ( c===cells[0] ) {
- return cells;
- }
- cells.push( c );
- }
- /**
- * the other two AABB points lie inside the screen as well.
- */
- if ( this.rectangle.contains(x+width-1,y) ) {
- var c= this.xycache[ this.ycache[y] ][ this.xcache[x+width-1] ];
- if ( c===cells[0] || c===cells[1] ) {
- return cells;
- }
- cells.push(c);
- }
- // worst case, touching 4 screen cells.
- if ( this.rectangle.contains(x+width-1,y+height-1) ) {
- var c= this.xycache[ this.ycache[y+height-1] ][ this.xcache[x] ];
- cells.push(c);
- }
- return cells;
- },
- solveCollision : function( callback ) {
- var i,j,k;
- for( i=0; i<this.elements.length; i++ ) {
- var cell= this.elements[i];
- if ( cell.length>1 ) { // at least 2 elements could collide
- this._solveCollisionCell( cell, callback );
- }
- }
- },
- _solveCollisionCell : function( cell, callback ) {
- var i,j;
- for( i=0; i<cell.length; i++ ) {
- var pivot= cell[i];
- this.r0.setBounds( pivot.x, pivot.y, pivot.width, pivot.height );
- for( j=i+1; j<cell.length; j++ ) {
- var c= cell[j];
- if ( this.r0.intersects( this.r1.setBounds( c.x, c.y, c.width, c.height ) ) ) {
- callback( pivot, c );
- }
- }
- }
- },
- /**
- *
- * @param x
- * @param y
- * @param w
- * @param h
- * @param oncollide function that returns boolean. if returns true, stop testing collision.
- */
- collide : function( x,y,w,h, oncollide ) {
- x|=0;
- y|=0;
- w|=0;
- h|=0;
- var cells= this.__getCells( x,y,w,h );
- var i,j,l;
- var el= this.elements;
- this.r0.setBounds( x,y,w,h );
- for( i=0; i<cells.length; i++ ) {
- var cell= cells[i];
- var elcell= el[cell];
- for( j=0, l=elcell.length; j<l; j++ ) {
- var obj= elcell[j];
- this.r1.setBounds( obj.x, obj.y, obj.width, obj.height );
- // collides
- if ( this.r0.intersects( this.r1 ) ) {
- if ( oncollide(obj) ) {
- return;
- }
- }
- }
- }
- }
- };
- })();/**
- * See LICENSE file.
- *
- * Generate interpolator.
- *
- * Partially based on Robert Penner easing equations.
- * http://www.robertpenner.com/easing/
- *
- *
- **/
- (function() {
- /**
- * a CAAT.Interpolator is a function which transforms a value into another but with some constraints:
- *
- * <ul>
- * <li>The input values must be between 0 and 1.
- * <li>Output values will be between 0 and 1.
- * <li>Every Interpolator has at least an entering boolean parameter called pingpong. if set to true, the Interpolator
- * will set values from 0..1 and back from 1..0. So half the time for each range.
- * </ul>
- *
- * <p>
- * CAAt.Interpolator is defined by a createXXXX method which sets up an internal getPosition(time)
- * function. You could set as an Interpolator up any object which exposes a method getPosition(time)
- * and returns a CAAT.Point or an object of the form {x:{number}, y:{number}}.
- * <p>
- * In the return value, the x attribute's value will be the same value as that of the time parameter,
- * and y attribute will hold a value between 0 and 1 with the resulting value of applying the
- * interpolation function for the time parameter.
- *
- * <p>
- * For am exponential interpolation, the getPosition function would look like this:
- * <code>function getPosition(time) { return { x:time, y: Math.pow(time,2) }�}</code>.
- * meaning that for time=0.5, a value of 0,5*0,5 should use instead.
- *
- * <p>
- * For a visual understanding of interpolators see tutorial 4 interpolators, or play with technical
- * demo 1 where a SpriteActor moves along a path and the way it does can be modified by every
- * out-of-the-box interpolator.
- *
- * @constructor
- *
- */
- CAAT.Interpolator = function() {
- this.interpolated= new CAAT.Point(0,0,0);
- return this;
- };
- CAAT.Interpolator.prototype= {
- interpolated: null, // a coordinate holder for not building a new CAAT.Point for each interpolation call.
- paintScale: 90, // the size of the interpolation draw on screen in pixels.
- /**
- * Set a linear interpolation function.
- *
- * @param bPingPong {boolean}
- * @param bInverse {boolean} will values will be from 1 to 0 instead of 0 to 1 ?.
- */
- createLinearInterpolator : function(bPingPong, bInverse) {
- /**
- * Linear and inverse linear interpolation function.
- * @param time {number}
- */
- this.getPosition= function getPosition(time) {
- var orgTime= time;
- if ( bPingPong ) {
- if ( time<0.5 ) {
- time*=2;
- } else {
- time= 1-(time-0.5)*2;
- }
- }
- if ( bInverse!==null && bInverse ) {
- time= 1-time;
- }
- return this.interpolated.set(orgTime,time);
- };
- return this;
- },
- createBackOutInterpolator : function(bPingPong) {
- this.getPosition= function getPosition(time) {
- var orgTime= time;
- if ( bPingPong ) {
- if ( time<0.5 ) {
- time*=2;
- } else {
- time= 1-(time-0.5)*2;
- }
- }
- time = time - 1;
- var overshoot= 1.70158;
- return this.interpolated.set(
- orgTime,
- time * time * ((overshoot + 1) * time + overshoot) + 1);
- };
- return this;
- },
- /**
- * Set an exponential interpolator function. The function to apply will be Math.pow(time,exponent).
- * This function starts with 0 and ends in values of 1.
- *
- * @param exponent {number} exponent of the function.
- * @param bPingPong {boolean}
- */
- createExponentialInInterpolator : function(exponent, bPingPong) {
- this.getPosition= function getPosition(time) {
- var orgTime= time;
- if ( bPingPong ) {
- if ( time<0.5 ) {
- time*=2;
- } else {
- time= 1-(time-0.5)*2;
- }
- }
- return this.interpolated.set(orgTime,Math.pow(time,exponent));
- };
- return this;
- },
- /**
- * Set an exponential interpolator function. The function to apply will be 1-Math.pow(time,exponent).
- * This function starts with 1 and ends in values of 0.
- *
- * @param exponent {number} exponent of the function.
- * @param bPingPong {boolean}
- */
- createExponentialOutInterpolator : function(exponent, bPingPong) {
- this.getPosition= function getPosition(time) {
- var orgTime= time;
- if ( bPingPong ) {
- if ( time<0.5 ) {
- time*=2;
- } else {
- time= 1-(time-0.5)*2;
- }
- }
- return this.interpolated.set(orgTime,1-Math.pow(1-time,exponent));
- };
- return this;
- },
- /**
- * Set an exponential interpolator function. Two functions will apply:
- * Math.pow(time*2,exponent)/2 for the first half of the function (t<0.5) and
- * 1-Math.abs(Math.pow(time*2-2,exponent))/2 for the second half (t>=.5)
- * This function starts with 0 and goes to values of 1 and ends with values of 0.
- *
- * @param exponent {number} exponent of the function.
- * @param bPingPong {boolean}
- */
- createExponentialInOutInterpolator : function(exponent, bPingPong) {
- this.getPosition= function getPosition(time) {
- var orgTime= time;
- if ( bPingPong ) {
- if ( time<0.5 ) {
- time*=2;
- } else {
- time= 1-(time-0.5)*2;
- }
- }
- if ( time*2<1 ) {
- return this.interpolated.set(orgTime,Math.pow(time*2,exponent)/2);
- }
-
- return this.interpolated.set(orgTime,1-Math.abs(Math.pow(time*2-2,exponent))/2);
- };
- return this;
- },
- /**
- * Creates a Quadric bezier curbe as interpolator.
- *
- * @param p0 {CAAT.Point} a CAAT.Point instance.
- * @param p1 {CAAT.Point} a CAAT.Point instance.
- * @param p2 {CAAT.Point} a CAAT.Point instance.
- * @param bPingPong {boolean} a boolean indicating if the interpolator must ping-pong.
- */
- createQuadricBezierInterpolator : function(p0,p1,p2,bPingPong) {
- this.getPosition= function getPosition(time) {
- var orgTime= time;
- if ( bPingPong ) {
- if ( time<0.5 ) {
- time*=2;
- } else {
- time= 1-(time-0.5)*2;
- }
- }
- time= (1-time)*(1-time)*p0.y + 2*(1-time)*time*p1.y + time*time*p2.y;
- return this.interpolated.set( orgTime, time );
- };
- return this;
- },
- /**
- * Creates a Cubic bezier curbe as interpolator.
- *
- * @param p0 {CAAT.Point} a CAAT.Point instance.
- * @param p1 {CAAT.Point} a CAAT.Point instance.
- * @param p2 {CAAT.Point} a CAAT.Point instance.
- * @param p3 {CAAT.Point} a CAAT.Point instance.
- * @param bPingPong {boolean} a boolean indicating if the interpolator must ping-pong.
- */
- createCubicBezierInterpolator : function(p0,p1,p2,p3,bPingPong) {
- this.getPosition= function getPosition(time) {
- var orgTime= time;
- if ( bPingPong ) {
- if ( time<0.5 ) {
- time*=2;
- } else {
- time= 1-(time-0.5)*2;
- }
- }
- var t2= time*time;
- var t3= time*t2;
- time = (p0.y + time * (-p0.y * 3 + time * (3 * p0.y -
- p0.y * time))) + time * (3 * p1.y + time * (-6 * p1.y +
- p1.y * 3 * time)) + t2 * (p2.y * 3 - p2.y * 3 * time) +
- p3.y * t3;
- return this.interpolated.set( orgTime, time );
- };
- return this;
- },
- createElasticOutInterpolator : function(amplitude,p,bPingPong) {
- this.getPosition= function getPosition(time) {
- if ( bPingPong ) {
- if ( time<0.5 ) {
- time*=2;
- } else {
- time= 1-(time-0.5)*2;
- }
- }
- if (time === 0) {
- return {x:0,y:0};
- }
- if (time === 1) {
- return {x:1,y:1};
- }
- var s = p/(2*Math.PI) * Math.asin (1/amplitude);
- return this.interpolated.set(
- time,
- (amplitude*Math.pow(2,-10*time) * Math.sin( (time-s)*(2*Math.PI)/p ) + 1 ) );
- };
- return this;
- },
- createElasticInInterpolator : function(amplitude,p,bPingPong) {
- this.getPosition= function getPosition(time) {
- if ( bPingPong ) {
- if ( time<0.5 ) {
- time*=2;
- } else {
- time= 1-(time-0.5)*2;
- }
- }
- if (time === 0) {
- return {x:0,y:0};
- }
- if (time === 1) {
- return {x:1,y:1};
- }
- var s = p/(2*Math.PI) * Math.asin (1/amplitude);
- return this.interpolated.set(
- time,
- -(amplitude*Math.pow(2,10*(time-=1)) * Math.sin( (time-s)*(2*Math.PI)/p ) ) );
- };
- return this;
- },
- createElasticInOutInterpolator : function(amplitude,p,bPingPong) {
- this.getPosition= function getPosition(time) {
- if ( bPingPong ) {
- if ( time<0.5 ) {
- time*=2;
- } else {
- time= 1-(time-0.5)*2;
- }
- }
- var s = p/(2*Math.PI) * Math.asin (1/amplitude);
- time*=2;
- if ( time<=1 ) {
- return this.interpolated.set(
- time,
- -0.5*(amplitude*Math.pow(2,10*(time-=1)) * Math.sin( (time-s)*(2*Math.PI)/p )));
- }
- return this.interpolated.set(
- time,
- 1+0.5*(amplitude*Math.pow(2,-10*(time-=1)) * Math.sin( (time-s)*(2*Math.PI)/p )));
- };
- return this;
- },
- /**
- * @param time {number}
- * @private
- */
- bounce : function(time) {
- if ((time /= 1) < (1 / 2.75)) {
- return {x:time, y:7.5625 * time * time};
- } else if (time < (2 / 2.75)) {
- return {x:time, y:7.5625 * (time -= (1.5 / 2.75)) * time + 0.75};
- } else if (time < (2.5 / 2.75)) {
- return {x:time, y:7.5625 * (time -= (2.25 / 2.75)) * time + 0.9375};
- } else {
- return {x:time, y:7.5625*(time-=(2.625/2.75))*time+0.984375};
- }
- },
- createBounceOutInterpolator : function(bPingPong) {
- this.getPosition= function getPosition(time) {
- if ( bPingPong ) {
- if ( time<0.5 ) {
- time*=2;
- } else {
- time= 1-(time-0.5)*2;
- }
- }
- return this.bounce(time);
- };
- return this;
- },
- createBounceInInterpolator : function(bPingPong) {
- this.getPosition= function getPosition(time) {
- if ( bPingPong ) {
- if ( time<0.5 ) {
- time*=2;
- } else {
- time= 1-(time-0.5)*2;
- }
- }
- var r= this.bounce(1-time);
- r.y= 1-r.y;
- return r;
- };
- return this;
- },
- createBounceInOutInterpolator : function(bPingPong) {
- this.getPosition= function getPosition(time) {
- if ( bPingPong ) {
- if ( time<0.5 ) {
- time*=2;
- } else {
- time= 1-(time-0.5)*2;
- }
- }
- var r;
- if (time < 0.5) {
- r= this.bounce(1 - time * 2);
- r.y= (1 - r.y)* 0.5;
- return r;
- }
- r= this.bounce(time * 2 - 1,bPingPong);
- r.y= r.y* 0.5 + 0.5;
- return r;
- };
- return this;
- },
- /**
- * Paints an interpolator on screen.
- * @param director {CAAT.Director} a CAAT.Director instance.
- * @param time {number} an integer indicating the scene time the Interpolator will be drawn at. This value is useless.
- */
- paint : function(director,time) {
- var canvas= director.crc;
- canvas.save();
- canvas.beginPath();
- canvas.moveTo( 0, this.getPosition(0).y * this.paintScale );
- for( var i=0; i<=this.paintScale; i++ ) {
- canvas.lineTo( i, this.getPosition(i/this.paintScale).y * this.paintScale );
- }
- canvas.strokeStyle='black';
- canvas.stroke();
- canvas.restore();
- },
- /**
- * Gets an array of coordinates which define the polyline of the intepolator's curve contour.
- * Values for both coordinates range from 0 to 1.
- * @param iSize {number} an integer indicating the number of contour segments.
- * @return array {[CAAT.Point]} of object of the form {x:float, y:float}.
- */
- getContour : function(iSize) {
- var contour=[];
- for( var i=0; i<=iSize; i++ ) {
- contour.push( {x: i/iSize, y: this.getPosition(i/iSize).y} );
- }
- return contour;
- },
- /**
- *
- */
- enumerateInterpolators : function() {
- return [
- new CAAT.Interpolator().createLinearInterpolator(false, false), 'Linear pingpong=false, inverse=false',
- new CAAT.Interpolator().createLinearInterpolator(true, false), 'Linear pingpong=true, inverse=false',
- new CAAT.Interpolator().createLinearInterpolator(false, true), 'Linear pingpong=false, inverse=true',
- new CAAT.Interpolator().createLinearInterpolator(true, true), 'Linear pingpong=true, inverse=true',
- new CAAT.Interpolator().createExponentialInInterpolator( 2, false), 'ExponentialIn pingpong=false, exponent=2',
- new CAAT.Interpolator().createExponentialOutInterpolator( 2, false), 'ExponentialOut pingpong=false, exponent=2',
- new CAAT.Interpolator().createExponentialInOutInterpolator( 2, false), 'ExponentialInOut pingpong=false, exponent=2',
- new CAAT.Interpolator().createExponentialInInterpolator( 2, true), 'ExponentialIn pingpong=true, exponent=2',
- new CAAT.Interpolator().createExponentialOutInterpolator( 2, true), 'ExponentialOut pingpong=true, exponent=2',
- new CAAT.Interpolator().createExponentialInOutInterpolator( 2, true), 'ExponentialInOut pingpong=true, exponent=2',
- new CAAT.Interpolator().createExponentialInInterpolator( 4, false), 'ExponentialIn pingpong=false, exponent=4',
- new CAAT.Interpolator().createExponentialOutInterpolator( 4, false), 'ExponentialOut pingpong=false, exponent=4',
- new CAAT.Interpolator().createExponentialInOutInterpolator( 4, false), 'ExponentialInOut pingpong=false, exponent=4',
- new CAAT.Interpolator().createExponentialInInterpolator( 4, true), 'ExponentialIn pingpong=true, exponent=4',
- new CAAT.Interpolator().createExponentialOutInterpolator( 4, true), 'ExponentialOut pingpong=true, exponent=4',
- new CAAT.Interpolator().createExponentialInOutInterpolator( 4, true), 'ExponentialInOut pingpong=true, exponent=4',
- new CAAT.Interpolator().createExponentialInInterpolator( 6, false), 'ExponentialIn pingpong=false, exponent=6',
- new CAAT.Interpolator().createExponentialOutInterpolator( 6, false), 'ExponentialOut pingpong=false, exponent=6',
- new CAAT.Interpolator().createExponentialInOutInterpolator( 6, false), 'ExponentialInOut pingpong=false, exponent=6',
- new CAAT.Interpolator().createExponentialInInterpolator( 6, true), 'ExponentialIn pingpong=true, exponent=6',
- new CAAT.Interpolator().createExponentialOutInterpolator( 6, true), 'ExponentialOut pingpong=true, exponent=6',
- new CAAT.Interpolator().createExponentialInOutInterpolator( 6, true), 'ExponentialInOut pingpong=true, exponent=6',
- new CAAT.Interpolator().createBounceInInterpolator(false), 'BounceIn pingpong=false',
- new CAAT.Interpolator().createBounceOutInterpolator(false), 'BounceOut pingpong=false',
- new CAAT.Interpolator().createBounceInOutInterpolator(false), 'BounceInOut pingpong=false',
- new CAAT.Interpolator().createBounceInInterpolator(true), 'BounceIn pingpong=true',
- new CAAT.Interpolator().createBounceOutInterpolator(true), 'BounceOut pingpong=true',
- new CAAT.Interpolator().createBounceInOutInterpolator(true), 'BounceInOut pingpong=true',
- new CAAT.Interpolator().createElasticInInterpolator( 1.1, 0.4, false), 'ElasticIn pingpong=false, amp=1.1, d=.4',
- new CAAT.Interpolator().createElasticOutInterpolator( 1.1, 0.4, false), 'ElasticOut pingpong=false, amp=1.1, d=.4',
- new CAAT.Interpolator().createElasticInOutInterpolator( 1.1, 0.4, false), 'ElasticInOut pingpong=false, amp=1.1, d=.4',
- new CAAT.Interpolator().createElasticInInterpolator( 1.1, 0.4, true), 'ElasticIn pingpong=true, amp=1.1, d=.4',
- new CAAT.Interpolator().createElasticOutInterpolator( 1.1, 0.4, true), 'ElasticOut pingpong=true, amp=1.1, d=.4',
- new CAAT.Interpolator().createElasticInOutInterpolator( 1.1, 0.4, true), 'ElasticInOut pingpong=true, amp=1.1, d=.4',
- new CAAT.Interpolator().createElasticInInterpolator( 1.0, 0.2, false), 'ElasticIn pingpong=false, amp=1.0, d=.2',
- new CAAT.Interpolator().createElasticOutInterpolator( 1.0, 0.2, false), 'ElasticOut pingpong=false, amp=1.0, d=.2',
- new CAAT.Interpolator().createElasticInOutInterpolator( 1.0, 0.2, false), 'ElasticInOut pingpong=false, amp=1.0, d=.2',
- new CAAT.Interpolator().createElasticInInterpolator( 1.0, 0.2, true), 'ElasticIn pingpong=true, amp=1.0, d=.2',
- new CAAT.Interpolator().createElasticOutInterpolator( 1.0, 0.2, true), 'ElasticOut pingpong=true, amp=1.0, d=.2',
- new CAAT.Interpolator().createElasticInOutInterpolator( 1.0, 0.2, true), 'ElasticInOut pingpong=true, amp=1.0, d=.2'
- ];
- }
- };
- })();
- /**
- * See LICENSE file.
- *
- * Behaviors are keyframing elements.
- * By using a BehaviorContainer, you can specify different actions on any animation Actor.
- * An undefined number of Behaviors can be defined for each Actor.
- *
- * There're the following Behaviors:
- * + AlphaBehavior: controls container/actor global alpha.
- * + RotateBehavior: takes control of rotation affine transform.
- * + ScaleBehavior: takes control of scaling on x/y axis affine transform.
- * + PathBehavior: takes control of translating an Actor/ActorContainer across a path [ie. pathSegment collection].
- * + GenericBehavior: applies a behavior to any given target object's property, or notifies a callback.
- *
- *
- **/
- (function() {
- /**
- * Behavior base class.
- *
- * <p>
- * A behavior is defined by a frame time (behavior duration) and a behavior application function called interpolator.
- * In its default form, a behaviour is applied linearly, that is, the same amount of behavior is applied every same
- * time interval.
- * <p>
- * A concrete Behavior, a rotateBehavior in example, will change a concrete Actor's rotationAngle during the specified
- * period.
- * <p>
- * A behavior is guaranteed to notify (if any observer is registered) on behavior expiration.
- * <p>
- * A behavior can keep an unlimited observers. Observers are objects of the form:
- * <p>
- * <code>
- * {
- * behaviorExpired : function( behavior, time, actor);
- * behaviorApplied : function( behavior, time, normalizedTime, actor, value);
- * }
- * </code>
- * <p>
- * <strong>behaviorExpired</strong>: function( behavior, time, actor). This method will be called for any registered observer when
- * the scene time is greater than behavior's startTime+duration. This method will be called regardless of the time
- * granurality.
- * <p>
- * <strong>behaviorApplied</strong> : function( behavior, time, normalizedTime, actor, value). This method will be called once per
- * frame while the behavior is not expired and is in frame time (behavior startTime>=scene time). This method can be
- * called multiple times.
- * <p>
- * Every behavior is applied to a concrete Actor.
- * Every actor must at least define an start and end value. The behavior will set start-value at behaviorStartTime and
- * is guaranteed to apply end-value when scene time= behaviorStartTime+behaviorDuration.
- * <p>
- * You can set behaviors to apply forever that is cyclically. When a behavior is cycle=true, won't notify
- * behaviorExpired to its registered observers.
- * <p>
- * Other Behaviors simply must supply with the method <code>setForTime(time, actor)</code> overriden.
- *
- * @constructor
- */
- CAAT.Behavior= function() {
- this.lifecycleListenerList=[];
- this.setDefaultInterpolator();
- return this;
- };
- /**
- * @enum
- */
- CAAT.Behavior.Status= {
- NOT_STARTED: 0,
- STARTED: 1,
- EXPIRED: 2
- };
- var DefaultInterpolator= new CAAT.Interpolator().createLinearInterpolator(false);
- var DefaultPPInterpolator= new CAAT.Interpolator().createLinearInterpolator(true);
- CAAT.Behavior.prototype= {
-
- lifecycleListenerList: null, // observer list.
- behaviorStartTime: -1, // scene time to start applying the behavior
- behaviorDuration: -1, // behavior duration in ms.
- cycleBehavior: false, // apply forever ?
- status: CAAT.Behavior.NOT_STARTED,
- interpolator: null, // behavior application function. linear by default.
- actor: null, // actor the Behavior acts on.
- id: 0, // an integer id suitable to identify this behavior by number.
- timeOffset: 0,
- doValueApplication: true,
- solved : true,
- setValueApplication : function( apply ) {
- this.doValueApplication= apply;
- return this;
- },
- setTimeOffset : function( offset ) {
- this.timeOffset= offset;
- return this;
- },
- /**
- * Sets this behavior id.
- * @param id an integer.
- *
- */
- setId : function( id ) {
- this.id= id;
- return this;
- },
- /**
- * Sets the default interpolator to a linear ramp, that is, behavior will be applied linearly.
- * @return this
- */
- setDefaultInterpolator : function() {
- this.interpolator= DefaultInterpolator;
- return this;
- },
- /**
- * Sets default interpolator to be linear from 0..1 and from 1..0.
- * @return this
- */
- setPingPong : function() {
- this.interpolator= DefaultPPInterpolator;
- return this;
- },
- /**
- *
- * @param status {CAAT.Behavior.Status}
- */
- setStatus : function(status) {
- this.status= status;
- },
- /**
- * Sets behavior start time and duration.
- * Scene time will be the time of the scene the behavior actor is bound to.
- * @param startTime {number} an integer indicating behavior start time in scene time in ms..
- * @param duration {number} an integer indicating behavior duration in ms.
- */
- setFrameTime : function( startTime, duration ) {
- this.behaviorStartTime= startTime;
- this.behaviorDuration= duration;
- this.setStatus( CAAT.Behavior.Status.NOT_STARTED );
- return this;
- },
- /**
- * Sets behavior start time and duration but instead as setFrameTime which sets initial time as absolute time
- * regarding scene's time, it uses a relative time offset from current scene time.
- * a call to
- * setFrameTime( scene.time, duration ) is equivalent to
- * setDelayTime( 0, duration )
- * @param delay {number}
- * @param duration {number}
- */
- setDelayTime : function( delay, duration ) {
- this.behaviorStartTime= delay;
- this.behaviorDuration= duration;
- this.setStatus( CAAT.Behavior.Status.NOT_STARTED );
- this.solved= false;
- return this;
- },
- setOutOfFrameTime : function() {
- this.setStatus( CAAT.Behavior.Status.EXPIRED );
- this.behaviorStartTime= Number.MAX_VALUE;
- this.behaviorDuration= 0;
- return this;
- },
- /**
- * Changes behavior default interpolator to another instance of CAAT.Interpolator.
- * If the behavior is not defined by CAAT.Interpolator factory methods, the interpolation function must return
- * its values in the range 0..1. The behavior will only apply for such value range.
- * @param interpolator a CAAT.Interpolator instance.
- */
- setInterpolator : function(interpolator) {
- this.interpolator= interpolator;
- return this;
- },
- /**
- * This method must no be called directly.
- * The director loop will call this method in orther to apply actor behaviors.
- * @param time the scene time the behaviro is being applied at.
- * @param actor a CAAT.Actor instance the behavior is being applied to.
- */
- apply : function( time, actor ) {
- if ( !this.solved ) {
- this.behaviorStartTime+= time;
- this.solved= true;
- }
- time+= this.timeOffset*this.behaviorDuration;
- var orgTime= time;
- if ( this.isBehaviorInTime(time,actor) ) {
- time= this.normalizeTime(time);
- this.fireBehaviorAppliedEvent(
- actor,
- orgTime,
- time,
- this.setForTime( time, actor ) );
- }
- },
- /**
- * Sets the behavior to cycle, ie apply forever.
- * @param bool a boolean indicating whether the behavior is cycle.
- */
- setCycle : function(bool) {
- this.cycleBehavior= bool;
- return this;
- },
- /**
- * Adds an observer to this behavior.
- * @param behaviorListener an observer instance.
- */
- addListener : function( behaviorListener ) {
- this.lifecycleListenerList.push(behaviorListener);
- return this;
- },
- /**
- * Remove all registered listeners to the behavior.
- */
- emptyListenerList : function() {
- this.lifecycleListenerList= [];
- return this;
- },
- /**
- * @return an integer indicating the behavior start time in ms..
- */
- getStartTime : function() {
- return this.behaviorStartTime;
- },
- /**
- * @return an integer indicating the behavior duration time in ms.
- */
- getDuration : function() {
- return this.behaviorDuration;
-
- },
- /**
- * Chekcs whether the behaviour is in scene time.
- * In case it gets out of scene time, and has not been tagged as expired, the behavior is expired and observers
- * are notified about that fact.
- * @param time the scene time to check the behavior against.
- * @param actor the actor the behavior is being applied to.
- * @return a boolean indicating whether the behavior is in scene time.
- */
- isBehaviorInTime : function(time,actor) {
- var S= CAAT.Behavior.Status;
- if ( this.status===S.EXPIRED || this.behaviorStartTime<0 ) {
- return false;
- }
-
- if ( this.cycleBehavior ) {
- if ( time>=this.behaviorStartTime ) {
- time= (time-this.behaviorStartTime)%this.behaviorDuration + this.behaviorStartTime;
- }
- }
-
- if ( time>this.behaviorStartTime+this.behaviorDuration ) {
- if ( this.status!==S.EXPIRED ) {
- this.setExpired(actor,time);
- }
-
- return false;
- }
- if ( this.status===S.NOT_STARTED ) {
- this.status=S.STARTED;
- this.fireBehaviorStartedEvent(actor,time);
- }
- return this.behaviorStartTime<=time; // && time<this.behaviorStartTime+this.behaviorDuration;
- },
- fireBehaviorStartedEvent : function(actor,time) {
- for( var i=0; i<this.lifecycleListenerList.length; i++ ) {
- if ( this.lifecycleListenerList[i].behaviorStarted ) {
- this.lifecycleListenerList[i].behaviorStarted(this,time,actor);
- }
- }
- },
- /**
- * Notify observers about expiration event.
- * @param actor a CAAT.Actor instance
- * @param time an integer with the scene time the behavior was expired at.
- */
- fireBehaviorExpiredEvent : function(actor,time) {
- for( var i=0; i<this.lifecycleListenerList.length; i++ ) {
- this.lifecycleListenerList[i].behaviorExpired(this,time,actor);
- }
- },
- /**
- * Notify observers about behavior being applied.
- * @param actor a CAAT.Actor instance the behavior is being applied to.
- * @param time the scene time of behavior application.
- * @param normalizedTime the normalized time (0..1) considering 0 behavior start time and 1
- * behaviorStartTime+behaviorDuration.
- * @param value the value being set for actor properties. each behavior will supply with its own value version.
- */
- fireBehaviorAppliedEvent : function(actor,time,normalizedTime,value) {
- for( var i=0; i<this.lifecycleListenerList.length; i++ ) {
- if (this.lifecycleListenerList[i].behaviorApplied) {
- this.lifecycleListenerList[i].behaviorApplied(this,time,normalizedTime,actor,value);
- }
- }
- },
- /**
- * Convert scene time into something more manageable for the behavior.
- * behaviorStartTime will be 0 and behaviorStartTime+behaviorDuration will be 1.
- * the time parameter will be proportional to those values.
- * @param time the scene time to be normalized. an integer.
- */
- normalizeTime : function(time) {
- time= time-this.behaviorStartTime;
- if ( this.cycleBehavior ) {
- time%=this.behaviorDuration;
- }
- return this.interpolator.getPosition(time/this.behaviorDuration).y;
- },
- /**
- * Sets the behavior as expired.
- * This method must not be called directly. It is an auxiliary method to isBehaviorInTime method.
- * @param actor {CAAT.Actor}
- * @param time {integer} the scene time.
- *
- * @private
- */
- setExpired : function(actor,time) {
- // set for final interpolator value.
- this.status= CAAT.Behavior.Status.EXPIRED;
- this.setForTime(this.interpolator.getPosition(1).y,actor);
- this.fireBehaviorExpiredEvent(actor,time);
- },
- /**
- * This method must be overriden for every Behavior breed.
- * Must not be called directly.
- * @param actor {CAAT.Actor} a CAAT.Actor instance.
- * @param time {number} an integer with the scene time.
- *
- * @private
- */
- setForTime : function( time, actor ) {
-
- },
- /**
- * @param overrides
- */
- initialize : function(overrides) {
- if (overrides) {
- for (var i in overrides) {
- this[i] = overrides[i];
- }
- }
- return this;
- },
-
- getPropertyName : function() {
- return "";
- }
- };
- })();
- (function() {
- /**
- * <p>
- * A ContainerBehavior is a holder to sum up different behaviors.
- * <p>
- * It imposes some constraints to contained Behaviors:
- * <ul>
- * <li>The time of every contained behavior will be zero based, so the frame time set for each behavior will
- * be referred to the container's behaviorStartTime and not scene time as usual.
- * <li>Cycling a ContainerBehavior means cycling every contained behavior.
- * <li>The container will not impose any Interpolator, so calling the method <code>setInterpolator(CAAT.Interpolator)
- * </code> will be useless.
- * <li>The Behavior application time will be bounded to the Container's frame time. I.E. if we set a container duration
- * to 10 seconds, setting a contained behavior's duration to 15 seconds will be useless since the container will stop
- * applying the behavior after 10 seconds have elapsed.
- * <li>Every ContainerBehavior adds itself as an observer for its contained Behaviors. The main reason is because
- * ContainerBehaviors modify cycling properties of its contained Behaviors. When a contained
- * Behavior is expired, if the Container has isCycle=true, will unexpire the contained Behavior, otherwise, it won't be
- * applied in the next frame. It is left up to the developer to manage correctly the logic of other posible contained
- * behaviors observers.
- * </ul>
- *
- * <p>
- * A ContainerBehavior can contain other ContainerBehaviors at will.
- * <p>
- * A ContainerBehavior will not apply any CAAT.Actor property change by itself, but will instrument its contained
- * Behaviors to do so.
- *
- * @constructor
- * @extends CAAT.Behavior
- */
- CAAT.ContainerBehavior= function() {
- CAAT.ContainerBehavior.superclass.constructor.call(this);
- this.behaviors= [];
- return this;
- };
- CAAT.ContainerBehavior.prototype= {
- behaviors: null, // contained behaviors array
- /**
- * Proportionally change this container duration to its children.
- * @param duration {number} new duration in ms.
- * @return this;
- */
- conformToDuration : function( duration ) {
- this.duration= duration;
-
- var f= duration/this.duration;
- var bh;
- for( var i=0; i<this.behavior.length; i++ ) {
- bh= this.behavior[i];
- bh.setFrameTime( bh.getStartTime()*f, bh.getDuration()*f );
- }
- return this;
- },
- /**
- * Adds a new behavior to the container.
- * @param behavior
- *
- * @override
- */
- addBehavior : function(behavior) {
- this.behaviors.push(behavior);
- behavior.addListener(this);
- return this;
- },
- /**
- * Applies every contained Behaviors.
- * The application time the contained behaviors will receive will be ContainerBehavior related and not the
- * received time.
- * @param time an integer indicating the time to apply the contained behaviors at.
- * @param actor a CAAT.Actor instance indicating the actor to apply the behaviors for.
- */
- apply : function(time, actor) {
- time+= this.timeOffset*this.behaviorDuration;
-
- if ( this.isBehaviorInTime(time,actor) ) {
- time-= this.getStartTime();
- if ( this.cycleBehavior ){
- time%= this.getDuration();
- }
- var bh= this.behaviors;
- for( var i=0; i<bh.length; i++ ) {
- bh[i].apply(time, actor);
- }
- }
- },
- /**
- * This method is the observer implementation for every contained behavior.
- * If a container is Cycle=true, won't allow its contained behaviors to be expired.
- * @param behavior a CAAT.Behavior instance which has been expired.
- * @param time an integer indicating the time at which has become expired.
- * @param actor a CAAT.Actor the expired behavior is being applied to.
- */
- behaviorExpired : function(behavior,time,actor) {
- if ( this.cycleBehavior ) {
- behavior.setStatus( CAAT.Behavior.Status.STARTED );
- }
- },
- /**
- * Implementation method of the behavior.
- * Just call implementation method for its contained behaviors.
- * @param time an intenger indicating the time the behavior is being applied at.
- * @param actor a CAAT.Actor the behavior is being applied to.
- */
- setForTime : function(time, actor) {
- var bh= this.behaviors;
- for( var i=0; i<bh.length; i++ ) {
- bh[i].setForTime( time, actor );
- }
- return null;
- },
- setExpired : function(actor,time) {
- CAAT.ContainerBehavior.superclass.setExpired.call(this,actor,time);
- var bh= this.behaviors;
- // set for final interpolator value.
- for( var i=0; i<bh.length; i++ ) {
- var bb= bh[i];
- if ( /*!bb.expired*/ bb.status!==CAAT.Behavior.Status.EXPIRED ) {
- bb.setExpired(actor,time-this.behaviorStartTime);
- }
- }
- // already notified in base class.
- // this.fireBehaviorExpiredEvent(actor,time);
- return this;
- },
- setFrameTime : function( start, duration ) {
- CAAT.ContainerBehavior.superclass.setFrameTime.call(this,start,duration);
- var bh= this.behaviors;
- for( var i=0; i<bh.length; i++ ) {
- //bh[i].expired= false;
- bh[i].setStatus( CAAT.Behavior.Status.NOT_STARTED );
- }
- return this;
- },
- calculateKeyFrameData : function(referenceTime, prefix, prevValues ) {
- var i;
- var bh;
- var retValue= {};
- var time;
- var cssRuleValue;
- var cssProperty;
- var property;
- for( i=0; i<this.behaviors.length; i++ ) {
- bh= this.behaviors[i];
- if ( /*!bh.expired*/ bh.status!==CAAT.Behavior.Status.EXPIRED && !(bh instanceof CAAT.GenericBehavior) ) {
- // ajustar tiempos:
- // time es tiempo normalizado a duracion de comportamiento contenedor.
- // 1.- desnormalizar
- time= referenceTime * this.behaviorDuration;
- // 2.- calcular tiempo relativo de comportamiento respecto a contenedor
- if ( bh.behaviorStartTime<=time && bh.behaviorStartTime+bh.behaviorDuration>=time ) {
- // 3.- renormalizar tiempo reltivo a comportamiento.
- time= (time-bh.behaviorStartTime)/bh.behaviorDuration;
- // 4.- obtener valor de comportamiento para tiempo normalizado relativo a contenedor
- cssRuleValue= bh.calculateKeyFrameData(time);
- cssProperty= bh.getPropertyName(prefix);
- if ( typeof retValue[cssProperty] ==='undefined' ) {
- retValue[cssProperty]= "";
- }
- // 5.- asignar a objeto, par de propiedad/valor css
- retValue[cssProperty]+= cssRuleValue+" ";
- }
- }
- }
- var tr="";
- var pv;
- function xx(pr) {
- if ( retValue[pr] ) {
- tr+= retValue[pr];
- } else {
- if ( prevValues ) {
- pv= prevValues[pr];
- if ( pv ) {
- tr+= pv;
- retValue[pr]= pv;
- }
- }
- }
- }
- xx('translate');
- xx('rotate');
- xx('scale');
- var keyFrameRule= "";
- if ( tr ) {
- keyFrameRule='-'+prefix+'-transform: '+tr+';';
- }
- tr="";
- xx('opacity');
- if( tr ) {
- keyFrameRule+= ' opacity: '+tr+';';
- }
- return {
- rules: keyFrameRule,
- ret: retValue
- };
- },
- /**
- *
- * @param prefix
- * @param name
- * @param keyframessize
- */
- calculateKeyFramesData : function(prefix, name, keyframessize) {
- if ( this.duration===Number.MAX_VALUE ) {
- return "";
- }
- if ( typeof keyframessize==='undefined' ) {
- keyframessize=100;
- }
- var i;
- var prevValues= null;
- var kfd= "@-"+prefix+"-keyframes "+name+" {";
- var ret;
- var time;
- var kfr;
- for( i=0; i<=keyframessize; i++ ) {
- time= this.interpolator.getPosition(i/keyframessize).y;
- ret= this.calculateKeyFrameData(time, prefix, prevValues);
- kfr= "" +
- (i/keyframessize*100) + "%" + // percentage
- "{" + ret.rules + "}\n";
- prevValues= ret.ret;
- kfd+= kfr;
- }
- kfd+= "}";
- return kfd;
- }
- };
- extend( CAAT.ContainerBehavior, CAAT.Behavior, null );
- })();
- (function() {
- /**
- * This class applies a rotation to a CAAt.Actor instance.
- * StartAngle, EndAngle must be supplied. Angles are in radians.
- * The RotationAnchor, if not supplied, will be ANCHOR_CENTER.
- *
- * An example os use will be
- *
- * var rb= new CAAT.RotateBehavior().
- * setValues(0,2*Math.PI).
- * setFrameTime(0,2500);
- *
- * @see CAAT.Actor.
- *
- * @constructor
- * @extends CAAT.Behavior
- *
- */
- CAAT.RotateBehavior= function() {
- CAAT.RotateBehavior.superclass.constructor.call(this);
- this.anchor= CAAT.Actor.prototype.ANCHOR_CENTER;
- return this;
- };
-
- CAAT.RotateBehavior.prototype= {
-
- startAngle: 0, // behavior start angle
- endAngle: 0, // behavior end angle
- anchorX: .50, // rotation center x.
- anchorY: .50, // rotation center y.
- getPropertyName : function() {
- return "rotate";
- },
- /**
- * Behavior application function.
- * Do not call directly.
- * @param time an integer indicating the application time.
- * @param actor a CAAT.Actor the behavior will be applied to.
- * @return the set angle.
- */
- setForTime : function(time,actor) {
- var angle= this.startAngle + time*(this.endAngle-this.startAngle);
- if ( this.doValueApplication ) {
- actor.setRotationAnchored(angle, this.anchorX, this.anchorY);
- }
- return angle;
-
- },
- /**
- * Set behavior bound values.
- * if no anchorx,anchory values are supplied, the behavior will assume
- * 50% for both values, that is, the actor's center.
- *
- * Be aware the anchor values are supplied in <b>RELATIVE PERCENT</b> to
- * actor's size.
- *
- * @param startAngle {float} indicating the starting angle.
- * @param endAngle {float} indicating the ending angle.
- * @param anchorx {float} the percent position for anchorX
- * @param anchory {float} the percent position for anchorY
- */
- setValues : function( startAngle, endAngle, anchorx, anchory ) {
- this.startAngle= startAngle;
- this.endAngle= endAngle;
- if ( typeof anchorx!=='undefined' && typeof anchory!=='undefined' ) {
- this.anchorX= anchorx;
- this.anchorY= anchory;
- }
- return this;
- },
- /**
- * @deprecated
- * Use setValues instead
- * @param start
- * @param end
- */
- setAngles : function( start, end ) {
- return this.setValues(start,end);
- },
- /**
- * Set the behavior rotation anchor. Use this method when setting an exact percent
- * by calling setValues is complicated.
- * @see CAAT.Actor
- * @param anchor any of CAAT.Actor.prototype.ANCHOR_* constants.
- *
- * These parameters are to set a custom rotation anchor point. if <code>anchor==CAAT.Actor.prototype.ANCHOR_CUSTOM
- * </code> the custom rotation point is set.
- * @param rx
- * @param ry
- *
- */
- setAnchor : function( actor, rx, ry ) {
- this.anchorX= rx/actor.width;
- this.anchorY= ry/actor.height;
- return this;
- },
- calculateKeyFrameData : function( time ) {
- time= this.interpolator.getPosition(time).y;
- return "rotate(" + (this.startAngle + time*(this.endAngle-this.startAngle)) +"rad)";
- },
- /**
- * @param prefix {string} browser vendor prefix
- * @param name {string} keyframes animation name
- * @param keyframessize {integer} number of keyframes to generate
- * @override
- */
- calculateKeyFramesData : function(prefix, name, keyframessize) {
- if ( typeof keyframessize==='undefined' ) {
- keyframessize= 100;
- }
- keyframessize>>=0;
- var i;
- var kfr;
- var kfd= "@-"+prefix+"-keyframes "+name+" {";
- for( i=0; i<=keyframessize; i++ ) {
- kfr= "" +
- (i/keyframessize*100) + "%" + // percentage
- "{" +
- "-"+prefix+"-transform:" + this.calculateKeyFrameData(i/keyframessize) +
- "}\n";
- kfd+= kfr;
- }
- kfd+="}";
- return kfd;
- }
- };
- extend( CAAT.RotateBehavior, CAAT.Behavior, null);
-
- })();
- (function() {
- /**
- * <p>
- * A generic behavior is supposed to be extended to create new behaviors when the out-of-the-box
- * ones are not sufficient. It applies the behavior result to a given target object in two ways:
- *
- * <ol>
- * <li>defining the property parameter: the toolkit will perform target_object[property]= calculated_value_for_time.
- * <li>defining a callback function. Sometimes setting of a property is not enough. In example,
- * for a give property in a DOM element, it is needed to set object.style['left']= '70px';
- * With the property approach, you won't be able to add de 'px' suffix to the value, and hence won't
- * work correctly. The function callback will allow to take control by receiving as parameters the
- * target object, and the calculated value to apply by the behavior for the given time.
- * </ol>
- *
- * <p>
- * For example, this code will move a dom element from 0 to 400 px on x during 1 second:
- * <code>
- * <p>
- * var enterBehavior= new CAAT.GenericBehavior(). <br>
- * setFrameTime( scene.time, 1000 ). <br>
- * setValues( <br>
- * 0, <br>
- * 400, <br>
- * domElement, <br>
- * null, <br>
- * function( currentValue, target ) { <br>
- * target.style['left']= currentValue+'px'; <br>
- * } <br>
- * ); <br>
- * </code>
- *
- * @constructor
- * @extends CAAT.Behavior
- *
- */
- CAAT.GenericBehavior= function() {
- CAAT.GenericBehavior.superclass.constructor.call(this);
- return this;
- };
- CAAT.GenericBehavior.prototype= {
- start: 0,
- end: 0,
- target: null,
- property: null,
- callback: null,
- /**
- * Sets the target objects property to the corresponding value for the given time.
- * If a callback function is defined, it is called as well.
- *
- * @param time {number} the scene time to apply the behavior at.
- * @param actor {CAAT.Actor} a CAAT.Actor object instance.
- */
- setForTime : function(time, actor) {
- var value= this.start+ time*(this.end-this.start);
- if ( this.callback ) {
- this.callback( value, this.target, actor );
- }
- if ( this.property ) {
- this.target[this.property]= value;
- }
- },
- /**
- * Defines the values to apply this behavior.
- *
- * @param start {number} initial behavior value.
- * @param end {number} final behavior value.
- * @param target {object} an object. Usually a CAAT.Actor.
- * @param property {string} target object's property to set value to.
- * @param callback {function} a function of the form <code>function( target, value )</code>.
- */
- setValues : function( start, end, target, property, callback ) {
- this.start= start;
- this.end= end;
- this.target= target;
- this.property= property;
- this.callback= callback;
- return this;
- }
- };
- extend( CAAT.GenericBehavior, CAAT.Behavior, null);
- })();
- (function() {
- /**
- * ScaleBehavior applies scale affine transforms in both axis.
- * StartScale and EndScale must be supplied for each axis. This method takes care of a FF bug in which if a Scale is
- * set to 0, the animation will fail playing.
- *
- * This behavior specifies anchors in values ranges 0..1
- *
- * @constructor
- * @extends CAAT.Behavior
- *
- */
- CAAT.ScaleBehavior= function() {
- CAAT.ScaleBehavior.superclass.constructor.call(this);
- this.anchor= CAAT.Actor.prototype.ANCHOR_CENTER;
- return this;
- };
-
- CAAT.ScaleBehavior.prototype= {
- startScaleX: 1,
- endScaleX: 1,
- startScaleY: 1,
- endScaleY: 1,
- anchorX: .50,
- anchorY: .50,
- getPropertyName : function() {
- return "scale";
- },
- /**
- * Applies corresponding scale values for a given time.
- *
- * @param time the time to apply the scale for.
- * @param actor the target actor to Scale.
- * @return {object} an object of the form <code>{ scaleX: {float}, scaleY: {float}�}</code>
- */
- setForTime : function(time,actor) {
- var scaleX= this.startScaleX + time*(this.endScaleX-this.startScaleX);
- var scaleY= this.startScaleY + time*(this.endScaleY-this.startScaleY);
- // Firefox 3.x & 4, will crash animation if either scaleX or scaleY equals 0.
- if (0===scaleX ) {
- scaleX=0.01;
- }
- if (0===scaleY ) {
- scaleY=0.01;
- }
- if ( this.doValueApplication ) {
- actor.setScaleAnchored( scaleX, scaleY, this.anchorX, this.anchorY );
- }
- return { scaleX: scaleX, scaleY: scaleY };
- },
- /**
- * Define this scale behaviors values.
- *
- * Be aware the anchor values are supplied in <b>RELATIVE PERCENT</b> to
- * actor's size.
- *
- * @param startX {number} initial X axis scale value.
- * @param endX {number} final X axis scale value.
- * @param startY {number} initial Y axis scale value.
- * @param endY {number} final Y axis scale value.
- * @param anchorx {float} the percent position for anchorX
- * @param anchory {float} the percent position for anchorY
- *
- * @return this.
- */
- setValues : function( startX, endX, startY, endY, anchorx, anchory ) {
- this.startScaleX= startX;
- this.endScaleX= endX;
- this.startScaleY= startY;
- this.endScaleY= endY;
- if ( typeof anchorx!=='undefined' && typeof anchory!=='undefined' ) {
- this.anchorX= anchorx;
- this.anchorY= anchory;
- }
- return this;
- },
- /**
- * Set an exact position scale anchor. Use this method when it is hard to
- * set a thorough anchor position expressed in percentage.
- * @param actor
- * @param x
- * @param y
- */
- setAnchor : function( actor, x, y ) {
- this.anchorX= x/actor.width;
- this.anchorY= y/actor.height;
- return this;
- },
- calculateKeyFrameData : function( time ) {
- var scaleX;
- var scaleY;
- time= this.interpolator.getPosition(time).y;
- scaleX= this.startScaleX + time*(this.endScaleX-this.startScaleX);
- scaleY= this.startScaleY + time*(this.endScaleY-this.startScaleY);
- return "scaleX("+scaleX+") scaleY("+scaleY+")";
- },
- calculateKeyFramesData : function(prefix, name, keyframessize) {
- if ( typeof keyframessize==='undefined' ) {
- keyframessize= 100;
- }
- keyframessize>>=0;
- var i;
- var kfr;
- var kfd= "@-"+prefix+"-keyframes "+name+" {";
- for( i=0; i<=keyframessize; i++ ) {
- kfr= "" +
- (i/keyframessize*100) + "%" + // percentage
- "{" +
- "-"+prefix+"-transform:" + this.calculateKeyFrameData(i/keyframessize) +
- "}";
- kfd+= kfr;
- }
- kfd+="}";
- return kfd;
- }
- };
- extend( CAAT.ScaleBehavior, CAAT.Behavior, null);
- })();
- (function() {
- /**
- * AlphaBehavior modifies alpha composition property for an actor.
- *
- * @constructor
- * @extends CAAT.Behavior
- */
- CAAT.AlphaBehavior= function() {
- CAAT.AlphaBehavior.superclass.constructor.call(this);
- return this;
- };
-
- CAAT.AlphaBehavior.prototype= {
- startAlpha: 0,
- endAlpha: 0,
- getPropertyName : function() {
- return "opacity";
- },
- /**
- * Applies corresponding alpha transparency value for a given time.
- *
- * @param time the time to apply the scale for.
- * @param actor the target actor to set transparency for.
- * @return {number} the alpha value set. Normalized from 0 (total transparency) to 1 (total opacity)
- */
- setForTime : function(time,actor) {
- var alpha= (this.startAlpha+time*(this.endAlpha-this.startAlpha));
- if ( this.doValueApplication ) {
- actor.setAlpha( alpha );
- }
- return alpha;
- },
- /**
- * Set alpha transparency minimum and maximum value.
- * This value can be coerced by Actor's property isGloblAlpha.
- *
- * @param start {number} a float indicating the starting alpha value.
- * @param end {number} a float indicating the ending alpha value.
- */
- setValues : function( start, end ) {
- this.startAlpha= start;
- this.endAlpha= end;
- return this;
- },
- calculateKeyFrameData : function( time ) {
- time= this.interpolator.getPosition(time).y;
- return (this.startAlpha+time*(this.endAlpha-this.startAlpha));
- },
- /**
- * @param prefix {string} browser vendor prefix
- * @param name {string} keyframes animation name
- * @param keyframessize {integer} number of keyframes to generate
- * @override
- */
- calculateKeyFramesData : function(prefix, name, keyframessize) {
- if ( typeof keyframessize==='undefined' ) {
- keyframessize= 100;
- }
- keyframessize>>=0;
- var i;
- var kfr;
- var kfd= "@-"+prefix+"-keyframes "+name+" {";
- for( i=0; i<=keyframessize; i++ ) {
- kfr= "" +
- (i/keyframessize*100) + "%" + // percentage
- "{" +
- "opacity: " + this.calculateKeyFrameData( i / keyframessize ) +
- "}";
- kfd+= kfr;
- }
- kfd+="}";
- return kfd;
- }
- };
- extend( CAAT.AlphaBehavior, CAAT.Behavior, null);
- })();
- (function() {
- /**
- * CAAT.PathBehavior modifies the position of a CAAT.Actor along the path represented by an
- * instance of <code>CAAT.Path</code>.
- *
- * @constructor
- * @extends CAAT.Behavior
- *
- */
- CAAT.PathBehavior= function() {
- CAAT.PathBehavior.superclass.constructor.call(this);
- return this;
- };
- /**
- * @enum
- */
- CAAT.PathBehavior.autorotate = {
- LEFT_TO_RIGHT: 0, // fix left_to_right direction
- RIGHT_TO_LEFT: 1, // fix right_to_left
- FREE: 2 // do not apply correction
- };
- CAAT.PathBehavior.prototype= {
- path: null, // the path to traverse
- autoRotate : false, // set whether the actor must be rotated tangentially to the path.
- prevX: -1, // private, do not use.
- prevY: -1, // private, do not use.
- autoRotateOp: CAAT.PathBehavior.autorotate.FREE,
- getPropertyName : function() {
- return "translate";
- },
- /**
- * Sets an actor rotation to be heading from past to current path's point.
- * Take into account that this will be incompatible with rotation Behaviors
- * since they will set their own rotation configuration.
- * @param autorotate {boolean}
- * @param autorotateOp {CAAT.PathBehavior.autorotate} whether the sprite is drawn heading to the right.
- * @return this.
- */
- setAutoRotate : function( autorotate, autorotateOp ) {
- this.autoRotate= autorotate;
- if (autorotateOp!==undefined) {
- this.autoRotateOp= autorotateOp;
- }
- return this;
- },
- /**
- * Set the behavior path.
- * The path can be any length, and will take behaviorDuration time to be traversed.
- * @param {CAAT.Path}
- *
- * @deprecated
- */
- setPath : function(path) {
- this.path= path;
- return this;
- },
- /**
- * Set the behavior path.
- * The path can be any length, and will take behaviorDuration time to be traversed.
- * @param {CAAT.Path}
- * @return this
- */
- setValues : function(path) {
- return this.setPath(path);
- },
- /**
- * @see Acotr.setPositionAcchor
- * @deprecated
- * @param tx a float with xoffset.
- * @param ty a float with yoffset.
- */
- setTranslation : function( tx, ty ) {
- return this;
- },
- calculateKeyFrameData : function( time ) {
- time= this.interpolator.getPosition(time).y;
- var point= this.path.getPosition(time);
- return "translateX("+point.x+"px) translateY("+point.y+"px)" ;
- },
- calculateKeyFramesData : function(prefix, name, keyframessize) {
- if ( typeof keyframessize==='undefined' ) {
- keyframessize= 100;
- }
- keyframessize>>=0;
- var i;
- var kfr;
- var time;
- var kfd= "@-"+prefix+"-keyframes "+name+" {";
- for( i=0; i<=keyframessize; i++ ) {
- kfr= "" +
- (i/keyframessize*100) + "%" + // percentage
- "{" +
- "-"+prefix+"-transform:" + this.calculateKeyFrameData(i/keyframessize) +
- "}";
- kfd+= kfr;
- }
- kfd+="}";
- return kfd;
- },
- /**
- * Translates the Actor to the corresponding time path position.
- * If autoRotate=true, the actor is rotated as well. The rotation anchor will (if set) always be ANCHOR_CENTER.
- * @param time an integer indicating the time the behavior is being applied at.
- * @param actor a CAAT.Actor instance to be translated.
- * @return {object} an object of the form <code>{ x: {float}, y: {float}�}</code>.
- */
- setForTime : function(time,actor) {
- if ( !this.path ) {
- return {
- x: actor.x,
- y: actor.y
- };
- }
- var point= this.path.getPosition(time);
- if ( this.autoRotate ) {
- if ( -1===this.prevX && -1===this.prevY ) {
- this.prevX= point.x;
- this.prevY= point.y;
- }
- var ax= point.x-this.prevX;
- var ay= point.y-this.prevY;
- if ( ax===0 && ay===0 ) {
- actor.setLocation( point.x, point.y );
- return { x: actor.x, y: actor.y };
- }
- var angle= Math.atan2( ay, ax );
- var si= CAAT.SpriteImage.prototype;
- var pba= CAAT.PathBehavior.autorotate;
- // actor is heading left to right
- if ( this.autoRotateOp===pba.LEFT_TO_RIGHT ) {
- if ( this.prevX<=point.x ) {
- actor.setImageTransformation( si.TR_NONE );
- }
- else {
- actor.setImageTransformation( si.TR_FLIP_HORIZONTAL );
- angle+=Math.PI;
- }
- } else if ( this.autoRotateOp===pba.RIGHT_TO_LEFT ) {
- if ( this.prevX<=point.x ) {
- actor.setImageTransformation( si.TR_FLIP_HORIZONTAL );
- }
- else {
- actor.setImageTransformation( si.TR_NONE );
- angle-=Math.PI;
- }
- }
- actor.setRotation(angle);
- this.prevX= point.x;
- this.prevY= point.y;
- var modulo= Math.sqrt(ax*ax+ay*ay);
- ax/=modulo;
- ay/=modulo;
- }
- if ( this.doValueApplication ) {
- actor.setLocation( point.x, point.y );
- return { x: actor.x, y: actor.y };
- } else {
- return {
- x: point.x,
- y: point.y
- };
- }
- },
- /**
- * Get a point on the path.
- * If the time to get the point at is in behaviors frame time, a point on the path will be returned, otherwise
- * a default {x:-1, y:-1} point will be returned.
- *
- * @param time {number} the time at which the point will be taken from the path.
- * @return {object} an object of the form {x:float y:float}
- */
- positionOnTime : function(time) {
- if ( this.isBehaviorInTime(time,null) ) {
- time= this.normalizeTime(time);
- return this.path.getPosition( time );
- }
- return {x:-1, y:-1};
- }
- };
- extend( CAAT.PathBehavior, CAAT.Behavior );
- })();
- (function() {
- /**
- * ColorBehavior interpolates between two given colors.
- * @constructor
- */
- CAAT.ColorBehavior= function() {
- return this;
- };
- CAAT.ColorBehavior.prototype= {
- };
- extend( CAAT.ColorBehavior, CAAT.Behavior );
- })();
- (function() {
- /**
- *
- * Scale only X or Y axis, instead both at the same time as ScaleBehavior.
- *
- * @constructor
- */
- CAAT.Scale1Behavior= function() {
- CAAT.Scale1Behavior.superclass.constructor.call(this);
- this.anchor= CAAT.Actor.prototype.ANCHOR_CENTER;
- return this;
- };
- CAAT.Scale1Behavior.prototype= {
- startScale: 1,
- endScale: 1,
- anchorX: .50,
- anchorY: .50,
- sx : 1,
- sy : 1,
- applyOnX : true,
- getPropertyName : function() {
- return "scale";
- },
- /**
- * Applies corresponding scale values for a given time.
- *
- * @param time the time to apply the scale for.
- * @param actor the target actor to Scale.
- * @return {object} an object of the form <code>{ scaleX: {float}, scaleY: {float}�}</code>
- */
- setForTime : function(time,actor) {
- var scale= this.startScale + time*(this.endScale-this.startScale);
- // Firefox 3.x & 4, will crash animation if either scaleX or scaleY equals 0.
- if (0===scale ) {
- scale=0.01;
- }
- if ( this.doValueApplication ) {
- if ( this.applyOnX ) {
- actor.setScaleAnchored( scale, actor.scaleY, this.anchorX, this.anchorY );
- } else {
- actor.setScaleAnchored( actor.scaleX, scale, this.anchorX, this.anchorY );
- }
- }
- return scale;
- },
- /**
- * Define this scale behaviors values.
- *
- * Be aware the anchor values are supplied in <b>RELATIVE PERCENT</b> to
- * actor's size.
- *
- * @param start {number} initial X axis scale value.
- * @param end {number} final X axis scale value.
- * @param anchorx {float} the percent position for anchorX
- * @param anchory {float} the percent position for anchorY
- *
- * @return this.
- */
- setValues : function( start, end, applyOnX, anchorx, anchory ) {
- this.startScale= start;
- this.endScale= end;
- this.applyOnX= !!applyOnX;
- if ( typeof anchorx!=='undefined' && typeof anchory!=='undefined' ) {
- this.anchorX= anchorx;
- this.anchorY= anchory;
- }
- return this;
- },
- /**
- * Set an exact position scale anchor. Use this method when it is hard to
- * set a thorough anchor position expressed in percentage.
- * @param actor
- * @param x
- * @param y
- */
- setAnchor : function( actor, x, y ) {
- this.anchorX= x/actor.width;
- this.anchorY= y/actor.height;
- return this;
- },
- calculateKeyFrameData : function( time ) {
- var scale;
- time= this.interpolator.getPosition(time).y;
- scale= this.startScale + time*(this.endScale-this.startScale);
- return this.applyOnX ? "scaleX("+scale+")" : "scaleY("+scale+")";
- },
- calculateKeyFramesData : function(prefix, name, keyframessize) {
- if ( typeof keyframessize==='undefined' ) {
- keyframessize= 100;
- }
- keyframessize>>=0;
- var i;
- var kfr;
- var kfd= "@-"+prefix+"-keyframes "+name+" {";
- for( i=0; i<=keyframessize; i++ ) {
- kfr= "" +
- (i/keyframessize*100) + "%" + // percentage
- "{" +
- "-"+prefix+"-transform:" + this.calculateKeyFrameData(i/keyframessize) +
- "}";
- kfd+= kfr;
- }
- kfd+="}";
- return kfd;
- }
- };
- extend( CAAT.Scale1Behavior, CAAT.Behavior );
- })();/**
- * See LICENSE file.
- *
- * This object manages CSS3 transitions reflecting applying behaviors.
- *
- **/
- (function() {
- CAAT.CSS= {};
- CAAT.CSS.PREFIX= (function() {
- var prefix = "";
- var prefixes = ['WebKit', 'Moz', 'O'];
- var keyframes= "";
- // guess this browser vendor prefix.
- for (var i = 0; i < prefixes.length; i++) {
- if (window[prefixes[i] + 'CSSKeyframeRule']) {
- prefix = prefixes[i].toLowerCase();
- break;
- }
- }
- CAAT.CSS.PROP_ANIMATION= '-'+prefix+'-animation';
- return prefix;
- })();
- CAAT.CSS.applyKeyframe= function( domElement, name, secs, forever ) {
- domElement.style[CAAT.CSS.PROP_ANIMATION]= name+' '+(secs/1000)+'s linear both '+(forever ? 'infinite' : '') ;
- };
- CAAT.CSS.unregisterKeyframes= function( name ) {
- var index= CAAT.CSS.getCSSKeyframesIndex(name);
- if ( -1!==index ) {
- document.styleSheets[0].deleteRule( index );
- }
- };
- /**
- *
- * @param kfDescriptor {object{ name{string}, behavior{CAAT.Behavior}, size{!number}, overwrite{boolean}}
- */
- CAAT.CSS.registerKeyframes= function( kfDescriptor ) {
- var name= kfDescriptor.name;
- var behavior= kfDescriptor.behavior;
- var size= kfDescriptor.size;
- var overwrite= kfDescriptor.overwrite;
- if ( typeof name==='undefined' || typeof behavior==='undefined' ) {
- throw 'Keyframes must be defined by a name and a CAAT.Behavior instance.';
- }
- if ( typeof size==='undefined' ) {
- size= 100;
- }
- if ( typeof overwrite==='undefined' ) {
- overwrite= false;
- }
- // find if keyframes has already a name set.
- var cssRulesIndex= CAAT.CSS.getCSSKeyframesIndex(name);
- if (-1!==cssRulesIndex && !overwrite) {
- return;
- }
- var keyframesRule= behavior.calculateKeyframesData(CAAT.CSS.PREFIX, name, size );
- if (document.styleSheets) {
- if ( !document.styleSheets.length) {
- var s = document.createElement('style');
- s.type="text/css";
- document.getElementsByTagName('head')[ 0 ].appendChild(s);
- }
- if ( -1!==cssRulesIndex ) {
- document.styleSheets[0].deleteRule( cssRulesIndex );
- }
- document.styleSheets[0].insertRule( keyframesRule, 0 );
- }
- };
- CAAT.CSS.getCSSKeyframesIndex= function(name) {
- var ss = document.styleSheets;
- for (var i = ss.length - 1; i >= 0; i--) {
- try {
- var s = ss[i],
- rs = s.cssRules ? s.cssRules :
- s.rules ? s.rules :
- [];
- for (var j = rs.length - 1; j >= 0; j--) {
- if ( ( rs[j].type === window.CSSRule.WEBKIT_KEYFRAMES_RULE ||
- rs[j].type === window.CSSRule.MOZ_KEYFRAMES_RULE ) && rs[j].name === name) {
- return j;
- }
- }
- } catch(e) {
- }
- }
- return -1;
- };
- CAAT.CSS.getCSSKeyframes= function(name) {
- var ss = document.styleSheets;
- for (var i = ss.length - 1; i >= 0; i--) {
- try {
- var s = ss[i],
- rs = s.cssRules ? s.cssRules :
- s.rules ? s.rules :
- [];
- for (var j = rs.length - 1; j >= 0; j--) {
- if ( ( rs[j].type === window.CSSRule.WEBKIT_KEYFRAMES_RULE ||
- rs[j].type === window.CSSRule.MOZ_KEYFRAMES_RULE ) && rs[j].name === name) {
- return rs[j];
- }
- }
- }
- catch(e) {
- }
- }
- return null;
- };
- })();/**
- *
- * taken from: http://www.quirksmode.org/js/detect.html
- *
- * 20101008 Hyperandroid. IE9 seems to identify himself as Explorer and stopped calling himself MSIE.
- * Added Explorer description to browser list. Thanks @alteredq for this tip.
- *
- */
- (function() {
- CAAT.BrowserDetect = function() {
- this.init();
- return this;
- };
- CAAT.BrowserDetect.prototype = {
- browser: '',
- version: 0,
- OS: '',
- init: function()
- {
- this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
- this.version = this.searchVersion(navigator.userAgent) ||
- this.searchVersion(navigator.appVersion) ||
- "an unknown version";
- this.OS = this.searchString(this.dataOS) || "an unknown OS";
- },
- searchString: function (data) {
- for (var i=0;i<data.length;i++) {
- var dataString = data[i].string;
- var dataProp = data[i].prop;
- this.versionSearchString = data[i].versionSearch || data[i].identity;
- if (dataString) {
- if (dataString.indexOf(data[i].subString) !== -1)
- return data[i].identity;
- }
- else if (dataProp)
- return data[i].identity;
- }
- },
- searchVersion: function (dataString) {
- var index = dataString.indexOf(this.versionSearchString);
- if (index === -1) return;
- return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
- },
- dataBrowser: [
- {
- string: navigator.userAgent,
- subString: "Chrome",
- identity: "Chrome"
- },
- { string: navigator.userAgent,
- subString: "OmniWeb",
- versionSearch: "OmniWeb/",
- identity: "OmniWeb"
- },
- {
- string: navigator.vendor,
- subString: "Apple",
- identity: "Safari",
- versionSearch: "Version"
- },
- {
- prop: window.opera,
- identity: "Opera"
- },
- {
- string: navigator.vendor,
- subString: "iCab",
- identity: "iCab"
- },
- {
- string: navigator.vendor,
- subString: "KDE",
- identity: "Konqueror"
- },
- {
- string: navigator.userAgent,
- subString: "Firefox",
- identity: "Firefox"
- },
- {
- string: navigator.vendor,
- subString: "Camino",
- identity: "Camino"
- },
- { // for newer Netscapes (6+)
- string: navigator.userAgent,
- subString: "Netscape",
- identity: "Netscape"
- },
- {
- string: navigator.userAgent,
- subString: "MSIE",
- identity: "Explorer",
- versionSearch: "MSIE"
- },
- {
- string: navigator.userAgent,
- subString: "Explorer",
- identity: "Explorer",
- versionSearch: "Explorer"
- },
- {
- string: navigator.userAgent,
- subString: "Gecko",
- identity: "Mozilla",
- versionSearch: "rv"
- },
- { // for older Netscapes (4-)
- string: navigator.userAgent,
- subString: "Mozilla",
- identity: "Netscape",
- versionSearch: "Mozilla"
- }
- ],
- dataOS : [
- {
- string: navigator.platform,
- subString: "Win",
- identity: "Windows"
- },
- {
- string: navigator.platform,
- subString: "Mac",
- identity: "Mac"
- },
- {
- string: navigator.userAgent,
- subString: "iPhone",
- identity: "iPhone/iPod"
- },
- {
- string: navigator.platform,
- subString: "Linux",
- identity: "Linux"
- }
- ]
- };
- })();/**
- * See LICENSE file.
- *
- * Get realtime Debug information of CAAT's activity.
- * Set CAAT.DEBUG=1 before any CAAT.Director object creation.
- * This class creates a DOM node called 'caat-debug' and associated styles
- * The debug panel is minimized by default and shows short information. It can be expanded and minimized again by clicking on it
- *
- */
- (function() {
- CAAT.Debug= function() {
- return this;
- };
- CAAT.Debug.prototype= {
- width: 0,
- height: 0,
- canvas: null,
- ctx: null,
- statistics: null,
- framerate: null,
- textContainer: null,
- textFPS: null,
- textEntitiesTotal: null,
- textEntitiesActive: null,
- textDraws: null,
- textDrawTime: null,
- textRAFTime: null,
- textDirtyRects: null,
- frameTimeAcc : 0,
- frameRAFAcc : 0,
- canDebug: false,
- SCALE: 60,
- debugTpl:
- " <style type=\"text/css\">"+
- " #caat-debug {"+
- " z-index: 10000;"+
- " position:fixed;"+
- " bottom:0;"+
- " left:0;"+
- " width:100%;"+
- " background-color: rgba(0,0,0,0.8);"+
- " }"+
- " #caat-debug.caat_debug_max {"+
- " margin-bottom: 0px;"+
- " }"+
- " .caat_debug_bullet {"+
- " display:inline-block;"+
- " background-color:#f00;"+
- " width:8px;"+
- " height:8px;"+
- " border-radius: 4px;"+
- " margin-left:10px;"+
- " margin-right:2px;"+
- " }"+
- " .caat_debug_description {"+
- " font-size:11px;"+
- " font-family: helvetica, arial;"+
- " color: #aaa;"+
- " display: inline-block;"+
- " }"+
- " .caat_debug_value {"+
- " font-size:11px;"+
- " font-family: helvetica, arial;"+
- " color: #fff;"+
- " width:25px;"+
- " text-align: right;"+
- " display: inline-block;"+
- " margin-right: .3em;"+
- " }"+
- " .caat_debug_indicator {"+
- " float: right;"+
- " }"+
- " #debug_tabs {"+
- " border-top: 1px solid #888;"+
- " height:25px;"+
- " }"+
- " .tab_max_min {"+
- " font-family: helvetica, arial;"+
- " font-size: 12px;"+
- " font-weight: bold;"+
- " color: #888;"+
- " border-right: 1px solid #888;"+
- " float: left;"+
- " cursor: pointer;"+
- " padding-left: 5px;"+
- " padding-right: 5px;"+
- " padding-top: 5px;"+
- " height: 20px;"+
- " }"+
- " .debug_tabs_content_hidden {"+
- " display: none;"+
- " width: 100%;"+
- " }"+
- " .debug_tabs_content_visible {"+
- " display: block;"+
- " width: 100%;"+
- " }"+
- " .checkbox_enabled {"+
- " display:inline-block;"+
- " background-color:#eee;"+
- " border: 1px solid #eee;"+
- " width:6px;"+
- " height:8px;"+
- " margin-left:12px;"+
- " margin-right:2px;"+
- " cursor: pointer;"+
- " }"+
- " .checkbox_disabled {"+
- " display:inline-block;"+
- " width:6px;"+
- " height:8px;"+
- " background-color: #333;"+
- " border: 1px solid #eee;"+
- " margin-left:12px;"+
- " margin-right:2px;"+
- " cursor: pointer;"+
- " }"+
- " .checkbox_description {"+
- " font-size:11px;"+
- " font-family: helvetica, arial;"+
- " color: #fff;"+
- " }"+
- " .debug_tab {"+
- " font-family: helvetica, arial;"+
- " font-size: 12px;"+
- " color: #fff;"+
- " border-right: 1px solid #888;"+
- " float: left;"+
- " padding-left: 5px;"+
- " padding-right: 5px;"+
- " height: 20px;"+
- " padding-top: 5px;"+
- " cursor: default;"+
- " }"+
- " .debug_tab_selected {"+
- " background-color: #444;"+
- " cursor: default;"+
- " }"+
- " .debug_tab_not_selected {"+
- " background-color: #000;"+
- " cursor: pointer;"+
- " }"+
- " </style>"+
- " <div id=\"caat-debug\">"+
- " <div id=\"debug_tabs\">"+
- " <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>"+
- " <span id=\"caat-debug-tab0\" class=\"debug_tab debug_tab_selected\">Performance</span>"+
- " <span id=\"caat-debug-tab1\" class=\"debug_tab debug_tab_not_selected\">Controls</span>"+
- " <span class=\"caat_debug_indicator\">"+
- " <span class=\"caat_debug_bullet\" style=\"background-color:#0f0;\"></span>"+
- " <span class=\"caat_debug_description\">Draw Time: </span>"+
- " <span class=\"caat_debug_value\" id=\"textDrawTime\">5.46</span>"+
- " <span class=\"caat_debug_description\">ms.</span>"+
- " </span>"+
- " <span class=\"caat_debug_indicator\">"+
- " <span class=\"caat_debug_bullet\" style=\"background-color:#f00;\"></span>"+
- " <span class=\"caat_debug_description\">FPS: </span>"+
- " <span class=\"caat_debug_value\" id=\"textFPS\">48</span>"+
- " </span>"+
- " </div>"+
- " <div id=\"debug_tabs_content\" class=\"debug_tabs_content_hidden\">"+
- " <div id=\"caat-debug-tab0-content\">"+
- " <canvas id=\"caat-debug-canvas\" height=\"60\"></canvas>"+
- " <div>"+
- " <span>"+
- " <span class=\"caat_debug_bullet\" style=\"background-color:#0f0;\"></span>"+
- " <span class=\"caat_debug_description\">RAF Time:</span>"+
- " <span class=\"caat_debug_value\" id=\"textRAFTime\">20.76</span>"+
- " <span class=\"caat_debug_description\">ms.</span>"+
- " </span>"+
- " <span>"+
- " <span class=\"caat_debug_bullet\" style=\"background-color:#0ff;\"></span>"+
- " <span class=\"caat_debug_description\">Entities Total: </span>"+
- " <span class=\"caat_debug_value\" id=\"textEntitiesTotal\">41</span>"+
- " </span>"+
- " <span>"+
- " <span class=\"caat_debug_bullet\" style=\"background-color:#0ff;\"></span>"+
- " <span class=\"caat_debug_description\">Entities Active: </span>"+
- " <span class=\"caat_debug_value\" id=\"textEntitiesActive\">37</span>"+
- " </span>"+
- " <span>"+
- " <span class=\"caat_debug_bullet\" style=\"background-color:#00f;\"></span>"+
- " <span class=\"caat_debug_description\">Draws: </span>"+
- " <span class=\"caat_debug_value\" id=\"textDraws\">0</span>"+
- " </span>"+
- " <span>"+
- " <span class=\"caat_debug_bullet\" style=\"background-color:#00f;\"></span>"+
- " <span class=\"caat_debug_description\">DirtyRects: </span>"+
- " <span class=\"caat_debug_value\" id=\"textDirtyRects\">0</span>"+
- " </span>"+
- " </div>"+
- " </div>"+
- " <div id=\"caat-debug-tab1-content\">"+
- " <div>"+
- " <div>"+
- " <span id=\"control-sound\"></span>"+
- " <span class=\"checkbox_description\">Sound</span>"+
- " </div>"+
- " <div>"+
- " <span id=\"control-music\"></span>"+
- " <span class=\"checkbox_description\">Music</span>"+
- " </div>"+
- " <div>"+
- " <span id=\"control-aabb\"></span>"+
- " <span class=\"checkbox_description\">AA Bounding Boxes</span>"+
- " </div>"+
- " <div>"+
- " <span id=\"control-bb\"></span>"+
- " <span class=\"checkbox_description\">Bounding Boxes</span>"+
- " </div>"+
- " <div>"+
- " <span id=\"control-dr\"></span>"+
- " <span class=\"checkbox_description\">Dirty Rects</span>"+
- " </div>"+
- " </div>"+
- " </div>"+
- " </div>"+
- " </div>",
- setScale : function(s) {
- this.scale= s;
- return this;
- },
- initialize: function(w,h) {
- w= window.innerWidth;
- this.width= w;
- this.height= h;
- this.framerate = {
- refreshInterval: CAAT.FPS_REFRESH || 500, // refresh every ? ms, updating too quickly gives too large rounding errors
- frames: 0, // number offrames since last refresh
- timeLastRefresh: 0, // When was the framerate counter refreshed last
- fps: 0, // current framerate
- prevFps: -1, // previously drawn FPS
- fpsMin: 1000, // minimum measured framerate
- fpsMax: 0 // maximum measured framerate
- };
- var debugContainer= document.getElementById('caat-debug');
- if (!debugContainer) {
- var wrap = document.createElement('div');
- wrap.innerHTML=this.debugTpl;
- document.body.appendChild(wrap);
- eval( ""+
- " function initCheck( name, bool, callback ) {"+
- " var elem= document.getElementById(name);"+
- " if ( elem ) {"+
- " elem.className= (bool) ? \"checkbox_enabled\" : \"checkbox_disabled\";"+
- " if ( callback ) {"+
- " elem.addEventListener( \"click\", (function(elem, callback) {"+
- " return function(e) {"+
- " elem.__value= !elem.__value;"+
- " elem.className= (elem.__value) ? \"checkbox_enabled\" : \"checkbox_disabled\";"+
- " callback(e,elem.__value);"+
- " }"+
- " })(elem, callback), false );"+
- " }"+
- " elem.__value= bool;"+
- " }"+
- " }"+
- " function setupTabs() {"+
- " var numTabs=0;"+
- " var elem;"+
- " var elemContent;"+
- " do {"+
- " elem= document.getElementById(\"caat-debug-tab\"+numTabs);"+
- " if ( elem ) {"+
- " elemContent= document.getElementById(\"caat-debug-tab\"+numTabs+\"-content\");"+
- " if ( elemContent ) {"+
- " elemContent.style.display= numTabs===0 ? 'block' : 'none';"+
- " elem.className= numTabs===0 ? \"debug_tab debug_tab_selected\" : \"debug_tab debug_tab_not_selected\";"+
- " elem.addEventListener( \"click\", (function(tabIndex) {"+
- " return function(e) {"+
- " for( var i=0; i<numTabs; i++ ) {"+
- " var _elem= document.getElementById(\"caat-debug-tab\"+i);"+
- " var _elemContent= document.getElementById(\"caat-debug-tab\"+i+\"-content\");"+
- " _elemContent.style.display= i===tabIndex ? 'block' : 'none';"+
- " _elem.className= i===tabIndex ? \"debug_tab debug_tab_selected\" : \"debug_tab debug_tab_not_selected\";"+
- " }"+
- " }"+
- " })(numTabs), false );"+
- " }"+
- " numTabs++;"+
- " }"+
- " } while( elem );"+
- " }"+
- " initCheck( \"control-sound\", CAAT.director[0].isSoundEffectsEnabled(), function(e, bool) {"+
- " CAAT.director[0].setSoundEffectsEnabled(bool);"+
- " } );"+
- " initCheck( \"control-music\", CAAT.director[0].isMusicEnabled(), function(e, bool) {"+
- " CAAT.director[0].setMusicEnabled(bool);"+
- " } );"+
- " initCheck( \"control-aabb\", CAAT.DEBUGBB, function(e,bool) {"+
- " CAAT.DEBUGAABB= bool;"+
- " CAAT.director[0].currentScene.dirty= true;"+
- " } );"+
- " initCheck( \"control-bb\", CAAT.DEBUGBB, function(e,bool) {"+
- " CAAT.DEBUGBB= bool;"+
- " if ( bool ) {"+
- " CAAT.DEBUGAABB= true;"+
- " }"+
- " CAAT.director[0].currentScene.dirty= true;"+
- " } );"+
- " initCheck( \"control-dr\", CAAT.DEBUG_DIRTYRECTS , function( e,bool ) {"+
- " CAAT.DEBUG_DIRTYRECTS= bool;"+
- " });"+
- " setupTabs();" );
- }
- this.canvas= document.getElementById('caat-debug-canvas');
- if ( null===this.canvas ) {
- this.canDebug= false;
- return;
- }
- this.canvas.width= w;
- this.canvas.height=h;
- this.ctx= this.canvas.getContext('2d');
- this.ctx.fillStyle= '#000';
- this.ctx.fillRect(0,0,this.width,this.height);
- this.textFPS= document.getElementById("textFPS");
- this.textDrawTime= document.getElementById("textDrawTime");
- this.textRAFTime= document.getElementById("textRAFTime");
- this.textEntitiesTotal= document.getElementById("textEntitiesTotal");
- this.textEntitiesActive= document.getElementById("textEntitiesActive");
- this.textDraws= document.getElementById("textDraws");
- this.textDirtyRects= document.getElementById("textDirtyRects");
- this.canDebug= true;
- return this;
- },
- debugInfo : function( statistics ) {
- this.statistics= statistics;
- this.frameTimeAcc+= CAAT.FRAME_TIME;
- this.frameRAFAcc+= CAAT.REQUEST_ANIMATION_FRAME_TIME;
- /* Update the framerate counter */
- this.framerate.frames++;
- if ( CAAT.RAF > this.framerate.timeLastRefresh + this.framerate.refreshInterval ) {
- this.framerate.fps = ( ( this.framerate.frames * 1000 ) / ( CAAT.RAF - this.framerate.timeLastRefresh ) ) | 0;
- this.framerate.fpsMin = this.framerate.frames > 0 ? Math.min( this.framerate.fpsMin, this.framerate.fps ) : this.framerate.fpsMin;
- this.framerate.fpsMax = Math.max( this.framerate.fpsMax, this.framerate.fps );
- this.textFPS.innerHTML= this.framerate.fps;
- var value= ((this.frameTimeAcc*100/this.framerate.frames)|0)/100;
- this.frameTimeAcc=0;
- this.textDrawTime.innerHTML= value;
- var value2= ((this.frameRAFAcc*100/this.framerate.frames)|0)/100;
- this.frameRAFAcc=0;
- this.textRAFTime.innerHTML= value2;
- this.framerate.timeLastRefresh = CAAT.RAF;
- this.framerate.frames = 0;
- this.paint(value2);
- }
- this.textEntitiesTotal.innerHTML= this.statistics.size_total;
- this.textEntitiesActive.innerHTML= this.statistics.size_active;
- this.textDirtyRects.innerHTML= this.statistics.size_dirtyRects;
- this.textDraws.innerHTML= this.statistics.draws;
- },
- paint : function( rafValue ) {
- var ctx= this.ctx;
- var t=0;
- ctx.drawImage(
- this.canvas,
- 1, 0, this.width-1, this.height,
- 0, 0, this.width-1, this.height );
- ctx.strokeStyle= 'black';
- ctx.beginPath();
- ctx.moveTo( this.width-.5, 0 );
- ctx.lineTo( this.width-.5, this.height );
- ctx.stroke();
- ctx.strokeStyle= '#a22';
- ctx.beginPath();
- t= this.height-((20/this.SCALE*this.height)>>0)-.5;
- ctx.moveTo( .5, t );
- ctx.lineTo( this.width+.5, t );
- ctx.stroke();
- ctx.strokeStyle= '#aa2';
- ctx.beginPath();
- t= this.height-((30/this.SCALE*this.height)>>0)-.5;
- ctx.moveTo( .5, t );
- ctx.lineTo( this.width+.5, t );
- ctx.stroke();
- var fps = Math.min( this.height-(this.framerate.fps/this.SCALE*this.height), 59 );
- if (-1===this.framerate.prevFps) {
- this.framerate.prevFps= fps|0;
- }
- ctx.strokeStyle= '#0ff';//this.framerate.fps<15 ? 'red' : this.framerate.fps<30 ? 'yellow' : 'green';
- ctx.beginPath();
- ctx.moveTo( this.width, (fps|0)-.5 );
- ctx.lineTo( this.width, this.framerate.prevFps-.5 );
- ctx.stroke();
- this.framerate.prevFps= fps;
- var t1= ((this.height-(rafValue/this.SCALE*this.height))>>0)-.5;
- ctx.strokeStyle= '#ff0';
- ctx.beginPath();
- ctx.moveTo( this.width, t1 );
- ctx.lineTo( this.width, t1 );
- ctx.stroke();
- }
- };
- })();/**
- * See LICENSE file.
- *
- * Classes to define animable elements.
- * Actor is the superclass of every animable element in the scene graph. It handles the whole
- * affine transformation MatrixStack, rotation, translation, globalAlpha and Behaviours. It also
- * defines input methods.
- * TODO: add text presentation/animation effects.
- **/
- (function() {
- /**
- * This class is the base for all animable entities in CAAT.
- * It defines an entity able to:
- *
- * <ul>
- * <li>Position itself on screen.
- * <li>Able to modify its presentation aspect via affine transforms.
- * <li>Take control of parent/child relationship.
- * <li>Take track of behaviors (@see CAAT.Behavior).
- * <li>Define a region on screen.
- * <li>Define alpha composition scope.
- * <li>Expose lifecycle.
- * <li>Manage itself in/out scene time.
- * <li>etc.
- * </ul>
- *
- * @constructor
- */
- CAAT.Actor = function() {
- this.behaviorList= [];
- // this.keyframesList= [];
- this.lifecycleListenerList= [];
- this.AABB= new CAAT.Rectangle();
- this.viewVertices= [
- new CAAT.Point(0,0,0),
- new CAAT.Point(0,0,0),
- new CAAT.Point(0,0,0),
- new CAAT.Point(0,0,0)
- ];
- this.scaleAnchor= this.ANCHOR_CENTER;
- this.modelViewMatrix= new CAAT.Matrix();
- this.worldModelViewMatrix= new CAAT.Matrix();
- this.resetTransform();
- this.setScale(1,1);
- this.setRotation(0);
- return this;
- };
- /**
- * Reflection information needed to use the inspector.
- * Each key defined identifies an object field. For each field, it could be specified:
- * + get : accessor function or field name. if ended with () a function will be assumed.
- * + set : mutator function or field name. if ended with () a function will be assumed.
- * + type : field or accessor function return type.
- *
- * If not get or set method is defined, the inspector will assume either the field can't be read and/or set.
- * If neither get and set are defined, the property will be avoided.
- *
- * The key can contain a set of comma separated values. This means these properties must be set/modified
- * at once in the inspector editor field (if any). The way these functions will be set will be by calling
- * the set method (must be a method) as previously defined.
- */
- CAAT.Actor.__reflectionInfo= {
- "x" : "set:setX(), get:x, type:number",
- "cached" : "get:isCached(), type:boolean",
- "scaleX,scaleY" : "set:setScale(), type:number"
- /*
- "y" : "setY,w",
- "width" : "setWidth,w",
- "height" : "setHeight,w",
- "start_time" : "setStartTime,w",
- "duration" : "setDuration,w",
- "clip" : "setClip,w",
- "rotationAngle" : "setRotation,w",
- "alpha" : "setAlpha,w",
- "isGlobalAlpha" : "isGlobalAlpha,w",
- "visible" : "isVisible",
- "id" : "getId",
- "backgroundImage" : ""*/
- };
- CAAT.Actor.ANCHOR_CENTER= 0; // constant values to determine different affine transform
- CAAT.Actor.ANCHOR_TOP= 1; // anchors.
- CAAT.Actor.ANCHOR_BOTTOM= 2;
- CAAT.Actor.ANCHOR_LEFT= 3;
- CAAT.Actor.ANCHOR_RIGHT= 4;
- CAAT.Actor.ANCHOR_TOP_LEFT= 5;
- CAAT.Actor.ANCHOR_TOP_RIGHT= 6;
- CAAT.Actor.ANCHOR_BOTTOM_LEFT= 7;
- CAAT.Actor.ANCHOR_BOTTOM_RIGHT= 8;
- CAAT.Actor.ANCHOR_CUSTOM= 9;
- CAAT.Actor.CACHE_SIMPLE= 1;
- CAAT.Actor.CACHE_DEEP= 2;
- CAAT.Actor.prototype= {
- lifecycleListenerList: null, // Array of life cycle listener
- behaviorList: null, // Array of behaviors to apply to the Actor
- parent: null, // Parent of this Actor. May be Scene.
- x: 0, // x position on parent. In parent's local coord. system.
- y: 0, // y position on parent. In parent's local coord. system.
- width: 0, // Actor's width. In parent's local coord. system.
- height: 0, // Actor's height. In parent's local coord. system.
- start_time: 0, // Start time in Scene time.
- duration: Number.MAX_VALUE, // Actor duration in Scene time
- clip: false, // should clip the Actor's content against its contour.
- clipPath: null,
- tAnchorX : 0,
- tAnchorY : 0,
- scaleX: 0, // transformation. width scale parameter
- scaleY: 0, // transformation. height scale parameter
- scaleTX: .50, // transformation. scale anchor x position
- scaleTY: .50, // transformation. scale anchor y position
- scaleAnchor: 0, // transformation. scale anchor
- rotationAngle: 0, // transformation. rotation angle in radians
- rotationY: .50, // transformation. rotation center y
- alpha: 1, // alpha transparency value
- rotationX: .50, // transformation. rotation center x
- isGlobalAlpha: false, // is this a global alpha
- frameAlpha: 1, // hierarchically calculated alpha for this Actor.
- expired: false, // set when the actor has been expired
- discardable: false, // set when you want this actor to be removed if expired
- pointed: false, // is the mouse pointer inside this actor
- mouseEnabled: true, // events enabled ?
- visible: true,
- ANCHOR_CENTER: 0, // constant values to determine different affine transform
- ANCHOR_TOP: 1, // anchors.
- ANCHOR_BOTTOM: 2,
- ANCHOR_LEFT: 3,
- ANCHOR_RIGHT: 4,
- ANCHOR_TOP_LEFT: 5,
- ANCHOR_TOP_RIGHT: 6,
- ANCHOR_BOTTOM_LEFT: 7,
- ANCHOR_BOTTOM_RIGHT: 8,
- ANCHOR_CUSTOM: 9,
- fillStyle: null, // any canvas rendering valid fill style.
- strokeStyle: null, // any canvas rendering valid stroke style.
- time: 0, // Cache Scene time.
- AABB: null, // CAAT.Rectangle
- viewVertices: null, // model to view transformed vertices.
- inFrame: false, // boolean indicating whether this Actor was present on last frame.
- dirty: true, // model view is dirty ?
- wdirty: true, // world model view is dirty ?
- oldX: -1,
- oldY: -1,
-
- modelViewMatrix: null, // model view matrix.
- worldModelViewMatrix: null, // world model view matrix.
- modelViewMatrixI: null, // model view matrix.
- worldModelViewMatrixI: null, // world model view matrix.
- glEnabled: false,
- backgroundImage: null,
- id: null,
- size_active: 1, // number of animated children
- size_total: 1,
- __next: null,
- __d_ax: -1, // for drag-enabled actors.
- __d_ay: -1,
- gestureEnabled: false,
- invalid : true,
- cached : 0, // 0 no, CACHE_SIMPLE | CACHE_DEEP
- collides : false,
- collidesAsRect : true,
- isAA : true, // is this actor/container Axis aligned ? if so, much faster inverse matrices
- // can be calculated.
- isVisible : function() {
- return this.isVisible;
- },
- setupCollission : function( collides, isCircular ) {
- this.collides= collides;
- this.collidesAsRect= !isCircular;
- },
- invalidate : function() {
- this.invalid= true;
- },
- setGestureEnabled : function( enable ) {
- this.gestureEnabled= !!enable;
- },
- isGestureEnabled : function() {
- return this.gestureEnabled;
- },
- getId : function() {
- return this.id;
- },
- setId : function(id) {
- this.id= id;
- return this;
- },
- /**
- * Set this actor's parent.
- * @param parent {CAAT.ActorContainer}
- * @return this
- */
- setParent : function(parent) {
- this.parent= parent;
- return this;
- },
- /**
- * Set this actor's background image.
- * The need of a background image is to kept compatibility with the new CSSDirector class.
- * The image parameter can be either an Image/Canvas or a CAAT.SpriteImage instance. If an image
- * is supplied, it will be wrapped into a CAAT.SriteImage instance of 1 row by 1 column.
- * If the actor has set an image in the background, the paint method will draw the image, otherwise
- * and if set, will fill its background with a solid color.
- * If adjust_size_to_image is true, the host actor will be redimensioned to the size of one
- * single image from the SpriteImage (either supplied or generated because of passing an Image or
- * Canvas to the function). That means the size will be set to [width:SpriteImage.singleWidth,
- * height:singleHeight].
- *
- * WARN: if using a CSS renderer, the image supplied MUST be a HTMLImageElement instance.
- *
- * @see CAAT.SpriteImage
- *
- * @param image {Image|HTMLCanvasElement|CAAT.SpriteImage}
- * @param adjust_size_to_image {boolean} whether to set this actor's size based on image parameter.
- *
- * @return this
- */
- setBackgroundImage : function(image, adjust_size_to_image ) {
- if ( image ) {
- if ( !(image instanceof CAAT.SpriteImage) ) {
- image= new CAAT.SpriteImage().initialize(image,1,1);
- }
- image.setOwner(this);
- this.backgroundImage= image;
- if ( typeof adjust_size_to_image==='undefined' || adjust_size_to_image ) {
- this.width= image.getWidth();
- this.height= image.getHeight();
- }
- this.glEnabled= true;
- } else {
- this.backgroundImage= null;
- }
-
- return this;
- },
- /**
- * Set the actor's SpriteImage index from animation sheet.
- * @see CAAT.SpriteImage
- * @param index {number}
- *
- * @return this
- */
- setSpriteIndex: function(index) {
- if ( this.backgroundImage ) {
- this.backgroundImage.setSpriteIndex(index);
- this.invalidate();
- }
- return this;
- },
- /**
- * Set this actor's background SpriteImage offset displacement.
- * The values can be either positive or negative meaning the texture space of this background
- * image does not start at (0,0) but at the desired position.
- * @see CAAT.SpriteImage
- * @param ox {number} horizontal offset
- * @param oy {number} vertical offset
- *
- * @return this
- */
- setBackgroundImageOffset : function( ox, oy ) {
- if ( this.backgroundImage ) {
- this.backgroundImage.setOffset(ox,oy);
- }
- return this;
- },
- /**
- * Set this actor's background SpriteImage its animation sequence.
- * In its simplet's form a SpriteImage treats a given image as an array of rows by columns
- * subimages. If you define d Sprite Image of 2x2, you'll be able to draw any of the 4 subimages.
- * This method defines the animation sequence so that it could be set [0,2,1,3,2,1] as the
- * animation sequence
- * @param ii {Array<number>} an array of integers.
- */
- setAnimationImageIndex : function( ii ) {
- if ( this.backgroundImage ) {
- this.backgroundImage.setAnimationImageIndex(ii);
- }
- return this;
- },
- resetAnimationTime : function() {
- if ( this.backgroundImage ) {
- this.backgroundImage.resetAnimationTime();
- }
- return this;
- },
- setChangeFPS : function(time) {
- if ( this.backgroundImage ) {
- this.backgroundImage.setChangeFPS(time);
- }
- return this;
- },
- /**
- * Set this background image transformation.
- * If GL is enabled, this parameter has no effect.
- * @param it any value from CAAT.SpriteImage.TR_*
- * @return this
- */
- setImageTransformation : function( it ) {
- if ( this.backgroundImage ) {
- this.backgroundImage.setSpriteTransformation(it);
- }
- return this;
- },
- /**
- * Center this actor at position (x,y).
- * @param x {number} x position
- * @param y {number} y position
- *
- * @return this
- * @deprecated
- */
- centerOn : function( x,y ) {
- this.setLocation( x-this.width/2, y-this.height/2 );
- return this;
- },
- /**
- * Center this actor at position (x,y).
- * @param x {number} x position
- * @param y {number} y position
- *
- * @return this
- */
- centerAt : function(x,y) {
- return this.centerOn(x,y);
- },
- /**
- * If GL is enables, get this background image's texture page, otherwise it will fail.
- * @return {CAAT.GLTexturePage}
- */
- getTextureGLPage : function() {
- return this.backgroundImage.image.__texturePage;
- },
- /**
- * Set this actor invisible.
- * The actor is animated but not visible.
- * A container won't show any of its children if set visible to false.
- *
- * @param visible {boolean} set this actor visible or not.
- * @return this
- */
- setVisible : function(visible) {
- this.visible= visible;
- return this;
- },
- /**
- * Puts an Actor out of time line, that is, won't be transformed nor rendered.
- * @return this
- */
- setOutOfFrameTime : function() {
- this.setFrameTime(-1,0);
- return this;
- },
- /**
- * Adds an Actor's life cycle listener.
- * The developer must ensure the actorListener is not already a listener, otherwise
- * it will notified more than once.
- * @param actorListener {object} an object with at least a method of the form:
- * <code>actorLyfeCycleEvent( actor, string_event_type, long_time )</code>
- */
- addListener : function( actorListener ) {
- this.lifecycleListenerList.push(actorListener);
- return this;
- },
- /**
- * Removes an Actor's life cycle listener.
- * It will only remove the first occurrence of the given actorListener.
- * @param actorListener {object} an Actor's life cycle listener.
- */
- removeListener : function( actorListener ) {
- var n= this.lifecycleListenerList.length;
- while(n--) {
- if ( this.lifecycleListenerList[n]===actorListener ) {
- // remove the nth element.
- this.lifecycleListenerList.splice(n,1);
- return;
- }
- }
- },
- /**
- * Set alpha composition scope. global will mean this alpha value will be its children maximum.
- * If set to false, only this actor will have this alpha value.
- * @param global {boolean} whether the alpha value should be propagated to children.
- */
- setGlobalAlpha : function( global ) {
- this.isGlobalAlpha= global;
- return this;
- },
- /**
- * Notifies the registered Actor's life cycle listener about some event.
- * @param sEventType an string indicating the type of event being notified.
- * @param time an integer indicating the time related to Scene's timeline when the event
- * is being notified.
- */
- fireEvent : function(sEventType, time) {
- for( var i=0; i<this.lifecycleListenerList.length; i++ ) {
- this.lifecycleListenerList[i].actorLifeCycleEvent(this, sEventType, time);
- }
- },
- /**
- * Sets this Actor as Expired.
- * If this is a Container, all the contained Actors won't be nor drawn nor will receive
- * any event. That is, expiring an Actor means totally taking it out the Scene's timeline.
- * @param time {number} an integer indicating the time the Actor was expired at.
- * @return this.
- */
- setExpired : function(time) {
- this.expired= true;
- this.fireEvent('expired',time);
- return this;
- },
- /**
- * Enable or disable the event bubbling for this Actor.
- * @param enable {boolean} a boolean indicating whether the event bubbling is enabled.
- * @return this
- */
- enableEvents : function( enable ) {
- this.mouseEnabled= enable;
- return this;
- },
- /**
- * Removes all behaviors from an Actor.
- * @return this
- */
- emptyBehaviorList : function() {
- this.behaviorList=[];
- return this;
- },
- /**
- * Caches a fillStyle in the Actor.
- * @param style a valid Canvas rendering context fillStyle.
- * @return this
- */
- setFillStyle : function( style ) {
- this.fillStyle= style;
- return this;
- },
- /**
- * Caches a stroke style in the Actor.
- * @param style a valid canvas rendering context stroke style.
- * @return this
- */
- setStrokeStyle : function( style ) {
- this.strokeStyle= style;
- return this;
- },
- /**
- * @deprecated
- * @param paint
- */
- setPaint : function( paint ) {
- return this.setFillStyle(paint);
- },
- /**
- * Stablishes the Alpha transparency for the Actor.
- * If it globalAlpha enabled, this alpha will the maximum alpha for every contained actors.
- * The alpha must be between 0 and 1.
- * @param alpha a float indicating the alpha value.
- * @return this
- */
- setAlpha : function( alpha ) {
- this.alpha= alpha;
- this.invalidate();
- return this;
- },
- /**
- * Remove all transformation values for the Actor.
- * @return this
- */
- resetTransform : function () {
- this.rotationAngle=0;
- this.rotationX=.5;
- this.rotationY=.5;
- this.scaleX=1;
- this.scaleY=1;
- this.scaleTX=.5;
- this.scaleTY=.5;
- this.scaleAnchor=0;
- this.oldX=-1;
- this.oldY=-1;
- this.dirty= true;
- return this;
- },
- /**
- * Sets the time life cycle for an Actor.
- * These values are related to Scene time.
- * @param startTime an integer indicating the time until which the Actor won't be visible on the Scene.
- * @param duration an integer indicating how much the Actor will last once visible.
- * @return this
- */
- setFrameTime : function( startTime, duration ) {
- this.start_time= startTime;
- this.duration= duration;
- this.expired= false;
- this.dirty= true;
- return this;
- },
- /**
- * This method should me overriden by every custom Actor.
- * It will be the drawing routine called by the Director to show every Actor.
- * @param director the CAAT.Director instance that contains the Scene the Actor is in.
- * @param time an integer indicating the Scene time in which the drawing is performed.
- */
- paint : function(director, time) {
- if ( this.backgroundImage ) {
- this.backgroundImage.paint(director,time,0,0);
- } else if ( this.fillStyle ) {
- var ctx= director.crc;
- ctx.fillStyle= this.fillStyle;
- ctx.fillRect(0,0,this.width,this.height );
- }
- },
- /**
- * A helper method to setScaleAnchored with an anchor of ANCHOR_CENTER
- *
- * @see setScaleAnchored
- *
- * @param sx a float indicating a width size multiplier.
- * @param sy a float indicating a height size multiplier.
- * @return this
- */
- setScale : function( sx, sy ) {
- this.scaleX=sx;
- this.scaleY=sy;
- this.dirty= true;
- return this;
- },
- getAnchorPercent : function( anchor ) {
- var anchors=[
- .50,.50, .50,0, .50,1.00,
- 0,.50, 1.00,.50, 0,0,
- 1.00,0, 0,1.00, 1.00,1.00
- ];
- return { x: anchors[anchor*2], y: anchors[anchor*2+1] };
- },
- /**
- * Private.
- * Gets a given anchor position referred to the Actor.
- * @param anchor
- * @return an object of the form { x: float, y: float }
- */
- getAnchor : function( anchor ) {
- var tx=0, ty=0;
- switch( anchor ) {
- case this.ANCHOR_CENTER:
- tx= .5;
- ty= .5;
- break;
- case this.ANCHOR_TOP:
- tx= .5;
- ty= 0;
- break;
- case this.ANCHOR_BOTTOM:
- tx= .5;
- ty= 1;
- break;
- case this.ANCHOR_LEFT:
- tx= 0;
- ty= .5;
- break;
- case this.ANCHOR_RIGHT:
- tx= 1;
- ty= .5;
- break;
- case this.ANCHOR_TOP_RIGHT:
- tx= 1;
- ty= 0;
- break;
- case this.ANCHOR_BOTTOM_LEFT:
- tx= 0;
- ty= 1;
- break;
- case this.ANCHOR_BOTTOM_RIGHT:
- tx= 1;
- ty= 1;
- break;
- case this.ANCHOR_TOP_LEFT:
- tx= 0;
- ty= 0;
- break;
- }
- return {x: tx, y: ty};
- },
- setGlobalAnchor : function( ax, ay ) {
- this.tAnchorX= ax;
- this.rotationX= ax;
- this.scaleTX= ax;
- this.tAnchorY= ay;
- this.rotationY= ay;
- this.scaleTY= ay;
- this.dirty= true;
- return this;
- },
- setScaleAnchor : function( sax, say ) {
- this.scaleTX= sax;
- this.scaleTY= say;
- this.dirty= true;
- return this;
- },
- /**
- * Modify the dimensions on an Actor.
- * The dimension will not affect the local coordinates system in opposition
- * to setSize or setBounds.
- *
- * @param sx {number} width scale.
- * @param sy {number} height scale.
- * @param anchorx {number} x anchor to perform the Scale operation.
- * @param anchory {number} y anchor to perform the Scale operation.
- *
- * @return this;
- */
- setScaleAnchored : function( sx, sy, anchorx, anchory ) {
- this.scaleTX= anchorx;
- this.scaleTY= anchory;
- this.scaleX=sx;
- this.scaleY=sy;
- this.dirty= true;
- return this;
- },
- setRotationAnchor : function( rax, ray ) {
- this.rotationX= ray;
- this.rotationY= rax;
- this.dirty= true;
- return this;
- },
- /**
- * A helper method for setRotationAnchored. This methods stablishes the center
- * of rotation to be the center of the Actor.
- *
- * @param angle a float indicating the angle in radians to rotate the Actor.
- * @return this
- */
- setRotation : function( angle ) {
- this.rotationAngle= angle;
- this.dirty= true;
- return this;
- },
- /**
- * This method sets Actor rotation around a given position.
- * @param angle {number} indicating the angle in radians to rotate the Actor.
- * @param rx {number} value in the range 0..1
- * @param ry {number} value in the range 0..1
- * @return this;
- */
- setRotationAnchored : function( angle, rx, ry ) {
- this.rotationAngle= angle;
- this.rotationX= rx;
- this.rotationY= ry;
- this.dirty= true;
- return this;
- },
- /**
- * Sets an Actor's dimension
- * @param w a float indicating Actor's width.
- * @param h a float indicating Actor's height.
- * @return this
- */
- setSize : function( w, h ) {
- this.width= w|0;
- this.height= h|0;
- this.dirty= true;
- return this;
- },
- /**
- * Set location and dimension of an Actor at once.
- *
- * @param x{number} a float indicating Actor's x position.
- * @param y{number} a float indicating Actor's y position
- * @param w{number} a float indicating Actor's width
- * @param h{number} a float indicating Actor's height
- * @return this
- */
- setBounds : function(x, y, w, h) {
- /*
- this.x= x|0;
- this.y= y|0;
- this.width= w|0;
- this.height= h|0;
- */
- this.x= x;
- this.y= y;
- this.width= w;
- this.height= h;
- this.dirty= true;
- return this;
- },
- /**
- * This method sets the position of an Actor inside its parent.
- *
- * @param x{number} a float indicating Actor's x position
- * @param y{number} a float indicating Actor's y position
- * @return this
- *
- * @deprecated
- */
- setLocation : function( x, y ) {
- this.x= x;
- this.y= y;
- this.oldX= x;
- this.oldY= y;
- this.dirty= true;
- return this;
- },
- setPosition : function( x,y ) {
- return this.setLocation( x,y );
- },
- setPositionAnchor : function( pax, pay ) {
- this.tAnchorX= pax;
- this.tAnchorY= pay;
- return this;
- },
- setPositionAnchored : function( x,y,pax,pay ) {
- this.setLocation( x,y );
- this.tAnchorX= pax;
- this.tAnchorY= pay;
- return this;
- },
- /**
- * This method is called by the Director to know whether the actor is on Scene time.
- * In case it was necessary, this method will notify any life cycle behaviors about
- * an Actor expiration.
- * @param time {number} time indicating the Scene time.
- *
- * @private
- *
- */
- isInAnimationFrame : function(time) {
- if ( this.expired ) {
- return false;
- }
- if ( this.duration===Number.MAX_VALUE ) {
- return this.start_time<=time;
- }
- if ( time>=this.start_time+this.duration ) {
- if ( !this.expired ) {
- this.setExpired(time);
- }
- return false;
- }
- return this.start_time<=time && time<this.start_time+this.duration;
- },
- /**
- * Checks whether a coordinate is inside the Actor's bounding box.
- * @param x {number} a float
- * @param y {number} a float
- *
- * @return boolean indicating whether it is inside.
- */
- contains : function(x, y) {
- return x>=0 && y>=0 && x<this.width && y<this.height;
- },
- /**
- * This method must be called explicitly by every CAAT Actor.
- * Making the life cycle explicitly initiated has always been a good idea.
- *
- * @return this
- * @deprecated no longer needed.
- */
- create : function() {
- return this;
- },
- /**
- * Add a Behavior to the Actor.
- * An Actor accepts an undefined number of Behaviors.
- *
- * @param behavior {CAAT.Behavior} a CAAT.Behavior instance
- * @return this
- *
- * @deprecated
- */
- addBehavior : function( behavior ) {
- this.behaviorList.push(behavior);
- return this;
- },
- /**
- * Remove a Behavior from the Actor.
- * If the Behavior is not present at the actor behavior collection nothing happends.
- *
- * @param behavior {CAAT.Behavior} a CAAT.Behavior instance.
- */
- removeBehaviour : function( behavior ) {
- var c= this.behaviorList;
- var n= c.length-1;
- while(n) {
- if ( c[n]===behavior ) {
- c.splice(n,1);
- return this;
- }
- }
- return this;
- },
- /**
- * Remove a Behavior with id param as behavior identifier from this actor.
- * This function will remove ALL behavior instances with the given id.
- *
- * @param id {number} an integer.
- * return this;
- */
- removeBehaviorById : function( id ) {
- var c= this.behaviorList;
- for( var n=0; n<c.length; n++ ) {
- if ( c[n].id===id) {
- c.splice(n,1);
- }
- }
- return this;
- },
- getBehavior : function(id) {
- var c= this.behaviorList;
- for( var n=0; n<c.length; n++ ) {
- var cc= c[n];
- if ( cc.id===id) {
- return cc;
- }
- }
- return null;
- },
- /**
- * Set discardable property. If an actor is discardable, upon expiration will be removed from
- * scene graph and hence deleted.
- * @param discardable {boolean} a boolean indicating whether the Actor is discardable.
- * @return this
- */
- setDiscardable : function( discardable ) {
- this.discardable= discardable;
- return this;
- },
- /**
- * This method will be called internally by CAAT when an Actor is expired, and at the
- * same time, is flagged as discardable.
- * It notifies the Actor life cycle listeners about the destruction event.
- *
- * @param time an integer indicating the time at wich the Actor has been destroyed.
- *
- * @private
- *
- */
- destroy : function(time) {
- if ( this.parent ) {
- this.parent.removeChild(this);
- }
- this.fireEvent('destroyed',time);
- },
- /**
- * Transform a point or array of points in model space to view space.
- *
- * @param point {CAAT.Point|Array} an object of the form {x : float, y: float}
- *
- * @return the source transformed elements.
- *
- * @private
- *
- */
- modelToView : function(point) {
- if ( this.dirty ) {
- this.setModelViewMatrix();
- }
- var tm= this.worldModelViewMatrix.matrix;
- if ( point instanceof Array ) {
- for( var i=0; i<point.length; i++ ) {
- //this.worldModelViewMatrix.transformCoord(point[i]);
- var pt= point[i];
- var x= pt.x;
- var y= pt.y;
- pt.x= x*tm[0] + y*tm[1] + tm[2];
- pt.y= x*tm[3] + y*tm[4] + tm[5];
- }
- }
- else {
- // this.worldModelViewMatrix.transformCoord(point);
- var x= point.x;
- var y= point.y;
- point.x= x*tm[0] + y*tm[1] + tm[2];
- point.y= x*tm[3] + y*tm[4] + tm[5];
- }
- return point;
- },
- /**
- * Transform a local coordinate point on this Actor's coordinate system into
- * another point in otherActor's coordinate system.
- * @param point {CAAT.Point}
- * @param otherActor {CAAT.Actor}
- */
- modelToModel : function( point, otherActor ) {
- if ( this.dirty ) {
- this.setModelViewMatrix();
- }
- return otherActor.viewToModel( this.modelToView( point ) );
- },
- /**
- * Transform a point from model to view space.
- * <p>
- * WARNING: every call to this method calculates
- * actor's world model view matrix.
- *
- * @param point {CAAT.Point} a point in screen space to be transformed to model space.
- *
- * @return the source point object
- *
- *
- */
- viewToModel : function(point) {
- if ( this.dirty ) {
- this.setModelViewMatrix();
- }
- this.worldModelViewMatrixI= this.worldModelViewMatrix.getInverse();
- this.worldModelViewMatrixI.transformCoord(point);
- return point;
- },
- /**
- * Private
- * This method does the needed point transformations across an Actor hierarchy to devise
- * whether the parameter point coordinate lies inside the Actor.
- * @param point {CAAT.Point}
- *
- * @return null if the point is not inside the Actor. The Actor otherwise.
- */
- findActorAtPosition : function(point) {
- if ( !this.visible || !this.mouseEnabled || !this.isInAnimationFrame(this.time) ) {
- return null;
- }
- this.modelViewMatrixI= this.modelViewMatrix.getInverse();
- this.modelViewMatrixI.transformCoord(point);
- return this.contains(point.x, point.y) ? this :null;
- },
- /**
- * Enables a default dragging routine for the Actor.
- * This default dragging routine allows to:
- * <li>scale the Actor by pressing shift+drag
- * <li>rotate the Actor by pressing control+drag
- * <li>scale non uniformly by pressing alt+shift+drag
- *
- * @return this
- */
- enableDrag : function() {
- var me= this;
- this.ax= 0;
- this.ay= 0;
- this.mx= 0;
- this.my= 0;
- this.asx=1;
- this.asy=1;
- this.ara=0;
- this.screenx=0;
- this.screeny=0;
- /**
- * Mouse enter handler for default drag behavior.
- * @param mouseEvent {CAAT.MouseEvent}
- *
- * @ignore
- */
- this.mouseEnter= function(mouseEvent) {
- this.__d_ax= -1;
- this.__d_ay= -1;
- this.pointed= true;
- CAAT.setCursor('move');
- };
- /**
- * Mouse exit handler for default drag behavior.
- * @param mouseEvent {CAAT.MouseEvent}
- *
- * @ignore
- */
- this.mouseExit = function(mouseEvent) {
- this.__d_ax = -1;
- this.__d_ay = -1;
- this.pointed = false;
- CAAT.setCursor('default');
- };
- /**
- * Mouse move handler for default drag behavior.
- * @param mouseEvent {CAAT.MouseEvent}
- *
- * @ignore
- */
- this.mouseMove = function(mouseEvent) {
- };
- /**
- * Mouse up handler for default drag behavior.
- * @param mouseEvent {CAAT.MouseEvent}
- *
- * @ignore
- */
- this.mouseUp = function(mouseEvent) {
- this.__d_ax = -1;
- this.__d_ay = -1;
- };
- /**
- * Mouse drag handler for default drag behavior.
- * @param mouseEvent {CAAT.MouseEvent}
- *
- * @ignore
- */
- this.mouseDrag = function(mouseEvent) {
- var pt;
- pt= this.modelToView( new CAAT.Point(mouseEvent.x, mouseEvent.y ) );
- this.parent.viewToModel( pt );
- if (this.__d_ax === -1 || this.__d_ay === -1) {
- this.__d_ax = pt.x;
- this.__d_ay = pt.y;
- this.__d_asx = this.scaleX;
- this.__d_asy = this.scaleY;
- this.__d_ara = this.rotationAngle;
- this.__d_screenx = mouseEvent.screenPoint.x;
- this.__d_screeny = mouseEvent.screenPoint.y;
- }
- if (mouseEvent.isShiftDown()) {
- var scx = (mouseEvent.screenPoint.x - this.__d_screenx) / 100;
- var scy = (mouseEvent.screenPoint.y - this.__d_screeny) / 100;
- if (!mouseEvent.isAltDown()) {
- var sc = Math.max(scx, scy);
- scx = sc;
- scy = sc;
- }
- this.setScale(scx + this.__d_asx, scy + this.__d_asy);
- } else if (mouseEvent.isControlDown()) {
- var vx = mouseEvent.screenPoint.x - this.__d_screenx;
- var vy = mouseEvent.screenPoint.y - this.__d_screeny;
- this.setRotation(-Math.atan2(vx, vy) + this.__d_ara);
- } else {
- this.x += pt.x-this.__d_ax;
- this.y += pt.y-this.__d_ay;
- }
- this.__d_ax= pt.x;
- this.__d_ay= pt.y;
- };
- return this;
- },
- /**
- * Default mouseClick handler.
- * Mouse click events are received after a call to mouseUp method if no dragging was in progress.
- *
- * @param mouseEvent {CAAT.MouseEvent}
- */
- mouseClick : function(mouseEvent) {
- },
- /**
- * Default double click handler
- *
- * @param mouseEvent {CAAT.MouseEvent}
- */
- mouseDblClick : function(mouseEvent) {
- },
- /**
- * Default mouse enter on Actor handler.
- * @param mouseEvent {CAAT.MouseEvent}
- */
- mouseEnter : function(mouseEvent) {
- this.pointed= true;
- },
- /**
- * Default mouse exit on Actor handler.
- *
- * @param mouseEvent {CAAT.MouseEvent}
- */
- mouseExit : function(mouseEvent) {
- this.pointed= false;
- },
- /**
- * Default mouse move inside Actor handler.
- *
- * @param mouseEvent {CAAT.MouseEvent}
- */
- mouseMove : function(mouseEvent) {
- },
- /**
- * default mouse press in Actor handler.
- *
- * @param mouseEvent {CAAT.MouseEvent}
- */
- mouseDown : function(mouseEvent) {
- },
- /**
- * default mouse release in Actor handler.
- *
- * @param mouseEvent {CAAT.MouseEvent}
- */
- mouseUp : function(mouseEvent) {
- },
- mouseOut : function(mouseEvent) {
- },
- mouseOver : function(mouseEvent) {
- },
- /**
- * default Actor mouse drag handler.
- *
- * @param mouseEvent {CAAT.MouseEvent}
- */
- mouseDrag : function(mouseEvent) {
- },
- /**
- * Draw a bounding box with on-screen coordinates regardless of the transformations
- * applied to the Actor.
- *
- * @param director {CAAT.Director} object instance that contains the Scene the Actor is in.
- * @param time {number} integer indicating the Scene time when the bounding box is to be drawn.
- */
- drawScreenBoundingBox : function( director, time ) {
- if ( null!==this.AABB && this.inFrame ) {
- var s= this.AABB;
- var ctx= director.ctx;
- ctx.strokeStyle= CAAT.DEBUGAABBCOLOR;
- ctx.strokeRect( .5+(s.x|0), .5+(s.y|0), s.width|0, s.height|0 );
- if ( CAAT.DEBUGBB ) {
- var vv= this.viewVertices;
- ctx.beginPath( );
- ctx.lineTo( vv[0].x, vv[0].y );
- ctx.lineTo( vv[1].x, vv[1].y );
- ctx.lineTo( vv[2].x, vv[2].y );
- ctx.lineTo( vv[3].x, vv[3].y );
- ctx.closePath();
- ctx.strokeStyle= CAAT.DEBUGBBCOLOR;
- ctx.stroke();
- }
- }
- },
- /**
- * Private
- * This method is called by the Director instance.
- * It applies the list of behaviors the Actor has registered.
- *
- * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
- * @param time an integer indicating the Scene time when the bounding box is to be drawn.
- */
- animate : function(director, time) {
- var i;
- if ( !this.isInAnimationFrame(time) ) {
- this.inFrame= false;
- this.dirty= true;
- return false;
- }
- if ( this.x!==this.oldX || this.y!==this.oldY ) {
- this.dirty= true;
- this.oldX= this.x;
- this.oldY= this.y;
- }
- for( i=0; i<this.behaviorList.length; i++ ) {
- this.behaviorList[i].apply(time,this);
- }
- if ( this.clipPath ) {
- this.clipPath.applyBehaviors(time);
- }
- // transformation stuff.
- this.setModelViewMatrix();
- if ( this.dirty || this.wdirty || this.invalid ) {
- if ( director.dirtyRectsEnabled ) {
- director.addDirtyRect( this.AABB );
- }
- this.setScreenBounds();
- if ( director.dirtyRectsEnabled ) {
- director.addDirtyRect( this.AABB );
- }
- }
- this.dirty= false;
- this.invalid= false;
- this.inFrame= true;
- return this.AABB.intersects( director.AABB );
- //return true;
- },
- /**
- * Set this model view matrix if the actor is Dirty.
- *
- mm[2]+= this.x;
- mm[5]+= this.y;
- if ( this.rotationAngle ) {
- this.modelViewMatrix.multiply( m.setTranslate( this.rotationX, this.rotationY) );
- this.modelViewMatrix.multiply( m.setRotation( this.rotationAngle ) );
- this.modelViewMatrix.multiply( m.setTranslate( -this.rotationX, -this.rotationY) ); c= Math.cos( this.rotationAngle );
- }
- if ( this.scaleX!=1 || this.scaleY!=1 && (this.scaleTX || this.scaleTY )) {
- this.modelViewMatrix.multiply( m.setTranslate( this.scaleTX , this.scaleTY ) );
- this.modelViewMatrix.multiply( m.setScale( this.scaleX, this.scaleY ) );
- this.modelViewMatrix.multiply( m.setTranslate( -this.scaleTX , -this.scaleTY ) );
- }
- *
- * @return this
- */
- setModelViewMatrix : function() {
- var c,s,_m00,_m01,_m10,_m11;
- var mm0, mm1, mm2, mm3, mm4, mm5;
- var mm;
- this.wdirty= false;
- mm= this.modelViewMatrix.matrix;
- if ( this.dirty ) {
- mm0= 1;
- mm1= 0;
- //mm2= mm[2];
- mm3= 0;
- mm4= 1;
- //mm5= mm[5];
- mm2= this.x - this.tAnchorX * this.width ;
- mm5= this.y - this.tAnchorY * this.height;
- if ( this.rotationAngle ) {
- var rx= this.rotationX*this.width;
- var ry= this.rotationY*this.height;
- mm2+= mm0*rx + mm1*ry;
- mm5+= mm3*rx + mm4*ry;
- c= Math.cos( this.rotationAngle );
- s= Math.sin( this.rotationAngle );
- _m00= mm0;
- _m01= mm1;
- _m10= mm3;
- _m11= mm4;
- mm0= _m00*c + _m01*s;
- mm1= -_m00*s + _m01*c;
- mm3= _m10*c + _m11*s;
- mm4= -_m10*s + _m11*c;
- mm2+= -mm0*rx - mm1*ry;
- mm5+= -mm3*rx - mm4*ry;
- }
- if ( this.scaleX!=1 || this.scaleY!=1 ) {
- var sx= this.scaleTX*this.width;
- var sy= this.scaleTY*this.height;
- mm2+= mm0*sx + mm1*sy;
- mm5+= mm3*sx + mm4*sy;
- mm0= mm0*this.scaleX;
- mm1= mm1*this.scaleY;
- mm3= mm3*this.scaleX;
- mm4= mm4*this.scaleY;
- mm2+= -mm0*sx - mm1*sy;
- mm5+= -mm3*sx - mm4*sy;
- }
- mm[0]= mm0;
- mm[1]= mm1;
- mm[2]= mm2;
- mm[3]= mm3;
- mm[4]= mm4;
- mm[5]= mm5;
- }
- if ( this.parent ) {
- this.isAA= this.rotationAngle===0 && this.scaleX===1 && this.scaleY===1 && this.parent.isAA;
- if ( this.dirty || this.parent.wdirty ) {
- this.worldModelViewMatrix.copy( this.parent.worldModelViewMatrix );
- if ( this.isAA ) {
- var mmm= this.worldModelViewMatrix.matrix;
- mmm[2]+= mm[2];
- mmm[5]+= mm[5];
- } else {
- this.worldModelViewMatrix.multiply( this.modelViewMatrix );
- }
- this.wdirty= true;
- }
- } else {
- if ( this.dirty ) {
- this.wdirty= true;
- }
- this.worldModelViewMatrix.identity();
- this.isAA= this.rotationAngle===0 && this.scaleX===1 && this.scaleY===1;
- }
- //if ( (CAAT.DEBUGAABB || glEnabled) && (this.dirty || this.wdirty ) ) {
- // screen bounding boxes will always be calculated.
- /*
- if ( this.dirty || this.wdirty || this.invalid ) {
- if ( director.dirtyRectsEnabled ) {
- director.addDirtyRect( this.AABB );
- }
- this.setScreenBounds();
- if ( director.dirtyRectsEnabled ) {
- director.addDirtyRect( this.AABB );
- }
- }
- this.dirty= false;
- this.invalid= false;
- */
- },
- /**
- * Calculates the 2D bounding box in canvas coordinates of the Actor.
- * This bounding box takes into account the transformations applied hierarchically for
- * each Scene Actor.
- *
- * @private
- *
- */
- setScreenBounds : function() {
- var AABB= this.AABB;
- var vv= this.viewVertices;
- if ( this.isAA ) {
- var m= this.worldModelViewMatrix.matrix;
- var x= m[2];
- var y= m[5];
- var w= this.width;
- var h= this.height;
- AABB.x= x;
- AABB.y= y;
- AABB.x1= x + w;
- AABB.y1= y + h;
- AABB.width= w;
- AABB.height= h;
- if ( CAAT.GLRENDER ) {
- var vvv;
- vvv= vv[0];
- vvv.x=x;
- vvv.y=y;
- vvv= vv[1];
- vvv.x=x+w;
- vvv.y=y;
- vvv= vv[2];
- vvv.x=x+w;
- vvv.y=y+h;
- vvv= vv[3];
- vvv.x=x;
- vvv.y=y+h;
- }
- return this;
- }
- var vvv;
- vvv= vv[0];
- vvv.x=0;
- vvv.y=0;
- vvv= vv[1];
- vvv.x=this.width;
- vvv.y=0;
- vvv= vv[2];
- vvv.x=this.width;
- vvv.y=this.height;
- vvv= vv[3];
- vvv.x=0;
- vvv.y=this.height;
- this.modelToView( this.viewVertices );
- var xmin= Number.MAX_VALUE, xmax=-Number.MAX_VALUE;
- var ymin= Number.MAX_VALUE, ymax=-Number.MAX_VALUE;
- vvv= vv[0];
- if ( vvv.x < xmin ) {
- xmin=vvv.x;
- }
- if ( vvv.x > xmax ) {
- xmax=vvv.x;
- }
- if ( vvv.y < ymin ) {
- ymin=vvv.y;
- }
- if ( vvv.y > ymax ) {
- ymax=vvv.y;
- }
- var vvv= vv[1];
- if ( vvv.x < xmin ) {
- xmin=vvv.x;
- }
- if ( vvv.x > xmax ) {
- xmax=vvv.x;
- }
- if ( vvv.y < ymin ) {
- ymin=vvv.y;
- }
- if ( vvv.y > ymax ) {
- ymax=vvv.y;
- }
- var vvv= vv[2];
- if ( vvv.x < xmin ) {
- xmin=vvv.x;
- }
- if ( vvv.x > xmax ) {
- xmax=vvv.x;
- }
- if ( vvv.y < ymin ) {
- ymin=vvv.y;
- }
- if ( vvv.y > ymax ) {
- ymax=vvv.y;
- }
- var vvv= vv[3];
- if ( vvv.x < xmin ) {
- xmin=vvv.x;
- }
- if ( vvv.x > xmax ) {
- xmax=vvv.x;
- }
- if ( vvv.y < ymin ) {
- ymin=vvv.y;
- }
- if ( vvv.y > ymax ) {
- ymax=vvv.y;
- }
- AABB.x= xmin;
- AABB.y= ymin;
- AABB.x1= xmax;
- AABB.y1= ymax;
- AABB.width= (xmax-xmin);
- AABB.height= (ymax-ymin);
- return this;
- },
- /**
- * @private.
- * This method will be called by the Director to set the whole Actor pre-render process.
- *
- * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
- * @param time an integer indicating the Scene time when the bounding box is to be drawn.
- *
- * @return boolean indicating whether the Actor isInFrameTime
- */
- paintActor : function(director, time) {
- if (!this.visible) {
- return true;
- }
- var ctx= director.ctx;
- this.frameAlpha= this.parent ? this.parent.frameAlpha*this.alpha : 1;
- ctx.globalAlpha= this.frameAlpha;
- director.modelViewMatrix.transformRenderingContextSet( ctx );
- this.worldModelViewMatrix.transformRenderingContext(ctx);
- if ( this.clip ) {
- ctx.beginPath();
- if (!this.clipPath ) {
- ctx.rect(0,0,this.width,this.height);
- } else {
- this.clipPath.applyAsPath(director);
- }
- ctx.clip();
- }
- this.paint(director, time);
- return true;
- },
- /**
- * for js2native
- * @param director
- * @param time
- */
- __paintActor : function(director, time) {
- if (!this.visible) {
- return true;
- }
- var ctx= director.ctx;
- // global opt: set alpha as owns alpha, not take globalAlpha procedure.
- this.frameAlpha= this.alpha;
- var m= this.worldModelViewMatrix.matrix;
- ctx.setTransform( m[0], m[3], m[1], m[4], m[2], m[5], this.frameAlpha );
- this.paint(director, time);
- return true;
- },
- /**
- * Set coordinates and uv values for this actor.
- * This function uses Director's coords and indexCoords values.
- * @param director
- * @param time
- */
- paintActorGL : function(director,time) {
- this.frameAlpha= this.parent.frameAlpha*this.alpha;
- if ( !this.glEnabled || !this.visible) {
- return;
- }
- if ( this.glNeedsFlush(director) ) {
- director.glFlush();
- this.glSetShader(director);
- if ( !this.__uv ) {
- this.__uv= new Float32Array(8);
- }
- if ( !this.__vv ) {
- this.__vv= new Float32Array(12);
- }
- this.setGLCoords( this.__vv, 0 );
- this.setUV( this.__uv, 0 );
- director.glRender(this.__vv, 12, this.__uv);
- return;
- }
- var glCoords= director.coords;
- var glCoordsIndex= director.coordsIndex;
- ////////////////// XYZ
- this.setGLCoords(glCoords, glCoordsIndex);
- director.coordsIndex= glCoordsIndex+12;
- ////////////////// UV
- this.setUV( director.uv, director.uvIndex );
- director.uvIndex+= 8;
- },
- /**
- * TODO: set GLcoords for different image transformations.
- * @param glCoords
- * @param glCoordsIndex
- * @param z
- */
- setGLCoords : function( glCoords, glCoordsIndex ) {
- var vv= this.viewVertices;
- glCoords[glCoordsIndex++]= vv[0].x;
- glCoords[glCoordsIndex++]= vv[0].y;
- glCoords[glCoordsIndex++]= 0;
- glCoords[glCoordsIndex++]= vv[1].x;
- glCoords[glCoordsIndex++]= vv[1].y;
- glCoords[glCoordsIndex++]= 0;
- glCoords[glCoordsIndex++]= vv[2].x;
- glCoords[glCoordsIndex++]= vv[2].y;
- glCoords[glCoordsIndex++]= 0;
- glCoords[glCoordsIndex++]= vv[3].x;
- glCoords[glCoordsIndex++]= vv[3].y;
- glCoords[glCoordsIndex++]= 0;
- },
- /**
- * Set UV for this actor's quad.
- *
- * @param uvBuffer {Float32Array}
- * @param uvIndex {number}
- */
- setUV : function( uvBuffer, uvIndex ) {
- this.backgroundImage.setUV(uvBuffer, uvIndex);
- },
- /**
- * Test for compulsory gl flushing:
- * 1.- opacity has changed.
- * 2.- texture page has changed.
- *
- */
- glNeedsFlush : function(director) {
- if ( this.getTextureGLPage()!==director.currentTexturePage ) {
- return true;
- }
- if ( this.frameAlpha!==director.currentOpacity ) {
- return true;
- }
- return false;
- },
- /**
- * Change texture shader program parameters.
- * @param director
- */
- glSetShader : function(director) {
- var tp= this.getTextureGLPage();
- if ( tp!==director.currentTexturePage ) {
- director.setGLTexturePage(tp);
- }
- if ( this.frameAlpha!==director.currentOpacity ) {
- director.setGLCurrentOpacity(this.frameAlpha);
- }
- },
- /**
- * @private.
- * This method is called after the Director has transformed and drawn a whole frame.
- *
- * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
- * @param time an integer indicating the Scene time when the bounding box is to be drawn.
- * @return this
- *
- * @deprecated
- */
- endAnimate : function(director,time) {
- return this;
- },
- initialize : function(overrides) {
- if (overrides) {
- for (var i in overrides) {
- this[i] = overrides[i];
- }
- }
- return this;
- },
- /**
- * Set this Actor's clipping area.
- * @param enable {boolean} enable clip area.
- * @param clipPath {CAAT.Path=} An optional path to apply clip with. If enabled and clipPath is not set,
- * a rectangle will be used.
- */
- setClip : function( enable, clipPath ) {
- this.clip= enable;
- this.clipPath= clipPath;
- return this;
- },
- /**
- *
- * @param time {Number=}
- * @param stragegy {CAAT.Actor.CACHE_SIMPLE | CAAT.Actor.CACHE_DEEP}
- * @return this
- */
- cacheAsBitmap : function(time, strategy) {
- time= time||0;
- var canvas= document.createElement('canvas');
- canvas.width= this.width;
- canvas.height= this.height;
- var ctx= canvas.getContext('2d');
- var director= {
- ctx: ctx,
- crc: ctx,
- modelViewMatrix: new CAAT.Matrix()
- };
- this.cached= false;
- this.paintActor(director,time);
- this.setBackgroundImage(canvas);
- this.cached= strategy ? strategy : CAAT.Actor.CACHE_SIMPLE;
- return this;
- },
- /**
- * Set this actor behavior as if it were a Button. The actor size will be set as SpriteImage's
- * single size.
- *
- * @param buttonImage {CAAT.SpriteImage} sprite image with button's state images.
- * @param _iNormal {number} button's normal state image index
- * @param _iOver {number} button's mouse over state image index
- * @param _iPress {number} button's pressed state image index
- * @param _iDisabled {number} button's disabled state image index
- * @param fn {function(button{CAAT.Actor})} callback function
- */
- setAsButton : function( buttonImage, iNormal, iOver, iPress, iDisabled, fn ) {
- var me= this;
-
- this.setBackgroundImage(buttonImage, true);
- this.iNormal= iNormal || 0;
- this.iOver= iOver || iNormal;
- this.iPress= iPress || iNormal;
- this.iDisabled= iDisabled || iNormal;
- this.fnOnClick= fn;
- this.enabled= true;
- this.setSpriteIndex( iNormal );
- /**
- * Enable or disable the button.
- * @param enabled {boolean}
- * @ignore
- */
- this.setEnabled= function( enabled ) {
- this.enabled= enabled;
- this.setSpriteIndex( this.enabled ? this.iNormal : this.iDisabled );
- return this;
- };
- /**
- * This method will be called by CAAT *before* the mouseUp event is fired.
- * @param event {CAAT.MouseEvent}
- * @ignore
- */
- this.actionPerformed= function(event) {
- if ( this.enabled && null!==this.fnOnClick ) {
- this.fnOnClick(this);
- }
- };
- /**
- * Button's mouse enter handler. It makes the button provide visual feedback
- * @param mouseEvent {CAAT.MouseEvent}
- * @ignore
- */
- this.mouseEnter= function(mouseEvent) {
- if ( !this.enabled ) {
- return;
- }
- if ( this.dragging ) {
- this.setSpriteIndex( this.iPress );
- } else {
- this.setSpriteIndex( this.iOver );
- }
- CAAT.setCursor('pointer');
- };
- /**
- * Button's mouse exit handler. Release visual apperance.
- * @param mouseEvent {CAAT.MouseEvent}
- * @ignore
- */
- this.mouseExit= function(mouseEvent) {
- if ( !this.enabled ) {
- return;
- }
- this.setSpriteIndex( this.iNormal );
- CAAT.setCursor('default');
- };
- /**
- * Button's mouse down handler.
- * @param mouseEvent {CAAT.MouseEvent}
- * @ignore
- */
- this.mouseDown= function(mouseEvent) {
- if ( !this.enabled ) {
- return;
- }
- this.setSpriteIndex( this.iPress );
- };
- /**
- * Button's mouse up handler.
- * @param mouseEvent {CAAT.MouseEvent}
- * @ignore
- */
- this.mouseUp= function(mouseEvent) {
- if ( !this.enabled ) {
- return;
- }
- this.setSpriteIndex( this.iNormal );
- this.dragging= false;
- };
- /**
- * Button's mouse click handler. Do nothing by default. This event handler will be
- * called ONLY if it has not been drag on the button.
- * @param mouseEvent {CAAT.MouseEvent}
- * @ignore
- */
- this.mouseClick= function(mouseEvent) {
- };
- /**
- * Button's mouse drag handler.
- * @param mouseEvent {CAAT.MouseEvent}
- * @ignore
- */
- this.mouseDrag= function(mouseEvent) {
- if ( !this.enabled ) {
- return;
- }
- this.dragging= true;
- };
- this.setButtonImageIndex= function(_normal, _over, _press, _disabled ) {
- this.iNormal= _normal;
- this.iOver= _over;
- this.iPress= _press;
- this.iDisabled= _disabled;
- this.setSpriteIndex( this.iNormal );
- return this;
- };
- return this;
- }
- };
- /*
- if ( CAAT.NO_PERF ) {
- CAAT.Actor.prototype.paintActor= CAAT.Actor.prototype.__paintActor;
- }
- */
- })();
- (function() {
- var __CD= 2;
- /**
- * This class is a general container of CAAT.Actor instances. It extends the concept of an Actor
- * from a single entity on screen to a set of entities with a parent/children relationship among
- * them.
- * <p>
- * This mainly overrides default behavior of a single entity and exposes methods to manage its children
- * collection.
- *
- * @constructor
- * @extends CAAT.Actor
- */
- CAAT.ActorContainer= function(hint) {
- CAAT.ActorContainer.superclass.constructor.call(this);
- this.childrenList= [];
- this.pendingChildrenList= [];
- if ( typeof hint!=='undefined' ) {
- this.addHint= hint;
- this.boundingBox= new CAAT.Rectangle();
- }
- return this;
- };
- CAAT.ActorContainer.AddHint= {
- CONFORM : 1
- };
- CAAT.ActorContainer.prototype= {
- childrenList : null, // the list of children contained.
- activeChildren : null,
- pendingChildrenList : null,
- addHint : 0,
- boundingBox : null,
- runion : new CAAT.Rectangle(), // Watch out. one for every container.
- /**
- * Draws this ActorContainer and all of its children screen bounding box.
- *
- * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
- * @param time an integer indicating the Scene time when the bounding box is to be drawn.
- */
- drawScreenBoundingBox : function( director, time ) {
- if (!this.inFrame) {
- return;
- }
- var cl= this.childrenList;
- for( var i=0; i<cl.length; i++ ) {
- cl[i].drawScreenBoundingBox(director,time);
- }
- CAAT.ActorContainer.superclass.drawScreenBoundingBox.call(this,director,time);
- },
- /**
- * Removes all children from this ActorContainer.
- *
- * @return this
- */
- emptyChildren : function() {
- this.childrenList= [];
- return this;
- },
- /**
- * Private
- * Paints this container and every contained children.
- *
- * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
- * @param time an integer indicating the Scene time when the bounding box is to be drawn.
- */
- paintActor : function(director, time ) {
- if (!this.visible) {
- return true;
- }
- var ctx= director.ctx;
- ctx.save();
- CAAT.ActorContainer.superclass.paintActor.call(this,director,time);
- if ( this.cached===__CD ) {
- return;
- }
- if ( !this.isGlobalAlpha ) {
- this.frameAlpha= this.parent ? this.parent.frameAlpha : 1;
- }
- for( var actor= this.activeChildren; actor; actor=actor.__next ) {
- if ( actor.visible ) {
- ctx.save();
- actor.paintActor(director,time);
- ctx.restore();
- }
- }
- ctx.restore();
- return true;
- },
- __paintActor : function(director, time ) {
- if (!this.visible) {
- return true;
- }
- var ctx= director.ctx;
- this.frameAlpha= this.parent ? this.parent.frameAlpha*this.alpha : 1;
- var m= this.worldModelViewMatrix.matrix;
- ctx.setTransform( m[0], m[3], m[1], m[4], m[2], m[5], this.frameAlpha );
- this.paint(director, time);
- if ( !this.isGlobalAlpha ) {
- this.frameAlpha= this.parent ? this.parent.frameAlpha : 1;
- }
- for( var actor= this.activeChildren; actor; actor=actor.__next ) {
- actor.paintActor(director,time);
- }
- return true;
- },
- paintActorGL : function(director,time) {
- var i, c;
- if (!this.visible) {
- return true;
- }
- CAAT.ActorContainer.superclass.paintActorGL.call(this,director,time);
- if ( !this.isGlobalAlpha ) {
- this.frameAlpha= this.parent.frameAlpha;
- }
- for( c= this.activeChildren; c; c=c.__next ) {
- c.paintActorGL(director,time);
- }
- },
- /**
- * Private.
- * Performs the animate method for this ActorContainer and every contained Actor.
- *
- * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
- * @param time an integer indicating the Scene time when the bounding box is to be drawn.
- *
- * @return {boolean} is this actor in active children list ??
- */
- animate : function(director,time) {
- this.activeChildren= null;
- var last= null;
- if (false===CAAT.ActorContainer.superclass.animate.call(this,director,time)) {
- return false;
- }
- if ( this.cached===__CD ) {
- return true;
- }
- var i,l;
- /**
- * Incluir los actores pendientes.
- * El momento es ahora, antes de procesar ninguno del contenedor.
- */
- var pcl= this.pendingChildrenList;
- for( i=0; i<pcl.length; i++ ) {
- var child= pcl[i];
- this.addChild(child);
- }
- this.pendingChildrenList= [];
- var markDelete= [];
- var cl= this.childrenList;
- this.size_active= 1;
- this.size_total= 1;
- for( i=0; i<cl.length; i++ ) {
- var actor= cl[i];
- actor.time= time;
- this.size_total+= actor.size_total;
- if ( actor.animate(director, time) ) {
- if ( !this.activeChildren ) {
- this.activeChildren= actor;
- actor.__next= null;
- last= actor;
- } else {
- actor.__next= null;
- last.__next= actor;
- last= actor;
- }
- this.size_active+= actor.size_active;
- } else {
- if ( actor.expired && actor.discardable ) {
- markDelete.push(actor);
- }
- }
- }
- for( i=0, l=markDelete.length; i<l; i++ ) {
- var md= markDelete[i];
- md.destroy(time);
- if ( director.dirtyRectsEnabled ) {
- director.addDirtyRect( md.AABB );
- }
- }
- return true;
- },
- /**
- * Removes Actors from this ActorContainer which are expired and flagged as Discardable.
- *
- * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
- * @param time an integer indicating the Scene time when the bounding box is to be drawn.
- *
- * @deprecated
- */
- endAnimate : function(director,time) {
- },
- /**
- * Adds an Actor to this Container.
- * The Actor will be added ON METHOD CALL, despite the rendering pipeline stage being executed at
- * the time of method call.
- *
- * This method is only used by CAAT.Director's transitionScene.
- *
- * @param child a CAAT.Actor instance.
- * @return this.
- */
- addChildImmediately : function(child) {
- return this.addChild(child);
- },
- /**
- * Adds an Actor to this ActorContainer.
- * The Actor will be added to the container AFTER frame animation, and not on method call time.
- * Except the Director and in orther to avoid visual artifacts, the developer SHOULD NOT call this
- * method directly.
- *
- * If the container has addingHint as CAAT.ActorContainer.AddHint.CONFORM, new continer size will be
- * calculated by summing up the union of every client actor bounding box.
- * This method will not take into acount actor's affine transformations, so the bounding box will be
- * AABB.
- *
- * @param child a CAAT.Actor object instance.
- * @return this
- */
- addChild : function(child) {
- if ( child.parent!=null ) {
- throw('adding to a container an element with parent.');
- }
- child.parent= this;
- this.childrenList.push(child);
- child.dirty= true;
- /**
- * if Conforming size, recalc new bountainer size.
- */
- if ( this.addHint===CAAT.ActorContainer.AddHint.CONFORM ) {
- this.recalcSize();
- }
- return this;
- },
- /**
- * Recalc this container size by computing the union of every children bounding box.
- */
- recalcSize : function() {
- var bb= this.boundingBox;
- bb.setEmpty();
- var cl= this.childrenList;
- var ac;
- for( var i=0; i<cl.length; i++ ) {
- ac= cl[i];
- this.runion.setBounds(
- ac.x<0 ? 0 : ac.x,
- ac.y<0 ? 0 : ac.y,
- ac.width,
- ac.height );
- bb.unionRectangle( this.runion );
- }
- this.setSize( bb.x1, bb.y1 );
- return this;
- },
- /**
- * Add a child element and make it active in the next frame.
- * @param child {CAAT.Actor}
- */
- addChildDelayed : function(child) {
- this.pendingChildrenList.push(child);
- return this;
- },
- /**
- * Adds an Actor to this ActorContainer.
- *
- * @param child a CAAT.Actor object instance.
- *
- * @return this
- */
- addChildAt : function(child, index) {
- if( index <= 0 ) {
- child.parent= this;
- child.dirty= true;
- //this.childrenList.unshift(child); // unshift unsupported on IE
- this.childrenList.splice( 0, 0, child );
- return this;
- } else {
- if ( index>=this.childrenList.length ) {
- index= this.childrenList.length;
- }
- }
- child.parent= this;
- child.dirty= true;
- this.childrenList.splice(index, 0, child);
- return this;
- },
- /**
- * Find the first actor with the supplied ID.
- * This method is not recommended to be used since executes a linear search.
- * @param id
- */
- findActorById : function(id) {
- var cl= this.childrenList;
- for( var i=0, l=cl.length; i<l; i++ ) {
- if ( cl[i].id===id ) {
- return cl[i];
- }
- }
- return null;
- },
- /**
- * Private
- * Gets a contained Actor z-index on this ActorContainer.
- *
- * @param child a CAAT.Actor object instance.
- *
- * @return an integer indicating the Actor's z-order.
- */
- findChild : function(child) {
- var cl= this.childrenList;
- var i=0;
- var len = cl.length;
- for( i=0; i<len; i++ ) {
- if ( cl[i]===child ) {
- return i;
- }
- }
- return -1;
- },
- /**
- * Removed an Actor form this ActorContainer.
- * If the Actor is not contained into this Container, nothing happends.
- *
- * @param child a CAAT.Actor object instance.
- *
- * @return this
- */
- removeChild : function(child) {
- var pos= this.findChild(child);
- var cl= this.childrenList;
- if ( -1!==pos ) {
- cl[pos].setParent(null);
- cl.splice(pos,1);
- }
- return this;
- },
- removeFirstChild : function() {
- var first= this.childrenList.shift();
- first.parent= null;
- return first;
- },
- /**
- * @private
- *
- * Gets the Actor inside this ActorContainer at a given Screen coordinate.
- *
- * @param point an object of the form { x: float, y: float }
- *
- * @return the Actor contained inside this ActorContainer if found, or the ActorContainer itself.
- */
- findActorAtPosition : function(point) {
- if( null===CAAT.ActorContainer.superclass.findActorAtPosition.call(this,point) ) {
- return null;
- }
- // z-order
- var cl= this.childrenList;
- for( var i=cl.length-1; i>=0; i-- ) {
- var child= this.childrenList[i];
- var np= new CAAT.Point( point.x, point.y, 0 );
- var contained= child.findActorAtPosition( np );
- if ( null!==contained ) {
- return contained;
- }
- }
- return this;
- },
- /**
- * Destroys this ActorContainer.
- * The process falls down recursively for each contained Actor into this ActorContainer.
- *
- * @return this
- */
- destroy : function() {
- var cl= this.childrenList;
- for( var i=cl.length-1; i>=0; i-- ) {
- cl[i].destroy();
- }
- CAAT.ActorContainer.superclass.destroy.call(this);
- return this;
- },
- /**
- * Get number of Actors into this container.
- * @return integer indicating the number of children.
- */
- getNumChildren : function() {
- return this.childrenList.length;
- },
- getNumActiveChildren : function() {
- return this.activeChildren.length;
- },
- /**
- * Returns the Actor at the iPosition(th) position.
- * @param iPosition an integer indicating the position array.
- * @return the CAAT.Actor object at position.
- */
- getChildAt : function( iPosition ) {
- return this.childrenList[ iPosition ];
- },
- /**
- * Changes an actor's ZOrder.
- * @param actor the actor to change ZOrder for
- * @param index an integer indicating the new ZOrder. a value greater than children list size means to be the
- * last ZOrder Actor.
- */
- setZOrder : function( actor, index ) {
- var actorPos= this.findChild(actor);
- // the actor is present
- if ( -1!==actorPos ) {
- var cl= this.childrenList;
- // trivial reject.
- if ( index===actorPos ) {
- return;
- }
- if ( index>=cl.length ) {
- cl.splice(actorPos,1);
- cl.push(actor);
- } else {
- var nActor= cl.splice(actorPos,1);
- if ( index<0 ) {
- index=0;
- } else if ( index>cl.length ) {
- index= cl.length;
- }
- cl.splice( index, 0, nActor[0] );
- }
- }
- }
- };
- /*
- if ( CAAT.NO_PERF ) {
- CAAT.ActorContainer.prototype.paintActor= CAAT.ActorContainer.prototype.__paintActor;
- }
- */
- extend( CAAT.ActorContainer, CAAT.Actor, null);
- })();
- (function() {
- /**
- * TextActor draws text on screen. The text can be drawn directly on screen or make if follow a
- * path defined by an instance of <code>CAAT.Path</code>.
- *
- * @constructor
- * @extends CAAT.ActorContainer
- *
- */
- CAAT.TextActor = function() {
- CAAT.TextActor.superclass.constructor.call(this);
- this.font= "10px sans-serif";
- this.textAlign= "left";
- this.textBaseline= "top";
- this.outlineColor= "black";
- this.clip= false;
- return this;
- };
- CAAT.TextActor.TRAVERSE_PATH_FORWARD= 1;
- CAAT.TextActor.TRAVERSE_PATH_BACKWARD= -1;
- CAAT.TextActor.prototype= {
- font: null, // a valid canvas rendering context font description. Default font
- // will be "10px sans-serif".
- textAlign: null, // a valid canvas rendering context textAlign string. Any of:
- // start, end, left, right, center.
- // defaults to "left".
- textBaseline: null, // a valid canvas rendering context textBaseLine string. Any of:
- // top, hanging, middle, alphabetic, ideographic, bottom.
- // defaults to "top".
- fill: true, // a boolean indicating whether the text should be filled.
- textFillStyle : '#eee', // text fill color
- text: null, // a string with the text to draw.
- textWidth: 0, // an integer indicating text width in pixels.
- textHeight: 0, // an integer indicating text height in pixels.
- outline: false, // a boolean indicating whether the text should be outlined.
- // not all browsers support it.
- outlineColor: null, // a valid color description string.
- path: null, // a CAAT.Path which will be traversed by the text. [Optional]
- pathInterpolator: null, // a CAAT.Interpolator to apply to the path traversing.
- pathDuration: 10000, // an integer indicating the time to be taken to traverse the path. ms.
- sign: 1, // traverse the path forward or backwards.
- /**
- * Set the text to be filled. The default Filling style will be set by calling setFillStyle method.
- * Default value is true.
- * @param fill {boolean} a boolean indicating whether the text will be filled.
- * @return this;
- */
- setFill : function( fill ) {
- this.fill= fill;
- return this;
- },
- setTextFillStyle : function( style ) {
- this.textFillStyle= style;
- return this;
- },
- /**
- * Sets whether the text will be outlined.
- * @param outline {boolean} a boolean indicating whether the text will be outlined.
- * @return this;
- */
- setOutline : function( outline ) {
- this.outline= outline;
- return this;
- },
- setPathTraverseDirection : function(direction) {
- this.sign= direction;
- return this;
- },
- /**
- * Defines text's outline color.
- *
- * @param color {string} sets a valid canvas context color.
- * @return this.
- */
- setOutlineColor : function( color ) {
- this.outlineColor= color;
- return this;
- },
- /**
- * Set the text to be shown by the actor.
- * @param sText a string with the text to be shwon.
- * @return this
- */
- setText : function( sText ) {
- this.text= sText;
- if ( null===this.text || this.text==="" ) {
- this.width= this.height= 0;
- }
- this.calcTextSize( CAAT.director[0] );
- return this;
- },
- setTextAlign : function( align ) {
- this.textAlign= align;
- return this;
- },
- /**
- * Sets text alignment
- * @param align
- * @deprecated use setTextAlign
- */
- setAlign : function( align ) {
- return this.setTextAlign(align);
- },
- /**
- * Set text baseline.
- * @param baseline
- */
- setTextBaseline : function( baseline ) {
- this.textBaseline= baseline;
- return this;
- },
- setBaseline : function( baseline ) {
- return this.setTextBaseline(baseline);
- },
- /**
- * Sets the font to be applied for the text.
- * @param font a string with a valid canvas rendering context font description.
- * @return this
- */
- setFont : function(font) {
- if ( !font ) {
- font= "10px sans-serif";
- }
- this.font= font;
- this.calcTextSize( CAAT.director[0] );
- return this;
- },
- /**
- * Calculates the text dimension in pixels and stores the values in textWidth and textHeight
- * attributes.
- * If Actor's width and height were not set, the Actor's dimension will be set to these values.
- * @param director a CAAT.Director instance.
- * @return this
- */
- calcTextSize : function(director) {
- if ( typeof this.text==='undefined' || null===this.text || ""===this.text ) {
- this.textWidth= 0;
- this.textHeight= 0;
- return this;
- }
- if ( director.glEnabled ) {
- return this;
- }
- if ( this.font instanceof CAAT.SpriteImage ) {
- this.textWidth= this.font.stringWidth( this.text );
- this.textHeight=this.font.stringHeight();
- this.width= this.textWidth;
- this.height= this.textHeight;
- return this;
- }
- var ctx= director.ctx;
- ctx.save();
- ctx.font= this.font;
- this.textWidth= ctx.measureText( this.text ).width;
- if (this.width===0) {
- this.width= this.textWidth;
- }
- try {
- var pos= this.font.indexOf("px");
- var s = this.font.substring(0, pos );
- this.textHeight= parseInt(s,10);
- // needed to calculate the descent.
- // no context.getDescent(font) WTF !!!
- this.textHeight+= (this.textHeight/4)>>0;
- } catch(e) {
- this.textHeight=20; // default height;
- }
- if ( this.height===0 ) {
- this.height= this.textHeight;
- }
- ctx.restore();
- return this;
- },
- /**
- * Custom paint method for TextActor instances.
- * If the path attribute is set, the text will be drawn traversing the path.
- *
- * @param director a valid CAAT.Director instance.
- * @param time an integer with the Scene time the Actor is being drawn.
- */
- paint : function(director, time) {
- CAAT.TextActor.superclass.paint.call(this, director, time );
- if ( this.cached ) {
- // cacheAsBitmap sets this actor's background image as a representation of itself.
- // So if after drawing the background it was cached, we're done.
- return;
- }
- if ( null===this.text) {
- return;
- }
- if ( this.textWidth===0 || this.textHeight===0 ) {
- this.calcTextSize(director);
- }
- var ctx= director.ctx;
-
- if ( this.font instanceof CAAT.SpriteImage ) {
- return this.drawSpriteText(director,time);
- }
- if( null!==this.font ) {
- ctx.font= this.font;
- }
- if ( null!==this.textAlign ) {
- ctx.textAlign= this.textAlign;
- }
- if ( null!==this.textBaseline ) {
- ctx.textBaseline= this.textBaseline;
- }
- if ( this.fill && null!==this.textFillStyle ) {
- ctx.fillStyle= this.textFillStyle;
- }
- if ( this.outline && null!==this.outlineColor ) {
- ctx.strokeStyle= this.outlineColor;
- }
- if (null===this.path) {
- var tx=0;
- if ( this.textAlign==='center') {
- tx= (this.width/2)|0;
- } else if ( this.textAlign==='right' ) {
- tx= this.width;
- }
- if ( this.fill ) {
- ctx.fillText( this.text, tx, 0 );
- if ( this.outline ) {
- // firefox necesita beginPath, si no, dibujara ademas el cuadrado del
- // contenedor de los textos.
- // if ( null!==this.outlineColor ) {
- // ctx.strokeStyle= this.outlineColor;
- // }
- ctx.beginPath();
- ctx.strokeText( this.text, tx, 0 );
- }
- } else {
- if ( null!==this.outlineColor ) {
- ctx.strokeStyle= this.outlineColor;
- }
- ctx.beginPath();
- ctx.strokeText( this.text, tx, 0 );
- }
- }
- else {
- this.drawOnPath(director,time);
- }
- },
- /**
- * Private.
- * Draw the text traversing a path.
- * @param director a valid CAAT.Director instance.
- * @param time an integer with the Scene time the Actor is being drawn.
- */
- drawOnPath : function(director, time) {
- var ctx= director.ctx;
- var textWidth=this.sign * this.pathInterpolator.getPosition(
- (time%this.pathDuration)/this.pathDuration ).y * this.path.getLength() ;
- var p0= new CAAT.Point(0,0,0);
- var p1= new CAAT.Point(0,0,0);
- for( var i=0; i<this.text.length; i++ ) {
- var caracter= this.text[i].toString();
- var charWidth= ctx.measureText( caracter ).width;
- // guonjien: remove "+charWidth/2" since it destroys the kerning. and he's right!!!. thanks.
- var currentCurveLength= textWidth;
- p0= this.path.getPositionFromLength(currentCurveLength).clone();
- p1= this.path.getPositionFromLength(currentCurveLength-0.1).clone();
- var angle= Math.atan2( p0.y-p1.y, p0.x-p1.x );
- ctx.save();
- ctx.translate( p0.x>>0, p0.y>>0 );
- ctx.rotate( angle );
- if ( this.fill ) {
- ctx.fillText(caracter,0,0);
- }
- if ( this.outline ) {
- // ctx.strokeStyle= this.outlineColor;
- ctx.strokeText(caracter,0,0);
- }
- ctx.restore();
- textWidth+= charWidth;
- }
- },
-
- /**
- * Private.
- * Draw the text using a sprited font instead of a canvas font.
- * @param director a valid CAAT.Director instance.
- * @param time an integer with the Scene time the Actor is being drawn.
- */
- drawSpriteText: function(director, time) {
- if (null===this.path) {
- this.font.drawString( director.ctx, this.text, 0, 0);
- } else {
- this.drawSpriteTextOnPath(director, time);
- }
- },
-
- /**
- * Private.
- * Draw the text traversing a path using a sprited font.
- * @param director a valid CAAT.Director instance.
- * @param time an integer with the Scene time the Actor is being drawn.
- */
- drawSpriteTextOnPath: function(director, time) {
- var context= director.ctx;
- var textWidth=this.sign * this.pathInterpolator.getPosition(
- (time%this.pathDuration)/this.pathDuration ).y * this.path.getLength() ;
- var p0= new CAAT.Point(0,0,0);
- var p1= new CAAT.Point(0,0,0);
- for( var i=0; i<this.text.length; i++ ) {
- var character= this.text[i].toString();
- var charWidth= this.font.stringWidth(character); //context.measureText( caracter ).width;
- var pathLength= this.path.getLength();
- var currentCurveLength= charWidth/2 + textWidth;
- p0= this.path.getPositionFromLength(currentCurveLength).clone();
- p1= this.path.getPositionFromLength(currentCurveLength-0.1).clone();
- var angle= Math.atan2( p0.y-p1.y, p0.x-p1.x );
- context.save();
- context.translate( p0.x|0, p0.y|0 );
- context.rotate( angle );
-
- var y = this.textBaseline === "bottom" ? 0 - this.font.height : 0;
-
- this.font.drawString(context,character, 0, y);
- context.restore();
- textWidth+= charWidth;
- }
- },
-
- /**
- * Set the path, interpolator and duration to draw the text on.
- * @param path a valid CAAT.Path instance.
- * @param interpolator a CAAT.Interpolator object. If not set, a Linear Interpolator will be used.
- * @param duration an integer indicating the time to take to traverse the path. Optional. 10000 ms
- * by default.
- */
- setPath : function( path, interpolator, duration ) {
- this.path= path;
- this.pathInterpolator= interpolator || new CAAT.Interpolator().createLinearInterpolator();
- this.pathDuration= duration || 10000;
- /*
- parent could not be set by the time this method is called.
- so the actors bounds set is removed.
- the developer must ensure to call setbounds properly on actor.
- */
- this.mouseEnabled= false;
- return this;
- }
- };
- extend( CAAT.TextActor, CAAT.Actor, null);
- })();
- (function() {
- /**
- * This Actor draws common shapes, concretely Circles and rectangles.
- *
- * @constructor
- * @extends CAAT.ActorContainer
- */
- CAAT.ShapeActor = function() {
- CAAT.ShapeActor.superclass.constructor.call(this);
- this.compositeOp= 'source-over';
- /**
- * Thanks Svend Dutz and Thomas Karolski for noticing this call was not performed by default,
- * so if no explicit call to setShape was made, nothing would be drawn.
- */
- this.setShape( this.SHAPE_CIRCLE );
- return this;
- };
- CAAT.ShapeActor.prototype= {
- shape: 0, // shape type. One of the constant SHAPE_* values
- compositeOp: null, // a valid canvas rendering context string describing compositeOps.
- lineWidth: 1,
- lineCap: null,
- lineJoin: null,
- miterLimit: null,
- SHAPE_CIRCLE: 0, // Constants to describe different shapes.
- SHAPE_RECTANGLE:1,
- /**
- *
- * @param l {number>0}
- */
- setLineWidth : function(l) {
- this.lineWidth= l;
- return this;
- },
- /**
- *
- * @param lc {string{butt|round|square}}
- */
- setLineCap : function(lc) {
- this.lineCap= lc;
- return this;
- },
- /**
- *
- * @param lj {string{bevel|round|miter}}
- */
- setLineJoin : function(lj) {
- this.lineJoin= lj;
- return this;
- },
- /**
- *
- * @param ml {integer>0}
- */
- setMiterLimit : function(ml) {
- this.miterLimit= ml;
- return this;
- },
- getLineCap : function() {
- return this.lineCap;
- },
- getLineJoin : function() {
- return this.lineJoin;
- },
- getMiterLimit : function() {
- return this.miterLimit;
- },
- getLineWidth : function() {
- return this.lineWidth;
- },
- /**
- * Sets shape type.
- * No check for parameter validity is performed.
- * Set paint method according to the shape.
- * @param iShape an integer with any of the SHAPE_* constants.
- * @return this
- */
- setShape : function(iShape) {
- this.shape= iShape;
- this.paint= this.shape===this.SHAPE_CIRCLE ?
- this.paintCircle :
- this.paintRectangle;
- return this;
- },
- /**
- * Sets the composite operation to apply on shape drawing.
- * @param compositeOp an string with a valid canvas rendering context string describing compositeOps.
- * @return this
- */
- setCompositeOp : function(compositeOp){
- this.compositeOp= compositeOp;
- return this;
- },
- /**
- * Draws the shape.
- * Applies the values of fillStype, strokeStyle, compositeOp, etc.
- *
- * @param director a valid CAAT.Director instance.
- * @param time an integer with the Scene time the Actor is being drawn.
- */
- paint : function(director,time) {
- },
- /**
- * @private
- * Draws a circle.
- * @param director a valid CAAT.Director instance.
- * @param time an integer with the Scene time the Actor is being drawn.
- */
- paintCircle : function(director,time) {
- var ctx= director.crc;
- ctx.lineWidth= this.lineWidth;
- ctx.globalCompositeOperation= this.compositeOp;
- if ( null!==this.fillStyle ) {
- ctx.fillStyle= this.fillStyle;
- ctx.beginPath();
- ctx.arc( this.width/2, this.height/2, Math.min(this.width,this.height)/2, 0, 2*Math.PI, false );
- ctx.fill();
- }
- if ( null!==this.strokeStyle ) {
- ctx.strokeStyle= this.strokeStyle;
- ctx.beginPath();
- ctx.arc( this.width/2, this.height/2, Math.min(this.width,this.height)/2, 0, 2*Math.PI, false );
- ctx.stroke();
- }
- },
- /**
- *
- * Private
- * Draws a Rectangle.
- *
- * @param director a valid CAAT.Director instance.
- * @param time an integer with the Scene time the Actor is being drawn.
- */
- paintRectangle : function(director,time) {
- var ctx= director.crc;
- ctx.lineWidth= this.lineWidth;
- if ( this.lineCap ) {
- ctx.lineCap= this.lineCap;
- }
- if ( this.lineJoin ) {
- ctx.lineJoin= this.lineJoin;
- }
- if ( this.miterLimit ) {
- ctx.miterLimit= this.miterLimit;
- }
- ctx.globalCompositeOperation= this.compositeOp;
- if ( null!==this.fillStyle ) {
- ctx.fillStyle= this.fillStyle;
- ctx.beginPath();
- ctx.fillRect(0,0,this.width,this.height);
- ctx.fill();
- }
- if ( null!==this.strokeStyle ) {
- ctx.strokeStyle= this.strokeStyle;
- ctx.beginPath();
- ctx.strokeRect(0,0,this.width,this.height);
- ctx.stroke();
- }
- }
- };
- extend( CAAT.ShapeActor, CAAT.ActorContainer, null);
- })();
- (function() {
- /**
- * This actor draws stars.
- *
- * @constructor
- * @extends CAAT.ActorContainer
- */
- CAAT.StarActor= function() {
- CAAT.StarActor.superclass.constructor.call(this);
- this.compositeOp= 'source-over';
- return this;
- };
- CAAT.StarActor.prototype= {
- nPeaks: 0,
- maxRadius: 0,
- minRadius: 0,
- initialAngle: 0,
- compositeOp: null,
- lineWidth: 1,
- lineCap: null,
- lineJoin: null,
- miterLimit: null,
- /**
- *
- * @param l {number>0}
- */
- setLineWidth : function(l) {
- this.lineWidth= l;
- return this;
- },
- /**
- *
- * @param lc {string{butt|round|square}}
- */
- setLineCap : function(lc) {
- this.lineCap= lc;
- return this;
- },
- /**
- *
- * @param lj {string{bevel|round|miter}}
- */
- setLineJoin : function(lj) {
- this.lineJoin= lj;
- return this;
- },
- /**
- *
- * @param ml {integer>0}
- */
- setMiterLimit : function(ml) {
- this.miterLimit= ml;
- return this;
- },
- getLineCap : function() {
- return this.lineCap;
- },
- getLineJoin : function() {
- return this.lineJoin;
- },
- getMiterLimit : function() {
- return this.miterLimit;
- },
- getLineWidth : function() {
- return this.lineWidth;
- },
- /**
- * Sets whether the star will be color filled.
- * @param filled {boolean}
- * @deprecated
- */
- setFilled : function( filled ) {
- return this;
- },
- /**
- * Sets whether the star will be outlined.
- * @param outlined {boolean}
- * @deprecated
- */
- setOutlined : function( outlined ) {
- return this;
- },
- /**
- * Sets the composite operation to apply on shape drawing.
- * @param compositeOp an string with a valid canvas rendering context string describing compositeOps.
- * @return this
- */
- setCompositeOp : function(compositeOp){
- this.compositeOp= compositeOp;
- return this;
- },
- /**
- *
- * @param angle {number} number in radians.
- */
- setInitialAngle : function(angle) {
- this.initialAngle= angle;
- return this;
- },
- /**
- * Initialize the star values.
- * <p>
- * The star actor will be of size 2*maxRadius.
- *
- * @param nPeaks {number} number of star points.
- * @param maxRadius {number} maximum star radius
- * @param minRadius {number} minimum star radius
- *
- * @return this
- */
- initialize : function(nPeaks, maxRadius, minRadius) {
- this.setSize( 2*maxRadius, 2*maxRadius );
- this.nPeaks= nPeaks;
- this.maxRadius= maxRadius;
- this.minRadius= minRadius;
- return this;
- },
- /**
- * Paint the star.
- *
- * @param director {CAAT.Director}
- * @param timer {number}
- */
- paint : function(director, timer) {
- var ctx= director.ctx;
- var centerX= this.width/2;
- var centerY= this.height/2;
- var r1= this.maxRadius;
- var r2= this.minRadius;
- var ix= centerX + r1*Math.cos(this.initialAngle);
- var iy= centerY + r1*Math.sin(this.initialAngle);
- ctx.lineWidth= this.lineWidth;
- if ( this.lineCap ) {
- ctx.lineCap= this.lineCap;
- }
- if ( this.lineJoin ) {
- ctx.lineJoin= this.lineJoin;
- }
- if ( this.miterLimit ) {
- ctx.miterLimit= this.miterLimit;
- }
- ctx.globalCompositeOperation= this.compositeOp;
- ctx.beginPath();
- ctx.moveTo(ix,iy);
- for( var i=1; i<this.nPeaks*2; i++ ) {
- var angleStar= Math.PI/this.nPeaks * i + this.initialAngle;
- var rr= (i%2===0) ? r1 : r2;
- var x= centerX + rr*Math.cos(angleStar);
- var y= centerY + rr*Math.sin(angleStar);
- ctx.lineTo(x,y);
- }
- ctx.lineTo(
- centerX + r1*Math.cos(this.initialAngle),
- centerY + r1*Math.sin(this.initialAngle) );
- ctx.closePath();
-
- if ( this.fillStyle ) {
- ctx.fillStyle= this.fillStyle;
- ctx.fill();
- }
- if ( this.strokeStyle ) {
- ctx.strokeStyle= this.strokeStyle;
- ctx.stroke();
- }
- }
- };
- extend(CAAT.StarActor, CAAT.ActorContainer, null);
- })();
- /**
- * An actor suitable to draw an ImageProcessor instance.
- */
- (function() {
- /**
- * This Actor will show the result of an image processing operation.
- *
- * @constructor
- * @extends CAAT.ActorContainer
- */
- CAAT.IMActor= function() {
- CAAT.IMActor.superclass.constructor.call(this);
- return this;
- };
- CAAT.IMActor.prototype= {
- imageProcessor: null,
- changeTime: 100,
- lastApplicationTime: -1,
- /**
- * Set the image processor.
- *
- * @param im {CAAT.ImageProcessor} a CAAT.ImageProcessor instance.
- */
- setImageProcessor : function(im) {
- this.imageProcessor= im;
- return this;
- },
- /**
- * Call image processor to update image every time milliseconds.
- * @param time an integer indicating milliseconds to elapse before updating the frame.
- */
- setImageProcessingTime : function( time ) {
- this.changeTime= time;
- return this;
- },
- paint : function( director, time ) {
- if ( time-this.lastApplicationTime>this.changeTime ) {
- this.imageProcessor.apply( director, time );
- this.lastApplicationTime= time;
- }
- var ctx= director.ctx;
- this.imageProcessor.paint( director, time );
- }
- };
- extend( CAAT.IMActor, CAAT.ActorContainer, null);
- })();/**
- * See LICENSE file.
- *
- * Sound implementation.
- */
- (function() {
- /**
- * This class is a sound manager implementation which can play at least 'numChannels' sounds at the same time.
- * By default, CAAT.Director instances will set eight channels to play sound.
- * <p>
- * If more than 'numChannels' sounds want to be played at the same time the requests will be dropped,
- * so no more than 'numChannels' sounds can be concurrently played.
- * <p>
- * Available sounds to be played must be supplied to every CAAT.Director instance by calling <code>addSound</code>
- * method. The default implementation will accept a URL/URI or a HTMLAudioElement as source.
- * <p>
- * The cached elements can be played, or looped. The <code>loop</code> method will return a handler to
- * give the opportunity of cancelling the sound.
- * <p>
- * Be aware of Audio.canPlay, is able to return 'yes', 'no', 'maybe', ..., so anything different from
- * '' and 'no' will do.
- *
- * @constructor
- *
- */
- CAAT.AudioManager= function() {
- this.browserInfo= new CAAT.BrowserDetect();
- return this;
- };
- CAAT.AudioManager.prototype= {
- browserInfo: null,
- musicEnabled: true,
- fxEnabled: true,
- audioCache: null, // audio elements.
- channels: null, // available playing channels.
- workingChannels: null, // currently playing channels.
- loopingChannels: [],
- audioTypes: { // supported audio formats. Don't remember where i took them from :S
- 'mp3': 'audio/mpeg;',
- 'ogg': 'audio/ogg; codecs="vorbis"',
- 'wav': 'audio/wav; codecs="1"',
- 'mp4': 'audio/mp4; codecs="mp4a.40.2"'
- },
- /**
- * Initializes the sound subsystem by creating a fixed number of Audio channels.
- * Every channel registers a handler for sound playing finalization. If a callback is set, the
- * callback function will be called with the associated sound id in the cache.
- *
- * @param numChannels {number} number of channels to pre-create. 8 by default.
- *
- * @return this.
- */
- initialize : function(numChannels) {
- this.audioCache= [];
- this.channels= [];
- this.workingChannels= [];
- for( var i=0; i<numChannels; i++ ) {
- var channel= document.createElement('audio');
- if ( null!==channel ) {
- channel.finished= -1;
- this.channels.push( channel );
- var me= this;
- channel.addEventListener(
- 'ended',
- // on sound end, set channel to available channels list.
- function(audioEvent) {
- var target= audioEvent.target;
- var i;
- // remove from workingChannels
- for( i=0; i<me.workingChannels.length; i++ ) {
- if (me.workingChannels[i]===target ) {
- me.workingChannels.splice(i,1);
- break;
- }
- }
- if ( target.caat_callback ) {
- target.caat_callback(target.caat_id);
- }
- // set back to channels.
- me.channels.push(target);
- },
- false
- );
- }
- }
- return this;
- },
- /**
- * Tries to add an audio tag to the available list of valid audios. The audio is described by a url.
- * @param id {object} an object to associate the audio element (if suitable to be played).
- * @param url {string} a string describing an url.
- * @param endplaying_callback {function} callback to be called upon sound end.
- *
- * @return {boolean} a boolean indicating whether the browser can play this resource.
- *
- * @private
- */
- addAudioFromURL : function( id, url, endplaying_callback ) {
- var extension= null;
- var audio= document.createElement('audio');
- if ( null!==audio ) {
- if(!audio.canPlayType) {
- return false;
- }
- extension= url.substr(url.lastIndexOf('.')+1);
- var canplay= audio.canPlayType(this.audioTypes[extension]);
- if(canplay!=="" && canplay!=="no") {
- audio.src= url;
- audio.preload = "auto";
- audio.load();
- if ( endplaying_callback ) {
- audio.caat_callback= endplaying_callback;
- audio.caat_id= id;
- }
- this.audioCache.push( { id:id, audio:audio } );
- return true;
- }
- }
- return false;
- },
- /**
- * Tries to add an audio tag to the available list of valid audios. The audio element comes from
- * an HTMLAudioElement.
- * @param id {object} an object to associate the audio element (if suitable to be played).
- * @param audio {HTMLAudioElement} a DOM audio node.
- * @param endplaying_callback {function} callback to be called upon sound end.
- *
- * @return {boolean} a boolean indicating whether the browser can play this resource.
- *
- * @private
- */
- addAudioFromDomNode : function( id, audio, endplaying_callback ) {
- var extension= audio.src.substr(audio.src.lastIndexOf('.')+1);
- if ( audio.canPlayType(this.audioTypes[extension]) ) {
- if ( endplaying_callback ) {
- audio.caat_callback= endplaying_callback;
- audio.caat_id= id;
- }
- this.audioCache.push( { id:id, audio:audio } );
- return true;
- }
- return false;
- },
- /**
- * Adds an elements to the audio cache.
- * @param id {object} an object to associate the audio element (if suitable to be played).
- * @param element {URL|HTMLElement} an url or html audio tag.
- * @param endplaying_callback {function} callback to be called upon sound end.
- *
- * @return {boolean} a boolean indicating whether the browser can play this resource.
- *
- * @private
- */
- addAudioElement : function( id, element, endplaying_callback ) {
- if ( typeof element === "string" ) {
- return this.addAudioFromURL( id, element, endplaying_callback );
- } else {
- try {
- if ( element instanceof HTMLAudioElement ) {
- return this.addAudioFromDomNode( id, element, endplaying_callback );
- }
- }
- catch(e) {
- }
- }
- return false;
- },
- /**
- * creates an Audio object and adds it to the audio cache.
- * This function expects audio data described by two elements, an id and an object which will
- * describe an audio element to be associated with the id. The object will be of the form
- * array, dom node or a url string.
- *
- * <p>
- * The audio element can be one of the two forms:
- *
- * <ol>
- * <li>Either an HTMLAudioElement/Audio object or a string url.
- * <li>An array of elements of the previous form.
- * </ol>
- *
- * <p>
- * When the audio attribute is an array, this function will iterate throught the array elements
- * until a suitable audio element to be played is found. When this is the case, the other array
- * elements won't be taken into account. The valid form of using this addAudio method will be:
- *
- * <p>
- * 1.<br>
- * addAudio( id, url } ). In this case, if the resource pointed by url is
- * not suitable to be played (i.e. a call to the Audio element's canPlayType method return 'no')
- * no resource will be added under such id, so no sound will be played when invoking the play(id)
- * method.
- * <p>
- * 2.<br>
- * addAudio( id, dom_audio_tag ). In this case, the same logic than previous case is applied, but
- * this time, the parameter url is expected to be an audio tag present in the html file.
- * <p>
- * 3.<br>
- * addAudio( id, [array_of_url_or_domaudiotag] ). In this case, the function tries to locate a valid
- * resource to be played in any of the elements contained in the array. The array element's can
- * be any type of case 1 and 2. As soon as a valid resource is found, it will be associated to the
- * id in the valid audio resources to be played list.
- *
- * @return this
- */
- addAudio : function( id, array_of_url_or_domnodes, endplaying_callback ) {
- if ( array_of_url_or_domnodes instanceof Array ) {
- /*
- iterate throught array elements until we can safely add an audio element.
- */
- for( var i=0; i<array_of_url_or_domnodes.length; i++ ) {
- if ( this.addAudioElement(id, array_of_url_or_domnodes[i], endplaying_callback) ) {
- break;
- }
- }
- } else {
- this.addAudioElement(id, array_of_url_or_domnodes, endplaying_callback);
- }
- return this;
- },
- /**
- * Returns an audio object.
- * @param aId {object} the id associated to the target Audio object.
- * @return {object} the HTMLAudioElement addociated to the given id.
- */
- getAudio : function(aId) {
- for( var i=0; i<this.audioCache.length; i++ ) {
- if ( this.audioCache[i].id===aId ) {
- return this.audioCache[i].audio;
- }
- }
- return null;
- },
- /**
- * Set an audio object volume.
- * @param id {object} an audio Id
- * @param volume {number} volume to set. The volume value is not checked.
- *
- * @return this
- */
- setVolume : function( id, volume ) {
- var audio= this.getAudio(id);
- if ( null!=audio ) {
- audio.volume= volume;
- }
- return this;
- },
- /**
- * Plays an audio file from the cache if any sound channel is available.
- * The playing sound will occupy a sound channel and when ends playing will leave
- * the channel free for any other sound to be played in.
- * @param id {object} an object identifying a sound in the sound cache.
- * @return this.
- */
- play : function( id ) {
- if ( !this.fxEnabled ) {
- return this;
- }
- var audio= this.getAudio(id);
- // existe el audio, y ademas hay un canal de audio disponible.
- if ( null!==audio && this.channels.length>0 ) {
- var channel= this.channels.shift();
- channel.src= audio.src;
- channel.load();
- channel.volume= audio.volume;
- channel.play();
- this.workingChannels.push(channel);
- }
- return this;
- },
- /**
- * This method creates a new AudioChannel to loop the sound with.
- * It returns an Audio object so that the developer can cancel the sound loop at will.
- * The user must call <code>pause()</code> method to stop playing a loop.
- * <p>
- * Firefox does not honor the loop property, so looping is performed by attending end playing
- * event on audio elements.
- *
- * @return {HTMLElement} an Audio instance if a valid sound id is supplied. Null otherwise
- */
- loop : function( id ) {
- if (!this.musicEnabled) {
- return this;
- }
- var audio_in_cache= this.getAudio(id);
- // existe el audio, y ademas hay un canal de audio disponible.
- if ( null!==audio_in_cache ) {
- var audio= document.createElement('audio');
- if ( null!==audio ) {
- audio.src= audio_in_cache.src;
- audio.preload = "auto";
- if ( this.browserInfo.browser==='Firefox') {
- audio.addEventListener(
- 'ended',
- // on sound end, set channel to available channels list.
- function(audioEvent) {
- var target= audioEvent.target;
- target.currentTime=0;
- },
- false
- );
- } else {
- audio.loop= true;
- }
- audio.load();
- audio.play();
- this.loopingChannels.push(audio);
- return audio;
- }
- }
- return null;
- },
- /**
- * Cancel all playing audio channels
- * Get back the playing channels to available channel list.
- *
- * @return this
- */
- endSound : function() {
- var i;
- for( i=0; i<this.workingChannels.length; i++ ) {
- this.workingChannels[i].pause();
- this.channels.push( this.workingChannels[i] );
- }
- for( i=0; i<this.loopingChannels.length; i++ ) {
- this.loopingChannels[i].pause();
- }
- return this;
- },
- setSoundEffectsEnabled : function( enable ) {
- this.fxEnabled= enable;
- return this;
- },
- isSoundEffectsEnabled : function() {
- return this.fxEnabled;
- },
- setMusicEnabled : function( enable ) {
- this.musicEnabled= enable;
- for( var i=0; i<this.loopingChannels.length; i++ ) {
- if ( enable ) {
- this.loopingChannels[i].play();
- } else {
- this.loopingChannels[i].pause();
- }
- }
- return this;
- },
- isMusicEnabled : function() {
- return this.musicEnabled;
- }
- };
- })();/**
- * See LICENSE file.
- *
- * In this file we'll be adding every useful Actor that is specific for certain purpose.
- *
- * + CAAT.Dock: a docking container that zooms in/out its actors.
- *
- */
- (function() {
- /**
- * This actor simulates a mac os-x docking component.
- * Every contained actor will be laid out in a row in the desired orientation.
- */
- CAAT.Dock = function() {
- CAAT.Dock.superclass.constructor.call(this);
- return this;
- };
- CAAT.Dock.prototype= {
- scene: null, // scene the actor is in.
- ttask: null, // resetting dimension timer.
- minSize: 0, // min contained actor size
- maxSize: 0, // max contained actor size
- range: 2, // aproximated number of elements affected.
- layoutOp: 0,
- OP_LAYOUT_BOTTOM: 0,
- OP_LAYOUT_TOP: 1,
- OP_LAYOUT_LEFT: 2,
- OP_LAYOUT_RIGHT: 3,
- initialize : function(scene) {
- this.scene= scene;
- return this;
- },
- /**
- * Set the number of elements that will be affected (zoomed) when the mouse is inside the component.
- * @param range {number} a number. Defaults to 2.
- */
- setApplicationRange : function( range ) {
- this.range= range;
- return this;
- },
- /**
- * Set layout orientation. Choose from
- * <ul>
- * <li>CAAT.Dock.prototype.OP_LAYOUT_BOTTOM
- * <li>CAAT.Dock.prototype.OP_LAYOUT_TOP
- * <li>CAAT.Dock.prototype.OP_LAYOUT_BOTTOM
- * <li>CAAT.Dock.prototype.OP_LAYOUT_RIGHT
- * </ul>
- * By default, the layou operation is OP_LAYOUT_BOTTOM, that is, elements zoom bottom anchored.
- *
- * @param lo {number} one of CAAT.Dock.OP_LAYOUT_BOTTOM, CAAT.Dock.OP_LAYOUT_TOP,
- * CAAT.Dock.OP_LAYOUT_BOTTOM, CAAT.Dock.OP_LAYOUT_RIGHT.
- *
- * @return this
- */
- setLayoutOp : function( lo ) {
- this.layoutOp= lo;
- return this;
- },
- /**
- *
- * Set maximum and minimum size of docked elements. By default, every contained actor will be
- * of 'min' size, and will be scaled up to 'max' size.
- *
- * @param min {number}
- * @param max {number}
- * @return this
- */
- setSizes : function( min, max ) {
- this.minSize= min;
- this.maxSize= max;
- for( var i=0; i<this.childrenList.length; i++ ) {
- this.childrenList[i].width= min;
- this.childrenList[i].height= min;
- }
- return this;
- },
- /**
- * Lay out the docking elements. The lay out will be a row with the orientation set by calling
- * the method <code>setLayoutOp</code>.
- *
- * @private
- */
- layout : function() {
- var i,actor;
- if ( this.layoutOp===this.OP_LAYOUT_BOTTOM || this.layoutOp===this.OP_LAYOUT_TOP ) {
- var currentWidth=0, currentX=0;
- for( i=0; i<this.getNumChildren(); i++ ) {
- currentWidth+= this.getChildAt(i).width;
- }
- currentX= (this.width-currentWidth)/2;
- for( i=0; i<this.getNumChildren(); i++ ) {
- actor= this.getChildAt(i);
- actor.x= currentX;
- currentX+= actor.width;
- if ( this.layoutOp===this.OP_LAYOUT_BOTTOM ) {
- actor.y= this.maxSize- actor.height;
- } else {
- actor.y= 0;
- }
- }
- } else {
- var currentHeight=0, currentY=0;
- for( i=0; i<this.getNumChildren(); i++ ) {
- currentHeight+= this.getChildAt(i).height;
- }
- currentY= (this.height-currentHeight)/2;
- for( i=0; i<this.getNumChildren(); i++ ) {
- actor= this.getChildAt(i);
- actor.y= currentY;
- currentY+= actor.height;
- if ( this.layoutOp===this.OP_LAYOUT_LEFT ) {
- actor.x= 0;
- } else {
- actor.x= this.width - actor.width;
- }
- }
- }
- },
- mouseMove : function(mouseEvent) {
- this.actorNotPointed();
- },
- mouseExit : function(mouseEvent) {
- this.actorNotPointed();
- },
- /**
- * Performs operation when the mouse is not in the dock element.
- *
- * @private
- */
- actorNotPointed : function() {
- var i;
- var me= this;
- for( i=0; i<this.getNumChildren(); i++ ) {
- var actor= this.getChildAt(i);
- actor.emptyBehaviorList();
- actor.addBehavior(
- new CAAT.GenericBehavior().
- setValues( actor.width, this.minSize, actor, 'width' ).
- setFrameTime( this.scene.time, 250 ) ).
- addBehavior(
- new CAAT.GenericBehavior().
- setValues( actor.height, this.minSize, actor, 'height' ).
- setFrameTime( this.scene.time, 250 ) );
- if ( i===this.getNumChildren()-1 ) {
- actor.behaviorList[0].addListener(
- {
- behaviorApplied : function(behavior,time,normalizedTime,targetActor,value) {
- targetActor.parent.layout();
- },
- behaviorExpired : function(behavior,time,targetActor) {
- for( i=0; i<me.getNumChildren(); i++ ) {
- actor= me.getChildAt(i);
- actor.width = me.minSize;
- actor.height = me.minSize;
- }
- targetActor.parent.layout();
- }
- });
- }
- }
- },
- /**
- *
- * Perform the process of pointing a docking actor.
- *
- * @param x {number}
- * @param y {number}
- * @param pointedActor {CAAT.Actor}
- *
- * @private
- */
- actorPointed : function(x, y, pointedActor) {
- var index= this.findChild(pointedActor);
- var across= 0;
- if ( this.layoutOp===this.OP_LAYOUT_BOTTOM || this.layoutOp===this.OP_LAYOUT_TOP ) {
- across= x / pointedActor.width;
- } else {
- across= y / pointedActor.height;
- }
- var i;
- for( i=0; i<this.childrenList.length; i++ ) {
- var actor= this.childrenList[i];
- actor.emptyBehaviorList();
- var wwidth=0;
- if (i < index - this.range || i > index + this.range) {
- wwidth = this.minSize;
- } else if (i === index) {
- wwidth = this.maxSize;
- } else if (i < index) {
- wwidth=
- this.minSize +
- (this.maxSize-this.minSize) *
- (Math.cos((i - index - across + 1) / this.range * Math.PI) + 1) /
- 2;
- } else {
- wwidth=
- this.minSize +
- (this.maxSize-this.minSize)*
- (Math.cos( (i - index - across) / this.range * Math.PI) + 1) /
- 2;
- }
- actor.height= wwidth;
- actor.width= wwidth;
- }
- this.layout();
- },
- /**
- * Perform the process of exiting the docking element, that is, animate elements to the minimum
- * size.
- *
- * @param mouseEvent {CAAT.MouseEvent} a CAAT.MouseEvent object.
- *
- * @private
- */
- actorMouseExit : function(mouseEvent) {
- if ( null!==this.ttask ) {
- this.ttask.cancel();
- }
- var me= this;
- this.ttask= this.scene.createTimer(
- this.scene.time,
- 100,
- function timeout(sceneTime, time, timerTask) {
- me.actorNotPointed();
- },
- null,
- null);
- },
- /**
- * Perform the beginning of docking elements.
- * @param mouseEvent {CAAT.MouseEvent} a CAAT.MouseEvent object.
- *
- * @private
- */
- actorMouseEnter : function(mouseEvent) {
- if ( null!==this.ttask ) {
- this.ttask.cancel();
- this.ttask= null;
- }
- },
- /**
- * Adds an actor to Dock.
- * <p>
- * Be aware that actor mouse functions must be set prior to calling this method. The Dock actor
- * needs set his own actor input events functions for mouseEnter, mouseExit and mouseMove and
- * will then chain to the original methods set by the developer.
- *
- * @param actor {CAAT.Actor} a CAAT.Actor instance.
- *
- * @return this
- */
- addChild : function(actor) {
- var me= this;
- actor.__Dock_mouseEnter= actor.mouseEnter;
- actor.__Dock_mouseExit= actor.mouseExit;
- actor.__Dock_mouseMove= actor.mouseMove;
- /**
- * @ignore
- * @param mouseEvent
- */
- actor.mouseEnter= function(mouseEvent) {
- me.actorMouseEnter(mouseEvent);
- this.__Dock_mouseEnter(mouseEvent);
- };
- /**
- * @ignore
- * @param mouseEvent
- */
- actor.mouseExit= function(mouseEvent) {
- me.actorMouseExit(mouseEvent);
- this.__Dock_mouseExit(mouseEvent);
- };
- /**
- * @ignore
- * @param mouseEvent
- */
- actor.mouseMove= function(mouseEvent) {
- me.actorPointed( mouseEvent.point.x, mouseEvent.point.y, mouseEvent.source );
- this.__Dock_mouseMove(mouseEvent);
- };
- actor.width= this.minSize;
- actor.height= this.minSize;
- return CAAT.Dock.superclass.addChild.call(this,actor);
- }
- };
- extend( CAAT.Dock, CAAT.ActorContainer, null);
- })();
- /**
- * See LICENSE file.
- *
- **/
- (function() {
- /**
- * Director is the animator scene graph manager.
- * <p>
- * The director elements is an ActorContainer itself with the main responsibility of managing
- * different Scenes.
- * <p>
- * It is responsible for:
- * <ul>
- * <li>scene changes.
- * <li>route input to the appropriate scene graph actor.
- * <li>be the central point for resource caching.
- * <li>manage the timeline.
- * <li>manage frame rate.
- * <li>etc.
- * </ul>
- *
- * <p>
- * One document can contain different CAAT.Director instances which will be kept together in CAAT
- * function.
- *
- * @constructor
- * @extends CAAT.ActorContainer
- */
- CAAT.Director = function() {
- CAAT.Director.superclass.constructor.call(this);
- this.browserInfo = new CAAT.BrowserDetect();
- this.audioManager = new CAAT.AudioManager().initialize(8);
- this.scenes = [];
- // input related variables initialization
- this.mousePoint = new CAAT.Point(0, 0, 0);
- this.prevMousePoint = new CAAT.Point(0, 0, 0);
- this.screenMousePoint = new CAAT.Point(0, 0, 0);
- this.isMouseDown = false;
- this.lastSelectedActor = null;
- this.dragging = false;
- this.cDirtyRects= [];
- this.dirtyRects= [];
- for( var i=0; i<64; i++ ) {
- this.dirtyRects.push( new CAAT.Rectangle() );
- }
- this.dirtyRectsIndex= 0;
- return this;
- };
- CAAT.Director.CLEAR_DIRTY_RECTS= 1;
- CAAT.Director.CLEAR_ALL= true;
- CAAT.Director.CLEAR_NONE= false;
- CAAT.Director.prototype = {
- debug: false, // flag indicating debug mode. It will draw affedted screen areas.
- onRenderStart: null,
- onRenderEnd: null,
- // input related attributes
- mousePoint: null, // mouse coordinate related to canvas 0,0 coord.
- prevMousePoint: null, // previous mouse position cache. Needed for drag events.
- screenMousePoint: null, // screen mouse coordinates.
- isMouseDown: false, // is the left mouse button pressed ?
- lastSelectedActor: null, // director's last actor receiving input.
- dragging: false, // is in drag mode ?
- // other attributes
- scenes: null, // Scenes collection. An array.
- currentScene: null, // The current Scene. This and only this will receive events.
- canvas: null, // The canvas the Director draws on.
- crc: null, // @deprecated. canvas rendering context
- ctx: null, // refactoring crc for a more convenient name
- time: 0, // virtual actor time.
- timeline: 0, // global director timeline.
- imagesCache: null, // An array of JSON elements of the form { id:string, image:Image }
- audioManager: null,
- clear: true, // clear background before drawing scenes ??
- transitionScene: null,
- browserInfo: null,
- gl: null,
- glEnabled: false,
- glTextureManager: null,
- glTtextureProgram: null,
- glColorProgram: null,
- pMatrix: null, // projection matrix
- coords: null, // Float32Array
- coordsIndex: 0,
- uv: null,
- uvIndex: 0,
- front_to_back: false,
- statistics: {
- size_total: 0,
- size_active: 0,
- size_dirtyRects: 0,
- draws: 0
- },
- currentTexturePage: 0,
- currentOpacity: 1,
- intervalId: null,
- frameCounter: 0,
- RESIZE_NONE: 1,
- RESIZE_WIDTH: 2,
- RESIZE_HEIGHT: 4,
- RESIZE_BOTH: 8,
- RESIZE_PROPORTIONAL:16,
- resize: 1,
- onResizeCallback : null,
- __gestureScale : 0,
- __gestureRotation : 0,
- dirtyRects : null,
- cDirtyRects : null,
- dirtyRectsIndex : 0,
- dirtyRectsEnabled : false,
- nDirtyRects : 0,
- stopped : false, // is stopped, this director will do nothing.
- checkDebug : function() {
- if ( CAAT.DEBUG ) {
- var dd= new CAAT.Debug().initialize( this.width, 60 );
- this.debugInfo= dd.debugInfo.bind(dd);
- }
- },
- getRenderType : function() {
- return this.glEnabled ? 'WEBGL' : 'CANVAS';
- },
- windowResized : function(w, h) {
- switch (this.resize) {
- case this.RESIZE_WIDTH:
- this.setBounds(0, 0, w, this.height);
- break;
- case this.RESIZE_HEIGHT:
- this.setBounds(0, 0, this.width, h);
- break;
- case this.RESIZE_BOTH:
- this.setScaleBoth(w,h);
- break;
- case this.RESIZE_PROPORTIONAL:
- this.setScaleProportional(w,h);
- break;
- }
- if ( this.glEnabled ) {
- this.glReset();
- }
- if ( this.onResizeCallback ) {
- this.onResizeCallback( this, w, h );
- }
- },setScaleBoth : function(w,h) {
-
- // var factor= Math.min(w/this.referenceWidth, h/this.referenceHeight);
- var wf = w/this.referenceWidth;
- var hf = h/this.referenceHeight
- this.setScaleAnchored( wf, hf, 0, 0 );
-
- this.canvas.width = this.referenceWidth*wf;
- this.canvas.height = this.referenceHeight*hf;
- this.ctx = this.canvas.getContext(this.glEnabled ? 'experimental-webgl' : '2d' );
- this.crc = this.ctx;
-
- if ( this.glEnabled ) {
- this.glReset();
- }
- },
- setScaleProportional : function(w,h) {
- var factor= Math.min(w/this.referenceWidth, h/this.referenceHeight);
- this.setScaleAnchored( factor, factor, 0, 0 );
- this.canvas.width = this.referenceWidth*factor;
- this.canvas.height = this.referenceHeight*factor;
- this.ctx = this.canvas.getContext(this.glEnabled ? 'experimental-webgl' : '2d' );
- this.crc = this.ctx;
- if ( this.glEnabled ) {
- this.glReset();
- }
- },
- /**
- * Enable window resize events and set redimension policy. A callback functio could be supplied
- * to be notified on a Director redimension event. This is necessary in the case you set a redim
- * policy not equal to RESIZE_PROPORTIONAL. In those redimension modes, director's area and their
- * children scenes are resized to fit the new area. But scenes content is not resized, and have
- * no option of knowing so uless an onResizeCallback function is supplied.
- *
- * @param mode {number} RESIZE_BOTH, RESIZE_WIDTH, RESIZE_HEIGHT, RESIZE_NONE.
- * @param onResizeCallback {function(director{CAAT.Director}, width{integer}, height{integer})} a callback
- * to notify on canvas resize.
- */
- enableResizeEvents : function(mode, onResizeCallback) {
- if (mode === this.RESIZE_BOTH || mode === this.RESIZE_WIDTH || mode === this.RESIZE_HEIGHT || mode===this.RESIZE_PROPORTIONAL) {
- this.referenceWidth= this.width;
- this.referenceHeight=this.height;
- this.resize = mode;
- CAAT.registerResizeListener(this);
- this.onResizeCallback= onResizeCallback;
- this.windowResized( window.innerWidth, window.innerHeight );
- } else {
- CAAT.unregisterResizeListener(this);
- this.onResizeCallback= null;
- }
- },
- /**
- * Set this director's bounds as well as its contained scenes.
- * @param x {number} ignored, will be 0.
- * @param y {number} ignored, will be 0.
- * @param w {number} director width.
- * @param h {number} director height.
- *
- * @return this
- */
- setBounds : function(x, y, w, h) {
- CAAT.Director.superclass.setBounds.call(this, x, y, w, h);
- this.canvas.width = w;
- this.canvas.height = h;
- this.ctx = this.canvas.getContext(this.glEnabled ? 'experimental-webgl' : '2d');
- this.crc = this.ctx;
- for (var i = 0; i < this.scenes.length; i++) {
- this.scenes[i].setBounds(0, 0, w, h);
- }
- if ( this.glEnabled ) {
- this.glReset();
- }
- return this;
- },
- /**
- * This method performs Director initialization. Must be called once.
- * If the canvas parameter is not set, it will create a Canvas itself,
- * and the developer must explicitly add the canvas to the desired DOM position.
- * This method will also set the Canvas dimension to the specified values
- * by width and height parameters.
- *
- * @param width {number} a canvas width
- * @param height {number} a canvas height
- * @param canvas {HTMLCanvasElement=} An optional Canvas object.
- * @param proxy {HTMLElement} this object can be an event proxy in case you'd like to layer different elements
- * and want events delivered to the correct element.
- *
- * @return this
- */
- initialize : function(width, height, canvas, proxy) {
- if ( !canvas ) {
- canvas= document.createElement('canvas');
- document.body.appendChild(canvas);
- }
- this.canvas = canvas;
- if ( typeof proxy==='undefined' ) {
- proxy= canvas;
- }
- this.setBounds(0, 0, width, height);
- this.create();
- this.enableEvents(proxy);
- this.timeline = new Date().getTime();
- // transition scene
- this.transitionScene = new CAAT.Scene().setBounds(0, 0, width, height);
- var transitionCanvas = document.createElement('canvas');
- transitionCanvas.width = width;
- transitionCanvas.height = height;
- var transitionImageActor = new CAAT.Actor().setBackgroundImage(transitionCanvas);
- this.transitionScene.ctx = transitionCanvas.getContext('2d');
- this.transitionScene.addChildImmediately(transitionImageActor);
- this.transitionScene.setEaseListener(this);
- this.checkDebug();
- return this;
- },
- glReset : function() {
- this.pMatrix= makeOrtho( 0, this.referenceWidth, this.referenceHeight, 0, -1, 1 );
- this.gl.viewport(0,0,this.canvas.width,this.canvas.height);
- this.glColorProgram.setMatrixUniform(this.pMatrix);
- this.glTextureProgram.setMatrixUniform(this.pMatrix);
- this.gl.viewportWidth = this.canvas.width;
- this.gl.viewportHeight = this.canvas.height;
- },
- /**
- * Experimental.
- * Initialize a gl enabled director.
- * @param width
- * @param height
- * @param canvas
- */
- initializeGL : function(width, height, canvas, proxy) {
- if ( !canvas ) {
- canvas= document.createElement('canvas');
- document.body.appendChild(canvas);
- }
- canvas.width = width;
- canvas.height = height;
- if ( typeof proxy==='undefined' ) {
- proxy= canvas;
- }
- this.referenceWidth= width;
- this.referenceHeight=height;
- var i;
- try {
- this.gl = canvas.getContext("experimental-webgl"/*, {antialias: false}*/);
- this.gl.viewportWidth = width;
- this.gl.viewportHeight = height;
- CAAT.GLRENDER= true;
- } catch(e) {
- }
- if (this.gl) {
- this.canvas = canvas;
- this.create();
- this.setBounds(0, 0, width, height);
- this.crc = this.ctx;
- this.enableEvents(canvas);
- this.timeline = new Date().getTime();
- this.glColorProgram = new CAAT.ColorProgram(this.gl).create().initialize();
- this.glTextureProgram = new CAAT.TextureProgram(this.gl).create().initialize();
- this.glTextureProgram.useProgram();
- this.glReset();
- var maxTris = 512;
- this.coords = new Float32Array(maxTris * 12);
- this.uv = new Float32Array(maxTris * 8);
- this.gl.clearColor(0.0, 0.0, 0.0, 255);
- if (this.front_to_back) {
- this.gl.clearDepth(1.0);
- this.gl.enable(this.gl.DEPTH_TEST);
- this.gl.depthFunc(this.gl.LESS);
- } else {
- this.gl.disable(this.gl.DEPTH_TEST);
- }
- this.gl.enable(this.gl.BLEND);
- // Fix FF this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
- this.gl.blendFunc(this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);
- this.glEnabled = true;
- this.checkDebug();
- } else {
- // fallback to non gl enabled canvas.
- return this.initialize(width, height, canvas);
- }
- return this;
- },
- /**
- * Creates an initializes a Scene object.
- * @return {CAAT.Scene}
- */
- createScene : function() {
- var scene = new CAAT.Scene().create();
- this.addScene(scene);
- return scene;
- },
- setImagesCache : function(imagesCache, tpW, tpH) {
- var i;
- if (null !== this.glTextureManager) {
- this.glTextureManager.deletePages();
- this.glTextureManager = null;
- }
- // delete previous image identifiers
- if ( this.imagesCache ) {
- var ids= [];
- for ( i = 0; i < this.imagesCache.length; i++) {
- ids.push( this.imagesCache[i].id );
- }
- for( i=0; i<ids.length; i++ ) {
- delete this.imagesCache[ ids[i] ];
- }
- }
-
- this.imagesCache = imagesCache;
- if ( imagesCache ) {
- for ( i = 0; i < imagesCache.length; i++) {
- this.imagesCache[ imagesCache[i].id ] = imagesCache[i].image;
- }
- }
- this.tpW = tpW || 2048;
- this.tpH = tpH || 2048;
- this.updateGLPages();
- return this;
- },
- updateGLPages : function() {
- if (this.glEnabled) {
- this.glTextureManager = new CAAT.GLTexturePageManager();
- this.glTextureManager.createPages(this.gl, this.tpW, this.tpH, this.imagesCache);
- this.currentTexturePage = this.glTextureManager.pages[0];
- this.glTextureProgram.setTexture(this.currentTexturePage.texture);
- }
- },
- setGLTexturePage : function( tp ) {
- this.currentTexturePage = tp;
- this.glTextureProgram.setTexture(tp.texture);
- return this;
- },
- /**
- * Add a new image to director's image cache. If gl is enabled and the 'noUpdateGL' is not set to true this
- * function will try to recreate the whole GL texture pages.
- * If many handcrafted images are to be added to the director, some performance can be achieved by calling
- * <code>director.addImage(id,image,false)</code> many times and a final call with
- * <code>director.addImage(id,image,true)</code> to finally command the director to create texture pages.
- *
- * @param id {string|object} an identitifier to retrieve the image with
- * @param image {Image|HTMLCanvasElement} image to add to cache
- * @param noUpdateGL {!boolean} unless otherwise stated, the director will
- * try to recreate the texture pages.
- */
- addImage : function( id, image, noUpdateGL ) {
- if ( this.getImage(id) ) {
- for (var i = 0; i < this.imagesCache.length; i++) {
- if (this.imagesCache[i].id === id) {
- this.imagesCache[i].image = image;
- break;
- }
- }
- this.imagesCache[ id ] = image;
- } else {
- this.imagesCache.push( { id: id, image: image } );
- this.imagesCache[id]= image;
- }
- if ( !!!noUpdateGL ) {
- this.updateGLPages( );
- }
- },
- deleteImage : function( id, noUpdateGL ) {
- for (var i = 0; i < this.imagesCache.length; i++) {
- if (this.imagesCache[i].id === id) {
- delete this.imagesCache[id];
- this.imagesCache.splice(i,1);
- break;
- }
- }
- if ( !!!noUpdateGL ) {
- this.updateGLPages();
- }
- },
- setGLCurrentOpacity : function(opacity) {
- this.currentOpacity = opacity;
- this.glTextureProgram.setAlpha(opacity);
- },
- /**
- * Render buffered elements.
- * @param vertex
- * @param coordsIndex
- * @param uv
- */
- glRender : function(vertex, coordsIndex, uv) {
- vertex = vertex || this.coords;
- uv = uv || this.uv;
- coordsIndex = coordsIndex || this.coordsIndex;
- var gl = this.gl;
- var numTris = coordsIndex / 12 * 2;
- var numVertices = coordsIndex / 3;
- this.glTextureProgram.updateVertexBuffer(vertex);
- this.glTextureProgram.updateUVBuffer(uv);
- gl.drawElements(gl.TRIANGLES, 3 * numTris, gl.UNSIGNED_SHORT, 0);
- },
- glFlush : function() {
- if (this.coordsIndex !== 0) {
- this.glRender(this.coords, this.coordsIndex, this.uv);
- }
- this.coordsIndex = 0;
- this.uvIndex = 0;
- this.statistics.draws++;
- },
- findActorAtPosition : function(point) {
- // z-order
- var cl= this.childrenList;
- for( var i=cl.length-1; i>=0; i-- ) {
- var child= this.childrenList[i];
- var np= new CAAT.Point( point.x, point.y, 0 );
- var contained= child.findActorAtPosition( np );
- if ( null!==contained ) {
- return contained;
- }
- }
- return this;
- },
- /**
- *
- * Reset statistics information.
- *
- * @private
- */
- resetStats : function() {
- this.statistics.size_total= 0;
- this.statistics.size_active=0;
- this.statistics.draws= 0;
- },
- /**
- * This is the entry point for the animation system of the Director.
- * The director is fed with the elapsed time value to maintain a virtual timeline.
- * This virtual timeline will provide each Scene with its own virtual timeline, and will only
- * feed time when the Scene is the current Scene, or is being switched.
- *
- * If dirty rectangles are enabled and canvas is used for rendering, the dirty rectangles will be
- * set up as a single clip area.
- *
- * @param time {number} integer indicating the elapsed time between two consecutive frames of the
- * Director.
- */
- render : function(time) {
- this.time += time;
- this.animate(this,time);
- if ( CAAT.DEBUG ) {
- this.resetStats();
- }
- /**
- * draw director active scenes.
- */
- var ne = this.childrenList.length;
- var i, tt, c;
- var ctx= this.ctx;
- if (this.glEnabled) {
- this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
- this.coordsIndex = 0;
- this.uvIndex = 0;
- for (i = 0; i < ne; i++) {
- c = this.childrenList[i];
- if (c.isInAnimationFrame(this.time)) {
- tt = c.time - c.start_time;
- if ( c.onRenderStart ) {
- c.onRenderStart(tt);
- }
- c.paintActorGL(this, tt);
- if ( c.onRenderEnd ) {
- c.onRenderEnd(tt);
- }
- if ( !c.isPaused() ) {
- c.time += time;
- }
- if ( CAAT.DEBUG ) {
- this.statistics.size_total+= c.size_total;
- this.statistics.size_active+= c.size_active;
- }
- }
- }
- this.glFlush();
- } else {
- ctx.globalAlpha = 1;
- ctx.globalCompositeOperation = 'source-over';
- ctx.save();
- if ( this.dirtyRectsEnabled ) {
- this.modelViewMatrix.transformRenderingContext( ctx );
- if ( !CAAT.DEBUG_DIRTYRECTS ) {
- ctx.beginPath();
- this.nDirtyRects=0;
- var dr= this.cDirtyRects;
- for( i=0; i<dr.length; i++ ) {
- var drr= dr[i];
- if ( !drr.isEmpty() ) {
- ctx.rect( drr.x|0, drr.y|0, 1+(drr.width|0), 1+(drr.height|0) );
- this.nDirtyRects++;
- }
- }
- ctx.clip();
- } else {
- ctx.clearRect(0, 0, this.width, this.height);
- }
- } else if (this.clear===true ) {
- ctx.clearRect(0, 0, this.width, this.height);
- }
- for (i = 0; i < ne; i++) {
- c= this.childrenList[i];
- if (c.isInAnimationFrame(this.time)) {
- tt = c.time - c.start_time;
- ctx.save();
- if ( c.onRenderStart ) {
- c.onRenderStart(tt);
- }
- if ( !CAAT.DEBUG_DIRTYRECTS && this.dirtyRectsEnabled ) {
- if ( this.nDirtyRects ) {
- c.paintActor(this, tt);
- }
- } else {
- c.paintActor(this, tt);
- }
- if ( c.onRenderEnd ) {
- c.onRenderEnd(tt);
- }
- ctx.restore();
- if (CAAT.DEBUGAABB) {
- ctx.globalAlpha= 1;
- ctx.globalCompositeOperation= 'source-over';
- this.modelViewMatrix.transformRenderingContextSet( ctx );
- c.drawScreenBoundingBox(this, tt);
- }
- if ( !c.isPaused() ) {
- c.time += time;
- }
- if ( CAAT.DEBUG ) {
- this.statistics.size_total+= c.size_total;
- this.statistics.size_active+= c.size_active;
- this.statistics.size_dirtyRects= this.nDirtyRects;
- }
- }
- }
- if ( this.nDirtyRects>0 && CAAT.DEBUG && CAAT.DEBUG_DIRTYRECTS ) {
- ctx.beginPath();
- this.nDirtyRects=0;
- var dr= this.cDirtyRects;
- for( i=0; i<dr.length; i++ ) {
- var drr= dr[i];
- if ( !drr.isEmpty() ) {
- ctx.rect( drr.x|0, drr.y|0, 1+(drr.width|0), 1+(drr.height|0) );
- this.nDirtyRects++;
- }
- }
- ctx.clip();
- ctx.fillStyle='rgba(160,255,150,.4)';
- ctx.fillRect(0,0,this.width, this.height);
- }
- ctx.restore();
- }
- this.frameCounter++;
- },
- /**
- * A director is a very special kind of actor.
- * Its animation routine simple sets its modelViewMatrix in case some transformation's been
- * applied.
- * No behaviors are allowed for Director instances.
- * @param director {CAAT.Director} redundant reference to CAAT.Director itself
- * @param time {number} director time.
- */
- animate : function(director, time) {
- this.setModelViewMatrix(this);
- this.modelViewMatrixI= this.modelViewMatrix.getInverse();
- this.setScreenBounds();
- this.dirty= false;
- this.invalid= false;
- this.dirtyRectsIndex= -1;
- this.cDirtyRects= [];
- var cl= this.childrenList;
- var cli;
- for (var i = 0; i < cl.length; i++) {
- cli= cl[i];
- var tt = cli.time - cli.start_time;
- cli.animate(this, tt);
- }
- return this;
- },
- /**
- * Add a rectangle to the list of dirty screen areas which should be redrawn.
- * This is the opposite method to clear the whole screen and repaint everything again.
- * Despite i'm not very fond of dirty rectangles because it needs some extra calculations, this
- * procedure has shown to be speeding things up under certain situations. Nevertheless it doesn't or
- * even lowers performance under others, so it is a developer choice to activate them via a call to
- * setClear( CAAT.Director.CLEAR_DIRTY_RECTS ).
- *
- * This function, not only tracks a list of dirty rectangles, but tries to optimize the list. Overlapping
- * rectangles will be removed and intersecting ones will be unioned.
- *
- * Before calling this method, check if this.dirtyRectsEnabled is true.
- *
- * @param rectangle {CAAT.Rectangle}
- */
- addDirtyRect : function( rectangle ) {
- if ( rectangle.isEmpty() ) {
- return;
- }
- var i, dr, j, drj;
- var cdr= this.cDirtyRects;
- for( i=0; i<cdr.length; i++ ) {
- dr= cdr[i];
- if ( !dr.isEmpty() && dr.intersects( rectangle ) ) {
- var intersected= true;
- while( intersected ) {
- dr.unionRectangle( rectangle );
- for( j=0; j<cdr.length; j++ ) {
- if ( j!==i ) {
- drj= cdr[j];
- if ( !drj.isEmpty() && drj.intersects( dr ) ) {
- dr.unionRectangle( drj );
- drj.setEmpty();
- break;
- }
- }
- }
- if ( j==cdr.length ) {
- intersected= false;
- }
- }
- for( j=0; j<cdr.length; j++ ) {
- if ( cdr[j].isEmpty() ) {
- cdr.splice( j, 1 );
- }
- }
- return;
- }
- }
- this.dirtyRectsIndex++;
- if ( this.dirtyRectsIndex>=this.dirtyRects.length ) {
- for( i=0; i<32; i++ ) {
- this.dirtyRects.push( new CAAT.Rectangle() );
- }
- }
- var r= this.dirtyRects[ this.dirtyRectsIndex ];
- r.x= rectangle.x;
- r.y= rectangle.y;
- r.x1= rectangle.x1;
- r.y1= rectangle.y1;
- r.width= rectangle.width;
- r.height= rectangle.height;
- this.cDirtyRects.push( r );
- },
- /**
- * This method draws an Scene to an offscreen canvas. This offscreen canvas is also a child of
- * another Scene (transitionScene). So instead of drawing two scenes while transitioning from
- * one to another, first of all an scene is drawn to offscreen, and that image is translated.
- * <p>
- * Until the creation of this method, both scenes where drawn while transitioning with
- * its performance penalty since drawing two scenes could be twice as expensive than drawing
- * only one.
- * <p>
- * Though a high performance increase, we should keep an eye on memory consumption.
- *
- * @param ctx a <code>canvas.getContext('2d')</code> instnce.
- * @param scene {CAAT.Scene} the scene to draw offscreen.
- */
- renderToContext : function(ctx, scene) {
- /**
- * draw actors on scene.
- */
- if (scene.isInAnimationFrame(this.time)) {
- ctx.setTransform(1,0,0,1, 0,0);
- ctx.globalAlpha = 1;
- ctx.globalCompositeOperation = 'source-over';
- ctx.clearRect(0, 0, this.width, this.height);
- var octx = this.ctx;
- var ocrc = this.crc;
- this.ctx = ctx;
- this.crc = ctx;
- ctx.save();
- /**
- * to draw an scene to an offscreen canvas, we have to:
- * 1.- save diector's world model view matrix
- * 2.- set no transformation on director since we want the offscreen to
- * be drawn 1:1.
- * 3.- set world dirty flag, so that the scene will recalculate its matrices
- * 4.- animate the scene
- * 5.- paint the scene
- * 6.- restore world model view matrix.
- */
- var matmv= this.modelViewMatrix;
- var matwmv= this.worldModelViewMatrix;
- this.worldModelViewMatrix= new CAAT.Matrix();
- this.modelViewMatrix= this.worldModelViewMatrix;
- this.wdirty= true;
- scene.animate(this, scene.time);
- if ( scene.onRenderStart ) {
- scene.onRenderStart(scene.time);
- }
- scene.paintActor(this, scene.time);
- if ( scene.onRenderEnd ) {
- scene.onRenderEnd(scene.time);
- }
- this.worldModelViewMatrix = matwmv;
- this.modelViewMatrix= matmv;
- ctx.restore();
- this.ctx = octx;
- this.crc = ocrc;
- }
- },
- /**
- * Add a new Scene to Director's Scene list. By adding a Scene to the Director
- * does not mean it will be immediately visible, you should explicitly call either
- * <ul>
- * <li>easeIn
- * <li>easeInOut
- * <li>easeInOutRandom
- * <li>setScene
- * <li>or any of the scene switching methods
- * </ul>
- *
- * @param scene {CAAT.Scene} an CAAT.Scene object.
- */
- addScene : function(scene) {
- scene.setBounds(0, 0, this.width, this.height);
- this.scenes.push(scene);
- scene.setEaseListener(this);
- if (null === this.currentScene) {
- this.setScene(0);
- }
- },
- /**
- * Get the number of scenes contained in the Director.
- * @return {number} the number of scenes contained in the Director.
- */
- getNumScenes : function() {
- return this.scenes.length;
- },
- /**
- * This method offers full control over the process of switching between any given two Scenes.
- * To apply this method, you must specify the type of transition to apply for each Scene and
- * the anchor to keep the Scene pinned at.
- * <p>
- * The type of transition will be one of the following values defined in CAAT.Scene.prototype:
- * <ul>
- * <li>EASE_ROTATION
- * <li>EASE_SCALE
- * <li>EASE_TRANSLATION
- * </ul>
- *
- * <p>
- * The anchor will be any of these values defined in CAAT.Actor.prototype:
- * <ul>
- * <li>ANCHOR_CENTER
- * <li>ANCHOR_TOP
- * <li>ANCHOR_BOTTOM
- * <li>ANCHOR_LEFT
- * <li>ANCHOR_RIGHT
- * <li>ANCHOR_TOP_LEFT
- * <li>ANCHOR_TOP_RIGHT
- * <li>ANCHOR_BOTTOM_LEFT
- * <li>ANCHOR_BOTTOM_RIGHT
- * </ul>
- *
- * <p>
- * In example, for an entering scene performing a EASE_SCALE transition, the anchor is the
- * point by which the scene will scaled.
- *
- * @param inSceneIndex integer indicating the Scene index to bring in to the Director.
- * @param typein integer indicating the type of transition to apply to the bringing in Scene.
- * @param anchorin integer indicating the anchor of the bringing in Scene.
- * @param outSceneIndex integer indicating the Scene index to take away from the Director.
- * @param typeout integer indicating the type of transition to apply to the taking away in Scene.
- * @param anchorout integer indicating the anchor of the taking away Scene.
- * @param time inteter indicating the time to perform the process of switchihg between Scene object
- * in milliseconds.
- * @param alpha boolean boolean indicating whether alpha transparency fading will be applied to
- * the scenes.
- * @param interpolatorIn CAAT.Interpolator object to apply to entering scene.
- * @param interpolatorOut CAAT.Interpolator object to apply to exiting scene.
- */
- easeInOut : function(inSceneIndex, typein, anchorin, outSceneIndex, typeout, anchorout, time, alpha, interpolatorIn, interpolatorOut) {
- if (inSceneIndex === this.getCurrentSceneIndex()) {
- return;
- }
- var ssin = this.scenes[ inSceneIndex ];
- var sout = this.scenes[ outSceneIndex ];
- if ( !CAAT.__CSS__ && !this.glEnabled ) {
- this.renderToContext(this.transitionScene.ctx, sout);
- sout = this.transitionScene;
- }
- ssin.setExpired(false);
- sout.setExpired(false);
- ssin.mouseEnabled = false;
- sout.mouseEnabled = false;
- ssin.resetTransform();
- sout.resetTransform();
- ssin.setLocation(0, 0);
- sout.setLocation(0, 0);
- ssin.alpha = 1;
- sout.alpha = 1;
- if (typein === CAAT.Scene.prototype.EASE_ROTATION) {
- ssin.easeRotationIn(time, alpha, anchorin, interpolatorIn);
- } else if (typein === CAAT.Scene.prototype.EASE_SCALE) {
- ssin.easeScaleIn(0, time, alpha, anchorin, interpolatorIn);
- } else {
- ssin.easeTranslationIn(time, alpha, anchorin, interpolatorIn);
- }
- if (typeout === CAAT.Scene.prototype.EASE_ROTATION) {
- sout.easeRotationOut(time, alpha, anchorout, interpolatorOut);
- } else if (typeout === CAAT.Scene.prototype.EASE_SCALE) {
- sout.easeScaleOut(0, time, alpha, anchorout, interpolatorOut);
- } else {
- sout.easeTranslationOut(time, alpha, anchorout, interpolatorOut);
- }
- this.childrenList = [];
- this.addChild(sout);
- this.addChild(ssin);
- },
- /**
- * This method will switch between two given Scene indexes (ie, take away scene number 2,
- * and bring in scene number 5).
- * <p>
- * It will randomly choose for each Scene the type of transition to apply and the anchor
- * point of each transition type.
- * <p>
- * It will also set for different kind of transitions the following interpolators:
- * <ul>
- * <li>EASE_ROTATION -> ExponentialInOutInterpolator, exponent 4.
- * <li>EASE_SCALE -> ElasticOutInterpolator, 1.1 and .4
- * <li>EASE_TRANSLATION -> BounceOutInterpolator
- * </ul>
- *
- * <p>
- * These are the default values, and could not be changed by now.
- * This method in final instance delegates the process to easeInOutMethod.
- *
- * @see easeInOutMethod.
- *
- * @param inIndex integer indicating the entering scene index.
- * @param outIndex integer indicating the exiting scene index.
- * @param time integer indicating the time to take for the process of Scene in/out in milliseconds.
- * @param alpha boolean indicating whether alpha transparency fading should be applied to transitions.
- */
- easeInOutRandom : function(inIndex, outIndex, time, alpha) {
- var pin = Math.random();
- var pout = Math.random();
- var typeIn;
- var interpolatorIn;
- if (pin < 0.33) {
- typeIn = CAAT.Scene.prototype.EASE_ROTATION;
- interpolatorIn = new CAAT.Interpolator().createExponentialInOutInterpolator(4);
- } else if (pin < 0.66) {
- typeIn = CAAT.Scene.prototype.EASE_SCALE;
- interpolatorIn = new CAAT.Interpolator().createElasticOutInterpolator(1.1, 0.4);
- } else {
- typeIn = CAAT.Scene.prototype.EASE_TRANSLATE;
- interpolatorIn = new CAAT.Interpolator().createBounceOutInterpolator();
- }
- var typeOut;
- var interpolatorOut;
- if (pout < 0.33) {
- typeOut = CAAT.Scene.prototype.EASE_ROTATION;
- interpolatorOut = new CAAT.Interpolator().createExponentialInOutInterpolator(4);
- } else if (pout < 0.66) {
- typeOut = CAAT.Scene.prototype.EASE_SCALE;
- interpolatorOut = new CAAT.Interpolator().createExponentialOutInterpolator(4);
- } else {
- typeOut = CAAT.Scene.prototype.EASE_TRANSLATE;
- interpolatorOut = new CAAT.Interpolator().createBounceOutInterpolator();
- }
- this.easeInOut(
- inIndex,
- typeIn,
- (Math.random() * 8.99) >> 0,
- outIndex,
- typeOut,
- (Math.random() * 8.99) >> 0,
- time,
- alpha,
- interpolatorIn,
- interpolatorOut);
- },
- /**
- * This method changes Director's current Scene to the scene index indicated by
- * inSceneIndex parameter. The Scene running in the director won't be eased out.
- *
- * @see {CAAT.Interpolator}
- * @see {CAAT.Actor}
- * @see {CAAT.Scene}
- *
- * @param inSceneIndex integer indicating the new Scene to set as current.
- * @param type integer indicating the type of transition to apply to bring the new current
- * Scene to the Director. The values will be one of: CAAT.Scene.prototype.EASE_ROTATION,
- * CAAT.Scene.prototype.EASE_SCALE, CAAT.Scene.prototype.EASE_TRANSLATION.
- * @param time integer indicating how much time in milliseconds the Scene entrance will take.
- * @param alpha boolean indicating whether alpha transparency fading will be applied to the
- * entereing Scene.
- * @param anchor integer indicating the anchor to fix for Scene transition. It will be any of
- * CAAT.Actor.prototype.ANCHOR_* values.
- * @param interpolator an CAAT.Interpolator object indicating the interpolation function to
- * apply.
- */
- easeIn : function(inSceneIndex, type, time, alpha, anchor, interpolator) {
- var sin = this.scenes[ inSceneIndex ];
- if (type === CAAT.Scene.prototype.EASE_ROTATION) {
- sin.easeRotationIn(time, alpha, anchor, interpolator);
- } else if (type === CAAT.Scene.prototype.EASE_SCALE) {
- sin.easeScaleIn(0, time, alpha, anchor, interpolator);
- } else {
- sin.easeTranslationIn(time, alpha, anchor, interpolator);
- }
- this.childrenList = [];
- this.addChild(sin);
- sin.resetTransform();
- sin.setLocation(0, 0);
- sin.alpha = 1;
- sin.mouseEnabled = false;
- sin.setExpired(false);
- },
- /**
- * Changes (or sets) the current Director scene to the index
- * parameter. There will be no transition on scene change.
- * @param sceneIndex {number} an integer indicating the index of the target Scene
- * to be shown.
- */
- setScene : function(sceneIndex) {
- var sin = this.scenes[ sceneIndex ];
- this.childrenList = [];
- this.addChild(sin);
- this.currentScene = sin;
- sin.setExpired(false);
- sin.mouseEnabled = true;
- sin.resetTransform();
- sin.setLocation(0, 0);
- sin.alpha = 1;
- sin.activated();
- },
- /**
- * This method will change the current Scene by the Scene indicated as parameter.
- * It will apply random values for anchor and transition type.
- * @see easeInOutRandom
- *
- * @param iNewSceneIndex {number} an integer indicating the index of the new scene to run on the Director.
- * @param time {number} an integer indicating the time the Scene transition will take.
- * @param alpha {boolean} a boolean indicating whether Scene transition should be fading.
- * @param transition {boolean} a boolean indicating whether the scene change must smoothly animated.
- */
- switchToScene : function(iNewSceneIndex, time, alpha, transition) {
- var currentSceneIndex = this.getSceneIndex(this.currentScene);
- if (!transition) {
- this.setScene(iNewSceneIndex);
- }
- else {
- this.easeInOutRandom(iNewSceneIndex, currentSceneIndex, time, alpha);
- }
- },
- /**
- * Sets the previous Scene in sequence as the current Scene.
- * @see switchToScene.
- *
- * @param time {number} integer indicating the time the Scene transition will take.
- * @param alpha {boolean} a boolean indicating whether Scene transition should be fading.
- * @param transition {boolean} a boolean indicating whether the scene change must smoothly animated.
- */
- switchToPrevScene : function(time, alpha, transition) {
- var currentSceneIndex = this.getSceneIndex(this.currentScene);
- if (this.getNumScenes() <= 1 || currentSceneIndex === 0) {
- return;
- }
- if (!transition) {
- this.setScene(currentSceneIndex - 1);
- }
- else {
- this.easeInOutRandom(currentSceneIndex - 1, currentSceneIndex, time, alpha);
- }
- },
- /**
- * Sets the previous Scene in sequence as the current Scene.
- * @see switchToScene.
- *
- * @param time {number} integer indicating the time the Scene transition will take.
- * @param alpha {boolean} a boolean indicating whether Scene transition should be fading.
- * @param transition {boolean} a boolean indicating whether the scene change must smoothly animated.
- */
- switchToNextScene: function(time, alpha, transition) {
- var currentSceneIndex = this.getSceneIndex(this.currentScene);
- if (this.getNumScenes() <= 1 || currentSceneIndex === this.getNumScenes() - 1) {
- return;
- }
- if (!transition) {
- this.setScene(currentSceneIndex + 1);
- }
- else {
- this.easeInOutRandom(currentSceneIndex + 1, currentSceneIndex, time, alpha);
- }
- },
- mouseEnter : function(mouseEvent) {
- },
- mouseExit : function(mouseEvent) {
- },
- mouseMove : function(mouseEvent) {
- },
- mouseDown : function(mouseEvent) {
- },
- mouseUp : function(mouseEvent) {
- },
- mouseDrag : function(mouseEvent) {
- },
- /**
- * Scene easing listener. Notifies scenes when they're about to be activated (set as current
- * director's scene).
- *
- * @param scene {CAAT.Scene} the scene that has just been brought in or taken out of the director.
- * @param b_easeIn {boolean} scene enters or exits ?
- */
- easeEnd : function(scene, b_easeIn) {
- // scene is going out
- if (!b_easeIn) {
- scene.setExpired(true);
- } else {
- this.currentScene = scene;
- this.currentScene.activated();
- }
- scene.mouseEnabled = true;
- scene.emptyBehaviorList();
- },
- /**
- * Return the index for a given Scene object contained in the Director.
- * @param scene {CAAT.Scene}
- */
- getSceneIndex : function(scene) {
- for (var i = 0; i < this.scenes.length; i++) {
- if (this.scenes[i] === scene) {
- return i;
- }
- }
- return -1;
- },
- /**
- * Get a concrete director's scene.
- * @param index {number} an integer indicating the scene index.
- * @return {CAAT.Scene} a CAAT.Scene object instance or null if the index is oob.
- */
- getScene : function(index) {
- return this.scenes[index];
- },
- /**
- * Return the index of the current scene in the Director's scene list.
- * @return {number} the current scene's index.
- */
- getCurrentSceneIndex : function() {
- return this.getSceneIndex(this.currentScene);
- },
- /**
- * Return the running browser name.
- * @return {string} the browser name.
- */
- getBrowserName : function() {
- return this.browserInfo.browser;
- },
- /**
- * Return the running browser version.
- * @return {string} the browser version.
- */
- getBrowserVersion : function() {
- return this.browserInfo.version;
- },
- /**
- * Return the operating system name.
- * @return {string} the os name.
- */
- getOSName : function() {
- return this.browserInfo.OS;
- },
- /**
- * Gets the resource with the specified resource name.
- * The Director holds a collection called <code>imagesCache</code>
- * where you can store a JSON of the form
- * <code>[ { id: imageId, image: imageObject } ]</code>.
- * This structure will be used as a resources cache.
- * There's a CAAT.ImagePreloader class to preload resources and
- * generate this structure on loading finalization.
- *
- * @param sId {object} an String identifying a resource.
- */
- getImage : function(sId) {
- var ret = this.imagesCache[sId];
- if (ret) {
- return ret;
- }
- for (var i = 0; i < this.imagesCache.length; i++) {
- if (this.imagesCache[i].id === sId) {
- return this.imagesCache[i].image;
- }
- }
- return null;
- },
- /**
- * Adds an audio to the cache.
- *
- * @see CAAT.AudioManager.addAudio
- * @return this
- */
- addAudio : function(id, url) {
- this.audioManager.addAudio(id, url);
- return this;
- },
- /**
- * Plays the audio instance identified by the id.
- * @param id {object} the object used to store a sound in the audioCache.
- */
- audioPlay : function(id) {
- this.audioManager.play(id);
- },
- /**
- * Loops an audio instance identified by the id.
- * @param id {object} the object used to store a sound in the audioCache.
- *
- * @return {HTMLElement|null} the value from audioManager.loop
- */
- audioLoop : function(id) {
- return this.audioManager.loop(id);
- },
- endSound : function() {
- return this.audioManager.endSound();
- },
- setSoundEffectsEnabled : function(enabled) {
- return this.audioManager.setSoundEffectsEnabled(enabled);
- },
- setMusicEnabled : function(enabled) {
- return this.audioManager.setMusicEnabled(enabled);
- },
- isMusicEnabled : function() {
- return this.audioManager.isMusicEnabled();
- },
- isSoundEffectsEnabled : function() {
- return this.audioManager.isSoundEffectsEnabled();
- },
- setVolume : function( id, volume ) {
- return this.audioManager.setVolume( id, volume );
- },
- /**
- * Removes Director's scenes.
- */
- emptyScenes : function() {
- this.scenes = [];
- },
- /**
- * Adds an scene to this Director.
- * @param scene {CAAT.Scene} a scene object.
- */
- addChild : function(scene) {
- scene.parent = this;
- this.childrenList.push(scene);
- },
- /**
- * @Deprecated use CAAT.loop instead.
- * @param fps
- * @param callback
- * @param callback2
- */
- loop : function(fps,callback,callback2) {
- if ( callback2 ) {
- this.onRenderStart= callback;
- this.onRenderEnd= callback2;
- } else if (callback) {
- this.onRenderEnd= callback;
- }
- CAAT.loop();
- },
- /**
- * Starts the director animation.If no scene is explicitly selected, the current Scene will
- * be the first scene added to the Director.
- * <p>
- * The fps parameter will set the animation quality. Higher values,
- * means CAAT will try to render more frames in the same second (at the
- * expense of cpu power at least until hardware accelerated canvas rendering
- * context are available). A value of 60 is a high frame rate and should not be exceeded.
- *
- * @param fps {number} integer value indicating the target frames per second to run
- * the animation at.
- */
- renderFrame : function(fps, callback) {
- if (this.stopped) {
- return;
- }
- var t = new Date().getTime(),
- delta = t - this.timeline;
- /*
- check for massive frame time. if for example the current browser tab is minified or taken out of
- foreground, the system will account for a bit time interval. minify that impact by lowering down
- the elapsed time (virtual timelines FTW)
- */
- if ( delta > 500 ) {
- delta= 500;
- }
- if ( this.onRenderStart ) {
- this.onRenderStart(delta);
- }
- this.render(delta);
- if ( this.debugInfo ) {
- this.debugInfo(this.statistics);
- }
-
- this.timeline = t;
- if (this.onRenderEnd) {
- this.onRenderEnd(delta);
- }
- },
- endLoop : function () {
- },
- /**
- * This method states whether the director must clear background before rendering
- * each frame.
- *
- * The clearing method could be:
- * + CAAT.Director.CLEAR_ALL. previous to draw anything on screen the canvas will have clearRect called on it.
- * + CAAT.Director.CLEAR_DIRTY_RECTS. Actors marked as invalid, or which have been moved, rotated or scaled
- * will have their areas redrawn.
- * + CAAT.Director.CLEAR_NONE. clears nothing.
- *
- * @param clear {CAAT.Director.CLEAR_ALL |�CAAT.Director.CLEAR_NONE | CAAT.Director.CLEAR_DIRTY_RECTS}
- * @return this.
- */
- setClear : function(clear) {
- this.clear = clear;
- if ( this.clear===CAAT.Director.CLEAR_DIRTY_RECTS ) {
- this.dirtyRectsEnabled= true;
- }
- return this;
- },
- /**
- * Get this Director's AudioManager instance.
- * @return {CAAT.AudioManager} the AudioManager instance.
- */
- getAudioManager : function() {
- return this.audioManager;
- },
- /**
- * Acculumate dom elements position to properly offset on-screen mouse/touch events.
- * @param node
- */
- cumulateOffset : function(node, parent, prop) {
- var left= prop+'Left';
- var top= prop+'Top';
- var x=0, y=0, style;
- while( navigator.browser!=='iOS' && node && node.style ) {
- if ( node.currentStyle ) {
- style= node.currentStyle['position'];
- } else {
- style= (node.ownerDocument.defaultView || node.ownerDocument.parentWindow).getComputedStyle(node, null);
- style= style ? style.getPropertyValue('position') : null;
- }
- // if (!/^(relative|absolute|fixed)$/.test(style)) {
- if (!/^(fixed)$/.test(style)) {
- x += node[left];
- y+= node[top];
- node = node[parent];
- } else {
- break;
- }
- }
- return {
- x: x,
- y: y,
- style: style
- };
- },
- getOffset : function( node ) {
- var res= this.cumulateOffset(node, 'offsetParent', 'offset');
- if ( res.style==='fixed' ) {
- var res2= this.cumulateOffset(node, node.parentNode ? 'parentNode' : 'parentElement', 'scroll');
- return {
- x: res.x + res2.x,
- y: res.y + res2.y
- };
- }
- return {
- x: res.x,
- y: res.y
- };
- },
- /**
- * Normalize input event coordinates to be related to (0,0) canvas position.
- * @param point {CAAT.Point} a CAAT.Point instance to hold the canvas coordinate.
- * @param e {MouseEvent} a mouse event from an input event.
- */
- getCanvasCoord : function(point, e) {
- var pt= new CAAT.Point( );
- var posx = 0;
- var posy = 0;
- if (!e) e = window.event;
- if (e.pageX || e.pageY) {
- posx = e.pageX;
- posy = e.pageY;
- }
- else if (e.clientX || e.clientY) {
- posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
- posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
- }
- var offset= this.getOffset(this.canvas);
- posx-= offset.x;
- posy-= offset.y;
- //////////////
- // transformar coordenada inversamente con affine transform de director.
- pt.x= posx;
- pt.y= posy;
- if ( !this.modelViewMatrixI ) {
- this.modelViewMatrixI= this.modelViewMatrix.getInverse();
- }
- this.modelViewMatrixI.transformCoord(pt);
- posx= pt.x;
- posy= pt.y
- point.set(posx, posy);
- this.screenMousePoint.set(posx, posy);
- },
- __mouseDownHandler : function(e) {
- /*
- was dragging and mousedown detected, can only mean a mouseOut's been performed and on mouseOver, no
- button was presses. Then, send a mouseUp for the previos actor, and return;
- */
- if ( this.dragging && this.lastSelectedActor ) {
- this.__mouseUpHandler(e);
- return;
- }
- this.getCanvasCoord(this.mousePoint, e);
- this.isMouseDown = true;
- var lactor = this.findActorAtPosition(this.mousePoint);
- if (null !== lactor) {
- var pos = lactor.viewToModel(
- new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
- lactor.mouseDown(
- new CAAT.MouseEvent().init(
- pos.x,
- pos.y,
- e,
- lactor,
- new CAAT.Point(
- this.screenMousePoint.x,
- this.screenMousePoint.y )));
- }
- this.lastSelectedActor= lactor;
- },
- __mouseUpHandler : function(e) {
- this.isMouseDown = false;
- this.getCanvasCoord(this.mousePoint, e);
- var pos= null;
- var lactor= this.lastSelectedActor;
- if (null !== lactor) {
- pos = lactor.viewToModel(
- new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
- if ( lactor.actionPerformed && lactor.contains(pos.x, pos.y) ) {
- lactor.actionPerformed(e)
- }
- lactor.mouseUp(
- new CAAT.MouseEvent().init(
- pos.x,
- pos.y,
- e,
- lactor,
- this.screenMousePoint,
- this.currentScene.time));
- }
- if (!this.dragging && null !== lactor) {
- if (lactor.contains(pos.x, pos.y)) {
- lactor.mouseClick(
- new CAAT.MouseEvent().init(
- pos.x,
- pos.y,
- e,
- lactor,
- this.screenMousePoint,
- this.currentScene.time));
- }
- }
- this.dragging = false;
- this.in_= false;
- // CAAT.setCursor('default');
- },
- __mouseMoveHandler : function(e) {
- //this.getCanvasCoord(this.mousePoint, e);
- var lactor;
- var pos;
- var ct= this.currentScene ? this.currentScene.time : 0;
- // drag
- if (this.isMouseDown && null !== this.lastSelectedActor) {
- lactor = this.lastSelectedActor;
- pos = lactor.viewToModel(
- new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
- // check for mouse move threshold.
- if (!this.dragging) {
- if (Math.abs(this.prevMousePoint.x - pos.x) < CAAT.DRAG_THRESHOLD_X &&
- Math.abs(this.prevMousePoint.y - pos.y) < CAAT.DRAG_THRESHOLD_Y) {
- return;
- }
- }
- this.dragging = true;
- var px= lactor.x;
- var py= lactor.y;
- lactor.mouseDrag(
- new CAAT.MouseEvent().init(
- pos.x,
- pos.y,
- e,
- lactor,
- new CAAT.Point(
- this.screenMousePoint.x,
- this.screenMousePoint.y),
- ct));
- this.prevMousePoint.x= pos.x;
- this.prevMousePoint.y= pos.y;
- /**
- * Element has not moved after drag, so treat it as a button.
- */
- if ( px===lactor.x && py===lactor.y ) {
- var contains= lactor.contains(pos.x, pos.y);
- if (this.in_ && !contains) {
- lactor.mouseExit(
- new CAAT.MouseEvent().init(
- pos.x,
- pos.y,
- e,
- lactor,
- this.screenMousePoint,
- ct));
- this.in_ = false;
- }
- if (!this.in_ && contains ) {
- lactor.mouseEnter(
- new CAAT.MouseEvent().init(
- pos.x,
- pos.y,
- e,
- lactor,
- this.screenMousePoint,
- ct));
- this.in_ = true;
- }
- }
- return;
- }
- // mouse move.
- this.in_= true;
- lactor = this.findActorAtPosition(this.mousePoint);
- // cambiamos de actor.
- if (lactor !== this.lastSelectedActor) {
- if (null !== this.lastSelectedActor) {
- pos = this.lastSelectedActor.viewToModel(
- new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
- this.lastSelectedActor.mouseExit(
- new CAAT.MouseEvent().init(
- pos.x,
- pos.y,
- e,
- this.lastSelectedActor,
- this.screenMousePoint,
- ct));
- }
- if (null !== lactor) {
- pos = lactor.viewToModel(
- new CAAT.Point( this.screenMousePoint.x, this.screenMousePoint.y, 0));
- lactor.mouseEnter(
- new CAAT.MouseEvent().init(
- pos.x,
- pos.y,
- e,
- lactor,
- this.screenMousePoint,
- ct));
- }
- }
- pos = lactor.viewToModel(
- new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
- if (null !== lactor) {
- lactor.mouseMove(
- new CAAT.MouseEvent().init(
- pos.x,
- pos.y,
- e,
- lactor,
- this.screenMousePoint,
- ct));
- }
- this.prevMousePoint.x= pos.x;
- this.prevMousePoint.y= pos.y;
- this.lastSelectedActor = lactor;
- },
- __mouseOutHandler : function(e) {
- if ( this.dragging ) {
- return;
- }
- if (null !== this.lastSelectedActor ) {
- this.getCanvasCoord(this.mousePoint, e);
- var pos = new CAAT.Point(this.mousePoint.x, this.mousePoint.y, 0);
- this.lastSelectedActor.viewToModel(pos);
- var ev= new CAAT.MouseEvent().init(
- pos.x,
- pos.y,
- e,
- this.lastSelectedActor,
- this.screenMousePoint,
- this.currentScene.time);
- this.lastSelectedActor.mouseExit(ev);
- this.lastSelectedActor.mouseOut(ev);
- if ( !this.dragging ) {
- this.lastSelectedActor = null;
- }
- } else {
- this.isMouseDown = false;
- this.in_ = false;
- }
- },
- __mouseOverHandler : function(e) {
- if (this.dragging ) {
- return;
- }
- var lactor;
- var pos, ev;
- if ( null==this.lastSelectedActor ) {
- lactor= this.findActorAtPosition( this.mousePoint );
- if (null !== lactor) {
- pos = lactor.viewToModel(
- new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
- ev= new CAAT.MouseEvent().init(
- pos.x,
- pos.y,
- e,
- lactor,
- this.screenMousePoint,
- this.currentScene ? this.currentScene.time : 0);
- lactor.mouseOver(ev);
- lactor.mouseEnter(ev);
- }
- this.lastSelectedActor= lactor;
- } else {
- lactor= this.lastSelectedActor;
- pos = lactor.viewToModel(
- new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
- ev= new CAAT.MouseEvent().init(
- pos.x,
- pos.y,
- e,
- lactor,
- this.screenMousePoint,
- this.currentScene.time);
- lactor.mouseOver(ev);
- lactor.mouseEnter(ev);
-
- }
- },
- __mouseDBLClickHandler : function(e) {
- this.getCanvasCoord(this.mousePoint, e);
- if (null !== this.lastSelectedActor) {
- /*
- var pos = this.lastSelectedActor.viewToModel(
- new CAAT.Point(this.screenMousePoint.x, this.screenMousePoint.y, 0));
- */
- this.lastSelectedActor.mouseDblClick(
- new CAAT.MouseEvent().init(
- this.mousePoint.x,
- this.mousePoint.y,
- e,
- this.lastSelectedActor,
- this.screenMousePoint,
- this.currentScene.time));
- }
- },
- /**
- * Same as mouseDown but not preventing event.
- * Will only take care of first touch.
- * @param e
- */
- __touchStartHandler : function(e) {
- if ( e.target===this.canvas ) {
- e.preventDefault();
- e= e.targetTouches[0];
- var mp= this.mousePoint;
- this.getCanvasCoord(mp, e);
- if ( mp.x<0 || mp.y<0 || mp.x>=this.width || mp.y>=this.height ) {
- return;
- }
- this.touching= true;
- this.__mouseDownHandler(e);
- }
- },
- __touchEndHandler : function(e) {
- if ( this.touching ) {
- e.preventDefault();
- e= e.changedTouches[0];
- var mp= this.mousePoint;
- this.getCanvasCoord(mp, e);
- this.touching= false;
- this.__mouseUpHandler(e);
- }
- },
- __touchMoveHandler : function(e) {
- if ( this.touching ) {
- e.preventDefault();
- if ( this.gesturing ) {
- return;
- }
- for( var i=0; i<e.targetTouches.length; i++ ) {
- var ee= e.targetTouches[i];
- var mp= this.mousePoint;
- this.getCanvasCoord(mp, ee);
- this.__mouseMoveHandler(ee);
- }
- }
- },
- __gestureStart : function( scale, rotation ) {
- this.gesturing= true;
- this.__gestureRotation= this.lastSelectedActor.rotationAngle;
- this.__gestureSX= this.lastSelectedActor.scaleX - 1;
- this.__gestureSY= this.lastSelectedActor.scaleY - 1;
- },
- __gestureChange : function( scale, rotation ) {
- if ( typeof scale==='undefined' || typeof rotation==='undefined' ) {
- return;
- }
- if ( this.lastSelectedActor!==null && this.lastSelectedActor.isGestureEnabled() ) {
- this.lastSelectedActor.setRotation( rotation*Math.PI/180 + this.__gestureRotation );
- this.lastSelectedActor.setScale(
- this.__gestureSX + scale,
- this.__gestureSY + scale );
- }
- },
- __gestureEnd : function( scale, rotation ) {
- this.gesturing= false;
- this.__gestureRotation= 0;
- this.__gestureScale= 0;
- },
- addHandlers: function(canvas) {
- var me= this;
- window.addEventListener('mouseup', function(e) {
- if ( me.touching ) {
- e.preventDefault();
- e.cancelBubble = true;
- if (e.stopPropagation) e.stopPropagation();
- var mp= me.mousePoint;
- me.getCanvasCoord(mp, e);
- me.__mouseUpHandler(e);
- me.touching= false;
- }
- }, false );
- window.addEventListener('mousedown', function(e) {
- if ( e.target===canvas ) {
- e.preventDefault();
- e.cancelBubble = true;
- if (e.stopPropagation) e.stopPropagation();
- var mp= me.mousePoint;
- me.getCanvasCoord(mp, e);
- if ( mp.x<0 || mp.y<0 || mp.x>=me.width || mp.y>=me.height ) {
- return;
- }
- me.touching= true;
- me.__mouseDownHandler(e);
- }
- }, false );
- window.addEventListener('mouseover',function(e) {
- if ( e.target===canvas && !me.dragging ) {
- e.preventDefault();
- e.cancelBubble = true;
- if (e.stopPropagation) e.stopPropagation();
- var mp= me.mousePoint;
- me.getCanvasCoord(mp, e);
- if ( mp.x<0 || mp.y<0 || mp.x>=me.width || mp.y>=me.height ) {
- return;
- }
- me.__mouseOverHandler(e);
- }
- }, false);
- window.addEventListener('mouseout',function(e) {
- if ( e.target===canvas && !me.dragging ) {
- e.preventDefault();
- e.cancelBubble = true;
- if (e.stopPropagation) e.stopPropagation();
- var mp= me.mousePoint;
- me.getCanvasCoord(mp, e);
- me.__mouseOutHandler(e);
- }
- }, false);
- window.addEventListener('mousemove',
- function(e) {
- e.preventDefault();
- e.cancelBubble = true;
- if (e.stopPropagation) e.stopPropagation();
- var mp= me.mousePoint;
- me.getCanvasCoord(mp, e);
- if ( !me.dragging && ( mp.x<0 || mp.y<0 || mp.x>=me.width || mp.y>=me.height ) ) {
- return;
- }
- me.__mouseMoveHandler(e);
- },
- false);
- window.addEventListener("dblclick", function(e) {
- if ( e.target===canvas ) {
- e.preventDefault();
- e.cancelBubble = true;
- if (e.stopPropagation) e.stopPropagation();
- var mp= me.mousePoint;
- me.getCanvasCoord(mp, e);
- if ( mp.x<0 || mp.y<0 || mp.x>=me.width || mp.y>=me.height ) {
- return;
- }
- me.__mouseDBLClickHandler(e);
- }
- }, false);
- window.addEventListener("touchstart", this.__touchStartHandler.bind(this), false);
- window.addEventListener("touchmove", this.__touchMoveHandler.bind(this), false);
- window.addEventListener("touchend", this.__touchEndHandler.bind(this), false);
- window.addEventListener("gesturestart", function(e) {
- if ( e.target===canvas ) {
- e.preventDefault();
- me.__gestureStart( e.scale, e.rotation );
- }
- }, false );
- window.addEventListener("gestureend", function(e) {
- if ( e.target===canvas ) {
- e.preventDefault();
- me.__gestureEnd( e.scale, e.rotation );
- }
- }, false );
- window.addEventListener("gesturechange", function(e) {
- if ( e.target===canvas ) {
- e.preventDefault();
- me.__gestureChange( e.scale, e.rotation );
- }
- }, false );
- },
- enableEvents : function( onElement ) {
- CAAT.RegisterDirector(this);
- this.in_ = false;
- this.createEventHandler( onElement );
- },
- createEventHandler : function( onElement ) {
- //var canvas= this.canvas;
- this.in_ = false;
- //this.addHandlers(canvas);
- this.addHandlers( onElement );
- }
- };
- if (CAAT.__CSS__) {
- CAAT.Director.prototype.clip= true;
- CAAT.Director.prototype.glEnabled= false;
- CAAT.Director.prototype.getRenderType= function() {
- return 'CSS';
- };
- CAAT.Director.prototype.setScaleProportional= function(w,h) {
- var factor= Math.min(w/this.referenceWidth, h/this.referenceHeight);
- this.setScaleAnchored( factor, factor, 0, 0 );
- this.eventHandler.style.width= ''+this.referenceWidth +'px';
- this.eventHandler.style.height= ''+this.referenceHeight+'px';
- };
- CAAT.Director.prototype.setBounds= function(x, y, w, h) {
- CAAT.Director.superclass.setBounds.call(this, x, y, w, h);
- for (var i = 0; i < this.scenes.length; i++) {
- this.scenes[i].setBounds(0, 0, w, h);
- }
- this.eventHandler.style.width= w+'px';
- this.eventHandler.style.height= h+'px';
- return this;
- };
- /**
- * In this DOM/CSS implementation, proxy is not taken into account since the event router is a top most
- * div in the document hierarchy (z-index 999999).
- * @param width
- * @param height
- * @param domElement
- * @param proxy
- */
- CAAT.Director.prototype.initialize= function(width, height, domElement, proxy) {
- this.timeline = new Date().getTime();
- this.domElement= domElement;
- this.style('position','absolute');
- this.style('width',''+width+'px');
- this.style('height',''+height+'px');
- this.style('overflow', 'hidden' );
- this.enableEvents(domElement);
- this.setBounds(0, 0, width, height);
- this.checkDebug();
- return this;
- };
- CAAT.Director.prototype.render= function(time) {
- this.time += time;
- this.animate(this,time);
- /**
- * draw director active scenes.
- */
- var i, l, tt;
- if ( CAAT.DEBUG ) {
- this.resetStats();
- }
- for (i = 0, l=this.childrenList.length; i < l; i++) {
- var c= this.childrenList[i];
- if (c.isInAnimationFrame(this.time)) {
- tt = c.time - c.start_time;
- if ( c.onRenderStart ) {
- c.onRenderStart(tt);
- }
- c.paintActor(this, tt);
- if ( c.onRenderEnd ) {
- c.onRenderEnd(tt);
- }
- if (!c.isPaused()) {
- c.time += time;
- }
- if ( CAAT.DEBUG ) {
- this.statistics.size_total+= c.size_total;
- this.statistics.size_active+= c.size_active;
- this.statistics.size_dirtyRects= this.nDirtyRects;
- }
- }
- }
- this.frameCounter++;
- };
- CAAT.Director.prototype.addScene= function(scene) {
- scene.setVisible(true);
- scene.setBounds(0, 0, this.width, this.height);
- this.scenes.push(scene);
- scene.setEaseListener(this);
- if (null === this.currentScene) {
- this.setScene(0);
- }
- this.domElement.appendChild( scene.domElement );
- };
- CAAT.Director.prototype.emptyScenes= function() {
- this.scenes = [];
- this.domElement.innerHTML='';
- this.createEventHandler();
- };
- CAAT.Director.prototype.setClear= function(clear) {
- return this;
- };
- CAAT.Director.prototype.createEventHandler= function() {
- this.eventHandler= document.createElement('div');
- this.domElement.appendChild(this.eventHandler);
- this.eventHandler.style.position= 'absolute';
- this.eventHandler.style.left= '0';
- this.eventHandler.style.top= '0';
- this.eventHandler.style.zIndex= 999999;
- this.eventHandler.style.width= ''+this.width+'px';
- this.eventHandler.style.height= ''+this.height+'px';
- var canvas= this.eventHandler;
- this.in_ = false;
- this.addHandlers(canvas);
- };
- }
- extend(CAAT.Director, CAAT.ActorContainer, null);
- })();
- /**
- * See LICENSE file.
- *
- * MouseEvent is a class to hold necessary information of every mouse event related to concrete
- * scene graph Actors.
- *
- * Here it is also the logic to on mouse events, pump the correct event to the appropiate scene
- * graph Actor.
- *
- * TODO: add events for event pumping:
- * + cancelBubling
- *
- **/
- (function() {
- /**
- * This function creates a mouse event that represents a touch or mouse event.
- * @constructor
- */
- CAAT.MouseEvent = function() {
- this.point= new CAAT.Point(0,0,0);
- this.screenPoint= new CAAT.Point(0,0,0);
- return this;
- };
-
- CAAT.MouseEvent.prototype= {
- screenPoint: null,
- point: null,
- time: 0,
- source: null,
- shift: false,
- control: false,
- alt: false,
- meta: false,
- sourceEvent: null,
- init : function( x,y,sourceEvent,source,screenPoint,time ) {
- this.point.set(x,y);
- this.source= source;
- this.screenPoint= screenPoint;
- this.alt = sourceEvent.altKey;
- this.control = sourceEvent.ctrlKey;
- this.shift = sourceEvent.shiftKey;
- this.meta = sourceEvent.metaKey;
- this.sourceEvent= sourceEvent;
- this.x= x;
- this.y= y;
- this.time= time;
- return this;
- },
- isAltDown : function() {
- return this.alt;
- },
- isControlDown : function() {
- return this.control;
- },
- isShiftDown : function() {
- return this.shift;
- },
- isMetaDown: function() {
- return this.meta;
- },
- getSourceEvent : function() {
- return this.sourceEvent;
- }
- };
- })();
- CAAT.setCoordinateClamping= function( clamp ) {
- if ( clamp ) {
- CAAT.Matrix.prototype.transformRenderingContext= CAAT.Matrix.prototype.transformRenderingContext_Clamp;
- CAAT.Matrix.prototype.transformRenderingContextSet= CAAT.Matrix.prototype.transformRenderingContextSet_Clamp;
- } else {
- CAAT.Matrix.prototype.transformRenderingContext= CAAT.Matrix.prototype.transformRenderingContext_NoClamp;
- CAAT.Matrix.prototype.transformRenderingContextSet= CAAT.Matrix.prototype.transformRenderingContextSet_NoClamp;
- }
- };
- CAAT.RENDER_MODE_CONTINUOUS= 1; // redraw every frame
- CAAT.RENDER_MODE_DIRTY= 2; // suitable for evented CAAT.
- CAAT.RENDER_MODE= CAAT.RENDER_MODE_CONTINUOUS;
- /**
- * Box2D point meter conversion ratio.
- */
- CAAT.PMR= 64;
- CAAT.GLRENDER= false;
- /**
- * Allow visual debugging artifacts.
- */
- CAAT.DEBUG= false;
- CAAT.DEBUGBB= false;
- CAAT.DEBUGBBBCOLOR='#00f';
- CAAT.DEBUGAABB= false; // debug bounding boxes.
- CAAT.DEBUGAABBCOLOR='#f00';
- CAAT.DEBUG_DIRTYRECTS=false;
- /**
- * Log function which deals with window's Console object.
- */
- CAAT.log= function() {
- if(window.console){
- window.console.log( Array.prototype.slice.call(arguments) );
- }
- };
- CAAT.FRAME_TIME= 0;
- /**
- * Flag to signal whether events are enabled for CAAT.
- */
- CAAT.GlobalEventsEnabled= false;
- /**
- * Accelerometer related data.
- */
- CAAT.prevOnDeviceMotion= null; // previous accelerometer callback function.
- CAAT.onDeviceMotion= null; // current accelerometer callback set for CAAT.
- CAAT.accelerationIncludingGravity= { x:0, y:0, z:0 }; // acceleration data.
- CAAT.rotationRate= { alpha: 0, beta:0, gamma: 0 }; // angles data.
- /**
- * Do not consider mouse drag gesture at least until you have dragged
- * 5 pixels in any direction.
- */
- CAAT.DRAG_THRESHOLD_X= 5;
- CAAT.DRAG_THRESHOLD_Y= 5;
- // has the animation loop began ?
- CAAT.renderEnabled= false;
- CAAT.FPS= 60;
- /**
- * On resize event listener
- */
- CAAT.windowResizeListeners= [];
- /**
- * Register an object as resize callback.
- * @param f { function( windowResized(width{number},height{number})} ) }
- */
- CAAT.registerResizeListener= function(f) {
- CAAT.windowResizeListeners.push(f);
- };
- /**
- * Unregister a resize listener.
- * @param director {CAAT.Director}
- */
- CAAT.unregisterResizeListener= function(director) {
- for( var i=0; i<CAAT.windowResizeListeners.length; i++ ) {
- if ( director===CAAT.windowResizeListeners[i] ) {
- CAAT.windowResizeListeners.splice(i,1);
- return;
- }
- }
- };
- /**
- * Pressed key codes.
- */
- CAAT.keyListeners= [];
- /**
- * Register key events notification function.
- * @param f {function(key {integer}, action {'down'|'up'})}
- */
- CAAT.registerKeyListener= function(f) {
- CAAT.keyListeners.push(f);
- };
- CAAT.Keys = {
- ENTER:13,
- BACKSPACE:8,
- TAB:9,
- SHIFT:16,
- CTRL:17,
- ALT:18,
- PAUSE:19,
- CAPSLOCK:20,
- ESCAPE:27,
- // SPACE:32,
- PAGEUP:33,
- PAGEDOWN:34,
- END:35,
- HOME:36,
- LEFT:37,
- UP:38,
- RIGHT:39,
- DOWN:40,
- INSERT:45,
- DELETE:46,
- 0:48,
- 1:49,
- 2:50,
- 3:51,
- 4:52,
- 5:53,
- 6:54,
- 7:55,
- 8:56,
- 9:57,
- a:65,
- b:66,
- c:67,
- d:68,
- e:69,
- f:70,
- g:71,
- h:72,
- i:73,
- j:74,
- k:75,
- l:76,
- m:77,
- n:78,
- o:79,
- p:80,
- q:81,
- r:82,
- s:83,
- t:84,
- u:85,
- v:86,
- w:87,
- x:88,
- y:89,
- z:90,
- SELECT:93,
- NUMPAD0:96,
- NUMPAD1:97,
- NUMPAD2:98,
- NUMPAD3:99,
- NUMPAD4:100,
- NUMPAD5:101,
- NUMPAD6:102,
- NUMPAD7:103,
- NUMPAD8:104,
- NUMPAD9:105,
- MULTIPLY:106,
- ADD:107,
- SUBTRACT:109,
- DECIMALPOINT:110,
- DIVIDE:111,
- F1:112,
- F2:113,
- F3:114,
- F4:115,
- F5:116,
- F6:117,
- F7:118,
- F8:119,
- F9:120,
- F10:121,
- F11:122,
- F12:123,
- NUMLOCK:144,
- SCROLLLOCK:145,
- SEMICOLON:186,
- EQUALSIGN:187,
- COMMA:188,
- DASH:189,
- PERIOD:190,
- FORWARDSLASH:191,
- GRAVEACCENT:192,
- OPENBRACKET:219,
- BACKSLASH:220,
- CLOSEBRAKET:221,
- SINGLEQUOTE:222
- };
- CAAT.SHIFT_KEY= 16;
- CAAT.CONTROL_KEY= 17;
- CAAT.ALT_KEY= 18;
- CAAT.ENTER_KEY= 13;
- /**
- * Event modifiers.
- */
- CAAT.KEY_MODIFIERS= {
- alt: false,
- control: false,
- shift: false
- };
- /**
- * Define a key event.
- * @constructor
- * @param keyCode
- * @param up_or_down
- * @param modifiers
- * @param originalEvent
- */
- CAAT.KeyEvent= function( keyCode, up_or_down, modifiers, originalEvent ) {
- this.keyCode= keyCode;
- this.action= up_or_down;
- this.modifiers= modifiers;
- this.sourceEvent= originalEvent;
- this.preventDefault= function() {
- this.sourceEvent.preventDefault();
- }
- this.getKeyCode= function() {
- return this.keyCode;
- };
- this.getAction= function() {
- return this.action;
- };
- this.modifiers= function() {
- return this.modifiers;
- };
- this.isShiftPressed= function() {
- return this.modifiers.shift;
- };
- this.isControlPressed= function() {
- return this.modifiers.control;
- };
- this.isAltPressed= function() {
- return this.modifiers.alt;
- };
- this.getSourceEvent= function() {
- return this.sourceEvent;
- };
- };
- /**
- * Enable window level input events, keys and redimension.
- */
- CAAT.GlobalEnableEvents= function __GlobalEnableEvents() {
- if ( CAAT.GlobalEventsEnabled ) {
- return;
- }
- this.GlobalEventsEnabled= true;
- window.addEventListener('keydown',
- function(evt) {
- var key = (evt.which) ? evt.which : evt.keyCode;
- if ( key===CAAT.SHIFT_KEY ) {
- CAAT.KEY_MODIFIERS.shift= true;
- } else if ( key===CAAT.CONTROL_KEY ) {
- CAAT.KEY_MODIFIERS.control= true;
- } else if ( key===CAAT.ALT_KEY ) {
- CAAT.KEY_MODIFIERS.alt= true;
- } else {
- for( var i=0; i<CAAT.keyListeners.length; i++ ) {
- CAAT.keyListeners[i]( new CAAT.KeyEvent(
- key,
- 'down',
- {
- alt: CAAT.KEY_MODIFIERS.alt,
- control: CAAT.KEY_MODIFIERS.control,
- shift: CAAT.KEY_MODIFIERS.shift
- },
- evt)) ;
- }
- }
- },
- false);
- window.addEventListener('keyup',
- function(evt) {
- var key = (evt.which) ? evt.which : evt.keyCode;
- if ( key===CAAT.SHIFT_KEY ) {
- CAAT.KEY_MODIFIERS.shift= false;
- } else if ( key===CAAT.CONTROL_KEY ) {
- CAAT.KEY_MODIFIERS.control= false;
- } else if ( key===CAAT.ALT_KEY ) {
- CAAT.KEY_MODIFIERS.alt= false;
- } else {
- for( var i=0; i<CAAT.keyListeners.length; i++ ) {
- CAAT.keyListeners[i]( new CAAT.KeyEvent(
- key,
- 'up',
- {
- alt: CAAT.KEY_MODIFIERS.alt,
- control: CAAT.KEY_MODIFIERS.control,
- shift: CAAT.KEY_MODIFIERS.shift
- },
- evt));
- }
- }
- },
- false );
- window.addEventListener('resize',
- function(evt) {
- for( var i=0; i<CAAT.windowResizeListeners.length; i++ ) {
- CAAT.windowResizeListeners[i].windowResized(
- window.innerWidth,
- window.innerHeight);
- }
- },
- false);
- };
- /**
- * Polyfill for requestAnimationFrame.
- */
- window.requestAnimFrame = (function(){
- return window.requestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- window.oRequestAnimationFrame ||
- window.msRequestAnimationFrame ||
- function raf(/* function */ callback, /* DOMElement */ element){
- window.setTimeout(callback, 1000 / CAAT.FPS);
- };
- })();
- CAAT.SET_INTERVAL=0;
- /**
- * Main animation loop entry point.
- * @param fps {number} desired fps. This parameter makes no sense unless requestAnimationFrame function
- * is not present in the system.
- */
- CAAT.loop= function(fps) {
- if (CAAT.renderEnabled) {
- return;
- }
- CAAT.FPS= fps || 60;
- CAAT.renderEnabled= true;
- if (CAAT.NO_RAF) {
- setInterval(
- function() {
- var t= new Date().getTime();
- for (var i = 0, l = CAAT.director.length; i < l; i++) {
- CAAT.director[i].renderFrame();
- }
- //t= new Date().getTime()-t;
- CAAT.FRAME_TIME= t - CAAT.SET_INTERVAL;
-
- CAAT.SET_INTERVAL= t;
- },
- 1000 / CAAT.FPS
- );
- } else {
- CAAT.renderFrame();
- }
- }
- CAAT.FPS_REFRESH= 500; // debug panel update time.
- CAAT.RAF= 0; // requestAnimationFrame time reference.
- CAAT.REQUEST_ANIMATION_FRAME_TIME= 0;
- /**
- * Make a frame for each director instance present in the system.
- */
- CAAT.renderFrame= function() {
- var t= new Date().getTime();
- for( var i=0, l=CAAT.director.length; i<l; i++ ) {
- CAAT.director[i].renderFrame();
- }
- t= new Date().getTime()-t;
- CAAT.FRAME_TIME= t;
- if (CAAT.RAF) {
- CAAT.REQUEST_ANIMATION_FRAME_TIME= new Date().getTime()-CAAT.RAF;
- }
- CAAT.RAF= new Date().getTime();
- window.requestAnimFrame(CAAT.renderFrame, 0 );
- }
- /**
- * Set browser cursor. The preferred method for cursor change is this method.
- * @param cursor
- */
- CAAT.setCursor= function(cursor) {
- if ( navigator.browser!=='iOS' ) {
- document.body.style.cursor= cursor;
- }
- };
- /**
- * Register and keep track of every CAAT.Director instance in the document.
- */
- CAAT.RegisterDirector= function __CAATGlobal_RegisterDirector(director) {
- if ( !CAAT.director ) {
- CAAT.director=[];
- }
- CAAT.director.push(director);
- CAAT.GlobalEnableEvents();
- };
- /**
- * Enable at window level accelerometer events.
- */
- (function() {
- function tilt(data) {
- CAAT.rotationRate= {
- alpha : 0,
- beta : data[0],
- gamma : data[1]
- };
- }
- if (window.DeviceOrientationEvent) {
- window.addEventListener("deviceorientation", function (event) {
- tilt([event.beta, event.gamma]);
- }, true);
- } else if (window.DeviceMotionEvent) {
- window.addEventListener('devicemotion', function (event) {
- tilt([event.acceleration.x * 2, event.acceleration.y * 2]);
- }, true);
- } else {
- window.addEventListener("MozOrientation", function (event) {
- tilt([-event.y * 45, event.x * 45]);
- }, true);
- }
- })();/**
- * See LICENSE file.
- *
- * TODO: allow set of margins, spacing, etc. to define subimages.
- *
- **/
- (function() {
- CAAT.SpriteImageHelper= function(x,y,w,h, iw, ih) {
- this.x= x;
- this.y= y;
- this.width= w;
- this.height= h;
- this.setGL( x/iw, y/ih, (x+w-1)/iw, (y+h-1)/ih );
- return this;
- };
- CAAT.SpriteImageHelper.prototype= {
- x : 0,
- y : 0,
- width : 0,
- height : 0,
- u : 0,
- v : 0,
- u1 : 0,
- v1 : 0,
- setGL : function( u,v,u1,v1 ) {
- this.u= u;
- this.v= v;
- this.u1= u1;
- this.v1= v1;
- return this;
- }
- };
- })();
- (function() {
- /**
- *
- * This class is used by CAAT.Actor to draw images. It differs from CAAT.CompoundImage in that it
- * manages the subimage change based on time and a list of animation sub-image indexes.
- * A common use of this class will be:
- *
- * <code>
- * var si= new CAAT.SpriteImage().
- * initialize( an_image_instance, rows, columns ).
- * setAnimationImageIndex( [2,1,0,1] ). // cycle throwout image with these indexes
- * setChangeFPS( 200 ). // change sprite every 200 ms.
- * setSpriteTransformation( CAAT.SpriteImage.TR_xx); // optionally draw images inverted, ...
- * </code>
- *
- * A SpriteImage is an sprite sheet. It encapsulates an Image and treates and references it as a two
- * dimensional array of row by columns sub-images. The access form will be sequential so if defined a
- * CompoundImage of more than one row, the subimages will be referenced by an index ranging from 0 to
- * rows*columns-1. Each sumimage will be of size (image.width/columns) by (image.height/rows).
- *
- * <p>
- * It is able to draw its sub-images in the following ways:
- * <ul>
- * <li>no transformed (default)
- * <li>flipped horizontally
- * <li>flipped vertically
- * <li>flipped both vertical and horizontally
- * </ul>
- *
- * <p>
- * It is supposed to be used in conjunction with <code>CAAT.SpriteActor</code> instances.
- *
- * @constructor
- *
- */
- CAAT.SpriteImage = function() {
- this.paint= this.paintN;
- this.setAnimationImageIndex([0]);
- this.mapInfo= {};
- return this;
- };
- CAAT.SpriteImage.prototype = {
- animationImageIndex: null, // an Array defining the sprite frame sequence
- prevAnimationTime: -1,
- changeFPS: 1000, // how much Scene time to take before changing an Sprite frame.
- transformation: 0, // any of the TR_* constants.
- spriteIndex: 0, // the current sprite frame
- TR_NONE: 0, // constants used to determine how to draw the sprite image,
- TR_FLIP_HORIZONTAL: 1,
- TR_FLIP_VERTICAL: 2,
- TR_FLIP_ALL: 3,
- TR_FIXED_TO_SIZE: 4,
- TR_TILE: 5,
- image: null,
- rows: 1,
- columns: 1,
- width: 0,
- height: 0,
- singleWidth: 0,
- singleHeight: 0,
- scaleX: 1,
- scaleY: 1,
- offsetX: 0,
- offsetY: 0,
- ownerActor: null,
- mapInfo : null,
- map : null,
- setOwner : function(actor) {
- this.ownerActor= actor;
- return this;
- },
- getRows: function() {
- return this.rows;
- },
- getColumns : function() {
- return this.columns;
- },
- getWidth : function() {
- var el= this.mapInfo[this.spriteIndex];
- return el.width;
- },
- getHeight : function() {
- var el= this.mapInfo[this.spriteIndex];
- return el.height;
- },
- /**
- * Get a reference to the same image information (rows, columns, image and uv cache) of this
- * SpriteImage. This means that re-initializing this objects image info (that is, calling initialize
- * method) will change all reference's image information at the same time.
- */
- getRef : function() {
- var ret= new CAAT.SpriteImage();
- ret.image= this.image;
- ret.rows= this.rows;
- ret.columns= this.columns;
- ret.width= this.width;
- ret.height= this.height;
- ret.singleWidth= this.singleWidth;
- ret.singleHeight= this.singleHeight;
- ret.mapInfo= this.mapInfo;
- ret.offsetX= this.offsetX;
- ret.offsetY= this.offsetY;
- ret.scaleX= this.scaleX;
- ret.scaleY= this.scaleY;
- return ret;
- },
- /**
- * Set horizontal displacement to draw image. Positive values means drawing the image more to the
- * right.
- * @param x {number}
- * @return this
- */
- setOffsetX : function(x) {
- this.offsetX= x;
- return this;
- },
- /**
- * Set vertical displacement to draw image. Positive values means drawing the image more to the
- * bottom.
- * @param y {number}
- * @return this
- */
- setOffsetY : function(y) {
- this.offsetY= y;
- return this;
- },
- setOffset : function( x,y ) {
- this.offsetX= x;
- this.offsetY= y;
- return this;
- },
- /**
- * Initialize a grid of subimages out of a given image.
- * @param image {HTMLImageElement|Image} an image object.
- * @param rows {number} number of rows.
- * @param columns {number} number of columns
- *
- * @return this
- */
- initialize : function(image, rows, columns) {
- this.image = image;
- this.rows = rows;
- this.columns = columns;
- this.width = image.width;
- this.height = image.height;
- this.singleWidth = Math.floor(this.width / columns);
- this.singleHeight = Math.floor(this.height / rows);
- this.mapInfo= {};
- var i,sx0,sy0;
- var helper;
- if (image.__texturePage) {
- image.__du = this.singleWidth / image.__texturePage.width;
- image.__dv = this.singleHeight / image.__texturePage.height;
- var w = this.singleWidth;
- var h = this.singleHeight;
- var mod = this.columns;
- if (image.inverted) {
- var t = w;
- w = h;
- h = t;
- mod = this.rows;
- }
- var xt = this.image.__tx;
- var yt = this.image.__ty;
- var tp = this.image.__texturePage;
- for (i = 0; i < rows * columns; i++) {
- var c = ((i % mod) >> 0);
- var r = ((i / mod) >> 0);
- var u = xt + c * w; // esquina izq x
- var v = yt + r * h;
- var u1 = u + w;
- var v1 = v + h;
- helper= new CAAT.SpriteImageHelper(u,v,(u1-u),(v1-v),tp.width,tp.height).setGL(
- u / tp.width,
- v / tp.height,
- u1 / tp.width,
- v1 / tp.height );
- this.mapInfo[i]= helper;
- }
- } else {
- for (i = 0; i < rows * columns; i++) {
- sx0 = ((i % this.columns) | 0) * this.singleWidth;
- sy0 = ((i / this.columns) | 0) * this.singleHeight;
- helper= new CAAT.SpriteImageHelper( sx0, sy0, this.singleWidth, this.singleHeight, image.width, image.height );
- this.mapInfo[i]= helper;
- }
- }
- return this;
- },
- /**
- * Must be used to draw actor background and the actor should have setClip(true) so that the image tiles
- * properly.
- * @param director
- * @param time
- * @param x
- * @param y
- */
- paintTiled : function( director, time, x, y ) {
- this.setSpriteIndexAtTime(time);
- var el= this.mapInfo[this.spriteIndex];
- var r= new CAAT.Rectangle();
- this.ownerActor.AABB.intersect( director.AABB, r );
- var w= this.getWidth();
- var h= this.getHeight();
- var xoff= (this.offsetX-this.ownerActor.x) % w;
- if ( xoff> 0 ) {
- xoff= xoff-w;
- }
- var yoff= (this.offsetY-this.ownerActor.y) % h;
- if ( yoff> 0 ) {
- yoff= yoff-h;
- }
- var nw= (((r.width-xoff)/w)>>0)+1;
- var nh= (((r.height-yoff)/h)>>0)+1;
- var i,j;
- var ctx= director.ctx;
- for( i=0; i<nh; i++ ) {
- for( j=0; j<nw; j++ ) {
- ctx.drawImage(
- this.image,
- el.x, el.y,
- el.width, el.height,
- (r.x-this.ownerActor.x+xoff+j*el.width)>>0, (r.y-this.ownerActor.y+yoff+i*el.height)>>0,
- el.width, el.height);
- }
- }
- },
- /**
- * Draws the subimage pointed by imageIndex horizontally inverted.
- * @param canvas a canvas context.
- * @param imageIndex {number} a subimage index.
- * @param x {number} x position in canvas to draw the image.
- * @param y {number} y position in canvas to draw the image.
- *
- * @return this
- */
- paintInvertedH : function(director, time, x, y) {
- this.setSpriteIndexAtTime(time);
- var el= this.mapInfo[this.spriteIndex];
- var ctx= director.ctx;
- ctx.save();
- //ctx.translate(((0.5 + x) | 0) + el.width, (0.5 + y) | 0);
- ctx.translate( (x|0) + el.width, y|0 );
- ctx.scale(-1, 1);
- ctx.drawImage(
- this.image,
- el.x, el.y,
- el.width, el.height,
- this.offsetX>>0, this.offsetY>>0,
- el.width, el.height );
- ctx.restore();
- return this;
- },
- /**
- * Draws the subimage pointed by imageIndex vertically inverted.
- * @param canvas a canvas context.
- * @param imageIndex {number} a subimage index.
- * @param x {number} x position in canvas to draw the image.
- * @param y {number} y position in canvas to draw the image.
- *
- * @return this
- */
- paintInvertedV : function(director, time, x, y) {
- this.setSpriteIndexAtTime(time);
- var el= this.mapInfo[this.spriteIndex];
- var ctx= director.ctx;
- ctx.save();
- //ctx.translate((x + 0.5) | 0, (0.5 + y + el.height) | 0);
- ctx.translate( x|0, (y + el.height) | 0);
- ctx.scale(1, -1);
- ctx.drawImage(
- this.image,
- el.x, el.y,
- el.width, el.height,
- this.offsetX>>0,this.offsetY>>0,
- el.width, el.height);
- ctx.restore();
- return this;
- },
- /**
- * Draws the subimage pointed by imageIndex both horizontal and vertically inverted.
- * @param canvas a canvas context.
- * @param imageIndex {number} a subimage index.
- * @param x {number} x position in canvas to draw the image.
- * @param y {number} y position in canvas to draw the image.
- *
- * @return this
- */
- paintInvertedHV : function(director, time, x, y) {
- this.setSpriteIndexAtTime(time);
- var el= this.mapInfo[this.spriteIndex];
- var ctx= director.ctx;
- ctx.save();
- //ctx.translate((x + 0.5) | 0, (0.5 + y + el.height) | 0);
- ctx.translate( x | 0, (y + el.height) | 0);
- ctx.scale(1, -1);
- ctx.translate(el.width, 0);
- ctx.scale(-1, 1);
- ctx.drawImage(
- this.image,
- el.x, el.y,
- el.width, el.height,
- this.offsetX>>0, this.offsetY>>0,
- el.width, el.height);
- ctx.restore();
- return this;
- },
- /**
- * Draws the subimage pointed by imageIndex.
- * @param canvas a canvas context.
- * @param imageIndex {number} a subimage index.
- * @param x {number} x position in canvas to draw the image.
- * @param y {number} y position in canvas to draw the image.
- *
- * @return this
- */
- paintN : function(director, time, x, y) {
- this.setSpriteIndexAtTime(time);
- var el= this.mapInfo[this.spriteIndex];
- director.ctx.drawImage(
- this.image,
- el.x, el.y,
- el.width, el.height,
- (this.offsetX+x)>>0, (this.offsetY+y)>>0,
- el.width, el.height);
- return this;
- },
- paintChunk : function( ctx, dx,dy, x, y, w, h ) {
- ctx.drawImage( this.image, x,y,w,h, dx,dy,w,h );
- },
- paintTile : function(ctx, index, x, y) {
- var el= this.mapInfo[index];
- ctx.drawImage(
- this.image,
- el.x, el.y,
- el.width, el.height,
- (this.offsetX+x)>>0, (this.offsetY+y)>>0,
- el.width, el.height);
- return this;
- },
- /**
- * Draws the subimage pointed by imageIndex scaled to the size of w and h.
- * @param canvas a canvas context.
- * @param imageIndex {number} a subimage index.
- * @param x {number} x position in canvas to draw the image.
- * @param y {number} y position in canvas to draw the image.
- * @param w {number} new width of the subimage.
- * @param h {number} new height of the subimage.
- *
- * @return this
- */
- paintScaled : function(director, time, x, y) {
- this.setSpriteIndexAtTime(time);
- var el= this.mapInfo[this.spriteIndex];
- director.ctx.drawImage(
- this.image,
- el.x, el.y,
- el.width, el.height,
- (this.offsetX+x)>>0, (this.offsetY+y)>>0,
- this.ownerActor.width, this.ownerActor.height );
- return this;
- },
- getCurrentSpriteImageCSSPosition : function() {
- var el= this.mapInfo[this.spriteIndex];
- var x= -(el.x-this.offsetX);
- var y= -(el.y-this.offsetY);
- return ''+x+'px '+
- y+'px '+
- (this.ownerActor.transformation===this.TR_TILE ? 'repeat' : 'no-repeat');
- },
- /**
- * Get the number of subimages in this compoundImage
- * @return {number}
- */
- getNumImages : function() {
- return this.rows * this.columns;
- },
- /**
- * TODO: set mapping coordinates for different transformations.
- * @param imageIndex
- * @param uvBuffer
- * @param uvIndex
- */
- setUV : function(uvBuffer, uvIndex) {
- var im = this.image;
- if (!im.__texturePage) {
- return;
- }
- var index = uvIndex;
- var sIndex= this.spriteIndex;
- var el= this.mapInfo[this.spriteIndex];
- var u= el.u;
- var v= el.v;
- var u1= el.u1;
- var v1= el.v1;
- if ( this.offsetX || this.offsetY ) {
- var w= this.ownerActor.width;
- var h= this.ownerActor.height;
- var tp= im.__texturePage;
- var _u= -this.offsetX / tp.width;
- var _v= -this.offsetY / tp.height;
- var _u1=(w-this.offsetX) / tp.width;
- var _v1=(h-this.offsetY) / tp.height;
- u= _u + im.__u;
- v= _v + im.__v;
- u1= _u1 + im.__u;
- v1= _v1 + im.__v;
- }
- if (im.inverted) {
- uvBuffer[index++] = u1;
- uvBuffer[index++] = v;
- uvBuffer[index++] = u1;
- uvBuffer[index++] = v1;
- uvBuffer[index++] = u;
- uvBuffer[index++] = v1;
- uvBuffer[index++] = u;
- uvBuffer[index++] = v;
- } else {
- uvBuffer[index++] = u;
- uvBuffer[index++] = v;
- uvBuffer[index++] = u1;
- uvBuffer[index++] = v;
- uvBuffer[index++] = u1;
- uvBuffer[index++] = v1;
- uvBuffer[index++] = u;
- uvBuffer[index++] = v1;
- }
- },
- /**
- * Set the elapsed time needed to change the image index.
- * @param fps an integer indicating the time in milliseconds to change.
- * @return this
- */
- setChangeFPS : function(fps) {
- this.changeFPS= fps;
- return this;
- },
- /**
- * Set the transformation to apply to the Sprite image.
- * Any value of
- * <li>TR_NONE
- * <li>TR_FLIP_HORIZONTAL
- * <li>TR_FLIP_VERTICAL
- * <li>TR_FLIP_ALL
- *
- * @param transformation an integer indicating one of the previous values.
- * @return this
- */
- setSpriteTransformation : function( transformation ) {
- this.transformation= transformation;
- switch(transformation) {
- case this.TR_FLIP_HORIZONTAL:
- this.paint= this.paintInvertedH;
- break;
- case this.TR_FLIP_VERTICAL:
- this.paint= this.paintInvertedV;
- break;
- case this.TR_FLIP_ALL:
- this.paint= this.paintInvertedHV;
- break;
- case this.TR_FIXED_TO_SIZE:
- this.paint= this.paintScaled;
- break;
- case this.TR_TILE:
- this.paint= this.paintTiled;
- break;
- default:
- this.paint= this.paintN;
- }
- return this;
- },
- resetAnimationTime : function() {
- this.prevAnimationTime= -1;
- return this;
- },
- /**
- * Set the sprite animation images index. This method accepts an array of objects which define indexes to
- * subimages inside this sprite image.
- * If the SpriteImage is instantiated by calling the method initialize( image, rows, cols ), the value of
- * aAnimationImageIndex should be an array of numbers, which define the indexes into an array of subimages
- * with size rows*columns.
- * If the method InitializeFromMap( image, map ) is called, the value for aAnimationImageIndex is expected
- * to be an array of strings which are the names of the subobjects contained in the map object.
- *
- * @param aAnimationImageIndex an array indicating the Sprite's frames.
- */
- setAnimationImageIndex : function( aAnimationImageIndex ) {
- this.animationImageIndex= aAnimationImageIndex;
- this.spriteIndex= aAnimationImageIndex[0];
- this.prevAnimationTime= -1;
- return this;
- },
- setSpriteIndex : function(index) {
- this.spriteIndex= index;
- return this;
- },
- /**
- * Draws the sprite image calculated and stored in spriteIndex.
- *
- * @param director the CAAT.Director object instance that contains the Scene the Actor is in.
- * @param time an integer indicating the Scene time when the bounding box is to be drawn.
- */
- setSpriteIndexAtTime : function(time) {
- if ( this.animationImageIndex.length>1 ) {
- if ( this.prevAnimationTime===-1 ) {
- this.prevAnimationTime= time;
- this.spriteIndex=0;
- }
- else {
- var ttime= time;
- ttime-= this.prevAnimationTime;
- ttime/= this.changeFPS;
- ttime%= this.animationImageIndex.length;
- this.spriteIndex= this.animationImageIndex[Math.floor(ttime)];
- }
- }
- },
- getMapInfo : function( index ) {
- return this.mapInfo[ index ];
- },
- /**
- * This method takes the output generated from the tool at http://labs.hyperandroid.com/static/texture/spriter.html
- * and creates a map into that image.
- * @param image {Image|HTMLImageElement|Canvas} an image
- * @param map {object} the map into the image to define subimages.
- */
- initializeFromMap : function( image, map ) {
- this.initialize( image, 1, 1 );
- var key;
- var helper;
- var count=0;
- for( key in map ) {
- var value= map[key];
- helper= new CAAT.SpriteImageHelper(
- value.x,
- value.y,
- value.width,
- value.height,
- image.width,
- image.height
- );
- this.mapInfo[key]= helper;
- // set a default spriteIndex
- if ( !count ) {
- this.setAnimationImageIndex( [key] );
- }
- count++;
- }
- return this;
- },
- /**
- *
- * @param image {Image|HTMLImageElement|Canvas}
- * @param map object with pairs "<a char>" : {
- * id : {number},
- * height : {number},
- * xoffset : {number},
- * letter : {string},
- * yoffset : {number},
- * width : {number},
- * xadvance: {number},
- * y : {number},
- * x : {number}
- * }
- */
- initializeAsGlyphDesigner : function( image, map ) {
- this.initialize( image, 1, 1 );
- var key;
- var helper;
- var count=0;
- for( key in map ) {
- var value= map[key];
- helper= new CAAT.SpriteImageHelper(
- value.x,
- value.y,
- value.width,
- value.height,
- image.width,
- image.height
- );
- helper.xoffset= typeof value.xoffset==='undefined' ? 0 : value.xoffset;
- helper.yoffset= typeof value.yoffset==='undefined' ? 0 : value.yoffset;
- helper.xadvance= typeof value.xadvance==='undefined' ? value.width : value.xadvance;
- this.mapInfo[key]= helper;
- // set a default spriteIndex
- if ( !count ) {
- this.setAnimationImageIndex( [key] );
- }
- count++;
- }
- return this;
- },
- /**
- *
- * @param image
- * @param map: Array<{c: "a", width: 40}>
- */
- initializeAsFontMap : function( image, chars ) {
- this.initialize( image, 1, 1 );
- var helper;
- var x=0;
- for( var i=0;i<chars.length;i++ ) {
- var value= chars[i];
- helper= new CAAT.SpriteImageHelper(
- x,
- 0,
- value.width,
- image.height,
- image.width,
- image.height
- );
- helper.xoffset= 0;
- helper.yoffset= 0;
- helper.xadvance= value.width;
- x += value.width;
- this.mapInfo[chars[i].c]= helper;
- // set a default spriteIndex
- if ( !i ) {
- this.setAnimationImageIndex( [chars[i].c] );
- }
- }
- return this;
- },
- /**
- * This method creates a font sprite image based on a proportional font
- * It assumes the font is evenly spaced in the image
- * Example:
- * var font = new CAAT.SpriteImage().initializeAsMonoTypeFontMap(
- * director.getImage('numbers'),
- * "0123456789"
- * );
- */
- initializeAsMonoTypeFontMap : function( image, chars ) {
- var map = [];
- var charArr = chars.split("");
-
- var w = image.width / charArr.length >> 0;
- for( var i=0;i<charArr.length;i++ ) {
- map.push({c: charArr[i], width: w });
- }
- return this.initializeAsFontMap(image,map);
- },
- stringWidth : function( str ) {
- var i,l,w=0,charInfo;
- for( i=0, l=str.length; i<l; i++ ) {
- charInfo= this.mapInfo[ str.charAt(i) ];
- if ( charInfo ) {
- w+= charInfo.xadvance;
- }
- }
- return w;
- },
- stringHeight : function() {
- if ( this.fontHeight ) {
- return this.fontHeight;
- }
- var y= 0;
- for( var i in this.mapInfo ) {
- var mi= this.mapInfo[i];
- var h= mi.height+mi.yoffset;
- if ( h>y ) {
- y=h;
- }
- }
- this.fontHeight= y;
- return this.fontHeight;
- },
- drawString : function( ctx, str, x, y ) {
- var i, l, charInfo, w;
- var charArr = str.split("");
-
- for( i=0; i<charArr.length; i++ ) {
- charInfo= this.mapInfo[ charArr[i] ];
- if ( charInfo ) {
- w= charInfo.width;
- ctx.drawImage(
- this.image,
- charInfo.x, charInfo.y,
- w, charInfo.height,
- x + charInfo.xoffset, y + charInfo.yoffset,
- w, charInfo.height );
- x+= charInfo.xadvance;
- }
- }
- }
-
- };
- })();
- /**
- * See LICENSE file.
- *
- * Image/Resource preloader.
- *
- *
- **/
- (function() {
- /**
- * This class is a image resource loader. It accepts an object of the form:
- *
- * {
- * id1: string_url1,
- * id2: string_url2,
- * id3: string_url3,
- * ...
- * }
- *
- * and on resources loaded correctly, will return an object of the form:
- *
- * {
- * id1: HTMLImageElement,
- * id2: HTMLImageElement,
- * id3: HTMLImageElement,
- * ...
- * }
- *
- * @constructor
- */
- CAAT.ImagePreloader = function() {
- this.images = [];
- return this;
- };
- CAAT.ImagePreloader.prototype = {
- images: null, // a list of elements to load
- notificationCallback: null, // notification callback invoked for each image loaded.
- imageCounter: 0, // elements counter.
- /**
- * Start images loading asynchronous process. This method will notify every image loaded event
- * and is responsibility of the caller to count the number of loaded images to see if it fits his
- * needs.
- *
- * @param aImages {{ id:{url}, id2:{url}, ...} an object with id/url pairs.
- * @param callback_loaded_one_image {function( imageloader {CAAT.ImagePreloader}, counter {number}, images {{ id:{string}, image: {Image}}} )}
- * function to call on every image load.
- */
- loadImages: function( aImages, callback_loaded_one_image, callback_error ) {
- if (!aImages) {
- if (callback_loaded_one_image ) {
- callback_loaded_one_image(0,[]);
- }
- }
- var me= this, i;
- this.notificationCallback = callback_loaded_one_image;
- this.images= [];
- for( i=0; i<aImages.length; i++ ) {
- this.images.push( {id:aImages[i].id, image: new Image() } );
- }
- for( i=0; i<aImages.length; i++ ) {
- this.images[i].image.onload = function imageLoaded() {
- me.imageCounter++;
- me.notificationCallback(me.imageCounter, me.images);
- };
- this.images[i].image.onerror= (function(index) {
- return function(e) {
- if ( callback_error ) {
- callback_error( e, index );
- }
- }
- })(i);
- this.images[i].image.src= aImages[i].url;
- }
- if ( aImages.length===0 ) {
- callback_loaded_one_image(0,[]);
- }
- }
- };
- })();/**
- * See LICENSE file.
- */
- (function() {
- /**
- * This class defines a timer action which is constrained to Scene time, so every Scene has the
- * abbility to create its own TimerTask objects. They must not be created by calling scene's
- * createTime method.
- *
- * <p>
- * A TimerTask is defined at least by:
- * <ul>
- * <li>startTime: since when the timer will be active
- * <li>duration: from startTime to startTime+duration, the timerTask will be notifying (if set) the callback callback_tick.
- * </ul>
- * <p>
- * Upon TimerTask expiration, the TimerTask will notify (if set) the callback function callback_timeout.
- * Upon a call to the method cancel, the timer will be set expired, and (if set) the callback to callback_cancel will be
- * invoked.
- * <p>
- * Timer notifications will be performed <strong>BEFORE<strong> scene loop.
- *
- * @constructor
- *
- */
- CAAT.TimerTask= function() {
- return this;
- };
- CAAT.TimerTask.prototype= {
- startTime: 0,
- duration: 0,
- callback_timeout: null,
- callback_tick: null,
- callback_cancel: null,
- scene: null,
- taskId: 0,
- remove: false,
- /**
- * Create a TimerTask.
- * The taskId will be set by the scene.
- * @param startTime {number} an integer indicating TimerTask enable time.
- * @param duration {number} an integer indicating TimerTask duration.
- * @param callback_timeout {function( sceneTime {number}, timertaskTime{number}, timertask {CAAT.TimerTask} )} on timeout callback function.
- * @param callback_tick {function( sceneTime {number}, timertaskTime{number}, timertask {CAAT.TimerTask} )} on tick callback function.
- * @param callback_cancel {function( sceneTime {number}, timertaskTime{number}, timertask {CAAT.TimerTask} )} on cancel callback function.
- *
- * @return this
- */
- create: function( startTime, duration, callback_timeout, callback_tick, callback_cancel ) {
- this.startTime= startTime;
- this.duration= duration;
- this.callback_timeout= callback_timeout;
- this.callback_tick= callback_tick;
- this.callback_cancel= callback_cancel;
- return this;
- },
- /**
- * Performs TimerTask operation. The task will check whether it is in frame time, and will
- * either notify callback_timeout or callback_tick.
- *
- * @param time {number} an integer indicating scene time.
- * @return this
- *
- * @protected
- *
- */
- checkTask : function(time) {
- var ttime= time;
- ttime-= this.startTime;
- if ( ttime>=this.duration ) {
- this.remove= true;
- if( this.callback_timeout ) {
- this.callback_timeout( time, ttime, this );
- }
- } else {
- if ( this.callback_tick ) {
- this.callback_tick( time, ttime, this );
- }
- }
- return this;
- },
- /**
- * Reschedules this TimerTask by changing its startTime to current scene's time.
- * @param time {number} an integer indicating scene time.
- * @return this
- */
- reset : function( time ) {
- this.remove= false;
- this.startTime= time;
- this.scene.ensureTimerTask(this);
- return this;
- },
- /**
- * Cancels this timer by removing it on scene's next frame. The function callback_cancel will
- * be called.
- * @return this
- */
- cancel : function() {
- this.remove= true;
- if ( null!=this.callback_cancel ) {
- this.callback_cancel( this.scene.time, this.scene.time-this.startTime, this );
- }
- return this;
- }
- };
- })();
- /**
- * See LICENSE file.
- *
- */
- (function() {
- /**
- * Scene is the top level ActorContainer of the Director at any given time.
- * The only time when 2 scenes could be active will be during scene change.
- * An scene controls the way it enters/exits the scene graph. It is also the entry point for all
- * input related and timed related events to every actor on screen.
- *
- * @constructor
- * @extends CAAT.ActorContainer
- *
- */
- CAAT.Scene= function() {
- CAAT.Scene.superclass.constructor.call(this);
- this.timerList= [];
- this.fillStyle= null;
- return this;
- };
-
- CAAT.Scene.prototype= {
-
- easeContainerBehaviour: null, // Behavior container used uniquely for Scene switching.
- easeContainerBehaviourListener: null, // who to notify about container behaviour events. Array.
- easeIn: false, // When Scene switching, this boolean identifies whether the
- // Scene is being brought in, or taken away.
- EASE_ROTATION: 1, // Constant values to identify the type of Scene transition
- EASE_SCALE: 2, // to perform on Scene switching by the Director.
- EASE_TRANSLATE: 3,
- timerList: null, // collection of CAAT.TimerTask objects.
- timerSequence: 0, // incremental CAAT.TimerTask id.
- paused: false,
- isPaused : function() {
- return this.paused;
- },
- setPaused : function( paused ) {
- this.paused= paused;
- },
- /**
- * Check and apply timers in frame time.
- * @param time {number} the current Scene time.
- */
- checkTimers : function(time) {
- var tl= this.timerList;
- var i=tl.length-1;
- while( i>=0 ) {
- if ( !tl[i].remove ) {
- tl[i].checkTask(time);
- }
- i--;
- }
- },
- /**
- * Make sure the timertask is contained in the timer task list by adding it to the list in case it
- * is not contained.
- * @param timertask {CAAT.TimerTask} a CAAT.TimerTask object.
- * @return this
- */
- ensureTimerTask : function( timertask ) {
- if ( !this.hasTimer(timertask) ) {
- this.timerList.push(timertask);
- }
- return this;
- },
- /**
- * Check whether the timertask is in this scene's timer task list.
- * @param timertask {CAAT.TimerTask} a CAAT.TimerTask object.
- * @return {boolean} a boolean indicating whether the timertask is in this scene or not.
- */
- hasTimer : function( timertask ) {
- var tl= this.timerList;
- var i=tl.length-1;
- while( i>=0 ) {
- if ( tl[i]===timertask ) {
- return true;
- }
- i--;
- }
- return false;
- },
- /**
- * Creates a timer task. Timertask object live and are related to scene's time, so when an Scene
- * is taken out of the Director the timer task is paused, and resumed on Scene restoration.
- *
- * @param startTime {number} an integer indicating the scene time this task must start executing at.
- * @param duration {number} an integer indicating the timerTask duration.
- * @param callback_timeout {function} timer on timeout callback function.
- * @param callback_tick {function} timer on tick callback function.
- * @param callback_cancel {function} timer on cancel callback function.
- *
- * @return {CAAT.TimerTask} a CAAT.TimerTask class instance.
- */
- createTimer : function( startTime, duration, callback_timeout, callback_tick, callback_cancel ) {
- var tt= new CAAT.TimerTask().create(
- startTime,
- duration,
- callback_timeout,
- callback_tick,
- callback_cancel );
- tt.taskId= this.timerSequence++;
- tt.sceneTime = this.time;
- tt.scene= this;
- this.timerList.push( tt );
- return tt;
- },
- /**
- * Removes expired timers. This method must not be called directly.
- */
- removeExpiredTimers : function() {
- var i;
- var tl= this.timerList;
- for( i=0; i<tl.length; i++ ) {
- if ( tl[i].remove ) {
- tl.splice(i,1);
- }
- }
- },
- /**
- * Scene animation method.
- * It extends Container's base behavior by adding timer control.
- * @param director {CAAT.Director} a CAAT.Director instance.
- * @param time {number} an integer indicating the Scene time the animation is being performed at.
- */
- animate : function(director, time) {
- this.checkTimers(time);
- CAAT.Scene.superclass.animate.call(this,director,time);
- this.removeExpiredTimers();
- },
- /**
- * Helper method to manage alpha transparency fading on Scene switch by the Director.
- * @param time {number} integer indicating the time in milliseconds the fading will take.
- * @param isIn {boolean} boolean indicating whether this Scene in the switch process is
- * being brought in.
- *
- * @private
- */
- createAlphaBehaviour: function(time, isIn) {
- var ab= new CAAT.AlphaBehavior();
- ab.setFrameTime( 0, time );
- ab.startAlpha= isIn ? 0 : 1;
- ab.endAlpha= isIn ? 1 : 0;
- this.easeContainerBehaviour.addBehavior(ab);
- },
- /**
- * Called from CAAT.Director to bring in an Scene.
- * A helper method for easeTranslation.
- * @param time integer indicating time in milliseconds for the Scene to be brought in.
- * @param alpha boolean indicating whether fading will be applied to the Scene.
- * @param anchor integer indicating the Scene switch anchor.
- * @param interpolator CAAT.Interpolator to apply to the Scene transition.
- */
- easeTranslationIn : function( time, alpha, anchor, interpolator ) {
- this.easeTranslation( time, alpha, anchor, true, interpolator );
- },
- /**
- * Called from CAAT.Director to bring in an Scene.
- * A helper method for easeTranslation.
- * @param time integer indicating time in milliseconds for the Scene to be taken away.
- * @param alpha boolean indicating whether fading will be applied to the Scene.
- * @param anchor integer indicating the Scene switch anchor.
- * @param interpolator CAAT.Interpolator to apply to the Scene transition.
- */
- easeTranslationOut : function( time, alpha, anchor, interpolator ) {
- this.easeTranslation( time, alpha, anchor, false, interpolator );
- },
- /**
- * This method will setup Scene behaviours to switch an Scene via a translation.
- * The anchor value can only be
- * <li>CAAT.Actor.prototype.ANCHOR_LEFT
- * <li>CAAT.Actor.prototype.ANCHOR_RIGHT
- * <li>CAAT.Actor.prototype.ANCHOR_TOP
- * <li>CAAT.Actor.prototype.ANCHOR_BOTTOM
- * if any other value is specified, any of the previous ones will be applied.
- *
- * @param time integer indicating time in milliseconds for the Scene.
- * @param alpha boolean indicating whether fading will be applied to the Scene.
- * @param anchor integer indicating the Scene switch anchor.
- * @param isIn boolean indicating whether the scene will be brought in.
- * @param interpolator {CAAT.Interpolator} a CAAT.Interpolator to apply to the Scene transition.
- */
- easeTranslation : function( time, alpha, anchor, isIn, interpolator ) {
- this.easeContainerBehaviour= new CAAT.ContainerBehavior();
- this.easeIn= isIn;
- var pb= new CAAT.PathBehavior();
- if ( interpolator ) {
- pb.setInterpolator( interpolator );
- }
- pb.setFrameTime( 0, time );
- // BUGBUG anchors: 1..4
- if ( anchor<1 ) {
- anchor=1;
- } else if ( anchor>4 ) {
- anchor= 4;
- }
- switch(anchor) {
- case CAAT.Actor.prototype.ANCHOR_TOP:
- if ( isIn ) {
- pb.setPath( new CAAT.Path().setLinear( 0, -this.height, 0, 0) );
- } else {
- pb.setPath( new CAAT.Path().setLinear( 0, 0, 0, -this.height) );
- }
- break;
- case CAAT.Actor.prototype.ANCHOR_BOTTOM:
- if ( isIn ) {
- pb.setPath( new CAAT.Path().setLinear( 0, this.height, 0, 0) );
- } else {
- pb.setPath( new CAAT.Path().setLinear( 0, 0, 0, this.height) );
- }
- break;
- case CAAT.Actor.prototype.ANCHOR_LEFT:
- if ( isIn ) {
- pb.setPath( new CAAT.Path().setLinear( -this.width, 0, 0, 0) );
- } else {
- pb.setPath( new CAAT.Path().setLinear( 0, 0, -this.width, 0) );
- }
- break;
- case CAAT.Actor.prototype.ANCHOR_RIGHT:
- if ( isIn ) {
- pb.setPath( new CAAT.Path().setLinear( this.width, 0, 0, 0) );
- } else {
- pb.setPath( new CAAT.Path().setLinear( 0, 0, this.width, 0) );
- }
- break;
- }
- if (alpha) {
- this.createAlphaBehaviour(time,isIn);
- }
- this.easeContainerBehaviour.addBehavior(pb);
- this.easeContainerBehaviour.setFrameTime( this.time, time );
- this.easeContainerBehaviour.addListener(this);
- this.emptyBehaviorList();
- CAAT.Scene.superclass.addBehavior.call( this, this.easeContainerBehaviour );
- },
- /**
- * Called from CAAT.Director to bring in a Scene.
- * A helper method for easeScale.
- * @param time integer indicating time in milliseconds for the Scene to be brought in.
- * @param alpha boolean indicating whether fading will be applied to the Scene.
- * @param anchor integer indicating the Scene switch anchor.
- * @param interpolator {CAAT.Interpolator} a CAAT.Interpolator to apply to the Scene transition.
- * @param starttime integer indicating in milliseconds from which scene time the behavior will be applied.
- */
- easeScaleIn : function(starttime,time,alpha,anchor,interpolator) {
- this.easeScale(starttime,time,alpha,anchor,true,interpolator);
- this.easeIn= true;
- },
- /**
- * Called from CAAT.Director to take away a Scene.
- * A helper method for easeScale.
- * @param time integer indicating time in milliseconds for the Scene to be taken away.
- * @param alpha boolean indicating whether fading will be applied to the Scene.
- * @param anchor integer indicating the Scene switch anchor.
- * @param interpolator {CAAT.Interpolator} a CAAT.Interpolator instance to apply to the Scene transition.
- * @param starttime integer indicating in milliseconds from which scene time the behavior will be applied.
- */
- easeScaleOut : function(starttime,time,alpha,anchor,interpolator) {
- this.easeScale(starttime,time,alpha,anchor,false,interpolator);
- this.easeIn= false;
- },
- /**
- * Called from CAAT.Director to bring in ot take away an Scene.
- * @param time integer indicating time in milliseconds for the Scene to be taken away.
- * @param alpha boolean indicating whether fading will be applied to the Scene.
- * @param anchor integer indicating the Scene switch anchor.
- * @param interpolator {CAAT.Interpolator} a CAAT.Interpolator to apply to the Scene transition.
- * @param starttime integer indicating in milliseconds from which scene time the behavior will be applied.
- * @param isIn boolean indicating whether the Scene is being brought in.
- */
- easeScale : function(starttime,time,alpha,anchor,isIn,interpolator) {
- this.easeContainerBehaviour= new CAAT.ContainerBehavior();
- var x=0;
- var y=0;
- var x2=0;
- var y2=0;
- switch(anchor) {
- case CAAT.Actor.prototype.ANCHOR_TOP_LEFT:
- case CAAT.Actor.prototype.ANCHOR_TOP_RIGHT:
- case CAAT.Actor.prototype.ANCHOR_BOTTOM_LEFT:
- case CAAT.Actor.prototype.ANCHOR_BOTTOM_RIGHT:
- case CAAT.Actor.prototype.ANCHOR_CENTER:
- x2=1;
- y2=1;
- break;
- case CAAT.Actor.prototype.ANCHOR_TOP:
- case CAAT.Actor.prototype.ANCHOR_BOTTOM:
- x=1;
- x2=1;
- y=0;
- y2=1;
- break;
- case CAAT.Actor.prototype.ANCHOR_LEFT:
- case CAAT.Actor.prototype.ANCHOR_RIGHT:
- y=1;
- y2=1;
- x=0;
- x2=1;
- break;
- default:
- alert('scale anchor ?? '+anchor);
- }
- if ( !isIn ) {
- var tmp;
- tmp= x;
- x= x2;
- x2= tmp;
-
- tmp= y;
- y= y2;
- y2= tmp;
- }
-
- if (alpha) {
- this.createAlphaBehaviour(time,isIn);
- }
- var anchorPercent= this.getAnchorPercent(anchor);
- var sb= new CAAT.ScaleBehavior().
- setFrameTime( starttime, time ).
- setValues(x,x2,y,y2, anchorPercent.x, anchorPercent.y);
- if ( interpolator ) {
- sb.setInterpolator(interpolator);
- }
- this.easeContainerBehaviour.addBehavior(sb);
-
- this.easeContainerBehaviour.setFrameTime( this.time, time );
- this.easeContainerBehaviour.addListener(this);
-
- this.emptyBehaviorList();
- CAAT.Scene.superclass.addBehavior.call( this, this.easeContainerBehaviour );
- },
- /**
- * Overriden method to disallow default behavior.
- * Do not use directly.
- */
- addBehavior : function(behaviour) {
- return this;
- },
- /**
- * Called from CAAT.Director to use Rotations for bringing in.
- * This method is a Helper for the method easeRotation.
- * @param time integer indicating time in milliseconds for the Scene to be brought in.
- * @param alpha boolean indicating whether fading will be applied to the Scene.
- * @param anchor integer indicating the Scene switch anchor.
- * @param interpolator {CAAT.Interpolator} a CAAT.Interpolator to apply to the Scene transition.
- */
- easeRotationIn : function(time,alpha,anchor,interpolator) {
- this.easeRotation(time,alpha,anchor,true, interpolator);
- this.easeIn= true;
- },
- /**
- * Called from CAAT.Director to use Rotations for taking Scenes away.
- * This method is a Helper for the method easeRotation.
- * @param time integer indicating time in milliseconds for the Scene to be taken away.
- * @param alpha boolean indicating whether fading will be applied to the Scene.
- * @param anchor integer indicating the Scene switch anchor.
- * @param interpolator {CAAT.Interpolator} a CAAT.Interpolator to apply to the Scene transition.
- */
- easeRotationOut : function(time,alpha,anchor,interpolator) {
- this.easeRotation(time,alpha,anchor,false,interpolator);
- this.easeIn= false;
- },
- /**
- * Called from CAAT.Director to use Rotations for taking away or bringing Scenes in.
- * @param time integer indicating time in milliseconds for the Scene to be taken away or brought in.
- * @param alpha boolean indicating whether fading will be applied to the Scene.
- * @param anchor integer indicating the Scene switch anchor.
- * @param interpolator {CAAT.Interpolator} a CAAT.Interpolator to apply to the Scene transition.
- * @param isIn boolean indicating whehter the Scene is brought in.
- */
- easeRotation : function(time,alpha,anchor,isIn,interpolator) {
- this.easeContainerBehaviour= new CAAT.ContainerBehavior();
-
- var start=0;
- var end=0;
- if (anchor==CAAT.Actor.prototype.ANCHOR_CENTER ) {
- anchor= CAAT.Actor.prototype.ANCHOR_TOP;
- }
- switch(anchor) {
- case CAAT.Actor.prototype.ANCHOR_TOP:
- case CAAT.Actor.prototype.ANCHOR_BOTTOM:
- case CAAT.Actor.prototype.ANCHOR_LEFT:
- case CAAT.Actor.prototype.ANCHOR_RIGHT:
- start= Math.PI * (Math.random()<0.5 ? 1 : -1);
- break;
- case CAAT.Actor.prototype.ANCHOR_TOP_LEFT:
- case CAAT.Actor.prototype.ANCHOR_TOP_RIGHT:
- case CAAT.Actor.prototype.ANCHOR_BOTTOM_LEFT:
- case CAAT.Actor.prototype.ANCHOR_BOTTOM_RIGHT:
- start= Math.PI/2 * (Math.random()<0.5 ? 1 : -1);
- break;
- default:
- alert('rot anchor ?? '+anchor);
- }
- if ( false===isIn ) {
- var tmp= start;
- start=end;
- end= tmp;
- }
- if ( alpha ) {
- this.createAlphaBehaviour(time,isIn);
- }
- var anchorPercent= this.getAnchorPercent(anchor);
- var rb= new CAAT.RotateBehavior().
- setFrameTime( 0, time ).
- setValues( start, end, anchorPercent.x, anchorPercent.y );
- if ( interpolator ) {
- rb.setInterpolator(interpolator);
- }
- this.easeContainerBehaviour.addBehavior(rb);
- this.easeContainerBehaviour.setFrameTime( this.time, time );
- this.easeContainerBehaviour.addListener(this);
-
- this.emptyBehaviorList();
- CAAT.Scene.superclass.addBehavior.call( this, this.easeContainerBehaviour );
- },
- /**
- * Registers a listener for listen for transitions events.
- * Al least, the Director registers himself as Scene easing transition listener.
- * When the transition is done, it restores the Scene's capability of receiving events.
- * @param listener {function(caat_behavior,time,actor)} an object which contains a method of the form <code>
- * behaviorExpired( caat_behaviour, time, actor);
- */
- setEaseListener : function( listener ) {
- this.easeContainerBehaviourListener=listener;
- },
- /**
- * Private.
- * listener for the Scene's easeContainerBehaviour.
- * @param actor
- */
- behaviorExpired : function(actor) {
- this.easeContainerBehaviourListener.easeEnd(this, this.easeIn);
- },
- /**
- * This method should be overriden in case the developer wants to do some special actions when
- * the scene has just been brought in.
- */
- activated : function() {
- },
- /**
- * Scenes, do not expire the same way Actors do.
- * It simply will be set expired=true, but the frameTime won't be modified.
- */
- setExpired : function(bExpired) {
- this.expired= bExpired;
- },
- /**
- * An scene by default does not paint anything because has not fillStyle set.
- * @param director
- * @param time
- */
- paint : function(director, time) {
- if ( this.fillStyle ) {
- var ctx= director.crc;
- ctx.fillStyle= this.fillStyle;
- ctx.fillRect(0,0,this.width,this.height );
- }
- },
- /**
- * Find a pointed actor at position point.
- * This method tries lo find the correctly pointed actor in two different ways.
- * + first of all, if inputList is defined, it will look for an actor in it.
- * + if no inputList is defined, it will traverse the scene graph trying to find a pointed actor.
- * @param point <CAAT.Point>
- */
- findActorAtPosition : function(point) {
- var i,j;
- var p= new CAAT.Point();
- if ( this.inputList ) {
- var il= this.inputList;
- for( i=0; i<il.length; i++ ) {
- var ill= il[i];
- for( j=0; j<ill.length; j++ ) {
- p.set(point.x, point.y);
- var modelViewMatrixI= ill[j].worldModelViewMatrix.getInverse();
- modelViewMatrixI.transformCoord(p);
- if ( ill[j].contains(p.x, p.y) ) {
- return ill[j];
- }
- }
- }
- }
- p.set(point.x, point.y);
- return CAAT.Scene.superclass.findActorAtPosition.call(this,p);
- },
- /**
- * Enable a number of input lists.
- * These lists are set in case the developer doesn't want the to traverse the scene graph to find the pointed
- * actor. The lists are a shortcut whete the developer can set what actors to look for input at first instance.
- * The system will traverse the whole lists in order trying to find a pointed actor.
- *
- * Elements are added to each list either in head or tail.
- *
- * @param size <number> number of lists.
- */
- enableInputList : function( size ) {
- this.inputList= [];
- for( var i=0; i<size; i++ ) {
- this.inputList.push([]);
- }
- return this;
- },
- /**
- * Add an actor to a given inputList.
- * @param actor <CAAT.Actor> an actor instance
- * @param index <number> the inputList index to add the actor to. This value will be clamped to the number of
- * available lists.
- * @param position <number> the position on the selected inputList to add the actor at. This value will be
- * clamped to the number of available lists.
- */
- addActorToInputList : function( actor, index, position ) {
- if ( index<0 ) index=0; else if ( index>=this.inputList.length ) index= this.inputList.length-1;
- var il= this.inputList[index];
- if ( typeof position==="undefined" || position>=il.length ) {
- il.push( actor );
- } else if (position<=0) {
- il.unshift( actor );
- } else {
- il.splice( position, 0, actor );
- }
- return this;
- },
- /**
- * Remove all elements from an input list.
- * @param index <number> the inputList index to add the actor to. This value will be clamped to the number of
- * available lists so take care when emptying a non existant inputList index since you could end up emptying
- * an undesired input list.
- */
- emptyInputList : function( index ) {
- if ( index<0 ) index=0; else if ( index>=this.inputList.length ) index= this.inputList.length-1;
- this.inputList[index]= [];
- return this;
- },
- /**
- * remove an actor from a given input list index.
- * If no index is supplied, the actor will be removed from every input list.
- * @param actor <CAAT.Actor>
- * @param index <!number> an optional input list index. This value will be clamped to the number of
- * available lists.
- */
- removeActorFromInputList : function( actor, index ) {
- if ( typeof index==="undefined" ) {
- var i,j;
- for( i=0; i<this.inputList.length; i++ ) {
- var il= this.inputList[i];
- for( j=0; j<il.length; j++ ) {
- if ( il[j]==actor ) {
- il.splice( j,1 );
- }
- }
- }
- return this;
- }
- if ( index<0 ) index=0; else if ( index>=this.inputList.length ) index= this.inputList.length-1;
- var il= this.inputList[index];
- for( j=0; j<il.length; j++ ) {
- if ( il[j]==actor ) {
- il.splice( j,1 );
- }
- }
- return this;
- }
- };
- extend( CAAT.Scene, CAAT.ActorContainer );
- })();/**
- * See LICENSE file.
- *
- * @author Mario Gonzalez || http://onedayitwillmake.com
- *
- **/
- /**
- * @namespace
- */
- CAAT.modules = CAAT.modules || {};
- /**
- * @namespace
- */
- CAAT.modules.CircleManager = CAAT.modules.CircleManager || {};/**
- * See LICENSE file.
- *
- #### ##### ##### #### ### # # ###### ###### ## ## ##### # # ######## ## # # #####
- # # # # ### # # ##### ### ## ## ## # ## # # # # ## # ##### ### ###
- ### # # ##### #### # # # ###### ## ######### ##### ##### ##### # ## # # # # # #####
- -
- File:
- PackedCircle.js
- Created By:
- Mario Gonzalez
- Project :
- None
- Abstract:
- A single packed circle.
- Contains a reference to it's div, and information pertaining to it state.
- Basic Usage:
- http://onedayitwillmake.com/CirclePackJS/
- */
- (function() {
- /**
- * @constructor
- */
- CAAT.modules.CircleManager.PackedCircle= function()
- {
- this.boundsRule = CAAT.modules.CircleManager.PackedCircle.BOUNDS_RULE_IGNORE;
- this.position = new CAAT.Point(0,0,0);
- this.offset = new CAAT.Point(0,0,0);
- this.targetPosition = new CAAT.Point(0,0,0);
- return this;
- };
- CAAT.modules.CircleManager.PackedCircle.prototype = {
- id: 0,
- delegate: null,
- position: new CAAT.Point(0,0,0),
- offset: new CAAT.Point(0,0,0), // Offset from delegates position by this much
- targetPosition: null, // Where it wants to go
- targetChaseSpeed: 0.02,
- isFixed: false,
- boundsRule: 0,
- collisionMask: 0,
- collisionGroup: 0,
- BOUNDS_RULE_WRAP: 1, // Wrap to otherside
- BOUNDS_RULE_CONSTRAINT: 2, // Constrain within bounds
- BOUNDS_RULE_DESTROY: 4, // Destroy when it reaches the edge
- BOUNDS_RULE_IGNORE: 8, // Ignore when reaching bounds
- containsPoint: function(aPoint)
- {
- var distanceSquared = this.position.getDistanceSquared(aPoint);
- return distanceSquared < this.radiusSquared;
- },
- getDistanceSquaredFromPosition: function(aPosition)
- {
- var distanceSquared = this.position.getDistanceSquared(aPosition);
- // if it's shorter than either radius, we intersect
- return distanceSquared < this.radiusSquared;
- },
- intersects: function(aCircle)
- {
- var distanceSquared = this.position.getDistanceSquared(aCircle.position);
- return (distanceSquared < this.radiusSquared || distanceSquared < aCircle.radiusSquared);
- },
- /**
- * ACCESSORS
- */
- setPosition: function(aPosition)
- {
- this.position = aPosition;
- return this;
- },
- setDelegate: function(aDelegate)
- {
- this.delegate = aDelegate;
- return this;
- },
- setOffset: function(aPosition)
- {
- this.offset = aPosition;
- return this;
- },
- setTargetPosition: function(aTargetPosition)
- {
- this.targetPosition = aTargetPosition;
- return this;
- },
- setTargetChaseSpeed: function(aTargetChaseSpeed)
- {
- this.targetChaseSpeed = aTargetChaseSpeed;
- return this;
- },
- setIsFixed: function(value)
- {
- this.isFixed = value;
- return this;
- },
- setCollisionMask: function(aCollisionMask)
- {
- this.collisionMask = aCollisionMask;
- return this;
- },
- setCollisionGroup: function(aCollisionGroup)
- {
- this.collisionGroup = aCollisionGroup;
- return this;
- },
- setRadius: function(aRadius)
- {
- this.radius = aRadius;
- this.radiusSquared = this.radius*this.radius;
- return this;
- },
- initialize : function(overrides)
- {
- if (overrides)
- {
- for (var i in overrides)
- {
- this[i] = overrides[i];
- }
- }
- return this;
- },
- dealloc: function()
- {
- this.position = null;
- this.offset = null;
- this.delegate = null;
- this.targetPosition = null;
- }
- };
- })();/**
- *
- * See LICENSE file.
- *
- #### ##### ##### #### ### # # ###### ###### ## ## ##### # # ######## ## # # #####
- # # # # ### # # ##### ### ## ## ## # ## # # # # ## # ##### ### ###
- ### # # ##### #### # # # ###### ## ######### ##### ##### ##### # ## # # # # # #####
- -
- File:
- PackedCircle.js
- Created By:
- Mario Gonzalez
- Project :
- None
- Abstract:
- A single packed circle.
- Contains a reference to it's div, and information pertaining to it state.
- Basic Usage:
- http://onedayitwillmake.com/CirclePackJS/
- */
- (function()
- {
- /**
- * @constructor
- */
- CAAT.modules.CircleManager.PackedCircleManager= function()
- {
- return this;
- };
- CAAT.modules.CircleManager.PackedCircleManager.prototype = {
- allCircles: [],
- numberOfCollisionPasses: 1,
- numberOfTargetingPasses: 0,
- bounds: new CAAT.Rectangle(),
- /**
- * Adds a circle to the simulation
- * @param aCircle
- */
- addCircle: function(aCircle)
- {
- aCircle.id = this.allCircles.length;
- this.allCircles.push(aCircle);
- return this;
- },
- /**
- * Removes a circle from the simulations
- * @param aCircle Circle to remove
- */
- removeCircle: function(aCircle)
- {
- var index = 0,
- found = false,
- len = this.allCircles.length;
- if(len === 0) {
- throw "Error: (PackedCircleManager) attempting to remove circle, and allCircles.length === 0!!";
- }
- while (len--) {
- if(this.allCircles[len] === aCircle) {
- found = true;
- index = len;
- break;
- }
- }
- if(!found) {
- throw "Could not locate circle in allCircles array!";
- }
- // Remove
- this.allCircles[index].dealloc();
- this.allCircles[index] = null;
- return this;
- },
- /**
- * Forces all circles to move to where their delegate position is
- * Assumes all targets have a 'position' property!
- */
- forceCirclesToMatchDelegatePositions: function()
- {
- var len = this.allCircles.length;
- // push toward target position
- for(var n = 0; n < len; n++)
- {
- var aCircle = this.allCircles[n];
- if(!aCircle || !aCircle.delegate) {
- continue;
- }
- aCircle.position.set(aCircle.delegate.x + aCircle.offset.x,
- aCircle.delegate.y + aCircle.offset.y);
- }
- },
- pushAllCirclesTowardTarget: function(aTarget)
- {
- var v = new CAAT.Point(0,0,0),
- circleList = this.allCircles,
- len = circleList.length;
- // push toward target position
- for(var n = 0; n < this.numberOfTargetingPasses; n++)
- {
- for(var i = 0; i < len; i++)
- {
- var c = circleList[i];
- if(c.isFixed) continue;
- v.x = c.position.x - (c.targetPosition.x+c.offset.x);
- v.y = c.position.y - (c.targetPosition.y+c.offset.y);
- v.multiply(c.targetChaseSpeed);
- c.position.x -= v.x;
- c.position.y -= v.y;
- }
- }
- },
- /**
- * Packs the circles towards the center of the bounds.
- * Each circle will have it's own 'targetPosition' later on
- */
- handleCollisions: function()
- {
- this.removeExpiredElements();
- var v = new CAAT.Point(0,0, 0),
- circleList = this.allCircles,
- len = circleList.length;
- // Collide circles
- for(var n = 0; n < this.numberOfCollisionPasses; n++)
- {
- for(var i = 0; i < len; i++)
- {
- var ci = circleList[i];
- for (var j = i + 1; j< len; j++)
- {
- var cj = circleList[j];
- if( !this.circlesCanCollide(ci, cj) ) continue; // It's us!
- var dx = cj.position.x - ci.position.x,
- dy = cj.position.y - ci.position.y;
- // The distance between the two circles radii, but we're also gonna pad it a tiny bit
- var r = (ci.radius + cj.radius) * 1.08,
- d = ci.position.getDistanceSquared(cj.position);
- /**
- * Collision detected!
- */
- if (d < (r * r) - 0.02 )
- {
- v.x = dx;
- v.y = dy;
- v.normalize();
- var inverseForce = (r - Math.sqrt(d)) * 0.5;
- v.multiply(inverseForce);
- // Move cj opposite of the collision as long as its not fixed
- if(!cj.isFixed)
- {
- if(ci.isFixed)
- v.multiply(2.2); // Double inverse force to make up for the fact that the other object is fixed
- // ADD the velocity
- cj.position.translatePoint(v);
- }
- // Move ci opposite of the collision as long as its not fixed
- if(!ci.isFixed)
- {
- if(cj.isFixed)
- v.multiply(2.2); // Double inverse force to make up for the fact that the other object is fixed
- // SUBTRACT the velocity
- ci.position.subtract(v);
- }
- // Emit the collision event from each circle, with itself as the first parameter
- // if(this.dispatchCollisionEvents && n == this.numberOfCollisionPasses-1)
- // {
- // this.eventEmitter.emit('collision', cj, ci, v);
- // }
- }
- }
- }
- }
- },
- handleBoundaryForCircle: function(aCircle, boundsRule)
- {
- // if(aCircle.boundsRule === true) return; // Ignore if being dragged
- var xpos = aCircle.position.x;
- var ypos = aCircle.position.y;
- var radius = aCircle.radius;
- var diameter = radius*2;
- // Toggle these on and off,
- // Wrap and bounce, are opposite behaviors so pick one or the other for each axis, or bad things will happen.
- var wrapXMask = 1 << 0;
- var wrapYMask = 1 << 2;
- var constrainXMask = 1 << 3;
- var constrainYMask = 1 << 4;
- var emitEvent = 1 << 5;
- // TODO: Promote to member variable
- // Convert to bitmask - Uncomment the one you want, or concact your own :)
- // boundsRule = wrapY; // Wrap only Y axis
- // boundsRule = wrapX; // Wrap only X axis
- // boundsRule = wrapXMask | wrapYMask; // Wrap both X and Y axis
- boundsRule = wrapYMask | constrainXMask; // Wrap Y axis, but constrain horizontally
- // Wrap X
- if(boundsRule & wrapXMask && xpos-diameter > this.bounds.right) {
- aCircle.position.x = this.bounds.left + radius;
- } else if(boundsRule & wrapXMask && xpos+diameter < this.bounds.left) {
- aCircle.position.x = this.bounds.right - radius;
- }
- // Wrap Y
- if(boundsRule & wrapYMask && ypos-diameter > this.bounds.bottom) {
- aCircle.position.y = this.bounds.top - radius;
- } else if(boundsRule & wrapYMask && ypos+diameter < this.bounds.top) {
- aCircle.position.y = this.bounds.bottom + radius;
- }
- // Constrain X
- if(boundsRule & constrainXMask && xpos+radius >= this.bounds.right) {
- aCircle.position.x = aCircle.position.x = this.bounds.right-radius;
- } else if(boundsRule & constrainXMask && xpos-radius < this.bounds.left) {
- aCircle.position.x = this.bounds.left + radius;
- }
- // Constrain Y
- if(boundsRule & constrainYMask && ypos+radius > this.bounds.bottom) {
- aCircle.position.y = this.bounds.bottom - radius;
- } else if(boundsRule & constrainYMask && ypos-radius < this.bounds.top) {
- aCircle.position.y = this.bounds.top + radius;
- }
- },
- /**
- * Given an x,y position finds circle underneath and sets it to the currently grabbed circle
- * @param {Number} xpos An x position
- * @param {Number} ypos A y position
- * @param {Number} buffer A radiusSquared around the point in question where something is considered to match
- */
- getCircleAt: function(xpos, ypos, buffer)
- {
- var circleList = this.allCircles;
- var len = circleList.length;
- var grabVector = new CAAT.Point(xpos, ypos, 0);
- // These are set every time a better match i found
- var closestCircle = null;
- var closestDistance = Number.MAX_VALUE;
- // Loop thru and find the closest match
- for(var i = 0; i < len; i++)
- {
- var aCircle = circleList[i];
- if(!aCircle) continue;
- var distanceSquared = aCircle.position.getDistanceSquared(grabVector);
- if(distanceSquared < closestDistance && distanceSquared < aCircle.radiusSquared + buffer)
- {
- closestDistance = distanceSquared;
- closestCircle = aCircle;
- }
- }
- return closestCircle;
- },
- circlesCanCollide: function(circleA, circleB)
- {
- if(!circleA || !circleB || circleA===circleB) return false; // one is null (will be deleted next loop), or both point to same obj.
- // if(circleA.delegate == null || circleB.delegate == null) return false; // This circle will be removed next loop, it's entity is already removed
- // if(circleA.isFixed & circleB.isFixed) return false;
- // if(circleA.delegate .clientID === circleB.delegate.clientID) return false; // Don't let something collide with stuff it owns
- // They dont want to collide
- // if((circleA.collisionGroup & circleB.collisionMask) == 0) return false;
- // if((circleB.collisionGroup & circleA.collisionMask) == 0) return false;
- return true;
- },
- /**
- * Accessors
- */
- setBounds: function(x, y, w, h)
- {
- this.bounds.x = x;
- this.bounds.y = y;
- this.bounds.width = w;
- this.bounds.height = h;
- },
- setNumberOfCollisionPasses: function(value)
- {
- this.numberOfCollisionPasses = value;
- return this;
- },
- setNumberOfTargetingPasses: function(value)
- {
- this.numberOfTargetingPasses = value;
- return this;
- },
- /**
- * Helpers
- */
- sortOnDistanceToTarget: function(circleA, circleB)
- {
- var valueA = circleA.getDistanceSquaredFromPosition(circleA.targetPosition);
- var valueB = circleB.getDistanceSquaredFromPosition(circleA.targetPosition);
- var comparisonResult = 0;
- if(valueA > valueB) comparisonResult = -1;
- else if(valueA < valueB) comparisonResult = 1;
- return comparisonResult;
- },
- /**
- * Memory Management
- */
- removeExpiredElements: function()
- {
- // remove null elements
- for (var k = this.allCircles.length; k >= 0; k--) {
- if (this.allCircles[k] === null)
- this.allCircles.splice(k, 1);
- }
- },
- initialize : function(overrides)
- {
- if (overrides)
- {
- for (var i in overrides)
- {
- this[i] = overrides[i];
- }
- }
- return this;
- }
- };
- })();/**
- * See LICENSE file.
- *
- **/
- (function() {
- /**
- * Local storage management.
- * @constructor
- */
- CAAT.modules.LocalStorage= function() {
- return this;
- };
- CAAT.modules.LocalStorage.prototype= {
- /**
- * Stores an object in local storage. The data will be saved as JSON.stringify.
- * @param key {string} key to store data under.
- * @param data {object} an object.
- * @return this
- *
- * @static
- */
- save : function( key, data ) {
- try {
- localStorage.setItem( key, JSON.stringify(data) );
- } catch(e) {
- // eat it
- }
- return this;
- },
- /**
- * Retrieve a value from local storage.
- * @param key {string} the key to retrieve.
- * @return {object} object stored under the key parameter.
- *
- * @static
- */
- load : function( key ) {
- try {
- return JSON.parse(localStorage.getItem( key ));
- } catch(e) {
- return null;
- }
- },
- /**
- * Removes a value stored in local storage.
- * @param key {string}
- * @return this
- *
- * @static
- */
- remove : function( key ) {
- try {
- localStorage.removeItem(key);
- } catch(e) {
- // eat it
- }
- return this;
- }
- };
- })();
- /**
- * See LICENSE file.
- */
- (function() {
- CAAT.modules.ImageUtil= {};
- CAAT.modules.ImageUtil.createAlphaSpriteSheet= function(maxAlpha, minAlpha, sheetSize, image, bg_fill_style ) {
- if ( maxAlpha<minAlpha ) {
- var t= maxAlpha;
- maxAlpha= minAlpha;
- minAlpha= t;
- }
- var canvas= document.createElement('canvas');
- canvas.width= image.width;
- canvas.height= image.height*sheetSize;
- var ctx= canvas.getContext('2d');
- ctx.fillStyle = bg_fill_style ? bg_fill_style : 'rgba(255,255,255,0)';
- ctx.fillRect(0,0,image.width,image.height*sheetSize);
- var i;
- for( i=0; i<sheetSize; i++ ) {
- ctx.globalAlpha= 1-(maxAlpha-minAlpha)/sheetSize*(i+1);
- ctx.drawImage(image, 0, i*image.height);
- }
- return canvas;
- };
- /**
- * Creates a rotated canvas image element.
- * @param img
- */
- CAAT.modules.ImageUtil.rotate= function( image, angle ) {
- angle= angle||0;
- if ( !angle ) {
- return image;
- }
- var canvas= document.createElement("canvas");
- canvas.width= image.height;
- canvas.height= image.width;
- var ctx= canvas.getContext('2d');
- ctx.globalAlpha= 1;
- ctx.fillStyle='rgba(0,0,0,0)';
- ctx.clearRect(0,0,canvas.width,canvas.height);
- var m= new CAAT.Matrix();
- m.multiply( new CAAT.Matrix().setTranslate( canvas.width/2, canvas.width/2 ) );
- m.multiply( new CAAT.Matrix().setRotation( angle*Math.PI/180 ) );
- m.multiply( new CAAT.Matrix().setTranslate( -canvas.width/2, -canvas.width/2 ) );
- m.transformRenderingContext(ctx);
- ctx.drawImage(image,0,0);
- return canvas;
- };
- /**
- * Remove an image's padding transparent border.
- * Transparent means that every scan pixel is alpha=0.
- * @param image
- * @param threshold {integer} any value below or equal to this will be optimized.
- * @param !areas { object{ top<boolean>, bottom<boolean>, left<boolean, right<boolean> }�}
- */
- CAAT.modules.ImageUtil.optimize= function(image, threshold, areas ) {
- threshold>>=0;
- var atop= true;
- var abottom= true;
- var aleft= true;
- var aright= true;
- if ( typeof areas!=='undefined' ) {
- if ( typeof areas.top!=='undefined' ) {
- atop= areas.top;
- }
- if ( typeof areas.bottom!=='undefined' ) {
- abottom= areas.bottom;
- }
- if ( typeof areas.left!=='undefined' ) {
- aleft= areas.left;
- }
- if ( typeof areas.right!=='undefined' ) {
- aright= areas.right;
- }
- }
- var canvas= document.createElement('canvas');
- canvas.width= image.width;
- canvas.height=image.height;
- var ctx= canvas.getContext('2d');
- ctx.fillStyle='rgba(0,0,0,0)';
- ctx.fillRect(0,0,image.width,image.height);
- ctx.drawImage( image, 0, 0 );
- var imageData= ctx.getImageData(0,0,image.width,image.height);
- var data= imageData.data;
- var i,j;
- var miny= 0, maxy=canvas.height-1;
- var minx= 0, maxx=canvas.width-1;
- var alpha= false;
- if ( atop ) {
- for( i=0; i<canvas.height; i++ ) {
- for( j=0; j<canvas.width; j++ ) {
- if ( data[i*canvas.width*4 + 3+j*4]>threshold ) {
- alpha= true;
- break;
- }
- }
- if ( alpha ) {
- break;
- }
- }
- // i contiene el indice del ultimo scan que no es transparente total.
- miny= i;
- }
- if ( abottom ) {
- alpha= false;
- for( i=canvas.height-1; i>=miny; i-- ) {
- for( j=0; j<canvas.width; j++ ) {
- if ( data[i*canvas.width*4 + 3+j*4]>threshold ) {
- alpha= true;
- break;
- }
- }
- if ( alpha ) {
- break;
- }
- }
- maxy= i;
- }
- if ( aleft ) {
- alpha= false;
- for( j=0; j<canvas.width; j++ ) {
- for( i=miny; i<=maxy; i++ ) {
- if ( data[i*canvas.width*4 + 3+j*4 ]>threshold ) {
- alpha= true;
- break;
- }
- }
- if ( alpha ) {
- break;
- }
- }
- minx= j;
- }
- if ( aright ) {
- alpha= false;
- for( j=canvas.width-1; j>=minx; j-- ) {
- for( i=miny; i<=maxy; i++ ) {
- if ( data[i*canvas.width*4 + 3+j*4 ]>threshold ) {
- alpha= true;
- break;
- }
- }
- if ( alpha ) {
- break;
- }
- }
- maxx= j;
- }
- if ( 0===minx && 0===miny && canvas.width-1===maxx && canvas.height-1===maxy ) {
- return canvas;
- }
- var width= maxx-minx+1;
- var height=maxy-miny+1;
- var id2= ctx.getImageData( minx, miny, width, height );
- canvas.width= width;
- canvas.height= height;
- ctx= canvas.getContext('2d');
- ctx.putImageData( id2, 0, 0 );
- return canvas;
- };
- CAAT.modules.ImageUtil.createThumb= function(image, w, h, best_fit) {
- w= w||24;
- h= h||24;
- var canvas= document.createElement('canvas');
- canvas.width= w;
- canvas.height= h;
- var ctx= canvas.getContext('2d');
- if ( best_fit ) {
- var max= Math.max( image.width, image.height );
- var ww= image.width/max*w;
- var hh= image.height/max*h;
- ctx.drawImage( image, (w-ww)/2,(h-hh)/2,ww,hh );
- } else {
- ctx.drawImage( image, 0, 0, w, h );
- }
- return canvas;
- }
- })();/**
- * See LICENSE file.
- */
- (function() {
- CAAT.modules.LayoutUtils= {};
- CAAT.modules.LayoutUtils.row= function( dst, what_to_layout_array, constraint_object ) {
- var width= dst.width;
- var x=0, y=0, i=0, l=0;
- var actor_max_h= -Number.MAX_VALUE, actor_max_w= Number.MAX_VALUE;
- // compute max/min actor list size.
- for( i=what_to_layout_array.length-1; i; i-=1 ) {
- if ( actor_max_w<what_to_layout_array[i].width ) {
- actor_max_w= what_to_layout_array[i].width;
- }
- if ( actor_max_h<what_to_layout_array[i].height ) {
- actor_max_h= what_to_layout_array[i].height;
- }
- }
- if ( constraint_object.padding_left ) {
- x= constraint_object.padding_left;
- width-= x;
- }
- if ( constraint_object.padding_right ) {
- width-= constraint_object.padding_right;
- }
- if ( constraint_object.top ) {
- var top= parseInt(constraint_object.top, 10);
- if ( !isNaN(top) ) {
- y= top;
- } else {
- // not number
- switch(constraint_object.top) {
- case 'center':
- y= (dst.height-actor_max_h)/2;
- break;
- case 'top':
- y=0;
- break;
- case 'bottom':
- y= dst.height-actor_max_h;
- break;
- default:
- y= 0;
- }
- }
- }
- // space for each actor
- var actor_area= width / what_to_layout_array.length;
- for( i=0, l=what_to_layout_array.length; i<l; i++ ) {
- what_to_layout_array[i].setLocation(
- x + i * actor_area + (actor_area - what_to_layout_array[i].width) / 2,
- y);
- }
- };
- })();/**
- * See LICENSE file.
- *
- * This class generates an in-memory image with the representation of a drawn list of characters.
- *
- **/
- (function() {
- /**
- * @constructor
- */
- CAAT.Font= function( ) {
- return this;
- };
- var UNKNOWN_CHAR_WIDTH= 10;
- CAAT.Font.prototype= {
- fontSize : 10,
- fontSizeUnit: "px",
- font : 'Sans-Serif',
- fontStyle : '',
- fillStyle : '#fff',
- strokeStyle : null,
- padding : 0,
- image : null,
- charMap : null,
- height : 0,
- setPadding : function( padding ) {
- this.padding= padding;
- return this;
- },
- setFontStyle : function( style ) {
- this.fontStyle= style;
- return this;
- },
- setFontSize : function( fontSize ) {
- this.fontSize= fontSize;
- this.fontSizeUnit= 'px';
- return this;
- },
- setFont : function( font ) {
- this.font= font;
- return this;
- },
- setFillStyle : function( style ) {
- this.fillStyle= style;
- return this;
- },
- setStrokeStyle : function( style ) {
- this.strokeStyle= style;
- return this;
- },
- createDefault : function( padding ) {
- var str="";
- for( var i=32; i<128; i++ ) {
- str= str+String.fromCharCode(i);
- }
- return this.create( str, padding );
- },
- create : function( chars, padding ) {
- padding= padding | 0;
- this.padding= padding;
- var canvas= document.createElement('canvas');
- canvas.width= 1;
- canvas.height= 1;
- var ctx= canvas.getContext('2d');
- ctx.textBaseline= 'top';
- ctx.font= this.fontStyle+' '+this.fontSize+""+this.fontSizeUnit+" "+ this.font;
- var textWidth= 0;
- var charWidth= [];
- var i;
- var x;
- var cchar;
- for( i=0; i<chars.length; i++ ) {
- var cw= Math.max( 1, (ctx.measureText( chars.charAt(i) ).width>>0)+1 ) + 2 * padding ;
- charWidth.push(cw);
- textWidth+= cw;
- }
- canvas.width= textWidth;
- canvas.height= (this.fontSize*1.5)>>0;
- ctx= canvas.getContext('2d');
- ctx.textBaseline= 'top';
- ctx.font= this.fontStyle+' '+this.fontSize+""+this.fontSizeUnit+" "+ this.font;
- ctx.fillStyle= this.fillStyle;
- ctx.strokeStyle= this.strokeStyle;
- this.charMap= {};
- x=0;
- for( i=0; i<chars.length; i++ ) {
- cchar= chars.charAt(i);
- ctx.fillText( cchar, x+padding, 0 );
- if ( this.strokeStyle ) {
- ctx.beginPath();
- ctx.strokeText( cchar, x+padding, 0 );
- }
- this.charMap[cchar]= {
- x: x,
- width: charWidth[i]
- };
- x+= charWidth[i];
- }
- this.image= CAAT.modules.ImageUtil.optimize( canvas, 32, { top: true, bottom: true, left: false, right: false } );
- this.height= this.image.height;
- return this;
- },
- setAsSpriteImage : function() {
- var cm= [];
- var _index= 0;
- for( var i in this.charMap ) {
- var _char= i;
- var charData= this.charMap[i];
- cm[i]={
- id: _index++,
- height: this.height,
- xoffset: 0,
- letter: _char,
- yoffset: 0,
- width: charData.width,
- xadvance: charData.width,
- x: charData.x,
- y: 0
- };
- }
- return new CAAT.SpriteImage().initializeAsGlyphDesigner( this.image, cm );
- },
- stringWidth : function( str ) {
- var i, l, w=0, c;
- for( i=0, l=str.length; i<l; i++ ) {
- c= this.charMap[ str.charAt(i) ];
- if ( c ) {
- w+= c.width;
- } else {
- w+= UNKNOWN_CHAR_WIDTH;
- }
- }
- return w;
- },
- drawText : function( str, ctx, x, y ) {
- var i,l,charInfo,w;
- var height= this.image.height;
- for( i=0, l=str.length; i<l; i++ ) {
- charInfo= this.charMap[ str.charAt(i) ];
- if ( charInfo ) {
- w= charInfo.width;
- ctx.drawImage(
- this.image,
- charInfo.x, 0,
- w, height,
- x, y,
- w, height);
- x+= w;
- } else {
- ctx.strokeStyle='#f00';
- ctx.strokeRect( x,y,UNKNOWN_CHAR_WIDTH,height );
- x+= UNKNOWN_CHAR_WIDTH;
- }
- }
- },
- save : function() {
- var str= "image/png";
- var strData= this.image.toDataURL(str);
- document.location.href= strData.replace( str, "image/octet-stream" );
- }
- };
- })();
- /**
- * See LICENSE file.
- *
- *
- *
- */
- /*
- (function() {
- CAAT.modules.Inspector= function() {
- return this;
- };
- CAAT.modules.Inspector.prototype= {
- initialize : function(root) {
- if ( !root ) {
- root= CAAT;
- }
- CAAT.log("Analyzing "+root.toString()+" for reflection info.");
- for( var clazz in root ) {
- if ( root[clazz].__reflectionInfo ) {
- CAAT.log(" Extracting reflection info for: "+root[clazz] );
- this.extractReflectionInfo( root[clazz] );
- }
- }
- },
- extractReflectionInfo : function( object ) {
- var ri= object.__reflectionInfo;
- var key;
- var i;
- var __removeEmpty= function( el, index, array ) {
- array[index]= array[index].trim();
- if ( array[index]==="" ) array.splice(index,1);
- };
- for( key in ri ) {
- var metadata= ri[key];
- CAAT.log(" reflection info for: "+key+"="+metadata );
- var ks= key.split(",");
- var data= metadata.split(",");
- ks.forEach( __removeEmpty );
- data.forEach( __removeEmpty );
- if ( ks.length===1 ) { // one property.
- data.forEach( function( el, index, array ) {
- // el is each metadata definition of the form: key:value
- var operation= el.split(":");
- operation.forEach( __removeEmpty );
- if ( operation.length!=2 ) {
- CAAT.log(" ERR. operation: "+el+" wrong format");
- } else {
- if ( operation[0]==="set" ) {
- CAAT.log("set="+operation[1]);
- } else if ( operation[0]==="get" ) {
- CAAT.log("get="+operation[1]);
- } else if ( operation[0]==="type" ) {
- CAAT.log("type="+operation[1]);
- }
- }
- });
- }
- }
- }
- };
- })();
- */
- /**
- * See LICENSE file.
- *
- * Interpolator actor will draw interpolators on screen.
- *
- **/
- (function() {
- /**
- * This actor class draws an interpolator function by caching an interpolator contour as a polyline.
- *
- * @constructor
- * @extends CAAT.ActorContainer
- */
- CAAT.InterpolatorActor = function() {
- CAAT.InterpolatorActor.superclass.constructor.call(this);
- return this;
- };
- CAAT.InterpolatorActor.prototype= {
- interpolator: null, // CAAT.Interpolator instance.
- contour: null, // interpolator contour cache
- S: 50, // contour samples.
- gap: 5, // border size in pixels.
- /**
- * Sets a padding border size. By default is 5 pixels.
- * @param gap {number} border size in pixels.
- * @return this
- */
- setGap : function( gap ) {
- this.gap= gap;
- return this;
- },
- /**
- * Sets the CAAT.Interpolator instance to draw.
- *
- * @param interpolator a CAAT.Interpolator instance.
- * @param size an integer indicating the number of polyline segments so draw to show the CAAT.Interpolator
- * instance.
- *
- * @return this
- */
- setInterpolator : function( interpolator, size ) {
- this.interpolator= interpolator;
- this.contour= interpolator.getContour(size || this.S);
- return this;
- },
- /**
- * Paint this actor.
- * @param director {CAAT.Director}
- * @param time {number} scene time.
- */
- paint : function( director, time ) {
- CAAT.InterpolatorActor.superclass.paint.call(this,director,time);
- if ( this.backgroundImage ) {
- return this;
- }
- if ( this.interpolator ) {
- var canvas= director.crc;
- var xs= (this.width-2*this.gap);
- var ys= (this.height-2*this.gap);
- canvas.beginPath();
- canvas.moveTo(
- this.gap + xs*this.contour[0].x,
- -this.gap + this.height - ys*this.contour[0].y);
- for( var i=1; i<this.contour.length; i++ ) {
- canvas.lineTo(
- this.gap + xs*this.contour[i].x,
- -this.gap + this.height - ys*this.contour[i].y);
- }
- canvas.strokeStyle= this.strokeStyle;
- canvas.stroke();
- }
- },
- /**
- * Return the represented interpolator.
- * @return {CAAT.Interpolator}
- */
- getInterpolator : function() {
- return this.interpolator;
- }
- };
- extend( CAAT.InterpolatorActor, CAAT.ActorContainer, null);
- })();/**
- * See LICENSE file.
- *
- * These classes encapsulate different kinds of paths.
- * LinearPath, defines an straight line path, just 2 points.
- * CurvePath, defines a path based on a Curve. Curves can be bezier quadric/cubic and catmull-rom.
- * Path, is a general purpose class, which composes a path of different path segments (Linear or Curve paths).
- *
- * A path, has an interpolator which stablishes the way the path is traversed (accelerating, by
- * easing functions, etc.). Normally, interpolators will be defined by CAAT,Interpolator instances, but
- * general Paths could be used as well.
- *
- **/
- (function() {
- /**
- * This is the abstract class that every path segment must conform to.
- * <p>
- * It is implemented by all path segment types, ie:
- * <ul>
- * <li>LinearPath
- * <li>CurvePath, base for all curves: quadric and cubic bezier.
- * <li>Path. A path built of different PathSegment implementations.
- * </ul>
- *
- * @constructor
- */
- CAAT.PathSegment = function() {
- this.bbox= new CAAT.Rectangle();
- return this;
- };
- CAAT.PathSegment.prototype = {
- color: '#000',
- length: 0,
- bbox: null,
- parent: null,
- /**
- * Set a PathSegment's parent
- * @param parent
- */
- setParent : function(parent) {
- this.parent= parent;
- return this;
- },
- setColor : function(color) {
- if ( color ) {
- this.color= color;
- }
- return this;
- },
- /**
- * Get path's last coordinate.
- * @return {CAAT.Point}
- */
- endCurvePosition : function() { },
- /**
- * Get path's starting coordinate.
- * @return {CAAT.Point}
- */
- startCurvePosition : function() { },
- /**
- * Set this path segment's points information.
- * @param points {Array<CAAT.Point>}
- */
- setPoints : function( points ) { },
- /**
- * Set a point from this path segment.
- * @param point {CAAT.Point}
- * @param index {integer} a point index.
- */
- setPoint : function( point, index ) { },
- /**
- * Get a coordinate on path.
- * The parameter time is normalized, that is, its values range from zero to one.
- * zero will mean <code>startCurvePosition</code> and one will be <code>endCurvePosition</code>. Other values
- * will be a position on the path relative to the path length. if the value is greater that 1, if will be set
- * to modulus 1.
- * @param time a float with a value between zero and 1 inclusive both.
- *
- * @return {CAAT.Point}
- */
- getPosition : function(time) { },
- /**
- * Gets Path length.
- * @return {number}
- */
- getLength : function() {
- return this.length;
- },
- /**
- * Gets the path bounding box (or the rectangle that contains the whole path).
- * @param rectangle a CAAT.Rectangle instance with the bounding box.
- * @return {CAAT.Rectangle}
- */
- getBoundingBox : function() {
- return this.bbox;
- },
- /**
- * Gets the number of control points needed to create the path.
- * Each PathSegment type can have different control points.
- * @return {number} an integer with the number of control points.
- */
- numControlPoints : function() { },
- /**
- * Gets CAAT.Point instance with the 2d position of a control point.
- * @param index an integer indicating the desired control point coordinate.
- * @return {CAAT.Point}
- */
- getControlPoint: function(index) { },
- /**
- * Instruments the path has finished building, and that no more segments will be added to it.
- * You could later add more PathSegments and <code>endPath</code> must be called again.
- */
- endPath : function() {},
- /**
- * Gets a polyline describing the path contour. The contour will be defined by as mush as iSize segments.
- * @param iSize an integer indicating the number of segments of the contour polyline.
- *
- * @return {[CAAT.Point]}
- */
- getContour : function(iSize) {},
- /**
- * Recalculate internal path structures.
- */
- updatePath : function(point) {},
- /**
- * Draw this path using RenderingContext2D drawing primitives.
- * The intention is to set a path or pathsegment as a clipping region.
- *
- * @param ctx {RenderingContext2D}
- */
- applyAsPath : function(director) {},
- /**
- * Transform this path with the given affinetransform matrix.
- * @param matrix
- */
- transform : function(matrix) {},
- drawHandle : function( ctx, x, y ) {
- var w= CAAT.Curve.prototype.HANDLE_SIZE/2;
- ctx.fillRect( x-w, y-w, w*2, w*2 );
- /*
- ctx.arc(
- this.points[0].x,
- this.points[0].y,
- CAAT.Curve.prototype.HANDLE_SIZE/2,
- 0,
- 2*Math.PI,
- false) ;
- */
- }
- };
- })();
- (function() {
- /**
- * Straight line segment path between two given points.
- *
- * @constructor
- * @extends CAAT.PathSegment
- */
- CAAT.LinearPath = function() {
- CAAT.LinearPath.superclass.constructor.call(this);
- this.points= [];
- this.points.push( new CAAT.Point() );
- this.points.push( new CAAT.Point() );
- this.newPosition= new CAAT.Point(0,0,0);
- return this;
- };
-
- CAAT.LinearPath.prototype= {
- points: null,
- newPosition: null, // spare holder for getPosition coordinate return.
- applyAsPath : function(director) {
- director.ctx.lineTo( this.points[0].x, this.points[1].y );
- },
- setPoint : function( point, index ) {
- if ( index===0 ) {
- this.points[0]= point;
- } else if ( index===1 ) {
- this.points[1]= point;
- }
- },
- /**
- * Update this segments length and bounding box info.
- */
- updatePath : function(point) {
- var x= this.points[1].x - this.points[0].x;
- var y= this.points[1].y - this.points[0].y;
- this.length= Math.sqrt( x*x+y*y );
- this.bbox.setEmpty();
- this.bbox.union( this.points[0].x, this.points[0].y );
- this.bbox.union( this.points[1].x, this.points[1].y );
- return this;
- },
- setPoints : function( points ) {
- this.points[0]= points[0];
- this.points[1]= points[1];
- this.updatePath();
- return this;
- },
- /**
- * Set this path segment's starting position.
- * @param x {number}
- * @param y {number}
- */
- setInitialPosition : function( x, y ) {
- this.points[0].x= x;
- this.points[0].y= y;
- this.newPosition.set(x,y);
- return this;
- },
- /**
- * Set this path segment's ending position.
- * @param finalX {number}
- * @param finalY {number}
- */
- setFinalPosition : function( finalX, finalY ) {
- this.points[1].x= finalX;
- this.points[1].y= finalY;
- return this;
- },
- /**
- * @inheritDoc
- */
- endCurvePosition : function() {
- return this.points[1];
- },
- /**
- * @inheritsDoc
- */
- startCurvePosition : function() {
- return this.points[0];
- },
- /**
- * @inheritsDoc
- */
- getPosition : function(time) {
- if ( time>1 || time<0 ) {
- time%=1;
- }
- if ( time<0 ) {
- time= 1+time;
- }
- this.newPosition.set(
- (this.points[0].x+(this.points[1].x-this.points[0].x)*time),
- (this.points[0].y+(this.points[1].y-this.points[0].y)*time) );
- return this.newPosition;
- },
- getPositionFromLength : function( len ) {
- return this.getPosition( len/this.length );
- },
- /**
- * Returns initial path segment point's x coordinate.
- * @return {number}
- */
- initialPositionX : function() {
- return this.points[0].x;
- },
- /**
- * Returns final path segment point's x coordinate.
- * @return {number}
- */
- finalPositionX : function() {
- return this.points[1].x;
- },
- /**
- * Draws this path segment on screen. Optionally it can draw handles for every control point, in
- * this case, start and ending path segment points.
- * @param director {CAAT.Director}
- * @param bDrawHandles {boolean}
- */
- paint : function(director, bDrawHandles) {
-
- var ctx= director.ctx;
- ctx.save();
- ctx.strokeStyle= this.color;
- ctx.beginPath();
- ctx.moveTo( this.points[0].x, this.points[0].y );
- ctx.lineTo( this.points[1].x, this.points[1].y );
- ctx.stroke();
- if ( bDrawHandles ) {
- ctx.globalAlpha=0.5;
- ctx.fillStyle='#7f7f00';
- ctx.beginPath();
- this.drawHandle( ctx, this.points[0].x, this.points[0].y );
- this.drawHandle( ctx, this.points[1].x, this.points[1].y );
- /*
- canvas.arc(
- this.points[0].x,
- this.points[0].y,
- CAAT.Curve.prototype.HANDLE_SIZE/2,
- 0,
- 2*Math.PI,
- false) ;
- canvas.arc(
- this.points[1].x,
- this.points[1].y,
- CAAT.Curve.prototype.HANDLE_SIZE/2,
- 0,
- 2*Math.PI,
- false) ;
- canvas.fill();
- */
- }
- ctx.restore();
- },
- /**
- * Get the number of control points. For this type of path segment, start and
- * ending path segment points. Defaults to 2.
- * @return {number}
- */
- numControlPoints : function() {
- return 2;
- },
- /**
- * @inheritsDoc
- */
- getControlPoint: function(index) {
- if ( 0===index ) {
- return this.points[0];
- } else if (1===index) {
- return this.points[1];
- }
- },
- /**
- * @inheritsDoc
- */
- getContour : function(iSize) {
- var contour= [];
- contour.push( this.getPosition(0).clone() );
- contour.push( this.getPosition(1).clone() );
- return contour;
- }
- };
- extend( CAAT.LinearPath, CAAT.PathSegment );
- })();
- (function() {
- /**
- * This class defines a Bezier cubic or quadric path segment.
- *
- * @constructor
- * @extends CAAT.PathSegment
- */
- CAAT.CurvePath = function() {
- CAAT.CurvePath.superclass.constructor.call(this);
- this.newPosition= new CAAT.Point(0,0,0);
- return this;
- };
-
- CAAT.CurvePath.prototype= {
- curve: null, // a CAAT.Bezier instance.
- newPosition: null, // spare holder for getPosition coordinate return.
- applyAsPath : function(director) {
- this.curve.applyAsPath(director);
- return this;
- },
- setPoint : function( point, index ) {
- if ( this.curve ) {
- this.curve.setPoint(point,index);
- }
- },
- /**
- * Set this curve segment's points.
- * @param points {Array<CAAT.Point>}
- */
- setPoints : function( points ) {
- var curve = new CAAT.Bezier();
- curve.setPoints(points);
- this.curve = curve;
- return this;
- },
- /**
- * Set the pathSegment as a CAAT.Bezier quadric instance.
- * Parameters are quadric coordinates control points.
- *
- * @param p0x {number}
- * @param p0y {number}
- * @param p1x {number}
- * @param p1y {number}
- * @param p2x {number}
- * @param p2y {number}
- * @return this
- */
- setQuadric : function(p0x,p0y, p1x,p1y, p2x,p2y) {
- var curve = new CAAT.Bezier();
- curve.setQuadric(p0x,p0y, p1x,p1y, p2x,p2y);
- this.curve = curve;
- this.updatePath();
- return this;
- },
- /**
- * Set the pathSegment as a CAAT.Bezier cubic instance.
- * Parameters are cubic coordinates control points.
- * @param p0x {number}
- * @param p0y {number}
- * @param p1x {number}
- * @param p1y {number}
- * @param p2x {number}
- * @param p2y {number}
- * @param p3x {number}
- * @param p3y {number}
- * @return this
- */
- setCubic : function(p0x,p0y, p1x,p1y, p2x,p2y, p3x,p3y) {
- var curve = new CAAT.Bezier();
- curve.setCubic(p0x,p0y, p1x,p1y, p2x,p2y, p3x,p3y);
- this.curve = curve;
- this.updatePath();
- return this;
- },
- /**
- * @inheritDoc
- */
- updatePath : function(point) {
- this.curve.update();
- this.length= this.curve.getLength();
- this.curve.getBoundingBox(this.bbox);
- return this;
- },
- /**
- * @inheritDoc
- */
- getPosition : function(time) {
- if ( time>1 || time<0 ) {
- time%=1;
- }
- if ( time<0 ) {
- time= 1+time;
- }
- this.curve.solve(this.newPosition, time);
- return this.newPosition;
- },
- /**
- * Gets the coordinate on the path relative to the path length.
- * @param iLength {number} the length at which the coordinate will be taken from.
- * @return {CAAT.Point} a CAAT.Point instance with the coordinate on the path corresponding to the
- * iLenght parameter relative to segment's length.
- */
- getPositionFromLength : function(iLength) {
- this.curve.solve( this.newPosition, iLength/this.length );
- return this.newPosition;
- },
- /**
- * Get path segment's first point's x coordinate.
- * @return {number}
- */
- initialPositionX : function() {
- return this.curve.coordlist[0].x;
- },
- /**
- * Get path segment's last point's y coordinate.
- * @return {number}
- */
- finalPositionX : function() {
- return this.curve.coordlist[this.curve.coordlist.length-1].x;
- },
- /**
- * @inheritDoc
- * @param director {CAAT.Director}
- * @param bDrawHandles {boolean}
- */
- paint : function( director,bDrawHandles ) {
- this.curve.drawHandles= bDrawHandles;
- director.ctx.strokeStyle= this.color;
- this.curve.paint(director,bDrawHandles);
- },
- /**
- * @inheritDoc
- */
- numControlPoints : function() {
- return this.curve.coordlist.length;
- },
- /**
- * @inheritDoc
- * @param index
- */
- getControlPoint : function(index) {
- return this.curve.coordlist[index];
- },
- /**
- * @inheritDoc
- */
- endCurvePosition : function() {
- return this.curve.endCurvePosition();
- },
- /**
- * @inheritDoc
- */
- startCurvePosition : function() {
- return this.curve.startCurvePosition();
- },
- /**
- * @inheritDoc
- * @param iSize
- */
- getContour : function(iSize) {
- var contour=[];
- for( var i=0; i<=iSize; i++ ) {
- contour.push( {x: i/iSize, y: this.getPosition(i/iSize).y} );
- }
- return contour;
- }
- };
- extend( CAAT.CurvePath, CAAT.PathSegment, null);
-
- })();
- (function() {
- CAAT.ShapePath= function() {
- CAAT.ShapePath.superclass.constructor.call(this);
- this.points= [];
- this.points.push( new CAAT.Point() );
- this.points.push( new CAAT.Point() );
- this.points.push( new CAAT.Point() );
- this.points.push( new CAAT.Point() );
- this.points.push( new CAAT.Point() );
- this.newPosition= new CAAT.Point();
- return this;
- };
- CAAT.ShapePath.prototype= {
- points: null,
- length: -1,
- cw: true, // should be clock wise traversed ?
- bbox: null,
- newPosition: null, // spare point for calculations
- applyAsPath : function(director) {
- var ctx= director.ctx;
- //ctx.rect( this.bbox.x, this.bbox.y, this.bbox.width, this.bbox.height );
- if ( this.cw ) {
- ctx.lineTo( this.points[0].x, this.points[0].y );
- ctx.lineTo( this.points[1].x, this.points[1].y );
- ctx.lineTo( this.points[2].x, this.points[2].y );
- ctx.lineTo( this.points[3].x, this.points[3].y );
- ctx.lineTo( this.points[4].x, this.points[4].y );
- } else {
- ctx.lineTo( this.points[4].x, this.points[4].y );
- ctx.lineTo( this.points[3].x, this.points[3].y );
- ctx.lineTo( this.points[2].x, this.points[2].y );
- ctx.lineTo( this.points[1].x, this.points[1].y );
- ctx.lineTo( this.points[0].x, this.points[0].y );
- }
- return this;
- },
- setPoint : function( point, index ) {
- if ( index>=0 && index<this.points.length ) {
- this.points[index]= point;
- }
- },
- /**
- * An array of {CAAT.Point} composed of two points.
- * @param points {Array<CAAT.Point>}
- */
- setPoints : function( points ) {
- this.points= [];
- this.points.push( points[0] );
- this.points.push( new CAAT.Point().set(points[1].x, points[0].y) );
- this.points.push( points[1] );
- this.points.push( new CAAT.Point().set(points[0].x, points[1].y) );
- this.points.push( points[0].clone() );
- this.updatePath();
- return this;
- },
- setClockWise : function(cw) {
- this.cw= cw!==undefined ? cw : true;
- return this;
- },
- isClockWise : function() {
- return this.cw;
- },
- /**
- * Set this path segment's starting position.
- * This method should not be called again after setFinalPosition has been called.
- * @param x {number}
- * @param y {number}
- */
- setInitialPosition : function( x, y ) {
- for( var i=0, l= this.points.length; i<l; i++ ) {
- this.points[i].x= x;
- this.points[i].y= y;
- }
- return this;
- },
- /**
- * Set a rectangle from points[0] to (finalX, finalY)
- * @param finalX {number}
- * @param finalY {number}
- */
- setFinalPosition : function( finalX, finalY ) {
- this.points[2].x= finalX;
- this.points[2].y= finalY;
- this.points[1].x= finalX;
- this.points[1].y= this.points[0].y;
- this.points[3].x= this.points[0].x;
- this.points[3].y= finalY;
- this.points[4].x= this.points[0].x;
- this.points[4].y= this.points[0].y;
- this.updatePath();
- return this;
- },
- /**
- * @inheritDoc
- */
- endCurvePosition : function() {
- return this.points[4];
- },
- /**
- * @inheritsDoc
- */
- startCurvePosition : function() {
- return this.points[0];
- },
- /**
- * @inheritsDoc
- */
- getPosition : function(time) {
- if ( time>1 || time<0 ) {
- time%=1;
- }
- if ( time<0 ) {
- time= 1+time;
- }
- if ( -1===this.length ) {
- this.newPosition.set(0,0);
- } else {
- var w= this.bbox.width / this.length;
- var h= this.bbox.height / this.length;
- var accTime= 0;
- var times;
- var segments;
- var index= 0;
- if ( this.cw ) {
- segments= [0,1,2,3,4];
- times= [w,h,w,h];
- } else {
- segments= [4,3,2,1,0];
- times= [h,w,h,w];
- }
- while( index<times.length ) {
- if ( accTime+times[index]<time ) {
- accTime+= times[index];
- index++;
- } else {
- break;
- }
- }
- time-=accTime;
- var p0= segments[index];
- var p1= segments[index+1];
- // index tiene el indice del segmento en tiempo.
- this.newPosition.set(
- (this.points[p0].x + (this.points[p1].x - this.points[p0].x)*time/times[index]),
- (this.points[p0].y + (this.points[p1].y - this.points[p0].y)*time/times[index]) );
- }
- return this.newPosition;
- },
- /**
- * Returns initial path segment point's x coordinate.
- * @return {number}
- */
- initialPositionX : function() {
- return this.points[0].x;
- },
- /**
- * Returns final path segment point's x coordinate.
- * @return {number}
- */
- finalPositionX : function() {
- return this.points[2].x;
- },
- /**
- * Draws this path segment on screen. Optionally it can draw handles for every control point, in
- * this case, start and ending path segment points.
- * @param director {CAAT.Director}
- * @param bDrawHandles {boolean}
- */
- paint : function(director, bDrawHandles) {
- var ctx= director.ctx;
- ctx.save();
- ctx.strokeStyle= this.color;
- ctx.beginPath();
- ctx.strokeRect(
- this.bbox.x, this.bbox.y,
- this.bbox.width, this.bbox.height );
- if ( bDrawHandles ) {
- ctx.globalAlpha=0.5;
- ctx.fillStyle='#7f7f00';
- for( var i=0; i<this.points.length; i++ ) {
- this.drawHandle( ctx, this.points[i].x, this.points[i].y );
- /*
- canvas.beginPath();
- canvas.arc(
- this.points[i].x,
- this.points[i].y,
- CAAT.Curve.prototype.HANDLE_SIZE/2,
- 0,
- 2*Math.PI,
- false) ;
- canvas.fill();
- */
- }
- }
- ctx.restore();
- },
- /**
- * Get the number of control points. For this type of path segment, start and
- * ending path segment points. Defaults to 2.
- * @return {number}
- */
- numControlPoints : function() {
- return this.points.length;
- },
- /**
- * @inheritsDoc
- */
- getControlPoint: function(index) {
- return this.points[index];
- },
- /**
- * @inheritsDoc
- */
- getContour : function(iSize) {
- var contour= [];
- for( var i=0; i<this.points.length; i++ ) {
- contour.push( this.points[i] );
- }
- return contour;
- },
- updatePath : function(point) {
- if ( point ) {
- if ( point===this.points[0] ) {
- this.points[1].y= point.y;
- this.points[3].x= point.x;
- } else if ( point===this.points[1] ) {
- this.points[0].y= point.y;
- this.points[2].x= point.x;
- } else if ( point===this.points[2] ) {
- this.points[3].y= point.y;
- this.points[1].x= point.x;
- } else if ( point===this.points[3] ) {
- this.points[0].x= point.x;
- this.points[2].y= point.y;
- }
- this.points[4].x= this.points[0].x;
- this.points[4].y= this.points[0].y;
- }
- this.bbox.setEmpty();
- var minx= Number.MAX_VALUE, miny= Number.MAX_VALUE, maxx= -Number.MAX_VALUE, maxy= -Number.MAX_VALUE;
- for( var i=0; i<4; i++ ) {
- this.bbox.union( this.points[i].x, this.points[i].y );
- }
- this.length= 2*this.bbox.width + 2*this.bbox.height;
- this.points[0].x= this.bbox.x;
- this.points[0].y= this.bbox.y;
- this.points[1].x= this.bbox.x+this.bbox.width;
- this.points[1].y= this.bbox.y;
- this.points[2].x= this.bbox.x + this.bbox.width;
- this.points[2].y= this.bbox.y + this.bbox.height;
- this.points[3].x= this.bbox.x;
- this.points[3].y= this.bbox.y + this.bbox.height;
- this.points[4].x= this.bbox.x;
- this.points[4].y= this.bbox.y;
- return this;
- }
- }
- extend( CAAT.ShapePath, CAAT.PathSegment );
- })();
- (function() {
- /**
- * This class the top most abstraction of path related classes in CAAT. It defines a path composes un
- * an unlimited number of path segments including CAAT.Path instances.
- * <p>
- * Every operation of the CAAT.PathSegment interface is performed for every path segment. In example,
- * the method <code>getLength</code> will contain the sum of every path segment's length.
- * <p>
- * An example of CAAT.Path will be as follows:
- * <code>
- * path.beginPath(x,y).<br>
- * addLineTo(x1,y1).<br>
- * addLineTo(x2,y2).<br>
- * addQuadricTo(...).<br>
- * addCubicTo(...).<br>
- * endPath();<br>
- * </code>
- * <p>
- * This code creates a path composed of four chained segments, starting at (x,y) and having each
- * segment starting where the previous one ended.
- * <p>
- * This class is intended to wrap the other kind of path segment classes when just a one segmented
- * path is to be defined. The methods <code>setLinear, setCubic and setQuadrid</code> will make
- * a CAAT.Path instance to be defined by just one segment.
- *
- * @constructor
- * @extends CAAT.PathSegment
- */
- CAAT.Path= function() {
- CAAT.Path.superclass.constructor.call(this);
- this.newPosition= new CAAT.Point(0,0,0);
- this.pathSegments= [];
- this.behaviorList= [];
- this.matrix= new CAAT.Matrix();
- this.tmpMatrix= new CAAT.Matrix();
-
- return this;
- };
-
- CAAT.Path.prototype= {
-
- pathSegments: null, // a collection of CAAT.PathSegment instances.
- pathSegmentDurationTime: null, // precomputed segment duration relative to segment legnth/path length
- pathSegmentStartTime: null, // precomputed segment start time relative to segment legnth/path length and duration.
- newPosition: null, // spare CAAT.Point.
-
- pathLength: -1, // path length (sum of every segment length)
- /*
- starting path position
- */
- beginPathX: -1,
- beginPathY: -1,
- /*
- last path coordinates position (using when building the path).
- */
- trackPathX: -1,
- trackPathY: -1,
- /*
- needed to drag control points.
- */
- ax: -1,
- ay: -1,
- point: [],
- interactive: true,
- behaviorList: null,
- /** rotation behavior info **/
- rb_angle: 0,
- rb_rotateAnchorX: .5,
- rb_rotateAnchorY: .5,
- /** scale behavior info **/
- sb_scaleX: 1,
- sb_scaleY: 1,
- sb_scaleAnchorX: .5,
- sb_scaleAnchorY: .5,
- tAnchorX: 0,
- tAnchorY: 0,
- /** translate behavior info **/
- tb_x: 0,
- tb_y: 0,
- /** behavior affine transformation matrix **/
- matrix: null,
- tmpMatrix: null,
- /** if behaviors are to be applied, save original path points **/
- pathPoints: null,
- /** path width and height **/
- width: 0,
- height: 0,
- clipOffsetX : 0,
- clipOffsetY : 0,
- applyAsPath : function(director) {
- var ctx= director.ctx;
- director.modelViewMatrix.transformRenderingContext( ctx );
- ctx.beginPath();
- ctx.globalCompositeOperation= 'source-out';
- ctx.moveTo(
- this.getFirstPathSegment().startCurvePosition().x,
- this.getFirstPathSegment().startCurvePosition().y
- );
- for( var i=0; i<this.pathSegments.length; i++ ) {
- this.pathSegments[i].applyAsPath(director);
- }
- ctx.globalCompositeOperation= 'source-over';
- return this;
- },
- /**
- * Set whether this path should paint handles for every control point.
- * @param interactive {boolean}.
- */
- setInteractive : function(interactive) {
- this.interactive= interactive;
- return this;
- },
- getFirstPathSegment : function() {
- return this.pathSegments.length ?
- this.pathSegments[0] :
- null;
- },
- getLastPathSegment : function() {
- return this.pathSegments.length ?
- this.pathSegments[ this.pathSegments.length-1 ] :
- null;
- },
- /**
- * Return the last point of the last path segment of this compound path.
- * @return {CAAT.Point}
- */
- endCurvePosition : function() {
- if ( this.pathSegments.length ) {
- return this.pathSegments[ this.pathSegments.length-1 ].endCurvePosition();
- } else {
- return new CAAT.Point().set( this.beginPathX, this.beginPathY );
- }
- },
- /**
- * Return the first point of the first path segment of this compound path.
- * @return {CAAT.Point}
- */
- startCurvePosition : function() {
- return this.pathSegments[ 0 ].startCurvePosition();
- },
- /**
- * Return the last path segment added to this path.
- * @return {CAAT.PathSegment}
- */
- getCurrentPathSegment : function() {
- return this.pathSegments[ this.pathSegments.length-1 ];
- },
- /**
- * Set the path to be composed by a single LinearPath segment.
- * @param x0 {number}
- * @param y0 {number}
- * @param x1 {number}
- * @param y1 {number}
- * @return this
- */
- setLinear : function(x0,y0,x1,y1) {
- this.beginPath(x0,y0);
- this.addLineTo(x1,y1);
- this.endPath();
- return this;
- },
- /**
- * Set this path to be composed by a single Quadric Bezier path segment.
- * @param x0 {number}
- * @param y0 {number}
- * @param x1 {number}
- * @param y1 {number}
- * @param x2 {number}
- * @param y2 {number}
- * @return this
- */
- setQuadric : function(x0,y0,x1,y1,x2,y2) {
- this.beginPath(x0,y0);
- this.addQuadricTo(x1,y1,x2,y2);
- this.endPath();
- return this;
- },
- /**
- * Sets this path to be composed by a single Cubic Bezier path segment.
- * @param x0 {number}
- * @param y0 {number}
- * @param x1 {number}
- * @param y1 {number}
- * @param x2 {number}
- * @param y2 {number}
- * @param x3 {number}
- * @param y3 {number}
- *
- * @return this
- */
- setCubic : function(x0,y0,x1,y1,x2,y2,x3,y3) {
- this.beginPath(x0,y0);
- this.addCubicTo(x1,y1,x2,y2,x3,y3);
- this.endPath();
- return this;
- },
- setRectangle : function(x0,y0, x1,y1) {
- this.beginPath(x0,y0);
- this.addRectangleTo(x1,y1);
- this.endPath();
- return this;
- },
- setCatmullRom : function( points, closed ) {
- if ( closed ) {
- points = points.slice(0)
- points.unshift(points[points.length-1])
- points.push(points[1])
- points.push(points[2])
- }
- for( var i=1; i<points.length-2; i++ ) {
- var segment= new CAAT.CurvePath().setColor("#000").setParent(this);
- var cm= new CAAT.CatmullRom().setCurve(
- points[ i-1 ],
- points[ i ],
- points[ i+1 ],
- points[ i+2 ]
- );
- segment.curve= cm;
- this.pathSegments.push(segment);
- }
- return this;
- },
- /**
- * Add a CAAT.PathSegment instance to this path.
- * @param pathSegment {CAAT.PathSegment}
- * @return this
- *
- * @deprecated
- */
- addSegment : function(pathSegment) {
- pathSegment.setParent(this);
- this.pathSegments.push(pathSegment);
- return this;
- },
- addRectangleTo : function( x1,y1, cw, color ) {
- var r= new CAAT.ShapePath();
- r.setPoints([
- this.endCurvePosition(),
- new CAAT.Point().set(x1,y1)
- ]);
- r.setClockWise(cw);
- r.setColor(color);
- r.setParent(this);
- this.pathSegments.push(r);
- return this;
- },
- /**
- * Add a Quadric Bezier path segment to this path.
- * The segment starts in the current last path coordinate.
- * @param px1 {number}
- * @param py1 {number}
- * @param px2 {number}
- * @param py2 {number}
- * @param color {color=}. optional parameter. determines the color to draw the segment with (if
- * being drawn by a CAAT.PathActor).
- *
- * @return this
- */
- addQuadricTo : function( px1,py1, px2,py2, color ) {
- var bezier= new CAAT.Bezier();
- bezier.setPoints(
- [
- this.endCurvePosition(),
- new CAAT.Point().set(px1,py1),
- new CAAT.Point().set(px2,py2)
- ]);
- this.trackPathX= px2;
- this.trackPathY= py2;
-
- var segment= new CAAT.CurvePath().setColor(color).setParent(this);
- segment.curve= bezier;
- this.pathSegments.push(segment);
- return this;
- },
- /**
- * Add a Cubic Bezier segment to this path.
- * The segment starts in the current last path coordinate.
- * @param px1 {number}
- * @param py1 {number}
- * @param px2 {number}
- * @param py2 {number}
- * @param px3 {number}
- * @param py3 {number}
- * @param color {color=}. optional parameter. determines the color to draw the segment with (if
- * being drawn by a CAAT.PathActor).
- *
- * @return this
- */
- addCubicTo : function( px1,py1, px2,py2, px3,py3, color ) {
- var bezier= new CAAT.Bezier();
- bezier.setPoints(
- [
- this.endCurvePosition(),
- new CAAT.Point().set(px1,py1),
- new CAAT.Point().set(px2,py2),
- new CAAT.Point().set(px3,py3)
- ]);
- this.trackPathX= px3;
- this.trackPathY= py3;
-
- var segment= new CAAT.CurvePath().setColor(color).setParent(this);
- segment.curve= bezier;
- this.pathSegments.push(segment);
- return this;
- },
- /**
- * Add a Catmull-Rom segment to this path.
- * The segment starts in the current last path coordinate.
- * @param px1 {number}
- * @param py1 {number}
- * @param px2 {number}
- * @param py2 {number}
- * @param px3 {number}
- * @param py3 {number}
- * @param color {color=}. optional parameter. determines the color to draw the segment with (if
- * being drawn by a CAAT.PathActor).
- *
- * @return this
- */
- addCatmullTo : function( px1,py1, px2,py2, px3,py3, color ) {
- var curve= new CAAT.CatmullRom().setColor(color);
- curve.setCurve(this.trackPathX,this.trackPathY, px1,py1, px2,py2, px3,py3);
- this.trackPathX= px3;
- this.trackPathY= py3;
-
- var segment= new CAAT.CurvePath().setParent(this);
- segment.curve= curve;
- this.pathSegments.push(segment);
- return this;
- },
- /**
- * Adds a line segment to this path.
- * The segment starts in the current last path coordinate.
- * @param px1 {number}
- * @param py1 {number}
- * @param color {color=}. optional parameter. determines the color to draw the segment with (if
- * being drawn by a CAAT.PathActor).
- *
- * @return this
- */
- addLineTo : function( px1,py1, color ) {
- var segment= new CAAT.LinearPath().setColor(color);
- segment.setPoints( [
- this.endCurvePosition(),
- new CAAT.Point().set(px1,py1)
- ]);
- segment.setParent(this);
- this.trackPathX= px1;
- this.trackPathY= py1;
-
- this.pathSegments.push(segment);
- return this;
- },
- /**
- * Set the path's starting point. The method startCurvePosition will return this coordinate.
- * <p>
- * If a call to any method of the form <code>add<Segment>To</code> is called before this calling
- * this method, they will assume to start at -1,-1 and probably you'll get the wrong path.
- * @param px0 {number}
- * @param py0 {number}
- *
- * @return this
- */
- beginPath : function( px0, py0 ) {
- this.trackPathX= px0;
- this.trackPathY= py0;
- this.beginPathX= px0;
- this.beginPathY= py0;
- return this;
- },
- /**
- * <del>Close the path by adding a line path segment from the current last path
- * coordinate to startCurvePosition coordinate</del>.
- * <p>
- * This method closes a path by setting its last path segment's last control point
- * to be the first path segment's first control point.
- * <p>
- * This method also sets the path as finished, and calculates all path's information
- * such as length and bounding box.
- *
- * @return this
- */
- closePath : function() {
- this.getLastPathSegment().setPoint(
- this.getFirstPathSegment().startCurvePosition(),
- this.getLastPathSegment().numControlPoints()-1 );
- this.trackPathX= this.beginPathX;
- this.trackPathY= this.beginPathY;
-
- this.endPath();
- return this;
- },
- /**
- * Finishes the process of building the path. It involves calculating each path segments length
- * and proportional length related to a normalized path length of 1.
- * It also sets current paths length.
- * These calculi are needed to traverse the path appropriately.
- * <p>
- * This method must be called explicitly, except when closing a path (that is, calling the
- * method closePath) which calls this method as well.
- *
- * @return this
- */
- endPath : function() {
- this.pathSegmentStartTime=[];
- this.pathSegmentDurationTime= [];
- this.updatePath();
- return this;
- },
- /**
- * This method, returns a CAAT.Point instance indicating a coordinate in the path.
- * The returned coordinate is the corresponding to normalizing the path's length to 1,
- * and then finding what path segment and what coordinate in that path segment corresponds
- * for the input time parameter.
- * <p>
- * The parameter time must be a value ranging 0..1.
- * If not constrained to these values, the parameter will be modulus 1, and then, if less
- * than 0, be normalized to 1+time, so that the value always ranges from 0 to 1.
- * <p>
- * This method is needed when traversing the path throughout a CAAT.Interpolator instance.
- *
- * @param time a value between 0 and 1 both inclusive. 0 will return path's starting coordinate.
- * 1 will return path's end coordinate.
- *
- * @return {CAAT.Point}
- */
- getPosition : function(time) {
- if ( time>1 || time<0 ) {
- time%=1;
- }
- if ( time<0 ) {
- time= 1+time;
- }
- /*
- var found= false;
- for( var i=0; i<this.pathSegments.length; i++ ) {
- if (this.pathSegmentStartTime[i]<=time && time<=this.pathSegmentStartTime[i]+this.pathSegmentDurationTime[i]) {
- time= this.pathSegmentDurationTime[i] ?
- (time-this.pathSegmentStartTime[i])/this.pathSegmentDurationTime[i] :
- 0;
- var pointInPath= this.pathSegments[i].getPosition(time);
- this.newPosition.x= pointInPath.x;
- this.newPosition.y= pointInPath.y;
- found= true;
- break;
- }
- }
- return found ? this.newPosition : this.endCurvePosition();
- */
- var ps= this.pathSegments;
- var psst= this.pathSegmentStartTime;
- var psdt= this.pathSegmentDurationTime;
- var l= 0;
- var r= ps.length;
- var m;
- var np= this.newPosition;
- var psstv;
- while( l!==r ) {
- m= ((r+l)/2)|0;
- psstv= psst[m];
- if ( psstv<=time && time<=psstv+psdt[m]) {
- time= psdt[m] ?
- (time-psstv)/psdt[m] :
- 0;
- var pointInPath= ps[m].getPosition(time);
- np.x= pointInPath.x;
- np.y= pointInPath.y;
- return np;
- } else if ( time<psstv ) {
- r= m;
- } else /*if ( time>=psstv )*/ {
- l= m+1;
- }
- }
- return this.endCurvePosition();
- },
- /**
- * Analogously to the method getPosition, this method returns a CAAT.Point instance with
- * the coordinate on the path that corresponds to the given length. The input length is
- * related to path's length.
- *
- * @param iLength {number} a float with the target length.
- * @return {CAAT.Point}
- */
- getPositionFromLength : function(iLength) {
-
- iLength%=this.getLength();
- if (iLength<0 ) {
- iLength+= this.getLength();
- }
-
- var accLength=0;
-
- for( var i=0; i<this.pathSegments.length; i++ ) {
- if (accLength<=iLength && iLength<=this.pathSegments[i].getLength()+accLength) {
- iLength-= accLength;
- var pointInPath= this.pathSegments[i].getPositionFromLength(iLength);
- this.newPosition.x= pointInPath.x;
- this.newPosition.y= pointInPath.y;
- break;
- }
- accLength+= this.pathSegments[i].getLength();
- }
-
- return this.newPosition;
- },
- /**
- * Paints the path.
- * This method is called by CAAT.PathActor instances.
- * If the path is set as interactive (by default) path segment will draw curve modification
- * handles as well.
- *
- * @param director {CAAT.Director} a CAAT.Director instance.
- */
- paint : function( director ) {
- for( var i=0; i<this.pathSegments.length; i++ ) {
- this.pathSegments[i].paint(director,this.interactive);
- }
- },
- /**
- * Method invoked when a CAAT.PathActor stops dragging a control point.
- */
- release : function() {
- this.ax= -1;
- this.ay= -1;
- },
- /**
- * Returns an integer with the number of path segments that conform this path.
- * @return {number}
- */
- getNumSegments : function() {
- return this.pathSegments.length;
- },
- /**
- * Gets a CAAT.PathSegment instance.
- * @param index {number} the index of the desired CAAT.PathSegment.
- * @return CAAT.PathSegment
- */
- getSegment : function(index) {
- return this.pathSegments[index];
- },
- numControlPoints : function() {
- return this.points.length;
- },
- getControlPoint : function(index) {
- return this.points[index];
- },
- /**
- * Indicates that some path control point has changed, and that the path must recalculate
- * its internal data, ie: length and bbox.
- */
- updatePath : function(point, callback) {
- var i,j;
- this.length=0;
- this.bbox.setEmpty();
- this.points= [];
- var xmin= Number.MAX_VALUE, ymin= Number.MAX_VALUE;
- for( i=0; i<this.pathSegments.length; i++ ) {
- this.pathSegments[i].updatePath(point);
- this.length+= this.pathSegments[i].getLength();
- this.bbox.unionRectangle( this.pathSegments[i].bbox );
- for( j=0; j<this.pathSegments[i].numControlPoints(); j++ ) {
- var pt= this.pathSegments[i].getControlPoint( j );
- this.points.push( pt );
- if ( pt.x < xmin ) {
- xmin= pt.x;
- }
- if ( pt.y < ymin ) {
- ymin= pt.y;
- }
- }
- }
- this.clipOffsetX= -xmin;
- this.clipOffsetY= -ymin;
- this.width= this.bbox.width;
- this.height= this.bbox.height;
- this.setLocation( this.bbox.x, this.bbox.y );
- this.bbox.x= 0;
- this.bbox.y= 0;
- this.bbox.x1= this.width;
- this.bbox.y1= this.height;
- this.pathSegmentStartTime= [];
- this.pathSegmentDurationTime= [];
-
- var i;
- for( i=0; i<this.pathSegments.length; i++) {
- this.pathSegmentStartTime.push(0);
- this.pathSegmentDurationTime.push(0);
- }
- for( i=0; i<this.pathSegments.length; i++) {
- this.pathSegmentDurationTime[i]= this.getLength() ? this.pathSegments[i].getLength()/this.getLength() : 0;
- if ( i>0 ) {
- this.pathSegmentStartTime[i]= this.pathSegmentStartTime[i-1]+this.pathSegmentDurationTime[i-1];
- } else {
- this.pathSegmentStartTime[0]= 0;
- }
- this.pathSegments[i].endPath();
- }
- this.extractPathPoints();
- if ( typeof callback!=='undefined' ) {
- callback(this);
- }
- return this;
- },
- /**
- * Sent by a CAAT.PathActor instance object to try to drag a path's control point.
- * @param x {number}
- * @param y {number}
- */
- press: function(x,y) {
- if (!this.interactive) {
- return;
- }
- var HS= CAAT.Curve.prototype.HANDLE_SIZE/2;
- for( var i=0; i<this.pathSegments.length; i++ ) {
- for( var j=0; j<this.pathSegments[i].numControlPoints(); j++ ) {
- var point= this.pathSegments[i].getControlPoint(j);
- if ( x>=point.x-HS &&
- y>=point.y-HS &&
- x<point.x+HS &&
- y<point.y+HS ) {
-
- this.point= point;
- return;
- }
- }
- }
- this.point= null;
- },
- /**
- * Drags a path's control point.
- * If the method press has not set needed internal data to drag a control point, this
- * method will do nothing, regardless the user is dragging on the CAAT.PathActor delegate.
- * @param x {number}
- * @param y {number}
- */
- drag : function(x,y,callback) {
- if (!this.interactive) {
- return;
- }
- if ( null===this.point ) {
- return;
- }
-
- if ( -1===this.ax || -1===this.ay ) {
- this.ax= x;
- this.ay= y;
- }
-
- this.point.x+= x-this.ax;
- this.point.y+= y-this.ay;
- this.ax= x;
- this.ay= y;
- this.updatePath(this.point,callback);
- },
- /**
- * Returns a collection of CAAT.Point objects which conform a path's contour.
- * @param iSize {number}. Number of samples for each path segment.
- * @return {[CAAT.Point]}
- */
- getContour : function(iSize) {
- var contour=[];
- for( var i=0; i<=iSize; i++ ) {
- contour.push( new CAAT.Point().set( i/iSize, this.getPosition(i/iSize).y, 0 ) );
- }
- return contour;
- },
- /**
- * Reposition this path points.
- * This operation will only take place if the supplied points array equals in size to
- * this path's already set points.
- * @param points {Array<CAAT.Point>}
- */
- setPoints : function( points ) {
- if ( this.points.length===points.length ) {
- for( var i=0; i<points.length; i++ ) {
- this.points[i].x= points[i].x;
- this.points[i].y= points[i].y;
- }
- }
- return this;
- },
- /**
- * Set a point from this path.
- * @param point {CAAT.Point}
- * @param index {integer} a point index.
- */
- setPoint : function( point, index ) {
- if ( index>=0 && index<this.points.length ) {
- this.points[index].x= point.x;
- this.points[index].y= point.y;
- }
- return this;
- },
- /**
- * Removes all behaviors from an Actor.
- * @return this
- */
- emptyBehaviorList : function() {
- this.behaviorList=[];
- return this;
- },
- extractPathPoints : function() {
- if ( !this.pathPoints ) {
- var i;
- this.pathPoints= [];
- for ( i=0; i<this.numControlPoints(); i++ ) {
- this.pathPoints.push( this.getControlPoint(i).clone() );
- }
- }
- return this;
- },
- /**
- * Add a Behavior to the Actor.
- * An Actor accepts an undefined number of Behaviors.
- *
- * @param behavior {CAAT.Behavior} a CAAT.Behavior instance
- * @return this
- */
- addBehavior : function( behavior ) {
- this.behaviorList.push(behavior);
- // this.extractPathPoints();
- return this;
- },
- /**
- * Remove a Behavior from the Actor.
- * If the Behavior is not present at the actor behavior collection nothing happends.
- *
- * @param behavior {CAAT.Behavior} a CAAT.Behavior instance.
- */
- removeBehaviour : function( behavior ) {
- var n= this.behaviorList.length-1;
- while(n) {
- if ( this.behaviorList[n]===behavior ) {
- this.behaviorList.splice(n,1);
- return this;
- }
- }
- return this;
- },
- /**
- * Remove a Behavior with id param as behavior identifier from this actor.
- * This function will remove ALL behavior instances with the given id.
- *
- * @param id {number} an integer.
- * return this;
- */
- removeBehaviorById : function( id ) {
- for( var n=0; n<this.behaviorList.length; n++ ) {
- if ( this.behaviorList[n].id===id) {
- this.behaviorList.splice(n,1);
- }
- }
- return this;
- },
- applyBehaviors : function(time) {
- // if (this.behaviorList.length) {
- for( var i=0; i<this.behaviorList.length; i++ ) {
- this.behaviorList[i].apply(time,this);
- }
- /** calculate behavior affine transform matrix **/
- this.setATMatrix();
- for (i = 0; i < this.numControlPoints(); i++) {
- this.setPoint(
- this.matrix.transformCoord(
- this.pathPoints[i].clone().translate( this.clipOffsetX, this.clipOffsetY )), i);
- }
- // }
- return this;
- },
- setATMatrix : function() {
- this.matrix.identity();
- var m= this.tmpMatrix.identity();
- var mm= this.matrix.matrix;
- var c,s,_m00,_m01,_m10,_m11;
- var mm0, mm1, mm2, mm3, mm4, mm5;
- var bbox= this.bbox;
- var bbw= bbox.width ;
- var bbh= bbox.height ;
- var bbx= bbox.x;
- var bby= bbox.y
- mm0= 1;
- mm1= 0;
- mm3= 0;
- mm4= 1;
- mm2= this.tb_x - bbx - this.tAnchorX * bbw;
- mm5= this.tb_y - bby - this.tAnchorY * bbh;
- if ( this.rb_angle ) {
- var rbx= (this.rb_rotateAnchorX*bbw + bbx);
- var rby= (this.rb_rotateAnchorY*bbh + bby);
- mm2+= mm0*rbx + mm1*rby;
- mm5+= mm3*rbx + mm4*rby;
- c= Math.cos( this.rb_angle );
- s= Math.sin( this.rb_angle);
- _m00= mm0;
- _m01= mm1;
- _m10= mm3;
- _m11= mm4;
- mm0= _m00*c + _m01*s;
- mm1= -_m00*s + _m01*c;
- mm3= _m10*c + _m11*s;
- mm4= -_m10*s + _m11*c;
- mm2+= -mm0*rbx - mm1*rby;
- mm5+= -mm3*rbx - mm4*rby;
- }
- if ( this.sb_scaleX!=1 || this.sb_scaleY!=1 ) {
- var sbx= (this.sb_scaleAnchorX*bbw + bbx);
- var sby= (this.sb_scaleAnchorY*bbh + bby);
- mm2+= mm0*sbx + mm1*sby;
- mm5+= mm3*sbx + mm4*sby;
- mm0= mm0*this.sb_scaleX;
- mm1= mm1*this.sb_scaleY;
- mm3= mm3*this.sb_scaleX;
- mm4= mm4*this.sb_scaleY;
- mm2+= -mm0*sbx - mm1*sby;
- mm5+= -mm3*sbx - mm4*sby;
- }
- mm[0]= mm0;
- mm[1]= mm1;
- mm[2]= mm2;
- mm[3]= mm3;
- mm[4]= mm4;
- mm[5]= mm5;
- return this;
- },
- setRotationAnchored : function( angle, rx, ry ) {
- this.rb_angle= angle;
- this.rb_rotateAnchorX= rx;
- this.rb_rotateAnchorY= ry;
- return this;
- },
- setRotationAnchor : function( ax, ay ) {
- this.rb_rotateAnchorX= ax;
- this.rb_rotateAnchorY= ay;
- },
- setRotation : function( angle ) {
- this.rb_angle= angle;
- },
- setScaleAnchored : function( scaleX, scaleY, sx, sy ) {
- this.sb_scaleX= scaleX;
- this.sb_scaleAnchorX= sx;
- this.sb_scaleY= scaleY;
- this.sb_scaleAnchorY= sy;
- return this;
- },
- setScale : function( sx, sy ) {
- this.sb_scaleX= sx;
- this.sb_scaleY= sy;
- return this;
- },
- setScaleAnchor : function( ax, ay ) {
- this.sb_scaleAnchorX= ax;
- this.sb_scaleAnchorY= ay;
- return this;
- },
- setPositionAnchor : function( ax, ay ) {
- this.tAnchorX= ax;
- this.tAnchorY= ay;
- return this;
- },
- setPositionAnchored : function( x,y,ax,ay ) {
- this.tb_x= x;
- this.tb_y= y;
- this.tAnchorX= ax;
- this.tAnchorY= ay;
- return this;
- },
- setPosition : function( x,y ) {
- this.tb_x= x;
- this.tb_y= y;
- return this;
- },
- setLocation : function( x, y ) {
- this.tb_x= x;
- this.tb_y= y;
- return this;
- },
- flatten : function( npatches, closed ) {
- var point= this.getPositionFromLength(0);
- var path= new CAAT.Path().beginPath( point.x, point.y );
- for( var i=0; i<npatches; i++ ) {
- point= this.getPositionFromLength(i/npatches*this.length);
- path.addLineTo( point.x, point.y );
- }
- if ( closed) {
- path.closePath();
- } else {
- path.endPath();
- }
- return path;
- }
- };
- extend( CAAT.Path, CAAT.PathSegment, null);
-
- })();/**
- * See LICENSE file.
- *
- * An actor to show the path and its handles in the scene graph.
- *
- **/
- (function() {
- /**
- * This class paints and handles the interactive behavior of a path.
- *
- * @constructor
- * @extends CAAT.ActorContainer
- */
- CAAT.PathActor= function() {
- CAAT.PathActor.superclass.constructor.call(this);
- return this;
- };
-
- CAAT.PathActor.prototype= {
- path : null,
- pathBoundingRectangle : null,
- bOutline : false,
- outlineColor : 'black',
- onUpdateCallback : null,
- interactive : false,
- /**
- * Return the contained path.
- * @return {CAAT.Path}
- */
- getPath : function() {
- return this.path;
- },
- /**
- * Sets the path to manage.
- * @param path {CAAT.PathSegment}
- * @return this
- */
- setPath : function(path) {
- this.path= path;
- if ( path!=null ) {
- this.pathBoundingRectangle= path.getBoundingBox();
- this.setInteractive( this.interactive );
- }
- return this;
- },
- /**
- * Paint this actor.
- * @param director {CAAT.Director}
- * @param time {number}. Scene time.
- */
- paint : function(director, time) {
- CAAT.PathActor.superclass.paint.call( this, director, time );
- if ( !this.path ) {
- return;
- }
- var ctx= director.ctx;
- ctx.strokeStyle='#000';
- this.path.paint(director, this.interactive);
- if ( this.bOutline ) {
- ctx.strokeStyle= this.outlineColor;
- ctx.strokeRect(0,0,this.width,this.height);
- }
- },
- /**
- * Enables/disables drawing of the contained path's bounding box.
- * @param show {boolean} whether to show the bounding box
- * @param color {=string} optional parameter defining the path's bounding box stroke style.
- */
- showBoundingBox : function(show, color) {
- this.bOutline= show;
- if ( show && color ) {
- this.outlineColor= color;
- }
- },
- /**
- * Set the contained path as interactive. This means it can be changed on the fly by manipulation
- * of its control points.
- * @param interactive
- */
- setInteractive : function(interactive) {
- this.interactive= interactive;
- if ( this.path ) {
- this.path.setInteractive(interactive);
- }
- return this;
- },
- setOnUpdateCallback : function( fn ) {
- this.onUpdateCallback= fn;
- return this;
- },
- /**
- * Route mouse dragging functionality to the contained path.
- * @param mouseEvent {CAAT.MouseEvent}
- */
- mouseDrag : function(mouseEvent) {
- this.path.drag(mouseEvent.point.x, mouseEvent.point.y, this.onUpdateCallback);
- },
- /**
- * Route mouse down functionality to the contained path.
- * @param mouseEvent {CAAT.MouseEvent}
- */
- mouseDown : function(mouseEvent) {
- this.path.press(mouseEvent.point.x, mouseEvent.point.y);
- },
- /**
- * Route mouse up functionality to the contained path.
- * @param mouseEvent {CAAT.MouseEvent}
- */
- mouseUp : function(mouseEvent) {
- this.path.release();
- }
- };
- extend( CAAT.PathActor, CAAT.ActorContainer, null);
- })();/**
- * See LICENSE file.
- *
- * This file contains some image processing effects.
- * Currently contains the following out-of-the-box effects:
- *
- * + IMPlasma: creates a plasma texture. The plasma is generated out of a color ramp (see color.js file)
- * + IMBump: creates a realtime bump-mapping from a given image. It supports multiple light sources
- * as well as different light colors.
- * + IMRotoZoom: produces a roto zoom effect out of a given square sized image. Image must be 2^n in size.
- *
- * This class must be used as fillStyle for an actor or any element that will be painted in a canvas context.
- *
- */
- (function() {
- /**
- * ImageProcessor is a class to encapsulate image processing operations. These image processing
- * manipulates individual image pixels and from an array of pixels builds an image which can
- * be used as a pattern or image.
- * <p>
- * This class pre-creates a canvas of the given dimensions and extracts an imageData object to
- * hold the pixel manipulation.
- *
- * @constructor
- */
- CAAT.ImageProcessor= function() {
- return this;
- };
- CAAT.ImageProcessor.prototype= {
- canvas: null,
- ctx: null,
- width: 0,
- height: 0,
- imageData: null,
- bufferImage:null,
- /**
- * Grabs an image pixels.
- *
- * @param image {HTMLImageElement}
- * @return {ImageData} returns an ImageData object with the image representation or null in
- * case the pixels can not be grabbed.
- *
- * @static
- */
- grabPixels : function(image) {
- var canvas= document.createElement('canvas');
- if ( canvas!==null ) {
- canvas.width= image.width;
- canvas.height= image.height;
- var ctx= canvas.getContext('2d');
- ctx.drawImage(image,0,0);
- try {
- var imageData= ctx.getImageData(0,0,canvas.width,canvas.height);
- return imageData;
- }
- catch(e) {
- CAAT.log('error pixelgrabbing.', image);
- return null;
- }
- }
- return null;
- },
- /**
- * Helper method to create an array.
- *
- * @param size {number} integer number of elements in the array.
- * @param initValue {number} initial array values.
- *
- * @return {[]} an array of 'initialValue' elements.
- *
- * @static
- */
- makeArray : function(size, initValue) {
- var a= [];
- for(var i=0; i<size; i++ ) {
- a.push( initValue );
- }
- return a;
- },
- /**
- * Helper method to create a bidimensional array.
- *
- * @param size {number} number of array rows.
- * @param size2 {number} number of array columns.
- * @param initvalue array initial values.
- *
- * @return {[]} a bidimensional array of 'initvalue' elements.
- *
- * @static
- *
- */
- makeArray2D : function (size, size2, initvalue) {
- var a= [];
- for( var i=0; i<size; i++ ) {
- a.push( this.makeArray(size2,initvalue) );
- }
- return a;
- },
- /**
- * Initializes and creates an offscreen Canvas object. It also creates an ImageData object and
- * initializes the internal bufferImage attribute to imageData's data.
- * @param width {number} canvas width.
- * @param height {number} canvas height.
- * @return this
- */
- initialize : function(width,height) {
- this.width= width;
- this.height= height;
- this.canvas= document.createElement('canvas');
- if ( this.canvas!==null ) {
- this.canvas.width= width;
- this.canvas.height= height;
- this.ctx= this.canvas.getContext('2d');
- this.imageData= this.ctx.getImageData(0,0,width,height);
- this.bufferImage= this.imageData.data;
- }
- return this;
- },
- /**
- * Clear this ImageData object to the given color components.
- * @param r {number} red color component 0..255.
- * @param g {number} green color component 0..255.
- * @param b {number} blue color component 0..255.
- * @param a {number} alpha color component 0..255.
- * @return this
- */
- clear : function( r,g,b,a ) {
- if ( null===this.imageData ) {
- return this;
- }
- var data= this.imageData.data;
- for( var i=0; i<this.width*this.height; i++ ) {
- data[i*4+0]= r;
- data[i*4+1]= g;
- data[i*4+2]= b;
- data[i*4+3]= a;
- }
- this.imageData.data= data;
- return this;
- },
- /**
- * Get this ImageData.
- * @return {ImageData}
- */
- getImageData : function() {
- return this.ctx.getImageData(0,0,this.width,this.height);
- },
- /**
- * Sets canvas pixels to be the applied effect. After process pixels, this method must be called
- * to show the result of such processing.
- * @param director {CAAT.Director}
- * @param time {number}
- * @return this
- */
- apply : function(director, time) {
- if ( null!==this.imageData ) {
- this.imageData.data= this.bufferImage;
- this.ctx.putImageData(this.imageData, 0, 0);
- }
- return this;
- },
- /**
- * Returns the offscreen canvas.
- * @return {HTMLCanvasElement}
- */
- getCanvas : function() {
- return this.canvas;
- },
- /**
- * Creates a pattern that will make this ImageProcessor object suitable as a fillStyle value.
- * This effect can be drawn too as an image by calling: canvas_context.drawImage methods.
- * @param type {string} the pattern type. if no value is supplied 'repeat' will be used.
- * @return CanvasPattern.
- */
- createPattern : function( type ) {
- return this.ctx.createPattern(this.canvas,type ? type : 'repeat');
- },
- /**
- * Paint this ImageProcessor object result.
- * @param director {CAAT.Director}.
- * @param time {number} scene time.
- */
- paint : function( director, time ) {
- if ( null!==this.canvas ) {
- var ctx= director.ctx;
- ctx.drawImage( this.getCanvas(), 0, 0 );
- }
- }
- };
- })();
- (function() {
- /**
- * Creates an additive plasma wave image.
- *
- * @constructor
- * @extends CAAT.ImageProcessor
- *
- */
- CAAT.IMPlasma= function() {
- CAAT.IMPlasma.superclass.constructor.call(this);
- return this;
- };
- CAAT.IMPlasma.prototype= {
- wavetable: null,
- m_colorMap: null,
- spd1: 1,
- spd2: 2,
- spd3: 3,
- spd4: 4,
- pos1: 0,
- pos2: 0,
- pos3: 0,
- pos4: 0,
- tpos1: 0,
- tpos2: 0,
- tpos3: 0,
- tpos4: 0,
- m_colorMapSize: 256,
- i1: 0,
- i2: 0,
- i3: 0,
- i4: 0,
- b1: false,
- b2: false,
- b3: false,
- b4: false,
- color: [0xffffffff, 0xffff00ff, 0xffffff00, 0xff00ff00, 0xffff0000, 0xff0000ff, 0xff000000],
- /**
- * Initialize the plasma image processor.
- * <p>
- * This image processor creates a color ramp of 256 elements from the colors of the parameter 'colors'.
- * Be aware of color definition since the alpha values count to create the ramp.
- *
- * @param width {number}
- * @param height {number}
- * @param colors {Array.<number>} an array of color values.
- *
- * @return this
- */
- initialize : function(width,height,colors) {
- CAAT.IMPlasma.superclass.initialize.call(this,width,height);
- this.wavetable= [];
- for (var x=0; x<256; x++) {
- this.wavetable.push( Math.floor(32 * (1 + Math.cos(x*2 * Math.PI / 256))) );
- }
- this.pos1=Math.floor(255*Math.random());
- this.pos2=Math.floor(255*Math.random());
- this.pos3=Math.floor(255*Math.random());
- this.pos4=Math.floor(255*Math.random());
- this.m_colorMap= CAAT.Color.prototype.makeRGBColorRamp(
- colors!==null ? colors : this.color,
- 256,
- CAAT.Color.prototype.RampEnumeration.RAMP_CHANNEL_RGBA_ARRAY );
- this.setB();
- return this;
- },
- /**
- * Initialize internal plasma structures. Calling repeatedly this method will make the plasma
- * look different.
- */
- setB : function() {
- this.b1= Math.random()>0.5;
- this.b2= Math.random()>0.5;
- this.b3= Math.random()>0.5;
- this.b4= Math.random()>0.5;
- this.spd1= Math.floor((Math.random()*3+1)*(Math.random()<0.5?1:-1));
- this.spd2= Math.floor((Math.random()*3+1)*(Math.random()<0.5?1:-1));
- this.spd3= Math.floor((Math.random()*3+1)*(Math.random()<0.5?1:-1));
- this.spd4= Math.floor((Math.random()*3+1)*(Math.random()<0.5?1:-1));
- this.i1= Math.floor((Math.random()*2.4+1)*(Math.random()<0.5?1:-1));
- this.i2= Math.floor((Math.random()*2.4+1)*(Math.random()<0.5?1:-1));
- this.i3= Math.floor((Math.random()*2.4+1)*(Math.random()<0.5?1:-1));
- this.i4= Math.floor((Math.random()*2.4+1)*(Math.random()<0.5?1:-1));
- },
- /**
- * Apply image processing to create the plasma and call superclass's apply to make the result
- * visible.
- * @param director {CAAT.Director}
- * @param time {number}
- *
- * @return this
- */
- apply : function(director,time) {
- var v = 0;
- this.tpos1 = this.pos1;
- this.tpos2 = this.pos2;
- var bi= this.bufferImage;
- var cm= this.m_colorMap;
- var wt= this.wavetable;
- var z;
- var cmz;
- for (var x=0; x<this.height; x++) {
- this.tpos3 = this.pos3;
- this.tpos4 = this.pos4;
- for(var y=0; y<this.width; y++) {
- // mix at will, or at your own risk.
- var o1= this.tpos1+this.tpos2+this.tpos3;
- var o2= this.tpos2+this.tpos3-this.tpos1;
- var o3= this.tpos3+this.tpos4-this.tpos2;
- var o4= this.tpos4+this.tpos1-this.tpos2;
- // set different directions. again, change at will.
- if ( this.b1 ) o1= -o1;
- if ( this.b2 ) o2= -o2;
- if ( this.b3 ) o3= -o3;
- if ( this.b4 ) o4= -o4;
- z = Math.floor( wt[o1&255] + wt[o2&255] + wt[o3&255] + wt[o4&255] );
- cmz= cm[z];
- bi[ v++ ]= cmz[0];
- bi[ v++ ]= cmz[1];
- bi[ v++ ]= cmz[2];
- bi[ v++ ]= cmz[3];
- this.tpos3 += this.i1;
- this.tpos3&=255;
- this.tpos4 += this.i2;
- this.tpos4&=255;
- }
- this.tpos1 += this.i3;
- this.tpos1&=255;
- this.tpos2 += this.i4;
- this.tpos2&=255;
- }
- this.pos1 += this.spd1;
- this.pos2 -= this.spd2;
- this.pos3 += this.spd3;
- this.pos4 -= this.spd4;
- this.pos1&=255;
- this.pos3&=255;
- this.pos2&=255;
- this.pos4&=255;
- return CAAT.IMPlasma.superclass.apply.call(this,director,time);
- }
- };
- extend( CAAT.IMPlasma, CAAT.ImageProcessor, null);
- })();
- (function() {
- /**
- * This class creates a bumpy effect from a given image. The effect can be applied by different lights
- * each of which can bump the image with a different color. The lights will have an additive color
- * effect on affected pixels.
- *
- * @constructor
- * @extends CAAT.ImageProcessor
- */
- CAAT.IMBump=function() {
- CAAT.IMBump.superclass.constructor.call(this);
- return this;
- };
- CAAT.IMBump.prototype= {
- // bump
- m_avgX: null,
- m_avgY: null,
- m_tt: null,
- phong: null,
- m_radius: 75,
- m_lightcolor: null,
- bcolor: false,
- lightPosition: [],
- /**
- * Initializes internal bump effect data.
- *
- * @param image {HTMLImageElement}
- * @param radius {number} lights radius.
- *
- * @private
- */
- prepareBump : function(image, radius) {
- var i,j;
- this.m_radius= (radius ? radius : 75);
- var imageData= this.grabPixels(image);
- this.m_tt= this.makeArray(this.height,0);
- for( i=0; i<this.height; i++ ){
- this.m_tt[ i ]=this.width*i;
- }
- this.m_avgX= this.makeArray2D(this.height,this.width,0);
- this.m_avgY= this.makeArray2D(this.height,this.width,0);
- var bump=this.makeArray2D(this.height,this.width,0);
- if ( null===imageData ) {
- return;
- }
-
- var sourceImagePixels= imageData.data;
- for (i=0;i<this.height;i++) {
- for (j=0;j<this.width;j++) {
- var pos= (i*this.width+j)*4;
- bump[i][j]=
- sourceImagePixels[pos ]+
- sourceImagePixels[pos+1]+
- sourceImagePixels[pos+2];
- }
- }
- bump= this.soften( bump );
- for (var x=1;x<this.width-1;x++) {
- for (var y=1;y<this.height-1;y++) {
- this.m_avgX[y][x]=Math.floor(bump[y][x+1]-bump[y][x-1]);
- this.m_avgY[y][x]=Math.floor(bump[y+1][x]-bump[y-1][x]);
- }
- }
- bump=null;
- },
- /**
- * Soften source images extracted data on prepareBump method.
- * @param bump bidimensional array of black and white source image version.
- * @return bidimensional array with softened version of source image's b&w representation.
- */
- soften : function( bump ) {
- var temp;
- var sbump=this.makeArray2D( this.height,this.width, 0);
- for (var j=0;j<this.width;j++) {
- for (var i=0;i<this.height;i++) {
- temp=(bump[i][j]);
- temp+=(bump[(i+1)%this.height][j]);
- temp+=(bump[(i+this.height-1)%this.height][j]);
- temp+=(bump[i][(j+1)%this.width]);
- temp+=(bump[i][(j+this.width-1)%this.width]);
- temp+=(bump[(i+1)%this.height][(j+1)%this.width]);
- temp+=(bump[(i+this.height-1)%this.height][(j+this.width-1)%this.width]);
- temp+=(bump[(i+this.height-1)%this.height][(j+1)%this.width]);
- temp+=(bump[(i+1)%this.height][(j+this.width-1)%this.width]);
- temp/=9;
- sbump[i][j]=temp/3;
- }
- }
- return sbump;
- },
- /**
- * Create a phong image to apply bump effect.
- * @private
- */
- calculatePhong : function( ) {
- this.phong= this.makeArray2D(this.m_radius,this.m_radius,0);
- var i,j,z;
- for( i=0; i<this.m_radius; i++ ) {
- for( j=0; j<this.m_radius; j++ ) {
- var x= j/this.m_radius;
- var y= i/this.m_radius;
- z= (1-Math.sqrt(x*x+y*y))*0.8;
- if ( z<0 ) {
- z=0;
- }
- this.phong[ i ][ j ]= Math.floor(z*255);
- }
- }
- },
- /**
- * Generates a bump image.
- * @param dstPixels {ImageData.data} destinarion pixel array to store the calculated image.
- */
- drawColored : function(dstPixels) {
- var i,j,k;
- for( i=0; i<this.height; i++ ) {
- for( j=0; j<this.width; j++ ){
- var rrr=0;
- var ggg=0;
- var bbb=0;
- for( k=0; k<this.m_lightcolor.length; k++ ) {
- var lx= this.lightPosition[k].x;
- var ly= this.lightPosition[k].y;
- var dx=Math.floor(Math.abs(this.m_avgX[i][j]-j+lx));
- var dy=Math.floor(Math.abs(this.m_avgY[i][j]-i+ly));
- if (dx>=this.m_radius) {
- dx=this.m_radius-1;
- }
- if (dy>=this.m_radius) {
- dy=this.m_radius-1;
- }
- var c= this.phong[ dx ] [ dy ];
- var r=0;
- var g=0;
- var b=0;
- if ( c>=0 ) {// oscurecer
- r= (this.m_lightcolor[k][0]*c/128);
- g= (this.m_lightcolor[k][1]*c/128);
- b= (this.m_lightcolor[k][2]*c/128);
- }
- else { // blanquear.
- c=128+c;
- var rr= (this.m_lightcolor[k][0]);
- var gg= (this.m_lightcolor[k][1]);
- var bb= (this.m_lightcolor[k][2]);
- r= Math.floor(rr+ (255-rr)*c/128);
- g= Math.floor(gg+ (255-gg)*c/128);
- b= Math.floor(bb+ (255-bb)*c/128);
- }
- rrr+=r;
- ggg+=g;
- bbb+=b;
- }
- if ( rrr>255 ) {
- rrr=255;
- }
- if ( ggg>255 ) {
- ggg=255;
- }
- if ( bbb>255 ) {
- bbb=255;
- }
- var pos= (j+this.m_tt[i])*4;
- dstPixels[pos ]= rrr;
- dstPixels[pos+1]= ggg;
- dstPixels[pos+2]= bbb;
- dstPixels[pos+3]= 255;
- }
- }
- },
- /**
- * Sets lights color.
- * @param colors_rgb_array an array of arrays. Each internal array has three integers defining an RGB color.
- * ie:
- * [
- * [ 255,0,0 ],
- * [ 0,255,0 ]
- * ]
- * @return this
- */
- setLightColors : function( colors_rgb_array ) {
- this.m_lightcolor= colors_rgb_array;
- this.lightPosition= [];
- for( var i=0; i<this.m_lightcolor.length; i++ ) {
- var x= this.width*Math.random();
- var y= this.height*Math.random();
- this.lightPosition.push( new CAAT.Point().set(x,y) );
- }
- return this;
- },
- /**
- * Initialize the bump image processor.
- * @param image {HTMLImageElement} source image to bump.
- * @param radius {number} light radius.
- */
- initialize : function(image,radius) {
- CAAT.IMBump.superclass.initialize.call(this,image.width,image.height);
- this.setLightColors(
- [
- [255,128,0],
- [0,0,255]
- ]);
- this.prepareBump(image,radius);
- this.calculatePhong();
- return this;
- },
- /**
- * Set a light position.
- * @param lightIndex {number} light index to position.
- * @param x {number} light x coordinate.
- * @param y {number} light y coordinate.
- * @return this
- */
- setLightPosition : function( lightIndex, x, y ) {
- this.lightPosition[lightIndex].set(x,y);
- return this;
- },
- /**
- * Applies the bump effect and makes it visible on the canvas surface.
- * @param director {CAAT.Director}
- * @param time {number}
- */
- apply : function(director,time) {
- this.drawColored(this.bufferImage);
- return CAAT.IMBump.superclass.apply.call(this,director,time);
- }
- };
- extend( CAAT.IMBump, CAAT.ImageProcessor, null);
- })();
- (function() {
- /**
- * This class creates an image processing Rotozoom effect.
- *
- * @constructor
- * @extends CAAT.ImageProcessor
- */
- CAAT.IMRotoZoom= function() {
- CAAT.IMRotoZoom.superclass.constructor.call(this);
- return this;
- };
- CAAT.IMRotoZoom.prototype= {
- m_alignv: 1,
- m_alignh: 1,
- distortion: 2,
- mask: 0,
- shift: 0,
- sourceImageData:null, // pattern to fill area with.
- /**
- * Initialize the rotozoom.
- * @param width {number}
- * @param height {number}
- * @param patternImage {HTMLImageElement} image to tile with.
- *
- * @return this
- */
- initialize : function( width, height, patternImage ) {
- CAAT.IMRotoZoom.superclass.initialize.call(this,width,height);
- this.clear( 255,128,0, 255 );
- this.sourceImageData= this.grabPixels(patternImage);
- if ( null!==this.sourceImageData ) {
- // patternImage must be 2^n sized.
- switch( this.sourceImageData.width ) {
- case 1024:
- this.mask=1023;
- this.shift=10;
- break;
- case 512:
- this.mask=511;
- this.shift=9;
- break;
- case 256:
- this.mask=255;
- this.shift=8;
- break;
- case 128:
- this.mask=127;
- this.shift=7;
- break;
- case 64:
- this.mask=63;
- this.shift=6;
- break;
- case 32:
- this.mask=31;
- this.shift=5;
- break;
- case 16:
- this.mask=15;
- this.shift=4;
- break;
- case 8:
- this.mask=7;
- this.shift=3;
- break;
- }
- }
- this.setCenter();
- return this;
- },
- /**
- * Performs the process of tiling rotozoom.
- * @param director {CAAT.Director}
- * @param time {number}
- *
- * @private
- */
- rotoZoom: function(director,time) {
- var timer = new Date().getTime();
- var angle=Math.PI*2 * Math.cos(timer * 0.0001);
- var distance= 600+ 550*Math.sin(timer*0.0002);
- var dist= this.distortion;
- var off=0;
- var ddx=Math.floor(Math.cos(angle)*distance);
- var ddy=Math.floor(Math.sin(angle)*distance);
- var hh=0, ww=0;
- switch( this.m_alignh ) {
- case 0:
- hh = 0;
- break;
- case 1:
- hh = (this.height >> 1);
- break;
- case 2:
- hh = this.height - 1;
- break;
- }
- switch (this.m_alignv) {
- case 0:
- ww = 0;
- break;
- case 1:
- ww = (this.width >> 1);
- break;
- case 2:
- ww = this.width - 1;
- break;
- }
- var i = (((this.width >> 1) << 8) - ddx * ww + ddy * hh)&0xffff;
- var j = (((this.height >> 1) << 8) - ddy * ww - ddx * hh) & 0xffff;
- var srcwidth= this.sourceImageData.width;
- var srcheight= this.sourceImageData.height;
- var srcdata= this.sourceImageData.data;
- var bi= this.bufferImage;
- var dstoff;
- var addx;
- var addy;
- while (off < this.width * this.height * 4) {
- addx = i;
- addy = j;
- for (var m = 0; m < this.width; m++) {
- dstoff = ((addy >> this.shift) & this.mask) * srcwidth + ((addx >> this.shift) & this.mask);
- dstoff <<= 2;
- bi[ off++ ] = srcdata[ dstoff++ ];
- bi[ off++ ] = srcdata[ dstoff++ ];
- bi[ off++ ] = srcdata[ dstoff++ ];
- bi[ off++ ] = srcdata[ dstoff++ ];
- addx += ddx;
- addy += ddy;
- }
- dist += this.distortion;
- i -= ddy;
- j += ddx - dist;
- }
- },
- /**
- * Perform and apply the rotozoom effect.
- * @param director {CAAT.Director}
- * @param time {number}
- * @return this
- */
- apply : function(director,time) {
- if ( null!==this.sourceImageData ) {
- this.rotoZoom(director,time);
- }
- return CAAT.IMRotoZoom.superclass.apply.call(this,director,time);
- },
- /**
- * Change the effect's rotation anchor. Call this method repeatedly to make the effect look
- * different.
- */
- setCenter: function() {
- var d = Math.random();
- if (d < 0.33) {
- this.m_alignv = 0;
- } else if (d < 0.66) {
- this.m_alignv = 1;
- } else {
- this.m_alignv = 2;
- }
- d = Math.random();
- if (d < 0.33) {
- this.m_alignh = 0;
- } else if (d < 0.66) {
- this.m_alignh = 1;
- } else {
- this.m_alignh = 2;
- }
- }
- };
- extend( CAAT.IMRotoZoom, CAAT.ImageProcessor, null);
- })();/**
- * See LICENSE file.
- */
- (function() {
- CAAT.Program= function(gl) {
- this.gl= gl;
- return this;
- };
- CAAT.Program.prototype= {
- shaderProgram: null,
- gl: null,
- /**
- * Set fragment shader's alpha composite value.
- * @param alpha {number} float value 0..1.
- */
- setAlpha : function( alpha ) {
- },
- getShader : function (gl,type,str) {
- var shader;
- if (type === "x-shader/x-fragment") {
- shader = gl.createShader(gl.FRAGMENT_SHADER);
- } else if (type === "x-shader/x-vertex") {
- shader = gl.createShader(gl.VERTEX_SHADER);
- } else {
- return null;
- }
- gl.shaderSource(shader, str);
- gl.compileShader(shader);
- if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
- alert(gl.getShaderInfoLog(shader));
- return null;
- }
- return shader;
- },
- getDomShader : function(gl, id) {
- var shaderScript = document.getElementById(id);
- if (!shaderScript) {
- return null;
- }
- var str = "";
- var k = shaderScript.firstChild;
- while (k) {
- if (k.nodeType === 3) {
- str += k.textContent;
- }
- k = k.nextSibling;
- }
- var shader;
- if (shaderScript.type === "x-shader/x-fragment") {
- shader = gl.createShader(gl.FRAGMENT_SHADER);
- } else if (shaderScript.type === "x-shader/x-vertex") {
- shader = gl.createShader(gl.VERTEX_SHADER);
- } else {
- return null;
- }
- gl.shaderSource(shader, str);
- gl.compileShader(shader);
- if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
- alert(gl.getShaderInfoLog(shader));
- return null;
- }
- return shader;
- },
- initialize : function() {
- return this;
- },
- getFragmentShader : function() {
- return null;
- },
- getVertexShader : function() {
- return null;
- },
- create : function() {
- var gl= this.gl;
- this.shaderProgram = gl.createProgram();
- gl.attachShader(this.shaderProgram, this.getVertexShader());
- gl.attachShader(this.shaderProgram, this.getFragmentShader());
- gl.linkProgram(this.shaderProgram);
- gl.useProgram(this.shaderProgram);
- return this;
- },
- setMatrixUniform : function( caatMatrix4 ) {
- this.gl.uniformMatrix4fv(
- this.shaderProgram.pMatrixUniform,
- false,
- new Float32Array(caatMatrix4.flatten()));
- },
- useProgram : function() {
- this.gl.useProgram(this.shaderProgram);
- return this;
- }
- };
- })();
- (function() {
- CAAT.ColorProgram= function(gl) {
- CAAT.ColorProgram.superclass.constructor.call(this,gl);
- return this;
- };
- CAAT.ColorProgram.prototype= {
- colorBuffer: null,
- vertexPositionBuffer: null,
- vertexPositionArray: null,
- getFragmentShader : function() {
- return this.getShader(this.gl, "x-shader/x-fragment",
- "#ifdef GL_ES \n"+
- "precision highp float; \n"+
- "#endif \n"+
- "varying vec4 color; \n"+
-
- "void main(void) { \n"+
- " gl_FragColor = color;\n"+
- "}\n"
- );
- },
- getVertexShader : function() {
- return this.getShader(this.gl, "x-shader/x-vertex",
- "attribute vec3 aVertexPosition; \n"+
- "attribute vec4 aColor; \n"+
- "uniform mat4 uPMatrix; \n"+
- "varying vec4 color; \n"+
- "void main(void) { \n"+
- "gl_Position = uPMatrix * vec4(aVertexPosition, 1.0); \n"+
- "color= aColor; \n"+
- "}\n"
- );
- },
- initialize : function() {
- this.shaderProgram.vertexPositionAttribute =
- this.gl.getAttribLocation(this.shaderProgram, "aVertexPosition");
- this.gl.enableVertexAttribArray(
- this.shaderProgram.vertexPositionAttribute);
- this.shaderProgram.vertexColorAttribute =
- this.gl.getAttribLocation(this.shaderProgram, "aColor");
- this.gl.enableVertexAttribArray(
- this.shaderProgram.vertexColorAttribute);
- this.shaderProgram.pMatrixUniform =
- this.gl.getUniformLocation(this.shaderProgram, "uPMatrix");
- this.useProgram();
- this.colorBuffer= this.gl.createBuffer();
- this.setColor( [1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1] );
- var maxTris=512, i;
- /// set vertex data
- this.vertexPositionBuffer = this.gl.createBuffer();
- this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexPositionBuffer );
- this.vertexPositionArray= new Float32Array(maxTris*12);
- this.gl.bufferData(this.gl.ARRAY_BUFFER, this.vertexPositionArray, this.gl.DYNAMIC_DRAW);
- this.gl.vertexAttribPointer(this.shaderProgram.vertexPositionAttribute, 3, this.gl.FLOAT, false, 0, 0);
- return CAAT.ColorProgram.superclass.initialize.call(this);
- },
- setColor : function( colorArray ) {
- this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.colorBuffer );
- this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(colorArray), this.gl.STATIC_DRAW);
- this.gl.vertexAttribPointer(
- this.shaderProgram.vertexColorAttribute,
- this.colorBuffer,
- this.gl.FLOAT,
- false,
- 0,
- 0);
- }
- };
- extend(CAAT.ColorProgram, CAAT.Program, null );
- })();
- (function() {
- CAAT.TextureProgram= function(gl) {
- CAAT.TextureProgram.superclass.constructor.call(this,gl);
- return this;
- };
- CAAT.TextureProgram.prototype= {
- vertexPositionBuffer: null,
- vertexPositionArray: null,
- vertexUVBuffer: null,
- vertexUVArray: null,
- vertexIndexBuffer: null,
- linesBuffer: null,
- prevAlpha: -1,
- prevR: -1,
- prevG: -1,
- prevB: -1,
- prevA: -1,
- prevTexture: null,
- getFragmentShader : function() {
- return this.getShader( this.gl, "x-shader/x-fragment",
- "#ifdef GL_ES \n"+
- "precision highp float; \n"+
- "#endif \n"+
- "varying vec2 vTextureCoord; \n"+
- "uniform sampler2D uSampler; \n"+
- "uniform float alpha; \n"+
- "uniform bool uUseColor;\n"+
- "uniform vec4 uColor;\n"+
- "void main(void) { \n"+
- "if ( uUseColor ) {\n"+
- " gl_FragColor= vec4(uColor.r*alpha, uColor.g*alpha, uColor.b*alpha, uColor.a*alpha);\n"+
- "} else { \n"+
- " vec4 textureColor= texture2D(uSampler, vec2(vTextureCoord)); \n"+
- // Fix FF " gl_FragColor = vec4(textureColor.rgb, textureColor.a * alpha); \n"+
- " gl_FragColor = vec4(textureColor.r*alpha, textureColor.g*alpha, textureColor.b*alpha, textureColor.a * alpha ); \n"+
- "}\n"+
- "}\n"
- );
- },
- getVertexShader : function() {
- return this.getShader(this.gl, "x-shader/x-vertex",
- "attribute vec3 aVertexPosition; \n"+
- "attribute vec2 aTextureCoord; \n"+
- "uniform mat4 uPMatrix; \n"+
- "varying vec2 vTextureCoord; \n"+
- "void main(void) { \n"+
- "gl_Position = uPMatrix * vec4(aVertexPosition, 1.0); \n"+
- "vTextureCoord = aTextureCoord;\n"+
- "}\n"
- );
- },
- useProgram : function() {
- CAAT.TextureProgram.superclass.useProgram.call(this);
- this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexPositionBuffer );
- this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexUVBuffer);
- this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
- },
- initialize : function() {
- var i;
- this.linesBuffer= this.gl.createBuffer();
- this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.linesBuffer );
- var arr= [];
- for( i=0; i<1024; i++ ) {
- arr[i]= i;
- }
- this.linesBufferArray= new Uint16Array(arr);
- this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, this.linesBufferArray, this.gl.DYNAMIC_DRAW);
- this.shaderProgram.vertexPositionAttribute =
- this.gl.getAttribLocation(this.shaderProgram, "aVertexPosition");
- this.gl.enableVertexAttribArray(
- this.shaderProgram.vertexPositionAttribute);
- this.shaderProgram.textureCoordAttribute =
- this.gl.getAttribLocation(this.shaderProgram, "aTextureCoord");
- this.gl.enableVertexAttribArray(
- this.shaderProgram.textureCoordAttribute);
- this.shaderProgram.pMatrixUniform =
- this.gl.getUniformLocation(this.shaderProgram, "uPMatrix");
- this.shaderProgram.samplerUniform =
- this.gl.getUniformLocation(this.shaderProgram, "uSampler");
- this.shaderProgram.alphaUniform =
- this.gl.getUniformLocation(this.shaderProgram, "alpha");
- this.shaderProgram.useColor =
- this.gl.getUniformLocation(this.shaderProgram, "uUseColor");
- this.shaderProgram.color =
- this.gl.getUniformLocation(this.shaderProgram, "uColor");
- this.setAlpha(1);
- this.setUseColor(false);
- var maxTris=4096;
- /// set vertex data
- this.vertexPositionBuffer = this.gl.createBuffer();
- this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexPositionBuffer );
- this.vertexPositionArray= new Float32Array(maxTris*12);
- this.gl.bufferData(this.gl.ARRAY_BUFFER, this.vertexPositionArray, this.gl.DYNAMIC_DRAW);
- this.gl.vertexAttribPointer(this.shaderProgram.vertexPositionAttribute, 3, this.gl.FLOAT, false, 0, 0);
- // uv info
- this.vertexUVBuffer= this.gl.createBuffer();
- this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexUVBuffer);
- this.vertexUVArray= new Float32Array(maxTris*8);
- this.gl.bufferData(this.gl.ARRAY_BUFFER, this.vertexUVArray, this.gl.DYNAMIC_DRAW);
- this.gl.vertexAttribPointer(this.shaderProgram.textureCoordAttribute, 2, this.gl.FLOAT, false, 0, 0);
- // vertex index
- this.vertexIndexBuffer = this.gl.createBuffer();
- this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
- var vertexIndex = [];
- for( i=0; i<maxTris; i++ ) {
- vertexIndex.push(0 + i*4); vertexIndex.push(1 + i*4); vertexIndex.push(2 + i*4);
- vertexIndex.push(0 + i*4); vertexIndex.push(2 + i*4); vertexIndex.push(3 + i*4);
- }
- this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(vertexIndex), this.gl.DYNAMIC_DRAW);
- return CAAT.TextureProgram.superclass.initialize.call(this);
- },
- setUseColor : function( use,r,g,b,a ) {
- this.gl.uniform1i(this.shaderProgram.useColor, use?1:0);
- if ( use ) {
- if ( this.prevA!==a || this.prevR!==r || this.prevG!==g || this.prevB!==b ) {
- this.gl.uniform4f(this.shaderProgram.color, r,g,b,a );
- this.prevA= a;
- this.prevR= r;
- this.prevG= g;
- this.prevB= b;
- }
- }
- },
- setTexture : function( glTexture ) {
- if ( this.prevTexture!==glTexture ) {
- var gl= this.gl;
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, glTexture);
- gl.uniform1i(this.shaderProgram.samplerUniform, 0);
- this.prevTexture= glTexture;
- }
- return this;
- },
- updateVertexBuffer : function(vertexArray) {
- var gl= this.gl;
- gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexPositionBuffer );
- gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertexArray);
- return this;
- },
- updateUVBuffer : function(uvArray) {
- var gl= this.gl;
- gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexUVBuffer );
- gl.bufferSubData(gl.ARRAY_BUFFER, 0, uvArray);
- return this;
- },
- setAlpha : function(alpha) {
- if ( this.prevAlpha !== alpha ) {
- this.gl.uniform1f(
- this.shaderProgram.alphaUniform, alpha);
- this.prevAlpha= alpha;
- }
- return this;
- },
- /**
- *
- * @param lines_data {Float32Array} array of number with x,y,z coords for each line point.
- * @param size {number} number of lines to draw.
- * @param r
- * @param g
- * @param b
- * @param a
- * @param lineWidth {number} drawing line size.
- */
- drawLines : function( lines_data, size, r,g,b,a, lineWidth ) {
- var gl= this.gl;
- this.setAlpha( a );
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.linesBuffer );
- gl.lineWidth(lineWidth);
- this.updateVertexBuffer(lines_data);
- this.setUseColor(true, r,g,b,1 );
- gl.drawElements(gl.LINES, size, gl.UNSIGNED_SHORT, 0);
- /// restore
- this.setAlpha( 1 );
- this.setUseColor(false);
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
- },
- /**
- *
- * @param polyline_data
- * @param size
- * @param r
- * @param g
- * @param b
- * @param a
- * @param lineWidth
- */
- drawPolylines : function( polyline_data, size, r,g,b,a, lineWidth ) {
- var gl= this.gl;
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.linesBuffer );
- gl.lineWidth(lineWidth);
- this.setAlpha(a);
- this.updateVertexBuffer(polyline_data);
- this.setUseColor(true, r,g,b,1 );
- gl.drawElements(gl.LINE_STRIP, size, gl.UNSIGNED_SHORT, 0);
- /// restore
- this.setAlpha( 1 );
- this.setUseColor(false);
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
- }
- };
- extend( CAAT.TextureProgram, CAAT.Program, null );
- })();/**
- * See LICENSE file.
- *
- */
- //
- // gluPerspective
- //
- function makePerspective(fovy, aspect, znear, zfar, viewportHeight) {
- var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
- var ymin = -ymax;
- var xmin = ymin * aspect;
- var xmax = ymax * aspect;
- return makeFrustum(xmin, xmax, ymin, ymax, znear, zfar, viewportHeight);
- }
- //
- // glFrustum
- //
- function makeFrustum(left, right, bottom, top, znear, zfar, viewportHeight) {
- var X = 2*znear/(right-left);
- var Y = 2*znear/(top-bottom);
- var A = (right+left)/(right-left);
- var B = (top+bottom)/(top-bottom);
- var C = -(zfar+znear)/(zfar-znear);
- var D = -2*zfar*znear/(zfar-znear);
- return new CAAT.Matrix3().initWithMatrix(
- [
- [X, 0, A, -viewportHeight/2 ],
- [0, -Y, B, viewportHeight/2 ],
- [0, 0, C, D ],
- [0, 0, -1, 0 ]
- ]);
- }
- function makeOrtho(left, right, bottom, top, znear, zfar) {
- var tx = - (right + left) / (right - left) ;
- var ty = - (top + bottom) / (top - bottom) ;
- var tz = - (zfar + znear) / (zfar - znear);
- return new CAAT.Matrix3().initWithMatrix(
- [
- [2 / (right - left), 0, 0, tx ],
- [0, 2 / (top - bottom), 0, ty ],
- [0, 0, -2 / (zfar- znear), tz ],
- [0, 0, 0, 1 ]
- ]);
- }
- /**
- * See LICENSE file.
- */
- (function() {
- CAAT.GLTextureElement = function() {
- return this;
- };
- CAAT.GLTextureElement.prototype= {
- inverted: false,
- image: null,
- u: 0,
- v: 0,
- glTexture: null
- };
- })();
- (function() {
- CAAT.GLTextureScan= function(w) {
- this.freeChunks=[ {position:0, size:w||1024} ];
- return this;
- };
- CAAT.GLTextureScan.prototype= {
- freeChunks: null,
- /**
- * return an array of values where a chunk of width size fits in this scan.
- * @param width
- */
- findWhereFits : function( width ) {
- if ( this.freeChunks.length===0 ) {
- return [];
- }
- var fitsOnPosition= [];
- var i;
- for( i=0; i<this.freeChunks.length; i++ ) {
- var pos= 0;
- while( pos+width<= this.freeChunks[i].size ) {
- fitsOnPosition.push( pos+this.freeChunks[i].position );
- pos+= width;
- }
- }
- return fitsOnPosition;
- },
- fits : function( position, size ) {
- var i=0;
- for( i=0; i<this.freeChunks.length; i++ ) {
- var fc= this.freeChunks[i];
- if ( fc.position<=position && position+size<=fc.position+fc.size ) {
- return true;
- }
- }
- return false;
- },
- substract : function( position, size ) {
- var i=0;
- for( i=0; i<this.freeChunks.length; i++ ) {
- var fc= this.freeChunks[i];
- if ( fc.position<=position && position+size<=fc.position+fc.size ) {
- var lp=0;
- var ls=0;
- var rp=0;
- var rs=0;
- lp= fc.position;
- ls= position-fc.position;
- rp= position+size;
- rs= fc.position+fc.size - rp;
- this.freeChunks.splice(i,1);
- if ( ls>0 ) {
- this.freeChunks.splice( i++,0,{position: lp, size:ls} );
- }
- if ( rs>0 ) {
- this.freeChunks.splice( i,0,{position: rp, size:rs} );
- }
- return true;
- }
- }
- return false;
- },
- log : function(index) {
- if ( 0===this.freeChunks.length ) {
- CAAT.log('index '+index+' empty');
- } else {
- var str='index '+index;
- for( var i=0; i<this.freeChunks.length; i++ ) {
- var fc= this.freeChunks[i];
- str+='['+fc.position+","+fc.size+"]";
- }
- CAAT.log(str);
- }
- }
- };
- })();
- (function() {
- CAAT.GLTextureScanMap= function(w,h) {
- this.scanMapHeight= h;
- this.scanMapWidth= w;
- this.scanMap= [];
- for( var i=0; i<this.scanMapHeight; i++ ) {
- this.scanMap.push( new CAAT.GLTextureScan(this.scanMapWidth) );
- }
- return this;
- };
-
- CAAT.GLTextureScanMap.prototype= {
- scanMap: null,
- scanMapWidth: 0,
- scanMapHeight: 0,
- /**
- * Always try to fit a chunk of size width*height pixels from left-top.
- * @param width
- * @param height
- */
- whereFitsChunk : function( width, height ) {
- // trivial rejection:
- if ( width>this.width||height>this.height) {
- return null;
- }
- // find first fitting point
- var i,j,initialPosition= 0;
- while( initialPosition<=this.scanMapHeight-height) {
- // para buscar sitio se buscara un sitio hasta el tamano de alto del trozo.
- // mas abajo no va a caber.
- // fitHorizontalPosition es un array con todas las posiciones de este scan donde
- // cabe un chunk de tamano width.
- var fitHorizontalPositions= null;
- var foundPositionOnScan= false;
- for( ; initialPosition<=this.scanMapHeight-height; initialPosition++ ) {
- fitHorizontalPositions= this.scanMap[ initialPosition ].findWhereFits( width );
- // si no es nulo el array de resultados, quiere decir que en alguno de los puntos
- // nos cabe un trozo de tamano width.
- if ( null!==fitHorizontalPositions && fitHorizontalPositions.length>0 ) {
- foundPositionOnScan= true;
- break;
- }
- }
- if ( foundPositionOnScan ) {
- // j es el scan donde cabe un trozo de tamano width.
- // comprobamos desde este scan que en todos los scan verticales cabe el trozo.
- // se comprueba que cabe en alguno de los tamanos que la rutina de busqueda horizontal
- // nos ha devuelto antes.
- var minInitialPosition=Number.MAX_VALUE;
- for( j=0; j<fitHorizontalPositions.length; j++ ) {
- var fits= true;
- for( i=initialPosition; i<initialPosition+height; i++ ) {
- // hay un trozo que no cabe
- if ( !this.scanMap[i].fits( fitHorizontalPositions[j], width ) ) {
- fits= false;
- break;
- }
- }
- // se ha encontrado un trozo donde la imagen entra.
- // d.p.m. incluirla en posicion, y seguir con otra.
- if ( fits ) {
- return { x: fitHorizontalPositions[j], y: initialPosition };
- }
- }
- initialPosition++;
- } else {
- // no hay sitio en ningun scan.
- return null;
- }
- }
- // no se ha podido encontrar un area en la textura para un trozo de tamano width*height
- return null;
- },
- substract : function( x,y, width, height ) {
- for( var i=0; i<height; i++ ) {
- if ( !this.scanMap[i+y].substract(x,width) ) {
- CAAT.log('Error: removing chunk ',width,height,' at ',x,y);
- }
- }
- },
- log : function() {
- for( var i=0; i<this.scanMapHeight; i++ ) {
- this.scanMap[i].log(i);
- }
- }
- };
- })();
- (function() {
- CAAT.GLTexturePage= function(w,h) {
- this.width= w || 1024;
- this.height= h || 1024;
- this.images= [];
- return this;
- };
- CAAT.GLTexturePage.prototype= {
- width: 1024,
- height: 1024,
- gl: null,
- texture: null,
- allowImagesInvertion: false,
- padding: 4,
- scan: null,
- images: null,
- criteria: 'area',
- initialize : function(gl) {
- this.gl= gl;
- // Fix firefox.
- gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
- this.texture = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, this.texture);
- gl.enable( gl.BLEND );
- gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
- var uarr= new Uint8Array(this.width*this.height*4);
- for (var jj = 0; jj < 4*this.width*this.height; ) {
- uarr[jj++]=0;
- uarr[jj++]=0;
- uarr[jj++]=0;
- uarr[jj++]=0;
- }
- gl.texImage2D(
- gl.TEXTURE_2D,
- 0,
- gl.RGBA,
- this.width,
- this.height,
- 0,
- gl.RGBA,
- gl.UNSIGNED_BYTE,
- uarr);
- gl.enable( gl.BLEND );
- for( var i=0; i<this.images.length; i++ ) {
- var img= this.images[i];
- if ( img.inverted ) {
- img= CAAT.modules.ImageUtil.prototype.rotate( img, -90 );
- }
- gl.texSubImage2D(
- gl.TEXTURE_2D,
- 0,
- this.images[i].__tx, this.images[i].__ty,
- gl.RGBA,
- gl.UNSIGNED_BYTE,
- img );
- }
- },
- create: function(imagesCache) {
- var images= [];
- for( var i=0; i<imagesCache.length; i++ ) {
- var img= imagesCache[i].image;
- if ( !img.__texturePage ) {
- images.push( img );
- }
- }
- this.createFromImages(images);
- },
- clear : function() {
- this.createFromImages([]);
- },
- update : function(invert,padding,width,height) {
- this.allowImagesInvertion= invert;
- this.padding= padding;
- if ( width<100 ) {
- width= 100;
- }
- if ( height<100 ) {
- height= 100;
- }
- this.width= width;
- this.height= height;
-
- this.createFromImages(this.images);
- },
- createFromImages : function( images ) {
- var i;
- this.scan= new CAAT.GLTextureScanMap( this.width, this.height );
- this.images= [];
- if ( this.allowImagesInvertion ) {
- for( i=0; i<images.length; i++ ) {
- images[i].inverted= this.allowImagesInvertion && images[i].height<images[i].width;
- }
- }
- var me= this;
- images.sort( function(a,b) {
- var aarea= a.width*a.height;
- var barea= b.width*b.height;
- if ( me.criteria==='width' ) {
- return a.width<b.width ? 1 : a.width>b.width ? -1 : 0;
- } else if ( me.criteria==='height' ) {
- return a.height<b.height ? 1 : a.height>b.height ? -1 : 0;
- }
- return aarea<barea ? 1 : aarea>barea ? -1 : 0;
- });
- for( i=0; i<images.length; i++ ) {
- var img= images[i];
- this.packImage(img);
- }
- },
- addImage : function( image, invert, padding ) {
- this.allowImagesInvertion= invert;
- this.padding= padding;
- this.images.push(image);
- this.createFromImages(Array.prototype.slice.call(this.images));
- },
- endCreation : function() {
- var gl= this.gl;
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
- gl.generateMipmap(gl.TEXTURE_2D);
- },
- deletePage : function() {
- for( var i=0; i<this.images.length; i++ ) {
- delete this.images[i].__texturePage;
- delete this.images[i].__u;
- delete this.images[i].__v;
- }
- this.gl.deleteTexture( this.texture );
- },
- toCanvas : function(canvass, outline) {
- canvass= canvass || document.createElement('canvas');
- canvass.width= this.width;
- canvass.height= this.height;
- var ctxx= canvass.getContext('2d');
- ctxx.fillStyle= 'rgba(0,0,0,0)';
- ctxx.fillRect(0,0,this.width,this.height);
- for( var i=0; i<this.images.length; i++ ) {
- ctxx.drawImage(
- !this.images[i].inverted ?
- this.images[i] :
- CAAT.modules.ImageUtil.prototype.rotate( this.images[i], 90 ),
- this.images[i].__tx,
- this.images[i].__ty );
- if ( outline ) {
- ctxx.strokeStyle= 'red';
- ctxx.strokeRect(
- this.images[i].__tx,
- this.images[i].__ty,
- this.images[i].__w,
- this.images[i].__h );
- }
- }
- if (outline) {
- ctxx.strokeStyle= 'red';
- ctxx.strokeRect(0,0,this.width,this.height);
- }
- return canvass;
- },
- packImage : function(img) {
- var newWidth, newHeight;
- if ( img.inverted ) {
- newWidth= img.height;
- newHeight= img.width;
- } else {
- newWidth= img.width;
- newHeight= img.height;
- }
- var w= newWidth;
- var h= newHeight;
- var mod;
- // dejamos un poco de espacio para que las texturas no se pisen.
- // coordenadas normalizadas 0..1 dan problemas cuando las texturas no estan
- // alineadas a posicion mod 4,8...
- if ( w && this.padding ) {
- mod= this.padding;
- if ( w+mod<=this.width ) {
- w+=mod;
- }
- }
- if ( h && this.padding ) {
- mod= this.padding;
- if ( h+mod<=this.height ) {
- h+=mod;
- }
- }
-
- var where= this.scan.whereFitsChunk( w, h );
- if ( null!==where ) {
- this.images.push( img );
- img.__tx= where.x;
- img.__ty= where.y;
- img.__u= where.x / this.width;
- img.__v= where.y / this.height;
- img.__u1= (where.x+newWidth) / this.width;
- img.__v1= (where.y+newHeight) / this.height;
- img.__texturePage= this;
- img.__w= newWidth;
- img.__h= newHeight;
- this.scan.substract(where.x,where.y,w,h);
- } else {
- CAAT.log('Imagen ',img.src,' de tamano ',img.width,img.height,' no cabe.');
- }
- },
- changeHeuristic : function(criteria) {
- this.criteria= criteria;
- }
- };
- })();
- (function() {
- CAAT.GLTexturePageManager= function() {
- this.pages= [];
- return this;
- };
- CAAT.GLTexturePageManager.prototype= {
- pages: null,
- createPages: function(gl,width,height,imagesCache) {
- var end= false;
- while( !end ) {
- var page= new CAAT.GLTexturePage(width,height);
- page.create(imagesCache);
- page.initialize(gl);
- page.endCreation();
- this.pages.push(page);
- end= true;
- for( var i=0; i<imagesCache.length; i++ ) {
- // imagen sin asociacion de textura
- if ( !imagesCache[i].image.__texturePage ) {
- // cabe en la pagina ?? continua con otras paginas.
- if ( imagesCache[i].image.width<=width && imagesCache[i].image.height<=height ) {
- end= false;
- }
- break;
- }
- }
- }
- },
- deletePages : function() {
- for( var i=0; i<this.pages.length; i++ ) {
- this.pages[i].deletePage();
- }
- this.pages= null;
- }
- };
- })();
|