[add] (render) PartMaskBuilder

This commit is contained in:
2020-01-15 12:03:47 +03:00
parent b2d510492e
commit 1f5a8de4be
9 changed files with 158 additions and 73 deletions

View File

@@ -1,67 +0,0 @@
package ru.m.puzzlez.render;
import flash.display.GraphicsPathCommand;
import flash.display.Shape;
import flash.geom.Rectangle;
import flash.Vector;
import ru.m.puzzlez.core.Part;
class PartMask extends Shape {
private static function createBound(commands:Vector<GraphicsPathCommand>, data:Vector<Float>, fromX:Float, fromY:Float, toX:Float, toY:Float, type:BoundType) {
var dx = toX == fromX ? 0 : (toX - fromX) / Math.abs(toX - fromX);
var dy = toY == fromY ? 0 : (toY - fromY) / Math.abs(toY - fromY);
var boundLength = Math.max(Math.abs(toX - fromX), Math.abs(toY - fromY));
var spikeWidth = boundLength * 0.2;
var spikeOffset = (boundLength - spikeWidth) / 2;
var spikeDepth = switch type {
case NONE: 0;
case IN: spikeWidth;
case OUT: -spikeWidth;
}
switch type {
case NONE:
case IN | OUT:
commands.push(GraphicsPathCommand.LINE_TO);
data.push(fromX + spikeOffset * dx);
data.push(fromY + spikeOffset * dy);
commands.push(GraphicsPathCommand.LINE_TO);
data.push(fromX + spikeOffset * dx - spikeDepth * dy);
data.push(fromY + spikeDepth * dx + spikeOffset * dy);
commands.push(GraphicsPathCommand.LINE_TO);
data.push(fromX + (spikeOffset + spikeWidth) * dx - spikeDepth * dy);
data.push(fromY + spikeDepth * dx + (spikeOffset + spikeWidth) * dy);
commands.push(GraphicsPathCommand.LINE_TO);
data.push(fromX + (spikeOffset + spikeWidth) * dx);
data.push(fromY + (spikeOffset + spikeWidth) * dy);
}
commands.push(GraphicsPathCommand.LINE_TO);
data.push(toX);
data.push(toY);
}
public var rect(default, null):Rectangle;
public function new(rect:Rectangle, bound:Bounds) {
super();
graphics.beginFill(0xff00ff, 1);
var commands = new Vector<GraphicsPathCommand>();
var data = new Vector<Float>();
commands.push(GraphicsPathCommand.MOVE_TO);
data.push(rect.left);
data.push(rect.top);
createBound(commands, data, rect.left, rect.top, rect.right, rect.top, bound.top);
createBound(commands, data, rect.right, rect.top, rect.right, rect.bottom, bound.right);
createBound(commands, data, rect.right, rect.bottom, rect.left, rect.bottom, bound.bottom);
createBound(commands, data, rect.left, rect.bottom, rect.left, rect.top, bound.left);
graphics.drawPath(commands, data);
graphics.endFill();
this.rect = rect.clone();
var offset = rect.width / 4 + rect.width * 0.05;
this.rect.x -= offset;
this.rect.y -= offset;
this.rect.width += offset * 2;
this.rect.height += offset * 2;
}
}

View File

@@ -1,9 +1,10 @@
package ru.m.puzzlez.render; package ru.m.puzzlez.render;
import flash.geom.Point;
import flash.display.Bitmap; import flash.display.Bitmap;
import flash.display.BitmapData; import flash.display.BitmapData;
import flash.display.PixelSnapping;
import flash.display.Sprite; import flash.display.Sprite;
import flash.geom.Point;
class PartView extends Sprite { class PartView extends Sprite {
@@ -24,8 +25,7 @@ class PartView extends Sprite {
super(); super();
this.id = id; this.id = id;
this.size = size; this.size = size;
bitmap = new Bitmap(); bitmap = new Bitmap(image, PixelSnapping.ALWAYS, true);
bitmap.bitmapData = image;
addChild(bitmap); addChild(bitmap);
} }

View File

@@ -11,6 +11,7 @@ import openfl.Assets;
import promhx.Promise; import promhx.Promise;
import ru.m.puzzlez.core.ImageSource; import ru.m.puzzlez.core.ImageSource;
import ru.m.puzzlez.core.Part; import ru.m.puzzlez.core.Part;
import ru.m.puzzlez.render.mask.PartMask;
class RenderUtil { class RenderUtil {
@@ -39,7 +40,7 @@ class RenderUtil {
var canvas:Shape = new Shape(); var canvas:Shape = new Shape();
canvas.cacheAsBitmap = true; canvas.cacheAsBitmap = true;
canvas.mask = mask; canvas.mask = mask;
canvas.graphics.beginBitmapFill(source); canvas.graphics.beginBitmapFill(source, null, false, true);
canvas.graphics.drawRect(0, 0, source.width, source.height); canvas.graphics.drawRect(0, 0, source.width, source.height);
canvas.graphics.endFill(); canvas.graphics.endFill();
var image = new BitmapData(Std.int(mask.rect.width), Std.int(mask.rect.height), true, 0x00000000); var image = new BitmapData(Std.int(mask.rect.width), Std.int(mask.rect.height), true, 0x00000000);

View File

@@ -0,0 +1,34 @@
package ru.m.puzzlez.render.mask;
import flash.display.GraphicsPathCommand;
import flash.geom.Rectangle;
import openfl.Vector;
import ru.m.puzzlez.core.Part;
import ru.m.puzzlez.render.mask.IPartMaskBuilder;
class BaseMaskBuilder implements IPartMaskBuilder {
public function new() {
}
private function createBound(path:DrawPath, fromX:Float, fromY:Float, toX:Float, toY:Float, type:BoundType):Void {
path.commands.push(GraphicsPathCommand.LINE_TO);
path.data.push(toX);
path.data.push(toY);
}
public function build(rect:Rectangle, bounds:Bounds):DrawPath {
var path:DrawPath = {
commands: new Vector<GraphicsPathCommand>(),
data: new Vector<Float>(),
}
path.commands.push(GraphicsPathCommand.MOVE_TO);
path.data.push(rect.left);
path.data.push(rect.top);
createBound(path, rect.left, rect.top, rect.right, rect.top, bounds.top);
createBound(path, rect.right, rect.top, rect.right, rect.bottom, bounds.right);
createBound(path, rect.right, rect.bottom, rect.left, rect.bottom, bounds.bottom);
createBound(path, rect.left, rect.bottom, rect.left, rect.top, bounds.left);
return path;
}
}

View File

@@ -0,0 +1,39 @@
package ru.m.puzzlez.render.mask;
import flash.display.GraphicsPathCommand;
import ru.m.puzzlez.core.Part;
import ru.m.puzzlez.render.mask.IPartMaskBuilder;
class ClassicMaskBuilder extends BaseMaskBuilder {
override private function createBound(path:DrawPath, fromX:Float, fromY:Float, toX:Float, toY:Float, type:BoundType):Void {
var dx = toX == fromX ? 0 : (toX - fromX) / Math.abs(toX - fromX);
var dy = toY == fromY ? 0 : (toY - fromY) / Math.abs(toY - fromY);
var boundLength = Math.max(Math.abs(toX - fromX), Math.abs(toY - fromY));
var spikeWidth = boundLength * 0.2;
var spikeOffset = (boundLength - spikeWidth) / 2;
var spikeDepth = switch type {
case NONE: 0;
case IN: spikeWidth;
case OUT: -spikeWidth;
};
switch type {
case NONE:
case IN | OUT:
path.commands.push(GraphicsPathCommand.LINE_TO);
path.data.push(fromX + spikeOffset * dx);
path.data.push(fromY + spikeOffset * dy);
path.commands.push(GraphicsPathCommand.CURVE_TO);
path.data.push(fromX + (spikeOffset * 0.8) * dx - spikeDepth * dy);
path.data.push(fromY + spikeDepth * dx + (spikeOffset * 0.8) * dy);
path.data.push(fromX + (spikeOffset + spikeWidth / 2) * dx - (spikeDepth * 1.1) * dy);
path.data.push(fromY + (spikeDepth * 1.1) * dx + (spikeOffset + spikeWidth / 2) * dy);
path.commands.push(GraphicsPathCommand.CURVE_TO);
path.data.push(fromX + (spikeOffset + spikeWidth + spikeOffset * 0.2) * dx - spikeDepth * dy);
path.data.push(fromY + spikeDepth * dx + (spikeOffset + spikeWidth + spikeOffset * 0.2) * dy);
path.data.push(fromX + (spikeOffset + spikeWidth) * dx);
path.data.push(fromY + (spikeOffset + spikeWidth) * dy);
}
super.createBound(path, fromY, fromY, toX, toY, type);
}
}

View File

@@ -0,0 +1,15 @@
package ru.m.puzzlez.render.mask;
import flash.display.GraphicsPathCommand;
import flash.geom.Rectangle;
import flash.Vector;
import ru.m.puzzlez.core.Part;
typedef DrawPath = {
var commands:Vector<GraphicsPathCommand>;
var data:Vector<Float>;
}
interface IPartMaskBuilder {
public function build(rect:Rectangle, bound:Bounds):DrawPath;
}

View File

@@ -0,0 +1,25 @@
package ru.m.puzzlez.render.mask;
import flash.display.Shape;
import flash.geom.Rectangle;
import ru.m.puzzlez.core.Part;
class PartMask extends Shape {
public var rect(default, null):Rectangle;
public function new(rect:Rectangle, bounds:Bounds) {
super();
graphics.beginFill(0xff00ff, 1);
var path = new ClassicMaskBuilder().build(rect, bounds);
graphics.drawPath(path.commands, path.data);
graphics.endFill();
this.rect = rect.clone();
var offset = rect.width / 4 + rect.width * 0.05;
this.rect.x -= offset;
this.rect.y -= offset;
this.rect.width += offset * 2;
this.rect.height += offset * 2;
}
}

View File

@@ -0,0 +1,38 @@
package ru.m.puzzlez.render.mask;
import flash.display.GraphicsPathCommand;
import ru.m.puzzlez.core.Part;
import ru.m.puzzlez.render.mask.IPartMaskBuilder;
class SquareMaskBuilder extends BaseMaskBuilder {
override private function createBound(path:DrawPath, fromX:Float, fromY:Float, toX:Float, toY:Float, type:BoundType):Void {
var dx = toX == fromX ? 0 : (toX - fromX) / Math.abs(toX - fromX);
var dy = toY == fromY ? 0 : (toY - fromY) / Math.abs(toY - fromY);
var boundLength = Math.max(Math.abs(toX - fromX), Math.abs(toY - fromY));
var spikeWidth = boundLength * 0.2;
var spikeOffset = (boundLength - spikeWidth) / 2;
var spikeDepth = switch type {
case NONE: 0;
case IN: spikeWidth;
case OUT: -spikeWidth;
}
switch type {
case NONE:
case IN | OUT:
path.commands.push(GraphicsPathCommand.LINE_TO);
path.data.push(fromX + spikeOffset * dx);
path.data.push(fromY + spikeOffset * dy);
path.commands.push(GraphicsPathCommand.LINE_TO);
path.data.push(fromX + spikeOffset * dx - spikeDepth * dy);
path.data.push(fromY + spikeDepth * dx + spikeOffset * dy);
path.commands.push(GraphicsPathCommand.LINE_TO);
path.data.push(fromX + (spikeOffset + spikeWidth) * dx - spikeDepth * dy);
path.data.push(fromY + spikeDepth * dx + (spikeOffset + spikeWidth) * dy);
path.commands.push(GraphicsPathCommand.LINE_TO);
path.data.push(fromX + (spikeOffset + spikeWidth) * dx);
path.data.push(fromY + (spikeOffset + spikeWidth) * dy);
}
super.createBound(path, fromY, fromY, toX, toY, type);
}
}

View File

@@ -34,11 +34,11 @@ typedef PixabayResponse = {
render.scale = 0.75; render.scale = 0.75;
scale.position = render.scale - scale.ratio; scale.position = render.scale - scale.ratio;
new JsonLoader<PixabayResponse>() /*new JsonLoader<PixabayResponse>()
.GET('https://pixabay.com/api/?key=14915210-5eae157281211e0ad28bc8def&category=nature') .GET('https://pixabay.com/api/?key=14915210-5eae157281211e0ad28bc8def&category=nature')
.then(function(result:PixabayResponse) { .then(function(result:PixabayResponse) {
images.data = images.data.concat([for (item in result.hits) URL(item.largeImageURL)]); images.data = images.data.concat([for (item in result.hits) URL(item.largeImageURL)]);
}); });*/
} }
private function imageViewFactory(index:Int, image:ImageSource):ImageView { private function imageViewFactory(index:Int, image:ImageSource):ImageView {