From 22e82245c0f63e12a805a655abc44db4b9ba3e5e Mon Sep 17 00:00:00 2001 From: Erick Zanardo Date: Wed, 3 Jun 2020 19:32:32 -0300 Subject: [PATCH 01/16] Layer proposal --- doc/examples/layers/.gitignore | 49 +++++++++++ doc/examples/layers/.metadata | 10 +++ doc/examples/layers/README.md | 3 + .../layers/assets/images/bomb_ptero.png | Bin 0 -> 1114 bytes doc/examples/layers/assets/images/sprites.png | Bin 0 -> 1010 bytes doc/examples/layers/lib/main.dart | 76 ++++++++++++++++++ doc/examples/layers/pubspec.yaml | 27 +++++++ lib/layer.dart | 71 ++++++++++++++++ 8 files changed, 236 insertions(+) create mode 100644 doc/examples/layers/.gitignore create mode 100644 doc/examples/layers/.metadata create mode 100644 doc/examples/layers/README.md create mode 100644 doc/examples/layers/assets/images/bomb_ptero.png create mode 100644 doc/examples/layers/assets/images/sprites.png create mode 100644 doc/examples/layers/lib/main.dart create mode 100644 doc/examples/layers/pubspec.yaml create mode 100644 lib/layer.dart diff --git a/doc/examples/layers/.gitignore b/doc/examples/layers/.gitignore new file mode 100644 index 000000000..4be785f38 --- /dev/null +++ b/doc/examples/layers/.gitignore @@ -0,0 +1,49 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Exceptions to above rules. +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages + +android +ios +macos +web diff --git a/doc/examples/layers/.metadata b/doc/examples/layers/.metadata new file mode 100644 index 000000000..97cd56733 --- /dev/null +++ b/doc/examples/layers/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 9d58a87066d1da98eb06826918e4b90cc76ae0ef + channel: master + +project_type: app diff --git a/doc/examples/layers/README.md b/doc/examples/layers/README.md new file mode 100644 index 000000000..7b2476580 --- /dev/null +++ b/doc/examples/layers/README.md @@ -0,0 +1,3 @@ +# layers + +Simple project to showcase the layer feature of Flame diff --git a/doc/examples/layers/assets/images/bomb_ptero.png b/doc/examples/layers/assets/images/bomb_ptero.png new file mode 100644 index 0000000000000000000000000000000000000000..fa4ddadc84fd252eb155441d1ebae241199bba89 GIT binary patch literal 1114 zcmV-g1f~0lP)QvvI+P9_L+K(SrBKl! zLo{?xvj(RwjZ>&1{UeCiL0-6v?{e?m`>*$bV0hlW`~KeV`@8qO8vSa}=vM>N zI@030ejQAx>^w_Ah6p;2p9G1^pElxz{La*T-FY_uOCn!gVF+U zH34rvUNW`WitG9bI{c%g0B%YGGR&aUKiNZY4B-KHv3OnAuM1@b;Bo?vUhR1-ZMNdN zen6jploSAMusipURa{Crxusl0``Pv*r*^Y)OF7dLxY1d_KFdL@TTu1l?lqAl0r}O= z@P8ux>1JU01w-DteBbNSf8y#@;9pg z!%@px?Tvmls26uV5(Ck`xp9K$`5A02fAPpMvaT8FNT&G-Gy{nuV*uh}Ei9hn@bZFs z&ccL`(}PK6n$ki{(dbtL7X9Q{)0%1RN&bnuk*1Bs8z&|WX$_PH-k@3HEG(V_0LsC? zNPFA6T8pyi*J-TLn0WP@)Jj8!e|Tc@Rs6>b0W{51w-ABHvBj zWkvMMB+dAX`iE!y{qO-Yi$P@qSWRWa5AaMcHB2Hh{<8d&H2#rYAliYZO_bI=qPhpA z@-PX5QW+4K!Aul^O#Nvv?VB*;#y{~zSiQLGkq^&B2cEjSxY4*<1Z)B9X{643P5dQGnZb8B;+4Hw=57J3gL3T-c%wvAa?WEZpLs9|D z(w_PmfCXCym=&^oi2HwK{sOJ8kI`j>EhOpRTK?jJvJA2n*ZhOE{guQAES6(3_~F@M gvFRmM7!&^a50>N07|5r#tN;K207*qoM6N<$f*y4lPx&tVu*cRCt{2ny+sgF%-vNtE$+M27-!C1Jx8TR4`2g8C#{n{Q(72&_Gd#R}?T5 z4fMZg*$zz8Kv6+JQBhG@g9b`&U~=m7*=IjL`*Oa#k5pAT|9bxV`L_WWhG7^ckR429 zA&M%MApiiY)g8*7KHzPz5JmM^PW>Xk`V?f$Xnc~Lh`XCMAa^`oJ8a&?-$jAG0>|A&igE}OUu6JY^~Y=wYrhasV1lC2Oh zC4(1Gh@yIYxG;KCXqXCm7M@HG8nbTf!-Sk3899yY{ygv|nt0NSBx=KihUo;Y1N)5L z<@EKW8jcCGF{mSbA&TmBdgK-NcX?jlY8{`=8j1BdCiHZ+G-^DbI5BK-;iCb- ze-Rr3x-x7NrcG>{5w37kIVv)pDcq-VOmST{UY;-D_-xh`PzLz4>NX>V9F0$&7t$=A zAG$`nwt!q&-tKo=9(pU+wSibBhfh)R@vSFXK%0TC0{bq!j;)?@sFSn`h^e%zvCy)TtphQI07*qoM6N<$g81OkiU0rr literal 0 HcmV?d00001 diff --git a/doc/examples/layers/lib/main.dart b/doc/examples/layers/lib/main.dart new file mode 100644 index 000000000..e9c348679 --- /dev/null +++ b/doc/examples/layers/lib/main.dart @@ -0,0 +1,76 @@ +import 'package:flutter/material.dart' hide Animation; +import 'package:flame/game.dart'; +import 'package:flame/sprite.dart'; +import 'package:flame/spritesheet.dart'; +import 'package:flame/animation.dart'; +import 'package:flame/layer.dart'; +import 'package:flame/flame.dart'; + +import 'dart:ui'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + + await Flame.util.fullScreen(); + + final sprite = await Sprite.loadSprite('sprites.png'); + + await Flame.images.load('bomb_ptero.png'); + final spriteSheet = SpriteSheet( + imageName: 'bomb_ptero.png', + textureWidth: 48, + textureHeight: 32, + columns: 4, + rows: 1); + + final animation = spriteSheet.createAnimation(0, stepTime: 0.2, to: 3); + runApp(LayerGame(sprite, animation).widget); +} + +class LayerGame extends Game { + Sprite sprite; + Animation animation; + Layer layerWithDropShadow; + Layer animationLayerWithDropShadow; + Layer layerWithoutDropShadow; + + LayerGame(this.sprite, this.animation) { + layerWithDropShadow = Layer()..preProcessors.add(ShadowProcessor()); + animationLayerWithDropShadow = Layer() + ..preProcessors.add(ShadowProcessor()); + + layerWithoutDropShadow = Layer(); + + layerWithoutDropShadow.beginRendering(); + layerWithDropShadow.beginRendering(); + + sprite.renderRect( + layerWithoutDropShadow.canvas, const Rect.fromLTWH(50, 50, 200, 200)); + sprite.renderRect( + layerWithDropShadow.canvas, const Rect.fromLTWH(50, 50, 200, 200)); + + layerWithoutDropShadow.finishRendering(); + layerWithDropShadow.finishRendering(); + } + + @override + void update(double dt) { + animation.update(dt); + } + + @override + void render(Canvas canvas) { + layerWithoutDropShadow.render(canvas); + layerWithDropShadow.render(canvas, y: 250); + + animationLayerWithDropShadow.beginRendering(); + animation.getSprite().renderRect(animationLayerWithDropShadow.canvas, + const Rect.fromLTWH(0, 0, 150, 100)); + animationLayerWithDropShadow + ..finishRendering() + ..render(canvas, x: 100, y: 600); + } + + @override + Color backgroundColor() => const Color(0xFF38607C); +} diff --git a/doc/examples/layers/pubspec.yaml b/doc/examples/layers/pubspec.yaml new file mode 100644 index 000000000..bde3559af --- /dev/null +++ b/doc/examples/layers/pubspec.yaml @@ -0,0 +1,27 @@ +name: layers +description: Simple project to showcase the layer feature of Flame + +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +version: 1.0.0+1 + +environment: + sdk: ">=2.7.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + flame: + path: ../../../ + + cupertino_icons: ^0.1.3 + +dev_dependencies: + flutter_test: + sdk: flutter + +flutter: + uses-material-design: true + assets: + - assets/images/sprites.png + - assets/images/bomb_ptero.png diff --git a/lib/layer.dart b/lib/layer.dart new file mode 100644 index 000000000..84fc213e7 --- /dev/null +++ b/lib/layer.dart @@ -0,0 +1,71 @@ +import 'dart:ui'; + +class Layer { + List preProcessors = []; + List postProcessors = []; + + Picture _picture; + + PictureRecorder _recorder; + Canvas _canvas; + + void render(Canvas canvas, {double x = 0.0, double y = 0.0}) { + if (_picture == null) { + return; + } + + canvas.save(); + canvas.translate(x, y); + + preProcessors.forEach((p) => p.process(_picture, canvas)); + canvas.drawPicture(_picture); + postProcessors.forEach((p) => p.process(_picture, canvas)); + canvas.restore(); + } + + Canvas get canvas { + assert(_canvas != null, + 'Layer is not ready for rendering, call beginRendering first'); + return _canvas; + } + + void beginRendering() { + _recorder = PictureRecorder(); + _canvas = Canvas(_recorder); + } + + void finishRendering() { + _picture = _recorder.endRecording(); + + _recorder = null; + _canvas = null; + } +} + +abstract class LayerProcessor { + void process(Picture pic, Canvas canvas); +} + +class ShadowProcessor extends LayerProcessor { + Paint _shadowPaint; + + final Offset offset; + + ShadowProcessor({ + this.offset = const Offset(10, 10), + double opacity = 0.9, + Color color = const Color(0xFF000000), + }) { + _shadowPaint = Paint() + ..colorFilter = + ColorFilter.mode(color.withOpacity(opacity), BlendMode.srcATop); + } + + @override + void process(Picture pic, Canvas canvas) { + canvas.saveLayer(Rect.largest, _shadowPaint); + canvas.translate(offset.dx, offset.dy); + canvas.drawPicture(pic); + canvas.restore(); + } +} From e28e12965b4ba3587a9fa0269c2b65b534d393fd Mon Sep 17 00:00:00 2001 From: Erick Zanardo Date: Sun, 7 Jun 2020 14:29:33 -0300 Subject: [PATCH 02/16] Some changes on the Layer API --- .../layers/assets/images/background.png | Bin 0 -> 550 bytes .../layers/assets/images/bomb_ptero.png | Bin 1114 -> 0 bytes doc/examples/layers/assets/images/enemy.png | Bin 0 -> 228 bytes doc/examples/layers/assets/images/player.png | Bin 0 -> 392 bytes doc/examples/layers/assets/images/sprites.png | Bin 1010 -> 0 bytes doc/examples/layers/lib/main.dart | 96 ++++++++++-------- doc/examples/layers/pubspec.yaml | 5 +- lib/layer.dart | 25 ++++- 8 files changed, 78 insertions(+), 48 deletions(-) create mode 100644 doc/examples/layers/assets/images/background.png delete mode 100644 doc/examples/layers/assets/images/bomb_ptero.png create mode 100644 doc/examples/layers/assets/images/enemy.png create mode 100644 doc/examples/layers/assets/images/player.png delete mode 100644 doc/examples/layers/assets/images/sprites.png diff --git a/doc/examples/layers/assets/images/background.png b/doc/examples/layers/assets/images/background.png new file mode 100644 index 0000000000000000000000000000000000000000..8bab4a85b17fe7564188c1ace88f13064927d5bd GIT binary patch literal 550 zcmV+>0@?kEP)uoVS2;TBXJfdg;^s=Wm_Ns)>JY`3Xtb_-UFqgb&NKjN_YW*BDh zL(*^APOuC3W4-?Pfdw&bdoKV03V^40-(R28dNeaO+at8?y(p-7x68Ft@o+x%8q+#9 zXgjWrSx-_YgfA{68UQ>+>|h1_h9P~wk^crvI)C08(4>ZVF+uXI=GlG;Hn``sf*KhikW0&)(z4CXF8g^LrH zI%H5lP0+5950x1{)J^sJgkm*Rm_yK%x~WF{6(gR`E-WR+bfkT9HgXtL>n^MzMi8{m z9E6h4d5qzh+XfID@g{kz^%z4t3z=EDW~s|B)tN}HK_V%#IN2IF#gt4j zz%8%D1&4IcWnt`H&b?t2giuTHe^lF8~p2k0EUGrdl oxm+}o*X1JoVY%L>1FyIJ0v~@Ka~Zf`DgXcg07*qoM6N<$f(pd-tN;K2 literal 0 HcmV?d00001 diff --git a/doc/examples/layers/assets/images/bomb_ptero.png b/doc/examples/layers/assets/images/bomb_ptero.png deleted file mode 100644 index fa4ddadc84fd252eb155441d1ebae241199bba89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1114 zcmV-g1f~0lP)QvvI+P9_L+K(SrBKl! zLo{?xvj(RwjZ>&1{UeCiL0-6v?{e?m`>*$bV0hlW`~KeV`@8qO8vSa}=vM>N zI@030ejQAx>^w_Ah6p;2p9G1^pElxz{La*T-FY_uOCn!gVF+U zH34rvUNW`WitG9bI{c%g0B%YGGR&aUKiNZY4B-KHv3OnAuM1@b;Bo?vUhR1-ZMNdN zen6jploSAMusipURa{Crxusl0``Pv*r*^Y)OF7dLxY1d_KFdL@TTu1l?lqAl0r}O= z@P8ux>1JU01w-DteBbNSf8y#@;9pg z!%@px?Tvmls26uV5(Ck`xp9K$`5A02fAPpMvaT8FNT&G-Gy{nuV*uh}Ei9hn@bZFs z&ccL`(}PK6n$ki{(dbtL7X9Q{)0%1RN&bnuk*1Bs8z&|WX$_PH-k@3HEG(V_0LsC? zNPFA6T8pyi*J-TLn0WP@)Jj8!e|Tc@Rs6>b0W{51w-ABHvBj zWkvMMB+dAX`iE!y{qO-Yi$P@qSWRWa5AaMcHB2Hh{<8d&H2#rYAliYZO_bI=qPhpA z@-PX5QW+4K!Aul^O#Nvv?VB*;#y{~zSiQLGkq^&B2cEjSxY4*<1Z)B9X{643P5dQGnZb8B;+4Hw=57J3gL3T-c%wvAa?WEZpLs9|D z(w_PmfCXCym=&^oi2HwK{sOJ8kI`j>EhOpRTK?jJvJA2n*ZhOE{guQAES6(3_~F@M gvFRmM7!&^a50>N07|5r#tN;K207*qoM6N<$f*y4lD%45QhI%eSnKp5ENt$O$B{|fsFM5`Tzw}(fIKAP&AOoC|f|EU?8|CsH}Yh7gbu* zB=xyTZ`ST(c5LT<-RXR`0Yy=Q=7BSq$k?F_0f56{%d!Vx2p}?cU!-n>pB7v@002?E zWQ!Pi{pk;JcL7nn>}+#U4@jc|xa@a%XPb+9KpGVwjS7&)sc;&)3jGbYm>XXkKxFJR zO}var9w+QM>kO77BKQ!x>VYQ8qB?8)dZ-N|AA3~uVXh52gc97@55kP46{ zcmcg+p}tvXKh9&l1k|rrqO|Z?rhWZg?tIt}K7>?&G%7$Eb{3kZ$wk)byO`r#@_MDw zz74MPug(L(A1T={B1Fc%e7!Y(`+oiGG=Rw1_f2-z_wl^)dYL&9dPx&tVu*cRCt{2ny+sgF%-vNtE$+M27-!C1Jx8TR4`2g8C#{n{Q(72&_Gd#R}?T5 z4fMZg*$zz8Kv6+JQBhG@g9b`&U~=m7*=IjL`*Oa#k5pAT|9bxV`L_WWhG7^ckR429 zA&M%MApiiY)g8*7KHzPz5JmM^PW>Xk`V?f$Xnc~Lh`XCMAa^`oJ8a&?-$jAG0>|A&igE}OUu6JY^~Y=wYrhasV1lC2Oh zC4(1Gh@yIYxG;KCXqXCm7M@HG8nbTf!-Sk3899yY{ygv|nt0NSBx=KihUo;Y1N)5L z<@EKW8jcCGF{mSbA&TmBdgK-NcX?jlY8{`=8j1BdCiHZ+G-^DbI5BK-;iCb- ze-Rr3x-x7NrcG>{5w37kIVv)pDcq-VOmST{UY;-D_-xh`PzLz4>NX>V9F0$&7t$=A zAG$`nwt!q&-tKo=9(pU+wSibBhfh)R@vSFXK%0TC0{bq!j;)?@sFSn`h^e%zvCy)TtphQI07*qoM6N<$g81OkiU0rr diff --git a/doc/examples/layers/lib/main.dart b/doc/examples/layers/lib/main.dart index e9c348679..6d5b330b2 100644 --- a/doc/examples/layers/lib/main.dart +++ b/doc/examples/layers/lib/main.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart' hide Animation; import 'package:flame/game.dart'; import 'package:flame/sprite.dart'; -import 'package:flame/spritesheet.dart'; -import 'package:flame/animation.dart'; import 'package:flame/layer.dart'; import 'package:flame/flame.dart'; @@ -13,62 +11,70 @@ void main() async { await Flame.util.fullScreen(); - final sprite = await Sprite.loadSprite('sprites.png'); + final playerSprite = await Sprite.loadSprite('player.png'); + final enemySprite = await Sprite.loadSprite('enemy.png'); + final backgroundSprite = await Sprite.loadSprite('background.png'); - await Flame.images.load('bomb_ptero.png'); - final spriteSheet = SpriteSheet( - imageName: 'bomb_ptero.png', - textureWidth: 48, - textureHeight: 32, - columns: 4, - rows: 1); + runApp(LayerGame(playerSprite, enemySprite, backgroundSprite).widget); +} - final animation = spriteSheet.createAnimation(0, stepTime: 0.2, to: 3); - runApp(LayerGame(sprite, animation).widget); +class GameLayer extends DynamicLayer { + final Sprite playerSprite; + final Sprite enemySprite; + + GameLayer(this.playerSprite, this.enemySprite) { + preProcessors.add(ShadowProcessor()); + } + + @override + void drawLayer() { + playerSprite.renderRect( + canvas, + const Rect.fromLTWH(50, 50, 150, 150), + ); + enemySprite.renderRect( + canvas, + const Rect.fromLTWH(250, 150, 100, 50), + ); + } +} + +class BackgroundLayer extends PreRenderedLayer { + final Sprite sprite; + + BackgroundLayer(this.sprite) { + preProcessors.add(ShadowProcessor()); + } + + @override + void drawLayer() { + sprite.renderRect( + canvas, + const Rect.fromLTWH(50, 200, 300, 150), + ); + } } class LayerGame extends Game { - Sprite sprite; - Animation animation; - Layer layerWithDropShadow; - Layer animationLayerWithDropShadow; - Layer layerWithoutDropShadow; + Sprite playerSprite; + Sprite enemySprite; + Sprite backgroundSprite; - LayerGame(this.sprite, this.animation) { - layerWithDropShadow = Layer()..preProcessors.add(ShadowProcessor()); - animationLayerWithDropShadow = Layer() - ..preProcessors.add(ShadowProcessor()); + Layer gameLayer; + Layer backgroundLayer; - layerWithoutDropShadow = Layer(); - - layerWithoutDropShadow.beginRendering(); - layerWithDropShadow.beginRendering(); - - sprite.renderRect( - layerWithoutDropShadow.canvas, const Rect.fromLTWH(50, 50, 200, 200)); - sprite.renderRect( - layerWithDropShadow.canvas, const Rect.fromLTWH(50, 50, 200, 200)); - - layerWithoutDropShadow.finishRendering(); - layerWithDropShadow.finishRendering(); + LayerGame(this.playerSprite, this.enemySprite, this.backgroundSprite) { + gameLayer = GameLayer(playerSprite, enemySprite); + backgroundLayer = BackgroundLayer(backgroundSprite); } @override - void update(double dt) { - animation.update(dt); - } + void update(double dt) {} @override void render(Canvas canvas) { - layerWithoutDropShadow.render(canvas); - layerWithDropShadow.render(canvas, y: 250); - - animationLayerWithDropShadow.beginRendering(); - animation.getSprite().renderRect(animationLayerWithDropShadow.canvas, - const Rect.fromLTWH(0, 0, 150, 100)); - animationLayerWithDropShadow - ..finishRendering() - ..render(canvas, x: 100, y: 600); + gameLayer.render(canvas); + backgroundLayer.render(canvas); } @override diff --git a/doc/examples/layers/pubspec.yaml b/doc/examples/layers/pubspec.yaml index bde3559af..d1a64a83c 100644 --- a/doc/examples/layers/pubspec.yaml +++ b/doc/examples/layers/pubspec.yaml @@ -23,5 +23,6 @@ dev_dependencies: flutter: uses-material-design: true assets: - - assets/images/sprites.png - - assets/images/bomb_ptero.png + - assets/images/background.png + - assets/images/enemy.png + - assets/images/player.png diff --git a/lib/layer.dart b/lib/layer.dart index 84fc213e7..f74b790e8 100644 --- a/lib/layer.dart +++ b/lib/layer.dart @@ -1,6 +1,7 @@ import 'dart:ui'; +import 'package:meta/meta.dart'; -class Layer { +abstract class Layer { List preProcessors = []; List postProcessors = []; @@ -9,6 +10,7 @@ class Layer { PictureRecorder _recorder; Canvas _canvas; + @mustCallSuper void render(Canvas canvas, {double x = 0.0, double y = 0.0}) { if (_picture == null) { return; @@ -40,6 +42,27 @@ class Layer { _recorder = null; _canvas = null; } + + void drawLayer(); +} + +abstract class PreRenderedLayer extends Layer { + PreRenderedLayer() { + beginRendering(); + drawLayer(); + finishRendering(); + } +} + +abstract class DynamicLayer extends Layer { + @override + void render(Canvas canvas, {double x = 0.0, double y = 0.0}) { + beginRendering(); + drawLayer(); + finishRendering(); + + super.render(canvas, x: x, y: y); + } } abstract class LayerProcessor { From 2390e3c26fec937a5eac7089f160d9b828ec5e79 Mon Sep 17 00:00:00 2001 From: Erick Zanardo Date: Tue, 23 Jun 2020 19:02:43 -0300 Subject: [PATCH 03/16] Better organizing layers --- doc/examples/layers/lib/main.dart | 2 +- lib/{ => layer}/layer.dart | 39 +++++++------------------------ lib/layer/processors.dart | 29 +++++++++++++++++++++++ 3 files changed, 38 insertions(+), 32 deletions(-) rename lib/{ => layer}/layer.dart (62%) create mode 100644 lib/layer/processors.dart diff --git a/doc/examples/layers/lib/main.dart b/doc/examples/layers/lib/main.dart index 6d5b330b2..818869073 100644 --- a/doc/examples/layers/lib/main.dart +++ b/doc/examples/layers/lib/main.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart' hide Animation; import 'package:flame/game.dart'; import 'package:flame/sprite.dart'; -import 'package:flame/layer.dart'; +import 'package:flame/layer/layer.dart'; import 'package:flame/flame.dart'; import 'dart:ui'; diff --git a/lib/layer.dart b/lib/layer/layer.dart similarity index 62% rename from lib/layer.dart rename to lib/layer/layer.dart index f74b790e8..5b534e81b 100644 --- a/lib/layer.dart +++ b/lib/layer/layer.dart @@ -1,5 +1,8 @@ -import 'dart:ui'; import 'package:meta/meta.dart'; +import 'dart:ui'; + +import './processors.dart'; +export './processors.dart'; abstract class Layer { List preProcessors = []; @@ -26,8 +29,10 @@ abstract class Layer { } Canvas get canvas { - assert(_canvas != null, - 'Layer is not ready for rendering, call beginRendering first'); + assert( + _canvas != null, + 'Layer is not ready for rendering, call beginRendering first', + ); return _canvas; } @@ -64,31 +69,3 @@ abstract class DynamicLayer extends Layer { super.render(canvas, x: x, y: y); } } - -abstract class LayerProcessor { - void process(Picture pic, Canvas canvas); -} - -class ShadowProcessor extends LayerProcessor { - Paint _shadowPaint; - - final Offset offset; - - ShadowProcessor({ - this.offset = const Offset(10, 10), - double opacity = 0.9, - Color color = const Color(0xFF000000), - }) { - _shadowPaint = Paint() - ..colorFilter = - ColorFilter.mode(color.withOpacity(opacity), BlendMode.srcATop); - } - - @override - void process(Picture pic, Canvas canvas) { - canvas.saveLayer(Rect.largest, _shadowPaint); - canvas.translate(offset.dx, offset.dy); - canvas.drawPicture(pic); - canvas.restore(); - } -} diff --git a/lib/layer/processors.dart b/lib/layer/processors.dart new file mode 100644 index 000000000..fc52a2cf9 --- /dev/null +++ b/lib/layer/processors.dart @@ -0,0 +1,29 @@ +import 'dart:ui'; + +abstract class LayerProcessor { + void process(Picture pic, Canvas canvas); +} + +class ShadowProcessor extends LayerProcessor { + Paint _shadowPaint; + + final Offset offset; + + ShadowProcessor({ + this.offset = const Offset(10, 10), + double opacity = 0.9, + Color color = const Color(0xFF000000), + }) { + _shadowPaint = Paint() + ..colorFilter = + ColorFilter.mode(color.withOpacity(opacity), BlendMode.srcATop); + } + + @override + void process(Picture pic, Canvas canvas) { + canvas.saveLayer(Rect.largest, _shadowPaint); + canvas.translate(offset.dx, offset.dy); + canvas.drawPicture(pic); + canvas.restore(); + } +} From 6f3397f08297e1f527b79b1e6e86fcd1180d5203 Mon Sep 17 00:00:00 2001 From: Erick Zanardo Date: Tue, 23 Jun 2020 19:31:46 -0300 Subject: [PATCH 04/16] Adding docs --- doc/README.md | 1 + doc/layers.md | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 doc/layers.md diff --git a/doc/README.md b/doc/README.md index c593cbd4b..e2963d824 100644 --- a/doc/README.md +++ b/doc/README.md @@ -42,6 +42,7 @@ Check out the [awesome flame repository](https://github.com/flame-engine/awesome - [Text Rendering](text.md) - [Colors and the Palette](palette.md) - [Particles](particles.md) + - [Layers](layers.md) * Other Modules - [Util](util.md) - [Gamepad](gamepad.md) diff --git a/doc/layers.md b/doc/layers.md new file mode 100644 index 000000000..7b5472447 --- /dev/null +++ b/doc/layers.md @@ -0,0 +1,92 @@ +# Layers + +Layers are an useful feature that lets you group renderization by context, and to also to obtain a way of pre rendering things, enabling for example the renderization in memory of parts of your game that don't change much, like a background for example, and by doing that, freeing resources for more dynamic content that needs to be rendered every loop cycle. + +There are two types of layers on Flame: `DynamicLayer` and `PreRenderedLayer`. + +## DynamicLayer + +Dynamic layers are layers that are rendered every time that they are draw on the canvas, as the name suggests, it is meant for dynamic content and is most useful to group renderizations that are of the same context. + +Usage example: +```dart +class GameLayer extends DynamicLayer { + final MyGame game; + + GameLayer(this.game); + + @override + void drawLayer() { + game.playerSprite.renderRect( + canvas, + game.playerRect, + ); + game.enemySprite.renderRect( + canvas, + game.enemyRect, + ); + } +} + +class MyGame extends Game { + // Other methods ommited... + + @override + void render(Canvas canvas) { + gameLayer.render(canvas); // x and y can be provided as optional position arguments + } +} +``` + +## PreRenderedLayer + +Pre rendered layers are layers that are rendered only once, cached on the memory and they can be used to be rendered on the game canas aftwards. They are most uesful to cache content that don't change during the game, like a background for example. + +Usage example: +```dart +class BackgroundLayer extends PreRenderedLayer { + final Sprite sprite; + + BackgroundLayer(this.sprite); + + @override + void drawLayer() { + sprite.renderRect( + canvas, + const Rect.fromLTWH(50, 200, 300, 150), + ); + } +} + +class MyGame extends Game { + // Other methods ommited... + + @override + void render(Canvas canvas) { + backgroundLayer.render(canvas); // x and y can be provided as optional position arguments + } +} +``` + +## Layer Processors + +Flame also provides a way to add processors on your layer, which are ways to add effects on all of your layer. At the moment, out of the box, only the `ShadowProcessor` is available, this processor renders a cool back drop shadow on your layer. + +To add processors to your layer, just add them to the layer `preProcessors` or `postProcessors` list. For example: + +```dart +// Works the same for both DynamicLayer and PreRenderedLayer +class BackgroundLayer extends PreRenderedLayer { + final Sprite sprite; + + BackgroundLayer(this.sprite) { + preProcessors.add(ShadowProcessor()); + } + + @override + void drawLayer() { /* ommited */ } +``` + +Custom processors can be creted by extending the `LayerProcessor` class. + +You can check an working example of layers [here](/doc/examples/layers) From 9168ef3836b327c0e9938345d2fb5931c5fc7d98 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Wed, 24 Jun 2020 11:46:33 +0200 Subject: [PATCH 05/16] onComplete callback for effects --- CHANGELOG.md | 1 + doc/effects.md | 2 ++ doc/examples/effects/combined_effects/lib/main.dart | 1 + lib/effects/combined_effect.dart | 3 ++- lib/effects/effects.dart | 10 +++++++++- lib/effects/move_effect.dart | 3 ++- lib/effects/rotate_effect.dart | 3 ++- lib/effects/scale_effect.dart | 3 ++- lib/effects/sequence_effect.dart | 3 ++- 9 files changed, 23 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9cb2d0aa..5ee191753 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [next] - Adding BaseGame#markToRemove - Upgrade tiled and flutter_svg dependencies + - onComplete callback for effects ## 0.22.1 - Fix Box2DComponent render priority diff --git a/doc/effects.md b/doc/effects.md index 1583be945..5faa1b53c 100644 --- a/doc/effects.md +++ b/doc/effects.md @@ -14,6 +14,8 @@ If `isInfinite` is false and `isAlternating` is true the effect will go from the `isInfinite` and `isAlternating` are false by default and then the effect is just applied once, from the beginning of the curve until the end. +When an effect is completed the callback `onComplete` will be called, it can be set as an optional argument to your effect. + ## MoveEffect Applied to `PositionComponent`s, this effect can be used to move the component to a new position, using an [animation curve](https://api.flutter.dev/flutter/animation/Curves-class.html). diff --git a/doc/examples/effects/combined_effects/lib/main.dart b/doc/examples/effects/combined_effects/lib/main.dart index e6cbd7b46..6a58565b5 100644 --- a/doc/examples/effects/combined_effects/lib/main.dart +++ b/doc/examples/effects/combined_effects/lib/main.dart @@ -65,6 +65,7 @@ class MyGame extends BaseGame with TapDetector { isInfinite: false, isAlternating: true, offset: 0.5, + onComplete: () => print("onComplete callback"), ); greenSquare.addEffect(combination); } diff --git a/lib/effects/combined_effect.dart b/lib/effects/combined_effect.dart index 3adb89eaa..74bebf49b 100644 --- a/lib/effects/combined_effect.dart +++ b/lib/effects/combined_effect.dart @@ -14,7 +14,8 @@ class CombinedEffect extends PositionComponentEffect { this.offset = 0.0, bool isInfinite = false, bool isAlternating = false, - }) : super(isInfinite, isAlternating) { + Function onComplete, + }) : super(isInfinite, isAlternating, onComplete: onComplete) { final types = effects.map((e) => e.runtimeType); assert( types.toSet().length == types.length, diff --git a/lib/effects/effects.dart b/lib/effects/effects.dart index 6965ae53c..ea31b677d 100644 --- a/lib/effects/effects.dart +++ b/lib/effects/effects.dart @@ -12,6 +12,7 @@ export './sequence_effect.dart'; abstract class PositionComponentEffect { PositionComponent component; + Function() onComplete; bool _isDisposed = false; bool get isDisposed => _isDisposed; @@ -37,7 +38,11 @@ abstract class PositionComponentEffect { /// travel time double get totalTravelTime => travelTime * (isAlternating ? 2 : 1); - PositionComponentEffect(this._initialIsInfinite, this._initialIsAlternating) { + PositionComponentEffect( + this._initialIsInfinite, + this._initialIsAlternating, { + this.onComplete, + }) { isInfinite = _initialIsInfinite; isAlternating = _initialIsAlternating; } @@ -53,6 +58,9 @@ abstract class PositionComponentEffect { if (!hasFinished()) { currentTime += dt * curveDirection + driftTime * driftMultiplier; percentage = min(1.0, max(0.0, currentTime / travelTime)); + if (hasFinished()){ + onComplete?.call(); + } } } diff --git a/lib/effects/move_effect.dart b/lib/effects/move_effect.dart index c7857c8f5..edb9f84a8 100644 --- a/lib/effects/move_effect.dart +++ b/lib/effects/move_effect.dart @@ -28,7 +28,8 @@ class MoveEffect extends PositionComponentEffect { this.curve, isInfinite = false, isAlternating = false, - }) : super(isInfinite, isAlternating); + Function onComplete + }) : super(isInfinite, isAlternating, onComplete: onComplete); @override void initialize(_comp) { diff --git a/lib/effects/rotate_effect.dart b/lib/effects/rotate_effect.dart index 19aa2e640..30e46adcc 100644 --- a/lib/effects/rotate_effect.dart +++ b/lib/effects/rotate_effect.dart @@ -18,7 +18,8 @@ class RotateEffect extends PositionComponentEffect { this.curve, isInfinite = false, isAlternating = false, - }) : super(isInfinite, isAlternating); + Function onComplete, + }) : super(isInfinite, isAlternating, onComplete: onComplete); @override void initialize(_comp) { diff --git a/lib/effects/scale_effect.dart b/lib/effects/scale_effect.dart index 8b2424996..41a525658 100644 --- a/lib/effects/scale_effect.dart +++ b/lib/effects/scale_effect.dart @@ -25,7 +25,8 @@ class ScaleEffect extends PositionComponentEffect { this.curve, isInfinite = false, isAlternating = false, - }) : super(isInfinite, isAlternating); + Function onComplete, + }) : super(isInfinite, isAlternating, onComplete: onComplete); @override void initialize(_comp) { diff --git a/lib/effects/sequence_effect.dart b/lib/effects/sequence_effect.dart index 5dcac0be4..953ce83ca 100644 --- a/lib/effects/sequence_effect.dart +++ b/lib/effects/sequence_effect.dart @@ -14,7 +14,8 @@ class SequenceEffect extends PositionComponentEffect { @required this.effects, isInfinite = false, isAlternating = false, - }) : super(isInfinite, isAlternating) { + Function onComplete, + }) : super(isInfinite, isAlternating, onComplete: onComplete) { assert( effects.every((effect) => effect.component == null), "No effects can be added to components from the start", From acde967bbc899b30949c1c7acdecdccac84cf3a0 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Wed, 24 Jun 2020 11:50:24 +0200 Subject: [PATCH 06/16] Fix formatting --- lib/effects/effects.dart | 10 +++++----- lib/effects/move_effect.dart | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/effects/effects.dart b/lib/effects/effects.dart index ea31b677d..658351182 100644 --- a/lib/effects/effects.dart +++ b/lib/effects/effects.dart @@ -39,10 +39,10 @@ abstract class PositionComponentEffect { double get totalTravelTime => travelTime * (isAlternating ? 2 : 1); PositionComponentEffect( - this._initialIsInfinite, - this._initialIsAlternating, { - this.onComplete, - }) { + this._initialIsInfinite, + this._initialIsAlternating, { + this.onComplete, + }) { isInfinite = _initialIsInfinite; isAlternating = _initialIsAlternating; } @@ -58,7 +58,7 @@ abstract class PositionComponentEffect { if (!hasFinished()) { currentTime += dt * curveDirection + driftTime * driftMultiplier; percentage = min(1.0, max(0.0, currentTime / travelTime)); - if (hasFinished()){ + if (hasFinished()) { onComplete?.call(); } } diff --git a/lib/effects/move_effect.dart b/lib/effects/move_effect.dart index edb9f84a8..21681c6be 100644 --- a/lib/effects/move_effect.dart +++ b/lib/effects/move_effect.dart @@ -22,14 +22,14 @@ class MoveEffect extends PositionComponentEffect { double _yDistance; double _yDirection; - MoveEffect({ - @required this.destination, - @required this.speed, - this.curve, - isInfinite = false, - isAlternating = false, - Function onComplete - }) : super(isInfinite, isAlternating, onComplete: onComplete); + MoveEffect( + {@required this.destination, + @required this.speed, + this.curve, + isInfinite = false, + isAlternating = false, + Function onComplete}) + : super(isInfinite, isAlternating, onComplete: onComplete); @override void initialize(_comp) { From cdf7de615d5a952ef022b2f298c760953fb92040 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Wed, 24 Jun 2020 20:55:23 +0200 Subject: [PATCH 07/16] Fixed argument list --- lib/effects/move_effect.dart | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/effects/move_effect.dart b/lib/effects/move_effect.dart index 21681c6be..a60d0bcd9 100644 --- a/lib/effects/move_effect.dart +++ b/lib/effects/move_effect.dart @@ -22,14 +22,14 @@ class MoveEffect extends PositionComponentEffect { double _yDistance; double _yDirection; - MoveEffect( - {@required this.destination, - @required this.speed, - this.curve, - isInfinite = false, - isAlternating = false, - Function onComplete}) - : super(isInfinite, isAlternating, onComplete: onComplete); + MoveEffect({ + @required this.destination, + @required this.speed, + this.curve, + isInfinite = false, + isAlternating = false, + Function onComplete, + }) : super(isInfinite, isAlternating, onComplete: onComplete); @override void initialize(_comp) { From 3148a483e3cf0d5faae427e35b40fcd1d08182a7 Mon Sep 17 00:00:00 2001 From: Erick Zanardo Date: Thu, 25 Jun 2020 18:19:05 -0300 Subject: [PATCH 08/16] PR nits --- doc/layers.md | 12 ++++++------ lib/layer/layer.dart | 4 ++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/doc/layers.md b/doc/layers.md index 7b5472447..d2feadf34 100644 --- a/doc/layers.md +++ b/doc/layers.md @@ -1,12 +1,12 @@ # Layers -Layers are an useful feature that lets you group renderization by context, and to also to obtain a way of pre rendering things, enabling for example the renderization in memory of parts of your game that don't change much, like a background for example, and by doing that, freeing resources for more dynamic content that needs to be rendered every loop cycle. +Layers are an useful feature that lets you group renderization by context, as well as allow you yo pre-render things. That enables, for example, the renderization in memory of parts of your game that don't change much, like a background, and by doing that, freeing resources for more dynamic content that needs to be rendered every loop cycle. -There are two types of layers on Flame: `DynamicLayer` and `PreRenderedLayer`. +There are two types of layers on Flame: `DynamicLayer` (for things that are moving or changing) and `PreRenderedLayer` (for things that are static). ## DynamicLayer -Dynamic layers are layers that are rendered every time that they are draw on the canvas, as the name suggests, it is meant for dynamic content and is most useful to group renderizations that are of the same context. +Dynamic layers are layers that are rendered every time that they are draw on the canvas. As the name suggests, it is meant for dynamic content and is most useful to group renderizations that are of the same context. Usage example: ```dart @@ -40,7 +40,7 @@ class MyGame extends Game { ## PreRenderedLayer -Pre rendered layers are layers that are rendered only once, cached on the memory and they can be used to be rendered on the game canas aftwards. They are most uesful to cache content that don't change during the game, like a background for example. +Pre-rendered layers are layers that are rendered only once, cached in memory and then just replicated on the game canvas afterwards. They are most useful to cache content that don't change during the game, like a background for example. Usage example: ```dart @@ -70,7 +70,7 @@ class MyGame extends Game { ## Layer Processors -Flame also provides a way to add processors on your layer, which are ways to add effects on all of your layer. At the moment, out of the box, only the `ShadowProcessor` is available, this processor renders a cool back drop shadow on your layer. +Flame also provides a way to add processors on your layer, which are ways to add effects on the entire layer. At the moment, out of the box, only the `ShadowProcessor` is available, this processor renders a cool back drop shadow on your layer. To add processors to your layer, just add them to the layer `preProcessors` or `postProcessors` list. For example: @@ -89,4 +89,4 @@ class BackgroundLayer extends PreRenderedLayer { Custom processors can be creted by extending the `LayerProcessor` class. -You can check an working example of layers [here](/doc/examples/layers) +You can check an working example of layers [here](/doc/examples/layers). diff --git a/lib/layer/layer.dart b/lib/layer/layer.dart index 5b534e81b..4983e210e 100644 --- a/lib/layer/layer.dart +++ b/lib/layer/layer.dart @@ -53,6 +53,10 @@ abstract class Layer { abstract class PreRenderedLayer extends Layer { PreRenderedLayer() { + reRender(); + } + + void reRender() { beginRendering(); drawLayer(); finishRendering(); From 57cbee9727276ba095df5070d7cdcb72cfd8f4d1 Mon Sep 17 00:00:00 2001 From: Erick Zanardo Date: Thu, 25 Jun 2020 18:22:02 -0300 Subject: [PATCH 09/16] Adding CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ee191753..ca50091bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Adding BaseGame#markToRemove - Upgrade tiled and flutter_svg dependencies - onComplete callback for effects + - Adding Layers ## 0.22.1 - Fix Box2DComponent render priority From 0041c2894f6d982589ad20d38467ee1b6b900c92 Mon Sep 17 00:00:00 2001 From: Luan Nico Date: Sun, 28 Jun 2020 12:50:41 -0400 Subject: [PATCH 10/16] Update tiled and add rotation feature --- doc/examples/tiled/assets/tiles/map.tmx | 4 +- doc/examples/tiled/lib/main.dart | 10 ++- lib/components/tiled_component.dart | 86 +++++++++++++++++++++++-- pubspec.yaml | 2 +- 4 files changed, 91 insertions(+), 11 deletions(-) diff --git a/doc/examples/tiled/assets/tiles/map.tmx b/doc/examples/tiled/assets/tiles/map.tmx index 86ea3c2d7..383dcc54c 100644 --- a/doc/examples/tiled/assets/tiles/map.tmx +++ b/doc/examples/tiled/assets/tiles/map.tmx @@ -1,5 +1,5 @@ - + @@ -18,7 +18,7 @@ - QQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD8AAAA+AAAAQAAAAD8AAAA+AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPQAAAEEAAABBAAAAPQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA9AAAAQQAAAEEAAAA9AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAADAAAAAOwAAADsAAAA7AAAAwAAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAD0AAABBAAAAQQAAAD0AAABBAAAAQQAAAEEAAAA7AAAAOwAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAMAAAAA7AAAAOwAAADsAAADAAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAwAAAADsAAAA7AAAAOwAAAMAAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAADAAAAAOwAAADsAAAA7AAAAwAAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAMAAAAA7AAAAOwAAADsAAADAAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAwAAAADsAAAA7AAAAOwAAAMAAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAADAAAAAOwAAADsAAAA7AAAAwAAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAMAAAADAAAAAwAAAAMAAAADAAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABAAAAAPwAAAD8AAAA+AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAD0AAABBAAAAQQAAAD0AAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPQAAAEEAAABBAAAAPQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA9AAAAQQAAAEEAAAA9AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA7AAAAOwAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD8AAAA/AAAAPwAAAD8AAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD8AAAA/AAAAPwAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADcAAAA4AAAAOQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA7AAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA3AAAAOAAAADkAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA7AAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAADsAAAA7AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABBAAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAEEAAABBAAAAQQAAAEEAAABBAAAAOwAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA7AAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA3AAAAOAAAADkAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAADsAAAA7AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAANwAAADgAAAA5AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA3AAAAOAAAADkAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAAA3AAAAOAAAADkAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAOwAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABBAAAAPAAAADQAAAA6AAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADcAAAA4AAAAOQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA3AAAAOAAAADkAAABBAAAAOwAAADwAAAA0AAAAOgAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAABcAAAAVAAAAFgAAAEEAAAA8AAAANAAAADoAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAAGAAAAFwAAABdAAAAQQAAADwAAAA0AAAAOgAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD4AAABAAAAAPgAAAEAAAAA/AAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEEAAABBAAAAQQAAAEEAAAA7AAAAOwAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD8AAAA/AAAAPgAAAEAAAAA/AAAAPwAAAD4AAABAAAAAPwAAAD4AAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADcAAAA4AAAAOQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAAA7AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEAAAAA+AAAAPgAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA9AAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAD0AAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADcAAAA4AAAAOQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAOwAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAOwAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAOwAAAEEAAAA7AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAAA7AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAANwAAADgAAAA5AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA7AAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAANwAAADgAAAA5AAAAQQAAADwAAAA0AAAAOgAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA3AAAAOAAAADkAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAPAAAADQAAAA6AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABfAAAANQAAADYAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAADwAAAA0AAAAOgAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAPAAAADQAAAA6AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAADsAAAA8AAAANAAAADoAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAOwAAADwAAAA0AAAAOgAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAXwAAADUAAAA2AAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAAA8AAAANAAAADoAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAANwAAADgAAAA5AAAAQQAAAEEAAABBAAAAQQAAAEEAAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAANwAAADgAAAA5AAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAOwAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAANwAAADgAAAA5AAAAPAAAADQAAAA6AAAANwAAADgAAAA5AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAABfAAAANQAAADYAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABAAAAAPgAAAEAAAAA+AAAAQQAAAF8AAAA1AAAANgAAADsAAABBAAAAQQAAADwAAAA0AAAAOgAAAF8AAAA1AAAANgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAD4AAABAAAAAPgAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAXwAAADUAAAA2AAAAXwAAADUAAAA2AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABfAAAANQAAADYAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAABfAAAANQAAADYAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAOwAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAAA3AAAAOAAAADkAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAABfAAAANQAAADYAAABfAAAANQAAADYAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAABBAAAAQQAAADsAAAA7AAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAF8AAAA1AAAANgAAAF8AAAA1AAAANgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAF8AAAA1AAAANgAAAF8AAAA1AAAANgAAAEEAAABBAAAAOwAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABfAAAANQAAADYAAABfAAAANQAAADYAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAF8AAAA1AAAANgAAAF8AAAA1AAAANgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAXwAAADUAAAA2AAAAPAAAAEAAAAA+AAAAawAAAGwAAABAAAAAPgAAADQAAAA6AAAAPAAAADQAAAA6AAAAXwAAADUAAAA2AAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAAA7AAAAQQAAAEEAAABfAAAANQAAADYAAAA8AAAANAAAADoAAAA8AAAAPQAAAGsAAABsAAAAawAAAGwAAAA9AAAANAAAADoAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAAA7AAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAQQAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAABAAAAAPgAAAGsAAABsAAAAQAAAAD4AAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADsAAABBAAAAQQAAAAoAAABBAAAAQQAAABcAAAAWAAAAFwAAABYAAAAXAAAAFgAAABcAAAAWAAAAFwAAABYAAAAXAAAAFgAAABcAAAAWAAAAFwAAABYAAAAXAAAAFgAAABcAAAAWAAAAFwAAABYAAAAXAAAAFgAAABcAAAAWAAAAQQAAAEEAAABBAAAACwAAAIEAAACCAAAAGAAAAF0AAAAYAAAAXQAAABgAAABdAAAAGAAAAF0AAAAYAAAAXQAAABgAAABdAAAAGAAAAF0AAAAYAAAAXQAAABgAAABdAAAAGAAAAF0AAAAYAAAAXQAAABgAAABdAAAAGAAAAF0AAABCAAAAggAAAEIAAAAMAAAAQwAAABoAAAAZAAAAGgAAAEQAAABDAAAAGQAAABkAAAAaAAAARAAAAEMAAAAZAAAAGQAAABoAAABEAAAAQwAAABkAAAAZAAAAGgAAAEQAAABDAAAAGQAAABkAAAAaAAAARAAAAEMAAAAZAAAARAAAAEMAAABEAAAAQwAAAA== + QQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD8AAAA+AAAAQAAAAD8AAAA+AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADcAACBBAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPQAAAEEAAABBAAAAPQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA9AAAAQQAAAEEAAAA9AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAADAAAAAOwAAADsAAAA7AAAAwAAAAEEAAABBAAAANwAA4EEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAD0AAABBAAAAQQAAAD0AAABBAAAAQQAAAEEAAAA7AAAAOwAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAMAAAAA7AAAAOwAAADsAAADAAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAwAAAADsAAAA7AAAAOwAAAMAAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAADcAAOBBAAAAQQAAAEEAAABBAAAAQQAAAEEAAADAAAAAOwAAADsAAAA7AAAAwAAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAMAAAAA7AAAAOwAAADsAAADAAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAwAAAADsAAAA7AAAAOwAAAMAAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAADAAAAAOwAAADsAAAA7AAAAwAAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAMAAAADAAAAAwAAAAMAAAADAAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABAAAAAPwAAAD8AAAA+AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAD0AAABBAAAAQQAAAD0AAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPQAAAEEAAABBAAAAPQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA9AAAAQQAAAEEAAAA9AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA7AAAAOwAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD8AAAA/AAAAPwAAAD8AAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD8AAAA/AAAAPwAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADcAAAA4AAAAOQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA7AAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA3AAAAOAAAADkAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA7AAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAADsAAAA7AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABBAAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAEEAAABBAAAAQQAAAEEAAABBAAAAOwAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA7AAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA3AAAAOAAAADkAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAADsAAAA7AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAANwAAADgAAAA5AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA3AAAAOAAAADkAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAAA3AAAAOAAAADkAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAOwAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABBAAAAPAAAADQAAAA6AAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADcAAAA4AAAAOQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA3AAAAOAAAADkAAABBAAAAOwAAADwAAAA0AAAAOgAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAABcAAAAVAAAAFgAAAEEAAAA8AAAANAAAADoAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAAGAAAAFwAAABdAAAAQQAAADwAAAA0AAAAOgAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD4AAABAAAAAPgAAAEAAAAA/AAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEEAAABBAAAAQQAAAEEAAAA7AAAAOwAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD8AAAA/AAAAPgAAAEAAAAA/AAAAPwAAAD4AAABAAAAAPwAAAD4AAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADcAAAA4AAAAOQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAAA7AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEAAAAA+AAAAPgAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA9AAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAD0AAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADcAAAA4AAAAOQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAOwAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAOwAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAOwAAAEEAAAA7AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAAA7AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAANwAAADgAAAA5AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA7AAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAANwAAADgAAAA5AAAAQQAAADwAAAA0AAAAOgAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA3AAAAOAAAADkAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAPAAAADQAAAA6AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABfAAAANQAAADYAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAADwAAAA0AAAAOgAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAPAAAADQAAAA6AAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAADsAAAA8AAAANAAAADoAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAOwAAADwAAAA0AAAAOgAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAXwAAADUAAAA2AAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAAA8AAAANAAAADoAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAANwAAADgAAAA5AAAAQQAAAEEAAABBAAAAQQAAAEEAAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABAAAAAPgAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABAAAAAPgAAAEAAAAA+AAAAQAAAAD4AAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAANwAAADgAAAA5AAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAOwAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABfAAAANQAAADYAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAANwAAADgAAAA5AAAAPAAAADQAAAA6AAAANwAAADgAAAA5AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAABfAAAANQAAADYAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABAAAAAPgAAAEAAAAA+AAAAQQAAAF8AAAA1AAAANgAAADsAAABBAAAAQQAAADwAAAA0AAAAOgAAAF8AAAA1AAAANgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAF8AAAA1AAAANgAAAEEAAABBAAAAQQAAAD4AAABAAAAAPgAAAEEAAABBAAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAXwAAADUAAAA2AAAAXwAAADUAAAA2AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABfAAAANQAAADYAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAABfAAAANQAAADYAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAOwAAAEEAAABBAAAAQQAAAEEAAAA8AAAANAAAADoAAAA3AAAAOAAAADkAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAABfAAAANQAAADYAAABfAAAANQAAADYAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAABBAAAAQQAAADsAAAA7AAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAF8AAAA1AAAANgAAAF8AAAA1AAAANgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAF8AAAA1AAAANgAAAF8AAAA1AAAANgAAAEEAAABBAAAAOwAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAPAAAADQAAAA6AAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABfAAAANQAAADYAAABfAAAANQAAADYAAABfAAAANQAAADYAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAF8AAAA1AAAANgAAAF8AAAA1AAAANgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAPAAAADQAAAA6AAAAXwAAADUAAAA2AAAAPAAAAEAAAAA+AAAAawAAAGwAAABAAAAAPgAAADQAAAA6AAAAPAAAADQAAAA6AAAAXwAAADUAAAA2AAAAXwAAADUAAAA2AAAAQQAAAEEAAABBAAAAQQAAAEEAAAA7AAAAQQAAAEEAAABfAAAANQAAADYAAAA8AAAANAAAADoAAAA8AAAAPQAAAGsAAABsAAAAawAAAGwAAAA9AAAANAAAADoAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAAA8AAAANAAAADoAAAA7AAAAQQAAAEEAAABBAAAAQQAAADsAAABBAAAAQQAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAABAAAAAPgAAAGsAAABsAAAAQAAAAD4AAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADwAAAA0AAAAOgAAADsAAABBAAAAQQAAAAoAAABBAAAAQQAAABcAAAAWAAAAFwAAABYAAAAXAAAAFgAAABcAAAAWAAAAFwAAABYAAAAXAAAAFgAAABcAAAAWAAAAFwAAABYAAAAXAAAAFgAAABcAAAAWAAAAFwAAABYAAAAXAAAAFgAAABcAAAAWAAAAQQAAAEEAAABBAAAACwAAAIEAAACCAAAAGAAAAF0AAAAYAAAAXQAAABgAAABdAAAAGAAAAF0AAAAYAAAAXQAAABgAAABdAAAAGAAAAF0AAAAYAAAAXQAAABgAAABdAAAAGAAAAF0AAAAYAAAAXQAAABgAAABdAAAAGAAAAF0AAABCAAAAggAAAEIAAAAMAAAAQwAAABoAAAAZAAAAGgAAAEQAAABDAAAAGQAAABkAAAAaAAAARAAAAEMAAAAZAAAAGQAAABoAAABEAAAAQwAAABkAAAAZAAAAGgAAAEQAAABDAAAAGQAAABkAAAAaAAAARAAAAEMAAAAZAAAARAAAAEMAAABEAAAAQwAAAA== diff --git a/doc/examples/tiled/lib/main.dart b/doc/examples/tiled/lib/main.dart index 87c0f1658..0cab05292 100644 --- a/doc/examples/tiled/lib/main.dart +++ b/doc/examples/tiled/lib/main.dart @@ -15,7 +15,7 @@ void main() { class TiledGame extends BaseGame { TiledGame() { - final TiledComponent tiledMap = TiledComponent('map.tmx'); + final TiledComponent tiledMap = TiledComponent('map.tmx', 16.0); add(tiledMap); _addCoinsInMap(tiledMap); } @@ -30,8 +30,12 @@ class TiledGame extends BaseGame { final comp = AnimationComponent( 20.0, 20.0, - Animation.sequenced('coins.png', 8, - textureWidth: 20, textureHeight: 20), + Animation.sequenced( + 'coins.png', + 8, + textureWidth: 20, + textureHeight: 20, + ), ); comp.x = obj.x.toDouble(); comp.y = obj.y.toDouble(); diff --git a/lib/components/tiled_component.dart b/lib/components/tiled_component.dart index ff34bfd7c..372a52e8d 100644 --- a/lib/components/tiled_component.dart +++ b/lib/components/tiled_component.dart @@ -1,3 +1,4 @@ +import 'dart:math' as math; import 'dart:async'; import 'dart:ui'; @@ -6,6 +7,64 @@ import 'package:flame/flame.dart'; import 'package:flutter/material.dart' show Colors; import 'package:tiled/tiled.dart' hide Image; +/// Tiled represents all flips and rotation using three possible flips: horizontal, vertical and diagonal. +/// This class converts that representation to a simpler one, that uses one angle (with pi/2 steps) and two flips (H or V). +class _SimpleFlips { + // angle (in steps of pi/2 rads), clockwise + final int angle; + // whether to flip across a central vertical axis. + final bool flipH; + // whether to flip across a central horizontal axis. + final bool flipV; + + _SimpleFlips(this.angle, this.flipH, this.flipV); + + // This is the conversion + factory _SimpleFlips.fromFlips(Flips flips) { + int angle; + bool flipV, flipH; + + if (!flips.diagonally && !flips.vertically && !flips.horizontally) { + angle = 0; + flipV = false; + flipH = false; + } else if (!flips.diagonally && !flips.vertically && flips.horizontally) { + angle = 0; + flipV = false; + flipH = true; + } else if (!flips.diagonally && flips.vertically && !flips.horizontally) { + angle = 0; + flipV = true; + flipH = false; + } else if (!flips.diagonally && flips.vertically && flips.horizontally) { + angle = 2; + flipV = false; + flipH = false; + } else if (flips.diagonally && !flips.vertically && !flips.horizontally) { + angle = 1; + flipV = false; + flipH = true; + } else if (flips.diagonally && !flips.vertically && flips.horizontally) { + angle = 1; + flipV = false; + flipH = false; + } else if (flips.diagonally && flips.vertically && !flips.horizontally) { + angle = 3; + flipV = false; + flipH = false; + } else if (flips.diagonally && flips.vertically && flips.horizontally) { + angle = 1; + flipV = true; + flipH = false; + } else { + // this should be exhaustive + throw 'Invalid combination of booleans: $flips'; + } + + return _SimpleFlips(angle, flipH, flipV); + } +} + class TiledComponent extends Component { String filename; TileMap map; @@ -13,10 +72,11 @@ class TiledComponent extends Component { Map images = {}; Future future; bool _loaded = false; + double destTileSize; static Paint paint = Paint()..color = Colors.white; - TiledComponent(this.filename) { + TiledComponent(this.filename, this.destTileSize) { future = _load(); } @@ -70,12 +130,28 @@ class TiledComponent extends Component { final image = images[tile.image.source]; final rect = tile.computeDrawRect(); - final src = Rect.fromLTWH(rect.left.toDouble(), rect.top.toDouble(), - rect.width.toDouble(), rect.height.toDouble()); - final dst = Rect.fromLTWH(tile.x.toDouble(), tile.y.toDouble(), - rect.width.toDouble(), rect.height.toDouble()); + final src = Rect.fromLTWH( + rect.left.toDouble(), + rect.top.toDouble(), + rect.width.toDouble(), + rect.height.toDouble(), + ); + final dst = Rect.fromLTWH( + tile.x * destTileSize, + tile.y * destTileSize, + destTileSize, + destTileSize, + ); + + final flips = _SimpleFlips.fromFlips(tile.flips); + c.save(); + c.translate(dst.center.dx, dst.center.dy); + c.rotate(flips.angle * math.pi / 2); + c.scale(flips.flipV ? -1.0 : 1.0, flips.flipH ? -1.0 : 1.0); + c.translate(-dst.center.dx, -dst.center.dy); c.drawImageRect(image, src, dst, paint); + c.restore(); }); }); } diff --git a/pubspec.yaml b/pubspec.yaml index 9b343717a..ee7e85495 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ dependencies: path_provider: ^1.6.0 box2d_flame: ^0.4.6 synchronized: ^2.1.0 - tiled: ^0.4.0 + tiled: ^0.5.0 convert: ^2.0.1 flutter_svg: ^0.18.0 flare_flutter: ^2.0.1 From 6c592c28b7c7e7a838d6905557b34c6e1bf106ea Mon Sep 17 00:00:00 2001 From: Luan Nico Date: Sun, 28 Jun 2020 12:56:27 -0400 Subject: [PATCH 11/16] Update docs --- doc/tiled.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/tiled.md b/doc/tiled.md index 6c5c1c84d..8035ef4be 100644 --- a/doc/tiled.md +++ b/doc/tiled.md @@ -1,7 +1,11 @@ # Tiled -[Tiled](https://www.mapeditor.org/) is an awesome tool to design levels and maps. Flame bundles a [dart package](https://pub.dev/packages/tiled) that parses tmx files and implements a very simple component for the map rendering. +[Tiled](https://www.mapeditor.org/) is an awesome tool to design levels and maps. -Right now Tiled support on Flame is quite simple and it only renders the map on the screen, other advanced features are not yet supported. +Flame bundles a [dart package](https://pub.dev/packages/tiled) that allows you to parse tmx (xml) files and access the tiles, objects and everything in there. + +Flame also provides a simple TiledComponent for the map rendering, which renders the tiles on the screen and supports rotations and flips. + +Other advanced features are not yet supported but you can easily read the objects and other features of the tmx and add custom behaviour (eg regions for triggers and walking areas, custom animated objects). You can check a working example [here](/doc/examples/tiled). From 3ab11c834bf49858fb143ca05cc8a18cd6aa60bf Mon Sep 17 00:00:00 2001 From: Luan Nico Date: Sun, 28 Jun 2020 12:59:33 -0400 Subject: [PATCH 12/16] Add to changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca50091bd..aa88aef82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,8 @@ - Upgrade tiled and flutter_svg dependencies - onComplete callback for effects - Adding Layers - + - Update tiled dep to 0.5.0 and add support for rotation with improved api + ## 0.22.1 - Fix Box2DComponent render priority - Fix PositionComponentEffect drifting From f105abfed81537da109008f11bfd2da64da39c8c Mon Sep 17 00:00:00 2001 From: Luan Nico Date: Sun, 28 Jun 2020 13:04:06 -0400 Subject: [PATCH 13/16] Fix tests --- test/components/tiled_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/components/tiled_test.dart b/test/components/tiled_test.dart index 04c0ba638..d451d9553 100644 --- a/test/components/tiled_test.dart +++ b/test/components/tiled_test.dart @@ -10,7 +10,7 @@ import 'package:test/test.dart'; void main() { test('my first widget test', () async { await Flame.init(bundle: TestAssetBundle()); - final tiled = TiledComponent('x'); + final tiled = TiledComponent('x', 16); await tiled.future; expect(1, equals(1)); }); From 752241bb976cff81ee8e6a27854e451b5b7f7ec6 Mon Sep 17 00:00:00 2001 From: Luan Nico Date: Sun, 28 Jun 2020 13:10:46 -0400 Subject: [PATCH 14/16] Better docs --- lib/components/tiled_component.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/components/tiled_component.dart b/lib/components/tiled_component.dart index 372a52e8d..daba7a52b 100644 --- a/lib/components/tiled_component.dart +++ b/lib/components/tiled_component.dart @@ -9,6 +9,7 @@ import 'package:tiled/tiled.dart' hide Image; /// Tiled represents all flips and rotation using three possible flips: horizontal, vertical and diagonal. /// This class converts that representation to a simpler one, that uses one angle (with pi/2 steps) and two flips (H or V). +/// More reference: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tile-flipping class _SimpleFlips { // angle (in steps of pi/2 rads), clockwise final int angle; From f4858305df0ba74a2c5a44ebdea9a419ba0480b1 Mon Sep 17 00:00:00 2001 From: Luan Nico Date: Sun, 28 Jun 2020 14:36:31 -0400 Subject: [PATCH 15/16] Add docs --- lib/components/tiled_component.dart | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/components/tiled_component.dart b/lib/components/tiled_component.dart index daba7a52b..814ec6168 100644 --- a/lib/components/tiled_component.dart +++ b/lib/components/tiled_component.dart @@ -11,16 +11,16 @@ import 'package:tiled/tiled.dart' hide Image; /// This class converts that representation to a simpler one, that uses one angle (with pi/2 steps) and two flips (H or V). /// More reference: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tile-flipping class _SimpleFlips { - // angle (in steps of pi/2 rads), clockwise + /// The angle (in steps of pi/2 rads), clockwise, around the center of the tile. final int angle; - // whether to flip across a central vertical axis. + /// Whether to flip across a central vertical axis (passing through the center). final bool flipH; - // whether to flip across a central horizontal axis. + /// Whether to flip across a central horizontal axis (passing through the center). final bool flipV; _SimpleFlips(this.angle, this.flipH, this.flipV); - // This is the conversion + /// This is the conversion from the truth table that I drew. factory _SimpleFlips.fromFlips(Flips flips) { int angle; bool flipV, flipH; @@ -66,6 +66,7 @@ class _SimpleFlips { } } +/// This component renders a tile map based on a TMX file from Tiled. class TiledComponent extends Component { String filename; TileMap map; @@ -77,6 +78,8 @@ class TiledComponent extends Component { static Paint paint = Paint()..color = Colors.white; + /// Creates this TiledComponent with the filename (for the tmx file resource) + /// and destTileSize is the tile size to be rendered (not the tile size in the texture, that one is configured inside Tiled). TiledComponent(this.filename, this.destTileSize) { future = _load(); } @@ -160,6 +163,8 @@ class TiledComponent extends Component { @override void update(double t) {} + /// This returns an object group fetch by name from a given layer. + /// Use this to add custom behaviour to special objects and groups. Future getObjectGroupFromLayer(String name) { return future.then((onValue) { return map.objectGroups From edb236b287b135cd7843a474b04b75ebefca46c4 Mon Sep 17 00:00:00 2001 From: Luan Nico Date: Sun, 28 Jun 2020 14:40:32 -0400 Subject: [PATCH 16/16] formatting --- lib/components/tiled_component.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/components/tiled_component.dart b/lib/components/tiled_component.dart index 814ec6168..f32a420e8 100644 --- a/lib/components/tiled_component.dart +++ b/lib/components/tiled_component.dart @@ -13,8 +13,10 @@ import 'package:tiled/tiled.dart' hide Image; class _SimpleFlips { /// The angle (in steps of pi/2 rads), clockwise, around the center of the tile. final int angle; + /// Whether to flip across a central vertical axis (passing through the center). final bool flipH; + /// Whether to flip across a central horizontal axis (passing through the center). final bool flipV;