Files
nothoughts/node_modules/pixi.js/lib/rendering/renderers/shared/system/AbstractRenderer.js
2025-08-04 18:57:35 +02:00

302 lines
10 KiB
JavaScript

'use strict';
var Color = require('../../../../color/Color.js');
var autoDetectEnvironment = require('../../../../environment/autoDetectEnvironment.js');
var Container = require('../../../../scene/container/Container.js');
var unsafeEvalSupported = require('../../../../utils/browser/unsafeEvalSupported.js');
var deprecation = require('../../../../utils/logging/deprecation.js');
require('../../../../utils/utils.js');
var _const = require('../../gl/const.js');
var SystemRunner = require('./SystemRunner.js');
var EventEmitter = require('eventemitter3');
"use strict";
const defaultRunners = [
"init",
"destroy",
"contextChange",
"resolutionChange",
"reset",
"renderEnd",
"renderStart",
"render",
"update",
"postrender",
"prerender"
];
const _AbstractRenderer = class _AbstractRenderer extends EventEmitter {
/**
* Set up a system with a collection of SystemClasses and runners.
* Systems are attached dynamically to this class when added.
* @param config - the config for the system manager
*/
constructor(config) {
super();
this.runners = /* @__PURE__ */ Object.create(null);
this.renderPipes = /* @__PURE__ */ Object.create(null);
this._initOptions = {};
this._systemsHash = /* @__PURE__ */ Object.create(null);
this.type = config.type;
this.name = config.name;
this.config = config;
const combinedRunners = [...defaultRunners, ...this.config.runners ?? []];
this._addRunners(...combinedRunners);
this._unsafeEvalCheck();
}
/**
* Initialize the renderer.
* @param options - The options to use to create the renderer.
*/
async init(options = {}) {
const skip = options.skipExtensionImports === true ? true : options.manageImports === false;
await autoDetectEnvironment.loadEnvironmentExtensions(skip);
this._addSystems(this.config.systems);
this._addPipes(this.config.renderPipes, this.config.renderPipeAdaptors);
for (const systemName in this._systemsHash) {
const system = this._systemsHash[systemName];
const defaultSystemOptions = system.constructor.defaultOptions;
options = { ...defaultSystemOptions, ...options };
}
options = { ..._AbstractRenderer.defaultOptions, ...options };
this._roundPixels = options.roundPixels ? 1 : 0;
for (let i = 0; i < this.runners.init.items.length; i++) {
await this.runners.init.items[i].init(options);
}
this._initOptions = options;
}
render(args, deprecated) {
let options = args;
if (options instanceof Container.Container) {
options = { container: options };
if (deprecated) {
deprecation.deprecation(deprecation.v8_0_0, "passing a second argument is deprecated, please use render options instead");
options.target = deprecated.renderTexture;
}
}
options.target || (options.target = this.view.renderTarget);
if (options.target === this.view.renderTarget) {
this._lastObjectRendered = options.container;
options.clearColor = this.background.colorRgba;
}
if (options.clearColor) {
const isRGBAArray = Array.isArray(options.clearColor) && options.clearColor.length === 4;
options.clearColor = isRGBAArray ? options.clearColor : Color.Color.shared.setValue(options.clearColor).toArray();
}
if (!options.transform) {
options.container.updateLocalTransform();
options.transform = options.container.localTransform;
}
this.runners.prerender.emit(options);
this.runners.renderStart.emit(options);
this.runners.render.emit(options);
this.runners.renderEnd.emit(options);
this.runners.postrender.emit(options);
}
/**
* Resizes the WebGL view to the specified width and height.
* @param desiredScreenWidth - The desired width of the screen.
* @param desiredScreenHeight - The desired height of the screen.
* @param resolution - The resolution / device pixel ratio of the renderer.
*/
resize(desiredScreenWidth, desiredScreenHeight, resolution) {
const previousResolution = this.view.resolution;
this.view.resize(desiredScreenWidth, desiredScreenHeight, resolution);
this.emit("resize", this.view.screen.width, this.view.screen.height, this.view.resolution);
if (resolution !== void 0 && resolution !== previousResolution) {
this.runners.resolutionChange.emit(resolution);
}
}
clear(options = {}) {
const renderer = this;
options.target || (options.target = renderer.renderTarget.renderTarget);
options.clearColor || (options.clearColor = this.background.colorRgba);
options.clear ?? (options.clear = _const.CLEAR.ALL);
const { clear, clearColor, target } = options;
Color.Color.shared.setValue(clearColor ?? this.background.colorRgba);
renderer.renderTarget.clear(target, clear, Color.Color.shared.toArray());
}
/** The resolution / device pixel ratio of the renderer. */
get resolution() {
return this.view.resolution;
}
set resolution(value) {
this.view.resolution = value;
this.runners.resolutionChange.emit(value);
}
/**
* Same as view.width, actual number of pixels in the canvas by horizontal.
* @member {number}
* @readonly
* @default 800
*/
get width() {
return this.view.texture.frame.width;
}
/**
* Same as view.height, actual number of pixels in the canvas by vertical.
* @default 600
*/
get height() {
return this.view.texture.frame.height;
}
// NOTE: this was `view` in v7
/**
* The canvas element that everything is drawn to.
* @type {environment.ICanvas}
*/
get canvas() {
return this.view.canvas;
}
/**
* the last object rendered by the renderer. Useful for other plugins like interaction managers
* @readonly
*/
get lastObjectRendered() {
return this._lastObjectRendered;
}
/**
* Flag if we are rendering to the screen vs renderTexture
* @readonly
* @default true
*/
get renderingToScreen() {
const renderer = this;
return renderer.renderTarget.renderingToScreen;
}
/**
* Measurements of the screen. (0, 0, screenWidth, screenHeight).
*
* Its safe to use as filterArea or hitArea for the whole stage.
*/
get screen() {
return this.view.screen;
}
/**
* Create a bunch of runners based of a collection of ids
* @param runnerIds - the runner ids to add
*/
_addRunners(...runnerIds) {
runnerIds.forEach((runnerId) => {
this.runners[runnerId] = new SystemRunner.SystemRunner(runnerId);
});
}
_addSystems(systems) {
let i;
for (i in systems) {
const val = systems[i];
this._addSystem(val.value, val.name);
}
}
/**
* Add a new system to the renderer.
* @param ClassRef - Class reference
* @param name - Property name for system, if not specified
* will use a static `name` property on the class itself. This
* name will be assigned as s property on the Renderer so make
* sure it doesn't collide with properties on Renderer.
* @returns Return instance of renderer
*/
_addSystem(ClassRef, name) {
const system = new ClassRef(this);
if (this[name]) {
throw new Error(`Whoops! The name "${name}" is already in use`);
}
this[name] = system;
this._systemsHash[name] = system;
for (const i in this.runners) {
this.runners[i].add(system);
}
return this;
}
_addPipes(pipes, pipeAdaptors) {
const adaptors = pipeAdaptors.reduce((acc, adaptor) => {
acc[adaptor.name] = adaptor.value;
return acc;
}, {});
pipes.forEach((pipe) => {
const PipeClass = pipe.value;
const name = pipe.name;
const Adaptor = adaptors[name];
this.renderPipes[name] = new PipeClass(
this,
Adaptor ? new Adaptor() : null
);
});
}
destroy(options = false) {
this.runners.destroy.items.reverse();
this.runners.destroy.emit(options);
Object.values(this.runners).forEach((runner) => {
runner.destroy();
});
this._systemsHash = null;
this.renderPipes = null;
}
/**
* Generate a texture from a container.
* @param options - options or container target to use when generating the texture
* @returns a texture
*/
generateTexture(options) {
return this.textureGenerator.generateTexture(options);
}
/**
* Whether the renderer will round coordinates to whole pixels when rendering.
* Can be overridden on a per scene item basis.
*/
get roundPixels() {
return !!this._roundPixels;
}
/**
* Overridable function by `pixi.js/unsafe-eval` to silence
* throwing an error if platform doesn't support unsafe-evals.
* @private
* @ignore
*/
_unsafeEvalCheck() {
if (!unsafeEvalSupported.unsafeEvalSupported()) {
throw new Error("Current environment does not allow unsafe-eval, please use pixi.js/unsafe-eval module to enable support.");
}
}
};
/** The default options for the renderer. */
_AbstractRenderer.defaultOptions = {
/**
* Default resolution / device pixel ratio of the renderer.
* @default 1
*/
resolution: 1,
/**
* Should the `failIfMajorPerformanceCaveat` flag be enabled as a context option used in the `isWebGLSupported`
* function. If set to true, a WebGL renderer can fail to be created if the browser thinks there could be
* performance issues when using WebGL.
*
* In PixiJS v6 this has changed from true to false by default, to allow WebGL to work in as many
* scenarios as possible. However, some users may have a poor experience, for example, if a user has a gpu or
* driver version blacklisted by the
* browser.
*
* If your application requires high performance rendering, you may wish to set this to false.
* We recommend one of two options if you decide to set this flag to false:
*
* 1: Use the Canvas renderer as a fallback in case high performance WebGL is
* not supported.
*
* 2: Call `isWebGLSupported` (which if found in the utils package) in your code before attempting to create a
* PixiJS renderer, and show an error message to the user if the function returns false, explaining that their
* device & browser combination does not support high performance WebGL.
* This is a much better strategy than trying to create a PixiJS renderer and finding it then fails.
* @default false
*/
failIfMajorPerformanceCaveat: false,
/**
* Should round pixels be forced when rendering?
* @default false
*/
roundPixels: false
};
let AbstractRenderer = _AbstractRenderer;
exports.AbstractRenderer = AbstractRenderer;
//# sourceMappingURL=AbstractRenderer.js.map