From 2a17749adc4ad4ef02e4e3413b861afa69c96d33 Mon Sep 17 00:00:00 2001 From: strawberry42271 <2806566736@qq.com> Date: Mon, 23 Dec 2024 19:23:13 +0800 Subject: [PATCH 1/8] =?UTF-8?q?feat:graphics=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/render/preset/graphics.ts | 228 +++++++++++++++++++++++++---- 1 file changed, 199 insertions(+), 29 deletions(-) diff --git a/src/core/render/preset/graphics.ts b/src/core/render/preset/graphics.ts index 57f9aaa..5ddf392 100644 --- a/src/core/render/preset/graphics.ts +++ b/src/core/render/preset/graphics.ts @@ -2,6 +2,7 @@ import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d'; import { ERenderItemEvent, RenderItem } from '../item'; import { Transform } from '../transform'; import { ElementNamespace, ComponentInternalInstance } from 'vue'; +import { isNil } from 'lodash-es'; /* * Expected usage (this comment needs to be deleted after implementing correctly): @@ -54,14 +55,14 @@ export interface EGraphicItemEvent extends ERenderItemEvent {} export abstract class GraphicItemBase extends RenderItem - implements IGraphicProperty + implements Required { mode: number = GraphicMode.Fill; fill: CanvasStyle = '#fff'; stroke: CanvasStyle = '#fff'; lineWidth: number = 2; - lineDash?: number[] | undefined; - lineDashOffset?: number | undefined; + lineDash: number[] = []; + lineDashOffset: number = 0; lineJoin: CanvasLineJoin = 'bevel'; lineCap: CanvasLineCap = 'butt'; miterLimit: number = 10; @@ -71,31 +72,50 @@ export abstract class GraphicItemBase * 设置描边绘制的信息 * @param options 线的信息 */ - setLineOption(options: Partial) {} + setLineOption(options: Partial) { + if (!isNil(options.lineWidth)) this.lineWidth = options.lineWidth; + if (!isNil(options.lineDash)) this.lineDash = options.lineDash; + if (!isNil(options.lineDashOffset)) this.lineDashOffset = options.lineDashOffset; + if (!isNil(options.lineJoin)) this.lineJoin = options.lineJoin; + if (!isNil(options.lineCap)) this.lineCap = options.lineCap; + if (!isNil(options.miterLimit)) this.miterLimit = options.miterLimit; + } /** * 设置填充样式 * @param style 绘制样式 */ - setFillStyle(style: CanvasStyle) {} + setFillStyle(style: CanvasStyle) { + this.fill = style; + this.update(); + } /** * 设置描边样式 * @param style 绘制样式 */ - setStrokeStyle(style: CanvasStyle) {} + setStrokeStyle(style: CanvasStyle) { + this.stroke = style; + this.update(); + } /** * 设置填充原则 * @param rule 填充原则 */ - setFillRule(rule: CanvasFillRule) {} + setFillRule(rule: CanvasFillRule) { + this.fillRule = rule; + this.update(); + } /** * 设置绘制模式,是描边还是填充 * @param mode 绘制模式 */ - setMode(mode: GraphicMode) {} + setMode(mode: GraphicMode) { + this.mode = mode; + this.update(); + } /** * 设置画布的渲染状态,在实际渲染前调用 @@ -103,7 +123,16 @@ export abstract class GraphicItemBase */ protected setCanvasState(canvas: MotaOffscreenCanvas2D) { const ctx = canvas.ctx; - ctx.fillStyle = this.fill; // 示例,后面的都按这个写,不需要save restore,写完把这个注释删了 + ctx.fillStyle = this.fill; + ctx.strokeStyle = this.stroke; + ctx.lineWidth = this.lineWidth; + ctx.setLineDash(this.lineDash) + ctx.lineDashOffset = this.lineDashOffset; + ctx.lineJoin = this.lineJoin; + ctx.lineCap = this.lineCap; + ctx.miterLimit = this.miterLimit; + ctx.fill(this.fillRule); + this.update(); } patchProp( @@ -156,20 +185,50 @@ export class Circle extends GraphicItemBase { protected render( canvas: MotaOffscreenCanvas2D, transform: Transform - ): void {} + ): void { + const ctx = canvas.ctx; + this.setCanvasState(canvas); + ctx.beginPath(); + ctx.arc(this.x,this.y,this.radius,this.start,this.end); + + switch (this.mode) { + case GraphicMode.Fill: + ctx.fill(this.fillRule); + break; + case GraphicMode.Stroke: + ctx.stroke(); + break; + case GraphicMode.FillAndStroke: + ctx.fill(this.fillRule); + ctx.stroke(); + break; + case GraphicMode.StrokeAndFill: + ctx.stroke(); + ctx.fill(this.fillRule); + break; + } + } /** * 设置圆的半径 * @param radius 半径 */ - setRadius(radius: number) {} + setRadius(radius: number) { + this.radius = radius; + this.size(radius*2,radius*2); + this.update(); + } /** * 设置圆的起始与终止角度 * @param start 起始角度 * @param end 终止角度 */ - setAngle(start: number, end: number) {} + setAngle(start: number, end: number) { + this.start = start; + this.end = end; + this.update(); + } patchProp( key: string, @@ -193,21 +252,52 @@ export class Ellipse extends GraphicItemBase { protected render( canvas: MotaOffscreenCanvas2D, transform: Transform - ): void {} + ): void { + const ctx = canvas.ctx; + this.setCanvasState(canvas); + ctx.beginPath(); + ctx.ellipse(this.x,this.y,this.radiusX,this.radiusY,0,this.start,this.end); + + switch (this.mode) { + case GraphicMode.Fill: + ctx.fill(this.fillRule); + break; + case GraphicMode.Stroke: + ctx.stroke(); + break; + case GraphicMode.FillAndStroke: + ctx.fill(this.fillRule); + ctx.stroke(); + break; + case GraphicMode.StrokeAndFill: + ctx.stroke(); + ctx.fill(this.fillRule); + break; + } + } /** * 设置椭圆的横纵轴长度 * @param x 横轴长度 * @param y 纵轴长度 */ - setRadius(x: number, y: number) {} + setRadius(x: number, y: number) { + this.radiusX = x; + this.radiusY = y; + this.update(); + } + /** * 设置椭圆的起始与终止角度 * @param start 起始角度 * @param end 终止角度 */ - setAngle(start: number, end: number) {} + setAngle(start: number, end: number) { + this.start = start; + this.end = end; + this.update(); + } patchProp( key: string, @@ -231,17 +321,33 @@ export class Line extends GraphicItemBase { protected render( canvas: MotaOffscreenCanvas2D, transform: Transform - ): void {} + ): void { + const ctx = canvas.ctx; + this.setCanvasState(canvas); + ctx.beginPath(); + ctx.moveTo(this.x1,this.y1) + ctx.lineTo(this.x2,this.y2); + ctx.stroke(); + + } /** * 设置第一个点的横纵坐标 */ - setPoint1(x: number, y: number) {} + setPoint1(x: number, y: number) { + this.x1 = x; + this.y1 = y; + this.update(); + } /** * 设置第二个点的横纵坐标 */ - setPoint2(x: number, y: number) {} + setPoint2(x: number, y: number) { + this.x2 = x; + this.y2 = y; + this.update(); + } patchProp( key: string, @@ -269,27 +375,50 @@ export class BezierCurve extends GraphicItemBase { protected render( canvas: MotaOffscreenCanvas2D, transform: Transform - ): void {} + ): void { + const ctx = canvas.ctx; + this.setCanvasState(canvas); + ctx.beginPath(); + ctx.moveTo(this.sx,this.sy) + ctx.bezierCurveTo(this.cp1x,this.cp1y,this.cp2x,this.cp2y,this.ex,this.ey); + ctx.stroke(); + } /** * 设置起始点坐标 */ - setStart(x: number, y: number) {} + setStart(x: number, y: number) { + this.sx = x; + this.sy = y; + this.update(); + } /** * 设置控制点1坐标 */ - setControl1(x: number, y: number) {} + setControl1(x: number, y: number) { + this.cp1x = x; + this.cp1y = y; + this.update(); + } /** * 设置控制点2坐标 */ - setControl2(x: number, y: number) {} + setControl2(x: number, y: number) { + this.cp2x = x; + this.cp2y = y; + this.update(); + } /** * 设置终点坐标 */ - setEnd(x: number, y: number) {} + setEnd(x: number, y: number) { + this.ex = x; + this.ey = y; + this.update(); + } patchProp( key: string, @@ -315,22 +444,41 @@ export class QuadraticCurve extends GraphicItemBase { protected render( canvas: MotaOffscreenCanvas2D, transform: Transform - ): void {} + ): void { + const ctx = canvas.ctx; + this.setCanvasState(canvas); + ctx.beginPath(); + ctx.moveTo(this.sx,this.sy) + ctx.quadraticCurveTo(this.cpx,this.cpy,this.ex,this.ey); + ctx.stroke(); + } /** * 设置起始点坐标 */ - setStart(x: number, y: number) {} + setStart(x: number, y: number) { + this.sx = x; + this.sy = y; + this.update(); + } /** * 设置控制点坐标 */ - setControl(x: number, y: number) {} + setControl(x: number, y: number) { + this.cpx = x; + this.cpy = y; + this.update(); + } /** * 设置终点坐标 */ - setEnd(x: number, y: number) {} + setEnd(x: number, y: number) { + this.ex = x; + this.ey = y; + this.update(); + } patchProp( key: string, @@ -352,7 +500,26 @@ export class Path extends GraphicItemBase { protected render( canvas: MotaOffscreenCanvas2D, transform: Transform - ): void {} + ): void { + const ctx = canvas.ctx; + this.setCanvasState(canvas); + switch (this.mode) { + case GraphicMode.Fill: + ctx.fill(this.path,this.fillRule); + break; + case GraphicMode.Stroke: + ctx.stroke(this.path); + break; + case GraphicMode.FillAndStroke: + ctx.fill(this.path,this.fillRule); + ctx.stroke(this.path); + break; + case GraphicMode.StrokeAndFill: + ctx.stroke(this.path); + ctx.fill(this.path,this.fillRule); + break; + } + } /** * 获取当前路径 @@ -365,7 +532,10 @@ export class Path extends GraphicItemBase { * 为路径添加路径 * @param path 要添加的路径 */ - addPath(path: Path2D) {} + addPath(path: Path2D) { + this.path.addPath(path); + this.update(); + } patchProp( key: string, From 4e583fb121aa480e8d5213e748dc97a4c38eae28 Mon Sep 17 00:00:00 2001 From: strawberry42271 <2806566736@qq.com> Date: Tue, 24 Dec 2024 17:11:49 +0800 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20graphic=E7=9A=84patchProp=E5=86=99?= =?UTF-8?q?=E5=AE=8C=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/render/preset/graphics.ts | 105 +++++++++++++++++++++++++++++ src/core/render/renderer/props.ts | 44 ++++++++++-- 2 files changed, 143 insertions(+), 6 deletions(-) diff --git a/src/core/render/preset/graphics.ts b/src/core/render/preset/graphics.ts index 5ddf392..803d801 100644 --- a/src/core/render/preset/graphics.ts +++ b/src/core/render/preset/graphics.ts @@ -238,6 +238,18 @@ export class Circle extends GraphicItemBase { parentComponent?: ComponentInternalInstance | null ): void { switch (key) { + case 'radius': + if (!this.assertType(nextValue, 'number', key)) return; + this.setRadius(nextValue); + return; + case 'start': + if (!this.assertType(nextValue, 'number', key)) return; + this.setAngle(nextValue,this.end); + return; + case 'end': + if (!this.assertType(nextValue, 'number', key)) return; + this.setAngle(this.start,nextValue); + return; } super.patchProp(key, prevValue, nextValue, namespace, parentComponent); } @@ -307,6 +319,22 @@ export class Ellipse extends GraphicItemBase { parentComponent?: ComponentInternalInstance | null ): void { switch (key) { + case 'radiusX': + if (!this.assertType(nextValue, 'number', key)) return; + this.setRadius(nextValue,this.radiusY); + return; + case 'radiusY': + if (!this.assertType(nextValue, 'number', key)) return; + this.setRadius(this.radiusY,nextValue); + return; + case 'start': + if (!this.assertType(nextValue, 'number', key)) return; + this.setAngle(nextValue,this.end); + return; + case 'end': + if (!this.assertType(nextValue, 'number', key)) return; + this.setAngle(this.start,nextValue); + return; } super.patchProp(key, prevValue, nextValue, namespace, parentComponent); } @@ -357,6 +385,22 @@ export class Line extends GraphicItemBase { parentComponent?: ComponentInternalInstance | null ): void { switch (key) { + case 'x1': + if (!this.assertType(nextValue, 'number', key)) return; + this.setPoint1(nextValue,this.y1); + return; + case 'y1': + if (!this.assertType(nextValue, 'number', key)) return; + this.setPoint1(this.x1,nextValue); + return; + case 'x2': + if (!this.assertType(nextValue, 'number', key)) return; + this.setPoint2(nextValue,this.y2); + return; + case 'y2': + if (!this.assertType(nextValue, 'number', key)) return; + this.setPoint2(this.x2,nextValue); + return; } super.patchProp(key, prevValue, nextValue, namespace, parentComponent); } @@ -428,6 +472,38 @@ export class BezierCurve extends GraphicItemBase { parentComponent?: ComponentInternalInstance | null ): void { switch (key) { + case 'sx': + if (!this.assertType(nextValue, 'number', key)) return; + this.setStart(nextValue,this.sy); + return; + case 'sy': + if (!this.assertType(nextValue, 'number', key)) return; + this.setStart(this.sx,nextValue); + return; + case 'cp1x': + if (!this.assertType(nextValue, 'number', key)) return; + this.setControl1(nextValue,this.cp1y); + return; + case 'cp1y': + if (!this.assertType(nextValue, 'number', key)) return; + this.setControl1(this.cp1x,nextValue); + return; + case 'cp2x': + if (!this.assertType(nextValue, 'number', key)) return; + this.setControl2(nextValue,this.cp2y); + return; + case 'cp2y': + if (!this.assertType(nextValue, 'number', key)) return; + this.setControl2(this.cp2x,nextValue); + return; + case 'ex': + if (!this.assertType(nextValue, 'number', key)) return; + this.setEnd(nextValue,this.ey); + return; + case 'ey': + if (!this.assertType(nextValue, 'number', key)) return; + this.setEnd(this.ex,nextValue); + return; } super.patchProp(key, prevValue, nextValue, namespace, parentComponent); } @@ -488,6 +564,30 @@ export class QuadraticCurve extends GraphicItemBase { parentComponent?: ComponentInternalInstance | null ): void { switch (key) { + case 'sx': + if (!this.assertType(nextValue, 'number', key)) return; + this.setStart(nextValue,this.sy); + return; + case 'sy': + if (!this.assertType(nextValue, 'number', key)) return; + this.setStart(this.sx,nextValue); + return; + case 'cpx': + if (!this.assertType(nextValue, 'number', key)) return; + this.setControl(nextValue,this.cpy); + return; + case 'cpy': + if (!this.assertType(nextValue, 'number', key)) return; + this.setControl(this.cpx,nextValue); + return; + case 'ex': + if (!this.assertType(nextValue, 'number', key)) return; + this.setEnd(nextValue,this.ey); + return; + case 'ey': + if (!this.assertType(nextValue, 'number', key)) return; + this.setEnd(this.ex,nextValue); + return; } super.patchProp(key, prevValue, nextValue, namespace, parentComponent); } @@ -545,6 +645,11 @@ export class Path extends GraphicItemBase { parentComponent?: ComponentInternalInstance | null ): void { switch (key) { + case 'path': + if (!this.assertType(nextValue, Path2D, key)) return; + this.path = nextValue; + this.update(); + return; } super.patchProp(key, prevValue, nextValue, namespace, parentComponent); } diff --git a/src/core/render/renderer/props.ts b/src/core/render/renderer/props.ts index 61f688e..ddc9cfc 100644 --- a/src/core/render/renderer/props.ts +++ b/src/core/render/renderer/props.ts @@ -108,17 +108,49 @@ export interface GraphicPropsBase extends BaseProps, Partial { export interface RectProps extends GraphicPropsBase {} -export interface CirclesProps extends GraphicPropsBase {} +export interface CirclesProps extends GraphicPropsBase { + radius?: number; + start?: number; + end?: number; +} -export interface EllipseProps extends GraphicPropsBase {} +export interface EllipseProps extends GraphicPropsBase { + radiusX?: number; + radiusY?: number; + start?: number; + end?: number; +} -export interface LineProps extends GraphicPropsBase {} +export interface LineProps extends GraphicPropsBase { + x1?: number; + y1?: number; + x2?: number; + y2?: number; +} -export interface BezierProps extends GraphicPropsBase {} +export interface BezierProps extends GraphicPropsBase { + sx?: number; + sy?: number; + cp1x?: number; + cp1y?: number; + cp2x?: number; + cp2y?: number; + ex?: number; + ey?: number; +} -export interface QuadraticProps extends GraphicPropsBase {} +export interface QuadraticProps extends GraphicPropsBase { + sx?: number; + sy?: number; + cpx?: number; + cpy?: number; + ex?: number; + ey?: number; +} -export interface PathProps extends GraphicPropsBase {} +export interface PathProps extends GraphicPropsBase { + path?: Path2D; +} export interface IconProps extends BaseProps {} From 26600c21541a4998cfa1db49c653b098838e2e48 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Tue, 24 Dec 2024 18:18:53 +0800 Subject: [PATCH 3/8] style: graphics.ts --- src/core/render/preset/graphics.ts | 95 +++++++++++++++++------------- 1 file changed, 55 insertions(+), 40 deletions(-) diff --git a/src/core/render/preset/graphics.ts b/src/core/render/preset/graphics.ts index 803d801..3624fd9 100644 --- a/src/core/render/preset/graphics.ts +++ b/src/core/render/preset/graphics.ts @@ -75,10 +75,12 @@ export abstract class GraphicItemBase setLineOption(options: Partial) { if (!isNil(options.lineWidth)) this.lineWidth = options.lineWidth; if (!isNil(options.lineDash)) this.lineDash = options.lineDash; - if (!isNil(options.lineDashOffset)) this.lineDashOffset = options.lineDashOffset; + if (!isNil(options.lineDashOffset)) + this.lineDashOffset = options.lineDashOffset; if (!isNil(options.lineJoin)) this.lineJoin = options.lineJoin; if (!isNil(options.lineCap)) this.lineCap = options.lineCap; if (!isNil(options.miterLimit)) this.miterLimit = options.miterLimit; + this.update(); } /** @@ -126,7 +128,7 @@ export abstract class GraphicItemBase ctx.fillStyle = this.fill; ctx.strokeStyle = this.stroke; ctx.lineWidth = this.lineWidth; - ctx.setLineDash(this.lineDash) + ctx.setLineDash(this.lineDash); ctx.lineDashOffset = this.lineDashOffset; ctx.lineJoin = this.lineJoin; ctx.lineCap = this.lineCap; @@ -189,7 +191,7 @@ export class Circle extends GraphicItemBase { const ctx = canvas.ctx; this.setCanvasState(canvas); ctx.beginPath(); - ctx.arc(this.x,this.y,this.radius,this.start,this.end); + ctx.arc(this.x, this.y, this.radius, this.start, this.end); switch (this.mode) { case GraphicMode.Fill: @@ -215,7 +217,7 @@ export class Circle extends GraphicItemBase { */ setRadius(radius: number) { this.radius = radius; - this.size(radius*2,radius*2); + this.size(radius * 2, radius * 2); this.update(); } @@ -244,11 +246,11 @@ export class Circle extends GraphicItemBase { return; case 'start': if (!this.assertType(nextValue, 'number', key)) return; - this.setAngle(nextValue,this.end); + this.setAngle(nextValue, this.end); return; case 'end': if (!this.assertType(nextValue, 'number', key)) return; - this.setAngle(this.start,nextValue); + this.setAngle(this.start, nextValue); return; } super.patchProp(key, prevValue, nextValue, namespace, parentComponent); @@ -268,7 +270,15 @@ export class Ellipse extends GraphicItemBase { const ctx = canvas.ctx; this.setCanvasState(canvas); ctx.beginPath(); - ctx.ellipse(this.x,this.y,this.radiusX,this.radiusY,0,this.start,this.end); + ctx.ellipse( + this.x, + this.y, + this.radiusX, + this.radiusY, + 0, + this.start, + this.end + ); switch (this.mode) { case GraphicMode.Fill: @@ -299,7 +309,6 @@ export class Ellipse extends GraphicItemBase { this.update(); } - /** * 设置椭圆的起始与终止角度 * @param start 起始角度 @@ -321,19 +330,19 @@ export class Ellipse extends GraphicItemBase { switch (key) { case 'radiusX': if (!this.assertType(nextValue, 'number', key)) return; - this.setRadius(nextValue,this.radiusY); + this.setRadius(nextValue, this.radiusY); return; case 'radiusY': if (!this.assertType(nextValue, 'number', key)) return; - this.setRadius(this.radiusY,nextValue); + this.setRadius(this.radiusY, nextValue); return; case 'start': if (!this.assertType(nextValue, 'number', key)) return; - this.setAngle(nextValue,this.end); + this.setAngle(nextValue, this.end); return; case 'end': if (!this.assertType(nextValue, 'number', key)) return; - this.setAngle(this.start,nextValue); + this.setAngle(this.start, nextValue); return; } super.patchProp(key, prevValue, nextValue, namespace, parentComponent); @@ -353,10 +362,9 @@ export class Line extends GraphicItemBase { const ctx = canvas.ctx; this.setCanvasState(canvas); ctx.beginPath(); - ctx.moveTo(this.x1,this.y1) - ctx.lineTo(this.x2,this.y2); + ctx.moveTo(this.x1, this.y1); + ctx.lineTo(this.x2, this.y2); ctx.stroke(); - } /** @@ -387,19 +395,19 @@ export class Line extends GraphicItemBase { switch (key) { case 'x1': if (!this.assertType(nextValue, 'number', key)) return; - this.setPoint1(nextValue,this.y1); + this.setPoint1(nextValue, this.y1); return; case 'y1': if (!this.assertType(nextValue, 'number', key)) return; - this.setPoint1(this.x1,nextValue); + this.setPoint1(this.x1, nextValue); return; case 'x2': if (!this.assertType(nextValue, 'number', key)) return; - this.setPoint2(nextValue,this.y2); + this.setPoint2(nextValue, this.y2); return; case 'y2': if (!this.assertType(nextValue, 'number', key)) return; - this.setPoint2(this.x2,nextValue); + this.setPoint2(this.x2, nextValue); return; } super.patchProp(key, prevValue, nextValue, namespace, parentComponent); @@ -423,8 +431,15 @@ export class BezierCurve extends GraphicItemBase { const ctx = canvas.ctx; this.setCanvasState(canvas); ctx.beginPath(); - ctx.moveTo(this.sx,this.sy) - ctx.bezierCurveTo(this.cp1x,this.cp1y,this.cp2x,this.cp2y,this.ex,this.ey); + ctx.moveTo(this.sx, this.sy); + ctx.bezierCurveTo( + this.cp1x, + this.cp1y, + this.cp2x, + this.cp2y, + this.ex, + this.ey + ); ctx.stroke(); } @@ -474,35 +489,35 @@ export class BezierCurve extends GraphicItemBase { switch (key) { case 'sx': if (!this.assertType(nextValue, 'number', key)) return; - this.setStart(nextValue,this.sy); + this.setStart(nextValue, this.sy); return; case 'sy': if (!this.assertType(nextValue, 'number', key)) return; - this.setStart(this.sx,nextValue); + this.setStart(this.sx, nextValue); return; case 'cp1x': if (!this.assertType(nextValue, 'number', key)) return; - this.setControl1(nextValue,this.cp1y); + this.setControl1(nextValue, this.cp1y); return; case 'cp1y': if (!this.assertType(nextValue, 'number', key)) return; - this.setControl1(this.cp1x,nextValue); + this.setControl1(this.cp1x, nextValue); return; case 'cp2x': if (!this.assertType(nextValue, 'number', key)) return; - this.setControl2(nextValue,this.cp2y); + this.setControl2(nextValue, this.cp2y); return; case 'cp2y': if (!this.assertType(nextValue, 'number', key)) return; - this.setControl2(this.cp2x,nextValue); + this.setControl2(this.cp2x, nextValue); return; case 'ex': if (!this.assertType(nextValue, 'number', key)) return; - this.setEnd(nextValue,this.ey); + this.setEnd(nextValue, this.ey); return; case 'ey': if (!this.assertType(nextValue, 'number', key)) return; - this.setEnd(this.ex,nextValue); + this.setEnd(this.ex, nextValue); return; } super.patchProp(key, prevValue, nextValue, namespace, parentComponent); @@ -524,8 +539,8 @@ export class QuadraticCurve extends GraphicItemBase { const ctx = canvas.ctx; this.setCanvasState(canvas); ctx.beginPath(); - ctx.moveTo(this.sx,this.sy) - ctx.quadraticCurveTo(this.cpx,this.cpy,this.ex,this.ey); + ctx.moveTo(this.sx, this.sy); + ctx.quadraticCurveTo(this.cpx, this.cpy, this.ex, this.ey); ctx.stroke(); } @@ -566,27 +581,27 @@ export class QuadraticCurve extends GraphicItemBase { switch (key) { case 'sx': if (!this.assertType(nextValue, 'number', key)) return; - this.setStart(nextValue,this.sy); + this.setStart(nextValue, this.sy); return; case 'sy': if (!this.assertType(nextValue, 'number', key)) return; - this.setStart(this.sx,nextValue); + this.setStart(this.sx, nextValue); return; case 'cpx': if (!this.assertType(nextValue, 'number', key)) return; - this.setControl(nextValue,this.cpy); + this.setControl(nextValue, this.cpy); return; case 'cpy': if (!this.assertType(nextValue, 'number', key)) return; - this.setControl(this.cpx,nextValue); + this.setControl(this.cpx, nextValue); return; case 'ex': if (!this.assertType(nextValue, 'number', key)) return; - this.setEnd(nextValue,this.ey); + this.setEnd(nextValue, this.ey); return; case 'ey': if (!this.assertType(nextValue, 'number', key)) return; - this.setEnd(this.ex,nextValue); + this.setEnd(this.ex, nextValue); return; } super.patchProp(key, prevValue, nextValue, namespace, parentComponent); @@ -605,18 +620,18 @@ export class Path extends GraphicItemBase { this.setCanvasState(canvas); switch (this.mode) { case GraphicMode.Fill: - ctx.fill(this.path,this.fillRule); + ctx.fill(this.path, this.fillRule); break; case GraphicMode.Stroke: ctx.stroke(this.path); break; case GraphicMode.FillAndStroke: - ctx.fill(this.path,this.fillRule); + ctx.fill(this.path, this.fillRule); ctx.stroke(this.path); break; case GraphicMode.StrokeAndFill: ctx.stroke(this.path); - ctx.fill(this.path,this.fillRule); + ctx.fill(this.path, this.fillRule); break; } } From 733b6908c8d512b3efda3fb51bb92176391028cb Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Tue, 24 Dec 2024 19:55:52 +0800 Subject: [PATCH 4/8] feat: patchProp for GraphicItemBase --- src/core/render/preset/graphics.ts | 104 +++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/src/core/render/preset/graphics.ts b/src/core/render/preset/graphics.ts index 3624fd9..d75c4ef 100644 --- a/src/core/render/preset/graphics.ts +++ b/src/core/render/preset/graphics.ts @@ -51,6 +51,12 @@ export const enum GraphicMode { StrokeAndFill } +const enum GraphicModeProp { + Fill, + Stroke, + StrokeAndFill +} + export interface EGraphicItemEvent extends ERenderItemEvent {} export abstract class GraphicItemBase @@ -68,6 +74,11 @@ export abstract class GraphicItemBase miterLimit: number = 10; fillRule: CanvasFillRule = 'nonzero'; + private propFill: boolean = true; + private propStroke: boolean = false; + private strokeAndFill: boolean = false; + private propFillSet: boolean = false; + /** * 设置描边绘制的信息 * @param options 线的信息 @@ -119,6 +130,46 @@ export abstract class GraphicItemBase this.update(); } + /** + * 检查渲染模式,参考 {@link GraphicPropsBase} 中的 fill stroke strokeAndFill 属性 + */ + private checkMode(mode: GraphicModeProp, value: boolean) { + switch (mode) { + case GraphicModeProp.Fill: + this.propFill = value; + this.propFillSet = true; + break; + case GraphicModeProp.Stroke: + this.propStroke = value; + break; + case GraphicModeProp.StrokeAndFill: + this.strokeAndFill = true; + break; + } + if (this.strokeAndFill) { + this.mode = GraphicMode.StrokeAndFill; + } else { + if (!this.propFillSet) { + if (this.propStroke) { + this.mode = GraphicMode.Stroke; + } else { + this.mode = GraphicMode.Fill; + } + } else { + if (this.propFill && this.propStroke) { + this.mode = GraphicMode.FillAndStroke; + } else if (this.propFill) { + this.mode = GraphicMode.Fill; + } else if (this.propStroke) { + this.mode = GraphicMode.Stroke; + } else { + this.mode = GraphicMode.Fill; + } + } + } + this.update(); + } + /** * 设置画布的渲染状态,在实际渲染前调用 * @param canvas 要设置的画布 @@ -144,7 +195,60 @@ export abstract class GraphicItemBase namespace?: ElementNamespace, parentComponent?: ComponentInternalInstance | null ): void { + if (isNil(prevValue) && isNil(nextValue)) return; switch (key) { + case 'fill': + if (!this.assertType(nextValue, 'number', key)) return; + this.checkMode(GraphicModeProp.Fill, nextValue); + break; + case 'stroke': + if (!this.assertType(nextValue, 'number', key)) return; + this.checkMode(GraphicModeProp.Stroke, nextValue); + break; + case 'strokeAndFill': + if (!this.assertType(nextValue, 'number', key)) return; + this.checkMode(GraphicModeProp.StrokeAndFill, nextValue); + break; + case 'fillRule': + if (!this.assertType(nextValue, 'string', key)) return; + this.setFillRule(nextValue); + break; + case 'fillStyle': + this.setFillStyle(nextValue); + break; + case 'strokeStyle': + this.setStrokeStyle(nextValue); + break; + case 'lineWidth': + if (!this.assertType(nextValue, 'number', key)) return; + this.lineWidth = nextValue; + this.update(); + break; + case 'lineDash': + if (!this.assertType(nextValue, Array, key)) return; + this.lineDash = nextValue; + this.update(); + break; + case 'lineDashOffset': + if (!this.assertType(nextValue, 'number', key)) return; + this.lineDashOffset = nextValue; + this.update(); + break; + case 'lineJoin': + if (!this.assertType(nextValue, 'string', key)) return; + this.lineJoin = nextValue; + this.update(); + break; + case 'lineCap': + if (!this.assertType(nextValue, 'string', key)) return; + this.lineCap = nextValue; + this.update(); + break; + case 'miterLimit': + if (!this.assertType(nextValue, 'number', key)) return; + this.miterLimit = nextValue; + this.update(); + break; } super.patchProp(key, prevValue, nextValue, namespace, parentComponent); } From 136de3072bf948ebfccbd4b10f683fe3d3741841 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Tue, 24 Dec 2024 19:57:44 +0800 Subject: [PATCH 5/8] fix: strokeAndFill in checkMode --- src/core/render/preset/graphics.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/render/preset/graphics.ts b/src/core/render/preset/graphics.ts index d75c4ef..6e1a048 100644 --- a/src/core/render/preset/graphics.ts +++ b/src/core/render/preset/graphics.ts @@ -143,7 +143,7 @@ export abstract class GraphicItemBase this.propStroke = value; break; case GraphicModeProp.StrokeAndFill: - this.strokeAndFill = true; + this.strokeAndFill = value; break; } if (this.strokeAndFill) { From 9d48e9c09d12a25155de6de8f8dd84ba503a483d Mon Sep 17 00:00:00 2001 From: strawberry42271 <2806566736@qq.com> Date: Wed, 25 Dec 2024 17:56:59 +0800 Subject: [PATCH 6/8] =?UTF-8?q?feat:=20Icon\winskin=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/render/preset/misc.ts | 231 +++++++++++++++++++++++++++++- src/core/render/renderer/props.ts | 12 +- 2 files changed, 234 insertions(+), 9 deletions(-) diff --git a/src/core/render/preset/misc.ts b/src/core/render/preset/misc.ts index fcb3847..8b27b78 100644 --- a/src/core/render/preset/misc.ts +++ b/src/core/render/preset/misc.ts @@ -1,9 +1,18 @@ import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d'; import { Sprite } from '../sprite'; -import { ERenderItemEvent, RenderItem, RenderItemPosition } from '../item'; +import { + ERenderItemEvent, + IAnimateFrame, + renderEmits, + RenderItem, + RenderItemPosition +} from '../item'; import { Transform } from '../transform'; import { ElementNamespace, ComponentInternalInstance } from 'vue'; import { AutotileRenderable, RenderableData } from '../cache'; +import { texture } from '../cache'; +import { isNil } from 'lodash-es'; +import { logger } from '@/core/common/logger'; type CanvasStyle = string | CanvasGradient | CanvasPattern; @@ -204,7 +213,7 @@ export class Comment extends RenderItem { export interface EIconEvent extends ERenderItemEvent {} -export class Icon extends RenderItem { +export class Icon extends RenderItem implements IAnimateFrame { /** 图标id */ icon: AllNumbers = 0; /** 帧数 */ @@ -217,13 +226,69 @@ export class Icon extends RenderItem { protected render( canvas: MotaOffscreenCanvas2D, transform: Transform - ): void {} + ): void { + const ctx = canvas.ctx; + const renderable = this.renderable; + if (!renderable) return; + const [x, y, w, h] = renderable.render[0]; + const cw = canvas.width; + const ch = canvas.height; + const frame = this.animate + ? RenderItem.animatedFrame % renderable.frame + : 0; + if (this.animate) { + if (renderable.autotile) { + ctx.drawImage(renderable.image[0], x, y, w, h, 0, 0, cw, ch); + } else { + ctx.drawImage(renderable.image, x, y, w, h, 0, 0, cw, ch); + } + } else { + const [x1, y1, w1, h1] = renderable.render[frame]; + if (renderable.autotile) { + ctx.drawImage( + renderable.image[0], + x1, + y1, + w1, + h1, + 0, + 0, + cw, + ch + ); + } else { + ctx.drawImage(renderable.image, x1, y1, w1, h1, 0, 0, cw, ch); + } + this.update(this), renderEmits.addFramer(this); + } + } /** * 设置图标 * @param id 图标id */ - setIcon(id: AllIds | AllNumbers) {} + setIcon(id: AllIds | AllNumbers) { + const num = typeof id === 'number' ? id : texture.idNumberMap[id]; + const renderable = texture.getRenderable(num); + + if (!renderable) { + //todo: logger.warn() + return; + } else { + this.icon = num; + renderable.animate = 0; + this.renderable = renderable; + this.frame = renderable.frame; + } + this.update(); + } + + /** + * 更新动画帧 + */ + updateFrameAnimate(): void { + this.update(this); + } patchProp( key: string, @@ -239,10 +304,12 @@ export class Icon extends RenderItem { case 'animate': if (!this.assertType(nextValue, 'boolean', key)) return; this.animate = nextValue; + this.update(); return; case 'frame': if (!this.assertType(nextValue, 'number', key)) return; this.frame = nextValue; + this.update(); return; } super.patchProp(key, prevValue, nextValue, namespace, parentComponent); @@ -267,19 +334,162 @@ export class Winskin extends RenderItem { protected render( canvas: MotaOffscreenCanvas2D, transform: Transform - ): void {} + ): void { + const ctx = canvas.ctx; + const img = this.image; + const x = 0; + const y = 0; + const w = canvas.width; + const h = canvas.height; + const sz = this.borderSize / 32; + ctx.drawImage(img, 128, 0, 16, 16, x, y, 16 * sz, 16 * sz); + for (var dx = 0; dx < w - 64 * sz; dx += 32 * sz) { + ctx.drawImage( + img, + 144, + 0, + 32, + 16, + x + dx + 16, + y, + 32 * sz, + 16 * sz + ); + ctx.drawImage( + img, + 144, + 48, + 32, + 16, + x + dx + 16, + y + h - 16 * sz, + 32 * sz, + 16 * sz + ); + } + ctx.drawImage( + img, + 144, + 0, + w - dx - 32, + 16, + x + dx + 16 * sz, + y, + w - dx - 32 * sz, + 16 * sz + ); + ctx.drawImage( + img, + 144, + 48, + w - dx - 32, + 16, + x + dx + 16 * sz, + y + h - 16 * sz, + w - dx - 32 * sz, + 16 * sz + ); + ctx.drawImage( + img, + 176, + 0, + 16, + 16, + x + w - 16 * sz, + y, + 16 * sz, + 16 * sz + ); + // 左右 + for (var dy = 0; dy < h - 64 * sz; dy += 32 * sz) { + ctx.drawImage( + img, + 128, + 16, + 16, + 32, + x, + y + dy + 16 * sz, + 16 * sz, + 32 * sz + ); + ctx.drawImage( + img, + 176, + 16, + 16, + 32, + x + w - 16 * sz, + y + dy + 16 * sz, + 16 * sz, + 32 * sz + ); + } + ctx.drawImage( + img, + 128, + 16, + 16, + h - dy - 32, + x, + y + dy + 16 * sz, + 16 * sz, + h - dy - 32 * sz + ); + ctx.drawImage( + img, + 176, + 16, + 16, + h - dy - 32, + x + w - 16 * sz, + y + dy + 16 * sz, + 16 * sz, + h - dy - 32 * sz + ); + // 下方 + ctx.drawImage( + img, + 128, + 48, + 16, + 16, + x, + y + h - 16 * sz, + 16 * sz, + 16 * sz + ); + ctx.drawImage( + img, + 176, + 48, + 16, + 16, + x + w - 16 * sz, + y + h - 16 * sz, + 16 * sz, + 16 * sz + ); + this.update(); + } /** * 设置winskin图片 * @param image winskin图片 */ - setImage(image: SizedCanvasImageSource) {} + setImage(image: SizedCanvasImageSource) { + this.image = image; + this.update(); + } /** * 设置边框大小 * @param size 边框大小 */ - setBorderSize(size: number) {} + setBorderSize(size: number) { + this.borderSize = size; + this.update(); + } patchProp( key: string, @@ -289,6 +499,13 @@ export class Winskin extends RenderItem { parentComponent?: ComponentInternalInstance | null ): void { switch (key) { + case 'image': + this.setImage(nextValue); + return; + case 'borderSize': + if (!this.assertType(nextValue, 'number', key)) return; + this.setBorderSize(nextValue); + return; } super.patchProp(key, prevValue, nextValue, namespace, parentComponent); } diff --git a/src/core/render/renderer/props.ts b/src/core/render/renderer/props.ts index ddc9cfc..71a55dc 100644 --- a/src/core/render/renderer/props.ts +++ b/src/core/render/renderer/props.ts @@ -7,6 +7,7 @@ import { } from '../preset/layer'; import type { EnemyCollection } from '@/game/enemy/damage'; import { ILineProperty } from '../preset/graphics'; +import { SizedCanvasImageSource } from '../preset'; export interface CustomProps { _item: (props: BaseProps) => RenderItem; @@ -152,6 +153,13 @@ export interface PathProps extends GraphicPropsBase { path?: Path2D; } -export interface IconProps extends BaseProps {} +export interface IconProps extends BaseProps { + icon: AllNumbers; + frame: number; + animate: boolean; +} -export interface WinskinProps extends BaseProps {} +export interface WinskinProps extends BaseProps { + image: SizedCanvasImageSource; + borderSize: number; +} From 3057d740b68a0528566948984238195c1f9fe5ef Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Thu, 26 Dec 2024 18:16:59 +0800 Subject: [PATCH 7/8] =?UTF-8?q?feat:=20=E5=9C=86=E8=A7=92=E7=9F=A9?= =?UTF-8?q?=E5=BD=A2=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/render/preset/graphics.ts | 102 +++++++++++++++++++++++++- src/core/render/renderer/elements.tsx | 2 + src/core/render/renderer/map.ts | 4 +- src/core/render/renderer/props.ts | 23 ++++++ 4 files changed, 129 insertions(+), 2 deletions(-) diff --git a/src/core/render/preset/graphics.ts b/src/core/render/preset/graphics.ts index 6e1a048..56dc874 100644 --- a/src/core/render/preset/graphics.ts +++ b/src/core/render/preset/graphics.ts @@ -1,5 +1,5 @@ import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d'; -import { ERenderItemEvent, RenderItem } from '../item'; +import { ERenderItemEvent, RenderItem, RenderItemPosition } from '../item'; import { Transform } from '../transform'; import { ElementNamespace, ComponentInternalInstance } from 'vue'; import { isNil } from 'lodash-es'; @@ -773,3 +773,103 @@ export class Path extends GraphicItemBase { super.patchProp(key, prevValue, nextValue, namespace, parentComponent); } } + +const enum RectRType { + /** 圆角为椭圆 */ + Ellipse, + /** 圆角为二次贝塞尔曲线 */ + Quad, + /** 圆角为三次贝塞尔曲线。该模式下,包含两个控制点,一个控制点位于上下矩形边延长线,另一个控制点位于左右矩形边延长线 */ + Cubic, + /** 圆角为直线连接 */ + Line +} + +export class RectR extends GraphicItemBase { + /** 矩形路径 */ + private path: Path2D; + + /** 圆角类型 */ + roundType: RectRType = RectRType.Ellipse; + /** 横向圆角半径 */ + radiusX: number = 0; + /** 纵向圆角半径 */ + radiusY: number = 0; + /** + * 二次贝塞尔曲线下,表示控制点的横向比例,控制点在上下矩形边与圆角的交界处为0,在左右矩形边与圆角的交界处延长线为1 + * 三次贝塞尔曲线下,表示在上下矩形边延长线上的控制点的比例 + */ + cpx: number = 0; + /** + * 二次贝塞尔曲线下,表示控制点的纵向比例,控制点在左右矩形边与圆角的交界处为0,在上下矩形边与圆角的交界处延长线为1 + * 三次贝塞尔曲线下,表示在左右矩形边延长线上的控制点的比例 + */ + cpy: number = 0; + + constructor( + type: RenderItemPosition, + cache: boolean = false, + fall: boolean = false + ) { + super(type, cache, fall); + + const path = new Path2D(); + path.rect(this.x, this.y, this.width, this.height); + this.path = path; + } + + /** + * 更新路径 + */ + private updatePath() {} + + /** + * 设置圆角半径 + * @param x 横向半径 + * @param y 纵向半径 + */ + setRadius(x: number, y: number) {} + + /** + * 设置贝塞尔曲线模式下的控制点 + * @param x cpx + * @param y cpy + */ + setControl(x: number, y: number) {} + + protected render( + canvas: MotaOffscreenCanvas2D, + transform: Transform + ): void { + const ctx = canvas.ctx; + this.setCanvasState(canvas); + switch (this.mode) { + case GraphicMode.Fill: + ctx.fill(this.path, this.fillRule); + break; + case GraphicMode.Stroke: + ctx.stroke(this.path); + break; + case GraphicMode.FillAndStroke: + ctx.fill(this.path, this.fillRule); + ctx.stroke(this.path); + break; + case GraphicMode.StrokeAndFill: + ctx.stroke(this.path); + ctx.fill(this.path, this.fillRule); + break; + } + } + + patchProp( + key: string, + prevValue: any, + nextValue: any, + namespace?: ElementNamespace, + parentComponent?: ComponentInternalInstance | null + ): void { + switch (key) { + } + super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + } +} diff --git a/src/core/render/renderer/elements.tsx b/src/core/render/renderer/elements.tsx index 2d08c29..4b9e1cc 100644 --- a/src/core/render/renderer/elements.tsx +++ b/src/core/render/renderer/elements.tsx @@ -26,6 +26,7 @@ import { PathProps, QuadraticProps, RectProps, + RectRProps, ShaderProps, SpriteProps, TextProps, @@ -101,6 +102,7 @@ declare module 'vue/jsx-runtime' { 'g-bezier': TagDefine; 'g-quad': TagDefine; 'g-path': TagDefine; + 'g-rectr': TagDefine; icon: TagDefine; winskin: TagDefine; } diff --git a/src/core/render/renderer/map.ts b/src/core/render/renderer/map.ts index b3b76b2..c67dee3 100644 --- a/src/core/render/renderer/map.ts +++ b/src/core/render/renderer/map.ts @@ -14,7 +14,8 @@ import { Line, Path, QuadraticCurve, - Rect + Rect, + RectR } from '../preset/graphics'; import { BaseProps } from './props'; @@ -189,6 +190,7 @@ tagMap.register('g-line', standardElementNoCache(Line)); tagMap.register('g-bezier', standardElementNoCache(BezierCurve)); tagMap.register('g-quad', standardElementNoCache(QuadraticCurve)); tagMap.register('g-path', standardElementNoCache(Path)); +tagMap.register('g-rectr', standardElementNoCache(RectR)); tagMap.register('icon', standardElementNoCache(Icon)); tagMap.register('winskin', (_0, _1, props) => { if (!props) return new Winskin(core.material.images.images['winskin.png']); diff --git a/src/core/render/renderer/props.ts b/src/core/render/renderer/props.ts index 71a55dc..10bf408 100644 --- a/src/core/render/renderer/props.ts +++ b/src/core/render/renderer/props.ts @@ -153,6 +153,29 @@ export interface PathProps extends GraphicPropsBase { path?: Path2D; } +export interface RectRProps extends GraphicPropsBase { + /** 圆角半径,此参数传入时,radiusX 和 radiusY 应保持一致 */ + radius: number; + /** 圆角横向半径 */ + radiusX?: number; + /** 圆角纵向半径 */ + radiusY?: number; + /** 圆角为线模式 */ + line?: boolean; + /** 圆角为椭圆模式,默认值 */ + ellipse?: boolean; + /** 圆角为二次贝塞尔曲线模式 */ + quad?: boolean; + /** 圆角为三次贝塞尔曲线模式 */ + cubic?: boolean; + /** 控制点,此参数传入时,cpx 和 cpy 应保持一致 */ + cp?: number; + /** 横向控制点 */ + cpx?: number; + /** 纵向控制点 */ + cpy?: number; +} + export interface IconProps extends BaseProps { icon: AllNumbers; frame: number; From b48dfae2112e482943059d3b7ff168b593ede3b0 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Sat, 28 Dec 2024 16:46:22 +0800 Subject: [PATCH 8/8] =?UTF-8?q?fix:=20graphic=E5=85=83=E7=B4=A0=E9=94=99?= =?UTF-8?q?=E4=BD=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/render/renderer/map.ts | 64 ++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/src/core/render/renderer/map.ts b/src/core/render/renderer/map.ts index c67dee3..81ac6b2 100644 --- a/src/core/render/renderer/map.ts +++ b/src/core/render/renderer/map.ts @@ -4,7 +4,14 @@ import { ElementNamespace, VNodeProps } from 'vue'; import { Container } from '../container'; import { MotaRenderer } from '../render'; import { Sprite } from '../sprite'; -import { Comment, Icon, Image, Text, Winskin } from '../preset/misc'; +import { + Comment, + ETextEvent, + Icon, + Image, + Text, + Winskin +} from '../preset/misc'; import { Shader } from '../shader'; import { Animate, Damage, EDamageEvent, Layer, LayerGroup } from '../preset'; import { @@ -14,8 +21,7 @@ import { Line, Path, QuadraticCurve, - Rect, - RectR + Rect } from '../preset/graphics'; import { BaseProps } from './props'; @@ -91,6 +97,40 @@ const standardElementNoCache = ( }; }; +const enum ElementState { + None = 0, + Cache = 1, + Fall = 2 +} + +/** + * standardElementFor + */ +const se = ( + Item: new ( + type: RenderItemPosition, + cache?: boolean, + fall?: boolean + ) => RenderItem, + position: RenderItemPosition, + state: ElementState +) => { + const defaultCache = !!(state & ElementState.Cache); + const defautFall = !!(state & ElementState.Fall); + + return (_0: any, _1: any, props?: any) => { + if (!props) return new Item('absolute'); + else { + const { + type = position, + cache = defaultCache, + fall = defautFall + } = props; + return new Item(type, cache, fall); + } + }; +}; + // Default elements tagMap.register('container', standardElement(Container)); tagMap.register('template', standardElement(Container)); @@ -98,7 +138,7 @@ tagMap.register('mota-renderer', (_0, _1, props) => { return new MotaRenderer(props?.id); }); tagMap.register('sprite', standardElement(Sprite)); -tagMap.register('text', (_0, _1, props) => { +tagMap.register('text', (_0, _1, props) => { if (!props) return new Text(); else { const { type = 'static', text = '' } = props; @@ -183,14 +223,14 @@ tagMap.register('damage', (_0, _1, props) => { tagMap.register('animation', (_0, _1, props) => { return new Animate(); }); -tagMap.register('g-rect', standardElementNoCache(Rect)); -tagMap.register('g-circle', standardElementNoCache(Circle)); -tagMap.register('g-ellipse', standardElementNoCache(Ellipse)); -tagMap.register('g-line', standardElementNoCache(Line)); -tagMap.register('g-bezier', standardElementNoCache(BezierCurve)); -tagMap.register('g-quad', standardElementNoCache(QuadraticCurve)); -tagMap.register('g-path', standardElementNoCache(Path)); -tagMap.register('g-rectr', standardElementNoCache(RectR)); +tagMap.register('g-rect', se(Rect, 'absolute', ElementState.None)); +tagMap.register('g-circle', se(Circle, 'absolute', ElementState.None)); +tagMap.register('g-ellipse', se(Ellipse, 'absolute', ElementState.None)); +tagMap.register('g-line', se(Line, 'absolute', ElementState.None)); +tagMap.register('g-bezier', se(BezierCurve, 'absolute', ElementState.None)); +tagMap.register('g-quad', se(QuadraticCurve, 'absolute', ElementState.None)); +tagMap.register('g-path', se(Path, 'absolute', ElementState.None)); +tagMap.register('g-rectr', se(Path, 'absolute', ElementState.None)); tagMap.register('icon', standardElementNoCache(Icon)); tagMap.register('winskin', (_0, _1, props) => { if (!props) return new Winskin(core.material.images.images['winskin.png']);