From 32484eb89e5a10e199b4edd71893fee05af7792e Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Mon, 19 Feb 2024 14:06:44 +0000 Subject: [PATCH] add more examples for v8 --- src/examples/v8.0.0/basic/blendModes.js | 147 ++-- src/examples/v8.0.0/basic/renderGroup.js | 66 ++ src/examples/v8.0.0/examplesData.json | 9 +- .../{basic => graphics}/fillGradient.js | 0 src/examples/v8.0.0/graphics/meshFromPath.js | 56 ++ src/examples/v8.0.0/graphics/svg-load.js | 37 + src/examples/v8.0.0/graphics/svg.js | 36 + src/examples/v8.0.0/graphics/texture.js | 41 + src/examples/v8.0.0/index.ts | 14 +- static/assets/rainbow-gradient.png | Bin 0 -> 40753 bytes static/assets/tiger.svg | 725 ++++++++++++++++++ static/assets/tree.png | Bin 0 -> 2692 bytes 12 files changed, 1048 insertions(+), 83 deletions(-) create mode 100644 src/examples/v8.0.0/basic/renderGroup.js rename src/examples/v8.0.0/{basic => graphics}/fillGradient.js (100%) create mode 100644 src/examples/v8.0.0/graphics/meshFromPath.js create mode 100644 src/examples/v8.0.0/graphics/svg-load.js create mode 100644 src/examples/v8.0.0/graphics/svg.js create mode 100644 src/examples/v8.0.0/graphics/texture.js create mode 100644 static/assets/rainbow-gradient.png create mode 100644 static/assets/tiger.svg create mode 100644 static/assets/tree.png diff --git a/src/examples/v8.0.0/basic/blendModes.js b/src/examples/v8.0.0/basic/blendModes.js index 3dc03bac5..75932bf30 100644 --- a/src/examples/v8.0.0/basic/blendModes.js +++ b/src/examples/v8.0.0/basic/blendModes.js @@ -1,4 +1,6 @@ -import { Application, Assets, Sprite, Rectangle } from 'pixi.js'; +import 'pixi.js/advanced-blend-modes'; + +import { Application, Assets, Container, Sprite } from 'pixi.js'; (async () => { @@ -6,99 +8,86 @@ import { Application, Assets, Sprite, Rectangle } from 'pixi.js'; const app = new Application(); // Initialize the application - await app.init({ resizeTo: window }); + await app.init({ + antialias: true, + backgroundColor: 'white', + resizeTo: window, + // NEEDS TO BE TRUE FOR WEBGL! + useBackBuffer: true, + }); // Append the application canvas to the document body document.body.appendChild(app.canvas); - // Load the textures - const bgTexture = await Assets.load('https://pixijs.com/assets/bg_rotate.jpg'); - const alienTexture = await Assets.load('https://pixijs.com/assets/flowerTop.png'); - - // Create a new background sprite - const background = new Sprite(bgTexture); - - background.width = app.screen.width; - background.height = app.screen.height; - app.stage.addChild(background); - - // Create an array to store references to the dudes - const dudeArray = []; - - const totaldudes = 20; - - for (let i = 0; i < totaldudes; i++) + const pandaTexture = await Assets.load(`https://pixijs.com/assets/panda.png`); + const rainbowGradient = await Assets.load(`https://pixijs.com/assets/rainbow-gradient.png`); + + const allBlendModes = [ + 'normal', + 'add', + 'screen', + 'darken', + 'lighten', + 'color-dodge', + 'color-burn', + 'linear-burn', + 'linear-dodge', + 'linear-light', + 'hard-light', + 'soft-light', + 'pin-light', + 'difference', + 'exclusion', + 'overlay', + 'saturation', + 'color', + 'luminosity', + 'add-npm', + 'subtract', + 'divide', + 'vivid-light', + 'hard-mix', + 'negation', + ]; + + const size = 800 / 5; + + const pandas = []; + + for (let i = 0; i < allBlendModes.length; i++) { - // Create a new alien Sprite - const dude = new Sprite(alienTexture); - - dude.anchor.set(0.5); - - // Set a random scale for the dude - dude.scale.set(0.8 + Math.random() * 0.3); + const container = new Container(); - // Finally let's set the dude to be at a random position... - dude.x = Math.floor(Math.random() * app.screen.width); - dude.y = Math.floor(Math.random() * app.screen.height); + const sprite = new Sprite({ + texture: pandaTexture, + width: 100, + height: 100, + anchor: 0.5, + position: { x: size / 2, y: size / 2 }, + }); - // The important bit of this example, this is how you change the default blend mode of the sprite - dude.blendMode = 'add'; + pandas.push(sprite); - // Create some extra properties that will control movement - dude.direction = Math.random() * Math.PI * 2; + const sprite2 = new Sprite({ + texture: rainbowGradient, + width: size, + height: size, + blendMode: allBlendModes[i], + }); - // This number will be used to modify the direction of the dude over time - dude.turningSpeed = Math.random() - 0.8; + container.addChild(sprite, sprite2); - // Create a random speed for the dude between 0 - 2 - dude.speed = 2 + Math.random() * 2; + app.stage.addChild(container); - // Finally we push the dude into the dudeArray so it it can be easily accessed later - dudeArray.push(dude); - - app.stage.addChild(dude); + container.x = (i % 5) * size; + container.y = Math.floor(i / 5) * size; } - // Create a bounding box for the little dudes - const dudeBoundsPadding = 100; - - const dudeBounds = new Rectangle( - -dudeBoundsPadding, - -dudeBoundsPadding, - app.screen.width + dudeBoundsPadding * 2, - app.screen.height + dudeBoundsPadding * 2, - ); - app.ticker.add(() => { - // Iterate through the dudes and update the positions - for (let i = 0; i < dudeArray.length; i++) + pandas.forEach((panda, i) => { - const dude = dudeArray[i]; - - dude.direction += dude.turningSpeed * 0.01; - dude.x += Math.sin(dude.direction) * dude.speed; - dude.y += Math.cos(dude.direction) * dude.speed; - dude.rotation = -dude.direction - Math.PI / 2; - - // Constrain the dudes' position by testing their bounds... - if (dude.x < dudeBounds.x) - { - dude.x += dudeBounds.width; - } - else if (dude.x > dudeBounds.x + dudeBounds.width) - { - dude.x -= dudeBounds.width; - } - - if (dude.y < dudeBounds.y) - { - dude.y += dudeBounds.height; - } - else if (dude.y > dudeBounds.y + dudeBounds.height) - { - dude.y -= dudeBounds.height; - } - } + panda.rotation += 0.01 * (i % 2 ? 1 : -1); + }); }); })(); diff --git a/src/examples/v8.0.0/basic/renderGroup.js b/src/examples/v8.0.0/basic/renderGroup.js new file mode 100644 index 000000000..ec09c5fbb --- /dev/null +++ b/src/examples/v8.0.0/basic/renderGroup.js @@ -0,0 +1,66 @@ +import { Application, Assets, Container, Sprite } from 'pixi.js'; + +(async () => +{ + // Create a new application + const app = new Application(); + + // Initialize the application + await app.init({ + backgroundColor: 'brown', + resizeTo: window, + }); + + const treeTexture = await Assets.load(`https://pixijs.com/assets/tree.png`); + + const worldContainer = new Container({ + // this will make moving this container GPU powered + isRenderGroup: true, + }); + + const worldSize = 5000; + + for (let i = 0; i < 100000; i++) + { + const yPos = Math.random() * worldSize; + + const tree = new Sprite({ + texture: treeTexture, + x: Math.random() * worldSize, + y: yPos, + scale: 0.25, + anchor: 0.5, + }); + + worldContainer.addChild(tree); + } + + // sort the trees by their y position + worldContainer.children.sort((a, b) => a.position.y - b.position.y); + + app.stage.addChild(worldContainer); + + // Append the application canvas to the document body + document.body.appendChild(app.canvas); + + let x = 0; + let y = 0; + + app.canvas.addEventListener('mousemove', (e) => + { + x = e.clientX; + y = e.clientY; + }); + + app.ticker.add(() => + { + const screenWidth = app.renderer.width; + const screenHeight = app.renderer.height; + + const targetX = (x / screenWidth) * (worldSize - screenWidth); + const targetY = (y / screenHeight) * (worldSize - screenHeight); + + worldContainer.x += (-targetX - worldContainer.x) * 0.1; + worldContainer.y += (-targetY - worldContainer.y) * 0.1; + }); +})(); diff --git a/src/examples/v8.0.0/examplesData.json b/src/examples/v8.0.0/examplesData.json index 09f1b63ef..74cfda3b6 100644 --- a/src/examples/v8.0.0/examplesData.json +++ b/src/examples/v8.0.0/examplesData.json @@ -6,7 +6,7 @@ "particleContainer", "blendModes", "meshPlane", - "fillGradient" + "renderGroup" ], "advanced": [ "slots", @@ -35,7 +35,12 @@ "graphics": [ "simple", "advanced", - "dynamic" + "dynamic", + "svg", + "svg-load", + "texture", + "fillGradient", + "meshFromPath" ], "events": [ "click", diff --git a/src/examples/v8.0.0/basic/fillGradient.js b/src/examples/v8.0.0/graphics/fillGradient.js similarity index 100% rename from src/examples/v8.0.0/basic/fillGradient.js rename to src/examples/v8.0.0/graphics/fillGradient.js diff --git a/src/examples/v8.0.0/graphics/meshFromPath.js b/src/examples/v8.0.0/graphics/meshFromPath.js new file mode 100644 index 000000000..938245e1b --- /dev/null +++ b/src/examples/v8.0.0/graphics/meshFromPath.js @@ -0,0 +1,56 @@ +import { Application, buildGeometryFromPath, Graphics, GraphicsPath, Mesh, Texture } from 'pixi.js'; + +(async () => +{ + // Create a new application + const app = new Application(); + + // Initialize the application + await app.init({ + backgroundColor: 'brown', + resizeTo: window, + antialias: true, + }); + + // Append the application canvas to the document body + document.body.appendChild(app.canvas); + + const path = new GraphicsPath() + .rect(-50, -50, 100, 100) + .circle(80, 80, 50) + .circle(80, -80, 50) + .circle(-80, 80, 50) + .circle(-80, -80, 50); + + const geometry = buildGeometryFromPath({ + path, + }); + + const meshes = []; + + for (let i = 0; i < 200; i++) + { + const x = Math.random() * app.screen.width; + const y = Math.random() * app.screen.height; + + const mesh = new Mesh({ + geometry, + texture: Texture.WHITE, + x, + y, + tint: Math.random() * 0xffffff, + }); + + app.stage.addChild(mesh); + + meshes.push(mesh); + } + + app.ticker.add(() => + { + meshes.forEach((mesh) => + { + mesh.rotation += 0.01; + }); + }); +})(); diff --git a/src/examples/v8.0.0/graphics/svg-load.js b/src/examples/v8.0.0/graphics/svg-load.js new file mode 100644 index 000000000..67bd35242 --- /dev/null +++ b/src/examples/v8.0.0/graphics/svg-load.js @@ -0,0 +1,37 @@ +import { Application, Assets, Graphics } from 'pixi.js'; + +(async () => +{ + // Create a new application + const app = new Application(); + + // Initialize the application + await app.init({ antialias: true, resizeTo: window }); + + // Append the application canvas to the document body + document.body.appendChild(app.canvas); + + const tigerSvg = await Assets.load({ + src: 'https://pixijs.com/assets/tiger.svg', + data: { + parseAsGraphicsContext: true, + }, + }); + + const graphics = new Graphics(tigerSvg); + + // line it up as this svg is not centered + const bounds = graphics.getLocalBounds(); + + graphics.pivot.set((bounds.x + bounds.width) / 2, (bounds.y + bounds.height) / 2); + + graphics.position.set(app.screen.width / 2, app.screen.height / 2); + + app.stage.addChild(graphics); + + app.ticker.add((time) => + { + graphics.rotation += 0.01; + graphics.scale.set(2 + Math.sin(graphics.rotation)); + }); +})(); diff --git a/src/examples/v8.0.0/graphics/svg.js b/src/examples/v8.0.0/graphics/svg.js new file mode 100644 index 000000000..b35053527 --- /dev/null +++ b/src/examples/v8.0.0/graphics/svg.js @@ -0,0 +1,36 @@ +import { Application, Assets, Graphics } from 'pixi.js'; + +(async () => +{ + // Create a new application + const app = new Application(); + + // Initialize the application + await app.init({ + antialias: true, + backgroundColor: 'white', + resizeTo: window, + }); + + // Append the application canvas to the document body + document.body.appendChild(app.canvas); + + const graphics = new Graphics().svg(` + + + + + + + + + + + + + + + `); + + app.stage.addChild(graphics); +})(); diff --git a/src/examples/v8.0.0/graphics/texture.js b/src/examples/v8.0.0/graphics/texture.js new file mode 100644 index 000000000..cd39b915f --- /dev/null +++ b/src/examples/v8.0.0/graphics/texture.js @@ -0,0 +1,41 @@ +import { Application, Assets, Graphics, GraphicsContext } from 'pixi.js'; + +(async () => +{ + // Create a new application + const app = new Application(); + + // Initialize the application + await app.init({ + antialias: true, + backgroundColor: 'white', + resizeTo: window, + }); + + // Append the application canvas to the document body + document.body.appendChild(app.canvas); + + const pandaTexture = await Assets.load(`https://pixijs.com/assets/panda.png`); + + const pandasContext = new GraphicsContext() + .circle(0, 0, 120) + .fill('green') + .texture(pandaTexture, 0xffffff, -pandaTexture.width / 2, -pandaTexture.height / 2) + // add a baby purple panda + .translate(100, 100) + .scale(0.4) + .texture(pandaTexture, 'yellow'); + + const graphics = new Graphics(pandasContext); + + const graphics2 = new Graphics(pandasContext); + + app.stage.addChild(graphics, graphics2); + + graphics.x = app.screen.width / 2; + graphics.y = app.screen.height / 2; + + graphics2.x = app.screen.width / 2 - 200; + graphics2.y = app.screen.height / 2 - 200; + graphics2.rotation = 0.5; +})(); diff --git a/src/examples/v8.0.0/index.ts b/src/examples/v8.0.0/index.ts index 86f753721..6dd8ef691 100644 --- a/src/examples/v8.0.0/index.ts +++ b/src/examples/v8.0.0/index.ts @@ -24,7 +24,7 @@ import particleContainer from '!!raw-loader!./basic/particleContainer.js'; import meshPlane from '!!raw-loader!./basic/meshPlane.js'; import tinting from '!!raw-loader!./basic/tinting.js'; import transparentBackground from '!!raw-loader!./basic/transparentBackground.js'; -import fillGradient from '!!raw-loader!./basic/fillGradient.js'; +import renderGroup from '!!raw-loader!./basic/renderGroup.js'; import click from '!!raw-loader!./events/click.js'; import customHitarea from '!!raw-loader!./events/customHitarea.js'; @@ -51,6 +51,11 @@ import displacementMapFlag from '!!raw-loader!./filtersBasic/displacementMapFlag import advanced from '!!raw-loader!./graphics/advanced.js'; import dynamic from '!!raw-loader!./graphics/dynamic.js'; import simple from '!!raw-loader!./graphics/simple.js'; +import svg from '!!raw-loader!./graphics/svg.js'; +import svgLoad from '!!raw-loader!./graphics/svg-load.js'; +import texture from '!!raw-loader!./graphics/texture.js'; +import fillGradient from '!!raw-loader!./graphics/fillGradient.js'; +import meshFromPath from '!!raw-loader!./graphics/meshFromPath.js'; import filter from '!!raw-loader!./masks/filter.js'; import graphics from '!!raw-loader!./masks/graphics.js'; @@ -125,7 +130,7 @@ const examplesSource: ExamplesSourceType = { meshPlane, tinting, transparentBackground, - fillGradient, + renderGroup, }, sprite: { animatedSpriteAnimationSpeed, @@ -146,6 +151,11 @@ const examplesSource: ExamplesSourceType = { advanced, dynamic, simple, + svg, + svgLoad, + texture, + fillGradient, + meshFromPath, }, events: { click, diff --git a/static/assets/rainbow-gradient.png b/static/assets/rainbow-gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..fe5cee19bf4cdb0a42cfd190b715fca08220ee71 GIT binary patch literal 40753 zcmcIt2|U#4{~xLBuY+w{Nphs!?XYDdDQB&&ZMRfnax^-KNK=WC!O*2GM{P+LlWeOD z2IVNmD20@xWZZ_3bBt>abAA8M_d7^shK~RKe*4Pq@_3%l^Euw1_viC@=I^arHcX!~ zX9^01n*PVewcAms3E;~KsP86&Kl;7i@W3Avoz`q#gF+>RP8IB#1pZlL-^T5mQ7G?U zP$>UXC=~oH{;epK$8RW9`)(A<;3^8Gbol0@ZARcfoO0ax$NtTmQH#OX-=QYS{D6`L zU&(;~p=9Qu;MKras7*2|!(VTgSvdGTU?+hGP!k8g#|Hcf|FseP4gZYzPuW{C?^nDv zVd%Rjpl->&{~G==?vsi$;E(?u-e~QPLQS0s|1E>MeseZh&HBKOoyT@={>xw=)@|t? z2kc(QrCx4_;h#boc^QB&-5ihY(eQFRc*xzr%UBcn4g>Ht{I9h&HIQ#P=4!0DbMsaW zGwe}EjTK9OTl$-($rKF@4WpwD`wh0QT|fBa;Gc{&osS(mY@n@;!{L_VbeCd}I%zLk zwQ802Z#vpKI!nNJEO9@6=-3{wC5PPSix(MMXRV|AzM}^YA3K0OqyewHXD`;{n6aiN z{ELSF67Tcaf&K4)(;@f4V}S!|!~aEl+0x&%ht~!_Y6SmV1M{N?9Kmmf*Ed;agnZ`* z|8DU27-_@5e8gtNCq@1(II77MBkf_anM_f}G{~V)t5JWfU9-bWrjru2N}%V zI_PI2b9rvxgR(zzCaek2BsG7Boiec}{KV>Tk~bR?(IH_AB+SD=I4{yc1KMgf$*1Op z+AfP5VUC5HU9C6Me3+N<`-n&GiHg|7HYOW4%bum%d@aeOcEPTW!VQcKj=|6~I>d1$ zPq)Oo3oUvUl&4#`HMO&@#Xv+B%PNp+;^j0D+FE9{kNk^kme%v@FI;NkuY~sMSwt$o z@S@(plgcqoIu{gVcgihI4s>Z@*dFk`V^_~yTyt;5QI-p*pVkcttNQcg8aicGb+Od` z)m3-$4nC4fSW8ZwgV(d}+w}*{&Z_Z{r%7%g<=3UmXrIii`T9q%&%mz_!urG>(omoL zn{4?7{YU2cRj)!)ERV$4;a7>*?(Zi*?xW|(`C}DMwC@o0m$Y85>Mua^`LpajK3v+# z=dRy>M!HveOm5(VV_30SX8TdPhoi5ioad1%&SGZWFm-v%s`{)Y7@)u3EJkp(o1OzBeOY6vf7ukU6S8r{1f*uF1NPRr--{%_}B6M zzc%`=;LI`au=EXliP~SkewnKh%RY(xWPwpluwmKy1U08fQE?7E#4k%G@k~o$j!e5j za#YtVy)w>Mo*ruJPD?2!OuVb`cL7oD2cSln0T%-OEosY$+b=9?2~sF4zU-8%Q|IJP z?s&yUly@!0)Kn1P!&31tzizCfjc+nn z_&ed=X0lHT729JOlZ3vcM-Ou-bkytG-{PJd*zQ!IyHA;U|6#e84Y}RW0cgDbIqQtO z&^cd4lZJ*vh`O)r>rcud5+>dHW_N>^CsgwX>}4u)9`ifbZ1*L{DeNWt7W>tbzI20> zK&XWzc8Mj4RY)kH`z>Fg?RrzI&FH4=|3HJy3zU2-pfj)lA9fr;o?dP}9Q9j-q zk8M_e@U`Z$K>;#_CfApm-FD^OVtu7G6P`6-P3q{Vo5mYsnPIFoohi&pGG6aXJx**6 zB%GdIdGcQ###;R;h94<>g#J>uKsFK-h6`K#F(!PYlq51@0-VY zN`=96v-8wj8i^-=P3C2G@Lt-|cIsaH)8=03 zD!ABSJL4iFVH{9KeH3gXJPmdgr?Z^$r4iq>uRCogoB2P?GDbkV*IiL1|M~tmbbWl8 zW3Q!p*wH)8S5?g}NSkr#kugZ>GYTt810Q>C_4N zMh-5~3SD8zyw_i<-G=gn^8+H(Erq&kaSCrMMKdT>Uo5^|fdmm2)xYMA9A}fY?}0D9 z1>Zob@m7dKgeu)R#W~PF&(7E$K-KshCVM8A=t|?J{@3Br%SWS# zY6iPXzfNvMIbn=h-5jXYyS4$lied_4$kkZtb}M^TvwC8{3Op6TtS{f~Pw^T8ZnfbV z%wU=!$OI&KXG;YFKf8yAI?UdU+{E;0rx&SDUXB1EkENtO!y!lC;*wA-aHTl$sjZTL z0ojLZdx$N3qO}2E@1y3RkESl>ykhjmTw9~5*|R3pRyF@JLVw#P3C)YD5c(V zy?Z1qOU(ho6Aj4Ja}(9ba%xqf>XYAa%0y<4?9Cuoma2k+{l_@)*gpJ{P`+Ub4*9EIGu@8jMR$9-Qvuafby7L zT-zchRi*^dS)djrfx+7#R%J`WpclVNBs5bG7+v1H+Zs2-wb{oINQK) z67n19k3eeKQ3f4lxAMox9Ed)zI8l9eqD6XK5i>3gNs`X{T~+Oy&Ga(9D$yelJ-POL zeUy^?=|yr^5RbA$J%Pj@GTO-s)qf(IgOj8=&{G7PD4I1ti8}oJf`Q5=vFTgAFfShp z*Jz`dXv%GtJXfOeTZq+WHz)rQZudf?KuB9hx&Kx#U;nuciG2l0&f-g^+K}tcOU5JS zCIWjH!qv|2s0*3b&A(;wW!Qnh1Gh9;L)T&H+$k0&)0`2flkFez#L>fV&@9V94KS_1R&3u@CBGAW2FGU4gaN-=vl9 zPzJl|!5fMzdcTt^J$8kxYlL{tK}gA1l9!;ibrXDLZz=Hftv&43c#8u0);^!Oh+i{` zadg*s9K!aDn)?!}5y9vjLj*H-RKYZ@%H(5?Nwfe+Urj{DqBPAm1n$oJKE2uhwKykz z2$XivrJpkj#L>@(a3uJ?T3Fw^PVLKWMs2|>TN2xoykisjM##j&l2?G7x-2ut(RPUV{_~f$ep9nX1xr4gd zWGIYg(S4aIbpbw-4AK-RUN?atdwA}|ybi@PZz{KnWqjYp?~!Ow#x@NPUwg}Whe`@` z?p&$@q4CMTN(+dSvtv>kK|t4PzHR4xC>E-28V;BIS`J29xOC@2$GKFh40k!oB)+Xa z-6Bhut*n2&x>7_;7;-S3CUjr2^y3ilT$Ke7-$`Tov;f;qkF)WB3d%Tw_sALwNoXojxzi! ziHs6Ko&a_0AF6|<>^?ouW5uas$X=XM1jmFQ#%nc6me|q_`Ej8EeUz-(o&xhUgQr$7 zBQrw#bs|X*P5Q{JNCtFUQW$~eidq68BJg#$cK(4`q@;S``i*vI#lSEo^5am-rC=iP z^GS$fkv|7Rj#o0V5ATVvmjSh}L z4vU0Pyk+qz#aFDiTwv~2X&GX9Zcr49N=!s?U6I_k( zR?sMnFBioyhAb0=e!BYE^+&C$127Wf_FPf9D(ujYU3dw|=ysrqwq&7sHDMUTQ22E& zQZNkgc&d1*X5D&p1s%D!5D*$Kpdf8UO z(>=h32H66z1cmcEhj39+ur>`O6vClx_dAUU<&GC9f!9vgLlm~D8#EjNSY3FMbcO0b z7;J-`i<>vmWo3IB5394%GAMOg@f#5CEbb5j4&^0>#<`*t_&)rV&9)%N(D`k*so(v? z;rzrk*Zl}h#fDia()O0@=IjYvYL?8^Wldt|WIwqzbY)F(`%q@L-$*H%^Y*3amK5jW z4!AIVRM^Rs*PK1scjTQ4-QLhYBL!&bCgR{dl&o>T<8y}`Aj9p+33%t30@Vs4hWHzL zR~Akhe?!b6bip@rYj11Y_qL!s1q>`tK`CQk=p2h9Pu5{dyzvYLzT{hl1h8JLepXUC zFBQ~x=1zVWy7DEyV~EZKYmk`h0!<|glK{eoXmWkQ8vGq{NPv<-rd}FJ_!-$JFjJ1$ zKDvYQ=cmfbGFJ%*Gw3gfby_KCq|8LJbtNuwrO5V3IRzz<+5=JPfi2l34}JY3oBbO6 zg@xg~8X%T1Q^eaOKT2U&CesYRCrb92bYCv@EyVdpR%|3dyR;kHySPI^v^KDexo(4> zB-8~iBsd4UPL;W8`~d&9tu7>hH(wqf&l!w4I+)8h#@Ybcom)*wJc!}^r2FHBgL0EG zt%qqfv5oOv(BL8k{R3qjs}9xfVo5k_m7v@JMp_PMZp$aZ)tlYfXG{*peclR&aGEe; z1(QJP#et4>p>~CicbMi6{cLVrJDEF2G7I3&B_pt=i0t`rB?rv!)}lq<8j%hlF@`cAC9Bn zEB_-#5&<&!=YbdBJI{+*30Y`hXGW4$oGNO7c#}1Bei8#KSy}cfLGVj^ZSS`(OSOCn z1+3DlmvfiXBvY+GGeX5^A{M0SYO{A!6~eTH_sC_vpH*i9uoYZHt=0>+NAW?8wynJX zN-6gp3*9^gWp9VwhJ9C-zBIQ1)4nJpOyBOR>j|buUqtj+7Qf(|PKqo{h=_;SGN0i6JA{t@i&^B8}1l@Y*ciRz_w@a9t= zCN=zaUSV%a&%x%fON_SJJ1yib3f)o!@2j=(B_yB=+LGuItio@`J37}S>g^&lT`^3L zUF$=52MM)M)lS-Gb-02#_>pS~6YCr#kT!I+-QIUAat^pY66G(!9k%?N%N`&QP*;tg zQlD8wltsA`F2$uR9;~N&xH9eolhrVhWU_2jso68NiMFMz4Tm0{ByD=i!HLR2(4Q*T z`2*dd!nfqQw?i#SB(8C{)2f_afHV3?GGB(we}U(WzXPmuXw6YMbl6#@yT~n1Ys3Ad zG)j8p64%bk9`yMkLg`iL{e5bUs${u7No48ZQFp&TYDfAdmED?tw7|9_iu~Z8;l*XS|0=o0cMB(i%W`=-^IV-5N|mk?zR{+45rClRa?x~ zs6gym)y`5gi_fJ(Sk%(FiD^FWdoo?8&rhz3C5$f`ig%`PBEF3`Kdt7m<*g+y*l$F(ST(X(O&-E(8edtLk{=-h|6# zoK7z3*${Bq-(Ob=va@0~;gzH+9iq8$uK*9O{;*j-Vet(5aS>e|b*$C0puM`iB!&71 z%_dCT{xN3Y|MaMaFQ}E(kjkwn3Z{3emLtp9P~_4x)b+x{dcNG3*~r>0v9eYz`bE2pi^g-rwy2dpx=_L6vNYUQ!&gYgh4D

5Nb83g(Y>#mP^r9Hl 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 literal 0 HcmV?d00001 diff --git a/static/assets/tiger.svg b/static/assets/tiger.svg new file mode 100644 index 000000000..679edec2e --- /dev/null +++ b/static/assets/tiger.svg @@ -0,0 +1,725 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/assets/tree.png b/static/assets/tree.png new file mode 100644 index 0000000000000000000000000000000000000000..e4ac06c75b8e51ac1c51252d02fb5b791e9436c2 GIT binary patch literal 2692 zcmV-~3VZd5P)Px#mQYMoMMrQ|JQIdhkcj%M>#nZdLlpxeitFL~f4OIp z2{~|35OAM&-}$3O`)jWzOzzw>N!#h%8NJcx*SPcO=vk}Pk5H}uqp|+>86FGVt_EbD``N41v@qpo-;>S(nZwMlhsmym=?2tyIlYnMt~ z*PZnHZ&4J5tJUXd^h7$n5BO<3p0=7#q`zDSlx{;lTo~a)))1$9-Xp1`+wI!RrGGeF zzIj+rJbLXeS3qL;8w#4T_qlnCGV85Kk+4mEDb^@2sSY_Mst zZ2bLZLp>UWVH|C@JexQ>;@Ze!+=4bSZGia&%@4PF4o7?+FuYVVQ%p#Ts;$>B@;pXu z+9Q)LxTU3_dRy>K=QxJRjUyiLfeF=kJnprS!-A@EIA)t{GS`jov?;3B8kKN0>bfLx zOG|E;4jWyYLbOj}5jEhTgj?wo&9_Kx%Iff{nH;`GrP{n2Q9FlOB?V&NS8mDYf!f5v zpn^QHc^=oT?m&(phaBmaf(;MUCIL|qgFL}ER{iQu)BGiO{Nj~HIWIK!v?`=YDtnhE zm1XfNSwmhcR6huUqtqrKe4{WSD~#hae2AN-X0$0fvQ$<(t=JJ-qk59+wLk^8G)E5{ z91a0$6U2pjTNI_p@G_`UKqYlmN;rO4rF$)}5^aj}9aQalpd>YHkcz&AiPB}Wxk!0p zRL~}(Nm~pG) zHmIJVjg&S-Rc>hsa^#~hLH1s_HYKkY^>w>FuMA9qz8VOAwpDILCFC2CTwCa3{dBt{L;I~{dx5>%;8?CIm_X(YG)vw`5XtR4SnwDkb3~(56x+ zcQs9oId2#1C^>f<(mqrlw^N#&-redI)R{G^*bC$6`jH>JIzg%%u=sZcdnE4z5R40SC*=@Nd@baU#aeHYW{6% zs?G{abZ>7^ufNx9b(a{`BC5DAFn6-*6Bw0Tv4awIUL>_iz1nj@e>~GiyQvMrEe4rx z5Y3)D6nWIUsF_?Zx|>sps!r!}6p1yP0@Nm{CfYqDpq^z9sK^=TQPt^O-d`vXX90$C zs(TIiW2DaR%8u1k|D0ddPSJw&9S$$K`&!&bC8U5#OHyfIbffgU2C1I0s_>@$em}Eh z_?g@lD$}qFx++vN#%Euki&A$D)Y&0?(C%pFX@knr&wnTCt^rM-SdMN|y}DHM zoYa$4H%E~S^|>aIX)mRp=b7CorcGeVo-C$Xf2b0^ zt|pn<3+p^<%KyDfwtnmD_sxr94WXX!gQ1+6I#X1Av)OE#x2tAuixpA*6g7Q^!>mH& z8qz(gxbN*ajz)Fl9q^?8l*BL@t6zd@mU|1A$OaVN_jbCjJC%z3hIhcl6U19GP%*;c z>2w<6(}j1%kNf?_mla=5?Z@I3L#e;x=HJZg6TRYECow$jc7mGj{1sGTS~NgiAMd3y z-vp)nfZzOf=JLiR-n~@!!n>2n1r{~dmDN9y=TsE-*dzSng!$q&t8>1BQ;m2|mpVgc4^D4*J;4qkFR;#zYszlBP`h-lQr z`*Z3I+fyT4uw_~j4TtK(>Cc~eOIUZfE()0LR;cXk?%`Cz{`Y}GD4Xs+d4M)#;ulff y2@ia=FB3h)cUZ0s+EWQ*T;jW7d#>Vtn))yCm=vC}|Khd)0000