From 3aa6b27a52accb33eb36ef4b725702324d5293fd Mon Sep 17 00:00:00 2001 From: shmyga Date: Mon, 27 Jan 2020 17:57:07 +0300 Subject: [PATCH] [add] ImagePartBuilder --- package.json | 4 +- src/haxe/ru/m/puzzlez/ImageUtil.hx | 4 ++ .../ru/m/puzzlez/render/ImagePartBuilder.hx | 40 +++++++++++++++++ src/haxe/ru/m/puzzlez/render/PartView.hx | 45 ++++++++++++++++--- src/haxe/ru/m/puzzlez/render/Render.hx | 25 ++++------- src/haxe/ru/m/puzzlez/render/RenderUtil.hx | 22 ++++----- .../puzzlez/render/mask/ClassicMaskBuilder.hx | 8 ++-- src/haxe/ru/m/puzzlez/storage/FileSource.hx | 10 ++++- 8 files changed, 118 insertions(+), 40 deletions(-) create mode 100644 src/haxe/ru/m/puzzlez/render/ImagePartBuilder.hx diff --git a/package.json b/package.json index ba5e535..eedbee1 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,8 @@ }, "haxeDependencies": { "haxework": "git@bitbucket.org:shmyga/haxework.git", - "lime": "7.5.0", - "openfl": "8.9.1", + "lime": "7.6.3", + "openfl": "8.9.5", "hxcpp": "4.0.52" }, "dependencies": {} diff --git a/src/haxe/ru/m/puzzlez/ImageUtil.hx b/src/haxe/ru/m/puzzlez/ImageUtil.hx index cf473ac..af70dc4 100644 --- a/src/haxe/ru/m/puzzlez/ImageUtil.hx +++ b/src/haxe/ru/m/puzzlez/ImageUtil.hx @@ -6,6 +6,7 @@ import flash.display.Loader; import flash.display.LoaderInfo; import flash.events.Event; import haxe.io.Bytes; +import openfl.events.IOErrorEvent; import promhx.Deferred; import promhx.Promise; @@ -17,6 +18,9 @@ class ImageUtil { loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(event:Event) { def.resolve(cast(cast(event.target, LoaderInfo).content, Bitmap).bitmapData); }); + loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, function(event:IOErrorEvent) { + def.throwError(event); + }); loader.loadBytes(bytes); return def.promise(); } diff --git a/src/haxe/ru/m/puzzlez/render/ImagePartBuilder.hx b/src/haxe/ru/m/puzzlez/render/ImagePartBuilder.hx new file mode 100644 index 0000000..62f6f45 --- /dev/null +++ b/src/haxe/ru/m/puzzlez/render/ImagePartBuilder.hx @@ -0,0 +1,40 @@ +package ru.m.puzzlez.render; + +import flash.display.BitmapData; +import haxe.Timer; +import promhx.PublicStream; +import promhx.Stream; +import ru.m.puzzlez.core.Part; + +typedef Result = { + var part:Part; + var image:BitmapData; +} + +class ImagePartBuilder { + + private var image:BitmapData; + + public function new(image:BitmapData) { + this.image = image; + } + + private function buildPart(index:Int, count:Int, parts:Array, stream:PublicStream):Void { + for (i in index...index + count) { + if (i >= parts.length) { + stream.end(); + return; + } + var part = parts[i]; + var partImage = RenderUtil.cropImagePart(image, part); + stream.update({part: part, image: partImage}); + } + Timer.delay(function() buildPart(index + count, count, parts, stream), 0); + } + + public function build(parts:Array):Stream { + var stream = new PublicStream(); + Timer.delay(function() buildPart(0, 5, parts, stream), 0); + return stream; + } +} diff --git a/src/haxe/ru/m/puzzlez/render/PartView.hx b/src/haxe/ru/m/puzzlez/render/PartView.hx index b687860..d6bd233 100644 --- a/src/haxe/ru/m/puzzlez/render/PartView.hx +++ b/src/haxe/ru/m/puzzlez/render/PartView.hx @@ -22,26 +22,59 @@ class PartView extends Sprite { private function set_image(value:BitmapData):BitmapData { image = value; - bitmap.bitmapData = image; + redraw(); refresh(); return image; } private var size:Point; - private var bitmap:Bitmap; public function new(id:Int, image:BitmapData, size:Point) { super(); + filters = RenderUtil.buildFilters(); this.id = id; this.size = size; - bitmap = new Bitmap(image, PixelSnapping.ALWAYS, true); - addChild(bitmap); + if (image != null) { + this.image = image; + } + } + + private function redraw():Void { + throw "Unimplemented"; } private function refresh():Void { if (position != null && image != null) { - x = position.x - (bitmap.bitmapData.width - size.x) / 2; - y = position.y - (bitmap.bitmapData.height - size.y) / 2; + x = position.x - (image.width - size.x) / 2; + y = position.y - (image.height - size.y) / 2; } } + + public static function factory(id:Int, image:BitmapData, size:Point):PartView { + return new BitmapPartView(id, image, size); + } +} + +class SpritePartView extends PartView { + + override private function redraw():Void { + graphics.clear(); + graphics.beginBitmapFill(image, null, false, true); + graphics.drawRect(0, 0, image.width, image.height); + graphics.endFill(); + } +} + +class BitmapPartView extends PartView { + private var bitmap:Bitmap; + + public function new(id:Int, image:BitmapData, size:Point) { + super(id, image, size); + bitmap = new Bitmap(image, PixelSnapping.AUTO, true); + addChild(bitmap); + } + + override private function redraw():Void { + bitmap.bitmapData = image; + } } diff --git a/src/haxe/ru/m/puzzlez/render/Render.hx b/src/haxe/ru/m/puzzlez/render/Render.hx index cca3ca3..303143b 100644 --- a/src/haxe/ru/m/puzzlez/render/Render.hx +++ b/src/haxe/ru/m/puzzlez/render/Render.hx @@ -8,7 +8,6 @@ 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; @@ -73,7 +72,7 @@ class Render extends SpriteView implements IRender { clean(); this.state = state; for (part in state.parts) { - var partView = new PartView(part.id, null, part.rect.size); + var partView = PartView.factory(part.id, null, part.rect.size); partView.position = part.rect.topLeft; parts.set(part.id, partView); table.addChild(partView); @@ -93,22 +92,14 @@ class Render extends SpriteView implements IRender { private function onImageResolved(image:BitmapData):Void { this.image = RenderUtil.cropImage(image, state.preset.imageRect); + var builder = new ImagePartBuilder(this.image); var i = 0; - var loadNext = null; - loadNext = function():Void { - var part = state.parts[i]; - var partImage = RenderUtil.cropImagePart(this.image, part); - var partView = parts[part.id]; - partView.image = partImage; - progress.setProgress(i, state.parts.length); - if (i < state.parts.length - 1) { - i++; - Timer.delay(loadNext, 0); - } else { - content.removeChild(progress.content); - } - } - Timer.delay(loadNext, 0); + builder.build(state.parts).then(function(result) { + parts[result.part.id].image = result.image; + progress.setProgress(++i, state.parts.length); + }).endThen(function(_) { + content.removeChild(progress.content); + }); } override public function update():Void { diff --git a/src/haxe/ru/m/puzzlez/render/RenderUtil.hx b/src/haxe/ru/m/puzzlez/render/RenderUtil.hx index 7f11a6e..c21570e 100644 --- a/src/haxe/ru/m/puzzlez/render/RenderUtil.hx +++ b/src/haxe/ru/m/puzzlez/render/RenderUtil.hx @@ -2,10 +2,10 @@ package ru.m.puzzlez.render; import flash.display.BitmapData; import flash.display.Shape; +import flash.filters.BitmapFilter; import flash.filters.BitmapFilterQuality; import flash.filters.DropShadowFilter; import flash.geom.Matrix; -import flash.geom.Point; import flash.geom.Rectangle; import ru.m.puzzlez.core.Part; import ru.m.puzzlez.render.mask.PartMask; @@ -22,6 +22,17 @@ class RenderUtil { return image; } + public static function buildFilters():Array { + var alpha = 0.6; + var blur = 1; + var strength = 4; + var distance = 2; + return [ + new DropShadowFilter(distance, 45 + 180, 0xffffff, alpha, blur, blur, strength, BitmapFilterQuality.HIGH, false), + new DropShadowFilter(distance, 45, 0x000000, alpha, blur, blur, strength, BitmapFilterQuality.HIGH, false), + ]; + } + public static function cropImagePart(source:BitmapData, part:Part):BitmapData { var rect = new Rectangle(part.rect.width * part.gridX, part.rect.height * part.gridY, part.rect.width, part.rect.width); var mask = new PartMask(rect, part.bounds); @@ -35,15 +46,6 @@ class RenderUtil { var matrix = new Matrix(); matrix.translate(-mask.rect.x, -mask.rect.y); image.draw(canvas, matrix, null, null, null, true); - var alpha = 1.0; - var blur = 2; - var strength = 255; - #if flash - alpha = 0.5; - strength = 8; - #end - image.applyFilter(image, image.rect, new Point(), new DropShadowFilter(0, 0, 0x000000, alpha, blur, blur, strength, BitmapFilterQuality.HIGH, true)); - image.applyFilter(image, image.rect, new Point(), new DropShadowFilter(0, 0, 0xffffff, alpha, blur / 2, blur / 2, strength / 2, BitmapFilterQuality.HIGH, true)); return image; } diff --git a/src/haxe/ru/m/puzzlez/render/mask/ClassicMaskBuilder.hx b/src/haxe/ru/m/puzzlez/render/mask/ClassicMaskBuilder.hx index 9f83490..feea67b 100644 --- a/src/haxe/ru/m/puzzlez/render/mask/ClassicMaskBuilder.hx +++ b/src/haxe/ru/m/puzzlez/render/mask/ClassicMaskBuilder.hx @@ -29,13 +29,13 @@ class ClassicMaskBuilder extends BaseMaskBuilder { path.data.push(fromX + spikeOffset * dx + spikeSideOffset * dy); path.data.push(fromY + spikeOffset * dy + spikeSideOffset * dx); path.commands.push(GraphicsPathCommand.CURVE_TO); - path.data.push(fromX + (spikeOffset * 0.8) * dx - spikeDepth * dy + spikeSideOffset * dy); - path.data.push(fromY + spikeDepth * dx + (spikeOffset * 0.8) * dy + spikeSideOffset * dx); + path.data.push(fromX + (spikeOffset * 0.7) * dx - spikeDepth * dy + spikeSideOffset * dy); + path.data.push(fromY + spikeDepth * dx + (spikeOffset * 0.7) * dy + spikeSideOffset * dx); path.data.push(fromX + (spikeOffset + spikeWidth / 2) * dx - (spikeDepth * 1.1) * dy + spikeSideOffset * dy); path.data.push(fromY + (spikeDepth * 1.1) * dx + (spikeOffset + spikeWidth / 2) * dy + spikeSideOffset * dx); path.commands.push(GraphicsPathCommand.CURVE_TO); - path.data.push(fromX + (spikeOffset + spikeWidth + spikeOffset * 0.2) * dx - spikeDepth * dy + spikeSideOffset * dy); - path.data.push(fromY + spikeDepth * dx + (spikeOffset + spikeWidth + spikeOffset * 0.2) * dy + spikeSideOffset * dx); + path.data.push(fromX + (spikeOffset + spikeWidth + spikeOffset * 0.3) * dx - spikeDepth * dy + spikeSideOffset * dy); + path.data.push(fromY + spikeDepth * dx + (spikeOffset + spikeWidth + spikeOffset * 0.3) * dy + spikeSideOffset * dx); path.data.push(fromX + (spikeOffset + spikeWidth) * dx + spikeSideOffset * dy); path.data.push(fromY + (spikeOffset + spikeWidth) * dy + spikeSideOffset * dx); } diff --git a/src/haxe/ru/m/puzzlez/storage/FileSource.hx b/src/haxe/ru/m/puzzlez/storage/FileSource.hx index df7ef94..df8480a 100644 --- a/src/haxe/ru/m/puzzlez/storage/FileSource.hx +++ b/src/haxe/ru/m/puzzlez/storage/FileSource.hx @@ -24,7 +24,15 @@ class FileSource implements IImageSource { public function loadImage(id:ImageId, preview:Bool = false):Promise { var fileData = SharedObject.getLocal(id); - return ImageUtil.bytesToImage(Bytes.ofHex(Reflect.field(fileData.data, "image"))); + var bytes = null; + try { + bytes = Bytes.ofHex(Reflect.field(fileData.data, "image")); + } catch (error:Dynamic) { + var result = new Promise(); + result.reject(error); + return result; + } + return ImageUtil.bytesToImage(bytes); } public function append(data:Bytes):ImageId {