[improve] (render) part shadow

This commit is contained in:
2020-02-12 11:57:53 +03:00
parent 1b6ed32d0a
commit fe6d605b13
10 changed files with 100 additions and 89 deletions

View File

@@ -0,0 +1,28 @@
package ru.m.draw;
import flash.display.Graphics;
import flash.display.GraphicsPathCommand;
import flash.Vector;
class DrawPath {
public var commands(default, null):Vector<GraphicsPathCommand>;
public var data(default, null):Vector<Float>;
public function new() {
commands = new Vector();
data = new Vector();
}
public function draw(graphics:Graphics):Void {
graphics.drawPath(commands, data);
}
public function move(x:Float, y:Float):DrawPath {
var result = new DrawPath();
result.commands = commands.slice();
for (value in data) {
result.data.push(value + x);
}
return result;
}
}

View File

@@ -1,10 +1,10 @@
package ru.m.puzzlez.render; package ru.m.puzzlez.render;
import haxework.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.PixelSnapping;
import flash.display.Sprite; import flash.display.Sprite;
import haxework.geom.Point;
import ru.m.puzzlez.core.Part; import ru.m.puzzlez.core.Part;
class PartView extends Sprite { class PartView extends Sprite {
@@ -33,9 +33,6 @@ class PartView extends Sprite {
public function new(part:Part) { public function new(part:Part) {
super(); super();
#if !android
filters = RenderUtil.buildFilters();
#end
this.id = part.id; this.id = part.id;
this.size = part.rect.size.clone(); this.size = part.rect.size.clone();
this.target = new Point(part.gridX * size.x, part.gridY * size.y); this.target = new Point(part.gridX * size.x, part.gridY * size.y);

View File

@@ -2,15 +2,15 @@ package ru.m.puzzlez.render;
import flash.display.BitmapData; import flash.display.BitmapData;
import flash.display.Shape; import flash.display.Shape;
import flash.filters.BitmapFilter;
import flash.filters.BitmapFilterQuality;
import flash.filters.DropShadowFilter;
import flash.geom.Matrix; import flash.geom.Matrix;
import haxework.geom.Rectangle; import haxework.geom.Rectangle;
import ru.m.puzzlez.core.Part; import ru.m.puzzlez.core.Part;
import ru.m.puzzlez.render.mask.PartMask; import ru.m.puzzlez.render.part.ClassicPartBuilder;
import ru.m.puzzlez.render.part.IPartBuilder;
import ru.m.puzzlez.render.part.PartMask;
class RenderUtil { class RenderUtil {
private static var builder:IPartBuilder = new ClassicPartBuilder();
public static function cropImage(source:BitmapData, rect:Rectangle):BitmapData { public static function cropImage(source:BitmapData, rect:Rectangle):BitmapData {
var image = new BitmapData(Std.int(rect.width), Std.int(rect.height)); var image = new BitmapData(Std.int(rect.width), Std.int(rect.height));
@@ -22,37 +22,48 @@ class RenderUtil {
return image; return image;
} }
public static function buildFilters():Array<BitmapFilter> { private static function buildPartGeometry(part:Part):{rect:Rectangle, drawRect:Rectangle} {
var alpha = 0.6; var source = new Rectangle(part.rect.width * part.gridX, part.rect.height * part.gridY, part.rect.width, part.rect.height);
var blur = 1; var rect = source.clone();
var strength = 4; var offset = rect.width / 4 + rect.width * 0.05;
var distance = 2; rect.x -= offset;
var quality = BitmapFilterQuality.HIGH; rect.y -= offset;
var inner = true; rect.width += offset * 2;
var knockout = false; rect.height += offset * 2;
return [ var drawRect = source.clone();
new DropShadowFilter(distance, 45 + 180, 0xffffff, alpha, blur, blur, strength, quality, inner, knockout), drawRect.x = offset;
new DropShadowFilter(distance, 45, 0x000000, alpha, blur, blur, strength, quality, inner, knockout), drawRect.y = offset ;
]; return {rect:rect, drawRect:drawRect};
} }
public static function cropImagePart(source:BitmapData, part:Part):BitmapData { 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 geometry = buildPartGeometry(part);
var mask = new PartMask(rect, part.bounds); var path = builder.build(geometry.drawRect, part.bounds);
var canvas:Shape = new Shape(); var canvas:Shape = new Shape();
canvas.cacheAsBitmap = true; canvas.cacheAsBitmap = true;
canvas.mask = mask; canvas.mask = new PartMask(path);
var matrix = new Matrix(); var matrix = new Matrix();
matrix.translate(-mask.rect.x, -mask.rect.y); matrix.translate(-geometry.rect.x, -geometry.rect.y);
canvas.graphics.beginBitmapFill(source, matrix, false, true); canvas.graphics.beginBitmapFill(source, matrix, false, true);
canvas.graphics.drawRect(0, 0, mask.rect.width, mask.rect.height); canvas.graphics.drawRect(0, 0, geometry.rect.width, geometry.rect.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(geometry.rect.width), Std.int(geometry.rect.height), true, 0x00000000);
image.draw(canvas, null, null, null, null, true); image.draw(canvas, null, null, null, null, true);
/*for (filter in buildFilters()) { var shadow = 2;
image.applyFilter(image, image.rect, image.rect.topLeft, filter); var canvas2 = new Shape();
}*/ canvas2.cacheAsBitmap = true;
return image; canvas2.graphics.beginFill(0x000000, 0.4);
path.move(-shadow, -shadow).draw(canvas2.graphics);
canvas2.graphics.endFill();
canvas2.graphics.beginFill(0xffffff, 0.4);
path.move(shadow, shadow).draw(canvas2.graphics);
canvas2.graphics.endFill();
canvas2.graphics.beginBitmapFill(image, null, false, true);
canvas2.graphics.drawRect(0, 0, geometry.rect.width, geometry.rect.height);
canvas2.graphics.endFill();
var image2 = new BitmapData(image.width, image.height, true, 0x00000000);
image2.draw(canvas2, null, null, null, null, true);
return image2;
} }
public static function containRectangle(source:Rectangle, target:Rectangle):Rectangle { public static function containRectangle(source:Rectangle, target:Rectangle):Rectangle {

View File

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

View File

@@ -1,30 +0,0 @@
package ru.m.puzzlez.render.mask;
import flash.display.Shape;
import haxework.geom.Rectangle;
import ru.m.puzzlez.core.Part;
import ru.m.puzzlez.render.mask.IPartMaskBuilder;
class PartMask extends Shape {
public var rect(default, null):Rectangle;
private static var builder:IPartMaskBuilder = new ClassicMaskBuilder();
public function new(rect:Rectangle, bounds:PartBounds) {
super();
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;
var drawRect = rect.clone();
drawRect.x = offset;
drawRect.y = offset;
var drawPath = builder.build(drawRect, bounds);
graphics.beginFill(0xff00ff, 1);
graphics.drawPath(drawPath.commands, drawPath.data);
graphics.endFill();
}
}

View File

@@ -1,12 +1,12 @@
package ru.m.puzzlez.render.mask; package ru.m.puzzlez.render.part;
import flash.display.GraphicsPathCommand; import flash.display.GraphicsPathCommand;
import haxework.geom.Rectangle; import haxework.geom.Rectangle;
import openfl.Vector; import ru.m.draw.DrawPath;
import ru.m.puzzlez.core.Part; import ru.m.puzzlez.core.Part;
import ru.m.puzzlez.render.mask.IPartMaskBuilder; import ru.m.puzzlez.render.part.IPartBuilder;
class BaseMaskBuilder implements IPartMaskBuilder { class BasePartBuilder implements IPartBuilder {
public function new() { public function new() {
} }
@@ -21,10 +21,7 @@ class BaseMaskBuilder implements IPartMaskBuilder {
} }
public function build(rect:Rectangle, bounds:PartBounds):DrawPath { public function build(rect:Rectangle, bounds:PartBounds):DrawPath {
var path:DrawPath = { var path = new DrawPath();
commands: new Vector<GraphicsPathCommand>(),
data: new Vector<Float>(),
}
createAngle(path, rect.left, rect.top); createAngle(path, rect.left, rect.top);
createBound(path, rect.left, rect.top, rect.right, rect.top, bounds.top); createBound(path, rect.left, rect.top, rect.right, rect.top, bounds.top);
createAngle(path, rect.right, rect.top); createAngle(path, rect.right, rect.top);

View File

@@ -1,11 +1,11 @@
package ru.m.puzzlez.render.mask; package ru.m.puzzlez.render.part;
import flash.display.GraphicsPathCommand; import flash.display.GraphicsPathCommand;
import ru.m.draw.DrawPath;
import ru.m.puzzlez.core.BoundType; import ru.m.puzzlez.core.BoundType;
import ru.m.puzzlez.core.Part; import ru.m.puzzlez.core.Part;
import ru.m.puzzlez.render.mask.IPartMaskBuilder;
class ClassicMaskBuilder extends BaseMaskBuilder { class ClassicPartBuilder extends BasePartBuilder {
override private function createBound(path:DrawPath, fromX:Float, fromY:Float, toX:Float, toY:Float, bound:PartBound):Void { override private function createBound(path:DrawPath, fromX:Float, fromY:Float, toX:Float, toY:Float, bound:PartBound):Void {
var dx = toX == fromX ? 0 : (toX - fromX) / Math.abs(toX - fromX); var dx = toX == fromX ? 0 : (toX - fromX) / Math.abs(toX - fromX);

View File

@@ -0,0 +1,9 @@
package ru.m.puzzlez.render.part;
import haxework.geom.Rectangle;
import ru.m.draw.DrawPath;
import ru.m.puzzlez.core.Part;
interface IPartBuilder {
public function build(rect:Rectangle, bound:PartBounds):DrawPath;
}

View File

@@ -0,0 +1,14 @@
package ru.m.puzzlez.render.part;
import flash.display.Shape;
import ru.m.draw.DrawPath;
class PartMask extends Shape {
public function new(path:DrawPath) {
super();
graphics.beginFill(0xff00ff, 1);
path.draw(graphics);
graphics.endFill();
}
}

View File

@@ -1,11 +1,11 @@
package ru.m.puzzlez.render.mask; package ru.m.puzzlez.render.part;
import flash.display.GraphicsPathCommand; import flash.display.GraphicsPathCommand;
import ru.m.draw.DrawPath;
import ru.m.puzzlez.core.BoundType; import ru.m.puzzlez.core.BoundType;
import ru.m.puzzlez.core.Part; import ru.m.puzzlez.core.Part;
import ru.m.puzzlez.render.mask.IPartMaskBuilder;
class SquareMaskBuilder extends BaseMaskBuilder { class SquarePartBuilder extends BasePartBuilder {
override private function createBound(path:DrawPath, fromX:Float, fromY:Float, toX:Float, toY:Float, bound:PartBound):Void { override private function createBound(path:DrawPath, fromX:Float, fromY:Float, toX:Float, toY:Float, bound:PartBound):Void {
var dx = toX == fromX ? 0 : (toX - fromX) / Math.abs(toX - fromX); var dx = toX == fromX ? 0 : (toX - fromX) / Math.abs(toX - fromX);