@sepveneto/dao 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dao.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dao.cjs","names":["child: Container","uidCache: Record<string, number>","EventEmitter","EventEmitter","effectMixin: Partial<Container>","sortMixin: Partial<Container>","measureMixin: Partial<Container>","childrenHelperMixin: ChildrenHelperMixin<ContainerChild>","removed: Container[]","oldChildren: ContainerChild[]","fontFamilies: string | string[]","width: number","height: number","keys: string[]","aliasesToUse: string[]","assets: Record<string, Texture>","src: any","out: Record<string, Texture>"],"sources":["../lib/maths/Matrix.ts","../lib/maths/shapes/Rectangle.ts","../lib/maths/index.ts","../lib/events/FederatedEvent.ts","../lib/system/EventSystem.ts","../lib/scene/container/utils.ts","../lib/renderer/InstructionSet.ts","../lib/scene/container/RenderGroup.ts","../lib/utils/uid.ts","../lib/utils/index.ts","../lib/maths/Point.ts","../lib/maths/const.ts","../node_modules/.pnpm/eventemitter3@5.0.4/node_modules/eventemitter3/index.js","../node_modules/.pnpm/eventemitter3@5.0.4/node_modules/eventemitter3/index.mjs","../lib/maths/Bounds.ts","../lib/scene/mask/StencilMask.ts","../lib/scene/container/mixins/effectMixin.ts","../lib/scene/container/mixins/sortMixin.ts","../lib/scene/container/mixins/measureMixin.ts","../lib/scene/container/mixins/childrenHelperMixin.ts","../lib/scene/container/Container.ts","../lib/scene/container/utils/updateRenderGroupTransform.ts","../lib/scene/container/utils/validateRenderables.ts","../lib/system/RenderGroupSystem.ts","../lib/scene/sprite/SpritePipe.ts","../lib/scene/text/TextPipe.ts","../lib/scene/ViewContainer.ts","../lib/maths/shapes/Polygon.ts","../lib/scene/graphics/path/buildAdaptiveBezier.ts","../lib/scene/graphics/path/ShapePath.ts","../lib/scene/graphics/path/GraphicsPath.ts","../lib/scene/graphics/GraphicsContext.ts","../lib/scene/graphics/Graphics.ts","../lib/scene/graphics/GraphicsPipe.ts","../lib/scene/batcher/BatcherPipe.ts","../lib/scene/batcher/Batcher.ts","../lib/renderer/CanvasPool.ts","../lib/scene/text/TextStyle.ts","../lib/scene/text/utils.ts","../lib/renderer/texture/TextureSource.ts","../lib/renderer/texture/Texture.ts","../lib/scene/text/TextSystem.ts","../lib/scene/mask/StencilMaskPipe.ts","../lib/renderer/texture/RenderTexture.ts","../lib/scene/sprite/Sprite.ts","../lib/scene/text/Text.ts","../lib/system/ExtractSystem.ts","../lib/system/CanvasContextSystem.ts","../lib/system/ViewSystem.ts","../lib/renderer/index.ts","../lib/ticker/TickerListener.ts","../lib/ticker/Ticker.ts","../lib/app/ResizePlugin.ts","../lib/app/Application.ts","../lib/assets/cache/Cache.ts","../lib/assets/loader/Loader.ts","../lib/assets/Assets.ts"],"sourcesContent":["import { Vector2 } from \".\"\n/**\n * Two Pi.\n * @type {number}\n * @category maths\n * @standard\n */\nexport const PI_2 = Math.PI * 2;\n\n/**\n * The data structure that contains the position, scale, pivot, skew and rotation of an object.\n * This is used by the {@link Matrix} class to decompose the matrix into its components.\n * @category maths\n * @advanced\n */\n\n/**\n * The data structure that contains the position, scale, pivot, skew and rotation of an object.\n * This is used by the {@link Matrix} class to decompose the matrix into its components.\n * @category maths\n * @advanced\n */\nexport interface TransformableObject {\n /** The position of the object */\n position: Vector2;\n /** The scale of the object */\n scale: Vector2;\n /** The skew of the object */\n skew: Vector2;\n /** The rotation of the object */\n rotation: number;\n pivot: Vector2\n}\n\nexport class Matrix {\n public a: number\n public b: number\n public c: number\n public d: number\n public tx: number\n public ty: number\n constructor(a = 1, b = 0, c = 0, d = 1, tx = 0, ty = 0) {\n this.a = a\n this.b = b\n this.c = c\n this.d = d\n this.tx = tx\n this.ty = ty\n }\n\n /**\n * A * B\n */\n static append(A: Matrix, B: Matrix) {\n const a = B.a * A.a + B.b * A.c\n const b = B.a * A.b + B.b * A.d\n const c = B.c * A.a + B.d * A.c\n const d = B.c * A.b + B.d * A.d\n const tx = B.tx * A.a + B.ty * A.c + A.tx\n const ty = B.tx * A.b + B.ty * A.d + A.ty\n\n return new Matrix(a, b, c, d, tx, ty)\n }\n\n apply(pos: Vector2) {\n const { x, y } = pos\n\n const newPos = new Vector2(\n x * this.a + y * this.c + this.tx,\n x * this.b + y * this.d + this.ty\n )\n\n return newPos\n }\n\n appendFrom(a: Matrix, b: Matrix) {\n const a1 = a.a\n const b1 = a.b\n const c1 = a.c\n const d1 = a.d\n const tx1 = a.tx\n const ty1 = a.ty\n\n const a2 = b.a\n const b2 = b.b\n const c2 = b.c\n const d2 = b.d\n const tx2 = b.tx\n const ty2 = b.ty\n\n this.a = (a1 * a2) + (b1 * c2)\n this.b = (a1 * b2) + (b1 * d2)\n this.c = (c1 * a2) + (d1 * c2)\n this.d = (c1 * b2) + (d1 * d2)\n this.tx = (tx1 * a2) + (ty1 * c2) + tx2\n this.ty = (tx1 * b2) + (ty1 * d2) + ty2\n }\n\n set(a: number, b: number, c: number, d: number, tx: number, ty: number) {\n this.a = a\n this.b = b\n this.c = c\n this.d = d\n this.tx = tx\n this.ty = ty\n }\n\n applyInverse(pos: Vector2, newPos?: Vector2) {\n newPos = newPos || new Vector2()\n\n const a = this.a\n const b = this.b\n const c = this.c\n const d = this.d\n const tx = this.tx\n const ty = this.ty\n\n const id = 1 / ((a * d) + (c * -b))\n\n const x = pos.x\n const y = pos.y\n\n newPos.x = (d * id * x) + (-c * id * y) + (((ty * c) - (tx * d)) * id);\n newPos.y = (a * id * y) + (-b * id * x) + (((-ty * a) + (tx * b)) * id);\n\n return newPos\n }\n\n copyFrom(matrix: Matrix): this {\n this.a = matrix.a;\n this.b = matrix.b;\n this.c = matrix.c;\n this.d = matrix.d;\n this.tx = matrix.tx;\n this.ty = matrix.ty;\n\n return this;\n }\n\n /**\n * Decomposes the matrix into its individual transform components.\n * Extracts position, scale, rotation and skew values from the matrix.\n * @example\n * ```ts\n * // Basic decomposition\n * const matrix = new Matrix()\n * .translate(100, 100)\n * .rotate(Math.PI / 4)\n * .scale(2, 2);\n *\n * const transform = {\n * position: new Point(),\n * scale: new Point(),\n * pivot: new Point(),\n * skew: new Point(),\n * rotation: 0\n * };\n *\n * matrix.decompose(transform);\n * console.log(transform.position); // Point(100, 100)\n * console.log(transform.rotation); // ~0.785 (PI/4)\n * console.log(transform.scale); // Point(2, 2)\n * ```\n * @remarks\n * - Handles combined transformations\n * - Accounts for pivot points\n * - Chooses between rotation/skew based on transform type\n * - Uses radians for rotation and skew\n * @param transform - The transform object to store the decomposed values\n * @returns The transform with the newly applied properties\n * @see {@link Matrix.setTransform} For composing from components\n * @see {@link TransformableObject} For transform structure\n */\n public decompose(transform: TransformableObject): TransformableObject {\n // sort out rotation / skew..\n const a = this.a;\n const b = this.b;\n const c = this.c;\n const d = this.d;\n const pivot = transform.pivot\n\n const skewX = -Math.atan2(-c, d);\n const skewY = Math.atan2(b, a);\n\n const delta = Math.abs(skewX + skewY);\n\n if (delta < 0.00001 || Math.abs(PI_2 - delta) < 0.00001) {\n transform.rotation = skewY;\n transform.skew.x = transform.skew.y = 0;\n }\n else {\n transform.rotation = 0;\n transform.skew.x = skewX;\n transform.skew.y = skewY;\n }\n\n // next set scale\n transform.scale.x = Math.sqrt((a * a) + (b * b));\n transform.scale.y = Math.sqrt((c * c) + (d * d));\n\n // next set position\n transform.position.x = this.tx + (pivot.x * a) + pivot.y * c;\n transform.position.y = this.ty + pivot.x * b + (pivot.y * d);\n\n return transform;\n }\n\n clone() {\n const matrix = new Matrix();\n\n matrix.a = this.a;\n matrix.b = this.b;\n matrix.c = this.c;\n matrix.d = this.d;\n matrix.tx = this.tx;\n matrix.ty = this.ty;\n\n return matrix;\n\n }\n}","export class Rectangle {\n public x: number\n public y: number\n public width: number\n public height: number\n\n public readonly type = 'rectangle'\n\n constructor(x = 0, y = 0, width = 0, height = 0) {\n this.x = x\n this.y = y\n this.width = width\n this.height = height\n }\n\n public getBounds() {\n const out = new Rectangle()\n out.copyFrom(this)\n return out\n }\n\n public copyFrom(rectangle: Rectangle): Rectangle\n {\n this.x = rectangle.x;\n this.y = rectangle.y;\n this.width = rectangle.width;\n this.height = rectangle.height;\n\n return this;\n }\n\n public contains(x: number, y: number) {\n if (this.width <= 0 || this.height <= 0) {\n return false\n }\n\n if (x >= this.x && x < this.x + this.width) {\n if (y >= this.y && y < this.y + this.height) {\n return true\n }\n }\n return false\n }\n}","export class Vector2 {\n public x: number\n public y: number\n constructor(x = 0, y = 0) {\n this.x = x\n this.y = y\n }\n\n set(xora: number, y?: number) {\n if (y == null) {\n this.x = this.y = xora\n } else {\n this.x = xora\n this.y = y\n }\n }\n\n copyFrom(data: Vector2) {\n this.set(data.x, data.y)\n }\n}\n\nexport * from './Matrix'\nexport * from './shapes/Rectangle'\n\n/**\n * Rounds to next power of two.\n * @function nextPow2\n * @param {number} v - input value\n * @returns {number} - next rounded power of two\n * @category maths\n * @advanced\n */\nexport function nextPow2(v: number): number\n{\n v += v === 0 ? 1 : 0;\n --v;\n v |= v >>> 1;\n v |= v >>> 2;\n v |= v >>> 4;\n v |= v >>> 8;\n v |= v >>> 16;\n\n return v + 1;\n}\n","import { Vector2 } from \"@/maths\";\nimport { Container } from \"@/scene\";\nimport { EventSystem } from \"@/system\";\n\nexport class FederatedEvent {\n public readonly system: EventSystem\n public target: Container \n public currentTarget: Container\n public nativeEvent: PointerEvent\n public global: Vector2\n public type: string\n\n public path: Container[]\n\n constructor(system: EventSystem) {\n this.system = system\n }\n\n getLocalPosition(container: Container, points?: Vector2) {\n return container.worldTransform.applyInverse(points || this.global)\n }\n\n composedPath(): Container[] {\n if (!this.path || this.path[this.path.length - 1] !== this.target) {\n this.path = this.target ? this.system.propagationPath(this.target) : []\n }\n\n return this.path\n }\n}\n","import { Container } from \"@/scene/container/Container\"\nimport { ViewContainer } from \"@/scene/ViewContainer\"\nimport { CanvasRenderer } from \"../renderer\"\nimport { Vector2 } from \"../maths\"\nimport { FederatedEventMap } from \"@/events/FederatedEventMap\"\nimport { FederatedEvent } from \"@/events/FederatedEvent\"\n\nconst PROPAGATION_LIMIT = 2048\n\nexport type EventMode = 'none' | 'static' | 'passive'\ntype EmitterListener = { fn(...args: any[]): any, context: any, once: boolean };\nexport type EmitterListeners = Record<string, EmitterListener | EmitterListener[]>;\n\nexport class EventSystem {\n public renderer: CanvasRenderer\n public domElement: HTMLElement = null\n public rootTarget: Container = null\n public resolution = 1\n\n private readonly _allInteractiveElements: Container[] = []\n private _hitElements: Container[] = []\n\n // private readonly _rootPointerEvent: FederatedEvent\n\n private _isPointerMoveEvent = false\n\n private mappingState: Record<string, any> = {\n trackingData: {}\n }\n\n static desc = {\n name: 'events'\n } as const\n\n\n constructor(renderer: CanvasRenderer) {\n this.renderer = renderer\n this.resolution = renderer.resolution\n\n // this._rootPointerEvent = new FederatedEvent(null)\n\n this._onPointerDown = this._onPointerDown.bind(this)\n this._onPointerMove = this._onPointerMove.bind(this)\n this._onPointerUp = this._onPointerUp.bind(this)\n this._onPointerOverOut = this._onPointerOverOut.bind(this)\n\n this.init()\n }\n\n /**\n * \n * @param id pointerId\n */\n private trackingData(id: number) {\n if (!this.mappingState.trackingData[id]) {\n this.mappingState.trackingData[id] = {\n pressTargetsByButton: {},\n clicksByButton: {},\n overTargets: null,\n }\n }\n\n return this.mappingState.trackingData[id]\n }\n\n init() {\n const canvas = this.renderer.canvas\n this.setTargetElement(canvas)\n }\n\n\n setTargetElement(element: HTMLElement) {\n this._removeEvents()\n this.domElement = element\n this._addEvents()\n }\n\n dispatchEvent(e: FederatedEvent, type: keyof FederatedEventMap) {\n if (!e.target) return\n\n const composedPath = e.composedPath()\n\n for (let i = 0; i < composedPath.length - 1; ++i) {\n e.currentTarget = composedPath[i]\n\n this._notifyTarget(e, type)\n\n // TODO: stopPropagation\n }\n\n e.currentTarget = e.target\n\n this._notifyTarget(e, type)\n }\n\n private _notifyTarget(e: FederatedEvent, type?: string) {\n\n type ??= e.type\n\n const listeners = ((e.currentTarget as any)._events as EmitterListeners)[type]\n if (!listeners) return\n\n if ('fn' in listeners) {\n if (listeners.once) {\n // @ts-expect-error: ignore\n e.target.removeListener(type, listeners.fn, undefined, true)\n }\n listeners.fn.call(listeners.context, e)\n } else {\n for (let i = 0; i < listeners.length; ++i) {\n const listener = listeners[i]\n if (listener.once) {\n // @ts-expect-error: ignore\n e.target.removeListener(type, listener.fn, undefined, true)\n }\n listener.fn.call(listener.context, e)\n }\n }\n }\n\n public propagationPath(target: Container) {\n const propagationPath = [target]\n\n for (let i = 0; i < PROPAGATION_LIMIT && (target !== this.rootTarget || target.parent); ++i) {\n if (!target.parent) {\n throw new Error('Cannot find propagation path to disconnected target')\n }\n\n propagationPath.push(target.parent)\n\n target = target.parent\n }\n propagationPath.reverse()\n\n return propagationPath\n }\n\n _removeEvents() {\n const canvas = this.domElement\n if (!canvas) return\n\n globalThis.document.removeEventListener('pointermove', this._onPointerMove, true)\n canvas.removeEventListener('pointerdown', this._onPointerDown, true)\n canvas.removeEventListener('pointerleave', this._onPointerOverOut, true)\n canvas.removeEventListener('pointerover', this._onPointerOverOut, true)\n globalThis.document.removeEventListener('pointerup', this._onPointerUp, true)\n }\n\n _addEvents() {\n const canvas = this.domElement\n if (!canvas) {\n return\n }\n\n const style = canvas.style as CSSStyleDeclaration\n if (style) {\n style.touchAction = 'none'\n }\n\n\n globalThis.document.addEventListener('pointermove', this._onPointerMove, true)\n canvas.addEventListener('pointerdown', this._onPointerDown, true)\n canvas.addEventListener('pointerleave', this._onPointerOverOut, true)\n canvas.addEventListener('pointerover', this._onPointerOverOut, true)\n globalThis.document.addEventListener('pointerup', this._onPointerUp, true)\n }\n\n _onPointerMove(event: PointerEvent) {\n this.rootTarget = this.renderer.renderedObject\n if (!this.rootTarget) return\n\n this._isPointerMoveEvent = true\n this._allInteractiveElements.length = 0\n this._hitElements.length = 0\n const evt = this.createPointEvent(event)\n\n this._isPointerMoveEvent = false\n const trackingData = this.trackingData(event.pointerId)\n const outTarget = findMountedTarget(trackingData.overTargets)\n\n if (trackingData.overTargets?.length > 0 && outTarget !== evt.target) {\n const outType = 'pointerout'\n const outEvent = this.createPointEvent(event, outType, outTarget)\n\n this.dispatchEvent(outEvent, 'pointerout')\n\n const composedPath = evt.composedPath()\n if (!composedPath.includes(outTarget)) {\n const leaveEvent = this.createPointEvent(event, 'pointerleave', outTarget)\n\n while (leaveEvent.target && !composedPath.includes(leaveEvent.target)) {\n leaveEvent.currentTarget = leaveEvent.target\n\n this._notifyTarget(leaveEvent)\n\n leaveEvent.target = leaveEvent.target.parent\n }\n }\n }\n\n if (outTarget !== evt.target) {\n const overType = 'pointerover'\n // TODO: clone\n const overEvent = this.clonePointEvent(evt, overType)\n\n this.dispatchEvent(overEvent, overType)\n\n let overTargetAncestor = outTarget?.parent\n\n while (overTargetAncestor && overTargetAncestor !== this.rootTarget.parent) {\n if (overTargetAncestor === evt.target) break\n\n overTargetAncestor = overTargetAncestor.parent\n }\n\n const didPointerEnter = !overTargetAncestor || overTargetAncestor === this.rootTarget.parent\n\n if (didPointerEnter) {\n const enterEvent = this.clonePointEvent(evt, 'pointerenter')\n\n while (enterEvent.target && enterEvent.target !== outTarget && enterEvent.target !== this.rootTarget.parent) {\n enterEvent.currentTarget = enterEvent.target\n\n this._notifyTarget(enterEvent)\n\n enterEvent.target = enterEvent.target.parent\n }\n }\n }\n\n this.dispatchEvent(evt, 'pointermove')\n\n const targets = this._allInteractiveElements\n for (let i = targets.length - 1; i >= 0; --i) {\n evt.currentTarget = targets[i]\n this._notifyTarget(evt, 'globalpointermove')\n }\n\n this._allInteractiveElements.length = 0\n this._hitElements.length = 0\n\n trackingData.overTargets = evt.composedPath()\n }\n\n _onPointerDown(event: PointerEvent) {\n this.rootTarget = this.renderer.renderedObject\n if (!this.rootTarget) return\n\n const evt = this.createPointEvent(event)\n this.dispatchEvent(evt, 'pointerdown')\n\n const trackingData = this.trackingData(event.pointerId)\n trackingData.pressTargetsByButton[event.button] = evt.composedPath()\n }\n\n _onPointerOverOut(event: PointerEvent) {\n this.rootTarget = this.renderer.renderedObject\n if (!this.rootTarget) return\n\n const evt = this.createPointEvent(event)\n this.dispatchEvent(evt, 'pointerout')\n }\n\n _onPointerUp(event: PointerEvent) {\n this.rootTarget = this.renderer.renderedObject\n if (!this.rootTarget) return\n\n let target = event.target\n\n // if in shadow DOM use composedPath to access target\n if (event.composedPath && event.composedPath().length > 1) {\n target = event.composedPath()[0]\n }\n\n const outside = target !== this.domElement ? 'outside' : ''\n const evt = this.createPointEvent(event)\n this.dispatchEvent(evt, `pointerup${outside}`)\n }\n\n _isInteractive(eventMode: EventMode) {\n return eventMode === 'static'\n }\n\n createPointEvent(from: PointerEvent, type?: string, target?: Container): FederatedEvent {\n const gp = this.mapPositionToPoint(from.clientX, from.clientY)\n\n if (from.type === 'pointerleave') {\n type = 'pointerout'\n }\n\n const event = new FederatedEvent(this)\n event.type = type \n event.nativeEvent = from\n event.target = target ?? this.hitTest(gp.x, gp.y) ?? this._hitElements[0],\n event.global = gp\n\n return event\n }\n\n clonePointEvent(from: FederatedEvent, type?: string) {\n const event = new FederatedEvent(this)\n\n event.nativeEvent = from.nativeEvent\n event.global = from.global\n\n event.type = type ?? from.type\n event.path = from.composedPath().slice()\n event.target = from.target\n\n return event\n }\n\n mapPositionToPoint(x: number, y: number) {\n const canvas = this.domElement as HTMLCanvasElement\n const rect = canvas.isConnected\n ? canvas.getBoundingClientRect()\n : {\n x: 0,\n y: 0,\n width: canvas.width,\n height: canvas.height,\n left: 0,\n top: 0,\n }\n const resolutionMuliplier = 1 / this.resolution\n\n const point = new Vector2()\n point.x = (x - rect.left) * (canvas.width / rect.width) * resolutionMuliplier\n point.y = (y - rect.top) * (canvas.height / rect.height) * resolutionMuliplier\n\n return point\n }\n\n hitTest(x: number,y: number) {\n const useMove = this._isPointerMoveEvent\n const invertedPath = this[useMove ? 'hitTestMoveRecursive' : 'hitTestRecursive'](\n this.rootTarget,\n this.rootTarget.eventMode,\n new Vector2(x, y),\n )\n\n return invertedPath && invertedPath[0]\n }\n\n private _interactivePrune(container: Container) {\n if (!container || !container.visible) {\n return true\n }\n\n if (container.eventMode === 'none') {\n return true\n }\n // TODO: passive\n return false\n }\n\n hitTestMoveRecursive(\n currentTarget: Container,\n eventMode: EventMode,\n location: Vector2,\n ): Container[] {\n let shouldReturn = false\n\n if (this._interactivePrune(currentTarget)) return\n\n const children = currentTarget.children\n if (children && children.length > 0) {\n for (let i = children.length - 1; i >= 0; --i) {\n const child: Container = children[i]\n\n const nestedHit = this.hitTestMoveRecursive(\n child,\n this._isInteractive(eventMode) ? eventMode : child.eventMode,\n location,\n )\n\n if (nestedHit) {\n if (nestedHit.length > 0 && !nestedHit[nestedHit.length - 1].parent) {\n continue\n }\n\n const isInteractive = this._isInteractive(currentTarget.eventMode)\n if (nestedHit.length > 0 || isInteractive) {\n if (isInteractive) this._allInteractiveElements.push(currentTarget)\n nestedHit.push(currentTarget)\n }\n\n if (this._hitElements.length === 0) {\n this._hitElements = nestedHit\n }\n\n shouldReturn = true\n }\n }\n }\n\n const isInteractiveMode = this._isInteractive(eventMode)\n const isInteractiveTarget = this._isInteractive(currentTarget.eventMode)\n\n if (isInteractiveTarget) {\n this._allInteractiveElements.push(currentTarget)\n }\n\n if (this._hitElements.length > 0) return\n\n if (shouldReturn) {\n return this._hitElements\n }\n\n if (isInteractiveMode && this.hitTestFn(currentTarget, location)) {\n return isInteractiveTarget ? [currentTarget] : []\n }\n\n return\n }\n\n hitTestRecursive(\n currentTarget: Container,\n eventMode: EventMode,\n location: Vector2,\n ): Container[] {\n // TODO: 剪枝优化\n\n const children = currentTarget.children\n for (let i = children.length - 1; i >= 0; i--) {\n const child = children[i] as Container\n\n const nestedHit = this.hitTestRecursive(\n child,\n this._isInteractive(eventMode) ? eventMode : child.eventMode,\n location,\n )\n\n if (nestedHit) {\n const isInteractive = this._isInteractive(currentTarget.eventMode)\n\n if (nestedHit.length > 0 || isInteractive) {\n nestedHit.push(currentTarget)\n }\n\n return nestedHit\n }\n }\n\n const isInteractiveMode = this._isInteractive(eventMode)\n const isInteractiveTarget = this._isInteractive(currentTarget.eventMode)\n\n if (isInteractiveMode && this.hitTestFn(currentTarget, location)) {\n return isInteractiveTarget ? [currentTarget] : []\n }\n\n return null\n }\n\n hitTestFn(container: Container, pos: Vector2) {\n if (container.hitArea) return true\n\n // ? container不为ViewContainer的情况\n if ((container as ViewContainer).containsPoint) {\n const localPos = container.worldTransform.applyInverse(pos)\n return (container as ViewContainer).containsPoint(localPos)\n }\n\n return false\n }\n}\n\n\nfunction findMountedTarget(propagationPath: Container[]) {\n if (!propagationPath) {\n return\n }\n\n let currentTarget = propagationPath[0]\n\n for (let i = 1; i < propagationPath.length; ++i) {\n if (propagationPath[i].parent === currentTarget) {\n currentTarget = propagationPath[i]\n } else {\n break\n }\n }\n\n return currentTarget\n}\n","export function clearList(list: unknown[], index?: number) {\n index ||= 0\n\n for (let i = index; i < list.length; ++i) {\n if (list[i]) {\n list[i] = null\n } else {\n break\n }\n }\n}\n\nexport function assignWithIgnore<T extends Record<string, any>>(\n target: T,\n options: T,\n ignore: Record<string, boolean> = {}\n) {\n for (const key in options) {\n if (!ignore[key] && options[key] !== undefined) {\n target[key] = options[key]\n }\n }\n}\n","export interface Instruction {\n readonly renderPipeId: string\n}\n\n/**\n * 对数组的简单封装\n * 出于性能优的考虑,不会主观的调整数组的大小\n * 因此length没有使用价值\n */\nexport class InstructionSet {\n public readonly instructions: Instruction[] = []\n public instructionSize = 0\n\n /**\n * @internal\n */\n public renderPipes: any\n\n public reset() {\n this.instructionSize = 0\n }\n\n public add(instruction: Instruction) {\n this.instructions[this.instructionSize++] = instruction\n }\n}","import { Matrix } from \"@/maths\";\nimport { Container } from \"./Container\";\nimport { InstructionSet } from \"@/renderer/InstructionSet\";\nimport { ViewContainer } from \"../ViewContainer\";\n\nexport class RenderGroup {\n public worldTransform = new Matrix()\n public localTransform = new Matrix()\n public root: Container = null\n public instructionSet = new InstructionSet()\n public structureDidChange = true\n\n public renderGroupParent: RenderGroup = null\n public renderGroupChildren: RenderGroup[] = []\n\n // 所有transform有更新的集合\n public readonly childrenToUpdate: Record<number, { list: Container[], index: number }> = Object.create(null)\n // 所有可渲染元素的集合\n public readonly childrenRenderablesToUpdate: { list: Container[], index: number } = { list: [], index: 0 }\n\n constructor(root: Container) {\n this.init(root)\n }\n\n init(root: Container) {\n this.root = root\n const children = root.children\n for (let i = 0; i < children.length; ++i) {\n this.addChild(children[i])\n }\n }\n\n addChild(child: Container) {\n this.structureDidChange = true\n\n child.parentRenderGroup = this\n\n if (child.parent === this.root) {\n child.relativeRenderGroupDepth = 1\n } else {\n child.relativeRenderGroupDepth = child.parent.relativeRenderGroupDepth + 1\n }\n\n child.didChange = true\n this.onChildUpdate(child)\n\n const children = child.children\n for (let i = 0; i < children.length; ++i) {\n this.addChild(children[i])\n }\n }\n\n removeChild(child: Container) {\n this.structureDidChange = true\n\n // TODO: ignore onRenderMixin\n\n child.parentRenderGroup = null\n if (child.renderGroup) {\n this._removeRenderGroupChild(child.renderGroup)\n return\n }\n\n const children = child.children\n\n for (let i = 0; i < children.length; ++i) {\n this.removeChild(children[i])\n }\n }\n\n public removeChildren(children: Container[]) {\n for (let i = 0; i < children.length; ++i) {\n this.removeChild(children[i])\n }\n }\n\n private _removeRenderGroupChild(renderGroupChild: RenderGroup) {\n const index = this.renderGroupChildren.indexOf(renderGroupChild)\n\n if (index > -1) {\n this.renderGroupChildren.splice(index, 1)\n }\n\n renderGroupChild.renderGroupParent = null\n }\n\n public onChildViewUpdate(child: Container) {\n this.childrenRenderablesToUpdate.list[this.childrenRenderablesToUpdate.index++] = child\n }\n\n public onChildUpdate(child: Container) {\n let childrenToUpdate = this.childrenToUpdate[child.relativeRenderGroupDepth]\n\n if (!childrenToUpdate) {\n childrenToUpdate = this.childrenToUpdate[child.relativeRenderGroupDepth] = {\n index: 0,\n list: [],\n }\n }\n\n // 不使用push为了避免频繁的数组扩缩容触发gc导致帧数抖动\n childrenToUpdate.list[childrenToUpdate.index++] = child\n }\n\n public updateRenderable(renderable: ViewContainer) {\n if (renderable.globalDisplayStatus < 0b111) return\n\n this.instructionSet.renderPipes[renderable.renderPipeId].updateRenderable(renderable)\n renderable.didViewUpdate = false\n }\n\n public destroy() {\n this.root = null\n ;(this.childrenRenderablesToUpdate as any) = null\n ;(this.childrenToUpdate as any) = null\n this.renderGroupChildren = null\n this.instructionSet = null\n }\n}","const uidCache: Record<string, number> = {\n default: -1,\n};\n\n/**\n * The names of the unique identifiers. These are used to create unique identifiers for different types of objects.\n * @category utils\n * @internal\n */\nexport type UIDNames =\n | 'default'\n | 'resource'\n | 'texture'\n | 'textureSource'\n | 'textureResource'\n | 'batcher' //\n | 'graphicsContext' //\n | 'graphicsView' //\n | 'graphicsPath' //\n | 'fillGradient' //\n | 'fillPattern' //\n | 'meshView' //\n | 'renderable' //\n | 'buffer' //\n | 'bufferResource' //\n | 'geometry'\n | 'instructionSet' //\n | 'renderTarget' //\n | 'uniform' //\n | 'spriteView' //\n | 'textView' //\n | 'tilingSpriteView' //\n | 'shader' //\n | 'renderer' //\n | 'textStyle'\n | (string & {});\n\n/**\n * Gets the next unique identifier\n * @param name - The name of the identifier.\n * @returns {number} The next unique identifier to use.\n * @category utils\n * @internal\n */\nexport function uid(name: UIDNames = 'default'): number\n{\n if (uidCache[name] === undefined)\n {\n uidCache[name] = -1;\n }\n\n return ++uidCache[name];\n}\n\n/**\n * Resets the next unique identifier to 0. This is used for some tests, dont touch or things WILL explode :)\n * @internal\n */\nexport function resetUids(): void\n{\n for (const key in uidCache)\n {\n delete uidCache[key];\n }\n}\n","import { Bounds } from '@/maths/Bounds'\nimport { ObservablePoint } from '@/maths/Point'\nimport { Texture } from '@/renderer/texture/Texture'\n\nexport * from './uid'\n\nexport function loadImage(url: string) {\n const { promise, resolve, reject } = Promise.withResolvers<{ image: HTMLImageElement, w: number, h: number }>()\n const image = document.createElement('img')\n image.src = url\n image.onload = () => {\n const w = image.naturalWidth\n const h = image.naturalHeight\n resolve({ w, h, image })\n }\n image.onerror = reject\n\n return promise\n}\n\n// export function gridWorld(gridX: number, gridY: number) {\n// const worldX = (gridX - gridY)\n// }\n\nexport function createDebug(ns: string) {\n return (...args: any[]) => {\n console.log(ns, ...args)\n }\n}\n\nexport function updateBounds(bounds: Bounds, anchor: ObservablePoint, texture: Texture) {\n const { width, height } = texture.orig\n\n bounds.minX = -anchor.x * width\n bounds.minY = -anchor.y * height\n\n bounds.maxX = bounds.minX + width\n bounds.maxY = bounds.minY + height\n}\n\nexport function applyMixins(base: any, ...mixins: Parameters<typeof Object.getOwnPropertyDescriptors>[0][]) {\n for (const mixin of mixins) {\n Object.defineProperties(base.prototype, Object.getOwnPropertyDescriptors(mixin))\n }\n}\n\n","import { Vector2 } from \".\"\n\nexport interface Observer<T> {\n _onUpdate: (point?: T) => void\n}\n\nexport class ObservablePoint {\n public _x: number\n public _y: number\n private readonly _observer: Observer<ObservablePoint>\n\n constructor(observer: Observer<ObservablePoint>, x?: number, y?: number) {\n this._x = x || 0\n this._y = y || 0\n this._observer = observer\n }\n\n public set(x = 0, y = x): this {\n if (this._x !== x || this._y !== y) {\n this._x = x\n this._y = y\n this._observer._onUpdate(this)\n }\n\n return this\n }\n\n get x() {\n return this._x\n }\n\n set x(value: number) {\n if (this._x !== value) {\n this._x = value\n this._observer._onUpdate(this)\n }\n }\n\n get y() {\n return this._y\n }\n\n set y(value: number) {\n if (this._y !== value) {\n this._y = value\n this._observer._onUpdate(this)\n }\n }\n\n public copyFrom(value: Vector2) {\n if (this.x !== value.x || this.y !== value.y) {\n this._x = value.x\n this._y = value.y\n this._observer._onUpdate(this)\n }\n return this\n }\n\n public toVector2() {\n return new Vector2(this.x, this.y)\n }\n}","/**\n * Conversion factor for converting radians to degrees.\n * @type {number} RAD_TO_DEG\n * @category maths\n * @standard\n */\nexport const RAD_TO_DEG = 180 / Math.PI;\n\n/**\n * Conversion factor for converting degrees to radians.\n * @type {number}\n * @category maths\n * @standard\n */\nexport const DEG_TO_RAD = Math.PI / 180;","'use strict';\n\nvar has = Object.prototype.hasOwnProperty\n , prefix = '~';\n\n/**\n * Constructor to create a storage for our `EE` objects.\n * An `Events` instance is a plain object whose properties are event names.\n *\n * @constructor\n * @private\n */\nfunction Events() {}\n\n//\n// We try to not inherit from `Object.prototype`. In some engines creating an\n// instance in this way is faster than calling `Object.create(null)` directly.\n// If `Object.create(null)` is not supported we prefix the event names with a\n// character to make sure that the built-in object properties are not\n// overridden or used as an attack vector.\n//\nif (Object.create) {\n Events.prototype = Object.create(null);\n\n //\n // This hack is needed because the `__proto__` property is still inherited in\n // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.\n //\n if (!new Events().__proto__) prefix = false;\n}\n\n/**\n * Representation of a single event listener.\n *\n * @param {Function} fn The listener function.\n * @param {*} context The context to invoke the listener with.\n * @param {Boolean} [once=false] Specify if the listener is a one-time listener.\n * @constructor\n * @private\n */\nfunction EE(fn, context, once) {\n this.fn = fn;\n this.context = context;\n this.once = once || false;\n}\n\n/**\n * Add a listener for a given event.\n *\n * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} context The context to invoke the listener with.\n * @param {Boolean} once Specify if the listener is a one-time listener.\n * @returns {EventEmitter}\n * @private\n */\nfunction addListener(emitter, event, fn, context, once) {\n if (typeof fn !== 'function') {\n throw new TypeError('The listener must be a function');\n }\n\n var listener = new EE(fn, context || emitter, once)\n , evt = prefix ? prefix + event : event;\n\n if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;\n else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);\n else emitter._events[evt] = [emitter._events[evt], listener];\n\n return emitter;\n}\n\n/**\n * Clear event by name.\n *\n * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.\n * @param {(String|Symbol)} evt The Event name.\n * @private\n */\nfunction clearEvent(emitter, evt) {\n if (--emitter._eventsCount === 0) emitter._events = new Events();\n else delete emitter._events[evt];\n}\n\n/**\n * Minimal `EventEmitter` interface that is molded against the Node.js\n * `EventEmitter` interface.\n *\n * @constructor\n * @public\n */\nfunction EventEmitter() {\n this._events = new Events();\n this._eventsCount = 0;\n}\n\n/**\n * Return an array listing the events for which the emitter has registered\n * listeners.\n *\n * @returns {Array}\n * @public\n */\nEventEmitter.prototype.eventNames = function eventNames() {\n var names = []\n , events\n , name;\n\n if (this._eventsCount === 0) return names;\n\n for (name in (events = this._events)) {\n if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);\n }\n\n if (Object.getOwnPropertySymbols) {\n return names.concat(Object.getOwnPropertySymbols(events));\n }\n\n return names;\n};\n\n/**\n * Return the listeners registered for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Array} The registered listeners.\n * @public\n */\nEventEmitter.prototype.listeners = function listeners(event) {\n var evt = prefix ? prefix + event : event\n , handlers = this._events[evt];\n\n if (!handlers) return [];\n if (handlers.fn) return [handlers.fn];\n\n for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {\n ee[i] = handlers[i].fn;\n }\n\n return ee;\n};\n\n/**\n * Return the number of listeners listening to a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Number} The number of listeners.\n * @public\n */\nEventEmitter.prototype.listenerCount = function listenerCount(event) {\n var evt = prefix ? prefix + event : event\n , listeners = this._events[evt];\n\n if (!listeners) return 0;\n if (listeners.fn) return 1;\n return listeners.length;\n};\n\n/**\n * Calls each of the listeners registered for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Boolean} `true` if the event had listeners, else `false`.\n * @public\n */\nEventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {\n var evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) return false;\n\n var listeners = this._events[evt]\n , len = arguments.length\n , args\n , i;\n\n if (listeners.fn) {\n if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);\n\n switch (len) {\n case 1: return listeners.fn.call(listeners.context), true;\n case 2: return listeners.fn.call(listeners.context, a1), true;\n case 3: return listeners.fn.call(listeners.context, a1, a2), true;\n case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;\n case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;\n case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;\n }\n\n for (i = 1, args = new Array(len -1); i < len; i++) {\n args[i - 1] = arguments[i];\n }\n\n listeners.fn.apply(listeners.context, args);\n } else {\n var length = listeners.length\n , j;\n\n for (i = 0; i < length; i++) {\n if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);\n\n switch (len) {\n case 1: listeners[i].fn.call(listeners[i].context); break;\n case 2: listeners[i].fn.call(listeners[i].context, a1); break;\n case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;\n case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;\n default:\n if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {\n args[j - 1] = arguments[j];\n }\n\n listeners[i].fn.apply(listeners[i].context, args);\n }\n }\n }\n\n return true;\n};\n\n/**\n * Add a listener for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.on = function on(event, fn, context) {\n return addListener(this, event, fn, context, false);\n};\n\n/**\n * Add a one-time listener for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.once = function once(event, fn, context) {\n return addListener(this, event, fn, context, true);\n};\n\n/**\n * Remove the listeners of a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn Only remove the listeners that match this function.\n * @param {*} context Only remove the listeners that have this context.\n * @param {Boolean} once Only remove one-time listeners.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {\n var evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) return this;\n if (!fn) {\n clearEvent(this, evt);\n return this;\n }\n\n var listeners = this._events[evt];\n\n if (listeners.fn) {\n if (\n listeners.fn === fn &&\n (!once || listeners.once) &&\n (!context || listeners.context === context)\n ) {\n clearEvent(this, evt);\n }\n } else {\n for (var i = 0, events = [], length = listeners.length; i < length; i++) {\n if (\n listeners[i].fn !== fn ||\n (once && !listeners[i].once) ||\n (context && listeners[i].context !== context)\n ) {\n events.push(listeners[i]);\n }\n }\n\n //\n // Reset the array, or remove it completely if we have no more listeners.\n //\n if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;\n else clearEvent(this, evt);\n }\n\n return this;\n};\n\n/**\n * Remove all listeners, or those of the specified event.\n *\n * @param {(String|Symbol)} [event] The event name.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {\n var evt;\n\n if (event) {\n evt = prefix ? prefix + event : event;\n if (this._events[evt]) clearEvent(this, evt);\n } else {\n this._events = new Events();\n this._eventsCount = 0;\n }\n\n return this;\n};\n\n//\n// Alias methods names because people roll like that.\n//\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\nEventEmitter.prototype.addListener = EventEmitter.prototype.on;\n\n//\n// Expose the prefix.\n//\nEventEmitter.prefixed = prefix;\n\n//\n// Allow `EventEmitter` to be imported as module namespace.\n//\nEventEmitter.EventEmitter = EventEmitter;\n\n//\n// Expose the module.\n//\nif ('undefined' !== typeof module) {\n module.exports = EventEmitter;\n}\n","import EventEmitter from './index.js'\n\nexport { EventEmitter }\nexport default EventEmitter\n","import { Matrix } from \"./Matrix\"\nimport { Container } from \"@/scene/container/Container\"\nimport { Rectangle } from \"./shapes/Rectangle\"\nimport { Renderable } from \"@/scene/ViewContainer\"\n\n\nexport class Bounds {\n public minX = Infinity\n public minY = Infinity\n public maxX = -Infinity\n public maxY = -Infinity\n public matrix = new Matrix()\n\n private _rectangle: Rectangle\n \n constructor(minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity) {\n this.minX = minX\n this.minY = minY\n this.maxX = maxX\n this.maxY = maxY\n }\n\n clone() {\n return new Bounds(this.minX, this.minY, this.maxX, this.maxY)\n }\n\n isEmpty() {\n return this.minX >= this.maxX || this.minY >= this.maxY\n }\n\n clear() {\n this.minX = Infinity\n this.minY = Infinity\n this.maxX = -Infinity\n this.maxY = -Infinity\n }\n\n get width() {\n return this.maxX - this.minX\n }\n set width(value: number) {\n this.maxX = this.minX + value\n }\n\n get height() {\n return this.maxY - this.minY\n }\n set height(value: number) {\n this.maxY = this.minY + value\n }\n\n get left() {\n return this.minX\n }\n get right() {\n return this.maxX\n }\n get top() {\n return this.minY\n }\n get bottom() {\n return this.maxY\n }\n\n get isValid() {\n return this.minX + this.minY !== Infinity\n }\n\n set(x0: number, y0: number, x1: number, y1: number) {\n this.minX = x0\n this.minY = y0\n this.maxX = x1\n this.maxY = y1\n }\n\n addBounds(bounds: Bounds, matrix?: Matrix) {\n this.addFrame(bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, matrix)\n }\n\n addRect(rect: Rectangle, matrix?: Matrix) {\n this.addFrame(rect.x, rect.y, rect.width + rect.x, rect.height + rect.y, matrix)\n }\n\n addFrame(x0: number, y0: number, x1: number, y1: number, matrix?: Matrix) {\n matrix ||= this.matrix\n\n const a = matrix.a\n const b = matrix.b\n const c = matrix.c\n const d = matrix.d\n const tx = matrix.tx\n const ty = matrix.ty\n\n {\n const x = a * x0 + c * y0 + tx;\n const y = b * x0 + d * y0 + ty;\n updateMinMax(x, y, this)\n }\n\n {\n const x = a * x1 + c * y0 + tx\n const y = b * x1 + d * y0 + ty\n updateMinMax(x, y, this)\n }\n\n {\n const x = a * x0 + c * y1 + tx\n const y = b * x0 + d * y1 + ty\n updateMinMax(x, y, this)\n }\n\n {\n const x = a * x1 + c * y1 + tx\n const y = b * x1 + d * y1 + ty\n updateMinMax(x, y, this)\n }\n }\n\n get rectangle() {\n if (!this._rectangle) {\n this._rectangle = new Rectangle()\n }\n\n const rectangle = this._rectangle\n\n // TODO: 有没有必要判断rectangle的合法性,即宽高是否存在小于0的情况?\n rectangle.x = this.minX\n rectangle.y = this.minY\n rectangle.width = this.maxX - this.minX\n rectangle.height = this.maxY - this.minY\n\n return rectangle\n }\n\n addBoundsMask(mask: Bounds) {\n this.minX = this.minX > mask.minX ? this.minX : mask.minX\n this.minY = this.minY > mask.minY ? this.minY : mask.minY\n this.maxX = this.maxX < mask.maxX ? this.maxX : mask.maxX\n this.maxY = this.maxY < mask.maxY ? this.maxY : mask.maxY\n }\n}\n\nfunction updateMinMax(x: number, y: number, bounds: Bounds) {\n if (x < bounds.minX) bounds.minX = x\n if (x > bounds.maxX) bounds.maxX = x\n if (y < bounds.minY) bounds.minY = y\n if (y > bounds.maxY) bounds.maxY = y\n}\n\nexport function getLocalBounds(target: Container, bounds: Bounds, relativeMatrix?: Matrix) {\n bounds.clear()\n\n relativeMatrix ||= new Matrix()\n _getLocalBounds(target, bounds, relativeMatrix, target, true)\n\n if (!bounds.isValid) {\n bounds.set(0, 0, 0, 0)\n }\n\n return bounds\n}\n\nfunction _getLocalBounds(\n target: Container,\n bounds: Bounds,\n parentTransform: Matrix,\n rootContainer: Container,\n isRoot: boolean,\n): Bounds {\n let relativeTransform = new Matrix()\n\n if (!isRoot) {\n if (!target.visible || !target.measurable) return\n\n target.updateLocalTransform()\n\n relativeTransform.appendFrom(target.localTransform, parentTransform)\n } else {\n relativeTransform.copyFrom(parentTransform)\n }\n\n const parentBounds = bounds\n // 判断后续计算边界时是否在一个独立的边界基础上进行\n const needIsolateBounds = !!target.effects.length\n\n if (needIsolateBounds) {\n bounds = new Bounds()\n }\n\n if (target.boundsArea) {\n bounds.addRect(target.boundsArea, relativeTransform)\n } else {\n if (target.renderPipeId) {\n bounds.matrix = relativeTransform\n bounds.addBounds((target as Renderable).bounds)\n }\n const children = target.children\n for (let i = 0; i < children.length; i++) {\n _getLocalBounds(children[i], bounds, relativeTransform, rootContainer, false)\n }\n\n if (needIsolateBounds) {\n for (let i = 0; i < target.effects.length; ++i) {\n target.effects[i].addLocalBounds?.(bounds, rootContainer)\n }\n\n parentBounds.addBounds(bounds, new Matrix())\n }\n }\n\n return bounds\n}\n\n","import { Instruction } from \"@/renderer/InstructionSet\"\nimport { Bounds, getLocalBounds } from \"@/maths/Bounds\"\nimport { Mask } from \"../container/mixins/effectMixin\"\nimport { Container } from \"../container/Container\"\nimport { Matrix } from \"@/maths\"\n\nexport interface StencilMaskInstruction extends Instruction {\n mask: StencilMask\n action: string\n}\n\nexport class StencilMask {\n public pipe = 'stencilMask'\n public mask?: Mask\n\n constructor(mask: Mask) {\n this.mask = mask\n mask.includeInBuild = false\n mask.measurable = false\n }\n\n public addLocalBounds(bounds: Bounds, localRoot: Container) {\n const boundsMask = new Bounds()\n\n this.mask.measurable = true\n\n const relativeMask = getMatrixRelativeToParent(this.mask, localRoot)\n\n getLocalBounds(this.mask, boundsMask, relativeMask)\n\n this.mask.measurable = false\n\n bounds.addBoundsMask(boundsMask)\n }\n}\n\nfunction getMatrixRelativeToParent(target: Container, root: Container, matrix?: Matrix) {\n matrix ||= new Matrix()\n if (target === root) {\n return matrix\n }\n\n matrix = getMatrixRelativeToParent(target.parent, root, matrix)\n\n target.updateLocalTransform()\n\n return Matrix.append(matrix, target.localTransform)\n}\n","import { Container } from \"../Container\"\nimport { StencilMask } from \"@/scene/mask/StencilMask\"\nimport { Graphics } from \"@/scene/graphics\"\n\nexport type Mask = Graphics | null\n\nexport type MaskEffect = StencilMask\n\nexport interface EffectMixinConstructor {\n mask?: Mask\n}\n\nexport interface EffectMixin extends Required<EffectMixinConstructor> {\n effects?: MaskEffect[]\n _maskEffect?: MaskEffect\n mask: Mask\n addEffect(effect: MaskEffect): void\n removeEffect(effect: MaskEffect): void\n}\n\nexport const effectMixin: Partial<Container> = {\n effects: [],\n _maskEffect: null,\n\n addEffect(effect) {\n this.effects.push(effect)\n\n this._updateIsSimple()\n },\n\n removeEffect(effect) {\n const index = this.effects.indexOf(effect)\n if (index === -1) {\n this.effects.splice(index, 1)\n }\n\n this._updateIsSimple()\n },\n\n set mask(value: Mask) {\n const effect = this._maskEffect\n if (value === effect?.mask) return\n\n if (effect) {\n this.removeEffect(effect)\n this._maskEffect = null\n }\n\n if (value == null) return\n\n // TODO: color filter stencil\n this._maskEffect = new StencilMask(value)\n\n this.addEffect(this._maskEffect)\n },\n\n get mask(): Mask {\n return this._maskEffect?.mask\n }\n}\n","import { Container } from \"../Container\";\n\nexport interface SortMixinConstructor {\n zIndex?: number\n sortDirty?: boolean\n sortableChildren?: boolean\n}\n\nexport interface SortMixin extends Required<SortMixinConstructor> {\n /**\n * @internal\n */\n _zIndex: number\n}\n\nexport const sortMixin: Partial<Container> = {\n _zIndex: 0,\n sortableChildren: false,\n sortDirty: false,\n}\n","import { Bounds, getLocalBounds } from \"@/maths/Bounds\"\nimport { Container } from \"../Container\"\n\nexport interface MeasureMixinConstructor {\n width?: number\n height?: number\n}\n\nexport interface MeasureMixin extends Required<MeasureMixinConstructor> {\n _localBoundsCacheData: any\n _localBounds: Bounds\n\n getLocalBounds: () => Bounds\n _setWidth: (value: number, localWidth: number) => void\n _setHeight: (value: number, localHeight: number) => void\n}\n\nexport const measureMixin: Partial<Container> = {\n _localBoundsCacheData: null,\n _localBounds: null,\n\n _setWidth(value: number, localWidth: number) {\n const sign = Math.sign(this.scale.x) || 1\n\n if (localWidth !== 0) {\n this.scale.x = (value / localWidth) * sign\n } else {\n this.scale.x = sign\n }\n },\n\n _setHeight(value: number, localHeight: number) {\n const sign = Math.sign(this.scale.y) || 1\n\n if (localHeight !== 0) {\n this.scale.y = (value / localHeight) * sign\n } else {\n this.scale.y = sign\n }\n },\n\n /**\n * TODO: 缓存\n */\n getLocalBounds() {\n if (!this._localBounds) {\n this._localBounds = new Bounds()\n }\n\n getLocalBounds(this, this._localBounds)\n return this._localBounds\n }\n} as Container\n","import { Container, ContainerChild } from \"@/scene\";\n\nexport interface ChildrenHelperMixin<C = Container> {\n removeChildren(beginIndex?: number, endIndex?: number): C[]\n}\n\nexport const childrenHelperMixin: ChildrenHelperMixin<ContainerChild> = {\n\n removeChildren(beginIndex = 0, endIndex?: number) {\n const end = endIndex ?? this.children.length\n const range = end - beginIndex\n const removed: Container[] = []\n\n if (range > 0 && range <= end) {\n for (let i = end - 1; i >= beginIndex; --i) {\n const child = this.children[i]\n\n if (!child) continue\n\n removed.push(child)\n child.parent = null\n }\n\n removeItems(this.children, beginIndex, end)\n\n const renderGroup = this.renderGroup || this.parentRenderGroup\n\n if (renderGroup) {\n renderGroup.removeChildren(removed)\n }\n\n // TODO: emit removed event\n // for (let i = 0; i < removed.length; ++i) {\n // const child = removed[i]\n\n // }\n\n return removed\n } else if (range === 0 && this.children.length === 0) {\n return removed\n }\n\n throw new Error('removeChildren: numeric values are outside the acceptable range.')\n }\n} as Container\n\nfunction removeItems(arr: any[], startIndex: number, removeCount: number) {\n const length = arr.length\n let i\n\n if (startIndex >= length || removeCount === 0) {\n return\n }\n\n removeCount = (startIndex + removeCount) > length ? (length - startIndex) : removeCount\n\n const len = length - removeCount\n\n for (i = startIndex; i < len; ++i) {\n arr[i] = arr[i + removeCount]\n }\n\n arr.length = len\n}\n","import { Matrix, Rectangle, Vector2 } from \"@/maths\"\nimport { EventMode } from '@/system'\nimport { RenderGroup } from './RenderGroup'\nimport { applyMixins } from '@/utils'\nimport { ObservablePoint } from '@/maths/Point'\nimport { DEG_TO_RAD, RAD_TO_DEG } from '@/maths/const'\nimport EventEmitter from \"eventemitter3\"\nimport { FederatedEventEmitterTypes } from \"@/events/FederatedEventMap\"\nimport { effectMixin, EffectMixin, EffectMixinConstructor } from \"./mixins/effectMixin\"\nimport { InstructionSet } from \"@/renderer/InstructionSet\"\nimport { sortMixin, SortMixin, SortMixinConstructor } from \"./mixins/sortMixin\"\nimport { measureMixin, MeasureMixin, MeasureMixinConstructor } from \"./mixins/measureMixin\"\nimport { assignWithIgnore } from \"./utils\"\nimport { DestroyOptions } from \"./destroyTypes\"\nimport { childrenHelperMixin, ChildrenHelperMixin } from \"./mixins/childrenHelperMixin\"\n\n/** @internal */\nexport const UPDATE_COLOR = 0b0001\n/** @internal */\nexport const UPDATE_BLEND = 0b0010\n/** @internal */\nexport const UPDATE_VISIBLE = 0b0100\n/** @internal */\nexport const UPDATE_TRANSFORM = 0b1000\n\nexport type ContainerChild = Container\n\nexport type IHitArea = {\n contains(x: number, y: number): boolean\n}\n\nconst defaultSkew = new ObservablePoint(null)\nconst defaultOrigin = new ObservablePoint(null)\nconst defaultScale = new ObservablePoint(null, 1, 1)\nconst defaultPivot = new ObservablePoint(null)\n\nexport interface ContainerOptions<C extends ContainerChild = ContainerChild> extends EffectMixinConstructor, SortMixinConstructor, MeasureMixinConstructor {\n label?: string\n isRenderGroup?: boolean\n alpha?: number\n angle?: number\n children?: C[]\n parent?: Container\n rotation?: number\n scale?: Vector2 | number\n pivot?: Vector2 | number\n origin?: Vector2 | number\n position?: Vector2\n skew?: Vector2\n visible?: boolean\n x?: number\n y?: number\n boundsArea?: Rectangle\n}\n\nexport interface Container extends EffectMixin, SortMixin, MeasureMixin, ChildrenHelperMixin {}\n\nexport class Container<C extends ContainerChild = ContainerChild> extends EventEmitter<FederatedEventEmitterTypes> {\n public label: string\n public destroyed = false\n public renderGroup: RenderGroup = null\n public parentRenderGroup: RenderGroup | null = null\n public parent: Container | null = null\n public eventMode: EventMode = 'passive'\n public hitArea: IHitArea | null = null\n public boundsArea: Rectangle\n /** @internal */\n public _position = new ObservablePoint(this, 0, 0)\n // mask需要,在收集渲染元素时需要被剔除\n /** @private */\n public includeInBuild = true\n\n public readonly renderPipeId: string\n\n // 如果容器的属性被修改了,就设为true\n // 当容器的属性被transform应用了就重置为false\n /** @private */\n public didChange = false\n /** @private */\n public didViewUpdate = false\n /** @private */\n public isSimple = true\n /** @private */\n public measurable = true\n // 当前元素相对于RenderGroup的深度\n /** @private */\n public relativeRenderGroupDepth = 0\n\n public _attrUpdateTick = 0\n public _localTransformUpdateTick = 0\n /**\n * @private\n */\n public _updateFlags = 0b1111\n /**\n * @internal\n */\n public localDisplayStatus = 0b111\n /**\n * @internal\n */\n public globalDisplayStatus = 0b111\n\n public children: C[] = []\n\n public localTransform = new Matrix()\n public relativeGroupTransform = new Matrix()\n public groupTransform = this.relativeGroupTransform\n public _rotation = 0\n public _worldTransform: Matrix\n /**\n * 归一化的x坐标在x轴上的投影, cosx\n */\n public _cx = 1\n /**\n * 归一化的y坐标在x轴上的投影, sinx\n */\n public _sx = 0\n /**\n * 归一化的x坐标在y轴上的投影, cosy\n */\n public _cy = 0\n /**\n * 归一化的y坐标在y轴上的投影, siny\n */\n public _sy = 1\n\n /**\n * 在x轴和y轴上的倾斜值\n * @internal\n */\n public _skew = defaultSkew\n /**\n * @internal\n */\n public _scale = defaultScale\n /**\n * @internal\n */\n public _origin = defaultOrigin\n /**\n * @internal\n */\n public _pivot = defaultPivot\n /**\n * @internal\n */\n public localAlpha = 1\n /**\n * @internal\n */\n public groupColor = 0xFFFFFF // BGR\n /**\n * @internal\n * TODO: tint\n */\n public localColor = 0xffffff\n /**\n * @internal\n */\n public groupAlpha = 1\n /**\n * @internal\n */\n public groupColorAlpha = 0xFFFFFFFF\n\n constructor(options: ContainerOptions<C> = {}) {\n super()\n\n assignWithIgnore(this, options, {\n children: true,\n parent: true,\n effects: true,\n })\n\n // 由于是通过原型链混入,需要在实例化时隔离混入的属性防止污染\n this.effects = []\n }\n\n get renderable() {\n return !!(this.localDisplayStatus & 0b001)\n }\n\n set renderable(value: boolean) {\n const valueNumber = value ? 0b001 : 0\n\n if ((this.localDisplayStatus & 0b001) === valueNumber) return\n\n this._updateFlags |= UPDATE_VISIBLE\n this.localDisplayStatus ^= 0b001\n\n if (this.parentRenderGroup) {\n this.parentRenderGroup.structureDidChange = true\n }\n\n this._onUpdate()\n }\n\n get visible() {\n return !!(this.localDisplayStatus & 0b010)\n }\n\n set visible(value: boolean) {\n const valueNumber = value ? 0b010 : 0\n\n if ((this.localDisplayStatus & 0b010) === valueNumber) return\n\n if (this.parentRenderGroup) {\n this.parentRenderGroup.structureDidChange = true\n }\n\n this._updateFlags |= UPDATE_VISIBLE\n\n this.localDisplayStatus ^= 0b010\n\n this._onUpdate()\n }\n\n get isRenderGroup() {\n return !!this.renderGroup\n }\n\n set isRenderGroup(value: boolean) {\n if (!!this.renderGroup === value) return\n\n if (value) {\n this.enableRenderGroup()\n } else {\n this.disableRenderGroup()\n }\n }\n\n get zIndex() {\n return this._zIndex\n }\n\n set zIndex(value: number) {\n if (value === this._zIndex) return\n\n this._zIndex = value\n\n this.depthOfChildModified()\n }\n\n _updateIsSimple() {\n this.isSimple = !this.renderGroup && this.effects.length == 0\n }\n\n sortChildren() {\n if (!this.sortDirty) return\n\n this.sortDirty = false\n\n this.children.sort(sortChildren)\n }\n\n depthOfChildModified() {\n if (this.parent) {\n this.parent.sortableChildren = true\n this.parent.sortDirty = true\n }\n if (this.parentRenderGroup) {\n // TODO flag render group struct change\n }\n }\n\n enableRenderGroup() {\n if (this.renderGroup) return\n\n this.renderGroup = new RenderGroup(this)\n\n this.groupTransform = new Matrix()\n\n this._updateIsSimple()\n }\n\n disableRenderGroup() {\n if (!this.renderGroup) return\n\n const parentRenderGroup = this.parentRenderGroup\n parentRenderGroup?.removeChild(this)\n\n this.renderGroup = null\n this.groupTransform = this.relativeGroupTransform\n\n parentRenderGroup?.addChild(this)\n\n this._updateIsSimple()\n }\n\n collectRenderables(renderPipes: any, instructionSet: any) {\n if (this.globalDisplayStatus < 0b111 || !this.includeInBuild) return\n\n if (this.sortableChildren) {\n this.sortChildren()\n }\n\n if (this.isSimple) {\n this.collectRenderableSimple(renderPipes, instructionSet)\n } else if (this.renderGroup) {\n // TODO: nested rendergroup\n } else {\n this.collectRenderablesWithEffects(renderPipes, instructionSet)\n }\n }\n\n collectRenderablesWithEffects(renderPipes: any, instructionSet: InstructionSet) {\n for (let i = 0; i < this.effects.length; ++i) {\n const effect = this.effects[i]\n const pipe = renderPipes[effect.pipe]\n pipe.push(effect, instructionSet)\n\n }\n this.collectRenderableSimple(renderPipes, instructionSet)\n for (let i = 0; i < this.effects.length; ++i) {\n const effect = this.effects[i]\n const pipe = renderPipes[effect.pipe]\n pipe.pop(effect, instructionSet)\n }\n }\n\n collectRenderableSimple(renderPipes: any, instructionSet: InstructionSet) {\n const children = this.children\n for (let i = 0; i < children.length; ++i) {\n children[i].collectRenderables(renderPipes, instructionSet)\n }\n }\n\n setFromMatrix(matrix: Matrix) {\n matrix.decompose(this)\n }\n\n /**\n * 更新仿射变换矩阵\n */\n _updateSkew() {\n const rotation = this.rotation\n const skew = this.skew\n\n this._cx = Math.cos(rotation + skew.y)\n this._sx = Math.sin(rotation + skew.y)\n this._cy = -Math.sin(rotation - skew.x)\n this._sy = Math.cos(rotation - skew.x)\n }\n updateLocalTransform() {\n const localTransformChangeTick = this._attrUpdateTick\n if (this._localTransformUpdateTick === localTransformChangeTick) {\n return\n }\n this._localTransformUpdateTick = localTransformChangeTick\n\n this._updateSkew()\n\n const position = this.position\n const lt = this.localTransform\n\n const sx = this._scale.x\n const sy = this._scale.y\n const ox = -this._origin.x\n const oy = -this._origin.y\n const px = this._pivot.x\n const py = this._pivot.y\n\n lt.a = this._cx * sx\n lt.b = this._sx * sx\n lt.c = this._cy * sy\n lt.d = this._sy * sy\n lt.tx = position.x - (px * lt.a + py * lt.c) + (ox * lt.a + oy * lt.c) - ox\n lt.ty = position.y - (px * lt.b + py * lt.d) + (ox * lt.b + oy * lt.d) - oy\n }\n\n get alpha() {\n return this.localAlpha\n }\n\n set alpha(value: number) {\n if (value === this.localAlpha) return\n\n this.localAlpha = value\n\n this._updateFlags |= UPDATE_COLOR\n\n this._onUpdate()\n }\n\n get root() {\n let parent = this.parent\n let temp = this.parent\n while (parent) {\n if (!parent.parent) {\n temp = parent\n }\n parent = parent.parent\n }\n return temp\n }\n\n get worldTransform() {\n // 惰性初始化与复用\n this._worldTransform ||= new Matrix()\n if (this.renderGroup) {\n this._worldTransform.copyFrom(this.renderGroup.worldTransform)\n } else if (this.parentRenderGroup) {\n this._worldTransform.appendFrom(this.relativeGroupTransform, this.parentRenderGroup.worldTransform)\n }\n return this._worldTransform\n }\n\n get x() {\n return this._position.x\n }\n set x(value: number) {\n this._position.x = value\n }\n get position() {\n return this._position\n }\n set position(value: Vector2) {\n this._position.copyFrom(value)\n }\n get y() {\n return this._position.y\n }\n set y(value: number) {\n this._position.y = value\n }\n get rotation() {\n return this._rotation\n }\n set rotation(value: number) {\n if (this._rotation !== value) {\n this._rotation = value\n this._onUpdate(this._skew)\n }\n }\n get angle() {\n return this.rotation * RAD_TO_DEG\n }\n set angle(value: number) {\n this.rotation = value * DEG_TO_RAD\n }\n get skew() {\n if (this._skew === defaultSkew) {\n this._skew = new ObservablePoint(this, 0, 0)\n }\n return this._skew\n }\n set skew(value: Vector2) {\n if (this._skew === defaultSkew) {\n this._skew = new ObservablePoint(this, 0, 0)\n }\n this._skew.copyFrom(value)\n }\n get scale() {\n if (this._scale === defaultScale) {\n this._scale = new ObservablePoint(this, 1, 1)\n }\n return this._scale\n }\n set scale(value: Vector2) {\n if (this._scale === defaultScale) {\n this._scale = new ObservablePoint(this, 1, 1)\n }\n this._scale.copyFrom(value)\n }\n get pivot() {\n if (this._pivot === defaultPivot) {\n this._pivot = new ObservablePoint(this, 0, 0)\n }\n return this._pivot\n }\n set pivot(value: Vector2) {\n if (this._pivot === defaultPivot) {\n this._pivot = new ObservablePoint(this, 0, 0)\n }\n this._pivot.copyFrom(value)\n }\n get origin() {\n if (this._origin === defaultOrigin) {\n this._origin = new ObservablePoint(this, 0, 0)\n }\n return this._origin\n }\n set origin(value: Vector2) {\n if (this._origin === defaultOrigin) {\n this._origin = new ObservablePoint(this, 0, 0)\n }\n this._origin.copyFrom(value)\n }\n get width() {\n return Math.abs(this.scale.x * this.getLocalBounds().width)\n }\n set width(_value) {\n // const localWidth = this.getLocalBounds().width\n // 通过计算sign来保留符号\n // const sign = Math.sign(this.scale.x) || 1\n }\n\n get height() {\n return Math.abs(this.scale.y * this.getLocalBounds().height)\n }\n set height(_value) {\n\n }\n\n addChild<U extends C[]>(...children: U): U[0] {\n if (children.length > 1) {\n for (let i = 0; i < children.length; ++i) {\n this.addChild(children[i]!)\n }\n\n return children[0]!\n }\n\n const child = children[0]!\n const renderGroup = this.renderGroup || this.parentRenderGroup\n\n // 子元素重复添加即改变渲染顺序,手动将其置顶\n if (child.parent === this) {\n this.children.splice(this.children.indexOf(child), 1)\n this.children.push(child)\n\n if (renderGroup) {\n renderGroup.structureDidChange = true\n }\n\n return child\n }\n\n // 已经启用sort的情况下,有新元素被追加就标记当前元素需要重新排序\n // 估计是为了处理子元素zIndex为零的特殊情况\n if (this.sortableChildren) {\n this.sortDirty = true\n }\n\n // 存在其它父元素需要先处理掉关联关系\n if (child.parent) {\n child.parent.removeChild(child)\n }\n\n this.children.push(child)\n\n if (this.sortableChildren) {\n this.sortDirty = true\n }\n\n child.parent = this\n child.didChange = true\n\n child._updateFlags = 0b111\n\n if (renderGroup) {\n renderGroup.addChild(child)\n }\n\n if (child._zIndex != 0) {\n child.depthOfChildModified()\n }\n\n return child\n }\n\n removeChild<U extends C[]>(...children: U): U[0] | undefined {\n if (children.length > 1) {\n for (let i = 0; i < children.length; ++i) {\n this.removeChild(children[i]!)\n }\n return children[0]!\n }\n\n const child = children[0]\n if (!child) {\n return child\n }\n\n const index = this.children.indexOf(child)\n\n if (index > -1) {\n this.children.splice(index, 1)\n child.parent = null\n }\n return child\n }\n\n public _onUpdate(point?: Vector2) {\n if (point && point === this._skew) {\n this._updateSkew()\n }\n\n this._attrUpdateTick++\n\n if (this.didChange) return\n this.didChange = true\n\n if (this.parentRenderGroup) {\n this.parentRenderGroup.onChildUpdate(this)\n }\n }\n\n toGlobal(position: Vector2, skipUpdate?: boolean) {\n const globalMatrix = this.getGlobalTransform(skipUpdate)\n\n const global = globalMatrix.apply(position)\n\n return global\n }\n\n toLocal(position: Vector2, from?: Container, skipUpdate?: boolean) {\n let pos\n if (from) {\n pos = from.toGlobal(position)\n }\n\n const globalMatrix = this.getGlobalTransform(skipUpdate)\n\n pos = globalMatrix.applyInverse(position)\n return pos\n }\n\n getGlobalTransform(skipUpdate = false) {\n if (skipUpdate) {\n return this.worldTransform.clone()\n }\n\n this.updateLocalTransform()\n const m = new Matrix()\n const parentTransform = updateTransformBackwards(this, m)\n m.appendFrom(this.localTransform, parentTransform)\n\n return m\n }\n\n getGlobalPosition(skipUpdate = false) {\n if (this.parent) {\n return this.parent.toGlobal(this._position, skipUpdate)\n } else {\n return this._position.toVector2()\n }\n }\n\n public destroy(options: DestroyOptions = false) {\n if (this.destroyed) return\n this.destroyed = true\n\n let oldChildren: ContainerChild[]\n if (this.children.length) {\n oldChildren = this.removeChildren(0, this.children.length)\n }\n\n this.parent?.removeChild(this)\n this.parent = null\n this._maskEffect = null\n this.effects = null\n this._position = null\n this._scale = null\n this._pivot = null\n this._origin = null\n this._skew = null\n\n const destroyChildren = typeof options === 'boolean' ? options : options?.children\n if (destroyChildren && oldChildren) {\n for (let i = 0; i < oldChildren.length; ++i) {\n oldChildren[i].destroy(options)\n }\n }\n\n this.renderGroup?.destroy()\n this.renderGroup = null\n }\n}\n\nfunction updateTransformBackwards(target: Container, parentTransform: Matrix) {\n const parent = target.parent\n\n if (parent) {\n updateTransformBackwards(parent, parentTransform)\n parent.updateLocalTransform()\n const res = Matrix.append(parentTransform, parent.localTransform)\n parentTransform.copyFrom(res)\n }\n\n return parentTransform\n}\n\nfunction sortChildren(a: Container, b: Container) {\n return a._zIndex - b._zIndex\n}\n\napplyMixins(\n Container,\n sortMixin,\n effectMixin,\n measureMixin,\n childrenHelperMixin,\n)\n","import { Container, UPDATE_BLEND, UPDATE_COLOR, UPDATE_VISIBLE } from \"../Container\";\nimport { RenderGroup } from \"../RenderGroup\";\nimport { clearList } from \"../utils\";\n\nconst UPDATE_BLEND_COLOR_VISIBLE = (UPDATE_VISIBLE | UPDATE_COLOR | UPDATE_BLEND)\n\nexport function updateRenderGroupTransform(renderGroup?: RenderGroup, updateChildRenderGroup = false) {\n // TODO: worldColor或者worldAlpha的计算\n const root = renderGroup.root\n renderGroup.worldTransform.copyFrom(root.localTransform)\n\n // TODO: cal update tick\n const childrenToUpdate = renderGroup.childrenToUpdate\n\n for (const i in childrenToUpdate) {\n const renderGroupDepth = Number(i)\n const childrenAtDepth = childrenToUpdate[renderGroupDepth]\n const list = childrenAtDepth.list\n const index = childrenAtDepth.index\n\n for (let j = 0; j < index; ++j) {\n const child = list[j]\n if (child.parentRenderGroup === renderGroup && child.relativeRenderGroupDepth === renderGroupDepth) {\n updateTransform(child, 0)\n }\n }\n\n clearList(list, index)\n childrenAtDepth.index = 0\n }\n\n if (updateChildRenderGroup) {\n for (let i = 0; i < renderGroup.renderGroupChildren.length; ++i) {\n updateRenderGroupTransform(renderGroup.renderGroupChildren[i], updateChildRenderGroup)\n }\n }\n}\nexport function updateTransform(container: Container, updateFlags: number) {\n container.didChange = false\n\n const parent = container.parent\n const localTransform = container.localTransform\n\n container.updateLocalTransform()\n\n if (parent) {\n updateFlags |= container._updateFlags\n\n container.relativeGroupTransform.appendFrom(localTransform, parent.relativeGroupTransform)\n\n if (updateFlags & UPDATE_BLEND_COLOR_VISIBLE) {\n updateBlendColorVisible(container, parent, updateFlags)\n }\n } else {\n // container.relativeGroupTransform.copyFrom(localTransform)\n }\n\n // if (!container.renderGroup) {\n const children = container.children\n for (let i = 0; i < children.length; i++) {\n updateTransform(children[i], updateFlags)\n }\n // }\n}\n\nfunction updateBlendColorVisible(container: Container, parent: Container, updateFlags: number) {\n if (updateFlags & UPDATE_COLOR) {\n // TODO: 颜色混合 tint\n container.groupColor = parent.groupColor\n\n let groupAlpha = container.localAlpha * parent.groupAlpha\n groupAlpha = groupAlpha < 0 ? 0 : (groupAlpha > 1 ? 1 : groupAlpha)\n\n container.groupAlpha = groupAlpha\n container.groupColorAlpha = container.groupColor + (((groupAlpha * 255) | 0) << 24)\n }\n\n if (updateFlags & UPDATE_VISIBLE) {\n container.globalDisplayStatus = container.localDisplayStatus & parent.globalDisplayStatus\n }\n\n container._updateFlags = 0\n}\n","import { RenderGroup } from \"../RenderGroup\";\n\nexport function validateRenderables(renderGroup: RenderGroup, renderPipes: any) {\n const { list, index } = renderGroup.childrenRenderablesToUpdate\n\n let rebuildRequired = false\n\n for (let i = 0; i < index; ++i) {\n const renderable = list[i]\n\n const pipe = renderPipes[renderable.renderPipeId]\n\n rebuildRequired = pipe.validateRenderable(renderable)\n\n if (rebuildRequired) {\n break\n }\n }\n\n renderGroup.structureDidChange = rebuildRequired\n\n return rebuildRequired\n}","import { Matrix } from \"@/maths\";\nimport { CanvasRenderer } from \"@/renderer\";\nimport { Container, RenderGroup } from \"@/scene\";\nimport { clearList } from \"@/scene/container/utils\";\nimport { updateRenderGroupTransform } from \"@/scene/container/utils/updateRenderGroupTransform\";\nimport { validateRenderables } from \"@/scene/container/utils/validateRenderables\";\n\nexport class RenderGroupSystem {\n public renderer: CanvasRenderer;\n\n static desc = {\n name: 'renderGroup'\n } as const\n\n constructor(renderer: CanvasRenderer) {\n this.renderer = renderer\n }\n\n private _updateRenderGroup(renderGroup: RenderGroup) {\n const renderer = this.renderer\n const renderPipes = renderer.renderPipes\n\n renderGroup.instructionSet.renderPipes = renderPipes\n\n // check renderable\n // renderable元素的属性变化会影响renderGroup\n // 决定是否需要重建指令集\n if (!renderGroup.structureDidChange) {\n // 有副作用,会修改renderGroup.structureDidChange\n validateRenderables(renderGroup, renderPipes)\n } else {\n clearList(renderGroup.childrenRenderablesToUpdate.list, 0)\n }\n\n // 更新\"所有\"元素的transform\n // 包括renderable元素\n updateRenderGroupTransform(renderGroup)\n\n if (renderGroup.structureDidChange) {\n renderGroup.structureDidChange = false\n\n this._buildInstructions(renderGroup, renderer)\n } else {\n\n }\n\n renderGroup.childrenRenderablesToUpdate.index = 0;\n }\n\n render({ container, transform }: { container: Container, transform: Matrix }) {\n const renderer = this.renderer\n\n if (transform) {\n container.renderGroup.localTransform.copyFrom(transform)\n }\n\n renderer.canvasContext.globalTransform = transform ? container.renderGroup.localTransform : container.renderGroup.worldTransform\n\n this._updateRenderGroup(container.renderGroup)\n\n executeInstructions(container.renderGroup, renderer.renderPipes)\n }\n\n _buildInstructions(renderGroup: RenderGroup, renderer: CanvasRenderer) {\n const renderPipes = renderer.renderPipes\n const root = renderGroup.root\n renderGroup.instructionSet.reset()\n\n if (root.sortableChildren) {\n root.sortChildren()\n }\n\n renderPipes.batch.buildStart()\n // renderPipes.batch = new BatchPipe()\n\n root.collectRenderablesWithEffects(renderPipes, renderGroup.instructionSet)\n\n renderPipes.batch.buildEnd(renderGroup.instructionSet)\n }\n\n}\n\nfunction executeInstructions(renderGroup: RenderGroup, renderPipes: any) {\n const { instructionSet } = renderGroup\n const instructions = instructionSet.instructions\n\n for (let i = 0; i < instructionSet.instructionSize; i++) {\n const instruction = instructions[i]\n const pipe = renderPipes[instruction.renderPipeId]\n pipe.execute(instruction)\n }\n}\n","import { CanvasRenderer } from \"@/renderer\";\nimport { Sprite } from \"./Sprite\";\nimport { InstructionSet } from \"@/renderer/InstructionSet\";\n\nexport class SpritePipe {\n private _renderer: CanvasRenderer\n static desc = {\n name: 'sprite',\n } as const\n\n constructor(renderer: CanvasRenderer) {\n this._renderer = renderer\n }\n\n addRenderable(sprite: Sprite, instructionSet: InstructionSet) {\n this._renderer.renderPipes.batch.addToBatch({\n renderable: sprite,\n texture: sprite.texture,\n transform: sprite.relativeGroupTransform,\n bounds: sprite.bounds,\n roundPixels: this._renderer._roundPixels | sprite._roundPixels,\n }, instructionSet)\n }\n\n public destroy() {\n this._renderer = null\n }\n}\n","import { CanvasRenderer } from \"@/renderer\";\nimport { Text } from \"./Text\";\nimport { InstructionSet } from \"@/renderer/InstructionSet\";\nimport { updateBounds } from \"@/utils\";\nimport { Texture } from \"@/main\";\n\nexport class TextPipe {\n public static desc = {\n name: 'text',\n } as const\n\n private _renderer: CanvasRenderer;\n\n constructor(renderer: CanvasRenderer) {\n this._renderer = renderer\n }\n\n addRenderable(text: Text, instructionSet: InstructionSet) {\n const batchableText = this._getRuntimeText(text)\n\n if (text._didTextUpdate) {\n const resolution = text._autoResolution ? this._renderer.resolution : text.resolution\n if (batchableText.currentKey !== text.styleKey || text._resolution !== resolution) {\n this._updateRuntimeText(text)\n }\n text._didTextUpdate = false\n updateBounds(batchableText.bounds, text._anchor, batchableText.texture)\n }\n\n this._renderer.renderPipes.batch.addToBatch(batchableText, instructionSet)\n }\n\n validateRenderable(text: Text) {\n const batchableText = this._getRuntimeText(text)\n\n const newKey = text.styleKey\n\n if (batchableText.currentKey !== newKey) return true\n\n return text._didTextUpdate\n }\n\n public initCacheText(text: Text) {\n const batchableText = {\n currentKey: '--',\n transform: text.relativeGroupTransform,\n bounds: text.bounds,\n roundPixels: this._renderer._roundPixels | text._roundPixels,\n renderable: text,\n texture: null as Texture | null,\n destroy: function () {\n this.renderable = null;\n this.texture = null;\n this.bounds = null;\n }\n }\n\n text._runtimeData[this._renderer.uid] = batchableText\n // TODO: gc\n\n return batchableText\n }\n\n private _getRuntimeText(text: Text) {\n return text._runtimeData[this._renderer.uid] || this.initCacheText(text)\n }\n\n private _updateRuntimeText(text: Text) {\n const batchableText = this._getRuntimeText(text)\n\n if (batchableText.texture) {\n // TODO: gc texture\n }\n\n text._resolution = text._autoResolution ? this._renderer.resolution : text.resolution\n\n batchableText.texture = this._renderer.text.getManagedTexture(text)\n batchableText.currentKey = text.styleKey\n }\n\n public destroy() {\n this._renderer = null\n }\n}\n","import { Bounds } from \"@/maths/Bounds\"\nimport { Container } from \"./container/Container\"\nimport { Vector2 } from \"@/maths\"\nimport { InstructionSet } from \"@/renderer/InstructionSet\"\nimport { DestroyOptions } from \"./container/destroyTypes\"\n\nexport type Renderable = ViewContainer\n\nexport interface RuntimeData {\n destroy: () => void\n}\n\nexport abstract class ViewContainer<RUNTIME_DATA extends RuntimeData = any> extends Container {\n public _runtimeData: Record<number, RUNTIME_DATA> = Object.create(null)\n\n /** @internal */\n public _resolution: number\n public _roundPixels: 0 | 1 = 0\n protected _bounds = new Bounds(0, 1, 0, 0)\n public get bounds() {\n this.updateBounds()\n\n return this._bounds\n }\n\n protected abstract updateBounds(): void\n\n protected onViewUpdate() {\n if (this.didViewUpdate) return\n this.didViewUpdate = true\n\n const renderGroup = this.renderGroup || this.parentRenderGroup\n\n if (renderGroup) {\n renderGroup.onChildViewUpdate(this)\n }\n }\n\n override collectRenderableSimple(renderPipes: Record<string, any>, instructionSet: InstructionSet): void {\n const pipe = renderPipes[this.renderPipeId]\n if (pipe && pipe.addRenderable) {\n pipe.addRenderable(this, instructionSet)\n }\n this.didViewUpdate = false\n\n const children = this.children\n\n for (let i = 0; i < children.length; ++i) {\n children[i].collectRenderables(renderPipes, instructionSet)\n }\n // switch (this.renderPipeId) {\n // case 'sprite':\n // renderPipes.batch.addRenderable(this)\n // break\n // case 'graphics':\n // instructionSet.push(this)\n // break\n // }\n // if (this.re)\n // batch.addRenderable(this)\n }\n\n containsPoint(point: Vector2) {\n const bounds = this.bounds\n const { x, y } = point\n\n return (x > bounds.minX && x < bounds.maxX && y > bounds.minY && y < bounds.maxY)\n }\n\n get roundPixels(): boolean {\n return !!this._roundPixels\n }\n set roundPixels(value: boolean) {\n this._roundPixels = value ? 1 : 0\n }\n\n override destroy(options: DestroyOptions = false) {\n for (const key in this._runtimeData) {\n this._runtimeData[key].destroy()\n }\n this._runtimeData = Object.create(null)\n this.onViewUpdate()\n\n super.destroy(options)\n this._bounds = null\n }\n}","import { Rectangle } from \"./Rectangle\"\n\nexport class Polygon {\n public points: number[] = []\n public closePath: boolean\n\n public readonly type = 'polygon'\n\n construction() {\n\n }\n\n get lastX() {\n return this.points[this.points.length - 2]\n }\n\n get lastY() {\n return this.points[this.points.length - 1]\n }\n\n public getBounds() {\n const out = new Rectangle()\n\n const points = this.points\n\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n\n for (let i = 0; i < points.length; i += 2) {\n const x = points[i]\n const y = points[i + 1]\n\n minX = Math.min(minX, x)\n minY = Math.min(minY, y)\n maxX = Math.max(maxX, x)\n maxY = Math.max(maxY, y)\n }\n\n out.x = minX\n out.width = maxX - minX\n\n out.y = minY\n out.height = maxY - minY\n\n return out\n }\n}","// thanks to https://github.com/mattdesl/adaptive-bezier-curve\n// for the original code!\nconst RECURSION_LIMIT = 8;\nconst FLT_EPSILON = 1.19209290e-7;\nconst PATH_DISTANCE_EPSILON = 1.0;\n\nconst curveAngleToleranceEpsilon = 0.01;\nconst mAngleTolerance = 0;\nconst mCuspLimit = 0;\n\n/**\n * @param points\n * @param sX\n * @param sY\n * @param cp1x\n * @param cp1y\n * @param cp2x\n * @param cp2y\n * @param eX\n * @param eY\n * @param smoothness\n * @internal\n */\nexport function buildAdaptiveBezier(\n points: number[],\n sX: number, sY: number,\n cp1x: number, cp1y: number,\n cp2x: number, cp2y: number,\n eX: number, eY: number,\n smoothness?: number,\n)\n{\n // TODO expose as a parameter\n const scale = 1;\n const smoothing = Math.min(\n 0.99, // a value of 1.0 actually inverts smoothing, so we cap it at 0.99\n Math.max(0, smoothness ?? 0.5)\n );\n let distanceTolerance = (PATH_DISTANCE_EPSILON - smoothing) / scale;\n\n distanceTolerance *= distanceTolerance;\n begin(sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, points, distanceTolerance);\n\n return points;\n}\n\n// //// Based on:\n// //// https://github.com/pelson/antigrain/blob/master/agg-2.4/src/agg_curves.cpp\n\nfunction begin(\n sX: number, sY: number,\n cp1x: number, cp1y: number,\n cp2x: number, cp2y: number,\n eX: number, eY: number,\n points: number[],\n distanceTolerance: number\n)\n{\n // dont need to actually ad this!\n // points.push(sX, sY);\n recursive(sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, points, distanceTolerance, 0);\n points.push(eX, eY);\n}\n\n// eslint-disable-next-line max-params\nfunction recursive(\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n x4: number, y4: number,\n points: number[],\n distanceTolerance: number,\n level: number)\n{\n if (level > RECURSION_LIMIT)\n { return; }\n\n const pi = Math.PI;\n\n // Calculate all the mid-points of the line segments\n // ----------------------\n const x12 = (x1 + x2) / 2;\n const y12 = (y1 + y2) / 2;\n const x23 = (x2 + x3) / 2;\n const y23 = (y2 + y3) / 2;\n const x34 = (x3 + x4) / 2;\n const y34 = (y3 + y4) / 2;\n const x123 = (x12 + x23) / 2;\n const y123 = (y12 + y23) / 2;\n const x234 = (x23 + x34) / 2;\n const y234 = (y23 + y34) / 2;\n const x1234 = (x123 + x234) / 2;\n const y1234 = (y123 + y234) / 2;\n\n if (level > 0)\n { // Enforce subdivision first time\n // Try to approximate the full cubic curve by a single straight line\n // ------------------\n let dx = x4 - x1;\n let dy = y4 - y1;\n\n const d2 = Math.abs(((x2 - x4) * dy) - ((y2 - y4) * dx));\n const d3 = Math.abs(((x3 - x4) * dy) - ((y3 - y4) * dx));\n\n let da1; let da2;\n\n if (d2 > FLT_EPSILON && d3 > FLT_EPSILON)\n {\n // Regular care\n // -----------------\n if ((d2 + d3) * (d2 + d3) <= distanceTolerance * ((dx * dx) + (dy * dy)))\n {\n // If the curvature doesn't exceed the distanceTolerance value\n // we tend to finish subdivisions.\n // ----------------------\n if (mAngleTolerance < curveAngleToleranceEpsilon)\n {\n points.push(x1234, y1234);\n\n return;\n }\n\n // Angle & Cusp Condition\n // ----------------------\n const a23 = Math.atan2(y3 - y2, x3 - x2);\n\n da1 = Math.abs(a23 - Math.atan2(y2 - y1, x2 - x1));\n da2 = Math.abs(Math.atan2(y4 - y3, x4 - x3) - a23);\n if (da1 >= pi) da1 = (2 * pi) - da1;\n if (da2 >= pi) da2 = (2 * pi) - da2;\n\n if (da1 + da2 < mAngleTolerance)\n {\n // Finally we can stop the recursion\n // ----------------------\n points.push(x1234, y1234);\n\n return;\n }\n\n if (mCuspLimit !== 0.0)\n {\n if (da1 > mCuspLimit)\n {\n points.push(x2, y2);\n\n return;\n }\n\n if (da2 > mCuspLimit)\n {\n points.push(x3, y3);\n\n return;\n }\n }\n }\n }\n else if (d2 > FLT_EPSILON)\n {\n // p1,p3,p4 are collinear, p2 is considerable\n // ----------------------\n if (d2 * d2 <= distanceTolerance * ((dx * dx) + (dy * dy)))\n {\n if (mAngleTolerance < curveAngleToleranceEpsilon)\n {\n points.push(x1234, y1234);\n\n return;\n }\n\n // Angle Condition\n // ----------------------\n da1 = Math.abs(Math.atan2(y3 - y2, x3 - x2) - Math.atan2(y2 - y1, x2 - x1));\n if (da1 >= pi) da1 = (2 * pi) - da1;\n\n if (da1 < mAngleTolerance)\n {\n points.push(x2, y2);\n points.push(x3, y3);\n\n return;\n }\n\n if (mCuspLimit !== 0.0)\n {\n if (da1 > mCuspLimit)\n {\n points.push(x2, y2);\n\n return;\n }\n }\n }\n }\n else if (d3 > FLT_EPSILON)\n {\n // p1,p2,p4 are collinear, p3 is considerable\n // ----------------------\n if (d3 * d3 <= distanceTolerance * ((dx * dx) + (dy * dy)))\n {\n if (mAngleTolerance < curveAngleToleranceEpsilon)\n {\n points.push(x1234, y1234);\n\n return;\n }\n\n // Angle Condition\n // ----------------------\n da1 = Math.abs(Math.atan2(y4 - y3, x4 - x3) - Math.atan2(y3 - y2, x3 - x2));\n if (da1 >= pi) da1 = (2 * pi) - da1;\n\n if (da1 < mAngleTolerance)\n {\n points.push(x2, y2);\n points.push(x3, y3);\n\n return;\n }\n\n if (mCuspLimit !== 0.0)\n {\n if (da1 > mCuspLimit)\n {\n points.push(x3, y3);\n\n return;\n }\n }\n }\n }\n else\n {\n // Collinear case\n // -----------------\n dx = x1234 - ((x1 + x4) / 2);\n dy = y1234 - ((y1 + y4) / 2);\n if ((dx * dx) + (dy * dy) <= distanceTolerance)\n {\n points.push(x1234, y1234);\n\n return;\n }\n }\n }\n\n // Continue subdivision\n // ----------------------\n recursive(x1, y1, x12, y12, x123, y123, x1234, y1234, points, distanceTolerance, level + 1);\n recursive(x1234, y1234, x234, y234, x34, y34, x4, y4, points, distanceTolerance, level + 1);\n}\n\n","import { Polygon } from \"@/maths/shapes/Polygon\";\nimport { GraphicsPath } from \"./GraphicsPath\";\nimport { Bounds } from \"@/maths/Bounds\";\nimport { buildAdaptiveBezier } from \"./buildAdaptiveBezier\";\nimport { Rectangle } from \"@/maths\";\n\nexport interface ShapePrimitive {\n type: 'rectangle' | 'polygon'\n getBounds(): Rectangle;\n}\n\nexport class ShapePath {\n private _currentPoly: Polygon | null\n public shapePrimitives: { shape: ShapePrimitive }[] = []\n private _graphicsPath: GraphicsPath\n private _bounds: Bounds = new Bounds()\n constructor(graphicsPath: GraphicsPath) {\n this._graphicsPath = graphicsPath\n }\n\n private _ensurePoly(start = true) {\n if (this._currentPoly) return\n\n this._currentPoly = new Polygon()\n\n if (start) {\n // TODO: last shape\n // const lastShape = this.shapePrimitives[this.shapePrimitives.length - 1]\n // if (lastShape) {\n\n // }\n\n this._currentPoly.points.push(0, 0)\n }\n }\n\n public lineTo(x: number, y: number) {\n this._ensurePoly()\n\n const points = this._currentPoly.points\n\n const fromX = points[points.length - 2]\n const fromY = points[points.length - 1]\n\n if (fromX !== x || fromY !== y) {\n points.push(x, y)\n }\n return this\n }\n\n public rect(x: number, y: number, w: number, h: number) {\n this.drawShape(new Rectangle(x, y, w, h))\n\n return this\n }\n\n public drawShape(shape: Rectangle) {\n this.endPloy()\n\n this.shapePrimitives.push({ shape })\n return this\n }\n\n public moveTo(x: number, y: number) {\n this.startPoly(x, y)\n return this\n }\n\n public bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number, smoothness?: number) {\n this._ensurePoly()\n\n const points = this._currentPoly.points\n\n buildAdaptiveBezier(\n points,\n this._currentPoly.lastX,\n this._currentPoly.lastY,\n cp1x, cp1y,\n cp2x, cp2y,\n x, y,\n smoothness\n )\n \n return this\n }\n\n public startPoly(x: number, y: number) {\n if (this._currentPoly) {\n this.endPloy()\n }\n\n this._currentPoly = new Polygon()\n this._currentPoly.points.push(x, y)\n return this\n }\n\n public endPloy(closePath = false) {\n const shape = this._currentPoly\n \n if (shape && shape.points.length > 2) {\n shape.closePath = closePath\n\n this.shapePrimitives.push({ shape })\n }\n this._currentPoly = null\n }\n\n public closePath() {\n this.endPloy(true)\n return this\n }\n\n buildPath() {\n const path = this._graphicsPath\n\n for (let i = 0; i < path.instructions.length; ++i) {\n const instruction = path.instructions[i]\n\n this[instruction.action](...(instruction.data as [number, number, number, number, number, number?]))\n }\n\n return this\n }\n\n get bounds() {\n const bounds = this._bounds\n bounds.clear()\n\n const shapePrimitives = this.shapePrimitives\n\n for (let i = 0; i < shapePrimitives.length; ++i) {\n const shapePrimitive = shapePrimitives[i]\n\n const boundRect = shapePrimitive.shape.getBounds()\n\n // TODO: transform\n\n bounds.addRect(boundRect)\n }\n\n return bounds\n }\n}\n","import { Bounds } from \"@/maths/Bounds\"\nimport { ShapePath } from \"./ShapePath\"\n\ntype PathInstruction = {\n action: 'moveTo' | 'lineTo' | 'closePath' | 'bezierCurveTo' | 'rect'\n data: any[]\n}\nexport class GraphicsPath {\n public instructions: PathInstruction[] = []\n private _dirty = true\n private _shapePath: ShapePath\n\n public rect(x: number, y: number, w: number, h: number) {\n this.instructions.push({ action: 'rect', data: [x, y, w, h]})\n this._dirty = true\n return this\n }\n public lineTo(...args: [number, number]) {\n this.instructions.push({ action: 'lineTo', data: args })\n this._dirty = true\n return this\n }\n\n public bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number, smoothness?: number): this\n public bezierCurveTo(...args: number[]) {\n this.instructions.push({ action: 'bezierCurveTo', data: args })\n return this\n }\n\n public moveTo(...args: [number, number]) {\n this.instructions.push({ action: 'moveTo', data: args })\n return this\n }\n public closePath() {\n this.instructions.push({ action: 'closePath', data: [] })\n this._dirty = true\n return this\n\n }\n\n get shapePath() {\n if (!this._shapePath) {\n this._shapePath = new ShapePath(this)\n }\n\n if (this._dirty) {\n this._dirty = false\n this._shapePath.buildPath()\n }\n\n return this._shapePath\n }\n\n get bounds(): Bounds {\n return this.shapePath.bounds\n }\n\n getLastPoint() {\n let index = this.instructions.length - 1\n\n const lastInstruction = this.instructions[index]\n\n if (!lastInstruction) {\n return { x: 0, y: 0 }\n }\n\n switch (lastInstruction.action) {\n case 'moveTo':\n case 'lineTo':\n return {\n x: lastInstruction.data[0],\n y: lastInstruction.data[1],\n }\n }\n\n return {\n x: 0,\n y: 0\n }\n }\n\n clear() {\n this.instructions.length = 0\n this._dirty = true\n }\n\n clone() {\n const newPath = new GraphicsPath()\n\n newPath.instructions = this.instructions.slice()\n return newPath\n }\n}\n","import { Bounds } from \"@/maths/Bounds\"\nimport { GraphicsPath } from \"./path/GraphicsPath\"\n\ninterface StrokeAttributes {\n width?: number\n /**\n * 1: inside\n * 0.5: center\n * 0: outside\n */\n alignment?: number\n cap?: 'butt' | 'round' | 'square'\n join?: 'round' | 'bevel' | 'miter'\n miterLimit?: number\n pixelLine?: boolean\n alpha?: number\n}\n\ninterface FillStyle {\n color?: string\n}\n\ntype FillInstruction = {\n action: 'fill',\n data: { style: ConvertedFillStyle, path: GraphicsPath }\n}\ntype StrokeInstruction = {\n action: 'stroke',\n data: { style: ConvertedStrokeStyle, path: GraphicsPath }\n}\ntype GraphicsInstruction = FillInstruction | StrokeInstruction\n\ntype ConvertedStrokeStyle = Required<StrokeAttributes & Omit<Required<FillStyle>, 'color'> & { color: string }>\ntype ConvertedFillStyle = { color: string, alpha: number }\n\nexport class GraphicsContext {\n _strokeStyle: ConvertedStrokeStyle\n\n static defaultStrokeStyle: ConvertedStrokeStyle = {\n width: 1,\n color: '#ffffff',\n alignment: 0.5,\n miterLimit: 10,\n cap: 'butt',\n join: 'miter',\n pixelLine: false,\n alpha: 1,\n }\n\n private _activePath = new GraphicsPath()\n private _bounds = new Bounds()\n public instructions: GraphicsInstruction[] = []\n\n setStrokeStyle(style: StrokeAttributes & FillStyle) {\n this._strokeStyle = toStrokeStyle(style, GraphicsContext.defaultStrokeStyle)\n }\n\n moveTo(x: number, y: number) {\n this._activePath.moveTo(x, y)\n return this\n }\n\n lineTo(x: number, y: number) {\n this._activePath.lineTo(x, y)\n return this\n }\n\n bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number, smoothness?: number) {\n this._activePath.bezierCurveTo(\n cp1x, cp1y, cp2x, cp2y, x, y, smoothness\n )\n return this\n }\n\n rect(x: number, y: number, w: number, h: number) {\n this._activePath.rect(x, y, w, h)\n return this\n }\n\n beginPath() {\n this._activePath = new GraphicsPath()\n return this\n }\n\n closePath() {\n this._activePath.closePath()\n return this\n }\n\n fill(color: string) {\n const fillStyle = {\n ...(GraphicsContext.defaultStrokeStyle),\n color,\n }\n this.instructions.push({\n action: 'fill',\n data: { style: fillStyle, path: this._activePath.clone() }\n })\n return this\n }\n\n stroke() {\n this.instructions.push({\n action: 'stroke',\n data: { style: this._strokeStyle, path: this._activePath.clone() }\n })\n this._initNextPathLocation()\n }\n\n private _initNextPathLocation() {\n const { x, y } = this._activePath.getLastPoint()\n this._activePath.clear()\n this._activePath.moveTo(x, y)\n }\n \n get bounds() {\n // TODO: dirty\n\n const bounds = this._bounds\n bounds.clear()\n\n for (let i = 0; i < this.instructions.length; ++i) {\n const instruction = this.instructions[i]\n const action = instruction.action\n\n if (action === 'fill') {\n const data = instruction.data\n bounds.addBounds(data.path.bounds)\n } else if (action === 'stroke') {\n const data = instruction.data\n const alignment = data.style.alignment\n\n const outerPadding = data.style.width * (1 - alignment)\n\n if (data.style.join === 'miter') {\n // TODO: cal miter\n }\n\n const _bounds = data.path.bounds\n\n bounds.addFrame(\n _bounds.minX - outerPadding,\n _bounds.minY - outerPadding,\n _bounds.maxX + outerPadding,\n _bounds.maxY + outerPadding,\n )\n }\n }\n\n return bounds\n }\n\n public clone() {\n const clone = new GraphicsContext()\n\n clone.instructions = this.instructions.slice()\n clone._activePath = this._activePath.clone()\n clone._bounds = this._bounds.clone()\n clone._strokeStyle = { ...this._strokeStyle }\n\n return clone\n }\n}\n\nfunction toStrokeStyle(style: StrokeAttributes & FillStyle, defaultStyle: ConvertedStrokeStyle) {\n return {\n ...defaultStyle,\n ...style,\n }\n}\n","import { ViewContainer } from \"../ViewContainer\";\nimport { GraphicsContext } from \"./GraphicsContext\";\n\nexport class Graphics extends ViewContainer {\n public override renderPipeId: string = 'graphics'\n context: GraphicsContext\n constructor(options?: GraphicsContext) {\n super()\n if (options instanceof GraphicsContext) {\n this.context = options\n } else {\n this.context = new GraphicsContext()\n }\n }\n\n setStrokeStyle(...args: Parameters<GraphicsContext['setStrokeStyle']>) {\n return this._callContextMethod('setStrokeStyle', args)\n }\n\n rect(x: number, y: number, w: number, h: number): this\n rect(...args: Parameters<GraphicsContext['rect']>) {\n return this._callContextMethod('rect', args)\n }\n\n bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cpy2y: number, x: number, y: number): this\n bezierCurveTo(...args: Parameters<GraphicsContext['bezierCurveTo']>) {\n return this._callContextMethod('bezierCurveTo', args)\n }\n\n lineTo(...args: Parameters<GraphicsContext['lineTo']>) {\n return this._callContextMethod('lineTo', args)\n }\n\n moveTo(...args: Parameters<GraphicsContext['moveTo']>) {\n return this._callContextMethod('moveTo', args)\n }\n\n stroke(...args: Parameters<GraphicsContext['stroke']>) {\n return this._callContextMethod('stroke', args)\n }\n\n beginPath(): this {\n return this._callContextMethod('beginPath', [])\n }\n\n closePath(): this {\n return this._callContextMethod('closePath', [])\n }\n\n fill(color: string): this {\n return this._callContextMethod('fill', [color])\n }\n\n private _callContextMethod(method: keyof GraphicsContext, args: any[]) {\n (this.context as any)[method](...args)\n\n return this\n }\n protected updateBounds(): void {}\n\n override get bounds() {\n return this.context.bounds\n }\n}","import { CanvasRenderer } from \"@/renderer\"\nimport { Graphics } from \"./Graphics\"\nimport { InstructionSet } from \"@/renderer/InstructionSet\"\nimport { Polygon } from \"@/maths/shapes/Polygon\"\nimport { ShapePrimitive } from \"./path/ShapePath\"\nimport { Rectangle } from \"@/maths\"\n\nexport class GraphicsPipe {\n private _renderer: CanvasRenderer\n public static desc = {\n name: 'graphics',\n } as const\n\n constructor(renderer: CanvasRenderer) {\n this._renderer = renderer\n }\n\n addRenderable(graphics: Graphics, instructionSet: InstructionSet) {\n this._renderer.renderPipes.batch.break(instructionSet)\n instructionSet.add(graphics)\n }\n\n execute(instruction: Graphics) {\n const renderer = this._renderer\n const contextSystem = renderer.canvasContext\n\n const ctx = contextSystem.activeConext\n const roundPixels = renderer.roundPixels\n\n const groupColorAlpha = instruction.groupColorAlpha\n const groupAlpha = ((groupColorAlpha >>> 24) & 0xFF) / 255\n\n if (groupAlpha <= 0) return\n\n ctx.save()\n\n contextSystem.setContextTransform(\n instruction.relativeGroupTransform,\n roundPixels,\n )\n\n for (let i = 0; i < instruction.context.instructions.length; ++i) {\n const ins = instruction.context.instructions[i]\n const style = ins.data.style as any\n const alpha = style.alpha * groupAlpha\n if (alpha <= 0) continue\n\n ctx.globalAlpha = alpha\n const isStroke = ins.action === 'stroke'\n\n if (isStroke) {\n\n const canvasStyle = style.color\n ctx.lineWidth = style.width\n ctx.lineCap = style.cap\n ctx.lineJoin = style.join\n ctx.miterLimit = style.miterLimit\n ctx.strokeStyle = canvasStyle\n }\n else {\n const style = ins.data.style\n ctx.fillStyle = style.color\n }\n const shapePath = ins.data.path.shapePath\n const shapePrimitives = shapePath.shapePrimitives\n\n for (let s = 0; s < shapePrimitives.length; ++s) {\n const primitive = shapePrimitives[s]\n if (!primitive.shape) continue \n\n ctx.beginPath()\n buildShapePath(ctx, primitive.shape)\n if (isStroke) {\n ctx.stroke()\n } else {\n ctx.fill()\n }\n }\n // TODO: stroke geometry\n }\n\n\n ctx.restore()\n }\n\n public destroy() {\n this._renderer = null\n }\n}\n\nexport function buildShapePath(ctx: CanvasRenderingContext2D, shape: ShapePrimitive) {\n switch (shape.type) {\n case 'rectangle': {\n const rect = shape as Rectangle\n ctx.rect(rect.x, rect.y, rect.width, rect.height)\n break\n }\n case 'polygon': {\n const poly = shape as Polygon\n const points = poly.points\n if (!points.length) return\n\n ctx.moveTo(points[0], points[1])\n for (let i = 2; i < points.length; i += 2) {\n ctx.lineTo(points[i], points[i + 1])\n }\n if (poly.closePath) {\n ctx.closePath()\n }\n break\n }\n }\n}\n","import { CanvasRenderer } from \"@/renderer\";\nimport { Batcher } from \"./Batcher\";\nimport { Matrix } from \"@/maths\";\nimport { Instruction, InstructionSet } from \"@/renderer/InstructionSet\";\nimport { Container } from \"@/main\";\nimport { Bounds } from \"@/maths/Bounds\";\nimport { Texture } from \"@/renderer/texture/Texture\";\n\nexport type BatchableElement = {\n renderable: Container\n texture: Texture\n transform: Matrix\n bounds: Bounds\n roundPixels: number\n getColor: () => number\n}\n\nexport class Batch implements Instruction {\n renderPipeId: string = 'batch'\n\n elements: BatchableElement[] = []\n}\n\nexport class BatchPipe {\n private _renderer: CanvasRenderer\n private _activeBatch: Batcher\n\n public static desc = {\n name: 'batch',\n } as const\n\n constructor(renderer: CanvasRenderer) {\n this._renderer = renderer\n }\n\n get batch() {\n return this._activeBatch\n }\n\n buildStart() {\n this._activeBatch = new Batcher()\n }\n\n buildEnd(instructionSet: InstructionSet) {\n this.break(instructionSet)\n // this._activeBatch.build(instructionSet)\n }\n\n break(instructionSet: InstructionSet) {\n this._activeBatch.build(instructionSet)\n }\n\n addToBatch(batchElement: Omit<BatchableElement, 'getColor'>, _instructionSet: InstructionSet) {\n this._activeBatch.add({\n ...batchElement,\n getColor: () => batchElement.renderable.groupColorAlpha,\n })\n }\n\n execute(batch: Batch) {\n const elements = batch.elements\n\n if (!elements || !elements.length) return\n\n const renderer = this._renderer\n const contextSystem = renderer.canvasContext\n const ctx = contextSystem.activeConext\n\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i]\n const roundPixels = element.roundPixels\n const argb = element.getColor()\n const elementAlpha = ((argb >>> 24) & 0xFF) / 255\n\n const alpha = elementAlpha\n\n if (alpha <= 0) continue\n\n ctx.globalAlpha = alpha\n\n contextSystem.setContextTransform(\n element.transform,\n roundPixels === 1,\n )\n\n const bounds = element.bounds\n const texture = element.texture as Texture\n const frame = texture.frame\n const resolution = texture.source._resolution || 1\n const sx = frame.x * resolution\n const sy = frame.y * resolution\n const sw = frame.width * resolution\n const sh = frame.height * resolution\n const dx = bounds.minX\n const dy = bounds.minY\n const dw = bounds.maxX - bounds.minX\n const dh = bounds.maxY - bounds.minY\n\n // TODO: rotate\n const drawX = dx\n const drawY = dy\n const drawW = dw\n const drawH = dh\n\n ctx.drawImage(\n texture.source.resource,\n sx,\n sy,\n sw,\n sh,\n drawX,\n drawY,\n drawW,\n drawH,\n )\n }\n }\n\n public destroy() {\n this._renderer = null\n this._activeBatch?.destroy()\n this._activeBatch = null\n }\n}","import { InstructionSet } from \"@/renderer/InstructionSet\"\nimport { Batch, BatchableElement } from \"./BatcherPipe\"\n\nexport class Batcher {\n public renderPipeId = 'batch'\n public elements: BatchableElement[] = []\n public elementSize = 0\n\n add(elm: BatchableElement) {\n this.elements[this.elementSize++] = elm\n }\n\n build(instructionSet: InstructionSet) {\n const batch = new Batch()\n const elements = this.elements\n // TODO: Maybe need elementStart\n if (!elements[0]) return\n\n for (let i = 0; i < elements.length; i++) {\n const elm = elements[i]\n\n this.elements[i] = null\n batch.elements.push(elm)\n }\n instructionSet.add(batch)\n }\n\n public destroy() {\n this.elements = null\n }\n}\n","import { nextPow2 } from \"@/maths\";\n\nexport type CanvasAndContext = {\n canvas: HTMLCanvasElement | OffscreenCanvas\n context: CanvasRenderingContext2D\n}\n\nclass CanvasPoolClass {\n private _canvasPool: Record<string | number, CanvasAndContext[]>\n constructor() {\n this._canvasPool = Object.create(null)\n }\n public getOptimalCanvasAndContext(minWidth: number, minHeight: number, resolution = 1) {\n const _minWidth = nextPow2((minWidth * resolution) - 1e-6)\n const _minHeight = nextPow2((minHeight * resolution) - 1e-6)\n\n const key = _minWidth << 17 + _minHeight << 1\n \n if (!this._canvasPool[key]) {\n this._canvasPool[key] = []\n }\n\n const canvasAndContext = this._canvasPool[key].pop()\n\n if (!canvasAndContext) {\n const canvas = document.createElement('canvas')\n canvas.width = _minWidth\n canvas.height = _minHeight\n return { canvas, context: canvas.getContext('2d') }\n } else {\n return canvasAndContext\n }\n }\n}\n\nexport const CanvasPool = new CanvasPoolClass();\n","import { uid } from \"@/utils/uid\";\nimport { DestroyOptions } from \"../container/destroyTypes\";\n\n/**\n * The alignment of the text.\n *\n * - 'left': Aligns text to the left edge.\n * - 'center': Centers text horizontally.\n * - 'right': Aligns text to the right edge.\n * - 'justify': Justifies text, aligning both left and right edges.\n * @example\n * ```ts\n * import { TextStyle } from 'pixi.js';\n * const style = new TextStyle({\n * align: 'center', // or 'left', 'right', 'justify'\n * });\n * ```\n * @category text\n * @standard\n */\nexport type TextStyleAlign = 'left' | 'center' | 'right' | 'justify';\n/**\n * The font style input for text styles. Controls the slant or italicization of the text.\n * @example\n * ```ts\n * // Create text with normal font style\n * const normalText = new Text({\n * text: 'Normal Style Text',\n * style: {\n * fontStyle: 'normal',\n * fontSize: 24\n * }\n * });\n *\n * // Create italic text\n * const italicText = new Text({\n * text: 'Italic Style Text',\n * style: {\n * fontStyle: 'italic',\n * fontSize: 24,\n * fontFamily: 'Arial'\n * }\n * });\n *\n * // Create oblique text\n * const obliqueText = new Text({\n * text: 'Oblique Style Text',\n * style: {\n * fontStyle: 'oblique',\n * fontSize: 24,\n * fontFamily: 'Times New Roman'\n * }\n * });\n *\n * // Dynamic style changes\n * let isItalic = false;\n * text.style = {\n * ...text.style,\n * fontStyle: isItalic ? 'italic' : 'normal'\n * };\n * ```\n *\n * Supported values:\n * - 'normal': Regular upright text with no slant\n * - 'italic': True italics using specifically designed italic glyphs\n * - 'oblique': Slanted version of the regular glyphs\n * @remarks\n * - 'italic' uses specially designed glyphs with cursive characteristics\n * - 'oblique' is a mechanical slant of the normal glyphs\n * - Not all fonts include true italic designs; some may fall back to oblique\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/font-style | MDN font-style}\n * @category text\n * @standard\n */\nexport type TextStyleFontStyle = 'normal' | 'italic' | 'oblique';\n/**\n * The font variant input for text styles. Controls the capitalization and presentation of letters.\n * Used to enable special rendering like small caps.\n * @example\n * ```ts\n * // Create text with normal font variant\n * const normalText = new Text({\n * text: 'Normal Text',\n * style: {\n * fontVariant: 'normal',\n * fontSize: 24\n * }\n * });\n *\n * // Create text with small-caps variant\n * const smallCapsText = new Text({\n * text: 'Small Caps Text',\n * style: {\n * fontVariant: 'small-caps',\n * fontSize: 24,\n * fontFamily: 'Arial'\n * }\n * });\n *\n * // Use in a TextStyle instance\n * const style = new TextStyle({\n * fontVariant: 'small-caps',\n * fontSize: 32,\n * fill: 0x4a4a4a\n * });\n *\n * // Update variant dynamically\n * text.style = {\n * ...text.style,\n * fontVariant: text.style.fontVariant === 'normal' ? 'small-caps' : 'normal'\n * };\n * ```\n *\n * Supported values:\n * - 'normal': Regular text rendering with standard capitalization\n * - 'small-caps': Renders lowercase letters as smaller versions of capital letters\n * @remarks\n * Small caps are only available if the font supports them.\n * Not all fonts include true small caps glyphs.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant | MDN font-variant}\n * @category text\n * @standard\n */\nexport type TextStyleFontVariant = 'normal' | 'small-caps';\n/**\n * The font weight input for text styles. Controls the thickness or boldness of the text.\n * @example\n * ```ts\n * // Create text with different font weights\n * const normalText = new Text({\n * text: 'Normal Weight',\n * style: { fontWeight: 'normal' }\n * });\n *\n * const boldText = new Text({\n * text: 'Bold Weight',\n * style: { fontWeight: 'bold' }\n * });\n *\n * // Using numeric weights\n * const lightText = new Text({\n * text: 'Light Weight',\n * style: { fontWeight: '300' }\n * });\n *\n * const mediumText = new Text({\n * text: 'Medium Weight',\n * style: { fontWeight: '500' }\n * });\n *\n * const heavyText = new Text({\n * text: 'Heavy Weight',\n * style: { fontWeight: '900' }\n * });\n *\n * // Responsive weight changes\n * const adaptiveText = new Text({\n * text: 'Adaptive Weight',\n * style: { fontWeight: window.innerWidth > 600 ? 'bold' : 'normal' }\n * });\n * ```\n *\n * Supported values:\n * - 'normal': Standard weight (equivalent to 400)\n * - 'bold': Bold weight (equivalent to 700)\n * - 'bolder': One weight darker than the parent element\n * - 'lighter': One weight lighter than the parent element\n * - '100': Thin (Hairline)\n * - '200': Extra Light (Ultra Light)\n * - '300': Light\n * - '400': Normal\n * - '500': Medium\n * - '600': Semi Bold (Demi Bold)\n * - '700': Bold\n * - '800': Extra Bold (Ultra Bold)\n * - '900': Heavy (Black)\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight | MDN font-weight}\n * @category text\n * @standard\n */\nexport type TextStyleFontWeight =\n | 'normal' // Standard weight (400)\n | 'bold' // Bold weight (700)\n | 'bolder' // Relative weight increase\n | 'lighter' // Relative weight decrease\n | '100' // Thin\n | '200' // Extra Light\n | '300' // Light\n | '400' // Normal\n | '500' // Medium\n | '600' // Semi Bold\n | '700' // Bold\n | '800' // Extra Bold\n | '900'; // Heavy\n/**\n * The line join style for text strokes. Determines how lines connect at corners.\n * @example\n * ```ts\n * // Create text with miter joins (sharp corners)\n * const sharpText = new Text({\n * text: 'Sharp Corners',\n * style: {\n * fontSize: 36,\n * stroke: {\n * color: '#4a1850',\n * width: 4,\n * lineJoin: 'miter' // Sharp corners\n * }\n * }\n * });\n *\n * // Create text with round joins\n * const roundText = new Text({\n * text: 'Rounded Corners',\n * style: {\n * fontSize: 36,\n * stroke: {\n * color: '#4a1850',\n * width: 4,\n * lineJoin: 'round' // Smooth rounded corners\n * }\n * }\n * });\n *\n * // Create text with beveled joins\n * const bevelText = new Text({\n * text: 'Beveled Corners',\n * style: {\n * fontSize: 36,\n * stroke: {\n * color: '#4a1850',\n * width: 4,\n * lineJoin: 'bevel' // Flattened corners\n * }\n * }\n * });\n * ```\n * Available values:\n * - 'miter': Creates sharp corners by extending the outer edges until they meet\n * - 'round': Creates smooth, rounded corners using a circular arc\n * - 'bevel': Creates flattened corners by filling an additional triangle between the outer edges\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin | MDN lineJoin}\n * @category text\n * @standard\n */\nexport type TextStyleLineJoin = 'miter' | 'round' | 'bevel';\n/**\n * The text baseline for text styles.\n *\n * This can be:\n * - 'alphabetic': The alphabetic baseline\n * - 'top': The top of the text\n * - 'hanging': The hanging baseline\n * - 'middle': The middle of the text\n * - 'ideographic': The ideographic baseline\n * - 'bottom': The bottom of the text\n * @category text\n * @standard\n */\nexport type TextStyleTextBaseline = 'alphabetic' | 'top' | 'hanging' | 'middle' | 'ideographic' | 'bottom';\n/**\n * Controls how whitespace (spaces, tabs, and line breaks) is handled within the text.\n * This affects text wrapping and spacing behavior.\n * @example\n * ```ts\n * // Normal mode (collapse spaces and newlines)\n * const normalText = new Text({\n * text: 'Hello World\\n\\nNew Line',\n * style: {\n * whiteSpace: 'normal',\n * fontSize: 24\n * }\n * }); // Renders as: \"Hello World New Line\"\n *\n * // Pre mode (preserve all whitespace)\n * const preText = new Text({\n * text: 'Hello World\\n\\nNew Line',\n * style: {\n * whiteSpace: 'pre',\n * fontSize: 24\n * }\n * }); // Preserves spaces and line breaks exactly\n *\n * // Pre-line mode (preserve newlines, collapse spaces)\n * const preLineText = new Text({\n * text: 'Hello World\\n\\nNew Line',\n * style: {\n * whiteSpace: 'pre-line',\n * fontSize: 24\n * }\n * }); // Preserves line breaks, collapses multiple spaces\n *\n * // With word wrap enabled\n * const wrappedText = new Text({\n * text: 'A long text with multiple spaces\\nand line breaks',\n * style: {\n * whiteSpace: 'pre-line',\n * wordWrap: true,\n * wordWrapWidth: 200,\n * fontSize: 24\n * }\n * });\n * ```\n *\n * Supported values:\n * - 'normal': Collapses all whitespace (spaces, tabs, line breaks) into a single space\n * - 'pre': Preserves all whitespace characters exactly as written\n * - 'pre-line': Preserves line breaks but collapses multiple spaces into a single space\n * @remarks\n * - 'normal' is best for single-line text or when you want to ignore formatting\n * - 'pre' is useful for code blocks or when exact spacing is important\n * - 'pre-line' is good for formatted text where you want to keep line breaks but clean up spaces\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/white-space | MDN white-space}\n * @see {@link TextStyle#wordWrap} For controlling text wrapping\n * @category text\n * @standard\n */\nexport type TextStyleWhiteSpace = 'normal' | 'pre' | 'pre-line';\n/**\n * Defines a drop shadow effect for text rendering.\n * Drop shadows add depth and emphasis to text by creating a shadow offset from the text.\n * @example\n * ```ts\n * // Create text with basic drop shadow\n * const text = new Text({\n * text: 'Shadow Text',\n * style: {\n * fontSize: 48,\n * dropShadow: {\n * alpha: 0.5, // 50% opacity shadow\n * angle: Math.PI / 6, // 30 degrees\n * blur: 4, // Soft shadow edge\n * color: '#000000', // Black shadow\n * distance: 6 // Shadow offset\n * }\n * }\n * });\n *\n * // Dynamic shadow updates\n * text.style.dropShadow = {\n * alpha: Math.sin(Date.now() / 1000) * 0.5 + 0.5, // Pulsing opacity\n * angle: Date.now() / 1000, // Rotating angle\n * blur: 4,\n * color: '#000000',\n * distance: 6\n * };\n * ```\n * @category text\n * @standard\n */\nexport type TextDropShadow = {\n /**\n * The opacity of the drop shadow.\n * - Range: 0 to 1\n * - 0 = fully transparent\n * - 1 = fully opaque\n * @example\n * ```ts\n * // Set drop shadow opacity to 50%\n * dropShadow: {\n * alpha: 0.5\n * }\n * ```\n * @default 1\n */\n alpha: number;\n\n /**\n * The angle of the drop shadow in radians.\n * - 0 = right\n * - Math.PI/2 = down\n * - Math.PI = left\n * - Math.PI*1.5 = up\n * @example\n * ```ts\n * // Set drop shadow angle to 30 degrees\n * dropShadow: {\n * angle: Math.PI / 6 // 30 degrees\n * }\n * ```\n * @default Math.PI/6 (30 degrees)\n */\n angle: number;\n\n /**\n * The blur radius of the shadow.\n * - 0 = sharp shadow\n * - Higher values = softer shadow\n * @example\n * ```ts\n * // Set drop shadow blur radius to 10 pixels\n * dropShadow: {\n * blur: 10\n * }\n * ```\n * @default 0\n */\n blur: number;\n\n /**\n * The color of the drop shadow.\n * Accepts any valid CSS color string, hex number, or RGB/RGBA values.\n * @example '#000000', 'rgba(0,0,0,0.5)', 0x000000\n * @default 'black'\n */\n color: string;\n\n /**\n * The distance of the drop shadow from the text.\n * Measured in pixels.\n * @example\n * ```ts\n * // Set drop shadow distance to 5 pixels\n * dropShadow: {\n * distance: 5\n * }\n * ```\n * @default 5\n */\n distance: number;\n};\n/**\n * Constructor options used for `TextStyle` instances. Defines the visual appearance and layout of text.\n * @example\n * ```ts\n * // Basic text style\n * const basicStyle = new TextStyle({\n * fontSize: 24,\n * fill: 'black',\n * fontFamily: 'Arial'\n * });\n *\n * // Rich text style with multiple features\n * const richStyle = new TextStyle({\n * fontFamily: ['Arial', 'Helvetica', 'sans-serif'],\n * fontSize: 36,\n * fontWeight: 'bold',\n * fill: 'red',\n * stroke: { color: '#4a1850', width: 5 },\n * align: 'center',\n * dropShadow: {\n * color: '#000000',\n * blur: 4,\n * distance: 6,\n * angle: Math.PI / 6\n * },\n * wordWrap: true,\n * wordWrapWidth: 440,\n * lineHeight: 40,\n * textBaseline: 'middle'\n * });\n * ```\n * @see {@link TextStyle} For the main style class\n * @category text\n * @standard\n */\nexport interface TextStyleOptions\n{\n /**\n * Alignment for multiline text, does not affect single line text\n * @default 'left'\n */\n align?: TextStyleAlign;\n /**\n * Whether to allow line breaks within words.\n * Requires wordWrap to be true.\n * @example\n * ```ts\n * // Enable word breaking\n * const style = new TextStyle({\n * breakWords: true,\n * wordWrap: true,\n * wordWrapWidth: 200\n * });\n * ```\n * @default false\n */\n breakWords?: boolean;\n /**\n * Drop shadow configuration for the text.\n * Can be boolean or a TextDropShadow object.\n * @default null\n */\n dropShadow?: boolean | Partial<TextDropShadow>;\n /**\n * Fill style for the text.\n * Can be a color, gradient, or pattern.\n * @default 'black'\n */\n fill?: string;\n /**\n * Font family or families to use.\n * Can be single name or array of fallbacks.\n * @example\n * ```ts\n * // Single font family\n * fontFamily: 'Arial'\n * // Multiple font families\n * fontFamily: ['Helvetica', 'Arial', 'sans-serif']\n * ```\n * @default 'Arial'\n */\n fontFamily?: string | string[];\n /**\n * Font size in pixels or as string.\n *\n * Equivalents are '26px','20pt','160%' or '1.6em')\n * @example\n * ```ts\n * // Numeric size\n * fontSize: 26\n * // String size\n * fontSize: '26px'\n * // Percentage size\n * fontSize: '160%' // 1.6 times the parent element's font size\n * // Em size\n * fontSize: '1.6em' // 1.6 times the parent element's font size\n * @default 26\n */\n fontSize?: number | string;\n /**\n * Font style (normal, italic, oblique).\n * @default 'normal'\n */\n fontStyle?: TextStyleFontStyle;\n /**\n * Font variant (normal, small-caps).\n * @default 'normal'\n */\n fontVariant?: TextStyleFontVariant;\n /**\n * Font weight (normal, bold, bolder, lighter, 100-900).\n * @default 'normal'\n */\n fontWeight?: TextStyleFontWeight;\n /** The height of the line, a number that represents the vertical space that a letter uses. */\n leading?: number;\n /** The amount of spacing between letters, default is 0 */\n letterSpacing?: number;\n /** The line height, a number that represents the vertical space that a letter uses */\n lineHeight?: number;\n /**\n * Padding around the text.\n *\n * Occasionally some fonts are cropped. Adding some padding will prevent this from\n * happening by adding padding to all sides of the text.\n */\n padding?: number;\n /**\n * Stroke style for text outline.\n * @default null\n */\n stroke?: string;\n /**\n * Vertical alignment baseline.\n * @default 'alphabetic'\n */\n textBaseline?: TextStyleTextBaseline;\n /**\n * Whether to trim transparent edges.\n * > [!NOTE] This is an expensive operation and should only be used when necessary.\n * @default false\n */\n trim?: boolean;\n /**\n * How to handle whitespace.\n *\n * It needs wordWrap to be set to true for this to have an effect.\n * @default 'pre'\n */\n whiteSpace?: TextStyleWhiteSpace;\n /** Indicates if word wrap should be used */\n wordWrap?: boolean;\n /** The width at which text will wrap, it needs wordWrap to be set to true */\n wordWrapWidth?: number;\n /**\n * Custom styles to apply to specific tags within the text.\n * Allows for rich text formatting using simple tag markup like `<red>text</red>`.\n *\n * Tags are only parsed when this property has entries. If `tagStyles` is empty or undefined,\n * `<` characters in text are treated as literal.\n *\n * Nested tags are supported via a style stack - inner tags inherit from outer tags\n * but can override specific properties.\n * @example\n * ```ts\n * const text = new Text({\n * text: '<red>Red</red>, <blue>Blue</blue>, <big>Big</big>',\n * style: {\n * fontFamily: 'Arial',\n * fontSize: 24,\n * fill: 'white',\n * tagStyles: {\n * red: { fill: 'red' },\n * blue: { fill: 'blue' },\n * big: { fontSize: 48 }\n * }\n * }\n * });\n * ```\n * @default undefined\n */\n tagStyles?: Record<string, TextStyleOptions>;\n}\n\nexport class TextStyle {\n public uid = uid('textStyle')\n public static defaultStyle: TextStyleOptions = {\n align: 'left',\n breakWords: false,\n dropShadow: null,\n fill: 'black',\n fontFamily: 'Arial',\n fontSize: 26,\n fontStyle: 'normal',\n fontVariant: 'normal',\n fontWeight: 'normal',\n leading: 0,\n letterSpacing: 0,\n lineHeight: 0,\n padding: 0,\n stroke: null,\n textBaseline: 'alphabetic',\n trim: false,\n whiteSpace: 'pre',\n wordWrap: false,\n wordWrapWidth: 100\n }\n\n private _cachedFontString: string\n private _fontSize: number\n private _fontFamily: string | string[]\n private _fontStyle: TextStyleFontStyle\n private _lineHeight: number\n private _leading: number\n private _fontVariant: TextStyleFontVariant\n private _fontWeight: TextStyleFontWeight\n private _letterSpacing: number\n private _textBaseline: TextStyleTextBaseline\n private _align: TextStyleAlign\n private _wordWrap: boolean\n private _fill: string\n\n public _tick = 0\n\n constructor(style: Partial<TextStyleOptions>) {\n const fullStyle = { ...TextStyle.defaultStyle, ...style }\n\n for (const key in fullStyle) {\n const thisKey = key as keyof typeof this\n this[thisKey] = fullStyle[key as keyof TextStyleOptions] as any\n }\n }\n\n public get styleKey(): string {\n return `${this.uid}-${this._tick}`;\n }\n\n get fontSize() {\n return this._fontSize\n }\n\n set fontSize(value: number) {\n if (this._fontSize === value) return\n\n this._fontSize = value\n this.update()\n }\n\n get fill() {\n return this._fill\n }\n\n set fill(value: string) {\n if (this._fill === value) return\n this._fill = value\n this.update()\n }\n\n get align() {\n return this._align\n }\n\n set align(value: TextStyleAlign) {\n if (this._align === value) return\n\n this._align = value\n this.update()\n }\n\n get wordWarp() {\n return this._wordWrap\n }\n\n set wordWrap(value: boolean) {\n if (this._wordWrap === value) return\n\n this._wordWrap = value\n this.update()\n }\n\n get fontFamily() {\n return this._fontFamily\n }\n\n set fontFamily(value: string | string[]) {\n if (this._fontFamily === value) return\n\n this._fontFamily = value\n this.update()\n }\n\n get leading() {\n return this._leading\n }\n set leading(value: number) {\n if (this._leading === value) return\n\n this._leading = value\n this.update()\n }\n\n get fontStyle() {\n return this._fontStyle\n }\n\n set fontStyle(value: TextStyleFontStyle) {\n if (this._fontStyle === value) return\n\n this._fontStyle = value.toLowerCase() as TextStyleFontStyle\n this.update()\n }\n\n get textBaseline() {\n return this._textBaseline\n }\n\n set textBaseline(value: TextStyleTextBaseline) {\n this._textBaseline = value\n this.update()\n }\n\n get lineHeight() {\n return this._lineHeight\n }\n\n set lineHeight(value: number) {\n if (this._lineHeight === value) return\n\n this._lineHeight = value\n this.update()\n }\n\n get letterSpacing() {\n return this._letterSpacing\n }\n\n set letterSpacing(value: number) {\n if (this._letterSpacing === value) return\n\n this._letterSpacing = value\n this.update()\n }\n\n get fontVariant() {\n return this._fontVariant\n }\n\n set fontVariant(value: TextStyleFontVariant) {\n if (this._fontVariant === value) return\n\n this._fontVariant = value\n this.update()\n }\n\n get fontWeight() {\n return this._fontWeight\n }\n\n set fontWeight(value: TextStyleFontWeight) {\n if (this._fontWeight === value) return\n\n this._fontWeight = value\n this.update()\n }\n\n get _fontString() {\n if (this._cachedFontString === null) {\n this._cachedFontString = fontStringFromTextStyle(this)\n }\n return this._cachedFontString\n }\n\n update() {\n this._tick++\n this._cachedFontString = null\n }\n\n public destroy(_options: DestroyOptions = false) {\n // const destroyTexture = typeof options === 'boolean' ? options : options?.texture\n\n // if (destroyTexture) {\n // const destroyTextureSource = typeof options === 'boolean' ? options : options?.textureSource\n // }\n this._fill = null\n }\n}\n\nconst genericFontFamilies = [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n];\nexport function fontStringFromTextStyle(style: TextStyle): string\n{\n // build canvas api font setting from individual components. Convert a numeric style.fontSize to px\n const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize;\n\n // Clean-up fontFamily property by quoting each font name\n // this will support font names with spaces\n let fontFamilies: string | string[] = style.fontFamily;\n\n if (!Array.isArray(style.fontFamily))\n {\n fontFamilies = style.fontFamily.split(',');\n }\n\n for (let i = fontFamilies.length - 1; i >= 0; i--)\n {\n // Trim any extra white-space\n let fontFamily = fontFamilies[i].trim();\n\n // Check if font already contains strings\n if (!(/([\\\"\\'])[^\\'\\\"]+\\1/).test(fontFamily) && !genericFontFamilies.includes(fontFamily))\n {\n fontFamily = `\"${fontFamily}\"`;\n }\n (fontFamilies as string[])[i] = fontFamily;\n }\n\n // eslint-disable-next-line max-len\n return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${(fontFamilies as string[]).join(',')}`;\n}\n","import { CanvasAndContext, CanvasPool } from \"@/renderer/CanvasPool\";\nimport { fontStringFromTextStyle, TextStyle } from \"./TextStyle\"\nimport { Rectangle } from \"@/maths/shapes/Rectangle\";\n\nexport const NEWLINE_MATCH_REGEX = /(?:\\r\\n|\\r|\\n)/;\n\n/**\n * A number, or a string containing a number.\n * @category text\n * @typedef {object} FontMetrics\n * @property {number} ascent - Font ascent\n * @property {number} descent - Font descent\n * @property {number} fontSize - Font size\n * @advanced\n */\nexport interface FontMetrics\n{\n ascent: number;\n descent: number;\n fontSize: number;\n}\n\nexport class TextMetrics {\n public text: string\n public style: TextStyle\n public width: number\n public height: number\n public lines: string[]\n public lineWidths: number[]\n public lineHeight: number\n public maxLineWidth: number\n public fontProperties: FontMetrics\n /**\n * String used for calculate font metrics.\n * These characters are all tall to help calculate the height required for text.\n */\n public static METRICS_STRING = '|ÉqÅ';\n\n /** Baseline symbol for calculate font metrics. */\n public static BASELINE_SYMBOL = 'M';\n private static _canvas: HTMLCanvasElement | OffscreenCanvas\n private static _context: CanvasRenderingContext2D\n // TODO tiny-lru\n private static readonly _measurementCache = new Map()\n /** Cache of {@link TextMetrics.FontMetrics} objects. */\n private static _fonts: Record<string, FontMetrics> = {};\n\n constructor(\n text: string,\n style: TextStyle,\n width: number,\n height: number,\n lines: string[],\n lineWidths: number[],\n lineHeight: number,\n maxLineWidth: number,\n fontProperties: FontMetrics\n ) {\n this.text = text\n this.style = style\n this.width = width\n this.height = height\n this.lines = lines\n this.lineWidths = lineWidths\n this.lineHeight = lineHeight\n this.maxLineWidth = maxLineWidth\n this.fontProperties = fontProperties\n }\n\n static get canvas() {\n if (!TextMetrics._canvas) {\n let canvas\n try {\n const c = new OffscreenCanvas(0, 0)\n const context = c.getContext('2d', { willReadFrequently: true })\n\n if (context.measureText) {\n TextMetrics._canvas = c\n return c\n }\n\n canvas = createCanvas(10, 10)\n } catch (_ctx) {\n canvas = createCanvas(10, 10)\n }\n TextMetrics._canvas = canvas\n }\n\n return TextMetrics._canvas\n }\n\n static get context() {\n if (!TextMetrics._context) {\n TextMetrics._context = TextMetrics.canvas.getContext('2d', { willReadFrequently: true }) as unknown as CanvasRenderingContext2D\n }\n return TextMetrics._context\n\n }\n\n static measureText(text: string, style: TextStyle): TextMetrics {\n const textKey = `${text}-${style.styleKey}`\n\n if (TextMetrics._measurementCache.has(textKey)) {\n return TextMetrics._measurementCache.get(textKey)\n }\n\n const font = style._fontString\n const fontProperties = TextMetrics.measureFont(font)\n // fallback in case UA disallow canvas data extraction\n if (fontProperties.fontSize === 0) {\n fontProperties.fontSize = style.fontSize as number;\n fontProperties.ascent = style.fontSize as number;\n fontProperties.descent = 0;\n }\n\n const context = TextMetrics.context\n context.font = font\n\n // TODO: wordWrap\n\n const lines = text.split(NEWLINE_MATCH_REGEX)\n const lineWidths = new Array<number>(lines.length)\n let maxLineWidth = 0\n\n for (let i = 0; i < lines.length; ++i) {\n const lineWidth = TextMetrics._measureText(lines[i], style.letterSpacing)\n\n lineWidths[i] = lineWidth\n maxLineWidth = Math.max(maxLineWidth, lineWidth)\n }\n\n // TODO: stroke\n const lineHeight = style.lineHeight || fontProperties.fontSize\n\n // TODO: adjust with stroke or shadow\n const width = maxLineWidth\n const baseHeight = Math.max(lineHeight, fontProperties.fontSize + (lines.length - 1) * (lineHeight + style.leading))\n // TODO: adjust with shadow\n const height = baseHeight\n\n const measurements = new TextMetrics(\n text,\n style,\n width,\n height,\n lines,\n lineWidths,\n lineHeight,\n maxLineWidth,\n fontProperties\n )\n TextMetrics._measurementCache.set(textKey, measurements)\n\n return measurements\n }\n\n public static _measureText(text: string, letterSpacing: number) {\n const context = TextMetrics.context\n context.letterSpacing = '0px'\n // @ts-expect-error: For Chrome < 94\n context.textLetterSpacing = letterSpacing\n\n const metrics = context.measureText(text)\n let metricWidth = metrics.width\n let letterSpacingVal = 0\n\n if (metricWidth > 0) {\n letterSpacingVal = (TextMetrics.graphemeSegmenter(text).length - 1) * letterSpacing\n metricWidth += letterSpacingVal\n }\n\n const actualBoundingBoxLeft = -(metrics.actualBoundingBoxLeft ?? 0);\n const actualBoundingBoxRight = metrics.actualBoundingBoxRight ?? 0;\n let boundsWidth = actualBoundingBoxRight - actualBoundingBoxLeft;\n\n if (metrics.width > 0)\n {\n boundsWidth += letterSpacingVal;\n }\n\n return Math.max(metricWidth, boundsWidth);\n }\n\n /**\n * A Unicode \"character\", or \"grapheme cluster\", can be composed of multiple Unicode code points,\n * such as letters with diacritical marks (e.g. `'\\u0065\\u0301'`, letter e with acute)\n * or emojis with modifiers (e.g. `'\\uD83E\\uDDD1\\u200D\\uD83D\\uDCBB'`, technologist).\n * The new `Intl.Segmenter` API in ES2022 can split the string into grapheme clusters correctly. If it is not available,\n * PixiJS will fallback to use the iterator of String, which can only spilt the string into code points.\n * If you want to get full functionality in environments that don't support `Intl.Segmenter` (such as Firefox),\n * you can use other libraries such as [grapheme-splitter]{@link https://www.npmjs.com/package/grapheme-splitter}\n * or [graphemer]{@link https://www.npmjs.com/package/graphemer} to create a polyfill. Since these libraries can be\n * relatively large in size to handle various Unicode grapheme clusters properly, PixiJS won't use them directly.\n */\n public static graphemeSegmenter: (s: string) => string[] = (() =>\n {\n if (typeof Intl?.Segmenter === 'function')\n {\n const segmenter = new Intl.Segmenter();\n\n return (s: string) =>\n {\n const segments = segmenter.segment(s);\n const result = [];\n\n let i = 0;\n\n for (const segment of segments)\n {\n result[i++] = (segment.segment);\n }\n\n return result;\n };\n }\n\n return (s: string) => [...s];\n })();\n\n /**\n * Calculates the ascent, descent and fontSize of a given font-style\n * @param font - String representing the style of the font\n * @returns Font properties object\n */\n public static measureFont(font: string): FontMetrics {\n // as this method is used for preparing assets, don't recalculate things if we don't need to\n if (TextMetrics._fonts[font])\n {\n return TextMetrics._fonts[font];\n }\n\n const context = TextMetrics.context;\n\n context.font = font;\n const metrics = context.measureText(TextMetrics.METRICS_STRING + TextMetrics.BASELINE_SYMBOL);\n\n const ascent = metrics.actualBoundingBoxAscent ?? 0;\n const descent = metrics.actualBoundingBoxDescent ?? 0;\n\n const properties = {\n ascent,\n descent,\n fontSize: ascent + descent\n };\n\n TextMetrics._fonts[font] = properties;\n\n return properties;\n }\n}\n\nexport function createCanvas(width?: number, height?: number) {\n const canvas = document.createElement('canvas')\n canvas.width = width\n canvas.height = height\n return canvas\n}\n\nexport function generateTextTexture(options: { text: string, style: TextStyle, resolution?: number, padding?: number }) {\n const { text, style, resolution = 1, padding = 0 } = options\n\n const measured = TextMetrics.measureText(text, style)\n\n const width = Math.ceil(Math.ceil(Math.max(1, measured.width) + padding * 2) * resolution)\n const height = Math.ceil(Math.ceil(Math.max(1, measured.height) + padding * 2) * resolution)\n\n const canvasAndContext = CanvasPool.getOptimalCanvasAndContext(width, height)\n\n renderTextToCanvas(style, resolution, padding, canvasAndContext, measured)\n\n return {\n canvasAndContext,\n frame: new Rectangle(0, 0, width, height)\n }\n}\n\nfunction renderTextToCanvas(\n style: TextStyle,\n resolution: number,\n padding: number,\n canvasAndContext: CanvasAndContext,\n measured: TextMetrics,\n) {\n const { context } = canvasAndContext\n\n const font = fontStringFromTextStyle(style)\n\n const {\n lines,\n lineHeight,\n lineWidths,\n maxLineWidth,\n fontProperties,\n } = measured\n\n // const height = canvas.height\n\n context.resetTransform()\n context.scale(resolution, resolution)\n context.textBaseline = style.textBaseline\n\n // TODO: stroke width\n\n context.font = font\n\n const linePositionYShift = Math.min(0, (lineHeight - fontProperties.fontSize) / 2)\n\n // TODO dropShadow\n // TODO: fill\n context.fillStyle = style.fill\n\n for (let i = 0; i < lines.length; ++i) {\n const linePositionX = getAlignmentOffset(lineWidths[i], maxLineWidth, style.align)\n const linePositionY = i * lineHeight + fontProperties.ascent + linePositionYShift\n\n let wordSpacing = 0\n\n if (style.align === 'justify' && style.wordWrap && i < lines.length - 1) {\n const spaces = countSpaces(lines[i])\n if (spaces > 0) {\n wordSpacing = (maxLineWidth - lineWidths[i]) / spaces\n }\n }\n\n drawLetterSpacing(\n lines[i],\n style,\n canvasAndContext,\n linePositionX + padding,\n linePositionY + padding,\n false,\n wordSpacing\n )\n }\n}\n\nfunction getAlignmentOffset(lineWidth: number, alignWidth: number, align: string) {\n if (align === 'right') {\n return alignWidth - lineWidth\n } else if (align === 'center') {\n return (alignWidth - lineWidth) / 2\n }\n return 0\n}\n\nfunction countSpaces(text: string): number\n{\n let count = 0;\n\n for (let i = 0; i < text.length; i++)\n {\n if (text.charCodeAt(i) === 32) count++;\n }\n\n return count;\n}\n\nfunction drawLetterSpacing(\n text: string,\n style: TextStyle,\n canvasAndContext: CanvasAndContext,\n x: number, y: number,\n _isStroke = false,\n wordSpacing = 0\n) {\n const context = canvasAndContext.context\n\n const letterSpacing = style.letterSpacing\n\n if (letterSpacing === 0 && wordSpacing === 0) {\n context.fillText(text, x, y)\n return\n }\n if (wordSpacing !== 0 && letterSpacing === 0) {\n const words = text.split(' ')\n let currentPosition = x\n const spaceWidth = context.measureText(' ').width\n\n for (let i = 0; i < words.length; ++i) {\n context.fillText(words[i], currentPosition, y)\n currentPosition += context.measureText(words[i]).width + spaceWidth + wordSpacing\n }\n return\n }\n\n let currentPosition = x\n\n const stringArray = TextMetrics.graphemeSegmenter(text)\n let previousWidth = context.measureText(text).width\n let currentWidth = 0\n\n for (let i = 0; i < stringArray.length; ++i) {\n const currentChar = stringArray[i]\n context.fillText(currentChar, currentPosition, y)\n\n let textStr = ''\n\n for (let j = i + 1; j < stringArray.length; ++j) {\n textStr += stringArray[j]\n }\n currentWidth = context.measureText(textStr).width\n currentPosition += previousWidth - currentWidth + letterSpacing\n if (currentChar === '') currentPosition += wordSpacing\n previousWidth = currentWidth\n }\n}\n","import { createCanvas } from \"@/scene/text/utils\"\nimport EventEmitter from \"eventemitter3\"\n\nexport type TextureSourceOptions<T extends Record<string, any> = any> = {\n label?: string\n resource?: T,\n width?: number,\n height?: number,\n resolution?: number\n}\n\nexport class TextureSource<T extends Record<string, any> = any> extends EventEmitter {\n public static defaultOptions = {\n resolution: 1,\n }\n\n public label: string\n\n /**\n * @internal\n */\n public _resolution = 1\n\n /** the pixel width of this texture source. This is the REAL pure number, not accounting resolution */\n public pixelWidth = 1\n /** the pixel height of this texture source. This is the REAL pure number, not accounting resolution */\n public pixelHeight = 1\n\n /**\n */\n /**\n * the width of this texture source, accounting for resolution\n * eg pixelWidth 200, resolution 2, then width will be 100\n */\n public width = 1\n /**\n * the height of this texture source, accounting for resolution\n * eg pixelHeight 200, resolution 2, then height will be 100\n */\n public height = 1\n public resource: T\n\n public destroyed: boolean\n\n constructor(options: TextureSourceOptions<T>) {\n super()\n\n const _options = { ...TextureSource.defaultOptions, ...options }\n this.label = options.label\n\n this.resource = _options.resource\n this._resolution = _options.resolution\n\n if (_options.width) {\n this.pixelWidth = options.width * this._resolution\n } else {\n this.pixelWidth = this.resource ? (this.resourceWidth || 1) : 1\n }\n\n if (_options.height) {\n this.pixelHeight = options.height * this._resolution\n } else {\n this.pixelHeight = this.resource ? (this.resourceHeight || 1) : 1\n }\n\n this.width = this.pixelWidth / this._resolution\n this.height = this.pixelHeight / this._resolution\n\n this.destroyed = false\n }\n\n get resolution() {\n return this._resolution\n }\n\n set resolution(value: number) {\n if (this._resolution === value) return\n\n this._resolution = value\n\n this.width = this.pixelWidth / value\n this.height = this.pixelHeight / value\n }\n\n public get resourceWidth() {\n const resource = this.resource\n\n return resource.naturalWidth || resource.width\n }\n public get resourceHeight() {\n const resource = this.resource\n\n return resource.naturalHeight || resource.height\n }\n\n public resize(width?: number, height?: number, resolution?: number) {\n resolution ||= this._resolution\n width ||= this.width\n height ||= this.height\n\n const newPixelWidth = Math.round(width * resolution)\n const newPixelHeight = Math.round(height * resolution)\n\n this.width = newPixelWidth / resolution\n this.height = newPixelHeight / resolution\n\n this._resolution = resolution\n\n if (this.pixelWidth === newPixelWidth && this.pixelHeight === newPixelHeight) {\n return false\n }\n\n this.pixelWidth = newPixelWidth\n this.pixelHeight = newPixelHeight\n\n this.emit('resize', this)\n\n return true\n }\n\n public destroy() {\n this.destroyed = true\n this.resource = null\n\n this.emit('destroy', this)\n this.removeAllListeners()\n }\n}\n\nexport interface CanvasSourceOptions extends TextureSourceOptions<HTMLCanvasElement> {\n autoDensity?: boolean\n}\nexport class CanvasSource extends TextureSource<HTMLCanvasElement> {\n public autoDensity: boolean\n\n constructor(options?: CanvasSourceOptions) {\n if (!options.resource) {\n options.resource = createCanvas()\n }\n\n if (!options.width) {\n options.width = options.resource.width\n if (!options.autoDensity) {\n options.width /= options.resolution\n }\n }\n\n if (!options.height) {\n options.height = options.resource.height\n if (!options.autoDensity) {\n options.height /= options.resolution\n }\n }\n\n super(options)\n\n this.autoDensity = options.autoDensity\n\n this.resizeCanvas()\n }\n\n public resizeCanvas() {\n if (this.autoDensity) {\n this.resource.style.width = `${this.width}px`\n this.resource.style.height = `${this.height}px`\n }\n\n if (this.resource.width !== this.pixelWidth || this.resource.height !== this.pixelHeight) {\n this.resource.width = this.pixelWidth\n this.resource.height = this.pixelHeight\n }\n }\n\n public resize(width = this.width, height = this.height, resolution = this._resolution) {\n const didResize = super.resize(width, height, resolution)\n\n if (didResize) {\n this.resizeCanvas()\n }\n\n return didResize\n }\n}\n","import { Rectangle } from \"@/maths\"\nimport { TextureSource } from \"./TextureSource\"\nimport EventEmitter from \"eventemitter3\"\n\nexport interface TextureOptions<TextureSourceType extends TextureSource = TextureSource> {\n source?: TextureSourceType\n label?: string\n frame?: Rectangle\n orig?: Rectangle\n rotate?: number\n}\n\nexport class Texture<T extends TextureSource = TextureSource> extends EventEmitter {\n public static EMPTY: Texture\n public label: string\n public _source: T\n public orig: Rectangle\n public frame = new Rectangle()\n public readonly rotate: number\n public destroyed: boolean\n\n public noFrame = false\n\n constructor({\n source,\n label,\n frame,\n orig,\n rotate,\n }: TextureOptions<T> = {}) {\n super()\n\n this.label = label\n this.source = source\n\n if (frame) {\n this.frame.copyFrom(frame)\n } else {\n this.noFrame = true\n const { width, height } = source\n\n this.frame.width = width\n this.frame.height = height\n }\n\n this.orig = orig || this.frame\n this.rotate = rotate ?? 0\n\n this.destroyed = false\n }\n\n get source() {\n return this._source\n }\n\n set source(value: T) {\n if (this._source) {\n this._source.off('resize', this.update, this)\n }\n\n this._source = value\n\n value.on('resize', this.update, this)\n }\n\n get width() {\n return this.orig.width\n }\n\n get height() {\n return this.orig.height\n }\n\n public update() {\n if (this.noFrame) {\n this.frame.width = this._source.width\n this.frame.height = this._source.height\n }\n }\n\n public destroy(destroySource = false) {\n if (this._source) {\n this._source.off('resize', this.update, this)\n\n if (destroySource) {\n this._source.destroy()\n this._source = null\n }\n }\n\n this.destroyed = true\n this.emit('destroy', this)\n this.removeAllListeners()\n }\n}\n\nTexture.EMPTY = new Texture({\n label: 'EMPTY',\n source: new TextureSource({\n label: 'EMPTY'\n })\n})\n","import { CanvasRenderer } from \"@/renderer\";\nimport { Text } from \"./Text\";\nimport { generateTextTexture } from \"./utils\";\nimport { TextStyle } from \"./TextStyle\";\nimport { Texture } from \"@/renderer/texture/Texture\";\nimport { TextureSource } from \"@/renderer/texture/TextureSource\";\n\nexport class TextSystem {\n static desc = {\n name: 'text'\n } as const\n public readonly renderer: CanvasRenderer\n\n private readonly _activeTexture: Record<string, Texture> = {}\n\n constructor(renderer: CanvasRenderer) {\n this.renderer = renderer\n }\n \n public getManagedTexture(text: Text) {\n text._resolution = text._autoResolution ? this.renderer.resolution : text.resolution\n const textKey = text.styleKey\n\n if (this._activeTexture[textKey]) {\n // TODO: gc count?\n return this._activeTexture[textKey]\n }\n\n const texture = this.getTexture({\n text: text.text,\n style: text.style,\n resolution: text._resolution,\n })\n\n this._activeTexture[textKey] = texture\n\n return texture\n }\n\n public getTexture(options: { text: string, style: TextStyle, resolution: number }) {\n const { text, style } = options\n\n const resolution = options.resolution || this.renderer.resolution\n const { frame, canvasAndContext } = generateTextTexture({\n text,\n style,\n resolution,\n })\n\n const image = canvasAndContext.canvas\n const source = new TextureSource({ resource: image, resolution })\n const texture = new Texture({ source })\n texture.frame.width = frame.width / resolution\n texture.frame.height = frame.height / resolution\n\n return texture\n }\n}","import { InstructionSet } from \"@/renderer/InstructionSet\"\nimport { MaskEffect } from \"../container/mixins/effectMixin\"\nimport { StencilMaskInstruction } from \"./StencilMask\"\nimport { CanvasRenderer } from \"@/renderer\"\nimport { buildShapePath } from \"../graphics\"\n\nexport class StencilMaskPipe {\n static desc = {\n name: 'stencilMask',\n } as const\n\n private _renderer: CanvasRenderer\n private _canvasMaskStack: boolean[] = []\n\n constructor(renderer: CanvasRenderer) {\n this._renderer = renderer\n }\n\n push(mask: MaskEffect, instructionSet: InstructionSet) {\n instructionSet.add({\n renderPipeId: 'stencilMask',\n action: 'pushMaskBegin',\n mask,\n } as StencilMaskInstruction)\n }\n\n pop(mask: MaskEffect, instructionSet: InstructionSet) {\n this._renderer.renderPipes.batch.break(instructionSet)\n\n instructionSet.add({\n renderPipeId: 'stencilMask',\n action: 'popMaskEnd',\n mask,\n } as StencilMaskInstruction)\n }\n\n execute(instruction: StencilMaskInstruction) {\n if (instruction.action !== 'pushMaskBegin' && instruction.action !== 'popMaskEnd') {\n return\n }\n\n const renderer = this._renderer\n const contextSystem = renderer.canvasContext\n const ctx = contextSystem.activeConext\n\n if (instruction.action === 'popMaskEnd') {\n const didClip = this._canvasMaskStack.pop()\n if (didClip) {\n ctx.restore()\n }\n return\n }\n\n const graphics = instruction.mask.mask\n const instructions = graphics.context.instructions\n const roundPixels = graphics._roundPixels === 1\n\n ctx.save()\n\n contextSystem.setContextTransform(graphics.relativeGroupTransform, roundPixels)\n\n ctx.beginPath()\n\n for (let i = 0; i < instructions.length; ++i) {\n const instructionData = instructions[i]\n const action = instructionData.action\n\n if (action !== 'fill' && action !== 'stroke') return\n\n const data = instructionData.data\n const shapePath = data.path.shapePath\n // const isStroke = action === 'stroke'\n const shapePrimitives = shapePath.shapePrimitives\n\n for (let j = 0; j < shapePrimitives.length; ++j) {\n const primitive = shapePrimitives[j]\n const shape = primitive.shape\n buildShapePath(ctx, shape)\n }\n }\n ctx.clip()\n\n this._canvasMaskStack.push(true)\n }\n\n public destroy() {\n this._renderer = null\n }\n}\n","import { Texture } from \"./Texture\";\nimport { TextureSource, TextureSourceOptions } from \"./TextureSource\";\n\nexport interface RenderTextureOptions extends TextureSourceOptions {}\n\nexport class RenderTexture extends Texture {\n public static create(options: RenderTextureOptions) {\n return new RenderTexture({ source: new TextureSource(options) })\n }\n}","import { Vector2 } from \"@/maths\";\nimport { ViewContainer } from \"../ViewContainer\";\nimport { Texture } from \"@/renderer/texture/Texture\";\nimport { ContainerOptions } from \"..\";\n\nexport interface SpriteOptions extends ContainerOptions {\n texture?: Texture\n\n}\n\nexport class Sprite extends ViewContainer {\n public _texture: Texture\n public anchor: Vector2\n\n public override readonly renderPipeId = 'sprite'\n\n private _width: number\n private _height: number\n\n constructor(options: SpriteOptions | Texture = Texture.EMPTY) {\n if (options instanceof Texture) {\n options = { texture: options }\n }\n const { texture = Texture.EMPTY, width, height, ...rest } = options\n super({\n label: 'Sprite',\n ...rest,\n })\n\n this.texture = texture\n this.anchor = new Vector2()\n\n if (width != null) this.width = width\n if (height != null) this.height = height\n }\n\n set texture(value: Texture) {\n value ||= Texture.EMPTY\n\n const currentTexture = this._texture\n\n if (currentTexture === value) return\n\n this._texture = value\n\n if (this._width) {\n this._setWidth(this.width, this._texture.orig.width)\n }\n if (this._height) {\n this._setHeight(this.height, this._texture.orig.height)\n }\n\n this.onViewUpdate()\n }\n\n get texture() {\n return this._texture\n }\n\n override get height() {\n return Math.abs(this.scale.y) * this.texture.orig.height\n }\n override set height(value: number) {\n const localHeight = this.texture.orig.height\n // 保留符号\n const sign = Math.sign(this.scale.y) || 1\n\n if (localHeight !== 0) {\n this.scale.y = (value / localHeight) * sign\n } else {\n this.scale.y = sign\n }\n\n this._height = value\n }\n\n override get width() {\n return Math.abs(this.scale.x) * this.texture.orig.width\n }\n override set width(value: number) {\n const localWidth = this.texture.orig.width\n // 保留符号\n const sign = Math.sign(this.scale.x) || 1\n\n if (localWidth !== 0) {\n this.scale.x = (value / localWidth) * sign\n } else {\n this.scale.x = sign\n }\n\n this._width = value\n }\n\n protected updateBounds() {\n const bounds = this._bounds\n const { width, height } = this.texture.orig\n\n bounds.minX = -this.anchor.x * width\n bounds.maxX = bounds.minX + width\n\n bounds.minY = -this.anchor.y * height\n bounds.maxY = bounds.minY + height\n }\n}\n","import { ObservablePoint } from \"@/maths/Point\";\nimport { ViewContainer } from \"../ViewContainer\";\nimport { Vector2 } from \"@/maths\";\nimport { TextStyle, TextStyleOptions } from \"./TextStyle\";\nimport { TextMetrics } from \"./utils\";\nimport { DestroyOptions } from \"../container/destroyTypes\";\nimport { ContainerOptions } from \"..\";\n\nexport interface TextOptions extends ContainerOptions {\n text?: string | number\n style?: TextStyleOptions\n resolution?: number\n}\n\nexport class Text extends ViewContainer {\n public override readonly renderPipeId = 'text'\n\n public _anchor: ObservablePoint\n /**\n * @internal\n */\n public _didTextUpdate = true\n public _resolution: number = null\n public _autoResolution = true\n\n private _text: string\n private _style: TextStyle\n\n constructor(options: TextOptions) {\n const { text, resolution, style, width, height, ...rest } = options\n super(rest)\n this._anchor = new ObservablePoint(this, 0, 0)\n this.text = options.text ?? ''\n this.style = style\n this.resolution = resolution ?? null\n\n if (width != null) this.width = width\n if (height != null) this.height = height\n }\n\n // 默认使用renderer resolution\n // 当手动设置resolution后会使用自身的\n // 除非设置的值是null,将会兜底使用renderer的\n set resolution(value: number) {\n this._autoResolution = value === null\n this._resolution = value\n this.onViewUpdate()\n }\n\n get resolution() {\n return this._resolution\n }\n\n get anchor() {\n return this._anchor\n }\n set anchor(value: Vector2) {\n this._anchor.copyFrom(value)\n }\n\n get text(): string {\n return this._text\n }\n\n set text(value: string | number) {\n const str = String(value)\n if (this._text === str) return\n\n this._text = str\n this.onViewUpdate()\n }\n\n get style(): TextStyle {\n return this._style\n }\n\n set style(value: TextStyle | TextStyleOptions) {\n value ||= {}\n\n if (value instanceof TextStyle) {\n this._style = value\n } else {\n this._style = new TextStyle(value)\n }\n this.onViewUpdate()\n }\n\n override get width() {\n return Math.abs(this.scale.x) * this.bounds.width\n }\n\n override set width(value: number) {\n this._setWidth(value, this.bounds.width)\n }\n\n override get height() {\n return Math.abs(this.scale.y) * this.bounds.height\n }\n\n override set height(value: number) {\n this._setHeight(value, this.bounds.height)\n }\n\n public override onViewUpdate() {\n if (!this.didViewUpdate) this._didTextUpdate = true\n\n super.onViewUpdate()\n }\n\n protected updateBounds(): void {\n const bounds = this._bounds\n const anchor = this._anchor\n // TODO cal with trim\n const measurement = TextMetrics.measureText(this._text, this._style)\n const width = measurement.width\n const height = measurement.height\n\n bounds.minX = (-anchor._x * width)\n bounds.minY = (-anchor._y * height)\n bounds.maxX = bounds.minX + width\n bounds.maxY = bounds.minY + height\n }\n\n get styleKey() {\n return `${this._text}:${this._style.styleKey}:${this._resolution}`\n }\n\n public override destroy(options: DestroyOptions = false) {\n super.destroy(options)\n\n this._bounds = null\n this._anchor = null\n\n if (typeof options === 'boolean' ? options : options?.style) {\n this._style.destroy(options)\n }\n this._style = null\n this._text = null\n }\n}\n","import { Matrix, Rectangle } from \"@/maths\";\nimport { Bounds, getLocalBounds } from \"@/maths/Bounds\";\nimport { CanvasRenderer } from \"@/renderer\";\nimport { RenderTexture } from \"@/renderer/texture/RenderTexture\";\nimport { Container } from \"@/scene\";\n\nexport type GenerateTextureOptions = {\n target: Container\n frame?: Rectangle\n resolution?: number\n}\n\nexport class ExtractSystem {\n static desc = {\n name: 'extract'\n } as const\n private _renderer: CanvasRenderer\n\n constructor(renderer: CanvasRenderer) {\n this._renderer = renderer\n }\n public texture(options: Container) {\n return this._generateTexture(options)\n }\n\n private _generateTexture(options: GenerateTextureOptions | Container) {\n if (options instanceof Container) {\n options = {\n target: options,\n }\n }\n\n const resolution = options.resolution || this._renderer.resolution\n const container = options.target\n\n const _bounds = new Bounds()\n const region = options.frame || getLocalBounds(container, _bounds).rectangle\n\n region.width = Math.max(region.width, 1 / resolution) | 0\n region.height = Math.max(region.height, 1 / resolution) | 0\n\n const target = RenderTexture.create({\n width: region.width,\n height: region.height,\n resolution,\n })\n\n const transform = new Matrix()\n transform.tx = -region.x\n transform.ty = -region.y\n\n this._renderer.render({\n clearColor: 'transparent',\n container,\n transform,\n target,\n })\n\n return target\n }\n}\n\n","import { Matrix } from \"@/maths\"\nimport { CanvasRenderer } from \"@/renderer\"\n\nexport class CanvasContextSystem {\n static desc = {\n name: 'canvasContext',\n } as const\n\n private _renderer: CanvasRenderer\n\n public rootContext: CanvasRenderingContext2D\n public activeConext: CanvasRenderingContext2D\n public activeResolution = 1\n\n public globalTransform = new Matrix()\n\n constructor(renderer: CanvasRenderer) {\n this._renderer = renderer\n }\n\n public init() {\n this.activeConext = this._renderer.canvas.getContext('2d')\n this.rootContext = this.activeConext\n this.activeResolution = this._renderer.resolution\n }\n\n public setContextTransform(\n transform: Matrix,\n roundPixels?: boolean,\n localResolution?: number\n ) {\n const contextResolution = this.activeResolution\n const mat = Matrix.append(this.globalTransform, transform)\n\n localResolution ||= this.activeResolution\n\n if (roundPixels) {\n this.activeConext.setTransform(\n mat.a * localResolution,\n mat.b * localResolution,\n mat.c * localResolution,\n mat.d * localResolution,\n (mat.tx * contextResolution) | 0,\n (mat.ty * contextResolution) | 0,\n )\n } else {\n this.activeConext.setTransform(\n mat.a * localResolution,\n mat.b * localResolution,\n mat.c * localResolution,\n mat.d * localResolution,\n mat.tx * contextResolution,\n mat.ty * contextResolution,\n )\n }\n }\n}\n","import { Rectangle } from \"@/maths\"\nimport { createCanvas } from \"@/scene/text/utils\"\nimport { Texture } from '@/renderer/texture/Texture'\nimport { CanvasSource } from \"@/renderer/texture/TextureSource\"\n\nexport type ViewSystemOptions = {\n width?: number\n height?: number\n resolution?: number\n autoDensity?: boolean\n}\n\nexport class ViewSystem {\n public static desc = {\n name: 'view',\n } as const\n\n public static defaultOptions: ViewSystemOptions = {\n width: 800,\n height: 600,\n autoDensity: false,\n }\n\n public canvas: HTMLCanvasElement\n public screen: Rectangle\n public texture: Texture<CanvasSource>\n\n get resolution() {\n return this.texture.source._resolution\n }\n\n set resolution(value: number) {\n this.texture.source.resize(\n this.texture.source.width,\n this.texture.source.height,\n value,\n )\n }\n\n public init(options: ViewSystemOptions) {\n options = {\n ...ViewSystem.defaultOptions,\n ...options,\n }\n\n this.screen = new Rectangle(0, 0, options.width, options.height)\n this.canvas = createCanvas()\n this.texture = new Texture({ source: new CanvasSource({\n resource: this.canvas,\n ...options,\n })})\n this.resolution = options.resolution\n }\n\n public resize(width: number, height: number, resolution: number) {\n this.texture.source.resize(width, height, resolution)\n\n this.screen.width = this.texture.frame.width\n this.screen.height = this.texture.frame.height\n }\n}\n","import { Matrix } from \"../maths\"\nimport { EventSystem, RenderGroupSystem } from \"../system\"\nimport { Container } from \"@/scene/container/Container\"\nimport { RenderGroup } from \"@/scene/container/RenderGroup\"\nimport { SpritePipe } from \"@/scene/sprite/SpritePipe\"\nimport { TextPipe } from \"@/scene/text/TextPipe\"\nimport { GraphicsPipe } from \"@/scene/graphics\"\nimport { BatchPipe } from \"@/scene/batcher\"\nimport { TextSystem } from \"@/scene/text/TextSystem\"\nimport { uid } from \"../utils\"\nimport { StencilMaskPipe } from \"@/scene/mask/StencilMaskPipe\"\nimport { ExtractSystemTypes } from \"@/utils/type\"\nimport { ExtractSystem } from \"@/system/ExtractSystem\"\nimport { CanvasContextSystem } from \"@/system/CanvasContextSystem\"\nimport { TextureSource } from \"./texture/TextureSource\"\nimport { createCanvas } from \"@/scene/text/utils\"\nimport { ViewSystem } from \"@/system/ViewSystem\"\nimport EventEmitter from \"eventemitter3\"\n\nconst systems = [\n ViewSystem,\n EventSystem,\n RenderGroupSystem,\n TextSystem,\n ExtractSystem,\n CanvasContextSystem,\n]\n\nconst pipes = [\n BatchPipe,\n GraphicsPipe,\n TextPipe,\n SpritePipe,\n StencilMaskPipe,\n]\n\ntype RenderOptions = {\n clearColor?: string\n container: Container\n transform?: Matrix\n target?: { source: TextureSource }\n}\nexport type CanvasSystems = ExtractSystemTypes<typeof systems>\n\nexport type CanvasPipes = ExtractSystemTypes<typeof pipes>\n\nexport interface RendererOptions {\n width?: number\n height?: number\n backgroundColor?: string\n roundPixels?: boolean\n autoStart?: boolean\n resolution?: number\n /**\n * Should the canvas be resized to preserve its screen width and height regardless\n * of the resolution of the renderer.\n */\n autoDensity?: boolean\n}\n\nexport interface CanvasRenderer extends CanvasSystems {}\n\nexport class CanvasRenderer extends EventEmitter {\n public uid = uid('renderer')\n public context!: CanvasRenderingContext2D\n public background: {\n color: string\n }\n public renderedObject: Container = null\n public _roundPixels: 0 | 1\n public resolution: number\n public activeRenderGroup: RenderGroup\n public renderPipes: CanvasPipes = {} as CanvasPipes\n\n constructor() {\n super()\n\n this.background = {\n color: '#000000',\n }\n }\n\n get canvas() {\n return this.view.canvas\n }\n\n private _addPipes() {\n pipes.forEach(pipe => {\n (this.renderPipes as any)[pipe.desc.name] = new pipe(this)\n })\n }\n\n private _addSystems() {\n systems.forEach(system => {\n (this as any)[system.desc.name] = new system(this)\n })\n }\n\n async init(options: RendererOptions) {\n this.resolution = options.resolution || 1\n\n this._addSystems()\n this._addPipes()\n\n for (let i = 0; i < systems.length; ++i) {\n await (this as any)[systems[i].desc.name].init?.(options)\n }\n\n if (options.backgroundColor) {\n this.background.color = options.backgroundColor\n }\n this._roundPixels = options.roundPixels ? 1 : 0\n }\n\n get roundPixels(): boolean {\n return !!this._roundPixels\n }\n\n render(args: Container | RenderOptions) {\n\n let options = args\n\n if (options instanceof Container) {\n options = {\n container: options,\n }\n }\n this.renderedObject = options.container\n\n // stage transform最多计算一次\n if (!options.transform) {\n options.container.updateLocalTransform()\n options.transform = options.container.localTransform\n }\n\n options.clearColor ?? (options.clearColor = this.background.color)\n\n if (!options.container.visible) return\n\n\n options.container.enableRenderGroup()\n\n const renderGroup = options.container.renderGroup\n this.activeRenderGroup = renderGroup\n\n this.canvasContext.globalTransform = renderGroup.worldTransform\n this.canvasContext.activeConext = this.canvasContext.rootContext\n\n if (options.target) {\n const { context } = ensureCanvas(options.target.source)\n this.canvasContext.activeConext = context\n }\n\n this.clear(options)\n\n systems.forEach(system => {\n (this as any)[system.desc.name].render?.(options)\n })\n\n }\n\n clear(options: RenderOptions) {\n const context = this.canvasContext.activeConext\n\n context.setTransform(1, 0, 0, 1, 0, 0)\n context.clearRect(0, 0, this.canvas.width, this.canvas.height)\n\n // TODO: implement Color with r, g, b, a\n context.globalAlpha = 1\n context.fillStyle = options.clearColor!\n context.fillRect(0, 0, this.canvas.width, this.canvas.height)\n // reset global alpha\n context.globalAlpha = 1\n }\n\n public destroy() {\n // TODO: remove view可控\n\n if (this.canvas.parentNode) {\n this.canvas.parentNode.removeChild(this.canvas)\n }\n\n pipes.forEach(pipe => {\n (this.renderPipes as any)[pipe.desc.name]?.destroy()\n })\n this.renderPipes = null\n }\n\n public resize(width: number, height: number, resolution?: number) {\n this.view.resize(width, height, resolution)\n this.emit('resize', this.view.screen.width, this.view.screen.height, this.view.resolution)\n }\n}\n\nfunction ensureCanvas(source: TextureSource) {\n let canvas = source.resource as HTMLCanvasElement\n if (!canvas) {\n canvas = createCanvas(source.pixelWidth, source.pixelHeight)\n source.resource = canvas\n }\n\n if (canvas.width !== source.pixelWidth || canvas.height !== source.pixelHeight) {\n canvas.width = source.pixelWidth\n canvas.height = source.pixelHeight\n }\n\n return { canvas, context: canvas.getContext('2d')}\n}\n","import { Ticker, TickerCallback } from \"./Ticker\"\n\nexport class TickerListener<T = any> {\n public next : TickerListener = null\n public previous: TickerListener = null\n public priority = 0\n private _fn: TickerCallback<T>\n private _context: T\n private _once: boolean\n private _destroyed = false\n\n constructor(fn: TickerCallback<T>, context: T, priority = 0, once = false) {\n this._fn = fn\n this._context = context\n this.priority = priority\n this._once = once\n }\n match(fn: TickerCallback<T>, context?: any) {\n return this._fn === fn && this._context === context\n }\n\n emit(ticker: Ticker) {\n if (this._fn) {\n if (this._context) {\n this._fn.call(this._context, ticker)\n } else {\n (this as TickerListener<any>)._fn(ticker)\n }\n }\n\n const redirect = this.next\n\n if (this._once) {\n this.destroy(true)\n }\n\n // 不管是软删还是硬删,都要断开当前节点与链表的连接\n if (this._destroyed) {\n this.next = null\n }\n return redirect\n }\n\n /**\n * Destroy and don't use after this.\n * @param hard - `true` to remove the `next` reference, this\n * is considered a hard destroy. Soft destroy maintains the next reference.\n * @returns The listener to redirect while emitting or removing.\n */\n destroy(hard?: boolean) {\n this._destroyed = true\n this._fn = null\n this._context = null\n\n if (this.previous) {\n this.previous.next = this.next\n }\n\n if (this.next) {\n this.next.previous = this.previous\n }\n\n const redirect = this.next\n\n this.next = hard ? null : redirect\n this.previous = null\n\n // hard为ture仅仅是断开了链表的连接,返回值仍然是下一个节点\n // 也就是说不论如何销毁这个操作在下一帧才会反应出来\n // 目前看来,两者的区别在于执行销毁操作的当前帧中能否通过该节点的next访问到下一个节点\n return redirect\n }\n\n public connect(previous: TickerListener) {\n this.previous = previous\n if (previous.next) {\n previous.next.previous = this\n }\n this.next = previous.next\n previous.next = this\n }\n}\n","import { TickerListener } from \"./TickerListener\";\n\nexport type TickerCallback<T> = (this: T, ticker: Ticker) => any;\n\nexport class Ticker {\n /**\n * Target frame rate in frames per millisecond.\n * Used for converting deltaTime to a scalar time delta.\n * @example\n * ```ts\n * // Default is 0.06 (60 FPS)\n * console.log(Ticker.targetFPMS); // 0.06\n *\n * // Calculate target frame duration\n * const frameDuration = 1 / Ticker.targetFPMS; // ≈ 16.67ms\n *\n * // Use in custom timing calculations\n * const deltaTime = elapsedMS * Ticker.targetFPMS;\n * ```\n * @remarks\n * - Default is 0.06 (equivalent to 60 FPS)\n * - Used in deltaTime calculations\n * - Affects all ticker instances\n * @default 0.06\n * @see {@link Ticker#deltaTime} For time scaling\n * @see {@link Ticker#FPS} For actual frame rate\n */\n public static targetFPMS = 0.06;\n\n /**\n * Whether or not this ticker should invoke the method {@link Ticker#start|start}\n * automatically when a listener is added.\n * @example\n * ```ts\n * // Default behavior (manual start)\n * const ticker = new Ticker();\n * ticker.autoStart = false;\n * ticker.add(() => {\n * // Won't run until ticker.start() is called\n * });\n *\n * // Auto-start behavior\n * const autoTicker = new Ticker();\n * autoTicker.autoStart = true;\n * autoTicker.add(() => {\n * // Runs immediately when added\n * });\n * ```\n * @default false\n * @see {@link Ticker#start} For manually starting the ticker\n * @see {@link Ticker#stop} For manually stopping the ticker\n */\n public autoStart = false;\n /**\n * Scalar representing the delta time factor.\n * This is a dimensionless value representing the fraction of a frame at the target framerate.\n * At 60 FPS, this value is typically around 1.0.\n *\n * This is NOT in milliseconds - it's a scalar multiplier for frame-independent animations.\n * For actual milliseconds, use {@link Ticker#deltaMS}.\n * @example\n * ```ts\n * // Frame-independent animation using deltaTime scalar\n * ticker.add((ticker) => {\n * // Rotate sprite by 0.1 radians per frame, scaled by deltaTime\n * sprite.rotation += 0.1 * ticker.deltaTime;\n * });\n * ```\n */\n public deltaTime: number = 1;\n /**\n * Scalar time elapsed in milliseconds from last frame to this frame.\n * Provides precise timing for animations and updates.\n *\n * This value is capped by setting {@link Ticker#minFPS|minFPS}\n * and is scaled with {@link Ticker#speed|speed}.\n *\n * If the platform supports DOMHighResTimeStamp,\n * this value will have a precision of 1 µs.\n *\n * Defaults to target frame time\n *\n * > [!NOTE] The cap may be exceeded by scaling.\n * @example\n * ```ts\n * // Animation timing\n * ticker.add((ticker) => {\n * // Use millisecond timing for precise animations\n * const progress = (ticker.deltaMS / animationDuration);\n * sprite.alpha = Math.min(1, progress);\n * });\n * ```\n * @default 16.66\n */\n public deltaMS: number;\n /**\n * Time elapsed in milliseconds from the last frame to this frame.\n * This value is not capped or scaled and provides raw timing information.\n *\n * Unlike {@link Ticker#deltaMS}, this value is unmodified by speed scaling or FPS capping.\n * @example\n * ```ts\n * ticker.add((ticker) => {\n * console.log(`Raw frame time: ${ticker.elapsedMS}ms`);\n * });\n * ```\n */\n public elapsedMS: number;\n /**\n * The last time update was invoked, in milliseconds since epoch.\n * Similar to performance.now() timestamp format.\n *\n * Used internally for calculating time deltas between frames.\n * @example\n * ```ts\n * ticker.add((ticker) => {\n * const currentTime = performance.now();\n * const timeSinceLastFrame = currentTime - ticker.lastTime;\n * console.log(`Time since last frame: ${timeSinceLastFrame}ms`);\n * });\n * ```\n */\n public lastTime: number = -1;\n /**\n * Factor of current {@link Ticker#deltaTime|deltaTime}.\n * Used to scale time for slow motion or fast-forward effects.\n * @example\n * ```ts\n * // Basic speed adjustment\n * ticker.speed = 0.5; // Half speed (slow motion)\n * ticker.speed = 2.0; // Double speed (fast forward)\n *\n * // Temporary speed changes\n * function slowMotion() {\n * const normalSpeed = ticker.speed;\n * ticker.speed = 0.2;\n * setTimeout(() => {\n * ticker.speed = normalSpeed;\n * }, 1000);\n * }\n * ```\n */\n public speed = 1;\n /**\n * Whether or not this ticker has been started.\n *\n * `true` if {@link Ticker#start|start} has been called.\n * `false` if {@link Ticker#stop|Stop} has been called.\n *\n * While `false`, this value may change to `true` in the\n * event of {@link Ticker#autoStart|autoStart} being `true`\n * and a listener is added.\n * @example\n * ```ts\n * // Check ticker state\n * const ticker = new Ticker();\n * console.log(ticker.started); // false\n *\n * // Start and verify\n * ticker.start();\n * console.log(ticker.started); // true\n * ```\n */\n public started = false;\n /**\n * Internal tick method bound to ticker instance.\n * This is because in early 2015, Function.bind\n * is still 60% slower in high performance scenarios.\n * Also separating frame requests from update method\n * so listeners may be called at any time and with\n * any animation API, just invoke ticker.update(time).\n * @param time - Time since last tick.\n */\n private readonly _tick: (time: number) => any;\n /** Internal current frame request ID */\n private _requestId: number = null;\n /**\n * Internal value managed by minFPS property setter and getter.\n * This is the maximum allowed milliseconds between updates.\n */\n private _maxElapsedMS = 100;\n /**\n * Internal value managed by maxFPS property setter and getter.\n * This is the minimum allowed milliseconds between updates.\n */\n private _minElapsedMS = 0;\n /** The last time keyframe was executed. Maintains a relatively fixed interval with the previous value. */\n private _lastFrame = -1;\n private _head: TickerListener = null\n constructor() {\n this._head = new TickerListener(null, null, Infinity)\n this.deltaMS = 1 / Ticker.targetFPMS\n this.elapsedMS = this.deltaMS\n\n this._tick = (time: number) => {\n this._requestId = null\n\n if (this.started) {\n this.update(time)\n\n if (this.started && this._requestId === null) {\n this._requestId = requestAnimationFrame(this._tick)\n }\n }\n }\n }\n /**\n * Triggers an update.\n *\n * An update entails setting the\n * current {@link Ticker#elapsedMS|elapsedMS},\n * the current {@link Ticker#deltaTime|deltaTime},\n * invoking all listeners with current deltaTime,\n * and then finally setting {@link Ticker#lastTime|lastTime}\n * with the value of currentTime that was provided.\n *\n * This method will be called automatically by animation\n * frame callbacks if the ticker instance has been started\n * and listeners are added.\n * @example\n * ```ts\n * // Basic manual update\n * const ticker = new Ticker();\n * ticker.update(performance.now());\n * ```\n * @param currentTime - The current time of execution (defaults to performance.now())\n * @see {@link Ticker#deltaTime} For frame delta value\n * @see {@link Ticker#elapsedMS} For raw elapsed time\n */\n update(currentTime = performance.now()) {\n let elapsedMS\n\n // 只有时间差是正数时,才认为需要更新\n // 差值为0说明时间没有变化,不需要更新\n // 而如果是负值,说明触发了竞态条件\n // 考虑以下情况,用户手动触发start,同时浏览器触发了rAF,一旦start的触发和rAF在同一帧且start要晚一点\n // 就会出现差值为负的情况,这种现象显然是异常的,不需要按正常流程渲染\n if (currentTime > this.lastTime) {\n elapsedMS = this.elapsedMS = currentTime - this.lastTime\n\n if (elapsedMS > this._maxElapsedMS) {\n elapsedMS = this._maxElapsedMS\n }\n\n elapsedMS *= this.speed\n\n if (this._minElapsedMS) {\n const delta = currentTime - this._lastFrame | 0\n\n if (delta < this._minElapsedMS) {\n return\n }\n\n this._lastFrame = currentTime - (delta % this._minElapsedMS)\n }\n\n this.deltaMS = elapsedMS\n this.deltaTime = this.deltaMS * Ticker.targetFPMS\n\n const head = this._head\n\n let listener = head.next\n\n while(listener) {\n listener = listener.emit(this)\n }\n\n if (!head.next) {\n this._cancelIfNeeded()\n }\n } else {\n this.deltaTime = this.deltaMS = this.elapsedMS = 0\n }\n\n this.lastTime = currentTime\n }\n /**\n * The frames per second at which this ticker is running.\n * The default is approximately 60 in most modern browsers.\n * > [!NOTE] This does not factor in the value of\n * > {@link Ticker#speed|speed}, which is specific\n * > to scaling {@link Ticker#deltaTime|deltaTime}.\n * @example\n * ```ts\n * // Basic FPS monitoring\n * ticker.add(() => {\n * console.log(`Current FPS: ${Math.round(ticker.FPS)}`);\n * });\n * ```\n * @readonly\n */\n get FPS() {\n return 1000 / this.elapsedMS\n }\n /**\n * Manages the minimum amount of milliseconds required to\n * elapse between invoking {@link Ticker#update|update}.\n *\n * This will effect the measured value of {@link Ticker#FPS|FPS}.\n *\n * If it is set to `0`, then there is no limit; PixiJS will render as many frames as it can.\n * Otherwise it will be at least `minFPS`.\n *\n * If `maxFPS` is set below the current `minFPS`, `minFPS` is automatically lowered to match.\n * This keeps the two limits consistent.\n * @example\n * ```ts\n * // Cap the frame rate\n * const ticker = new Ticker();\n * ticker.maxFPS = 60; // Never go above 60 FPS\n *\n * // Use with minFPS for frame rate clamping\n * ticker.minFPS = 30;\n * ticker.maxFPS = 60;\n *\n * // maxFPS below minFPS pushes minFPS down\n * ticker.maxFPS = 20; // minFPS is now also 20\n * ```\n * @default 0\n */\n get maxFPS(): number\n {\n if (this._minElapsedMS)\n {\n return Math.round(1000 / this._minElapsedMS);\n }\n\n return 0;\n }\n set maxFPS(value: number) {\n if (value === 0) {\n this._minElapsedMS = 0\n } else {\n if (value < this.minFPS) {\n this.minFPS = value\n }\n\n this._minElapsedMS = 1 / (value / 1000)\n }\n }\n /**\n * Manages the maximum amount of milliseconds allowed to\n * elapse between invoking {@link Ticker#update|update}.\n *\n * This value is used to cap {@link Ticker#deltaTime|deltaTime},\n * but does not effect the measured value of {@link Ticker#FPS|FPS}.\n *\n * When setting this property it is clamped to a value between\n * `0` and `Ticker.targetFPMS * 1000` (typically 60).\n *\n * If `maxFPS` is currently set (non-zero) and `minFPS` is set above it,\n * `maxFPS` is automatically raised to match. This keeps the two limits consistent.\n * @example\n * ```ts\n * // Set minimum acceptable frame rate\n * const ticker = new Ticker();\n * ticker.minFPS = 30; // Never go below 30 FPS\n *\n * // Use with maxFPS for frame rate clamping\n * ticker.minFPS = 30;\n * ticker.maxFPS = 60;\n *\n * // minFPS above maxFPS pushes maxFPS up\n * ticker.minFPS = 50; // maxFPS is raised to 50\n * ```\n * @default 10\n */\n get minFPS(): number\n {\n return 1000 / this._maxElapsedMS;\n }\n\n set minFPS(value: number) {\n const minFPSMS = Math.min(Math.max(0, value) / 1000, Ticker.targetFPMS)\n\n this._maxElapsedMS = 1 / minFPSMS\n\n if (this._minElapsedMS && value > this.maxFPS) {\n this.maxFPS = value\n }\n }\n\n add<T = any>(fn: TickerCallback<T>, context?: T, priority = 0) {\n const listener = new TickerListener(fn, context, priority)\n let current = this._head.next\n let previous = this._head\n\n // 没有下一个节点,直接将当前的追到链表后\n if (!current) {\n listener.connect(previous)\n } else {\n while(current) {\n if (listener.priority > current.priority) {\n listener.connect(previous)\n break\n }\n previous = current\n current = current.next\n }\n\n // 保护性写法?已经遍历到末尾了,还需要判断节点是否被添加吗\n if (!listener.previous) {\n listener.connect(previous)\n }\n }\n\n this._startIfPossible()\n\n return this\n }\n\n public start() {\n if (!this.started) {\n this.started = true\n this._requestIfNeeded()\n }\n }\n\n public stop() {\n if (this.started) {\n this.started = false\n this._cancelIfNeeded()\n }\n }\n\n public remove<T>(fn: TickerCallback<T>, context?: T) {\n let listener = this._head.next\n\n while(listener) {\n if (listener.match(fn, context)) {\n listener = listener.destroy()\n } else {\n listener = listener.next\n }\n }\n\n if (!this._head.next) {\n this._cancelIfNeeded()\n }\n\n return this\n }\n\n private _startIfPossible() {\n if (this.started) {\n this._requestIfNeeded()\n } else if (this.autoStart) {\n this.start()\n }\n }\n\n private _requestIfNeeded() {\n // 如果ticker里没有事件就不启动\n if (this._requestId === null && this._head.next) {\n this.lastTime = performance.now()\n this._lastFrame = this.lastTime\n this._requestId = requestAnimationFrame(this._tick)\n }\n }\n\n private _cancelIfNeeded() {\n if (this._requestId !== null) {\n cancelAnimationFrame(this._requestId)\n this._requestId = null\n }\n }\n\n public destroy() {\n this.stop()\n let listener = this._head.next\n\n while (listener) {\n listener = listener.destroy(true)\n }\n\n this._head.destroy()\n this._head = null\n }\n}\n","import { CanvasRenderer } from \"@/renderer\"\n\nexport interface ResizePluginOptions {\n resizeTo?: Window | HTMLElement\n}\nexport class ResizePlugin {\n public static resizeTo: Window | HTMLElement\n public static queueResize: () => void\n public static _resizeTo: Window | HTMLElement\n public static _resizeId: number\n public static resize: () => void\n public static _cancelResize: () => void\n public static renderer: Pick<CanvasRenderer, 'resize'>\n public static render: () => void\n\n public static init(options: ResizePluginOptions) {\n Object.defineProperty(this, 'resizeTo', {\n configurable: true,\n set(dom: Window | HTMLElement) {\n globalThis.removeEventListener('resize', this.queueResize)\n this._resizeTo = dom\n if (dom) {\n globalThis.addEventListener('resize', this.queueResize)\n this.resize()\n }\n },\n get() {\n return this._resizeTo\n }\n })\n\n this.queueResize = () => {\n if (!this._resizeTo) {\n return\n }\n\n this._cancelResize()\n this._resizeId = requestAnimationFrame(() => this.resize)\n }\n\n this._cancelResize = () => {\n if (this._resizeId) {\n cancelAnimationFrame(this._resizeId)\n this._resizeId = null\n }\n }\n\n this.resize = () => {\n if (!this._resizeTo) {\n return\n }\n\n this._cancelResize()\n\n let width: number\n let height: number\n\n if (this._resizeTo === globalThis.window) {\n width = globalThis.innerWidth\n height = globalThis.innerHeight\n } else {\n const { clientWidth, clientHeight } = this._resizeTo as HTMLElement\n\n width = clientWidth\n height = clientHeight\n }\n\n this.renderer.resize(width, height)\n this.render()\n }\n\n this._resizeId = null\n this._resizeTo = null\n this.resizeTo = options.resizeTo || null\n }\n\n public static destroy() {\n globalThis.removeEventListener('resize', this.queueResize)\n this._cancelResize()\n this._cancelResize = null\n this.queueResize = null\n this.resizeTo = null\n this.resize = null\n }\n}\n","import { CanvasRenderer, RendererOptions } from \"@/renderer\";\nimport { Container } from \"@/scene\";\nimport { Ticker } from \"@/ticker\";\nimport { ResizePlugin, ResizePluginOptions } from \"./ResizePlugin\";\n\nconst plugins = [\n ResizePlugin\n]\n\nexport interface ApplicationOptions extends RendererOptions, ResizePluginOptions {}\n\nexport class Application {\n public renderer: CanvasRenderer\n public stage: Container = new Container()\n\n private _ticker: Ticker\n async init(options: Partial<ApplicationOptions> = {}) {\n options = { ...options }\n this.stage ||= new Container()\n\n this.renderer = new CanvasRenderer()\n await this.renderer.init(options)\n\n plugins.forEach(plugin => {\n plugin.init.call(this, options)\n })\n\n this.ticker = new Ticker()\n if (options.autoStart || options.autoStart == undefined) {\n this._ticker.start()\n }\n }\n\n get canvas() {\n return this.renderer.canvas\n }\n\n get screen() {\n return this.renderer.view.screen\n }\n\n get ticker(): Ticker {\n return this._ticker\n }\n set ticker(ticker: Ticker) {\n if (this._ticker) {\n this._ticker.remove(this.render, this)\n }\n this._ticker = ticker\n if (ticker) {\n ticker.add(this.render, this)\n }\n }\n\n public render() {\n this.renderer.render({ container: this.stage })\n }\n\n public destroy() {\n const _plugins = plugins.slice(0)\n\n _plugins.reverse()\n _plugins.forEach(plugin => {\n plugin.destroy.call(this)\n })\n\n this.stage.destroy()\n this.stage = null\n this.renderer.destroy()\n this.renderer = null\n\n if (this._ticker) {\n const oldTicker = this._ticker\n this._ticker = null\n oldTicker.destroy()\n }\n }\n}","class CacheClass {\n private readonly _cache: Map<any, any> = new Map()\n private readonly _cacheMap: Map<string, { keys: string[], cacheKeys: string[] }> = new Map()\n\n public reset() {\n this._cache.clear()\n this._cacheMap.clear()\n }\n\n public has(key: any) {\n return this._cache.has(key)\n }\n\n public get(key: any) {\n const res = this._cache.get(key)\n\n if (!res) {\n throw new Error(`Asset ${key} not found`)\n }\n\n return res\n }\n\n public set<T = any>(key: any | any[], value: T) {\n const keys: string[] = Array.isArray(key) ? key : [key]\n const cacheableMap = new Map()\n\n keys.forEach(key => {\n cacheableMap.set(key, value)\n })\n\n const cacheKeys = [...cacheableMap.keys()]\n const cacheAssets = {\n cacheKeys,\n keys,\n }\n\n keys.forEach(key => {\n this._cacheMap.set(key, cacheAssets)\n })\n\n cacheKeys.forEach(key => {\n const val = value\n\n if (this._cache.has(key) && this._cache.has(key) !== val) {\n\n }\n\n this._cache.set(key, cacheableMap.get(key))\n })\n }\n\n public remove(key: any) {\n if (!this._cacheMap.has(key)) {\n return\n }\n\n const cacheMap = this._cacheMap.get(key)\n const cacheKeys = cacheMap?.cacheKeys || []\n\n cacheKeys.forEach(key => {\n this._cache.delete(key)\n })\n\n cacheMap?.keys.forEach(key => {\n this._cacheMap.delete(key)\n })\n }\n}\n\n// function getCacheableAssets(keys: string[], assets: Texture[]) {\n// const out: Record<string, Texture> = {}\n\n// keys.forEach(key => {\n// assets.forEach((asset, i) => {\n// out[key + (i === 0 ? '' : i + 1)] = asset\n// })\n// })\n\n// return out\n// }\n\nexport const Cache = new CacheClass()\n","import { TextureSource } from '@/renderer/texture/TextureSource'\nimport { Texture } from '@/renderer/texture/Texture'\nimport { Cache} from '../cache/Cache'\nimport { UnresolvedAsset } from '../Assets'\n\nexport interface ResolvedAsset {\n alias: string[]\n src: string\n progressSize?: number\n}\n\nexport type ProgressCallback = (progress: number) => void\n\nexport interface LoadOptions {\n onProgress?: (progress: number) => void\n onError?: (error: Error, url: string) => void\n strategy?: 'throw' | 'skip' | 'retry'\n retryCount?: number\n retryDelay?: number\n}\n\nabstract class File<T> {\n public key: string\n public url: string\n constructor(key: string, url: string) {\n this.key = key\n this.url = url\n }\n\n abstract load(): Promise<T>\n}\n\nexport class ImageFile extends File<HTMLImageElement> {\n load(): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image()\n img.onload = () => resolve(img)\n img.onerror = () => reject(new Error(`Failed to load ${this.url}`))\n img.src = this.url\n })\n }\n}\n\nexport class Loader {\n public static defaultOptions: LoadOptions = {\n strategy: 'throw',\n retryCount: 3,\n retryDelay: 250,\n }\n public promiseCache: Record<string, Promise<Texture>> = {}\n public loadOptions = { ...Loader.defaultOptions }\n\n public getAlias(asset: UnresolvedAsset) {\n const { alias, src } = asset\n\n const origin = alias || src\n const list = Array.isArray(origin) ? origin : [origin]\n const aliasesToUse: string[] = list.map(item => {\n if (typeof item === 'string') return item\n if (Array.isArray(item)) return item.map(v => v.src ?? v)\n if (item?.src) return item.src\n\n return item\n })\n\n return aliasesToUse\n }\n\n async load(\n assetsToLoad: ResolvedAsset[],\n onProgressOrOptions?: ProgressCallback | LoadOptions\n ) {\n\n const options = typeof onProgressOrOptions === 'function'\n ? { ...Loader.defaultOptions, ...this.loadOptions, onProgress: onProgressOrOptions }\n : { ...Loader.defaultOptions, ...this.loadOptions, ...(onProgressOrOptions || {}) }\n const { onProgress, onError, strategy, retryCount, retryDelay } = options\n\n let count = 0\n\n const assets: Record<string, Texture> = {}\n const total = assetsToLoad.reduce((sum, asset) => sum + (asset.progressSize || 1), 0)\n\n const promises = assetsToLoad.map(async asset => {\n if (assets[asset.src]) return\n\n const url = asset.src\n\n await this._loadAssetWithRetry(url, asset, { onProgress, onError, strategy, retryCount, retryDelay }, assets)\n\n count += (asset.progressSize || 1)\n if (onProgress) onProgress(count / total)\n })\n\n await Promise.all(promises)\n\n return assets\n }\n\n public async unload(assetsToLoad: ResolvedAsset[]) {\n const promises = assetsToLoad.map(async asset => {\n const url = asset.src\n const loadPromise = this.promiseCache[url]\n\n if (loadPromise) {\n const loadedAsset = await loadPromise\n\n delete this.promiseCache[url]\n\n loadedAsset.destroy(true)\n }\n })\n\n await Promise.all(promises)\n }\n\n private _getLoadPromise(url: string, data?: any) {\n const promise = (async () => {\n const asset = await loadTextures(url, data, this)\n return asset\n })()\n\n return promise\n }\n\n private async _loadAssetWithRetry(\n url: string,\n asset: ResolvedAsset,\n options: LoadOptions,\n assets: Record<string, Texture>\n ) {\n let attempt = 0\n\n const { onError, strategy, retryCount, retryDelay } = options\n const wait = (ms: number) => new Promise(r => setTimeout(r, ms))\n\n while (true) {\n try {\n if (!this.promiseCache[url]) {\n this.promiseCache[url] = this._getLoadPromise(url, asset)\n }\n\n assets[asset.src] = await this.promiseCache[url]\n\n return\n } catch(e) {\n delete this.promiseCache[url]\n delete assets[asset.src]\n\n attempt++\n\n const isLast = strategy !== 'retry' || attempt > retryCount\n\n if (strategy === 'retry' && !isLast) {\n if (onError) onError(e as Error, asset.src)\n\n await wait(retryDelay)\n continue\n }\n\n if (strategy === 'skip') {\n if (onError) onError(e as Error, asset.src)\n return\n }\n\n if (onError) onError(e as Error, asset.src)\n const error = new Error(`[Loader.load] Failed to load ${url}.\\n${e}`);\n\n if (e instanceof Error && e.stack) {\n error.stack = e.stack\n }\n\n throw error\n }\n }\n }\n\n public reset() {\n this.promiseCache = {}\n }\n}\n\n// function toAbsolute(url: string) {\n// const { origin, pathname } = window.location\n// if (url.startsWith('/')) {\n// return origin + url\n// }\n// const baseUrl = origin + pathname\n\n// return baseUrl + url\n// }\n\nasync function loadTextures(url: string, _asset: ResolvedAsset, loader: Loader) {\n let src: any = null\n\n if (globalThis.createImageBitmap) {\n src = await loadImageBitmap(url)\n } else {\n src = await new Promise((resolve, reject) => {\n src = new Image()\n ;(src as HTMLImageElement).crossOrigin = 'anonymous'\n\n src.src = url\n if (src.complete) {\n resolve(src)\n } else {\n src.onload = () => { resolve(src) }\n src.onerror = reject\n }\n })\n }\n\n const base = new TextureSource({\n resource: src\n })\n\n return createTexture(base, loader, url)\n}\n\nasync function loadImageBitmap(url: string) {\n const response = await window.fetch(url)\n\n // TODO: 暂时针对测试用例明确html算失败\n if (response.headers.get('content-type') === 'text/html' || !response.ok) {\n throw new Error(`[loadImageBitmap] Failed to fetch ${url}: `\n + `${response.status} ${response.statusText}`);\n }\n\n const imageBlob = await response.blob()\n return window.createImageBitmap(imageBlob)\n}\n\nfunction createTexture(source: TextureSource, loader: Loader, url: string) {\n source.label = url\n\n const texture = new Texture({\n source,\n label: url,\n })\n\n const unload = () => {\n delete loader.promiseCache[url]\n\n if (Cache.has(url)) {\n Cache.remove(url)\n }\n }\n\n texture.source.on('destroy', () => {\n if (loader.promiseCache[url]) {\n unload()\n }\n })\n\n texture.on('destroy', () => {\n if (!source.destroyed) {\n unload()\n }\n })\n\n return texture\n}\n","import { ArrayOr } from \"@/utils/type\"\nimport { Loader, LoadOptions, ProgressCallback } from \"./loader/Loader\"\nimport { Cache } from \"./cache/Cache\"\nimport { Texture } from \"@/renderer/texture/Texture\"\n\nexport type UnresolvedAsset<T = any> = {\n alias: ArrayOr<T>\n src: string\n}\n\n\nexport interface AssetInitOptions {\n basePath?: string\n loadOptions?: Partial<LoadOptions>\n}\n\nexport class AssetsClass {\n public cache: typeof Cache\n public loader: Loader\n public basePath: string\n\n private _initialized = false\n\n constructor() {\n this.loader = new Loader()\n this.cache = Cache\n }\n\n public init(options: AssetInitOptions = {}) {\n if (this._initialized) return\n\n this._initialized = true\n\n if (options.basePath) {\n // TODO: resolver\n this.basePath = options.basePath\n }\n\n // const formats = ['png', 'jpg', 'jpeg']\n // TODO: resolver\n\n if (options.loadOptions) {\n this.loader.loadOptions = {\n ...this.loader.loadOptions,\n ...options.loadOptions,\n }\n }\n }\n\n public async load(\n urls: UnresolvedAsset[],\n onProgress?: ProgressCallback | LoadOptions\n ) {\n if (!this._initialized) {\n this.init()\n }\n\n // TODO: check cache\n const resolvedResults = urls.map(item => {\n return { ...item, src: this.basePath ? `${this.basePath}/${item.src}` : item.src}\n })\n\n const out = await this._mapLoadToResolve(resolvedResults, onProgress)\n\n return out\n }\n\n private async _mapLoadToResolve(\n resolveResults: UnresolvedAsset[],\n progressOrLoadOptions?: ProgressCallback | LoadOptions\n ) {\n const resolvedArray = Object.values(resolveResults)\n const loadedAssets = await this.loader.load(resolvedArray, progressOrLoadOptions)\n\n const out: Record<string, Texture> = {}\n\n resolvedArray.forEach(resolveResult => {\n const asset = loadedAssets[resolveResult.src]\n const alias = Array.isArray(resolveResult.alias) ? resolveResult.alias : [resolveResult.alias]\n const keys = [resolveResult.src, ...alias]\n\n keys.forEach(key => {\n out[key] = asset\n })\n\n Cache.set(keys, asset)\n })\n\n return out\n }\n\n public reset() {\n this._initialized = false\n this.cache.reset()\n this.loader.reset()\n }\n}\n\nexport const Assets = new AssetsClass()\n"],"x_google_ignoreList":[12,13],"mappings":"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"}
1
+ {"version":3,"file":"dao.cjs","names":["child: Container","uidCache: Record<string, number>","EventEmitter","EventEmitter","effectMixin: Partial<Container>","sortMixin: Partial<Container>","measureMixin: Partial<Container>","childrenHelperMixin: ChildrenHelperMixin<ContainerChild>","removed: Container[]","oldChildren: ContainerChild[]","fontFamilies: string | string[]","width: number","height: number","keys: string[]","aliasesToUse: string[]","assets: Record<string, Texture>","src: any","out: Record<string, Texture>"],"sources":["../lib/maths/Matrix.ts","../lib/maths/shapes/Rectangle.ts","../lib/maths/index.ts","../lib/events/FederatedEvent.ts","../lib/system/EventSystem.ts","../lib/scene/container/utils.ts","../lib/renderer/InstructionSet.ts","../lib/scene/container/RenderGroup.ts","../lib/utils/uid.ts","../lib/utils/index.ts","../lib/maths/Point.ts","../lib/maths/const.ts","../node_modules/.pnpm/eventemitter3@5.0.4/node_modules/eventemitter3/index.js","../node_modules/.pnpm/eventemitter3@5.0.4/node_modules/eventemitter3/index.mjs","../lib/maths/Bounds.ts","../lib/scene/mask/StencilMask.ts","../lib/scene/container/mixins/effectMixin.ts","../lib/scene/container/mixins/sortMixin.ts","../lib/scene/container/mixins/measureMixin.ts","../lib/scene/container/mixins/childrenHelperMixin.ts","../lib/scene/container/Container.ts","../lib/scene/container/utils/updateRenderGroupTransform.ts","../lib/scene/container/utils/validateRenderables.ts","../lib/system/RenderGroupSystem.ts","../lib/scene/sprite/SpritePipe.ts","../lib/scene/text/TextPipe.ts","../lib/scene/ViewContainer.ts","../lib/maths/shapes/Polygon.ts","../lib/scene/graphics/path/buildAdaptiveBezier.ts","../lib/scene/graphics/path/ShapePath.ts","../lib/scene/graphics/path/GraphicsPath.ts","../lib/scene/graphics/GraphicsContext.ts","../lib/scene/graphics/Graphics.ts","../lib/scene/graphics/GraphicsPipe.ts","../lib/scene/batcher/BatcherPipe.ts","../lib/scene/batcher/Batcher.ts","../lib/renderer/CanvasPool.ts","../lib/scene/text/TextStyle.ts","../lib/scene/text/utils.ts","../lib/renderer/texture/TextureSource.ts","../lib/renderer/texture/Texture.ts","../lib/scene/text/TextSystem.ts","../lib/scene/mask/StencilMaskPipe.ts","../lib/renderer/texture/RenderTexture.ts","../lib/scene/sprite/Sprite.ts","../lib/scene/text/Text.ts","../lib/system/ExtractSystem.ts","../lib/system/CanvasContextSystem.ts","../lib/system/ViewSystem.ts","../lib/renderer/index.ts","../lib/ticker/TickerListener.ts","../lib/ticker/Ticker.ts","../lib/app/ResizePlugin.ts","../lib/app/Application.ts","../lib/assets/cache/Cache.ts","../lib/assets/loader/Loader.ts","../lib/assets/Assets.ts"],"sourcesContent":["import { Vector2 } from \".\"\n/**\n * Two Pi.\n * @type {number}\n * @category maths\n * @standard\n */\nexport const PI_2 = Math.PI * 2;\n\n/**\n * The data structure that contains the position, scale, pivot, skew and rotation of an object.\n * This is used by the {@link Matrix} class to decompose the matrix into its components.\n * @category maths\n * @advanced\n */\n\n/**\n * The data structure that contains the position, scale, pivot, skew and rotation of an object.\n * This is used by the {@link Matrix} class to decompose the matrix into its components.\n * @category maths\n * @advanced\n */\nexport interface TransformableObject {\n /** The position of the object */\n position: Vector2;\n /** The scale of the object */\n scale: Vector2;\n /** The skew of the object */\n skew: Vector2;\n /** The rotation of the object */\n rotation: number;\n pivot: Vector2\n}\n\nexport class Matrix {\n public a: number\n public b: number\n public c: number\n public d: number\n public tx: number\n public ty: number\n constructor(a = 1, b = 0, c = 0, d = 1, tx = 0, ty = 0) {\n this.a = a\n this.b = b\n this.c = c\n this.d = d\n this.tx = tx\n this.ty = ty\n }\n\n /**\n * A * B\n */\n static append(A: Matrix, B: Matrix) {\n const a = B.a * A.a + B.b * A.c\n const b = B.a * A.b + B.b * A.d\n const c = B.c * A.a + B.d * A.c\n const d = B.c * A.b + B.d * A.d\n const tx = B.tx * A.a + B.ty * A.c + A.tx\n const ty = B.tx * A.b + B.ty * A.d + A.ty\n\n return new Matrix(a, b, c, d, tx, ty)\n }\n\n apply(pos: Vector2) {\n const { x, y } = pos\n\n const newPos = new Vector2(\n x * this.a + y * this.c + this.tx,\n x * this.b + y * this.d + this.ty\n )\n\n return newPos\n }\n\n appendFrom(a: Matrix, b: Matrix) {\n const a1 = a.a\n const b1 = a.b\n const c1 = a.c\n const d1 = a.d\n const tx1 = a.tx\n const ty1 = a.ty\n\n const a2 = b.a\n const b2 = b.b\n const c2 = b.c\n const d2 = b.d\n const tx2 = b.tx\n const ty2 = b.ty\n\n this.a = (a1 * a2) + (b1 * c2)\n this.b = (a1 * b2) + (b1 * d2)\n this.c = (c1 * a2) + (d1 * c2)\n this.d = (c1 * b2) + (d1 * d2)\n this.tx = (tx1 * a2) + (ty1 * c2) + tx2\n this.ty = (tx1 * b2) + (ty1 * d2) + ty2\n }\n\n set(a: number, b: number, c: number, d: number, tx: number, ty: number) {\n this.a = a\n this.b = b\n this.c = c\n this.d = d\n this.tx = tx\n this.ty = ty\n }\n\n applyInverse(pos: Vector2, newPos?: Vector2) {\n newPos = newPos || new Vector2()\n\n const a = this.a\n const b = this.b\n const c = this.c\n const d = this.d\n const tx = this.tx\n const ty = this.ty\n\n const id = 1 / ((a * d) + (c * -b))\n\n const x = pos.x\n const y = pos.y\n\n newPos.x = (d * id * x) + (-c * id * y) + (((ty * c) - (tx * d)) * id);\n newPos.y = (a * id * y) + (-b * id * x) + (((-ty * a) + (tx * b)) * id);\n\n return newPos\n }\n\n copyFrom(matrix: Matrix): this {\n this.a = matrix.a;\n this.b = matrix.b;\n this.c = matrix.c;\n this.d = matrix.d;\n this.tx = matrix.tx;\n this.ty = matrix.ty;\n\n return this;\n }\n\n /**\n * Decomposes the matrix into its individual transform components.\n * Extracts position, scale, rotation and skew values from the matrix.\n * @example\n * ```ts\n * // Basic decomposition\n * const matrix = new Matrix()\n * .translate(100, 100)\n * .rotate(Math.PI / 4)\n * .scale(2, 2);\n *\n * const transform = {\n * position: new Point(),\n * scale: new Point(),\n * pivot: new Point(),\n * skew: new Point(),\n * rotation: 0\n * };\n *\n * matrix.decompose(transform);\n * console.log(transform.position); // Point(100, 100)\n * console.log(transform.rotation); // ~0.785 (PI/4)\n * console.log(transform.scale); // Point(2, 2)\n * ```\n * @remarks\n * - Handles combined transformations\n * - Accounts for pivot points\n * - Chooses between rotation/skew based on transform type\n * - Uses radians for rotation and skew\n * @param transform - The transform object to store the decomposed values\n * @returns The transform with the newly applied properties\n * @see {@link Matrix.setTransform} For composing from components\n * @see {@link TransformableObject} For transform structure\n */\n public decompose(transform: TransformableObject): TransformableObject {\n // sort out rotation / skew..\n const a = this.a;\n const b = this.b;\n const c = this.c;\n const d = this.d;\n const pivot = transform.pivot\n\n const skewX = -Math.atan2(-c, d);\n const skewY = Math.atan2(b, a);\n\n const delta = Math.abs(skewX + skewY);\n\n if (delta < 0.00001 || Math.abs(PI_2 - delta) < 0.00001) {\n transform.rotation = skewY;\n transform.skew.x = transform.skew.y = 0;\n }\n else {\n transform.rotation = 0;\n transform.skew.x = skewX;\n transform.skew.y = skewY;\n }\n\n // next set scale\n transform.scale.x = Math.sqrt((a * a) + (b * b));\n transform.scale.y = Math.sqrt((c * c) + (d * d));\n\n // next set position\n transform.position.x = this.tx + (pivot.x * a) + pivot.y * c;\n transform.position.y = this.ty + pivot.x * b + (pivot.y * d);\n\n return transform;\n }\n\n clone() {\n const matrix = new Matrix();\n\n matrix.a = this.a;\n matrix.b = this.b;\n matrix.c = this.c;\n matrix.d = this.d;\n matrix.tx = this.tx;\n matrix.ty = this.ty;\n\n return matrix;\n\n }\n}","export class Rectangle {\n public x: number\n public y: number\n public width: number\n public height: number\n\n public readonly type = 'rectangle'\n\n constructor(x = 0, y = 0, width = 0, height = 0) {\n this.x = x\n this.y = y\n this.width = width\n this.height = height\n }\n\n public getBounds() {\n const out = new Rectangle()\n out.copyFrom(this)\n return out\n }\n\n public copyFrom(rectangle: Rectangle): Rectangle\n {\n this.x = rectangle.x;\n this.y = rectangle.y;\n this.width = rectangle.width;\n this.height = rectangle.height;\n\n return this;\n }\n\n public contains(x: number, y: number) {\n if (this.width <= 0 || this.height <= 0) {\n return false\n }\n\n if (x >= this.x && x < this.x + this.width) {\n if (y >= this.y && y < this.y + this.height) {\n return true\n }\n }\n return false\n }\n}","export class Vector2 {\n public x: number\n public y: number\n constructor(x = 0, y = 0) {\n this.x = x\n this.y = y\n }\n\n set(xora: number, y?: number) {\n if (y == null) {\n this.x = this.y = xora\n } else {\n this.x = xora\n this.y = y\n }\n }\n\n copyFrom(data: Vector2) {\n this.set(data.x, data.y)\n }\n}\n\nexport * from './Matrix'\nexport * from './shapes/Rectangle'\n\n/**\n * Rounds to next power of two.\n * @function nextPow2\n * @param {number} v - input value\n * @returns {number} - next rounded power of two\n * @category maths\n * @advanced\n */\nexport function nextPow2(v: number): number\n{\n v += v === 0 ? 1 : 0;\n --v;\n v |= v >>> 1;\n v |= v >>> 2;\n v |= v >>> 4;\n v |= v >>> 8;\n v |= v >>> 16;\n\n return v + 1;\n}\n","import { Vector2 } from \"@/maths\";\nimport { Container } from \"@/scene\";\nimport { EventSystem } from \"@/system\";\n\nexport class FederatedEvent {\n public readonly system: EventSystem\n public target: Container \n public currentTarget: Container\n public nativeEvent: PointerEvent\n public global: Vector2\n public type: string\n\n public path: Container[]\n\n constructor(system: EventSystem) {\n this.system = system\n }\n\n getLocalPosition(container: Container, points?: Vector2) {\n return container.worldTransform.applyInverse(points || this.global)\n }\n\n composedPath(): Container[] {\n if (!this.path || this.path[this.path.length - 1] !== this.target) {\n this.path = this.target ? this.system.propagationPath(this.target) : []\n }\n\n return this.path\n }\n}\n","import { Container } from \"@/scene/container/Container\"\nimport { ViewContainer } from \"@/scene/ViewContainer\"\nimport { CanvasRenderer } from \"../renderer\"\nimport { Vector2 } from \"../maths\"\nimport { FederatedEventMap } from \"@/events/FederatedEventMap\"\nimport { FederatedEvent } from \"@/events/FederatedEvent\"\n\nconst PROPAGATION_LIMIT = 2048\n\nexport type EventMode = 'none' | 'static' | 'passive'\ntype EmitterListener = { fn(...args: any[]): any, context: any, once: boolean };\nexport type EmitterListeners = Record<string, EmitterListener | EmitterListener[]>;\n\nexport class EventSystem {\n public renderer: CanvasRenderer\n public domElement: HTMLElement = null\n public rootTarget: Container = null\n public resolution = 1\n\n private readonly _allInteractiveElements: Container[] = []\n private _hitElements: Container[] = []\n\n // private readonly _rootPointerEvent: FederatedEvent\n\n private _isPointerMoveEvent = false\n\n private mappingState: Record<string, any> = {\n trackingData: {}\n }\n\n static desc = {\n name: 'events'\n } as const\n\n\n constructor(renderer: CanvasRenderer) {\n this.renderer = renderer\n this.resolution = renderer.resolution\n\n // this._rootPointerEvent = new FederatedEvent(null)\n\n this._onPointerDown = this._onPointerDown.bind(this)\n this._onPointerMove = this._onPointerMove.bind(this)\n this._onPointerUp = this._onPointerUp.bind(this)\n this._onPointerOverOut = this._onPointerOverOut.bind(this)\n\n this.init()\n }\n\n /**\n * \n * @param id pointerId\n */\n private trackingData(id: number) {\n if (!this.mappingState.trackingData[id]) {\n this.mappingState.trackingData[id] = {\n pressTargetsByButton: {},\n clicksByButton: {},\n overTargets: null,\n }\n }\n\n return this.mappingState.trackingData[id]\n }\n\n init() {\n const canvas = this.renderer.canvas\n this.setTargetElement(canvas)\n }\n\n\n setTargetElement(element: HTMLElement) {\n this._removeEvents()\n this.domElement = element\n this._addEvents()\n }\n\n dispatchEvent(e: FederatedEvent, type: keyof FederatedEventMap) {\n if (!e.target) return\n\n const composedPath = e.composedPath()\n\n for (let i = 0; i < composedPath.length - 1; ++i) {\n e.currentTarget = composedPath[i]\n\n this._notifyTarget(e, type)\n\n // TODO: stopPropagation\n }\n\n e.currentTarget = e.target\n\n this._notifyTarget(e, type)\n }\n\n private _notifyTarget(e: FederatedEvent, type?: string) {\n\n type ??= e.type\n\n const listeners = ((e.currentTarget as any)._events as EmitterListeners)[type]\n if (!listeners) return\n\n if ('fn' in listeners) {\n if (listeners.once) {\n // @ts-expect-error: ignore\n e.target.removeListener(type, listeners.fn, undefined, true)\n }\n listeners.fn.call(listeners.context, e)\n } else {\n for (let i = 0; i < listeners.length; ++i) {\n const listener = listeners[i]\n if (listener.once) {\n // @ts-expect-error: ignore\n e.target.removeListener(type, listener.fn, undefined, true)\n }\n listener.fn.call(listener.context, e)\n }\n }\n }\n\n public propagationPath(target: Container) {\n const propagationPath = [target]\n\n for (let i = 0; i < PROPAGATION_LIMIT && (target !== this.rootTarget || target.parent); ++i) {\n if (!target.parent) {\n throw new Error('Cannot find propagation path to disconnected target')\n }\n\n propagationPath.push(target.parent)\n\n target = target.parent\n }\n propagationPath.reverse()\n\n return propagationPath\n }\n\n _removeEvents() {\n const canvas = this.domElement\n if (!canvas) return\n\n globalThis.document.removeEventListener('pointermove', this._onPointerMove, true)\n canvas.removeEventListener('pointerdown', this._onPointerDown, true)\n canvas.removeEventListener('pointerleave', this._onPointerOverOut, true)\n canvas.removeEventListener('pointerover', this._onPointerOverOut, true)\n globalThis.document.removeEventListener('pointerup', this._onPointerUp, true)\n }\n\n _addEvents() {\n const canvas = this.domElement\n if (!canvas) {\n return\n }\n\n const style = canvas.style as CSSStyleDeclaration\n if (style) {\n style.touchAction = 'none'\n }\n\n\n globalThis.document.addEventListener('pointermove', this._onPointerMove, true)\n canvas.addEventListener('pointerdown', this._onPointerDown, true)\n canvas.addEventListener('pointerleave', this._onPointerOverOut, true)\n canvas.addEventListener('pointerover', this._onPointerOverOut, true)\n globalThis.document.addEventListener('pointerup', this._onPointerUp, true)\n }\n\n _onPointerMove(event: PointerEvent) {\n this.rootTarget = this.renderer.renderedObject\n if (!this.rootTarget) return\n\n this._isPointerMoveEvent = true\n this._allInteractiveElements.length = 0\n this._hitElements.length = 0\n const evt = this.createPointEvent(event)\n\n this._isPointerMoveEvent = false\n const trackingData = this.trackingData(event.pointerId)\n const outTarget = findMountedTarget(trackingData.overTargets)\n\n if (trackingData.overTargets?.length > 0 && outTarget !== evt.target) {\n const outType = 'pointerout'\n const outEvent = this.createPointEvent(event, outType, outTarget)\n\n this.dispatchEvent(outEvent, 'pointerout')\n\n const composedPath = evt.composedPath()\n if (!composedPath.includes(outTarget)) {\n const leaveEvent = this.createPointEvent(event, 'pointerleave', outTarget)\n\n while (leaveEvent.target && !composedPath.includes(leaveEvent.target)) {\n leaveEvent.currentTarget = leaveEvent.target\n\n this._notifyTarget(leaveEvent)\n\n leaveEvent.target = leaveEvent.target.parent\n }\n }\n }\n\n if (outTarget !== evt.target) {\n const overType = 'pointerover'\n // TODO: clone\n const overEvent = this.clonePointEvent(evt, overType)\n\n this.dispatchEvent(overEvent, overType)\n\n let overTargetAncestor = outTarget?.parent\n\n while (overTargetAncestor && overTargetAncestor !== this.rootTarget.parent) {\n if (overTargetAncestor === evt.target) break\n\n overTargetAncestor = overTargetAncestor.parent\n }\n\n const didPointerEnter = !overTargetAncestor || overTargetAncestor === this.rootTarget.parent\n\n if (didPointerEnter) {\n const enterEvent = this.clonePointEvent(evt, 'pointerenter')\n\n while (enterEvent.target && enterEvent.target !== outTarget && enterEvent.target !== this.rootTarget.parent) {\n enterEvent.currentTarget = enterEvent.target\n\n this._notifyTarget(enterEvent)\n\n enterEvent.target = enterEvent.target.parent\n }\n }\n }\n\n this.dispatchEvent(evt, 'pointermove')\n\n const targets = this._allInteractiveElements\n for (let i = targets.length - 1; i >= 0; --i) {\n evt.currentTarget = targets[i]\n this._notifyTarget(evt, 'globalpointermove')\n }\n\n this._allInteractiveElements.length = 0\n this._hitElements.length = 0\n\n trackingData.overTargets = evt.composedPath()\n }\n\n _onPointerDown(event: PointerEvent) {\n this.rootTarget = this.renderer.renderedObject\n if (!this.rootTarget) return\n\n const evt = this.createPointEvent(event)\n this.dispatchEvent(evt, 'pointerdown')\n\n const trackingData = this.trackingData(event.pointerId)\n trackingData.pressTargetsByButton[event.button] = evt.composedPath()\n }\n\n _onPointerOverOut(event: PointerEvent) {\n this.rootTarget = this.renderer.renderedObject\n if (!this.rootTarget) return\n\n const evt = this.createPointEvent(event)\n this.dispatchEvent(evt, 'pointerout')\n }\n\n _onPointerUp(event: PointerEvent) {\n this.rootTarget = this.renderer.renderedObject\n if (!this.rootTarget) return\n\n let target = event.target\n\n // if in shadow DOM use composedPath to access target\n if (event.composedPath && event.composedPath().length > 1) {\n target = event.composedPath()[0]\n }\n\n const outside = target !== this.domElement ? 'outside' : ''\n const evt = this.createPointEvent(event)\n this.dispatchEvent(evt, `pointerup${outside}`)\n }\n\n _isInteractive(eventMode: EventMode) {\n return eventMode === 'static'\n }\n\n createPointEvent(from: PointerEvent, type?: string, target?: Container): FederatedEvent {\n const gp = this.mapPositionToPoint(from.clientX, from.clientY)\n\n if (from.type === 'pointerleave') {\n type = 'pointerout'\n }\n\n const event = new FederatedEvent(this)\n event.type = type \n event.nativeEvent = from\n event.target = target ?? this.hitTest(gp.x, gp.y) ?? this._hitElements[0],\n event.global = gp\n\n return event\n }\n\n clonePointEvent(from: FederatedEvent, type?: string) {\n const event = new FederatedEvent(this)\n\n event.nativeEvent = from.nativeEvent\n event.global = from.global\n\n event.type = type ?? from.type\n event.path = from.composedPath().slice()\n event.target = from.target\n\n return event\n }\n\n mapPositionToPoint(x: number, y: number) {\n const canvas = this.domElement as HTMLCanvasElement\n const rect = canvas.isConnected\n ? canvas.getBoundingClientRect()\n : {\n x: 0,\n y: 0,\n width: canvas.width,\n height: canvas.height,\n left: 0,\n top: 0,\n }\n const resolutionMuliplier = 1 / this.resolution\n\n const point = new Vector2()\n point.x = (x - rect.left) * (canvas.width / rect.width) * resolutionMuliplier\n point.y = (y - rect.top) * (canvas.height / rect.height) * resolutionMuliplier\n\n return point\n }\n\n hitTest(x: number,y: number) {\n const useMove = this._isPointerMoveEvent\n const invertedPath = this[useMove ? 'hitTestMoveRecursive' : 'hitTestRecursive'](\n this.rootTarget,\n this.rootTarget.eventMode,\n new Vector2(x, y),\n )\n\n return invertedPath && invertedPath[0]\n }\n\n private _interactivePrune(container: Container) {\n if (!container || !container.visible) {\n return true\n }\n\n if (container.eventMode === 'none') {\n return true\n }\n // TODO: passive\n return false\n }\n\n hitTestMoveRecursive(\n currentTarget: Container,\n eventMode: EventMode,\n location: Vector2,\n ): Container[] {\n let shouldReturn = false\n\n if (this._interactivePrune(currentTarget)) return\n\n const children = currentTarget.children\n if (children && children.length > 0) {\n for (let i = children.length - 1; i >= 0; --i) {\n const child: Container = children[i]\n\n const nestedHit = this.hitTestMoveRecursive(\n child,\n this._isInteractive(eventMode) ? eventMode : child.eventMode,\n location,\n )\n\n if (nestedHit) {\n if (nestedHit.length > 0 && !nestedHit[nestedHit.length - 1].parent) {\n continue\n }\n\n const isInteractive = this._isInteractive(currentTarget.eventMode)\n if (nestedHit.length > 0 || isInteractive) {\n if (isInteractive) this._allInteractiveElements.push(currentTarget)\n nestedHit.push(currentTarget)\n }\n\n if (this._hitElements.length === 0) {\n this._hitElements = nestedHit\n }\n\n shouldReturn = true\n }\n }\n }\n\n const isInteractiveMode = this._isInteractive(eventMode)\n const isInteractiveTarget = this._isInteractive(currentTarget.eventMode)\n\n if (isInteractiveTarget) {\n this._allInteractiveElements.push(currentTarget)\n }\n\n if (this._hitElements.length > 0) return\n\n if (shouldReturn) {\n return this._hitElements\n }\n\n if (isInteractiveMode && this.hitTestFn(currentTarget, location)) {\n return isInteractiveTarget ? [currentTarget] : []\n }\n\n return\n }\n\n hitTestRecursive(\n currentTarget: Container,\n eventMode: EventMode,\n location: Vector2,\n ): Container[] {\n // TODO: 剪枝优化\n\n const children = currentTarget.children\n for (let i = children.length - 1; i >= 0; i--) {\n const child = children[i] as Container\n\n const nestedHit = this.hitTestRecursive(\n child,\n this._isInteractive(eventMode) ? eventMode : child.eventMode,\n location,\n )\n\n if (nestedHit) {\n const isInteractive = this._isInteractive(currentTarget.eventMode)\n\n if (nestedHit.length > 0 || isInteractive) {\n nestedHit.push(currentTarget)\n }\n\n return nestedHit\n }\n }\n\n const isInteractiveMode = this._isInteractive(eventMode)\n const isInteractiveTarget = this._isInteractive(currentTarget.eventMode)\n\n if (isInteractiveMode && this.hitTestFn(currentTarget, location)) {\n return isInteractiveTarget ? [currentTarget] : []\n }\n\n return null\n }\n\n hitTestFn(container: Container, pos: Vector2) {\n if (container.hitArea) return true\n\n // ? container不为ViewContainer的情况\n if ((container as ViewContainer).containsPoint) {\n const localPos = container.worldTransform.applyInverse(pos)\n return (container as ViewContainer).containsPoint(localPos)\n }\n\n return false\n }\n}\n\n\nfunction findMountedTarget(propagationPath: Container[]) {\n if (!propagationPath) {\n return\n }\n\n let currentTarget = propagationPath[0]\n\n for (let i = 1; i < propagationPath.length; ++i) {\n if (propagationPath[i].parent === currentTarget) {\n currentTarget = propagationPath[i]\n } else {\n break\n }\n }\n\n return currentTarget\n}\n","export function clearList(list: unknown[], index?: number) {\n index ||= 0\n\n for (let i = index; i < list.length; ++i) {\n if (list[i]) {\n list[i] = null\n } else {\n break\n }\n }\n}\n\nexport function assignWithIgnore<T extends Record<string, any>>(\n target: T,\n options: T,\n ignore: Record<string, boolean> = {}\n) {\n for (const key in options) {\n if (!ignore[key] && options[key] !== undefined) {\n target[key] = options[key]\n }\n }\n}\n","export interface Instruction {\n readonly renderPipeId: string\n}\n\n/**\n * 对数组的简单封装\n * 出于性能优的考虑,不会主观的调整数组的大小\n * 因此length没有使用价值\n */\nexport class InstructionSet {\n public readonly instructions: Instruction[] = []\n public instructionSize = 0\n\n /**\n * @internal\n */\n public renderPipes: any\n\n public reset() {\n this.instructionSize = 0\n }\n\n public add(instruction: Instruction) {\n this.instructions[this.instructionSize++] = instruction\n }\n}","import { Matrix } from \"@/maths\";\nimport { Container } from \"./Container\";\nimport { InstructionSet } from \"@/renderer/InstructionSet\";\nimport { ViewContainer } from \"../ViewContainer\";\n\nexport class RenderGroup {\n public worldTransform = new Matrix()\n public localTransform = new Matrix()\n public root: Container = null\n public instructionSet = new InstructionSet()\n public structureDidChange = true\n\n public renderGroupParent: RenderGroup = null\n public renderGroupChildren: RenderGroup[] = []\n\n // 所有transform有更新的集合\n public readonly childrenToUpdate: Record<number, { list: Container[], index: number }> = Object.create(null)\n // 所有可渲染元素的集合\n public readonly childrenRenderablesToUpdate: { list: Container[], index: number } = { list: [], index: 0 }\n\n constructor(root: Container) {\n this.init(root)\n }\n\n init(root: Container) {\n this.root = root\n const children = root.children\n for (let i = 0; i < children.length; ++i) {\n this.addChild(children[i])\n }\n }\n\n addChild(child: Container) {\n this.structureDidChange = true\n\n child.parentRenderGroup = this\n\n if (child.parent === this.root) {\n child.relativeRenderGroupDepth = 1\n } else {\n child.relativeRenderGroupDepth = child.parent.relativeRenderGroupDepth + 1\n }\n\n child.didChange = true\n this.onChildUpdate(child)\n\n const children = child.children\n for (let i = 0; i < children.length; ++i) {\n this.addChild(children[i])\n }\n }\n\n removeChild(child: Container) {\n this.structureDidChange = true\n\n // TODO: ignore onRenderMixin\n\n child.parentRenderGroup = null\n if (child.renderGroup) {\n this._removeRenderGroupChild(child.renderGroup)\n return\n }\n\n const children = child.children\n\n for (let i = 0; i < children.length; ++i) {\n this.removeChild(children[i])\n }\n }\n\n public removeChildren(children: Container[]) {\n for (let i = 0; i < children.length; ++i) {\n this.removeChild(children[i])\n }\n }\n\n private _removeRenderGroupChild(renderGroupChild: RenderGroup) {\n const index = this.renderGroupChildren.indexOf(renderGroupChild)\n\n if (index > -1) {\n this.renderGroupChildren.splice(index, 1)\n }\n\n renderGroupChild.renderGroupParent = null\n }\n\n public onChildViewUpdate(child: Container) {\n this.childrenRenderablesToUpdate.list[this.childrenRenderablesToUpdate.index++] = child\n }\n\n public onChildUpdate(child: Container) {\n let childrenToUpdate = this.childrenToUpdate[child.relativeRenderGroupDepth]\n\n if (!childrenToUpdate) {\n childrenToUpdate = this.childrenToUpdate[child.relativeRenderGroupDepth] = {\n index: 0,\n list: [],\n }\n }\n\n // 不使用push为了避免频繁的数组扩缩容触发gc导致帧数抖动\n childrenToUpdate.list[childrenToUpdate.index++] = child\n }\n\n public updateRenderable(renderable: ViewContainer) {\n if (renderable.globalDisplayStatus < 0b111) return\n\n this.instructionSet.renderPipes[renderable.renderPipeId].updateRenderable(renderable)\n renderable.didViewUpdate = false\n }\n\n public destroy() {\n this.root = null\n ;(this.childrenRenderablesToUpdate as any) = null\n ;(this.childrenToUpdate as any) = null\n this.renderGroupChildren = null\n this.instructionSet = null\n }\n}","const uidCache: Record<string, number> = {\n default: -1,\n};\n\n/**\n * The names of the unique identifiers. These are used to create unique identifiers for different types of objects.\n * @category utils\n * @internal\n */\nexport type UIDNames =\n | 'default'\n | 'resource'\n | 'texture'\n | 'textureSource'\n | 'textureResource'\n | 'batcher' //\n | 'graphicsContext' //\n | 'graphicsView' //\n | 'graphicsPath' //\n | 'fillGradient' //\n | 'fillPattern' //\n | 'meshView' //\n | 'renderable' //\n | 'buffer' //\n | 'bufferResource' //\n | 'geometry'\n | 'instructionSet' //\n | 'renderTarget' //\n | 'uniform' //\n | 'spriteView' //\n | 'textView' //\n | 'tilingSpriteView' //\n | 'shader' //\n | 'renderer' //\n | 'textStyle'\n | (string & {});\n\n/**\n * Gets the next unique identifier\n * @param name - The name of the identifier.\n * @returns {number} The next unique identifier to use.\n * @category utils\n * @internal\n */\nexport function uid(name: UIDNames = 'default'): number\n{\n if (uidCache[name] === undefined)\n {\n uidCache[name] = -1;\n }\n\n return ++uidCache[name];\n}\n\n/**\n * Resets the next unique identifier to 0. This is used for some tests, dont touch or things WILL explode :)\n * @internal\n */\nexport function resetUids(): void\n{\n for (const key in uidCache)\n {\n delete uidCache[key];\n }\n}\n","import { Bounds } from '@/maths/Bounds'\nimport { ObservablePoint } from '@/maths/Point'\nimport { Texture } from '@/renderer/texture/Texture'\n\nexport * from './uid'\n\nexport function loadImage(url: string) {\n const { promise, resolve, reject } = Promise.withResolvers<{ image: HTMLImageElement, w: number, h: number }>()\n const image = document.createElement('img')\n image.src = url\n image.onload = () => {\n const w = image.naturalWidth\n const h = image.naturalHeight\n resolve({ w, h, image })\n }\n image.onerror = reject\n\n return promise\n}\n\n// export function gridWorld(gridX: number, gridY: number) {\n// const worldX = (gridX - gridY)\n// }\n\nexport function createDebug(ns: string) {\n return (...args: any[]) => {\n console.log(ns, ...args)\n }\n}\n\nexport function updateBounds(bounds: Bounds, anchor: ObservablePoint, texture: Texture) {\n const { width, height } = texture.orig\n\n bounds.minX = -anchor.x * width\n bounds.minY = -anchor.y * height\n\n bounds.maxX = bounds.minX + width\n bounds.maxY = bounds.minY + height\n}\n\nexport function applyMixins(base: any, ...mixins: Parameters<typeof Object.getOwnPropertyDescriptors>[0][]) {\n for (const mixin of mixins) {\n Object.defineProperties(base.prototype, Object.getOwnPropertyDescriptors(mixin))\n }\n}\n\n","import { Vector2 } from \".\"\n\nexport interface Observer<T> {\n _onUpdate: (point?: T) => void\n}\n\nexport class ObservablePoint {\n public _x: number\n public _y: number\n private readonly _observer: Observer<ObservablePoint>\n\n constructor(observer: Observer<ObservablePoint>, x?: number, y?: number) {\n this._x = x || 0\n this._y = y || 0\n this._observer = observer\n }\n\n public set(x = 0, y = x): this {\n if (this._x !== x || this._y !== y) {\n this._x = x\n this._y = y\n this._observer._onUpdate(this)\n }\n\n return this\n }\n\n get x() {\n return this._x\n }\n\n set x(value: number) {\n if (this._x !== value) {\n this._x = value\n this._observer._onUpdate(this)\n }\n }\n\n get y() {\n return this._y\n }\n\n set y(value: number) {\n if (this._y !== value) {\n this._y = value\n this._observer._onUpdate(this)\n }\n }\n\n public copyFrom(value: Vector2) {\n if (this.x !== value.x || this.y !== value.y) {\n this._x = value.x\n this._y = value.y\n this._observer._onUpdate(this)\n }\n return this\n }\n\n public toVector2() {\n return new Vector2(this.x, this.y)\n }\n}","/**\n * Conversion factor for converting radians to degrees.\n * @type {number} RAD_TO_DEG\n * @category maths\n * @standard\n */\nexport const RAD_TO_DEG = 180 / Math.PI;\n\n/**\n * Conversion factor for converting degrees to radians.\n * @type {number}\n * @category maths\n * @standard\n */\nexport const DEG_TO_RAD = Math.PI / 180;","'use strict';\n\nvar has = Object.prototype.hasOwnProperty\n , prefix = '~';\n\n/**\n * Constructor to create a storage for our `EE` objects.\n * An `Events` instance is a plain object whose properties are event names.\n *\n * @constructor\n * @private\n */\nfunction Events() {}\n\n//\n// We try to not inherit from `Object.prototype`. In some engines creating an\n// instance in this way is faster than calling `Object.create(null)` directly.\n// If `Object.create(null)` is not supported we prefix the event names with a\n// character to make sure that the built-in object properties are not\n// overridden or used as an attack vector.\n//\nif (Object.create) {\n Events.prototype = Object.create(null);\n\n //\n // This hack is needed because the `__proto__` property is still inherited in\n // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.\n //\n if (!new Events().__proto__) prefix = false;\n}\n\n/**\n * Representation of a single event listener.\n *\n * @param {Function} fn The listener function.\n * @param {*} context The context to invoke the listener with.\n * @param {Boolean} [once=false] Specify if the listener is a one-time listener.\n * @constructor\n * @private\n */\nfunction EE(fn, context, once) {\n this.fn = fn;\n this.context = context;\n this.once = once || false;\n}\n\n/**\n * Add a listener for a given event.\n *\n * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} context The context to invoke the listener with.\n * @param {Boolean} once Specify if the listener is a one-time listener.\n * @returns {EventEmitter}\n * @private\n */\nfunction addListener(emitter, event, fn, context, once) {\n if (typeof fn !== 'function') {\n throw new TypeError('The listener must be a function');\n }\n\n var listener = new EE(fn, context || emitter, once)\n , evt = prefix ? prefix + event : event;\n\n if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;\n else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);\n else emitter._events[evt] = [emitter._events[evt], listener];\n\n return emitter;\n}\n\n/**\n * Clear event by name.\n *\n * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.\n * @param {(String|Symbol)} evt The Event name.\n * @private\n */\nfunction clearEvent(emitter, evt) {\n if (--emitter._eventsCount === 0) emitter._events = new Events();\n else delete emitter._events[evt];\n}\n\n/**\n * Minimal `EventEmitter` interface that is molded against the Node.js\n * `EventEmitter` interface.\n *\n * @constructor\n * @public\n */\nfunction EventEmitter() {\n this._events = new Events();\n this._eventsCount = 0;\n}\n\n/**\n * Return an array listing the events for which the emitter has registered\n * listeners.\n *\n * @returns {Array}\n * @public\n */\nEventEmitter.prototype.eventNames = function eventNames() {\n var names = []\n , events\n , name;\n\n if (this._eventsCount === 0) return names;\n\n for (name in (events = this._events)) {\n if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);\n }\n\n if (Object.getOwnPropertySymbols) {\n return names.concat(Object.getOwnPropertySymbols(events));\n }\n\n return names;\n};\n\n/**\n * Return the listeners registered for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Array} The registered listeners.\n * @public\n */\nEventEmitter.prototype.listeners = function listeners(event) {\n var evt = prefix ? prefix + event : event\n , handlers = this._events[evt];\n\n if (!handlers) return [];\n if (handlers.fn) return [handlers.fn];\n\n for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {\n ee[i] = handlers[i].fn;\n }\n\n return ee;\n};\n\n/**\n * Return the number of listeners listening to a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Number} The number of listeners.\n * @public\n */\nEventEmitter.prototype.listenerCount = function listenerCount(event) {\n var evt = prefix ? prefix + event : event\n , listeners = this._events[evt];\n\n if (!listeners) return 0;\n if (listeners.fn) return 1;\n return listeners.length;\n};\n\n/**\n * Calls each of the listeners registered for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Boolean} `true` if the event had listeners, else `false`.\n * @public\n */\nEventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {\n var evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) return false;\n\n var listeners = this._events[evt]\n , len = arguments.length\n , args\n , i;\n\n if (listeners.fn) {\n if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);\n\n switch (len) {\n case 1: return listeners.fn.call(listeners.context), true;\n case 2: return listeners.fn.call(listeners.context, a1), true;\n case 3: return listeners.fn.call(listeners.context, a1, a2), true;\n case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;\n case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;\n case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;\n }\n\n for (i = 1, args = new Array(len -1); i < len; i++) {\n args[i - 1] = arguments[i];\n }\n\n listeners.fn.apply(listeners.context, args);\n } else {\n var length = listeners.length\n , j;\n\n for (i = 0; i < length; i++) {\n if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);\n\n switch (len) {\n case 1: listeners[i].fn.call(listeners[i].context); break;\n case 2: listeners[i].fn.call(listeners[i].context, a1); break;\n case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;\n case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;\n default:\n if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {\n args[j - 1] = arguments[j];\n }\n\n listeners[i].fn.apply(listeners[i].context, args);\n }\n }\n }\n\n return true;\n};\n\n/**\n * Add a listener for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.on = function on(event, fn, context) {\n return addListener(this, event, fn, context, false);\n};\n\n/**\n * Add a one-time listener for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.once = function once(event, fn, context) {\n return addListener(this, event, fn, context, true);\n};\n\n/**\n * Remove the listeners of a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn Only remove the listeners that match this function.\n * @param {*} context Only remove the listeners that have this context.\n * @param {Boolean} once Only remove one-time listeners.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {\n var evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) return this;\n if (!fn) {\n clearEvent(this, evt);\n return this;\n }\n\n var listeners = this._events[evt];\n\n if (listeners.fn) {\n if (\n listeners.fn === fn &&\n (!once || listeners.once) &&\n (!context || listeners.context === context)\n ) {\n clearEvent(this, evt);\n }\n } else {\n for (var i = 0, events = [], length = listeners.length; i < length; i++) {\n if (\n listeners[i].fn !== fn ||\n (once && !listeners[i].once) ||\n (context && listeners[i].context !== context)\n ) {\n events.push(listeners[i]);\n }\n }\n\n //\n // Reset the array, or remove it completely if we have no more listeners.\n //\n if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;\n else clearEvent(this, evt);\n }\n\n return this;\n};\n\n/**\n * Remove all listeners, or those of the specified event.\n *\n * @param {(String|Symbol)} [event] The event name.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {\n var evt;\n\n if (event) {\n evt = prefix ? prefix + event : event;\n if (this._events[evt]) clearEvent(this, evt);\n } else {\n this._events = new Events();\n this._eventsCount = 0;\n }\n\n return this;\n};\n\n//\n// Alias methods names because people roll like that.\n//\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\nEventEmitter.prototype.addListener = EventEmitter.prototype.on;\n\n//\n// Expose the prefix.\n//\nEventEmitter.prefixed = prefix;\n\n//\n// Allow `EventEmitter` to be imported as module namespace.\n//\nEventEmitter.EventEmitter = EventEmitter;\n\n//\n// Expose the module.\n//\nif ('undefined' !== typeof module) {\n module.exports = EventEmitter;\n}\n","import EventEmitter from './index.js'\n\nexport { EventEmitter }\nexport default EventEmitter\n","import { Matrix } from \"./Matrix\"\nimport { Container } from \"@/scene/container/Container\"\nimport { Rectangle } from \"./shapes/Rectangle\"\nimport { Renderable } from \"@/scene/ViewContainer\"\n\n\nexport class Bounds {\n public minX = Infinity\n public minY = Infinity\n public maxX = -Infinity\n public maxY = -Infinity\n public matrix = new Matrix()\n\n private _rectangle: Rectangle\n \n constructor(minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity) {\n this.minX = minX\n this.minY = minY\n this.maxX = maxX\n this.maxY = maxY\n }\n\n clone() {\n return new Bounds(this.minX, this.minY, this.maxX, this.maxY)\n }\n\n isEmpty() {\n return this.minX >= this.maxX || this.minY >= this.maxY\n }\n\n clear() {\n this.minX = Infinity\n this.minY = Infinity\n this.maxX = -Infinity\n this.maxY = -Infinity\n }\n\n get width() {\n return this.maxX - this.minX\n }\n set width(value: number) {\n this.maxX = this.minX + value\n }\n\n get height() {\n return this.maxY - this.minY\n }\n set height(value: number) {\n this.maxY = this.minY + value\n }\n\n get left() {\n return this.minX\n }\n get right() {\n return this.maxX\n }\n get top() {\n return this.minY\n }\n get bottom() {\n return this.maxY\n }\n\n get isValid() {\n return this.minX + this.minY !== Infinity\n }\n\n set(x0: number, y0: number, x1: number, y1: number) {\n this.minX = x0\n this.minY = y0\n this.maxX = x1\n this.maxY = y1\n }\n\n addBounds(bounds: Bounds, matrix?: Matrix) {\n this.addFrame(bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, matrix)\n }\n\n addRect(rect: Rectangle, matrix?: Matrix) {\n this.addFrame(rect.x, rect.y, rect.width + rect.x, rect.height + rect.y, matrix)\n }\n\n addFrame(x0: number, y0: number, x1: number, y1: number, matrix?: Matrix) {\n matrix ||= this.matrix\n\n const a = matrix.a\n const b = matrix.b\n const c = matrix.c\n const d = matrix.d\n const tx = matrix.tx\n const ty = matrix.ty\n\n {\n const x = a * x0 + c * y0 + tx;\n const y = b * x0 + d * y0 + ty;\n updateMinMax(x, y, this)\n }\n\n {\n const x = a * x1 + c * y0 + tx\n const y = b * x1 + d * y0 + ty\n updateMinMax(x, y, this)\n }\n\n {\n const x = a * x0 + c * y1 + tx\n const y = b * x0 + d * y1 + ty\n updateMinMax(x, y, this)\n }\n\n {\n const x = a * x1 + c * y1 + tx\n const y = b * x1 + d * y1 + ty\n updateMinMax(x, y, this)\n }\n }\n\n get rectangle() {\n if (!this._rectangle) {\n this._rectangle = new Rectangle()\n }\n\n const rectangle = this._rectangle\n\n // TODO: 有没有必要判断rectangle的合法性,即宽高是否存在小于0的情况?\n rectangle.x = this.minX\n rectangle.y = this.minY\n rectangle.width = this.maxX - this.minX\n rectangle.height = this.maxY - this.minY\n\n return rectangle\n }\n\n addBoundsMask(mask: Bounds) {\n this.minX = this.minX > mask.minX ? this.minX : mask.minX\n this.minY = this.minY > mask.minY ? this.minY : mask.minY\n this.maxX = this.maxX < mask.maxX ? this.maxX : mask.maxX\n this.maxY = this.maxY < mask.maxY ? this.maxY : mask.maxY\n }\n}\n\nfunction updateMinMax(x: number, y: number, bounds: Bounds) {\n if (x < bounds.minX) bounds.minX = x\n if (x > bounds.maxX) bounds.maxX = x\n if (y < bounds.minY) bounds.minY = y\n if (y > bounds.maxY) bounds.maxY = y\n}\n\nexport function getLocalBounds(target: Container, bounds: Bounds, relativeMatrix?: Matrix) {\n bounds.clear()\n\n relativeMatrix ||= new Matrix()\n _getLocalBounds(target, bounds, relativeMatrix, target, true)\n\n if (!bounds.isValid) {\n bounds.set(0, 0, 0, 0)\n }\n\n return bounds\n}\n\nfunction _getLocalBounds(\n target: Container,\n bounds: Bounds,\n parentTransform: Matrix,\n rootContainer: Container,\n isRoot: boolean,\n): Bounds {\n let relativeTransform = new Matrix()\n\n if (!isRoot) {\n if (!target.visible || !target.measurable) return\n\n target.updateLocalTransform()\n\n relativeTransform.appendFrom(target.localTransform, parentTransform)\n } else {\n relativeTransform.copyFrom(parentTransform)\n }\n\n const parentBounds = bounds\n // 判断后续计算边界时是否在一个独立的边界基础上进行\n const needIsolateBounds = !!target.effects.length\n\n if (needIsolateBounds) {\n bounds = new Bounds()\n }\n\n if (target.boundsArea) {\n bounds.addRect(target.boundsArea, relativeTransform)\n } else {\n if (target.renderPipeId) {\n bounds.matrix = relativeTransform\n bounds.addBounds((target as Renderable).bounds)\n }\n const children = target.children\n for (let i = 0; i < children.length; i++) {\n _getLocalBounds(children[i], bounds, relativeTransform, rootContainer, false)\n }\n\n if (needIsolateBounds) {\n for (let i = 0; i < target.effects.length; ++i) {\n target.effects[i].addLocalBounds?.(bounds, rootContainer)\n }\n\n parentBounds.addBounds(bounds, new Matrix())\n }\n }\n\n return bounds\n}\n\n","import { Instruction } from \"@/renderer/InstructionSet\"\nimport { Bounds, getLocalBounds } from \"@/maths/Bounds\"\nimport { Mask } from \"../container/mixins/effectMixin\"\nimport { Container } from \"../container/Container\"\nimport { Matrix } from \"@/maths\"\n\nexport interface StencilMaskInstruction extends Instruction {\n mask: StencilMask\n action: string\n}\n\nexport class StencilMask {\n public pipe = 'stencilMask'\n public mask?: Mask\n\n constructor(mask: Mask) {\n this.mask = mask\n mask.includeInBuild = false\n mask.measurable = false\n }\n\n public addLocalBounds(bounds: Bounds, localRoot: Container) {\n const boundsMask = new Bounds()\n\n this.mask.measurable = true\n\n const relativeMask = getMatrixRelativeToParent(this.mask, localRoot)\n\n getLocalBounds(this.mask, boundsMask, relativeMask)\n\n this.mask.measurable = false\n\n bounds.addBoundsMask(boundsMask)\n }\n}\n\nfunction getMatrixRelativeToParent(target: Container, root: Container, matrix?: Matrix) {\n matrix ||= new Matrix()\n if (target === root) {\n return matrix\n }\n\n matrix = getMatrixRelativeToParent(target.parent, root, matrix)\n\n target.updateLocalTransform()\n\n return Matrix.append(matrix, target.localTransform)\n}\n","import { Container } from \"../Container\"\nimport { StencilMask } from \"@/scene/mask/StencilMask\"\nimport { Graphics } from \"@/scene/graphics\"\n\nexport type Mask = Graphics | null\n\nexport type MaskEffect = StencilMask\n\nexport interface EffectMixinConstructor {\n mask?: Mask\n}\n\nexport interface EffectMixin extends Required<EffectMixinConstructor> {\n effects?: MaskEffect[]\n _maskEffect?: MaskEffect\n mask: Mask\n addEffect(effect: MaskEffect): void\n removeEffect(effect: MaskEffect): void\n}\n\nexport const effectMixin: Partial<Container> = {\n effects: [],\n _maskEffect: null,\n\n addEffect(effect) {\n this.effects.push(effect)\n\n this._updateIsSimple()\n },\n\n removeEffect(effect) {\n const index = this.effects.indexOf(effect)\n if (index === -1) {\n this.effects.splice(index, 1)\n }\n\n this._updateIsSimple()\n },\n\n set mask(value: Mask) {\n const effect = this._maskEffect\n if (value === effect?.mask) return\n\n if (effect) {\n this.removeEffect(effect)\n this._maskEffect = null\n }\n\n if (value == null) return\n\n // TODO: color filter stencil\n this._maskEffect = new StencilMask(value)\n\n this.addEffect(this._maskEffect)\n },\n\n get mask(): Mask {\n return this._maskEffect?.mask\n }\n}\n","import { Container } from \"../Container\";\n\nexport interface SortMixinConstructor {\n zIndex?: number\n sortDirty?: boolean\n sortableChildren?: boolean\n}\n\nexport interface SortMixin extends Required<SortMixinConstructor> {\n /**\n * @internal\n */\n _zIndex: number\n}\n\nexport const sortMixin: Partial<Container> = {\n _zIndex: 0,\n sortableChildren: false,\n sortDirty: false,\n}\n","import { Bounds, getLocalBounds } from \"@/maths/Bounds\"\nimport { Container } from \"../Container\"\n\nexport interface MeasureMixinConstructor {\n width?: number\n height?: number\n}\n\nexport interface MeasureMixin extends Required<MeasureMixinConstructor> {\n _localBoundsCacheData: any\n _localBounds: Bounds\n\n getLocalBounds: () => Bounds\n _setWidth: (value: number, localWidth: number) => void\n _setHeight: (value: number, localHeight: number) => void\n}\n\nexport const measureMixin: Partial<Container> = {\n _localBoundsCacheData: null,\n _localBounds: null,\n\n _setWidth(value: number, localWidth: number) {\n const sign = Math.sign(this.scale.x) || 1\n\n if (localWidth !== 0) {\n this.scale.x = (value / localWidth) * sign\n } else {\n this.scale.x = sign\n }\n },\n\n _setHeight(value: number, localHeight: number) {\n const sign = Math.sign(this.scale.y) || 1\n\n if (localHeight !== 0) {\n this.scale.y = (value / localHeight) * sign\n } else {\n this.scale.y = sign\n }\n },\n\n /**\n * TODO: 缓存\n */\n getLocalBounds() {\n if (!this._localBounds) {\n this._localBounds = new Bounds()\n }\n\n getLocalBounds(this, this._localBounds)\n return this._localBounds\n }\n} as Container\n","import { Container, ContainerChild } from \"@/scene\";\n\nexport interface ChildrenHelperMixin<C = Container> {\n removeChildren(beginIndex?: number, endIndex?: number): C[]\n}\n\nexport const childrenHelperMixin: ChildrenHelperMixin<ContainerChild> = {\n\n removeChildren(beginIndex = 0, endIndex?: number) {\n const end = endIndex ?? this.children.length\n const range = end - beginIndex\n const removed: Container[] = []\n\n if (range > 0 && range <= end) {\n for (let i = end - 1; i >= beginIndex; --i) {\n const child = this.children[i]\n\n if (!child) continue\n\n removed.push(child)\n child.parent = null\n }\n\n removeItems(this.children, beginIndex, end)\n\n const renderGroup = this.renderGroup || this.parentRenderGroup\n\n if (renderGroup) {\n renderGroup.removeChildren(removed)\n }\n\n // TODO: emit removed event\n // for (let i = 0; i < removed.length; ++i) {\n // const child = removed[i]\n\n // }\n\n return removed\n } else if (range === 0 && this.children.length === 0) {\n return removed\n }\n\n throw new Error('removeChildren: numeric values are outside the acceptable range.')\n }\n} as Container\n\nfunction removeItems(arr: any[], startIndex: number, removeCount: number) {\n const length = arr.length\n let i\n\n if (startIndex >= length || removeCount === 0) {\n return\n }\n\n removeCount = (startIndex + removeCount) > length ? (length - startIndex) : removeCount\n\n const len = length - removeCount\n\n for (i = startIndex; i < len; ++i) {\n arr[i] = arr[i + removeCount]\n }\n\n arr.length = len\n}\n","import { Matrix, Rectangle, Vector2 } from \"@/maths\"\nimport { EventMode } from '@/system'\nimport { RenderGroup } from './RenderGroup'\nimport { applyMixins } from '@/utils'\nimport { ObservablePoint } from '@/maths/Point'\nimport { DEG_TO_RAD, RAD_TO_DEG } from '@/maths/const'\nimport EventEmitter from \"eventemitter3\"\nimport { FederatedEventEmitterTypes } from \"@/events/FederatedEventMap\"\nimport { effectMixin, EffectMixin, EffectMixinConstructor } from \"./mixins/effectMixin\"\nimport { InstructionSet } from \"@/renderer/InstructionSet\"\nimport { sortMixin, SortMixin, SortMixinConstructor } from \"./mixins/sortMixin\"\nimport { measureMixin, MeasureMixin, MeasureMixinConstructor } from \"./mixins/measureMixin\"\nimport { assignWithIgnore } from \"./utils\"\nimport { DestroyOptions } from \"./destroyTypes\"\nimport { childrenHelperMixin, ChildrenHelperMixin } from \"./mixins/childrenHelperMixin\"\n\n/** @internal */\nexport const UPDATE_COLOR = 0b0001\n/** @internal */\nexport const UPDATE_BLEND = 0b0010\n/** @internal */\nexport const UPDATE_VISIBLE = 0b0100\n/** @internal */\nexport const UPDATE_TRANSFORM = 0b1000\n\nexport type ContainerChild = Container\n\nexport type IHitArea = {\n contains(x: number, y: number): boolean\n}\n\nconst defaultSkew = new ObservablePoint(null)\nconst defaultOrigin = new ObservablePoint(null)\nconst defaultScale = new ObservablePoint(null, 1, 1)\nconst defaultPivot = new ObservablePoint(null)\n\nexport interface ContainerEvents extends FederatedEventEmitterTypes {\n destroyed: [container: Container]\n}\n\ntype AnyEvent = {\n [K: ({} & string) | ({} & symbol)]: any\n}\n\nexport interface ContainerOptions<C extends ContainerChild = ContainerChild> extends EffectMixinConstructor, SortMixinConstructor, MeasureMixinConstructor {\n label?: string\n isRenderGroup?: boolean\n alpha?: number\n angle?: number\n children?: C[]\n parent?: Container\n rotation?: number\n scale?: Vector2 | number\n pivot?: Vector2 | number\n origin?: Vector2 | number\n position?: Vector2\n skew?: Vector2\n visible?: boolean\n x?: number\n y?: number\n boundsArea?: Rectangle\n}\n\nexport interface Container extends EffectMixin, SortMixin, MeasureMixin, ChildrenHelperMixin, EventEmitter<ContainerEvents & AnyEvent> {}\n\nexport class Container<C extends ContainerChild = ContainerChild> extends EventEmitter<ContainerEvents & AnyEvent> {\n public label: string\n public destroyed = false\n public renderGroup: RenderGroup = null\n public parentRenderGroup: RenderGroup | null = null\n public parent: Container | null = null\n public eventMode: EventMode = 'passive'\n public hitArea: IHitArea | null = null\n public boundsArea: Rectangle\n /** @internal */\n public _position = new ObservablePoint(this, 0, 0)\n // mask需要,在收集渲染元素时需要被剔除\n /** @private */\n public includeInBuild = true\n\n public readonly renderPipeId: string\n\n // 如果容器的属性被修改了,就设为true\n // 当容器的属性被transform应用了就重置为false\n /** @private */\n public didChange = false\n /** @private */\n public didViewUpdate = false\n /** @private */\n public isSimple = true\n /** @private */\n public measurable = true\n // 当前元素相对于RenderGroup的深度\n /** @private */\n public relativeRenderGroupDepth = 0\n\n public _attrUpdateTick = 0\n public _localTransformUpdateTick = 0\n /**\n * @private\n */\n public _updateFlags = 0b1111\n /**\n * @internal\n */\n public localDisplayStatus = 0b111\n /**\n * @internal\n */\n public globalDisplayStatus = 0b111\n\n public children: C[] = []\n\n public localTransform = new Matrix()\n public relativeGroupTransform = new Matrix()\n public groupTransform = this.relativeGroupTransform\n public _rotation = 0\n public _worldTransform: Matrix\n /**\n * 归一化的x坐标在x轴上的投影, cosx\n */\n public _cx = 1\n /**\n * 归一化的y坐标在x轴上的投影, sinx\n */\n public _sx = 0\n /**\n * 归一化的x坐标在y轴上的投影, cosy\n */\n public _cy = 0\n /**\n * 归一化的y坐标在y轴上的投影, siny\n */\n public _sy = 1\n\n /**\n * 在x轴和y轴上的倾斜值\n * @internal\n */\n public _skew = defaultSkew\n /**\n * @internal\n */\n public _scale = defaultScale\n /**\n * @internal\n */\n public _origin = defaultOrigin\n /**\n * @internal\n */\n public _pivot = defaultPivot\n /**\n * @internal\n */\n public localAlpha = 1\n /**\n * @internal\n */\n public groupColor = 0xFFFFFF // BGR\n /**\n * @internal\n * TODO: tint\n */\n public localColor = 0xffffff\n /**\n * @internal\n */\n public groupAlpha = 1\n /**\n * @internal\n */\n public groupColorAlpha = 0xFFFFFFFF\n\n constructor(options: ContainerOptions<C> = {}) {\n super()\n\n assignWithIgnore(this, options, {\n children: true,\n parent: true,\n effects: true,\n })\n\n // 由于是通过原型链混入,需要在实例化时隔离混入的属性防止污染\n this.effects = []\n }\n\n get renderable() {\n return !!(this.localDisplayStatus & 0b001)\n }\n\n set renderable(value: boolean) {\n const valueNumber = value ? 0b001 : 0\n\n if ((this.localDisplayStatus & 0b001) === valueNumber) return\n\n this._updateFlags |= UPDATE_VISIBLE\n this.localDisplayStatus ^= 0b001\n\n if (this.parentRenderGroup) {\n this.parentRenderGroup.structureDidChange = true\n }\n\n this._onUpdate()\n }\n\n get visible() {\n return !!(this.localDisplayStatus & 0b010)\n }\n\n set visible(value: boolean) {\n const valueNumber = value ? 0b010 : 0\n\n if ((this.localDisplayStatus & 0b010) === valueNumber) return\n\n if (this.parentRenderGroup) {\n this.parentRenderGroup.structureDidChange = true\n }\n\n this._updateFlags |= UPDATE_VISIBLE\n\n this.localDisplayStatus ^= 0b010\n\n this._onUpdate()\n }\n\n get isRenderGroup() {\n return !!this.renderGroup\n }\n\n set isRenderGroup(value: boolean) {\n if (!!this.renderGroup === value) return\n\n if (value) {\n this.enableRenderGroup()\n } else {\n this.disableRenderGroup()\n }\n }\n\n get zIndex() {\n return this._zIndex\n }\n\n set zIndex(value: number) {\n if (value === this._zIndex) return\n\n this._zIndex = value\n\n this.depthOfChildModified()\n }\n\n _updateIsSimple() {\n this.isSimple = !this.renderGroup && this.effects.length == 0\n }\n\n sortChildren() {\n if (!this.sortDirty) return\n\n this.sortDirty = false\n\n this.children.sort(sortChildren)\n }\n\n depthOfChildModified() {\n if (this.parent) {\n this.parent.sortableChildren = true\n this.parent.sortDirty = true\n }\n if (this.parentRenderGroup) {\n // TODO flag render group struct change\n }\n }\n\n enableRenderGroup() {\n if (this.renderGroup) return\n\n this.renderGroup = new RenderGroup(this)\n\n this.groupTransform = new Matrix()\n\n this._updateIsSimple()\n }\n\n disableRenderGroup() {\n if (!this.renderGroup) return\n\n const parentRenderGroup = this.parentRenderGroup\n parentRenderGroup?.removeChild(this)\n\n this.renderGroup = null\n this.groupTransform = this.relativeGroupTransform\n\n parentRenderGroup?.addChild(this)\n\n this._updateIsSimple()\n }\n\n collectRenderables(renderPipes: any, instructionSet: any) {\n if (this.globalDisplayStatus < 0b111 || !this.includeInBuild) return\n\n if (this.sortableChildren) {\n this.sortChildren()\n }\n\n if (this.isSimple) {\n this.collectRenderableSimple(renderPipes, instructionSet)\n } else if (this.renderGroup) {\n // TODO: nested rendergroup\n } else {\n this.collectRenderablesWithEffects(renderPipes, instructionSet)\n }\n }\n\n collectRenderablesWithEffects(renderPipes: any, instructionSet: InstructionSet) {\n for (let i = 0; i < this.effects.length; ++i) {\n const effect = this.effects[i]\n const pipe = renderPipes[effect.pipe]\n pipe.push(effect, instructionSet)\n\n }\n this.collectRenderableSimple(renderPipes, instructionSet)\n for (let i = 0; i < this.effects.length; ++i) {\n const effect = this.effects[i]\n const pipe = renderPipes[effect.pipe]\n pipe.pop(effect, instructionSet)\n }\n }\n\n collectRenderableSimple(renderPipes: any, instructionSet: InstructionSet) {\n const children = this.children\n for (let i = 0; i < children.length; ++i) {\n children[i].collectRenderables(renderPipes, instructionSet)\n }\n }\n\n setFromMatrix(matrix: Matrix) {\n matrix.decompose(this)\n }\n\n /**\n * 更新仿射变换矩阵\n */\n _updateSkew() {\n const rotation = this.rotation\n const skew = this.skew\n\n this._cx = Math.cos(rotation + skew.y)\n this._sx = Math.sin(rotation + skew.y)\n this._cy = -Math.sin(rotation - skew.x)\n this._sy = Math.cos(rotation - skew.x)\n }\n updateLocalTransform() {\n const localTransformChangeTick = this._attrUpdateTick\n if (this._localTransformUpdateTick === localTransformChangeTick) {\n return\n }\n this._localTransformUpdateTick = localTransformChangeTick\n\n this._updateSkew()\n\n const position = this.position\n const lt = this.localTransform\n\n const sx = this._scale.x\n const sy = this._scale.y\n const ox = -this._origin.x\n const oy = -this._origin.y\n const px = this._pivot.x\n const py = this._pivot.y\n\n lt.a = this._cx * sx\n lt.b = this._sx * sx\n lt.c = this._cy * sy\n lt.d = this._sy * sy\n lt.tx = position.x - (px * lt.a + py * lt.c) + (ox * lt.a + oy * lt.c) - ox\n lt.ty = position.y - (px * lt.b + py * lt.d) + (ox * lt.b + oy * lt.d) - oy\n }\n\n get alpha() {\n return this.localAlpha\n }\n\n set alpha(value: number) {\n if (value === this.localAlpha) return\n\n this.localAlpha = value\n\n this._updateFlags |= UPDATE_COLOR\n\n this._onUpdate()\n }\n\n get root() {\n let parent = this.parent\n let temp = this.parent\n while (parent) {\n if (!parent.parent) {\n temp = parent\n }\n parent = parent.parent\n }\n return temp\n }\n\n get worldTransform() {\n // 惰性初始化与复用\n this._worldTransform ||= new Matrix()\n if (this.renderGroup) {\n this._worldTransform.copyFrom(this.renderGroup.worldTransform)\n } else if (this.parentRenderGroup) {\n this._worldTransform.appendFrom(this.relativeGroupTransform, this.parentRenderGroup.worldTransform)\n }\n return this._worldTransform\n }\n\n get x() {\n return this._position.x\n }\n set x(value: number) {\n this._position.x = value\n }\n get position() {\n return this._position\n }\n set position(value: Vector2) {\n this._position.copyFrom(value)\n }\n get y() {\n return this._position.y\n }\n set y(value: number) {\n this._position.y = value\n }\n get rotation() {\n return this._rotation\n }\n set rotation(value: number) {\n if (this._rotation !== value) {\n this._rotation = value\n this._onUpdate(this._skew)\n }\n }\n get angle() {\n return this.rotation * RAD_TO_DEG\n }\n set angle(value: number) {\n this.rotation = value * DEG_TO_RAD\n }\n get skew() {\n if (this._skew === defaultSkew) {\n this._skew = new ObservablePoint(this, 0, 0)\n }\n return this._skew\n }\n set skew(value: Vector2) {\n if (this._skew === defaultSkew) {\n this._skew = new ObservablePoint(this, 0, 0)\n }\n this._skew.copyFrom(value)\n }\n get scale() {\n if (this._scale === defaultScale) {\n this._scale = new ObservablePoint(this, 1, 1)\n }\n return this._scale\n }\n set scale(value: Vector2) {\n if (this._scale === defaultScale) {\n this._scale = new ObservablePoint(this, 1, 1)\n }\n this._scale.copyFrom(value)\n }\n get pivot() {\n if (this._pivot === defaultPivot) {\n this._pivot = new ObservablePoint(this, 0, 0)\n }\n return this._pivot\n }\n set pivot(value: Vector2) {\n if (this._pivot === defaultPivot) {\n this._pivot = new ObservablePoint(this, 0, 0)\n }\n this._pivot.copyFrom(value)\n }\n get origin() {\n if (this._origin === defaultOrigin) {\n this._origin = new ObservablePoint(this, 0, 0)\n }\n return this._origin\n }\n set origin(value: Vector2) {\n if (this._origin === defaultOrigin) {\n this._origin = new ObservablePoint(this, 0, 0)\n }\n this._origin.copyFrom(value)\n }\n get width() {\n return Math.abs(this.scale.x * this.getLocalBounds().width)\n }\n set width(_value) {\n // const localWidth = this.getLocalBounds().width\n // 通过计算sign来保留符号\n // const sign = Math.sign(this.scale.x) || 1\n }\n\n get height() {\n return Math.abs(this.scale.y * this.getLocalBounds().height)\n }\n set height(_value) {\n\n }\n\n addChild<U extends C[]>(...children: U): U[0] {\n if (children.length > 1) {\n for (let i = 0; i < children.length; ++i) {\n this.addChild(children[i]!)\n }\n\n return children[0]!\n }\n\n const child = children[0]!\n const renderGroup = this.renderGroup || this.parentRenderGroup\n\n // 子元素重复添加即改变渲染顺序,手动将其置顶\n if (child.parent === this) {\n this.children.splice(this.children.indexOf(child), 1)\n this.children.push(child)\n\n if (renderGroup) {\n renderGroup.structureDidChange = true\n }\n\n return child\n }\n\n // 已经启用sort的情况下,有新元素被追加就标记当前元素需要重新排序\n // 估计是为了处理子元素zIndex为零的特殊情况\n if (this.sortableChildren) {\n this.sortDirty = true\n }\n\n // 存在其它父元素需要先处理掉关联关系\n if (child.parent) {\n child.parent.removeChild(child)\n }\n\n this.children.push(child)\n\n if (this.sortableChildren) {\n this.sortDirty = true\n }\n\n child.parent = this\n child.didChange = true\n\n child._updateFlags = 0b111\n\n if (renderGroup) {\n renderGroup.addChild(child)\n }\n\n if (child._zIndex != 0) {\n child.depthOfChildModified()\n }\n\n return child\n }\n\n removeChild<U extends C[]>(...children: U): U[0] | undefined {\n if (children.length > 1) {\n for (let i = 0; i < children.length; ++i) {\n this.removeChild(children[i]!)\n }\n return children[0]!\n }\n\n const child = children[0]\n if (!child) {\n return child\n }\n\n const index = this.children.indexOf(child)\n\n if (index > -1) {\n this.children.splice(index, 1)\n child.parent = null\n }\n return child\n }\n\n public _onUpdate(point?: Vector2) {\n if (point && point === this._skew) {\n this._updateSkew()\n }\n\n this._attrUpdateTick++\n\n if (this.didChange) return\n this.didChange = true\n\n if (this.parentRenderGroup) {\n this.parentRenderGroup.onChildUpdate(this)\n }\n }\n\n toGlobal(position: Vector2, skipUpdate?: boolean) {\n const globalMatrix = this.getGlobalTransform(skipUpdate)\n\n const global = globalMatrix.apply(position)\n\n return global\n }\n\n toLocal(position: Vector2, from?: Container, skipUpdate?: boolean) {\n let pos\n if (from) {\n pos = from.toGlobal(position)\n }\n\n const globalMatrix = this.getGlobalTransform(skipUpdate)\n\n pos = globalMatrix.applyInverse(position)\n return pos\n }\n\n getGlobalTransform(skipUpdate = false) {\n if (skipUpdate) {\n return this.worldTransform.clone()\n }\n\n this.updateLocalTransform()\n const m = new Matrix()\n const parentTransform = updateTransformBackwards(this, m)\n m.appendFrom(this.localTransform, parentTransform)\n\n return m\n }\n\n getGlobalPosition(skipUpdate = false) {\n if (this.parent) {\n return this.parent.toGlobal(this._position, skipUpdate)\n } else {\n return this._position.toVector2()\n }\n }\n\n public destroy(options: DestroyOptions = false) {\n if (this.destroyed) return\n this.destroyed = true\n\n let oldChildren: ContainerChild[]\n if (this.children.length) {\n oldChildren = this.removeChildren(0, this.children.length)\n }\n\n this.parent?.removeChild(this)\n this.parent = null\n this._maskEffect = null\n this.effects = null\n this._position = null\n this._scale = null\n this._pivot = null\n this._origin = null\n this._skew = null\n\n const destroyChildren = typeof options === 'boolean' ? options : options?.children\n if (destroyChildren && oldChildren) {\n for (let i = 0; i < oldChildren.length; ++i) {\n oldChildren[i].destroy(options)\n }\n }\n\n this.renderGroup?.destroy()\n this.renderGroup = null\n }\n}\n\nfunction updateTransformBackwards(target: Container, parentTransform: Matrix) {\n const parent = target.parent\n\n if (parent) {\n updateTransformBackwards(parent, parentTransform)\n parent.updateLocalTransform()\n const res = Matrix.append(parentTransform, parent.localTransform)\n parentTransform.copyFrom(res)\n }\n\n return parentTransform\n}\n\nfunction sortChildren(a: Container, b: Container) {\n return a._zIndex - b._zIndex\n}\n\napplyMixins(\n Container,\n sortMixin,\n effectMixin,\n measureMixin,\n childrenHelperMixin,\n)\n","import { Container, UPDATE_BLEND, UPDATE_COLOR, UPDATE_VISIBLE } from \"../Container\";\nimport { RenderGroup } from \"../RenderGroup\";\nimport { clearList } from \"../utils\";\n\nconst UPDATE_BLEND_COLOR_VISIBLE = (UPDATE_VISIBLE | UPDATE_COLOR | UPDATE_BLEND)\n\nexport function updateRenderGroupTransform(renderGroup?: RenderGroup, updateChildRenderGroup = false) {\n // TODO: worldColor或者worldAlpha的计算\n const root = renderGroup.root\n renderGroup.worldTransform.copyFrom(root.localTransform)\n\n // TODO: cal update tick\n const childrenToUpdate = renderGroup.childrenToUpdate\n\n for (const i in childrenToUpdate) {\n const renderGroupDepth = Number(i)\n const childrenAtDepth = childrenToUpdate[renderGroupDepth]\n const list = childrenAtDepth.list\n const index = childrenAtDepth.index\n\n for (let j = 0; j < index; ++j) {\n const child = list[j]\n if (child.parentRenderGroup === renderGroup && child.relativeRenderGroupDepth === renderGroupDepth) {\n updateTransform(child, 0)\n }\n }\n\n clearList(list, index)\n childrenAtDepth.index = 0\n }\n\n if (updateChildRenderGroup) {\n for (let i = 0; i < renderGroup.renderGroupChildren.length; ++i) {\n updateRenderGroupTransform(renderGroup.renderGroupChildren[i], updateChildRenderGroup)\n }\n }\n}\nexport function updateTransform(container: Container, updateFlags: number) {\n container.didChange = false\n\n const parent = container.parent\n const localTransform = container.localTransform\n\n container.updateLocalTransform()\n\n if (parent) {\n updateFlags |= container._updateFlags\n\n container.relativeGroupTransform.appendFrom(localTransform, parent.relativeGroupTransform)\n\n if (updateFlags & UPDATE_BLEND_COLOR_VISIBLE) {\n updateBlendColorVisible(container, parent, updateFlags)\n }\n } else {\n // container.relativeGroupTransform.copyFrom(localTransform)\n }\n\n // if (!container.renderGroup) {\n const children = container.children\n for (let i = 0; i < children.length; i++) {\n updateTransform(children[i], updateFlags)\n }\n // }\n}\n\nfunction updateBlendColorVisible(container: Container, parent: Container, updateFlags: number) {\n if (updateFlags & UPDATE_COLOR) {\n // TODO: 颜色混合 tint\n container.groupColor = parent.groupColor\n\n let groupAlpha = container.localAlpha * parent.groupAlpha\n groupAlpha = groupAlpha < 0 ? 0 : (groupAlpha > 1 ? 1 : groupAlpha)\n\n container.groupAlpha = groupAlpha\n container.groupColorAlpha = container.groupColor + (((groupAlpha * 255) | 0) << 24)\n }\n\n if (updateFlags & UPDATE_VISIBLE) {\n container.globalDisplayStatus = container.localDisplayStatus & parent.globalDisplayStatus\n }\n\n container._updateFlags = 0\n}\n","import { RenderGroup } from \"../RenderGroup\";\n\nexport function validateRenderables(renderGroup: RenderGroup, renderPipes: any) {\n const { list, index } = renderGroup.childrenRenderablesToUpdate\n\n let rebuildRequired = false\n\n for (let i = 0; i < index; ++i) {\n const renderable = list[i]\n\n const pipe = renderPipes[renderable.renderPipeId]\n\n rebuildRequired = pipe.validateRenderable(renderable)\n\n if (rebuildRequired) {\n break\n }\n }\n\n renderGroup.structureDidChange = rebuildRequired\n\n return rebuildRequired\n}","import { Matrix } from \"@/maths\";\nimport { CanvasRenderer } from \"@/renderer\";\nimport { Container, RenderGroup } from \"@/scene\";\nimport { clearList } from \"@/scene/container/utils\";\nimport { updateRenderGroupTransform } from \"@/scene/container/utils/updateRenderGroupTransform\";\nimport { validateRenderables } from \"@/scene/container/utils/validateRenderables\";\n\nexport class RenderGroupSystem {\n public renderer: CanvasRenderer;\n\n static desc = {\n name: 'renderGroup'\n } as const\n\n constructor(renderer: CanvasRenderer) {\n this.renderer = renderer\n }\n\n private _updateRenderGroup(renderGroup: RenderGroup) {\n const renderer = this.renderer\n const renderPipes = renderer.renderPipes\n\n renderGroup.instructionSet.renderPipes = renderPipes\n\n // check renderable\n // renderable元素的属性变化会影响renderGroup\n // 决定是否需要重建指令集\n if (!renderGroup.structureDidChange) {\n // 有副作用,会修改renderGroup.structureDidChange\n validateRenderables(renderGroup, renderPipes)\n } else {\n clearList(renderGroup.childrenRenderablesToUpdate.list, 0)\n }\n\n // 更新\"所有\"元素的transform\n // 包括renderable元素\n updateRenderGroupTransform(renderGroup)\n\n if (renderGroup.structureDidChange) {\n renderGroup.structureDidChange = false\n\n this._buildInstructions(renderGroup, renderer)\n } else {\n\n }\n\n renderGroup.childrenRenderablesToUpdate.index = 0;\n }\n\n render({ container, transform }: { container: Container, transform: Matrix }) {\n const renderer = this.renderer\n\n if (transform) {\n container.renderGroup.localTransform.copyFrom(transform)\n }\n\n renderer.canvasContext.globalTransform = transform ? container.renderGroup.localTransform : container.renderGroup.worldTransform\n\n this._updateRenderGroup(container.renderGroup)\n\n executeInstructions(container.renderGroup, renderer.renderPipes)\n }\n\n _buildInstructions(renderGroup: RenderGroup, renderer: CanvasRenderer) {\n const renderPipes = renderer.renderPipes\n const root = renderGroup.root\n renderGroup.instructionSet.reset()\n\n if (root.sortableChildren) {\n root.sortChildren()\n }\n\n renderPipes.batch.buildStart()\n // renderPipes.batch = new BatchPipe()\n\n root.collectRenderablesWithEffects(renderPipes, renderGroup.instructionSet)\n\n renderPipes.batch.buildEnd(renderGroup.instructionSet)\n }\n\n}\n\nfunction executeInstructions(renderGroup: RenderGroup, renderPipes: any) {\n const { instructionSet } = renderGroup\n const instructions = instructionSet.instructions\n\n for (let i = 0; i < instructionSet.instructionSize; i++) {\n const instruction = instructions[i]\n const pipe = renderPipes[instruction.renderPipeId]\n pipe.execute(instruction)\n }\n}\n","import { CanvasRenderer } from \"@/renderer\";\nimport { Sprite } from \"./Sprite\";\nimport { InstructionSet } from \"@/renderer/InstructionSet\";\n\nexport class SpritePipe {\n private _renderer: CanvasRenderer\n static desc = {\n name: 'sprite',\n } as const\n\n constructor(renderer: CanvasRenderer) {\n this._renderer = renderer\n }\n\n addRenderable(sprite: Sprite, instructionSet: InstructionSet) {\n this._renderer.renderPipes.batch.addToBatch({\n renderable: sprite,\n texture: sprite.texture,\n transform: sprite.relativeGroupTransform,\n bounds: sprite.bounds,\n roundPixels: this._renderer._roundPixels | sprite._roundPixels,\n }, instructionSet)\n }\n\n public destroy() {\n this._renderer = null\n }\n}\n","import { CanvasRenderer } from \"@/renderer\";\nimport { Text } from \"./Text\";\nimport { InstructionSet } from \"@/renderer/InstructionSet\";\nimport { updateBounds } from \"@/utils\";\nimport { Texture } from \"@/main\";\n\nexport class TextPipe {\n public static desc = {\n name: 'text',\n } as const\n\n private _renderer: CanvasRenderer;\n\n constructor(renderer: CanvasRenderer) {\n this._renderer = renderer\n }\n\n addRenderable(text: Text, instructionSet: InstructionSet) {\n const batchableText = this._getRuntimeText(text)\n\n if (text._didTextUpdate) {\n const resolution = text._autoResolution ? this._renderer.resolution : text.resolution\n if (batchableText.currentKey !== text.styleKey || text._resolution !== resolution) {\n this._updateRuntimeText(text)\n }\n text._didTextUpdate = false\n updateBounds(batchableText.bounds, text._anchor, batchableText.texture)\n }\n\n this._renderer.renderPipes.batch.addToBatch(batchableText, instructionSet)\n }\n\n validateRenderable(text: Text) {\n const batchableText = this._getRuntimeText(text)\n\n const newKey = text.styleKey\n\n if (batchableText.currentKey !== newKey) return true\n\n return text._didTextUpdate\n }\n\n public initCacheText(text: Text) {\n const batchableText = {\n currentKey: '--',\n transform: text.relativeGroupTransform,\n bounds: text.bounds,\n roundPixels: this._renderer._roundPixels | text._roundPixels,\n renderable: text,\n texture: null as Texture | null,\n destroy: function () {\n this.renderable = null;\n this.texture = null;\n this.bounds = null;\n }\n }\n\n text._runtimeData[this._renderer.uid] = batchableText\n // TODO: gc\n\n return batchableText\n }\n\n private _getRuntimeText(text: Text) {\n return text._runtimeData[this._renderer.uid] || this.initCacheText(text)\n }\n\n private _updateRuntimeText(text: Text) {\n const batchableText = this._getRuntimeText(text)\n\n if (batchableText.texture) {\n // TODO: gc texture\n }\n\n text._resolution = text._autoResolution ? this._renderer.resolution : text.resolution\n\n batchableText.texture = this._renderer.text.getManagedTexture(text)\n batchableText.currentKey = text.styleKey\n }\n\n public destroy() {\n this._renderer = null\n }\n}\n","import { Bounds } from \"@/maths/Bounds\"\nimport { Container } from \"./container/Container\"\nimport { Vector2 } from \"@/maths\"\nimport { InstructionSet } from \"@/renderer/InstructionSet\"\nimport { DestroyOptions } from \"./container/destroyTypes\"\n\nexport type Renderable = ViewContainer\n\nexport interface RuntimeData {\n destroy: () => void\n}\n\nexport abstract class ViewContainer<RUNTIME_DATA extends RuntimeData = any> extends Container {\n public _runtimeData: Record<number, RUNTIME_DATA> = Object.create(null)\n\n /** @internal */\n public _resolution: number\n public _roundPixels: 0 | 1 = 0\n protected _bounds = new Bounds(0, 1, 0, 0)\n public get bounds() {\n this.updateBounds()\n\n return this._bounds\n }\n\n protected abstract updateBounds(): void\n\n protected onViewUpdate() {\n if (this.didViewUpdate) return\n this.didViewUpdate = true\n\n const renderGroup = this.renderGroup || this.parentRenderGroup\n\n if (renderGroup) {\n renderGroup.onChildViewUpdate(this)\n }\n }\n\n override collectRenderableSimple(renderPipes: Record<string, any>, instructionSet: InstructionSet): void {\n const pipe = renderPipes[this.renderPipeId]\n if (pipe && pipe.addRenderable) {\n pipe.addRenderable(this, instructionSet)\n }\n this.didViewUpdate = false\n\n const children = this.children\n\n for (let i = 0; i < children.length; ++i) {\n children[i].collectRenderables(renderPipes, instructionSet)\n }\n // switch (this.renderPipeId) {\n // case 'sprite':\n // renderPipes.batch.addRenderable(this)\n // break\n // case 'graphics':\n // instructionSet.push(this)\n // break\n // }\n // if (this.re)\n // batch.addRenderable(this)\n }\n\n containsPoint(point: Vector2) {\n const bounds = this.bounds\n const { x, y } = point\n\n return (x > bounds.minX && x < bounds.maxX && y > bounds.minY && y < bounds.maxY)\n }\n\n get roundPixels(): boolean {\n return !!this._roundPixels\n }\n set roundPixels(value: boolean) {\n this._roundPixels = value ? 1 : 0\n }\n\n override destroy(options: DestroyOptions = false) {\n for (const key in this._runtimeData) {\n this._runtimeData[key].destroy()\n }\n this._runtimeData = Object.create(null)\n this.onViewUpdate()\n\n super.destroy(options)\n this._bounds = null\n }\n}","import { Rectangle } from \"./Rectangle\"\n\nexport class Polygon {\n public points: number[] = []\n public closePath: boolean\n\n public readonly type = 'polygon'\n\n construction() {\n\n }\n\n get lastX() {\n return this.points[this.points.length - 2]\n }\n\n get lastY() {\n return this.points[this.points.length - 1]\n }\n\n public getBounds() {\n const out = new Rectangle()\n\n const points = this.points\n\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n\n for (let i = 0; i < points.length; i += 2) {\n const x = points[i]\n const y = points[i + 1]\n\n minX = Math.min(minX, x)\n minY = Math.min(minY, y)\n maxX = Math.max(maxX, x)\n maxY = Math.max(maxY, y)\n }\n\n out.x = minX\n out.width = maxX - minX\n\n out.y = minY\n out.height = maxY - minY\n\n return out\n }\n}","// thanks to https://github.com/mattdesl/adaptive-bezier-curve\n// for the original code!\nconst RECURSION_LIMIT = 8;\nconst FLT_EPSILON = 1.19209290e-7;\nconst PATH_DISTANCE_EPSILON = 1.0;\n\nconst curveAngleToleranceEpsilon = 0.01;\nconst mAngleTolerance = 0;\nconst mCuspLimit = 0;\n\n/**\n * @param points\n * @param sX\n * @param sY\n * @param cp1x\n * @param cp1y\n * @param cp2x\n * @param cp2y\n * @param eX\n * @param eY\n * @param smoothness\n * @internal\n */\nexport function buildAdaptiveBezier(\n points: number[],\n sX: number, sY: number,\n cp1x: number, cp1y: number,\n cp2x: number, cp2y: number,\n eX: number, eY: number,\n smoothness?: number,\n)\n{\n // TODO expose as a parameter\n const scale = 1;\n const smoothing = Math.min(\n 0.99, // a value of 1.0 actually inverts smoothing, so we cap it at 0.99\n Math.max(0, smoothness ?? 0.5)\n );\n let distanceTolerance = (PATH_DISTANCE_EPSILON - smoothing) / scale;\n\n distanceTolerance *= distanceTolerance;\n begin(sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, points, distanceTolerance);\n\n return points;\n}\n\n// //// Based on:\n// //// https://github.com/pelson/antigrain/blob/master/agg-2.4/src/agg_curves.cpp\n\nfunction begin(\n sX: number, sY: number,\n cp1x: number, cp1y: number,\n cp2x: number, cp2y: number,\n eX: number, eY: number,\n points: number[],\n distanceTolerance: number\n)\n{\n // dont need to actually ad this!\n // points.push(sX, sY);\n recursive(sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, points, distanceTolerance, 0);\n points.push(eX, eY);\n}\n\n// eslint-disable-next-line max-params\nfunction recursive(\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n x4: number, y4: number,\n points: number[],\n distanceTolerance: number,\n level: number)\n{\n if (level > RECURSION_LIMIT)\n { return; }\n\n const pi = Math.PI;\n\n // Calculate all the mid-points of the line segments\n // ----------------------\n const x12 = (x1 + x2) / 2;\n const y12 = (y1 + y2) / 2;\n const x23 = (x2 + x3) / 2;\n const y23 = (y2 + y3) / 2;\n const x34 = (x3 + x4) / 2;\n const y34 = (y3 + y4) / 2;\n const x123 = (x12 + x23) / 2;\n const y123 = (y12 + y23) / 2;\n const x234 = (x23 + x34) / 2;\n const y234 = (y23 + y34) / 2;\n const x1234 = (x123 + x234) / 2;\n const y1234 = (y123 + y234) / 2;\n\n if (level > 0)\n { // Enforce subdivision first time\n // Try to approximate the full cubic curve by a single straight line\n // ------------------\n let dx = x4 - x1;\n let dy = y4 - y1;\n\n const d2 = Math.abs(((x2 - x4) * dy) - ((y2 - y4) * dx));\n const d3 = Math.abs(((x3 - x4) * dy) - ((y3 - y4) * dx));\n\n let da1; let da2;\n\n if (d2 > FLT_EPSILON && d3 > FLT_EPSILON)\n {\n // Regular care\n // -----------------\n if ((d2 + d3) * (d2 + d3) <= distanceTolerance * ((dx * dx) + (dy * dy)))\n {\n // If the curvature doesn't exceed the distanceTolerance value\n // we tend to finish subdivisions.\n // ----------------------\n if (mAngleTolerance < curveAngleToleranceEpsilon)\n {\n points.push(x1234, y1234);\n\n return;\n }\n\n // Angle & Cusp Condition\n // ----------------------\n const a23 = Math.atan2(y3 - y2, x3 - x2);\n\n da1 = Math.abs(a23 - Math.atan2(y2 - y1, x2 - x1));\n da2 = Math.abs(Math.atan2(y4 - y3, x4 - x3) - a23);\n if (da1 >= pi) da1 = (2 * pi) - da1;\n if (da2 >= pi) da2 = (2 * pi) - da2;\n\n if (da1 + da2 < mAngleTolerance)\n {\n // Finally we can stop the recursion\n // ----------------------\n points.push(x1234, y1234);\n\n return;\n }\n\n if (mCuspLimit !== 0.0)\n {\n if (da1 > mCuspLimit)\n {\n points.push(x2, y2);\n\n return;\n }\n\n if (da2 > mCuspLimit)\n {\n points.push(x3, y3);\n\n return;\n }\n }\n }\n }\n else if (d2 > FLT_EPSILON)\n {\n // p1,p3,p4 are collinear, p2 is considerable\n // ----------------------\n if (d2 * d2 <= distanceTolerance * ((dx * dx) + (dy * dy)))\n {\n if (mAngleTolerance < curveAngleToleranceEpsilon)\n {\n points.push(x1234, y1234);\n\n return;\n }\n\n // Angle Condition\n // ----------------------\n da1 = Math.abs(Math.atan2(y3 - y2, x3 - x2) - Math.atan2(y2 - y1, x2 - x1));\n if (da1 >= pi) da1 = (2 * pi) - da1;\n\n if (da1 < mAngleTolerance)\n {\n points.push(x2, y2);\n points.push(x3, y3);\n\n return;\n }\n\n if (mCuspLimit !== 0.0)\n {\n if (da1 > mCuspLimit)\n {\n points.push(x2, y2);\n\n return;\n }\n }\n }\n }\n else if (d3 > FLT_EPSILON)\n {\n // p1,p2,p4 are collinear, p3 is considerable\n // ----------------------\n if (d3 * d3 <= distanceTolerance * ((dx * dx) + (dy * dy)))\n {\n if (mAngleTolerance < curveAngleToleranceEpsilon)\n {\n points.push(x1234, y1234);\n\n return;\n }\n\n // Angle Condition\n // ----------------------\n da1 = Math.abs(Math.atan2(y4 - y3, x4 - x3) - Math.atan2(y3 - y2, x3 - x2));\n if (da1 >= pi) da1 = (2 * pi) - da1;\n\n if (da1 < mAngleTolerance)\n {\n points.push(x2, y2);\n points.push(x3, y3);\n\n return;\n }\n\n if (mCuspLimit !== 0.0)\n {\n if (da1 > mCuspLimit)\n {\n points.push(x3, y3);\n\n return;\n }\n }\n }\n }\n else\n {\n // Collinear case\n // -----------------\n dx = x1234 - ((x1 + x4) / 2);\n dy = y1234 - ((y1 + y4) / 2);\n if ((dx * dx) + (dy * dy) <= distanceTolerance)\n {\n points.push(x1234, y1234);\n\n return;\n }\n }\n }\n\n // Continue subdivision\n // ----------------------\n recursive(x1, y1, x12, y12, x123, y123, x1234, y1234, points, distanceTolerance, level + 1);\n recursive(x1234, y1234, x234, y234, x34, y34, x4, y4, points, distanceTolerance, level + 1);\n}\n\n","import { Polygon } from \"@/maths/shapes/Polygon\";\nimport { GraphicsPath } from \"./GraphicsPath\";\nimport { Bounds } from \"@/maths/Bounds\";\nimport { buildAdaptiveBezier } from \"./buildAdaptiveBezier\";\nimport { Rectangle } from \"@/maths\";\n\nexport interface ShapePrimitive {\n type: 'rectangle' | 'polygon'\n getBounds(): Rectangle;\n}\n\nexport class ShapePath {\n private _currentPoly: Polygon | null\n public shapePrimitives: { shape: ShapePrimitive }[] = []\n private _graphicsPath: GraphicsPath\n private _bounds: Bounds = new Bounds()\n constructor(graphicsPath: GraphicsPath) {\n this._graphicsPath = graphicsPath\n }\n\n private _ensurePoly(start = true) {\n if (this._currentPoly) return\n\n this._currentPoly = new Polygon()\n\n if (start) {\n // TODO: last shape\n // const lastShape = this.shapePrimitives[this.shapePrimitives.length - 1]\n // if (lastShape) {\n\n // }\n\n this._currentPoly.points.push(0, 0)\n }\n }\n\n public lineTo(x: number, y: number) {\n this._ensurePoly()\n\n const points = this._currentPoly.points\n\n const fromX = points[points.length - 2]\n const fromY = points[points.length - 1]\n\n if (fromX !== x || fromY !== y) {\n points.push(x, y)\n }\n return this\n }\n\n public rect(x: number, y: number, w: number, h: number) {\n this.drawShape(new Rectangle(x, y, w, h))\n\n return this\n }\n\n public drawShape(shape: Rectangle) {\n this.endPloy()\n\n this.shapePrimitives.push({ shape })\n return this\n }\n\n public moveTo(x: number, y: number) {\n this.startPoly(x, y)\n return this\n }\n\n public bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number, smoothness?: number) {\n this._ensurePoly()\n\n const points = this._currentPoly.points\n\n buildAdaptiveBezier(\n points,\n this._currentPoly.lastX,\n this._currentPoly.lastY,\n cp1x, cp1y,\n cp2x, cp2y,\n x, y,\n smoothness\n )\n \n return this\n }\n\n public startPoly(x: number, y: number) {\n if (this._currentPoly) {\n this.endPloy()\n }\n\n this._currentPoly = new Polygon()\n this._currentPoly.points.push(x, y)\n return this\n }\n\n public endPloy(closePath = false) {\n const shape = this._currentPoly\n \n if (shape && shape.points.length > 2) {\n shape.closePath = closePath\n\n this.shapePrimitives.push({ shape })\n }\n this._currentPoly = null\n }\n\n public closePath() {\n this.endPloy(true)\n return this\n }\n\n buildPath() {\n const path = this._graphicsPath\n\n for (let i = 0; i < path.instructions.length; ++i) {\n const instruction = path.instructions[i]\n\n this[instruction.action](...(instruction.data as [number, number, number, number, number, number?]))\n }\n\n return this\n }\n\n get bounds() {\n const bounds = this._bounds\n bounds.clear()\n\n const shapePrimitives = this.shapePrimitives\n\n for (let i = 0; i < shapePrimitives.length; ++i) {\n const shapePrimitive = shapePrimitives[i]\n\n const boundRect = shapePrimitive.shape.getBounds()\n\n // TODO: transform\n\n bounds.addRect(boundRect)\n }\n\n return bounds\n }\n}\n","import { Bounds } from \"@/maths/Bounds\"\nimport { ShapePath } from \"./ShapePath\"\n\ntype PathInstruction = {\n action: 'moveTo' | 'lineTo' | 'closePath' | 'bezierCurveTo' | 'rect'\n data: any[]\n}\nexport class GraphicsPath {\n public instructions: PathInstruction[] = []\n private _dirty = true\n private _shapePath: ShapePath\n\n public rect(x: number, y: number, w: number, h: number) {\n this.instructions.push({ action: 'rect', data: [x, y, w, h]})\n this._dirty = true\n return this\n }\n public lineTo(...args: [number, number]) {\n this.instructions.push({ action: 'lineTo', data: args })\n this._dirty = true\n return this\n }\n\n public bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number, smoothness?: number): this\n public bezierCurveTo(...args: number[]) {\n this.instructions.push({ action: 'bezierCurveTo', data: args })\n return this\n }\n\n public moveTo(...args: [number, number]) {\n this.instructions.push({ action: 'moveTo', data: args })\n return this\n }\n public closePath() {\n this.instructions.push({ action: 'closePath', data: [] })\n this._dirty = true\n return this\n\n }\n\n get shapePath() {\n if (!this._shapePath) {\n this._shapePath = new ShapePath(this)\n }\n\n if (this._dirty) {\n this._dirty = false\n this._shapePath.buildPath()\n }\n\n return this._shapePath\n }\n\n get bounds(): Bounds {\n return this.shapePath.bounds\n }\n\n getLastPoint() {\n let index = this.instructions.length - 1\n\n const lastInstruction = this.instructions[index]\n\n if (!lastInstruction) {\n return { x: 0, y: 0 }\n }\n\n switch (lastInstruction.action) {\n case 'moveTo':\n case 'lineTo':\n return {\n x: lastInstruction.data[0],\n y: lastInstruction.data[1],\n }\n }\n\n return {\n x: 0,\n y: 0\n }\n }\n\n clear() {\n this.instructions.length = 0\n this._dirty = true\n }\n\n clone() {\n const newPath = new GraphicsPath()\n\n newPath.instructions = this.instructions.slice()\n return newPath\n }\n}\n","import { Bounds } from \"@/maths/Bounds\"\nimport { GraphicsPath } from \"./path/GraphicsPath\"\n\ninterface StrokeAttributes {\n width?: number\n /**\n * 1: inside\n * 0.5: center\n * 0: outside\n */\n alignment?: number\n cap?: 'butt' | 'round' | 'square'\n join?: 'round' | 'bevel' | 'miter'\n miterLimit?: number\n pixelLine?: boolean\n alpha?: number\n}\n\ninterface FillStyle {\n color?: string\n}\n\ntype FillInstruction = {\n action: 'fill',\n data: { style: ConvertedFillStyle, path: GraphicsPath }\n}\ntype StrokeInstruction = {\n action: 'stroke',\n data: { style: ConvertedStrokeStyle, path: GraphicsPath }\n}\ntype GraphicsInstruction = FillInstruction | StrokeInstruction\n\ntype ConvertedStrokeStyle = Required<StrokeAttributes & Omit<Required<FillStyle>, 'color'> & { color: string }>\ntype ConvertedFillStyle = { color: string, alpha: number }\n\nexport class GraphicsContext {\n _strokeStyle: ConvertedStrokeStyle\n\n static defaultStrokeStyle: ConvertedStrokeStyle = {\n width: 1,\n color: '#ffffff',\n alignment: 0.5,\n miterLimit: 10,\n cap: 'butt',\n join: 'miter',\n pixelLine: false,\n alpha: 1,\n }\n\n private _activePath = new GraphicsPath()\n private _bounds = new Bounds()\n public instructions: GraphicsInstruction[] = []\n\n setStrokeStyle(style: StrokeAttributes & FillStyle) {\n this._strokeStyle = toStrokeStyle(style, GraphicsContext.defaultStrokeStyle)\n }\n\n public clear(): this {\n this._activePath.clear()\n this.instructions.length = 0\n this.onUpdate()\n\n return this\n }\n\n protected onUpdate() {\n }\n\n moveTo(x: number, y: number) {\n this._activePath.moveTo(x, y)\n return this\n }\n\n lineTo(x: number, y: number) {\n this._activePath.lineTo(x, y)\n return this\n }\n\n bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number, smoothness?: number) {\n this._activePath.bezierCurveTo(\n cp1x, cp1y, cp2x, cp2y, x, y, smoothness\n )\n return this\n }\n\n rect(x: number, y: number, w: number, h: number) {\n this._activePath.rect(x, y, w, h)\n return this\n }\n\n beginPath() {\n this._activePath = new GraphicsPath()\n return this\n }\n\n closePath() {\n this._activePath.closePath()\n return this\n }\n\n fill(color: string) {\n const fillStyle = {\n ...(GraphicsContext.defaultStrokeStyle),\n color,\n }\n this.instructions.push({\n action: 'fill',\n data: { style: fillStyle, path: this._activePath.clone() }\n })\n return this\n }\n\n stroke() {\n this.instructions.push({\n action: 'stroke',\n data: { style: this._strokeStyle, path: this._activePath.clone() }\n })\n this._initNextPathLocation()\n }\n\n private _initNextPathLocation() {\n const { x, y } = this._activePath.getLastPoint()\n this._activePath.clear()\n this._activePath.moveTo(x, y)\n }\n \n get bounds() {\n // TODO: dirty\n\n const bounds = this._bounds\n bounds.clear()\n\n for (let i = 0; i < this.instructions.length; ++i) {\n const instruction = this.instructions[i]\n const action = instruction.action\n\n if (action === 'fill') {\n const data = instruction.data\n bounds.addBounds(data.path.bounds)\n } else if (action === 'stroke') {\n const data = instruction.data\n const alignment = data.style.alignment\n\n const outerPadding = data.style.width * (1 - alignment)\n\n if (data.style.join === 'miter') {\n // TODO: cal miter\n }\n\n const _bounds = data.path.bounds\n\n bounds.addFrame(\n _bounds.minX - outerPadding,\n _bounds.minY - outerPadding,\n _bounds.maxX + outerPadding,\n _bounds.maxY + outerPadding,\n )\n }\n }\n\n return bounds\n }\n\n public clone() {\n const clone = new GraphicsContext()\n\n clone.instructions = this.instructions.slice()\n clone._activePath = this._activePath.clone()\n clone._bounds = this._bounds.clone()\n clone._strokeStyle = { ...this._strokeStyle }\n\n return clone\n }\n}\n\nfunction toStrokeStyle(style: StrokeAttributes & FillStyle, defaultStyle: ConvertedStrokeStyle) {\n return {\n ...defaultStyle,\n ...style,\n }\n}\n","import { ViewContainer } from \"../ViewContainer\";\nimport { GraphicsContext } from \"./GraphicsContext\";\n\nexport class Graphics extends ViewContainer {\n public override renderPipeId: string = 'graphics'\n context: GraphicsContext\n constructor(options?: GraphicsContext) {\n super()\n if (options instanceof GraphicsContext) {\n this.context = options\n } else {\n this.context = new GraphicsContext()\n }\n }\n\n setStrokeStyle(...args: Parameters<GraphicsContext['setStrokeStyle']>) {\n return this._callContextMethod('setStrokeStyle', args)\n }\n\n rect(x: number, y: number, w: number, h: number): this\n rect(...args: Parameters<GraphicsContext['rect']>) {\n return this._callContextMethod('rect', args)\n }\n\n bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cpy2y: number, x: number, y: number): this\n bezierCurveTo(...args: Parameters<GraphicsContext['bezierCurveTo']>) {\n return this._callContextMethod('bezierCurveTo', args)\n }\n\n lineTo(...args: Parameters<GraphicsContext['lineTo']>) {\n return this._callContextMethod('lineTo', args)\n }\n\n moveTo(...args: Parameters<GraphicsContext['moveTo']>) {\n return this._callContextMethod('moveTo', args)\n }\n\n stroke(...args: Parameters<GraphicsContext['stroke']>) {\n return this._callContextMethod('stroke', args)\n }\n\n beginPath(): this {\n return this._callContextMethod('beginPath', [])\n }\n\n closePath(): this {\n return this._callContextMethod('closePath', [])\n }\n\n fill(color: string): this {\n return this._callContextMethod('fill', [color])\n }\n\n private _callContextMethod(method: keyof GraphicsContext, args: any[]) {\n (this.context as any)[method](...args)\n\n return this\n }\n protected updateBounds(): void {}\n\n override get bounds() {\n return this.context.bounds\n }\n\n public clear(): this {\n return this._callContextMethod('clear', [])\n }\n}","import { CanvasRenderer } from \"@/renderer\"\nimport { Graphics } from \"./Graphics\"\nimport { InstructionSet } from \"@/renderer/InstructionSet\"\nimport { Polygon } from \"@/maths/shapes/Polygon\"\nimport { ShapePrimitive } from \"./path/ShapePath\"\nimport { Rectangle } from \"@/maths\"\n\nexport class GraphicsPipe {\n private _renderer: CanvasRenderer\n public static desc = {\n name: 'graphics',\n } as const\n\n constructor(renderer: CanvasRenderer) {\n this._renderer = renderer\n }\n\n addRenderable(graphics: Graphics, instructionSet: InstructionSet) {\n this._renderer.renderPipes.batch.break(instructionSet)\n instructionSet.add(graphics)\n }\n\n execute(instruction: Graphics) {\n const renderer = this._renderer\n const contextSystem = renderer.canvasContext\n\n const ctx = contextSystem.activeConext\n const roundPixels = renderer.roundPixels\n\n const groupColorAlpha = instruction.groupColorAlpha\n const groupAlpha = ((groupColorAlpha >>> 24) & 0xFF) / 255\n\n if (groupAlpha <= 0) return\n\n ctx.save()\n\n contextSystem.setContextTransform(\n instruction.relativeGroupTransform,\n roundPixels,\n )\n\n for (let i = 0; i < instruction.context.instructions.length; ++i) {\n const ins = instruction.context.instructions[i]\n const style = ins.data.style as any\n const alpha = style.alpha * groupAlpha\n if (alpha <= 0) continue\n\n ctx.globalAlpha = alpha\n const isStroke = ins.action === 'stroke'\n\n if (isStroke) {\n\n const canvasStyle = style.color\n ctx.lineWidth = style.width\n ctx.lineCap = style.cap\n ctx.lineJoin = style.join\n ctx.miterLimit = style.miterLimit\n ctx.strokeStyle = canvasStyle\n }\n else {\n const style = ins.data.style\n ctx.fillStyle = style.color\n }\n const shapePath = ins.data.path.shapePath\n const shapePrimitives = shapePath.shapePrimitives\n\n for (let s = 0; s < shapePrimitives.length; ++s) {\n const primitive = shapePrimitives[s]\n if (!primitive.shape) continue \n\n ctx.beginPath()\n buildShapePath(ctx, primitive.shape)\n if (isStroke) {\n ctx.stroke()\n } else {\n ctx.fill()\n }\n }\n // TODO: stroke geometry\n }\n\n\n ctx.restore()\n }\n\n public destroy() {\n this._renderer = null\n }\n}\n\nexport function buildShapePath(ctx: CanvasRenderingContext2D, shape: ShapePrimitive) {\n switch (shape.type) {\n case 'rectangle': {\n const rect = shape as Rectangle\n ctx.rect(rect.x, rect.y, rect.width, rect.height)\n break\n }\n case 'polygon': {\n const poly = shape as Polygon\n const points = poly.points\n if (!points.length) return\n\n ctx.moveTo(points[0], points[1])\n for (let i = 2; i < points.length; i += 2) {\n ctx.lineTo(points[i], points[i + 1])\n }\n if (poly.closePath) {\n ctx.closePath()\n }\n break\n }\n }\n}\n","import { CanvasRenderer } from \"@/renderer\";\nimport { Batcher } from \"./Batcher\";\nimport { Matrix } from \"@/maths\";\nimport { Instruction, InstructionSet } from \"@/renderer/InstructionSet\";\nimport { Container } from \"@/main\";\nimport { Bounds } from \"@/maths/Bounds\";\nimport { Texture } from \"@/renderer/texture/Texture\";\n\nexport type BatchableElement = {\n renderable: Container\n texture: Texture\n transform: Matrix\n bounds: Bounds\n roundPixels: number\n getColor: () => number\n}\n\nexport class Batch implements Instruction {\n renderPipeId: string = 'batch'\n\n elements: BatchableElement[] = []\n}\n\nexport class BatchPipe {\n private _renderer: CanvasRenderer\n private _activeBatch: Batcher\n\n public static desc = {\n name: 'batch',\n } as const\n\n constructor(renderer: CanvasRenderer) {\n this._renderer = renderer\n }\n\n get batch() {\n return this._activeBatch\n }\n\n buildStart() {\n this._activeBatch = new Batcher()\n }\n\n buildEnd(instructionSet: InstructionSet) {\n this.break(instructionSet)\n // this._activeBatch.build(instructionSet)\n }\n\n break(instructionSet: InstructionSet) {\n this._activeBatch.build(instructionSet)\n }\n\n addToBatch(batchElement: Omit<BatchableElement, 'getColor'>, _instructionSet: InstructionSet) {\n this._activeBatch.add({\n ...batchElement,\n getColor: () => batchElement.renderable.groupColorAlpha,\n })\n }\n\n execute(batch: Batch) {\n const elements = batch.elements\n\n if (!elements || !elements.length) return\n\n const renderer = this._renderer\n const contextSystem = renderer.canvasContext\n const ctx = contextSystem.activeConext\n\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i]\n const roundPixels = element.roundPixels\n const argb = element.getColor()\n const elementAlpha = ((argb >>> 24) & 0xFF) / 255\n\n const alpha = elementAlpha\n\n if (alpha <= 0) continue\n\n ctx.globalAlpha = alpha\n\n contextSystem.setContextTransform(\n element.transform,\n roundPixels === 1,\n )\n\n const bounds = element.bounds\n const texture = element.texture as Texture\n const frame = texture.frame\n const resolution = texture.source._resolution || 1\n const sx = frame.x * resolution\n const sy = frame.y * resolution\n const sw = frame.width * resolution\n const sh = frame.height * resolution\n const dx = bounds.minX\n const dy = bounds.minY\n const dw = bounds.maxX - bounds.minX\n const dh = bounds.maxY - bounds.minY\n\n // TODO: rotate\n const drawX = dx\n const drawY = dy\n const drawW = dw\n const drawH = dh\n\n ctx.drawImage(\n texture.source.resource,\n sx,\n sy,\n sw,\n sh,\n drawX,\n drawY,\n drawW,\n drawH,\n )\n }\n }\n\n public destroy() {\n this._renderer = null\n this._activeBatch?.destroy()\n this._activeBatch = null\n }\n}","import { InstructionSet } from \"@/renderer/InstructionSet\"\nimport { Batch, BatchableElement } from \"./BatcherPipe\"\n\nexport class Batcher {\n public renderPipeId = 'batch'\n public elements: BatchableElement[] = []\n public elementSize = 0\n\n add(elm: BatchableElement) {\n this.elements[this.elementSize++] = elm\n }\n\n build(instructionSet: InstructionSet) {\n const batch = new Batch()\n const elements = this.elements\n // TODO: Maybe need elementStart\n if (!elements[0]) return\n\n for (let i = 0; i < elements.length; i++) {\n const elm = elements[i]\n\n this.elements[i] = null\n batch.elements.push(elm)\n }\n instructionSet.add(batch)\n }\n\n public destroy() {\n this.elements = null\n }\n}\n","import { nextPow2 } from \"@/maths\";\n\nexport type CanvasAndContext = {\n canvas: HTMLCanvasElement | OffscreenCanvas\n context: CanvasRenderingContext2D\n}\n\nclass CanvasPoolClass {\n private _canvasPool: Record<string | number, CanvasAndContext[]>\n constructor() {\n this._canvasPool = Object.create(null)\n }\n public getOptimalCanvasAndContext(minWidth: number, minHeight: number, resolution = 1) {\n const _minWidth = nextPow2((minWidth * resolution) - 1e-6)\n const _minHeight = nextPow2((minHeight * resolution) - 1e-6)\n\n const key = _minWidth << 17 + _minHeight << 1\n \n if (!this._canvasPool[key]) {\n this._canvasPool[key] = []\n }\n\n const canvasAndContext = this._canvasPool[key].pop()\n\n if (!canvasAndContext) {\n const canvas = document.createElement('canvas')\n canvas.width = _minWidth\n canvas.height = _minHeight\n return { canvas, context: canvas.getContext('2d') }\n } else {\n return canvasAndContext\n }\n }\n}\n\nexport const CanvasPool = new CanvasPoolClass();\n","import { uid } from \"@/utils/uid\";\nimport { DestroyOptions } from \"../container/destroyTypes\";\n\n/**\n * The alignment of the text.\n *\n * - 'left': Aligns text to the left edge.\n * - 'center': Centers text horizontally.\n * - 'right': Aligns text to the right edge.\n * - 'justify': Justifies text, aligning both left and right edges.\n * @example\n * ```ts\n * import { TextStyle } from 'pixi.js';\n * const style = new TextStyle({\n * align: 'center', // or 'left', 'right', 'justify'\n * });\n * ```\n * @category text\n * @standard\n */\nexport type TextStyleAlign = 'left' | 'center' | 'right' | 'justify';\n/**\n * The font style input for text styles. Controls the slant or italicization of the text.\n * @example\n * ```ts\n * // Create text with normal font style\n * const normalText = new Text({\n * text: 'Normal Style Text',\n * style: {\n * fontStyle: 'normal',\n * fontSize: 24\n * }\n * });\n *\n * // Create italic text\n * const italicText = new Text({\n * text: 'Italic Style Text',\n * style: {\n * fontStyle: 'italic',\n * fontSize: 24,\n * fontFamily: 'Arial'\n * }\n * });\n *\n * // Create oblique text\n * const obliqueText = new Text({\n * text: 'Oblique Style Text',\n * style: {\n * fontStyle: 'oblique',\n * fontSize: 24,\n * fontFamily: 'Times New Roman'\n * }\n * });\n *\n * // Dynamic style changes\n * let isItalic = false;\n * text.style = {\n * ...text.style,\n * fontStyle: isItalic ? 'italic' : 'normal'\n * };\n * ```\n *\n * Supported values:\n * - 'normal': Regular upright text with no slant\n * - 'italic': True italics using specifically designed italic glyphs\n * - 'oblique': Slanted version of the regular glyphs\n * @remarks\n * - 'italic' uses specially designed glyphs with cursive characteristics\n * - 'oblique' is a mechanical slant of the normal glyphs\n * - Not all fonts include true italic designs; some may fall back to oblique\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/font-style | MDN font-style}\n * @category text\n * @standard\n */\nexport type TextStyleFontStyle = 'normal' | 'italic' | 'oblique';\n/**\n * The font variant input for text styles. Controls the capitalization and presentation of letters.\n * Used to enable special rendering like small caps.\n * @example\n * ```ts\n * // Create text with normal font variant\n * const normalText = new Text({\n * text: 'Normal Text',\n * style: {\n * fontVariant: 'normal',\n * fontSize: 24\n * }\n * });\n *\n * // Create text with small-caps variant\n * const smallCapsText = new Text({\n * text: 'Small Caps Text',\n * style: {\n * fontVariant: 'small-caps',\n * fontSize: 24,\n * fontFamily: 'Arial'\n * }\n * });\n *\n * // Use in a TextStyle instance\n * const style = new TextStyle({\n * fontVariant: 'small-caps',\n * fontSize: 32,\n * fill: 0x4a4a4a\n * });\n *\n * // Update variant dynamically\n * text.style = {\n * ...text.style,\n * fontVariant: text.style.fontVariant === 'normal' ? 'small-caps' : 'normal'\n * };\n * ```\n *\n * Supported values:\n * - 'normal': Regular text rendering with standard capitalization\n * - 'small-caps': Renders lowercase letters as smaller versions of capital letters\n * @remarks\n * Small caps are only available if the font supports them.\n * Not all fonts include true small caps glyphs.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant | MDN font-variant}\n * @category text\n * @standard\n */\nexport type TextStyleFontVariant = 'normal' | 'small-caps';\n/**\n * The font weight input for text styles. Controls the thickness or boldness of the text.\n * @example\n * ```ts\n * // Create text with different font weights\n * const normalText = new Text({\n * text: 'Normal Weight',\n * style: { fontWeight: 'normal' }\n * });\n *\n * const boldText = new Text({\n * text: 'Bold Weight',\n * style: { fontWeight: 'bold' }\n * });\n *\n * // Using numeric weights\n * const lightText = new Text({\n * text: 'Light Weight',\n * style: { fontWeight: '300' }\n * });\n *\n * const mediumText = new Text({\n * text: 'Medium Weight',\n * style: { fontWeight: '500' }\n * });\n *\n * const heavyText = new Text({\n * text: 'Heavy Weight',\n * style: { fontWeight: '900' }\n * });\n *\n * // Responsive weight changes\n * const adaptiveText = new Text({\n * text: 'Adaptive Weight',\n * style: { fontWeight: window.innerWidth > 600 ? 'bold' : 'normal' }\n * });\n * ```\n *\n * Supported values:\n * - 'normal': Standard weight (equivalent to 400)\n * - 'bold': Bold weight (equivalent to 700)\n * - 'bolder': One weight darker than the parent element\n * - 'lighter': One weight lighter than the parent element\n * - '100': Thin (Hairline)\n * - '200': Extra Light (Ultra Light)\n * - '300': Light\n * - '400': Normal\n * - '500': Medium\n * - '600': Semi Bold (Demi Bold)\n * - '700': Bold\n * - '800': Extra Bold (Ultra Bold)\n * - '900': Heavy (Black)\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight | MDN font-weight}\n * @category text\n * @standard\n */\nexport type TextStyleFontWeight =\n | 'normal' // Standard weight (400)\n | 'bold' // Bold weight (700)\n | 'bolder' // Relative weight increase\n | 'lighter' // Relative weight decrease\n | '100' // Thin\n | '200' // Extra Light\n | '300' // Light\n | '400' // Normal\n | '500' // Medium\n | '600' // Semi Bold\n | '700' // Bold\n | '800' // Extra Bold\n | '900'; // Heavy\n/**\n * The line join style for text strokes. Determines how lines connect at corners.\n * @example\n * ```ts\n * // Create text with miter joins (sharp corners)\n * const sharpText = new Text({\n * text: 'Sharp Corners',\n * style: {\n * fontSize: 36,\n * stroke: {\n * color: '#4a1850',\n * width: 4,\n * lineJoin: 'miter' // Sharp corners\n * }\n * }\n * });\n *\n * // Create text with round joins\n * const roundText = new Text({\n * text: 'Rounded Corners',\n * style: {\n * fontSize: 36,\n * stroke: {\n * color: '#4a1850',\n * width: 4,\n * lineJoin: 'round' // Smooth rounded corners\n * }\n * }\n * });\n *\n * // Create text with beveled joins\n * const bevelText = new Text({\n * text: 'Beveled Corners',\n * style: {\n * fontSize: 36,\n * stroke: {\n * color: '#4a1850',\n * width: 4,\n * lineJoin: 'bevel' // Flattened corners\n * }\n * }\n * });\n * ```\n * Available values:\n * - 'miter': Creates sharp corners by extending the outer edges until they meet\n * - 'round': Creates smooth, rounded corners using a circular arc\n * - 'bevel': Creates flattened corners by filling an additional triangle between the outer edges\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin | MDN lineJoin}\n * @category text\n * @standard\n */\nexport type TextStyleLineJoin = 'miter' | 'round' | 'bevel';\n/**\n * The text baseline for text styles.\n *\n * This can be:\n * - 'alphabetic': The alphabetic baseline\n * - 'top': The top of the text\n * - 'hanging': The hanging baseline\n * - 'middle': The middle of the text\n * - 'ideographic': The ideographic baseline\n * - 'bottom': The bottom of the text\n * @category text\n * @standard\n */\nexport type TextStyleTextBaseline = 'alphabetic' | 'top' | 'hanging' | 'middle' | 'ideographic' | 'bottom';\n/**\n * Controls how whitespace (spaces, tabs, and line breaks) is handled within the text.\n * This affects text wrapping and spacing behavior.\n * @example\n * ```ts\n * // Normal mode (collapse spaces and newlines)\n * const normalText = new Text({\n * text: 'Hello World\\n\\nNew Line',\n * style: {\n * whiteSpace: 'normal',\n * fontSize: 24\n * }\n * }); // Renders as: \"Hello World New Line\"\n *\n * // Pre mode (preserve all whitespace)\n * const preText = new Text({\n * text: 'Hello World\\n\\nNew Line',\n * style: {\n * whiteSpace: 'pre',\n * fontSize: 24\n * }\n * }); // Preserves spaces and line breaks exactly\n *\n * // Pre-line mode (preserve newlines, collapse spaces)\n * const preLineText = new Text({\n * text: 'Hello World\\n\\nNew Line',\n * style: {\n * whiteSpace: 'pre-line',\n * fontSize: 24\n * }\n * }); // Preserves line breaks, collapses multiple spaces\n *\n * // With word wrap enabled\n * const wrappedText = new Text({\n * text: 'A long text with multiple spaces\\nand line breaks',\n * style: {\n * whiteSpace: 'pre-line',\n * wordWrap: true,\n * wordWrapWidth: 200,\n * fontSize: 24\n * }\n * });\n * ```\n *\n * Supported values:\n * - 'normal': Collapses all whitespace (spaces, tabs, line breaks) into a single space\n * - 'pre': Preserves all whitespace characters exactly as written\n * - 'pre-line': Preserves line breaks but collapses multiple spaces into a single space\n * @remarks\n * - 'normal' is best for single-line text or when you want to ignore formatting\n * - 'pre' is useful for code blocks or when exact spacing is important\n * - 'pre-line' is good for formatted text where you want to keep line breaks but clean up spaces\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/white-space | MDN white-space}\n * @see {@link TextStyle#wordWrap} For controlling text wrapping\n * @category text\n * @standard\n */\nexport type TextStyleWhiteSpace = 'normal' | 'pre' | 'pre-line';\n/**\n * Defines a drop shadow effect for text rendering.\n * Drop shadows add depth and emphasis to text by creating a shadow offset from the text.\n * @example\n * ```ts\n * // Create text with basic drop shadow\n * const text = new Text({\n * text: 'Shadow Text',\n * style: {\n * fontSize: 48,\n * dropShadow: {\n * alpha: 0.5, // 50% opacity shadow\n * angle: Math.PI / 6, // 30 degrees\n * blur: 4, // Soft shadow edge\n * color: '#000000', // Black shadow\n * distance: 6 // Shadow offset\n * }\n * }\n * });\n *\n * // Dynamic shadow updates\n * text.style.dropShadow = {\n * alpha: Math.sin(Date.now() / 1000) * 0.5 + 0.5, // Pulsing opacity\n * angle: Date.now() / 1000, // Rotating angle\n * blur: 4,\n * color: '#000000',\n * distance: 6\n * };\n * ```\n * @category text\n * @standard\n */\nexport type TextDropShadow = {\n /**\n * The opacity of the drop shadow.\n * - Range: 0 to 1\n * - 0 = fully transparent\n * - 1 = fully opaque\n * @example\n * ```ts\n * // Set drop shadow opacity to 50%\n * dropShadow: {\n * alpha: 0.5\n * }\n * ```\n * @default 1\n */\n alpha: number;\n\n /**\n * The angle of the drop shadow in radians.\n * - 0 = right\n * - Math.PI/2 = down\n * - Math.PI = left\n * - Math.PI*1.5 = up\n * @example\n * ```ts\n * // Set drop shadow angle to 30 degrees\n * dropShadow: {\n * angle: Math.PI / 6 // 30 degrees\n * }\n * ```\n * @default Math.PI/6 (30 degrees)\n */\n angle: number;\n\n /**\n * The blur radius of the shadow.\n * - 0 = sharp shadow\n * - Higher values = softer shadow\n * @example\n * ```ts\n * // Set drop shadow blur radius to 10 pixels\n * dropShadow: {\n * blur: 10\n * }\n * ```\n * @default 0\n */\n blur: number;\n\n /**\n * The color of the drop shadow.\n * Accepts any valid CSS color string, hex number, or RGB/RGBA values.\n * @example '#000000', 'rgba(0,0,0,0.5)', 0x000000\n * @default 'black'\n */\n color: string;\n\n /**\n * The distance of the drop shadow from the text.\n * Measured in pixels.\n * @example\n * ```ts\n * // Set drop shadow distance to 5 pixels\n * dropShadow: {\n * distance: 5\n * }\n * ```\n * @default 5\n */\n distance: number;\n};\n/**\n * Constructor options used for `TextStyle` instances. Defines the visual appearance and layout of text.\n * @example\n * ```ts\n * // Basic text style\n * const basicStyle = new TextStyle({\n * fontSize: 24,\n * fill: 'black',\n * fontFamily: 'Arial'\n * });\n *\n * // Rich text style with multiple features\n * const richStyle = new TextStyle({\n * fontFamily: ['Arial', 'Helvetica', 'sans-serif'],\n * fontSize: 36,\n * fontWeight: 'bold',\n * fill: 'red',\n * stroke: { color: '#4a1850', width: 5 },\n * align: 'center',\n * dropShadow: {\n * color: '#000000',\n * blur: 4,\n * distance: 6,\n * angle: Math.PI / 6\n * },\n * wordWrap: true,\n * wordWrapWidth: 440,\n * lineHeight: 40,\n * textBaseline: 'middle'\n * });\n * ```\n * @see {@link TextStyle} For the main style class\n * @category text\n * @standard\n */\nexport interface TextStyleOptions\n{\n /**\n * Alignment for multiline text, does not affect single line text\n * @default 'left'\n */\n align?: TextStyleAlign;\n /**\n * Whether to allow line breaks within words.\n * Requires wordWrap to be true.\n * @example\n * ```ts\n * // Enable word breaking\n * const style = new TextStyle({\n * breakWords: true,\n * wordWrap: true,\n * wordWrapWidth: 200\n * });\n * ```\n * @default false\n */\n breakWords?: boolean;\n /**\n * Drop shadow configuration for the text.\n * Can be boolean or a TextDropShadow object.\n * @default null\n */\n dropShadow?: boolean | Partial<TextDropShadow>;\n /**\n * Fill style for the text.\n * Can be a color, gradient, or pattern.\n * @default 'black'\n */\n fill?: string;\n /**\n * Font family or families to use.\n * Can be single name or array of fallbacks.\n * @example\n * ```ts\n * // Single font family\n * fontFamily: 'Arial'\n * // Multiple font families\n * fontFamily: ['Helvetica', 'Arial', 'sans-serif']\n * ```\n * @default 'Arial'\n */\n fontFamily?: string | string[];\n /**\n * Font size in pixels or as string.\n *\n * Equivalents are '26px','20pt','160%' or '1.6em')\n * @example\n * ```ts\n * // Numeric size\n * fontSize: 26\n * // String size\n * fontSize: '26px'\n * // Percentage size\n * fontSize: '160%' // 1.6 times the parent element's font size\n * // Em size\n * fontSize: '1.6em' // 1.6 times the parent element's font size\n * @default 26\n */\n fontSize?: number | string;\n /**\n * Font style (normal, italic, oblique).\n * @default 'normal'\n */\n fontStyle?: TextStyleFontStyle;\n /**\n * Font variant (normal, small-caps).\n * @default 'normal'\n */\n fontVariant?: TextStyleFontVariant;\n /**\n * Font weight (normal, bold, bolder, lighter, 100-900).\n * @default 'normal'\n */\n fontWeight?: TextStyleFontWeight;\n /** The height of the line, a number that represents the vertical space that a letter uses. */\n leading?: number;\n /** The amount of spacing between letters, default is 0 */\n letterSpacing?: number;\n /** The line height, a number that represents the vertical space that a letter uses */\n lineHeight?: number;\n /**\n * Padding around the text.\n *\n * Occasionally some fonts are cropped. Adding some padding will prevent this from\n * happening by adding padding to all sides of the text.\n */\n padding?: number;\n /**\n * Stroke style for text outline.\n * @default null\n */\n stroke?: string;\n /**\n * Vertical alignment baseline.\n * @default 'alphabetic'\n */\n textBaseline?: TextStyleTextBaseline;\n /**\n * Whether to trim transparent edges.\n * > [!NOTE] This is an expensive operation and should only be used when necessary.\n * @default false\n */\n trim?: boolean;\n /**\n * How to handle whitespace.\n *\n * It needs wordWrap to be set to true for this to have an effect.\n * @default 'pre'\n */\n whiteSpace?: TextStyleWhiteSpace;\n /** Indicates if word wrap should be used */\n wordWrap?: boolean;\n /** The width at which text will wrap, it needs wordWrap to be set to true */\n wordWrapWidth?: number;\n /**\n * Custom styles to apply to specific tags within the text.\n * Allows for rich text formatting using simple tag markup like `<red>text</red>`.\n *\n * Tags are only parsed when this property has entries. If `tagStyles` is empty or undefined,\n * `<` characters in text are treated as literal.\n *\n * Nested tags are supported via a style stack - inner tags inherit from outer tags\n * but can override specific properties.\n * @example\n * ```ts\n * const text = new Text({\n * text: '<red>Red</red>, <blue>Blue</blue>, <big>Big</big>',\n * style: {\n * fontFamily: 'Arial',\n * fontSize: 24,\n * fill: 'white',\n * tagStyles: {\n * red: { fill: 'red' },\n * blue: { fill: 'blue' },\n * big: { fontSize: 48 }\n * }\n * }\n * });\n * ```\n * @default undefined\n */\n tagStyles?: Record<string, TextStyleOptions>;\n}\n\nexport class TextStyle {\n public uid = uid('textStyle')\n public static defaultStyle: TextStyleOptions = {\n align: 'left',\n breakWords: false,\n dropShadow: null,\n fill: 'black',\n fontFamily: 'Arial',\n fontSize: 26,\n fontStyle: 'normal',\n fontVariant: 'normal',\n fontWeight: 'normal',\n leading: 0,\n letterSpacing: 0,\n lineHeight: 0,\n padding: 0,\n stroke: null,\n textBaseline: 'alphabetic',\n trim: false,\n whiteSpace: 'pre',\n wordWrap: false,\n wordWrapWidth: 100\n }\n\n private _cachedFontString: string\n private _fontSize: number\n private _fontFamily: string | string[]\n private _fontStyle: TextStyleFontStyle\n private _lineHeight: number\n private _leading: number\n private _fontVariant: TextStyleFontVariant\n private _fontWeight: TextStyleFontWeight\n private _letterSpacing: number\n private _textBaseline: TextStyleTextBaseline\n private _align: TextStyleAlign\n private _wordWrap: boolean\n private _fill: string\n\n public _tick = 0\n\n constructor(style: Partial<TextStyleOptions>) {\n const fullStyle = { ...TextStyle.defaultStyle, ...style }\n\n for (const key in fullStyle) {\n const thisKey = key as keyof typeof this\n this[thisKey] = fullStyle[key as keyof TextStyleOptions] as any\n }\n }\n\n public get styleKey(): string {\n return `${this.uid}-${this._tick}`;\n }\n\n get fontSize() {\n return this._fontSize\n }\n\n set fontSize(value: number) {\n if (this._fontSize === value) return\n\n this._fontSize = value\n this.update()\n }\n\n get fill() {\n return this._fill\n }\n\n set fill(value: string) {\n if (this._fill === value) return\n this._fill = value\n this.update()\n }\n\n get align() {\n return this._align\n }\n\n set align(value: TextStyleAlign) {\n if (this._align === value) return\n\n this._align = value\n this.update()\n }\n\n get wordWarp() {\n return this._wordWrap\n }\n\n set wordWrap(value: boolean) {\n if (this._wordWrap === value) return\n\n this._wordWrap = value\n this.update()\n }\n\n get fontFamily() {\n return this._fontFamily\n }\n\n set fontFamily(value: string | string[]) {\n if (this._fontFamily === value) return\n\n this._fontFamily = value\n this.update()\n }\n\n get leading() {\n return this._leading\n }\n set leading(value: number) {\n if (this._leading === value) return\n\n this._leading = value\n this.update()\n }\n\n get fontStyle() {\n return this._fontStyle\n }\n\n set fontStyle(value: TextStyleFontStyle) {\n if (this._fontStyle === value) return\n\n this._fontStyle = value.toLowerCase() as TextStyleFontStyle\n this.update()\n }\n\n get textBaseline() {\n return this._textBaseline\n }\n\n set textBaseline(value: TextStyleTextBaseline) {\n this._textBaseline = value\n this.update()\n }\n\n get lineHeight() {\n return this._lineHeight\n }\n\n set lineHeight(value: number) {\n if (this._lineHeight === value) return\n\n this._lineHeight = value\n this.update()\n }\n\n get letterSpacing() {\n return this._letterSpacing\n }\n\n set letterSpacing(value: number) {\n if (this._letterSpacing === value) return\n\n this._letterSpacing = value\n this.update()\n }\n\n get fontVariant() {\n return this._fontVariant\n }\n\n set fontVariant(value: TextStyleFontVariant) {\n if (this._fontVariant === value) return\n\n this._fontVariant = value\n this.update()\n }\n\n get fontWeight() {\n return this._fontWeight\n }\n\n set fontWeight(value: TextStyleFontWeight) {\n if (this._fontWeight === value) return\n\n this._fontWeight = value\n this.update()\n }\n\n get _fontString() {\n if (this._cachedFontString === null) {\n this._cachedFontString = fontStringFromTextStyle(this)\n }\n return this._cachedFontString\n }\n\n update() {\n this._tick++\n this._cachedFontString = null\n }\n\n public destroy(_options: DestroyOptions = false) {\n // const destroyTexture = typeof options === 'boolean' ? options : options?.texture\n\n // if (destroyTexture) {\n // const destroyTextureSource = typeof options === 'boolean' ? options : options?.textureSource\n // }\n this._fill = null\n }\n}\n\nconst genericFontFamilies = [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n];\nexport function fontStringFromTextStyle(style: TextStyle): string\n{\n // build canvas api font setting from individual components. Convert a numeric style.fontSize to px\n const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize;\n\n // Clean-up fontFamily property by quoting each font name\n // this will support font names with spaces\n let fontFamilies: string | string[] = style.fontFamily;\n\n if (!Array.isArray(style.fontFamily))\n {\n fontFamilies = style.fontFamily.split(',');\n }\n\n for (let i = fontFamilies.length - 1; i >= 0; i--)\n {\n // Trim any extra white-space\n let fontFamily = fontFamilies[i].trim();\n\n // Check if font already contains strings\n if (!(/([\\\"\\'])[^\\'\\\"]+\\1/).test(fontFamily) && !genericFontFamilies.includes(fontFamily))\n {\n fontFamily = `\"${fontFamily}\"`;\n }\n (fontFamilies as string[])[i] = fontFamily;\n }\n\n // eslint-disable-next-line max-len\n return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${(fontFamilies as string[]).join(',')}`;\n}\n","import { CanvasAndContext, CanvasPool } from \"@/renderer/CanvasPool\";\nimport { fontStringFromTextStyle, TextStyle } from \"./TextStyle\"\nimport { Rectangle } from \"@/maths/shapes/Rectangle\";\n\nexport const NEWLINE_MATCH_REGEX = /(?:\\r\\n|\\r|\\n)/;\n\n/**\n * A number, or a string containing a number.\n * @category text\n * @typedef {object} FontMetrics\n * @property {number} ascent - Font ascent\n * @property {number} descent - Font descent\n * @property {number} fontSize - Font size\n * @advanced\n */\nexport interface FontMetrics\n{\n ascent: number;\n descent: number;\n fontSize: number;\n}\n\nexport class TextMetrics {\n public text: string\n public style: TextStyle\n public width: number\n public height: number\n public lines: string[]\n public lineWidths: number[]\n public lineHeight: number\n public maxLineWidth: number\n public fontProperties: FontMetrics\n /**\n * String used for calculate font metrics.\n * These characters are all tall to help calculate the height required for text.\n */\n public static METRICS_STRING = '|ÉqÅ';\n\n /** Baseline symbol for calculate font metrics. */\n public static BASELINE_SYMBOL = 'M';\n private static _canvas: HTMLCanvasElement | OffscreenCanvas\n private static _context: CanvasRenderingContext2D\n // TODO tiny-lru\n private static readonly _measurementCache = new Map()\n /** Cache of {@link TextMetrics.FontMetrics} objects. */\n private static _fonts: Record<string, FontMetrics> = {};\n\n constructor(\n text: string,\n style: TextStyle,\n width: number,\n height: number,\n lines: string[],\n lineWidths: number[],\n lineHeight: number,\n maxLineWidth: number,\n fontProperties: FontMetrics\n ) {\n this.text = text\n this.style = style\n this.width = width\n this.height = height\n this.lines = lines\n this.lineWidths = lineWidths\n this.lineHeight = lineHeight\n this.maxLineWidth = maxLineWidth\n this.fontProperties = fontProperties\n }\n\n static get canvas() {\n if (!TextMetrics._canvas) {\n let canvas\n try {\n const c = new OffscreenCanvas(0, 0)\n const context = c.getContext('2d', { willReadFrequently: true })\n\n if (context.measureText) {\n TextMetrics._canvas = c\n return c\n }\n\n canvas = createCanvas(10, 10)\n } catch (_ctx) {\n canvas = createCanvas(10, 10)\n }\n TextMetrics._canvas = canvas\n }\n\n return TextMetrics._canvas\n }\n\n static get context() {\n if (!TextMetrics._context) {\n TextMetrics._context = TextMetrics.canvas.getContext('2d', { willReadFrequently: true }) as unknown as CanvasRenderingContext2D\n }\n return TextMetrics._context\n\n }\n\n static measureText(text: string, style: TextStyle): TextMetrics {\n const textKey = `${text}-${style.styleKey}`\n\n if (TextMetrics._measurementCache.has(textKey)) {\n return TextMetrics._measurementCache.get(textKey)\n }\n\n const font = style._fontString\n const fontProperties = TextMetrics.measureFont(font)\n // fallback in case UA disallow canvas data extraction\n if (fontProperties.fontSize === 0) {\n fontProperties.fontSize = style.fontSize as number;\n fontProperties.ascent = style.fontSize as number;\n fontProperties.descent = 0;\n }\n\n const context = TextMetrics.context\n context.font = font\n\n // TODO: wordWrap\n\n const lines = text.split(NEWLINE_MATCH_REGEX)\n const lineWidths = new Array<number>(lines.length)\n let maxLineWidth = 0\n\n for (let i = 0; i < lines.length; ++i) {\n const lineWidth = TextMetrics._measureText(lines[i], style.letterSpacing)\n\n lineWidths[i] = lineWidth\n maxLineWidth = Math.max(maxLineWidth, lineWidth)\n }\n\n // TODO: stroke\n const lineHeight = style.lineHeight || fontProperties.fontSize\n\n // TODO: adjust with stroke or shadow\n const width = maxLineWidth\n const baseHeight = Math.max(lineHeight, fontProperties.fontSize + (lines.length - 1) * (lineHeight + style.leading))\n // TODO: adjust with shadow\n const height = baseHeight\n\n const measurements = new TextMetrics(\n text,\n style,\n width,\n height,\n lines,\n lineWidths,\n lineHeight,\n maxLineWidth,\n fontProperties\n )\n TextMetrics._measurementCache.set(textKey, measurements)\n\n return measurements\n }\n\n public static _measureText(text: string, letterSpacing: number) {\n const context = TextMetrics.context\n context.letterSpacing = '0px'\n // @ts-expect-error: For Chrome < 94\n context.textLetterSpacing = letterSpacing\n\n const metrics = context.measureText(text)\n let metricWidth = metrics.width\n let letterSpacingVal = 0\n\n if (metricWidth > 0) {\n letterSpacingVal = (TextMetrics.graphemeSegmenter(text).length - 1) * letterSpacing\n metricWidth += letterSpacingVal\n }\n\n const actualBoundingBoxLeft = -(metrics.actualBoundingBoxLeft ?? 0);\n const actualBoundingBoxRight = metrics.actualBoundingBoxRight ?? 0;\n let boundsWidth = actualBoundingBoxRight - actualBoundingBoxLeft;\n\n if (metrics.width > 0)\n {\n boundsWidth += letterSpacingVal;\n }\n\n return Math.max(metricWidth, boundsWidth);\n }\n\n /**\n * A Unicode \"character\", or \"grapheme cluster\", can be composed of multiple Unicode code points,\n * such as letters with diacritical marks (e.g. `'\\u0065\\u0301'`, letter e with acute)\n * or emojis with modifiers (e.g. `'\\uD83E\\uDDD1\\u200D\\uD83D\\uDCBB'`, technologist).\n * The new `Intl.Segmenter` API in ES2022 can split the string into grapheme clusters correctly. If it is not available,\n * PixiJS will fallback to use the iterator of String, which can only spilt the string into code points.\n * If you want to get full functionality in environments that don't support `Intl.Segmenter` (such as Firefox),\n * you can use other libraries such as [grapheme-splitter]{@link https://www.npmjs.com/package/grapheme-splitter}\n * or [graphemer]{@link https://www.npmjs.com/package/graphemer} to create a polyfill. Since these libraries can be\n * relatively large in size to handle various Unicode grapheme clusters properly, PixiJS won't use them directly.\n */\n public static graphemeSegmenter: (s: string) => string[] = (() =>\n {\n if (typeof Intl?.Segmenter === 'function')\n {\n const segmenter = new Intl.Segmenter();\n\n return (s: string) =>\n {\n const segments = segmenter.segment(s);\n const result = [];\n\n let i = 0;\n\n for (const segment of segments)\n {\n result[i++] = (segment.segment);\n }\n\n return result;\n };\n }\n\n return (s: string) => [...s];\n })();\n\n /**\n * Calculates the ascent, descent and fontSize of a given font-style\n * @param font - String representing the style of the font\n * @returns Font properties object\n */\n public static measureFont(font: string): FontMetrics {\n // as this method is used for preparing assets, don't recalculate things if we don't need to\n if (TextMetrics._fonts[font])\n {\n return TextMetrics._fonts[font];\n }\n\n const context = TextMetrics.context;\n\n context.font = font;\n const metrics = context.measureText(TextMetrics.METRICS_STRING + TextMetrics.BASELINE_SYMBOL);\n\n const ascent = metrics.actualBoundingBoxAscent ?? 0;\n const descent = metrics.actualBoundingBoxDescent ?? 0;\n\n const properties = {\n ascent,\n descent,\n fontSize: ascent + descent\n };\n\n TextMetrics._fonts[font] = properties;\n\n return properties;\n }\n}\n\nexport function createCanvas(width?: number, height?: number) {\n const canvas = document.createElement('canvas')\n canvas.width = width\n canvas.height = height\n return canvas\n}\n\nexport function generateTextTexture(options: { text: string, style: TextStyle, resolution?: number, padding?: number }) {\n const { text, style, resolution = 1, padding = 0 } = options\n\n const measured = TextMetrics.measureText(text, style)\n\n const width = Math.ceil(Math.ceil(Math.max(1, measured.width) + padding * 2) * resolution)\n const height = Math.ceil(Math.ceil(Math.max(1, measured.height) + padding * 2) * resolution)\n\n const canvasAndContext = CanvasPool.getOptimalCanvasAndContext(width, height)\n\n renderTextToCanvas(style, resolution, padding, canvasAndContext, measured)\n\n return {\n canvasAndContext,\n frame: new Rectangle(0, 0, width, height)\n }\n}\n\nfunction renderTextToCanvas(\n style: TextStyle,\n resolution: number,\n padding: number,\n canvasAndContext: CanvasAndContext,\n measured: TextMetrics,\n) {\n const { context } = canvasAndContext\n\n const font = fontStringFromTextStyle(style)\n\n const {\n lines,\n lineHeight,\n lineWidths,\n maxLineWidth,\n fontProperties,\n } = measured\n\n // const height = canvas.height\n\n context.resetTransform()\n context.scale(resolution, resolution)\n context.textBaseline = style.textBaseline\n\n // TODO: stroke width\n\n context.font = font\n\n const linePositionYShift = Math.min(0, (lineHeight - fontProperties.fontSize) / 2)\n\n // TODO dropShadow\n // TODO: fill\n context.fillStyle = style.fill\n\n for (let i = 0; i < lines.length; ++i) {\n const linePositionX = getAlignmentOffset(lineWidths[i], maxLineWidth, style.align)\n const linePositionY = i * lineHeight + fontProperties.ascent + linePositionYShift\n\n let wordSpacing = 0\n\n if (style.align === 'justify' && style.wordWrap && i < lines.length - 1) {\n const spaces = countSpaces(lines[i])\n if (spaces > 0) {\n wordSpacing = (maxLineWidth - lineWidths[i]) / spaces\n }\n }\n\n drawLetterSpacing(\n lines[i],\n style,\n canvasAndContext,\n linePositionX + padding,\n linePositionY + padding,\n false,\n wordSpacing\n )\n }\n}\n\nfunction getAlignmentOffset(lineWidth: number, alignWidth: number, align: string) {\n if (align === 'right') {\n return alignWidth - lineWidth\n } else if (align === 'center') {\n return (alignWidth - lineWidth) / 2\n }\n return 0\n}\n\nfunction countSpaces(text: string): number\n{\n let count = 0;\n\n for (let i = 0; i < text.length; i++)\n {\n if (text.charCodeAt(i) === 32) count++;\n }\n\n return count;\n}\n\nfunction drawLetterSpacing(\n text: string,\n style: TextStyle,\n canvasAndContext: CanvasAndContext,\n x: number, y: number,\n _isStroke = false,\n wordSpacing = 0\n) {\n const context = canvasAndContext.context\n\n const letterSpacing = style.letterSpacing\n\n if (letterSpacing === 0 && wordSpacing === 0) {\n context.fillText(text, x, y)\n return\n }\n if (wordSpacing !== 0 && letterSpacing === 0) {\n const words = text.split(' ')\n let currentPosition = x\n const spaceWidth = context.measureText(' ').width\n\n for (let i = 0; i < words.length; ++i) {\n context.fillText(words[i], currentPosition, y)\n currentPosition += context.measureText(words[i]).width + spaceWidth + wordSpacing\n }\n return\n }\n\n let currentPosition = x\n\n const stringArray = TextMetrics.graphemeSegmenter(text)\n let previousWidth = context.measureText(text).width\n let currentWidth = 0\n\n for (let i = 0; i < stringArray.length; ++i) {\n const currentChar = stringArray[i]\n context.fillText(currentChar, currentPosition, y)\n\n let textStr = ''\n\n for (let j = i + 1; j < stringArray.length; ++j) {\n textStr += stringArray[j]\n }\n currentWidth = context.measureText(textStr).width\n currentPosition += previousWidth - currentWidth + letterSpacing\n if (currentChar === '') currentPosition += wordSpacing\n previousWidth = currentWidth\n }\n}\n","import { createCanvas } from \"@/scene/text/utils\"\nimport EventEmitter from \"eventemitter3\"\n\nexport type TextureSourceOptions<T extends Record<string, any> = any> = {\n label?: string\n resource?: T,\n width?: number,\n height?: number,\n resolution?: number\n}\n\nexport class TextureSource<T extends Record<string, any> = any> extends EventEmitter {\n public static defaultOptions = {\n resolution: 1,\n }\n\n public label: string\n\n /**\n * @internal\n */\n public _resolution = 1\n\n /** the pixel width of this texture source. This is the REAL pure number, not accounting resolution */\n public pixelWidth = 1\n /** the pixel height of this texture source. This is the REAL pure number, not accounting resolution */\n public pixelHeight = 1\n\n /**\n */\n /**\n * the width of this texture source, accounting for resolution\n * eg pixelWidth 200, resolution 2, then width will be 100\n */\n public width = 1\n /**\n * the height of this texture source, accounting for resolution\n * eg pixelHeight 200, resolution 2, then height will be 100\n */\n public height = 1\n public resource: T\n\n public destroyed: boolean\n\n constructor(options: TextureSourceOptions<T>) {\n super()\n\n const _options = { ...TextureSource.defaultOptions, ...options }\n this.label = options.label\n\n this.resource = _options.resource\n this._resolution = _options.resolution\n\n if (_options.width) {\n this.pixelWidth = options.width * this._resolution\n } else {\n this.pixelWidth = this.resource ? (this.resourceWidth || 1) : 1\n }\n\n if (_options.height) {\n this.pixelHeight = options.height * this._resolution\n } else {\n this.pixelHeight = this.resource ? (this.resourceHeight || 1) : 1\n }\n\n this.width = this.pixelWidth / this._resolution\n this.height = this.pixelHeight / this._resolution\n\n this.destroyed = false\n }\n\n get resolution() {\n return this._resolution\n }\n\n set resolution(value: number) {\n if (this._resolution === value) return\n\n this._resolution = value\n\n this.width = this.pixelWidth / value\n this.height = this.pixelHeight / value\n }\n\n public get resourceWidth() {\n const resource = this.resource\n\n return resource.naturalWidth || resource.width\n }\n public get resourceHeight() {\n const resource = this.resource\n\n return resource.naturalHeight || resource.height\n }\n\n public resize(width?: number, height?: number, resolution?: number) {\n resolution ||= this._resolution\n width ||= this.width\n height ||= this.height\n\n const newPixelWidth = Math.round(width * resolution)\n const newPixelHeight = Math.round(height * resolution)\n\n this.width = newPixelWidth / resolution\n this.height = newPixelHeight / resolution\n\n this._resolution = resolution\n\n if (this.pixelWidth === newPixelWidth && this.pixelHeight === newPixelHeight) {\n return false\n }\n\n this.pixelWidth = newPixelWidth\n this.pixelHeight = newPixelHeight\n\n this.emit('resize', this)\n\n return true\n }\n\n public destroy() {\n this.destroyed = true\n this.resource = null\n\n this.emit('destroy', this)\n this.removeAllListeners()\n }\n}\n\nexport interface CanvasSourceOptions extends TextureSourceOptions<HTMLCanvasElement> {\n autoDensity?: boolean\n}\nexport class CanvasSource extends TextureSource<HTMLCanvasElement> {\n public autoDensity: boolean\n\n constructor(options?: CanvasSourceOptions) {\n if (!options.resource) {\n options.resource = createCanvas()\n }\n\n if (!options.width) {\n options.width = options.resource.width\n if (!options.autoDensity) {\n options.width /= options.resolution\n }\n }\n\n if (!options.height) {\n options.height = options.resource.height\n if (!options.autoDensity) {\n options.height /= options.resolution\n }\n }\n\n super(options)\n\n this.autoDensity = options.autoDensity\n\n this.resizeCanvas()\n }\n\n public resizeCanvas() {\n if (this.autoDensity) {\n this.resource.style.width = `${this.width}px`\n this.resource.style.height = `${this.height}px`\n }\n\n if (this.resource.width !== this.pixelWidth || this.resource.height !== this.pixelHeight) {\n this.resource.width = this.pixelWidth\n this.resource.height = this.pixelHeight\n }\n }\n\n public resize(width = this.width, height = this.height, resolution = this._resolution) {\n const didResize = super.resize(width, height, resolution)\n\n if (didResize) {\n this.resizeCanvas()\n }\n\n return didResize\n }\n}\n","import { Rectangle } from \"@/maths\"\nimport { TextureSource } from \"./TextureSource\"\nimport EventEmitter from \"eventemitter3\"\n\nexport interface TextureOptions<TextureSourceType extends TextureSource = TextureSource> {\n source?: TextureSourceType\n label?: string\n frame?: Rectangle\n orig?: Rectangle\n rotate?: number\n}\n\nexport class Texture<T extends TextureSource = TextureSource> extends EventEmitter {\n public static EMPTY: Texture\n public label: string\n public _source: T\n public orig: Rectangle\n public frame = new Rectangle()\n public readonly rotate: number\n public destroyed: boolean\n\n public noFrame = false\n\n constructor({\n source,\n label,\n frame,\n orig,\n rotate,\n }: TextureOptions<T> = {}) {\n super()\n\n this.label = label\n this.source = source\n\n if (frame) {\n this.frame.copyFrom(frame)\n } else {\n this.noFrame = true\n const { width, height } = source\n\n this.frame.width = width\n this.frame.height = height\n }\n\n this.orig = orig || this.frame\n this.rotate = rotate ?? 0\n\n this.destroyed = false\n }\n\n get source() {\n return this._source\n }\n\n set source(value: T) {\n if (this._source) {\n this._source.off('resize', this.update, this)\n }\n\n this._source = value\n\n value.on('resize', this.update, this)\n }\n\n get width() {\n return this.orig.width\n }\n\n get height() {\n return this.orig.height\n }\n\n public update() {\n if (this.noFrame) {\n this.frame.width = this._source.width\n this.frame.height = this._source.height\n }\n }\n\n public destroy(destroySource = false) {\n if (this._source) {\n this._source.off('resize', this.update, this)\n\n if (destroySource) {\n this._source.destroy()\n this._source = null\n }\n }\n\n this.destroyed = true\n this.emit('destroy', this)\n this.removeAllListeners()\n }\n}\n\nTexture.EMPTY = new Texture({\n label: 'EMPTY',\n source: new TextureSource({\n label: 'EMPTY'\n })\n})\n","import { CanvasRenderer } from \"@/renderer\";\nimport { Text } from \"./Text\";\nimport { generateTextTexture } from \"./utils\";\nimport { TextStyle } from \"./TextStyle\";\nimport { Texture } from \"@/renderer/texture/Texture\";\nimport { TextureSource } from \"@/renderer/texture/TextureSource\";\n\nexport class TextSystem {\n static desc = {\n name: 'text'\n } as const\n public readonly renderer: CanvasRenderer\n\n private readonly _activeTexture: Record<string, Texture> = {}\n\n constructor(renderer: CanvasRenderer) {\n this.renderer = renderer\n }\n \n public getManagedTexture(text: Text) {\n text._resolution = text._autoResolution ? this.renderer.resolution : text.resolution\n const textKey = text.styleKey\n\n if (this._activeTexture[textKey]) {\n // TODO: gc count?\n return this._activeTexture[textKey]\n }\n\n const texture = this.getTexture({\n text: text.text,\n style: text.style,\n resolution: text._resolution,\n })\n\n this._activeTexture[textKey] = texture\n\n return texture\n }\n\n public getTexture(options: { text: string, style: TextStyle, resolution: number }) {\n const { text, style } = options\n\n const resolution = options.resolution || this.renderer.resolution\n const { frame, canvasAndContext } = generateTextTexture({\n text,\n style,\n resolution,\n })\n\n const image = canvasAndContext.canvas\n const source = new TextureSource({ resource: image, resolution })\n const texture = new Texture({ source })\n texture.frame.width = frame.width / resolution\n texture.frame.height = frame.height / resolution\n\n return texture\n }\n}","import { InstructionSet } from \"@/renderer/InstructionSet\"\nimport { MaskEffect } from \"../container/mixins/effectMixin\"\nimport { StencilMaskInstruction } from \"./StencilMask\"\nimport { CanvasRenderer } from \"@/renderer\"\nimport { buildShapePath } from \"../graphics\"\n\nexport class StencilMaskPipe {\n static desc = {\n name: 'stencilMask',\n } as const\n\n private _renderer: CanvasRenderer\n private _canvasMaskStack: boolean[] = []\n\n constructor(renderer: CanvasRenderer) {\n this._renderer = renderer\n }\n\n push(mask: MaskEffect, instructionSet: InstructionSet) {\n instructionSet.add({\n renderPipeId: 'stencilMask',\n action: 'pushMaskBegin',\n mask,\n } as StencilMaskInstruction)\n }\n\n pop(mask: MaskEffect, instructionSet: InstructionSet) {\n this._renderer.renderPipes.batch.break(instructionSet)\n\n instructionSet.add({\n renderPipeId: 'stencilMask',\n action: 'popMaskEnd',\n mask,\n } as StencilMaskInstruction)\n }\n\n execute(instruction: StencilMaskInstruction) {\n if (instruction.action !== 'pushMaskBegin' && instruction.action !== 'popMaskEnd') {\n return\n }\n\n const renderer = this._renderer\n const contextSystem = renderer.canvasContext\n const ctx = contextSystem.activeConext\n\n if (instruction.action === 'popMaskEnd') {\n const didClip = this._canvasMaskStack.pop()\n if (didClip) {\n ctx.restore()\n }\n return\n }\n\n const graphics = instruction.mask.mask\n const instructions = graphics.context.instructions\n const roundPixels = graphics._roundPixels === 1\n\n ctx.save()\n\n contextSystem.setContextTransform(graphics.relativeGroupTransform, roundPixels)\n\n ctx.beginPath()\n\n for (let i = 0; i < instructions.length; ++i) {\n const instructionData = instructions[i]\n const action = instructionData.action\n\n if (action !== 'fill' && action !== 'stroke') return\n\n const data = instructionData.data\n const shapePath = data.path.shapePath\n // const isStroke = action === 'stroke'\n const shapePrimitives = shapePath.shapePrimitives\n\n for (let j = 0; j < shapePrimitives.length; ++j) {\n const primitive = shapePrimitives[j]\n const shape = primitive.shape\n buildShapePath(ctx, shape)\n }\n }\n ctx.clip()\n\n this._canvasMaskStack.push(true)\n }\n\n public destroy() {\n this._renderer = null\n }\n}\n","import { Texture } from \"./Texture\";\nimport { TextureSource, TextureSourceOptions } from \"./TextureSource\";\n\nexport interface RenderTextureOptions extends TextureSourceOptions {}\n\nexport class RenderTexture extends Texture {\n public static create(options: RenderTextureOptions) {\n return new RenderTexture({ source: new TextureSource(options) })\n }\n}","import { Vector2 } from \"@/maths\";\nimport { ViewContainer } from \"../ViewContainer\";\nimport { Texture } from \"@/renderer/texture/Texture\";\nimport { ContainerOptions } from \"..\";\n\nexport interface SpriteOptions extends ContainerOptions {\n texture?: Texture\n\n}\n\nexport class Sprite extends ViewContainer {\n public _texture: Texture\n public anchor: Vector2\n\n public override readonly renderPipeId = 'sprite'\n\n private _width: number\n private _height: number\n\n constructor(options: SpriteOptions | Texture = Texture.EMPTY) {\n if (options instanceof Texture) {\n options = { texture: options }\n }\n const { texture = Texture.EMPTY, width, height, ...rest } = options\n super({\n label: 'Sprite',\n ...rest,\n })\n\n this.texture = texture\n this.anchor = new Vector2()\n\n if (width != null) this.width = width\n if (height != null) this.height = height\n }\n\n set texture(value: Texture) {\n value ||= Texture.EMPTY\n\n const currentTexture = this._texture\n\n if (currentTexture === value) return\n\n this._texture = value\n\n if (this._width) {\n this._setWidth(this.width, this._texture.orig.width)\n }\n if (this._height) {\n this._setHeight(this.height, this._texture.orig.height)\n }\n\n this.onViewUpdate()\n }\n\n get texture() {\n return this._texture\n }\n\n override get height() {\n return Math.abs(this.scale.y) * this.texture.orig.height\n }\n override set height(value: number) {\n const localHeight = this.texture.orig.height\n // 保留符号\n const sign = Math.sign(this.scale.y) || 1\n\n if (localHeight !== 0) {\n this.scale.y = (value / localHeight) * sign\n } else {\n this.scale.y = sign\n }\n\n this._height = value\n }\n\n override get width() {\n return Math.abs(this.scale.x) * this.texture.orig.width\n }\n override set width(value: number) {\n const localWidth = this.texture.orig.width\n // 保留符号\n const sign = Math.sign(this.scale.x) || 1\n\n if (localWidth !== 0) {\n this.scale.x = (value / localWidth) * sign\n } else {\n this.scale.x = sign\n }\n\n this._width = value\n }\n\n protected updateBounds() {\n const bounds = this._bounds\n const { width, height } = this.texture.orig\n\n bounds.minX = -this.anchor.x * width\n bounds.maxX = bounds.minX + width\n\n bounds.minY = -this.anchor.y * height\n bounds.maxY = bounds.minY + height\n }\n}\n","import { ObservablePoint } from \"@/maths/Point\";\nimport { ViewContainer } from \"../ViewContainer\";\nimport { Vector2 } from \"@/maths\";\nimport { TextStyle, TextStyleOptions } from \"./TextStyle\";\nimport { TextMetrics } from \"./utils\";\nimport { DestroyOptions } from \"../container/destroyTypes\";\nimport { ContainerOptions } from \"..\";\n\nexport interface TextOptions extends ContainerOptions {\n text?: string | number\n style?: TextStyleOptions\n resolution?: number\n}\n\nexport class Text extends ViewContainer {\n public override readonly renderPipeId = 'text'\n\n public _anchor: ObservablePoint\n /**\n * @internal\n */\n public _didTextUpdate = true\n public _resolution: number = null\n public _autoResolution = true\n\n private _text: string\n private _style: TextStyle\n\n constructor(options: TextOptions) {\n const { text, resolution, style, width, height, ...rest } = options\n super(rest)\n this._anchor = new ObservablePoint(this, 0, 0)\n this.text = options.text ?? ''\n this.style = style\n this.resolution = resolution ?? null\n\n if (width != null) this.width = width\n if (height != null) this.height = height\n }\n\n // 默认使用renderer resolution\n // 当手动设置resolution后会使用自身的\n // 除非设置的值是null,将会兜底使用renderer的\n set resolution(value: number) {\n this._autoResolution = value === null\n this._resolution = value\n this.onViewUpdate()\n }\n\n get resolution() {\n return this._resolution\n }\n\n get anchor() {\n return this._anchor\n }\n set anchor(value: Vector2) {\n this._anchor.copyFrom(value)\n }\n\n get text(): string {\n return this._text\n }\n\n set text(value: string | number) {\n const str = String(value)\n if (this._text === str) return\n\n this._text = str\n this.onViewUpdate()\n }\n\n get style(): TextStyle {\n return this._style\n }\n\n set style(value: TextStyle | TextStyleOptions) {\n value ||= {}\n\n if (value instanceof TextStyle) {\n this._style = value\n } else {\n this._style = new TextStyle(value)\n }\n this.onViewUpdate()\n }\n\n override get width() {\n return Math.abs(this.scale.x) * this.bounds.width\n }\n\n override set width(value: number) {\n this._setWidth(value, this.bounds.width)\n }\n\n override get height() {\n return Math.abs(this.scale.y) * this.bounds.height\n }\n\n override set height(value: number) {\n this._setHeight(value, this.bounds.height)\n }\n\n public override onViewUpdate() {\n if (!this.didViewUpdate) this._didTextUpdate = true\n\n super.onViewUpdate()\n }\n\n protected updateBounds(): void {\n const bounds = this._bounds\n const anchor = this._anchor\n // TODO cal with trim\n const measurement = TextMetrics.measureText(this._text, this._style)\n const width = measurement.width\n const height = measurement.height\n\n bounds.minX = (-anchor._x * width)\n bounds.minY = (-anchor._y * height)\n bounds.maxX = bounds.minX + width\n bounds.maxY = bounds.minY + height\n }\n\n get styleKey() {\n return `${this._text}:${this._style.styleKey}:${this._resolution}`\n }\n\n public override destroy(options: DestroyOptions = false) {\n super.destroy(options)\n\n this._bounds = null\n this._anchor = null\n\n if (typeof options === 'boolean' ? options : options?.style) {\n this._style.destroy(options)\n }\n this._style = null\n this._text = null\n }\n}\n","import { Matrix, Rectangle } from \"@/maths\";\nimport { Bounds, getLocalBounds } from \"@/maths/Bounds\";\nimport { CanvasRenderer } from \"@/renderer\";\nimport { RenderTexture } from \"@/renderer/texture/RenderTexture\";\nimport { Container } from \"@/scene\";\n\nexport type GenerateTextureOptions = {\n target: Container\n frame?: Rectangle\n resolution?: number\n}\n\nexport class ExtractSystem {\n static desc = {\n name: 'extract'\n } as const\n private _renderer: CanvasRenderer\n\n constructor(renderer: CanvasRenderer) {\n this._renderer = renderer\n }\n public texture(options: Container) {\n return this._generateTexture(options)\n }\n\n private _generateTexture(options: GenerateTextureOptions | Container) {\n if (options instanceof Container) {\n options = {\n target: options,\n }\n }\n\n const resolution = options.resolution || this._renderer.resolution\n const container = options.target\n\n const _bounds = new Bounds()\n const region = options.frame || getLocalBounds(container, _bounds).rectangle\n\n region.width = Math.max(region.width, 1 / resolution) | 0\n region.height = Math.max(region.height, 1 / resolution) | 0\n\n const target = RenderTexture.create({\n width: region.width,\n height: region.height,\n resolution,\n })\n\n const transform = new Matrix()\n transform.tx = -region.x\n transform.ty = -region.y\n\n this._renderer.render({\n clearColor: 'transparent',\n container,\n transform,\n target,\n })\n\n return target\n }\n}\n\n","import { Matrix } from \"@/maths\"\nimport { CanvasRenderer } from \"@/renderer\"\n\nexport class CanvasContextSystem {\n static desc = {\n name: 'canvasContext',\n } as const\n\n private _renderer: CanvasRenderer\n\n public rootContext: CanvasRenderingContext2D\n public activeConext: CanvasRenderingContext2D\n public activeResolution = 1\n\n public globalTransform = new Matrix()\n\n constructor(renderer: CanvasRenderer) {\n this._renderer = renderer\n }\n\n public init() {\n this.activeConext = this._renderer.canvas.getContext('2d')\n this.rootContext = this.activeConext\n this.activeResolution = this._renderer.resolution\n }\n\n public setContextTransform(\n transform: Matrix,\n roundPixels?: boolean,\n localResolution?: number\n ) {\n const contextResolution = this.activeResolution\n const mat = Matrix.append(this.globalTransform, transform)\n\n localResolution ||= this.activeResolution\n\n if (roundPixels) {\n this.activeConext.setTransform(\n mat.a * localResolution,\n mat.b * localResolution,\n mat.c * localResolution,\n mat.d * localResolution,\n (mat.tx * contextResolution) | 0,\n (mat.ty * contextResolution) | 0,\n )\n } else {\n this.activeConext.setTransform(\n mat.a * localResolution,\n mat.b * localResolution,\n mat.c * localResolution,\n mat.d * localResolution,\n mat.tx * contextResolution,\n mat.ty * contextResolution,\n )\n }\n }\n}\n","import { Rectangle } from \"@/maths\"\nimport { createCanvas } from \"@/scene/text/utils\"\nimport { Texture } from '@/renderer/texture/Texture'\nimport { CanvasSource } from \"@/renderer/texture/TextureSource\"\n\nexport type ViewSystemOptions = {\n width?: number\n height?: number\n resolution?: number\n autoDensity?: boolean\n}\n\nexport class ViewSystem {\n public static desc = {\n name: 'view',\n } as const\n\n public static defaultOptions: ViewSystemOptions = {\n width: 800,\n height: 600,\n autoDensity: false,\n }\n\n public canvas: HTMLCanvasElement\n public screen: Rectangle\n public texture: Texture<CanvasSource>\n\n get resolution() {\n return this.texture.source._resolution\n }\n\n set resolution(value: number) {\n this.texture.source.resize(\n this.texture.source.width,\n this.texture.source.height,\n value,\n )\n }\n\n public init(options: ViewSystemOptions) {\n options = {\n ...ViewSystem.defaultOptions,\n ...options,\n }\n\n this.screen = new Rectangle(0, 0, options.width, options.height)\n this.canvas = createCanvas()\n this.texture = new Texture({ source: new CanvasSource({\n resource: this.canvas,\n ...options,\n })})\n this.resolution = options.resolution\n }\n\n public resize(width: number, height: number, resolution: number) {\n this.texture.source.resize(width, height, resolution)\n\n this.screen.width = this.texture.frame.width\n this.screen.height = this.texture.frame.height\n }\n}\n","import { Matrix } from \"../maths\"\nimport { EventSystem, RenderGroupSystem } from \"../system\"\nimport { Container } from \"@/scene/container/Container\"\nimport { RenderGroup } from \"@/scene/container/RenderGroup\"\nimport { SpritePipe } from \"@/scene/sprite/SpritePipe\"\nimport { TextPipe } from \"@/scene/text/TextPipe\"\nimport { GraphicsPipe } from \"@/scene/graphics\"\nimport { BatchPipe } from \"@/scene/batcher\"\nimport { TextSystem } from \"@/scene/text/TextSystem\"\nimport { uid } from \"../utils\"\nimport { StencilMaskPipe } from \"@/scene/mask/StencilMaskPipe\"\nimport { ExtractSystemTypes } from \"@/utils/type\"\nimport { ExtractSystem } from \"@/system/ExtractSystem\"\nimport { CanvasContextSystem } from \"@/system/CanvasContextSystem\"\nimport { TextureSource } from \"./texture/TextureSource\"\nimport { createCanvas } from \"@/scene/text/utils\"\nimport { ViewSystem } from \"@/system/ViewSystem\"\nimport EventEmitter from \"eventemitter3\"\n\nconst systems = [\n ViewSystem,\n EventSystem,\n RenderGroupSystem,\n TextSystem,\n ExtractSystem,\n CanvasContextSystem,\n]\n\nconst pipes = [\n BatchPipe,\n GraphicsPipe,\n TextPipe,\n SpritePipe,\n StencilMaskPipe,\n]\n\ntype RenderOptions = {\n clearColor?: string\n container: Container\n transform?: Matrix\n target?: { source: TextureSource }\n}\nexport type CanvasSystems = ExtractSystemTypes<typeof systems>\n\nexport type CanvasPipes = ExtractSystemTypes<typeof pipes>\n\nexport interface RendererOptions {\n width?: number\n height?: number\n backgroundColor?: string\n roundPixels?: boolean\n autoStart?: boolean\n resolution?: number\n /**\n * Should the canvas be resized to preserve its screen width and height regardless\n * of the resolution of the renderer.\n */\n autoDensity?: boolean\n}\n\nexport interface CanvasRenderer extends CanvasSystems {}\n\nexport class CanvasRenderer extends EventEmitter {\n public uid = uid('renderer')\n public context!: CanvasRenderingContext2D\n public background: {\n color: string\n }\n public renderedObject: Container = null\n public _roundPixels: 0 | 1\n public resolution: number\n public activeRenderGroup: RenderGroup\n public renderPipes: CanvasPipes = {} as CanvasPipes\n\n constructor() {\n super()\n\n this.background = {\n color: '#000000',\n }\n }\n\n get canvas() {\n return this.view.canvas\n }\n\n private _addPipes() {\n pipes.forEach(pipe => {\n (this.renderPipes as any)[pipe.desc.name] = new pipe(this)\n })\n }\n\n private _addSystems() {\n systems.forEach(system => {\n (this as any)[system.desc.name] = new system(this)\n })\n }\n\n async init(options: RendererOptions) {\n this.resolution = options.resolution || 1\n\n this._addSystems()\n this._addPipes()\n\n for (let i = 0; i < systems.length; ++i) {\n await (this as any)[systems[i].desc.name].init?.(options)\n }\n\n if (options.backgroundColor) {\n this.background.color = options.backgroundColor\n }\n this._roundPixels = options.roundPixels ? 1 : 0\n }\n\n get roundPixels(): boolean {\n return !!this._roundPixels\n }\n\n render(args: Container | RenderOptions) {\n\n let options = args\n\n if (options instanceof Container) {\n options = {\n container: options,\n }\n }\n this.renderedObject = options.container\n\n // stage transform最多计算一次\n if (!options.transform) {\n options.container.updateLocalTransform()\n options.transform = options.container.localTransform\n }\n\n options.clearColor ?? (options.clearColor = this.background.color)\n\n if (!options.container.visible) return\n\n\n options.container.enableRenderGroup()\n\n const renderGroup = options.container.renderGroup\n this.activeRenderGroup = renderGroup\n\n this.canvasContext.globalTransform = renderGroup.worldTransform\n this.canvasContext.activeConext = this.canvasContext.rootContext\n\n if (options.target) {\n const { context } = ensureCanvas(options.target.source)\n this.canvasContext.activeConext = context\n }\n\n this.clear(options)\n\n systems.forEach(system => {\n (this as any)[system.desc.name].render?.(options)\n })\n\n }\n\n clear(options: RenderOptions) {\n const context = this.canvasContext.activeConext\n\n context.setTransform(1, 0, 0, 1, 0, 0)\n context.clearRect(0, 0, this.canvas.width, this.canvas.height)\n\n // TODO: implement Color with r, g, b, a\n context.globalAlpha = 1\n context.fillStyle = options.clearColor!\n context.fillRect(0, 0, this.canvas.width, this.canvas.height)\n // reset global alpha\n context.globalAlpha = 1\n }\n\n public destroy() {\n // TODO: remove view可控\n\n if (this.canvas.parentNode) {\n this.canvas.parentNode.removeChild(this.canvas)\n }\n\n pipes.forEach(pipe => {\n (this.renderPipes as any)[pipe.desc.name]?.destroy()\n })\n this.renderPipes = null\n }\n\n public resize(width: number, height: number, resolution?: number) {\n this.view.resize(width, height, resolution)\n this.emit('resize', this.view.screen.width, this.view.screen.height, this.view.resolution)\n }\n}\n\nfunction ensureCanvas(source: TextureSource) {\n let canvas = source.resource as HTMLCanvasElement\n if (!canvas) {\n canvas = createCanvas(source.pixelWidth, source.pixelHeight)\n source.resource = canvas\n }\n\n if (canvas.width !== source.pixelWidth || canvas.height !== source.pixelHeight) {\n canvas.width = source.pixelWidth\n canvas.height = source.pixelHeight\n }\n\n return { canvas, context: canvas.getContext('2d')}\n}\n","import { Ticker, TickerCallback } from \"./Ticker\"\n\nexport class TickerListener<T = any> {\n public next : TickerListener = null\n public previous: TickerListener = null\n public priority = 0\n private _fn: TickerCallback<T>\n private _context: T\n private _once: boolean\n private _destroyed = false\n\n constructor(fn: TickerCallback<T>, context: T, priority = 0, once = false) {\n this._fn = fn\n this._context = context\n this.priority = priority\n this._once = once\n }\n match(fn: TickerCallback<T>, context?: any) {\n return this._fn === fn && this._context === context\n }\n\n emit(ticker: Ticker) {\n if (this._fn) {\n if (this._context) {\n this._fn.call(this._context, ticker)\n } else {\n (this as TickerListener<any>)._fn(ticker)\n }\n }\n\n const redirect = this.next\n\n if (this._once) {\n this.destroy(true)\n }\n\n // 不管是软删还是硬删,都要断开当前节点与链表的连接\n if (this._destroyed) {\n this.next = null\n }\n return redirect\n }\n\n /**\n * Destroy and don't use after this.\n * @param hard - `true` to remove the `next` reference, this\n * is considered a hard destroy. Soft destroy maintains the next reference.\n * @returns The listener to redirect while emitting or removing.\n */\n destroy(hard?: boolean) {\n this._destroyed = true\n this._fn = null\n this._context = null\n\n if (this.previous) {\n this.previous.next = this.next\n }\n\n if (this.next) {\n this.next.previous = this.previous\n }\n\n const redirect = this.next\n\n this.next = hard ? null : redirect\n this.previous = null\n\n // hard为ture仅仅是断开了链表的连接,返回值仍然是下一个节点\n // 也就是说不论如何销毁这个操作在下一帧才会反应出来\n // 目前看来,两者的区别在于执行销毁操作的当前帧中能否通过该节点的next访问到下一个节点\n return redirect\n }\n\n public connect(previous: TickerListener) {\n this.previous = previous\n if (previous.next) {\n previous.next.previous = this\n }\n this.next = previous.next\n previous.next = this\n }\n}\n","import { TickerListener } from \"./TickerListener\";\n\nexport type TickerCallback<T> = (this: T, ticker: Ticker) => any;\n\nexport class Ticker {\n /**\n * Target frame rate in frames per millisecond.\n * Used for converting deltaTime to a scalar time delta.\n * @example\n * ```ts\n * // Default is 0.06 (60 FPS)\n * console.log(Ticker.targetFPMS); // 0.06\n *\n * // Calculate target frame duration\n * const frameDuration = 1 / Ticker.targetFPMS; // ≈ 16.67ms\n *\n * // Use in custom timing calculations\n * const deltaTime = elapsedMS * Ticker.targetFPMS;\n * ```\n * @remarks\n * - Default is 0.06 (equivalent to 60 FPS)\n * - Used in deltaTime calculations\n * - Affects all ticker instances\n * @default 0.06\n * @see {@link Ticker#deltaTime} For time scaling\n * @see {@link Ticker#FPS} For actual frame rate\n */\n public static targetFPMS = 0.06;\n\n /**\n * Whether or not this ticker should invoke the method {@link Ticker#start|start}\n * automatically when a listener is added.\n * @example\n * ```ts\n * // Default behavior (manual start)\n * const ticker = new Ticker();\n * ticker.autoStart = false;\n * ticker.add(() => {\n * // Won't run until ticker.start() is called\n * });\n *\n * // Auto-start behavior\n * const autoTicker = new Ticker();\n * autoTicker.autoStart = true;\n * autoTicker.add(() => {\n * // Runs immediately when added\n * });\n * ```\n * @default false\n * @see {@link Ticker#start} For manually starting the ticker\n * @see {@link Ticker#stop} For manually stopping the ticker\n */\n public autoStart = false;\n /**\n * Scalar representing the delta time factor.\n * This is a dimensionless value representing the fraction of a frame at the target framerate.\n * At 60 FPS, this value is typically around 1.0.\n *\n * This is NOT in milliseconds - it's a scalar multiplier for frame-independent animations.\n * For actual milliseconds, use {@link Ticker#deltaMS}.\n * @example\n * ```ts\n * // Frame-independent animation using deltaTime scalar\n * ticker.add((ticker) => {\n * // Rotate sprite by 0.1 radians per frame, scaled by deltaTime\n * sprite.rotation += 0.1 * ticker.deltaTime;\n * });\n * ```\n */\n public deltaTime: number = 1;\n /**\n * Scalar time elapsed in milliseconds from last frame to this frame.\n * Provides precise timing for animations and updates.\n *\n * This value is capped by setting {@link Ticker#minFPS|minFPS}\n * and is scaled with {@link Ticker#speed|speed}.\n *\n * If the platform supports DOMHighResTimeStamp,\n * this value will have a precision of 1 µs.\n *\n * Defaults to target frame time\n *\n * > [!NOTE] The cap may be exceeded by scaling.\n * @example\n * ```ts\n * // Animation timing\n * ticker.add((ticker) => {\n * // Use millisecond timing for precise animations\n * const progress = (ticker.deltaMS / animationDuration);\n * sprite.alpha = Math.min(1, progress);\n * });\n * ```\n * @default 16.66\n */\n public deltaMS: number;\n /**\n * Time elapsed in milliseconds from the last frame to this frame.\n * This value is not capped or scaled and provides raw timing information.\n *\n * Unlike {@link Ticker#deltaMS}, this value is unmodified by speed scaling or FPS capping.\n * @example\n * ```ts\n * ticker.add((ticker) => {\n * console.log(`Raw frame time: ${ticker.elapsedMS}ms`);\n * });\n * ```\n */\n public elapsedMS: number;\n /**\n * The last time update was invoked, in milliseconds since epoch.\n * Similar to performance.now() timestamp format.\n *\n * Used internally for calculating time deltas between frames.\n * @example\n * ```ts\n * ticker.add((ticker) => {\n * const currentTime = performance.now();\n * const timeSinceLastFrame = currentTime - ticker.lastTime;\n * console.log(`Time since last frame: ${timeSinceLastFrame}ms`);\n * });\n * ```\n */\n public lastTime: number = -1;\n /**\n * Factor of current {@link Ticker#deltaTime|deltaTime}.\n * Used to scale time for slow motion or fast-forward effects.\n * @example\n * ```ts\n * // Basic speed adjustment\n * ticker.speed = 0.5; // Half speed (slow motion)\n * ticker.speed = 2.0; // Double speed (fast forward)\n *\n * // Temporary speed changes\n * function slowMotion() {\n * const normalSpeed = ticker.speed;\n * ticker.speed = 0.2;\n * setTimeout(() => {\n * ticker.speed = normalSpeed;\n * }, 1000);\n * }\n * ```\n */\n public speed = 1;\n /**\n * Whether or not this ticker has been started.\n *\n * `true` if {@link Ticker#start|start} has been called.\n * `false` if {@link Ticker#stop|Stop} has been called.\n *\n * While `false`, this value may change to `true` in the\n * event of {@link Ticker#autoStart|autoStart} being `true`\n * and a listener is added.\n * @example\n * ```ts\n * // Check ticker state\n * const ticker = new Ticker();\n * console.log(ticker.started); // false\n *\n * // Start and verify\n * ticker.start();\n * console.log(ticker.started); // true\n * ```\n */\n public started = false;\n /**\n * Internal tick method bound to ticker instance.\n * This is because in early 2015, Function.bind\n * is still 60% slower in high performance scenarios.\n * Also separating frame requests from update method\n * so listeners may be called at any time and with\n * any animation API, just invoke ticker.update(time).\n * @param time - Time since last tick.\n */\n private readonly _tick: (time: number) => any;\n /** Internal current frame request ID */\n private _requestId: number = null;\n /**\n * Internal value managed by minFPS property setter and getter.\n * This is the maximum allowed milliseconds between updates.\n */\n private _maxElapsedMS = 100;\n /**\n * Internal value managed by maxFPS property setter and getter.\n * This is the minimum allowed milliseconds between updates.\n */\n private _minElapsedMS = 0;\n /** The last time keyframe was executed. Maintains a relatively fixed interval with the previous value. */\n private _lastFrame = -1;\n private _head: TickerListener = null\n constructor() {\n this._head = new TickerListener(null, null, Infinity)\n this.deltaMS = 1 / Ticker.targetFPMS\n this.elapsedMS = this.deltaMS\n\n this._tick = (time: number) => {\n this._requestId = null\n\n if (this.started) {\n this.update(time)\n\n if (this.started && this._requestId === null) {\n this._requestId = requestAnimationFrame(this._tick)\n }\n }\n }\n }\n /**\n * Triggers an update.\n *\n * An update entails setting the\n * current {@link Ticker#elapsedMS|elapsedMS},\n * the current {@link Ticker#deltaTime|deltaTime},\n * invoking all listeners with current deltaTime,\n * and then finally setting {@link Ticker#lastTime|lastTime}\n * with the value of currentTime that was provided.\n *\n * This method will be called automatically by animation\n * frame callbacks if the ticker instance has been started\n * and listeners are added.\n * @example\n * ```ts\n * // Basic manual update\n * const ticker = new Ticker();\n * ticker.update(performance.now());\n * ```\n * @param currentTime - The current time of execution (defaults to performance.now())\n * @see {@link Ticker#deltaTime} For frame delta value\n * @see {@link Ticker#elapsedMS} For raw elapsed time\n */\n update(currentTime = performance.now()) {\n let elapsedMS\n\n // 只有时间差是正数时,才认为需要更新\n // 差值为0说明时间没有变化,不需要更新\n // 而如果是负值,说明触发了竞态条件\n // 考虑以下情况,用户手动触发start,同时浏览器触发了rAF,一旦start的触发和rAF在同一帧且start要晚一点\n // 就会出现差值为负的情况,这种现象显然是异常的,不需要按正常流程渲染\n if (currentTime > this.lastTime) {\n elapsedMS = this.elapsedMS = currentTime - this.lastTime\n\n if (elapsedMS > this._maxElapsedMS) {\n elapsedMS = this._maxElapsedMS\n }\n\n elapsedMS *= this.speed\n\n if (this._minElapsedMS) {\n const delta = currentTime - this._lastFrame | 0\n\n if (delta < this._minElapsedMS) {\n return\n }\n\n this._lastFrame = currentTime - (delta % this._minElapsedMS)\n }\n\n this.deltaMS = elapsedMS\n this.deltaTime = this.deltaMS * Ticker.targetFPMS\n\n const head = this._head\n\n let listener = head.next\n\n while(listener) {\n listener = listener.emit(this)\n }\n\n if (!head.next) {\n this._cancelIfNeeded()\n }\n } else {\n this.deltaTime = this.deltaMS = this.elapsedMS = 0\n }\n\n this.lastTime = currentTime\n }\n /**\n * The frames per second at which this ticker is running.\n * The default is approximately 60 in most modern browsers.\n * > [!NOTE] This does not factor in the value of\n * > {@link Ticker#speed|speed}, which is specific\n * > to scaling {@link Ticker#deltaTime|deltaTime}.\n * @example\n * ```ts\n * // Basic FPS monitoring\n * ticker.add(() => {\n * console.log(`Current FPS: ${Math.round(ticker.FPS)}`);\n * });\n * ```\n * @readonly\n */\n get FPS() {\n return 1000 / this.elapsedMS\n }\n /**\n * Manages the minimum amount of milliseconds required to\n * elapse between invoking {@link Ticker#update|update}.\n *\n * This will effect the measured value of {@link Ticker#FPS|FPS}.\n *\n * If it is set to `0`, then there is no limit; PixiJS will render as many frames as it can.\n * Otherwise it will be at least `minFPS`.\n *\n * If `maxFPS` is set below the current `minFPS`, `minFPS` is automatically lowered to match.\n * This keeps the two limits consistent.\n * @example\n * ```ts\n * // Cap the frame rate\n * const ticker = new Ticker();\n * ticker.maxFPS = 60; // Never go above 60 FPS\n *\n * // Use with minFPS for frame rate clamping\n * ticker.minFPS = 30;\n * ticker.maxFPS = 60;\n *\n * // maxFPS below minFPS pushes minFPS down\n * ticker.maxFPS = 20; // minFPS is now also 20\n * ```\n * @default 0\n */\n get maxFPS(): number\n {\n if (this._minElapsedMS)\n {\n return Math.round(1000 / this._minElapsedMS);\n }\n\n return 0;\n }\n set maxFPS(value: number) {\n if (value === 0) {\n this._minElapsedMS = 0\n } else {\n if (value < this.minFPS) {\n this.minFPS = value\n }\n\n this._minElapsedMS = 1 / (value / 1000)\n }\n }\n /**\n * Manages the maximum amount of milliseconds allowed to\n * elapse between invoking {@link Ticker#update|update}.\n *\n * This value is used to cap {@link Ticker#deltaTime|deltaTime},\n * but does not effect the measured value of {@link Ticker#FPS|FPS}.\n *\n * When setting this property it is clamped to a value between\n * `0` and `Ticker.targetFPMS * 1000` (typically 60).\n *\n * If `maxFPS` is currently set (non-zero) and `minFPS` is set above it,\n * `maxFPS` is automatically raised to match. This keeps the two limits consistent.\n * @example\n * ```ts\n * // Set minimum acceptable frame rate\n * const ticker = new Ticker();\n * ticker.minFPS = 30; // Never go below 30 FPS\n *\n * // Use with maxFPS for frame rate clamping\n * ticker.minFPS = 30;\n * ticker.maxFPS = 60;\n *\n * // minFPS above maxFPS pushes maxFPS up\n * ticker.minFPS = 50; // maxFPS is raised to 50\n * ```\n * @default 10\n */\n get minFPS(): number\n {\n return 1000 / this._maxElapsedMS;\n }\n\n set minFPS(value: number) {\n const minFPSMS = Math.min(Math.max(0, value) / 1000, Ticker.targetFPMS)\n\n this._maxElapsedMS = 1 / minFPSMS\n\n if (this._minElapsedMS && value > this.maxFPS) {\n this.maxFPS = value\n }\n }\n\n add<T = any>(fn: TickerCallback<T>, context?: T, priority = 0) {\n const listener = new TickerListener(fn, context, priority)\n let current = this._head.next\n let previous = this._head\n\n // 没有下一个节点,直接将当前的追到链表后\n if (!current) {\n listener.connect(previous)\n } else {\n while(current) {\n if (listener.priority > current.priority) {\n listener.connect(previous)\n break\n }\n previous = current\n current = current.next\n }\n\n // 保护性写法?已经遍历到末尾了,还需要判断节点是否被添加吗\n if (!listener.previous) {\n listener.connect(previous)\n }\n }\n\n this._startIfPossible()\n\n return this\n }\n\n public start() {\n if (!this.started) {\n this.started = true\n this._requestIfNeeded()\n }\n }\n\n public stop() {\n if (this.started) {\n this.started = false\n this._cancelIfNeeded()\n }\n }\n\n public remove<T>(fn: TickerCallback<T>, context?: T) {\n let listener = this._head.next\n\n while(listener) {\n if (listener.match(fn, context)) {\n listener = listener.destroy()\n } else {\n listener = listener.next\n }\n }\n\n if (!this._head.next) {\n this._cancelIfNeeded()\n }\n\n return this\n }\n\n private _startIfPossible() {\n if (this.started) {\n this._requestIfNeeded()\n } else if (this.autoStart) {\n this.start()\n }\n }\n\n private _requestIfNeeded() {\n // 如果ticker里没有事件就不启动\n if (this._requestId === null && this._head.next) {\n this.lastTime = performance.now()\n this._lastFrame = this.lastTime\n this._requestId = requestAnimationFrame(this._tick)\n }\n }\n\n private _cancelIfNeeded() {\n if (this._requestId !== null) {\n cancelAnimationFrame(this._requestId)\n this._requestId = null\n }\n }\n\n public destroy() {\n this.stop()\n let listener = this._head.next\n\n while (listener) {\n listener = listener.destroy(true)\n }\n\n this._head.destroy()\n this._head = null\n }\n}\n","import { CanvasRenderer } from \"@/renderer\"\n\nexport interface ResizePluginOptions {\n resizeTo?: Window | HTMLElement\n}\nexport class ResizePlugin {\n public static resizeTo: Window | HTMLElement\n public static queueResize: () => void\n public static _resizeTo: Window | HTMLElement\n public static _resizeId: number\n public static resize: () => void\n public static _cancelResize: () => void\n public static renderer: Pick<CanvasRenderer, 'resize'>\n public static render: () => void\n\n public static init(options: ResizePluginOptions) {\n Object.defineProperty(this, 'resizeTo', {\n configurable: true,\n set(dom: Window | HTMLElement) {\n globalThis.removeEventListener('resize', this.queueResize)\n this._resizeTo = dom\n if (dom) {\n globalThis.addEventListener('resize', this.queueResize)\n this.resize()\n }\n },\n get() {\n return this._resizeTo\n }\n })\n\n this.queueResize = () => {\n if (!this._resizeTo) {\n return\n }\n\n this._cancelResize()\n this._resizeId = requestAnimationFrame(() => this.resize)\n }\n\n this._cancelResize = () => {\n if (this._resizeId) {\n cancelAnimationFrame(this._resizeId)\n this._resizeId = null\n }\n }\n\n this.resize = () => {\n if (!this._resizeTo) {\n return\n }\n\n this._cancelResize()\n\n let width: number\n let height: number\n\n if (this._resizeTo === globalThis.window) {\n width = globalThis.innerWidth\n height = globalThis.innerHeight\n } else {\n const { clientWidth, clientHeight } = this._resizeTo as HTMLElement\n\n width = clientWidth\n height = clientHeight\n }\n\n this.renderer.resize(width, height)\n this.render()\n }\n\n this._resizeId = null\n this._resizeTo = null\n this.resizeTo = options.resizeTo || null\n }\n\n public static destroy() {\n globalThis.removeEventListener('resize', this.queueResize)\n this._cancelResize()\n this._cancelResize = null\n this.queueResize = null\n this.resizeTo = null\n this.resize = null\n }\n}\n","import { CanvasRenderer, RendererOptions } from \"@/renderer\";\nimport { Container } from \"@/scene\";\nimport { Ticker } from \"@/ticker\";\nimport { ResizePlugin, ResizePluginOptions } from \"./ResizePlugin\";\n\nconst plugins = [\n ResizePlugin\n]\n\nexport interface ApplicationOptions extends RendererOptions, ResizePluginOptions {}\n\nexport class Application {\n public renderer: CanvasRenderer\n public stage: Container = new Container()\n\n private _ticker: Ticker\n async init(options: Partial<ApplicationOptions> = {}) {\n options = { ...options }\n this.stage ||= new Container()\n\n this.renderer = new CanvasRenderer()\n await this.renderer.init(options)\n\n plugins.forEach(plugin => {\n plugin.init.call(this, options)\n })\n\n this.ticker = new Ticker()\n if (options.autoStart || options.autoStart == undefined) {\n this._ticker.start()\n }\n }\n\n get canvas() {\n return this.renderer.canvas\n }\n\n get screen() {\n return this.renderer.view.screen\n }\n\n get ticker(): Ticker {\n return this._ticker\n }\n set ticker(ticker: Ticker) {\n if (this._ticker) {\n this._ticker.remove(this.render, this)\n }\n this._ticker = ticker\n if (ticker) {\n ticker.add(this.render, this)\n }\n }\n\n public render() {\n this.renderer.render({ container: this.stage })\n }\n\n public destroy() {\n const _plugins = plugins.slice(0)\n\n _plugins.reverse()\n _plugins.forEach(plugin => {\n plugin.destroy.call(this)\n })\n\n this.stage.destroy()\n this.stage = null\n this.renderer.destroy()\n this.renderer = null\n\n if (this._ticker) {\n const oldTicker = this._ticker\n this._ticker = null\n oldTicker.destroy()\n }\n }\n}","class CacheClass {\n private readonly _cache: Map<any, any> = new Map()\n private readonly _cacheMap: Map<string, { keys: string[], cacheKeys: string[] }> = new Map()\n\n public reset() {\n this._cache.clear()\n this._cacheMap.clear()\n }\n\n public has(key: any) {\n return this._cache.has(key)\n }\n\n public get(key: any) {\n const res = this._cache.get(key)\n\n if (!res) {\n throw new Error(`Asset ${key} not found`)\n }\n\n return res\n }\n\n public set<T = any>(key: any | any[], value: T) {\n const keys: string[] = Array.isArray(key) ? key : [key]\n const cacheableMap = new Map()\n\n keys.forEach(key => {\n cacheableMap.set(key, value)\n })\n\n const cacheKeys = [...cacheableMap.keys()]\n const cacheAssets = {\n cacheKeys,\n keys,\n }\n\n keys.forEach(key => {\n this._cacheMap.set(key, cacheAssets)\n })\n\n cacheKeys.forEach(key => {\n const val = value\n\n if (this._cache.has(key) && this._cache.has(key) !== val) {\n\n }\n\n this._cache.set(key, cacheableMap.get(key))\n })\n }\n\n public remove(key: any) {\n if (!this._cacheMap.has(key)) {\n return\n }\n\n const cacheMap = this._cacheMap.get(key)\n const cacheKeys = cacheMap?.cacheKeys || []\n\n cacheKeys.forEach(key => {\n this._cache.delete(key)\n })\n\n cacheMap?.keys.forEach(key => {\n this._cacheMap.delete(key)\n })\n }\n}\n\n// function getCacheableAssets(keys: string[], assets: Texture[]) {\n// const out: Record<string, Texture> = {}\n\n// keys.forEach(key => {\n// assets.forEach((asset, i) => {\n// out[key + (i === 0 ? '' : i + 1)] = asset\n// })\n// })\n\n// return out\n// }\n\nexport const Cache = new CacheClass()\n","import { TextureSource } from '@/renderer/texture/TextureSource'\nimport { Texture } from '@/renderer/texture/Texture'\nimport { Cache} from '../cache/Cache'\nimport { UnresolvedAsset } from '../Assets'\n\nexport interface ResolvedAsset {\n alias: string[]\n src: string\n progressSize?: number\n}\n\nexport type ProgressCallback = (progress: number) => void\n\nexport interface LoadOptions {\n onProgress?: (progress: number) => void\n onError?: (error: Error, url: string) => void\n strategy?: 'throw' | 'skip' | 'retry'\n retryCount?: number\n retryDelay?: number\n}\n\nabstract class File<T> {\n public key: string\n public url: string\n constructor(key: string, url: string) {\n this.key = key\n this.url = url\n }\n\n abstract load(): Promise<T>\n}\n\nexport class ImageFile extends File<HTMLImageElement> {\n load(): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image()\n img.onload = () => resolve(img)\n img.onerror = () => reject(new Error(`Failed to load ${this.url}`))\n img.src = this.url\n })\n }\n}\n\nexport class Loader {\n public static defaultOptions: LoadOptions = {\n strategy: 'throw',\n retryCount: 3,\n retryDelay: 250,\n }\n public promiseCache: Record<string, Promise<Texture>> = {}\n public loadOptions = { ...Loader.defaultOptions }\n\n public getAlias(asset: UnresolvedAsset) {\n const { alias, src } = asset\n\n const origin = alias || src\n const list = Array.isArray(origin) ? origin : [origin]\n const aliasesToUse: string[] = list.map(item => {\n if (typeof item === 'string') return item\n if (Array.isArray(item)) return item.map(v => v.src ?? v)\n if (item?.src) return item.src\n\n return item\n })\n\n return aliasesToUse\n }\n\n async load(\n assetsToLoad: ResolvedAsset[],\n onProgressOrOptions?: ProgressCallback | LoadOptions\n ) {\n\n const options = typeof onProgressOrOptions === 'function'\n ? { ...Loader.defaultOptions, ...this.loadOptions, onProgress: onProgressOrOptions }\n : { ...Loader.defaultOptions, ...this.loadOptions, ...(onProgressOrOptions || {}) }\n const { onProgress, onError, strategy, retryCount, retryDelay } = options\n\n let count = 0\n\n const assets: Record<string, Texture> = {}\n const total = assetsToLoad.reduce((sum, asset) => sum + (asset.progressSize || 1), 0)\n\n const promises = assetsToLoad.map(async asset => {\n if (assets[asset.src]) return\n\n const url = asset.src\n\n await this._loadAssetWithRetry(url, asset, { onProgress, onError, strategy, retryCount, retryDelay }, assets)\n\n count += (asset.progressSize || 1)\n if (onProgress) onProgress(count / total)\n })\n\n await Promise.all(promises)\n\n return assets\n }\n\n public async unload(assetsToLoad: ResolvedAsset[]) {\n const promises = assetsToLoad.map(async asset => {\n const url = asset.src\n const loadPromise = this.promiseCache[url]\n\n if (loadPromise) {\n const loadedAsset = await loadPromise\n\n delete this.promiseCache[url]\n\n loadedAsset.destroy(true)\n }\n })\n\n await Promise.all(promises)\n }\n\n private _getLoadPromise(url: string, data?: any) {\n const promise = (async () => {\n const asset = await loadTextures(url, data, this)\n return asset\n })()\n\n return promise\n }\n\n private async _loadAssetWithRetry(\n url: string,\n asset: ResolvedAsset,\n options: LoadOptions,\n assets: Record<string, Texture>\n ) {\n let attempt = 0\n\n const { onError, strategy, retryCount, retryDelay } = options\n const wait = (ms: number) => new Promise(r => setTimeout(r, ms))\n\n while (true) {\n try {\n if (!this.promiseCache[url]) {\n this.promiseCache[url] = this._getLoadPromise(url, asset)\n }\n\n assets[asset.src] = await this.promiseCache[url]\n\n return\n } catch(e) {\n delete this.promiseCache[url]\n delete assets[asset.src]\n\n attempt++\n\n const isLast = strategy !== 'retry' || attempt > retryCount\n\n if (strategy === 'retry' && !isLast) {\n if (onError) onError(e as Error, asset.src)\n\n await wait(retryDelay)\n continue\n }\n\n if (strategy === 'skip') {\n if (onError) onError(e as Error, asset.src)\n return\n }\n\n if (onError) onError(e as Error, asset.src)\n const error = new Error(`[Loader.load] Failed to load ${url}.\\n${e}`);\n\n if (e instanceof Error && e.stack) {\n error.stack = e.stack\n }\n\n throw error\n }\n }\n }\n\n public reset() {\n this.promiseCache = {}\n }\n}\n\n// function toAbsolute(url: string) {\n// const { origin, pathname } = window.location\n// if (url.startsWith('/')) {\n// return origin + url\n// }\n// const baseUrl = origin + pathname\n\n// return baseUrl + url\n// }\n\nasync function loadTextures(url: string, _asset: ResolvedAsset, loader: Loader) {\n let src: any = null\n\n if (globalThis.createImageBitmap) {\n src = await loadImageBitmap(url)\n } else {\n src = await new Promise((resolve, reject) => {\n src = new Image()\n ;(src as HTMLImageElement).crossOrigin = 'anonymous'\n\n src.src = url\n if (src.complete) {\n resolve(src)\n } else {\n src.onload = () => { resolve(src) }\n src.onerror = reject\n }\n })\n }\n\n const base = new TextureSource({\n resource: src\n })\n\n return createTexture(base, loader, url)\n}\n\nasync function loadImageBitmap(url: string) {\n const response = await window.fetch(url)\n\n // TODO: 暂时针对测试用例明确html算失败\n if (response.headers.get('content-type') === 'text/html' || !response.ok) {\n throw new Error(`[loadImageBitmap] Failed to fetch ${url}: `\n + `${response.status} ${response.statusText}`);\n }\n\n const imageBlob = await response.blob()\n return window.createImageBitmap(imageBlob)\n}\n\nfunction createTexture(source: TextureSource, loader: Loader, url: string) {\n source.label = url\n\n const texture = new Texture({\n source,\n label: url,\n })\n\n const unload = () => {\n delete loader.promiseCache[url]\n\n if (Cache.has(url)) {\n Cache.remove(url)\n }\n }\n\n texture.source.on('destroy', () => {\n if (loader.promiseCache[url]) {\n unload()\n }\n })\n\n texture.on('destroy', () => {\n if (!source.destroyed) {\n unload()\n }\n })\n\n return texture\n}\n","import { ArrayOr } from \"@/utils/type\"\nimport { Loader, LoadOptions, ProgressCallback } from \"./loader/Loader\"\nimport { Cache } from \"./cache/Cache\"\nimport { Texture } from \"@/renderer/texture/Texture\"\n\nexport type UnresolvedAsset<T = any> = {\n alias: ArrayOr<T>\n src: string\n}\n\n\nexport interface AssetInitOptions {\n basePath?: string\n loadOptions?: Partial<LoadOptions>\n}\n\nexport class AssetsClass {\n public cache: typeof Cache\n public loader: Loader\n public basePath: string\n\n private _initialized = false\n\n constructor() {\n this.loader = new Loader()\n this.cache = Cache\n }\n\n public init(options: AssetInitOptions = {}) {\n if (this._initialized) return\n\n this._initialized = true\n\n if (options.basePath) {\n // TODO: resolver\n this.basePath = options.basePath\n }\n\n // const formats = ['png', 'jpg', 'jpeg']\n // TODO: resolver\n\n if (options.loadOptions) {\n this.loader.loadOptions = {\n ...this.loader.loadOptions,\n ...options.loadOptions,\n }\n }\n }\n\n public async load(\n urls: UnresolvedAsset[],\n onProgress?: ProgressCallback | LoadOptions\n ) {\n if (!this._initialized) {\n this.init()\n }\n\n // TODO: check cache\n const resolvedResults = urls.map(item => {\n return { ...item, src: this.basePath ? `${this.basePath}/${item.src}` : item.src}\n })\n\n const out = await this._mapLoadToResolve(resolvedResults, onProgress)\n\n return out\n }\n\n private async _mapLoadToResolve(\n resolveResults: UnresolvedAsset[],\n progressOrLoadOptions?: ProgressCallback | LoadOptions\n ) {\n const resolvedArray = Object.values(resolveResults)\n const loadedAssets = await this.loader.load(resolvedArray, progressOrLoadOptions)\n\n const out: Record<string, Texture> = {}\n\n resolvedArray.forEach(resolveResult => {\n const asset = loadedAssets[resolveResult.src]\n const alias = Array.isArray(resolveResult.alias) ? resolveResult.alias : [resolveResult.alias]\n const keys = [resolveResult.src, ...alias]\n\n keys.forEach(key => {\n out[key] = asset\n })\n\n Cache.set(keys, asset)\n })\n\n return out\n }\n\n public reset() {\n this._initialized = false\n this.cache.reset()\n this.loader.reset()\n }\n}\n\nexport const Assets = new AssetsClass()\n"],"x_google_ignoreList":[12,13],"mappings":"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"}