diff --git a/src/haxe/ru/m/puzzlez/render/PartMask.hx b/src/haxe/ru/m/puzzlez/render/PartMask.hx deleted file mode 100644 index 15437c4..0000000 --- a/src/haxe/ru/m/puzzlez/render/PartMask.hx +++ /dev/null @@ -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, data:Vector, 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(); - var data = new Vector(); - 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; - } -} diff --git a/src/haxe/ru/m/puzzlez/render/PartView.hx b/src/haxe/ru/m/puzzlez/render/PartView.hx index bc79491..e80ac04 100644 --- a/src/haxe/ru/m/puzzlez/render/PartView.hx +++ b/src/haxe/ru/m/puzzlez/render/PartView.hx @@ -1,9 +1,10 @@ package ru.m.puzzlez.render; -import flash.geom.Point; import flash.display.Bitmap; import flash.display.BitmapData; +import flash.display.PixelSnapping; import flash.display.Sprite; +import flash.geom.Point; class PartView extends Sprite { @@ -24,8 +25,7 @@ class PartView extends Sprite { super(); this.id = id; this.size = size; - bitmap = new Bitmap(); - bitmap.bitmapData = image; + bitmap = new Bitmap(image, PixelSnapping.ALWAYS, true); addChild(bitmap); } diff --git a/src/haxe/ru/m/puzzlez/render/RenderUtil.hx b/src/haxe/ru/m/puzzlez/render/RenderUtil.hx index e3750a0..4815f7f 100644 --- a/src/haxe/ru/m/puzzlez/render/RenderUtil.hx +++ b/src/haxe/ru/m/puzzlez/render/RenderUtil.hx @@ -11,6 +11,7 @@ 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 { @@ -39,7 +40,7 @@ class RenderUtil { var canvas:Shape = new Shape(); canvas.cacheAsBitmap = true; 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.endFill(); var image = new BitmapData(Std.int(mask.rect.width), Std.int(mask.rect.height), true, 0x00000000); diff --git a/src/haxe/ru/m/puzzlez/render/mask/BaseMaskBuilder.hx b/src/haxe/ru/m/puzzlez/render/mask/BaseMaskBuilder.hx new file mode 100644 index 0000000..e8a39bf --- /dev/null +++ b/src/haxe/ru/m/puzzlez/render/mask/BaseMaskBuilder.hx @@ -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(), + data: new Vector(), + } + 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; + } +} diff --git a/src/haxe/ru/m/puzzlez/render/mask/ClassicMaskBuilder.hx b/src/haxe/ru/m/puzzlez/render/mask/ClassicMaskBuilder.hx new file mode 100644 index 0000000..106f0e2 --- /dev/null +++ b/src/haxe/ru/m/puzzlez/render/mask/ClassicMaskBuilder.hx @@ -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); + } +} diff --git a/src/haxe/ru/m/puzzlez/render/mask/IPartMaskBuilder.hx b/src/haxe/ru/m/puzzlez/render/mask/IPartMaskBuilder.hx new file mode 100644 index 0000000..cee85a2 --- /dev/null +++ b/src/haxe/ru/m/puzzlez/render/mask/IPartMaskBuilder.hx @@ -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; + var data:Vector; +} + +interface IPartMaskBuilder { + public function build(rect:Rectangle, bound:Bounds):DrawPath; +} diff --git a/src/haxe/ru/m/puzzlez/render/mask/PartMask.hx b/src/haxe/ru/m/puzzlez/render/mask/PartMask.hx new file mode 100644 index 0000000..86bd72c --- /dev/null +++ b/src/haxe/ru/m/puzzlez/render/mask/PartMask.hx @@ -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; + } +} diff --git a/src/haxe/ru/m/puzzlez/render/mask/SquareMaskBuilder.hx b/src/haxe/ru/m/puzzlez/render/mask/SquareMaskBuilder.hx new file mode 100644 index 0000000..8d42bd1 --- /dev/null +++ b/src/haxe/ru/m/puzzlez/render/mask/SquareMaskBuilder.hx @@ -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); + } +} diff --git a/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.hx b/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.hx index f627143..c4c5790 100644 --- a/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.hx +++ b/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.hx @@ -34,11 +34,11 @@ typedef PixabayResponse = { render.scale = 0.75; scale.position = render.scale - scale.ratio; - new JsonLoader() + /*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)]); - }); + });*/ } private function imageViewFactory(index:Int, image:ImageSource):ImageView {