Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856268572685826859268602686126862268632686426865268662686726868268692687026871268722687326874268752687626877268782687926880268812688226883268842688526886268872688826889268902689126892268932689426895268962689726898268992690026901269022690326904269052690626907269082690926910269112691226913269142691526916269172691826919269202692126922269232692426925269262692726928269292693026931269322693326934269352693626937269382693926940269412694226943269442694526946269472694826949269502695126952269532695426955269562695726958269592696026961269622696326964269652696626967269682696926970269712697226973269742697526976269772697826979269802698126982269832698426985269862698726988269892699026991269922699326994269952699626997269982699927000270012700227003270042700527006270072700827009270102701127012270132701427015270162701727018270192702027021270222702327024270252702627027270282702927030270312703227033270342703527036270372703827039270402704127042270432704427045270462704727048270492705027051270522705327054270552705627057270582705927060270612706227063270642706527066270672706827069270702707127072270732707427075270762707727078270792708027081270822708327084270852708627087270882708927090270912709227093270942709527096270972709827099271002710127102271032710427105271062710727108271092711027111271122711327114271152711627117271182711927120271212712227123271242712527126271272712827129271302713127132271332713427135271362713727138271392714027141271422714327144271452714627147271482714927150271512715227153271542715527156271572715827159271602716127162271632716427165271662716727168271692717027171271722717327174271752717627177271782717927180271812718227183271842718527186271872718827189271902719127192271932719427195271962719727198271992720027201272022720327204272052720627207272082720927210272112721227213272142721527216272172721827219272202722127222272232722427225272262722727228272292723027231272322723327234272352723627237272382723927240272412724227243272442724527246272472724827249272502725127252272532725427255272562725727258272592726027261272622726327264272652726627267272682726927270272712727227273272742727527276272772727827279272802728127282272832728427285272862728727288272892729027291272922729327294272952729627297272982729927300273012730227303273042730527306273072730827309273102731127312273132731427315273162731727318273192732027321273222732327324273252732627327273282732927330273312733227333273342733527336273372733827339273402734127342273432734427345273462734727348273492735027351273522735327354273552735627357273582735927360273612736227363273642736527366273672736827369273702737127372273732737427375273762737727378273792738027381273822738327384273852738627387273882738927390273912739227393273942739527396273972739827399274002740127402274032740427405274062740727408274092741027411274122741327414274152741627417274182741927420274212742227423274242742527426274272742827429274302743127432274332743427435274362743727438274392744027441274422744327444274452744627447274482744927450274512745227453274542745527456274572745827459274602746127462274632746427465274662746727468274692747027471274722747327474274752747627477274782747927480274812748227483274842748527486274872748827489274902749127492274932749427495274962749727498274992750027501275022750327504275052750627507275082750927510275112751227513275142751527516275172751827519275202752127522275232752427525275262752727528275292753027531275322753327534275352753627537275382753927540275412754227543275442754527546275472754827549275502755127552275532755427555275562755727558275592756027561275622756327564275652756627567275682756927570275712757227573275742757527576275772757827579275802758127582275832758427585275862758727588275892759027591275922759327594275952759627597275982759927600276012760227603276042760527606276072760827609276102761127612276132761427615276162761727618276192762027621276222762327624276252762627627276282762927630276312763227633276342763527636276372763827639276402764127642276432764427645276462764727648276492765027651276522765327654276552765627657276582765927660276612766227663276642766527666276672766827669276702767127672276732767427675276762767727678276792768027681276822768327684276852768627687276882768927690276912769227693276942769527696276972769827699277002770127702277032770427705277062770727708277092771027711277122771327714277152771627717277182771927720277212772227723277242772527726277272772827729277302773127732277332773427735277362773727738277392774027741277422774327744277452774627747277482774927750277512775227753277542775527756277572775827759277602776127762277632776427765277662776727768277692777027771277722777327774277752777627777277782777927780277812778227783277842778527786277872778827789277902779127792277932779427795277962779727798277992780027801278022780327804278052780627807278082780927810278112781227813278142781527816278172781827819278202782127822278232782427825278262782727828278292783027831278322783327834278352783627837278382783927840278412784227843278442784527846278472784827849278502785127852278532785427855278562785727858278592786027861278622786327864278652786627867278682786927870278712787227873278742787527876278772787827879278802788127882278832788427885278862788727888278892789027891278922789327894278952789627897278982789927900279012790227903279042790527906279072790827909279102791127912279132791427915279162791727918279192792027921279222792327924279252792627927279282792927930279312793227933279342793527936279372793827939279402794127942279432794427945279462794727948279492795027951279522795327954279552795627957279582795927960279612796227963279642796527966279672796827969279702797127972279732797427975279762797727978279792798027981279822798327984279852798627987279882798927990279912799227993279942799527996279972799827999280002800128002280032800428005280062800728008280092801028011280122801328014280152801628017280182801928020280212802228023280242802528026280272802828029280302803128032280332803428035280362803728038280392804028041280422804328044280452804628047280482804928050280512805228053280542805528056280572805828059280602806128062280632806428065280662806728068280692807028071280722807328074280752807628077280782807928080280812808228083280842808528086280872808828089280902809128092280932809428095280962809728098280992810028101281022810328104281052810628107281082810928110281112811228113281142811528116281172811828119281202812128122281232812428125281262812728128281292813028131281322813328134281352813628137281382813928140281412814228143281442814528146281472814828149281502815128152281532815428155281562815728158281592816028161281622816328164281652816628167281682816928170281712817228173281742817528176281772817828179281802818128182281832818428185281862818728188281892819028191281922819328194281952819628197281982819928200282012820228203282042820528206282072820828209282102821128212282132821428215282162821728218282192822028221282222822328224282252822628227282282822928230282312823228233282342823528236282372823828239282402824128242282432824428245282462824728248282492825028251282522825328254282552825628257282582825928260282612826228263282642826528266282672826828269282702827128272282732827428275282762827728278282792828028281282822828328284282852828628287282882828928290282912829228293282942829528296282972829828299283002830128302283032830428305283062830728308283092831028311283122831328314283152831628317283182831928320283212832228323283242832528326283272832828329283302833128332283332833428335283362833728338283392834028341283422834328344283452834628347283482834928350283512835228353283542835528356283572835828359283602836128362283632836428365283662836728368283692837028371283722837328374283752837628377283782837928380283812838228383283842838528386283872838828389283902839128392283932839428395283962839728398283992840028401284022840328404284052840628407284082840928410284112841228413284142841528416284172841828419284202842128422284232842428425284262842728428284292843028431284322843328434284352843628437284382843928440284412844228443284442844528446284472844828449284502845128452284532845428455284562845728458284592846028461284622846328464284652846628467284682846928470284712847228473284742847528476284772847828479284802848128482284832848428485284862848728488284892849028491284922849328494284952849628497284982849928500285012850228503285042850528506285072850828509285102851128512285132851428515285162851728518285192852028521285222852328524285252852628527285282852928530285312853228533285342853528536285372853828539285402854128542285432854428545285462854728548285492855028551285522855328554285552855628557285582855928560285612856228563285642856528566285672856828569285702857128572285732857428575285762857728578285792858028581285822858328584285852858628587285882858928590285912859228593285942859528596285972859828599286002860128602286032860428605286062860728608286092861028611286122861328614286152861628617286182861928620286212862228623286242862528626286272862828629286302863128632286332863428635286362863728638286392864028641286422864328644286452864628647286482864928650286512865228653286542865528656286572865828659286602866128662286632866428665286662866728668286692867028671286722867328674286752867628677286782867928680286812868228683286842868528686286872868828689286902869128692286932869428695286962869728698286992870028701287022870328704287052870628707287082870928710287112871228713287142871528716287172871828719287202872128722287232872428725287262872728728287292873028731287322873328734287352873628737287382873928740287412874228743287442874528746287472874828749287502875128752287532875428755287562875728758287592876028761287622876328764287652876628767287682876928770287712877228773287742877528776287772877828779287802878128782287832878428785287862878728788287892879028791287922879328794287952879628797287982879928800288012880228803288042880528806288072880828809288102881128812288132881428815288162881728818288192882028821288222882328824288252882628827288282882928830288312883228833288342883528836288372883828839288402884128842288432884428845288462884728848288492885028851288522885328854288552885628857288582885928860288612886228863288642886528866288672886828869288702887128872288732887428875288762887728878288792888028881288822888328884288852888628887288882888928890288912889228893288942889528896288972889828899289002890128902289032890428905289062890728908289092891028911289122891328914289152891628917289182891928920289212892228923289242892528926289272892828929289302893128932289332893428935289362893728938289392894028941289422894328944289452894628947289482894928950289512895228953289542895528956289572895828959289602896128962289632896428965289662896728968289692897028971289722897328974289752897628977289782897928980289812898228983289842898528986289872898828989289902899128992289932899428995289962899728998289992900029001290022900329004290052900629007290082900929010290112901229013290142901529016290172901829019290202902129022290232902429025290262902729028290292903029031290322903329034290352903629037290382903929040290412904229043290442904529046290472904829049290502905129052290532905429055290562905729058290592906029061290622906329064290652906629067290682906929070290712907229073290742907529076290772907829079290802908129082290832908429085290862908729088290892909029091290922909329094290952909629097290982909929100291012910229103291042910529106291072910829109291102911129112291132911429115291162911729118291192912029121291222912329124291252912629127291282912929130291312913229133291342913529136291372913829139291402914129142291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163291642916529166291672916829169291702917129172291732917429175291762917729178291792918029181291822918329184291852918629187291882918929190291912919229193291942919529196291972919829199292002920129202292032920429205292062920729208292092921029211292122921329214292152921629217292182921929220292212922229223292242922529226292272922829229292302923129232292332923429235292362923729238292392924029241292422924329244292452924629247292482924929250292512925229253292542925529256292572925829259292602926129262292632926429265292662926729268292692927029271292722927329274292752927629277292782927929280292812928229283292842928529286292872928829289292902929129292292932929429295292962929729298292992930029301293022930329304293052930629307293082930929310293112931229313293142931529316293172931829319293202932129322293232932429325293262932729328293292933029331293322933329334293352933629337293382933929340293412934229343293442934529346293472934829349293502935129352293532935429355293562935729358293592936029361293622936329364293652936629367293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388293892939029391293922939329394293952939629397293982939929400294012940229403294042940529406294072940829409294102941129412294132941429415294162941729418294192942029421294222942329424294252942629427294282942929430294312943229433294342943529436294372943829439294402944129442294432944429445294462944729448294492945029451294522945329454294552945629457294582945929460294612946229463294642946529466294672946829469294702947129472294732947429475294762947729478294792948029481294822948329484294852948629487294882948929490294912949229493294942949529496294972949829499295002950129502295032950429505295062950729508295092951029511295122951329514295152951629517295182951929520295212952229523295242952529526295272952829529295302953129532295332953429535295362953729538295392954029541295422954329544295452954629547295482954929550295512955229553295542955529556295572955829559295602956129562295632956429565295662956729568295692957029571295722957329574295752957629577295782957929580295812958229583295842958529586295872958829589295902959129592295932959429595295962959729598295992960029601296022960329604296052960629607296082960929610296112961229613296142961529616296172961829619296202962129622296232962429625296262962729628296292963029631296322963329634296352963629637296382963929640296412964229643296442964529646296472964829649296502965129652296532965429655296562965729658296592966029661296622966329664296652966629667296682966929670296712967229673296742967529676296772967829679296802968129682296832968429685296862968729688296892969029691296922969329694296952969629697296982969929700297012970229703297042970529706297072970829709297102971129712297132971429715297162971729718297192972029721297222972329724297252972629727297282972929730297312973229733297342973529736297372973829739297402974129742297432974429745297462974729748297492975029751297522975329754297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775297762977729778297792978029781297822978329784297852978629787297882978929790297912979229793297942979529796297972979829799298002980129802298032980429805298062980729808298092981029811298122981329814298152981629817298182981929820298212982229823298242982529826298272982829829298302983129832298332983429835298362983729838298392984029841298422984329844298452984629847298482984929850298512985229853298542985529856298572985829859298602986129862298632986429865298662986729868298692987029871298722987329874298752987629877298782987929880298812988229883298842988529886298872988829889298902989129892298932989429895298962989729898298992990029901299022990329904299052990629907299082990929910299112991229913299142991529916299172991829919299202992129922299232992429925299262992729928299292993029931299322993329934299352993629937299382993929940299412994229943299442994529946299472994829949299502995129952299532995429955299562995729958299592996029961299622996329964299652996629967299682996929970299712997229973299742997529976299772997829979299802998129982299832998429985299862998729988299892999029991299922999329994299952999629997299982999930000300013000230003300043000530006300073000830009300103001130012300133001430015300163001730018300193002030021300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042300433004430045300463004730048300493005030051300523005330054300553005630057300583005930060300613006230063300643006530066300673006830069300703007130072300733007430075300763007730078300793008030081300823008330084300853008630087300883008930090300913009230093300943009530096300973009830099301003010130102301033010430105301063010730108301093011030111301123011330114301153011630117301183011930120301213012230123301243012530126301273012830129301303013130132301333013430135301363013730138301393014030141301423014330144301453014630147301483014930150301513015230153301543015530156301573015830159301603016130162301633016430165301663016730168301693017030171301723017330174301753017630177301783017930180301813018230183301843018530186301873018830189301903019130192301933019430195301963019730198301993020030201302023020330204302053020630207302083020930210302113021230213302143021530216302173021830219302203022130222302233022430225302263022730228302293023030231302323023330234302353023630237302383023930240302413024230243302443024530246302473024830249302503025130252302533025430255302563025730258302593026030261302623026330264302653026630267302683026930270302713027230273302743027530276302773027830279302803028130282302833028430285302863028730288302893029030291302923029330294302953029630297302983029930300303013030230303303043030530306303073030830309303103031130312303133031430315303163031730318303193032030321303223032330324303253032630327303283032930330303313033230333303343033530336303373033830339303403034130342303433034430345303463034730348303493035030351303523035330354303553035630357303583035930360303613036230363303643036530366303673036830369303703037130372303733037430375303763037730378303793038030381303823038330384303853038630387303883038930390303913039230393303943039530396303973039830399304003040130402304033040430405304063040730408304093041030411304123041330414304153041630417304183041930420304213042230423304243042530426304273042830429304303043130432304333043430435304363043730438304393044030441304423044330444304453044630447304483044930450304513045230453304543045530456304573045830459304603046130462304633046430465304663046730468304693047030471304723047330474304753047630477304783047930480304813048230483304843048530486304873048830489304903049130492304933049430495304963049730498304993050030501305023050330504305053050630507305083050930510305113051230513305143051530516305173051830519305203052130522305233052430525305263052730528305293053030531305323053330534305353053630537305383053930540305413054230543305443054530546305473054830549305503055130552305533055430555305563055730558305593056030561305623056330564305653056630567305683056930570305713057230573305743057530576305773057830579305803058130582305833058430585305863058730588305893059030591305923059330594305953059630597305983059930600306013060230603306043060530606306073060830609306103061130612306133061430615306163061730618306193062030621306223062330624306253062630627306283062930630306313063230633306343063530636306373063830639306403064130642306433064430645306463064730648306493065030651306523065330654306553065630657306583065930660306613066230663306643066530666306673066830669306703067130672306733067430675306763067730678306793068030681306823068330684306853068630687306883068930690306913069230693306943069530696306973069830699307003070130702307033070430705307063070730708307093071030711307123071330714307153071630717307183071930720307213072230723307243072530726307273072830729307303073130732307333073430735307363073730738307393074030741307423074330744307453074630747307483074930750307513075230753307543075530756307573075830759307603076130762307633076430765307663076730768307693077030771307723077330774307753077630777307783077930780307813078230783307843078530786307873078830789307903079130792307933079430795307963079730798307993080030801308023080330804308053080630807308083080930810308113081230813308143081530816308173081830819308203082130822308233082430825308263082730828308293083030831308323083330834308353083630837308383083930840308413084230843308443084530846308473084830849308503085130852308533085430855308563085730858308593086030861308623086330864308653086630867308683086930870308713087230873308743087530876308773087830879308803088130882308833088430885308863088730888308893089030891308923089330894308953089630897308983089930900309013090230903309043090530906309073090830909309103091130912309133091430915309163091730918309193092030921309223092330924309253092630927309283092930930309313093230933309343093530936309373093830939309403094130942309433094430945309463094730948309493095030951309523095330954309553095630957309583095930960309613096230963309643096530966309673096830969309703097130972309733097430975309763097730978309793098030981309823098330984309853098630987309883098930990309913099230993309943099530996309973099830999310003100131002310033100431005310063100731008310093101031011310123101331014310153101631017310183101931020310213102231023310243102531026310273102831029310303103131032310333103431035310363103731038310393104031041310423104331044310453104631047310483104931050310513105231053310543105531056310573105831059310603106131062310633106431065310663106731068310693107031071310723107331074310753107631077310783107931080310813108231083310843108531086310873108831089310903109131092310933109431095310963109731098310993110031101311023110331104311053110631107311083110931110311113111231113311143111531116311173111831119311203112131122311233112431125311263112731128311293113031131311323113331134311353113631137311383113931140311413114231143311443114531146311473114831149311503115131152311533115431155311563115731158311593116031161311623116331164311653116631167311683116931170311713117231173311743117531176311773117831179311803118131182311833118431185311863118731188311893119031191311923119331194311953119631197311983119931200312013120231203312043120531206312073120831209312103121131212312133121431215312163121731218312193122031221312223122331224312253122631227312283122931230312313123231233312343123531236312373123831239312403124131242312433124431245312463124731248312493125031251312523125331254312553125631257312583125931260312613126231263312643126531266312673126831269312703127131272312733127431275312763127731278312793128031281312823128331284312853128631287312883128931290312913129231293312943129531296312973129831299313003130131302313033130431305313063130731308313093131031311313123131331314313153131631317313183131931320313213132231323313243132531326313273132831329313303133131332313333133431335313363133731338313393134031341313423134331344313453134631347313483134931350313513135231353313543135531356313573135831359313603136131362313633136431365313663136731368313693137031371313723137331374313753137631377313783137931380313813138231383313843138531386313873138831389313903139131392313933139431395313963139731398313993140031401314023140331404314053140631407314083140931410314113141231413314143141531416314173141831419314203142131422314233142431425314263142731428314293143031431314323143331434314353143631437314383143931440314413144231443314443144531446314473144831449314503145131452314533145431455314563145731458314593146031461314623146331464314653146631467314683146931470314713147231473314743147531476314773147831479314803148131482314833148431485314863148731488314893149031491314923149331494314953149631497314983149931500315013150231503315043150531506315073150831509315103151131512315133151431515315163151731518315193152031521315223152331524315253152631527315283152931530315313153231533315343153531536315373153831539315403154131542315433154431545315463154731548315493155031551315523155331554315553155631557315583155931560315613156231563315643156531566315673156831569315703157131572315733157431575315763157731578315793158031581315823158331584315853158631587315883158931590315913159231593315943159531596315973159831599316003160131602316033160431605316063160731608316093161031611316123161331614316153161631617316183161931620316213162231623316243162531626316273162831629316303163131632316333163431635316363163731638316393164031641316423164331644316453164631647316483164931650316513165231653316543165531656316573165831659316603166131662316633166431665316663166731668316693167031671316723167331674316753167631677316783167931680316813168231683316843168531686316873168831689316903169131692316933169431695316963169731698316993170031701317023170331704317053170631707317083170931710317113171231713317143171531716317173171831719317203172131722317233172431725317263172731728317293173031731317323173331734317353173631737317383173931740317413174231743317443174531746317473174831749317503175131752317533175431755317563175731758317593176031761317623176331764317653176631767317683176931770317713177231773317743177531776317773177831779317803178131782317833178431785317863178731788317893179031791317923179331794317953179631797317983179931800318013180231803318043180531806318073180831809318103181131812318133181431815318163181731818318193182031821318223182331824318253182631827318283182931830318313183231833318343183531836318373183831839318403184131842318433184431845318463184731848318493185031851318523185331854318553185631857318583185931860318613186231863318643186531866318673186831869318703187131872318733187431875318763187731878318793188031881318823188331884318853188631887318883188931890318913189231893318943189531896318973189831899319003190131902319033190431905319063190731908319093191031911319123191331914319153191631917319183191931920319213192231923319243192531926319273192831929319303193131932319333193431935319363193731938319393194031941319423194331944319453194631947319483194931950319513195231953319543195531956319573195831959319603196131962319633196431965319663196731968319693197031971319723197331974319753197631977319783197931980319813198231983319843198531986319873198831989319903199131992319933199431995319963199731998319993200032001320023200332004320053200632007320083200932010320113201232013320143201532016320173201832019320203202132022320233202432025320263202732028320293203032031320323203332034320353203632037320383203932040320413204232043320443204532046320473204832049320503205132052320533205432055320563205732058320593206032061320623206332064320653206632067320683206932070320713207232073320743207532076320773207832079320803208132082320833208432085320863208732088320893209032091320923209332094320953209632097320983209932100321013210232103321043210532106321073210832109321103211132112321133211432115321163211732118321193212032121321223212332124321253212632127321283212932130321313213232133321343213532136321373213832139321403214132142321433214432145321463214732148321493215032151321523215332154321553215632157321583215932160321613216232163321643216532166321673216832169321703217132172321733217432175321763217732178321793218032181321823218332184321853218632187321883218932190321913219232193321943219532196321973219832199322003220132202322033220432205322063220732208322093221032211322123221332214322153221632217322183221932220322213222232223322243222532226322273222832229322303223132232322333223432235322363223732238322393224032241322423224332244322453224632247322483224932250322513225232253322543225532256322573225832259322603226132262322633226432265322663226732268322693227032271322723227332274322753227632277322783227932280322813228232283322843228532286322873228832289322903229132292322933229432295322963229732298322993230032301323023230332304323053230632307323083230932310323113231232313323143231532316323173231832319323203232132322323233232432325323263232732328323293233032331323323233332334323353233632337323383233932340323413234232343323443234532346323473234832349323503235132352323533235432355323563235732358323593236032361323623236332364323653236632367323683236932370323713237232373323743237532376323773237832379323803238132382323833238432385323863238732388323893239032391323923239332394323953239632397323983239932400324013240232403324043240532406324073240832409324103241132412324133241432415324163241732418324193242032421324223242332424324253242632427324283242932430324313243232433324343243532436324373243832439324403244132442324433244432445324463244732448324493245032451324523245332454324553245632457324583245932460324613246232463324643246532466324673246832469324703247132472324733247432475324763247732478324793248032481324823248332484324853248632487324883248932490324913249232493324943249532496324973249832499325003250132502325033250432505325063250732508325093251032511325123251332514325153251632517325183251932520325213252232523325243252532526325273252832529325303253132532325333253432535325363253732538325393254032541325423254332544325453254632547325483254932550325513255232553325543255532556325573255832559325603256132562325633256432565325663256732568325693257032571325723257332574325753257632577325783257932580325813258232583325843258532586325873258832589325903259132592325933259432595325963259732598325993260032601326023260332604326053260632607326083260932610326113261232613326143261532616326173261832619326203262132622326233262432625326263262732628326293263032631326323263332634326353263632637326383263932640326413264232643326443264532646326473264832649326503265132652326533265432655326563265732658326593266032661326623266332664326653266632667326683266932670326713267232673326743267532676326773267832679326803268132682326833268432685326863268732688326893269032691326923269332694326953269632697326983269932700327013270232703327043270532706327073270832709327103271132712327133271432715327163271732718327193272032721327223272332724327253272632727327283272932730327313273232733327343273532736327373273832739327403274132742327433274432745327463274732748327493275032751327523275332754327553275632757327583275932760327613276232763327643276532766327673276832769327703277132772327733277432775327763277732778327793278032781327823278332784327853278632787327883278932790327913279232793327943279532796327973279832799328003280132802328033280432805328063280732808328093281032811328123281332814328153281632817328183281932820328213282232823328243282532826328273282832829328303283132832328333283432835328363283732838328393284032841328423284332844328453284632847328483284932850328513285232853328543285532856328573285832859328603286132862328633286432865328663286732868328693287032871328723287332874328753287632877328783287932880328813288232883328843288532886328873288832889328903289132892328933289432895328963289732898328993290032901329023290332904329053290632907329083290932910329113291232913329143291532916329173291832919329203292132922329233292432925329263292732928329293293032931329323293332934329353293632937329383293932940329413294232943329443294532946329473294832949329503295132952329533295432955329563295732958329593296032961329623296332964329653296632967329683296932970329713297232973329743297532976329773297832979329803298132982329833298432985329863298732988329893299032991329923299332994329953299632997329983299933000330013300233003330043300533006330073300833009330103301133012330133301433015330163301733018330193302033021330223302333024330253302633027330283302933030330313303233033330343303533036330373303833039330403304133042330433304433045330463304733048330493305033051330523305333054330553305633057330583305933060330613306233063330643306533066330673306833069330703307133072330733307433075330763307733078330793308033081330823308333084330853308633087330883308933090330913309233093330943309533096330973309833099331003310133102331033310433105331063310733108331093311033111331123311333114331153311633117331183311933120331213312233123331243312533126331273312833129331303313133132331333313433135331363313733138331393314033141331423314333144331453314633147331483314933150331513315233153331543315533156331573315833159331603316133162331633316433165331663316733168331693317033171331723317333174331753317633177331783317933180331813318233183331843318533186331873318833189331903319133192331933319433195331963319733198331993320033201332023320333204332053320633207332083320933210332113321233213332143321533216332173321833219332203322133222332233322433225332263322733228332293323033231332323323333234332353323633237332383323933240332413324233243332443324533246332473324833249332503325133252332533325433255332563325733258332593326033261332623326333264332653326633267332683326933270332713327233273332743327533276332773327833279332803328133282332833328433285332863328733288332893329033291332923329333294332953329633297332983329933300333013330233303333043330533306333073330833309333103331133312333133331433315333163331733318333193332033321333223332333324333253332633327333283332933330333313333233333333343333533336333373333833339333403334133342333433334433345333463334733348333493335033351333523335333354333553335633357333583335933360333613336233363333643336533366333673336833369333703337133372333733337433375333763337733378333793338033381333823338333384333853338633387333883338933390333913339233393333943339533396333973339833399334003340133402334033340433405334063340733408334093341033411334123341333414334153341633417334183341933420334213342233423334243342533426334273342833429334303343133432334333343433435334363343733438334393344033441334423344333444334453344633447334483344933450334513345233453334543345533456334573345833459334603346133462334633346433465334663346733468334693347033471334723347333474334753347633477334783347933480334813348233483334843348533486334873348833489334903349133492334933349433495334963349733498334993350033501335023350333504335053350633507335083350933510335113351233513335143351533516335173351833519335203352133522335233352433525335263352733528335293353033531335323353333534335353353633537335383353933540335413354233543335443354533546335473354833549335503355133552335533355433555335563355733558335593356033561335623356333564335653356633567335683356933570335713357233573335743357533576335773357833579335803358133582335833358433585335863358733588335893359033591335923359333594335953359633597335983359933600336013360233603336043360533606336073360833609336103361133612336133361433615336163361733618336193362033621336223362333624336253362633627336283362933630336313363233633336343363533636336373363833639336403364133642336433364433645336463364733648336493365033651336523365333654336553365633657336583365933660336613366233663336643366533666336673366833669336703367133672336733367433675336763367733678336793368033681336823368333684336853368633687336883368933690336913369233693336943369533696336973369833699337003370133702337033370433705337063370733708337093371033711337123371333714337153371633717337183371933720337213372233723337243372533726337273372833729337303373133732337333373433735337363373733738337393374033741337423374333744337453374633747337483374933750337513375233753337543375533756337573375833759337603376133762337633376433765337663376733768337693377033771337723377333774337753377633777337783377933780337813378233783337843378533786337873378833789337903379133792337933379433795337963379733798337993380033801338023380333804338053380633807338083380933810338113381233813338143381533816338173381833819338203382133822338233382433825338263382733828338293383033831338323383333834338353383633837338383383933840338413384233843338443384533846338473384833849338503385133852338533385433855338563385733858338593386033861338623386333864338653386633867338683386933870338713387233873338743387533876338773387833879338803388133882338833388433885338863388733888338893389033891338923389333894338953389633897338983389933900339013390233903339043390533906339073390833909339103391133912339133391433915339163391733918339193392033921339223392333924339253392633927339283392933930339313393233933339343393533936339373393833939339403394133942339433394433945339463394733948339493395033951339523395333954339553395633957339583395933960339613396233963339643396533966339673396833969339703397133972339733397433975339763397733978339793398033981339823398333984339853398633987339883398933990339913399233993339943399533996339973399833999340003400134002340033400434005340063400734008340093401034011340123401334014340153401634017340183401934020340213402234023340243402534026340273402834029340303403134032340333403434035340363403734038340393404034041340423404334044340453404634047340483404934050340513405234053340543405534056340573405834059340603406134062340633406434065340663406734068340693407034071340723407334074340753407634077340783407934080340813408234083340843408534086340873408834089340903409134092340933409434095340963409734098340993410034101341023410334104341053410634107341083410934110341113411234113341143411534116341173411834119341203412134122341233412434125341263412734128341293413034131341323413334134341353413634137341383413934140341413414234143341443414534146341473414834149341503415134152341533415434155341563415734158341593416034161341623416334164341653416634167341683416934170341713417234173341743417534176341773417834179341803418134182341833418434185341863418734188341893419034191341923419334194341953419634197341983419934200342013420234203342043420534206342073420834209342103421134212342133421434215342163421734218342193422034221342223422334224342253422634227342283422934230342313423234233342343423534236342373423834239342403424134242342433424434245342463424734248342493425034251342523425334254342553425634257342583425934260342613426234263342643426534266342673426834269342703427134272342733427434275342763427734278342793428034281342823428334284342853428634287342883428934290342913429234293342943429534296342973429834299343003430134302343033430434305343063430734308343093431034311343123431334314343153431634317343183431934320343213432234323343243432534326343273432834329343303433134332343333433434335343363433734338343393434034341343423434334344343453434634347343483434934350343513435234353343543435534356343573435834359343603436134362343633436434365343663436734368343693437034371343723437334374343753437634377343783437934380343813438234383343843438534386343873438834389343903439134392343933439434395343963439734398343993440034401344023440334404344053440634407344083440934410344113441234413344143441534416344173441834419344203442134422344233442434425344263442734428344293443034431344323443334434344353443634437344383443934440344413444234443344443444534446344473444834449344503445134452344533445434455344563445734458344593446034461344623446334464344653446634467344683446934470344713447234473344743447534476344773447834479344803448134482344833448434485344863448734488344893449034491344923449334494344953449634497344983449934500345013450234503345043450534506345073450834509345103451134512345133451434515345163451734518345193452034521345223452334524345253452634527345283452934530345313453234533345343453534536345373453834539345403454134542345433454434545345463454734548345493455034551345523455334554345553455634557345583455934560345613456234563345643456534566345673456834569345703457134572345733457434575345763457734578345793458034581345823458334584345853458634587345883458934590345913459234593345943459534596345973459834599346003460134602346033460434605346063460734608346093461034611346123461334614346153461634617346183461934620346213462234623346243462534626346273462834629346303463134632346333463434635346363463734638346393464034641346423464334644346453464634647346483464934650346513465234653346543465534656346573465834659346603466134662346633466434665346663466734668346693467034671346723467334674346753467634677346783467934680346813468234683346843468534686346873468834689346903469134692346933469434695346963469734698346993470034701347023470334704347053470634707347083470934710347113471234713347143471534716347173471834719347203472134722347233472434725347263472734728347293473034731347323473334734347353473634737347383473934740347413474234743347443474534746347473474834749347503475134752347533475434755347563475734758347593476034761347623476334764347653476634767347683476934770347713477234773347743477534776347773477834779347803478134782347833478434785347863478734788347893479034791347923479334794347953479634797347983479934800348013480234803348043480534806348073480834809348103481134812348133481434815348163481734818348193482034821348223482334824348253482634827348283482934830348313483234833348343483534836348373483834839348403484134842348433484434845348463484734848348493485034851348523485334854348553485634857348583485934860348613486234863348643486534866348673486834869348703487134872348733487434875348763487734878348793488034881348823488334884348853488634887348883488934890348913489234893348943489534896348973489834899349003490134902349033490434905349063490734908349093491034911349123491334914349153491634917349183491934920349213492234923349243492534926349273492834929349303493134932349333493434935349363493734938349393494034941349423494334944349453494634947349483494934950349513495234953349543495534956349573495834959349603496134962349633496434965349663496734968349693497034971349723497334974349753497634977349783497934980349813498234983349843498534986349873498834989349903499134992349933499434995349963499734998349993500035001350023500335004350053500635007350083500935010350113501235013350143501535016350173501835019350203502135022350233502435025350263502735028350293503035031350323503335034350353503635037350383503935040350413504235043350443504535046350473504835049350503505135052350533505435055350563505735058350593506035061350623506335064350653506635067350683506935070350713507235073350743507535076350773507835079350803508135082350833508435085350863508735088350893509035091350923509335094350953509635097350983509935100351013510235103351043510535106351073510835109351103511135112351133511435115351163511735118351193512035121351223512335124351253512635127351283512935130351313513235133351343513535136351373513835139351403514135142351433514435145351463514735148351493515035151351523515335154351553515635157351583515935160351613516235163351643516535166351673516835169351703517135172351733517435175351763517735178351793518035181351823518335184351853518635187351883518935190351913519235193351943519535196351973519835199352003520135202352033520435205352063520735208352093521035211352123521335214352153521635217352183521935220352213522235223352243522535226352273522835229352303523135232352333523435235352363523735238352393524035241352423524335244352453524635247352483524935250352513525235253352543525535256352573525835259352603526135262352633526435265352663526735268352693527035271352723527335274352753527635277352783527935280352813528235283352843528535286352873528835289352903529135292352933529435295352963529735298352993530035301353023530335304353053530635307353083530935310353113531235313353143531535316353173531835319353203532135322353233532435325353263532735328353293533035331353323533335334353353533635337353383533935340353413534235343353443534535346353473534835349353503535135352353533535435355353563535735358353593536035361353623536335364353653536635367353683536935370353713537235373353743537535376353773537835379353803538135382353833538435385353863538735388353893539035391353923539335394353953539635397353983539935400354013540235403354043540535406354073540835409354103541135412354133541435415354163541735418354193542035421354223542335424354253542635427354283542935430354313543235433354343543535436354373543835439354403544135442354433544435445354463544735448354493545035451354523545335454354553545635457354583545935460354613546235463354643546535466354673546835469354703547135472354733547435475354763547735478354793548035481354823548335484354853548635487354883548935490354913549235493354943549535496354973549835499355003550135502355033550435505355063550735508355093551035511355123551335514355153551635517355183551935520355213552235523355243552535526355273552835529355303553135532355333553435535355363553735538355393554035541355423554335544355453554635547355483554935550355513555235553355543555535556355573555835559355603556135562355633556435565355663556735568355693557035571355723557335574355753557635577355783557935580355813558235583355843558535586355873558835589355903559135592355933559435595355963559735598355993560035601356023560335604356053560635607356083560935610356113561235613356143561535616356173561835619356203562135622356233562435625356263562735628356293563035631356323563335634356353563635637356383563935640356413564235643356443564535646356473564835649356503565135652356533565435655356563565735658356593566035661356623566335664356653566635667356683566935670356713567235673356743567535676356773567835679356803568135682356833568435685356863568735688356893569035691356923569335694356953569635697356983569935700357013570235703357043570535706357073570835709357103571135712357133571435715357163571735718357193572035721357223572335724357253572635727357283572935730357313573235733357343573535736357373573835739357403574135742357433574435745357463574735748357493575035751357523575335754357553575635757357583575935760357613576235763357643576535766357673576835769357703577135772357733577435775357763577735778357793578035781357823578335784357853578635787357883578935790357913579235793357943579535796357973579835799358003580135802358033580435805358063580735808358093581035811358123581335814358153581635817358183581935820358213582235823358243582535826358273582835829358303583135832358333583435835358363583735838358393584035841358423584335844358453584635847358483584935850358513585235853358543585535856358573585835859358603586135862358633586435865358663586735868358693587035871358723587335874358753587635877358783587935880358813588235883358843588535886358873588835889358903589135892358933589435895358963589735898358993590035901359023590335904359053590635907359083590935910359113591235913359143591535916359173591835919359203592135922359233592435925359263592735928359293593035931359323593335934359353593635937359383593935940359413594235943359443594535946359473594835949359503595135952359533595435955359563595735958359593596035961359623596335964359653596635967359683596935970359713597235973359743597535976359773597835979359803598135982359833598435985359863598735988359893599035991359923599335994359953599635997359983599936000360013600236003360043600536006360073600836009360103601136012360133601436015360163601736018360193602036021360223602336024360253602636027360283602936030360313603236033360343603536036360373603836039360403604136042360433604436045360463604736048360493605036051360523605336054360553605636057360583605936060360613606236063360643606536066360673606836069360703607136072360733607436075360763607736078360793608036081360823608336084360853608636087360883608936090360913609236093360943609536096360973609836099361003610136102361033610436105361063610736108361093611036111361123611336114361153611636117361183611936120361213612236123361243612536126361273612836129361303613136132361333613436135361363613736138361393614036141361423614336144361453614636147361483614936150361513615236153361543615536156361573615836159361603616136162361633616436165361663616736168361693617036171361723617336174361753617636177361783617936180361813618236183361843618536186361873618836189361903619136192361933619436195361963619736198361993620036201362023620336204362053620636207362083620936210362113621236213362143621536216362173621836219362203622136222362233622436225362263622736228362293623036231362323623336234362353623636237362383623936240362413624236243362443624536246362473624836249362503625136252362533625436255362563625736258362593626036261362623626336264362653626636267362683626936270362713627236273362743627536276362773627836279362803628136282362833628436285362863628736288362893629036291362923629336294362953629636297362983629936300363013630236303363043630536306363073630836309363103631136312363133631436315363163631736318363193632036321363223632336324363253632636327363283632936330363313633236333363343633536336363373633836339363403634136342363433634436345363463634736348363493635036351363523635336354363553635636357363583635936360363613636236363363643636536366363673636836369363703637136372363733637436375363763637736378363793638036381363823638336384363853638636387363883638936390363913639236393363943639536396363973639836399364003640136402364033640436405364063640736408364093641036411364123641336414364153641636417364183641936420364213642236423364243642536426364273642836429364303643136432364333643436435364363643736438364393644036441364423644336444364453644636447364483644936450364513645236453364543645536456364573645836459364603646136462364633646436465364663646736468364693647036471364723647336474364753647636477364783647936480364813648236483364843648536486364873648836489364903649136492364933649436495364963649736498364993650036501365023650336504365053650636507365083650936510365113651236513365143651536516365173651836519365203652136522365233652436525365263652736528365293653036531365323653336534365353653636537365383653936540365413654236543365443654536546365473654836549365503655136552365533655436555365563655736558365593656036561365623656336564365653656636567365683656936570365713657236573365743657536576365773657836579365803658136582365833658436585365863658736588365893659036591365923659336594365953659636597365983659936600366013660236603366043660536606366073660836609366103661136612366133661436615366163661736618366193662036621366223662336624366253662636627366283662936630366313663236633366343663536636366373663836639366403664136642366433664436645366463664736648366493665036651366523665336654366553665636657366583665936660366613666236663366643666536666366673666836669366703667136672366733667436675366763667736678366793668036681366823668336684366853668636687366883668936690366913669236693366943669536696366973669836699367003670136702367033670436705367063670736708367093671036711367123671336714367153671636717367183671936720367213672236723367243672536726367273672836729367303673136732367333673436735367363673736738367393674036741367423674336744367453674636747367483674936750367513675236753367543675536756367573675836759367603676136762367633676436765367663676736768367693677036771367723677336774367753677636777367783677936780367813678236783367843678536786367873678836789367903679136792367933679436795367963679736798367993680036801368023680336804368053680636807368083680936810368113681236813368143681536816368173681836819368203682136822368233682436825368263682736828368293683036831368323683336834368353683636837368383683936840368413684236843368443684536846368473684836849368503685136852368533685436855368563685736858368593686036861368623686336864368653686636867368683686936870368713687236873368743687536876368773687836879368803688136882368833688436885368863688736888368893689036891368923689336894368953689636897368983689936900369013690236903369043690536906369073690836909369103691136912369133691436915369163691736918369193692036921369223692336924369253692636927369283692936930369313693236933369343693536936369373693836939369403694136942369433694436945369463694736948369493695036951369523695336954369553695636957369583695936960369613696236963369643696536966369673696836969369703697136972369733697436975369763697736978369793698036981369823698336984369853698636987369883698936990369913699236993369943699536996369973699836999370003700137002370033700437005370063700737008370093701037011370123701337014370153701637017370183701937020370213702237023370243702537026370273702837029370303703137032370333703437035370363703737038370393704037041370423704337044370453704637047370483704937050370513705237053370543705537056370573705837059370603706137062370633706437065370663706737068370693707037071370723707337074370753707637077370783707937080370813708237083370843708537086370873708837089370903709137092370933709437095370963709737098370993710037101371023710337104371053710637107371083710937110371113711237113371143711537116371173711837119371203712137122371233712437125371263712737128371293713037131371323713337134371353713637137371383713937140371413714237143371443714537146371473714837149371503715137152371533715437155371563715737158371593716037161371623716337164371653716637167371683716937170371713717237173371743717537176371773717837179371803718137182371833718437185371863718737188371893719037191371923719337194371953719637197371983719937200372013720237203372043720537206372073720837209372103721137212372133721437215372163721737218372193722037221372223722337224372253722637227372283722937230372313723237233372343723537236372373723837239372403724137242372433724437245372463724737248372493725037251372523725337254372553725637257372583725937260372613726237263372643726537266372673726837269372703727137272372733727437275372763727737278372793728037281372823728337284372853728637287372883728937290372913729237293372943729537296372973729837299373003730137302373033730437305373063730737308373093731037311373123731337314373153731637317373183731937320373213732237323373243732537326373273732837329373303733137332373333733437335373363733737338373393734037341373423734337344373453734637347373483734937350373513735237353373543735537356373573735837359373603736137362373633736437365373663736737368373693737037371373723737337374373753737637377373783737937380373813738237383373843738537386373873738837389373903739137392373933739437395373963739737398373993740037401374023740337404374053740637407374083740937410374113741237413374143741537416374173741837419374203742137422374233742437425374263742737428374293743037431374323743337434374353743637437374383743937440374413744237443374443744537446374473744837449374503745137452374533745437455374563745737458374593746037461374623746337464374653746637467374683746937470374713747237473374743747537476374773747837479374803748137482374833748437485374863748737488374893749037491374923749337494374953749637497374983749937500375013750237503375043750537506375073750837509375103751137512375133751437515375163751737518375193752037521375223752337524375253752637527375283752937530375313753237533375343753537536375373753837539375403754137542375433754437545375463754737548375493755037551375523755337554375553755637557375583755937560375613756237563375643756537566375673756837569375703757137572375733757437575375763757737578375793758037581375823758337584375853758637587375883758937590375913759237593375943759537596375973759837599376003760137602376033760437605376063760737608376093761037611376123761337614376153761637617376183761937620376213762237623376243762537626376273762837629376303763137632376333763437635376363763737638376393764037641376423764337644376453764637647376483764937650376513765237653376543765537656376573765837659376603766137662376633766437665376663766737668376693767037671376723767337674376753767637677376783767937680376813768237683376843768537686376873768837689376903769137692376933769437695376963769737698376993770037701377023770337704377053770637707377083770937710377113771237713377143771537716377173771837719377203772137722377233772437725377263772737728377293773037731377323773337734377353773637737377383773937740377413774237743377443774537746377473774837749377503775137752377533775437755377563775737758377593776037761377623776337764377653776637767377683776937770377713777237773377743777537776377773777837779377803778137782377833778437785377863778737788377893779037791377923779337794377953779637797377983779937800378013780237803378043780537806378073780837809378103781137812378133781437815378163781737818378193782037821378223782337824378253782637827378283782937830378313783237833378343783537836378373783837839378403784137842378433784437845378463784737848378493785037851378523785337854378553785637857378583785937860378613786237863378643786537866378673786837869378703787137872378733787437875378763787737878378793788037881378823788337884378853788637887378883788937890378913789237893378943789537896378973789837899379003790137902379033790437905379063790737908379093791037911379123791337914379153791637917379183791937920379213792237923379243792537926379273792837929379303793137932379333793437935379363793737938379393794037941379423794337944379453794637947379483794937950379513795237953379543795537956379573795837959379603796137962379633796437965379663796737968379693797037971379723797337974379753797637977379783797937980379813798237983379843798537986379873798837989379903799137992379933799437995379963799737998379993800038001380023800338004380053800638007380083800938010380113801238013380143801538016380173801838019380203802138022380233802438025380263802738028380293803038031380323803338034380353803638037380383803938040380413804238043380443804538046380473804838049380503805138052380533805438055380563805738058380593806038061380623806338064380653806638067380683806938070380713807238073380743807538076380773807838079380803808138082380833808438085380863808738088380893809038091380923809338094380953809638097380983809938100381013810238103381043810538106381073810838109381103811138112381133811438115381163811738118381193812038121381223812338124381253812638127381283812938130381313813238133381343813538136381373813838139381403814138142381433814438145381463814738148381493815038151381523815338154381553815638157381583815938160381613816238163381643816538166381673816838169381703817138172381733817438175381763817738178381793818038181381823818338184381853818638187381883818938190381913819238193381943819538196381973819838199382003820138202382033820438205382063820738208382093821038211382123821338214382153821638217382183821938220382213822238223382243822538226382273822838229382303823138232382333823438235382363823738238382393824038241382423824338244382453824638247382483824938250382513825238253382543825538256382573825838259382603826138262382633826438265382663826738268382693827038271382723827338274382753827638277382783827938280382813828238283382843828538286382873828838289382903829138292382933829438295382963829738298382993830038301383023830338304383053830638307383083830938310383113831238313383143831538316383173831838319383203832138322383233832438325383263832738328383293833038331383323833338334383353833638337383383833938340383413834238343383443834538346383473834838349383503835138352383533835438355383563835738358383593836038361383623836338364383653836638367383683836938370383713837238373383743837538376383773837838379383803838138382383833838438385383863838738388383893839038391383923839338394383953839638397383983839938400384013840238403384043840538406384073840838409384103841138412384133841438415384163841738418384193842038421384223842338424384253842638427384283842938430384313843238433384343843538436384373843838439384403844138442384433844438445384463844738448384493845038451384523845338454384553845638457384583845938460384613846238463384643846538466384673846838469384703847138472384733847438475384763847738478384793848038481384823848338484384853848638487384883848938490384913849238493384943849538496384973849838499385003850138502385033850438505385063850738508385093851038511385123851338514385153851638517385183851938520385213852238523385243852538526385273852838529385303853138532385333853438535385363853738538385393854038541385423854338544385453854638547385483854938550385513855238553385543855538556385573855838559385603856138562385633856438565385663856738568385693857038571385723857338574385753857638577385783857938580385813858238583385843858538586385873858838589385903859138592385933859438595385963859738598385993860038601386023860338604386053860638607386083860938610386113861238613386143861538616386173861838619386203862138622386233862438625386263862738628386293863038631386323863338634386353863638637386383863938640386413864238643386443864538646386473864838649386503865138652386533865438655386563865738658386593866038661386623866338664386653866638667386683866938670386713867238673386743867538676386773867838679386803868138682386833868438685386863868738688386893869038691386923869338694386953869638697386983869938700387013870238703387043870538706387073870838709387103871138712387133871438715387163871738718387193872038721387223872338724387253872638727387283872938730387313873238733387343873538736387373873838739387403874138742387433874438745387463874738748387493875038751387523875338754387553875638757387583875938760387613876238763387643876538766387673876838769387703877138772387733877438775387763877738778387793878038781387823878338784387853878638787387883878938790387913879238793387943879538796387973879838799388003880138802388033880438805388063880738808388093881038811388123881338814388153881638817388183881938820388213882238823388243882538826388273882838829388303883138832388333883438835388363883738838388393884038841388423884338844388453884638847388483884938850388513885238853388543885538856388573885838859388603886138862388633886438865388663886738868388693887038871388723887338874388753887638877388783887938880388813888238883388843888538886388873888838889388903889138892388933889438895388963889738898388993890038901389023890338904389053890638907389083890938910389113891238913389143891538916389173891838919389203892138922389233892438925389263892738928389293893038931389323893338934389353893638937389383893938940389413894238943389443894538946389473894838949389503895138952389533895438955389563895738958389593896038961389623896338964389653896638967389683896938970389713897238973389743897538976389773897838979389803898138982389833898438985389863898738988389893899038991389923899338994389953899638997389983899939000390013900239003390043900539006390073900839009390103901139012390133901439015390163901739018390193902039021390223902339024390253902639027390283902939030390313903239033390343903539036390373903839039390403904139042390433904439045390463904739048390493905039051390523905339054390553905639057390583905939060390613906239063390643906539066390673906839069390703907139072390733907439075390763907739078390793908039081390823908339084390853908639087390883908939090390913909239093390943909539096390973909839099391003910139102391033910439105391063910739108391093911039111391123911339114391153911639117391183911939120391213912239123391243912539126391273912839129391303913139132391333913439135391363913739138391393914039141391423914339144391453914639147391483914939150391513915239153391543915539156391573915839159391603916139162391633916439165391663916739168391693917039171391723917339174391753917639177391783917939180391813918239183391843918539186391873918839189391903919139192391933919439195391963919739198391993920039201392023920339204392053920639207392083920939210392113921239213392143921539216392173921839219392203922139222392233922439225392263922739228392293923039231392323923339234392353923639237392383923939240392413924239243392443924539246392473924839249392503925139252392533925439255392563925739258392593926039261392623926339264392653926639267392683926939270392713927239273392743927539276392773927839279392803928139282392833928439285392863928739288392893929039291392923929339294392953929639297392983929939300393013930239303393043930539306393073930839309393103931139312393133931439315393163931739318393193932039321393223932339324393253932639327393283932939330393313933239333393343933539336393373933839339393403934139342393433934439345393463934739348393493935039351393523935339354393553935639357393583935939360393613936239363393643936539366393673936839369393703937139372393733937439375393763937739378393793938039381393823938339384393853938639387393883938939390393913939239393393943939539396393973939839399394003940139402394033940439405394063940739408394093941039411394123941339414394153941639417394183941939420394213942239423394243942539426394273942839429394303943139432394333943439435394363943739438394393944039441394423944339444394453944639447394483944939450394513945239453394543945539456394573945839459394603946139462394633946439465394663946739468394693947039471394723947339474394753947639477394783947939480394813948239483394843948539486394873948839489394903949139492394933949439495394963949739498394993950039501395023950339504395053950639507395083950939510395113951239513395143951539516395173951839519395203952139522395233952439525395263952739528395293953039531395323953339534395353953639537395383953939540395413954239543395443954539546395473954839549395503955139552395533955439555395563955739558395593956039561395623956339564395653956639567395683956939570395713957239573395743957539576395773957839579395803958139582395833958439585395863958739588395893959039591395923959339594395953959639597395983959939600396013960239603396043960539606396073960839609396103961139612396133961439615396163961739618396193962039621396223962339624396253962639627396283962939630396313963239633396343963539636396373963839639396403964139642396433964439645396463964739648396493965039651396523965339654396553965639657396583965939660396613966239663396643966539666396673966839669396703967139672396733967439675396763967739678396793968039681396823968339684396853968639687396883968939690396913969239693396943969539696396973969839699397003970139702397033970439705397063970739708397093971039711397123971339714397153971639717397183971939720397213972239723397243972539726397273972839729397303973139732397333973439735397363973739738397393974039741397423974339744397453974639747397483974939750397513975239753397543975539756397573975839759397603976139762397633976439765397663976739768397693977039771397723977339774397753977639777397783977939780397813978239783397843978539786397873978839789397903979139792397933979439795397963979739798397993980039801398023980339804398053980639807398083980939810398113981239813398143981539816398173981839819398203982139822398233982439825398263982739828398293983039831398323983339834398353983639837398383983939840398413984239843398443984539846398473984839849398503985139852398533985439855398563985739858398593986039861398623986339864398653986639867398683986939870398713987239873398743987539876398773987839879398803988139882398833988439885398863988739888398893989039891398923989339894398953989639897398983989939900399013990239903399043990539906399073990839909399103991139912399133991439915399163991739918399193992039921399223992339924399253992639927399283992939930399313993239933399343993539936399373993839939399403994139942399433994439945399463994739948399493995039951399523995339954399553995639957399583995939960399613996239963399643996539966399673996839969399703997139972399733997439975399763997739978399793998039981399823998339984399853998639987399883998939990399913999239993399943999539996399973999839999400004000140002400034000440005400064000740008400094001040011400124001340014400154001640017400184001940020400214002240023400244002540026400274002840029400304003140032400334003440035400364003740038400394004040041400424004340044400454004640047400484004940050400514005240053400544005540056400574005840059400604006140062400634006440065400664006740068400694007040071400724007340074400754007640077400784007940080400814008240083400844008540086400874008840089400904009140092400934009440095400964009740098400994010040101401024010340104401054010640107401084010940110401114011240113401144011540116401174011840119401204012140122401234012440125401264012740128401294013040131401324013340134401354013640137401384013940140401414014240143401444014540146401474014840149401504015140152401534015440155401564015740158401594016040161401624016340164401654016640167401684016940170401714017240173401744017540176401774017840179401804018140182401834018440185401864018740188401894019040191401924019340194401954019640197401984019940200402014020240203402044020540206402074020840209402104021140212402134021440215402164021740218402194022040221402224022340224402254022640227402284022940230402314023240233402344023540236402374023840239402404024140242402434024440245402464024740248402494025040251402524025340254402554025640257402584025940260402614026240263402644026540266402674026840269402704027140272402734027440275402764027740278402794028040281402824028340284402854028640287402884028940290402914029240293402944029540296402974029840299403004030140302403034030440305403064030740308403094031040311403124031340314403154031640317403184031940320403214032240323403244032540326403274032840329403304033140332403334033440335403364033740338403394034040341403424034340344403454034640347403484034940350403514035240353403544035540356403574035840359403604036140362403634036440365403664036740368403694037040371403724037340374403754037640377403784037940380403814038240383403844038540386403874038840389403904039140392403934039440395403964039740398403994040040401404024040340404404054040640407404084040940410404114041240413404144041540416404174041840419404204042140422
  1. /**
  2. * @license
  3. * pixi.js - v3.0.10
  4. * Compiled 2016-03-31T20:39:38.722Z
  5. *
  6. * pixi.js is licensed under the MIT License.
  7. * http://www.opensource.org/licenses/mit-license.php
  8. *
  9. *
  10. * The MIT License
  11. *
  12. * Copyright (c) 2013-2015 Mathew Groves
  13. *
  14. * Permission is hereby granted, free of charge, to any person obtaining a copy
  15. * of this software and associated documentation files (the "Software"), to deal
  16. * in the Software without restriction, including without limitation the rights
  17. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  18. * copies of the Software, and to permit persons to whom the Software is
  19. * furnished to do so, subject to the following conditions:
  20. *
  21. * The above copyright notice and this permission notice shall be included in
  22. * all copies or substantial portions of the Software.
  23. *
  24. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  25. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  26. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  27. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  28. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  29. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  30. * THE SOFTWARE.
  31. *
  32. *
  33. */
  34. (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.PIXI = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  35. (function (process,global){
  36. /*!
  37. * async
  38. * https://github.com/caolan/async
  39. *
  40. * Copyright 2010-2014 Caolan McMahon
  41. * Released under the MIT license
  42. */
  43. (function () {
  44. var async = {};
  45. function noop() {}
  46. function identity(v) {
  47. return v;
  48. }
  49. function toBool(v) {
  50. return !!v;
  51. }
  52. function notId(v) {
  53. return !v;
  54. }
  55. // global on the server, window in the browser
  56. var previous_async;
  57. // Establish the root object, `window` (`self`) in the browser, `global`
  58. // on the server, or `this` in some virtual machines. We use `self`
  59. // instead of `window` for `WebWorker` support.
  60. var root = typeof self === 'object' && self.self === self && self ||
  61. typeof global === 'object' && global.global === global && global ||
  62. this;
  63. if (root != null) {
  64. previous_async = root.async;
  65. }
  66. async.noConflict = function () {
  67. root.async = previous_async;
  68. return async;
  69. };
  70. function only_once(fn) {
  71. return function() {
  72. if (fn === null) throw new Error("Callback was already called.");
  73. fn.apply(this, arguments);
  74. fn = null;
  75. };
  76. }
  77. function _once(fn) {
  78. return function() {
  79. if (fn === null) return;
  80. fn.apply(this, arguments);
  81. fn = null;
  82. };
  83. }
  84. //// cross-browser compatiblity functions ////
  85. var _toString = Object.prototype.toString;
  86. var _isArray = Array.isArray || function (obj) {
  87. return _toString.call(obj) === '[object Array]';
  88. };
  89. // Ported from underscore.js isObject
  90. var _isObject = function(obj) {
  91. var type = typeof obj;
  92. return type === 'function' || type === 'object' && !!obj;
  93. };
  94. function _isArrayLike(arr) {
  95. return _isArray(arr) || (
  96. // has a positive integer length property
  97. typeof arr.length === "number" &&
  98. arr.length >= 0 &&
  99. arr.length % 1 === 0
  100. );
  101. }
  102. function _arrayEach(arr, iterator) {
  103. var index = -1,
  104. length = arr.length;
  105. while (++index < length) {
  106. iterator(arr[index], index, arr);
  107. }
  108. }
  109. function _map(arr, iterator) {
  110. var index = -1,
  111. length = arr.length,
  112. result = Array(length);
  113. while (++index < length) {
  114. result[index] = iterator(arr[index], index, arr);
  115. }
  116. return result;
  117. }
  118. function _range(count) {
  119. return _map(Array(count), function (v, i) { return i; });
  120. }
  121. function _reduce(arr, iterator, memo) {
  122. _arrayEach(arr, function (x, i, a) {
  123. memo = iterator(memo, x, i, a);
  124. });
  125. return memo;
  126. }
  127. function _forEachOf(object, iterator) {
  128. _arrayEach(_keys(object), function (key) {
  129. iterator(object[key], key);
  130. });
  131. }
  132. function _indexOf(arr, item) {
  133. for (var i = 0; i < arr.length; i++) {
  134. if (arr[i] === item) return i;
  135. }
  136. return -1;
  137. }
  138. var _keys = Object.keys || function (obj) {
  139. var keys = [];
  140. for (var k in obj) {
  141. if (obj.hasOwnProperty(k)) {
  142. keys.push(k);
  143. }
  144. }
  145. return keys;
  146. };
  147. function _keyIterator(coll) {
  148. var i = -1;
  149. var len;
  150. var keys;
  151. if (_isArrayLike(coll)) {
  152. len = coll.length;
  153. return function next() {
  154. i++;
  155. return i < len ? i : null;
  156. };
  157. } else {
  158. keys = _keys(coll);
  159. len = keys.length;
  160. return function next() {
  161. i++;
  162. return i < len ? keys[i] : null;
  163. };
  164. }
  165. }
  166. // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html)
  167. // This accumulates the arguments passed into an array, after a given index.
  168. // From underscore.js (https://github.com/jashkenas/underscore/pull/2140).
  169. function _restParam(func, startIndex) {
  170. startIndex = startIndex == null ? func.length - 1 : +startIndex;
  171. return function() {
  172. var length = Math.max(arguments.length - startIndex, 0);
  173. var rest = Array(length);
  174. for (var index = 0; index < length; index++) {
  175. rest[index] = arguments[index + startIndex];
  176. }
  177. switch (startIndex) {
  178. case 0: return func.call(this, rest);
  179. case 1: return func.call(this, arguments[0], rest);
  180. }
  181. // Currently unused but handle cases outside of the switch statement:
  182. // var args = Array(startIndex + 1);
  183. // for (index = 0; index < startIndex; index++) {
  184. // args[index] = arguments[index];
  185. // }
  186. // args[startIndex] = rest;
  187. // return func.apply(this, args);
  188. };
  189. }
  190. function _withoutIndex(iterator) {
  191. return function (value, index, callback) {
  192. return iterator(value, callback);
  193. };
  194. }
  195. //// exported async module functions ////
  196. //// nextTick implementation with browser-compatible fallback ////
  197. // capture the global reference to guard against fakeTimer mocks
  198. var _setImmediate = typeof setImmediate === 'function' && setImmediate;
  199. var _delay = _setImmediate ? function(fn) {
  200. // not a direct alias for IE10 compatibility
  201. _setImmediate(fn);
  202. } : function(fn) {
  203. setTimeout(fn, 0);
  204. };
  205. if (typeof process === 'object' && typeof process.nextTick === 'function') {
  206. async.nextTick = process.nextTick;
  207. } else {
  208. async.nextTick = _delay;
  209. }
  210. async.setImmediate = _setImmediate ? _delay : async.nextTick;
  211. async.forEach =
  212. async.each = function (arr, iterator, callback) {
  213. return async.eachOf(arr, _withoutIndex(iterator), callback);
  214. };
  215. async.forEachSeries =
  216. async.eachSeries = function (arr, iterator, callback) {
  217. return async.eachOfSeries(arr, _withoutIndex(iterator), callback);
  218. };
  219. async.forEachLimit =
  220. async.eachLimit = function (arr, limit, iterator, callback) {
  221. return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback);
  222. };
  223. async.forEachOf =
  224. async.eachOf = function (object, iterator, callback) {
  225. callback = _once(callback || noop);
  226. object = object || [];
  227. var iter = _keyIterator(object);
  228. var key, completed = 0;
  229. while ((key = iter()) != null) {
  230. completed += 1;
  231. iterator(object[key], key, only_once(done));
  232. }
  233. if (completed === 0) callback(null);
  234. function done(err) {
  235. completed--;
  236. if (err) {
  237. callback(err);
  238. }
  239. // Check key is null in case iterator isn't exhausted
  240. // and done resolved synchronously.
  241. else if (key === null && completed <= 0) {
  242. callback(null);
  243. }
  244. }
  245. };
  246. async.forEachOfSeries =
  247. async.eachOfSeries = function (obj, iterator, callback) {
  248. callback = _once(callback || noop);
  249. obj = obj || [];
  250. var nextKey = _keyIterator(obj);
  251. var key = nextKey();
  252. function iterate() {
  253. var sync = true;
  254. if (key === null) {
  255. return callback(null);
  256. }
  257. iterator(obj[key], key, only_once(function (err) {
  258. if (err) {
  259. callback(err);
  260. }
  261. else {
  262. key = nextKey();
  263. if (key === null) {
  264. return callback(null);
  265. } else {
  266. if (sync) {
  267. async.setImmediate(iterate);
  268. } else {
  269. iterate();
  270. }
  271. }
  272. }
  273. }));
  274. sync = false;
  275. }
  276. iterate();
  277. };
  278. async.forEachOfLimit =
  279. async.eachOfLimit = function (obj, limit, iterator, callback) {
  280. _eachOfLimit(limit)(obj, iterator, callback);
  281. };
  282. function _eachOfLimit(limit) {
  283. return function (obj, iterator, callback) {
  284. callback = _once(callback || noop);
  285. obj = obj || [];
  286. var nextKey = _keyIterator(obj);
  287. if (limit <= 0) {
  288. return callback(null);
  289. }
  290. var done = false;
  291. var running = 0;
  292. var errored = false;
  293. (function replenish () {
  294. if (done && running <= 0) {
  295. return callback(null);
  296. }
  297. while (running < limit && !errored) {
  298. var key = nextKey();
  299. if (key === null) {
  300. done = true;
  301. if (running <= 0) {
  302. callback(null);
  303. }
  304. return;
  305. }
  306. running += 1;
  307. iterator(obj[key], key, only_once(function (err) {
  308. running -= 1;
  309. if (err) {
  310. callback(err);
  311. errored = true;
  312. }
  313. else {
  314. replenish();
  315. }
  316. }));
  317. }
  318. })();
  319. };
  320. }
  321. function doParallel(fn) {
  322. return function (obj, iterator, callback) {
  323. return fn(async.eachOf, obj, iterator, callback);
  324. };
  325. }
  326. function doParallelLimit(fn) {
  327. return function (obj, limit, iterator, callback) {
  328. return fn(_eachOfLimit(limit), obj, iterator, callback);
  329. };
  330. }
  331. function doSeries(fn) {
  332. return function (obj, iterator, callback) {
  333. return fn(async.eachOfSeries, obj, iterator, callback);
  334. };
  335. }
  336. function _asyncMap(eachfn, arr, iterator, callback) {
  337. callback = _once(callback || noop);
  338. arr = arr || [];
  339. var results = _isArrayLike(arr) ? [] : {};
  340. eachfn(arr, function (value, index, callback) {
  341. iterator(value, function (err, v) {
  342. results[index] = v;
  343. callback(err);
  344. });
  345. }, function (err) {
  346. callback(err, results);
  347. });
  348. }
  349. async.map = doParallel(_asyncMap);
  350. async.mapSeries = doSeries(_asyncMap);
  351. async.mapLimit = doParallelLimit(_asyncMap);
  352. // reduce only has a series version, as doing reduce in parallel won't
  353. // work in many situations.
  354. async.inject =
  355. async.foldl =
  356. async.reduce = function (arr, memo, iterator, callback) {
  357. async.eachOfSeries(arr, function (x, i, callback) {
  358. iterator(memo, x, function (err, v) {
  359. memo = v;
  360. callback(err);
  361. });
  362. }, function (err) {
  363. callback(err, memo);
  364. });
  365. };
  366. async.foldr =
  367. async.reduceRight = function (arr, memo, iterator, callback) {
  368. var reversed = _map(arr, identity).reverse();
  369. async.reduce(reversed, memo, iterator, callback);
  370. };
  371. async.transform = function (arr, memo, iterator, callback) {
  372. if (arguments.length === 3) {
  373. callback = iterator;
  374. iterator = memo;
  375. memo = _isArray(arr) ? [] : {};
  376. }
  377. async.eachOf(arr, function(v, k, cb) {
  378. iterator(memo, v, k, cb);
  379. }, function(err) {
  380. callback(err, memo);
  381. });
  382. };
  383. function _filter(eachfn, arr, iterator, callback) {
  384. var results = [];
  385. eachfn(arr, function (x, index, callback) {
  386. iterator(x, function (v) {
  387. if (v) {
  388. results.push({index: index, value: x});
  389. }
  390. callback();
  391. });
  392. }, function () {
  393. callback(_map(results.sort(function (a, b) {
  394. return a.index - b.index;
  395. }), function (x) {
  396. return x.value;
  397. }));
  398. });
  399. }
  400. async.select =
  401. async.filter = doParallel(_filter);
  402. async.selectLimit =
  403. async.filterLimit = doParallelLimit(_filter);
  404. async.selectSeries =
  405. async.filterSeries = doSeries(_filter);
  406. function _reject(eachfn, arr, iterator, callback) {
  407. _filter(eachfn, arr, function(value, cb) {
  408. iterator(value, function(v) {
  409. cb(!v);
  410. });
  411. }, callback);
  412. }
  413. async.reject = doParallel(_reject);
  414. async.rejectLimit = doParallelLimit(_reject);
  415. async.rejectSeries = doSeries(_reject);
  416. function _createTester(eachfn, check, getResult) {
  417. return function(arr, limit, iterator, cb) {
  418. function done() {
  419. if (cb) cb(getResult(false, void 0));
  420. }
  421. function iteratee(x, _, callback) {
  422. if (!cb) return callback();
  423. iterator(x, function (v) {
  424. if (cb && check(v)) {
  425. cb(getResult(true, x));
  426. cb = iterator = false;
  427. }
  428. callback();
  429. });
  430. }
  431. if (arguments.length > 3) {
  432. eachfn(arr, limit, iteratee, done);
  433. } else {
  434. cb = iterator;
  435. iterator = limit;
  436. eachfn(arr, iteratee, done);
  437. }
  438. };
  439. }
  440. async.any =
  441. async.some = _createTester(async.eachOf, toBool, identity);
  442. async.someLimit = _createTester(async.eachOfLimit, toBool, identity);
  443. async.all =
  444. async.every = _createTester(async.eachOf, notId, notId);
  445. async.everyLimit = _createTester(async.eachOfLimit, notId, notId);
  446. function _findGetResult(v, x) {
  447. return x;
  448. }
  449. async.detect = _createTester(async.eachOf, identity, _findGetResult);
  450. async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult);
  451. async.detectLimit = _createTester(async.eachOfLimit, identity, _findGetResult);
  452. async.sortBy = function (arr, iterator, callback) {
  453. async.map(arr, function (x, callback) {
  454. iterator(x, function (err, criteria) {
  455. if (err) {
  456. callback(err);
  457. }
  458. else {
  459. callback(null, {value: x, criteria: criteria});
  460. }
  461. });
  462. }, function (err, results) {
  463. if (err) {
  464. return callback(err);
  465. }
  466. else {
  467. callback(null, _map(results.sort(comparator), function (x) {
  468. return x.value;
  469. }));
  470. }
  471. });
  472. function comparator(left, right) {
  473. var a = left.criteria, b = right.criteria;
  474. return a < b ? -1 : a > b ? 1 : 0;
  475. }
  476. };
  477. async.auto = function (tasks, concurrency, callback) {
  478. if (typeof arguments[1] === 'function') {
  479. // concurrency is optional, shift the args.
  480. callback = concurrency;
  481. concurrency = null;
  482. }
  483. callback = _once(callback || noop);
  484. var keys = _keys(tasks);
  485. var remainingTasks = keys.length;
  486. if (!remainingTasks) {
  487. return callback(null);
  488. }
  489. if (!concurrency) {
  490. concurrency = remainingTasks;
  491. }
  492. var results = {};
  493. var runningTasks = 0;
  494. var hasError = false;
  495. var listeners = [];
  496. function addListener(fn) {
  497. listeners.unshift(fn);
  498. }
  499. function removeListener(fn) {
  500. var idx = _indexOf(listeners, fn);
  501. if (idx >= 0) listeners.splice(idx, 1);
  502. }
  503. function taskComplete() {
  504. remainingTasks--;
  505. _arrayEach(listeners.slice(0), function (fn) {
  506. fn();
  507. });
  508. }
  509. addListener(function () {
  510. if (!remainingTasks) {
  511. callback(null, results);
  512. }
  513. });
  514. _arrayEach(keys, function (k) {
  515. if (hasError) return;
  516. var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];
  517. var taskCallback = _restParam(function(err, args) {
  518. runningTasks--;
  519. if (args.length <= 1) {
  520. args = args[0];
  521. }
  522. if (err) {
  523. var safeResults = {};
  524. _forEachOf(results, function(val, rkey) {
  525. safeResults[rkey] = val;
  526. });
  527. safeResults[k] = args;
  528. hasError = true;
  529. callback(err, safeResults);
  530. }
  531. else {
  532. results[k] = args;
  533. async.setImmediate(taskComplete);
  534. }
  535. });
  536. var requires = task.slice(0, task.length - 1);
  537. // prevent dead-locks
  538. var len = requires.length;
  539. var dep;
  540. while (len--) {
  541. if (!(dep = tasks[requires[len]])) {
  542. throw new Error('Has nonexistent dependency in ' + requires.join(', '));
  543. }
  544. if (_isArray(dep) && _indexOf(dep, k) >= 0) {
  545. throw new Error('Has cyclic dependencies');
  546. }
  547. }
  548. function ready() {
  549. return runningTasks < concurrency && _reduce(requires, function (a, x) {
  550. return (a && results.hasOwnProperty(x));
  551. }, true) && !results.hasOwnProperty(k);
  552. }
  553. if (ready()) {
  554. runningTasks++;
  555. task[task.length - 1](taskCallback, results);
  556. }
  557. else {
  558. addListener(listener);
  559. }
  560. function listener() {
  561. if (ready()) {
  562. runningTasks++;
  563. removeListener(listener);
  564. task[task.length - 1](taskCallback, results);
  565. }
  566. }
  567. });
  568. };
  569. async.retry = function(times, task, callback) {
  570. var DEFAULT_TIMES = 5;
  571. var DEFAULT_INTERVAL = 0;
  572. var attempts = [];
  573. var opts = {
  574. times: DEFAULT_TIMES,
  575. interval: DEFAULT_INTERVAL
  576. };
  577. function parseTimes(acc, t){
  578. if(typeof t === 'number'){
  579. acc.times = parseInt(t, 10) || DEFAULT_TIMES;
  580. } else if(typeof t === 'object'){
  581. acc.times = parseInt(t.times, 10) || DEFAULT_TIMES;
  582. acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL;
  583. } else {
  584. throw new Error('Unsupported argument type for \'times\': ' + typeof t);
  585. }
  586. }
  587. var length = arguments.length;
  588. if (length < 1 || length > 3) {
  589. throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)');
  590. } else if (length <= 2 && typeof times === 'function') {
  591. callback = task;
  592. task = times;
  593. }
  594. if (typeof times !== 'function') {
  595. parseTimes(opts, times);
  596. }
  597. opts.callback = callback;
  598. opts.task = task;
  599. function wrappedTask(wrappedCallback, wrappedResults) {
  600. function retryAttempt(task, finalAttempt) {
  601. return function(seriesCallback) {
  602. task(function(err, result){
  603. seriesCallback(!err || finalAttempt, {err: err, result: result});
  604. }, wrappedResults);
  605. };
  606. }
  607. function retryInterval(interval){
  608. return function(seriesCallback){
  609. setTimeout(function(){
  610. seriesCallback(null);
  611. }, interval);
  612. };
  613. }
  614. while (opts.times) {
  615. var finalAttempt = !(opts.times-=1);
  616. attempts.push(retryAttempt(opts.task, finalAttempt));
  617. if(!finalAttempt && opts.interval > 0){
  618. attempts.push(retryInterval(opts.interval));
  619. }
  620. }
  621. async.series(attempts, function(done, data){
  622. data = data[data.length - 1];
  623. (wrappedCallback || opts.callback)(data.err, data.result);
  624. });
  625. }
  626. // If a callback is passed, run this as a controll flow
  627. return opts.callback ? wrappedTask() : wrappedTask;
  628. };
  629. async.waterfall = function (tasks, callback) {
  630. callback = _once(callback || noop);
  631. if (!_isArray(tasks)) {
  632. var err = new Error('First argument to waterfall must be an array of functions');
  633. return callback(err);
  634. }
  635. if (!tasks.length) {
  636. return callback();
  637. }
  638. function wrapIterator(iterator) {
  639. return _restParam(function (err, args) {
  640. if (err) {
  641. callback.apply(null, [err].concat(args));
  642. }
  643. else {
  644. var next = iterator.next();
  645. if (next) {
  646. args.push(wrapIterator(next));
  647. }
  648. else {
  649. args.push(callback);
  650. }
  651. ensureAsync(iterator).apply(null, args);
  652. }
  653. });
  654. }
  655. wrapIterator(async.iterator(tasks))();
  656. };
  657. function _parallel(eachfn, tasks, callback) {
  658. callback = callback || noop;
  659. var results = _isArrayLike(tasks) ? [] : {};
  660. eachfn(tasks, function (task, key, callback) {
  661. task(_restParam(function (err, args) {
  662. if (args.length <= 1) {
  663. args = args[0];
  664. }
  665. results[key] = args;
  666. callback(err);
  667. }));
  668. }, function (err) {
  669. callback(err, results);
  670. });
  671. }
  672. async.parallel = function (tasks, callback) {
  673. _parallel(async.eachOf, tasks, callback);
  674. };
  675. async.parallelLimit = function(tasks, limit, callback) {
  676. _parallel(_eachOfLimit(limit), tasks, callback);
  677. };
  678. async.series = function(tasks, callback) {
  679. _parallel(async.eachOfSeries, tasks, callback);
  680. };
  681. async.iterator = function (tasks) {
  682. function makeCallback(index) {
  683. function fn() {
  684. if (tasks.length) {
  685. tasks[index].apply(null, arguments);
  686. }
  687. return fn.next();
  688. }
  689. fn.next = function () {
  690. return (index < tasks.length - 1) ? makeCallback(index + 1): null;
  691. };
  692. return fn;
  693. }
  694. return makeCallback(0);
  695. };
  696. async.apply = _restParam(function (fn, args) {
  697. return _restParam(function (callArgs) {
  698. return fn.apply(
  699. null, args.concat(callArgs)
  700. );
  701. });
  702. });
  703. function _concat(eachfn, arr, fn, callback) {
  704. var result = [];
  705. eachfn(arr, function (x, index, cb) {
  706. fn(x, function (err, y) {
  707. result = result.concat(y || []);
  708. cb(err);
  709. });
  710. }, function (err) {
  711. callback(err, result);
  712. });
  713. }
  714. async.concat = doParallel(_concat);
  715. async.concatSeries = doSeries(_concat);
  716. async.whilst = function (test, iterator, callback) {
  717. callback = callback || noop;
  718. if (test()) {
  719. var next = _restParam(function(err, args) {
  720. if (err) {
  721. callback(err);
  722. } else if (test.apply(this, args)) {
  723. iterator(next);
  724. } else {
  725. callback.apply(null, [null].concat(args));
  726. }
  727. });
  728. iterator(next);
  729. } else {
  730. callback(null);
  731. }
  732. };
  733. async.doWhilst = function (iterator, test, callback) {
  734. var calls = 0;
  735. return async.whilst(function() {
  736. return ++calls <= 1 || test.apply(this, arguments);
  737. }, iterator, callback);
  738. };
  739. async.until = function (test, iterator, callback) {
  740. return async.whilst(function() {
  741. return !test.apply(this, arguments);
  742. }, iterator, callback);
  743. };
  744. async.doUntil = function (iterator, test, callback) {
  745. return async.doWhilst(iterator, function() {
  746. return !test.apply(this, arguments);
  747. }, callback);
  748. };
  749. async.during = function (test, iterator, callback) {
  750. callback = callback || noop;
  751. var next = _restParam(function(err, args) {
  752. if (err) {
  753. callback(err);
  754. } else {
  755. args.push(check);
  756. test.apply(this, args);
  757. }
  758. });
  759. var check = function(err, truth) {
  760. if (err) {
  761. callback(err);
  762. } else if (truth) {
  763. iterator(next);
  764. } else {
  765. callback(null);
  766. }
  767. };
  768. test(check);
  769. };
  770. async.doDuring = function (iterator, test, callback) {
  771. var calls = 0;
  772. async.during(function(next) {
  773. if (calls++ < 1) {
  774. next(null, true);
  775. } else {
  776. test.apply(this, arguments);
  777. }
  778. }, iterator, callback);
  779. };
  780. function _queue(worker, concurrency, payload) {
  781. if (concurrency == null) {
  782. concurrency = 1;
  783. }
  784. else if(concurrency === 0) {
  785. throw new Error('Concurrency must not be zero');
  786. }
  787. function _insert(q, data, pos, callback) {
  788. if (callback != null && typeof callback !== "function") {
  789. throw new Error("task callback must be a function");
  790. }
  791. q.started = true;
  792. if (!_isArray(data)) {
  793. data = [data];
  794. }
  795. if(data.length === 0 && q.idle()) {
  796. // call drain immediately if there are no tasks
  797. return async.setImmediate(function() {
  798. q.drain();
  799. });
  800. }
  801. _arrayEach(data, function(task) {
  802. var item = {
  803. data: task,
  804. callback: callback || noop
  805. };
  806. if (pos) {
  807. q.tasks.unshift(item);
  808. } else {
  809. q.tasks.push(item);
  810. }
  811. if (q.tasks.length === q.concurrency) {
  812. q.saturated();
  813. }
  814. });
  815. async.setImmediate(q.process);
  816. }
  817. function _next(q, tasks) {
  818. return function(){
  819. workers -= 1;
  820. var removed = false;
  821. var args = arguments;
  822. _arrayEach(tasks, function (task) {
  823. _arrayEach(workersList, function (worker, index) {
  824. if (worker === task && !removed) {
  825. workersList.splice(index, 1);
  826. removed = true;
  827. }
  828. });
  829. task.callback.apply(task, args);
  830. });
  831. if (q.tasks.length + workers === 0) {
  832. q.drain();
  833. }
  834. q.process();
  835. };
  836. }
  837. var workers = 0;
  838. var workersList = [];
  839. var q = {
  840. tasks: [],
  841. concurrency: concurrency,
  842. payload: payload,
  843. saturated: noop,
  844. empty: noop,
  845. drain: noop,
  846. started: false,
  847. paused: false,
  848. push: function (data, callback) {
  849. _insert(q, data, false, callback);
  850. },
  851. kill: function () {
  852. q.drain = noop;
  853. q.tasks = [];
  854. },
  855. unshift: function (data, callback) {
  856. _insert(q, data, true, callback);
  857. },
  858. process: function () {
  859. while(!q.paused && workers < q.concurrency && q.tasks.length){
  860. var tasks = q.payload ?
  861. q.tasks.splice(0, q.payload) :
  862. q.tasks.splice(0, q.tasks.length);
  863. var data = _map(tasks, function (task) {
  864. return task.data;
  865. });
  866. if (q.tasks.length === 0) {
  867. q.empty();
  868. }
  869. workers += 1;
  870. workersList.push(tasks[0]);
  871. var cb = only_once(_next(q, tasks));
  872. worker(data, cb);
  873. }
  874. },
  875. length: function () {
  876. return q.tasks.length;
  877. },
  878. running: function () {
  879. return workers;
  880. },
  881. workersList: function () {
  882. return workersList;
  883. },
  884. idle: function() {
  885. return q.tasks.length + workers === 0;
  886. },
  887. pause: function () {
  888. q.paused = true;
  889. },
  890. resume: function () {
  891. if (q.paused === false) { return; }
  892. q.paused = false;
  893. var resumeCount = Math.min(q.concurrency, q.tasks.length);
  894. // Need to call q.process once per concurrent
  895. // worker to preserve full concurrency after pause
  896. for (var w = 1; w <= resumeCount; w++) {
  897. async.setImmediate(q.process);
  898. }
  899. }
  900. };
  901. return q;
  902. }
  903. async.queue = function (worker, concurrency) {
  904. var q = _queue(function (items, cb) {
  905. worker(items[0], cb);
  906. }, concurrency, 1);
  907. return q;
  908. };
  909. async.priorityQueue = function (worker, concurrency) {
  910. function _compareTasks(a, b){
  911. return a.priority - b.priority;
  912. }
  913. function _binarySearch(sequence, item, compare) {
  914. var beg = -1,
  915. end = sequence.length - 1;
  916. while (beg < end) {
  917. var mid = beg + ((end - beg + 1) >>> 1);
  918. if (compare(item, sequence[mid]) >= 0) {
  919. beg = mid;
  920. } else {
  921. end = mid - 1;
  922. }
  923. }
  924. return beg;
  925. }
  926. function _insert(q, data, priority, callback) {
  927. if (callback != null && typeof callback !== "function") {
  928. throw new Error("task callback must be a function");
  929. }
  930. q.started = true;
  931. if (!_isArray(data)) {
  932. data = [data];
  933. }
  934. if(data.length === 0) {
  935. // call drain immediately if there are no tasks
  936. return async.setImmediate(function() {
  937. q.drain();
  938. });
  939. }
  940. _arrayEach(data, function(task) {
  941. var item = {
  942. data: task,
  943. priority: priority,
  944. callback: typeof callback === 'function' ? callback : noop
  945. };
  946. q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
  947. if (q.tasks.length === q.concurrency) {
  948. q.saturated();
  949. }
  950. async.setImmediate(q.process);
  951. });
  952. }
  953. // Start with a normal queue
  954. var q = async.queue(worker, concurrency);
  955. // Override push to accept second parameter representing priority
  956. q.push = function (data, priority, callback) {
  957. _insert(q, data, priority, callback);
  958. };
  959. // Remove unshift function
  960. delete q.unshift;
  961. return q;
  962. };
  963. async.cargo = function (worker, payload) {
  964. return _queue(worker, 1, payload);
  965. };
  966. function _console_fn(name) {
  967. return _restParam(function (fn, args) {
  968. fn.apply(null, args.concat([_restParam(function (err, args) {
  969. if (typeof console === 'object') {
  970. if (err) {
  971. if (console.error) {
  972. console.error(err);
  973. }
  974. }
  975. else if (console[name]) {
  976. _arrayEach(args, function (x) {
  977. console[name](x);
  978. });
  979. }
  980. }
  981. })]));
  982. });
  983. }
  984. async.log = _console_fn('log');
  985. async.dir = _console_fn('dir');
  986. /*async.info = _console_fn('info');
  987. async.warn = _console_fn('warn');
  988. async.error = _console_fn('error');*/
  989. async.memoize = function (fn, hasher) {
  990. var memo = {};
  991. var queues = {};
  992. var has = Object.prototype.hasOwnProperty;
  993. hasher = hasher || identity;
  994. var memoized = _restParam(function memoized(args) {
  995. var callback = args.pop();
  996. var key = hasher.apply(null, args);
  997. if (has.call(memo, key)) {
  998. async.setImmediate(function () {
  999. callback.apply(null, memo[key]);
  1000. });
  1001. }
  1002. else if (has.call(queues, key)) {
  1003. queues[key].push(callback);
  1004. }
  1005. else {
  1006. queues[key] = [callback];
  1007. fn.apply(null, args.concat([_restParam(function (args) {
  1008. memo[key] = args;
  1009. var q = queues[key];
  1010. delete queues[key];
  1011. for (var i = 0, l = q.length; i < l; i++) {
  1012. q[i].apply(null, args);
  1013. }
  1014. })]));
  1015. }
  1016. });
  1017. memoized.memo = memo;
  1018. memoized.unmemoized = fn;
  1019. return memoized;
  1020. };
  1021. async.unmemoize = function (fn) {
  1022. return function () {
  1023. return (fn.unmemoized || fn).apply(null, arguments);
  1024. };
  1025. };
  1026. function _times(mapper) {
  1027. return function (count, iterator, callback) {
  1028. mapper(_range(count), iterator, callback);
  1029. };
  1030. }
  1031. async.times = _times(async.map);
  1032. async.timesSeries = _times(async.mapSeries);
  1033. async.timesLimit = function (count, limit, iterator, callback) {
  1034. return async.mapLimit(_range(count), limit, iterator, callback);
  1035. };
  1036. async.seq = function (/* functions... */) {
  1037. var fns = arguments;
  1038. return _restParam(function (args) {
  1039. var that = this;
  1040. var callback = args[args.length - 1];
  1041. if (typeof callback == 'function') {
  1042. args.pop();
  1043. } else {
  1044. callback = noop;
  1045. }
  1046. async.reduce(fns, args, function (newargs, fn, cb) {
  1047. fn.apply(that, newargs.concat([_restParam(function (err, nextargs) {
  1048. cb(err, nextargs);
  1049. })]));
  1050. },
  1051. function (err, results) {
  1052. callback.apply(that, [err].concat(results));
  1053. });
  1054. });
  1055. };
  1056. async.compose = function (/* functions... */) {
  1057. return async.seq.apply(null, Array.prototype.reverse.call(arguments));
  1058. };
  1059. function _applyEach(eachfn) {
  1060. return _restParam(function(fns, args) {
  1061. var go = _restParam(function(args) {
  1062. var that = this;
  1063. var callback = args.pop();
  1064. return eachfn(fns, function (fn, _, cb) {
  1065. fn.apply(that, args.concat([cb]));
  1066. },
  1067. callback);
  1068. });
  1069. if (args.length) {
  1070. return go.apply(this, args);
  1071. }
  1072. else {
  1073. return go;
  1074. }
  1075. });
  1076. }
  1077. async.applyEach = _applyEach(async.eachOf);
  1078. async.applyEachSeries = _applyEach(async.eachOfSeries);
  1079. async.forever = function (fn, callback) {
  1080. var done = only_once(callback || noop);
  1081. var task = ensureAsync(fn);
  1082. function next(err) {
  1083. if (err) {
  1084. return done(err);
  1085. }
  1086. task(next);
  1087. }
  1088. next();
  1089. };
  1090. function ensureAsync(fn) {
  1091. return _restParam(function (args) {
  1092. var callback = args.pop();
  1093. args.push(function () {
  1094. var innerArgs = arguments;
  1095. if (sync) {
  1096. async.setImmediate(function () {
  1097. callback.apply(null, innerArgs);
  1098. });
  1099. } else {
  1100. callback.apply(null, innerArgs);
  1101. }
  1102. });
  1103. var sync = true;
  1104. fn.apply(this, args);
  1105. sync = false;
  1106. });
  1107. }
  1108. async.ensureAsync = ensureAsync;
  1109. async.constant = _restParam(function(values) {
  1110. var args = [null].concat(values);
  1111. return function (callback) {
  1112. return callback.apply(this, args);
  1113. };
  1114. });
  1115. async.wrapSync =
  1116. async.asyncify = function asyncify(func) {
  1117. return _restParam(function (args) {
  1118. var callback = args.pop();
  1119. var result;
  1120. try {
  1121. result = func.apply(this, args);
  1122. } catch (e) {
  1123. return callback(e);
  1124. }
  1125. // if result is Promise object
  1126. if (_isObject(result) && typeof result.then === "function") {
  1127. result.then(function(value) {
  1128. callback(null, value);
  1129. })["catch"](function(err) {
  1130. callback(err.message ? err : new Error(err));
  1131. });
  1132. } else {
  1133. callback(null, result);
  1134. }
  1135. });
  1136. };
  1137. // Node.js
  1138. if (typeof module === 'object' && module.exports) {
  1139. module.exports = async;
  1140. }
  1141. // AMD / RequireJS
  1142. else if (typeof define === 'function' && define.amd) {
  1143. define([], function () {
  1144. return async;
  1145. });
  1146. }
  1147. // included directly via <script> tag
  1148. else {
  1149. root.async = async;
  1150. }
  1151. }());
  1152. }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  1153. },{"_process":3}],2:[function(require,module,exports){
  1154. (function (process){
  1155. // Copyright Joyent, Inc. and other Node contributors.
  1156. //
  1157. // Permission is hereby granted, free of charge, to any person obtaining a
  1158. // copy of this software and associated documentation files (the
  1159. // "Software"), to deal in the Software without restriction, including
  1160. // without limitation the rights to use, copy, modify, merge, publish,
  1161. // distribute, sublicense, and/or sell copies of the Software, and to permit
  1162. // persons to whom the Software is furnished to do so, subject to the
  1163. // following conditions:
  1164. //
  1165. // The above copyright notice and this permission notice shall be included
  1166. // in all copies or substantial portions of the Software.
  1167. //
  1168. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  1169. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  1170. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  1171. // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  1172. // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  1173. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  1174. // USE OR OTHER DEALINGS IN THE SOFTWARE.
  1175. // resolves . and .. elements in a path array with directory names there
  1176. // must be no slashes, empty elements, or device names (c:\) in the array
  1177. // (so also no leading and trailing slashes - it does not distinguish
  1178. // relative and absolute paths)
  1179. function normalizeArray(parts, allowAboveRoot) {
  1180. // if the path tries to go above the root, `up` ends up > 0
  1181. var up = 0;
  1182. for (var i = parts.length - 1; i >= 0; i--) {
  1183. var last = parts[i];
  1184. if (last === '.') {
  1185. parts.splice(i, 1);
  1186. } else if (last === '..') {
  1187. parts.splice(i, 1);
  1188. up++;
  1189. } else if (up) {
  1190. parts.splice(i, 1);
  1191. up--;
  1192. }
  1193. }
  1194. // if the path is allowed to go above the root, restore leading ..s
  1195. if (allowAboveRoot) {
  1196. for (; up--; up) {
  1197. parts.unshift('..');
  1198. }
  1199. }
  1200. return parts;
  1201. }
  1202. // Split a filename into [root, dir, basename, ext], unix version
  1203. // 'root' is just a slash, or nothing.
  1204. var splitPathRe =
  1205. /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
  1206. var splitPath = function(filename) {
  1207. return splitPathRe.exec(filename).slice(1);
  1208. };
  1209. // path.resolve([from ...], to)
  1210. // posix version
  1211. exports.resolve = function() {
  1212. var resolvedPath = '',
  1213. resolvedAbsolute = false;
  1214. for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
  1215. var path = (i >= 0) ? arguments[i] : process.cwd();
  1216. // Skip empty and invalid entries
  1217. if (typeof path !== 'string') {
  1218. throw new TypeError('Arguments to path.resolve must be strings');
  1219. } else if (!path) {
  1220. continue;
  1221. }
  1222. resolvedPath = path + '/' + resolvedPath;
  1223. resolvedAbsolute = path.charAt(0) === '/';
  1224. }
  1225. // At this point the path should be resolved to a full absolute path, but
  1226. // handle relative paths to be safe (might happen when process.cwd() fails)
  1227. // Normalize the path
  1228. resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
  1229. return !!p;
  1230. }), !resolvedAbsolute).join('/');
  1231. return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
  1232. };
  1233. // path.normalize(path)
  1234. // posix version
  1235. exports.normalize = function(path) {
  1236. var isAbsolute = exports.isAbsolute(path),
  1237. trailingSlash = substr(path, -1) === '/';
  1238. // Normalize the path
  1239. path = normalizeArray(filter(path.split('/'), function(p) {
  1240. return !!p;
  1241. }), !isAbsolute).join('/');
  1242. if (!path && !isAbsolute) {
  1243. path = '.';
  1244. }
  1245. if (path && trailingSlash) {
  1246. path += '/';
  1247. }
  1248. return (isAbsolute ? '/' : '') + path;
  1249. };
  1250. // posix version
  1251. exports.isAbsolute = function(path) {
  1252. return path.charAt(0) === '/';
  1253. };
  1254. // posix version
  1255. exports.join = function() {
  1256. var paths = Array.prototype.slice.call(arguments, 0);
  1257. return exports.normalize(filter(paths, function(p, index) {
  1258. if (typeof p !== 'string') {
  1259. throw new TypeError('Arguments to path.join must be strings');
  1260. }
  1261. return p;
  1262. }).join('/'));
  1263. };
  1264. // path.relative(from, to)
  1265. // posix version
  1266. exports.relative = function(from, to) {
  1267. from = exports.resolve(from).substr(1);
  1268. to = exports.resolve(to).substr(1);
  1269. function trim(arr) {
  1270. var start = 0;
  1271. for (; start < arr.length; start++) {
  1272. if (arr[start] !== '') break;
  1273. }
  1274. var end = arr.length - 1;
  1275. for (; end >= 0; end--) {
  1276. if (arr[end] !== '') break;
  1277. }
  1278. if (start > end) return [];
  1279. return arr.slice(start, end - start + 1);
  1280. }
  1281. var fromParts = trim(from.split('/'));
  1282. var toParts = trim(to.split('/'));
  1283. var length = Math.min(fromParts.length, toParts.length);
  1284. var samePartsLength = length;
  1285. for (var i = 0; i < length; i++) {
  1286. if (fromParts[i] !== toParts[i]) {
  1287. samePartsLength = i;
  1288. break;
  1289. }
  1290. }
  1291. var outputParts = [];
  1292. for (var i = samePartsLength; i < fromParts.length; i++) {
  1293. outputParts.push('..');
  1294. }
  1295. outputParts = outputParts.concat(toParts.slice(samePartsLength));
  1296. return outputParts.join('/');
  1297. };
  1298. exports.sep = '/';
  1299. exports.delimiter = ':';
  1300. exports.dirname = function(path) {
  1301. var result = splitPath(path),
  1302. root = result[0],
  1303. dir = result[1];
  1304. if (!root && !dir) {
  1305. // No dirname whatsoever
  1306. return '.';
  1307. }
  1308. if (dir) {
  1309. // It has a dirname, strip trailing slash
  1310. dir = dir.substr(0, dir.length - 1);
  1311. }
  1312. return root + dir;
  1313. };
  1314. exports.basename = function(path, ext) {
  1315. var f = splitPath(path)[2];
  1316. // TODO: make this comparison case-insensitive on windows?
  1317. if (ext && f.substr(-1 * ext.length) === ext) {
  1318. f = f.substr(0, f.length - ext.length);
  1319. }
  1320. return f;
  1321. };
  1322. exports.extname = function(path) {
  1323. return splitPath(path)[3];
  1324. };
  1325. function filter (xs, f) {
  1326. if (xs.filter) return xs.filter(f);
  1327. var res = [];
  1328. for (var i = 0; i < xs.length; i++) {
  1329. if (f(xs[i], i, xs)) res.push(xs[i]);
  1330. }
  1331. return res;
  1332. }
  1333. // String.prototype.substr - negative index don't work in IE8
  1334. var substr = 'ab'.substr(-1) === 'b'
  1335. ? function (str, start, len) { return str.substr(start, len) }
  1336. : function (str, start, len) {
  1337. if (start < 0) start = str.length + start;
  1338. return str.substr(start, len);
  1339. }
  1340. ;
  1341. }).call(this,require('_process'))
  1342. },{"_process":3}],3:[function(require,module,exports){
  1343. // shim for using process in browser
  1344. var process = module.exports = {};
  1345. var queue = [];
  1346. var draining = false;
  1347. var currentQueue;
  1348. var queueIndex = -1;
  1349. function cleanUpNextTick() {
  1350. draining = false;
  1351. if (currentQueue.length) {
  1352. queue = currentQueue.concat(queue);
  1353. } else {
  1354. queueIndex = -1;
  1355. }
  1356. if (queue.length) {
  1357. drainQueue();
  1358. }
  1359. }
  1360. function drainQueue() {
  1361. if (draining) {
  1362. return;
  1363. }
  1364. var timeout = setTimeout(cleanUpNextTick);
  1365. draining = true;
  1366. var len = queue.length;
  1367. while(len) {
  1368. currentQueue = queue;
  1369. queue = [];
  1370. while (++queueIndex < len) {
  1371. if (currentQueue) {
  1372. currentQueue[queueIndex].run();
  1373. }
  1374. }
  1375. queueIndex = -1;
  1376. len = queue.length;
  1377. }
  1378. currentQueue = null;
  1379. draining = false;
  1380. clearTimeout(timeout);
  1381. }
  1382. process.nextTick = function (fun) {
  1383. var args = new Array(arguments.length - 1);
  1384. if (arguments.length > 1) {
  1385. for (var i = 1; i < arguments.length; i++) {
  1386. args[i - 1] = arguments[i];
  1387. }
  1388. }
  1389. queue.push(new Item(fun, args));
  1390. if (queue.length === 1 && !draining) {
  1391. setTimeout(drainQueue, 0);
  1392. }
  1393. };
  1394. // v8 likes predictible objects
  1395. function Item(fun, array) {
  1396. this.fun = fun;
  1397. this.array = array;
  1398. }
  1399. Item.prototype.run = function () {
  1400. this.fun.apply(null, this.array);
  1401. };
  1402. process.title = 'browser';
  1403. process.browser = true;
  1404. process.env = {};
  1405. process.argv = [];
  1406. process.version = ''; // empty string to avoid regexp issues
  1407. process.versions = {};
  1408. function noop() {}
  1409. process.on = noop;
  1410. process.addListener = noop;
  1411. process.once = noop;
  1412. process.off = noop;
  1413. process.removeListener = noop;
  1414. process.removeAllListeners = noop;
  1415. process.emit = noop;
  1416. process.binding = function (name) {
  1417. throw new Error('process.binding is not supported');
  1418. };
  1419. process.cwd = function () { return '/' };
  1420. process.chdir = function (dir) {
  1421. throw new Error('process.chdir is not supported');
  1422. };
  1423. process.umask = function() { return 0; };
  1424. },{}],4:[function(require,module,exports){
  1425. (function (global){
  1426. /*! https://mths.be/punycode v1.4.0 by @mathias */
  1427. ;(function(root) {
  1428. /** Detect free variables */
  1429. var freeExports = typeof exports == 'object' && exports &&
  1430. !exports.nodeType && exports;
  1431. var freeModule = typeof module == 'object' && module &&
  1432. !module.nodeType && module;
  1433. var freeGlobal = typeof global == 'object' && global;
  1434. if (
  1435. freeGlobal.global === freeGlobal ||
  1436. freeGlobal.window === freeGlobal ||
  1437. freeGlobal.self === freeGlobal
  1438. ) {
  1439. root = freeGlobal;
  1440. }
  1441. /**
  1442. * The `punycode` object.
  1443. * @name punycode
  1444. * @type Object
  1445. */
  1446. var punycode,
  1447. /** Highest positive signed 32-bit float value */
  1448. maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
  1449. /** Bootstring parameters */
  1450. base = 36,
  1451. tMin = 1,
  1452. tMax = 26,
  1453. skew = 38,
  1454. damp = 700,
  1455. initialBias = 72,
  1456. initialN = 128, // 0x80
  1457. delimiter = '-', // '\x2D'
  1458. /** Regular expressions */
  1459. regexPunycode = /^xn--/,
  1460. regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
  1461. regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
  1462. /** Error messages */
  1463. errors = {
  1464. 'overflow': 'Overflow: input needs wider integers to process',
  1465. 'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
  1466. 'invalid-input': 'Invalid input'
  1467. },
  1468. /** Convenience shortcuts */
  1469. baseMinusTMin = base - tMin,
  1470. floor = Math.floor,
  1471. stringFromCharCode = String.fromCharCode,
  1472. /** Temporary variable */
  1473. key;
  1474. /*--------------------------------------------------------------------------*/
  1475. /**
  1476. * A generic error utility function.
  1477. * @private
  1478. * @param {String} type The error type.
  1479. * @returns {Error} Throws a `RangeError` with the applicable error message.
  1480. */
  1481. function error(type) {
  1482. throw new RangeError(errors[type]);
  1483. }
  1484. /**
  1485. * A generic `Array#map` utility function.
  1486. * @private
  1487. * @param {Array} array The array to iterate over.
  1488. * @param {Function} callback The function that gets called for every array
  1489. * item.
  1490. * @returns {Array} A new array of values returned by the callback function.
  1491. */
  1492. function map(array, fn) {
  1493. var length = array.length;
  1494. var result = [];
  1495. while (length--) {
  1496. result[length] = fn(array[length]);
  1497. }
  1498. return result;
  1499. }
  1500. /**
  1501. * A simple `Array#map`-like wrapper to work with domain name strings or email
  1502. * addresses.
  1503. * @private
  1504. * @param {String} domain The domain name or email address.
  1505. * @param {Function} callback The function that gets called for every
  1506. * character.
  1507. * @returns {Array} A new string of characters returned by the callback
  1508. * function.
  1509. */
  1510. function mapDomain(string, fn) {
  1511. var parts = string.split('@');
  1512. var result = '';
  1513. if (parts.length > 1) {
  1514. // In email addresses, only the domain name should be punycoded. Leave
  1515. // the local part (i.e. everything up to `@`) intact.
  1516. result = parts[0] + '@';
  1517. string = parts[1];
  1518. }
  1519. // Avoid `split(regex)` for IE8 compatibility. See #17.
  1520. string = string.replace(regexSeparators, '\x2E');
  1521. var labels = string.split('.');
  1522. var encoded = map(labels, fn).join('.');
  1523. return result + encoded;
  1524. }
  1525. /**
  1526. * Creates an array containing the numeric code points of each Unicode
  1527. * character in the string. While JavaScript uses UCS-2 internally,
  1528. * this function will convert a pair of surrogate halves (each of which
  1529. * UCS-2 exposes as separate characters) into a single code point,
  1530. * matching UTF-16.
  1531. * @see `punycode.ucs2.encode`
  1532. * @see <https://mathiasbynens.be/notes/javascript-encoding>
  1533. * @memberOf punycode.ucs2
  1534. * @name decode
  1535. * @param {String} string The Unicode input string (UCS-2).
  1536. * @returns {Array} The new array of code points.
  1537. */
  1538. function ucs2decode(string) {
  1539. var output = [],
  1540. counter = 0,
  1541. length = string.length,
  1542. value,
  1543. extra;
  1544. while (counter < length) {
  1545. value = string.charCodeAt(counter++);
  1546. if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
  1547. // high surrogate, and there is a next character
  1548. extra = string.charCodeAt(counter++);
  1549. if ((extra & 0xFC00) == 0xDC00) { // low surrogate
  1550. output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
  1551. } else {
  1552. // unmatched surrogate; only append this code unit, in case the next
  1553. // code unit is the high surrogate of a surrogate pair
  1554. output.push(value);
  1555. counter--;
  1556. }
  1557. } else {
  1558. output.push(value);
  1559. }
  1560. }
  1561. return output;
  1562. }
  1563. /**
  1564. * Creates a string based on an array of numeric code points.
  1565. * @see `punycode.ucs2.decode`
  1566. * @memberOf punycode.ucs2
  1567. * @name encode
  1568. * @param {Array} codePoints The array of numeric code points.
  1569. * @returns {String} The new Unicode string (UCS-2).
  1570. */
  1571. function ucs2encode(array) {
  1572. return map(array, function(value) {
  1573. var output = '';
  1574. if (value > 0xFFFF) {
  1575. value -= 0x10000;
  1576. output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
  1577. value = 0xDC00 | value & 0x3FF;
  1578. }
  1579. output += stringFromCharCode(value);
  1580. return output;
  1581. }).join('');
  1582. }
  1583. /**
  1584. * Converts a basic code point into a digit/integer.
  1585. * @see `digitToBasic()`
  1586. * @private
  1587. * @param {Number} codePoint The basic numeric code point value.
  1588. * @returns {Number} The numeric value of a basic code point (for use in
  1589. * representing integers) in the range `0` to `base - 1`, or `base` if
  1590. * the code point does not represent a value.
  1591. */
  1592. function basicToDigit(codePoint) {
  1593. if (codePoint - 48 < 10) {
  1594. return codePoint - 22;
  1595. }
  1596. if (codePoint - 65 < 26) {
  1597. return codePoint - 65;
  1598. }
  1599. if (codePoint - 97 < 26) {
  1600. return codePoint - 97;
  1601. }
  1602. return base;
  1603. }
  1604. /**
  1605. * Converts a digit/integer into a basic code point.
  1606. * @see `basicToDigit()`
  1607. * @private
  1608. * @param {Number} digit The numeric value of a basic code point.
  1609. * @returns {Number} The basic code point whose value (when used for
  1610. * representing integers) is `digit`, which needs to be in the range
  1611. * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
  1612. * used; else, the lowercase form is used. The behavior is undefined
  1613. * if `flag` is non-zero and `digit` has no uppercase form.
  1614. */
  1615. function digitToBasic(digit, flag) {
  1616. // 0..25 map to ASCII a..z or A..Z
  1617. // 26..35 map to ASCII 0..9
  1618. return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
  1619. }
  1620. /**
  1621. * Bias adaptation function as per section 3.4 of RFC 3492.
  1622. * https://tools.ietf.org/html/rfc3492#section-3.4
  1623. * @private
  1624. */
  1625. function adapt(delta, numPoints, firstTime) {
  1626. var k = 0;
  1627. delta = firstTime ? floor(delta / damp) : delta >> 1;
  1628. delta += floor(delta / numPoints);
  1629. for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
  1630. delta = floor(delta / baseMinusTMin);
  1631. }
  1632. return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
  1633. }
  1634. /**
  1635. * Converts a Punycode string of ASCII-only symbols to a string of Unicode
  1636. * symbols.
  1637. * @memberOf punycode
  1638. * @param {String} input The Punycode string of ASCII-only symbols.
  1639. * @returns {String} The resulting string of Unicode symbols.
  1640. */
  1641. function decode(input) {
  1642. // Don't use UCS-2
  1643. var output = [],
  1644. inputLength = input.length,
  1645. out,
  1646. i = 0,
  1647. n = initialN,
  1648. bias = initialBias,
  1649. basic,
  1650. j,
  1651. index,
  1652. oldi,
  1653. w,
  1654. k,
  1655. digit,
  1656. t,
  1657. /** Cached calculation results */
  1658. baseMinusT;
  1659. // Handle the basic code points: let `basic` be the number of input code
  1660. // points before the last delimiter, or `0` if there is none, then copy
  1661. // the first basic code points to the output.
  1662. basic = input.lastIndexOf(delimiter);
  1663. if (basic < 0) {
  1664. basic = 0;
  1665. }
  1666. for (j = 0; j < basic; ++j) {
  1667. // if it's not a basic code point
  1668. if (input.charCodeAt(j) >= 0x80) {
  1669. error('not-basic');
  1670. }
  1671. output.push(input.charCodeAt(j));
  1672. }
  1673. // Main decoding loop: start just after the last delimiter if any basic code
  1674. // points were copied; start at the beginning otherwise.
  1675. for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
  1676. // `index` is the index of the next character to be consumed.
  1677. // Decode a generalized variable-length integer into `delta`,
  1678. // which gets added to `i`. The overflow checking is easier
  1679. // if we increase `i` as we go, then subtract off its starting
  1680. // value at the end to obtain `delta`.
  1681. for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
  1682. if (index >= inputLength) {
  1683. error('invalid-input');
  1684. }
  1685. digit = basicToDigit(input.charCodeAt(index++));
  1686. if (digit >= base || digit > floor((maxInt - i) / w)) {
  1687. error('overflow');
  1688. }
  1689. i += digit * w;
  1690. t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
  1691. if (digit < t) {
  1692. break;
  1693. }
  1694. baseMinusT = base - t;
  1695. if (w > floor(maxInt / baseMinusT)) {
  1696. error('overflow');
  1697. }
  1698. w *= baseMinusT;
  1699. }
  1700. out = output.length + 1;
  1701. bias = adapt(i - oldi, out, oldi == 0);
  1702. // `i` was supposed to wrap around from `out` to `0`,
  1703. // incrementing `n` each time, so we'll fix that now:
  1704. if (floor(i / out) > maxInt - n) {
  1705. error('overflow');
  1706. }
  1707. n += floor(i / out);
  1708. i %= out;
  1709. // Insert `n` at position `i` of the output
  1710. output.splice(i++, 0, n);
  1711. }
  1712. return ucs2encode(output);
  1713. }
  1714. /**
  1715. * Converts a string of Unicode symbols (e.g. a domain name label) to a
  1716. * Punycode string of ASCII-only symbols.
  1717. * @memberOf punycode
  1718. * @param {String} input The string of Unicode symbols.
  1719. * @returns {String} The resulting Punycode string of ASCII-only symbols.
  1720. */
  1721. function encode(input) {
  1722. var n,
  1723. delta,
  1724. handledCPCount,
  1725. basicLength,
  1726. bias,
  1727. j,
  1728. m,
  1729. q,
  1730. k,
  1731. t,
  1732. currentValue,
  1733. output = [],
  1734. /** `inputLength` will hold the number of code points in `input`. */
  1735. inputLength,
  1736. /** Cached calculation results */
  1737. handledCPCountPlusOne,
  1738. baseMinusT,
  1739. qMinusT;
  1740. // Convert the input in UCS-2 to Unicode
  1741. input = ucs2decode(input);
  1742. // Cache the length
  1743. inputLength = input.length;
  1744. // Initialize the state
  1745. n = initialN;
  1746. delta = 0;
  1747. bias = initialBias;
  1748. // Handle the basic code points
  1749. for (j = 0; j < inputLength; ++j) {
  1750. currentValue = input[j];
  1751. if (currentValue < 0x80) {
  1752. output.push(stringFromCharCode(currentValue));
  1753. }
  1754. }
  1755. handledCPCount = basicLength = output.length;
  1756. // `handledCPCount` is the number of code points that have been handled;
  1757. // `basicLength` is the number of basic code points.
  1758. // Finish the basic string - if it is not empty - with a delimiter
  1759. if (basicLength) {
  1760. output.push(delimiter);
  1761. }
  1762. // Main encoding loop:
  1763. while (handledCPCount < inputLength) {
  1764. // All non-basic code points < n have been handled already. Find the next
  1765. // larger one:
  1766. for (m = maxInt, j = 0; j < inputLength; ++j) {
  1767. currentValue = input[j];
  1768. if (currentValue >= n && currentValue < m) {
  1769. m = currentValue;
  1770. }
  1771. }
  1772. // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
  1773. // but guard against overflow
  1774. handledCPCountPlusOne = handledCPCount + 1;
  1775. if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
  1776. error('overflow');
  1777. }
  1778. delta += (m - n) * handledCPCountPlusOne;
  1779. n = m;
  1780. for (j = 0; j < inputLength; ++j) {
  1781. currentValue = input[j];
  1782. if (currentValue < n && ++delta > maxInt) {
  1783. error('overflow');
  1784. }
  1785. if (currentValue == n) {
  1786. // Represent delta as a generalized variable-length integer
  1787. for (q = delta, k = base; /* no condition */; k += base) {
  1788. t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
  1789. if (q < t) {
  1790. break;
  1791. }
  1792. qMinusT = q - t;
  1793. baseMinusT = base - t;
  1794. output.push(
  1795. stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
  1796. );
  1797. q = floor(qMinusT / baseMinusT);
  1798. }
  1799. output.push(stringFromCharCode(digitToBasic(q, 0)));
  1800. bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
  1801. delta = 0;
  1802. ++handledCPCount;
  1803. }
  1804. }
  1805. ++delta;
  1806. ++n;
  1807. }
  1808. return output.join('');
  1809. }
  1810. /**
  1811. * Converts a Punycode string representing a domain name or an email address
  1812. * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
  1813. * it doesn't matter if you call it on a string that has already been
  1814. * converted to Unicode.
  1815. * @memberOf punycode
  1816. * @param {String} input The Punycoded domain name or email address to
  1817. * convert to Unicode.
  1818. * @returns {String} The Unicode representation of the given Punycode
  1819. * string.
  1820. */
  1821. function toUnicode(input) {
  1822. return mapDomain(input, function(string) {
  1823. return regexPunycode.test(string)
  1824. ? decode(string.slice(4).toLowerCase())
  1825. : string;
  1826. });
  1827. }
  1828. /**
  1829. * Converts a Unicode string representing a domain name or an email address to
  1830. * Punycode. Only the non-ASCII parts of the domain name will be converted,
  1831. * i.e. it doesn't matter if you call it with a domain that's already in
  1832. * ASCII.
  1833. * @memberOf punycode
  1834. * @param {String} input The domain name or email address to convert, as a
  1835. * Unicode string.
  1836. * @returns {String} The Punycode representation of the given domain name or
  1837. * email address.
  1838. */
  1839. function toASCII(input) {
  1840. return mapDomain(input, function(string) {
  1841. return regexNonASCII.test(string)
  1842. ? 'xn--' + encode(string)
  1843. : string;
  1844. });
  1845. }
  1846. /*--------------------------------------------------------------------------*/
  1847. /** Define the public API */
  1848. punycode = {
  1849. /**
  1850. * A string representing the current Punycode.js version number.
  1851. * @memberOf punycode
  1852. * @type String
  1853. */
  1854. 'version': '1.3.2',
  1855. /**
  1856. * An object of methods to convert from JavaScript's internal character
  1857. * representation (UCS-2) to Unicode code points, and back.
  1858. * @see <https://mathiasbynens.be/notes/javascript-encoding>
  1859. * @memberOf punycode
  1860. * @type Object
  1861. */
  1862. 'ucs2': {
  1863. 'decode': ucs2decode,
  1864. 'encode': ucs2encode
  1865. },
  1866. 'decode': decode,
  1867. 'encode': encode,
  1868. 'toASCII': toASCII,
  1869. 'toUnicode': toUnicode
  1870. };
  1871. /** Expose `punycode` */
  1872. // Some AMD build optimizers, like r.js, check for specific condition patterns
  1873. // like the following:
  1874. if (
  1875. typeof define == 'function' &&
  1876. typeof define.amd == 'object' &&
  1877. define.amd
  1878. ) {
  1879. define('punycode', function() {
  1880. return punycode;
  1881. });
  1882. } else if (freeExports && freeModule) {
  1883. if (module.exports == freeExports) {
  1884. // in Node.js, io.js, or RingoJS v0.8.0+
  1885. freeModule.exports = punycode;
  1886. } else {
  1887. // in Narwhal or RingoJS v0.7.0-
  1888. for (key in punycode) {
  1889. punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
  1890. }
  1891. }
  1892. } else {
  1893. // in Rhino or a web browser
  1894. root.punycode = punycode;
  1895. }
  1896. }(this));
  1897. }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  1898. },{}],5:[function(require,module,exports){
  1899. // Copyright Joyent, Inc. and other Node contributors.
  1900. //
  1901. // Permission is hereby granted, free of charge, to any person obtaining a
  1902. // copy of this software and associated documentation files (the
  1903. // "Software"), to deal in the Software without restriction, including
  1904. // without limitation the rights to use, copy, modify, merge, publish,
  1905. // distribute, sublicense, and/or sell copies of the Software, and to permit
  1906. // persons to whom the Software is furnished to do so, subject to the
  1907. // following conditions:
  1908. //
  1909. // The above copyright notice and this permission notice shall be included
  1910. // in all copies or substantial portions of the Software.
  1911. //
  1912. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  1913. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  1914. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  1915. // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  1916. // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  1917. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  1918. // USE OR OTHER DEALINGS IN THE SOFTWARE.
  1919. 'use strict';
  1920. // If obj.hasOwnProperty has been overridden, then calling
  1921. // obj.hasOwnProperty(prop) will break.
  1922. // See: https://github.com/joyent/node/issues/1707
  1923. function hasOwnProperty(obj, prop) {
  1924. return Object.prototype.hasOwnProperty.call(obj, prop);
  1925. }
  1926. module.exports = function(qs, sep, eq, options) {
  1927. sep = sep || '&';
  1928. eq = eq || '=';
  1929. var obj = {};
  1930. if (typeof qs !== 'string' || qs.length === 0) {
  1931. return obj;
  1932. }
  1933. var regexp = /\+/g;
  1934. qs = qs.split(sep);
  1935. var maxKeys = 1000;
  1936. if (options && typeof options.maxKeys === 'number') {
  1937. maxKeys = options.maxKeys;
  1938. }
  1939. var len = qs.length;
  1940. // maxKeys <= 0 means that we should not limit keys count
  1941. if (maxKeys > 0 && len > maxKeys) {
  1942. len = maxKeys;
  1943. }
  1944. for (var i = 0; i < len; ++i) {
  1945. var x = qs[i].replace(regexp, '%20'),
  1946. idx = x.indexOf(eq),
  1947. kstr, vstr, k, v;
  1948. if (idx >= 0) {
  1949. kstr = x.substr(0, idx);
  1950. vstr = x.substr(idx + 1);
  1951. } else {
  1952. kstr = x;
  1953. vstr = '';
  1954. }
  1955. k = decodeURIComponent(kstr);
  1956. v = decodeURIComponent(vstr);
  1957. if (!hasOwnProperty(obj, k)) {
  1958. obj[k] = v;
  1959. } else if (isArray(obj[k])) {
  1960. obj[k].push(v);
  1961. } else {
  1962. obj[k] = [obj[k], v];
  1963. }
  1964. }
  1965. return obj;
  1966. };
  1967. var isArray = Array.isArray || function (xs) {
  1968. return Object.prototype.toString.call(xs) === '[object Array]';
  1969. };
  1970. },{}],6:[function(require,module,exports){
  1971. // Copyright Joyent, Inc. and other Node contributors.
  1972. //
  1973. // Permission is hereby granted, free of charge, to any person obtaining a
  1974. // copy of this software and associated documentation files (the
  1975. // "Software"), to deal in the Software without restriction, including
  1976. // without limitation the rights to use, copy, modify, merge, publish,
  1977. // distribute, sublicense, and/or sell copies of the Software, and to permit
  1978. // persons to whom the Software is furnished to do so, subject to the
  1979. // following conditions:
  1980. //
  1981. // The above copyright notice and this permission notice shall be included
  1982. // in all copies or substantial portions of the Software.
  1983. //
  1984. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  1985. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  1986. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  1987. // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  1988. // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  1989. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  1990. // USE OR OTHER DEALINGS IN THE SOFTWARE.
  1991. 'use strict';
  1992. var stringifyPrimitive = function(v) {
  1993. switch (typeof v) {
  1994. case 'string':
  1995. return v;
  1996. case 'boolean':
  1997. return v ? 'true' : 'false';
  1998. case 'number':
  1999. return isFinite(v) ? v : '';
  2000. default:
  2001. return '';
  2002. }
  2003. };
  2004. module.exports = function(obj, sep, eq, name) {
  2005. sep = sep || '&';
  2006. eq = eq || '=';
  2007. if (obj === null) {
  2008. obj = undefined;
  2009. }
  2010. if (typeof obj === 'object') {
  2011. return map(objectKeys(obj), function(k) {
  2012. var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
  2013. if (isArray(obj[k])) {
  2014. return map(obj[k], function(v) {
  2015. return ks + encodeURIComponent(stringifyPrimitive(v));
  2016. }).join(sep);
  2017. } else {
  2018. return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
  2019. }
  2020. }).join(sep);
  2021. }
  2022. if (!name) return '';
  2023. return encodeURIComponent(stringifyPrimitive(name)) + eq +
  2024. encodeURIComponent(stringifyPrimitive(obj));
  2025. };
  2026. var isArray = Array.isArray || function (xs) {
  2027. return Object.prototype.toString.call(xs) === '[object Array]';
  2028. };
  2029. function map (xs, f) {
  2030. if (xs.map) return xs.map(f);
  2031. var res = [];
  2032. for (var i = 0; i < xs.length; i++) {
  2033. res.push(f(xs[i], i));
  2034. }
  2035. return res;
  2036. }
  2037. var objectKeys = Object.keys || function (obj) {
  2038. var res = [];
  2039. for (var key in obj) {
  2040. if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);
  2041. }
  2042. return res;
  2043. };
  2044. },{}],7:[function(require,module,exports){
  2045. 'use strict';
  2046. exports.decode = exports.parse = require('./decode');
  2047. exports.encode = exports.stringify = require('./encode');
  2048. },{"./decode":5,"./encode":6}],8:[function(require,module,exports){
  2049. // Copyright Joyent, Inc. and other Node contributors.
  2050. //
  2051. // Permission is hereby granted, free of charge, to any person obtaining a
  2052. // copy of this software and associated documentation files (the
  2053. // "Software"), to deal in the Software without restriction, including
  2054. // without limitation the rights to use, copy, modify, merge, publish,
  2055. // distribute, sublicense, and/or sell copies of the Software, and to permit
  2056. // persons to whom the Software is furnished to do so, subject to the
  2057. // following conditions:
  2058. //
  2059. // The above copyright notice and this permission notice shall be included
  2060. // in all copies or substantial portions of the Software.
  2061. //
  2062. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  2063. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  2064. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  2065. // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  2066. // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  2067. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  2068. // USE OR OTHER DEALINGS IN THE SOFTWARE.
  2069. var punycode = require('punycode');
  2070. exports.parse = urlParse;
  2071. exports.resolve = urlResolve;
  2072. exports.resolveObject = urlResolveObject;
  2073. exports.format = urlFormat;
  2074. exports.Url = Url;
  2075. function Url() {
  2076. this.protocol = null;
  2077. this.slashes = null;
  2078. this.auth = null;
  2079. this.host = null;
  2080. this.port = null;
  2081. this.hostname = null;
  2082. this.hash = null;
  2083. this.search = null;
  2084. this.query = null;
  2085. this.pathname = null;
  2086. this.path = null;
  2087. this.href = null;
  2088. }
  2089. // Reference: RFC 3986, RFC 1808, RFC 2396
  2090. // define these here so at least they only have to be
  2091. // compiled once on the first module load.
  2092. var protocolPattern = /^([a-z0-9.+-]+:)/i,
  2093. portPattern = /:[0-9]*$/,
  2094. // RFC 2396: characters reserved for delimiting URLs.
  2095. // We actually just auto-escape these.
  2096. delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
  2097. // RFC 2396: characters not allowed for various reasons.
  2098. unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
  2099. // Allowed by RFCs, but cause of XSS attacks. Always escape these.
  2100. autoEscape = ['\''].concat(unwise),
  2101. // Characters that are never ever allowed in a hostname.
  2102. // Note that any invalid chars are also handled, but these
  2103. // are the ones that are *expected* to be seen, so we fast-path
  2104. // them.
  2105. nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
  2106. hostEndingChars = ['/', '?', '#'],
  2107. hostnameMaxLen = 255,
  2108. hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/,
  2109. hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/,
  2110. // protocols that can allow "unsafe" and "unwise" chars.
  2111. unsafeProtocol = {
  2112. 'javascript': true,
  2113. 'javascript:': true
  2114. },
  2115. // protocols that never have a hostname.
  2116. hostlessProtocol = {
  2117. 'javascript': true,
  2118. 'javascript:': true
  2119. },
  2120. // protocols that always contain a // bit.
  2121. slashedProtocol = {
  2122. 'http': true,
  2123. 'https': true,
  2124. 'ftp': true,
  2125. 'gopher': true,
  2126. 'file': true,
  2127. 'http:': true,
  2128. 'https:': true,
  2129. 'ftp:': true,
  2130. 'gopher:': true,
  2131. 'file:': true
  2132. },
  2133. querystring = require('querystring');
  2134. function urlParse(url, parseQueryString, slashesDenoteHost) {
  2135. if (url && isObject(url) && url instanceof Url) return url;
  2136. var u = new Url;
  2137. u.parse(url, parseQueryString, slashesDenoteHost);
  2138. return u;
  2139. }
  2140. Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
  2141. if (!isString(url)) {
  2142. throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
  2143. }
  2144. var rest = url;
  2145. // trim before proceeding.
  2146. // This is to support parse stuff like " http://foo.com \n"
  2147. rest = rest.trim();
  2148. var proto = protocolPattern.exec(rest);
  2149. if (proto) {
  2150. proto = proto[0];
  2151. var lowerProto = proto.toLowerCase();
  2152. this.protocol = lowerProto;
  2153. rest = rest.substr(proto.length);
  2154. }
  2155. // figure out if it's got a host
  2156. // user@server is *always* interpreted as a hostname, and url
  2157. // resolution will treat //foo/bar as host=foo,path=bar because that's
  2158. // how the browser resolves relative URLs.
  2159. if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
  2160. var slashes = rest.substr(0, 2) === '//';
  2161. if (slashes && !(proto && hostlessProtocol[proto])) {
  2162. rest = rest.substr(2);
  2163. this.slashes = true;
  2164. }
  2165. }
  2166. if (!hostlessProtocol[proto] &&
  2167. (slashes || (proto && !slashedProtocol[proto]))) {
  2168. // there's a hostname.
  2169. // the first instance of /, ?, ;, or # ends the host.
  2170. //
  2171. // If there is an @ in the hostname, then non-host chars *are* allowed
  2172. // to the left of the last @ sign, unless some host-ending character
  2173. // comes *before* the @-sign.
  2174. // URLs are obnoxious.
  2175. //
  2176. // ex:
  2177. // http://a@b@c/ => user:a@b host:c
  2178. // http://a@b?@c => user:a host:c path:/?@c
  2179. // v0.12 TODO(isaacs): This is not quite how Chrome does things.
  2180. // Review our test case against browsers more comprehensively.
  2181. // find the first instance of any hostEndingChars
  2182. var hostEnd = -1;
  2183. for (var i = 0; i < hostEndingChars.length; i++) {
  2184. var hec = rest.indexOf(hostEndingChars[i]);
  2185. if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
  2186. hostEnd = hec;
  2187. }
  2188. // at this point, either we have an explicit point where the
  2189. // auth portion cannot go past, or the last @ char is the decider.
  2190. var auth, atSign;
  2191. if (hostEnd === -1) {
  2192. // atSign can be anywhere.
  2193. atSign = rest.lastIndexOf('@');
  2194. } else {
  2195. // atSign must be in auth portion.
  2196. // http://a@b/c@d => host:b auth:a path:/c@d
  2197. atSign = rest.lastIndexOf('@', hostEnd);
  2198. }
  2199. // Now we have a portion which is definitely the auth.
  2200. // Pull that off.
  2201. if (atSign !== -1) {
  2202. auth = rest.slice(0, atSign);
  2203. rest = rest.slice(atSign + 1);
  2204. this.auth = decodeURIComponent(auth);
  2205. }
  2206. // the host is the remaining to the left of the first non-host char
  2207. hostEnd = -1;
  2208. for (var i = 0; i < nonHostChars.length; i++) {
  2209. var hec = rest.indexOf(nonHostChars[i]);
  2210. if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
  2211. hostEnd = hec;
  2212. }
  2213. // if we still have not hit it, then the entire thing is a host.
  2214. if (hostEnd === -1)
  2215. hostEnd = rest.length;
  2216. this.host = rest.slice(0, hostEnd);
  2217. rest = rest.slice(hostEnd);
  2218. // pull out port.
  2219. this.parseHost();
  2220. // we've indicated that there is a hostname,
  2221. // so even if it's empty, it has to be present.
  2222. this.hostname = this.hostname || '';
  2223. // if hostname begins with [ and ends with ]
  2224. // assume that it's an IPv6 address.
  2225. var ipv6Hostname = this.hostname[0] === '[' &&
  2226. this.hostname[this.hostname.length - 1] === ']';
  2227. // validate a little.
  2228. if (!ipv6Hostname) {
  2229. var hostparts = this.hostname.split(/\./);
  2230. for (var i = 0, l = hostparts.length; i < l; i++) {
  2231. var part = hostparts[i];
  2232. if (!part) continue;
  2233. if (!part.match(hostnamePartPattern)) {
  2234. var newpart = '';
  2235. for (var j = 0, k = part.length; j < k; j++) {
  2236. if (part.charCodeAt(j) > 127) {
  2237. // we replace non-ASCII char with a temporary placeholder
  2238. // we need this to make sure size of hostname is not
  2239. // broken by replacing non-ASCII by nothing
  2240. newpart += 'x';
  2241. } else {
  2242. newpart += part[j];
  2243. }
  2244. }
  2245. // we test again with ASCII char only
  2246. if (!newpart.match(hostnamePartPattern)) {
  2247. var validParts = hostparts.slice(0, i);
  2248. var notHost = hostparts.slice(i + 1);
  2249. var bit = part.match(hostnamePartStart);
  2250. if (bit) {
  2251. validParts.push(bit[1]);
  2252. notHost.unshift(bit[2]);
  2253. }
  2254. if (notHost.length) {
  2255. rest = '/' + notHost.join('.') + rest;
  2256. }
  2257. this.hostname = validParts.join('.');
  2258. break;
  2259. }
  2260. }
  2261. }
  2262. }
  2263. if (this.hostname.length > hostnameMaxLen) {
  2264. this.hostname = '';
  2265. } else {
  2266. // hostnames are always lower case.
  2267. this.hostname = this.hostname.toLowerCase();
  2268. }
  2269. if (!ipv6Hostname) {
  2270. // IDNA Support: Returns a puny coded representation of "domain".
  2271. // It only converts the part of the domain name that
  2272. // has non ASCII characters. I.e. it dosent matter if
  2273. // you call it with a domain that already is in ASCII.
  2274. var domainArray = this.hostname.split('.');
  2275. var newOut = [];
  2276. for (var i = 0; i < domainArray.length; ++i) {
  2277. var s = domainArray[i];
  2278. newOut.push(s.match(/[^A-Za-z0-9_-]/) ?
  2279. 'xn--' + punycode.encode(s) : s);
  2280. }
  2281. this.hostname = newOut.join('.');
  2282. }
  2283. var p = this.port ? ':' + this.port : '';
  2284. var h = this.hostname || '';
  2285. this.host = h + p;
  2286. this.href += this.host;
  2287. // strip [ and ] from the hostname
  2288. // the host field still retains them, though
  2289. if (ipv6Hostname) {
  2290. this.hostname = this.hostname.substr(1, this.hostname.length - 2);
  2291. if (rest[0] !== '/') {
  2292. rest = '/' + rest;
  2293. }
  2294. }
  2295. }
  2296. // now rest is set to the post-host stuff.
  2297. // chop off any delim chars.
  2298. if (!unsafeProtocol[lowerProto]) {
  2299. // First, make 100% sure that any "autoEscape" chars get
  2300. // escaped, even if encodeURIComponent doesn't think they
  2301. // need to be.
  2302. for (var i = 0, l = autoEscape.length; i < l; i++) {
  2303. var ae = autoEscape[i];
  2304. var esc = encodeURIComponent(ae);
  2305. if (esc === ae) {
  2306. esc = escape(ae);
  2307. }
  2308. rest = rest.split(ae).join(esc);
  2309. }
  2310. }
  2311. // chop off from the tail first.
  2312. var hash = rest.indexOf('#');
  2313. if (hash !== -1) {
  2314. // got a fragment string.
  2315. this.hash = rest.substr(hash);
  2316. rest = rest.slice(0, hash);
  2317. }
  2318. var qm = rest.indexOf('?');
  2319. if (qm !== -1) {
  2320. this.search = rest.substr(qm);
  2321. this.query = rest.substr(qm + 1);
  2322. if (parseQueryString) {
  2323. this.query = querystring.parse(this.query);
  2324. }
  2325. rest = rest.slice(0, qm);
  2326. } else if (parseQueryString) {
  2327. // no query string, but parseQueryString still requested
  2328. this.search = '';
  2329. this.query = {};
  2330. }
  2331. if (rest) this.pathname = rest;
  2332. if (slashedProtocol[lowerProto] &&
  2333. this.hostname && !this.pathname) {
  2334. this.pathname = '/';
  2335. }
  2336. //to support http.request
  2337. if (this.pathname || this.search) {
  2338. var p = this.pathname || '';
  2339. var s = this.search || '';
  2340. this.path = p + s;
  2341. }
  2342. // finally, reconstruct the href based on what has been validated.
  2343. this.href = this.format();
  2344. return this;
  2345. };
  2346. // format a parsed object into a url string
  2347. function urlFormat(obj) {
  2348. // ensure it's an object, and not a string url.
  2349. // If it's an obj, this is a no-op.
  2350. // this way, you can call url_format() on strings
  2351. // to clean up potentially wonky urls.
  2352. if (isString(obj)) obj = urlParse(obj);
  2353. if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
  2354. return obj.format();
  2355. }
  2356. Url.prototype.format = function() {
  2357. var auth = this.auth || '';
  2358. if (auth) {
  2359. auth = encodeURIComponent(auth);
  2360. auth = auth.replace(/%3A/i, ':');
  2361. auth += '@';
  2362. }
  2363. var protocol = this.protocol || '',
  2364. pathname = this.pathname || '',
  2365. hash = this.hash || '',
  2366. host = false,
  2367. query = '';
  2368. if (this.host) {
  2369. host = auth + this.host;
  2370. } else if (this.hostname) {
  2371. host = auth + (this.hostname.indexOf(':') === -1 ?
  2372. this.hostname :
  2373. '[' + this.hostname + ']');
  2374. if (this.port) {
  2375. host += ':' + this.port;
  2376. }
  2377. }
  2378. if (this.query &&
  2379. isObject(this.query) &&
  2380. Object.keys(this.query).length) {
  2381. query = querystring.stringify(this.query);
  2382. }
  2383. var search = this.search || (query && ('?' + query)) || '';
  2384. if (protocol && protocol.substr(-1) !== ':') protocol += ':';
  2385. // only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
  2386. // unless they had them to begin with.
  2387. if (this.slashes ||
  2388. (!protocol || slashedProtocol[protocol]) && host !== false) {
  2389. host = '//' + (host || '');
  2390. if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
  2391. } else if (!host) {
  2392. host = '';
  2393. }
  2394. if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
  2395. if (search && search.charAt(0) !== '?') search = '?' + search;
  2396. pathname = pathname.replace(/[?#]/g, function(match) {
  2397. return encodeURIComponent(match);
  2398. });
  2399. search = search.replace('#', '%23');
  2400. return protocol + host + pathname + search + hash;
  2401. };
  2402. function urlResolve(source, relative) {
  2403. return urlParse(source, false, true).resolve(relative);
  2404. }
  2405. Url.prototype.resolve = function(relative) {
  2406. return this.resolveObject(urlParse(relative, false, true)).format();
  2407. };
  2408. function urlResolveObject(source, relative) {
  2409. if (!source) return relative;
  2410. return urlParse(source, false, true).resolveObject(relative);
  2411. }
  2412. Url.prototype.resolveObject = function(relative) {
  2413. if (isString(relative)) {
  2414. var rel = new Url();
  2415. rel.parse(relative, false, true);
  2416. relative = rel;
  2417. }
  2418. var result = new Url();
  2419. Object.keys(this).forEach(function(k) {
  2420. result[k] = this[k];
  2421. }, this);
  2422. // hash is always overridden, no matter what.
  2423. // even href="" will remove it.
  2424. result.hash = relative.hash;
  2425. // if the relative url is empty, then there's nothing left to do here.
  2426. if (relative.href === '') {
  2427. result.href = result.format();
  2428. return result;
  2429. }
  2430. // hrefs like //foo/bar always cut to the protocol.
  2431. if (relative.slashes && !relative.protocol) {
  2432. // take everything except the protocol from relative
  2433. Object.keys(relative).forEach(function(k) {
  2434. if (k !== 'protocol')
  2435. result[k] = relative[k];
  2436. });
  2437. //urlParse appends trailing / to urls like http://www.example.com
  2438. if (slashedProtocol[result.protocol] &&
  2439. result.hostname && !result.pathname) {
  2440. result.path = result.pathname = '/';
  2441. }
  2442. result.href = result.format();
  2443. return result;
  2444. }
  2445. if (relative.protocol && relative.protocol !== result.protocol) {
  2446. // if it's a known url protocol, then changing
  2447. // the protocol does weird things
  2448. // first, if it's not file:, then we MUST have a host,
  2449. // and if there was a path
  2450. // to begin with, then we MUST have a path.
  2451. // if it is file:, then the host is dropped,
  2452. // because that's known to be hostless.
  2453. // anything else is assumed to be absolute.
  2454. if (!slashedProtocol[relative.protocol]) {
  2455. Object.keys(relative).forEach(function(k) {
  2456. result[k] = relative[k];
  2457. });
  2458. result.href = result.format();
  2459. return result;
  2460. }
  2461. result.protocol = relative.protocol;
  2462. if (!relative.host && !hostlessProtocol[relative.protocol]) {
  2463. var relPath = (relative.pathname || '').split('/');
  2464. while (relPath.length && !(relative.host = relPath.shift()));
  2465. if (!relative.host) relative.host = '';
  2466. if (!relative.hostname) relative.hostname = '';
  2467. if (relPath[0] !== '') relPath.unshift('');
  2468. if (relPath.length < 2) relPath.unshift('');
  2469. result.pathname = relPath.join('/');
  2470. } else {
  2471. result.pathname = relative.pathname;
  2472. }
  2473. result.search = relative.search;
  2474. result.query = relative.query;
  2475. result.host = relative.host || '';
  2476. result.auth = relative.auth;
  2477. result.hostname = relative.hostname || relative.host;
  2478. result.port = relative.port;
  2479. // to support http.request
  2480. if (result.pathname || result.search) {
  2481. var p = result.pathname || '';
  2482. var s = result.search || '';
  2483. result.path = p + s;
  2484. }
  2485. result.slashes = result.slashes || relative.slashes;
  2486. result.href = result.format();
  2487. return result;
  2488. }
  2489. var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
  2490. isRelAbs = (
  2491. relative.host ||
  2492. relative.pathname && relative.pathname.charAt(0) === '/'
  2493. ),
  2494. mustEndAbs = (isRelAbs || isSourceAbs ||
  2495. (result.host && relative.pathname)),
  2496. removeAllDots = mustEndAbs,
  2497. srcPath = result.pathname && result.pathname.split('/') || [],
  2498. relPath = relative.pathname && relative.pathname.split('/') || [],
  2499. psychotic = result.protocol && !slashedProtocol[result.protocol];
  2500. // if the url is a non-slashed url, then relative
  2501. // links like ../.. should be able
  2502. // to crawl up to the hostname, as well. This is strange.
  2503. // result.protocol has already been set by now.
  2504. // Later on, put the first path part into the host field.
  2505. if (psychotic) {
  2506. result.hostname = '';
  2507. result.port = null;
  2508. if (result.host) {
  2509. if (srcPath[0] === '') srcPath[0] = result.host;
  2510. else srcPath.unshift(result.host);
  2511. }
  2512. result.host = '';
  2513. if (relative.protocol) {
  2514. relative.hostname = null;
  2515. relative.port = null;
  2516. if (relative.host) {
  2517. if (relPath[0] === '') relPath[0] = relative.host;
  2518. else relPath.unshift(relative.host);
  2519. }
  2520. relative.host = null;
  2521. }
  2522. mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
  2523. }
  2524. if (isRelAbs) {
  2525. // it's absolute.
  2526. result.host = (relative.host || relative.host === '') ?
  2527. relative.host : result.host;
  2528. result.hostname = (relative.hostname || relative.hostname === '') ?
  2529. relative.hostname : result.hostname;
  2530. result.search = relative.search;
  2531. result.query = relative.query;
  2532. srcPath = relPath;
  2533. // fall through to the dot-handling below.
  2534. } else if (relPath.length) {
  2535. // it's relative
  2536. // throw away the existing file, and take the new path instead.
  2537. if (!srcPath) srcPath = [];
  2538. srcPath.pop();
  2539. srcPath = srcPath.concat(relPath);
  2540. result.search = relative.search;
  2541. result.query = relative.query;
  2542. } else if (!isNullOrUndefined(relative.search)) {
  2543. // just pull out the search.
  2544. // like href='?foo'.
  2545. // Put this after the other two cases because it simplifies the booleans
  2546. if (psychotic) {
  2547. result.hostname = result.host = srcPath.shift();
  2548. //occationaly the auth can get stuck only in host
  2549. //this especialy happens in cases like
  2550. //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
  2551. var authInHost = result.host && result.host.indexOf('@') > 0 ?
  2552. result.host.split('@') : false;
  2553. if (authInHost) {
  2554. result.auth = authInHost.shift();
  2555. result.host = result.hostname = authInHost.shift();
  2556. }
  2557. }
  2558. result.search = relative.search;
  2559. result.query = relative.query;
  2560. //to support http.request
  2561. if (!isNull(result.pathname) || !isNull(result.search)) {
  2562. result.path = (result.pathname ? result.pathname : '') +
  2563. (result.search ? result.search : '');
  2564. }
  2565. result.href = result.format();
  2566. return result;
  2567. }
  2568. if (!srcPath.length) {
  2569. // no path at all. easy.
  2570. // we've already handled the other stuff above.
  2571. result.pathname = null;
  2572. //to support http.request
  2573. if (result.search) {
  2574. result.path = '/' + result.search;
  2575. } else {
  2576. result.path = null;
  2577. }
  2578. result.href = result.format();
  2579. return result;
  2580. }
  2581. // if a url ENDs in . or .., then it must get a trailing slash.
  2582. // however, if it ends in anything else non-slashy,
  2583. // then it must NOT get a trailing slash.
  2584. var last = srcPath.slice(-1)[0];
  2585. var hasTrailingSlash = (
  2586. (result.host || relative.host) && (last === '.' || last === '..') ||
  2587. last === '');
  2588. // strip single dots, resolve double dots to parent dir
  2589. // if the path tries to go above the root, `up` ends up > 0
  2590. var up = 0;
  2591. for (var i = srcPath.length; i >= 0; i--) {
  2592. last = srcPath[i];
  2593. if (last == '.') {
  2594. srcPath.splice(i, 1);
  2595. } else if (last === '..') {
  2596. srcPath.splice(i, 1);
  2597. up++;
  2598. } else if (up) {
  2599. srcPath.splice(i, 1);
  2600. up--;
  2601. }
  2602. }
  2603. // if the path is allowed to go above the root, restore leading ..s
  2604. if (!mustEndAbs && !removeAllDots) {
  2605. for (; up--; up) {
  2606. srcPath.unshift('..');
  2607. }
  2608. }
  2609. if (mustEndAbs && srcPath[0] !== '' &&
  2610. (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
  2611. srcPath.unshift('');
  2612. }
  2613. if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
  2614. srcPath.push('');
  2615. }
  2616. var isAbsolute = srcPath[0] === '' ||
  2617. (srcPath[0] && srcPath[0].charAt(0) === '/');
  2618. // put the host back
  2619. if (psychotic) {
  2620. result.hostname = result.host = isAbsolute ? '' :
  2621. srcPath.length ? srcPath.shift() : '';
  2622. //occationaly the auth can get stuck only in host
  2623. //this especialy happens in cases like
  2624. //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
  2625. var authInHost = result.host && result.host.indexOf('@') > 0 ?
  2626. result.host.split('@') : false;
  2627. if (authInHost) {
  2628. result.auth = authInHost.shift();
  2629. result.host = result.hostname = authInHost.shift();
  2630. }
  2631. }
  2632. mustEndAbs = mustEndAbs || (result.host && srcPath.length);
  2633. if (mustEndAbs && !isAbsolute) {
  2634. srcPath.unshift('');
  2635. }
  2636. if (!srcPath.length) {
  2637. result.pathname = null;
  2638. result.path = null;
  2639. } else {
  2640. result.pathname = srcPath.join('/');
  2641. }
  2642. //to support request.http
  2643. if (!isNull(result.pathname) || !isNull(result.search)) {
  2644. result.path = (result.pathname ? result.pathname : '') +
  2645. (result.search ? result.search : '');
  2646. }
  2647. result.auth = relative.auth || result.auth;
  2648. result.slashes = result.slashes || relative.slashes;
  2649. result.href = result.format();
  2650. return result;
  2651. };
  2652. Url.prototype.parseHost = function() {
  2653. var host = this.host;
  2654. var port = portPattern.exec(host);
  2655. if (port) {
  2656. port = port[0];
  2657. if (port !== ':') {
  2658. this.port = port.substr(1);
  2659. }
  2660. host = host.substr(0, host.length - port.length);
  2661. }
  2662. if (host) this.hostname = host;
  2663. };
  2664. function isString(arg) {
  2665. return typeof arg === "string";
  2666. }
  2667. function isObject(arg) {
  2668. return typeof arg === 'object' && arg !== null;
  2669. }
  2670. function isNull(arg) {
  2671. return arg === null;
  2672. }
  2673. function isNullOrUndefined(arg) {
  2674. return arg == null;
  2675. }
  2676. },{"punycode":4,"querystring":7}],9:[function(require,module,exports){
  2677. 'use strict';
  2678. module.exports = earcut;
  2679. function earcut(data, holeIndices, dim) {
  2680. dim = dim || 2;
  2681. var hasHoles = holeIndices && holeIndices.length,
  2682. outerLen = hasHoles ? holeIndices[0] * dim : data.length,
  2683. outerNode = linkedList(data, 0, outerLen, dim, true),
  2684. triangles = [];
  2685. if (!outerNode) return triangles;
  2686. var minX, minY, maxX, maxY, x, y, size;
  2687. if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
  2688. // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
  2689. if (data.length > 80 * dim) {
  2690. minX = maxX = data[0];
  2691. minY = maxY = data[1];
  2692. for (var i = dim; i < outerLen; i += dim) {
  2693. x = data[i];
  2694. y = data[i + 1];
  2695. if (x < minX) minX = x;
  2696. if (y < minY) minY = y;
  2697. if (x > maxX) maxX = x;
  2698. if (y > maxY) maxY = y;
  2699. }
  2700. // minX, minY and size are later used to transform coords into integers for z-order calculation
  2701. size = Math.max(maxX - minX, maxY - minY);
  2702. }
  2703. earcutLinked(outerNode, triangles, dim, minX, minY, size);
  2704. return triangles;
  2705. }
  2706. // create a circular doubly linked list from polygon points in the specified winding order
  2707. function linkedList(data, start, end, dim, clockwise) {
  2708. var sum = 0,
  2709. i, j, last;
  2710. // calculate original winding order of a polygon ring
  2711. for (i = start, j = end - dim; i < end; i += dim) {
  2712. sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
  2713. j = i;
  2714. }
  2715. // link points into circular doubly-linked list in the specified winding order
  2716. if (clockwise === (sum > 0)) {
  2717. for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last);
  2718. } else {
  2719. for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last);
  2720. }
  2721. return last;
  2722. }
  2723. // eliminate colinear or duplicate points
  2724. function filterPoints(start, end) {
  2725. if (!start) return start;
  2726. if (!end) end = start;
  2727. var p = start,
  2728. again;
  2729. do {
  2730. again = false;
  2731. if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
  2732. removeNode(p);
  2733. p = end = p.prev;
  2734. if (p === p.next) return null;
  2735. again = true;
  2736. } else {
  2737. p = p.next;
  2738. }
  2739. } while (again || p !== end);
  2740. return end;
  2741. }
  2742. // main ear slicing loop which triangulates a polygon (given as a linked list)
  2743. function earcutLinked(ear, triangles, dim, minX, minY, size, pass) {
  2744. if (!ear) return;
  2745. // interlink polygon nodes in z-order
  2746. if (!pass && size) indexCurve(ear, minX, minY, size);
  2747. var stop = ear,
  2748. prev, next;
  2749. // iterate through ears, slicing them one by one
  2750. while (ear.prev !== ear.next) {
  2751. prev = ear.prev;
  2752. next = ear.next;
  2753. if (size ? isEarHashed(ear, minX, minY, size) : isEar(ear)) {
  2754. // cut off the triangle
  2755. triangles.push(prev.i / dim);
  2756. triangles.push(ear.i / dim);
  2757. triangles.push(next.i / dim);
  2758. removeNode(ear);
  2759. // skipping the next vertice leads to less sliver triangles
  2760. ear = next.next;
  2761. stop = next.next;
  2762. continue;
  2763. }
  2764. ear = next;
  2765. // if we looped through the whole remaining polygon and can't find any more ears
  2766. if (ear === stop) {
  2767. // try filtering points and slicing again
  2768. if (!pass) {
  2769. earcutLinked(filterPoints(ear), triangles, dim, minX, minY, size, 1);
  2770. // if this didn't work, try curing all small self-intersections locally
  2771. } else if (pass === 1) {
  2772. ear = cureLocalIntersections(ear, triangles, dim);
  2773. earcutLinked(ear, triangles, dim, minX, minY, size, 2);
  2774. // as a last resort, try splitting the remaining polygon into two
  2775. } else if (pass === 2) {
  2776. splitEarcut(ear, triangles, dim, minX, minY, size);
  2777. }
  2778. break;
  2779. }
  2780. }
  2781. }
  2782. // check whether a polygon node forms a valid ear with adjacent nodes
  2783. function isEar(ear) {
  2784. var a = ear.prev,
  2785. b = ear,
  2786. c = ear.next;
  2787. if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
  2788. // now make sure we don't have other points inside the potential ear
  2789. var p = ear.next.next;
  2790. while (p !== ear.prev) {
  2791. if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
  2792. area(p.prev, p, p.next) >= 0) return false;
  2793. p = p.next;
  2794. }
  2795. return true;
  2796. }
  2797. function isEarHashed(ear, minX, minY, size) {
  2798. var a = ear.prev,
  2799. b = ear,
  2800. c = ear.next;
  2801. if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
  2802. // triangle bbox; min & max are calculated like this for speed
  2803. var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x),
  2804. minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y),
  2805. maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x),
  2806. maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y);
  2807. // z-order range for the current triangle bbox;
  2808. var minZ = zOrder(minTX, minTY, minX, minY, size),
  2809. maxZ = zOrder(maxTX, maxTY, minX, minY, size);
  2810. // first look for points inside the triangle in increasing z-order
  2811. var p = ear.nextZ;
  2812. while (p && p.z <= maxZ) {
  2813. if (p !== ear.prev && p !== ear.next &&
  2814. pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
  2815. area(p.prev, p, p.next) >= 0) return false;
  2816. p = p.nextZ;
  2817. }
  2818. // then look for points in decreasing z-order
  2819. p = ear.prevZ;
  2820. while (p && p.z >= minZ) {
  2821. if (p !== ear.prev && p !== ear.next &&
  2822. pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
  2823. area(p.prev, p, p.next) >= 0) return false;
  2824. p = p.prevZ;
  2825. }
  2826. return true;
  2827. }
  2828. // go through all polygon nodes and cure small local self-intersections
  2829. function cureLocalIntersections(start, triangles, dim) {
  2830. var p = start;
  2831. do {
  2832. var a = p.prev,
  2833. b = p.next.next;
  2834. // a self-intersection where edge (v[i-1],v[i]) intersects (v[i+1],v[i+2])
  2835. if (intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
  2836. triangles.push(a.i / dim);
  2837. triangles.push(p.i / dim);
  2838. triangles.push(b.i / dim);
  2839. // remove two nodes involved
  2840. removeNode(p);
  2841. removeNode(p.next);
  2842. p = start = b;
  2843. }
  2844. p = p.next;
  2845. } while (p !== start);
  2846. return p;
  2847. }
  2848. // try splitting polygon into two and triangulate them independently
  2849. function splitEarcut(start, triangles, dim, minX, minY, size) {
  2850. // look for a valid diagonal that divides the polygon into two
  2851. var a = start;
  2852. do {
  2853. var b = a.next.next;
  2854. while (b !== a.prev) {
  2855. if (a.i !== b.i && isValidDiagonal(a, b)) {
  2856. // split the polygon in two by the diagonal
  2857. var c = splitPolygon(a, b);
  2858. // filter colinear points around the cuts
  2859. a = filterPoints(a, a.next);
  2860. c = filterPoints(c, c.next);
  2861. // run earcut on each half
  2862. earcutLinked(a, triangles, dim, minX, minY, size);
  2863. earcutLinked(c, triangles, dim, minX, minY, size);
  2864. return;
  2865. }
  2866. b = b.next;
  2867. }
  2868. a = a.next;
  2869. } while (a !== start);
  2870. }
  2871. // link every hole into the outer loop, producing a single-ring polygon without holes
  2872. function eliminateHoles(data, holeIndices, outerNode, dim) {
  2873. var queue = [],
  2874. i, len, start, end, list;
  2875. for (i = 0, len = holeIndices.length; i < len; i++) {
  2876. start = holeIndices[i] * dim;
  2877. end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
  2878. list = linkedList(data, start, end, dim, false);
  2879. if (list === list.next) list.steiner = true;
  2880. queue.push(getLeftmost(list));
  2881. }
  2882. queue.sort(compareX);
  2883. // process holes from left to right
  2884. for (i = 0; i < queue.length; i++) {
  2885. eliminateHole(queue[i], outerNode);
  2886. outerNode = filterPoints(outerNode, outerNode.next);
  2887. }
  2888. return outerNode;
  2889. }
  2890. function compareX(a, b) {
  2891. return a.x - b.x;
  2892. }
  2893. // find a bridge between vertices that connects hole with an outer ring and and link it
  2894. function eliminateHole(hole, outerNode) {
  2895. outerNode = findHoleBridge(hole, outerNode);
  2896. if (outerNode) {
  2897. var b = splitPolygon(outerNode, hole);
  2898. filterPoints(b, b.next);
  2899. }
  2900. }
  2901. // David Eberly's algorithm for finding a bridge between hole and outer polygon
  2902. function findHoleBridge(hole, outerNode) {
  2903. var p = outerNode,
  2904. hx = hole.x,
  2905. hy = hole.y,
  2906. qx = -Infinity,
  2907. m;
  2908. // find a segment intersected by a ray from the hole's leftmost point to the left;
  2909. // segment's endpoint with lesser x will be potential connection point
  2910. do {
  2911. if (hy <= p.y && hy >= p.next.y) {
  2912. var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
  2913. if (x <= hx && x > qx) {
  2914. qx = x;
  2915. m = p.x < p.next.x ? p : p.next;
  2916. }
  2917. }
  2918. p = p.next;
  2919. } while (p !== outerNode);
  2920. if (!m) return null;
  2921. if (hole.x === m.x) return m.prev; // hole touches outer segment; pick lower endpoint
  2922. // look for points inside the triangle of hole point, segment intersection and endpoint;
  2923. // if there are no points found, we have a valid connection;
  2924. // otherwise choose the point of the minimum angle with the ray as connection point
  2925. var stop = m,
  2926. tanMin = Infinity,
  2927. tan;
  2928. p = m.next;
  2929. while (p !== stop) {
  2930. if (hx >= p.x && p.x >= m.x &&
  2931. pointInTriangle(hy < m.y ? hx : qx, hy, m.x, m.y, hy < m.y ? qx : hx, hy, p.x, p.y)) {
  2932. tan = Math.abs(hy - p.y) / (hx - p.x); // tangential
  2933. if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && locallyInside(p, hole)) {
  2934. m = p;
  2935. tanMin = tan;
  2936. }
  2937. }
  2938. p = p.next;
  2939. }
  2940. return m;
  2941. }
  2942. // interlink polygon nodes in z-order
  2943. function indexCurve(start, minX, minY, size) {
  2944. var p = start;
  2945. do {
  2946. if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, size);
  2947. p.prevZ = p.prev;
  2948. p.nextZ = p.next;
  2949. p = p.next;
  2950. } while (p !== start);
  2951. p.prevZ.nextZ = null;
  2952. p.prevZ = null;
  2953. sortLinked(p);
  2954. }
  2955. // Simon Tatham's linked list merge sort algorithm
  2956. // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
  2957. function sortLinked(list) {
  2958. var i, p, q, e, tail, numMerges, pSize, qSize,
  2959. inSize = 1;
  2960. do {
  2961. p = list;
  2962. list = null;
  2963. tail = null;
  2964. numMerges = 0;
  2965. while (p) {
  2966. numMerges++;
  2967. q = p;
  2968. pSize = 0;
  2969. for (i = 0; i < inSize; i++) {
  2970. pSize++;
  2971. q = q.nextZ;
  2972. if (!q) break;
  2973. }
  2974. qSize = inSize;
  2975. while (pSize > 0 || (qSize > 0 && q)) {
  2976. if (pSize === 0) {
  2977. e = q;
  2978. q = q.nextZ;
  2979. qSize--;
  2980. } else if (qSize === 0 || !q) {
  2981. e = p;
  2982. p = p.nextZ;
  2983. pSize--;
  2984. } else if (p.z <= q.z) {
  2985. e = p;
  2986. p = p.nextZ;
  2987. pSize--;
  2988. } else {
  2989. e = q;
  2990. q = q.nextZ;
  2991. qSize--;
  2992. }
  2993. if (tail) tail.nextZ = e;
  2994. else list = e;
  2995. e.prevZ = tail;
  2996. tail = e;
  2997. }
  2998. p = q;
  2999. }
  3000. tail.nextZ = null;
  3001. inSize *= 2;
  3002. } while (numMerges > 1);
  3003. return list;
  3004. }
  3005. // z-order of a point given coords and size of the data bounding box
  3006. function zOrder(x, y, minX, minY, size) {
  3007. // coords are transformed into non-negative 15-bit integer range
  3008. x = 32767 * (x - minX) / size;
  3009. y = 32767 * (y - minY) / size;
  3010. x = (x | (x << 8)) & 0x00FF00FF;
  3011. x = (x | (x << 4)) & 0x0F0F0F0F;
  3012. x = (x | (x << 2)) & 0x33333333;
  3013. x = (x | (x << 1)) & 0x55555555;
  3014. y = (y | (y << 8)) & 0x00FF00FF;
  3015. y = (y | (y << 4)) & 0x0F0F0F0F;
  3016. y = (y | (y << 2)) & 0x33333333;
  3017. y = (y | (y << 1)) & 0x55555555;
  3018. return x | (y << 1);
  3019. }
  3020. // find the leftmost node of a polygon ring
  3021. function getLeftmost(start) {
  3022. var p = start,
  3023. leftmost = start;
  3024. do {
  3025. if (p.x < leftmost.x) leftmost = p;
  3026. p = p.next;
  3027. } while (p !== start);
  3028. return leftmost;
  3029. }
  3030. // check if a point lies within a convex triangle
  3031. function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
  3032. return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 &&
  3033. (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 &&
  3034. (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0;
  3035. }
  3036. // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
  3037. function isValidDiagonal(a, b) {
  3038. return equals(a, b) || a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) &&
  3039. locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b);
  3040. }
  3041. // signed area of a triangle
  3042. function area(p, q, r) {
  3043. return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
  3044. }
  3045. // check if two points are equal
  3046. function equals(p1, p2) {
  3047. return p1.x === p2.x && p1.y === p2.y;
  3048. }
  3049. // check if two segments intersect
  3050. function intersects(p1, q1, p2, q2) {
  3051. return area(p1, q1, p2) > 0 !== area(p1, q1, q2) > 0 &&
  3052. area(p2, q2, p1) > 0 !== area(p2, q2, q1) > 0;
  3053. }
  3054. // check if a polygon diagonal intersects any polygon segments
  3055. function intersectsPolygon(a, b) {
  3056. var p = a;
  3057. do {
  3058. if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
  3059. intersects(p, p.next, a, b)) return true;
  3060. p = p.next;
  3061. } while (p !== a);
  3062. return false;
  3063. }
  3064. // check if a polygon diagonal is locally inside the polygon
  3065. function locallyInside(a, b) {
  3066. return area(a.prev, a, a.next) < 0 ?
  3067. area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :
  3068. area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
  3069. }
  3070. // check if the middle point of a polygon diagonal is inside the polygon
  3071. function middleInside(a, b) {
  3072. var p = a,
  3073. inside = false,
  3074. px = (a.x + b.x) / 2,
  3075. py = (a.y + b.y) / 2;
  3076. do {
  3077. if (((p.y > py) !== (p.next.y > py)) && (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))
  3078. inside = !inside;
  3079. p = p.next;
  3080. } while (p !== a);
  3081. return inside;
  3082. }
  3083. // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
  3084. // if one belongs to the outer ring and another to a hole, it merges it into a single ring
  3085. function splitPolygon(a, b) {
  3086. var a2 = new Node(a.i, a.x, a.y),
  3087. b2 = new Node(b.i, b.x, b.y),
  3088. an = a.next,
  3089. bp = b.prev;
  3090. a.next = b;
  3091. b.prev = a;
  3092. a2.next = an;
  3093. an.prev = a2;
  3094. b2.next = a2;
  3095. a2.prev = b2;
  3096. bp.next = b2;
  3097. b2.prev = bp;
  3098. return b2;
  3099. }
  3100. // create a node and optionally link it with previous one (in a circular doubly linked list)
  3101. function insertNode(i, x, y, last) {
  3102. var p = new Node(i, x, y);
  3103. if (!last) {
  3104. p.prev = p;
  3105. p.next = p;
  3106. } else {
  3107. p.next = last.next;
  3108. p.prev = last;
  3109. last.next.prev = p;
  3110. last.next = p;
  3111. }
  3112. return p;
  3113. }
  3114. function removeNode(p) {
  3115. p.next.prev = p.prev;
  3116. p.prev.next = p.next;
  3117. if (p.prevZ) p.prevZ.nextZ = p.nextZ;
  3118. if (p.nextZ) p.nextZ.prevZ = p.prevZ;
  3119. }
  3120. function Node(i, x, y) {
  3121. // vertice index in coordinates array
  3122. this.i = i;
  3123. // vertex coordinates
  3124. this.x = x;
  3125. this.y = y;
  3126. // previous and next vertice nodes in a polygon ring
  3127. this.prev = null;
  3128. this.next = null;
  3129. // z-order curve value
  3130. this.z = null;
  3131. // previous and next nodes in z-order
  3132. this.prevZ = null;
  3133. this.nextZ = null;
  3134. // indicates whether this is a steiner point
  3135. this.steiner = false;
  3136. }
  3137. },{}],10:[function(require,module,exports){
  3138. 'use strict';
  3139. //
  3140. // We store our EE objects in a plain object whose properties are event names.
  3141. // If `Object.create(null)` is not supported we prefix the event names with a
  3142. // `~` to make sure that the built-in object properties are not overridden or
  3143. // used as an attack vector.
  3144. // We also assume that `Object.create(null)` is available when the event name
  3145. // is an ES6 Symbol.
  3146. //
  3147. var prefix = typeof Object.create !== 'function' ? '~' : false;
  3148. /**
  3149. * Representation of a single EventEmitter function.
  3150. *
  3151. * @param {Function} fn Event handler to be called.
  3152. * @param {Mixed} context Context for function execution.
  3153. * @param {Boolean} once Only emit once
  3154. * @api private
  3155. */
  3156. function EE(fn, context, once) {
  3157. this.fn = fn;
  3158. this.context = context;
  3159. this.once = once || false;
  3160. }
  3161. /**
  3162. * Minimal EventEmitter interface that is molded against the Node.js
  3163. * EventEmitter interface.
  3164. *
  3165. * @constructor
  3166. * @api public
  3167. */
  3168. function EventEmitter() { /* Nothing to set */ }
  3169. /**
  3170. * Holds the assigned EventEmitters by name.
  3171. *
  3172. * @type {Object}
  3173. * @private
  3174. */
  3175. EventEmitter.prototype._events = undefined;
  3176. /**
  3177. * Return a list of assigned event listeners.
  3178. *
  3179. * @param {String} event The events that should be listed.
  3180. * @param {Boolean} exists We only need to know if there are listeners.
  3181. * @returns {Array|Boolean}
  3182. * @api public
  3183. */
  3184. EventEmitter.prototype.listeners = function listeners(event, exists) {
  3185. var evt = prefix ? prefix + event : event
  3186. , available = this._events && this._events[evt];
  3187. if (exists) return !!available;
  3188. if (!available) return [];
  3189. if (available.fn) return [available.fn];
  3190. for (var i = 0, l = available.length, ee = new Array(l); i < l; i++) {
  3191. ee[i] = available[i].fn;
  3192. }
  3193. return ee;
  3194. };
  3195. /**
  3196. * Emit an event to all registered event listeners.
  3197. *
  3198. * @param {String} event The name of the event.
  3199. * @returns {Boolean} Indication if we've emitted an event.
  3200. * @api public
  3201. */
  3202. EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
  3203. var evt = prefix ? prefix + event : event;
  3204. if (!this._events || !this._events[evt]) return false;
  3205. var listeners = this._events[evt]
  3206. , len = arguments.length
  3207. , args
  3208. , i;
  3209. if ('function' === typeof listeners.fn) {
  3210. if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
  3211. switch (len) {
  3212. case 1: return listeners.fn.call(listeners.context), true;
  3213. case 2: return listeners.fn.call(listeners.context, a1), true;
  3214. case 3: return listeners.fn.call(listeners.context, a1, a2), true;
  3215. case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
  3216. case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
  3217. case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
  3218. }
  3219. for (i = 1, args = new Array(len -1); i < len; i++) {
  3220. args[i - 1] = arguments[i];
  3221. }
  3222. listeners.fn.apply(listeners.context, args);
  3223. } else {
  3224. var length = listeners.length
  3225. , j;
  3226. for (i = 0; i < length; i++) {
  3227. if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
  3228. switch (len) {
  3229. case 1: listeners[i].fn.call(listeners[i].context); break;
  3230. case 2: listeners[i].fn.call(listeners[i].context, a1); break;
  3231. case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
  3232. default:
  3233. if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
  3234. args[j - 1] = arguments[j];
  3235. }
  3236. listeners[i].fn.apply(listeners[i].context, args);
  3237. }
  3238. }
  3239. }
  3240. return true;
  3241. };
  3242. /**
  3243. * Register a new EventListener for the given event.
  3244. *
  3245. * @param {String} event Name of the event.
  3246. * @param {Functon} fn Callback function.
  3247. * @param {Mixed} context The context of the function.
  3248. * @api public
  3249. */
  3250. EventEmitter.prototype.on = function on(event, fn, context) {
  3251. var listener = new EE(fn, context || this)
  3252. , evt = prefix ? prefix + event : event;
  3253. if (!this._events) this._events = prefix ? {} : Object.create(null);
  3254. if (!this._events[evt]) this._events[evt] = listener;
  3255. else {
  3256. if (!this._events[evt].fn) this._events[evt].push(listener);
  3257. else this._events[evt] = [
  3258. this._events[evt], listener
  3259. ];
  3260. }
  3261. return this;
  3262. };
  3263. /**
  3264. * Add an EventListener that's only called once.
  3265. *
  3266. * @param {String} event Name of the event.
  3267. * @param {Function} fn Callback function.
  3268. * @param {Mixed} context The context of the function.
  3269. * @api public
  3270. */
  3271. EventEmitter.prototype.once = function once(event, fn, context) {
  3272. var listener = new EE(fn, context || this, true)
  3273. , evt = prefix ? prefix + event : event;
  3274. if (!this._events) this._events = prefix ? {} : Object.create(null);
  3275. if (!this._events[evt]) this._events[evt] = listener;
  3276. else {
  3277. if (!this._events[evt].fn) this._events[evt].push(listener);
  3278. else this._events[evt] = [
  3279. this._events[evt], listener
  3280. ];
  3281. }
  3282. return this;
  3283. };
  3284. /**
  3285. * Remove event listeners.
  3286. *
  3287. * @param {String} event The event we want to remove.
  3288. * @param {Function} fn The listener that we need to find.
  3289. * @param {Mixed} context Only remove listeners matching this context.
  3290. * @param {Boolean} once Only remove once listeners.
  3291. * @api public
  3292. */
  3293. EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
  3294. var evt = prefix ? prefix + event : event;
  3295. if (!this._events || !this._events[evt]) return this;
  3296. var listeners = this._events[evt]
  3297. , events = [];
  3298. if (fn) {
  3299. if (listeners.fn) {
  3300. if (
  3301. listeners.fn !== fn
  3302. || (once && !listeners.once)
  3303. || (context && listeners.context !== context)
  3304. ) {
  3305. events.push(listeners);
  3306. }
  3307. } else {
  3308. for (var i = 0, length = listeners.length; i < length; i++) {
  3309. if (
  3310. listeners[i].fn !== fn
  3311. || (once && !listeners[i].once)
  3312. || (context && listeners[i].context !== context)
  3313. ) {
  3314. events.push(listeners[i]);
  3315. }
  3316. }
  3317. }
  3318. }
  3319. //
  3320. // Reset the array, or remove it completely if we have no more listeners.
  3321. //
  3322. if (events.length) {
  3323. this._events[evt] = events.length === 1 ? events[0] : events;
  3324. } else {
  3325. delete this._events[evt];
  3326. }
  3327. return this;
  3328. };
  3329. /**
  3330. * Remove all listeners or only the listeners for the specified event.
  3331. *
  3332. * @param {String} event The event want to remove all listeners for.
  3333. * @api public
  3334. */
  3335. EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
  3336. if (!this._events) return this;
  3337. if (event) delete this._events[prefix ? prefix + event : event];
  3338. else this._events = prefix ? {} : Object.create(null);
  3339. return this;
  3340. };
  3341. //
  3342. // Alias methods names because people roll like that.
  3343. //
  3344. EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
  3345. EventEmitter.prototype.addListener = EventEmitter.prototype.on;
  3346. //
  3347. // This function doesn't apply anymore.
  3348. //
  3349. EventEmitter.prototype.setMaxListeners = function setMaxListeners() {
  3350. return this;
  3351. };
  3352. //
  3353. // Expose the prefix.
  3354. //
  3355. EventEmitter.prefixed = prefix;
  3356. //
  3357. // Expose the module.
  3358. //
  3359. if ('undefined' !== typeof module) {
  3360. module.exports = EventEmitter;
  3361. }
  3362. },{}],11:[function(require,module,exports){
  3363. /* eslint-disable no-unused-vars */
  3364. 'use strict';
  3365. var hasOwnProperty = Object.prototype.hasOwnProperty;
  3366. var propIsEnumerable = Object.prototype.propertyIsEnumerable;
  3367. function toObject(val) {
  3368. if (val === null || val === undefined) {
  3369. throw new TypeError('Object.assign cannot be called with null or undefined');
  3370. }
  3371. return Object(val);
  3372. }
  3373. module.exports = Object.assign || function (target, source) {
  3374. var from;
  3375. var to = toObject(target);
  3376. var symbols;
  3377. for (var s = 1; s < arguments.length; s++) {
  3378. from = Object(arguments[s]);
  3379. for (var key in from) {
  3380. if (hasOwnProperty.call(from, key)) {
  3381. to[key] = from[key];
  3382. }
  3383. }
  3384. if (Object.getOwnPropertySymbols) {
  3385. symbols = Object.getOwnPropertySymbols(from);
  3386. for (var i = 0; i < symbols.length; i++) {
  3387. if (propIsEnumerable.call(from, symbols[i])) {
  3388. to[symbols[i]] = from[symbols[i]];
  3389. }
  3390. }
  3391. }
  3392. }
  3393. return to;
  3394. };
  3395. },{}],12:[function(require,module,exports){
  3396. (function (process){
  3397. /*!
  3398. * async
  3399. * https://github.com/caolan/async
  3400. *
  3401. * Copyright 2010-2014 Caolan McMahon
  3402. * Released under the MIT license
  3403. */
  3404. /*jshint onevar: false, indent:4 */
  3405. /*global setImmediate: false, setTimeout: false, console: false */
  3406. (function () {
  3407. var async = {};
  3408. // global on the server, window in the browser
  3409. var root, previous_async;
  3410. root = this;
  3411. if (root != null) {
  3412. previous_async = root.async;
  3413. }
  3414. async.noConflict = function () {
  3415. root.async = previous_async;
  3416. return async;
  3417. };
  3418. function only_once(fn) {
  3419. var called = false;
  3420. return function() {
  3421. if (called) throw new Error("Callback was already called.");
  3422. called = true;
  3423. fn.apply(root, arguments);
  3424. }
  3425. }
  3426. //// cross-browser compatiblity functions ////
  3427. var _toString = Object.prototype.toString;
  3428. var _isArray = Array.isArray || function (obj) {
  3429. return _toString.call(obj) === '[object Array]';
  3430. };
  3431. var _each = function (arr, iterator) {
  3432. for (var i = 0; i < arr.length; i += 1) {
  3433. iterator(arr[i], i, arr);
  3434. }
  3435. };
  3436. var _map = function (arr, iterator) {
  3437. if (arr.map) {
  3438. return arr.map(iterator);
  3439. }
  3440. var results = [];
  3441. _each(arr, function (x, i, a) {
  3442. results.push(iterator(x, i, a));
  3443. });
  3444. return results;
  3445. };
  3446. var _reduce = function (arr, iterator, memo) {
  3447. if (arr.reduce) {
  3448. return arr.reduce(iterator, memo);
  3449. }
  3450. _each(arr, function (x, i, a) {
  3451. memo = iterator(memo, x, i, a);
  3452. });
  3453. return memo;
  3454. };
  3455. var _keys = function (obj) {
  3456. if (Object.keys) {
  3457. return Object.keys(obj);
  3458. }
  3459. var keys = [];
  3460. for (var k in obj) {
  3461. if (obj.hasOwnProperty(k)) {
  3462. keys.push(k);
  3463. }
  3464. }
  3465. return keys;
  3466. };
  3467. //// exported async module functions ////
  3468. //// nextTick implementation with browser-compatible fallback ////
  3469. if (typeof process === 'undefined' || !(process.nextTick)) {
  3470. if (typeof setImmediate === 'function') {
  3471. async.nextTick = function (fn) {
  3472. // not a direct alias for IE10 compatibility
  3473. setImmediate(fn);
  3474. };
  3475. async.setImmediate = async.nextTick;
  3476. }
  3477. else {
  3478. async.nextTick = function (fn) {
  3479. setTimeout(fn, 0);
  3480. };
  3481. async.setImmediate = async.nextTick;
  3482. }
  3483. }
  3484. else {
  3485. async.nextTick = process.nextTick;
  3486. if (typeof setImmediate !== 'undefined') {
  3487. async.setImmediate = function (fn) {
  3488. // not a direct alias for IE10 compatibility
  3489. setImmediate(fn);
  3490. };
  3491. }
  3492. else {
  3493. async.setImmediate = async.nextTick;
  3494. }
  3495. }
  3496. async.each = function (arr, iterator, callback) {
  3497. callback = callback || function () {};
  3498. if (!arr.length) {
  3499. return callback();
  3500. }
  3501. var completed = 0;
  3502. _each(arr, function (x) {
  3503. iterator(x, only_once(done) );
  3504. });
  3505. function done(err) {
  3506. if (err) {
  3507. callback(err);
  3508. callback = function () {};
  3509. }
  3510. else {
  3511. completed += 1;
  3512. if (completed >= arr.length) {
  3513. callback();
  3514. }
  3515. }
  3516. }
  3517. };
  3518. async.forEach = async.each;
  3519. async.eachSeries = function (arr, iterator, callback) {
  3520. callback = callback || function () {};
  3521. if (!arr.length) {
  3522. return callback();
  3523. }
  3524. var completed = 0;
  3525. var iterate = function () {
  3526. iterator(arr[completed], function (err) {
  3527. if (err) {
  3528. callback(err);
  3529. callback = function () {};
  3530. }
  3531. else {
  3532. completed += 1;
  3533. if (completed >= arr.length) {
  3534. callback();
  3535. }
  3536. else {
  3537. iterate();
  3538. }
  3539. }
  3540. });
  3541. };
  3542. iterate();
  3543. };
  3544. async.forEachSeries = async.eachSeries;
  3545. async.eachLimit = function (arr, limit, iterator, callback) {
  3546. var fn = _eachLimit(limit);
  3547. fn.apply(null, [arr, iterator, callback]);
  3548. };
  3549. async.forEachLimit = async.eachLimit;
  3550. var _eachLimit = function (limit) {
  3551. return function (arr, iterator, callback) {
  3552. callback = callback || function () {};
  3553. if (!arr.length || limit <= 0) {
  3554. return callback();
  3555. }
  3556. var completed = 0;
  3557. var started = 0;
  3558. var running = 0;
  3559. (function replenish () {
  3560. if (completed >= arr.length) {
  3561. return callback();
  3562. }
  3563. while (running < limit && started < arr.length) {
  3564. started += 1;
  3565. running += 1;
  3566. iterator(arr[started - 1], function (err) {
  3567. if (err) {
  3568. callback(err);
  3569. callback = function () {};
  3570. }
  3571. else {
  3572. completed += 1;
  3573. running -= 1;
  3574. if (completed >= arr.length) {
  3575. callback();
  3576. }
  3577. else {
  3578. replenish();
  3579. }
  3580. }
  3581. });
  3582. }
  3583. })();
  3584. };
  3585. };
  3586. var doParallel = function (fn) {
  3587. return function () {
  3588. var args = Array.prototype.slice.call(arguments);
  3589. return fn.apply(null, [async.each].concat(args));
  3590. };
  3591. };
  3592. var doParallelLimit = function(limit, fn) {
  3593. return function () {
  3594. var args = Array.prototype.slice.call(arguments);
  3595. return fn.apply(null, [_eachLimit(limit)].concat(args));
  3596. };
  3597. };
  3598. var doSeries = function (fn) {
  3599. return function () {
  3600. var args = Array.prototype.slice.call(arguments);
  3601. return fn.apply(null, [async.eachSeries].concat(args));
  3602. };
  3603. };
  3604. var _asyncMap = function (eachfn, arr, iterator, callback) {
  3605. arr = _map(arr, function (x, i) {
  3606. return {index: i, value: x};
  3607. });
  3608. if (!callback) {
  3609. eachfn(arr, function (x, callback) {
  3610. iterator(x.value, function (err) {
  3611. callback(err);
  3612. });
  3613. });
  3614. } else {
  3615. var results = [];
  3616. eachfn(arr, function (x, callback) {
  3617. iterator(x.value, function (err, v) {
  3618. results[x.index] = v;
  3619. callback(err);
  3620. });
  3621. }, function (err) {
  3622. callback(err, results);
  3623. });
  3624. }
  3625. };
  3626. async.map = doParallel(_asyncMap);
  3627. async.mapSeries = doSeries(_asyncMap);
  3628. async.mapLimit = function (arr, limit, iterator, callback) {
  3629. return _mapLimit(limit)(arr, iterator, callback);
  3630. };
  3631. var _mapLimit = function(limit) {
  3632. return doParallelLimit(limit, _asyncMap);
  3633. };
  3634. // reduce only has a series version, as doing reduce in parallel won't
  3635. // work in many situations.
  3636. async.reduce = function (arr, memo, iterator, callback) {
  3637. async.eachSeries(arr, function (x, callback) {
  3638. iterator(memo, x, function (err, v) {
  3639. memo = v;
  3640. callback(err);
  3641. });
  3642. }, function (err) {
  3643. callback(err, memo);
  3644. });
  3645. };
  3646. // inject alias
  3647. async.inject = async.reduce;
  3648. // foldl alias
  3649. async.foldl = async.reduce;
  3650. async.reduceRight = function (arr, memo, iterator, callback) {
  3651. var reversed = _map(arr, function (x) {
  3652. return x;
  3653. }).reverse();
  3654. async.reduce(reversed, memo, iterator, callback);
  3655. };
  3656. // foldr alias
  3657. async.foldr = async.reduceRight;
  3658. var _filter = function (eachfn, arr, iterator, callback) {
  3659. var results = [];
  3660. arr = _map(arr, function (x, i) {
  3661. return {index: i, value: x};
  3662. });
  3663. eachfn(arr, function (x, callback) {
  3664. iterator(x.value, function (v) {
  3665. if (v) {
  3666. results.push(x);
  3667. }
  3668. callback();
  3669. });
  3670. }, function (err) {
  3671. callback(_map(results.sort(function (a, b) {
  3672. return a.index - b.index;
  3673. }), function (x) {
  3674. return x.value;
  3675. }));
  3676. });
  3677. };
  3678. async.filter = doParallel(_filter);
  3679. async.filterSeries = doSeries(_filter);
  3680. // select alias
  3681. async.select = async.filter;
  3682. async.selectSeries = async.filterSeries;
  3683. var _reject = function (eachfn, arr, iterator, callback) {
  3684. var results = [];
  3685. arr = _map(arr, function (x, i) {
  3686. return {index: i, value: x};
  3687. });
  3688. eachfn(arr, function (x, callback) {
  3689. iterator(x.value, function (v) {
  3690. if (!v) {
  3691. results.push(x);
  3692. }
  3693. callback();
  3694. });
  3695. }, function (err) {
  3696. callback(_map(results.sort(function (a, b) {
  3697. return a.index - b.index;
  3698. }), function (x) {
  3699. return x.value;
  3700. }));
  3701. });
  3702. };
  3703. async.reject = doParallel(_reject);
  3704. async.rejectSeries = doSeries(_reject);
  3705. var _detect = function (eachfn, arr, iterator, main_callback) {
  3706. eachfn(arr, function (x, callback) {
  3707. iterator(x, function (result) {
  3708. if (result) {
  3709. main_callback(x);
  3710. main_callback = function () {};
  3711. }
  3712. else {
  3713. callback();
  3714. }
  3715. });
  3716. }, function (err) {
  3717. main_callback();
  3718. });
  3719. };
  3720. async.detect = doParallel(_detect);
  3721. async.detectSeries = doSeries(_detect);
  3722. async.some = function (arr, iterator, main_callback) {
  3723. async.each(arr, function (x, callback) {
  3724. iterator(x, function (v) {
  3725. if (v) {
  3726. main_callback(true);
  3727. main_callback = function () {};
  3728. }
  3729. callback();
  3730. });
  3731. }, function (err) {
  3732. main_callback(false);
  3733. });
  3734. };
  3735. // any alias
  3736. async.any = async.some;
  3737. async.every = function (arr, iterator, main_callback) {
  3738. async.each(arr, function (x, callback) {
  3739. iterator(x, function (v) {
  3740. if (!v) {
  3741. main_callback(false);
  3742. main_callback = function () {};
  3743. }
  3744. callback();
  3745. });
  3746. }, function (err) {
  3747. main_callback(true);
  3748. });
  3749. };
  3750. // all alias
  3751. async.all = async.every;
  3752. async.sortBy = function (arr, iterator, callback) {
  3753. async.map(arr, function (x, callback) {
  3754. iterator(x, function (err, criteria) {
  3755. if (err) {
  3756. callback(err);
  3757. }
  3758. else {
  3759. callback(null, {value: x, criteria: criteria});
  3760. }
  3761. });
  3762. }, function (err, results) {
  3763. if (err) {
  3764. return callback(err);
  3765. }
  3766. else {
  3767. var fn = function (left, right) {
  3768. var a = left.criteria, b = right.criteria;
  3769. return a < b ? -1 : a > b ? 1 : 0;
  3770. };
  3771. callback(null, _map(results.sort(fn), function (x) {
  3772. return x.value;
  3773. }));
  3774. }
  3775. });
  3776. };
  3777. async.auto = function (tasks, callback) {
  3778. callback = callback || function () {};
  3779. var keys = _keys(tasks);
  3780. var remainingTasks = keys.length
  3781. if (!remainingTasks) {
  3782. return callback();
  3783. }
  3784. var results = {};
  3785. var listeners = [];
  3786. var addListener = function (fn) {
  3787. listeners.unshift(fn);
  3788. };
  3789. var removeListener = function (fn) {
  3790. for (var i = 0; i < listeners.length; i += 1) {
  3791. if (listeners[i] === fn) {
  3792. listeners.splice(i, 1);
  3793. return;
  3794. }
  3795. }
  3796. };
  3797. var taskComplete = function () {
  3798. remainingTasks--
  3799. _each(listeners.slice(0), function (fn) {
  3800. fn();
  3801. });
  3802. };
  3803. addListener(function () {
  3804. if (!remainingTasks) {
  3805. var theCallback = callback;
  3806. // prevent final callback from calling itself if it errors
  3807. callback = function () {};
  3808. theCallback(null, results);
  3809. }
  3810. });
  3811. _each(keys, function (k) {
  3812. var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];
  3813. var taskCallback = function (err) {
  3814. var args = Array.prototype.slice.call(arguments, 1);
  3815. if (args.length <= 1) {
  3816. args = args[0];
  3817. }
  3818. if (err) {
  3819. var safeResults = {};
  3820. _each(_keys(results), function(rkey) {
  3821. safeResults[rkey] = results[rkey];
  3822. });
  3823. safeResults[k] = args;
  3824. callback(err, safeResults);
  3825. // stop subsequent errors hitting callback multiple times
  3826. callback = function () {};
  3827. }
  3828. else {
  3829. results[k] = args;
  3830. async.setImmediate(taskComplete);
  3831. }
  3832. };
  3833. var requires = task.slice(0, Math.abs(task.length - 1)) || [];
  3834. var ready = function () {
  3835. return _reduce(requires, function (a, x) {
  3836. return (a && results.hasOwnProperty(x));
  3837. }, true) && !results.hasOwnProperty(k);
  3838. };
  3839. if (ready()) {
  3840. task[task.length - 1](taskCallback, results);
  3841. }
  3842. else {
  3843. var listener = function () {
  3844. if (ready()) {
  3845. removeListener(listener);
  3846. task[task.length - 1](taskCallback, results);
  3847. }
  3848. };
  3849. addListener(listener);
  3850. }
  3851. });
  3852. };
  3853. async.retry = function(times, task, callback) {
  3854. var DEFAULT_TIMES = 5;
  3855. var attempts = [];
  3856. // Use defaults if times not passed
  3857. if (typeof times === 'function') {
  3858. callback = task;
  3859. task = times;
  3860. times = DEFAULT_TIMES;
  3861. }
  3862. // Make sure times is a number
  3863. times = parseInt(times, 10) || DEFAULT_TIMES;
  3864. var wrappedTask = function(wrappedCallback, wrappedResults) {
  3865. var retryAttempt = function(task, finalAttempt) {
  3866. return function(seriesCallback) {
  3867. task(function(err, result){
  3868. seriesCallback(!err || finalAttempt, {err: err, result: result});
  3869. }, wrappedResults);
  3870. };
  3871. };
  3872. while (times) {
  3873. attempts.push(retryAttempt(task, !(times-=1)));
  3874. }
  3875. async.series(attempts, function(done, data){
  3876. data = data[data.length - 1];
  3877. (wrappedCallback || callback)(data.err, data.result);
  3878. });
  3879. }
  3880. // If a callback is passed, run this as a controll flow
  3881. return callback ? wrappedTask() : wrappedTask
  3882. };
  3883. async.waterfall = function (tasks, callback) {
  3884. callback = callback || function () {};
  3885. if (!_isArray(tasks)) {
  3886. var err = new Error('First argument to waterfall must be an array of functions');
  3887. return callback(err);
  3888. }
  3889. if (!tasks.length) {
  3890. return callback();
  3891. }
  3892. var wrapIterator = function (iterator) {
  3893. return function (err) {
  3894. if (err) {
  3895. callback.apply(null, arguments);
  3896. callback = function () {};
  3897. }
  3898. else {
  3899. var args = Array.prototype.slice.call(arguments, 1);
  3900. var next = iterator.next();
  3901. if (next) {
  3902. args.push(wrapIterator(next));
  3903. }
  3904. else {
  3905. args.push(callback);
  3906. }
  3907. async.setImmediate(function () {
  3908. iterator.apply(null, args);
  3909. });
  3910. }
  3911. };
  3912. };
  3913. wrapIterator(async.iterator(tasks))();
  3914. };
  3915. var _parallel = function(eachfn, tasks, callback) {
  3916. callback = callback || function () {};
  3917. if (_isArray(tasks)) {
  3918. eachfn.map(tasks, function (fn, callback) {
  3919. if (fn) {
  3920. fn(function (err) {
  3921. var args = Array.prototype.slice.call(arguments, 1);
  3922. if (args.length <= 1) {
  3923. args = args[0];
  3924. }
  3925. callback.call(null, err, args);
  3926. });
  3927. }
  3928. }, callback);
  3929. }
  3930. else {
  3931. var results = {};
  3932. eachfn.each(_keys(tasks), function (k, callback) {
  3933. tasks[k](function (err) {
  3934. var args = Array.prototype.slice.call(arguments, 1);
  3935. if (args.length <= 1) {
  3936. args = args[0];
  3937. }
  3938. results[k] = args;
  3939. callback(err);
  3940. });
  3941. }, function (err) {
  3942. callback(err, results);
  3943. });
  3944. }
  3945. };
  3946. async.parallel = function (tasks, callback) {
  3947. _parallel({ map: async.map, each: async.each }, tasks, callback);
  3948. };
  3949. async.parallelLimit = function(tasks, limit, callback) {
  3950. _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
  3951. };
  3952. async.series = function (tasks, callback) {
  3953. callback = callback || function () {};
  3954. if (_isArray(tasks)) {
  3955. async.mapSeries(tasks, function (fn, callback) {
  3956. if (fn) {
  3957. fn(function (err) {
  3958. var args = Array.prototype.slice.call(arguments, 1);
  3959. if (args.length <= 1) {
  3960. args = args[0];
  3961. }
  3962. callback.call(null, err, args);
  3963. });
  3964. }
  3965. }, callback);
  3966. }
  3967. else {
  3968. var results = {};
  3969. async.eachSeries(_keys(tasks), function (k, callback) {
  3970. tasks[k](function (err) {
  3971. var args = Array.prototype.slice.call(arguments, 1);
  3972. if (args.length <= 1) {
  3973. args = args[0];
  3974. }
  3975. results[k] = args;
  3976. callback(err);
  3977. });
  3978. }, function (err) {
  3979. callback(err, results);
  3980. });
  3981. }
  3982. };
  3983. async.iterator = function (tasks) {
  3984. var makeCallback = function (index) {
  3985. var fn = function () {
  3986. if (tasks.length) {
  3987. tasks[index].apply(null, arguments);
  3988. }
  3989. return fn.next();
  3990. };
  3991. fn.next = function () {
  3992. return (index < tasks.length - 1) ? makeCallback(index + 1): null;
  3993. };
  3994. return fn;
  3995. };
  3996. return makeCallback(0);
  3997. };
  3998. async.apply = function (fn) {
  3999. var args = Array.prototype.slice.call(arguments, 1);
  4000. return function () {
  4001. return fn.apply(
  4002. null, args.concat(Array.prototype.slice.call(arguments))
  4003. );
  4004. };
  4005. };
  4006. var _concat = function (eachfn, arr, fn, callback) {
  4007. var r = [];
  4008. eachfn(arr, function (x, cb) {
  4009. fn(x, function (err, y) {
  4010. r = r.concat(y || []);
  4011. cb(err);
  4012. });
  4013. }, function (err) {
  4014. callback(err, r);
  4015. });
  4016. };
  4017. async.concat = doParallel(_concat);
  4018. async.concatSeries = doSeries(_concat);
  4019. async.whilst = function (test, iterator, callback) {
  4020. if (test()) {
  4021. iterator(function (err) {
  4022. if (err) {
  4023. return callback(err);
  4024. }
  4025. async.whilst(test, iterator, callback);
  4026. });
  4027. }
  4028. else {
  4029. callback();
  4030. }
  4031. };
  4032. async.doWhilst = function (iterator, test, callback) {
  4033. iterator(function (err) {
  4034. if (err) {
  4035. return callback(err);
  4036. }
  4037. var args = Array.prototype.slice.call(arguments, 1);
  4038. if (test.apply(null, args)) {
  4039. async.doWhilst(iterator, test, callback);
  4040. }
  4041. else {
  4042. callback();
  4043. }
  4044. });
  4045. };
  4046. async.until = function (test, iterator, callback) {
  4047. if (!test()) {
  4048. iterator(function (err) {
  4049. if (err) {
  4050. return callback(err);
  4051. }
  4052. async.until(test, iterator, callback);
  4053. });
  4054. }
  4055. else {
  4056. callback();
  4057. }
  4058. };
  4059. async.doUntil = function (iterator, test, callback) {
  4060. iterator(function (err) {
  4061. if (err) {
  4062. return callback(err);
  4063. }
  4064. var args = Array.prototype.slice.call(arguments, 1);
  4065. if (!test.apply(null, args)) {
  4066. async.doUntil(iterator, test, callback);
  4067. }
  4068. else {
  4069. callback();
  4070. }
  4071. });
  4072. };
  4073. async.queue = function (worker, concurrency) {
  4074. if (concurrency === undefined) {
  4075. concurrency = 1;
  4076. }
  4077. function _insert(q, data, pos, callback) {
  4078. if (!q.started){
  4079. q.started = true;
  4080. }
  4081. if (!_isArray(data)) {
  4082. data = [data];
  4083. }
  4084. if(data.length == 0) {
  4085. // call drain immediately if there are no tasks
  4086. return async.setImmediate(function() {
  4087. if (q.drain) {
  4088. q.drain();
  4089. }
  4090. });
  4091. }
  4092. _each(data, function(task) {
  4093. var item = {
  4094. data: task,
  4095. callback: typeof callback === 'function' ? callback : null
  4096. };
  4097. if (pos) {
  4098. q.tasks.unshift(item);
  4099. } else {
  4100. q.tasks.push(item);
  4101. }
  4102. if (q.saturated && q.tasks.length === q.concurrency) {
  4103. q.saturated();
  4104. }
  4105. async.setImmediate(q.process);
  4106. });
  4107. }
  4108. var workers = 0;
  4109. var q = {
  4110. tasks: [],
  4111. concurrency: concurrency,
  4112. saturated: null,
  4113. empty: null,
  4114. drain: null,
  4115. started: false,
  4116. paused: false,
  4117. push: function (data, callback) {
  4118. _insert(q, data, false, callback);
  4119. },
  4120. kill: function () {
  4121. q.drain = null;
  4122. q.tasks = [];
  4123. },
  4124. unshift: function (data, callback) {
  4125. _insert(q, data, true, callback);
  4126. },
  4127. process: function () {
  4128. if (!q.paused && workers < q.concurrency && q.tasks.length) {
  4129. var task = q.tasks.shift();
  4130. if (q.empty && q.tasks.length === 0) {
  4131. q.empty();
  4132. }
  4133. workers += 1;
  4134. var next = function () {
  4135. workers -= 1;
  4136. if (task.callback) {
  4137. task.callback.apply(task, arguments);
  4138. }
  4139. if (q.drain && q.tasks.length + workers === 0) {
  4140. q.drain();
  4141. }
  4142. q.process();
  4143. };
  4144. var cb = only_once(next);
  4145. worker(task.data, cb);
  4146. }
  4147. },
  4148. length: function () {
  4149. return q.tasks.length;
  4150. },
  4151. running: function () {
  4152. return workers;
  4153. },
  4154. idle: function() {
  4155. return q.tasks.length + workers === 0;
  4156. },
  4157. pause: function () {
  4158. if (q.paused === true) { return; }
  4159. q.paused = true;
  4160. },
  4161. resume: function () {
  4162. if (q.paused === false) { return; }
  4163. q.paused = false;
  4164. // Need to call q.process once per concurrent
  4165. // worker to preserve full concurrency after pause
  4166. for (var w = 1; w <= q.concurrency; w++) {
  4167. async.setImmediate(q.process);
  4168. }
  4169. }
  4170. };
  4171. return q;
  4172. };
  4173. async.priorityQueue = function (worker, concurrency) {
  4174. function _compareTasks(a, b){
  4175. return a.priority - b.priority;
  4176. };
  4177. function _binarySearch(sequence, item, compare) {
  4178. var beg = -1,
  4179. end = sequence.length - 1;
  4180. while (beg < end) {
  4181. var mid = beg + ((end - beg + 1) >>> 1);
  4182. if (compare(item, sequence[mid]) >= 0) {
  4183. beg = mid;
  4184. } else {
  4185. end = mid - 1;
  4186. }
  4187. }
  4188. return beg;
  4189. }
  4190. function _insert(q, data, priority, callback) {
  4191. if (!q.started){
  4192. q.started = true;
  4193. }
  4194. if (!_isArray(data)) {
  4195. data = [data];
  4196. }
  4197. if(data.length == 0) {
  4198. // call drain immediately if there are no tasks
  4199. return async.setImmediate(function() {
  4200. if (q.drain) {
  4201. q.drain();
  4202. }
  4203. });
  4204. }
  4205. _each(data, function(task) {
  4206. var item = {
  4207. data: task,
  4208. priority: priority,
  4209. callback: typeof callback === 'function' ? callback : null
  4210. };
  4211. q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
  4212. if (q.saturated && q.tasks.length === q.concurrency) {
  4213. q.saturated();
  4214. }
  4215. async.setImmediate(q.process);
  4216. });
  4217. }
  4218. // Start with a normal queue
  4219. var q = async.queue(worker, concurrency);
  4220. // Override push to accept second parameter representing priority
  4221. q.push = function (data, priority, callback) {
  4222. _insert(q, data, priority, callback);
  4223. };
  4224. // Remove unshift function
  4225. delete q.unshift;
  4226. return q;
  4227. };
  4228. async.cargo = function (worker, payload) {
  4229. var working = false,
  4230. tasks = [];
  4231. var cargo = {
  4232. tasks: tasks,
  4233. payload: payload,
  4234. saturated: null,
  4235. empty: null,
  4236. drain: null,
  4237. drained: true,
  4238. push: function (data, callback) {
  4239. if (!_isArray(data)) {
  4240. data = [data];
  4241. }
  4242. _each(data, function(task) {
  4243. tasks.push({
  4244. data: task,
  4245. callback: typeof callback === 'function' ? callback : null
  4246. });
  4247. cargo.drained = false;
  4248. if (cargo.saturated && tasks.length === payload) {
  4249. cargo.saturated();
  4250. }
  4251. });
  4252. async.setImmediate(cargo.process);
  4253. },
  4254. process: function process() {
  4255. if (working) return;
  4256. if (tasks.length === 0) {
  4257. if(cargo.drain && !cargo.drained) cargo.drain();
  4258. cargo.drained = true;
  4259. return;
  4260. }
  4261. var ts = typeof payload === 'number'
  4262. ? tasks.splice(0, payload)
  4263. : tasks.splice(0, tasks.length);
  4264. var ds = _map(ts, function (task) {
  4265. return task.data;
  4266. });
  4267. if(cargo.empty) cargo.empty();
  4268. working = true;
  4269. worker(ds, function () {
  4270. working = false;
  4271. var args = arguments;
  4272. _each(ts, function (data) {
  4273. if (data.callback) {
  4274. data.callback.apply(null, args);
  4275. }
  4276. });
  4277. process();
  4278. });
  4279. },
  4280. length: function () {
  4281. return tasks.length;
  4282. },
  4283. running: function () {
  4284. return working;
  4285. }
  4286. };
  4287. return cargo;
  4288. };
  4289. var _console_fn = function (name) {
  4290. return function (fn) {
  4291. var args = Array.prototype.slice.call(arguments, 1);
  4292. fn.apply(null, args.concat([function (err) {
  4293. var args = Array.prototype.slice.call(arguments, 1);
  4294. if (typeof console !== 'undefined') {
  4295. if (err) {
  4296. if (console.error) {
  4297. console.error(err);
  4298. }
  4299. }
  4300. else if (console[name]) {
  4301. _each(args, function (x) {
  4302. console[name](x);
  4303. });
  4304. }
  4305. }
  4306. }]));
  4307. };
  4308. };
  4309. async.log = _console_fn('log');
  4310. async.dir = _console_fn('dir');
  4311. /*async.info = _console_fn('info');
  4312. async.warn = _console_fn('warn');
  4313. async.error = _console_fn('error');*/
  4314. async.memoize = function (fn, hasher) {
  4315. var memo = {};
  4316. var queues = {};
  4317. hasher = hasher || function (x) {
  4318. return x;
  4319. };
  4320. var memoized = function () {
  4321. var args = Array.prototype.slice.call(arguments);
  4322. var callback = args.pop();
  4323. var key = hasher.apply(null, args);
  4324. if (key in memo) {
  4325. async.nextTick(function () {
  4326. callback.apply(null, memo[key]);
  4327. });
  4328. }
  4329. else if (key in queues) {
  4330. queues[key].push(callback);
  4331. }
  4332. else {
  4333. queues[key] = [callback];
  4334. fn.apply(null, args.concat([function () {
  4335. memo[key] = arguments;
  4336. var q = queues[key];
  4337. delete queues[key];
  4338. for (var i = 0, l = q.length; i < l; i++) {
  4339. q[i].apply(null, arguments);
  4340. }
  4341. }]));
  4342. }
  4343. };
  4344. memoized.memo = memo;
  4345. memoized.unmemoized = fn;
  4346. return memoized;
  4347. };
  4348. async.unmemoize = function (fn) {
  4349. return function () {
  4350. return (fn.unmemoized || fn).apply(null, arguments);
  4351. };
  4352. };
  4353. async.times = function (count, iterator, callback) {
  4354. var counter = [];
  4355. for (var i = 0; i < count; i++) {
  4356. counter.push(i);
  4357. }
  4358. return async.map(counter, iterator, callback);
  4359. };
  4360. async.timesSeries = function (count, iterator, callback) {
  4361. var counter = [];
  4362. for (var i = 0; i < count; i++) {
  4363. counter.push(i);
  4364. }
  4365. return async.mapSeries(counter, iterator, callback);
  4366. };
  4367. async.seq = function (/* functions... */) {
  4368. var fns = arguments;
  4369. return function () {
  4370. var that = this;
  4371. var args = Array.prototype.slice.call(arguments);
  4372. var callback = args.pop();
  4373. async.reduce(fns, args, function (newargs, fn, cb) {
  4374. fn.apply(that, newargs.concat([function () {
  4375. var err = arguments[0];
  4376. var nextargs = Array.prototype.slice.call(arguments, 1);
  4377. cb(err, nextargs);
  4378. }]))
  4379. },
  4380. function (err, results) {
  4381. callback.apply(that, [err].concat(results));
  4382. });
  4383. };
  4384. };
  4385. async.compose = function (/* functions... */) {
  4386. return async.seq.apply(null, Array.prototype.reverse.call(arguments));
  4387. };
  4388. var _applyEach = function (eachfn, fns /*args...*/) {
  4389. var go = function () {
  4390. var that = this;
  4391. var args = Array.prototype.slice.call(arguments);
  4392. var callback = args.pop();
  4393. return eachfn(fns, function (fn, cb) {
  4394. fn.apply(that, args.concat([cb]));
  4395. },
  4396. callback);
  4397. };
  4398. if (arguments.length > 2) {
  4399. var args = Array.prototype.slice.call(arguments, 2);
  4400. return go.apply(this, args);
  4401. }
  4402. else {
  4403. return go;
  4404. }
  4405. };
  4406. async.applyEach = doParallel(_applyEach);
  4407. async.applyEachSeries = doSeries(_applyEach);
  4408. async.forever = function (fn, callback) {
  4409. function next(err) {
  4410. if (err) {
  4411. if (callback) {
  4412. return callback(err);
  4413. }
  4414. throw err;
  4415. }
  4416. fn(next);
  4417. }
  4418. next();
  4419. };
  4420. // Node.js
  4421. if (typeof module !== 'undefined' && module.exports) {
  4422. module.exports = async;
  4423. }
  4424. // AMD / RequireJS
  4425. else if (typeof define !== 'undefined' && define.amd) {
  4426. define([], function () {
  4427. return async;
  4428. });
  4429. }
  4430. // included directly via <script> tag
  4431. else {
  4432. root.async = async;
  4433. }
  4434. }());
  4435. }).call(this,require('_process'))
  4436. },{"_process":3}],13:[function(require,module,exports){
  4437. var async = require('async'),
  4438. urlParser = require('url'),
  4439. Resource = require('./Resource'),
  4440. EventEmitter = require('eventemitter3');
  4441. /**
  4442. * Manages the state and loading of multiple resources to load.
  4443. *
  4444. * @class
  4445. * @param [baseUrl=''] {string} The base url for all resources loaded by this loader.
  4446. * @param [concurrency=10] {number} The number of resources to load concurrently.
  4447. */
  4448. function Loader(baseUrl, concurrency) {
  4449. EventEmitter.call(this);
  4450. concurrency = concurrency || 10;
  4451. /**
  4452. * The base url for all resources loaded by this loader.
  4453. *
  4454. * @member {string}
  4455. */
  4456. this.baseUrl = baseUrl || '';
  4457. /**
  4458. * The progress percent of the loader going through the queue.
  4459. *
  4460. * @member {number}
  4461. */
  4462. this.progress = 0;
  4463. /**
  4464. * Loading state of the loader, true if it is currently loading resources.
  4465. *
  4466. * @member {boolean}
  4467. */
  4468. this.loading = false;
  4469. /**
  4470. * The percentage of total progress that a single resource represents.
  4471. *
  4472. * @member {number}
  4473. */
  4474. this._progressChunk = 0;
  4475. /**
  4476. * The middleware to run before loading each resource.
  4477. *
  4478. * @member {function[]}
  4479. */
  4480. this._beforeMiddleware = [];
  4481. /**
  4482. * The middleware to run after loading each resource.
  4483. *
  4484. * @member {function[]}
  4485. */
  4486. this._afterMiddleware = [];
  4487. /**
  4488. * The `_loadResource` function bound with this object context.
  4489. *
  4490. * @private
  4491. * @member {function}
  4492. */
  4493. this._boundLoadResource = this._loadResource.bind(this);
  4494. /**
  4495. * The `_onLoad` function bound with this object context.
  4496. *
  4497. * @private
  4498. * @member {function}
  4499. */
  4500. this._boundOnLoad = this._onLoad.bind(this);
  4501. /**
  4502. * The resource buffer that fills until `load` is called to start loading resources.
  4503. *
  4504. * @private
  4505. * @member {Resource[]}
  4506. */
  4507. this._buffer = [];
  4508. /**
  4509. * Used to track load completion.
  4510. *
  4511. * @private
  4512. * @member {number}
  4513. */
  4514. this._numToLoad = 0;
  4515. /**
  4516. * The resources waiting to be loaded.
  4517. *
  4518. * @private
  4519. * @member {Resource[]}
  4520. */
  4521. this._queue = async.queue(this._boundLoadResource, concurrency);
  4522. /**
  4523. * All the resources for this loader keyed by name.
  4524. *
  4525. * @member {object<string, Resource>}
  4526. */
  4527. this.resources = {};
  4528. /**
  4529. * Emitted once per loaded or errored resource.
  4530. *
  4531. * @event progress
  4532. * @memberof Loader#
  4533. */
  4534. /**
  4535. * Emitted once per errored resource.
  4536. *
  4537. * @event error
  4538. * @memberof Loader#
  4539. */
  4540. /**
  4541. * Emitted once per loaded resource.
  4542. *
  4543. * @event load
  4544. * @memberof Loader#
  4545. */
  4546. /**
  4547. * Emitted when the loader begins to process the queue.
  4548. *
  4549. * @event start
  4550. * @memberof Loader#
  4551. */
  4552. /**
  4553. * Emitted when the queued resources all load.
  4554. *
  4555. * @event complete
  4556. * @memberof Loader#
  4557. */
  4558. }
  4559. Loader.prototype = Object.create(EventEmitter.prototype);
  4560. Loader.prototype.constructor = Loader;
  4561. module.exports = Loader;
  4562. /**
  4563. * Adds a resource (or multiple resources) to the loader queue.
  4564. *
  4565. * This function can take a wide variety of different parameters. The only thing that is always
  4566. * required the url to load. All the following will work:
  4567. *
  4568. * ```js
  4569. * loader
  4570. * // normal param syntax
  4571. * .add('key', 'http://...', function () {})
  4572. * .add('http://...', function () {})
  4573. * .add('http://...')
  4574. *
  4575. * // object syntax
  4576. * .add({
  4577. * name: 'key2',
  4578. * url: 'http://...'
  4579. * }, function () {})
  4580. * .add({
  4581. * url: 'http://...'
  4582. * }, function () {})
  4583. * .add({
  4584. * name: 'key3',
  4585. * url: 'http://...'
  4586. * onComplete: function () {}
  4587. * })
  4588. * .add({
  4589. * url: 'https://...',
  4590. * onComplete: function () {},
  4591. * crossOrigin: true
  4592. * })
  4593. *
  4594. * // you can also pass an array of objects or urls or both
  4595. * .add([
  4596. * { name: 'key4', url: 'http://...', onComplete: function () {} },
  4597. * { url: 'http://...', onComplete: function () {} },
  4598. * 'http://...'
  4599. * ]);
  4600. * ```
  4601. *
  4602. * @alias enqueue
  4603. * @param [name] {string} The name of the resource to load, if not passed the url is used.
  4604. * @param url {string} The url for this resource, relative to the baseUrl of this loader.
  4605. * @param [options] {object} The options for the load.
  4606. * @param [options.crossOrigin] {boolean} Is this request cross-origin? Default is to determine automatically.
  4607. * @param [options.loadType=Resource.LOAD_TYPE.XHR] {Resource.XHR_LOAD_TYPE} How should this resource be loaded?
  4608. * @param [options.xhrType=Resource.XHR_RESPONSE_TYPE.DEFAULT] {Resource.XHR_RESPONSE_TYPE} How should the data being
  4609. * loaded be interpreted when using XHR?
  4610. * @param [callback] {function} Function to call when this specific resource completes loading.
  4611. * @return {Loader}
  4612. */
  4613. Loader.prototype.add = Loader.prototype.enqueue = function (name, url, options, cb) {
  4614. // special case of an array of objects or urls
  4615. if (Array.isArray(name)) {
  4616. for (var i = 0; i < name.length; ++i) {
  4617. this.add(name[i]);
  4618. }
  4619. return this;
  4620. }
  4621. // if an object is passed instead of params
  4622. if (typeof name === 'object') {
  4623. cb = url || name.callback || name.onComplete;
  4624. options = name;
  4625. url = name.url;
  4626. name = name.name || name.key || name.url;
  4627. }
  4628. // case where no name is passed shift all args over by one.
  4629. if (typeof url !== 'string') {
  4630. cb = options;
  4631. options = url;
  4632. url = name;
  4633. }
  4634. // now that we shifted make sure we have a proper url.
  4635. if (typeof url !== 'string') {
  4636. throw new Error('No url passed to add resource to loader.');
  4637. }
  4638. // options are optional so people might pass a function and no options
  4639. if (typeof options === 'function') {
  4640. cb = options;
  4641. options = null;
  4642. }
  4643. // check if resource already exists.
  4644. if (this.resources[name]) {
  4645. throw new Error('Resource with name "' + name + '" already exists.');
  4646. }
  4647. // add base url if this isn't an absolute url
  4648. url = this._handleBaseUrl(url);
  4649. // create the store the resource
  4650. this.resources[name] = new Resource(name, url, options);
  4651. if (typeof cb === 'function') {
  4652. this.resources[name].once('afterMiddleware', cb);
  4653. }
  4654. this._numToLoad++;
  4655. // if already loading add it to the worker queue
  4656. if (this._queue.started) {
  4657. this._queue.push(this.resources[name]);
  4658. this._progressChunk = (100 - this.progress) / (this._queue.length() + this._queue.running());
  4659. }
  4660. // otherwise buffer it to be added to the queue later
  4661. else {
  4662. this._buffer.push(this.resources[name]);
  4663. this._progressChunk = 100 / this._buffer.length;
  4664. }
  4665. return this;
  4666. };
  4667. Loader.prototype._handleBaseUrl = function (url) {
  4668. var parsedUrl = urlParser.parse(url);
  4669. // absolute url, just use it as is.
  4670. if (parsedUrl.protocol || parsedUrl.pathname.indexOf('//') === 0) {
  4671. return url;
  4672. }
  4673. // if baseUrl doesn't end in slash and url doesn't start with slash, then add a slash inbetween
  4674. if (
  4675. this.baseUrl.length &&
  4676. this.baseUrl.lastIndexOf('/') !== this.baseUrl.length - 1 &&
  4677. url.charAt(0) !== '/'
  4678. ) {
  4679. return this.baseUrl + '/' + url;
  4680. }
  4681. else {
  4682. return this.baseUrl + url;
  4683. }
  4684. };
  4685. /**
  4686. * Sets up a middleware function that will run *before* the
  4687. * resource is loaded.
  4688. *
  4689. * @alias pre
  4690. * @param middleware {function} The middleware function to register.
  4691. * @return {Loader}
  4692. */
  4693. Loader.prototype.before = Loader.prototype.pre = function (fn) {
  4694. this._beforeMiddleware.push(fn);
  4695. return this;
  4696. };
  4697. /**
  4698. * Sets up a middleware function that will run *after* the
  4699. * resource is loaded.
  4700. *
  4701. * @alias use
  4702. * @param middleware {function} The middleware function to register.
  4703. * @return {Loader}
  4704. */
  4705. Loader.prototype.after = Loader.prototype.use = function (fn) {
  4706. this._afterMiddleware.push(fn);
  4707. return this;
  4708. };
  4709. /**
  4710. * Resets the queue of the loader to prepare for a new load.
  4711. *
  4712. * @return {Loader}
  4713. */
  4714. Loader.prototype.reset = function () {
  4715. // this.baseUrl = baseUrl || '';
  4716. this.progress = 0;
  4717. this.loading = false;
  4718. this._progressChunk = 0;
  4719. // this._beforeMiddleware.length = 0;
  4720. // this._afterMiddleware.length = 0;
  4721. this._buffer.length = 0;
  4722. this._numToLoad = 0;
  4723. this._queue.kill();
  4724. this._queue.started = false;
  4725. this.resources = {};
  4726. };
  4727. /**
  4728. * Starts loading the queued resources.
  4729. *
  4730. * @fires start
  4731. * @param [callback] {function} Optional callback that will be bound to the `complete` event.
  4732. * @return {Loader}
  4733. */
  4734. Loader.prototype.load = function (cb) {
  4735. // register complete callback if they pass one
  4736. if (typeof cb === 'function') {
  4737. this.once('complete', cb);
  4738. }
  4739. // if the queue has already started we are done here
  4740. if (this._queue.started) {
  4741. return this;
  4742. }
  4743. // notify of start
  4744. this.emit('start', this);
  4745. // start the internal queue
  4746. for (var i = 0; i < this._buffer.length; ++i) {
  4747. this._queue.push(this._buffer[i]);
  4748. }
  4749. // empty the buffer
  4750. this._buffer.length = 0;
  4751. return this;
  4752. };
  4753. /**
  4754. * Loads a single resource.
  4755. *
  4756. * @fires progress
  4757. * @private
  4758. */
  4759. Loader.prototype._loadResource = function (resource, dequeue) {
  4760. var self = this;
  4761. resource._dequeue = dequeue;
  4762. this._runMiddleware(resource, this._beforeMiddleware, function () {
  4763. // resource.on('progress', self.emit.bind(self, 'progress'));
  4764. resource.load(self._boundOnLoad);
  4765. });
  4766. };
  4767. /**
  4768. * Called once each resource has loaded.
  4769. *
  4770. * @fires complete
  4771. * @private
  4772. */
  4773. Loader.prototype._onComplete = function () {
  4774. this.emit('complete', this, this.resources);
  4775. };
  4776. /**
  4777. * Called each time a resources is loaded.
  4778. *
  4779. * @fires progress
  4780. * @fires error
  4781. * @fires load
  4782. * @private
  4783. */
  4784. Loader.prototype._onLoad = function (resource) {
  4785. this.progress += this._progressChunk;
  4786. this.emit('progress', this, resource);
  4787. // run middleware, this *must* happen before dequeue so sub-assets get added properly
  4788. this._runMiddleware(resource, this._afterMiddleware, function () {
  4789. resource.emit('afterMiddleware', resource);
  4790. this._numToLoad--;
  4791. // do completion check
  4792. if (this._numToLoad === 0) {
  4793. this.progress = 100;
  4794. this._onComplete();
  4795. }
  4796. if (resource.error) {
  4797. this.emit('error', resource.error, this, resource);
  4798. }
  4799. else {
  4800. this.emit('load', this, resource);
  4801. }
  4802. });
  4803. // remove this resource from the async queue
  4804. resource._dequeue();
  4805. };
  4806. /**
  4807. * Run middleware functions on a resource.
  4808. *
  4809. * @private
  4810. */
  4811. Loader.prototype._runMiddleware = function (resource, fns, cb) {
  4812. var self = this;
  4813. async.eachSeries(fns, function (fn, next) {
  4814. fn.call(self, resource, next);
  4815. }, cb.bind(this, resource));
  4816. };
  4817. Loader.LOAD_TYPE = Resource.LOAD_TYPE;
  4818. Loader.XHR_READY_STATE = Resource.XHR_READY_STATE;
  4819. Loader.XHR_RESPONSE_TYPE = Resource.XHR_RESPONSE_TYPE;
  4820. },{"./Resource":14,"async":12,"eventemitter3":10,"url":8}],14:[function(require,module,exports){
  4821. var EventEmitter = require('eventemitter3'),
  4822. _url = require('url'),
  4823. // tests is CORS is supported in XHR, if not we need to use XDR
  4824. useXdr = !!(window.XDomainRequest && !('withCredentials' in (new XMLHttpRequest()))),
  4825. tempAnchor = null;
  4826. /**
  4827. * Manages the state and loading of a single resource represented by
  4828. * a single URL.
  4829. *
  4830. * @class
  4831. * @param name {string} The name of the resource to load.
  4832. * @param url {string|string[]} The url for this resource, for audio/video loads you can pass an array of sources.
  4833. * @param [options] {object} The options for the load.
  4834. * @param [options.crossOrigin] {string|boolean} Is this request cross-origin? Default is to determine automatically.
  4835. * @param [options.loadType=Resource.LOAD_TYPE.XHR] {Resource.LOAD_TYPE} How should this resource be loaded?
  4836. * @param [options.xhrType=Resource.XHR_RESPONSE_TYPE.DEFAULT] {Resource.XHR_RESPONSE_TYPE} How should the data being
  4837. * loaded be interpreted when using XHR?
  4838. * @param [options.metadata] {object} Extra info for middleware.
  4839. */
  4840. function Resource(name, url, options) {
  4841. EventEmitter.call(this);
  4842. options = options || {};
  4843. if (typeof name !== 'string' || typeof url !== 'string') {
  4844. throw new Error('Both name and url are required for constructing a resource.');
  4845. }
  4846. /**
  4847. * The name of this resource.
  4848. *
  4849. * @member {string}
  4850. * @readonly
  4851. */
  4852. this.name = name;
  4853. /**
  4854. * The url used to load this resource.
  4855. *
  4856. * @member {string}
  4857. * @readonly
  4858. */
  4859. this.url = url;
  4860. /**
  4861. * Stores whether or not this url is a data url.
  4862. *
  4863. * @member {boolean}
  4864. * @readonly
  4865. */
  4866. this.isDataUrl = this.url.indexOf('data:') === 0;
  4867. /**
  4868. * The data that was loaded by the resource.
  4869. *
  4870. * @member {any}
  4871. */
  4872. this.data = null;
  4873. /**
  4874. * Is this request cross-origin? If unset, determined automatically.
  4875. *
  4876. * @member {string}
  4877. */
  4878. this.crossOrigin = options.crossOrigin === true ? 'anonymous' : options.crossOrigin;
  4879. /**
  4880. * The method of loading to use for this resource.
  4881. *
  4882. * @member {Resource.LOAD_TYPE}
  4883. */
  4884. this.loadType = options.loadType || this._determineLoadType();
  4885. /**
  4886. * The type used to load the resource via XHR. If unset, determined automatically.
  4887. *
  4888. * @member {string}
  4889. */
  4890. this.xhrType = options.xhrType;
  4891. /**
  4892. * Extra info for middleware
  4893. *
  4894. * @member {object}
  4895. */
  4896. this.metadata = options.metadata || {};
  4897. /**
  4898. * The error that occurred while loading (if any).
  4899. *
  4900. * @member {Error}
  4901. * @readonly
  4902. */
  4903. this.error = null;
  4904. /**
  4905. * The XHR object that was used to load this resource. This is only set
  4906. * when `loadType` is `Resource.LOAD_TYPE.XHR`.
  4907. *
  4908. * @member {XMLHttpRequest}
  4909. */
  4910. this.xhr = null;
  4911. /**
  4912. * Describes if this resource was loaded as json. Only valid after the resource
  4913. * has completely loaded.
  4914. *
  4915. * @member {boolean}
  4916. */
  4917. this.isJson = false;
  4918. /**
  4919. * Describes if this resource was loaded as xml. Only valid after the resource
  4920. * has completely loaded.
  4921. *
  4922. * @member {boolean}
  4923. */
  4924. this.isXml = false;
  4925. /**
  4926. * Describes if this resource was loaded as an image tag. Only valid after the resource
  4927. * has completely loaded.
  4928. *
  4929. * @member {boolean}
  4930. */
  4931. this.isImage = false;
  4932. /**
  4933. * Describes if this resource was loaded as an audio tag. Only valid after the resource
  4934. * has completely loaded.
  4935. *
  4936. * @member {boolean}
  4937. */
  4938. this.isAudio = false;
  4939. /**
  4940. * Describes if this resource was loaded as a video tag. Only valid after the resource
  4941. * has completely loaded.
  4942. *
  4943. * @member {boolean}
  4944. */
  4945. this.isVideo = false;
  4946. /**
  4947. * The `dequeue` method that will be used a storage place for the async queue dequeue method
  4948. * used privately by the loader.
  4949. *
  4950. * @member {function}
  4951. * @private
  4952. */
  4953. this._dequeue = null;
  4954. /**
  4955. * The `complete` function bound to this resource's context.
  4956. *
  4957. * @member {function}
  4958. * @private
  4959. */
  4960. this._boundComplete = this.complete.bind(this);
  4961. /**
  4962. * The `_onError` function bound to this resource's context.
  4963. *
  4964. * @member {function}
  4965. * @private
  4966. */
  4967. this._boundOnError = this._onError.bind(this);
  4968. /**
  4969. * The `_onProgress` function bound to this resource's context.
  4970. *
  4971. * @member {function}
  4972. * @private
  4973. */
  4974. this._boundOnProgress = this._onProgress.bind(this);
  4975. // xhr callbacks
  4976. this._boundXhrOnError = this._xhrOnError.bind(this);
  4977. this._boundXhrOnAbort = this._xhrOnAbort.bind(this);
  4978. this._boundXhrOnLoad = this._xhrOnLoad.bind(this);
  4979. this._boundXdrOnTimeout = this._xdrOnTimeout.bind(this);
  4980. /**
  4981. * Emitted when the resource beings to load.
  4982. *
  4983. * @event start
  4984. * @memberof Resource#
  4985. */
  4986. /**
  4987. * Emitted each time progress of this resource load updates.
  4988. * Not all resources types and loader systems can support this event
  4989. * so sometimes it may not be available. If the resource
  4990. * is being loaded on a modern browser, using XHR, and the remote server
  4991. * properly sets Content-Length headers, then this will be available.
  4992. *
  4993. * @event progress
  4994. * @memberof Resource#
  4995. */
  4996. /**
  4997. * Emitted once this resource has loaded, if there was an error it will
  4998. * be in the `error` property.
  4999. *
  5000. * @event complete
  5001. * @memberof Resource#
  5002. */
  5003. }
  5004. Resource.prototype = Object.create(EventEmitter.prototype);
  5005. Resource.prototype.constructor = Resource;
  5006. module.exports = Resource;
  5007. /**
  5008. * Marks the resource as complete.
  5009. *
  5010. * @fires complete
  5011. */
  5012. Resource.prototype.complete = function () {
  5013. // TODO: Clean this up in a wrapper or something...gross....
  5014. if (this.data && this.data.removeEventListener) {
  5015. this.data.removeEventListener('error', this._boundOnError);
  5016. this.data.removeEventListener('load', this._boundComplete);
  5017. this.data.removeEventListener('progress', this._boundOnProgress);
  5018. this.data.removeEventListener('canplaythrough', this._boundComplete);
  5019. }
  5020. if (this.xhr) {
  5021. if (this.xhr.removeEventListener) {
  5022. this.xhr.removeEventListener('error', this._boundXhrOnError);
  5023. this.xhr.removeEventListener('abort', this._boundXhrOnAbort);
  5024. this.xhr.removeEventListener('progress', this._boundOnProgress);
  5025. this.xhr.removeEventListener('load', this._boundXhrOnLoad);
  5026. }
  5027. else {
  5028. this.xhr.onerror = null;
  5029. this.xhr.ontimeout = null;
  5030. this.xhr.onprogress = null;
  5031. this.xhr.onload = null;
  5032. }
  5033. }
  5034. this.emit('complete', this);
  5035. };
  5036. /**
  5037. * Kicks off loading of this resource.
  5038. *
  5039. * @fires start
  5040. * @param [callback] {function} Optional callback to call once the resource is loaded.
  5041. */
  5042. Resource.prototype.load = function (cb) {
  5043. this.emit('start', this);
  5044. // if a callback is set, listen for complete event
  5045. if (cb) {
  5046. this.once('complete', cb);
  5047. }
  5048. // if unset, determine the value
  5049. if (this.crossOrigin === false || typeof this.crossOrigin !== 'string') {
  5050. this.crossOrigin = this._determineCrossOrigin(this.url);
  5051. }
  5052. switch(this.loadType) {
  5053. case Resource.LOAD_TYPE.IMAGE:
  5054. this._loadImage();
  5055. break;
  5056. case Resource.LOAD_TYPE.AUDIO:
  5057. this._loadElement('audio');
  5058. break;
  5059. case Resource.LOAD_TYPE.VIDEO:
  5060. this._loadElement('video');
  5061. break;
  5062. case Resource.LOAD_TYPE.XHR:
  5063. /* falls through */
  5064. default:
  5065. if (useXdr && this.crossOrigin) {
  5066. this._loadXdr();
  5067. }
  5068. else {
  5069. this._loadXhr();
  5070. }
  5071. break;
  5072. }
  5073. };
  5074. /**
  5075. * Loads this resources using an Image object.
  5076. *
  5077. * @private
  5078. */
  5079. Resource.prototype._loadImage = function () {
  5080. this.data = new Image();
  5081. if (this.crossOrigin) {
  5082. this.data.crossOrigin = this.crossOrigin;
  5083. }
  5084. this.data.src = this.url;
  5085. this.isImage = true;
  5086. this.data.addEventListener('error', this._boundOnError, false);
  5087. this.data.addEventListener('load', this._boundComplete, false);
  5088. this.data.addEventListener('progress', this._boundOnProgress, false);
  5089. };
  5090. /**
  5091. * Loads this resources using an HTMLAudioElement or HTMLVideoElement.
  5092. *
  5093. * @private
  5094. */
  5095. Resource.prototype._loadElement = function (type) {
  5096. if (type === 'audio' && typeof Audio !== 'undefined') {
  5097. this.data = new Audio();
  5098. }
  5099. else {
  5100. this.data = document.createElement(type);
  5101. }
  5102. if (this.data === null) {
  5103. this.error = new Error('Unsupported element ' + type);
  5104. this.complete();
  5105. return;
  5106. }
  5107. // support for CocoonJS Canvas+ runtime, lacks document.createElement('source')
  5108. if (navigator.isCocoonJS) {
  5109. this.data.src = Array.isArray(this.url) ? this.url[0] : this.url;
  5110. }
  5111. else {
  5112. if (Array.isArray(this.url)) {
  5113. for (var i = 0; i < this.url.length; ++i) {
  5114. this.data.appendChild(this._createSource(type, this.url[i]));
  5115. }
  5116. }
  5117. else {
  5118. this.data.appendChild(this._createSource(type, this.url));
  5119. }
  5120. }
  5121. this['is' + type[0].toUpperCase() + type.substring(1)] = true;
  5122. this.data.addEventListener('error', this._boundOnError, false);
  5123. this.data.addEventListener('load', this._boundComplete, false);
  5124. this.data.addEventListener('progress', this._boundOnProgress, false);
  5125. this.data.addEventListener('canplaythrough', this._boundComplete, false);
  5126. this.data.load();
  5127. };
  5128. /**
  5129. * Loads this resources using an XMLHttpRequest.
  5130. *
  5131. * @private
  5132. */
  5133. Resource.prototype._loadXhr = function () {
  5134. // if unset, determine the value
  5135. if (typeof this.xhrType !== 'string') {
  5136. this.xhrType = this._determineXhrType();
  5137. }
  5138. var xhr = this.xhr = new XMLHttpRequest();
  5139. // set the request type and url
  5140. xhr.open('GET', this.url, true);
  5141. // load json as text and parse it ourselves. We do this because some browsers
  5142. // *cough* safari *cough* can't deal with it.
  5143. if (this.xhrType === Resource.XHR_RESPONSE_TYPE.JSON || this.xhrType === Resource.XHR_RESPONSE_TYPE.DOCUMENT) {
  5144. xhr.responseType = Resource.XHR_RESPONSE_TYPE.TEXT;
  5145. }
  5146. else {
  5147. xhr.responseType = this.xhrType;
  5148. }
  5149. xhr.addEventListener('error', this._boundXhrOnError, false);
  5150. xhr.addEventListener('abort', this._boundXhrOnAbort, false);
  5151. xhr.addEventListener('progress', this._boundOnProgress, false);
  5152. xhr.addEventListener('load', this._boundXhrOnLoad, false);
  5153. xhr.send();
  5154. };
  5155. /**
  5156. * Loads this resources using an XDomainRequest. This is here because we need to support IE9 (gross).
  5157. *
  5158. * @private
  5159. */
  5160. Resource.prototype._loadXdr = function () {
  5161. // if unset, determine the value
  5162. if (typeof this.xhrType !== 'string') {
  5163. this.xhrType = this._determineXhrType();
  5164. }
  5165. var xdr = this.xhr = new XDomainRequest();
  5166. // XDomainRequest has a few quirks. Occasionally it will abort requests
  5167. // A way to avoid this is to make sure ALL callbacks are set even if not used
  5168. // More info here: http://stackoverflow.com/questions/15786966/xdomainrequest-aborts-post-on-ie-9
  5169. xdr.timeout = 5000;
  5170. xdr.onerror = this._boundXhrOnError;
  5171. xdr.ontimeout = this._boundXdrOnTimeout;
  5172. xdr.onprogress = this._boundOnProgress;
  5173. xdr.onload = this._boundXhrOnLoad;
  5174. xdr.open('GET', this.url, true);
  5175. // Note: The xdr.send() call is wrapped in a timeout to prevent an issue with the interface where some requests are lost
  5176. // if multiple XDomainRequests are being sent at the same time.
  5177. // Some info here: https://github.com/photonstorm/phaser/issues/1248
  5178. setTimeout(function () {
  5179. xdr.send();
  5180. }, 0);
  5181. };
  5182. /**
  5183. * Creates a source used in loading via an element.
  5184. *
  5185. * @param type {string} The element type (video or audio).
  5186. * @param url {string} The source URL to load from.
  5187. * @param [mime] {string} The mime type of the video
  5188. * @private
  5189. */
  5190. Resource.prototype._createSource = function (type, url, mime) {
  5191. if (!mime) {
  5192. mime = type + '/' + url.substr(url.lastIndexOf('.') + 1);
  5193. }
  5194. var source = document.createElement('source');
  5195. source.src = url;
  5196. source.type = mime;
  5197. return source;
  5198. };
  5199. /**
  5200. * Called if a load errors out.
  5201. *
  5202. * @param event {Event} The error event from the element that emits it.
  5203. * @private
  5204. */
  5205. Resource.prototype._onError = function (event) {
  5206. this.error = new Error('Failed to load element using ' + event.target.nodeName);
  5207. this.complete();
  5208. };
  5209. /**
  5210. * Called if a load progress event fires for xhr/xdr.
  5211. *
  5212. * @fires progress
  5213. * @param event {XMLHttpRequestProgressEvent|Event}
  5214. * @private
  5215. */
  5216. Resource.prototype._onProgress = function (event) {
  5217. if (event && event.lengthComputable) {
  5218. this.emit('progress', this, event.loaded / event.total);
  5219. }
  5220. };
  5221. /**
  5222. * Called if an error event fires for xhr/xdr.
  5223. *
  5224. * @param event {XMLHttpRequestErrorEvent|Event}
  5225. * @private
  5226. */
  5227. Resource.prototype._xhrOnError = function () {
  5228. this.error = new Error(
  5229. reqType(this.xhr) + ' Request failed. ' +
  5230. 'Status: ' + this.xhr.status + ', text: "' + this.xhr.statusText + '"'
  5231. );
  5232. this.complete();
  5233. };
  5234. /**
  5235. * Called if an abort event fires for xhr.
  5236. *
  5237. * @param event {XMLHttpRequestAbortEvent}
  5238. * @private
  5239. */
  5240. Resource.prototype._xhrOnAbort = function () {
  5241. this.error = new Error(reqType(this.xhr) + ' Request was aborted by the user.');
  5242. this.complete();
  5243. };
  5244. /**
  5245. * Called if a timeout event fires for xdr.
  5246. *
  5247. * @param event {Event}
  5248. * @private
  5249. */
  5250. Resource.prototype._xdrOnTimeout = function () {
  5251. this.error = new Error(reqType(this.xhr) + ' Request timed out.');
  5252. this.complete();
  5253. };
  5254. /**
  5255. * Called when data successfully loads from an xhr/xdr request.
  5256. *
  5257. * @param event {XMLHttpRequestLoadEvent|Event}
  5258. * @private
  5259. */
  5260. Resource.prototype._xhrOnLoad = function () {
  5261. var xhr = this.xhr,
  5262. status = xhr.status !== undefined ? xhr.status : 200; //XDR has no `.status`, assume 200.
  5263. // status can be 0 when using the file:// protocol, also check if a response was found
  5264. if (status === 200 || status === 204 || (status === 0 && xhr.responseText.length > 0)) {
  5265. // if text, just return it
  5266. if (this.xhrType === Resource.XHR_RESPONSE_TYPE.TEXT) {
  5267. this.data = xhr.responseText;
  5268. }
  5269. // if json, parse into json object
  5270. else if (this.xhrType === Resource.XHR_RESPONSE_TYPE.JSON) {
  5271. try {
  5272. this.data = JSON.parse(xhr.responseText);
  5273. this.isJson = true;
  5274. } catch(e) {
  5275. this.error = new Error('Error trying to parse loaded json:', e);
  5276. }
  5277. }
  5278. // if xml, parse into an xml document or div element
  5279. else if (this.xhrType === Resource.XHR_RESPONSE_TYPE.DOCUMENT) {
  5280. try {
  5281. if (window.DOMParser) {
  5282. var domparser = new DOMParser();
  5283. this.data = domparser.parseFromString(xhr.responseText, 'text/xml');
  5284. }
  5285. else {
  5286. var div = document.createElement('div');
  5287. div.innerHTML = xhr.responseText;
  5288. this.data = div;
  5289. }
  5290. this.isXml = true;
  5291. } catch (e) {
  5292. this.error = new Error('Error trying to parse loaded xml:', e);
  5293. }
  5294. }
  5295. // other types just return the response
  5296. else {
  5297. this.data = xhr.response || xhr.responseText;
  5298. }
  5299. }
  5300. else {
  5301. this.error = new Error('[' + xhr.status + ']' + xhr.statusText + ':' + xhr.responseURL);
  5302. }
  5303. this.complete();
  5304. };
  5305. function reqType(xhr) {
  5306. return xhr.toString().replace('object ', '');
  5307. }
  5308. /**
  5309. * Sets the `crossOrigin` property for this resource based on if the url
  5310. * for this resource is cross-origin. If crossOrigin was manually set, this
  5311. * function does nothing.
  5312. *
  5313. * @private
  5314. * @param url {string} The url to test.
  5315. * @param [location=window.location] {object} The location object to test against.
  5316. * @return {string} The crossOrigin value to use (or empty string for none).
  5317. */
  5318. Resource.prototype._determineCrossOrigin = function (url, loc) {
  5319. // data: and javascript: urls are considered same-origin
  5320. if (url.indexOf('data:') === 0) {
  5321. return '';
  5322. }
  5323. // default is window.location
  5324. loc = loc || window.location;
  5325. if (!tempAnchor) {
  5326. tempAnchor = document.createElement('a');
  5327. }
  5328. // let the browser determine the full href for the url of this resource and then
  5329. // parse with the node url lib, we can't use the properties of the anchor element
  5330. // because they don't work in IE9 :(
  5331. tempAnchor.href = url;
  5332. url = _url.parse(tempAnchor.href);
  5333. var samePort = (!url.port && loc.port === '') || (url.port === loc.port);
  5334. // if cross origin
  5335. if (url.hostname !== loc.hostname || !samePort || url.protocol !== loc.protocol) {
  5336. return 'anonymous';
  5337. }
  5338. return '';
  5339. };
  5340. /**
  5341. * Determines the responseType of an XHR request based on the extension of the
  5342. * resource being loaded.
  5343. *
  5344. * @private
  5345. * @return {Resource.XHR_RESPONSE_TYPE} The responseType to use.
  5346. */
  5347. Resource.prototype._determineXhrType = function () {
  5348. return Resource._xhrTypeMap[this._getExtension()] || Resource.XHR_RESPONSE_TYPE.TEXT;
  5349. };
  5350. Resource.prototype._determineLoadType = function () {
  5351. return Resource._loadTypeMap[this._getExtension()] || Resource.LOAD_TYPE.XHR;
  5352. };
  5353. Resource.prototype._getExtension = function () {
  5354. var url = this.url,
  5355. ext;
  5356. if (this.isDataUrl) {
  5357. var slashIndex = url.indexOf('/');
  5358. ext = url.substring(slashIndex + 1, url.indexOf(';', slashIndex));
  5359. }
  5360. else {
  5361. var queryStart = url.indexOf('?');
  5362. if (queryStart !== -1) {
  5363. url = url.substring(0, queryStart);
  5364. }
  5365. ext = url.substring(url.lastIndexOf('.') + 1);
  5366. }
  5367. return ext;
  5368. };
  5369. /**
  5370. * Determines the mime type of an XHR request based on the responseType of
  5371. * resource being loaded.
  5372. *
  5373. * @private
  5374. * @return {string} The mime type to use.
  5375. */
  5376. Resource.prototype._getMimeFromXhrType = function (type) {
  5377. switch(type) {
  5378. case Resource.XHR_RESPONSE_TYPE.BUFFER:
  5379. return 'application/octet-binary';
  5380. case Resource.XHR_RESPONSE_TYPE.BLOB:
  5381. return 'application/blob';
  5382. case Resource.XHR_RESPONSE_TYPE.DOCUMENT:
  5383. return 'application/xml';
  5384. case Resource.XHR_RESPONSE_TYPE.JSON:
  5385. return 'application/json';
  5386. case Resource.XHR_RESPONSE_TYPE.DEFAULT:
  5387. case Resource.XHR_RESPONSE_TYPE.TEXT:
  5388. /* falls through */
  5389. default:
  5390. return 'text/plain';
  5391. }
  5392. };
  5393. /**
  5394. * The types of loading a resource can use.
  5395. *
  5396. * @static
  5397. * @constant
  5398. * @property {object} LOAD_TYPE
  5399. * @property {number} LOAD_TYPE.XHR - Uses XMLHttpRequest to load the resource.
  5400. * @property {number} LOAD_TYPE.IMAGE - Uses an `Image` object to load the resource.
  5401. * @property {number} LOAD_TYPE.AUDIO - Uses an `Audio` object to load the resource.
  5402. * @property {number} LOAD_TYPE.VIDEO - Uses a `Video` object to load the resource.
  5403. */
  5404. Resource.LOAD_TYPE = {
  5405. XHR: 1,
  5406. IMAGE: 2,
  5407. AUDIO: 3,
  5408. VIDEO: 4
  5409. };
  5410. /**
  5411. * The XHR ready states, used internally.
  5412. *
  5413. * @static
  5414. * @constant
  5415. * @property {object} XHR_READY_STATE
  5416. * @property {number} XHR_READY_STATE.UNSENT - open()has not been called yet.
  5417. * @property {number} XHR_READY_STATE.OPENED - send()has not been called yet.
  5418. * @property {number} XHR_READY_STATE.HEADERS_RECEIVED - send() has been called, and headers and status are available.
  5419. * @property {number} XHR_READY_STATE.LOADING - Downloading; responseText holds partial data.
  5420. * @property {number} XHR_READY_STATE.DONE - The operation is complete.
  5421. */
  5422. Resource.XHR_READY_STATE = {
  5423. UNSENT: 0,
  5424. OPENED: 1,
  5425. HEADERS_RECEIVED: 2,
  5426. LOADING: 3,
  5427. DONE: 4
  5428. };
  5429. /**
  5430. * The XHR ready states, used internally.
  5431. *
  5432. * @static
  5433. * @constant
  5434. * @property {object} XHR_RESPONSE_TYPE
  5435. * @property {string} XHR_RESPONSE_TYPE.DEFAULT - defaults to text
  5436. * @property {string} XHR_RESPONSE_TYPE.BUFFER - ArrayBuffer
  5437. * @property {string} XHR_RESPONSE_TYPE.BLOB - Blob
  5438. * @property {string} XHR_RESPONSE_TYPE.DOCUMENT - Document
  5439. * @property {string} XHR_RESPONSE_TYPE.JSON - Object
  5440. * @property {string} XHR_RESPONSE_TYPE.TEXT - String
  5441. */
  5442. Resource.XHR_RESPONSE_TYPE = {
  5443. DEFAULT: 'text',
  5444. BUFFER: 'arraybuffer',
  5445. BLOB: 'blob',
  5446. DOCUMENT: 'document',
  5447. JSON: 'json',
  5448. TEXT: 'text'
  5449. };
  5450. Resource._loadTypeMap = {
  5451. 'gif': Resource.LOAD_TYPE.IMAGE,
  5452. 'png': Resource.LOAD_TYPE.IMAGE,
  5453. 'bmp': Resource.LOAD_TYPE.IMAGE,
  5454. 'jpg': Resource.LOAD_TYPE.IMAGE,
  5455. 'jpeg': Resource.LOAD_TYPE.IMAGE,
  5456. 'tif': Resource.LOAD_TYPE.IMAGE,
  5457. 'tiff': Resource.LOAD_TYPE.IMAGE,
  5458. 'webp': Resource.LOAD_TYPE.IMAGE,
  5459. 'tga': Resource.LOAD_TYPE.IMAGE
  5460. };
  5461. Resource._xhrTypeMap = {
  5462. // xml
  5463. 'xhtml': Resource.XHR_RESPONSE_TYPE.DOCUMENT,
  5464. 'html': Resource.XHR_RESPONSE_TYPE.DOCUMENT,
  5465. 'htm': Resource.XHR_RESPONSE_TYPE.DOCUMENT,
  5466. 'xml': Resource.XHR_RESPONSE_TYPE.DOCUMENT,
  5467. 'tmx': Resource.XHR_RESPONSE_TYPE.DOCUMENT,
  5468. 'tsx': Resource.XHR_RESPONSE_TYPE.DOCUMENT,
  5469. 'svg': Resource.XHR_RESPONSE_TYPE.DOCUMENT,
  5470. // images
  5471. 'gif': Resource.XHR_RESPONSE_TYPE.BLOB,
  5472. 'png': Resource.XHR_RESPONSE_TYPE.BLOB,
  5473. 'bmp': Resource.XHR_RESPONSE_TYPE.BLOB,
  5474. 'jpg': Resource.XHR_RESPONSE_TYPE.BLOB,
  5475. 'jpeg': Resource.XHR_RESPONSE_TYPE.BLOB,
  5476. 'tif': Resource.XHR_RESPONSE_TYPE.BLOB,
  5477. 'tiff': Resource.XHR_RESPONSE_TYPE.BLOB,
  5478. 'webp': Resource.XHR_RESPONSE_TYPE.BLOB,
  5479. 'tga': Resource.XHR_RESPONSE_TYPE.BLOB,
  5480. // json
  5481. 'json': Resource.XHR_RESPONSE_TYPE.JSON,
  5482. // text
  5483. 'text': Resource.XHR_RESPONSE_TYPE.TEXT,
  5484. 'txt': Resource.XHR_RESPONSE_TYPE.TEXT
  5485. };
  5486. /**
  5487. * Sets the load type to be used for a specific extension.
  5488. *
  5489. * @static
  5490. * @param extname {string} The extension to set the type for, e.g. "png" or "fnt"
  5491. * @param loadType {Resource.LOAD_TYPE} The load type to set it to.
  5492. */
  5493. Resource.setExtensionLoadType = function (extname, loadType) {
  5494. setExtMap(Resource._loadTypeMap, extname, loadType);
  5495. };
  5496. /**
  5497. * Sets the load type to be used for a specific extension.
  5498. *
  5499. * @static
  5500. * @param extname {string} The extension to set the type for, e.g. "png" or "fnt"
  5501. * @param xhrType {Resource.XHR_RESPONSE_TYPE} The xhr type to set it to.
  5502. */
  5503. Resource.setExtensionXhrType = function (extname, xhrType) {
  5504. setExtMap(Resource._xhrTypeMap, extname, xhrType);
  5505. };
  5506. function setExtMap(map, extname, val) {
  5507. if (extname && extname.indexOf('.') === 0) {
  5508. extname = extname.substring(1);
  5509. }
  5510. if (!extname) {
  5511. return;
  5512. }
  5513. map[extname] = val;
  5514. }
  5515. },{"eventemitter3":10,"url":8}],15:[function(require,module,exports){
  5516. module.exports = {
  5517. // private property
  5518. _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
  5519. encodeBinary: function (input) {
  5520. var output = "";
  5521. var bytebuffer;
  5522. var encodedCharIndexes = new Array(4);
  5523. var inx = 0;
  5524. var jnx = 0;
  5525. var paddingBytes = 0;
  5526. while (inx < input.length) {
  5527. // Fill byte buffer array
  5528. bytebuffer = new Array(3);
  5529. for (jnx = 0; jnx < bytebuffer.length; jnx++) {
  5530. if (inx < input.length) {
  5531. // throw away high-order byte, as documented at:
  5532. // https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data
  5533. bytebuffer[jnx] = input.charCodeAt(inx++) & 0xff;
  5534. }
  5535. else {
  5536. bytebuffer[jnx] = 0;
  5537. }
  5538. }
  5539. // Get each encoded character, 6 bits at a time
  5540. // index 1: first 6 bits
  5541. encodedCharIndexes[0] = bytebuffer[0] >> 2;
  5542. // index 2: second 6 bits (2 least significant bits from input byte 1 + 4 most significant bits from byte 2)
  5543. encodedCharIndexes[1] = ((bytebuffer[0] & 0x3) << 4) | (bytebuffer[1] >> 4);
  5544. // index 3: third 6 bits (4 least significant bits from input byte 2 + 2 most significant bits from byte 3)
  5545. encodedCharIndexes[2] = ((bytebuffer[1] & 0x0f) << 2) | (bytebuffer[2] >> 6);
  5546. // index 3: forth 6 bits (6 least significant bits from input byte 3)
  5547. encodedCharIndexes[3] = bytebuffer[2] & 0x3f;
  5548. // Determine whether padding happened, and adjust accordingly
  5549. paddingBytes = inx - (input.length - 1);
  5550. switch (paddingBytes) {
  5551. case 2:
  5552. // Set last 2 characters to padding char
  5553. encodedCharIndexes[3] = 64;
  5554. encodedCharIndexes[2] = 64;
  5555. break;
  5556. case 1:
  5557. // Set last character to padding char
  5558. encodedCharIndexes[3] = 64;
  5559. break;
  5560. default:
  5561. break; // No padding - proceed
  5562. }
  5563. // Now we will grab each appropriate character out of our keystring
  5564. // based on our index array and append it to the output string
  5565. for (jnx = 0; jnx < encodedCharIndexes.length; jnx++) {
  5566. output += this._keyStr.charAt(encodedCharIndexes[jnx]);
  5567. }
  5568. }
  5569. return output;
  5570. }
  5571. };
  5572. },{}],16:[function(require,module,exports){
  5573. module.exports = require('./Loader');
  5574. module.exports.Resource = require('./Resource');
  5575. module.exports.middleware = {
  5576. caching: {
  5577. memory: require('./middlewares/caching/memory')
  5578. },
  5579. parsing: {
  5580. blob: require('./middlewares/parsing/blob')
  5581. }
  5582. };
  5583. },{"./Loader":13,"./Resource":14,"./middlewares/caching/memory":17,"./middlewares/parsing/blob":18}],17:[function(require,module,exports){
  5584. // a simple in-memory cache for resources
  5585. var cache = {};
  5586. module.exports = function () {
  5587. return function (resource, next) {
  5588. // if cached, then set data and complete the resource
  5589. if (cache[resource.url]) {
  5590. resource.data = cache[resource.url];
  5591. resource.complete();
  5592. }
  5593. // if not cached, wait for complete and store it in the cache.
  5594. else {
  5595. resource.once('complete', function () {
  5596. cache[this.url] = this.data;
  5597. });
  5598. }
  5599. next();
  5600. };
  5601. };
  5602. },{}],18:[function(require,module,exports){
  5603. var Resource = require('../../Resource'),
  5604. b64 = require('../../b64');
  5605. window.URL = window.URL || window.webkitURL;
  5606. // a middleware for transforming XHR loaded Blobs into more useful objects
  5607. module.exports = function () {
  5608. return function (resource, next) {
  5609. if (!resource.data) {
  5610. return next();
  5611. }
  5612. // if this was an XHR load of a blob
  5613. if (resource.xhr && resource.xhrType === Resource.XHR_RESPONSE_TYPE.BLOB) {
  5614. // if there is no blob support we probably got a binary string back
  5615. if (!window.Blob || typeof resource.data === 'string') {
  5616. var type = resource.xhr.getResponseHeader('content-type');
  5617. // this is an image, convert the binary string into a data url
  5618. if (type && type.indexOf('image') === 0) {
  5619. resource.data = new Image();
  5620. resource.data.src = 'data:' + type + ';base64,' + b64.encodeBinary(resource.xhr.responseText);
  5621. resource.isImage = true;
  5622. // wait until the image loads and then callback
  5623. resource.data.onload = function () {
  5624. resource.data.onload = null;
  5625. next();
  5626. };
  5627. }
  5628. }
  5629. // if content type says this is an image, then we should transform the blob into an Image object
  5630. else if (resource.data.type.indexOf('image') === 0) {
  5631. var src = URL.createObjectURL(resource.data);
  5632. resource.blob = resource.data;
  5633. resource.data = new Image();
  5634. resource.data.src = src;
  5635. resource.isImage = true;
  5636. // cleanup the no longer used blob after the image loads
  5637. resource.data.onload = function () {
  5638. URL.revokeObjectURL(src);
  5639. resource.data.onload = null;
  5640. next();
  5641. };
  5642. }
  5643. }
  5644. else {
  5645. next();
  5646. }
  5647. };
  5648. };
  5649. },{"../../Resource":14,"../../b64":15}],19:[function(require,module,exports){
  5650. var core = require('../core');
  5651. // add some extra variables to the container..
  5652. Object.assign(
  5653. core.DisplayObject.prototype,
  5654. require('./accessibleTarget')
  5655. );
  5656. /**
  5657. * The Accessibility manager reacreates the ability to tab and and have content read by screen readers. This is very important as it can possibly help people with disabilities access pixi content.
  5658. * Much like interaction any DisplayObject can be made accessible. This manager will map the events as if the mouse was being used, minimizing the efferot required to implement.
  5659. *
  5660. * @class
  5661. * @memberof PIXI
  5662. * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} A reference to the current renderer
  5663. */
  5664. function AccessibilityManager(renderer)
  5665. {
  5666. // first we create a div that will sit over the pixi element. This is where the div overlays will go.
  5667. var div = document.createElement('div');
  5668. div.style.width = 100 + 'px';
  5669. div.style.height = 100 + 'px';
  5670. div.style.position = 'absolute';
  5671. div.style.top = 0;
  5672. div.style.left = 0;
  5673. //
  5674. div.style.zIndex = 2;
  5675. /**
  5676. * This is the dom element that will sit over the pixi element. This is where the div overlays will go.
  5677. *
  5678. * @type {HTMLElement}
  5679. * @private
  5680. */
  5681. this.div = div;
  5682. /**
  5683. * A simple pool for storing divs.
  5684. *
  5685. * @type {Array}
  5686. * @private
  5687. */
  5688. this.pool = [];
  5689. /**
  5690. * This is a tick used to check if an object is no longer being rendered.
  5691. *
  5692. * @type {Number}
  5693. * @private
  5694. */
  5695. this.renderId = 0;
  5696. /**
  5697. * Setting this to true will visually show the divs
  5698. *
  5699. * @type {Boolean}
  5700. */
  5701. this.debug = false;
  5702. /**
  5703. * The renderer this accessibility manager works for.
  5704. *
  5705. * @member {PIXI.SystemRenderer}
  5706. */
  5707. this.renderer = renderer;
  5708. /**
  5709. * The array of currently active accessible items.
  5710. *
  5711. * @member {Array}
  5712. * @private
  5713. */
  5714. this.children = [];
  5715. /**
  5716. * pre bind the functions..
  5717. */
  5718. this._onKeyDown = this._onKeyDown.bind(this);
  5719. this._onMouseMove = this._onMouseMove.bind(this);
  5720. /**
  5721. * stores the state of the manager. If there are no accessible objects or the mouse is moving the will be false.
  5722. *
  5723. * @member {Array}
  5724. * @private
  5725. */
  5726. this.isActive = false;
  5727. // let listen for tab.. once pressed we can fire up and show the accessibility layer
  5728. window.addEventListener('keydown', this._onKeyDown, false);
  5729. }
  5730. AccessibilityManager.prototype.constructor = AccessibilityManager;
  5731. module.exports = AccessibilityManager;
  5732. /**
  5733. * Activating will cause the Accessibility layer to be shown. This is called when a user preses the tab key
  5734. * @private
  5735. */
  5736. AccessibilityManager.prototype.activate = function()
  5737. {
  5738. if(this.isActive)
  5739. {
  5740. return;
  5741. }
  5742. this.isActive = true;
  5743. window.document.addEventListener('mousemove', this._onMouseMove, true);
  5744. window.removeEventListener('keydown', this._onKeyDown, false);
  5745. this.renderer.on('postrender', this.update, this);
  5746. this.renderer.view.parentNode.appendChild(this.div);
  5747. };
  5748. /**
  5749. * Deactivating will cause the Accessibility layer to be hidden. This is called when a user moves the mouse
  5750. * @private
  5751. */
  5752. AccessibilityManager.prototype.deactivate = function()
  5753. {
  5754. if(!this.isActive)
  5755. {
  5756. return;
  5757. }
  5758. this.isActive = false;
  5759. window.document.removeEventListener('mousemove', this._onMouseMove);
  5760. window.addEventListener('keydown', this._onKeyDown, false);
  5761. this.renderer.off('postrender', this.update);
  5762. this.div.parentNode.removeChild(this.div);
  5763. };
  5764. /**
  5765. * This recursive function will run throught he scene graph and add any new accessible objects to the DOM layer.
  5766. * @param element {PIXI.Container|PIXI.Sprite|PIXI.extras.TilingSprite} the DisplayObject to check.
  5767. * @private
  5768. */
  5769. AccessibilityManager.prototype.updateAccessibleObjects = function(displayObject)
  5770. {
  5771. if(!displayObject.visible)
  5772. {
  5773. return;
  5774. }
  5775. if(displayObject.accessible && displayObject.interactive)
  5776. {
  5777. if(!displayObject._accessibleActive)
  5778. {
  5779. this.addChild(displayObject);
  5780. }
  5781. displayObject.renderId = this.renderId;
  5782. }
  5783. if(displayObject.interactiveChildren)
  5784. {
  5785. var children = displayObject.children;
  5786. for (var i = children.length - 1; i >= 0; i--) {
  5787. this.updateAccessibleObjects(children[i]);
  5788. }
  5789. }
  5790. };
  5791. /**
  5792. * Before each render this function will ensure that all divs are mapped correctly to their DisplayObjects
  5793. * @private
  5794. */
  5795. AccessibilityManager.prototype.update = function()
  5796. {
  5797. // update children...
  5798. this.updateAccessibleObjects(this.renderer._lastObjectRendered);
  5799. var rect = this.renderer.view.getBoundingClientRect();
  5800. var sx = rect.width / this.renderer.width;
  5801. var sy = rect.height / this.renderer.height;
  5802. var div = this.div;
  5803. div.style.left = rect.left + 'px';
  5804. div.style.top = rect.top + 'px';
  5805. div.style.width = this.renderer.width + 'px';
  5806. div.style.height = this.renderer.height + 'px';
  5807. for (var i = 0; i < this.children.length; i++)
  5808. {
  5809. var child = this.children[i];
  5810. if(child.renderId !== this.renderId)
  5811. {
  5812. child._accessibleActive = false;
  5813. core.utils.removeItems(this.children, i, 1);
  5814. this.div.removeChild( child._accessibleDiv );
  5815. this.pool.push(child._accessibleDiv);
  5816. child._accessibleDiv = null;
  5817. i--;
  5818. if(this.children.length === 0)
  5819. {
  5820. this.deactivate();
  5821. }
  5822. }
  5823. else
  5824. {
  5825. // map div to display..
  5826. div = child._accessibleDiv;
  5827. var hitArea = child.hitArea;
  5828. var wt = child.worldTransform;
  5829. if(child.hitArea)
  5830. {
  5831. div.style.left = ((wt.tx + (hitArea.x * wt.a)) * sx) + 'px';
  5832. div.style.top = ((wt.ty + (hitArea.y * wt.d)) * sy) + 'px';
  5833. div.style.width = (hitArea.width * wt.a * sx) + 'px';
  5834. div.style.height = (hitArea.height * wt.d * sy) + 'px';
  5835. }
  5836. else
  5837. {
  5838. hitArea = child.getBounds();
  5839. this.capHitArea(hitArea);
  5840. div.style.left = (hitArea.x * sx) + 'px';
  5841. div.style.top = (hitArea.y * sy) + 'px';
  5842. div.style.width = (hitArea.width * sx) + 'px';
  5843. div.style.height = (hitArea.height * sy) + 'px';
  5844. }
  5845. }
  5846. }
  5847. // increment the render id..
  5848. this.renderId++;
  5849. };
  5850. AccessibilityManager.prototype.capHitArea = function (hitArea)
  5851. {
  5852. if (hitArea.x < 0)
  5853. {
  5854. hitArea.width += hitArea.x;
  5855. hitArea.x = 0;
  5856. }
  5857. if (hitArea.y < 0)
  5858. {
  5859. hitArea.height += hitArea.y;
  5860. hitArea.y = 0;
  5861. }
  5862. if ( hitArea.x + hitArea.width > this.renderer.width )
  5863. {
  5864. hitArea.width = this.renderer.width - hitArea.x;
  5865. }
  5866. if ( hitArea.y + hitArea.height > this.renderer.height )
  5867. {
  5868. hitArea.height = this.renderer.height - hitArea.y;
  5869. }
  5870. };
  5871. /**
  5872. * Adds a DisplayObject to the accessibility manager
  5873. * @private
  5874. */
  5875. AccessibilityManager.prototype.addChild = function(displayObject)
  5876. {
  5877. // this.activate();
  5878. var div = this.pool.pop();
  5879. if(!div)
  5880. {
  5881. div = document.createElement('button');
  5882. div.style.width = 100 + 'px';
  5883. div.style.height = 100 + 'px';
  5884. div.style.backgroundColor = this.debug ? 'rgba(255,0,0,0.5)' : 'transparent';
  5885. div.style.position = 'absolute';
  5886. div.style.zIndex = 2;
  5887. div.style.borderStyle = 'none';
  5888. div.addEventListener('click', this._onClick.bind(this));
  5889. div.addEventListener('focus', this._onFocus.bind(this));
  5890. div.addEventListener('focusout', this._onFocusOut.bind(this));
  5891. }
  5892. div.title = displayObject.accessibleTitle || 'displayObject ' + this.tabIndex;
  5893. //
  5894. displayObject._accessibleActive = true;
  5895. displayObject._accessibleDiv = div;
  5896. div.displayObject = displayObject;
  5897. this.children.push(displayObject);
  5898. this.div.appendChild( displayObject._accessibleDiv );
  5899. displayObject._accessibleDiv.tabIndex = displayObject.tabIndex;
  5900. };
  5901. /**
  5902. * Maps the div button press to pixi's InteractionManager (click)
  5903. * @private
  5904. */
  5905. AccessibilityManager.prototype._onClick = function(e)
  5906. {
  5907. var interactionManager = this.renderer.plugins.interaction;
  5908. interactionManager.dispatchEvent(e.target.displayObject, 'click', interactionManager.eventData);
  5909. };
  5910. /**
  5911. * Maps the div focus events to pixis InteractionManager (mouseover)
  5912. * @private
  5913. */
  5914. AccessibilityManager.prototype._onFocus = function(e)
  5915. {
  5916. var interactionManager = this.renderer.plugins.interaction;
  5917. interactionManager.dispatchEvent(e.target.displayObject, 'mouseover', interactionManager.eventData);
  5918. };
  5919. /**
  5920. * Maps the div focus events to pixis InteractionManager (mouseout)
  5921. * @private
  5922. */
  5923. AccessibilityManager.prototype._onFocusOut = function(e)
  5924. {
  5925. var interactionManager = this.renderer.plugins.interaction;
  5926. interactionManager.dispatchEvent(e.target.displayObject, 'mouseout', interactionManager.eventData);
  5927. };
  5928. /**
  5929. * Is called when a key is pressed
  5930. *
  5931. * @private
  5932. */
  5933. AccessibilityManager.prototype._onKeyDown = function(e)
  5934. {
  5935. if(e.keyCode !== 9)
  5936. {
  5937. return;
  5938. }
  5939. this.activate();
  5940. };
  5941. /**
  5942. * Is called when the mouse moves across the renderer element
  5943. *
  5944. * @private
  5945. */
  5946. AccessibilityManager.prototype._onMouseMove = function()
  5947. {
  5948. this.deactivate();
  5949. };
  5950. /**
  5951. * Destroys the accessibility manager
  5952. *
  5953. */
  5954. AccessibilityManager.prototype.destroy = function ()
  5955. {
  5956. this.div = null;
  5957. for (var i = 0; i < this.children.length; i++)
  5958. {
  5959. this.children[i].div = null;
  5960. }
  5961. window.document.removeEventListener('mousemove', this._onMouseMove);
  5962. window.removeEventListener('keydown', this._onKeyDown);
  5963. this.pool = null;
  5964. this.children = null;
  5965. this.renderer = null;
  5966. };
  5967. core.WebGLRenderer.registerPlugin('accessibility', AccessibilityManager);
  5968. core.CanvasRenderer.registerPlugin('accessibility', AccessibilityManager);
  5969. },{"../core":29,"./accessibleTarget":20}],20:[function(require,module,exports){
  5970. /**
  5971. * Default property values of accessible objects
  5972. * used by {@link PIXI.accessibility.AccessibilityManager}.
  5973. *
  5974. * @mixin
  5975. * @memberof PIXI
  5976. * @example
  5977. * function MyObject() {}
  5978. *
  5979. * Object.assign(
  5980. * MyObject.prototype,
  5981. * PIXI.accessibility.accessibleTarget
  5982. * );
  5983. */
  5984. var accessibleTarget = {
  5985. /**
  5986. * @todo Needs docs.
  5987. */
  5988. accessible:false,
  5989. /**
  5990. * @todo Needs docs.
  5991. */
  5992. accessibleTitle:null,
  5993. /**
  5994. * @todo Needs docs.
  5995. */
  5996. tabIndex:0,
  5997. /**
  5998. * @todo Needs docs.
  5999. */
  6000. _accessibleActive:false,
  6001. /**
  6002. * @todo Needs docs.
  6003. */
  6004. _accessibleDiv:false
  6005. };
  6006. module.exports = accessibleTarget;
  6007. },{}],21:[function(require,module,exports){
  6008. /**
  6009. * @file Main export of the PIXI accessibility library
  6010. * @author Mat Groves <mat@goodboydigital.com>
  6011. * @copyright 2013-2015 GoodBoyDigital
  6012. * @license {@link https://github.com/pixijs/pixi.js/blob/master/LICENSE|MIT License}
  6013. */
  6014. /**
  6015. * @namespace PIXI.interaction
  6016. */
  6017. module.exports = {
  6018. accessibleTarget: require('./accessibleTarget'),
  6019. AccessibilityManager: require('./AccessibilityManager')
  6020. };
  6021. },{"./AccessibilityManager":19,"./accessibleTarget":20}],22:[function(require,module,exports){
  6022. /**
  6023. * Constant values used in pixi
  6024. *
  6025. * @lends PIXI
  6026. */
  6027. var CONST = {
  6028. /**
  6029. * String of the current PIXI version
  6030. *
  6031. * @static
  6032. * @constant
  6033. * @property {string} VERSION
  6034. */
  6035. VERSION: '3.0.10',
  6036. /**
  6037. * @property {number} PI_2 - Two Pi
  6038. * @constant
  6039. * @static
  6040. */
  6041. PI_2: Math.PI * 2,
  6042. /**
  6043. * @property {number} RAD_TO_DEG - Constant conversion factor for converting radians to degrees
  6044. * @constant
  6045. * @static
  6046. */
  6047. RAD_TO_DEG: 180 / Math.PI,
  6048. /**
  6049. * @property {Number} DEG_TO_RAD - Constant conversion factor for converting degrees to radians
  6050. * @constant
  6051. * @static
  6052. */
  6053. DEG_TO_RAD: Math.PI / 180,
  6054. /**
  6055. * Target frames per millisecond.
  6056. *
  6057. * @static
  6058. * @constant
  6059. * @property {number} TARGET_FPMS=0.06
  6060. */
  6061. TARGET_FPMS: 0.06,
  6062. /**
  6063. * Constant to identify the Renderer Type.
  6064. *
  6065. * @static
  6066. * @constant
  6067. * @property {object} RENDERER_TYPE
  6068. * @property {number} RENDERER_TYPE.UNKNOWN
  6069. * @property {number} RENDERER_TYPE.WEBGL
  6070. * @property {number} RENDERER_TYPE.CANVAS
  6071. */
  6072. RENDERER_TYPE: {
  6073. UNKNOWN: 0,
  6074. WEBGL: 1,
  6075. CANVAS: 2
  6076. },
  6077. /**
  6078. * Various blend modes supported by PIXI. IMPORTANT - The WebGL renderer only supports
  6079. * the NORMAL, ADD, MULTIPLY and SCREEN blend modes. Anything else will silently act like
  6080. * NORMAL.
  6081. *
  6082. * @static
  6083. * @constant
  6084. * @property {object} BLEND_MODES
  6085. * @property {number} BLEND_MODES.NORMAL
  6086. * @property {number} BLEND_MODES.ADD
  6087. * @property {number} BLEND_MODES.MULTIPLY
  6088. * @property {number} BLEND_MODES.SCREEN
  6089. * @property {number} BLEND_MODES.OVERLAY
  6090. * @property {number} BLEND_MODES.DARKEN
  6091. * @property {number} BLEND_MODES.LIGHTEN
  6092. * @property {number} BLEND_MODES.COLOR_DODGE
  6093. * @property {number} BLEND_MODES.COLOR_BURN
  6094. * @property {number} BLEND_MODES.HARD_LIGHT
  6095. * @property {number} BLEND_MODES.SOFT_LIGHT
  6096. * @property {number} BLEND_MODES.DIFFERENCE
  6097. * @property {number} BLEND_MODES.EXCLUSION
  6098. * @property {number} BLEND_MODES.HUE
  6099. * @property {number} BLEND_MODES.SATURATION
  6100. * @property {number} BLEND_MODES.COLOR
  6101. * @property {number} BLEND_MODES.LUMINOSITY
  6102. */
  6103. BLEND_MODES: {
  6104. NORMAL: 0,
  6105. ADD: 1,
  6106. MULTIPLY: 2,
  6107. SCREEN: 3,
  6108. OVERLAY: 4,
  6109. DARKEN: 5,
  6110. LIGHTEN: 6,
  6111. COLOR_DODGE: 7,
  6112. COLOR_BURN: 8,
  6113. HARD_LIGHT: 9,
  6114. SOFT_LIGHT: 10,
  6115. DIFFERENCE: 11,
  6116. EXCLUSION: 12,
  6117. HUE: 13,
  6118. SATURATION: 14,
  6119. COLOR: 15,
  6120. LUMINOSITY: 16
  6121. },
  6122. /**
  6123. * Various webgl draw modes. These can be used to specify which GL drawMode to use
  6124. * under certain situations and renderers.
  6125. *
  6126. * @static
  6127. * @constant
  6128. * @property {object} DRAW_MODES
  6129. * @property {number} DRAW_MODES.POINTS
  6130. * @property {number} DRAW_MODES.LINES
  6131. * @property {number} DRAW_MODES.LINE_LOOP
  6132. * @property {number} DRAW_MODES.LINE_STRIP
  6133. * @property {number} DRAW_MODES.TRIANGLES
  6134. * @property {number} DRAW_MODES.TRIANGLE_STRIP
  6135. * @property {number} DRAW_MODES.TRIANGLE_FAN
  6136. */
  6137. DRAW_MODES: {
  6138. POINTS: 0,
  6139. LINES: 1,
  6140. LINE_LOOP: 2,
  6141. LINE_STRIP: 3,
  6142. TRIANGLES: 4,
  6143. TRIANGLE_STRIP: 5,
  6144. TRIANGLE_FAN: 6
  6145. },
  6146. /**
  6147. * The scale modes that are supported by pixi.
  6148. *
  6149. * The DEFAULT scale mode affects the default scaling mode of future operations.
  6150. * It can be re-assigned to either LINEAR or NEAREST, depending upon suitability.
  6151. *
  6152. * @static
  6153. * @constant
  6154. * @property {object} SCALE_MODES
  6155. * @property {number} SCALE_MODES.DEFAULT=LINEAR
  6156. * @property {number} SCALE_MODES.LINEAR Smooth scaling
  6157. * @property {number} SCALE_MODES.NEAREST Pixelating scaling
  6158. */
  6159. SCALE_MODES: {
  6160. DEFAULT: 0,
  6161. LINEAR: 0,
  6162. NEAREST: 1
  6163. },
  6164. /**
  6165. * The prefix that denotes a URL is for a retina asset
  6166. *
  6167. * @static
  6168. * @constant
  6169. * @property {string} RETINA_PREFIX
  6170. */
  6171. //example: '@2x',
  6172. RETINA_PREFIX: /@(.+)x/,
  6173. RESOLUTION:1,
  6174. FILTER_RESOLUTION:1,
  6175. /**
  6176. * The default render options if none are supplied to {@link PIXI.WebGLRenderer}
  6177. * or {@link PIXI.CanvasRenderer}.
  6178. *
  6179. * @static
  6180. * @constant
  6181. * @property {object} DEFAULT_RENDER_OPTIONS
  6182. * @property {HTMLCanvasElement} DEFAULT_RENDER_OPTIONS.view=null
  6183. * @property {boolean} DEFAULT_RENDER_OPTIONS.transparent=false
  6184. * @property {boolean} DEFAULT_RENDER_OPTIONS.antialias=false
  6185. * @property {boolean} DEFAULT_RENDER_OPTIONS.forceFXAA=false
  6186. * @property {boolean} DEFAULT_RENDER_OPTIONS.preserveDrawingBuffer=false
  6187. * @property {number} DEFAULT_RENDER_OPTIONS.resolution=1
  6188. * @property {number} DEFAULT_RENDER_OPTIONS.backgroundColor=0x000000
  6189. * @property {boolean} DEFAULT_RENDER_OPTIONS.clearBeforeRender=true
  6190. * @property {boolean} DEFAULT_RENDER_OPTIONS.autoResize=false
  6191. */
  6192. DEFAULT_RENDER_OPTIONS: {
  6193. view: null,
  6194. resolution: 1,
  6195. antialias: false,
  6196. forceFXAA: false,
  6197. autoResize: false,
  6198. transparent: false,
  6199. backgroundColor: 0x000000,
  6200. clearBeforeRender: true,
  6201. preserveDrawingBuffer: false,
  6202. roundPixels: false
  6203. },
  6204. /**
  6205. * Constants that identify shapes, mainly to prevent `instanceof` calls.
  6206. *
  6207. * @static
  6208. * @constant
  6209. * @property {object} SHAPES
  6210. * @property {object} SHAPES.POLY=0
  6211. * @property {object} SHAPES.RECT=1
  6212. * @property {object} SHAPES.CIRC=2
  6213. * @property {object} SHAPES.ELIP=3
  6214. * @property {object} SHAPES.RREC=4
  6215. */
  6216. SHAPES: {
  6217. POLY: 0,
  6218. RECT: 1,
  6219. CIRC: 2,
  6220. ELIP: 3,
  6221. RREC: 4
  6222. },
  6223. // TODO: maybe change to SPRITE.BATCH_SIZE: 2000
  6224. // TODO: maybe add PARTICLE.BATCH_SIZE: 15000
  6225. SPRITE_BATCH_SIZE: 2000 //nice balance between mobile and desktop machines
  6226. };
  6227. module.exports = CONST;
  6228. },{}],23:[function(require,module,exports){
  6229. var math = require('../math'),
  6230. utils = require('../utils'),
  6231. DisplayObject = require('./DisplayObject'),
  6232. RenderTexture = require('../textures/RenderTexture'),
  6233. _tempMatrix = new math.Matrix();
  6234. /**
  6235. * A Container represents a collection of display objects.
  6236. * It is the base class of all display objects that act as a container for other objects.
  6237. *
  6238. *```js
  6239. * var container = new PIXI.Container();
  6240. * container.addChild(sprite);
  6241. * ```
  6242. * @class
  6243. * @extends PIXI.DisplayObject
  6244. * @memberof PIXI
  6245. */
  6246. function Container()
  6247. {
  6248. DisplayObject.call(this);
  6249. /**
  6250. * The array of children of this container.
  6251. *
  6252. * @member {PIXI.DisplayObject[]}
  6253. * @readonly
  6254. */
  6255. this.children = [];
  6256. }
  6257. // constructor
  6258. Container.prototype = Object.create(DisplayObject.prototype);
  6259. Container.prototype.constructor = Container;
  6260. module.exports = Container;
  6261. Object.defineProperties(Container.prototype, {
  6262. /**
  6263. * The width of the Container, setting this will actually modify the scale to achieve the value set
  6264. *
  6265. * @member {number}
  6266. * @memberof PIXI.Container#
  6267. */
  6268. width: {
  6269. get: function ()
  6270. {
  6271. return this.scale.x * this.getLocalBounds().width;
  6272. },
  6273. set: function (value)
  6274. {
  6275. var width = this.getLocalBounds().width;
  6276. if (width !== 0)
  6277. {
  6278. this.scale.x = value / width;
  6279. }
  6280. else
  6281. {
  6282. this.scale.x = 1;
  6283. }
  6284. this._width = value;
  6285. }
  6286. },
  6287. /**
  6288. * The height of the Container, setting this will actually modify the scale to achieve the value set
  6289. *
  6290. * @member {number}
  6291. * @memberof PIXI.Container#
  6292. */
  6293. height: {
  6294. get: function ()
  6295. {
  6296. return this.scale.y * this.getLocalBounds().height;
  6297. },
  6298. set: function (value)
  6299. {
  6300. var height = this.getLocalBounds().height;
  6301. if (height !== 0)
  6302. {
  6303. this.scale.y = value / height ;
  6304. }
  6305. else
  6306. {
  6307. this.scale.y = 1;
  6308. }
  6309. this._height = value;
  6310. }
  6311. }
  6312. });
  6313. /**
  6314. * Overridable method that can be used by Container subclasses whenever the children array is modified
  6315. *
  6316. * @private
  6317. */
  6318. Container.prototype.onChildrenChange = function () {};
  6319. /**
  6320. * Adds a child to the container.
  6321. *
  6322. * You can also add multple items like so: myContainer.addChild(thinkOne, thingTwo, thingThree)
  6323. * @param child {PIXI.DisplayObject} The DisplayObject to add to the container
  6324. * @return {PIXI.DisplayObject} The child that was added.
  6325. */
  6326. Container.prototype.addChild = function (child)
  6327. {
  6328. var argumentsLength = arguments.length;
  6329. // if there is only one argument we can bypass looping through the them
  6330. if(argumentsLength > 1)
  6331. {
  6332. // loop through the arguments property and add all children
  6333. // use it the right way (.length and [i]) so that this function can still be optimised by JS runtimes
  6334. for (var i = 0; i < argumentsLength; i++)
  6335. {
  6336. this.addChild( arguments[i] );
  6337. }
  6338. }
  6339. else
  6340. {
  6341. // if the child has a parent then lets remove it as Pixi objects can only exist in one place
  6342. if (child.parent)
  6343. {
  6344. child.parent.removeChild(child);
  6345. }
  6346. child.parent = this;
  6347. this.children.push(child);
  6348. // TODO - lets either do all callbacks or all events.. not both!
  6349. this.onChildrenChange(this.children.length-1);
  6350. child.emit('added', this);
  6351. }
  6352. return child;
  6353. };
  6354. /**
  6355. * Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown
  6356. *
  6357. * @param child {PIXI.DisplayObject} The child to add
  6358. * @param index {number} The index to place the child in
  6359. * @return {PIXI.DisplayObject} The child that was added.
  6360. */
  6361. Container.prototype.addChildAt = function (child, index)
  6362. {
  6363. if (index >= 0 && index <= this.children.length)
  6364. {
  6365. if (child.parent)
  6366. {
  6367. child.parent.removeChild(child);
  6368. }
  6369. child.parent = this;
  6370. this.children.splice(index, 0, child);
  6371. // TODO - lets either do all callbacks or all events.. not both!
  6372. this.onChildrenChange(index);
  6373. child.emit('added', this);
  6374. return child;
  6375. }
  6376. else
  6377. {
  6378. throw new Error(child + 'addChildAt: The index '+ index +' supplied is out of bounds ' + this.children.length);
  6379. }
  6380. };
  6381. /**
  6382. * Swaps the position of 2 Display Objects within this container.
  6383. *
  6384. * @param child {PIXI.DisplayObject}
  6385. * @param child2 {PIXI.DisplayObject}
  6386. */
  6387. Container.prototype.swapChildren = function (child, child2)
  6388. {
  6389. if (child === child2)
  6390. {
  6391. return;
  6392. }
  6393. var index1 = this.getChildIndex(child);
  6394. var index2 = this.getChildIndex(child2);
  6395. if (index1 < 0 || index2 < 0)
  6396. {
  6397. throw new Error('swapChildren: Both the supplied DisplayObjects must be children of the caller.');
  6398. }
  6399. this.children[index1] = child2;
  6400. this.children[index2] = child;
  6401. this.onChildrenChange(index1 < index2 ? index1 : index2);
  6402. };
  6403. /**
  6404. * Returns the index position of a child DisplayObject instance
  6405. *
  6406. * @param child {PIXI.DisplayObject} The DisplayObject instance to identify
  6407. * @return {number} The index position of the child display object to identify
  6408. */
  6409. Container.prototype.getChildIndex = function (child)
  6410. {
  6411. var index = this.children.indexOf(child);
  6412. if (index === -1)
  6413. {
  6414. throw new Error('The supplied DisplayObject must be a child of the caller');
  6415. }
  6416. return index;
  6417. };
  6418. /**
  6419. * Changes the position of an existing child in the display object container
  6420. *
  6421. * @param child {PIXI.DisplayObject} The child DisplayObject instance for which you want to change the index number
  6422. * @param index {number} The resulting index number for the child display object
  6423. */
  6424. Container.prototype.setChildIndex = function (child, index)
  6425. {
  6426. if (index < 0 || index >= this.children.length)
  6427. {
  6428. throw new Error('The supplied index is out of bounds');
  6429. }
  6430. var currentIndex = this.getChildIndex(child);
  6431. utils.removeItems(this.children, currentIndex, 1); // remove from old position
  6432. this.children.splice(index, 0, child); //add at new position
  6433. this.onChildrenChange(index);
  6434. };
  6435. /**
  6436. * Returns the child at the specified index
  6437. *
  6438. * @param index {number} The index to get the child at
  6439. * @return {PIXI.DisplayObject} The child at the given index, if any.
  6440. */
  6441. Container.prototype.getChildAt = function (index)
  6442. {
  6443. if (index < 0 || index >= this.children.length)
  6444. {
  6445. throw new Error('getChildAt: Supplied index ' + index + ' does not exist in the child list, or the supplied DisplayObject is not a child of the caller');
  6446. }
  6447. return this.children[index];
  6448. };
  6449. /**
  6450. * Removes a child from the container.
  6451. *
  6452. * @param child {PIXI.DisplayObject} The DisplayObject to remove
  6453. * @return {PIXI.DisplayObject} The child that was removed.
  6454. */
  6455. Container.prototype.removeChild = function (child)
  6456. {
  6457. var argumentsLength = arguments.length;
  6458. // if there is only one argument we can bypass looping through the them
  6459. if(argumentsLength > 1)
  6460. {
  6461. // loop through the arguments property and add all children
  6462. // use it the right way (.length and [i]) so that this function can still be optimised by JS runtimes
  6463. for (var i = 0; i < argumentsLength; i++)
  6464. {
  6465. this.removeChild( arguments[i] );
  6466. }
  6467. }
  6468. else
  6469. {
  6470. var index = this.children.indexOf(child);
  6471. if (index === -1)
  6472. {
  6473. return;
  6474. }
  6475. child.parent = null;
  6476. utils.removeItems(this.children, index, 1);
  6477. // TODO - lets either do all callbacks or all events.. not both!
  6478. this.onChildrenChange(index);
  6479. child.emit('removed', this);
  6480. }
  6481. return child;
  6482. };
  6483. /**
  6484. * Removes a child from the specified index position.
  6485. *
  6486. * @param index {number} The index to get the child from
  6487. * @return {PIXI.DisplayObject} The child that was removed.
  6488. */
  6489. Container.prototype.removeChildAt = function (index)
  6490. {
  6491. var child = this.getChildAt(index);
  6492. child.parent = null;
  6493. utils.removeItems(this.children, index, 1);
  6494. // TODO - lets either do all callbacks or all events.. not both!
  6495. this.onChildrenChange(index);
  6496. child.emit('removed', this);
  6497. return child;
  6498. };
  6499. /**
  6500. * Removes all children from this container that are within the begin and end indexes.
  6501. *
  6502. * @param beginIndex {number} The beginning position. Default value is 0.
  6503. * @param endIndex {number} The ending position. Default value is size of the container.
  6504. */
  6505. Container.prototype.removeChildren = function (beginIndex, endIndex)
  6506. {
  6507. var begin = beginIndex || 0;
  6508. var end = typeof endIndex === 'number' ? endIndex : this.children.length;
  6509. var range = end - begin;
  6510. var removed, i;
  6511. if (range > 0 && range <= end)
  6512. {
  6513. removed = this.children.splice(begin, range);
  6514. for (i = 0; i < removed.length; ++i)
  6515. {
  6516. removed[i].parent = null;
  6517. }
  6518. this.onChildrenChange(beginIndex);
  6519. for (i = 0; i < removed.length; ++i)
  6520. {
  6521. removed[i].emit('removed', this);
  6522. }
  6523. return removed;
  6524. }
  6525. else if (range === 0 && this.children.length === 0)
  6526. {
  6527. return [];
  6528. }
  6529. else
  6530. {
  6531. throw new RangeError('removeChildren: numeric values are outside the acceptable range.');
  6532. }
  6533. };
  6534. /**
  6535. * Useful function that returns a texture of the display object that can then be used to create sprites
  6536. * This can be quite useful if your displayObject is static / complicated and needs to be reused multiple times.
  6537. *
  6538. * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} The renderer used to generate the texture.
  6539. * @param resolution {number} The resolution of the texture being generated
  6540. * @param scaleMode {number} See {@link PIXI.SCALE_MODES} for possible values
  6541. * @return {PIXI.Texture} a texture of the display object
  6542. */
  6543. Container.prototype.generateTexture = function (renderer, resolution, scaleMode)
  6544. {
  6545. var bounds = this.getLocalBounds();
  6546. var renderTexture = new RenderTexture(renderer, bounds.width | 0, bounds.height | 0, scaleMode, resolution);
  6547. _tempMatrix.tx = -bounds.x;
  6548. _tempMatrix.ty = -bounds.y;
  6549. renderTexture.render(this, _tempMatrix);
  6550. return renderTexture;
  6551. };
  6552. /*
  6553. * Updates the transform on all children of this container for rendering
  6554. *
  6555. * @private
  6556. */
  6557. Container.prototype.updateTransform = function ()
  6558. {
  6559. if (!this.visible)
  6560. {
  6561. return;
  6562. }
  6563. this.displayObjectUpdateTransform();
  6564. for (var i = 0, j = this.children.length; i < j; ++i)
  6565. {
  6566. this.children[i].updateTransform();
  6567. }
  6568. };
  6569. // performance increase to avoid using call.. (10x faster)
  6570. Container.prototype.containerUpdateTransform = Container.prototype.updateTransform;
  6571. /**
  6572. * Retrieves the bounds of the Container as a rectangle. The bounds calculation takes all visible children into consideration.
  6573. *
  6574. * @return {PIXI.Rectangle} The rectangular bounding area
  6575. */
  6576. Container.prototype.getBounds = function ()
  6577. {
  6578. if(!this._currentBounds)
  6579. {
  6580. if (this.children.length === 0)
  6581. {
  6582. return math.Rectangle.EMPTY;
  6583. }
  6584. // TODO the bounds have already been calculated this render session so return what we have
  6585. var minX = Infinity;
  6586. var minY = Infinity;
  6587. var maxX = -Infinity;
  6588. var maxY = -Infinity;
  6589. var childBounds;
  6590. var childMaxX;
  6591. var childMaxY;
  6592. var childVisible = false;
  6593. for (var i = 0, j = this.children.length; i < j; ++i)
  6594. {
  6595. var child = this.children[i];
  6596. if (!child.visible)
  6597. {
  6598. continue;
  6599. }
  6600. childVisible = true;
  6601. childBounds = this.children[i].getBounds();
  6602. minX = minX < childBounds.x ? minX : childBounds.x;
  6603. minY = minY < childBounds.y ? minY : childBounds.y;
  6604. childMaxX = childBounds.width + childBounds.x;
  6605. childMaxY = childBounds.height + childBounds.y;
  6606. maxX = maxX > childMaxX ? maxX : childMaxX;
  6607. maxY = maxY > childMaxY ? maxY : childMaxY;
  6608. }
  6609. if (!childVisible)
  6610. {
  6611. return math.Rectangle.EMPTY;
  6612. }
  6613. var bounds = this._bounds;
  6614. bounds.x = minX;
  6615. bounds.y = minY;
  6616. bounds.width = maxX - minX;
  6617. bounds.height = maxY - minY;
  6618. this._currentBounds = bounds;
  6619. }
  6620. return this._currentBounds;
  6621. };
  6622. Container.prototype.containerGetBounds = Container.prototype.getBounds;
  6623. /**
  6624. * Retrieves the non-global local bounds of the Container as a rectangle.
  6625. * The calculation takes all visible children into consideration.
  6626. *
  6627. * @return {PIXI.Rectangle} The rectangular bounding area
  6628. */
  6629. Container.prototype.getLocalBounds = function ()
  6630. {
  6631. var matrixCache = this.worldTransform;
  6632. this.worldTransform = math.Matrix.IDENTITY;
  6633. for (var i = 0, j = this.children.length; i < j; ++i)
  6634. {
  6635. this.children[i].updateTransform();
  6636. }
  6637. this.worldTransform = matrixCache;
  6638. this._currentBounds = null;
  6639. return this.getBounds( math.Matrix.IDENTITY );
  6640. };
  6641. /**
  6642. * Renders the object using the WebGL renderer
  6643. *
  6644. * @param renderer {PIXI.WebGLRenderer} The renderer
  6645. */
  6646. Container.prototype.renderWebGL = function (renderer)
  6647. {
  6648. // if the object is not visible or the alpha is 0 then no need to render this element
  6649. if (!this.visible || this.worldAlpha <= 0 || !this.renderable)
  6650. {
  6651. return;
  6652. }
  6653. var i, j;
  6654. // do a quick check to see if this element has a mask or a filter.
  6655. if (this._mask || this._filters)
  6656. {
  6657. renderer.currentRenderer.flush();
  6658. // push filter first as we need to ensure the stencil buffer is correct for any masking
  6659. if (this._filters && this._filters.length)
  6660. {
  6661. renderer.filterManager.pushFilter(this, this._filters);
  6662. }
  6663. if (this._mask)
  6664. {
  6665. renderer.maskManager.pushMask(this, this._mask);
  6666. }
  6667. renderer.currentRenderer.start();
  6668. // add this object to the batch, only rendered if it has a texture.
  6669. this._renderWebGL(renderer);
  6670. // now loop through the children and make sure they get rendered
  6671. for (i = 0, j = this.children.length; i < j; i++)
  6672. {
  6673. this.children[i].renderWebGL(renderer);
  6674. }
  6675. renderer.currentRenderer.flush();
  6676. if (this._mask)
  6677. {
  6678. renderer.maskManager.popMask(this, this._mask);
  6679. }
  6680. if (this._filters)
  6681. {
  6682. renderer.filterManager.popFilter();
  6683. }
  6684. renderer.currentRenderer.start();
  6685. }
  6686. else
  6687. {
  6688. this._renderWebGL(renderer);
  6689. // simple render children!
  6690. for (i = 0, j = this.children.length; i < j; ++i)
  6691. {
  6692. this.children[i].renderWebGL(renderer);
  6693. }
  6694. }
  6695. };
  6696. /**
  6697. * To be overridden by the subclass
  6698. *
  6699. * @param renderer {PIXI.WebGLRenderer} The renderer
  6700. * @private
  6701. */
  6702. Container.prototype._renderWebGL = function (renderer) // jshint unused:false
  6703. {
  6704. // this is where content itself gets rendered...
  6705. };
  6706. /**
  6707. * To be overridden by the subclass
  6708. *
  6709. * @param renderer {PIXI.CanvasRenderer} The renderer
  6710. * @private
  6711. */
  6712. Container.prototype._renderCanvas = function (renderer) // jshint unused:false
  6713. {
  6714. // this is where content itself gets rendered...
  6715. };
  6716. /**
  6717. * Renders the object using the Canvas renderer
  6718. *
  6719. * @param renderer {PIXI.CanvasRenderer} The renderer
  6720. */
  6721. Container.prototype.renderCanvas = function (renderer)
  6722. {
  6723. // if not visible or the alpha is 0 then no need to render this
  6724. if (!this.visible || this.alpha <= 0 || !this.renderable)
  6725. {
  6726. return;
  6727. }
  6728. if (this._mask)
  6729. {
  6730. renderer.maskManager.pushMask(this._mask, renderer);
  6731. }
  6732. this._renderCanvas(renderer);
  6733. for (var i = 0, j = this.children.length; i < j; ++i)
  6734. {
  6735. this.children[i].renderCanvas(renderer);
  6736. }
  6737. if (this._mask)
  6738. {
  6739. renderer.maskManager.popMask(renderer);
  6740. }
  6741. };
  6742. /**
  6743. * Destroys the container
  6744. * @param [destroyChildren=false] {boolean} if set to true, all the children will have their destroy method called as well
  6745. */
  6746. Container.prototype.destroy = function (destroyChildren)
  6747. {
  6748. DisplayObject.prototype.destroy.call(this);
  6749. if (destroyChildren)
  6750. {
  6751. for (var i = 0, j = this.children.length; i < j; ++i)
  6752. {
  6753. this.children[i].destroy(destroyChildren);
  6754. }
  6755. }
  6756. this.removeChildren();
  6757. this.children = null;
  6758. };
  6759. },{"../math":33,"../textures/RenderTexture":71,"../utils":77,"./DisplayObject":24}],24:[function(require,module,exports){
  6760. var math = require('../math'),
  6761. RenderTexture = require('../textures/RenderTexture'),
  6762. EventEmitter = require('eventemitter3'),
  6763. CONST = require('../const'),
  6764. _tempMatrix = new math.Matrix(),
  6765. _tempDisplayObjectParent = {worldTransform:new math.Matrix(), worldAlpha:1, children:[]};
  6766. /**
  6767. * The base class for all objects that are rendered on the screen.
  6768. * This is an abstract class and should not be used on its own rather it should be extended.
  6769. *
  6770. * @class
  6771. * @extends EventEmitter
  6772. * @memberof PIXI
  6773. */
  6774. function DisplayObject()
  6775. {
  6776. EventEmitter.call(this);
  6777. /**
  6778. * The coordinate of the object relative to the local coordinates of the parent.
  6779. *
  6780. * @member {PIXI.Point}
  6781. */
  6782. this.position = new math.Point();
  6783. /**
  6784. * The scale factor of the object.
  6785. *
  6786. * @member {PIXI.Point}
  6787. */
  6788. this.scale = new math.Point(1, 1);
  6789. /**
  6790. * The pivot point of the displayObject that it rotates around
  6791. *
  6792. * @member {PIXI.Point}
  6793. */
  6794. this.pivot = new math.Point(0, 0);
  6795. /**
  6796. * The skew factor for the object in radians.
  6797. *
  6798. * @member {PIXI.Point}
  6799. */
  6800. this.skew = new math.Point(0, 0);
  6801. /**
  6802. * The rotation of the object in radians.
  6803. *
  6804. * @member {number}
  6805. */
  6806. this.rotation = 0;
  6807. /**
  6808. * The opacity of the object.
  6809. *
  6810. * @member {number}
  6811. */
  6812. this.alpha = 1;
  6813. /**
  6814. * The visibility of the object. If false the object will not be drawn, and
  6815. * the updateTransform function will not be called.
  6816. *
  6817. * @member {boolean}
  6818. */
  6819. this.visible = true;
  6820. /**
  6821. * Can this object be rendered, if false the object will not be drawn but the updateTransform
  6822. * methods will still be called.
  6823. *
  6824. * @member {boolean}
  6825. */
  6826. this.renderable = true;
  6827. /**
  6828. * The display object container that contains this display object.
  6829. *
  6830. * @member {PIXI.Container}
  6831. * @readOnly
  6832. */
  6833. this.parent = null;
  6834. /**
  6835. * The multiplied alpha of the displayObject
  6836. *
  6837. * @member {number}
  6838. * @readOnly
  6839. */
  6840. this.worldAlpha = 1;
  6841. /**
  6842. * Current transform of the object based on world (parent) factors
  6843. *
  6844. * @member {PIXI.Matrix}
  6845. * @readOnly
  6846. */
  6847. this.worldTransform = new math.Matrix();
  6848. /**
  6849. * The area the filter is applied to. This is used as more of an optimisation
  6850. * rather than figuring out the dimensions of the displayObject each frame you can set this rectangle
  6851. *
  6852. * @member {PIXI.Rectangle}
  6853. */
  6854. this.filterArea = null;
  6855. /**
  6856. * cached sin rotation
  6857. *
  6858. * @member {number}
  6859. * @private
  6860. */
  6861. this._sr = 0;
  6862. /**
  6863. * cached cos rotation
  6864. *
  6865. * @member {number}
  6866. * @private
  6867. */
  6868. this._cr = 1;
  6869. /**
  6870. * The original, cached bounds of the object
  6871. *
  6872. * @member {PIXI.Rectangle}
  6873. * @private
  6874. */
  6875. this._bounds = new math.Rectangle(0, 0, 1, 1);
  6876. /**
  6877. * The most up-to-date bounds of the object
  6878. *
  6879. * @member {PIXI.Rectangle}
  6880. * @private
  6881. */
  6882. this._currentBounds = null;
  6883. /**
  6884. * The original, cached mask of the object
  6885. *
  6886. * @member {PIXI.Rectangle}
  6887. * @private
  6888. */
  6889. this._mask = null;
  6890. }
  6891. // constructor
  6892. DisplayObject.prototype = Object.create(EventEmitter.prototype);
  6893. DisplayObject.prototype.constructor = DisplayObject;
  6894. module.exports = DisplayObject;
  6895. Object.defineProperties(DisplayObject.prototype, {
  6896. /**
  6897. * The position of the displayObject on the x axis relative to the local coordinates of the parent.
  6898. *
  6899. * @member {number}
  6900. * @memberof PIXI.DisplayObject#
  6901. */
  6902. x: {
  6903. get: function ()
  6904. {
  6905. return this.position.x;
  6906. },
  6907. set: function (value)
  6908. {
  6909. this.position.x = value;
  6910. }
  6911. },
  6912. /**
  6913. * The position of the displayObject on the y axis relative to the local coordinates of the parent.
  6914. *
  6915. * @member {number}
  6916. * @memberof PIXI.DisplayObject#
  6917. */
  6918. y: {
  6919. get: function ()
  6920. {
  6921. return this.position.y;
  6922. },
  6923. set: function (value)
  6924. {
  6925. this.position.y = value;
  6926. }
  6927. },
  6928. /**
  6929. * Indicates if the sprite is globally visible.
  6930. *
  6931. * @member {boolean}
  6932. * @memberof PIXI.DisplayObject#
  6933. * @readonly
  6934. */
  6935. worldVisible: {
  6936. get: function ()
  6937. {
  6938. var item = this;
  6939. do {
  6940. if (!item.visible)
  6941. {
  6942. return false;
  6943. }
  6944. item = item.parent;
  6945. } while (item);
  6946. return true;
  6947. }
  6948. },
  6949. /**
  6950. * Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it.
  6951. * In PIXI a regular mask must be a PIXI.Graphics or a PIXI.Sprite object. This allows for much faster masking in canvas as it utilises shape clipping.
  6952. * To remove a mask, set this property to null.
  6953. *
  6954. * @todo For the moment, PIXI.CanvasRenderer doesn't support PIXI.Sprite as mask.
  6955. *
  6956. * @member {PIXI.Graphics|PIXI.Sprite}
  6957. * @memberof PIXI.DisplayObject#
  6958. */
  6959. mask: {
  6960. get: function ()
  6961. {
  6962. return this._mask;
  6963. },
  6964. set: function (value)
  6965. {
  6966. if (this._mask)
  6967. {
  6968. this._mask.renderable = true;
  6969. }
  6970. this._mask = value;
  6971. if (this._mask)
  6972. {
  6973. this._mask.renderable = false;
  6974. }
  6975. }
  6976. },
  6977. /**
  6978. * Sets the filters for the displayObject.
  6979. * * IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer.
  6980. * To remove filters simply set this property to 'null'
  6981. *
  6982. * @member {PIXI.AbstractFilter[]}
  6983. * @memberof PIXI.DisplayObject#
  6984. */
  6985. filters: {
  6986. get: function ()
  6987. {
  6988. return this._filters && this._filters.slice();
  6989. },
  6990. set: function (value)
  6991. {
  6992. this._filters = value && value.slice();
  6993. }
  6994. }
  6995. });
  6996. /*
  6997. * Updates the object transform for rendering
  6998. *
  6999. * TODO - Optimization pass!
  7000. */
  7001. DisplayObject.prototype.updateTransform = function ()
  7002. {
  7003. // create some matrix refs for easy access
  7004. var pt = this.parent.worldTransform;
  7005. var wt = this.worldTransform;
  7006. // temporary matrix variables
  7007. var a, b, c, d, tx, ty;
  7008. // looks like we are skewing
  7009. if(this.skew.x || this.skew.y)
  7010. {
  7011. // I'm assuming that skewing is not going to be very common
  7012. // With that in mind, we can do a full setTransform using the temp matrix
  7013. _tempMatrix.setTransform(
  7014. this.position.x,
  7015. this.position.y,
  7016. this.pivot.x,
  7017. this.pivot.y,
  7018. this.scale.x,
  7019. this.scale.y,
  7020. this.rotation,
  7021. this.skew.x,
  7022. this.skew.y
  7023. );
  7024. // now concat the matrix (inlined so that we can avoid using copy)
  7025. wt.a = _tempMatrix.a * pt.a + _tempMatrix.b * pt.c;
  7026. wt.b = _tempMatrix.a * pt.b + _tempMatrix.b * pt.d;
  7027. wt.c = _tempMatrix.c * pt.a + _tempMatrix.d * pt.c;
  7028. wt.d = _tempMatrix.c * pt.b + _tempMatrix.d * pt.d;
  7029. wt.tx = _tempMatrix.tx * pt.a + _tempMatrix.ty * pt.c + pt.tx;
  7030. wt.ty = _tempMatrix.tx * pt.b + _tempMatrix.ty * pt.d + pt.ty;
  7031. }
  7032. else
  7033. {
  7034. // so if rotation is between 0 then we can simplify the multiplication process...
  7035. if (this.rotation % CONST.PI_2)
  7036. {
  7037. // check to see if the rotation is the same as the previous render. This means we only need to use sin and cos when rotation actually changes
  7038. if (this.rotation !== this.rotationCache)
  7039. {
  7040. this.rotationCache = this.rotation;
  7041. this._sr = Math.sin(this.rotation);
  7042. this._cr = Math.cos(this.rotation);
  7043. }
  7044. // get the matrix values of the displayobject based on its transform properties..
  7045. a = this._cr * this.scale.x;
  7046. b = this._sr * this.scale.x;
  7047. c = -this._sr * this.scale.y;
  7048. d = this._cr * this.scale.y;
  7049. tx = this.position.x;
  7050. ty = this.position.y;
  7051. // check for pivot.. not often used so geared towards that fact!
  7052. if (this.pivot.x || this.pivot.y)
  7053. {
  7054. tx -= this.pivot.x * a + this.pivot.y * c;
  7055. ty -= this.pivot.x * b + this.pivot.y * d;
  7056. }
  7057. // concat the parent matrix with the objects transform.
  7058. wt.a = a * pt.a + b * pt.c;
  7059. wt.b = a * pt.b + b * pt.d;
  7060. wt.c = c * pt.a + d * pt.c;
  7061. wt.d = c * pt.b + d * pt.d;
  7062. wt.tx = tx * pt.a + ty * pt.c + pt.tx;
  7063. wt.ty = tx * pt.b + ty * pt.d + pt.ty;
  7064. }
  7065. else
  7066. {
  7067. // lets do the fast version as we know there is no rotation..
  7068. a = this.scale.x;
  7069. d = this.scale.y;
  7070. tx = this.position.x - this.pivot.x * a;
  7071. ty = this.position.y - this.pivot.y * d;
  7072. wt.a = a * pt.a;
  7073. wt.b = a * pt.b;
  7074. wt.c = d * pt.c;
  7075. wt.d = d * pt.d;
  7076. wt.tx = tx * pt.a + ty * pt.c + pt.tx;
  7077. wt.ty = tx * pt.b + ty * pt.d + pt.ty;
  7078. }
  7079. }
  7080. // multiply the alphas..
  7081. this.worldAlpha = this.alpha * this.parent.worldAlpha;
  7082. // reset the bounds each time this is called!
  7083. this._currentBounds = null;
  7084. };
  7085. // performance increase to avoid using call.. (10x faster)
  7086. DisplayObject.prototype.displayObjectUpdateTransform = DisplayObject.prototype.updateTransform;
  7087. /**
  7088. *
  7089. *
  7090. * Retrieves the bounds of the displayObject as a rectangle object
  7091. *
  7092. * @param matrix {PIXI.Matrix}
  7093. * @return {PIXI.Rectangle} the rectangular bounding area
  7094. */
  7095. DisplayObject.prototype.getBounds = function (matrix) // jshint unused:false
  7096. {
  7097. return math.Rectangle.EMPTY;
  7098. };
  7099. /**
  7100. * Retrieves the local bounds of the displayObject as a rectangle object
  7101. *
  7102. * @return {PIXI.Rectangle} the rectangular bounding area
  7103. */
  7104. DisplayObject.prototype.getLocalBounds = function ()
  7105. {
  7106. return this.getBounds(math.Matrix.IDENTITY);
  7107. };
  7108. /**
  7109. * Calculates the global position of the display object
  7110. *
  7111. * @param position {PIXI.Point} The world origin to calculate from
  7112. * @return {PIXI.Point} A point object representing the position of this object
  7113. */
  7114. DisplayObject.prototype.toGlobal = function (position)
  7115. {
  7116. // this parent check is for just in case the item is a root object.
  7117. // If it is we need to give it a temporary parent so that displayObjectUpdateTransform works correctly
  7118. // this is mainly to avoid a parent check in the main loop. Every little helps for performance :)
  7119. if(!this.parent)
  7120. {
  7121. this.parent = _tempDisplayObjectParent;
  7122. this.displayObjectUpdateTransform();
  7123. this.parent = null;
  7124. }
  7125. else
  7126. {
  7127. this.displayObjectUpdateTransform();
  7128. }
  7129. // don't need to update the lot
  7130. return this.worldTransform.apply(position);
  7131. };
  7132. /**
  7133. * Calculates the local position of the display object relative to another point
  7134. *
  7135. * @param position {PIXI.Point} The world origin to calculate from
  7136. * @param [from] {PIXI.DisplayObject} The DisplayObject to calculate the global position from
  7137. * @param [point] {PIXI.Point} A Point object in which to store the value, optional (otherwise will create a new Point)
  7138. * @return {PIXI.Point} A point object representing the position of this object
  7139. */
  7140. DisplayObject.prototype.toLocal = function (position, from, point)
  7141. {
  7142. if (from)
  7143. {
  7144. position = from.toGlobal(position);
  7145. }
  7146. // this parent check is for just in case the item is a root object.
  7147. // If it is we need to give it a temporary parent so that displayObjectUpdateTransform works correctly
  7148. // this is mainly to avoid a parent check in the main loop. Every little helps for performance :)
  7149. if(!this.parent)
  7150. {
  7151. this.parent = _tempDisplayObjectParent;
  7152. this.displayObjectUpdateTransform();
  7153. this.parent = null;
  7154. }
  7155. else
  7156. {
  7157. this.displayObjectUpdateTransform();
  7158. }
  7159. // simply apply the matrix..
  7160. return this.worldTransform.applyInverse(position, point);
  7161. };
  7162. /**
  7163. * Renders the object using the WebGL renderer
  7164. *
  7165. * @param renderer {PIXI.WebGLRenderer} The renderer
  7166. * @private
  7167. */
  7168. DisplayObject.prototype.renderWebGL = function (renderer) // jshint unused:false
  7169. {
  7170. // OVERWRITE;
  7171. };
  7172. /**
  7173. * Renders the object using the Canvas renderer
  7174. *
  7175. * @param renderer {PIXI.CanvasRenderer} The renderer
  7176. * @private
  7177. */
  7178. DisplayObject.prototype.renderCanvas = function (renderer) // jshint unused:false
  7179. {
  7180. // OVERWRITE;
  7181. };
  7182. /**
  7183. * Useful function that returns a texture of the display object that can then be used to create sprites
  7184. * This can be quite useful if your displayObject is static / complicated and needs to be reused multiple times.
  7185. *
  7186. * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} The renderer used to generate the texture.
  7187. * @param scaleMode {number} See {@link PIXI.SCALE_MODES} for possible values
  7188. * @param resolution {number} The resolution of the texture being generated
  7189. * @return {PIXI.Texture} a texture of the display object
  7190. */
  7191. DisplayObject.prototype.generateTexture = function (renderer, scaleMode, resolution)
  7192. {
  7193. var bounds = this.getLocalBounds();
  7194. var renderTexture = new RenderTexture(renderer, bounds.width | 0, bounds.height | 0, scaleMode, resolution);
  7195. _tempMatrix.tx = -bounds.x;
  7196. _tempMatrix.ty = -bounds.y;
  7197. renderTexture.render(this, _tempMatrix);
  7198. return renderTexture;
  7199. };
  7200. /**
  7201. * Set the parent Container of this DisplayObject
  7202. *
  7203. * @param container {Container} The Container to add this DisplayObject to
  7204. * @return {Container} The Container that this DisplayObject was added to
  7205. */
  7206. DisplayObject.prototype.setParent = function (container)
  7207. {
  7208. if (!container || !container.addChild)
  7209. {
  7210. throw new Error('setParent: Argument must be a Container');
  7211. }
  7212. container.addChild(this);
  7213. return container;
  7214. };
  7215. /**
  7216. * Convenience function to set the postion, scale, skew and pivot at once.
  7217. *
  7218. * @param [x=0] {number} The X position
  7219. * @param [y=0] {number} The Y position
  7220. * @param [scaleX=1] {number} The X scale value
  7221. * @param [scaleY=1] {number} The Y scale value
  7222. * @param [rotation=0] {number} The rotation
  7223. * @param [skewX=0] {number} The X skew value
  7224. * @param [skewY=0] {number} The Y skew value
  7225. * @param [pivotX=0] {number} The X pivot value
  7226. * @param [pivotY=0] {number} The Y pivot value
  7227. * @return {PIXI.DisplayObject}
  7228. */
  7229. DisplayObject.prototype.setTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, pivotX, pivotY) //jshint ignore:line
  7230. {
  7231. this.position.x = x || 0;
  7232. this.position.y = y || 0;
  7233. this.scale.x = !scaleX ? 1 : scaleX;
  7234. this.scale.y = !scaleY ? 1 : scaleY;
  7235. this.rotation = rotation || 0;
  7236. this.skew.x = skewX || 0;
  7237. this.skew.y = skewY || 0;
  7238. this.pivot.x = pivotX || 0;
  7239. this.pivot.y = pivotY || 0;
  7240. return this;
  7241. };
  7242. /**
  7243. * Base destroy method for generic display objects
  7244. *
  7245. */
  7246. DisplayObject.prototype.destroy = function ()
  7247. {
  7248. this.position = null;
  7249. this.scale = null;
  7250. this.pivot = null;
  7251. this.skew = null;
  7252. this.parent = null;
  7253. this._bounds = null;
  7254. this._currentBounds = null;
  7255. this._mask = null;
  7256. this.worldTransform = null;
  7257. this.filterArea = null;
  7258. };
  7259. },{"../const":22,"../math":33,"../textures/RenderTexture":71,"eventemitter3":10}],25:[function(require,module,exports){
  7260. var Container = require('../display/Container'),
  7261. Texture = require('../textures/Texture'),
  7262. CanvasBuffer = require('../renderers/canvas/utils/CanvasBuffer'),
  7263. CanvasGraphics = require('../renderers/canvas/utils/CanvasGraphics'),
  7264. GraphicsData = require('./GraphicsData'),
  7265. math = require('../math'),
  7266. CONST = require('../const'),
  7267. tempPoint = new math.Point();
  7268. /**
  7269. * The Graphics class contains methods used to draw primitive shapes such as lines, circles and
  7270. * rectangles to the display, and to color and fill them.
  7271. *
  7272. * @class
  7273. * @extends PIXI.Container
  7274. * @memberof PIXI
  7275. */
  7276. function Graphics()
  7277. {
  7278. Container.call(this);
  7279. /**
  7280. * The alpha value used when filling the Graphics object.
  7281. *
  7282. * @member {number}
  7283. * @default 1
  7284. */
  7285. this.fillAlpha = 1;
  7286. /**
  7287. * The width (thickness) of any lines drawn.
  7288. *
  7289. * @member {number}
  7290. * @default 0
  7291. */
  7292. this.lineWidth = 0;
  7293. /**
  7294. * The color of any lines drawn.
  7295. *
  7296. * @member {string}
  7297. * @default 0
  7298. */
  7299. this.lineColor = 0;
  7300. /**
  7301. * Graphics data
  7302. *
  7303. * @member {PIXI.GraphicsData[]}
  7304. * @private
  7305. */
  7306. this.graphicsData = [];
  7307. /**
  7308. * The tint applied to the graphic shape. This is a hex value. Apply a value of 0xFFFFFF to reset the tint.
  7309. *
  7310. * @member {number}
  7311. * @default 0xFFFFFF
  7312. */
  7313. this.tint = 0xFFFFFF;
  7314. /**
  7315. * The previous tint applied to the graphic shape. Used to compare to the current tint and check if theres change.
  7316. *
  7317. * @member {number}
  7318. * @private
  7319. * @default 0xFFFFFF
  7320. */
  7321. this._prevTint = 0xFFFFFF;
  7322. /**
  7323. * The blend mode to be applied to the graphic shape. Apply a value of `PIXI.BLEND_MODES.NORMAL` to reset the blend mode.
  7324. *
  7325. * @member {number}
  7326. * @default PIXI.BLEND_MODES.NORMAL;
  7327. * @see PIXI.BLEND_MODES
  7328. */
  7329. this.blendMode = CONST.BLEND_MODES.NORMAL;
  7330. /**
  7331. * Current path
  7332. *
  7333. * @member {PIXI.GraphicsData}
  7334. * @private
  7335. */
  7336. this.currentPath = null;
  7337. /**
  7338. * Array containing some WebGL-related properties used by the WebGL renderer.
  7339. *
  7340. * @member {object<number, object>}
  7341. * @private
  7342. */
  7343. // TODO - _webgl should use a prototype object, not a random undocumented object...
  7344. this._webGL = {};
  7345. /**
  7346. * Whether this shape is being used as a mask.
  7347. *
  7348. * @member {boolean}
  7349. */
  7350. this.isMask = false;
  7351. /**
  7352. * The bounds' padding used for bounds calculation.
  7353. *
  7354. * @member {number}
  7355. */
  7356. this.boundsPadding = 0;
  7357. /**
  7358. * A cache of the local bounds to prevent recalculation.
  7359. *
  7360. * @member {PIXI.Rectangle}
  7361. * @private
  7362. */
  7363. this._localBounds = new math.Rectangle(0,0,1,1);
  7364. /**
  7365. * Used to detect if the graphics object has changed. If this is set to true then the graphics
  7366. * object will be recalculated.
  7367. *
  7368. * @member {boolean}
  7369. * @private
  7370. */
  7371. this.dirty = true;
  7372. /**
  7373. * Used to detect if the WebGL graphics object has changed. If this is set to true then the
  7374. * graphics object will be recalculated.
  7375. *
  7376. * @member {boolean}
  7377. * @private
  7378. */
  7379. this.glDirty = false;
  7380. this.boundsDirty = true;
  7381. /**
  7382. * Used to detect if the cached sprite object needs to be updated.
  7383. *
  7384. * @member {boolean}
  7385. * @private
  7386. */
  7387. this.cachedSpriteDirty = false;
  7388. /**
  7389. * When cacheAsBitmap is set to true the graphics object will be rendered as if it was a sprite.
  7390. * This is useful if your graphics element does not change often, as it will speed up the rendering
  7391. * of the object in exchange for taking up texture memory. It is also useful if you need the graphics
  7392. * object to be anti-aliased, because it will be rendered using canvas. This is not recommended if
  7393. * you are constantly redrawing the graphics element.
  7394. *
  7395. * @name cacheAsBitmap
  7396. * @member {boolean}
  7397. * @memberof PIXI.Graphics#
  7398. * @default false
  7399. */
  7400. }
  7401. // constructor
  7402. Graphics.prototype = Object.create(Container.prototype);
  7403. Graphics.prototype.constructor = Graphics;
  7404. module.exports = Graphics;
  7405. /**
  7406. * Creates a new Graphics object with the same values as this one.
  7407. * Note that the only the properties of the object are cloned, not its transform (position,scale,etc)
  7408. *
  7409. * @return {PIXI.Graphics}
  7410. */
  7411. Graphics.prototype.clone = function ()
  7412. {
  7413. var clone = new Graphics();
  7414. clone.renderable = this.renderable;
  7415. clone.fillAlpha = this.fillAlpha;
  7416. clone.lineWidth = this.lineWidth;
  7417. clone.lineColor = this.lineColor;
  7418. clone.tint = this.tint;
  7419. clone.blendMode = this.blendMode;
  7420. clone.isMask = this.isMask;
  7421. clone.boundsPadding = this.boundsPadding;
  7422. clone.dirty = true;
  7423. clone.glDirty = true;
  7424. clone.cachedSpriteDirty = this.cachedSpriteDirty;
  7425. // copy graphics data
  7426. for (var i = 0; i < this.graphicsData.length; ++i)
  7427. {
  7428. clone.graphicsData.push(this.graphicsData[i].clone());
  7429. }
  7430. clone.currentPath = clone.graphicsData[clone.graphicsData.length - 1];
  7431. clone.updateLocalBounds();
  7432. return clone;
  7433. };
  7434. /**
  7435. * Specifies the line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method.
  7436. *
  7437. * @param lineWidth {number} width of the line to draw, will update the objects stored style
  7438. * @param color {number} color of the line to draw, will update the objects stored style
  7439. * @param alpha {number} alpha of the line to draw, will update the objects stored style
  7440. * @return {PIXI.Graphics}
  7441. */
  7442. Graphics.prototype.lineStyle = function (lineWidth, color, alpha)
  7443. {
  7444. this.lineWidth = lineWidth || 0;
  7445. this.lineColor = color || 0;
  7446. this.lineAlpha = (alpha === undefined) ? 1 : alpha;
  7447. if (this.currentPath)
  7448. {
  7449. if (this.currentPath.shape.points.length)
  7450. {
  7451. // halfway through a line? start a new one!
  7452. var shape = new math.Polygon(this.currentPath.shape.points.slice(-2));
  7453. shape.closed = false;
  7454. this.drawShape(shape);
  7455. }
  7456. else
  7457. {
  7458. // otherwise its empty so lets just set the line properties
  7459. this.currentPath.lineWidth = this.lineWidth;
  7460. this.currentPath.lineColor = this.lineColor;
  7461. this.currentPath.lineAlpha = this.lineAlpha;
  7462. }
  7463. }
  7464. return this;
  7465. };
  7466. /**
  7467. * Moves the current drawing position to x, y.
  7468. *
  7469. * @param x {number} the X coordinate to move to
  7470. * @param y {number} the Y coordinate to move to
  7471. * @return {PIXI.Graphics}
  7472. */
  7473. Graphics.prototype.moveTo = function (x, y)
  7474. {
  7475. var shape = new math.Polygon([x,y]);
  7476. shape.closed = false;
  7477. this.drawShape(shape);
  7478. return this;
  7479. };
  7480. /**
  7481. * Draws a line using the current line style from the current drawing position to (x, y);
  7482. * The current drawing position is then set to (x, y).
  7483. *
  7484. * @param x {number} the X coordinate to draw to
  7485. * @param y {number} the Y coordinate to draw to
  7486. * @return {PIXI.Graphics}
  7487. */
  7488. Graphics.prototype.lineTo = function (x, y)
  7489. {
  7490. this.currentPath.shape.points.push(x, y);
  7491. this.dirty = true;
  7492. return this;
  7493. };
  7494. /**
  7495. * Calculate the points for a quadratic bezier curve and then draws it.
  7496. * Based on: https://stackoverflow.com/questions/785097/how-do-i-implement-a-bezier-curve-in-c
  7497. *
  7498. * @param cpX {number} Control point x
  7499. * @param cpY {number} Control point y
  7500. * @param toX {number} Destination point x
  7501. * @param toY {number} Destination point y
  7502. * @return {PIXI.Graphics}
  7503. */
  7504. Graphics.prototype.quadraticCurveTo = function (cpX, cpY, toX, toY)
  7505. {
  7506. if (this.currentPath)
  7507. {
  7508. if (this.currentPath.shape.points.length === 0)
  7509. {
  7510. this.currentPath.shape.points = [0, 0];
  7511. }
  7512. }
  7513. else
  7514. {
  7515. this.moveTo(0,0);
  7516. }
  7517. var xa,
  7518. ya,
  7519. n = 20,
  7520. points = this.currentPath.shape.points;
  7521. if (points.length === 0)
  7522. {
  7523. this.moveTo(0, 0);
  7524. }
  7525. var fromX = points[points.length-2];
  7526. var fromY = points[points.length-1];
  7527. var j = 0;
  7528. for (var i = 1; i <= n; ++i)
  7529. {
  7530. j = i / n;
  7531. xa = fromX + ( (cpX - fromX) * j );
  7532. ya = fromY + ( (cpY - fromY) * j );
  7533. points.push( xa + ( ((cpX + ( (toX - cpX) * j )) - xa) * j ),
  7534. ya + ( ((cpY + ( (toY - cpY) * j )) - ya) * j ) );
  7535. }
  7536. this.dirty = this.boundsDirty = true;
  7537. return this;
  7538. };
  7539. /**
  7540. * Calculate the points for a bezier curve and then draws it.
  7541. *
  7542. * @param cpX {number} Control point x
  7543. * @param cpY {number} Control point y
  7544. * @param cpX2 {number} Second Control point x
  7545. * @param cpY2 {number} Second Control point y
  7546. * @param toX {number} Destination point x
  7547. * @param toY {number} Destination point y
  7548. * @return {PIXI.Graphics}
  7549. */
  7550. Graphics.prototype.bezierCurveTo = function (cpX, cpY, cpX2, cpY2, toX, toY)
  7551. {
  7552. if (this.currentPath)
  7553. {
  7554. if (this.currentPath.shape.points.length === 0)
  7555. {
  7556. this.currentPath.shape.points = [0, 0];
  7557. }
  7558. }
  7559. else
  7560. {
  7561. this.moveTo(0,0);
  7562. }
  7563. var n = 20,
  7564. dt,
  7565. dt2,
  7566. dt3,
  7567. t2,
  7568. t3,
  7569. points = this.currentPath.shape.points;
  7570. var fromX = points[points.length-2];
  7571. var fromY = points[points.length-1];
  7572. var j = 0;
  7573. for (var i = 1; i <= n; ++i)
  7574. {
  7575. j = i / n;
  7576. dt = (1 - j);
  7577. dt2 = dt * dt;
  7578. dt3 = dt2 * dt;
  7579. t2 = j * j;
  7580. t3 = t2 * j;
  7581. points.push( dt3 * fromX + 3 * dt2 * j * cpX + 3 * dt * t2 * cpX2 + t3 * toX,
  7582. dt3 * fromY + 3 * dt2 * j * cpY + 3 * dt * t2 * cpY2 + t3 * toY);
  7583. }
  7584. this.dirty = this.boundsDirty = true;
  7585. return this;
  7586. };
  7587. /**
  7588. * The arcTo() method creates an arc/curve between two tangents on the canvas.
  7589. *
  7590. * "borrowed" from https://code.google.com/p/fxcanvas/ - thanks google!
  7591. *
  7592. * @param x1 {number} The x-coordinate of the beginning of the arc
  7593. * @param y1 {number} The y-coordinate of the beginning of the arc
  7594. * @param x2 {number} The x-coordinate of the end of the arc
  7595. * @param y2 {number} The y-coordinate of the end of the arc
  7596. * @param radius {number} The radius of the arc
  7597. * @return {PIXI.Graphics}
  7598. */
  7599. Graphics.prototype.arcTo = function (x1, y1, x2, y2, radius)
  7600. {
  7601. if (this.currentPath)
  7602. {
  7603. if (this.currentPath.shape.points.length === 0)
  7604. {
  7605. this.currentPath.shape.points.push(x1, y1);
  7606. }
  7607. }
  7608. else
  7609. {
  7610. this.moveTo(x1, y1);
  7611. }
  7612. var points = this.currentPath.shape.points,
  7613. fromX = points[points.length-2],
  7614. fromY = points[points.length-1],
  7615. a1 = fromY - y1,
  7616. b1 = fromX - x1,
  7617. a2 = y2 - y1,
  7618. b2 = x2 - x1,
  7619. mm = Math.abs(a1 * b2 - b1 * a2);
  7620. if (mm < 1.0e-8 || radius === 0)
  7621. {
  7622. if (points[points.length-2] !== x1 || points[points.length-1] !== y1)
  7623. {
  7624. points.push(x1, y1);
  7625. }
  7626. }
  7627. else
  7628. {
  7629. var dd = a1 * a1 + b1 * b1,
  7630. cc = a2 * a2 + b2 * b2,
  7631. tt = a1 * a2 + b1 * b2,
  7632. k1 = radius * Math.sqrt(dd) / mm,
  7633. k2 = radius * Math.sqrt(cc) / mm,
  7634. j1 = k1 * tt / dd,
  7635. j2 = k2 * tt / cc,
  7636. cx = k1 * b2 + k2 * b1,
  7637. cy = k1 * a2 + k2 * a1,
  7638. px = b1 * (k2 + j1),
  7639. py = a1 * (k2 + j1),
  7640. qx = b2 * (k1 + j2),
  7641. qy = a2 * (k1 + j2),
  7642. startAngle = Math.atan2(py - cy, px - cx),
  7643. endAngle = Math.atan2(qy - cy, qx - cx);
  7644. this.arc(cx + x1, cy + y1, radius, startAngle, endAngle, b1 * a2 > b2 * a1);
  7645. }
  7646. this.dirty = this.boundsDirty = true;
  7647. return this;
  7648. };
  7649. /**
  7650. * The arc method creates an arc/curve (used to create circles, or parts of circles).
  7651. *
  7652. * @param cx {number} The x-coordinate of the center of the circle
  7653. * @param cy {number} The y-coordinate of the center of the circle
  7654. * @param radius {number} The radius of the circle
  7655. * @param startAngle {number} The starting angle, in radians (0 is at the 3 o'clock position of the arc's circle)
  7656. * @param endAngle {number} The ending angle, in radians
  7657. * @param anticlockwise {boolean} Optional. Specifies whether the drawing should be counterclockwise or clockwise. False is default, and indicates clockwise, while true indicates counter-clockwise.
  7658. * @return {PIXI.Graphics}
  7659. */
  7660. Graphics.prototype.arc = function(cx, cy, radius, startAngle, endAngle, anticlockwise)
  7661. {
  7662. anticlockwise = anticlockwise || false;
  7663. if (startAngle === endAngle)
  7664. {
  7665. return this;
  7666. }
  7667. if( !anticlockwise && endAngle <= startAngle )
  7668. {
  7669. endAngle += Math.PI * 2;
  7670. }
  7671. else if( anticlockwise && startAngle <= endAngle )
  7672. {
  7673. startAngle += Math.PI * 2;
  7674. }
  7675. var sweep = anticlockwise ? (startAngle - endAngle) * -1 : (endAngle - startAngle);
  7676. var segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40;
  7677. if(sweep === 0)
  7678. {
  7679. return this;
  7680. }
  7681. var startX = cx + Math.cos(startAngle) * radius;
  7682. var startY = cy + Math.sin(startAngle) * radius;
  7683. if (this.currentPath)
  7684. {
  7685. this.currentPath.shape.points.push(startX, startY);
  7686. }
  7687. else
  7688. {
  7689. this.moveTo(startX, startY);
  7690. }
  7691. var points = this.currentPath.shape.points;
  7692. var theta = sweep/(segs*2);
  7693. var theta2 = theta*2;
  7694. var cTheta = Math.cos(theta);
  7695. var sTheta = Math.sin(theta);
  7696. var segMinus = segs - 1;
  7697. var remainder = ( segMinus % 1 ) / segMinus;
  7698. for(var i=0; i<=segMinus; i++)
  7699. {
  7700. var real = i + remainder * i;
  7701. var angle = ((theta) + startAngle + (theta2 * real));
  7702. var c = Math.cos(angle);
  7703. var s = -Math.sin(angle);
  7704. points.push(( (cTheta * c) + (sTheta * s) ) * radius + cx,
  7705. ( (cTheta * -s) + (sTheta * c) ) * radius + cy);
  7706. }
  7707. this.dirty = this.boundsDirty = true;
  7708. return this;
  7709. };
  7710. /**
  7711. * Specifies a simple one-color fill that subsequent calls to other Graphics methods
  7712. * (such as lineTo() or drawCircle()) use when drawing.
  7713. *
  7714. * @param color {number} the color of the fill
  7715. * @param alpha {number} the alpha of the fill
  7716. * @return {PIXI.Graphics}
  7717. */
  7718. Graphics.prototype.beginFill = function (color, alpha)
  7719. {
  7720. this.filling = true;
  7721. this.fillColor = color || 0;
  7722. this.fillAlpha = (alpha === undefined) ? 1 : alpha;
  7723. if (this.currentPath)
  7724. {
  7725. if (this.currentPath.shape.points.length <= 2)
  7726. {
  7727. this.currentPath.fill = this.filling;
  7728. this.currentPath.fillColor = this.fillColor;
  7729. this.currentPath.fillAlpha = this.fillAlpha;
  7730. }
  7731. }
  7732. return this;
  7733. };
  7734. /**
  7735. * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method.
  7736. *
  7737. * @return {Graphics}
  7738. */
  7739. Graphics.prototype.endFill = function ()
  7740. {
  7741. this.filling = false;
  7742. this.fillColor = null;
  7743. this.fillAlpha = 1;
  7744. return this;
  7745. };
  7746. /**
  7747. *
  7748. * @param x {number} The X coord of the top-left of the rectangle
  7749. * @param y {number} The Y coord of the top-left of the rectangle
  7750. * @param width {number} The width of the rectangle
  7751. * @param height {number} The height of the rectangle
  7752. * @return {PIXI.Graphics}
  7753. */
  7754. Graphics.prototype.drawRect = function ( x, y, width, height )
  7755. {
  7756. this.drawShape(new math.Rectangle(x,y, width, height));
  7757. return this;
  7758. };
  7759. /**
  7760. *
  7761. * @param x {number} The X coord of the top-left of the rectangle
  7762. * @param y {number} The Y coord of the top-left of the rectangle
  7763. * @param width {number} The width of the rectangle
  7764. * @param height {number} The height of the rectangle
  7765. * @param radius {number} Radius of the rectangle corners
  7766. * @return {PIXI.Graphics}
  7767. */
  7768. Graphics.prototype.drawRoundedRect = function ( x, y, width, height, radius )
  7769. {
  7770. this.drawShape(new math.RoundedRectangle(x, y, width, height, radius));
  7771. return this;
  7772. };
  7773. /**
  7774. * Draws a circle.
  7775. *
  7776. * @param x {number} The X coordinate of the center of the circle
  7777. * @param y {number} The Y coordinate of the center of the circle
  7778. * @param radius {number} The radius of the circle
  7779. * @return {PIXI.Graphics}
  7780. */
  7781. Graphics.prototype.drawCircle = function (x, y, radius)
  7782. {
  7783. this.drawShape(new math.Circle(x,y, radius));
  7784. return this;
  7785. };
  7786. /**
  7787. * Draws an ellipse.
  7788. *
  7789. * @param x {number} The X coordinate of the center of the ellipse
  7790. * @param y {number} The Y coordinate of the center of the ellipse
  7791. * @param width {number} The half width of the ellipse
  7792. * @param height {number} The half height of the ellipse
  7793. * @return {PIXI.Graphics}
  7794. */
  7795. Graphics.prototype.drawEllipse = function (x, y, width, height)
  7796. {
  7797. this.drawShape(new math.Ellipse(x, y, width, height));
  7798. return this;
  7799. };
  7800. /**
  7801. * Draws a polygon using the given path.
  7802. *
  7803. * @param path {number[]|PIXI.Point[]} The path data used to construct the polygon.
  7804. * @return {PIXI.Graphics}
  7805. */
  7806. Graphics.prototype.drawPolygon = function (path)
  7807. {
  7808. // prevents an argument assignment deopt
  7809. // see section 3.1: https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments
  7810. var points = path;
  7811. var closed = true;
  7812. if (points instanceof math.Polygon)
  7813. {
  7814. closed = points.closed;
  7815. points = points.points;
  7816. }
  7817. if (!Array.isArray(points))
  7818. {
  7819. // prevents an argument leak deopt
  7820. // see section 3.2: https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments
  7821. points = new Array(arguments.length);
  7822. for (var i = 0; i < points.length; ++i)
  7823. {
  7824. points[i] = arguments[i];
  7825. }
  7826. }
  7827. var shape = new math.Polygon(points);
  7828. shape.closed = closed;
  7829. this.drawShape(shape);
  7830. return this;
  7831. };
  7832. /**
  7833. * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings.
  7834. *
  7835. * @return {PIXI.Graphics}
  7836. */
  7837. Graphics.prototype.clear = function ()
  7838. {
  7839. this.lineWidth = 0;
  7840. this.filling = false;
  7841. this.dirty = true;
  7842. this.clearDirty = true;
  7843. this.graphicsData = [];
  7844. return this;
  7845. };
  7846. /**
  7847. * Useful function that returns a texture of the graphics object that can then be used to create sprites
  7848. * This can be quite useful if your geometry is complicated and needs to be reused multiple times.
  7849. *
  7850. * @param resolution {number} The resolution of the texture being generated
  7851. * @param scaleMode {number} Should be one of the scaleMode consts
  7852. * @return {PIXI.Texture} a texture of the graphics object
  7853. */
  7854. Graphics.prototype.generateTexture = function (renderer, resolution, scaleMode)
  7855. {
  7856. resolution = resolution || 1;
  7857. var bounds = this.getLocalBounds();
  7858. var canvasBuffer = new CanvasBuffer(bounds.width * resolution, bounds.height * resolution);
  7859. var texture = Texture.fromCanvas(canvasBuffer.canvas, scaleMode);
  7860. texture.baseTexture.resolution = resolution;
  7861. canvasBuffer.context.scale(resolution, resolution);
  7862. canvasBuffer.context.translate(-bounds.x,-bounds.y);
  7863. CanvasGraphics.renderGraphics(this, canvasBuffer.context);
  7864. return texture;
  7865. };
  7866. /**
  7867. * Renders the object using the WebGL renderer
  7868. *
  7869. * @param renderer {PIXI.WebGLRenderer}
  7870. * @private
  7871. */
  7872. Graphics.prototype._renderWebGL = function (renderer)
  7873. {
  7874. // if the sprite is not visible or the alpha is 0 then no need to render this element
  7875. // this code may still be needed so leaving for now..
  7876. //
  7877. /*
  7878. if (this._cacheAsBitmap)
  7879. {
  7880. if (this.dirty || this.cachedSpriteDirty)
  7881. {
  7882. this._generateCachedSprite();
  7883. // we will also need to update the texture on the gpu too!
  7884. this.updateCachedSpriteTexture();
  7885. this.cachedSpriteDirty = false;
  7886. this.dirty = false;
  7887. }
  7888. this._cachedSprite.worldAlpha = this.worldAlpha;
  7889. Sprite.prototype.renderWebGL.call(this._cachedSprite, renderer);
  7890. return;
  7891. }
  7892. */
  7893. if (this.glDirty)
  7894. {
  7895. this.dirty = true;
  7896. this.glDirty = false;
  7897. }
  7898. renderer.setObjectRenderer(renderer.plugins.graphics);
  7899. renderer.plugins.graphics.render(this);
  7900. };
  7901. /**
  7902. * Renders the object using the Canvas renderer
  7903. *
  7904. * @param renderer {PIXI.CanvasRenderer}
  7905. * @private
  7906. */
  7907. Graphics.prototype._renderCanvas = function (renderer)
  7908. {
  7909. if (this.isMask === true)
  7910. {
  7911. return;
  7912. }
  7913. // if the tint has changed, set the graphics object to dirty.
  7914. if (this._prevTint !== this.tint) {
  7915. this.dirty = true;
  7916. }
  7917. // this code may still be needed so leaving for now..
  7918. //
  7919. /*
  7920. if (this._cacheAsBitmap)
  7921. {
  7922. if (this.dirty || this.cachedSpriteDirty)
  7923. {
  7924. this._generateCachedSprite();
  7925. // we will also need to update the texture
  7926. this.updateCachedSpriteTexture();
  7927. this.cachedSpriteDirty = false;
  7928. this.dirty = false;
  7929. }
  7930. this._cachedSprite.alpha = this.alpha;
  7931. Sprite.prototype._renderCanvas.call(this._cachedSprite, renderer);
  7932. return;
  7933. }
  7934. */
  7935. var context = renderer.context;
  7936. var transform = this.worldTransform;
  7937. var compositeOperation = renderer.blendModes[this.blendMode];
  7938. if (compositeOperation !== context.globalCompositeOperation)
  7939. {
  7940. context.globalCompositeOperation = compositeOperation;
  7941. }
  7942. var resolution = renderer.resolution;
  7943. context.setTransform(
  7944. transform.a * resolution,
  7945. transform.b * resolution,
  7946. transform.c * resolution,
  7947. transform.d * resolution,
  7948. transform.tx * resolution,
  7949. transform.ty * resolution
  7950. );
  7951. CanvasGraphics.renderGraphics(this, context);
  7952. };
  7953. /**
  7954. * Retrieves the bounds of the graphic shape as a rectangle object
  7955. *
  7956. * @param [matrix] {PIXI.Matrix} The world transform matrix to use, defaults to this
  7957. * object's worldTransform.
  7958. * @return {PIXI.Rectangle} the rectangular bounding area
  7959. */
  7960. Graphics.prototype.getBounds = function (matrix)
  7961. {
  7962. if(!this._currentBounds)
  7963. {
  7964. // return an empty object if the item is a mask!
  7965. if (!this.renderable)
  7966. {
  7967. return math.Rectangle.EMPTY;
  7968. }
  7969. if (this.boundsDirty)
  7970. {
  7971. this.updateLocalBounds();
  7972. this.glDirty = true;
  7973. this.cachedSpriteDirty = true;
  7974. this.boundsDirty = false;
  7975. }
  7976. var bounds = this._localBounds;
  7977. var w0 = bounds.x;
  7978. var w1 = bounds.width + bounds.x;
  7979. var h0 = bounds.y;
  7980. var h1 = bounds.height + bounds.y;
  7981. var worldTransform = matrix || this.worldTransform;
  7982. var a = worldTransform.a;
  7983. var b = worldTransform.b;
  7984. var c = worldTransform.c;
  7985. var d = worldTransform.d;
  7986. var tx = worldTransform.tx;
  7987. var ty = worldTransform.ty;
  7988. var x1 = a * w1 + c * h1 + tx;
  7989. var y1 = d * h1 + b * w1 + ty;
  7990. var x2 = a * w0 + c * h1 + tx;
  7991. var y2 = d * h1 + b * w0 + ty;
  7992. var x3 = a * w0 + c * h0 + tx;
  7993. var y3 = d * h0 + b * w0 + ty;
  7994. var x4 = a * w1 + c * h0 + tx;
  7995. var y4 = d * h0 + b * w1 + ty;
  7996. var maxX = x1;
  7997. var maxY = y1;
  7998. var minX = x1;
  7999. var minY = y1;
  8000. minX = x2 < minX ? x2 : minX;
  8001. minX = x3 < minX ? x3 : minX;
  8002. minX = x4 < minX ? x4 : minX;
  8003. minY = y2 < minY ? y2 : minY;
  8004. minY = y3 < minY ? y3 : minY;
  8005. minY = y4 < minY ? y4 : minY;
  8006. maxX = x2 > maxX ? x2 : maxX;
  8007. maxX = x3 > maxX ? x3 : maxX;
  8008. maxX = x4 > maxX ? x4 : maxX;
  8009. maxY = y2 > maxY ? y2 : maxY;
  8010. maxY = y3 > maxY ? y3 : maxY;
  8011. maxY = y4 > maxY ? y4 : maxY;
  8012. this._bounds.x = minX;
  8013. this._bounds.width = maxX - minX;
  8014. this._bounds.y = minY;
  8015. this._bounds.height = maxY - minY;
  8016. this._currentBounds = this._bounds;
  8017. }
  8018. return this._currentBounds;
  8019. };
  8020. /**
  8021. * Tests if a point is inside this graphics object
  8022. *
  8023. * @param point {PIXI.Point} the point to test
  8024. * @return {boolean} the result of the test
  8025. */
  8026. Graphics.prototype.containsPoint = function( point )
  8027. {
  8028. this.worldTransform.applyInverse(point, tempPoint);
  8029. var graphicsData = this.graphicsData;
  8030. for (var i = 0; i < graphicsData.length; i++)
  8031. {
  8032. var data = graphicsData[i];
  8033. if (!data.fill)
  8034. {
  8035. continue;
  8036. }
  8037. // only deal with fills..
  8038. if (data.shape)
  8039. {
  8040. if ( data.shape.contains( tempPoint.x, tempPoint.y ) )
  8041. {
  8042. return true;
  8043. }
  8044. }
  8045. }
  8046. return false;
  8047. };
  8048. /**
  8049. * Update the bounds of the object
  8050. *
  8051. */
  8052. Graphics.prototype.updateLocalBounds = function ()
  8053. {
  8054. var minX = Infinity;
  8055. var maxX = -Infinity;
  8056. var minY = Infinity;
  8057. var maxY = -Infinity;
  8058. if (this.graphicsData.length)
  8059. {
  8060. var shape, points, x, y, w, h;
  8061. for (var i = 0; i < this.graphicsData.length; i++)
  8062. {
  8063. var data = this.graphicsData[i];
  8064. var type = data.type;
  8065. var lineWidth = data.lineWidth;
  8066. shape = data.shape;
  8067. if (type === CONST.SHAPES.RECT || type === CONST.SHAPES.RREC)
  8068. {
  8069. x = shape.x - lineWidth/2;
  8070. y = shape.y - lineWidth/2;
  8071. w = shape.width + lineWidth;
  8072. h = shape.height + lineWidth;
  8073. minX = x < minX ? x : minX;
  8074. maxX = x + w > maxX ? x + w : maxX;
  8075. minY = y < minY ? y : minY;
  8076. maxY = y + h > maxY ? y + h : maxY;
  8077. }
  8078. else if (type === CONST.SHAPES.CIRC)
  8079. {
  8080. x = shape.x;
  8081. y = shape.y;
  8082. w = shape.radius + lineWidth/2;
  8083. h = shape.radius + lineWidth/2;
  8084. minX = x - w < minX ? x - w : minX;
  8085. maxX = x + w > maxX ? x + w : maxX;
  8086. minY = y - h < minY ? y - h : minY;
  8087. maxY = y + h > maxY ? y + h : maxY;
  8088. }
  8089. else if (type === CONST.SHAPES.ELIP)
  8090. {
  8091. x = shape.x;
  8092. y = shape.y;
  8093. w = shape.width + lineWidth/2;
  8094. h = shape.height + lineWidth/2;
  8095. minX = x - w < minX ? x - w : minX;
  8096. maxX = x + w > maxX ? x + w : maxX;
  8097. minY = y - h < minY ? y - h : minY;
  8098. maxY = y + h > maxY ? y + h : maxY;
  8099. }
  8100. else
  8101. {
  8102. // POLY
  8103. points = shape.points;
  8104. for (var j = 0; j < points.length; j += 2)
  8105. {
  8106. x = points[j];
  8107. y = points[j+1];
  8108. minX = x-lineWidth < minX ? x-lineWidth : minX;
  8109. maxX = x+lineWidth > maxX ? x+lineWidth : maxX;
  8110. minY = y-lineWidth < minY ? y-lineWidth : minY;
  8111. maxY = y+lineWidth > maxY ? y+lineWidth : maxY;
  8112. }
  8113. }
  8114. }
  8115. }
  8116. else
  8117. {
  8118. minX = 0;
  8119. maxX = 0;
  8120. minY = 0;
  8121. maxY = 0;
  8122. }
  8123. var padding = this.boundsPadding;
  8124. this._localBounds.x = minX - padding;
  8125. this._localBounds.width = (maxX - minX) + padding * 2;
  8126. this._localBounds.y = minY - padding;
  8127. this._localBounds.height = (maxY - minY) + padding * 2;
  8128. };
  8129. /**
  8130. * Generates the cached sprite when the sprite has cacheAsBitmap = true
  8131. *
  8132. * @private
  8133. */
  8134. /*
  8135. Graphics.prototype._generateCachedSprite = function ()
  8136. {
  8137. var bounds = this.getLocalBounds();
  8138. if (!this._cachedSprite)
  8139. {
  8140. var canvasBuffer = new CanvasBuffer(bounds.width, bounds.height);
  8141. var texture = Texture.fromCanvas(canvasBuffer.canvas);
  8142. this._cachedSprite = new Sprite(texture);
  8143. this._cachedSprite.buffer = canvasBuffer;
  8144. this._cachedSprite.worldTransform = this.worldTransform;
  8145. }
  8146. else
  8147. {
  8148. this._cachedSprite.buffer.resize(bounds.width, bounds.height);
  8149. }
  8150. // leverage the anchor to account for the offset of the element
  8151. this._cachedSprite.anchor.x = -( bounds.x / bounds.width );
  8152. this._cachedSprite.anchor.y = -( bounds.y / bounds.height );
  8153. // this._cachedSprite.buffer.context.save();
  8154. this._cachedSprite.buffer.context.translate(-bounds.x,-bounds.y);
  8155. // make sure we set the alpha of the graphics to 1 for the render..
  8156. this.worldAlpha = 1;
  8157. // now render the graphic..
  8158. CanvasGraphics.renderGraphics(this, this._cachedSprite.buffer.context);
  8159. this._cachedSprite.alpha = this.alpha;
  8160. };
  8161. */
  8162. /**
  8163. * Updates texture size based on canvas size
  8164. *
  8165. * @private
  8166. */
  8167. /*
  8168. Graphics.prototype.updateCachedSpriteTexture = function ()
  8169. {
  8170. var cachedSprite = this._cachedSprite;
  8171. var texture = cachedSprite.texture;
  8172. var canvas = cachedSprite.buffer.canvas;
  8173. texture.baseTexture.width = canvas.width;
  8174. texture.baseTexture.height = canvas.height;
  8175. texture.crop.width = texture.frame.width = canvas.width;
  8176. texture.crop.height = texture.frame.height = canvas.height;
  8177. cachedSprite._width = canvas.width;
  8178. cachedSprite._height = canvas.height;
  8179. // update the dirty base textures
  8180. texture.baseTexture.dirty();
  8181. };*/
  8182. /**
  8183. * Destroys a previous cached sprite.
  8184. *
  8185. */
  8186. /*
  8187. Graphics.prototype.destroyCachedSprite = function ()
  8188. {
  8189. this._cachedSprite.texture.destroy(true);
  8190. // let the gc collect the unused sprite
  8191. // TODO could be object pooled!
  8192. this._cachedSprite = null;
  8193. };*/
  8194. /**
  8195. * Draws the given shape to this Graphics object. Can be any of Circle, Rectangle, Ellipse, Line or Polygon.
  8196. *
  8197. * @param shape {PIXI.Circle|PIXI.Rectangle|PIXI.Ellipse|PIXI.Line|PIXI.Polygon} The shape object to draw.
  8198. * @return {PIXI.GraphicsData} The generated GraphicsData object.
  8199. */
  8200. Graphics.prototype.drawShape = function (shape)
  8201. {
  8202. if (this.currentPath)
  8203. {
  8204. // check current path!
  8205. if (this.currentPath.shape.points.length <= 2)
  8206. {
  8207. this.graphicsData.pop();
  8208. }
  8209. }
  8210. this.currentPath = null;
  8211. var data = new GraphicsData(this.lineWidth, this.lineColor, this.lineAlpha, this.fillColor, this.fillAlpha, this.filling, shape);
  8212. this.graphicsData.push(data);
  8213. if (data.type === CONST.SHAPES.POLY)
  8214. {
  8215. data.shape.closed = data.shape.closed || this.filling;
  8216. this.currentPath = data;
  8217. }
  8218. this.dirty = this.boundsDirty = true;
  8219. return data;
  8220. };
  8221. /**
  8222. * Destroys the Graphics object.
  8223. */
  8224. Graphics.prototype.destroy = function () {
  8225. Container.prototype.destroy.apply(this, arguments);
  8226. // destroy each of the GraphicsData objects
  8227. for (var i = 0; i < this.graphicsData.length; ++i) {
  8228. this.graphicsData[i].destroy();
  8229. }
  8230. // for each webgl data entry, destroy the WebGLGraphicsData
  8231. for (var id in this._webgl) {
  8232. for (var j = 0; j < this._webgl[id].data.length; ++j) {
  8233. this._webgl[id].data[j].destroy();
  8234. }
  8235. }
  8236. this.graphicsData = null;
  8237. this.currentPath = null;
  8238. this._webgl = null;
  8239. this._localBounds = null;
  8240. };
  8241. },{"../const":22,"../display/Container":23,"../math":33,"../renderers/canvas/utils/CanvasBuffer":45,"../renderers/canvas/utils/CanvasGraphics":46,"../textures/Texture":72,"./GraphicsData":26}],26:[function(require,module,exports){
  8242. /**
  8243. * A GraphicsData object.
  8244. *
  8245. * @class
  8246. * @memberof PIXI
  8247. * @param lineWidth {number} the width of the line to draw
  8248. * @param lineColor {number} the color of the line to draw
  8249. * @param lineAlpha {number} the alpha of the line to draw
  8250. * @param fillColor {number} the color of the fill
  8251. * @param fillAlpha {number} the alpha of the fill
  8252. * @param fill {boolean} whether or not the shape is filled with a colour
  8253. * @param shape {Circle|Rectangle|Ellipse|Line|Polygon} The shape object to draw.
  8254. */
  8255. function GraphicsData(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, shape)
  8256. {
  8257. /*
  8258. * @member {number} the width of the line to draw
  8259. */
  8260. this.lineWidth = lineWidth;
  8261. /*
  8262. * @member {number} the color of the line to draw
  8263. */
  8264. this.lineColor = lineColor;
  8265. /*
  8266. * @member {number} the alpha of the line to draw
  8267. */
  8268. this.lineAlpha = lineAlpha;
  8269. /*
  8270. * @member {number} cached tint of the line to draw
  8271. */
  8272. this._lineTint = lineColor;
  8273. /*
  8274. * @member {number} the color of the fill
  8275. */
  8276. this.fillColor = fillColor;
  8277. /*
  8278. * @member {number} the alpha of the fill
  8279. */
  8280. this.fillAlpha = fillAlpha;
  8281. /*
  8282. * @member {number} cached tint of the fill
  8283. */
  8284. this._fillTint = fillColor;
  8285. /*
  8286. * @member {boolean} whether or not the shape is filled with a colour
  8287. */
  8288. this.fill = fill;
  8289. /*
  8290. * @member {PIXI.Circle|PIXI.Rectangle|PIXI.Ellipse|PIXI.Line|PIXI.Polygon} The shape object to draw.
  8291. */
  8292. this.shape = shape;
  8293. /*
  8294. * @member {number} The type of the shape, see the Const.Shapes file for all the existing types,
  8295. */
  8296. this.type = shape.type;
  8297. }
  8298. GraphicsData.prototype.constructor = GraphicsData;
  8299. module.exports = GraphicsData;
  8300. /**
  8301. * Creates a new GraphicsData object with the same values as this one.
  8302. *
  8303. * @return {PIXI.GraphicsData}
  8304. */
  8305. GraphicsData.prototype.clone = function ()
  8306. {
  8307. return new GraphicsData(
  8308. this.lineWidth,
  8309. this.lineColor,
  8310. this.lineAlpha,
  8311. this.fillColor,
  8312. this.fillAlpha,
  8313. this.fill,
  8314. this.shape
  8315. );
  8316. };
  8317. /**
  8318. * Destroys the Graphics data.
  8319. */
  8320. GraphicsData.prototype.destroy = function () {
  8321. this.shape = null;
  8322. };
  8323. },{}],27:[function(require,module,exports){
  8324. var utils = require('../../utils'),
  8325. math = require('../../math'),
  8326. CONST = require('../../const'),
  8327. ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'),
  8328. WebGLRenderer = require('../../renderers/webgl/WebGLRenderer'),
  8329. WebGLGraphicsData = require('./WebGLGraphicsData'),
  8330. earcut = require('earcut');
  8331. /**
  8332. * Renders the graphics object.
  8333. *
  8334. * @class
  8335. * @private
  8336. * @memberof PIXI
  8337. * @extends PIXI.ObjectRenderer
  8338. * @param renderer {PIXI.WebGLRenderer} The renderer this object renderer works for.
  8339. */
  8340. function GraphicsRenderer(renderer)
  8341. {
  8342. ObjectRenderer.call(this, renderer);
  8343. this.graphicsDataPool = [];
  8344. this.primitiveShader = null;
  8345. this.complexPrimitiveShader = null;
  8346. /**
  8347. * This is the maximum number of points a poly can contain before it is rendered as a complex polygon (using the stencil buffer)
  8348. * @type {Number}
  8349. */
  8350. this.maximumSimplePolySize = 200;
  8351. }
  8352. GraphicsRenderer.prototype = Object.create(ObjectRenderer.prototype);
  8353. GraphicsRenderer.prototype.constructor = GraphicsRenderer;
  8354. module.exports = GraphicsRenderer;
  8355. WebGLRenderer.registerPlugin('graphics', GraphicsRenderer);
  8356. /**
  8357. * Called when there is a WebGL context change
  8358. *
  8359. * @private
  8360. *
  8361. */
  8362. GraphicsRenderer.prototype.onContextChange = function()
  8363. {
  8364. };
  8365. /**
  8366. * Destroys this renderer.
  8367. *
  8368. */
  8369. GraphicsRenderer.prototype.destroy = function () {
  8370. ObjectRenderer.prototype.destroy.call(this);
  8371. for (var i = 0; i < this.graphicsDataPool.length; ++i) {
  8372. this.graphicsDataPool[i].destroy();
  8373. }
  8374. this.graphicsDataPool = null;
  8375. };
  8376. /**
  8377. * Renders a graphics object.
  8378. *
  8379. * @param graphics {PIXI.Graphics} The graphics object to render.
  8380. */
  8381. GraphicsRenderer.prototype.render = function(graphics)
  8382. {
  8383. var renderer = this.renderer;
  8384. var gl = renderer.gl;
  8385. var shader = renderer.shaderManager.plugins.primitiveShader,
  8386. webGLData;
  8387. if (graphics.dirty || !graphics._webGL[gl.id])
  8388. {
  8389. this.updateGraphics(graphics);
  8390. }
  8391. var webGL = graphics._webGL[gl.id];
  8392. // This could be speeded up for sure!
  8393. renderer.blendModeManager.setBlendMode( graphics.blendMode );
  8394. // var matrix = graphics.worldTransform.clone();
  8395. // var matrix = renderer.currentRenderTarget.projectionMatrix.clone();
  8396. // matrix.append(graphics.worldTransform);
  8397. for (var i = 0, n = webGL.data.length; i < n; i++)
  8398. {
  8399. webGLData = webGL.data[i];
  8400. if (webGL.data[i].mode === 1)
  8401. {
  8402. renderer.stencilManager.pushStencil(graphics, webGLData);
  8403. gl.uniform1f(renderer.shaderManager.complexPrimitiveShader.uniforms.alpha._location, graphics.worldAlpha * webGLData.alpha);
  8404. // render quad..
  8405. gl.drawElements(gl.TRIANGLE_FAN, 4, gl.UNSIGNED_SHORT, ( webGLData.indices.length - 4 ) * 2 );
  8406. renderer.stencilManager.popStencil(graphics, webGLData);
  8407. }
  8408. else
  8409. {
  8410. shader = renderer.shaderManager.primitiveShader;
  8411. renderer.shaderManager.setShader( shader );//activatePrimitiveShader();
  8412. gl.uniformMatrix3fv(shader.uniforms.translationMatrix._location, false, graphics.worldTransform.toArray(true));
  8413. gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, renderer.currentRenderTarget.projectionMatrix.toArray(true));
  8414. gl.uniform3fv(shader.uniforms.tint._location, utils.hex2rgb(graphics.tint));
  8415. gl.uniform1f(shader.uniforms.alpha._location, graphics.worldAlpha);
  8416. gl.bindBuffer(gl.ARRAY_BUFFER, webGLData.buffer);
  8417. gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 4 * 6, 0);
  8418. gl.vertexAttribPointer(shader.attributes.aColor, 4, gl.FLOAT, false,4 * 6, 2 * 4);
  8419. // set the index buffer!
  8420. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, webGLData.indexBuffer);
  8421. gl.drawElements(gl.TRIANGLE_STRIP, webGLData.indices.length, gl.UNSIGNED_SHORT, 0 );
  8422. }
  8423. renderer.drawCount++;
  8424. }
  8425. };
  8426. /**
  8427. * Updates the graphics object
  8428. *
  8429. * @private
  8430. * @param graphics {PIXI.Graphics} The graphics object to update
  8431. */
  8432. GraphicsRenderer.prototype.updateGraphics = function(graphics)
  8433. {
  8434. var gl = this.renderer.gl;
  8435. // get the contexts graphics object
  8436. var webGL = graphics._webGL[gl.id];
  8437. // if the graphics object does not exist in the webGL context time to create it!
  8438. if (!webGL)
  8439. {
  8440. webGL = graphics._webGL[gl.id] = {lastIndex:0, data:[], gl:gl};
  8441. }
  8442. // flag the graphics as not dirty as we are about to update it...
  8443. graphics.dirty = false;
  8444. var i;
  8445. // if the user cleared the graphics object we will need to clear every object
  8446. if (graphics.clearDirty)
  8447. {
  8448. graphics.clearDirty = false;
  8449. // loop through and return all the webGLDatas to the object pool so than can be reused later on
  8450. for (i = 0; i < webGL.data.length; i++)
  8451. {
  8452. var graphicsData = webGL.data[i];
  8453. graphicsData.reset();
  8454. this.graphicsDataPool.push( graphicsData );
  8455. }
  8456. // clear the array and reset the index..
  8457. webGL.data = [];
  8458. webGL.lastIndex = 0;
  8459. }
  8460. var webGLData;
  8461. // loop through the graphics datas and construct each one..
  8462. // if the object is a complex fill then the new stencil buffer technique will be used
  8463. // other wise graphics objects will be pushed into a batch..
  8464. for (i = webGL.lastIndex; i < graphics.graphicsData.length; i++)
  8465. {
  8466. var data = graphics.graphicsData[i];
  8467. if (data.type === CONST.SHAPES.POLY)
  8468. {
  8469. // need to add the points the the graphics object..
  8470. data.points = data.shape.points.slice();
  8471. if (data.shape.closed)
  8472. {
  8473. // close the poly if the value is true!
  8474. if (data.points[0] !== data.points[data.points.length-2] || data.points[1] !== data.points[data.points.length-1])
  8475. {
  8476. data.points.push(data.points[0], data.points[1]);
  8477. }
  8478. }
  8479. // MAKE SURE WE HAVE THE CORRECT TYPE..
  8480. if (data.fill)
  8481. {
  8482. if (data.points.length >= 6)
  8483. {
  8484. if (data.points.length < this.maximumSimplePolySize * 2)
  8485. {
  8486. webGLData = this.switchMode(webGL, 0);
  8487. var canDrawUsingSimple = this.buildPoly(data, webGLData);
  8488. if (!canDrawUsingSimple)
  8489. {
  8490. webGLData = this.switchMode(webGL, 1);
  8491. this.buildComplexPoly(data, webGLData);
  8492. }
  8493. }
  8494. else
  8495. {
  8496. webGLData = this.switchMode(webGL, 1);
  8497. this.buildComplexPoly(data, webGLData);
  8498. }
  8499. }
  8500. }
  8501. if (data.lineWidth > 0)
  8502. {
  8503. webGLData = this.switchMode(webGL, 0);
  8504. this.buildLine(data, webGLData);
  8505. }
  8506. }
  8507. else
  8508. {
  8509. webGLData = this.switchMode(webGL, 0);
  8510. if (data.type === CONST.SHAPES.RECT)
  8511. {
  8512. this.buildRectangle(data, webGLData);
  8513. }
  8514. else if (data.type === CONST.SHAPES.CIRC || data.type === CONST.SHAPES.ELIP)
  8515. {
  8516. this.buildCircle(data, webGLData);
  8517. }
  8518. else if (data.type === CONST.SHAPES.RREC)
  8519. {
  8520. this.buildRoundedRectangle(data, webGLData);
  8521. }
  8522. }
  8523. webGL.lastIndex++;
  8524. }
  8525. // upload all the dirty data...
  8526. for (i = 0; i < webGL.data.length; i++)
  8527. {
  8528. webGLData = webGL.data[i];
  8529. if (webGLData.dirty)
  8530. {
  8531. webGLData.upload();
  8532. }
  8533. }
  8534. };
  8535. /**
  8536. *
  8537. *
  8538. * @private
  8539. * @param webGL {WebGLRenderingContext} the current WebGL drawing context
  8540. * @param type {number} TODO @Alvin
  8541. */
  8542. GraphicsRenderer.prototype.switchMode = function (webGL, type)
  8543. {
  8544. var webGLData;
  8545. if (!webGL.data.length)
  8546. {
  8547. webGLData = this.graphicsDataPool.pop() || new WebGLGraphicsData(webGL.gl);
  8548. webGLData.mode = type;
  8549. webGL.data.push(webGLData);
  8550. }
  8551. else
  8552. {
  8553. webGLData = webGL.data[webGL.data.length-1];
  8554. if ((webGLData.points.length > 320000) || webGLData.mode !== type || type === 1)
  8555. {
  8556. webGLData = this.graphicsDataPool.pop() || new WebGLGraphicsData(webGL.gl);
  8557. webGLData.mode = type;
  8558. webGL.data.push(webGLData);
  8559. }
  8560. }
  8561. webGLData.dirty = true;
  8562. return webGLData;
  8563. };
  8564. /**
  8565. * Builds a rectangle to draw
  8566. *
  8567. * @private
  8568. * @param graphicsData {PIXI.Graphics} The graphics object containing all the necessary properties
  8569. * @param webGLData {object} an object containing all the webGL-specific information to create this shape
  8570. */
  8571. GraphicsRenderer.prototype.buildRectangle = function (graphicsData, webGLData)
  8572. {
  8573. // --- //
  8574. // need to convert points to a nice regular data
  8575. //
  8576. var rectData = graphicsData.shape;
  8577. var x = rectData.x;
  8578. var y = rectData.y;
  8579. var width = rectData.width;
  8580. var height = rectData.height;
  8581. if (graphicsData.fill)
  8582. {
  8583. var color = utils.hex2rgb(graphicsData.fillColor);
  8584. var alpha = graphicsData.fillAlpha;
  8585. var r = color[0] * alpha;
  8586. var g = color[1] * alpha;
  8587. var b = color[2] * alpha;
  8588. var verts = webGLData.points;
  8589. var indices = webGLData.indices;
  8590. var vertPos = verts.length/6;
  8591. // start
  8592. verts.push(x, y);
  8593. verts.push(r, g, b, alpha);
  8594. verts.push(x + width, y);
  8595. verts.push(r, g, b, alpha);
  8596. verts.push(x , y + height);
  8597. verts.push(r, g, b, alpha);
  8598. verts.push(x + width, y + height);
  8599. verts.push(r, g, b, alpha);
  8600. // insert 2 dead triangles..
  8601. indices.push(vertPos, vertPos, vertPos+1, vertPos+2, vertPos+3, vertPos+3);
  8602. }
  8603. if (graphicsData.lineWidth)
  8604. {
  8605. var tempPoints = graphicsData.points;
  8606. graphicsData.points = [x, y,
  8607. x + width, y,
  8608. x + width, y + height,
  8609. x, y + height,
  8610. x, y];
  8611. this.buildLine(graphicsData, webGLData);
  8612. graphicsData.points = tempPoints;
  8613. }
  8614. };
  8615. /**
  8616. * Builds a rounded rectangle to draw
  8617. *
  8618. * @private
  8619. * @param graphicsData {PIXI.Graphics} The graphics object containing all the necessary properties
  8620. * @param webGLData {object} an object containing all the webGL-specific information to create this shape
  8621. */
  8622. GraphicsRenderer.prototype.buildRoundedRectangle = function (graphicsData, webGLData)
  8623. {
  8624. var rrectData = graphicsData.shape;
  8625. var x = rrectData.x;
  8626. var y = rrectData.y;
  8627. var width = rrectData.width;
  8628. var height = rrectData.height;
  8629. var radius = rrectData.radius;
  8630. var recPoints = [];
  8631. recPoints.push(x, y + radius);
  8632. this.quadraticBezierCurve(x, y + height - radius, x, y + height, x + radius, y + height, recPoints);
  8633. this.quadraticBezierCurve(x + width - radius, y + height, x + width, y + height, x + width, y + height - radius, recPoints);
  8634. this.quadraticBezierCurve(x + width, y + radius, x + width, y, x + width - radius, y, recPoints);
  8635. this.quadraticBezierCurve(x + radius, y, x, y, x, y + radius + 0.0000000001, recPoints);
  8636. // this tiny number deals with the issue that occurs when points overlap and earcut fails to triangulate the item.
  8637. // TODO - fix this properly, this is not very elegant.. but it works for now.
  8638. if (graphicsData.fill)
  8639. {
  8640. var color = utils.hex2rgb(graphicsData.fillColor);
  8641. var alpha = graphicsData.fillAlpha;
  8642. var r = color[0] * alpha;
  8643. var g = color[1] * alpha;
  8644. var b = color[2] * alpha;
  8645. var verts = webGLData.points;
  8646. var indices = webGLData.indices;
  8647. var vecPos = verts.length/6;
  8648. var triangles = earcut(recPoints, null, 2);
  8649. var i = 0;
  8650. for (i = 0; i < triangles.length; i+=3)
  8651. {
  8652. indices.push(triangles[i] + vecPos);
  8653. indices.push(triangles[i] + vecPos);
  8654. indices.push(triangles[i+1] + vecPos);
  8655. indices.push(triangles[i+2] + vecPos);
  8656. indices.push(triangles[i+2] + vecPos);
  8657. }
  8658. for (i = 0; i < recPoints.length; i++)
  8659. {
  8660. verts.push(recPoints[i], recPoints[++i], r, g, b, alpha);
  8661. }
  8662. }
  8663. if (graphicsData.lineWidth)
  8664. {
  8665. var tempPoints = graphicsData.points;
  8666. graphicsData.points = recPoints;
  8667. this.buildLine(graphicsData, webGLData);
  8668. graphicsData.points = tempPoints;
  8669. }
  8670. };
  8671. /**
  8672. * Calculate the points for a quadratic bezier curve. (helper function..)
  8673. * Based on: https://stackoverflow.com/questions/785097/how-do-i-implement-a-bezier-curve-in-c
  8674. *
  8675. * @private
  8676. * @param fromX {number} Origin point x
  8677. * @param fromY {number} Origin point x
  8678. * @param cpX {number} Control point x
  8679. * @param cpY {number} Control point y
  8680. * @param toX {number} Destination point x
  8681. * @param toY {number} Destination point y
  8682. * @param [out] {number[]} The output array to add points into. If not passed, a new array is created.
  8683. * @return {number[]} an array of points
  8684. */
  8685. GraphicsRenderer.prototype.quadraticBezierCurve = function (fromX, fromY, cpX, cpY, toX, toY, out)
  8686. {
  8687. var xa,
  8688. ya,
  8689. xb,
  8690. yb,
  8691. x,
  8692. y,
  8693. n = 20,
  8694. points = out || [];
  8695. function getPt(n1 , n2, perc) {
  8696. var diff = n2 - n1;
  8697. return n1 + ( diff * perc );
  8698. }
  8699. var j = 0;
  8700. for (var i = 0; i <= n; i++ ) {
  8701. j = i / n;
  8702. // The Green Line
  8703. xa = getPt( fromX , cpX , j );
  8704. ya = getPt( fromY , cpY , j );
  8705. xb = getPt( cpX , toX , j );
  8706. yb = getPt( cpY , toY , j );
  8707. // The Black Dot
  8708. x = getPt( xa , xb , j );
  8709. y = getPt( ya , yb , j );
  8710. points.push(x, y);
  8711. }
  8712. return points;
  8713. };
  8714. /**
  8715. * Builds a circle to draw
  8716. *
  8717. * @private
  8718. * @param graphicsData {PIXI.Graphics} The graphics object to draw
  8719. * @param webGLData {object} an object containing all the webGL-specific information to create this shape
  8720. */
  8721. GraphicsRenderer.prototype.buildCircle = function (graphicsData, webGLData)
  8722. {
  8723. // need to convert points to a nice regular data
  8724. var circleData = graphicsData.shape;
  8725. var x = circleData.x;
  8726. var y = circleData.y;
  8727. var width;
  8728. var height;
  8729. // TODO - bit hacky??
  8730. if (graphicsData.type === CONST.SHAPES.CIRC)
  8731. {
  8732. width = circleData.radius;
  8733. height = circleData.radius;
  8734. }
  8735. else
  8736. {
  8737. width = circleData.width;
  8738. height = circleData.height;
  8739. }
  8740. var totalSegs = Math.floor(30 * Math.sqrt(circleData.radius)) || Math.floor(15 * Math.sqrt(circleData.width + circleData.height));
  8741. var seg = (Math.PI * 2) / totalSegs ;
  8742. var i = 0;
  8743. if (graphicsData.fill)
  8744. {
  8745. var color = utils.hex2rgb(graphicsData.fillColor);
  8746. var alpha = graphicsData.fillAlpha;
  8747. var r = color[0] * alpha;
  8748. var g = color[1] * alpha;
  8749. var b = color[2] * alpha;
  8750. var verts = webGLData.points;
  8751. var indices = webGLData.indices;
  8752. var vecPos = verts.length/6;
  8753. indices.push(vecPos);
  8754. for (i = 0; i < totalSegs + 1 ; i++)
  8755. {
  8756. verts.push(x,y, r, g, b, alpha);
  8757. verts.push(x + Math.sin(seg * i) * width,
  8758. y + Math.cos(seg * i) * height,
  8759. r, g, b, alpha);
  8760. indices.push(vecPos++, vecPos++);
  8761. }
  8762. indices.push(vecPos-1);
  8763. }
  8764. if (graphicsData.lineWidth)
  8765. {
  8766. var tempPoints = graphicsData.points;
  8767. graphicsData.points = [];
  8768. for (i = 0; i < totalSegs + 1; i++)
  8769. {
  8770. graphicsData.points.push(x + Math.sin(seg * i) * width,
  8771. y + Math.cos(seg * i) * height);
  8772. }
  8773. this.buildLine(graphicsData, webGLData);
  8774. graphicsData.points = tempPoints;
  8775. }
  8776. };
  8777. /**
  8778. * Builds a line to draw
  8779. *
  8780. * @private
  8781. * @param graphicsData {PIXI.Graphics} The graphics object containing all the necessary properties
  8782. * @param webGLData {object} an object containing all the webGL-specific information to create this shape
  8783. */
  8784. GraphicsRenderer.prototype.buildLine = function (graphicsData, webGLData)
  8785. {
  8786. // TODO OPTIMISE!
  8787. var i = 0;
  8788. var points = graphicsData.points;
  8789. if (points.length === 0)
  8790. {
  8791. return;
  8792. }
  8793. // if the line width is an odd number add 0.5 to align to a whole pixel
  8794. // commenting this out fixes #711 and #1620
  8795. // if (graphicsData.lineWidth%2)
  8796. // {
  8797. // for (i = 0; i < points.length; i++)
  8798. // {
  8799. // points[i] += 0.5;
  8800. // }
  8801. // }
  8802. // get first and last point.. figure out the middle!
  8803. var firstPoint = new math.Point(points[0], points[1]);
  8804. var lastPoint = new math.Point(points[points.length - 2], points[points.length - 1]);
  8805. // if the first point is the last point - gonna have issues :)
  8806. if (firstPoint.x === lastPoint.x && firstPoint.y === lastPoint.y)
  8807. {
  8808. // need to clone as we are going to slightly modify the shape..
  8809. points = points.slice();
  8810. points.pop();
  8811. points.pop();
  8812. lastPoint = new math.Point(points[points.length - 2], points[points.length - 1]);
  8813. var midPointX = lastPoint.x + (firstPoint.x - lastPoint.x) *0.5;
  8814. var midPointY = lastPoint.y + (firstPoint.y - lastPoint.y) *0.5;
  8815. points.unshift(midPointX, midPointY);
  8816. points.push(midPointX, midPointY);
  8817. }
  8818. var verts = webGLData.points;
  8819. var indices = webGLData.indices;
  8820. var length = points.length / 2;
  8821. var indexCount = points.length;
  8822. var indexStart = verts.length/6;
  8823. // DRAW the Line
  8824. var width = graphicsData.lineWidth / 2;
  8825. // sort color
  8826. var color = utils.hex2rgb(graphicsData.lineColor);
  8827. var alpha = graphicsData.lineAlpha;
  8828. var r = color[0] * alpha;
  8829. var g = color[1] * alpha;
  8830. var b = color[2] * alpha;
  8831. var px, py, p1x, p1y, p2x, p2y, p3x, p3y;
  8832. var perpx, perpy, perp2x, perp2y, perp3x, perp3y;
  8833. var a1, b1, c1, a2, b2, c2;
  8834. var denom, pdist, dist;
  8835. p1x = points[0];
  8836. p1y = points[1];
  8837. p2x = points[2];
  8838. p2y = points[3];
  8839. perpx = -(p1y - p2y);
  8840. perpy = p1x - p2x;
  8841. dist = Math.sqrt(perpx*perpx + perpy*perpy);
  8842. perpx /= dist;
  8843. perpy /= dist;
  8844. perpx *= width;
  8845. perpy *= width;
  8846. // start
  8847. verts.push(p1x - perpx , p1y - perpy,
  8848. r, g, b, alpha);
  8849. verts.push(p1x + perpx , p1y + perpy,
  8850. r, g, b, alpha);
  8851. for (i = 1; i < length-1; i++)
  8852. {
  8853. p1x = points[(i-1)*2];
  8854. p1y = points[(i-1)*2 + 1];
  8855. p2x = points[(i)*2];
  8856. p2y = points[(i)*2 + 1];
  8857. p3x = points[(i+1)*2];
  8858. p3y = points[(i+1)*2 + 1];
  8859. perpx = -(p1y - p2y);
  8860. perpy = p1x - p2x;
  8861. dist = Math.sqrt(perpx*perpx + perpy*perpy);
  8862. perpx /= dist;
  8863. perpy /= dist;
  8864. perpx *= width;
  8865. perpy *= width;
  8866. perp2x = -(p2y - p3y);
  8867. perp2y = p2x - p3x;
  8868. dist = Math.sqrt(perp2x*perp2x + perp2y*perp2y);
  8869. perp2x /= dist;
  8870. perp2y /= dist;
  8871. perp2x *= width;
  8872. perp2y *= width;
  8873. a1 = (-perpy + p1y) - (-perpy + p2y);
  8874. b1 = (-perpx + p2x) - (-perpx + p1x);
  8875. c1 = (-perpx + p1x) * (-perpy + p2y) - (-perpx + p2x) * (-perpy + p1y);
  8876. a2 = (-perp2y + p3y) - (-perp2y + p2y);
  8877. b2 = (-perp2x + p2x) - (-perp2x + p3x);
  8878. c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y);
  8879. denom = a1*b2 - a2*b1;
  8880. if (Math.abs(denom) < 0.1 )
  8881. {
  8882. denom+=10.1;
  8883. verts.push(p2x - perpx , p2y - perpy,
  8884. r, g, b, alpha);
  8885. verts.push(p2x + perpx , p2y + perpy,
  8886. r, g, b, alpha);
  8887. continue;
  8888. }
  8889. px = (b1*c2 - b2*c1)/denom;
  8890. py = (a2*c1 - a1*c2)/denom;
  8891. pdist = (px -p2x) * (px -p2x) + (py -p2y) * (py -p2y);
  8892. if (pdist > 140 * 140)
  8893. {
  8894. perp3x = perpx - perp2x;
  8895. perp3y = perpy - perp2y;
  8896. dist = Math.sqrt(perp3x*perp3x + perp3y*perp3y);
  8897. perp3x /= dist;
  8898. perp3y /= dist;
  8899. perp3x *= width;
  8900. perp3y *= width;
  8901. verts.push(p2x - perp3x, p2y -perp3y);
  8902. verts.push(r, g, b, alpha);
  8903. verts.push(p2x + perp3x, p2y +perp3y);
  8904. verts.push(r, g, b, alpha);
  8905. verts.push(p2x - perp3x, p2y -perp3y);
  8906. verts.push(r, g, b, alpha);
  8907. indexCount++;
  8908. }
  8909. else
  8910. {
  8911. verts.push(px , py);
  8912. verts.push(r, g, b, alpha);
  8913. verts.push(p2x - (px-p2x), p2y - (py - p2y));
  8914. verts.push(r, g, b, alpha);
  8915. }
  8916. }
  8917. p1x = points[(length-2)*2];
  8918. p1y = points[(length-2)*2 + 1];
  8919. p2x = points[(length-1)*2];
  8920. p2y = points[(length-1)*2 + 1];
  8921. perpx = -(p1y - p2y);
  8922. perpy = p1x - p2x;
  8923. dist = Math.sqrt(perpx*perpx + perpy*perpy);
  8924. perpx /= dist;
  8925. perpy /= dist;
  8926. perpx *= width;
  8927. perpy *= width;
  8928. verts.push(p2x - perpx , p2y - perpy);
  8929. verts.push(r, g, b, alpha);
  8930. verts.push(p2x + perpx , p2y + perpy);
  8931. verts.push(r, g, b, alpha);
  8932. indices.push(indexStart);
  8933. for (i = 0; i < indexCount; i++)
  8934. {
  8935. indices.push(indexStart++);
  8936. }
  8937. indices.push(indexStart-1);
  8938. };
  8939. /**
  8940. * Builds a complex polygon to draw
  8941. *
  8942. * @private
  8943. * @param graphicsData {PIXI.Graphics} The graphics object containing all the necessary properties
  8944. * @param webGLData {object} an object containing all the webGL-specific information to create this shape
  8945. */
  8946. GraphicsRenderer.prototype.buildComplexPoly = function (graphicsData, webGLData)
  8947. {
  8948. //TODO - no need to copy this as it gets turned into a FLoat32Array anyways..
  8949. var points = graphicsData.points.slice();
  8950. if (points.length < 6)
  8951. {
  8952. return;
  8953. }
  8954. // get first and last point.. figure out the middle!
  8955. var indices = webGLData.indices;
  8956. webGLData.points = points;
  8957. webGLData.alpha = graphicsData.fillAlpha;
  8958. webGLData.color = utils.hex2rgb(graphicsData.fillColor);
  8959. // calclate the bounds..
  8960. var minX = Infinity;
  8961. var maxX = -Infinity;
  8962. var minY = Infinity;
  8963. var maxY = -Infinity;
  8964. var x,y;
  8965. // get size..
  8966. for (var i = 0; i < points.length; i+=2)
  8967. {
  8968. x = points[i];
  8969. y = points[i+1];
  8970. minX = x < minX ? x : minX;
  8971. maxX = x > maxX ? x : maxX;
  8972. minY = y < minY ? y : minY;
  8973. maxY = y > maxY ? y : maxY;
  8974. }
  8975. // add a quad to the end cos there is no point making another buffer!
  8976. points.push(minX, minY,
  8977. maxX, minY,
  8978. maxX, maxY,
  8979. minX, maxY);
  8980. // push a quad onto the end..
  8981. //TODO - this aint needed!
  8982. var length = points.length / 2;
  8983. for (i = 0; i < length; i++)
  8984. {
  8985. indices.push( i );
  8986. }
  8987. };
  8988. /**
  8989. * Builds a polygon to draw
  8990. *
  8991. * @private
  8992. * @param graphicsData {PIXI.WebGLGraphicsData} The graphics object containing all the necessary properties
  8993. * @param webGLData {object} an object containing all the webGL-specific information to create this shape
  8994. */
  8995. GraphicsRenderer.prototype.buildPoly = function (graphicsData, webGLData)
  8996. {
  8997. var points = graphicsData.points;
  8998. if (points.length < 6)
  8999. {
  9000. return;
  9001. }
  9002. // get first and last point.. figure out the middle!
  9003. var verts = webGLData.points;
  9004. var indices = webGLData.indices;
  9005. var length = points.length / 2;
  9006. // sort color
  9007. var color = utils.hex2rgb(graphicsData.fillColor);
  9008. var alpha = graphicsData.fillAlpha;
  9009. var r = color[0] * alpha;
  9010. var g = color[1] * alpha;
  9011. var b = color[2] * alpha;
  9012. var triangles = earcut(points, null, 2);
  9013. if (!triangles) {
  9014. return false;
  9015. }
  9016. var vertPos = verts.length / 6;
  9017. var i = 0;
  9018. for (i = 0; i < triangles.length; i+=3)
  9019. {
  9020. indices.push(triangles[i] + vertPos);
  9021. indices.push(triangles[i] + vertPos);
  9022. indices.push(triangles[i+1] + vertPos);
  9023. indices.push(triangles[i+2] +vertPos);
  9024. indices.push(triangles[i+2] + vertPos);
  9025. }
  9026. for (i = 0; i < length; i++)
  9027. {
  9028. verts.push(points[i * 2], points[i * 2 + 1],
  9029. r, g, b, alpha);
  9030. }
  9031. return true;
  9032. };
  9033. },{"../../const":22,"../../math":33,"../../renderers/webgl/WebGLRenderer":49,"../../renderers/webgl/utils/ObjectRenderer":63,"../../utils":77,"./WebGLGraphicsData":28,"earcut":9}],28:[function(require,module,exports){
  9034. /**
  9035. * An object containing WebGL specific properties to be used by the WebGL renderer
  9036. *
  9037. * @class
  9038. * @memberof PIXI
  9039. * @param gl {WebGLRenderingContext} the current WebGL drawing context
  9040. * @private
  9041. */
  9042. function WebGLGraphicsData(gl) {
  9043. /**
  9044. * The current WebGL drawing context
  9045. *
  9046. * @member {WebGLRenderingContext}
  9047. */
  9048. this.gl = gl;
  9049. //TODO does this need to be split before uploding??
  9050. /**
  9051. * An array of color components (r,g,b)
  9052. * @member {number[]}
  9053. */
  9054. this.color = [0,0,0]; // color split!
  9055. /**
  9056. * An array of points to draw
  9057. * @member {PIXI.Point[]}
  9058. */
  9059. this.points = [];
  9060. /**
  9061. * The indices of the vertices
  9062. * @member {number[]}
  9063. */
  9064. this.indices = [];
  9065. /**
  9066. * The main buffer
  9067. * @member {WebGLBuffer}
  9068. */
  9069. this.buffer = gl.createBuffer();
  9070. /**
  9071. * The index buffer
  9072. * @member {WebGLBuffer}
  9073. */
  9074. this.indexBuffer = gl.createBuffer();
  9075. /**
  9076. * todo @alvin
  9077. * @member {number}
  9078. */
  9079. this.mode = 1;
  9080. /**
  9081. * The alpha of the graphics
  9082. * @member {number}
  9083. */
  9084. this.alpha = 1;
  9085. /**
  9086. * Whether this graphics is dirty or not
  9087. * @member {boolean}
  9088. */
  9089. this.dirty = true;
  9090. this.glPoints = null;
  9091. this.glIndices = null;
  9092. }
  9093. WebGLGraphicsData.prototype.constructor = WebGLGraphicsData;
  9094. module.exports = WebGLGraphicsData;
  9095. /**
  9096. * Resets the vertices and the indices
  9097. */
  9098. WebGLGraphicsData.prototype.reset = function () {
  9099. this.points.length = 0;
  9100. this.indices.length = 0;
  9101. };
  9102. /**
  9103. * Binds the buffers and uploads the data
  9104. */
  9105. WebGLGraphicsData.prototype.upload = function () {
  9106. var gl = this.gl;
  9107. // this.lastIndex = graphics.graphicsData.length;
  9108. this.glPoints = new Float32Array(this.points);
  9109. gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
  9110. gl.bufferData(gl.ARRAY_BUFFER, this.glPoints, gl.STATIC_DRAW);
  9111. this.glIndices = new Uint16Array(this.indices);
  9112. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
  9113. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.glIndices, gl.STATIC_DRAW);
  9114. this.dirty = false;
  9115. };
  9116. WebGLGraphicsData.prototype.destroy = function () {
  9117. this.color = null;
  9118. this.points = null;
  9119. this.indices = null;
  9120. this.gl.deleteBuffer(this.buffer);
  9121. this.gl.deleteBuffer(this.indexBuffer);
  9122. this.gl = null;
  9123. this.buffer = null;
  9124. this.indexBuffer = null;
  9125. this.glPoints = null;
  9126. this.glIndices = null;
  9127. };
  9128. },{}],29:[function(require,module,exports){
  9129. /**
  9130. * @file Main export of the PIXI core library
  9131. * @author Mat Groves <mat@goodboydigital.com>
  9132. * @copyright 2013-2015 GoodBoyDigital
  9133. * @license {@link https://github.com/pixijs/pixi.js/blob/master/LICENSE|MIT License}
  9134. */
  9135. /**
  9136. * @namespace PIXI
  9137. */
  9138. // export core and const. We assign core to const so that the non-reference types in const remain in-tact
  9139. var core = module.exports = Object.assign(require('./const'), require('./math'), {
  9140. // utils
  9141. utils: require('./utils'),
  9142. ticker: require('./ticker'),
  9143. // display
  9144. DisplayObject: require('./display/DisplayObject'),
  9145. Container: require('./display/Container'),
  9146. // sprites
  9147. Sprite: require('./sprites/Sprite'),
  9148. ParticleContainer: require('./particles/ParticleContainer'),
  9149. SpriteRenderer: require('./sprites/webgl/SpriteRenderer'),
  9150. ParticleRenderer: require('./particles/webgl/ParticleRenderer'),
  9151. // text
  9152. Text: require('./text/Text'),
  9153. // primitives
  9154. Graphics: require('./graphics/Graphics'),
  9155. GraphicsData: require('./graphics/GraphicsData'),
  9156. GraphicsRenderer: require('./graphics/webgl/GraphicsRenderer'),
  9157. // textures
  9158. Texture: require('./textures/Texture'),
  9159. BaseTexture: require('./textures/BaseTexture'),
  9160. RenderTexture: require('./textures/RenderTexture'),
  9161. VideoBaseTexture: require('./textures/VideoBaseTexture'),
  9162. TextureUvs: require('./textures/TextureUvs'),
  9163. // renderers - canvas
  9164. CanvasRenderer: require('./renderers/canvas/CanvasRenderer'),
  9165. CanvasGraphics: require('./renderers/canvas/utils/CanvasGraphics'),
  9166. CanvasBuffer: require('./renderers/canvas/utils/CanvasBuffer'),
  9167. // renderers - webgl
  9168. WebGLRenderer: require('./renderers/webgl/WebGLRenderer'),
  9169. WebGLManager: require('./renderers/webgl/managers/WebGLManager'),
  9170. ShaderManager: require('./renderers/webgl/managers/ShaderManager'),
  9171. Shader: require('./renderers/webgl/shaders/Shader'),
  9172. TextureShader: require('./renderers/webgl/shaders/TextureShader'),
  9173. PrimitiveShader: require('./renderers/webgl/shaders/PrimitiveShader'),
  9174. ComplexPrimitiveShader: require('./renderers/webgl/shaders/ComplexPrimitiveShader'),
  9175. ObjectRenderer: require('./renderers/webgl/utils/ObjectRenderer'),
  9176. RenderTarget: require('./renderers/webgl/utils/RenderTarget'),
  9177. // filters - webgl
  9178. AbstractFilter: require('./renderers/webgl/filters/AbstractFilter'),
  9179. FXAAFilter: require('./renderers/webgl/filters/FXAAFilter'),
  9180. SpriteMaskFilter: require('./renderers/webgl/filters/SpriteMaskFilter'),
  9181. /**
  9182. * This helper function will automatically detect which renderer you should be using.
  9183. * WebGL is the preferred renderer as it is a lot faster. If webGL is not supported by
  9184. * the browser then this function will return a canvas renderer
  9185. *
  9186. * @memberof PIXI
  9187. * @param width=800 {number} the width of the renderers view
  9188. * @param height=600 {number} the height of the renderers view
  9189. * @param [options] {object} The optional renderer parameters
  9190. * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional
  9191. * @param [options.transparent=false] {boolean} If the render view is transparent, default false
  9192. * @param [options.antialias=false] {boolean} sets antialias (only applicable in chrome at the moment)
  9193. * @param [options.preserveDrawingBuffer=false] {boolean} enables drawing buffer preservation, enable this if you
  9194. * need to call toDataUrl on the webgl context
  9195. * @param [options.resolution=1] {number} the resolution of the renderer, retina would be 2
  9196. * @param [noWebGL=false] {boolean} prevents selection of WebGL renderer, even if such is present
  9197. *
  9198. * @return {WebGLRenderer|CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer
  9199. */
  9200. autoDetectRenderer: function (width, height, options, noWebGL)
  9201. {
  9202. width = width || 800;
  9203. height = height || 600;
  9204. if (!noWebGL && core.utils.isWebGLSupported())
  9205. {
  9206. return new core.WebGLRenderer(width, height, options);
  9207. }
  9208. return new core.CanvasRenderer(width, height, options);
  9209. }
  9210. });
  9211. },{"./const":22,"./display/Container":23,"./display/DisplayObject":24,"./graphics/Graphics":25,"./graphics/GraphicsData":26,"./graphics/webgl/GraphicsRenderer":27,"./math":33,"./particles/ParticleContainer":39,"./particles/webgl/ParticleRenderer":41,"./renderers/canvas/CanvasRenderer":44,"./renderers/canvas/utils/CanvasBuffer":45,"./renderers/canvas/utils/CanvasGraphics":46,"./renderers/webgl/WebGLRenderer":49,"./renderers/webgl/filters/AbstractFilter":50,"./renderers/webgl/filters/FXAAFilter":51,"./renderers/webgl/filters/SpriteMaskFilter":52,"./renderers/webgl/managers/ShaderManager":56,"./renderers/webgl/managers/WebGLManager":58,"./renderers/webgl/shaders/ComplexPrimitiveShader":59,"./renderers/webgl/shaders/PrimitiveShader":60,"./renderers/webgl/shaders/Shader":61,"./renderers/webgl/shaders/TextureShader":62,"./renderers/webgl/utils/ObjectRenderer":63,"./renderers/webgl/utils/RenderTarget":65,"./sprites/Sprite":67,"./sprites/webgl/SpriteRenderer":68,"./text/Text":69,"./textures/BaseTexture":70,"./textures/RenderTexture":71,"./textures/Texture":72,"./textures/TextureUvs":73,"./textures/VideoBaseTexture":74,"./ticker":76,"./utils":77}],30:[function(require,module,exports){
  9212. // Your friendly neighbour https://en.wikipedia.org/wiki/Dihedral_group of order 16
  9213. var ux = [1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1];
  9214. var uy = [0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1];
  9215. var vx = [0, -1, -1, -1, 0, 1, 1, 1, 0, 1, 1, 1, 0, -1, -1, -1];
  9216. var vy = [1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, 1, 1, 1, 0, -1];
  9217. var tempMatrices = [];
  9218. var Matrix = require('./Matrix');
  9219. var mul = [];
  9220. function signum(x) {
  9221. if (x < 0) {
  9222. return -1;
  9223. }
  9224. if (x > 0) {
  9225. return 1;
  9226. }
  9227. return 0;
  9228. }
  9229. function init() {
  9230. for (var i = 0; i < 16; i++) {
  9231. var row = [];
  9232. mul.push(row);
  9233. for (var j = 0; j < 16; j++) {
  9234. var _ux = signum(ux[i] * ux[j] + vx[i] * uy[j]);
  9235. var _uy = signum(uy[i] * ux[j] + vy[i] * uy[j]);
  9236. var _vx = signum(ux[i] * vx[j] + vx[i] * vy[j]);
  9237. var _vy = signum(uy[i] * vx[j] + vy[i] * vy[j]);
  9238. for (var k = 0; k < 16; k++) {
  9239. if (ux[k] === _ux && uy[k] === _uy && vx[k] === _vx && vy[k] === _vy) {
  9240. row.push(k);
  9241. break;
  9242. }
  9243. }
  9244. }
  9245. }
  9246. for (i=0;i<16;i++) {
  9247. var mat = new Matrix();
  9248. mat.set(ux[i], uy[i], vx[i], vy[i], 0, 0);
  9249. tempMatrices.push(mat);
  9250. }
  9251. }
  9252. init();
  9253. /**
  9254. * Implements Dihedral Group D_8, see [group D4]{@link http://mathworld.wolfram.com/DihedralGroupD4.html}, D8 is the same but with diagonals
  9255. * Used for texture rotations
  9256. * Vector xX(i), xY(i) is U-axis of sprite with rotation i
  9257. * Vector yY(i), yY(i) is V-axis of sprite with rotation i
  9258. * Rotations: 0 grad (0), 90 grad (2), 180 grad (4), 270 grad (6)
  9259. * Mirrors: vertical (8), main diagonal (10), horizontal (12), reverse diagonal (14)
  9260. * This is the small part of gameofbombs.com portal system. It works.
  9261. * @author Ivan @ivanpopelyshev
  9262. *
  9263. * @namespace PIXI.GroupD8
  9264. */
  9265. var GroupD8 = {
  9266. E: 0,
  9267. SE: 1,
  9268. S: 2,
  9269. SW: 3,
  9270. W: 4,
  9271. NW: 5,
  9272. N: 6,
  9273. NE: 7,
  9274. MIRROR_VERTICAL: 8,
  9275. MIRROR_HORIZONTAL: 12,
  9276. uX: function (ind) {
  9277. return ux[ind];
  9278. },
  9279. uY: function (ind) {
  9280. return uy[ind];
  9281. },
  9282. vX: function (ind) {
  9283. return vx[ind];
  9284. },
  9285. vY: function (ind) {
  9286. return vy[ind];
  9287. },
  9288. inv: function (rotation) {
  9289. if (rotation & 8) {
  9290. return rotation & 15;
  9291. }
  9292. return (-rotation) & 7;
  9293. },
  9294. add: function (rotationSecond, rotationFirst) {
  9295. return mul[rotationSecond][rotationFirst];
  9296. },
  9297. sub: function (rotationSecond, rotationFirst) {
  9298. return mul[rotationSecond][GroupD8.inv(rotationFirst)];
  9299. },
  9300. /**
  9301. * Adds 180 degrees to rotation. Commutative operation
  9302. * @param rotation
  9303. * @returns {number}
  9304. */
  9305. rotate180: function (rotation) {
  9306. return rotation ^ 4;
  9307. },
  9308. /**
  9309. * I dont know why sometimes width and heights needs to be swapped. We'll fix it later.
  9310. * @param rotation
  9311. * @returns {boolean}
  9312. */
  9313. isSwapWidthHeight: function(rotation) {
  9314. return (rotation & 3) === 2;
  9315. },
  9316. byDirection: function (dx, dy) {
  9317. if (Math.abs(dx) * 2 <= Math.abs(dy)) {
  9318. if (dy >= 0) {
  9319. return GroupD8.S;
  9320. }
  9321. else {
  9322. return GroupD8.N;
  9323. }
  9324. } else if (Math.abs(dy) * 2 <= Math.abs(dx)) {
  9325. if (dx > 0) {
  9326. return GroupD8.E;
  9327. }
  9328. else {
  9329. return GroupD8.W;
  9330. }
  9331. } else {
  9332. if (dy > 0) {
  9333. if (dx > 0) {
  9334. return GroupD8.SE;
  9335. }
  9336. else {
  9337. return GroupD8.SW;
  9338. }
  9339. }
  9340. else if (dx > 0) {
  9341. return GroupD8.NE;
  9342. }
  9343. else {
  9344. return GroupD8.NW;
  9345. }
  9346. }
  9347. },
  9348. /**
  9349. * Helps sprite to compensate texture packer rotation.
  9350. * @param matrix {PIXI.Matrix} sprite world matrix
  9351. * @param rotation {number}
  9352. * @param tx {number|*} sprite anchoring
  9353. * @param ty {number|*} sprite anchoring
  9354. */
  9355. matrixAppendRotationInv: function (matrix, rotation, tx, ty) {
  9356. //Packer used "rotation", we use "inv(rotation)"
  9357. var mat = tempMatrices[GroupD8.inv(rotation)];
  9358. tx = tx || 0;
  9359. ty = ty || 0;
  9360. mat.tx = tx;
  9361. mat.ty = ty;
  9362. matrix.append(mat);
  9363. }
  9364. };
  9365. module.exports = GroupD8;
  9366. },{"./Matrix":31}],31:[function(require,module,exports){
  9367. // @todo - ignore the too many parameters warning for now
  9368. // should either fix it or change the jshint config
  9369. // jshint -W072
  9370. var Point = require('./Point');
  9371. /**
  9372. * The pixi Matrix class as an object, which makes it a lot faster,
  9373. * here is a representation of it :
  9374. * | a | b | tx|
  9375. * | c | d | ty|
  9376. * | 0 | 0 | 1 |
  9377. *
  9378. * @class
  9379. * @memberof PIXI
  9380. */
  9381. function Matrix()
  9382. {
  9383. /**
  9384. * @member {number}
  9385. * @default 1
  9386. */
  9387. this.a = 1;
  9388. /**
  9389. * @member {number}
  9390. * @default 0
  9391. */
  9392. this.b = 0;
  9393. /**
  9394. * @member {number}
  9395. * @default 0
  9396. */
  9397. this.c = 0;
  9398. /**
  9399. * @member {number}
  9400. * @default 1
  9401. */
  9402. this.d = 1;
  9403. /**
  9404. * @member {number}
  9405. * @default 0
  9406. */
  9407. this.tx = 0;
  9408. /**
  9409. * @member {number}
  9410. * @default 0
  9411. */
  9412. this.ty = 0;
  9413. }
  9414. Matrix.prototype.constructor = Matrix;
  9415. module.exports = Matrix;
  9416. /**
  9417. * Creates a Matrix object based on the given array. The Element to Matrix mapping order is as follows:
  9418. *
  9419. * a = array[0]
  9420. * b = array[1]
  9421. * c = array[3]
  9422. * d = array[4]
  9423. * tx = array[2]
  9424. * ty = array[5]
  9425. *
  9426. * @param array {number[]} The array that the matrix will be populated from.
  9427. */
  9428. Matrix.prototype.fromArray = function (array)
  9429. {
  9430. this.a = array[0];
  9431. this.b = array[1];
  9432. this.c = array[3];
  9433. this.d = array[4];
  9434. this.tx = array[2];
  9435. this.ty = array[5];
  9436. };
  9437. /**
  9438. * sets the matrix properties
  9439. *
  9440. * @param {number} a
  9441. * @param {number} b
  9442. * @param {number} c
  9443. * @param {number} d
  9444. * @param {number} tx
  9445. * @param {number} ty
  9446. *
  9447. * @return {PIXI.Matrix} This matrix. Good for chaining method calls.
  9448. */
  9449. Matrix.prototype.set = function (a, b, c, d, tx, ty)
  9450. {
  9451. this.a = a;
  9452. this.b = b;
  9453. this.c = c;
  9454. this.d = d;
  9455. this.tx = tx;
  9456. this.ty = ty;
  9457. return this;
  9458. };
  9459. /**
  9460. * Creates an array from the current Matrix object.
  9461. *
  9462. * @param transpose {boolean} Whether we need to transpose the matrix or not
  9463. * @param [out] {Array} If provided the array will be assigned to out
  9464. * @return {number[]} the newly created array which contains the matrix
  9465. */
  9466. Matrix.prototype.toArray = function (transpose, out)
  9467. {
  9468. if (!this.array)
  9469. {
  9470. this.array = new Float32Array(9);
  9471. }
  9472. var array = out || this.array;
  9473. if (transpose)
  9474. {
  9475. array[0] = this.a;
  9476. array[1] = this.b;
  9477. array[2] = 0;
  9478. array[3] = this.c;
  9479. array[4] = this.d;
  9480. array[5] = 0;
  9481. array[6] = this.tx;
  9482. array[7] = this.ty;
  9483. array[8] = 1;
  9484. }
  9485. else
  9486. {
  9487. array[0] = this.a;
  9488. array[1] = this.c;
  9489. array[2] = this.tx;
  9490. array[3] = this.b;
  9491. array[4] = this.d;
  9492. array[5] = this.ty;
  9493. array[6] = 0;
  9494. array[7] = 0;
  9495. array[8] = 1;
  9496. }
  9497. return array;
  9498. };
  9499. /**
  9500. * Get a new position with the current transformation applied.
  9501. * Can be used to go from a child's coordinate space to the world coordinate space. (e.g. rendering)
  9502. *
  9503. * @param pos {PIXI.Point} The origin
  9504. * @param [newPos] {PIXI.Point} The point that the new position is assigned to (allowed to be same as input)
  9505. * @return {PIXI.Point} The new point, transformed through this matrix
  9506. */
  9507. Matrix.prototype.apply = function (pos, newPos)
  9508. {
  9509. newPos = newPos || new Point();
  9510. var x = pos.x;
  9511. var y = pos.y;
  9512. newPos.x = this.a * x + this.c * y + this.tx;
  9513. newPos.y = this.b * x + this.d * y + this.ty;
  9514. return newPos;
  9515. };
  9516. /**
  9517. * Get a new position with the inverse of the current transformation applied.
  9518. * Can be used to go from the world coordinate space to a child's coordinate space. (e.g. input)
  9519. *
  9520. * @param pos {PIXI.Point} The origin
  9521. * @param [newPos] {PIXI.Point} The point that the new position is assigned to (allowed to be same as input)
  9522. * @return {PIXI.Point} The new point, inverse-transformed through this matrix
  9523. */
  9524. Matrix.prototype.applyInverse = function (pos, newPos)
  9525. {
  9526. newPos = newPos || new Point();
  9527. var id = 1 / (this.a * this.d + this.c * -this.b);
  9528. var x = pos.x;
  9529. var y = pos.y;
  9530. newPos.x = this.d * id * x + -this.c * id * y + (this.ty * this.c - this.tx * this.d) * id;
  9531. newPos.y = this.a * id * y + -this.b * id * x + (-this.ty * this.a + this.tx * this.b) * id;
  9532. return newPos;
  9533. };
  9534. /**
  9535. * Translates the matrix on the x and y.
  9536. *
  9537. * @param {number} x
  9538. * @param {number} y
  9539. * @return {PIXI.Matrix} This matrix. Good for chaining method calls.
  9540. */
  9541. Matrix.prototype.translate = function (x, y)
  9542. {
  9543. this.tx += x;
  9544. this.ty += y;
  9545. return this;
  9546. };
  9547. /**
  9548. * Applies a scale transformation to the matrix.
  9549. *
  9550. * @param {number} x The amount to scale horizontally
  9551. * @param {number} y The amount to scale vertically
  9552. * @return {PIXI.Matrix} This matrix. Good for chaining method calls.
  9553. */
  9554. Matrix.prototype.scale = function (x, y)
  9555. {
  9556. this.a *= x;
  9557. this.d *= y;
  9558. this.c *= x;
  9559. this.b *= y;
  9560. this.tx *= x;
  9561. this.ty *= y;
  9562. return this;
  9563. };
  9564. /**
  9565. * Applies a rotation transformation to the matrix.
  9566. *
  9567. * @param {number} angle - The angle in radians.
  9568. * @return {PIXI.Matrix} This matrix. Good for chaining method calls.
  9569. */
  9570. Matrix.prototype.rotate = function (angle)
  9571. {
  9572. var cos = Math.cos( angle );
  9573. var sin = Math.sin( angle );
  9574. var a1 = this.a;
  9575. var c1 = this.c;
  9576. var tx1 = this.tx;
  9577. this.a = a1 * cos-this.b * sin;
  9578. this.b = a1 * sin+this.b * cos;
  9579. this.c = c1 * cos-this.d * sin;
  9580. this.d = c1 * sin+this.d * cos;
  9581. this.tx = tx1 * cos - this.ty * sin;
  9582. this.ty = tx1 * sin + this.ty * cos;
  9583. return this;
  9584. };
  9585. /**
  9586. * Appends the given Matrix to this Matrix.
  9587. *
  9588. * @param {PIXI.Matrix} matrix
  9589. * @return {PIXI.Matrix} This matrix. Good for chaining method calls.
  9590. */
  9591. Matrix.prototype.append = function (matrix)
  9592. {
  9593. var a1 = this.a;
  9594. var b1 = this.b;
  9595. var c1 = this.c;
  9596. var d1 = this.d;
  9597. this.a = matrix.a * a1 + matrix.b * c1;
  9598. this.b = matrix.a * b1 + matrix.b * d1;
  9599. this.c = matrix.c * a1 + matrix.d * c1;
  9600. this.d = matrix.c * b1 + matrix.d * d1;
  9601. this.tx = matrix.tx * a1 + matrix.ty * c1 + this.tx;
  9602. this.ty = matrix.tx * b1 + matrix.ty * d1 + this.ty;
  9603. return this;
  9604. };
  9605. /**
  9606. * Sets the matrix based on all the available properties
  9607. *
  9608. * @param {number} x
  9609. * @param {number} y
  9610. * @param {number} pivotX
  9611. * @param {number} pivotY
  9612. * @param {number} scaleX
  9613. * @param {number} scaleY
  9614. * @param {number} rotation
  9615. * @param {number} skewX
  9616. * @param {number} skewY
  9617. *
  9618. * @return {PIXI.Matrix} This matrix. Good for chaining method calls.
  9619. */
  9620. Matrix.prototype.setTransform = function (x, y, pivotX, pivotY, scaleX, scaleY, rotation, skewX, skewY)
  9621. {
  9622. var a, b, c, d, sr, cr, cy, sy, nsx, cx;
  9623. sr = Math.sin(rotation);
  9624. cr = Math.cos(rotation);
  9625. cy = Math.cos(skewY);
  9626. sy = Math.sin(skewY);
  9627. nsx = -Math.sin(skewX);
  9628. cx = Math.cos(skewX);
  9629. a = cr * scaleX;
  9630. b = sr * scaleX;
  9631. c = -sr * scaleY;
  9632. d = cr * scaleY;
  9633. this.a = cy * a + sy * c;
  9634. this.b = cy * b + sy * d;
  9635. this.c = nsx * a + cx * c;
  9636. this.d = nsx * b + cx * d;
  9637. this.tx = x + ( pivotX * a + pivotY * c );
  9638. this.ty = y + ( pivotX * b + pivotY * d );
  9639. return this;
  9640. };
  9641. /**
  9642. * Prepends the given Matrix to this Matrix.
  9643. *
  9644. * @param {PIXI.Matrix} matrix
  9645. * @return {PIXI.Matrix} This matrix. Good for chaining method calls.
  9646. */
  9647. Matrix.prototype.prepend = function(matrix)
  9648. {
  9649. var tx1 = this.tx;
  9650. if (matrix.a !== 1 || matrix.b !== 0 || matrix.c !== 0 || matrix.d !== 1)
  9651. {
  9652. var a1 = this.a;
  9653. var c1 = this.c;
  9654. this.a = a1*matrix.a+this.b*matrix.c;
  9655. this.b = a1*matrix.b+this.b*matrix.d;
  9656. this.c = c1*matrix.a+this.d*matrix.c;
  9657. this.d = c1*matrix.b+this.d*matrix.d;
  9658. }
  9659. this.tx = tx1*matrix.a+this.ty*matrix.c+matrix.tx;
  9660. this.ty = tx1*matrix.b+this.ty*matrix.d+matrix.ty;
  9661. return this;
  9662. };
  9663. /**
  9664. * Inverts this matrix
  9665. *
  9666. * @return {PIXI.Matrix} This matrix. Good for chaining method calls.
  9667. */
  9668. Matrix.prototype.invert = function()
  9669. {
  9670. var a1 = this.a;
  9671. var b1 = this.b;
  9672. var c1 = this.c;
  9673. var d1 = this.d;
  9674. var tx1 = this.tx;
  9675. var n = a1*d1-b1*c1;
  9676. this.a = d1/n;
  9677. this.b = -b1/n;
  9678. this.c = -c1/n;
  9679. this.d = a1/n;
  9680. this.tx = (c1*this.ty-d1*tx1)/n;
  9681. this.ty = -(a1*this.ty-b1*tx1)/n;
  9682. return this;
  9683. };
  9684. /**
  9685. * Resets this Matix to an identity (default) matrix.
  9686. *
  9687. * @return {PIXI.Matrix} This matrix. Good for chaining method calls.
  9688. */
  9689. Matrix.prototype.identity = function ()
  9690. {
  9691. this.a = 1;
  9692. this.b = 0;
  9693. this.c = 0;
  9694. this.d = 1;
  9695. this.tx = 0;
  9696. this.ty = 0;
  9697. return this;
  9698. };
  9699. /**
  9700. * Creates a new Matrix object with the same values as this one.
  9701. *
  9702. * @return {PIXI.Matrix} A copy of this matrix. Good for chaining method calls.
  9703. */
  9704. Matrix.prototype.clone = function ()
  9705. {
  9706. var matrix = new Matrix();
  9707. matrix.a = this.a;
  9708. matrix.b = this.b;
  9709. matrix.c = this.c;
  9710. matrix.d = this.d;
  9711. matrix.tx = this.tx;
  9712. matrix.ty = this.ty;
  9713. return matrix;
  9714. };
  9715. /**
  9716. * Changes the values of the given matrix to be the same as the ones in this matrix
  9717. *
  9718. * @return {PIXI.Matrix} The matrix given in parameter with its values updated.
  9719. */
  9720. Matrix.prototype.copy = function (matrix)
  9721. {
  9722. matrix.a = this.a;
  9723. matrix.b = this.b;
  9724. matrix.c = this.c;
  9725. matrix.d = this.d;
  9726. matrix.tx = this.tx;
  9727. matrix.ty = this.ty;
  9728. return matrix;
  9729. };
  9730. /**
  9731. * A default (identity) matrix
  9732. *
  9733. * @static
  9734. * @const
  9735. */
  9736. Matrix.IDENTITY = new Matrix();
  9737. /**
  9738. * A temp matrix
  9739. *
  9740. * @static
  9741. * @const
  9742. */
  9743. Matrix.TEMP_MATRIX = new Matrix();
  9744. },{"./Point":32}],32:[function(require,module,exports){
  9745. /**
  9746. * The Point object represents a location in a two-dimensional coordinate system, where x represents
  9747. * the horizontal axis and y represents the vertical axis.
  9748. *
  9749. * @class
  9750. * @memberof PIXI
  9751. * @param [x=0] {number} position of the point on the x axis
  9752. * @param [y=0] {number} position of the point on the y axis
  9753. */
  9754. function Point(x, y)
  9755. {
  9756. /**
  9757. * @member {number}
  9758. * @default 0
  9759. */
  9760. this.x = x || 0;
  9761. /**
  9762. * @member {number}
  9763. * @default 0
  9764. */
  9765. this.y = y || 0;
  9766. }
  9767. Point.prototype.constructor = Point;
  9768. module.exports = Point;
  9769. /**
  9770. * Creates a clone of this point
  9771. *
  9772. * @return {PIXI.Point} a copy of the point
  9773. */
  9774. Point.prototype.clone = function ()
  9775. {
  9776. return new Point(this.x, this.y);
  9777. };
  9778. /**
  9779. * Copies x and y from the given point
  9780. *
  9781. * @param p {PIXI.Point}
  9782. */
  9783. Point.prototype.copy = function (p) {
  9784. this.set(p.x, p.y);
  9785. };
  9786. /**
  9787. * Returns true if the given point is equal to this point
  9788. *
  9789. * @param p {PIXI.Point}
  9790. * @returns {boolean}
  9791. */
  9792. Point.prototype.equals = function (p) {
  9793. return (p.x === this.x) && (p.y === this.y);
  9794. };
  9795. /**
  9796. * Sets the point to a new x and y position.
  9797. * If y is omitted, both x and y will be set to x.
  9798. *
  9799. * @param [x=0] {number} position of the point on the x axis
  9800. * @param [y=0] {number} position of the point on the y axis
  9801. */
  9802. Point.prototype.set = function (x, y)
  9803. {
  9804. this.x = x || 0;
  9805. this.y = y || ( (y !== 0) ? this.x : 0 ) ;
  9806. };
  9807. },{}],33:[function(require,module,exports){
  9808. /**
  9809. * Math classes and utilities mixed into PIXI namespace.
  9810. *
  9811. * @lends PIXI
  9812. */
  9813. module.exports = {
  9814. // These will be mixed to be made publicly available,
  9815. // while this module is used internally in core
  9816. // to avoid circular dependencies and cut down on
  9817. // internal module requires.
  9818. Point: require('./Point'),
  9819. Matrix: require('./Matrix'),
  9820. GroupD8: require('./GroupD8'),
  9821. Circle: require('./shapes/Circle'),
  9822. Ellipse: require('./shapes/Ellipse'),
  9823. Polygon: require('./shapes/Polygon'),
  9824. Rectangle: require('./shapes/Rectangle'),
  9825. RoundedRectangle: require('./shapes/RoundedRectangle')
  9826. };
  9827. },{"./GroupD8":30,"./Matrix":31,"./Point":32,"./shapes/Circle":34,"./shapes/Ellipse":35,"./shapes/Polygon":36,"./shapes/Rectangle":37,"./shapes/RoundedRectangle":38}],34:[function(require,module,exports){
  9828. var Rectangle = require('./Rectangle'),
  9829. CONST = require('../../const');
  9830. /**
  9831. * The Circle object can be used to specify a hit area for displayObjects
  9832. *
  9833. * @class
  9834. * @memberof PIXI
  9835. * @param x {number} The X coordinate of the center of this circle
  9836. * @param y {number} The Y coordinate of the center of this circle
  9837. * @param radius {number} The radius of the circle
  9838. */
  9839. function Circle(x, y, radius)
  9840. {
  9841. /**
  9842. * @member {number}
  9843. * @default 0
  9844. */
  9845. this.x = x || 0;
  9846. /**
  9847. * @member {number}
  9848. * @default 0
  9849. */
  9850. this.y = y || 0;
  9851. /**
  9852. * @member {number}
  9853. * @default 0
  9854. */
  9855. this.radius = radius || 0;
  9856. /**
  9857. * The type of the object, mainly used to avoid `instanceof` checks
  9858. *
  9859. * @member {number}
  9860. */
  9861. this.type = CONST.SHAPES.CIRC;
  9862. }
  9863. Circle.prototype.constructor = Circle;
  9864. module.exports = Circle;
  9865. /**
  9866. * Creates a clone of this Circle instance
  9867. *
  9868. * @return {PIXI.Circle} a copy of the Circle
  9869. */
  9870. Circle.prototype.clone = function ()
  9871. {
  9872. return new Circle(this.x, this.y, this.radius);
  9873. };
  9874. /**
  9875. * Checks whether the x and y coordinates given are contained within this circle
  9876. *
  9877. * @param x {number} The X coordinate of the point to test
  9878. * @param y {number} The Y coordinate of the point to test
  9879. * @return {boolean} Whether the x/y coordinates are within this Circle
  9880. */
  9881. Circle.prototype.contains = function (x, y)
  9882. {
  9883. if (this.radius <= 0)
  9884. {
  9885. return false;
  9886. }
  9887. var dx = (this.x - x),
  9888. dy = (this.y - y),
  9889. r2 = this.radius * this.radius;
  9890. dx *= dx;
  9891. dy *= dy;
  9892. return (dx + dy <= r2);
  9893. };
  9894. /**
  9895. * Returns the framing rectangle of the circle as a Rectangle object
  9896. *
  9897. * @return {PIXI.Rectangle} the framing rectangle
  9898. */
  9899. Circle.prototype.getBounds = function ()
  9900. {
  9901. return new Rectangle(this.x - this.radius, this.y - this.radius, this.radius * 2, this.radius * 2);
  9902. };
  9903. },{"../../const":22,"./Rectangle":37}],35:[function(require,module,exports){
  9904. var Rectangle = require('./Rectangle'),
  9905. CONST = require('../../const');
  9906. /**
  9907. * The Ellipse object can be used to specify a hit area for displayObjects
  9908. *
  9909. * @class
  9910. * @memberof PIXI
  9911. * @param x {number} The X coordinate of the center of the ellipse
  9912. * @param y {number} The Y coordinate of the center of the ellipse
  9913. * @param width {number} The half width of this ellipse
  9914. * @param height {number} The half height of this ellipse
  9915. */
  9916. function Ellipse(x, y, width, height)
  9917. {
  9918. /**
  9919. * @member {number}
  9920. * @default 0
  9921. */
  9922. this.x = x || 0;
  9923. /**
  9924. * @member {number}
  9925. * @default 0
  9926. */
  9927. this.y = y || 0;
  9928. /**
  9929. * @member {number}
  9930. * @default 0
  9931. */
  9932. this.width = width || 0;
  9933. /**
  9934. * @member {number}
  9935. * @default 0
  9936. */
  9937. this.height = height || 0;
  9938. /**
  9939. * The type of the object, mainly used to avoid `instanceof` checks
  9940. *
  9941. * @member {number}
  9942. */
  9943. this.type = CONST.SHAPES.ELIP;
  9944. }
  9945. Ellipse.prototype.constructor = Ellipse;
  9946. module.exports = Ellipse;
  9947. /**
  9948. * Creates a clone of this Ellipse instance
  9949. *
  9950. * @return {PIXI.Ellipse} a copy of the ellipse
  9951. */
  9952. Ellipse.prototype.clone = function ()
  9953. {
  9954. return new Ellipse(this.x, this.y, this.width, this.height);
  9955. };
  9956. /**
  9957. * Checks whether the x and y coordinates given are contained within this ellipse
  9958. *
  9959. * @param x {number} The X coordinate of the point to test
  9960. * @param y {number} The Y coordinate of the point to test
  9961. * @return {boolean} Whether the x/y coords are within this ellipse
  9962. */
  9963. Ellipse.prototype.contains = function (x, y)
  9964. {
  9965. if (this.width <= 0 || this.height <= 0)
  9966. {
  9967. return false;
  9968. }
  9969. //normalize the coords to an ellipse with center 0,0
  9970. var normx = ((x - this.x) / this.width),
  9971. normy = ((y - this.y) / this.height);
  9972. normx *= normx;
  9973. normy *= normy;
  9974. return (normx + normy <= 1);
  9975. };
  9976. /**
  9977. * Returns the framing rectangle of the ellipse as a Rectangle object
  9978. *
  9979. * @return {PIXI.Rectangle} the framing rectangle
  9980. */
  9981. Ellipse.prototype.getBounds = function ()
  9982. {
  9983. return new Rectangle(this.x - this.width, this.y - this.height, this.width, this.height);
  9984. };
  9985. },{"../../const":22,"./Rectangle":37}],36:[function(require,module,exports){
  9986. var Point = require('../Point'),
  9987. CONST = require('../../const');
  9988. /**
  9989. * @class
  9990. * @memberof PIXI
  9991. * @param points {PIXI.Point[]|number[]|...PIXI.Point|...number} This can be an array of Points that form the polygon,
  9992. * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be
  9993. * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the
  9994. * arguments passed can be flat x,y values e.g. `new Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are
  9995. * Numbers.
  9996. */
  9997. function Polygon(points_)
  9998. {
  9999. // prevents an argument assignment deopt
  10000. // see section 3.1: https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments
  10001. var points = points_;
  10002. //if points isn't an array, use arguments as the array
  10003. if (!Array.isArray(points))
  10004. {
  10005. // prevents an argument leak deopt
  10006. // see section 3.2: https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments
  10007. points = new Array(arguments.length);
  10008. for (var a = 0; a < points.length; ++a) {
  10009. points[a] = arguments[a];
  10010. }
  10011. }
  10012. // if this is an array of points, convert it to a flat array of numbers
  10013. if (points[0] instanceof Point)
  10014. {
  10015. var p = [];
  10016. for (var i = 0, il = points.length; i < il; i++)
  10017. {
  10018. p.push(points[i].x, points[i].y);
  10019. }
  10020. points = p;
  10021. }
  10022. this.closed = true;
  10023. /**
  10024. * An array of the points of this polygon
  10025. *
  10026. * @member {number[]}
  10027. */
  10028. this.points = points;
  10029. /**
  10030. * The type of the object, mainly used to avoid `instanceof` checks
  10031. *
  10032. * @member {number}
  10033. */
  10034. this.type = CONST.SHAPES.POLY;
  10035. }
  10036. Polygon.prototype.constructor = Polygon;
  10037. module.exports = Polygon;
  10038. /**
  10039. * Creates a clone of this polygon
  10040. *
  10041. * @return {PIXI.Polygon} a copy of the polygon
  10042. */
  10043. Polygon.prototype.clone = function ()
  10044. {
  10045. return new Polygon(this.points.slice());
  10046. };
  10047. /**
  10048. * Checks whether the x and y coordinates passed to this function are contained within this polygon
  10049. *
  10050. * @param x {number} The X coordinate of the point to test
  10051. * @param y {number} The Y coordinate of the point to test
  10052. * @return {boolean} Whether the x/y coordinates are within this polygon
  10053. */
  10054. Polygon.prototype.contains = function (x, y)
  10055. {
  10056. var inside = false;
  10057. // use some raycasting to test hits
  10058. // https://github.com/substack/point-in-polygon/blob/master/index.js
  10059. var length = this.points.length / 2;
  10060. for (var i = 0, j = length - 1; i < length; j = i++)
  10061. {
  10062. var xi = this.points[i * 2], yi = this.points[i * 2 + 1],
  10063. xj = this.points[j * 2], yj = this.points[j * 2 + 1],
  10064. intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
  10065. if (intersect)
  10066. {
  10067. inside = !inside;
  10068. }
  10069. }
  10070. return inside;
  10071. };
  10072. },{"../../const":22,"../Point":32}],37:[function(require,module,exports){
  10073. var CONST = require('../../const');
  10074. /**
  10075. * the Rectangle object is an area defined by its position, as indicated by its top-left corner point (x, y) and by its width and its height.
  10076. *
  10077. * @class
  10078. * @memberof PIXI
  10079. * @param x {number} The X coordinate of the upper-left corner of the rectangle
  10080. * @param y {number} The Y coordinate of the upper-left corner of the rectangle
  10081. * @param width {number} The overall width of this rectangle
  10082. * @param height {number} The overall height of this rectangle
  10083. */
  10084. function Rectangle(x, y, width, height)
  10085. {
  10086. /**
  10087. * @member {number}
  10088. * @default 0
  10089. */
  10090. this.x = x || 0;
  10091. /**
  10092. * @member {number}
  10093. * @default 0
  10094. */
  10095. this.y = y || 0;
  10096. /**
  10097. * @member {number}
  10098. * @default 0
  10099. */
  10100. this.width = width || 0;
  10101. /**
  10102. * @member {number}
  10103. * @default 0
  10104. */
  10105. this.height = height || 0;
  10106. /**
  10107. * The type of the object, mainly used to avoid `instanceof` checks
  10108. *
  10109. * @member {number}
  10110. */
  10111. this.type = CONST.SHAPES.RECT;
  10112. }
  10113. Rectangle.prototype.constructor = Rectangle;
  10114. module.exports = Rectangle;
  10115. /**
  10116. * A constant empty rectangle.
  10117. *
  10118. * @static
  10119. * @constant
  10120. */
  10121. Rectangle.EMPTY = new Rectangle(0, 0, 0, 0);
  10122. /**
  10123. * Creates a clone of this Rectangle
  10124. *
  10125. * @return {PIXI.Rectangle} a copy of the rectangle
  10126. */
  10127. Rectangle.prototype.clone = function ()
  10128. {
  10129. return new Rectangle(this.x, this.y, this.width, this.height);
  10130. };
  10131. /**
  10132. * Checks whether the x and y coordinates given are contained within this Rectangle
  10133. *
  10134. * @param x {number} The X coordinate of the point to test
  10135. * @param y {number} The Y coordinate of the point to test
  10136. * @return {boolean} Whether the x/y coordinates are within this Rectangle
  10137. */
  10138. Rectangle.prototype.contains = function (x, y)
  10139. {
  10140. if (this.width <= 0 || this.height <= 0)
  10141. {
  10142. return false;
  10143. }
  10144. if (x >= this.x && x < this.x + this.width)
  10145. {
  10146. if (y >= this.y && y < this.y + this.height)
  10147. {
  10148. return true;
  10149. }
  10150. }
  10151. return false;
  10152. };
  10153. },{"../../const":22}],38:[function(require,module,exports){
  10154. var CONST = require('../../const');
  10155. /**
  10156. * The Rounded Rectangle object is an area that has nice rounded corners, as indicated by its top-left corner point (x, y) and by its width and its height and its radius.
  10157. *
  10158. * @class
  10159. * @memberof PIXI
  10160. * @param x {number} The X coordinate of the upper-left corner of the rounded rectangle
  10161. * @param y {number} The Y coordinate of the upper-left corner of the rounded rectangle
  10162. * @param width {number} The overall width of this rounded rectangle
  10163. * @param height {number} The overall height of this rounded rectangle
  10164. * @param radius {number} Controls the radius of the rounded corners
  10165. */
  10166. function RoundedRectangle(x, y, width, height, radius)
  10167. {
  10168. /**
  10169. * @member {number}
  10170. * @default 0
  10171. */
  10172. this.x = x || 0;
  10173. /**
  10174. * @member {number}
  10175. * @default 0
  10176. */
  10177. this.y = y || 0;
  10178. /**
  10179. * @member {number}
  10180. * @default 0
  10181. */
  10182. this.width = width || 0;
  10183. /**
  10184. * @member {number}
  10185. * @default 0
  10186. */
  10187. this.height = height || 0;
  10188. /**
  10189. * @member {number}
  10190. * @default 20
  10191. */
  10192. this.radius = radius || 20;
  10193. /**
  10194. * The type of the object, mainly used to avoid `instanceof` checks
  10195. *
  10196. * @member {number}
  10197. */
  10198. this.type = CONST.SHAPES.RREC;
  10199. }
  10200. RoundedRectangle.prototype.constructor = RoundedRectangle;
  10201. module.exports = RoundedRectangle;
  10202. /**
  10203. * Creates a clone of this Rounded Rectangle
  10204. *
  10205. * @return {PIXI.RoundedRectangle} a copy of the rounded rectangle
  10206. */
  10207. RoundedRectangle.prototype.clone = function ()
  10208. {
  10209. return new RoundedRectangle(this.x, this.y, this.width, this.height, this.radius);
  10210. };
  10211. /**
  10212. * Checks whether the x and y coordinates given are contained within this Rounded Rectangle
  10213. *
  10214. * @param x {number} The X coordinate of the point to test
  10215. * @param y {number} The Y coordinate of the point to test
  10216. * @return {boolean} Whether the x/y coordinates are within this Rounded Rectangle
  10217. */
  10218. RoundedRectangle.prototype.contains = function (x, y)
  10219. {
  10220. if (this.width <= 0 || this.height <= 0)
  10221. {
  10222. return false;
  10223. }
  10224. if (x >= this.x && x <= this.x + this.width)
  10225. {
  10226. if (y >= this.y && y <= this.y + this.height)
  10227. {
  10228. return true;
  10229. }
  10230. }
  10231. return false;
  10232. };
  10233. },{"../../const":22}],39:[function(require,module,exports){
  10234. var Container = require('../display/Container'),
  10235. CONST = require('../const');
  10236. /**
  10237. * The ParticleContainer class is a really fast version of the Container built solely for speed,
  10238. * so use when you need a lot of sprites or particles. The tradeoff of the ParticleContainer is that advanced
  10239. * functionality will not work. ParticleContainer implements only the basic object transform (position, scale, rotation).
  10240. * Any other functionality like tinting, masking, etc will not work on sprites in this batch.
  10241. *
  10242. * It's extremely easy to use :
  10243. *
  10244. * ```js
  10245. * var container = new ParticleContainer();
  10246. *
  10247. * for (var i = 0; i < 100; ++i)
  10248. * {
  10249. * var sprite = new PIXI.Sprite.fromImage("myImage.png");
  10250. * container.addChild(sprite);
  10251. * }
  10252. * ```
  10253. *
  10254. * And here you have a hundred sprites that will be renderer at the speed of light.
  10255. *
  10256. * @class
  10257. * @extends PIXI.Container
  10258. * @memberof PIXI
  10259. * @param [maxSize=15000] {number} The maximum number of particles that can be renderer by the container.
  10260. * @param [properties] {object} The properties of children that should be uploaded to the gpu and applied.
  10261. * @param [properties.scale=false] {boolean} When true, scale be uploaded and applied.
  10262. * @param [properties.position=true] {boolean} When true, position be uploaded and applied.
  10263. * @param [properties.rotation=false] {boolean} When true, rotation be uploaded and applied.
  10264. * @param [properties.uvs=false] {boolean} When true, uvs be uploaded and applied.
  10265. * @param [properties.alpha=false] {boolean} When true, alpha be uploaded and applied.
  10266. * @param [batchSize=15000] {number} Number of particles per batch.
  10267. */
  10268. function ParticleContainer(maxSize, properties, batchSize)
  10269. {
  10270. Container.call(this);
  10271. batchSize = batchSize || 15000; //CONST.SPRITE_BATCH_SIZE; // 2000 is a nice balance between mobile / desktop
  10272. maxSize = maxSize || 15000;
  10273. // Making sure the batch size is valid
  10274. // 65535 is max vertex index in the index buffer (see ParticleRenderer)
  10275. // so max number of particles is 65536 / 4 = 16384
  10276. var maxBatchSize = 16384;
  10277. if (batchSize > maxBatchSize) {
  10278. batchSize = maxBatchSize;
  10279. }
  10280. if (batchSize > maxSize) {
  10281. batchSize = maxSize;
  10282. }
  10283. /**
  10284. * Set properties to be dynamic (true) / static (false)
  10285. *
  10286. * @member {boolean[]}
  10287. * @private
  10288. */
  10289. this._properties = [false, true, false, false, false];
  10290. /**
  10291. * @member {number}
  10292. * @private
  10293. */
  10294. this._maxSize = maxSize;
  10295. /**
  10296. * @member {number}
  10297. * @private
  10298. */
  10299. this._batchSize = batchSize;
  10300. /**
  10301. * @member {WebGLBuffer}
  10302. * @private
  10303. */
  10304. this._buffers = null;
  10305. /**
  10306. * @member {number}
  10307. * @private
  10308. */
  10309. this._bufferToUpdate = 0;
  10310. /**
  10311. * @member {boolean}
  10312. *
  10313. */
  10314. this.interactiveChildren = false;
  10315. /**
  10316. * The blend mode to be applied to the sprite. Apply a value of `PIXI.BLEND_MODES.NORMAL` to reset the blend mode.
  10317. *
  10318. * @member {number}
  10319. * @default PIXI.BLEND_MODES.NORMAL
  10320. * @see PIXI.BLEND_MODES
  10321. */
  10322. this.blendMode = CONST.BLEND_MODES.NORMAL;
  10323. /**
  10324. * Used for canvas renderering. If true then the elements will be positioned at the nearest pixel. This provides a nice speed boost.
  10325. *
  10326. * @member {boolean}
  10327. * @default true;
  10328. */
  10329. this.roundPixels = true;
  10330. this.setProperties(properties);
  10331. }
  10332. ParticleContainer.prototype = Object.create(Container.prototype);
  10333. ParticleContainer.prototype.constructor = ParticleContainer;
  10334. module.exports = ParticleContainer;
  10335. /**
  10336. * Sets the private properties array to dynamic / static based on the passed properties object
  10337. *
  10338. * @param properties {object} The properties to be uploaded
  10339. */
  10340. ParticleContainer.prototype.setProperties = function(properties)
  10341. {
  10342. if ( properties ) {
  10343. this._properties[0] = 'scale' in properties ? !!properties.scale : this._properties[0];
  10344. this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1];
  10345. this._properties[2] = 'rotation' in properties ? !!properties.rotation : this._properties[2];
  10346. this._properties[3] = 'uvs' in properties ? !!properties.uvs : this._properties[3];
  10347. this._properties[4] = 'alpha' in properties ? !!properties.alpha : this._properties[4];
  10348. }
  10349. };
  10350. /**
  10351. * Updates the object transform for rendering
  10352. *
  10353. * @private
  10354. */
  10355. ParticleContainer.prototype.updateTransform = function ()
  10356. {
  10357. // TODO don't need to!
  10358. this.displayObjectUpdateTransform();
  10359. // PIXI.Container.prototype.updateTransform.call( this );
  10360. };
  10361. /**
  10362. * Renders the container using the WebGL renderer
  10363. *
  10364. * @param renderer {PIXI.WebGLRenderer} The webgl renderer
  10365. * @private
  10366. */
  10367. ParticleContainer.prototype.renderWebGL = function (renderer)
  10368. {
  10369. if (!this.visible || this.worldAlpha <= 0 || !this.children.length || !this.renderable)
  10370. {
  10371. return;
  10372. }
  10373. renderer.setObjectRenderer( renderer.plugins.particle );
  10374. renderer.plugins.particle.render( this );
  10375. };
  10376. /**
  10377. * Set the flag that static data should be updated to true
  10378. *
  10379. * @private
  10380. */
  10381. ParticleContainer.prototype.onChildrenChange = function (smallestChildIndex)
  10382. {
  10383. var bufferIndex = Math.floor(smallestChildIndex / this._batchSize);
  10384. if (bufferIndex < this._bufferToUpdate) {
  10385. this._bufferToUpdate = bufferIndex;
  10386. }
  10387. };
  10388. /**
  10389. * Renders the object using the Canvas renderer
  10390. *
  10391. * @param renderer {PIXI.CanvasRenderer} The canvas renderer
  10392. * @private
  10393. */
  10394. ParticleContainer.prototype.renderCanvas = function (renderer)
  10395. {
  10396. if (!this.visible || this.worldAlpha <= 0 || !this.children.length || !this.renderable)
  10397. {
  10398. return;
  10399. }
  10400. var context = renderer.context;
  10401. var transform = this.worldTransform;
  10402. var isRotated = true;
  10403. var positionX = 0;
  10404. var positionY = 0;
  10405. var finalWidth = 0;
  10406. var finalHeight = 0;
  10407. var compositeOperation = renderer.blendModes[this.blendMode];
  10408. if (compositeOperation !== context.globalCompositeOperation)
  10409. {
  10410. context.globalCompositeOperation = compositeOperation;
  10411. }
  10412. context.globalAlpha = this.worldAlpha;
  10413. this.displayObjectUpdateTransform();
  10414. for (var i = 0; i < this.children.length; ++i)
  10415. {
  10416. var child = this.children[i];
  10417. if (!child.visible)
  10418. {
  10419. continue;
  10420. }
  10421. var frame = child.texture.frame;
  10422. context.globalAlpha = this.worldAlpha * child.alpha;
  10423. if (child.rotation % (Math.PI * 2) === 0)
  10424. {
  10425. // this is the fastest way to optimise! - if rotation is 0 then we can avoid any kind of setTransform call
  10426. if (isRotated)
  10427. {
  10428. context.setTransform(
  10429. transform.a,
  10430. transform.b,
  10431. transform.c,
  10432. transform.d,
  10433. transform.tx,
  10434. transform.ty
  10435. );
  10436. isRotated = false;
  10437. }
  10438. positionX = ((child.anchor.x) * (-frame.width * child.scale.x) + child.position.x + 0.5);
  10439. positionY = ((child.anchor.y) * (-frame.height * child.scale.y) + child.position.y + 0.5);
  10440. finalWidth = frame.width * child.scale.x;
  10441. finalHeight = frame.height * child.scale.y;
  10442. }
  10443. else
  10444. {
  10445. if (!isRotated)
  10446. {
  10447. isRotated = true;
  10448. }
  10449. child.displayObjectUpdateTransform();
  10450. var childTransform = child.worldTransform;
  10451. if (renderer.roundPixels)
  10452. {
  10453. context.setTransform(
  10454. childTransform.a,
  10455. childTransform.b,
  10456. childTransform.c,
  10457. childTransform.d,
  10458. childTransform.tx | 0,
  10459. childTransform.ty | 0
  10460. );
  10461. }
  10462. else
  10463. {
  10464. context.setTransform(
  10465. childTransform.a,
  10466. childTransform.b,
  10467. childTransform.c,
  10468. childTransform.d,
  10469. childTransform.tx,
  10470. childTransform.ty
  10471. );
  10472. }
  10473. positionX = ((child.anchor.x) * (-frame.width) + 0.5);
  10474. positionY = ((child.anchor.y) * (-frame.height) + 0.5);
  10475. finalWidth = frame.width;
  10476. finalHeight = frame.height;
  10477. }
  10478. context.drawImage(
  10479. child.texture.baseTexture.source,
  10480. frame.x,
  10481. frame.y,
  10482. frame.width,
  10483. frame.height,
  10484. positionX,
  10485. positionY,
  10486. finalWidth,
  10487. finalHeight
  10488. );
  10489. }
  10490. };
  10491. /**
  10492. * Destroys the container
  10493. *
  10494. * @param [destroyChildren=false] {boolean} if set to true, all the children will have their destroy method called as well
  10495. */
  10496. ParticleContainer.prototype.destroy = function () {
  10497. Container.prototype.destroy.apply(this, arguments);
  10498. if (this._buffers) {
  10499. for (var i = 0; i < this._buffers.length; ++i) {
  10500. this._buffers[i].destroy();
  10501. }
  10502. }
  10503. this._properties = null;
  10504. this._buffers = null;
  10505. };
  10506. },{"../const":22,"../display/Container":23}],40:[function(require,module,exports){
  10507. /**
  10508. * @author Mat Groves
  10509. *
  10510. * Big thanks to the very clever Matt DesLauriers <mattdesl> https://github.com/mattdesl/
  10511. * for creating the original pixi version!
  10512. * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer
  10513. *
  10514. * Heavily inspired by LibGDX's ParticleBuffer:
  10515. * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/ParticleBuffer.java
  10516. */
  10517. /**
  10518. * The particle buffer manages the static and dynamic buffers for a particle container.
  10519. *
  10520. * @class
  10521. * @private
  10522. * @memberof PIXI
  10523. */
  10524. function ParticleBuffer(gl, properties, dynamicPropertyFlags, size)
  10525. {
  10526. /**
  10527. * The current WebGL drawing context.
  10528. *
  10529. * @member {WebGLRenderingContext}
  10530. */
  10531. this.gl = gl;
  10532. /**
  10533. * Size of a single vertex.
  10534. *
  10535. * @member {number}
  10536. */
  10537. this.vertSize = 2;
  10538. /**
  10539. * Size of a single vertex in bytes.
  10540. *
  10541. * @member {number}
  10542. */
  10543. this.vertByteSize = this.vertSize * 4;
  10544. /**
  10545. * The number of particles the buffer can hold
  10546. *
  10547. * @member {number}
  10548. */
  10549. this.size = size;
  10550. /**
  10551. * A list of the properties that are dynamic.
  10552. *
  10553. * @member {object[]}
  10554. */
  10555. this.dynamicProperties = [];
  10556. /**
  10557. * A list of the properties that are static.
  10558. *
  10559. * @member {object[]}
  10560. */
  10561. this.staticProperties = [];
  10562. for (var i = 0; i < properties.length; i++)
  10563. {
  10564. var property = properties[i];
  10565. if(dynamicPropertyFlags[i])
  10566. {
  10567. this.dynamicProperties.push(property);
  10568. }
  10569. else
  10570. {
  10571. this.staticProperties.push(property);
  10572. }
  10573. }
  10574. this.staticStride = 0;
  10575. this.staticBuffer = null;
  10576. this.staticData = null;
  10577. this.dynamicStride = 0;
  10578. this.dynamicBuffer = null;
  10579. this.dynamicData = null;
  10580. this.initBuffers();
  10581. }
  10582. ParticleBuffer.prototype.constructor = ParticleBuffer;
  10583. module.exports = ParticleBuffer;
  10584. /**
  10585. * Sets up the renderer context and necessary buffers.
  10586. *
  10587. * @private
  10588. */
  10589. ParticleBuffer.prototype.initBuffers = function ()
  10590. {
  10591. var gl = this.gl;
  10592. var i;
  10593. var property;
  10594. var dynamicOffset = 0;
  10595. this.dynamicStride = 0;
  10596. for (i = 0; i < this.dynamicProperties.length; i++)
  10597. {
  10598. property = this.dynamicProperties[i];
  10599. property.offset = dynamicOffset;
  10600. dynamicOffset += property.size;
  10601. this.dynamicStride += property.size;
  10602. }
  10603. this.dynamicData = new Float32Array( this.size * this.dynamicStride * 4);
  10604. this.dynamicBuffer = gl.createBuffer();
  10605. gl.bindBuffer(gl.ARRAY_BUFFER, this.dynamicBuffer);
  10606. gl.bufferData(gl.ARRAY_BUFFER, this.dynamicData, gl.DYNAMIC_DRAW);
  10607. // static //
  10608. var staticOffset = 0;
  10609. this.staticStride = 0;
  10610. for (i = 0; i < this.staticProperties.length; i++)
  10611. {
  10612. property = this.staticProperties[i];
  10613. property.offset = staticOffset;
  10614. staticOffset += property.size;
  10615. this.staticStride += property.size;
  10616. }
  10617. this.staticData = new Float32Array( this.size * this.staticStride * 4);
  10618. this.staticBuffer = gl.createBuffer();
  10619. gl.bindBuffer(gl.ARRAY_BUFFER, this.staticBuffer);
  10620. gl.bufferData(gl.ARRAY_BUFFER, this.staticData, gl.DYNAMIC_DRAW);
  10621. };
  10622. /**
  10623. * Uploads the dynamic properties.
  10624. *
  10625. */
  10626. ParticleBuffer.prototype.uploadDynamic = function(children, startIndex, amount)
  10627. {
  10628. var gl = this.gl;
  10629. for (var i = 0; i < this.dynamicProperties.length; i++)
  10630. {
  10631. var property = this.dynamicProperties[i];
  10632. property.uploadFunction(children, startIndex, amount, this.dynamicData, this.dynamicStride, property.offset);
  10633. }
  10634. gl.bindBuffer(gl.ARRAY_BUFFER, this.dynamicBuffer);
  10635. gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.dynamicData);
  10636. };
  10637. /**
  10638. * Uploads the static properties.
  10639. *
  10640. */
  10641. ParticleBuffer.prototype.uploadStatic = function(children, startIndex, amount)
  10642. {
  10643. var gl = this.gl;
  10644. for (var i = 0; i < this.staticProperties.length; i++)
  10645. {
  10646. var property = this.staticProperties[i];
  10647. property.uploadFunction(children, startIndex, amount, this.staticData, this.staticStride, property.offset);
  10648. }
  10649. gl.bindBuffer(gl.ARRAY_BUFFER, this.staticBuffer);
  10650. gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.staticData);
  10651. };
  10652. /**
  10653. * Binds the buffers to the GPU
  10654. *
  10655. */
  10656. ParticleBuffer.prototype.bind = function ()
  10657. {
  10658. var gl = this.gl;
  10659. var i, property;
  10660. gl.bindBuffer(gl.ARRAY_BUFFER, this.dynamicBuffer);
  10661. for (i = 0; i < this.dynamicProperties.length; i++)
  10662. {
  10663. property = this.dynamicProperties[i];
  10664. gl.vertexAttribPointer(property.attribute, property.size, gl.FLOAT, false, this.dynamicStride * 4, property.offset * 4);
  10665. }
  10666. gl.bindBuffer(gl.ARRAY_BUFFER, this.staticBuffer);
  10667. for (i = 0; i < this.staticProperties.length; i++)
  10668. {
  10669. property = this.staticProperties[i];
  10670. gl.vertexAttribPointer(property.attribute, property.size, gl.FLOAT, false, this.staticStride * 4, property.offset * 4);
  10671. }
  10672. };
  10673. /**
  10674. * Destroys the ParticleBuffer.
  10675. *
  10676. */
  10677. ParticleBuffer.prototype.destroy = function ()
  10678. {
  10679. this.dynamicProperties = null;
  10680. this.dynamicData = null;
  10681. this.gl.deleteBuffer(this.dynamicBuffer);
  10682. this.staticProperties = null;
  10683. this.staticData = null;
  10684. this.gl.deleteBuffer(this.staticBuffer);
  10685. };
  10686. },{}],41:[function(require,module,exports){
  10687. var ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'),
  10688. WebGLRenderer = require('../../renderers/webgl/WebGLRenderer'),
  10689. ParticleShader = require('./ParticleShader'),
  10690. ParticleBuffer = require('./ParticleBuffer'),
  10691. math = require('../../math');
  10692. /**
  10693. * @author Mat Groves
  10694. *
  10695. * Big thanks to the very clever Matt DesLauriers <mattdesl> https://github.com/mattdesl/
  10696. * for creating the original pixi version!
  10697. * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer
  10698. *
  10699. * Heavily inspired by LibGDX's ParticleRenderer:
  10700. * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/ParticleRenderer.java
  10701. */
  10702. /**
  10703. *
  10704. * @class
  10705. * @private
  10706. * @memberof PIXI
  10707. * @param renderer {PIXI.WebGLRenderer} The renderer this sprite batch works for.
  10708. */
  10709. function ParticleRenderer(renderer)
  10710. {
  10711. ObjectRenderer.call(this, renderer);
  10712. // 65535 is max vertex index in the index buffer (see ParticleRenderer)
  10713. // so max number of particles is 65536 / 4 = 16384
  10714. // and max number of element in the index buffer is 16384 * 6 = 98304
  10715. // Creating a full index buffer, overhead is 98304 * 2 = 196Ko
  10716. var numIndices = 98304;
  10717. /**
  10718. * Holds the indices
  10719. *
  10720. * @member {Uint16Array}
  10721. */
  10722. this.indices = new Uint16Array(numIndices);
  10723. for (var i=0, j=0; i < numIndices; i += 6, j += 4)
  10724. {
  10725. this.indices[i + 0] = j + 0;
  10726. this.indices[i + 1] = j + 1;
  10727. this.indices[i + 2] = j + 2;
  10728. this.indices[i + 3] = j + 0;
  10729. this.indices[i + 4] = j + 2;
  10730. this.indices[i + 5] = j + 3;
  10731. }
  10732. /**
  10733. * The default shader that is used if a sprite doesn't have a more specific one.
  10734. *
  10735. * @member {PIXI.Shader}
  10736. */
  10737. this.shader = null;
  10738. this.indexBuffer = null;
  10739. this.properties = null;
  10740. this.tempMatrix = new math.Matrix();
  10741. }
  10742. ParticleRenderer.prototype = Object.create(ObjectRenderer.prototype);
  10743. ParticleRenderer.prototype.constructor = ParticleRenderer;
  10744. module.exports = ParticleRenderer;
  10745. WebGLRenderer.registerPlugin('particle', ParticleRenderer);
  10746. /**
  10747. * When there is a WebGL context change
  10748. *
  10749. * @private
  10750. */
  10751. ParticleRenderer.prototype.onContextChange = function ()
  10752. {
  10753. var gl = this.renderer.gl;
  10754. // setup default shader
  10755. this.shader = new ParticleShader(this.renderer.shaderManager);
  10756. this.indexBuffer = gl.createBuffer();
  10757. // 65535 is max index, so 65535 / 6 = 10922.
  10758. //upload the index data
  10759. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
  10760. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);
  10761. this.properties = [
  10762. // verticesData
  10763. {
  10764. attribute:this.shader.attributes.aVertexPosition,
  10765. size:2,
  10766. uploadFunction:this.uploadVertices,
  10767. offset:0
  10768. },
  10769. // positionData
  10770. {
  10771. attribute:this.shader.attributes.aPositionCoord,
  10772. size:2,
  10773. uploadFunction:this.uploadPosition,
  10774. offset:0
  10775. },
  10776. // rotationData
  10777. {
  10778. attribute:this.shader.attributes.aRotation,
  10779. size:1,
  10780. uploadFunction:this.uploadRotation,
  10781. offset:0
  10782. },
  10783. // uvsData
  10784. {
  10785. attribute:this.shader.attributes.aTextureCoord,
  10786. size:2,
  10787. uploadFunction:this.uploadUvs,
  10788. offset:0
  10789. },
  10790. // alphaData
  10791. {
  10792. attribute:this.shader.attributes.aColor,
  10793. size:1,
  10794. uploadFunction:this.uploadAlpha,
  10795. offset:0
  10796. }
  10797. ];
  10798. };
  10799. /**
  10800. * Starts a new particle batch.
  10801. *
  10802. */
  10803. ParticleRenderer.prototype.start = function ()
  10804. {
  10805. var gl = this.renderer.gl;
  10806. // bind the main texture
  10807. gl.activeTexture(gl.TEXTURE0);
  10808. // bind the buffers
  10809. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
  10810. var shader = this.shader;
  10811. this.renderer.shaderManager.setShader(shader);
  10812. };
  10813. /**
  10814. * Renders the particle container object.
  10815. *
  10816. * @param container {PIXI.ParticleContainer} The container to render using this ParticleRenderer
  10817. */
  10818. ParticleRenderer.prototype.render = function (container)
  10819. {
  10820. var children = container.children,
  10821. totalChildren = children.length,
  10822. maxSize = container._maxSize,
  10823. batchSize = container._batchSize;
  10824. if(totalChildren === 0)
  10825. {
  10826. return;
  10827. }
  10828. else if(totalChildren > maxSize)
  10829. {
  10830. totalChildren = maxSize;
  10831. }
  10832. if(!container._buffers)
  10833. {
  10834. container._buffers = this.generateBuffers( container );
  10835. }
  10836. // if the uvs have not updated then no point rendering just yet!
  10837. this.renderer.blendModeManager.setBlendMode(container.blendMode);
  10838. var gl = this.renderer.gl;
  10839. var m = container.worldTransform.copy( this.tempMatrix );
  10840. m.prepend( this.renderer.currentRenderTarget.projectionMatrix );
  10841. gl.uniformMatrix3fv(this.shader.uniforms.projectionMatrix._location, false, m.toArray(true));
  10842. gl.uniform1f(this.shader.uniforms.uAlpha._location, container.worldAlpha);
  10843. // make sure the texture is bound..
  10844. var baseTexture = children[0]._texture.baseTexture;
  10845. if (!baseTexture._glTextures[gl.id])
  10846. {
  10847. // if the texture has not updated then lets not upload any static properties
  10848. if(!this.renderer.updateTexture(baseTexture))
  10849. {
  10850. return;
  10851. }
  10852. if(!container._properties[0] || !container._properties[3])
  10853. {
  10854. container._bufferToUpdate = 0;
  10855. }
  10856. }
  10857. else
  10858. {
  10859. gl.bindTexture(gl.TEXTURE_2D, baseTexture._glTextures[gl.id]);
  10860. }
  10861. // now lets upload and render the buffers..
  10862. for (var i = 0, j = 0; i < totalChildren; i += batchSize, j += 1)
  10863. {
  10864. var amount = ( totalChildren - i);
  10865. if(amount > batchSize)
  10866. {
  10867. amount = batchSize;
  10868. }
  10869. var buffer = container._buffers[j];
  10870. // we always upload the dynamic
  10871. buffer.uploadDynamic(children, i, amount);
  10872. // we only upload the static content when we have to!
  10873. if(container._bufferToUpdate === j)
  10874. {
  10875. buffer.uploadStatic(children, i, amount);
  10876. container._bufferToUpdate = j + 1;
  10877. }
  10878. // bind the buffer
  10879. buffer.bind( this.shader );
  10880. // now draw those suckas!
  10881. gl.drawElements(gl.TRIANGLES, amount * 6, gl.UNSIGNED_SHORT, 0);
  10882. this.renderer.drawCount++;
  10883. }
  10884. };
  10885. /**
  10886. * Creates one particle buffer for each child in the container we want to render and updates internal properties
  10887. *
  10888. * @param container {PIXI.ParticleContainer} The container to render using this ParticleRenderer
  10889. */
  10890. ParticleRenderer.prototype.generateBuffers = function (container)
  10891. {
  10892. var gl = this.renderer.gl,
  10893. buffers = [],
  10894. size = container._maxSize,
  10895. batchSize = container._batchSize,
  10896. dynamicPropertyFlags = container._properties,
  10897. i;
  10898. for (i = 0; i < size; i += batchSize)
  10899. {
  10900. buffers.push(new ParticleBuffer(gl, this.properties, dynamicPropertyFlags, batchSize));
  10901. }
  10902. return buffers;
  10903. };
  10904. /**
  10905. * Uploads the verticies.
  10906. *
  10907. * @param children {PIXI.DisplayObject[]} the array of display objects to render
  10908. * @param startIndex {number} the index to start from in the children array
  10909. * @param amount {number} the amount of children that will have their vertices uploaded
  10910. * @param array {number[]}
  10911. * @param stride {number}
  10912. * @param offset {number}
  10913. */
  10914. ParticleRenderer.prototype.uploadVertices = function (children, startIndex, amount, array, stride, offset)
  10915. {
  10916. var sprite,
  10917. texture,
  10918. trim,
  10919. sx,
  10920. sy,
  10921. w0, w1, h0, h1;
  10922. for (var i = 0; i < amount; i++) {
  10923. sprite = children[startIndex + i];
  10924. texture = sprite._texture;
  10925. sx = sprite.scale.x;
  10926. sy = sprite.scale.y;
  10927. if (texture.trim)
  10928. {
  10929. // if the sprite is trimmed then we need to add the extra space before transforming the sprite coords..
  10930. trim = texture.trim;
  10931. w1 = trim.x - sprite.anchor.x * trim.width;
  10932. w0 = w1 + texture.crop.width;
  10933. h1 = trim.y - sprite.anchor.y * trim.height;
  10934. h0 = h1 + texture.crop.height;
  10935. }
  10936. else
  10937. {
  10938. w0 = (texture._frame.width ) * (1-sprite.anchor.x);
  10939. w1 = (texture._frame.width ) * -sprite.anchor.x;
  10940. h0 = texture._frame.height * (1-sprite.anchor.y);
  10941. h1 = texture._frame.height * -sprite.anchor.y;
  10942. }
  10943. array[offset] = w1 * sx;
  10944. array[offset + 1] = h1 * sy;
  10945. array[offset + stride] = w0 * sx;
  10946. array[offset + stride + 1] = h1 * sy;
  10947. array[offset + stride * 2] = w0 * sx;
  10948. array[offset + stride * 2 + 1] = h0 * sy;
  10949. array[offset + stride * 3] = w1 * sx;
  10950. array[offset + stride * 3 + 1] = h0 * sy;
  10951. offset += stride * 4;
  10952. }
  10953. };
  10954. /**
  10955. *
  10956. * @param children {PIXI.DisplayObject[]} the array of display objects to render
  10957. * @param startIndex {number} the index to start from in the children array
  10958. * @param amount {number} the amount of children that will have their positions uploaded
  10959. * @param array {number[]}
  10960. * @param stride {number}
  10961. * @param offset {number}
  10962. */
  10963. ParticleRenderer.prototype.uploadPosition = function (children,startIndex, amount, array, stride, offset)
  10964. {
  10965. for (var i = 0; i < amount; i++)
  10966. {
  10967. var spritePosition = children[startIndex + i].position;
  10968. array[offset] = spritePosition.x;
  10969. array[offset + 1] = spritePosition.y;
  10970. array[offset + stride] = spritePosition.x;
  10971. array[offset + stride + 1] = spritePosition.y;
  10972. array[offset + stride * 2] = spritePosition.x;
  10973. array[offset + stride * 2 + 1] = spritePosition.y;
  10974. array[offset + stride * 3] = spritePosition.x;
  10975. array[offset + stride * 3 + 1] = spritePosition.y;
  10976. offset += stride * 4;
  10977. }
  10978. };
  10979. /**
  10980. *
  10981. * @param children {PIXI.DisplayObject[]} the array of display objects to render
  10982. * @param startIndex {number} the index to start from in the children array
  10983. * @param amount {number} the amount of children that will have their rotation uploaded
  10984. * @param array {number[]}
  10985. * @param stride {number}
  10986. * @param offset {number}
  10987. */
  10988. ParticleRenderer.prototype.uploadRotation = function (children,startIndex, amount, array, stride, offset)
  10989. {
  10990. for (var i = 0; i < amount; i++)
  10991. {
  10992. var spriteRotation = children[startIndex + i].rotation;
  10993. array[offset] = spriteRotation;
  10994. array[offset + stride] = spriteRotation;
  10995. array[offset + stride * 2] = spriteRotation;
  10996. array[offset + stride * 3] = spriteRotation;
  10997. offset += stride * 4;
  10998. }
  10999. };
  11000. /**
  11001. *
  11002. * @param children {PIXI.DisplayObject[]} the array of display objects to render
  11003. * @param startIndex {number} the index to start from in the children array
  11004. * @param amount {number} the amount of children that will have their Uvs uploaded
  11005. * @param array {number[]}
  11006. * @param stride {number}
  11007. * @param offset {number}
  11008. */
  11009. ParticleRenderer.prototype.uploadUvs = function (children,startIndex, amount, array, stride, offset)
  11010. {
  11011. for (var i = 0; i < amount; i++)
  11012. {
  11013. var textureUvs = children[startIndex + i]._texture._uvs;
  11014. if (textureUvs)
  11015. {
  11016. array[offset] = textureUvs.x0;
  11017. array[offset + 1] = textureUvs.y0;
  11018. array[offset + stride] = textureUvs.x1;
  11019. array[offset + stride + 1] = textureUvs.y1;
  11020. array[offset + stride * 2] = textureUvs.x2;
  11021. array[offset + stride * 2 + 1] = textureUvs.y2;
  11022. array[offset + stride * 3] = textureUvs.x3;
  11023. array[offset + stride * 3 + 1] = textureUvs.y3;
  11024. offset += stride * 4;
  11025. }
  11026. else
  11027. {
  11028. //TODO you know this can be easier!
  11029. array[offset] = 0;
  11030. array[offset + 1] = 0;
  11031. array[offset + stride] = 0;
  11032. array[offset + stride + 1] = 0;
  11033. array[offset + stride * 2] = 0;
  11034. array[offset + stride * 2 + 1] = 0;
  11035. array[offset + stride * 3] = 0;
  11036. array[offset + stride * 3 + 1] = 0;
  11037. offset += stride * 4;
  11038. }
  11039. }
  11040. };
  11041. /**
  11042. *
  11043. * @param children {PIXI.DisplayObject[]} the array of display objects to render
  11044. * @param startIndex {number} the index to start from in the children array
  11045. * @param amount {number} the amount of children that will have their alpha uploaded
  11046. * @param array {number[]}
  11047. * @param stride {number}
  11048. * @param offset {number}
  11049. */
  11050. ParticleRenderer.prototype.uploadAlpha = function (children,startIndex, amount, array, stride, offset)
  11051. {
  11052. for (var i = 0; i < amount; i++)
  11053. {
  11054. var spriteAlpha = children[startIndex + i].alpha;
  11055. array[offset] = spriteAlpha;
  11056. array[offset + stride] = spriteAlpha;
  11057. array[offset + stride * 2] = spriteAlpha;
  11058. array[offset + stride * 3] = spriteAlpha;
  11059. offset += stride * 4;
  11060. }
  11061. };
  11062. /**
  11063. * Destroys the ParticleRenderer.
  11064. *
  11065. */
  11066. ParticleRenderer.prototype.destroy = function ()
  11067. {
  11068. if (this.renderer.gl) {
  11069. this.renderer.gl.deleteBuffer(this.indexBuffer);
  11070. }
  11071. ObjectRenderer.prototype.destroy.apply(this, arguments);
  11072. this.shader.destroy();
  11073. this.indices = null;
  11074. this.tempMatrix = null;
  11075. };
  11076. },{"../../math":33,"../../renderers/webgl/WebGLRenderer":49,"../../renderers/webgl/utils/ObjectRenderer":63,"./ParticleBuffer":40,"./ParticleShader":42}],42:[function(require,module,exports){
  11077. var TextureShader = require('../../renderers/webgl/shaders/TextureShader');
  11078. /**
  11079. * @class
  11080. * @extends PIXI.TextureShader
  11081. * @memberof PIXI
  11082. * @param shaderManager {ShaderManager} The webgl shader manager this shader works for.
  11083. */
  11084. function ParticleShader(shaderManager)
  11085. {
  11086. TextureShader.call(this,
  11087. shaderManager,
  11088. // vertex shader
  11089. [
  11090. 'attribute vec2 aVertexPosition;',
  11091. 'attribute vec2 aTextureCoord;',
  11092. 'attribute float aColor;',
  11093. 'attribute vec2 aPositionCoord;',
  11094. 'attribute vec2 aScale;',
  11095. 'attribute float aRotation;',
  11096. 'uniform mat3 projectionMatrix;',
  11097. 'varying vec2 vTextureCoord;',
  11098. 'varying float vColor;',
  11099. 'void main(void){',
  11100. ' vec2 v = aVertexPosition;',
  11101. ' v.x = (aVertexPosition.x) * cos(aRotation) - (aVertexPosition.y) * sin(aRotation);',
  11102. ' v.y = (aVertexPosition.x) * sin(aRotation) + (aVertexPosition.y) * cos(aRotation);',
  11103. ' v = v + aPositionCoord;',
  11104. ' gl_Position = vec4((projectionMatrix * vec3(v, 1.0)).xy, 0.0, 1.0);',
  11105. ' vTextureCoord = aTextureCoord;',
  11106. ' vColor = aColor;',
  11107. '}'
  11108. ].join('\n'),
  11109. // hello
  11110. [
  11111. 'precision lowp float;',
  11112. 'varying vec2 vTextureCoord;',
  11113. 'varying float vColor;',
  11114. 'uniform sampler2D uSampler;',
  11115. 'uniform float uAlpha;',
  11116. 'void main(void){',
  11117. ' vec4 color = texture2D(uSampler, vTextureCoord) * vColor * uAlpha;',
  11118. ' if (color.a == 0.0) discard;',
  11119. ' gl_FragColor = color;',
  11120. '}'
  11121. ].join('\n'),
  11122. // custom uniforms
  11123. {
  11124. uAlpha: { type: '1f', value: 1 }
  11125. },
  11126. // custom attributes
  11127. {
  11128. aPositionCoord: 0,
  11129. // aScale: 0,
  11130. aRotation: 0
  11131. }
  11132. );
  11133. // TEMP HACK
  11134. }
  11135. ParticleShader.prototype = Object.create(TextureShader.prototype);
  11136. ParticleShader.prototype.constructor = ParticleShader;
  11137. module.exports = ParticleShader;
  11138. },{"../../renderers/webgl/shaders/TextureShader":62}],43:[function(require,module,exports){
  11139. var utils = require('../utils'),
  11140. math = require('../math'),
  11141. CONST = require('../const'),
  11142. EventEmitter = require('eventemitter3');
  11143. /**
  11144. * The CanvasRenderer draws the scene and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL.
  11145. * Don't forget to add the CanvasRenderer.view to your DOM or you will not see anything :)
  11146. *
  11147. * @class
  11148. * @memberof PIXI
  11149. * @param system {string} The name of the system this renderer is for.
  11150. * @param [width=800] {number} the width of the canvas view
  11151. * @param [height=600] {number} the height of the canvas view
  11152. * @param [options] {object} The optional renderer parameters
  11153. * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional
  11154. * @param [options.transparent=false] {boolean} If the render view is transparent, default false
  11155. * @param [options.autoResize=false] {boolean} If the render view is automatically resized, default false
  11156. * @param [options.antialias=false] {boolean} sets antialias (only applicable in chrome at the moment)
  11157. * @param [options.resolution=1] {number} the resolution of the renderer retina would be 2
  11158. * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or
  11159. * not before the new render pass.
  11160. * @param [options.backgroundColor=0x000000] {number} The background color of the rendered area (shown if not transparent).
  11161. * @param [options.roundPixels=false] {boolean} If true Pixi will Math.floor() x/y values when rendering, stopping pixel interpolation.
  11162. */
  11163. function SystemRenderer(system, width, height, options)
  11164. {
  11165. EventEmitter.call(this);
  11166. utils.sayHello(system);
  11167. // prepare options
  11168. if (options)
  11169. {
  11170. for (var i in CONST.DEFAULT_RENDER_OPTIONS)
  11171. {
  11172. if (typeof options[i] === 'undefined')
  11173. {
  11174. options[i] = CONST.DEFAULT_RENDER_OPTIONS[i];
  11175. }
  11176. }
  11177. }
  11178. else
  11179. {
  11180. options = CONST.DEFAULT_RENDER_OPTIONS;
  11181. }
  11182. /**
  11183. * The type of the renderer.
  11184. *
  11185. * @member {number}
  11186. * @default PIXI.RENDERER_TYPE.UNKNOWN
  11187. * @see PIXI.RENDERER_TYPE
  11188. */
  11189. this.type = CONST.RENDERER_TYPE.UNKNOWN;
  11190. /**
  11191. * The width of the canvas view
  11192. *
  11193. * @member {number}
  11194. * @default 800
  11195. */
  11196. this.width = width || 800;
  11197. /**
  11198. * The height of the canvas view
  11199. *
  11200. * @member {number}
  11201. * @default 600
  11202. */
  11203. this.height = height || 600;
  11204. /**
  11205. * The canvas element that everything is drawn to
  11206. *
  11207. * @member {HTMLCanvasElement}
  11208. */
  11209. this.view = options.view || document.createElement('canvas');
  11210. /**
  11211. * The resolution of the renderer
  11212. *
  11213. * @member {number}
  11214. * @default 1
  11215. */
  11216. this.resolution = options.resolution;
  11217. /**
  11218. * Whether the render view is transparent
  11219. *
  11220. * @member {boolean}
  11221. */
  11222. this.transparent = options.transparent;
  11223. /**
  11224. * Whether the render view should be resized automatically
  11225. *
  11226. * @member {boolean}
  11227. */
  11228. this.autoResize = options.autoResize || false;
  11229. /**
  11230. * Tracks the blend modes useful for this renderer.
  11231. *
  11232. * @member {object<string, mixed>}
  11233. */
  11234. this.blendModes = null;
  11235. /**
  11236. * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering.
  11237. *
  11238. * @member {boolean}
  11239. */
  11240. this.preserveDrawingBuffer = options.preserveDrawingBuffer;
  11241. /**
  11242. * This sets if the CanvasRenderer will clear the canvas or not before the new render pass.
  11243. * If the scene is NOT transparent Pixi will use a canvas sized fillRect operation every frame to set the canvas background color.
  11244. * If the scene is transparent Pixi will use clearRect to clear the canvas every frame.
  11245. * Disable this by setting this to false. For example if your game has a canvas filling background image you often don't need this set.
  11246. *
  11247. * @member {boolean}
  11248. * @default
  11249. */
  11250. this.clearBeforeRender = options.clearBeforeRender;
  11251. /**
  11252. * If true Pixi will Math.floor() x/y values when rendering, stopping pixel interpolation.
  11253. * Handy for crisp pixel art and speed on legacy devices.
  11254. *
  11255. * @member {boolean}
  11256. */
  11257. this.roundPixels = options.roundPixels;
  11258. /**
  11259. * The background color as a number.
  11260. *
  11261. * @member {number}
  11262. * @private
  11263. */
  11264. this._backgroundColor = 0x000000;
  11265. /**
  11266. * The background color as an [R, G, B] array.
  11267. *
  11268. * @member {number[]}
  11269. * @private
  11270. */
  11271. this._backgroundColorRgb = [0, 0, 0];
  11272. /**
  11273. * The background color as a string.
  11274. *
  11275. * @member {string}
  11276. * @private
  11277. */
  11278. this._backgroundColorString = '#000000';
  11279. this.backgroundColor = options.backgroundColor || this._backgroundColor; // run bg color setter
  11280. /**
  11281. * This temporary display object used as the parent of the currently being rendered item
  11282. *
  11283. * @member {PIXI.DisplayObject}
  11284. * @private
  11285. */
  11286. this._tempDisplayObjectParent = {worldTransform:new math.Matrix(), worldAlpha:1, children:[]};
  11287. /**
  11288. * The last root object that the renderer tried to render.
  11289. *
  11290. * @member {PIXI.DisplayObject}
  11291. * @private
  11292. */
  11293. this._lastObjectRendered = this._tempDisplayObjectParent;
  11294. }
  11295. // constructor
  11296. SystemRenderer.prototype = Object.create(EventEmitter.prototype);
  11297. SystemRenderer.prototype.constructor = SystemRenderer;
  11298. module.exports = SystemRenderer;
  11299. Object.defineProperties(SystemRenderer.prototype, {
  11300. /**
  11301. * The background color to fill if not transparent
  11302. *
  11303. * @member {number}
  11304. * @memberof PIXI.SystemRenderer#
  11305. */
  11306. backgroundColor:
  11307. {
  11308. get: function ()
  11309. {
  11310. return this._backgroundColor;
  11311. },
  11312. set: function (val)
  11313. {
  11314. this._backgroundColor = val;
  11315. this._backgroundColorString = utils.hex2string(val);
  11316. utils.hex2rgb(val, this._backgroundColorRgb);
  11317. }
  11318. }
  11319. });
  11320. /**
  11321. * Resizes the canvas view to the specified width and height
  11322. *
  11323. * @param width {number} the new width of the canvas view
  11324. * @param height {number} the new height of the canvas view
  11325. */
  11326. SystemRenderer.prototype.resize = function (width, height) {
  11327. this.width = width * this.resolution;
  11328. this.height = height * this.resolution;
  11329. this.view.width = this.width;
  11330. this.view.height = this.height;
  11331. if (this.autoResize)
  11332. {
  11333. this.view.style.width = this.width / this.resolution + 'px';
  11334. this.view.style.height = this.height / this.resolution + 'px';
  11335. }
  11336. };
  11337. /**
  11338. * Removes everything from the renderer and optionally removes the Canvas DOM element.
  11339. *
  11340. * @param [removeView=false] {boolean} Removes the Canvas element from the DOM.
  11341. */
  11342. SystemRenderer.prototype.destroy = function (removeView) {
  11343. if (removeView && this.view.parentNode)
  11344. {
  11345. this.view.parentNode.removeChild(this.view);
  11346. }
  11347. this.type = CONST.RENDERER_TYPE.UNKNOWN;
  11348. this.width = 0;
  11349. this.height = 0;
  11350. this.view = null;
  11351. this.resolution = 0;
  11352. this.transparent = false;
  11353. this.autoResize = false;
  11354. this.blendModes = null;
  11355. this.preserveDrawingBuffer = false;
  11356. this.clearBeforeRender = false;
  11357. this.roundPixels = false;
  11358. this._backgroundColor = 0;
  11359. this._backgroundColorRgb = null;
  11360. this._backgroundColorString = null;
  11361. };
  11362. },{"../const":22,"../math":33,"../utils":77,"eventemitter3":10}],44:[function(require,module,exports){
  11363. var SystemRenderer = require('../SystemRenderer'),
  11364. CanvasMaskManager = require('./utils/CanvasMaskManager'),
  11365. utils = require('../../utils'),
  11366. math = require('../../math'),
  11367. CONST = require('../../const');
  11368. /**
  11369. * The CanvasRenderer draws the scene and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL.
  11370. * Don't forget to add the CanvasRenderer.view to your DOM or you will not see anything :)
  11371. *
  11372. * @class
  11373. * @memberof PIXI
  11374. * @extends PIXI.SystemRenderer
  11375. * @param [width=800] {number} the width of the canvas view
  11376. * @param [height=600] {number} the height of the canvas view
  11377. * @param [options] {object} The optional renderer parameters
  11378. * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional
  11379. * @param [options.transparent=false] {boolean} If the render view is transparent, default false
  11380. * @param [options.autoResize=false] {boolean} If the render view is automatically resized, default false
  11381. * @param [options.antialias=false] {boolean} sets antialias (only applicable in chrome at the moment)
  11382. * @param [options.resolution=1] {number} the resolution of the renderer retina would be 2
  11383. * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or
  11384. * not before the new render pass.
  11385. * @param [options.roundPixels=false] {boolean} If true Pixi will Math.floor() x/y values when rendering, stopping pixel interpolation.
  11386. */
  11387. function CanvasRenderer(width, height, options)
  11388. {
  11389. options = options || {};
  11390. SystemRenderer.call(this, 'Canvas', width, height, options);
  11391. this.type = CONST.RENDERER_TYPE.CANVAS;
  11392. /**
  11393. * The canvas 2d context that everything is drawn with.
  11394. *
  11395. * @member {CanvasRenderingContext2D}
  11396. */
  11397. this.context = this.view.getContext('2d', { alpha: this.transparent });
  11398. /**
  11399. * Boolean flag controlling canvas refresh.
  11400. *
  11401. * @member {boolean}
  11402. */
  11403. this.refresh = true;
  11404. /**
  11405. * Instance of a CanvasMaskManager, handles masking when using the canvas renderer.
  11406. *
  11407. * @member {PIXI.CanvasMaskManager}
  11408. */
  11409. this.maskManager = new CanvasMaskManager();
  11410. /**
  11411. * The canvas property used to set the canvas smoothing property.
  11412. *
  11413. * @member {string}
  11414. */
  11415. this.smoothProperty = 'imageSmoothingEnabled';
  11416. if (!this.context.imageSmoothingEnabled)
  11417. {
  11418. if (this.context.webkitImageSmoothingEnabled)
  11419. {
  11420. this.smoothProperty = 'webkitImageSmoothingEnabled';
  11421. }
  11422. else if (this.context.mozImageSmoothingEnabled)
  11423. {
  11424. this.smoothProperty = 'mozImageSmoothingEnabled';
  11425. }
  11426. else if (this.context.oImageSmoothingEnabled)
  11427. {
  11428. this.smoothProperty = 'oImageSmoothingEnabled';
  11429. }
  11430. else if (this.context.msImageSmoothingEnabled)
  11431. {
  11432. this.smoothProperty = 'msImageSmoothingEnabled';
  11433. }
  11434. }
  11435. this.initPlugins();
  11436. this._mapBlendModes();
  11437. /**
  11438. * This temporary display object used as the parent of the currently being rendered item
  11439. *
  11440. * @member {PIXI.DisplayObject}
  11441. * @private
  11442. */
  11443. this._tempDisplayObjectParent = {
  11444. worldTransform: new math.Matrix(),
  11445. worldAlpha: 1
  11446. };
  11447. this.resize(width, height);
  11448. }
  11449. // constructor
  11450. CanvasRenderer.prototype = Object.create(SystemRenderer.prototype);
  11451. CanvasRenderer.prototype.constructor = CanvasRenderer;
  11452. module.exports = CanvasRenderer;
  11453. utils.pluginTarget.mixin(CanvasRenderer);
  11454. /**
  11455. * Renders the object to this canvas view
  11456. *
  11457. * @param object {PIXI.DisplayObject} the object to be rendered
  11458. */
  11459. CanvasRenderer.prototype.render = function (object)
  11460. {
  11461. this.emit('prerender');
  11462. var cacheParent = object.parent;
  11463. this._lastObjectRendered = object;
  11464. object.parent = this._tempDisplayObjectParent;
  11465. // update the scene graph
  11466. object.updateTransform();
  11467. object.parent = cacheParent;
  11468. this.context.setTransform(1, 0, 0, 1, 0, 0);
  11469. this.context.globalAlpha = 1;
  11470. this.context.globalCompositeOperation = this.blendModes[CONST.BLEND_MODES.NORMAL];
  11471. if (navigator.isCocoonJS && this.view.screencanvas)
  11472. {
  11473. this.context.fillStyle = 'black';
  11474. this.context.clear();
  11475. }
  11476. if (this.clearBeforeRender)
  11477. {
  11478. if (this.transparent)
  11479. {
  11480. this.context.clearRect(0, 0, this.width, this.height);
  11481. }
  11482. else
  11483. {
  11484. this.context.fillStyle = this._backgroundColorString;
  11485. this.context.fillRect(0, 0, this.width , this.height);
  11486. }
  11487. }
  11488. this.renderDisplayObject(object, this.context);
  11489. this.emit('postrender');
  11490. };
  11491. /**
  11492. * Removes everything from the renderer and optionally removes the Canvas DOM element.
  11493. *
  11494. * @param [removeView=false] {boolean} Removes the Canvas element from the DOM.
  11495. */
  11496. CanvasRenderer.prototype.destroy = function (removeView)
  11497. {
  11498. this.destroyPlugins();
  11499. // call the base destroy
  11500. SystemRenderer.prototype.destroy.call(this, removeView);
  11501. this.context = null;
  11502. this.refresh = true;
  11503. this.maskManager.destroy();
  11504. this.maskManager = null;
  11505. this.smoothProperty = null;
  11506. };
  11507. /**
  11508. * Renders a display object
  11509. *
  11510. * @param displayObject {PIXI.DisplayObject} The displayObject to render
  11511. * @private
  11512. */
  11513. CanvasRenderer.prototype.renderDisplayObject = function (displayObject, context)
  11514. {
  11515. var tempContext = this.context;
  11516. this.context = context;
  11517. displayObject.renderCanvas(this);
  11518. this.context = tempContext;
  11519. };
  11520. /**
  11521. * @extends PIXI.SystemRenderer#resize
  11522. *
  11523. * @param {number} w
  11524. * @param {number} h
  11525. */
  11526. CanvasRenderer.prototype.resize = function (w, h)
  11527. {
  11528. SystemRenderer.prototype.resize.call(this, w, h);
  11529. //reset the scale mode.. oddly this seems to be reset when the canvas is resized.
  11530. //surely a browser bug?? Let pixi fix that for you..
  11531. if(this.smoothProperty)
  11532. {
  11533. this.context[this.smoothProperty] = (CONST.SCALE_MODES.DEFAULT === CONST.SCALE_MODES.LINEAR);
  11534. }
  11535. };
  11536. /**
  11537. * Maps Pixi blend modes to canvas blend modes.
  11538. *
  11539. * @private
  11540. */
  11541. CanvasRenderer.prototype._mapBlendModes = function ()
  11542. {
  11543. if (!this.blendModes)
  11544. {
  11545. this.blendModes = {};
  11546. if (utils.canUseNewCanvasBlendModes())
  11547. {
  11548. this.blendModes[CONST.BLEND_MODES.NORMAL] = 'source-over';
  11549. this.blendModes[CONST.BLEND_MODES.ADD] = 'lighter'; //IS THIS OK???
  11550. this.blendModes[CONST.BLEND_MODES.MULTIPLY] = 'multiply';
  11551. this.blendModes[CONST.BLEND_MODES.SCREEN] = 'screen';
  11552. this.blendModes[CONST.BLEND_MODES.OVERLAY] = 'overlay';
  11553. this.blendModes[CONST.BLEND_MODES.DARKEN] = 'darken';
  11554. this.blendModes[CONST.BLEND_MODES.LIGHTEN] = 'lighten';
  11555. this.blendModes[CONST.BLEND_MODES.COLOR_DODGE] = 'color-dodge';
  11556. this.blendModes[CONST.BLEND_MODES.COLOR_BURN] = 'color-burn';
  11557. this.blendModes[CONST.BLEND_MODES.HARD_LIGHT] = 'hard-light';
  11558. this.blendModes[CONST.BLEND_MODES.SOFT_LIGHT] = 'soft-light';
  11559. this.blendModes[CONST.BLEND_MODES.DIFFERENCE] = 'difference';
  11560. this.blendModes[CONST.BLEND_MODES.EXCLUSION] = 'exclusion';
  11561. this.blendModes[CONST.BLEND_MODES.HUE] = 'hue';
  11562. this.blendModes[CONST.BLEND_MODES.SATURATION] = 'saturate';
  11563. this.blendModes[CONST.BLEND_MODES.COLOR] = 'color';
  11564. this.blendModes[CONST.BLEND_MODES.LUMINOSITY] = 'luminosity';
  11565. }
  11566. else
  11567. {
  11568. // this means that the browser does not support the cool new blend modes in canvas 'cough' ie 'cough'
  11569. this.blendModes[CONST.BLEND_MODES.NORMAL] = 'source-over';
  11570. this.blendModes[CONST.BLEND_MODES.ADD] = 'lighter'; //IS THIS OK???
  11571. this.blendModes[CONST.BLEND_MODES.MULTIPLY] = 'source-over';
  11572. this.blendModes[CONST.BLEND_MODES.SCREEN] = 'source-over';
  11573. this.blendModes[CONST.BLEND_MODES.OVERLAY] = 'source-over';
  11574. this.blendModes[CONST.BLEND_MODES.DARKEN] = 'source-over';
  11575. this.blendModes[CONST.BLEND_MODES.LIGHTEN] = 'source-over';
  11576. this.blendModes[CONST.BLEND_MODES.COLOR_DODGE] = 'source-over';
  11577. this.blendModes[CONST.BLEND_MODES.COLOR_BURN] = 'source-over';
  11578. this.blendModes[CONST.BLEND_MODES.HARD_LIGHT] = 'source-over';
  11579. this.blendModes[CONST.BLEND_MODES.SOFT_LIGHT] = 'source-over';
  11580. this.blendModes[CONST.BLEND_MODES.DIFFERENCE] = 'source-over';
  11581. this.blendModes[CONST.BLEND_MODES.EXCLUSION] = 'source-over';
  11582. this.blendModes[CONST.BLEND_MODES.HUE] = 'source-over';
  11583. this.blendModes[CONST.BLEND_MODES.SATURATION] = 'source-over';
  11584. this.blendModes[CONST.BLEND_MODES.COLOR] = 'source-over';
  11585. this.blendModes[CONST.BLEND_MODES.LUMINOSITY] = 'source-over';
  11586. }
  11587. }
  11588. };
  11589. },{"../../const":22,"../../math":33,"../../utils":77,"../SystemRenderer":43,"./utils/CanvasMaskManager":47}],45:[function(require,module,exports){
  11590. /**
  11591. * Creates a Canvas element of the given size.
  11592. *
  11593. * @class
  11594. * @memberof PIXI
  11595. * @param width {number} the width for the newly created canvas
  11596. * @param height {number} the height for the newly created canvas
  11597. */
  11598. function CanvasBuffer(width, height)
  11599. {
  11600. /**
  11601. * The Canvas object that belongs to this CanvasBuffer.
  11602. *
  11603. * @member {HTMLCanvasElement}
  11604. */
  11605. this.canvas = document.createElement('canvas');
  11606. /**
  11607. * A CanvasRenderingContext2D object representing a two-dimensional rendering context.
  11608. *
  11609. * @member {CanvasRenderingContext2D}
  11610. */
  11611. this.context = this.canvas.getContext('2d');
  11612. this.canvas.width = width;
  11613. this.canvas.height = height;
  11614. }
  11615. CanvasBuffer.prototype.constructor = CanvasBuffer;
  11616. module.exports = CanvasBuffer;
  11617. Object.defineProperties(CanvasBuffer.prototype, {
  11618. /**
  11619. * The width of the canvas buffer in pixels.
  11620. *
  11621. * @member {number}
  11622. * @memberof PIXI.CanvasBuffer#
  11623. */
  11624. width: {
  11625. get: function ()
  11626. {
  11627. return this.canvas.width;
  11628. },
  11629. set: function (val)
  11630. {
  11631. this.canvas.width = val;
  11632. }
  11633. },
  11634. /**
  11635. * The height of the canvas buffer in pixels.
  11636. *
  11637. * @member {number}
  11638. * @memberof PIXI.CanvasBuffer#
  11639. */
  11640. height: {
  11641. get: function ()
  11642. {
  11643. return this.canvas.height;
  11644. },
  11645. set: function (val)
  11646. {
  11647. this.canvas.height = val;
  11648. }
  11649. }
  11650. });
  11651. /**
  11652. * Clears the canvas that was created by the CanvasBuffer class.
  11653. *
  11654. * @private
  11655. */
  11656. CanvasBuffer.prototype.clear = function ()
  11657. {
  11658. this.context.setTransform(1, 0, 0, 1, 0, 0);
  11659. this.context.clearRect(0,0, this.canvas.width, this.canvas.height);
  11660. };
  11661. /**
  11662. * Resizes the canvas to the specified width and height.
  11663. *
  11664. * @param width {number} the new width of the canvas
  11665. * @param height {number} the new height of the canvas
  11666. */
  11667. CanvasBuffer.prototype.resize = function (width, height)
  11668. {
  11669. this.canvas.width = width;
  11670. this.canvas.height = height;
  11671. };
  11672. /**
  11673. * Destroys this canvas.
  11674. *
  11675. */
  11676. CanvasBuffer.prototype.destroy = function ()
  11677. {
  11678. this.context = null;
  11679. this.canvas = null;
  11680. };
  11681. },{}],46:[function(require,module,exports){
  11682. var CONST = require('../../../const');
  11683. /**
  11684. * A set of functions used by the canvas renderer to draw the primitive graphics data.
  11685. * @static
  11686. * @class
  11687. * @memberof PIXI
  11688. */
  11689. var CanvasGraphics = {};
  11690. module.exports = CanvasGraphics;
  11691. /*
  11692. * Renders a Graphics object to a canvas.
  11693. *
  11694. * @param graphics {PIXI.Graphics} the actual graphics object to render
  11695. * @param context {CanvasRenderingContext2D} the 2d drawing method of the canvas
  11696. */
  11697. CanvasGraphics.renderGraphics = function (graphics, context)
  11698. {
  11699. var worldAlpha = graphics.worldAlpha;
  11700. if (graphics.dirty)
  11701. {
  11702. this.updateGraphicsTint(graphics);
  11703. graphics.dirty = false;
  11704. }
  11705. for (var i = 0; i < graphics.graphicsData.length; i++)
  11706. {
  11707. var data = graphics.graphicsData[i];
  11708. var shape = data.shape;
  11709. var fillColor = data._fillTint;
  11710. var lineColor = data._lineTint;
  11711. context.lineWidth = data.lineWidth;
  11712. if (data.type === CONST.SHAPES.POLY)
  11713. {
  11714. context.beginPath();
  11715. var points = shape.points;
  11716. context.moveTo(points[0], points[1]);
  11717. for (var j=1; j < points.length/2; j++)
  11718. {
  11719. context.lineTo(points[j * 2], points[j * 2 + 1]);
  11720. }
  11721. if (shape.closed)
  11722. {
  11723. context.lineTo(points[0], points[1]);
  11724. }
  11725. // if the first and last point are the same close the path - much neater :)
  11726. if (points[0] === points[points.length-2] && points[1] === points[points.length-1])
  11727. {
  11728. context.closePath();
  11729. }
  11730. if (data.fill)
  11731. {
  11732. context.globalAlpha = data.fillAlpha * worldAlpha;
  11733. context.fillStyle = '#' + ('00000' + ( fillColor | 0).toString(16)).substr(-6);
  11734. context.fill();
  11735. }
  11736. if (data.lineWidth)
  11737. {
  11738. context.globalAlpha = data.lineAlpha * worldAlpha;
  11739. context.strokeStyle = '#' + ('00000' + ( lineColor | 0).toString(16)).substr(-6);
  11740. context.stroke();
  11741. }
  11742. }
  11743. else if (data.type === CONST.SHAPES.RECT)
  11744. {
  11745. if (data.fillColor || data.fillColor === 0)
  11746. {
  11747. context.globalAlpha = data.fillAlpha * worldAlpha;
  11748. context.fillStyle = '#' + ('00000' + ( fillColor | 0).toString(16)).substr(-6);
  11749. context.fillRect(shape.x, shape.y, shape.width, shape.height);
  11750. }
  11751. if (data.lineWidth)
  11752. {
  11753. context.globalAlpha = data.lineAlpha * worldAlpha;
  11754. context.strokeStyle = '#' + ('00000' + ( lineColor | 0).toString(16)).substr(-6);
  11755. context.strokeRect(shape.x, shape.y, shape.width, shape.height);
  11756. }
  11757. }
  11758. else if (data.type === CONST.SHAPES.CIRC)
  11759. {
  11760. // TODO - need to be Undefined!
  11761. context.beginPath();
  11762. context.arc(shape.x, shape.y, shape.radius,0,2*Math.PI);
  11763. context.closePath();
  11764. if (data.fill)
  11765. {
  11766. context.globalAlpha = data.fillAlpha * worldAlpha;
  11767. context.fillStyle = '#' + ('00000' + ( fillColor | 0).toString(16)).substr(-6);
  11768. context.fill();
  11769. }
  11770. if (data.lineWidth)
  11771. {
  11772. context.globalAlpha = data.lineAlpha * worldAlpha;
  11773. context.strokeStyle = '#' + ('00000' + ( lineColor | 0).toString(16)).substr(-6);
  11774. context.stroke();
  11775. }
  11776. }
  11777. else if (data.type === CONST.SHAPES.ELIP)
  11778. {
  11779. // ellipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
  11780. var w = shape.width * 2;
  11781. var h = shape.height * 2;
  11782. var x = shape.x - w/2;
  11783. var y = shape.y - h/2;
  11784. context.beginPath();
  11785. var kappa = 0.5522848,
  11786. ox = (w / 2) * kappa, // control point offset horizontal
  11787. oy = (h / 2) * kappa, // control point offset vertical
  11788. xe = x + w, // x-end
  11789. ye = y + h, // y-end
  11790. xm = x + w / 2, // x-middle
  11791. ym = y + h / 2; // y-middle
  11792. context.moveTo(x, ym);
  11793. context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
  11794. context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
  11795. context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
  11796. context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
  11797. context.closePath();
  11798. if (data.fill)
  11799. {
  11800. context.globalAlpha = data.fillAlpha * worldAlpha;
  11801. context.fillStyle = '#' + ('00000' + ( fillColor | 0).toString(16)).substr(-6);
  11802. context.fill();
  11803. }
  11804. if (data.lineWidth)
  11805. {
  11806. context.globalAlpha = data.lineAlpha * worldAlpha;
  11807. context.strokeStyle = '#' + ('00000' + ( lineColor | 0).toString(16)).substr(-6);
  11808. context.stroke();
  11809. }
  11810. }
  11811. else if (data.type === CONST.SHAPES.RREC)
  11812. {
  11813. var rx = shape.x;
  11814. var ry = shape.y;
  11815. var width = shape.width;
  11816. var height = shape.height;
  11817. var radius = shape.radius;
  11818. var maxRadius = Math.min(width, height) / 2 | 0;
  11819. radius = radius > maxRadius ? maxRadius : radius;
  11820. context.beginPath();
  11821. context.moveTo(rx, ry + radius);
  11822. context.lineTo(rx, ry + height - radius);
  11823. context.quadraticCurveTo(rx, ry + height, rx + radius, ry + height);
  11824. context.lineTo(rx + width - radius, ry + height);
  11825. context.quadraticCurveTo(rx + width, ry + height, rx + width, ry + height - radius);
  11826. context.lineTo(rx + width, ry + radius);
  11827. context.quadraticCurveTo(rx + width, ry, rx + width - radius, ry);
  11828. context.lineTo(rx + radius, ry);
  11829. context.quadraticCurveTo(rx, ry, rx, ry + radius);
  11830. context.closePath();
  11831. if (data.fillColor || data.fillColor === 0)
  11832. {
  11833. context.globalAlpha = data.fillAlpha * worldAlpha;
  11834. context.fillStyle = '#' + ('00000' + ( fillColor | 0).toString(16)).substr(-6);
  11835. context.fill();
  11836. }
  11837. if (data.lineWidth)
  11838. {
  11839. context.globalAlpha = data.lineAlpha * worldAlpha;
  11840. context.strokeStyle = '#' + ('00000' + ( lineColor | 0).toString(16)).substr(-6);
  11841. context.stroke();
  11842. }
  11843. }
  11844. }
  11845. };
  11846. /*
  11847. * Renders a graphics mask
  11848. *
  11849. * @private
  11850. * @param graphics {PIXI.Graphics} the graphics which will be used as a mask
  11851. * @param context {CanvasRenderingContext2D} the context 2d method of the canvas
  11852. */
  11853. CanvasGraphics.renderGraphicsMask = function (graphics, context)
  11854. {
  11855. var len = graphics.graphicsData.length;
  11856. if (len === 0)
  11857. {
  11858. return;
  11859. }
  11860. context.beginPath();
  11861. for (var i = 0; i < len; i++)
  11862. {
  11863. var data = graphics.graphicsData[i];
  11864. var shape = data.shape;
  11865. if (data.type === CONST.SHAPES.POLY)
  11866. {
  11867. var points = shape.points;
  11868. context.moveTo(points[0], points[1]);
  11869. for (var j=1; j < points.length/2; j++)
  11870. {
  11871. context.lineTo(points[j * 2], points[j * 2 + 1]);
  11872. }
  11873. // if the first and last point are the same close the path - much neater :)
  11874. if (points[0] === points[points.length-2] && points[1] === points[points.length-1])
  11875. {
  11876. context.closePath();
  11877. }
  11878. }
  11879. else if (data.type === CONST.SHAPES.RECT)
  11880. {
  11881. context.rect(shape.x, shape.y, shape.width, shape.height);
  11882. context.closePath();
  11883. }
  11884. else if (data.type === CONST.SHAPES.CIRC)
  11885. {
  11886. // TODO - need to be Undefined!
  11887. context.arc(shape.x, shape.y, shape.radius, 0, 2 * Math.PI);
  11888. context.closePath();
  11889. }
  11890. else if (data.type === CONST.SHAPES.ELIP)
  11891. {
  11892. // ellipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
  11893. var w = shape.width * 2;
  11894. var h = shape.height * 2;
  11895. var x = shape.x - w/2;
  11896. var y = shape.y - h/2;
  11897. var kappa = 0.5522848,
  11898. ox = (w / 2) * kappa, // control point offset horizontal
  11899. oy = (h / 2) * kappa, // control point offset vertical
  11900. xe = x + w, // x-end
  11901. ye = y + h, // y-end
  11902. xm = x + w / 2, // x-middle
  11903. ym = y + h / 2; // y-middle
  11904. context.moveTo(x, ym);
  11905. context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
  11906. context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
  11907. context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
  11908. context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
  11909. context.closePath();
  11910. }
  11911. else if (data.type === CONST.SHAPES.RREC)
  11912. {
  11913. var rx = shape.x;
  11914. var ry = shape.y;
  11915. var width = shape.width;
  11916. var height = shape.height;
  11917. var radius = shape.radius;
  11918. var maxRadius = Math.min(width, height) / 2 | 0;
  11919. radius = radius > maxRadius ? maxRadius : radius;
  11920. context.moveTo(rx, ry + radius);
  11921. context.lineTo(rx, ry + height - radius);
  11922. context.quadraticCurveTo(rx, ry + height, rx + radius, ry + height);
  11923. context.lineTo(rx + width - radius, ry + height);
  11924. context.quadraticCurveTo(rx + width, ry + height, rx + width, ry + height - radius);
  11925. context.lineTo(rx + width, ry + radius);
  11926. context.quadraticCurveTo(rx + width, ry, rx + width - radius, ry);
  11927. context.lineTo(rx + radius, ry);
  11928. context.quadraticCurveTo(rx, ry, rx, ry + radius);
  11929. context.closePath();
  11930. }
  11931. }
  11932. };
  11933. /*
  11934. * Updates the tint of a graphics object
  11935. *
  11936. * @private
  11937. * @param graphics {PIXI.Graphics} the graphics that will have its tint updated
  11938. *
  11939. */
  11940. CanvasGraphics.updateGraphicsTint = function (graphics)
  11941. {
  11942. if (graphics.tint === 0xFFFFFF && graphics._prevTint === graphics.tint)
  11943. {
  11944. return;
  11945. }
  11946. graphics._prevTint = graphics.tint;
  11947. var tintR = (graphics.tint >> 16 & 0xFF) / 255;
  11948. var tintG = (graphics.tint >> 8 & 0xFF) / 255;
  11949. var tintB = (graphics.tint & 0xFF)/ 255;
  11950. for (var i = 0; i < graphics.graphicsData.length; i++)
  11951. {
  11952. var data = graphics.graphicsData[i];
  11953. var fillColor = data.fillColor | 0;
  11954. var lineColor = data.lineColor | 0;
  11955. /*
  11956. var colorR = (fillColor >> 16 & 0xFF) / 255;
  11957. var colorG = (fillColor >> 8 & 0xFF) / 255;
  11958. var colorB = (fillColor & 0xFF) / 255;
  11959. colorR *= tintR;
  11960. colorG *= tintG;
  11961. colorB *= tintB;
  11962. fillColor = ((colorR*255 << 16) + (colorG*255 << 8) + colorB*255);
  11963. colorR = (lineColor >> 16 & 0xFF) / 255;
  11964. colorG = (lineColor >> 8 & 0xFF) / 255;
  11965. colorB = (lineColor & 0xFF) / 255;
  11966. colorR *= tintR;
  11967. colorG *= tintG;
  11968. colorB *= tintB;
  11969. lineColor = ((colorR*255 << 16) + (colorG*255 << 8) + colorB*255);
  11970. */
  11971. // super inline cos im an optimization NAZI :)
  11972. data._fillTint = (((fillColor >> 16 & 0xFF) / 255 * tintR*255 << 16) + ((fillColor >> 8 & 0xFF) / 255 * tintG*255 << 8) + (fillColor & 0xFF) / 255 * tintB*255);
  11973. data._lineTint = (((lineColor >> 16 & 0xFF) / 255 * tintR*255 << 16) + ((lineColor >> 8 & 0xFF) / 255 * tintG*255 << 8) + (lineColor & 0xFF) / 255 * tintB*255);
  11974. }
  11975. };
  11976. },{"../../../const":22}],47:[function(require,module,exports){
  11977. var CanvasGraphics = require('./CanvasGraphics');
  11978. /**
  11979. * A set of functions used to handle masking.
  11980. *
  11981. * @class
  11982. * @memberof PIXI
  11983. */
  11984. function CanvasMaskManager()
  11985. {}
  11986. CanvasMaskManager.prototype.constructor = CanvasMaskManager;
  11987. module.exports = CanvasMaskManager;
  11988. /**
  11989. * This method adds it to the current stack of masks.
  11990. *
  11991. * @param maskData {object} the maskData that will be pushed
  11992. * @param renderer {PIXI.WebGLRenderer|PIXI.CanvasRenderer} The renderer context to use.
  11993. */
  11994. CanvasMaskManager.prototype.pushMask = function (maskData, renderer)
  11995. {
  11996. renderer.context.save();
  11997. var cacheAlpha = maskData.alpha;
  11998. var transform = maskData.worldTransform;
  11999. var resolution = renderer.resolution;
  12000. renderer.context.setTransform(
  12001. transform.a * resolution,
  12002. transform.b * resolution,
  12003. transform.c * resolution,
  12004. transform.d * resolution,
  12005. transform.tx * resolution,
  12006. transform.ty * resolution
  12007. );
  12008. //TODO suport sprite alpha masks??
  12009. //lots of effort required. If demand is great enough..
  12010. if(!maskData.texture)
  12011. {
  12012. CanvasGraphics.renderGraphicsMask(maskData, renderer.context);
  12013. renderer.context.clip();
  12014. }
  12015. maskData.worldAlpha = cacheAlpha;
  12016. };
  12017. /**
  12018. * Restores the current drawing context to the state it was before the mask was applied.
  12019. *
  12020. * @param renderer {PIXI.WebGLRenderer|PIXI.CanvasRenderer} The renderer context to use.
  12021. */
  12022. CanvasMaskManager.prototype.popMask = function (renderer)
  12023. {
  12024. renderer.context.restore();
  12025. };
  12026. CanvasMaskManager.prototype.destroy = function () {};
  12027. },{"./CanvasGraphics":46}],48:[function(require,module,exports){
  12028. var utils = require('../../../utils');
  12029. /**
  12030. * Utility methods for Sprite/Texture tinting.
  12031. * @static
  12032. * @class
  12033. * @memberof PIXI
  12034. */
  12035. var CanvasTinter = {};
  12036. module.exports = CanvasTinter;
  12037. /**
  12038. * Basically this method just needs a sprite and a color and tints the sprite with the given color.
  12039. *
  12040. * @param sprite {PIXI.Sprite} the sprite to tint
  12041. * @param color {number} the color to use to tint the sprite with
  12042. * @return {HTMLCanvasElement} The tinted canvas
  12043. */
  12044. CanvasTinter.getTintedTexture = function (sprite, color)
  12045. {
  12046. var texture = sprite.texture;
  12047. color = CanvasTinter.roundColor(color);
  12048. var stringColor = '#' + ('00000' + ( color | 0).toString(16)).substr(-6);
  12049. texture.tintCache = texture.tintCache || {};
  12050. if (texture.tintCache[stringColor])
  12051. {
  12052. return texture.tintCache[stringColor];
  12053. }
  12054. // clone texture..
  12055. var canvas = CanvasTinter.canvas || document.createElement('canvas');
  12056. //CanvasTinter.tintWithPerPixel(texture, stringColor, canvas);
  12057. CanvasTinter.tintMethod(texture, color, canvas);
  12058. if (CanvasTinter.convertTintToImage)
  12059. {
  12060. // is this better?
  12061. var tintImage = new Image();
  12062. tintImage.src = canvas.toDataURL();
  12063. texture.tintCache[stringColor] = tintImage;
  12064. }
  12065. else
  12066. {
  12067. texture.tintCache[stringColor] = canvas;
  12068. // if we are not converting the texture to an image then we need to lose the reference to the canvas
  12069. CanvasTinter.canvas = null;
  12070. }
  12071. return canvas;
  12072. };
  12073. /**
  12074. * Tint a texture using the 'multiply' operation.
  12075. *
  12076. * @param texture {PIXI.Texture} the texture to tint
  12077. * @param color {number} the color to use to tint the sprite with
  12078. * @param canvas {HTMLCanvasElement} the current canvas
  12079. */
  12080. CanvasTinter.tintWithMultiply = function (texture, color, canvas)
  12081. {
  12082. var context = canvas.getContext( '2d' );
  12083. var resolution = texture.baseTexture.resolution;
  12084. var crop = texture.crop.clone();
  12085. crop.x *= resolution;
  12086. crop.y *= resolution;
  12087. crop.width *= resolution;
  12088. crop.height *= resolution;
  12089. canvas.width = crop.width;
  12090. canvas.height = crop.height;
  12091. context.fillStyle = '#' + ('00000' + ( color | 0).toString(16)).substr(-6);
  12092. context.fillRect(0, 0, crop.width, crop.height);
  12093. context.globalCompositeOperation = 'multiply';
  12094. context.drawImage(
  12095. texture.baseTexture.source,
  12096. crop.x,
  12097. crop.y,
  12098. crop.width,
  12099. crop.height,
  12100. 0,
  12101. 0,
  12102. crop.width,
  12103. crop.height
  12104. );
  12105. context.globalCompositeOperation = 'destination-atop';
  12106. context.drawImage(
  12107. texture.baseTexture.source,
  12108. crop.x,
  12109. crop.y,
  12110. crop.width,
  12111. crop.height,
  12112. 0,
  12113. 0,
  12114. crop.width,
  12115. crop.height
  12116. );
  12117. };
  12118. /**
  12119. * Tint a texture using the 'overlay' operation.
  12120. *
  12121. * @param texture {PIXI.Texture} the texture to tint
  12122. * @param color {number} the color to use to tint the sprite with
  12123. * @param canvas {HTMLCanvasElement} the current canvas
  12124. */
  12125. CanvasTinter.tintWithOverlay = function (texture, color, canvas)
  12126. {
  12127. var context = canvas.getContext( '2d' );
  12128. var resolution = texture.baseTexture.resolution;
  12129. var crop = texture.crop.clone();
  12130. crop.x *= resolution;
  12131. crop.y *= resolution;
  12132. crop.width *= resolution;
  12133. crop.height *= resolution;
  12134. canvas.width = crop.width;
  12135. canvas.height = crop.height;
  12136. context.globalCompositeOperation = 'copy';
  12137. context.fillStyle = '#' + ('00000' + ( color | 0).toString(16)).substr(-6);
  12138. context.fillRect(0, 0, crop.width, crop.height);
  12139. context.globalCompositeOperation = 'destination-atop';
  12140. context.drawImage(
  12141. texture.baseTexture.source,
  12142. crop.x,
  12143. crop.y,
  12144. crop.width,
  12145. crop.height,
  12146. 0,
  12147. 0,
  12148. crop.width,
  12149. crop.height
  12150. );
  12151. // context.globalCompositeOperation = 'copy';
  12152. };
  12153. /**
  12154. * Tint a texture pixel per pixel.
  12155. *
  12156. * @param texture {PIXI.Texture} the texture to tint
  12157. * @param color {number} the color to use to tint the sprite with
  12158. * @param canvas {HTMLCanvasElement} the current canvas
  12159. */
  12160. CanvasTinter.tintWithPerPixel = function (texture, color, canvas)
  12161. {
  12162. var context = canvas.getContext( '2d' );
  12163. var resolution = texture.baseTexture.resolution;
  12164. var crop = texture.crop.clone();
  12165. crop.x *= resolution;
  12166. crop.y *= resolution;
  12167. crop.width *= resolution;
  12168. crop.height *= resolution;
  12169. canvas.width = crop.width;
  12170. canvas.height = crop.height;
  12171. context.globalCompositeOperation = 'copy';
  12172. context.drawImage(
  12173. texture.baseTexture.source,
  12174. crop.x,
  12175. crop.y,
  12176. crop.width,
  12177. crop.height,
  12178. 0,
  12179. 0,
  12180. crop.width,
  12181. crop.height
  12182. );
  12183. var rgbValues = utils.hex2rgb(color);
  12184. var r = rgbValues[0], g = rgbValues[1], b = rgbValues[2];
  12185. var pixelData = context.getImageData(0, 0, crop.width, crop.height);
  12186. var pixels = pixelData.data;
  12187. for (var i = 0; i < pixels.length; i += 4)
  12188. {
  12189. pixels[i+0] *= r;
  12190. pixels[i+1] *= g;
  12191. pixels[i+2] *= b;
  12192. }
  12193. context.putImageData(pixelData, 0, 0);
  12194. };
  12195. /**
  12196. * Rounds the specified color according to the CanvasTinter.cacheStepsPerColorChannel.
  12197. *
  12198. * @param color {number} the color to round, should be a hex color
  12199. */
  12200. CanvasTinter.roundColor = function (color)
  12201. {
  12202. var step = CanvasTinter.cacheStepsPerColorChannel;
  12203. var rgbValues = utils.hex2rgb(color);
  12204. rgbValues[0] = Math.min(255, (rgbValues[0] / step) * step);
  12205. rgbValues[1] = Math.min(255, (rgbValues[1] / step) * step);
  12206. rgbValues[2] = Math.min(255, (rgbValues[2] / step) * step);
  12207. return utils.rgb2hex(rgbValues);
  12208. };
  12209. /**
  12210. * Number of steps which will be used as a cap when rounding colors.
  12211. *
  12212. * @member
  12213. */
  12214. CanvasTinter.cacheStepsPerColorChannel = 8;
  12215. /**
  12216. * Tint cache boolean flag.
  12217. *
  12218. * @member
  12219. */
  12220. CanvasTinter.convertTintToImage = false;
  12221. /**
  12222. * Whether or not the Canvas BlendModes are supported, consequently the ability to tint using the multiply method.
  12223. *
  12224. * @member
  12225. */
  12226. CanvasTinter.canUseMultiply = utils.canUseNewCanvasBlendModes();
  12227. /**
  12228. * The tinting method that will be used.
  12229. *
  12230. */
  12231. CanvasTinter.tintMethod = CanvasTinter.canUseMultiply ? CanvasTinter.tintWithMultiply : CanvasTinter.tintWithPerPixel;
  12232. },{"../../../utils":77}],49:[function(require,module,exports){
  12233. var SystemRenderer = require('../SystemRenderer'),
  12234. ShaderManager = require('./managers/ShaderManager'),
  12235. MaskManager = require('./managers/MaskManager'),
  12236. StencilManager = require('./managers/StencilManager'),
  12237. FilterManager = require('./managers/FilterManager'),
  12238. BlendModeManager = require('./managers/BlendModeManager'),
  12239. RenderTarget = require('./utils/RenderTarget'),
  12240. ObjectRenderer = require('./utils/ObjectRenderer'),
  12241. FXAAFilter = require('./filters/FXAAFilter'),
  12242. utils = require('../../utils'),
  12243. CONST = require('../../const');
  12244. /**
  12245. * The WebGLRenderer draws the scene and all its content onto a webGL enabled canvas. This renderer
  12246. * should be used for browsers that support webGL. This Render works by automatically managing webGLBatchs.
  12247. * So no need for Sprite Batches or Sprite Clouds.
  12248. * Don't forget to add the view to your DOM or you will not see anything :)
  12249. *
  12250. * @class
  12251. * @memberof PIXI
  12252. * @extends PIXI.SystemRenderer
  12253. * @param [width=0] {number} the width of the canvas view
  12254. * @param [height=0] {number} the height of the canvas view
  12255. * @param [options] {object} The optional renderer parameters
  12256. * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional
  12257. * @param [options.transparent=false] {boolean} If the render view is transparent, default false
  12258. * @param [options.autoResize=false] {boolean} If the render view is automatically resized, default false
  12259. * @param [options.antialias=false] {boolean} sets antialias. If not available natively then FXAA antialiasing is used
  12260. * @param [options.forceFXAA=false] {boolean} forces FXAA antialiasing to be used over native. FXAA is faster, but may not always look as great
  12261. * @param [options.resolution=1] {number} the resolution of the renderer retina would be 2
  12262. * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or
  12263. * not before the new render pass. If you wish to set this to false, you *must* set preserveDrawingBuffer to `true`.
  12264. * @param [options.preserveDrawingBuffer=false] {boolean} enables drawing buffer preservation, enable this if
  12265. * you need to call toDataUrl on the webgl context.
  12266. * @param [options.roundPixels=false] {boolean} If true Pixi will Math.floor() x/y values when rendering, stopping pixel interpolation.
  12267. */
  12268. function WebGLRenderer(width, height, options)
  12269. {
  12270. options = options || {};
  12271. SystemRenderer.call(this, 'WebGL', width, height, options);
  12272. /**
  12273. * The type of this renderer as a standardised const
  12274. *
  12275. * @member {number}
  12276. *
  12277. */
  12278. this.type = CONST.RENDERER_TYPE.WEBGL;
  12279. this.handleContextLost = this.handleContextLost.bind(this);
  12280. this.handleContextRestored = this.handleContextRestored.bind(this);
  12281. this.view.addEventListener('webglcontextlost', this.handleContextLost, false);
  12282. this.view.addEventListener('webglcontextrestored', this.handleContextRestored, false);
  12283. //TODO possibility to force FXAA as it may offer better performance?
  12284. /**
  12285. * Does it use FXAA ?
  12286. *
  12287. * @member {boolean}
  12288. * @private
  12289. */
  12290. this._useFXAA = !!options.forceFXAA && options.antialias;
  12291. /**
  12292. * The fxaa filter
  12293. *
  12294. * @member {PIXI.FXAAFilter}
  12295. * @private
  12296. */
  12297. this._FXAAFilter = null;
  12298. /**
  12299. * The options passed in to create a new webgl context.
  12300. *
  12301. * @member {object}
  12302. * @private
  12303. */
  12304. this._contextOptions = {
  12305. alpha: this.transparent,
  12306. antialias: options.antialias,
  12307. premultipliedAlpha: this.transparent && this.transparent !== 'notMultiplied',
  12308. stencil: true,
  12309. preserveDrawingBuffer: options.preserveDrawingBuffer
  12310. };
  12311. /**
  12312. * Counter for the number of draws made each frame
  12313. *
  12314. * @member {number}
  12315. */
  12316. this.drawCount = 0;
  12317. /**
  12318. * Deals with managing the shader programs and their attribs.
  12319. *
  12320. * @member {PIXI.ShaderManager}
  12321. */
  12322. this.shaderManager = new ShaderManager(this);
  12323. /**
  12324. * Manages the masks using the stencil buffer.
  12325. *
  12326. * @member {PIXI.MaskManager}
  12327. */
  12328. this.maskManager = new MaskManager(this);
  12329. /**
  12330. * Manages the stencil buffer.
  12331. *
  12332. * @member {PIXI.StencilManager}
  12333. */
  12334. this.stencilManager = new StencilManager(this);
  12335. /**
  12336. * Manages the filters.
  12337. *
  12338. * @member {PIXI.FilterManager}
  12339. */
  12340. this.filterManager = new FilterManager(this);
  12341. /**
  12342. * Manages the blendModes
  12343. *
  12344. * @member {PIXI.BlendModeManager}
  12345. */
  12346. this.blendModeManager = new BlendModeManager(this);
  12347. /**
  12348. * Holds the current render target
  12349. *
  12350. * @member {PIXI.RenderTarget}
  12351. */
  12352. this.currentRenderTarget = null;
  12353. /**
  12354. * The currently active ObjectRenderer.
  12355. *
  12356. * @member {PIXI.ObjectRenderer}
  12357. */
  12358. this.currentRenderer = new ObjectRenderer(this);
  12359. this.initPlugins();
  12360. // initialize the context so it is ready for the managers.
  12361. this._createContext();
  12362. this._initContext();
  12363. // map some webGL blend modes..
  12364. this._mapGlModes();
  12365. // track textures in the renderer so we can no longer listen to them on destruction.
  12366. this._managedTextures = [];
  12367. /**
  12368. * An array of render targets
  12369. * @member {PIXI.RenderTarget[]}
  12370. * @private
  12371. */
  12372. this._renderTargetStack = [];
  12373. }
  12374. // constructor
  12375. WebGLRenderer.prototype = Object.create(SystemRenderer.prototype);
  12376. WebGLRenderer.prototype.constructor = WebGLRenderer;
  12377. module.exports = WebGLRenderer;
  12378. utils.pluginTarget.mixin(WebGLRenderer);
  12379. WebGLRenderer.glContextId = 0;
  12380. /**
  12381. * Creates the gl context.
  12382. *
  12383. * @private
  12384. */
  12385. WebGLRenderer.prototype._createContext = function () {
  12386. var gl = this.view.getContext('webgl', this._contextOptions) || this.view.getContext('experimental-webgl', this._contextOptions);
  12387. this.gl = gl;
  12388. if (!gl)
  12389. {
  12390. // fail, not able to get a context
  12391. throw new Error('This browser does not support webGL. Try using the canvas renderer');
  12392. }
  12393. this.glContextId = WebGLRenderer.glContextId++;
  12394. gl.id = this.glContextId;
  12395. gl.renderer = this;
  12396. };
  12397. /**
  12398. * Creates the WebGL context
  12399. *
  12400. * @private
  12401. */
  12402. WebGLRenderer.prototype._initContext = function ()
  12403. {
  12404. var gl = this.gl;
  12405. // set up the default pixi settings..
  12406. gl.disable(gl.DEPTH_TEST);
  12407. gl.disable(gl.CULL_FACE);
  12408. gl.enable(gl.BLEND);
  12409. this.renderTarget = new RenderTarget(gl, this.width, this.height, null, this.resolution, true);
  12410. this.setRenderTarget(this.renderTarget);
  12411. this.emit('context', gl);
  12412. // setup the width/height properties and gl viewport
  12413. this.resize(this.width, this.height);
  12414. if(!this._useFXAA)
  12415. {
  12416. this._useFXAA = (this._contextOptions.antialias && ! gl.getContextAttributes().antialias);
  12417. }
  12418. if(this._useFXAA)
  12419. {
  12420. window.console.warn('FXAA antialiasing being used instead of native antialiasing');
  12421. this._FXAAFilter = [new FXAAFilter()];
  12422. }
  12423. };
  12424. /**
  12425. * Renders the object to its webGL view
  12426. *
  12427. * @param object {PIXI.DisplayObject} the object to be rendered
  12428. */
  12429. WebGLRenderer.prototype.render = function (object)
  12430. {
  12431. this.emit('prerender');
  12432. // no point rendering if our context has been blown up!
  12433. if (this.gl.isContextLost())
  12434. {
  12435. return;
  12436. }
  12437. this.drawCount = 0;
  12438. this._lastObjectRendered = object;
  12439. if(this._useFXAA)
  12440. {
  12441. this._FXAAFilter[0].uniforms.resolution.value.x = this.width;
  12442. this._FXAAFilter[0].uniforms.resolution.value.y = this.height;
  12443. object.filterArea = this.renderTarget.size;
  12444. object.filters = this._FXAAFilter;
  12445. }
  12446. var cacheParent = object.parent;
  12447. object.parent = this._tempDisplayObjectParent;
  12448. // update the scene graph
  12449. object.updateTransform();
  12450. object.parent = cacheParent;
  12451. var gl = this.gl;
  12452. // make sure we are bound to the main frame buffer
  12453. this.setRenderTarget(this.renderTarget);
  12454. if (this.clearBeforeRender)
  12455. {
  12456. if (this.transparent)
  12457. {
  12458. gl.clearColor(0, 0, 0, 0);
  12459. }
  12460. else
  12461. {
  12462. gl.clearColor(this._backgroundColorRgb[0], this._backgroundColorRgb[1], this._backgroundColorRgb[2], 1);
  12463. }
  12464. gl.clear(gl.COLOR_BUFFER_BIT);
  12465. }
  12466. this.renderDisplayObject(object, this.renderTarget);//this.projection);
  12467. this.emit('postrender');
  12468. };
  12469. /**
  12470. * Renders a Display Object.
  12471. *
  12472. * @param displayObject {PIXI.DisplayObject} The DisplayObject to render
  12473. * @param renderTarget {PIXI.RenderTarget} The render target to use to render this display object
  12474. *
  12475. */
  12476. WebGLRenderer.prototype.renderDisplayObject = function (displayObject, renderTarget, clear)//projection, buffer)
  12477. {
  12478. // TODO is this needed...
  12479. //this.blendModeManager.setBlendMode(CONST.BLEND_MODES.NORMAL);
  12480. this.setRenderTarget(renderTarget);
  12481. if(clear)
  12482. {
  12483. renderTarget.clear();
  12484. }
  12485. // start the filter manager
  12486. this.filterManager.setFilterStack( renderTarget.filterStack );
  12487. // render the scene!
  12488. displayObject.renderWebGL(this);
  12489. // finish the current renderer..
  12490. this.currentRenderer.flush();
  12491. };
  12492. /**
  12493. * Changes the current renderer to the one given in parameter
  12494. *
  12495. * @param objectRenderer {PIXI.ObjectRenderer} The object renderer to use.
  12496. */
  12497. WebGLRenderer.prototype.setObjectRenderer = function (objectRenderer)
  12498. {
  12499. if (this.currentRenderer === objectRenderer)
  12500. {
  12501. return;
  12502. }
  12503. this.currentRenderer.stop();
  12504. this.currentRenderer = objectRenderer;
  12505. this.currentRenderer.start();
  12506. };
  12507. /**
  12508. * Changes the current render target to the one given in parameter
  12509. *
  12510. * @param renderTarget {PIXI.RenderTarget} the new render target
  12511. */
  12512. WebGLRenderer.prototype.setRenderTarget = function (renderTarget)
  12513. {
  12514. if( this.currentRenderTarget === renderTarget)
  12515. {
  12516. return;
  12517. }
  12518. // TODO - maybe down the line this should be a push pos thing? Leaving for now though.
  12519. this.currentRenderTarget = renderTarget;
  12520. this.currentRenderTarget.activate();
  12521. this.stencilManager.setMaskStack( renderTarget.stencilMaskStack );
  12522. };
  12523. /**
  12524. * Resizes the webGL view to the specified width and height.
  12525. *
  12526. * @param width {number} the new width of the webGL view
  12527. * @param height {number} the new height of the webGL view
  12528. */
  12529. WebGLRenderer.prototype.resize = function (width, height)
  12530. {
  12531. SystemRenderer.prototype.resize.call(this, width, height);
  12532. this.filterManager.resize(width, height);
  12533. this.renderTarget.resize(width, height);
  12534. if(this.currentRenderTarget === this.renderTarget)
  12535. {
  12536. this.renderTarget.activate();
  12537. this.gl.viewport(0, 0, this.width, this.height);
  12538. }
  12539. };
  12540. /**
  12541. * Updates and/or Creates a WebGL texture for the renderer's context.
  12542. *
  12543. * @param texture {PIXI.BaseTexture|PIXI.Texture} the texture to update
  12544. */
  12545. WebGLRenderer.prototype.updateTexture = function (texture)
  12546. {
  12547. texture = texture.baseTexture || texture;
  12548. if (!texture.hasLoaded)
  12549. {
  12550. return;
  12551. }
  12552. var gl = this.gl;
  12553. if (!texture._glTextures[gl.id])
  12554. {
  12555. texture._glTextures[gl.id] = gl.createTexture();
  12556. texture.on('update', this.updateTexture, this);
  12557. texture.on('dispose', this.destroyTexture, this);
  12558. this._managedTextures.push(texture);
  12559. }
  12560. gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]);
  12561. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha);
  12562. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source);
  12563. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === CONST.SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST);
  12564. if (texture.mipmap && texture.isPowerOfTwo)
  12565. {
  12566. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === CONST.SCALE_MODES.LINEAR ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST);
  12567. gl.generateMipmap(gl.TEXTURE_2D);
  12568. }
  12569. else
  12570. {
  12571. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === CONST.SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST);
  12572. }
  12573. if (!texture.isPowerOfTwo)
  12574. {
  12575. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  12576. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  12577. }
  12578. else
  12579. {
  12580. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
  12581. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
  12582. }
  12583. return texture._glTextures[gl.id];
  12584. };
  12585. /**
  12586. * Deletes the texture from WebGL
  12587. *
  12588. * @param texture {PIXI.BaseTexture|PIXI.Texture} the texture to destroy
  12589. */
  12590. WebGLRenderer.prototype.destroyTexture = function (texture, _skipRemove)
  12591. {
  12592. texture = texture.baseTexture || texture;
  12593. if (!texture.hasLoaded)
  12594. {
  12595. return;
  12596. }
  12597. if (texture._glTextures[this.gl.id])
  12598. {
  12599. this.gl.deleteTexture(texture._glTextures[this.gl.id]);
  12600. delete texture._glTextures[this.gl.id];
  12601. if (!_skipRemove)
  12602. {
  12603. var i = this._managedTextures.indexOf(texture);
  12604. if (i !== -1) {
  12605. utils.removeItems(this._managedTextures, i, 1);
  12606. }
  12607. }
  12608. }
  12609. };
  12610. /**
  12611. * Handles a lost webgl context
  12612. *
  12613. * @private
  12614. */
  12615. WebGLRenderer.prototype.handleContextLost = function (event)
  12616. {
  12617. event.preventDefault();
  12618. };
  12619. /**
  12620. * Handles a restored webgl context
  12621. *
  12622. * @private
  12623. */
  12624. WebGLRenderer.prototype.handleContextRestored = function ()
  12625. {
  12626. this._initContext();
  12627. // empty all the old gl textures as they are useless now
  12628. for (var i = 0; i < this._managedTextures.length; ++i)
  12629. {
  12630. var texture = this._managedTextures[i];
  12631. if (texture._glTextures[this.gl.id])
  12632. {
  12633. delete texture._glTextures[this.gl.id];
  12634. }
  12635. }
  12636. };
  12637. /**
  12638. * Removes everything from the renderer (event listeners, spritebatch, etc...)
  12639. *
  12640. * @param [removeView=false] {boolean} Removes the Canvas element from the DOM.
  12641. */
  12642. WebGLRenderer.prototype.destroy = function (removeView)
  12643. {
  12644. this.destroyPlugins();
  12645. // remove listeners
  12646. this.view.removeEventListener('webglcontextlost', this.handleContextLost);
  12647. this.view.removeEventListener('webglcontextrestored', this.handleContextRestored);
  12648. // destroy managed textures
  12649. for (var i = 0; i < this._managedTextures.length; ++i)
  12650. {
  12651. var texture = this._managedTextures[i];
  12652. this.destroyTexture(texture, true);
  12653. texture.off('update', this.updateTexture, this);
  12654. texture.off('dispose', this.destroyTexture, this);
  12655. }
  12656. // call base destroy
  12657. SystemRenderer.prototype.destroy.call(this, removeView);
  12658. this.uid = 0;
  12659. // destroy the managers
  12660. this.shaderManager.destroy();
  12661. this.maskManager.destroy();
  12662. this.stencilManager.destroy();
  12663. this.filterManager.destroy();
  12664. this.blendModeManager.destroy();
  12665. this.shaderManager = null;
  12666. this.maskManager = null;
  12667. this.filterManager = null;
  12668. this.blendModeManager = null;
  12669. this.currentRenderer = null;
  12670. this.handleContextLost = null;
  12671. this.handleContextRestored = null;
  12672. this._contextOptions = null;
  12673. this._managedTextures = null;
  12674. this.drawCount = 0;
  12675. this.gl.useProgram(null);
  12676. this.gl.flush();
  12677. this.gl = null;
  12678. };
  12679. /**
  12680. * Maps Pixi blend modes to WebGL blend modes. It works only for pre-multiplied textures.
  12681. *
  12682. * @private
  12683. */
  12684. WebGLRenderer.prototype._mapGlModes = function ()
  12685. {
  12686. var gl = this.gl;
  12687. if (!this.blendModes)
  12688. {
  12689. this.blendModes = {};
  12690. this.blendModes[CONST.BLEND_MODES.NORMAL] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  12691. this.blendModes[CONST.BLEND_MODES.ADD] = [gl.ONE, gl.DST_ALPHA];
  12692. this.blendModes[CONST.BLEND_MODES.MULTIPLY] = [gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA];
  12693. this.blendModes[CONST.BLEND_MODES.SCREEN] = [gl.ONE, gl.ONE_MINUS_SRC_COLOR];
  12694. this.blendModes[CONST.BLEND_MODES.OVERLAY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  12695. this.blendModes[CONST.BLEND_MODES.DARKEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  12696. this.blendModes[CONST.BLEND_MODES.LIGHTEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  12697. this.blendModes[CONST.BLEND_MODES.COLOR_DODGE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  12698. this.blendModes[CONST.BLEND_MODES.COLOR_BURN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  12699. this.blendModes[CONST.BLEND_MODES.HARD_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  12700. this.blendModes[CONST.BLEND_MODES.SOFT_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  12701. this.blendModes[CONST.BLEND_MODES.DIFFERENCE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  12702. this.blendModes[CONST.BLEND_MODES.EXCLUSION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  12703. this.blendModes[CONST.BLEND_MODES.HUE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  12704. this.blendModes[CONST.BLEND_MODES.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  12705. this.blendModes[CONST.BLEND_MODES.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  12706. this.blendModes[CONST.BLEND_MODES.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  12707. }
  12708. if (!this.drawModes)
  12709. {
  12710. this.drawModes = {};
  12711. this.drawModes[CONST.DRAW_MODES.POINTS] = gl.POINTS;
  12712. this.drawModes[CONST.DRAW_MODES.LINES] = gl.LINES;
  12713. this.drawModes[CONST.DRAW_MODES.LINE_LOOP] = gl.LINE_LOOP;
  12714. this.drawModes[CONST.DRAW_MODES.LINE_STRIP] = gl.LINE_STRIP;
  12715. this.drawModes[CONST.DRAW_MODES.TRIANGLES] = gl.TRIANGLES;
  12716. this.drawModes[CONST.DRAW_MODES.TRIANGLE_STRIP] = gl.TRIANGLE_STRIP;
  12717. this.drawModes[CONST.DRAW_MODES.TRIANGLE_FAN] = gl.TRIANGLE_FAN;
  12718. }
  12719. };
  12720. },{"../../const":22,"../../utils":77,"../SystemRenderer":43,"./filters/FXAAFilter":51,"./managers/BlendModeManager":53,"./managers/FilterManager":54,"./managers/MaskManager":55,"./managers/ShaderManager":56,"./managers/StencilManager":57,"./utils/ObjectRenderer":63,"./utils/RenderTarget":65}],50:[function(require,module,exports){
  12721. var DefaultShader = require('../shaders/TextureShader');
  12722. /**
  12723. * This is the base class for creating a PIXI filter. Currently only WebGL supports filters.
  12724. * If you want to make a custom filter this should be your base class.
  12725. *
  12726. * @class
  12727. * @memberof PIXI
  12728. * @param vertexSrc {string|string[]} The vertex shader source as an array of strings.
  12729. * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings.
  12730. * @param uniforms {object} An object containing the uniforms for this filter.
  12731. */
  12732. function AbstractFilter(vertexSrc, fragmentSrc, uniforms)
  12733. {
  12734. /**
  12735. * An array of shaders
  12736. * @member {PIXI.Shader[]}
  12737. * @private
  12738. */
  12739. this.shaders = [];
  12740. /**
  12741. * The extra padding that the filter might need
  12742. * @member {number}
  12743. */
  12744. this.padding = 0;
  12745. /**
  12746. * The uniforms as an object
  12747. * @member {object}
  12748. */
  12749. this.uniforms = uniforms || {};
  12750. /**
  12751. * The code of the vertex shader
  12752. * @member {string[]}
  12753. * @private
  12754. */
  12755. this.vertexSrc = vertexSrc || DefaultShader.defaultVertexSrc;
  12756. /**
  12757. * The code of the frament shader
  12758. * @member {string[]}
  12759. * @private
  12760. */
  12761. this.fragmentSrc = fragmentSrc || DefaultShader.defaultFragmentSrc;
  12762. //TODO a reminder - would be cool to have lower res filters as this would give better performance.
  12763. //typeof fragmentSrc === 'string' ? fragmentSrc.split('') : (fragmentSrc || []);
  12764. }
  12765. AbstractFilter.prototype.constructor = AbstractFilter;
  12766. module.exports = AbstractFilter;
  12767. /**
  12768. * Grabs a shader from the current renderer
  12769. *
  12770. * @param renderer {PIXI.WebGLRenderer} The renderer to retrieve the shader from
  12771. */
  12772. AbstractFilter.prototype.getShader = function (renderer)
  12773. {
  12774. var gl = renderer.gl;
  12775. var shader = this.shaders[gl.id];
  12776. if (!shader)
  12777. {
  12778. shader = new DefaultShader(renderer.shaderManager,
  12779. this.vertexSrc,
  12780. this.fragmentSrc,
  12781. this.uniforms,
  12782. this.attributes
  12783. );
  12784. this.shaders[gl.id] = shader;
  12785. }
  12786. return shader;
  12787. };
  12788. /**
  12789. * Applies the filter
  12790. *
  12791. * @param renderer {PIXI.WebGLRenderer} The renderer to retrieve the filter from
  12792. * @param input {PIXI.RenderTarget}
  12793. * @param output {PIXI.RenderTarget}
  12794. * @param clear {boolean} Whether or not we want to clear the outputTarget
  12795. */
  12796. AbstractFilter.prototype.applyFilter = function (renderer, input, output, clear)
  12797. {
  12798. var shader = this.getShader(renderer);
  12799. renderer.filterManager.applyFilter(shader, input, output, clear);
  12800. };
  12801. /**
  12802. * Syncs a uniform between the class object and the shaders.
  12803. *
  12804. */
  12805. AbstractFilter.prototype.syncUniform = function (uniform)
  12806. {
  12807. for (var i = 0, j = this.shaders.length; i < j; ++i)
  12808. {
  12809. this.shaders[i].syncUniform(uniform);
  12810. }
  12811. };
  12812. },{"../shaders/TextureShader":62}],51:[function(require,module,exports){
  12813. var AbstractFilter = require('./AbstractFilter');
  12814. // @see https://github.com/substack/brfs/issues/25
  12815. /**
  12816. *
  12817. * Basic FXAA implementation based on the code on geeks3d.com with the
  12818. * modification that the texture2DLod stuff was removed since it's
  12819. * unsupported by WebGL.
  12820. *
  12821. * --
  12822. * From:
  12823. * https://github.com/mitsuhiko/webgl-meincraft
  12824. *
  12825. * @class
  12826. * @extends PIXI.AbstractFilter
  12827. * @memberof PIXI
  12828. *
  12829. */
  12830. function FXAAFilter()
  12831. {
  12832. AbstractFilter.call(this,
  12833. // vertex shader
  12834. "\nprecision mediump float;\n\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\n\nuniform mat3 projectionMatrix;\nuniform vec2 resolution;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nvarying vec2 vResolution;\n\n//texcoords computed in vertex step\n//to avoid dependent texture reads\nvarying vec2 v_rgbNW;\nvarying vec2 v_rgbNE;\nvarying vec2 v_rgbSW;\nvarying vec2 v_rgbSE;\nvarying vec2 v_rgbM;\n\n\nvoid texcoords(vec2 fragCoord, vec2 resolution,\n out vec2 v_rgbNW, out vec2 v_rgbNE,\n out vec2 v_rgbSW, out vec2 v_rgbSE,\n out vec2 v_rgbM) {\n vec2 inverseVP = 1.0 / resolution.xy;\n v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP;\n v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP;\n v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP;\n v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP;\n v_rgbM = vec2(fragCoord * inverseVP);\n}\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n vResolution = resolution;\n\n //compute the texture coords and send them to varyings\n texcoords(aTextureCoord * resolution, resolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);\n}\n",
  12835. // fragment shader
  12836. "precision lowp float;\n\n\n/**\nBasic FXAA implementation based on the code on geeks3d.com with the\nmodification that the texture2DLod stuff was removed since it's\nunsupported by WebGL.\n\n--\n\nFrom:\nhttps://github.com/mitsuhiko/webgl-meincraft\n\nCopyright (c) 2011 by Armin Ronacher.\n\nSome rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n * Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer.\n\n * Redistributions in binary form must reproduce the above\n copyright notice, this list of conditions and the following\n disclaimer in the documentation and/or other materials provided\n with the distribution.\n\n * The names of the contributors may not be used to endorse or\n promote products derived from this software without specific\n prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef FXAA_REDUCE_MIN\n #define FXAA_REDUCE_MIN (1.0/ 128.0)\n#endif\n#ifndef FXAA_REDUCE_MUL\n #define FXAA_REDUCE_MUL (1.0 / 8.0)\n#endif\n#ifndef FXAA_SPAN_MAX\n #define FXAA_SPAN_MAX 8.0\n#endif\n\n//optimized version for mobile, where dependent\n//texture reads can be a bottleneck\nvec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution,\n vec2 v_rgbNW, vec2 v_rgbNE,\n vec2 v_rgbSW, vec2 v_rgbSE,\n vec2 v_rgbM) {\n vec4 color;\n mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y);\n vec3 rgbNW = texture2D(tex, v_rgbNW).xyz;\n vec3 rgbNE = texture2D(tex, v_rgbNE).xyz;\n vec3 rgbSW = texture2D(tex, v_rgbSW).xyz;\n vec3 rgbSE = texture2D(tex, v_rgbSE).xyz;\n vec4 texColor = texture2D(tex, v_rgbM);\n vec3 rgbM = texColor.xyz;\n vec3 luma = vec3(0.299, 0.587, 0.114);\n float lumaNW = dot(rgbNW, luma);\n float lumaNE = dot(rgbNE, luma);\n float lumaSW = dot(rgbSW, luma);\n float lumaSE = dot(rgbSE, luma);\n float lumaM = dot(rgbM, luma);\n float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n\n mediump vec2 dir;\n dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n\n float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *\n (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\n\n float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\n dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),\n max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\n dir * rcpDirMin)) * inverseVP;\n\n vec3 rgbA = 0.5 * (\n texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +\n texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);\n vec3 rgbB = rgbA * 0.5 + 0.25 * (\n texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz +\n texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz);\n\n float lumaB = dot(rgbB, luma);\n if ((lumaB < lumaMin) || (lumaB > lumaMax))\n color = vec4(rgbA, texColor.a);\n else\n color = vec4(rgbB, texColor.a);\n return color;\n}\n\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\nvarying vec2 vResolution;\n\n//texcoords computed in vertex step\n//to avoid dependent texture reads\nvarying vec2 v_rgbNW;\nvarying vec2 v_rgbNE;\nvarying vec2 v_rgbSW;\nvarying vec2 v_rgbSE;\nvarying vec2 v_rgbM;\n\nuniform sampler2D uSampler;\n\n\nvoid main(void){\n\n gl_FragColor = fxaa(uSampler, vTextureCoord * vResolution, vResolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);\n\n}\n",
  12837. // uniforms
  12838. {
  12839. resolution: { type: 'v2', value: { x: 1, y: 1 } }
  12840. }
  12841. );
  12842. }
  12843. FXAAFilter.prototype = Object.create(AbstractFilter.prototype);
  12844. FXAAFilter.prototype.constructor = FXAAFilter;
  12845. module.exports = FXAAFilter;
  12846. /**
  12847. * Applies the filter
  12848. *
  12849. * @param renderer {PIXI.WebGLRenderer} The renderer to retrieve the filter from
  12850. * @param input {PIXI.RenderTarget}
  12851. * @param output {PIXI.RenderTarget}
  12852. */
  12853. FXAAFilter.prototype.applyFilter = function (renderer, input, output)
  12854. {
  12855. var filterManager = renderer.filterManager;
  12856. var shader = this.getShader( renderer );
  12857. // draw the filter...
  12858. filterManager.applyFilter(shader, input, output);
  12859. };
  12860. },{"./AbstractFilter":50}],52:[function(require,module,exports){
  12861. var AbstractFilter = require('./AbstractFilter'),
  12862. math = require('../../../math');
  12863. // @see https://github.com/substack/brfs/issues/25
  12864. /**
  12865. * The SpriteMaskFilter class
  12866. *
  12867. * @class
  12868. * @extends PIXI.AbstractFilter
  12869. * @memberof PIXI
  12870. * @param sprite {PIXI.Sprite} the target sprite
  12871. */
  12872. function SpriteMaskFilter(sprite)
  12873. {
  12874. var maskMatrix = new math.Matrix();
  12875. AbstractFilter.call(this,
  12876. "attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\n\nuniform mat3 projectionMatrix;\nuniform mat3 otherMatrix;\n\nvarying vec2 vMaskCoord;\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}\n",
  12877. "precision lowp float;\n\nvarying vec2 vMaskCoord;\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform sampler2D uSampler;\nuniform float alpha;\nuniform sampler2D mask;\n\nvoid main(void)\n{\n // check clip! this will stop the mask bleeding out from the edges\n vec2 text = abs( vMaskCoord - 0.5 );\n text = step(0.5, text);\n float clip = 1.0 - max(text.y, text.x);\n vec4 original = texture2D(uSampler, vTextureCoord);\n vec4 masky = texture2D(mask, vMaskCoord);\n original *= (masky.r * masky.a * alpha * clip);\n gl_FragColor = original;\n}\n",
  12878. {
  12879. mask: { type: 'sampler2D', value: sprite._texture },
  12880. alpha: { type: 'f', value: 1},
  12881. otherMatrix: { type: 'mat3', value: maskMatrix.toArray(true) }
  12882. }
  12883. );
  12884. this.maskSprite = sprite;
  12885. this.maskMatrix = maskMatrix;
  12886. }
  12887. SpriteMaskFilter.prototype = Object.create(AbstractFilter.prototype);
  12888. SpriteMaskFilter.prototype.constructor = SpriteMaskFilter;
  12889. module.exports = SpriteMaskFilter;
  12890. /**
  12891. * Applies the filter
  12892. *
  12893. * @param renderer {PIXI.WebGLRenderer} The renderer to retrieve the filter from
  12894. * @param input {PIXI.RenderTarget}
  12895. * @param output {PIXI.RenderTarget}
  12896. */
  12897. SpriteMaskFilter.prototype.applyFilter = function (renderer, input, output)
  12898. {
  12899. var filterManager = renderer.filterManager;
  12900. this.uniforms.mask.value = this.maskSprite._texture;
  12901. filterManager.calculateMappedMatrix(input.frame, this.maskSprite, this.maskMatrix);
  12902. this.uniforms.otherMatrix.value = this.maskMatrix.toArray(true);
  12903. this.uniforms.alpha.value = this.maskSprite.worldAlpha;
  12904. var shader = this.getShader(renderer);
  12905. // draw the filter...
  12906. filterManager.applyFilter(shader, input, output);
  12907. };
  12908. Object.defineProperties(SpriteMaskFilter.prototype, {
  12909. /**
  12910. * The texture used for the displacement map. Must be power of 2 sized texture.
  12911. *
  12912. * @member {PIXI.Texture}
  12913. * @memberof PIXI.SpriteMaskFilter#
  12914. */
  12915. map: {
  12916. get: function ()
  12917. {
  12918. return this.uniforms.mask.value;
  12919. },
  12920. set: function (value)
  12921. {
  12922. this.uniforms.mask.value = value;
  12923. }
  12924. },
  12925. /**
  12926. * The offset used to move the displacement map.
  12927. *
  12928. * @member {PIXI.Point}
  12929. * @memberof PIXI.SpriteMaskFilter#
  12930. */
  12931. offset: {
  12932. get: function()
  12933. {
  12934. return this.uniforms.offset.value;
  12935. },
  12936. set: function(value)
  12937. {
  12938. this.uniforms.offset.value = value;
  12939. }
  12940. }
  12941. });
  12942. },{"../../../math":33,"./AbstractFilter":50}],53:[function(require,module,exports){
  12943. var WebGLManager = require('./WebGLManager');
  12944. /**
  12945. * @class
  12946. * @memberof PIXI
  12947. * @extends PIXI.WebGlManager
  12948. * @param renderer {PIXI.WebGLRenderer} The renderer this manager works for.
  12949. */
  12950. function BlendModeManager(renderer)
  12951. {
  12952. WebGLManager.call(this, renderer);
  12953. /**
  12954. * @member {number}
  12955. */
  12956. this.currentBlendMode = 99999;
  12957. }
  12958. BlendModeManager.prototype = Object.create(WebGLManager.prototype);
  12959. BlendModeManager.prototype.constructor = BlendModeManager;
  12960. module.exports = BlendModeManager;
  12961. /**
  12962. * Sets-up the given blendMode from WebGL's point of view.
  12963. *
  12964. * @param blendMode {number} the blendMode, should be a Pixi const, such as `PIXI.BLEND_MODES.ADD`. See
  12965. * {@link PIXI.BLEND_MODES} for possible values.
  12966. */
  12967. BlendModeManager.prototype.setBlendMode = function (blendMode)
  12968. {
  12969. if (this.currentBlendMode === blendMode)
  12970. {
  12971. return false;
  12972. }
  12973. this.currentBlendMode = blendMode;
  12974. var mode = this.renderer.blendModes[this.currentBlendMode];
  12975. this.renderer.gl.blendFunc(mode[0], mode[1]);
  12976. return true;
  12977. };
  12978. },{"./WebGLManager":58}],54:[function(require,module,exports){
  12979. var WebGLManager = require('./WebGLManager'),
  12980. RenderTarget = require('../utils/RenderTarget'),
  12981. CONST = require('../../../const'),
  12982. Quad = require('../utils/Quad'),
  12983. math = require('../../../math');
  12984. /**
  12985. * @class
  12986. * @memberof PIXI
  12987. * @extends PIXI.WebGLManager
  12988. * @param renderer {PIXI.WebGLRenderer} The renderer this manager works for.
  12989. */
  12990. function FilterManager(renderer)
  12991. {
  12992. WebGLManager.call(this, renderer);
  12993. /**
  12994. * @member {object[]}
  12995. */
  12996. this.filterStack = [];
  12997. this.filterStack.push({
  12998. renderTarget:renderer.currentRenderTarget,
  12999. filter:[],
  13000. bounds:null
  13001. });
  13002. /**
  13003. * @member {PIXI.RenderTarget[]}
  13004. */
  13005. this.texturePool = [];
  13006. /**
  13007. * The size of the texture
  13008. *
  13009. * @member {PIXI.Rectangle}
  13010. */
  13011. // listen for context and update necessary buffers
  13012. //TODO make this dynamic!
  13013. //TODO test this out by forces power of two?
  13014. this.textureSize = new math.Rectangle(0, 0, renderer.width, renderer.height);
  13015. /**
  13016. * The current frame
  13017. *
  13018. * @member {PIXI.Rectangle}
  13019. */
  13020. this.currentFrame = null;
  13021. }
  13022. FilterManager.prototype = Object.create(WebGLManager.prototype);
  13023. FilterManager.prototype.constructor = FilterManager;
  13024. module.exports = FilterManager;
  13025. /**
  13026. * Called when there is a WebGL context change.
  13027. *
  13028. */
  13029. FilterManager.prototype.onContextChange = function ()
  13030. {
  13031. this.texturePool.length = 0;
  13032. var gl = this.renderer.gl;
  13033. this.quad = new Quad(gl);
  13034. };
  13035. /**
  13036. * @param renderer {PIXI.WebGLRenderer}
  13037. * @param buffer {ArrayBuffer}
  13038. */
  13039. FilterManager.prototype.setFilterStack = function ( filterStack )
  13040. {
  13041. this.filterStack = filterStack;
  13042. };
  13043. /**
  13044. * Applies the filter and adds it to the current filter stack.
  13045. *
  13046. * @param target {PIXI.DisplayObject}
  13047. * @param filters {PIXI.AbstractFiler[]} the filters that will be pushed to the current filter stack
  13048. */
  13049. FilterManager.prototype.pushFilter = function (target, filters)
  13050. {
  13051. // get the bounds of the object..
  13052. // TODO replace clone with a copy to save object creation
  13053. var bounds = target.filterArea ? target.filterArea.clone() : target.getBounds();
  13054. //bounds = bounds.clone();
  13055. // round off the rectangle to get a nice smoooooooth filter :)
  13056. bounds.x = bounds.x | 0;
  13057. bounds.y = bounds.y | 0;
  13058. bounds.width = bounds.width | 0;
  13059. bounds.height = bounds.height | 0;
  13060. // padding!
  13061. var padding = filters[0].padding | 0;
  13062. bounds.x -= padding;
  13063. bounds.y -= padding;
  13064. bounds.width += padding * 2;
  13065. bounds.height += padding * 2;
  13066. if(this.renderer.currentRenderTarget.transform)
  13067. {
  13068. //TODO this will break if the renderTexture transform is anything other than a translation.
  13069. //Will need to take the full matrix transform into acount..
  13070. var transform = this.renderer.currentRenderTarget.transform;
  13071. bounds.x += transform.tx;
  13072. bounds.y += transform.ty;
  13073. this.capFilterArea( bounds );
  13074. bounds.x -= transform.tx;
  13075. bounds.y -= transform.ty;
  13076. }
  13077. else
  13078. {
  13079. this.capFilterArea( bounds );
  13080. }
  13081. if(bounds.width > 0 && bounds.height > 0)
  13082. {
  13083. this.currentFrame = bounds;
  13084. var texture = this.getRenderTarget();
  13085. this.renderer.setRenderTarget(texture);
  13086. // clear the texture..
  13087. texture.clear();
  13088. // TODO get rid of object creation!
  13089. this.filterStack.push({
  13090. renderTarget: texture,
  13091. filter: filters
  13092. });
  13093. }
  13094. else
  13095. {
  13096. // push somthing on to the stack that is empty
  13097. this.filterStack.push({
  13098. renderTarget: null,
  13099. filter: filters
  13100. });
  13101. }
  13102. };
  13103. /**
  13104. * Removes the last filter from the filter stack and returns it.
  13105. *
  13106. */
  13107. FilterManager.prototype.popFilter = function ()
  13108. {
  13109. var filterData = this.filterStack.pop();
  13110. var previousFilterData = this.filterStack[this.filterStack.length-1];
  13111. var input = filterData.renderTarget;
  13112. // if the renderTarget is null then we don't apply the filter as its offscreen
  13113. if(!filterData.renderTarget)
  13114. {
  13115. return;
  13116. }
  13117. var output = previousFilterData.renderTarget;
  13118. // use program
  13119. var gl = this.renderer.gl;
  13120. this.currentFrame = input.frame;
  13121. this.quad.map(this.textureSize, input.frame);
  13122. // TODO.. this probably only needs to be done once!
  13123. gl.bindBuffer(gl.ARRAY_BUFFER, this.quad.vertexBuffer);
  13124. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.quad.indexBuffer);
  13125. var filters = filterData.filter;
  13126. // assuming all filters follow the correct format??
  13127. gl.vertexAttribPointer(this.renderer.shaderManager.defaultShader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
  13128. gl.vertexAttribPointer(this.renderer.shaderManager.defaultShader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 2 * 4 * 4);
  13129. gl.vertexAttribPointer(this.renderer.shaderManager.defaultShader.attributes.aColor, 4, gl.FLOAT, false, 0, 4 * 4 * 4);
  13130. // restore the normal blendmode!
  13131. this.renderer.blendModeManager.setBlendMode(CONST.BLEND_MODES.NORMAL);
  13132. if (filters.length === 1)
  13133. {
  13134. // TODO (cengler) - There has to be a better way then setting this each time?
  13135. if (filters[0].uniforms.dimensions)
  13136. {
  13137. filters[0].uniforms.dimensions.value[0] = this.renderer.width;
  13138. filters[0].uniforms.dimensions.value[1] = this.renderer.height;
  13139. filters[0].uniforms.dimensions.value[2] = this.quad.vertices[0];
  13140. filters[0].uniforms.dimensions.value[3] = this.quad.vertices[5];
  13141. }
  13142. filters[0].applyFilter( this.renderer, input, output );
  13143. this.returnRenderTarget( input );
  13144. }
  13145. else
  13146. {
  13147. var flipTexture = input;
  13148. var flopTexture = this.getRenderTarget(true);
  13149. for (var i = 0; i < filters.length-1; i++)
  13150. {
  13151. var filter = filters[i];
  13152. // TODO (cengler) - There has to be a better way then setting this each time?
  13153. if (filter.uniforms.dimensions)
  13154. {
  13155. filter.uniforms.dimensions.value[0] = this.renderer.width;
  13156. filter.uniforms.dimensions.value[1] = this.renderer.height;
  13157. filter.uniforms.dimensions.value[2] = this.quad.vertices[0];
  13158. filter.uniforms.dimensions.value[3] = this.quad.vertices[5];
  13159. }
  13160. filter.applyFilter( this.renderer, flipTexture, flopTexture );
  13161. var temp = flipTexture;
  13162. flipTexture = flopTexture;
  13163. flopTexture = temp;
  13164. }
  13165. filters[filters.length-1].applyFilter( this.renderer, flipTexture, output );
  13166. this.returnRenderTarget( flipTexture );
  13167. this.returnRenderTarget( flopTexture );
  13168. }
  13169. return filterData.filter;
  13170. };
  13171. /**
  13172. * Grabs an render target from the internal pool
  13173. *
  13174. * @param clear {boolean} Whether or not we need to clear the RenderTarget
  13175. * @return {RenderTarget}
  13176. */
  13177. FilterManager.prototype.getRenderTarget = function ( clear )
  13178. {
  13179. var renderTarget = this.texturePool.pop() || new RenderTarget(this.renderer.gl, this.textureSize.width, this.textureSize.height, CONST.SCALE_MODES.LINEAR, this.renderer.resolution * CONST.FILTER_RESOLUTION);
  13180. renderTarget.frame = this.currentFrame;
  13181. if (clear)
  13182. {
  13183. renderTarget.clear(true);
  13184. }
  13185. return renderTarget;
  13186. };
  13187. /*
  13188. * Returns a RenderTarget to the internal pool
  13189. * @param renderTarget {RenderTarget} The RenderTarget we want to return to the pool
  13190. */
  13191. FilterManager.prototype.returnRenderTarget = function (renderTarget)
  13192. {
  13193. this.texturePool.push( renderTarget );
  13194. };
  13195. /*
  13196. * Applies the filter
  13197. * @param shader {Shader} The shader to upload
  13198. * @param inputTarget {RenderTarget}
  13199. * @param outputTarget {RenderTarget}
  13200. * @param clear {boolean} Whether or not we want to clear the outputTarget
  13201. */
  13202. FilterManager.prototype.applyFilter = function (shader, inputTarget, outputTarget, clear)
  13203. {
  13204. var gl = this.renderer.gl;
  13205. this.renderer.setRenderTarget(outputTarget);
  13206. if (clear)
  13207. {
  13208. outputTarget.clear();
  13209. }
  13210. // set the shader
  13211. this.renderer.shaderManager.setShader(shader);
  13212. // TODO (cengler) - Can this be cached and not `toArray`ed each frame?
  13213. shader.uniforms.projectionMatrix.value = this.renderer.currentRenderTarget.projectionMatrix.toArray(true);
  13214. //TODO can this be optimised?
  13215. shader.syncUniforms();
  13216. /*
  13217. gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
  13218. gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 2 * 4 * 4);
  13219. gl.vertexAttribPointer(shader.attributes.aColor, 4, gl.FLOAT, false, 0, 4 * 4 * 4);
  13220. */
  13221. gl.activeTexture(gl.TEXTURE0);
  13222. gl.bindTexture(gl.TEXTURE_2D, inputTarget.texture);
  13223. gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
  13224. this.renderer.drawCount++;
  13225. };
  13226. /*
  13227. * Calculates the mapped matrix
  13228. * @param filterArea {Rectangle} The filter area
  13229. * @param sprite {Sprite} the target sprite
  13230. * @param outputMatrix {Matrix} @alvin
  13231. */
  13232. // TODO playing around here.. this is temporary - (will end up in the shader)
  13233. FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite, outputMatrix)
  13234. {
  13235. var worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX),
  13236. texture = sprite._texture.baseTexture;
  13237. var mappedMatrix = outputMatrix.identity();
  13238. // scale..
  13239. var ratio = this.textureSize.height / this.textureSize.width;
  13240. mappedMatrix.translate(filterArea.x / this.textureSize.width, filterArea.y / this.textureSize.height );
  13241. mappedMatrix.scale(1 , ratio);
  13242. var translateScaleX = (this.textureSize.width / texture.width);
  13243. var translateScaleY = (this.textureSize.height / texture.height);
  13244. worldTransform.tx /= texture.width * translateScaleX;
  13245. worldTransform.ty /= texture.width * translateScaleX;
  13246. worldTransform.invert();
  13247. mappedMatrix.prepend(worldTransform);
  13248. // apply inverse scale..
  13249. mappedMatrix.scale(1 , 1/ratio);
  13250. mappedMatrix.scale( translateScaleX , translateScaleY );
  13251. mappedMatrix.translate(sprite.anchor.x, sprite.anchor.y);
  13252. return mappedMatrix;
  13253. // Keeping the orginal as a reminder to me on how this works!
  13254. //
  13255. // var m = new math.Matrix();
  13256. // // scale..
  13257. // var ratio = this.textureSize.height / this.textureSize.width;
  13258. // m.translate(filterArea.x / this.textureSize.width, filterArea.y / this.textureSize.height);
  13259. // m.scale(1 , ratio);
  13260. // var transform = wt.clone();
  13261. // var translateScaleX = (this.textureSize.width / 620);
  13262. // var translateScaleY = (this.textureSize.height / 380);
  13263. // transform.tx /= 620 * translateScaleX;
  13264. // transform.ty /= 620 * translateScaleX;
  13265. // transform.invert();
  13266. // transform.append(m);
  13267. // // apply inverse scale..
  13268. // transform.scale(1 , 1/ratio);
  13269. // transform.scale( translateScaleX , translateScaleY );
  13270. // return transform;
  13271. };
  13272. /*
  13273. * Constrains the filter area to the texture size
  13274. * @param filterArea {Rectangle} The filter area we want to cap
  13275. */
  13276. FilterManager.prototype.capFilterArea = function (filterArea)
  13277. {
  13278. if (filterArea.x < 0)
  13279. {
  13280. filterArea.width += filterArea.x;
  13281. filterArea.x = 0;
  13282. }
  13283. if (filterArea.y < 0)
  13284. {
  13285. filterArea.height += filterArea.y;
  13286. filterArea.y = 0;
  13287. }
  13288. if ( filterArea.x + filterArea.width > this.textureSize.width )
  13289. {
  13290. filterArea.width = this.textureSize.width - filterArea.x;
  13291. }
  13292. if ( filterArea.y + filterArea.height > this.textureSize.height )
  13293. {
  13294. filterArea.height = this.textureSize.height - filterArea.y;
  13295. }
  13296. };
  13297. /*
  13298. * Resizes all the render targets in the pool
  13299. * @param width {number} the new width
  13300. * @param height {number} the new height
  13301. */
  13302. FilterManager.prototype.resize = function ( width, height )
  13303. {
  13304. this.textureSize.width = width;
  13305. this.textureSize.height = height;
  13306. for (var i = 0; i < this.texturePool.length; i++)
  13307. {
  13308. this.texturePool[i].resize( width, height );
  13309. }
  13310. };
  13311. /**
  13312. * Destroys the filter and removes it from the filter stack.
  13313. *
  13314. */
  13315. FilterManager.prototype.destroy = function ()
  13316. {
  13317. this.quad.destroy();
  13318. WebGLManager.prototype.destroy.call(this);
  13319. this.filterStack = null;
  13320. this.offsetY = 0;
  13321. // destroy textures
  13322. for (var i = 0; i < this.texturePool.length; i++)
  13323. {
  13324. this.texturePool[i].destroy();
  13325. }
  13326. this.texturePool = null;
  13327. };
  13328. },{"../../../const":22,"../../../math":33,"../utils/Quad":64,"../utils/RenderTarget":65,"./WebGLManager":58}],55:[function(require,module,exports){
  13329. var WebGLManager = require('./WebGLManager'),
  13330. AlphaMaskFilter = require('../filters/SpriteMaskFilter');
  13331. /**
  13332. * @class
  13333. * @memberof PIXI
  13334. * @param renderer {PIXI.WebGLRenderer} The renderer this manager works for.
  13335. */
  13336. function MaskManager(renderer)
  13337. {
  13338. WebGLManager.call(this, renderer);
  13339. this.stencilStack = [];
  13340. this.reverse = true;
  13341. this.count = 0;
  13342. this.alphaMaskPool = [];
  13343. }
  13344. MaskManager.prototype = Object.create(WebGLManager.prototype);
  13345. MaskManager.prototype.constructor = MaskManager;
  13346. module.exports = MaskManager;
  13347. /**
  13348. * Applies the Mask and adds it to the current filter stack.
  13349. *
  13350. * @param graphics {PIXI.Graphics}
  13351. * @param webGLData {any[]}
  13352. */
  13353. MaskManager.prototype.pushMask = function (target, maskData)
  13354. {
  13355. if (maskData.texture)
  13356. {
  13357. this.pushSpriteMask(target, maskData);
  13358. }
  13359. else
  13360. {
  13361. this.pushStencilMask(target, maskData);
  13362. }
  13363. };
  13364. /**
  13365. * Removes the last mask from the mask stack and doesn't return it.
  13366. *
  13367. * @param target {PIXI.RenderTarget}
  13368. * @param maskData {any[]}
  13369. */
  13370. MaskManager.prototype.popMask = function (target, maskData)
  13371. {
  13372. if (maskData.texture)
  13373. {
  13374. this.popSpriteMask(target, maskData);
  13375. }
  13376. else
  13377. {
  13378. this.popStencilMask(target, maskData);
  13379. }
  13380. };
  13381. /**
  13382. * Applies the Mask and adds it to the current filter stack.
  13383. *
  13384. * @param target {PIXI.RenderTarget}
  13385. * @param maskData {any[]}
  13386. */
  13387. MaskManager.prototype.pushSpriteMask = function (target, maskData)
  13388. {
  13389. var alphaMaskFilter = this.alphaMaskPool.pop();
  13390. if (!alphaMaskFilter)
  13391. {
  13392. alphaMaskFilter = [new AlphaMaskFilter(maskData)];
  13393. }
  13394. alphaMaskFilter[0].maskSprite = maskData;
  13395. this.renderer.filterManager.pushFilter(target, alphaMaskFilter);
  13396. };
  13397. /**
  13398. * Removes the last filter from the filter stack and doesn't return it.
  13399. *
  13400. */
  13401. MaskManager.prototype.popSpriteMask = function ()
  13402. {
  13403. var filters = this.renderer.filterManager.popFilter();
  13404. this.alphaMaskPool.push(filters);
  13405. };
  13406. /**
  13407. * Applies the Mask and adds it to the current filter stack.
  13408. *
  13409. * @param target {PIXI.RenderTarget}
  13410. * @param maskData {any[]}
  13411. */
  13412. MaskManager.prototype.pushStencilMask = function (target, maskData)
  13413. {
  13414. this.renderer.stencilManager.pushMask(maskData);
  13415. };
  13416. /**
  13417. * Removes the last filter from the filter stack and doesn't return it.
  13418. *
  13419. * @param target {PIXI.RenderTarget}
  13420. * @param maskData {any[]}
  13421. */
  13422. MaskManager.prototype.popStencilMask = function (target, maskData)
  13423. {
  13424. this.renderer.stencilManager.popMask(maskData);
  13425. };
  13426. },{"../filters/SpriteMaskFilter":52,"./WebGLManager":58}],56:[function(require,module,exports){
  13427. var WebGLManager = require('./WebGLManager'),
  13428. TextureShader = require('../shaders/TextureShader'),
  13429. ComplexPrimitiveShader = require('../shaders/ComplexPrimitiveShader'),
  13430. PrimitiveShader = require('../shaders/PrimitiveShader'),
  13431. utils = require('../../../utils');
  13432. /**
  13433. * @class
  13434. * @memberof PIXI
  13435. * @extends PIXI.WebGLManager
  13436. * @param renderer {PIXI.WebGLRenderer} The renderer this manager works for.
  13437. */
  13438. function ShaderManager(renderer)
  13439. {
  13440. WebGLManager.call(this, renderer);
  13441. /**
  13442. * @member {number}
  13443. */
  13444. this.maxAttibs = 10;
  13445. /**
  13446. * @member {any[]}
  13447. */
  13448. this.attribState = [];
  13449. /**
  13450. * @member {any[]}
  13451. */
  13452. this.tempAttribState = [];
  13453. for (var i = 0; i < this.maxAttibs; i++)
  13454. {
  13455. this.attribState[i] = false;
  13456. }
  13457. /**
  13458. * @member {any[]}
  13459. */
  13460. this.stack = [];
  13461. /**
  13462. * @member {number}
  13463. * @private
  13464. */
  13465. this._currentId = -1;
  13466. /**
  13467. * @member {PIXI.Shader}
  13468. * @private
  13469. */
  13470. this.currentShader = null;
  13471. // this.initPlugins();
  13472. }
  13473. ShaderManager.prototype = Object.create(WebGLManager.prototype);
  13474. ShaderManager.prototype.constructor = ShaderManager;
  13475. utils.pluginTarget.mixin(ShaderManager);
  13476. module.exports = ShaderManager;
  13477. /**
  13478. * Called when there is a WebGL context change.
  13479. *
  13480. */
  13481. ShaderManager.prototype.onContextChange = function ()
  13482. {
  13483. this.initPlugins();
  13484. var gl = this.renderer.gl;
  13485. // get the maximum number of attribute correctly as this tends to vary
  13486. this.maxAttibs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
  13487. this.attribState = [];
  13488. for (var i = 0; i < this.maxAttibs; i++)
  13489. {
  13490. this.attribState[i] = false;
  13491. }
  13492. // TODO - Why are these not plugins? We can't decouple primitives unless they are....
  13493. this.defaultShader = new TextureShader(this);
  13494. this.primitiveShader = new PrimitiveShader(this);
  13495. this.complexPrimitiveShader = new ComplexPrimitiveShader(this);
  13496. };
  13497. /**
  13498. * Takes the attributes given in parameters and uploads them.
  13499. *
  13500. * @param attribs {any[]} attribs
  13501. */
  13502. ShaderManager.prototype.setAttribs = function (attribs)
  13503. {
  13504. // reset temp state
  13505. var i;
  13506. for (i = 0; i < this.tempAttribState.length; i++)
  13507. {
  13508. this.tempAttribState[i] = false;
  13509. }
  13510. // set the new attribs
  13511. for (var a in attribs)
  13512. {
  13513. this.tempAttribState[attribs[a]] = true;
  13514. }
  13515. var gl = this.renderer.gl;
  13516. for (i = 0; i < this.attribState.length; i++)
  13517. {
  13518. if (this.attribState[i] !== this.tempAttribState[i])
  13519. {
  13520. this.attribState[i] = this.tempAttribState[i];
  13521. if (this.attribState[i])
  13522. {
  13523. gl.enableVertexAttribArray(i);
  13524. }
  13525. else
  13526. {
  13527. gl.disableVertexAttribArray(i);
  13528. }
  13529. }
  13530. }
  13531. };
  13532. /**
  13533. * Sets the current shader.
  13534. *
  13535. * @param shader {PIXI.Shader} the shader to upload
  13536. */
  13537. ShaderManager.prototype.setShader = function (shader)
  13538. {
  13539. if (this._currentId === shader.uid)
  13540. {
  13541. return false;
  13542. }
  13543. this._currentId = shader.uid;
  13544. this.currentShader = shader;
  13545. this.renderer.gl.useProgram(shader.program);
  13546. this.setAttribs(shader.attributes);
  13547. return true;
  13548. };
  13549. /**
  13550. * Destroys this object.
  13551. *
  13552. */
  13553. ShaderManager.prototype.destroy = function ()
  13554. {
  13555. this.primitiveShader.destroy();
  13556. this.complexPrimitiveShader.destroy();
  13557. WebGLManager.prototype.destroy.call(this);
  13558. this.destroyPlugins();
  13559. this.attribState = null;
  13560. this.tempAttribState = null;
  13561. };
  13562. },{"../../../utils":77,"../shaders/ComplexPrimitiveShader":59,"../shaders/PrimitiveShader":60,"../shaders/TextureShader":62,"./WebGLManager":58}],57:[function(require,module,exports){
  13563. var WebGLManager = require('./WebGLManager'),
  13564. utils = require('../../../utils');
  13565. /**
  13566. * @class
  13567. * @memberof PIXI
  13568. * @param renderer {PIXI.WebGLRenderer} The renderer this manager works for.
  13569. */
  13570. function WebGLMaskManager(renderer)
  13571. {
  13572. WebGLManager.call(this, renderer);
  13573. this.stencilMaskStack = null;
  13574. }
  13575. WebGLMaskManager.prototype = Object.create(WebGLManager.prototype);
  13576. WebGLMaskManager.prototype.constructor = WebGLMaskManager;
  13577. module.exports = WebGLMaskManager;
  13578. /**
  13579. * Changes the mask stack that is used by this manager.
  13580. *
  13581. * @param stencilMaskStack {PIXI.StencilMaskStack} The mask stack
  13582. */
  13583. WebGLMaskManager.prototype.setMaskStack = function ( stencilMaskStack )
  13584. {
  13585. this.stencilMaskStack = stencilMaskStack;
  13586. var gl = this.renderer.gl;
  13587. if (stencilMaskStack.stencilStack.length === 0)
  13588. {
  13589. gl.disable(gl.STENCIL_TEST);
  13590. }
  13591. else
  13592. {
  13593. gl.enable(gl.STENCIL_TEST);
  13594. }
  13595. };
  13596. /**
  13597. * Applies the Mask and adds it to the current filter stack. @alvin
  13598. *
  13599. * @param graphics {PIXI.Graphics}
  13600. * @param webGLData {any[]}
  13601. */
  13602. WebGLMaskManager.prototype.pushStencil = function (graphics, webGLData)
  13603. {
  13604. this.renderer.currentRenderTarget.attachStencilBuffer();
  13605. var gl = this.renderer.gl,
  13606. sms = this.stencilMaskStack;
  13607. this.bindGraphics(graphics, webGLData);
  13608. if (sms.stencilStack.length === 0)
  13609. {
  13610. gl.enable(gl.STENCIL_TEST);
  13611. gl.clear(gl.STENCIL_BUFFER_BIT);
  13612. sms.reverse = true;
  13613. sms.count = 0;
  13614. }
  13615. sms.stencilStack.push(webGLData);
  13616. var level = sms.count;
  13617. gl.colorMask(false, false, false, false);
  13618. gl.stencilFunc(gl.ALWAYS,0,0xFF);
  13619. gl.stencilOp(gl.KEEP,gl.KEEP,gl.INVERT);
  13620. // draw the triangle strip!
  13621. if (webGLData.mode === 1)
  13622. {
  13623. gl.drawElements(gl.TRIANGLE_FAN, webGLData.indices.length - 4, gl.UNSIGNED_SHORT, 0 );
  13624. if (sms.reverse)
  13625. {
  13626. gl.stencilFunc(gl.EQUAL, 0xFF - level, 0xFF);
  13627. gl.stencilOp(gl.KEEP,gl.KEEP,gl.DECR);
  13628. }
  13629. else
  13630. {
  13631. gl.stencilFunc(gl.EQUAL,level, 0xFF);
  13632. gl.stencilOp(gl.KEEP,gl.KEEP,gl.INCR);
  13633. }
  13634. // draw a quad to increment..
  13635. gl.drawElements(gl.TRIANGLE_FAN, 4, gl.UNSIGNED_SHORT, ( webGLData.indices.length - 4 ) * 2 );
  13636. if (sms.reverse)
  13637. {
  13638. gl.stencilFunc(gl.EQUAL,0xFF-(level+1), 0xFF);
  13639. }
  13640. else
  13641. {
  13642. gl.stencilFunc(gl.EQUAL,level+1, 0xFF);
  13643. }
  13644. sms.reverse = !sms.reverse;
  13645. }
  13646. else
  13647. {
  13648. if (!sms.reverse)
  13649. {
  13650. gl.stencilFunc(gl.EQUAL, 0xFF - level, 0xFF);
  13651. gl.stencilOp(gl.KEEP,gl.KEEP,gl.DECR);
  13652. }
  13653. else
  13654. {
  13655. gl.stencilFunc(gl.EQUAL,level, 0xFF);
  13656. gl.stencilOp(gl.KEEP,gl.KEEP,gl.INCR);
  13657. }
  13658. gl.drawElements(gl.TRIANGLE_STRIP, webGLData.indices.length, gl.UNSIGNED_SHORT, 0 );
  13659. if (!sms.reverse)
  13660. {
  13661. gl.stencilFunc(gl.EQUAL,0xFF-(level+1), 0xFF);
  13662. }
  13663. else
  13664. {
  13665. gl.stencilFunc(gl.EQUAL,level+1, 0xFF);
  13666. }
  13667. }
  13668. gl.colorMask(true, true, true, true);
  13669. gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP);
  13670. sms.count++;
  13671. };
  13672. /**
  13673. * TODO this does not belong here!
  13674. *
  13675. * @param graphics {PIXI.Graphics}
  13676. * @param webGLData {any[]}
  13677. */
  13678. WebGLMaskManager.prototype.bindGraphics = function (graphics, webGLData)
  13679. {
  13680. //if (this._currentGraphics === graphics)return;
  13681. var gl = this.renderer.gl;
  13682. // bind the graphics object..
  13683. var shader;// = this.renderer.shaderManager.plugins.primitiveShader;
  13684. if (webGLData.mode === 1)
  13685. {
  13686. shader = this.renderer.shaderManager.complexPrimitiveShader;
  13687. this.renderer.shaderManager.setShader(shader);
  13688. gl.uniformMatrix3fv(shader.uniforms.translationMatrix._location, false, graphics.worldTransform.toArray(true));
  13689. gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, this.renderer.currentRenderTarget.projectionMatrix.toArray(true));
  13690. gl.uniform3fv(shader.uniforms.tint._location, utils.hex2rgb(graphics.tint));
  13691. gl.uniform3fv(shader.uniforms.color._location, webGLData.color);
  13692. gl.uniform1f(shader.uniforms.alpha._location, graphics.worldAlpha);
  13693. gl.bindBuffer(gl.ARRAY_BUFFER, webGLData.buffer);
  13694. gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 4 * 2, 0);
  13695. // now do the rest..
  13696. // set the index buffer!
  13697. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, webGLData.indexBuffer);
  13698. }
  13699. else
  13700. {
  13701. //this.renderer.shaderManager.activatePrimitiveShader();
  13702. shader = this.renderer.shaderManager.primitiveShader;
  13703. this.renderer.shaderManager.setShader(shader);
  13704. gl.uniformMatrix3fv(shader.uniforms.translationMatrix._location, false, graphics.worldTransform.toArray(true));
  13705. gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, this.renderer.currentRenderTarget.projectionMatrix.toArray(true));
  13706. gl.uniform3fv(shader.uniforms.tint._location, utils.hex2rgb(graphics.tint));
  13707. gl.uniform1f(shader.uniforms.alpha._location, graphics.worldAlpha);
  13708. gl.bindBuffer(gl.ARRAY_BUFFER, webGLData.buffer);
  13709. gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 4 * 6, 0);
  13710. gl.vertexAttribPointer(shader.attributes.aColor, 4, gl.FLOAT, false,4 * 6, 2 * 4);
  13711. // set the index buffer!
  13712. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, webGLData.indexBuffer);
  13713. }
  13714. };
  13715. /**
  13716. * TODO @alvin
  13717. * @param graphics {PIXI.Graphics}
  13718. * @param webGLData {any[]}
  13719. */
  13720. WebGLMaskManager.prototype.popStencil = function (graphics, webGLData)
  13721. {
  13722. var gl = this.renderer.gl,
  13723. sms = this.stencilMaskStack;
  13724. sms.stencilStack.pop();
  13725. sms.count--;
  13726. if (sms.stencilStack.length === 0)
  13727. {
  13728. // the stack is empty!
  13729. gl.disable(gl.STENCIL_TEST);
  13730. }
  13731. else
  13732. {
  13733. var level = sms.count;
  13734. this.bindGraphics(graphics, webGLData);
  13735. gl.colorMask(false, false, false, false);
  13736. if (webGLData.mode === 1)
  13737. {
  13738. sms.reverse = !sms.reverse;
  13739. if (sms.reverse)
  13740. {
  13741. gl.stencilFunc(gl.EQUAL, 0xFF - (level+1), 0xFF);
  13742. gl.stencilOp(gl.KEEP,gl.KEEP,gl.INCR);
  13743. }
  13744. else
  13745. {
  13746. gl.stencilFunc(gl.EQUAL,level+1, 0xFF);
  13747. gl.stencilOp(gl.KEEP,gl.KEEP,gl.DECR);
  13748. }
  13749. // draw a quad to increment..
  13750. gl.drawElements(gl.TRIANGLE_FAN, 4, gl.UNSIGNED_SHORT, ( webGLData.indices.length - 4 ) * 2 );
  13751. gl.stencilFunc(gl.ALWAYS,0,0xFF);
  13752. gl.stencilOp(gl.KEEP,gl.KEEP,gl.INVERT);
  13753. // draw the triangle strip!
  13754. gl.drawElements(gl.TRIANGLE_FAN, webGLData.indices.length - 4, gl.UNSIGNED_SHORT, 0 );
  13755. this.renderer.drawCount += 2;
  13756. if (!sms.reverse)
  13757. {
  13758. gl.stencilFunc(gl.EQUAL,0xFF-(level), 0xFF);
  13759. }
  13760. else
  13761. {
  13762. gl.stencilFunc(gl.EQUAL,level, 0xFF);
  13763. }
  13764. }
  13765. else
  13766. {
  13767. // console.log("<<>>")
  13768. if (!sms.reverse)
  13769. {
  13770. gl.stencilFunc(gl.EQUAL, 0xFF - (level+1), 0xFF);
  13771. gl.stencilOp(gl.KEEP,gl.KEEP,gl.INCR);
  13772. }
  13773. else
  13774. {
  13775. gl.stencilFunc(gl.EQUAL,level+1, 0xFF);
  13776. gl.stencilOp(gl.KEEP,gl.KEEP,gl.DECR);
  13777. }
  13778. gl.drawElements(gl.TRIANGLE_STRIP, webGLData.indices.length, gl.UNSIGNED_SHORT, 0 );
  13779. this.renderer.drawCount++;
  13780. if (!sms.reverse)
  13781. {
  13782. gl.stencilFunc(gl.EQUAL,0xFF-(level), 0xFF);
  13783. }
  13784. else
  13785. {
  13786. gl.stencilFunc(gl.EQUAL,level, 0xFF);
  13787. }
  13788. }
  13789. gl.colorMask(true, true, true, true);
  13790. gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP);
  13791. }
  13792. };
  13793. /**
  13794. * Destroys the mask stack.
  13795. *
  13796. */
  13797. WebGLMaskManager.prototype.destroy = function ()
  13798. {
  13799. WebGLManager.prototype.destroy.call(this);
  13800. this.stencilMaskStack.stencilStack = null;
  13801. };
  13802. /**
  13803. * Applies the Mask and adds it to the current filter stack.
  13804. *
  13805. * @param maskData {any[]} The mask data structure to use
  13806. */
  13807. WebGLMaskManager.prototype.pushMask = function (maskData)
  13808. {
  13809. this.renderer.setObjectRenderer(this.renderer.plugins.graphics);
  13810. if (maskData.dirty)
  13811. {
  13812. this.renderer.plugins.graphics.updateGraphics(maskData, this.renderer.gl);
  13813. }
  13814. if (!maskData._webGL[this.renderer.gl.id].data.length)
  13815. {
  13816. return;
  13817. }
  13818. this.pushStencil(maskData, maskData._webGL[this.renderer.gl.id].data[0]);
  13819. };
  13820. /**
  13821. * Removes the last filter from the filter stack and doesn't return it.
  13822. *
  13823. * @param maskData {any[]}
  13824. */
  13825. WebGLMaskManager.prototype.popMask = function (maskData)
  13826. {
  13827. this.renderer.setObjectRenderer(this.renderer.plugins.graphics);
  13828. this.popStencil(maskData, maskData._webGL[this.renderer.gl.id].data[0]);
  13829. };
  13830. },{"../../../utils":77,"./WebGLManager":58}],58:[function(require,module,exports){
  13831. /**
  13832. * @class
  13833. * @memberof PIXI
  13834. * @param renderer {PIXI.WebGLRenderer} The renderer this manager works for.
  13835. */
  13836. function WebGLManager(renderer)
  13837. {
  13838. /**
  13839. * The renderer this manager works for.
  13840. *
  13841. * @member {PIXI.WebGLRenderer}
  13842. */
  13843. this.renderer = renderer;
  13844. this.renderer.on('context', this.onContextChange, this);
  13845. }
  13846. WebGLManager.prototype.constructor = WebGLManager;
  13847. module.exports = WebGLManager;
  13848. /**
  13849. * Generic method called when there is a WebGL context change.
  13850. *
  13851. */
  13852. WebGLManager.prototype.onContextChange = function ()
  13853. {
  13854. // do some codes init!
  13855. };
  13856. /**
  13857. * Generic destroy methods to be overridden by the subclass
  13858. *
  13859. */
  13860. WebGLManager.prototype.destroy = function ()
  13861. {
  13862. this.renderer.off('context', this.onContextChange, this);
  13863. this.renderer = null;
  13864. };
  13865. },{}],59:[function(require,module,exports){
  13866. var Shader = require('./Shader');
  13867. /**
  13868. * This shader is used to draw complex primitive shapes for {@link PIXI.Graphics}.
  13869. *
  13870. * @class
  13871. * @memberof PIXI
  13872. * @extends PIXI.Shader
  13873. * @param shaderManager {PIXI.ShaderManager} The webgl shader manager this shader works for.
  13874. */
  13875. function ComplexPrimitiveShader(shaderManager)
  13876. {
  13877. Shader.call(this,
  13878. shaderManager,
  13879. // vertex shader
  13880. [
  13881. 'attribute vec2 aVertexPosition;',
  13882. 'uniform mat3 translationMatrix;',
  13883. 'uniform mat3 projectionMatrix;',
  13884. 'uniform vec3 tint;',
  13885. 'uniform float alpha;',
  13886. 'uniform vec3 color;',
  13887. 'varying vec4 vColor;',
  13888. 'void main(void){',
  13889. ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);',
  13890. ' vColor = vec4(color * alpha * tint, alpha);',//" * vec4(tint * alpha, alpha);',
  13891. '}'
  13892. ].join('\n'),
  13893. // fragment shader
  13894. [
  13895. 'precision mediump float;',
  13896. 'varying vec4 vColor;',
  13897. 'void main(void){',
  13898. ' gl_FragColor = vColor;',
  13899. '}'
  13900. ].join('\n'),
  13901. // custom uniforms
  13902. {
  13903. tint: { type: '3f', value: [0, 0, 0] },
  13904. alpha: { type: '1f', value: 0 },
  13905. color: { type: '3f', value: [0,0,0] },
  13906. translationMatrix: { type: 'mat3', value: new Float32Array(9) },
  13907. projectionMatrix: { type: 'mat3', value: new Float32Array(9) }
  13908. },
  13909. // attributes
  13910. {
  13911. aVertexPosition:0
  13912. }
  13913. );
  13914. }
  13915. ComplexPrimitiveShader.prototype = Object.create(Shader.prototype);
  13916. ComplexPrimitiveShader.prototype.constructor = ComplexPrimitiveShader;
  13917. module.exports = ComplexPrimitiveShader;
  13918. },{"./Shader":61}],60:[function(require,module,exports){
  13919. var Shader = require('./Shader');
  13920. /**
  13921. * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}.
  13922. *
  13923. * @class
  13924. * @memberof PIXI
  13925. * @extends PIXI.Shader
  13926. * @param shaderManager {ShaderManager} The webgl shader manager this shader works for.
  13927. */
  13928. function PrimitiveShader(shaderManager)
  13929. {
  13930. Shader.call(this,
  13931. shaderManager,
  13932. // vertex shader
  13933. [
  13934. 'attribute vec2 aVertexPosition;',
  13935. 'attribute vec4 aColor;',
  13936. 'uniform mat3 translationMatrix;',
  13937. 'uniform mat3 projectionMatrix;',
  13938. 'uniform float alpha;',
  13939. 'uniform float flipY;',
  13940. 'uniform vec3 tint;',
  13941. 'varying vec4 vColor;',
  13942. 'void main(void){',
  13943. ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);',
  13944. ' vColor = aColor * vec4(tint * alpha, alpha);',
  13945. '}'
  13946. ].join('\n'),
  13947. // fragment shader
  13948. [
  13949. 'precision mediump float;',
  13950. 'varying vec4 vColor;',
  13951. 'void main(void){',
  13952. ' gl_FragColor = vColor;',
  13953. '}'
  13954. ].join('\n'),
  13955. // custom uniforms
  13956. {
  13957. tint: { type: '3f', value: [0, 0, 0] },
  13958. alpha: { type: '1f', value: 0 },
  13959. translationMatrix: { type: 'mat3', value: new Float32Array(9) },
  13960. projectionMatrix: { type: 'mat3', value: new Float32Array(9) }
  13961. },
  13962. // custom attributes
  13963. {
  13964. aVertexPosition:0,
  13965. aColor:0
  13966. }
  13967. );
  13968. }
  13969. PrimitiveShader.prototype = Object.create(Shader.prototype);
  13970. PrimitiveShader.prototype.constructor = PrimitiveShader;
  13971. module.exports = PrimitiveShader;
  13972. },{"./Shader":61}],61:[function(require,module,exports){
  13973. /*global console */
  13974. var utils = require('../../../utils');
  13975. /**
  13976. * Base shader class for PIXI managed shaders.
  13977. *
  13978. * @class
  13979. * @memberof PIXI
  13980. * @param shaderManager {PIXI.ShaderManager} The webgl shader manager this shader works for.
  13981. * @param [vertexSrc] {string} The source of the vertex shader.
  13982. * @param [fragmentSrc] {string} The source of the fragment shader.
  13983. * @param [uniforms] {object} Uniforms for this shader.
  13984. * @param [attributes] {object} Attributes for this shader.
  13985. */
  13986. function Shader(shaderManager, vertexSrc, fragmentSrc, uniforms, attributes)
  13987. {
  13988. if (!vertexSrc || !fragmentSrc)
  13989. {
  13990. throw new Error('Pixi.js Error. Shader requires vertexSrc and fragmentSrc');
  13991. }
  13992. /**
  13993. * A unique id
  13994. * @member {number}
  13995. * @readonly
  13996. */
  13997. this.uid = utils.uid();
  13998. /**
  13999. * The current WebGL drawing context
  14000. * @member {WebGLRenderingContext}
  14001. * @readonly
  14002. */
  14003. this.gl = shaderManager.renderer.gl;
  14004. //TODO maybe we should pass renderer rather than shader manger?? food for thought..
  14005. this.shaderManager = shaderManager;
  14006. /**
  14007. * The WebGL program.
  14008. *
  14009. * @member {WebGLProgram}
  14010. * @readonly
  14011. */
  14012. this.program = null;
  14013. /**
  14014. * The uniforms as an object
  14015. * @member {object}
  14016. * @private
  14017. */
  14018. this.uniforms = uniforms || {};
  14019. /**
  14020. * The attributes as an object
  14021. * @member {object}
  14022. * @private
  14023. */
  14024. this.attributes = attributes || {};
  14025. /**
  14026. * Internal texture counter
  14027. * @member {number}
  14028. * @private
  14029. */
  14030. this.textureCount = 1;
  14031. /**
  14032. * The vertex shader as an array of strings
  14033. *
  14034. * @member {string}
  14035. */
  14036. this.vertexSrc = vertexSrc;
  14037. /**
  14038. * The fragment shader as an array of strings
  14039. *
  14040. * @member {string}
  14041. */
  14042. this.fragmentSrc = fragmentSrc;
  14043. this.init();
  14044. }
  14045. Shader.prototype.constructor = Shader;
  14046. module.exports = Shader;
  14047. /**
  14048. * Creates the shader and uses it
  14049. *
  14050. */
  14051. Shader.prototype.init = function ()
  14052. {
  14053. this.compile();
  14054. this.gl.useProgram(this.program);
  14055. this.cacheUniformLocations(Object.keys(this.uniforms));
  14056. this.cacheAttributeLocations(Object.keys(this.attributes));
  14057. };
  14058. /**
  14059. * Caches the locations of the uniform for reuse.
  14060. *
  14061. * @param keys {string} the uniforms to cache
  14062. */
  14063. Shader.prototype.cacheUniformLocations = function (keys)
  14064. {
  14065. for (var i = 0; i < keys.length; ++i)
  14066. {
  14067. this.uniforms[keys[i]]._location = this.gl.getUniformLocation(this.program, keys[i]);
  14068. }
  14069. };
  14070. /**
  14071. * Caches the locations of the attribute for reuse.
  14072. *
  14073. * @param keys {string} the attributes to cache
  14074. */
  14075. Shader.prototype.cacheAttributeLocations = function (keys)
  14076. {
  14077. for (var i = 0; i < keys.length; ++i)
  14078. {
  14079. this.attributes[keys[i]] = this.gl.getAttribLocation(this.program, keys[i]);
  14080. }
  14081. // TODO: Check if this is needed anymore...
  14082. // Begin worst hack eva //
  14083. // WHY??? ONLY on my chrome pixel the line above returns -1 when using filters?
  14084. // maybe its something to do with the current state of the gl context.
  14085. // I'm convinced this is a bug in the chrome browser as there is NO reason why this should be returning -1 especially as it only manifests on my chrome pixel
  14086. // If theres any webGL people that know why could happen please help :)
  14087. // if (this.attributes.aColor === -1){
  14088. // this.attributes.aColor = 2;
  14089. // }
  14090. // End worst hack eva //
  14091. };
  14092. /**
  14093. * Attaches the shaders and creates the program.
  14094. *
  14095. * @return {WebGLProgram}
  14096. */
  14097. Shader.prototype.compile = function ()
  14098. {
  14099. var gl = this.gl;
  14100. var glVertShader = this._glCompile(gl.VERTEX_SHADER, this.vertexSrc);
  14101. var glFragShader = this._glCompile(gl.FRAGMENT_SHADER, this.fragmentSrc);
  14102. var program = gl.createProgram();
  14103. gl.attachShader(program, glVertShader);
  14104. gl.attachShader(program, glFragShader);
  14105. gl.linkProgram(program);
  14106. // if linking fails, then log and cleanup
  14107. if (!gl.getProgramParameter(program, gl.LINK_STATUS))
  14108. {
  14109. console.error('Pixi.js Error: Could not initialize shader.');
  14110. console.error('gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS));
  14111. console.error('gl.getError()', gl.getError());
  14112. // if there is a program info log, log it
  14113. if (gl.getProgramInfoLog(program) !== '')
  14114. {
  14115. console.warn('Pixi.js Warning: gl.getProgramInfoLog()', gl.getProgramInfoLog(program));
  14116. }
  14117. gl.deleteProgram(program);
  14118. program = null;
  14119. }
  14120. // clean up some shaders
  14121. gl.deleteShader(glVertShader);
  14122. gl.deleteShader(glFragShader);
  14123. return (this.program = program);
  14124. };
  14125. /*
  14126. Shader.prototype.buildSync = function ()
  14127. {
  14128. // var str = ""
  14129. // str = "Shader.prototype.syncUniforms = function()";
  14130. // str += "{\n";
  14131. for (var key in this.uniforms)
  14132. {
  14133. var uniform = this.uniforms[key];
  14134. Object.defineProperty(this, key, {
  14135. get: function ()
  14136. {
  14137. return uniform.value
  14138. },
  14139. set: function (value)
  14140. {
  14141. this.setUniform(uniform, value);
  14142. }
  14143. });
  14144. console.log( makePropSetter( key, " bloop", uniform.type ) )
  14145. // Object.def
  14146. // location = uniform._location,
  14147. // value = uniform.value,
  14148. //i, il;
  14149. // str += "gl.uniform1i(this.uniforms."+ key +"._location, this.uniforms." + key + ".value );\n"
  14150. }
  14151. }*/
  14152. /**
  14153. * Adds a new uniform
  14154. *
  14155. * @param uniform {object} the new uniform to attach
  14156. */
  14157. Shader.prototype.syncUniform = function (uniform)
  14158. {
  14159. var location = uniform._location,
  14160. value = uniform.value,
  14161. gl = this.gl,
  14162. i, il;
  14163. switch (uniform.type)
  14164. {
  14165. case 'b':
  14166. case 'bool':
  14167. case 'boolean':
  14168. gl.uniform1i(location, value ? 1 : 0);
  14169. break;
  14170. // single int value
  14171. case 'i':
  14172. case '1i':
  14173. gl.uniform1i(location, value);
  14174. break;
  14175. // single float value
  14176. case 'f':
  14177. case '1f':
  14178. gl.uniform1f(location, value);
  14179. break;
  14180. // Float32Array(2) or JS Arrray
  14181. case '2f':
  14182. gl.uniform2f(location, value[0], value[1]);
  14183. break;
  14184. // Float32Array(3) or JS Arrray
  14185. case '3f':
  14186. gl.uniform3f(location, value[0], value[1], value[2]);
  14187. break;
  14188. // Float32Array(4) or JS Arrray
  14189. case '4f':
  14190. gl.uniform4f(location, value[0], value[1], value[2], value[3]);
  14191. break;
  14192. // a 2D Point object
  14193. case 'v2':
  14194. gl.uniform2f(location, value.x, value.y);
  14195. break;
  14196. // a 3D Point object
  14197. case 'v3':
  14198. gl.uniform3f(location, value.x, value.y, value.z);
  14199. break;
  14200. // a 4D Point object
  14201. case 'v4':
  14202. gl.uniform4f(location, value.x, value.y, value.z, value.w);
  14203. break;
  14204. // Int32Array or JS Array
  14205. case '1iv':
  14206. gl.uniform1iv(location, value);
  14207. break;
  14208. // Int32Array or JS Array
  14209. case '2iv':
  14210. gl.uniform2iv(location, value);
  14211. break;
  14212. // Int32Array or JS Array
  14213. case '3iv':
  14214. gl.uniform3iv(location, value);
  14215. break;
  14216. // Int32Array or JS Array
  14217. case '4iv':
  14218. gl.uniform4iv(location, value);
  14219. break;
  14220. // Float32Array or JS Array
  14221. case '1fv':
  14222. gl.uniform1fv(location, value);
  14223. break;
  14224. // Float32Array or JS Array
  14225. case '2fv':
  14226. gl.uniform2fv(location, value);
  14227. break;
  14228. // Float32Array or JS Array
  14229. case '3fv':
  14230. gl.uniform3fv(location, value);
  14231. break;
  14232. // Float32Array or JS Array
  14233. case '4fv':
  14234. gl.uniform4fv(location, value);
  14235. break;
  14236. // Float32Array or JS Array
  14237. case 'm2':
  14238. case 'mat2':
  14239. case 'Matrix2fv':
  14240. gl.uniformMatrix2fv(location, uniform.transpose, value);
  14241. break;
  14242. // Float32Array or JS Array
  14243. case 'm3':
  14244. case 'mat3':
  14245. case 'Matrix3fv':
  14246. gl.uniformMatrix3fv(location, uniform.transpose, value);
  14247. break;
  14248. // Float32Array or JS Array
  14249. case 'm4':
  14250. case 'mat4':
  14251. case 'Matrix4fv':
  14252. gl.uniformMatrix4fv(location, uniform.transpose, value);
  14253. break;
  14254. // a Color Value
  14255. case 'c':
  14256. if (typeof value === 'number')
  14257. {
  14258. value = utils.hex2rgb(value);
  14259. }
  14260. gl.uniform3f(location, value[0], value[1], value[2]);
  14261. break;
  14262. // flat array of integers (JS or typed array)
  14263. case 'iv1':
  14264. gl.uniform1iv(location, value);
  14265. break;
  14266. // flat array of integers with 3 x N size (JS or typed array)
  14267. case 'iv':
  14268. gl.uniform3iv(location, value);
  14269. break;
  14270. // flat array of floats (JS or typed array)
  14271. case 'fv1':
  14272. gl.uniform1fv(location, value);
  14273. break;
  14274. // flat array of floats with 3 x N size (JS or typed array)
  14275. case 'fv':
  14276. gl.uniform3fv(location, value);
  14277. break;
  14278. // array of 2D Point objects
  14279. case 'v2v':
  14280. if (!uniform._array)
  14281. {
  14282. uniform._array = new Float32Array(2 * value.length);
  14283. }
  14284. for (i = 0, il = value.length; i < il; ++i)
  14285. {
  14286. uniform._array[i * 2] = value[i].x;
  14287. uniform._array[i * 2 + 1] = value[i].y;
  14288. }
  14289. gl.uniform2fv(location, uniform._array);
  14290. break;
  14291. // array of 3D Point objects
  14292. case 'v3v':
  14293. if (!uniform._array)
  14294. {
  14295. uniform._array = new Float32Array(3 * value.length);
  14296. }
  14297. for (i = 0, il = value.length; i < il; ++i)
  14298. {
  14299. uniform._array[i * 3] = value[i].x;
  14300. uniform._array[i * 3 + 1] = value[i].y;
  14301. uniform._array[i * 3 + 2] = value[i].z;
  14302. }
  14303. gl.uniform3fv(location, uniform._array);
  14304. break;
  14305. // array of 4D Point objects
  14306. case 'v4v':
  14307. if (!uniform._array)
  14308. {
  14309. uniform._array = new Float32Array(4 * value.length);
  14310. }
  14311. for (i = 0, il = value.length; i < il; ++i)
  14312. {
  14313. uniform._array[i * 4] = value[i].x;
  14314. uniform._array[i * 4 + 1] = value[i].y;
  14315. uniform._array[i * 4 + 2] = value[i].z;
  14316. uniform._array[i * 4 + 3] = value[i].w;
  14317. }
  14318. gl.uniform4fv(location, uniform._array);
  14319. break;
  14320. // PIXI.Texture
  14321. case 't':
  14322. case 'sampler2D':
  14323. if (!uniform.value || !uniform.value.baseTexture.hasLoaded)
  14324. {
  14325. break;
  14326. }
  14327. // activate this texture
  14328. gl.activeTexture(gl['TEXTURE' + this.textureCount]);
  14329. var texture = uniform.value.baseTexture._glTextures[gl.id];
  14330. if (!texture)
  14331. {
  14332. this.initSampler2D(uniform);
  14333. // set the textur to the newly created one..
  14334. texture = uniform.value.baseTexture._glTextures[gl.id];
  14335. }
  14336. // bind the texture
  14337. gl.bindTexture(gl.TEXTURE_2D, texture);
  14338. // set uniform to texture index
  14339. gl.uniform1i(uniform._location, this.textureCount);
  14340. // increment next texture id
  14341. this.textureCount++;
  14342. break;
  14343. default:
  14344. console.warn('Pixi.js Shader Warning: Unknown uniform type: ' + uniform.type);
  14345. }
  14346. };
  14347. /**
  14348. * Updates the shader uniform values.
  14349. *
  14350. */
  14351. Shader.prototype.syncUniforms = function ()
  14352. {
  14353. this.textureCount = 1;
  14354. for (var key in this.uniforms)
  14355. {
  14356. this.syncUniform(this.uniforms[key]);
  14357. }
  14358. };
  14359. /**
  14360. * Initialises a Sampler2D uniform (which may only be available later on after initUniforms once the texture has loaded)
  14361. *
  14362. */
  14363. Shader.prototype.initSampler2D = function (uniform)
  14364. {
  14365. var gl = this.gl;
  14366. var texture = uniform.value.baseTexture;
  14367. if(!texture.hasLoaded)
  14368. {
  14369. return;
  14370. }
  14371. if (uniform.textureData)
  14372. {
  14373. //TODO move this...
  14374. var data = uniform.textureData;
  14375. texture._glTextures[gl.id] = gl.createTexture();
  14376. gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]);
  14377. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha);
  14378. // GLTexture = mag linear, min linear_mipmap_linear, wrap repeat + gl.generateMipmap(gl.TEXTURE_2D);
  14379. // GLTextureLinear = mag/min linear, wrap clamp
  14380. // GLTextureNearestRepeat = mag/min NEAREST, wrap repeat
  14381. // GLTextureNearest = mag/min nearest, wrap clamp
  14382. // AudioTexture = whatever + luminance + width 512, height 2, border 0
  14383. // KeyTexture = whatever + luminance + width 256, height 2, border 0
  14384. // magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST
  14385. // wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT
  14386. gl.texImage2D(gl.TEXTURE_2D, 0, data.luminance ? gl.LUMINANCE : gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source);
  14387. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, data.magFilter ? data.magFilter : gl.LINEAR );
  14388. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, data.wrapS ? data.wrapS : gl.CLAMP_TO_EDGE );
  14389. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, data.wrapS ? data.wrapS : gl.CLAMP_TO_EDGE);
  14390. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, data.wrapT ? data.wrapT : gl.CLAMP_TO_EDGE);
  14391. }
  14392. else
  14393. {
  14394. this.shaderManager.renderer.updateTexture(texture);
  14395. }
  14396. };
  14397. /**
  14398. * Destroys the shader.
  14399. *
  14400. */
  14401. Shader.prototype.destroy = function ()
  14402. {
  14403. this.gl.deleteProgram(this.program);
  14404. this.gl = null;
  14405. this.uniforms = null;
  14406. this.attributes = null;
  14407. this.vertexSrc = null;
  14408. this.fragmentSrc = null;
  14409. };
  14410. Shader.prototype._glCompile = function (type, src)
  14411. {
  14412. var shader = this.gl.createShader(type);
  14413. this.gl.shaderSource(shader, src);
  14414. this.gl.compileShader(shader);
  14415. if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS))
  14416. {
  14417. console.log(this.gl.getShaderInfoLog(shader));
  14418. return null;
  14419. }
  14420. return shader;
  14421. };
  14422. },{"../../../utils":77}],62:[function(require,module,exports){
  14423. var Shader = require('./Shader');
  14424. /**
  14425. * @class
  14426. * @memberof PIXI
  14427. * @extends PIXI.Shader
  14428. * @param shaderManager {PIXI.ShaderManager} The webgl shader manager this shader works for.
  14429. * @param [vertexSrc] {string} The source of the vertex shader.
  14430. * @param [fragmentSrc] {string} The source of the fragment shader.
  14431. * @param [customUniforms] {object} Custom uniforms to use to augment the built-in ones.
  14432. * @param [fragmentSrc] {string} The source of the fragment shader.
  14433. */
  14434. function TextureShader(shaderManager, vertexSrc, fragmentSrc, customUniforms, customAttributes)
  14435. {
  14436. var uniforms = {
  14437. uSampler: { type: 'sampler2D', value: 0 },
  14438. projectionMatrix: { type: 'mat3', value: new Float32Array([1, 0, 0,
  14439. 0, 1, 0,
  14440. 0, 0, 1]) }
  14441. };
  14442. if (customUniforms)
  14443. {
  14444. for (var u in customUniforms)
  14445. {
  14446. uniforms[u] = customUniforms[u];
  14447. }
  14448. }
  14449. var attributes = {
  14450. aVertexPosition: 0,
  14451. aTextureCoord: 0,
  14452. aColor: 0
  14453. };
  14454. if (customAttributes)
  14455. {
  14456. for (var a in customAttributes)
  14457. {
  14458. attributes[a] = customAttributes[a];
  14459. }
  14460. }
  14461. /**
  14462. * The vertex shader.
  14463. *
  14464. * @member {string}
  14465. */
  14466. vertexSrc = vertexSrc || TextureShader.defaultVertexSrc;
  14467. /**
  14468. * The fragment shader.
  14469. *
  14470. * @member {string}
  14471. */
  14472. fragmentSrc = fragmentSrc || TextureShader.defaultFragmentSrc;
  14473. Shader.call(this, shaderManager, vertexSrc, fragmentSrc, uniforms, attributes);
  14474. }
  14475. // constructor
  14476. TextureShader.prototype = Object.create(Shader.prototype);
  14477. TextureShader.prototype.constructor = TextureShader;
  14478. module.exports = TextureShader;
  14479. /**
  14480. * The default vertex shader source
  14481. *
  14482. * @static
  14483. * @constant
  14484. */
  14485. TextureShader.defaultVertexSrc = [
  14486. 'precision lowp float;',
  14487. 'attribute vec2 aVertexPosition;',
  14488. 'attribute vec2 aTextureCoord;',
  14489. 'attribute vec4 aColor;',
  14490. 'uniform mat3 projectionMatrix;',
  14491. 'varying vec2 vTextureCoord;',
  14492. 'varying vec4 vColor;',
  14493. 'void main(void){',
  14494. ' gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);',
  14495. ' vTextureCoord = aTextureCoord;',
  14496. ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);',
  14497. '}'
  14498. ].join('\n');
  14499. /**
  14500. * The default fragment shader source
  14501. *
  14502. * @static
  14503. * @constant
  14504. */
  14505. TextureShader.defaultFragmentSrc = [
  14506. 'precision lowp float;',
  14507. 'varying vec2 vTextureCoord;',
  14508. 'varying vec4 vColor;',
  14509. 'uniform sampler2D uSampler;',
  14510. 'void main(void){',
  14511. ' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;',
  14512. '}'
  14513. ].join('\n');
  14514. },{"./Shader":61}],63:[function(require,module,exports){
  14515. var WebGLManager = require('../managers/WebGLManager');
  14516. /**
  14517. * Base for a common object renderer that can be used as a system renderer plugin.
  14518. *
  14519. * @class
  14520. * @extends PIXI.WebGLManager
  14521. * @memberof PIXI
  14522. * @param renderer {PIXI.WebGLRenderer} The renderer this object renderer works for.
  14523. */
  14524. function ObjectRenderer(renderer)
  14525. {
  14526. WebGLManager.call(this, renderer);
  14527. }
  14528. ObjectRenderer.prototype = Object.create(WebGLManager.prototype);
  14529. ObjectRenderer.prototype.constructor = ObjectRenderer;
  14530. module.exports = ObjectRenderer;
  14531. /**
  14532. * Starts the renderer and sets the shader
  14533. *
  14534. */
  14535. ObjectRenderer.prototype.start = function ()
  14536. {
  14537. // set the shader..
  14538. };
  14539. /**
  14540. * Stops the renderer
  14541. *
  14542. */
  14543. ObjectRenderer.prototype.stop = function ()
  14544. {
  14545. this.flush();
  14546. };
  14547. /**
  14548. * flushes
  14549. *
  14550. */
  14551. ObjectRenderer.prototype.flush = function ()
  14552. {
  14553. // flush!
  14554. };
  14555. /**
  14556. * Renders an object
  14557. *
  14558. * @param object {PIXI.DisplayObject} The object to render.
  14559. */
  14560. ObjectRenderer.prototype.render = function (object) // jshint unused:false
  14561. {
  14562. // render the object
  14563. };
  14564. },{"../managers/WebGLManager":58}],64:[function(require,module,exports){
  14565. /**
  14566. * Helper class to create a quad
  14567. *
  14568. * @class
  14569. * @memberof PIXI
  14570. * @param gl {WebGLRenderingContext} The gl context for this quad to use.
  14571. */
  14572. function Quad(gl)
  14573. {
  14574. /*
  14575. * the current WebGL drawing context
  14576. *
  14577. * @member {WebGLRenderingContext}
  14578. */
  14579. this.gl = gl;
  14580. // this.textures = new TextureUvs();
  14581. /**
  14582. * An array of vertices
  14583. *
  14584. * @member {Float32Array}
  14585. */
  14586. this.vertices = new Float32Array([
  14587. 0,0,
  14588. 200,0,
  14589. 200,200,
  14590. 0,200
  14591. ]);
  14592. /**
  14593. * The Uvs of the quad
  14594. *
  14595. * @member {Float32Array}
  14596. */
  14597. this.uvs = new Float32Array([
  14598. 0,0,
  14599. 1,0,
  14600. 1,1,
  14601. 0,1
  14602. ]);
  14603. // var white = (0xFFFFFF >> 16) + (0xFFFFFF & 0xff00) + ((0xFFFFFF & 0xff) << 16) + (1 * 255 << 24);
  14604. //TODO convert this to a 32 unsigned int array
  14605. /**
  14606. * The color components of the triangles
  14607. *
  14608. * @member {Float32Array}
  14609. */
  14610. this.colors = new Float32Array([
  14611. 1,1,1,1,
  14612. 1,1,1,1,
  14613. 1,1,1,1,
  14614. 1,1,1,1
  14615. ]);
  14616. /*
  14617. * @member {Uint16Array} An array containing the indices of the vertices
  14618. */
  14619. this.indices = new Uint16Array([
  14620. 0, 1, 2, 0, 3, 2
  14621. ]);
  14622. /*
  14623. * @member {WebGLBuffer} The vertex buffer
  14624. */
  14625. this.vertexBuffer = gl.createBuffer();
  14626. /*
  14627. * @member {WebGLBuffer} The index buffer
  14628. */
  14629. this.indexBuffer = gl.createBuffer();
  14630. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
  14631. gl.bufferData(gl.ARRAY_BUFFER, (8 + 8 + 16) * 4, gl.DYNAMIC_DRAW);
  14632. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
  14633. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);
  14634. this.upload();
  14635. }
  14636. Quad.prototype.constructor = Quad;
  14637. /**
  14638. * Maps two Rectangle to the quad
  14639. * @param rect {PIXI.Rectangle} the first rectangle
  14640. * @param rect2 {PIXI.Rectangle} the second rectangle
  14641. */
  14642. Quad.prototype.map = function(rect, rect2)
  14643. {
  14644. var x = 0; //rect2.x / rect.width;
  14645. var y = 0; //rect2.y / rect.height;
  14646. this.uvs[0] = x;
  14647. this.uvs[1] = y;
  14648. this.uvs[2] = x + rect2.width / rect.width;
  14649. this.uvs[3] = y;
  14650. this.uvs[4] = x + rect2.width / rect.width;
  14651. this.uvs[5] = y + rect2.height / rect.height;
  14652. this.uvs[6] = x;
  14653. this.uvs[7] = y + rect2.height / rect.height;
  14654. /// -----
  14655. x = rect2.x;
  14656. y = rect2.y;
  14657. this.vertices[0] = x;
  14658. this.vertices[1] = y;
  14659. this.vertices[2] = x + rect2.width;
  14660. this.vertices[3] = y;
  14661. this.vertices[4] = x + rect2.width;
  14662. this.vertices[5] = y + rect2.height;
  14663. this.vertices[6] = x;
  14664. this.vertices[7] = y + rect2.height;
  14665. this.upload();
  14666. };
  14667. /**
  14668. * Binds the buffer and uploads the data
  14669. */
  14670. Quad.prototype.upload = function()
  14671. {
  14672. var gl = this.gl;
  14673. // TODO could probably be pushed into one upload!
  14674. gl.bindBuffer( gl.ARRAY_BUFFER, this.vertexBuffer );
  14675. gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices);
  14676. gl.bufferSubData(gl.ARRAY_BUFFER, 8 * 4, this.uvs);
  14677. gl.bufferSubData(gl.ARRAY_BUFFER, (8 + 8) * 4, this.colors);
  14678. };
  14679. Quad.prototype.destroy = function()
  14680. {
  14681. var gl = this.gl;
  14682. gl.deleteBuffer(this.vertexBuffer);
  14683. gl.deleteBuffer(this.indexBuffer);
  14684. };
  14685. module.exports = Quad;
  14686. },{}],65:[function(require,module,exports){
  14687. var math = require('../../../math'),
  14688. utils = require('../../../utils'),
  14689. CONST = require('../../../const'),
  14690. //StencilManager = require('../managers/StencilManager'),
  14691. StencilMaskStack = require('./StencilMaskStack');
  14692. /**
  14693. * @author Mat Groves http://matgroves.com/ @Doormat23
  14694. */
  14695. /**
  14696. * @class
  14697. * @memberof PIXI
  14698. * @param gl {WebGLRenderingContext} the current WebGL drawing context
  14699. * @param width {number} the horizontal range of the filter
  14700. * @param height {number} the vertical range of the filter
  14701. * @param scaleMode {number} See {@link PIXI.SCALE_MODES} for possible values
  14702. * @param resolution {number} the current resolution
  14703. * @param root {boolean} Whether this object is the root element or not
  14704. */
  14705. var RenderTarget = function(gl, width, height, scaleMode, resolution, root)
  14706. {
  14707. //TODO Resolution could go here ( eg low res blurs )
  14708. /**
  14709. * The current WebGL drawing context.
  14710. *
  14711. * @member {WebGLRenderingContext}
  14712. */
  14713. this.gl = gl;
  14714. // next time to create a frame buffer and texture
  14715. /**
  14716. * A frame buffer
  14717. *
  14718. * @member {WebGLFrameBuffer}
  14719. */
  14720. this.frameBuffer = null;
  14721. /**
  14722. * The texture
  14723. *
  14724. * @member {PIXI.Texture}
  14725. */
  14726. this.texture = null;
  14727. /**
  14728. * The size of the object as a rectangle
  14729. *
  14730. * @member {PIXI.Rectangle}
  14731. */
  14732. this.size = new math.Rectangle(0, 0, 1, 1);
  14733. /**
  14734. * The current resolution
  14735. *
  14736. * @member {number}
  14737. */
  14738. this.resolution = resolution || CONST.RESOLUTION;
  14739. /**
  14740. * The projection matrix
  14741. *
  14742. * @member {PIXI.Matrix}
  14743. */
  14744. this.projectionMatrix = new math.Matrix();
  14745. /**
  14746. * The object's transform
  14747. *
  14748. * @member {PIXI.Matrix}
  14749. */
  14750. this.transform = null;
  14751. /**
  14752. * The frame.
  14753. *
  14754. * @member {PIXI.Rectangle}
  14755. */
  14756. this.frame = null;
  14757. /**
  14758. * The stencil buffer stores masking data for the render target
  14759. *
  14760. * @member {WebGLRenderBuffer}
  14761. */
  14762. this.stencilBuffer = null;
  14763. /**
  14764. * The data structure for the stencil masks
  14765. *
  14766. * @member {PIXI.StencilMaskStack}
  14767. */
  14768. this.stencilMaskStack = new StencilMaskStack();
  14769. /**
  14770. * Stores filter data for the render target
  14771. *
  14772. * @member {object[]}
  14773. */
  14774. this.filterStack = [
  14775. {
  14776. renderTarget:this,
  14777. filter:[],
  14778. bounds:this.size
  14779. }
  14780. ];
  14781. /**
  14782. * The scale mode.
  14783. *
  14784. * @member {number}
  14785. * @default PIXI.SCALE_MODES.DEFAULT
  14786. * @see PIXI.SCALE_MODES
  14787. */
  14788. this.scaleMode = scaleMode || CONST.SCALE_MODES.DEFAULT;
  14789. /**
  14790. * Whether this object is the root element or not
  14791. *
  14792. * @member {boolean}
  14793. */
  14794. this.root = root;
  14795. if (!this.root)
  14796. {
  14797. // this.flipY = true;
  14798. this.frameBuffer = gl.createFramebuffer();
  14799. /*
  14800. A frame buffer needs a target to render to..
  14801. create a texture and bind it attach it to the framebuffer..
  14802. */
  14803. this.texture = gl.createTexture();
  14804. gl.bindTexture(gl.TEXTURE_2D, this.texture);
  14805. // set the scale properties of the texture..
  14806. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, scaleMode === CONST.SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST);
  14807. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, scaleMode === CONST.SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST);
  14808. // check to see if the texture is a power of two!
  14809. var isPowerOfTwo = utils.isPowerOfTwo(width, height);
  14810. //TODO for 99% of use cases if a texture is power of two we should tile the texture...
  14811. if (!isPowerOfTwo)
  14812. {
  14813. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  14814. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  14815. }
  14816. else
  14817. {
  14818. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
  14819. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
  14820. }
  14821. gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer );
  14822. gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);
  14823. }
  14824. this.resize(width, height);
  14825. };
  14826. RenderTarget.prototype.constructor = RenderTarget;
  14827. module.exports = RenderTarget;
  14828. /**
  14829. * Clears the filter texture.
  14830. *
  14831. * @param [bind=false] {boolean} Should we bind our framebuffer before clearing?
  14832. */
  14833. RenderTarget.prototype.clear = function(bind)
  14834. {
  14835. var gl = this.gl;
  14836. if(bind)
  14837. {
  14838. gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer);
  14839. }
  14840. gl.clearColor(0,0,0,0);
  14841. gl.clear(gl.COLOR_BUFFER_BIT);
  14842. };
  14843. /**
  14844. * Binds the stencil buffer.
  14845. *
  14846. */
  14847. RenderTarget.prototype.attachStencilBuffer = function()
  14848. {
  14849. if (this.stencilBuffer)
  14850. {
  14851. return;
  14852. }
  14853. /**
  14854. * The stencil buffer is used for masking in pixi
  14855. * lets create one and then add attach it to the framebuffer..
  14856. */
  14857. if (!this.root)
  14858. {
  14859. var gl = this.gl;
  14860. this.stencilBuffer = gl.createRenderbuffer();
  14861. gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencilBuffer);
  14862. gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencilBuffer);
  14863. gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.size.width * this.resolution , this.size.height * this.resolution );
  14864. }
  14865. };
  14866. /**
  14867. * Binds the buffers and initialises the viewport.
  14868. *
  14869. */
  14870. RenderTarget.prototype.activate = function()
  14871. {
  14872. //TOOD refactor usage of frame..
  14873. var gl = this.gl;
  14874. gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer);
  14875. var projectionFrame = this.frame || this.size;
  14876. // TODO add a dirty flag to this of a setter for the frame?
  14877. this.calculateProjection( projectionFrame );
  14878. if(this.transform)
  14879. {
  14880. this.projectionMatrix.append(this.transform);
  14881. }
  14882. gl.viewport(0,0, projectionFrame.width * this.resolution, projectionFrame.height * this.resolution);
  14883. };
  14884. /**
  14885. * Updates the projection matrix based on a projection frame (which is a rectangle)
  14886. *
  14887. */
  14888. RenderTarget.prototype.calculateProjection = function (projectionFrame)
  14889. {
  14890. var pm = this.projectionMatrix;
  14891. pm.identity();
  14892. if (!this.root)
  14893. {
  14894. pm.a = 1 / projectionFrame.width*2;
  14895. pm.d = 1 / projectionFrame.height*2;
  14896. pm.tx = -1 - projectionFrame.x * pm.a;
  14897. pm.ty = -1 - projectionFrame.y * pm.d;
  14898. }
  14899. else
  14900. {
  14901. pm.a = 1 / projectionFrame.width*2;
  14902. pm.d = -1 / projectionFrame.height*2;
  14903. pm.tx = -1 - projectionFrame.x * pm.a;
  14904. pm.ty = 1 - projectionFrame.y * pm.d;
  14905. }
  14906. };
  14907. /**
  14908. * Resizes the texture to the specified width and height
  14909. *
  14910. * @param width {Number} the new width of the texture
  14911. * @param height {Number} the new height of the texture
  14912. */
  14913. RenderTarget.prototype.resize = function (width, height)
  14914. {
  14915. width = width | 0;
  14916. height = height | 0;
  14917. if (this.size.width === width && this.size.height === height) {
  14918. return;
  14919. }
  14920. this.size.width = width;
  14921. this.size.height = height;
  14922. if (!this.root)
  14923. {
  14924. var gl = this.gl;
  14925. gl.bindTexture(gl.TEXTURE_2D, this.texture);
  14926. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width * this.resolution, height * this.resolution , 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
  14927. if (this.stencilBuffer )
  14928. {
  14929. // update the stencil buffer width and height
  14930. gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencilBuffer);
  14931. gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width * this.resolution, height * this.resolution );
  14932. }
  14933. }
  14934. var projectionFrame = this.frame || this.size;
  14935. this.calculateProjection( projectionFrame );
  14936. };
  14937. /**
  14938. * Destroys the render target.
  14939. *
  14940. */
  14941. RenderTarget.prototype.destroy = function ()
  14942. {
  14943. var gl = this.gl;
  14944. gl.deleteRenderbuffer( this.stencilBuffer );
  14945. gl.deleteFramebuffer( this.frameBuffer );
  14946. gl.deleteTexture( this.texture );
  14947. this.frameBuffer = null;
  14948. this.texture = null;
  14949. };
  14950. },{"../../../const":22,"../../../math":33,"../../../utils":77,"./StencilMaskStack":66}],66:[function(require,module,exports){
  14951. /**
  14952. * Generic Mask Stack data structure
  14953. * @class
  14954. * @memberof PIXI
  14955. */
  14956. function StencilMaskStack()
  14957. {
  14958. /**
  14959. * The actual stack
  14960. *
  14961. * @member {any[]}
  14962. */
  14963. this.stencilStack = [];
  14964. /**
  14965. * TODO @alvin
  14966. *
  14967. * @member {boolean}
  14968. */
  14969. this.reverse = true;
  14970. /**
  14971. * Internal count
  14972. *
  14973. * @member {number}
  14974. */
  14975. this.count = 0;
  14976. }
  14977. StencilMaskStack.prototype.constructor = StencilMaskStack;
  14978. module.exports = StencilMaskStack;
  14979. },{}],67:[function(require,module,exports){
  14980. var math = require('../math'),
  14981. Texture = require('../textures/Texture'),
  14982. Container = require('../display/Container'),
  14983. CanvasTinter = require('../renderers/canvas/utils/CanvasTinter'),
  14984. utils = require('../utils'),
  14985. CONST = require('../const'),
  14986. tempPoint = new math.Point(),
  14987. GroupD8 = math.GroupD8,
  14988. canvasRenderWorldTransform = new math.Matrix();
  14989. /**
  14990. * The Sprite object is the base for all textured objects that are rendered to the screen
  14991. *
  14992. * A sprite can be created directly from an image like this:
  14993. *
  14994. * ```js
  14995. * var sprite = new PIXI.Sprite.fromImage('assets/image.png');
  14996. * ```
  14997. *
  14998. * @class
  14999. * @extends PIXI.Container
  15000. * @memberof PIXI
  15001. * @param texture {PIXI.Texture} The texture for this sprite
  15002. */
  15003. function Sprite(texture)
  15004. {
  15005. Container.call(this);
  15006. /**
  15007. * The anchor sets the origin point of the texture.
  15008. * The default is 0,0 this means the texture's origin is the top left
  15009. * Setting the anchor to 0.5,0.5 means the texture's origin is centered
  15010. * Setting the anchor to 1,1 would mean the texture's origin point will be the bottom right corner
  15011. *
  15012. * @member {PIXI.Point}
  15013. */
  15014. this.anchor = new math.Point();
  15015. /**
  15016. * The texture that the sprite is using
  15017. *
  15018. * @member {PIXI.Texture}
  15019. * @private
  15020. */
  15021. this._texture = null;
  15022. /**
  15023. * The width of the sprite (this is initially set by the texture)
  15024. *
  15025. * @member {number}
  15026. * @private
  15027. */
  15028. this._width = 0;
  15029. /**
  15030. * The height of the sprite (this is initially set by the texture)
  15031. *
  15032. * @member {number}
  15033. * @private
  15034. */
  15035. this._height = 0;
  15036. /**
  15037. * The tint applied to the sprite. This is a hex value. A value of 0xFFFFFF will remove any tint effect.
  15038. *
  15039. * @member {number}
  15040. * @default 0xFFFFFF
  15041. */
  15042. this.tint = 0xFFFFFF;
  15043. /**
  15044. * The blend mode to be applied to the sprite. Apply a value of `PIXI.BLEND_MODES.NORMAL` to reset the blend mode.
  15045. *
  15046. * @member {number}
  15047. * @default PIXI.BLEND_MODES.NORMAL
  15048. * @see PIXI.BLEND_MODES
  15049. */
  15050. this.blendMode = CONST.BLEND_MODES.NORMAL;
  15051. /**
  15052. * The shader that will be used to render the sprite. Set to null to remove a current shader.
  15053. *
  15054. * @member {PIXI.AbstractFilter|PIXI.Shader}
  15055. */
  15056. this.shader = null;
  15057. /**
  15058. * An internal cached value of the tint.
  15059. *
  15060. * @member {number}
  15061. * @default 0xFFFFFF
  15062. */
  15063. this.cachedTint = 0xFFFFFF;
  15064. // call texture setter
  15065. this.texture = texture || Texture.EMPTY;
  15066. }
  15067. // constructor
  15068. Sprite.prototype = Object.create(Container.prototype);
  15069. Sprite.prototype.constructor = Sprite;
  15070. module.exports = Sprite;
  15071. Object.defineProperties(Sprite.prototype, {
  15072. /**
  15073. * The width of the sprite, setting this will actually modify the scale to achieve the value set
  15074. *
  15075. * @member {number}
  15076. * @memberof PIXI.Sprite#
  15077. */
  15078. width: {
  15079. get: function ()
  15080. {
  15081. return Math.abs(this.scale.x) * this.texture._frame.width;
  15082. },
  15083. set: function (value)
  15084. {
  15085. var sign = utils.sign(this.scale.x) || 1;
  15086. this.scale.x = sign * value / this.texture._frame.width;
  15087. this._width = value;
  15088. }
  15089. },
  15090. /**
  15091. * The height of the sprite, setting this will actually modify the scale to achieve the value set
  15092. *
  15093. * @member {number}
  15094. * @memberof PIXI.Sprite#
  15095. */
  15096. height: {
  15097. get: function ()
  15098. {
  15099. return Math.abs(this.scale.y) * this.texture._frame.height;
  15100. },
  15101. set: function (value)
  15102. {
  15103. var sign = utils.sign(this.scale.y) || 1;
  15104. this.scale.y = sign * value / this.texture._frame.height;
  15105. this._height = value;
  15106. }
  15107. },
  15108. /**
  15109. * The texture that the sprite is using
  15110. *
  15111. * @member {PIXI.Texture}
  15112. * @memberof PIXI.Sprite#
  15113. */
  15114. texture: {
  15115. get: function ()
  15116. {
  15117. return this._texture;
  15118. },
  15119. set: function (value)
  15120. {
  15121. if (this._texture === value)
  15122. {
  15123. return;
  15124. }
  15125. this._texture = value;
  15126. this.cachedTint = 0xFFFFFF;
  15127. if (value)
  15128. {
  15129. // wait for the texture to load
  15130. if (value.baseTexture.hasLoaded)
  15131. {
  15132. this._onTextureUpdate();
  15133. }
  15134. else
  15135. {
  15136. value.once('update', this._onTextureUpdate, this);
  15137. }
  15138. }
  15139. }
  15140. }
  15141. });
  15142. /**
  15143. * When the texture is updated, this event will fire to update the scale and frame
  15144. *
  15145. * @private
  15146. */
  15147. Sprite.prototype._onTextureUpdate = function ()
  15148. {
  15149. // so if _width is 0 then width was not set..
  15150. if (this._width)
  15151. {
  15152. this.scale.x = utils.sign(this.scale.x) * this._width / this.texture.frame.width;
  15153. }
  15154. if (this._height)
  15155. {
  15156. this.scale.y = utils.sign(this.scale.y) * this._height / this.texture.frame.height;
  15157. }
  15158. };
  15159. /**
  15160. *
  15161. * Renders the object using the WebGL renderer
  15162. *
  15163. * @param renderer {PIXI.WebGLRenderer}
  15164. * @private
  15165. */
  15166. Sprite.prototype._renderWebGL = function (renderer)
  15167. {
  15168. renderer.setObjectRenderer(renderer.plugins.sprite);
  15169. renderer.plugins.sprite.render(this);
  15170. };
  15171. /**
  15172. * Returns the bounds of the Sprite as a rectangle. The bounds calculation takes the worldTransform into account.
  15173. *
  15174. * @param matrix {PIXI.Matrix} the transformation matrix of the sprite
  15175. * @return {PIXI.Rectangle} the framing rectangle
  15176. */
  15177. Sprite.prototype.getBounds = function (matrix)
  15178. {
  15179. if(!this._currentBounds)
  15180. {
  15181. var width = this._texture._frame.width;
  15182. var height = this._texture._frame.height;
  15183. var w0 = width * (1-this.anchor.x);
  15184. var w1 = width * -this.anchor.x;
  15185. var h0 = height * (1-this.anchor.y);
  15186. var h1 = height * -this.anchor.y;
  15187. var worldTransform = matrix || this.worldTransform ;
  15188. var a = worldTransform.a;
  15189. var b = worldTransform.b;
  15190. var c = worldTransform.c;
  15191. var d = worldTransform.d;
  15192. var tx = worldTransform.tx;
  15193. var ty = worldTransform.ty;
  15194. var minX,
  15195. maxX,
  15196. minY,
  15197. maxY;
  15198. //TODO - I am SURE this can be optimised, but the below is not accurate enough..
  15199. /*
  15200. if (b === 0 && c === 0)
  15201. {
  15202. // scale may be negative!
  15203. if (a < 0)
  15204. {
  15205. a *= -1;
  15206. }
  15207. if (d < 0)
  15208. {
  15209. d *= -1;
  15210. }
  15211. // this means there is no rotation going on right? RIGHT?
  15212. // if thats the case then we can avoid checking the bound values! yay
  15213. minX = a * w1 + tx;
  15214. maxX = a * w0 + tx;
  15215. minY = d * h1 + ty;
  15216. maxY = d * h0 + ty;
  15217. }
  15218. else
  15219. {
  15220. */
  15221. var x1 = a * w1 + c * h1 + tx;
  15222. var y1 = d * h1 + b * w1 + ty;
  15223. var x2 = a * w0 + c * h1 + tx;
  15224. var y2 = d * h1 + b * w0 + ty;
  15225. var x3 = a * w0 + c * h0 + tx;
  15226. var y3 = d * h0 + b * w0 + ty;
  15227. var x4 = a * w1 + c * h0 + tx;
  15228. var y4 = d * h0 + b * w1 + ty;
  15229. minX = x1;
  15230. minX = x2 < minX ? x2 : minX;
  15231. minX = x3 < minX ? x3 : minX;
  15232. minX = x4 < minX ? x4 : minX;
  15233. minY = y1;
  15234. minY = y2 < minY ? y2 : minY;
  15235. minY = y3 < minY ? y3 : minY;
  15236. minY = y4 < minY ? y4 : minY;
  15237. maxX = x1;
  15238. maxX = x2 > maxX ? x2 : maxX;
  15239. maxX = x3 > maxX ? x3 : maxX;
  15240. maxX = x4 > maxX ? x4 : maxX;
  15241. maxY = y1;
  15242. maxY = y2 > maxY ? y2 : maxY;
  15243. maxY = y3 > maxY ? y3 : maxY;
  15244. maxY = y4 > maxY ? y4 : maxY;
  15245. //}
  15246. // check for children
  15247. if(this.children.length)
  15248. {
  15249. var childBounds = this.containerGetBounds();
  15250. w0 = childBounds.x;
  15251. w1 = childBounds.x + childBounds.width;
  15252. h0 = childBounds.y;
  15253. h1 = childBounds.y + childBounds.height;
  15254. minX = (minX < w0) ? minX : w0;
  15255. minY = (minY < h0) ? minY : h0;
  15256. maxX = (maxX > w1) ? maxX : w1;
  15257. maxY = (maxY > h1) ? maxY : h1;
  15258. }
  15259. var bounds = this._bounds;
  15260. bounds.x = minX;
  15261. bounds.width = maxX - minX;
  15262. bounds.y = minY;
  15263. bounds.height = maxY - minY;
  15264. // store a reference so that if this function gets called again in the render cycle we do not have to recalculate
  15265. this._currentBounds = bounds;
  15266. }
  15267. return this._currentBounds;
  15268. };
  15269. /**
  15270. * Gets the local bounds of the sprite object.
  15271. *
  15272. */
  15273. Sprite.prototype.getLocalBounds = function ()
  15274. {
  15275. this._bounds.x = -this._texture._frame.width * this.anchor.x;
  15276. this._bounds.y = -this._texture._frame.height * this.anchor.y;
  15277. this._bounds.width = this._texture._frame.width;
  15278. this._bounds.height = this._texture._frame.height;
  15279. return this._bounds;
  15280. };
  15281. /**
  15282. * Tests if a point is inside this sprite
  15283. *
  15284. * @param point {PIXI.Point} the point to test
  15285. * @return {boolean} the result of the test
  15286. */
  15287. Sprite.prototype.containsPoint = function( point )
  15288. {
  15289. this.worldTransform.applyInverse(point, tempPoint);
  15290. var width = this._texture._frame.width;
  15291. var height = this._texture._frame.height;
  15292. var x1 = -width * this.anchor.x;
  15293. var y1;
  15294. if ( tempPoint.x > x1 && tempPoint.x < x1 + width )
  15295. {
  15296. y1 = -height * this.anchor.y;
  15297. if ( tempPoint.y > y1 && tempPoint.y < y1 + height )
  15298. {
  15299. return true;
  15300. }
  15301. }
  15302. return false;
  15303. };
  15304. /**
  15305. * Renders the object using the Canvas renderer
  15306. *
  15307. * @param renderer {PIXI.CanvasRenderer} The renderer
  15308. * @private
  15309. */
  15310. Sprite.prototype._renderCanvas = function (renderer)
  15311. {
  15312. if (this.texture.crop.width <= 0 || this.texture.crop.height <= 0)
  15313. {
  15314. return;
  15315. }
  15316. var compositeOperation = renderer.blendModes[this.blendMode];
  15317. if (compositeOperation !== renderer.context.globalCompositeOperation)
  15318. {
  15319. renderer.context.globalCompositeOperation = compositeOperation;
  15320. }
  15321. // Ignore null sources
  15322. if (this.texture.valid)
  15323. {
  15324. var texture = this._texture,
  15325. wt = this.worldTransform,
  15326. dx,
  15327. dy,
  15328. width = texture.crop.width,
  15329. height = texture.crop.height;
  15330. renderer.context.globalAlpha = this.worldAlpha;
  15331. // If smoothingEnabled is supported and we need to change the smoothing property for this texture
  15332. var smoothingEnabled = texture.baseTexture.scaleMode === CONST.SCALE_MODES.LINEAR;
  15333. if (renderer.smoothProperty && renderer.context[renderer.smoothProperty] !== smoothingEnabled)
  15334. {
  15335. renderer.context[renderer.smoothProperty] = smoothingEnabled;
  15336. }
  15337. //inline GroupD8.isSwapWidthHeight
  15338. if ((texture.rotate & 3) === 2) {
  15339. width = texture.crop.height;
  15340. height = texture.crop.width;
  15341. }
  15342. if (texture.trim) {
  15343. dx = texture.crop.width/2 + texture.trim.x - this.anchor.x * texture.trim.width;
  15344. dy = texture.crop.height/2 + texture.trim.y - this.anchor.y * texture.trim.height;
  15345. } else {
  15346. dx = (0.5 - this.anchor.x) * texture._frame.width;
  15347. dy = (0.5 - this.anchor.y) * texture._frame.height;
  15348. }
  15349. if(texture.rotate) {
  15350. wt.copy(canvasRenderWorldTransform);
  15351. wt = canvasRenderWorldTransform;
  15352. GroupD8.matrixAppendRotationInv(wt, texture.rotate, dx, dy);
  15353. // the anchor has already been applied above, so lets set it to zero
  15354. dx = 0;
  15355. dy = 0;
  15356. }
  15357. dx -= width/2;
  15358. dy -= height/2;
  15359. // Allow for pixel rounding
  15360. if (renderer.roundPixels)
  15361. {
  15362. renderer.context.setTransform(
  15363. wt.a,
  15364. wt.b,
  15365. wt.c,
  15366. wt.d,
  15367. (wt.tx * renderer.resolution) | 0,
  15368. (wt.ty * renderer.resolution) | 0
  15369. );
  15370. dx = dx | 0;
  15371. dy = dy | 0;
  15372. }
  15373. else
  15374. {
  15375. renderer.context.setTransform(
  15376. wt.a,
  15377. wt.b,
  15378. wt.c,
  15379. wt.d,
  15380. wt.tx * renderer.resolution,
  15381. wt.ty * renderer.resolution
  15382. );
  15383. }
  15384. var resolution = texture.baseTexture.resolution;
  15385. if (this.tint !== 0xFFFFFF)
  15386. {
  15387. if (this.cachedTint !== this.tint)
  15388. {
  15389. this.cachedTint = this.tint;
  15390. // TODO clean up caching - how to clean up the caches?
  15391. this.tintedTexture = CanvasTinter.getTintedTexture(this, this.tint);
  15392. }
  15393. renderer.context.drawImage(
  15394. this.tintedTexture,
  15395. 0,
  15396. 0,
  15397. width * resolution,
  15398. height * resolution,
  15399. dx * renderer.resolution,
  15400. dy * renderer.resolution,
  15401. width * renderer.resolution,
  15402. height * renderer.resolution
  15403. );
  15404. }
  15405. else
  15406. {
  15407. renderer.context.drawImage(
  15408. texture.baseTexture.source,
  15409. texture.crop.x * resolution,
  15410. texture.crop.y * resolution,
  15411. width * resolution,
  15412. height * resolution,
  15413. dx * renderer.resolution,
  15414. dy * renderer.resolution,
  15415. width * renderer.resolution,
  15416. height * renderer.resolution
  15417. );
  15418. }
  15419. }
  15420. };
  15421. /**
  15422. * Destroys this sprite and optionally its texture
  15423. *
  15424. * @param [destroyTexture=false] {boolean} Should it destroy the current texture of the sprite as well
  15425. * @param [destroyBaseTexture=false] {boolean} Should it destroy the base texture of the sprite as well
  15426. */
  15427. Sprite.prototype.destroy = function (destroyTexture, destroyBaseTexture)
  15428. {
  15429. Container.prototype.destroy.call(this);
  15430. this.anchor = null;
  15431. if (destroyTexture)
  15432. {
  15433. this._texture.destroy(destroyBaseTexture);
  15434. }
  15435. this._texture = null;
  15436. this.shader = null;
  15437. };
  15438. // some helper functions..
  15439. /**
  15440. * Helper function that creates a sprite that will contain a texture from the TextureCache based on the frameId
  15441. * The frame ids are created when a Texture packer file has been loaded
  15442. *
  15443. * @static
  15444. * @param frameId {string} The frame Id of the texture in the cache
  15445. * @param [crossorigin=(auto)] {boolean} if you want to specify the cross-origin parameter
  15446. * @param [scaleMode=PIXI.SCALE_MODES.DEFAULT] {number} if you want to specify the scale mode, see {@link PIXI.SCALE_MODES} for possible values
  15447. * @return {PIXI.Sprite} A new Sprite using a texture from the texture cache matching the frameId
  15448. */
  15449. Sprite.fromFrame = function (frameId)
  15450. {
  15451. var texture = utils.TextureCache[frameId];
  15452. if (!texture)
  15453. {
  15454. throw new Error('The frameId "' + frameId + '" does not exist in the texture cache');
  15455. }
  15456. return new Sprite(texture);
  15457. };
  15458. /**
  15459. * Helper function that creates a sprite that will contain a texture based on an image url
  15460. * If the image is not in the texture cache it will be loaded
  15461. *
  15462. * @static
  15463. * @param imageId {string} The image url of the texture
  15464. * @return {PIXI.Sprite} A new Sprite using a texture from the texture cache matching the image id
  15465. */
  15466. Sprite.fromImage = function (imageId, crossorigin, scaleMode)
  15467. {
  15468. return new Sprite(Texture.fromImage(imageId, crossorigin, scaleMode));
  15469. };
  15470. },{"../const":22,"../display/Container":23,"../math":33,"../renderers/canvas/utils/CanvasTinter":48,"../textures/Texture":72,"../utils":77}],68:[function(require,module,exports){
  15471. var ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'),
  15472. WebGLRenderer = require('../../renderers/webgl/WebGLRenderer'),
  15473. CONST = require('../../const');
  15474. /**
  15475. * @author Mat Groves
  15476. *
  15477. * Big thanks to the very clever Matt DesLauriers <mattdesl> https://github.com/mattdesl/
  15478. * for creating the original pixi version!
  15479. * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer
  15480. *
  15481. * Heavily inspired by LibGDX's SpriteRenderer:
  15482. * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/SpriteRenderer.java
  15483. */
  15484. /**
  15485. * Renderer dedicated to drawing and batching sprites.
  15486. *
  15487. * @class
  15488. * @private
  15489. * @memberof PIXI
  15490. * @extends PIXI.ObjectRenderer
  15491. * @param renderer {PIXI.WebGLRenderer} The renderer this sprite batch works for.
  15492. */
  15493. function SpriteRenderer(renderer)
  15494. {
  15495. ObjectRenderer.call(this, renderer);
  15496. /**
  15497. * Number of values sent in the vertex buffer.
  15498. * positionX, positionY, colorR, colorG, colorB = 5
  15499. *
  15500. * @member {number}
  15501. */
  15502. this.vertSize = 5;
  15503. /**
  15504. * The size of the vertex information in bytes.
  15505. *
  15506. * @member {number}
  15507. */
  15508. this.vertByteSize = this.vertSize * 4;
  15509. /**
  15510. * The number of images in the SpriteBatch before it flushes.
  15511. *
  15512. * @member {number}
  15513. */
  15514. this.size = CONST.SPRITE_BATCH_SIZE; // 2000 is a nice balance between mobile / desktop
  15515. // the total number of bytes in our batch
  15516. var numVerts = (this.size * 4) * this.vertByteSize;
  15517. // the total number of indices in our batch, there are 6 points per quad.
  15518. var numIndices = this.size * 6;
  15519. /**
  15520. * Holds the vertex data that will be sent to the vertex shader.
  15521. *
  15522. * @member {ArrayBuffer}
  15523. */
  15524. this.vertices = new ArrayBuffer(numVerts);
  15525. /**
  15526. * View on the vertices as a Float32Array for positions
  15527. *
  15528. * @member {Float32Array}
  15529. */
  15530. this.positions = new Float32Array(this.vertices);
  15531. /**
  15532. * View on the vertices as a Uint32Array for colors
  15533. *
  15534. * @member {Uint32Array}
  15535. */
  15536. this.colors = new Uint32Array(this.vertices);
  15537. /**
  15538. * Holds the indices of the geometry (quads) to draw
  15539. *
  15540. * @member {Uint16Array}
  15541. */
  15542. this.indices = new Uint16Array(numIndices);
  15543. // fill the indices with the quads to draw
  15544. for (var i=0, j=0; i < numIndices; i += 6, j += 4)
  15545. {
  15546. this.indices[i + 0] = j + 0;
  15547. this.indices[i + 1] = j + 1;
  15548. this.indices[i + 2] = j + 2;
  15549. this.indices[i + 3] = j + 0;
  15550. this.indices[i + 4] = j + 2;
  15551. this.indices[i + 5] = j + 3;
  15552. }
  15553. /**
  15554. * The current size of the batch, each render() call adds to this number.
  15555. *
  15556. * @member {number}
  15557. */
  15558. this.currentBatchSize = 0;
  15559. /**
  15560. * The current sprites in the batch.
  15561. *
  15562. * @member {PIXI.Sprite[]}
  15563. */
  15564. this.sprites = [];
  15565. /**
  15566. * The default shader that is used if a sprite doesn't have a more specific one.
  15567. *
  15568. * @member {PIXI.Shader}
  15569. */
  15570. this.shader = null;
  15571. }
  15572. SpriteRenderer.prototype = Object.create(ObjectRenderer.prototype);
  15573. SpriteRenderer.prototype.constructor = SpriteRenderer;
  15574. module.exports = SpriteRenderer;
  15575. WebGLRenderer.registerPlugin('sprite', SpriteRenderer);
  15576. /**
  15577. * Sets up the renderer context and necessary buffers.
  15578. *
  15579. * @private
  15580. * @param gl {WebGLRenderingContext} the current WebGL drawing context
  15581. */
  15582. SpriteRenderer.prototype.onContextChange = function ()
  15583. {
  15584. var gl = this.renderer.gl;
  15585. // setup default shader
  15586. this.shader = this.renderer.shaderManager.defaultShader;
  15587. // create a couple of buffers
  15588. this.vertexBuffer = gl.createBuffer();
  15589. this.indexBuffer = gl.createBuffer();
  15590. //upload the index data
  15591. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
  15592. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);
  15593. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
  15594. gl.bufferData(gl.ARRAY_BUFFER, this.vertices, gl.DYNAMIC_DRAW);
  15595. this.currentBlendMode = 99999;
  15596. };
  15597. /**
  15598. * Renders the sprite object.
  15599. *
  15600. * @param sprite {PIXI.Sprite} the sprite to render when using this spritebatch
  15601. */
  15602. SpriteRenderer.prototype.render = function (sprite)
  15603. {
  15604. var texture = sprite._texture;
  15605. //TODO set blend modes..
  15606. // check texture..
  15607. if (this.currentBatchSize >= this.size)
  15608. {
  15609. this.flush();
  15610. }
  15611. // get the uvs for the texture
  15612. var uvs = texture._uvs;
  15613. // if the uvs have not updated then no point rendering just yet!
  15614. if (!uvs)
  15615. {
  15616. return;
  15617. }
  15618. // TODO trim??
  15619. var aX = sprite.anchor.x;
  15620. var aY = sprite.anchor.y;
  15621. var w0, w1, h0, h1;
  15622. if (texture.trim && sprite.tileScale === undefined)
  15623. {
  15624. // if the sprite is trimmed and is not a tilingsprite then we need to add the extra space before transforming the sprite coords..
  15625. var trim = texture.trim;
  15626. w1 = trim.x - aX * trim.width;
  15627. w0 = w1 + texture.crop.width;
  15628. h1 = trim.y - aY * trim.height;
  15629. h0 = h1 + texture.crop.height;
  15630. }
  15631. else
  15632. {
  15633. w0 = (texture._frame.width ) * (1-aX);
  15634. w1 = (texture._frame.width ) * -aX;
  15635. h0 = texture._frame.height * (1-aY);
  15636. h1 = texture._frame.height * -aY;
  15637. }
  15638. var index = this.currentBatchSize * this.vertByteSize;
  15639. var worldTransform = sprite.worldTransform;
  15640. var a = worldTransform.a;
  15641. var b = worldTransform.b;
  15642. var c = worldTransform.c;
  15643. var d = worldTransform.d;
  15644. var tx = worldTransform.tx;
  15645. var ty = worldTransform.ty;
  15646. var colors = this.colors;
  15647. var positions = this.positions;
  15648. if (this.renderer.roundPixels)
  15649. {
  15650. var resolution = this.renderer.resolution;
  15651. // xy
  15652. positions[index] = (((a * w1 + c * h1 + tx) * resolution) | 0) / resolution;
  15653. positions[index+1] = (((d * h1 + b * w1 + ty) * resolution) | 0) / resolution;
  15654. // xy
  15655. positions[index+5] = (((a * w0 + c * h1 + tx) * resolution) | 0) / resolution;
  15656. positions[index+6] = (((d * h1 + b * w0 + ty) * resolution) | 0) / resolution;
  15657. // xy
  15658. positions[index+10] = (((a * w0 + c * h0 + tx) * resolution) | 0) / resolution;
  15659. positions[index+11] = (((d * h0 + b * w0 + ty) * resolution) | 0) / resolution;
  15660. // xy
  15661. positions[index+15] = (((a * w1 + c * h0 + tx) * resolution) | 0) / resolution;
  15662. positions[index+16] = (((d * h0 + b * w1 + ty) * resolution) | 0) / resolution;
  15663. }
  15664. else
  15665. {
  15666. // xy
  15667. positions[index] = a * w1 + c * h1 + tx;
  15668. positions[index+1] = d * h1 + b * w1 + ty;
  15669. // xy
  15670. positions[index+5] = a * w0 + c * h1 + tx;
  15671. positions[index+6] = d * h1 + b * w0 + ty;
  15672. // xy
  15673. positions[index+10] = a * w0 + c * h0 + tx;
  15674. positions[index+11] = d * h0 + b * w0 + ty;
  15675. // xy
  15676. positions[index+15] = a * w1 + c * h0 + tx;
  15677. positions[index+16] = d * h0 + b * w1 + ty;
  15678. }
  15679. // uv
  15680. positions[index+2] = uvs.x0;
  15681. positions[index+3] = uvs.y0;
  15682. // uv
  15683. positions[index+7] = uvs.x1;
  15684. positions[index+8] = uvs.y1;
  15685. // uv
  15686. positions[index+12] = uvs.x2;
  15687. positions[index+13] = uvs.y2;
  15688. // uv
  15689. positions[index+17] = uvs.x3;
  15690. positions[index+18] = uvs.y3;
  15691. // color and alpha
  15692. var tint = sprite.tint;
  15693. colors[index+4] = colors[index+9] = colors[index+14] = colors[index+19] = (tint >> 16) + (tint & 0xff00) + ((tint & 0xff) << 16) + (sprite.worldAlpha * 255 << 24);
  15694. // increment the batchsize
  15695. this.sprites[this.currentBatchSize++] = sprite;
  15696. };
  15697. /**
  15698. * Renders the content and empties the current batch.
  15699. *
  15700. */
  15701. SpriteRenderer.prototype.flush = function ()
  15702. {
  15703. // If the batch is length 0 then return as there is nothing to draw
  15704. if (this.currentBatchSize === 0)
  15705. {
  15706. return;
  15707. }
  15708. var gl = this.renderer.gl;
  15709. var shader;
  15710. // upload the verts to the buffer
  15711. if (this.currentBatchSize > ( this.size * 0.5 ) )
  15712. {
  15713. gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices);
  15714. }
  15715. else
  15716. {
  15717. var view = this.positions.subarray(0, this.currentBatchSize * this.vertByteSize);
  15718. gl.bufferSubData(gl.ARRAY_BUFFER, 0, view);
  15719. }
  15720. var nextTexture, nextBlendMode, nextShader;
  15721. var batchSize = 0;
  15722. var start = 0;
  15723. var currentBaseTexture = null;
  15724. var currentBlendMode = this.renderer.blendModeManager.currentBlendMode;
  15725. var currentShader = null;
  15726. var blendSwap = false;
  15727. var shaderSwap = false;
  15728. var sprite;
  15729. for (var i = 0, j = this.currentBatchSize; i < j; i++)
  15730. {
  15731. sprite = this.sprites[i];
  15732. nextTexture = sprite._texture.baseTexture;
  15733. nextBlendMode = sprite.blendMode;
  15734. nextShader = sprite.shader || this.shader;
  15735. blendSwap = currentBlendMode !== nextBlendMode;
  15736. shaderSwap = currentShader !== nextShader; // should I use uidS???
  15737. if (currentBaseTexture !== nextTexture || blendSwap || shaderSwap)
  15738. {
  15739. this.renderBatch(currentBaseTexture, batchSize, start);
  15740. start = i;
  15741. batchSize = 0;
  15742. currentBaseTexture = nextTexture;
  15743. if (blendSwap)
  15744. {
  15745. currentBlendMode = nextBlendMode;
  15746. this.renderer.blendModeManager.setBlendMode( currentBlendMode );
  15747. }
  15748. if (shaderSwap)
  15749. {
  15750. currentShader = nextShader;
  15751. shader = currentShader.shaders ? currentShader.shaders[gl.id] : currentShader;
  15752. if (!shader)
  15753. {
  15754. shader = currentShader.getShader(this.renderer);
  15755. }
  15756. // set shader function???
  15757. this.renderer.shaderManager.setShader(shader);
  15758. //TODO - i KNOW this can be optimised! Once v3 is stable il look at this next...
  15759. shader.uniforms.projectionMatrix.value = this.renderer.currentRenderTarget.projectionMatrix.toArray(true);
  15760. //Make this a little more dynamic / intelligent!
  15761. shader.syncUniforms();
  15762. //TODO investigate some kind of texture state managment??
  15763. // need to make sure this texture is the active one for all the batch swaps..
  15764. gl.activeTexture(gl.TEXTURE0);
  15765. // both thease only need to be set if they are changing..
  15766. // set the projection
  15767. //gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, this.renderer.currentRenderTarget.projectionMatrix.toArray(true));
  15768. }
  15769. }
  15770. batchSize++;
  15771. }
  15772. this.renderBatch(currentBaseTexture, batchSize, start);
  15773. // then reset the batch!
  15774. this.currentBatchSize = 0;
  15775. };
  15776. /**
  15777. * Draws the currently batches sprites.
  15778. *
  15779. * @private
  15780. * @param texture {PIXI.Texture}
  15781. * @param size {number}
  15782. * @param startIndex {number}
  15783. */
  15784. SpriteRenderer.prototype.renderBatch = function (texture, size, startIndex)
  15785. {
  15786. if (size === 0)
  15787. {
  15788. return;
  15789. }
  15790. var gl = this.renderer.gl;
  15791. if (!texture._glTextures[gl.id])
  15792. {
  15793. this.renderer.updateTexture(texture);
  15794. }
  15795. else
  15796. {
  15797. // bind the current texture
  15798. gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]);
  15799. }
  15800. // now draw those suckas!
  15801. gl.drawElements(gl.TRIANGLES, size * 6, gl.UNSIGNED_SHORT, startIndex * 6 * 2);
  15802. // increment the draw count
  15803. this.renderer.drawCount++;
  15804. };
  15805. /**
  15806. * Starts a new sprite batch.
  15807. *
  15808. */
  15809. SpriteRenderer.prototype.start = function ()
  15810. {
  15811. var gl = this.renderer.gl;
  15812. // bind the main texture
  15813. // bind the buffers
  15814. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
  15815. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
  15816. // this is the same for each shader?
  15817. var stride = this.vertByteSize;
  15818. gl.vertexAttribPointer(this.shader.attributes.aVertexPosition, 2, gl.FLOAT, false, stride, 0);
  15819. gl.vertexAttribPointer(this.shader.attributes.aTextureCoord, 2, gl.FLOAT, false, stride, 2 * 4);
  15820. // color attributes will be interpreted as unsigned bytes and normalized
  15821. gl.vertexAttribPointer(this.shader.attributes.aColor, 4, gl.UNSIGNED_BYTE, true, stride, 4 * 4);
  15822. };
  15823. /**
  15824. * Destroys the SpriteBatch.
  15825. *
  15826. */
  15827. SpriteRenderer.prototype.destroy = function ()
  15828. {
  15829. this.renderer.gl.deleteBuffer(this.vertexBuffer);
  15830. this.renderer.gl.deleteBuffer(this.indexBuffer);
  15831. ObjectRenderer.prototype.destroy.call(this);
  15832. this.shader.destroy();
  15833. this.renderer = null;
  15834. this.vertices = null;
  15835. this.positions = null;
  15836. this.colors = null;
  15837. this.indices = null;
  15838. this.vertexBuffer = null;
  15839. this.indexBuffer = null;
  15840. this.sprites = null;
  15841. this.shader = null;
  15842. };
  15843. },{"../../const":22,"../../renderers/webgl/WebGLRenderer":49,"../../renderers/webgl/utils/ObjectRenderer":63}],69:[function(require,module,exports){
  15844. var Sprite = require('../sprites/Sprite'),
  15845. Texture = require('../textures/Texture'),
  15846. math = require('../math'),
  15847. utils = require('../utils'),
  15848. CONST = require('../const');
  15849. /**
  15850. * A Text Object will create a line or multiple lines of text. To split a line you can use '\n' in your text string,
  15851. * or add a wordWrap property set to true and and wordWrapWidth property with a value in the style object.
  15852. *
  15853. * A Text can be created directly from a string and a style object
  15854. *
  15855. * ```js
  15856. * var text = new PIXI.Text('This is a pixi text',{font : '24px Arial', fill : 0xff1010, align : 'center'});
  15857. * ```
  15858. *
  15859. * @class
  15860. * @extends PIXI.Sprite
  15861. * @memberof PIXI
  15862. * @param text {string} The copy that you would like the text to display
  15863. * @param [style] {object} The style parameters
  15864. * @param [style.font] {string} default 'bold 20px Arial' The style and size of the font
  15865. * @param [style.fill='black'] {String|Number} A canvas fillstyle that will be used on the text e.g 'red', '#00FF00'
  15866. * @param [style.align='left'] {string} Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text
  15867. * @param [style.stroke] {String|Number} A canvas fillstyle that will be used on the text stroke e.g 'blue', '#FCFF00'
  15868. * @param [style.strokeThickness=0] {number} A number that represents the thickness of the stroke. Default is 0 (no stroke)
  15869. * @param [style.wordWrap=false] {boolean} Indicates if word wrap should be used
  15870. * @param [style.wordWrapWidth=100] {number} The width at which text will wrap, it needs wordWrap to be set to true
  15871. * @param [style.letterSpacing=0] {number} The amount of spacing between letters, default is 0
  15872. * @param [style.breakWords=false] {boolean} Indicates if lines can be wrapped within words, it needs wordWrap to be set to true
  15873. * @param [style.lineHeight] {number} The line height, a number that represents the vertical space that a letter uses
  15874. * @param [style.dropShadow=false] {boolean} Set a drop shadow for the text
  15875. * @param [style.dropShadowColor='#000000'] {string} A fill style to be used on the dropshadow e.g 'red', '#00FF00'
  15876. * @param [style.dropShadowAngle=Math.PI/4] {number} Set a angle of the drop shadow
  15877. * @param [style.dropShadowDistance=5] {number} Set a distance of the drop shadow
  15878. * @param [style.dropShadowBlur=0] {number} Set a shadow blur radius
  15879. * @param [style.padding=0] {number} Occasionally some fonts are cropped on top or bottom. Adding some padding will
  15880. * prevent this from happening by adding padding to the top and bottom of text height.
  15881. * @param [style.textBaseline='alphabetic'] {string} The baseline of the text that is rendered.
  15882. * @param [style.lineJoin='miter'] {string} The lineJoin property sets the type of corner created, it can resolve
  15883. * spiked text issues. Default is 'miter' (creates a sharp corner).
  15884. * @param [style.miterLimit=10] {number} The miter limit to use when using the 'miter' lineJoin mode. This can reduce
  15885. * or increase the spikiness of rendered text.
  15886. */
  15887. function Text(text, style, resolution)
  15888. {
  15889. /**
  15890. * The canvas element that everything is drawn to
  15891. *
  15892. * @member {HTMLCanvasElement}
  15893. */
  15894. this.canvas = document.createElement('canvas');
  15895. /**
  15896. * The canvas 2d context that everything is drawn with
  15897. * @member {HTMLCanvasElement}
  15898. */
  15899. this.context = this.canvas.getContext('2d');
  15900. /**
  15901. * The resolution of the canvas.
  15902. * @member {number}
  15903. */
  15904. this.resolution = resolution || CONST.RESOLUTION;
  15905. /**
  15906. * Private tracker for the current text.
  15907. *
  15908. * @member {string}
  15909. * @private
  15910. */
  15911. this._text = null;
  15912. /**
  15913. * Private tracker for the current style.
  15914. *
  15915. * @member {object}
  15916. * @private
  15917. */
  15918. this._style = null;
  15919. var texture = Texture.fromCanvas(this.canvas);
  15920. texture.trim = new math.Rectangle();
  15921. Sprite.call(this, texture);
  15922. this.text = text;
  15923. this.style = style;
  15924. }
  15925. // constructor
  15926. Text.prototype = Object.create(Sprite.prototype);
  15927. Text.prototype.constructor = Text;
  15928. module.exports = Text;
  15929. Text.fontPropertiesCache = {};
  15930. Text.fontPropertiesCanvas = document.createElement('canvas');
  15931. Text.fontPropertiesContext = Text.fontPropertiesCanvas.getContext('2d');
  15932. Object.defineProperties(Text.prototype, {
  15933. /**
  15934. * The width of the Text, setting this will actually modify the scale to achieve the value set
  15935. *
  15936. * @member {number}
  15937. * @memberof PIXI.Text#
  15938. */
  15939. width: {
  15940. get: function ()
  15941. {
  15942. if (this.dirty)
  15943. {
  15944. this.updateText();
  15945. }
  15946. return this.scale.x * this._texture._frame.width;
  15947. },
  15948. set: function (value)
  15949. {
  15950. this.scale.x = value / this._texture._frame.width;
  15951. this._width = value;
  15952. }
  15953. },
  15954. /**
  15955. * The height of the Text, setting this will actually modify the scale to achieve the value set
  15956. *
  15957. * @member {number}
  15958. * @memberof PIXI.Text#
  15959. */
  15960. height: {
  15961. get: function ()
  15962. {
  15963. if (this.dirty)
  15964. {
  15965. this.updateText();
  15966. }
  15967. return this.scale.y * this._texture._frame.height;
  15968. },
  15969. set: function (value)
  15970. {
  15971. this.scale.y = value / this._texture._frame.height;
  15972. this._height = value;
  15973. }
  15974. },
  15975. /**
  15976. * Set the style of the text
  15977. *
  15978. * @param [style] {object} The style parameters
  15979. * @param [style.font='bold 20pt Arial'] {string} The style and size of the font
  15980. * @param [style.fill='black'] {string|number} A canvas fillstyle that will be used on the text eg 'red', '#00FF00'
  15981. * @param [style.align='left'] {string} Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text
  15982. * @param [style.stroke='black'] {string|number} A canvas fillstyle that will be used on the text stroke eg 'blue', '#FCFF00'
  15983. * @param [style.strokeThickness=0] {number} A number that represents the thickness of the stroke. Default is 0 (no stroke)
  15984. * @param [style.wordWrap=false] {boolean} Indicates if word wrap should be used
  15985. * @param [style.wordWrapWidth=100] {number} The width at which text will wrap
  15986. * @param [style.lineHeight] {number} The line height, a number that represents the vertical space that a letter uses
  15987. * @param [style.dropShadow=false] {boolean} Set a drop shadow for the text
  15988. * @param [style.dropShadowColor='#000000'] {string|number} A fill style to be used on the dropshadow e.g 'red', '#00FF00'
  15989. * @param [style.dropShadowAngle=Math.PI/6] {number} Set a angle of the drop shadow
  15990. * @param [style.dropShadowDistance=5] {number} Set a distance of the drop shadow
  15991. * @param [style.dropShadowBlur=0] {number} Set a shadow blur radius
  15992. * @param [style.padding=0] {number} Occasionally some fonts are cropped on top or bottom. Adding some padding will
  15993. * prevent this from happening by adding padding to the top and bottom of text height.
  15994. * @param [style.textBaseline='alphabetic'] {string} The baseline of the text that is rendered.
  15995. * @param [style.lineJoin='miter'] {string} The lineJoin property sets the type of corner created, it can resolve
  15996. * spiked text issues. Default is 'miter' (creates a sharp corner).
  15997. * @param [style.miterLimit=10] {number} The miter limit to use when using the 'miter' lineJoin mode. This can reduce
  15998. * or increase the spikiness of rendered text.
  15999. * @memberof PIXI.Text#
  16000. */
  16001. style: {
  16002. get: function ()
  16003. {
  16004. return this._style;
  16005. },
  16006. set: function (style)
  16007. {
  16008. style = style || {};
  16009. if (typeof style.fill === 'number') {
  16010. style.fill = utils.hex2string(style.fill);
  16011. }
  16012. if (typeof style.stroke === 'number') {
  16013. style.stroke = utils.hex2string(style.stroke);
  16014. }
  16015. if (typeof style.dropShadowColor === 'number') {
  16016. style.dropShadowColor = utils.hex2string(style.dropShadowColor);
  16017. }
  16018. style.font = style.font || 'bold 20pt Arial';
  16019. style.fill = style.fill || 'black';
  16020. style.align = style.align || 'left';
  16021. style.stroke = style.stroke || 'black'; //provide a default, see: https://github.com/pixijs/pixi.js/issues/136
  16022. style.strokeThickness = style.strokeThickness || 0;
  16023. style.wordWrap = style.wordWrap || false;
  16024. style.wordWrapWidth = style.wordWrapWidth || 100;
  16025. style.breakWords = style.breakWords || false;
  16026. style.letterSpacing = style.letterSpacing || 0;
  16027. style.dropShadow = style.dropShadow || false;
  16028. style.dropShadowColor = style.dropShadowColor || '#000000';
  16029. style.dropShadowAngle = style.dropShadowAngle !== undefined ? style.dropShadowAngle : Math.PI / 6;
  16030. style.dropShadowDistance = style.dropShadowDistance !== undefined ? style.dropShadowDistance : 5;
  16031. style.dropShadowBlur = style.dropShadowBlur !== undefined ? style.dropShadowBlur : 0; //shadowBlur is '0' by default according to HTML
  16032. style.padding = style.padding || 0;
  16033. style.textBaseline = style.textBaseline || 'alphabetic';
  16034. style.lineJoin = style.lineJoin || 'miter';
  16035. style.miterLimit = style.miterLimit || 10;
  16036. this._style = style;
  16037. this.dirty = true;
  16038. }
  16039. },
  16040. /**
  16041. * Set the copy for the text object. To split a line you can use '\n'.
  16042. *
  16043. * @param text {string} The copy that you would like the text to display
  16044. * @memberof PIXI.Text#
  16045. */
  16046. text: {
  16047. get: function()
  16048. {
  16049. return this._text;
  16050. },
  16051. set: function (text){
  16052. text = text.toString() || ' ';
  16053. if (this._text === text)
  16054. {
  16055. return;
  16056. }
  16057. this._text = text;
  16058. this.dirty = true;
  16059. }
  16060. }
  16061. });
  16062. /**
  16063. * Renders text and updates it when needed
  16064. *
  16065. * @private
  16066. */
  16067. Text.prototype.updateText = function ()
  16068. {
  16069. var style = this._style;
  16070. this.context.font = style.font;
  16071. // word wrap
  16072. // preserve original text
  16073. var outputText = style.wordWrap ? this.wordWrap(this._text) : this._text;
  16074. // split text into lines
  16075. var lines = outputText.split(/(?:\r\n|\r|\n)/);
  16076. // calculate text width
  16077. var lineWidths = new Array(lines.length);
  16078. var maxLineWidth = 0;
  16079. var fontProperties = this.determineFontProperties(style.font);
  16080. for (var i = 0; i < lines.length; i++)
  16081. {
  16082. var lineWidth = this.context.measureText(lines[i]).width + ((lines[i].length - 1) * style.letterSpacing);
  16083. lineWidths[i] = lineWidth;
  16084. maxLineWidth = Math.max(maxLineWidth, lineWidth);
  16085. }
  16086. var width = maxLineWidth + style.strokeThickness;
  16087. if (style.dropShadow)
  16088. {
  16089. width += style.dropShadowDistance;
  16090. }
  16091. this.canvas.width = Math.ceil( ( width + this.context.lineWidth ) * this.resolution );
  16092. // calculate text height
  16093. var lineHeight = this.style.lineHeight || fontProperties.fontSize + style.strokeThickness;
  16094. var height = lineHeight * lines.length;
  16095. if (style.dropShadow)
  16096. {
  16097. height += style.dropShadowDistance;
  16098. }
  16099. this.canvas.height = Math.ceil( ( height + this._style.padding * 2 ) * this.resolution );
  16100. this.context.scale( this.resolution, this.resolution);
  16101. if (navigator.isCocoonJS)
  16102. {
  16103. this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
  16104. }
  16105. //this.context.fillStyle="#FF0000";
  16106. //this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
  16107. this.context.font = style.font;
  16108. this.context.strokeStyle = style.stroke;
  16109. this.context.lineWidth = style.strokeThickness;
  16110. this.context.textBaseline = style.textBaseline;
  16111. this.context.lineJoin = style.lineJoin;
  16112. this.context.miterLimit = style.miterLimit;
  16113. var linePositionX;
  16114. var linePositionY;
  16115. if (style.dropShadow)
  16116. {
  16117. if (style.dropShadowBlur > 0) {
  16118. this.context.shadowColor = style.dropShadowColor;
  16119. this.context.shadowBlur = style.dropShadowBlur;
  16120. } else {
  16121. this.context.fillStyle = style.dropShadowColor;
  16122. }
  16123. var xShadowOffset = Math.cos(style.dropShadowAngle) * style.dropShadowDistance;
  16124. var yShadowOffset = Math.sin(style.dropShadowAngle) * style.dropShadowDistance;
  16125. for (i = 0; i < lines.length; i++)
  16126. {
  16127. linePositionX = style.strokeThickness / 2;
  16128. linePositionY = (style.strokeThickness / 2 + i * lineHeight) + fontProperties.ascent;
  16129. if (style.align === 'right')
  16130. {
  16131. linePositionX += maxLineWidth - lineWidths[i];
  16132. }
  16133. else if (style.align === 'center')
  16134. {
  16135. linePositionX += (maxLineWidth - lineWidths[i]) / 2;
  16136. }
  16137. if (style.fill)
  16138. {
  16139. this.drawLetterSpacing(lines[i], linePositionX + xShadowOffset, linePositionY + yShadowOffset + style.padding);
  16140. }
  16141. }
  16142. }
  16143. //set canvas text styles
  16144. this.context.fillStyle = style.fill;
  16145. //draw lines line by line
  16146. for (i = 0; i < lines.length; i++)
  16147. {
  16148. linePositionX = style.strokeThickness / 2;
  16149. linePositionY = (style.strokeThickness / 2 + i * lineHeight) + fontProperties.ascent;
  16150. if (style.align === 'right')
  16151. {
  16152. linePositionX += maxLineWidth - lineWidths[i];
  16153. }
  16154. else if (style.align === 'center')
  16155. {
  16156. linePositionX += (maxLineWidth - lineWidths[i]) / 2;
  16157. }
  16158. if (style.stroke && style.strokeThickness)
  16159. {
  16160. this.drawLetterSpacing(lines[i], linePositionX, linePositionY + style.padding, true);
  16161. }
  16162. if (style.fill)
  16163. {
  16164. this.drawLetterSpacing(lines[i], linePositionX, linePositionY + style.padding);
  16165. }
  16166. }
  16167. this.updateTexture();
  16168. };
  16169. /**
  16170. * Render the text with letter-spacing.
  16171. *
  16172. * @private
  16173. */
  16174. Text.prototype.drawLetterSpacing = function(text, x, y, isStroke)
  16175. {
  16176. var style = this._style;
  16177. // letterSpacing of 0 means normal
  16178. var letterSpacing = style.letterSpacing;
  16179. if (letterSpacing === 0)
  16180. {
  16181. if (isStroke)
  16182. {
  16183. this.context.strokeText(text, x, y);
  16184. }
  16185. else
  16186. {
  16187. this.context.fillText(text, x, y);
  16188. }
  16189. return;
  16190. }
  16191. var characters = String.prototype.split.call(text, ''),
  16192. index = 0,
  16193. current,
  16194. currentPosition = x;
  16195. while (index < text.length)
  16196. {
  16197. current = characters[index++];
  16198. if (isStroke)
  16199. {
  16200. this.context.strokeText(current, currentPosition, y);
  16201. }
  16202. else
  16203. {
  16204. this.context.fillText(current, currentPosition, y);
  16205. }
  16206. currentPosition += this.context.measureText(current).width + letterSpacing;
  16207. }
  16208. };
  16209. /**
  16210. * Updates texture size based on canvas size
  16211. *
  16212. * @private
  16213. */
  16214. Text.prototype.updateTexture = function ()
  16215. {
  16216. var texture = this._texture;
  16217. var style = this._style;
  16218. texture.baseTexture.hasLoaded = true;
  16219. texture.baseTexture.resolution = this.resolution;
  16220. texture.baseTexture.width = this.canvas.width / this.resolution;
  16221. texture.baseTexture.height = this.canvas.height / this.resolution;
  16222. texture.crop.width = texture._frame.width = this.canvas.width / this.resolution;
  16223. texture.crop.height = texture._frame.height = this.canvas.height / this.resolution;
  16224. texture.trim.x = 0;
  16225. texture.trim.y = -style.padding;
  16226. texture.trim.width = texture._frame.width;
  16227. texture.trim.height = texture._frame.height - style.padding*2;
  16228. this._width = this.canvas.width / this.resolution;
  16229. this._height = this.canvas.height / this.resolution;
  16230. texture.baseTexture.emit('update', texture.baseTexture);
  16231. this.dirty = false;
  16232. };
  16233. /**
  16234. * Renders the object using the WebGL renderer
  16235. *
  16236. * @param renderer {PIXI.WebGLRenderer}
  16237. */
  16238. Text.prototype.renderWebGL = function (renderer)
  16239. {
  16240. if (this.dirty)
  16241. {
  16242. //this.resolution = 1//renderer.resolution;
  16243. this.updateText();
  16244. }
  16245. Sprite.prototype.renderWebGL.call(this, renderer);
  16246. };
  16247. /**
  16248. * Renders the object using the Canvas renderer
  16249. *
  16250. * @param renderer {PIXI.CanvasRenderer}
  16251. * @private
  16252. */
  16253. Text.prototype._renderCanvas = function (renderer)
  16254. {
  16255. if (this.dirty)
  16256. {
  16257. // this.resolution = 1//renderer.resolution;
  16258. this.updateText();
  16259. }
  16260. Sprite.prototype._renderCanvas.call(this, renderer);
  16261. };
  16262. /**
  16263. * Calculates the ascent, descent and fontSize of a given fontStyle
  16264. *
  16265. * @param fontStyle {object}
  16266. * @private
  16267. */
  16268. Text.prototype.determineFontProperties = function (fontStyle)
  16269. {
  16270. var properties = Text.fontPropertiesCache[fontStyle];
  16271. if (!properties)
  16272. {
  16273. properties = {};
  16274. var canvas = Text.fontPropertiesCanvas;
  16275. var context = Text.fontPropertiesContext;
  16276. context.font = fontStyle;
  16277. var width = Math.ceil(context.measureText('|MÉq').width);
  16278. var baseline = Math.ceil(context.measureText('M').width);
  16279. var height = 2 * baseline;
  16280. baseline = baseline * 1.4 | 0;
  16281. canvas.width = width;
  16282. canvas.height = height;
  16283. context.fillStyle = '#f00';
  16284. context.fillRect(0, 0, width, height);
  16285. context.font = fontStyle;
  16286. context.textBaseline = 'alphabetic';
  16287. context.fillStyle = '#000';
  16288. context.fillText('|MÉq', 0, baseline);
  16289. var imagedata = context.getImageData(0, 0, width, height).data;
  16290. var pixels = imagedata.length;
  16291. var line = width * 4;
  16292. var i, j;
  16293. var idx = 0;
  16294. var stop = false;
  16295. // ascent. scan from top to bottom until we find a non red pixel
  16296. for (i = 0; i < baseline; i++)
  16297. {
  16298. for (j = 0; j < line; j += 4)
  16299. {
  16300. if (imagedata[idx + j] !== 255)
  16301. {
  16302. stop = true;
  16303. break;
  16304. }
  16305. }
  16306. if (!stop)
  16307. {
  16308. idx += line;
  16309. }
  16310. else
  16311. {
  16312. break;
  16313. }
  16314. }
  16315. properties.ascent = baseline - i;
  16316. idx = pixels - line;
  16317. stop = false;
  16318. // descent. scan from bottom to top until we find a non red pixel
  16319. for (i = height; i > baseline; i--)
  16320. {
  16321. for (j = 0; j < line; j += 4)
  16322. {
  16323. if (imagedata[idx + j] !== 255)
  16324. {
  16325. stop = true;
  16326. break;
  16327. }
  16328. }
  16329. if (!stop)
  16330. {
  16331. idx -= line;
  16332. }
  16333. else
  16334. {
  16335. break;
  16336. }
  16337. }
  16338. properties.descent = i - baseline;
  16339. properties.fontSize = properties.ascent + properties.descent;
  16340. Text.fontPropertiesCache[fontStyle] = properties;
  16341. }
  16342. return properties;
  16343. };
  16344. /**
  16345. * Applies newlines to a string to have it optimally fit into the horizontal
  16346. * bounds set by the Text object's wordWrapWidth property.
  16347. *
  16348. * @param text {string}
  16349. * @private
  16350. */
  16351. Text.prototype.wordWrap = function (text)
  16352. {
  16353. // Greedy wrapping algorithm that will wrap words as the line grows longer
  16354. // than its horizontal bounds.
  16355. var result = '';
  16356. var lines = text.split('\n');
  16357. var wordWrapWidth = this._style.wordWrapWidth;
  16358. for (var i = 0; i < lines.length; i++)
  16359. {
  16360. var spaceLeft = wordWrapWidth;
  16361. var words = lines[i].split(' ');
  16362. for (var j = 0; j < words.length; j++)
  16363. {
  16364. var wordWidth = this.context.measureText(words[j]).width;
  16365. if (this._style.breakWords && wordWidth > wordWrapWidth)
  16366. {
  16367. // Word should be split in the middle
  16368. var characters = words[j].split('');
  16369. for (var c = 0; c < characters.length; c++)
  16370. {
  16371. var characterWidth = this.context.measureText(characters[c]).width;
  16372. if (characterWidth > spaceLeft)
  16373. {
  16374. result += '\n' + characters[c];
  16375. spaceLeft = wordWrapWidth - characterWidth;
  16376. }
  16377. else
  16378. {
  16379. if (c === 0)
  16380. {
  16381. result += ' ';
  16382. }
  16383. result += characters[c];
  16384. spaceLeft -= characterWidth;
  16385. }
  16386. }
  16387. }
  16388. else
  16389. {
  16390. var wordWidthWithSpace = wordWidth + this.context.measureText(' ').width;
  16391. if (j === 0 || wordWidthWithSpace > spaceLeft)
  16392. {
  16393. // Skip printing the newline if it's the first word of the line that is
  16394. // greater than the word wrap width.
  16395. if (j > 0)
  16396. {
  16397. result += '\n';
  16398. }
  16399. result += words[j];
  16400. spaceLeft = wordWrapWidth - wordWidth;
  16401. }
  16402. else
  16403. {
  16404. spaceLeft -= wordWidthWithSpace;
  16405. result += ' ' + words[j];
  16406. }
  16407. }
  16408. }
  16409. if (i < lines.length-1)
  16410. {
  16411. result += '\n';
  16412. }
  16413. }
  16414. return result;
  16415. };
  16416. /**
  16417. * Returns the bounds of the Text as a rectangle. The bounds calculation takes the worldTransform into account.
  16418. *
  16419. * @param matrix {PIXI.Matrix} the transformation matrix of the Text
  16420. * @return {PIXI.Rectangle} the framing rectangle
  16421. */
  16422. Text.prototype.getBounds = function (matrix)
  16423. {
  16424. if (this.dirty)
  16425. {
  16426. this.updateText();
  16427. }
  16428. return Sprite.prototype.getBounds.call(this, matrix);
  16429. };
  16430. /**
  16431. * Destroys this text object.
  16432. *
  16433. * @param [destroyBaseTexture=true] {boolean} whether to destroy the base texture as well
  16434. */
  16435. Text.prototype.destroy = function (destroyBaseTexture)
  16436. {
  16437. // make sure to reset the the context and canvas.. dont want this hanging around in memory!
  16438. this.context = null;
  16439. this.canvas = null;
  16440. this._style = null;
  16441. this._texture.destroy(destroyBaseTexture === undefined ? true : destroyBaseTexture);
  16442. };
  16443. },{"../const":22,"../math":33,"../sprites/Sprite":67,"../textures/Texture":72,"../utils":77}],70:[function(require,module,exports){
  16444. var utils = require('../utils'),
  16445. CONST = require('../const'),
  16446. EventEmitter = require('eventemitter3');
  16447. /**
  16448. * A texture stores the information that represents an image. All textures have a base texture.
  16449. *
  16450. * @class
  16451. * @memberof PIXI
  16452. * @param source {Image|Canvas} the source object of the texture.
  16453. * @param [scaleMode=PIXI.SCALE_MODES.DEFAULT] {number} See {@link PIXI.SCALE_MODES} for possible values
  16454. * @param resolution {number} the resolution of the texture for devices with different pixel ratios
  16455. */
  16456. function BaseTexture(source, scaleMode, resolution)
  16457. {
  16458. EventEmitter.call(this);
  16459. this.uid = utils.uid();
  16460. /**
  16461. * The Resolution of the texture.
  16462. *
  16463. * @member {number}
  16464. */
  16465. this.resolution = resolution || 1;
  16466. /**
  16467. * The width of the base texture set when the image has loaded
  16468. *
  16469. * @member {number}
  16470. * @readOnly
  16471. */
  16472. this.width = 100;
  16473. /**
  16474. * The height of the base texture set when the image has loaded
  16475. *
  16476. * @member {number}
  16477. * @readOnly
  16478. */
  16479. this.height = 100;
  16480. // TODO docs
  16481. // used to store the actual dimensions of the source
  16482. /**
  16483. * Used to store the actual width of the source of this texture
  16484. *
  16485. * @member {number}
  16486. * @readOnly
  16487. */
  16488. this.realWidth = 100;
  16489. /**
  16490. * Used to store the actual height of the source of this texture
  16491. *
  16492. * @member {number}
  16493. * @readOnly
  16494. */
  16495. this.realHeight = 100;
  16496. /**
  16497. * The scale mode to apply when scaling this texture
  16498. *
  16499. * @member {number}
  16500. * @default PIXI.SCALE_MODES.LINEAR
  16501. * @see PIXI.SCALE_MODES
  16502. */
  16503. this.scaleMode = scaleMode || CONST.SCALE_MODES.DEFAULT;
  16504. /**
  16505. * Set to true once the base texture has successfully loaded.
  16506. *
  16507. * This is never true if the underlying source fails to load or has no texture data.
  16508. *
  16509. * @member {boolean}
  16510. * @readOnly
  16511. */
  16512. this.hasLoaded = false;
  16513. /**
  16514. * Set to true if the source is currently loading.
  16515. *
  16516. * If an Image source is loading the 'loaded' or 'error' event will be
  16517. * dispatched when the operation ends. An underyling source that is
  16518. * immediately-available bypasses loading entirely.
  16519. *
  16520. * @member {boolean}
  16521. * @readonly
  16522. */
  16523. this.isLoading = false;
  16524. /**
  16525. * The image source that is used to create the texture.
  16526. *
  16527. * TODO: Make this a setter that calls loadSource();
  16528. *
  16529. * @member {Image|Canvas}
  16530. * @readonly
  16531. */
  16532. this.source = null; // set in loadSource, if at all
  16533. /**
  16534. * Controls if RGB channels should be pre-multiplied by Alpha (WebGL only)
  16535. * All blend modes, and shaders written for default value. Change it on your own risk.
  16536. *
  16537. * @member {boolean}
  16538. * @default true
  16539. */
  16540. this.premultipliedAlpha = true;
  16541. /**
  16542. * @member {string}
  16543. */
  16544. this.imageUrl = null;
  16545. /**
  16546. * Wether or not the texture is a power of two, try to use power of two textures as much as you can
  16547. * @member {boolean}
  16548. * @private
  16549. */
  16550. this.isPowerOfTwo = false;
  16551. // used for webGL
  16552. /**
  16553. *
  16554. * Set this to true if a mipmap of this texture needs to be generated. This value needs to be set before the texture is used
  16555. * Also the texture must be a power of two size to work
  16556. *
  16557. * @member {boolean}
  16558. */
  16559. this.mipmap = false;
  16560. /**
  16561. * A map of renderer IDs to webgl textures
  16562. *
  16563. * @member {object<number, WebGLTexture>}
  16564. * @private
  16565. */
  16566. this._glTextures = {};
  16567. // if no source passed don't try to load
  16568. if (source)
  16569. {
  16570. this.loadSource(source);
  16571. }
  16572. /**
  16573. * Fired when a not-immediately-available source finishes loading.
  16574. *
  16575. * @event loaded
  16576. * @memberof PIXI.BaseTexture#
  16577. * @protected
  16578. */
  16579. /**
  16580. * Fired when a not-immediately-available source fails to load.
  16581. *
  16582. * @event error
  16583. * @memberof PIXI.BaseTexture#
  16584. * @protected
  16585. */
  16586. }
  16587. BaseTexture.prototype = Object.create(EventEmitter.prototype);
  16588. BaseTexture.prototype.constructor = BaseTexture;
  16589. module.exports = BaseTexture;
  16590. /**
  16591. * Updates the texture on all the webgl renderers, this also assumes the src has changed.
  16592. *
  16593. * @fires update
  16594. */
  16595. BaseTexture.prototype.update = function ()
  16596. {
  16597. this.realWidth = this.source.naturalWidth || this.source.width;
  16598. this.realHeight = this.source.naturalHeight || this.source.height;
  16599. this.width = this.realWidth / this.resolution;
  16600. this.height = this.realHeight / this.resolution;
  16601. this.isPowerOfTwo = utils.isPowerOfTwo(this.realWidth, this.realHeight);
  16602. this.emit('update', this);
  16603. };
  16604. /**
  16605. * Load a source.
  16606. *
  16607. * If the source is not-immediately-available, such as an image that needs to be
  16608. * downloaded, then the 'loaded' or 'error' event will be dispatched in the future
  16609. * and `hasLoaded` will remain false after this call.
  16610. *
  16611. * The logic state after calling `loadSource` directly or indirectly (eg. `fromImage`, `new BaseTexture`) is:
  16612. *
  16613. * if (texture.hasLoaded)
  16614. {
  16615. * // texture ready for use
  16616. * } else if (texture.isLoading)
  16617. {
  16618. * // listen to 'loaded' and/or 'error' events on texture
  16619. * } else {
  16620. * // not loading, not going to load UNLESS the source is reloaded
  16621. * // (it may still make sense to listen to the events)
  16622. * }
  16623. *
  16624. * @protected
  16625. * @param source {Image|Canvas} the source object of the texture.
  16626. */
  16627. BaseTexture.prototype.loadSource = function (source)
  16628. {
  16629. var wasLoading = this.isLoading;
  16630. this.hasLoaded = false;
  16631. this.isLoading = false;
  16632. if (wasLoading && this.source)
  16633. {
  16634. this.source.onload = null;
  16635. this.source.onerror = null;
  16636. }
  16637. this.source = source;
  16638. // Apply source if loaded. Otherwise setup appropriate loading monitors.
  16639. if ((this.source.complete || this.source.getContext) && this.source.width && this.source.height)
  16640. {
  16641. this._sourceLoaded();
  16642. }
  16643. else if (!source.getContext)
  16644. {
  16645. // Image fail / not ready
  16646. this.isLoading = true;
  16647. var scope = this;
  16648. source.onload = function ()
  16649. {
  16650. source.onload = null;
  16651. source.onerror = null;
  16652. if (!scope.isLoading)
  16653. {
  16654. return;
  16655. }
  16656. scope.isLoading = false;
  16657. scope._sourceLoaded();
  16658. scope.emit('loaded', scope);
  16659. };
  16660. source.onerror = function ()
  16661. {
  16662. source.onload = null;
  16663. source.onerror = null;
  16664. if (!scope.isLoading)
  16665. {
  16666. return;
  16667. }
  16668. scope.isLoading = false;
  16669. scope.emit('error', scope);
  16670. };
  16671. // Per http://www.w3.org/TR/html5/embedded-content-0.html#the-img-element
  16672. // "The value of `complete` can thus change while a script is executing."
  16673. // So complete needs to be re-checked after the callbacks have been added..
  16674. // NOTE: complete will be true if the image has no src so best to check if the src is set.
  16675. if (source.complete && source.src)
  16676. {
  16677. this.isLoading = false;
  16678. // ..and if we're complete now, no need for callbacks
  16679. source.onload = null;
  16680. source.onerror = null;
  16681. if (source.width && source.height)
  16682. {
  16683. this._sourceLoaded();
  16684. // If any previous subscribers possible
  16685. if (wasLoading)
  16686. {
  16687. this.emit('loaded', this);
  16688. }
  16689. }
  16690. else
  16691. {
  16692. // If any previous subscribers possible
  16693. if (wasLoading)
  16694. {
  16695. this.emit('error', this);
  16696. }
  16697. }
  16698. }
  16699. }
  16700. };
  16701. /**
  16702. * Used internally to update the width, height, and some other tracking vars once
  16703. * a source has successfully loaded.
  16704. *
  16705. * @private
  16706. */
  16707. BaseTexture.prototype._sourceLoaded = function ()
  16708. {
  16709. this.hasLoaded = true;
  16710. this.update();
  16711. };
  16712. /**
  16713. * Destroys this base texture
  16714. *
  16715. */
  16716. BaseTexture.prototype.destroy = function ()
  16717. {
  16718. if (this.imageUrl)
  16719. {
  16720. delete utils.BaseTextureCache[this.imageUrl];
  16721. delete utils.TextureCache[this.imageUrl];
  16722. this.imageUrl = null;
  16723. if (!navigator.isCocoonJS)
  16724. {
  16725. this.source.src = '';
  16726. }
  16727. }
  16728. else if (this.source && this.source._pixiId)
  16729. {
  16730. delete utils.BaseTextureCache[this.source._pixiId];
  16731. }
  16732. this.source = null;
  16733. this.dispose();
  16734. };
  16735. /**
  16736. * Frees the texture from WebGL memory without destroying this texture object.
  16737. * This means you can still use the texture later which will upload it to GPU
  16738. * memory again.
  16739. *
  16740. */
  16741. BaseTexture.prototype.dispose = function ()
  16742. {
  16743. this.emit('dispose', this);
  16744. // this should no longer be needed, the renderers should cleanup all the gl textures.
  16745. // this._glTextures = {};
  16746. };
  16747. /**
  16748. * Changes the source image of the texture.
  16749. * The original source must be an Image element.
  16750. *
  16751. * @param newSrc {string} the path of the image
  16752. */
  16753. BaseTexture.prototype.updateSourceImage = function (newSrc)
  16754. {
  16755. this.source.src = newSrc;
  16756. this.loadSource(this.source);
  16757. };
  16758. /**
  16759. * Helper function that creates a base texture from the given image url.
  16760. * If the image is not in the base texture cache it will be created and loaded.
  16761. *
  16762. * @static
  16763. * @param imageUrl {string} The image url of the texture
  16764. * @param [crossorigin=(auto)] {boolean} Should use anonymous CORS? Defaults to true if the URL is not a data-URI.
  16765. * @param [scaleMode=PIXI.SCALE_MODES.DEFAULT] {number} See {@link PIXI.SCALE_MODES} for possible values
  16766. * @return PIXI.BaseTexture
  16767. */
  16768. BaseTexture.fromImage = function (imageUrl, crossorigin, scaleMode)
  16769. {
  16770. var baseTexture = utils.BaseTextureCache[imageUrl];
  16771. if (crossorigin === undefined && imageUrl.indexOf('data:') !== 0)
  16772. {
  16773. crossorigin = true;
  16774. }
  16775. if (!baseTexture)
  16776. {
  16777. // new Image() breaks tex loading in some versions of Chrome.
  16778. // See https://code.google.com/p/chromium/issues/detail?id=238071
  16779. var image = new Image();//document.createElement('img');
  16780. if (crossorigin)
  16781. {
  16782. image.crossOrigin = '';
  16783. }
  16784. baseTexture = new BaseTexture(image, scaleMode);
  16785. baseTexture.imageUrl = imageUrl;
  16786. image.src = imageUrl;
  16787. utils.BaseTextureCache[imageUrl] = baseTexture;
  16788. // if there is an @2x at the end of the url we are going to assume its a highres image
  16789. baseTexture.resolution = utils.getResolutionOfUrl(imageUrl);
  16790. }
  16791. return baseTexture;
  16792. };
  16793. /**
  16794. * Helper function that creates a base texture from the given canvas element.
  16795. *
  16796. * @static
  16797. * @param canvas {Canvas} The canvas element source of the texture
  16798. * @param scaleMode {number} See {@link PIXI.SCALE_MODES} for possible values
  16799. * @return PIXI.BaseTexture
  16800. */
  16801. BaseTexture.fromCanvas = function (canvas, scaleMode)
  16802. {
  16803. if (!canvas._pixiId)
  16804. {
  16805. canvas._pixiId = 'canvas_' + utils.uid();
  16806. }
  16807. var baseTexture = utils.BaseTextureCache[canvas._pixiId];
  16808. if (!baseTexture)
  16809. {
  16810. baseTexture = new BaseTexture(canvas, scaleMode);
  16811. utils.BaseTextureCache[canvas._pixiId] = baseTexture;
  16812. }
  16813. return baseTexture;
  16814. };
  16815. },{"../const":22,"../utils":77,"eventemitter3":10}],71:[function(require,module,exports){
  16816. var BaseTexture = require('./BaseTexture'),
  16817. Texture = require('./Texture'),
  16818. RenderTarget = require('../renderers/webgl/utils/RenderTarget'),
  16819. FilterManager = require('../renderers/webgl/managers/FilterManager'),
  16820. CanvasBuffer = require('../renderers/canvas/utils/CanvasBuffer'),
  16821. math = require('../math'),
  16822. CONST = require('../const'),
  16823. tempMatrix = new math.Matrix();
  16824. /**
  16825. * A RenderTexture is a special texture that allows any Pixi display object to be rendered to it.
  16826. *
  16827. * __Hint__: All DisplayObjects (i.e. Sprites) that render to a RenderTexture should be preloaded
  16828. * otherwise black rectangles will be drawn instead.
  16829. *
  16830. * A RenderTexture takes a snapshot of any Display Object given to its render method. The position
  16831. * and rotation of the given Display Objects is ignored. For example:
  16832. *
  16833. * ```js
  16834. * var renderer = PIXI.autoDetectRenderer(1024, 1024, { view: canvas, ratio: 1 });
  16835. * var renderTexture = new PIXI.RenderTexture(renderer, 800, 600);
  16836. * var sprite = PIXI.Sprite.fromImage("spinObj_01.png");
  16837. *
  16838. * sprite.position.x = 800/2;
  16839. * sprite.position.y = 600/2;
  16840. * sprite.anchor.x = 0.5;
  16841. * sprite.anchor.y = 0.5;
  16842. *
  16843. * renderTexture.render(sprite);
  16844. * ```
  16845. *
  16846. * The Sprite in this case will be rendered to a position of 0,0. To render this sprite at its actual
  16847. * position a Container should be used:
  16848. *
  16849. * ```js
  16850. * var doc = new PIXI.Container();
  16851. *
  16852. * doc.addChild(sprite);
  16853. *
  16854. * renderTexture.render(doc); // Renders to center of renderTexture
  16855. * ```
  16856. *
  16857. * @class
  16858. * @extends PIXI.Texture
  16859. * @memberof PIXI
  16860. * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} The renderer used for this RenderTexture
  16861. * @param [width=100] {number} The width of the render texture
  16862. * @param [height=100] {number} The height of the render texture
  16863. * @param [scaleMode] {number} See {@link PIXI.SCALE_MODES} for possible values
  16864. * @param [resolution=1] {number} The resolution of the texture being generated
  16865. */
  16866. function RenderTexture(renderer, width, height, scaleMode, resolution)
  16867. {
  16868. if (!renderer)
  16869. {
  16870. throw new Error('Unable to create RenderTexture, you must pass a renderer into the constructor.');
  16871. }
  16872. width = width || 100;
  16873. height = height || 100;
  16874. resolution = resolution || CONST.RESOLUTION;
  16875. /**
  16876. * The base texture object that this texture uses
  16877. *
  16878. * @member {BaseTexture}
  16879. */
  16880. var baseTexture = new BaseTexture();
  16881. baseTexture.width = width;
  16882. baseTexture.height = height;
  16883. baseTexture.resolution = resolution;
  16884. baseTexture.scaleMode = scaleMode || CONST.SCALE_MODES.DEFAULT;
  16885. baseTexture.hasLoaded = true;
  16886. Texture.call(this,
  16887. baseTexture,
  16888. new math.Rectangle(0, 0, width, height)
  16889. );
  16890. /**
  16891. * The with of the render texture
  16892. *
  16893. * @member {number}
  16894. */
  16895. this.width = width;
  16896. /**
  16897. * The height of the render texture
  16898. *
  16899. * @member {number}
  16900. */
  16901. this.height = height;
  16902. /**
  16903. * The Resolution of the texture.
  16904. *
  16905. * @member {number}
  16906. */
  16907. this.resolution = resolution;
  16908. /**
  16909. * Draw/render the given DisplayObject onto the texture.
  16910. *
  16911. * The displayObject and descendents are transformed during this operation.
  16912. * If `updateTransform` is true then the transformations will be restored before the
  16913. * method returns. Otherwise it is up to the calling code to correctly use or reset
  16914. * the transformed display objects.
  16915. *
  16916. * The display object is always rendered with a worldAlpha value of 1.
  16917. *
  16918. * @method
  16919. * @param displayObject {PIXI.DisplayObject} The display object to render this texture on
  16920. * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering.
  16921. * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn
  16922. * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children
  16923. * transformations will be restored. Not restoring this information will be a little faster.
  16924. */
  16925. this.render = null;
  16926. /**
  16927. * The renderer this RenderTexture uses. A RenderTexture can only belong to one renderer at the moment if its webGL.
  16928. *
  16929. * @member {PIXI.CanvasRenderer|PIXI.WebGLRenderer}
  16930. */
  16931. this.renderer = renderer;
  16932. if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL)
  16933. {
  16934. var gl = this.renderer.gl;
  16935. this.textureBuffer = new RenderTarget(gl, this.width, this.height, baseTexture.scaleMode, this.resolution);//, this.baseTexture.scaleMode);
  16936. this.baseTexture._glTextures[gl.id] = this.textureBuffer.texture;
  16937. //TODO refactor filter manager.. as really its no longer a manager if we use it here..
  16938. this.filterManager = new FilterManager(this.renderer);
  16939. this.filterManager.onContextChange();
  16940. this.filterManager.resize(width, height);
  16941. this.render = this.renderWebGL;
  16942. // the creation of a filter manager unbinds the buffers..
  16943. this.renderer.currentRenderer.start();
  16944. this.renderer.currentRenderTarget.activate();
  16945. }
  16946. else
  16947. {
  16948. this.render = this.renderCanvas;
  16949. this.textureBuffer = new CanvasBuffer(this.width* this.resolution, this.height* this.resolution);
  16950. this.baseTexture.source = this.textureBuffer.canvas;
  16951. }
  16952. /**
  16953. * @member {boolean}
  16954. */
  16955. this.valid = true;
  16956. this._updateUvs();
  16957. }
  16958. RenderTexture.prototype = Object.create(Texture.prototype);
  16959. RenderTexture.prototype.constructor = RenderTexture;
  16960. module.exports = RenderTexture;
  16961. /**
  16962. * Resizes the RenderTexture.
  16963. *
  16964. * @param width {number} The width to resize to.
  16965. * @param height {number} The height to resize to.
  16966. * @param updateBase {boolean} Should the baseTexture.width and height values be resized as well?
  16967. */
  16968. RenderTexture.prototype.resize = function (width, height, updateBase)
  16969. {
  16970. if (width === this.width && height === this.height)
  16971. {
  16972. return;
  16973. }
  16974. this.valid = (width > 0 && height > 0);
  16975. this.width = this._frame.width = this.crop.width = width;
  16976. this.height = this._frame.height = this.crop.height = height;
  16977. if (updateBase)
  16978. {
  16979. this.baseTexture.width = this.width;
  16980. this.baseTexture.height = this.height;
  16981. }
  16982. if (!this.valid)
  16983. {
  16984. return;
  16985. }
  16986. this.textureBuffer.resize(this.width, this.height);
  16987. if(this.filterManager)
  16988. {
  16989. this.filterManager.resize(this.width, this.height);
  16990. }
  16991. };
  16992. /**
  16993. * Clears the RenderTexture.
  16994. *
  16995. */
  16996. RenderTexture.prototype.clear = function ()
  16997. {
  16998. if (!this.valid)
  16999. {
  17000. return;
  17001. }
  17002. if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL)
  17003. {
  17004. this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER, this.textureBuffer.frameBuffer);
  17005. }
  17006. this.textureBuffer.clear();
  17007. };
  17008. /**
  17009. * Internal method assigned to the `render` property if using a CanvasRenderer.
  17010. *
  17011. * @private
  17012. * @param displayObject {PIXI.DisplayObject} The display object to render this texture on
  17013. * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering.
  17014. * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn
  17015. * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children
  17016. * transformations will be restored. Not restoring this information will be a little faster.
  17017. */
  17018. RenderTexture.prototype.renderWebGL = function (displayObject, matrix, clear, updateTransform)
  17019. {
  17020. if (!this.valid)
  17021. {
  17022. return;
  17023. }
  17024. updateTransform = (updateTransform !== undefined) ? updateTransform : true;//!updateTransform;
  17025. this.textureBuffer.transform = matrix;
  17026. //TODO not a fan that this is here... it will move!
  17027. this.textureBuffer.activate();
  17028. // setWorld Alpha to ensure that the object is renderer at full opacity
  17029. displayObject.worldAlpha = 1;
  17030. if (updateTransform)
  17031. {
  17032. // reset the matrix of the displatyObject..
  17033. displayObject.worldTransform.identity();
  17034. displayObject.currentBounds = null;
  17035. // Time to update all the children of the displayObject with the new matrix..
  17036. var children = displayObject.children;
  17037. var i, j;
  17038. for (i = 0, j = children.length; i < j; ++i)
  17039. {
  17040. children[i].updateTransform();
  17041. }
  17042. }
  17043. //TODO rename textureBuffer to renderTarget..
  17044. var temp = this.renderer.filterManager;
  17045. this.renderer.filterManager = this.filterManager;
  17046. this.renderer.renderDisplayObject(displayObject, this.textureBuffer, clear);
  17047. this.renderer.filterManager = temp;
  17048. };
  17049. /**
  17050. * Internal method assigned to the `render` property if using a CanvasRenderer.
  17051. *
  17052. * @private
  17053. * @param displayObject {PIXI.DisplayObject} The display object to render this texture on
  17054. * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering.
  17055. * @param [clear] {boolean} If true the texture will be cleared before the displayObject is drawn
  17056. */
  17057. RenderTexture.prototype.renderCanvas = function (displayObject, matrix, clear, updateTransform)
  17058. {
  17059. if (!this.valid)
  17060. {
  17061. return;
  17062. }
  17063. updateTransform = !!updateTransform;
  17064. var wt = tempMatrix;
  17065. wt.identity();
  17066. if (matrix)
  17067. {
  17068. wt.append(matrix);
  17069. }
  17070. var cachedWt = displayObject.worldTransform;
  17071. displayObject.worldTransform = wt;
  17072. // setWorld Alpha to ensure that the object is renderer at full opacity
  17073. displayObject.worldAlpha = 1;
  17074. // Time to update all the children of the displayObject with the new matrix..
  17075. var children = displayObject.children;
  17076. var i, j;
  17077. for (i = 0, j = children.length; i < j; ++i)
  17078. {
  17079. children[i].updateTransform();
  17080. }
  17081. if (clear)
  17082. {
  17083. this.textureBuffer.clear();
  17084. }
  17085. // this.textureBuffer.
  17086. var context = this.textureBuffer.context;
  17087. var realResolution = this.renderer.resolution;
  17088. this.renderer.resolution = this.resolution;
  17089. this.renderer.renderDisplayObject(displayObject, context);
  17090. this.renderer.resolution = realResolution;
  17091. if(displayObject.worldTransform === wt)
  17092. {
  17093. // fixes cacheAsBitmap Happening during the above..
  17094. displayObject.worldTransform = cachedWt;
  17095. }
  17096. };
  17097. /**
  17098. * Destroys this texture
  17099. *
  17100. * @param destroyBase {boolean} Whether to destroy the base texture as well
  17101. */
  17102. RenderTexture.prototype.destroy = function ()
  17103. {
  17104. Texture.prototype.destroy.call(this, true);
  17105. this.textureBuffer.destroy();
  17106. // destroy the filtermanager..
  17107. if(this.filterManager)
  17108. {
  17109. this.filterManager.destroy();
  17110. }
  17111. this.renderer = null;
  17112. };
  17113. /**
  17114. * Will return a HTML Image of the texture
  17115. *
  17116. * @return {Image}
  17117. */
  17118. RenderTexture.prototype.getImage = function ()
  17119. {
  17120. var image = new Image();
  17121. image.src = this.getBase64();
  17122. return image;
  17123. };
  17124. /**
  17125. * Will return a a base64 encoded string of this texture. It works by calling RenderTexture.getCanvas and then running toDataURL on that.
  17126. *
  17127. * @return {string} A base64 encoded string of the texture.
  17128. */
  17129. RenderTexture.prototype.getBase64 = function ()
  17130. {
  17131. return this.getCanvas().toDataURL();
  17132. };
  17133. /**
  17134. * Creates a Canvas element, renders this RenderTexture to it and then returns it.
  17135. *
  17136. * @return {HTMLCanvasElement} A Canvas element with the texture rendered on.
  17137. */
  17138. RenderTexture.prototype.getCanvas = function ()
  17139. {
  17140. if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL)
  17141. {
  17142. var gl = this.renderer.gl;
  17143. var width = this.textureBuffer.size.width;
  17144. var height = this.textureBuffer.size.height;
  17145. var webGLPixels = new Uint8Array(4 * width * height);
  17146. gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer);
  17147. gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels);
  17148. gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  17149. var tempCanvas = new CanvasBuffer(width, height);
  17150. var canvasData = tempCanvas.context.getImageData(0, 0, width, height);
  17151. canvasData.data.set(webGLPixels);
  17152. tempCanvas.context.putImageData(canvasData, 0, 0);
  17153. return tempCanvas.canvas;
  17154. }
  17155. else
  17156. {
  17157. return this.textureBuffer.canvas;
  17158. }
  17159. };
  17160. /**
  17161. * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA order, with integer values between 0 and 255 (included).
  17162. *
  17163. * @return {Uint8ClampedArray}
  17164. */
  17165. RenderTexture.prototype.getPixels = function ()
  17166. {
  17167. var width, height;
  17168. if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL)
  17169. {
  17170. var gl = this.renderer.gl;
  17171. width = this.textureBuffer.size.width;
  17172. height = this.textureBuffer.size.height;
  17173. var webGLPixels = new Uint8Array(4 * width * height);
  17174. gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer);
  17175. gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels);
  17176. gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  17177. return webGLPixels;
  17178. }
  17179. else
  17180. {
  17181. width = this.textureBuffer.canvas.width;
  17182. height = this.textureBuffer.canvas.height;
  17183. return this.textureBuffer.canvas.getContext('2d').getImageData(0, 0, width, height).data;
  17184. }
  17185. };
  17186. /**
  17187. * Will return a one-dimensional array containing the pixel data of a pixel within the texture in RGBA order, with integer values between 0 and 255 (included).
  17188. *
  17189. * @param x {number} The x coordinate of the pixel to retrieve.
  17190. * @param y {number} The y coordinate of the pixel to retrieve.
  17191. * @return {Uint8ClampedArray}
  17192. */
  17193. RenderTexture.prototype.getPixel = function (x, y)
  17194. {
  17195. if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL)
  17196. {
  17197. var gl = this.renderer.gl;
  17198. var webGLPixels = new Uint8Array(4);
  17199. gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer);
  17200. gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels);
  17201. gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  17202. return webGLPixels;
  17203. }
  17204. else
  17205. {
  17206. return this.textureBuffer.canvas.getContext('2d').getImageData(x, y, 1, 1).data;
  17207. }
  17208. };
  17209. },{"../const":22,"../math":33,"../renderers/canvas/utils/CanvasBuffer":45,"../renderers/webgl/managers/FilterManager":54,"../renderers/webgl/utils/RenderTarget":65,"./BaseTexture":70,"./Texture":72}],72:[function(require,module,exports){
  17210. var BaseTexture = require('./BaseTexture'),
  17211. VideoBaseTexture = require('./VideoBaseTexture'),
  17212. TextureUvs = require('./TextureUvs'),
  17213. EventEmitter = require('eventemitter3'),
  17214. math = require('../math'),
  17215. utils = require('../utils');
  17216. /**
  17217. * A texture stores the information that represents an image or part of an image. It cannot be added
  17218. * to the display list directly. Instead use it as the texture for a Sprite. If no frame is provided then the whole image is used.
  17219. *
  17220. * You can directly create a texture from an image and then reuse it multiple times like this :
  17221. *
  17222. * ```js
  17223. * var texture = PIXI.Texture.fromImage('assets/image.png');
  17224. * var sprite1 = new PIXI.Sprite(texture);
  17225. * var sprite2 = new PIXI.Sprite(texture);
  17226. * ```
  17227. *
  17228. * @class
  17229. * @memberof PIXI
  17230. * @param baseTexture {PIXI.BaseTexture} The base texture source to create the texture from
  17231. * @param [frame] {PIXI.Rectangle} The rectangle frame of the texture to show
  17232. * @param [crop] {PIXI.Rectangle} The area of original texture
  17233. * @param [trim] {PIXI.Rectangle} Trimmed texture rectangle
  17234. * @param [rotate] {number} indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
  17235. */
  17236. function Texture(baseTexture, frame, crop, trim, rotate)
  17237. {
  17238. EventEmitter.call(this);
  17239. /**
  17240. * Does this Texture have any frame data assigned to it?
  17241. *
  17242. * @member {boolean}
  17243. */
  17244. this.noFrame = false;
  17245. if (!frame)
  17246. {
  17247. this.noFrame = true;
  17248. frame = new math.Rectangle(0, 0, 1, 1);
  17249. }
  17250. if (baseTexture instanceof Texture)
  17251. {
  17252. baseTexture = baseTexture.baseTexture;
  17253. }
  17254. /**
  17255. * The base texture that this texture uses.
  17256. *
  17257. * @member {PIXI.BaseTexture}
  17258. */
  17259. this.baseTexture = baseTexture;
  17260. /**
  17261. * The frame specifies the region of the base texture that this texture uses
  17262. *
  17263. * @member {PIXI.Rectangle}
  17264. * @private
  17265. */
  17266. this._frame = frame;
  17267. /**
  17268. * The texture trim data.
  17269. *
  17270. * @member {PIXI.Rectangle}
  17271. */
  17272. this.trim = trim;
  17273. /**
  17274. * This will let the renderer know if the texture is valid. If it's not then it cannot be rendered.
  17275. *
  17276. * @member {boolean}
  17277. */
  17278. this.valid = false;
  17279. /**
  17280. * This will let a renderer know that a texture has been updated (used mainly for webGL uv updates)
  17281. *
  17282. * @member {boolean}
  17283. */
  17284. this.requiresUpdate = false;
  17285. /**
  17286. * The WebGL UV data cache.
  17287. *
  17288. * @member {PIXI.TextureUvs}
  17289. * @private
  17290. */
  17291. this._uvs = null;
  17292. /**
  17293. * The width of the Texture in pixels.
  17294. *
  17295. * @member {number}
  17296. */
  17297. this.width = 0;
  17298. /**
  17299. * The height of the Texture in pixels.
  17300. *
  17301. * @member {number}
  17302. */
  17303. this.height = 0;
  17304. /**
  17305. * This is the area of the BaseTexture image to actually copy to the Canvas / WebGL when rendering,
  17306. * irrespective of the actual frame size or placement (which can be influenced by trimmed texture atlases)
  17307. *
  17308. * @member {PIXI.Rectangle}
  17309. */
  17310. this.crop = crop || frame;//new math.Rectangle(0, 0, 1, 1);
  17311. this._rotate = +(rotate || 0);
  17312. if (rotate === true) {
  17313. // this is old texturepacker legacy, some games/libraries are passing "true" for rotated textures
  17314. this._rotate = 2;
  17315. } else {
  17316. if (this._rotate % 2 !== 0) {
  17317. throw 'attempt to use diamond-shaped UVs. If you are sure, set rotation manually';
  17318. }
  17319. }
  17320. if (baseTexture.hasLoaded)
  17321. {
  17322. if (this.noFrame)
  17323. {
  17324. frame = new math.Rectangle(0, 0, baseTexture.width, baseTexture.height);
  17325. // if there is no frame we should monitor for any base texture changes..
  17326. baseTexture.on('update', this.onBaseTextureUpdated, this);
  17327. }
  17328. this.frame = frame;
  17329. }
  17330. else
  17331. {
  17332. baseTexture.once('loaded', this.onBaseTextureLoaded, this);
  17333. }
  17334. /**
  17335. * Fired when the texture is updated. This happens if the frame or the baseTexture is updated.
  17336. *
  17337. * @event update
  17338. * @memberof PIXI.Texture#
  17339. * @protected
  17340. */
  17341. }
  17342. Texture.prototype = Object.create(EventEmitter.prototype);
  17343. Texture.prototype.constructor = Texture;
  17344. module.exports = Texture;
  17345. Object.defineProperties(Texture.prototype, {
  17346. /**
  17347. * The frame specifies the region of the base texture that this texture uses.
  17348. *
  17349. * @member {PIXI.Rectangle}
  17350. * @memberof PIXI.Texture#
  17351. */
  17352. frame: {
  17353. get: function ()
  17354. {
  17355. return this._frame;
  17356. },
  17357. set: function (frame)
  17358. {
  17359. this._frame = frame;
  17360. this.noFrame = false;
  17361. this.width = frame.width;
  17362. this.height = frame.height;
  17363. if (!this.trim && !this.rotate && (frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height))
  17364. {
  17365. throw new Error('Texture Error: frame does not fit inside the base Texture dimensions ' + this);
  17366. }
  17367. //this.valid = frame && frame.width && frame.height && this.baseTexture.source && this.baseTexture.hasLoaded;
  17368. this.valid = frame && frame.width && frame.height && this.baseTexture.hasLoaded;
  17369. if (this.trim)
  17370. {
  17371. this.width = this.trim.width;
  17372. this.height = this.trim.height;
  17373. this._frame.width = this.trim.width;
  17374. this._frame.height = this.trim.height;
  17375. }
  17376. else
  17377. {
  17378. this.crop = frame;
  17379. }
  17380. if (this.valid)
  17381. {
  17382. this._updateUvs();
  17383. }
  17384. }
  17385. },
  17386. /**
  17387. * Indicates whether the texture is rotated inside the atlas
  17388. * set to 2 to compensate for texture packer rotation
  17389. * set to 6 to compensate for spine packer rotation
  17390. * can be used to rotate or mirror sprites
  17391. * See {@link PIXI.GroupD8} for explanation
  17392. *
  17393. * @member {number}
  17394. */
  17395. rotate: {
  17396. get: function ()
  17397. {
  17398. return this._rotate;
  17399. },
  17400. set: function (rotate)
  17401. {
  17402. this._rotate = rotate;
  17403. if (this.valid)
  17404. {
  17405. this._updateUvs();
  17406. }
  17407. }
  17408. }
  17409. });
  17410. /**
  17411. * Updates this texture on the gpu.
  17412. *
  17413. */
  17414. Texture.prototype.update = function ()
  17415. {
  17416. this.baseTexture.update();
  17417. };
  17418. /**
  17419. * Called when the base texture is loaded
  17420. *
  17421. * @private
  17422. */
  17423. Texture.prototype.onBaseTextureLoaded = function (baseTexture)
  17424. {
  17425. // TODO this code looks confusing.. boo to abusing getters and setterss!
  17426. if (this.noFrame)
  17427. {
  17428. this.frame = new math.Rectangle(0, 0, baseTexture.width, baseTexture.height);
  17429. }
  17430. else
  17431. {
  17432. this.frame = this._frame;
  17433. }
  17434. this.emit('update', this);
  17435. };
  17436. /**
  17437. * Called when the base texture is updated
  17438. *
  17439. * @private
  17440. */
  17441. Texture.prototype.onBaseTextureUpdated = function (baseTexture)
  17442. {
  17443. this._frame.width = baseTexture.width;
  17444. this._frame.height = baseTexture.height;
  17445. this.emit('update', this);
  17446. };
  17447. /**
  17448. * Destroys this texture
  17449. *
  17450. * @param [destroyBase=false] {boolean} Whether to destroy the base texture as well
  17451. */
  17452. Texture.prototype.destroy = function (destroyBase)
  17453. {
  17454. if (this.baseTexture)
  17455. {
  17456. if (destroyBase)
  17457. {
  17458. this.baseTexture.destroy();
  17459. }
  17460. this.baseTexture.off('update', this.onBaseTextureUpdated, this);
  17461. this.baseTexture.off('loaded', this.onBaseTextureLoaded, this);
  17462. this.baseTexture = null;
  17463. }
  17464. this._frame = null;
  17465. this._uvs = null;
  17466. this.trim = null;
  17467. this.crop = null;
  17468. this.valid = false;
  17469. this.off('dispose', this.dispose, this);
  17470. this.off('update', this.update, this);
  17471. };
  17472. /**
  17473. * Creates a new texture object that acts the same as this one.
  17474. *
  17475. * @return {PIXI.Texture}
  17476. */
  17477. Texture.prototype.clone = function ()
  17478. {
  17479. return new Texture(this.baseTexture, this.frame, this.crop, this.trim, this.rotate);
  17480. };
  17481. /**
  17482. * Updates the internal WebGL UV cache.
  17483. *
  17484. * @private
  17485. */
  17486. Texture.prototype._updateUvs = function ()
  17487. {
  17488. if (!this._uvs)
  17489. {
  17490. this._uvs = new TextureUvs();
  17491. }
  17492. this._uvs.set(this.crop, this.baseTexture, this.rotate);
  17493. };
  17494. /**
  17495. * Helper function that creates a Texture object from the given image url.
  17496. * If the image is not in the texture cache it will be created and loaded.
  17497. *
  17498. * @static
  17499. * @param imageUrl {string} The image url of the texture
  17500. * @param crossorigin {boolean} Whether requests should be treated as crossorigin
  17501. * @param scaleMode {number} See {@link PIXI.SCALE_MODES} for possible values
  17502. * @return {PIXI.Texture} The newly created texture
  17503. */
  17504. Texture.fromImage = function (imageUrl, crossorigin, scaleMode)
  17505. {
  17506. var texture = utils.TextureCache[imageUrl];
  17507. if (!texture)
  17508. {
  17509. texture = new Texture(BaseTexture.fromImage(imageUrl, crossorigin, scaleMode));
  17510. utils.TextureCache[imageUrl] = texture;
  17511. }
  17512. return texture;
  17513. };
  17514. /**
  17515. * Helper function that creates a sprite that will contain a texture from the TextureCache based on the frameId
  17516. * The frame ids are created when a Texture packer file has been loaded
  17517. *
  17518. * @static
  17519. * @param frameId {string} The frame Id of the texture in the cache
  17520. * @return {PIXI.Texture} The newly created texture
  17521. */
  17522. Texture.fromFrame = function (frameId)
  17523. {
  17524. var texture = utils.TextureCache[frameId];
  17525. if (!texture)
  17526. {
  17527. throw new Error('The frameId "' + frameId + '" does not exist in the texture cache');
  17528. }
  17529. return texture;
  17530. };
  17531. /**
  17532. * Helper function that creates a new Texture based on the given canvas element.
  17533. *
  17534. * @static
  17535. * @param canvas {Canvas} The canvas element source of the texture
  17536. * @param scaleMode {number} See {@link PIXI.SCALE_MODES} for possible values
  17537. * @return {PIXI.Texture}
  17538. */
  17539. Texture.fromCanvas = function (canvas, scaleMode)
  17540. {
  17541. return new Texture(BaseTexture.fromCanvas(canvas, scaleMode));
  17542. };
  17543. /**
  17544. * Helper function that creates a new Texture based on the given video element.
  17545. *
  17546. * @static
  17547. * @param video {HTMLVideoElement}
  17548. * @param scaleMode {number} See {@link PIXI.SCALE_MODES} for possible values
  17549. * @return {PIXI.Texture} A Texture
  17550. */
  17551. Texture.fromVideo = function (video, scaleMode)
  17552. {
  17553. if (typeof video === 'string')
  17554. {
  17555. return Texture.fromVideoUrl(video, scaleMode);
  17556. }
  17557. else
  17558. {
  17559. return new Texture(VideoBaseTexture.fromVideo(video, scaleMode));
  17560. }
  17561. };
  17562. /**
  17563. * Helper function that creates a new Texture based on the video url.
  17564. *
  17565. * @static
  17566. * @param videoUrl {string}
  17567. * @param scaleMode {number} See {@link PIXI.SCALE_MODES} for possible values
  17568. * @return {PIXI.Texture} A Texture
  17569. */
  17570. Texture.fromVideoUrl = function (videoUrl, scaleMode)
  17571. {
  17572. return new Texture(VideoBaseTexture.fromUrl(videoUrl, scaleMode));
  17573. };
  17574. /**
  17575. * Adds a texture to the global utils.TextureCache. This cache is shared across the whole PIXI object.
  17576. *
  17577. * @static
  17578. * @param texture {PIXI.Texture} The Texture to add to the cache.
  17579. * @param id {string} The id that the texture will be stored against.
  17580. */
  17581. Texture.addTextureToCache = function (texture, id)
  17582. {
  17583. utils.TextureCache[id] = texture;
  17584. };
  17585. /**
  17586. * Remove a texture from the global utils.TextureCache.
  17587. *
  17588. * @static
  17589. * @param id {string} The id of the texture to be removed
  17590. * @return {PIXI.Texture} The texture that was removed
  17591. */
  17592. Texture.removeTextureFromCache = function (id)
  17593. {
  17594. var texture = utils.TextureCache[id];
  17595. delete utils.TextureCache[id];
  17596. delete utils.BaseTextureCache[id];
  17597. return texture;
  17598. };
  17599. /**
  17600. * An empty texture, used often to not have to create multiple empty textures.
  17601. *
  17602. * @static
  17603. * @constant
  17604. */
  17605. Texture.EMPTY = new Texture(new BaseTexture());
  17606. },{"../math":33,"../utils":77,"./BaseTexture":70,"./TextureUvs":73,"./VideoBaseTexture":74,"eventemitter3":10}],73:[function(require,module,exports){
  17607. /**
  17608. * A standard object to store the Uvs of a texture
  17609. *
  17610. * @class
  17611. * @private
  17612. * @memberof PIXI
  17613. */
  17614. function TextureUvs()
  17615. {
  17616. this.x0 = 0;
  17617. this.y0 = 0;
  17618. this.x1 = 1;
  17619. this.y1 = 0;
  17620. this.x2 = 1;
  17621. this.y2 = 1;
  17622. this.x3 = 0;
  17623. this.y3 = 1;
  17624. }
  17625. module.exports = TextureUvs;
  17626. var GroupD8 = require('../math/GroupD8');
  17627. /**
  17628. * Sets the texture Uvs based on the given frame information
  17629. * @param frame {PIXI.Rectangle}
  17630. * @param baseFrame {PIXI.Rectangle}
  17631. * @param rotate {number} Rotation of frame, see {@link PIXI.GroupD8}
  17632. * @private
  17633. */
  17634. TextureUvs.prototype.set = function (frame, baseFrame, rotate)
  17635. {
  17636. var tw = baseFrame.width;
  17637. var th = baseFrame.height;
  17638. if(rotate)
  17639. {
  17640. //width and height div 2 div baseFrame size
  17641. var swapWidthHeight = GroupD8.isSwapWidthHeight(rotate);
  17642. var w2 = (swapWidthHeight ? frame.height : frame.width) / 2 / tw;
  17643. var h2 = (swapWidthHeight ? frame.width : frame.height) / 2 / th;
  17644. //coordinates of center
  17645. var cX = frame.x / tw + w2;
  17646. var cY = frame.y / th + h2;
  17647. rotate = GroupD8.add(rotate, GroupD8.NW); //NW is top-left corner
  17648. this.x0 = cX + w2 * GroupD8.uX(rotate);
  17649. this.y0 = cY + h2 * GroupD8.uY(rotate);
  17650. rotate = GroupD8.add(rotate, 2); //rotate 90 degrees clockwise
  17651. this.x1 = cX + w2 * GroupD8.uX(rotate);
  17652. this.y1 = cY + h2 * GroupD8.uY(rotate);
  17653. rotate = GroupD8.add(rotate, 2);
  17654. this.x2 = cX + w2 * GroupD8.uX(rotate);
  17655. this.y2 = cY + h2 * GroupD8.uY(rotate);
  17656. rotate = GroupD8.add(rotate, 2);
  17657. this.x3 = cX + w2 * GroupD8.uX(rotate);
  17658. this.y3 = cY + h2 * GroupD8.uY(rotate);
  17659. }
  17660. else
  17661. {
  17662. this.x0 = frame.x / tw;
  17663. this.y0 = frame.y / th;
  17664. this.x1 = (frame.x + frame.width) / tw;
  17665. this.y1 = frame.y / th;
  17666. this.x2 = (frame.x + frame.width) / tw;
  17667. this.y2 = (frame.y + frame.height) / th;
  17668. this.x3 = frame.x / tw;
  17669. this.y3 = (frame.y + frame.height) / th;
  17670. }
  17671. };
  17672. },{"../math/GroupD8":30}],74:[function(require,module,exports){
  17673. var BaseTexture = require('./BaseTexture'),
  17674. utils = require('../utils');
  17675. /**
  17676. * A texture of a [playing] Video.
  17677. *
  17678. * Video base textures mimic Pixi BaseTexture.from.... method in their creation process.
  17679. *
  17680. * This can be used in several ways, such as:
  17681. *
  17682. * ```js
  17683. * var texture = PIXI.VideoBaseTexture.fromUrl('http://mydomain.com/video.mp4');
  17684. *
  17685. * var texture = PIXI.VideoBaseTexture.fromUrl({ src: 'http://mydomain.com/video.mp4', mime: 'video/mp4' });
  17686. *
  17687. * var texture = PIXI.VideoBaseTexture.fromUrls(['/video.webm', '/video.mp4']);
  17688. *
  17689. * var texture = PIXI.VideoBaseTexture.fromUrls([
  17690. * { src: '/video.webm', mime: 'video/webm' },
  17691. * { src: '/video.mp4', mime: 'video/mp4' }
  17692. * ]);
  17693. * ```
  17694. *
  17695. * See the ["deus" demo](http://www.goodboydigital.com/pixijs/examples/deus/).
  17696. *
  17697. * @class
  17698. * @extends PIXI.BaseTexture
  17699. * @memberof PIXI
  17700. * @param source {HTMLVideoElement}
  17701. * @param [scaleMode] {number} See {@link PIXI.SCALE_MODES} for possible values
  17702. */
  17703. function VideoBaseTexture(source, scaleMode)
  17704. {
  17705. if (!source)
  17706. {
  17707. throw new Error('No video source element specified.');
  17708. }
  17709. // hook in here to check if video is already available.
  17710. // BaseTexture looks for a source.complete boolean, plus width & height.
  17711. if ((source.readyState === source.HAVE_ENOUGH_DATA || source.readyState === source.HAVE_FUTURE_DATA) && source.width && source.height)
  17712. {
  17713. source.complete = true;
  17714. }
  17715. BaseTexture.call(this, source, scaleMode);
  17716. /**
  17717. * Should the base texture automatically update itself, set to true by default
  17718. *
  17719. * @member {boolean}
  17720. * @default true
  17721. */
  17722. this.autoUpdate = false;
  17723. this._onUpdate = this._onUpdate.bind(this);
  17724. this._onCanPlay = this._onCanPlay.bind(this);
  17725. if (!source.complete)
  17726. {
  17727. source.addEventListener('canplay', this._onCanPlay);
  17728. source.addEventListener('canplaythrough', this._onCanPlay);
  17729. // started playing..
  17730. source.addEventListener('play', this._onPlayStart.bind(this));
  17731. source.addEventListener('pause', this._onPlayStop.bind(this));
  17732. }
  17733. this.__loaded = false;
  17734. }
  17735. VideoBaseTexture.prototype = Object.create(BaseTexture.prototype);
  17736. VideoBaseTexture.prototype.constructor = VideoBaseTexture;
  17737. module.exports = VideoBaseTexture;
  17738. /**
  17739. * The internal update loop of the video base texture, only runs when autoUpdate is set to true
  17740. *
  17741. * @private
  17742. */
  17743. VideoBaseTexture.prototype._onUpdate = function ()
  17744. {
  17745. if (this.autoUpdate)
  17746. {
  17747. window.requestAnimationFrame(this._onUpdate);
  17748. this.update();
  17749. }
  17750. };
  17751. /**
  17752. * Runs the update loop when the video is ready to play
  17753. *
  17754. * @private
  17755. */
  17756. VideoBaseTexture.prototype._onPlayStart = function ()
  17757. {
  17758. if (!this.autoUpdate)
  17759. {
  17760. window.requestAnimationFrame(this._onUpdate);
  17761. this.autoUpdate = true;
  17762. }
  17763. };
  17764. /**
  17765. * Fired when a pause event is triggered, stops the update loop
  17766. *
  17767. * @private
  17768. */
  17769. VideoBaseTexture.prototype._onPlayStop = function ()
  17770. {
  17771. this.autoUpdate = false;
  17772. };
  17773. /**
  17774. * Fired when the video is loaded and ready to play
  17775. *
  17776. * @private
  17777. */
  17778. VideoBaseTexture.prototype._onCanPlay = function ()
  17779. {
  17780. this.hasLoaded = true;
  17781. if (this.source)
  17782. {
  17783. this.source.removeEventListener('canplay', this._onCanPlay);
  17784. this.source.removeEventListener('canplaythrough', this._onCanPlay);
  17785. this.width = this.source.videoWidth;
  17786. this.height = this.source.videoHeight;
  17787. this.source.play();
  17788. // prevent multiple loaded dispatches..
  17789. if (!this.__loaded)
  17790. {
  17791. this.__loaded = true;
  17792. this.emit('loaded', this);
  17793. }
  17794. }
  17795. };
  17796. /**
  17797. * Destroys this texture
  17798. *
  17799. */
  17800. VideoBaseTexture.prototype.destroy = function ()
  17801. {
  17802. if (this.source && this.source._pixiId)
  17803. {
  17804. delete utils.BaseTextureCache[ this.source._pixiId ];
  17805. delete this.source._pixiId;
  17806. }
  17807. BaseTexture.prototype.destroy.call(this);
  17808. };
  17809. /**
  17810. * Mimic Pixi BaseTexture.from.... method.
  17811. *
  17812. * @static
  17813. * @param video {HTMLVideoElement}
  17814. * @param scaleMode {number} See {@link PIXI.SCALE_MODES} for possible values
  17815. * @return {PIXI.VideoBaseTexture}
  17816. */
  17817. VideoBaseTexture.fromVideo = function (video, scaleMode)
  17818. {
  17819. if (!video._pixiId)
  17820. {
  17821. video._pixiId = 'video_' + utils.uid();
  17822. }
  17823. var baseTexture = utils.BaseTextureCache[video._pixiId];
  17824. if (!baseTexture)
  17825. {
  17826. baseTexture = new VideoBaseTexture(video, scaleMode);
  17827. utils.BaseTextureCache[ video._pixiId ] = baseTexture;
  17828. }
  17829. return baseTexture;
  17830. };
  17831. /**
  17832. * Helper function that creates a new BaseTexture based on the given video element.
  17833. * This BaseTexture can then be used to create a texture
  17834. *
  17835. * @static
  17836. * @param videoSrc {string|object|string[]|object[]} The URL(s) for the video.
  17837. * @param [videoSrc.src] {string} One of the source urls for the video
  17838. * @param [videoSrc.mime] {string} The mimetype of the video (e.g. 'video/mp4'). If not specified
  17839. * the url's extension will be used as the second part of the mime type.
  17840. * @param scaleMode {number} See {@link PIXI.SCALE_MODES} for possible values
  17841. * @return {PIXI.VideoBaseTexture}
  17842. */
  17843. VideoBaseTexture.fromUrl = function (videoSrc, scaleMode)
  17844. {
  17845. var video = document.createElement('video');
  17846. // array of objects or strings
  17847. if (Array.isArray(videoSrc))
  17848. {
  17849. for (var i = 0; i < videoSrc.length; ++i)
  17850. {
  17851. video.appendChild(createSource(videoSrc[i].src || videoSrc[i], videoSrc[i].mime));
  17852. }
  17853. }
  17854. // single object or string
  17855. else
  17856. {
  17857. video.appendChild(createSource(videoSrc.src || videoSrc, videoSrc.mime));
  17858. }
  17859. video.load();
  17860. video.play();
  17861. return VideoBaseTexture.fromVideo(video, scaleMode);
  17862. };
  17863. VideoBaseTexture.fromUrls = VideoBaseTexture.fromUrl;
  17864. function createSource(path, type)
  17865. {
  17866. if (!type)
  17867. {
  17868. type = 'video/' + path.substr(path.lastIndexOf('.') + 1);
  17869. }
  17870. var source = document.createElement('source');
  17871. source.src = path;
  17872. source.type = type;
  17873. return source;
  17874. }
  17875. },{"../utils":77,"./BaseTexture":70}],75:[function(require,module,exports){
  17876. var CONST = require('../const'),
  17877. EventEmitter = require('eventemitter3'),
  17878. // Internal event used by composed emitter
  17879. TICK = 'tick';
  17880. /**
  17881. * A Ticker class that runs an update loop that other objects listen to.
  17882. * This class is composed around an EventEmitter object to add listeners
  17883. * meant for execution on the next requested animation frame.
  17884. * Animation frames are requested only when necessary,
  17885. * e.g. When the ticker is started and the emitter has listeners.
  17886. *
  17887. * @class
  17888. * @memberof PIXI.ticker
  17889. */
  17890. function Ticker()
  17891. {
  17892. var _this = this;
  17893. /**
  17894. * Internal tick method bound to ticker instance.
  17895. * This is because in early 2015, Function.bind
  17896. * is still 60% slower in high performance scenarios.
  17897. * Also separating frame requests from update method
  17898. * so listeners may be called at any time and with
  17899. * any animation API, just invoke ticker.update(time).
  17900. *
  17901. * @private
  17902. */
  17903. this._tick = function _tick(time) {
  17904. _this._requestId = null;
  17905. if (_this.started)
  17906. {
  17907. // Invoke listeners now
  17908. _this.update(time);
  17909. // Listener side effects may have modified ticker state.
  17910. if (_this.started && _this._requestId === null && _this._emitter.listeners(TICK, true))
  17911. {
  17912. _this._requestId = requestAnimationFrame(_this._tick);
  17913. }
  17914. }
  17915. };
  17916. /**
  17917. * Internal emitter used to fire 'tick' event
  17918. * @private
  17919. */
  17920. this._emitter = new EventEmitter();
  17921. /**
  17922. * Internal current frame request ID
  17923. * @private
  17924. */
  17925. this._requestId = null;
  17926. /**
  17927. * Internal value managed by minFPS property setter and getter.
  17928. * This is the maximum allowed milliseconds between updates.
  17929. * @private
  17930. */
  17931. this._maxElapsedMS = 100;
  17932. /**
  17933. * Whether or not this ticker should invoke the method
  17934. * {@link PIXI.ticker.Ticker#start} automatically
  17935. * when a listener is added.
  17936. *
  17937. * @member {boolean}
  17938. * @default false
  17939. */
  17940. this.autoStart = false;
  17941. /**
  17942. * Scalar time value from last frame to this frame.
  17943. * This value is capped by setting {@link PIXI.ticker.Ticker#minFPS}
  17944. * and is scaled with {@link PIXI.ticker.Ticker#speed}.
  17945. * **Note:** The cap may be exceeded by scaling.
  17946. *
  17947. * @member {number}
  17948. * @default 1
  17949. */
  17950. this.deltaTime = 1;
  17951. /**
  17952. * Time elapsed in milliseconds from last frame to this frame.
  17953. * Opposed to what the scalar {@link PIXI.ticker.Ticker#deltaTime}
  17954. * is based, this value is neither capped nor scaled.
  17955. * If the platform supports DOMHighResTimeStamp,
  17956. * this value will have a precision of 1 µs.
  17957. *
  17958. * @member {DOMHighResTimeStamp|number}
  17959. * @default 1 / TARGET_FPMS
  17960. */
  17961. this.elapsedMS = 1 / CONST.TARGET_FPMS; // default to target frame time
  17962. /**
  17963. * The last time {@link PIXI.ticker.Ticker#update} was invoked.
  17964. * This value is also reset internally outside of invoking
  17965. * update, but only when a new animation frame is requested.
  17966. * If the platform supports DOMHighResTimeStamp,
  17967. * this value will have a precision of 1 µs.
  17968. *
  17969. * @member {DOMHighResTimeStamp|number}
  17970. * @default 0
  17971. */
  17972. this.lastTime = 0;
  17973. /**
  17974. * Factor of current {@link PIXI.ticker.Ticker#deltaTime}.
  17975. * @example
  17976. * // Scales ticker.deltaTime to what would be
  17977. * // the equivalent of approximately 120 FPS
  17978. * ticker.speed = 2;
  17979. *
  17980. * @member {number}
  17981. * @default 1
  17982. */
  17983. this.speed = 1;
  17984. /**
  17985. * Whether or not this ticker has been started.
  17986. * `true` if {@link PIXI.ticker.Ticker#start} has been called.
  17987. * `false` if {@link PIXI.ticker.Ticker#stop} has been called.
  17988. * While `false`, this value may change to `true` in the
  17989. * event of {@link PIXI.ticker.Ticker#autoStart} being `true`
  17990. * and a listener is added.
  17991. *
  17992. * @member {boolean}
  17993. * @default false
  17994. */
  17995. this.started = false;
  17996. }
  17997. Object.defineProperties(Ticker.prototype, {
  17998. /**
  17999. * The frames per second at which this ticker is running.
  18000. * The default is approximately 60 in most modern browsers.
  18001. * **Note:** This does not factor in the value of
  18002. * {@link PIXI.ticker.Ticker#speed}, which is specific
  18003. * to scaling {@link PIXI.ticker.Ticker#deltaTime}.
  18004. *
  18005. * @member
  18006. * @memberof PIXI.ticker.Ticker#
  18007. * @readonly
  18008. */
  18009. FPS: {
  18010. get: function()
  18011. {
  18012. return 1000 / this.elapsedMS;
  18013. }
  18014. },
  18015. /**
  18016. * Manages the maximum amount of milliseconds allowed to
  18017. * elapse between invoking {@link PIXI.ticker.Ticker#update}.
  18018. * This value is used to cap {@link PIXI.ticker.Ticker#deltaTime},
  18019. * but does not effect the measured value of {@link PIXI.ticker.Ticker#FPS}.
  18020. * When setting this property it is clamped to a value between
  18021. * `0` and `PIXI.TARGET_FPMS * 1000`.
  18022. *
  18023. * @member
  18024. * @memberof PIXI.ticker.Ticker#
  18025. * @default 10
  18026. */
  18027. minFPS: {
  18028. get: function()
  18029. {
  18030. return 1000 / this._maxElapsedMS;
  18031. },
  18032. set: function(fps)
  18033. {
  18034. // Clamp: 0 to TARGET_FPMS
  18035. var minFPMS = Math.min(Math.max(0, fps) / 1000, CONST.TARGET_FPMS);
  18036. this._maxElapsedMS = 1 / minFPMS;
  18037. }
  18038. }
  18039. });
  18040. /**
  18041. * Conditionally requests a new animation frame.
  18042. * If a frame has not already been requested, and if the internal
  18043. * emitter has listeners, a new frame is requested.
  18044. *
  18045. * @private
  18046. */
  18047. Ticker.prototype._requestIfNeeded = function _requestIfNeeded()
  18048. {
  18049. if (this._requestId === null && this._emitter.listeners(TICK, true))
  18050. {
  18051. // ensure callbacks get correct delta
  18052. this.lastTime = performance.now();
  18053. this._requestId = requestAnimationFrame(this._tick);
  18054. }
  18055. };
  18056. /**
  18057. * Conditionally cancels a pending animation frame.
  18058. *
  18059. * @private
  18060. */
  18061. Ticker.prototype._cancelIfNeeded = function _cancelIfNeeded()
  18062. {
  18063. if (this._requestId !== null)
  18064. {
  18065. cancelAnimationFrame(this._requestId);
  18066. this._requestId = null;
  18067. }
  18068. };
  18069. /**
  18070. * Conditionally requests a new animation frame.
  18071. * If the ticker has been started it checks if a frame has not already
  18072. * been requested, and if the internal emitter has listeners. If these
  18073. * conditions are met, a new frame is requested. If the ticker has not
  18074. * been started, but autoStart is `true`, then the ticker starts now,
  18075. * and continues with the previous conditions to request a new frame.
  18076. *
  18077. * @private
  18078. */
  18079. Ticker.prototype._startIfPossible = function _startIfPossible()
  18080. {
  18081. if (this.started)
  18082. {
  18083. this._requestIfNeeded();
  18084. }
  18085. else if (this.autoStart)
  18086. {
  18087. this.start();
  18088. }
  18089. };
  18090. /**
  18091. * Calls {@link module:eventemitter3.EventEmitter#on} internally for the
  18092. * internal 'tick' event. It checks if the emitter has listeners,
  18093. * and if so it requests a new animation frame at this point.
  18094. *
  18095. * @param fn {Function} The listener function to be added for updates
  18096. * @param [context] {Function} The listener context
  18097. * @returns {PIXI.ticker.Ticker} this
  18098. */
  18099. Ticker.prototype.add = function add(fn, context)
  18100. {
  18101. this._emitter.on(TICK, fn, context);
  18102. this._startIfPossible();
  18103. return this;
  18104. };
  18105. /**
  18106. * Calls {@link module:eventemitter3.EventEmitter#once} internally for the
  18107. * internal 'tick' event. It checks if the emitter has listeners,
  18108. * and if so it requests a new animation frame at this point.
  18109. *
  18110. * @param fn {Function} The listener function to be added for one update
  18111. * @param [context] {Function} The listener context
  18112. * @returns {PIXI.ticker.Ticker} this
  18113. */
  18114. Ticker.prototype.addOnce = function addOnce(fn, context)
  18115. {
  18116. this._emitter.once(TICK, fn, context);
  18117. this._startIfPossible();
  18118. return this;
  18119. };
  18120. /**
  18121. * Calls {@link module:eventemitter3.EventEmitter#off} internally for 'tick' event.
  18122. * It checks if the emitter has listeners for 'tick' event.
  18123. * If it does, then it cancels the animation frame.
  18124. *
  18125. * @param [fn] {Function} The listener function to be removed
  18126. * @param [context] {Function} The listener context to be removed
  18127. * @returns {PIXI.ticker.Ticker} this
  18128. */
  18129. Ticker.prototype.remove = function remove(fn, context)
  18130. {
  18131. this._emitter.off(TICK, fn, context);
  18132. if (!this._emitter.listeners(TICK, true))
  18133. {
  18134. this._cancelIfNeeded();
  18135. }
  18136. return this;
  18137. };
  18138. /**
  18139. * Starts the ticker. If the ticker has listeners
  18140. * a new animation frame is requested at this point.
  18141. */
  18142. Ticker.prototype.start = function start()
  18143. {
  18144. if (!this.started)
  18145. {
  18146. this.started = true;
  18147. this._requestIfNeeded();
  18148. }
  18149. };
  18150. /**
  18151. * Stops the ticker. If the ticker has requested
  18152. * an animation frame it is canceled at this point.
  18153. */
  18154. Ticker.prototype.stop = function stop()
  18155. {
  18156. if (this.started)
  18157. {
  18158. this.started = false;
  18159. this._cancelIfNeeded();
  18160. }
  18161. };
  18162. /**
  18163. * Triggers an update. An update entails setting the
  18164. * current {@link PIXI.ticker.Ticker#elapsedMS},
  18165. * the current {@link PIXI.ticker.Ticker#deltaTime},
  18166. * invoking all listeners with current deltaTime,
  18167. * and then finally setting {@link PIXI.ticker.Ticker#lastTime}
  18168. * with the value of currentTime that was provided.
  18169. * This method will be called automatically by animation
  18170. * frame callbacks if the ticker instance has been started
  18171. * and listeners are added.
  18172. *
  18173. * @param [currentTime=performance.now()] {DOMHighResTimeStamp|number} the current time of execution
  18174. */
  18175. Ticker.prototype.update = function update(currentTime)
  18176. {
  18177. var elapsedMS;
  18178. // Allow calling update directly with default currentTime.
  18179. currentTime = currentTime || performance.now();
  18180. // Save uncapped elapsedMS for measurement
  18181. elapsedMS = this.elapsedMS = currentTime - this.lastTime;
  18182. // cap the milliseconds elapsed used for deltaTime
  18183. if (elapsedMS > this._maxElapsedMS)
  18184. {
  18185. elapsedMS = this._maxElapsedMS;
  18186. }
  18187. this.deltaTime = elapsedMS * CONST.TARGET_FPMS * this.speed;
  18188. // Invoke listeners added to internal emitter
  18189. this._emitter.emit(TICK, this.deltaTime);
  18190. this.lastTime = currentTime;
  18191. };
  18192. module.exports = Ticker;
  18193. },{"../const":22,"eventemitter3":10}],76:[function(require,module,exports){
  18194. var Ticker = require('./Ticker');
  18195. /**
  18196. * The shared ticker instance used by {@link PIXI.extras.MovieClip}.
  18197. * and by {@link PIXI.interaction.InteractionManager}.
  18198. * The property {@link PIXI.ticker.Ticker#autoStart} is set to `true`
  18199. * for this instance. Please follow the examples for usage, including
  18200. * how to opt-out of auto-starting the shared ticker.
  18201. *
  18202. * @example
  18203. * var ticker = PIXI.ticker.shared;
  18204. * // Set this to prevent starting this ticker when listeners are added.
  18205. * // By default this is true only for the PIXI.ticker.shared instance.
  18206. * ticker.autoStart = false;
  18207. * // FYI, call this to ensure the ticker is stopped. It should be stopped
  18208. * // if you have not attempted to render anything yet.
  18209. * ticker.stop();
  18210. * // Call this when you are ready for a running shared ticker.
  18211. * ticker.start();
  18212. *
  18213. * @example
  18214. * // You may use the shared ticker to render...
  18215. * var renderer = PIXI.autoDetectRenderer(800, 600);
  18216. * var stage = new PIXI.Container();
  18217. * var interactionManager = PIXI.interaction.InteractionManager(renderer);
  18218. * document.body.appendChild(renderer.view);
  18219. * ticker.add(function (time) {
  18220. * renderer.render(stage);
  18221. * });
  18222. *
  18223. * @example
  18224. * // Or you can just update it manually.
  18225. * ticker.autoStart = false;
  18226. * ticker.stop();
  18227. * function animate(time) {
  18228. * ticker.update(time);
  18229. * renderer.render(stage);
  18230. * requestAnimationFrame(animate);
  18231. * }
  18232. * animate(performance.now());
  18233. *
  18234. * @type {PIXI.ticker.Ticker}
  18235. * @memberof PIXI.ticker
  18236. */
  18237. var shared = new Ticker();
  18238. shared.autoStart = true;
  18239. /**
  18240. * @namespace PIXI.ticker
  18241. */
  18242. module.exports = {
  18243. shared: shared,
  18244. Ticker: Ticker
  18245. };
  18246. },{"./Ticker":75}],77:[function(require,module,exports){
  18247. var CONST = require('../const');
  18248. /**
  18249. * @namespace PIXI.utils
  18250. */
  18251. var utils = module.exports = {
  18252. _uid: 0,
  18253. _saidHello: false,
  18254. EventEmitter: require('eventemitter3'),
  18255. pluginTarget: require('./pluginTarget'),
  18256. async: require('async'),
  18257. /**
  18258. * Gets the next unique identifier
  18259. *
  18260. * @return {number} The next unique identifier to use.
  18261. */
  18262. uid: function ()
  18263. {
  18264. return ++utils._uid;
  18265. },
  18266. /**
  18267. * Converts a hex color number to an [R, G, B] array
  18268. *
  18269. * @param hex {number}
  18270. * @param {number[]} [out=[]]
  18271. * @return {number[]} An array representing the [R, G, B] of the color.
  18272. */
  18273. hex2rgb: function (hex, out)
  18274. {
  18275. out = out || [];
  18276. out[0] = (hex >> 16 & 0xFF) / 255;
  18277. out[1] = (hex >> 8 & 0xFF) / 255;
  18278. out[2] = (hex & 0xFF) / 255;
  18279. return out;
  18280. },
  18281. /**
  18282. * Converts a hex color number to a string.
  18283. *
  18284. * @param hex {number}
  18285. * @return {string} The string color.
  18286. */
  18287. hex2string: function (hex)
  18288. {
  18289. hex = hex.toString(16);
  18290. hex = '000000'.substr(0, 6 - hex.length) + hex;
  18291. return '#' + hex;
  18292. },
  18293. /**
  18294. * Converts a color as an [R, G, B] array to a hex number
  18295. *
  18296. * @param rgb {number[]}
  18297. * @return {number} The color number
  18298. */
  18299. rgb2hex: function (rgb)
  18300. {
  18301. return ((rgb[0]*255 << 16) + (rgb[1]*255 << 8) + rgb[2]*255);
  18302. },
  18303. /**
  18304. * Checks whether the Canvas BlendModes are supported by the current browser
  18305. *
  18306. * @return {boolean} whether they are supported
  18307. */
  18308. canUseNewCanvasBlendModes: function ()
  18309. {
  18310. if (typeof document === 'undefined')
  18311. {
  18312. return false;
  18313. }
  18314. var pngHead = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAABAQMAAADD8p2OAAAAA1BMVEX/';
  18315. var pngEnd = 'AAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==';
  18316. var magenta = new Image();
  18317. magenta.src = pngHead + 'AP804Oa6' + pngEnd;
  18318. var yellow = new Image();
  18319. yellow.src = pngHead + '/wCKxvRF' + pngEnd;
  18320. var canvas = document.createElement('canvas');
  18321. canvas.width = 6;
  18322. canvas.height = 1;
  18323. var context = canvas.getContext('2d');
  18324. context.globalCompositeOperation = 'multiply';
  18325. context.drawImage(magenta, 0, 0);
  18326. context.drawImage(yellow, 2, 0);
  18327. var data = context.getImageData(2,0,1,1).data;
  18328. return (data[0] === 255 && data[1] === 0 && data[2] === 0);
  18329. },
  18330. /**
  18331. * Given a number, this function returns the closest number that is a power of two
  18332. * this function is taken from Starling Framework as its pretty neat ;)
  18333. *
  18334. * @param number {number}
  18335. * @return {number} the closest number that is a power of two
  18336. */
  18337. getNextPowerOfTwo: function (number)
  18338. {
  18339. // see: http://en.wikipedia.org/wiki/Power_of_two#Fast_algorithm_to_check_if_a_positive_number_is_a_power_of_two
  18340. if (number > 0 && (number & (number - 1)) === 0)
  18341. {
  18342. return number;
  18343. }
  18344. else
  18345. {
  18346. var result = 1;
  18347. while (result < number)
  18348. {
  18349. result <<= 1;
  18350. }
  18351. return result;
  18352. }
  18353. },
  18354. /**
  18355. * checks if the given width and height make a power of two rectangle
  18356. *
  18357. * @param width {number}
  18358. * @param height {number}
  18359. * @return {boolean}
  18360. */
  18361. isPowerOfTwo: function (width, height)
  18362. {
  18363. return (width > 0 && (width & (width - 1)) === 0 && height > 0 && (height & (height - 1)) === 0);
  18364. },
  18365. /**
  18366. * get the resolution of an asset by looking for the prefix
  18367. * used by spritesheets and image urls
  18368. *
  18369. * @param url {string} the image path
  18370. * @return {number}
  18371. */
  18372. getResolutionOfUrl: function (url)
  18373. {
  18374. var resolution = CONST.RETINA_PREFIX.exec(url);
  18375. if (resolution)
  18376. {
  18377. return parseFloat(resolution[1]);
  18378. }
  18379. return 1;
  18380. },
  18381. /**
  18382. * Logs out the version and renderer information for this running instance of PIXI.
  18383. * If you don't want to see this message you can set `PIXI.utils._saidHello = true;`
  18384. * so the library thinks it already said it. Keep in mind that doing that will forever
  18385. * makes you a jerk face.
  18386. *
  18387. * @param {string} type - The string renderer type to log.
  18388. * @constant
  18389. * @static
  18390. */
  18391. sayHello: function (type)
  18392. {
  18393. if (utils._saidHello)
  18394. {
  18395. return;
  18396. }
  18397. if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1)
  18398. {
  18399. var args = [
  18400. '\n %c %c %c Pixi.js ' + CONST.VERSION + ' - ✰ ' + type + ' ✰ %c ' + ' %c ' + ' http://www.pixijs.com/ %c %c ♥%c♥%c♥ \n\n',
  18401. 'background: #ff66a5; padding:5px 0;',
  18402. 'background: #ff66a5; padding:5px 0;',
  18403. 'color: #ff66a5; background: #030307; padding:5px 0;',
  18404. 'background: #ff66a5; padding:5px 0;',
  18405. 'background: #ffc3dc; padding:5px 0;',
  18406. 'background: #ff66a5; padding:5px 0;',
  18407. 'color: #ff2424; background: #fff; padding:5px 0;',
  18408. 'color: #ff2424; background: #fff; padding:5px 0;',
  18409. 'color: #ff2424; background: #fff; padding:5px 0;'
  18410. ];
  18411. window.console.log.apply(console, args); //jshint ignore:line
  18412. }
  18413. else if (window.console)
  18414. {
  18415. window.console.log('Pixi.js ' + CONST.VERSION + ' - ' + type + ' - http://www.pixijs.com/'); //jshint ignore:line
  18416. }
  18417. utils._saidHello = true;
  18418. },
  18419. /**
  18420. * Helper for checking for webgl support
  18421. *
  18422. * @return {boolean}
  18423. */
  18424. isWebGLSupported: function ()
  18425. {
  18426. var contextOptions = { stencil: true };
  18427. try
  18428. {
  18429. if (!window.WebGLRenderingContext)
  18430. {
  18431. return false;
  18432. }
  18433. var canvas = document.createElement('canvas'),
  18434. gl = canvas.getContext('webgl', contextOptions) || canvas.getContext('experimental-webgl', contextOptions);
  18435. return !!(gl && gl.getContextAttributes().stencil);
  18436. }
  18437. catch (e)
  18438. {
  18439. return false;
  18440. }
  18441. },
  18442. /**
  18443. * Returns sign of number
  18444. *
  18445. * @param n {number}
  18446. * @returns {number} 0 if n is 0, -1 if n is negative, 1 if n i positive
  18447. */
  18448. sign: function (n)
  18449. {
  18450. return n ? (n < 0 ? -1 : 1) : 0;
  18451. },
  18452. /**
  18453. * removeItems
  18454. *
  18455. * @param {array} arr The target array
  18456. * @param {number} startIdx The index to begin removing from (inclusive)
  18457. * @param {number} removeCount How many items to remove
  18458. */
  18459. removeItems: function (arr, startIdx, removeCount)
  18460. {
  18461. var length = arr.length;
  18462. if (startIdx >= length || removeCount === 0)
  18463. {
  18464. return;
  18465. }
  18466. removeCount = (startIdx+removeCount > length ? length-startIdx : removeCount);
  18467. for (var i = startIdx, len = length-removeCount; i < len; ++i)
  18468. {
  18469. arr[i] = arr[i + removeCount];
  18470. }
  18471. arr.length = len;
  18472. },
  18473. /**
  18474. * @todo Describe property usage
  18475. * @private
  18476. */
  18477. TextureCache: {},
  18478. /**
  18479. * @todo Describe property usage
  18480. * @private
  18481. */
  18482. BaseTextureCache: {}
  18483. };
  18484. },{"../const":22,"./pluginTarget":78,"async":1,"eventemitter3":10}],78:[function(require,module,exports){
  18485. /**
  18486. * Mixins functionality to make an object have "plugins".
  18487. *
  18488. * @mixin
  18489. * @memberof PIXI.utils
  18490. * @param obj {object} The object to mix into.
  18491. * @example
  18492. * function MyObject() {}
  18493. *
  18494. * pluginTarget.mixin(MyObject);
  18495. */
  18496. function pluginTarget(obj)
  18497. {
  18498. obj.__plugins = {};
  18499. /**
  18500. * Adds a plugin to an object
  18501. *
  18502. * @param pluginName {string} The events that should be listed.
  18503. * @param ctor {Function} The constructor function for the plugin.
  18504. */
  18505. obj.registerPlugin = function (pluginName, ctor)
  18506. {
  18507. obj.__plugins[pluginName] = ctor;
  18508. };
  18509. /**
  18510. * Instantiates all the plugins of this object
  18511. *
  18512. */
  18513. obj.prototype.initPlugins = function ()
  18514. {
  18515. this.plugins = this.plugins || {};
  18516. for (var o in obj.__plugins)
  18517. {
  18518. this.plugins[o] = new (obj.__plugins[o])(this);
  18519. }
  18520. };
  18521. /**
  18522. * Removes all the plugins of this object
  18523. *
  18524. */
  18525. obj.prototype.destroyPlugins = function ()
  18526. {
  18527. for (var o in this.plugins)
  18528. {
  18529. this.plugins[o].destroy();
  18530. this.plugins[o] = null;
  18531. }
  18532. this.plugins = null;
  18533. };
  18534. }
  18535. module.exports = {
  18536. /**
  18537. * Mixes in the properties of the pluginTarget into another object
  18538. *
  18539. * @param object {object} The obj to mix into
  18540. */
  18541. mixin: function mixin(obj)
  18542. {
  18543. pluginTarget(obj);
  18544. }
  18545. };
  18546. },{}],79:[function(require,module,exports){
  18547. /*global console */
  18548. var core = require('./core'),
  18549. mesh = require('./mesh'),
  18550. extras = require('./extras'),
  18551. filters = require('./filters');
  18552. /**
  18553. * @class
  18554. * @private
  18555. * @name SpriteBatch
  18556. * @memberof PIXI
  18557. * @see PIXI.ParticleContainer
  18558. * @throws {ReferenceError} SpriteBatch does not exist any more, please use the new ParticleContainer instead.
  18559. * @deprecated since version 3.0.0
  18560. */
  18561. core.SpriteBatch = function()
  18562. {
  18563. throw new ReferenceError('SpriteBatch does not exist any more, please use the new ParticleContainer instead.');
  18564. };
  18565. /**
  18566. * @class
  18567. * @private
  18568. * @name AssetLoader
  18569. * @memberof PIXI
  18570. * @see PIXI.loaders.Loader
  18571. * @throws {ReferenceError} The loader system was overhauled in pixi v3, please see the new PIXI.loaders.Loader class.
  18572. * @deprecated since version 3.0.0
  18573. */
  18574. core.AssetLoader = function()
  18575. {
  18576. throw new ReferenceError('The loader system was overhauled in pixi v3, please see the new PIXI.loaders.Loader class.');
  18577. };
  18578. Object.defineProperties(core, {
  18579. /**
  18580. * @class
  18581. * @private
  18582. * @name Stage
  18583. * @memberof PIXI
  18584. * @see PIXI.Container
  18585. * @deprecated since version 3.0.0
  18586. */
  18587. Stage: {
  18588. get: function()
  18589. {
  18590. console.warn('You do not need to use a PIXI Stage any more, you can simply render any container.');
  18591. return core.Container;
  18592. }
  18593. },
  18594. /**
  18595. * @class
  18596. * @private
  18597. * @name DisplayObjectContainer
  18598. * @memberof PIXI
  18599. * @see PIXI.Container
  18600. * @deprecated since version 3.0.0
  18601. */
  18602. DisplayObjectContainer: {
  18603. get: function()
  18604. {
  18605. console.warn('DisplayObjectContainer has been shortened to Container, please use Container from now on.');
  18606. return core.Container;
  18607. }
  18608. },
  18609. /**
  18610. * @class
  18611. * @private
  18612. * @name Strip
  18613. * @memberof PIXI
  18614. * @see PIXI.mesh.Mesh
  18615. * @deprecated since version 3.0.0
  18616. */
  18617. Strip: {
  18618. get: function()
  18619. {
  18620. console.warn('The Strip class has been renamed to Mesh and moved to mesh.Mesh, please use mesh.Mesh from now on.');
  18621. return mesh.Mesh;
  18622. }
  18623. },
  18624. /**
  18625. * @class
  18626. * @private
  18627. * @name Rope
  18628. * @memberof PIXI
  18629. * @see PIXI.mesh.Rope
  18630. * @deprecated since version 3.0.0
  18631. */
  18632. Rope: {
  18633. get: function()
  18634. {
  18635. console.warn('The Rope class has been moved to mesh.Rope, please use mesh.Rope from now on.');
  18636. return mesh.Rope;
  18637. }
  18638. },
  18639. /**
  18640. * @class
  18641. * @private
  18642. * @name MovieClip
  18643. * @memberof PIXI
  18644. * @see PIXI.extras.MovieClip
  18645. * @deprecated since version 3.0.0
  18646. */
  18647. MovieClip: {
  18648. get: function()
  18649. {
  18650. console.warn('The MovieClip class has been moved to extras.MovieClip, please use extras.MovieClip from now on.');
  18651. return extras.MovieClip;
  18652. }
  18653. },
  18654. /**
  18655. * @class
  18656. * @private
  18657. * @name TilingSprite
  18658. * @memberof PIXI
  18659. * @see PIXI.extras.TilingSprite
  18660. * @deprecated since version 3.0.0
  18661. */
  18662. TilingSprite: {
  18663. get: function()
  18664. {
  18665. console.warn('The TilingSprite class has been moved to extras.TilingSprite, please use extras.TilingSprite from now on.');
  18666. return extras.TilingSprite;
  18667. }
  18668. },
  18669. /**
  18670. * @class
  18671. * @private
  18672. * @name BitmapText
  18673. * @memberof PIXI
  18674. * @see PIXI.extras.BitmapText
  18675. * @deprecated since version 3.0.0
  18676. */
  18677. BitmapText: {
  18678. get: function()
  18679. {
  18680. console.warn('The BitmapText class has been moved to extras.BitmapText, please use extras.BitmapText from now on.');
  18681. return extras.BitmapText;
  18682. }
  18683. },
  18684. /**
  18685. * @class
  18686. * @private
  18687. * @name blendModes
  18688. * @memberof PIXI
  18689. * @see PIXI.BLEND_MODES
  18690. * @deprecated since version 3.0.0
  18691. */
  18692. blendModes: {
  18693. get: function()
  18694. {
  18695. console.warn('The blendModes has been moved to BLEND_MODES, please use BLEND_MODES from now on.');
  18696. return core.BLEND_MODES;
  18697. }
  18698. },
  18699. /**
  18700. * @class
  18701. * @private
  18702. * @name scaleModes
  18703. * @memberof PIXI
  18704. * @see PIXI.SCALE_MODES
  18705. * @deprecated since version 3.0.0
  18706. */
  18707. scaleModes: {
  18708. get: function()
  18709. {
  18710. console.warn('The scaleModes has been moved to SCALE_MODES, please use SCALE_MODES from now on.');
  18711. return core.SCALE_MODES;
  18712. }
  18713. },
  18714. /**
  18715. * @class
  18716. * @private
  18717. * @name BaseTextureCache
  18718. * @memberof PIXI
  18719. * @see PIXI.utils.BaseTextureCache
  18720. * @deprecated since version 3.0.0
  18721. */
  18722. BaseTextureCache: {
  18723. get: function ()
  18724. {
  18725. console.warn('The BaseTextureCache class has been moved to utils.BaseTextureCache, please use utils.BaseTextureCache from now on.');
  18726. return core.utils.BaseTextureCache;
  18727. }
  18728. },
  18729. /**
  18730. * @class
  18731. * @private
  18732. * @name TextureCache
  18733. * @memberof PIXI
  18734. * @see PIXI.utils.TextureCache
  18735. * @deprecated since version 3.0.0
  18736. */
  18737. TextureCache: {
  18738. get: function ()
  18739. {
  18740. console.warn('The TextureCache class has been moved to utils.TextureCache, please use utils.TextureCache from now on.');
  18741. return core.utils.TextureCache;
  18742. }
  18743. },
  18744. /**
  18745. * @namespace
  18746. * @private
  18747. * @name math
  18748. * @memberof PIXI
  18749. * @see PIXI
  18750. * @deprecated since version 3.0.6
  18751. */
  18752. math: {
  18753. get: function ()
  18754. {
  18755. console.warn('The math namespace is deprecated, please access members already accessible on PIXI.');
  18756. return core;
  18757. }
  18758. }
  18759. });
  18760. /**
  18761. * @method
  18762. * @private
  18763. * @name PIXI.Sprite#setTexture
  18764. * @see PIXI.Sprite#texture
  18765. * @deprecated since version 3.0.0
  18766. */
  18767. core.Sprite.prototype.setTexture = function(texture)
  18768. {
  18769. this.texture = texture;
  18770. console.warn('setTexture is now deprecated, please use the texture property, e.g : sprite.texture = texture;');
  18771. };
  18772. /**
  18773. * @method
  18774. * @name PIXI.extras.BitmapText#setText
  18775. * @see PIXI.extras.BitmapText#text
  18776. * @deprecated since version 3.0.0
  18777. */
  18778. extras.BitmapText.prototype.setText = function(text)
  18779. {
  18780. this.text = text;
  18781. console.warn('setText is now deprecated, please use the text property, e.g : myBitmapText.text = \'my text\';');
  18782. };
  18783. /**
  18784. * @method
  18785. * @name PIXI.Text#setText
  18786. * @see PIXI.Text#text
  18787. * @deprecated since version 3.0.0
  18788. */
  18789. core.Text.prototype.setText = function(text)
  18790. {
  18791. this.text = text;
  18792. console.warn('setText is now deprecated, please use the text property, e.g : myText.text = \'my text\';');
  18793. };
  18794. /**
  18795. * @method
  18796. * @name PIXI.Text#setStyle
  18797. * @see PIXI.Text#style
  18798. * @deprecated since version 3.0.0
  18799. */
  18800. core.Text.prototype.setStyle = function(style)
  18801. {
  18802. this.style = style;
  18803. console.warn('setStyle is now deprecated, please use the style property, e.g : myText.style = style;');
  18804. };
  18805. /**
  18806. * @method
  18807. * @name PIXI.Texture#setFrame
  18808. * @see PIXI.Texture#setFrame
  18809. * @deprecated since version 3.0.0
  18810. */
  18811. core.Texture.prototype.setFrame = function(frame)
  18812. {
  18813. this.frame = frame;
  18814. console.warn('setFrame is now deprecated, please use the frame property, e.g : myTexture.frame = frame;');
  18815. };
  18816. Object.defineProperties(filters, {
  18817. /**
  18818. * @class
  18819. * @private
  18820. * @name PIXI.filters.AbstractFilter
  18821. * @see PIXI.AbstractFilter
  18822. * @deprecated since version 3.0.6
  18823. */
  18824. AbstractFilter: {
  18825. get: function()
  18826. {
  18827. console.warn('filters.AbstractFilter is an undocumented alias, please use AbstractFilter from now on.');
  18828. return core.AbstractFilter;
  18829. }
  18830. },
  18831. /**
  18832. * @class
  18833. * @private
  18834. * @name PIXI.filters.FXAAFilter
  18835. * @see PIXI.FXAAFilter
  18836. * @deprecated since version 3.0.6
  18837. */
  18838. FXAAFilter: {
  18839. get: function()
  18840. {
  18841. console.warn('filters.FXAAFilter is an undocumented alias, please use FXAAFilter from now on.');
  18842. return core.FXAAFilter;
  18843. }
  18844. },
  18845. /**
  18846. * @class
  18847. * @private
  18848. * @name PIXI.filters.SpriteMaskFilter
  18849. * @see PIXI.SpriteMaskFilter
  18850. * @deprecated since version 3.0.6
  18851. */
  18852. SpriteMaskFilter: {
  18853. get: function()
  18854. {
  18855. console.warn('filters.SpriteMaskFilter is an undocumented alias, please use SpriteMaskFilter from now on.');
  18856. return core.SpriteMaskFilter;
  18857. }
  18858. }
  18859. });
  18860. /**
  18861. * @method
  18862. * @name PIXI.utils.uuid
  18863. * @see PIXI.utils.uid
  18864. * @deprecated since version 3.0.6
  18865. */
  18866. core.utils.uuid = function ()
  18867. {
  18868. console.warn('utils.uuid() is deprecated, please use utils.uid() from now on.');
  18869. return core.utils.uid();
  18870. };
  18871. },{"./core":29,"./extras":86,"./filters":103,"./mesh":128}],80:[function(require,module,exports){
  18872. var core = require('../core');
  18873. /**
  18874. * A BitmapText object will create a line or multiple lines of text using bitmap font. To
  18875. * split a line you can use '\n', '\r' or '\r\n' in your string. You can generate the fnt files using:
  18876. *
  18877. * A BitmapText can only be created when the font is loaded
  18878. *
  18879. * ```js
  18880. * // in this case the font is in a file called 'desyrel.fnt'
  18881. * var bitmapText = new PIXI.extras.BitmapText("text using a fancy font!", {font: "35px Desyrel", align: "right"});
  18882. * ```
  18883. *
  18884. *
  18885. * http://www.angelcode.com/products/bmfont/ for windows or
  18886. * http://www.bmglyph.com/ for mac.
  18887. *
  18888. * @class
  18889. * @extends PIXI.Container
  18890. * @memberof PIXI.extras
  18891. * @param text {string} The copy that you would like the text to display
  18892. * @param style {object} The style parameters
  18893. * @param style.font {string|object} The font descriptor for the object, can be passed as a string of form
  18894. * "24px FontName" or "FontName" or as an object with explicit name/size properties.
  18895. * @param [style.font.name] {string} The bitmap font id
  18896. * @param [style.font.size] {number} The size of the font in pixels, e.g. 24
  18897. * @param [style.align='left'] {string} Alignment for multiline text ('left', 'center' or 'right'), does not affect
  18898. * single line text
  18899. * @param [style.tint=0xFFFFFF] {number} The tint color
  18900. */
  18901. function BitmapText(text, style)
  18902. {
  18903. core.Container.call(this);
  18904. style = style || {};
  18905. /**
  18906. * The width of the overall text, different from fontSize,
  18907. * which is defined in the style object
  18908. *
  18909. * @member {number}
  18910. * @readOnly
  18911. */
  18912. this.textWidth = 0;
  18913. /**
  18914. * The height of the overall text, different from fontSize,
  18915. * which is defined in the style object
  18916. *
  18917. * @member {number}
  18918. * @readOnly
  18919. */
  18920. this.textHeight = 0;
  18921. /**
  18922. * Private tracker for the letter sprite pool.
  18923. *
  18924. * @member {PIXI.Sprite[]}
  18925. * @private
  18926. */
  18927. this._glyphs = [];
  18928. /**
  18929. * Private tracker for the current style.
  18930. *
  18931. * @member {object}
  18932. * @private
  18933. */
  18934. this._font = {
  18935. tint: style.tint !== undefined ? style.tint : 0xFFFFFF,
  18936. align: style.align || 'left',
  18937. name: null,
  18938. size: 0
  18939. };
  18940. /**
  18941. * Private tracker for the current font.
  18942. *
  18943. * @member {object}
  18944. * @private
  18945. */
  18946. this.font = style.font; // run font setter
  18947. /**
  18948. * Private tracker for the current text.
  18949. *
  18950. * @member {string}
  18951. * @private
  18952. */
  18953. this._text = text;
  18954. /**
  18955. * The max width of this bitmap text in pixels. If the text provided is longer than the value provided, line breaks will be automatically inserted in the last whitespace.
  18956. * Disable by setting value to 0
  18957. *
  18958. * @member {number}
  18959. */
  18960. this.maxWidth = 0;
  18961. /**
  18962. * The max line height. This is useful when trying to use the total height of the Text, ie: when trying to vertically align.
  18963. *
  18964. * @member {number}
  18965. */
  18966. this.maxLineHeight = 0;
  18967. /**
  18968. * The dirty state of this object.
  18969. *
  18970. * @member {boolean}
  18971. */
  18972. this.dirty = false;
  18973. this.updateText();
  18974. }
  18975. // constructor
  18976. BitmapText.prototype = Object.create(core.Container.prototype);
  18977. BitmapText.prototype.constructor = BitmapText;
  18978. module.exports = BitmapText;
  18979. Object.defineProperties(BitmapText.prototype, {
  18980. /**
  18981. * The tint of the BitmapText object
  18982. *
  18983. * @member {number}
  18984. * @memberof PIXI.extras.BitmapText#
  18985. */
  18986. tint: {
  18987. get: function ()
  18988. {
  18989. return this._font.tint;
  18990. },
  18991. set: function (value)
  18992. {
  18993. this._font.tint = (typeof value === 'number' && value >= 0) ? value : 0xFFFFFF;
  18994. this.dirty = true;
  18995. }
  18996. },
  18997. /**
  18998. * The alignment of the BitmapText object
  18999. *
  19000. * @member {string}
  19001. * @default 'left'
  19002. * @memberof PIXI.extras.BitmapText#
  19003. */
  19004. align: {
  19005. get: function ()
  19006. {
  19007. return this._font.align;
  19008. },
  19009. set: function (value)
  19010. {
  19011. this._font.align = value || 'left';
  19012. this.dirty = true;
  19013. }
  19014. },
  19015. /**
  19016. * The font descriptor of the BitmapText object
  19017. *
  19018. * @member {Font}
  19019. * @memberof PIXI.extras.BitmapText#
  19020. */
  19021. font: {
  19022. get: function ()
  19023. {
  19024. return this._font;
  19025. },
  19026. set: function (value)
  19027. {
  19028. if (!value) {
  19029. return;
  19030. }
  19031. if (typeof value === 'string') {
  19032. value = value.split(' ');
  19033. this._font.name = value.length === 1 ? value[0] : value.slice(1).join(' ');
  19034. this._font.size = value.length >= 2 ? parseInt(value[0], 10) : BitmapText.fonts[this._font.name].size;
  19035. }
  19036. else {
  19037. this._font.name = value.name;
  19038. this._font.size = typeof value.size === 'number' ? value.size : parseInt(value.size, 10);
  19039. }
  19040. this.dirty = true;
  19041. }
  19042. },
  19043. /**
  19044. * The text of the BitmapText object
  19045. *
  19046. * @member {string}
  19047. * @memberof PIXI.extras.BitmapText#
  19048. */
  19049. text: {
  19050. get: function ()
  19051. {
  19052. return this._text;
  19053. },
  19054. set: function (value)
  19055. {
  19056. value = value.toString() || ' ';
  19057. if (this._text === value)
  19058. {
  19059. return;
  19060. }
  19061. this._text = value;
  19062. this.dirty = true;
  19063. }
  19064. }
  19065. });
  19066. /**
  19067. * Renders text and updates it when needed
  19068. *
  19069. * @private
  19070. */
  19071. BitmapText.prototype.updateText = function ()
  19072. {
  19073. var data = BitmapText.fonts[this._font.name];
  19074. var pos = new core.Point();
  19075. var prevCharCode = null;
  19076. var chars = [];
  19077. var lastLineWidth = 0;
  19078. var maxLineWidth = 0;
  19079. var lineWidths = [];
  19080. var line = 0;
  19081. var scale = this._font.size / data.size;
  19082. var lastSpace = -1;
  19083. var maxLineHeight = 0;
  19084. for (var i = 0; i < this.text.length; i++)
  19085. {
  19086. var charCode = this.text.charCodeAt(i);
  19087. lastSpace = /(\s)/.test(this.text.charAt(i)) ? i : lastSpace;
  19088. if (/(?:\r\n|\r|\n)/.test(this.text.charAt(i)))
  19089. {
  19090. lineWidths.push(lastLineWidth);
  19091. maxLineWidth = Math.max(maxLineWidth, lastLineWidth);
  19092. line++;
  19093. pos.x = 0;
  19094. pos.y += data.lineHeight;
  19095. prevCharCode = null;
  19096. continue;
  19097. }
  19098. if (lastSpace !== -1 && this.maxWidth > 0 && pos.x * scale > this.maxWidth)
  19099. {
  19100. core.utils.removeItems(chars, lastSpace, i - lastSpace);
  19101. i = lastSpace;
  19102. lastSpace = -1;
  19103. lineWidths.push(lastLineWidth);
  19104. maxLineWidth = Math.max(maxLineWidth, lastLineWidth);
  19105. line++;
  19106. pos.x = 0;
  19107. pos.y += data.lineHeight;
  19108. prevCharCode = null;
  19109. continue;
  19110. }
  19111. var charData = data.chars[charCode];
  19112. if (!charData)
  19113. {
  19114. continue;
  19115. }
  19116. if (prevCharCode && charData.kerning[prevCharCode])
  19117. {
  19118. pos.x += charData.kerning[prevCharCode];
  19119. }
  19120. chars.push({texture:charData.texture, line: line, charCode: charCode, position: new core.Point(pos.x + charData.xOffset, pos.y + charData.yOffset)});
  19121. lastLineWidth = pos.x + (charData.texture.width + charData.xOffset);
  19122. pos.x += charData.xAdvance;
  19123. maxLineHeight = Math.max(maxLineHeight, (charData.yOffset + charData.texture.height));
  19124. prevCharCode = charCode;
  19125. }
  19126. lineWidths.push(lastLineWidth);
  19127. maxLineWidth = Math.max(maxLineWidth, lastLineWidth);
  19128. var lineAlignOffsets = [];
  19129. for (i = 0; i <= line; i++)
  19130. {
  19131. var alignOffset = 0;
  19132. if (this._font.align === 'right')
  19133. {
  19134. alignOffset = maxLineWidth - lineWidths[i];
  19135. }
  19136. else if (this._font.align === 'center')
  19137. {
  19138. alignOffset = (maxLineWidth - lineWidths[i]) / 2;
  19139. }
  19140. lineAlignOffsets.push(alignOffset);
  19141. }
  19142. var lenChars = chars.length;
  19143. var tint = this.tint;
  19144. for (i = 0; i < lenChars; i++)
  19145. {
  19146. var c = this._glyphs[i]; // get the next glyph sprite
  19147. if (c)
  19148. {
  19149. c.texture = chars[i].texture;
  19150. }
  19151. else
  19152. {
  19153. c = new core.Sprite(chars[i].texture);
  19154. this._glyphs.push(c);
  19155. }
  19156. c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale;
  19157. c.position.y = chars[i].position.y * scale;
  19158. c.scale.x = c.scale.y = scale;
  19159. c.tint = tint;
  19160. if (!c.parent)
  19161. {
  19162. this.addChild(c);
  19163. }
  19164. }
  19165. // remove unnecessary children.
  19166. for (i = lenChars; i < this._glyphs.length; ++i)
  19167. {
  19168. this.removeChild(this._glyphs[i]);
  19169. }
  19170. this.textWidth = maxLineWidth * scale;
  19171. this.textHeight = (pos.y + data.lineHeight) * scale;
  19172. this.maxLineHeight = maxLineHeight * scale;
  19173. };
  19174. /**
  19175. * Updates the transform of this object
  19176. *
  19177. * @private
  19178. */
  19179. BitmapText.prototype.updateTransform = function ()
  19180. {
  19181. this.validate();
  19182. this.containerUpdateTransform();
  19183. };
  19184. /**
  19185. * Validates text before calling parent's getLocalBounds
  19186. *
  19187. * @return {PIXI.Rectangle} The rectangular bounding area
  19188. */
  19189. BitmapText.prototype.getLocalBounds = function()
  19190. {
  19191. this.validate();
  19192. return core.Container.prototype.getLocalBounds.call(this);
  19193. };
  19194. /**
  19195. * Updates text when needed
  19196. *
  19197. * @private
  19198. */
  19199. BitmapText.prototype.validate = function()
  19200. {
  19201. if (this.dirty)
  19202. {
  19203. this.updateText();
  19204. this.dirty = false;
  19205. }
  19206. };
  19207. BitmapText.fonts = {};
  19208. },{"../core":29}],81:[function(require,module,exports){
  19209. var core = require('../core');
  19210. /**
  19211. * A MovieClip is a simple way to display an animation depicted by a list of textures.
  19212. *
  19213. * ```js
  19214. * var alienImages = ["image_sequence_01.png","image_sequence_02.png","image_sequence_03.png","image_sequence_04.png"];
  19215. * var textureArray = [];
  19216. *
  19217. * for (var i=0; i < 4; i++)
  19218. * {
  19219. * var texture = PIXI.Texture.fromImage(alienImages[i]);
  19220. * textureArray.push(texture);
  19221. * };
  19222. *
  19223. * var mc = new PIXI.MovieClip(textureArray);
  19224. * ```
  19225. *
  19226. * @class
  19227. * @extends PIXI.Sprite
  19228. * @memberof PIXI.extras
  19229. * @param textures {PIXI.Texture[]|Object[]} an array of {@link PIXI.Texture} or frame objects that make up the animation
  19230. * @param textures[].texture {PIXI.Texture} the {@link PIXI.Texture} of the frame
  19231. * @param textures[].time {number} the duration of the frame in ms
  19232. */
  19233. function MovieClip(textures)
  19234. {
  19235. core.Sprite.call(this, textures[0] instanceof core.Texture ? textures[0] : textures[0].texture);
  19236. /**
  19237. * @private
  19238. */
  19239. this._textures = null;
  19240. /**
  19241. * @private
  19242. */
  19243. this._durations = null;
  19244. this.textures = textures;
  19245. /**
  19246. * The speed that the MovieClip will play at. Higher is faster, lower is slower
  19247. *
  19248. * @member {number}
  19249. * @default 1
  19250. */
  19251. this.animationSpeed = 1;
  19252. /**
  19253. * Whether or not the movie clip repeats after playing.
  19254. *
  19255. * @member {boolean}
  19256. * @default true
  19257. */
  19258. this.loop = true;
  19259. /**
  19260. * Function to call when a MovieClip finishes playing
  19261. *
  19262. * @method
  19263. * @memberof PIXI.extras.MovieClip#
  19264. */
  19265. this.onComplete = null;
  19266. /**
  19267. * Elapsed time since animation has been started, used internally to display current texture
  19268. *
  19269. * @member {number}
  19270. * @private
  19271. */
  19272. this._currentTime = 0;
  19273. /**
  19274. * Indicates if the MovieClip is currently playing
  19275. *
  19276. * @member {boolean}
  19277. * @readonly
  19278. */
  19279. this.playing = false;
  19280. }
  19281. // constructor
  19282. MovieClip.prototype = Object.create(core.Sprite.prototype);
  19283. MovieClip.prototype.constructor = MovieClip;
  19284. module.exports = MovieClip;
  19285. Object.defineProperties(MovieClip.prototype, {
  19286. /**
  19287. * totalFrames is the total number of frames in the MovieClip. This is the same as number of textures
  19288. * assigned to the MovieClip.
  19289. *
  19290. * @member {number}
  19291. * @memberof PIXI.extras.MovieClip#
  19292. * @default 0
  19293. * @readonly
  19294. */
  19295. totalFrames: {
  19296. get: function()
  19297. {
  19298. return this._textures.length;
  19299. }
  19300. },
  19301. /**
  19302. * The array of textures used for this MovieClip
  19303. *
  19304. * @member {PIXI.Texture[]}
  19305. * @memberof PIXI.extras.MovieClip#
  19306. *
  19307. */
  19308. textures: {
  19309. get: function ()
  19310. {
  19311. return this._textures;
  19312. },
  19313. set: function (value)
  19314. {
  19315. if(value[0] instanceof core.Texture)
  19316. {
  19317. this._textures = value;
  19318. this._durations = null;
  19319. }
  19320. else
  19321. {
  19322. this._textures = [];
  19323. this._durations = [];
  19324. for(var i = 0; i < value.length; i++)
  19325. {
  19326. this._textures.push(value[i].texture);
  19327. this._durations.push(value[i].time);
  19328. }
  19329. }
  19330. }
  19331. },
  19332. /**
  19333. * The MovieClips current frame index
  19334. *
  19335. * @member {number}
  19336. * @memberof PIXI.extras.MovieClip#
  19337. * @readonly
  19338. */
  19339. currentFrame: {
  19340. get: function ()
  19341. {
  19342. var currentFrame = Math.floor(this._currentTime) % this._textures.length;
  19343. if (currentFrame < 0)
  19344. {
  19345. currentFrame += this._textures.length;
  19346. }
  19347. return currentFrame;
  19348. }
  19349. }
  19350. });
  19351. /**
  19352. * Stops the MovieClip
  19353. *
  19354. */
  19355. MovieClip.prototype.stop = function ()
  19356. {
  19357. if(!this.playing)
  19358. {
  19359. return;
  19360. }
  19361. this.playing = false;
  19362. core.ticker.shared.remove(this.update, this);
  19363. };
  19364. /**
  19365. * Plays the MovieClip
  19366. *
  19367. */
  19368. MovieClip.prototype.play = function ()
  19369. {
  19370. if(this.playing)
  19371. {
  19372. return;
  19373. }
  19374. this.playing = true;
  19375. core.ticker.shared.add(this.update, this);
  19376. };
  19377. /**
  19378. * Stops the MovieClip and goes to a specific frame
  19379. *
  19380. * @param frameNumber {number} frame index to stop at
  19381. */
  19382. MovieClip.prototype.gotoAndStop = function (frameNumber)
  19383. {
  19384. this.stop();
  19385. this._currentTime = frameNumber;
  19386. this._texture = this._textures[this.currentFrame];
  19387. };
  19388. /**
  19389. * Goes to a specific frame and begins playing the MovieClip
  19390. *
  19391. * @param frameNumber {number} frame index to start at
  19392. */
  19393. MovieClip.prototype.gotoAndPlay = function (frameNumber)
  19394. {
  19395. this._currentTime = frameNumber;
  19396. this.play();
  19397. };
  19398. /*
  19399. * Updates the object transform for rendering
  19400. * @private
  19401. */
  19402. MovieClip.prototype.update = function (deltaTime)
  19403. {
  19404. var elapsed = this.animationSpeed * deltaTime;
  19405. if (this._durations !== null)
  19406. {
  19407. var lag = this._currentTime % 1 * this._durations[this.currentFrame];
  19408. lag += elapsed / 60 * 1000;
  19409. while (lag < 0)
  19410. {
  19411. this._currentTime--;
  19412. lag += this._durations[this.currentFrame];
  19413. }
  19414. var sign = Math.sign(this.animationSpeed * deltaTime);
  19415. this._currentTime = Math.floor(this._currentTime);
  19416. while (lag >= this._durations[this.currentFrame])
  19417. {
  19418. lag -= this._durations[this.currentFrame] * sign;
  19419. this._currentTime += sign;
  19420. }
  19421. this._currentTime += lag / this._durations[this.currentFrame];
  19422. }
  19423. else
  19424. {
  19425. this._currentTime += elapsed;
  19426. }
  19427. if (this._currentTime < 0 && !this.loop)
  19428. {
  19429. this.gotoAndStop(0);
  19430. if (this.onComplete)
  19431. {
  19432. this.onComplete();
  19433. }
  19434. }
  19435. else if (this._currentTime >= this._textures.length && !this.loop)
  19436. {
  19437. this.gotoAndStop(this._textures.length - 1);
  19438. if (this.onComplete)
  19439. {
  19440. this.onComplete();
  19441. }
  19442. }
  19443. else
  19444. {
  19445. this._texture = this._textures[this.currentFrame];
  19446. }
  19447. };
  19448. /*
  19449. * Stops the MovieClip and destroys it
  19450. *
  19451. */
  19452. MovieClip.prototype.destroy = function ( )
  19453. {
  19454. this.stop();
  19455. core.Sprite.prototype.destroy.call(this);
  19456. };
  19457. /**
  19458. * A short hand way of creating a movieclip from an array of frame ids
  19459. *
  19460. * @static
  19461. * @param frames {string[]} the array of frames ids the movieclip will use as its texture frames
  19462. */
  19463. MovieClip.fromFrames = function (frames)
  19464. {
  19465. var textures = [];
  19466. for (var i = 0; i < frames.length; ++i)
  19467. {
  19468. textures.push(new core.Texture.fromFrame(frames[i]));
  19469. }
  19470. return new MovieClip(textures);
  19471. };
  19472. /**
  19473. * A short hand way of creating a movieclip from an array of image ids
  19474. *
  19475. * @static
  19476. * @param images {string[]} the array of image urls the movieclip will use as its texture frames
  19477. */
  19478. MovieClip.fromImages = function (images)
  19479. {
  19480. var textures = [];
  19481. for (var i = 0; i < images.length; ++i)
  19482. {
  19483. textures.push(new core.Texture.fromImage(images[i]));
  19484. }
  19485. return new MovieClip(textures);
  19486. };
  19487. },{"../core":29}],82:[function(require,module,exports){
  19488. var core = require('../core'),
  19489. // a sprite use dfor rendering textures..
  19490. tempPoint = new core.Point(),
  19491. CanvasTinter = require('../core/renderers/canvas/utils/CanvasTinter');
  19492. /**
  19493. * A tiling sprite is a fast way of rendering a tiling image
  19494. *
  19495. * @class
  19496. * @extends PIXI.Sprite
  19497. * @memberof PIXI.extras
  19498. * @param texture {Texture} the texture of the tiling sprite
  19499. * @param width {number} the width of the tiling sprite
  19500. * @param height {number} the height of the tiling sprite
  19501. */
  19502. function TilingSprite(texture, width, height)
  19503. {
  19504. core.Sprite.call(this, texture);
  19505. /**
  19506. * The scaling of the image that is being tiled
  19507. *
  19508. * @member {PIXI.Point}
  19509. */
  19510. this.tileScale = new core.Point(1,1);
  19511. /**
  19512. * The offset position of the image that is being tiled
  19513. *
  19514. * @member {PIXI.Point}
  19515. */
  19516. this.tilePosition = new core.Point(0,0);
  19517. ///// private
  19518. /**
  19519. * The with of the tiling sprite
  19520. *
  19521. * @member {number}
  19522. * @private
  19523. */
  19524. this._width = width || 100;
  19525. /**
  19526. * The height of the tiling sprite
  19527. *
  19528. * @member {number}
  19529. * @private
  19530. */
  19531. this._height = height || 100;
  19532. /**
  19533. * An internal WebGL UV cache.
  19534. *
  19535. * @member {PIXI.TextureUvs}
  19536. * @private
  19537. */
  19538. this._uvs = new core.TextureUvs();
  19539. this._canvasPattern = null;
  19540. //TODO move..
  19541. this.shader = new core.AbstractFilter(
  19542. [
  19543. 'precision lowp float;',
  19544. 'attribute vec2 aVertexPosition;',
  19545. 'attribute vec2 aTextureCoord;',
  19546. 'attribute vec4 aColor;',
  19547. 'uniform mat3 projectionMatrix;',
  19548. 'uniform vec4 uFrame;',
  19549. 'uniform vec4 uTransform;',
  19550. 'varying vec2 vTextureCoord;',
  19551. 'varying vec4 vColor;',
  19552. 'void main(void){',
  19553. ' gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);',
  19554. ' vec2 coord = aTextureCoord;',
  19555. ' coord -= uTransform.xy;',
  19556. ' coord /= uTransform.zw;',
  19557. ' vTextureCoord = coord;',
  19558. ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);',
  19559. '}'
  19560. ].join('\n'),
  19561. [
  19562. 'precision lowp float;',
  19563. 'varying vec2 vTextureCoord;',
  19564. 'varying vec4 vColor;',
  19565. 'uniform sampler2D uSampler;',
  19566. 'uniform vec4 uFrame;',
  19567. 'uniform vec2 uPixelSize;',
  19568. 'void main(void){',
  19569. ' vec2 coord = mod(vTextureCoord, uFrame.zw);',
  19570. ' coord = clamp(coord, uPixelSize, uFrame.zw - uPixelSize);',
  19571. ' coord += uFrame.xy;',
  19572. ' gl_FragColor = texture2D(uSampler, coord) * vColor ;',
  19573. '}'
  19574. ].join('\n'),
  19575. // set the uniforms
  19576. {
  19577. uFrame: { type: '4fv', value: [0,0,1,1] },
  19578. uTransform: { type: '4fv', value: [0,0,1,1] },
  19579. uPixelSize : { type : '2fv', value: [1, 1]}
  19580. }
  19581. );
  19582. }
  19583. TilingSprite.prototype = Object.create(core.Sprite.prototype);
  19584. TilingSprite.prototype.constructor = TilingSprite;
  19585. module.exports = TilingSprite;
  19586. Object.defineProperties(TilingSprite.prototype, {
  19587. /**
  19588. * The width of the sprite, setting this will actually modify the scale to achieve the value set
  19589. *
  19590. * @member {number}
  19591. * @memberof PIXI.extras.TilingSprite#
  19592. */
  19593. width: {
  19594. get: function ()
  19595. {
  19596. return this._width;
  19597. },
  19598. set: function (value)
  19599. {
  19600. this._width = value;
  19601. }
  19602. },
  19603. /**
  19604. * The height of the TilingSprite, setting this will actually modify the scale to achieve the value set
  19605. *
  19606. * @member {number}
  19607. * @memberof PIXI.extras.TilingSprite#
  19608. */
  19609. height: {
  19610. get: function ()
  19611. {
  19612. return this._height;
  19613. },
  19614. set: function (value)
  19615. {
  19616. this._height = value;
  19617. }
  19618. }
  19619. });
  19620. TilingSprite.prototype._onTextureUpdate = function ()
  19621. {
  19622. return;
  19623. };
  19624. /**
  19625. * Renders the object using the WebGL renderer
  19626. *
  19627. * @param renderer {PIXI.WebGLRenderer}
  19628. * @private
  19629. */
  19630. TilingSprite.prototype._renderWebGL = function (renderer)
  19631. {
  19632. // tweak our texture temporarily..
  19633. var texture = this._texture;
  19634. if(!texture || !texture._uvs)
  19635. {
  19636. return;
  19637. }
  19638. var tempUvs = texture._uvs,
  19639. tempWidth = texture._frame.width,
  19640. tempHeight = texture._frame.height,
  19641. tw = texture.baseTexture.width,
  19642. th = texture.baseTexture.height;
  19643. texture._uvs = this._uvs;
  19644. texture._frame.width = this.width;
  19645. texture._frame.height = this.height;
  19646. this.shader.uniforms.uPixelSize.value[0] = 1.0/tw;
  19647. this.shader.uniforms.uPixelSize.value[1] = 1.0/th;
  19648. this.shader.uniforms.uFrame.value[0] = tempUvs.x0;
  19649. this.shader.uniforms.uFrame.value[1] = tempUvs.y0;
  19650. this.shader.uniforms.uFrame.value[2] = tempUvs.x1 - tempUvs.x0;
  19651. this.shader.uniforms.uFrame.value[3] = tempUvs.y2 - tempUvs.y0;
  19652. this.shader.uniforms.uTransform.value[0] = (this.tilePosition.x % (tempWidth * this.tileScale.x)) / this._width;
  19653. this.shader.uniforms.uTransform.value[1] = (this.tilePosition.y % (tempHeight * this.tileScale.y)) / this._height;
  19654. this.shader.uniforms.uTransform.value[2] = ( tw / this._width ) * this.tileScale.x;
  19655. this.shader.uniforms.uTransform.value[3] = ( th / this._height ) * this.tileScale.y;
  19656. renderer.setObjectRenderer(renderer.plugins.sprite);
  19657. renderer.plugins.sprite.render(this);
  19658. texture._uvs = tempUvs;
  19659. texture._frame.width = tempWidth;
  19660. texture._frame.height = tempHeight;
  19661. };
  19662. /**
  19663. * Renders the object using the Canvas renderer
  19664. *
  19665. * @param renderer {PIXI.CanvasRenderer} a reference to the canvas renderer
  19666. * @private
  19667. */
  19668. TilingSprite.prototype._renderCanvas = function (renderer)
  19669. {
  19670. var texture = this._texture;
  19671. if (!texture.baseTexture.hasLoaded)
  19672. {
  19673. return;
  19674. }
  19675. var context = renderer.context,
  19676. transform = this.worldTransform,
  19677. resolution = renderer.resolution,
  19678. baseTexture = texture.baseTexture,
  19679. modX = (this.tilePosition.x / this.tileScale.x) % texture._frame.width,
  19680. modY = (this.tilePosition.y / this.tileScale.y) % texture._frame.height;
  19681. // create a nice shiny pattern!
  19682. // TODO this needs to be refreshed if texture changes..
  19683. if(!this._canvasPattern)
  19684. {
  19685. // cut an object from a spritesheet..
  19686. var tempCanvas = new core.CanvasBuffer(texture._frame.width * resolution, texture._frame.height * resolution);
  19687. // Tint the tiling sprite
  19688. if (this.tint !== 0xFFFFFF)
  19689. {
  19690. if (this.cachedTint !== this.tint)
  19691. {
  19692. this.cachedTint = this.tint;
  19693. this.tintedTexture = CanvasTinter.getTintedTexture(this, this.tint);
  19694. }
  19695. tempCanvas.context.drawImage(this.tintedTexture, 0, 0);
  19696. }
  19697. else
  19698. {
  19699. tempCanvas.context.drawImage(baseTexture.source, -texture._frame.x * resolution, -texture._frame.y * resolution);
  19700. }
  19701. this._canvasPattern = tempCanvas.context.createPattern( tempCanvas.canvas, 'repeat' );
  19702. }
  19703. // set context state..
  19704. context.globalAlpha = this.worldAlpha;
  19705. context.setTransform(transform.a * resolution,
  19706. transform.b * resolution,
  19707. transform.c * resolution,
  19708. transform.d * resolution,
  19709. transform.tx * resolution,
  19710. transform.ty * resolution);
  19711. // TODO - this should be rolled into the setTransform above..
  19712. context.scale(this.tileScale.x / resolution, this.tileScale.y / resolution);
  19713. context.translate(modX + (this.anchor.x * -this._width ),
  19714. modY + (this.anchor.y * -this._height));
  19715. // check blend mode
  19716. var compositeOperation = renderer.blendModes[this.blendMode];
  19717. if (compositeOperation !== renderer.context.globalCompositeOperation)
  19718. {
  19719. context.globalCompositeOperation = compositeOperation;
  19720. }
  19721. // fill the pattern!
  19722. context.fillStyle = this._canvasPattern;
  19723. context.fillRect(-modX,
  19724. -modY,
  19725. this._width * resolution / this.tileScale.x,
  19726. this._height * resolution / this.tileScale.y);
  19727. //TODO - pretty sure this can be deleted...
  19728. //context.translate(-this.tilePosition.x + (this.anchor.x * this._width), -this.tilePosition.y + (this.anchor.y * this._height));
  19729. //context.scale(1 / this.tileScale.x, 1 / this.tileScale.y);
  19730. };
  19731. /**
  19732. * Returns the framing rectangle of the sprite as a Rectangle object
  19733. *
  19734. * @return {PIXI.Rectangle} the framing rectangle
  19735. */
  19736. TilingSprite.prototype.getBounds = function ()
  19737. {
  19738. var width = this._width;
  19739. var height = this._height;
  19740. var w0 = width * (1-this.anchor.x);
  19741. var w1 = width * -this.anchor.x;
  19742. var h0 = height * (1-this.anchor.y);
  19743. var h1 = height * -this.anchor.y;
  19744. var worldTransform = this.worldTransform;
  19745. var a = worldTransform.a;
  19746. var b = worldTransform.b;
  19747. var c = worldTransform.c;
  19748. var d = worldTransform.d;
  19749. var tx = worldTransform.tx;
  19750. var ty = worldTransform.ty;
  19751. var x1 = a * w1 + c * h1 + tx;
  19752. var y1 = d * h1 + b * w1 + ty;
  19753. var x2 = a * w0 + c * h1 + tx;
  19754. var y2 = d * h1 + b * w0 + ty;
  19755. var x3 = a * w0 + c * h0 + tx;
  19756. var y3 = d * h0 + b * w0 + ty;
  19757. var x4 = a * w1 + c * h0 + tx;
  19758. var y4 = d * h0 + b * w1 + ty;
  19759. var minX,
  19760. maxX,
  19761. minY,
  19762. maxY;
  19763. minX = x1;
  19764. minX = x2 < minX ? x2 : minX;
  19765. minX = x3 < minX ? x3 : minX;
  19766. minX = x4 < minX ? x4 : minX;
  19767. minY = y1;
  19768. minY = y2 < minY ? y2 : minY;
  19769. minY = y3 < minY ? y3 : minY;
  19770. minY = y4 < minY ? y4 : minY;
  19771. maxX = x1;
  19772. maxX = x2 > maxX ? x2 : maxX;
  19773. maxX = x3 > maxX ? x3 : maxX;
  19774. maxX = x4 > maxX ? x4 : maxX;
  19775. maxY = y1;
  19776. maxY = y2 > maxY ? y2 : maxY;
  19777. maxY = y3 > maxY ? y3 : maxY;
  19778. maxY = y4 > maxY ? y4 : maxY;
  19779. var bounds = this._bounds;
  19780. bounds.x = minX;
  19781. bounds.width = maxX - minX;
  19782. bounds.y = minY;
  19783. bounds.height = maxY - minY;
  19784. // store a reference so that if this function gets called again in the render cycle we do not have to recalculate
  19785. this._currentBounds = bounds;
  19786. return bounds;
  19787. };
  19788. /**
  19789. * Checks if a point is inside this tiling sprite
  19790. * @param point {PIXI.Point} the point to check
  19791. */
  19792. TilingSprite.prototype.containsPoint = function( point )
  19793. {
  19794. this.worldTransform.applyInverse(point, tempPoint);
  19795. var width = this._width;
  19796. var height = this._height;
  19797. var x1 = -width * this.anchor.x;
  19798. var y1;
  19799. if ( tempPoint.x > x1 && tempPoint.x < x1 + width )
  19800. {
  19801. y1 = -height * this.anchor.y;
  19802. if ( tempPoint.y > y1 && tempPoint.y < y1 + height )
  19803. {
  19804. return true;
  19805. }
  19806. }
  19807. return false;
  19808. };
  19809. /**
  19810. * Destroys this tiling sprite
  19811. *
  19812. */
  19813. TilingSprite.prototype.destroy = function () {
  19814. core.Sprite.prototype.destroy.call(this);
  19815. this.tileScale = null;
  19816. this._tileScaleOffset = null;
  19817. this.tilePosition = null;
  19818. this._uvs = null;
  19819. };
  19820. /**
  19821. * Helper function that creates a tiling sprite that will use a texture from the TextureCache based on the frameId
  19822. * The frame ids are created when a Texture packer file has been loaded
  19823. *
  19824. * @static
  19825. * @param frameId {string} The frame Id of the texture in the cache
  19826. * @return {PIXI.extras.TilingSprite} A new TilingSprite using a texture from the texture cache matching the frameId
  19827. * @param width {number} the width of the tiling sprite
  19828. * @param height {number} the height of the tiling sprite
  19829. */
  19830. TilingSprite.fromFrame = function (frameId,width,height)
  19831. {
  19832. var texture = core.utils.TextureCache[frameId];
  19833. if (!texture)
  19834. {
  19835. throw new Error('The frameId "' + frameId + '" does not exist in the texture cache ' + this);
  19836. }
  19837. return new TilingSprite(texture,width,height);
  19838. };
  19839. /**
  19840. * Helper function that creates a sprite that will contain a texture based on an image url
  19841. * If the image is not in the texture cache it will be loaded
  19842. *
  19843. * @static
  19844. * @param imageId {string} The image url of the texture
  19845. * @param width {number} the width of the tiling sprite
  19846. * @param height {number} the height of the tiling sprite
  19847. * @param [crossorigin=(auto)] {boolean} if you want to specify the cross-origin parameter
  19848. * @param [scaleMode=PIXI.SCALE_MODES.DEFAULT] {number} if you want to specify the scale mode, see {@link PIXI.SCALE_MODES} for possible values
  19849. * @return {PIXI.extras.TilingSprite} A new TilingSprite using a texture from the texture cache matching the image id
  19850. */
  19851. TilingSprite.fromImage = function (imageId, width, height, crossorigin, scaleMode)
  19852. {
  19853. return new TilingSprite(core.Texture.fromImage(imageId, crossorigin, scaleMode),width,height);
  19854. };
  19855. },{"../core":29,"../core/renderers/canvas/utils/CanvasTinter":48}],83:[function(require,module,exports){
  19856. var core = require('../core'),
  19857. DisplayObject = core.DisplayObject,
  19858. _tempMatrix = new core.Matrix();
  19859. DisplayObject.prototype._cacheAsBitmap = false;
  19860. DisplayObject.prototype._originalRenderWebGL = null;
  19861. DisplayObject.prototype._originalRenderCanvas = null;
  19862. DisplayObject.prototype._originalUpdateTransform = null;
  19863. DisplayObject.prototype._originalHitTest = null;
  19864. DisplayObject.prototype._originalDestroy = null;
  19865. DisplayObject.prototype._cachedSprite = null;
  19866. Object.defineProperties(DisplayObject.prototype, {
  19867. /**
  19868. * Set this to true if you want this display object to be cached as a bitmap.
  19869. * This basically takes a snap shot of the display object as it is at that moment. It can provide a performance benefit for complex static displayObjects.
  19870. * To remove simply set this property to 'false'
  19871. *
  19872. * @member {boolean}
  19873. * @memberof PIXI.DisplayObject#
  19874. */
  19875. cacheAsBitmap: {
  19876. get: function ()
  19877. {
  19878. return this._cacheAsBitmap;
  19879. },
  19880. set: function (value)
  19881. {
  19882. if (this._cacheAsBitmap === value)
  19883. {
  19884. return;
  19885. }
  19886. this._cacheAsBitmap = value;
  19887. if (value)
  19888. {
  19889. this._originalRenderWebGL = this.renderWebGL;
  19890. this._originalRenderCanvas = this.renderCanvas;
  19891. this._originalUpdateTransform = this.updateTransform;
  19892. this._originalGetBounds = this.getBounds;
  19893. this._originalDestroy = this.destroy;
  19894. this._originalContainsPoint = this.containsPoint;
  19895. this.renderWebGL = this._renderCachedWebGL;
  19896. this.renderCanvas = this._renderCachedCanvas;
  19897. this.destroy = this._cacheAsBitmapDestroy;
  19898. }
  19899. else
  19900. {
  19901. if (this._cachedSprite)
  19902. {
  19903. this._destroyCachedDisplayObject();
  19904. }
  19905. this.renderWebGL = this._originalRenderWebGL;
  19906. this.renderCanvas = this._originalRenderCanvas;
  19907. this.getBounds = this._originalGetBounds;
  19908. this.destroy = this._originalDestroy;
  19909. this.updateTransform = this._originalUpdateTransform;
  19910. this.containsPoint = this._originalContainsPoint;
  19911. }
  19912. }
  19913. }
  19914. });
  19915. /**
  19916. * Renders a cached version of the sprite with WebGL
  19917. *
  19918. * @param renderer {PIXI.WebGLRenderer} the WebGL renderer
  19919. * @private
  19920. */
  19921. DisplayObject.prototype._renderCachedWebGL = function (renderer)
  19922. {
  19923. if (!this.visible || this.worldAlpha <= 0 || !this.renderable)
  19924. {
  19925. return;
  19926. }
  19927. this._initCachedDisplayObject( renderer );
  19928. this._cachedSprite.worldAlpha = this.worldAlpha;
  19929. renderer.setObjectRenderer(renderer.plugins.sprite);
  19930. renderer.plugins.sprite.render( this._cachedSprite );
  19931. };
  19932. /**
  19933. * Prepares the WebGL renderer to cache the sprite
  19934. *
  19935. * @param renderer {PIXI.WebGLRenderer} the WebGL renderer
  19936. * @private
  19937. */
  19938. DisplayObject.prototype._initCachedDisplayObject = function (renderer)
  19939. {
  19940. if(this._cachedSprite)
  19941. {
  19942. return;
  19943. }
  19944. // first we flush anything left in the renderer (otherwise it would get rendered to the cached texture)
  19945. renderer.currentRenderer.flush();
  19946. //this.filters= [];
  19947. // next we find the dimensions of the untransformed object
  19948. // this function also calls updatetransform on all its children as part of the measuring. This means we don't need to update the transform again in this function
  19949. // TODO pass an object to clone too? saves having to create a new one each time!
  19950. var bounds = this.getLocalBounds().clone();
  19951. // add some padding!
  19952. if(this._filters)
  19953. {
  19954. var padding = this._filters[0].padding;
  19955. bounds.x -= padding;
  19956. bounds.y -= padding;
  19957. bounds.width += padding * 2;
  19958. bounds.height += padding * 2;
  19959. }
  19960. // for now we cache the current renderTarget that the webGL renderer is currently using.
  19961. // this could be more elegent..
  19962. var cachedRenderTarget = renderer.currentRenderTarget;
  19963. // We also store the filter stack - I will definitely look to change how this works a little later down the line.
  19964. var stack = renderer.filterManager.filterStack;
  19965. // this renderTexture will be used to store the cached DisplayObject
  19966. var renderTexture = new core.RenderTexture(renderer, bounds.width | 0, bounds.height | 0);
  19967. // need to set //
  19968. var m = _tempMatrix;
  19969. m.tx = -bounds.x;
  19970. m.ty = -bounds.y;
  19971. // set all properties to there original so we can render to a texture
  19972. this.renderWebGL = this._originalRenderWebGL;
  19973. renderTexture.render(this, m, true, true);
  19974. // now restore the state be setting the new properties
  19975. renderer.setRenderTarget(cachedRenderTarget);
  19976. renderer.filterManager.filterStack = stack;
  19977. this.renderWebGL = this._renderCachedWebGL;
  19978. this.updateTransform = this.displayObjectUpdateTransform;
  19979. this.getBounds = this._getCachedBounds;
  19980. // create our cached sprite
  19981. this._cachedSprite = new core.Sprite(renderTexture);
  19982. this._cachedSprite.worldTransform = this.worldTransform;
  19983. this._cachedSprite.anchor.x = -( bounds.x / bounds.width );
  19984. this._cachedSprite.anchor.y = -( bounds.y / bounds.height );
  19985. // restore the transform of the cached sprite to avoid the nasty flicker..
  19986. this.updateTransform();
  19987. // map the hit test..
  19988. this.containsPoint = this._cachedSprite.containsPoint.bind(this._cachedSprite);
  19989. };
  19990. /**
  19991. * Renders a cached version of the sprite with canvas
  19992. *
  19993. * @param renderer {PIXI.CanvasRenderer} the Canvas renderer
  19994. * @private
  19995. */
  19996. DisplayObject.prototype._renderCachedCanvas = function (renderer)
  19997. {
  19998. if (!this.visible || this.worldAlpha <= 0 || !this.renderable)
  19999. {
  20000. return;
  20001. }
  20002. this._initCachedDisplayObjectCanvas( renderer );
  20003. this._cachedSprite.worldAlpha = this.worldAlpha;
  20004. this._cachedSprite.renderCanvas(renderer);
  20005. };
  20006. //TODO this can be the same as the webGL verison.. will need to do a little tweaking first though..
  20007. /**
  20008. * Prepares the Canvas renderer to cache the sprite
  20009. *
  20010. * @param renderer {PIXI.CanvasRenderer} the Canvas renderer
  20011. * @private
  20012. */
  20013. DisplayObject.prototype._initCachedDisplayObjectCanvas = function (renderer)
  20014. {
  20015. if(this._cachedSprite)
  20016. {
  20017. return;
  20018. }
  20019. //get bounds actually transforms the object for us already!
  20020. var bounds = this.getLocalBounds();
  20021. var cachedRenderTarget = renderer.context;
  20022. var renderTexture = new core.RenderTexture(renderer, bounds.width | 0, bounds.height | 0);
  20023. // need to set //
  20024. var m = _tempMatrix;
  20025. m.tx = -bounds.x;
  20026. m.ty = -bounds.y;
  20027. // set all properties to there original so we can render to a texture
  20028. this.renderCanvas = this._originalRenderCanvas;
  20029. renderTexture.render(this, m, true);
  20030. // now restore the state be setting the new properties
  20031. renderer.context = cachedRenderTarget;
  20032. this.renderCanvas = this._renderCachedCanvas;
  20033. this.updateTransform = this.displayObjectUpdateTransform;
  20034. this.getBounds = this._getCachedBounds;
  20035. // create our cached sprite
  20036. this._cachedSprite = new core.Sprite(renderTexture);
  20037. this._cachedSprite.worldTransform = this.worldTransform;
  20038. this._cachedSprite.anchor.x = -( bounds.x / bounds.width );
  20039. this._cachedSprite.anchor.y = -( bounds.y / bounds.height );
  20040. this.updateTransform();
  20041. this.containsPoint = this._cachedSprite.containsPoint.bind(this._cachedSprite);
  20042. };
  20043. /**
  20044. * Calculates the bounds of the cached sprite
  20045. *
  20046. * @private
  20047. */
  20048. DisplayObject.prototype._getCachedBounds = function ()
  20049. {
  20050. this._cachedSprite._currentBounds = null;
  20051. return this._cachedSprite.getBounds();
  20052. };
  20053. /**
  20054. * Destroys the cached sprite.
  20055. *
  20056. * @private
  20057. */
  20058. DisplayObject.prototype._destroyCachedDisplayObject = function ()
  20059. {
  20060. this._cachedSprite._texture.destroy();
  20061. this._cachedSprite = null;
  20062. };
  20063. DisplayObject.prototype._cacheAsBitmapDestroy = function ()
  20064. {
  20065. this.cacheAsBitmap = false;
  20066. this._originalDestroy();
  20067. };
  20068. },{"../core":29}],84:[function(require,module,exports){
  20069. var core = require('../core');
  20070. /**
  20071. * The instance name of the object.
  20072. *
  20073. * @memberof PIXI.DisplayObject#
  20074. * @member {string}
  20075. */
  20076. core.DisplayObject.prototype.name = null;
  20077. /**
  20078. * Returns the display object in the container
  20079. *
  20080. * @memberof PIXI.Container#
  20081. * @param name {string} instance name
  20082. * @return {PIXI.DisplayObject}
  20083. */
  20084. core.Container.prototype.getChildByName = function (name)
  20085. {
  20086. for (var i = 0; i < this.children.length; i++)
  20087. {
  20088. if (this.children[i].name === name)
  20089. {
  20090. return this.children[i];
  20091. }
  20092. }
  20093. return null;
  20094. };
  20095. },{"../core":29}],85:[function(require,module,exports){
  20096. var core = require('../core');
  20097. /**
  20098. * Returns the global position of the displayObject
  20099. *
  20100. * @memberof PIXI.DisplayObject#
  20101. * @param point {Point} the point to write the global value to. If null a new point will be returned
  20102. * @return {Point}
  20103. */
  20104. core.DisplayObject.prototype.getGlobalPosition = function (point)
  20105. {
  20106. point = point || new core.Point();
  20107. if(this.parent)
  20108. {
  20109. this.displayObjectUpdateTransform();
  20110. point.x = this.worldTransform.tx;
  20111. point.y = this.worldTransform.ty;
  20112. }
  20113. else
  20114. {
  20115. point.x = this.position.x;
  20116. point.y = this.position.y;
  20117. }
  20118. return point;
  20119. };
  20120. },{"../core":29}],86:[function(require,module,exports){
  20121. /**
  20122. * @file Main export of the PIXI extras library
  20123. * @author Mat Groves <mat@goodboydigital.com>
  20124. * @copyright 2013-2015 GoodBoyDigital
  20125. * @license {@link https://github.com/pixijs/pixi.js/blob/master/LICENSE|MIT License}
  20126. */
  20127. require('./cacheAsBitmap');
  20128. require('./getChildByName');
  20129. require('./getGlobalPosition');
  20130. /**
  20131. * @namespace PIXI.extras
  20132. */
  20133. module.exports = {
  20134. MovieClip: require('./MovieClip'),
  20135. TilingSprite: require('./TilingSprite'),
  20136. BitmapText: require('./BitmapText')
  20137. };
  20138. },{"./BitmapText":80,"./MovieClip":81,"./TilingSprite":82,"./cacheAsBitmap":83,"./getChildByName":84,"./getGlobalPosition":85}],87:[function(require,module,exports){
  20139. var core = require('../../core');
  20140. // @see https://github.com/substack/brfs/issues/25
  20141. // TODO (cengler) - The Y is flipped in this shader for some reason.
  20142. /**
  20143. * @author Vico @vicocotea
  20144. * original shader : https://www.shadertoy.com/view/lssGDj by @movAX13h
  20145. */
  20146. /**
  20147. * An ASCII filter.
  20148. *
  20149. * @class
  20150. * @extends PIXI.AbstractFilter
  20151. * @memberof PIXI.filters
  20152. */
  20153. function AsciiFilter()
  20154. {
  20155. core.AbstractFilter.call(this,
  20156. // vertex shader
  20157. null,
  20158. // fragment shader
  20159. "precision mediump float;\n\nuniform vec4 dimensions;\nuniform float pixelSize;\nuniform sampler2D uSampler;\n\nfloat character(float n, vec2 p)\n{\n p = floor(p*vec2(4.0, -4.0) + 2.5);\n if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y)\n {\n if (int(mod(n/exp2(p.x + 5.0*p.y), 2.0)) == 1) return 1.0;\n }\n return 0.0;\n}\n\nvoid main()\n{\n vec2 uv = gl_FragCoord.xy;\n\n vec3 col = texture2D(uSampler, floor( uv / pixelSize ) * pixelSize / dimensions.xy).rgb;\n\n float gray = (col.r + col.g + col.b) / 3.0;\n\n float n = 65536.0; // .\n if (gray > 0.2) n = 65600.0; // :\n if (gray > 0.3) n = 332772.0; // *\n if (gray > 0.4) n = 15255086.0; // o\n if (gray > 0.5) n = 23385164.0; // &\n if (gray > 0.6) n = 15252014.0; // 8\n if (gray > 0.7) n = 13199452.0; // @\n if (gray > 0.8) n = 11512810.0; // #\n\n vec2 p = mod( uv / ( pixelSize * 0.5 ), 2.0) - vec2(1.0);\n col = col * character(n, p);\n\n gl_FragColor = vec4(col, 1.0);\n}\n",
  20160. // custom uniforms
  20161. {
  20162. dimensions: { type: '4fv', value: new Float32Array([0, 0, 0, 0]) },
  20163. pixelSize: { type: '1f', value: 8 }
  20164. }
  20165. );
  20166. }
  20167. AsciiFilter.prototype = Object.create(core.AbstractFilter.prototype);
  20168. AsciiFilter.prototype.constructor = AsciiFilter;
  20169. module.exports = AsciiFilter;
  20170. Object.defineProperties(AsciiFilter.prototype, {
  20171. /**
  20172. * The pixel size used by the filter.
  20173. *
  20174. * @member {number}
  20175. * @memberof PIXI.filters.AsciiFilter#
  20176. */
  20177. size: {
  20178. get: function ()
  20179. {
  20180. return this.uniforms.pixelSize.value;
  20181. },
  20182. set: function (value)
  20183. {
  20184. this.uniforms.pixelSize.value = value;
  20185. }
  20186. }
  20187. });
  20188. },{"../../core":29}],88:[function(require,module,exports){
  20189. var core = require('../../core'),
  20190. BlurXFilter = require('../blur/BlurXFilter'),
  20191. BlurYFilter = require('../blur/BlurYFilter');
  20192. /**
  20193. * The BloomFilter applies a Gaussian blur to an object.
  20194. * The strength of the blur can be set for x- and y-axis separately.
  20195. *
  20196. * @class
  20197. * @extends PIXI.AbstractFilter
  20198. * @memberof PIXI.filters
  20199. */
  20200. function BloomFilter()
  20201. {
  20202. core.AbstractFilter.call(this);
  20203. this.blurXFilter = new BlurXFilter();
  20204. this.blurYFilter = new BlurYFilter();
  20205. this.defaultFilter = new core.AbstractFilter();
  20206. }
  20207. BloomFilter.prototype = Object.create(core.AbstractFilter.prototype);
  20208. BloomFilter.prototype.constructor = BloomFilter;
  20209. module.exports = BloomFilter;
  20210. BloomFilter.prototype.applyFilter = function (renderer, input, output)
  20211. {
  20212. var renderTarget = renderer.filterManager.getRenderTarget(true);
  20213. //TODO - copyTexSubImage2D could be used here?
  20214. this.defaultFilter.applyFilter(renderer, input, output);
  20215. this.blurXFilter.applyFilter(renderer, input, renderTarget);
  20216. renderer.blendModeManager.setBlendMode(core.BLEND_MODES.SCREEN);
  20217. this.blurYFilter.applyFilter(renderer, renderTarget, output);
  20218. renderer.blendModeManager.setBlendMode(core.BLEND_MODES.NORMAL);
  20219. renderer.filterManager.returnRenderTarget(renderTarget);
  20220. };
  20221. Object.defineProperties(BloomFilter.prototype, {
  20222. /**
  20223. * Sets the strength of both the blurX and blurY properties simultaneously
  20224. *
  20225. * @member {number}
  20226. * @memberOf PIXI.filters.BloomFilter#
  20227. * @default 2
  20228. */
  20229. blur: {
  20230. get: function ()
  20231. {
  20232. return this.blurXFilter.blur;
  20233. },
  20234. set: function (value)
  20235. {
  20236. this.blurXFilter.blur = this.blurYFilter.blur = value;
  20237. }
  20238. },
  20239. /**
  20240. * Sets the strength of the blurX property
  20241. *
  20242. * @member {number}
  20243. * @memberOf PIXI.filters.BloomFilter#
  20244. * @default 2
  20245. */
  20246. blurX: {
  20247. get: function ()
  20248. {
  20249. return this.blurXFilter.blur;
  20250. },
  20251. set: function (value)
  20252. {
  20253. this.blurXFilter.blur = value;
  20254. }
  20255. },
  20256. /**
  20257. * Sets the strength of the blurY property
  20258. *
  20259. * @member {number}
  20260. * @memberOf PIXI.filters.BloomFilter#
  20261. * @default 2
  20262. */
  20263. blurY: {
  20264. get: function ()
  20265. {
  20266. return this.blurYFilter.blur;
  20267. },
  20268. set: function (value)
  20269. {
  20270. this.blurYFilter.blur = value;
  20271. }
  20272. }
  20273. });
  20274. },{"../../core":29,"../blur/BlurXFilter":91,"../blur/BlurYFilter":92}],89:[function(require,module,exports){
  20275. var core = require('../../core');
  20276. /**
  20277. * The BlurDirFilter applies a Gaussian blur toward a direction to an object.
  20278. *
  20279. * @class
  20280. * @param {number} dirX
  20281. * @param {number} dirY
  20282. * @extends PIXI.AbstractFilter
  20283. * @memberof PIXI.filters
  20284. */
  20285. function BlurDirFilter(dirX, dirY)
  20286. {
  20287. core.AbstractFilter.call(this,
  20288. // vertex shader
  20289. "attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\n\nuniform float strength;\nuniform float dirX;\nuniform float dirY;\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\nvarying vec2 vBlurTexCoords[3];\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n\n vBlurTexCoords[0] = aTextureCoord + vec2( (0.004 * strength) * dirX, (0.004 * strength) * dirY );\n vBlurTexCoords[1] = aTextureCoord + vec2( (0.008 * strength) * dirX, (0.008 * strength) * dirY );\n vBlurTexCoords[2] = aTextureCoord + vec2( (0.012 * strength) * dirX, (0.012 * strength) * dirY );\n\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}\n",
  20290. // fragment shader
  20291. "precision lowp float;\n\nvarying vec2 vTextureCoord;\nvarying vec2 vBlurTexCoords[3];\nvarying vec4 vColor;\n\nuniform sampler2D uSampler;\n\nvoid main(void)\n{\n gl_FragColor = vec4(0.0);\n\n gl_FragColor += texture2D(uSampler, vTextureCoord ) * 0.3989422804014327;\n gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 0]) * 0.2419707245191454;\n gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 1]) * 0.05399096651318985;\n gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 2]) * 0.004431848411938341;\n}\n",
  20292. // set the uniforms
  20293. {
  20294. strength: { type: '1f', value: 1 },
  20295. dirX: { type: '1f', value: dirX || 0 },
  20296. dirY: { type: '1f', value: dirY || 0 }
  20297. }
  20298. );
  20299. this.defaultFilter = new core.AbstractFilter();
  20300. /**
  20301. * Sets the number of passes for blur. More passes means higher quaility bluring.
  20302. *
  20303. * @member {number}
  20304. * @default 1
  20305. */
  20306. this.passes = 1;
  20307. /**
  20308. * Sets the X direction of the blur
  20309. *
  20310. * @member {number}
  20311. * @default 0
  20312. */
  20313. this.dirX = dirX || 0;
  20314. /**
  20315. * Sets the Y direction of the blur
  20316. *
  20317. * @member {number}
  20318. * @default 0
  20319. */
  20320. this.dirY = dirY || 0;
  20321. this.strength = 4;
  20322. }
  20323. BlurDirFilter.prototype = Object.create(core.AbstractFilter.prototype);
  20324. BlurDirFilter.prototype.constructor = BlurDirFilter;
  20325. module.exports = BlurDirFilter;
  20326. BlurDirFilter.prototype.applyFilter = function (renderer, input, output, clear) {
  20327. var shader = this.getShader(renderer);
  20328. this.uniforms.strength.value = this.strength / 4 / this.passes * (input.frame.width / input.size.width);
  20329. if (this.passes === 1) {
  20330. renderer.filterManager.applyFilter(shader, input, output, clear);
  20331. } else {
  20332. var renderTarget = renderer.filterManager.getRenderTarget(true);
  20333. renderer.filterManager.applyFilter(shader, input, renderTarget, clear);
  20334. for(var i = 0; i < this.passes-2; i++)
  20335. {
  20336. //this.uniforms.strength.value = this.strength / 4 / (this.passes+(i*2)) * (input.frame.width / input.size.width);
  20337. renderer.filterManager.applyFilter(shader, renderTarget, renderTarget, clear);
  20338. }
  20339. renderer.filterManager.applyFilter(shader, renderTarget, output, clear);
  20340. renderer.filterManager.returnRenderTarget(renderTarget);
  20341. }
  20342. };
  20343. Object.defineProperties(BlurDirFilter.prototype, {
  20344. /**
  20345. * Sets the strength of both the blur.
  20346. *
  20347. * @member {number}
  20348. * @memberof PIXI.filters.BlurDirFilter#
  20349. * @default 2
  20350. */
  20351. blur: {
  20352. get: function ()
  20353. {
  20354. return this.strength;
  20355. },
  20356. set: function (value)
  20357. {
  20358. this.padding = value * 0.5;
  20359. this.strength = value;
  20360. }
  20361. },
  20362. /**
  20363. * Sets the X direction of the blur.
  20364. *
  20365. * @member {number}
  20366. * @memberof PIXI.filters.BlurYFilter#
  20367. * @default 0
  20368. */
  20369. dirX: {
  20370. get: function ()
  20371. {
  20372. return this.dirX;
  20373. },
  20374. set: function (value)
  20375. {
  20376. this.uniforms.dirX.value = value;
  20377. }
  20378. },
  20379. /**
  20380. * Sets the Y direction of the blur.
  20381. *
  20382. * @member {number}
  20383. * @memberof PIXI.filters.BlurDirFilter#
  20384. * @default 0
  20385. */
  20386. dirY: {
  20387. get: function ()
  20388. {
  20389. return this.dirY;
  20390. },
  20391. set: function (value)
  20392. {
  20393. this.uniforms.dirY.value = value;
  20394. }
  20395. }
  20396. });
  20397. },{"../../core":29}],90:[function(require,module,exports){
  20398. var core = require('../../core'),
  20399. BlurXFilter = require('./BlurXFilter'),
  20400. BlurYFilter = require('./BlurYFilter');
  20401. /**
  20402. * The BlurFilter applies a Gaussian blur to an object.
  20403. * The strength of the blur can be set for x- and y-axis separately.
  20404. *
  20405. * @class
  20406. * @extends PIXI.AbstractFilter
  20407. * @memberof PIXI.filters
  20408. */
  20409. function BlurFilter()
  20410. {
  20411. core.AbstractFilter.call(this);
  20412. this.blurXFilter = new BlurXFilter();
  20413. this.blurYFilter = new BlurYFilter();
  20414. }
  20415. BlurFilter.prototype = Object.create(core.AbstractFilter.prototype);
  20416. BlurFilter.prototype.constructor = BlurFilter;
  20417. module.exports = BlurFilter;
  20418. BlurFilter.prototype.applyFilter = function (renderer, input, output)
  20419. {
  20420. var renderTarget = renderer.filterManager.getRenderTarget(true);
  20421. this.blurXFilter.applyFilter(renderer, input, renderTarget);
  20422. this.blurYFilter.applyFilter(renderer, renderTarget, output);
  20423. renderer.filterManager.returnRenderTarget(renderTarget);
  20424. };
  20425. Object.defineProperties(BlurFilter.prototype, {
  20426. /**
  20427. * Sets the strength of both the blurX and blurY properties simultaneously
  20428. *
  20429. * @member {number}
  20430. * @memberOf PIXI.filters.BlurFilter#
  20431. * @default 2
  20432. */
  20433. blur: {
  20434. get: function ()
  20435. {
  20436. return this.blurXFilter.blur;
  20437. },
  20438. set: function (value)
  20439. {
  20440. this.padding = Math.abs(value) * 0.5;
  20441. this.blurXFilter.blur = this.blurYFilter.blur = value;
  20442. }
  20443. },
  20444. /**
  20445. * Sets the number of passes for blur. More passes means higher quaility bluring.
  20446. *
  20447. * @member {number}
  20448. * @memberof PIXI.filters.BlurYFilter#
  20449. * @default 1
  20450. */
  20451. passes: {
  20452. get: function ()
  20453. {
  20454. return this.blurXFilter.passes;
  20455. },
  20456. set: function (value)
  20457. {
  20458. this.blurXFilter.passes = this.blurYFilter.passes = value;
  20459. }
  20460. },
  20461. /**
  20462. * Sets the strength of the blurX property
  20463. *
  20464. * @member {number}
  20465. * @memberOf PIXI.filters.BlurFilter#
  20466. * @default 2
  20467. */
  20468. blurX: {
  20469. get: function ()
  20470. {
  20471. return this.blurXFilter.blur;
  20472. },
  20473. set: function (value)
  20474. {
  20475. this.blurXFilter.blur = value;
  20476. }
  20477. },
  20478. /**
  20479. * Sets the strength of the blurY property
  20480. *
  20481. * @member {number}
  20482. * @memberOf PIXI.filters.BlurFilter#
  20483. * @default 2
  20484. */
  20485. blurY: {
  20486. get: function ()
  20487. {
  20488. return this.blurYFilter.blur;
  20489. },
  20490. set: function (value)
  20491. {
  20492. this.blurYFilter.blur = value;
  20493. }
  20494. }
  20495. });
  20496. },{"../../core":29,"./BlurXFilter":91,"./BlurYFilter":92}],91:[function(require,module,exports){
  20497. var core = require('../../core');
  20498. // @see https://github.com/substack/brfs/issues/25
  20499. /**
  20500. * The BlurXFilter applies a horizontal Gaussian blur to an object.
  20501. *
  20502. * @class
  20503. * @extends PIXI.AbstractFilter
  20504. * @memberof PIXI.filters
  20505. */
  20506. function BlurXFilter()
  20507. {
  20508. core.AbstractFilter.call(this,
  20509. // vertex shader
  20510. "attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\n\nuniform float strength;\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\nvarying vec2 vBlurTexCoords[6];\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n\n vBlurTexCoords[ 0] = aTextureCoord + vec2(-0.012 * strength, 0.0);\n vBlurTexCoords[ 1] = aTextureCoord + vec2(-0.008 * strength, 0.0);\n vBlurTexCoords[ 2] = aTextureCoord + vec2(-0.004 * strength, 0.0);\n vBlurTexCoords[ 3] = aTextureCoord + vec2( 0.004 * strength, 0.0);\n vBlurTexCoords[ 4] = aTextureCoord + vec2( 0.008 * strength, 0.0);\n vBlurTexCoords[ 5] = aTextureCoord + vec2( 0.012 * strength, 0.0);\n\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}\n",
  20511. // fragment shader
  20512. "precision lowp float;\n\nvarying vec2 vTextureCoord;\nvarying vec2 vBlurTexCoords[6];\nvarying vec4 vColor;\n\nuniform sampler2D uSampler;\n\nvoid main(void)\n{\n gl_FragColor = vec4(0.0);\n\n gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 0])*0.004431848411938341;\n gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 1])*0.05399096651318985;\n gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 2])*0.2419707245191454;\n gl_FragColor += texture2D(uSampler, vTextureCoord )*0.3989422804014327;\n gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 3])*0.2419707245191454;\n gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 4])*0.05399096651318985;\n gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 5])*0.004431848411938341;\n}\n",
  20513. // set the uniforms
  20514. {
  20515. strength: { type: '1f', value: 1 }
  20516. }
  20517. );
  20518. /**
  20519. * Sets the number of passes for blur. More passes means higher quaility bluring.
  20520. *
  20521. * @member {number}
  20522. * @default 1
  20523. */
  20524. this.passes = 1;
  20525. this.strength = 4;
  20526. }
  20527. BlurXFilter.prototype = Object.create(core.AbstractFilter.prototype);
  20528. BlurXFilter.prototype.constructor = BlurXFilter;
  20529. module.exports = BlurXFilter;
  20530. BlurXFilter.prototype.applyFilter = function (renderer, input, output, clear)
  20531. {
  20532. var shader = this.getShader(renderer);
  20533. this.uniforms.strength.value = this.strength / 4 / this.passes * (input.frame.width / input.size.width);
  20534. if(this.passes === 1)
  20535. {
  20536. renderer.filterManager.applyFilter(shader, input, output, clear);
  20537. }
  20538. else
  20539. {
  20540. var renderTarget = renderer.filterManager.getRenderTarget(true);
  20541. var flip = input;
  20542. var flop = renderTarget;
  20543. for(var i = 0; i < this.passes-1; i++)
  20544. {
  20545. renderer.filterManager.applyFilter(shader, flip, flop, true);
  20546. var temp = flop;
  20547. flop = flip;
  20548. flip = temp;
  20549. }
  20550. renderer.filterManager.applyFilter(shader, flip, output, clear);
  20551. renderer.filterManager.returnRenderTarget(renderTarget);
  20552. }
  20553. };
  20554. Object.defineProperties(BlurXFilter.prototype, {
  20555. /**
  20556. * Sets the strength of both the blur.
  20557. *
  20558. * @member {number}
  20559. * @memberof PIXI.filters.BlurXFilter#
  20560. * @default 2
  20561. */
  20562. blur: {
  20563. get: function ()
  20564. {
  20565. return this.strength;
  20566. },
  20567. set: function (value)
  20568. {
  20569. this.padding = Math.abs(value) * 0.5;
  20570. this.strength = value;
  20571. }
  20572. }
  20573. });
  20574. },{"../../core":29}],92:[function(require,module,exports){
  20575. var core = require('../../core');
  20576. // @see https://github.com/substack/brfs/issues/25
  20577. /**
  20578. * The BlurYFilter applies a horizontal Gaussian blur to an object.
  20579. *
  20580. * @class
  20581. * @extends PIXI.AbstractFilter
  20582. * @memberof PIXI.filters
  20583. */
  20584. function BlurYFilter()
  20585. {
  20586. core.AbstractFilter.call(this,
  20587. // vertex shader
  20588. "attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\n\nuniform float strength;\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\nvarying vec2 vBlurTexCoords[6];\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n\n vBlurTexCoords[ 0] = aTextureCoord + vec2(0.0, -0.012 * strength);\n vBlurTexCoords[ 1] = aTextureCoord + vec2(0.0, -0.008 * strength);\n vBlurTexCoords[ 2] = aTextureCoord + vec2(0.0, -0.004 * strength);\n vBlurTexCoords[ 3] = aTextureCoord + vec2(0.0, 0.004 * strength);\n vBlurTexCoords[ 4] = aTextureCoord + vec2(0.0, 0.008 * strength);\n vBlurTexCoords[ 5] = aTextureCoord + vec2(0.0, 0.012 * strength);\n\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}\n",
  20589. // fragment shader
  20590. "precision lowp float;\n\nvarying vec2 vTextureCoord;\nvarying vec2 vBlurTexCoords[6];\nvarying vec4 vColor;\n\nuniform sampler2D uSampler;\n\nvoid main(void)\n{\n gl_FragColor = vec4(0.0);\n\n gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 0])*0.004431848411938341;\n gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 1])*0.05399096651318985;\n gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 2])*0.2419707245191454;\n gl_FragColor += texture2D(uSampler, vTextureCoord )*0.3989422804014327;\n gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 3])*0.2419707245191454;\n gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 4])*0.05399096651318985;\n gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 5])*0.004431848411938341;\n}\n",
  20591. // set the uniforms
  20592. {
  20593. strength: { type: '1f', value: 1 }
  20594. }
  20595. );
  20596. this.passes = 1;
  20597. this.strength = 4;
  20598. }
  20599. BlurYFilter.prototype = Object.create(core.AbstractFilter.prototype);
  20600. BlurYFilter.prototype.constructor = BlurYFilter;
  20601. module.exports = BlurYFilter;
  20602. BlurYFilter.prototype.applyFilter = function (renderer, input, output, clear)
  20603. {
  20604. var shader = this.getShader(renderer);
  20605. this.uniforms.strength.value = Math.abs(this.strength) / 4 / this.passes * (input.frame.height / input.size.height);
  20606. if(this.passes === 1)
  20607. {
  20608. renderer.filterManager.applyFilter(shader, input, output, clear);
  20609. }
  20610. else
  20611. {
  20612. var renderTarget = renderer.filterManager.getRenderTarget(true);
  20613. var flip = input;
  20614. var flop = renderTarget;
  20615. for(var i = 0; i < this.passes-1; i++)
  20616. {
  20617. renderer.filterManager.applyFilter(shader, flip, flop, true);
  20618. var temp = flop;
  20619. flop = flip;
  20620. flip = temp;
  20621. }
  20622. renderer.filterManager.applyFilter(shader, flip, output, clear);
  20623. renderer.filterManager.returnRenderTarget(renderTarget);
  20624. }
  20625. };
  20626. Object.defineProperties(BlurYFilter.prototype, {
  20627. /**
  20628. * Sets the strength of both the blur.
  20629. *
  20630. * @member {number}
  20631. * @memberof PIXI.filters.BlurYFilter#
  20632. * @default 2
  20633. */
  20634. blur: {
  20635. get: function ()
  20636. {
  20637. return this.strength;
  20638. },
  20639. set: function (value)
  20640. {
  20641. this.padding = Math.abs(value) * 0.5;
  20642. this.strength = value;
  20643. }
  20644. }
  20645. });
  20646. },{"../../core":29}],93:[function(require,module,exports){
  20647. var core = require('../../core');
  20648. // @see https://github.com/substack/brfs/issues/25
  20649. /**
  20650. * A Smart Blur Filter.
  20651. *
  20652. * @class
  20653. * @extends PIXI.AbstractFilter
  20654. * @memberof PIXI.filters
  20655. */
  20656. function SmartBlurFilter()
  20657. {
  20658. core.AbstractFilter.call(this,
  20659. // vertex shader
  20660. null,
  20661. // fragment shader
  20662. "precision mediump float;\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform vec2 delta;\n\nfloat random(vec3 scale, float seed)\n{\n return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);\n}\n\nvoid main(void)\n{\n vec4 color = vec4(0.0);\n float total = 0.0;\n\n float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);\n\n for (float t = -30.0; t <= 30.0; t++)\n {\n float percent = (t + offset - 0.5) / 30.0;\n float weight = 1.0 - abs(percent);\n vec4 sample = texture2D(uSampler, vTextureCoord + delta * percent);\n sample.rgb *= sample.a;\n color += sample * weight;\n total += weight;\n }\n\n gl_FragColor = color / total;\n gl_FragColor.rgb /= gl_FragColor.a + 0.00001;\n}\n",
  20663. // uniforms
  20664. {
  20665. delta: { type: 'v2', value: { x: 0.1, y: 0.0 } }
  20666. }
  20667. );
  20668. }
  20669. SmartBlurFilter.prototype = Object.create(core.AbstractFilter.prototype);
  20670. SmartBlurFilter.prototype.constructor = SmartBlurFilter;
  20671. module.exports = SmartBlurFilter;
  20672. },{"../../core":29}],94:[function(require,module,exports){
  20673. var core = require('../../core');
  20674. // @see https://github.com/substack/brfs/issues/25
  20675. /**
  20676. * The ColorMatrixFilter class lets you apply a 5x4 matrix transformation on the RGBA
  20677. * color and alpha values of every pixel on your displayObject to produce a result
  20678. * with a new set of RGBA color and alpha values. It's pretty powerful!
  20679. *
  20680. * ```js
  20681. * var colorMatrix = new PIXI.ColorMatrixFilter();
  20682. * container.filters = [colorMatrix];
  20683. * colorMatrix.contrast(2);
  20684. * ```
  20685. * @author Clément Chenebault <clement@goodboydigital.com>
  20686. * @class
  20687. * @extends PIXI.AbstractFilter
  20688. * @memberof PIXI.filters
  20689. */
  20690. function ColorMatrixFilter()
  20691. {
  20692. core.AbstractFilter.call(this,
  20693. // vertex shader
  20694. null,
  20695. // fragment shader
  20696. "precision mediump float;\n\nvarying vec2 vTextureCoord;\nuniform sampler2D uSampler;\nuniform float m[25];\n\nvoid main(void)\n{\n\n vec4 c = texture2D(uSampler, vTextureCoord);\n\n gl_FragColor.r = (m[0] * c.r);\n gl_FragColor.r += (m[1] * c.g);\n gl_FragColor.r += (m[2] * c.b);\n gl_FragColor.r += (m[3] * c.a);\n gl_FragColor.r += m[4] * c.a;\n\n gl_FragColor.g = (m[5] * c.r);\n gl_FragColor.g += (m[6] * c.g);\n gl_FragColor.g += (m[7] * c.b);\n gl_FragColor.g += (m[8] * c.a);\n gl_FragColor.g += m[9] * c.a;\n\n gl_FragColor.b = (m[10] * c.r);\n gl_FragColor.b += (m[11] * c.g);\n gl_FragColor.b += (m[12] * c.b);\n gl_FragColor.b += (m[13] * c.a);\n gl_FragColor.b += m[14] * c.a;\n\n gl_FragColor.a = (m[15] * c.r);\n gl_FragColor.a += (m[16] * c.g);\n gl_FragColor.a += (m[17] * c.b);\n gl_FragColor.a += (m[18] * c.a);\n gl_FragColor.a += m[19] * c.a;\n\n}\n",
  20697. // custom uniforms
  20698. {
  20699. m: {
  20700. type: '1fv', value: [
  20701. 1, 0, 0, 0, 0,
  20702. 0, 1, 0, 0, 0,
  20703. 0, 0, 1, 0, 0,
  20704. 0, 0, 0, 1, 0
  20705. ]
  20706. }
  20707. }
  20708. );
  20709. }
  20710. ColorMatrixFilter.prototype = Object.create(core.AbstractFilter.prototype);
  20711. ColorMatrixFilter.prototype.constructor = ColorMatrixFilter;
  20712. module.exports = ColorMatrixFilter;
  20713. /**
  20714. * Transforms current matrix and set the new one
  20715. *
  20716. * @param matrix {number[]} (mat 5x4)
  20717. * @param multiply {boolean} if true, current matrix and matrix are multiplied. If false, just set the current matrix with @param matrix
  20718. */
  20719. ColorMatrixFilter.prototype._loadMatrix = function (matrix, multiply)
  20720. {
  20721. multiply = !!multiply;
  20722. var newMatrix = matrix;
  20723. if (multiply) {
  20724. this._multiply(newMatrix, this.uniforms.m.value, matrix);
  20725. newMatrix = this._colorMatrix(newMatrix);
  20726. }
  20727. // set the new matrix
  20728. this.uniforms.m.value = newMatrix;
  20729. };
  20730. /**
  20731. * Multiplies two mat5's
  20732. *
  20733. * @param out {number[]} (mat 5x4) the receiving matrix
  20734. * @param a {number[]} (mat 5x4) the first operand
  20735. * @param b {number[]} (mat 5x4) the second operand
  20736. * @returns out {number[]} (mat 5x4)
  20737. */
  20738. ColorMatrixFilter.prototype._multiply = function (out, a, b)
  20739. {
  20740. // Red Channel
  20741. out[0] = (a[0] * b[0]) + (a[1] * b[5]) + (a[2] * b[10]) + (a[3] * b[15]);
  20742. out[1] = (a[0] * b[1]) + (a[1] * b[6]) + (a[2] * b[11]) + (a[3] * b[16]);
  20743. out[2] = (a[0] * b[2]) + (a[1] * b[7]) + (a[2] * b[12]) + (a[3] * b[17]);
  20744. out[3] = (a[0] * b[3]) + (a[1] * b[8]) + (a[2] * b[13]) + (a[3] * b[18]);
  20745. out[4] = (a[0] * b[4]) + (a[1] * b[9]) + (a[2] * b[14]) + (a[3] * b[19]);
  20746. // Green Channel
  20747. out[5] = (a[5] * b[0]) + (a[6] * b[5]) + (a[7] * b[10]) + (a[8] * b[15]);
  20748. out[6] = (a[5] * b[1]) + (a[6] * b[6]) + (a[7] * b[11]) + (a[8] * b[16]);
  20749. out[7] = (a[5] * b[2]) + (a[6] * b[7]) + (a[7] * b[12]) + (a[8] * b[17]);
  20750. out[8] = (a[5] * b[3]) + (a[6] * b[8]) + (a[7] * b[13]) + (a[8] * b[18]);
  20751. out[9] = (a[5] * b[4]) + (a[6] * b[9]) + (a[7] * b[14]) + (a[8] * b[19]);
  20752. // Blue Channel
  20753. out[10] = (a[10] * b[0]) + (a[11] * b[5]) + (a[12] * b[10]) + (a[13] * b[15]);
  20754. out[11] = (a[10] * b[1]) + (a[11] * b[6]) + (a[12] * b[11]) + (a[13] * b[16]);
  20755. out[12] = (a[10] * b[2]) + (a[11] * b[7]) + (a[12] * b[12]) + (a[13] * b[17]);
  20756. out[13] = (a[10] * b[3]) + (a[11] * b[8]) + (a[12] * b[13]) + (a[13] * b[18]);
  20757. out[14] = (a[10] * b[4]) + (a[11] * b[9]) + (a[12] * b[14]) + (a[13] * b[19]);
  20758. // Alpha Channel
  20759. out[15] = (a[15] * b[0]) + (a[16] * b[5]) + (a[17] * b[10]) + (a[18] * b[15]);
  20760. out[16] = (a[15] * b[1]) + (a[16] * b[6]) + (a[17] * b[11]) + (a[18] * b[16]);
  20761. out[17] = (a[15] * b[2]) + (a[16] * b[7]) + (a[17] * b[12]) + (a[18] * b[17]);
  20762. out[18] = (a[15] * b[3]) + (a[16] * b[8]) + (a[17] * b[13]) + (a[18] * b[18]);
  20763. out[19] = (a[15] * b[4]) + (a[16] * b[9]) + (a[17] * b[14]) + (a[18] * b[19]);
  20764. return out;
  20765. };
  20766. /**
  20767. * Create a Float32 Array and normalize the offset component to 0-1
  20768. *
  20769. * @param matrix {number[]} (mat 5x4)
  20770. * @return m {number[]} (mat 5x4) with all values between 0-1
  20771. */
  20772. ColorMatrixFilter.prototype._colorMatrix = function (matrix)
  20773. {
  20774. // Create a Float32 Array and normalize the offset component to 0-1
  20775. var m = new Float32Array(matrix);
  20776. m[4] /= 255;
  20777. m[9] /= 255;
  20778. m[14] /= 255;
  20779. m[19] /= 255;
  20780. return m;
  20781. };
  20782. /**
  20783. * Adjusts brightness
  20784. *
  20785. * @param b {number} value of the brigthness (0 is black)
  20786. * @param multiply {boolean} refer to ._loadMatrix() method
  20787. */
  20788. ColorMatrixFilter.prototype.brightness = function (b, multiply)
  20789. {
  20790. var matrix = [
  20791. b, 0, 0, 0, 0,
  20792. 0, b, 0, 0, 0,
  20793. 0, 0, b, 0, 0,
  20794. 0, 0, 0, 1, 0
  20795. ];
  20796. this._loadMatrix(matrix, multiply);
  20797. };
  20798. /**
  20799. * Set the matrices in grey scales
  20800. *
  20801. * @param scale {number} value of the grey (0 is black)
  20802. * @param multiply {boolean} refer to ._loadMatrix() method
  20803. */
  20804. ColorMatrixFilter.prototype.greyscale = function (scale, multiply)
  20805. {
  20806. var matrix = [
  20807. scale, scale, scale, 0, 0,
  20808. scale, scale, scale, 0, 0,
  20809. scale, scale, scale, 0, 0,
  20810. 0, 0, 0, 1, 0
  20811. ];
  20812. this._loadMatrix(matrix, multiply);
  20813. };
  20814. //Americanized alias
  20815. ColorMatrixFilter.prototype.grayscale = ColorMatrixFilter.prototype.greyscale;
  20816. /**
  20817. * Set the black and white matrice
  20818. * Multiply the current matrix
  20819. *
  20820. * @param multiply {boolean} refer to ._loadMatrix() method
  20821. */
  20822. ColorMatrixFilter.prototype.blackAndWhite = function (multiply)
  20823. {
  20824. var matrix = [
  20825. 0.3, 0.6, 0.1, 0, 0,
  20826. 0.3, 0.6, 0.1, 0, 0,
  20827. 0.3, 0.6, 0.1, 0, 0,
  20828. 0, 0, 0, 1, 0
  20829. ];
  20830. this._loadMatrix(matrix, multiply);
  20831. };
  20832. /**
  20833. * Set the hue property of the color
  20834. *
  20835. * @param rotation {number} in degrees
  20836. * @param multiply {boolean} refer to ._loadMatrix() method
  20837. */
  20838. ColorMatrixFilter.prototype.hue = function (rotation, multiply)
  20839. {
  20840. rotation = (rotation || 0) / 180 * Math.PI;
  20841. var cos = Math.cos(rotation),
  20842. sin = Math.sin(rotation);
  20843. // luminanceRed, luminanceGreen, luminanceBlue
  20844. var lumR = 0.213, // or 0.3086
  20845. lumG = 0.715, // or 0.6094
  20846. lumB = 0.072; // or 0.0820
  20847. var matrix = [
  20848. lumR + cos * (1 - lumR) + sin * (-lumR), lumG + cos * (-lumG) + sin * (-lumG), lumB + cos * (-lumB) + sin * (1 - lumB), 0, 0,
  20849. lumR + cos * (-lumR) + sin * (0.143), lumG + cos * (1 - lumG) + sin * (0.140), lumB + cos * (-lumB) + sin * (-0.283), 0, 0,
  20850. lumR + cos * (-lumR) + sin * (-(1 - lumR)), lumG + cos * (-lumG) + sin * (lumG), lumB + cos * (1 - lumB) + sin * (lumB), 0, 0,
  20851. 0, 0, 0, 1, 0
  20852. ];
  20853. this._loadMatrix(matrix, multiply);
  20854. };
  20855. /**
  20856. * Set the contrast matrix, increase the separation between dark and bright
  20857. * Increase contrast : shadows darker and highlights brighter
  20858. * Decrease contrast : bring the shadows up and the highlights down
  20859. *
  20860. * @param amount {number} value of the contrast
  20861. * @param multiply {boolean} refer to ._loadMatrix() method
  20862. */
  20863. ColorMatrixFilter.prototype.contrast = function (amount, multiply)
  20864. {
  20865. var v = (amount || 0) + 1;
  20866. var o = -128 * (v - 1);
  20867. var matrix = [
  20868. v, 0, 0, 0, o,
  20869. 0, v, 0, 0, o,
  20870. 0, 0, v, 0, o,
  20871. 0, 0, 0, 1, 0
  20872. ];
  20873. this._loadMatrix(matrix, multiply);
  20874. };
  20875. /**
  20876. * Set the saturation matrix, increase the separation between colors
  20877. * Increase saturation : increase contrast, brightness, and sharpness
  20878. *
  20879. * @param amount {number}
  20880. * @param multiply {boolean} refer to ._loadMatrix() method
  20881. */
  20882. ColorMatrixFilter.prototype.saturate = function (amount, multiply)
  20883. {
  20884. var x = (amount || 0) * 2 / 3 + 1;
  20885. var y = ((x - 1) * -0.5);
  20886. var matrix = [
  20887. x, y, y, 0, 0,
  20888. y, x, y, 0, 0,
  20889. y, y, x, 0, 0,
  20890. 0, 0, 0, 1, 0
  20891. ];
  20892. this._loadMatrix(matrix, multiply);
  20893. };
  20894. /**
  20895. * Desaturate image (remove color)
  20896. *
  20897. * Call the saturate function
  20898. *
  20899. * @param multiply {boolean} refer to ._loadMatrix() method
  20900. */
  20901. ColorMatrixFilter.prototype.desaturate = function (multiply) // jshint unused:false
  20902. {
  20903. this.saturate(-1);
  20904. };
  20905. /**
  20906. * Negative image (inverse of classic rgb matrix)
  20907. *
  20908. * @param multiply {boolean} refer to ._loadMatrix() method
  20909. */
  20910. ColorMatrixFilter.prototype.negative = function (multiply)
  20911. {
  20912. var matrix = [
  20913. 0, 1, 1, 0, 0,
  20914. 1, 0, 1, 0, 0,
  20915. 1, 1, 0, 0, 0,
  20916. 0, 0, 0, 1, 0
  20917. ];
  20918. this._loadMatrix(matrix, multiply);
  20919. };
  20920. /**
  20921. * Sepia image
  20922. *
  20923. * @param multiply {boolean} refer to ._loadMatrix() method
  20924. */
  20925. ColorMatrixFilter.prototype.sepia = function (multiply)
  20926. {
  20927. var matrix = [
  20928. 0.393, 0.7689999, 0.18899999, 0, 0,
  20929. 0.349, 0.6859999, 0.16799999, 0, 0,
  20930. 0.272, 0.5339999, 0.13099999, 0, 0,
  20931. 0, 0, 0, 1, 0
  20932. ];
  20933. this._loadMatrix(matrix, multiply);
  20934. };
  20935. /**
  20936. * Color motion picture process invented in 1916 (thanks Dominic Szablewski)
  20937. *
  20938. * @param multiply {boolean} refer to ._loadMatrix() method
  20939. */
  20940. ColorMatrixFilter.prototype.technicolor = function (multiply)
  20941. {
  20942. var matrix = [
  20943. 1.9125277891456083, -0.8545344976951645, -0.09155508482755585, 0, 11.793603434377337,
  20944. -0.3087833385928097, 1.7658908555458428, -0.10601743074722245, 0, -70.35205161461398,
  20945. -0.231103377548616, -0.7501899197440212, 1.847597816108189, 0, 30.950940869491138,
  20946. 0, 0, 0, 1, 0
  20947. ];
  20948. this._loadMatrix(matrix, multiply);
  20949. };
  20950. /**
  20951. * Polaroid filter
  20952. *
  20953. * @param multiply {boolean} refer to ._loadMatrix() method
  20954. */
  20955. ColorMatrixFilter.prototype.polaroid = function (multiply)
  20956. {
  20957. var matrix = [
  20958. 1.438, -0.062, -0.062, 0, 0,
  20959. -0.122, 1.378, -0.122, 0, 0,
  20960. -0.016, -0.016, 1.483, 0, 0,
  20961. 0, 0, 0, 1, 0
  20962. ];
  20963. this._loadMatrix(matrix, multiply);
  20964. };
  20965. /**
  20966. * Filter who transforms : Red -> Blue and Blue -> Red
  20967. *
  20968. * @param multiply {boolean} refer to ._loadMatrix() method
  20969. */
  20970. ColorMatrixFilter.prototype.toBGR = function (multiply)
  20971. {
  20972. var matrix = [
  20973. 0, 0, 1, 0, 0,
  20974. 0, 1, 0, 0, 0,
  20975. 1, 0, 0, 0, 0,
  20976. 0, 0, 0, 1, 0
  20977. ];
  20978. this._loadMatrix(matrix, multiply);
  20979. };
  20980. /**
  20981. * Color reversal film introduced by Eastman Kodak in 1935. (thanks Dominic Szablewski)
  20982. *
  20983. * @param multiply {boolean} refer to ._loadMatrix() method
  20984. */
  20985. ColorMatrixFilter.prototype.kodachrome = function (multiply)
  20986. {
  20987. var matrix = [
  20988. 1.1285582396593525, -0.3967382283601348, -0.03992559172921793, 0, 63.72958762196502,
  20989. -0.16404339962244616, 1.0835251566291304, -0.05498805115633132, 0, 24.732407896706203,
  20990. -0.16786010706155763, -0.5603416277695248, 1.6014850761964943, 0, 35.62982807460946,
  20991. 0, 0, 0, 1, 0
  20992. ];
  20993. this._loadMatrix(matrix, multiply);
  20994. };
  20995. /**
  20996. * Brown delicious browni filter (thanks Dominic Szablewski)
  20997. *
  20998. * @param multiply {boolean} refer to ._loadMatrix() method
  20999. */
  21000. ColorMatrixFilter.prototype.browni = function (multiply)
  21001. {
  21002. var matrix = [
  21003. 0.5997023498159715, 0.34553243048391263, -0.2708298674538042, 0, 47.43192855600873,
  21004. -0.037703249837783157, 0.8609577587992641, 0.15059552388459913, 0, -36.96841498319127,
  21005. 0.24113635128153335, -0.07441037908422492, 0.44972182064877153, 0, -7.562075277591283,
  21006. 0, 0, 0, 1, 0
  21007. ];
  21008. this._loadMatrix(matrix, multiply);
  21009. };
  21010. /*
  21011. * Vintage filter (thanks Dominic Szablewski)
  21012. *
  21013. * @param multiply {boolean} refer to ._loadMatrix() method
  21014. */
  21015. ColorMatrixFilter.prototype.vintage = function (multiply)
  21016. {
  21017. var matrix = [
  21018. 0.6279345635605994, 0.3202183420819367, -0.03965408211312453, 0, 9.651285835294123,
  21019. 0.02578397704808868, 0.6441188644374771, 0.03259127616149294, 0, 7.462829176470591,
  21020. 0.0466055556782719, -0.0851232987247891, 0.5241648018700465, 0, 5.159190588235296,
  21021. 0, 0, 0, 1, 0
  21022. ];
  21023. this._loadMatrix(matrix, multiply);
  21024. };
  21025. /*
  21026. * We don't know exactly what it does, kind of gradient map, but funny to play with!
  21027. *
  21028. * @param desaturation {number}
  21029. * @param toned {number}
  21030. * @param lightColor {string} (example : "0xFFE580")
  21031. * @param darkColor {string} (example : "0xFFE580")
  21032. *
  21033. * @param multiply {boolean} refer to ._loadMatrix() method
  21034. */
  21035. ColorMatrixFilter.prototype.colorTone = function (desaturation, toned, lightColor, darkColor, multiply)
  21036. {
  21037. desaturation = desaturation || 0.2;
  21038. toned = toned || 0.15;
  21039. lightColor = lightColor || 0xFFE580;
  21040. darkColor = darkColor || 0x338000;
  21041. var lR = ((lightColor >> 16) & 0xFF) / 255;
  21042. var lG = ((lightColor >> 8) & 0xFF) / 255;
  21043. var lB = (lightColor & 0xFF) / 255;
  21044. var dR = ((darkColor >> 16) & 0xFF) / 255;
  21045. var dG = ((darkColor >> 8) & 0xFF) / 255;
  21046. var dB = (darkColor & 0xFF) / 255;
  21047. var matrix = [
  21048. 0.3, 0.59, 0.11, 0, 0,
  21049. lR, lG, lB, desaturation, 0,
  21050. dR, dG, dB, toned, 0,
  21051. lR - dR, lG - dG, lB - dB, 0, 0
  21052. ];
  21053. this._loadMatrix(matrix, multiply);
  21054. };
  21055. /*
  21056. * Night effect
  21057. *
  21058. * @param intensity {number}
  21059. * @param multiply {boolean} refer to ._loadMatrix() method
  21060. */
  21061. ColorMatrixFilter.prototype.night = function (intensity, multiply)
  21062. {
  21063. intensity = intensity || 0.1;
  21064. var matrix = [
  21065. intensity * ( -2.0), -intensity, 0, 0, 0,
  21066. -intensity, 0, intensity, 0, 0,
  21067. 0, intensity, intensity * 2.0, 0, 0,
  21068. 0, 0, 0, 1, 0
  21069. ];
  21070. this._loadMatrix(matrix, multiply);
  21071. };
  21072. /*
  21073. * Predator effect
  21074. *
  21075. * Erase the current matrix by setting a new indepent one
  21076. *
  21077. * @param amount {number} how much the predator feels his future victim
  21078. * @param multiply {boolean} refer to ._loadMatrix() method
  21079. */
  21080. ColorMatrixFilter.prototype.predator = function (amount, multiply)
  21081. {
  21082. var matrix = [
  21083. 11.224130630493164 * amount, -4.794486999511719 * amount, -2.8746118545532227 * amount, 0 * amount, 0.40342438220977783 * amount,
  21084. -3.6330697536468506 * amount, 9.193157196044922 * amount, -2.951810836791992 * amount, 0 * amount, -1.316135048866272 * amount,
  21085. -3.2184197902679443 * amount, -4.2375030517578125 * amount, 7.476448059082031 * amount, 0 * amount, 0.8044459223747253 * amount,
  21086. 0, 0, 0, 1, 0
  21087. ];
  21088. this._loadMatrix(matrix, multiply);
  21089. };
  21090. /*
  21091. * LSD effect
  21092. *
  21093. * Multiply the current matrix
  21094. *
  21095. * @param amount {number} How crazy is your effect
  21096. * @param multiply {boolean} refer to ._loadMatrix() method
  21097. */
  21098. ColorMatrixFilter.prototype.lsd = function (multiply)
  21099. {
  21100. var matrix = [
  21101. 2, -0.4, 0.5, 0, 0,
  21102. -0.5, 2, -0.4, 0, 0,
  21103. -0.4, -0.5, 3, 0, 0,
  21104. 0, 0, 0, 1, 0
  21105. ];
  21106. this._loadMatrix(matrix, multiply);
  21107. };
  21108. /*
  21109. * Erase the current matrix by setting the default one
  21110. *
  21111. */
  21112. ColorMatrixFilter.prototype.reset = function ()
  21113. {
  21114. var matrix = [
  21115. 1, 0, 0, 0, 0,
  21116. 0, 1, 0, 0, 0,
  21117. 0, 0, 1, 0, 0,
  21118. 0, 0, 0, 1, 0
  21119. ];
  21120. this._loadMatrix(matrix, false);
  21121. };
  21122. Object.defineProperties(ColorMatrixFilter.prototype, {
  21123. /**
  21124. * Sets the matrix of the color matrix filter
  21125. *
  21126. * @member {number[]}
  21127. * @memberof PIXI.filters.ColorMatrixFilter#
  21128. * @default [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0]
  21129. */
  21130. matrix: {
  21131. get: function ()
  21132. {
  21133. return this.uniforms.m.value;
  21134. },
  21135. set: function (value)
  21136. {
  21137. this.uniforms.m.value = value;
  21138. }
  21139. }
  21140. });
  21141. },{"../../core":29}],95:[function(require,module,exports){
  21142. var core = require('../../core');
  21143. // @see https://github.com/substack/brfs/issues/25
  21144. /**
  21145. * This lowers the color depth of your image by the given amount, producing an image with a smaller palette.
  21146. *
  21147. * @class
  21148. * @extends PIXI.AbstractFilter
  21149. * @memberof PIXI.filters
  21150. */
  21151. function ColorStepFilter()
  21152. {
  21153. core.AbstractFilter.call(this,
  21154. // vertex shader
  21155. null,
  21156. // fragment shader
  21157. "precision mediump float;\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float step;\n\nvoid main(void)\n{\n vec4 color = texture2D(uSampler, vTextureCoord);\n\n color = floor(color * step) / step;\n\n gl_FragColor = color;\n}\n",
  21158. // custom uniforms
  21159. {
  21160. step: { type: '1f', value: 5 }
  21161. }
  21162. );
  21163. }
  21164. ColorStepFilter.prototype = Object.create(core.AbstractFilter.prototype);
  21165. ColorStepFilter.prototype.constructor = ColorStepFilter;
  21166. module.exports = ColorStepFilter;
  21167. Object.defineProperties(ColorStepFilter.prototype, {
  21168. /**
  21169. * The number of steps to reduce the palette by.
  21170. *
  21171. * @member {number}
  21172. * @memberof PIXI.filters.ColorStepFilter#
  21173. */
  21174. step: {
  21175. get: function ()
  21176. {
  21177. return this.uniforms.step.value;
  21178. },
  21179. set: function (value)
  21180. {
  21181. this.uniforms.step.value = value;
  21182. }
  21183. }
  21184. });
  21185. },{"../../core":29}],96:[function(require,module,exports){
  21186. var core = require('../../core');
  21187. // @see https://github.com/substack/brfs/issues/25
  21188. /**
  21189. * The ConvolutionFilter class applies a matrix convolution filter effect.
  21190. * A convolution combines pixels in the input image with neighboring pixels to produce a new image.
  21191. * A wide variety of image effects can be achieved through convolutions, including blurring, edge
  21192. * detection, sharpening, embossing, and beveling. The matrix should be specified as a 9 point Array.
  21193. * See http://docs.gimp.org/en/plug-in-convmatrix.html for more info.
  21194. *
  21195. * @class
  21196. * @extends PIXI.AbstractFilter
  21197. * @memberof PIXI.filters
  21198. * @param matrix {number[]} An array of values used for matrix transformation. Specified as a 9 point Array.
  21199. * @param width {number} Width of the object you are transforming
  21200. * @param height {number} Height of the object you are transforming
  21201. */
  21202. function ConvolutionFilter(matrix, width, height)
  21203. {
  21204. core.AbstractFilter.call(this,
  21205. // vertex shader
  21206. null,
  21207. // fragment shader
  21208. "precision mediump float;\n\nvarying mediump vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform vec2 texelSize;\nuniform float matrix[9];\n\nvoid main(void)\n{\n vec4 c11 = texture2D(uSampler, vTextureCoord - texelSize); // top left\n vec4 c12 = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y - texelSize.y)); // top center\n vec4 c13 = texture2D(uSampler, vec2(vTextureCoord.x + texelSize.x, vTextureCoord.y - texelSize.y)); // top right\n\n vec4 c21 = texture2D(uSampler, vec2(vTextureCoord.x - texelSize.x, vTextureCoord.y)); // mid left\n vec4 c22 = texture2D(uSampler, vTextureCoord); // mid center\n vec4 c23 = texture2D(uSampler, vec2(vTextureCoord.x + texelSize.x, vTextureCoord.y)); // mid right\n\n vec4 c31 = texture2D(uSampler, vec2(vTextureCoord.x - texelSize.x, vTextureCoord.y + texelSize.y)); // bottom left\n vec4 c32 = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y + texelSize.y)); // bottom center\n vec4 c33 = texture2D(uSampler, vTextureCoord + texelSize); // bottom right\n\n gl_FragColor =\n c11 * matrix[0] + c12 * matrix[1] + c13 * matrix[2] +\n c21 * matrix[3] + c22 * matrix[4] + c23 * matrix[5] +\n c31 * matrix[6] + c32 * matrix[7] + c33 * matrix[8];\n\n gl_FragColor.a = c22.a;\n}\n",
  21209. // custom uniforms
  21210. {
  21211. matrix: { type: '1fv', value: new Float32Array(matrix) },
  21212. texelSize: { type: 'v2', value: { x: 1 / width, y: 1 / height } }
  21213. }
  21214. );
  21215. }
  21216. ConvolutionFilter.prototype = Object.create(core.AbstractFilter.prototype);
  21217. ConvolutionFilter.prototype.constructor = ConvolutionFilter;
  21218. module.exports = ConvolutionFilter;
  21219. Object.defineProperties(ConvolutionFilter.prototype, {
  21220. /**
  21221. * An array of values used for matrix transformation. Specified as a 9 point Array.
  21222. *
  21223. * @member {number[]}
  21224. * @memberof PIXI.filters.ConvolutionFilter#
  21225. */
  21226. matrix: {
  21227. get: function ()
  21228. {
  21229. return this.uniforms.matrix.value;
  21230. },
  21231. set: function (value)
  21232. {
  21233. this.uniforms.matrix.value = new Float32Array(value);
  21234. }
  21235. },
  21236. /**
  21237. * Width of the object you are transforming
  21238. *
  21239. * @member {number}
  21240. * @memberof PIXI.filters.ConvolutionFilter#
  21241. */
  21242. width: {
  21243. get: function ()
  21244. {
  21245. return 1/this.uniforms.texelSize.value.x;
  21246. },
  21247. set: function (value)
  21248. {
  21249. this.uniforms.texelSize.value.x = 1/value;
  21250. }
  21251. },
  21252. /**
  21253. * Height of the object you are transforming
  21254. *
  21255. * @member {number}
  21256. * @memberof PIXI.filters.ConvolutionFilter#
  21257. */
  21258. height: {
  21259. get: function ()
  21260. {
  21261. return 1/this.uniforms.texelSize.value.y;
  21262. },
  21263. set: function (value)
  21264. {
  21265. this.uniforms.texelSize.value.y = 1/value;
  21266. }
  21267. }
  21268. });
  21269. },{"../../core":29}],97:[function(require,module,exports){
  21270. var core = require('../../core');
  21271. // @see https://github.com/substack/brfs/issues/25
  21272. /**
  21273. * A Cross Hatch effect filter.
  21274. *
  21275. * @class
  21276. * @extends PIXI.AbstractFilter
  21277. * @memberof PIXI.filters
  21278. */
  21279. function CrossHatchFilter()
  21280. {
  21281. core.AbstractFilter.call(this,
  21282. // vertex shader
  21283. null,
  21284. // fragment shader
  21285. "precision mediump float;\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\n\nvoid main(void)\n{\n float lum = length(texture2D(uSampler, vTextureCoord.xy).rgb);\n\n gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n\n if (lum < 1.00)\n {\n if (mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0)\n {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n }\n }\n\n if (lum < 0.75)\n {\n if (mod(gl_FragCoord.x - gl_FragCoord.y, 10.0) == 0.0)\n {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n }\n }\n\n if (lum < 0.50)\n {\n if (mod(gl_FragCoord.x + gl_FragCoord.y - 5.0, 10.0) == 0.0)\n {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n }\n }\n\n if (lum < 0.3)\n {\n if (mod(gl_FragCoord.x - gl_FragCoord.y - 5.0, 10.0) == 0.0)\n {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n }\n }\n}\n"
  21286. );
  21287. }
  21288. CrossHatchFilter.prototype = Object.create(core.AbstractFilter.prototype);
  21289. CrossHatchFilter.prototype.constructor = CrossHatchFilter;
  21290. module.exports = CrossHatchFilter;
  21291. },{"../../core":29}],98:[function(require,module,exports){
  21292. var core = require('../../core');
  21293. // @see https://github.com/substack/brfs/issues/25
  21294. /**
  21295. * The DisplacementFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object.
  21296. * You can use this filter to apply all manor of crazy warping effects
  21297. * Currently the r property of the texture is used to offset the x and the g property of the texture is used to offset the y.
  21298. *
  21299. * @class
  21300. * @extends PIXI.AbstractFilter
  21301. * @memberof PIXI.filters
  21302. * @param sprite {PIXI.Sprite} the sprite used for the displacement map. (make sure its added to the scene!)
  21303. */
  21304. function DisplacementFilter(sprite, scale)
  21305. {
  21306. var maskMatrix = new core.Matrix();
  21307. sprite.renderable = false;
  21308. core.AbstractFilter.call(this,
  21309. // vertex shader
  21310. "attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\n\nuniform mat3 projectionMatrix;\nuniform mat3 otherMatrix;\n\nvarying vec2 vMapCoord;\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n vMapCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}\n",
  21311. // fragment shader
  21312. "precision mediump float;\n\nvarying vec2 vMapCoord;\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform vec2 scale;\n\nuniform sampler2D uSampler;\nuniform sampler2D mapSampler;\n\nvoid main(void)\n{\n vec4 map = texture2D(mapSampler, vMapCoord);\n\n map -= 0.5;\n map.xy *= scale;\n\n gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y));\n}\n",
  21313. // uniforms
  21314. {
  21315. mapSampler: { type: 'sampler2D', value: sprite.texture },
  21316. otherMatrix: { type: 'mat3', value: maskMatrix.toArray(true) },
  21317. scale: { type: 'v2', value: { x: 1, y: 1 } }
  21318. }
  21319. );
  21320. this.maskSprite = sprite;
  21321. this.maskMatrix = maskMatrix;
  21322. if (scale === null || scale === undefined)
  21323. {
  21324. scale = 20;
  21325. }
  21326. this.scale = new core.Point(scale, scale);
  21327. }
  21328. DisplacementFilter.prototype = Object.create(core.AbstractFilter.prototype);
  21329. DisplacementFilter.prototype.constructor = DisplacementFilter;
  21330. module.exports = DisplacementFilter;
  21331. DisplacementFilter.prototype.applyFilter = function (renderer, input, output)
  21332. {
  21333. var filterManager = renderer.filterManager;
  21334. filterManager.calculateMappedMatrix(input.frame, this.maskSprite, this.maskMatrix);
  21335. this.uniforms.otherMatrix.value = this.maskMatrix.toArray(true);
  21336. this.uniforms.scale.value.x = this.scale.x * (1/input.frame.width);
  21337. this.uniforms.scale.value.y = this.scale.y * (1/input.frame.height);
  21338. var shader = this.getShader(renderer);
  21339. // draw the filter...
  21340. filterManager.applyFilter(shader, input, output);
  21341. };
  21342. Object.defineProperties(DisplacementFilter.prototype, {
  21343. /**
  21344. * The texture used for the displacement map. Must be power of 2 sized texture.
  21345. *
  21346. * @member {PIXI.Texture}
  21347. * @memberof PIXI.filters.DisplacementFilter#
  21348. */
  21349. map: {
  21350. get: function ()
  21351. {
  21352. return this.uniforms.mapSampler.value;
  21353. },
  21354. set: function (value)
  21355. {
  21356. this.uniforms.mapSampler.value = value;
  21357. }
  21358. }
  21359. });
  21360. },{"../../core":29}],99:[function(require,module,exports){
  21361. var core = require('../../core');
  21362. // @see https://github.com/substack/brfs/issues/25
  21363. /**
  21364. * @author Mat Groves http://matgroves.com/ @Doormat23
  21365. * original filter: https://github.com/evanw/glfx.js/blob/master/src/filters/fun/dotscreen.js
  21366. */
  21367. /**
  21368. * This filter applies a dotscreen effect making display objects appear to be made out of
  21369. * black and white halftone dots like an old printer.
  21370. *
  21371. * @class
  21372. * @extends PIXI.AbstractFilter
  21373. * @memberof PIXI.filters
  21374. */
  21375. function DotScreenFilter()
  21376. {
  21377. core.AbstractFilter.call(this,
  21378. // vertex shader
  21379. null,
  21380. // fragment shader
  21381. "precision mediump float;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform vec4 dimensions;\nuniform sampler2D uSampler;\n\nuniform float angle;\nuniform float scale;\n\nfloat pattern()\n{\n float s = sin(angle), c = cos(angle);\n vec2 tex = vTextureCoord * dimensions.xy;\n vec2 point = vec2(\n c * tex.x - s * tex.y,\n s * tex.x + c * tex.y\n ) * scale;\n return (sin(point.x) * sin(point.y)) * 4.0;\n}\n\nvoid main()\n{\n vec4 color = texture2D(uSampler, vTextureCoord);\n float average = (color.r + color.g + color.b) / 3.0;\n gl_FragColor = vec4(vec3(average * 10.0 - 5.0 + pattern()), color.a);\n}\n",
  21382. // custom uniforms
  21383. {
  21384. scale: { type: '1f', value: 1 },
  21385. angle: { type: '1f', value: 5 },
  21386. dimensions: { type: '4fv', value: [0, 0, 0, 0] }
  21387. }
  21388. );
  21389. }
  21390. DotScreenFilter.prototype = Object.create(core.AbstractFilter.prototype);
  21391. DotScreenFilter.prototype.constructor = DotScreenFilter;
  21392. module.exports = DotScreenFilter;
  21393. Object.defineProperties(DotScreenFilter.prototype, {
  21394. /**
  21395. * The scale of the effect.
  21396. * @member {number}
  21397. * @memberof PIXI.filters.DotScreenFilter#
  21398. */
  21399. scale: {
  21400. get: function ()
  21401. {
  21402. return this.uniforms.scale.value;
  21403. },
  21404. set: function (value)
  21405. {
  21406. this.uniforms.scale.value = value;
  21407. }
  21408. },
  21409. /**
  21410. * The radius of the effect.
  21411. * @member {number}
  21412. * @memberof PIXI.filters.DotScreenFilter#
  21413. */
  21414. angle: {
  21415. get: function ()
  21416. {
  21417. return this.uniforms.angle.value;
  21418. },
  21419. set: function (value)
  21420. {
  21421. this.uniforms.angle.value = value;
  21422. }
  21423. }
  21424. });
  21425. },{"../../core":29}],100:[function(require,module,exports){
  21426. var core = require('../../core');
  21427. // @see https://github.com/substack/brfs/issues/25
  21428. /**
  21429. * The BlurYTintFilter applies a vertical Gaussian blur to an object.
  21430. *
  21431. * @class
  21432. * @extends PIXI.AbstractFilter
  21433. * @memberof PIXI.filters
  21434. */
  21435. function BlurYTintFilter()
  21436. {
  21437. core.AbstractFilter.call(this,
  21438. // vertex shader
  21439. "attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\n\nuniform float strength;\nuniform vec2 offset;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\nvarying vec2 vBlurTexCoords[6];\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3((aVertexPosition+offset), 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n\n vBlurTexCoords[ 0] = aTextureCoord + vec2(0.0, -0.012 * strength);\n vBlurTexCoords[ 1] = aTextureCoord + vec2(0.0, -0.008 * strength);\n vBlurTexCoords[ 2] = aTextureCoord + vec2(0.0, -0.004 * strength);\n vBlurTexCoords[ 3] = aTextureCoord + vec2(0.0, 0.004 * strength);\n vBlurTexCoords[ 4] = aTextureCoord + vec2(0.0, 0.008 * strength);\n vBlurTexCoords[ 5] = aTextureCoord + vec2(0.0, 0.012 * strength);\n\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}\n",
  21440. // fragment shader
  21441. "precision lowp float;\n\nvarying vec2 vTextureCoord;\nvarying vec2 vBlurTexCoords[6];\nvarying vec4 vColor;\n\nuniform vec3 color;\nuniform float alpha;\n\nuniform sampler2D uSampler;\n\nvoid main(void)\n{\n vec4 sum = vec4(0.0);\n\n sum += texture2D(uSampler, vBlurTexCoords[ 0])*0.004431848411938341;\n sum += texture2D(uSampler, vBlurTexCoords[ 1])*0.05399096651318985;\n sum += texture2D(uSampler, vBlurTexCoords[ 2])*0.2419707245191454;\n sum += texture2D(uSampler, vTextureCoord )*0.3989422804014327;\n sum += texture2D(uSampler, vBlurTexCoords[ 3])*0.2419707245191454;\n sum += texture2D(uSampler, vBlurTexCoords[ 4])*0.05399096651318985;\n sum += texture2D(uSampler, vBlurTexCoords[ 5])*0.004431848411938341;\n\n gl_FragColor = vec4( color.rgb * sum.a * alpha, sum.a * alpha );\n}\n",
  21442. // set the uniforms
  21443. {
  21444. blur: { type: '1f', value: 1 / 512 },
  21445. color: { type: 'c', value: [0,0,0]},
  21446. alpha: { type: '1f', value: 0.7 },
  21447. offset: { type: '2f', value:[5, 5]},
  21448. strength: { type: '1f', value:1}
  21449. }
  21450. );
  21451. this.passes = 1;
  21452. this.strength = 4;
  21453. }
  21454. BlurYTintFilter.prototype = Object.create(core.AbstractFilter.prototype);
  21455. BlurYTintFilter.prototype.constructor = BlurYTintFilter;
  21456. module.exports = BlurYTintFilter;
  21457. BlurYTintFilter.prototype.applyFilter = function (renderer, input, output, clear)
  21458. {
  21459. var shader = this.getShader(renderer);
  21460. this.uniforms.strength.value = this.strength / 4 / this.passes * (input.frame.height / input.size.height);
  21461. if(this.passes === 1)
  21462. {
  21463. renderer.filterManager.applyFilter(shader, input, output, clear);
  21464. }
  21465. else
  21466. {
  21467. var renderTarget = renderer.filterManager.getRenderTarget(true);
  21468. var flip = input;
  21469. var flop = renderTarget;
  21470. for(var i = 0; i < this.passes-1; i++)
  21471. {
  21472. renderer.filterManager.applyFilter(shader, flip, flop, clear);
  21473. var temp = flop;
  21474. flop = flip;
  21475. flip = temp;
  21476. }
  21477. renderer.filterManager.applyFilter(shader, flip, output, clear);
  21478. renderer.filterManager.returnRenderTarget(renderTarget);
  21479. }
  21480. };
  21481. Object.defineProperties(BlurYTintFilter.prototype, {
  21482. /**
  21483. * Sets the strength of both the blur.
  21484. *
  21485. * @member {number}
  21486. * @memberof PIXI.filters.BlurYTintFilter#
  21487. * @default 2
  21488. */
  21489. blur: {
  21490. get: function ()
  21491. {
  21492. return this.strength;
  21493. },
  21494. set: function (value)
  21495. {
  21496. this.padding = value * 0.5;
  21497. this.strength = value;
  21498. }
  21499. }
  21500. });
  21501. },{"../../core":29}],101:[function(require,module,exports){
  21502. var core = require('../../core'),
  21503. BlurXFilter = require('../blur/BlurXFilter'),
  21504. BlurYTintFilter = require('./BlurYTintFilter');
  21505. /**
  21506. * The DropShadowFilter applies a Gaussian blur to an object.
  21507. * The strength of the blur can be set for x- and y-axis separately.
  21508. *
  21509. * @class
  21510. * @extends PIXI.AbstractFilter
  21511. * @memberof PIXI.filters
  21512. */
  21513. function DropShadowFilter()
  21514. {
  21515. core.AbstractFilter.call(this);
  21516. this.blurXFilter = new BlurXFilter();
  21517. this.blurYTintFilter = new BlurYTintFilter();
  21518. this.defaultFilter = new core.AbstractFilter();
  21519. this.padding = 30;
  21520. this._dirtyPosition = true;
  21521. this._angle = 45 * Math.PI / 180;
  21522. this._distance = 10;
  21523. this.alpha = 0.75;
  21524. this.hideObject = false;
  21525. this.blendMode = core.BLEND_MODES.MULTIPLY;
  21526. }
  21527. DropShadowFilter.prototype = Object.create(core.AbstractFilter.prototype);
  21528. DropShadowFilter.prototype.constructor = DropShadowFilter;
  21529. module.exports = DropShadowFilter;
  21530. DropShadowFilter.prototype.applyFilter = function (renderer, input, output)
  21531. {
  21532. var renderTarget = renderer.filterManager.getRenderTarget(true);
  21533. //TODO - copyTexSubImage2D could be used here?
  21534. if(this._dirtyPosition)
  21535. {
  21536. this._dirtyPosition = false;
  21537. this.blurYTintFilter.uniforms.offset.value[0] = Math.sin(this._angle) * this._distance;
  21538. this.blurYTintFilter.uniforms.offset.value[1] = Math.cos(this._angle) * this._distance;
  21539. }
  21540. this.blurXFilter.applyFilter(renderer, input, renderTarget);
  21541. renderer.blendModeManager.setBlendMode(this.blendMode);
  21542. this.blurYTintFilter.applyFilter(renderer, renderTarget, output);
  21543. renderer.blendModeManager.setBlendMode(core.BLEND_MODES.NORMAL);
  21544. if(!this.hideObject)
  21545. {
  21546. this.defaultFilter.applyFilter(renderer, input, output);
  21547. }
  21548. renderer.filterManager.returnRenderTarget(renderTarget);
  21549. };
  21550. Object.defineProperties(DropShadowFilter.prototype, {
  21551. /**
  21552. * Sets the strength of both the blurX and blurY properties simultaneously
  21553. *
  21554. * @member {number}
  21555. * @memberOf PIXI.filters.DropShadowFilter#
  21556. * @default 2
  21557. */
  21558. blur: {
  21559. get: function ()
  21560. {
  21561. return this.blurXFilter.blur;
  21562. },
  21563. set: function (value)
  21564. {
  21565. this.blurXFilter.blur = this.blurYTintFilter.blur = value;
  21566. }
  21567. },
  21568. /**
  21569. * Sets the strength of the blurX property
  21570. *
  21571. * @member {number}
  21572. * @memberOf PIXI.filters.DropShadowFilter#
  21573. * @default 2
  21574. */
  21575. blurX: {
  21576. get: function ()
  21577. {
  21578. return this.blurXFilter.blur;
  21579. },
  21580. set: function (value)
  21581. {
  21582. this.blurXFilter.blur = value;
  21583. }
  21584. },
  21585. /**
  21586. * Sets the strength of the blurY property
  21587. *
  21588. * @member {number}
  21589. * @memberOf PIXI.filters.DropShadowFilter#
  21590. * @default 2
  21591. */
  21592. blurY: {
  21593. get: function ()
  21594. {
  21595. return this.blurYTintFilter.blur;
  21596. },
  21597. set: function (value)
  21598. {
  21599. this.blurYTintFilter.blur = value;
  21600. }
  21601. },
  21602. /**
  21603. * Sets the color of the shadow
  21604. *
  21605. * @member {number}
  21606. * @memberOf PIXI.filters.DropShadowFilter#
  21607. */
  21608. color: {
  21609. get: function ()
  21610. {
  21611. return core.utils.rgb2hex( this.blurYTintFilter.uniforms.color.value );
  21612. },
  21613. set: function (value)
  21614. {
  21615. this.blurYTintFilter.uniforms.color.value = core.utils.hex2rgb(value);
  21616. }
  21617. },
  21618. /**
  21619. * Sets the alpha of the shadow
  21620. *
  21621. * @member {number}
  21622. * @memberOf PIXI.filters.DropShadowFilter#
  21623. */
  21624. alpha: {
  21625. get: function ()
  21626. {
  21627. return this.blurYTintFilter.uniforms.alpha.value;
  21628. },
  21629. set: function (value)
  21630. {
  21631. this.blurYTintFilter.uniforms.alpha.value = value;
  21632. }
  21633. },
  21634. /**
  21635. * Sets the distance of the shadow
  21636. *
  21637. * @member {number}
  21638. * @memberOf PIXI.filters.DropShadowFilter#
  21639. */
  21640. distance: {
  21641. get: function ()
  21642. {
  21643. return this._distance;
  21644. },
  21645. set: function (value)
  21646. {
  21647. this._dirtyPosition = true;
  21648. this._distance = value;
  21649. }
  21650. },
  21651. /**
  21652. * Sets the angle of the shadow
  21653. *
  21654. * @member {number}
  21655. * @memberOf PIXI.filters.DropShadowFilter#
  21656. */
  21657. angle: {
  21658. get: function ()
  21659. {
  21660. return this._angle;
  21661. },
  21662. set: function (value)
  21663. {
  21664. this._dirtyPosition = true;
  21665. this._angle = value;
  21666. }
  21667. }
  21668. });
  21669. },{"../../core":29,"../blur/BlurXFilter":91,"./BlurYTintFilter":100}],102:[function(require,module,exports){
  21670. var core = require('../../core');
  21671. // @see https://github.com/substack/brfs/issues/25
  21672. /**
  21673. * This greyscales the palette of your Display Objects.
  21674. *
  21675. * @class
  21676. * @extends PIXI.AbstractFilter
  21677. * @memberof PIXI.filters
  21678. */
  21679. function GrayFilter()
  21680. {
  21681. core.AbstractFilter.call(this,
  21682. // vertex shader
  21683. null,
  21684. // fragment shader
  21685. "precision mediump float;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform sampler2D uSampler;\nuniform float gray;\n\nvoid main(void)\n{\n gl_FragColor = texture2D(uSampler, vTextureCoord);\n gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), gray);\n}\n",
  21686. // set the uniforms
  21687. {
  21688. gray: { type: '1f', value: 1 }
  21689. }
  21690. );
  21691. }
  21692. GrayFilter.prototype = Object.create(core.AbstractFilter.prototype);
  21693. GrayFilter.prototype.constructor = GrayFilter;
  21694. module.exports = GrayFilter;
  21695. Object.defineProperties(GrayFilter.prototype, {
  21696. /**
  21697. * The strength of the gray. 1 will make the object black and white, 0 will make the object its normal color.
  21698. *
  21699. * @member {number}
  21700. * @memberof PIXI.filters.GrayFilter#
  21701. */
  21702. gray: {
  21703. get: function ()
  21704. {
  21705. return this.uniforms.gray.value;
  21706. },
  21707. set: function (value)
  21708. {
  21709. this.uniforms.gray.value = value;
  21710. }
  21711. }
  21712. });
  21713. },{"../../core":29}],103:[function(require,module,exports){
  21714. /**
  21715. * @file Main export of the PIXI filters library
  21716. * @author Mat Groves <mat@goodboydigital.com>
  21717. * @copyright 2013-2015 GoodBoyDigital
  21718. * @license {@link https://github.com/pixijs/pixi.js/blob/master/LICENSE|MIT License}
  21719. */
  21720. /**
  21721. * @namespace PIXI.filters
  21722. */
  21723. module.exports = {
  21724. AsciiFilter: require('./ascii/AsciiFilter'),
  21725. BloomFilter: require('./bloom/BloomFilter'),
  21726. BlurFilter: require('./blur/BlurFilter'),
  21727. BlurXFilter: require('./blur/BlurXFilter'),
  21728. BlurYFilter: require('./blur/BlurYFilter'),
  21729. BlurDirFilter: require('./blur/BlurDirFilter'),
  21730. ColorMatrixFilter: require('./color/ColorMatrixFilter'),
  21731. ColorStepFilter: require('./color/ColorStepFilter'),
  21732. ConvolutionFilter: require('./convolution/ConvolutionFilter'),
  21733. CrossHatchFilter: require('./crosshatch/CrossHatchFilter'),
  21734. DisplacementFilter: require('./displacement/DisplacementFilter'),
  21735. DotScreenFilter: require('./dot/DotScreenFilter'),
  21736. GrayFilter: require('./gray/GrayFilter'),
  21737. DropShadowFilter: require('./dropshadow/DropShadowFilter'),
  21738. InvertFilter: require('./invert/InvertFilter'),
  21739. NoiseFilter: require('./noise/NoiseFilter'),
  21740. PixelateFilter: require('./pixelate/PixelateFilter'),
  21741. RGBSplitFilter: require('./rgb/RGBSplitFilter'),
  21742. ShockwaveFilter: require('./shockwave/ShockwaveFilter'),
  21743. SepiaFilter: require('./sepia/SepiaFilter'),
  21744. SmartBlurFilter: require('./blur/SmartBlurFilter'),
  21745. TiltShiftFilter: require('./tiltshift/TiltShiftFilter'),
  21746. TiltShiftXFilter: require('./tiltshift/TiltShiftXFilter'),
  21747. TiltShiftYFilter: require('./tiltshift/TiltShiftYFilter'),
  21748. TwistFilter: require('./twist/TwistFilter')
  21749. };
  21750. },{"./ascii/AsciiFilter":87,"./bloom/BloomFilter":88,"./blur/BlurDirFilter":89,"./blur/BlurFilter":90,"./blur/BlurXFilter":91,"./blur/BlurYFilter":92,"./blur/SmartBlurFilter":93,"./color/ColorMatrixFilter":94,"./color/ColorStepFilter":95,"./convolution/ConvolutionFilter":96,"./crosshatch/CrossHatchFilter":97,"./displacement/DisplacementFilter":98,"./dot/DotScreenFilter":99,"./dropshadow/DropShadowFilter":101,"./gray/GrayFilter":102,"./invert/InvertFilter":104,"./noise/NoiseFilter":105,"./pixelate/PixelateFilter":106,"./rgb/RGBSplitFilter":107,"./sepia/SepiaFilter":108,"./shockwave/ShockwaveFilter":109,"./tiltshift/TiltShiftFilter":111,"./tiltshift/TiltShiftXFilter":112,"./tiltshift/TiltShiftYFilter":113,"./twist/TwistFilter":114}],104:[function(require,module,exports){
  21751. var core = require('../../core');
  21752. // @see https://github.com/substack/brfs/issues/25
  21753. /**
  21754. * This inverts your Display Objects colors.
  21755. *
  21756. * @class
  21757. * @extends PIXI.AbstractFilter
  21758. * @memberof PIXI.filters
  21759. */
  21760. function InvertFilter()
  21761. {
  21762. core.AbstractFilter.call(this,
  21763. // vertex shader
  21764. null,
  21765. // fragment shader
  21766. "precision mediump float;\n\nvarying vec2 vTextureCoord;\n\nuniform float invert;\nuniform sampler2D uSampler;\n\nvoid main(void)\n{\n gl_FragColor = texture2D(uSampler, vTextureCoord);\n\n gl_FragColor.rgb = mix( (vec3(1)-gl_FragColor.rgb) * gl_FragColor.a, gl_FragColor.rgb, 1.0 - invert);\n}\n",
  21767. // custom uniforms
  21768. {
  21769. invert: { type: '1f', value: 1 }
  21770. }
  21771. );
  21772. }
  21773. InvertFilter.prototype = Object.create(core.AbstractFilter.prototype);
  21774. InvertFilter.prototype.constructor = InvertFilter;
  21775. module.exports = InvertFilter;
  21776. Object.defineProperties(InvertFilter.prototype, {
  21777. /**
  21778. * The strength of the invert. `1` will fully invert the colors, and
  21779. * `0` will make the object its normal color.
  21780. *
  21781. * @member {number}
  21782. * @memberof PIXI.filters.InvertFilter#
  21783. */
  21784. invert: {
  21785. get: function ()
  21786. {
  21787. return this.uniforms.invert.value;
  21788. },
  21789. set: function (value)
  21790. {
  21791. this.uniforms.invert.value = value;
  21792. }
  21793. }
  21794. });
  21795. },{"../../core":29}],105:[function(require,module,exports){
  21796. var core = require('../../core');
  21797. // @see https://github.com/substack/brfs/issues/25
  21798. /**
  21799. * @author Vico @vicocotea
  21800. * original filter: https://github.com/evanw/glfx.js/blob/master/src/filters/adjust/noise.js
  21801. */
  21802. /**
  21803. * A Noise effect filter.
  21804. *
  21805. * @class
  21806. * @extends PIXI.AbstractFilter
  21807. * @memberof PIXI.filters
  21808. */
  21809. function NoiseFilter()
  21810. {
  21811. core.AbstractFilter.call(this,
  21812. // vertex shader
  21813. null,
  21814. // fragment shader
  21815. "precision highp float;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform float noise;\nuniform sampler2D uSampler;\n\nfloat rand(vec2 co)\n{\n return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);\n}\n\nvoid main()\n{\n vec4 color = texture2D(uSampler, vTextureCoord);\n\n float diff = (rand(vTextureCoord) - 0.5) * noise;\n\n color.r += diff;\n color.g += diff;\n color.b += diff;\n\n gl_FragColor = color;\n}\n",
  21816. // custom uniforms
  21817. {
  21818. noise: { type: '1f', value: 0.5 }
  21819. }
  21820. );
  21821. }
  21822. NoiseFilter.prototype = Object.create(core.AbstractFilter.prototype);
  21823. NoiseFilter.prototype.constructor = NoiseFilter;
  21824. module.exports = NoiseFilter;
  21825. Object.defineProperties(NoiseFilter.prototype, {
  21826. /**
  21827. * The amount of noise to apply.
  21828. *
  21829. * @member {number}
  21830. * @memberof PIXI.filters.NoiseFilter#
  21831. * @default 0.5
  21832. */
  21833. noise: {
  21834. get: function ()
  21835. {
  21836. return this.uniforms.noise.value;
  21837. },
  21838. set: function (value)
  21839. {
  21840. this.uniforms.noise.value = value;
  21841. }
  21842. }
  21843. });
  21844. },{"../../core":29}],106:[function(require,module,exports){
  21845. var core = require('../../core');
  21846. // @see https://github.com/substack/brfs/issues/25
  21847. /**
  21848. * This filter applies a pixelate effect making display objects appear 'blocky'.
  21849. *
  21850. * @class
  21851. * @extends PIXI.AbstractFilter
  21852. * @memberof PIXI.filters
  21853. */
  21854. function PixelateFilter()
  21855. {
  21856. core.AbstractFilter.call(this,
  21857. // vertex shader
  21858. null,
  21859. // fragment shader
  21860. "precision mediump float;\n\nvarying vec2 vTextureCoord;\n\nuniform vec4 dimensions;\nuniform vec2 pixelSize;\nuniform sampler2D uSampler;\n\nvoid main(void)\n{\n vec2 coord = vTextureCoord;\n\n vec2 size = dimensions.xy / pixelSize;\n\n vec2 color = floor( ( vTextureCoord * size ) ) / size + pixelSize/dimensions.xy * 0.5;\n\n gl_FragColor = texture2D(uSampler, color);\n}\n",
  21861. // custom uniforms
  21862. {
  21863. dimensions: { type: '4fv', value: new Float32Array([0, 0, 0, 0]) },
  21864. pixelSize: { type: 'v2', value: { x: 10, y: 10 } }
  21865. }
  21866. );
  21867. }
  21868. PixelateFilter.prototype = Object.create(core.AbstractFilter.prototype);
  21869. PixelateFilter.prototype.constructor = PixelateFilter;
  21870. module.exports = PixelateFilter;
  21871. Object.defineProperties(PixelateFilter.prototype, {
  21872. /**
  21873. * This a point that describes the size of the blocks.
  21874. * x is the width of the block and y is the height.
  21875. *
  21876. * @member {PIXI.Point}
  21877. * @memberof PIXI.filters.PixelateFilter#
  21878. */
  21879. size: {
  21880. get: function ()
  21881. {
  21882. return this.uniforms.pixelSize.value;
  21883. },
  21884. set: function (value)
  21885. {
  21886. this.uniforms.pixelSize.value = value;
  21887. }
  21888. }
  21889. });
  21890. },{"../../core":29}],107:[function(require,module,exports){
  21891. var core = require('../../core');
  21892. // @see https://github.com/substack/brfs/issues/25
  21893. /**
  21894. * An RGB Split Filter.
  21895. *
  21896. * @class
  21897. * @extends PIXI.AbstractFilter
  21898. * @memberof PIXI.filters
  21899. */
  21900. function RGBSplitFilter()
  21901. {
  21902. core.AbstractFilter.call(this,
  21903. // vertex shader
  21904. null,
  21905. // fragment shader
  21906. "precision mediump float;\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform vec4 dimensions;\nuniform vec2 red;\nuniform vec2 green;\nuniform vec2 blue;\n\nvoid main(void)\n{\n gl_FragColor.r = texture2D(uSampler, vTextureCoord + red/dimensions.xy).r;\n gl_FragColor.g = texture2D(uSampler, vTextureCoord + green/dimensions.xy).g;\n gl_FragColor.b = texture2D(uSampler, vTextureCoord + blue/dimensions.xy).b;\n gl_FragColor.a = texture2D(uSampler, vTextureCoord).a;\n}\n",
  21907. // custom uniforms
  21908. {
  21909. red: { type: 'v2', value: { x: 20, y: 20 } },
  21910. green: { type: 'v2', value: { x: -20, y: 20 } },
  21911. blue: { type: 'v2', value: { x: 20, y: -20 } },
  21912. dimensions: { type: '4fv', value: [0, 0, 0, 0] }
  21913. }
  21914. );
  21915. }
  21916. RGBSplitFilter.prototype = Object.create(core.AbstractFilter.prototype);
  21917. RGBSplitFilter.prototype.constructor = RGBSplitFilter;
  21918. module.exports = RGBSplitFilter;
  21919. Object.defineProperties(RGBSplitFilter.prototype, {
  21920. /**
  21921. * Red channel offset.
  21922. *
  21923. * @member {PIXI.Point}
  21924. * @memberof PIXI.filters.RGBSplitFilter#
  21925. */
  21926. red: {
  21927. get: function ()
  21928. {
  21929. return this.uniforms.red.value;
  21930. },
  21931. set: function (value)
  21932. {
  21933. this.uniforms.red.value = value;
  21934. }
  21935. },
  21936. /**
  21937. * Green channel offset.
  21938. *
  21939. * @member {PIXI.Point}
  21940. * @memberof PIXI.filters.RGBSplitFilter#
  21941. */
  21942. green: {
  21943. get: function ()
  21944. {
  21945. return this.uniforms.green.value;
  21946. },
  21947. set: function (value)
  21948. {
  21949. this.uniforms.green.value = value;
  21950. }
  21951. },
  21952. /**
  21953. * Blue offset.
  21954. *
  21955. * @member {PIXI.Point}
  21956. * @memberof PIXI.filters.RGBSplitFilter#
  21957. */
  21958. blue: {
  21959. get: function ()
  21960. {
  21961. return this.uniforms.blue.value;
  21962. },
  21963. set: function (value)
  21964. {
  21965. this.uniforms.blue.value = value;
  21966. }
  21967. }
  21968. });
  21969. },{"../../core":29}],108:[function(require,module,exports){
  21970. var core = require('../../core');
  21971. // @see https://github.com/substack/brfs/issues/25
  21972. /**
  21973. * This applies a sepia effect to your Display Objects.
  21974. *
  21975. * @class
  21976. * @extends PIXI.AbstractFilter
  21977. * @memberof PIXI.filters
  21978. */
  21979. function SepiaFilter()
  21980. {
  21981. core.AbstractFilter.call(this,
  21982. // vertex shader
  21983. null,
  21984. // fragment shader
  21985. "precision mediump float;\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float sepia;\n\nconst mat3 sepiaMatrix = mat3(0.3588, 0.7044, 0.1368, 0.2990, 0.5870, 0.1140, 0.2392, 0.4696, 0.0912);\n\nvoid main(void)\n{\n gl_FragColor = texture2D(uSampler, vTextureCoord);\n gl_FragColor.rgb = mix( gl_FragColor.rgb, gl_FragColor.rgb * sepiaMatrix, sepia);\n}\n",
  21986. // custom uniforms
  21987. {
  21988. sepia: { type: '1f', value: 1 }
  21989. }
  21990. );
  21991. }
  21992. SepiaFilter.prototype = Object.create(core.AbstractFilter.prototype);
  21993. SepiaFilter.prototype.constructor = SepiaFilter;
  21994. module.exports = SepiaFilter;
  21995. Object.defineProperties(SepiaFilter.prototype, {
  21996. /**
  21997. * The strength of the sepia. `1` will apply the full sepia effect, and
  21998. * `0` will make the object its normal color.
  21999. *
  22000. * @member {number}
  22001. * @memberof PIXI.filters.SepiaFilter#
  22002. */
  22003. sepia: {
  22004. get: function ()
  22005. {
  22006. return this.uniforms.sepia.value;
  22007. },
  22008. set: function (value)
  22009. {
  22010. this.uniforms.sepia.value = value;
  22011. }
  22012. }
  22013. });
  22014. },{"../../core":29}],109:[function(require,module,exports){
  22015. var core = require('../../core');
  22016. // @see https://github.com/substack/brfs/issues/25
  22017. /**
  22018. * The ColorMatrixFilter class lets you apply a 4x4 matrix transformation on the RGBA
  22019. * color and alpha values of every pixel on your displayObject to produce a result
  22020. * with a new set of RGBA color and alpha values. It's pretty powerful!
  22021. *
  22022. * @class
  22023. * @extends PIXI.AbstractFilter
  22024. * @memberof PIXI.filters
  22025. */
  22026. function ShockwaveFilter()
  22027. {
  22028. core.AbstractFilter.call(this,
  22029. // vertex shader
  22030. null,
  22031. // fragment shader
  22032. "precision lowp float;\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\n\nuniform vec2 center;\nuniform vec3 params; // 10.0, 0.8, 0.1\nuniform float time;\n\nvoid main()\n{\n vec2 uv = vTextureCoord;\n vec2 texCoord = uv;\n\n float dist = distance(uv, center);\n\n if ( (dist <= (time + params.z)) && (dist >= (time - params.z)) )\n {\n float diff = (dist - time);\n float powDiff = 1.0 - pow(abs(diff*params.x), params.y);\n\n float diffTime = diff * powDiff;\n vec2 diffUV = normalize(uv - center);\n texCoord = uv + (diffUV * diffTime);\n }\n\n gl_FragColor = texture2D(uSampler, texCoord);\n}\n",
  22033. // custom uniforms
  22034. {
  22035. center: { type: 'v2', value: { x: 0.5, y: 0.5 } },
  22036. params: { type: 'v3', value: { x: 10, y: 0.8, z: 0.1 } },
  22037. time: { type: '1f', value: 0 }
  22038. }
  22039. );
  22040. }
  22041. ShockwaveFilter.prototype = Object.create(core.AbstractFilter.prototype);
  22042. ShockwaveFilter.prototype.constructor = ShockwaveFilter;
  22043. module.exports = ShockwaveFilter;
  22044. Object.defineProperties(ShockwaveFilter.prototype, {
  22045. /**
  22046. * Sets the center of the shockwave in normalized screen coords. That is
  22047. * (0,0) is the top-left and (1,1) is the bottom right.
  22048. *
  22049. * @member {object<string, number>}
  22050. * @memberof PIXI.filters.ShockwaveFilter#
  22051. */
  22052. center: {
  22053. get: function ()
  22054. {
  22055. return this.uniforms.center.value;
  22056. },
  22057. set: function (value)
  22058. {
  22059. this.uniforms.center.value = value;
  22060. }
  22061. },
  22062. /**
  22063. * Sets the params of the shockwave. These modify the look and behavior of
  22064. * the shockwave as it ripples out.
  22065. *
  22066. * @member {object<string, number>}
  22067. * @memberof PIXI.filters.ShockwaveFilter#
  22068. */
  22069. params: {
  22070. get: function ()
  22071. {
  22072. return this.uniforms.params.value;
  22073. },
  22074. set: function (value)
  22075. {
  22076. this.uniforms.params.value = value;
  22077. }
  22078. },
  22079. /**
  22080. * Sets the elapsed time of the shockwave. This controls the speed at which
  22081. * the shockwave ripples out.
  22082. *
  22083. * @member {number}
  22084. * @memberof PIXI.filters.ShockwaveFilter#
  22085. */
  22086. time: {
  22087. get: function ()
  22088. {
  22089. return this.uniforms.time.value;
  22090. },
  22091. set: function (value)
  22092. {
  22093. this.uniforms.time.value = value;
  22094. }
  22095. }
  22096. });
  22097. },{"../../core":29}],110:[function(require,module,exports){
  22098. var core = require('../../core');
  22099. // @see https://github.com/substack/brfs/issues/25
  22100. /**
  22101. * @author Vico @vicocotea
  22102. * original filter https://github.com/evanw/glfx.js/blob/master/src/filters/blur/tiltshift.js by Evan Wallace : http://madebyevan.com/
  22103. */
  22104. /**
  22105. * A TiltShiftAxisFilter.
  22106. *
  22107. * @class
  22108. * @extends PIXI.AbstractFilter
  22109. * @memberof PIXI.filters
  22110. */
  22111. function TiltShiftAxisFilter()
  22112. {
  22113. core.AbstractFilter.call(this,
  22114. // vertex shader
  22115. null,
  22116. // fragment shader
  22117. "precision mediump float;\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float blur;\nuniform float gradientBlur;\nuniform vec2 start;\nuniform vec2 end;\nuniform vec2 delta;\nuniform vec2 texSize;\n\nfloat random(vec3 scale, float seed)\n{\n return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);\n}\n\nvoid main(void)\n{\n vec4 color = vec4(0.0);\n float total = 0.0;\n\n float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);\n vec2 normal = normalize(vec2(start.y - end.y, end.x - start.x));\n float radius = smoothstep(0.0, 1.0, abs(dot(vTextureCoord * texSize - start, normal)) / gradientBlur) * blur;\n\n for (float t = -30.0; t <= 30.0; t++)\n {\n float percent = (t + offset - 0.5) / 30.0;\n float weight = 1.0 - abs(percent);\n vec4 sample = texture2D(uSampler, vTextureCoord + delta / texSize * percent * radius);\n sample.rgb *= sample.a;\n color += sample * weight;\n total += weight;\n }\n\n gl_FragColor = color / total;\n gl_FragColor.rgb /= gl_FragColor.a + 0.00001;\n}\n",
  22118. // custom uniforms
  22119. {
  22120. blur: { type: '1f', value: 100 },
  22121. gradientBlur: { type: '1f', value: 600 },
  22122. start: { type: 'v2', value: { x: 0, y: window.innerHeight / 2 } },
  22123. end: { type: 'v2', value: { x: 600, y: window.innerHeight / 2 } },
  22124. delta: { type: 'v2', value: { x: 30, y: 30 } },
  22125. texSize: { type: 'v2', value: { x: window.innerWidth, y: window.innerHeight } }
  22126. }
  22127. );
  22128. this.updateDelta();
  22129. }
  22130. TiltShiftAxisFilter.prototype = Object.create(core.AbstractFilter.prototype);
  22131. TiltShiftAxisFilter.prototype.constructor = TiltShiftAxisFilter;
  22132. module.exports = TiltShiftAxisFilter;
  22133. /**
  22134. * Updates the filter delta values.
  22135. * This is overridden in the X and Y filters, does nothing for this class.
  22136. *
  22137. */
  22138. TiltShiftAxisFilter.prototype.updateDelta = function ()
  22139. {
  22140. this.uniforms.delta.value.x = 0;
  22141. this.uniforms.delta.value.y = 0;
  22142. };
  22143. Object.defineProperties(TiltShiftAxisFilter.prototype, {
  22144. /**
  22145. * The strength of the blur.
  22146. *
  22147. * @member {number}
  22148. * @memberof PIXI.filters.TiltShiftAxisFilter#
  22149. */
  22150. blur: {
  22151. get: function ()
  22152. {
  22153. return this.uniforms.blur.value;
  22154. },
  22155. set: function (value)
  22156. {
  22157. this.uniforms.blur.value = value;
  22158. }
  22159. },
  22160. /**
  22161. * The strength of the gradient blur.
  22162. *
  22163. * @member {number}
  22164. * @memberof PIXI.filters.TiltShiftAxisFilter#
  22165. */
  22166. gradientBlur: {
  22167. get: function ()
  22168. {
  22169. return this.uniforms.gradientBlur.value;
  22170. },
  22171. set: function (value)
  22172. {
  22173. this.uniforms.gradientBlur.value = value;
  22174. }
  22175. },
  22176. /**
  22177. * The X value to start the effect at.
  22178. *
  22179. * @member {PIXI.Point}
  22180. * @memberof PIXI.filters.TiltShiftAxisFilter#
  22181. */
  22182. start: {
  22183. get: function ()
  22184. {
  22185. return this.uniforms.start.value;
  22186. },
  22187. set: function (value)
  22188. {
  22189. this.uniforms.start.value = value;
  22190. this.updateDelta();
  22191. }
  22192. },
  22193. /**
  22194. * The X value to end the effect at.
  22195. *
  22196. * @member {PIXI.Point}
  22197. * @memberof PIXI.filters.TiltShiftAxisFilter#
  22198. */
  22199. end: {
  22200. get: function ()
  22201. {
  22202. return this.uniforms.end.value;
  22203. },
  22204. set: function (value)
  22205. {
  22206. this.uniforms.end.value = value;
  22207. this.updateDelta();
  22208. }
  22209. }
  22210. });
  22211. },{"../../core":29}],111:[function(require,module,exports){
  22212. var core = require('../../core'),
  22213. TiltShiftXFilter = require('./TiltShiftXFilter'),
  22214. TiltShiftYFilter = require('./TiltShiftYFilter');
  22215. /**
  22216. * @author Vico @vicocotea
  22217. * original filter https://github.com/evanw/glfx.js/blob/master/src/filters/blur/tiltshift.js by Evan Wallace : http://madebyevan.com/
  22218. */
  22219. /**
  22220. * A TiltShift Filter. Manages the pass of both a TiltShiftXFilter and TiltShiftYFilter.
  22221. *
  22222. * @class
  22223. * @extends PIXI.AbstractFilter
  22224. * @memberof PIXI.filters
  22225. */
  22226. function TiltShiftFilter()
  22227. {
  22228. core.AbstractFilter.call(this);
  22229. this.tiltShiftXFilter = new TiltShiftXFilter();
  22230. this.tiltShiftYFilter = new TiltShiftYFilter();
  22231. }
  22232. TiltShiftFilter.prototype = Object.create(core.AbstractFilter.prototype);
  22233. TiltShiftFilter.prototype.constructor = TiltShiftFilter;
  22234. module.exports = TiltShiftFilter;
  22235. TiltShiftFilter.prototype.applyFilter = function (renderer, input, output)
  22236. {
  22237. var renderTarget = renderer.filterManager.getRenderTarget(true);
  22238. this.tiltShiftXFilter.applyFilter(renderer, input, renderTarget);
  22239. this.tiltShiftYFilter.applyFilter(renderer, renderTarget, output);
  22240. renderer.filterManager.returnRenderTarget(renderTarget);
  22241. };
  22242. Object.defineProperties(TiltShiftFilter.prototype, {
  22243. /**
  22244. * The strength of the blur.
  22245. *
  22246. * @member {number}
  22247. * @memberof PIXI.filters.TiltShiftFilter#
  22248. */
  22249. blur: {
  22250. get: function ()
  22251. {
  22252. return this.tiltShiftXFilter.blur;
  22253. },
  22254. set: function (value)
  22255. {
  22256. this.tiltShiftXFilter.blur = this.tiltShiftYFilter.blur = value;
  22257. }
  22258. },
  22259. /**
  22260. * The strength of the gradient blur.
  22261. *
  22262. * @member {number}
  22263. * @memberof PIXI.filters.TiltShiftFilter#
  22264. */
  22265. gradientBlur: {
  22266. get: function ()
  22267. {
  22268. return this.tiltShiftXFilter.gradientBlur;
  22269. },
  22270. set: function (value)
  22271. {
  22272. this.tiltShiftXFilter.gradientBlur = this.tiltShiftYFilter.gradientBlur = value;
  22273. }
  22274. },
  22275. /**
  22276. * The Y value to start the effect at.
  22277. *
  22278. * @member {number}
  22279. * @memberof PIXI.filters.TiltShiftFilter#
  22280. */
  22281. start: {
  22282. get: function ()
  22283. {
  22284. return this.tiltShiftXFilter.start;
  22285. },
  22286. set: function (value)
  22287. {
  22288. this.tiltShiftXFilter.start = this.tiltShiftYFilter.start = value;
  22289. }
  22290. },
  22291. /**
  22292. * The Y value to end the effect at.
  22293. *
  22294. * @member {number}
  22295. * @memberof PIXI.filters.TiltShiftFilter#
  22296. */
  22297. end: {
  22298. get: function ()
  22299. {
  22300. return this.tiltShiftXFilter.end;
  22301. },
  22302. set: function (value)
  22303. {
  22304. this.tiltShiftXFilter.end = this.tiltShiftYFilter.end = value;
  22305. }
  22306. }
  22307. });
  22308. },{"../../core":29,"./TiltShiftXFilter":112,"./TiltShiftYFilter":113}],112:[function(require,module,exports){
  22309. var TiltShiftAxisFilter = require('./TiltShiftAxisFilter');
  22310. /**
  22311. * @author Vico @vicocotea
  22312. * original filter https://github.com/evanw/glfx.js/blob/master/src/filters/blur/tiltshift.js by Evan Wallace : http://madebyevan.com/
  22313. */
  22314. /**
  22315. * A TiltShiftXFilter.
  22316. *
  22317. * @class
  22318. * @extends PIXI.TiltShiftAxisFilter
  22319. * @memberof PIXI.filters
  22320. */
  22321. function TiltShiftXFilter()
  22322. {
  22323. TiltShiftAxisFilter.call(this);
  22324. }
  22325. TiltShiftXFilter.prototype = Object.create(TiltShiftAxisFilter.prototype);
  22326. TiltShiftXFilter.prototype.constructor = TiltShiftXFilter;
  22327. module.exports = TiltShiftXFilter;
  22328. /**
  22329. * Updates the filter delta values.
  22330. *
  22331. */
  22332. TiltShiftXFilter.prototype.updateDelta = function ()
  22333. {
  22334. var dx = this.uniforms.end.value.x - this.uniforms.start.value.x;
  22335. var dy = this.uniforms.end.value.y - this.uniforms.start.value.y;
  22336. var d = Math.sqrt(dx * dx + dy * dy);
  22337. this.uniforms.delta.value.x = dx / d;
  22338. this.uniforms.delta.value.y = dy / d;
  22339. };
  22340. },{"./TiltShiftAxisFilter":110}],113:[function(require,module,exports){
  22341. var TiltShiftAxisFilter = require('./TiltShiftAxisFilter');
  22342. /**
  22343. * @author Vico @vicocotea
  22344. * original filter https://github.com/evanw/glfx.js/blob/master/src/filters/blur/tiltshift.js by Evan Wallace : http://madebyevan.com/
  22345. */
  22346. /**
  22347. * A TiltShiftYFilter.
  22348. *
  22349. * @class
  22350. * @extends PIXI.TiltShiftAxisFilter
  22351. * @memberof PIXI.filters
  22352. */
  22353. function TiltShiftYFilter()
  22354. {
  22355. TiltShiftAxisFilter.call(this);
  22356. }
  22357. TiltShiftYFilter.prototype = Object.create(TiltShiftAxisFilter.prototype);
  22358. TiltShiftYFilter.prototype.constructor = TiltShiftYFilter;
  22359. module.exports = TiltShiftYFilter;
  22360. /**
  22361. * Updates the filter delta values.
  22362. *
  22363. */
  22364. TiltShiftYFilter.prototype.updateDelta = function ()
  22365. {
  22366. var dx = this.uniforms.end.value.x - this.uniforms.start.value.x;
  22367. var dy = this.uniforms.end.value.y - this.uniforms.start.value.y;
  22368. var d = Math.sqrt(dx * dx + dy * dy);
  22369. this.uniforms.delta.value.x = -dy / d;
  22370. this.uniforms.delta.value.y = dx / d;
  22371. };
  22372. },{"./TiltShiftAxisFilter":110}],114:[function(require,module,exports){
  22373. var core = require('../../core');
  22374. // @see https://github.com/substack/brfs/issues/25
  22375. /**
  22376. * This filter applies a twist effect making display objects appear twisted in the given direction.
  22377. *
  22378. * @class
  22379. * @extends PIXI.AbstractFilter
  22380. * @memberof PIXI.filters
  22381. */
  22382. function TwistFilter()
  22383. {
  22384. core.AbstractFilter.call(this,
  22385. // vertex shader
  22386. null,
  22387. // fragment shader
  22388. "precision mediump float;\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float radius;\nuniform float angle;\nuniform vec2 offset;\n\nvoid main(void)\n{\n vec2 coord = vTextureCoord - offset;\n float dist = length(coord);\n\n if (dist < radius)\n {\n float ratio = (radius - dist) / radius;\n float angleMod = ratio * ratio * angle;\n float s = sin(angleMod);\n float c = cos(angleMod);\n coord = vec2(coord.x * c - coord.y * s, coord.x * s + coord.y * c);\n }\n\n gl_FragColor = texture2D(uSampler, coord+offset);\n}\n",
  22389. // custom uniforms
  22390. {
  22391. radius: { type: '1f', value: 0.5 },
  22392. angle: { type: '1f', value: 5 },
  22393. offset: { type: 'v2', value: { x: 0.5, y: 0.5 } }
  22394. }
  22395. );
  22396. }
  22397. TwistFilter.prototype = Object.create(core.AbstractFilter.prototype);
  22398. TwistFilter.prototype.constructor = TwistFilter;
  22399. module.exports = TwistFilter;
  22400. Object.defineProperties(TwistFilter.prototype, {
  22401. /**
  22402. * This point describes the the offset of the twist.
  22403. *
  22404. * @member {PIXI.Point}
  22405. * @memberof PIXI.filters.TwistFilter#
  22406. */
  22407. offset: {
  22408. get: function ()
  22409. {
  22410. return this.uniforms.offset.value;
  22411. },
  22412. set: function (value)
  22413. {
  22414. this.uniforms.offset.value = value;
  22415. }
  22416. },
  22417. /**
  22418. * This radius of the twist.
  22419. *
  22420. * @member {number}
  22421. * @memberof PIXI.filters.TwistFilter#
  22422. */
  22423. radius: {
  22424. get: function ()
  22425. {
  22426. return this.uniforms.radius.value;
  22427. },
  22428. set: function (value)
  22429. {
  22430. this.uniforms.radius.value = value;
  22431. }
  22432. },
  22433. /**
  22434. * This angle of the twist.
  22435. *
  22436. * @member {number}
  22437. * @memberof PIXI.filters.TwistFilter#
  22438. */
  22439. angle: {
  22440. get: function ()
  22441. {
  22442. return this.uniforms.angle.value;
  22443. },
  22444. set: function (value)
  22445. {
  22446. this.uniforms.angle.value = value;
  22447. }
  22448. }
  22449. });
  22450. },{"../../core":29}],115:[function(require,module,exports){
  22451. (function (global){
  22452. // run the polyfills
  22453. require('./polyfill');
  22454. var core = module.exports = require('./core');
  22455. // add core plugins.
  22456. core.extras = require('./extras');
  22457. core.filters = require('./filters');
  22458. core.interaction = require('./interaction');
  22459. core.loaders = require('./loaders');
  22460. core.mesh = require('./mesh');
  22461. core.accessibility = require('./accessibility');
  22462. // export a premade loader instance
  22463. /**
  22464. * A premade instance of the loader that can be used to loader resources.
  22465. *
  22466. * @name loader
  22467. * @memberof PIXI
  22468. * @property {PIXI.loaders.Loader}
  22469. */
  22470. core.loader = new core.loaders.Loader();
  22471. // mixin the deprecation features.
  22472. Object.assign(core, require('./deprecation'));
  22473. // Always export pixi globally.
  22474. global.PIXI = core;
  22475. }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  22476. },{"./accessibility":21,"./core":29,"./deprecation":79,"./extras":86,"./filters":103,"./interaction":118,"./loaders":121,"./mesh":128,"./polyfill":133}],116:[function(require,module,exports){
  22477. var core = require('../core');
  22478. /**
  22479. * Holds all information related to an Interaction event
  22480. *
  22481. * @class
  22482. * @memberof PIXI.interaction
  22483. */
  22484. function InteractionData()
  22485. {
  22486. /**
  22487. * This point stores the global coords of where the touch/mouse event happened
  22488. *
  22489. * @member {PIXI.Point}
  22490. */
  22491. this.global = new core.Point();
  22492. /**
  22493. * The target Sprite that was interacted with
  22494. *
  22495. * @member {PIXI.Sprite}
  22496. */
  22497. this.target = null;
  22498. /**
  22499. * When passed to an event handler, this will be the original DOM Event that was captured
  22500. *
  22501. * @member {Event}
  22502. */
  22503. this.originalEvent = null;
  22504. }
  22505. InteractionData.prototype.constructor = InteractionData;
  22506. module.exports = InteractionData;
  22507. /**
  22508. * This will return the local coordinates of the specified displayObject for this InteractionData
  22509. *
  22510. * @param displayObject {PIXI.DisplayObject} The DisplayObject that you would like the local coords off
  22511. * @param [point] {PIXI.Point} A Point object in which to store the value, optional (otherwise will create a new point)
  22512. * @param [globalPos] {PIXI.Point} A Point object containing your custom global coords, optional (otherwise will use the current global coords)
  22513. * @return {PIXI.Point} A point containing the coordinates of the InteractionData position relative to the DisplayObject
  22514. */
  22515. InteractionData.prototype.getLocalPosition = function (displayObject, point, globalPos)
  22516. {
  22517. return displayObject.worldTransform.applyInverse(globalPos || this.global, point);
  22518. };
  22519. },{"../core":29}],117:[function(require,module,exports){
  22520. var core = require('../core'),
  22521. InteractionData = require('./InteractionData');
  22522. // Mix interactiveTarget into core.DisplayObject.prototype
  22523. Object.assign(
  22524. core.DisplayObject.prototype,
  22525. require('./interactiveTarget')
  22526. );
  22527. /**
  22528. * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive
  22529. * if its interactive parameter is set to true
  22530. * This manager also supports multitouch.
  22531. *
  22532. * @class
  22533. * @memberof PIXI.interaction
  22534. * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} A reference to the current renderer
  22535. * @param [options] {object}
  22536. * @param [options.autoPreventDefault=true] {boolean} Should the manager automatically prevent default browser actions.
  22537. * @param [options.interactionFrequency=10] {number} Frequency increases the interaction events will be checked.
  22538. */
  22539. function InteractionManager(renderer, options)
  22540. {
  22541. options = options || {};
  22542. /**
  22543. * The renderer this interaction manager works for.
  22544. *
  22545. * @member {PIXI.SystemRenderer}
  22546. */
  22547. this.renderer = renderer;
  22548. /**
  22549. * Should default browser actions automatically be prevented.
  22550. *
  22551. * @member {boolean}
  22552. * @default true
  22553. */
  22554. this.autoPreventDefault = options.autoPreventDefault !== undefined ? options.autoPreventDefault : true;
  22555. /**
  22556. * As this frequency increases the interaction events will be checked more often.
  22557. *
  22558. * @member {number}
  22559. * @default 10
  22560. */
  22561. this.interactionFrequency = options.interactionFrequency || 10;
  22562. /**
  22563. * The mouse data
  22564. *
  22565. * @member {PIXI.interaction.InteractionData}
  22566. */
  22567. this.mouse = new InteractionData();
  22568. /**
  22569. * An event data object to handle all the event tracking/dispatching
  22570. *
  22571. * @member {object}
  22572. */
  22573. this.eventData = {
  22574. stopped: false,
  22575. target: null,
  22576. type: null,
  22577. data: this.mouse,
  22578. stopPropagation:function(){
  22579. this.stopped = true;
  22580. }
  22581. };
  22582. /**
  22583. * Tiny little interactiveData pool !
  22584. *
  22585. * @member {PIXI.interaction.InteractionData[]}
  22586. */
  22587. this.interactiveDataPool = [];
  22588. /**
  22589. * The DOM element to bind to.
  22590. *
  22591. * @member {HTMLElement}
  22592. * @private
  22593. */
  22594. this.interactionDOMElement = null;
  22595. /**
  22596. * This property determins if mousemove and touchmove events are fired only when the cursror is over the object
  22597. * Setting to true will make things work more in line with how the DOM verison works.
  22598. * Setting to false can make things easier for things like dragging
  22599. * It is currently set to false as this is how pixi used to work. This will be set to true in future versions of pixi.
  22600. * @member {boolean}
  22601. * @private
  22602. */
  22603. this.moveWhenInside = false;
  22604. /**
  22605. * Have events been attached to the dom element?
  22606. *
  22607. * @member {boolean}
  22608. * @private
  22609. */
  22610. this.eventsAdded = false;
  22611. //this will make it so that you don't have to call bind all the time
  22612. /**
  22613. * @member {Function}
  22614. */
  22615. this.onMouseUp = this.onMouseUp.bind(this);
  22616. this.processMouseUp = this.processMouseUp.bind( this );
  22617. /**
  22618. * @member {Function}
  22619. */
  22620. this.onMouseDown = this.onMouseDown.bind(this);
  22621. this.processMouseDown = this.processMouseDown.bind( this );
  22622. /**
  22623. * @member {Function}
  22624. */
  22625. this.onMouseMove = this.onMouseMove.bind( this );
  22626. this.processMouseMove = this.processMouseMove.bind( this );
  22627. /**
  22628. * @member {Function}
  22629. */
  22630. this.onMouseOut = this.onMouseOut.bind(this);
  22631. this.processMouseOverOut = this.processMouseOverOut.bind( this );
  22632. /**
  22633. * @member {Function}
  22634. */
  22635. this.onTouchStart = this.onTouchStart.bind(this);
  22636. this.processTouchStart = this.processTouchStart.bind(this);
  22637. /**
  22638. * @member {Function}
  22639. */
  22640. this.onTouchEnd = this.onTouchEnd.bind(this);
  22641. this.processTouchEnd = this.processTouchEnd.bind(this);
  22642. /**
  22643. * @member {Function}
  22644. */
  22645. this.onTouchMove = this.onTouchMove.bind(this);
  22646. this.processTouchMove = this.processTouchMove.bind(this);
  22647. /**
  22648. * @member {number}
  22649. */
  22650. this.last = 0;
  22651. /**
  22652. * The css style of the cursor that is being used
  22653. * @member {string}
  22654. */
  22655. this.currentCursorStyle = 'inherit';
  22656. /**
  22657. * Internal cached var
  22658. * @member {PIXI.Point}
  22659. * @private
  22660. */
  22661. this._tempPoint = new core.Point();
  22662. /**
  22663. * The current resolution
  22664. * @member {number}
  22665. */
  22666. this.resolution = 1;
  22667. this.setTargetElement(this.renderer.view, this.renderer.resolution);
  22668. }
  22669. InteractionManager.prototype.constructor = InteractionManager;
  22670. module.exports = InteractionManager;
  22671. /**
  22672. * Sets the DOM element which will receive mouse/touch events. This is useful for when you have
  22673. * other DOM elements on top of the renderers Canvas element. With this you'll be bale to deletegate
  22674. * another DOM element to receive those events.
  22675. *
  22676. * @param element {HTMLElement} the DOM element which will receive mouse and touch events.
  22677. * @param [resolution=1] {number} THe resolution of the new element (relative to the canvas).
  22678. * @private
  22679. */
  22680. InteractionManager.prototype.setTargetElement = function (element, resolution)
  22681. {
  22682. this.removeEvents();
  22683. this.interactionDOMElement = element;
  22684. this.resolution = resolution || 1;
  22685. this.addEvents();
  22686. };
  22687. /**
  22688. * Registers all the DOM events
  22689. *
  22690. * @private
  22691. */
  22692. InteractionManager.prototype.addEvents = function ()
  22693. {
  22694. if (!this.interactionDOMElement)
  22695. {
  22696. return;
  22697. }
  22698. core.ticker.shared.add(this.update, this);
  22699. if (window.navigator.msPointerEnabled)
  22700. {
  22701. this.interactionDOMElement.style['-ms-content-zooming'] = 'none';
  22702. this.interactionDOMElement.style['-ms-touch-action'] = 'none';
  22703. }
  22704. window.document.addEventListener('mousemove', this.onMouseMove, true);
  22705. this.interactionDOMElement.addEventListener('mousedown', this.onMouseDown, true);
  22706. this.interactionDOMElement.addEventListener('mouseout', this.onMouseOut, true);
  22707. this.interactionDOMElement.addEventListener('touchstart', this.onTouchStart, true);
  22708. this.interactionDOMElement.addEventListener('touchend', this.onTouchEnd, true);
  22709. this.interactionDOMElement.addEventListener('touchmove', this.onTouchMove, true);
  22710. window.addEventListener('mouseup', this.onMouseUp, true);
  22711. this.eventsAdded = true;
  22712. };
  22713. /**
  22714. * Removes all the DOM events that were previously registered
  22715. *
  22716. * @private
  22717. */
  22718. InteractionManager.prototype.removeEvents = function ()
  22719. {
  22720. if (!this.interactionDOMElement)
  22721. {
  22722. return;
  22723. }
  22724. core.ticker.shared.remove(this.update);
  22725. if (window.navigator.msPointerEnabled)
  22726. {
  22727. this.interactionDOMElement.style['-ms-content-zooming'] = '';
  22728. this.interactionDOMElement.style['-ms-touch-action'] = '';
  22729. }
  22730. window.document.removeEventListener('mousemove', this.onMouseMove, true);
  22731. this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true);
  22732. this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true);
  22733. this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true);
  22734. this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true);
  22735. this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true);
  22736. this.interactionDOMElement = null;
  22737. window.removeEventListener('mouseup', this.onMouseUp, true);
  22738. this.eventsAdded = false;
  22739. };
  22740. /**
  22741. * Updates the state of interactive objects.
  22742. * Invoked by a throttled ticker update from
  22743. * {@link PIXI.ticker.shared}.
  22744. *
  22745. * @param deltaTime {number}
  22746. */
  22747. InteractionManager.prototype.update = function (deltaTime)
  22748. {
  22749. this._deltaTime += deltaTime;
  22750. if (this._deltaTime < this.interactionFrequency)
  22751. {
  22752. return;
  22753. }
  22754. this._deltaTime = 0;
  22755. if (!this.interactionDOMElement)
  22756. {
  22757. return;
  22758. }
  22759. // if the user move the mouse this check has already been dfone using the mouse move!
  22760. if(this.didMove)
  22761. {
  22762. this.didMove = false;
  22763. return;
  22764. }
  22765. this.cursor = 'inherit';
  22766. this.processInteractive(this.mouse.global, this.renderer._lastObjectRendered, this.processMouseOverOut, true );
  22767. if (this.currentCursorStyle !== this.cursor)
  22768. {
  22769. this.currentCursorStyle = this.cursor;
  22770. this.interactionDOMElement.style.cursor = this.cursor;
  22771. }
  22772. //TODO
  22773. };
  22774. /**
  22775. * Dispatches an event on the display object that was interacted with
  22776. *
  22777. * @param displayObject {PIXI.Container|PIXI.Sprite|PIXI.extras.TilingSprite} the display object in question
  22778. * @param eventString {string} the name of the event (e.g, mousedown)
  22779. * @param eventData {object} the event data object
  22780. * @private
  22781. */
  22782. InteractionManager.prototype.dispatchEvent = function ( displayObject, eventString, eventData )
  22783. {
  22784. if(!eventData.stopped)
  22785. {
  22786. eventData.target = displayObject;
  22787. eventData.type = eventString;
  22788. displayObject.emit( eventString, eventData );
  22789. if( displayObject[eventString] )
  22790. {
  22791. displayObject[eventString]( eventData );
  22792. }
  22793. }
  22794. };
  22795. /**
  22796. * Maps x and y coords from a DOM object and maps them correctly to the pixi view. The resulting value is stored in the point.
  22797. * This takes into account the fact that the DOM element could be scaled and positioned anywhere on the screen.
  22798. *
  22799. * @param {PIXI.Point} point the point that the result will be stored in
  22800. * @param {number} x the x coord of the position to map
  22801. * @param {number} y the y coord of the position to map
  22802. */
  22803. InteractionManager.prototype.mapPositionToPoint = function ( point, x, y )
  22804. {
  22805. var rect = this.interactionDOMElement.getBoundingClientRect();
  22806. point.x = ( ( x - rect.left ) * (this.interactionDOMElement.width / rect.width ) ) / this.resolution;
  22807. point.y = ( ( y - rect.top ) * (this.interactionDOMElement.height / rect.height ) ) / this.resolution;
  22808. };
  22809. /**
  22810. * This function is provides a neat way of crawling through the scene graph and running a specified function on all interactive objects it finds.
  22811. * It will also take care of hit testing the interactive objects and passes the hit across in the function.
  22812. *
  22813. * @param {PIXI.Point} point the point that is tested for collision
  22814. * @param {PIXI.Container|PIXI.Sprite|PIXI.extras.TilingSprite} displayObject the displayObject that will be hit test (recurcsivly crawls its children)
  22815. * @param {Function} func the function that will be called on each interactive object. The displayObject and hit will be passed to the function
  22816. * @param {boolean} hitTest this indicates if the objects inside should be hit test against the point
  22817. * @return {boolean} returns true if the displayObject hit the point
  22818. */
  22819. InteractionManager.prototype.processInteractive = function (point, displayObject, func, hitTest, interactive)
  22820. {
  22821. if(!displayObject || !displayObject.visible)
  22822. {
  22823. return false;
  22824. }
  22825. // Took a little while to rework this function correctly! But now it is done and nice and optimised. ^_^
  22826. //
  22827. // This function will now loop through all objects and then only hit test the objects it HAS to, not all of them. MUCH faster..
  22828. // An object will be hit test if the following is true:
  22829. //
  22830. // 1: It is interactive.
  22831. // 2: It belongs to a parent that is interactive AND one of the parents children have not already been hit.
  22832. //
  22833. // As another little optimisation once an interactive object has been hit we can carry on through the scenegraph, but we know that there will be no more hits! So we can avoid extra hit tests
  22834. // A final optimisation is that an object is not hit test directly if a child has already been hit.
  22835. var hit = false,
  22836. interactiveParent = interactive = displayObject.interactive || interactive;
  22837. // if the displayobject has a hitArea, then it does not need to hitTest children.
  22838. if(displayObject.hitArea)
  22839. {
  22840. interactiveParent = false;
  22841. }
  22842. // ** FREE TIP **! If an object is not interacttive or has no buttons in it (such as a game scene!) set interactiveChildren to false for that displayObject.
  22843. // This will allow pixi to completly ignore and bypass checking the displayObjects children.
  22844. if(displayObject.interactiveChildren)
  22845. {
  22846. var children = displayObject.children;
  22847. for (var i = children.length-1; i >= 0; i--)
  22848. {
  22849. var child = children[i];
  22850. // time to get recursive.. if this function will return if somthing is hit..
  22851. if(this.processInteractive(point, child, func, hitTest, interactiveParent))
  22852. {
  22853. // its a good idea to check if a child has lost its parent.
  22854. // this means it has been removed whilst looping so its best
  22855. if(!child.parent)
  22856. {
  22857. continue;
  22858. }
  22859. hit = true;
  22860. // we no longer need to hit test any more objects in this container as we we now know the parent has been hit
  22861. interactiveParent = false;
  22862. // If the child is interactive , that means that the object hit was actually interactive and not just the child of an interactive object.
  22863. // This means we no longer need to hit test anything else. We still need to run through all objects, but we don't need to perform any hit tests.
  22864. //if(child.interactive)
  22865. //{
  22866. hitTest = false;
  22867. //}
  22868. // we can break now as we have hit an object.
  22869. //break;
  22870. }
  22871. }
  22872. }
  22873. // no point running this if the item is not interactive or does not have an interactive parent.
  22874. if(interactive)
  22875. {
  22876. // if we are hit testing (as in we have no hit any objects yet)
  22877. // We also don't need to worry about hit testing if once of the displayObjects children has already been hit!
  22878. if(hitTest && !hit)
  22879. {
  22880. if(displayObject.hitArea)
  22881. {
  22882. displayObject.worldTransform.applyInverse(point, this._tempPoint);
  22883. hit = displayObject.hitArea.contains( this._tempPoint.x, this._tempPoint.y );
  22884. }
  22885. else if(displayObject.containsPoint)
  22886. {
  22887. hit = displayObject.containsPoint(point);
  22888. }
  22889. }
  22890. if(displayObject.interactive)
  22891. {
  22892. func(displayObject, hit);
  22893. }
  22894. }
  22895. return hit;
  22896. };
  22897. /**
  22898. * Is called when the mouse button is pressed down on the renderer element
  22899. *
  22900. * @param event {Event} The DOM event of a mouse button being pressed down
  22901. * @private
  22902. */
  22903. InteractionManager.prototype.onMouseDown = function (event)
  22904. {
  22905. this.mouse.originalEvent = event;
  22906. this.eventData.data = this.mouse;
  22907. this.eventData.stopped = false;
  22908. // Update internal mouse reference
  22909. this.mapPositionToPoint( this.mouse.global, event.clientX, event.clientY);
  22910. if (this.autoPreventDefault)
  22911. {
  22912. this.mouse.originalEvent.preventDefault();
  22913. }
  22914. this.processInteractive(this.mouse.global, this.renderer._lastObjectRendered, this.processMouseDown, true );
  22915. };
  22916. /**
  22917. * Processes the result of the mouse down check and dispatches the event if need be
  22918. *
  22919. * @param displayObject {PIXI.Container|PIXI.Sprite|PIXI.extras.TilingSprite} The display object that was tested
  22920. * @param hit {boolean} the result of the hit test on the dispay object
  22921. * @private
  22922. */
  22923. InteractionManager.prototype.processMouseDown = function ( displayObject, hit )
  22924. {
  22925. var e = this.mouse.originalEvent;
  22926. var isRightButton = e.button === 2 || e.which === 3;
  22927. if(hit)
  22928. {
  22929. displayObject[ isRightButton ? '_isRightDown' : '_isLeftDown' ] = true;
  22930. this.dispatchEvent( displayObject, isRightButton ? 'rightdown' : 'mousedown', this.eventData );
  22931. }
  22932. };
  22933. /**
  22934. * Is called when the mouse button is released on the renderer element
  22935. *
  22936. * @param event {Event} The DOM event of a mouse button being released
  22937. * @private
  22938. */
  22939. InteractionManager.prototype.onMouseUp = function (event)
  22940. {
  22941. this.mouse.originalEvent = event;
  22942. this.eventData.data = this.mouse;
  22943. this.eventData.stopped = false;
  22944. // Update internal mouse reference
  22945. this.mapPositionToPoint( this.mouse.global, event.clientX, event.clientY);
  22946. this.processInteractive(this.mouse.global, this.renderer._lastObjectRendered, this.processMouseUp, true );
  22947. };
  22948. /**
  22949. * Processes the result of the mouse up check and dispatches the event if need be
  22950. *
  22951. * @param displayObject {PIXI.Container|PIXI.Sprite|PIXI.extras.TilingSprite} The display object that was tested
  22952. * @param hit {boolean} the result of the hit test on the display object
  22953. * @private
  22954. */
  22955. InteractionManager.prototype.processMouseUp = function ( displayObject, hit )
  22956. {
  22957. var e = this.mouse.originalEvent;
  22958. var isRightButton = e.button === 2 || e.which === 3;
  22959. var isDown = isRightButton ? '_isRightDown' : '_isLeftDown';
  22960. if(hit)
  22961. {
  22962. this.dispatchEvent( displayObject, isRightButton ? 'rightup' : 'mouseup', this.eventData );
  22963. if( displayObject[ isDown ] )
  22964. {
  22965. displayObject[ isDown ] = false;
  22966. this.dispatchEvent( displayObject, isRightButton ? 'rightclick' : 'click', this.eventData );
  22967. }
  22968. }
  22969. else
  22970. {
  22971. if( displayObject[ isDown ] )
  22972. {
  22973. displayObject[ isDown ] = false;
  22974. this.dispatchEvent( displayObject, isRightButton ? 'rightupoutside' : 'mouseupoutside', this.eventData );
  22975. }
  22976. }
  22977. };
  22978. /**
  22979. * Is called when the mouse moves across the renderer element
  22980. *
  22981. * @param event {Event} The DOM event of the mouse moving
  22982. * @private
  22983. */
  22984. InteractionManager.prototype.onMouseMove = function (event)
  22985. {
  22986. this.mouse.originalEvent = event;
  22987. this.eventData.data = this.mouse;
  22988. this.eventData.stopped = false;
  22989. this.mapPositionToPoint( this.mouse.global, event.clientX, event.clientY);
  22990. this.didMove = true;
  22991. this.cursor = 'inherit';
  22992. this.processInteractive(this.mouse.global, this.renderer._lastObjectRendered, this.processMouseMove, true );
  22993. if (this.currentCursorStyle !== this.cursor)
  22994. {
  22995. this.currentCursorStyle = this.cursor;
  22996. this.interactionDOMElement.style.cursor = this.cursor;
  22997. }
  22998. //TODO BUG for parents ineractive object (border order issue)
  22999. };
  23000. /**
  23001. * Processes the result of the mouse move check and dispatches the event if need be
  23002. *
  23003. * @param displayObject {PIXI.Container|PIXI.Sprite|PIXI.extras.TilingSprite} The display object that was tested
  23004. * @param hit {boolean} the result of the hit test on the display object
  23005. * @private
  23006. */
  23007. InteractionManager.prototype.processMouseMove = function ( displayObject, hit )
  23008. {
  23009. this.processMouseOverOut(displayObject, hit);
  23010. // only display on mouse over
  23011. if(!this.moveWhenInside || hit)
  23012. {
  23013. this.dispatchEvent( displayObject, 'mousemove', this.eventData);
  23014. }
  23015. };
  23016. /**
  23017. * Is called when the mouse is moved out of the renderer element
  23018. *
  23019. * @param event {Event} The DOM event of a mouse being moved out
  23020. * @private
  23021. */
  23022. InteractionManager.prototype.onMouseOut = function (event)
  23023. {
  23024. this.mouse.originalEvent = event;
  23025. this.eventData.stopped = false;
  23026. // Update internal mouse reference
  23027. this.mapPositionToPoint( this.mouse.global, event.clientX, event.clientY);
  23028. this.interactionDOMElement.style.cursor = 'inherit';
  23029. // TODO optimize by not check EVERY TIME! maybe half as often? //
  23030. this.mapPositionToPoint( this.mouse.global, event.clientX, event.clientY );
  23031. this.processInteractive( this.mouse.global, this.renderer._lastObjectRendered, this.processMouseOverOut, false );
  23032. };
  23033. /**
  23034. * Processes the result of the mouse over/out check and dispatches the event if need be
  23035. *
  23036. * @param displayObject {PIXI.Container|PIXI.Sprite|PIXI.extras.TilingSprite} The display object that was tested
  23037. * @param hit {boolean} the result of the hit test on the display object
  23038. * @private
  23039. */
  23040. InteractionManager.prototype.processMouseOverOut = function ( displayObject, hit )
  23041. {
  23042. if(hit)
  23043. {
  23044. if(!displayObject._over)
  23045. {
  23046. displayObject._over = true;
  23047. this.dispatchEvent( displayObject, 'mouseover', this.eventData );
  23048. }
  23049. if (displayObject.buttonMode)
  23050. {
  23051. this.cursor = displayObject.defaultCursor;
  23052. }
  23053. }
  23054. else
  23055. {
  23056. if(displayObject._over)
  23057. {
  23058. displayObject._over = false;
  23059. this.dispatchEvent( displayObject, 'mouseout', this.eventData);
  23060. }
  23061. }
  23062. };
  23063. /**
  23064. * Is called when a touch is started on the renderer element
  23065. *
  23066. * @param event {Event} The DOM event of a touch starting on the renderer view
  23067. * @private
  23068. */
  23069. InteractionManager.prototype.onTouchStart = function (event)
  23070. {
  23071. if (this.autoPreventDefault)
  23072. {
  23073. event.preventDefault();
  23074. }
  23075. var changedTouches = event.changedTouches;
  23076. var cLength = changedTouches.length;
  23077. for (var i=0; i < cLength; i++)
  23078. {
  23079. var touchEvent = changedTouches[i];
  23080. //TODO POOL
  23081. var touchData = this.getTouchData( touchEvent );
  23082. touchData.originalEvent = event;
  23083. this.eventData.data = touchData;
  23084. this.eventData.stopped = false;
  23085. this.processInteractive( touchData.global, this.renderer._lastObjectRendered, this.processTouchStart, true );
  23086. this.returnTouchData( touchData );
  23087. }
  23088. };
  23089. /**
  23090. * Processes the result of a touch check and dispatches the event if need be
  23091. *
  23092. * @param displayObject {PIXI.Container|PIXI.Sprite|PIXI.extras.TilingSprite} The display object that was tested
  23093. * @param hit {boolean} the result of the hit test on the display object
  23094. * @private
  23095. */
  23096. InteractionManager.prototype.processTouchStart = function ( displayObject, hit )
  23097. {
  23098. if(hit)
  23099. {
  23100. displayObject._touchDown = true;
  23101. this.dispatchEvent( displayObject, 'touchstart', this.eventData );
  23102. }
  23103. };
  23104. /**
  23105. * Is called when a touch ends on the renderer element
  23106. *
  23107. * @param event {Event} The DOM event of a touch ending on the renderer view
  23108. */
  23109. InteractionManager.prototype.onTouchEnd = function (event)
  23110. {
  23111. if (this.autoPreventDefault)
  23112. {
  23113. event.preventDefault();
  23114. }
  23115. var changedTouches = event.changedTouches;
  23116. var cLength = changedTouches.length;
  23117. for (var i=0; i < cLength; i++)
  23118. {
  23119. var touchEvent = changedTouches[i];
  23120. var touchData = this.getTouchData( touchEvent );
  23121. touchData.originalEvent = event;
  23122. //TODO this should be passed along.. no set
  23123. this.eventData.data = touchData;
  23124. this.eventData.stopped = false;
  23125. this.processInteractive( touchData.global, this.renderer._lastObjectRendered, this.processTouchEnd, true );
  23126. this.returnTouchData( touchData );
  23127. }
  23128. };
  23129. /**
  23130. * Processes the result of the end of a touch and dispatches the event if need be
  23131. *
  23132. * @param displayObject {PIXI.Container|PIXI.Sprite|PIXI.extras.TilingSprite} The display object that was tested
  23133. * @param hit {boolean} the result of the hit test on the display object
  23134. * @private
  23135. */
  23136. InteractionManager.prototype.processTouchEnd = function ( displayObject, hit )
  23137. {
  23138. if(hit)
  23139. {
  23140. this.dispatchEvent( displayObject, 'touchend', this.eventData );
  23141. if( displayObject._touchDown )
  23142. {
  23143. displayObject._touchDown = false;
  23144. this.dispatchEvent( displayObject, 'tap', this.eventData );
  23145. }
  23146. }
  23147. else
  23148. {
  23149. if( displayObject._touchDown )
  23150. {
  23151. displayObject._touchDown = false;
  23152. this.dispatchEvent( displayObject, 'touchendoutside', this.eventData );
  23153. }
  23154. }
  23155. };
  23156. /**
  23157. * Is called when a touch is moved across the renderer element
  23158. *
  23159. * @param event {Event} The DOM event of a touch moving across the renderer view
  23160. * @private
  23161. */
  23162. InteractionManager.prototype.onTouchMove = function (event)
  23163. {
  23164. if (this.autoPreventDefault)
  23165. {
  23166. event.preventDefault();
  23167. }
  23168. var changedTouches = event.changedTouches;
  23169. var cLength = changedTouches.length;
  23170. for (var i=0; i < cLength; i++)
  23171. {
  23172. var touchEvent = changedTouches[i];
  23173. var touchData = this.getTouchData( touchEvent );
  23174. touchData.originalEvent = event;
  23175. this.eventData.data = touchData;
  23176. this.eventData.stopped = false;
  23177. this.processInteractive( touchData.global, this.renderer._lastObjectRendered, this.processTouchMove, this.moveWhenInside );
  23178. this.returnTouchData( touchData );
  23179. }
  23180. };
  23181. /**
  23182. * Processes the result of a touch move check and dispatches the event if need be
  23183. *
  23184. * @param displayObject {PIXI.Container|PIXI.Sprite|PIXI.extras.TilingSprite} The display object that was tested
  23185. * @param hit {boolean} the result of the hit test on the display object
  23186. * @private
  23187. */
  23188. InteractionManager.prototype.processTouchMove = function ( displayObject, hit )
  23189. {
  23190. if(!this.moveWhenInside || hit)
  23191. {
  23192. this.dispatchEvent( displayObject, 'touchmove', this.eventData);
  23193. }
  23194. };
  23195. /**
  23196. * Grabs an interaction data object from the internal pool
  23197. *
  23198. * @param touchEvent {EventData} The touch event we need to pair with an interactionData object
  23199. *
  23200. * @private
  23201. */
  23202. InteractionManager.prototype.getTouchData = function (touchEvent)
  23203. {
  23204. var touchData = this.interactiveDataPool.pop();
  23205. if(!touchData)
  23206. {
  23207. touchData = new InteractionData();
  23208. }
  23209. touchData.identifier = touchEvent.identifier;
  23210. this.mapPositionToPoint( touchData.global, touchEvent.clientX, touchEvent.clientY );
  23211. if(navigator.isCocoonJS)
  23212. {
  23213. touchData.global.x = touchData.global.x / this.resolution;
  23214. touchData.global.y = touchData.global.y / this.resolution;
  23215. }
  23216. touchEvent.globalX = touchData.global.x;
  23217. touchEvent.globalY = touchData.global.y;
  23218. return touchData;
  23219. };
  23220. /**
  23221. * Returns an interaction data object to the internal pool
  23222. *
  23223. * @param touchData {PIXI.interaction.InteractionData} The touch data object we want to return to the pool
  23224. *
  23225. * @private
  23226. */
  23227. InteractionManager.prototype.returnTouchData = function ( touchData )
  23228. {
  23229. this.interactiveDataPool.push( touchData );
  23230. };
  23231. /**
  23232. * Destroys the interaction manager
  23233. *
  23234. */
  23235. InteractionManager.prototype.destroy = function () {
  23236. this.removeEvents();
  23237. this.renderer = null;
  23238. this.mouse = null;
  23239. this.eventData = null;
  23240. this.interactiveDataPool = null;
  23241. this.interactionDOMElement = null;
  23242. this.onMouseUp = null;
  23243. this.processMouseUp = null;
  23244. this.onMouseDown = null;
  23245. this.processMouseDown = null;
  23246. this.onMouseMove = null;
  23247. this.processMouseMove = null;
  23248. this.onMouseOut = null;
  23249. this.processMouseOverOut = null;
  23250. this.onTouchStart = null;
  23251. this.processTouchStart = null;
  23252. this.onTouchEnd = null;
  23253. this.processTouchEnd = null;
  23254. this.onTouchMove = null;
  23255. this.processTouchMove = null;
  23256. this._tempPoint = null;
  23257. };
  23258. core.WebGLRenderer.registerPlugin('interaction', InteractionManager);
  23259. core.CanvasRenderer.registerPlugin('interaction', InteractionManager);
  23260. },{"../core":29,"./InteractionData":116,"./interactiveTarget":119}],118:[function(require,module,exports){
  23261. /**
  23262. * @file Main export of the PIXI interactions library
  23263. * @author Mat Groves <mat@goodboydigital.com>
  23264. * @copyright 2013-2015 GoodBoyDigital
  23265. * @license {@link https://github.com/pixijs/pixi.js/blob/master/LICENSE|MIT License}
  23266. */
  23267. /**
  23268. * @namespace PIXI.interaction
  23269. */
  23270. module.exports = {
  23271. InteractionData: require('./InteractionData'),
  23272. InteractionManager: require('./InteractionManager'),
  23273. interactiveTarget: require('./interactiveTarget')
  23274. };
  23275. },{"./InteractionData":116,"./InteractionManager":117,"./interactiveTarget":119}],119:[function(require,module,exports){
  23276. /**
  23277. * Default property values of interactive objects
  23278. * used by {@link PIXI.interaction.InteractionManager}.
  23279. *
  23280. * @mixin
  23281. * @memberof PIXI.interaction
  23282. * @example
  23283. * function MyObject() {}
  23284. *
  23285. * Object.assign(
  23286. * MyObject.prototype,
  23287. * PIXI.interaction.interactiveTarget
  23288. * );
  23289. */
  23290. var interactiveTarget = {
  23291. /**
  23292. * @todo Needs docs.
  23293. */
  23294. interactive: false,
  23295. /**
  23296. * @todo Needs docs.
  23297. */
  23298. buttonMode: false,
  23299. /**
  23300. * @todo Needs docs.
  23301. */
  23302. interactiveChildren: true,
  23303. /**
  23304. * @todo Needs docs.
  23305. */
  23306. defaultCursor: 'pointer',
  23307. // some internal checks..
  23308. /**
  23309. * @todo Needs docs.
  23310. * @private
  23311. */
  23312. _over: false,
  23313. /**
  23314. * @todo Needs docs.
  23315. * @private
  23316. */
  23317. _touchDown: false
  23318. };
  23319. module.exports = interactiveTarget;
  23320. },{}],120:[function(require,module,exports){
  23321. var Resource = require('resource-loader').Resource,
  23322. core = require('../core'),
  23323. extras = require('../extras'),
  23324. path = require('path');
  23325. function parse(resource, texture) {
  23326. var data = {};
  23327. var info = resource.data.getElementsByTagName('info')[0];
  23328. var common = resource.data.getElementsByTagName('common')[0];
  23329. data.font = info.getAttribute('face');
  23330. data.size = parseInt(info.getAttribute('size'), 10);
  23331. data.lineHeight = parseInt(common.getAttribute('lineHeight'), 10);
  23332. data.chars = {};
  23333. //parse letters
  23334. var letters = resource.data.getElementsByTagName('char');
  23335. for (var i = 0; i < letters.length; i++)
  23336. {
  23337. var charCode = parseInt(letters[i].getAttribute('id'), 10);
  23338. var textureRect = new core.Rectangle(
  23339. parseInt(letters[i].getAttribute('x'), 10) + texture.frame.x,
  23340. parseInt(letters[i].getAttribute('y'), 10) + texture.frame.y,
  23341. parseInt(letters[i].getAttribute('width'), 10),
  23342. parseInt(letters[i].getAttribute('height'), 10)
  23343. );
  23344. data.chars[charCode] = {
  23345. xOffset: parseInt(letters[i].getAttribute('xoffset'), 10),
  23346. yOffset: parseInt(letters[i].getAttribute('yoffset'), 10),
  23347. xAdvance: parseInt(letters[i].getAttribute('xadvance'), 10),
  23348. kerning: {},
  23349. texture: new core.Texture(texture.baseTexture, textureRect)
  23350. };
  23351. }
  23352. //parse kernings
  23353. var kernings = resource.data.getElementsByTagName('kerning');
  23354. for (i = 0; i < kernings.length; i++)
  23355. {
  23356. var first = parseInt(kernings[i].getAttribute('first'), 10);
  23357. var second = parseInt(kernings[i].getAttribute('second'), 10);
  23358. var amount = parseInt(kernings[i].getAttribute('amount'), 10);
  23359. if(data.chars[second])
  23360. {
  23361. data.chars[second].kerning[first] = amount;
  23362. }
  23363. }
  23364. resource.bitmapFont = data;
  23365. // I'm leaving this as a temporary fix so we can test the bitmap fonts in v3
  23366. // but it's very likely to change
  23367. extras.BitmapText.fonts[data.font] = data;
  23368. }
  23369. module.exports = function ()
  23370. {
  23371. return function (resource, next)
  23372. {
  23373. // skip if no data or not xml data
  23374. if (!resource.data || !resource.isXml)
  23375. {
  23376. return next();
  23377. }
  23378. // skip if not bitmap font data, using some silly duck-typing
  23379. if (
  23380. resource.data.getElementsByTagName('page').length === 0 ||
  23381. resource.data.getElementsByTagName('info').length === 0 ||
  23382. resource.data.getElementsByTagName('info')[0].getAttribute('face') === null
  23383. )
  23384. {
  23385. return next();
  23386. }
  23387. var xmlUrl = path.dirname(resource.url);
  23388. if (xmlUrl === '.') {
  23389. xmlUrl = '';
  23390. }
  23391. if (this.baseUrl && xmlUrl) {
  23392. // if baseurl has a trailing slash then add one to xmlUrl so the replace works below
  23393. if (this.baseUrl.charAt(this.baseUrl.length - 1) === '/') {
  23394. xmlUrl += '/';
  23395. }
  23396. // remove baseUrl from xmlUrl
  23397. xmlUrl = xmlUrl.replace(this.baseUrl, '');
  23398. }
  23399. // if there is an xmlUrl now, it needs a trailing slash. Ensure that it does if the string isn't empty.
  23400. if (xmlUrl && xmlUrl.charAt(xmlUrl.length - 1) !== '/') {
  23401. xmlUrl += '/';
  23402. }
  23403. var textureUrl = xmlUrl + resource.data.getElementsByTagName('page')[0].getAttribute('file');
  23404. if (core.utils.TextureCache[textureUrl]) {
  23405. //reuse existing texture
  23406. parse(resource, core.utils.TextureCache[textureUrl]);
  23407. next();
  23408. }
  23409. else {
  23410. var loadOptions = {
  23411. crossOrigin: resource.crossOrigin,
  23412. loadType: Resource.LOAD_TYPE.IMAGE,
  23413. metadata: resource.metadata.imageMetadata
  23414. };
  23415. // load the texture for the font
  23416. this.add(resource.name + '_image', textureUrl, loadOptions, function (res) {
  23417. parse(resource, res.texture);
  23418. next();
  23419. });
  23420. }
  23421. };
  23422. };
  23423. },{"../core":29,"../extras":86,"path":2,"resource-loader":16}],121:[function(require,module,exports){
  23424. /**
  23425. * @file Main export of the PIXI loaders library
  23426. * @author Mat Groves <mat@goodboydigital.com>
  23427. * @copyright 2013-2015 GoodBoyDigital
  23428. * @license {@link https://github.com/pixijs/pixi.js/blob/master/LICENSE|MIT License}
  23429. */
  23430. /**
  23431. * @namespace PIXI.loaders
  23432. */
  23433. module.exports = {
  23434. Loader: require('./loader'),
  23435. // parsers
  23436. bitmapFontParser: require('./bitmapFontParser'),
  23437. spritesheetParser: require('./spritesheetParser'),
  23438. textureParser: require('./textureParser'),
  23439. Resource: require('resource-loader').Resource
  23440. };
  23441. },{"./bitmapFontParser":120,"./loader":122,"./spritesheetParser":123,"./textureParser":124,"resource-loader":16}],122:[function(require,module,exports){
  23442. var ResourceLoader = require('resource-loader'),
  23443. textureParser = require('./textureParser'),
  23444. spritesheetParser = require('./spritesheetParser'),
  23445. bitmapFontParser = require('./bitmapFontParser');
  23446. /**
  23447. *
  23448. * The new loader, extends Resource Loader by Chad Engler : https://github.com/englercj/resource-loader
  23449. *
  23450. * ```js
  23451. * var loader = PIXI.loader; // pixi exposes a premade instance for you to use.
  23452. * //or
  23453. * var loader = new PIXI.loaders.Loader(); // you can also create your own if you want
  23454. *
  23455. * loader.add('bunny',"data/bunny.png");
  23456. *
  23457. * loader.once('complete',onAssetsLoaded);
  23458. *
  23459. * loader.load();
  23460. * ```
  23461. *
  23462. * @class
  23463. * @extends PIXI.ResourceLoader
  23464. * @memberof PIXI.loaders
  23465. * @param [baseUrl=''] {string} The base url for all resources loaded by this loader.
  23466. * @param [concurrency=10] {number} The number of resources to load concurrently.
  23467. */
  23468. function Loader(baseUrl, concurrency)
  23469. {
  23470. ResourceLoader.call(this, baseUrl, concurrency);
  23471. for (var i = 0; i < Loader._pixiMiddleware.length; ++i) {
  23472. this.use(Loader._pixiMiddleware[i]());
  23473. }
  23474. }
  23475. Loader.prototype = Object.create(ResourceLoader.prototype);
  23476. Loader.prototype.constructor = Loader;
  23477. module.exports = Loader;
  23478. Loader._pixiMiddleware = [
  23479. // parse any blob into more usable objects (e.g. Image)
  23480. ResourceLoader.middleware.parsing.blob,
  23481. // parse any Image objects into textures
  23482. textureParser,
  23483. // parse any spritesheet data into multiple textures
  23484. spritesheetParser,
  23485. // parse any spritesheet data into multiple textures
  23486. bitmapFontParser
  23487. ];
  23488. Loader.addPixiMiddleware = function (fn) {
  23489. Loader._pixiMiddleware.push(fn);
  23490. };
  23491. // Add custom extentions
  23492. var Resource = ResourceLoader.Resource;
  23493. Resource.setExtensionXhrType('fnt', Resource.XHR_RESPONSE_TYPE.DOCUMENT);
  23494. },{"./bitmapFontParser":120,"./spritesheetParser":123,"./textureParser":124,"resource-loader":16}],123:[function(require,module,exports){
  23495. var Resource = require('resource-loader').Resource,
  23496. path = require('path'),
  23497. core = require('../core'),
  23498. async = require('async');
  23499. var BATCH_SIZE = 1000;
  23500. module.exports = function ()
  23501. {
  23502. return function (resource, next)
  23503. {
  23504. var imageResourceName = resource.name + '_image';
  23505. // skip if no data, its not json, it isn't spritesheet data, or the image resource already exists
  23506. if (!resource.data || !resource.isJson || !resource.data.frames || this.resources[imageResourceName])
  23507. {
  23508. return next();
  23509. }
  23510. var loadOptions = {
  23511. crossOrigin: resource.crossOrigin,
  23512. loadType: Resource.LOAD_TYPE.IMAGE,
  23513. metadata: resource.metadata.imageMetadata
  23514. };
  23515. var route = path.dirname(resource.url.replace(this.baseUrl, ''));
  23516. // load the image for this sheet
  23517. this.add(imageResourceName, route + '/' + resource.data.meta.image, loadOptions, function (res)
  23518. {
  23519. resource.textures = {};
  23520. var frames = resource.data.frames;
  23521. var frameKeys = Object.keys(frames);
  23522. var resolution = core.utils.getResolutionOfUrl(resource.url);
  23523. var batchIndex = 0;
  23524. function processFrames(initialFrameIndex, maxFrames)
  23525. {
  23526. var frameIndex = initialFrameIndex;
  23527. while (frameIndex - initialFrameIndex < maxFrames && frameIndex < frameKeys.length)
  23528. {
  23529. var frame = frames[frameKeys[frameIndex]];
  23530. var rect = frame.frame;
  23531. if (rect)
  23532. {
  23533. var size = null;
  23534. var trim = null;
  23535. if (frame.rotated)
  23536. {
  23537. size = new core.Rectangle(rect.x, rect.y, rect.h, rect.w);
  23538. }
  23539. else
  23540. {
  23541. size = new core.Rectangle(rect.x, rect.y, rect.w, rect.h);
  23542. }
  23543. // Check to see if the sprite is trimmed
  23544. if (frame.trimmed)
  23545. {
  23546. trim = new core.Rectangle(
  23547. frame.spriteSourceSize.x / resolution,
  23548. frame.spriteSourceSize.y / resolution,
  23549. frame.sourceSize.w / resolution,
  23550. frame.sourceSize.h / resolution
  23551. );
  23552. }
  23553. // flip the width and height!
  23554. if (frame.rotated)
  23555. {
  23556. var temp = size.width;
  23557. size.width = size.height;
  23558. size.height = temp;
  23559. }
  23560. size.x /= resolution;
  23561. size.y /= resolution;
  23562. size.width /= resolution;
  23563. size.height /= resolution;
  23564. resource.textures[frameKeys[frameIndex]] = new core.Texture(res.texture.baseTexture, size, size.clone(), trim, frame.rotated);
  23565. // lets also add the frame to pixi's global cache for fromFrame and fromImage functions
  23566. core.utils.TextureCache[frameKeys[frameIndex]] = resource.textures[frameKeys[frameIndex]];
  23567. }
  23568. frameIndex++;
  23569. }
  23570. }
  23571. function shouldProcessNextBatch()
  23572. {
  23573. return batchIndex * BATCH_SIZE < frameKeys.length;
  23574. }
  23575. function processNextBatch(done)
  23576. {
  23577. processFrames(batchIndex * BATCH_SIZE, BATCH_SIZE);
  23578. batchIndex++;
  23579. setTimeout(done, 0);
  23580. }
  23581. if (frameKeys.length <= BATCH_SIZE)
  23582. {
  23583. processFrames(0, BATCH_SIZE);
  23584. next();
  23585. }
  23586. else
  23587. {
  23588. async.whilst(shouldProcessNextBatch, processNextBatch, next);
  23589. }
  23590. });
  23591. };
  23592. };
  23593. },{"../core":29,"async":1,"path":2,"resource-loader":16}],124:[function(require,module,exports){
  23594. var core = require('../core');
  23595. module.exports = function ()
  23596. {
  23597. return function (resource, next)
  23598. {
  23599. // create a new texture if the data is an Image object
  23600. if (resource.data && resource.isImage)
  23601. {
  23602. var baseTexture = new core.BaseTexture(resource.data, null, core.utils.getResolutionOfUrl(resource.url));
  23603. baseTexture.imageUrl = resource.url;
  23604. resource.texture = new core.Texture(baseTexture);
  23605. // lets also add the frame to pixi's global cache for fromFrame and fromImage fucntions
  23606. core.utils.BaseTextureCache[resource.url] = baseTexture;
  23607. core.utils.TextureCache[resource.url] = resource.texture;
  23608. }
  23609. next();
  23610. };
  23611. };
  23612. },{"../core":29}],125:[function(require,module,exports){
  23613. var core = require('../core'),
  23614. tempPoint = new core.Point(),
  23615. tempPolygon = new core.Polygon();
  23616. /**
  23617. * Base mesh class
  23618. * @class
  23619. * @extends PIXI.Container
  23620. * @memberof PIXI.mesh
  23621. * @param texture {PIXI.Texture} The texture to use
  23622. * @param [vertices] {Float32Array} if you want to specify the vertices
  23623. * @param [uvs] {Float32Array} if you want to specify the uvs
  23624. * @param [indices] {Uint16Array} if you want to specify the indices
  23625. * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts
  23626. */
  23627. function Mesh(texture, vertices, uvs, indices, drawMode)
  23628. {
  23629. core.Container.call(this);
  23630. /**
  23631. * The texture of the Mesh
  23632. *
  23633. * @member {PIXI.Texture}
  23634. * @private
  23635. */
  23636. this._texture = null;
  23637. /**
  23638. * The Uvs of the Mesh
  23639. *
  23640. * @member {Float32Array}
  23641. */
  23642. this.uvs = uvs || new Float32Array([0, 0,
  23643. 1, 0,
  23644. 1, 1,
  23645. 0, 1]);
  23646. /**
  23647. * An array of vertices
  23648. *
  23649. * @member {Float32Array}
  23650. */
  23651. this.vertices = vertices || new Float32Array([0, 0,
  23652. 100, 0,
  23653. 100, 100,
  23654. 0, 100]);
  23655. /*
  23656. * @member {Uint16Array} An array containing the indices of the vertices
  23657. */
  23658. // TODO auto generate this based on draw mode!
  23659. this.indices = indices || new Uint16Array([0, 1, 3, 2]);
  23660. /**
  23661. * Whether the Mesh is dirty or not
  23662. *
  23663. * @member {boolean}
  23664. */
  23665. this.dirty = true;
  23666. /**
  23667. * The blend mode to be applied to the sprite. Set to `PIXI.BLEND_MODES.NORMAL` to remove any blend mode.
  23668. *
  23669. * @member {number}
  23670. * @default PIXI.BLEND_MODES.NORMAL
  23671. * @see PIXI.BLEND_MODES
  23672. */
  23673. this.blendMode = core.BLEND_MODES.NORMAL;
  23674. /**
  23675. * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other.
  23676. *
  23677. * @member {number}
  23678. */
  23679. this.canvasPadding = 0;
  23680. /**
  23681. * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts
  23682. *
  23683. * @member {number}
  23684. * @see PIXI.mesh.Mesh.DRAW_MODES
  23685. */
  23686. this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH;
  23687. // run texture setter;
  23688. this.texture = texture;
  23689. /**
  23690. * The default shader that is used if a mesh doesn't have a more specific one.
  23691. *
  23692. * @member {PIXI.Shader}
  23693. */
  23694. this.shader = null;
  23695. }
  23696. // constructor
  23697. Mesh.prototype = Object.create(core.Container.prototype);
  23698. Mesh.prototype.constructor = Mesh;
  23699. module.exports = Mesh;
  23700. Object.defineProperties(Mesh.prototype, {
  23701. /**
  23702. * The texture that the sprite is using
  23703. *
  23704. * @member {PIXI.Texture}
  23705. * @memberof PIXI.mesh.Mesh#
  23706. */
  23707. texture: {
  23708. get: function ()
  23709. {
  23710. return this._texture;
  23711. },
  23712. set: function (value)
  23713. {
  23714. if (this._texture === value)
  23715. {
  23716. return;
  23717. }
  23718. this._texture = value;
  23719. if (value)
  23720. {
  23721. // wait for the texture to load
  23722. if (value.baseTexture.hasLoaded)
  23723. {
  23724. this._onTextureUpdate();
  23725. }
  23726. else
  23727. {
  23728. value.once('update', this._onTextureUpdate, this);
  23729. }
  23730. }
  23731. }
  23732. }
  23733. });
  23734. /**
  23735. * Renders the object using the WebGL renderer
  23736. *
  23737. * @param renderer {PIXI.WebGLRenderer} a reference to the WebGL renderer
  23738. * @private
  23739. */
  23740. Mesh.prototype._renderWebGL = function (renderer)
  23741. {
  23742. renderer.setObjectRenderer(renderer.plugins.mesh);
  23743. renderer.plugins.mesh.render(this);
  23744. };
  23745. /**
  23746. * Renders the object using the Canvas renderer
  23747. *
  23748. * @param renderer {PIXI.CanvasRenderer}
  23749. * @private
  23750. */
  23751. Mesh.prototype._renderCanvas = function (renderer)
  23752. {
  23753. var context = renderer.context;
  23754. var transform = this.worldTransform;
  23755. var res = renderer.resolution;
  23756. if (renderer.roundPixels)
  23757. {
  23758. context.setTransform(transform.a * res, transform.b * res, transform.c * res, transform.d * res, (transform.tx * res) | 0, (transform.ty * res) | 0);
  23759. }
  23760. else
  23761. {
  23762. context.setTransform(transform.a * res, transform.b * res, transform.c * res, transform.d * res, transform.tx * res, transform.ty * res);
  23763. }
  23764. if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH)
  23765. {
  23766. this._renderCanvasTriangleMesh(context);
  23767. }
  23768. else
  23769. {
  23770. this._renderCanvasTriangles(context);
  23771. }
  23772. };
  23773. /**
  23774. * Draws the object in Triangle Mesh mode using canvas
  23775. *
  23776. * @param context {CanvasRenderingContext2D} the current drawing context
  23777. * @private
  23778. */
  23779. Mesh.prototype._renderCanvasTriangleMesh = function (context)
  23780. {
  23781. // draw triangles!!
  23782. var vertices = this.vertices;
  23783. var uvs = this.uvs;
  23784. var length = vertices.length / 2;
  23785. // this.count++;
  23786. for (var i = 0; i < length - 2; i++)
  23787. {
  23788. // draw some triangles!
  23789. var index = i * 2;
  23790. this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4));
  23791. }
  23792. };
  23793. /**
  23794. * Draws the object in triangle mode using canvas
  23795. *
  23796. * @param context {CanvasRenderingContext2D} the current drawing context
  23797. * @private
  23798. */
  23799. Mesh.prototype._renderCanvasTriangles = function (context)
  23800. {
  23801. // draw triangles!!
  23802. var vertices = this.vertices;
  23803. var uvs = this.uvs;
  23804. var indices = this.indices;
  23805. var length = indices.length;
  23806. // this.count++;
  23807. for (var i = 0; i < length; i += 3)
  23808. {
  23809. // draw some triangles!
  23810. var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2;
  23811. this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2);
  23812. }
  23813. };
  23814. /**
  23815. * Draws one of the triangles that form this Mesh
  23816. *
  23817. * @param context {CanvasRenderingContext2D} the current drawing context
  23818. * @param vertices {Float32Array} a reference to the vertices of the Mesh
  23819. * @param uvs {Float32Array} a reference to the uvs of the Mesh
  23820. * @param index0 {number} the index of the first vertex
  23821. * @param index1 {number} the index of the second vertex
  23822. * @param index2 {number} the index of the third vertex
  23823. * @private
  23824. */
  23825. Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2)
  23826. {
  23827. var base = this._texture.baseTexture;
  23828. var textureSource = base.source;
  23829. var textureWidth = base.width;
  23830. var textureHeight = base.height;
  23831. var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2];
  23832. var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1];
  23833. var u0 = uvs[index0] * base.width, u1 = uvs[index1] * base.width, u2 = uvs[index2] * base.width;
  23834. var v0 = uvs[index0 + 1] * base.height, v1 = uvs[index1 + 1] * base.height, v2 = uvs[index2 + 1] * base.height;
  23835. if (this.canvasPadding > 0)
  23836. {
  23837. var paddingX = this.canvasPadding / this.worldTransform.a;
  23838. var paddingY = this.canvasPadding / this.worldTransform.d;
  23839. var centerX = (x0 + x1 + x2) / 3;
  23840. var centerY = (y0 + y1 + y2) / 3;
  23841. var normX = x0 - centerX;
  23842. var normY = y0 - centerY;
  23843. var dist = Math.sqrt(normX * normX + normY * normY);
  23844. x0 = centerX + (normX / dist) * (dist + paddingX);
  23845. y0 = centerY + (normY / dist) * (dist + paddingY);
  23846. //
  23847. normX = x1 - centerX;
  23848. normY = y1 - centerY;
  23849. dist = Math.sqrt(normX * normX + normY * normY);
  23850. x1 = centerX + (normX / dist) * (dist + paddingX);
  23851. y1 = centerY + (normY / dist) * (dist + paddingY);
  23852. normX = x2 - centerX;
  23853. normY = y2 - centerY;
  23854. dist = Math.sqrt(normX * normX + normY * normY);
  23855. x2 = centerX + (normX / dist) * (dist + paddingX);
  23856. y2 = centerY + (normY / dist) * (dist + paddingY);
  23857. }
  23858. context.save();
  23859. context.beginPath();
  23860. context.moveTo(x0, y0);
  23861. context.lineTo(x1, y1);
  23862. context.lineTo(x2, y2);
  23863. context.closePath();
  23864. context.clip();
  23865. // Compute matrix transform
  23866. var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2);
  23867. var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2);
  23868. var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2);
  23869. var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2);
  23870. var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2);
  23871. var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2);
  23872. var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2);
  23873. context.transform(deltaA / delta, deltaD / delta,
  23874. deltaB / delta, deltaE / delta,
  23875. deltaC / delta, deltaF / delta);
  23876. context.drawImage(textureSource, 0, 0, textureWidth * base.resolution, textureHeight * base.resolution, 0, 0, textureWidth, textureHeight);
  23877. context.restore();
  23878. };
  23879. /**
  23880. * Renders a flat Mesh
  23881. *
  23882. * @param Mesh {PIXI.mesh.Mesh} The Mesh to render
  23883. * @private
  23884. */
  23885. Mesh.prototype.renderMeshFlat = function (Mesh)
  23886. {
  23887. var context = this.context;
  23888. var vertices = Mesh.vertices;
  23889. var length = vertices.length/2;
  23890. // this.count++;
  23891. context.beginPath();
  23892. for (var i=1; i < length-2; i++)
  23893. {
  23894. // draw some triangles!
  23895. var index = i*2;
  23896. var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4];
  23897. var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5];
  23898. context.moveTo(x0, y0);
  23899. context.lineTo(x1, y1);
  23900. context.lineTo(x2, y2);
  23901. }
  23902. context.fillStyle = '#FF0000';
  23903. context.fill();
  23904. context.closePath();
  23905. };
  23906. /**
  23907. * When the texture is updated, this event will fire to update the scale and frame
  23908. *
  23909. * @param event
  23910. * @private
  23911. */
  23912. Mesh.prototype._onTextureUpdate = function ()
  23913. {
  23914. this.updateFrame = true;
  23915. };
  23916. /**
  23917. * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account.
  23918. *
  23919. * @param matrix {PIXI.Matrix} the transformation matrix of the sprite
  23920. * @return {PIXI.Rectangle} the framing rectangle
  23921. */
  23922. Mesh.prototype.getBounds = function (matrix)
  23923. {
  23924. if (!this._currentBounds) {
  23925. var worldTransform = matrix || this.worldTransform;
  23926. var a = worldTransform.a;
  23927. var b = worldTransform.b;
  23928. var c = worldTransform.c;
  23929. var d = worldTransform.d;
  23930. var tx = worldTransform.tx;
  23931. var ty = worldTransform.ty;
  23932. var maxX = -Infinity;
  23933. var maxY = -Infinity;
  23934. var minX = Infinity;
  23935. var minY = Infinity;
  23936. var vertices = this.vertices;
  23937. for (var i = 0, n = vertices.length; i < n; i += 2) {
  23938. var rawX = vertices[i], rawY = vertices[i + 1];
  23939. var x = (a * rawX) + (c * rawY) + tx;
  23940. var y = (d * rawY) + (b * rawX) + ty;
  23941. minX = x < minX ? x : minX;
  23942. minY = y < minY ? y : minY;
  23943. maxX = x > maxX ? x : maxX;
  23944. maxY = y > maxY ? y : maxY;
  23945. }
  23946. if (minX === -Infinity || maxY === Infinity) {
  23947. return core.Rectangle.EMPTY;
  23948. }
  23949. var bounds = this._bounds;
  23950. bounds.x = minX;
  23951. bounds.width = maxX - minX;
  23952. bounds.y = minY;
  23953. bounds.height = maxY - minY;
  23954. // store a reference so that if this function gets called again in the render cycle we do not have to recalculate
  23955. this._currentBounds = bounds;
  23956. }
  23957. return this._currentBounds;
  23958. };
  23959. /**
  23960. * Tests if a point is inside this mesh. Works only for TRIANGLE_MESH
  23961. *
  23962. * @param point {PIXI.Point} the point to test
  23963. * @return {boolean} the result of the test
  23964. */
  23965. Mesh.prototype.containsPoint = function( point ) {
  23966. if (!this.getBounds().contains(point.x, point.y)) {
  23967. return false;
  23968. }
  23969. this.worldTransform.applyInverse(point, tempPoint);
  23970. var vertices = this.vertices;
  23971. var points = tempPolygon.points;
  23972. var i, len;
  23973. if (this.drawMode === Mesh.DRAW_MODES.TRIANGLES) {
  23974. var indices = this.indices;
  23975. len = this.indices.length;
  23976. //TODO: inline this.
  23977. for (i=0;i<len;i+=3) {
  23978. var ind0 = indices[i]*2, ind1 = indices[i+1]*2, ind2 = indices[i+2]*2;
  23979. points[0] = vertices[ind0];
  23980. points[1] = vertices[ind0+1];
  23981. points[2] = vertices[ind1];
  23982. points[3] = vertices[ind1+1];
  23983. points[4] = vertices[ind2];
  23984. points[5] = vertices[ind2+1];
  23985. if (tempPolygon.contains(tempPoint.x, tempPoint.y)) {
  23986. return true;
  23987. }
  23988. }
  23989. } else {
  23990. len = vertices.length;
  23991. for (i=0;i<len;i+=6) {
  23992. points[0] = vertices[i];
  23993. points[1] = vertices[i+1];
  23994. points[2] = vertices[i+2];
  23995. points[3] = vertices[i+3];
  23996. points[4] = vertices[i+4];
  23997. points[5] = vertices[i+5];
  23998. if (tempPolygon.contains(tempPoint.x, tempPoint.y)) {
  23999. return true;
  24000. }
  24001. }
  24002. }
  24003. return false;
  24004. };
  24005. /**
  24006. * Different drawing buffer modes supported
  24007. *
  24008. * @static
  24009. * @constant
  24010. * @property {object} DRAW_MODES
  24011. * @property {number} DRAW_MODES.TRIANGLE_MESH
  24012. * @property {number} DRAW_MODES.TRIANGLES
  24013. */
  24014. Mesh.DRAW_MODES = {
  24015. TRIANGLE_MESH: 0,
  24016. TRIANGLES: 1
  24017. };
  24018. },{"../core":29}],126:[function(require,module,exports){
  24019. var Mesh = require('./Mesh');
  24020. /**
  24021. * The Plane allows you to draw a texture across several points and them manipulate these points
  24022. *
  24023. *```js
  24024. * for (var i = 0; i < 20; i++) {
  24025. * points.push(new PIXI.Point(i * 50, 0));
  24026. * };
  24027. * var Plane = new PIXI.Plane(PIXI.Texture.fromImage("snake.png"), points);
  24028. * ```
  24029. *
  24030. * @class
  24031. * @extends PIXI.mesh.Mesh
  24032. * @memberof PIXI.mesh
  24033. * @param {PIXI.Texture} texture - The texture to use on the Plane.
  24034. * @param {int} segmentsX - The number ox x segments
  24035. * @param {int} segmentsY - The number of y segments
  24036. *
  24037. */
  24038. function Plane(texture, segmentsX, segmentsY)
  24039. {
  24040. Mesh.call(this, texture);
  24041. /**
  24042. * Tracker for if the Plane is ready to be drawn. Needed because Mesh ctor can
  24043. * call _onTextureUpdated which could call refresh too early.
  24044. *
  24045. * @member {boolean}
  24046. * @private
  24047. */
  24048. this._ready = true;
  24049. this.segmentsX = segmentsX || 10;
  24050. this.segmentsY = segmentsY || 10;
  24051. this.drawMode = Mesh.DRAW_MODES.TRIANGLES;
  24052. this.refresh();
  24053. }
  24054. // constructor
  24055. Plane.prototype = Object.create( Mesh.prototype );
  24056. Plane.prototype.constructor = Plane;
  24057. module.exports = Plane;
  24058. /**
  24059. * Refreshes
  24060. *
  24061. */
  24062. Plane.prototype.refresh = function()
  24063. {
  24064. var total = this.segmentsX * this.segmentsY;
  24065. var verts = [];
  24066. var colors = [];
  24067. var uvs = [];
  24068. var indices = [];
  24069. var texture = this.texture;
  24070. // texture.width = 800 texture.width || 800;
  24071. // texture.height = 800//texture.height || 800;
  24072. var segmentsXSub = this.segmentsX - 1;
  24073. var segmentsYSub = this.segmentsY - 1;
  24074. var i = 0;
  24075. var sizeX = texture.width / segmentsXSub;
  24076. var sizeY = texture.height / segmentsYSub;
  24077. for (i = 0; i < total; i++) {
  24078. var x = (i % this.segmentsX);
  24079. var y = ( (i / this.segmentsX ) | 0 );
  24080. verts.push((x * sizeX),
  24081. (y * sizeY));
  24082. // this works for rectangular textures.
  24083. uvs.push(texture._uvs.x0 + (texture._uvs.x1 - texture._uvs.x0) * (x / (this.segmentsX-1)), texture._uvs.y0 + (texture._uvs.y3-texture._uvs.y0) * (y/ (this.segmentsY-1)));
  24084. }
  24085. // cons
  24086. var totalSub = segmentsXSub * segmentsYSub;
  24087. for (i = 0; i < totalSub; i++) {
  24088. var xpos = i % segmentsXSub;
  24089. var ypos = (i / segmentsXSub ) | 0;
  24090. var value = (ypos * this.segmentsX) + xpos;
  24091. var value2 = (ypos * this.segmentsX) + xpos + 1;
  24092. var value3 = ((ypos+1) * this.segmentsX) + xpos;
  24093. var value4 = ((ypos+1) * this.segmentsX) + xpos + 1;
  24094. indices.push(value, value2, value3);
  24095. indices.push(value2, value4, value3);
  24096. }
  24097. //console.log(indices)
  24098. this.vertices = new Float32Array(verts);
  24099. this.uvs = new Float32Array(uvs);
  24100. this.colors = new Float32Array(colors);
  24101. this.indices = new Uint16Array(indices);
  24102. };
  24103. /**
  24104. * Clear texture UVs when new texture is set
  24105. *
  24106. * @private
  24107. */
  24108. Plane.prototype._onTextureUpdate = function ()
  24109. {
  24110. Mesh.prototype._onTextureUpdate.call(this);
  24111. // wait for the Plane ctor to finish before calling refresh
  24112. if (this._ready) {
  24113. this.refresh();
  24114. }
  24115. };
  24116. },{"./Mesh":125}],127:[function(require,module,exports){
  24117. var Mesh = require('./Mesh');
  24118. var core = require('../core');
  24119. /**
  24120. * The rope allows you to draw a texture across several points and them manipulate these points
  24121. *
  24122. *```js
  24123. * for (var i = 0; i < 20; i++) {
  24124. * points.push(new PIXI.Point(i * 50, 0));
  24125. * };
  24126. * var rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points);
  24127. * ```
  24128. *
  24129. * @class
  24130. * @extends PIXI.mesh.Mesh
  24131. * @memberof PIXI.mesh
  24132. * @param {PIXI.Texture} texture - The texture to use on the rope.
  24133. * @param {PIXI.Point[]} points - An array of {@link PIXI.Point} objects to construct this rope.
  24134. *
  24135. */
  24136. function Rope(texture, points)
  24137. {
  24138. Mesh.call(this, texture);
  24139. /*
  24140. * @member {PIXI.Point[]} An array of points that determine the rope
  24141. */
  24142. this.points = points;
  24143. /*
  24144. * @member {Float32Array} An array of vertices used to construct this rope.
  24145. */
  24146. this.vertices = new Float32Array(points.length * 4);
  24147. /*
  24148. * @member {Float32Array} The WebGL Uvs of the rope.
  24149. */
  24150. this.uvs = new Float32Array(points.length * 4);
  24151. /*
  24152. * @member {Float32Array} An array containing the color components
  24153. */
  24154. this.colors = new Float32Array(points.length * 2);
  24155. /*
  24156. * @member {Uint16Array} An array containing the indices of the vertices
  24157. */
  24158. this.indices = new Uint16Array(points.length * 2);
  24159. /**
  24160. * Tracker for if the rope is ready to be drawn. Needed because Mesh ctor can
  24161. * call _onTextureUpdated which could call refresh too early.
  24162. *
  24163. * @member {boolean}
  24164. * @private
  24165. */
  24166. this._ready = true;
  24167. this.refresh();
  24168. }
  24169. // constructor
  24170. Rope.prototype = Object.create(Mesh.prototype);
  24171. Rope.prototype.constructor = Rope;
  24172. module.exports = Rope;
  24173. /**
  24174. * Refreshes
  24175. *
  24176. */
  24177. Rope.prototype.refresh = function ()
  24178. {
  24179. var points = this.points;
  24180. // if too little points, or texture hasn't got UVs set yet just move on.
  24181. if (points.length < 1 || !this._texture._uvs)
  24182. {
  24183. return;
  24184. }
  24185. var uvs = this.uvs;
  24186. var indices = this.indices;
  24187. var colors = this.colors;
  24188. var textureUvs = this._texture._uvs;
  24189. var offset = new core.Point(textureUvs.x0, textureUvs.y0);
  24190. var factor = new core.Point(textureUvs.x2 - textureUvs.x0, textureUvs.y2 - textureUvs.y0);
  24191. uvs[0] = 0 + offset.x;
  24192. uvs[1] = 0 + offset.y;
  24193. uvs[2] = 0 + offset.x;
  24194. uvs[3] = 1 * factor.y + offset.y;
  24195. colors[0] = 1;
  24196. colors[1] = 1;
  24197. indices[0] = 0;
  24198. indices[1] = 1;
  24199. var total = points.length,
  24200. point, index, amount;
  24201. for (var i = 1; i < total; i++)
  24202. {
  24203. point = points[i];
  24204. index = i * 4;
  24205. // time to do some smart drawing!
  24206. amount = i / (total-1);
  24207. uvs[index] = amount * factor.x + offset.x;
  24208. uvs[index+1] = 0 + offset.y;
  24209. uvs[index+2] = amount * factor.x + offset.x;
  24210. uvs[index+3] = 1 * factor.y + offset.y;
  24211. index = i * 2;
  24212. colors[index] = 1;
  24213. colors[index+1] = 1;
  24214. index = i * 2;
  24215. indices[index] = index;
  24216. indices[index + 1] = index + 1;
  24217. }
  24218. this.dirty = true;
  24219. };
  24220. /**
  24221. * Clear texture UVs when new texture is set
  24222. *
  24223. * @private
  24224. */
  24225. Rope.prototype._onTextureUpdate = function ()
  24226. {
  24227. Mesh.prototype._onTextureUpdate.call(this);
  24228. // wait for the Rope ctor to finish before calling refresh
  24229. if (this._ready) {
  24230. this.refresh();
  24231. }
  24232. };
  24233. /**
  24234. * Updates the object transform for rendering
  24235. *
  24236. * @private
  24237. */
  24238. Rope.prototype.updateTransform = function ()
  24239. {
  24240. var points = this.points;
  24241. if (points.length < 1)
  24242. {
  24243. return;
  24244. }
  24245. var lastPoint = points[0];
  24246. var nextPoint;
  24247. var perpX = 0;
  24248. var perpY = 0;
  24249. // this.count -= 0.2;
  24250. var vertices = this.vertices;
  24251. var total = points.length,
  24252. point, index, ratio, perpLength, num;
  24253. for (var i = 0; i < total; i++)
  24254. {
  24255. point = points[i];
  24256. index = i * 4;
  24257. if (i < points.length-1)
  24258. {
  24259. nextPoint = points[i+1];
  24260. }
  24261. else
  24262. {
  24263. nextPoint = point;
  24264. }
  24265. perpY = -(nextPoint.x - lastPoint.x);
  24266. perpX = nextPoint.y - lastPoint.y;
  24267. ratio = (1 - (i / (total-1))) * 10;
  24268. if (ratio > 1)
  24269. {
  24270. ratio = 1;
  24271. }
  24272. perpLength = Math.sqrt(perpX * perpX + perpY * perpY);
  24273. num = this._texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio;
  24274. perpX /= perpLength;
  24275. perpY /= perpLength;
  24276. perpX *= num;
  24277. perpY *= num;
  24278. vertices[index] = point.x + perpX;
  24279. vertices[index+1] = point.y + perpY;
  24280. vertices[index+2] = point.x - perpX;
  24281. vertices[index+3] = point.y - perpY;
  24282. lastPoint = point;
  24283. }
  24284. this.containerUpdateTransform();
  24285. };
  24286. },{"../core":29,"./Mesh":125}],128:[function(require,module,exports){
  24287. /**
  24288. * @file Main export of the PIXI extras library
  24289. * @author Mat Groves <mat@goodboydigital.com>
  24290. * @copyright 2013-2015 GoodBoyDigital
  24291. * @license {@link https://github.com/pixijs/pixi.js/blob/master/LICENSE|MIT License}
  24292. */
  24293. /**
  24294. * @namespace PIXI.mesh
  24295. */
  24296. module.exports = {
  24297. Mesh: require('./Mesh'),
  24298. Plane: require('./Plane'),
  24299. Rope: require('./Rope'),
  24300. MeshRenderer: require('./webgl/MeshRenderer'),
  24301. MeshShader: require('./webgl/MeshShader')
  24302. };
  24303. },{"./Mesh":125,"./Plane":126,"./Rope":127,"./webgl/MeshRenderer":129,"./webgl/MeshShader":130}],129:[function(require,module,exports){
  24304. var core = require('../../core'),
  24305. Mesh = require('../Mesh');
  24306. /**
  24307. * @author Mat Groves
  24308. *
  24309. * Big thanks to the very clever Matt DesLauriers <mattdesl> https://github.com/mattdesl/
  24310. * for creating the original pixi version!
  24311. * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer
  24312. *
  24313. * Heavily inspired by LibGDX's MeshRenderer:
  24314. * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/MeshRenderer.java
  24315. */
  24316. /**
  24317. *
  24318. * @class
  24319. * @private
  24320. * @memberof PIXI.mesh
  24321. * @extends PIXI.ObjectRenderer
  24322. * @param renderer {PIXI.WebGLRenderer} The renderer this sprite batch works for.
  24323. */
  24324. function MeshRenderer(renderer)
  24325. {
  24326. core.ObjectRenderer.call(this, renderer);
  24327. /**
  24328. * Holds the indices
  24329. *
  24330. * @member {Uint16Array}
  24331. */
  24332. this.indices = new Uint16Array(15000);
  24333. //TODO this could be a single buffer shared amongst all renderers as we reuse this set up in most renderers
  24334. for (var i=0, j=0; i < 15000; i += 6, j += 4)
  24335. {
  24336. this.indices[i + 0] = j + 0;
  24337. this.indices[i + 1] = j + 1;
  24338. this.indices[i + 2] = j + 2;
  24339. this.indices[i + 3] = j + 0;
  24340. this.indices[i + 4] = j + 2;
  24341. this.indices[i + 5] = j + 3;
  24342. }
  24343. this.currentShader = null;
  24344. }
  24345. MeshRenderer.prototype = Object.create(core.ObjectRenderer.prototype);
  24346. MeshRenderer.prototype.constructor = MeshRenderer;
  24347. module.exports = MeshRenderer;
  24348. core.WebGLRenderer.registerPlugin('mesh', MeshRenderer);
  24349. /**
  24350. * Sets up the renderer context and necessary buffers.
  24351. *
  24352. * @private
  24353. * @param gl {WebGLRenderingContext} the current WebGL drawing context
  24354. */
  24355. MeshRenderer.prototype.onContextChange = function ()
  24356. {
  24357. };
  24358. /**
  24359. * Renders the sprite object.
  24360. *
  24361. * @param mesh {PIXI.mesh.Mesh} the mesh to render
  24362. */
  24363. MeshRenderer.prototype.render = function (mesh)
  24364. {
  24365. if(!mesh._vertexBuffer)
  24366. {
  24367. this._initWebGL(mesh);
  24368. }
  24369. var renderer = this.renderer,
  24370. gl = renderer.gl,
  24371. texture = mesh._texture.baseTexture,
  24372. shader = mesh.shader;// || renderer.shaderManager.plugins.meshShader;
  24373. var drawMode = mesh.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH ? gl.TRIANGLE_STRIP : gl.TRIANGLES;
  24374. renderer.blendModeManager.setBlendMode(mesh.blendMode);
  24375. //TODO cache custom state..
  24376. if (!shader)
  24377. {
  24378. shader = renderer.shaderManager.plugins.meshShader;
  24379. }
  24380. else
  24381. {
  24382. shader = shader.shaders[gl.id] || shader.getShader(renderer);// : shader;
  24383. }
  24384. this.renderer.shaderManager.setShader(shader);
  24385. shader.uniforms.translationMatrix.value = mesh.worldTransform.toArray(true);
  24386. shader.uniforms.projectionMatrix.value = renderer.currentRenderTarget.projectionMatrix.toArray(true);
  24387. shader.uniforms.alpha.value = mesh.worldAlpha;
  24388. shader.syncUniforms();
  24389. if (!mesh.dirty)
  24390. {
  24391. gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer);
  24392. gl.bufferSubData(gl.ARRAY_BUFFER, 0, mesh.vertices);
  24393. gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
  24394. // update the uvs
  24395. gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer);
  24396. gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0);
  24397. gl.activeTexture(gl.TEXTURE0);
  24398. if (!texture._glTextures[gl.id])
  24399. {
  24400. this.renderer.updateTexture(texture);
  24401. }
  24402. else
  24403. {
  24404. // bind the current texture
  24405. gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]);
  24406. }
  24407. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer);
  24408. gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, mesh.indices);
  24409. }
  24410. else
  24411. {
  24412. mesh.dirty = false;
  24413. gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer);
  24414. gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.STATIC_DRAW);
  24415. gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
  24416. // update the uvs
  24417. gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer);
  24418. gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW);
  24419. gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0);
  24420. gl.activeTexture(gl.TEXTURE0);
  24421. if (!texture._glTextures[gl.id])
  24422. {
  24423. this.renderer.updateTexture(texture);
  24424. }
  24425. else
  24426. {
  24427. // bind the current texture
  24428. gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]);
  24429. }
  24430. // dont need to upload!
  24431. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer);
  24432. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW);
  24433. }
  24434. gl.drawElements(drawMode, mesh.indices.length, gl.UNSIGNED_SHORT, 0);
  24435. };
  24436. /**
  24437. * Prepares all the buffers to render this mesh
  24438. * @param mesh {PIXI.mesh.Mesh} the mesh to render
  24439. */
  24440. MeshRenderer.prototype._initWebGL = function (mesh)
  24441. {
  24442. // build the strip!
  24443. var gl = this.renderer.gl;
  24444. mesh._vertexBuffer = gl.createBuffer();
  24445. mesh._indexBuffer = gl.createBuffer();
  24446. mesh._uvBuffer = gl.createBuffer();
  24447. gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer);
  24448. gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.DYNAMIC_DRAW);
  24449. gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer);
  24450. gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW);
  24451. if(mesh.colors){
  24452. mesh._colorBuffer = gl.createBuffer();
  24453. gl.bindBuffer(gl.ARRAY_BUFFER, mesh._colorBuffer);
  24454. gl.bufferData(gl.ARRAY_BUFFER, mesh.colors, gl.STATIC_DRAW);
  24455. }
  24456. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer);
  24457. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW);
  24458. };
  24459. /**
  24460. * Empties the current batch.
  24461. *
  24462. */
  24463. MeshRenderer.prototype.flush = function ()
  24464. {
  24465. };
  24466. /**
  24467. * Starts a new mesh renderer.
  24468. *
  24469. */
  24470. MeshRenderer.prototype.start = function ()
  24471. {
  24472. this.currentShader = null;
  24473. };
  24474. /**
  24475. * Destroys the Mesh renderer
  24476. *
  24477. */
  24478. MeshRenderer.prototype.destroy = function ()
  24479. {
  24480. core.ObjectRenderer.prototype.destroy.call(this);
  24481. };
  24482. },{"../../core":29,"../Mesh":125}],130:[function(require,module,exports){
  24483. var core = require('../../core');
  24484. /**
  24485. * @class
  24486. * @extends PIXI.Shader
  24487. * @memberof PIXI.mesh
  24488. * @param shaderManager {PIXI.ShaderManager} The WebGL shader manager this shader works for.
  24489. */
  24490. function MeshShader(shaderManager)
  24491. {
  24492. core.Shader.call(this,
  24493. shaderManager,
  24494. // vertex shader
  24495. [
  24496. 'precision lowp float;',
  24497. 'attribute vec2 aVertexPosition;',
  24498. 'attribute vec2 aTextureCoord;',
  24499. 'uniform mat3 translationMatrix;',
  24500. 'uniform mat3 projectionMatrix;',
  24501. 'varying vec2 vTextureCoord;',
  24502. 'void main(void){',
  24503. ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);',
  24504. ' vTextureCoord = aTextureCoord;',
  24505. '}'
  24506. ].join('\n'),
  24507. [
  24508. 'precision lowp float;',
  24509. 'varying vec2 vTextureCoord;',
  24510. 'uniform float alpha;',
  24511. 'uniform sampler2D uSampler;',
  24512. 'void main(void){',
  24513. ' gl_FragColor = texture2D(uSampler, vTextureCoord) * alpha ;',
  24514. '}'
  24515. ].join('\n'),
  24516. // custom uniforms
  24517. {
  24518. alpha: { type: '1f', value: 0 },
  24519. translationMatrix: { type: 'mat3', value: new Float32Array(9) },
  24520. projectionMatrix: { type: 'mat3', value: new Float32Array(9) }
  24521. },
  24522. // custom attributes
  24523. {
  24524. aVertexPosition:0,
  24525. aTextureCoord:0
  24526. }
  24527. );
  24528. }
  24529. MeshShader.prototype = Object.create(core.Shader.prototype);
  24530. MeshShader.prototype.constructor = MeshShader;
  24531. module.exports = MeshShader;
  24532. core.ShaderManager.registerPlugin('meshShader', MeshShader);
  24533. },{"../../core":29}],131:[function(require,module,exports){
  24534. // References:
  24535. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
  24536. if (!Math.sign)
  24537. {
  24538. Math.sign = function (x) {
  24539. x = +x;
  24540. if (x === 0 || isNaN(x))
  24541. {
  24542. return x;
  24543. }
  24544. return x > 0 ? 1 : -1;
  24545. };
  24546. }
  24547. },{}],132:[function(require,module,exports){
  24548. // References:
  24549. // https://github.com/sindresorhus/object-assign
  24550. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
  24551. if (!Object.assign)
  24552. {
  24553. Object.assign = require('object-assign');
  24554. }
  24555. },{"object-assign":11}],133:[function(require,module,exports){
  24556. require('./Object.assign');
  24557. require('./requestAnimationFrame');
  24558. require('./Math.sign');
  24559. },{"./Math.sign":131,"./Object.assign":132,"./requestAnimationFrame":134}],134:[function(require,module,exports){
  24560. (function (global){
  24561. // References:
  24562. // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
  24563. // https://gist.github.com/1579671
  24564. // http://updates.html5rocks.com/2012/05/requestAnimationFrame-API-now-with-sub-millisecond-precision
  24565. // https://gist.github.com/timhall/4078614
  24566. // https://github.com/Financial-Times/polyfill-service/tree/master/polyfills/requestAnimationFrame
  24567. // Expected to be used with Browserfiy
  24568. // Browserify automatically detects the use of `global` and passes the
  24569. // correct reference of `global`, `self`, and finally `window`
  24570. // Date.now
  24571. if (!(Date.now && Date.prototype.getTime)) {
  24572. Date.now = function now() {
  24573. return new Date().getTime();
  24574. };
  24575. }
  24576. // performance.now
  24577. if (!(global.performance && global.performance.now)) {
  24578. var startTime = Date.now();
  24579. if (!global.performance) {
  24580. global.performance = {};
  24581. }
  24582. global.performance.now = function () {
  24583. return Date.now() - startTime;
  24584. };
  24585. }
  24586. // requestAnimationFrame
  24587. var lastTime = Date.now();
  24588. var vendors = ['ms', 'moz', 'webkit', 'o'];
  24589. for(var x = 0; x < vendors.length && !global.requestAnimationFrame; ++x) {
  24590. global.requestAnimationFrame = global[vendors[x] + 'RequestAnimationFrame'];
  24591. global.cancelAnimationFrame = global[vendors[x] + 'CancelAnimationFrame'] ||
  24592. global[vendors[x] + 'CancelRequestAnimationFrame'];
  24593. }
  24594. if (!global.requestAnimationFrame) {
  24595. global.requestAnimationFrame = function (callback) {
  24596. if (typeof callback !== 'function') {
  24597. throw new TypeError(callback + 'is not a function');
  24598. }
  24599. var currentTime = Date.now(),
  24600. delay = 16 + lastTime - currentTime;
  24601. if (delay < 0) {
  24602. delay = 0;
  24603. }
  24604. lastTime = currentTime;
  24605. return setTimeout(function () {
  24606. lastTime = Date.now();
  24607. callback(performance.now());
  24608. }, delay);
  24609. };
  24610. }
  24611. if (!global.cancelAnimationFrame) {
  24612. global.cancelAnimationFrame = function(id) {
  24613. clearTimeout(id);
  24614. };
  24615. }
  24616. }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  24617. },{}]},{},[115])(115)
  24618. });
  24619. //# sourceMappingURL=pixi.js.map
  24620. /*
  24621. Sound.js
  24622. ===============
  24623. A complete micro library of useful, modular functions that help you load, play, control
  24624. and generate sound effects and music for games and interactive applications. All the
  24625. code targets the WebAudio API.
  24626. */
  24627. /*
  24628. Fixing the WebAudio API
  24629. --------------------------
  24630. The WebAudio API is so new that it's API is not consistently implemented properly across
  24631. all modern browsers. Thankfully, Chris Wilson's Audio Context Monkey Patch script
  24632. normalizes the API for maximum compatibility.
  24633. https://github.com/cwilso/AudioContext-MonkeyPatch/blob/gh-pages/AudioContextMonkeyPatch.js
  24634. It's included here.
  24635. Thank you, Chris!
  24636. */
  24637. (function (global, exports, perf) {
  24638. 'use strict';
  24639. function fixSetTarget(param) {
  24640. if (!param) // if NYI, just return
  24641. return;
  24642. if (!param.setTargetAtTime)
  24643. param.setTargetAtTime = param.setTargetValueAtTime;
  24644. }
  24645. if (window.hasOwnProperty('webkitAudioContext') &&
  24646. !window.hasOwnProperty('AudioContext')) {
  24647. window.AudioContext = webkitAudioContext;
  24648. if (!AudioContext.prototype.hasOwnProperty('createGain'))
  24649. AudioContext.prototype.createGain = AudioContext.prototype.createGainNode;
  24650. if (!AudioContext.prototype.hasOwnProperty('createDelay'))
  24651. AudioContext.prototype.createDelay = AudioContext.prototype.createDelayNode;
  24652. if (!AudioContext.prototype.hasOwnProperty('createScriptProcessor'))
  24653. AudioContext.prototype.createScriptProcessor = AudioContext.prototype.createJavaScriptNode;
  24654. if (!AudioContext.prototype.hasOwnProperty('createPeriodicWave'))
  24655. AudioContext.prototype.createPeriodicWave = AudioContext.prototype.createWaveTable;
  24656. AudioContext.prototype.internal_createGain = AudioContext.prototype.createGain;
  24657. AudioContext.prototype.createGain = function() {
  24658. var node = this.internal_createGain();
  24659. fixSetTarget(node.gain);
  24660. return node;
  24661. };
  24662. AudioContext.prototype.internal_createDelay = AudioContext.prototype.createDelay;
  24663. AudioContext.prototype.createDelay = function(maxDelayTime) {
  24664. var node = maxDelayTime ? this.internal_createDelay(maxDelayTime) : this.internal_createDelay();
  24665. fixSetTarget(node.delayTime);
  24666. return node;
  24667. };
  24668. AudioContext.prototype.internal_createBufferSource = AudioContext.prototype.createBufferSource;
  24669. AudioContext.prototype.createBufferSource = function() {
  24670. var node = this.internal_createBufferSource();
  24671. if (!node.start) {
  24672. node.start = function ( when, offset, duration ) {
  24673. if ( offset || duration )
  24674. this.noteGrainOn( when || 0, offset, duration );
  24675. else
  24676. this.noteOn( when || 0 );
  24677. };
  24678. } else {
  24679. node.internal_start = node.start;
  24680. node.start = function( when, offset, duration ) {
  24681. if( typeof duration !== 'undefined' )
  24682. node.internal_start( when || 0, offset, duration );
  24683. else
  24684. node.internal_start( when || 0, offset || 0 );
  24685. };
  24686. }
  24687. if (!node.stop) {
  24688. node.stop = function ( when ) {
  24689. this.noteOff( when || 0 );
  24690. };
  24691. } else {
  24692. node.internal_stop = node.stop;
  24693. node.stop = function( when ) {
  24694. node.internal_stop( when || 0 );
  24695. };
  24696. }
  24697. fixSetTarget(node.playbackRate);
  24698. return node;
  24699. };
  24700. AudioContext.prototype.internal_createDynamicsCompressor = AudioContext.prototype.createDynamicsCompressor;
  24701. AudioContext.prototype.createDynamicsCompressor = function() {
  24702. var node = this.internal_createDynamicsCompressor();
  24703. fixSetTarget(node.threshold);
  24704. fixSetTarget(node.knee);
  24705. fixSetTarget(node.ratio);
  24706. fixSetTarget(node.reduction);
  24707. fixSetTarget(node.attack);
  24708. fixSetTarget(node.release);
  24709. return node;
  24710. };
  24711. AudioContext.prototype.internal_createBiquadFilter = AudioContext.prototype.createBiquadFilter;
  24712. AudioContext.prototype.createBiquadFilter = function() {
  24713. var node = this.internal_createBiquadFilter();
  24714. fixSetTarget(node.frequency);
  24715. fixSetTarget(node.detune);
  24716. fixSetTarget(node.Q);
  24717. fixSetTarget(node.gain);
  24718. return node;
  24719. };
  24720. if (AudioContext.prototype.hasOwnProperty( 'createOscillator' )) {
  24721. AudioContext.prototype.internal_createOscillator = AudioContext.prototype.createOscillator;
  24722. AudioContext.prototype.createOscillator = function() {
  24723. var node = this.internal_createOscillator();
  24724. if (!node.start) {
  24725. node.start = function ( when ) {
  24726. this.noteOn( when || 0 );
  24727. };
  24728. } else {
  24729. node.internal_start = node.start;
  24730. node.start = function ( when ) {
  24731. node.internal_start( when || 0);
  24732. };
  24733. }
  24734. if (!node.stop) {
  24735. node.stop = function ( when ) {
  24736. this.noteOff( when || 0 );
  24737. };
  24738. } else {
  24739. node.internal_stop = node.stop;
  24740. node.stop = function( when ) {
  24741. node.internal_stop( when || 0 );
  24742. };
  24743. }
  24744. if (!node.setPeriodicWave)
  24745. node.setPeriodicWave = node.setWaveTable;
  24746. fixSetTarget(node.frequency);
  24747. fixSetTarget(node.detune);
  24748. return node;
  24749. };
  24750. }
  24751. }
  24752. if (window.hasOwnProperty('webkitOfflineAudioContext') &&
  24753. !window.hasOwnProperty('OfflineAudioContext')) {
  24754. window.OfflineAudioContext = webkitOfflineAudioContext;
  24755. }
  24756. }(window));
  24757. /*
  24758. Define the audio context
  24759. ------------------------
  24760. All this code uses a single `AudioContext` If you want to use any of these functions
  24761. independently of this file, make sure that have an `AudioContext` called `actx`.
  24762. */
  24763. var actx = new AudioContext();
  24764. /*
  24765. sounds
  24766. ------
  24767. `sounds` is an object that you can use to store all your loaded sound fles.
  24768. It also has a helpful `load` method that manages asset loading. You can load sounds at
  24769. any time during the game by using the `sounds.load` method. You don't have to use
  24770. the `sounds` object or its `load` method, but it's a really convenient way to
  24771. work with sound file assets.
  24772. Here's how could use the `sound` object to load three sound files from a `sounds` folder and
  24773. call a `setup` method when all the files have finished loading:
  24774. sounds.load([
  24775. "sounds/shoot.wav",
  24776. "sounds/music.wav",
  24777. "sounds/bounce.mp3"
  24778. ]);
  24779. sounds.whenLoaded = setup;
  24780. You can now access these loaded sounds in your application code like this:
  24781. var shoot = sounds["sounds/shoot.wav"],
  24782. music = sounds["sounds/music.wav"],
  24783. bounce = sounds["sounds/bounce.mp3"];
  24784. */
  24785. var sounds = {
  24786. //Properties to help track the assets being loaded.
  24787. toLoad: 0,
  24788. loaded: 0,
  24789. //File extensions for different types of sounds.
  24790. audioExtensions: ["mp3", "ogg", "wav", "webm"],
  24791. //The callback function that should run when all assets have loaded.
  24792. //Assign this when you load the fonts, like this: `assets.whenLoaded = makeSprites;`.
  24793. whenLoaded: undefined,
  24794. //The callback function to run after each asset is loaded
  24795. onProgress: undefined,
  24796. //The callback function to run if an asset fails to load or decode
  24797. onFailed: function(source, error) {
  24798. throw new Error("Audio could not be loaded: " + source);
  24799. },
  24800. //The load method creates and loads all the assets. Use it like this:
  24801. //`assets.load(["images/anyImage.png", "fonts/anyFont.otf"]);`.
  24802. load: function(sources) {
  24803. console.log("Loading sounds..");
  24804. //Get a reference to this asset object so we can
  24805. //refer to it in the `forEach` loop ahead.
  24806. var self = this;
  24807. //Find the number of files that need to be loaded.
  24808. self.toLoad = sources.length;
  24809. sources.forEach(function(source){
  24810. //Find the file extension of the asset.
  24811. var extension = source.split('.').pop();
  24812. //#### Sounds
  24813. //Load audio files that have file extensions that match
  24814. //the `audioExtensions` array.
  24815. if (self.audioExtensions.indexOf(extension) !== -1) {
  24816. //Create a sound sprite.
  24817. var soundSprite = makeSound(source, self.loadHandler.bind(self), true, false, self.onFailed);
  24818. //Get the sound file name.
  24819. soundSprite.name = source;
  24820. //If you just want to extract the file name with the
  24821. //extension, you can do it like this:
  24822. //soundSprite.name = source.split("/").pop();
  24823. //Assign the sound as a property of the assets object so
  24824. //we can access it like this: `assets["sounds/sound.mp3"]`.
  24825. self[soundSprite.name] = soundSprite;
  24826. }
  24827. //Display a message if the file type isn't recognized.
  24828. else {
  24829. console.log("File type not recognized: " + source);
  24830. }
  24831. });
  24832. },
  24833. //#### loadHandler
  24834. //The `loadHandler` will be called each time an asset finishes loading.
  24835. loadHandler: function () {
  24836. var self = this;
  24837. self.loaded += 1;
  24838. if (self.onProgress) {
  24839. self.onProgress(100 * self.loaded / self.toLoad);
  24840. }
  24841. //Check whether everything has loaded.
  24842. if (self.toLoad === self.loaded) {
  24843. //If it has, run the callback function that was assigned to the `whenLoaded` property
  24844. console.log("Sounds finished loading");
  24845. //Reset `loaded` and `toLoaded` so we can load more assets
  24846. //later if we want to.
  24847. self.toLoad = 0;
  24848. self.loaded = 0;
  24849. self.whenLoaded();
  24850. }
  24851. }
  24852. };
  24853. /*
  24854. makeSound
  24855. ---------
  24856. `makeSound` is the function you want to use to load and play sound files.
  24857. It creates and returns and WebAudio sound object with lots of useful methods you can
  24858. use to control the sound.
  24859. You can use it to load a sound like this:
  24860. var anySound = makeSound("sounds/anySound.mp3", loadHandler);
  24861. The code above will load the sound and then call the `loadHandler`
  24862. when the sound has finished loading.
  24863. (However, it's more convenient to load the sound file using
  24864. the `sounds.load` method described above, so I don't recommend loading sounds
  24865. like this unless you need more low-level control.)
  24866. After the sound has been loaded you can access and use it like this:
  24867. function loadHandler() {
  24868. anySound.loop = true;
  24869. anySound.pan = 0.8;
  24870. anySound.volume = 0.5;
  24871. anySound.play();
  24872. anySound.pause();
  24873. anySound.playFrom(second);
  24874. anySound.restart();
  24875. anySound.setReverb(2, 2, false);
  24876. anySound.setEcho(0.2, 0.2, 0);
  24877. anySound.playbackRate = 0.5;
  24878. }
  24879. For advanced configurations, you can optionally supply `makeSound` with optional 3rd and
  24880. 4th arguments:
  24881. var anySound = makeSound(source, loadHandler, loadTheSound?, xhrObject);
  24882. `loadTheSound?` is a Boolean (true/false) value that, if `false` prevents the sound file
  24883. from being loaded. You would only want to set it to `false` like this if you were
  24884. using another file loading library to load the sound, and didn't want it to be loaded
  24885. twice.
  24886. `xhrObject`, the optional 4th argument, is the XHR object that was used to load the sound. Again, you
  24887. would only supply this if you were using another file loading library to load the sound,
  24888. and that library had generated its own XHR object. If you supply the `xhr` argument, `makeSound`
  24889. will skip the file loading step (because you've already done that), but still decode the audio buffer for you.
  24890. (If you are loading the sound file using another file loading library, make sure that your sound
  24891. files are loaded with the XHR `responseType = "arraybuffer"` option.)
  24892. For example, here's how you could use this advanced configuration to decode a sound that you've already loaded
  24893. using your own custom loading system:
  24894. var soundSprite = makeSound(source, decodeHandler.bind(this), false, xhr);
  24895. When the file has finished being decoded, your custom `decodeHandler` will run, which tells you
  24896. that the file has finished decoding.
  24897. If you're creating more than one sound like this, use counter variables to track the number of sounds
  24898. you need to decode, and the number of sounds that have been decoded. When both sets of counters are the
  24899. same, you'll know that all your sound files have finished decoding and you can proceed with the rest
  24900. of you application. (The [Hexi game engine](https://github.com/kittykatattack/hexi) uses `makeSound` in this way.)
  24901. */
  24902. function makeSound(source, loadHandler, loadSound, xhr, failHandler) {
  24903. //The sound object that this function returns.
  24904. var o = {};
  24905. //Set the default properties.
  24906. o.volumeNode = actx.createGain();
  24907. //Create the pan node using the efficient `createStereoPanner`
  24908. //method, if it's available.
  24909. if (!actx.createStereoPanner) {
  24910. o.panNode = actx.createPanner();
  24911. } else {
  24912. o.panNode = actx.createStereoPanner();
  24913. }
  24914. o.delayNode = actx.createDelay();
  24915. o.feedbackNode = actx.createGain();
  24916. o.filterNode = actx.createBiquadFilter();
  24917. o.convolverNode = actx.createConvolver();
  24918. o.soundNode = null;
  24919. o.buffer = null;
  24920. o.source = source;
  24921. o.loop = false;
  24922. o.playing = false;
  24923. //The function that should run when the sound is loaded.
  24924. o.loadHandler = undefined;
  24925. //Values for the `pan` and `volume` getters/setters.
  24926. o.panValue = 0;
  24927. o.volumeValue = 1;
  24928. //Values to help track and set the start and pause times.
  24929. o.startTime = 0;
  24930. o.startOffset = 0;
  24931. //Set the playback rate.
  24932. o.playbackRate = 1;
  24933. //Echo properties.
  24934. o.echo = false;
  24935. o.delayValue = 0.3;
  24936. o.feebackValue = 0.3;
  24937. o.filterValue = 0;
  24938. //Reverb properties
  24939. o.reverb = false;
  24940. o.reverbImpulse = null;
  24941. //The sound object's methods.
  24942. o.play = function() {
  24943. //Set the start time (it will be `0` when the sound
  24944. //first starts.
  24945. o.startTime = actx.currentTime;
  24946. //Create a sound node.
  24947. o.soundNode = actx.createBufferSource();
  24948. //Set the sound node's buffer property to the loaded sound.
  24949. o.soundNode.buffer = o.buffer;
  24950. //Set the playback rate
  24951. o.soundNode.playbackRate.value = this.playbackRate;
  24952. //Connect the sound to the pan, connect the pan to the
  24953. //volume, and connect the volume to the destination.
  24954. o.soundNode.connect(o.volumeNode);
  24955. //If there's no reverb, bypass the convolverNode
  24956. if (o.reverb === false) {
  24957. o.volumeNode.connect(o.panNode);
  24958. }
  24959. //If there is reverb, connect the `convolverNode` and apply
  24960. //the impulse response
  24961. else {
  24962. o.volumeNode.connect(o.convolverNode);
  24963. o.convolverNode.connect(o.panNode);
  24964. o.convolverNode.buffer = o.reverbImpulse;
  24965. }
  24966. //Connect the `panNode` to the destination to complete the chain.
  24967. o.panNode.connect(actx.destination);
  24968. //Add optional echo.
  24969. if (o.echo) {
  24970. //Set the values.
  24971. o.feedbackNode.gain.value = o.feebackValue;
  24972. o.delayNode.delayTime.value = o.delayValue;
  24973. o.filterNode.frequency.value = o.filterValue;
  24974. //Create the delay loop, with optional filtering.
  24975. o.delayNode.connect(o.feedbackNode);
  24976. if (o.filterValue > 0) {
  24977. o.feedbackNode.connect(o.filterNode);
  24978. o.filterNode.connect(o.delayNode);
  24979. } else {
  24980. o.feedbackNode.connect(o.delayNode);
  24981. }
  24982. //Capture the sound from the main node chain, send it to the
  24983. //delay loop, and send the final echo effect to the `panNode` which
  24984. //will then route it to the destination.
  24985. o.volumeNode.connect(o.delayNode);
  24986. o.delayNode.connect(o.panNode);
  24987. }
  24988. //Will the sound loop? This can be `true` or `false`.
  24989. o.soundNode.loop = o.loop;
  24990. //Finally, use the `start` method to play the sound.
  24991. //The start time will either be `0`,
  24992. //or a later time if the sound was paused.
  24993. o.soundNode.start(
  24994. 0, o.startOffset % o.buffer.duration
  24995. );
  24996. //Set `playing` to `true` to help control the
  24997. //`pause` and `restart` methods.
  24998. o.playing = true;
  24999. };
  25000. o.pause = function() {
  25001. //Pause the sound if it's playing, and calculate the
  25002. //`startOffset` to save the current position.
  25003. if (o.playing) {
  25004. o.soundNode.stop(0);
  25005. o.startOffset += actx.currentTime - o.startTime;
  25006. o.playing = false;
  25007. }
  25008. };
  25009. o.restart = function() {
  25010. //Stop the sound if it's playing, reset the start and offset times,
  25011. //then call the `play` method again.
  25012. if (o.playing) {
  25013. o.soundNode.stop(0);
  25014. }
  25015. o.startOffset = 0;
  25016. o.play();
  25017. };
  25018. o.playFrom = function(value) {
  25019. if (o.playing) {
  25020. o.soundNode.stop(0);
  25021. }
  25022. o.startOffset = value;
  25023. o.play();
  25024. };
  25025. o.setEcho = function(delayValue, feedbackValue, filterValue) {
  25026. if (delayValue === undefined) delayValue = 0.3;
  25027. if (feedbackValue === undefined) feedbackValue = 0.3;
  25028. if (filterValue === undefined) filterValue = 0;
  25029. o.delayValue = delayValue;
  25030. o.feebackValue = feedbackValue;
  25031. o.filterValue = filterValue;
  25032. o.echo = true;
  25033. };
  25034. o.setReverb = function(duration, decay, reverse) {
  25035. if (duration === undefined) duration = 2;
  25036. if (decay === undefined) decay = 2;
  25037. if (reverse === undefined) reverse = false;
  25038. o.reverbImpulse = impulseResponse(duration, decay, reverse, actx);
  25039. o.reverb = true;
  25040. };
  25041. //A general purpose `fade` method for fading sounds in or out.
  25042. //The first argument is the volume that the sound should
  25043. //fade to, and the second value is the duration, in seconds,
  25044. //that the fade should last.
  25045. o.fade = function(endValue, durationInSeconds) {
  25046. if (o.playing) {
  25047. o.volumeNode.gain.linearRampToValueAtTime(
  25048. o.volumeNode.gain.value, actx.currentTime
  25049. );
  25050. o.volumeNode.gain.linearRampToValueAtTime(
  25051. endValue, actx.currentTime + durationInSeconds
  25052. );
  25053. }
  25054. };
  25055. //Fade a sound in, from an initial volume level of zero.
  25056. o.fadeIn = function(durationInSeconds) {
  25057. //Set the volume to 0 so that you can fade
  25058. //in from silence
  25059. o.volumeNode.gain.value = 0;
  25060. o.fade(1, durationInSeconds);
  25061. };
  25062. //Fade a sound out, from its current volume level to zero.
  25063. o.fadeOut = function(durationInSeconds) {
  25064. o.fade(0, durationInSeconds);
  25065. };
  25066. //Volume and pan getters/setters.
  25067. Object.defineProperties(o, {
  25068. volume: {
  25069. get: function() {
  25070. return o.volumeValue;
  25071. },
  25072. set: function(value) {
  25073. o.volumeNode.gain.value = value;
  25074. o.volumeValue = value;
  25075. },
  25076. enumerable: true, configurable: true
  25077. },
  25078. //The pan node uses the high-efficiency stereo panner, if it's
  25079. //available. But, because this is a new addition to the
  25080. //WebAudio spec, it might not be available on all browsers.
  25081. //So the code checks for this and uses the older 3D panner
  25082. //if 2D isn't available.
  25083. pan: {
  25084. get: function() {
  25085. if (!actx.createStereoPanner) {
  25086. return o.panValue;
  25087. } else {
  25088. return o.panNode.pan.value;
  25089. }
  25090. },
  25091. set: function(value) {
  25092. if (!actx.createStereoPanner) {
  25093. //Panner objects accept x, y and z coordinates for 3D
  25094. //sound. However, because we're only doing 2D left/right
  25095. //panning we're only interested in the x coordinate,
  25096. //the first one. However, for a natural effect, the z
  25097. //value also has to be set proportionately.
  25098. var x = value,
  25099. y = 0,
  25100. z = 1 - Math.abs(x);
  25101. o.panNode.setPosition(x, y, z);
  25102. o.panValue = value;
  25103. } else {
  25104. o.panNode.pan.value = value;
  25105. }
  25106. },
  25107. enumerable: true, configurable: true
  25108. }
  25109. });
  25110. //Optionally Load and decode the sound.
  25111. if (loadSound) {
  25112. this.loadSound(o, source, loadHandler, failHandler);
  25113. }
  25114. //Optionally, if you've loaded the sound using some other loader, just decode the sound
  25115. if (xhr) {
  25116. this.decodeAudio(o, xhr, loadHandler, failHandler);
  25117. }
  25118. //Return the sound object.
  25119. return o;
  25120. }
  25121. //The `loadSound` function loads the sound file using XHR
  25122. function loadSound(o, source, loadHandler, failHandler) {
  25123. var xhr = new XMLHttpRequest();
  25124. //Use xhr to load the sound file.
  25125. xhr.open("GET", source, true);
  25126. xhr.responseType = "arraybuffer";
  25127. //When the sound has finished loading, decode it using the
  25128. //`decodeAudio` function (which you'll see ahead)
  25129. xhr.addEventListener("load", decodeAudio.bind(this, o, xhr, loadHandler, failHandler));
  25130. //Send the request to load the file.
  25131. xhr.send();
  25132. }
  25133. //The `decodeAudio` function decodes the audio file for you and
  25134. //launches the `loadHandler` when it's done
  25135. function decodeAudio(o, xhr, loadHandler, failHandler) {
  25136. //Decode the sound and store a reference to the buffer.
  25137. actx.decodeAudioData(
  25138. xhr.response,
  25139. function(buffer) {
  25140. o.buffer = buffer;
  25141. o.hasLoaded = true;
  25142. //This next bit is optional, but important.
  25143. //If you have a load manager in your game, call it here so that
  25144. //the sound is registered as having loaded.
  25145. if (loadHandler) {
  25146. loadHandler();
  25147. }
  25148. },
  25149. function(error) {
  25150. if (failHandler) failHandler(o.source, error);
  25151. }
  25152. );
  25153. }
  25154. /*
  25155. soundEffect
  25156. -----------
  25157. The `soundEffect` function let's you generate your sounds and musical notes from scratch
  25158. (Reverb effect requires the `impulseResponse` function that you'll see further ahead in this file)
  25159. To create a custom sound effect, define all the parameters that characterize your sound. Here's how to
  25160. create a laser shooting sound:
  25161. soundEffect(
  25162. 1046.5, //frequency
  25163. 0, //attack
  25164. 0.3, //decay
  25165. "sawtooth", //waveform
  25166. 1, //Volume
  25167. -0.8, //pan
  25168. 0, //wait before playing
  25169. 1200, //pitch bend amount
  25170. false, //reverse bend
  25171. 0, //random pitch range
  25172. 25, //dissonance
  25173. [0.2, 0.2, 2000], //echo: [delay, feedback, filter]
  25174. undefined //reverb: [duration, decay, reverse?]
  25175. 3 //Maximum duration of sound, in seconds
  25176. );
  25177. Experiment by changing these parameters to see what kinds of effects you can create, and build
  25178. your own library of custom sound effects for games.
  25179. */
  25180. function soundEffect(
  25181. frequencyValue, //The sound's fequency pitch in Hertz
  25182. attack, //The time, in seconds, to fade the sound in
  25183. decay, //The time, in seconds, to fade the sound out
  25184. type, //waveform type: "sine", "triangle", "square", "sawtooth"
  25185. volumeValue, //The sound's maximum volume
  25186. panValue, //The speaker pan. left: -1, middle: 0, right: 1
  25187. wait, //The time, in seconds, to wait before playing the sound
  25188. pitchBendAmount, //The number of Hz in which to bend the sound's pitch down
  25189. reverse, //If `reverse` is true the pitch will bend up
  25190. randomValue, //A range, in Hz, within which to randomize the pitch
  25191. dissonance, //A value in Hz. It creates 2 dissonant frequencies above and below the target pitch
  25192. echo, //An array: [delayTimeInSeconds, feedbackTimeInSeconds, filterValueInHz]
  25193. reverb, //An array: [durationInSeconds, decayRateInSeconds, reverse]
  25194. timeout //A number, in seconds, which is the maximum duration for sound effects
  25195. ) {
  25196. //Set the default values
  25197. if (frequencyValue === undefined) frequencyValue = 200;
  25198. if (attack === undefined) attack = 0;
  25199. if (decay === undefined) decay = 1;
  25200. if (type === undefined) type = "sine";
  25201. if (volumeValue === undefined) volumeValue = 1;
  25202. if (panValue === undefined) panValue = 0;
  25203. if (wait === undefined) wait = 0;
  25204. if (pitchBendAmount === undefined) pitchBendAmount = 0;
  25205. if (reverse === undefined) reverse = false;
  25206. if (randomValue === undefined) randomValue = 0;
  25207. if (dissonance === undefined) dissonance = 0;
  25208. if (echo === undefined) echo = undefined;
  25209. if (reverb === undefined) reverb = undefined;
  25210. if (timeout === undefined) timeout = undefined;
  25211. //Create an oscillator, gain and pan nodes, and connect them
  25212. //together to the destination
  25213. var oscillator, volume, pan;
  25214. oscillator = actx.createOscillator();
  25215. volume = actx.createGain();
  25216. if (!actx.createStereoPanner) {
  25217. pan = actx.createPanner();
  25218. } else {
  25219. pan = actx.createStereoPanner();
  25220. }
  25221. oscillator.connect(volume);
  25222. volume.connect(pan);
  25223. pan.connect(actx.destination);
  25224. //Set the supplied values
  25225. volume.gain.value = volumeValue;
  25226. if (!actx.createStereoPanner) {
  25227. pan.setPosition(panValue, 0, 1 - Math.abs(panValue));
  25228. } else {
  25229. pan.pan.value = panValue;
  25230. }
  25231. oscillator.type = type;
  25232. //Optionally randomize the pitch. If the `randomValue` is greater
  25233. //than zero, a random pitch is selected that's within the range
  25234. //specified by `frequencyValue`. The random pitch will be either
  25235. //above or below the target frequency.
  25236. var frequency;
  25237. var randomInt = function(min, max){
  25238. return Math.floor(Math.random() * (max - min + 1)) + min
  25239. };
  25240. if (randomValue > 0) {
  25241. frequency = randomInt(
  25242. frequencyValue - randomValue / 2,
  25243. frequencyValue + randomValue / 2
  25244. );
  25245. } else {
  25246. frequency = frequencyValue;
  25247. }
  25248. oscillator.frequency.value = frequency;
  25249. //Apply effects
  25250. if (attack > 0) fadeIn(volume);
  25251. fadeOut(volume);
  25252. if (pitchBendAmount > 0) pitchBend(oscillator);
  25253. if (echo) addEcho(volume);
  25254. if (reverb) addReverb(volume);
  25255. if (dissonance > 0) addDissonance();
  25256. //Play the sound
  25257. play(oscillator);
  25258. //The helper functions:
  25259. function addReverb(volumeNode) {
  25260. var convolver = actx.createConvolver();
  25261. convolver.buffer = impulseResponse(reverb[0], reverb[1], reverb[2], actx);
  25262. volumeNode.connect(convolver);
  25263. convolver.connect(pan);
  25264. }
  25265. function addEcho(volumeNode) {
  25266. //Create the nodes
  25267. var feedback = actx.createGain(),
  25268. delay = actx.createDelay(),
  25269. filter = actx.createBiquadFilter();
  25270. //Set their values (delay time, feedback time and filter frequency)
  25271. delay.delayTime.value = echo[0];
  25272. feedback.gain.value = echo[1];
  25273. if (echo[2]) filter.frequency.value = echo[2];
  25274. //Create the delay feedback loop, with
  25275. //optional filtering
  25276. delay.connect(feedback);
  25277. if (echo[2]) {
  25278. feedback.connect(filter);
  25279. filter.connect(delay);
  25280. } else {
  25281. feedback.connect(delay);
  25282. }
  25283. //Connect the delay loop to the oscillator's volume
  25284. //node, and then to the destination
  25285. volumeNode.connect(delay);
  25286. //Connect the delay loop to the main sound chain's
  25287. //pan node, so that the echo effect is directed to
  25288. //the correct speaker
  25289. delay.connect(pan);
  25290. }
  25291. //The `fadeIn` function
  25292. function fadeIn(volumeNode) {
  25293. //Set the volume to 0 so that you can fade
  25294. //in from silence
  25295. volumeNode.gain.value = 0;
  25296. volumeNode.gain.linearRampToValueAtTime(
  25297. 0, actx.currentTime + wait
  25298. );
  25299. volumeNode.gain.linearRampToValueAtTime(
  25300. volumeValue, actx.currentTime + wait + attack
  25301. );
  25302. }
  25303. //The `fadeOut` function
  25304. function fadeOut(volumeNode) {
  25305. volumeNode.gain.linearRampToValueAtTime(
  25306. volumeValue, actx.currentTime + attack + wait
  25307. );
  25308. volumeNode.gain.linearRampToValueAtTime(
  25309. 0, actx.currentTime + wait + attack + decay
  25310. );
  25311. }
  25312. //The `pitchBend` function
  25313. function pitchBend(oscillatorNode) {
  25314. //If `reverse` is true, make the note drop in frequency. Useful for
  25315. //shooting sounds
  25316. //Get the frequency of the current oscillator
  25317. var frequency = oscillatorNode.frequency.value;
  25318. //If `reverse` is true, make the sound drop in pitch
  25319. if (!reverse) {
  25320. oscillatorNode.frequency.linearRampToValueAtTime(
  25321. frequency,
  25322. actx.currentTime + wait
  25323. );
  25324. oscillatorNode.frequency.linearRampToValueAtTime(
  25325. frequency - pitchBendAmount,
  25326. actx.currentTime + wait + attack + decay
  25327. );
  25328. }
  25329. //If `reverse` is false, make the note rise in pitch. Useful for
  25330. //jumping sounds
  25331. else {
  25332. oscillatorNode.frequency.linearRampToValueAtTime(
  25333. frequency,
  25334. actx.currentTime + wait
  25335. );
  25336. oscillatorNode.frequency.linearRampToValueAtTime(
  25337. frequency + pitchBendAmount,
  25338. actx.currentTime + wait + attack + decay
  25339. );
  25340. }
  25341. }
  25342. //The `addDissonance` function
  25343. function addDissonance() {
  25344. //Create two more oscillators and gain nodes
  25345. var d1 = actx.createOscillator(),
  25346. d2 = actx.createOscillator(),
  25347. d1Volume = actx.createGain(),
  25348. d2Volume = actx.createGain();
  25349. //Set the volume to the `volumeValue`
  25350. d1Volume.gain.value = volumeValue;
  25351. d2Volume.gain.value = volumeValue;
  25352. //Connect the oscillators to the gain and destination nodes
  25353. d1.connect(d1Volume);
  25354. d1Volume.connect(actx.destination);
  25355. d2.connect(d2Volume);
  25356. d2Volume.connect(actx.destination);
  25357. //Set the waveform to "sawtooth" for a harsh effect
  25358. d1.type = "sawtooth";
  25359. d2.type = "sawtooth";
  25360. //Make the two oscillators play at frequencies above and
  25361. //below the main sound's frequency. Use whatever value was
  25362. //supplied by the `dissonance` argument
  25363. d1.frequency.value = frequency + dissonance;
  25364. d2.frequency.value = frequency - dissonance;
  25365. //Fade in/out, pitch bend and play the oscillators
  25366. //to match the main sound
  25367. if (attack > 0) {
  25368. fadeIn(d1Volume);
  25369. fadeIn(d2Volume);
  25370. }
  25371. if (decay > 0) {
  25372. fadeOut(d1Volume);
  25373. fadeOut(d2Volume);
  25374. }
  25375. if (pitchBendAmount > 0) {
  25376. pitchBend(d1);
  25377. pitchBend(d2);
  25378. }
  25379. if (echo) {
  25380. addEcho(d1Volume);
  25381. addEcho(d2Volume);
  25382. }
  25383. if (reverb) {
  25384. addReverb(d1Volume);
  25385. addReverb(d2Volume);
  25386. }
  25387. play(d1);
  25388. play(d2);
  25389. }
  25390. //The `play` function
  25391. function play(node) {
  25392. node.start(actx.currentTime + wait);
  25393. //Oscillators have to be stopped otherwise they accumulate in
  25394. //memory and tax the CPU. They'll be stopped after a default
  25395. //timeout of 2 seconds, which should be enough for most sound
  25396. //effects. Override this in the `soundEffect` parameters if you
  25397. //need a longer sound
  25398. node.stop(actx.currentTime + wait + 2);
  25399. }
  25400. }
  25401. /*
  25402. impulseResponse
  25403. ---------------
  25404. The `makeSound` and `soundEffect` functions uses `impulseResponse` to help create an optional reverb effect.
  25405. It simulates a model of sound reverberation in an acoustic space which
  25406. a convolver node can blend with the source sound. Make sure to include this function along with `makeSound`
  25407. and `soundEffect` if you need to use the reverb feature.
  25408. */
  25409. function impulseResponse(duration, decay, reverse, actx) {
  25410. //The length of the buffer.
  25411. var length = actx.sampleRate * duration;
  25412. //Create an audio buffer (an empty sound container) to store the reverb effect.
  25413. var impulse = actx.createBuffer(2, length, actx.sampleRate);
  25414. //Use `getChannelData` to initialize empty arrays to store sound data for
  25415. //the left and right channels.
  25416. var left = impulse.getChannelData(0),
  25417. right = impulse.getChannelData(1);
  25418. //Loop through each sample-frame and fill the channel
  25419. //data with random noise.
  25420. for (var i = 0; i < length; i++){
  25421. //Apply the reverse effect, if `reverse` is `true`.
  25422. var n;
  25423. if (reverse) {
  25424. n = length - i;
  25425. } else {
  25426. n = i;
  25427. }
  25428. //Fill the left and right channels with random white noise which
  25429. //decays exponentially.
  25430. left[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);
  25431. right[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);
  25432. }
  25433. //Return the `impulse`.
  25434. return impulse;
  25435. }
  25436. /*
  25437. keyboard
  25438. --------
  25439. This isn't really necessary - I just included it for fun to help with the
  25440. examples in the `index.html` files.
  25441. The `keyboard` helper function creates `key` objects
  25442. that listen for keyboard events. Create a new key object like
  25443. this:
  25444. var keyObject = g.keyboard(asciiKeyCodeNumber);
  25445. Then assign `press` and `release` methods like this:
  25446. keyObject.press = function() {
  25447. //key object pressed
  25448. };
  25449. keyObject.release = function() {
  25450. //key object released
  25451. };
  25452. Keyboard objects also have `isDown` and `isUp` Booleans that you can check.
  25453. This is so much easier than having to write out tedious keyboard even capture
  25454. code from scratch.
  25455. Like I said, the `keyboard` function has nothing to do with generating sounds,
  25456. so just delete it if you don't want it!
  25457. */
  25458. function keyboard(keyCode) {
  25459. var key = {};
  25460. key.code = keyCode;
  25461. key.isDown = false;
  25462. key.isUp = true;
  25463. key.press = undefined;
  25464. key.release = undefined;
  25465. //The `downHandler`
  25466. key.downHandler = function(event) {
  25467. if (event.keyCode === key.code) {
  25468. if (key.isUp && key.press) key.press();
  25469. key.isDown = true;
  25470. key.isUp = false;
  25471. }
  25472. event.preventDefault();
  25473. };
  25474. //The `upHandler`
  25475. key.upHandler = function(event) {
  25476. if (event.keyCode === key.code) {
  25477. if (key.isDown && key.release) key.release();
  25478. key.isDown = false;
  25479. key.isUp = true;
  25480. }
  25481. event.preventDefault();
  25482. };
  25483. //Attach event listeners
  25484. window.addEventListener(
  25485. "keydown", key.downHandler.bind(key), false
  25486. );
  25487. window.addEventListener(
  25488. "keyup", key.upHandler.bind(key), false
  25489. );
  25490. return key;
  25491. }
  25492. function scaleToWindow(canvas, backgroundColor) {
  25493. var scaleX, scaleY, scale, center;
  25494. //1. Scale the canvas to the correct size
  25495. //Figure out the scale amount on each axis
  25496. scaleX = window.innerWidth / canvas.offsetWidth;
  25497. scaleY = window.innerHeight / canvas.offsetHeight;
  25498. //Scale the canvas based on whichever value is less: `scaleX` or `scaleY`
  25499. scale = Math.min(scaleX, scaleY);
  25500. canvas.style.transformOrigin = "0 0";
  25501. canvas.style.transform = "scale(" + scale + ")";
  25502. //2. Center the canvas.
  25503. //Decide whether to center the canvas vertically or horizontally.
  25504. //Wide canvases should be centered vertically, and
  25505. //square or tall canvases should be centered horizontally
  25506. if (canvas.offsetWidth > canvas.offsetHeight) {
  25507. if (canvas.offsetWidth * scale < window.innerWidth) {
  25508. center = "horizontally";
  25509. } else {
  25510. center = "vertically";
  25511. }
  25512. } else {
  25513. if (canvas.offsetHeight * scale < window.innerHeight) {
  25514. center = "vertically";
  25515. } else {
  25516. center = "horizontally";
  25517. }
  25518. }
  25519. //Center horizontally (for square or tall canvases)
  25520. var margin;
  25521. if (center === "horizontally") {
  25522. margin = (window.innerWidth - canvas.offsetWidth * scale) / 2;
  25523. canvas.style.marginTop = 0 + "px";
  25524. canvas.style.marginBottom = 0 + "px";
  25525. canvas.style.marginLeft = margin + "px";
  25526. canvas.style.marginRight = margin + "px";
  25527. }
  25528. //Center vertically (for wide canvases)
  25529. if (center === "vertically") {
  25530. margin = (window.innerHeight - canvas.offsetHeight * scale) / 2;
  25531. canvas.style.marginTop = margin + "px";
  25532. canvas.style.marginBottom = margin + "px";
  25533. canvas.style.marginLeft = 0 + "px";
  25534. canvas.style.marginRight = 0 + "px";
  25535. }
  25536. //3. Remove any padding from the canvas and body and set the canvas
  25537. //display style to "block"
  25538. canvas.style.paddingLeft = 0 + "px";
  25539. canvas.style.paddingRight = 0 + "px";
  25540. canvas.style.paddingTop = 0 + "px";
  25541. canvas.style.paddingBottom = 0 + "px";
  25542. canvas.style.display = "block";
  25543. //4. Set the color of the HTML body background
  25544. document.body.style.backgroundColor = backgroundColor;
  25545. //Fix some quirkiness in scaling for Safari
  25546. var ua = navigator.userAgent.toLowerCase();
  25547. if (ua.indexOf("safari") != -1) {
  25548. if (ua.indexOf("chrome") > -1) {
  25549. // Chrome
  25550. } else {
  25551. // Safari
  25552. //canvas.style.maxHeight = "100%";
  25553. //canvas.style.minHeight = "100%";
  25554. }
  25555. }
  25556. //5. Return the `scale` value. This is important, because you'll nee this value
  25557. //for correct hit testing between the pointer and sprites
  25558. return scale;
  25559. }"use strict";
  25560. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  25561. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  25562. var Bump = (function () {
  25563. function Bump() {
  25564. var renderingEngine = arguments.length <= 0 || arguments[0] === undefined ? PIXI : arguments[0];
  25565. _classCallCheck(this, Bump);
  25566. if (renderingEngine === undefined) throw new Error("Please assign a rendering engine in the constructor before using bump.js");
  25567. this.renderer = "pixi";
  25568. }
  25569. //`addCollisionProperties` adds extra properties to sprites to help
  25570. //simplify the collision code. It won't add these properties if they
  25571. //already exist on the sprite. After these properties have been
  25572. //added, this methods adds a Boolean property to the sprite called `_bumpPropertiesAdded`
  25573. //and sets it to `true` to flag that the sprite has these
  25574. //new properties
  25575. _createClass(Bump, [{
  25576. key: "addCollisionProperties",
  25577. value: function addCollisionProperties(sprite) {
  25578. //Add properties to Pixi sprites
  25579. if (this.renderer === "pixi") {
  25580. //gx
  25581. if (sprite.gx === undefined) {
  25582. Object.defineProperty(sprite, "gx", {
  25583. get: function get() {
  25584. return sprite.getGlobalPosition().x;
  25585. },
  25586. enumerable: true, configurable: true
  25587. });
  25588. }
  25589. //gy
  25590. if (sprite.gy === undefined) {
  25591. Object.defineProperty(sprite, "gy", {
  25592. get: function get() {
  25593. return sprite.getGlobalPosition().y;
  25594. },
  25595. enumerable: true, configurable: true
  25596. });
  25597. }
  25598. //centerX
  25599. if (sprite.centerX === undefined) {
  25600. Object.defineProperty(sprite, "centerX", {
  25601. get: function get() {
  25602. return sprite.x + sprite.width / 2;
  25603. },
  25604. enumerable: true, configurable: true
  25605. });
  25606. }
  25607. //centerY
  25608. if (sprite.centerY === undefined) {
  25609. Object.defineProperty(sprite, "centerY", {
  25610. get: function get() {
  25611. return sprite.y + sprite.height / 2;
  25612. },
  25613. enumerable: true, configurable: true
  25614. });
  25615. }
  25616. //halfWidth
  25617. if (sprite.halfWidth === undefined) {
  25618. Object.defineProperty(sprite, "halfWidth", {
  25619. get: function get() {
  25620. return sprite.width / 2;
  25621. },
  25622. enumerable: true, configurable: true
  25623. });
  25624. }
  25625. //halfHeight
  25626. if (sprite.halfHeight === undefined) {
  25627. Object.defineProperty(sprite, "halfHeight", {
  25628. get: function get() {
  25629. return sprite.height / 2;
  25630. },
  25631. enumerable: true, configurable: true
  25632. });
  25633. }
  25634. //xAnchorOffset
  25635. if (sprite.xAnchorOffset === undefined) {
  25636. Object.defineProperty(sprite, "xAnchorOffset", {
  25637. get: function get() {
  25638. if (sprite.anchor !== undefined) {
  25639. return sprite.width * sprite.anchor.x;
  25640. } else {
  25641. return 0;
  25642. }
  25643. },
  25644. enumerable: true, configurable: true
  25645. });
  25646. }
  25647. //yAnchorOffset
  25648. if (sprite.yAnchorOffset === undefined) {
  25649. Object.defineProperty(sprite, "yAnchorOffset", {
  25650. get: function get() {
  25651. if (sprite.anchor !== undefined) {
  25652. return sprite.height * sprite.anchor.y;
  25653. } else {
  25654. return 0;
  25655. }
  25656. },
  25657. enumerable: true, configurable: true
  25658. });
  25659. }
  25660. if (sprite.circular && sprite.radius === undefined) {
  25661. Object.defineProperty(sprite, "radius", {
  25662. get: function get() {
  25663. return sprite.width / 2;
  25664. },
  25665. enumerable: true, configurable: true
  25666. });
  25667. }
  25668. //Earlier code - not needed now.
  25669. /*
  25670. Object.defineProperties(sprite, {
  25671. "gx": {
  25672. get(){return sprite.getGlobalPosition().x},
  25673. enumerable: true, configurable: true
  25674. },
  25675. "gy": {
  25676. get(){return sprite.getGlobalPosition().y},
  25677. enumerable: true, configurable: true
  25678. },
  25679. "centerX": {
  25680. get(){return sprite.x + sprite.width / 2},
  25681. enumerable: true, configurable: true
  25682. },
  25683. "centerY": {
  25684. get(){return sprite.y + sprite.height / 2},
  25685. enumerable: true, configurable: true
  25686. },
  25687. "halfWidth": {
  25688. get(){return sprite.width / 2},
  25689. enumerable: true, configurable: true
  25690. },
  25691. "halfHeight": {
  25692. get(){return sprite.height / 2},
  25693. enumerable: true, configurable: true
  25694. },
  25695. "xAnchorOffset": {
  25696. get(){
  25697. if (sprite.anchor !== undefined) {
  25698. return sprite.height * sprite.anchor.x;
  25699. } else {
  25700. return 0;
  25701. }
  25702. },
  25703. enumerable: true, configurable: true
  25704. },
  25705. "yAnchorOffset": {
  25706. get(){
  25707. if (sprite.anchor !== undefined) {
  25708. return sprite.width * sprite.anchor.y;
  25709. } else {
  25710. return 0;
  25711. }
  25712. },
  25713. enumerable: true, configurable: true
  25714. }
  25715. });
  25716. */
  25717. }
  25718. //Add a Boolean `_bumpPropertiesAdded` property to the sprite to flag it
  25719. //as having these new properties
  25720. sprite._bumpPropertiesAdded = true;
  25721. }
  25722. /*
  25723. hitTestPoint
  25724. ------------
  25725. Use it to find out if a point is touching a circlular or rectangular sprite.
  25726. Parameters:
  25727. a. An object with `x` and `y` properties.
  25728. b. A sprite object with `x`, `y`, `centerX` and `centerY` properties.
  25729. If the sprite has a `radius` property, the function will interpret
  25730. the shape as a circle.
  25731. */
  25732. }, {
  25733. key: "hitTestPoint",
  25734. value: function hitTestPoint(point, sprite) {
  25735. //Add collision properties
  25736. if (!sprite._bumpPropertiesAdded) this.addCollisionProperties(sprite);
  25737. var shape = undefined,
  25738. left = undefined,
  25739. right = undefined,
  25740. top = undefined,
  25741. bottom = undefined,
  25742. vx = undefined,
  25743. vy = undefined,
  25744. magnitude = undefined,
  25745. hit = undefined;
  25746. //Find out if the sprite is rectangular or circular depending
  25747. //on whether it has a `radius` property
  25748. if (sprite.radius) {
  25749. shape = "circle";
  25750. } else {
  25751. shape = "rectangle";
  25752. }
  25753. //Rectangle
  25754. if (shape === "rectangle") {
  25755. //Get the position of the sprite's edges
  25756. left = sprite.x - sprite.xAnchorOffset;
  25757. right = sprite.x + sprite.width - sprite.xAnchorOffset;
  25758. top = sprite.y - sprite.yAnchorOffset;
  25759. bottom = sprite.y + sprite.height - sprite.yAnchorOffset;
  25760. //Find out if the point is intersecting the rectangle
  25761. hit = point.x > left && point.x < right && point.y > top && point.y < bottom;
  25762. }
  25763. //Circle
  25764. if (shape === "circle") {
  25765. //Find the distance between the point and the
  25766. //center of the circle
  25767. var _vx = point.x - sprite.x - sprite.width / 2 + sprite.xAnchorOffset,
  25768. _vy = point.y - sprite.y - sprite.height / 2 + sprite.yAnchorOffset,
  25769. _magnitude = Math.sqrt(_vx * _vx + _vy * _vy);
  25770. //The point is intersecting the circle if the magnitude
  25771. //(distance) is less than the circle's radius
  25772. hit = _magnitude < sprite.radius;
  25773. }
  25774. //`hit` will be either `true` or `false`
  25775. return hit;
  25776. }
  25777. /*
  25778. hitTestCircle
  25779. -------------
  25780. Use it to find out if two circular sprites are touching.
  25781. Parameters:
  25782. a. A sprite object with `centerX`, `centerY` and `radius` properties.
  25783. b. A sprite object with `centerX`, `centerY` and `radius`.
  25784. */
  25785. }, {
  25786. key: "hitTestCircle",
  25787. value: function hitTestCircle(c1, c2) {
  25788. var global = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  25789. //Add collision properties
  25790. if (!c1._bumpPropertiesAdded) this.addCollisionProperties(c1);
  25791. if (!c2._bumpPropertiesAdded) this.addCollisionProperties(c2);
  25792. var vx = undefined,
  25793. vy = undefined,
  25794. magnitude = undefined,
  25795. combinedRadii = undefined,
  25796. hit = undefined;
  25797. //Calculate the vector between the circles’ center points
  25798. if (global) {
  25799. //Use global coordinates
  25800. vx = c2.gx + c2.width / 2 - c2.xAnchorOffset - (c1.gx + c1.width / 2 - c1.xAnchorOffset);
  25801. vy = c2.gy + c2.width / 2 - c2.yAnchorOffset - (c1.gy + c1.width / 2 - c1.yAnchorOffset);
  25802. } else {
  25803. //Use local coordinates
  25804. vx = c2.x + c2.width / 2 - c2.xAnchorOffset - (c1.x + c1.width / 2 - c1.xAnchorOffset);
  25805. vy = c2.y + c2.width / 2 - c2.yAnchorOffset - (c1.y + c1.width / 2 - c1.yAnchorOffset);
  25806. }
  25807. //Find the distance between the circles by calculating
  25808. //the vector's magnitude (how long the vector is)
  25809. magnitude = Math.sqrt(vx * vx + vy * vy);
  25810. //Add together the circles' total radii
  25811. combinedRadii = c1.radius + c2.radius;
  25812. //Set `hit` to `true` if the distance between the circles is
  25813. //less than their `combinedRadii`
  25814. hit = magnitude < combinedRadii;
  25815. //`hit` will be either `true` or `false`
  25816. return hit;
  25817. }
  25818. /*
  25819. circleCollision
  25820. ---------------
  25821. Use it to prevent a moving circular sprite from overlapping and optionally
  25822. bouncing off a non-moving circular sprite.
  25823. Parameters:
  25824. a. A sprite object with `x`, `y` `centerX`, `centerY` and `radius` properties.
  25825. b. A sprite object with `x`, `y` `centerX`, `centerY` and `radius` properties.
  25826. c. Optional: true or false to indicate whether or not the first sprite
  25827. should bounce off the second sprite.
  25828. The sprites can contain an optional mass property that should be greater than 1.
  25829. */
  25830. }, {
  25831. key: "circleCollision",
  25832. value: function circleCollision(c1, c2) {
  25833. var bounce = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  25834. var global = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
  25835. //Add collision properties
  25836. if (!c1._bumpPropertiesAdded) this.addCollisionProperties(c1);
  25837. if (!c2._bumpPropertiesAdded) this.addCollisionProperties(c2);
  25838. var magnitude = undefined,
  25839. combinedRadii = undefined,
  25840. overlap = undefined,
  25841. vx = undefined,
  25842. vy = undefined,
  25843. dx = undefined,
  25844. dy = undefined,
  25845. s = {},
  25846. hit = false;
  25847. //Calculate the vector between the circles’ center points
  25848. if (global) {
  25849. //Use global coordinates
  25850. vx = c2.gx + c2.width / 2 - c2.xAnchorOffset - (c1.gx + c1.width / 2 - c1.xAnchorOffset);
  25851. vy = c2.gy + c2.width / 2 - c2.yAnchorOffset - (c1.gy + c1.width / 2 - c1.yAnchorOffset);
  25852. } else {
  25853. //Use local coordinates
  25854. vx = c2.x + c2.width / 2 - c2.xAnchorOffset - (c1.x + c1.width / 2 - c1.xAnchorOffset);
  25855. vy = c2.y + c2.width / 2 - c2.yAnchorOffset - (c1.y + c1.width / 2 - c1.yAnchorOffset);
  25856. }
  25857. //Find the distance between the circles by calculating
  25858. //the vector's magnitude (how long the vector is)
  25859. magnitude = Math.sqrt(vx * vx + vy * vy);
  25860. //Add together the circles' combined half-widths
  25861. combinedRadii = c1.radius + c2.radius;
  25862. //Figure out if there's a collision
  25863. if (magnitude < combinedRadii) {
  25864. //Yes, a collision is happening
  25865. hit = true;
  25866. //Find the amount of overlap between the circles
  25867. overlap = combinedRadii - magnitude;
  25868. //Add some "quantum padding". This adds a tiny amount of space
  25869. //between the circles to reduce their surface tension and make
  25870. //them more slippery. "0.3" is a good place to start but you might
  25871. //need to modify this slightly depending on the exact behaviour
  25872. //you want. Too little and the balls will feel sticky, too much
  25873. //and they could start to jitter if they're jammed together
  25874. var quantumPadding = 0.3;
  25875. overlap += quantumPadding;
  25876. //Normalize the vector
  25877. //These numbers tell us the direction of the collision
  25878. dx = vx / magnitude;
  25879. dy = vy / magnitude;
  25880. //Move circle 1 out of the collision by multiplying
  25881. //the overlap with the normalized vector and subtract it from
  25882. //circle 1's position
  25883. c1.x -= overlap * dx;
  25884. c1.y -= overlap * dy;
  25885. //Bounce
  25886. if (bounce) {
  25887. //Create a collision vector object, `s` to represent the bounce "surface".
  25888. //Find the bounce surface's x and y properties
  25889. //(This represents the normal of the distance vector between the circles)
  25890. s.x = vy;
  25891. s.y = -vx;
  25892. //Bounce c1 off the surface
  25893. this.bounceOffSurface(c1, s);
  25894. }
  25895. }
  25896. return hit;
  25897. }
  25898. /*
  25899. movingCircleCollision
  25900. ---------------------
  25901. Use it to make two moving circles bounce off each other.
  25902. Parameters:
  25903. a. A sprite object with `x`, `y` `centerX`, `centerY` and `radius` properties.
  25904. b. A sprite object with `x`, `y` `centerX`, `centerY` and `radius` properties.
  25905. The sprites can contain an optional mass property that should be greater than 1.
  25906. */
  25907. }, {
  25908. key: "movingCircleCollision",
  25909. value: function movingCircleCollision(c1, c2) {
  25910. var global = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  25911. //Add collision properties
  25912. if (!c1._bumpPropertiesAdded) this.addCollisionProperties(c1);
  25913. if (!c2._bumpPropertiesAdded) this.addCollisionProperties(c2);
  25914. var combinedRadii = undefined,
  25915. overlap = undefined,
  25916. xSide = undefined,
  25917. ySide = undefined,
  25918. //`s` refers to the distance vector between the circles
  25919. s = {},
  25920. p1A = {},
  25921. p1B = {},
  25922. p2A = {},
  25923. p2B = {},
  25924. hit = false;
  25925. //Apply mass, if the circles have mass properties
  25926. c1.mass = c1.mass || 1;
  25927. c2.mass = c2.mass || 1;
  25928. //Calculate the vector between the circles’ center points
  25929. if (global) {
  25930. //Use global coordinates
  25931. s.vx = c2.gx + c2.radius - c2.xAnchorOffset - (c1.gx + c1.radius - c1.xAnchorOffset);
  25932. s.vy = c2.gy + c2.radius - c2.yAnchorOffset - (c1.gy + c1.radius - c1.yAnchorOffset);
  25933. } else {
  25934. //Use local coordinates
  25935. s.vx = c2.x + c2.radius - c2.xAnchorOffset - (c1.x + c1.radius - c1.xAnchorOffset);
  25936. s.vy = c2.y + c2.radius - c2.yAnchorOffset - (c1.y + c1.radius - c1.yAnchorOffset);
  25937. }
  25938. //Find the distance between the circles by calculating
  25939. //the vector's magnitude (how long the vector is)
  25940. s.magnitude = Math.sqrt(s.vx * s.vx + s.vy * s.vy);
  25941. //Add together the circles' combined half-widths
  25942. combinedRadii = c1.radius + c2.radius;
  25943. //Figure out if there's a collision
  25944. if (s.magnitude < combinedRadii) {
  25945. //Yes, a collision is happening
  25946. hit = true;
  25947. //Find the amount of overlap between the circles
  25948. overlap = combinedRadii - s.magnitude;
  25949. //Add some "quantum padding" to the overlap
  25950. overlap += 0.3;
  25951. //Normalize the vector.
  25952. //These numbers tell us the direction of the collision
  25953. s.dx = s.vx / s.magnitude;
  25954. s.dy = s.vy / s.magnitude;
  25955. //Find the collision vector.
  25956. //Divide it in half to share between the circles, and make it absolute
  25957. s.vxHalf = Math.abs(s.dx * overlap / 2);
  25958. s.vyHalf = Math.abs(s.dy * overlap / 2);
  25959. //Find the side that the collision is occurring on
  25960. c1.x > c2.x ? xSide = 1 : xSide = -1;
  25961. c1.y > c2.y ? ySide = 1 : ySide = -1;
  25962. //Move c1 out of the collision by multiplying
  25963. //the overlap with the normalized vector and adding it to
  25964. //the circles' positions
  25965. c1.x = c1.x + s.vxHalf * xSide;
  25966. c1.y = c1.y + s.vyHalf * ySide;
  25967. //Move c2 out of the collision
  25968. c2.x = c2.x + s.vxHalf * -xSide;
  25969. c2.y = c2.y + s.vyHalf * -ySide;
  25970. //1. Calculate the collision surface's properties
  25971. //Find the surface vector's left normal
  25972. s.lx = s.vy;
  25973. s.ly = -s.vx;
  25974. //2. Bounce c1 off the surface (s)
  25975. //Find the dot product between c1 and the surface
  25976. var dp1 = c1.vx * s.dx + c1.vy * s.dy;
  25977. //Project c1's velocity onto the collision surface
  25978. p1A.x = dp1 * s.dx;
  25979. p1A.y = dp1 * s.dy;
  25980. //Find the dot product of c1 and the surface's left normal (s.lx and s.ly)
  25981. var dp2 = c1.vx * (s.lx / s.magnitude) + c1.vy * (s.ly / s.magnitude);
  25982. //Project the c1's velocity onto the surface's left normal
  25983. p1B.x = dp2 * (s.lx / s.magnitude);
  25984. p1B.y = dp2 * (s.ly / s.magnitude);
  25985. //3. Bounce c2 off the surface (s)
  25986. //Find the dot product between c2 and the surface
  25987. var dp3 = c2.vx * s.dx + c2.vy * s.dy;
  25988. //Project c2's velocity onto the collision surface
  25989. p2A.x = dp3 * s.dx;
  25990. p2A.y = dp3 * s.dy;
  25991. //Find the dot product of c2 and the surface's left normal (s.lx and s.ly)
  25992. var dp4 = c2.vx * (s.lx / s.magnitude) + c2.vy * (s.ly / s.magnitude);
  25993. //Project c2's velocity onto the surface's left normal
  25994. p2B.x = dp4 * (s.lx / s.magnitude);
  25995. p2B.y = dp4 * (s.ly / s.magnitude);
  25996. //4. Calculate the bounce vectors
  25997. //Bounce c1
  25998. //using p1B and p2A
  25999. c1.bounce = {};
  26000. c1.bounce.x = p1B.x + p2A.x;
  26001. c1.bounce.y = p1B.y + p2A.y;
  26002. //Bounce c2
  26003. //using p1A and p2B
  26004. c2.bounce = {};
  26005. c2.bounce.x = p1A.x + p2B.x;
  26006. c2.bounce.y = p1A.y + p2B.y;
  26007. //Add the bounce vector to the circles' velocity
  26008. //and add mass if the circle has a mass property
  26009. c1.vx = c1.bounce.x / c1.mass;
  26010. c1.vy = c1.bounce.y / c1.mass;
  26011. c2.vx = c2.bounce.x / c2.mass;
  26012. c2.vy = c2.bounce.y / c2.mass;
  26013. }
  26014. return hit;
  26015. }
  26016. /*
  26017. multipleCircleCollision
  26018. -----------------------
  26019. Checks all the circles in an array for a collision against
  26020. all the other circles in an array, using `movingCircleCollision` (above)
  26021. */
  26022. }, {
  26023. key: "multipleCircleCollision",
  26024. value: function multipleCircleCollision(arrayOfCircles) {
  26025. var global = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1];
  26026. for (var i = 0; i < arrayOfCircles.length; i++) {
  26027. //The first circle to use in the collision check
  26028. var c1 = arrayOfCircles[i];
  26029. for (var j = i + 1; j < arrayOfCircles.length; j++) {
  26030. //The second circle to use in the collision check
  26031. var c2 = arrayOfCircles[j];
  26032. //Check for a collision and bounce the circles apart if
  26033. //they collide. Use an optional `mass` property on the sprite
  26034. //to affect the bounciness of each marble
  26035. this.movingCircleCollision(c1, c2, global);
  26036. }
  26037. }
  26038. }
  26039. /*
  26040. rectangleCollision
  26041. ------------------
  26042. Use it to prevent two rectangular sprites from overlapping.
  26043. Optionally, make the first rectangle bounce off the second rectangle.
  26044. Parameters:
  26045. a. A sprite object with `x`, `y` `centerX`, `centerY`, `halfWidth` and `halfHeight` properties.
  26046. b. A sprite object with `x`, `y` `centerX`, `centerY`, `halfWidth` and `halfHeight` properties.
  26047. c. Optional: true or false to indicate whether or not the first sprite
  26048. should bounce off the second sprite.
  26049. */
  26050. }, {
  26051. key: "rectangleCollision",
  26052. value: function rectangleCollision(r1, r2) {
  26053. var bounce = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  26054. var global = arguments.length <= 3 || arguments[3] === undefined ? true : arguments[3];
  26055. //Add collision properties
  26056. if (!r1._bumpPropertiesAdded) this.addCollisionProperties(r1);
  26057. if (!r2._bumpPropertiesAdded) this.addCollisionProperties(r2);
  26058. var collision = undefined,
  26059. combinedHalfWidths = undefined,
  26060. combinedHalfHeights = undefined,
  26061. overlapX = undefined,
  26062. overlapY = undefined,
  26063. vx = undefined,
  26064. vy = undefined;
  26065. //Calculate the distance vector
  26066. if (global) {
  26067. vx = r1.gx + Math.abs(r1.halfWidth) - r1.xAnchorOffset - (r2.gx + Math.abs(r2.halfWidth) - r2.xAnchorOffset);
  26068. vy = r1.gy + Math.abs(r1.halfHeight) - r1.yAnchorOffset - (r2.gy + Math.abs(r2.halfHeight) - r2.yAnchorOffset);
  26069. } else {
  26070. //vx = r1.centerX - r2.centerX;
  26071. //vy = r1.centerY - r2.centerY;
  26072. vx = r1.x + Math.abs(r1.halfWidth) - r1.xAnchorOffset - (r2.x + Math.abs(r2.halfWidth) - r2.xAnchorOffset);
  26073. vy = r1.y + Math.abs(r1.halfHeight) - r1.yAnchorOffset - (r2.y + Math.abs(r2.halfHeight) - r2.yAnchorOffset);
  26074. }
  26075. //Figure out the combined half-widths and half-heights
  26076. combinedHalfWidths = Math.abs(r1.halfWidth) + Math.abs(r2.halfWidth);
  26077. combinedHalfHeights = Math.abs(r1.halfHeight) + Math.abs(r2.halfHeight);
  26078. //Check whether vx is less than the combined half widths
  26079. if (Math.abs(vx) < combinedHalfWidths) {
  26080. //A collision might be occurring!
  26081. //Check whether vy is less than the combined half heights
  26082. if (Math.abs(vy) < combinedHalfHeights) {
  26083. //A collision has occurred! This is good!
  26084. //Find out the size of the overlap on both the X and Y axes
  26085. overlapX = combinedHalfWidths - Math.abs(vx);
  26086. overlapY = combinedHalfHeights - Math.abs(vy);
  26087. //The collision has occurred on the axis with the
  26088. //*smallest* amount of overlap. Let's figure out which
  26089. //axis that is
  26090. if (overlapX >= overlapY) {
  26091. //The collision is happening on the X axis
  26092. //But on which side? vy can tell us
  26093. if (vy > 0) {
  26094. collision = "top";
  26095. //Move the rectangle out of the collision
  26096. r1.y = r1.y + overlapY;
  26097. } else {
  26098. collision = "bottom";
  26099. //Move the rectangle out of the collision
  26100. r1.y = r1.y - overlapY;
  26101. }
  26102. //Bounce
  26103. if (bounce) {
  26104. r1.vy *= -1;
  26105. /*Alternative
  26106. //Find the bounce surface's vx and vy properties
  26107. var s = {};
  26108. s.vx = r2.x - r2.x + r2.width;
  26109. s.vy = 0;
  26110. //Bounce r1 off the surface
  26111. //this.bounceOffSurface(r1, s);
  26112. */
  26113. }
  26114. } else {
  26115. //The collision is happening on the Y axis
  26116. //But on which side? vx can tell us
  26117. if (vx > 0) {
  26118. collision = "left";
  26119. //Move the rectangle out of the collision
  26120. r1.x = r1.x + overlapX;
  26121. } else {
  26122. collision = "right";
  26123. //Move the rectangle out of the collision
  26124. r1.x = r1.x - overlapX;
  26125. }
  26126. //Bounce
  26127. if (bounce) {
  26128. r1.vx *= -1;
  26129. /*Alternative
  26130. //Find the bounce surface's vx and vy properties
  26131. var s = {};
  26132. s.vx = 0;
  26133. s.vy = r2.y - r2.y + r2.height;
  26134. //Bounce r1 off the surface
  26135. this.bounceOffSurface(r1, s);
  26136. */
  26137. }
  26138. }
  26139. } else {
  26140. //No collision
  26141. }
  26142. } else {}
  26143. //No collision
  26144. //Return the collision string. it will be either "top", "right",
  26145. //"bottom", or "left" depending on which side of r1 is touching r2.
  26146. return collision;
  26147. }
  26148. /*
  26149. hitTestRectangle
  26150. ----------------
  26151. Use it to find out if two rectangular sprites are touching.
  26152. Parameters:
  26153. a. A sprite object with `centerX`, `centerY`, `halfWidth` and `halfHeight` properties.
  26154. b. A sprite object with `centerX`, `centerY`, `halfWidth` and `halfHeight` properties.
  26155. */
  26156. }, {
  26157. key: "hitTestRectangle",
  26158. value: function hitTestRectangle(r1, r2) {
  26159. var global = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  26160. //Add collision properties
  26161. if (!r1._bumpPropertiesAdded) this.addCollisionProperties(r1);
  26162. if (!r2._bumpPropertiesAdded) this.addCollisionProperties(r2);
  26163. var hit = undefined,
  26164. combinedHalfWidths = undefined,
  26165. combinedHalfHeights = undefined,
  26166. vx = undefined,
  26167. vy = undefined;
  26168. //A variable to determine whether there's a collision
  26169. hit = false;
  26170. //Calculate the distance vector
  26171. if (global) {
  26172. vx = r1.gx + Math.abs(r1.halfWidth) - r1.xAnchorOffset - (r2.gx + Math.abs(r2.halfWidth) - r2.xAnchorOffset);
  26173. vy = r1.gy + Math.abs(r1.halfHeight) - r1.yAnchorOffset - (r2.gy + Math.abs(r2.halfHeight) - r2.yAnchorOffset);
  26174. } else {
  26175. vx = r1.x + Math.abs(r1.halfWidth) - r1.xAnchorOffset - (r2.x + Math.abs(r2.halfWidth) - r2.xAnchorOffset);
  26176. vy = r1.y + Math.abs(r1.halfHeight) - r1.yAnchorOffset - (r2.y + Math.abs(r2.halfHeight) - r2.yAnchorOffset);
  26177. }
  26178. //Figure out the combined half-widths and half-heights
  26179. combinedHalfWidths = Math.abs(r1.halfWidth) + Math.abs(r2.halfWidth);
  26180. combinedHalfHeights = Math.abs(r1.halfHeight) + Math.abs(r2.halfHeight);
  26181. //Check for a collision on the x axis
  26182. if (Math.abs(vx) < combinedHalfWidths) {
  26183. //A collision might be occuring. Check for a collision on the y axis
  26184. if (Math.abs(vy) < combinedHalfHeights) {
  26185. //There's definitely a collision happening
  26186. hit = true;
  26187. } else {
  26188. //There's no collision on the y axis
  26189. hit = false;
  26190. }
  26191. } else {
  26192. //There's no collision on the x axis
  26193. hit = false;
  26194. }
  26195. //`hit` will be either `true` or `false`
  26196. return hit;
  26197. }
  26198. /*
  26199. hitTestCircleRectangle
  26200. ----------------
  26201. Use it to find out if a circular shape is touching a rectangular shape
  26202. Parameters:
  26203. a. A sprite object with `centerX`, `centerY`, `halfWidth` and `halfHeight` properties.
  26204. b. A sprite object with `centerX`, `centerY`, `halfWidth` and `halfHeight` properties.
  26205. */
  26206. }, {
  26207. key: "hitTestCircleRectangle",
  26208. value: function hitTestCircleRectangle(c1, r1) {
  26209. var global = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  26210. //Add collision properties
  26211. if (!r1._bumpPropertiesAdded) this.addCollisionProperties(r1);
  26212. if (!c1._bumpPropertiesAdded) this.addCollisionProperties(c1);
  26213. var region = undefined,
  26214. collision = undefined,
  26215. c1x = undefined,
  26216. c1y = undefined,
  26217. r1x = undefined,
  26218. r1y = undefined;
  26219. //Use either global or local coordinates
  26220. if (global) {
  26221. c1x = c1.gx;
  26222. c1y = c1.gy;
  26223. r1x = r1.gx;
  26224. r1y = r1.gy;
  26225. } else {
  26226. c1x = c1.x;
  26227. c1y = c1.y;
  26228. r1x = r1.x;
  26229. r1y = r1.y;
  26230. }
  26231. //Is the circle above the rectangle's top edge?
  26232. if (c1y - c1.yAnchorOffset < r1y - Math.abs(r1.halfHeight) - r1.yAnchorOffset) {
  26233. //If it is, we need to check whether it's in the
  26234. //top left, top center or top right
  26235. if (c1x - c1.xAnchorOffset < r1x - 1 - Math.abs(r1.halfWidth) - r1.xAnchorOffset) {
  26236. region = "topLeft";
  26237. } else if (c1x - c1.xAnchorOffset > r1x + 1 + Math.abs(r1.halfWidth) - r1.xAnchorOffset) {
  26238. region = "topRight";
  26239. } else {
  26240. region = "topMiddle";
  26241. }
  26242. }
  26243. //The circle isn't above the top edge, so it might be
  26244. //below the bottom edge
  26245. else if (c1y - c1.yAnchorOffset > r1y + Math.abs(r1.halfHeight) - r1.yAnchorOffset) {
  26246. //If it is, we need to check whether it's in the bottom left,
  26247. //bottom center, or bottom right
  26248. if (c1x - c1.xAnchorOffset < r1x - 1 - Math.abs(r1.halfWidth) - r1.xAnchorOffset) {
  26249. region = "bottomLeft";
  26250. } else if (c1x - c1.xAnchorOffset > r1x + 1 + Math.abs(r1.halfWidth) - r1.xAnchorOffset) {
  26251. region = "bottomRight";
  26252. } else {
  26253. region = "bottomMiddle";
  26254. }
  26255. }
  26256. //The circle isn't above the top edge or below the bottom edge,
  26257. //so it must be on the left or right side
  26258. else {
  26259. if (c1x - c1.xAnchorOffset < r1x - Math.abs(r1.halfWidth) - r1.xAnchorOffset) {
  26260. region = "leftMiddle";
  26261. } else {
  26262. region = "rightMiddle";
  26263. }
  26264. }
  26265. //Is this the circle touching the flat sides
  26266. //of the rectangle?
  26267. if (region === "topMiddle" || region === "bottomMiddle" || region === "leftMiddle" || region === "rightMiddle") {
  26268. //Yes, it is, so do a standard rectangle vs. rectangle collision test
  26269. collision = this.hitTestRectangle(c1, r1, global);
  26270. }
  26271. //The circle is touching one of the corners, so do a
  26272. //circle vs. point collision test
  26273. else {
  26274. var point = {};
  26275. switch (region) {
  26276. case "topLeft":
  26277. point.x = r1x - r1.xAnchorOffset;
  26278. point.y = r1y - r1.yAnchorOffset;
  26279. break;
  26280. case "topRight":
  26281. point.x = r1x + r1.width - r1.xAnchorOffset;
  26282. point.y = r1y - r1.yAnchorOffset;
  26283. break;
  26284. case "bottomLeft":
  26285. point.x = r1x - r1.xAnchorOffset;
  26286. point.y = r1y + r1.height - r1.yAnchorOffset;
  26287. break;
  26288. case "bottomRight":
  26289. point.x = r1x + r1.width - r1.xAnchorOffset;
  26290. point.y = r1y + r1.height - r1.yAnchorOffset;
  26291. }
  26292. //Check for a collision between the circle and the point
  26293. collision = this.hitTestCirclePoint(c1, point, global);
  26294. }
  26295. //Return the result of the collision.
  26296. //The return value will be `undefined` if there's no collision
  26297. if (collision) {
  26298. return region;
  26299. } else {
  26300. return collision;
  26301. }
  26302. }
  26303. /*
  26304. hitTestCirclePoint
  26305. ------------------
  26306. Use it to find out if a circular shape is touching a point
  26307. Parameters:
  26308. a. A sprite object with `centerX`, `centerY`, and `radius` properties.
  26309. b. A point object with `x` and `y` properties.
  26310. */
  26311. }, {
  26312. key: "hitTestCirclePoint",
  26313. value: function hitTestCirclePoint(c1, point) {
  26314. var global = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  26315. //Add collision properties
  26316. if (!c1._bumpPropertiesAdded) this.addCollisionProperties(c1);
  26317. //A point is just a circle with a diameter of
  26318. //1 pixel, so we can cheat. All we need to do is an ordinary circle vs. circle
  26319. //Collision test. Just supply the point with the properties
  26320. //it needs
  26321. point.diameter = 1;
  26322. point.width = point.diameter;
  26323. point.radius = 0.5;
  26324. point.centerX = point.x;
  26325. point.centerY = point.y;
  26326. point.gx = point.x;
  26327. point.gy = point.y;
  26328. point.xAnchorOffset = 0;
  26329. point.yAnchorOffset = 0;
  26330. point._bumpPropertiesAdded = true;
  26331. return this.hitTestCircle(c1, point, global);
  26332. }
  26333. /*
  26334. circleRectangleCollision
  26335. ------------------------
  26336. Use it to bounce a circular shape off a rectangular shape
  26337. Parameters:
  26338. a. A sprite object with `centerX`, `centerY`, `halfWidth` and `halfHeight` properties.
  26339. b. A sprite object with `centerX`, `centerY`, `halfWidth` and `halfHeight` properties.
  26340. */
  26341. }, {
  26342. key: "circleRectangleCollision",
  26343. value: function circleRectangleCollision(c1, r1) {
  26344. var bounce = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  26345. var global = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
  26346. //Add collision properties
  26347. if (!r1._bumpPropertiesAdded) this.addCollisionProperties(r1);
  26348. if (!c1._bumpPropertiesAdded) this.addCollisionProperties(c1);
  26349. var region = undefined,
  26350. collision = undefined,
  26351. c1x = undefined,
  26352. c1y = undefined,
  26353. r1x = undefined,
  26354. r1y = undefined;
  26355. //Use either the global or local coordinates
  26356. if (global) {
  26357. c1x = c1.gx;
  26358. c1y = c1.gy;
  26359. r1x = r1.gx;
  26360. r1y = r1.gy;
  26361. } else {
  26362. c1x = c1.x;
  26363. c1y = c1.y;
  26364. r1x = r1.x;
  26365. r1y = r1.y;
  26366. }
  26367. //Is the circle above the rectangle's top edge?
  26368. if (c1y - c1.yAnchorOffset < r1y - Math.abs(r1.halfHeight) - r1.yAnchorOffset) {
  26369. //If it is, we need to check whether it's in the
  26370. //top left, top center or top right
  26371. if (c1x - c1.xAnchorOffset < r1x - 1 - Math.abs(r1.halfWidth) - r1.xAnchorOffset) {
  26372. region = "topLeft";
  26373. } else if (c1x - c1.xAnchorOffset > r1x + 1 + Math.abs(r1.halfWidth) - r1.xAnchorOffset) {
  26374. region = "topRight";
  26375. } else {
  26376. region = "topMiddle";
  26377. }
  26378. }
  26379. //The circle isn't above the top edge, so it might be
  26380. //below the bottom edge
  26381. else if (c1y - c1.yAnchorOffset > r1y + Math.abs(r1.halfHeight) - r1.yAnchorOffset) {
  26382. //If it is, we need to check whether it's in the bottom left,
  26383. //bottom center, or bottom right
  26384. if (c1x - c1.xAnchorOffset < r1x - 1 - Math.abs(r1.halfWidth) - r1.xAnchorOffset) {
  26385. region = "bottomLeft";
  26386. } else if (c1x - c1.xAnchorOffset > r1x + 1 + Math.abs(r1.halfWidth) - r1.xAnchorOffset) {
  26387. region = "bottomRight";
  26388. } else {
  26389. region = "bottomMiddle";
  26390. }
  26391. }
  26392. //The circle isn't above the top edge or below the bottom edge,
  26393. //so it must be on the left or right side
  26394. else {
  26395. if (c1x - c1.xAnchorOffset < r1x - Math.abs(r1.halfWidth) - r1.xAnchorOffset) {
  26396. region = "leftMiddle";
  26397. } else {
  26398. region = "rightMiddle";
  26399. }
  26400. }
  26401. //Is this the circle touching the flat sides
  26402. //of the rectangle?
  26403. if (region === "topMiddle" || region === "bottomMiddle" || region === "leftMiddle" || region === "rightMiddle") {
  26404. //Yes, it is, so do a standard rectangle vs. rectangle collision test
  26405. collision = this.rectangleCollision(c1, r1, bounce, global);
  26406. }
  26407. //The circle is touching one of the corners, so do a
  26408. //circle vs. point collision test
  26409. else {
  26410. var point = {};
  26411. switch (region) {
  26412. case "topLeft":
  26413. point.x = r1x - r1.xAnchorOffset;
  26414. point.y = r1y - r1.yAnchorOffset;
  26415. break;
  26416. case "topRight":
  26417. point.x = r1x + r1.width - r1.xAnchorOffset;
  26418. point.y = r1y - r1.yAnchorOffset;
  26419. break;
  26420. case "bottomLeft":
  26421. point.x = r1x - r1.xAnchorOffset;
  26422. point.y = r1y + r1.height - r1.yAnchorOffset;
  26423. break;
  26424. case "bottomRight":
  26425. point.x = r1x + r1.width - r1.xAnchorOffset;
  26426. point.y = r1y + r1.height - r1.yAnchorOffset;
  26427. }
  26428. //Check for a collision between the circle and the point
  26429. collision = this.circlePointCollision(c1, point, bounce, global);
  26430. }
  26431. if (collision) {
  26432. return region;
  26433. } else {
  26434. return collision;
  26435. }
  26436. }
  26437. /*
  26438. circlePointCollision
  26439. --------------------
  26440. Use it to boucnce a circle off a point.
  26441. Parameters:
  26442. a. A sprite object with `centerX`, `centerY`, and `radius` properties.
  26443. b. A point object with `x` and `y` properties.
  26444. */
  26445. }, {
  26446. key: "circlePointCollision",
  26447. value: function circlePointCollision(c1, point) {
  26448. var bounce = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  26449. var global = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
  26450. //Add collision properties
  26451. if (!c1._bumpPropertiesAdded) this.addCollisionProperties(c1);
  26452. //A point is just a circle with a diameter of
  26453. //1 pixel, so we can cheat. All we need to do is an ordinary circle vs. circle
  26454. //Collision test. Just supply the point with the properties
  26455. //it needs
  26456. point.diameter = 1;
  26457. point.width = point.diameter;
  26458. point.radius = 0.5;
  26459. point.centerX = point.x;
  26460. point.centerY = point.y;
  26461. point.gx = point.x;
  26462. point.gy = point.y;
  26463. point.xAnchorOffset = 0;
  26464. point.yAnchorOffset = 0;
  26465. point._bumpPropertiesAdded = true;
  26466. return this.circleCollision(c1, point, bounce, global);
  26467. }
  26468. /*
  26469. bounceOffSurface
  26470. ----------------
  26471. Use this to bounce an object off another object.
  26472. Parameters:
  26473. a. An object with `v.x` and `v.y` properties. This represents the object that is colliding
  26474. with a surface.
  26475. b. An object with `x` and `y` properties. This represents the surface that the object
  26476. is colliding into.
  26477. The first object can optionally have a mass property that's greater than 1. The mass will
  26478. be used to dampen the bounce effect.
  26479. */
  26480. }, {
  26481. key: "bounceOffSurface",
  26482. value: function bounceOffSurface(o, s) {
  26483. //Add collision properties
  26484. if (!o._bumpPropertiesAdded) this.addCollisionProperties(o);
  26485. var dp1 = undefined,
  26486. dp2 = undefined,
  26487. p1 = {},
  26488. p2 = {},
  26489. bounce = {},
  26490. mass = o.mass || 1;
  26491. //1. Calculate the collision surface's properties
  26492. //Find the surface vector's left normal
  26493. s.lx = s.y;
  26494. s.ly = -s.x;
  26495. //Find its magnitude
  26496. s.magnitude = Math.sqrt(s.x * s.x + s.y * s.y);
  26497. //Find its normalized values
  26498. s.dx = s.x / s.magnitude;
  26499. s.dy = s.y / s.magnitude;
  26500. //2. Bounce the object (o) off the surface (s)
  26501. //Find the dot product between the object and the surface
  26502. dp1 = o.vx * s.dx + o.vy * s.dy;
  26503. //Project the object's velocity onto the collision surface
  26504. p1.vx = dp1 * s.dx;
  26505. p1.vy = dp1 * s.dy;
  26506. //Find the dot product of the object and the surface's left normal (s.lx and s.ly)
  26507. dp2 = o.vx * (s.lx / s.magnitude) + o.vy * (s.ly / s.magnitude);
  26508. //Project the object's velocity onto the surface's left normal
  26509. p2.vx = dp2 * (s.lx / s.magnitude);
  26510. p2.vy = dp2 * (s.ly / s.magnitude);
  26511. //Reverse the projection on the surface's left normal
  26512. p2.vx *= -1;
  26513. p2.vy *= -1;
  26514. //Add up the projections to create a new bounce vector
  26515. bounce.x = p1.vx + p2.vx;
  26516. bounce.y = p1.vy + p2.vy;
  26517. //Assign the bounce vector to the object's velocity
  26518. //with optional mass to dampen the effect
  26519. o.vx = bounce.x / mass;
  26520. o.vy = bounce.y / mass;
  26521. }
  26522. /*
  26523. contain
  26524. -------
  26525. `contain` can be used to contain a sprite with `x` and
  26526. `y` properties inside a rectangular area.
  26527. The `contain` function takes four arguments: a sprite with `x` and `y`
  26528. properties, an object literal with `x`, `y`, `width` and `height` properties. The
  26529. third argument is a Boolean (true/false) value that determines if the sprite
  26530. should bounce when it hits the edge of the container. The fourth argument
  26531. is an extra user-defined callback function that you can call when the
  26532. sprite hits the container
  26533. ```js
  26534. contain(anySprite, {x: 0, y: 0, width: 512, height: 512}, true, callbackFunction);
  26535. ```
  26536. The code above will contain the sprite's position inside the 512 by
  26537. 512 pixel area defined by the object. If the sprite hits the edges of
  26538. the container, it will bounce. The `callBackFunction` will run if
  26539. there's a collision.
  26540. An additional feature of the `contain` method is that if the sprite
  26541. has a `mass` property, it will be used to dampen the sprite's bounce
  26542. in a natural looking way.
  26543. If the sprite bumps into any of the containing object's boundaries,
  26544. the `contain` function will return a value that tells you which side
  26545. the sprite bumped into: “left”, “top”, “right” or “bottom”. Here's how
  26546. you could keep the sprite contained and also find out which boundary
  26547. it hit:
  26548. ```js
  26549. //Contain the sprite and find the collision value
  26550. let collision = contain(anySprite, {x: 0, y: 0, width: 512, height: 512});
  26551. //If there's a collision, display the boundary that the collision happened on
  26552. if(collision) {
  26553. if collision.has("left") console.log("The sprite hit the left");
  26554. if collision.has("top") console.log("The sprite hit the top");
  26555. if collision.has("right") console.log("The sprite hit the right");
  26556. if collision.has("bottom") console.log("The sprite hit the bottom");
  26557. }
  26558. ```
  26559. If the sprite doesn't hit a boundary, the value of
  26560. `collision` will be `undefined`.
  26561. */
  26562. /*
  26563. contain(sprite, container, bounce = false, extra = undefined) {
  26564. //Helper methods that compensate for any possible shift the the
  26565. //sprites' anchor points
  26566. let nudgeAnchor = (o, value, axis) => {
  26567. if (o.anchor !== undefined) {
  26568. if (o.anchor[axis] !== 0) {
  26569. return value * ((1 - o.anchor[axis]) - o.anchor[axis]);
  26570. } else {
  26571. return value;
  26572. }
  26573. } else {
  26574. return value;
  26575. }
  26576. };
  26577. let compensateForAnchor = (o, value, axis) => {
  26578. if (o.anchor !== undefined) {
  26579. if (o.anchor[axis] !== 0) {
  26580. return value * o.anchor[axis];
  26581. } else {
  26582. return 0;
  26583. }
  26584. } else {
  26585. return 0;
  26586. }
  26587. };
  26588. let compensateForAnchors = (a, b, property1, property2) => {
  26589. return compensateForAnchor(a, a[property1], property2) + compensateForAnchor(b, b[property1], property2)
  26590. };
  26591. //Create a set called `collision` to keep track of the
  26592. //boundaries with which the sprite is colliding
  26593. let collision = new Set();
  26594. //Left
  26595. if (sprite.x - compensateForAnchor(sprite, sprite.width, "x") < container.x - sprite.parent.gx - compensateForAnchor(container, container.width, "x")) {
  26596. //Bounce the sprite if `bounce` is true
  26597. if (bounce) sprite.vx *= -1;
  26598. //If the sprite has `mass`, let the mass
  26599. //affect the sprite's velocity
  26600. if(sprite.mass) sprite.vx /= sprite.mass;
  26601. //Keep the sprite inside the container
  26602. sprite.x = container.x - sprite.parent.gx + compensateForAnchor(sprite, sprite.width, "x") - compensateForAnchor(container, container.width, "x");
  26603. //Add "left" to the collision set
  26604. collision.add("left");
  26605. }
  26606. //Top
  26607. if (sprite.y - compensateForAnchor(sprite, sprite.height, "y") < container.y - sprite.parent.gy - compensateForAnchor(container, container.height, "y")) {
  26608. if (bounce) sprite.vy *= -1;
  26609. if(sprite.mass) sprite.vy /= sprite.mass;
  26610. sprite.y = container.x - sprite.parent.gy + compensateForAnchor(sprite, sprite.height, "y") - compensateForAnchor(container, container.height, "y");
  26611. collision.add("top");
  26612. }
  26613. //Right
  26614. if (sprite.x - compensateForAnchor(sprite, sprite.width, "x") + sprite.width > container.width - compensateForAnchor(container, container.width, "x")) {
  26615. if (bounce) sprite.vx *= -1;
  26616. if(sprite.mass) sprite.vx /= sprite.mass;
  26617. sprite.x = container.width - sprite.width + compensateForAnchor(sprite, sprite.width, "x") - compensateForAnchor(container, container.width, "x");
  26618. collision.add("right");
  26619. }
  26620. //Bottom
  26621. if (sprite.y - compensateForAnchor(sprite, sprite.height, "y") + sprite.height > container.height - compensateForAnchor(container, container.height, "y")) {
  26622. if (bounce) sprite.vy *= -1;
  26623. if(sprite.mass) sprite.vy /= sprite.mass;
  26624. sprite.y = container.height - sprite.height + compensateForAnchor(sprite, sprite.height, "y") - compensateForAnchor(container, container.height, "y");
  26625. collision.add("bottom");
  26626. }
  26627. //If there were no collisions, set `collision` to `undefined`
  26628. if (collision.size === 0) collision = undefined;
  26629. //The `extra` function runs if there was a collision
  26630. //and `extra` has been defined
  26631. if (collision && extra) extra(collision);
  26632. //Return the `collision` value
  26633. return collision;
  26634. }
  26635. */
  26636. }, {
  26637. key: "contain",
  26638. value: function contain(sprite, container) {
  26639. var bounce = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  26640. var extra = arguments.length <= 3 || arguments[3] === undefined ? undefined : arguments[3];
  26641. //Add collision properties
  26642. if (!sprite._bumpPropertiesAdded) this.addCollisionProperties(sprite);
  26643. //Give the container x and y anchor offset values, if it doesn't
  26644. //have any
  26645. if (container.xAnchorOffset === undefined) container.xAnchorOffset = 0;
  26646. if (container.yAnchorOffset === undefined) container.yAnchorOffset = 0;
  26647. if (sprite.parent.gx === undefined) sprite.parent.gx = 0;
  26648. if (sprite.parent.gy === undefined) sprite.parent.gy = 0;
  26649. //Create a Set called `collision` to keep track of the
  26650. //boundaries with which the sprite is colliding
  26651. var collision = new Set();
  26652. //Left
  26653. if (sprite.x - sprite.xAnchorOffset < container.x - sprite.parent.gx - container.xAnchorOffset) {
  26654. //Bounce the sprite if `bounce` is true
  26655. if (bounce) sprite.vx *= -1;
  26656. //If the sprite has `mass`, let the mass
  26657. //affect the sprite's velocity
  26658. if (sprite.mass) sprite.vx /= sprite.mass;
  26659. //Reposition the sprite inside the container
  26660. sprite.x = container.x - sprite.parent.gx - container.xAnchorOffset + sprite.xAnchorOffset;
  26661. //Make a record of the side which the container hit
  26662. collision.add("left");
  26663. }
  26664. //Top
  26665. if (sprite.y - sprite.yAnchorOffset < container.y - sprite.parent.gy - container.yAnchorOffset) {
  26666. if (bounce) sprite.vy *= -1;
  26667. if (sprite.mass) sprite.vy /= sprite.mass;
  26668. sprite.y = container.y - sprite.parent.gy - container.yAnchorOffset + sprite.yAnchorOffset;;
  26669. collision.add("top");
  26670. }
  26671. //Right
  26672. if (sprite.x - sprite.xAnchorOffset + sprite.width > container.width - container.xAnchorOffset) {
  26673. if (bounce) sprite.vx *= -1;
  26674. if (sprite.mass) sprite.vx /= sprite.mass;
  26675. sprite.x = container.width - sprite.width - container.xAnchorOffset + sprite.xAnchorOffset;
  26676. collision.add("right");
  26677. }
  26678. //Bottom
  26679. if (sprite.y - sprite.yAnchorOffset + sprite.height > container.height - container.yAnchorOffset) {
  26680. if (bounce) sprite.vy *= -1;
  26681. if (sprite.mass) sprite.vy /= sprite.mass;
  26682. sprite.y = container.height - sprite.height - container.yAnchorOffset + sprite.yAnchorOffset;
  26683. collision.add("bottom");
  26684. }
  26685. //If there were no collisions, set `collision` to `undefined`
  26686. if (collision.size === 0) collision = undefined;
  26687. //The `extra` function runs if there was a collision
  26688. //and `extra` has been defined
  26689. if (collision && extra) extra(collision);
  26690. //Return the `collision` value
  26691. return collision;
  26692. }
  26693. //`outsideBounds` checks whether a sprite is outide the boundary of
  26694. //another object. It returns an object called `collision`. `collision` will be `undefined` if there's no
  26695. //collision. But if there is a collision, `collision` will be
  26696. //returned as a Set containg strings that tell you which boundary
  26697. //side was crossed: "left", "right", "top" or "bottom"
  26698. }, {
  26699. key: "outsideBounds",
  26700. value: function outsideBounds(s, bounds, extra) {
  26701. var x = bounds.x,
  26702. y = bounds.y,
  26703. width = bounds.width,
  26704. height = bounds.height;
  26705. //The `collision` object is used to store which
  26706. //side of the containing rectangle the sprite hits
  26707. var collision = new Set();
  26708. //Left
  26709. if (s.x < x - s.width) {
  26710. collision.add("left");
  26711. }
  26712. //Top
  26713. if (s.y < y - s.height) {
  26714. collision.add("top");
  26715. }
  26716. //Right
  26717. if (s.x > width + s.width) {
  26718. collision.add("right");
  26719. }
  26720. //Bottom
  26721. if (s.y > height + s.height) {
  26722. collision.add("bottom");
  26723. }
  26724. //If there were no collisions, set `collision` to `undefined`
  26725. if (collision.size === 0) collision = undefined;
  26726. //The `extra` function runs if there was a collision
  26727. //and `extra` has been defined
  26728. if (collision && extra) extra(collision);
  26729. //Return the `collision` object
  26730. return collision;
  26731. }
  26732. /*
  26733. _getCenter
  26734. ----------
  26735. A utility that finds the center point of the sprite. If it's anchor point is the
  26736. sprite's top left corner, then the center is calculated from that point.
  26737. If the anchor point has been shifted, then the anchor x/y point is used as the sprite's center
  26738. */
  26739. }, {
  26740. key: "_getCenter",
  26741. value: function _getCenter(o, dimension, axis) {
  26742. if (o.anchor !== undefined) {
  26743. if (o.anchor[axis] !== 0) {
  26744. return 0;
  26745. } else {
  26746. //console.log(o.anchor[axis])
  26747. return dimension / 2;
  26748. }
  26749. } else {
  26750. return dimension;
  26751. }
  26752. }
  26753. /*
  26754. hit
  26755. ---
  26756. A convenient universal collision function to test for collisions
  26757. between rectangles, circles, and points.
  26758. */
  26759. }, {
  26760. key: "hit",
  26761. value: function hit(a, b) {
  26762. var react = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  26763. var bounce = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
  26764. var global = arguments[4];
  26765. var extra = arguments.length <= 5 || arguments[5] === undefined ? undefined : arguments[5];
  26766. //Local references to bump's collision methods
  26767. var hitTestPoint = this.hitTestPoint.bind(this),
  26768. hitTestRectangle = this.hitTestRectangle.bind(this),
  26769. hitTestCircle = this.hitTestCircle.bind(this),
  26770. movingCircleCollision = this.movingCircleCollision.bind(this),
  26771. circleCollision = this.circleCollision.bind(this),
  26772. hitTestCircleRectangle = this.hitTestCircleRectangle.bind(this),
  26773. rectangleCollision = this.rectangleCollision.bind(this),
  26774. circleRectangleCollision = this.circleRectangleCollision.bind(this);
  26775. var collision = undefined,
  26776. aIsASprite = a.parent !== undefined,
  26777. bIsASprite = b.parent !== undefined;
  26778. //Check to make sure one of the arguments isn't an array
  26779. if (aIsASprite && b instanceof Array || bIsASprite && a instanceof Array) {
  26780. //If it is, check for a collision between a sprite and an array
  26781. spriteVsArray();
  26782. } else {
  26783. //If one of the arguments isn't an array, find out what type of
  26784. //collision check to run
  26785. collision = findCollisionType(a, b);
  26786. if (collision && extra) extra(collision);
  26787. }
  26788. //Return the result of the collision.
  26789. //It will be `undefined` if there's no collision and `true` if
  26790. //there is a collision. `rectangleCollision` sets `collsision` to
  26791. //"top", "bottom", "left" or "right" depeneding on which side the
  26792. //collision is occuring on
  26793. return collision;
  26794. function findCollisionType(a, b) {
  26795. //Are `a` and `b` both sprites?
  26796. //(We have to check again if this function was called from
  26797. //`spriteVsArray`)
  26798. var aIsASprite = a.parent !== undefined;
  26799. var bIsASprite = b.parent !== undefined;
  26800. if (aIsASprite && bIsASprite) {
  26801. //Yes, but what kind of sprites?
  26802. if (a.diameter && b.diameter) {
  26803. //They're circles
  26804. return circleVsCircle(a, b);
  26805. } else if (a.diameter && !b.diameter) {
  26806. //The first one is a circle and the second is a rectangle
  26807. return circleVsRectangle(a, b);
  26808. } else {
  26809. //They're rectangles
  26810. return rectangleVsRectangle(a, b);
  26811. }
  26812. }
  26813. //They're not both sprites, so what are they?
  26814. //Is `a` not a sprite and does it have x and y properties?
  26815. else if (bIsASprite && !(a.x === undefined) && !(a.y === undefined)) {
  26816. //Yes, so this is a point vs. sprite collision test
  26817. return hitTestPoint(a, b);
  26818. } else {
  26819. //The user is trying to test some incompatible objects
  26820. throw new Error("I'm sorry, " + a + " and " + b + " cannot be use together in a collision test.'");
  26821. }
  26822. }
  26823. function spriteVsArray() {
  26824. //If `a` happens to be the array, flip it around so that it becomes `b`
  26825. if (a instanceof Array) {
  26826. var _ref = [_b, _a];
  26827. var _a = _ref[0];
  26828. var _b = _ref[1];
  26829. }
  26830. //Loop through the array in reverse
  26831. for (var i = b.length - 1; i >= 0; i--) {
  26832. var sprite = b[i];
  26833. collision = findCollisionType(a, sprite);
  26834. if (collision && extra) extra(collision, sprite);
  26835. }
  26836. }
  26837. function circleVsCircle(a, b) {
  26838. //If the circles shouldn't react to the collision,
  26839. //just test to see if they're touching
  26840. if (!react) {
  26841. return hitTestCircle(a, b);
  26842. }
  26843. //Yes, the circles should react to the collision
  26844. else {
  26845. //Are they both moving?
  26846. if (a.vx + a.vy !== 0 && b.vx + b.vy !== 0) {
  26847. //Yes, they are both moving
  26848. //(moving circle collisions always bounce apart so there's
  26849. //no need for the third, `bounce`, argument)
  26850. return movingCircleCollision(a, b, global);
  26851. } else {
  26852. //No, they're not both moving
  26853. return circleCollision(a, b, bounce, global);
  26854. }
  26855. }
  26856. }
  26857. function rectangleVsRectangle(a, b) {
  26858. //If the rectangles shouldn't react to the collision, just
  26859. //test to see if they're touching
  26860. if (!react) {
  26861. return hitTestRectangle(a, b, global);
  26862. } else {
  26863. return rectangleCollision(a, b, bounce, global);
  26864. }
  26865. }
  26866. function circleVsRectangle(a, b) {
  26867. //If the rectangles shouldn't react to the collision, just
  26868. //test to see if they're touching
  26869. if (!react) {
  26870. return hitTestCircleRectangle(a, b, global);
  26871. } else {
  26872. return circleRectangleCollision(a, b, bounce, global);
  26873. }
  26874. }
  26875. }
  26876. }]);
  26877. return Bump;
  26878. })();
  26879. //# sourceMappingURL=bump.js.map"use strict";
  26880. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  26881. function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
  26882. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  26883. var Charm = (function () {
  26884. function Charm() {
  26885. var _this = this;
  26886. var renderingEngine = arguments.length <= 0 || arguments[0] === undefined ? PIXI : arguments[0];
  26887. _classCallCheck(this, Charm);
  26888. if (renderingEngine === undefined) throw new Error("Please assign a rendering engine in the constructor before using charm.js");
  26889. //Find out which rendering engine is being used (the default is Pixi)
  26890. this.renderer = "";
  26891. //If the `renderingEngine` is Pixi, set up Pixi object aliases
  26892. if (renderingEngine.ParticleContainer && renderingEngine.Sprite) {
  26893. this.renderer = "pixi";
  26894. }
  26895. //An array to store the global tweens
  26896. this.globalTweens = [];
  26897. //An object that stores all the easing formulas
  26898. this.easingFormulas = {
  26899. //Linear
  26900. linear: function linear(x) {
  26901. return x;
  26902. },
  26903. //Smoothstep
  26904. smoothstep: function smoothstep(x) {
  26905. return x * x * (3 - 2 * x);
  26906. },
  26907. smoothstepSquared: function smoothstepSquared(x) {
  26908. return Math.pow(x * x * (3 - 2 * x), 2);
  26909. },
  26910. smoothstepCubed: function smoothstepCubed(x) {
  26911. return Math.pow(x * x * (3 - 2 * x), 3);
  26912. },
  26913. //Acceleration
  26914. acceleration: function acceleration(x) {
  26915. return x * x;
  26916. },
  26917. accelerationCubed: function accelerationCubed(x) {
  26918. return Math.pow(x * x, 3);
  26919. },
  26920. //Deceleration
  26921. deceleration: function deceleration(x) {
  26922. return 1 - Math.pow(1 - x, 2);
  26923. },
  26924. decelerationCubed: function decelerationCubed(x) {
  26925. return 1 - Math.pow(1 - x, 3);
  26926. },
  26927. //Sine
  26928. sine: function sine(x) {
  26929. return Math.sin(x * Math.PI / 2);
  26930. },
  26931. sineSquared: function sineSquared(x) {
  26932. return Math.pow(Math.sin(x * Math.PI / 2), 2);
  26933. },
  26934. sineCubed: function sineCubed(x) {
  26935. return Math.pow(Math.sin(x * Math.PI / 2), 2);
  26936. },
  26937. inverseSine: function inverseSine(x) {
  26938. return 1 - Math.sin((1 - x) * Math.PI / 2);
  26939. },
  26940. inverseSineSquared: function inverseSineSquared(x) {
  26941. return 1 - Math.pow(Math.sin((1 - x) * Math.PI / 2), 2);
  26942. },
  26943. inverseSineCubed: function inverseSineCubed(x) {
  26944. return 1 - Math.pow(Math.sin((1 - x) * Math.PI / 2), 3);
  26945. },
  26946. //Spline
  26947. spline: function spline(t, p0, p1, p2, p3) {
  26948. return 0.5 * (2 * p1 + (-p0 + p2) * t + (2 * p0 - 5 * p1 + 4 * p2 - p3) * t * t + (-p0 + 3 * p1 - 3 * p2 + p3) * t * t * t);
  26949. },
  26950. //Bezier curve
  26951. cubicBezier: function cubicBezier(t, a, b, c, d) {
  26952. var t2 = t * t;
  26953. var t3 = t2 * t;
  26954. return a + (-a * 3 + t * (3 * a - a * t)) * t + (3 * b + t * (-6 * b + b * 3 * t)) * t + (c * 3 - c * 3 * t) * t2 + d * t3;
  26955. }
  26956. };
  26957. //Add `scaleX` and `scaleY` properties to Pixi sprites
  26958. this._addScaleProperties = function (sprite) {
  26959. if (_this.renderer === "pixi") {
  26960. if (!("scaleX" in sprite) && "scale" in sprite && "x" in sprite.scale) {
  26961. Object.defineProperty(sprite, "scaleX", {
  26962. get: function get() {
  26963. return sprite.scale.x;
  26964. },
  26965. set: function set(value) {
  26966. sprite.scale.x = value;
  26967. }
  26968. });
  26969. }
  26970. if (!("scaleY" in sprite) && "scale" in sprite && "y" in sprite.scale) {
  26971. Object.defineProperty(sprite, "scaleY", {
  26972. get: function get() {
  26973. return sprite.scale.y;
  26974. },
  26975. set: function set(value) {
  26976. sprite.scale.y = value;
  26977. }
  26978. });
  26979. }
  26980. }
  26981. };
  26982. }
  26983. //The low level `tweenProperty` function is used as the foundation
  26984. //for the the higher level tween methods.
  26985. _createClass(Charm, [{
  26986. key: "tweenProperty",
  26987. value: function tweenProperty(sprite, //Sprite object
  26988. property, //String property
  26989. startValue, //Tween start value
  26990. endValue, //Tween end value
  26991. totalFrames) //Delay in frames before repeating
  26992. {
  26993. var type = arguments.length <= 5 || arguments[5] === undefined ? "smoothstep" : arguments[5];
  26994. var _this2 = this;
  26995. var yoyo = arguments.length <= 6 || arguments[6] === undefined ? false : arguments[6];
  26996. var delayBeforeRepeat = arguments.length <= 7 || arguments[7] === undefined ? 0 : arguments[7];
  26997. //Create the tween object
  26998. var o = {};
  26999. //If the tween is a bounce type (a spline), set the
  27000. //start and end magnitude values
  27001. var typeArray = type.split(" ");
  27002. if (typeArray[0] === "bounce") {
  27003. o.startMagnitude = parseInt(typeArray[1]);
  27004. o.endMagnitude = parseInt(typeArray[2]);
  27005. }
  27006. //Use `o.start` to make a new tween using the current
  27007. //end point values
  27008. o.start = function (startValue, endValue) {
  27009. //Clone the start and end values so that any possible references to sprite
  27010. //properties are converted to ordinary numbers
  27011. o.startValue = JSON.parse(JSON.stringify(startValue));
  27012. o.endValue = JSON.parse(JSON.stringify(endValue));
  27013. o.playing = true;
  27014. o.totalFrames = totalFrames;
  27015. o.frameCounter = 0;
  27016. //Add the tween to the global `tweens` array. The `tweens` array is
  27017. //updated on each frame
  27018. _this2.globalTweens.push(o);
  27019. };
  27020. //Call `o.start` to start the tween
  27021. o.start(startValue, endValue);
  27022. //The `update` method will be called on each frame by the game loop.
  27023. //This is what makes the tween move
  27024. o.update = function () {
  27025. var time = undefined,
  27026. curvedTime = undefined;
  27027. if (o.playing) {
  27028. //If the elapsed frames are less than the total frames,
  27029. //use the tweening formulas to move the sprite
  27030. if (o.frameCounter < o.totalFrames) {
  27031. //Find the normalized value
  27032. var normalizedTime = o.frameCounter / o.totalFrames;
  27033. //Select the correct easing function from the
  27034. //`ease` object’s library of easing functions
  27035. //If it's not a spline, use one of the ordinary easing functions
  27036. if (typeArray[0] !== "bounce") {
  27037. curvedTime = _this2.easingFormulas[type](normalizedTime);
  27038. }
  27039. //If it's a spline, use the `spline` function and apply the
  27040. //2 additional `type` array values as the spline's start and
  27041. //end points
  27042. else {
  27043. curvedTime = _this2.easingFormulas.spline(normalizedTime, o.startMagnitude, 0, 1, o.endMagnitude);
  27044. }
  27045. //Interpolate the sprite's property based on the curve
  27046. sprite[property] = o.endValue * curvedTime + o.startValue * (1 - curvedTime);
  27047. o.frameCounter += 1;
  27048. }
  27049. //When the tween has finished playing, run the end tasks
  27050. else {
  27051. sprite[property] = o.endValue;
  27052. o.end();
  27053. }
  27054. }
  27055. };
  27056. //The `end` method will be called when the tween is finished
  27057. o.end = function () {
  27058. //Set `playing` to `false`
  27059. o.playing = false;
  27060. //Call the tween's `onComplete` method, if it's been assigned
  27061. if (o.onComplete) o.onComplete();
  27062. //Remove the tween from the `tweens` array
  27063. _this2.globalTweens.splice(_this2.globalTweens.indexOf(o), 1);
  27064. //If the tween's `yoyo` property is `true`, create a new tween
  27065. //using the same values, but use the current tween's `startValue`
  27066. //as the next tween's `endValue`
  27067. if (yoyo) {
  27068. _this2.wait(delayBeforeRepeat).then(function () {
  27069. o.start(o.endValue, o.startValue);
  27070. });
  27071. }
  27072. };
  27073. //Pause and play methods
  27074. o.play = function () {
  27075. return o.playing = true;
  27076. };
  27077. o.pause = function () {
  27078. return o.playing = false;
  27079. };
  27080. //Return the tween object
  27081. return o;
  27082. }
  27083. //`makeTween` is a general low-level method for making complex tweens
  27084. //out of multiple `tweenProperty` functions. Its one argument,
  27085. //`tweensToAdd` is an array containing multiple `tweenProperty` calls
  27086. }, {
  27087. key: "makeTween",
  27088. value: function makeTween(tweensToAdd) {
  27089. var _this3 = this;
  27090. //Create an object to manage the tweens
  27091. var o = {};
  27092. //Create a `tweens` array to store the new tweens
  27093. o.tweens = [];
  27094. //Make a new tween for each array
  27095. tweensToAdd.forEach(function (tweenPropertyArguments) {
  27096. //Use the tween property arguments to make a new tween
  27097. var newTween = _this3.tweenProperty.apply(_this3, _toConsumableArray(tweenPropertyArguments));
  27098. //Push the new tween into this object's internal `tweens` array
  27099. o.tweens.push(newTween);
  27100. });
  27101. //Add a counter to keep track of the
  27102. //number of tweens that have completed their actions
  27103. var completionCounter = 0;
  27104. //`o.completed` will be called each time one of the tweens
  27105. //finishes
  27106. o.completed = function () {
  27107. //Add 1 to the `completionCounter`
  27108. completionCounter += 1;
  27109. //If all tweens have finished, call the user-defined `onComplete`
  27110. //method, if it's been assigned. Reset the `completionCounter`
  27111. if (completionCounter === o.tweens.length) {
  27112. if (o.onComplete) o.onComplete();
  27113. completionCounter = 0;
  27114. }
  27115. };
  27116. //Add `onComplete` methods to all tweens
  27117. o.tweens.forEach(function (tween) {
  27118. tween.onComplete = function () {
  27119. return o.completed();
  27120. };
  27121. });
  27122. //Add pause and play methods to control all the tweens
  27123. o.pause = function () {
  27124. o.tweens.forEach(function (tween) {
  27125. tween.playing = false;
  27126. });
  27127. };
  27128. o.play = function () {
  27129. o.tweens.forEach(function (tween) {
  27130. tween.playing = true;
  27131. });
  27132. };
  27133. //Return the tween object
  27134. return o;
  27135. }
  27136. /* High level tween methods */
  27137. //1. Simple tweens
  27138. //`fadeOut`
  27139. }, {
  27140. key: "fadeOut",
  27141. value: function fadeOut(sprite) {
  27142. var frames = arguments.length <= 1 || arguments[1] === undefined ? 60 : arguments[1];
  27143. return this.tweenProperty(sprite, "alpha", sprite.alpha, 0, frames, "sine");
  27144. }
  27145. //`fadeIn`
  27146. }, {
  27147. key: "fadeIn",
  27148. value: function fadeIn(sprite) {
  27149. var frames = arguments.length <= 1 || arguments[1] === undefined ? 60 : arguments[1];
  27150. return this.tweenProperty(sprite, "alpha", sprite.alpha, 1, frames, "sine");
  27151. }
  27152. //`pulse`
  27153. //Fades the sprite in and out at a steady rate.
  27154. //Set the `minAlpha` to something greater than 0 if you
  27155. //don't want the sprite to fade away completely
  27156. }, {
  27157. key: "pulse",
  27158. value: function pulse(sprite) {
  27159. var frames = arguments.length <= 1 || arguments[1] === undefined ? 60 : arguments[1];
  27160. var minAlpha = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2];
  27161. return this.tweenProperty(sprite, "alpha", sprite.alpha, minAlpha, frames, "smoothstep", true);
  27162. }
  27163. //2. Complex tweens
  27164. }, {
  27165. key: "slide",
  27166. value: function slide(sprite, endX, endY) {
  27167. var frames = arguments.length <= 3 || arguments[3] === undefined ? 60 : arguments[3];
  27168. var type = arguments.length <= 4 || arguments[4] === undefined ? "smoothstep" : arguments[4];
  27169. var yoyo = arguments.length <= 5 || arguments[5] === undefined ? false : arguments[5];
  27170. var delayBeforeRepeat = arguments.length <= 6 || arguments[6] === undefined ? 0 : arguments[6];
  27171. return this.makeTween([
  27172. //Create the x axis tween
  27173. [sprite, "x", sprite.x, endX, frames, type, yoyo, delayBeforeRepeat],
  27174. //Create the y axis tween
  27175. [sprite, "y", sprite.y, endY, frames, type, yoyo, delayBeforeRepeat]]);
  27176. }
  27177. }, {
  27178. key: "breathe",
  27179. value: function breathe(sprite) {
  27180. var endScaleX = arguments.length <= 1 || arguments[1] === undefined ? 0.8 : arguments[1];
  27181. var endScaleY = arguments.length <= 2 || arguments[2] === undefined ? 0.8 : arguments[2];
  27182. var frames = arguments.length <= 3 || arguments[3] === undefined ? 60 : arguments[3];
  27183. var yoyo = arguments.length <= 4 || arguments[4] === undefined ? true : arguments[4];
  27184. var delayBeforeRepeat = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5];
  27185. //Add `scaleX` and `scaleY` properties to Pixi sprites
  27186. this._addScaleProperties(sprite);
  27187. return this.makeTween([
  27188. //Create the scaleX tween
  27189. [sprite, "scaleX", sprite.scaleX, endScaleX, frames, "smoothstepSquared", yoyo, delayBeforeRepeat],
  27190. //Create the scaleY tween
  27191. [sprite, "scaleY", sprite.scaleY, endScaleY, frames, "smoothstepSquared", yoyo, delayBeforeRepeat]]);
  27192. }
  27193. }, {
  27194. key: "scale",
  27195. value: function scale(sprite) {
  27196. var endScaleX = arguments.length <= 1 || arguments[1] === undefined ? 0.5 : arguments[1];
  27197. var endScaleY = arguments.length <= 2 || arguments[2] === undefined ? 0.5 : arguments[2];
  27198. var frames = arguments.length <= 3 || arguments[3] === undefined ? 60 : arguments[3];
  27199. //Add `scaleX` and `scaleY` properties to Pixi sprites
  27200. this._addScaleProperties(sprite);
  27201. return this.makeTween([
  27202. //Create the scaleX tween
  27203. [sprite, "scaleX", sprite.scaleX, endScaleX, frames, "smoothstep", false],
  27204. //Create the scaleY tween
  27205. [sprite, "scaleY", sprite.scaleY, endScaleY, frames, "smoothstep", false]]);
  27206. }
  27207. }, {
  27208. key: "strobe",
  27209. value: function strobe(sprite) {
  27210. var scaleFactor = arguments.length <= 1 || arguments[1] === undefined ? 1.3 : arguments[1];
  27211. var startMagnitude = arguments.length <= 2 || arguments[2] === undefined ? 10 : arguments[2];
  27212. var endMagnitude = arguments.length <= 3 || arguments[3] === undefined ? 20 : arguments[3];
  27213. var frames = arguments.length <= 4 || arguments[4] === undefined ? 10 : arguments[4];
  27214. var yoyo = arguments.length <= 5 || arguments[5] === undefined ? true : arguments[5];
  27215. var delayBeforeRepeat = arguments.length <= 6 || arguments[6] === undefined ? 0 : arguments[6];
  27216. var bounce = "bounce " + startMagnitude + " " + endMagnitude;
  27217. //Add `scaleX` and `scaleY` properties to Pixi sprites
  27218. this._addScaleProperties(sprite);
  27219. return this.makeTween([
  27220. //Create the scaleX tween
  27221. [sprite, "scaleX", sprite.scaleX, scaleFactor, frames, bounce, yoyo, delayBeforeRepeat],
  27222. //Create the scaleY tween
  27223. [sprite, "scaleY", sprite.scaleY, scaleFactor, frames, bounce, yoyo, delayBeforeRepeat]]);
  27224. }
  27225. }, {
  27226. key: "wobble",
  27227. value: function wobble(sprite) {
  27228. var scaleFactorX = arguments.length <= 1 || arguments[1] === undefined ? 1.2 : arguments[1];
  27229. var scaleFactorY = arguments.length <= 2 || arguments[2] === undefined ? 1.2 : arguments[2];
  27230. var frames = arguments.length <= 3 || arguments[3] === undefined ? 10 : arguments[3];
  27231. var xStartMagnitude = arguments.length <= 4 || arguments[4] === undefined ? 10 : arguments[4];
  27232. var xEndMagnitude = arguments.length <= 5 || arguments[5] === undefined ? 10 : arguments[5];
  27233. var yStartMagnitude = arguments.length <= 6 || arguments[6] === undefined ? -10 : arguments[6];
  27234. var yEndMagnitude = arguments.length <= 7 || arguments[7] === undefined ? -10 : arguments[7];
  27235. var friction = arguments.length <= 8 || arguments[8] === undefined ? 0.98 : arguments[8];
  27236. var _this4 = this;
  27237. var yoyo = arguments.length <= 9 || arguments[9] === undefined ? true : arguments[9];
  27238. var delayBeforeRepeat = arguments.length <= 10 || arguments[10] === undefined ? 0 : arguments[10];
  27239. var bounceX = "bounce " + xStartMagnitude + " " + xEndMagnitude;
  27240. var bounceY = "bounce " + yStartMagnitude + " " + yEndMagnitude;
  27241. //Add `scaleX` and `scaleY` properties to Pixi sprites
  27242. this._addScaleProperties(sprite);
  27243. var o = this.makeTween([
  27244. //Create the scaleX tween
  27245. [sprite, "scaleX", sprite.scaleX, scaleFactorX, frames, bounceX, yoyo, delayBeforeRepeat],
  27246. //Create the scaleY tween
  27247. [sprite, "scaleY", sprite.scaleY, scaleFactorY, frames, bounceY, yoyo, delayBeforeRepeat]]);
  27248. //Add some friction to the `endValue` at the end of each tween
  27249. o.tweens.forEach(function (tween) {
  27250. tween.onComplete = function () {
  27251. //Add friction if the `endValue` is greater than 1
  27252. if (tween.endValue > 1) {
  27253. tween.endValue *= friction;
  27254. //Set the `endValue` to 1 when the effect is finished and
  27255. //remove the tween from the global `tweens` array
  27256. if (tween.endValue <= 1) {
  27257. tween.endValue = 1;
  27258. _this4.removeTween(tween);
  27259. }
  27260. }
  27261. };
  27262. });
  27263. return o;
  27264. }
  27265. //3. Motion path tweens
  27266. }, {
  27267. key: "followCurve",
  27268. value: function followCurve(sprite, pointsArray, totalFrames) {
  27269. var type = arguments.length <= 3 || arguments[3] === undefined ? "smoothstep" : arguments[3];
  27270. var _this5 = this;
  27271. var yoyo = arguments.length <= 4 || arguments[4] === undefined ? false : arguments[4];
  27272. var delayBeforeRepeat = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5];
  27273. //Create the tween object
  27274. var o = {};
  27275. //If the tween is a bounce type (a spline), set the
  27276. //start and end magnitude values
  27277. var typeArray = type.split(" ");
  27278. if (typeArray[0] === "bounce") {
  27279. o.startMagnitude = parseInt(typeArray[1]);
  27280. o.endMagnitude = parseInt(typeArray[2]);
  27281. }
  27282. //Use `tween.start` to make a new tween using the current
  27283. //end point values
  27284. o.start = function (pointsArray) {
  27285. o.playing = true;
  27286. o.totalFrames = totalFrames;
  27287. o.frameCounter = 0;
  27288. //Clone the points array
  27289. o.pointsArray = JSON.parse(JSON.stringify(pointsArray));
  27290. //Add the tween to the `globalTweens` array. The `globalTweens` array is
  27291. //updated on each frame
  27292. _this5.globalTweens.push(o);
  27293. };
  27294. //Call `tween.start` to start the first tween
  27295. o.start(pointsArray);
  27296. //The `update` method will be called on each frame by the game loop.
  27297. //This is what makes the tween move
  27298. o.update = function () {
  27299. var normalizedTime = undefined,
  27300. curvedTime = undefined,
  27301. p = o.pointsArray;
  27302. if (o.playing) {
  27303. //If the elapsed frames are less than the total frames,
  27304. //use the tweening formulas to move the sprite
  27305. if (o.frameCounter < o.totalFrames) {
  27306. //Find the normalized value
  27307. normalizedTime = o.frameCounter / o.totalFrames;
  27308. //Select the correct easing function
  27309. //If it's not a spline, use one of the ordinary tween
  27310. //functions
  27311. if (typeArray[0] !== "bounce") {
  27312. curvedTime = _this5.easingFormulas[type](normalizedTime);
  27313. }
  27314. //If it's a spline, use the `spline` function and apply the
  27315. //2 additional `type` array values as the spline's start and
  27316. //end points
  27317. else {
  27318. //curve = tweenFunction.spline(n, type[1], 0, 1, type[2]);
  27319. curvedTime = _this5.easingFormulas.spline(normalizedTime, o.startMagnitude, 0, 1, o.endMagnitude);
  27320. }
  27321. //Apply the Bezier curve to the sprite's position
  27322. sprite.x = _this5.easingFormulas.cubicBezier(curvedTime, p[0][0], p[1][0], p[2][0], p[3][0]);
  27323. sprite.y = _this5.easingFormulas.cubicBezier(curvedTime, p[0][1], p[1][1], p[2][1], p[3][1]);
  27324. //Add one to the `elapsedFrames`
  27325. o.frameCounter += 1;
  27326. }
  27327. //When the tween has finished playing, run the end tasks
  27328. else {
  27329. //sprite[property] = o.endValue;
  27330. o.end();
  27331. }
  27332. }
  27333. };
  27334. //The `end` method will be called when the tween is finished
  27335. o.end = function () {
  27336. //Set `playing` to `false`
  27337. o.playing = false;
  27338. //Call the tween's `onComplete` method, if it's been
  27339. //assigned
  27340. if (o.onComplete) o.onComplete();
  27341. //Remove the tween from the global `tweens` array
  27342. _this5.globalTweens.splice(_this5.globalTweens.indexOf(o), 1);
  27343. //If the tween's `yoyo` property is `true`, reverse the array and
  27344. //use it to create a new tween
  27345. if (yoyo) {
  27346. _this5.wait(delayBeforeRepeat).then(function () {
  27347. o.pointsArray = o.pointsArray.reverse();
  27348. o.start(o.pointsArray);
  27349. });
  27350. }
  27351. };
  27352. //Pause and play methods
  27353. o.pause = function () {
  27354. o.playing = false;
  27355. };
  27356. o.play = function () {
  27357. o.playing = true;
  27358. };
  27359. //Return the tween object
  27360. return o;
  27361. }
  27362. }, {
  27363. key: "walkPath",
  27364. value: function walkPath(sprite, //The sprite
  27365. originalPathArray) //Delay, in milliseconds, between sections
  27366. {
  27367. var totalFrames = arguments.length <= 2 || arguments[2] === undefined ? 300 : arguments[2];
  27368. var type = arguments.length <= 3 || arguments[3] === undefined ? "smoothstep" : arguments[3];
  27369. var loop = arguments.length <= 4 || arguments[4] === undefined ? false : arguments[4];
  27370. var _this6 = this;
  27371. var yoyo = arguments.length <= 5 || arguments[5] === undefined ? false : arguments[5];
  27372. var delayBetweenSections = arguments.length <= 6 || arguments[6] === undefined ? 0 : arguments[6];
  27373. //Clone the path array so that any possible references to sprite
  27374. //properties are converted into ordinary numbers
  27375. var pathArray = JSON.parse(JSON.stringify(originalPathArray));
  27376. //Figure out the duration, in frames, of each path section by
  27377. //dividing the `totalFrames` by the length of the `pathArray`
  27378. var frames = totalFrames / pathArray.length;
  27379. //Set the current point to 0, which will be the first waypoint
  27380. var currentPoint = 0;
  27381. //The `makePath` function creates a single tween between two points and
  27382. //then schedules the next path to be made after it
  27383. var makePath = function makePath(currentPoint) {
  27384. //Use the `makeTween` function to tween the sprite's
  27385. //x and y position
  27386. var tween = _this6.makeTween([
  27387. //Create the x axis tween between the first x value in the
  27388. //current point and the x value in the following point
  27389. [sprite, "x", pathArray[currentPoint][0], pathArray[currentPoint + 1][0], frames, type],
  27390. //Create the y axis tween in the same way
  27391. [sprite, "y", pathArray[currentPoint][1], pathArray[currentPoint + 1][1], frames, type]]);
  27392. //When the tween is complete, advance the `currentPoint` by one.
  27393. //Add an optional delay between path segments, and then make the
  27394. //next connecting path
  27395. tween.onComplete = function () {
  27396. //Advance to the next point
  27397. currentPoint += 1;
  27398. //If the sprite hasn't reached the end of the
  27399. //path, tween the sprite to the next point
  27400. if (currentPoint < pathArray.length - 1) {
  27401. _this6.wait(delayBetweenSections).then(function () {
  27402. tween = makePath(currentPoint);
  27403. });
  27404. }
  27405. //If we've reached the end of the path, optionally
  27406. //loop and yoyo it
  27407. else {
  27408. //Reverse the path if `loop` is `true`
  27409. if (loop) {
  27410. //Reverse the array if `yoyo` is `true`
  27411. if (yoyo) pathArray.reverse();
  27412. //Optionally wait before restarting
  27413. _this6.wait(delayBetweenSections).then(function () {
  27414. //Reset the `currentPoint` to 0 so that we can
  27415. //restart at the first point
  27416. currentPoint = 0;
  27417. //Set the sprite to the first point
  27418. sprite.x = pathArray[0][0];
  27419. sprite.y = pathArray[0][1];
  27420. //Make the first new path
  27421. tween = makePath(currentPoint);
  27422. //... and so it continues!
  27423. });
  27424. }
  27425. }
  27426. };
  27427. //Return the path tween to the main function
  27428. return tween;
  27429. };
  27430. //Make the first path using the internal `makePath` function (below)
  27431. var tween = makePath(currentPoint);
  27432. //Pass the tween back to the main program
  27433. return tween;
  27434. }
  27435. }, {
  27436. key: "walkCurve",
  27437. value: function walkCurve(sprite, //The sprite
  27438. pathArray) //Delay, in milliseconds, between sections
  27439. {
  27440. var totalFrames = arguments.length <= 2 || arguments[2] === undefined ? 300 : arguments[2];
  27441. var type = arguments.length <= 3 || arguments[3] === undefined ? "smoothstep" : arguments[3];
  27442. var loop = arguments.length <= 4 || arguments[4] === undefined ? false : arguments[4];
  27443. var _this7 = this;
  27444. var yoyo = arguments.length <= 5 || arguments[5] === undefined ? false : arguments[5];
  27445. var delayBeforeContinue = arguments.length <= 6 || arguments[6] === undefined ? 0 : arguments[6];
  27446. //Divide the `totalFrames` into sections for each part of the path
  27447. var frames = totalFrames / pathArray.length;
  27448. //Set the current curve to 0, which will be the first one
  27449. var currentCurve = 0;
  27450. //The `makePath` function
  27451. var makePath = function makePath(currentCurve) {
  27452. //Use the custom `followCurve` function to make
  27453. //a sprite follow a curve
  27454. var tween = _this7.followCurve(sprite, pathArray[currentCurve], frames, type);
  27455. //When the tween is complete, advance the `currentCurve` by one.
  27456. //Add an optional delay between path segments, and then make the
  27457. //next path
  27458. tween.onComplete = function () {
  27459. currentCurve += 1;
  27460. if (currentCurve < pathArray.length) {
  27461. _this7.wait(delayBeforeContinue).then(function () {
  27462. tween = makePath(currentCurve);
  27463. });
  27464. }
  27465. //If we've reached the end of the path, optionally
  27466. //loop and reverse it
  27467. else {
  27468. if (loop) {
  27469. if (yoyo) {
  27470. //Reverse order of the curves in the `pathArray`
  27471. pathArray.reverse();
  27472. //Reverse the order of the points in each curve
  27473. pathArray.forEach(function (curveArray) {
  27474. return curveArray.reverse();
  27475. });
  27476. }
  27477. //After an optional delay, reset the sprite to the
  27478. //beginning of the path and make the next new path
  27479. _this7.wait(delayBeforeContinue).then(function () {
  27480. currentCurve = 0;
  27481. sprite.x = pathArray[0][0];
  27482. sprite.y = pathArray[0][1];
  27483. tween = makePath(currentCurve);
  27484. });
  27485. }
  27486. }
  27487. };
  27488. //Return the path tween to the main function
  27489. return tween;
  27490. };
  27491. //Make the first path
  27492. var tween = makePath(currentCurve);
  27493. //Pass the tween back to the main program
  27494. return tween;
  27495. }
  27496. //4. Utilities
  27497. /*
  27498. The `wait` method lets you set up a timed sequence of events
  27499. wait(1000)
  27500. .then(() => console.log("One"))
  27501. .then(() => wait(1000))
  27502. .then(() => console.log("Two"))
  27503. .then(() => wait(1000))
  27504. .then(() => console.log("Three"))
  27505. */
  27506. }, {
  27507. key: "wait",
  27508. value: function wait() {
  27509. var duration = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];
  27510. return new Promise(function (resolve, reject) {
  27511. setTimeout(resolve, duration);
  27512. });
  27513. }
  27514. //A utility to remove tweens from the game
  27515. }, {
  27516. key: "removeTween",
  27517. value: function removeTween(tweenObject) {
  27518. var _this8 = this;
  27519. //Remove the tween if `tweenObject` doesn't have any nested
  27520. //tween objects
  27521. if (!tweenObject.tweens) {
  27522. tweenObject.pause();
  27523. //array.splice(-1,1) will always remove last elemnt of array, so this
  27524. //extra check prevents that (Thank you, MCumic10! https://github.com/kittykatattack/charm/issues/5)
  27525. if (this.globalTweens.indexOf(tweenObject) != -1) {
  27526. this.globalTweens.splice(this.globalTweens.indexOf(tweenObject), 1);
  27527. }
  27528. //Otherwise, remove the nested tween objects
  27529. } else {
  27530. tweenObject.pause();
  27531. tweenObject.tweens.forEach(function (element) {
  27532. _this8.globalTweens.splice(_this8.globalTweens.indexOf(element), 1);
  27533. });
  27534. }
  27535. }
  27536. }, {
  27537. key: "update",
  27538. value: function update() {
  27539. //Update all the tween objects in the `globalTweens` array
  27540. if (this.globalTweens.length > 0) {
  27541. for (var i = this.globalTweens.length - 1; i >= 0; i--) {
  27542. var tween = this.globalTweens[i];
  27543. if (tween) tween.update();
  27544. }
  27545. }
  27546. }
  27547. }]);
  27548. return Charm;
  27549. })();
  27550. //# sourceMappingURL=charm.js.map"use strict";
  27551. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  27552. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  27553. var Tink = (function () {
  27554. function Tink(PIXI, element) {
  27555. var scale = arguments.length <= 2 || arguments[2] === undefined ? 1 : arguments[2];
  27556. _classCallCheck(this, Tink);
  27557. //Add element and scale properties
  27558. this.element = element;
  27559. this._scale = scale;
  27560. //An array to store all the draggable sprites
  27561. this.draggableSprites = [];
  27562. //An array to store all the pointer objects
  27563. //(there will usually just be one)
  27564. this.pointers = [];
  27565. //An array to store all the buttons and button-like
  27566. //interactive sprites
  27567. this.buttons = [];
  27568. //A local PIXI reference
  27569. this.PIXI = PIXI;
  27570. //Aliases for Pixi objects
  27571. this.TextureCache = this.PIXI.utils.TextureCache;
  27572. //Note: change MovieClip to AnimatedSprite for Pixi v4
  27573. this.AnimatedSprite = this.PIXI.extras.MovieClip;
  27574. this.Texture = this.PIXI.Texture;
  27575. }
  27576. _createClass(Tink, [{
  27577. key: "makeDraggable",
  27578. //`makeDraggable` lets you make a drag-and-drop sprite by pushing it
  27579. //into the `draggableSprites` array
  27580. value: function makeDraggable() {
  27581. var _this = this;
  27582. for (var _len = arguments.length, sprites = Array(_len), _key = 0; _key < _len; _key++) {
  27583. sprites[_key] = arguments[_key];
  27584. }
  27585. //If the first argument isn't an array of sprites...
  27586. if (!(sprites[0] instanceof Array)) {
  27587. sprites.forEach(function (sprite) {
  27588. _this.draggableSprites.push(sprite);
  27589. //If the sprite's `draggable` property hasn't already been defined by
  27590. //another library, like Hexi, define it
  27591. if (sprite.draggable === undefined) {
  27592. sprite.draggable = true;
  27593. sprite._localDraggableAllocation = true;
  27594. }
  27595. });
  27596. }
  27597. //If the first argument is an array of sprites...
  27598. else {
  27599. var spritesArray = sprites[0];
  27600. if (spritesArray.length > 0) {
  27601. for (var i = spritesArray.length - 1; i >= 0; i--) {
  27602. var sprite = spritesArray[i];
  27603. this.draggableSprites.push(sprite);
  27604. //If the sprite's `draggable` property hasn't already been defined by
  27605. //another library, like Hexi, define it
  27606. if (sprite.draggable === undefined) {
  27607. sprite.draggable = true;
  27608. sprite._localDraggableAllocation = true;
  27609. }
  27610. }
  27611. }
  27612. }
  27613. }
  27614. //`makeUndraggable` removes the sprite from the `draggableSprites`
  27615. //array
  27616. }, {
  27617. key: "makeUndraggable",
  27618. value: function makeUndraggable() {
  27619. var _this2 = this;
  27620. for (var _len2 = arguments.length, sprites = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
  27621. sprites[_key2] = arguments[_key2];
  27622. }
  27623. //If the first argument isn't an array of sprites...
  27624. if (!(sprites[0] instanceof Array)) {
  27625. sprites.forEach(function (sprite) {
  27626. _this2.draggableSprites.splice(_this2.draggableSprites.indexOf(sprite), 1);
  27627. if (sprite._localDraggableAllocation === true) sprite.draggable = false;
  27628. });
  27629. }
  27630. //If the first argument is an array of sprites
  27631. else {
  27632. var spritesArray = sprites[0];
  27633. if (spritesArray.length > 0) {
  27634. for (var i = spritesArray.length - 1; i >= 0; i--) {
  27635. var sprite = spritesArray[i];
  27636. this.draggableSprites.splice(this.draggableSprites.indexOf(sprite), 1);
  27637. if (sprite._localDraggableAllocation === true) sprite.draggable = false;
  27638. }
  27639. }
  27640. }
  27641. }
  27642. }, {
  27643. key: "makePointer",
  27644. value: function makePointer() {
  27645. var element = arguments.length <= 0 || arguments[0] === undefined ? this.element : arguments[0];
  27646. var scale = arguments.length <= 1 || arguments[1] === undefined ? this.scale : arguments[1];
  27647. //Get a reference to Tink's global `draggableSprites` array
  27648. var draggableSprites = this.draggableSprites;
  27649. //Get a reference to Tink's `addGlobalPositionProperties` method
  27650. var addGlobalPositionProperties = this.addGlobalPositionProperties;
  27651. //The pointer object will be returned by this function
  27652. var pointer = {
  27653. element: element,
  27654. _scale: scale,
  27655. //Private x and y properties
  27656. _x: 0,
  27657. _y: 0,
  27658. //Width and height
  27659. width: 1,
  27660. height: 1,
  27661. //The public x and y properties are divided by the scale. If the
  27662. //HTML element that the pointer is sensitive to (like the canvas)
  27663. //is scaled up or down, you can change the `scale` value to
  27664. //correct the pointer's position values
  27665. get x() {
  27666. return this._x / this.scale;
  27667. },
  27668. get y() {
  27669. return this._y / this.scale;
  27670. },
  27671. //Add `centerX` and `centerY` getters so that we
  27672. //can use the pointer's coordinates with easing
  27673. //and collision functions
  27674. get centerX() {
  27675. return this.x;
  27676. },
  27677. get centerY() {
  27678. return this.y;
  27679. },
  27680. //`position` returns an object with x and y properties that
  27681. //contain the pointer's position
  27682. get position() {
  27683. return {
  27684. x: this.x,
  27685. y: this.y
  27686. };
  27687. },
  27688. get scale() {
  27689. return this._scale;
  27690. },
  27691. set scale(value) {
  27692. this._scale = value;
  27693. },
  27694. //Add a `cursor` getter/setter to change the pointer's cursor
  27695. //style. Values can be "pointer" (for a hand icon) or "auto" for
  27696. //an ordinary arrow icon.
  27697. get cursor() {
  27698. return this.element.style.cursor;
  27699. },
  27700. set cursor(value) {
  27701. this.element.style.cursor = value;
  27702. },
  27703. //Booleans to track the pointer state
  27704. isDown: false,
  27705. isUp: true,
  27706. tapped: false,
  27707. //Properties to help measure the time between up and down states
  27708. downTime: 0,
  27709. elapsedTime: 0,
  27710. //Optional `press`,`release` and `tap` methods
  27711. press: undefined,
  27712. release: undefined,
  27713. tap: undefined,
  27714. //A `dragSprite` property to help with drag and drop
  27715. dragSprite: null,
  27716. //The drag offsets to help drag sprites
  27717. dragOffsetX: 0,
  27718. dragOffsetY: 0,
  27719. //A property to check whether or not the pointer
  27720. //is visible
  27721. _visible: true,
  27722. get visible() {
  27723. return this._visible;
  27724. },
  27725. set visible(value) {
  27726. if (value === true) {
  27727. this.cursor = "auto";
  27728. } else {
  27729. this.cursor = "none";
  27730. }
  27731. this._visible = value;
  27732. },
  27733. //The pointer's mouse `moveHandler`
  27734. moveHandler: function moveHandler(event) {
  27735. //Get the element that's firing the event
  27736. var element = event.target;
  27737. //Find the pointer’s x and y position (for mouse).
  27738. //Subtract the element's top and left offset from the browser window
  27739. this._x = event.pageX - element.offsetLeft;
  27740. this._y = event.pageY - element.offsetTop;
  27741. //Prevent the event's default behavior
  27742. event.preventDefault();
  27743. },
  27744. //The pointer's `touchmoveHandler`
  27745. touchmoveHandler: function touchmoveHandler(event) {
  27746. var element = event.target;
  27747. //Find the touch point's x and y position
  27748. this._x = event.targetTouches[0].pageX - element.offsetLeft;
  27749. this._y = event.targetTouches[0].pageY - element.offsetTop;
  27750. event.preventDefault();
  27751. },
  27752. //The pointer's `downHandler`
  27753. downHandler: function downHandler(event) {
  27754. //Set the down states
  27755. this.isDown = true;
  27756. this.isUp = false;
  27757. this.tapped = false;
  27758. //Capture the current time
  27759. this.downTime = Date.now();
  27760. //Call the `press` method if it's been assigned
  27761. if (this.press) this.press();
  27762. event.preventDefault();
  27763. },
  27764. //The pointer's `touchstartHandler`
  27765. touchstartHandler: function touchstartHandler(event) {
  27766. var element = event.target;
  27767. //Find the touch point's x and y position
  27768. this._x = event.targetTouches[0].pageX - element.offsetLeft;
  27769. this._y = event.targetTouches[0].pageY - element.offsetTop;
  27770. //Set the down states
  27771. this.isDown = true;
  27772. this.isUp = false;
  27773. this.tapped = false;
  27774. //Capture the current time
  27775. this.downTime = Date.now();
  27776. //Call the `press` method if it's been assigned
  27777. if (this.press) this.press();
  27778. event.preventDefault();
  27779. },
  27780. //The pointer's `upHandler`
  27781. upHandler: function upHandler(event) {
  27782. //Figure out how much time the pointer has been down
  27783. this.elapsedTime = Math.abs(this.downTime - Date.now());
  27784. //If it's less than 200 milliseconds, it must be a tap or click
  27785. if (this.elapsedTime <= 200 && this.tapped === false) {
  27786. this.tapped = true;
  27787. //Call the `tap` method if it's been assigned
  27788. if (this.tap) this.tap();
  27789. }
  27790. this.isUp = true;
  27791. this.isDown = false;
  27792. //Call the `release` method if it's been assigned
  27793. if (this.release) this.release();
  27794. //`event.preventDefault();` needs to be disabled to prevent <input> range sliders
  27795. //from getting trapped in Firefox (and possibly Safari)
  27796. //event.preventDefault();
  27797. },
  27798. //The pointer's `touchendHandler`
  27799. touchendHandler: function touchendHandler(event) {
  27800. //Figure out how much time the pointer has been down
  27801. this.elapsedTime = Math.abs(this.downTime - Date.now());
  27802. //If it's less than 200 milliseconds, it must be a tap or click
  27803. if (this.elapsedTime <= 200 && this.tapped === false) {
  27804. this.tapped = true;
  27805. //Call the `tap` method if it's been assigned
  27806. if (this.tap) this.tap();
  27807. }
  27808. this.isUp = true;
  27809. this.isDown = false;
  27810. //Call the `release` method if it's been assigned
  27811. if (this.release) this.release();
  27812. //event.preventDefault();
  27813. },
  27814. //`hitTestSprite` figures out if the pointer is touching a sprite
  27815. hitTestSprite: function hitTestSprite(sprite) {
  27816. //Add global `gx` and `gy` properties to the sprite if they
  27817. //don't already exist
  27818. addGlobalPositionProperties(sprite);
  27819. //The `hit` variable will become `true` if the pointer is
  27820. //touching the sprite and remain `false` if it isn't
  27821. var hit = false;
  27822. //Find out the sprite's offset from its anchor point
  27823. var xAnchorOffset = undefined,
  27824. yAnchorOffset = undefined;
  27825. if (sprite.anchor !== undefined) {
  27826. xAnchorOffset = sprite.width * sprite.anchor.x;
  27827. yAnchorOffset = sprite.height * sprite.anchor.y;
  27828. } else {
  27829. xAnchorOffset = 0;
  27830. yAnchorOffset = 0;
  27831. }
  27832. //Is the sprite rectangular?
  27833. if (!sprite.circular) {
  27834. //Get the position of the sprite's edges using global
  27835. //coordinates
  27836. var left = sprite.gx - xAnchorOffset,
  27837. right = sprite.gx + sprite.width - xAnchorOffset,
  27838. top = sprite.gy - yAnchorOffset,
  27839. bottom = sprite.gy + sprite.height - yAnchorOffset;
  27840. //Find out if the pointer is intersecting the rectangle.
  27841. //`hit` will become `true` if the pointer is inside the
  27842. //sprite's area
  27843. hit = this.x > left && this.x < right && this.y > top && this.y < bottom;
  27844. }
  27845. //Is the sprite circular?
  27846. else {
  27847. //Find the distance between the pointer and the
  27848. //center of the circle
  27849. var vx = this.x - (sprite.gx + sprite.width / 2 - xAnchorOffset),
  27850. vy = this.y - (sprite.gy + sprite.width / 2 - yAnchorOffset),
  27851. distance = Math.sqrt(vx * vx + vy * vy);
  27852. //The pointer is intersecting the circle if the
  27853. //distance is less than the circle's radius
  27854. hit = distance < sprite.width / 2;
  27855. }
  27856. //Check the value of `hit`
  27857. return hit;
  27858. }
  27859. };
  27860. //Bind the events to the handlers
  27861. //Mouse events
  27862. element.addEventListener("mousemove", pointer.moveHandler.bind(pointer), false);
  27863. element.addEventListener("mousedown", pointer.downHandler.bind(pointer), false);
  27864. //Add the `mouseup` event to the `window` to
  27865. //catch a mouse button release outside of the canvas area
  27866. window.addEventListener("mouseup", pointer.upHandler.bind(pointer), false);
  27867. //Touch events
  27868. element.addEventListener("touchmove", pointer.touchmoveHandler.bind(pointer), false);
  27869. element.addEventListener("touchstart", pointer.touchstartHandler.bind(pointer), false);
  27870. //Add the `touchend` event to the `window` object to
  27871. //catch a mouse button release outside of the canvas area
  27872. window.addEventListener("touchend", pointer.touchendHandler.bind(pointer), false);
  27873. //Disable the default pan and zoom actions on the `canvas`
  27874. element.style.touchAction = "none";
  27875. //Add the pointer to Tink's global `pointers` array
  27876. this.pointers.push(pointer);
  27877. //Return the pointer
  27878. return pointer;
  27879. }
  27880. //Many of Tink's objects, like pointers, use collision
  27881. //detection using the sprites' global x and y positions. To make
  27882. //this easier, new `gx` and `gy` properties are added to sprites
  27883. //that reference Pixi sprites' `getGlobalPosition()` values.
  27884. }, {
  27885. key: "addGlobalPositionProperties",
  27886. value: function addGlobalPositionProperties(sprite) {
  27887. if (sprite.gx === undefined) {
  27888. Object.defineProperty(sprite, "gx", {
  27889. get: function get() {
  27890. return sprite.getGlobalPosition().x;
  27891. }
  27892. });
  27893. }
  27894. if (sprite.gy === undefined) {
  27895. Object.defineProperty(sprite, "gy", {
  27896. get: function get() {
  27897. return sprite.getGlobalPosition().y;
  27898. }
  27899. });
  27900. }
  27901. }
  27902. //A method that implments drag-and-drop functionality
  27903. //for each pointer
  27904. }, {
  27905. key: "updateDragAndDrop",
  27906. value: function updateDragAndDrop(draggableSprites) {
  27907. //Create a pointer if one doesn't already exist
  27908. if (this.pointers.length === 0) {
  27909. this.makePointer(this.element, this.scale);
  27910. }
  27911. //Loop through all the pointers in Tink's global `pointers` array
  27912. //(there will usually just be one, but you never know)
  27913. this.pointers.forEach(function (pointer) {
  27914. //Check whether the pointer is pressed down
  27915. if (pointer.isDown) {
  27916. //You need to capture the co-ordinates at which the pointer was
  27917. //pressed down and find out if it's touching a sprite
  27918. //Only run pointer.code if the pointer isn't already dragging
  27919. //sprite
  27920. if (pointer.dragSprite === null) {
  27921. //Loop through the `draggableSprites` in reverse to start searching at the bottom of the stack
  27922. for (var i = draggableSprites.length - 1; i > -1; i--) {
  27923. //Get a reference to the current sprite
  27924. var sprite = draggableSprites[i];
  27925. //Check for a collision with the pointer using `hitTestSprite`
  27926. if (pointer.hitTestSprite(sprite) && sprite.draggable) {
  27927. //Calculate the difference between the pointer's
  27928. //position and the sprite's position
  27929. pointer.dragOffsetX = pointer.x - sprite.gx;
  27930. pointer.dragOffsetY = pointer.y - sprite.gy;
  27931. //Set the sprite as the pointer's `dragSprite` property
  27932. pointer.dragSprite = sprite;
  27933. //The next two lines re-order the `sprites` array so that the
  27934. //selected sprite is displayed above all the others.
  27935. //First, splice the sprite out of its current position in
  27936. //its parent's `children` array
  27937. var children = sprite.parent.children;
  27938. children.splice(children.indexOf(sprite), 1);
  27939. //Next, push the `dragSprite` to the end of its `children` array so that it's
  27940. //displayed last, above all the other sprites
  27941. children.push(sprite);
  27942. //Reorganize the `draggableSpites` array in the same way
  27943. draggableSprites.splice(draggableSprites.indexOf(sprite), 1);
  27944. draggableSprites.push(sprite);
  27945. //Break the loop, because we only need to drag the topmost sprite
  27946. break;
  27947. }
  27948. }
  27949. }
  27950. //If the pointer is down and it has a `dragSprite`, make the sprite follow the pointer's
  27951. //position, with the calculated offset
  27952. else {
  27953. pointer.dragSprite.x = pointer.x - pointer.dragOffsetX;
  27954. pointer.dragSprite.y = pointer.y - pointer.dragOffsetY;
  27955. }
  27956. }
  27957. //If the pointer is up, drop the `dragSprite` by setting it to `null`
  27958. if (pointer.isUp) {
  27959. pointer.dragSprite = null;
  27960. }
  27961. //Change the mouse arrow pointer to a hand if it's over a
  27962. //draggable sprite
  27963. draggableSprites.some(function (sprite) {
  27964. if (pointer.hitTestSprite(sprite) && sprite.draggable) {
  27965. if (pointer.visible) pointer.cursor = "pointer";
  27966. return true;
  27967. } else {
  27968. if (pointer.visible) pointer.cursor = "auto";
  27969. return false;
  27970. }
  27971. });
  27972. });
  27973. }
  27974. }, {
  27975. key: "makeInteractive",
  27976. value: function makeInteractive(o) {
  27977. //The `press`,`release`, `over`, `out` and `tap` methods. They're `undefined`
  27978. //for now, but they can be defined in the game program
  27979. o.press = o.press || undefined;
  27980. o.release = o.release || undefined;
  27981. o.over = o.over || undefined;
  27982. o.out = o.out || undefined;
  27983. o.tap = o.tap || undefined;
  27984. //The `state` property tells you the button's
  27985. //current state. Set its initial state to "up"
  27986. o.state = "up";
  27987. //The `action` property tells you whether its being pressed or
  27988. //released
  27989. o.action = "";
  27990. //The `pressed` and `hoverOver` Booleans are mainly for internal
  27991. //use in this code to help figure out the correct state.
  27992. //`pressed` is a Boolean that helps track whether or not
  27993. //the sprite has been pressed down
  27994. o.pressed = false;
  27995. //`hoverOver` is a Boolean which checks whether the pointer
  27996. //has hovered over the sprite
  27997. o.hoverOver = false;
  27998. //tinkType is a string that will be set to "button" if the
  27999. //user creates an object using the `button` function
  28000. o.tinkType = "";
  28001. //Set `enabled` to true to allow for interactivity
  28002. //Set `enabled` to false to disable interactivity
  28003. o.enabled = true;
  28004. //Add the sprite to the global `buttons` array so that it can
  28005. //be updated each frame in the `updateButtons method
  28006. this.buttons.push(o);
  28007. }
  28008. //The `updateButtons` method will be called each frame
  28009. //inside the game loop. It updates all the button-like sprites
  28010. }, {
  28011. key: "updateButtons",
  28012. value: function updateButtons() {
  28013. var _this3 = this;
  28014. //Create a pointer if one doesn't already exist
  28015. if (this.pointers.length === 0) {
  28016. this.makePointer(this.element, this.scale);
  28017. }
  28018. //Loop through all of Tink's pointers (there will usually
  28019. //just be one)
  28020. this.pointers.forEach(function (pointer) {
  28021. pointer.shouldBeHand = false;
  28022. //Loop through all the button-like sprites that were created
  28023. //using the `makeInteractive` method
  28024. _this3.buttons.forEach(function (o) {
  28025. //Only do this if the interactive object is enabled
  28026. if (o.enabled) {
  28027. //Figure out if the pointer is touching the sprite
  28028. var hit = pointer.hitTestSprite(o);
  28029. //1. Figure out the current state
  28030. if (pointer.isUp) {
  28031. //Up state
  28032. o.state = "up";
  28033. //Show the first image state frame, if this is a `Button` sprite
  28034. if (o.tinkType === "button") o.gotoAndStop(0);
  28035. }
  28036. //If the pointer is touching the sprite, figure out
  28037. //if the over or down state should be displayed
  28038. if (hit) {
  28039. //Over state
  28040. o.state = "over";
  28041. //Show the second image state frame if this sprite has
  28042. //3 frames and it's a `Button` sprite
  28043. if (o.totalFrames && o.totalFrames === 3 && o.tinkType === "button") {
  28044. o.gotoAndStop(1);
  28045. }
  28046. //Down state
  28047. if (pointer.isDown) {
  28048. o.state = "down";
  28049. //Show the third frame if this sprite is a `Button` sprite and it
  28050. //has only three frames, or show the second frame if it
  28051. //only has two frames
  28052. if (o.tinkType === "button") {
  28053. if (o.totalFrames === 3) {
  28054. o.gotoAndStop(2);
  28055. } else {
  28056. o.gotoAndStop(1);
  28057. }
  28058. }
  28059. }
  28060. //Flag this pointer to be changed to a hand
  28061. pointer.shouldBeHand = true;
  28062. //if (pointer.visible) pointer.cursor = "pointer";
  28063. // } else {
  28064. // //Turn the pointer to an ordinary arrow icon if the
  28065. // //pointer isn't touching a sprite
  28066. // if (pointer.visible) pointer.cursor = "auto";
  28067. //Change the pointer icon to a hand
  28068. if (pointer.visible) pointer.cursor = "pointer";
  28069. } else {
  28070. //Turn the pointer to an ordinary arrow icon if the
  28071. //pointer isn't touching a sprite
  28072. if (pointer.visible) pointer.cursor = "auto";
  28073. }
  28074. //Perform the correct interactive action
  28075. //a. Run the `press` method if the sprite state is "down" and
  28076. //the sprite hasn't already been pressed
  28077. if (o.state === "down") {
  28078. if (!o.pressed) {
  28079. if (o.press) o.press();
  28080. o.pressed = true;
  28081. o.action = "pressed";
  28082. }
  28083. }
  28084. //b. Run the `release` method if the sprite state is "over" and
  28085. //the sprite has been pressed
  28086. if (o.state === "over") {
  28087. if (o.pressed) {
  28088. if (o.release) o.release();
  28089. o.pressed = false;
  28090. o.action = "released";
  28091. //If the pointer was tapped and the user assigned a `tap`
  28092. //method, call the `tap` method
  28093. if (pointer.tapped && o.tap) o.tap();
  28094. }
  28095. //Run the `over` method if it has been assigned
  28096. if (!o.hoverOver) {
  28097. if (o.over) o.over();
  28098. o.hoverOver = true;
  28099. }
  28100. }
  28101. //c. Check whether the pointer has been released outside
  28102. //the sprite's area. If the button state is "up" and it's
  28103. //already been pressed, then run the `release` method.
  28104. if (o.state === "up") {
  28105. if (o.pressed) {
  28106. if (o.release) o.release();
  28107. o.pressed = false;
  28108. o.action = "released";
  28109. }
  28110. //Run the `out` method if it has been assigned
  28111. if (o.hoverOver) {
  28112. if (o.out) o.out();
  28113. o.hoverOver = false;
  28114. }
  28115. }
  28116. }
  28117. });
  28118. if (pointer.shouldBeHand) {
  28119. pointer.cursor = "pointer";
  28120. } else {
  28121. pointer.cursor = "auto";
  28122. }
  28123. });
  28124. }
  28125. //A function that creates a sprite with 3 frames that
  28126. //represent the button states: up, over and down
  28127. }, {
  28128. key: "button",
  28129. value: function button(source) {
  28130. var x = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
  28131. var y = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2];
  28132. //The sprite object that will be returned
  28133. var o = undefined;
  28134. //Is it an array of frame ids or textures?
  28135. if (typeof source[0] === "string") {
  28136. //They're strings, but are they pre-existing texture or
  28137. //paths to image files?
  28138. //Check to see if the first element matches a texture in the
  28139. //cache
  28140. if (this.TextureCache[source[0]]) {
  28141. //It does, so it's an array of frame ids
  28142. o = this.AnimatedSprite.fromFrames(source);
  28143. } else {
  28144. //It's not already in the cache, so let's load it
  28145. o = this.AnimatedSprite.fromImages(source);
  28146. }
  28147. }
  28148. //If the `source` isn't an array of strings, check whether
  28149. //it's an array of textures
  28150. else if (source[0] instanceof this.Texture) {
  28151. //Yes, it's an array of textures.
  28152. //Use them to make a AnimatedSprite o
  28153. o = new this.AnimatedSprite(source);
  28154. }
  28155. //Add interactive properties to the button
  28156. this.makeInteractive(o);
  28157. //Set the `tinkType` to "button"
  28158. o.tinkType = "button";
  28159. //Position the button
  28160. o.x = x;
  28161. o.y = y;
  28162. //Return the new button sprite
  28163. return o;
  28164. }
  28165. //Run the `udpate` function in your game loop
  28166. //to update all of Tink's interactive objects
  28167. }, {
  28168. key: "update",
  28169. value: function update() {
  28170. //Update the drag and drop system
  28171. if (this.draggableSprites.length !== 0) this.updateDragAndDrop(this.draggableSprites);
  28172. //Update the buttons and button-like interactive sprites
  28173. if (this.buttons.length !== 0) this.updateButtons();
  28174. }
  28175. /*
  28176. `keyboard` is a method that listens for and captures keyboard events. It's really
  28177. just a convenient wrapper function for HTML `keyup` and `keydown` events so that you can keep your application code clutter-free and easier to write and read.
  28178. Here's how to use the `keyboard` method. Create a new keyboard object like this:
  28179. ```js
  28180. let keyObject = keyboard(asciiKeyCodeNumber);
  28181. ```
  28182. It's one argument is the ASCII key code number of the keyboard key
  28183. that you want to listen for. [Here's a list of ASCII key codes you can
  28184. use](http://www.asciitable.com).
  28185. Then assign `press` and `release` methods to the keyboard object like this:
  28186. ```js
  28187. keyObject.press = () => {
  28188. //key object pressed
  28189. };
  28190. keyObject.release = () => {
  28191. //key object released
  28192. };
  28193. ```
  28194. Keyboard objects also have `isDown` and `isUp` Boolean properties that you can use to check the state of each key.
  28195. */
  28196. }, {
  28197. key: "keyboard",
  28198. value: function keyboard(keyCode) {
  28199. var key = {};
  28200. key.code = keyCode;
  28201. key.isDown = false;
  28202. key.isUp = true;
  28203. key.press = undefined;
  28204. key.release = undefined;
  28205. //The `downHandler`
  28206. key.downHandler = function (event) {
  28207. if (event.keyCode === key.code) {
  28208. if (key.isUp && key.press) key.press();
  28209. key.isDown = true;
  28210. key.isUp = false;
  28211. }
  28212. event.preventDefault();
  28213. };
  28214. //The `upHandler`
  28215. key.upHandler = function (event) {
  28216. if (event.keyCode === key.code) {
  28217. if (key.isDown && key.release) key.release();
  28218. key.isDown = false;
  28219. key.isUp = true;
  28220. }
  28221. event.preventDefault();
  28222. };
  28223. //Attach event listeners
  28224. window.addEventListener("keydown", key.downHandler.bind(key), false);
  28225. window.addEventListener("keyup", key.upHandler.bind(key), false);
  28226. //Return the key object
  28227. return key;
  28228. }
  28229. //`arrowControl` is a convenience method for updating a sprite's velocity
  28230. //for 4-way movement using the arrow directional keys. Supply it
  28231. //with the sprite you want to control and the speed per frame, in
  28232. //pixels, that you want to update the sprite's velocity
  28233. }, {
  28234. key: "arrowControl",
  28235. value: function arrowControl(sprite, speed) {
  28236. if (speed === undefined) {
  28237. throw new Error("Please supply the arrowControl method with the speed at which you want the sprite to move");
  28238. }
  28239. var upArrow = this.keyboard(38),
  28240. rightArrow = this.keyboard(39),
  28241. downArrow = this.keyboard(40),
  28242. leftArrow = this.keyboard(37);
  28243. //Assign key `press` methods
  28244. leftArrow.press = function () {
  28245. //Change the sprite's velocity when the key is pressed
  28246. sprite.vx = -speed;
  28247. sprite.vy = 0;
  28248. };
  28249. leftArrow.release = function () {
  28250. //If the left arrow has been released, and the right arrow isn't down,
  28251. //and the sprite isn't moving vertically:
  28252. //Stop the sprite
  28253. if (!rightArrow.isDown && sprite.vy === 0) {
  28254. sprite.vx = 0;
  28255. }
  28256. };
  28257. upArrow.press = function () {
  28258. sprite.vy = -speed;
  28259. sprite.vx = 0;
  28260. };
  28261. upArrow.release = function () {
  28262. if (!downArrow.isDown && sprite.vx === 0) {
  28263. sprite.vy = 0;
  28264. }
  28265. };
  28266. rightArrow.press = function () {
  28267. sprite.vx = speed;
  28268. sprite.vy = 0;
  28269. };
  28270. rightArrow.release = function () {
  28271. if (!leftArrow.isDown && sprite.vy === 0) {
  28272. sprite.vx = 0;
  28273. }
  28274. };
  28275. downArrow.press = function () {
  28276. sprite.vy = speed;
  28277. sprite.vx = 0;
  28278. };
  28279. downArrow.release = function () {
  28280. if (!upArrow.isDown && sprite.vx === 0) {
  28281. sprite.vy = 0;
  28282. }
  28283. };
  28284. }
  28285. }, {
  28286. key: "scale",
  28287. get: function get() {
  28288. return this._scale;
  28289. },
  28290. set: function set(value) {
  28291. this._scale = value;
  28292. //Update scale values for all pointers
  28293. this.pointers.forEach(function (pointer) {
  28294. return pointer.scale = value;
  28295. });
  28296. }
  28297. }]);
  28298. return Tink;
  28299. })();
  28300. //# sourceMappingURL=tink.js.map"use strict";
  28301. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  28302. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  28303. var Dust = (function () {
  28304. function Dust() {
  28305. var renderingEngine = arguments.length <= 0 || arguments[0] === undefined ? PIXI : arguments[0];
  28306. _classCallCheck(this, Dust);
  28307. if (renderingEngine === undefined) throw new Error("Please assign a rendering engine in the constructor before using pixiDust.js");
  28308. //Find out which rendering engine is being used (the default is Pixi)
  28309. this.renderer = "";
  28310. //If the `renderingEngine` is Pixi, set up Pixi object aliases
  28311. if (renderingEngine.ParticleContainer) {
  28312. this.Container = renderingEngine.Container;
  28313. this.renderer = "pixi";
  28314. }
  28315. //The `particles` array stores all the particles you make
  28316. this.globalParticles = [];
  28317. }
  28318. //Random number functions
  28319. _createClass(Dust, [{
  28320. key: "randomFloat",
  28321. value: function randomFloat(min, max) {
  28322. return min + Math.random() * (max - min);
  28323. }
  28324. }, {
  28325. key: "randomInt",
  28326. value: function randomInt(min, max) {
  28327. return Math.floor(Math.random() * (max - min + 1)) + min;
  28328. }
  28329. //Use the create function to create new particle effects
  28330. }, {
  28331. key: "create",
  28332. value: function create() {
  28333. var x = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];
  28334. var y = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
  28335. var spriteFunction = arguments.length <= 2 || arguments[2] === undefined ? function () {
  28336. return console.log("Sprite creation function");
  28337. } : arguments[2];
  28338. var container = arguments.length <= 3 || arguments[3] === undefined ? function () {
  28339. return new _this.Container();
  28340. } : arguments[3];
  28341. var numberOfParticles = arguments.length <= 4 || arguments[4] === undefined ? 20 : arguments[4];
  28342. var gravity = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5];
  28343. var randomSpacing = arguments.length <= 6 || arguments[6] === undefined ? true : arguments[6];
  28344. var minAngle = arguments.length <= 7 || arguments[7] === undefined ? 0 : arguments[7];
  28345. var maxAngle = arguments.length <= 8 || arguments[8] === undefined ? 6.28 : arguments[8];
  28346. var minSize = arguments.length <= 9 || arguments[9] === undefined ? 4 : arguments[9];
  28347. var maxSize = arguments.length <= 10 || arguments[10] === undefined ? 16 : arguments[10];
  28348. var minSpeed = arguments.length <= 11 || arguments[11] === undefined ? 0.3 : arguments[11];
  28349. var maxSpeed = arguments.length <= 12 || arguments[12] === undefined ? 3 : arguments[12];
  28350. var minScaleSpeed = arguments.length <= 13 || arguments[13] === undefined ? 0.01 : arguments[13];
  28351. var maxScaleSpeed = arguments.length <= 14 || arguments[14] === undefined ? 0.05 : arguments[14];
  28352. var minAlphaSpeed = arguments.length <= 15 || arguments[15] === undefined ? 0.02 : arguments[15];
  28353. var maxAlphaSpeed = arguments.length <= 16 || arguments[16] === undefined ? 0.02 : arguments[16];
  28354. var _this = this;
  28355. var minRotationSpeed = arguments.length <= 17 || arguments[17] === undefined ? 0.01 : arguments[17];
  28356. var maxRotationSpeed = arguments.length <= 18 || arguments[18] === undefined ? 0.03 : arguments[18];
  28357. //An array to store the curent batch of particles
  28358. var particles = [];
  28359. //Add the current `particles` array to the `globalParticles` array
  28360. this.globalParticles.push(particles);
  28361. //An array to store the angles
  28362. var angles = [];
  28363. //A variable to store the current particle's angle
  28364. var angle = undefined;
  28365. //Figure out by how many radians each particle should be separated
  28366. var spacing = (maxAngle - minAngle) / (numberOfParticles - 1);
  28367. //Create an angle value for each particle and push that //value into the `angles` array
  28368. for (var i = 0; i < numberOfParticles; i++) {
  28369. //If `randomSpacing` is `true`, give the particle any angle
  28370. //value between `minAngle` and `maxAngle`
  28371. if (randomSpacing) {
  28372. angle = this.randomFloat(minAngle, maxAngle);
  28373. angles.push(angle);
  28374. }
  28375. //If `randomSpacing` is `false`, space each particle evenly,
  28376. //starting with the `minAngle` and ending with the `maxAngle`
  28377. else {
  28378. if (angle === undefined) angle = minAngle;
  28379. angles.push(angle);
  28380. angle += spacing;
  28381. }
  28382. }
  28383. //A function to make particles
  28384. var makeParticle = function makeParticle(angle) {
  28385. //Create the particle using the supplied sprite function
  28386. var particle = spriteFunction();
  28387. //Display a random frame if the particle has more than 1 frame
  28388. if (particle.totalFrames > 0) {
  28389. particle.gotoAndStop(_this.randomInt(0, particle.totalFrames - 1));
  28390. }
  28391. //Set a random width and height
  28392. var size = _this.randomInt(minSize, maxSize);
  28393. particle.width = size;
  28394. particle.height = size;
  28395. //Set the particle's `anchor` to its center
  28396. particle.anchor.set(0.5, 0.5);
  28397. //Set the x and y position
  28398. particle.x = x;
  28399. particle.y = y;
  28400. //Set a random speed to change the scale, alpha and rotation
  28401. particle.scaleSpeed = _this.randomFloat(minScaleSpeed, maxScaleSpeed);
  28402. particle.alphaSpeed = _this.randomFloat(minAlphaSpeed, maxAlphaSpeed);
  28403. particle.rotationSpeed = _this.randomFloat(minRotationSpeed, maxRotationSpeed);
  28404. //Set a random velocity at which the particle should move
  28405. var speed = _this.randomFloat(minSpeed, maxSpeed);
  28406. particle.vx = speed * Math.cos(angle);
  28407. particle.vy = speed * Math.sin(angle);
  28408. //Push the particle into the `particles` array.
  28409. //The `particles` array needs to be updated by the game loop each frame particles.push(particle);
  28410. particles.push(particle);
  28411. //Add the particle to its parent container
  28412. container.addChild(particle);
  28413. //The particle's `updateParticle` method is called on each frame of the
  28414. //game loop
  28415. particle.updateParticle = function () {
  28416. //Add gravity
  28417. particle.vy += gravity;
  28418. //Move the particle
  28419. particle.x += particle.vx;
  28420. particle.y += particle.vy;
  28421. //Change the particle's `scale`
  28422. if (particle.scale.x - particle.scaleSpeed > 0) {
  28423. particle.scale.x -= particle.scaleSpeed;
  28424. }
  28425. if (particle.scale.y - particle.scaleSpeed > 0) {
  28426. particle.scale.y -= particle.scaleSpeed;
  28427. }
  28428. //Change the particle's rotation
  28429. particle.rotation += particle.rotationSpeed;
  28430. //Change the particle's `alpha`
  28431. particle.alpha -= particle.alphaSpeed;
  28432. //Remove the particle if its `alpha` reaches zero
  28433. if (particle.alpha <= 0) {
  28434. container.removeChild(particle);
  28435. particles.splice(particles.indexOf(particle), 1);
  28436. }
  28437. };
  28438. };
  28439. //Make a particle for each angle
  28440. angles.forEach(function (angle) {
  28441. return makeParticle(angle);
  28442. });
  28443. //Return the `particles` array back to the main program
  28444. return particles;
  28445. }
  28446. //A particle emitter
  28447. }, {
  28448. key: "emitter",
  28449. value: function emitter(interval, particleFunction) {
  28450. var emitterObject = {},
  28451. timerInterval = undefined;
  28452. emitterObject.playing = false;
  28453. function play() {
  28454. if (!emitterObject.playing) {
  28455. particleFunction();
  28456. timerInterval = setInterval(emitParticle.bind(this), interval);
  28457. emitterObject.playing = true;
  28458. }
  28459. }
  28460. function stop() {
  28461. if (emitterObject.playing) {
  28462. clearInterval(timerInterval);
  28463. emitterObject.playing = false;
  28464. }
  28465. }
  28466. function emitParticle() {
  28467. particleFunction();
  28468. }
  28469. emitterObject.play = play;
  28470. emitterObject.stop = stop;
  28471. return emitterObject;
  28472. }
  28473. //A function to update the particles in the game loop
  28474. }, {
  28475. key: "update",
  28476. value: function update() {
  28477. //Check so see if the `globalParticles` array contains any
  28478. //sub-arrays
  28479. if (this.globalParticles.length > 0) {
  28480. //If it does, Loop through the particle arrays in reverse
  28481. for (var i = this.globalParticles.length - 1; i >= 0; i--) {
  28482. //Get the current particle sub-array
  28483. var particles = this.globalParticles[i];
  28484. //Loop through the `particles` sub-array and update the
  28485. //all the particle sprites that it contains
  28486. if (particles.length > 0) {
  28487. for (var j = particles.length - 1; j >= 0; j--) {
  28488. var particle = particles[j];
  28489. particle.updateParticle();
  28490. }
  28491. }
  28492. //Remove the particle array from the `globalParticles` array if doesn't
  28493. //contain any more sprites
  28494. else {
  28495. this.globalParticles.splice(this.globalParticles.indexOf(particles), 1);
  28496. }
  28497. }
  28498. }
  28499. }
  28500. }]);
  28501. return Dust;
  28502. })();
  28503. //# sourceMappingURL=dust.js.map"use strict";
  28504. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  28505. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  28506. var SpriteUtilities = (function () {
  28507. function SpriteUtilities() {
  28508. var renderingEngine = arguments.length <= 0 || arguments[0] === undefined ? PIXI : arguments[0];
  28509. _classCallCheck(this, SpriteUtilities);
  28510. if (renderingEngine === undefined) throw new Error("Please supply a reference to PIXI in the SpriteUtilities constructor before using spriteUtilities.js");
  28511. //Find out which rendering engine is being used (the default is Pixi)
  28512. this.renderer = "";
  28513. //If the `renderingEngine` is Pixi, set up Pixi object aliases
  28514. if (renderingEngine.ParticleContainer && renderingEngine.Sprite) {
  28515. this.renderer = "pixi";
  28516. this.Container = renderingEngine.Container;
  28517. this.ParticleContainer = renderingEngine.ParticleContainer;
  28518. this.TextureCache = renderingEngine.utils.TextureCache;
  28519. this.Texture = renderingEngine.Texture;
  28520. this.Rectangle = renderingEngine.Rectangle;
  28521. this.MovieClip = renderingEngine.extras.MovieClip;
  28522. this.BitmapText = renderingEngine.extras.BitmapText;
  28523. this.Sprite = renderingEngine.Sprite;
  28524. this.TilingSprite = renderingEngine.extras.TilingSprite;
  28525. this.Graphics = renderingEngine.Graphics;
  28526. this.Text = renderingEngine.Text;
  28527. //An array to store all the shaking sprites
  28528. this.shakingSprites = [];
  28529. }
  28530. }
  28531. _createClass(SpriteUtilities, [{
  28532. key: "update",
  28533. value: function update() {
  28534. if (this.shakingSprites.length > 0) {
  28535. for (var i = this.shakingSprites.length - 1; i >= 0; i--) {
  28536. var shakingSprite = this.shakingSprites[i];
  28537. if (shakingSprite.updateShake) shakingSprite.updateShake();
  28538. }
  28539. }
  28540. }
  28541. }, {
  28542. key: "sprite",
  28543. value: function sprite(source) {
  28544. var x = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
  28545. var y = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2];
  28546. var tiling = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
  28547. var width = arguments[4];
  28548. var height = arguments[5];
  28549. var o = undefined,
  28550. texture = undefined;
  28551. //Create a sprite if the `source` is a string
  28552. if (typeof source === "string") {
  28553. //Access the texture in the cache if it's there
  28554. if (this.TextureCache[source]) {
  28555. texture = this.TextureCache[source];
  28556. }
  28557. //If it's not is the cache, load it from the source file
  28558. else {
  28559. texture = this.Texture.fromImage(source);
  28560. }
  28561. //If the texture was created, make the o
  28562. if (texture) {
  28563. //If `tiling` is `false`, make a regular `Sprite`
  28564. if (!tiling) {
  28565. o = new this.Sprite(texture);
  28566. }
  28567. //If `tiling` is `true` make a `TilingSprite`
  28568. else {
  28569. o = new this.TilingSprite(texture, width, height);
  28570. }
  28571. }
  28572. //But if the source still can't be found, alert the user
  28573. else {
  28574. throw new Error(source + " cannot be found");
  28575. }
  28576. }
  28577. //Create a o if the `source` is a texture
  28578. else if (source instanceof this.Texture) {
  28579. if (!tiling) {
  28580. o = new this.Sprite(source);
  28581. } else {
  28582. o = new this.TilingSprite(source, width, height);
  28583. }
  28584. }
  28585. //Create a `MovieClip` o if the `source` is an array
  28586. else if (source instanceof Array) {
  28587. //Is it an array of frame ids or textures?
  28588. if (typeof source[0] === "string") {
  28589. //They're strings, but are they pre-existing texture or
  28590. //paths to image files?
  28591. //Check to see if the first element matches a texture in the
  28592. //cache
  28593. if (this.TextureCache[source[0]]) {
  28594. //It does, so it's an array of frame ids
  28595. o = this.MovieClip.fromFrames(source);
  28596. } else {
  28597. //It's not already in the cache, so let's load it
  28598. o = this.MovieClip.fromImages(source);
  28599. }
  28600. }
  28601. //If the `source` isn't an array of strings, check whether
  28602. //it's an array of textures
  28603. else if (source[0] instanceof this.Texture) {
  28604. //Yes, it's an array of textures.
  28605. //Use them to make a MovieClip o
  28606. o = new this.MovieClip(source);
  28607. }
  28608. }
  28609. //If the sprite was successfully created, intialize it
  28610. if (o) {
  28611. //Position the sprite
  28612. o.x = x;
  28613. o.y = y;
  28614. //Set optional width and height
  28615. if (width) o.width = width;
  28616. if (height) o.height = height;
  28617. //If the sprite is a MovieClip, add a state player so that
  28618. //it's easier to control
  28619. if (o instanceof this.MovieClip) this.addStatePlayer(o);
  28620. //Assign the sprite
  28621. return o;
  28622. }
  28623. }
  28624. }, {
  28625. key: "addStatePlayer",
  28626. value: function addStatePlayer(sprite) {
  28627. var frameCounter = 0,
  28628. numberOfFrames = 0,
  28629. startFrame = 0,
  28630. endFrame = 0,
  28631. timerInterval = undefined;
  28632. //The `show` function (to display static states)
  28633. function show(frameNumber) {
  28634. //Reset any possible previous animations
  28635. reset();
  28636. //Find the new state on the sprite
  28637. sprite.gotoAndStop(frameNumber);
  28638. }
  28639. //The `stop` function stops the animation at the current frame
  28640. function stopAnimation() {
  28641. reset();
  28642. sprite.gotoAndStop(sprite.currentFrame);
  28643. }
  28644. //The `playSequence` function, to play a sequence of frames
  28645. function playAnimation(sequenceArray) {
  28646. //Reset any possible previous animations
  28647. reset();
  28648. //Figure out how many frames there are in the range
  28649. if (!sequenceArray) {
  28650. startFrame = 0;
  28651. endFrame = sprite.totalFrames - 1;
  28652. } else {
  28653. startFrame = sequenceArray[0];
  28654. endFrame = sequenceArray[1];
  28655. }
  28656. //Calculate the number of frames
  28657. numberOfFrames = endFrame - startFrame;
  28658. //Compensate for two edge cases:
  28659. //1. If the `startFrame` happens to be `0`
  28660. /*
  28661. if (startFrame === 0) {
  28662. numberOfFrames += 1;
  28663. frameCounter += 1;
  28664. }
  28665. */
  28666. //2. If only a two-frame sequence was provided
  28667. /*
  28668. if(numberOfFrames === 1) {
  28669. numberOfFrames = 2;
  28670. frameCounter += 1;
  28671. }
  28672. */
  28673. //Calculate the frame rate. Set the default fps to 12
  28674. if (!sprite.fps) sprite.fps = 12;
  28675. var frameRate = 1000 / sprite.fps;
  28676. //Set the sprite to the starting frame
  28677. sprite.gotoAndStop(startFrame);
  28678. //Set the `frameCounter` to the first frame
  28679. frameCounter = 1;
  28680. //If the state isn't already `playing`, start it
  28681. if (!sprite.animating) {
  28682. timerInterval = setInterval(advanceFrame.bind(this), frameRate);
  28683. sprite.animating = true;
  28684. }
  28685. }
  28686. //`advanceFrame` is called by `setInterval` to display the next frame
  28687. //in the sequence based on the `frameRate`. When the frame sequence
  28688. //reaches the end, it will either stop or loop
  28689. function advanceFrame() {
  28690. //Advance the frame if `frameCounter` is less than
  28691. //the state's total frames
  28692. if (frameCounter < numberOfFrames + 1) {
  28693. //Advance the frame
  28694. sprite.gotoAndStop(sprite.currentFrame + 1);
  28695. //Update the frame counter
  28696. frameCounter += 1;
  28697. //If we've reached the last frame and `loop`
  28698. //is `true`, then start from the first frame again
  28699. } else {
  28700. if (sprite.loop) {
  28701. sprite.gotoAndStop(startFrame);
  28702. frameCounter = 1;
  28703. }
  28704. }
  28705. }
  28706. function reset() {
  28707. //Reset `sprite.playing` to `false`, set the `frameCounter` to 0, //and clear the `timerInterval`
  28708. if (timerInterval !== undefined && sprite.animating === true) {
  28709. sprite.animating = false;
  28710. frameCounter = 0;
  28711. startFrame = 0;
  28712. endFrame = 0;
  28713. numberOfFrames = 0;
  28714. clearInterval(timerInterval);
  28715. }
  28716. }
  28717. //Add the `show`, `play`, `stop`, and `playSequence` methods to the sprite
  28718. sprite.show = show;
  28719. sprite.stopAnimation = stopAnimation;
  28720. sprite.playAnimation = playAnimation;
  28721. }
  28722. //`tilingSpirte` lets you quickly create Pixi tiling sprites
  28723. }, {
  28724. key: "tilingSprite",
  28725. value: function tilingSprite(source, width, height, x, y) {
  28726. if (width === undefined) {
  28727. throw new Error("Please define a width as your second argument for the tiling sprite");
  28728. }
  28729. if (height === undefined) {
  28730. throw new Error("Please define a height as your third argument for the tiling sprite");
  28731. }
  28732. var o = this.sprite(source, x, y, true, width, height);
  28733. //Add `tileX`, `tileY`, `tileScaleX` and `tileScaleY` properties
  28734. Object.defineProperties(o, {
  28735. "tileX": {
  28736. get: function get() {
  28737. return o.tilePosition.x;
  28738. },
  28739. set: function set(value) {
  28740. o.tilePosition.x = value;
  28741. },
  28742. enumerable: true, configurable: true
  28743. },
  28744. "tileY": {
  28745. get: function get() {
  28746. return o.tilePosition.y;
  28747. },
  28748. set: function set(value) {
  28749. o.tilePosition.y = value;
  28750. },
  28751. enumerable: true, configurable: true
  28752. },
  28753. "tileScaleX": {
  28754. get: function get() {
  28755. return o.tileScale.x;
  28756. },
  28757. set: function set(value) {
  28758. o.tileScale.x = value;
  28759. },
  28760. enumerable: true, configurable: true
  28761. },
  28762. "tileScaleY": {
  28763. get: function get() {
  28764. return o.tileScale.y;
  28765. },
  28766. set: function set(value) {
  28767. o.tileScale.y = value;
  28768. },
  28769. enumerable: true, configurable: true
  28770. }
  28771. });
  28772. return o;
  28773. }
  28774. }, {
  28775. key: "filmstrip",
  28776. value: function filmstrip(texture, frameWidth, frameHeight) {
  28777. var spacing = arguments.length <= 3 || arguments[3] === undefined ? 0 : arguments[3];
  28778. //An array to store the x/y positions of the frames
  28779. var positions = [];
  28780. //Find the width and height of the texture
  28781. var textureWidth = this.TextureCache[texture].width,
  28782. textureHeight = this.TextureCache[texture].height;
  28783. //Find out how many columns and rows there are
  28784. var columns = textureWidth / frameWidth,
  28785. rows = textureHeight / frameHeight;
  28786. //Find the total number of frames
  28787. var numberOfFrames = columns * rows;
  28788. for (var i = 0; i < numberOfFrames; i++) {
  28789. //Find the correct row and column for each frame
  28790. //and figure out its x and y position
  28791. var x = i % columns * frameWidth,
  28792. y = Math.floor(i / columns) * frameHeight;
  28793. //Compensate for any optional spacing (padding) around the tiles if
  28794. //there is any. This bit of code accumlates the spacing offsets from the
  28795. //left side of the tileset and adds them to the current tile's position
  28796. if (spacing > 0) {
  28797. x += spacing + spacing * i % columns;
  28798. y += spacing + spacing * Math.floor(i / columns);
  28799. }
  28800. //Add the x and y value of each frame to the `positions` array
  28801. positions.push([x, y]);
  28802. }
  28803. //Return the frames
  28804. return this.frames(texture, positions, frameWidth, frameHeight);
  28805. }
  28806. //Make a texture from a frame in another texture or image
  28807. }, {
  28808. key: "frame",
  28809. value: function frame(source, x, y, width, height) {
  28810. var texture = undefined,
  28811. imageFrame = undefined;
  28812. //If the source is a string, it's either a texture in the
  28813. //cache or an image file
  28814. if (typeof source === "string") {
  28815. if (this.TextureCache[source]) {
  28816. texture = new this.Texture(this.TextureCache[source]);
  28817. }
  28818. }
  28819. //If the `source` is a texture, use it
  28820. else if (source instanceof this.Texture) {
  28821. texture = new this.Texture(source);
  28822. }
  28823. if (!texture) {
  28824. throw new Error("Please load the " + source + " texture into the cache.");
  28825. } else {
  28826. //Make a rectangle the size of the sub-image
  28827. imageFrame = new this.Rectangle(x, y, width, height);
  28828. texture.frame = imageFrame;
  28829. return texture;
  28830. }
  28831. }
  28832. //Make an array of textures from a 2D array of frame x and y coordinates in
  28833. //texture
  28834. }, {
  28835. key: "frames",
  28836. value: function frames(source, coordinates, frameWidth, frameHeight) {
  28837. var _this = this;
  28838. var baseTexture = undefined,
  28839. textures = undefined;
  28840. //If the source is a string, it's either a texture in the
  28841. //cache or an image file
  28842. if (typeof source === "string") {
  28843. if (this.TextureCache[source]) {
  28844. baseTexture = new this.Texture(this.TextureCache[source]);
  28845. }
  28846. }
  28847. //If the `source` is a texture, use it
  28848. else if (source instanceof this.Texture) {
  28849. baseTexture = new this.Texture(source);
  28850. }
  28851. if (!baseTexture) {
  28852. throw new Error("Please load the " + source + " texture into the cache.");
  28853. } else {
  28854. var _textures = coordinates.map(function (position) {
  28855. var x = position[0],
  28856. y = position[1];
  28857. var imageFrame = new _this.Rectangle(x, y, frameWidth, frameHeight);
  28858. var frameTexture = new _this.Texture(baseTexture);
  28859. frameTexture.frame = imageFrame;
  28860. return frameTexture;
  28861. });
  28862. return _textures;
  28863. }
  28864. }
  28865. }, {
  28866. key: "frameSeries",
  28867. value: function frameSeries() {
  28868. var startNumber = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];
  28869. var endNumber = arguments.length <= 1 || arguments[1] === undefined ? 1 : arguments[1];
  28870. var baseName = arguments.length <= 2 || arguments[2] === undefined ? "" : arguments[2];
  28871. var extension = arguments.length <= 3 || arguments[3] === undefined ? "" : arguments[3];
  28872. //Create an array to store the frame names
  28873. var frames = [];
  28874. for (var i = startNumber; i < endNumber + 1; i++) {
  28875. var frame = this.TextureCache["" + (baseName + i + extension)];
  28876. frames.push(frame);
  28877. }
  28878. return frames;
  28879. }
  28880. /* Text creation */
  28881. //The`text` method is a quick way to create a Pixi Text sprite
  28882. }, {
  28883. key: "text",
  28884. value: function text() {
  28885. var content = arguments.length <= 0 || arguments[0] === undefined ? "message" : arguments[0];
  28886. var font = arguments.length <= 1 || arguments[1] === undefined ? "16px sans" : arguments[1];
  28887. var fillStyle = arguments.length <= 2 || arguments[2] === undefined ? "red" : arguments[2];
  28888. var x = arguments.length <= 3 || arguments[3] === undefined ? 0 : arguments[3];
  28889. var y = arguments.length <= 4 || arguments[4] === undefined ? 0 : arguments[4];
  28890. //Create a Pixi Sprite object
  28891. var message = new this.Text(content, { font: font, fill: fillStyle });
  28892. message.x = x;
  28893. message.y = y;
  28894. //Add a `_text` property with a getter/setter
  28895. message._content = content;
  28896. Object.defineProperty(message, "content", {
  28897. get: function get() {
  28898. return this._content;
  28899. },
  28900. set: function set(value) {
  28901. this._content = value;
  28902. this.text = value;
  28903. },
  28904. enumerable: true, configurable: true
  28905. });
  28906. //Return the text object
  28907. return message;
  28908. }
  28909. //The`bitmapText` method lets you create bitmap text
  28910. }, {
  28911. key: "bitmapText",
  28912. value: function bitmapText() {
  28913. var content = arguments.length <= 0 || arguments[0] === undefined ? "message" : arguments[0];
  28914. var font = arguments[1];
  28915. var align = arguments[2];
  28916. var tint = arguments[3];
  28917. var x = arguments.length <= 4 || arguments[4] === undefined ? 0 : arguments[4];
  28918. var y = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5];
  28919. //Create a Pixi Sprite object
  28920. var message = new this.BitmapText(content, { font: font, align: align, tint: tint });
  28921. message.x = x;
  28922. message.y = y;
  28923. //Add a `_text` property with a getter/setter
  28924. message._content = content;
  28925. Object.defineProperty(message, "content", {
  28926. get: function get() {
  28927. return this._content;
  28928. },
  28929. set: function set(value) {
  28930. this._content = value;
  28931. this.text = value;
  28932. },
  28933. enumerable: true, configurable: true
  28934. });
  28935. //Return the text object
  28936. return message;
  28937. }
  28938. /* Shapes and lines */
  28939. //Rectangle
  28940. }, {
  28941. key: "rectangle",
  28942. value: function rectangle() {
  28943. var width = arguments.length <= 0 || arguments[0] === undefined ? 32 : arguments[0];
  28944. var height = arguments.length <= 1 || arguments[1] === undefined ? 32 : arguments[1];
  28945. var fillStyle = arguments.length <= 2 || arguments[2] === undefined ? 0xFF3300 : arguments[2];
  28946. var strokeStyle = arguments.length <= 3 || arguments[3] === undefined ? 0x0033CC : arguments[3];
  28947. var lineWidth = arguments.length <= 4 || arguments[4] === undefined ? 0 : arguments[4];
  28948. var x = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5];
  28949. var y = arguments.length <= 6 || arguments[6] === undefined ? 0 : arguments[6];
  28950. var o = new this.Graphics();
  28951. o._sprite = undefined;
  28952. o._width = width;
  28953. o._height = height;
  28954. o._fillStyle = this.color(fillStyle);
  28955. o._strokeStyle = this.color(strokeStyle);
  28956. o._lineWidth = lineWidth;
  28957. //Draw the rectangle
  28958. var draw = function draw(width, height, fillStyle, strokeStyle, lineWidth) {
  28959. o.clear();
  28960. o.beginFill(fillStyle);
  28961. if (lineWidth > 0) {
  28962. o.lineStyle(lineWidth, strokeStyle, 1);
  28963. }
  28964. o.drawRect(0, 0, width, height);
  28965. o.endFill();
  28966. };
  28967. //Draw the line and capture the sprite that the `draw` function
  28968. //returns
  28969. draw(o._width, o._height, o._fillStyle, o._strokeStyle, o._lineWidth);
  28970. //Generate a texture from the rectangle
  28971. var texture = o.generateTexture();
  28972. //Use the texture to create a sprite
  28973. var sprite = new this.Sprite(texture);
  28974. //Position the sprite
  28975. sprite.x = x;
  28976. sprite.y = y;
  28977. //Add getters and setters to the sprite
  28978. var self = this;
  28979. Object.defineProperties(sprite, {
  28980. "fillStyle": {
  28981. get: function get() {
  28982. return o._fillStyle;
  28983. },
  28984. set: function set(value) {
  28985. o._fillStyle = self.color(value);
  28986. //Draw the new rectangle
  28987. draw(o._width, o._height, o._fillStyle, o._strokeStyle, o._lineWidth, o._x, o._y);
  28988. //Generate a new texture and set it as the sprite's texture
  28989. var texture = o.generateTexture();
  28990. o._sprite.texture = texture;
  28991. },
  28992. enumerable: true, configurable: true
  28993. },
  28994. "strokeStyle": {
  28995. get: function get() {
  28996. return o._strokeStyle;
  28997. },
  28998. set: function set(value) {
  28999. o._strokeStyle = self.color(value);
  29000. //Draw the new rectangle
  29001. draw(o._width, o._height, o._fillStyle, o._strokeStyle, o._lineWidth, o._x, o._y);
  29002. //Generate a new texture and set it as the sprite's texture
  29003. var texture = o.generateTexture();
  29004. o._sprite.texture = texture;
  29005. },
  29006. enumerable: true, configurable: true
  29007. },
  29008. "lineWidth": {
  29009. get: function get() {
  29010. return o._lineWidth;
  29011. },
  29012. set: function set(value) {
  29013. o._lineWidth = value;
  29014. //Draw the new rectangle
  29015. draw(o._width, o._height, o._fillStyle, o._strokeStyle, o._lineWidth, o._x, o._y);
  29016. //Generate a new texture and set it as the sprite's texture
  29017. var texture = o.generateTexture();
  29018. o._sprite.texture = texture;
  29019. },
  29020. enumerable: true, configurable: true
  29021. }
  29022. });
  29023. //Get a local reference to the sprite so that we can
  29024. //change the rectangle properties later using the getters/setters
  29025. o._sprite = sprite;
  29026. //Return the sprite
  29027. return sprite;
  29028. }
  29029. //Circle
  29030. }, {
  29031. key: "circle",
  29032. value: function circle() {
  29033. var diameter = arguments.length <= 0 || arguments[0] === undefined ? 32 : arguments[0];
  29034. var fillStyle = arguments.length <= 1 || arguments[1] === undefined ? 0xFF3300 : arguments[1];
  29035. var strokeStyle = arguments.length <= 2 || arguments[2] === undefined ? 0x0033CC : arguments[2];
  29036. var lineWidth = arguments.length <= 3 || arguments[3] === undefined ? 0 : arguments[3];
  29037. var x = arguments.length <= 4 || arguments[4] === undefined ? 0 : arguments[4];
  29038. var y = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5];
  29039. var o = new this.Graphics();
  29040. o._diameter = diameter;
  29041. o._fillStyle = this.color(fillStyle);
  29042. o._strokeStyle = this.color(strokeStyle);
  29043. o._lineWidth = lineWidth;
  29044. //Draw the circle
  29045. var draw = function draw(diameter, fillStyle, strokeStyle, lineWidth) {
  29046. o.clear();
  29047. o.beginFill(fillStyle);
  29048. if (lineWidth > 0) {
  29049. o.lineStyle(lineWidth, strokeStyle, 1);
  29050. }
  29051. o.drawCircle(0, 0, diameter / 2);
  29052. o.endFill();
  29053. };
  29054. //Draw the cirlce
  29055. draw(o._diameter, o._fillStyle, o._strokeStyle, o._lineWidth);
  29056. //Generate a texture from the rectangle
  29057. var texture = o.generateTexture();
  29058. //Use the texture to create a sprite
  29059. var sprite = new this.Sprite(texture);
  29060. //Position the sprite
  29061. sprite.x = x;
  29062. sprite.y = y;
  29063. //Add getters and setters to the sprite
  29064. var self = this;
  29065. Object.defineProperties(sprite, {
  29066. "fillStyle": {
  29067. get: function get() {
  29068. return o._fillStyle;
  29069. },
  29070. set: function set(value) {
  29071. o._fillStyle = self.color(value);
  29072. //Draw the cirlce
  29073. draw(o._diameter, o._fillStyle, o._strokeStyle, o._lineWidth);
  29074. //Generate a new texture and set it as the sprite's texture
  29075. var texture = o.generateTexture();
  29076. o._sprite.texture = texture;
  29077. },
  29078. enumerable: true, configurable: true
  29079. },
  29080. "strokeStyle": {
  29081. get: function get() {
  29082. return o._strokeStyle;
  29083. },
  29084. set: function set(value) {
  29085. o._strokeStyle = self.color(value);
  29086. //Draw the cirlce
  29087. draw(o._diameter, o._fillStyle, o._strokeStyle, o._lineWidth);
  29088. //Generate a new texture and set it as the sprite's texture
  29089. var texture = o.generateTexture();
  29090. o._sprite.texture = texture;
  29091. },
  29092. enumerable: true, configurable: true
  29093. },
  29094. "diameter": {
  29095. get: function get() {
  29096. return o._diameter;
  29097. },
  29098. set: function set(value) {
  29099. o._lineWidth = 10;
  29100. //Draw the cirlce
  29101. draw(o._diameter, o._fillStyle, o._strokeStyle, o._lineWidth);
  29102. //Generate a new texture and set it as the sprite's texture
  29103. var texture = o.generateTexture();
  29104. o._sprite.texture = texture;
  29105. },
  29106. enumerable: true, configurable: true
  29107. },
  29108. "radius": {
  29109. get: function get() {
  29110. return o._diameter / 2;
  29111. },
  29112. set: function set(value) {
  29113. //Draw the cirlce
  29114. draw(value * 2, o._fillStyle, o._strokeStyle, o._lineWidth);
  29115. //Generate a new texture and set it as the sprite's texture
  29116. var texture = o.generateTexture();
  29117. o._sprite.texture = texture;
  29118. },
  29119. enumerable: true, configurable: true
  29120. }
  29121. });
  29122. //Get a local reference to the sprite so that we can
  29123. //change the circle properties later using the getters/setters
  29124. o._sprite = sprite;
  29125. //Return the sprite
  29126. return sprite;
  29127. }
  29128. //Line
  29129. }, {
  29130. key: "line",
  29131. value: function line() {
  29132. var strokeStyle = arguments.length <= 0 || arguments[0] === undefined ? 0x000000 : arguments[0];
  29133. var lineWidth = arguments.length <= 1 || arguments[1] === undefined ? 1 : arguments[1];
  29134. var ax = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2];
  29135. var ay = arguments.length <= 3 || arguments[3] === undefined ? 0 : arguments[3];
  29136. var bx = arguments.length <= 4 || arguments[4] === undefined ? 32 : arguments[4];
  29137. var by = arguments.length <= 5 || arguments[5] === undefined ? 32 : arguments[5];
  29138. //Create the line object
  29139. var o = new this.Graphics();
  29140. //Private properties
  29141. o._strokeStyle = this.color(strokeStyle);
  29142. o._width = lineWidth;
  29143. o._ax = ax;
  29144. o._ay = ay;
  29145. o._bx = bx;
  29146. o._by = by;
  29147. //A helper function that draws the line
  29148. var draw = function draw(strokeStyle, lineWidth, ax, ay, bx, by) {
  29149. o.clear();
  29150. o.lineStyle(lineWidth, strokeStyle, 1);
  29151. o.moveTo(ax, ay);
  29152. o.lineTo(bx, by);
  29153. };
  29154. //Draw the line
  29155. draw(o._strokeStyle, o._width, o._ax, o._ay, o._bx, o._by);
  29156. //Define getters and setters that redefine the line's start and
  29157. //end points and re-draws it if they change
  29158. var self = this;
  29159. Object.defineProperties(o, {
  29160. "ax": {
  29161. get: function get() {
  29162. return o._ax;
  29163. },
  29164. set: function set(value) {
  29165. o._ax = value;
  29166. draw(o._strokeStyle, o._width, o._ax, o._ay, o._bx, o._by);
  29167. },
  29168. enumerable: true, configurable: true
  29169. },
  29170. "ay": {
  29171. get: function get() {
  29172. return o._ay;
  29173. },
  29174. set: function set(value) {
  29175. o._ay = value;
  29176. draw(o._strokeStyle, o._width, o._ax, o._ay, o._bx, o._by);
  29177. },
  29178. enumerable: true, configurable: true
  29179. },
  29180. "bx": {
  29181. get: function get() {
  29182. return o._bx;
  29183. },
  29184. set: function set(value) {
  29185. o._bx = value;
  29186. draw(o._strokeStyle, o._width, o._ax, o._ay, o._bx, o._by);
  29187. },
  29188. enumerable: true, configurable: true
  29189. },
  29190. "by": {
  29191. get: function get() {
  29192. return o._by;
  29193. },
  29194. set: function set(value) {
  29195. o._by = value;
  29196. draw(o._strokeStyle, o._width, o._ax, o._ay, o._bx, o._by);
  29197. },
  29198. enumerable: true, configurable: true
  29199. },
  29200. "strokeStyle": {
  29201. get: function get() {
  29202. return o._strokeStyle;
  29203. },
  29204. set: function set(value) {
  29205. o._strokeStyle = self.color(value);
  29206. //Draw the line
  29207. draw(o._strokeStyle, o._width, o._ax, o._ay, o._bx, o._by);
  29208. },
  29209. enumerable: true, configurable: true
  29210. },
  29211. "width": {
  29212. get: function get() {
  29213. return o._width;
  29214. },
  29215. set: function set(value) {
  29216. o._width = value;
  29217. //Draw the line
  29218. draw(o._strokeStyle, o._width, o._ax, o._ay, o._bx, o._by);
  29219. },
  29220. enumerable: true, configurable: true
  29221. }
  29222. });
  29223. //Return the line
  29224. return o;
  29225. }
  29226. /* Compound sprites */
  29227. //Use `grid` to create a grid of sprites
  29228. }, {
  29229. key: "grid",
  29230. value: function grid() {
  29231. var columns = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];
  29232. var rows = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
  29233. var cellWidth = arguments.length <= 2 || arguments[2] === undefined ? 32 : arguments[2];
  29234. var cellHeight = arguments.length <= 3 || arguments[3] === undefined ? 32 : arguments[3];
  29235. var centerCell = arguments.length <= 4 || arguments[4] === undefined ? false : arguments[4];
  29236. var xOffset = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5];
  29237. var yOffset = arguments.length <= 6 || arguments[6] === undefined ? 0 : arguments[6];
  29238. var makeSprite = arguments.length <= 7 || arguments[7] === undefined ? undefined : arguments[7];
  29239. var extra = arguments.length <= 8 || arguments[8] === undefined ? undefined : arguments[8];
  29240. //Create an empty group called `container`. This `container`
  29241. //group is what the function returns back to the main program.
  29242. //All the sprites in the grid cells will be added
  29243. //as children to this container
  29244. var container = new this.Container();
  29245. //The `create` method plots the grid
  29246. var createGrid = function createGrid() {
  29247. //Figure out the number of cells in the grid
  29248. var length = columns * rows;
  29249. //Create a sprite for each cell
  29250. for (var i = 0; i < length; i++) {
  29251. //Figure out the sprite's x/y placement in the grid
  29252. var x = i % columns * cellWidth,
  29253. y = Math.floor(i / columns) * cellHeight;
  29254. //Use the `makeSprite` function supplied in the constructor
  29255. //to make a sprite for the grid cell
  29256. var sprite = makeSprite();
  29257. //Add the sprite to the `container`
  29258. container.addChild(sprite);
  29259. //Should the sprite be centered in the cell?
  29260. //No, it shouldn't be centered
  29261. if (!centerCell) {
  29262. sprite.x = x + xOffset;
  29263. sprite.y = y + yOffset;
  29264. }
  29265. //Yes, it should be centered
  29266. else {
  29267. sprite.x = x + cellWidth / 2 - sprite.width / 2 + xOffset;
  29268. sprite.y = y + cellHeight / 2 - sprite.width / 2 + yOffset;
  29269. }
  29270. //Run any optional extra code. This calls the
  29271. //`extra` function supplied by the constructor
  29272. if (extra) extra(sprite);
  29273. }
  29274. };
  29275. //Run the `createGrid` method
  29276. createGrid();
  29277. //Return the `container` group back to the main program
  29278. return container;
  29279. }
  29280. //Use `shoot` to create bullet sprites
  29281. }, {
  29282. key: "shoot",
  29283. value: function shoot(shooter, angle, x, y, container, bulletSpeed, bulletArray, bulletSprite) {
  29284. //Make a new sprite using the user-supplied `bulletSprite` function
  29285. var bullet = bulletSprite();
  29286. //Set the bullet's anchor point to its center
  29287. bullet.anchor.set(0.5, 0.5);
  29288. //Temporarily add the bullet to the shooter
  29289. //so that we can position it relative to the
  29290. //shooter's position
  29291. shooter.addChild(bullet);
  29292. bullet.x = x;
  29293. bullet.y = y;
  29294. //Find the bullet's global coordinates so that we can use
  29295. //them to position the bullet on the new parent container
  29296. var tempGx = bullet.getGlobalPosition().x,
  29297. tempGy = bullet.getGlobalPosition().y;
  29298. //Add the bullet to the new parent container using
  29299. //the new global coordinates
  29300. container.addChild(bullet);
  29301. bullet.x = tempGx;
  29302. bullet.y = tempGy;
  29303. //Set the bullet's velocity
  29304. bullet.vx = Math.cos(angle) * bulletSpeed;
  29305. bullet.vy = Math.sin(angle) * bulletSpeed;
  29306. //Push the bullet into the `bulletArray`
  29307. bulletArray.push(bullet);
  29308. }
  29309. /*
  29310. grid
  29311. ----
  29312. Helps you to automatically create a grid of sprites. `grid` returns a
  29313. `group` sprite object that contains a sprite for every cell in the
  29314. grid. You can define the rows and columns in the grid, whether or
  29315. not the sprites should be centered inside each cell, or what their offset from the
  29316. top left corner of each cell should be. Supply a function that
  29317. returns the sprite that you want to make for each cell. You can
  29318. supply an optional final function that runs any extra code after
  29319. each sprite has been created. Here's the format for creating a grid:
  29320. gridGroup = grid(
  29321. //Set the grid's properties
  29322. columns, rows, cellWidth, cellHeight,
  29323. areSpirtesCentered?, xOffset, yOffset,
  29324. //A function that returns a sprite
  29325. () => g.circle(16, "blue"),
  29326. //An optional final function that runs some extra code
  29327. () => console.log("extra!")
  29328. );
  29329. */
  29330. }, {
  29331. key: "grid",
  29332. value: function grid() {
  29333. var columns = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];
  29334. var rows = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
  29335. var cellWidth = arguments.length <= 2 || arguments[2] === undefined ? 32 : arguments[2];
  29336. var cellHeight = arguments.length <= 3 || arguments[3] === undefined ? 32 : arguments[3];
  29337. var centerCell = arguments.length <= 4 || arguments[4] === undefined ? false : arguments[4];
  29338. var xOffset = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5];
  29339. var yOffset = arguments.length <= 6 || arguments[6] === undefined ? 0 : arguments[6];
  29340. var makeSprite = arguments.length <= 7 || arguments[7] === undefined ? undefined : arguments[7];
  29341. var extra = arguments.length <= 8 || arguments[8] === undefined ? undefined : arguments[8];
  29342. //Create an empty group called `container`. This `container`
  29343. //group is what the function returns back to the main program.
  29344. //All the sprites in the grid cells will be added
  29345. //as children to this container
  29346. var container = this.group();
  29347. //The `create` method plots the grid
  29348. var createGrid = function createGrid() {
  29349. //Figure out the number of cells in the grid
  29350. var length = columns * rows;
  29351. //Create a sprite for each cell
  29352. for (var i = 0; i < length; i++) {
  29353. //Figure out the sprite's x/y placement in the grid
  29354. var x = i % columns * cellWidth,
  29355. y = Math.floor(i / columns) * cellHeight;
  29356. //Use the `makeSprite` function supplied in the constructor
  29357. //to make a sprite for the grid cell
  29358. var sprite = makeSprite();
  29359. //Add the sprite to the `container`
  29360. container.addChild(sprite);
  29361. //Should the sprite be centered in the cell?
  29362. //No, it shouldn't be centered
  29363. if (!centerCell) {
  29364. sprite.x = x + xOffset;
  29365. sprite.y = y + yOffset;
  29366. }
  29367. //Yes, it should be centered
  29368. else {
  29369. sprite.x = x + cellWidth / 2 - sprite.halfWidth + xOffset;
  29370. sprite.y = y + cellHeight / 2 - sprite.halfHeight + yOffset;
  29371. }
  29372. //Run any optional extra code. This calls the
  29373. //`extra` function supplied by the constructor
  29374. if (extra) extra(sprite);
  29375. }
  29376. };
  29377. //Run the `createGrid` method
  29378. createGrid();
  29379. //Return the `container` group back to the main program
  29380. return container;
  29381. }
  29382. /*
  29383. shake
  29384. -----
  29385. Used to create a shaking effect, like a screen shake
  29386. */
  29387. }, {
  29388. key: "shake",
  29389. value: function shake(sprite) {
  29390. var magnitude = arguments.length <= 1 || arguments[1] === undefined ? 16 : arguments[1];
  29391. var angular = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  29392. //Get a reference to this current object so that
  29393. //it's easy to maintain scope in the nested sub-functions
  29394. var self = this;
  29395. //A counter to count the number of shakes
  29396. var counter = 1;
  29397. //The total number of shakes (there will be 1 shake per frame)
  29398. var numberOfShakes = 10;
  29399. //Capture the sprite's position and angle so you can
  29400. //restore them after the shaking has finished
  29401. var startX = sprite.x,
  29402. startY = sprite.y,
  29403. startAngle = sprite.rotation;
  29404. //Divide the magnitude into 10 units so that you can
  29405. //reduce the amount of shake by 10 percent each frame
  29406. var magnitudeUnit = magnitude / numberOfShakes;
  29407. //The `randomInt` helper function
  29408. var randomInt = function randomInt(min, max) {
  29409. return Math.floor(Math.random() * (max - min + 1)) + min;
  29410. };
  29411. //Add the sprite to the `shakingSprites` array if it
  29412. //isn't already there
  29413. if (self.shakingSprites.indexOf(sprite) === -1) {
  29414. self.shakingSprites.push(sprite);
  29415. //Add an `updateShake` method to the sprite.
  29416. //The `updateShake` method will be called each frame
  29417. //in the game loop. The shake effect type can be either
  29418. //up and down (x/y shaking) or angular (rotational shaking).
  29419. sprite.updateShake = function () {
  29420. if (angular) {
  29421. angularShake();
  29422. } else {
  29423. upAndDownShake();
  29424. }
  29425. };
  29426. }
  29427. //The `upAndDownShake` function
  29428. function upAndDownShake() {
  29429. //Shake the sprite while the `counter` is less than
  29430. //the `numberOfShakes`
  29431. if (counter < numberOfShakes) {
  29432. //Reset the sprite's position at the start of each shake
  29433. sprite.x = startX;
  29434. sprite.y = startY;
  29435. //Reduce the magnitude
  29436. magnitude -= magnitudeUnit;
  29437. //Randomly change the sprite's position
  29438. sprite.x += randomInt(-magnitude, magnitude);
  29439. sprite.y += randomInt(-magnitude, magnitude);
  29440. //Add 1 to the counter
  29441. counter += 1;
  29442. }
  29443. //When the shaking is finished, restore the sprite to its original
  29444. //position and remove it from the `shakingSprites` array
  29445. if (counter >= numberOfShakes) {
  29446. sprite.x = startX;
  29447. sprite.y = startY;
  29448. self.shakingSprites.splice(self.shakingSprites.indexOf(sprite), 1);
  29449. }
  29450. }
  29451. //The `angularShake` function
  29452. //First set the initial tilt angle to the right (+1)
  29453. var tiltAngle = 1;
  29454. function angularShake() {
  29455. if (counter < numberOfShakes) {
  29456. //Reset the sprite's rotation
  29457. sprite.rotation = startAngle;
  29458. //Reduce the magnitude
  29459. magnitude -= magnitudeUnit;
  29460. //Rotate the sprite left or right, depending on the direction,
  29461. //by an amount in radians that matches the magnitude
  29462. sprite.rotation = magnitude * tiltAngle;
  29463. counter += 1;
  29464. //Reverse the tilt angle so that the sprite is tilted
  29465. //in the opposite direction for the next shake
  29466. tiltAngle *= -1;
  29467. }
  29468. //When the shaking is finished, reset the sprite's angle and
  29469. //remove it from the `shakingSprites` array
  29470. if (counter >= numberOfShakes) {
  29471. sprite.rotation = startAngle;
  29472. self.shakingSprites.splice(self.shakingSprites.indexOf(sprite), 1);
  29473. }
  29474. }
  29475. }
  29476. /*
  29477. _getCenter
  29478. ----------
  29479. A utility that finds the center point of the sprite. If it's anchor point is the
  29480. sprite's top left corner, then the center is calculated from that point.
  29481. If the anchor point has been shifted, then the anchor x/y point is used as the sprite's center
  29482. */
  29483. }, {
  29484. key: "_getCenter",
  29485. value: function _getCenter(o, dimension, axis) {
  29486. if (o.anchor !== undefined) {
  29487. if (o.anchor[axis] !== 0) {
  29488. return 0;
  29489. } else {
  29490. return dimension / 2;
  29491. }
  29492. } else {
  29493. return dimension;
  29494. }
  29495. }
  29496. /* Groups */
  29497. //Group sprites into a container
  29498. }, {
  29499. key: "group",
  29500. value: function group() {
  29501. var container = new this.Container();
  29502. for (var _len = arguments.length, sprites = Array(_len), _key = 0; _key < _len; _key++) {
  29503. sprites[_key] = arguments[_key];
  29504. }
  29505. sprites.forEach(function (sprite) {
  29506. container.addChild(sprite);
  29507. });
  29508. return container;
  29509. }
  29510. //Use the `batch` method to create a ParticleContainer
  29511. }, {
  29512. key: "batch",
  29513. value: function batch() {
  29514. var size = arguments.length <= 0 || arguments[0] === undefined ? 15000 : arguments[0];
  29515. var options = arguments.length <= 1 || arguments[1] === undefined ? { rotation: true, alpha: true, scale: true, uvs: true } : arguments[1];
  29516. var o = new this.ParticleContainer(size, options);
  29517. return o;
  29518. }
  29519. //`remove` is a global convenience method that will
  29520. //remove any sprite, or an argument list of sprites, from its parent.
  29521. }, {
  29522. key: "remove",
  29523. value: function remove() {
  29524. for (var _len2 = arguments.length, sprites = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
  29525. sprites[_key2] = arguments[_key2];
  29526. }
  29527. //Remove sprites that's aren't in an array
  29528. if (!(sprites[0] instanceof Array)) {
  29529. if (sprites.length > 1) {
  29530. sprites.forEach(function (sprite) {
  29531. sprite.parent.removeChild(sprite);
  29532. });
  29533. } else {
  29534. sprites[0].parent.removeChild(sprites[0]);
  29535. }
  29536. }
  29537. //Remove sprites in an array of sprites
  29538. else {
  29539. var spritesArray = sprites[0];
  29540. if (spritesArray.length > 0) {
  29541. for (var i = spritesArray.length - 1; i >= 0; i--) {
  29542. var sprite = spritesArray[i];
  29543. sprite.parent.removeChild(sprite);
  29544. spritesArray.splice(spritesArray.indexOf(sprite), 1);
  29545. }
  29546. }
  29547. }
  29548. }
  29549. /* Color conversion */
  29550. //From: http://stackoverflow.com/questions/1573053/javascript-function-to-convert-color-names-to-hex-codes
  29551. //Utilities to convert HTML color string names to hexadecimal codes
  29552. }, {
  29553. key: "colorToRGBA",
  29554. value: function colorToRGBA(color) {
  29555. // Returns the color as an array of [r, g, b, a] -- all range from 0 - 255
  29556. // color must be a valid canvas fillStyle. This will cover most anything
  29557. // you'd want to use.
  29558. // Examples:
  29559. // colorToRGBA('red') # [255, 0, 0, 255]
  29560. // colorToRGBA('#f00') # [255, 0, 0, 255]
  29561. var cvs, ctx;
  29562. cvs = document.createElement('canvas');
  29563. cvs.height = 1;
  29564. cvs.width = 1;
  29565. ctx = cvs.getContext('2d');
  29566. ctx.fillStyle = color;
  29567. ctx.fillRect(0, 0, 1, 1);
  29568. var data = ctx.getImageData(0, 0, 1, 1).data;
  29569. return data;
  29570. }
  29571. }, {
  29572. key: "byteToHex",
  29573. value: function byteToHex(num) {
  29574. // Turns a number (0-255) into a 2-character hex number (00-ff)
  29575. return ('0' + num.toString(16)).slice(-2);
  29576. }
  29577. }, {
  29578. key: "colorToHex",
  29579. value: function colorToHex(color) {
  29580. var _this2 = this;
  29581. // Convert any CSS color to a hex representation
  29582. // Examples:
  29583. // colorToHex('red') # '#ff0000'
  29584. // colorToHex('rgb(255, 0, 0)') # '#ff0000'
  29585. var rgba, hex;
  29586. rgba = this.colorToRGBA(color);
  29587. hex = [0, 1, 2].map(function (idx) {
  29588. return _this2.byteToHex(rgba[idx]);
  29589. }).join('');
  29590. return "0x" + hex;
  29591. }
  29592. //A function to find out if the user entered a number (a hex color
  29593. //code) or a string (an HTML color string)
  29594. }, {
  29595. key: "color",
  29596. value: function color(value) {
  29597. //Check if it's a number
  29598. if (!isNaN(value)) {
  29599. //Yes, it is a number, so just return it
  29600. return value;
  29601. }
  29602. //No it's not a number, so it must be a string
  29603. else {
  29604. return parseInt(this.colorToHex(value));
  29605. /*
  29606. //Find out what kind of color string it is.
  29607. //Let's first grab the first character of the string
  29608. let firstCharacter = value.charAt(0);
  29609. //If the first character is a "#" or a number, then
  29610. //we know it must be a RGBA color
  29611. if (firstCharacter === "#") {
  29612. console.log("first character: " + value.charAt(0))
  29613. }
  29614. */
  29615. }
  29616. /*
  29617. //Find out if the first character in the string is a number
  29618. if (!isNaN(parseInt(string.charAt(0)))) {
  29619. //It's not, so convert it to a hex code
  29620. return colorToHex(string);
  29621. //The use input a number, so it must be a hex code. Just return it
  29622. } else {
  29623. return string;
  29624. }
  29625. */
  29626. }
  29627. }]);
  29628. return SpriteUtilities;
  29629. })();
  29630. //# sourceMappingURL=spriteUtilities.js.map"use strict";
  29631. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  29632. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  29633. var GameUtilities = (function () {
  29634. function GameUtilities() {
  29635. _classCallCheck(this, GameUtilities);
  29636. }
  29637. /*
  29638. distance
  29639. ----------------
  29640. Find the distance in pixels between two sprites.
  29641. Parameters:
  29642. a. A sprite object.
  29643. b. A sprite object.
  29644. The function returns the number of pixels distance between the sprites.
  29645. let distanceBetweenSprites = gu.distance(spriteA, spriteB);
  29646. */
  29647. _createClass(GameUtilities, [{
  29648. key: "distance",
  29649. value: function distance(s1, s2) {
  29650. var vx = s2.x + this._getCenter(s2, s2.width, "x") - (s1.x + this._getCenter(s1, s1.width, "x")),
  29651. vy = s2.y + this._getCenter(s2, s2.height, "y") - (s1.y + this._getCenter(s1, s1.height, "y"));
  29652. return Math.sqrt(vx * vx + vy * vy);
  29653. }
  29654. /*
  29655. followEase
  29656. ----------------
  29657. Make a sprite ease to the position of another sprite.
  29658. Parameters:
  29659. a. A sprite object. This is the `follower` sprite.
  29660. b. A sprite object. This is the `leader` sprite that the follower will chase.
  29661. c. The easing value, such as 0.3. A higher number makes the follower move faster.
  29662. gu.followEase(follower, leader, speed);
  29663. Use it inside a game loop.
  29664. */
  29665. }, {
  29666. key: "followEase",
  29667. value: function followEase(follower, leader, speed) {
  29668. //Figure out the distance between the sprites
  29669. /*
  29670. let vx = (leader.x + leader.width / 2) - (follower.x + follower.width / 2),
  29671. vy = (leader.y + leader.height / 2) - (follower.y + follower.height / 2),
  29672. distance = Math.sqrt(vx * vx + vy * vy);
  29673. */
  29674. var vx = leader.x + this._getCenter(leader, leader.width, "x") - (follower.x + this._getCenter(follower, follower.width, "x")),
  29675. vy = leader.y + this._getCenter(leader, leader.height, "y") - (follower.y + this._getCenter(follower, follower.height, "y")),
  29676. distance = Math.sqrt(vx * vx + vy * vy);
  29677. //Move the follower if it's more than 1 pixel
  29678. //away from the leader
  29679. if (distance >= 1) {
  29680. follower.x += vx * speed;
  29681. follower.y += vy * speed;
  29682. }
  29683. }
  29684. /*
  29685. followConstant
  29686. ----------------
  29687. Make a sprite move towards another sprite at a constant speed.
  29688. Parameters:
  29689. a. A sprite object. This is the `follower` sprite.
  29690. b. A sprite object. This is the `leader` sprite that the follower will chase.
  29691. c. The speed value, such as 3. The is the pixels per frame that the sprite will move. A higher number makes the follower move faster.
  29692. gu.followConstant(follower, leader, speed);
  29693. */
  29694. }, {
  29695. key: "followConstant",
  29696. value: function followConstant(follower, leader, speed) {
  29697. //Figure out the distance between the sprites
  29698. var vx = leader.x + this._getCenter(leader, leader.width, "x") - (follower.x + this._getCenter(follower, follower.width, "x")),
  29699. vy = leader.y + this._getCenter(leader, leader.height, "y") - (follower.y + this._getCenter(follower, follower.height, "y")),
  29700. distance = Math.sqrt(vx * vx + vy * vy);
  29701. //Move the follower if it's more than 1 move
  29702. //away from the leader
  29703. if (distance >= speed) {
  29704. follower.x += vx / distance * speed;
  29705. follower.y += vy / distance * speed;
  29706. }
  29707. }
  29708. /*
  29709. angle
  29710. -----
  29711. Return the angle in Radians between two sprites.
  29712. Parameters:
  29713. a. A sprite object.
  29714. b. A sprite object.
  29715. You can use it to make a sprite rotate towards another sprite like this:
  29716. box.rotation = gu.angle(box, pointer);
  29717. */
  29718. }, {
  29719. key: "angle",
  29720. value: function angle(s1, s2) {
  29721. return Math.atan2(
  29722. //This is the code you need if you don't want to compensate
  29723. //for a possible shift in the sprites' x/y anchor points
  29724. /*
  29725. (s2.y + s2.height / 2) - (s1.y + s1.height / 2),
  29726. (s2.x + s2.width / 2) - (s1.x + s1.width / 2)
  29727. */
  29728. //This code adapts to a shifted anchor point
  29729. s2.y + this._getCenter(s2, s2.height, "y") - (s1.y + this._getCenter(s1, s1.height, "y")), s2.x + this._getCenter(s2, s2.width, "x") - (s1.x + this._getCenter(s1, s1.width, "x")));
  29730. }
  29731. /*
  29732. _getCenter
  29733. ----------
  29734. A utility that finds the center point of the sprite. If it's anchor point is the
  29735. sprite's top left corner, then the center is calculated from that point.
  29736. If the anchor point has been shifted, then the anchor x/y point is used as the sprite's center
  29737. */
  29738. }, {
  29739. key: "_getCenter",
  29740. value: function _getCenter(o, dimension, axis) {
  29741. if (o.anchor !== undefined) {
  29742. if (o.anchor[axis] !== 0) {
  29743. return 0;
  29744. } else {
  29745. //console.log(o.anchor[axis])
  29746. return dimension / 2;
  29747. }
  29748. } else {
  29749. return dimension;
  29750. }
  29751. }
  29752. /*
  29753. rotateAroundSprite
  29754. ------------
  29755. Make a sprite rotate around another sprite.
  29756. Parameters:
  29757. a. The sprite you want to rotate.
  29758. b. The sprite around which you want to rotate the first sprite.
  29759. c. The distance, in pixels, that the roating sprite should be offset from the center.
  29760. d. The angle of rotations, in radians.
  29761. gu.rotateAroundSprite(orbitingSprite, centerSprite, 50, angleInRadians);
  29762. Use it inside a game loop, and make sure you update the angle value (the 4th argument) each frame.
  29763. */
  29764. }, {
  29765. key: "rotateAroundSprite",
  29766. value: function rotateAroundSprite(rotatingSprite, centerSprite, distance, angle) {
  29767. rotatingSprite.x = centerSprite.x + this._getCenter(centerSprite, centerSprite.width, "x") - rotatingSprite.parent.x + distance * Math.cos(angle) - this._getCenter(rotatingSprite, rotatingSprite.width, "x");
  29768. rotatingSprite.y = centerSprite.y + this._getCenter(centerSprite, centerSprite.height, "y") - rotatingSprite.parent.y + distance * Math.sin(angle) - this._getCenter(rotatingSprite, rotatingSprite.height, "y");
  29769. }
  29770. /*
  29771. rotateAroundPoint
  29772. -----------------
  29773. Make a point rotate around another point.
  29774. Parameters:
  29775. a. The point you want to rotate.
  29776. b. The point around which you want to rotate the first point.
  29777. c. The distance, in pixels, that the roating sprite should be offset from the center.
  29778. d. The angle of rotations, in radians.
  29779. gu.rotateAroundPoint(orbitingPoint, centerPoint, 50, angleInRadians);
  29780. Use it inside a game loop, and make sure you update the angle value (the 4th argument) each frame.
  29781. */
  29782. }, {
  29783. key: "rotateAroundPoint",
  29784. value: function rotateAroundPoint(pointX, pointY, distanceX, distanceY, angle) {
  29785. var point = {};
  29786. point.x = pointX + Math.cos(angle) * distanceX;
  29787. point.y = pointY + Math.sin(angle) * distanceY;
  29788. return point;
  29789. }
  29790. /*
  29791. randomInt
  29792. ---------
  29793. Return a random integer between a minimum and maximum value
  29794. Parameters:
  29795. a. An integer.
  29796. b. An integer.
  29797. Here's how you can use it to get a random number between, 1 and 10:
  29798. let number = gu.randomInt(1, 10);
  29799. */
  29800. }, {
  29801. key: "randomInt",
  29802. value: function randomInt(min, max) {
  29803. return Math.floor(Math.random() * (max - min + 1)) + min;
  29804. }
  29805. /*
  29806. randomFloat
  29807. -----------
  29808. Return a random floating point number between a minimum and maximum value
  29809. Parameters:
  29810. a. Any number.
  29811. b. Any number.
  29812. Here's how you can use it to get a random floating point number between, 1 and 10:
  29813. let number = gu.randomFloat(1, 10);
  29814. */
  29815. }, {
  29816. key: "randomFloat",
  29817. value: function randomFloat(min, max) {
  29818. return min + Math.random() * (max - min);
  29819. }
  29820. /*
  29821. Wait
  29822. ----
  29823. Lets you wait for a specific number of milliseconds before running the
  29824. next function.
  29825. gu.wait(1000, runThisFunctionNext());
  29826. */
  29827. }, {
  29828. key: "wait",
  29829. value: function wait(duration, callBack) {
  29830. setTimeout(callBack, duration);
  29831. }
  29832. /*
  29833. Move
  29834. ----
  29835. Move a sprite by adding it's velocity to it's position. The sprite
  29836. must have `vx` and `vy` values for this to work. You can supply a
  29837. single sprite, or a list of sprites, separated by commas.
  29838. gu.move(sprite);
  29839. */
  29840. }, {
  29841. key: "move",
  29842. value: function move() {
  29843. for (var _len = arguments.length, sprites = Array(_len), _key = 0; _key < _len; _key++) {
  29844. sprites[_key] = arguments[_key];
  29845. }
  29846. //Move sprites that's aren't in an array
  29847. if (!(sprites[0] instanceof Array)) {
  29848. if (sprites.length > 1) {
  29849. sprites.forEach(function (sprite) {
  29850. sprite.x += sprite.vx;
  29851. sprite.y += sprite.vy;
  29852. });
  29853. } else {
  29854. sprites[0].x += sprites[0].vx;
  29855. sprites[0].y += sprites[0].vy;
  29856. }
  29857. }
  29858. //Move sprites in an array of sprites
  29859. else {
  29860. var spritesArray = sprites[0];
  29861. if (spritesArray.length > 0) {
  29862. for (var i = spritesArray.length - 1; i >= 0; i--) {
  29863. var sprite = spritesArray[i];
  29864. sprite.x += sprite.vx;
  29865. sprite.y += sprite.vy;
  29866. }
  29867. }
  29868. }
  29869. }
  29870. /*
  29871. World camera
  29872. ------------
  29873. The `worldCamera` method returns a `camera` object
  29874. with `x` and `y` properties. It has
  29875. two useful methods: `centerOver`, to center the camera over
  29876. a sprite, and `follow` to make it follow a sprite.
  29877. `worldCamera` arguments: worldObject, theCanvas
  29878. The worldObject needs to have a `width` and `height` property.
  29879. */
  29880. }, {
  29881. key: "worldCamera",
  29882. value: function worldCamera(world, worldWidth, worldHeight, canvas) {
  29883. //Define a `camera` object with helpful properties
  29884. var camera = {
  29885. width: canvas.width,
  29886. height: canvas.height,
  29887. _x: 0,
  29888. _y: 0,
  29889. //`x` and `y` getters/setters
  29890. //When you change the camera's position,
  29891. //they shift the position of the world in the opposite direction
  29892. get x() {
  29893. return this._x;
  29894. },
  29895. set x(value) {
  29896. this._x = value;
  29897. world.x = -this._x;
  29898. //world._previousX = world.x;
  29899. },
  29900. get y() {
  29901. return this._y;
  29902. },
  29903. set y(value) {
  29904. this._y = value;
  29905. world.y = -this._y;
  29906. //world._previousY = world.y;
  29907. },
  29908. //The center x and y position of the camera
  29909. get centerX() {
  29910. return this.x + this.width / 2;
  29911. },
  29912. get centerY() {
  29913. return this.y + this.height / 2;
  29914. },
  29915. //Boundary properties that define a rectangular area, half the size
  29916. //of the game screen. If the sprite that the camera is following
  29917. //is inide this area, the camera won't scroll. If the sprite
  29918. //crosses this boundary, the `follow` function ahead will change
  29919. //the camera's x and y position to scroll the game world
  29920. get rightInnerBoundary() {
  29921. return this.x + this.width / 2 + this.width / 4;
  29922. },
  29923. get leftInnerBoundary() {
  29924. return this.x + this.width / 2 - this.width / 4;
  29925. },
  29926. get topInnerBoundary() {
  29927. return this.y + this.height / 2 - this.height / 4;
  29928. },
  29929. get bottomInnerBoundary() {
  29930. return this.y + this.height / 2 + this.height / 4;
  29931. },
  29932. //The code next defines two camera
  29933. //methods: `follow` and `centerOver`
  29934. //Use the `follow` method to make the camera follow a sprite
  29935. follow: function follow(sprite) {
  29936. //Check the sprites position in relation to the inner
  29937. //boundary. Move the camera to follow the sprite if the sprite
  29938. //strays outside the boundary
  29939. if (sprite.x < this.leftInnerBoundary) {
  29940. this.x = sprite.x - this.width / 4;
  29941. }
  29942. if (sprite.y < this.topInnerBoundary) {
  29943. this.y = sprite.y - this.height / 4;
  29944. }
  29945. if (sprite.x + sprite.width > this.rightInnerBoundary) {
  29946. this.x = sprite.x + sprite.width - this.width / 4 * 3;
  29947. }
  29948. if (sprite.y + sprite.height > this.bottomInnerBoundary) {
  29949. this.y = sprite.y + sprite.height - this.height / 4 * 3;
  29950. }
  29951. //If the camera reaches the edge of the map, stop it from moving
  29952. if (this.x < 0) {
  29953. this.x = 0;
  29954. }
  29955. if (this.y < 0) {
  29956. this.y = 0;
  29957. }
  29958. if (this.x + this.width > worldWidth) {
  29959. this.x = worldWidth - this.width;
  29960. }
  29961. if (this.y + this.height > worldHeight) {
  29962. this.y = worldHeight - this.height;
  29963. }
  29964. },
  29965. //Use the `centerOver` method to center the camera over a sprite
  29966. centerOver: function centerOver(sprite) {
  29967. //Center the camera over a sprite
  29968. this.x = sprite.x + sprite.halfWidth - this.width / 2;
  29969. this.y = sprite.y + sprite.halfHeight - this.height / 2;
  29970. }
  29971. };
  29972. //Return the `camera` object
  29973. return camera;
  29974. }
  29975. }, {
  29976. key: "lineOfSight",
  29977. /*
  29978. Line of sight
  29979. ------------
  29980. The `lineOfSight` method will return `true` if there’s clear line of sight
  29981. between two sprites, and `false` if there isn’t. Here’s how to use it in your game code:
  29982. monster.lineOfSight = gu.lineOfSight(
  29983. monster, //Sprite one
  29984. alien, //Sprite two
  29985. boxes, //An array of obstacle sprites
  29986. 16 //The distance between each collision point
  29987. );
  29988. The 4th argument determines the distance between collision points.
  29989. For better performance, make this a large number, up to the maximum
  29990. width of your smallest sprite (such as 64 or 32). For greater precision,
  29991. use a smaller number. You can use the lineOfSight value to decide how
  29992. to change certain things in your game. For example:
  29993. if (monster.lineOfSight) {
  29994. monster.show(monster.states.angry)
  29995. } else {
  29996. monster.show(monster.states.normal)
  29997. }
  29998. */
  29999. value: function lineOfSight(s1, //The first sprite, with `centerX` and `centerY` properties
  30000. s2, //The second sprite, with `centerX` and `centerY` properties
  30001. obstacles) //The distance between collision points
  30002. {
  30003. var segment = arguments.length <= 3 || arguments[3] === undefined ? 32 : arguments[3];
  30004. //Calculate the center points of each sprite
  30005. spriteOneCenterX = s1.x + this._getCenter(s1, s1.width, "x");
  30006. spriteOneCenterY = s1.y + this._getCenter(s1, s1.height, "y");
  30007. spriteTwoCenterX = s2.x + this._getCenter(s2, s2.width, "x");
  30008. spriteTwoCenterY = s2.y + this._getCenter(s2, s2.height, "y");
  30009. //Plot a vector between spriteTwo and spriteOne
  30010. var vx = spriteTwoCenterX - spriteOneCenterX,
  30011. vy = spriteTwoCenterY - spriteOneCenterY;
  30012. //Find the vector's magnitude (its length in pixels)
  30013. var magnitude = Math.sqrt(vx * vx + vy * vy);
  30014. //How many points will we need to test?
  30015. var numberOfPoints = magnitude / segment;
  30016. //Create an array of x/y points, separated by 64 pixels, that
  30017. //extends from `spriteOne` to `spriteTwo`
  30018. var points = function points() {
  30019. //Initialize an array that is going to store all our points
  30020. //along the vector
  30021. var arrayOfPoints = [];
  30022. //Create a point object for each segment of the vector and
  30023. //store its x/y position as well as its index number on
  30024. //the map array
  30025. for (var i = 1; i <= numberOfPoints; i++) {
  30026. //Calculate the new magnitude for this iteration of the loop
  30027. var newMagnitude = segment * i;
  30028. //Find the unit vector. This is a small, scaled down version of
  30029. //the vector between the sprites that's less than one pixel long.
  30030. //It points in the same direction as the main vector, but because it's
  30031. //the smallest size that the vector can be, we can use it to create
  30032. //new vectors of varying length
  30033. var dx = vx / magnitude,
  30034. dy = vy / magnitude;
  30035. //Use the unit vector and newMagnitude to figure out the x/y
  30036. //position of the next point in this loop iteration
  30037. var x = spriteOneCenterX + dx * newMagnitude,
  30038. y = spriteOneCenterY + dy * newMagnitude;
  30039. //Push a point object with x and y properties into the `arrayOfPoints`
  30040. arrayOfPoints.push({
  30041. x: x, y: y
  30042. });
  30043. }
  30044. //Return the array of point objects
  30045. return arrayOfPoints;
  30046. };
  30047. //Test for a collision between a point and a sprite
  30048. var hitTestPoint = function hitTestPoint(point, sprite) {
  30049. //Find out if the point's position is inside the area defined
  30050. //by the sprite's left, right, top and bottom sides
  30051. var left = point.x > sprite.x,
  30052. right = point.x < sprite.x + sprite.width,
  30053. top = point.y > sprite.y,
  30054. bottom = point.y < sprite.y + sprite.height;
  30055. //If all the collision conditions are met, you know the
  30056. //point is intersecting the sprite
  30057. return left && right && top && bottom;
  30058. };
  30059. //The `noObstacles` function will return `true` if all the tile
  30060. //index numbers along the vector are `0`, which means they contain
  30061. //no obstacles. If any of them aren't 0, then the function returns
  30062. //`false` which means there's an obstacle in the way
  30063. var noObstacles = points().every(function (point) {
  30064. return obstacles.every(function (obstacle) {
  30065. return !hitTestPoint(point, obstacle);
  30066. });
  30067. });
  30068. //Return the true/false value of the collision test
  30069. return noObstacles;
  30070. }
  30071. }]);
  30072. return GameUtilities;
  30073. })();
  30074. //# sourceMappingURL=gameUtilities.js.map"use strict";
  30075. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  30076. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  30077. var Smoothie = (function () {
  30078. function Smoothie() //Refers to `tileposition` and `tileScale` x and y properties
  30079. {
  30080. var options = arguments.length <= 0 || arguments[0] === undefined ? {
  30081. engine: PIXI, //The rendering engine (Pixi)
  30082. renderer: undefined, //The Pixi renderer you created in your application
  30083. root: undefined, //The root Pixi display object (usually the `stage`)
  30084. update: undefined, //A logic function that should be called every frame of the game loop
  30085. interpolate: true, //A Boolean to turn interpolation on or off
  30086. fps: 60, //The frame rate at which the application's looping logic function should update
  30087. renderFps: undefined, //The frame rate at which sprites should be rendered
  30088. properties: { //Sprite roperties that should be interpolated
  30089. position: true,
  30090. rotation: true,
  30091. size: false,
  30092. scale: false,
  30093. alpha: false,
  30094. tile: false }
  30095. } : arguments[0];
  30096. _classCallCheck(this, Smoothie);
  30097. if (options.engine === undefined) throw new Error("Please assign a rendering engine as Smoothie's engine option");
  30098. //Find out which rendering engine is being used (the default is Pixi)
  30099. this.engine = "";
  30100. //If the `renderingEngine` is Pixi, set up Pixi object aliases
  30101. if (options.engine.ParticleContainer && options.engine.Sprite) {
  30102. this.renderingEngine = "pixi";
  30103. this.Container = options.engine.Container;
  30104. this.Sprite = options.engine.Sprite;
  30105. this.MovieClip = options.engine.extras.MovieClip;
  30106. }
  30107. //Check to make sure the user had supplied a renderer. If you're
  30108. //using Pixi, this should be the instantiated `renderer` object
  30109. //that you created in your main application
  30110. if (options.renderer === undefined) {
  30111. throw new Error("Please assign a renderer object as Smoothie's renderer option");
  30112. } else {
  30113. this.renderer = options.renderer;
  30114. }
  30115. //Check to make sure the user has supplied a root container. This
  30116. //is the object is at the top of the display list heirarchy. If
  30117. //you're using Pixi, it would be a `Container` object, often by
  30118. //convention called the `stage`
  30119. if (options.root === undefined) {
  30120. throw new Error("Please assign a root container object (the stage) as Smoothie's rootr option");
  30121. } else {
  30122. this.stage = options.root;
  30123. }
  30124. if (options.update === undefined) {
  30125. throw new Error("Please assign a function that you want to update on each frame as Smoothie's update option");
  30126. } else {
  30127. this.update = options.update;
  30128. }
  30129. //Define the sprite properties that should be interpolated
  30130. if (options.properties === undefined) {
  30131. this.properties = { position: true, rotation: true };
  30132. } else {
  30133. this.properties = options.properties;
  30134. }
  30135. //The upper-limit frames per second that the game' logic update
  30136. //function should run at.
  30137. //Smoothie defaults to 60 fps.
  30138. if (options.fps !== undefined) {
  30139. this._fps = options.fps;
  30140. } else {
  30141. this._fps = undefined;
  30142. }
  30143. //Optionally Clamp the upper-limit frame rate at which sprites should render
  30144. if (options.renderFps !== undefined) {
  30145. this._renderFps = options.renderFps;
  30146. } else {
  30147. this._renderFps = undefined;
  30148. }
  30149. //Set sprite rendering position interpolation to
  30150. //`true` by default
  30151. if (options.interpolate === false) {
  30152. this.interpolate = false;
  30153. } else {
  30154. this.interpolate = true;
  30155. }
  30156. //A variable that can be used to pause and play Smoothie
  30157. this.paused = false;
  30158. //Private properties used to set the frame rate and figure out the interpolation values
  30159. this._startTime = Date.now();
  30160. this._frameDuration = 1000 / this._fps;
  30161. this._lag = 0;
  30162. this._lagOffset = 0;
  30163. this._renderStartTime = 0;
  30164. if (this._renderFps !== undefined) {
  30165. this._renderDuration = 1000 / this._renderFps;
  30166. }
  30167. }
  30168. //Getters and setters
  30169. //Fps
  30170. _createClass(Smoothie, [{
  30171. key: "pause",
  30172. //Methods to pause and resume Smoothie
  30173. value: function pause() {
  30174. this.paused = true;
  30175. }
  30176. }, {
  30177. key: "resume",
  30178. value: function resume() {
  30179. this.paused = false;
  30180. }
  30181. //The `start` method gets Smoothie's game loop running
  30182. }, {
  30183. key: "start",
  30184. value: function start() {
  30185. //Start the game loop
  30186. this.gameLoop();
  30187. }
  30188. //The core game loop
  30189. }, {
  30190. key: "gameLoop",
  30191. value: function gameLoop(timestamp) {
  30192. var _this = this;
  30193. requestAnimationFrame(this.gameLoop.bind(this));
  30194. //Only run if Smoothie isn't paused
  30195. if (!this.paused) {
  30196. //The `interpolate` function updates the logic function at the
  30197. //same rate as the user-defined fps, renders the sprites, with
  30198. //interpolation, at the maximum frame rate the system is capbale
  30199. //of
  30200. var interpolate = function interpolate() {
  30201. //Calculate the time that has elapsed since the last frame
  30202. var current = Date.now(),
  30203. elapsed = current - _this._startTime;
  30204. //Catch any unexpectedly large frame rate spikes
  30205. if (elapsed > 1000) elapsed = _this._frameDuration;
  30206. //For interpolation:
  30207. _this._startTime = current;
  30208. //Add the elapsed time to the lag counter
  30209. _this._lag += elapsed;
  30210. //Update the frame if the lag counter is greater than or
  30211. //equal to the frame duration
  30212. while (_this._lag >= _this._frameDuration) {
  30213. //Capture the sprites' previous properties for rendering
  30214. //interpolation
  30215. _this.capturePreviousSpriteProperties();
  30216. //Update the logic in the user-defined update function
  30217. _this.update();
  30218. //Reduce the lag counter by the frame duration
  30219. _this._lag -= _this._frameDuration;
  30220. }
  30221. //Calculate the lag offset and use it to render the sprites
  30222. _this._lagOffset = _this._lag / _this._frameDuration;
  30223. _this.render(_this._lagOffset);
  30224. };
  30225. //If the `fps` hasn't been defined, call the user-defined update
  30226. //function and render the sprites at the maximum rate the
  30227. //system is capable of
  30228. if (this._fps === undefined) {
  30229. //Run the user-defined game logic function each frame of the
  30230. //game at the maxium frame rate your system is capable of
  30231. this.update();
  30232. this.render();
  30233. } else {
  30234. if (this._renderFps === undefined) {
  30235. interpolate();
  30236. } else {
  30237. //Implement optional frame rate rendering clamping
  30238. if (timestamp >= this._renderStartTime) {
  30239. //Update the current logic frame and render with
  30240. //interpolation
  30241. interpolate();
  30242. //Reset the frame render start time
  30243. this._renderStartTime = timestamp + this._renderDuration;
  30244. }
  30245. }
  30246. }
  30247. }
  30248. }
  30249. //`capturePreviousSpritePositions`
  30250. //This function is run in the game loop just before the logic update
  30251. //to store all the sprites' previous positions from the last frame.
  30252. //It allows the render function to interpolate the sprite positions
  30253. //for ultra-smooth sprite rendering at any frame rate
  30254. }, {
  30255. key: "capturePreviousSpriteProperties",
  30256. value: function capturePreviousSpriteProperties() {
  30257. var _this2 = this;
  30258. //A function that capture's the sprites properties
  30259. var setProperties = function setProperties(sprite) {
  30260. if (_this2.properties.position) {
  30261. sprite._previousX = sprite.x;
  30262. sprite._previousY = sprite.y;
  30263. }
  30264. if (_this2.properties.rotation) {
  30265. sprite._previousRotation = sprite.rotation;
  30266. }
  30267. if (_this2.properties.size) {
  30268. sprite._previousWidth = sprite.width;
  30269. sprite._previousHeight = sprite.height;
  30270. }
  30271. if (_this2.properties.scale) {
  30272. sprite._previousScaleX = sprite.scale.x;
  30273. sprite._previousScaleY = sprite.scale.y;
  30274. }
  30275. if (_this2.properties.alpha) {
  30276. sprite._previousAlpha = sprite.alpha;
  30277. }
  30278. if (_this2.properties.tile) {
  30279. if (sprite.tilePosition !== undefined) {
  30280. sprite._previousTilePositionX = sprite.tilePosition.x;
  30281. sprite._previousTilePositionY = sprite.tilePosition.y;
  30282. }
  30283. if (sprite.tileScale !== undefined) {
  30284. sprite._previousTileScaleX = sprite.tileScale.x;
  30285. sprite._previousTileScaleY = sprite.tileScale.y;
  30286. }
  30287. }
  30288. if (sprite.children && sprite.children.length > 0) {
  30289. for (var i = 0; i < sprite.children.length; i++) {
  30290. var child = sprite.children[i];
  30291. setProperties(child);
  30292. }
  30293. }
  30294. };
  30295. //loop through the all the sprites and capture their properties
  30296. for (var i = 0; i < this.stage.children.length; i++) {
  30297. var sprite = this.stage.children[i];
  30298. setProperties(sprite);
  30299. }
  30300. }
  30301. //Smoothie's `render` method will interpolate the sprite positions and
  30302. //rotation for
  30303. //ultra-smooth animation, if Hexi's `interpolate` property is `true`
  30304. //(it is by default)
  30305. }, {
  30306. key: "render",
  30307. value: function render() {
  30308. var _this3 = this;
  30309. var lagOffset = arguments.length <= 0 || arguments[0] === undefined ? 1 : arguments[0];
  30310. //Calculate the sprites' interpolated render positions if
  30311. //`this.interpolate` is `true` (It is true by default)
  30312. if (this.interpolate) {
  30313. (function () {
  30314. //A recursive function that does the work of figuring out the
  30315. //interpolated positions
  30316. var interpolateSprite = function interpolateSprite(sprite) {
  30317. //Position (`x` and `y` properties)
  30318. if (_this3.properties.position) {
  30319. //Capture the sprite's current x and y positions
  30320. sprite._currentX = sprite.x;
  30321. sprite._currentY = sprite.y;
  30322. //Figure out its interpolated positions
  30323. if (sprite._previousX !== undefined) {
  30324. sprite.x = (sprite.x - sprite._previousX) * lagOffset + sprite._previousX;
  30325. }
  30326. if (sprite._previousY !== undefined) {
  30327. sprite.y = (sprite.y - sprite._previousY) * lagOffset + sprite._previousY;
  30328. }
  30329. }
  30330. //Rotation (`rotation` property)
  30331. if (_this3.properties.rotation) {
  30332. //Capture the sprite's current rotation
  30333. sprite._currentRotation = sprite.rotation;
  30334. //Figure out its interpolated rotation
  30335. if (sprite._previousRotation !== undefined) {
  30336. sprite.rotation = (sprite.rotation - sprite._previousRotation) * lagOffset + sprite._previousRotation;
  30337. }
  30338. }
  30339. //Size (`width` and `height` properties)
  30340. if (_this3.properties.size) {
  30341. //Only allow this for Sprites or MovieClips. Because
  30342. //Containers vary in size when the sprites they contain
  30343. //move, the interpolation will cause them to scale erraticly
  30344. if (sprite instanceof _this3.Sprite || sprite instanceof _this3.MovieClip) {
  30345. //Capture the sprite's current size
  30346. sprite._currentWidth = sprite.width;
  30347. sprite._currentHeight = sprite.height;
  30348. //Figure out the sprite's interpolated size
  30349. if (sprite._previousWidth !== undefined) {
  30350. sprite.width = (sprite.width - sprite._previousWidth) * lagOffset + sprite._previousWidth;
  30351. }
  30352. if (sprite._previousHeight !== undefined) {
  30353. sprite.height = (sprite.height - sprite._previousHeight) * lagOffset + sprite._previousHeight;
  30354. }
  30355. }
  30356. }
  30357. //Scale (`scale.x` and `scale.y` properties)
  30358. if (_this3.properties.scale) {
  30359. //Capture the sprite's current scale
  30360. sprite._currentScaleX = sprite.scale.x;
  30361. sprite._currentScaleY = sprite.scale.y;
  30362. //Figure out the sprite's interpolated scale
  30363. if (sprite._previousScaleX !== undefined) {
  30364. sprite.scale.x = (sprite.scale.x - sprite._previousScaleX) * lagOffset + sprite._previousScaleX;
  30365. }
  30366. if (sprite._previousScaleY !== undefined) {
  30367. sprite.scale.y = (sprite.scale.y - sprite._previousScaleY) * lagOffset + sprite._previousScaleY;
  30368. }
  30369. }
  30370. //Alpha (`alpha` property)
  30371. if (_this3.properties.alpha) {
  30372. //Capture the sprite's current alpha
  30373. sprite._currentAlpha = sprite.alpha;
  30374. //Figure out its interpolated alpha
  30375. if (sprite._previousAlpha !== undefined) {
  30376. sprite.alpha = (sprite.alpha - sprite._previousAlpha) * lagOffset + sprite._previousAlpha;
  30377. }
  30378. }
  30379. //Tiling sprite properties (`tileposition` and `tileScale` x
  30380. //and y values)
  30381. if (_this3.properties.tile) {
  30382. //`tilePosition.x` and `tilePosition.y`
  30383. if (sprite.tilePosition !== undefined) {
  30384. //Capture the sprite's current tile x and y positions
  30385. sprite._currentTilePositionX = sprite.tilePosition.x;
  30386. sprite._currentTilePositionY = sprite.tilePosition.y;
  30387. //Figure out its interpolated positions
  30388. if (sprite._previousTilePositionX !== undefined) {
  30389. sprite.tilePosition.x = (sprite.tilePosition.x - sprite._previousTilePositionX) * lagOffset + sprite._previousTilePositionX;
  30390. }
  30391. if (sprite._previousTilePositionY !== undefined) {
  30392. sprite.tilePosition.y = (sprite.tilePosition.y - sprite._previousTilePositionY) * lagOffset + sprite._previousTilePositionY;
  30393. }
  30394. }
  30395. //`tileScale.x` and `tileScale.y`
  30396. if (sprite.tileScale !== undefined) {
  30397. //Capture the sprite's current tile scale
  30398. sprite._currentTileScaleX = sprite.tileScale.x;
  30399. sprite._currentTileScaleY = sprite.tileScale.y;
  30400. //Figure out the sprite's interpolated scale
  30401. if (sprite._previousTileScaleX !== undefined) {
  30402. sprite.tileScale.x = (sprite.tileScale.x - sprite._previousTileScaleX) * lagOffset + sprite._previousTileScaleX;
  30403. }
  30404. if (sprite._previousTileScaleY !== undefined) {
  30405. sprite.tileScale.y = (sprite.tileScale.y - sprite._previousTileScaleY) * lagOffset + sprite._previousTileScaleY;
  30406. }
  30407. }
  30408. }
  30409. //Interpolate the sprite's children, if it has any
  30410. if (sprite.children.length !== 0) {
  30411. for (var j = 0; j < sprite.children.length; j++) {
  30412. //Find the sprite's child
  30413. var child = sprite.children[j];
  30414. //display the child
  30415. interpolateSprite(child);
  30416. }
  30417. }
  30418. };
  30419. //loop through the all the sprites and interpolate them
  30420. for (var i = 0; i < _this3.stage.children.length; i++) {
  30421. var sprite = _this3.stage.children[i];
  30422. interpolateSprite(sprite);
  30423. }
  30424. })();
  30425. }
  30426. //Render the stage. If the sprite positions have been
  30427. //interpolated, those position values will be used to render the
  30428. //sprite
  30429. this.renderer.render(this.stage);
  30430. //Restore the sprites' original x and y values if they've been
  30431. //interpolated for this frame
  30432. if (this.interpolate) {
  30433. (function () {
  30434. //A recursive function that restores the sprite's original,
  30435. //uninterpolated x and y positions
  30436. var restoreSpriteProperties = function restoreSpriteProperties(sprite) {
  30437. if (_this3.properties.position) {
  30438. sprite.x = sprite._currentX;
  30439. sprite.y = sprite._currentY;
  30440. }
  30441. if (_this3.properties.rotation) {
  30442. sprite.rotation = sprite._currentRotation;
  30443. }
  30444. if (_this3.properties.size) {
  30445. //Only allow this for Sprites or Movie clips, to prevent
  30446. //Container scaling bug
  30447. if (sprite instanceof _this3.Sprite || sprite instanceof _this3.MovieClip) {
  30448. sprite.width = sprite._currentWidth;
  30449. sprite.height = sprite._currentHeight;
  30450. }
  30451. }
  30452. if (_this3.properties.scale) {
  30453. sprite.scale.x = sprite._currentScaleX;
  30454. sprite.scale.y = sprite._currentScaleY;
  30455. }
  30456. if (_this3.properties.alpha) {
  30457. sprite.alpha = sprite._currentAlpha;
  30458. }
  30459. if (_this3.properties.tile) {
  30460. if (sprite.tilePosition !== undefined) {
  30461. sprite.tilePosition.x = sprite._currentTilePositionX;
  30462. sprite.tilePosition.y = sprite._currentTilePositionY;
  30463. }
  30464. if (sprite.tileScale !== undefined) {
  30465. sprite.tileScale.x = sprite._currentTileScaleX;
  30466. sprite.tileScale.y = sprite._currentTileScaleY;
  30467. }
  30468. }
  30469. //Restore the sprite's children, if it has any
  30470. if (sprite.children.length !== 0) {
  30471. for (var i = 0; i < sprite.children.length; i++) {
  30472. //Find the sprite's child
  30473. var child = sprite.children[i];
  30474. //Restore the child sprite properties
  30475. restoreSpriteProperties(child);
  30476. }
  30477. }
  30478. };
  30479. for (var i = 0; i < _this3.stage.children.length; i++) {
  30480. var sprite = _this3.stage.children[i];
  30481. restoreSpriteProperties(sprite);
  30482. }
  30483. })();
  30484. }
  30485. }
  30486. }, {
  30487. key: "fps",
  30488. get: function get() {
  30489. return this._fps;
  30490. },
  30491. set: function set(value) {
  30492. this._fps = value;
  30493. this._frameDuration = 1000 / this._fps;
  30494. }
  30495. //renderFps
  30496. }, {
  30497. key: "renderFps",
  30498. get: function get() {
  30499. return this._renderFps;
  30500. },
  30501. set: function set(value) {
  30502. this._renderFps = value;
  30503. this._renderDuration = 1000 / this._renderFps;
  30504. }
  30505. //`dt` (Delta time, the `this._lagOffset` value in Smoothie's code)
  30506. }, {
  30507. key: "dt",
  30508. get: function get() {
  30509. return this._lagOffset;
  30510. }
  30511. }]);
  30512. return Smoothie;
  30513. })();
  30514. //# sourceMappingURL=smoothie.js.map"use strict";
  30515. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  30516. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  30517. var TileUtilities = (function () {
  30518. function TileUtilities() {
  30519. var renderingEngine = arguments.length <= 0 || arguments[0] === undefined ? PIXI : arguments[0];
  30520. _classCallCheck(this, TileUtilities);
  30521. if (renderingEngine === undefined) throw new Error("Please assign a rendering engine in the constructor before using bump.js");
  30522. //Find out which rendering engine is being used (the default is Pixi)
  30523. this.renderer = "";
  30524. //If the `renderingEngine` is Pixi, set up Pixi object aliases
  30525. if (renderingEngine.ParticleContainer && renderingEngine.Sprite) {
  30526. this.renderingEngine = renderingEngine;
  30527. this.renderer = "pixi";
  30528. this.Container = this.renderingEngine.Container;
  30529. this.TextureCache = this.renderingEngine.utils.TextureCache;
  30530. this.Texture = this.renderingEngine.Texture;
  30531. this.Sprite = this.renderingEngine.Sprite;
  30532. this.Rectangle = this.renderingEngine.Rectangle;
  30533. this.Graphics = this.renderingEngine.Graphics;
  30534. this.loader = this.renderingEngine.loader;
  30535. this.resources = this.renderingEngine.loader.resources;
  30536. }
  30537. }
  30538. //Make a texture from a frame in another texture or image
  30539. _createClass(TileUtilities, [{
  30540. key: "frame",
  30541. value: function frame(source, x, y, width, height) {
  30542. var texture = undefined,
  30543. imageFrame = undefined;
  30544. //If the source is a string, it's either a texture in the
  30545. //cache or an image file
  30546. if (typeof source === "string") {
  30547. if (this.TextureCache[source]) {
  30548. texture = new this.Texture(this.TextureCache[source]);
  30549. }
  30550. }
  30551. //If the `source` is a texture, use it
  30552. else if (source instanceof this.Texture) {
  30553. texture = new this.Texture(source);
  30554. }
  30555. if (!texture) {
  30556. throw new Error("Please load the " + source + " texture into the cache.");
  30557. } else {
  30558. //Make a rectangle the size of the sub-image
  30559. imageFrame = new this.Rectangle(x, y, width, height);
  30560. texture.frame = imageFrame;
  30561. return texture;
  30562. }
  30563. }
  30564. //#### getIndex
  30565. //The `getIndex` helper method
  30566. //converts a sprite's x and y position to an array index number.
  30567. //It returns a single index value that tells you the map array
  30568. //index number that the sprite is in
  30569. }, {
  30570. key: "getIndex",
  30571. value: function getIndex(x, y, tilewidth, tileheight, mapWidthInTiles) {
  30572. var index = {};
  30573. //Convert pixel coordinates to map index coordinates
  30574. index.x = Math.floor(x / tilewidth);
  30575. index.y = Math.floor(y / tileheight);
  30576. //Return the index number
  30577. return index.x + index.y * mapWidthInTiles;
  30578. }
  30579. /*
  30580. #### getTile
  30581. The `getTile` helper method
  30582. converts a tile's index number into x/y screen
  30583. coordinates, and capture's the tile's grid index (`gid`) number.
  30584. It returns an object with `x`, `y`, `centerX`, `centerY`, `width`, `height`, `halfWidth`
  30585. `halffHeight` and `gid` properties. (The `gid` number is the value that the tile has in the
  30586. mapArray) This lets you use the returned object
  30587. with the 2d geometric collision functions like `hitTestRectangle`
  30588. or `rectangleCollision`
  30589. The `world` object requires these properties:
  30590. `x`, `y`, `tilewidth`, `tileheight` and `widthInTiles`
  30591. */
  30592. }, {
  30593. key: "getTile",
  30594. value: function getTile(index, mapArray, world) {
  30595. var tile = {};
  30596. tile.gid = mapArray[index];
  30597. tile.width = world.tilewidth;
  30598. tile.height = world.tileheight;
  30599. tile.halfWidth = world.tilewidth / 2;
  30600. tile.halfHeight = world.tileheight / 2;
  30601. tile.x = index % world.widthInTiles * world.tilewidth + world.x;
  30602. tile.y = Math.floor(index / world.widthInTiles) * world.tileheight + world.y;
  30603. tile.gx = tile.x;
  30604. tile.gy = tile.y;
  30605. tile.centerX = tile.x + world.tilewidth / 2;
  30606. tile.centery = tile.y + world.tileheight / 2;
  30607. //Return the tile object
  30608. return tile;
  30609. }
  30610. /*
  30611. #### surroundingCells
  30612. The `surroundingCells` helper method returns an array containing 9
  30613. index numbers of map array cells around any given index number.
  30614. Use it for an efficient broadphase/narrowphase collision test.
  30615. The 2 arguments are the index number that represents the center cell,
  30616. and the width of the map array.
  30617. */
  30618. }, {
  30619. key: "surroundingCells",
  30620. value: function surroundingCells(index, widthInTiles) {
  30621. return [index - widthInTiles - 1, index - widthInTiles, index - widthInTiles + 1, index - 1, index, index + 1, index + widthInTiles - 1, index + widthInTiles, index + widthInTiles + 1];
  30622. }
  30623. //#### getPoints
  30624. /*
  30625. The `getPoints` method takes a sprite and returns
  30626. an object that tells you what all its corner points are. The return
  30627. object has four properties, each of which is an object with `x` and `y` properties:
  30628. - `topLeft`: `x` and `y` properties describing the top left corner
  30629. point.
  30630. - `topRight`: `x` and `y` properties describing the top right corner
  30631. point.
  30632. - `bottomLeft`: `x` and `y` properties describing the bottom left corner
  30633. point.
  30634. - `bottomRight`: `x` and `y` properties describing the bottom right corner
  30635. point.
  30636. If the sprite has a `collisionArea` property that defines a
  30637. smaller rectangular area inside the sprite, that collision
  30638. area can be used instead for collisions instead of the sprite's dimensions. Here's
  30639. How you could define a `collsionArea` on a sprite called `elf`:
  30640. ```js
  30641. elf.collisionArea = {x: 22, y: 44, width: 20, height: 20};
  30642. ```
  30643. Here's how you could use the `getPoints` method to find all the collision area's corner points.
  30644. ```js
  30645. let cornerPoints = tu.getPoints(elf.collisionArea);
  30646. ```
  30647. */
  30648. }, {
  30649. key: "getPoints",
  30650. value: function getPoints(s) {
  30651. var ca = s.collisionArea;
  30652. if (ca !== undefined) {
  30653. return {
  30654. topLeft: {
  30655. x: s.x + ca.x,
  30656. y: s.y + ca.y
  30657. },
  30658. topRight: {
  30659. x: s.x + ca.x + ca.width,
  30660. y: s.y + ca.y
  30661. },
  30662. bottomLeft: {
  30663. x: s.x + ca.x,
  30664. y: s.y + ca.y + ca.height
  30665. },
  30666. bottomRight: {
  30667. x: s.x + ca.x + ca.width,
  30668. y: s.y + ca.y + ca.height
  30669. }
  30670. };
  30671. } else {
  30672. return {
  30673. topLeft: {
  30674. x: s.x,
  30675. y: s.y
  30676. },
  30677. topRight: {
  30678. x: s.x + s.width - 1,
  30679. y: s.y
  30680. },
  30681. bottomLeft: {
  30682. x: s.x,
  30683. y: s.y + s.height - 1
  30684. },
  30685. bottomRight: {
  30686. x: s.x + s.width - 1,
  30687. y: s.y + s.height - 1
  30688. }
  30689. };
  30690. }
  30691. }
  30692. //### hitTestTile
  30693. /*
  30694. `hitTestTile` checks for a
  30695. collision between a sprite and a tile in any map array that you
  30696. specify. It returns a `collision` object.
  30697. `collision.hit` is a Boolean that tells you if a sprite is colliding
  30698. with the tile that you're checking. `collision.index` tells you the
  30699. map array's index number of the colliding sprite. You can check for
  30700. a collision with the tile against "every" corner point on the
  30701. sprite, "some" corner points, or the sprite's "center" point.
  30702. `hitTestTile` arguments:
  30703. sprite, array, collisionTileGridIdNumber, worldObject, spritesPointsToCheck
  30704. ```js
  30705. tu.hitTestTile(sprite, array, collisioGid, world, pointsToCheck);
  30706. ```
  30707. The `world` object (the 4th argument) has to have these properties:
  30708. `tileheight`, `tilewidth`, `widthInTiles`.
  30709. Here's how you could use `hitTestTile` to check for a collision between a sprite
  30710. called `alien` and an array of wall sprites with map gid numbers of 0.
  30711. ```js
  30712. let alienVsFloor = g.hitTestTile(alien, wallMapArray, 0, world, "every");
  30713. ```
  30714. */
  30715. }, {
  30716. key: "hitTestTile",
  30717. value: function hitTestTile(sprite, mapArray, gidToCheck, world, pointsToCheck) {
  30718. var _this = this;
  30719. //The `checkPoints` helper function Loop through the sprite's corner points to
  30720. //find out if they are inside an array cell that you're interested in.
  30721. //Return `true` if they are
  30722. var checkPoints = function checkPoints(key) {
  30723. //Get a reference to the current point to check.
  30724. //(`topLeft`, `topRight`, `bottomLeft` or `bottomRight` )
  30725. var point = sprite.collisionPoints[key];
  30726. //Find the point's index number in the map array
  30727. collision.index = _this.getIndex(point.x, point.y, world.tilewidth, world.tileheight, world.widthInTiles);
  30728. //Find out what the gid value is in the map position
  30729. //that the point is currently over
  30730. collision.gid = mapArray[collision.index];
  30731. //If it matches the value of the gid that we're interested, in
  30732. //then there's been a collision
  30733. if (collision.gid === gidToCheck) {
  30734. return true;
  30735. } else {
  30736. return false;
  30737. }
  30738. };
  30739. //Assign "some" as the default value for `pointsToCheck`
  30740. pointsToCheck = pointsToCheck || "some";
  30741. //The collision object that will be returned by this function
  30742. var collision = {};
  30743. //Which points do you want to check?
  30744. //"every", "some" or "center"?
  30745. switch (pointsToCheck) {
  30746. case "center":
  30747. //`hit` will be true only if the center point is touching
  30748. var point = {
  30749. center: {
  30750. x: sprite.centerX,
  30751. y: sprite.centerY
  30752. }
  30753. };
  30754. sprite.collisionPoints = point;
  30755. collision.hit = Object.keys(sprite.collisionPoints).some(checkPoints);
  30756. break;
  30757. case "every":
  30758. //`hit` will be true if every point is touching
  30759. sprite.collisionPoints = this.getPoints(sprite);
  30760. collision.hit = Object.keys(sprite.collisionPoints).every(checkPoints);
  30761. break;
  30762. case "some":
  30763. //`hit` will be true only if some points are touching
  30764. sprite.collisionPoints = this.getPoints(sprite);
  30765. collision.hit = Object.keys(sprite.collisionPoints).some(checkPoints);
  30766. break;
  30767. }
  30768. //Return the collision object.
  30769. //`collision.hit` will be true if a collision is detected.
  30770. //`collision.index` tells you the map array index number where the
  30771. //collision occured
  30772. return collision;
  30773. }
  30774. //### updateMap
  30775. /*
  30776. `updateMap` takes a map array and adds a sprite's grid index number (`gid`) to it.
  30777. It finds the sprite's new index position, and retuns the new map array.
  30778. You can use it to do very efficient collision detection in tile based game worlds.
  30779. `updateMap` arguments:
  30780. array, singleSpriteOrArrayOfSprites, worldObject
  30781. The `world` object (the 4th argument) has to have these properties:
  30782. `tileheight`, `tilewidth`, `widthInTiles`.
  30783. The sprite objects have to have have these properties:
  30784. `centerX`, `centerY`, `index`, `gid` (The number in the array that represpents the sprite)
  30785. Here's an example of how you could use `updateMap` in your game code like this:
  30786. blockLayer.data = updateMap(blockLayer.data, blockLayer.children, world);
  30787. The `blockLayer.data` array would now contain the new index position numbers of all the
  30788. child sprites on that layer.
  30789. */
  30790. }, {
  30791. key: "updateMap",
  30792. value: function updateMap(mapArray, spritesToUpdate, world) {
  30793. var _this2 = this;
  30794. //First create a map a new array filled with zeros.
  30795. //The new map array will be exactly the same size as the original
  30796. var newMapArray = mapArray.map(function (gid) {
  30797. gid = 0;
  30798. return gid;
  30799. });
  30800. //Is `spriteToUpdate` an array of sprites?
  30801. if (spritesToUpdate instanceof Array) {
  30802. (function () {
  30803. //Get the index number of each sprite in the `spritesToUpdate` array
  30804. //and add the sprite's `gid` to the matching index on the map
  30805. var self = _this2;
  30806. spritesToUpdate.forEach(function (sprite) {
  30807. //Find the new index number
  30808. sprite.index = self.getIndex(sprite.centerX, sprite.centerY, world.tilewidth, world.tileheight, world.widthInTiles);
  30809. //Add the sprite's `gid` number to the correct index on the map
  30810. newMapArray[sprite.index] = sprite.gid;
  30811. });
  30812. })();
  30813. }
  30814. //Is `spritesToUpdate` just a single sprite?
  30815. else {
  30816. var sprite = spritesToUpdate;
  30817. //Find the new index number
  30818. sprite.index = this.getIndex(sprite.centerX, sprite.centerY, world.tilewidth, world.tileheight, world.widthInTiles);
  30819. //Add the sprite's `gid` number to the correct index on the map
  30820. newMapArray[sprite.index] = sprite.gid;
  30821. }
  30822. //Return the new map array to replace the previous one
  30823. return newMapArray;
  30824. }
  30825. /*
  30826. ###makeTiledWorld
  30827. `makeTiledWorld` is a quick and easy way to display a game world designed in
  30828. Tiled Editor. Supply `makeTiledWorld` with 2 **string arguments**:
  30829. 1. A JSON file generated by Tiled Editor.
  30830. 2. A source image that represents the tile set you used to create the Tiled Editor world.
  30831. ```js
  30832. let world = makeTiledWorld("tiledEditorMapData.json", "tileset.png");
  30833. ```
  30834. (Note: `makeTiledWorld` looks for the JSON data file in Pixi's `loader.resources` object. So,
  30835. make sure you've loaded the JSON file using Pixi's `loader`.)
  30836. `makeTiledWorld` will return a Pixi `Container` that contains all the things in your Tiled Editor
  30837. map as Pixi sprites.
  30838. All the image tiles you create in Tiled Editor are automatically converted into Pixi sprites
  30839. for you by `makeTiledWorld`. You can access all of them using two methods: `getObject` (for
  30840. single sprites) and `getObjects` (with an "s") for multiple sprites. Let's find out how they work.
  30841. ####world.getObject
  30842. Tile Editor lets you assign a "name" properties any object.
  30843. You can access any sprite by this name using the `getObject` method. `getObject` searches for and
  30844. returns a sprite in the `world` that has the same `name` property that you assigned
  30845. in Tiled Editor. Here's how to use `getObject` to look for an object called "alien"
  30846. in the Tiled map data and assign it to a variable called `alien`
  30847. ```js
  30848. let alien = world.getObject("alien");
  30849. ```
  30850. `alien` is now an ordinary Pixi sprite that you can control just like any other Pixi
  30851. sprite in your games.
  30852. #### Creating sprites from generic objects
  30853. Tiled Editor lets you create generic objects. These are objects that don't have images associated
  30854. with them. Generic objects are handy to use, because they let you create complex game objects inside
  30855. Tiled Editor, as pure data. You can then use that data your game code to build complex game objects.
  30856. For example, imagine that you want to create a complex animated walking sprite called "elf".
  30857. First, create the elf object in Tiled Editor as a generic object, but don't assign any image tiles
  30858. to it. Next, in your game code, create a new Pixi MovieClip called `elf` and give it any textures you want
  30859. to use for its animation states.
  30860. ```js
  30861. //Create a new Pixi MovieClip sprite
  30862. let elf = new PIXI.MovieClip(elfSpriteTextures);
  30863. ```
  30864. Then use the `x` and `y` data from the generic "elf" object you created in Tiled Editor to position the
  30865. `elf` sprite.
  30866. ```js
  30867. elf.x = world.getObject("elf").x;
  30868. elf.y = world.getObject("elf").y;
  30869. ```
  30870. This is a simple example, but you could make very complex data objects in Tiled Editor and
  30871. use them to build complex sprites in the same way.
  30872. ####Accessing Tiled Editor layer groups
  30873. Tiled Editor lets you create **layer groups**. Each layer group you create
  30874. in Tiled Editor is automatically converted by `makeTiledWorld` into a Pixi `Container`
  30875. object. You can access those containers using `getObject` to extract the layer group
  30876. container.
  30877. Here's how you could extract the layer group called "objects" and add the
  30878. `elf` sprite to it.
  30879. ```js
  30880. let objectsLayer = world.getObject("objects");
  30881. objectsLayer.addChild(elf);
  30882. ```
  30883. If you want to add the sprite to a different world layer, you can do it like this:
  30884. ```js
  30885. world.getObject("treeTops").addChild(elf);
  30886. ```
  30887. If you want to access all the sprites in a specific Tiled Editor layer, just supply
  30888. `getObject` with the name of the layer. For example, if the layer name is "items", you
  30889. can access it like this:
  30890. ```js
  30891. let itemsLayer = world.getObject("items");
  30892. ```
  30893. `itemsLayer` is now a Pixi container with a `children` array that contains all the sprites
  30894. on that layer.
  30895. To be safe, clone this array to create a new version
  30896. that doesn't point to the original data file:
  30897. ```js
  30898. items = itemsLayer.children.slice(0);
  30899. ```
  30900. You can now manipulate the `items` array freely without worrying about changing
  30901. the original array. This can possibly help prevent some weird bugs in a complex game.
  30902. ###Finding the "gid" values
  30903. Tiled Editor uses "gid" numbers to identify different kinds of things in the world.
  30904. If you ever need to extract sprites with specific `gid` numbers in a
  30905. layer that contains different kinds of things, you can do it like this:
  30906. ```js
  30907. let items = itemsLayer.children.map(sprite => {
  30908. if (sprite.gid !== 0) return sprite;
  30909. });
  30910. ```
  30911. Every sprite created by `makeTiledWorld` has a `gid` property with a value that matches its
  30912. Tiled Editor "gid" value.
  30913. ####Accessing a layer's "data" array
  30914. Tiled Editor's layers have a `data` property
  30915. that is an array containing all the grid index numbers (`gid`) of
  30916. the tiles in that array. Imagine that you've got a layer full of similar
  30917. tiles representing the walls in a game. How do you access the array
  30918. containing all the "gid" numbers of the wall sprites in that layer? If the layer's name is called "wallLayer", you
  30919. can access the `wallLayer`'s `data` array of sprites like this:
  30920. ```js
  30921. wallMapArray = world.getObject("wallLayer").data;
  30922. ```
  30923. `wallMapArray` is now an array of "gid" numbers referring to all the sprites on that
  30924. layer. You can now use this data for collision detection, or doing any other kind
  30925. of world building.
  30926. ###world.getObjects
  30927. There's another method called `getObjects` (with an "s"!) that lets you extract
  30928. an array of sprites from the Tiled Editor data. Imagine that you created three
  30929. game objects in Tiled Editor called "marmot", "skull" and "heart". `makeTiledWorld`
  30930. automatically turns them into sprites, and you can access
  30931. all of them as array of sprites using `getObjects` like this:
  30932. ```js
  30933. let gameItemsArray = world.getObjects("marmot", "skull", "heart");
  30934. ```
  30935. */
  30936. }, {
  30937. key: "makeTiledWorld",
  30938. value: function makeTiledWorld(jsonTiledMap, tileset) {
  30939. var _this3 = this;
  30940. //Create a group called `world` to contain all the layers, sprites
  30941. //and objects from the `tiledMap`. The `world` object is going to be
  30942. //returned to the main game program
  30943. var tiledMap = PIXI.loader.resources[jsonTiledMap].data;
  30944. var world = new this.Container();
  30945. world.tileheight = tiledMap.tileheight;
  30946. world.tilewidth = tiledMap.tilewidth;
  30947. //Calculate the `width` and `height` of the world, in pixels
  30948. world.worldWidth = tiledMap.width * tiledMap.tilewidth;
  30949. world.worldHeight = tiledMap.height * tiledMap.tileheight;
  30950. //Get a reference to the world's height and width in
  30951. //tiles, in case you need to know this later (you will!)
  30952. world.widthInTiles = tiledMap.width;
  30953. world.heightInTiles = tiledMap.height;
  30954. //Create an `objects` array to store references to any
  30955. //named objects in the map. Named objects all have
  30956. //a `name` property that was assigned in Tiled Editor
  30957. world.objects = [];
  30958. //The optional spacing (padding) around each tile
  30959. //This is to account for spacing around tiles
  30960. //that's commonly used with texture atlas tilesets. Set the
  30961. //`spacing` property when you create a new map in Tiled Editor
  30962. var spacing = tiledMap.tilesets[0].spacing;
  30963. //Figure out how many columns there are on the tileset.
  30964. //This is the width of the image, divided by the width
  30965. //of each tile, plus any optional spacing thats around each tile
  30966. var numberOfTilesetColumns = Math.floor(tiledMap.tilesets[0].imagewidth / (tiledMap.tilewidth + spacing));
  30967. //Loop through all the map layers
  30968. tiledMap.layers.forEach(function (tiledLayer) {
  30969. //Make a group for this layer and copy
  30970. //all of the layer properties onto it.
  30971. var layerGroup = new _this3.Container();
  30972. Object.keys(tiledLayer).forEach(function (key) {
  30973. //Add all the layer's properties to the group, except the
  30974. //width and height (because the group will work those our for
  30975. //itself based on its content).
  30976. if (key !== "width" && key !== "height") {
  30977. layerGroup[key] = tiledLayer[key];
  30978. }
  30979. });
  30980. //Set the width and height of the layer to
  30981. //the `world`'s width and height
  30982. //layerGroup.width = world.width;
  30983. //layerGroup.height = world.height;
  30984. //Translate `opacity` to `alpha`
  30985. layerGroup.alpha = tiledLayer.opacity;
  30986. //Add the group to the `world`
  30987. world.addChild(layerGroup);
  30988. //Push the group into the world's `objects` array
  30989. //So you can access it later
  30990. world.objects.push(layerGroup);
  30991. //Is this current layer a `tilelayer`?
  30992. if (tiledLayer.type === "tilelayer") {
  30993. //Loop through the `data` array of this layer
  30994. tiledLayer.data.forEach(function (gid, index) {
  30995. var tileSprite = undefined,
  30996. texture = undefined,
  30997. mapX = undefined,
  30998. mapY = undefined,
  30999. tilesetX = undefined,
  31000. tilesetY = undefined,
  31001. mapColumn = undefined,
  31002. mapRow = undefined,
  31003. tilesetColumn = undefined,
  31004. tilesetRow = undefined;
  31005. //If the grid id number (`gid`) isn't zero, create a sprite
  31006. if (gid !== 0) {
  31007. (function () {
  31008. //Figure out the map column and row number that we're on, and then
  31009. //calculate the grid cell's x and y pixel position.
  31010. mapColumn = index % world.widthInTiles;
  31011. mapRow = Math.floor(index / world.widthInTiles);
  31012. mapX = mapColumn * world.tilewidth;
  31013. mapY = mapRow * world.tileheight;
  31014. //Figure out the column and row number that the tileset
  31015. //image is on, and then use those values to calculate
  31016. //the x and y pixel position of the image on the tileset
  31017. tilesetColumn = (gid - 1) % numberOfTilesetColumns;
  31018. tilesetRow = Math.floor((gid - 1) / numberOfTilesetColumns);
  31019. tilesetX = tilesetColumn * world.tilewidth;
  31020. tilesetY = tilesetRow * world.tileheight;
  31021. //Compensate for any optional spacing (padding) around the tiles if
  31022. //there is any. This bit of code accumlates the spacing offsets from the
  31023. //left side of the tileset and adds them to the current tile's position
  31024. if (spacing > 0) {
  31025. tilesetX += spacing + spacing * ((gid - 1) % numberOfTilesetColumns);
  31026. tilesetY += spacing + spacing * Math.floor((gid - 1) / numberOfTilesetColumns);
  31027. }
  31028. //Use the above values to create the sprite's image from
  31029. //the tileset image
  31030. texture = _this3.frame(tileset, tilesetX, tilesetY, world.tilewidth, world.tileheight);
  31031. //I've dedcided that any tiles that have a `name` property are important
  31032. //and should be accessible in the `world.objects` array.
  31033. var tileproperties = tiledMap.tilesets[0].tileproperties,
  31034. key = String(gid - 1);
  31035. //If the JSON `tileproperties` object has a sub-object that
  31036. //matches the current tile, and that sub-object has a `name` property,
  31037. //then create a sprite and assign the tile properties onto
  31038. //the sprite
  31039. if (tileproperties[key] && tileproperties[key].name) {
  31040. //Make a sprite
  31041. tileSprite = new _this3.Sprite(texture);
  31042. //Copy all of the tile's properties onto the sprite
  31043. //(This includes the `name` property)
  31044. Object.keys(tileproperties[key]).forEach(function (property) {
  31045. //console.log(tileproperties[key][property])
  31046. tileSprite[property] = tileproperties[key][property];
  31047. });
  31048. //Push the sprite into the world's `objects` array
  31049. //so that you can access it by `name` later
  31050. world.objects.push(tileSprite);
  31051. }
  31052. //If the tile doesn't have a `name` property, just use it to
  31053. //create an ordinary sprite (it will only need one texture)
  31054. else {
  31055. tileSprite = new _this3.Sprite(texture);
  31056. }
  31057. //Position the sprite on the map
  31058. tileSprite.x = mapX;
  31059. tileSprite.y = mapY;
  31060. //Make a record of the sprite's index number in the array
  31061. //(We'll use this for collision detection later)
  31062. tileSprite.index = index;
  31063. //Make a record of the sprite's `gid` on the tileset.
  31064. //This will also be useful for collision detection later
  31065. tileSprite.gid = gid;
  31066. //Add the sprite to the current layer group
  31067. layerGroup.addChild(tileSprite);
  31068. })();
  31069. }
  31070. });
  31071. }
  31072. //Is this layer an `objectgroup`?
  31073. if (tiledLayer.type === "objectgroup") {
  31074. tiledLayer.objects.forEach(function (object) {
  31075. //We're just going to capture the object's properties
  31076. //so that we can decide what to do with it later
  31077. //Get a reference to the layer group the object is in
  31078. object.group = layerGroup;
  31079. //Because this is an object layer, it doesn't contain any
  31080. //sprites, just data object. That means it won't be able to
  31081. //calucalte its own height and width. To help it out, give
  31082. //the `layerGroup` the same `width` and `height` as the `world`
  31083. //layerGroup.width = world.width;
  31084. //layerGroup.height = world.height;
  31085. //Push the object into the world's `objects` array
  31086. world.objects.push(object);
  31087. });
  31088. }
  31089. });
  31090. //Search functions
  31091. //`world.getObject` and `world.getObjects` search for and return
  31092. //any sprites or objects in the `world.objects` array.
  31093. //Any object that has a `name` propery in
  31094. //Tiled Editor will show up in a search.
  31095. //`getObject` gives you a single object, `getObjects` gives you an array
  31096. //of objects.
  31097. //`getObject` returns the actual search function, so you
  31098. //can use the following format to directly access a single object:
  31099. //sprite.x = world.getObject("anySprite").x;
  31100. //sprite.y = world.getObject("anySprite").y;
  31101. world.getObject = function (objectName) {
  31102. var searchForObject = function searchForObject() {
  31103. var foundObject = undefined;
  31104. world.objects.some(function (object) {
  31105. if (object.name && object.name === objectName) {
  31106. foundObject = object;
  31107. return true;
  31108. }
  31109. });
  31110. if (foundObject) {
  31111. return foundObject;
  31112. } else {
  31113. throw new Error("There is no object with the property name: " + objectName);
  31114. }
  31115. };
  31116. //Return the search function
  31117. return searchForObject();
  31118. };
  31119. world.getObjects = function (objectNames) {
  31120. var foundObjects = [];
  31121. world.objects.forEach(function (object) {
  31122. if (object.name && objectNames.indexOf(object.name) !== -1) {
  31123. foundObjects.push(object);
  31124. }
  31125. });
  31126. if (foundObjects.length > 0) {
  31127. return foundObjects;
  31128. } else {
  31129. throw new Error("I could not find those objects");
  31130. }
  31131. return foundObjects;
  31132. };
  31133. //That's it, we're done!
  31134. //Finally, return the `world` object back to the game program
  31135. return world;
  31136. }
  31137. /* Isometric tile utilities */
  31138. /*
  31139. ### byDepth
  31140. And array `sort` function that depth-sorts sprites according to
  31141. their `z` properties
  31142. */
  31143. }, {
  31144. key: "byDepth",
  31145. value: function byDepth(a, b) {
  31146. //Calculate the depths of `a` and `b`
  31147. //(add `1` to `a.z` and `b.x` to avoid multiplying by 0)
  31148. a.depth = (a.cartX + a.cartY) * (a.z + 1);
  31149. b.depth = (b.cartX + b.cartY) * (b.z + 1);
  31150. //Move sprites with a lower depth to a higher position in the array
  31151. if (a.depth < b.depth) {
  31152. return -1;
  31153. } else if (a.depth > b.depth) {
  31154. return 1;
  31155. } else {
  31156. return 0;
  31157. }
  31158. }
  31159. /*
  31160. ### hitTestIsoTile
  31161. Same API as `hitTestTile`, except that it works with isometric sprites.
  31162. Make sure that your `world` object has properties called
  31163. `cartTileWidth` and `cartTileHeight` that define the Cartesian with and
  31164. height of your tile cells, in pixels.
  31165. */
  31166. }, {
  31167. key: "hitTestIsoTile",
  31168. value: function hitTestIsoTile(sprite, mapArray, gidToCheck, world, pointsToCheck) {
  31169. var _this4 = this;
  31170. //The `checkPoints` helper function Loop through the sprite's corner points to
  31171. //find out if they are inside an array cell that you're interested in.
  31172. //Return `true` if they are
  31173. var checkPoints = function checkPoints(key) {
  31174. //Get a reference to the current point to check.
  31175. //(`topLeft`, `topRight`, `bottomLeft` or `bottomRight` )
  31176. var point = sprite.collisionPoints[key];
  31177. //Find the point's index number in the map array
  31178. collision.index = _this4.getIndex(point.x, point.y, world.cartTilewidth, world.cartTileheight, world.widthInTiles);
  31179. //Find out what the gid value is in the map position
  31180. //that the point is currently over
  31181. collision.gid = mapArray[collision.index];
  31182. //If it matches the value of the gid that we're interested, in
  31183. //then there's been a collision
  31184. if (collision.gid === gidToCheck) {
  31185. return true;
  31186. } else {
  31187. return false;
  31188. }
  31189. };
  31190. //Assign "some" as the default value for `pointsToCheck`
  31191. pointsToCheck = pointsToCheck || "some";
  31192. //The collision object that will be returned by this function
  31193. var collision = {};
  31194. //Which points do you want to check?
  31195. //"every", "some" or "center"?
  31196. switch (pointsToCheck) {
  31197. case "center":
  31198. //`hit` will be true only if the center point is touching
  31199. var point = {
  31200. center: {
  31201. //x: sprite.centerX,
  31202. //y: sprite.centerY
  31203. x: s.cartX + ca.x + ca.width / 2,
  31204. y: s.cartY + ca.y + ca.height / 2
  31205. }
  31206. };
  31207. sprite.collisionPoints = point;
  31208. collision.hit = Object.keys(sprite.collisionPoints).some(checkPoints);
  31209. break;
  31210. case "every":
  31211. //`hit` will be true if every point is touching
  31212. sprite.collisionPoints = this.getIsoPoints(sprite);
  31213. collision.hit = Object.keys(sprite.collisionPoints).every(checkPoints);
  31214. break;
  31215. case "some":
  31216. //`hit` will be true only if some points are touching
  31217. sprite.collisionPoints = this.getIsoPoints(sprite);
  31218. collision.hit = Object.keys(sprite.collisionPoints).some(checkPoints);
  31219. break;
  31220. }
  31221. //Return the collision object.
  31222. //`collision.hit` will be true if a collision is detected.
  31223. //`collision.index` tells you the map array index number where the
  31224. //collision occured
  31225. return collision;
  31226. }
  31227. /*
  31228. ### getIsoPoints
  31229. The isomertic version of `getPoints`
  31230. */
  31231. }, {
  31232. key: "getIsoPoints",
  31233. value: function getIsoPoints(s) {
  31234. var ca = s.collisionArea;
  31235. if (ca !== undefined) {
  31236. return {
  31237. topLeft: {
  31238. x: s.cartX + ca.x,
  31239. y: s.cartY + ca.y
  31240. },
  31241. topRight: {
  31242. x: s.cartX + ca.x + ca.width,
  31243. y: s.cartY + ca.y
  31244. },
  31245. bottomLeft: {
  31246. x: s.cartX + ca.x,
  31247. y: s.cartY + ca.y + ca.height
  31248. },
  31249. bottomRight: {
  31250. x: s.cartX + ca.x + ca.width,
  31251. y: s.cartY + ca.y + ca.height
  31252. }
  31253. };
  31254. } else {
  31255. return {
  31256. topLeft: {
  31257. x: s.cartX,
  31258. y: s.cartY
  31259. },
  31260. topRight: {
  31261. x: s.cartX + s.cartWidth - 1,
  31262. y: s.cartY
  31263. },
  31264. bottomLeft: {
  31265. x: s.cartX,
  31266. y: s.cartY + s.cartHeight - 1
  31267. },
  31268. bottomRight: {
  31269. x: s.cartX + s.cartWidth - 1,
  31270. y: s.cartY + s.cartHeight - 1
  31271. }
  31272. };
  31273. }
  31274. }
  31275. /*
  31276. ### makeIsoPointer
  31277. Used to add a isometric properties to any mouse/touch `pointer` object with
  31278. `x` and `y` properties. Supply `makeIsoPointer` with the pointer object and
  31279. the isometric `world` object
  31280. */
  31281. //Create some useful properties on the pointer
  31282. }, {
  31283. key: "makeIsoPointer",
  31284. value: function makeIsoPointer(pointer, world) {
  31285. Object.defineProperties(pointer, {
  31286. //The isometric's world's Cartesian coordiantes
  31287. cartX: {
  31288. get: function get() {
  31289. var x = (2 * this.y + this.x - (2 * world.y + world.x)) / 2 - world.cartTilewidth / 2;
  31290. return x;
  31291. },
  31292. enumerable: true,
  31293. configurable: true
  31294. },
  31295. cartY: {
  31296. get: function get() {
  31297. var y = (2 * this.y - this.x - (2 * world.y - world.x)) / 2 + world.cartTileheight / 2;
  31298. return y;
  31299. },
  31300. enumerable: true,
  31301. configurable: true
  31302. },
  31303. //The tile's column and row in the array
  31304. column: {
  31305. get: function get() {
  31306. return Math.floor(this.cartX / world.cartTilewidth);
  31307. },
  31308. enumerable: true,
  31309. configurable: true
  31310. },
  31311. row: {
  31312. get: function get() {
  31313. return Math.floor(this.cartY / world.cartTileheight);
  31314. },
  31315. enumerable: true,
  31316. configurable: true
  31317. },
  31318. //The tile's index number in the array
  31319. index: {
  31320. get: function get() {
  31321. var index = {};
  31322. //Convert pixel coordinates to map index coordinates
  31323. index.x = Math.floor(this.cartX / world.cartTilewidth);
  31324. index.y = Math.floor(this.cartY / world.cartTileheight);
  31325. //Return the index number
  31326. return index.x + index.y * world.widthInTiles;
  31327. },
  31328. enumerable: true,
  31329. configurable: true
  31330. }
  31331. });
  31332. }
  31333. /*
  31334. ### isoRectangle
  31335. A function for creating a simple isometric diamond
  31336. shaped rectangle using Pixi's graphics library
  31337. */
  31338. }, {
  31339. key: "isoRectangle",
  31340. value: function isoRectangle(width, height, fillStyle) {
  31341. //Figure out the `halfHeight` value
  31342. var halfHeight = height / 2;
  31343. //Draw the flattened and rotated square (diamond shape)
  31344. var rectangle = new this.Graphics();
  31345. rectangle.beginFill(fillStyle);
  31346. rectangle.moveTo(0, 0);
  31347. rectangle.lineTo(width, halfHeight);
  31348. rectangle.lineTo(0, height);
  31349. rectangle.lineTo(-width, halfHeight);
  31350. rectangle.lineTo(0, 0);
  31351. rectangle.endFill();
  31352. //Generate a texture from the rectangle
  31353. var texture = rectangle.generateTexture();
  31354. //Use the texture to create a sprite
  31355. var sprite = new this.Sprite(texture);
  31356. //Return it to the main program
  31357. return sprite;
  31358. }
  31359. /*
  31360. ### addIsoProperties
  31361. Add properties to a sprite to help work between Cartesian
  31362. and isometric properties: `isoX`, `isoY`, `cartX`,
  31363. `cartWidth` and `cartHeight`.
  31364. */
  31365. }, {
  31366. key: "addIsoProperties",
  31367. value: function addIsoProperties(sprite, x, y, width, height) {
  31368. //Cartisian (flat 2D) properties
  31369. sprite.cartX = x;
  31370. sprite.cartY = y;
  31371. sprite.cartWidth = width;
  31372. sprite.cartHeight = height;
  31373. //Add a getter/setter for the isometric properties
  31374. Object.defineProperties(sprite, {
  31375. isoX: {
  31376. get: function get() {
  31377. return this.cartX - this.cartY;
  31378. },
  31379. enumerable: true,
  31380. configurable: true
  31381. },
  31382. isoY: {
  31383. get: function get() {
  31384. return (this.cartX + this.cartY) / 2;
  31385. },
  31386. enumerable: true,
  31387. configurable: true
  31388. }
  31389. });
  31390. }
  31391. /*
  31392. ### makeIsoTiledWorld
  31393. Make an isometric world from TiledEditor map data. Uses the same API as `makeTiledWorld`
  31394. */
  31395. }, {
  31396. key: "makeIsoTiledWorld",
  31397. value: function makeIsoTiledWorld(jsonTiledMap, tileset) {
  31398. var _this5 = this;
  31399. //Create a group called `world` to contain all the layers, sprites
  31400. //and objects from the `tiledMap`. The `world` object is going to be
  31401. //returned to the main game program
  31402. var tiledMap = PIXI.loader.resources[jsonTiledMap].data;
  31403. //A. You need to add three custom properties to your Tiled Editor
  31404. //map: `cartTilewidth`,`cartTileheight` and `tileDepth`. They define the Cartesian
  31405. //dimesions of the tiles (32x32x64).
  31406. //Check to make sure that these custom properties exist
  31407. if (!tiledMap.properties.cartTilewidth && !tiledMap.properties.cartTileheight && !tiledMao.properties.tileDepth) {
  31408. throw new Error("Set custom cartTilewidth, cartTileheight and tileDepth map properties in Tiled Editor");
  31409. }
  31410. //Create the `world` container
  31411. var world = new this.Container();
  31412. //B. Set the `tileHeight` to the `tiledMap`'s `tileDepth` property
  31413. //so that it matches the pixel height of the sprite tile image
  31414. world.tileheight = parseInt(tiledMap.properties.tileDepth);
  31415. world.tilewidth = tiledMap.tilewidth;
  31416. //C. Define the Cartesian dimesions of each tile
  31417. world.cartTileheight = parseInt(tiledMap.properties.cartTileheight);
  31418. world.cartTilewidth = parseInt(tiledMap.properties.cartTilewidth);
  31419. //D. Calculate the `width` and `height` of the world, in pixels
  31420. //using the `world.cartTileHeight` and `world.cartTilewidth`
  31421. //values
  31422. world.worldWidth = tiledMap.width * world.cartTilewidth;
  31423. world.worldHeight = tiledMap.height * world.cartTileheight;
  31424. //Get a reference to the world's height and width in
  31425. //tiles, in case you need to know this later (you will!)
  31426. world.widthInTiles = tiledMap.width;
  31427. world.heightInTiles = tiledMap.height;
  31428. //Create an `objects` array to store references to any
  31429. //named objects in the map. Named objects all have
  31430. //a `name` property that was assigned in Tiled Editor
  31431. world.objects = [];
  31432. //The optional spacing (padding) around each tile
  31433. //This is to account for spacing around tiles
  31434. //that's commonly used with texture atlas tilesets. Set the
  31435. //`spacing` property when you create a new map in Tiled Editor
  31436. var spacing = tiledMap.tilesets[0].spacing;
  31437. //Figure out how many columns there are on the tileset.
  31438. //This is the width of the image, divided by the width
  31439. //of each tile, plus any optional spacing thats around each tile
  31440. var numberOfTilesetColumns = Math.floor(tiledMap.tilesets[0].imagewidth / (tiledMap.tilewidth + spacing));
  31441. //E. A `z` property to help track which depth level the sprites are on
  31442. var z = 0;
  31443. //Loop through all the map layers
  31444. tiledMap.layers.forEach(function (tiledLayer) {
  31445. //Make a group for this layer and copy
  31446. //all of the layer properties onto it.
  31447. var layerGroup = new _this5.Container();
  31448. Object.keys(tiledLayer).forEach(function (key) {
  31449. //Add all the layer's properties to the group, except the
  31450. //width and height (because the group will work those our for
  31451. //itself based on its content).
  31452. if (key !== "width" && key !== "height") {
  31453. layerGroup[key] = tiledLayer[key];
  31454. }
  31455. });
  31456. //Translate `opacity` to `alpha`
  31457. layerGroup.alpha = tiledLayer.opacity;
  31458. //Add the group to the `world`
  31459. world.addChild(layerGroup);
  31460. //Push the group into the world's `objects` array
  31461. //So you can access it later
  31462. world.objects.push(layerGroup);
  31463. //Is this current layer a `tilelayer`?
  31464. if (tiledLayer.type === "tilelayer") {
  31465. //Loop through the `data` array of this layer
  31466. tiledLayer.data.forEach(function (gid, index) {
  31467. var tileSprite = undefined,
  31468. texture = undefined,
  31469. mapX = undefined,
  31470. mapY = undefined,
  31471. tilesetX = undefined,
  31472. tilesetY = undefined,
  31473. mapColumn = undefined,
  31474. mapRow = undefined,
  31475. tilesetColumn = undefined,
  31476. tilesetRow = undefined;
  31477. //If the grid id number (`gid`) isn't zero, create a sprite
  31478. if (gid !== 0) {
  31479. (function () {
  31480. //Figure out the map column and row number that we're on, and then
  31481. //calculate the grid cell's x and y pixel position.
  31482. mapColumn = index % world.widthInTiles;
  31483. mapRow = Math.floor(index / world.widthInTiles);
  31484. //F. Use the Cartesian values to find the
  31485. //`mapX` and `mapY` values
  31486. mapX = mapColumn * world.cartTilewidth;
  31487. mapY = mapRow * world.cartTileheight;
  31488. //Figure out the column and row number that the tileset
  31489. //image is on, and then use those values to calculate
  31490. //the x and y pixel position of the image on the tileset
  31491. tilesetColumn = (gid - 1) % numberOfTilesetColumns;
  31492. tilesetRow = Math.floor((gid - 1) / numberOfTilesetColumns);
  31493. tilesetX = tilesetColumn * world.tilewidth;
  31494. tilesetY = tilesetRow * world.tileheight;
  31495. //Compensate for any optional spacing (padding) around the tiles if
  31496. //there is any. This bit of code accumlates the spacing offsets from the
  31497. //left side of the tileset and adds them to the current tile's position
  31498. if (spacing > 0) {
  31499. tilesetX += spacing + spacing * ((gid - 1) % numberOfTilesetColumns);
  31500. tilesetY += spacing + spacing * Math.floor((gid - 1) / numberOfTilesetColumns);
  31501. }
  31502. //Use the above values to create the sprite's image from
  31503. //the tileset image
  31504. texture = _this5.frame(tileset, tilesetX, tilesetY, world.tilewidth, world.tileheight);
  31505. //I've dedcided that any tiles that have a `name` property are important
  31506. //and should be accessible in the `world.objects` array.
  31507. var tileproperties = tiledMap.tilesets[0].tileproperties,
  31508. key = String(gid - 1);
  31509. //If the JSON `tileproperties` object has a sub-object that
  31510. //matches the current tile, and that sub-object has a `name` property,
  31511. //then create a sprite and assign the tile properties onto
  31512. //the sprite
  31513. if (tileproperties[key] && tileproperties[key].name) {
  31514. //Make a sprite
  31515. tileSprite = new _this5.Sprite(texture);
  31516. //Copy all of the tile's properties onto the sprite
  31517. //(This includes the `name` property)
  31518. Object.keys(tileproperties[key]).forEach(function (property) {
  31519. //console.log(tileproperties[key][property])
  31520. tileSprite[property] = tileproperties[key][property];
  31521. });
  31522. //Push the sprite into the world's `objects` array
  31523. //so that you can access it by `name` later
  31524. world.objects.push(tileSprite);
  31525. }
  31526. //If the tile doesn't have a `name` property, just use it to
  31527. //create an ordinary sprite (it will only need one texture)
  31528. else {
  31529. tileSprite = new _this5.Sprite(texture);
  31530. }
  31531. //G. Add isometric properties to the sprite
  31532. _this5.addIsoProperties(tileSprite, mapX, mapY, world.cartTilewidth, world.cartTileheight);
  31533. //H. Use the isometric position to add the sprite to the world
  31534. tileSprite.x = tileSprite.isoX;
  31535. tileSprite.y = tileSprite.isoY;
  31536. tileSprite.z = z;
  31537. //Make a record of the sprite's index number in the array
  31538. //(We'll use this for collision detection later)
  31539. tileSprite.index = index;
  31540. //Make a record of the sprite's `gid` on the tileset.
  31541. //This will also be useful for collision detection later
  31542. tileSprite.gid = gid;
  31543. //Add the sprite to the current layer group
  31544. layerGroup.addChild(tileSprite);
  31545. })();
  31546. }
  31547. });
  31548. }
  31549. //Is this layer an `objectgroup`?
  31550. if (tiledLayer.type === "objectgroup") {
  31551. tiledLayer.objects.forEach(function (object) {
  31552. //We're just going to capture the object's properties
  31553. //so that we can decide what to do with it later
  31554. //Get a reference to the layer group the object is in
  31555. object.group = layerGroup;
  31556. //Push the object into the world's `objects` array
  31557. world.objects.push(object);
  31558. });
  31559. }
  31560. //I. Add 1 to the z index (the first layer will have a z index of `1`)
  31561. z += 1;
  31562. });
  31563. //Search functions
  31564. //`world.getObject` and `world.getObjects` search for and return
  31565. //any sprites or objects in the `world.objects` array.
  31566. //Any object that has a `name` propery in
  31567. //Tiled Editor will show up in a search.
  31568. //`getObject` gives you a single object, `getObjects` gives you an array
  31569. //of objects.
  31570. //`getObject` returns the actual search function, so you
  31571. //can use the following format to directly access a single object:
  31572. //sprite.x = world.getObject("anySprite").x;
  31573. //sprite.y = world.getObject("anySprite").y;
  31574. world.getObject = function (objectName) {
  31575. var searchForObject = function searchForObject() {
  31576. var foundObject = undefined;
  31577. world.objects.some(function (object) {
  31578. if (object.name && object.name === objectName) {
  31579. foundObject = object;
  31580. return true;
  31581. }
  31582. });
  31583. if (foundObject) {
  31584. return foundObject;
  31585. } else {
  31586. throw new Error("There is no object with the property name: " + objectName);
  31587. }
  31588. };
  31589. //Return the search function
  31590. return searchForObject();
  31591. };
  31592. world.getObjects = function (objectNames) {
  31593. var foundObjects = [];
  31594. world.objects.forEach(function (object) {
  31595. if (object.name && objectNames.indexOf(object.name) !== -1) {
  31596. foundObjects.push(object);
  31597. }
  31598. });
  31599. if (foundObjects.length > 0) {
  31600. return foundObjects;
  31601. } else {
  31602. throw new Error("I could not find those objects");
  31603. }
  31604. return foundObjects;
  31605. };
  31606. //That's it, we're done!
  31607. //Finally, return the `world` object back to the game program
  31608. return world;
  31609. }
  31610. /*
  31611. //### The `shortestPath` function
  31612. An A-Star search algorithm that returns an array of grid index numbers that
  31613. represent the shortest path between two points on a map. Use it like this:
  31614. let shortestPath = tu.shortestPath(
  31615. startIndex, //The start map index
  31616. destinationIndex, //The destination index
  31617. mapArray, //The map array
  31618. mapWidthInTiles, //Map wdith, in tiles
  31619. [1,2], //Obstacle gid array
  31620. "manhattan" //Heuristic to use: "manhatten", "euclidean" or "diagonal"
  31621. );
  31622. */
  31623. }, {
  31624. key: "shortestPath",
  31625. value: function shortestPath(startIndex, destinationIndex, mapArray, mapWidthInTiles) {
  31626. var obstacleGids = arguments.length <= 4 || arguments[4] === undefined ? [] : arguments[4];
  31627. var heuristic = arguments.length <= 5 || arguments[5] === undefined ? "manhattan" : arguments[5];
  31628. var useDiagonalNodes = arguments.length <= 6 || arguments[6] === undefined ? true : arguments[6];
  31629. //The `nodes` function creates the array of node objects
  31630. var nodes = function nodes(mapArray, mapWidthInTiles) {
  31631. return mapArray.map(function (cell, index) {
  31632. //Figure out the row and column of this cell
  31633. var column = index % mapWidthInTiles;
  31634. var row = Math.floor(index / mapWidthInTiles);
  31635. //The node object
  31636. return node = {
  31637. f: 0,
  31638. g: 0,
  31639. h: 0,
  31640. parent: null,
  31641. column: column,
  31642. row: row,
  31643. index: index
  31644. };
  31645. });
  31646. };
  31647. //Initialize theShortestPath array
  31648. var theShortestPath = [];
  31649. //Initialize the node map
  31650. var nodeMap = nodes(mapArray, mapWidthInTiles);
  31651. //Initialize the closed and open list arrays
  31652. var closedList = [];
  31653. var openList = [];
  31654. //Declare the "costs" of travelling in straight or
  31655. //diagonal lines
  31656. var straightCost = 10;
  31657. var diagonalCost = 14;
  31658. //Get the start node
  31659. var startNode = nodeMap[startIndex];
  31660. //Get the current center node. The first one will
  31661. //match the path's start position
  31662. var centerNode = startNode;
  31663. //Push the `centerNode` into the `openList`, because
  31664. //it's the first node that we're going to check
  31665. openList.push(centerNode);
  31666. //Get the current destination node. The first one will
  31667. //match the path's end position
  31668. var destinationNode = nodeMap[destinationIndex];
  31669. //All the nodes that are surrounding the current map index number
  31670. var surroundingNodes = function surroundingNodes(index, mapArray, mapWidthInTiles, useDiagonalNodes) {
  31671. //Find out what all the surrounding nodes are, including those that
  31672. //might be beyond the borders of the map
  31673. var allSurroundingNodes = [nodeMap[index - mapWidthInTiles - 1], nodeMap[index - mapWidthInTiles], nodeMap[index - mapWidthInTiles + 1], nodeMap[index - 1], nodeMap[index + 1], nodeMap[index + mapWidthInTiles - 1], nodeMap[index + mapWidthInTiles], nodeMap[index + mapWidthInTiles + 1]];
  31674. //Optionaly exlude the diagonal nodes, which is often perferable
  31675. //for 2D maze games
  31676. var crossSurroundingNodes = [nodeMap[index - mapWidthInTiles], nodeMap[index - 1], nodeMap[index + 1], nodeMap[index + mapWidthInTiles]];
  31677. //Use either `allSurroundingNodes` or `crossSurroundingNodes` depending
  31678. //on the the value of `useDiagonalNodes`
  31679. var nodesToCheck = undefined;
  31680. if (useDiagonalNodes) {
  31681. nodesToCheck = allSurroundingNodes;
  31682. } else {
  31683. nodesToCheck = crossSurroundingNodes;
  31684. }
  31685. //Find the valid sourrounding nodes, which are ones inside
  31686. //the map border that don't incldue obstacles. Change `allSurroundingNodes`
  31687. //to `crossSurroundingNodes` to prevent the path from choosing diagonal routes
  31688. var validSurroundingNodes = nodesToCheck.filter(function (node) {
  31689. //The node will be beyond the top and bottom edges of the
  31690. //map if it is `undefined`
  31691. var nodeIsWithinTopAndBottomBounds = node !== undefined;
  31692. //Only return nodes that are within the top and bottom map bounds
  31693. if (nodeIsWithinTopAndBottomBounds) {
  31694. //Some Boolean values that tell us whether the current map index is on
  31695. //the left or right border of the map, and whether any of the nodes
  31696. //surrounding that index extend beyond the left and right borders
  31697. var indexIsOnLeftBorder = index % mapWidthInTiles === 0;
  31698. var indexIsOnRightBorder = (index + 1) % mapWidthInTiles === 0;
  31699. var nodeIsBeyondLeftBorder = node.column % (mapWidthInTiles - 1) === 0 && node.column !== 0;
  31700. var nodeIsBeyondRightBorder = node.column % mapWidthInTiles === 0;
  31701. //Find out whether of not the node contains an obstacle by looping
  31702. //through the obstacle gids and and returning `true` if it
  31703. //finds any at this node's location
  31704. var nodeContainsAnObstacle = obstacleGids.some(function (obstacle) {
  31705. return mapArray[node.index] === obstacle;
  31706. });
  31707. //If the index is on the left border and any nodes surrounding it are beyond the
  31708. //left border, don't return that node
  31709. if (indexIsOnLeftBorder) {
  31710. //console.log("left border")
  31711. return !nodeIsBeyondLeftBorder;
  31712. }
  31713. //If the index is on the right border and any nodes surrounding it are beyond the
  31714. //right border, don't return that node
  31715. else if (indexIsOnRightBorder) {
  31716. //console.log("right border")
  31717. return !nodeIsBeyondRightBorder;
  31718. }
  31719. //Return `true` if the node doesn't contain any obstacles
  31720. else if (nodeContainsAnObstacle) {
  31721. return false;
  31722. }
  31723. //The index must be inside the area defined by the left and right borders,
  31724. //so return the node
  31725. else {
  31726. //console.log("map interior")
  31727. return true;
  31728. }
  31729. }
  31730. });
  31731. //console.log(validSurroundingNodes)
  31732. //Return the array of `validSurroundingNodes`
  31733. return validSurroundingNodes;
  31734. };
  31735. //Diagnostic
  31736. //console.log(nodeMap);
  31737. //console.log(centerNode);
  31738. //console.log(destinationNode);
  31739. //console.log(wallMapArray);
  31740. //console.log(surroundingNodes(86, mapArray, mapWidthInTiles));
  31741. //Heuristic methods
  31742. //1. Manhattan
  31743. var manhattan = function manhattan(testNode, destinationNode) {
  31744. var h = Math.abs(testNode.row - destinationNode.row) * straightCost + Math.abs(testNode.column - destinationNode.column) * straightCost;
  31745. return h;
  31746. };
  31747. //2. Euclidean
  31748. var euclidean = function euclidean(testNode, destinationNode) {
  31749. var vx = destinationNode.column - testNode.column,
  31750. vy = destinationNode.row - testNode.row,
  31751. h = Math.floor(Math.sqrt(vx * vx + vy * vy) * straightCost);
  31752. return h;
  31753. };
  31754. //3. Diagonal
  31755. var diagonal = function diagonal(testNode, destinationNode) {
  31756. var vx = Math.abs(destinationNode.column - testNode.column),
  31757. vy = Math.abs(destinationNode.row - testNode.row),
  31758. h = 0;
  31759. if (vx > vy) {
  31760. h = Math.floor(diagonalCost * vy + straightCost * (vx - vy));
  31761. } else {
  31762. h = Math.floor(diagonalCost * vx + straightCost * (vy - vx));
  31763. }
  31764. return h;
  31765. };
  31766. //Loop through all the nodes until the current `centerNode` matches the
  31767. //`destinationNode`. When they they're the same we know we've reached the
  31768. //end of the path
  31769. while (centerNode !== destinationNode) {
  31770. //Find all the nodes surrounding the current `centerNode`
  31771. var surroundingTestNodes = surroundingNodes(centerNode.index, mapArray, mapWidthInTiles, useDiagonalNodes);
  31772. //Loop through all the `surroundingTestNodes` using a classic `for` loop
  31773. //(A `for` loop gives us a marginal performance boost)
  31774. var _loop = function _loop(i) {
  31775. //Get a reference to the current test node
  31776. var testNode = surroundingTestNodes[i];
  31777. //Find out whether the node is on a straight axis or
  31778. //a diagonal axis, and assign the appropriate cost
  31779. //A. Declare the cost variable
  31780. var cost = 0;
  31781. //B. Do they occupy the same row or column?
  31782. if (centerNode.row === testNode.row || centerNode.column === testNode.column) {
  31783. //If they do, assign a cost of "10"
  31784. cost = straightCost;
  31785. } else {
  31786. //Otherwise, assign a cost of "14"
  31787. cost = diagonalCost;
  31788. }
  31789. //C. Calculate the costs (g, h and f)
  31790. //The node's current cost
  31791. var g = centerNode.g + cost;
  31792. //The cost of travelling from this node to the
  31793. //destination node (the heuristic)
  31794. var h = undefined;
  31795. switch (heuristic) {
  31796. case "manhattan":
  31797. h = manhattan(testNode, destinationNode);
  31798. break;
  31799. case "euclidean":
  31800. h = euclidean(testNode, destinationNode);
  31801. break;
  31802. case "diagonal":
  31803. h = diagonal(testNode, destinationNode);
  31804. break;
  31805. default:
  31806. throw new Error("Oops! It looks like you misspelled the name of the heuristic");
  31807. }
  31808. //The final cost
  31809. var f = g + h;
  31810. //Find out if the testNode is in either
  31811. //the openList or closedList array
  31812. var isOnOpenList = openList.some(function (node) {
  31813. return testNode === node;
  31814. });
  31815. var isOnClosedList = closedList.some(function (node) {
  31816. return testNode === node;
  31817. });
  31818. //If it's on either of these lists, we can check
  31819. //whether this route is a lower-cost alternative
  31820. //to the previous cost calculation. The new G cost
  31821. //will make the difference to the final F cost
  31822. if (isOnOpenList || isOnClosedList) {
  31823. if (testNode.f > f) {
  31824. testNode.f = f;
  31825. testNode.g = g;
  31826. testNode.h = h;
  31827. //Only change the parent if the new cost is lower
  31828. testNode.parent = centerNode;
  31829. }
  31830. }
  31831. //Otherwise, add the testNode to the open list
  31832. else {
  31833. testNode.f = f;
  31834. testNode.g = g;
  31835. testNode.h = h;
  31836. testNode.parent = centerNode;
  31837. openList.push(testNode);
  31838. }
  31839. //The `for` loop ends here
  31840. };
  31841. for (var i = 0; i < surroundingTestNodes.length; i++) {
  31842. _loop(i);
  31843. }
  31844. //Push the current centerNode into the closed list
  31845. closedList.push(centerNode);
  31846. //Quit the loop if there's nothing on the open list.
  31847. //This means that there is no path to the destination or the
  31848. //destination is invalid, like a wall tile
  31849. if (openList.length === 0) {
  31850. return theShortestPath;
  31851. }
  31852. //Sort the open list according to final cost
  31853. openList = openList.sort(function (a, b) {
  31854. return a.f - b.f;
  31855. });
  31856. //Set the node with the lowest final cost as the new centerNode
  31857. centerNode = openList.shift();
  31858. //The `while` loop ends here
  31859. }
  31860. //Now that we have all the candidates, let's find the shortest path!
  31861. if (openList.length !== 0) {
  31862. //Start with the destination node
  31863. var _testNode = destinationNode;
  31864. theShortestPath.push(_testNode);
  31865. //Work backwards through the node parents
  31866. //until the start node is found
  31867. while (_testNode !== startNode) {
  31868. //Step through the parents of each node,
  31869. //starting with the destination node and ending with the start node
  31870. _testNode = _testNode.parent;
  31871. //Add the node to the beginning of the array
  31872. theShortestPath.unshift(_testNode);
  31873. //...and then loop again to the next node's parent till you
  31874. //reach the end of the path
  31875. }
  31876. }
  31877. //Return an array of nodes that link together to form
  31878. //the shortest path
  31879. return theShortestPath;
  31880. }
  31881. /*
  31882. ### tileBasedLineOfSight
  31883. Use the `tileBasedLineOfSight` function to find out whether two sprites
  31884. are visible to each other inside a tile based maze environment.
  31885. */
  31886. }, {
  31887. key: "tileBasedLineOfSight",
  31888. value: function tileBasedLineOfSight(spriteOne, //The first sprite, with `centerX` and `centerY` properties
  31889. spriteTwo, //The second sprite, with `centerX` and `centerY` properties
  31890. mapArray, //The tile map array
  31891. world) //An array of angles to which you want to
  31892. //restrict the line of sight
  31893. {
  31894. var emptyGid = arguments.length <= 4 || arguments[4] === undefined ? 0 : arguments[4];
  31895. var _this6 = this;
  31896. var segment = arguments.length <= 5 || arguments[5] === undefined ? 32 : arguments[5];
  31897. var angles = arguments.length <= 6 || arguments[6] === undefined ? [] : arguments[6];
  31898. //Plot a vector between spriteTwo and spriteOne
  31899. var vx = spriteTwo.centerX - spriteOne.centerX,
  31900. vy = spriteTwo.centerY - spriteOne.centerY;
  31901. //Find the vector's magnitude (its length in pixels)
  31902. var magnitude = Math.sqrt(vx * vx + vy * vy);
  31903. //How many points will we need to test?
  31904. var numberOfPoints = magnitude / segment;
  31905. //Create an array of x/y points that
  31906. //extends from `spriteOne` to `spriteTwo`
  31907. var points = function points() {
  31908. //Initialize an array that is going to store all our points
  31909. //along the vector
  31910. var arrayOfPoints = [];
  31911. //Create a point object for each segment of the vector and
  31912. //store its x/y position as well as its index number on
  31913. //the map array
  31914. for (var i = 1; i <= numberOfPoints; i++) {
  31915. //Calculate the new magnitude for this iteration of the loop
  31916. var newMagnitude = segment * i;
  31917. //Find the unit vector
  31918. var dx = vx / magnitude,
  31919. dy = vy / magnitude;
  31920. //Use the unit vector and newMagnitude to figure out the x/y
  31921. //position of the next point in this loop iteration
  31922. var x = spriteOne.centerX + dx * newMagnitude,
  31923. y = spriteOne.centerY + dy * newMagnitude;
  31924. //The getIndex function converts x/y coordinates into
  31925. //map array index positon numbers
  31926. var getIndex = function getIndex(x, y, tilewidth, tileheight, mapWidthInTiles) {
  31927. //Convert pixel coordinates to map index coordinates
  31928. var index = {};
  31929. index.x = Math.floor(x / tilewidth);
  31930. index.y = Math.floor(y / tileheight);
  31931. //Return the index number
  31932. return index.x + index.y * mapWidthInTiles;
  31933. };
  31934. //Find the map index number that this x and y point corresponds to
  31935. var index = _this6.getIndex(x, y, world.tilewidth, world.tileheight, world.widthInTiles);
  31936. //Push the point into the `arrayOfPoints`
  31937. arrayOfPoints.push({
  31938. x: x, y: y, index: index
  31939. });
  31940. }
  31941. //Return the array
  31942. return arrayOfPoints;
  31943. };
  31944. //The tile-based collision test.
  31945. //The `noObstacles` function will return `true` if all the tile
  31946. //index numbers along the vector are `0`, which means they contain
  31947. //no walls. If any of them aren't 0, then the function returns
  31948. //`false` which means there's a wall in the way
  31949. var noObstacles = points().every(function (point) {
  31950. return mapArray[point.index] === emptyGid;
  31951. });
  31952. //Restrict the line of sight to right angles only (we don't want to
  31953. //use diagonals)
  31954. var validAngle = function validAngle() {
  31955. //Find the angle of the vector between the two sprites
  31956. var angle = Math.atan2(vy, vx) * 180 / Math.PI;
  31957. //If the angle matches one of the valid angles, return
  31958. //`true`, otherwise return `false`
  31959. if (angles.length !== 0) {
  31960. return angles.some(function (x) {
  31961. return x === angle;
  31962. });
  31963. } else {
  31964. return true;
  31965. }
  31966. };
  31967. //Return `true` if there are no obstacles and the line of sight
  31968. //is at a 90 degree angle
  31969. if (noObstacles === true && validAngle() === true) {
  31970. return true;
  31971. } else {
  31972. return false;
  31973. }
  31974. }
  31975. /*
  31976. surroundingCrossCells
  31977. ---------------------
  31978. Returns an array of index numbers matching the cells that are orthogonally
  31979. adjacent to the center `index` cell
  31980. */
  31981. }, {
  31982. key: "surroundingCrossCells",
  31983. value: function surroundingCrossCells(index, widthInTiles) {
  31984. return [index - widthInTiles, index - 1, index + 1, index + widthInTiles];
  31985. }
  31986. /*
  31987. surroundingDiagonalCells
  31988. ---------------------
  31989. Returns an array of index numbers matching the cells that touch the
  31990. 4 corners of the center the center `index` cell
  31991. */
  31992. }, {
  31993. key: "surroundingDiagonalCells",
  31994. value: function surroundingDiagonalCells(index, widthInTiles) {
  31995. return [index - widthInTiles - 1, index - widthInTiles + 1, index + widthInTiles - 1, index + widthInTiles + 1];
  31996. }
  31997. /*
  31998. validDirections
  31999. ---------------
  32000. Returns an array with the values "up", "down", "left" or "right"
  32001. that represent all the valid directions in which a sprite can move
  32002. The `validGid` is the grid index number for the "walkable" part of the world
  32003. (such as, possibly, `0`.)
  32004. */
  32005. }, {
  32006. key: "validDirections",
  32007. value: function validDirections(sprite, mapArray, validGid, world) {
  32008. //Get the sprite's current map index position number
  32009. var index = g.getIndex(sprite.x, sprite.y, world.tilewidth, world.tileheight, world.widthInTiles);
  32010. //An array containing the index numbers of tile cells
  32011. //above, below and to the left and right of the sprite
  32012. var surroundingCrossCells = function surroundingCrossCells(index, widthInTiles) {
  32013. return [index - widthInTiles, index - 1, index + 1, index + widthInTiles];
  32014. };
  32015. //Get the index position numbers of the 4 cells to the top, right, left
  32016. //and bottom of the sprite
  32017. var surroundingIndexNumbers = surroundingCrossCells(index, world.widthInTiles);
  32018. //Find all the tile gid numbers that match the surrounding index numbers
  32019. var surroundingTileGids = surroundingIndexNumbers.map(function (index) {
  32020. return mapArray[index];
  32021. });
  32022. //`directionList` is an array of 4 string values that can be either
  32023. //"up", "left", "right", "down" or "none", depending on
  32024. //whether there is a cell with a valid gid that matches that direction.
  32025. var directionList = surroundingTileGids.map(function (gid, i) {
  32026. //The possible directions
  32027. var possibleDirections = ["up", "left", "right", "down"];
  32028. //If the direction is valid, choose the matching string
  32029. //identifier for that direction. Otherwise, return "none"
  32030. if (gid === validGid) {
  32031. return possibleDirections[i];
  32032. } else {
  32033. return "none";
  32034. }
  32035. });
  32036. //We don't need "none" in the list of directions
  32037. //(it's just a placeholder), so let's filter it out
  32038. var filteredDirectionList = directionList.filter(function (direction) {
  32039. return direction != "none";
  32040. });
  32041. //Return the filtered list of valid directions
  32042. return filteredDirectionList;
  32043. }
  32044. /*
  32045. canChangeDirection
  32046. ------------------
  32047. Returns `true` or `false` depending on whether a sprite in at a map
  32048. array location in which it able to change its direction
  32049. */
  32050. }, {
  32051. key: "canChangeDirection",
  32052. value: function canChangeDirection() {
  32053. var validDirections = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0];
  32054. //Is the sprite in a dead-end (cul de sac.) This will be true if there's only
  32055. //one element in the `validDirections` array
  32056. var inCulDeSac = validDirections.length === 1;
  32057. //Is the sprite trapped? This will be true if there are no elements in
  32058. //the `validDirections` array
  32059. var trapped = validDirections.length === 0;
  32060. //Is the sprite in a passage? This will be `true` if the the sprite
  32061. //is at a location that contain the values
  32062. //“left” or “right” and “up” or “down”
  32063. var up = validDirections.find(function (x) {
  32064. return x === "up";
  32065. }),
  32066. down = validDirections.find(function (x) {
  32067. return x === "down";
  32068. }),
  32069. left = validDirections.find(function (x) {
  32070. return x === "left";
  32071. }),
  32072. right = validDirections.find(function (x) {
  32073. return x === "right";
  32074. }),
  32075. atIntersection = (up || down) && (left || right);
  32076. //Return `true` if the sprite can change direction or
  32077. //`false` if it can't
  32078. return trapped || atIntersection || inCulDeSac;
  32079. }
  32080. /*
  32081. randomDirection
  32082. ---------------
  32083. Randomly returns the values "up", "down", "left" or "right" based on
  32084. valid directions supplied. If the are no valid directions, it returns "trapped"
  32085. */
  32086. }, {
  32087. key: "randomDirection",
  32088. value: function randomDirection(sprite) {
  32089. var validDirections = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1];
  32090. //The `randomInt` helper function returns a random integer between a minimum
  32091. //and maximum value
  32092. var randomInt = function randomInt(min, max) {
  32093. return Math.floor(Math.random() * (max - min + 1)) + min;
  32094. };
  32095. //Is the sprite trapped?
  32096. var trapped = validDirections.length === 0;
  32097. //If the sprite isn't trapped, randomly choose one of the valid
  32098. //directions. Otherwise, return the string "trapped"
  32099. if (!trapped) {
  32100. return validDirections[randomInt(0, validDirections.length - 1)];
  32101. } else {
  32102. return "trapped";
  32103. }
  32104. }
  32105. /*
  32106. closestDirection
  32107. ----------------
  32108. Tells you the closes direction to `spriteTwo` from `spriteOne` based on
  32109. supplied validDirections. The function returns any of these
  32110. 4 values: "up", "down", "left" or "right"
  32111. */
  32112. }, {
  32113. key: "closestDirection",
  32114. value: function closestDirection(spriteOne, spriteTwo) {
  32115. var validDirections = arguments.length <= 2 || arguments[2] === undefined ? [] : arguments[2];
  32116. //A helper function to find the closest direction
  32117. var closest = function closest() {
  32118. //Plot a vector between spriteTwo and spriteOne
  32119. var vx = spriteTwo.centerX - spriteOne.centerX,
  32120. vy = spriteTwo.centerY - spriteOne.centerY;
  32121. //If the distance is greater on the X axis...
  32122. if (Math.abs(vx) >= Math.abs(vy)) {
  32123. //Try left and right
  32124. if (vx <= 0) {
  32125. return "left";
  32126. } else {
  32127. return "right";
  32128. }
  32129. }
  32130. //If the distance is greater on the Y axis...
  32131. else {
  32132. //Try up and down
  32133. if (vy <= 0) {
  32134. return "up";
  32135. } else {
  32136. return "down";
  32137. }
  32138. }
  32139. };
  32140. }
  32141. }]);
  32142. return TileUtilities;
  32143. })();
  32144. //# sourceMappingURL=tileUtilities.js.map"use strict";
  32145. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  32146. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  32147. /*
  32148. Hexi
  32149. ====
  32150. Welcome to Hexi's source code!
  32151. This file, `core.js` is the glue that holds Hexi together. Most of Hexi's functionality comes
  32152. from some external libraries, written for Hexi, that `core.js` instantiates and wires
  32153. together. Here are the external libraries that Hexi is currently using:
  32154. - [Pixi](https://github.com/pixijs/pixi.js/): The world's fastest 2D WebGL and canvas renderer.
  32155. - [Bump](https://github.com/kittykatattack/bump): A complete suite of 2D collision functions for games.
  32156. - [Tink](https://github.com/kittykatattack/tink): Drag-and-drop, buttons, a universal pointer and other
  32157. helpful interactivity tools.
  32158. - [Charm](https://github.com/kittykatattack/charm): Easy-to-use tweening animation effects for Pixi sprites.
  32159. - [Dust](https://github.com/kittykatattack/dust): Particle effects for creating things like explosions, fire
  32160. and magic.
  32161. - [Sprite Utilities](https://github.com/kittykatattack/spriteUtilities): Easier and more intuitive ways to
  32162. create and use Pixi sprites, as well adding a state machine and animation player
  32163. - [Game Utilities](https://github.com/kittykatattack/gameUtilities): A collection of useful methods for games.
  32164. - [Tile Utilities](https://github.com/kittykatattack/tileUtilities): A collection of useful methods for making tile-based game worlds with [Tiled Editor](http://www.mapeditor.org).
  32165. - [Sound.js](https://github.com/kittykatattack/sound.js): A micro-library for loading, controlling and generating
  32166. sound and music effects. Everything you need to add sound to games.
  32167. - [fullScreen.js](https://github.com/kittykatattack/fullScreen): Adds an easy-to-implement full screen feature.
  32168. - [Smoothie](https://github.com/kittykatattack/smoothie): Ultra-smooth sprite animation using
  32169. true delta-time interpolation. It also lets you specify the fps (frames-per-second) at which
  32170. your game or application runs, and completely separates your sprite rendering loop from your
  32171. application logic loop.
  32172. The job of `core.js` (this file!) is to instantiate Hexi, load the assets, start the game loop, and
  32173. create top-level access to most of the properties and methods in the external libraries.
  32174. It also customizes some of those methods and runs them with some useful side-effects, such as
  32175. automatically adding sprites to Hexi's `stage`. (Hexi's `stage` is the root Pixi `Container` for the display list.)
  32176. I've divided this `core.js` file into "Chapters" which describes what each major section of code does.
  32177. You'll find a "Table of Contents" ahead, which is your guide to this file.
  32178. All this code is fully commented, but if there's something you don't understand, please ask
  32179. in this repository's Issues and we will do our best to help. All this code is in one single file for now, just for the sake of simplicity,
  32180. until the total scope of this project stabilizes.
  32181. Hexi's build system
  32182. -------------------
  32183. All of Hexi's source code is written in JavaScript ES6, transpiled to ES5 using Babel, and minified using Uglify2.
  32184. Make is currently being used as the build
  32185. system. So, to build Hexi, make sure you have Node, Babel and Uglify2 installed, and call `make` in the
  32186. command line from Hexi's root directory. Make will compile the `core.js` file, concatenate all files (including
  32187. the modules) and produce the `hexi.min.js` file using Uglify2.
  32188. You can also use Make to build individual sections of Hexi's code base.
  32189. If you just want to watch and compile the core.js file from ES6 to ES5, run:
  32190. make watchSrc
  32191. If you want to concatenate all the modules, run:
  32192. make concatModules
  32193. If you want to concatenate all the files, run:
  32194. make concatAllFiles
  32195. To watch and compile the example files from ES6 to ES5, run:
  32196. make watchExamples
  32197. To watch and compile the tutorial files from ES6 to ES5, run:
  32198. make watchTutorials
  32199. If anyone reading this wishes to contribute a simpler, more automated system using Grunt of Gulp,
  32200. we would welcome the contribution!
  32201. Table of Contents
  32202. -----------------
  32203. Here's your handy guide to this `core.js` file.
  32204. 1. Setup and instantiation.
  32205. 2. The `Hexi` class constructor.
  32206. 3. Hexi's engine: `start`, `load` and `update` methods.
  32207. 4. Module interfaces: Hexi's top-level access to the module properties and methods.
  32208. 5. Sprite creation methods: `sprite`, `tilingSprite`, `text`, `bitmapText`, `rectangle`, `circle`, `line`, `button`.
  32209. 6. Display utilities: `group`, `batch`, `grid`, `makeTiledWorld`, `remove`, `flowRight`, `flowDown`, `flowLeft`, `flowUp`.
  32210. 7. Sprite properties: Hexi's custom sprite properties (also known as super-powers!).
  32211. 8. Utilities: `scaleToWindow`, `log`, `makeProgressBar`, `loadingBar`, `compensateForStageSize`, `image`, `id`, `json`, `xml`, `sound`
  32212. */
  32213. //1. SETUP AND INSTANTIATION
  32214. //---------------------------
  32215. //IMPORTANT: Make sure to load Pixi and the modules before instantiating Hexi!
  32216. //The high level `hexi` function lets you quickly create an instance
  32217. //of Hexi using sensible defaults.
  32218. function hexi(width, height, setup) {
  32219. var thingsToLoad = arguments.length <= 3 || arguments[3] === undefined ? undefined : arguments[3];
  32220. var load = arguments.length <= 4 || arguments[4] === undefined ? undefined : arguments[4];
  32221. //If you need to, you can also instantiate Hexi with a configuration
  32222. //object, which lets you fine-tune the options.
  32223. var hexi = new Hexi({
  32224. //Required options:
  32225. width: width, //Width, in pixels
  32226. height: height, //Height, in pixels
  32227. setup: setup, //Function to run when Hexi starts
  32228. //Optional options:
  32229. assets: thingsToLoad, //Array of assets that should be loaded
  32230. load: load, //Function to run while Hexi is loading asssets
  32231. /*
  32232. renderer: "auto", //"auto", "canvas" or "webgl"
  32233. backgroundColor: 0xCCCCCC, //Hexadecimal color code
  32234. border: "1px dashed black", //CSS border string
  32235. scaleToWindow: true, //Boolean
  32236. scaleBorderColor: "gray", //Color string
  32237. fps: 30, //The frames per second the logic loop should run at
  32238. //An an object of Boolean (true/false) properties that describe which sprite
  32239. //properties should be smoothly animated. These can be any of 5
  32240. //properties: `position`, `rotation`, `size`, `scale` or `alpha`.
  32241. //(Position and rotation are on by default, unless you set Hexi's
  32242. //`interpolate` property to `false`)
  32243. */
  32244. interpolationProperties: {
  32245. position: true,
  32246. rotation: true,
  32247. size: true,
  32248. alpha: true
  32249. },
  32250. interpolate: true
  32251. });
  32252. //To change PIXI's renderer, set the `renderer` option to
  32253. //"auto", "canvas" or "webgl", like this:
  32254. //renderer: "auto"
  32255. //Add any other Pixi initialization options you need, depending
  32256. //on which Pixi renderer you're using
  32257. return hexi;
  32258. }
  32259. //The Hexi main class. It contains all of Hexi's properties and
  32260. //methods, and sets up bindings between Hexi and the module libraries.
  32261. //If you need more find control over Hexi's initialization options,
  32262. //you can create a new instance of the Hexi class directly in your application
  32263. //code. See how it's done in the `hexi` function above for a good example
  32264. //of how to do that.
  32265. //2. THE HEXI CLASS CONSTRUCTOR
  32266. //----------------------------
  32267. var Hexi = (function () {
  32268. /*
  32269. Initialize Hexi's constructor with an options object literal called `o`.
  32270. Here are the required options:
  32271. `width`: Value in pixels that describes the canvas's width
  32272. `height`: Value in pixels that describes the canvas's height
  32273. `setup`: A function that should run as soon as Hexi is initialized
  32274. Here are the optional options:
  32275. `assets`: Array of assets (files) that should be loaded
  32276. `load`: A function that should run while Hexi is loading assets
  32277. `renderer`: The type of renderer to use: "auto" (the default), "canvas" or "webgl"
  32278. `backgroundColor`: Hexadecimal color code that defines the canvas color
  32279. `border`: The canvas border style as a CSS border string, such as "1px dashed black"
  32280. `scaleToWindow`: A Boolean that determines whether the canvas should scale to maximum window size.
  32281. `scaleBorderColor`: Color string that defines the color of the border around a scaled canvas.
  32282. `interpolationProperties: An object that defines 5 Boolean properties that determines which sprite properties are interpolated
  32283. (smoothly animated) by Hexi's rendering engine (Smoothie): `position`, `size`, `rotation`, `scale` or `alpha`
  32284. `interpolate`: A Boolean which should be `false` if you *don't* want any sprite animation smoothing.
  32285. `fps`: The frames-per-second the engine's game logic loop should run at (the default is 60).
  32286. `renderFps`: Clamps the fps rendering to the supplied frame rate.
  32287. You can also add any of Pixi's initialization options, and those will be applied
  32288. to Pixi's renderer when Hexi creates it.
  32289. */
  32290. function Hexi(o) {
  32291. _classCallCheck(this, Hexi);
  32292. //Initialize all the helper modules.
  32293. //(See Hexi's README.md on information about these libraries)
  32294. this.charm = new Charm(PIXI);
  32295. this.dust = new Dust(PIXI);
  32296. this.bump = new Bump(PIXI);
  32297. this.spriteUtilities = new SpriteUtilities(PIXI);
  32298. this.tileUtilities = new TileUtilities(PIXI);
  32299. this.gameUtilities = new GameUtilities();
  32300. //Any modules that have an `update` method that should updated
  32301. //each frame in the game loop should be added to the
  32302. //`modulesToUpdate` array. The game loop will call the `update`
  32303. //method on each of these modules while the game is running.
  32304. //This is very efficient and does not effect performance: no modules are updated unless they
  32305. //contain objects that need updating.
  32306. this.modulesToUpdate = [];
  32307. this.modulesToUpdate.push(this.charm);
  32308. this.modulesToUpdate.push(this.dust);
  32309. this.modulesToUpdate.push(this.spriteUtilities);
  32310. //Create the stage and renderer
  32311. //Auto renderer (default)
  32312. if (o.renderer === "auto" || o.renderer === undefined) {
  32313. this.renderer = PIXI.autoDetectRenderer(o.width, o.height, o, o.noWebGL);
  32314. //Canvas renderer
  32315. } else if (o.renderer === "canvas") {
  32316. this.renderer = new PIXI.CanvasRenderer(o.width, o.height, o);
  32317. //WebGL renderer
  32318. } else if (o.renderer === "webgl") {
  32319. this.renderer = new PIXI.WebGLRenderer(o.width, o.height, o);
  32320. }
  32321. //Get a reference to the `renderer.view`, which is the
  32322. //HTML canvas element
  32323. this.canvas = this.renderer.view;
  32324. //Initialize the Tink interactive module (it needs a reference to the canvas)
  32325. this.tink = new Tink(PIXI, this.canvas);
  32326. this.modulesToUpdate.push(this.tink);
  32327. //Create local aliases for the important methods and properties of
  32328. //these libraries, including the most useful Pixi properties.
  32329. //Take a look at Hexi's `createModulePropertyAliases` method in the
  32330. //source code ahead to see how this works
  32331. this.createModulePropertyAliases();
  32332. //Add `halfWidth` and `halfHeight` properties to the canvas
  32333. Object.defineProperties.bind(this, this.canvas, {
  32334. "halfWidth": {
  32335. get: function get() {
  32336. return this.canvas.width / 2;
  32337. },
  32338. enumerable: true,
  32339. configurable: true
  32340. },
  32341. "halfHeight": {
  32342. get: function get() {
  32343. return this.canvas.height / 2;
  32344. },
  32345. enumerable: true,
  32346. configurable: true
  32347. }
  32348. });
  32349. //A Boolean to flag whether the canvas has been scaled
  32350. this.canvas.scaled = false;
  32351. //Add the FullScreen module and supply it with the canvas element
  32352. //this.fullScreen = new FullScreen(this.canvas);
  32353. //Note: Hexi's `update` function checks whether we're in full screen
  32354. //mode and updates the global scale value accordingly
  32355. //Set the canvas's optional background color and border style
  32356. if (o.backgroundColor) {
  32357. this.renderer.backgroundColor = this.color(o.backgroundColor);
  32358. } else {
  32359. this.renderer.backgroundColor = 0xFFFFFF;
  32360. }
  32361. if (o.border) this.canvas.style.border = o.border;
  32362. //Add the canvas to the HTML document
  32363. document.body.appendChild(this.canvas);
  32364. //Create a container object called the `stage`
  32365. this.stage = new this.Container();
  32366. //Add Hexi's special sprite properties to the stage
  32367. this.addProperties(this.stage);
  32368. this.stage._stage = true;
  32369. //The game's scale
  32370. if (o.scaleToWindow) {
  32371. this.scaleToWindow(o.scaleBorderColor);
  32372. } else {
  32373. this.scale = 1;
  32374. }
  32375. //Make the pointer
  32376. this.pointer = this.makePointer(this.canvas, this.scale);
  32377. //Set the game `state`
  32378. this.state = undefined;
  32379. //Set the user-defined `load` and `setup` states
  32380. if (o.load !== undefined) this.loadState = o.load;
  32381. //The `setup` function is required, so throw an error if it's
  32382. //missing
  32383. if (!o.setup) {
  32384. throw new Error("Please supply the setup option in the constructor to tell Hexi which function should run first when it starts.");
  32385. } else {
  32386. this.setupState = o.setup;
  32387. }
  32388. //A variable to track the current percentage of loading assets
  32389. this.loadingProgress = 0;
  32390. //A variable to track the currently loading asset
  32391. this.loadingFile = "";
  32392. //Load any assets if they've been provided
  32393. if (o.assets !== undefined) {
  32394. this.assetsToLoad = o.assets;
  32395. }
  32396. //Tell Hexi that we're not using a loading progress bar.
  32397. //(This will be set to `true` if the user invokes the `loadingBar`
  32398. //function, which you'll see ahead)
  32399. this._progressBarAdded = false;
  32400. //The `soundObjects` object is used to store all sounds
  32401. this.soundObjects = {};
  32402. //Create a new instance of Smoothie, which manages Hexi's game
  32403. //loop and adds smooth sprite interpolation
  32404. this.smoothie = new Smoothie({
  32405. engine: PIXI,
  32406. renderer: this.renderer,
  32407. root: this.stage,
  32408. update: this.update.bind(this),
  32409. properties: o.interpolationProperties,
  32410. interpolate: o.interpolate,
  32411. fps: o.fps,
  32412. renderFps: o.renderFps,
  32413. properties: {
  32414. position: true,
  32415. scale: true,
  32416. tile: true
  32417. }
  32418. });
  32419. }
  32420. //3. HEXI'S ENGINE: START, LOAD AND SETUP
  32421. //---------------------------------------
  32422. //The `start` method must be called by the user after Hexi has been
  32423. //initialized to start the loading process and turn on the engine.
  32424. _createClass(Hexi, [{
  32425. key: "start",
  32426. value: function start() {
  32427. //If there are assets to load, load them, and set the game's state
  32428. //to the user-defined `loadState` (which can be supplied by the user in the
  32429. //constructor)
  32430. if (this.assetsToLoad) {
  32431. //Call Hexi's `load` method (ahead) to load the assets
  32432. this.load(this.assetsToLoad, this.validateAssets);
  32433. //After the assets have been loaded, a method called
  32434. //`validateAssets` will run (see `validateAssets` ahead.)
  32435. //`validateAssets` checks to see what has been loaded and,
  32436. //in the case of sound files, decodes them and creates sound
  32437. //objects.
  32438. //If the user has supplied Hexi with a `load` function (in
  32439. //Hexi's constructor), it will be assigned to Hexi's current
  32440. //`state` and, as you'll see ahead, called in a loop while the
  32441. //assets load
  32442. if (this.loadState) this.state = this.loadState;
  32443. } else {
  32444. //If there's nothing to load, run the `setup` state, which will
  32445. //just run once
  32446. this.setupState();
  32447. }
  32448. //Start the game loop
  32449. this.smoothie.start();
  32450. }
  32451. //Use the `load` method to load any files into Hexi. Pass it a
  32452. //callback function as the second argument to launch a function that
  32453. //should run when all the assets have finished loading. Hexi's
  32454. //default callback function is `validateAssets`, which you'll find
  32455. //in the code ahead
  32456. }, {
  32457. key: "load",
  32458. value: function load(assetsToLoad) {
  32459. var _this = this;
  32460. var callbackFunction = arguments.length <= 1 || arguments[1] === undefined ? undefined : arguments[1];
  32461. //Handle special file types that Pixi's loader doesn't understand
  32462. //The `findAssets` function will return an array to get an array just
  32463. //containing those file source paths you're interested in
  32464. var findAssets = function findAssets(fileExtensionArray) {
  32465. var fileSourcePaths = assetsToLoad.filter(function (source) {
  32466. //Find the file extension of the asset
  32467. var extension = source.split(".").pop();
  32468. if (fileExtensionArray.indexOf(extension) !== -1) {
  32469. return true;
  32470. }
  32471. });
  32472. return fileSourcePaths;
  32473. };
  32474. /* Load fonts */
  32475. //First, define the file extensions for the special file types
  32476. //you're interested in
  32477. //Fonts
  32478. var fontExtensions = ["ttf", "otf", "ttc", "woff"];
  32479. //Get the font source paths
  32480. var fontFiles = findAssets(fontExtensions);
  32481. //If there are any font files, load them into the browser using an
  32482. //old trick that forces the browser to load them
  32483. if (fontFiles.length > 0) {
  32484. this.spanElements = [];
  32485. fontFiles.forEach(function (source) {
  32486. //Loads the font files by writing CSS code to the HTML document head.
  32487. //Use the font's filename as the `fontFamily` name. This code captures
  32488. //the font file's name without the extension or file path
  32489. var fontFamily = source.split("/").pop().split(".")[0];
  32490. //Push the font family name into Hexi's `fontFamilies` array
  32491. if (_this.fontFamilies) _this.fontFamilies.push(fontFamily);
  32492. //Append an `@afont-face` style rule to the head of the HTML document
  32493. var newStyle = document.createElement("style");
  32494. var fontFace = "@font-face {font-family: '" + fontFamily + "'; src: url('" + source + "');}";
  32495. newStyle.appendChild(document.createTextNode(fontFace));
  32496. document.head.appendChild(newStyle);
  32497. //Trick the browser into loading the font file by
  32498. //displaying an invisible element
  32499. var span = document.createElement("span");
  32500. span.style.fontFamily = fontFamily;
  32501. document.body.appendChild(span);
  32502. span.innerHTML = "?";
  32503. span.style.display = "block";
  32504. span.style.opacity = "0";
  32505. _this.spanElements.push(span);
  32506. });
  32507. }
  32508. /* Load sound */
  32509. //Set default loading mechanism for sound file extensions to use XHR
  32510. var Resource = PIXI.loaders.Resource;
  32511. Resource.setExtensionLoadType("wav", Resource.LOAD_TYPE.XHR);
  32512. Resource.setExtensionLoadType("mp3", Resource.LOAD_TYPE.XHR);
  32513. Resource.setExtensionLoadType("ogg", Resource.LOAD_TYPE.XHR);
  32514. Resource.setExtensionLoadType("webm", Resource.LOAD_TYPE.XHR);
  32515. //Set default loading type for sound file extensions to be arraybuffer
  32516. Resource.setExtensionXhrType("wav", Resource.XHR_RESPONSE_TYPE.BUFFER);
  32517. Resource.setExtensionXhrType("mp3", Resource.XHR_RESPONSE_TYPE.BUFFER);
  32518. Resource.setExtensionXhrType("ogg", Resource.XHR_RESPONSE_TYPE.BUFFER);
  32519. Resource.setExtensionXhrType("webm", Resource.XHR_RESPONSE_TYPE.BUFFER);
  32520. /* Load ordinary assets */
  32521. var loadProgressHandler = function loadProgressHandler(loader, resource) {
  32522. //Display the file `url` currently being loaded
  32523. _this.loadingFile = resource.url;
  32524. //Display the percentage of files currently loaded
  32525. _this.loadingProgress = loader.progress;
  32526. };
  32527. //Load the files and call the `loadProgressHandler` while they're
  32528. //loading
  32529. this.loader.reset();
  32530. this.loadingProgress = 0;
  32531. this.loadingFile = "";
  32532. this.loader.add(assetsToLoad).on("progress", loadProgressHandler).load(callbackFunction.bind(this));
  32533. }
  32534. //The `validateAssets` method runs when all the assets have finished
  32535. //loading. It checks to see if there are any sounds files and, if
  32536. //there are, decodes them and turns them into sound objects using the
  32537. //`sounds.js` module's `makeSound` function. If there are no sounds
  32538. //to load, the loading state is finished and the setup state is run.
  32539. //But, if there are sounds to load, the setup state will only run
  32540. //after the sounds have been decoded.
  32541. }, {
  32542. key: "validateAssets",
  32543. value: function validateAssets() {
  32544. var _this2 = this;
  32545. console.log("All assets loaded");
  32546. //The `finishLoadingState` method will be called if everything has
  32547. //finished loading and any possible sounds have been decoded
  32548. var finishLoadingState = function finishLoadingState() {
  32549. //Reset the `assetsToLoad` array
  32550. _this2.assetsToLoad = [];
  32551. //Clear the `loadState`
  32552. _this2.loadState = undefined;
  32553. //Clear the game `state` function for now to stop the loop.
  32554. _this2.state = undefined;
  32555. //Remove the loading progress bar if the user invoked the `loadingBar`
  32556. //function
  32557. if (_this2._progressBarAdded) {
  32558. _this2.progressBar.remove();
  32559. }
  32560. //If any fonts were tricked into loading
  32561. //make the <span> tags that use them invisible
  32562. if (_this2.spanElements) {
  32563. _this2.spanElements.forEach(function (element) {
  32564. element.style.display = "none";
  32565. });
  32566. }
  32567. //Call the `setup` state
  32568. _this2.setupState();
  32569. };
  32570. //We need to check if any possible sound file have been loaded
  32571. //because, if there have, they need to fist be decoded before we
  32572. //can launch the `setup` state.
  32573. //Variables to count the number of sound files and the sound files
  32574. //that have been decoded. If both these numbers are the same at
  32575. //some point, then we know all the sounds have been decoded and we
  32576. //can call the `finishLoadingState` function
  32577. var soundsToDecode = 0,
  32578. soundsDecoded = 0;
  32579. //First, create a list of the kind of sound files we want to check
  32580. var soundExtensions = ["wav", "mp3", "ogg", "webm"];
  32581. //The `decodeHandler` will run when each sound file is decoded
  32582. var decodeHandler = function decodeHandler() {
  32583. //Count 1 more sound as having been decoded
  32584. soundsDecoded += 1;
  32585. //If the decoded sounds match the number of sounds to decode,
  32586. //then we know all the sounds have been decoded and we can call
  32587. //`finishLoadingState`
  32588. if (soundsToDecode === soundsDecoded) {
  32589. finishLoadingState();
  32590. }
  32591. };
  32592. //Loop through all the loader's resources and look for sound files
  32593. Object.keys(this.loader.resources).forEach(function (resource) {
  32594. //Find the file extension of the asset
  32595. var extension = resource.split(".").pop();
  32596. //If one of the resource file extensions matches the sound file
  32597. //extensions, then we know we have a sound file
  32598. if (soundExtensions.indexOf(extension) !== -1) {
  32599. //Count one more sound to load
  32600. soundsToDecode += 1;
  32601. //Create aliases for the sound's `xhr` object and `url` (its
  32602. //file name)
  32603. var xhr = _this2.loader.resources[resource].xhr,
  32604. url = _this2.loader.resources[resource].url;
  32605. //Create a sound sprite using the `sound.js` module's
  32606. //`makeSound` function. Notice the 4th argument is the loaded
  32607. //sound's `xhr` object. Setting the 3rd argument to `false`
  32608. //means that `makeSound` won't attempt to load the sounds
  32609. //again. When the sound has been decoded, the `decodeHandler`
  32610. //(see above!) will be run
  32611. var soundSprite = makeSound(url, decodeHandler.bind(_this2), false, xhr);
  32612. //Get the sound file name.
  32613. soundSprite.name = _this2.loader.resources[resource].name;
  32614. //Add the sound object to Hexi's `soundObjects` object.
  32615. //You'll be able to access them in your application through
  32616. //Hexi's higher-level `sound` method, like this:
  32617. //`hexi.sound("soundFileName.wav");`
  32618. _this2.soundObjects[soundSprite.name] = soundSprite;
  32619. }
  32620. });
  32621. //If there are no sound files, we can skip the decoding step and
  32622. //just call `finishLoadingState` directly
  32623. if (soundsToDecode === 0) {
  32624. finishLoadingState();
  32625. }
  32626. }
  32627. //The `update` method is run by Hexi's game loop each frame.
  32628. //It manages the game state and updates the modules
  32629. }, {
  32630. key: "update",
  32631. value: function update() {
  32632. //Update all the modules in the `modulesToUpdate` array.
  32633. //These are modules that contain `update` methods that need to be
  32634. //called every frame
  32635. this.modulesToUpdate.forEach(function (module) {
  32636. return module.update();
  32637. });
  32638. //If the application is in full screen mode, make sure that Hexi
  32639. //is using the correct scale value
  32640. /*
  32641. if (document.fullscreenEnabled === true) {
  32642. console.log("fullscreenEnabled")
  32643. //Note: Check Firefox's current FullScreen API and specifically:
  32644. //https://github.com/neovov/Fullscreen-API-Polyfill/blob/master/fullscreen-api-polyfill.js
  32645. //if (this.fullScreen.fullscreenScale !== 1) {
  32646. this.scale = this.fullScreen.fullscreenScale;
  32647. //console.log("this.fullScreen.fullscreenScale: " + this.fullScreen.fullscreenScale)
  32648. this.pointer.scale = this.scale;
  32649. //Find out if the pointer scale is propagating to Tink's pointer?
  32650. console.log(this.pointer.scale)
  32651. } else {
  32652. if (!this.canvas.scaled) {
  32653. this.scale = 1;
  32654. this.pointer.scale = 1;
  32655. }
  32656. }
  32657. */
  32658. //Run the current game `state` function if it's been defined and
  32659. //the game isn't `paused`
  32660. if (this.state && !this.paused) {
  32661. this.state();
  32662. }
  32663. }
  32664. //Pause and resume methods
  32665. }, {
  32666. key: "pause",
  32667. value: function pause() {
  32668. this.paused = true;
  32669. }
  32670. }, {
  32671. key: "resume",
  32672. value: function resume() {
  32673. this.paused = false;
  32674. }
  32675. //4. MODULE INTERFACES
  32676. //A method that helpfully creates local, top-level references to the
  32677. //most useful properties and methods from the loaded modules
  32678. }, {
  32679. key: "createModulePropertyAliases",
  32680. value: function createModulePropertyAliases() {
  32681. var _this3 = this;
  32682. //Pixi - Rendering
  32683. this.Container = PIXI.Container;
  32684. this.loader = PIXI.loader;
  32685. this.TextureCache = PIXI.utils.TextureCache;
  32686. this.filters = PIXI.filters;
  32687. //Filters
  32688. this.dropShadowFilter = function () {
  32689. return new _this3.filters.DropShadowFilter();
  32690. };
  32691. this.asciiFilter = function () {
  32692. return new _this3.filters.AsciiFilter();
  32693. };
  32694. this.alphaMaskFilter = function () {
  32695. return new _this3.filters.AlphaMaskFilter();
  32696. };
  32697. this.bloomFilter = function () {
  32698. return new _this3.filters.BloomFilter();
  32699. };
  32700. this.blurDirFilter = function () {
  32701. return new _this3.filters.BlurDirFilter();
  32702. };
  32703. this.blurFilter = function () {
  32704. return new _this3.filters.BlurFilter();
  32705. };
  32706. this.colorMatrixFilter = function () {
  32707. return new _this3.filters.ColorMatrixFilter();
  32708. };
  32709. this.colorStepFilter = function () {
  32710. return new _this3.filters.ColorStepFilter();
  32711. };
  32712. this.crossHatchFilter = function () {
  32713. return new _this3.filters.CrossHatchFilter();
  32714. };
  32715. this.displacementFilter = function () {
  32716. return new _this3.filters.DisplacementFilter();
  32717. };
  32718. this.dotScreenFilter = function () {
  32719. return new _this3.filters.DotScreenFilter();
  32720. };
  32721. this.grayFilter = function () {
  32722. return new _this3.filters.GrayFilter();
  32723. };
  32724. this.invertFilter = function () {
  32725. return new _this3.filters.InvertFilter();
  32726. };
  32727. this.pixelateFilter = function () {
  32728. return new _this3.filters.PixelateFilter();
  32729. };
  32730. this.sepiaFilter = function () {
  32731. return new _this3.filters.SepiaFilter();
  32732. };
  32733. this.shockwaveFilter = function () {
  32734. return new _this3.filters.ShockwaveFilter();
  32735. };
  32736. this.twistFilter = function () {
  32737. return new _this3.filters.TwistFilter();
  32738. };
  32739. this.rgbSplitFilter = function () {
  32740. return new _this3.filters.RGBSplitFilter();
  32741. };
  32742. this.smartBlurFilter = function () {
  32743. return new _this3.filters.SmartBlurFilter();
  32744. };
  32745. this.tiltShiftFilter = function () {
  32746. return new _this3.filters.TiltShiftFilter();
  32747. };
  32748. //Tink - Interactivity
  32749. this.draggableSprites = this.tink.draggableSprites;
  32750. this.pointers = this.tink.pointers;
  32751. this.buttons = this.tink.buttons;
  32752. this.makePointer = function (canvas, scale) {
  32753. return _this3.tink.makePointer(canvas, scale);
  32754. };
  32755. this.makeDraggable = function () {
  32756. var _tink;
  32757. return (_tink = _this3.tink).makeDraggable.apply(_tink, arguments);
  32758. };
  32759. this.makeUndraggable = function () {
  32760. var _tink2;
  32761. return (_tink2 = _this3.tink).makeUndraggable.apply(_tink2, arguments);
  32762. };
  32763. this.makeInteractive = function (o) {
  32764. return _this3.tink.makeInteractive(o);
  32765. };
  32766. this.keyboard = this.tink.keyboard;
  32767. this.arrowControl = function (sprite, speed) {
  32768. return _this3.tink.arrowControl(sprite, speed);
  32769. };
  32770. //Add the arrow key objects
  32771. /*
  32772. this.upArrow = this.keyboard(38);
  32773. this.rightArrow = this.keyboard(39);
  32774. this.downArrow = this.keyboard(40);
  32775. this.leftArrow = this.keyboard(37);
  32776. this.spaceBar = this.keyboard(32);
  32777. */
  32778. //Dust - Particle effects
  32779. this.createParticles = function (x, y, spriteFunction, container, numberOfParticles, gravity, randomSpacing, minAngle, maxAngle, minSize, maxSize, minSpeed, maxSpeed, minScaleSpeed, maxScaleSpeed, minAlphaSpeed, maxAlphaSpeed, minRotationSpeed, maxRotationSpeed) {
  32780. return _this3.dust.create(x, y, spriteFunction, container, numberOfParticles, gravity, randomSpacing, minAngle, maxAngle, minSize, maxSize, minSpeed, maxSpeed, minScaleSpeed, maxScaleSpeed, minAlphaSpeed, maxAlphaSpeed, minRotationSpeed, maxRotationSpeed);
  32781. };
  32782. this.particleEmitter = function (interval, particleFunction) {
  32783. return _this3.dust.emitter(interval, particleFunction);
  32784. };
  32785. //SpriteUtilities - Sprite creation tools
  32786. this.filmstrip = function (texture, frameWidth, frameHeight, spacing) {
  32787. return _this3.spriteUtilities.filmstrip(texture, frameWidth, frameHeight, spacing);
  32788. };
  32789. this.frame = function (source, x, y, width, height) {
  32790. return _this3.spriteUtilities.frame(source, x, y, width, height);
  32791. };
  32792. this.frames = function (source, coordinates, frameWidth, frameHeight) {
  32793. return _this3.spriteUtilities.frames(source, coordinates, frameWidth, frameHeight);
  32794. };
  32795. this.frameSeries = function (startNumber, endNumber, baseName, extension) {
  32796. return _this3.spriteUtilities.frames(startNumber, endNumber, baseName, extension);
  32797. };
  32798. this.colorToRGBA = function (value) {
  32799. return _this3.spriteUtilities.colorToRGBA(value);
  32800. };
  32801. this.colorToHex = function (value) {
  32802. return _this3.spriteUtilities.colorToHex(value);
  32803. };
  32804. this.byteToHex = function (value) {
  32805. return _this3.spriteUtilities.byteToHex(value);
  32806. };
  32807. this.color = function (value) {
  32808. return _this3.spriteUtilities.color(value);
  32809. };
  32810. this.shoot = function (shooter, angle, x, y, container, bulletSpeed, bulletArray, bulletSprite) {
  32811. return _this3.spriteUtilities.shoot(shooter, angle, x, y, container, bulletSpeed, bulletArray, bulletSprite);
  32812. };
  32813. this.shake = function (sprite) {
  32814. var magnitude = arguments.length <= 1 || arguments[1] === undefined ? 16 : arguments[1];
  32815. var angular = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  32816. console.log("shake");
  32817. return _this3.spriteUtilities.shake(sprite, magnitude, angular);
  32818. };
  32819. //Charm - Tweening
  32820. this.fadeOut = function (sprite) {
  32821. var frames = arguments.length <= 1 || arguments[1] === undefined ? 60 : arguments[1];
  32822. return _this3.charm.fadeOut(sprite, frames);
  32823. };
  32824. this.fadeIn = function (sprite) {
  32825. var frames = arguments.length <= 1 || arguments[1] === undefined ? 60 : arguments[1];
  32826. return _this3.charm.fadeIn(sprite, frames);
  32827. };
  32828. this.pulse = function (sprite) {
  32829. var frames = arguments.length <= 1 || arguments[1] === undefined ? 60 : arguments[1];
  32830. var minAlpha = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2];
  32831. return _this3.charm.pulse(sprite, frames, minAlpha);
  32832. };
  32833. this.slide = function (sprite, endX, endY) {
  32834. var frames = arguments.length <= 3 || arguments[3] === undefined ? 60 : arguments[3];
  32835. var type = arguments.length <= 4 || arguments[4] === undefined ? "smoothstep" : arguments[4];
  32836. var yoyo = arguments.length <= 5 || arguments[5] === undefined ? false : arguments[5];
  32837. var delayBeforeRepeat = arguments.length <= 6 || arguments[6] === undefined ? 0 : arguments[6];
  32838. return _this3.charm.slide(sprite, endX, endY, frames, type, yoyo, delayBeforeRepeat = 0);
  32839. };
  32840. this.breathe = function (sprite) {
  32841. var endScaleX = arguments.length <= 1 || arguments[1] === undefined ? 0.8 : arguments[1];
  32842. var endScaleY = arguments.length <= 2 || arguments[2] === undefined ? 0.8 : arguments[2];
  32843. var frames = arguments.length <= 3 || arguments[3] === undefined ? 60 : arguments[3];
  32844. var yoyo = arguments.length <= 4 || arguments[4] === undefined ? true : arguments[4];
  32845. var delayBeforeRepeat = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5];
  32846. return _this3.charm.breathe(sprite, endScaleX, endScaleY, frames, yoyo, delayBeforeRepeat);
  32847. };
  32848. this.scale = function (sprite) {
  32849. var endScaleX = arguments.length <= 1 || arguments[1] === undefined ? 0.5 : arguments[1];
  32850. var endScaleY = arguments.length <= 2 || arguments[2] === undefined ? 0.5 : arguments[2];
  32851. var frames = arguments.length <= 3 || arguments[3] === undefined ? 60 : arguments[3];
  32852. return _this3.charm.scale(sprite, endScaleX, endScaleY, frames);
  32853. };
  32854. this.strobe = function (sprite) {
  32855. var scaleFactor = arguments.length <= 1 || arguments[1] === undefined ? 1.3 : arguments[1];
  32856. var startMagnitude = arguments.length <= 2 || arguments[2] === undefined ? 10 : arguments[2];
  32857. var endMagnitude = arguments.length <= 3 || arguments[3] === undefined ? 20 : arguments[3];
  32858. var frames = arguments.length <= 4 || arguments[4] === undefined ? 10 : arguments[4];
  32859. var yoyo = arguments.length <= 5 || arguments[5] === undefined ? true : arguments[5];
  32860. var delayBeforeRepeat = arguments.length <= 6 || arguments[6] === undefined ? 0 : arguments[6];
  32861. return _this3.charm.strobe(sprite, scaleFactor, startMagnitude, endMagnitude, frames, yoyo, delayBeforeRepeat);
  32862. };
  32863. this.wobble = function (sprite) {
  32864. var scaleFactorX = arguments.length <= 1 || arguments[1] === undefined ? 1.2 : arguments[1];
  32865. var scaleFactorY = arguments.length <= 2 || arguments[2] === undefined ? 1.2 : arguments[2];
  32866. var frames = arguments.length <= 3 || arguments[3] === undefined ? 10 : arguments[3];
  32867. var xStartMagnitude = arguments.length <= 4 || arguments[4] === undefined ? 10 : arguments[4];
  32868. var xEndMagnitude = arguments.length <= 5 || arguments[5] === undefined ? 10 : arguments[5];
  32869. var yStartMagnitude = arguments.length <= 6 || arguments[6] === undefined ? -10 : arguments[6];
  32870. var yEndMagnitude = arguments.length <= 7 || arguments[7] === undefined ? -10 : arguments[7];
  32871. var friction = arguments.length <= 8 || arguments[8] === undefined ? 0.98 : arguments[8];
  32872. var yoyo = arguments.length <= 9 || arguments[9] === undefined ? true : arguments[9];
  32873. var delayBeforeRepeat = arguments.length <= 10 || arguments[10] === undefined ? 0 : arguments[10];
  32874. return _this3.charm.wobble(sprite, scaleFactorX = 1.2, scaleFactorY = 1.2, frames = 10, xStartMagnitude = 10, xEndMagnitude = 10, yStartMagnitude = -10, yEndMagnitude = -10, friction = 0.98, yoyo = true, delayBeforeRepeat = 0);
  32875. };
  32876. this.followCurve = function (sprite, pointsArray, totalFrames) {
  32877. var type = arguments.length <= 3 || arguments[3] === undefined ? "smoothstep" : arguments[3];
  32878. var yoyo = arguments.length <= 4 || arguments[4] === undefined ? false : arguments[4];
  32879. var delayBeforeRepeat = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5];
  32880. return _this3.charm.followCurve(sprite, pointsArray, totalFrames, type, yoyo, delayBeforeRepeat);
  32881. };
  32882. this.walkPath = function (sprite, originalPathArray) {
  32883. var totalFrames = arguments.length <= 2 || arguments[2] === undefined ? 300 : arguments[2];
  32884. var type = arguments.length <= 3 || arguments[3] === undefined ? "smoothstep" : arguments[3];
  32885. var loop = arguments.length <= 4 || arguments[4] === undefined ? false : arguments[4];
  32886. var yoyo = arguments.length <= 5 || arguments[5] === undefined ? false : arguments[5];
  32887. var delayBetweenSections = arguments.length <= 6 || arguments[6] === undefined ? 0 : arguments[6];
  32888. return _this3.charm.walkPath(sprite, originalPathArray, totalFrames, type, loop, yoyo, delayBetweenSections);
  32889. };
  32890. this.walkCurve = function (sprite, pathArray) {
  32891. var totalFrames = arguments.length <= 2 || arguments[2] === undefined ? 300 : arguments[2];
  32892. var type = arguments.length <= 3 || arguments[3] === undefined ? "smoothstep" : arguments[3];
  32893. var loop = arguments.length <= 4 || arguments[4] === undefined ? false : arguments[4];
  32894. var yoyo = arguments.length <= 5 || arguments[5] === undefined ? false : arguments[5];
  32895. var delayBeforeContinue = arguments.length <= 6 || arguments[6] === undefined ? 0 : arguments[6];
  32896. return _this3.charm.walkCurve(sprite, pathArray, totalFrames, type, loop, yoyo, delayBeforeContinue);
  32897. };
  32898. this.removeTween = function (tweenObject) {
  32899. return _this3.charm.removeTween(tweenObject);
  32900. };
  32901. this.makeTween = function (tweensToAdd) {
  32902. return _this3.charm.makeTween(tweensToAdd);
  32903. };
  32904. this.tweenProperty = function (sprite, property, startValue, endValue, totalFrames) {
  32905. var type = arguments.length <= 5 || arguments[5] === undefined ? "smoothstep" : arguments[5];
  32906. var yoyo = arguments.length <= 6 || arguments[6] === undefined ? false : arguments[6];
  32907. var delayBeforeRepeat = arguments.length <= 7 || arguments[7] === undefined ? 0 : arguments[7];
  32908. return _this3.charm.tweenProperty(sprite, property, startValue, endValue, totalFrames, type, yoyo, delayBeforeRepeat);
  32909. };
  32910. //Bump - Collision
  32911. this.hitTestPoint = function (point, sprite) {
  32912. return _this3.bump.hitTestPoint(point, sprite);
  32913. };
  32914. this.hitTestCircle = function (c1, c2) {
  32915. var global = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  32916. return _this3.bump.hitTestCircle(c1, c2, global);
  32917. };
  32918. this.circleCollision = function (c1, c2) {
  32919. var bounce = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  32920. var global = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
  32921. return _this3.bump.circleCollision(c1, c2, bounce, global);
  32922. };
  32923. this.movingCircleCollision = function (c1, c2) {
  32924. var global = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  32925. return _this3.bump.movingCircleCollision(c1, c2, global);
  32926. };
  32927. this.multipleCircleCollision = function (arrayOfCircles) {
  32928. var global = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1];
  32929. return _this3.bump.multipleCircleCollision(arrayOfCircles, global);
  32930. };
  32931. this.rectangleCollision = function (r1, r2) {
  32932. var bounce = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  32933. var global = arguments.length <= 3 || arguments[3] === undefined ? true : arguments[3];
  32934. return _this3.bump.rectangleCollision(r1, r2, bounce, global);
  32935. };
  32936. this.hitTestRectangle = function (r1, r2) {
  32937. var global = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  32938. return _this3.bump.hitTestRectangle(r1, r2, global);
  32939. };
  32940. this.hitTestCircleRectangle = function (c1, r1) {
  32941. var global = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  32942. return _this3.bump.hitTestCircleRectangle(c1, r1, global);
  32943. };
  32944. this.hitTestCirclePoint = function (c1, point) {
  32945. var global = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  32946. return _this3.bump.hitTestCirclePoint(c1, point, global);
  32947. };
  32948. this.circleRectangleCollision = function (c1, r1) {
  32949. var bounce = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  32950. var global = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
  32951. return _this3.bump.circleRectangleCollision(c1, r1, bounce, global);
  32952. };
  32953. this.circlePointCollision = function (c1, point) {
  32954. var bounce = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  32955. var global = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
  32956. return _this3.bump.circlePointCollision(c1, point, bounce, global);
  32957. };
  32958. this.bounceOffSurface = function (o, s) {
  32959. return _this3.bump.bounceOffSurface(o, s);
  32960. };
  32961. this.hit = function (a, b) {
  32962. var react = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  32963. var bounce = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
  32964. var global = arguments[4];
  32965. var extra = arguments.length <= 5 || arguments[5] === undefined ? undefined : arguments[5];
  32966. return _this3.bump.hit(a, b, react, bounce, global, extra);
  32967. };
  32968. this.shortestPath = function (startIndex, destinationIndex, mapArray, mapWidthInTiles) {
  32969. var obstacleGids = arguments.length <= 4 || arguments[4] === undefined ? [] : arguments[4];
  32970. var heuristic = arguments.length <= 5 || arguments[5] === undefined ? "manhattan" : arguments[5];
  32971. var useDiagonalNodes = arguments.length <= 6 || arguments[6] === undefined ? true : arguments[6];
  32972. return _this3.tileUtilities.shortestPath(startIndex, destinationIndex, mapArray, mapWidthInTiles, obstacleGids, heuristic, useDiagonalNodes);
  32973. };
  32974. this.tileBasedLineOfSight = function (spriteOne, spriteTwo, mapArray, world) {
  32975. var emptyGid = arguments.length <= 4 || arguments[4] === undefined ? 0 : arguments[4];
  32976. var segment = arguments.length <= 5 || arguments[5] === undefined ? 32 : arguments[5];
  32977. var angles = arguments.length <= 6 || arguments[6] === undefined ? [] : arguments[6];
  32978. return _this3.tileUtilities.tileBasedLineOfSight(spriteOne, spriteTwo, mapArray, world, emptyGid, segment, angles);
  32979. };
  32980. //Intercept the Bump library's `contain` and `outsideBounds` methods to make sure that
  32981. //the stage `width` and `height` match the canvas width and height
  32982. this.contain = function (sprite, container) {
  32983. var bounce = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
  32984. var extra = arguments.length <= 3 || arguments[3] === undefined ? undefined : arguments[3];
  32985. var o = {};
  32986. if (container._stage) {
  32987. o = _this3.compensateForStageSize(container);
  32988. } else {
  32989. o = container;
  32990. }
  32991. return _this3.bump.contain(sprite, o, bounce, extra);
  32992. };
  32993. this.outsideBounds = function (sprite, container) {
  32994. var extra = arguments.length <= 2 || arguments[2] === undefined ? undefined : arguments[2];
  32995. var o = {};
  32996. if (container._stage) {
  32997. o = _this3.compensateForStageSize(container);
  32998. } else {
  32999. o = container;
  33000. }
  33001. return _this3.bump.outsideBounds(sprite, o, extra);
  33002. };
  33003. //GameUtilities - Useful utilities
  33004. this.distance = function (s1, s2) {
  33005. return _this3.gameUtilities.distance(s1, s2);
  33006. };
  33007. this.followEase = function (follower, leader, speed) {
  33008. return _this3.gameUtilities.followEase(follower, leader, speed);
  33009. };
  33010. this.followConstant = function (follower, leader, speed) {
  33011. return _this3.gameUtilities.followConstant(follower, leader, speed);
  33012. };
  33013. this.angle = function (s1, s2) {
  33014. return _this3.gameUtilities.angle(s1, s2);
  33015. };
  33016. this.rotateAroundSprite = function (rotatingSprite, centerSprite, distance, angle) {
  33017. return _this3.gameUtilities.rotateAroundSprite(rotatingSprite, centerSprite, distance, angle);
  33018. };
  33019. this.rotateAroundPoint = this.gameUtilities.rotateAroundPoint;
  33020. this.randomInt = this.gameUtilities.randomInt;
  33021. this.randomFloat = this.gameUtilities.randomFloat;
  33022. this.move = this.gameUtilities.move;
  33023. this.wait = this.gameUtilities.wait;
  33024. this.worldCamera = function (world, worldWidth, worldHeight) {
  33025. var canvas = arguments.length <= 3 || arguments[3] === undefined ? _this3.canvas : arguments[3];
  33026. return _this3.gameUtilities.worldCamera(world, worldWidth, worldHeight, canvas);
  33027. };
  33028. this.lineOfSight = function (spriteOne, spriteTwo, obstacles) {
  33029. var segment = arguments.length <= 3 || arguments[3] === undefined ? 32 : arguments[3];
  33030. return _this3.gameUtilities.lineOfSight(spriteOne, spriteTwo, obstacles, segment);
  33031. };
  33032. //Sound.js - Sound
  33033. this.soundEffect = function (frequencyValue, attack, decay, type, volumeValue, panValue, wait, pitchBendAmount, reverse, randomValue, dissonance, echo, reverb) {
  33034. return soundEffect(frequencyValue, attack, decay, type, volumeValue, panValue, wait, pitchBendAmount, reverse, randomValue, dissonance, echo, reverb);
  33035. };
  33036. //FullScreen
  33037. //this.enableFullScreen = (exitKeyCodes) => this.fullScreen.enableFullScreen(exitKeyCodes);
  33038. //TileUtilities
  33039. this.hitTestTile = function (sprite, mapArray, gidToCheck, world, pointsToCheck) {
  33040. return _this3.tileUtilities.hitTestTile(sprite, mapArray, gidToCheck, world, pointsToCheck);
  33041. };
  33042. this.getIndex = function (x, y, tilewidth, tileheight, mapWidthInTiles) {
  33043. return _this3.tileUtilities.getIndex(x, y, tilewidth, tileheight, mapWidthInTiles);
  33044. };
  33045. this.getTile = this.tileUtilities.getTile;
  33046. this.surroundingCells = this.tileUtilities.surroundingCells;
  33047. this.getPoints = this.tileUtilities.getPoints;
  33048. this.updateMap = function (mapArray, spritesToUpdate, world) {
  33049. return _this3.tileUtilities.updateMap(mapArray, spritesToUpdate, world);
  33050. };
  33051. this.byDepth = this.tileUtilities.byDepth;
  33052. this.hitTestIsoTile = function (sprite, mapArray, gidToCheck, world, pointsToCheck) {
  33053. return _this3.tileUtilities.hitTestIsoTile(sprite, mapArray, gidToCheck, world, pointsToCheck);
  33054. };
  33055. this.getIsoPoints = this.tileUtilities.getIsoPoints;
  33056. this.makeIsoPointer = function (pointer, world) {
  33057. return _this3.tileUtilities.makeIsoPointer(pointer, world);
  33058. };
  33059. this.isoRectangle = function (width, height, fillStyle) {
  33060. return _this3.tileUtilities.isoRectangle(width, height, fillStyle);
  33061. };
  33062. this.addIsoProperties = function (sprite, x, y, width, height) {
  33063. return _this3.tileUtilities.addIsoProperties(sprite, x, y, width, height);
  33064. };
  33065. this.makeIsoTiledWorld = function (jsonTiledMap, tileset) {
  33066. return _this3.tileUtilities.makeIsoTiledWorld(jsonTiledMap, tileset);
  33067. };
  33068. }
  33069. //Getters and setters
  33070. //Pixi's loader resources
  33071. }, {
  33072. key: "sprite",
  33073. //5. SPRITE CREATION METHODS
  33074. //Hexi uses methods from the
  33075. //SpriteUtilities module to help create sprites. But, as a helpful bonus, Hexi automatically adds sprites
  33076. //to the `stage` container. (The `stage` is Hexi's root container for all
  33077. //Hexi sprites.) Hexi also adds a whole bunch of
  33078. //extra, useful properties and methods to sprites with the
  33079. //`addProperties` method
  33080. //Universal sprites
  33081. value: function sprite(source) {
  33082. var x = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
  33083. var y = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2];
  33084. var tiling = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
  33085. var width = arguments[4];
  33086. var height = arguments[5];
  33087. var o = this.spriteUtilities.sprite(source, x, y, tiling, width, height);
  33088. this.addProperties(o);
  33089. this.stage.addChild(o);
  33090. return o;
  33091. }
  33092. //Tiling sprites
  33093. }, {
  33094. key: "tilingSprite",
  33095. value: function tilingSprite(source, width, height) {
  33096. var x = arguments.length <= 3 || arguments[3] === undefined ? 0 : arguments[3];
  33097. var y = arguments.length <= 4 || arguments[4] === undefined ? 0 : arguments[4];
  33098. var o = this.spriteUtilities.tilingSprite(source, width, height, x, y);
  33099. this.addProperties(o);
  33100. this.stage.addChild(o);
  33101. return o;
  33102. }
  33103. //Hexi's `text` method is a quick way to create a Pixi Text sprite
  33104. //and add it to the stage
  33105. }, {
  33106. key: "text",
  33107. value: function text() {
  33108. var content = arguments.length <= 0 || arguments[0] === undefined ? "message" : arguments[0];
  33109. var font = arguments.length <= 1 || arguments[1] === undefined ? "16px sans" : arguments[1];
  33110. var fillStyle = arguments.length <= 2 || arguments[2] === undefined ? "red" : arguments[2];
  33111. var x = arguments.length <= 3 || arguments[3] === undefined ? 0 : arguments[3];
  33112. var y = arguments.length <= 4 || arguments[4] === undefined ? 0 : arguments[4];
  33113. var message = this.spriteUtilities.text(content, font, fillStyle, x, y);
  33114. this.addProperties(message);
  33115. this.stage.addChild(message);
  33116. return message;
  33117. }
  33118. //The `bitmapText` method is a quick way to create a Pixi BitmapText sprite
  33119. }, {
  33120. key: "bitmapText",
  33121. value: function bitmapText() {
  33122. var content = arguments.length <= 0 || arguments[0] === undefined ? "message" : arguments[0];
  33123. var font = arguments[1];
  33124. var align = arguments[2];
  33125. var tint = arguments[3];
  33126. var x = arguments.length <= 4 || arguments[4] === undefined ? 0 : arguments[4];
  33127. var y = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5];
  33128. var message = this.spriteUtilities.bitmapText(content, font, align, tint, x, y);
  33129. this.addProperties(message);
  33130. this.stage.addChild(message);
  33131. return message;
  33132. }
  33133. //Make a rectangle and add it to the stage
  33134. }, {
  33135. key: "rectangle",
  33136. value: function rectangle() {
  33137. var width = arguments.length <= 0 || arguments[0] === undefined ? 32 : arguments[0];
  33138. var height = arguments.length <= 1 || arguments[1] === undefined ? 32 : arguments[1];
  33139. var fillStyle = arguments.length <= 2 || arguments[2] === undefined ? 0xFF3300 : arguments[2];
  33140. var strokeStyle = arguments.length <= 3 || arguments[3] === undefined ? 0x0033CC : arguments[3];
  33141. var lineWidth = arguments.length <= 4 || arguments[4] === undefined ? 0 : arguments[4];
  33142. var x = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5];
  33143. var y = arguments.length <= 6 || arguments[6] === undefined ? 0 : arguments[6];
  33144. var o = this.spriteUtilities.rectangle(width, height, fillStyle, strokeStyle, lineWidth, x, y);
  33145. this.addProperties(o);
  33146. this.stage.addChild(o);
  33147. return o;
  33148. }
  33149. //Make a circle and add it to the stage
  33150. }, {
  33151. key: "circle",
  33152. value: function circle() {
  33153. var diameter = arguments.length <= 0 || arguments[0] === undefined ? 32 : arguments[0];
  33154. var fillStyle = arguments.length <= 1 || arguments[1] === undefined ? 0xFF3300 : arguments[1];
  33155. var strokeStyle = arguments.length <= 2 || arguments[2] === undefined ? 0x0033CC : arguments[2];
  33156. var lineWidth = arguments.length <= 3 || arguments[3] === undefined ? 0 : arguments[3];
  33157. var x = arguments.length <= 4 || arguments[4] === undefined ? 0 : arguments[4];
  33158. var y = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5];
  33159. var o = this.spriteUtilities.circle(diameter, fillStyle, strokeStyle, lineWidth, x, y);
  33160. this.addProperties(o);
  33161. //Add diameter and radius properties to the circle
  33162. o.circular = true;
  33163. this.stage.addChild(o);
  33164. return o;
  33165. }
  33166. //Draw a line
  33167. }, {
  33168. key: "line",
  33169. value: function line() {
  33170. var strokeStyle = arguments.length <= 0 || arguments[0] === undefined ? 0x000000 : arguments[0];
  33171. var lineWidth = arguments.length <= 1 || arguments[1] === undefined ? 1 : arguments[1];
  33172. var ax = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2];
  33173. var ay = arguments.length <= 3 || arguments[3] === undefined ? 0 : arguments[3];
  33174. var bx = arguments.length <= 4 || arguments[4] === undefined ? 32 : arguments[4];
  33175. var by = arguments.length <= 5 || arguments[5] === undefined ? 32 : arguments[5];
  33176. var o = this.spriteUtilities.line(strokeStyle, lineWidth, ax, ay, bx, by);
  33177. this.addProperties(o);
  33178. this.stage.addChild(o);
  33179. return o;
  33180. }
  33181. //Make a button and add it to the stage
  33182. }, {
  33183. key: "button",
  33184. value: function button(source, x, y) {
  33185. var o = this.tink.button(source, x, y);
  33186. this.addProperties(o);
  33187. this.stage.addChild(o);
  33188. return o;
  33189. }
  33190. //6. DISPLAY UTILITIES
  33191. //--------------------
  33192. //Use `group` to create a Container
  33193. }, {
  33194. key: "group",
  33195. value: function group() {
  33196. var _spriteUtilities;
  33197. var o = (_spriteUtilities = this.spriteUtilities).group.apply(_spriteUtilities, arguments);
  33198. this.addProperties(o);
  33199. this.stage.addChild(o);
  33200. return o;
  33201. }
  33202. //`batch` creates a Pixi ParticleContainer
  33203. }, {
  33204. key: "batch",
  33205. value: function batch(size, options) {
  33206. var o = this.spriteUtilities.batch(size, options);
  33207. this.addProperties(o);
  33208. this.stage.addChild(o);
  33209. return o;
  33210. }
  33211. //Create a grid of sprite
  33212. }, {
  33213. key: "grid",
  33214. value: function grid() {
  33215. var columns = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];
  33216. var rows = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
  33217. var cellWidth = arguments.length <= 2 || arguments[2] === undefined ? 32 : arguments[2];
  33218. var cellHeight = arguments.length <= 3 || arguments[3] === undefined ? 32 : arguments[3];
  33219. var centerCell = arguments.length <= 4 || arguments[4] === undefined ? false : arguments[4];
  33220. var xOffset = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5];
  33221. var yOffset = arguments.length <= 6 || arguments[6] === undefined ? 0 : arguments[6];
  33222. var makeSprite = arguments.length <= 7 || arguments[7] === undefined ? undefined : arguments[7];
  33223. var extra = arguments.length <= 8 || arguments[8] === undefined ? undefined : arguments[8];
  33224. var o = this.spriteUtilities.grid(columns, rows, cellWidth, cellHeight, centerCell, xOffset, yOffset, makeSprite, extra);
  33225. this.addProperties(o);
  33226. this.stage.addChild(o);
  33227. return o;
  33228. }
  33229. //`makeTiledWorld` uses a Tiled Editor JSON file to generate a game
  33230. //world. It uses the `makeTiledWorld` method from the
  33231. //`tileUtilities` module to do help do this.
  33232. }, {
  33233. key: "makeTiledWorld",
  33234. value: function makeTiledWorld(jsonTiledMap, tileset) {
  33235. var _this4 = this;
  33236. var o = this.tileUtilities.makeTiledWorld(jsonTiledMap, tileset);
  33237. this.addProperties(o);
  33238. //Add Hexi's special sprite properties to the world object and all
  33239. //its child objects
  33240. var addHexiSpriteProperties = function addHexiSpriteProperties(object) {
  33241. _this4.addProperties(object);
  33242. if (object.children) {
  33243. if (object.children.length > 0) {
  33244. object.children.forEach(function (child) {
  33245. addHexiSpriteProperties(child);
  33246. });
  33247. }
  33248. }
  33249. };
  33250. if (o.children) {
  33251. if (o.children.length > 0) {
  33252. o.children.forEach(function (child) {
  33253. addHexiSpriteProperties(child);
  33254. });
  33255. }
  33256. }
  33257. //Return the world object
  33258. this.stage.addChild(o);
  33259. return o;
  33260. }
  33261. //Use `remove` to remove a sprite from its parent. You can supply a
  33262. //single sprite, a list of sprites, or an array of sprites
  33263. }, {
  33264. key: "remove",
  33265. value: function remove() {
  33266. var _spriteUtilities2;
  33267. (_spriteUtilities2 = this.spriteUtilities).remove.apply(_spriteUtilities2, arguments);
  33268. }
  33269. //The flow methods: `flowRight`, `flowDown`, `flowLeft` and
  33270. //`flowUp`.
  33271. //Use them to easily align a row of sprites horizontally or
  33272. //vertically. The flow methods take two arguments: the padding (in
  33273. //pixels) between the sprites, and list of sprites (or an array
  33274. //containing sprites) that you want to align.
  33275. //(This feature was inspired by the Elm programming language)
  33276. //flowRight
  33277. }, {
  33278. key: "flowRight",
  33279. value: function flowRight(padding) {
  33280. //A function to flow the sprites
  33281. var flowSprites = function flowSprites(spritesToFlow) {
  33282. if (spritesToFlow.length > 0) {
  33283. for (var i = 0; i < spritesToFlow.length - 1; i++) {
  33284. var sprite = spritesToFlow[i];
  33285. sprite.putRight(spritesToFlow[i + 1], +padding);
  33286. }
  33287. }
  33288. };
  33289. //Check if `sprites` is a an array of sprites, or an
  33290. //array containing sprite objects
  33291. for (var _len = arguments.length, sprites = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  33292. sprites[_key - 1] = arguments[_key];
  33293. }
  33294. if (!(sprites[0] instanceof Array)) {
  33295. //It's an array of sprites
  33296. flowSprites(sprites);
  33297. } else {
  33298. //It's an array containing sprite objects
  33299. var spritesArray = sprites[0];
  33300. flowSprites(spritesArray);
  33301. }
  33302. }
  33303. //flowDown
  33304. }, {
  33305. key: "flowDown",
  33306. value: function flowDown(padding) {
  33307. var flowSprites = function flowSprites(spritesToFlow) {
  33308. if (spritesToFlow.length > 0) {
  33309. for (var i = 0; i < spritesToFlow.length - 1; i++) {
  33310. var sprite = spritesToFlow[i];
  33311. sprite.putBottom(spritesToFlow[i + 1], 0, +padding);
  33312. }
  33313. }
  33314. };
  33315. for (var _len2 = arguments.length, sprites = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
  33316. sprites[_key2 - 1] = arguments[_key2];
  33317. }
  33318. if (!(sprites[0] instanceof Array)) {
  33319. flowSprites(sprites);
  33320. } else {
  33321. var spritesArray = sprites[0];
  33322. flowSprites(spritesArray);
  33323. }
  33324. }
  33325. //flowLeft
  33326. }, {
  33327. key: "flowLeft",
  33328. value: function flowLeft(padding) {
  33329. var flowSprites = function flowSprites(spritesToFlow) {
  33330. if (spritesToFlow.length > 0) {
  33331. for (var i = 0; i < spritesToFlow.length - 1; i++) {
  33332. var sprite = spritesToFlow[i];
  33333. sprite.putLeft(spritesToFlow[i + 1], -padding);
  33334. }
  33335. }
  33336. };
  33337. for (var _len3 = arguments.length, sprites = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
  33338. sprites[_key3 - 1] = arguments[_key3];
  33339. }
  33340. if (!(sprites[0] instanceof Array)) {
  33341. flowSprites(sprites);
  33342. } else {
  33343. var spritesArray = sprites[0];
  33344. flowSprites(spritesArray);
  33345. }
  33346. }
  33347. //flowUp
  33348. }, {
  33349. key: "flowUp",
  33350. value: function flowUp(padding) {
  33351. var flowSprites = function flowSprites(spritesToFlow) {
  33352. if (spritesToFlow.length > 0) {
  33353. for (var i = 0; i < spritesToFlow.length - 1; i++) {
  33354. var sprite = spritesToFlow[i];
  33355. sprite.putTop(spritesToFlow[i + 1], 0, -padding);
  33356. }
  33357. }
  33358. };
  33359. for (var _len4 = arguments.length, sprites = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
  33360. sprites[_key4 - 1] = arguments[_key4];
  33361. }
  33362. if (!(sprites[0] instanceof Array)) {
  33363. flowSprites(sprites);
  33364. } else {
  33365. var spritesArray = sprites[0];
  33366. flowSprites(spritesArray);
  33367. }
  33368. }
  33369. //7. SPRITE PROPERTIES
  33370. //The sprite creation methods above all run the `addProperties`
  33371. //method on each sprite they create. `addProperties` adds special
  33372. //properties and methods (super powers!) to Hexi sprites.
  33373. }, {
  33374. key: "addProperties",
  33375. value: function addProperties(o) {
  33376. var _this5 = this;
  33377. //Velocity
  33378. o.vx = 0;
  33379. o.vy = 0;
  33380. //A "private" `_layer` property
  33381. o._layer = 0;
  33382. //Is the sprite circular? If it is, it will be given a `radius`
  33383. //and `diameter`
  33384. o._circular = false;
  33385. //Is the sprite interactive? Setting this to `true` makes the
  33386. //sprite behave like a button
  33387. o._interact = false;
  33388. //Is the sprite draggable?
  33389. o._draggable = false;
  33390. //Flag this object for compatibility with the Bump collision
  33391. //library
  33392. o._bumpPropertiesAdded = true;
  33393. //Swap the depth layer positions of two child sprites
  33394. o.swapChildren = function (child1, child2) {
  33395. var index1 = o.children.indexOf(child1),
  33396. index2 = o.children.indexOf(child2);
  33397. if (index1 !== -1 && index2 !== -1) {
  33398. //Swap the indexes
  33399. child1.childIndex = index2;
  33400. child2.childIndex = index1;
  33401. //Swap the array positions
  33402. o.children[index1] = child2;
  33403. o.children[index2] = child1;
  33404. } else {
  33405. throw new Error(child + " Both objects must be a child of the caller " + o);
  33406. }
  33407. };
  33408. //`add` and `remove` convenience methods let you add and remove
  33409. //many sprites at the same time.
  33410. o.add = function () {
  33411. for (var _len5 = arguments.length, sprites = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
  33412. sprites[_key5] = arguments[_key5];
  33413. }
  33414. if (sprites.length > 1) {
  33415. sprites.forEach(function (sprite) {
  33416. return o.addChild(sprite);
  33417. });
  33418. } else {
  33419. o.addChild(sprites[0]);
  33420. }
  33421. };
  33422. o.remove = function () {
  33423. for (var _len6 = arguments.length, sprites = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
  33424. sprites[_key6] = arguments[_key6];
  33425. }
  33426. if (sprites.length > 1) {
  33427. sprites.forEach(function (sprite) {
  33428. return o.removeChild(sprite);
  33429. });
  33430. } else {
  33431. o.removeChild(sprites[0]);
  33432. }
  33433. };
  33434. //The `put` methods are conveniences that help you position a
  33435. //another sprite in and around this sprite.
  33436. //First, get a short form reference to the sprite to make the code
  33437. //easier to read
  33438. var a = o;
  33439. //The `nudgeAnchor`, `compensateForAnchor` and
  33440. //`compensateForAnchors` (with an "s"!) methods are used by
  33441. //the `put` methods to adjust the position of the sprite based on
  33442. //its x/y anchor point.
  33443. var nudgeAnchor = function nudgeAnchor(o, value, axis) {
  33444. if (o.anchor !== undefined) {
  33445. if (o.anchor[axis] !== 0) {
  33446. return value * (1 - o.anchor[axis] - o.anchor[axis]);
  33447. } else {
  33448. return value;
  33449. }
  33450. } else {
  33451. return value;
  33452. }
  33453. };
  33454. var compensateForAnchor = function compensateForAnchor(o, value, axis) {
  33455. if (o.anchor !== undefined) {
  33456. if (o.anchor[axis] !== 0) {
  33457. return value * o.anchor[axis];
  33458. } else {
  33459. return 0;
  33460. }
  33461. } else {
  33462. return 0;
  33463. }
  33464. };
  33465. var compensateForAnchors = function compensateForAnchors(a, b, property1, property2) {
  33466. return compensateForAnchor(a, a[property1], property2) + compensateForAnchor(b, b[property1], property2);
  33467. };
  33468. //The `put` methods:
  33469. //Center a sprite inside this sprite. `xOffset` and `yOffset`
  33470. //arguments determine by how much the other sprite's position
  33471. //should be offset from the center. These methods use the
  33472. //sprites' global coordinates (`gx` and `gy`).
  33473. //In all these functions, `b` is the second sprite that is being
  33474. //positioned relative to the first sprite (this one), `a`.
  33475. //Center `b` inside `a`.
  33476. o.putCenter = function (b) {
  33477. var xOffset = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
  33478. var yOffset = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2];
  33479. if (o._stage) a = _this5.compensateForStageSize(o);
  33480. //b.x = (a.x + a.halfWidth - (b.halfWidth * ((1 - b.anchor.x) - b.anchor.x))) + xOffset;
  33481. b.x = a.x + nudgeAnchor(a, a.halfWidth, "x") - nudgeAnchor(b, b.halfWidth, "x") + xOffset;
  33482. b.y = a.y + nudgeAnchor(a, a.halfHeight, "y") - nudgeAnchor(b, b.halfHeight, "y") + yOffset;
  33483. //Compensate for the parent's position
  33484. if (!o._stage) o.compensateForParentPosition(a, b);
  33485. };
  33486. //Position `b` to the left of `a`.
  33487. o.putLeft = function (b) {
  33488. var xOffset = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
  33489. var yOffset = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2];
  33490. if (o._stage) a = _this5.compensateForStageSize(o);
  33491. b.x = a.x - nudgeAnchor(b, b.width, "x") + xOffset - compensateForAnchors(a, b, "width", "x");
  33492. b.y = a.y + nudgeAnchor(a, a.halfHeight, "y") - nudgeAnchor(b, b.halfHeight, "y") + yOffset;
  33493. //Compensate for the parent's position
  33494. if (!o._stage) o.compensateForParentPosition(a, b);
  33495. };
  33496. //Position `b` above `a`.
  33497. o.putTop = function (b) {
  33498. var xOffset = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
  33499. var yOffset = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2];
  33500. if (o._stage) a = _this5.compensateForStageSize(o);
  33501. b.x = a.x + nudgeAnchor(a, a.halfWidth, "x") - nudgeAnchor(b, b.halfWidth, "x") + xOffset;
  33502. b.y = a.y - nudgeAnchor(b, b.height, "y") + yOffset - compensateForAnchors(a, b, "height", "y");
  33503. //Compensate for the parent's position
  33504. if (!o._stage) o.compensateForParentPosition(a, b);
  33505. };
  33506. //Position `b` to the right of `a`.
  33507. o.putRight = function (b) {
  33508. var xOffset = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
  33509. var yOffset = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2];
  33510. if (o._stage) a = _this5.compensateForStageSize(o);
  33511. b.x = a.x + nudgeAnchor(a, a.width, "x") + xOffset + compensateForAnchors(a, b, "width", "x");
  33512. b.y = a.y + nudgeAnchor(a, a.halfHeight, "y") - nudgeAnchor(b, b.halfHeight, "y") + yOffset;
  33513. //b.x = (a.x + a.width) + xOffset;
  33514. //b.y = (a.y + a.halfHeight - b.halfHeight) + yOffset;
  33515. //Compensate for the parent's position
  33516. if (!o._stage) o.compensateForParentPosition(a, b);
  33517. };
  33518. //Position `b` below `a`.
  33519. o.putBottom = function (b) {
  33520. var xOffset = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
  33521. var yOffset = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2];
  33522. if (o._stage) a = _this5.compensateForStageSize(o);
  33523. //b.x = (a.x + a.halfWidth - b.halfWidth) + xOffset;
  33524. b.x = a.x + nudgeAnchor(a, a.halfWidth, "x") - nudgeAnchor(b, b.halfWidth, "x") + xOffset;
  33525. //b.y = (a.y + a.height) + yOffset;
  33526. b.y = a.y + nudgeAnchor(a, a.height, "y") + yOffset + compensateForAnchors(a, b, "height", "y");
  33527. //Compensate for the parent's position
  33528. if (!o._stage) o.compensateForParentPosition(a, b);
  33529. };
  33530. //`compensateForParentPosition` is a helper function for the above
  33531. //`put` methods that subracts the parent's global position from
  33532. //the nested child's position.
  33533. o.compensateForParentPosition = function (a, b) {
  33534. if (b.parent.gx !== 0 || b.parent.gy !== 0) {
  33535. b.x -= a.gx;
  33536. b.y -= a.gy;
  33537. }
  33538. };
  33539. var self = this;
  33540. Object.defineProperties(o, {
  33541. "gx": {
  33542. get: function get() {
  33543. return o.getGlobalPosition().x;
  33544. },
  33545. enumerable: true,
  33546. configurable: true
  33547. },
  33548. "gy": {
  33549. get: function get() {
  33550. return o.getGlobalPosition().y;
  33551. },
  33552. enumerable: true,
  33553. configurable: true
  33554. },
  33555. "centerX": {
  33556. get: function get() {
  33557. return o.x + o.width / 2 - o.xAnchorOffset;
  33558. },
  33559. enumerable: true,
  33560. configurable: true
  33561. },
  33562. "centerY": {
  33563. get: function get() {
  33564. return o.y + o.height / 2 - o.yAnchorOffset;
  33565. },
  33566. enumerable: true,
  33567. configurable: true
  33568. },
  33569. "halfWidth": {
  33570. get: function get() {
  33571. return o.width / 2;
  33572. },
  33573. enumerable: true,
  33574. configurable: true
  33575. },
  33576. "halfHeight": {
  33577. get: function get() {
  33578. return o.height / 2;
  33579. },
  33580. enumerable: true,
  33581. configurable: true
  33582. },
  33583. "scaleModeNearest": {
  33584. set: function set(value) {
  33585. if (o.texture.baseTexture) {
  33586. if (value) {
  33587. o.texture.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST;
  33588. } else {
  33589. o.texture.baseTexture.scaleMode = PIXI.SCALE_MODES.LINEAR;
  33590. }
  33591. } else {
  33592. throw new Error("The scale mode of " + o + " cannot be modified");
  33593. }
  33594. },
  33595. enumerable: true,
  33596. configurable: true
  33597. },
  33598. "pivotX": {
  33599. get: function get() {
  33600. return o.anchor.x;
  33601. },
  33602. set: function set(value) {
  33603. if (o.anchor === undefined) {
  33604. throw new Error(o + " does not have a PivotX value");
  33605. }
  33606. o.anchor.x = value;
  33607. if (!o._previousPivotX) {
  33608. o.x += value * o.width;
  33609. } else {
  33610. o.x += (value - o._previousPivotX) * o.width;
  33611. }
  33612. o._previousPivotX = value;
  33613. },
  33614. enumerable: true,
  33615. configurable: true
  33616. },
  33617. "pivotY": {
  33618. get: function get() {
  33619. return o.anchor.y;
  33620. },
  33621. set: function set(value) {
  33622. if (o.anchor === undefined) {
  33623. throw new Error(o + " does not have a PivotY value");
  33624. }
  33625. o.anchor.y = value;
  33626. if (!o._previousPivotY) {
  33627. o.y += value * o.height;
  33628. } else {
  33629. o.y += (value - o._previousPivotY) * o.height;
  33630. }
  33631. o._previousPivotY = value;
  33632. },
  33633. enumerable: true,
  33634. configurable: true
  33635. },
  33636. "xAnchorOffset": {
  33637. get: function get() {
  33638. if (o.anchor !== undefined) {
  33639. return o.height * o.anchor.x;
  33640. } else {
  33641. return 0;
  33642. }
  33643. },
  33644. enumerable: true,
  33645. configurable: true
  33646. },
  33647. "yAnchorOffset": {
  33648. get: function get() {
  33649. if (o.anchor !== undefined) {
  33650. return o.width * o.anchor.y;
  33651. } else {
  33652. return 0;
  33653. }
  33654. },
  33655. enumerable: true,
  33656. configurable: true
  33657. },
  33658. "scaleX": {
  33659. get: function get() {
  33660. return o.scale.x;
  33661. },
  33662. set: function set(value) {
  33663. o.scale.x = value;
  33664. },
  33665. enumerable: true,
  33666. configurable: true
  33667. },
  33668. "scaleY": {
  33669. get: function get() {
  33670. return o.scale.y;
  33671. },
  33672. set: function set(value) {
  33673. o.scale.y = value;
  33674. },
  33675. enumerable: true,
  33676. configurable: true
  33677. },
  33678. //Depth layer
  33679. "layer": {
  33680. get: function get() {
  33681. return o._layer;
  33682. },
  33683. set: function set(value) {
  33684. o._layer = value;
  33685. if (o.parent) {
  33686. //Sort the sprite’s parent’s `children` array so that sprites with a
  33687. //higher `layer` value are moved to the end of the array
  33688. o.parent.children.sort(function (a, b) {
  33689. return a.layer - b.layer;
  33690. });
  33691. }
  33692. },
  33693. enumerable: true,
  33694. configurable: true
  33695. },
  33696. //Interactivity
  33697. "interact": {
  33698. get: function get() {
  33699. return o._interact;
  33700. },
  33701. set: function set(value) {
  33702. if (value === true) {
  33703. if (!o._interact) {
  33704. self.makeInteractive(o);
  33705. o._interact = true;
  33706. }
  33707. } else {
  33708. if (self.tink.buttons.indexOf(o) !== -1) {
  33709. self.tink.buttons.splice(self.tink.buttons.indexOf(o), 1);
  33710. o._interact = false;
  33711. }
  33712. }
  33713. },
  33714. enumerable: true,
  33715. configurable: true
  33716. },
  33717. //Drag and drop
  33718. "draggable": {
  33719. get: function get() {
  33720. return o._draggable;
  33721. },
  33722. set: function set(value) {
  33723. if (value === true) {
  33724. if (!o._draggable) {
  33725. self.makeDraggable(o);
  33726. o._draggable = true;
  33727. }
  33728. } else {
  33729. self.makeUndraggable(o);
  33730. o._draggable = false;
  33731. }
  33732. },
  33733. enumerable: true,
  33734. configurable: true
  33735. },
  33736. //The `localBounds` and `globalBounds` methods return an object
  33737. //with `x`, `y`, `width`, and `height` properties that define
  33738. //the dimensions and position of the sprite. This is a convenience
  33739. //to help you set or test boundaries without having to know
  33740. //these numbers or request them specifically in your code.
  33741. "localBounds": {
  33742. get: function get() {
  33743. return {
  33744. x: 0,
  33745. y: 0,
  33746. width: o.width,
  33747. height: o.height
  33748. };
  33749. },
  33750. enumerable: true,
  33751. configurable: true
  33752. },
  33753. "globalBounds": {
  33754. get: function get() {
  33755. return {
  33756. x: o.gx,
  33757. y: o.gy,
  33758. width: o.gx + o.width,
  33759. height: o.gy + o.height
  33760. };
  33761. },
  33762. enumerable: true,
  33763. configurable: true
  33764. },
  33765. //`empty` is a convenience property that will return `true` or
  33766. //`false` depending on whether or not this sprite's `children`
  33767. //array is empty
  33768. "empty": {
  33769. get: function get() {
  33770. if (o.children.length === 0) {
  33771. return true;
  33772. } else {
  33773. return false;
  33774. }
  33775. },
  33776. enumerable: true,
  33777. configurable: true
  33778. },
  33779. //The `circular` property lets you define whether a sprite
  33780. //should be interpreted as a circular object. If you set
  33781. //`circular` to `true`, the sprite is given `radius` and `diameter`
  33782. //properties. If you set `circular` to `false`, the `radius`
  33783. //and `diameter` properties are deleted from the sprite
  33784. "circular": {
  33785. get: function get() {
  33786. return o._circular;
  33787. },
  33788. set: function set(value) {
  33789. //Give the sprite `diameter` and `radius` properties
  33790. //if `circular` is `true`
  33791. if (value === true && o._circular === false) {
  33792. Object.defineProperties(o, {
  33793. "diameter": {
  33794. get: function get() {
  33795. return o.width;
  33796. },
  33797. set: function set(value) {
  33798. o.width = value;
  33799. o.height = value;
  33800. },
  33801. enumerable: true,
  33802. configurable: true
  33803. },
  33804. "radius": {
  33805. get: function get() {
  33806. return o.halfWidth;
  33807. },
  33808. set: function set(value) {
  33809. o.width = value * 2;
  33810. o.height = value * 2;
  33811. },
  33812. enumerable: true,
  33813. configurable: true
  33814. }
  33815. });
  33816. //Set o.sprite's `_circular` property to `true`
  33817. o._circular = true;
  33818. }
  33819. //Remove the sprite's `diameter` and `radius` properties
  33820. //if `circular` is `false`
  33821. if (value === false && o._circular === true) {
  33822. delete o.diameter;
  33823. delete o.radius;
  33824. o._circular = false;
  33825. }
  33826. },
  33827. enumerable: true,
  33828. configurable: true
  33829. }
  33830. });
  33831. //A `setPosition` convenience method to let you set the
  33832. //x any y position of a sprite with one line of code.
  33833. o.setPosition = function (x, y) {
  33834. o.x = x;
  33835. o.y = y;
  33836. };
  33837. //A similar `setScale` convenience method
  33838. o.setScale = function (xScale, yScale) {
  33839. o.scale.x = xScale;
  33840. o.scale.y = yScale;
  33841. };
  33842. //And a matching `setPivot` method
  33843. o.setPivot = function (xPivot, yPivot) {
  33844. o.pivotX = xPivot;
  33845. o.pivotY = yPivot;
  33846. };
  33847. if (o.circular) {
  33848. Object.defineProperty(o, "radius", {
  33849. get: function get() {
  33850. return o.width / 2;
  33851. },
  33852. enumerable: true,
  33853. configurable: true
  33854. });
  33855. }
  33856. }
  33857. //8. Utilities
  33858. //A method to scale and align the canvas in the browser
  33859. //window using the `scaleToWindow.js` function module
  33860. }, {
  33861. key: "scaleToWindow",
  33862. value: (function (_scaleToWindow) {
  33863. function scaleToWindow() {
  33864. return _scaleToWindow.apply(this, arguments);
  33865. }
  33866. scaleToWindow.toString = function () {
  33867. return _scaleToWindow.toString();
  33868. };
  33869. return scaleToWindow;
  33870. })(function () {
  33871. var _this6 = this;
  33872. var scaleBorderColor = arguments.length <= 0 || arguments[0] === undefined ? "#2C3539" : arguments[0];
  33873. //Set the default CSS padding and margins of HTML elements to 0
  33874. //<style>* {padding: 0; margin: 0}</style>
  33875. var newStyle = document.createElement("style");
  33876. var style = "* {padding: 0; margin: 0}";
  33877. newStyle.appendChild(document.createTextNode(style));
  33878. document.head.appendChild(newStyle);
  33879. //Use the `scaleToWindow` function module to scale the canvas to
  33880. //the maximum window size
  33881. this.scale = scaleToWindow(this.canvas, scaleBorderColor);
  33882. this.pointer.scale = this.scale;
  33883. //this.pointer = this.makePointer(this.canvas, this.scale);
  33884. console.log(this.pointer);
  33885. //Re-scale on each browser resize
  33886. window.addEventListener("resize", function (event) {
  33887. //Scale the canvas and update Hexi's global `scale` value and
  33888. //the pointer's `scale` value
  33889. _this6.scale = scaleToWindow(_this6.canvas, scaleBorderColor);
  33890. _this6.pointer.scale = _this6.scale;
  33891. });
  33892. //Flag that the canvas has been scaled
  33893. this.canvas.scaled = true;
  33894. })
  33895. //`log` is a shortcut for `console.log`, so that you have less to
  33896. //type when you're debugging
  33897. }, {
  33898. key: "log",
  33899. value: function log(value) {
  33900. return console.log(value);
  33901. }
  33902. //The `makeProgressBar` method creates a `progressBar` object with
  33903. //`create`, `update` and `remove` methods. It's called by the
  33904. //`loadingBar` method, which should be run inside the `load`
  33905. //function of your application code.
  33906. }, {
  33907. key: "makeProgressBar",
  33908. value: function makeProgressBar(hexiObject) {
  33909. var hexi = hexiObject;
  33910. //The `progressBar` object
  33911. hexi.progressBar = {
  33912. maxWidth: 0,
  33913. height: 0,
  33914. backgroundColor: "0x808080",
  33915. foregroundColor: "0x00FFFF",
  33916. backBar: null,
  33917. frontBar: null,
  33918. percentage: null,
  33919. assets: null,
  33920. initialized: false,
  33921. //Use the `create` method to create the progress bar
  33922. create: function create() {
  33923. //Set the maximum width to half the width of the canvas
  33924. this.maxWidth = hexi.canvas.width / 2;
  33925. //Build the progress bar using two rectangle sprites and
  33926. //one text sprite
  33927. //1. Create the background bar's gray background
  33928. this.backBar = hexi.rectangle(this.maxWidth, 32, this.backgroundColor);
  33929. this.backBar.x = hexi.canvas.width / 2 - this.maxWidth / 2;
  33930. this.backBar.y = hexi.canvas.height / 2 - 16;
  33931. //2. Create the blue foreground bar. This is the element of the
  33932. //progress bar that will increase in width as assets load
  33933. this.frontBar = hexi.rectangle(this.maxWidth, 32, this.foregroundColor);
  33934. this.frontBar.x = hexi.canvas.width / 2 - this.maxWidth / 2;
  33935. this.frontBar.y = hexi.canvas.height / 2 - 16;
  33936. //3. A text sprite that will display the percentage
  33937. //of assets that have loaded
  33938. this.percentage = hexi.text("0%", "28px sans-serif", "black");
  33939. this.percentage.x = hexi.canvas.width / 2 - this.maxWidth / 2 + 12;
  33940. this.percentage.y = hexi.canvas.height / 2 - 17;
  33941. },
  33942. //Use the `update` method to update the width of the bar and
  33943. //percentage loaded each frame
  33944. update: function update() {
  33945. //Change the width of the blue `frontBar` to match the
  33946. //ratio of assets that have loaded.
  33947. var ratio = hexi.loadingProgress / 100;
  33948. //console.log(`ratio: ${ratio}`);
  33949. this.frontBar.width = this.maxWidth * ratio;
  33950. //Display the percentage
  33951. this.percentage.content = Math.round(hexi.loadingProgress) + " %";
  33952. },
  33953. //Use the `remove` method to remove the progress bar when all the
  33954. //game assets have finished loading
  33955. remove: function remove() {
  33956. //Remove the progress bar using the universal sprite `remove`
  33957. //function
  33958. hexi.stage.removeChild(this.frontBar);
  33959. hexi.stage.removeChild(this.backBar);
  33960. hexi.stage.removeChild(this.percentage);
  33961. }
  33962. };
  33963. }
  33964. //The `loadingBar` method should be called inside the user-definable
  33965. //`load` method in the application code. This function will run in a
  33966. //loop. It will create the loading bar, and then call the loading
  33967. //bar's `update` method each frame. After all the assets have been
  33968. //loaded, Hexi's `validateAssets` method removes the loading bar.
  33969. }, {
  33970. key: "loadingBar",
  33971. value: function loadingBar() {
  33972. if (!this._progressBarAdded) {
  33973. //Run the method that creates the progress bar object
  33974. this.makeProgressBar(this);
  33975. //Create the loading bar
  33976. this.progressBar.create();
  33977. //Tell Hexi that a progress bar has been added
  33978. this._progressBarAdded = true;
  33979. } else {
  33980. //Update the progress bar each frame
  33981. this.progressBar.update();
  33982. }
  33983. }
  33984. //Hexi's root `stage` object will have a width and height equal to
  33985. //its contents, not the size of the canvas. So, let's use the more
  33986. //useful canvas width and height for relative positioning instead
  33987. }, {
  33988. key: "compensateForStageSize",
  33989. value: function compensateForStageSize(o) {
  33990. if (o._stage === true) {
  33991. var a = {};
  33992. a.x = 0;
  33993. a.y = 0;
  33994. a.width = this.canvas.width;
  33995. a.height = this.canvas.height;
  33996. a.halfWidth = this.canvas.width / 2;
  33997. a.halfHeight = this.canvas.height / 2;
  33998. a.xAnchorOffset = 0;
  33999. a.yAnchorOffset = 0;
  34000. return a;
  34001. }
  34002. }
  34003. //High level functions for accessing the loaded resources and custom parsed
  34004. //objects, like sounds.
  34005. }, {
  34006. key: "image",
  34007. value: function image(imageFileName) {
  34008. if (this.TextureCache[imageFileName]) {
  34009. return this.TextureCache[imageFileName];
  34010. } else {
  34011. throw new Error(imageFileName + " does not appear to be an image");
  34012. }
  34013. }
  34014. }, {
  34015. key: "id",
  34016. value: function id(textureAtlasFrameId) {
  34017. if (this.TextureCache[textureAtlasFrameId]) {
  34018. return this.TextureCache[textureAtlasFrameId];
  34019. } else {
  34020. throw new Error(textureAtlasFrameId + " does not appear to be a texture atlas frame id");
  34021. }
  34022. }
  34023. }, {
  34024. key: "json",
  34025. value: function json(jsonFileName) {
  34026. if (this.loader.resources[jsonFileName].data) {
  34027. return this.resources[jsonFileName].data;
  34028. } else {
  34029. throw new Error(jsonFileName + " does not appear to be a JSON data file");
  34030. }
  34031. }
  34032. }, {
  34033. key: "xml",
  34034. value: function xml(xmlFileName) {
  34035. if (this.loader.resources[xmlFileName].data) {
  34036. return this.resources[xmlFileName].data;
  34037. } else {
  34038. throw new Error(xmlFileName + " does not appear to be a XML data file");
  34039. }
  34040. }
  34041. }, {
  34042. key: "sound",
  34043. value: function sound(soundFileName) {
  34044. if (this.soundObjects[soundFileName]) {
  34045. return this.soundObjects[soundFileName];
  34046. } else {
  34047. throw new Error(soundFileName + " does not appear to be a sound object");
  34048. }
  34049. }
  34050. }, {
  34051. key: "resources",
  34052. get: function get() {
  34053. return this.loader.resources;
  34054. }
  34055. //Add Smoothie getters and setters to access the `fps`,
  34056. //`properties`, `renderFps` and `interpolate` properties
  34057. }, {
  34058. key: "fps",
  34059. get: function get() {
  34060. return this.smoothie.fps;
  34061. },
  34062. set: function set(value) {
  34063. this.smoothie.fps = value;
  34064. }
  34065. }, {
  34066. key: "renderFps",
  34067. get: function get() {
  34068. return this.smoothie.renderFps;
  34069. },
  34070. set: function set(value) {
  34071. this.smoothie.renderFps = value;
  34072. }
  34073. }, {
  34074. key: "interpolate",
  34075. get: function get() {
  34076. return this.smoothie.interpolate;
  34077. },
  34078. set: function set(value) {
  34079. this.smoothie.interpolate = value;
  34080. }
  34081. }, {
  34082. key: "interpolationProperties",
  34083. get: function get() {
  34084. return this.smoothie.properties;
  34085. },
  34086. set: function set(value) {
  34087. this.smoothie.properties = value;
  34088. }
  34089. //The `border` property lets you set the border style on the canvas
  34090. }, {
  34091. key: "border",
  34092. set: function set(value) {
  34093. this.canvas.style.border = value;
  34094. }
  34095. //The `backgroundColor` property lets you set the background color
  34096. //of the renderer
  34097. }, {
  34098. key: "backgroundColor",
  34099. set: function set(value) {
  34100. this.renderer.backgroundColor = this.color(value);
  34101. }
  34102. }]);
  34103. return Hexi;
  34104. })();
  34105. //# sourceMappingURL=core.js.map