[add] ImagePartBuilder

This commit is contained in:
2020-01-27 17:57:07 +03:00
parent 198d62e12d
commit 3aa6b27a52
8 changed files with 118 additions and 40 deletions

View File

@@ -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": {}

View File

@@ -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();
}

View File

@@ -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<Part>, stream:PublicStream<Result>):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<Part>):Stream<Result> {
var stream = new PublicStream<Result>();
Timer.delay(function() buildPart(0, 5, parts, stream), 0);
return stream;
}
}

View File

@@ -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;
}
}

View File

@@ -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 {
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);
}
}
Timer.delay(loadNext, 0);
});
}
override public function update():Void {

View File

@@ -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<BitmapFilter> {
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;
}

View File

@@ -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);
}

View File

@@ -24,7 +24,15 @@ class FileSource implements IImageSource<Dynamic> {
public function loadImage(id:ImageId, preview:Bool = false):Promise<BitmapData> {
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<BitmapData>();
result.reject(error);
return result;
}
return ImageUtil.bytesToImage(bytes);
}
public function append(data:Bytes):ImageId {