Source: tiny/core/renderers/SystemRenderer.js

import EventEmitter from 'eventemitter3';
import { hex2string, hex2rgb } from '../../../utils';
import { Matrix, Rectangle } from '../math';
import { RENDERER_TYPE, WIN_SIZE } from '../const';
import settings from '../settings';
import Container from '../display/Container';
import RenderTexture from '../textures/RenderTexture';

const tempMatrix = new Matrix();

/**
 * The SystemRenderer is the base for a Tiny Renderer. It is extended by the {@link Tiny.CanvasRenderer} and {@link Tiny.WebGLRenderer} which can be used for rendering a Tiny scene.
 *
 * @abstract
 * @class
 * @extends EventEmitter
 * @memberof Tiny
 */
export default class SystemRenderer extends EventEmitter {
  /**
   * @param {string} system - The name of the system this renderer is for.
   * @param {number} width - the width of the screen
   * @param {number} height - the height of the screen
   * @param {object} [options] - The optional renderer parameters
   * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional
   * @param {boolean} [options.transparent=false] - If the render view is transparent, default false
   * @param {boolean} [options.autoResize=false] - If the render view is automatically resized, default false
   * @param {boolean} [options.antialias=false] - sets antialias (only applicable in chrome at the moment)
   * @param {number} [options.resolution=1] - The resolution / device pixel ratio of the renderer. The resolution of the renderer retina would be 2.
   * @param {boolean} [options.preserveDrawingBuffer=false] - enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context.
   * @param {boolean} [options.clearBeforeRender=true] - This sets if the renderer will clear the canvas or not before the new render pass.
   * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area (shown if not transparent).
   * @param {boolean} [options.roundPixels=false] - If true Tiny will Math.floor() x/y values when rendering, stopping pixel interpolation.
   */
  constructor(system, width, height, options) {
    super();

    options = Object.assign({
      width,
      height,
    }, options);

    // Add the default render options
    options = Object.assign({}, settings.RENDER_OPTIONS, options);

    /**
     * The supplied constructor options.
     *
     * @member {object}
     * @readOnly
     */
    this.options = options;
    // console.log(options);

    /**
     * The type of the renderer.
     *
     * @member {number}
     * @default Tiny.RENDERER_TYPE.UNKNOWN
     * @see Tiny.RENDERER_TYPE
     */
    this.type = RENDERER_TYPE.UNKNOWN;

    /**
     * Measurements of the screen. (0, 0, screenWidth, screenHeight)
     *
     * Its safe to use as filterArea or hitArea for whole stage
     *
     * @member {Tiny.Rectangle}
     */
    this.screen = new Rectangle(0, 0, options.width, options.height);

    /**
     * The canvas element that everything is drawn to
     *
     * @member {HTMLCanvasElement}
     */
    this.view = options.view || document.createElement('canvas');

    /**
     * The resolution / device pixel ratio of the renderer
     *
     * @member {number}
     * @default 1
     */
    this.resolution = options.resolution || settings.RESOLUTION;

    /**
     * Whether the render view is transparent
     *
     * @member {boolean}
     */
    this.transparent = options.transparent;

    /**
     * Whether css dimensions of canvas view should be resized to screen dimensions automatically
     *
     * @member {boolean}
     */
    this.autoResize = options.autoResize || false;

    /**
     * Tracks the blend modes useful for this renderer.
     *
     * @member {object<string, mixed>}
     */
    this.blendModes = null;

    /**
     * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering.
     *
     * @member {boolean}
     */
    this.preserveDrawingBuffer = options.preserveDrawingBuffer;

    /**
     * This sets if the CanvasRenderer will clear the canvas or not before the new render pass.
     * If the scene is NOT transparent Tiny will use a canvas sized fillRect operation every frame to set the canvas background color. If the scene is transparent Tiny will use clearRect to clear the canvas every frame. Disable this by setting this to false. For example if your game has a canvas filling background image you often don't need this set.
     *
     * @member {boolean}
     * @default
     */
    this.clearBeforeRender = options.clearBeforeRender;

    /**
     * If true Tiny will Math.floor() x/y values when rendering, stopping pixel interpolation.
     * Handy for crisp pixel art and speed on legacy devices.
     *
     * @member {boolean}
     */
    this.roundPixels = options.roundPixels;

    /**
     * The background color as a number.
     *
     * @member {number}
     * @private
     */
    this._backgroundColor = 0x000000;

    /**
     * The background color as an [R, G, B] array.
     *
     * @member {number[]}
     * @private
     */
    this._backgroundColorRgba = [0, 0, 0, 0];

    /**
     * The background color as a string.
     *
     * @member {string}
     * @private
     */
    this._backgroundColorString = '#000000';

    this.backgroundColor = options.backgroundColor || this._backgroundColor; // run bg color setter

    /**
     * This temporary display object used as the parent of the currently being rendered item
     *
     * @member {Tiny.DisplayObject}
     * @private
     */
    this._tempDisplayObjectParent = new Container();

    /**
     * The last root object that the renderer tried to render.
     *
     * @member {Tiny.DisplayObject}
     * @private
     */
    this._lastObjectRendered = this._tempDisplayObjectParent;
  }

  /**
   * Same as view.width, actual number of pixels in the canvas by horizontal
   *
   * @member {number}
   * @readonly
   */
  get width() {
    return this.view.width;
  }

  /**
   * Same as view.height, actual number of pixels in the canvas by vertical
   *
   * @member {number}
   * @readonly
   */
  get height() {
    return this.view.height;
  }

  /**
   * Resizes the screen and canvas to the specified width and height
   * Canvas dimensions are multiplied by resolution
   *
   * @param {number} screenWidth - the new width of the screen
   * @param {number} screenHeight - the new height of the screen
   */
  resize(screenWidth, screenHeight) {
    this.screen.width = screenWidth;
    this.screen.height = screenHeight;

    this.view.width = screenWidth * this.resolution;
    this.view.height = screenHeight * this.resolution;

    if (this.autoResize) {
      this.view.style.width = `${screenWidth}px`;
      this.view.style.height = `${screenHeight}px`;

      WIN_SIZE.width = Math.round(this.width);
      WIN_SIZE.height = Math.round(this.height);
    }
  }

  /**
   * Useful function that returns a texture of the display object that can then be used to create sprites
   * This can be quite useful if your displayObject is complicated and needs to be reused multiple times.
   *
   * @param {Tiny.DisplayObject} displayObject - The displayObject the object will be generated from
   * @param {number} scaleMode - Should be one of the scaleMode consts
   * @param {number} resolution - The resolution / device pixel ratio of the texture being generated
   * @param {Tiny.Rectangle} [region] - The region of the displayObject, that shall be rendered, if no region is specified, defaults to the local bounds of the displayObject.
   * @return {Tiny.Texture} a texture of the graphics object
   */
  generateTexture(displayObject, scaleMode, resolution, region) {
    region = region || displayObject.getLocalBounds(null, true);

    const renderTexture = RenderTexture.create(region.width | 0, region.height | 0, scaleMode, resolution);

    tempMatrix.tx = -region.x;
    tempMatrix.ty = -region.y;

    this.render(displayObject, renderTexture, false, tempMatrix, !!displayObject.parent);

    return renderTexture;
  }

  /**
   * Removes everything from the renderer and optionally removes the Canvas DOM element.
   *
   * @param {boolean} [removeView=false] - Removes the Canvas element from the DOM.
   */
  destroy(removeView) {
    if (removeView && this.view.parentNode) {
      this.view.parentNode.removeChild(this.view);
    }

    this.type = RENDERER_TYPE.UNKNOWN;

    this.view = null;

    this.screen = null;

    this.resolution = 0;

    this.transparent = false;

    this.autoResize = false;

    this.blendModes = null;

    this.options = null;

    this.preserveDrawingBuffer = false;
    this.clearBeforeRender = false;

    this.roundPixels = false;

    this.backgroundColor = 0;
    this._backgroundColorRgba = null;
    this._backgroundColorString = null;

    this._tempDisplayObjectParent = null;
    this._lastObjectRendered = null;
  }

  /**
   * The background color to fill if not transparent
   *
   * @member {number}
   */
  get backgroundColor() {
    return this._backgroundColor;
  }

  set backgroundColor(value) {
    this._backgroundColor = value;
    this._backgroundColorString = hex2string(value);
    hex2rgb(value, this._backgroundColorRgba);
  }
}
Documentation generated by JSDoc 3.4.3 on Fri Jul 09 2021 19:32:25 GMT+0800 (CST)