From fbacb7a6062b35f8c037a7da15c25c6c50a32a6d Mon Sep 17 00:00:00 2001 From: ienaga Date: Fri, 2 Aug 2024 09:49:19 +0900 Subject: [PATCH] =?UTF-8?q?#154=20display=E3=83=91=E3=83=83=E3=82=B1?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=81=AE=E7=A7=BB=E6=A4=8D(WIP)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- @types/window.d.ts | 17 - packages/core/src/CoreUtil.ts | 44 +- packages/core/src/Display.ts | 12 +- .../core/src/Next2D/CreateRootMovieClip.ts | 4 +- packages/core/src/Next2D/LoadService.ts | 123 +- packages/core/src/Player.ts | 356 +- .../Player/PlayerResizePostMessageService.ts | 11 +- packages/core/src/interface/DisplayImpl.ts | 12 +- packages/display/src/BlendMode.test.ts | 107 + packages/display/src/BlendMode.ts | 58 +- packages/display/src/DisplayObject.ts | 4118 ++++++++--------- .../DisplayObjectGetPlaceObjectService.ts | 53 + .../DisplayObjectGetRawMatrixService.ts | 47 + .../display/src/DisplayObjectContainer.ts | 4047 ++++++++-------- packages/display/src/DisplayObjectUtil.ts | 289 ++ packages/display/src/FrameLabel.ts | 35 +- packages/display/src/InteractiveObject.ts | 14 +- packages/display/src/Loader.ts | 404 +- .../display/src/Loader/LoaderBuildService.ts | 35 + .../Loader/LoaderLoadEndEventService.test.ts | 93 + .../src/Loader/LoaderLoadEndEventService.ts | 57 + .../src/Loader/LoaderLoadJsonService.ts | 41 + .../LoaderLoadStartEventService.test.ts | 74 + .../src/Loader/LoaderLoadStartEventService.ts | 29 + .../Loader/LoaderProgressEventService.test.ts | 44 + .../src/Loader/LoaderProgressEventService.ts | 22 + .../display/src/Loader/ZlibInflateWorker.ts | 24 + packages/display/src/LoaderInfo.test.ts | 31 + packages/display/src/LoaderInfo.ts | 92 +- packages/display/src/index.ts | 6 +- .../display/src/interface/AjaxEventImpl.ts | 5 + .../display/src/interface/AjaxOptionImpl.ts | 14 + .../display/src/interface/BlendModeImpl.ts | 15 + packages/display/src/interface/Character.ts | 3 + .../display/src/interface/CharacterImpl.ts | 1 + .../src/interface/DictionaryTagImpl.ts | 7 + .../src/interface/DisplayObjectImpl.ts | 3 + .../display/src/interface/FilterArrayImpl.ts | 23 + .../src/interface/LoaderInfoDataImpl.ts | 8 + .../display/src/interface/LoopConfigImpl.ts | 9 + .../display/src/interface/LoopTypeImpl.ts | 5 + .../display/src/interface/NoCodeDataImpl.ts | 8 + packages/display/src/interface/ParentImpl.ts | 3 + .../display/src/interface/PlaceObjectImpl.ts | 15 + .../display/src/interface/StageDataImpl.ts | 6 + .../src/interface/SurfaceFilterImpl.ts | 14 + .../src/interface/URLLoaderDataFormatImpl.ts | 1 + .../src/interface/URLRequestHeaderImpl.ts | 5 + .../src/interface/URLRequestMethodImpl.ts | 1 + packages/geom/src/Matrix.ts | 13 + packages/interface/src/Character.ts | 2 +- packages/media/src/Sound.ts | 11 +- .../Sound/SoundLoadendEventService.test.ts | 2 +- .../src/Sound/SoundLoadendEventService.ts | 4 +- packages/renderer/package.json | 4 +- .../CommandInitializeContextService.test.ts | 67 + .../CommandInitializeContextService.ts | 48 + .../src/Command/CommandResizeService.ts | 77 + packages/renderer/src/CommandController.ts | 46 +- .../renderer/src/RendererDisplayObject.ts | 819 ++++ .../src/RendererDisplayObjectContainer.ts | 783 ++++ packages/renderer/src/RendererGraphics.ts | 1176 +++++ packages/renderer/src/RendererShape.ts | 152 + packages/renderer/src/RendererTextField.ts | 1031 +++++ packages/renderer/src/RendererUtil.ts | 140 + packages/renderer/src/RendererVideo.ts | 452 ++ packages/renderer/src/index.ts | 12 +- .../renderer/src/interface/BlendModeImpl.ts | 15 + packages/renderer/src/interface/GridImpl.ts | 6 + .../src/interface/PropertyMessageImpl.ts | 39 + .../src/interface/PropertyMessageMapImpl.ts | 3 + packages/{display => text}/src/TextField.ts | 0 packages/webgl/src/CanvasToWebGLContext.ts | 162 +- packages/webgl/src/WebGLUtil.ts | 20 + packages/webgl/src/index.ts | 1 + worker/unzip/UnzipWorker.min.js | 1 - worker/unzip/src/index.ts | 12 +- 77 files changed, 10572 insertions(+), 4971 deletions(-) create mode 100644 packages/display/src/BlendMode.test.ts create mode 100644 packages/display/src/DisplayObject/DisplayObjectGetPlaceObjectService.ts create mode 100644 packages/display/src/DisplayObject/DisplayObjectGetRawMatrixService.ts create mode 100644 packages/display/src/DisplayObjectUtil.ts create mode 100644 packages/display/src/Loader/LoaderBuildService.ts create mode 100644 packages/display/src/Loader/LoaderLoadEndEventService.test.ts create mode 100644 packages/display/src/Loader/LoaderLoadEndEventService.ts create mode 100644 packages/display/src/Loader/LoaderLoadJsonService.ts create mode 100644 packages/display/src/Loader/LoaderLoadStartEventService.test.ts create mode 100644 packages/display/src/Loader/LoaderLoadStartEventService.ts create mode 100644 packages/display/src/Loader/LoaderProgressEventService.test.ts create mode 100644 packages/display/src/Loader/LoaderProgressEventService.ts create mode 100644 packages/display/src/Loader/ZlibInflateWorker.ts create mode 100644 packages/display/src/LoaderInfo.test.ts create mode 100644 packages/display/src/interface/AjaxEventImpl.ts create mode 100644 packages/display/src/interface/AjaxOptionImpl.ts create mode 100644 packages/display/src/interface/BlendModeImpl.ts create mode 100644 packages/display/src/interface/Character.ts create mode 100644 packages/display/src/interface/CharacterImpl.ts create mode 100644 packages/display/src/interface/DictionaryTagImpl.ts create mode 100644 packages/display/src/interface/DisplayObjectImpl.ts create mode 100644 packages/display/src/interface/FilterArrayImpl.ts create mode 100644 packages/display/src/interface/LoaderInfoDataImpl.ts create mode 100644 packages/display/src/interface/LoopConfigImpl.ts create mode 100644 packages/display/src/interface/LoopTypeImpl.ts create mode 100644 packages/display/src/interface/NoCodeDataImpl.ts create mode 100644 packages/display/src/interface/ParentImpl.ts create mode 100644 packages/display/src/interface/PlaceObjectImpl.ts create mode 100644 packages/display/src/interface/StageDataImpl.ts create mode 100644 packages/display/src/interface/SurfaceFilterImpl.ts create mode 100644 packages/display/src/interface/URLLoaderDataFormatImpl.ts create mode 100644 packages/display/src/interface/URLRequestHeaderImpl.ts create mode 100644 packages/display/src/interface/URLRequestMethodImpl.ts create mode 100644 packages/renderer/src/Command/CommandInitializeContextService.test.ts create mode 100644 packages/renderer/src/Command/CommandInitializeContextService.ts create mode 100644 packages/renderer/src/Command/CommandResizeService.ts create mode 100644 packages/renderer/src/RendererDisplayObject.ts create mode 100644 packages/renderer/src/RendererDisplayObjectContainer.ts create mode 100644 packages/renderer/src/RendererGraphics.ts create mode 100644 packages/renderer/src/RendererShape.ts create mode 100644 packages/renderer/src/RendererTextField.ts create mode 100644 packages/renderer/src/RendererUtil.ts create mode 100644 packages/renderer/src/RendererVideo.ts create mode 100644 packages/renderer/src/interface/BlendModeImpl.ts create mode 100644 packages/renderer/src/interface/GridImpl.ts create mode 100644 packages/renderer/src/interface/PropertyMessageImpl.ts create mode 100644 packages/renderer/src/interface/PropertyMessageMapImpl.ts rename packages/{display => text}/src/TextField.ts (100%) delete mode 100644 worker/unzip/UnzipWorker.min.js diff --git a/@types/window.d.ts b/@types/window.d.ts index 9540f433..0a9c1852 100644 --- a/@types/window.d.ts +++ b/@types/window.d.ts @@ -6,25 +6,8 @@ declare global { // eslint-disable-next-line no-unused-vars const next2d: Next2D; - // eslint-disable-next-line no-unused-vars - interface Location { - search: string; - origin: string; - } - // eslint-disable-next-line no-unused-vars interface Window { - performance: Performance; - navigator: Navigator; - setTimeout: setTimeout; - Map: Map; - Number: Number; - Array: Array; - document: Document; - location: Location; - isNaN: isNaN; - Math: Math; - Event: Event; next2d?: Next2D; } diff --git a/packages/core/src/CoreUtil.ts b/packages/core/src/CoreUtil.ts index 82f38aab..4e656c59 100644 --- a/packages/core/src/CoreUtil.ts +++ b/packages/core/src/CoreUtil.ts @@ -1,3 +1,12 @@ +// @ts-ignore +import RendererWorker from "@next2d/renderer?worker&inline"; + +/** + * @type {Worker} + * @public + */ +export const $rendererWorker: Worker = new RendererWorker(); + /** * @type {number} * @const @@ -22,15 +31,6 @@ export const $PREFIX: string = "__next2d__"; */ export const $devicePixelRatio: number = window.devicePixelRatio; -// @ts-ignore -import RendererWorker from "@next2d/renderer?worker&inline"; - -/** - * @type {Worker} - * @public - */ -export const $rendererWorker: Worker = new RendererWorker(); - /** * @param {number} value * @param {number} min @@ -54,3 +54,29 @@ export const $clamp = ( : Math.min(Math.max(min, isNaN(number) ? 0 : number), max); }; +/** + * @type {number} + * @public + */ +export let $stageWidth: number = 0; + +/** + * @type {number} + * @public + */ +export let $stageHeight: number = 0; + +/** + * @description ステージサイズを設定 + * Set stage size + * + * @param {number} width + * @return {void} + * @method + * @public + */ +export const $setStageSize = (width: number, height: number): void => +{ + $stageWidth = width; + $stageHeight = height; +}; \ No newline at end of file diff --git a/packages/core/src/Display.ts b/packages/core/src/Display.ts index 2ceea93e..98d10c0d 100644 --- a/packages/core/src/Display.ts +++ b/packages/core/src/Display.ts @@ -1,33 +1,29 @@ import type { DisplayImpl } from "./interface/DisplayImpl"; import { - DisplayObject, - InteractiveObject, - DisplayObjectContainer, Sprite, MovieClip, BitmapData, BlendMode, + DisplayObject, FrameLabel, Graphics, + InteractiveObject, Loader, - LoaderInfo, Shape, Stage, TextField } from "@next2d/display"; const display: DisplayImpl = { - DisplayObject, - InteractiveObject, - DisplayObjectContainer, Sprite, MovieClip, BitmapData, BlendMode, + DisplayObject, FrameLabel, Graphics, + InteractiveObject, Loader, - LoaderInfo, Shape, Stage, TextField diff --git a/packages/core/src/Next2D/CreateRootMovieClip.ts b/packages/core/src/Next2D/CreateRootMovieClip.ts index c926c3ef..ea237fc1 100644 --- a/packages/core/src/Next2D/CreateRootMovieClip.ts +++ b/packages/core/src/Next2D/CreateRootMovieClip.ts @@ -28,9 +28,7 @@ export const execute = async ( $player.height = height | 0; $player.frameRate = fps | 0; - $player - .setOptions(options) - .boot(); + $player.boot(options); const root: Sprite = $stage.addChild(new Sprite()); diff --git a/packages/core/src/Next2D/LoadService.ts b/packages/core/src/Next2D/LoadService.ts index 167b254a..d027824e 100644 --- a/packages/core/src/Next2D/LoadService.ts +++ b/packages/core/src/Next2D/LoadService.ts @@ -2,13 +2,10 @@ import type { PlayerOptionsImpl } from "../interface/PlayerOptionsImpl"; import type { StageDataImpl } from "../interface/StageDataImpl"; import { $player } from "../Player"; import { $clamp } from "../CoreUtil"; -import { - Event, - IOErrorEvent -} from "@next2d/events"; +import { URLRequest } from "@next2d/net"; +import { IOErrorEvent } from "@next2d/events"; import { Loader, - LoaderInfo, $stage } from "@next2d/display"; @@ -22,76 +19,86 @@ import { * @method * @protected */ -export const execute = (url: string, options: PlayerOptionsImpl): Promise => +export const execute = async (url: string, options: PlayerOptionsImpl): Promise => { - return new Promise((resolve: Function) => - { - if (url === "develop") { - const path: string = location - .search - .slice(1) - .split("&")[0]; - - if (!path) { - return ; - } - url = `${location.origin}/${path}`; - } + if (url === "develop") { + const path: string = location + .search + .slice(1) + .split("&")[0]; - if (!url) { + if (!path) { return ; } + url = `${location.origin}/${path}`; + } - if (url.charAt(1) === "/") { - url = url.slice(1); - } + if (!url) { + return ; + } - $player - .setOptions(options) - .boot(); + if (url.charAt(1) === "/") { + url = url.slice(1); + } - const loader: Loader = new Loader(); + $player.boot(options); - loader - .contentLoaderInfo - .addEventListener(IOErrorEvent.IO_ERROR, (event: IOErrorEvent): void => - { - alert("Error: " + event.text); - resolve(); - }); + const loader: Loader = new Loader(); - loader - .contentLoaderInfo - .addEventListener(Event.COMPLETE, (event: Event): void => - { - const loaderInfo: LoaderInfo = event.target as NonNullable; + const loaderInfo = loader.contentLoaderInfo; + loaderInfo.addEventListener(IOErrorEvent.IO_ERROR, (event: IOErrorEvent): void => + { + alert("Error: " + event.text); + }); - if (event.listener) { - loaderInfo - .removeEventListener(Event.COMPLETE, event.listener); - } + // loader + // .contentLoaderInfo + // .addEventListener(Event.COMPLETE, (event: Event): void => + // { + // const loaderInfo: LoaderInfo = event.target as NonNullable; - if (loaderInfo._$data) { + // if (event.listener) { + // loaderInfo + // .removeEventListener(Event.COMPLETE, event.listener); + // } - const stage: StageDataImpl = loaderInfo._$data.stage; + // if (loaderInfo._$data) { - $player.bgColor = stage.bgColor; - // $player._$setBackgroundColor(stage.bgColor); + // const stage: StageDataImpl = loaderInfo._$data.stage; - $stage.addChild(loaderInfo.content); + // $player.bgColor = stage.bgColor; + // // $player._$setBackgroundColor(stage.bgColor); - $player.width = stage.width; - $player.height = stage.height; + // $stage.addChild(loaderInfo.content); - // set fps fixed logic - $player.frameRate = $clamp(+stage.fps, 1, 60, 60); - } + // $player.width = stage.width; + // $player.height = stage.height; - // $player._$resize(); + // // set fps fixed logic + // $player.frameRate = $clamp(+stage.fps, 1, 60, 60); + // } - resolve(); - }); + // // $player._$resize(); - // loader.load(new URLRequest(url)); - }); + // resolve(); + // }); + + await loader.load(new URLRequest(url)); + + if (!loaderInfo.data) { + return ; + } + + const stage: StageDataImpl = loaderInfo.data.stage; + + $player.bgColor = stage.bgColor; + // $player._$setBackgroundColor(stage.bgColor); + + $stage.addChild(loaderInfo.content); + + $player.rendererWidth = stage.width; + $player.rendererHeight = stage.height; + + // set fps fixed logic + $player.frameRate = $clamp(stage.fps, 1, 60, 60); }; \ No newline at end of file diff --git a/packages/core/src/Player.ts b/packages/core/src/Player.ts index 33c7401f..7e3a4ddc 100644 --- a/packages/core/src/Player.ts +++ b/packages/core/src/Player.ts @@ -479,6 +479,35 @@ export class Player this._$rendererScale = renderer_scale; } + /** + * @description フルスクリーンモードの設定 + * Full screen mode setting + * + * @member {boolean} + * @default false + * @public + */ + get fullScreen (): boolean + { + return this._$fullScreen; + } + set fullScreen (full_screen: boolean) + { + if (this._$fullScreen === full_screen) { + return ; + } + + this._$fullScreen = full_screen; + + // display resize + playerResizeEventService( + this, + this._$initialWidth, + this._$initialHeight, + this._$fullScreen + ); + } + /** * @member {string} * @public @@ -555,32 +584,32 @@ export class Player // } } - /** - * @param {string} id - * @return {void} - * @method - * @public - */ - removeCache (id: string): void - { - $cacheStore.removeCache(id); - if ($rendererWorker) { - $rendererWorker.postMessage({ - "command": "removeCache", - "id": id - }); - } - } + // /** + // * @param {string} id + // * @return {void} + // * @method + // * @public + // */ + // removeCache (id: string): void + // { + // $cacheStore.removeCache(id); + // if ($rendererWorker) { + // $rendererWorker.postMessage({ + // "command": "removeCache", + // "id": id + // }); + // } + // } /** * @param {object} [options=null] - * @return {Player} + * @return {void} * @public */ - setOptions (options: PlayerOptionsImpl | null = null): Player + setOptions (options: PlayerOptionsImpl | null = null): void { if (!options) { - return this; + return ; } this._$fixedWidth = options.width || this._$fixedWidth; @@ -588,8 +617,6 @@ export class Player this._$tagId = options.tagId || this._$tagId; this._$bgColor = options.bgColor || this._$bgColor; this._$fullScreen = !!options.fullScreen; - - return this; } /** @@ -600,8 +627,10 @@ export class Player * @method * @public */ - boot (): void + boot (options: PlayerOptionsImpl | null = null): void { + this.setOptions(options); + // create element const element = playerCreateContainerElementService(); @@ -616,9 +645,6 @@ export class Player // start loading playerLoadingAnimationService(element); - // initialize worker - - if (!this._$fixedWidth && !this._$fixedHeight) { // register resize event playerResizeRegisterService( @@ -638,179 +664,179 @@ export class Player ); } - /** - * @return {void} - * @method - * @private - */ - _$updateLoadStatus (): void - { - if (this._$loadStatus === $LOAD_END) { - if (this._$loadId > -1) { - $cancelAnimationFrame(this._$loadId); - } + // /** + // * @return {void} + // * @method + // * @private + // */ + // _$updateLoadStatus (): void + // { + // if (this._$loadStatus === $LOAD_END) { + // if (this._$loadId > -1) { + // $cancelAnimationFrame(this._$loadId); + // } - this._$loadId = -1; - this._$loaded(); - return ; - } + // this._$loadId = -1; + // this._$loaded(); + // return ; + // } - this._$loadId = $requestAnimationFrame(() => - { - this._$updateLoadStatus(); - }); - } + // this._$loadId = $requestAnimationFrame(() => + // { + // this._$updateLoadStatus(); + // }); + // } - /** - * @return {void} - * @method - * @private - */ - _$loaded (): void - { - const element: HTMLElement | null = $document - .getElementById($PREFIX); + // /** + // * @return {void} + // * @method + // * @private + // */ + // _$loaded (): void + // { + // const element: HTMLElement | null = $document + // .getElementById($PREFIX); - if (element) { + // if (element) { - // background color - this._$setBackgroundColor(this._$bgColor); + // // background color + // this._$setBackgroundColor(this._$bgColor); - // DOM - this._$deleteNode(); + // // DOM + // this._$deleteNode(); - // append canvas - element.appendChild(this._$canvas); - element.appendChild($textArea); + // // append canvas + // element.appendChild(this._$canvas); + // element.appendChild($textArea); - // stage init action - this._$stage._$prepareActions(); + // // stage init action + // this._$stage._$prepareActions(); - // constructed event - if (this._$broadcastEvents.has(Next2DEvent.FRAME_CONSTRUCTED)) { - this._$dispatchEvent(new Next2DEvent(Next2DEvent.FRAME_CONSTRUCTED)); - } + // // constructed event + // if (this._$broadcastEvents.has(Next2DEvent.FRAME_CONSTRUCTED)) { + // this._$dispatchEvent(new Next2DEvent(Next2DEvent.FRAME_CONSTRUCTED)); + // } - // frame1 action - this._$doAction(); + // // frame1 action + // this._$doAction(); - // exit event - if (this._$broadcastEvents.has(Next2DEvent.EXIT_FRAME)) { - this._$dispatchEvent(new Next2DEvent(Next2DEvent.EXIT_FRAME)); - } + // // exit event + // if (this._$broadcastEvents.has(Next2DEvent.EXIT_FRAME)) { + // this._$dispatchEvent(new Next2DEvent(Next2DEvent.EXIT_FRAME)); + // } - // loader events - const length: number = this._$loaders.length; - for (let idx: number = 0; idx < length; ++idx) { + // // loader events + // const length: number = this._$loaders.length; + // for (let idx: number = 0; idx < length; ++idx) { - const loader: EventDispatcherImpl = this._$loaders.shift(); + // const loader: EventDispatcherImpl = this._$loaders.shift(); - // init event - if (loader.hasEventListener(Next2DEvent.INIT)) { - loader.dispatchEvent(new Next2DEvent(Next2DEvent.INIT)); - } + // // init event + // if (loader.hasEventListener(Next2DEvent.INIT)) { + // loader.dispatchEvent(new Next2DEvent(Next2DEvent.INIT)); + // } - // complete event - if (loader.hasEventListener(Next2DEvent.COMPLETE)) { - loader.dispatchEvent(new Next2DEvent(Next2DEvent.COMPLETE)); - } - } + // // complete event + // if (loader.hasEventListener(Next2DEvent.COMPLETE)) { + // loader.dispatchEvent(new Next2DEvent(Next2DEvent.COMPLETE)); + // } + // } - // activate event - if (this._$broadcastEvents.has(Next2DEvent.ACTIVATE)) { - this._$dispatchEvent(new Next2DEvent(Next2DEvent.ACTIVATE)); - } + // // activate event + // if (this._$broadcastEvents.has(Next2DEvent.ACTIVATE)) { + // this._$dispatchEvent(new Next2DEvent(Next2DEvent.ACTIVATE)); + // } - // frame action - this._$doAction(); + // // frame action + // this._$doAction(); - // render - this._$draw(); + // // render + // this._$draw(); - // start - this.play(); - } + // // start + // this.play(); + // } - } + // } - /** - * @return {void} - * @method - * @private - */ - _$initialize (): void - { - if (!this._$tagId) { + // /** + // * @return {void} + // * @method + // * @private + // */ + // _$initialize (): void + // { + // if (!this._$tagId) { - $document - .body - .insertAdjacentHTML( - "beforeend", `
` - ); + // $document + // .body + // .insertAdjacentHTML( + // "beforeend", `
` + // ); - } else { + // } else { - const container: HTMLElement | null = $document.getElementById(this._$tagId); - if (!container) { - alert("Not Found Tag ID:" + this._$tagId); - return ; - } + // const container: HTMLElement | null = $document.getElementById(this._$tagId); + // if (!container) { + // alert("Not Found Tag ID:" + this._$tagId); + // return ; + // } - const div: HTMLElement | null = $document.getElementById($PREFIX); - if (!div) { + // const div: HTMLElement | null = $document.getElementById($PREFIX); + // if (!div) { - const element: HTMLDivElement = $document.createElement("div"); - element.id = $PREFIX; - element.tabIndex = -1; - container.appendChild(element); + // const element: HTMLDivElement = $document.createElement("div"); + // element.id = $PREFIX; + // element.tabIndex = -1; + // container.appendChild(element); - } else { + // } else { - this._$deleteNode(); + // this._$deleteNode(); - } + // } - } + // } - const element: HTMLElement | null = $document.getElementById($PREFIX); - if (!element) { - throw new Error("the content element is null."); - } + // const element: HTMLElement | null = $document.getElementById($PREFIX); + // if (!element) { + // throw new Error("the content element is null."); + // } - const parent: HTMLElement | null = element.parentElement; - if (parent) { - - this._$initStyle(element); - this._$buildWait(); - - const width: number = this._$fixedWidth - ? this._$fixedWidth - : parent.tagName === "BODY" - ? window.innerWidth - : parent.clientWidth; - - const height: number = this._$fixedHeight - ? this._$fixedHeight - : parent.tagName === "BODY" - ? window.innerHeight - : parent.clientHeight; - - // set center - if (this._$mode === "loader" && width && height) { - this._$baseWidth = width; - this._$baseHeight = height; - this._$resize(); - } - } + // const parent: HTMLElement | null = element.parentElement; + // if (parent) { - if (this._$mode === "loader") { - this._$loadStatus = $LOAD_START; - this._$updateLoadStatus(); - } else { - this._$resize(); - this._$loaded(); - } - } + // this._$initStyle(element); + // this._$buildWait(); + + // const width: number = this._$fixedWidth + // ? this._$fixedWidth + // : parent.tagName === "BODY" + // ? window.innerWidth + // : parent.clientWidth; + + // const height: number = this._$fixedHeight + // ? this._$fixedHeight + // : parent.tagName === "BODY" + // ? window.innerHeight + // : parent.clientHeight; + + // // set center + // if (this._$mode === "loader" && width && height) { + // this._$baseWidth = width; + // this._$baseHeight = height; + // this._$resize(); + // } + // } + + // if (this._$mode === "loader") { + // this._$loadStatus = $LOAD_START; + // this._$updateLoadStatus(); + // } else { + // this._$resize(); + // this._$loaded(); + // } + // } // /** // * @returns {void} diff --git a/packages/core/src/Player/PlayerResizePostMessageService.ts b/packages/core/src/Player/PlayerResizePostMessageService.ts index d5950a8f..eaad7ce4 100644 --- a/packages/core/src/Player/PlayerResizePostMessageService.ts +++ b/packages/core/src/Player/PlayerResizePostMessageService.ts @@ -1,6 +1,10 @@ import type { Player } from "../Player"; import type { ResizeMessageImpl } from "../interface/ResizeMessageImpl"; -import { $rendererWorker } from "../CoreUtil"; +import { + $rendererWorker, + $stageWidth, + $stageHeight +} from "../CoreUtil"; /** * @description リサイズメッセージ @@ -38,7 +42,10 @@ export const execute = (player: Player): void => message.buffer = new Float32Array([ player.rendererScale, player.rendererWidth, - player.rendererHeight + player.rendererHeight, + $stageWidth, + $stageHeight, + player.fullScreen ? 1 : 0 ]); options[0] = message.buffer.buffer; diff --git a/packages/core/src/interface/DisplayImpl.ts b/packages/core/src/interface/DisplayImpl.ts index 8f4369ca..099ea16e 100644 --- a/packages/core/src/interface/DisplayImpl.ts +++ b/packages/core/src/interface/DisplayImpl.ts @@ -1,13 +1,11 @@ import type { - DisplayObject, - InteractiveObject, - DisplayObjectContainer, BitmapData, BlendMode, + DisplayObject, FrameLabel, Graphics, + InteractiveObject, Loader, - LoaderInfo, MovieClip, Shape, Sprite, @@ -15,15 +13,13 @@ import type { TextField } from "@next2d/display"; export interface DisplayImpl { - DisplayObject: typeof DisplayObject; - InteractiveObject: typeof InteractiveObject; - DisplayObjectContainer: typeof DisplayObjectContainer; BitmapData: typeof BitmapData; BlendMode: typeof BlendMode; + DisplayObject: typeof DisplayObject; FrameLabel: typeof FrameLabel; Graphics: typeof Graphics; + InteractiveObject: typeof InteractiveObject; Loader: typeof Loader; - LoaderInfo: typeof LoaderInfo; MovieClip: typeof MovieClip; Shape: typeof Shape; Sprite: typeof Sprite; diff --git a/packages/display/src/BlendMode.test.ts b/packages/display/src/BlendMode.test.ts new file mode 100644 index 00000000..c4bfd228 --- /dev/null +++ b/packages/display/src/BlendMode.test.ts @@ -0,0 +1,107 @@ +import { BlendMode } from "./BlendMode"; +import { describe, expect, it } from "vitest"; + +describe("BlendMode.js toString test", () => +{ + it("toString test case1", () => + { + const blendMode = new BlendMode(); + expect(blendMode.toString()) + .toBe("[object BlendMode]"); + }); +}); + +describe("BlendMode.js static toString test", () => +{ + it("static toString test", () => + { + expect(BlendMode.toString()).toBe("[class BlendMode]"); + }); +}); + +describe("BlendMode.js namespace test", () => +{ + it("namespace test public", () => + { + const blendMode = new BlendMode(); + expect(blendMode.namespace).toBe("next2d.display.BlendMode"); + }); + + it("namespace test static", () => + { + expect(BlendMode.namespace).toBe("next2d.display.BlendMode"); + }); +}); + +describe("BlendMode.js property test", () => +{ + it("ADD test", () => + { + expect(BlendMode.ADD).toBe("add"); + }); + + it("ALPHA test", () => + { + expect(BlendMode.ALPHA).toBe("alpha"); + }); + + it("DARKEN test", () => + { + expect(BlendMode.DARKEN).toBe("darken"); + }); + + it("DIFFERENCE test", () => + { + expect(BlendMode.DIFFERENCE).toBe("difference"); + }); + + it("ERASE test", () => + { + expect(BlendMode.ERASE).toBe("erase"); + }); + + it("HARDLIGHT test", () => + { + expect(BlendMode.HARDLIGHT).toBe("hardlight"); + }); + + it("INVERT test", () => + { + expect(BlendMode.INVERT).toBe("invert"); + }); + + it("LAYER test", () => + { + expect(BlendMode.LAYER).toBe("layer"); + }); + + it("LIGHTEN test", () => + { + expect(BlendMode.LIGHTEN).toBe("lighten"); + }); + + it("MULTIPLY test", () => + { + expect(BlendMode.MULTIPLY).toBe("multiply"); + }); + + it("NORMAL test", () => + { + expect(BlendMode.NORMAL).toBe("normal"); + }); + + it("OVERLAY test", () => + { + expect(BlendMode.OVERLAY).toBe("overlay"); + }); + + it("SCREEN test", () => + { + expect(BlendMode.SCREEN).toBe("screen"); + }); + + it("SUBTRACT test", () => + { + expect(BlendMode.SUBTRACT).toBe("subtract"); + }); +}); \ No newline at end of file diff --git a/packages/display/src/BlendMode.ts b/packages/display/src/BlendMode.ts index dc2effa9..74f6f93d 100644 --- a/packages/display/src/BlendMode.ts +++ b/packages/display/src/BlendMode.ts @@ -1,14 +1,8 @@ /** - * ブレンドモードの視覚効果のために定数値を提供するクラスです。 - * 全てのDisplayObjectに設定が可能です。 - * A class that provides constant values for visual blend mode effects. - * It can be set for all DisplayObjects. - * - * @example usage of BlendMode. - * // static BlendMode - * const {BlendMode, MovieClip} = next2d.display; - * const movieClip = new MovieClip(); - * movieClip.blendMode = BlendMode.ADD; + * @description ブレンドモードの視覚効果のために定数値を提供するクラスです。 + * 全てのDisplayObjectに設定が可能です。 + * A class that provides constant values for visual blend mode effects. + * It can be set for all DisplayObjects. * * @class * @memberOf next2d.display @@ -21,11 +15,11 @@ export class BlendMode * Returns the string representation of the specified class. * * @return {string} - * @default [class BlendMode] + * @default "[class BlendMode]" * @method * @static */ - static toString () + static toString (): string { return "[class BlendMode]"; } @@ -35,11 +29,11 @@ export class BlendMode * Returns the space name of the specified class. * * @return {string} - * @default next2d.display.BlendMode + * @default "next2d.display.BlendMode" * @const * @static */ - static get namespace () + static get namespace (): string { return "next2d.display.BlendMode"; } @@ -49,11 +43,11 @@ export class BlendMode * Returns the string representation of the specified object. * * @return {string} - * @default [object BlendMode] + * @default "[object BlendMode]" * @method * @public */ - toString () + toString (): string { return "[object BlendMode]"; } @@ -63,11 +57,11 @@ export class BlendMode * Returns the space name of the specified object. * * @return {string} - * @default next2d.display.BlendMode + * @default "next2d.display.BlendMode" * @const * @public */ - get namespace () + get namespace (): string { return "next2d.display.BlendMode"; } @@ -82,7 +76,7 @@ export class BlendMode * @const * @static */ - static get ADD () + static get ADD (): string { return "add"; } @@ -96,7 +90,7 @@ export class BlendMode * @const * @static */ - static get ALPHA () + static get ALPHA (): string { return "alpha"; } @@ -111,7 +105,7 @@ export class BlendMode * @const * @static */ - static get DARKEN () + static get DARKEN (): string { return "darken"; } @@ -126,7 +120,7 @@ export class BlendMode * @const * @static */ - static get DIFFERENCE () + static get DIFFERENCE (): string { return "difference"; } @@ -140,7 +134,7 @@ export class BlendMode * @const * @static */ - static get ERASE () + static get ERASE (): string { return "erase"; } @@ -154,7 +148,7 @@ export class BlendMode * @const * @static */ - static get HARDLIGHT () + static get HARDLIGHT (): string { return "hardlight"; } @@ -168,7 +162,7 @@ export class BlendMode * @const * @static */ - static get INVERT () + static get INVERT (): string { return "invert"; } @@ -182,7 +176,7 @@ export class BlendMode * @const * @static */ - static get LAYER () + static get LAYER (): string { return "layer"; } @@ -197,7 +191,7 @@ export class BlendMode * @const * @static */ - static get LIGHTEN () + static get LIGHTEN (): string { return "lighten"; } @@ -212,7 +206,7 @@ export class BlendMode * @const * @static */ - static get MULTIPLY () + static get MULTIPLY (): string { return "multiply"; } @@ -226,7 +220,7 @@ export class BlendMode * @const * @static */ - static get NORMAL () + static get NORMAL (): string { return "normal"; } @@ -240,7 +234,7 @@ export class BlendMode * @const * @static */ - static get OVERLAY () + static get OVERLAY (): string { return "overlay"; } @@ -255,7 +249,7 @@ export class BlendMode * @const * @static */ - static get SCREEN () + static get SCREEN (): string { return "screen"; } @@ -270,7 +264,7 @@ export class BlendMode * @const * @static */ - static get SUBTRACT () + static get SUBTRACT (): string { return "subtract"; } diff --git a/packages/display/src/DisplayObject.ts b/packages/display/src/DisplayObject.ts index 9983220a..f888c913 100644 --- a/packages/display/src/DisplayObject.ts +++ b/packages/display/src/DisplayObject.ts @@ -5,79 +5,31 @@ import { Event as Next2DEvent, EventDispatcher } from "@next2d/events"; +// import { +// Transform, +// Rectangle, +// Point, +// ColorTransform, +// Matrix +// } from "@next2d/geom"; +// import type { +// CanvasToWebGLContext, +// FrameBufferManager +// } from "@next2d/webgl"; import { - Transform, - Rectangle, - Point, - ColorTransform, - Matrix -} from "@next2d/geom"; -import type { - FilterArrayImpl, - BlendModeImpl, - ParentImpl, - PlaceObjectImpl, - BoundsImpl, - DictionaryTagImpl, - PropertyMessageMapImpl, - DisplayObjectImpl, - AttachmentImpl, - PropertyMessageImpl, - CachePositionImpl -} from "@next2d/interface"; -import type { - CanvasToWebGLContext, - FrameBufferManager -} from "@next2d/webgl"; -import { - $getEvent, - $getInstanceId, - $currentMousePoint, - $poolColorTransform, - $rendererWorker, - $poolMatrix, - $hitContext, - $variables, - $blendToNumber -} from "@next2d/util"; -import { - $doUpdated, - $clamp, - $getArray, - $boundsMatrix, - $Math, - $poolBoundsObject, - $Infinity, - $getBoundsObject, - $isNaN, - $Deg2Rad, - $Number, - $Rad2Deg, - $SHORT_INT_MIN, - $SHORT_INT_MAX, - $MATRIX_ARRAY_IDENTITY, - $multiplicationMatrix, - $poolFloat32Array6, - $getMap, - $poolMap, - $getFloat32Array6, - $devicePixelRatio, - $poolArray, - $cacheStore -} from "@next2d/share"; + $getInstanceId +} from "./DisplayObjectUtil"; /** - * DisplayObject クラスは、表示リストに含めることのできるすべてのオブジェクトに関する基本クラスです。 - * DisplayObject クラス自体は、画面上でのコンテンツの描画のための API を含みません。 - * そのため、DisplayObject クラスのカスタムサブクラスを作成する場合は、 - * Shape、Sprite、Bitmap、TextField または MovieClip など、 - * 画面上にコンテンツを描画する API を持つサブクラスの 1 つを拡張する必要があります。 + * @description DisplayObject クラスは、表示リストに含めることのできるすべてのオブジェクトに関する基本クラスです。 + * DisplayObject クラス自体は、画面上でのコンテンツの描画のための API を含みません。 + * そのため、DisplayObject クラスのカスタムサブクラスを作成する場合は、 + * Shape、Sprite、TextField または MovieClip など、画面上にコンテンツを描画する API を持つサブクラスの 1 つを拡張する必要があります。 * - * The DisplayObject class is the base class for all objects that can be placed on the display list. - * The DisplayObject class itself does not include any APIs for rendering content onscreen. - * For that reason, if you want create a custom subclass of the DisplayObject class, - * you will want to extend one of its subclasses that do have APIs for rendering content onscreen, - * such as the Shape, Sprite, Bitmap, TextField, or MovieClip class. + * The DisplayObject class is the base class for all objects that can be placed on the display list. + * The DisplayObject class itself does not include any APIs for rendering content onscreen. + * For that reason, if you want create a custom subclass of the DisplayObject class, + * you will want to extend one of its subclasses that do have APIs for rendering content onscreen, such as the Shape, Sprite, TextField, or MovieClip class. * * @class * @memberOf next2d.display @@ -85,7 +37,7 @@ import { */ export class DisplayObject extends EventDispatcher { - public readonly _$instanceId: number; + protected readonly _$instanceId: number; protected _$id: number; protected _$stage: Stage | null; protected _$parent: ParentImpl | null; @@ -93,13 +45,13 @@ export class DisplayObject extends EventDispatcher protected _$characterId: number; protected _$active: boolean; protected _$isMask: boolean; - public _$updated: boolean; + protected _$updated: boolean; protected _$added: boolean; protected _$addedStage: boolean; protected _$filters: FilterArrayImpl | null; protected _$blendMode: BlendModeImpl | null; protected _$transform: Transform; - public _$hitObject: Sprite | null; + protected _$hitObject: Sprite | null; protected _$isNext: boolean; protected _$created: boolean; protected _$posted: boolean; @@ -108,7 +60,7 @@ export class DisplayObject extends EventDispatcher protected _$mask: DisplayObjectImpl | null; protected _$visible: boolean; protected _$root: ParentImpl | null; - public _$loaderInfo: LoaderInfo | null; + protected _$loaderInfo: LoaderInfo | null; protected _$scaleX: number | null; protected _$scaleY: number | null; protected _$variables: Map | null; @@ -315,11 +267,11 @@ export class DisplayObject extends EventDispatcher */ this._$endFrame = 0; - /** - * @type {Transform} - * @private - */ - this._$transform = new Transform(this); + // /** + // * @type {Transform} + // * @private + // */ + // this._$transform = new Transform(this); /** * @type {Map} @@ -420,2013 +372,2013 @@ export class DisplayObject extends EventDispatcher } } - /** - * @description 使用するブレンドモードを指定する BlendMode クラスの値です。 - * A value from the BlendMode class that specifies which blend mode to use. - * - * @member {string} - * @default BlendMode.NORMAL - * @public - */ - get blendMode (): BlendModeImpl - { - // use cache - if (this._$blendMode) { - return this._$blendMode; - } - - const transform: Transform = this._$transform; - if (transform._$blendMode) { - - // cache - this._$blendMode = transform._$blendMode; - - return transform._$blendMode; - } - - const placeObject: PlaceObjectImpl | null = this._$placeObject || this._$getPlaceObject(); - if (placeObject && placeObject.blendMode) { - - // cache - this._$blendMode = placeObject.blendMode; - - return placeObject.blendMode; - } - - // cache - this._$blendMode = "normal"; - - return "normal"; - } - set blendMode (blend_mode: BlendModeImpl) - { - const transform: Transform = this._$transform; - if (!transform._$blendMode) { - transform._$transform(null, null, null, blend_mode); - } else { - transform._$blendMode = blend_mode; - this._$doChanged(); - $doUpdated(); - } - this._$blendMode = blend_mode; - } - - /** - * @description 表示オブジェクトに現在関連付けられている各フィルターオブジェクトが - * 格納されているインデックス付きの配列です。 - * An indexed array that contains each filter object - * currently associated with the display object. - * - * @member {array} - * @default {array} - * @public - */ - get filters (): FilterArrayImpl - { - // use cache - if (this._$filters) { - const filters: FilterArrayImpl = $getArray(); - for (let idx: number = 0; idx < this._$filters.length; ++idx) { - filters[idx] = this._$filters[idx].clone(); - } - return filters; - } - - const transform: Transform = this._$transform; - if (transform._$filters) { - - const clone: FilterArrayImpl = $getArray(); - const filters: FilterArrayImpl = $getArray(); - for (let idx: number = 0; idx < transform._$filters.length; ++idx) { - const filter = transform._$filters[idx]; - clone[idx] = filter.clone(); - filters[idx] = filter.clone(); - } - - // cache - this._$filters = clone; - - return filters; - } - - const placeObject: PlaceObjectImpl | null = this._$placeObject || this._$getPlaceObject(); - if (placeObject && placeObject.surfaceFilterList) { - - // create filter - if (!placeObject.filters) { - placeObject.filters = transform - ._$buildFilter(placeObject.surfaceFilterList); - } - - const clone: FilterArrayImpl = $getArray(); - - // @ts-ignore - const filters: FilterArrayImpl = $getArray(); - for (let idx: number = 0; idx < placeObject.filters.length; ++idx) { - const filter = placeObject.filters[idx]; - clone[idx] = filter.clone(); - filters[idx] = filter.clone(); - } - - // cache - this._$filters = clone; - - return filters; - } - - const filters: FilterArrayImpl = $getArray(); - - // cache - this._$filters = filters; - - return filters; - } - set filters (filters: FilterArrayImpl | null) - { - if (!filters) { - filters = $getArray(); - } - - this._$transform._$transform(null, null, filters); - this._$filters = filters; - } - - /** - * @description 表示オブジェクトの高さを示します(ピクセル単位)。 - * Indicates the height of the display object, in pixels. - * - * @member {number} - * @public - */ - get height (): number - { - const baseBounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" - ? this._$getBounds() as BoundsImpl - : $getBoundsObject(); - - const bounds: BoundsImpl = $boundsMatrix( - baseBounds, - this._$transform._$rawMatrix() - ); - $poolBoundsObject(baseBounds); - - const height: number = $Math.abs(bounds.yMax - bounds.yMin); - - // object pool - $poolBoundsObject(bounds); - - switch (height) { - - case 0: - case $Infinity: - case -$Infinity: - return 0; - - default: - return +height.toFixed(2); - - } - } - set height (height: number) - { - height = +height; - if (!$isNaN(height) && height > -1) { - - const baseBounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" - ? this._$getBounds() as BoundsImpl - : $getBoundsObject(); - - const rotation: number = this.rotation; - const bounds: BoundsImpl = rotation - ? $boundsMatrix(baseBounds, this._$transform._$rawMatrix()) - : baseBounds; - - if (rotation) { - $poolBoundsObject(baseBounds); - } - - const exHeight: number = $Math.abs(bounds.yMax - bounds.yMin); - $poolBoundsObject(bounds); - - switch (exHeight) { - - case 0: - case $Infinity: - case -$Infinity: - this.scaleY = 0; - break; - - default: - this.scaleY = height / exHeight; - break; - - } - } - } - - /** - * @description この表示オブジェクトが属するファイルの読み込み情報を含む LoaderInfo オブジェクトを返します。 - * Returns a LoaderInfo object containing information - * about loading the file to which this display object belongs. - * - * @member {LoaderInfo} - * @default null - * @readonly - * @public - */ - get loaderInfo (): LoaderInfo | null - { - return this._$loaderInfo; - } - - /** - * @description 呼び出し元の表示オブジェクトは、指定された mask オブジェクトによってマスクされます。 - * The calling display object is masked by the specified mask object. - * - * @member {DisplayObject|null} - * @public - */ - get mask (): DisplayObjectImpl | null - { - return this._$mask; - } - set mask (mask: DisplayObjectImpl | null) - { - if (mask === this._$mask) { - return ; - } - - // reset - if (this._$mask) { - if ($rendererWorker && this._$mask.stage) { - this._$mask._$removeWorkerInstance(); - } - - this._$mask._$isMask = false; - this._$mask = null; - } - - if (mask) { - if ($rendererWorker - && "_$createWorkerInstance" in mask - && typeof mask._$createWorkerInstance === "function" - ) { - mask._$createWorkerInstance(); - } - - mask._$isMask = true; - this._$mask = mask; - } - - this._$doChanged(); - } - - /** - * @description マウスまたはユーザー入力デバイスの x 軸の位置をピクセルで示します。 - * Indicates the x coordinate of the mouse or user input device position, in pixels. - * - * @member {number} - * @default 0 - * @readonly - * @public - */ - get mouseX (): number - { - return $getEvent() - ? this.globalToLocal($currentMousePoint()).x - : 0; - } - - /** - * @description マウスまたはユーザー入力デバイスの y 軸の位置をピクセルで示します。 - * Indicates the y coordinate of the mouse or user input device position, in pixels. - * - * @member {number} - * @default 0 - * @readonly - * @public - */ - get mouseY (): number - { - return $getEvent() - ? this.globalToLocal($currentMousePoint()).y - : 0; - } - - /** - * @description DisplayObject のインスタンス名を示します。 - * Indicates the instance name of the DisplayObject. - * - * @member {string} - * @public - */ - get name (): string - { - if (this._$name) { - return this._$name; - } - return `instance${this._$instanceId}`; - } - set name (name: string) - { - this._$name = `${name}`; - - const parent: ParentImpl | null = this._$parent; - if (parent && parent._$names) { - - parent._$names.clear(); - - const children: DisplayObjectImpl[] = parent._$getChildren(); - for (let idx: number = 0; idx < children.length; ++idx) { - const child: DisplayObjectImpl = children[idx]; - if (child._$name) { - parent._$names.set(child.name, child); - } - } - } - } - - /** - * @description この表示オブジェクトを含む DisplayObjectContainer オブジェクトを示します。 - * Indicates the DisplayObjectContainer object that contains this display object. - * - * @member {DisplayObjectContainer | null} - * @readonly - * @public - */ - get parent (): ParentImpl | null - { - return this._$parent; - } - - /** - * @description 読み込まれた SWF ファイル内の表示オブジェクトの場合、 - * root プロパティはその SWF ファイルが表す表示リストのツリー構造部分の一番上にある表示オブジェクトとなります。 - * For a display object in a loaded SWF file, - * the root property is the top-most display object - * in the portion of the display list's tree structure represented by that SWF file. - * - * @member {DisplayObject|null} - * @readonly - * @public - */ - get root (): ParentImpl - { - return this._$root; - } - - /** - * @description DisplayObject インスタンスの元の位置からの回転角を度単位で示します。 - * Indicates the rotation of the DisplayObject instance, - * in degrees, from its original orientation. - * - * @member {number} - * @public - */ - get rotation (): number - { - if (this._$rotation !== null) { - return this._$rotation; - } - - const matrix: Float32Array = this._$transform._$rawMatrix(); - return $Math.atan2(matrix[1], matrix[0]) * $Rad2Deg; - } - set rotation (rotation: number) - { - rotation = $clamp(rotation % 360, 0 - 360, 360, 0); - if (this._$rotation === rotation) { - return ; - } - - const transform: Transform = this._$transform; - - const hasMatrix: boolean = transform._$matrix !== null; - - const matrix: Matrix = hasMatrix - ? transform._$matrix as NonNullable - : transform.matrix; - - const scaleX: number = $Math.sqrt(matrix.a * matrix.a + matrix.b * matrix.b); - const scaleY: number = $Math.sqrt(matrix.c * matrix.c + matrix.d * matrix.d); - if (rotation === 0) { - - matrix.a = scaleX; - matrix.b = 0; - matrix.c = 0; - matrix.d = scaleY; - - } else { - - let radianX: number = $Math.atan2(matrix.b, matrix.a); - let radianY: number = $Math.atan2(0 - matrix.c, matrix.d); - - const radian: number = rotation * $Deg2Rad; - radianY = radianY + radian - radianX; - radianX = radian; - - matrix.b = scaleX * $Math.sin(radianX); - if (matrix.b === 1 || matrix.b === -1) { - matrix.a = 0; - } else { - matrix.a = scaleX * $Math.cos(radianX); - } - - matrix.c = -scaleY * $Math.sin(radianY); - if (matrix.c === 1 || matrix.c === -1) { - matrix.d = 0; - } else { - matrix.d = scaleY * $Math.cos(radianY); - } - } - - if (hasMatrix) { - this._$doChanged(); - $doUpdated(); - } else { - transform.matrix = matrix; - $poolMatrix(matrix); - } - - this._$rotation = rotation; - } - - /** - * @description 現在有効な拡大 / 縮小グリッドです。 - * The current scaling grid that is in effect. - * - * @member {Rectangle} - * @public - */ - get scale9Grid (): Rectangle | null - { - return this._$scale9Grid; - } - set scale9Grid (scale_9_grid: Rectangle | null) - { - if (this._$scale9Grid !== scale_9_grid) { - this._$scale9Grid = scale_9_grid; - this._$doChanged(); - $doUpdated(); - } - } - - /** - * @description 基準点から適用されるオブジェクトの水平スケール(パーセンテージ)を示します。 - * Indicates the horizontal scale (percentage) - * of the object as applied from the registration point. - * - * @member {number} - * @public - */ - get scaleX (): number - { - if (this._$scaleX !== null) { - return this._$scaleX; - } - - const matrix: Float32Array = this._$transform._$rawMatrix(); - - let xScale: number = $Math.sqrt( - matrix[0] * matrix[0] - + matrix[1] * matrix[1] - ); - if (!$Number.isInteger(xScale)) { - const value: string = xScale.toString(); - const index: number = value.indexOf("e"); - if (index !== -1) { - xScale = +value.slice(0, index); - } - xScale = +xScale.toFixed(4); - } - - return 0 > matrix[0] ? xScale * -1 : xScale; - } - set scaleX (scale_x: number) - { - scale_x = $clamp(+scale_x, - $SHORT_INT_MIN, $SHORT_INT_MAX - ); - - if (!$Number.isInteger(scale_x)) { - const value: string = scale_x.toString(); - const index: number = value.indexOf("e"); - if (index !== -1) { - scale_x = +value.slice(0, index); - } - scale_x = +scale_x.toFixed(4); - } - - if (this._$scaleX === scale_x) { - return ; - } - - const transform: Transform = this._$transform; - - const hasMatrix: boolean = transform._$matrix !== null; - - const matrix: Matrix = hasMatrix - ? transform._$matrix as NonNullable - : transform.matrix; - - if (matrix.b === 0 || $isNaN(matrix.b)) { - - matrix.a = scale_x; - - } else { - - let radianX = $Math.atan2(matrix.b, matrix.a); - if (radianX === -$Math.PI) { - radianX = 0; - } - - matrix.b = scale_x * $Math.sin(radianX); - matrix.a = scale_x * $Math.cos(radianX); - - } - - if (hasMatrix) { - this._$doChanged(); - $doUpdated(); - } else { - transform.matrix = matrix; - $poolMatrix(matrix); - } - - this._$scaleX = scale_x; - } - - /** - * @description 基準点から適用されるオブジェクトの垂直スケール(パーセンテージ)を示します。 - * IIndicates the vertical scale (percentage) - * of an object as applied from the registration point. - * - * @member {number} - * @public - */ - get scaleY (): number - { - if (this._$scaleY !== null) { - return this._$scaleY; - } - - const matrix: Float32Array = this._$transform._$rawMatrix(); - - let yScale: number = $Math.sqrt( - matrix[2] * matrix[2] - + matrix[3] * matrix[3] - ); - - if (!$Number.isInteger(yScale)) { - const value: string = yScale.toString(); - const index: number = value.indexOf("e"); - if (index !== -1) { - yScale = +value.slice(0, index); - } - yScale = +yScale.toFixed(4); - } - - return 0 > matrix[3] ? yScale * -1 : yScale; - } - set scaleY (scale_y: number) - { - scale_y = $clamp(+scale_y, - $SHORT_INT_MIN, $SHORT_INT_MAX - ); - - if (!$Number.isInteger(scale_y)) { - const value: string = scale_y.toString(); - const index: number = value.indexOf("e"); - if (index !== -1) { - scale_y = +value.slice(0, index); - } - scale_y = +scale_y.toFixed(4); - } - - if (this._$scaleY === scale_y) { - return ; - } - - const transform: Transform = this._$transform; - - const hasMatrix: boolean = transform._$matrix !== null; - - const matrix: Matrix = hasMatrix - ? transform._$matrix as NonNullable - : transform.matrix; - - if (matrix.c === 0 || $isNaN(matrix.c)) { + // /** + // * @description 使用するブレンドモードを指定する BlendMode クラスの値です。 + // * A value from the BlendMode class that specifies which blend mode to use. + // * + // * @member {string} + // * @default BlendMode.NORMAL + // * @public + // */ + // get blendMode (): BlendModeImpl + // { + // // use cache + // if (this._$blendMode) { + // return this._$blendMode; + // } + + // const transform: Transform = this._$transform; + // if (transform._$blendMode) { + + // // cache + // this._$blendMode = transform._$blendMode; + + // return transform._$blendMode; + // } + + // const placeObject: PlaceObjectImpl | null = this._$placeObject || this._$getPlaceObject(); + // if (placeObject && placeObject.blendMode) { + + // // cache + // this._$blendMode = placeObject.blendMode; + + // return placeObject.blendMode; + // } + + // // cache + // this._$blendMode = "normal"; + + // return "normal"; + // } + // set blendMode (blend_mode: BlendModeImpl) + // { + // const transform: Transform = this._$transform; + // if (!transform._$blendMode) { + // transform._$transform(null, null, null, blend_mode); + // } else { + // transform._$blendMode = blend_mode; + // this._$doChanged(); + // $doUpdated(); + // } + // this._$blendMode = blend_mode; + // } + + // /** + // * @description 表示オブジェクトに現在関連付けられている各フィルターオブジェクトが + // * 格納されているインデックス付きの配列です。 + // * An indexed array that contains each filter object + // * currently associated with the display object. + // * + // * @member {array} + // * @default {array} + // * @public + // */ + // get filters (): FilterArrayImpl + // { + // // use cache + // if (this._$filters) { + // const filters: FilterArrayImpl = $getArray(); + // for (let idx: number = 0; idx < this._$filters.length; ++idx) { + // filters[idx] = this._$filters[idx].clone(); + // } + // return filters; + // } + + // const transform: Transform = this._$transform; + // if (transform._$filters) { + + // const clone: FilterArrayImpl = $getArray(); + // const filters: FilterArrayImpl = $getArray(); + // for (let idx: number = 0; idx < transform._$filters.length; ++idx) { + // const filter = transform._$filters[idx]; + // clone[idx] = filter.clone(); + // filters[idx] = filter.clone(); + // } + + // // cache + // this._$filters = clone; + + // return filters; + // } + + // const placeObject: PlaceObjectImpl | null = this._$placeObject || this._$getPlaceObject(); + // if (placeObject && placeObject.surfaceFilterList) { + + // // create filter + // if (!placeObject.filters) { + // placeObject.filters = transform + // ._$buildFilter(placeObject.surfaceFilterList); + // } + + // const clone: FilterArrayImpl = $getArray(); + + // // @ts-ignore + // const filters: FilterArrayImpl = $getArray(); + // for (let idx: number = 0; idx < placeObject.filters.length; ++idx) { + // const filter = placeObject.filters[idx]; + // clone[idx] = filter.clone(); + // filters[idx] = filter.clone(); + // } + + // // cache + // this._$filters = clone; + + // return filters; + // } + + // const filters: FilterArrayImpl = $getArray(); + + // // cache + // this._$filters = filters; + + // return filters; + // } + // set filters (filters: FilterArrayImpl | null) + // { + // if (!filters) { + // filters = $getArray(); + // } + + // this._$transform._$transform(null, null, filters); + // this._$filters = filters; + // } + + // /** + // * @description 表示オブジェクトの高さを示します(ピクセル単位)。 + // * Indicates the height of the display object, in pixels. + // * + // * @member {number} + // * @public + // */ + // get height (): number + // { + // const baseBounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" + // ? this._$getBounds() as BoundsImpl + // : $getBoundsObject(); + + // const bounds: BoundsImpl = $boundsMatrix( + // baseBounds, + // this._$transform._$rawMatrix() + // ); + // $poolBoundsObject(baseBounds); + + // const height: number = $Math.abs(bounds.yMax - bounds.yMin); + + // // object pool + // $poolBoundsObject(bounds); + + // switch (height) { + + // case 0: + // case $Infinity: + // case -$Infinity: + // return 0; + + // default: + // return +height.toFixed(2); + + // } + // } + // set height (height: number) + // { + // height = +height; + // if (!$isNaN(height) && height > -1) { + + // const baseBounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" + // ? this._$getBounds() as BoundsImpl + // : $getBoundsObject(); + + // const rotation: number = this.rotation; + // const bounds: BoundsImpl = rotation + // ? $boundsMatrix(baseBounds, this._$transform._$rawMatrix()) + // : baseBounds; + + // if (rotation) { + // $poolBoundsObject(baseBounds); + // } + + // const exHeight: number = $Math.abs(bounds.yMax - bounds.yMin); + // $poolBoundsObject(bounds); + + // switch (exHeight) { + + // case 0: + // case $Infinity: + // case -$Infinity: + // this.scaleY = 0; + // break; + + // default: + // this.scaleY = height / exHeight; + // break; + + // } + // } + // } + + // /** + // * @description この表示オブジェクトが属するファイルの読み込み情報を含む LoaderInfo オブジェクトを返します。 + // * Returns a LoaderInfo object containing information + // * about loading the file to which this display object belongs. + // * + // * @member {LoaderInfo} + // * @default null + // * @readonly + // * @public + // */ + // get loaderInfo (): LoaderInfo | null + // { + // return this._$loaderInfo; + // } + + // /** + // * @description 呼び出し元の表示オブジェクトは、指定された mask オブジェクトによってマスクされます。 + // * The calling display object is masked by the specified mask object. + // * + // * @member {DisplayObject|null} + // * @public + // */ + // get mask (): DisplayObjectImpl | null + // { + // return this._$mask; + // } + // set mask (mask: DisplayObjectImpl | null) + // { + // if (mask === this._$mask) { + // return ; + // } + + // // reset + // if (this._$mask) { + // if ($rendererWorker && this._$mask.stage) { + // this._$mask._$removeWorkerInstance(); + // } + + // this._$mask._$isMask = false; + // this._$mask = null; + // } + + // if (mask) { + // if ($rendererWorker + // && "_$createWorkerInstance" in mask + // && typeof mask._$createWorkerInstance === "function" + // ) { + // mask._$createWorkerInstance(); + // } + + // mask._$isMask = true; + // this._$mask = mask; + // } + + // this._$doChanged(); + // } + + // /** + // * @description マウスまたはユーザー入力デバイスの x 軸の位置をピクセルで示します。 + // * Indicates the x coordinate of the mouse or user input device position, in pixels. + // * + // * @member {number} + // * @default 0 + // * @readonly + // * @public + // */ + // get mouseX (): number + // { + // return $getEvent() + // ? this.globalToLocal($currentMousePoint()).x + // : 0; + // } + + // /** + // * @description マウスまたはユーザー入力デバイスの y 軸の位置をピクセルで示します。 + // * Indicates the y coordinate of the mouse or user input device position, in pixels. + // * + // * @member {number} + // * @default 0 + // * @readonly + // * @public + // */ + // get mouseY (): number + // { + // return $getEvent() + // ? this.globalToLocal($currentMousePoint()).y + // : 0; + // } + + // /** + // * @description DisplayObject のインスタンス名を示します。 + // * Indicates the instance name of the DisplayObject. + // * + // * @member {string} + // * @public + // */ + // get name (): string + // { + // if (this._$name) { + // return this._$name; + // } + // return `instance${this._$instanceId}`; + // } + // set name (name: string) + // { + // this._$name = `${name}`; + + // const parent: ParentImpl | null = this._$parent; + // if (parent && parent._$names) { + + // parent._$names.clear(); + + // const children: DisplayObjectImpl[] = parent._$getChildren(); + // for (let idx: number = 0; idx < children.length; ++idx) { + // const child: DisplayObjectImpl = children[idx]; + // if (child._$name) { + // parent._$names.set(child.name, child); + // } + // } + // } + // } + + // /** + // * @description この表示オブジェクトを含む DisplayObjectContainer オブジェクトを示します。 + // * Indicates the DisplayObjectContainer object that contains this display object. + // * + // * @member {DisplayObjectContainer | null} + // * @readonly + // * @public + // */ + // get parent (): ParentImpl | null + // { + // return this._$parent; + // } + + // /** + // * @description 読み込まれた SWF ファイル内の表示オブジェクトの場合、 + // * root プロパティはその SWF ファイルが表す表示リストのツリー構造部分の一番上にある表示オブジェクトとなります。 + // * For a display object in a loaded SWF file, + // * the root property is the top-most display object + // * in the portion of the display list's tree structure represented by that SWF file. + // * + // * @member {DisplayObject|null} + // * @readonly + // * @public + // */ + // get root (): ParentImpl + // { + // return this._$root; + // } + + // /** + // * @description DisplayObject インスタンスの元の位置からの回転角を度単位で示します。 + // * Indicates the rotation of the DisplayObject instance, + // * in degrees, from its original orientation. + // * + // * @member {number} + // * @public + // */ + // get rotation (): number + // { + // if (this._$rotation !== null) { + // return this._$rotation; + // } + + // const matrix: Float32Array = this._$transform._$rawMatrix(); + // return $Math.atan2(matrix[1], matrix[0]) * $Rad2Deg; + // } + // set rotation (rotation: number) + // { + // rotation = $clamp(rotation % 360, 0 - 360, 360, 0); + // if (this._$rotation === rotation) { + // return ; + // } + + // const transform: Transform = this._$transform; + + // const hasMatrix: boolean = transform._$matrix !== null; + + // const matrix: Matrix = hasMatrix + // ? transform._$matrix as NonNullable + // : transform.matrix; + + // const scaleX: number = $Math.sqrt(matrix.a * matrix.a + matrix.b * matrix.b); + // const scaleY: number = $Math.sqrt(matrix.c * matrix.c + matrix.d * matrix.d); + // if (rotation === 0) { + + // matrix.a = scaleX; + // matrix.b = 0; + // matrix.c = 0; + // matrix.d = scaleY; + + // } else { + + // let radianX: number = $Math.atan2(matrix.b, matrix.a); + // let radianY: number = $Math.atan2(0 - matrix.c, matrix.d); + + // const radian: number = rotation * $Deg2Rad; + // radianY = radianY + radian - radianX; + // radianX = radian; + + // matrix.b = scaleX * $Math.sin(radianX); + // if (matrix.b === 1 || matrix.b === -1) { + // matrix.a = 0; + // } else { + // matrix.a = scaleX * $Math.cos(radianX); + // } + + // matrix.c = -scaleY * $Math.sin(radianY); + // if (matrix.c === 1 || matrix.c === -1) { + // matrix.d = 0; + // } else { + // matrix.d = scaleY * $Math.cos(radianY); + // } + // } + + // if (hasMatrix) { + // this._$doChanged(); + // $doUpdated(); + // } else { + // transform.matrix = matrix; + // $poolMatrix(matrix); + // } + + // this._$rotation = rotation; + // } + + // /** + // * @description 現在有効な拡大 / 縮小グリッドです。 + // * The current scaling grid that is in effect. + // * + // * @member {Rectangle} + // * @public + // */ + // get scale9Grid (): Rectangle | null + // { + // return this._$scale9Grid; + // } + // set scale9Grid (scale_9_grid: Rectangle | null) + // { + // if (this._$scale9Grid !== scale_9_grid) { + // this._$scale9Grid = scale_9_grid; + // this._$doChanged(); + // $doUpdated(); + // } + // } + + // /** + // * @description 基準点から適用されるオブジェクトの水平スケール(パーセンテージ)を示します。 + // * Indicates the horizontal scale (percentage) + // * of the object as applied from the registration point. + // * + // * @member {number} + // * @public + // */ + // get scaleX (): number + // { + // if (this._$scaleX !== null) { + // return this._$scaleX; + // } + + // const matrix: Float32Array = this._$transform._$rawMatrix(); + + // let xScale: number = $Math.sqrt( + // matrix[0] * matrix[0] + // + matrix[1] * matrix[1] + // ); + // if (!$Number.isInteger(xScale)) { + // const value: string = xScale.toString(); + // const index: number = value.indexOf("e"); + // if (index !== -1) { + // xScale = +value.slice(0, index); + // } + // xScale = +xScale.toFixed(4); + // } + + // return 0 > matrix[0] ? xScale * -1 : xScale; + // } + // set scaleX (scale_x: number) + // { + // scale_x = $clamp(+scale_x, + // $SHORT_INT_MIN, $SHORT_INT_MAX + // ); + + // if (!$Number.isInteger(scale_x)) { + // const value: string = scale_x.toString(); + // const index: number = value.indexOf("e"); + // if (index !== -1) { + // scale_x = +value.slice(0, index); + // } + // scale_x = +scale_x.toFixed(4); + // } + + // if (this._$scaleX === scale_x) { + // return ; + // } + + // const transform: Transform = this._$transform; + + // const hasMatrix: boolean = transform._$matrix !== null; + + // const matrix: Matrix = hasMatrix + // ? transform._$matrix as NonNullable + // : transform.matrix; + + // if (matrix.b === 0 || $isNaN(matrix.b)) { + + // matrix.a = scale_x; + + // } else { + + // let radianX = $Math.atan2(matrix.b, matrix.a); + // if (radianX === -$Math.PI) { + // radianX = 0; + // } + + // matrix.b = scale_x * $Math.sin(radianX); + // matrix.a = scale_x * $Math.cos(radianX); + + // } + + // if (hasMatrix) { + // this._$doChanged(); + // $doUpdated(); + // } else { + // transform.matrix = matrix; + // $poolMatrix(matrix); + // } + + // this._$scaleX = scale_x; + // } + + // /** + // * @description 基準点から適用されるオブジェクトの垂直スケール(パーセンテージ)を示します。 + // * IIndicates the vertical scale (percentage) + // * of an object as applied from the registration point. + // * + // * @member {number} + // * @public + // */ + // get scaleY (): number + // { + // if (this._$scaleY !== null) { + // return this._$scaleY; + // } + + // const matrix: Float32Array = this._$transform._$rawMatrix(); + + // let yScale: number = $Math.sqrt( + // matrix[2] * matrix[2] + // + matrix[3] * matrix[3] + // ); + + // if (!$Number.isInteger(yScale)) { + // const value: string = yScale.toString(); + // const index: number = value.indexOf("e"); + // if (index !== -1) { + // yScale = +value.slice(0, index); + // } + // yScale = +yScale.toFixed(4); + // } + + // return 0 > matrix[3] ? yScale * -1 : yScale; + // } + // set scaleY (scale_y: number) + // { + // scale_y = $clamp(+scale_y, + // $SHORT_INT_MIN, $SHORT_INT_MAX + // ); + + // if (!$Number.isInteger(scale_y)) { + // const value: string = scale_y.toString(); + // const index: number = value.indexOf("e"); + // if (index !== -1) { + // scale_y = +value.slice(0, index); + // } + // scale_y = +scale_y.toFixed(4); + // } + + // if (this._$scaleY === scale_y) { + // return ; + // } + + // const transform: Transform = this._$transform; + + // const hasMatrix: boolean = transform._$matrix !== null; + + // const matrix: Matrix = hasMatrix + // ? transform._$matrix as NonNullable + // : transform.matrix; + + // if (matrix.c === 0 || $isNaN(matrix.c)) { + + // matrix.d = scale_y; + + // } else { + + // let radianY = $Math.atan2(-matrix.c, matrix.d); + // if (radianY === -$Math.PI) { + // radianY = 0; + // } + // matrix.c = -scale_y * $Math.sin(radianY); + // matrix.d = scale_y * $Math.cos(radianY); + + // } + + // if (hasMatrix) { + // this._$doChanged(); + // $doUpdated(); + // } else { + // transform.matrix = matrix; + // $poolMatrix(matrix); + // } + + // this._$scaleY = scale_y; + // } + + // /** + // * @description 表示オブジェクトのステージです。 + // * The Stage of the display object. + // * + // * @member {Stage} + // * @readonly + // * @public + // */ + // get stage (): Stage | null + // { + // if (this._$stage) { + // return this._$stage; + // } + + // // find parent + // const parent: ParentImpl | null = this._$parent; + // if (parent) { + // return parent._$stage; + // } + + // return null; + // } + + // /** + // * @description 表示オブジェクトのマトリックス、カラー変換、 + // * ピクセル境界に関係するプロパティを持つオブジェクトです。 + // * An object with properties pertaining + // * to a display object's matrix, color transform, and pixel bounds. + // * + // * @member {Transform} + // * @public + // */ + // get transform (): Transform + // { + // return this._$transform; + // } + // set transform (transform: Transform) + // { + // this._$transform = transform; + // } + + // /** + // * @description 表示オブジェクトが可視かどうかを示します。 + // * Whether or not the display object is visible. + // * + // * @member {boolean} + // * @public + // */ + // get visible (): boolean + // { + // return this._$visible; + // } + // set visible (visible: boolean) + // { + // if (this._$visible !== visible) { + // this._$visible = !!visible; + // this._$doChanged(); + // $doUpdated(); + // } + // } + + // /** + // * @description 表示オブジェクトの幅を示します(ピクセル単位)。 + // * Indicates the width of the display object, in pixels. + // * + // * @member {number} + // * @public + // */ + // get width (): number + // { + // const baseBounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" + // ? this._$getBounds() as BoundsImpl + // : $getBoundsObject(); + + // const bounds: BoundsImpl = $boundsMatrix( + // baseBounds, + // this._$transform._$rawMatrix() + // ); + + // $poolBoundsObject(baseBounds); + + // const width: number = $Math.abs(bounds.xMax - bounds.xMin); + // $poolBoundsObject(bounds); + + // switch (true) { + + // case width === 0: + // case width === $Infinity: + // case width === 0 - $Infinity: + // return 0; + + // default: + // return +width.toFixed(2); + + // } + // } + // set width (width: number) + // { + // width = +width; + // if (!$isNaN(width) && width > -1) { + + // const baseBounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" + // ? this._$getBounds() as BoundsImpl + // : $getBoundsObject(); + + // const rotation: number = this.rotation; + // const bounds = rotation + // ? $boundsMatrix(baseBounds, this._$transform._$rawMatrix()) + // : baseBounds; + + // if (rotation) { + // $poolBoundsObject(baseBounds); + // } + + // const exWidth = $Math.abs(bounds.xMax - bounds.xMin); + // $poolBoundsObject(bounds); + + // switch (true) { + + // case exWidth === 0: + // case exWidth === $Infinity: + // case exWidth === -$Infinity: + // this.scaleX = 0; + // break; + + // default: + // this.scaleX = width / exWidth; + // break; + + // } + // } + // } + + // /** + // * @description 親 DisplayObjectContainer のローカル座標を基準にした + // * DisplayObject インスタンスの x 座標を示します。 + // * Indicates the x coordinate + // * of the DisplayObject instance relative to the local coordinates + // * of the parent DisplayObjectContainer. + // * + // * @member {number} + // * @public + // */ + // get x (): number + // { + // return this._$transform._$rawMatrix()[4]; + // } + // set x (x: number) + // { + // const transform: Transform = this._$transform; + + // if (!transform._$matrix) { + // const matrix: Matrix = transform.matrix; + // matrix.tx = x; + // transform.matrix = matrix; + // $poolMatrix(matrix); + // } else { + // transform._$matrix.tx = x; + // this._$doChanged(); + // $doUpdated(); + // } + // } + + // /** + // * @description 親 DisplayObjectContainer のローカル座標を基準にした + // * DisplayObject インスタンスの y 座標を示します。 + // * Indicates the y coordinate + // * of the DisplayObject instance relative to the local coordinates + // * of the parent DisplayObjectContainer. + // * + // * @member {number} + // * @public + // */ + // get y (): number + // { + // return this._$transform._$rawMatrix()[5]; + // } + // set y (y: number) + // { + // const transform: Transform = this._$transform; + + // if (!transform._$matrix) { + // const matrix = transform.matrix; + // matrix.ty = y; + + // transform.matrix = matrix; + // $poolMatrix(matrix); + // } else { + // transform._$matrix.ty = y; + // this._$doChanged(); + // $doUpdated(); + // } + // } + + // /** + // * @description targetCoordinateSpace オブジェクトの座標系を基準にして、 + // * 表示オブジェクトの領域を定義する矩形を返します。 + // * Returns a rectangle that defines the area + // * of the display object relative to the coordinate system + // * of the targetCoordinateSpace object. + // * + // * @param {DisplayObject} [target=null] + // * @return {Rectangle} + // */ + // getBounds (target: DisplayObjectImpl | null = null): Rectangle + // { + // const baseBounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" + // ? this._$getBounds() as BoundsImpl + // : $getBoundsObject(); + + // const matrix: Matrix = this._$transform.concatenatedMatrix; + + // // to global + // const bounds: BoundsImpl = $boundsMatrix(baseBounds, matrix._$matrix); + + // // pool + // $poolMatrix(matrix); + // $poolBoundsObject(baseBounds); + + // // create bounds object + // const targetBaseBounds: BoundsImpl = $getBoundsObject( + // bounds.xMin, + // bounds.xMax, + // bounds.yMin, + // bounds.yMax + // ); + + // // pool + // $poolBoundsObject(bounds); + + // if (!target) { + // target = this; + // } + + // const targetMatrix: Matrix = target._$transform.concatenatedMatrix; + // targetMatrix.invert(); + + // const resultBounds: BoundsImpl = $boundsMatrix( + // targetBaseBounds, targetMatrix._$matrix + // ); + // $poolBoundsObject(targetBaseBounds); + // $poolMatrix(targetMatrix); + + // const xMin: number = resultBounds.xMin; + // const yMin: number = resultBounds.yMin; + // const xMax: number = resultBounds.xMax; + // const yMax: number = resultBounds.yMax; + + // // pool + // $poolBoundsObject(resultBounds); + + // return new Rectangle( + // xMin, yMin, + // $Math.abs(xMax - xMin), + // $Math.abs(yMax - yMin) + // ); + // } + + // /** + // * @description point オブジェクトをステージ(グローバル)座標から + // * 表示オブジェクトの(ローカル)座標に変換します。 + // * Converts the point object from the Stage (global) coordinates + // * to the display object's (local) coordinates. + // * + // * @param {Point} point + // * @return {Point} + // * @public + // */ + // globalToLocal (point: Point): Point + // { + // const matrix: Matrix = this._$transform.concatenatedMatrix; + // matrix.invert(); + + // const newPoint: Point = new Point( + // point.x * matrix.a + point.y * matrix.c + matrix.tx, + // point.x * matrix.b + point.y * matrix.d + matrix.ty + // ); + + // $poolMatrix(matrix); + + // return newPoint; + // } + + // /** + // * @description 表示オブジェクトの境界ボックスを評価して、 + // * obj 表示オブジェクトの境界ボックスと重複または交差するかどうかを調べます。 + // * Evaluates the bounding box of the display object to see + // * if it overlaps or intersects with the bounding box of the obj display object. + // * + // * @param {DisplayObject} object + // * @returns {boolean} + // * @public + // */ + // hitTestObject (object: DisplayObjectImpl): boolean + // { + // const baseBounds1: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" + // ? this._$getBounds() as BoundsImpl + // : $getBoundsObject(); + + // const matrix1: Matrix = this._$transform.concatenatedMatrix; + // const bounds1: BoundsImpl = $boundsMatrix(baseBounds1, matrix1._$matrix); + + // // pool + // $poolMatrix(matrix1); + // $poolBoundsObject(baseBounds1); + + // const baseBounds2: BoundsImpl = object._$getBounds(null); + // const matrix2: Matrix = object._$transform.concatenatedMatrix; + // const bounds2: BoundsImpl = $boundsMatrix(baseBounds2, matrix2._$matrix); + + // // pool + // $poolMatrix(matrix2); + // $poolBoundsObject(baseBounds2); + + // // calc + // const sx: number = $Math.max(bounds1.xMin, bounds2.xMin); + // const sy: number = $Math.max(bounds1.yMin, bounds2.yMin); + // const ex: number = $Math.min(bounds1.xMax, bounds2.xMax); + // const ey: number = $Math.min(bounds1.yMax, bounds2.yMax); + + // // pool + // $poolBoundsObject(bounds1); + // $poolBoundsObject(bounds2); + + // return ex - sx >= 0 && ey - sy >= 0; + // } + + // /** + // * @description 表示オブジェクトを評価して、x および y パラメーターで指定された + // * ポイントと重複または交差するかどうかを調べます。 + // * Evaluates the display object to see if it overlaps + // * or intersects with the point specified by the x and y parameters. + // * + // * @param {number} x + // * @param {number} y + // * @param {boolean} [shape_flag=false] + // * @returns {boolean} + // * @public + // */ + // hitTestPoint ( + // x: number, y: number, + // shape_flag: boolean = false + // ): boolean { + + // if (shape_flag) { + + // let matrix: Float32Array = $MATRIX_ARRAY_IDENTITY; + + // let parent: ParentImpl | null = this._$parent; + // while (parent) { + + // matrix = $multiplicationMatrix( + // parent._$transform._$rawMatrix(), + // matrix + // ); + + // parent = parent._$parent; + // } + + // $hitContext.setTransform(1, 0, 0, 1, 0, 0); + // $hitContext.beginPath(); + + // let result: boolean = false; + // if ("_$hit" in this && typeof this._$hit === "function") { + // result = this._$hit($hitContext, matrix, { "x": x, "y": y }, true); + // } + + // if (matrix !== $MATRIX_ARRAY_IDENTITY) { + // $poolFloat32Array6(matrix); + // } + + // return result; + // } + + // const baseBounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" + // ? this._$getBounds() as BoundsImpl + // : $getBoundsObject(); + + // const bounds: BoundsImpl = $boundsMatrix(baseBounds, this._$transform._$rawMatrix()); + // $poolBoundsObject(baseBounds); + + // const rectangle: Rectangle = new Rectangle( + // bounds.xMin, bounds.yMin, + // bounds.xMax - bounds.xMin, + // bounds.yMax - bounds.yMin + // ); + + // // pool + // $poolBoundsObject(bounds); + + // const point: Point = this._$parent + // ? this._$parent.globalToLocal(new Point(x, y)) + // : new Point(x, y); + + // return rectangle.containsPoint(point); + // } + + // /** + // * @description point オブジェクトを表示オブジェクトの(ローカル)座標から + // * ステージ(グローバル)座標に変換します。 + // * Converts the point object from the display object's (local) coordinates + // * to the Stage (global) coordinates. + // * + // * + // * @param {Point} point + // * @returns {Point} + // * @public + // */ + // localToGlobal (point: Point): Point + // { + // const matrix: Matrix = this + // ._$transform + // .concatenatedMatrix; + + // const newPoint: Point = new Point( + // point.x * matrix.a + point.y * matrix.c + matrix.tx, + // point.x * matrix.b + point.y * matrix.d + matrix.ty + // ); + + // $poolMatrix(matrix); + + // return newPoint; + // } + + // /** + // * @description クラスのローカル変数空間から値を取得 + // * Get a value from the local variable space of the class + // * + // * @param {*} key + // * @return {*} + // * @method + // * @public + // */ + // getLocalVariable (key: any): any + // { + // if (!this._$variables) { + // return null; + // } + + // if (this._$variables.has(key)) { + // return this._$variables.get(key); + // } + // } + + // /** + // * @description クラスのローカル変数空間へ値を保存 + // * Store values in the local variable space of the class + // * + // * @param {*} key + // * @param {*} value + // * @return {void} + // * @method + // * @public + // */ + // setLocalVariable (key: any, value: any): void + // { + // if (!this._$variables) { + // this._$variables = $getMap(); + // } + // this._$variables.set(key, value); + // } + + // /** + // * @description クラスのローカル変数空間に値があるかどうかを判断します。 + // * Determines if there is a value in the local variable space of the class. + // * + // * @param {*} key + // * @return {boolean} + // * @method + // * @public + // */ + // hasLocalVariable (key: any): boolean + // { + // return this._$variables + // ? this._$variables.has(key) + // : false; + // } + + // /** + // * @description クラスのローカル変数空間の値を削除 + // * Remove values from the local variable space of a class + // * + // * @param {*} key + // * @return {void} + // * @method + // * @public + // */ + // deleteLocalVariable (key: any): void + // { + // if (this._$variables && this._$variables.has(key)) { + // this._$variables.delete(key); + // if (!this._$variables.size) { + // $poolMap(this._$variables); + // this._$variables = null; + // } + // } + // } + + // /** + // * @description グローバル変数空間から値を取得 + // * Get a value from the global variable space + // * + // * @param {*} key + // * @return {*} + // * @method + // * @public + // */ + // getGlobalVariable (key: any): any + // { + // if ($variables.has(key)) { + // return $variables.get(key); + // } + // return null; + // } + + // /** + // * @description グローバル変数空間へ値を保存 + // * Save values to global variable space + // * + // * @param {*} key + // * @param {*} value + // * @return {void} + // * @method + // * @public + // */ + // setGlobalVariable (key: any, value: any): void + // { + // $variables.set(key, value); + // } + + // /** + // * @description グローバル変数空間に値があるかどうかを判断します。 + // * Determines if there is a value in the global variable space. + // * + // * @param {*} key + // * @return {boolean} + // * @method + // * @public + // */ + // hasGlobalVariable (key: any): boolean + // { + // return $variables.has(key); + // } + + // /** + // * @description グローバル変数空間の値を削除 + // * Remove values from global variable space. + // * + // * @param {*} key + // * @return {void} + // * @method + // * @public + // */ + // deleteGlobalVariable (key: any): void + // { + // if ($variables.has(key)) { + // $variables.delete(key); + // } + // } + + // /** + // * @description グローバル変数空間に値を全てクリアします。 + // * Clear all values in the global variable space. + // * + // * @return {void} + // * @method + // * @public + // */ + // clearGlobalVariable (): void + // { + // return $variables.clear(); + // } + + // /** + // * @return {object} + // * @method + // * @private + // */ + // _$getPlaceObject (): PlaceObjectImpl | null + // { + // if (!this._$placeObject) { + + // const placeId = this._$placeId; + // if (placeId === -1) { + // return null; + // } + + // const parent: ParentImpl | null = this._$parent; + // if (!parent || !parent._$placeObjects) { + // return null; + // } + + // const placeMap: Array> | null = parent._$placeMap; + // if (!placeMap || !placeMap.length) { + // return null; + // } + + // const frame: number = "currentFrame" in parent ? parent.currentFrame : 1; + // const places: number[] | void = placeMap[frame]; + // if (!places) { + // return null; + // } + + // const currentPlaceId: number = places[placeId] | 0; + // const placeObject: PlaceObjectImpl | void = parent._$placeObjects[currentPlaceId]; + // if (!placeObject) { + // return null; + // } + + // this._$changePlace = currentPlaceId !== this._$currentPlaceId; + // this._$currentPlaceId = currentPlaceId; + // this._$placeObject = placeObject; + + // return placeObject; + // } + + // return this._$placeObject; + // } + + // /** + // * @param {object} tag + // * @param {DisplayObjectContainer} parent + // * @return {object} + // * @method + // * @private + // */ + // _$baseBuild ( + // tag: DictionaryTagImpl, + // parent: ParentImpl + // ): T { + + // const loaderInfo: LoaderInfo | null = parent._$loaderInfo; + // if (!loaderInfo || !loaderInfo._$data) { + // throw new Error("the loaderInfo or data is nul."); + // } + + // // setup + // this._$parent = parent; + // this._$root = parent._$root; + // this._$stage = parent._$stage; + // this._$loaderInfo = loaderInfo; + + // // bind tag data + // this._$characterId = tag.characterId | 0; + // this._$clipDepth = tag.clipDepth | 0; + // this._$startFrame = tag.startFrame | 0; + // this._$endFrame = tag.endFrame | 0; + // this._$name = tag.name || ""; + + // return loaderInfo._$data.characters[tag.characterId]; + // } + + // /** + // * @return {boolean} + // * @method + // * @private + // */ + // _$isUpdated (): boolean + // { + // return this._$updated; + // } + + // /** + // * @return {void} + // * @method + // * @private + // */ + // _$updateState (): void + // { + // this._$isNext = true; + + // const parent: ParentImpl | null = this._$parent; + // if (parent) { + // parent._$updateState(); + // } + // } + + // /** + // * @return {void} + // * @method + // * @private + // */ + // _$doChanged (): void + // { + // this._$posted = false; + // this._$isNext = true; + // this._$updated = true; + + // const parent: ParentImpl | null = this._$parent; + // if (parent) { + // if (!parent._$updated) { + // parent._$doChanged(); + // } + // } + // } + + // /** + // * @param {CanvasToWebGLContext} context + // * @param {Float32Array} matrix + // * @param {array} filters + // * @param {number} width + // * @param {number} height + // * @param {WebGLTexture} [target_texture = null] + // * @return {object} + // * @method + // * @private + // */ + // _$drawFilter ( + // context: CanvasToWebGLContext, + // matrix: Float32Array, + // filters: FilterArrayImpl, + // width: number, + // height: number, + // target_texture: WebGLTexture | null = null + // ): CachePositionImpl { + + // const cacheKeys: any[] = $getArray(this._$instanceId, "f"); + // let position: CachePositionImpl | void = $cacheStore.get(cacheKeys); + + // const updated: boolean = this._$isFilterUpdated(matrix, filters, true); + + // if (position && !updated) { + // context.cachePosition = position; + // return position; + // } + + // // cache clear + // if (position) { + // $cacheStore.set(cacheKeys, null); + // } + + // const manager: FrameBufferManager = context.frameBuffer; + // const targetTexture: WebGLTexture = target_texture + // ? target_texture + // : context.getTextureFromRect( + // context.cachePosition as NonNullable + // ); + + // const texture: WebGLTexture = this._$applyFilter( + // context, filters, targetTexture, + // matrix, width, height + // ); + // manager.textureManager.release(targetTexture); + + // const bounds: BoundsImpl = this._$getLayerBounds(matrix); + // position = manager.createCachePosition( + // $Math.ceil($Math.abs(bounds.xMax - bounds.xMin)), + // $Math.ceil($Math.abs(bounds.yMax - bounds.yMin)) + // ); + // $poolBoundsObject(bounds); + + // position.filterState = true; + // position.matrix = `${matrix[0]}_${matrix[1]}_${matrix[2]}_${matrix[3]}_0_0`; + // position.offsetX = texture.offsetX; + // position.offsetY = texture.offsetY; + + // // 関数先でtextureがreleaseされる + // context.drawTextureFromRect(texture, position); + + // $cacheStore.set(cacheKeys, position); + // $poolArray(cacheKeys); + + // return position; + // } + + // /** + // * @param {Float32Array} multi_matrix + // * @returns {object} + // * @private + // */ + // _$getLayerBounds (multi_matrix: Float32Array): BoundsImpl + // { + // const baseBounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" + // ? this._$getBounds() as BoundsImpl + // : $getBoundsObject(); + + // const bounds: BoundsImpl = $boundsMatrix(baseBounds, multi_matrix); + // $poolBoundsObject(baseBounds); + + // const filters: FilterArrayImpl = this._$filters || this.filters; + // if (!filters.length) { + // return bounds; + // } + + // let filterBounds: BoundsImpl = $getBoundsObject( + // 0, + // $Math.abs(bounds.xMax - bounds.xMin), + // 0, + // $Math.abs(bounds.yMax - bounds.yMin) + // ); + // $poolBoundsObject(bounds); + + // let xScale: number = +$Math.sqrt( + // multi_matrix[0] * multi_matrix[0] + // + multi_matrix[1] * multi_matrix[1] + // ); + // let yScale: number = +$Math.sqrt( + // multi_matrix[2] * multi_matrix[2] + // + multi_matrix[3] * multi_matrix[3] + // ); + + // xScale /= $devicePixelRatio; + // yScale /= $devicePixelRatio; + + // xScale *= 2; + // yScale *= 2; + + // for (let idx: number = 0; idx < filters.length; ++idx) { + // filterBounds = filters[idx] + // ._$generateFilterRect(filterBounds, xScale, yScale); + // } + + // return filterBounds; + // } + + // /** + // * @return {void} + // * @method + // * @private + // */ + // _$executeAddedEvent (): void + // { + // if (!this._$parent) { + // return ; + // } + + // // add event + // if (!this._$added) { + + // // added event + // if (this.willTrigger(Next2DEvent.ADDED)) { + // this.dispatchEvent(new Next2DEvent(Next2DEvent.ADDED, true)); + // } + + // // update + // this._$added = true; + // } + + // if (!this._$addedStage && this._$stage !== null) { + + // if (this.willTrigger(Next2DEvent.ADDED_TO_STAGE)) { + // this.dispatchEvent(new Next2DEvent(Next2DEvent.ADDED_TO_STAGE)); + // } + + // // update + // this._$addedStage = true; + // } + // } + + // /** + // * @return {void} + // * @method + // * @private + // */ + // _$prepareActions (): void + // { + // this._$nextFrame(); + // } + + // /** + // * @return {boolean} + // * @method + // * @private + // */ + // _$nextFrame (): boolean + // { + // // added event + // this._$executeAddedEvent(); + + // this._$isNext = false; + + // if (!this._$posted && $rendererWorker) { + // // @ts-ignore + // this._$postProperty(); + // } + + // return false; + // } + + // /** + // * @param {array} [filters=null] + // * @return {boolean} + // * @private + // */ + // _$canApply (filters: FilterArrayImpl | null = null): boolean + // { + // if (filters) { + // for (let idx: number = 0; idx < filters.length; ++idx) { + // if (filters[idx]._$canApply()) { + // return true; + // } + // } + // } + // return false; + // } + + // /** + // * @param {Float32Array} matrix + // * @param {array} [filters=null] + // * @param {boolean} [can_apply=false] + // * @param {number} [position_x=0] + // * @param {number} [position_y=0] + // * @return {boolean} + // * @private + // */ + // _$isFilterUpdated ( + // matrix: Float32Array, + // filters: FilterArrayImpl | null = null, + // can_apply: boolean = false + // ): boolean { + + // // cache flag + // if (this._$isUpdated()) { + // return true; + // } + + // // check filter data + // if (can_apply && filters) { + + // for (let idx: number = 0; idx < filters.length; ++idx) { + + // if (!filters[idx]._$isUpdated()) { + // continue; + // } + + // return true; + // } + + // } + + // // check status + // const cache: CachePositionImpl = $cacheStore.get([this._$instanceId, "f"]); + // if (!cache) { + // return true; + // } + + // if (cache.filterState !== can_apply) { + // return true; + // } + + // if (cache.matrix !== `${matrix[0]}_${matrix[1]}_${matrix[2]}_${matrix[3]}`) { + // return true; + // } + + // return false; + // } + + // /** + // * @param {CanvasToWebGLContext} context + // * @param {array} filters + // * @param {WebGLTexture} target_texture + // * @param {Float32Array} matrix + // * @param {number} width + // * @param {number} height + // * @return {WebGLTexture} + // * @private + // */ + // _$applyFilter ( + // context: CanvasToWebGLContext, + // filters: FilterArrayImpl, + // target_texture: WebGLTexture, + // matrix: Float32Array, + // width: number, + // height: number + // ): WebGLTexture { + + // const xScale: number = +$Math.sqrt( + // matrix[0] * matrix[0] + // + matrix[1] * matrix[1] + // ); + // const yScale: number = +$Math.sqrt( + // matrix[2] * matrix[2] + // + matrix[3] * matrix[3] + // ); + + // const radianX: number = $Math.atan2(matrix[1], matrix[0]); + // const radianY: number = $Math.atan2(-matrix[2], matrix[3]); + + // const parentMatrix: Float32Array = $getFloat32Array6( + // $Math.cos(radianX), $Math.sin(radianX), + // -$Math.sin(radianY), $Math.cos(radianY), + // width / 2, height / 2 + // ); + + // const baseMatrix: Float32Array = $getFloat32Array6( + // 1, 0, 0, 1, + // -target_texture.width / 2, + // -target_texture.height / 2 + // ); + + // const multiMatrix: Float32Array = $multiplicationMatrix( + // parentMatrix, baseMatrix + // ); + // $poolFloat32Array6(parentMatrix); + // $poolFloat32Array6(baseMatrix); + + // const manager: FrameBufferManager = context.frameBuffer; + // const currentAttachment: AttachmentImpl | null = manager.currentAttachment; + + // const attachment: AttachmentImpl = manager + // .createCacheAttachment(width, height); + // context._$bind(attachment); + + // context.reset(); + // context.setTransform( + // multiMatrix[0], multiMatrix[1], + // multiMatrix[2], multiMatrix[3], + // multiMatrix[4], multiMatrix[5] + // ); + // $poolFloat32Array6(multiMatrix); + + // context.drawImage(target_texture, + // 0, 0, target_texture.width, target_texture.height + // ); + + // // init + // context._$offsetX = 0; + // context._$offsetY = 0; + + // const filterMatrix: Float32Array = $getFloat32Array6( + // xScale, 0, 0, yScale, 0, 0 + // ); + + // let texture: WebGLTexture | null = null; + // for (let idx: number = 0; idx < filters.length; ++idx) { + // texture = filters[idx]._$applyFilter(context, filterMatrix); + // } + + // $poolFloat32Array6(filterMatrix); + + // if (!texture) { + // return target_texture; + // } + + // const offsetX: number = context._$offsetX; + // const offsetY: number = context._$offsetY; + + // // reset + // context._$offsetX = 0; + // context._$offsetY = 0; + + // // set offset + // texture.offsetX = offsetX; + // texture.offsetY = offsetY; + + // context._$bind(currentAttachment); + // manager.releaseAttachment(attachment, false); + + // return texture; + // } + + // /** + // * @param {Float32Array} matrix + // * @return {boolean} + // * @method + // * @private + // */ + // _$shouldClip (matrix: Float32Array): boolean + // { + // const bounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" + // ? this._$getBounds(matrix) as BoundsImpl + // : $getBoundsObject(); + + // const width = $Math.abs(bounds.xMax - bounds.xMin); + // const height = $Math.abs(bounds.yMax - bounds.yMin); + // $poolBoundsObject(bounds); + + // // size 0 + // return !(!width || !height); + // } + + // /** + // * @param {CanvasToWebGLContext} context + // * @param {Float32Array} matrix + // * @return {boolean} + // * @method + // * @private + // */ + // _$startClip ( + // context: CanvasToWebGLContext, + // matrix: Float32Array + // ): boolean { + + // context.drawInstacedArray(); + + // // マスクの描画反映を限定 + // const bounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" + // ? this._$getBounds(matrix) as BoundsImpl + // : $getBoundsObject(); + + // const result = context._$startClip(bounds); + // $poolBoundsObject(bounds); + + // if (!result) { + // return false; + // } + + // // start clip + // context._$enterClip(); + + // // mask start + // context._$beginClipDef(); + + // let containerClip = false; + // if ("_$children" in this) { + // containerClip = true; + // context._$updateContainerClipFlag(true); + // } + + // // @ts-ignore + // this._$clip(context, matrix); + // this._$updated = false; + + // // container clip + // if (containerClip) { + + // // update flag + // context._$updateContainerClipFlag(false); + + // // execute clip + // context._$drawContainerClip(); + // } + + // // mask end + // context._$endClipDef(); + + // return true; + // } + + // /** + // * @return {void} + // * @method + // * @private + // */ + // _$removeWorkerInstance (): void + // { + // if ($rendererWorker) { + // $rendererWorker.postMessage({ + // "command": "remove", + // "instanceId": this._$instanceId + // }); + // } + // } + + // /** + // * @param {Float32Array} buffer + // * @param {number} [index = 0] + // * @return {void} + // * @method + // * @private + // */ + // _$registerProperty (buffer: Float32Array, index: number = 0): void + // { + // // visible + // buffer[index++] = +this._$visible; + + // // depth + // buffer[index++] = this._$placeId; + + // // clip depth + // buffer[index++] = this._$clipDepth; + + // // isMask + // buffer[index++] = +this._$isMask; + + // const mask: DisplayObjectImpl | null = this._$mask; + // buffer[index++] = +(mask !== null); + // if (mask) { + + // // mask id + // buffer[index++] = mask._$instanceId; + + // let maskMatrix: Float32Array = $MATRIX_ARRAY_IDENTITY; + // let parent: ParentImpl | null = mask._$parent; + // while (parent) { + + // maskMatrix = $multiplicationMatrix( + // parent._$transform._$rawMatrix(), + // maskMatrix + // ); + + // parent = parent._$parent; + // } + + // // mask matrix + // buffer[index++] = maskMatrix[0]; + // buffer[index++] = maskMatrix[1]; + // buffer[index++] = maskMatrix[2]; + // buffer[index++] = maskMatrix[3]; + // buffer[index++] = maskMatrix[4]; + // buffer[index++] = maskMatrix[5]; + // } else { + // index += 7; + // } + + // if (this._$visible) { + // const transform: Transform = this._$transform; + + // // matrix + // const matrix: Float32Array = transform._$rawMatrix(); + // buffer[index++] = matrix[0]; + // buffer[index++] = matrix[1]; + // buffer[index++] = matrix[2]; + // buffer[index++] = matrix[3]; + // buffer[index++] = matrix[4]; + // buffer[index++] = matrix[5]; + + // // colorTransform + // const colorTransform = transform._$rawColorTransform(); + // buffer[index++] = colorTransform[0]; + // buffer[index++] = colorTransform[1]; + // buffer[index++] = colorTransform[2]; + // buffer[index++] = colorTransform[3]; + // buffer[index++] = colorTransform[4]; + // buffer[index++] = colorTransform[5]; + // buffer[index++] = colorTransform[6]; + // buffer[index++] = colorTransform[7]; + + // } else { + // index += 6; // matrix + // index += 8; // colorTransform + // } + + // // blend mode + // const blendMode: BlendModeImpl = this._$blendMode || this.blendMode; + // buffer[index++] = $blendToNumber(blendMode); + + // // scale9Grid + // const scale9Grid: Rectangle | null = this._$scale9Grid; + // buffer[index++] = +(scale9Grid !== null); + + // if (scale9Grid) { + // buffer[index++] = scale9Grid.x; + // buffer[index++] = scale9Grid.y; + // buffer[index++] = scale9Grid.width; + // buffer[index++] = scale9Grid.height; + // } else { + // index += 4; + // } + + // // filter + // } + + // /** + // * @return {object} + // * @method + // * @private + // */ + // _$createMessage (): PropertyMessageMapImpl + // { + // const message: PropertyMessageImpl = { + // "command": "setProperty", + // "buffer": new Float32Array(), + // "instanceId": this._$instanceId, + // "parentId": this._$parent ? this._$parent._$instanceId : -1, + // "visible": this._$visible + // }; + + // if (this._$placeId > -1) { + // message.depth = this._$placeId; + // } + + // if (this._$clipDepth) { + // message.clipDepth = this._$clipDepth; + // } + + // if (this._$isMask) { + // message.isMask = this._$isMask; + // } + + // const mask: DisplayObjectImpl | null = this._$mask; + // if (mask) { + // message.maskId = mask._$instanceId; + + // let maskMatrix: Float32Array = $MATRIX_ARRAY_IDENTITY; + // let parent: ParentImpl | null = mask._$parent; + // while (parent) { + + // maskMatrix = $multiplicationMatrix( + // parent._$transform._$rawMatrix(), + // maskMatrix + // ); + + // parent = parent._$parent; + // } + + // message.maskMatrix = maskMatrix; + // } + + // if (this._$visible) { + + // const transform: Transform = this._$transform; + + // const matrix: Float32Array = transform._$rawMatrix(); + // if (matrix[0] !== 1) { + // message.a = matrix[0]; + // } + + // if (matrix[1] !== 0) { + // message.b = matrix[1]; + // } + + // if (matrix[2] !== 0) { + // message.c = matrix[2]; + // } + + // if (matrix[3] !== 1) { + // message.d = matrix[3]; + // } + + // if (matrix[4] !== 0) { + // message.tx = matrix[4]; + // } + + // if (matrix[5] !== 0) { + // message.ty = matrix[5]; + // } + + // const colorTransform = transform._$rawColorTransform(); + // if (colorTransform[0] !== 1) { + // message.f0 = colorTransform[0]; + // } + + // if (colorTransform[1] !== 1) { + // message.f1 = colorTransform[1]; + // } + + // if (colorTransform[2] !== 1) { + // message.f2 = colorTransform[2]; + // } + + // if (colorTransform[3] !== 1) { + // message.f3 = colorTransform[3]; + // } + + // if (colorTransform[4] !== 0) { + // message.f4 = colorTransform[4]; + // } + + // if (colorTransform[5] !== 0) { + // message.f5 = colorTransform[5]; + // } + + // if (colorTransform[6] !== 0) { + // message.f6 = colorTransform[6]; + // } + + // if (colorTransform[7] !== 0) { + // message.f7 = colorTransform[7]; + // } + + // const filters: FilterArrayImpl | null = this._$filters || this.filters; + // if (filters && filters.length) { + // const parameters: any[] = $getArray(); + // for (let idx: number = 0; idx < filters.length; ++idx) { + // parameters.push(filters[idx]._$toArray()); + // } - matrix.d = scale_y; + // message.filters = parameters; + // } + + // const blendMode: BlendModeImpl = this._$blendMode || this.blendMode; + // if (blendMode !== "normal") { + // message.blendMode = blendMode; + // } - } else { - - let radianY = $Math.atan2(-matrix.c, matrix.d); - if (radianY === -$Math.PI) { - radianY = 0; - } - matrix.c = -scale_y * $Math.sin(radianY); - matrix.d = scale_y * $Math.cos(radianY); - - } + // const scale9Grid: Rectangle | null = this._$scale9Grid; + // if (scale9Grid && this._$isUpdated()) { + + // const baseMatrix: Matrix = this + // ._$parent + // ._$transform + // .concatenatedMatrix; - if (hasMatrix) { - this._$doChanged(); - $doUpdated(); - } else { - transform.matrix = matrix; - $poolMatrix(matrix); - } + // message.matrixBase = baseMatrix._$matrix.slice(); + // $poolMatrix(baseMatrix); + + // message.grid = { + // "x": scale9Grid.x, + // "y": scale9Grid.y, + // "w": scale9Grid.width, + // "h": scale9Grid.height + // }; + // } + // } - this._$scaleY = scale_y; - } - - /** - * @description 表示オブジェクトのステージです。 - * The Stage of the display object. - * - * @member {Stage} - * @readonly - * @public - */ - get stage (): Stage | null - { - if (this._$stage) { - return this._$stage; - } - - // find parent - const parent: ParentImpl | null = this._$parent; - if (parent) { - return parent._$stage; - } - - return null; - } - - /** - * @description 表示オブジェクトのマトリックス、カラー変換、 - * ピクセル境界に関係するプロパティを持つオブジェクトです。 - * An object with properties pertaining - * to a display object's matrix, color transform, and pixel bounds. - * - * @member {Transform} - * @public - */ - get transform (): Transform - { - return this._$transform; - } - set transform (transform: Transform) - { - this._$transform = transform; - } - - /** - * @description 表示オブジェクトが可視かどうかを示します。 - * Whether or not the display object is visible. - * - * @member {boolean} - * @public - */ - get visible (): boolean - { - return this._$visible; - } - set visible (visible: boolean) - { - if (this._$visible !== visible) { - this._$visible = !!visible; - this._$doChanged(); - $doUpdated(); - } - } - - /** - * @description 表示オブジェクトの幅を示します(ピクセル単位)。 - * Indicates the width of the display object, in pixels. - * - * @member {number} - * @public - */ - get width (): number - { - const baseBounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" - ? this._$getBounds() as BoundsImpl - : $getBoundsObject(); - - const bounds: BoundsImpl = $boundsMatrix( - baseBounds, - this._$transform._$rawMatrix() - ); - - $poolBoundsObject(baseBounds); - - const width: number = $Math.abs(bounds.xMax - bounds.xMin); - $poolBoundsObject(bounds); - - switch (true) { - - case width === 0: - case width === $Infinity: - case width === 0 - $Infinity: - return 0; - - default: - return +width.toFixed(2); - - } - } - set width (width: number) - { - width = +width; - if (!$isNaN(width) && width > -1) { - - const baseBounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" - ? this._$getBounds() as BoundsImpl - : $getBoundsObject(); - - const rotation: number = this.rotation; - const bounds = rotation - ? $boundsMatrix(baseBounds, this._$transform._$rawMatrix()) - : baseBounds; - - if (rotation) { - $poolBoundsObject(baseBounds); - } - - const exWidth = $Math.abs(bounds.xMax - bounds.xMin); - $poolBoundsObject(bounds); - - switch (true) { - - case exWidth === 0: - case exWidth === $Infinity: - case exWidth === -$Infinity: - this.scaleX = 0; - break; - - default: - this.scaleX = width / exWidth; - break; - - } - } - } - - /** - * @description 親 DisplayObjectContainer のローカル座標を基準にした - * DisplayObject インスタンスの x 座標を示します。 - * Indicates the x coordinate - * of the DisplayObject instance relative to the local coordinates - * of the parent DisplayObjectContainer. - * - * @member {number} - * @public - */ - get x (): number - { - return this._$transform._$rawMatrix()[4]; - } - set x (x: number) - { - const transform: Transform = this._$transform; - - if (!transform._$matrix) { - const matrix: Matrix = transform.matrix; - matrix.tx = x; - transform.matrix = matrix; - $poolMatrix(matrix); - } else { - transform._$matrix.tx = x; - this._$doChanged(); - $doUpdated(); - } - } - - /** - * @description 親 DisplayObjectContainer のローカル座標を基準にした - * DisplayObject インスタンスの y 座標を示します。 - * Indicates the y coordinate - * of the DisplayObject instance relative to the local coordinates - * of the parent DisplayObjectContainer. - * - * @member {number} - * @public - */ - get y (): number - { - return this._$transform._$rawMatrix()[5]; - } - set y (y: number) - { - const transform: Transform = this._$transform; - - if (!transform._$matrix) { - const matrix = transform.matrix; - matrix.ty = y; - - transform.matrix = matrix; - $poolMatrix(matrix); - } else { - transform._$matrix.ty = y; - this._$doChanged(); - $doUpdated(); - } - } - - /** - * @description targetCoordinateSpace オブジェクトの座標系を基準にして、 - * 表示オブジェクトの領域を定義する矩形を返します。 - * Returns a rectangle that defines the area - * of the display object relative to the coordinate system - * of the targetCoordinateSpace object. - * - * @param {DisplayObject} [target=null] - * @return {Rectangle} - */ - getBounds (target: DisplayObjectImpl | null = null): Rectangle - { - const baseBounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" - ? this._$getBounds() as BoundsImpl - : $getBoundsObject(); - - const matrix: Matrix = this._$transform.concatenatedMatrix; - - // to global - const bounds: BoundsImpl = $boundsMatrix(baseBounds, matrix._$matrix); - - // pool - $poolMatrix(matrix); - $poolBoundsObject(baseBounds); - - // create bounds object - const targetBaseBounds: BoundsImpl = $getBoundsObject( - bounds.xMin, - bounds.xMax, - bounds.yMin, - bounds.yMax - ); - - // pool - $poolBoundsObject(bounds); - - if (!target) { - target = this; - } - - const targetMatrix: Matrix = target._$transform.concatenatedMatrix; - targetMatrix.invert(); - - const resultBounds: BoundsImpl = $boundsMatrix( - targetBaseBounds, targetMatrix._$matrix - ); - $poolBoundsObject(targetBaseBounds); - $poolMatrix(targetMatrix); - - const xMin: number = resultBounds.xMin; - const yMin: number = resultBounds.yMin; - const xMax: number = resultBounds.xMax; - const yMax: number = resultBounds.yMax; - - // pool - $poolBoundsObject(resultBounds); - - return new Rectangle( - xMin, yMin, - $Math.abs(xMax - xMin), - $Math.abs(yMax - yMin) - ); - } - - /** - * @description point オブジェクトをステージ(グローバル)座標から - * 表示オブジェクトの(ローカル)座標に変換します。 - * Converts the point object from the Stage (global) coordinates - * to the display object's (local) coordinates. - * - * @param {Point} point - * @return {Point} - * @public - */ - globalToLocal (point: Point): Point - { - const matrix: Matrix = this._$transform.concatenatedMatrix; - matrix.invert(); - - const newPoint: Point = new Point( - point.x * matrix.a + point.y * matrix.c + matrix.tx, - point.x * matrix.b + point.y * matrix.d + matrix.ty - ); - - $poolMatrix(matrix); - - return newPoint; - } - - /** - * @description 表示オブジェクトの境界ボックスを評価して、 - * obj 表示オブジェクトの境界ボックスと重複または交差するかどうかを調べます。 - * Evaluates the bounding box of the display object to see - * if it overlaps or intersects with the bounding box of the obj display object. - * - * @param {DisplayObject} object - * @returns {boolean} - * @public - */ - hitTestObject (object: DisplayObjectImpl): boolean - { - const baseBounds1: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" - ? this._$getBounds() as BoundsImpl - : $getBoundsObject(); - - const matrix1: Matrix = this._$transform.concatenatedMatrix; - const bounds1: BoundsImpl = $boundsMatrix(baseBounds1, matrix1._$matrix); - - // pool - $poolMatrix(matrix1); - $poolBoundsObject(baseBounds1); - - const baseBounds2: BoundsImpl = object._$getBounds(null); - const matrix2: Matrix = object._$transform.concatenatedMatrix; - const bounds2: BoundsImpl = $boundsMatrix(baseBounds2, matrix2._$matrix); - - // pool - $poolMatrix(matrix2); - $poolBoundsObject(baseBounds2); - - // calc - const sx: number = $Math.max(bounds1.xMin, bounds2.xMin); - const sy: number = $Math.max(bounds1.yMin, bounds2.yMin); - const ex: number = $Math.min(bounds1.xMax, bounds2.xMax); - const ey: number = $Math.min(bounds1.yMax, bounds2.yMax); - - // pool - $poolBoundsObject(bounds1); - $poolBoundsObject(bounds2); - - return ex - sx >= 0 && ey - sy >= 0; - } - - /** - * @description 表示オブジェクトを評価して、x および y パラメーターで指定された - * ポイントと重複または交差するかどうかを調べます。 - * Evaluates the display object to see if it overlaps - * or intersects with the point specified by the x and y parameters. - * - * @param {number} x - * @param {number} y - * @param {boolean} [shape_flag=false] - * @returns {boolean} - * @public - */ - hitTestPoint ( - x: number, y: number, - shape_flag: boolean = false - ): boolean { - - if (shape_flag) { - - let matrix: Float32Array = $MATRIX_ARRAY_IDENTITY; - - let parent: ParentImpl | null = this._$parent; - while (parent) { - - matrix = $multiplicationMatrix( - parent._$transform._$rawMatrix(), - matrix - ); - - parent = parent._$parent; - } - - $hitContext.setTransform(1, 0, 0, 1, 0, 0); - $hitContext.beginPath(); - - let result: boolean = false; - if ("_$hit" in this && typeof this._$hit === "function") { - result = this._$hit($hitContext, matrix, { "x": x, "y": y }, true); - } - - if (matrix !== $MATRIX_ARRAY_IDENTITY) { - $poolFloat32Array6(matrix); - } - - return result; - } - - const baseBounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" - ? this._$getBounds() as BoundsImpl - : $getBoundsObject(); - - const bounds: BoundsImpl = $boundsMatrix(baseBounds, this._$transform._$rawMatrix()); - $poolBoundsObject(baseBounds); - - const rectangle: Rectangle = new Rectangle( - bounds.xMin, bounds.yMin, - bounds.xMax - bounds.xMin, - bounds.yMax - bounds.yMin - ); - - // pool - $poolBoundsObject(bounds); - - const point: Point = this._$parent - ? this._$parent.globalToLocal(new Point(x, y)) - : new Point(x, y); - - return rectangle.containsPoint(point); - } - - /** - * @description point オブジェクトを表示オブジェクトの(ローカル)座標から - * ステージ(グローバル)座標に変換します。 - * Converts the point object from the display object's (local) coordinates - * to the Stage (global) coordinates. - * - * - * @param {Point} point - * @returns {Point} - * @public - */ - localToGlobal (point: Point): Point - { - const matrix: Matrix = this - ._$transform - .concatenatedMatrix; - - const newPoint: Point = new Point( - point.x * matrix.a + point.y * matrix.c + matrix.tx, - point.x * matrix.b + point.y * matrix.d + matrix.ty - ); - - $poolMatrix(matrix); - - return newPoint; - } - - /** - * @description クラスのローカル変数空間から値を取得 - * Get a value from the local variable space of the class - * - * @param {*} key - * @return {*} - * @method - * @public - */ - getLocalVariable (key: any): any - { - if (!this._$variables) { - return null; - } - - if (this._$variables.has(key)) { - return this._$variables.get(key); - } - } - - /** - * @description クラスのローカル変数空間へ値を保存 - * Store values in the local variable space of the class - * - * @param {*} key - * @param {*} value - * @return {void} - * @method - * @public - */ - setLocalVariable (key: any, value: any): void - { - if (!this._$variables) { - this._$variables = $getMap(); - } - this._$variables.set(key, value); - } - - /** - * @description クラスのローカル変数空間に値があるかどうかを判断します。 - * Determines if there is a value in the local variable space of the class. - * - * @param {*} key - * @return {boolean} - * @method - * @public - */ - hasLocalVariable (key: any): boolean - { - return this._$variables - ? this._$variables.has(key) - : false; - } - - /** - * @description クラスのローカル変数空間の値を削除 - * Remove values from the local variable space of a class - * - * @param {*} key - * @return {void} - * @method - * @public - */ - deleteLocalVariable (key: any): void - { - if (this._$variables && this._$variables.has(key)) { - this._$variables.delete(key); - if (!this._$variables.size) { - $poolMap(this._$variables); - this._$variables = null; - } - } - } - - /** - * @description グローバル変数空間から値を取得 - * Get a value from the global variable space - * - * @param {*} key - * @return {*} - * @method - * @public - */ - getGlobalVariable (key: any): any - { - if ($variables.has(key)) { - return $variables.get(key); - } - return null; - } - - /** - * @description グローバル変数空間へ値を保存 - * Save values to global variable space - * - * @param {*} key - * @param {*} value - * @return {void} - * @method - * @public - */ - setGlobalVariable (key: any, value: any): void - { - $variables.set(key, value); - } - - /** - * @description グローバル変数空間に値があるかどうかを判断します。 - * Determines if there is a value in the global variable space. - * - * @param {*} key - * @return {boolean} - * @method - * @public - */ - hasGlobalVariable (key: any): boolean - { - return $variables.has(key); - } - - /** - * @description グローバル変数空間の値を削除 - * Remove values from global variable space. - * - * @param {*} key - * @return {void} - * @method - * @public - */ - deleteGlobalVariable (key: any): void - { - if ($variables.has(key)) { - $variables.delete(key); - } - } - - /** - * @description グローバル変数空間に値を全てクリアします。 - * Clear all values in the global variable space. - * - * @return {void} - * @method - * @public - */ - clearGlobalVariable (): void - { - return $variables.clear(); - } - - /** - * @return {object} - * @method - * @private - */ - _$getPlaceObject (): PlaceObjectImpl | null - { - if (!this._$placeObject) { - - const placeId = this._$placeId; - if (placeId === -1) { - return null; - } - - const parent: ParentImpl | null = this._$parent; - if (!parent || !parent._$placeObjects) { - return null; - } - - const placeMap: Array> | null = parent._$placeMap; - if (!placeMap || !placeMap.length) { - return null; - } - - const frame: number = "currentFrame" in parent ? parent.currentFrame : 1; - const places: number[] | void = placeMap[frame]; - if (!places) { - return null; - } - - const currentPlaceId: number = places[placeId] | 0; - const placeObject: PlaceObjectImpl | void = parent._$placeObjects[currentPlaceId]; - if (!placeObject) { - return null; - } - - this._$changePlace = currentPlaceId !== this._$currentPlaceId; - this._$currentPlaceId = currentPlaceId; - this._$placeObject = placeObject; - - return placeObject; - } - - return this._$placeObject; - } - - /** - * @param {object} tag - * @param {DisplayObjectContainer} parent - * @return {object} - * @method - * @private - */ - _$baseBuild ( - tag: DictionaryTagImpl, - parent: ParentImpl - ): T { - - const loaderInfo: LoaderInfo | null = parent._$loaderInfo; - if (!loaderInfo || !loaderInfo._$data) { - throw new Error("the loaderInfo or data is nul."); - } - - // setup - this._$parent = parent; - this._$root = parent._$root; - this._$stage = parent._$stage; - this._$loaderInfo = loaderInfo; - - // bind tag data - this._$characterId = tag.characterId | 0; - this._$clipDepth = tag.clipDepth | 0; - this._$startFrame = tag.startFrame | 0; - this._$endFrame = tag.endFrame | 0; - this._$name = tag.name || ""; - - return loaderInfo._$data.characters[tag.characterId]; - } - - /** - * @return {boolean} - * @method - * @private - */ - _$isUpdated (): boolean - { - return this._$updated; - } - - /** - * @return {void} - * @method - * @private - */ - _$updateState (): void - { - this._$isNext = true; - - const parent: ParentImpl | null = this._$parent; - if (parent) { - parent._$updateState(); - } - } - - /** - * @return {void} - * @method - * @private - */ - _$doChanged (): void - { - this._$posted = false; - this._$isNext = true; - this._$updated = true; - - const parent: ParentImpl | null = this._$parent; - if (parent) { - if (!parent._$updated) { - parent._$doChanged(); - } - } - } - - /** - * @param {CanvasToWebGLContext} context - * @param {Float32Array} matrix - * @param {array} filters - * @param {number} width - * @param {number} height - * @param {WebGLTexture} [target_texture = null] - * @return {object} - * @method - * @private - */ - _$drawFilter ( - context: CanvasToWebGLContext, - matrix: Float32Array, - filters: FilterArrayImpl, - width: number, - height: number, - target_texture: WebGLTexture | null = null - ): CachePositionImpl { - - const cacheKeys: any[] = $getArray(this._$instanceId, "f"); - let position: CachePositionImpl | void = $cacheStore.get(cacheKeys); - - const updated: boolean = this._$isFilterUpdated(matrix, filters, true); - - if (position && !updated) { - context.cachePosition = position; - return position; - } - - // cache clear - if (position) { - $cacheStore.set(cacheKeys, null); - } - - const manager: FrameBufferManager = context.frameBuffer; - const targetTexture: WebGLTexture = target_texture - ? target_texture - : context.getTextureFromRect( - context.cachePosition as NonNullable - ); - - const texture: WebGLTexture = this._$applyFilter( - context, filters, targetTexture, - matrix, width, height - ); - manager.textureManager.release(targetTexture); - - const bounds: BoundsImpl = this._$getLayerBounds(matrix); - position = manager.createCachePosition( - $Math.ceil($Math.abs(bounds.xMax - bounds.xMin)), - $Math.ceil($Math.abs(bounds.yMax - bounds.yMin)) - ); - $poolBoundsObject(bounds); - - position.filterState = true; - position.matrix = `${matrix[0]}_${matrix[1]}_${matrix[2]}_${matrix[3]}_0_0`; - position.offsetX = texture.offsetX; - position.offsetY = texture.offsetY; - - // 関数先でtextureがreleaseされる - context.drawTextureFromRect(texture, position); - - $cacheStore.set(cacheKeys, position); - $poolArray(cacheKeys); - - return position; - } - - /** - * @param {Float32Array} multi_matrix - * @returns {object} - * @private - */ - _$getLayerBounds (multi_matrix: Float32Array): BoundsImpl - { - const baseBounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" - ? this._$getBounds() as BoundsImpl - : $getBoundsObject(); - - const bounds: BoundsImpl = $boundsMatrix(baseBounds, multi_matrix); - $poolBoundsObject(baseBounds); - - const filters: FilterArrayImpl = this._$filters || this.filters; - if (!filters.length) { - return bounds; - } - - let filterBounds: BoundsImpl = $getBoundsObject( - 0, - $Math.abs(bounds.xMax - bounds.xMin), - 0, - $Math.abs(bounds.yMax - bounds.yMin) - ); - $poolBoundsObject(bounds); - - let xScale: number = +$Math.sqrt( - multi_matrix[0] * multi_matrix[0] - + multi_matrix[1] * multi_matrix[1] - ); - let yScale: number = +$Math.sqrt( - multi_matrix[2] * multi_matrix[2] - + multi_matrix[3] * multi_matrix[3] - ); - - xScale /= $devicePixelRatio; - yScale /= $devicePixelRatio; - - xScale *= 2; - yScale *= 2; - - for (let idx: number = 0; idx < filters.length; ++idx) { - filterBounds = filters[idx] - ._$generateFilterRect(filterBounds, xScale, yScale); - } - - return filterBounds; - } - - /** - * @return {void} - * @method - * @private - */ - _$executeAddedEvent (): void - { - if (!this._$parent) { - return ; - } - - // add event - if (!this._$added) { - - // added event - if (this.willTrigger(Next2DEvent.ADDED)) { - this.dispatchEvent(new Next2DEvent(Next2DEvent.ADDED, true)); - } - - // update - this._$added = true; - } - - if (!this._$addedStage && this._$stage !== null) { - - if (this.willTrigger(Next2DEvent.ADDED_TO_STAGE)) { - this.dispatchEvent(new Next2DEvent(Next2DEvent.ADDED_TO_STAGE)); - } - - // update - this._$addedStage = true; - } - } - - /** - * @return {void} - * @method - * @private - */ - _$prepareActions (): void - { - this._$nextFrame(); - } - - /** - * @return {boolean} - * @method - * @private - */ - _$nextFrame (): boolean - { - // added event - this._$executeAddedEvent(); - - this._$isNext = false; - - if (!this._$posted && $rendererWorker) { - // @ts-ignore - this._$postProperty(); - } - - return false; - } - - /** - * @param {array} [filters=null] - * @return {boolean} - * @private - */ - _$canApply (filters: FilterArrayImpl | null = null): boolean - { - if (filters) { - for (let idx: number = 0; idx < filters.length; ++idx) { - if (filters[idx]._$canApply()) { - return true; - } - } - } - return false; - } - - /** - * @param {Float32Array} matrix - * @param {array} [filters=null] - * @param {boolean} [can_apply=false] - * @param {number} [position_x=0] - * @param {number} [position_y=0] - * @return {boolean} - * @private - */ - _$isFilterUpdated ( - matrix: Float32Array, - filters: FilterArrayImpl | null = null, - can_apply: boolean = false - ): boolean { - - // cache flag - if (this._$isUpdated()) { - return true; - } - - // check filter data - if (can_apply && filters) { - - for (let idx: number = 0; idx < filters.length; ++idx) { - - if (!filters[idx]._$isUpdated()) { - continue; - } - - return true; - } - - } - - // check status - const cache: CachePositionImpl = $cacheStore.get([this._$instanceId, "f"]); - if (!cache) { - return true; - } - - if (cache.filterState !== can_apply) { - return true; - } - - if (cache.matrix !== `${matrix[0]}_${matrix[1]}_${matrix[2]}_${matrix[3]}`) { - return true; - } - - return false; - } - - /** - * @param {CanvasToWebGLContext} context - * @param {array} filters - * @param {WebGLTexture} target_texture - * @param {Float32Array} matrix - * @param {number} width - * @param {number} height - * @return {WebGLTexture} - * @private - */ - _$applyFilter ( - context: CanvasToWebGLContext, - filters: FilterArrayImpl, - target_texture: WebGLTexture, - matrix: Float32Array, - width: number, - height: number - ): WebGLTexture { - - const xScale: number = +$Math.sqrt( - matrix[0] * matrix[0] - + matrix[1] * matrix[1] - ); - const yScale: number = +$Math.sqrt( - matrix[2] * matrix[2] - + matrix[3] * matrix[3] - ); - - const radianX: number = $Math.atan2(matrix[1], matrix[0]); - const radianY: number = $Math.atan2(-matrix[2], matrix[3]); - - const parentMatrix: Float32Array = $getFloat32Array6( - $Math.cos(radianX), $Math.sin(radianX), - -$Math.sin(radianY), $Math.cos(radianY), - width / 2, height / 2 - ); - - const baseMatrix: Float32Array = $getFloat32Array6( - 1, 0, 0, 1, - -target_texture.width / 2, - -target_texture.height / 2 - ); - - const multiMatrix: Float32Array = $multiplicationMatrix( - parentMatrix, baseMatrix - ); - $poolFloat32Array6(parentMatrix); - $poolFloat32Array6(baseMatrix); - - const manager: FrameBufferManager = context.frameBuffer; - const currentAttachment: AttachmentImpl | null = manager.currentAttachment; - - const attachment: AttachmentImpl = manager - .createCacheAttachment(width, height); - context._$bind(attachment); - - context.reset(); - context.setTransform( - multiMatrix[0], multiMatrix[1], - multiMatrix[2], multiMatrix[3], - multiMatrix[4], multiMatrix[5] - ); - $poolFloat32Array6(multiMatrix); - - context.drawImage(target_texture, - 0, 0, target_texture.width, target_texture.height - ); - - // init - context._$offsetX = 0; - context._$offsetY = 0; - - const filterMatrix: Float32Array = $getFloat32Array6( - xScale, 0, 0, yScale, 0, 0 - ); - - let texture: WebGLTexture | null = null; - for (let idx: number = 0; idx < filters.length; ++idx) { - texture = filters[idx]._$applyFilter(context, filterMatrix); - } - - $poolFloat32Array6(filterMatrix); - - if (!texture) { - return target_texture; - } - - const offsetX: number = context._$offsetX; - const offsetY: number = context._$offsetY; - - // reset - context._$offsetX = 0; - context._$offsetY = 0; - - // set offset - texture.offsetX = offsetX; - texture.offsetY = offsetY; - - context._$bind(currentAttachment); - manager.releaseAttachment(attachment, false); - - return texture; - } - - /** - * @param {Float32Array} matrix - * @return {boolean} - * @method - * @private - */ - _$shouldClip (matrix: Float32Array): boolean - { - const bounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" - ? this._$getBounds(matrix) as BoundsImpl - : $getBoundsObject(); - - const width = $Math.abs(bounds.xMax - bounds.xMin); - const height = $Math.abs(bounds.yMax - bounds.yMin); - $poolBoundsObject(bounds); - - // size 0 - return !(!width || !height); - } - - /** - * @param {CanvasToWebGLContext} context - * @param {Float32Array} matrix - * @return {boolean} - * @method - * @private - */ - _$startClip ( - context: CanvasToWebGLContext, - matrix: Float32Array - ): boolean { - - context.drawInstacedArray(); - - // マスクの描画反映を限定 - const bounds: BoundsImpl = "_$getBounds" in this && typeof this._$getBounds === "function" - ? this._$getBounds(matrix) as BoundsImpl - : $getBoundsObject(); - - const result = context._$startClip(bounds); - $poolBoundsObject(bounds); - - if (!result) { - return false; - } - - // start clip - context._$enterClip(); - - // mask start - context._$beginClipDef(); - - let containerClip = false; - if ("_$children" in this) { - containerClip = true; - context._$updateContainerClipFlag(true); - } - - // @ts-ignore - this._$clip(context, matrix); - this._$updated = false; - - // container clip - if (containerClip) { - - // update flag - context._$updateContainerClipFlag(false); - - // execute clip - context._$drawContainerClip(); - } - - // mask end - context._$endClipDef(); - - return true; - } - - /** - * @return {void} - * @method - * @private - */ - _$removeWorkerInstance (): void - { - if ($rendererWorker) { - $rendererWorker.postMessage({ - "command": "remove", - "instanceId": this._$instanceId - }); - } - } - - /** - * @param {Float32Array} buffer - * @param {number} [index = 0] - * @return {void} - * @method - * @private - */ - _$registerProperty (buffer: Float32Array, index: number = 0): void - { - // visible - buffer[index++] = +this._$visible; - - // depth - buffer[index++] = this._$placeId; - - // clip depth - buffer[index++] = this._$clipDepth; - - // isMask - buffer[index++] = +this._$isMask; - - const mask: DisplayObjectImpl | null = this._$mask; - buffer[index++] = +(mask !== null); - if (mask) { - - // mask id - buffer[index++] = mask._$instanceId; - - let maskMatrix: Float32Array = $MATRIX_ARRAY_IDENTITY; - let parent: ParentImpl | null = mask._$parent; - while (parent) { - - maskMatrix = $multiplicationMatrix( - parent._$transform._$rawMatrix(), - maskMatrix - ); - - parent = parent._$parent; - } - - // mask matrix - buffer[index++] = maskMatrix[0]; - buffer[index++] = maskMatrix[1]; - buffer[index++] = maskMatrix[2]; - buffer[index++] = maskMatrix[3]; - buffer[index++] = maskMatrix[4]; - buffer[index++] = maskMatrix[5]; - } else { - index += 7; - } - - if (this._$visible) { - const transform: Transform = this._$transform; - - // matrix - const matrix: Float32Array = transform._$rawMatrix(); - buffer[index++] = matrix[0]; - buffer[index++] = matrix[1]; - buffer[index++] = matrix[2]; - buffer[index++] = matrix[3]; - buffer[index++] = matrix[4]; - buffer[index++] = matrix[5]; - - // colorTransform - const colorTransform = transform._$rawColorTransform(); - buffer[index++] = colorTransform[0]; - buffer[index++] = colorTransform[1]; - buffer[index++] = colorTransform[2]; - buffer[index++] = colorTransform[3]; - buffer[index++] = colorTransform[4]; - buffer[index++] = colorTransform[5]; - buffer[index++] = colorTransform[6]; - buffer[index++] = colorTransform[7]; - - } else { - index += 6; // matrix - index += 8; // colorTransform - } - - // blend mode - const blendMode: BlendModeImpl = this._$blendMode || this.blendMode; - buffer[index++] = $blendToNumber(blendMode); - - // scale9Grid - const scale9Grid: Rectangle | null = this._$scale9Grid; - buffer[index++] = +(scale9Grid !== null); - - if (scale9Grid) { - buffer[index++] = scale9Grid.x; - buffer[index++] = scale9Grid.y; - buffer[index++] = scale9Grid.width; - buffer[index++] = scale9Grid.height; - } else { - index += 4; - } - - // filter - } - - /** - * @return {object} - * @method - * @private - */ - _$createMessage (): PropertyMessageMapImpl - { - const message: PropertyMessageImpl = { - "command": "setProperty", - "buffer": new Float32Array(), - "instanceId": this._$instanceId, - "parentId": this._$parent ? this._$parent._$instanceId : -1, - "visible": this._$visible - }; - - if (this._$placeId > -1) { - message.depth = this._$placeId; - } - - if (this._$clipDepth) { - message.clipDepth = this._$clipDepth; - } - - if (this._$isMask) { - message.isMask = this._$isMask; - } - - const mask: DisplayObjectImpl | null = this._$mask; - if (mask) { - message.maskId = mask._$instanceId; - - let maskMatrix: Float32Array = $MATRIX_ARRAY_IDENTITY; - let parent: ParentImpl | null = mask._$parent; - while (parent) { - - maskMatrix = $multiplicationMatrix( - parent._$transform._$rawMatrix(), - maskMatrix - ); - - parent = parent._$parent; - } - - message.maskMatrix = maskMatrix; - } - - if (this._$visible) { - - const transform: Transform = this._$transform; - - const matrix: Float32Array = transform._$rawMatrix(); - if (matrix[0] !== 1) { - message.a = matrix[0]; - } - - if (matrix[1] !== 0) { - message.b = matrix[1]; - } - - if (matrix[2] !== 0) { - message.c = matrix[2]; - } - - if (matrix[3] !== 1) { - message.d = matrix[3]; - } - - if (matrix[4] !== 0) { - message.tx = matrix[4]; - } - - if (matrix[5] !== 0) { - message.ty = matrix[5]; - } - - const colorTransform = transform._$rawColorTransform(); - if (colorTransform[0] !== 1) { - message.f0 = colorTransform[0]; - } - - if (colorTransform[1] !== 1) { - message.f1 = colorTransform[1]; - } - - if (colorTransform[2] !== 1) { - message.f2 = colorTransform[2]; - } - - if (colorTransform[3] !== 1) { - message.f3 = colorTransform[3]; - } - - if (colorTransform[4] !== 0) { - message.f4 = colorTransform[4]; - } - - if (colorTransform[5] !== 0) { - message.f5 = colorTransform[5]; - } - - if (colorTransform[6] !== 0) { - message.f6 = colorTransform[6]; - } - - if (colorTransform[7] !== 0) { - message.f7 = colorTransform[7]; - } - - const filters: FilterArrayImpl | null = this._$filters || this.filters; - if (filters && filters.length) { - const parameters: any[] = $getArray(); - for (let idx: number = 0; idx < filters.length; ++idx) { - parameters.push(filters[idx]._$toArray()); - } - - message.filters = parameters; - } - - const blendMode: BlendModeImpl = this._$blendMode || this.blendMode; - if (blendMode !== "normal") { - message.blendMode = blendMode; - } - - const scale9Grid: Rectangle | null = this._$scale9Grid; - if (scale9Grid && this._$isUpdated()) { - - const baseMatrix: Matrix = this - ._$parent - ._$transform - .concatenatedMatrix; - - message.matrixBase = baseMatrix._$matrix.slice(); - $poolMatrix(baseMatrix); - - message.grid = { - "x": scale9Grid.x, - "y": scale9Grid.y, - "w": scale9Grid.width, - "h": scale9Grid.height - }; - } - } - - return message; - } + // return message; + // } } diff --git a/packages/display/src/DisplayObject/DisplayObjectGetPlaceObjectService.ts b/packages/display/src/DisplayObject/DisplayObjectGetPlaceObjectService.ts new file mode 100644 index 00000000..e4c1b5de --- /dev/null +++ b/packages/display/src/DisplayObject/DisplayObjectGetPlaceObjectService.ts @@ -0,0 +1,53 @@ +import type { DisplayObjectImpl } from "../interface/DisplayObjectImpl"; +import type { PlaceObjectImpl } from "../interface/PlaceObjectImpl"; +import type { ParentImpl } from "../interface/ParentImpl"; + +/** + * @description DisplayObjectのPlaceObjectを返却、存在しない場合はnullを返却 + * Return the PlaceObject of the DisplayObject, or return null if it does not exist. + * + * @param {DisplayObject} display_object + * @return {object} + * @method + * @protected + */ +export const execute = (display_object: DisplayObjectImpl): PlaceObjectImpl | null => +{ + // キャッシュされたPlaceObjectがあれば返却 + const placeObject: PlaceObjectImpl | null = display_object._$placeObject; + if (placeObject) { + return placeObject; + } + + const placeId = display_object._$placeId; + if (placeId === -1) { + return null; + } + + const parent: ParentImpl | null = display_object.parent; + if (!parent || !parent._$placeObjects) { + return null; + } + + const placeMap: Array> | null = parent._$placeMap; + if (!placeMap || !placeMap.length) { + return null; + } + + const frame: number = "currentFrame" in parent ? parent.currentFrame : 1; + const places: number[] | void = placeMap[frame]; + if (!places) { + return null; + } + + const targetPlaceId: number = places[placeId] | 0; + const targetPlaceObject: PlaceObjectImpl | void = parent._$placeObjects[targetPlaceId]; + if (!targetPlaceObject) { + return null; + } + + // キャッシュ + display_object._$placeObject = targetPlaceObject; + + return null; +}; \ No newline at end of file diff --git a/packages/display/src/DisplayObject/DisplayObjectGetRawMatrixService.ts b/packages/display/src/DisplayObject/DisplayObjectGetRawMatrixService.ts new file mode 100644 index 00000000..9cb3d3e2 --- /dev/null +++ b/packages/display/src/DisplayObject/DisplayObjectGetRawMatrixService.ts @@ -0,0 +1,47 @@ +import type { Matrix } from "@next2d/geom"; +import type { PlaceObjectImpl } from "../interface/PlaceObjectImpl"; +import type { DisplayObjectImpl } from "../interface/DisplayObjectImpl"; +import { execute as displayObjectGetPlaceObjectService } from "./DisplayObjectGetPlaceObjectService"; +import { $getFloat32Array6 } from "../DisplayObjectUtil"; + +/** + * @type {Float32Array} + * @const + */ +const $MATRIX_ARRAY_IDENTITY: Float32Array = new Float32Array([1, 0, 0, 1, 0, 0]); + +/** + * @description DisplayObjectの内部Float32Arrayデータを返却、存在しない場合は固定のFloat32Arrayデータを返却 + * Return the internal Float32Array data of the DisplayObject, + * or return a fixed Float32Array data if it does not exist. + * + * @param {DisplayObject} display_object + * @param {Matrix | null} [matrix=null] + * @return {Float32Array} + * @method + * @protected + */ +export const execute = ( + display_object: DisplayObjectImpl, + matrix: Matrix | null = null +): Float32Array => { + + if (matrix) { + return matrix.rawData; + } + + const placeObject: PlaceObjectImpl | null = displayObjectGetPlaceObjectService(display_object); + if (!placeObject || !placeObject.matrix) { + return $MATRIX_ARRAY_IDENTITY; + } + + if (!placeObject.typedMatrix) { + const matrix: number[] = placeObject.matrix; + placeObject.typedMatrix = $getFloat32Array6( + matrix[0], matrix[1], matrix[2], + matrix[3], matrix[4], matrix[5] + ); + } + + return placeObject.typedMatrix; +}; \ No newline at end of file diff --git a/packages/display/src/DisplayObjectContainer.ts b/packages/display/src/DisplayObjectContainer.ts index 92a2d815..1af55957 100644 --- a/packages/display/src/DisplayObjectContainer.ts +++ b/packages/display/src/DisplayObjectContainer.ts @@ -1,78 +1,31 @@ import { InteractiveObject } from "./InteractiveObject"; -import { Event as Next2DEvent } from "@next2d/events"; -import type { LoaderInfo } from "./LoaderInfo"; -import type { Player } from "@next2d/core"; -import type { Sound } from "@next2d/media"; -import type { Transform } from "@next2d/geom"; -import type { - DictionaryTagImpl, - PlaceObjectImpl, - DisplayObjectImpl, - BoundsImpl, - FilterArrayImpl, - LoopConfigImpl, - ParentImpl, - PreObjectImpl, - AttachmentImpl, - BlendModeImpl, - PlayerHitObjectImpl, - PropertyMessageMapImpl, - PropertyContainerMessageImpl, - Character -} from "@next2d/interface"; -import type { - CanvasToWebGLContext, - FrameBufferManager -} from "@next2d/webgl"; +// import { Event as Next2DEvent } from "@next2d/events"; +// import type { LoaderInfo } from "./LoaderInfo"; +// import type { Sound } from "@next2d/media"; +// import type { Transform } from "@next2d/geom"; +import type { PlaceObjectImpl } from "./interface/PlaceObjectImpl"; +import type { DisplayObjectImpl } from "./interface/DisplayObjectImpl"; +import type { DictionaryTagImpl } from "./interface/DictionaryTagImpl"; +// import type { +// CanvasToWebGLContext, +// FrameBufferManager +// } from "@next2d/webgl"; import { - $createInstance, - $currentPlayer, - $getRenderBufferArray, - $getRenderMessageObject, - $hitContext, - $isTouch, - $MATRIX_HIT_ARRAY_IDENTITY, - $poolRenderMessageObject, - $rendererWorker -} from "@next2d/util"; -import { - $cacheStore, - $doUpdated, - $boundsMatrix, - $clamp, - $getArray, - $getBoundsObject, - $getFloat32Array6, - $getFloat32Array8, - $getMap, - $getPreObject, - $Math, - $COLOR_ARRAY_IDENTITY, - $MATRIX_ARRAY_IDENTITY, - $multiplicationColor, - $multiplicationMatrix, - $Number, - $poolArray, - $poolBoundsObject, - $poolFloat32Array6, - $poolFloat32Array8, - $poolMap, - $poolPreObject, - $devicePixelRatio -} from "@next2d/share"; + $getArray +} from "./DisplayObjectUtil"; /** - * DisplayObjectContainer クラスは、表示リストで表示オブジェクトコンテナとして機能するすべてのオブジェクトの基本クラスです。 - * このクラス自体は、画面上でのコンテンツの描画のための API を含みません。 - * そのため、DisplayObject クラスのカスタムサブクラスを作成する場合は、 - * Sprite、または MovieClip など、画面上にコンテンツを描画する API を持つサブクラスの 1 つを拡張する必要があります。 + * @description DisplayObjectContainer クラスは、表示リストで表示オブジェクトコンテナとして機能するすべてのオブジェクトの基本クラスです。 + * このクラス自体は、画面上でのコンテンツの描画のための API を含みません。 + * そのため、DisplayObject クラスのカスタムサブクラスを作成する場合は、 + * Sprite、または MovieClip など、画面上にコンテンツを描画する API を持つサブクラスの 1 つを拡張する必要があります。 * - * The DisplayObjectContainer class is the base class for all objects that can serve - * as display object containers on the display list. - * This class itself does not contain any API for drawing content on the screen. - * Therefore, if you want to create a custom subclass of the DisplayObject class, - * you need to extend one of its subclasses that has an API for drawing content on the screen, - * such as Sprite or MovieClip. + * The DisplayObjectContainer class is the base class for all objects that can serve + * as display object containers on the display list. + * This class itself does not contain any API for drawing content on the screen. + * Therefore, if you want to create a custom subclass of the DisplayObject class, + * you need to extend one of its subclasses that has an API for drawing content on the screen, + * such as Sprite or MovieClip. * * @class * @memberOf next2d.display @@ -157,7 +110,7 @@ export class DisplayObjectContainer extends InteractiveObject * @type {Map} * @private */ - this._$names = $getMap(); + this._$names = new Map(); return new Proxy(this, { "get": (object: this, name: string): any => @@ -187,2088 +140,1984 @@ export class DisplayObjectContainer extends InteractiveObject this._$mouseChildren = !!mouse_children; } - /** - * @description このオブジェクトの子の数を返します。 - * Returns the number of children of this object. - * - * @member {number} - * @readonly - * @public - */ - get numChildren (): number - { - return this._$needsChildren - ? this._$getChildren().length - : this._$children.length; - } - - /** - * @description この DisplayObjectContainer インスタンスに子 DisplayObject インスタンスを追加します。 - * Adds a child DisplayObject instance to this DisplayObjectContainer instance. - * - * @param {DisplayObject} child - * @return {DisplayObject} - * @method - * @public - */ - addChild (child: DisplayObjectImpl): DisplayObjectImpl - { - if (child._$parent) { - child._$parent._$remove(child, - !(child._$parent._$instanceId === this._$instanceId) - ); - } - - this._$getChildren().push(child); - - if (child._$name) { - this._$names.set(child._$name, child); - } - - return this._$addChild(child); - } - - /** - * @description この DisplayObjectContainer インスタンスに子 DisplayObject インスタンスを追加します。 - * Adds a child DisplayObject instance to this DisplayObjectContainer instance. - * - * @param {DisplayObject} child - * @param {number} index - * @return {DisplayObject} - * @method - * @public - */ - addChildAt ( - child: DisplayObjectImpl, - index: number - ): DisplayObjectImpl { - - if (child._$parent) { - child._$parent._$remove(child, - !(child._$parent._$instanceId === this._$instanceId) - ); - } - - const children: DisplayObjectImpl[] = this._$getChildren(); - const length: number = children.length; - if (0 > index || index > length) { - throw new RangeError(`RangeError: addChildAt: index error: ${index}`); - } - - if (length && length > index) { - - children.splice(index, 0, child); - - for (let idx: number = 0; idx < index; ++idx) { - const instance: DisplayObjectImpl = children[idx]; - if (instance._$name) { - this._$names.set(instance._$name, instance); - } - } - - } else { - - children.push(child); - if (child._$name) { - this._$names.set(child._$name, child); - } - - } - - return this._$addChild(child); - } - - /** - * @description 指定された表示オブジェクトが、DisplayObjectContainer インスタンスの子であるか - * インスタンス自体であるかを指定します。 - * Determines whether the specified display object is a child - * of the DisplayObjectContainer instance or the instance itself. - * - * @param {DisplayObject} child - * @return {boolean} - * @method - * @public - */ - contains (child: DisplayObjectImpl): boolean - { - if (this._$instanceId === child._$instanceId) { - return true; - } - - const children: DisplayObjectImpl[] = this._$getChildren(); - for (let idx: number = 0; idx < children.length; ++idx) { - - const instance: DisplayObjectImpl = children[idx]; - - if (instance._$instanceId === child._$instanceId) { - return true; - } - - if (instance instanceof DisplayObjectContainer) { - - if (instance.contains(child)) { - return true; - } - - } - - } - - return false; - } - - /** - * @description 指定のインデックス位置にある子表示オブジェクトインスタンスを返します。 - * Returns the child display object instance that exists at the specified index. - * - * @param {number} index - * @return {DisplayObject} - * @method - * @public - */ - getChildAt (index: number): DisplayObjectImpl - { - const children: DisplayObjectImpl[] = this._$getChildren(); - - if (0 > index || index > children.length) { - throw new RangeError(`RangeError: getChildAt: index error: ${index}`); - } - - return index in children ? children[index] : null; - } - - /** - * @description 指定された名前に一致する子表示オブジェクトを返します。 - * Returns the child display object that exists with the specified name. - * - * @param {string} name - * @return {{DisplayObject}|null} - * @method - * @public - */ - getChildByName (name: string): DisplayObjectImpl | null - { - if (!name) { - return null; - } - - // fixed logic - const children: DisplayObjectImpl[] = this._$getChildren(); - for (let idx: number = 0; idx < children.length; ++idx) { - - const child: DisplayObjectImpl = children[idx]; - if (child.name !== name) { - continue; - } - - return child; - } - - return null; - } - - /** - * @description 子 DisplayObject インスタンスのインデックス位置を返します。 - * Returns the index position of a child DisplayObject instance. - * - * @param {DisplayObject} child - * @return {number} - * @method - * @public - */ - getChildIndex (child: DisplayObjectImpl): number - { - if (child._$parent !== this) { - throw new Error("ArgumentError: getChildIndex: not child"); - } - - const index: number = this._$getChildren().indexOf(child); - if (index === -1) { - throw new Error("ArgumentError: getChildIndex: not found."); - } - - return index; - } - - /** - * @description DisplayObjectContainer インスタンスの子リストから指定の - * child DisplayObject インスタンスを削除します。 - * Removes the specified child DisplayObject instance from the - * child list of the DisplayObjectContainer instance. - * - * @param {DisplayObject} child - * @return {DisplayObject} - * @method - * @public - */ - removeChild (child: DisplayObjectImpl): DisplayObjectImpl - { - if (child._$parent !== this) { - throw new Error("ArgumentError: removeChild: not child"); - } - return this._$remove(child); - } - - /** - * @description DisplayObjectContainer の子リストの指定された index 位置から子 DisplayObject を削除します。 - * Removes a child DisplayObject from the specified index position - * in the child list of the DisplayObjectContainer. - * - * @param {number} index - * @return {DisplayObject} - * @method - * @public - */ - removeChildAt (index: number): DisplayObjectImpl - { - return this._$remove(this.getChildAt(index)); - } - - /** - * @description DisplayObjectContainer インスタンスの子リストから - * すべての child DisplayObject インスタンスを削除します。 - * Removes all child DisplayObject instances from - * the child list of the DisplayObjectContainer instance. - * - * @param {number} [begin_index=0] - * @param {number} [end_index=0x7fffffff] - * @return {void} - * @method - * @public - */ - removeChildren ( - begin_index: number = 0, - end_index: number = 0x7fffffff - ): void { - - const children: DisplayObjectImpl[] = this._$getChildren(); - if (!children.length) { - return ; - } - - begin_index = $clamp(begin_index, 0, 0x7ffffffe, 0) - 1; - end_index = $clamp(end_index, 1, 0x7ffffff, 0x7ffffff); - - for (let idx: number = $Math.min(end_index, children.length - 1); idx > begin_index; --idx) { - this._$remove(children[idx]); - } - } - - /** - * @description 表示オブジェクトコンテナの既存の子の位置を変更します。 - * Changes the position of an existing child in the display object container. - * - * @param {DisplayObject} child - * @param {number} index - * @return {void} - * @method - * @public - */ - setChildIndex ( - child: DisplayObjectImpl, - index: number - ): void { - - const currentIndex: number = this.getChildIndex(child); - if (currentIndex === index) { - return ; - } - - const children: DisplayObjectImpl[] = this._$getChildren(); - children.splice(currentIndex, 1); - children.splice(index, 0, child); - - if ($rendererWorker) { - this._$postChildrenIds(); - } - - this._$doChanged(); - } - - /** - * @description 指定された 2 つの子オブジェクトの z 順序(重ね順)を入れ替えます。 - * Swaps the z-order (front-to-back order) of the two specified child objects. - * - * @param {DisplayObject} child1 - * @param {DisplayObject} child2 - * @return {void} - * @method - * @public - */ - swapChildren ( - child1: DisplayObjectImpl, - child2: DisplayObjectImpl - ): void { - - const children: DisplayObjectImpl[] = this._$getChildren(); - const index1: number = this.getChildIndex(child1); - const index2: number = this.getChildIndex(child2); - - children[index1] = child2; - children[index2] = child1; - - if ($rendererWorker) { - this._$postChildrenIds(); - } - - this._$doChanged(); - } - - /** - * @description 子リスト内の指定されたインデックス位置に該当する 2 つの子オブジェクトの z 順序(重ね順)を入れ替えます。 - * Swaps the z-order (front-to-back order) of the child objects at - * the two specified index positions in the child list. - * - * @param {number} index1 - * @param {number} index2 - * @return {void} - * @method - * @public - */ - swapChildrenAt (index1: number, index2: number): void - { - this.swapChildren( - this.getChildAt(index1), - this.getChildAt(index2) - ); - } - - /** - * @param {array} [matrix=null] - * @return {object} - * @private - */ - _$getBounds (matrix: Float32Array | null = null): BoundsImpl - { - let multiMatrix: Float32Array = $MATRIX_ARRAY_IDENTITY; - if (matrix) { - - multiMatrix = matrix; - - const rawMatrix: Float32Array = this._$transform._$rawMatrix(); - if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 - || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 - || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 - ) { - multiMatrix = $multiplicationMatrix(matrix, rawMatrix); - } - } - - const children: DisplayObjectImpl[] = this._$needsChildren - ? this._$getChildren() - : this._$children; - - // size zero - if (!children.length) { - - const bounds: BoundsImpl = $getBoundsObject( - multiMatrix[4], -multiMatrix[4], - multiMatrix[5], -multiMatrix[5] - ); - - if (matrix && multiMatrix !== matrix) { - $poolFloat32Array6(multiMatrix); - } - - return bounds; - } - - // data init - const no = $Number.MAX_VALUE; - let xMin = no; - let xMax = -no; - let yMin = no; - let yMax = -no; - for (let idx: number = 0; idx < children.length; ++idx) { - - const bounds: BoundsImpl = children[idx]._$getBounds(multiMatrix); - - xMin = $Math.min(xMin, bounds.xMin); - xMax = $Math.max(xMax, bounds.xMax); - yMin = $Math.min(yMin, bounds.yMin); - yMax = $Math.max(yMax, bounds.yMax); - - $poolBoundsObject(bounds); - - } - - if (matrix && multiMatrix !== matrix) { - $poolFloat32Array6(multiMatrix); - } - - // end - return $getBoundsObject(xMin, xMax, yMin, yMax); - } - - /** - * @param {Float32Array} multi_matrix - * @return {object} - * @private - */ - _$getLayerBounds (multi_matrix: Float32Array): BoundsImpl - { - - const children: DisplayObjectImpl[] = this._$needsChildren - ? this._$getChildren() - : this._$children; - - // size zero - if (!children.length) { - return $getBoundsObject(0, 0, 0, 0); - } - - // data init - const no: number = $Number.MAX_VALUE; - let xMin: number = no; - let xMax: number = -no; - let yMin: number = no; - let yMax: number = -no; - for (let idx: number = 0; idx < children.length; ++idx) { - - const instance = children[idx]; - - let multiMatrix = multi_matrix; - const rawMatrix: Float32Array = instance._$transform._$rawMatrix(); - if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 - || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 - || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 - ) { - multiMatrix = $multiplicationMatrix(multi_matrix, rawMatrix); - } - - const bounds: BoundsImpl = instance._$getLayerBounds(multiMatrix); - - xMin = $Math.min(xMin, bounds.xMin); - xMax = $Math.max(xMax, bounds.xMax); - yMin = $Math.min(yMin, bounds.yMin); - yMax = $Math.max(yMax, bounds.yMax); - - $poolBoundsObject(bounds); - - if (multiMatrix !== multi_matrix) { - $poolFloat32Array6(multiMatrix); - } - } - - const filters: FilterArrayImpl = this._$filters || this.filters; - if (!filters.length) { - return $getBoundsObject(xMin, xMax, yMin, yMax); - } - - let filterBounds: BoundsImpl = $getBoundsObject( - 0, xMax - xMin, - 0, yMax - yMin - ); - - let xScale: number = +$Math.sqrt( - multi_matrix[0] * multi_matrix[0] - + multi_matrix[1] * multi_matrix[1] - ); - let yScale: number = +$Math.sqrt( - multi_matrix[2] * multi_matrix[2] - + multi_matrix[3] * multi_matrix[3] - ); - - xScale /= $devicePixelRatio; - yScale /= $devicePixelRatio; - - xScale *= 2; - yScale *= 2; - - for (let idx: number = 0; idx < filters.length; ++idx) { - filterBounds = filters[idx] - ._$generateFilterRect(filterBounds, xScale, yScale); - } - - xMax += filterBounds.xMax - (xMax - xMin); - yMax += filterBounds.yMax - (yMax - yMin); - xMin += filterBounds.xMin; - yMin += filterBounds.yMin; - - $poolBoundsObject(filterBounds); - - return $getBoundsObject(xMin, xMax, yMin, yMax); - } - - /** - * @return {array} - * @private - */ - _$getChildren (): DisplayObjectImpl[] - { - if (this._$needsChildren) { - - // set flag - this._$needsChildren = false; - - const currentChildren: DisplayObjectImpl[] = this._$children; - if (!this._$controller) { - return currentChildren; - } - - const frame: number = "_$currentFrame" in this ? this._$currentFrame as number : 1; - const controller: number[] = this._$controller[frame]; - - // first build - if (!currentChildren.length) { - - if (controller) { - - for (let idx: number = 0; idx < controller.length; ++idx) { - - const dictionaryId = controller[idx]; - if (typeof dictionaryId !== "number") { - continue; - } - - const instance: DisplayObjectImpl = this._$createInstance(dictionaryId); - instance._$placeId = idx; - - const loopConfig: LoopConfigImpl | null = instance.loopConfig; - if (loopConfig) { - instance._$currentFrame = instance - ._$getLoopFrame(loopConfig); - } - - currentChildren.push(instance); - if (instance._$name) { - this._$names.set(instance._$name, instance); - } - } - } - - return currentChildren; - } - - const useWorker: boolean = !!$rendererWorker && !!this._$stage; - - const skipIds: Map = $getMap(); - const poolInstances: Map> = $getMap(); - - let depth: number = 0; - const children: DisplayObjectImpl[] = $getArray(); - for (let idx: number = 0; idx < currentChildren.length; ++idx) { - - const instance: DisplayObjectImpl = currentChildren[idx]; - - const parent: ParentImpl = instance._$parent; - if (!parent || parent._$instanceId !== this._$instanceId) { - continue; - } - - const instanceId: number = instance._$instanceId; - const startFrame: number = instance._$startFrame; - const endFrame: number = instance._$endFrame; - if (startFrame === 1 && endFrame === 0 - || startFrame <= frame && endFrame > frame - ) { - - // reset - instance._$isNext = true; - instance._$placeObject = null; - instance._$filters = null; - instance._$blendMode = null; - - if (instance._$id === -1) { - - children.push(instance); - if (instance._$name) { - this._$names.set(instance._$name, instance); - } - - continue; - } - - const id: number = controller[depth]; - if (instance._$id === id) { - - instance._$placeId = depth; - children.push(instance); - - if (instance._$name) { - this._$names.set(instance._$name, instance); - } - - if (poolInstances.has(id)) { - poolInstances.delete(id); - } - - skipIds.set(id, true); - depth++; + // /** + // * @description このオブジェクトの子の数を返します。 + // * Returns the number of children of this object. + // * + // * @member {number} + // * @readonly + // * @public + // */ + // get numChildren (): number + // { + // return this._$needsChildren + // ? this._$getChildren().length + // : this._$children.length; + // } + + // /** + // * @description この DisplayObjectContainer インスタンスに子 DisplayObject インスタンスを追加します。 + // * Adds a child DisplayObject instance to this DisplayObjectContainer instance. + // * + // * @param {DisplayObject} child + // * @return {DisplayObject} + // * @method + // * @public + // */ + // addChild (child: DisplayObjectImpl): DisplayObjectImpl + // { + // if (child._$parent) { + // child._$parent._$remove(child, + // !(child._$parent._$instanceId === this._$instanceId) + // ); + // } + + // this._$getChildren().push(child); + + // if (child._$name) { + // this._$names.set(child._$name, child); + // } + + // return this._$addChild(child); + // } + + // /** + // * @description この DisplayObjectContainer インスタンスに子 DisplayObject インスタンスを追加します。 + // * Adds a child DisplayObject instance to this DisplayObjectContainer instance. + // * + // * @param {DisplayObject} child + // * @param {number} index + // * @return {DisplayObject} + // * @method + // * @public + // */ + // addChildAt ( + // child: DisplayObjectImpl, + // index: number + // ): DisplayObjectImpl { + + // if (child._$parent) { + // child._$parent._$remove(child, + // !(child._$parent._$instanceId === this._$instanceId) + // ); + // } + + // const children: DisplayObjectImpl[] = this._$getChildren(); + // const length: number = children.length; + // if (0 > index || index > length) { + // throw new RangeError(`RangeError: addChildAt: index error: ${index}`); + // } + + // if (length && length > index) { + + // children.splice(index, 0, child); + + // for (let idx: number = 0; idx < index; ++idx) { + // const instance: DisplayObjectImpl = children[idx]; + // if (instance._$name) { + // this._$names.set(instance._$name, instance); + // } + // } + + // } else { + + // children.push(child); + // if (child._$name) { + // this._$names.set(child._$name, child); + // } + + // } + + // return this._$addChild(child); + // } + + // /** + // * @description 指定された表示オブジェクトが、DisplayObjectContainer インスタンスの子であるか + // * インスタンス自体であるかを指定します。 + // * Determines whether the specified display object is a child + // * of the DisplayObjectContainer instance or the instance itself. + // * + // * @param {DisplayObject} child + // * @return {boolean} + // * @method + // * @public + // */ + // contains (child: DisplayObjectImpl): boolean + // { + // if (this._$instanceId === child._$instanceId) { + // return true; + // } + + // const children: DisplayObjectImpl[] = this._$getChildren(); + // for (let idx: number = 0; idx < children.length; ++idx) { + + // const instance: DisplayObjectImpl = children[idx]; + + // if (instance._$instanceId === child._$instanceId) { + // return true; + // } + + // if (instance instanceof DisplayObjectContainer) { + + // if (instance.contains(child)) { + // return true; + // } + + // } + + // } + + // return false; + // } + + // /** + // * @description 指定のインデックス位置にある子表示オブジェクトインスタンスを返します。 + // * Returns the child display object instance that exists at the specified index. + // * + // * @param {number} index + // * @return {DisplayObject} + // * @method + // * @public + // */ + // getChildAt (index: number): DisplayObjectImpl + // { + // const children: DisplayObjectImpl[] = this._$getChildren(); + + // if (0 > index || index > children.length) { + // throw new RangeError(`RangeError: getChildAt: index error: ${index}`); + // } + + // return index in children ? children[index] : null; + // } + + // /** + // * @description 指定された名前に一致する子表示オブジェクトを返します。 + // * Returns the child display object that exists with the specified name. + // * + // * @param {string} name + // * @return {{DisplayObject}|null} + // * @method + // * @public + // */ + // getChildByName (name: string): DisplayObjectImpl | null + // { + // if (!name) { + // return null; + // } + + // // fixed logic + // const children: DisplayObjectImpl[] = this._$getChildren(); + // for (let idx: number = 0; idx < children.length; ++idx) { + + // const child: DisplayObjectImpl = children[idx]; + // if (child.name !== name) { + // continue; + // } + + // return child; + // } + + // return null; + // } + + // /** + // * @description 子 DisplayObject インスタンスのインデックス位置を返します。 + // * Returns the index position of a child DisplayObject instance. + // * + // * @param {DisplayObject} child + // * @return {number} + // * @method + // * @public + // */ + // getChildIndex (child: DisplayObjectImpl): number + // { + // if (child._$parent !== this) { + // throw new Error("ArgumentError: getChildIndex: not child"); + // } + + // const index: number = this._$getChildren().indexOf(child); + // if (index === -1) { + // throw new Error("ArgumentError: getChildIndex: not found."); + // } + + // return index; + // } + + // /** + // * @description DisplayObjectContainer インスタンスの子リストから指定の + // * child DisplayObject インスタンスを削除します。 + // * Removes the specified child DisplayObject instance from the + // * child list of the DisplayObjectContainer instance. + // * + // * @param {DisplayObject} child + // * @return {DisplayObject} + // * @method + // * @public + // */ + // removeChild (child: DisplayObjectImpl): DisplayObjectImpl + // { + // if (child._$parent !== this) { + // throw new Error("ArgumentError: removeChild: not child"); + // } + // return this._$remove(child); + // } + + // /** + // * @description DisplayObjectContainer の子リストの指定された index 位置から子 DisplayObject を削除します。 + // * Removes a child DisplayObject from the specified index position + // * in the child list of the DisplayObjectContainer. + // * + // * @param {number} index + // * @return {DisplayObject} + // * @method + // * @public + // */ + // removeChildAt (index: number): DisplayObjectImpl + // { + // return this._$remove(this.getChildAt(index)); + // } + + // /** + // * @description DisplayObjectContainer インスタンスの子リストから + // * すべての child DisplayObject インスタンスを削除します。 + // * Removes all child DisplayObject instances from + // * the child list of the DisplayObjectContainer instance. + // * + // * @param {number} [begin_index=0] + // * @param {number} [end_index=0x7fffffff] + // * @return {void} + // * @method + // * @public + // */ + // removeChildren ( + // begin_index: number = 0, + // end_index: number = 0x7fffffff + // ): void { + + // const children: DisplayObjectImpl[] = this._$getChildren(); + // if (!children.length) { + // return ; + // } + + // begin_index = $clamp(begin_index, 0, 0x7ffffffe, 0) - 1; + // end_index = $clamp(end_index, 1, 0x7ffffff, 0x7ffffff); + + // for (let idx: number = $Math.min(end_index, children.length - 1); idx > begin_index; --idx) { + // this._$remove(children[idx]); + // } + // } + + // /** + // * @description 表示オブジェクトコンテナの既存の子の位置を変更します。 + // * Changes the position of an existing child in the display object container. + // * + // * @param {DisplayObject} child + // * @param {number} index + // * @return {void} + // * @method + // * @public + // */ + // setChildIndex ( + // child: DisplayObjectImpl, + // index: number + // ): void { + + // const currentIndex: number = this.getChildIndex(child); + // if (currentIndex === index) { + // return ; + // } + + // const children: DisplayObjectImpl[] = this._$getChildren(); + // children.splice(currentIndex, 1); + // children.splice(index, 0, child); + + // if ($rendererWorker) { + // this._$postChildrenIds(); + // } + + // this._$doChanged(); + // } + + // /** + // * @description 指定された 2 つの子オブジェクトの z 順序(重ね順)を入れ替えます。 + // * Swaps the z-order (front-to-back order) of the two specified child objects. + // * + // * @param {DisplayObject} child1 + // * @param {DisplayObject} child2 + // * @return {void} + // * @method + // * @public + // */ + // swapChildren ( + // child1: DisplayObjectImpl, + // child2: DisplayObjectImpl + // ): void { + + // const children: DisplayObjectImpl[] = this._$getChildren(); + // const index1: number = this.getChildIndex(child1); + // const index2: number = this.getChildIndex(child2); + + // children[index1] = child2; + // children[index2] = child1; + + // if ($rendererWorker) { + // this._$postChildrenIds(); + // } + + // this._$doChanged(); + // } + + // /** + // * @description 子リスト内の指定されたインデックス位置に該当する 2 つの子オブジェクトの z 順序(重ね順)を入れ替えます。 + // * Swaps the z-order (front-to-back order) of the child objects at + // * the two specified index positions in the child list. + // * + // * @param {number} index1 + // * @param {number} index2 + // * @return {void} + // * @method + // * @public + // */ + // swapChildrenAt (index1: number, index2: number): void + // { + // this.swapChildren( + // this.getChildAt(index1), + // this.getChildAt(index2) + // ); + // } + + // /** + // * @param {array} [matrix=null] + // * @return {object} + // * @private + // */ + // _$getBounds (matrix: Float32Array | null = null): BoundsImpl + // { + // let multiMatrix: Float32Array = $MATRIX_ARRAY_IDENTITY; + // if (matrix) { + + // multiMatrix = matrix; + + // const rawMatrix: Float32Array = this._$transform._$rawMatrix(); + // if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 + // || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 + // || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 + // ) { + // multiMatrix = $multiplicationMatrix(matrix, rawMatrix); + // } + // } + + // const children: DisplayObjectImpl[] = this._$needsChildren + // ? this._$getChildren() + // : this._$children; + + // // size zero + // if (!children.length) { + + // const bounds: BoundsImpl = $getBoundsObject( + // multiMatrix[4], -multiMatrix[4], + // multiMatrix[5], -multiMatrix[5] + // ); + + // if (matrix && multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + + // return bounds; + // } + + // // data init + // const no = $Number.MAX_VALUE; + // let xMin = no; + // let xMax = -no; + // let yMin = no; + // let yMax = -no; + // for (let idx: number = 0; idx < children.length; ++idx) { + + // const bounds: BoundsImpl = children[idx]._$getBounds(multiMatrix); + + // xMin = $Math.min(xMin, bounds.xMin); + // xMax = $Math.max(xMax, bounds.xMax); + // yMin = $Math.min(yMin, bounds.yMin); + // yMax = $Math.max(yMax, bounds.yMax); + + // $poolBoundsObject(bounds); + + // } + + // if (matrix && multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + + // // end + // return $getBoundsObject(xMin, xMax, yMin, yMax); + // } + + // /** + // * @param {Float32Array} multi_matrix + // * @return {object} + // * @private + // */ + // _$getLayerBounds (multi_matrix: Float32Array): BoundsImpl + // { + + // const children: DisplayObjectImpl[] = this._$needsChildren + // ? this._$getChildren() + // : this._$children; + + // // size zero + // if (!children.length) { + // return $getBoundsObject(0, 0, 0, 0); + // } + + // // data init + // const no: number = $Number.MAX_VALUE; + // let xMin: number = no; + // let xMax: number = -no; + // let yMin: number = no; + // let yMax: number = -no; + // for (let idx: number = 0; idx < children.length; ++idx) { + + // const instance = children[idx]; + + // let multiMatrix = multi_matrix; + // const rawMatrix: Float32Array = instance._$transform._$rawMatrix(); + // if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 + // || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 + // || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 + // ) { + // multiMatrix = $multiplicationMatrix(multi_matrix, rawMatrix); + // } + + // const bounds: BoundsImpl = instance._$getLayerBounds(multiMatrix); + + // xMin = $Math.min(xMin, bounds.xMin); + // xMax = $Math.max(xMax, bounds.xMax); + // yMin = $Math.min(yMin, bounds.yMin); + // yMax = $Math.max(yMax, bounds.yMax); + + // $poolBoundsObject(bounds); + + // if (multiMatrix !== multi_matrix) { + // $poolFloat32Array6(multiMatrix); + // } + // } + + // const filters: FilterArrayImpl = this._$filters || this.filters; + // if (!filters.length) { + // return $getBoundsObject(xMin, xMax, yMin, yMax); + // } + + // let filterBounds: BoundsImpl = $getBoundsObject( + // 0, xMax - xMin, + // 0, yMax - yMin + // ); + + // let xScale: number = +$Math.sqrt( + // multi_matrix[0] * multi_matrix[0] + // + multi_matrix[1] * multi_matrix[1] + // ); + // let yScale: number = +$Math.sqrt( + // multi_matrix[2] * multi_matrix[2] + // + multi_matrix[3] * multi_matrix[3] + // ); + + // xScale /= $devicePixelRatio; + // yScale /= $devicePixelRatio; + + // xScale *= 2; + // yScale *= 2; + + // for (let idx: number = 0; idx < filters.length; ++idx) { + // filterBounds = filters[idx] + // ._$generateFilterRect(filterBounds, xScale, yScale); + // } + + // xMax += filterBounds.xMax - (xMax - xMin); + // yMax += filterBounds.yMax - (yMax - yMin); + // xMin += filterBounds.xMin; + // yMin += filterBounds.yMin; + + // $poolBoundsObject(filterBounds); + + // return $getBoundsObject(xMin, xMax, yMin, yMax); + // } + + // /** + // * @return {array} + // * @private + // */ + // _$getChildren (): DisplayObjectImpl[] + // { + // if (this._$needsChildren) { + + // // set flag + // this._$needsChildren = false; + + // const currentChildren: DisplayObjectImpl[] = this._$children; + // if (!this._$controller) { + // return currentChildren; + // } + + // const frame: number = "_$currentFrame" in this ? this._$currentFrame as number : 1; + // const controller: number[] = this._$controller[frame]; + + // // first build + // if (!currentChildren.length) { - if (useWorker) { - instance._$postProperty(); - } + // if (controller) { + + // for (let idx: number = 0; idx < controller.length; ++idx) { + + // const dictionaryId = controller[idx]; + // if (typeof dictionaryId !== "number") { + // continue; + // } + + // const instance: DisplayObjectImpl = this._$createInstance(dictionaryId); + // instance._$placeId = idx; + + // const loopConfig: LoopConfigImpl | null = instance.loopConfig; + // if (loopConfig) { + // instance._$currentFrame = instance + // ._$getLoopFrame(loopConfig); + // } + + // currentChildren.push(instance); + // if (instance._$name) { + // this._$names.set(instance._$name, instance); + // } + // } + // } + + // return currentChildren; + // } + + // const useWorker: boolean = !!$rendererWorker && !!this._$stage; + + // const skipIds: Map = $getMap(); + // const poolInstances: Map> = $getMap(); + + // let depth: number = 0; + // const children: DisplayObjectImpl[] = $getArray(); + // for (let idx: number = 0; idx < currentChildren.length; ++idx) { + + // const instance: DisplayObjectImpl = currentChildren[idx]; + + // const parent: ParentImpl = instance._$parent; + // if (!parent || parent._$instanceId !== this._$instanceId) { + // continue; + // } + + // const instanceId: number = instance._$instanceId; + // const startFrame: number = instance._$startFrame; + // const endFrame: number = instance._$endFrame; + // if (startFrame === 1 && endFrame === 0 + // || startFrame <= frame && endFrame > frame + // ) { + + // // reset + // instance._$isNext = true; + // instance._$placeObject = null; + // instance._$filters = null; + // instance._$blendMode = null; + + // if (instance._$id === -1) { + + // children.push(instance); + // if (instance._$name) { + // this._$names.set(instance._$name, instance); + // } + + // continue; + // } + + // const id: number = controller[depth]; + // if (instance._$id === id) { + + // instance._$placeId = depth; + // children.push(instance); + + // if (instance._$name) { + // this._$names.set(instance._$name, instance); + // } + + // if (poolInstances.has(id)) { + // poolInstances.delete(id); + // } + + // skipIds.set(id, true); + // depth++; + + // if (useWorker) { + // instance._$postProperty(); + // } + + // continue; + // } + + // poolInstances.set(instance._$id, instance); + + // continue; + // } + + // if (useWorker) { + // instance._$removeWorkerInstance(); + // } + + // $cacheStore.setRemoveTimer(instanceId); + // if (instance._$loaderInfo && instance._$characterId) { + // $cacheStore.setRemoveTimer( + // `${instance._$loaderInfo._$id}@${instance._$characterId}` + // ); + // } + // if (instance._$graphics) { + // $cacheStore.setRemoveTimer(instance._$graphics._$uniqueKey); + // } + + // // remove event + // if (instance.willTrigger(Next2DEvent.REMOVED)) { + // instance.dispatchEvent( + // new Next2DEvent(Next2DEvent.REMOVED, true) + // ); + // } + // if (instance.willTrigger(Next2DEvent.REMOVED_FROM_STAGE)) { + // instance.dispatchEvent( + // new Next2DEvent(Next2DEvent.REMOVED_FROM_STAGE, true) + // ); + // } + + // // reset + // instance._$added = false; + // instance._$addedStage = false; + // instance._$active = false; + // instance._$updated = true; + // instance._$filters = null; + // instance._$blendMode = null; + // instance._$isNext = true; + // instance._$placeObject = null; + // instance._$created = false; + // instance._$posted = false; + + // if (instance instanceof DisplayObjectContainer) { + // instance._$executeRemovedFromStage(); + // instance._$removeParentAndStage(); + // } + + // } + + // if (controller) { + + // for (let idx: number = 0; idx < controller.length; ++idx) { + + // const dictionaryId: number = controller[idx]; + // if (typeof dictionaryId !== "number" || skipIds.has(dictionaryId)) { + // continue; + // } + + // const instance: DisplayObjectImpl = poolInstances.has(dictionaryId) + // ? poolInstances.get(dictionaryId) + // : this._$createInstance(dictionaryId); + + // instance._$placeId = idx; + + // const loopConfig: LoopConfigImpl | null = instance.loopConfig; + // if (loopConfig) { + // instance._$currentFrame = instance + // ._$getLoopFrame(loopConfig); + // } + + // children.push(instance); + // if (instance._$name) { + // this._$names.set(instance._$name, instance); + // } + + // } + // } + + // // object pool + // $poolMap(skipIds); + // $poolMap(poolInstances); + + // // update + // currentChildren.length = 0; + // currentChildren.push(...children); + // $poolArray(children); + // } + + // return this._$children; + // } + + // /** + // * @return void + // * @private + // */ + // _$clearChildren (): void + // { + // this._$doChanged(); + // $doUpdated(); + + // // reset + // this._$names.clear(); + + // // clear + // this._$needsChildren = true; + // } + + // /** + // * @param {DisplayObject} child + // * @returns {DisplayObject} + // * @private + // */ + // _$addChild (child: DisplayObjectImpl): DisplayObjectImpl + // { + // // init + // child._$parent = this; + // if (!child._$stage || !child._$root) { + // child._$stage = this._$stage; + // child._$root = this._$root; + // } + + // // setup + // if (child instanceof DisplayObjectContainer) { + // child._$setParentAndStage(); + // child._$wait = true; + // } + + // // added event + // if (!child._$added) { + // if (child.willTrigger(Next2DEvent.ADDED)) { + // child.dispatchEvent( + // new Next2DEvent(Next2DEvent.ADDED, true) + // ); + // } + // child._$added = true; + // } + + // if (this._$stage !== null && !child._$addedStage) { + + // if (child.willTrigger(Next2DEvent.ADDED_TO_STAGE)) { + // child.dispatchEvent( + // new Next2DEvent(Next2DEvent.ADDED_TO_STAGE) + // ); + // } + + // child._$addedStage = true; + + // // set params + // if (child instanceof DisplayObjectContainer) { + // child._$executeAddedToStage(); + // } + + // if ($rendererWorker) { + // child._$createWorkerInstance(); + // this._$postChildrenIds(); + // } + // } + + // this._$doChanged(); + // child._$active = true; + // child._$updated = true; + // child._$isNext = true; + + // return child; + // } + + // /** + // * @return {void} + // * @method + // * @private + // */ + // _$setParentAndStage (): void + // { + // const children: DisplayObjectImpl[] = this._$needsChildren + // ? this._$getChildren() + // : this._$children; + + // for (let idx: number = 0; idx < children.length; ++idx) { + + // const instance: DisplayObjectImpl = children[idx]; + + // instance._$root = this._$root; + // instance._$stage = this._$stage; + + // if (instance instanceof DisplayObjectContainer) { + // instance._$setParentAndStage(); + // instance._$wait = true; + // } + + // } + // } + + // /** + // * @return {void} + // * @method + // * @private + // */ + // _$executeAddedToStage (): void + // { + // const children: DisplayObjectImpl[] = this._$needsChildren + // ? this._$getChildren() + // : this._$children; + + // const childrenIds: number[] = $getArray(); + + // for (let idx: number = 0; idx < children.length; ++idx) { + + // const instance: DisplayObjectImpl = children[idx]; + // if (!instance) { + // continue; + // } + + // childrenIds.push(instance._$instanceId); + // if (!instance._$addedStage) { + + // if ($rendererWorker) { + // instance._$createWorkerInstance(); + // } + + // if (instance.willTrigger(Next2DEvent.ADDED_TO_STAGE)) { + // instance.dispatchEvent( + // new Next2DEvent(Next2DEvent.ADDED_TO_STAGE) + // ); + // } + + // instance._$addedStage = true; + // } + + // if (instance instanceof DisplayObjectContainer) { + // instance._$executeAddedToStage(); + // } + + // } + + // if ($rendererWorker) { + // this._$postChildrenIds(childrenIds); + // } + + // $poolArray(childrenIds); + // } + + // /** + // * @param {DisplayObject} child + // * @param {boolean} do_event + // * @return {DisplayObject} + // * @private + // */ + // _$remove ( + // child: DisplayObjectImpl, + // do_event: boolean = true + // ): DisplayObjectImpl { + + // child._$transform._$transform(); + + // // remove all broadcast events + // if (child.hasEventListener(Next2DEvent.ENTER_FRAME)) { + // child.removeAllEventListener(Next2DEvent.ENTER_FRAME); + // } + + // if (child.hasEventListener(Next2DEvent.EXIT_FRAME)) { + // child.removeAllEventListener(Next2DEvent.EXIT_FRAME); + // } + + // if (child.hasEventListener(Next2DEvent.FRAME_CONSTRUCTED)) { + // child.removeAllEventListener(Next2DEvent.FRAME_CONSTRUCTED); + // } + + // if (child.hasEventListener(Next2DEvent.RENDER)) { + // child.removeAllEventListener(Next2DEvent.RENDER); + // } + + // if (child.hasEventListener(Next2DEvent.ACTIVATE)) { + // child.removeAllEventListener(Next2DEvent.ACTIVATE); + // } + + // if (child.hasEventListener(Next2DEvent.DEACTIVATE)) { + // child.removeAllEventListener(Next2DEvent.DEACTIVATE); + // } + + // if (child.hasEventListener("keyDown")) { + // child.removeAllEventListener("keyDown"); + // } + + // if (child.hasEventListener("keyUp")) { + // child.removeAllEventListener("keyUp"); + // } + + // // remove + // const children: DisplayObjectImpl[] = this._$needsChildren + // ? this._$getChildren() + // : this._$children; + + // const depth: number = this.getChildIndex(child); + // children.splice(depth, 1); + + // this._$names.delete(child.name); + // if (do_event) { + + // // event + // if (child.willTrigger(Next2DEvent.REMOVED)) { + // child.dispatchEvent( + // new Next2DEvent(Next2DEvent.REMOVED, true) + // ); + // } + + // // remove stage event + // if (this._$stage !== null) { + + // // worker側のDisplayObjectも削除 + // if ($rendererWorker) { + // child._$removeWorkerInstance(); + // this._$postChildrenIds(); + // } + + // if (child.willTrigger(Next2DEvent.REMOVED_FROM_STAGE)) { + // child.dispatchEvent( + // new Next2DEvent(Next2DEvent.REMOVED_FROM_STAGE) + // ); + // } + + // if (child instanceof DisplayObjectContainer) { + // child._$executeRemovedFromStage(); + // } + // } + + // $cacheStore.setRemoveTimer(child._$instanceId); + // if (child._$loaderInfo && child._$characterId) { + // $cacheStore.setRemoveTimer( + // `${child._$loaderInfo._$id}@${child._$characterId}` + // ); + // } + // if (child._$graphics) { + // $cacheStore.setRemoveTimer(child._$graphics._$uniqueKey); + // } + + // // reset params + // if (child instanceof DisplayObjectContainer) { + // child._$removeParentAndStage(); + // } + + // // reset + // child._$stage = null; + // child._$parent = null; + // child._$root = null; + // child._$active = false; + // child._$wait = true; + // child._$updated = true; + // child._$added = false; + // child._$addedStage = false; + // child._$created = false; + // child._$posted = false; + // this._$doChanged(); + + // } + + // return child; + // } + + // /** + // * @return {void} + // * @method + // * @private + // */ + // _$executeRemovedFromStage (): void + // { + // const children: DisplayObjectImpl[] = this._$getChildren().slice(0); + // for (let idx: number = 0; idx < children.length; ++idx) { + + // const instance: DisplayObjectImpl = children[idx]; + // if (!instance) { + // continue; + // } + + // if (instance._$addedStage) { + + // // workerのDisplayObjectを削除 + // if ($rendererWorker) { + // instance._$removeWorkerInstance(); + // } + + // if (instance.willTrigger(Next2DEvent.REMOVED_FROM_STAGE)) { + // instance.dispatchEvent( + // new Next2DEvent(Next2DEvent.REMOVED_FROM_STAGE) + // ); + // } + + // instance._$created = false; + // instance._$posted = false; + // instance._$addedStage = false; + // } + + // if (instance instanceof DisplayObjectContainer) { + // instance._$executeRemovedFromStage(); + // } + + // } + // } + + // /** + // * @return {void} + // * @method + // * @private + // */ + // _$removeParentAndStage (): void + // { + // const children: DisplayObjectImpl[] = this._$needsChildren + // ? this._$getChildren() + // : this._$children; + + // for (let idx: number = 0; idx < children.length; ++idx) { + + // const instance: DisplayObjectImpl = children[idx]; + + // $cacheStore.setRemoveTimer(instance._$instanceId); + // if (instance._$loaderInfo && instance._$characterId) { + // $cacheStore.setRemoveTimer( + // `${instance._$loaderInfo._$id}@${instance._$characterId}` + // ); + // } + // if (instance._$graphics) { + // $cacheStore.setRemoveTimer(instance._$graphics._$uniqueKey); + // } + + // if (instance instanceof DisplayObjectContainer) { + // instance._$removeParentAndStage(); + // } + + // instance._$stage = null; + // instance._$root = null; + // instance._$addedStage = false; + // } + + // if ("_$sounds" in this) { + // const soundsMap: Map = this._$sounds as Map; + // if (soundsMap.size) { + // for (const sounds of soundsMap.values()) { + // for (let idx: number = 0; idx < sounds.length; ++idx) { + // const sound: Sound = sounds[idx]; + // sound.stop(); + // } + // } + // } + // } + + // this._$needsChildren = true; + // } + + // /** + // * @return {void} + // * @method + // * @private + // */ + // _$prepareActions (): void + // { + // const children: DisplayObjectImpl[] = this._$needsChildren + // ? this._$getChildren() + // : this._$children; + + // for (let idx: number = children.length - 1; idx > -1; --idx) { + // children[idx]._$prepareActions(); + // } + + // // added event + // this._$executeAddedEvent(); + // } + + // /** + // * @return {boolean} + // * @method + // * @private + // */ + // _$nextFrame (): boolean + // { + // let isNext: boolean = false; + + // const children: DisplayObjectImpl[] = this._$getChildren(); + // for (let idx: number = children.length - 1; idx > -1; --idx) { + + // const child: DisplayObjectImpl = children[idx]; + // if (!child._$isNext) { + // continue; + // } + + // if (isNext) { + + // child._$nextFrame(); + + // } else { + + // isNext = child._$nextFrame(); + + // } + // } + + // // added event + // this._$executeAddedEvent(); + + // this._$isNext = isNext; + + // if (!this._$posted && $rendererWorker) { + // this._$postProperty(); + // } + + // return this._$isNext; + // } + + // /** + // * @param {CanvasToWebGLContext} context + // * @param {Float32Array} matrix + // * @return {void} + // * @method + // * @private + // */ + // _$clip ( + // context: CanvasToWebGLContext, + // matrix: Float32Array + // ): void { + + // let multiMatrix: Float32Array = matrix; + + // const rawMatrix: Float32Array = this._$transform._$rawMatrix(); + // if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 + // || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 + // || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 + // ) { + // multiMatrix = $multiplicationMatrix(matrix, rawMatrix); + // } + + // const children: DisplayObjectImpl[] = this._$getChildren(); + // for (let idx: number = 0; idx < children.length; ++idx) { + + // const instance: DisplayObjectImpl = children[idx]; + + // // mask instance + // if (instance._$isMask) { + // continue; + // } + + // instance._$clip(context, multiMatrix); + // instance._$updated = false; + + // } + + // if (multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + // } + + // /** + // * @param {CanvasToWebGLContext} context + // * @param {Float32Array} matrix + // * @return {object} + // * @private + // */ + // _$preDraw ( + // context: CanvasToWebGLContext, + // matrix: Float32Array + // ): PreObjectImpl | null { + + // let multiMatrix: Float32Array = matrix; + // const rawMatrix: Float32Array = this._$transform._$rawMatrix(); + // if (rawMatrix !== $MATRIX_HIT_ARRAY_IDENTITY + // && rawMatrix[0] !== 1 || rawMatrix[1] !== 0 + // || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 + // || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 + // ) { + // multiMatrix = $multiplicationMatrix(matrix, rawMatrix); + // } + + // // size zero + // if (!multiMatrix[0] && !multiMatrix[1] + // || !multiMatrix[2] && !multiMatrix[3] + // ) { + // if (multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + // return null; + // } + + // // return object + // const object: PreObjectImpl = $getPreObject(); + + // // setup + // object.matrix = multiMatrix; + + // // check + // const filters: FilterArrayImpl = this._$filters || this.filters; + // const blendMode: BlendModeImpl = this._$blendMode || this.blendMode; + // if (filters.length > 0 || blendMode !== "normal") { + + // // check size + // const baseBounds: BoundsImpl = this._$getBounds(null); + // const bounds: BoundsImpl = $boundsMatrix(baseBounds, multiMatrix); + // $poolBoundsObject(baseBounds); + + // const xMax: number = +bounds.xMax; + // const xMin: number = +bounds.xMin; + // const yMax: number = +bounds.yMax; + // const yMin: number = +bounds.yMin; + // $poolBoundsObject(bounds); + + // const width: number = $Math.ceil($Math.abs(xMax - xMin)); + // const height: number = $Math.ceil($Math.abs(yMax - yMin)); + // if (0 >= width || 0 >= height) { + // $poolPreObject(object); + // if (multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + // return null; + // } + + // let xScale: number = +$Math.sqrt( + // multiMatrix[0] * multiMatrix[0] + // + multiMatrix[1] * multiMatrix[1] + // ); + // if (!$Number.isInteger(xScale)) { + // const value: string = xScale.toString(); + // const index: number = value.indexOf("e"); + // if (index !== -1) { + // xScale = +value.slice(0, index); + // } + // xScale = +xScale.toFixed(4); + // } + + // let yScale: number = +$Math.sqrt( + // multiMatrix[2] * multiMatrix[2] + // + multiMatrix[3] * multiMatrix[3] + // ); + // if (!$Number.isInteger(yScale)) { + // const value: string = yScale.toString(); + // const index: number = value.indexOf("e"); + // if (index !== -1) { + // yScale = +value.slice(0, index); + // } + // yScale = +yScale.toFixed(4); + // } + + // object.canApply = this._$canApply(filters); + // let filterBounds: BoundsImpl = $getBoundsObject(0, width, 0, height); + // if (object.canApply && filters) { + // for (let idx: number = 0; idx < filters.length ; ++idx) { + // filterBounds = filters[idx] + // ._$generateFilterRect(filterBounds, xScale, yScale); + // } + // } + + // const currentAttachment: AttachmentImpl | null = context + // .frameBuffer + // .currentAttachment; + + // if (!currentAttachment + // || !currentAttachment.texture + // || xMin - filterBounds.xMin > currentAttachment.width + // || yMin - filterBounds.yMin > currentAttachment.height + // ) { + // $poolBoundsObject(filterBounds); + // $poolPreObject(object); + // if (multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + // return null; + // } + + // if (0 > xMin + filterBounds.xMax || 0 > yMin + filterBounds.yMax) { + // $poolBoundsObject(filterBounds); + // $poolPreObject(object); + // if (multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + // return null; + // } + + // // move size + // let tx: number = multiMatrix[4] - xMin; + // let ty: number = multiMatrix[5] - yMin; + + // // start layer + // context._$startLayer( + // $getBoundsObject(xMin, xMax, yMin, yMax) + // ); + + // // check cache + // const updated: boolean = this._$isFilterUpdated( + // multiMatrix, filters, object.canApply + // ); + + // const layerBounds: BoundsImpl = this._$getLayerBounds(multiMatrix); + + // const layerWidth: number = $Math.ceil($Math.abs(layerBounds.xMax - layerBounds.xMin)); + // const layerHeight: number = $Math.ceil($Math.abs(layerBounds.yMax - layerBounds.yMin)); + // $poolBoundsObject(layerBounds); + + // const sw = layerWidth - filterBounds.xMax + filterBounds.xMin; + // const sh = layerHeight - filterBounds.yMax + filterBounds.yMin; + + // tx += sw; + // ty += sh; + + // object.sw = sw; + // object.sh = sh; + // if (updated) { + // context._$saveAttachment( + // $Math.ceil(width + sw), + // $Math.ceil(height + sh), + // true + // ); + // } + + // // setup + // object.isLayer = true; + // object.isUpdated = updated; + // object.filters = filters; + // object.blendMode = blendMode; + // object.color = $getFloat32Array8(); + // object.matrix = $getFloat32Array6( + // multiMatrix[0], multiMatrix[1], + // multiMatrix[2], multiMatrix[3], + // tx, ty + // ); + + // if (multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + + // $poolBoundsObject(filterBounds); + // } + + // return object; + // } + + // /** + // * @param {CanvasToWebGLContext} context + // * @param {Float32Array} matrix + // * @param {Float32Array} color_transform + // * @param {object} object + // * @return {void} + // * @method + // * @private + // */ + // _$postDraw ( + // context: CanvasToWebGLContext, + // matrix: Float32Array, + // color_transform: Float32Array, + // object: PreObjectImpl + // ): void { + + // context.drawInstacedArray(); + + // // cache + // const cacheKeys: any[] = $getArray(this._$instanceId, "f"); + + // const manager: FrameBufferManager = context.frameBuffer; + // const multiMatrix: Float32Array = object.matrix as NonNullable; + + // let offsetX: number = 0; + // let offsetY: number = 0; + // let texture: WebGLTexture | null = $cacheStore.get(cacheKeys); + + // if (!texture || object.isUpdated) { + + // // remove + // if (texture) { + // $cacheStore.set(cacheKeys, null); + // } + + // texture = manager + // .getTextureFromCurrentAttachment(); + + // const filters: FilterArrayImpl | null = object.filters; + // let filterState = false; + // if (filters && filters.length) { + + // for (let idx: number = 0; idx < filters.length; ++idx) { + // texture = filters[idx] + // ._$applyFilter(context, matrix); + // } + + // // update + // filterState = true; + // offsetX = context._$offsetX; + // offsetY = context._$offsetY; + + // // reset + // context._$offsetX = 0; + // context._$offsetY = 0; + // } + + // texture.filterState = filterState; + // texture.matrix = `${multiMatrix[0]}_` + // + `${multiMatrix[1]}_` + // + `${multiMatrix[2]}_` + // + `${multiMatrix[3]}`; + + // texture.offsetX = offsetX; + // texture.offsetY = offsetY; + + // $cacheStore.set(cacheKeys, texture); + + // context._$restoreAttachment(); + // } + + // if (texture.offsetX) { + // offsetX = texture.offsetX; + // } + + // if (texture.offsetY) { + // offsetY = texture.offsetY; + // } + + // // set + // context.reset(); + // context.globalAlpha = $clamp( + // color_transform[3] + color_transform[7] / 255, 0, 1 + // ); + // context.globalCompositeOperation = object.blendMode; + + // const bounds: BoundsImpl = context.getCurrentPosition(); + + // context.setTransform( + // 1, 0, 0, 1, + // bounds.xMin - offsetX - object.sw, + // bounds.yMin - offsetY - object.sh + // ); + + // context.drawImage(texture, + // 0, 0, texture.width, texture.height, + // color_transform + // ); + + // // end blend + // context._$endLayer(); + + // // object pool + // $poolFloat32Array6(object.matrix as NonNullable); + // $poolPreObject(object); + + // // reset + // context.cachePosition = null; + // } + + // /** + // * @param {CanvasToWebGLContext} context + // * @param {Float32Array} matrix + // * @param {Float32Array} color_transform + // * @return {void} + // * @method + // * @private + // */ + // _$draw ( + // context: CanvasToWebGLContext, + // matrix: Float32Array, + // color_transform: Float32Array + // ): void { + + // // not draw + // if (!this._$visible) { + // return ; + // } + + // const transform: Transform = this._$transform; + + // let multiColor: Float32Array = color_transform; + // const rawColor: Float32Array = transform._$rawColorTransform(); + // if (rawColor !== $COLOR_ARRAY_IDENTITY + // && rawColor[0] !== 1 || rawColor[1] !== 1 + // || rawColor[2] !== 1 || rawColor[3] !== 1 + // || rawColor[4] !== 0 || rawColor[5] !== 0 + // || rawColor[6] !== 0 || rawColor[7] !== 0 + // ) { + // multiColor = $multiplicationColor(color_transform, rawColor); + // } + + // // not draw + // const alpha: number = $clamp(multiColor[3] + multiColor[7] / 255, 0, 1, 0); + // if (!alpha) { + // return ; + // } + + // // not draw + // const children: DisplayObjectImpl[] = this._$getChildren(); + // const length: number = children.length; + // if (!length) { + // return ; + // } + + // // pre data + // const preObject: PreObjectImpl | null = this._$preDraw(context, matrix); + // if (!preObject) { + // return ; + // } + + // // use cache + // if (preObject.isLayer && !preObject.isUpdated) { + // this._$postDraw(context, matrix, multiColor, preObject); + // return ; + // } + + // const preMatrix: Float32Array = preObject.matrix as NonNullable; + + // const preColorTransform: Float32Array = preObject.isLayer && preObject.color + // ? preObject.color + // : multiColor; + + // // init clip params + // let shouldClip: boolean = true; + // let clipDepth: number = 0; + + // const player: Player = $currentPlayer(); + + // // draw children + // const isLayer: boolean = context.isLayer; + // const isUpdate: boolean = this._$isUpdated(); + // for (let idx: number = 0; idx < length; ++idx) { + + // const instance = children[idx]; + + // if (isUpdate) { + // instance._$placeObject = null; + // } + + // // mask instance + // if (instance._$isMask) { + // continue; + // } + + // // not layer mode + // const blendMode: BlendModeImpl = instance._$blendMode || instance.blendMode; + // if ((blendMode === "alpha" || blendMode === "erase") + // && !isLayer + // ) { + // continue; + // } + + // // mask end + // if (clipDepth + // && (instance._$placeId > clipDepth || instance._$clipDepth > 0) + // ) { + + // context.restore(); + + // if (shouldClip) { + // context._$leaveClip(); + // } + + // // clear + // clipDepth = 0; + // shouldClip = true; + // } + + // // mask size 0 + // if (!shouldClip) { + // continue; + // } - continue; - } + // // mask start + // if (instance._$clipDepth > 0) { - poolInstances.set(instance._$id, instance); + // clipDepth = instance._$clipDepth; + // shouldClip = instance._$shouldClip(preMatrix); - continue; - } - - if (useWorker) { - instance._$removeWorkerInstance(); - } - - $cacheStore.setRemoveTimer(instanceId); - if (instance._$loaderInfo && instance._$characterId) { - $cacheStore.setRemoveTimer( - `${instance._$loaderInfo._$id}@${instance._$characterId}` - ); - } - if (instance._$graphics) { - $cacheStore.setRemoveTimer(instance._$graphics._$uniqueKey); - } - - // remove event - if (instance.willTrigger(Next2DEvent.REMOVED)) { - instance.dispatchEvent( - new Next2DEvent(Next2DEvent.REMOVED, true) - ); - } - if (instance.willTrigger(Next2DEvent.REMOVED_FROM_STAGE)) { - instance.dispatchEvent( - new Next2DEvent(Next2DEvent.REMOVED_FROM_STAGE, true) - ); - } - - // reset - instance._$added = false; - instance._$addedStage = false; - instance._$active = false; - instance._$updated = true; - instance._$filters = null; - instance._$blendMode = null; - instance._$isNext = true; - instance._$placeObject = null; - instance._$created = false; - instance._$posted = false; - - if (instance instanceof DisplayObjectContainer) { - instance._$executeRemovedFromStage(); - instance._$removeParentAndStage(); - } - - } - - if (controller) { - - for (let idx: number = 0; idx < controller.length; ++idx) { - - const dictionaryId: number = controller[idx]; - if (typeof dictionaryId !== "number" || skipIds.has(dictionaryId)) { - continue; - } + // if (shouldClip) { + // context.save(); + // shouldClip = instance._$startClip(context, preMatrix); + // } - const instance: DisplayObjectImpl = poolInstances.has(dictionaryId) - ? poolInstances.get(dictionaryId) - : this._$createInstance(dictionaryId); + // continue; + // } - instance._$placeId = idx; + // // mask start + // const maskInstance: DisplayObjectImpl | null = instance._$mask; + // if (maskInstance) { - const loopConfig: LoopConfigImpl | null = instance.loopConfig; - if (loopConfig) { - instance._$currentFrame = instance - ._$getLoopFrame(loopConfig); - } + // maskInstance._$updated = false; + + // let maskMatrix: Float32Array; + + // if (this === maskInstance._$parent) { + + // maskMatrix = preMatrix; + + // } else { + + // maskMatrix = $MATRIX_ARRAY_IDENTITY; + + // let parent: ParentImpl | null = maskInstance._$parent; + // while (parent) { - children.push(instance); - if (instance._$name) { - this._$names.set(instance._$name, instance); - } + // maskMatrix = $multiplicationMatrix( + // parent._$transform._$rawMatrix(), + // maskMatrix + // ); - } - } + // parent = parent._$parent; + // } - // object pool - $poolMap(skipIds); - $poolMap(poolInstances); + // const mScale: number = player.scaleX; + // const playerMatrix: Float32Array = $getFloat32Array6( + // mScale, 0, 0, mScale, 0, 0 + // ); - // update - currentChildren.length = 0; - currentChildren.push(...children); - $poolArray(children); - } + // maskMatrix = $multiplicationMatrix( + // playerMatrix, maskMatrix + // ); + // $poolFloat32Array6(playerMatrix); - return this._$children; - } + // if (context.isLayer) { + // const currentPosition: BoundsImpl = context.getCurrentPosition(); + // maskMatrix[4] -= currentPosition.xMin; + // maskMatrix[5] -= currentPosition.yMin; + // } + + // } + + // if (!maskInstance._$shouldClip(maskMatrix)) { + // continue; + // } + + // const result: boolean = maskInstance._$startClip(context, maskMatrix); + + // context.save(); + + // if (!result) { // fixed + // context.restore(); + // continue; + // } + + // } - /** - * @return void - * @private - */ - _$clearChildren (): void - { - this._$doChanged(); - $doUpdated(); + // instance._$draw(context, preMatrix, preColorTransform); + // instance._$updated = false; - // reset - this._$names.clear(); + // // mask end + // if (maskInstance) { + // context.restore(); + // context._$leaveClip(); + // } + // } - // clear - this._$needsChildren = true; - } + // // end mask + // if (clipDepth) { + // context.restore(); - /** - * @param {DisplayObject} child - * @returns {DisplayObject} - * @private - */ - _$addChild (child: DisplayObjectImpl): DisplayObjectImpl - { - // init - child._$parent = this; - if (!child._$stage || !child._$root) { - child._$stage = this._$stage; - child._$root = this._$root; - } - - // setup - if (child instanceof DisplayObjectContainer) { - child._$setParentAndStage(); - child._$wait = true; - } - - // added event - if (!child._$added) { - if (child.willTrigger(Next2DEvent.ADDED)) { - child.dispatchEvent( - new Next2DEvent(Next2DEvent.ADDED, true) - ); - } - child._$added = true; - } + // if (shouldClip) { + // context._$leaveClip(); + // } + // } - if (this._$stage !== null && !child._$addedStage) { + // // filter and blend + // if (preObject.isLayer) { + // return this._$postDraw(context, matrix, multiColor, preObject); + // } - if (child.willTrigger(Next2DEvent.ADDED_TO_STAGE)) { - child.dispatchEvent( - new Next2DEvent(Next2DEvent.ADDED_TO_STAGE) - ); - } + // if (preObject.matrix !== matrix) { + // $poolFloat32Array6(preObject.matrix as NonNullable); + // } - child._$addedStage = true; + // if (multiColor !== color_transform) { + // $poolFloat32Array8(multiColor); + // } - // set params - if (child instanceof DisplayObjectContainer) { - child._$executeAddedToStage(); - } + // $poolPreObject(preObject); + // } - if ($rendererWorker) { - child._$createWorkerInstance(); - this._$postChildrenIds(); - } - } + // /** + // * @param {CanvasRenderingContext2D} context + // * @param {Float32Array} matrix + // * @param {object} options + // * @param {boolean} [mouse_children=true] + // * @return {boolean} + // * @method + // * @private + // */ + // _$mouseHit ( + // context: CanvasRenderingContext2D, + // matrix: Float32Array, + // options: PlayerHitObjectImpl, + // mouse_children: boolean = true + // ): boolean { - this._$doChanged(); - child._$active = true; - child._$updated = true; - child._$isNext = true; + // let multiMatrix: Float32Array = matrix; + // const rawMatrix: Float32Array = this._$transform._$rawMatrix(); + // if (rawMatrix !== $MATRIX_ARRAY_IDENTITY) { + // multiMatrix = $multiplicationMatrix(matrix, rawMatrix); + // } - return child; - } + // const children: DisplayObjectImpl[] = this._$getChildren(); - /** - * @return {void} - * @method - * @private - */ - _$setParentAndStage (): void - { - const children: DisplayObjectImpl[] = this._$needsChildren - ? this._$getChildren() - : this._$children; + // // mask set + // const clips: DisplayObjectImpl[] = $getArray(); + // const targets: DisplayObjectImpl[] = $getArray(); + // const clipIndexes: Map = $getMap(); - for (let idx: number = 0; idx < children.length; ++idx) { + // let clipDepth: number = 0; + // let clipIdx: number = 0; + // for (let idx: number = 0; idx < children.length; ++idx) { - const instance: DisplayObjectImpl = children[idx]; + // const instance: DisplayObjectImpl = children[idx]; - instance._$root = this._$root; - instance._$stage = this._$stage; + // if (!instance._$visible && !instance._$hitObject) { + // continue; + // } - if (instance instanceof DisplayObjectContainer) { - instance._$setParentAndStage(); - instance._$wait = true; - } + // if (instance._$clipDepth) { + // clipIdx = clips.length; + // clipDepth = instance._$clipDepth; + // clips.push(instance); + // continue; + // } - } - } + // // clip end + // if (clipDepth && instance._$placeId > clipDepth) { + // clipIdx = 0; + // clipDepth = 0; + // } - /** - * @return {void} - * @method - * @private - */ - _$executeAddedToStage (): void - { - const children: DisplayObjectImpl[] = this._$needsChildren - ? this._$getChildren() - : this._$children; + // // clip check on + // if (clipIdx) { + // clipIndexes.set(instance._$instanceId, clipIdx); + // } - const childrenIds: number[] = $getArray(); + // targets.push(instance); + + // } + + // // setup + // const mouseChildren: boolean = this._$mouseChildren && mouse_children; + + // let hit: boolean = false; + // const isRoot = this._$root === this; + + // while (targets.length) { + + // const instance: DisplayObjectImpl = targets.pop(); + // if (instance._$isMask) { + // continue; + // } - for (let idx: number = 0; idx < children.length; ++idx) { + // if (isRoot && !(instance instanceof InteractiveObject)) { + // continue; + // } - const instance: DisplayObjectImpl = children[idx]; - if (!instance) { - continue; - } + // // mask target + // if (clipIndexes.has(instance._$instanceId)) { - childrenIds.push(instance._$instanceId); - if (!instance._$addedStage) { + // const index: number | void = clipIndexes.get(instance._$instanceId); + // if (!index) { + // continue; + // } - if ($rendererWorker) { - instance._$createWorkerInstance(); - } + // const clip: DisplayObjectImpl = clips[index]; + // if (!clip._$hit(context, multiMatrix, options, true)) { + // continue; + // } - if (instance.willTrigger(Next2DEvent.ADDED_TO_STAGE)) { - instance.dispatchEvent( - new Next2DEvent(Next2DEvent.ADDED_TO_STAGE) - ); - } + // } - instance._$addedStage = true; - } + // // mask hit test + // const maskInstance: DisplayObjectImpl | null = instance._$mask; + // if (maskInstance) { - if (instance instanceof DisplayObjectContainer) { - instance._$executeAddedToStage(); - } + // if (this === maskInstance._$parent) { - } + // if (!maskInstance._$hit(context, multiMatrix, options, true)) { + // continue; + // } - if ($rendererWorker) { - this._$postChildrenIds(childrenIds); - } + // } else { - $poolArray(childrenIds); - } + // let maskMatrix: Float32Array = $MATRIX_ARRAY_IDENTITY; - /** - * @param {DisplayObject} child - * @param {boolean} do_event - * @return {DisplayObject} - * @private - */ - _$remove ( - child: DisplayObjectImpl, - do_event: boolean = true - ): DisplayObjectImpl { - - child._$transform._$transform(); - - // remove all broadcast events - if (child.hasEventListener(Next2DEvent.ENTER_FRAME)) { - child.removeAllEventListener(Next2DEvent.ENTER_FRAME); - } - - if (child.hasEventListener(Next2DEvent.EXIT_FRAME)) { - child.removeAllEventListener(Next2DEvent.EXIT_FRAME); - } - - if (child.hasEventListener(Next2DEvent.FRAME_CONSTRUCTED)) { - child.removeAllEventListener(Next2DEvent.FRAME_CONSTRUCTED); - } - - if (child.hasEventListener(Next2DEvent.RENDER)) { - child.removeAllEventListener(Next2DEvent.RENDER); - } - - if (child.hasEventListener(Next2DEvent.ACTIVATE)) { - child.removeAllEventListener(Next2DEvent.ACTIVATE); - } - - if (child.hasEventListener(Next2DEvent.DEACTIVATE)) { - child.removeAllEventListener(Next2DEvent.DEACTIVATE); - } - - if (child.hasEventListener("keyDown")) { - child.removeAllEventListener("keyDown"); - } - - if (child.hasEventListener("keyUp")) { - child.removeAllEventListener("keyUp"); - } - - // remove - const children: DisplayObjectImpl[] = this._$needsChildren - ? this._$getChildren() - : this._$children; - - const depth: number = this.getChildIndex(child); - children.splice(depth, 1); - - this._$names.delete(child.name); - if (do_event) { - - // event - if (child.willTrigger(Next2DEvent.REMOVED)) { - child.dispatchEvent( - new Next2DEvent(Next2DEvent.REMOVED, true) - ); - } + // let parent: ParentImpl | null = maskInstance._$parent; + // while (parent) { - // remove stage event - if (this._$stage !== null) { + // maskMatrix = $multiplicationMatrix( + // parent._$transform._$rawMatrix(), + // maskMatrix + // ); - // worker側のDisplayObjectも削除 - if ($rendererWorker) { - child._$removeWorkerInstance(); - this._$postChildrenIds(); - } + // parent = parent._$parent; + // } - if (child.willTrigger(Next2DEvent.REMOVED_FROM_STAGE)) { - child.dispatchEvent( - new Next2DEvent(Next2DEvent.REMOVED_FROM_STAGE) - ); - } + // if (!maskInstance._$hit(context, maskMatrix, options, true)) { + // continue; + // } - if (child instanceof DisplayObjectContainer) { - child._$executeRemovedFromStage(); - } - } + // } - $cacheStore.setRemoveTimer(child._$instanceId); - if (child._$loaderInfo && child._$characterId) { - $cacheStore.setRemoveTimer( - `${child._$loaderInfo._$id}@${child._$characterId}` - ); - } - if (child._$graphics) { - $cacheStore.setRemoveTimer(child._$graphics._$uniqueKey); - } + // } - // reset params - if (child instanceof DisplayObjectContainer) { - child._$removeParentAndStage(); - } + // if (instance._$mouseHit(context, multiMatrix, options, mouseChildren) + // || instance._$hitArea + // && instance + // ._$hitArea + // ._$mouseHit(context, multiMatrix, options, mouseChildren) + // ) { - // reset - child._$stage = null; - child._$parent = null; - child._$root = null; - child._$active = false; - child._$wait = true; - child._$updated = true; - child._$added = false; - child._$addedStage = false; - child._$created = false; - child._$posted = false; - this._$doChanged(); - - } - - return child; - } + // if (instance._$root === instance) { + // return true; + // } - /** - * @return {void} - * @method - * @private - */ - _$executeRemovedFromStage (): void - { - const children: DisplayObjectImpl[] = this._$getChildren().slice(0); - for (let idx: number = 0; idx < children.length; ++idx) { + // if (!mouseChildren) { + // return true; + // } - const instance: DisplayObjectImpl = children[idx]; - if (!instance) { - continue; - } + // hit = true; + // if (instance instanceof InteractiveObject) { - if (instance._$addedStage) { + // if (!instance.mouseEnabled && !instance._$hitObject) { + // continue; + // } - // workerのDisplayObjectを削除 - if ($rendererWorker) { - instance._$removeWorkerInstance(); - } + // if (!$isTouch && !options.pointer) { - if (instance.willTrigger(Next2DEvent.REMOVED_FROM_STAGE)) { - instance.dispatchEvent( - new Next2DEvent(Next2DEvent.REMOVED_FROM_STAGE) - ); - } + // if ("_$text" in instance + // && "type" in instance + // && instance.type === "input" + // ) { + // options.pointer = "text"; + // } - instance._$created = false; - instance._$posted = false; - instance._$addedStage = false; - } + // if ("buttonMode" in instance + // && "useHandCursor" in instance + // && instance.buttonMode + // && instance.useHandCursor + // ) { + // options.pointer = "pointer"; + // } + + // } - if (instance instanceof DisplayObjectContainer) { - instance._$executeRemovedFromStage(); - } - - } - } - - /** - * @return {void} - * @method - * @private - */ - _$removeParentAndStage (): void - { - const children: DisplayObjectImpl[] = this._$needsChildren - ? this._$getChildren() - : this._$children; - - for (let idx: number = 0; idx < children.length; ++idx) { - - const instance: DisplayObjectImpl = children[idx]; - - $cacheStore.setRemoveTimer(instance._$instanceId); - if (instance._$loaderInfo && instance._$characterId) { - $cacheStore.setRemoveTimer( - `${instance._$loaderInfo._$id}@${instance._$characterId}` - ); - } - if (instance._$graphics) { - $cacheStore.setRemoveTimer(instance._$graphics._$uniqueKey); - } - - if (instance instanceof DisplayObjectContainer) { - instance._$removeParentAndStage(); - } - - instance._$stage = null; - instance._$root = null; - instance._$addedStage = false; - } - - if ("_$sounds" in this) { - const soundsMap: Map = this._$sounds as Map; - if (soundsMap.size) { - for (const sounds of soundsMap.values()) { - for (let idx: number = 0; idx < sounds.length; ++idx) { - const sound: Sound = sounds[idx]; - sound.stop(); - } - } - } - } - - this._$needsChildren = true; - } - - /** - * @return {void} - * @method - * @private - */ - _$prepareActions (): void - { - const children: DisplayObjectImpl[] = this._$needsChildren - ? this._$getChildren() - : this._$children; - - for (let idx: number = children.length - 1; idx > -1; --idx) { - children[idx]._$prepareActions(); - } - - // added event - this._$executeAddedEvent(); - } - - /** - * @return {boolean} - * @method - * @private - */ - _$nextFrame (): boolean - { - let isNext: boolean = false; - - const children: DisplayObjectImpl[] = this._$getChildren(); - for (let idx: number = children.length - 1; idx > -1; --idx) { - - const child: DisplayObjectImpl = children[idx]; - if (!child._$isNext) { - continue; - } - - if (isNext) { - - child._$nextFrame(); - - } else { - - isNext = child._$nextFrame(); - - } - } - - // added event - this._$executeAddedEvent(); - - this._$isNext = isNext; - - if (!this._$posted && $rendererWorker) { - this._$postProperty(); - } - - return this._$isNext; - } - - /** - * @param {CanvasToWebGLContext} context - * @param {Float32Array} matrix - * @return {void} - * @method - * @private - */ - _$clip ( - context: CanvasToWebGLContext, - matrix: Float32Array - ): void { - - let multiMatrix: Float32Array = matrix; - - const rawMatrix: Float32Array = this._$transform._$rawMatrix(); - if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 - || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 - || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 - ) { - multiMatrix = $multiplicationMatrix(matrix, rawMatrix); - } - - const children: DisplayObjectImpl[] = this._$getChildren(); - for (let idx: number = 0; idx < children.length; ++idx) { - - const instance: DisplayObjectImpl = children[idx]; - - // mask instance - if (instance._$isMask) { - continue; - } - - instance._$clip(context, multiMatrix); - instance._$updated = false; - - } - - if (multiMatrix !== matrix) { - $poolFloat32Array6(multiMatrix); - } - } - - /** - * @param {CanvasToWebGLContext} context - * @param {Float32Array} matrix - * @return {object} - * @private - */ - _$preDraw ( - context: CanvasToWebGLContext, - matrix: Float32Array - ): PreObjectImpl | null { - - let multiMatrix: Float32Array = matrix; - const rawMatrix: Float32Array = this._$transform._$rawMatrix(); - if (rawMatrix !== $MATRIX_HIT_ARRAY_IDENTITY - && rawMatrix[0] !== 1 || rawMatrix[1] !== 0 - || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 - || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 - ) { - multiMatrix = $multiplicationMatrix(matrix, rawMatrix); - } - - // size zero - if (!multiMatrix[0] && !multiMatrix[1] - || !multiMatrix[2] && !multiMatrix[3] - ) { - if (multiMatrix !== matrix) { - $poolFloat32Array6(multiMatrix); - } - return null; - } - - // return object - const object: PreObjectImpl = $getPreObject(); - - // setup - object.matrix = multiMatrix; - - // check - const filters: FilterArrayImpl = this._$filters || this.filters; - const blendMode: BlendModeImpl = this._$blendMode || this.blendMode; - if (filters.length > 0 || blendMode !== "normal") { - - // check size - const baseBounds: BoundsImpl = this._$getBounds(null); - const bounds: BoundsImpl = $boundsMatrix(baseBounds, multiMatrix); - $poolBoundsObject(baseBounds); - - const xMax: number = +bounds.xMax; - const xMin: number = +bounds.xMin; - const yMax: number = +bounds.yMax; - const yMin: number = +bounds.yMin; - $poolBoundsObject(bounds); - - const width: number = $Math.ceil($Math.abs(xMax - xMin)); - const height: number = $Math.ceil($Math.abs(yMax - yMin)); - if (0 >= width || 0 >= height) { - $poolPreObject(object); - if (multiMatrix !== matrix) { - $poolFloat32Array6(multiMatrix); - } - return null; - } - - let xScale: number = +$Math.sqrt( - multiMatrix[0] * multiMatrix[0] - + multiMatrix[1] * multiMatrix[1] - ); - if (!$Number.isInteger(xScale)) { - const value: string = xScale.toString(); - const index: number = value.indexOf("e"); - if (index !== -1) { - xScale = +value.slice(0, index); - } - xScale = +xScale.toFixed(4); - } - - let yScale: number = +$Math.sqrt( - multiMatrix[2] * multiMatrix[2] - + multiMatrix[3] * multiMatrix[3] - ); - if (!$Number.isInteger(yScale)) { - const value: string = yScale.toString(); - const index: number = value.indexOf("e"); - if (index !== -1) { - yScale = +value.slice(0, index); - } - yScale = +yScale.toFixed(4); - } - - object.canApply = this._$canApply(filters); - let filterBounds: BoundsImpl = $getBoundsObject(0, width, 0, height); - if (object.canApply && filters) { - for (let idx: number = 0; idx < filters.length ; ++idx) { - filterBounds = filters[idx] - ._$generateFilterRect(filterBounds, xScale, yScale); - } - } - - const currentAttachment: AttachmentImpl | null = context - .frameBuffer - .currentAttachment; - - if (!currentAttachment - || !currentAttachment.texture - || xMin - filterBounds.xMin > currentAttachment.width - || yMin - filterBounds.yMin > currentAttachment.height - ) { - $poolBoundsObject(filterBounds); - $poolPreObject(object); - if (multiMatrix !== matrix) { - $poolFloat32Array6(multiMatrix); - } - return null; - } - - if (0 > xMin + filterBounds.xMax || 0 > yMin + filterBounds.yMax) { - $poolBoundsObject(filterBounds); - $poolPreObject(object); - if (multiMatrix !== matrix) { - $poolFloat32Array6(multiMatrix); - } - return null; - } - - // move size - let tx: number = multiMatrix[4] - xMin; - let ty: number = multiMatrix[5] - yMin; - - // start layer - context._$startLayer( - $getBoundsObject(xMin, xMax, yMin, yMax) - ); - - // check cache - const updated: boolean = this._$isFilterUpdated( - multiMatrix, filters, object.canApply - ); - - const layerBounds: BoundsImpl = this._$getLayerBounds(multiMatrix); - - const layerWidth: number = $Math.ceil($Math.abs(layerBounds.xMax - layerBounds.xMin)); - const layerHeight: number = $Math.ceil($Math.abs(layerBounds.yMax - layerBounds.yMin)); - $poolBoundsObject(layerBounds); - - const sw = layerWidth - filterBounds.xMax + filterBounds.xMin; - const sh = layerHeight - filterBounds.yMax + filterBounds.yMin; - - tx += sw; - ty += sh; - - object.sw = sw; - object.sh = sh; - if (updated) { - context._$saveAttachment( - $Math.ceil(width + sw), - $Math.ceil(height + sh), - true - ); - } - - // setup - object.isLayer = true; - object.isUpdated = updated; - object.filters = filters; - object.blendMode = blendMode; - object.color = $getFloat32Array8(); - object.matrix = $getFloat32Array6( - multiMatrix[0], multiMatrix[1], - multiMatrix[2], multiMatrix[3], - tx, ty - ); - - if (multiMatrix !== matrix) { - $poolFloat32Array6(multiMatrix); - } - - $poolBoundsObject(filterBounds); - } - - return object; - } - - /** - * @param {CanvasToWebGLContext} context - * @param {Float32Array} matrix - * @param {Float32Array} color_transform - * @param {object} object - * @return {void} - * @method - * @private - */ - _$postDraw ( - context: CanvasToWebGLContext, - matrix: Float32Array, - color_transform: Float32Array, - object: PreObjectImpl - ): void { - - context.drawInstacedArray(); - - // cache - const cacheKeys: any[] = $getArray(this._$instanceId, "f"); - - const manager: FrameBufferManager = context.frameBuffer; - const multiMatrix: Float32Array = object.matrix as NonNullable; - - let offsetX: number = 0; - let offsetY: number = 0; - let texture: WebGLTexture | null = $cacheStore.get(cacheKeys); - - if (!texture || object.isUpdated) { - - // remove - if (texture) { - $cacheStore.set(cacheKeys, null); - } - - texture = manager - .getTextureFromCurrentAttachment(); - - const filters: FilterArrayImpl | null = object.filters; - let filterState = false; - if (filters && filters.length) { - - for (let idx: number = 0; idx < filters.length; ++idx) { - texture = filters[idx] - ._$applyFilter(context, matrix); - } - - // update - filterState = true; - offsetX = context._$offsetX; - offsetY = context._$offsetY; - - // reset - context._$offsetX = 0; - context._$offsetY = 0; - } - - texture.filterState = filterState; - texture.matrix = `${multiMatrix[0]}_` - + `${multiMatrix[1]}_` - + `${multiMatrix[2]}_` - + `${multiMatrix[3]}`; - - texture.offsetX = offsetX; - texture.offsetY = offsetY; - - $cacheStore.set(cacheKeys, texture); - - context._$restoreAttachment(); - } - - if (texture.offsetX) { - offsetX = texture.offsetX; - } - - if (texture.offsetY) { - offsetY = texture.offsetY; - } - - // set - context.reset(); - context.globalAlpha = $clamp( - color_transform[3] + color_transform[7] / 255, 0, 1 - ); - context.globalCompositeOperation = object.blendMode; - - const bounds: BoundsImpl = context.getCurrentPosition(); - - context.setTransform( - 1, 0, 0, 1, - bounds.xMin - offsetX - object.sw, - bounds.yMin - offsetY - object.sh - ); - - context.drawImage(texture, - 0, 0, texture.width, texture.height, - color_transform - ); - - // end blend - context._$endLayer(); - - // object pool - $poolFloat32Array6(object.matrix as NonNullable); - $poolPreObject(object); - - // reset - context.cachePosition = null; - } - - /** - * @param {CanvasToWebGLContext} context - * @param {Float32Array} matrix - * @param {Float32Array} color_transform - * @return {void} - * @method - * @private - */ - _$draw ( - context: CanvasToWebGLContext, - matrix: Float32Array, - color_transform: Float32Array - ): void { - - // not draw - if (!this._$visible) { - return ; - } - - const transform: Transform = this._$transform; - - let multiColor: Float32Array = color_transform; - const rawColor: Float32Array = transform._$rawColorTransform(); - if (rawColor !== $COLOR_ARRAY_IDENTITY - && rawColor[0] !== 1 || rawColor[1] !== 1 - || rawColor[2] !== 1 || rawColor[3] !== 1 - || rawColor[4] !== 0 || rawColor[5] !== 0 - || rawColor[6] !== 0 || rawColor[7] !== 0 - ) { - multiColor = $multiplicationColor(color_transform, rawColor); - } - - // not draw - const alpha: number = $clamp(multiColor[3] + multiColor[7] / 255, 0, 1, 0); - if (!alpha) { - return ; - } - - // not draw - const children: DisplayObjectImpl[] = this._$getChildren(); - const length: number = children.length; - if (!length) { - return ; - } - - // pre data - const preObject: PreObjectImpl | null = this._$preDraw(context, matrix); - if (!preObject) { - return ; - } - - // use cache - if (preObject.isLayer && !preObject.isUpdated) { - this._$postDraw(context, matrix, multiColor, preObject); - return ; - } - - const preMatrix: Float32Array = preObject.matrix as NonNullable; - - const preColorTransform: Float32Array = preObject.isLayer && preObject.color - ? preObject.color - : multiColor; - - // init clip params - let shouldClip: boolean = true; - let clipDepth: number = 0; - - const player: Player = $currentPlayer(); - - // draw children - const isLayer: boolean = context.isLayer; - const isUpdate: boolean = this._$isUpdated(); - for (let idx: number = 0; idx < length; ++idx) { - - const instance = children[idx]; - - if (isUpdate) { - instance._$placeObject = null; - } - - // mask instance - if (instance._$isMask) { - continue; - } - - // not layer mode - const blendMode: BlendModeImpl = instance._$blendMode || instance.blendMode; - if ((blendMode === "alpha" || blendMode === "erase") - && !isLayer - ) { - continue; - } - - // mask end - if (clipDepth - && (instance._$placeId > clipDepth || instance._$clipDepth > 0) - ) { - - context.restore(); - - if (shouldClip) { - context._$leaveClip(); - } - - // clear - clipDepth = 0; - shouldClip = true; - } - - // mask size 0 - if (!shouldClip) { - continue; - } - - // mask start - if (instance._$clipDepth > 0) { - - clipDepth = instance._$clipDepth; - shouldClip = instance._$shouldClip(preMatrix); - - if (shouldClip) { - context.save(); - shouldClip = instance._$startClip(context, preMatrix); - } - - continue; - } - - // mask start - const maskInstance: DisplayObjectImpl | null = instance._$mask; - if (maskInstance) { - - maskInstance._$updated = false; - - let maskMatrix: Float32Array; - - if (this === maskInstance._$parent) { - - maskMatrix = preMatrix; - - } else { - - maskMatrix = $MATRIX_ARRAY_IDENTITY; - - let parent: ParentImpl | null = maskInstance._$parent; - while (parent) { - - maskMatrix = $multiplicationMatrix( - parent._$transform._$rawMatrix(), - maskMatrix - ); - - parent = parent._$parent; - } - - const mScale: number = player.scaleX; - const playerMatrix: Float32Array = $getFloat32Array6( - mScale, 0, 0, mScale, 0, 0 - ); - - maskMatrix = $multiplicationMatrix( - playerMatrix, maskMatrix - ); - $poolFloat32Array6(playerMatrix); - - if (context.isLayer) { - const currentPosition: BoundsImpl = context.getCurrentPosition(); - maskMatrix[4] -= currentPosition.xMin; - maskMatrix[5] -= currentPosition.yMin; - } - - } - - if (!maskInstance._$shouldClip(maskMatrix)) { - continue; - } - - const result: boolean = maskInstance._$startClip(context, maskMatrix); - - context.save(); - - if (!result) { // fixed - context.restore(); - continue; - } - - } - - instance._$draw(context, preMatrix, preColorTransform); - instance._$updated = false; - - // mask end - if (maskInstance) { - context.restore(); - context._$leaveClip(); - } - } - - // end mask - if (clipDepth) { - context.restore(); - - if (shouldClip) { - context._$leaveClip(); - } - } - - // filter and blend - if (preObject.isLayer) { - return this._$postDraw(context, matrix, multiColor, preObject); - } - - if (preObject.matrix !== matrix) { - $poolFloat32Array6(preObject.matrix as NonNullable); - } - - if (multiColor !== color_transform) { - $poolFloat32Array8(multiColor); - } - - $poolPreObject(preObject); - } - - /** - * @param {CanvasRenderingContext2D} context - * @param {Float32Array} matrix - * @param {object} options - * @param {boolean} [mouse_children=true] - * @return {boolean} - * @method - * @private - */ - _$mouseHit ( - context: CanvasRenderingContext2D, - matrix: Float32Array, - options: PlayerHitObjectImpl, - mouse_children: boolean = true - ): boolean { - - let multiMatrix: Float32Array = matrix; - const rawMatrix: Float32Array = this._$transform._$rawMatrix(); - if (rawMatrix !== $MATRIX_ARRAY_IDENTITY) { - multiMatrix = $multiplicationMatrix(matrix, rawMatrix); - } - - const children: DisplayObjectImpl[] = this._$getChildren(); - - // mask set - const clips: DisplayObjectImpl[] = $getArray(); - const targets: DisplayObjectImpl[] = $getArray(); - const clipIndexes: Map = $getMap(); - - let clipDepth: number = 0; - let clipIdx: number = 0; - for (let idx: number = 0; idx < children.length; ++idx) { - - const instance: DisplayObjectImpl = children[idx]; - - if (!instance._$visible && !instance._$hitObject) { - continue; - } - - if (instance._$clipDepth) { - clipIdx = clips.length; - clipDepth = instance._$clipDepth; - clips.push(instance); - continue; - } - - // clip end - if (clipDepth && instance._$placeId > clipDepth) { - clipIdx = 0; - clipDepth = 0; - } - - // clip check on - if (clipIdx) { - clipIndexes.set(instance._$instanceId, clipIdx); - } - - targets.push(instance); - - } - - // setup - const mouseChildren: boolean = this._$mouseChildren && mouse_children; - - let hit: boolean = false; - const isRoot = this._$root === this; - - while (targets.length) { - - const instance: DisplayObjectImpl = targets.pop(); - if (instance._$isMask) { - continue; - } - - if (isRoot && !(instance instanceof InteractiveObject)) { - continue; - } - - // mask target - if (clipIndexes.has(instance._$instanceId)) { - - const index: number | void = clipIndexes.get(instance._$instanceId); - if (!index) { - continue; - } - - const clip: DisplayObjectImpl = clips[index]; - if (!clip._$hit(context, multiMatrix, options, true)) { - continue; - } - - } - - // mask hit test - const maskInstance: DisplayObjectImpl | null = instance._$mask; - if (maskInstance) { - - if (this === maskInstance._$parent) { - - if (!maskInstance._$hit(context, multiMatrix, options, true)) { - continue; - } - - } else { - - let maskMatrix: Float32Array = $MATRIX_ARRAY_IDENTITY; - - let parent: ParentImpl | null = maskInstance._$parent; - while (parent) { - - maskMatrix = $multiplicationMatrix( - parent._$transform._$rawMatrix(), - maskMatrix - ); - - parent = parent._$parent; - } - - if (!maskInstance._$hit(context, maskMatrix, options, true)) { - continue; - } - - } - - } - - if (instance._$mouseHit(context, multiMatrix, options, mouseChildren) - || instance._$hitArea - && instance - ._$hitArea - ._$mouseHit(context, multiMatrix, options, mouseChildren) - ) { - - if (instance._$root === instance) { - return true; - } - - if (!mouseChildren) { - return true; - } - - hit = true; - if (instance instanceof InteractiveObject) { - - if (!instance.mouseEnabled && !instance._$hitObject) { - continue; - } - - if (!$isTouch && !options.pointer) { - - if ("_$text" in instance - && "type" in instance - && instance.type === "input" - ) { - options.pointer = "text"; - } - - if ("buttonMode" in instance - && "useHandCursor" in instance - && instance.buttonMode - && instance.useHandCursor - ) { - options.pointer = "pointer"; - } - - } - - if (!options.hit) { - - options.hit = !instance.mouseEnabled && instance._$hitObject - ? instance._$hitObject - : instance; - - } - - return true; - } - - } - - } - - // pool - $poolArray(clips); - $poolArray(targets); - $poolMap(clipIndexes); - - if (multiMatrix !== matrix) { - $poolFloat32Array6(multiMatrix); - } - - // not found - return hit; - } - - /** - * @param {CanvasRenderingContext2D} context - * @param {Float32Array} matrix - * @param {object} options - * @param {boolean} [is_clip=false] - * @return {boolean} - * @method - * @private - */ - _$hit ( - context: CanvasRenderingContext2D, - matrix: Float32Array, - options: PlayerHitObjectImpl, - is_clip: boolean = false - ): boolean { - - let multiMatrix: Float32Array = matrix; - const rawMatrix: Float32Array = this._$transform._$rawMatrix(); - if (rawMatrix !== $MATRIX_ARRAY_IDENTITY) { - multiMatrix = $multiplicationMatrix(matrix, rawMatrix); - } - - const children: DisplayObjectImpl[] = this._$getChildren(); - for (let idx: number = children.length; idx > -1; --idx) { - - const instance: DisplayObjectImpl = children[idx]; - if (instance._$isMask) { - continue; - } - - if (instance._$hit(context, multiMatrix, options, is_clip)) { - return true; - } - - } - - if (multiMatrix !== matrix) { - $poolFloat32Array6(multiMatrix); - } - - return false; - } - - /** - * @param {number} index - * @return {DisplayObject} - * @method - * @private - */ - _$createInstance (index: number): DisplayObjectImpl - { - if (!this._$dictionary) { - throw new Error("the dictionary is null."); - } - - // build - const tag: DictionaryTagImpl = this._$dictionary[index]; - const loaderInfo: LoaderInfo | null = this._$loaderInfo; - if (!loaderInfo || !loaderInfo._$data) { - throw new Error("the loaderInfo or data is null."); - } - - const character: Character = loaderInfo._$data.characters[tag.characterId]; - - // symbol class - const instance: DisplayObjectImpl = $createInstance(character.extends); - instance._$build(tag, this); - instance._$id = index; - - return instance; - } - - /** - * @param {number} x - * @param {number} y - * @return {boolean} - * @method - * @private - */ - _$outCheck (x: number, y: number): boolean - { - let matrix: Float32Array = $MATRIX_ARRAY_IDENTITY; - let parent: ParentImpl | null = this._$parent; - while (parent) { - - matrix = $multiplicationMatrix( - parent._$transform._$rawMatrix(), - matrix - ); - - parent = parent._$parent; - } - - $hitContext.setTransform(1, 0, 0, 1, 0, 0); - $hitContext.beginPath(); - - const options: PlayerHitObjectImpl = { - "x": x, - "y": y, - "pointer": "", - "hit": null - }; - - return this._$mouseHit($hitContext, matrix, options); - } - - /** - * @return {void} - * @method - * @private - */ - _$createWorkerInstance (): void - { - if (this._$created || !$rendererWorker) { - return ; - } - - this._$created = true; - this._$posted = true; - this._$updated = false; - - let index: number = 0; - const buffer: Float32Array = $getRenderBufferArray(); - buffer[index++] = this._$instanceId; - buffer[index++] = this._$parent ? this._$parent._$instanceId : -1; - - this._$registerProperty(buffer, index); - - const message: PropertyMessageMapImpl = $getRenderMessageObject(); - message.command = "createDisplayObjectContainer"; - message.buffer = buffer; - - const options: ArrayBuffer[] = $getArray(buffer.buffer); - $rendererWorker.postMessage(message, options); - - $poolRenderMessageObject(message); - $poolArray(options); - - this._$postChildrenIds(); - } - - /** - * @return {void} - * @method - * @private - */ - _$postProperty (): void - { - if (!$rendererWorker) { - return ; - } - - this._$postChildrenIds(); - - const options: ArrayBuffer[] = $getArray(); - const message: PropertyMessageMapImpl = this._$createMessage(); - - $rendererWorker - .postMessage(message, options); - - $poolArray(options); - - this._$posted = true; - this._$updated = false; - } - - /** - * @param {array} [childrenIds=null] - * @return {void} - * @method - * @private - */ - _$postChildrenIds (childrenIds: number[] | null = null): void - { - if (!$rendererWorker || !this._$created) { - return ; - } - - let poolIds = false; - if (!childrenIds) { - - const children: DisplayObjectImpl[] = this._$getChildren(); - - childrenIds = $getArray(); - for (let idx: number = 0; idx < children.length; ++idx) { - childrenIds.push(children[idx]._$instanceId); - } - - poolIds = true; - } - - const buffer: Int32Array = new Int32Array(childrenIds.length + 1); - buffer[0] = this._$instanceId; - buffer.set(childrenIds, 1); - - const message: PropertyMessageMapImpl = $getRenderMessageObject(); - message.command = "setChildren"; - message.buffer = buffer; - - const options: ArrayBuffer[] = $getArray(buffer.buffer); - $rendererWorker.postMessage(message, options); - - $poolRenderMessageObject(message); - $poolArray(options); - - if (poolIds) { - $poolArray(childrenIds); - } - } + // if (!options.hit) { + + // options.hit = !instance.mouseEnabled && instance._$hitObject + // ? instance._$hitObject + // : instance; + + // } + + // return true; + // } + + // } + + // } + + // // pool + // $poolArray(clips); + // $poolArray(targets); + // $poolMap(clipIndexes); + + // if (multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + + // // not found + // return hit; + // } + + // /** + // * @param {CanvasRenderingContext2D} context + // * @param {Float32Array} matrix + // * @param {object} options + // * @param {boolean} [is_clip=false] + // * @return {boolean} + // * @method + // * @private + // */ + // _$hit ( + // context: CanvasRenderingContext2D, + // matrix: Float32Array, + // options: PlayerHitObjectImpl, + // is_clip: boolean = false + // ): boolean { + + // let multiMatrix: Float32Array = matrix; + // const rawMatrix: Float32Array = this._$transform._$rawMatrix(); + // if (rawMatrix !== $MATRIX_ARRAY_IDENTITY) { + // multiMatrix = $multiplicationMatrix(matrix, rawMatrix); + // } + + // const children: DisplayObjectImpl[] = this._$getChildren(); + // for (let idx: number = children.length; idx > -1; --idx) { + + // const instance: DisplayObjectImpl = children[idx]; + // if (instance._$isMask) { + // continue; + // } + + // if (instance._$hit(context, multiMatrix, options, is_clip)) { + // return true; + // } + + // } + + // if (multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + + // return false; + // } + + // /** + // * @param {number} index + // * @return {DisplayObject} + // * @method + // * @private + // */ + // _$createInstance (index: number): DisplayObjectImpl + // { + // if (!this._$dictionary) { + // throw new Error("the dictionary is null."); + // } + + // // build + // const tag: DictionaryTagImpl = this._$dictionary[index]; + // const loaderInfo: LoaderInfo | null = this._$loaderInfo; + // if (!loaderInfo || !loaderInfo._$data) { + // throw new Error("the loaderInfo or data is null."); + // } + + // const character: Character = loaderInfo._$data.characters[tag.characterId]; + + // // symbol class + // const instance: DisplayObjectImpl = $createInstance(character.extends); + // instance._$build(tag, this); + // instance._$id = index; + + // return instance; + // } + + // /** + // * @param {number} x + // * @param {number} y + // * @return {boolean} + // * @method + // * @private + // */ + // _$outCheck (x: number, y: number): boolean + // { + // let matrix: Float32Array = $MATRIX_ARRAY_IDENTITY; + // let parent: ParentImpl | null = this._$parent; + // while (parent) { + + // matrix = $multiplicationMatrix( + // parent._$transform._$rawMatrix(), + // matrix + // ); + + // parent = parent._$parent; + // } + + // $hitContext.setTransform(1, 0, 0, 1, 0, 0); + // $hitContext.beginPath(); + + // const options: PlayerHitObjectImpl = { + // "x": x, + // "y": y, + // "pointer": "", + // "hit": null + // }; + + // return this._$mouseHit($hitContext, matrix, options); + // } } diff --git a/packages/display/src/DisplayObjectUtil.ts b/packages/display/src/DisplayObjectUtil.ts new file mode 100644 index 00000000..4f3a2e74 --- /dev/null +++ b/packages/display/src/DisplayObjectUtil.ts @@ -0,0 +1,289 @@ +import type { AjaxOptionImpl } from "./interface/AjaxOptionImpl"; +import type { URLRequestHeaderImpl } from "./interface/URLRequestHeaderImpl"; + +/** + * @type {number} + */ +let instanceId: number = 0; + +/** + * @description インスタンスユニークIDを返却 + * Returns the instance unique ID + * + * @return {number} + * @method + * @public + */ +export const $getInstanceId = (): number => +{ + return instanceId++; +}; + +/** + * @description 使用済みになったArrayのプール配列 + * Pool array of used Array. + * + * @type {array[]} + * @const + * @static + */ +export const $arrays: any[] = []; + +/** + * @description 使用済みになったFloat32Arrayをプール、サイズは6固定 + * Pool used Float32Array, size fixed at 6. + * + * @type {Float32Array[]} + * @const + * @static + */ +export const $float32Array6: Float32Array[] = []; + +/** + * @description 使用済みになったFloat32Arrayをプール、サイズは8固定 + * Pool used Float32Array, size fixed at 8. + * + * @type {Float32Array[]} + * @const + * @static + */ +export const $float32Array8: Float32Array[] = []; + +/** + * @description プールされたFloat32Arrayがあればプールから。なければ新規作成して返却、サイズは6固定 + * If there is a pooled Float32Array, it is taken from the pool. + * If not, create a new one and return it. Size is fixed at 6. + * + * @param {number} [f0=0] + * @param {number} [f0=0] + * @param {number} [f1=0] + * @param {number} [f2=0] + * @param {number} [f3=0] + * @param {number} [f4=0] + * @param {number} [f5=0] + * @return {Float32Array} + * @method + * @static + */ +export const $getFloat32Array6 = ( + f0: number = 0, f1: number = 0, + f2: number = 0, f3: number = 0, + f4: number = 0, f5: number = 0 +): Float32Array => { + + const array: Float32Array = $float32Array6.pop() || new Float32Array(6); + + array[0] = f0; + array[1] = f1; + array[2] = f2; + array[3] = f3; + array[4] = f4; + array[5] = f5; + + return array; +}; + +/** + * @description 使用済みになったFloat32Arrayをプール + * Pool used Float32Array. + * + * @param {Float32Array} array + * @return {void} + * @method + * @static + */ +export const $poolFloat32Array6 = (array: Float32Array): void => +{ + $float32Array6.push(array); +}; + +/** + * @description プールされたFloat32Arrayがあればプールから。なければ新規作成して返却、サイズは8固定 + * If there is a pooled Float32Array, it is taken from the pool. + * If not, create a new one and return it. Size is fixed at 8. + * + * @param {number} [f0=0] + * @param {number} [f1=0] + * @param {number} [f2=0] + * @param {number} [f3=0] + * @param {number} [f4=0] + * @param {number} [f5=0] + * @param {number} [f6=0] + * @param {number} [f7=0] + * @return {Float32Array} + * @method + * @static + */ +export const $getFloat32Array8 = ( + f0: number = 1, f1: number = 1, + f2: number = 1, f3: number = 1, + f4: number = 0, f5: number = 0, + f6: number = 0, f7: number = 0 +): Float32Array => { + + const array: Float32Array = $float32Array8.pop() || new Float32Array(8); + + array[0] = f0; + array[1] = f1; + array[2] = f2; + array[3] = f3; + array[4] = f4; + array[5] = f5; + array[6] = f6; + array[7] = f7; + + return array; +}; + +/** + * @description 使用済みになったFloat32Arrayをプール + * Pool used Float32Array. + * + * @param {Float32Array} array + * @return {void} + * @method + * @static + */ +export const $poolFloat32Array8 = (array: Float32Array): void => +{ + $float32Array8.push(array); +}; + +/** + * @description プールされたArrayがあればプールから、なければ新規作成して返却 + * If there is a pooled Array, return it from the pool, + * otherwise create a new one and return it. + * + * @param {array} args + * @return {array} + * @method + * @static + */ +export const $getArray = (...args: any[]): any[] => +{ + const array: any[] = $arrays.pop() || []; + if (args.length) { + array.push(...args); + } + return array; +}; + +/** + * @description 使用済みになったArrayをプール + * Pool used Array. + * + * @param {array} array + * @return {void} + * @method + * @static + */ +export const $poolArray = (array: any[]): void => +{ + if (array.length) { + array.length = 0; + } + + $arrays.push(array); +}; + +/** + * @param {object} option + * @return {void} + * @method + * @public + */ +export const $ajax = (option: AjaxOptionImpl): void => +{ + // get or post + let postData: string | null = null; + switch (option.method.toUpperCase()) { + + case "GET": + if (option.data) { + const urls = option.url.split("?"); + + urls[1] = urls.length === 1 + ? option.data.toString() + : `${urls[1]}&${option.data.toString()}`; + + option.url = urls.join("?"); + } + break; + + case "PUT": + case "POST": + if (option.data) { + postData = option.data.toString(); + } + break; + + default: + break; + + } + + // start + const xmlHttpRequest = new XMLHttpRequest(); + + // init + xmlHttpRequest.open(option.method, option.url, true); + + // set mimeType + xmlHttpRequest.responseType = option.format; + + // use cookie + xmlHttpRequest.withCredentials = option.withCredentials; + + // add event + if (option.event) { + const keys: string[] = Object.keys(option.event); + for (let idx = 0; idx < keys.length; ++idx) { + + const name: string = keys[idx]; + + // @ts-ignore + xmlHttpRequest.addEventListener(name, option.event[name]); + } + } + + // set request header + for (let idx: number = 0; idx < option.headers.length; ++idx) { + const header = option.headers[idx]; + if (!header) { + continue; + } + xmlHttpRequest.setRequestHeader(header.name, header.value); + } + + xmlHttpRequest.send(postData); +}; + +/** + * @description ヘッダー文字列を配列に変換 + * Convert header string to array + * + * @param {string} header + * @return {array} + * @method + * @public + */ +export const $headerStringToArray = (header: string): URLRequestHeaderImpl[] => +{ + const results = $getArray(); + if (header) { + + const headers = header.trim().split("\n"); + for (let idx = 0; idx < headers.length; ++idx) { + + const values = headers[idx].split(":"); + + results.push({ + "name": values[0].trim(), + "value": values[1].trim() + }); + + } + + } + return results; +}; \ No newline at end of file diff --git a/packages/display/src/FrameLabel.ts b/packages/display/src/FrameLabel.ts index 4400db43..e5b8f558 100644 --- a/packages/display/src/FrameLabel.ts +++ b/packages/display/src/FrameLabel.ts @@ -1,25 +1,16 @@ import { EventDispatcher } from "@next2d/events"; /** - * FrameLabel オブジェクトには、フレーム番号および対応するラベル名を指定するプロパティがあります。 - * MovieClip クラスには、currentLabels プロパティがあります。 - * これは、現在のシーンの FrameLabel オブジェクトの配列です。 - * MovieClip インスタンスがシーンを使用していない場合、配列には MovieClip インスタンス全体のすべてのフレームラベルが含まれます。 + * @description FrameLabel オブジェクトには、フレーム番号および対応するラベル名を指定するプロパティがあります。 + * MovieClip クラスには、currentLabels プロパティがあります。 + * これは、現在のシーンの FrameLabel オブジェクトの配列です。 + * MovieClip インスタンスがシーンを使用していない場合、配列には MovieClip インスタンス全体のすべてのフレームラベルが含まれます。 * - * The FrameLabel object contains properties that specify a frame number and the corresponding label name. - * The MovieClip class includes a currentLabels property, - * which is an Array of FrameLabel objects for the current scene. - * If the MovieClip instance does not use scenes, - * the Array includes all frame labels from the entire MovieClip instance. - * - * @example Example usage of FrameLabel. - * // static BlendMode - * const {FrameLabel} = next2d.display; - * const frameLabel = new FrameLabel(); - * frameLabel.addEventListener(Event.FRAME_LABEL, (event) => - * { - * // more... - * } + * The FrameLabel object contains properties that specify a frame number and the corresponding label name. + * The MovieClip class includes a currentLabels property, + * which is an Array of FrameLabel objects for the current scene. + * If the MovieClip instance does not use scenes, + * the Array includes all frame labels from the entire MovieClip instance. * * @class * @memberOf next2d.display @@ -59,7 +50,7 @@ export class FrameLabel extends EventDispatcher * Returns the string representation of the specified class. * * @return {string} - * @default [class FrameLabel] + * @default "[class FrameLabel]" * @method * @static */ @@ -73,7 +64,7 @@ export class FrameLabel extends EventDispatcher * Returns the space name of the specified class. * * @return {string} - * @default next2d.display.FrameLabel + * @default "next2d.display.FrameLabel" * @const * @static */ @@ -87,7 +78,7 @@ export class FrameLabel extends EventDispatcher * Returns the string representation of the specified object. * * @return {string} - * @default [object FrameLabel] + * @default "[object FrameLabel]" * @method * @public */ @@ -101,7 +92,7 @@ export class FrameLabel extends EventDispatcher * Returns the space name of the specified object. * * @return {string} - * @default next2d.display.FrameLabel + * @default "next2d.display.FrameLabel" * @const * @public */ diff --git a/packages/display/src/InteractiveObject.ts b/packages/display/src/InteractiveObject.ts index 4fe499e9..8ab73b21 100644 --- a/packages/display/src/InteractiveObject.ts +++ b/packages/display/src/InteractiveObject.ts @@ -1,11 +1,11 @@ import { DisplayObject } from "./DisplayObject"; /** - * InteractiveObject クラスは、マウス、キーボードまたは他のユーザー入力デバイスを使用して - * ユーザーが操作できるすべての表示オブジェクトの抽象基本クラスです。 + * @description InteractiveObject クラスは、マウス、キーボードまたは他のユーザー入力デバイスを使用して + * ユーザーが操作できるすべての表示オブジェクトの抽象基本クラスです。 * - * The InteractiveObject class is the abstract base class for all display objects - * with which the user can interact, using the mouse, keyboard, or other user input device. + * The InteractiveObject class is the abstract base class for all display objects + * with which the user can interact, using the mouse, keyboard, or other user input device. * * @class * @memberOf next2d.display @@ -32,10 +32,8 @@ export class InteractiveObject extends DisplayObject } /** - * @description このオブジェクトでマウスまたはその他のユーザー入力メッセージを - * 受け取るかどうかを指定します。 - * Specifies whether this object receives mouse, - * or other user input, messages. + * @description このオブジェクトでマウスまたはその他のユーザー入力メッセージを受け取るかどうかを指定します。 + * Specifies whether this object receives mouse, or other user input, messages. * * @member {boolean} * @default true diff --git a/packages/display/src/Loader.ts b/packages/display/src/Loader.ts index 4e32d8f9..c62d49cf 100644 --- a/packages/display/src/Loader.ts +++ b/packages/display/src/Loader.ts @@ -1,39 +1,21 @@ +import type { ParentImpl } from "./interface/ParentImpl"; +import type { Sprite } from "./Sprite"; import { DisplayObjectContainer } from "./DisplayObjectContainer"; import { LoaderInfo } from "./LoaderInfo"; import { MovieClip } from "./MovieClip"; import { URLRequest } from "@next2d/net"; -import { $getMap } from "@next2d/share"; -import { - IOErrorEvent, - Event, - ProgressEvent as Next2DProgressEvent, - HTTPStatusEvent -} from "@next2d/events"; -import type { Player } from "@next2d/core"; -import type { - NoCodeDataZlibImpl, - NoCodeDataImpl, - ParentImpl, - MovieClipCharacterImpl -} from "@next2d/interface"; -import { - $ajax, - $headerToArray, - $unzipQueues, - $updateUnzipWorkerStatus, - $getUnzipWorker, - $currentPlayer, - $useUnzipWorker -} from "@next2d/util"; +import { $ajax } from "./DisplayObjectUtil"; +import { execute as loaderLoadstartEventService } from "./Loader/LoaderLoadStartEventService"; +import { execute as loaderProgressEventService } from "./Loader/LoaderProgressEventService"; +import { execute as loaderLoadEndEventService } from "./Loader/LoaderLoadEndEventService"; +import { execute as loaderLoadJsonService } from "./Loader/LoaderLoadJsonService"; /** - * Loader クラスは、JSON ファイルまたはイメージ(JPEG、PNG、または GIF)ファイルを読み込むために使用します。 - * 読み込みを開始するには load() メソッドを使用します。 - * 読み込まれた表示オブジェクトは Loader オブジェクトの子として追加されます。 + * @description Loader クラスは、JSON ファイルを読み込むために使用します。 + * 外部からの読み込みを開始するには load() メソッドを使用し、ローカルのJSONを読み込むには loadJSON() メソッドを使用します。 * - * The Loader class is used to load JSON files or image (JPEG, PNG, or GIF) files. - * Use the load() method to initiate loading. - * The loaded display object is added as a child of the Loader object. + * The Loader class is used to load JSON files. + * To start loading from an external source, use the load() method, and to load local JSON, use the loadJSON() method. * * @class * @memberOf next2d.display @@ -61,7 +43,7 @@ export class Loader extends DisplayObjectContainer * Returns the string representation of the specified class. * * @return {string} - * @default [class Loader] + * @default "[class Loader]" * @method * @static */ @@ -75,7 +57,7 @@ export class Loader extends DisplayObjectContainer * Returns the space name of the specified class. * * @return {string} - * @default next2d.display.Loader + * @default "next2d.display.Loader" * @const * @static */ @@ -89,7 +71,7 @@ export class Loader extends DisplayObjectContainer * Returns the string representation of the specified object. * * @return {string} - * @default [object Loader] + * @default "[object Loader]" * @method * @public */ @@ -103,7 +85,7 @@ export class Loader extends DisplayObjectContainer * Returns the space name of the specified object. * * @return {string} - * @default next2d.display.Loader + * @default "next2d.display.Loader" * @const * @public */ @@ -120,9 +102,9 @@ export class Loader extends DisplayObjectContainer * @readonly * @public */ - get content (): ParentImpl | null + get content (): ParentImpl | null { - return this._$loaderInfo ? this._$loaderInfo.content : null; + return (this._$loaderInfo as NonNullable).content; } /** @@ -146,41 +128,45 @@ export class Loader extends DisplayObjectContainer * are loaded into the content property in the same way with loadImage. * * @param {URLRequest} request - * @returns {void} + * @returns {Promise} * @method * @public */ - load (request: URLRequest): void + async load (request: URLRequest): Promise { - const loaderInfo: LoaderInfo | null = this._$loaderInfo; - if (!loaderInfo) { - return ; - } - + const loaderInfo = this._$loaderInfo as NonNullable; loaderInfo.url = request.url; loaderInfo.format = request.responseDataFormat; - $ajax({ - "format": request.responseDataFormat, - "url": request.url, - "method": request.method, - "data": request.data, - "headers": request.headers, - "withCredentials": request.withCredentials, - "event": { - "loadstart": (event: ProgressEvent) => - { - this._$loadstart(event); - }, - "progress": (event: ProgressEvent) => - { - this._$progress(event); - }, - "loadend": (event: ProgressEvent) => - { - this._$loadend(event); + if (loaderInfo.format !== "json") { + throw new Error("The only format that can be loaded by this function is `json` format."); + } + + await new Promise((resolve): void => + { + $ajax({ + "format": request.responseDataFormat, + "url": request.url, + "method": request.method, + "data": request.data, + "headers": request.headers, + "withCredentials": request.withCredentials, + "event": { + "loadstart": (event: ProgressEvent): void => + { + loaderLoadstartEventService(loaderInfo, event); + }, + "progress": (event: ProgressEvent): void => + { + loaderProgressEventService(loaderInfo, event); + }, + "loadend": async (event: ProgressEvent): Promise => + { + await loaderLoadEndEventService(loaderInfo, event); + resolve(); + } } - } + }); }); } @@ -188,197 +174,15 @@ export class Loader extends DisplayObjectContainer * @description NoCodeToolのJSONを直接読み込む * Read JSON directly from NoCodeTool * - * @param {object} json + * @param {string} json * @return {void} * @method * @public */ - loadJSON (json: any): void + async loadJSON (json: string): Promise { - if (json.type === "zlib") { - - if ($useUnzipWorker()) { - - $unzipQueues.push(json); - - return ; - } - - $updateUnzipWorkerStatus(true); - - const unzipWorker: Worker = $getUnzipWorker(); - - const buffer: Uint8Array = new Uint8Array(json.buffer); - unzipWorker.onmessage = (event: MessageEvent) => - { - this._$unzipHandler(event); - }; - unzipWorker.postMessage(buffer, [buffer.buffer]); - - } else { - - this._$build(json); - - } - } - - /** - * @param {ProgressEvent} event - * @return {void} - * @method - * @private - */ - _$loadend (event: ProgressEvent): void - { - const loaderInfo: LoaderInfo | null = this._$loaderInfo; - if (!loaderInfo) { - return ; - } - - // set - loaderInfo.bytesLoaded = event.loaded; - loaderInfo.bytesTotal = event.total; - - // progress event - if (loaderInfo.willTrigger(Next2DProgressEvent.PROGRESS)) { - loaderInfo.dispatchEvent(new Next2DProgressEvent( - Next2DProgressEvent.PROGRESS, - false, false, event.loaded, event.total - )); - } - - const target: any = event.target; - - // http status event - if (loaderInfo.willTrigger(HTTPStatusEvent.HTTP_STATUS)) { - - const responseHeaders = $headerToArray( - target.getAllResponseHeaders() - ); - - loaderInfo.dispatchEvent(new HTTPStatusEvent( - HTTPStatusEvent.HTTP_STATUS, false, false, - target.status, target.responseURL, - responseHeaders - )); - } - - if (199 < target.status && 400 > target.status) { - - if (loaderInfo.format === "json") { - - this.loadJSON(target.response); - - } else { - - if (loaderInfo.willTrigger(IOErrorEvent.IO_ERROR)) { - loaderInfo.dispatchEvent(new IOErrorEvent( - IOErrorEvent.IO_ERROR, false, false, - "LoaderInfo format is `json`" - )); - } - - } - - } else { - - if (loaderInfo.willTrigger(IOErrorEvent.IO_ERROR)) { - loaderInfo.dispatchEvent(new IOErrorEvent( - IOErrorEvent.IO_ERROR, false, false, - target.statusText - )); - } - - } - - } - - /** - * @param {MessageEvent} event - * @return {void} - * @method - * @private - */ - _$unzipHandler (event: MessageEvent): void - { - this._$build(event.data); - - if ($unzipQueues.length) { - - const object: NoCodeDataZlibImpl | void = $unzipQueues.pop(); - if (!object) { - return ; - } - - const buffer: Uint8Array = new Uint8Array(object.buffer); - - const unzipWorker = $getUnzipWorker(); - - unzipWorker.onmessage = (event: MessageEvent) => - { - this._$unzipHandler(event); - }; - unzipWorker.postMessage(buffer, [buffer.buffer]); - - } else { - - $updateUnzipWorkerStatus(false); - - } - } - - /** - * @param {ProgressEvent} event - * @return {void} - * @method - * @private - */ - _$loadstart (event: ProgressEvent): void - { - const loaderInfo: LoaderInfo | null = this._$loaderInfo; - if (!loaderInfo) { - return ; - } - - loaderInfo.bytesLoaded = event.loaded; - loaderInfo.bytesTotal = event.total; - - if (loaderInfo.willTrigger(Event.OPEN)) { - loaderInfo.dispatchEvent(new Event(Event.OPEN)); - } - - if (loaderInfo.willTrigger(Next2DProgressEvent.PROGRESS)) { - loaderInfo.dispatchEvent(new Next2DProgressEvent( - Next2DProgressEvent.PROGRESS, - false, false, event.loaded, event.total - )); - } - } - - /** - * @param {ProgressEvent} event - * @return {void} - * @method - * @private - */ - _$progress (event: ProgressEvent): void - { - const loaderInfo: LoaderInfo | null = this._$loaderInfo; - if (!loaderInfo) { - return ; - } - - // set - loaderInfo.bytesLoaded = event.loaded; - loaderInfo.bytesTotal = event.total; - - // progress event - if (loaderInfo.willTrigger(Next2DProgressEvent.PROGRESS)) { - loaderInfo.dispatchEvent(new Next2DProgressEvent( - Next2DProgressEvent.PROGRESS, - false, false, event.loaded, event.total - )); - } + const loaderInfo = this._$loaderInfo as NonNullable; + await loaderLoadJsonService(loaderInfo, json); } /** @@ -387,56 +191,56 @@ export class Loader extends DisplayObjectContainer * @method * @private */ - _$build (object: NoCodeDataImpl): void - { - const loaderInfo: LoaderInfo | null = this._$loaderInfo; - if (!loaderInfo) { - return ; - } - - const symbols: Map = $getMap(); - if (object.symbols.length) { - for (let idx: number = 0; idx < object.symbols.length; ++idx) { - - const values: any[] = object.symbols[idx]; - - symbols.set(values[0], values[1]); - } - } - - loaderInfo._$data = { - "stage": object.stage, - "characters": object.characters, - "symbols": symbols - }; - - // setup - loaderInfo._$content = new MovieClip(); - - // build root - const root: MovieClipCharacterImpl = object.characters[0]; - loaderInfo._$content._$build({ - "characterId": 0, - "clipDepth": 0, - "depth": 0, - "endFrame": root.controller.length, - "startFrame": 1 - }, this); - - // fixed logic - loaderInfo._$content._$parent = null; - this.addChild(loaderInfo._$content); - - // fixed logic - loaderInfo._$content._$added = false; - loaderInfo._$content._$addedStage = false; - - // to event - const player: Player = $currentPlayer(); - player._$loaders.push(loaderInfo); - - if (player._$loadStatus === 1) { // LOAD_START - player._$loadStatus = 2; // LOAD_END - } - } + // _$build (object: NoCodeDataImpl): void + // { + // const loaderInfo: LoaderInfo | null = this._$loaderInfo; + // if (!loaderInfo) { + // return ; + // } + + // const symbols: Map = $getMap(); + // if (object.symbols.length) { + // for (let idx: number = 0; idx < object.symbols.length; ++idx) { + + // const values: any[] = object.symbols[idx]; + + // symbols.set(values[0], values[1]); + // } + // } + + // loaderInfo._$data = { + // "stage": object.stage, + // "characters": object.characters, + // "symbols": symbols + // }; + + // // setup + // loaderInfo._$content = new MovieClip(); + + // // build root + // const root: MovieClipCharacterImpl = object.characters[0]; + // loaderInfo._$content._$build({ + // "characterId": 0, + // "clipDepth": 0, + // "depth": 0, + // "endFrame": root.controller.length, + // "startFrame": 1 + // }, this); + + // // fixed logic + // loaderInfo._$content._$parent = null; + // this.addChild(loaderInfo._$content); + + // // fixed logic + // loaderInfo._$content._$added = false; + // loaderInfo._$content._$addedStage = false; + + // // to event + // const player: Player = $currentPlayer(); + // player._$loaders.push(loaderInfo); + + // if (player._$loadStatus === 1) { // LOAD_START + // player._$loadStatus = 2; // LOAD_END + // } + // } } diff --git a/packages/display/src/Loader/LoaderBuildService.ts b/packages/display/src/Loader/LoaderBuildService.ts new file mode 100644 index 00000000..c2a84337 --- /dev/null +++ b/packages/display/src/Loader/LoaderBuildService.ts @@ -0,0 +1,35 @@ +import type { NoCodeDataImpl } from "../interface/NoCodeDataImpl"; +import type { LoaderInfo } from "../LoaderInfo"; + +export const execute = async (loader_info: LoaderInfo, object: NoCodeDataImpl): Promise => +{ + const symbols: Map = new Map(); + if (object.symbols.length) { + for (let idx: number = 0; idx < object.symbols.length; ++idx) { + + const values: any[] = object.symbols[idx]; + + symbols.set(values[0], values[1]); + } + } + + loader_info.data = { + "stage": object.stage, + "characters": object.characters, + "symbols": symbols + }; + + // setup + // loader_info.content = new MovieClip(); + console.log(object); + + // build root + // const root: MovieClipCharacterImpl = object.characters[0]; + // loaderInfo._$content._$build({ + // "characterId": 0, + // "clipDepth": 0, + // "depth": 0, + // "endFrame": root.controller.length, + // "startFrame": 1 + // }, this); +}; \ No newline at end of file diff --git a/packages/display/src/Loader/LoaderLoadEndEventService.test.ts b/packages/display/src/Loader/LoaderLoadEndEventService.test.ts new file mode 100644 index 00000000..666d3007 --- /dev/null +++ b/packages/display/src/Loader/LoaderLoadEndEventService.test.ts @@ -0,0 +1,93 @@ +import { Loader } from "../Loader"; +import { execute } from "./LoaderLoadEndEventService"; +import { + IOErrorEvent, + ProgressEvent as Next2DProgressEvent +} from "@next2d/events"; +import { describe, expect, it, vi } from "vitest"; + +describe("LoaderLoadEndEventService.js test", () => +{ + it("execute test case1", () => + { + const loader = new Loader(); + + let openState = ""; + let loaded = 0; + let total = 0; + loader + .contentLoaderInfo + .addEventListener(Next2DProgressEvent.PROGRESS, (event: Next2DProgressEvent): void => + { + openState = event.type; + loaded = event.bytesLoaded; + total = event.bytesTotal; + }); + + expect(openState).toBe(""); + expect(loaded).toBe(0); + expect(total).toBe(0); + + const json = { + "type": "json", + "stage": { + "width": 240, + "height": 240, + "fps": 60, + "bgColor": "#ffffff" + }, + "characters": [], + "symbols": [] + }; + + // mock event + const MockEvent = vi.fn().mockImplementation(() => + { + return { + "target": { + "status": 200, + "statusText": "OK", + "response": JSON.stringify(json) + }, + "loaded": 1, + "total": 10 + } as unknown as ProgressEvent; + }); + + execute(loader.contentLoaderInfo, new MockEvent()); + + expect(openState).toBe(Next2DProgressEvent.PROGRESS); + }); + + it("execute test case2", () => + { + const loader = new Loader(); + + let openState = ""; + loader + .contentLoaderInfo + .addEventListener(IOErrorEvent.IO_ERROR, (event: IOErrorEvent): void => + { + openState = event.type; + }); + + expect(openState).toBe(""); + + // mock event + const MockEvent = vi.fn().mockImplementation(() => + { + return { + "target": { + "status": 404, + "statusText": "Not Found" + }, + "loaded": 1, + "total": 10 + } as unknown as ProgressEvent; + }); + + execute(loader.contentLoaderInfo, new MockEvent()); + + expect(openState).toBe(IOErrorEvent.IO_ERROR); + }); +}); \ No newline at end of file diff --git a/packages/display/src/Loader/LoaderLoadEndEventService.ts b/packages/display/src/Loader/LoaderLoadEndEventService.ts new file mode 100644 index 00000000..73f6ac72 --- /dev/null +++ b/packages/display/src/Loader/LoaderLoadEndEventService.ts @@ -0,0 +1,57 @@ +import type { LoaderInfo } from "../LoaderInfo"; +import { $headerStringToArray } from "../DisplayObjectUtil"; +import { execute as loaderLoadJsonService } from "./LoaderLoadJsonService"; +import { + ProgressEvent as Next2DProgressEvent, + IOErrorEvent, + HTTPStatusEvent +} from "@next2d/events"; + +/** + * @description 外部JSONのローディング完了イベントの実行関数 + * Execution function for external JSON loading completion event + * + * @param {LoaderInfo} loader_info + * @param {ProgressEvent} event + * @return {Promise} + * @method + * @public + */ +export const execute = async (loader_info: LoaderInfo, event: ProgressEvent): Promise => +{ + const target = event.target as XMLHttpRequest; + if (!target) { + return ; + } + + if (loader_info.willTrigger(Next2DProgressEvent.PROGRESS)) { + loader_info.dispatchEvent(new Next2DProgressEvent( + Next2DProgressEvent.PROGRESS, false, false, + event.loaded, event.total + )); + } + + // http status event + if (loader_info.willTrigger(HTTPStatusEvent.HTTP_STATUS)) { + + const responseHeaders = $headerStringToArray( + target.getAllResponseHeaders() + ); + + loader_info.dispatchEvent(new HTTPStatusEvent( + HTTPStatusEvent.HTTP_STATUS, false, false, + target.status, target.responseURL, + responseHeaders + )); + } + + if (199 < target.status && 400 > target.status) { + await loaderLoadJsonService(loader_info, target.response); + } else { + if (loader_info.willTrigger(IOErrorEvent.IO_ERROR)) { + loader_info.dispatchEvent(new IOErrorEvent( + IOErrorEvent.IO_ERROR, false, false, target.statusText + )); + } + } +}; \ No newline at end of file diff --git a/packages/display/src/Loader/LoaderLoadJsonService.ts b/packages/display/src/Loader/LoaderLoadJsonService.ts new file mode 100644 index 00000000..45043ede --- /dev/null +++ b/packages/display/src/Loader/LoaderLoadJsonService.ts @@ -0,0 +1,41 @@ +import type { NoCodeDataImpl } from "../interface/NoCodeDataImpl"; +import type { LoaderInfo } from "../LoaderInfo"; +import { execute as loaderBuildService } from "./LoaderBuildService"; + +// @ts-ignore +import ZlibInflateWorker from "./ZlibInflateWorker?worker&inline"; + +/** + * @type {Worker} + * @private + */ +const worker: Worker = new ZlibInflateWorker(); + +/** + * @description JSONオブジェクトがzlib圧縮されている場合はworkerで解凍、無圧縮ならビルド処理を実行 + * If the JSON object is zlib compressed, decompress it with a worker, otherwise execute the build process + * + * @param {LoaderInfo} loader_info + * @param {object} json + * @return {Promise} + * @method + * @public + */ +export const execute = async (loader_info: LoaderInfo, json: any): Promise => +{ + if (json.type === "zlib") { + await new Promise((resolve): void => + { + worker.onmessage = async (event: MessageEvent): Promise => + { + await loaderBuildService(loader_info, event.data as NoCodeDataImpl); + resolve(); + }; + + const buffer: Uint8Array = new Uint8Array(json.buffer); + worker.postMessage(buffer, [buffer.buffer]); + }); + } else { + await loaderBuildService(loader_info, json as NoCodeDataImpl); + } +}; \ No newline at end of file diff --git a/packages/display/src/Loader/LoaderLoadStartEventService.test.ts b/packages/display/src/Loader/LoaderLoadStartEventService.test.ts new file mode 100644 index 00000000..d959d97e --- /dev/null +++ b/packages/display/src/Loader/LoaderLoadStartEventService.test.ts @@ -0,0 +1,74 @@ +import { Loader } from "../Loader"; +import { execute } from "./LoaderLoadStartEventService"; +import { + Event, + ProgressEvent as Next2DProgressEvent +} from "@next2d/events"; +import { describe, expect, it, vi } from "vitest"; + +describe("SoundLoadStartEventService.js test", () => +{ + it("execute test case1", () => + { + const loader = new Loader(); + + let openState = ""; + loader + .contentLoaderInfo + .addEventListener(Event.OPEN, (event: Event): void => + { + openState = event.type; + }); + + expect(openState).toBe(""); + + // mock event + const MockEvent = vi.fn().mockImplementation(() => + { + return { + "loaded": 1, + "total": 10 + } as unknown as ProgressEvent; + }); + + execute(loader.contentLoaderInfo, new MockEvent()); + + expect(openState).toBe(Event.OPEN); + }); + + it("execute test case2", () => + { + const loader = new Loader(); + + let openState = ""; + let loaded = 0; + let total = 0; + loader + .contentLoaderInfo + .addEventListener(Next2DProgressEvent.PROGRESS, (event: Next2DProgressEvent): void => + { + openState = event.type; + loaded = event.bytesLoaded; + total = event.bytesTotal; + }); + + expect(openState).toBe(""); + expect(loaded).toBe(0); + expect(total).toBe(0); + + // mock event + const MockEvent = vi.fn().mockImplementation(() => + { + return { + "loaded": 1, + "total": 10 + } as unknown as ProgressEvent; + }); + + execute(loader.contentLoaderInfo, new MockEvent()); + + expect(openState).toBe(Next2DProgressEvent.PROGRESS); + expect(loaded).toBe(1); + expect(total).toBe(10); + }); +}); \ No newline at end of file diff --git a/packages/display/src/Loader/LoaderLoadStartEventService.ts b/packages/display/src/Loader/LoaderLoadStartEventService.ts new file mode 100644 index 00000000..1c1e52cd --- /dev/null +++ b/packages/display/src/Loader/LoaderLoadStartEventService.ts @@ -0,0 +1,29 @@ +import type { LoaderInfo } from "../LoaderInfo"; +import { + Event, + ProgressEvent as Next2DProgressEvent +} from "@next2d/events"; + +/** + * @description 外部JSONの読み込みが開始イベントの実行関数 + * Execution function of the external JSON loading start event + * + * @param {LoaderInfo} loader_info + * @param {ProgressEvent} event + * @return {void} + * @method + * @public + */ +export const execute = (loader_info: LoaderInfo, event: ProgressEvent): void => +{ + if (loader_info.willTrigger(Event.OPEN)) { + loader_info.dispatchEvent(new Event(Event.OPEN)); + } + + if (loader_info.willTrigger(Next2DProgressEvent.PROGRESS)) { + loader_info.dispatchEvent(new Next2DProgressEvent( + Next2DProgressEvent.PROGRESS, false, false, + event.loaded, event.total + )); + } +}; \ No newline at end of file diff --git a/packages/display/src/Loader/LoaderProgressEventService.test.ts b/packages/display/src/Loader/LoaderProgressEventService.test.ts new file mode 100644 index 00000000..8d8f9dd5 --- /dev/null +++ b/packages/display/src/Loader/LoaderProgressEventService.test.ts @@ -0,0 +1,44 @@ +import { Loader } from "../Loader"; +import { execute } from "./LoaderProgressEventService"; +import { ProgressEvent as Next2DProgressEvent } from "@next2d/events"; +import { describe, expect, it, vi } from "vitest"; + +describe("LoaderProgressEventService.js test", () => +{ + it("execute test case1", () => + { + const loader = new Loader(); + + let openState = ""; + let loaded = 0; + let total = 0; + loader + .contentLoaderInfo + .addEventListener(Next2DProgressEvent.PROGRESS, (event: Next2DProgressEvent): void => + { + openState = event.type; + loaded = event.bytesLoaded; + total = event.bytesTotal; + }); + + expect(openState).toBe(""); + expect(loaded).toBe(0); + expect(total).toBe(0); + + // mock event + const MockEvent = vi.fn().mockImplementation(() => + { + return { + "loaded": 1, + "total": 10 + } as unknown as ProgressEvent; + }); + + execute(loader.contentLoaderInfo, new MockEvent()); + + expect(openState).toBe(Next2DProgressEvent.PROGRESS); + expect(loaded).toBe(1); + expect(total).toBe(10); + + }); +}); \ No newline at end of file diff --git a/packages/display/src/Loader/LoaderProgressEventService.ts b/packages/display/src/Loader/LoaderProgressEventService.ts new file mode 100644 index 00000000..874eb3b8 --- /dev/null +++ b/packages/display/src/Loader/LoaderProgressEventService.ts @@ -0,0 +1,22 @@ +import type { LoaderInfo } from "../LoaderInfo"; +import { ProgressEvent as Next2DProgressEvent } from "@next2d/events"; + +/** + * @description 外部JSONのローディング中のイベント実行関数 + * Execution function of the external JSON loading event + * + * @param {Sound} loader_info + * @param {ProgressEvent} event + * @return {void} + * @method + * @public + */ +export const execute = (loader_info: LoaderInfo, event: ProgressEvent): void => +{ + if (loader_info.willTrigger(Next2DProgressEvent.PROGRESS)) { + loader_info.dispatchEvent(new Next2DProgressEvent( + Next2DProgressEvent.PROGRESS, false, false, + event.loaded, event.total + )); + } +}; \ No newline at end of file diff --git a/packages/display/src/Loader/ZlibInflateWorker.ts b/packages/display/src/Loader/ZlibInflateWorker.ts new file mode 100644 index 00000000..1a995ea6 --- /dev/null +++ b/packages/display/src/Loader/ZlibInflateWorker.ts @@ -0,0 +1,24 @@ +"use strict"; + +import { decompressSync } from "fflate"; + +/** + * @description zilbの圧縮されたデータを解凍します。 + * Unzips zlib-compressed data. + * + * @param {MessageEvent} event + * @return {void} + * @method + * @public + */ +self.addEventListener("message", (event: MessageEvent): void => +{ + const buffer = decompressSync(event.data); + + let json = ""; + for (let idx: number = 0; idx < buffer.length; idx += 4096) { + json += String.fromCharCode(...buffer.slice(idx, idx + 4096)); + } + + self.postMessage(JSON.parse(decodeURIComponent(json))); +}); \ No newline at end of file diff --git a/packages/display/src/LoaderInfo.test.ts b/packages/display/src/LoaderInfo.test.ts new file mode 100644 index 00000000..293321e5 --- /dev/null +++ b/packages/display/src/LoaderInfo.test.ts @@ -0,0 +1,31 @@ +import { LoaderInfo } from "./LoaderInfo"; +import { describe, expect, it } from "vitest"; + +describe("LoaderInfo.js namespace test", () => +{ + it("namespace test public", () => + { + expect(new LoaderInfo().namespace).toBe("next2d.display.LoaderInfo"); + }); + + it("namespace test static", () => + { + expect(LoaderInfo.namespace).toBe("next2d.display.LoaderInfo"); + }); +}); + +describe("LoaderInfo.js toString test", () => +{ + it("toString test success", () => + { + expect(new LoaderInfo().toString()).toBe("[object LoaderInfo]"); + }); +}); + +describe("LoaderInfo.js static toString test", () => +{ + it("static toString test", () => + { + expect(LoaderInfo.toString()).toBe("[class LoaderInfo]"); + }); +}); \ No newline at end of file diff --git a/packages/display/src/LoaderInfo.ts b/packages/display/src/LoaderInfo.ts index c7d39bb9..375b090d 100644 --- a/packages/display/src/LoaderInfo.ts +++ b/packages/display/src/LoaderInfo.ts @@ -1,20 +1,17 @@ +import type { MovieClip } from "./MovieClip"; +import type { Sprite } from "./Sprite"; +import type { ParentImpl } from "./interface/ParentImpl"; +import type { URLLoaderDataFormatImpl } from "./interface/URLLoaderDataFormatImpl"; +import type { LoaderInfoDataImpl } from "./interface/LoaderInfoDataImpl"; import { EventDispatcher } from "@next2d/events"; -import { $getLoaderInfoId } from "@next2d/util"; -import type { - URLLoaderDataFormatImpl, - ParentImpl, - LoaderInfoDataImpl -} from "@next2d/interface"; +import { $getInstanceId } from "./DisplayObjectUtil"; /** - * LoaderInfo クラスは、読み込まれる JSON ファイルやイメージファイル(JPEG、GIF、PNG ファイルなど)に関する情報を提供します。 - * LoaderInfo オブジェクトは、すべての表示オブジェクトで使用できます。 - * 提供される情報には、読み込みの進行状況、読み込む側と読み込まれたコンテンツの URL、メディアの総バイト数、メディアの規格高さと幅などが含まれます。 + * @description LoaderInfo クラスは、読み込まれる JSON ファイルに関する情報を提供します。 + * LoaderInfo オブジェクトは、すべての表示オブジェクトで使用できます。 * - * The LoaderInfo class provides information about a loaded JSON file or a loaded image file (JPEG, GIF, or PNG). - * LoaderInfo objects are available for any display object. - * The information provided includes load progress, the URLs of the loader and loaded content, - * the number of bytes total for the media, and the nominal height and width of the media. + * The LoaderInfo class provides information about the JSON file to be loaded. + * The LoaderInfo object can be used with all display objects. * * @class * @memberOf next2d.display @@ -22,11 +19,9 @@ import type { */ export class LoaderInfo extends EventDispatcher { - public readonly _$id: number; - public _$content: ParentImpl | null; - public _$data: LoaderInfoDataImpl | null; - private _$bytesLoaded: number; - private _$bytesTotal: number; + private readonly _$id: number; + private _$content: ParentImpl | null; + private _$data: LoaderInfoDataImpl | null; private _$url: string; private _$format: URLLoaderDataFormatImpl; @@ -42,21 +37,7 @@ export class LoaderInfo extends EventDispatcher * @type {number} * @private */ - this._$id = $getLoaderInfoId(); - - /** - * @type {number} - * @default 0 - * @private - */ - this._$bytesLoaded = 0; - - /** - * @type {number} - * @default 0 - * @private - */ - this._$bytesTotal = 0; + this._$id = $getInstanceId(); /** * @type {string} @@ -66,7 +47,7 @@ export class LoaderInfo extends EventDispatcher this._$url = ""; /** - * @type {DisplayObject} + * @type {Sprite} * @default null * @private */ @@ -92,7 +73,7 @@ export class LoaderInfo extends EventDispatcher * Returns the string representation of the specified class. * * @return {string} - * @default [class LoaderInfo] + * @default "[class LoaderInfo]" * @method * @static */ @@ -106,7 +87,7 @@ export class LoaderInfo extends EventDispatcher * Returns the space name of the specified class. * * @return {string} - * @default next2d.display.LoaderInfo + * @default "next2d.display.LoaderInfo" * @const * @static */ @@ -120,7 +101,7 @@ export class LoaderInfo extends EventDispatcher * Returns the string representation of the specified object. * * @return {string} - * @default [object LoaderInfo] + * @default "[object LoaderInfo]" * @method * @public */ @@ -134,7 +115,7 @@ export class LoaderInfo extends EventDispatcher * Returns the space name of the specified object. * * @return {string} - * @default next2d.display.LoaderInfo + * @default "next2d.display.LoaderInfo" * @const * @public */ @@ -144,51 +125,46 @@ export class LoaderInfo extends EventDispatcher } /** - * @description そのメディアのロード済みのバイト数です。 - * The uint of bytes that are loaded for the media. + * @description LoaderInfoのユニークIDを返却 + * Returns the unique ID of LoaderInfo * * @member {number} - * @default 0 + * @readonly * @public */ - get bytesLoaded (): number + get id (): number { - return this._$bytesLoaded; - } - set bytesLoaded (bytes_loaded: number) - { - this._$bytesLoaded = bytes_loaded | 0; + return this._$id; } /** - * @description メディアファイル全体のバイト数です。 - * The number of bytes in the entire media file. + * @description Loaderで読み込まれたデータオブジェクトを返却 + * Returns the data object loaded by the Loader * - * @member {number} - * @default 0 + * @member {object} * @public */ - get bytesTotal (): number + get data (): LoaderInfoDataImpl | null { - return this._$bytesTotal; + return this._$data; } - set bytesTotal (bytes_total: number) + set data (data: LoaderInfoDataImpl | null) { - this._$bytesTotal = bytes_total | 0; + this._$data = data; } /** * @description LoaderInfo オブジェクトに関係したロードされたオブジェクトです。 * The loaded object associated with this LoaderInfo object. * - * @member {DisplayObject} + * @member {MovieClip | Sprite | null} * @public */ - get content (): ParentImpl + get content (): ParentImpl | null { return this._$content; } - set content (content: ParentImpl) + set content (content: ParentImpl) { this._$content = content; } diff --git a/packages/display/src/index.ts b/packages/display/src/index.ts index dd7e3996..1810b63a 100644 --- a/packages/display/src/index.ts +++ b/packages/display/src/index.ts @@ -1,18 +1,14 @@ export * from "./BitmapData"; export * from "./BlendMode"; export * from "./DisplayObject"; -export * from "./DisplayObjectContainer"; export * from "./FrameLabel"; export * from "./Graphics"; -export * from "./GraphicsBitmapFill"; -export * from "./GraphicsGradientFill"; export * from "./InteractiveObject"; export * from "./Loader"; -export * from "./LoaderInfo"; export * from "./LoopConfig"; export * from "./LoopType"; export * from "./MovieClip"; export * from "./Shape"; export * from "./Sprite"; export * from "./Stage"; -export * from "./TextField"; \ No newline at end of file +export * from "../../text/src/TextField"; \ No newline at end of file diff --git a/packages/display/src/interface/AjaxEventImpl.ts b/packages/display/src/interface/AjaxEventImpl.ts new file mode 100644 index 00000000..6cd6ce28 --- /dev/null +++ b/packages/display/src/interface/AjaxEventImpl.ts @@ -0,0 +1,5 @@ +export interface AjaxEventImpl { + loadstart?: Function; + progress?: Function; + loadend?: Function; +} \ No newline at end of file diff --git a/packages/display/src/interface/AjaxOptionImpl.ts b/packages/display/src/interface/AjaxOptionImpl.ts new file mode 100644 index 00000000..e431eb1f --- /dev/null +++ b/packages/display/src/interface/AjaxOptionImpl.ts @@ -0,0 +1,14 @@ +import type { URLRequestMethodImpl } from "./URLRequestMethodImpl"; +import type { URLLoaderDataFormatImpl } from "./URLLoaderDataFormatImpl"; +import type { AjaxEventImpl } from "./AjaxEventImpl"; +import type { URLRequestHeaderImpl } from "./URLRequestHeaderImpl"; + +export interface AjaxOptionImpl { + url: string; + format: URLLoaderDataFormatImpl; + method: URLRequestMethodImpl; + withCredentials: boolean; + headers: URLRequestHeaderImpl[]; + data?: any; + event?: AjaxEventImpl; +} \ No newline at end of file diff --git a/packages/display/src/interface/BlendModeImpl.ts b/packages/display/src/interface/BlendModeImpl.ts new file mode 100644 index 00000000..6ed290eb --- /dev/null +++ b/packages/display/src/interface/BlendModeImpl.ts @@ -0,0 +1,15 @@ +export type BlendModeImpl = "copy" + | "add" + | "alpha" + | "darken" + | "difference" + | "erase" + | "hardlight" + | "invert" + | "layer" + | "lighten" + | "multiply" + | "normal" + | "overlay" + | "screen" + | "subtract"; \ No newline at end of file diff --git a/packages/display/src/interface/Character.ts b/packages/display/src/interface/Character.ts new file mode 100644 index 00000000..7b37721a --- /dev/null +++ b/packages/display/src/interface/Character.ts @@ -0,0 +1,3 @@ +import { CharacterImpl } from "./CharacterImpl"; + +export type Character = T; \ No newline at end of file diff --git a/packages/display/src/interface/CharacterImpl.ts b/packages/display/src/interface/CharacterImpl.ts new file mode 100644 index 00000000..a4a2ac84 --- /dev/null +++ b/packages/display/src/interface/CharacterImpl.ts @@ -0,0 +1 @@ +export interface CharacterImpl {} \ No newline at end of file diff --git a/packages/display/src/interface/DictionaryTagImpl.ts b/packages/display/src/interface/DictionaryTagImpl.ts new file mode 100644 index 00000000..a441e1e6 --- /dev/null +++ b/packages/display/src/interface/DictionaryTagImpl.ts @@ -0,0 +1,7 @@ +export interface DictionaryTagImpl { + characterId: number; + name: string; + startFrame: number; + endFrame: number; + clipDepth: number; +} \ No newline at end of file diff --git a/packages/display/src/interface/DisplayObjectImpl.ts b/packages/display/src/interface/DisplayObjectImpl.ts new file mode 100644 index 00000000..23c464fe --- /dev/null +++ b/packages/display/src/interface/DisplayObjectImpl.ts @@ -0,0 +1,3 @@ +import type { DisplayObject } from "@next2d/display"; + +export type DisplayObjectImpl = T; \ No newline at end of file diff --git a/packages/display/src/interface/FilterArrayImpl.ts b/packages/display/src/interface/FilterArrayImpl.ts new file mode 100644 index 00000000..0ce7f18f --- /dev/null +++ b/packages/display/src/interface/FilterArrayImpl.ts @@ -0,0 +1,23 @@ +import type { + BlurFilter, + BevelFilter, + ColorMatrixFilter, + ConvolutionFilter, + DisplacementMapFilter, + DropShadowFilter, + GlowFilter, + GradientBevelFilter, + GradientGlowFilter +} from "@next2d/filters"; + +export type FilterArrayImpl = Array< + BlurFilter + | BevelFilter + | ColorMatrixFilter + | ConvolutionFilter + | DisplacementMapFilter + | DropShadowFilter + | GlowFilter + | GradientBevelFilter + | GradientGlowFilter +>; \ No newline at end of file diff --git a/packages/display/src/interface/LoaderInfoDataImpl.ts b/packages/display/src/interface/LoaderInfoDataImpl.ts new file mode 100644 index 00000000..92a8e337 --- /dev/null +++ b/packages/display/src/interface/LoaderInfoDataImpl.ts @@ -0,0 +1,8 @@ +import type { StageDataImpl } from "./StageDataImpl"; +import type { Character } from "./Character"; + +export interface LoaderInfoDataImpl { + stage: StageDataImpl; + characters: Character[]; + symbols: Map; +} \ No newline at end of file diff --git a/packages/display/src/interface/LoopConfigImpl.ts b/packages/display/src/interface/LoopConfigImpl.ts new file mode 100644 index 00000000..22b8a727 --- /dev/null +++ b/packages/display/src/interface/LoopConfigImpl.ts @@ -0,0 +1,9 @@ +import type { LoopTypeImpl } from "./LoopTypeImpl"; + +export interface LoopConfigImpl { + type: LoopTypeImpl; + frame: number; + start: number; + end: number; + tweenFrame?: number; +} \ No newline at end of file diff --git a/packages/display/src/interface/LoopTypeImpl.ts b/packages/display/src/interface/LoopTypeImpl.ts new file mode 100644 index 00000000..75998297 --- /dev/null +++ b/packages/display/src/interface/LoopTypeImpl.ts @@ -0,0 +1,5 @@ +export type LoopTypeImpl = 0 // REPEAT + | 1 // NO_REPEAT + | 2 // FIXED + | 3 // NO_REPEAT_REVERSAL + | 4 ;// REPEAT_REVERSAL \ No newline at end of file diff --git a/packages/display/src/interface/NoCodeDataImpl.ts b/packages/display/src/interface/NoCodeDataImpl.ts new file mode 100644 index 00000000..2cf30a8b --- /dev/null +++ b/packages/display/src/interface/NoCodeDataImpl.ts @@ -0,0 +1,8 @@ +import { StageDataImpl } from "./StageDataImpl"; + +export interface NoCodeDataImpl { + type: "json"; + stage: StageDataImpl; + characters: any[]; + symbols: any[]; +} \ No newline at end of file diff --git a/packages/display/src/interface/ParentImpl.ts b/packages/display/src/interface/ParentImpl.ts new file mode 100644 index 00000000..1bea3398 --- /dev/null +++ b/packages/display/src/interface/ParentImpl.ts @@ -0,0 +1,3 @@ +import type { DisplayObjectContainer } from "@next2d/display"; + +export type ParentImpl = T; \ No newline at end of file diff --git a/packages/display/src/interface/PlaceObjectImpl.ts b/packages/display/src/interface/PlaceObjectImpl.ts new file mode 100644 index 00000000..139f5ecf --- /dev/null +++ b/packages/display/src/interface/PlaceObjectImpl.ts @@ -0,0 +1,15 @@ +import type { LoopConfigImpl } from "./LoopConfigImpl"; +import type { SurfaceFilterImpl } from "./SurfaceFilterImpl"; +import type { FilterArrayImpl } from "./FilterArrayImpl"; +import type { BlendModeImpl } from "./BlendModeImpl"; + +export interface PlaceObjectImpl { + matrix?: number[]; + colorTransform?: number[]; + typedMatrix?: Float32Array; + typedColorTransform?: Float32Array; + blendMode?: BlendModeImpl; + surfaceFilterList?: SurfaceFilterImpl[]; + filters?: FilterArrayImpl; + loop?: LoopConfigImpl; +} \ No newline at end of file diff --git a/packages/display/src/interface/StageDataImpl.ts b/packages/display/src/interface/StageDataImpl.ts new file mode 100644 index 00000000..1eab12a2 --- /dev/null +++ b/packages/display/src/interface/StageDataImpl.ts @@ -0,0 +1,6 @@ +export interface StageDataImpl { + width: number; + height: number; + fps: number + bgColor: string; +} \ No newline at end of file diff --git a/packages/display/src/interface/SurfaceFilterImpl.ts b/packages/display/src/interface/SurfaceFilterImpl.ts new file mode 100644 index 00000000..3bddb677 --- /dev/null +++ b/packages/display/src/interface/SurfaceFilterImpl.ts @@ -0,0 +1,14 @@ +type ClassName = "BevelFilter" + | "BlurFilter" + | "ColorMatrixFilter" + | "ConvolutionFilter" + | "DisplacementMapFilter" + | "DropShadowFilter" + | "GlowFilter" + | "GradientBevelFilter" + | "GradientGlowFilter"; + +export interface SurfaceFilterImpl { + class: ClassName; + params: any[]; +} \ No newline at end of file diff --git a/packages/display/src/interface/URLLoaderDataFormatImpl.ts b/packages/display/src/interface/URLLoaderDataFormatImpl.ts new file mode 100644 index 00000000..af72978d --- /dev/null +++ b/packages/display/src/interface/URLLoaderDataFormatImpl.ts @@ -0,0 +1 @@ +export type URLLoaderDataFormatImpl = "json" | "arraybuffer" | "text"; \ No newline at end of file diff --git a/packages/display/src/interface/URLRequestHeaderImpl.ts b/packages/display/src/interface/URLRequestHeaderImpl.ts new file mode 100644 index 00000000..efbdd5c9 --- /dev/null +++ b/packages/display/src/interface/URLRequestHeaderImpl.ts @@ -0,0 +1,5 @@ +export interface URLRequestHeaderImpl +{ + name: string; + value: string; +} \ No newline at end of file diff --git a/packages/display/src/interface/URLRequestMethodImpl.ts b/packages/display/src/interface/URLRequestMethodImpl.ts new file mode 100644 index 00000000..866e2360 --- /dev/null +++ b/packages/display/src/interface/URLRequestMethodImpl.ts @@ -0,0 +1 @@ +export type URLRequestMethodImpl = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "POST" | "PUT"; \ No newline at end of file diff --git a/packages/geom/src/Matrix.ts b/packages/geom/src/Matrix.ts index 6a5b8ef6..abae4dcc 100644 --- a/packages/geom/src/Matrix.ts +++ b/packages/geom/src/Matrix.ts @@ -220,6 +220,19 @@ export class Matrix this._$matrix[5] = ty; } + /** + * @description Matrixの内部Float32Arrayデータを返却 + * Returns the internal Float32Array data of Matrix + * + * @member {Float32Array} + * @readonly + * @public + */ + get rawData (): Float32Array + { + return this._$matrix; + } + /** * @return {Matrix} * @method diff --git a/packages/interface/src/Character.ts b/packages/interface/src/Character.ts index 7b37721a..8df0291f 100644 --- a/packages/interface/src/Character.ts +++ b/packages/interface/src/Character.ts @@ -1,3 +1,3 @@ -import { CharacterImpl } from "./CharacterImpl"; +import type { CharacterImpl } from "./CharacterImpl"; export type Character = T; \ No newline at end of file diff --git a/packages/media/src/Sound.ts b/packages/media/src/Sound.ts index 30011da1..1403466d 100644 --- a/packages/media/src/Sound.ts +++ b/packages/media/src/Sound.ts @@ -3,7 +3,7 @@ import { URLRequest } from "@next2d/net"; import { SoundMixer } from "./SoundMixer"; import { execute as soundLoadStartEventService } from "./Sound/SoundLoadStartEventService"; import { execute as soundProgressEventService } from "./Sound/SoundProgressEventService"; -import { execute as soundLoadendEventService } from "./Sound/SoundLoadendEventService"; +import { execute as soundLoadEndEventService } from "./Sound/SoundLoadEndEventService"; import { execute as soundEndedEventService } from "./Sound/SoundEndedEventService"; import { execute as soundDecodeService } from "./Sound/SoundDecodeService"; import { @@ -16,6 +16,7 @@ import { $audioContext, $getSounds } from "./MediaUtil"; +import { LoaderInfo } from "packages/display/src/LoaderInfo"; /** * @description Sound クラスを使用すると、アプリケーション内のサウンドを処理することができます。 @@ -297,7 +298,7 @@ export class Sound extends EventDispatcher }, "loadend": async (event: ProgressEvent): Promise => { - await soundLoadendEventService(this, event); + await soundLoadEndEventService(this, event); resolve(); } } @@ -388,13 +389,13 @@ export class Sound extends EventDispatcher parent: any ): Promise { - const loaderInfo: any = parent.loaderInfo; - if (!loaderInfo || !loaderInfo._$data) { + const loaderInfo: LoaderInfo | null = parent.loaderInfo; + if (!loaderInfo || !loaderInfo.data) { throw new Error("the loaderInfo or data is null."); } const character = loaderInfo - ._$data + .data .characters[tag.characterId]; if (!character) { diff --git a/packages/media/src/Sound/SoundLoadendEventService.test.ts b/packages/media/src/Sound/SoundLoadendEventService.test.ts index 1f841162..9e8074df 100644 --- a/packages/media/src/Sound/SoundLoadendEventService.test.ts +++ b/packages/media/src/Sound/SoundLoadendEventService.test.ts @@ -1,5 +1,5 @@ import { Sound } from "../Sound"; -import { execute } from "./SoundLoadendEventService"; +import { execute } from "./SoundLoadEndEventService"; import { IOErrorEvent, ProgressEvent as Next2DProgressEvent diff --git a/packages/media/src/Sound/SoundLoadendEventService.ts b/packages/media/src/Sound/SoundLoadendEventService.ts index 314741bd..16dbbf20 100644 --- a/packages/media/src/Sound/SoundLoadendEventService.ts +++ b/packages/media/src/Sound/SoundLoadendEventService.ts @@ -7,8 +7,8 @@ import { } from "@next2d/events"; /** - * @description サウンドデータのローディング中のイベント実行関数 - * Event execution function during sound data loading + * @description サウンドデータのローディング完了イベントの実行関数 + * Execution function for sound data loading completion event * * @param {Sound} sound * @param {ProgressEvent} event diff --git a/packages/renderer/package.json b/packages/renderer/package.json index 3bdedc08..b79e49ba 100644 --- a/packages/renderer/package.json +++ b/packages/renderer/package.json @@ -26,6 +26,8 @@ "url": "git+https://github.com/Next2D/Player.git" }, "peerDependencies": { - "@next2d/webgl": "file:../webgl" + "@next2d/webgl": "file:../webgl", + "@next2d/filters": "file:../filters", + "@next2d/cache": "file:../cache" } } diff --git a/packages/renderer/src/Command/CommandInitializeContextService.test.ts b/packages/renderer/src/Command/CommandInitializeContextService.test.ts new file mode 100644 index 00000000..8c5f5c1e --- /dev/null +++ b/packages/renderer/src/Command/CommandInitializeContextService.test.ts @@ -0,0 +1,67 @@ +import { execute } from "./CommandInitializeContextService"; +import { $devicePixelRatio } from "../RendererUtil"; +import { describe, expect, it, vi } from "vitest"; + +describe("CommandInitializeContextService.js test", () => +{ + it("execute test case1", () => + { + const MockCanvas = vi.fn().mockImplementation(() => + { + return { + "getContext": vi.fn((contextId: string, options: any) => + { + expect(contextId).toBe("webgl2"); + expect(options.stencil).toBe(true); + expect(options.premultipliedAlpha).toBe(true); + expect(options.antialias).toBe(false); + expect(options.depth).toBe(false); + expect(options.preserveDrawingBuffer).toBe(true); + + return { + "getParameter": vi.fn(), + "createFramebuffer": vi.fn(), + "bindFramebuffer": vi.fn(), + "pixelStorei": vi.fn(), + "createRenderbuffer": vi.fn(), + "bindRenderbuffer": vi.fn(), + "renderbufferStorageMultisample": vi.fn(), + "createTexture": vi.fn(() => + { + return {}; + }), + "activeTexture": vi.fn(), + "bindTexture": vi.fn(), + "texParameteri": vi.fn(), + "texStorage2D": vi.fn(), + "createBuffer": vi.fn(), + "createVertexArray": vi.fn(), + "bindBuffer": vi.fn(), + "bufferData": vi.fn(), + "enableVertexAttribArray": vi.fn(), + "vertexAttribPointer": vi.fn(), + "vertexAttribDivisor": vi.fn(), + "createProgram": vi.fn(() => + { + return {}; + }), + "createShader": vi.fn(), + "shaderSource": vi.fn(), + "compileShader": vi.fn(), + "attachShader": vi.fn(), + "linkProgram": vi.fn(), + "detachShader": vi.fn(), + "deleteShader": vi.fn(), + "getProgramParameter": vi.fn(), + "enable": vi.fn(), + "blendFunc": vi.fn(), + }; + }) + } as unknown as HTMLCanvasElement; + }); + + expect($devicePixelRatio).toBe(1); + execute(new MockCanvas(), 2); + expect($devicePixelRatio).toBe(2); + }); +}); \ No newline at end of file diff --git a/packages/renderer/src/Command/CommandInitializeContextService.ts b/packages/renderer/src/Command/CommandInitializeContextService.ts new file mode 100644 index 00000000..fbf74f0e --- /dev/null +++ b/packages/renderer/src/Command/CommandInitializeContextService.ts @@ -0,0 +1,48 @@ +import { CanvasToWebGLContext } from "@next2d/webgl"; +import { + $setCanvas, + $setContext, + $setDevicePixelRatio, + $setWebGL2RenderingContext, + $samples +} from "../RendererUtil"; + +/** + * @description OffscreenCanvasからWebGL2のコンテキストを取得 + * Get WebGL2 context from OffscreenCanvas + * + * @param {OffscreenCanvas} canvas + * @param {number} ratio + * @return {void} + * @method + * @public + */ +export const execute = ( + canvas: OffscreenCanvas, + ratio: number +): void => { + + // Set OffscreenCanvas + $setCanvas(canvas); + + // // Set Device Pixel Ratio + $setDevicePixelRatio(ratio); + + const gl: WebGL2RenderingContext | null = canvas.getContext("webgl2", { + "stencil": true, + "premultipliedAlpha": true, + "antialias": false, + "depth": false, + "preserveDrawingBuffer": true + }); + + if (!gl) { + throw new Error("webgl2 is not supported."); + } + + // Set WebGL2 context + $setWebGL2RenderingContext(gl); + + // Set CanvasToWebGLContext + $setContext(new CanvasToWebGLContext(gl, $samples)); +}; \ No newline at end of file diff --git a/packages/renderer/src/Command/CommandResizeService.ts b/packages/renderer/src/Command/CommandResizeService.ts new file mode 100644 index 00000000..7166d9aa --- /dev/null +++ b/packages/renderer/src/Command/CommandResizeService.ts @@ -0,0 +1,77 @@ +import { + $canvas, + $setRendererHeight, + $setRendererWidth, + $rendererMatrix, + $devicePixelRatio, + $gl, + $context, + $rendererStage +} from "../RendererUtil"; +import { $cacheStore } from "@next2d/cache"; + +/** + * @description 画面リサイズ時にcanvasのリサイズ、内部情報の更新を行う + * Resize the canvas when resizing the screen and update internal information + * + * @param {number} scale + * @param {number} renderer_width + * @param {number} renderer_height + * @param {number} stage_width + * @param {number} stage_height + * @param {boolean} full_screen + * @return {void} + * @method + * @public + */ +export const execute = ( + scale: number, + renderer_width: number, + renderer_height: number, + stage_width: number, + stage_height: number, + full_screen: boolean +): void => { + + if ($canvas.width === renderer_width + && $canvas.height === renderer_height + ) { + return ; + } + + // resize + $setRendererWidth(renderer_width); + $setRendererHeight(renderer_height); + + // update canvas size + $canvas.width = renderer_width; + $canvas.height = renderer_height; + $gl.viewport(0, 0, renderer_width, renderer_height); + + // update matrix scale + $rendererMatrix[0] = scale; + $rendererMatrix[3] = scale; + + // reset + $rendererMatrix[4] = 0; + $rendererMatrix[5] = 0; + + if (full_screen) { + $rendererMatrix[4] = (renderer_width + - stage_width + * scale * $devicePixelRatio) / 2; + + $rendererMatrix[5] = (stage_height + - stage_height + * scale * $devicePixelRatio) / 2; + } + + // cache clear + $cacheStore.reset(); + + // context reset and update + $context.resize(renderer_width, renderer_height); + + // stage update + $rendererStage.doChanged(); +}; \ No newline at end of file diff --git a/packages/renderer/src/CommandController.ts b/packages/renderer/src/CommandController.ts index d51982e5..28173498 100644 --- a/packages/renderer/src/CommandController.ts +++ b/packages/renderer/src/CommandController.ts @@ -6,7 +6,8 @@ // $cacheStore // } from "@next2d/share"; import type { PropertyMessageMapImpl } from "./interface/PropertyMessageMapImpl"; -import type { RenderDisplayObjectImpl } from "./interface/RenderDisplayObjectImpl"; +import { execute as commandInitializeContextService } from "./Command/CommandInitializeContextService"; +import { execute as commandResizeService } from "./Command/CommandResizeService"; /** * @class @@ -55,7 +56,7 @@ export class CommandController { this.state = "active"; - let returnBuffer = true; + // let returnBuffer = true; while (this.queue.length) { const object: PropertyMessageMapImpl | void = this.queue.shift(); @@ -63,7 +64,7 @@ export class CommandController continue; } - returnBuffer = true; + // returnBuffer = true; switch (object.command) { // case "draw": @@ -131,18 +132,25 @@ export class CommandController // break; case "resize": - $renderPlayer._$resize(object.buffer); + commandResizeService( + object.buffer[0] as number, + object.buffer[1] as number, + object.buffer[2] as number, + object.buffer[3] as number, + object.buffer[4] as number, + !!object.buffer[5] + ); break; case "initialize": - $renderPlayer._$initialize( - object.buffer, object.canvas + commandInitializeContextService( + object.canvas, object.buffer[0] as number ); break; - case "setBackgroundColor": - $renderPlayer._$setBackgroundColor(object.buffer); - break; + // case "setBackgroundColor": + // $renderPlayer._$setBackgroundColor(object.buffer); + // break; // case "stop": // $renderPlayer.stop(); @@ -194,18 +202,18 @@ export class CommandController } - if (object.buffer && returnBuffer) { - // this._$options.push(object.buffer.buffer); + // if (object.buffer && returnBuffer) { + // // this._$options.push(object.buffer.buffer); - // globalThis.postMessage({ - // "command": "renderBuffer", - // "buffer": object.buffer - // // @ts-ignore - // }, this._$options); + // // globalThis.postMessage({ + // // "command": "renderBuffer", + // // "buffer": object.buffer + // // // @ts-ignore + // // }, this._$options); - // reset - this._$options.length = 0; - } + // // reset + // this._$options.length = 0; + // } } this.state = "deactivate"; diff --git a/packages/renderer/src/RendererDisplayObject.ts b/packages/renderer/src/RendererDisplayObject.ts new file mode 100644 index 00000000..56ebdbeb --- /dev/null +++ b/packages/renderer/src/RendererDisplayObject.ts @@ -0,0 +1,819 @@ +// import type { RenderPlayer } from "../RenderPlayer"; +// import type { RenderDisplayObjectImpl } from "../interface/RenderDisplayObjectImpl"; +// import type { BlendModeImpl } from "../interface/BlendModeImpl"; +// import type { FilterArrayImpl } from "../interface/FilterArrayImpl"; +// import type { BoundsImpl } from "../interface/BoundsImpl"; +// import type { PropertyMessageMapImpl } from "../interface/PropertyMessageMapImpl"; +// import type { AttachmentImpl } from "../interface/AttachmentImpl"; +// import type { GridImpl } from "../interface/GridImpl"; +// import type { CachePositionImpl } from "../interface/CachePositionImpl"; +// import { $renderPlayer } from "../RenderGlobal"; +// import type { +// CanvasToWebGLContext, +// FrameBufferManager +// } from "@next2d/webgl"; +// import { +// BevelFilter, +// BlurFilter, +// ColorMatrixFilter, +// ConvolutionFilter, +// DisplacementMapFilter, +// DropShadowFilter, +// GlowFilter, +// GradientBevelFilter, +// GradientGlowFilter +// } from "@next2d/filters"; + +/** + * @class + */ +export class RendererDisplayObject +{ + protected _$instanceId: number; + protected _$parentId: number; + protected _$loaderInfoId: number; + protected _$characterId: number; + protected _$clipDepth: number; + protected _$depth: number; + protected _$isMask: boolean; + protected _$updated: boolean; + protected readonly _$matrix: Float32Array; + protected _$blendMode: BlendModeImpl; + protected readonly _$colorTransform: Float32Array; + protected _$filters: FilterArrayImpl | null; + protected _$visible: boolean; + protected _$maskId: number; + protected _$maskMatrix: Float32Array | null; + protected _$xMin: number; + protected _$yMin: number; + protected _$xMax: number; + protected _$yMax: number; + protected _$scale9Grid: GridImpl | null; + protected _$matrixBase: Float32Array | null; + + /** + * @constructor + * @public + */ + constructor () + { + /** + * @type {number} + * @default -1 + * @private + */ + this._$instanceId = -1; + + /** + * @type {number} + * @default -1 + * @private + */ + this._$parentId = -1; + + /** + * @type {number} + * @default -1 + * @private + */ + this._$loaderInfoId = -1; + + /** + * @type {number} + * @default -1 + * @private + */ + this._$characterId = -1; + + /** + * @type {number} + * @default 0 + * @private + */ + this._$clipDepth = 0; + + /** + * @type {number} + * @default 0 + * @private + */ + this._$depth = 0; + + /** + * @type {boolean} + * @default false + * @private + */ + this._$isMask = false; + + /** + * @type {boolean} + * @default true + * @private + */ + this._$updated = true; + + // /** + // * @type {Float32Array} + // * @private + // */ + // this._$matrix = $getFloat32Array6(1, 0, 0, 1, 0, 0); + + // /** + // * @type {Float32Array} + // * @private + // */ + // this._$colorTransform = $getFloat32Array8(1, 1, 1, 1, 0, 0, 0, 0); + + /** + * @type {string} + * @default BlendMode.NORMAL + * @private + */ + this._$blendMode = "normal"; + + /** + * @type {array} + * @default null + * @private + */ + this._$filters = null; + + /** + * @type {boolean} + * @default true + * @private + */ + this._$visible = true; + + /** + * @type {number} + * @default -1 + * @private + */ + this._$maskId = -1; + + /** + * @type {Float32Array} + * @default null + * @private + */ + this._$maskMatrix = null; + + /** + * @type {boolean} + * @default false + * @private + */ + this._$isMask = false; + + /** + * @type {number} + * @default 0 + * @private + */ + this._$xMin = 0; + + /** + * @type {number} + * @default 0 + * @private + */ + this._$yMin = 0; + + /** + * @type {number} + * @default 0 + * @private + */ + this._$xMax = 0; + + /** + * @type {number} + * @default 0 + * @private + */ + this._$yMax = 0; + + /** + * @type {object|null} + * @default null + * @private + */ + this._$scale9Grid = null; + + /** + * @type {Float32Array} + * @default null + * @private + */ + this._$matrixBase = null; + } + + // /** + // * @param {Float32Array} matrix + // * @return {boolean} + // * @method + // * @private + // */ + // _$shouldClip (matrix: Float32Array): boolean + // { + // const bounds: BoundsImpl = this._$getBounds(matrix); + // const width: number = $Math.abs(bounds.xMax - bounds.xMin); + // const height: number = $Math.abs(bounds.yMax - bounds.yMin); + // $poolBoundsObject(bounds); + + // return !(!width || !height); + // } + + // /** + // * @param {Float32Array} multi_matrix + // * @returns {object} + // * @private + // */ + // _$getLayerBounds (multi_matrix: Float32Array): BoundsImpl + // { + // const baseBounds: BoundsImpl = this._$getBounds(); + + // const bounds: BoundsImpl = $boundsMatrix(baseBounds, multi_matrix); + // $poolBoundsObject(baseBounds); + + // const filters: FilterArrayImpl | null = this._$filters; + // if (!filters || !filters.length) { + // return bounds; + // } + + // let filterBounds: BoundsImpl = $getBoundsObject( + // 0, + // $Math.abs(bounds.xMax - bounds.xMin), + // 0, + // $Math.abs(bounds.yMax - bounds.yMin) + // ); + // $poolBoundsObject(bounds); + + // let xScale: number = +$Math.sqrt( + // multi_matrix[0] * multi_matrix[0] + // + multi_matrix[1] * multi_matrix[1] + // ); + // let yScale: number = +$Math.sqrt( + // multi_matrix[2] * multi_matrix[2] + // + multi_matrix[3] * multi_matrix[3] + // ); + + // xScale /= $devicePixelRatio; + // yScale /= $devicePixelRatio; + + // xScale *= 2; + // yScale *= 2; + + // for (let idx: number = 0; idx < filters.length; ++idx) { + // filterBounds = filters[idx] + // ._$generateFilterRect(filterBounds, xScale, yScale); + // } + + // return filterBounds; + // } + + // /** + // * @param {Float32Array} [matrix=null] + // * @returns {object} + // * @method + // * @private + // */ + // _$getBounds (matrix: Float32Array | null = null): BoundsImpl + // { + // const baseBounds: BoundsImpl = $getBoundsObject( + // this._$xMin, this._$xMax, + // this._$yMin, this._$yMax + // ); + + // if (!matrix) { + // return baseBounds; + // } + + // let multiMatrix: Float32Array = matrix; + // const rawMatrix: Float32Array = this._$matrix; + // if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 + // || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 + // || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 + // ) { + // multiMatrix = $multiplicationMatrix(matrix, rawMatrix); + // } + + // const bounds: BoundsImpl = $boundsMatrix(baseBounds, multiMatrix); + // $poolBoundsObject(baseBounds); + + // if (multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + + // return bounds; + // } + + // /** + // * @param {CanvasToWebGLContext} context + // * @param {Float32Array} matrix + // * @return {boolean} + // * @method + // * @private + // */ + // _$startClip ( + // context: CanvasToWebGLContext, + // matrix: Float32Array + // ): boolean { + + // context.drawInstacedArray(); + + // const bounds: BoundsImpl = this._$getBounds(matrix); + // const result = context._$startClip(bounds); + // $poolBoundsObject(bounds); + + // if (!result) { + // return false; + // } + + // // start clip + // context._$enterClip(); + + // // mask start + // context._$beginClipDef(); + + // let containerClip = false; + // if ("_$children" in this) { + // containerClip = true; + // context._$updateContainerClipFlag(true); + // } + + // // @ts-ignore + // this._$clip(context, matrix); + // this._$updated = false; + + // // container clip + // if (containerClip) { + + // // update flag + // context._$updateContainerClipFlag(false); + + // // execute clip + // context._$drawContainerClip(); + // } + + // // mask end + // context._$endClipDef(); + + // return true; + // } + + /** + * @description 自身と親の状態をアクティブにする + * + * @return {void} + * @method + * @protected + */ + doChanged (): void + { + this._$updated = true; + + // if (this._$parentId > -1) { + + // const instances: Map> = $renderPlayer.instances; + // if (!instances.has(this._$parentId)) { + // return ; + // } + + // const instance = instances.get(this._$parentId); + // if (!instance._$updated) { + // instance._$doChanged(); + // } + // } + } + + // /** + // * @description 描画情報を更新 + // * + // * @param {object} object + // * @return {void} + // * @method + // * @private + // */ + // _$update (object: PropertyMessageMapImpl): void + // { + // this._$doChanged(); + + // this._$visible = object.visible; + + // if ("depth" in object) { + // this._$depth = object.depth; + // } + + // if ("isMask" in object) { + // this._$isMask = object.isMask; + // } + + // if ("clipDepth" in object) { + // this._$clipDepth = object.clipDepth; + // } + + // if ("maskId" in object) { + // this._$maskId = object.maskId; + // if (this._$maskId > -1 && object.maskMatrix) { + // this._$maskMatrix = object.maskMatrix; + // } + // } + + // this._$matrix[0] = "a" in object ? object.a : 1; + // this._$matrix[1] = "b" in object ? object.b : 0; + // this._$matrix[2] = "c" in object ? object.c : 0; + // this._$matrix[3] = "d" in object ? object.d : 1; + // this._$matrix[4] = "tx" in object ? object.tx : 0; + // this._$matrix[5] = "ty" in object ? object.ty : 0; + + // this._$colorTransform[0] = "f0" in object ? object.f0 : 1; + // this._$colorTransform[1] = "f1" in object ? object.f1 : 1; + // this._$colorTransform[2] = "f2" in object ? object.f2 : 1; + // this._$colorTransform[3] = "f3" in object ? object.f3 : 1; + // this._$colorTransform[4] = "f4" in object ? object.f4 : 0; + // this._$colorTransform[5] = "f5" in object ? object.f5 : 0; + // this._$colorTransform[6] = "f6" in object ? object.f6 : 0; + // this._$colorTransform[7] = "f7" in object ? object.f7 : 0; + + // this._$blendMode = object.blendMode || "normal"; + + // this._$filters = null; + // if (object.filters && object.filters.length) { + // this._$filters = $getArray(); + // for (let idx: number = 0; idx < object.filters.length; ++idx) { + + // const parameters = object.filters[idx]; + // const type: number = parameters.shift(); + + // switch (type) { + + // case 0: + // this._$filters.push( + // new BevelFilter(...parameters) + // ); + // break; + + // case 1: + // this._$filters.push( + // new BlurFilter(...parameters) + // ); + // break; + + // case 2: + // this._$filters.push( + // new ColorMatrixFilter(...parameters) + // ); + // break; + + // case 3: + // this._$filters.push( + // new ConvolutionFilter(...parameters) + // ); + // break; + + // case 4: + // this._$filters.push( + // new DisplacementMapFilter(...parameters) + // ); + // break; + + // case 5: + // this._$filters.push( + // new DropShadowFilter(...parameters) + // ); + // break; + + // case 6: + // this._$filters.push( + // new GlowFilter(...parameters) + // ); + // break; + + // case 7: + // this._$filters.push( + // new GradientBevelFilter(...parameters) + // ); + // break; + + // case 8: + // this._$filters.push( + // new GradientGlowFilter(...parameters) + // ); + // break; + + // } + // } + // } + + // if (object.grid) { + // this._$scale9Grid = object.grid; + + // if (object.matrixBase) { + // this._$matrixBase = object.matrixBase; + // } + // } + // } + + // /** + // * @param {array} [filters] + // * @return {boolean} + // * @private + // */ + // _$canApply (filters: FilterArrayImpl | null = null): boolean + // { + // if (filters) { + // for (let idx: number = 0; idx < filters.length; ++idx) { + // if (filters[idx]._$canApply()) { + // return true; + // } + // } + // } + // return false; + // } + + // /** + // * @description Playerから登録を削除 + // * + // * @return {void} + // * @method + // * @private + // */ + // _$remove (): void + // { + // this._$doChanged(); + + // const player: RenderPlayer = $renderPlayer; + + // // キャッシュ削除のタイマーをセット + // $cacheStore.setRemoveTimer(this._$instanceId); + + // if (this._$loaderInfoId > -1 && this._$characterId) { + // $cacheStore.setRemoveTimer( + // `${this._$loaderInfoId}@${this._$characterId}` + // ); + // } + + // player.instances.delete(this._$instanceId); + + // // reset + // this._$instanceId = -1; + // this._$parentId = -1; + // this._$loaderInfoId = -1; + // this._$characterId = -1; + // this._$blendMode = "normal"; + // this._$filters = null; + // this._$visible = true; + // this._$maskId = -1; + // this._$isMask = false; + // this._$depth = 0; + // this._$clipDepth = 0; + // this._$scale9Grid = null; + // } + + // /** + // * @return {boolean} + // * @method + // * @private + // */ + // _$isUpdated (): boolean + // { + // return this._$updated; + // } + + // /** + // * @param {number} width + // * @param {number} height + // * @param {Float32Array} matrix + // * @param {array} [filters=null] + // * @param {boolean} [can_apply=false] + // * @param {number} [position_x=0] + // * @param {number} [position_y=0] + // * @return {boolean} + // * @private + // */ + // _$isFilterUpdated ( + // matrix: Float32Array, + // filters: FilterArrayImpl | null = null, + // can_apply: boolean = false + // ): boolean { + + // // cache flag + // if (this._$isUpdated()) { + // return true; + // } + + // // check filter data + // if (can_apply && filters) { + + // for (let idx: number = 0; idx < filters.length; ++idx) { + + // if (!filters[idx]._$isUpdated()) { + // continue; + // } + + // return true; + // } + + // } + + // // check status + // const cache: CachePositionImpl = $cacheStore.get([this._$instanceId, "f"]); + + // if (!cache) { + // return true; + // } + + // if (cache.filterState !== can_apply) { + // return true; + // } + + // if (cache.matrix !== `${matrix[0]}_${matrix[1]}_${matrix[2]}_${matrix[3]}`) { + // return true; + // } + + // return false; + // } + + // /** + // * @param {CanvasToWebGLContext} context + // * @param {array} filters + // * @param {WebGLTexture} target_texture + // * @param {Float32Array} matrix + // * @param {number} width + // * @param {number} height + // * @return {WebGLTexture} + // * @private + // */ + // _$applyFilter ( + // context: CanvasToWebGLContext, + // filters: FilterArrayImpl, + // target_texture: WebGLTexture, + // matrix: Float32Array, + // width: number, height: number + // ): WebGLTexture { + + // const xScale: number = +$Math.sqrt( + // matrix[0] * matrix[0] + // + matrix[1] * matrix[1] + // ); + // const yScale: number = +$Math.sqrt( + // matrix[2] * matrix[2] + // + matrix[3] * matrix[3] + // ); + + // const radianX: number = $Math.atan2(matrix[1], matrix[0]); + // const radianY: number = $Math.atan2(0 - matrix[2], matrix[3]); + + // const parentMatrix: Float32Array = $getFloat32Array6( + // $Math.cos(radianX), $Math.sin(radianX), + // 0 - $Math.sin(radianY), $Math.cos(radianY), + // width / 2, height / 2 + // ); + + // const baseMatrix: Float32Array = $getFloat32Array6( + // 1, 0, 0, 1, + // 0 - target_texture.width / 2, + // 0 - target_texture.height / 2 + // ); + + // const multiMatrix: Float32Array = $multiplicationMatrix( + // parentMatrix, baseMatrix + // ); + // $poolFloat32Array6(parentMatrix); + // $poolFloat32Array6(baseMatrix); + + // const manager: FrameBufferManager = context.frameBuffer; + // const currentAttachment: AttachmentImpl | null = manager.currentAttachment; + + // const attachment: AttachmentImpl = manager + // .createCacheAttachment(width, height); + + // context._$bind(attachment); + + // context.reset(); + // context.setTransform( + // multiMatrix[0], multiMatrix[1], + // multiMatrix[2], multiMatrix[3], + // multiMatrix[4], multiMatrix[5] + // ); + // $poolFloat32Array6(multiMatrix); + + // context.drawImage(target_texture, + // 0, 0, target_texture.width, target_texture.height + // ); + + // // init + // context._$offsetX = 0; + // context._$offsetY = 0; + + // const filterMatrix: Float32Array = $getFloat32Array6( + // xScale, 0, 0, yScale, 0, 0 + // ); + + // let texture: WebGLTexture | null = null; + // for (let idx: number = 0; idx < filters.length; ++idx) { + // texture = filters[idx]._$applyFilter(context, filterMatrix); + // } + + // $poolFloat32Array6(filterMatrix); + + // if (!texture) { + // return target_texture; + // } + + // const offsetX: number = context._$offsetX; + // const offsetY: number = context._$offsetY; + + // // reset + // context._$offsetX = 0; + // context._$offsetY = 0; + + // // set offset + // texture.offsetX = offsetX; + // texture.offsetY = offsetY; + + // // cache texture + // texture.matrix = + // matrix[0] + "_" + matrix[1] + "_" + // + matrix[2] + "_" + matrix[3]; + + // texture.filterState = true; + + // context._$bind(currentAttachment); + // manager.releaseAttachment(attachment, false); + + // return texture; + // } + + // /** + // * @param {CanvasToWebGLContext} context + // * @param {Float32Array} matrix + // * @param {array} filters + // * @param {number} width + // * @param {number} height + // * @param {WebGLTexture} [target_texture = null] + // * @return {object} + // * @method + // * @private + // */ + // _$drawFilter ( + // context: CanvasToWebGLContext, + // matrix: Float32Array, + // filters: FilterArrayImpl, + // width: number, + // height: number, + // target_texture: WebGLTexture | null = null + // ): CachePositionImpl { + + // const cacheKeys: any[] = $getArray(this._$instanceId, "f"); + // let position: CachePositionImpl | void = $cacheStore.get(cacheKeys); + + // const updated: boolean = this._$isFilterUpdated(matrix, filters, true); + + // if (position && !updated) { + // context.cachePosition = position; + // return position; + // } + + // // cache clear + // if (position) { + // $cacheStore.set(cacheKeys, null); + // } + + // const manager: FrameBufferManager = context.frameBuffer; + // const targetTexture: WebGLTexture = target_texture + // ? target_texture + // : context.getTextureFromRect( + // context.cachePosition as NonNullable + // ); + + // const texture: WebGLTexture = this._$applyFilter( + // context, filters, targetTexture, + // matrix, width, height + // ); + // manager.textureManager.release(targetTexture); + + // const bounds: BoundsImpl = this._$getLayerBounds(matrix); + // position = manager.createCachePosition( + // $Math.ceil($Math.abs(bounds.xMax - bounds.xMin)), + // $Math.ceil($Math.abs(bounds.yMax - bounds.yMin)) + // ); + + // $poolBoundsObject(bounds); + // position.filterState = true; + // position.matrix = `${matrix[0]}_${matrix[1]}_${matrix[2]}_${matrix[3]}_0_0`; + // position.offsetX = texture.offsetX; + // position.offsetY = texture.offsetY; + + // // 関数先でtextureがreleaseされる + // context.drawTextureFromRect(texture, position); + + // $cacheStore.set(cacheKeys, position); + // $poolArray(cacheKeys); + + // return position; + // } +} \ No newline at end of file diff --git a/packages/renderer/src/RendererDisplayObjectContainer.ts b/packages/renderer/src/RendererDisplayObjectContainer.ts new file mode 100644 index 00000000..84f9cbec --- /dev/null +++ b/packages/renderer/src/RendererDisplayObjectContainer.ts @@ -0,0 +1,783 @@ +import { RendererDisplayObject } from "./RendererDisplayObject"; +// import type { RenderDisplayObjectImpl } from "../interface/RenderDisplayObjectImpl"; +// import type { FilterArrayImpl } from "../interface/FilterArrayImpl"; +// import type { BlendModeImpl } from "../interface/BlendModeImpl"; +// import type { BoundsImpl } from "../interface/BoundsImpl"; +// import type { AttachmentImpl } from "../interface/AttachmentImpl"; +// import type { ParentImpl } from "../interface/ParentImpl"; +// import type { PreObjectImpl } from "../interface/PreObjectImpl"; +// import type { +// CanvasToWebGLContext, +// FrameBufferManager +// } from "@next2d/webgl"; +// import { +// $containers, +// $renderPlayer +// } from "../RenderGlobal"; + +/** + * @class + */ +export class RendererDisplayObjectContainer extends RendererDisplayObject +{ + private _$children: Int32Array; + + /** + * @constructor + * @public + */ + constructor () + { + super(); + + /** + * @type {Int32Array} + * @private + */ + this._$children = new Int32Array(); + } + + // /** + // * @param {CanvasToWebGLContext} context + // * @param {Float32Array} matrix + // * @return {void} + // * @method + // * @private + // */ + // _$clip ( + // context: CanvasToWebGLContext, + // matrix: Float32Array + // ): void { + + // let multiMatrix: Float32Array = matrix; + // const rawMatrix: Float32Array = this._$matrix; + // if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 + // || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 + // || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 + // ) { + // multiMatrix = $multiplicationMatrix(matrix, rawMatrix); + // } + + // const instances: Map> = $renderPlayer.instances; + // const children: Int32Array = this._$children; + // for (let idx: number = 0; idx < this._$children.length; ++idx) { + + // const id: number = children[idx]; + // if (!instances.has(id)) { + // continue; + // } + + // const instance: RenderDisplayObjectImpl | void = instances.get(id); + + // // mask instance + // if (!instance || instance._$isMask) { + // continue; + // } + + // instance._$clip(context, multiMatrix); + // instance._$updated = false; + + // } + + // if (multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + // } + + // /** + // * @param {CanvasToWebGLContext} context + // * @param {Float32Array} matrix + // * @param {Float32Array} color_transform + // * @return {void} + // * @method + // * @private + // */ + // _$draw ( + // context: CanvasToWebGLContext, + // matrix: Float32Array, + // color_transform: Float32Array + // ): void { + + // // not draw + // if (!this._$visible) { + // return ; + // } + + // let multiColor: Float32Array = color_transform; + // const rawColor: Float32Array = this._$colorTransform; + // if (rawColor[0] !== 1 || rawColor[1] !== 1 + // || rawColor[2] !== 1 || rawColor[3] !== 1 + // || rawColor[4] !== 0 || rawColor[5] !== 0 + // || rawColor[6] !== 0 || rawColor[7] !== 0 + // ) { + // multiColor = $multiplicationColor(color_transform, rawColor); + // } + + // // not draw + // const alpha: number = $clamp(multiColor[3] + multiColor[7] / 255, 0, 1, 0); + // if (!alpha) { + // return ; + // } + + // // not draw + // const children: Int32Array = this._$children; + // const length: number = children.length; + // if (!length) { + // return ; + // } + + // // pre data + // const preObject: PreObjectImpl | null = this._$preDraw(context, matrix); + // if (!preObject) { + // return ; + // } + + // // use cache + // if (preObject.isLayer && !preObject.isUpdated) { + // this._$postDraw(context, matrix, multiColor, preObject); + // return ; + // } + + // const preMatrix: Float32Array = preObject.matrix as NonNullable; + // const preColorTransform: Float32Array = preObject.isLayer && preObject.color + // ? preObject.color + // : multiColor; + + // // init clip params + // let shouldClip: boolean = true; + // let clipDepth: number = 0; + + // // draw children + // const instances: Map> = $renderPlayer.instances; + // const isLayer: boolean = context.isLayer; + // for (let idx: number = 0; idx < length; ++idx) { + + // const id: number = children[idx]; + // if (!instances.has(id)) { + // continue; + // } + + // const instance: RenderDisplayObjectImpl = instances.get(id); + + // // mask instance + // if (instance._$isMask) { + // continue; + // } + + // // not layer mode + // const blendMode: BlendModeImpl = instance._$blendMode; + // if ((blendMode === "alpha" || blendMode === "erase") + // && !isLayer + // ) { + // continue; + // } + + // // mask end + // if (clipDepth + // && (instance._$depth > clipDepth || instance._$clipDepth > 0) + // ) { + + // context.restore(); + + // if (shouldClip) { + // context._$leaveClip(); + // } + + // // clear + // clipDepth = 0; + // shouldClip = true; + // } + + // // mask size 0 + // if (!shouldClip) { + // continue; + // } + + // // mask start + // if (instance._$clipDepth > 0) { + + // clipDepth = instance._$clipDepth; + // shouldClip = instance._$shouldClip(preMatrix); + + // if (shouldClip) { + // context.save(); + // shouldClip = instance._$startClip(context, preMatrix); + // } + + // continue; + // } + + // // mask start + // const maskInstance: RenderDisplayObjectImpl | null = instance._$maskId > -1 && instances.has(instance._$maskId) + // ? instances.get(instance._$maskId) + // : null; + + // if (maskInstance) { + + // maskInstance._$updated = false; + + // let maskMatrix: Float32Array; + + // if (this._$instanceId === maskInstance._$parentId) { + + // maskMatrix = preMatrix; + + // } else { + + // maskMatrix = $MATRIX_ARRAY_IDENTITY; + + // let parent: ParentImpl | void = instances.get(maskInstance._$parentId); + // while (parent || parent._$instanceId !== parent._$parentId) { + + // maskMatrix = $multiplicationMatrix( + // parent._$matrix, + // maskMatrix + // ); + + // parent = instances.get(parent._$parentId); + // } + + // const mScale: number = $renderPlayer.scaleX; + // const playerMatrix: Float32Array = $getFloat32Array6( + // mScale, 0, 0, mScale, 0, 0 + // ); + + // maskMatrix = $multiplicationMatrix( + // playerMatrix, maskMatrix + // ); + // $poolFloat32Array6(playerMatrix); + + // if (context.isLayer) { + // const currentPosition: BoundsImpl = context.getCurrentPosition(); + // maskMatrix[4] -= currentPosition.xMin; + // maskMatrix[5] -= currentPosition.yMin; + // } + // } + + // if (!maskInstance._$shouldClip(maskMatrix)) { + // continue; + // } + + // const result: boolean = maskInstance._$startClip(context, maskMatrix); + + // context.save(); + + // if (!result) { // fixed + // context.restore(); + // continue; + // } + // } + + // instance._$draw(context, preMatrix, preColorTransform); + // instance._$updated = false; + + // // mask end + // if (maskInstance) { + // context.restore(); + // context._$leaveClip(); + // } + // } + + // // end mask + // if (clipDepth) { + // context.restore(); + + // if (shouldClip) { + // context._$leaveClip(); + // } + // } + + // // filter and blend + // if (preObject.isLayer) { + // return this._$postDraw(context, matrix, multiColor, preObject); + // } + + // if (preObject.matrix !== matrix) { + // $poolFloat32Array6(preObject.matrix as NonNullable); + // } + + // if (multiColor !== color_transform) { + // $poolFloat32Array8(multiColor); + // } + + // $poolPreObject(preObject); + // } + + // /** + // * @param {Float32Array} multi_matrix + // * @return {object} + // * @private + // */ + // _$getLayerBounds (multi_matrix: Float32Array): BoundsImpl + // { + // const children: Int32Array = this._$children; + // const length: number = children.length; + + // // size zero + // if (!length) { + // return $getBoundsObject(0, 0, 0, 0); + // } + + // // data init + // const no: number = $Number.MAX_VALUE; + // let xMin: number = no; + // let xMax: number = -no; + // let yMin: number = no; + // let yMax: number = -no; + + // const instances: Map> = $renderPlayer.instances; + // for (let idx: number = 0; idx < children.length; ++idx) { + + // const id: number = children[idx]; + // if (!instances.has(id)) { + // continue; + // } + + // const instance = instances.get(id); + + // let multiMatrix = multi_matrix; + // const rawMatrix: Float32Array = instance._$matrix; + // if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 + // || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 + // || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 + // ) { + // multiMatrix = $multiplicationMatrix(multi_matrix, rawMatrix); + // } + + // const bounds: BoundsImpl = instance._$getLayerBounds(multiMatrix); + + // xMin = $Math.min(xMin, bounds.xMin); + // xMax = $Math.max(xMax, bounds.xMax); + // yMin = $Math.min(yMin, bounds.yMin); + // yMax = $Math.max(yMax, bounds.yMax); + + // $poolBoundsObject(bounds); + + // if (multiMatrix !== multi_matrix) { + // $poolFloat32Array6(multiMatrix); + // } + // } + + // if (!this._$filters || !this._$filters.length) { + // return $getBoundsObject(xMin, xMax, yMin, yMax); + // } + + // let filterBounds: BoundsImpl = $getBoundsObject( + // 0, xMax - xMin, + // 0, yMax - yMin + // ); + + // let xScale: number = +$Math.sqrt( + // multi_matrix[0] * multi_matrix[0] + // + multi_matrix[1] * multi_matrix[1] + // ); + // let yScale: number = +$Math.sqrt( + // multi_matrix[2] * multi_matrix[2] + // + multi_matrix[3] * multi_matrix[3] + // ); + + // xScale /= $devicePixelRatio; + // yScale /= $devicePixelRatio; + + // xScale *= 2; + // yScale *= 2; + // for (let idx: number = 0; idx < this._$filters.length; ++idx) { + // filterBounds = this._$filters[idx] + // ._$generateFilterRect(filterBounds, xScale, yScale); + // } + + // xMax += filterBounds.xMax - (xMax - xMin); + // yMax += filterBounds.yMax - (yMax - yMin); + // xMin += filterBounds.xMin; + // yMin += filterBounds.yMin; + + // $poolBoundsObject(filterBounds); + + // return $getBoundsObject(xMin, xMax, yMin, yMax); + // } + + // /** + // * @param {Float32Array} [matrix=null] + // * @returns {object} + // * @method + // * @private + // */ + // _$getBounds (matrix: Float32Array | null = null): BoundsImpl + // { + // let multiMatrix: Float32Array = $MATRIX_ARRAY_IDENTITY; + // if (matrix) { + + // multiMatrix = matrix; + + // const rawMatrix: Float32Array = this._$matrix; + // if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 + // || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 + // || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 + // ) { + // multiMatrix = $multiplicationMatrix(matrix, rawMatrix); + // } + // } + + // const children: Int32Array = this._$children; + // const length: number = children.length; + + // // size zero + // if (!length) { + + // const bounds: BoundsImpl = $getBoundsObject( + // multiMatrix[4], -multiMatrix[4], + // multiMatrix[5], -multiMatrix[5] + // ); + + // if (matrix && multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + + // return bounds; + // } + + // // data init + // const no = $Number.MAX_VALUE; + // let xMin = no; + // let xMax = -no; + // let yMin = no; + // let yMax = -no; + + // const instances: Map> = $renderPlayer.instances; + // for (let idx: number = 0; idx < children.length; ++idx) { + + // const id: number = children[idx]; + // if (!instances.has(id)) { + // continue; + // } + + // const bounds: BoundsImpl = instances + // .get(id) + // ._$getBounds(multiMatrix); + + // xMin = $Math.min(xMin, bounds.xMin); + // xMax = $Math.max(xMax, bounds.xMax); + // yMin = $Math.min(yMin, bounds.yMin); + // yMax = $Math.max(yMax, bounds.yMax); + + // $poolBoundsObject(bounds); + + // } + + // if (matrix && multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + + // // end + // return $getBoundsObject(xMin, xMax, yMin, yMax); + // } + + // /** + // * @param {CanvasToWebGLContext} context + // * @param {Float32Array} matrix + // * @return {object} + // * @private + // */ + // _$preDraw ( + // context: CanvasToWebGLContext, + // matrix: Float32Array + // ): PreObjectImpl | null { + + // let multiMatrix: Float32Array = matrix; + // const rawMatrix: Float32Array = this._$matrix; + // if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 + // || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 + // || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 + // ) { + // multiMatrix = $multiplicationMatrix(matrix, rawMatrix); + // } + + // // size zero + // if (!multiMatrix[0] && !multiMatrix[1] + // || !multiMatrix[2] && !multiMatrix[3] + // ) { + // return null; + // } + + // // return object + // const object: PreObjectImpl = $getPreObject(); + + // // setup + // object.matrix = multiMatrix; + + // // check + // const blendMode: BlendModeImpl = this._$blendMode; + // if (blendMode !== "normal" + // || this._$filters && this._$filters.length > 0 + // ) { + + // // check size + // const baseBounds: BoundsImpl = this._$getBounds(null); + // const bounds: BoundsImpl = $boundsMatrix(baseBounds, multiMatrix); + // $poolBoundsObject(baseBounds); + + // const xMax: number = +bounds.xMax; + // const xMin: number = +bounds.xMin; + // const yMax: number = +bounds.yMax; + // const yMin: number = +bounds.yMin; + // $poolBoundsObject(bounds); + + // const width: number = $Math.ceil($Math.abs(xMax - xMin)); + // const height: number = $Math.ceil($Math.abs(yMax - yMin)); + // if (0 >= width || 0 >= height) { + // $poolPreObject(object); + // if (multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + // return null; + // } + + // let xScale: number = +$Math.sqrt( + // multiMatrix[0] * multiMatrix[0] + // + multiMatrix[1] * multiMatrix[1] + // ); + // if (!$Number.isInteger(xScale)) { + // const value: string = xScale.toString(); + // const index: number = value.indexOf("e"); + // if (index !== -1) { + // xScale = +value.slice(0, index); + // } + // xScale = +xScale.toFixed(4); + // } + + // let yScale: number = +$Math.sqrt( + // multiMatrix[2] * multiMatrix[2] + // + multiMatrix[3] * multiMatrix[3] + // ); + // if (!$Number.isInteger(yScale)) { + // const value: string = yScale.toString(); + // const index: number = value.indexOf("e"); + // if (index !== -1) { + // yScale = +value.slice(0, index); + // } + // yScale = +yScale.toFixed(4); + // } + + // object.canApply = this._$canApply(this._$filters); + // let filterBounds: BoundsImpl = $getBoundsObject(0, width, 0, height); + // if (object.canApply && this._$filters) { + // for (let idx: number = 0; idx < this._$filters.length ; ++idx) { + // filterBounds = this._$filters[idx] + // ._$generateFilterRect(filterBounds, xScale, yScale); + // } + // } + + // const currentAttachment: AttachmentImpl | null = context + // .frameBuffer + // .currentAttachment; + + // if (!currentAttachment + // || !currentAttachment.texture + // || xMin - filterBounds.xMin > currentAttachment.width + // || yMin - filterBounds.yMin > currentAttachment.height + // ) { + // $poolBoundsObject(filterBounds); + // $poolPreObject(object); + // if (multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + // return null; + // } + + // if (0 > xMin + filterBounds.xMax || 0 > yMin + filterBounds.yMax) { + // $poolBoundsObject(filterBounds); + // $poolPreObject(object); + // if (multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + // return null; + // } + + // // move size + // let tx: number = multiMatrix[4] - xMin; + // let ty: number = multiMatrix[5] - yMin; + + // // start layer + // context._$startLayer( + // $getBoundsObject(xMin, xMax, yMin, yMax) + // ); + + // // check cache + // const updated: boolean = this._$isFilterUpdated( + // multiMatrix, this._$filters, object.canApply + // ); + + // const layerBounds: BoundsImpl = this._$getLayerBounds(multiMatrix); + + // const layerWidth: number = $Math.ceil($Math.abs(layerBounds.xMax - layerBounds.xMin)); + // const layerHeight: number = $Math.ceil($Math.abs(layerBounds.yMax - layerBounds.yMin)); + // $poolBoundsObject(layerBounds); + + // const sw = layerWidth - filterBounds.xMax + filterBounds.xMin; + // const sh = layerHeight - filterBounds.yMax + filterBounds.yMin; + + // tx += sw; + // ty += sh; + + // object.sw = sw; + // object.sh = sh; + // if (updated) { + // context._$saveAttachment( + // $Math.ceil(width + sw), + // $Math.ceil(height + sh), + // true + // ); + // } + + // // setup + // object.isLayer = true; + // object.isUpdated = updated; + // object.filters = this._$filters; + // object.blendMode = blendMode; + // object.color = $getFloat32Array8(); + // object.matrix = $getFloat32Array6( + // multiMatrix[0], multiMatrix[1], + // multiMatrix[2], multiMatrix[3], + // tx, ty + // ); + + // if (multiMatrix !== matrix) { + // $poolFloat32Array6(multiMatrix); + // } + + // $poolBoundsObject(filterBounds); + // } + + // return object; + // } + + // /** + // * @param {CanvasToWebGLContext} context + // * @param {Float32Array} matrix + // * @param {Float32Array} color_transform + // * @param {object} object + // * @return {void} + // * @method + // * @private + // */ + // _$postDraw ( + // context: CanvasToWebGLContext, + // matrix: Float32Array, + // color_transform: Float32Array, + // object: PreObjectImpl + // ): void { + + // context.drawInstacedArray(); + + // // cache + // const cacheKeys: any[] = $getArray(this._$instanceId, "f"); + + // const manager: FrameBufferManager = context.frameBuffer; + // const multiMatrix: Float32Array = object.matrix as NonNullable; + + // let offsetX: number = 0; + // let offsetY: number = 0; + // let texture: WebGLTexture | null = $cacheStore.get(cacheKeys); + + // if (!texture || object.isUpdated) { + + // // remove + // if (texture) { + // $cacheStore.set(cacheKeys, null); + // } + + // texture = manager + // .getTextureFromCurrentAttachment(); + + // const filters: FilterArrayImpl | null = object.filters; + // let filterState = false; + // if (filters && filters.length) { + + // for (let idx: number = 0; idx < filters.length; ++idx) { + // texture = filters[idx] + // ._$applyFilter(context, matrix); + // } + + // // update + // filterState = true; + // offsetX = context._$offsetX; + // offsetY = context._$offsetY; + + // // reset + // context._$offsetX = 0; + // context._$offsetY = 0; + // } + + // texture.filterState = filterState; + // texture.matrix = `${multiMatrix[0]}_` + // + `${multiMatrix[1]}_` + // + `${multiMatrix[2]}_` + // + `${multiMatrix[3]}`; + + // texture.offsetX = offsetX; + // texture.offsetY = offsetY; + + // $cacheStore.set(cacheKeys, texture); + + // context._$restoreAttachment(); + // } + + // if (texture.offsetX) { + // offsetX = texture.offsetX; + // } + + // if (texture.offsetY) { + // offsetY = texture.offsetY; + // } + + // // set + // context.reset(); + // context.globalAlpha = $clamp( + // color_transform[3] + color_transform[7] / 255, 0, 1 + // ); + // context.globalCompositeOperation = object.blendMode; + + // const bounds: BoundsImpl = context.getCurrentPosition(); + + // context.setTransform( + // 1, 0, 0, 1, + // bounds.xMin - offsetX - object.sw, + // bounds.yMin - offsetY - object.sh + // ); + + // context.drawImage(texture, + // 0, 0, texture.width, texture.height, + // color_transform + // ); + + // // end blend + // context._$endLayer(); + + // // end blend + // context._$endLayer(); + + // // object pool + // $poolFloat32Array6(object.matrix as NonNullable); + // $poolPreObject(object); + + // // reset + // context.cachePosition = null; + // } + + // /** + // * @description Playerから登録を削除 + // * + // * @return {void} + // * @method + // * @private + // */ + // _$remove (): void + // { + // // reset + // this._$children = new Int32Array(); + + // super._$remove(); + + // $containers.push(this); + // } +} \ No newline at end of file diff --git a/packages/renderer/src/RendererGraphics.ts b/packages/renderer/src/RendererGraphics.ts new file mode 100644 index 00000000..f27ebad6 --- /dev/null +++ b/packages/renderer/src/RendererGraphics.ts @@ -0,0 +1,1176 @@ +import { RenderDisplayObject } from "./RenderDisplayObject"; +import type { GridImpl } from "../interface/GridImpl"; +import type { BlendModeImpl } from "../interface/BlendModeImpl"; +import type { FilterArrayImpl } from "../interface/FilterArrayImpl"; +import type { BoundsImpl } from "../interface/BoundsImpl"; +import type { AttachmentImpl } from "../interface/AttachmentImpl"; +import type { SpreadMethodImpl } from "../interface/SpreadMethodImpl"; +import type { PropertyMessageMapImpl } from "../interface/PropertyMessageMapImpl"; +import type { ColorStopImpl } from "../interface/ColorStopImpl"; +import type { CachePositionImpl } from "../interface/CachePositionImpl"; +import type { ShapeModeImpl } from "../interface/ShapeModeImpl"; +import type { + CanvasToWebGLContext, + CanvasGradientToWebGL, + FrameBufferManager +} from "@next2d/webgl"; +import { $renderPlayer } from "../RenderGlobal"; +import { + $cacheStore, + $clamp, + $getBoundsObject, + $boundsMatrix, + $Math, + $poolBoundsObject, + $Infinity, + $Number, + $getArray, + $poolArray, + $getFloat32Array6, + $getFloat32Array4, + $multiplicationMatrix, + $poolFloat32Array6, + $getInt32Array4, + $linearGradientXY, + $getFloat32Array8 +} from "@next2d/share"; + +/** + * @class + */ +export class RenderGraphics extends RenderDisplayObject +{ + public _$recodes: Float32Array | null; + public _$maxAlpha: number; + public _$canDraw: boolean; + private _$uniqueKey: string; + private _$cacheKeys: string[]; + private _$cacheParams: number[]; + public _$bitmapId: number; + public _$mode: ShapeModeImpl; + + /** + * @constructor + * @public + */ + constructor () + { + super(); + + /** + * @type {Float32Array} + * @default null + * @private + */ + this._$recodes = null; + + /** + * @type {number} + * @default 0 + * @private + */ + this._$maxAlpha = 0; + + /** + * @type {boolean} + * @default false + * @private + */ + this._$canDraw = false; + + /** + * @type {string} + * @default "" + * @private + */ + this._$uniqueKey = ""; + + /** + * @type {array} + * @private + */ + this._$cacheKeys = $getArray(); + + /** + * @type {array} + * @private + */ + this._$cacheParams = $getArray(0, 0, 0); + + /** + * @type {number} + * @default 0 + * @private + */ + this._$bitmapId = 0; + + /** + * @type {string} + * @default "shape" + * @private + */ + this._$mode = "shape"; + } + + /** + * @param {CanvasToWebGLContext} context + * @param {Float32Array} matrix + * @return {void} + * @method + * @private + */ + _$clip ( + context: CanvasToWebGLContext, + matrix: Float32Array + ): void { + + if (!this._$recodes) { + return ; + } + + // size + const baseBounds: BoundsImpl = this._$getBounds(); + + const bounds: BoundsImpl = $boundsMatrix(baseBounds, matrix); + $poolBoundsObject(baseBounds); + + const width: number = $Math.ceil($Math.abs(bounds.xMax - bounds.xMin)); + const height: number = $Math.ceil($Math.abs(bounds.yMax - bounds.yMin)); + $poolBoundsObject(bounds); + + switch (true) { + + case width === 0: + case height === 0: + case width === -$Infinity: + case height === -$Infinity: + case width === $Infinity: + case height === $Infinity: + return; + + default: + break; + + } + + context.reset(); + context.setTransform( + matrix[0], matrix[1], matrix[2], + matrix[3], matrix[4], matrix[5] + ); + + this._$runCommand(context, this._$recodes, null, true); + + context.clip(); + } + + /** + * @return {string} + * @method + * @private + */ + _$createCacheKey (): string + { + if (!this._$recodes) { + return ""; + } + + let hash = 0; + for (let idx: number = 0; idx < this._$recodes.length; idx++) { + + const chr: number = this._$recodes[idx]; + + hash = (hash << 5) - hash + chr; + hash |= 0; + } + + return `${hash}`; + } + + /** + * @return {WebGLTexture | null} + * @method + * @private + */ + _$createBitmapTexture ( + context: CanvasToWebGLContext, + position: CachePositionImpl, + x_scale: number, + y_scale: number, + width: number, + height: number + ): WebGLTexture | null { + + if (this._$mode !== "bitmap") { + return null; + } + + context.drawInstacedArray(); + + const manager: FrameBufferManager = context.frameBuffer; + const currentAttachment: AttachmentImpl | null = manager.currentAttachment; + + const attachment: AttachmentImpl = manager + .createCacheAttachment(width, height); + + context._$bind(attachment); + + context.reset(); + + const parentMatrix: Float32Array = $getFloat32Array6( + x_scale, 0, 0, y_scale, + width / 2, height / 2 + ); + + const texture: WebGLTexture = context.getTextureFromRect(position); + + const baseMatrix: Float32Array = $getFloat32Array6( + 1, 0, 0, 1, + -texture.width / 2, + -texture.height / 2 + ); + + const scaleMatrix = $multiplicationMatrix( + parentMatrix, baseMatrix + ); + $poolFloat32Array6(parentMatrix); + $poolFloat32Array6(baseMatrix); + + context.setTransform( + scaleMatrix[0], scaleMatrix[1], + scaleMatrix[2], scaleMatrix[3], + scaleMatrix[4], scaleMatrix[5] + ); + + context.drawImage(texture, 0, 0, texture.width, texture.height); + + const bitmapTexture: WebGLTexture = manager.getTextureFromCurrentAttachment(); + context._$bind(currentAttachment); + + manager.releaseAttachment(attachment); + manager.textureManager.release(texture); + + return bitmapTexture; + } + + /** + * @param {CanvasToWebGLContext} context + * @param {Float32Array} matrix + * @param {Float32Array} color_transform + * @param {string} [blend_mode=BlendMode.NORMAL] + * @param {array} [filters=null] + * @return {void} + * @method + * @private + */ + _$draw ( + context: CanvasToWebGLContext, + matrix: Float32Array, + color_transform: Float32Array, + blend_mode: BlendModeImpl = "normal", + filters: FilterArrayImpl | null = null + ): void { + + if (!this._$visible + || !this._$recodes + || !this._$maxAlpha + || !this._$canDraw + ) { + return ; + } + + const alpha: number = $clamp(color_transform[3] + color_transform[7] / 255, 0, 1, 0); + if (!alpha) { + return ; + } + + const rawMatrix: Float32Array = this._$matrix; + + // set grid data + let hasGrid: boolean = this._$scale9Grid !== null; + + // 9スライスを有効にしたオブジェクトが回転・傾斜成分を含む場合は + // 9スライスは無効になる + if (hasGrid) { + hasGrid = hasGrid + && $Math.abs(rawMatrix[1]) < 0.001 + && $Math.abs(rawMatrix[2]) < 0.0001; + } + + // size + const baseBounds: BoundsImpl = $getBoundsObject( + this._$xMin, this._$xMax, + this._$yMin, this._$yMax + ); + + const bounds: BoundsImpl = $boundsMatrix(baseBounds, matrix); + const xMax: number = bounds.xMax; + const xMin: number = bounds.xMin; + const yMax: number = bounds.yMax; + const yMin: number = bounds.yMin; + $poolBoundsObject(bounds); + + const width: number = $Math.ceil($Math.abs(xMax - xMin)); + const height: number = $Math.ceil($Math.abs(yMax - yMin)); + switch (true) { + + case width === 0: + case height === 0: + case width === 0 - $Infinity: + case height === 0 - $Infinity: + case width === $Infinity: + case height === $Infinity: + return; + + default: + break; + + } + + let xScale: number = +$Math.sqrt( + matrix[0] * matrix[0] + + matrix[1] * matrix[1] + ); + if (!$Number.isInteger(xScale)) { + const value: string = xScale.toString(); + const index: number = value.indexOf("e"); + if (index !== -1) { + xScale = +value.slice(0, index); + } + xScale = +xScale.toFixed(4); + } + + let yScale: number = +$Math.sqrt( + matrix[2] * matrix[2] + + matrix[3] * matrix[3] + ); + if (!$Number.isInteger(yScale)) { + const value: string = yScale.toString(); + const index: number = value.indexOf("e"); + if (index !== -1) { + yScale = +value.slice(0, index); + } + yScale = +yScale.toFixed(4); + } + + const canApply: boolean = filters !== null + && filters.length > 0 + && this._$canApply(filters); + + let filterBounds: BoundsImpl = $getBoundsObject(0, width, 0, height); + if (canApply && filters) { + for (let idx: number = 0; idx < filters.length ; ++idx) { + filterBounds = filters[idx] + ._$generateFilterRect(filterBounds, xScale, yScale); + } + } + + // cache current buffer + const manager: FrameBufferManager = context.frameBuffer; + const currentAttachment: AttachmentImpl | null = manager.currentAttachment; + if (!currentAttachment + || xMin - filterBounds.xMin > currentAttachment.width + || yMin - filterBounds.yMin > currentAttachment.height + ) { + $poolBoundsObject(filterBounds); + return; + } + + if (0 > xMin + filterBounds.xMax || 0 > yMin + filterBounds.yMax) { + $poolBoundsObject(filterBounds); + return; + } + + $poolBoundsObject(filterBounds); + + // get cache + if (this._$uniqueKey === "") { + if (!hasGrid + && this._$loaderInfoId > -1 + && this._$characterId > -1 + ) { + this._$uniqueKey = `${this._$loaderInfoId}@${this._$characterId}`; + } else { + this._$uniqueKey = this._$createCacheKey(); + } + } + + if (this._$mode === "bitmap") { + + if (!this._$cacheKeys.length) { + this._$cacheKeys = $cacheStore.generateKeys(this._$uniqueKey); + } + + } else { + + if (!this._$cacheKeys.length + || this._$cacheParams[0] !== xScale + || this._$cacheParams[1] !== yScale + || this._$cacheParams[2] !== color_transform[7] + ) { + + const keys: number[] = $getArray(); + keys[0] = xScale; + keys[1] = yScale; + + this._$cacheKeys = $cacheStore.generateKeys( + this._$uniqueKey, keys, color_transform + ); + + $poolArray(keys); + + this._$cacheParams[0] = xScale; + this._$cacheParams[1] = yScale; + this._$cacheParams[2] = color_transform[7]; + } + } + + context.cachePosition = $cacheStore.get(this._$cacheKeys); + if (!context.cachePosition) { + + const currentAttachment: AttachmentImpl | null = manager.currentAttachment; + + if (currentAttachment && currentAttachment.mask) { + context.stopStencil(); + } + + let width: number = 0; + let height: number = 0; + if (this._$mode === "shape") { + + width = $Math.ceil($Math.abs(baseBounds.xMax - baseBounds.xMin) * xScale); + height = $Math.ceil($Math.abs(baseBounds.yMax - baseBounds.yMin) * yScale); + + // resize + const textureScale: number = context._$getTextureScale(width, height); + if (textureScale < 1) { + width *= textureScale; + height *= textureScale; + } + + } else { + width = $Math.ceil($Math.abs(baseBounds.xMax - baseBounds.xMin)); + height = $Math.ceil($Math.abs(baseBounds.yMax - baseBounds.yMin)); + } + + // create cache position + context.cachePosition = manager.createCachePosition(width, height); + context.bindRenderBuffer(context.cachePosition); + + // reset + context.reset(); + + if (this._$mode === "shape") { + context.setTransform( + xScale, 0, 0, yScale, + -baseBounds.xMin * xScale, + -baseBounds.yMin * yScale + ); + } else { + context.setTransform( + 1, 0, 0, 1, + -baseBounds.xMin, + -baseBounds.yMin + ); + } + + if (hasGrid) { + + const mScale: number = $renderPlayer.scaleX; + + const baseMatrix: Float32Array = $getFloat32Array6( + mScale, 0, 0, mScale, 0, 0 + ); + + const pMatrix: Float32Array = $multiplicationMatrix( + baseMatrix, rawMatrix + ); + + $poolFloat32Array6(baseMatrix); + + const aMatrixBase: Float32Array = this._$matrixBase as NonNullable; + const aMatrix = $getFloat32Array6( + aMatrixBase[0], aMatrixBase[1], + aMatrixBase[2], aMatrixBase[3], + aMatrixBase[4] * mScale - xMin, + aMatrixBase[5] * mScale - yMin + ); + + const apMatrix: Float32Array = $multiplicationMatrix( + aMatrix, pMatrix + ); + + const aOffsetX: number = apMatrix[4] - (matrix[4] - xMin); + const aOffsetY: number = apMatrix[5] - (matrix[5] - yMin); + $poolFloat32Array6(apMatrix); + + const parentBounds: BoundsImpl = $boundsMatrix(baseBounds, pMatrix); + const parentXMax: number = +parentBounds.xMax; + const parentXMin: number = +parentBounds.xMin; + const parentYMax: number = +parentBounds.yMax; + const parentYMin: number = +parentBounds.yMin; + const parentWidth: number = $Math.ceil($Math.abs(parentXMax - parentXMin)); + const parentHeight: number = $Math.ceil($Math.abs(parentYMax - parentYMin)); + + $poolBoundsObject(parentBounds); + + context.grid.enable( + parentXMin, parentYMin, parentWidth, parentHeight, + baseBounds, this._$scale9Grid as NonNullable, mScale, + pMatrix[0], pMatrix[1], pMatrix[2], pMatrix[3], pMatrix[4], pMatrix[5], + aMatrix[0], aMatrix[1], aMatrix[2], aMatrix[3], aMatrix[4] - aOffsetX, aMatrix[5] - aOffsetY + ); + + $poolFloat32Array6(pMatrix); + $poolFloat32Array6(aMatrix); + } + + this._$runCommand(context, this._$recodes, color_transform, false); + + if (hasGrid) { + context.grid.disable(); + } + + manager.transferTexture(context.cachePosition); + + // set cache + $cacheStore.set(this._$cacheKeys, context.cachePosition); + + // end draw and reset current buffer + context._$bind(currentAttachment); + } + + let offsetX: number = 0; + let offsetY: number = 0; + if (canApply && filters) { + + const bitmapTexture: WebGLTexture | null = this._$createBitmapTexture( + context, context.cachePosition, + xScale, yScale, width, height + ); + + const position: CachePositionImpl = this._$drawFilter( + context, matrix, filters, + width, height, bitmapTexture + ); + + if (position.offsetX) { + offsetX = position.offsetX; + } + + if (position.offsetY) { + offsetY = position.offsetY; + } + + // update + context.cachePosition = position; + } + + if (!canApply && this._$mode === "bitmap") { + + context.setTransform( + matrix[0], matrix[1], + matrix[2], matrix[3], + baseBounds.xMin * matrix[0] + baseBounds.yMin * matrix[2] + matrix[4], + baseBounds.xMin * matrix[1] + baseBounds.yMin * matrix[3] + matrix[5] + ); + + } else { + + const radianX: number = $Math.atan2(matrix[1], matrix[0]); + const radianY: number = $Math.atan2(-matrix[2], matrix[3]); + if (!canApply && (radianX || radianY)) { + + const tx: number = baseBounds.xMin * xScale; + const ty: number = baseBounds.yMin * yScale; + + const cosX: number = $Math.cos(radianX); + const sinX: number = $Math.sin(radianX); + const cosY: number = $Math.cos(radianY); + const sinY: number = $Math.sin(radianY); + + context.setTransform( + cosX, sinX, -sinY, cosY, + tx * cosX - ty * sinY + matrix[4], + tx * sinX + ty * cosY + matrix[5] + ); + + } else { + + context.setTransform(1, 0, 0, 1, + xMin - offsetX, yMin - offsetY + ); + + } + } + + // draw + if (context.cachePosition) { + + context.globalAlpha = alpha; + context.imageSmoothingEnabled = this._$mode === "shape"; + context.globalCompositeOperation = blend_mode; + + context.drawInstance( + xMin - offsetX, yMin - offsetY, xMax, yMax, + color_transform + ); + + // cache position clear + context.cachePosition = null; + } + + // pool + $poolBoundsObject(baseBounds); + } + + /** + * @description strokeのセットアップ + * + * @param {CanvasToWebGLContext} context + * @param {number} line_width + * @param {number} line_cap + * @param {number} line_join + * @param {number} miter_limit + * @return {void} + * @method + * @public + */ + setupStroke ( + context: CanvasToWebGLContext, + line_width: number, line_cap: number, + line_join: number, miter_limit: number + ): void { + + context.lineWidth = line_width; + + switch (line_cap) { + + case 0: + context.lineCap = "none"; + break; + + case 1: + context.lineCap = "round"; + break; + + case 2: + context.lineCap = "square"; + break; + + } + + switch (line_join) { + + case 0: + context.lineJoin = "bevel"; + break; + + case 1: + context.lineJoin = "miter"; + break; + + case 2: + context.lineJoin = "round"; + break; + + } + + context.miterLimit = miter_limit; + } + + /** + * @description CanvasGradientToWebGLオブジェクトを生成 + * + * @param {CanvasToWebGLContext} context + * @param {number} type + * @param {array} stops + * @param {Float32Array} matrix + * @param {number} spread + * @param {number} interpolation + * @param {number} focal + * @param {Float32Array} [color_transform=null] + * @return {CanvasGradientToWebGL} + * @method + * @public + */ + createGradientStyle ( + context: CanvasToWebGLContext, + type: number, stops: ColorStopImpl[], + matrix: Float32Array, + spread: number, interpolation: number, focal: number, + color_transform: Float32Array | null = null + ): CanvasGradientToWebGL { + + let spreadMethod: SpreadMethodImpl = "pad"; + switch (spread) { + + case 0:// REFLECT + spreadMethod = "reflect"; + break; + + case 1: // REPEAT + spreadMethod = "repeat"; + break; + + } + + let css: CanvasGradientToWebGL; + if (type === 0) { + + // LINEAR + const xy: Float32Array = $linearGradientXY(matrix); + css = context.createLinearGradient( + xy[0], xy[1], xy[2], xy[3], + interpolation ? "rgb" : "linearRGB", + spreadMethod + ); + + } else { + + // RADIAL + context.save(); + context.transform( + matrix[0], matrix[1], matrix[2], + matrix[3], matrix[4], matrix[5] + ); + + css = context.createRadialGradient( + 0, 0, 0, 0, 0, 819.2, + interpolation ? "rgb" : "linearRGB", + spreadMethod, focal + ); + + } + + for (let idx: number = 0; idx < stops.length; ++idx) { + + const color: ColorStopImpl = stops[idx]; + + let alpha: number = color.A; + if (color_transform) { + if (color_transform[3] !== 1 || color_transform[7] !== 0) { + alpha = $Math.max(0, $Math.min(color.A * color_transform[3] + color_transform[7], 255)) | 0; + } + } + + css.addColorStop(color.ratio, $getInt32Array4( + color.R, color.G, color.B, alpha + )); + } + + return css; + } + + /** + * @description Graphicsクラスの描画を実行 + * Execute drawing in the Graphics class + * + * @param {CanvasToWebGLContext} context + * @param {Float32Array} recodes + * @param {Float32Array} [color_transform=null] + * @param {boolean} [is_clip=false] + * @return {void} + * @method + * @public + */ + _$runCommand ( + context: CanvasToWebGLContext, + recodes: Float32Array, + color_transform: Float32Array | null = null, + is_clip: boolean = false + ): void { + + // reset + context.reset(); + context.beginPath(); + + const length: number = recodes.length; + for (let idx: number = 0; idx < length; ) { + + switch (recodes[idx++]) { + + case 9: // BEGIN_PATH + context.beginPath(); + break; + + case 0: // MOVE_TO + context.moveTo(recodes[idx++], recodes[idx++]); + break; + + case 2: // LINE_TO + context.lineTo(recodes[idx++], recodes[idx++]); + break; + + case 1: // CURVE_TO + context.quadraticCurveTo( + recodes[idx++], recodes[idx++], + recodes[idx++], recodes[idx++] + ); + break; + + case 5: // FILL_STYLE + { + if (is_clip) { + idx += 4; + continue; + } + + const color: Float32Array = $getFloat32Array4(); + color[0] = recodes[idx++] / 255; + color[1] = recodes[idx++] / 255; + color[2] = recodes[idx++] / 255; + color[3] = recodes[idx++] / 255; + + if (color_transform !== null) { + if (color_transform[3] !== 1 || color_transform[7] !== 0) { + color[3] = $Math.max(0, $Math.min( + color[3] * color_transform[3] + color_transform[7], 255) + ) / 255; + } + } + + context.fillStyle = color; + } + break; + + case 7: // END_FILL + + if (!is_clip) { + context.fill(); + } + + break; + + case 6: // STROKE_STYLE + { + if (is_clip) { + idx += 8; + continue; + } + + this.setupStroke( + context, + recodes[idx++], recodes[idx++], + recodes[idx++], recodes[idx++] + ); + + const color = $getFloat32Array4(); + + color[0] = recodes[idx++] / 255; + color[1] = recodes[idx++] / 255; + color[2] = recodes[idx++] / 255; + color[3] = recodes[idx++] / 255; + + if (color_transform !== null) { + if (color_transform[3] !== 1 || color_transform[7] !== 0) { + color[3] = $Math.max(0, $Math.min( + color[3] * color_transform[3] + color_transform[7], 255) + ) / 255; + } + } + + context.strokeStyle = color; + } + break; + + case 8: // END_STROKE + if (!is_clip) { + context.stroke(); + } + break; + + case 12: // CLOSE_PATH + context.closePath(); + break; + + case 3: // CUBIC + context.bezierCurveTo( + recodes[idx++], recodes[idx++], + recodes[idx++], recodes[idx++], + recodes[idx++], recodes[idx++] + ); + break; + + case 4: // ARC + context.arc(recodes[idx++], recodes[idx++], recodes[idx++]); + break; + + case 10: // GRADIENT_FILL + { + if (is_clip) { + idx += 1; + const length = recodes[idx++]; + idx += length * 5; + idx += 9; + continue; + } + + const type: number = recodes[idx++]; + + let stopLength: number = recodes[idx++]; + const stops: ColorStopImpl[] = $getArray(); + while (stopLength) { + stops.push({ + "ratio": recodes[idx++], + "R": recodes[idx++], + "G": recodes[idx++], + "B": recodes[idx++], + "A": recodes[idx++] + }); + stopLength--; + } + + const matrix: Float32Array = $getFloat32Array6( + recodes[idx++], recodes[idx++], recodes[idx++], + recodes[idx++], recodes[idx++], recodes[idx++] + ); + + context.fillStyle = this.createGradientStyle( + context, type, stops, matrix, + recodes[idx++], recodes[idx++], recodes[idx++], + color_transform + ); + + context.fill(); + + // if RADIAL + if (type === 1) { + context.restore(); + } + + $poolFloat32Array6(matrix); + $poolArray(stops); + } + break; + + case 11: // GRADIENT_STROKE + { + if (is_clip) { + idx += 5; + const length = recodes[idx++]; + idx += length * 5; + idx += 9; + continue; + } + + this.setupStroke( + context, + recodes[idx++], recodes[idx++], + recodes[idx++], recodes[idx++] + ); + + const type: number = recodes[idx++]; + + let stopLength: number = recodes[idx++]; + + const stops: ColorStopImpl[] = $getArray(); + while (stopLength) { + stops.push({ + "ratio": recodes[idx++], + "R": recodes[idx++], + "G": recodes[idx++], + "B": recodes[idx++], + "A": recodes[idx++] + }); + stopLength--; + } + + const matrix: Float32Array = $getFloat32Array6( + recodes[idx++], recodes[idx++], recodes[idx++], + recodes[idx++], recodes[idx++], recodes[idx++] + ); + + context.strokeStyle = this.createGradientStyle( + context, type, stops, matrix, + recodes[idx++], recodes[idx++], recodes[idx++], + color_transform + ); + + context.stroke(); + + // if RADIAL + if (type === 1) { + context.restore(); + } + + $poolFloat32Array6(matrix); + $poolArray(stops); + } + break; + + case 13: // BITMAP_FILL + { + const width: number = recodes[idx++]; + const height: number = recodes[idx++]; + const graphicsWidth: number = recodes[idx++]; + const graphicsHeight: number = recodes[idx++]; + const bitmapLength: number = recodes[idx++]; + if (is_clip) { + idx += bitmapLength; + idx += 8; + continue; + } + + const buffer: Uint8Array = new Uint8Array( + recodes.subarray(idx, bitmapLength + idx) + ); + + idx += bitmapLength; + const matrix: Float32Array = $getFloat32Array6( + recodes[idx++], recodes[idx++], recodes[idx++], + recodes[idx++], recodes[idx++], recodes[idx++] + ); + + const repeat: boolean = !!recodes[idx++]; + const smooth: boolean = !!recodes[idx++]; + + context.save(); + + if (matrix[0] !== 1 || matrix[1] !== 0 + || matrix[2] !== 0 || matrix[3] !== 1 + || matrix[4] !== 0 || matrix[5] !== 0 + ) { + context.transform( + matrix[0], matrix[1], matrix[2], + matrix[3], matrix[4], matrix[5] + ); + } + $poolFloat32Array6(matrix); + + const manager: FrameBufferManager = context.frameBuffer; + const texture: WebGLTexture = manager.createTextureFromPixels( + width, height, buffer, true + ); + + if (!repeat + && width === graphicsWidth + && height === graphicsHeight + ) { + + context.drawImage(texture, 0, 0, width, height); + manager.releaseTexture(texture); + + } else { + + context.fillStyle = context.createPattern( + texture, repeat, color_transform || $getFloat32Array8() + ); + + context.imageSmoothingEnabled = smooth; + context.fill(); + + } + + // restore + context.restore(); + context.imageSmoothingEnabled = false; + + } + break; + + case 14: // BITMAP_STROKE + { + if (is_clip) { + idx += 4; + const bitmapLength = recodes[idx++]; + idx += bitmapLength; + idx += 8; + continue; + } + + context.save(); + + this.setupStroke( + context, + recodes[idx++], recodes[idx++], + recodes[idx++], recodes[idx++] + ); + + const width: number = recodes[idx++]; + const height: number = recodes[idx++]; + const bitmapLength: number = recodes[idx++]; + + const buffer: Uint8Array = new Uint8Array( + recodes.subarray(idx, bitmapLength + idx) + ); + + idx += bitmapLength; + const matrix: Float32Array = $getFloat32Array6( + recodes[idx++], recodes[idx++], recodes[idx++], + recodes[idx++], recodes[idx++], recodes[idx++] + ); + + if (matrix[0] !== 1 || matrix[1] !== 0 + || matrix[2] !== 0 || matrix[3] !== 1 + || matrix[4] !== 0 || matrix[5] !== 0 + ) { + context.transform( + matrix[0], matrix[1], matrix[2], + matrix[3], matrix[4], matrix[5] + ); + } + $poolFloat32Array6(matrix); + + const repeat: boolean = !!recodes[idx++]; + const smooth: boolean = !!recodes[idx++]; + + const manager: FrameBufferManager = context.frameBuffer; + const texture: WebGLTexture = manager.createTextureFromPixels( + width, height, buffer, true + ); + + context.strokeStyle = context.createPattern( + texture, repeat, color_transform || $getFloat32Array8() + ); + + context.imageSmoothingEnabled = smooth; + context.stroke(); + + // restore + context.restore(); + context.imageSmoothingEnabled = false; + } + break; + + default: + break; + + } + } + } + + /** + * @description 描画情報を更新 + * + * @param {object} object + * @return {void} + * @method + * @private + */ + _$update (object: PropertyMessageMapImpl): void + { + super._$update(object); + + if (object.recodes) { + + this._$recodes = object.recodes; + this._$xMin = object.xMin; + this._$yMin = object.yMin; + this._$xMax = object.xMax; + this._$yMax = object.yMax; + this._$maxAlpha = object.maxAlpha; + this._$canDraw = object.canDraw; + + $cacheStore.removeCache(this._$instanceId); + + if (this._$loaderInfoId > -1 + && this._$characterId > -1 + ) { + $cacheStore.removeCache( + `${this._$loaderInfoId}@${this._$characterId}` + ); + } + } + } +} \ No newline at end of file diff --git a/packages/renderer/src/RendererShape.ts b/packages/renderer/src/RendererShape.ts new file mode 100644 index 00000000..2c826a9f --- /dev/null +++ b/packages/renderer/src/RendererShape.ts @@ -0,0 +1,152 @@ +import { RenderGraphics } from "./RenderGraphics"; +import { $shapes } from "../RenderGlobal"; +import type { BoundsImpl } from "../interface/BoundsImpl"; +import type { CanvasToWebGLContext } from "@next2d/webgl"; +import { + $boundsMatrix, + $clamp, + $Infinity, + $Math, + $multiplicationColor, + $multiplicationMatrix, + $poolBoundsObject, + $poolFloat32Array6, + $poolFloat32Array8 +} from "@next2d/share"; + +/** + * @class + */ +export class RenderShape extends RenderGraphics +{ + /** + * @param {CanvasToWebGLContext} context + * @param {Float32Array} matrix + * @return {void} + * @method + * @private + */ + _$clip ( + context: CanvasToWebGLContext, + matrix: Float32Array + ): void { + + let multiMatrix: Float32Array = matrix; + const rawMatrix: Float32Array = this._$matrix; + if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 + || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 + || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 + ) { + multiMatrix = $multiplicationMatrix(matrix, rawMatrix); + } + + // size + const baseBounds: BoundsImpl = this._$getBounds(); + const bounds: BoundsImpl = $boundsMatrix(baseBounds, multiMatrix); + $poolBoundsObject(baseBounds); + + const width: number = $Math.ceil($Math.abs(bounds.xMax - bounds.xMin)); + const height: number = $Math.ceil($Math.abs(bounds.yMax - bounds.yMin)); + $poolBoundsObject(bounds); + + switch (true) { + + case width === 0: + case height === 0: + case width === 0 - $Infinity: + case height === 0 - $Infinity: + case width === $Infinity: + case height === $Infinity: + return; + + default: + break; + + } + + super._$clip(context, multiMatrix); + + if (multiMatrix !== matrix) { + $poolFloat32Array6(multiMatrix); + } + } + + /** + * @param {CanvasToWebGLContext} context + * @param {Float32Array} matrix + * @param {Float32Array} color_transform + * @return {void} + * @method + * @private + */ + _$draw ( + context: CanvasToWebGLContext, + matrix: Float32Array, + color_transform: Float32Array + ): void { + + if (!this._$visible || !this._$maxAlpha || !this._$canDraw) { + return ; + } + + let multiColor: Float32Array = color_transform; + const rawColor: Float32Array = this._$colorTransform; + if (rawColor[0] !== 1 || rawColor[1] !== 1 + || rawColor[2] !== 1 || rawColor[3] !== 1 + || rawColor[4] !== 0 || rawColor[5] !== 0 + || rawColor[6] !== 0 || rawColor[7] !== 0 + ) { + multiColor = $multiplicationColor(color_transform, rawColor); + } + + const alpha: number = $clamp(multiColor[3] + multiColor[7] / 255, 0, 1, 0); + if (!alpha) { + if (multiColor !== color_transform) { + $poolFloat32Array8(multiColor); + } + return ; + } + + let multiMatrix: Float32Array = matrix; + const rawMatrix: Float32Array = this._$matrix; + if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 + || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 + || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 + ) { + multiMatrix = $multiplicationMatrix(matrix, rawMatrix); + } + + super._$draw( + context, multiMatrix, multiColor, + this._$blendMode, this._$filters + ); + + if (multiMatrix !== matrix) { + $poolFloat32Array6(multiMatrix); + } + + if (multiColor !== color_transform) { + $poolFloat32Array8(multiColor); + } + } + + /** + * @description Playerから登録を削除 + * + * @return {void} + * @method + * @private + */ + _$remove (): void + { + this._$xMin = 0; + this._$yMin = 0; + this._$xMax = 0; + this._$yMax = 0; + this._$recodes = null; + + super._$remove(); + + $shapes.push(this); + } +} \ No newline at end of file diff --git a/packages/renderer/src/RendererTextField.ts b/packages/renderer/src/RendererTextField.ts new file mode 100644 index 00000000..1a16d4cc --- /dev/null +++ b/packages/renderer/src/RendererTextField.ts @@ -0,0 +1,1031 @@ +import { RenderDisplayObject } from "./RenderDisplayObject"; +import type{ TextDataImpl } from "../interface/TextDataImpl"; +import type{ PropertyTextMessageImpl } from "../interface/PropertyTextMessageImpl"; +import type{ TextFieldAutoSizeImpl } from "../interface/TextFieldAutoSizeImpl"; +import type{ TextFormatVerticalAlignImpl } from "../interface/TextFormatVerticalAlignImpl"; +import type{ BoundsImpl } from "../interface/BoundsImpl"; +import type{ AttachmentImpl } from "../interface/AttachmentImpl"; +import type{ RGBAImpl } from "../interface/RGBAImpl"; +import type{ TextFormatImpl } from "../interface/TextFormatImpl"; +import type { FilterArrayImpl } from "../interface/FilterArrayImpl"; +import type { CachePositionImpl } from "../interface/CachePositionImpl"; +import type { + CanvasToWebGLContext, + FrameBufferManager +} from "@next2d/webgl"; +import { + $isSafari, + $textFields +} from "../RenderGlobal"; +import { + $cacheStore, + $boundsMatrix, + $clamp, + $generateFontStyle, + $getArray, + $Infinity, + $intToRGBA, + $Math, + $multiplicationColor, + $multiplicationMatrix, + $Number, + $poolArray, + $poolBoundsObject, + $poolFloat32Array6, + $poolFloat32Array8, + $getBoundsObject +} from "@next2d/share"; + +/** + * @class + */ +export class RenderTextField extends RenderDisplayObject +{ + private _$background: boolean; + private _$backgroundColor: number; + private _$border: boolean; + private _$borderColor: number; + private readonly _$textData: TextDataImpl[]; + private _$textAreaActive: boolean; + private _$thickness: number; + private _$thicknessColor: number; + private _$limitWidth: number; + private _$limitHeight: number; + private _$autoSize: TextFieldAutoSizeImpl; + private readonly _$widthTable: number[]; + private readonly _$heightTable: number[]; + private readonly _$objectTable: TextDataImpl[]; + private readonly _$textHeightTable: number[]; + private _$scrollV: number; + private _$maxScrollV: number | null; + private _$textHeight: number; + private _$verticalAlign: TextFormatVerticalAlignImpl; + private _$wordWrap: boolean; + private _$cacheKeys: string[]; + private _$cacheParams: number[]; + + /** + * @constructor + * @public + */ + constructor () + { + super(); + + /** + * @type {boolean} + * @default false + * @private + */ + this._$background = false; + + /** + * @type {number} + * @default 0xffffff + * @private + */ + this._$backgroundColor = 0xffffff; + + /** + * @type {boolean} + * @default false + * @private + */ + this._$border = false; + + /** + * @type {number} + * @default 0x000000 + * @private + */ + this._$borderColor = 0x000000; + + /** + * @type {boolean} + * @default false + * @private + */ + this._$wordWrap = false; + + /** + * @type {array} + * @private + */ + this._$textData = $getArray(); + + /** + * @type {boolean} + * @default false + * @private + */ + this._$textAreaActive = false; + + /** + * @type {number} + * @default 0 + * @private + */ + this._$thickness = 0; + + /** + * @type {number} + * @default 0 + * @private + */ + this._$thicknessColor = 0; + + /** + * @type {number} + * @default 0 + * @private + */ + this._$limitWidth = 0; + + /** + * @type {number} + * @default 0 + * @private + */ + this._$limitHeight = 0; + + /** + * @type {string} + * @default TextFieldAutoSize.NONE + * @private + */ + this._$autoSize = "none"; + + /** + * @type {array} + * @default null + * @private + */ + this._$widthTable = $getArray(); + + /** + * @type {array} + * @default null + * @private + */ + this._$heightTable = $getArray(); + + /** + * @type {array} + * @default null + * @private + */ + this._$objectTable = $getArray(); + + /** + * @type {array} + * @default null + * @private + */ + this._$textHeightTable = $getArray(); + + /** + * @type {number} + * @default 0 + * @private + */ + this._$xMin = 0; + + /** + * @type {number} + * @default 0 + * @private + */ + this._$yMin = 0; + + /** + * @type {number} + * @default 0 + * @private + */ + this._$xMax = 0; + + /** + * @type {number} + * @default 0 + * @private + */ + this._$yMax = 0; + + /** + * @type {number} + * @default null + * @private + */ + this._$maxScrollV = null; + + /** + * @type {number} + * @default 1 + * @private + */ + this._$scrollV = 1; + + /** + * @type {number} + * @default 0 + * @private + */ + this._$textHeight = 0; + + /** + * @type {string} + * @default TextFormatVerticalAlign.TOP + * @private + */ + this._$verticalAlign = "top"; + + /** + * @type {array} + * @private + */ + this._$cacheKeys = $getArray(); + + /** + * @type {array} + * @private + */ + this._$cacheParams = $getArray(0, 0, 0); + } + + /** + * @description 表示オブジェクトの幅を示します(ピクセル単位)。 + * Indicates the width of the display object, in pixels. + * + * @member {number} + * @public + */ + get width (): number + { + const bounds: BoundsImpl = $boundsMatrix( + this._$getBounds(null), + this._$matrix + ); + + const width: number = $Math.abs(bounds.xMax - bounds.xMin); + $poolBoundsObject(bounds); + + switch (true) { + + case width === 0: + case width === $Infinity: + case width === 0 - $Infinity: + return 0; + + default: + return width; + + } + } + + /** + * @description 表示オブジェクトの高さを示します(ピクセル単位)。 + * Indicates the height of the display object, in pixels. + * + * @member {number} + * @public + */ + get height (): number + { + const bounds: BoundsImpl = $boundsMatrix( + this._$getBounds(null), + this._$matrix + ); + + const height: number = $Math.abs(bounds.yMax - bounds.yMin); + + // object pool + $poolBoundsObject(bounds); + + switch (height) { + + case 0: + case $Infinity: + case 0 - $Infinity: + return 0; + + default: + return height; + + } + } + + /** + * @description scrollV の最大値です。 + * The maximum value of scrollV. + * + * @member {number} + * @readonly + * @public + */ + get maxScrollV (): number + { + if (this._$maxScrollV === null) { + + this._$maxScrollV = 1; + + const length: number = this._$textHeightTable.length; + const maxHeight: number = this.height; + + if (maxHeight > this._$textHeight) { + return this._$maxScrollV; + } + + let textHeight: number = 0; + + let idx: number = 0; + while (length > idx) { + + textHeight += this._$textHeightTable[idx++]; + if (textHeight > maxHeight) { + break; + } + + this._$maxScrollV++; + } + } + return this._$maxScrollV; + } + + /** + * @param {CanvasToWebGLContext} context + * @param {Float32Array} matrix + * @return {void} + * @method + * @private + */ + _$clip ( + context: CanvasToWebGLContext, + matrix: Float32Array + ): void { + + // size + const bounds: BoundsImpl = this._$getBounds(); + const xMax: number = bounds.xMax; + const xMin: number = bounds.xMin; + const yMax: number = bounds.yMax; + const yMin: number = bounds.yMin; + $poolBoundsObject(bounds); + + const width: number = $Math.ceil($Math.abs(xMax - xMin)); + const height: number = $Math.ceil($Math.abs(yMax - yMin)); + if (!width || !height) { + return; + } + + let multiMatrix: Float32Array = matrix; + const rawMatrix: Float32Array = this._$matrix; + if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 + || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 + || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 + ) { + multiMatrix = $multiplicationMatrix(matrix, rawMatrix); + } + + context.reset(); + context.setTransform( + matrix[0], matrix[1], matrix[2], + matrix[3], matrix[4], matrix[5] + ); + context.beginPath(); + context.moveTo(0, 0); + context.lineTo(width, 0); + context.lineTo(width, height); + context.lineTo(0, height); + context.lineTo(0, 0); + context.clip(); + + if (multiMatrix !== matrix) { + $poolFloat32Array6(multiMatrix); + } + } + + /** + * @param {CanvasToWebGLContext} context + * @param {Float32Array} matrix + * @param {Float32Array} color_transform + * @return {void} + * @method + * @private + */ + _$draw ( + context: CanvasToWebGLContext, + matrix: Float32Array, + color_transform: Float32Array + ): void { + + if (!this._$visible || this._$textAreaActive) { + return ; + } + + if (!this._$background && !this._$border + && 2 > this._$textData.length + ) { + return; + } + + let multiColor: Float32Array = color_transform; + const rawColor: Float32Array = this._$colorTransform; + if (rawColor[0] !== 1 || rawColor[1] !== 1 + || rawColor[2] !== 1 || rawColor[3] !== 1 + || rawColor[4] !== 0 || rawColor[5] !== 0 + || rawColor[6] !== 0 || rawColor[7] !== 0 + ) { + multiColor = $multiplicationColor(color_transform, rawColor); + } + + const alpha: number = $clamp(multiColor[3] + multiColor[7] / 255, 0 ,1); + if (!alpha) { + return ; + } + + let multiMatrix: Float32Array = matrix; + const rawMatrix: Float32Array = this._$matrix; + if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 + || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 + || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 + ) { + multiMatrix = $multiplicationMatrix(matrix, rawMatrix); + } + + const baseBounds: BoundsImpl = this._$getBounds(null); + baseBounds.xMin -= this._$thickness; + baseBounds.xMax += this._$thickness; + baseBounds.yMin -= this._$thickness; + baseBounds.yMax += this._$thickness; + + const bounds: BoundsImpl = $boundsMatrix(baseBounds, multiMatrix); + const xMax = +bounds.xMax; + const xMin = +bounds.xMin; + const yMax = +bounds.yMax; + const yMin = +bounds.yMin; + $poolBoundsObject(bounds); + + const width: number = $Math.ceil($Math.abs(xMax - xMin)); + const height: number = $Math.ceil($Math.abs(yMax - yMin)); + switch (true) { + + case width === 0: + case height === 0: + case width === -$Infinity: + case height === -$Infinity: + case width === $Infinity: + case height === $Infinity: + return; + + default: + break; + + } + + let xScale: number = +$Math.sqrt( + multiMatrix[0] * multiMatrix[0] + + multiMatrix[1] * multiMatrix[1] + ); + if (!$Number.isInteger(xScale)) { + const value: string = xScale.toString(); + const index: number = value.indexOf("e"); + if (index !== -1) { + xScale = +value.slice(0, index); + } + xScale = +xScale.toFixed(4); + } + + let yScale: number = +$Math.sqrt( + multiMatrix[2] * multiMatrix[2] + + multiMatrix[3] * multiMatrix[3] + ); + if (!$Number.isInteger(yScale)) { + const value: string = yScale.toString(); + const index: number = value.indexOf("e"); + if (index !== -1) { + yScale = +value.slice(0, index); + } + yScale = +yScale.toFixed(4); + } + + const filters: FilterArrayImpl | null = this._$filters; + const canApply: boolean = filters !== null + && filters.length > 0 + && this._$canApply(filters); + + let filterBounds: BoundsImpl = $getBoundsObject(0, width, 0, height); + if (canApply && filters) { + for (let idx: number = 0; idx < filters.length ; ++idx) { + filterBounds = filters[idx] + ._$generateFilterRect(filterBounds, xScale, yScale); + } + } + + // cache current buffer + const manager: FrameBufferManager = context.frameBuffer; + const currentAttachment: AttachmentImpl | null = manager.currentAttachment; + if (!currentAttachment + || xMin - filterBounds.xMin > currentAttachment.width + || yMin - filterBounds.yMin > currentAttachment.height + ) { + $poolBoundsObject(filterBounds); + return; + } + + if (0 > xMin + filterBounds.xMax || 0 > yMin + filterBounds.yMax) { + $poolBoundsObject(filterBounds); + return; + } + + $poolBoundsObject(filterBounds); + + // texture is small or renew + if (this._$isUpdated()) { + $cacheStore.removeCache(this._$instanceId); + context.cachePosition = null; + this._$cacheKeys.length = 0; + } + + if (!this._$cacheKeys.length + || this._$cacheParams[0] !== xScale + || this._$cacheParams[1] !== yScale + || this._$cacheParams[2] !== color_transform[7] + ) { + const keys: number[] = $getArray(xScale, yScale); + this._$cacheKeys = $cacheStore.generateKeys( + this._$instanceId, keys + ); + $poolArray(keys); + + this._$cacheParams[0] = xScale; + this._$cacheParams[1] = yScale; + this._$cacheParams[2] = color_transform[7]; + } + + context.cachePosition = $cacheStore.get(this._$cacheKeys); + if (!context.cachePosition) { + + // resize + const lineWidth: number = $Math.min(1, $Math.max(xScale, yScale)); + const baseWidth: number = $Math.ceil($Math.abs(baseBounds.xMax - baseBounds.xMin) * xScale); + const baseHeight: number = $Math.ceil($Math.abs(baseBounds.yMax - baseBounds.yMin) * yScale); + + // alpha reset + multiColor[3] = 1; + + // new canvas + const canvas: OffscreenCanvas = new OffscreenCanvas( + baseWidth + lineWidth * 2, + baseHeight + lineWidth * 2 + ); + const ctx: OffscreenCanvasRenderingContext2D | null = canvas.getContext("2d"); + if (!ctx) { + return ; + } + + // border and background + if (this._$background || this._$border) { + + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.lineTo(baseWidth, 0); + ctx.lineTo(baseWidth, baseHeight); + ctx.lineTo(0, baseHeight); + ctx.lineTo(0, 0); + + if (this._$background) { + + const color: RGBAImpl = $intToRGBA(this._$backgroundColor); + const alpha: number = $Math.max(0, $Math.min( + color.A * 255 * color_transform[3] + color_transform[7], 255) + ) / 255; + + ctx.fillStyle = `rgba(${color.R},${color.G},${color.B},${alpha})`; + ctx.fill(); + } + + if (this._$border) { + + const color: RGBAImpl = $intToRGBA(this._$borderColor); + const alpha: number = $Math.max(0, $Math.min( + color.A * 255 * color_transform[3] + color_transform[7], 255) + ) / 255; + + ctx.lineWidth = lineWidth; + ctx.strokeStyle = `rgba(${color.R},${color.G},${color.B},${alpha})`; + ctx.stroke(); + } + + } + + // mask start + ctx.save(); + ctx.beginPath(); + ctx.moveTo(2, 2); + ctx.lineTo(baseWidth - 2, 2); + ctx.lineTo(baseWidth - 2, baseHeight - 2); + ctx.lineTo(2, baseHeight - 2); + ctx.lineTo(2, 2); + ctx.clip(); + + ctx.beginPath(); + ctx.setTransform(xScale, 0, 0, yScale, 0, 0); + this._$doDraw(ctx, matrix, color_transform, baseWidth / xScale); + ctx.restore(); + + const position: CachePositionImpl = manager + .createCachePosition(width, height); + + const texture: WebGLTexture = manager + .createTextureFromCanvas(ctx.canvas); + + context.drawTextureFromRect(texture, position); + + // set cache + context.cachePosition = position; + $cacheStore.set(this._$cacheKeys, position); + } + + let drawFilter: boolean = false; + let offsetX: number = 0; + let offsetY: number = 0; + if (filters && filters.length + && this._$canApply(filters) + ) { + + drawFilter = true; + + const position: CachePositionImpl = this._$drawFilter( + context, multiMatrix, filters, + width, height + ); + + if (position.offsetX) { + offsetX = position.offsetX; + } + + if (position.offsetY) { + offsetY = position.offsetY; + } + + // update + context.cachePosition = position; + } + + const radianX: number = $Math.atan2(multiMatrix[1], multiMatrix[0]); + const radianY: number = $Math.atan2(-multiMatrix[2], multiMatrix[3]); + if (!drawFilter && (radianX || radianY)) { + + const tx: number = baseBounds.xMin * xScale; + const ty: number = baseBounds.yMin * yScale; + + const cosX: number = $Math.cos(radianX); + const sinX: number = $Math.sin(radianX); + const cosY: number = $Math.cos(radianY); + const sinY: number = $Math.sin(radianY); + + context.setTransform( + cosX, sinX, -sinY, cosY, + tx * cosX - ty * sinY + multiMatrix[4], + tx * sinX + ty * cosY + multiMatrix[5] + ); + + } else { + + context.setTransform(1, 0, 0, 1, + xMin - offsetX, yMin - offsetY + ); + + } + + // draw + if (context.cachePosition) { + + context.globalAlpha = alpha; + context.imageSmoothingEnabled = true; + context.globalCompositeOperation = this._$blendMode; + + context.drawInstance( + xMin - offsetX, yMin - offsetY, xMax, yMax, + color_transform + ); + + // cache position clear + context.cachePosition = null; + } + + // get cache + $poolBoundsObject(baseBounds); + + // pool + if (multiMatrix !== matrix) { + $poolFloat32Array6(multiMatrix); + } + + if (multiColor !== color_transform) { + $poolFloat32Array8(multiColor); + } + } + + /** + * @param {CanvasRenderingContext2D} context + * @param {Float32Array} matrix + * @param {Float32Array} color_transform + * @param {number} width + * @return {void} + * @method + * @private + */ + _$doDraw ( + context: OffscreenCanvasRenderingContext2D, + matrix: Float32Array, + color_transform: Float32Array, + width: number + ): void { + + const limitWidth: number = this.width; + const limitHeight: number = this.height; + + // setup + let xOffset: number = 0; + let offsetHeight: number = 0; + let currentV: number = 0; + + let yOffset: number = 0; + if (this._$verticalAlign !== "top" + && this.height > this._$textHeight + ) { + + switch (this._$verticalAlign) { + + case "middle": + yOffset = (this.height - this._$textHeight + 2) / 2; + break; + + case "bottom": + yOffset = this.height - this._$textHeight + 2; + break; + + } + + } + + const length: number = this._$textData.length; + for (let idx: number = 0; idx < length; ++idx) { + + const obj: TextDataImpl = this._$textData[idx]; + if (obj.width === 0) { + continue; + } + + // check + const offsetWidth: number = xOffset + obj.x; + if (this._$autoSize === "none" + && (offsetHeight > limitHeight || offsetWidth > limitWidth) + ) { + continue; + } + + const tf: TextFormatImpl = obj.textFormat; + + // color + const color: RGBAImpl = $intToRGBA(obj.textFormat._$color); + const alpha: number = $Math.max(0, $Math.min( + color.A * 255 * color_transform[3] + color_transform[7], 255) + ) / 255; + + context.fillStyle = `rgba(${color.R},${color.G},${color.B},${alpha})`; + + if (this._$thickness) { + const color: RGBAImpl = $intToRGBA(this._$thicknessColor); + const alpha: number = $Math.max(0, $Math.min( + color.A * 255 * color_transform[3] + color_transform[7], 255) + ) / 255; + context.lineWidth = this._$thickness; + context.strokeStyle = `rgba(${color.R},${color.G},${color.B},${alpha})`; + } + + const yIndex: number = obj.yIndex; + switch (obj.mode) { + + case "break": + case "wrap": + + currentV++; + + if (this._$scrollV > currentV) { + continue; + } + + offsetHeight += this._$textHeightTable[yIndex]; + + xOffset = this._$getAlignOffset(this._$objectTable[yIndex], width); + if (tf._$underline) { + + const offset: number = obj.textFormat._$size / 12; + + const color: RGBAImpl = $intToRGBA(tf._$color); + const alpha: number = $Math.max(0, $Math.min( + color.A * 255 * color_transform[3] + color_transform[7], 255) + ) / 255; + + context.lineWidth = $Math.max(1, 1 / $Math.min(matrix[0], matrix[3])); + context.strokeStyle = `rgba(${color.R},${color.G},${color.B},${alpha})`; + + context.beginPath(); + context.moveTo(xOffset, yOffset + offsetHeight - offset); + context.lineTo(xOffset + this._$widthTable[yIndex], yOffset + offsetHeight - offset); + context.stroke(); + + } + + break; + + case "text": + { + if (this._$scrollV > currentV) { + continue; + } + + let offsetY = offsetHeight - this._$heightTable[0]; + if (!$isSafari) { + offsetY += 2 * (obj.textFormat._$size / 12); + } + + context.beginPath(); + context.textBaseline = "top"; + context.font = $generateFontStyle( + tf._$font, tf._$size, tf._$italic, tf._$bold + ); + + if (this._$thickness) { + context.strokeText(obj.text, offsetWidth, yOffset + offsetY); + } + + context.fillText(obj.text, offsetWidth, yOffset + offsetY); + + } + break; + + case "image": + + if (!obj.loaded) { + continue; + } + + context.beginPath(); + context.drawImage(obj.image, + obj.hspace, yOffset + obj.y, + obj.width, obj.height + ); + + break; + + } + } + } + + /** + * @param {object} obj + * @param {number} width + * @return {number} + * @private + */ + _$getAlignOffset ( + obj: TextDataImpl, + width: number + ): number { + + // default + const totalWidth: number = this._$widthTable[obj.yIndex]; + const textFormat: TextFormatImpl = obj.textFormat; + const indent: number = textFormat._$blockIndent + textFormat._$leftMargin > 0 + ? textFormat._$blockIndent + textFormat._$leftMargin + : 0; + + switch (true) { + + // wordWrap case + case !this._$wordWrap && totalWidth > width: + return $Math.max(0, indent); + + case textFormat._$align === "center": // format CENTER + case this._$autoSize === "center": // autoSize CENTER + return $Math.max(0, width / 2 - indent - textFormat._$rightMargin - totalWidth / 2); + + case textFormat._$align === "right": // format RIGHT + case this._$autoSize === "right": // autoSize RIGHT + return $Math.max(0, width - indent - totalWidth - textFormat._$rightMargin - 2); + + // autoSize LEFT + // format LEFT + default: + return $Math.max(0, indent + 2); + + } + } + + /** + * @description Playerから登録を削除 + * + * @return {void} + * @method + * @private + */ + _$remove (): void + { + this._$xMin = 0; + this._$yMin = 0; + this._$xMax = 0; + this._$yMax = 0; + + // array reset + this._$textData.length = 0; + this._$widthTable.length = 0; + this._$heightTable.length = 0; + this._$objectTable.length = 0; + this._$textHeightTable.length = 0; + + this._$textAreaActive = false; + + super._$remove(); + + $textFields.push(this); + } + + /** + * @description 情報を更新 + * + * @param {object} object + * @return {void} + * @method + * @private + */ + _$updateProperty (object: PropertyTextMessageImpl): void + { + // update property + this._$textAreaActive = !!object.textAreaActive; + + // set array + this._$textData.length = 0; + this._$widthTable.length = 0; + this._$heightTable.length = 0; + this._$objectTable.length = 0; + this._$textHeightTable.length = 0; + + this._$textData.push(...object.textData); + this._$widthTable.push(...object.widthTable); + this._$heightTable.push(...object.heightTable); + this._$objectTable.push(...object.objectTable); + this._$textHeightTable.push(...object.textHeightTable); + + // format + this._$wordWrap = object.wordWrap; + this._$limitWidth = object.limitWidth; + this._$limitHeight = object.limitHeight; + this._$autoSize = object.autoSize; + this._$scrollV = object.scrollV; + this._$textHeight = object.textHeight; + this._$verticalAlign = object.verticalAlign; + + // color + this._$border = object.border; + if (this._$border) { + this._$borderColor = object.borderColor as NonNullable; + } + + this._$background = object.background; + if (this._$background) { + this._$backgroundColor = object.backgroundColor as NonNullable; + } + + if ("thickness" in object) { + this._$thickness = object.thickness; + this._$thicknessColor = object.thicknessColor as NonNullable; + } + } + + /** + * @description 描画情報を更新 + * + * @param {object} object + * @return {void} + * @method + * @private + */ + _$update (object: PropertyTextMessageImpl): void + { + super._$update(object); + + this._$textAreaActive = !!object.textAreaActive; + + this._$xMin = object.xMin as NonNullable; + this._$yMin = object.yMin as NonNullable; + this._$xMax = object.xMax as NonNullable; + this._$yMax = object.yMax as NonNullable; + + if (object.textData) { + this._$updateProperty(object); + } + } +} \ No newline at end of file diff --git a/packages/renderer/src/RendererUtil.ts b/packages/renderer/src/RendererUtil.ts new file mode 100644 index 00000000..d6151aba --- /dev/null +++ b/packages/renderer/src/RendererUtil.ts @@ -0,0 +1,140 @@ +import type { CanvasToWebGLContext } from "@next2d/webgl"; +import { RendererDisplayObjectContainer } from "./RendererDisplayObjectContainer"; + +/** + * @type {RendererDisplayObjectContainer} + * @public + */ +export const $rendererStage: RendererDisplayObjectContainer = new RendererDisplayObjectContainer(); + +/** + * @type {number} + * @public + */ +export const $samples: number = 4; + +/** + * @type {number} + * @public + */ +export let $devicePixelRatio: number = 1; + +/** + * @description 画面の解像度を設定 + * Set screen resolution + * + * @param {number} ratio + * @return {void} + * @method + * @public + */ +export const $setDevicePixelRatio = (ratio: number): void => +{ + $devicePixelRatio = ratio; +}; + +/** + * @type {CanvasToWebGLContext} + * @public + */ +export let $context: CanvasToWebGLContext; + +/** + * @description Next2DのWebGLの描画コンテキストを設定 + * Set the drawing context of Next2D's WebGL + * + * @param {number} context + * @return {void} + * @method + * @public + */ +export const $setContext = (context: CanvasToWebGLContext): void => +{ + $context = context; +}; + +/** + * @type {CanvasToWebGLContext} + * @public + */ +export let $canvas: OffscreenCanvas; + +/** + * @description OffscreenCanvasをutilの変数のセット + * Set OffscreenCanvas to util variable + * + * @param {OffscreenCanvas} canvas + * @return {void} + * @method + * @public + */ +export const $setCanvas = (canvas: OffscreenCanvas): void => +{ + $canvas = canvas; +}; + +/** + * @type {WebGL2RenderingContext} + * @public + */ +export let $gl: WebGL2RenderingContext; + +/** + * @description WebGL2のコンテキストをセット + * Set WebGL2 context + * + * @param {WebGL2RenderingContext} gl + * @return {void} + * @method + * @public + */ +export const $setWebGL2RenderingContext = (gl: WebGL2RenderingContext): void => +{ + $gl = gl; +}; + +/** + * @type {number} + * @public + */ +export let $rendererWidth: number = 0; + +/** + * @description 描画エリアの幅を設定 + * Set the width of the drawing area + * + * @param {number} width + * @return {void} + * @method + * @public + */ +export const $setRendererWidth = (width: number): void => +{ + $rendererWidth = width; +}; + +/** + * @type {number} + * @public + */ +export let $rendererHeight: number = 0; + +/** + * @description 描画エリアの高さを設定 + * Set the height of the drawing area + * + * @param {number} height + * @return {void} + * @method + * @public + */ +export const $setRendererHeight = (height: number): void => +{ + $rendererHeight = height; +}; + +/** + * @type {Float32Array} + * @public + */ +export const $rendererMatrix: Float32Array = new Float32Array([1, 0, 0, 1, 0, 0]); \ No newline at end of file diff --git a/packages/renderer/src/RendererVideo.ts b/packages/renderer/src/RendererVideo.ts new file mode 100644 index 00000000..0a0c50fc --- /dev/null +++ b/packages/renderer/src/RendererVideo.ts @@ -0,0 +1,452 @@ +import { RenderDisplayObject } from "../display/RenderDisplayObject"; +import { $videos } from "../RenderGlobal"; +import type { BoundsImpl } from "../interface/BoundsImpl"; +import type { AttachmentImpl } from "../interface/AttachmentImpl"; +import type { PropertyVideoMessageImpl } from "../interface/PropertyVideoMessageImpl"; +import type { FilterArrayImpl } from "../interface/FilterArrayImpl"; +import type { CachePositionImpl } from "../interface/CachePositionImpl"; +import type { + CanvasToWebGLContext, + FrameBufferManager +} from "@next2d/webgl"; + +/** + * @class + */ +export class RenderVideo extends RenderDisplayObject +{ + private _$imageBitmap: ImageBitmap | null; + private _$context: OffscreenCanvasRenderingContext2D | null; + private _$smoothing: boolean; + private _$cacheKeys: string[]; + private _$cacheParams: number[]; + + /** + * @constructor + * @public + */ + constructor () + { + super(); + + /** + * @type {ImageBitmap} + * @default null + * @private + */ + this._$imageBitmap = null; + + /** + * @type {OffscreenCanvasRenderingContext2D} + * @default null + * @private + */ + this._$context = null; + + /** + * @type {boolean} + * @default true + * @private + */ + this._$smoothing = true; + + /** + * @type {array} + * @private + */ + this._$cacheKeys = $getArray(); + + /** + * @type {array} + * @private + */ + this._$cacheParams = $getArray(0, 0, 0); + } + + /** + * @param {CanvasToWebGLContext} context + * @param {Float32Array} matrix + * @return {void} + * @method + * @private + */ + _$clip ( + context: CanvasToWebGLContext, + matrix: Float32Array + ): void { + + const width: number = this._$xMax; + const height: number = this._$yMax; + if (!width || !height) { + return; + } + + let multiMatrix: Float32Array = matrix; + const rawMatrix: Float32Array = this._$matrix; + if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 + || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 + || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 + ) { + multiMatrix = $multiplicationMatrix(matrix, rawMatrix); + } + + context.reset(); + context.setTransform( + multiMatrix[0], multiMatrix[1], multiMatrix[2], + multiMatrix[3], multiMatrix[4], multiMatrix[5] + ); + + context.beginPath(); + context.moveTo(0, 0); + context.lineTo(width, 0); + context.lineTo(width, height); + context.lineTo(0, height); + context.lineTo(0, 0); + context.clip(); + + if (multiMatrix !== matrix) { + $poolFloat32Array6(multiMatrix); + } + } + + /** + * @param {CanvasToWebGLContext} context + * @param {Float32Array} matrix + * @param {Float32Array} color_transform + * @return {void} + * @method + * @private + */ + _$draw ( + context: CanvasToWebGLContext, + matrix: Float32Array, + color_transform: Float32Array + ): void { + + if (!this._$visible + || !this._$imageBitmap + || !this._$context + ) { + return ; + } + + let multiColor: Float32Array = color_transform; + const rawColor: Float32Array = this._$colorTransform; + if (rawColor[0] !== 1 || rawColor[1] !== 1 + || rawColor[2] !== 1 || rawColor[3] !== 1 + || rawColor[4] !== 0 || rawColor[5] !== 0 + || rawColor[6] !== 0 || rawColor[7] !== 0 + ) { + multiColor = $multiplicationColor(color_transform, rawColor); + } + + const alpha: number = $clamp(multiColor[3] + multiColor[7] / 255, 0, 1, 0); + if (!alpha) { + if (multiColor !== color_transform) { + $poolFloat32Array8(multiColor); + } + return ; + } + + let multiMatrix: Float32Array = matrix; + const rawMatrix: Float32Array = this._$matrix; + if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0 + || rawMatrix[2] !== 0 || rawMatrix[3] !== 1 + || rawMatrix[4] !== 0 || rawMatrix[5] !== 0 + ) { + multiMatrix = $multiplicationMatrix(matrix, rawMatrix); + } + + // default bounds + const baseBounds: BoundsImpl = this._$getBounds(); + $poolBoundsObject(baseBounds); + + const bounds: BoundsImpl = $boundsMatrix(baseBounds, multiMatrix); + const xMax: number = +bounds.xMax; + const xMin: number = +bounds.xMin; + const yMax: number = +bounds.yMax; + const yMin: number = +bounds.yMin; + $poolBoundsObject(bounds); + + const width: number = $Math.ceil($Math.abs(xMax - xMin)); + const height: number = $Math.ceil($Math.abs(yMax - yMin)); + switch (true) { + + case width === 0: + case height === 0: + case width === 0 - $Infinity: + case height === 0 - $Infinity: + case width === $Infinity: + case height === $Infinity: + return; + + default: + break; + + } + + let xScale: number = +$Math.sqrt( + multiMatrix[0] * multiMatrix[0] + + multiMatrix[1] * multiMatrix[1] + ); + if (!$Number.isInteger(xScale)) { + const value: string = xScale.toString(); + const index: number = value.indexOf("e"); + if (index !== -1) { + xScale = +value.slice(0, index); + } + xScale = +xScale.toFixed(4); + } + + let yScale: number = +$Math.sqrt( + multiMatrix[2] * multiMatrix[2] + + multiMatrix[3] * multiMatrix[3] + ); + if (!$Number.isInteger(yScale)) { + const value: string = yScale.toString(); + const index: number = value.indexOf("e"); + if (index !== -1) { + yScale = +value.slice(0, index); + } + yScale = +yScale.toFixed(4); + } + + const filters: FilterArrayImpl | null = this._$filters; + const canApply: boolean = filters !== null + && filters.length > 0 + && this._$canApply(filters); + + let filterBounds: BoundsImpl = $getBoundsObject(0, width, 0, height); + if (canApply && filters) { + for (let idx: number = 0; idx < filters.length ; ++idx) { + filterBounds = filters[idx] + ._$generateFilterRect(filterBounds, xScale, yScale); + } + } + + // cache current buffer + const manager: FrameBufferManager = context.frameBuffer; + const currentAttachment: AttachmentImpl | null = manager.currentAttachment; + if (!currentAttachment + || xMin - filterBounds.xMin > currentAttachment.width + || yMin - filterBounds.yMin > currentAttachment.height + ) { + $poolBoundsObject(filterBounds); + return; + } + + if (0 > xMin + filterBounds.xMax || 0 > yMin + filterBounds.yMax) { + $poolBoundsObject(filterBounds); + return; + } + $poolBoundsObject(filterBounds); + + if (!this._$cacheKeys.length + || this._$cacheParams[0] !== xScale + || this._$cacheParams[1] !== yScale + || this._$cacheParams[2] !== color_transform[7] + ) { + const keys: number[] = $getArray(); + keys[0] = xScale; + keys[1] = yScale; + + this._$cacheKeys = $cacheStore.generateKeys( + this._$instanceId, keys, color_transform + ); + + $poolArray(keys); + + this._$cacheParams[0] = xScale; + this._$cacheParams[1] = yScale; + this._$cacheParams[2] = color_transform[7]; + } + + context.cachePosition = $cacheStore.get(this._$cacheKeys); + if (!context.cachePosition) { + + const width: number = $Math.ceil($Math.abs(this._$xMax - this._$xMin)); + const height: number = $Math.ceil($Math.abs(this._$yMax - this._$yMin)); + + const position: CachePositionImpl = manager + .createCachePosition(width, height); + + context.cachePosition = position; + $cacheStore.set(this._$cacheKeys, position); + } + + this._$context.drawImage(this._$imageBitmap, 0, 0); + + const texture: WebGLTexture = manager + .textureManager + ._$createFromElement( + this._$imageBitmap.width, + this._$imageBitmap.height, + this._$context.canvas, + this._$smoothing + ); + + let offsetX: number = 0; + let offsetY: number = 0; + if (canApply && filters) { + + const currentAttachment: AttachmentImpl | null = manager.currentAttachment; + + const attachment: AttachmentImpl = manager + .createCacheAttachment(width, height); + + context._$bind(attachment); + + context.reset(); + + const parentMatrix: Float32Array = $getFloat32Array6( + xScale, 0, 0, yScale, + width / 2, height / 2 + ); + + const baseMatrix: Float32Array = $getFloat32Array6( + 1, 0, 0, 1, + -texture.width / 2, + -texture.height / 2 + ); + + const scaleMatrix = $multiplicationMatrix( + parentMatrix, baseMatrix + ); + $poolFloat32Array6(parentMatrix); + $poolFloat32Array6(baseMatrix); + + context.setTransform( + scaleMatrix[0], scaleMatrix[1], + scaleMatrix[2], scaleMatrix[3], + scaleMatrix[4], scaleMatrix[5] + ); + + context.drawImage(texture, 0, 0, texture.width, texture.height); + + const videoTexture: WebGLTexture = manager.getTextureFromCurrentAttachment(); + context._$bind(currentAttachment); + + manager.releaseAttachment(attachment); + + // release + context.drawTextureFromRect(texture, context.cachePosition); + + const position: CachePositionImpl = this._$drawFilter( + context, multiMatrix, filters, + width, height, videoTexture + ); + + if (position.offsetX) { + offsetX = position.offsetX; + } + + if (position.offsetY) { + offsetY = position.offsetY; + } + + // update + context.cachePosition = position; + + context.setTransform(1, 0, 0, 1, + xMin - offsetX, yMin - offsetY + ); + + } else { + + context.drawTextureFromRect(texture, context.cachePosition); + + context.setTransform( + multiMatrix[0], multiMatrix[1], multiMatrix[2], + multiMatrix[3], multiMatrix[4], multiMatrix[5] + ); + + } + + // draw + if (context.cachePosition) { + + context.globalAlpha = alpha; + context.imageSmoothingEnabled = true; + context.globalCompositeOperation = this._$blendMode; + + context.drawInstance( + xMin - offsetX, yMin - offsetY, xMax, yMax, + color_transform + ); + + // cache position clear + context.cachePosition = null; + } + + // pool + if (multiMatrix !== matrix) { + $poolFloat32Array6(multiMatrix); + } + + if (multiColor !== color_transform) { + $poolFloat32Array8(multiColor); + } + } + + /** + * @description Playerから登録を削除 + * + * @return {void} + * @method + * @private + */ + _$remove () + { + this._$xMin = 0; + this._$yMin = 0; + this._$xMax = 0; + this._$yMax = 0; + this._$context = null; + this._$imageBitmap = null; + this._$smoothing = true; + + super._$remove(); + + $videos.push(this); + } + + /** + * @description 情報を更新 + * + * @param {object} object + * @return {void} + * @method + * @private + */ + _$updateProperty (object: PropertyVideoMessageImpl) + { + this._$xMin = object.xMin as NonNullable; + this._$yMin = object.yMin as NonNullable; + this._$xMax = object.xMax as NonNullable; + this._$yMax = object.yMax as NonNullable; + this._$imageBitmap = object.imageBitmap as NonNullable; + this._$smoothing = object.smoothing as NonNullable; + + if (!this._$context && this._$imageBitmap) { + const canvas: OffscreenCanvas = new $OffscreenCanvas( + this._$imageBitmap.width, + this._$imageBitmap.height + ); + this._$context = canvas.getContext("2d"); + } + } + + /** + * @description 描画情報を更新 + * + * @param {object} object + * @return {void} + * @method + * @private + */ + _$update (object: PropertyVideoMessageImpl): void + { + super._$update(object); + this._$updateProperty(object); + } +} \ No newline at end of file diff --git a/packages/renderer/src/index.ts b/packages/renderer/src/index.ts index 98826cab..cb5a2a0e 100644 --- a/packages/renderer/src/index.ts +++ b/packages/renderer/src/index.ts @@ -1,8 +1,8 @@ "use strict"; -// import { CommandController } from "./CommandController"; +import { CommandController } from "./CommandController"; -// const command: CommandController = new CommandController(); +const command: CommandController = new CommandController(); /** * @description OffscreenCanvasのメッセージイベント @@ -16,10 +16,10 @@ self.addEventListener("message", async (event: MessageEvent): Promise => { console.log(event.data); - // command.queue.push(event.data); - // if (command.state === "deactivate") { - // await command.execute(); - // } + command.queue.push(event.data); + if (command.state === "deactivate") { + await command.execute(); + } }); export default {}; \ No newline at end of file diff --git a/packages/renderer/src/interface/BlendModeImpl.ts b/packages/renderer/src/interface/BlendModeImpl.ts new file mode 100644 index 00000000..6ed290eb --- /dev/null +++ b/packages/renderer/src/interface/BlendModeImpl.ts @@ -0,0 +1,15 @@ +export type BlendModeImpl = "copy" + | "add" + | "alpha" + | "darken" + | "difference" + | "erase" + | "hardlight" + | "invert" + | "layer" + | "lighten" + | "multiply" + | "normal" + | "overlay" + | "screen" + | "subtract"; \ No newline at end of file diff --git a/packages/renderer/src/interface/GridImpl.ts b/packages/renderer/src/interface/GridImpl.ts new file mode 100644 index 00000000..eecb9aba --- /dev/null +++ b/packages/renderer/src/interface/GridImpl.ts @@ -0,0 +1,6 @@ +export interface GridImpl { + x: number; + y: number; + w: number; + h: number; +} \ No newline at end of file diff --git a/packages/renderer/src/interface/PropertyMessageImpl.ts b/packages/renderer/src/interface/PropertyMessageImpl.ts new file mode 100644 index 00000000..4e9896bb --- /dev/null +++ b/packages/renderer/src/interface/PropertyMessageImpl.ts @@ -0,0 +1,39 @@ +import type { BlendModeImpl } from "./BlendModeImpl"; +import type { GridImpl } from "./GridImpl"; + +export interface PropertyMessageImpl { + command: string; + buffer: Float32Array; + instanceId?: number; + parentId?: number; + visible?: boolean; + isMask?: boolean; + clipDepth?: number; + depth?: number; + maskId?: number; + loaderInfoId?: number; + characterId?: number; + maskMatrix?: Float32Array; + xMin?: number; + yMin?: number; + xMax?: number; + yMax?: number; + a?: number; + b?: number; + c?: number; + d?: number; + tx?: number; + ty?: number; + f0?: number; + f1?: number; + f2?: number; + f3?: number; + f4?: number; + f5?: number; + f6?: number; + f7?: number; + filters?: any[]; + blendMode?: BlendModeImpl; + matrixBase?: Float32Array; + grid?: GridImpl; +} \ No newline at end of file diff --git a/packages/renderer/src/interface/PropertyMessageMapImpl.ts b/packages/renderer/src/interface/PropertyMessageMapImpl.ts new file mode 100644 index 00000000..b286a99d --- /dev/null +++ b/packages/renderer/src/interface/PropertyMessageMapImpl.ts @@ -0,0 +1,3 @@ +import type { PropertyMessageImpl } from "./PropertyMessageImpl"; + +export type PropertyMessageMapImpl = T; \ No newline at end of file diff --git a/packages/display/src/TextField.ts b/packages/text/src/TextField.ts similarity index 100% rename from packages/display/src/TextField.ts rename to packages/text/src/TextField.ts diff --git a/packages/webgl/src/CanvasToWebGLContext.ts b/packages/webgl/src/CanvasToWebGLContext.ts index 8c69b8c9..bcd1d083 100644 --- a/packages/webgl/src/CanvasToWebGLContext.ts +++ b/packages/webgl/src/CanvasToWebGLContext.ts @@ -29,12 +29,14 @@ import type { JointStyleImpl } from "./interface/JointStyleImpl"; import type { CachePositionImpl } from "./interface/CachePositionImpl"; import { $setRenderSize, + $setWebGL2RenderingContext, $getFloat32Array9, $getArray, $clamp, $poolArray, $inverseMatrix, - $poolFloat32Array9 + $poolFloat32Array9, + $gl } from "./WebGLUtil"; /** @@ -44,7 +46,6 @@ export class CanvasToWebGLContext { public _$offsetX: number; public _$offsetY: number; - public readonly _$gl: WebGL2RenderingContext; private _$cacheBounds: BoundsImpl; private _$matrix: Float32Array; private _$cacheAttachment: AttachmentImpl|null; @@ -74,6 +75,7 @@ export class CanvasToWebGLContext private readonly _$blend: CanvasToWebGLContextBlend; private readonly _$maskBounds: BoundsImpl; private readonly _$attachmentArray: Array; + private _$mainAttachment: AttachmentImpl | null; /** * @param {WebGL2RenderingContext} gl @@ -83,14 +85,9 @@ export class CanvasToWebGLContext */ constructor (gl: WebGL2RenderingContext, sample: number) { + $setWebGL2RenderingContext(gl); $setRenderSize(gl.getParameter(gl.MAX_TEXTURE_SIZE)); - /** - * @type {WebGL2RenderingContext} - * @private - */ - this._$gl = gl; - /** * @type {number} * @private @@ -311,6 +308,58 @@ export class CanvasToWebGLContext * @private */ this._$cachePosition = null; + + /** + * @type {object} + * @default null + * @private + */ + this._$mainAttachment = null; + } + + /** + * @description 描画のメインとなるAttachmentを設定 + * Set the main Attachment for drawing + * + * @member {AttachmentImpl | null} + * @public + */ + get mainAttachment (): AttachmentImpl | null + { + return this._$mainAttachment; + } + set mainAttachment (attachment: AttachmentImpl | null) + { + this._$mainAttachment = attachment; + } + + /** + * @description 描画サイズのリサイズ処理 + * Resize processing of drawing size + * + * @param {number} width + * @param {number} height + * @return {void} + * @method + * @public + */ + resize (width: number, height: number): void + { + this.clearInstacedArray(); + + const manager: FrameBufferManager = this.frameBuffer; + if (this._$mainAttachment) { + manager.unbind(); + manager.releaseAttachment(this._$mainAttachment, true); + } + + this._$mainAttachment = manager + .createCacheAttachment(width, height, true); + + this.bind(this._$mainAttachment); + + // update cache max size + this.setMaxSize(width, height); } /** @@ -358,7 +407,7 @@ export class CanvasToWebGLContext */ get canvas (): HTMLCanvasElement | OffscreenCanvas { - return this._$gl.canvas; + return $gl.canvas; } /** @@ -626,16 +675,16 @@ export class CanvasToWebGLContext .bindRenderBuffer(); // 初期化 - this._$gl.clearColor(0, 0, 0, 0); - this._$gl.clear(this._$gl.COLOR_BUFFER_BIT | this._$gl.STENCIL_BUFFER_BIT); + $gl.clearColor(0, 0, 0, 0); + $gl.clear($gl.COLOR_BUFFER_BIT | $gl.STENCIL_BUFFER_BIT); // 描画領域をあらためて設定 this._$viewportWidth = position.w; this._$viewportHeight = position.h; - this._$gl.viewport(position.x, position.y, position.w, position.h); + $gl.viewport(position.x, position.y, position.w, position.h); - this._$gl.enable(this._$gl.SCISSOR_TEST); - this._$gl.scissor( + $gl.enable($gl.SCISSOR_TEST); + $gl.scissor( position.x, position.y, position.w, position.h ); @@ -662,7 +711,7 @@ export class CanvasToWebGLContext position.w, position.h ); - this._$bind(attachment); + this.bind(attachment); this.save(); this.setTransform(1, 0, 0, 1, 0, 0); @@ -680,7 +729,7 @@ export class CanvasToWebGLContext manager.releaseAttachment(attachment); // reset - this._$bind(currentAttachment); + this.bind(currentAttachment); return texture; } @@ -736,15 +785,15 @@ export class CanvasToWebGLContext const attachment: AttachmentImpl = manager .createTextureAttachmentFrom(atlasTexture); - this._$bind(attachment); + this.bind(attachment); - this._$gl.enable(this._$gl.SCISSOR_TEST); - this._$gl.scissor( + $gl.enable($gl.SCISSOR_TEST); + $gl.scissor( position.x, position.y, position.w, position.h ); - this._$gl.clearColor(0, 0, 0, 0); - this._$gl.disable(this._$gl.SCISSOR_TEST); + $gl.clearColor(0, 0, 0, 0); + $gl.disable($gl.SCISSOR_TEST); this.save(); this.setTransform(1, 0, 0, 1, 0, 0); @@ -760,7 +809,7 @@ export class CanvasToWebGLContext manager.releaseAttachment(attachment); // reset - this._$bind(currentAttachment); + this.bind(currentAttachment); manager.textureManager.release(texture); } @@ -781,7 +830,7 @@ export class CanvasToWebGLContext * @method * @public */ - _$bind (attachment: AttachmentImpl | null = null): void + bind (attachment: AttachmentImpl | null = null): void { if (!attachment) { return; @@ -798,7 +847,7 @@ export class CanvasToWebGLContext if (this._$viewportWidth !== width || this._$viewportHeight !== height) { this._$viewportWidth = width; this._$viewportHeight = height; - this._$gl.viewport(0, 0, width, height); + $gl.viewport(0, 0, width, height); } // カラーバッファorステンシルバッファが、未初期化の場合はクリアする @@ -814,9 +863,9 @@ export class CanvasToWebGLContext stencilBuffer.dirty = false; } - this._$gl.clearColor(0, 0, 0, 0); + $gl.clearColor(0, 0, 0, 0); this.clearRect(0, 0, this._$viewportWidth, this._$viewportHeight); - this._$gl.clearColor(this._$clearColorR, this._$clearColorG, this._$clearColorB, this._$clearColorA); + $gl.clearColor(this._$clearColorR, this._$clearColorG, this._$clearColorB, this._$clearColorA); this._$mask._$onClear(attachment.mask); } @@ -900,12 +949,12 @@ export class CanvasToWebGLContext const currentAttachment = manager.currentAttachment; const attachment: AttachmentImpl = manager.createTextureAttachmentFrom(atlasTexture); - this._$bind(attachment); + this.bind(attachment); const pixels = new Uint8Array(atlasTexture.width * atlasTexture.height * 4); - this._$gl.readPixels( + $gl.readPixels( 0, 0, atlasTexture.width, atlasTexture.height, - this._$gl.RGBA, this._$gl.UNSIGNED_BYTE, pixels + $gl.RGBA, $gl.UNSIGNED_BYTE, pixels ); const canvas = document.createElement("canvas"); @@ -921,7 +970,7 @@ export class CanvasToWebGLContext ctx?.putImageData(imageData, 0, 0); console.log(canvas.toDataURL()); - this._$bind(currentAttachment); + this.bind(currentAttachment); manager.releaseAttachment(attachment); } @@ -1067,10 +1116,13 @@ export class CanvasToWebGLContext this._$clearColorG = g; this._$clearColorB = b; this._$clearColorA = a; - this._$gl.clearColor(r, g, b, a); + $gl.clearColor(r, g, b, a); } /** + * @description 指定範囲の描画をクリア + * Clear the drawing in the specified range + * * @param {number} x * @param {number} y * @param {number} w @@ -1084,10 +1136,10 @@ export class CanvasToWebGLContext w: number, h: number ): void { this._$mask._$onClearRect(); - this._$gl.enable(this._$gl.SCISSOR_TEST); - this._$gl.scissor(x, y, w, h); - this._$gl.clear(this._$gl.COLOR_BUFFER_BIT | this._$gl.STENCIL_BUFFER_BIT); - this._$gl.disable(this._$gl.SCISSOR_TEST); + $gl.enable($gl.SCISSOR_TEST); + $gl.scissor(x, y, w, h); + $gl.clear($gl.COLOR_BUFFER_BIT | $gl.STENCIL_BUFFER_BIT); + $gl.disable($gl.SCISSOR_TEST); } /** @@ -1101,15 +1153,15 @@ export class CanvasToWebGLContext this._$mask._$onClearRect(); // マスクの描画領域に限定してstencil情報をクリア - this._$gl.enable(this._$gl.SCISSOR_TEST); - this._$gl.scissor( + $gl.enable($gl.SCISSOR_TEST); + $gl.scissor( this._$maskBounds.xMin, this._$maskBounds.yMin, this._$maskBounds.xMax, this._$maskBounds.yMax ); - this._$gl.clear(this._$gl.STENCIL_BUFFER_BIT); - this._$gl.disable(this._$gl.SCISSOR_TEST); + $gl.clear($gl.STENCIL_BUFFER_BIT); + $gl.disable($gl.SCISSOR_TEST); } /** @@ -1356,25 +1408,25 @@ export class CanvasToWebGLContext ); // mask on - this._$gl.enable(this._$gl.STENCIL_TEST); - this._$gl.stencilMask(0xff); + $gl.enable($gl.STENCIL_TEST); + $gl.stencilMask(0xff); // draw shape - this._$gl.enable(this._$gl.SAMPLE_ALPHA_TO_COVERAGE); - this._$gl.stencilFunc(this._$gl.ALWAYS, 0, 0xff); - this._$gl.stencilOp(this._$gl.KEEP, this._$gl.INVERT, this._$gl.INVERT); - this._$gl.colorMask(false, false, false, false); + $gl.enable($gl.SAMPLE_ALPHA_TO_COVERAGE); + $gl.stencilFunc($gl.ALWAYS, 0, 0xff); + $gl.stencilOp($gl.KEEP, $gl.INVERT, $gl.INVERT); + $gl.colorMask(false, false, false, false); coverageShader._$fill(fillVertexArrayObject); - this._$gl.disable(this._$gl.SAMPLE_ALPHA_TO_COVERAGE); + $gl.disable($gl.SAMPLE_ALPHA_TO_COVERAGE); // draw shape range - this._$gl.stencilFunc(this._$gl.NOTEQUAL, 0, 0xff); - this._$gl.stencilOp(this._$gl.KEEP, this._$gl.ZERO, this._$gl.ZERO); - this._$gl.colorMask(true, true, true, true); + $gl.stencilFunc($gl.NOTEQUAL, 0, 0xff); + $gl.stencilOp($gl.KEEP, $gl.ZERO, $gl.ZERO); + $gl.colorMask(true, true, true, true); shader._$fill(fillVertexArrayObject); // mask off - this._$gl.disable(this._$gl.STENCIL_TEST); + $gl.disable($gl.STENCIL_TEST); // release vertex array this.releaseFillVertexArray(fillVertexArrayObject); @@ -2019,7 +2071,7 @@ export class CanvasToWebGLContext ._$frameBufferManager .createTextureAttachment(width, height); - this._$bind(targetTextureAttachment); + this.bind(targetTextureAttachment); if (isGradient && lut) { @@ -2150,7 +2202,7 @@ export class CanvasToWebGLContext ._$frameBufferManager .createTextureAttachment(width, height); - this._$bind(targetTextureAttachment); + this.bind(targetTextureAttachment); this ._$frameBufferManager @@ -2215,7 +2267,7 @@ export class CanvasToWebGLContext ._$frameBufferManager .createTextureAttachment(width, height); - this._$bind(targetTextureAttachment); + this.bind(targetTextureAttachment); if (!point) { point = { "x": 0, "y": 0 }; @@ -2299,7 +2351,7 @@ export class CanvasToWebGLContext ._$attachmentArray .push(manager.currentAttachment); - this._$bind( + this.bind( manager.createCacheAttachment(width, height, multisample) ); } @@ -2318,7 +2370,7 @@ export class CanvasToWebGLContext manager.currentAttachment, release_texture ); - this._$bind( + this.bind( this._$attachmentArray.pop() ); } diff --git a/packages/webgl/src/WebGLUtil.ts b/packages/webgl/src/WebGLUtil.ts index fb9c8031..59975d08 100644 --- a/packages/webgl/src/WebGLUtil.ts +++ b/packages/webgl/src/WebGLUtil.ts @@ -15,6 +15,26 @@ export const $setRenderSize = (size: number): void => $RENDER_SIZE = Math.min(4096, size / 2); }; +/** + * @type {WebGL2RenderingContext} + * @public + */ +export let $gl: WebGL2RenderingContext; + +/** + * @description WebGL2のコンテキストをセット + * Set WebGL2 context + * + * @param {WebGL2RenderingContext} gl + * @return {void} + * @method + * @public + */ +export const $setWebGL2RenderingContext = (gl: WebGL2RenderingContext): void => +{ + $gl = gl; +}; + /** * @type {number} */ diff --git a/packages/webgl/src/index.ts b/packages/webgl/src/index.ts index ee7e3c28..f79807ad 100644 --- a/packages/webgl/src/index.ts +++ b/packages/webgl/src/index.ts @@ -1,5 +1,6 @@ export * from "./CanvasGradientToWebGL"; export * from "./CanvasPatternToWebGL"; +export * from "./CanvasToWebGLContext"; export * from "./CanvasToWebGLContextPath"; export * from "./CanvasToWebGLContextStyle"; export * from "./FrameBufferManager"; \ No newline at end of file diff --git a/worker/unzip/UnzipWorker.min.js b/worker/unzip/UnzipWorker.min.js deleted file mode 100644 index c10543fd..00000000 --- a/worker/unzip/UnzipWorker.min.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{"use strict";var r=Uint8Array,n=Uint16Array,e=Int32Array,a=new r([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),t=new r([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),i=new r([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),o=function(r,a){for(var t=new n(31),i=0;i<31;++i)t[i]=a+=1<>1|(21845&s)<<1;w=(61680&(w=(52428&w)>>2|(13107&w)<<2))>>4|(3855&w)<<4,d[s]=((65280&w)>>8|(255&w)<<8)>>1}var h=function(r,e,a){for(var t=r.length,i=0,o=new n(e);i>v]=c}else for(f=new n(t),i=0;i>15-r[i]);return f},y=new r(288);for(s=0;s<144;++s)y[s]=8;for(s=144;s<256;++s)y[s]=9;for(s=256;s<280;++s)y[s]=7;for(s=280;s<288;++s)y[s]=8;var b=new r(32);for(s=0;s<32;++s)b[s]=5;var g=h(y,9,1),p=h(b,5,1),m=function(r){for(var n=r[0],e=1;en&&(n=r[e]);return n},k=function(r,n,e){var a=n/8|0;return(r[a]|r[a+1]<<8)>>(7&n)&e},x=function(r,n){var e=n/8|0;return(r[e]|r[e+1]<<8|r[e+2]<<16)>>(7&n)},T=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],z=function(r,n,e){var a=new Error(n||T[r]);if(a.code=r,Error.captureStackTrace&&Error.captureStackTrace(a,z),!e)throw a;return a},E=function(n,e,o,f){var v=n.length,c=f?f.length:0;if(!v||e.f&&!e.l)return o||new r(0);var d=!o,s=d||2!=e.i,w=e.i;d&&(o=new r(3*v));var y,b=function(n){var e=o.length;if(n>e){var a=new r(Math.max(2*e,n));a.set(o),o=a}},T=e.f||0,E=e.p||0,M=e.b||0,S=e.l,U=e.d,A=e.m,C=e.n,q=8*v;do{if(!S){T=k(n,E,1);var D=k(n,E+1,3);if(E+=3,!D){var F=n[(y=E,(H=4+((y+7)/8|0))-4)]|n[H-3]<<8,I=H+F;if(I>v){w&&z(0);break}s&&b(M+F),o.set(n.subarray(H,I),M),e.b=M+=F,e.p=E=8*I,e.f=T;continue}if(1==D)S=g,U=p,A=9,C=5;else if(2==D){var O=k(n,E,31)+257,J=k(n,E+10,15)+4,L=O+k(n,E+5,31)+1;E+=14;for(var N=new r(L),P=new r(19),R=0;R>4)<16)N[R++]=H;else{var Q=0,V=0;for(16==H?(V=3+k(n,E,3),E+=2,Q=N[R-1]):17==H?(V=3+k(n,E,7),E+=3):18==H&&(V=11+k(n,E,127),E+=7);V--;)N[R++]=Q}}var W=N.subarray(0,O),X=N.subarray(O);A=m(W),C=m(X),S=h(W,A,1),U=h(X,C,1)}else z(1);if(E>q){w&&z(0);break}}s&&b(M+131072);for(var Y=(1<>4;if((E+=15&Q)>q){w&&z(0);break}if(Q||z(2),_<256)o[M++]=_;else{if(256==_){$=E,S=null;break}var rr=_-254;if(_>264){var nr=a[R=_-257];rr=k(n,E,(1<>4;if(er||z(3),E+=15&er,X=l[ar],ar>3&&(nr=t[ar],X+=x(n,E)&(1<q){w&&z(0);break}s&&b(M+131072);var tr=M+rr;if(Mn.length)&&(a=n.length),new r(n.subarray(e,a))}(o,0,M):o.subarray(0,M)},M=new r(0);function S(n,e){var a,t,i=function(r){31==r[0]&&139==r[1]&&8==r[2]||z(6,"invalid gzip data");var n=r[3],e=10;4&n&&(e+=2+(r[10]|r[11]<<8));for(var a=(n>>3&1)+(n>>4&1);a>0;a-=!r[e++]);return e+(2&n)}(n);return i+8>n.length&&z(6,"invalid gzip data"),E(n.subarray(i,-8),{i:2},e&&e.out||new r((t=(a=n).length,(a[t-4]|a[t-3]<<8|a[t-2]<<16|a[t-1]<<24)>>>0)),e&&e.dictionary)}function U(r,n){return E(r.subarray((e=r,a=n&&n.dictionary,(8!=(15&e[0])||e[0]>>4>7||(e[0]<<8|e[1])%31)&&z(6,"invalid zlib data"),(e[1]>>5&1)==+!a&&z(6,"invalid zlib data: "+(32&e[1]?"need":"unexpected")+" dictionary"),2+(e[1]>>3&4)),-4),{i:2},n&&n.out,n&&n.dictionary);var e,a}var A="undefined"!=typeof TextDecoder&&new TextDecoder;try{A.decode(M,{stream:!0})}catch(r){}"function"==typeof queueMicrotask?queueMicrotask:"function"==typeof setTimeout&&setTimeout;self.addEventListener("message",(r=>{return n=void 0,e=void 0,t=function*(){const n=31==(e=r.data)[0]&&139==e[1]&&8==e[2]?S(e,a):8!=(15&e[0])||e[0]>>4>7||(e[0]<<8|e[1])%31?function(r,n){return E(r,{i:2},n&&n.out,n&&n.dictionary)}(e,a):U(e,a);var e,a;let t="";for(let r=0;r +self.addEventListener("message", (event: MessageEvent): void => { - const buffer: Uint8Array = decompressSync(event.data); + const buffer = decompressSync(event.data); - let json: string = ""; + let json = ""; for (let idx: number = 0; idx < buffer.length; idx += 4096) { json += String.fromCharCode(...buffer.slice(idx, idx + 4096)); }