diff --git a/src/haxe/ru/m/puzzlez/render/Render.hx b/src/haxe/ru/m/puzzlez/render/Render.hx index 3c6065e..6796fea 100644 --- a/src/haxe/ru/m/puzzlez/render/Render.hx +++ b/src/haxe/ru/m/puzzlez/render/Render.hx @@ -1,6 +1,5 @@ package ru.m.puzzlez.render; -import haxe.Timer; import flash.display.BitmapData; import flash.display.PNGEncoderOptions; import flash.display.Sprite; @@ -9,10 +8,12 @@ import flash.geom.Point; import flash.geom.Rectangle; import flash.net.FileReference; import flash.utils.ByteArray; +import haxe.Timer; import haxework.signal.Signal; import haxework.view.SpriteView; import ru.m.puzzlez.core.GameEvent; import ru.m.puzzlez.core.GameState; +import ru.m.puzzlez.storage.ImageStorage; class Render extends SpriteView implements IRender { @@ -40,6 +41,8 @@ class Render extends SpriteView implements IRender { private var activePart:PartView; private var activePoint:Point; + @:provide var imageStorage:ImageStorage; + public function new() { super(); progress = new ProgressView(); @@ -83,7 +86,7 @@ class Render extends SpriteView implements IRender { table.graphics.lineStyle(); progress.setProgress(0, state.parts.length); content.addChild(progress.content); - RenderUtil.resolveImage(state.preset.image).then(onImageResolved); + imageStorage.resolve(state.preset.image).then(onImageResolved); toUpdate(); } diff --git a/src/haxe/ru/m/puzzlez/render/RenderUtil.hx b/src/haxe/ru/m/puzzlez/render/RenderUtil.hx index 9fb5455..7f11a6e 100644 --- a/src/haxe/ru/m/puzzlez/render/RenderUtil.hx +++ b/src/haxe/ru/m/puzzlez/render/RenderUtil.hx @@ -7,24 +7,11 @@ import flash.filters.DropShadowFilter; import flash.geom.Matrix; import flash.geom.Point; import flash.geom.Rectangle; -import haxework.net.ImageLoader; -import openfl.Assets; -import promhx.Promise; -import ru.m.puzzlez.core.ImageSource; import ru.m.puzzlez.core.Part; import ru.m.puzzlez.render.mask.PartMask; class RenderUtil { - public static function resolveImage(source:ImageSource):Promise { - return switch source { - case ASSET(name): - Promise.promise(Assets.getBitmapData(name)); - case URL(url): - new ImageLoader().GET(url); - } - } - public static function cropImage(source:BitmapData, rect:Rectangle):BitmapData { var image = new BitmapData(Std.int(rect.width), Std.int(rect.height)); var matrix = new Matrix(); diff --git a/src/haxe/ru/m/puzzlez/storage/AssetStorage.hx b/src/haxe/ru/m/puzzlez/storage/AssetStorage.hx new file mode 100644 index 0000000..a3cdb9f --- /dev/null +++ b/src/haxe/ru/m/puzzlez/storage/AssetStorage.hx @@ -0,0 +1,21 @@ +package ru.m.puzzlez.storage; + +import openfl.Assets; +import openfl.utils.AssetType; +import promhx.Promise; +import ru.m.puzzlez.core.ImageSource; + +@:provide class AssetStorage implements ISourceStorage { + + var data:Promise>; + + public function new() { + } + + public function resolve(?type:String):Promise> { + if (data == null) { + data = Promise.promise([for (name in Assets.list(AssetType.IMAGE).filter(function(name:String) return name.substr(0, 15) == "resources/image")) ASSET(name)]); + } + return data; + } +} diff --git a/src/haxe/ru/m/puzzlez/storage/ISourceStorage.hx b/src/haxe/ru/m/puzzlez/storage/ISourceStorage.hx new file mode 100644 index 0000000..e365e16 --- /dev/null +++ b/src/haxe/ru/m/puzzlez/storage/ISourceStorage.hx @@ -0,0 +1,8 @@ +package ru.m.puzzlez.storage; + +import ru.m.puzzlez.core.ImageSource; +import promhx.Promise; + +interface ISourceStorage { + public function resolve(?type:String):Promise>; +} diff --git a/src/haxe/ru/m/puzzlez/storage/ImageStorage.hx b/src/haxe/ru/m/puzzlez/storage/ImageStorage.hx new file mode 100644 index 0000000..13e617c --- /dev/null +++ b/src/haxe/ru/m/puzzlez/storage/ImageStorage.hx @@ -0,0 +1,66 @@ +package ru.m.puzzlez.storage; + +import flash.display.Bitmap; +import flash.display.BitmapData; +import flash.display.Loader; +import flash.display.LoaderInfo; +import flash.display.PNGEncoderOptions; +import flash.events.Event; +import flash.geom.Rectangle; +import flash.utils.ByteArray; +import haxework.net.ImageLoader; +import haxework.storage.SharedObjectStorage; +import openfl.utils.Assets; +import promhx.Deferred; +import promhx.Promise; +import ru.m.puzzlez.core.ImageSource; + +@:provide class ImageStorage extends SharedObjectStorage { + + private var cache:Map>; + private var enabled:Bool; + + public function new() { + super("image_1"); + cache = new Map(); + enabled = false; + } + + public static function serialize(image:BitmapData):ByteArray { + var data = new ByteArray(); + return image.encode(new Rectangle(0, 0, image.width, image.height), new PNGEncoderOptions(), data); + return data; + } + + public static function unserialize(data:ByteArray):Promise { + var def = new Deferred(); + var loader = new Loader(); + loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(event:Event) { + def.resolve(cast(cast(event.target, LoaderInfo).content, Bitmap).bitmapData); + }); + loader.loadBytes(data); + return def.promise(); + } + + public function resolve(source:ImageSource):Promise { + if (cache.exists(source)) { + return cache.get(source); + } + var key = Std.string(source); + var result:Promise = enabled && exists(key) ? + unserialize(Reflect.field(so.data, key)) : + (switch source { + case ASSET(name): + Promise.promise(Assets.getBitmapData(name)); + case URL(url): + new ImageLoader().GET(url); + }).then(function(image) { + if (enabled) { + so.setProperty(key, serialize(image)); + } + return image; + }); + cache.set(source, result); + return result; + } +} diff --git a/src/haxe/ru/m/puzzlez/storage/PixabayStorage.hx b/src/haxe/ru/m/puzzlez/storage/PixabayStorage.hx new file mode 100644 index 0000000..48c8cea --- /dev/null +++ b/src/haxe/ru/m/puzzlez/storage/PixabayStorage.hx @@ -0,0 +1,38 @@ +package ru.m.puzzlez.storage; + +import haxework.net.JsonLoader; +import haxework.storage.SharedObjectStorage; +import promhx.Promise; +import ru.m.puzzlez.core.ImageSource; + +typedef PixabayResponse = { + hits:Array<{ + largeImageURL:String, + }> +} + +@:provide class PixabayStorage extends SharedObjectStorage implements ISourceStorage { + + private var key:String; + private var enabled:Bool; + + public function new() { + super("pixabay_1"); + key = "14915210-5eae157281211e0ad28bc8def"; + enabled = false; + } + + public function resolve(?type:String):Promise> { + return enabled && exists(type) ? + Promise.promise(read(type)) : + new JsonLoader() + .GET('https://pixabay.com/api/?key=${key}&category=${type}') + .then(function(result:PixabayResponse) { + var result = [for (item in result.hits) URL(item.largeImageURL)]; + if (enabled) { + write(type, result); + } + return result; + }); + } +} diff --git a/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.hx b/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.hx index 25c1a70..06417fe 100644 --- a/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.hx +++ b/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.hx @@ -1,25 +1,19 @@ package ru.m.puzzlez.view; -import haxework.net.JsonLoader; import haxework.view.data.DataView; import haxework.view.form.ButtonView; import haxework.view.group.VGroupView; import haxework.view.ImageView; import haxework.view.utils.DrawUtil; import openfl.utils.Assets; -import openfl.utils.AssetType; import ru.m.puzzlez.core.Game; import ru.m.puzzlez.core.GameUtil; import ru.m.puzzlez.core.IGame; import ru.m.puzzlez.core.ImageSource; import ru.m.puzzlez.render.IRender; -import ru.m.puzzlez.render.RenderUtil; - -typedef PixabayResponse = { - hits:Array<{ - largeImageURL:String, - }> -} +import ru.m.puzzlez.storage.AssetStorage; +import ru.m.puzzlez.storage.ImageStorage; +import ru.m.puzzlez.storage.PixabayStorage; @:template class PuzzlezAppView extends VGroupView { @@ -27,9 +21,13 @@ typedef PixabayResponse = { @:view private var render:IRender; private var game:IGame; + @:provide var imageStorage:ImageStorage; + @:provide var assetStorage:AssetStorage; + @:provide var pixabayStorage:PixabayStorage; + public function new() { super(); - images.data = [for (name in Assets.list(AssetType.IMAGE).filter(function(name:String) return name.substr(0, 15) == "resources/image")) ASSET(name)]; + assetStorage.resolve().then(function(data) images.data = data); } private function imageViewFactory(index:Int, image:ImageSource):ImageView { @@ -39,18 +37,14 @@ typedef PixabayResponse = { result.fillType = FillType.COVER; result.setSize(192, 128); result.image = Assets.getBitmapData("resources/icon.png"); - RenderUtil.resolveImage(image).then(function(image) result.image = image); + imageStorage.resolve(image).then(function(image) result.image = image); return result; } private function moreImages(view:ButtonView):Void { view.visible = false; view.toUpdateParent(); - new JsonLoader() - .GET('https://pixabay.com/api/?key=14915210-5eae157281211e0ad28bc8def&category=nature') - .then(function(result:PixabayResponse) { - images.data = images.data.concat([for (item in result.hits) URL(item.largeImageURL)]); - }); + pixabayStorage.resolve("nature").then(function(data) images.data = images.data.concat(data)); } public function start(image:ImageSource):Void {