Upgrade RPG Maker MV from PIXI 4.5.4 to PIXI 5.3.0

WARNING

This upgrade still requires more investigation and it is highly likely this upgrade will break plugins

Download PIXI v5 Project

Download the project files here or follow the guide below to upgrade manually

📦 PIXI v5.3.0 MV Project Files (.zip - 1mb)

Current Compatibility

  • pixi-pictures is incompatible with pixi v5, so blend modes will be disabled for all pictures.

  • It appears the WindowLayer class is broken so a quick fix has been applied below and to project files, unfortunately it may cause unintended behavior to plugins and the way all windows are drawn.

Manual Installation

WARNING

Backup your project(s) before proceeding.

Preparation

TIP

If you're up to it, feel free to read the migration guide for v5 of PIXI as it should help you understand why we are making some of the changes we make.

  1. Download pixi-legacy.js from Github

  2. Download pixi-tilemap from Github

  3. Rename pixi-legacy.js to pixi.js

  4. Move all above files to your projects js/libs/ directory

Code Changes

We need to make changes to RPG Maker MV's codebase, this is done quicker and easier in a code editor like Visual Studio Code

Index.html

  1. Remove line 16
<script type="text/javascript" src="js/libs/pixi-picture.js"></script>

rpg_core.js

  1. Rename VoidFilter() on line 3952 to AlphaFilter()
// Old
Sprite.voidFilter = new PIXI.filters.VoidFilter();

// Rename to this
Sprite.voidFilter = new PIXI.filters.AlphaFilter();
  1. Rename VoidFilter() on line 6977 to AlphaFilter()
WindowLayer.voidFilter = new PIXI.filters.VoidFilter();

// Rename to this
WindowLayer.voidFilter = new PIXI.filters.AlphaFilter();
  1. Comment out or remove line 5946
// PIXI.glCore.VertexArrayObject.FORCE_NATIVE = true;
  1. On line 5910 change PIXI.extras.PictureTilingSprite.prototype to PIXI.TilingSprite.prototype as shown below
// Change from this
TilingSprite.prototype = Object.create(PIXI.extras.PictureTilingSprite.prototype);

// To this
TilingSprite.prototype = Object.create(PIXI.TilingSprite.prototype);
  1. Change line 5916 to PIXI.TilingSprite.call(this, texture);

Do the same on 5935 and 5934 as shown below

TilingSprite.prototype._renderCanvas_PIXI = PIXI.TilingSprite.prototype._renderCanvas;
TilingSprite.prototype._renderWebGL_PIXI = PIXI.TilingSprite.prototype._renderWebGL;
  1. on line 6063 change PIXI.extras.TilingSprite.prototype.updateTransform; to PIXI.TilingSprite.prototype.updateTransform;
TilingSprite.prototype.updateTransformTS = PIXI.TilingSprite.prototype.updateTransform;
  1. Change line 6969 as seen below
// from
    this._windowRect = this._windowMask.graphicsData[0].shape;

// to this
    this._windowRect = this._windowMask.geometry.graphicsData[0].shape;

on line 2895 change entire method

from:

Graphics._createRenderer = function() {
    PIXI.dontSayHello = true;
    var width = this._width;
    var height = this._height;
    var options = { view: this._canvas };
    try {
        switch (this._rendererType) {
        case 'canvas':
            this._renderer = new PIXI.CanvasRenderer(width, height, options);
            break;
        case 'webgl':
            this._renderer = new PIXI.WebGLRenderer(width, height, options);
            break;
        default:
            this._renderer = PIXI.autoDetectRenderer(width, height, options);
            break;
        }

        if(this._renderer && this._renderer.textureGC)
            this._renderer.textureGC.maxIdle = 1;

    } catch (e) {
        this._renderer = null;
    }
};

to this:

Graphics._createRenderer = function() {
    PIXI.dontSayHello = true;
    var options = {
        view: this._canvas,
        width: this._width,
        height: this._height,
        resolution: window.devicePixelRatio,
        autoDensity: true
    };
    try {
        this._renderer = new PIXI.Renderer(options);

        if(this._renderer && this._renderer.textureGC) {
            this._renderer.textureGC.maxIdle = 1;
        }
    } catch (e) {
        this._renderer = null;
    }
};
  1. On line 2411 add

TIP

The code below is a quick fix to ensure the tilemap is correctly loaded when using PIXI v5 as it appears the tilemap is unable to render the tileset correctly due to the bitmaps not being ready when the map is loaded.

    if (this._tilemap.bitmaps) {
        if (!this.isTilesetReady && this._tilemap.bitmaps.every(bitmap => bitmap.isRequestReady())) {
            this._tilemap.refresh();
            this._tilemap.refreshTileset()
            this.isTilesetReady = true
        }
    }

Full method should look like this 👇

Spriteset_Map.prototype.updateTilemap = function() {
    this._tilemap.origin.x = $gameMap.displayX() * $gameMap.tileWidth();
    this._tilemap.origin.y = $gameMap.displayY() * $gameMap.tileHeight();

    if (this._tilemap.bitmaps) {
        if (!this.isTilesetReady && this._tilemap.bitmaps.every(bitmap => bitmap.isRequestReady())) {
            this._tilemap.refresh();
            this._tilemap.refreshTileset()
            this.isTilesetReady = true
        }
    }
};
  1. And then on line 5528 and on line 5530 we change renderWebGL to render
ShaderTilemap.prototype.render = function(renderer) {
    this._hackRenderer(renderer);
    PIXI.Container.prototype.render.call(this, renderer);
};

Scene_Map

It appears WindowLayer() class is broken due to the renderWebGL method, which I believe was a fix for window masks. It appears that directly adding the window to the scene works fine.

  1. change line 175 from this._windowLayer.addChild(window) to this.addChild(window)
Scene_Base.prototype.addWindow = function(window) {
    this.addChild(window);
};
  1. On line 163 change the creation of WindowLayer to PIXI.Container().
this._windowLayer = new PIXI.Container();

Entire method below 👇

Scene_Base.prototype.createWindowLayer = function() {
    var width = Graphics.boxWidth;
    var height = Graphics.boxHeight;
    var x = (Graphics.width - width) / 2;
    var y = (Graphics.height - height) / 2;
    this._windowLayer = new PIXI.Container();
    this.addChild(this._windowLayer);
};