Working through new plugin structure

This commit is contained in:
Richard Davey 2018-05-11 01:50:37 +01:00
parent ade37dd35e
commit 0a46c13f4c
4 changed files with 192 additions and 116 deletions

View file

@ -13,6 +13,7 @@
* Optimized TextureTintPipeline.drawBlitter so it skips bobs that have alpha of zero and only calls `setTexture2D` if the bob sourceIndex has changed, previously it called it for every single bob. * Optimized TextureTintPipeline.drawBlitter so it skips bobs that have alpha of zero and only calls `setTexture2D` if the bob sourceIndex has changed, previously it called it for every single bob.
* Game.context used to be undefined if running in WebGL. It is now set to be the `WebGLRenderingContext` during WebGLRenderer.init. If you provided your own custom context, it is set to this instead. * Game.context used to be undefined if running in WebGL. It is now set to be the `WebGLRenderingContext` during WebGLRenderer.init. If you provided your own custom context, it is set to this instead.
* Game.onStepCallback has been removed.
### Bug Fixes ### Bug Fixes

View file

@ -447,39 +447,25 @@ var Config = new Class({
// Plugins // Plugins
/**
* @const {any} Phaser.Boot.Config#defaultPlugins - The plugins installed into every Scene (in addition to CoreScene and Global).
*/
this.defaultPlugins = Plugins.DefaultScene;
/**
* @const {any} Phaser.Boot.Config#installPlugins - [description]
*/
this.installPlugins = { global: [], scene: [], files: [] };
var plugins = GetValue(config, 'plugins', null);
/* /*
* Allows `plugins` property to either be an array, in which case it just replaces * Allows `plugins` property to either be an array, in which case it just replaces
* the default plugins like previously. * the default plugins like previously, or a config object.
* *
* plugins: { * plugins: {
* install: [ * install: [
* ModPlayerPlugin, * ModPlayerPlugin,
* WireFramePlugin * WireFramePlugin
* ], * ],
* filetypes: [
* MODFile
* OBJFile,
* ],
* default: [], OR * default: [], OR
* defaultMerge: { * defaultMerge: {
* 'ModPlayer': 'mod' * 'ModPlayer'
* } * }
* } * }
*
* If an object, it checks for an 'install' property,
*/ */
var plugins = GetValue(config, 'plugins', null);
var defaultPlugins = Plugins.DefaultScene;
if (plugins) if (plugins)
{ {
// Old 3.7 array format? // Old 3.7 array format?
@ -489,19 +475,29 @@ var Config = new Class({
} }
else if (IsPlainObject(plugins)) else if (IsPlainObject(plugins))
{ {
this.installPlugins.global = GetFastValue(plugins, 'install', []); // this.installPlugins.global = GetFastValue(plugins, 'install', []);
if (Array.isArray(plugins.default)) if (Array.isArray(plugins.default))
{ {
this.defaultPlugins = plugins.default; defaultPlugins = plugins.default;
} }
else if (Array.isArray(plugins.defaultMerge)) else if (Array.isArray(plugins.defaultMerge))
{ {
this.defaultPlugins = this.defaultPlugins.concat(plugins.defaultMerge); defaultPlugins = defaultPlugins.concat(plugins.defaultMerge);
} }
} }
} }
/**
* @const {any} Phaser.Boot.Config#defaultPlugins - The plugins installed into every Scene (in addition to CoreScene and Global).
*/
this.defaultPlugins = defaultPlugins;
/**
* @const {any} Phaser.Boot.Config#installPlugins - [description]
*/
this.installPlugins = GetValue(config, 'plugins.install', []);
// Default / Missing Images // Default / Missing Images
var pngPrefix = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAg'; var pngPrefix = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAg';

View file

@ -6,6 +6,13 @@
var Class = require('../utils/Class'); var Class = require('../utils/Class');
// A Scene Level Plugin is installed into every Scene and belongs to that Scene.
// It can listen for Scene events and respond to them.
// It can map itself to a Scene property, or into the Scene Systems, or both.
//
// A Global Plugin is installed just once into the Game owned Plugin Manager.
// It can listen for Game events and respond to them.
/** /**
* @classdesc * @classdesc
* [description] * [description]
@ -21,19 +28,20 @@ var Plugin = new Class({
initialize: initialize:
function Plugin (key, game) function Plugin (key, pluginManager)
{ {
/** /**
* All plugins _must_ set a key property. It's a unique string which is used by the * The unique (within this game instance) name of this plugin within the Plugin Manager.
* PluginManager to register this plugin, return it and invoke it. * This is set by the developer in their game config, although you should provide a default value.
* It must be unique within the scope of the game instance. *
*
* @name Phaser.Plugins.Plugin#key * @name Phaser.Plugins.Plugin#key
* @type {string} * @type {string}
* @since 3.8.0 * @since 3.8.0
*/ */
this.key = key; this.key = key;
this.pluginManager = pluginManager;
/** /**
* [description] * [description]
* *
@ -41,94 +49,127 @@ var Plugin = new Class({
* @type {Phaser.Game} * @type {Phaser.Game}
* @since 3.8.0 * @since 3.8.0
*/ */
this.game = game; this.game = pluginManager.game;
this.active = true; this.active = true;
// this.sceneConfig =
// The Scene that owns this plugin, if any // The Scene that owns this plugin, if any
this.scene; this.scene;
// Scene Systems (if any) // Scene Systems (if any)
this.systems; this.systems;
if (game.isBooted)
{
this.gameBoot();
}
else
{
game.events.once('boot', this.gameBoot, this);
}
}, },
/** /**
* [description] * Called when the Game boots. Or, if already booted, called immediately by the PluginManager.
* *
* @method Phaser.Plugins.Plugin#gameBoot * @method Phaser.Plugins.Plugin#init
* @since 3.8.0 * @since 3.8.0
*/ */
gameBoot: function () init: function ()
{ {
console.log('gameBoot'); console.log('Plugin.init');
this.game.events.on('pause', this.gamePause, this);
this.game.events.on('resume', this.gameResume, this);
this.game.events.on('resize', this.gameResize, this);
this.game.events.once('destroy', this.gameDestroy, this);
}, },
gamePause: function () /**
* Called when the Game pauses.
*
* @method Phaser.Plugins.Plugin#pauseGame
* @since 3.8.0
*/
pauseGame: function ()
{ {
// Game instance has paused
}, },
gameResume: function () /**
* Called when the Game resumes from a paused state.
*
* @method Phaser.Plugins.Plugin#resumeGame
* @since 3.8.0
*/
resumeGame: function ()
{ {
// Game instance has resumed from a paused state
}, },
gameResize: function (newWidth, newHeight) /**
* Called when the Game resizes.
*
* @method Phaser.Plugins.Plugin#resize
* @since 3.8.0
*/
resize: function (newWidth, newHeight)
{ {
// Game instance has been resized // Game instance has been resized
}, },
step: function (time, delta)
{
// Called automatically by the PluginManager, invoked from the Game.step
// Do any continuous processing or updating that you need in here
// Not called if Plugin.active = false
},
/** /**
* Game instance has been destroyed. * Called when the Game steps.
* Called automatically by the PluginManager, invoked from the Game.step.
* Do any continuous processing or updating that you need in here.
* Not called if Plugin.active = false
* *
* @method Phaser.Plugins.Plugin#gameDestroy * @method Phaser.Plugins.Plugin#step
* @since 3.8.0 * @since 3.8.0
*/ */
gameDestroy: function () step: function (time, delta)
{ {
this.game = null;
this.scene = null;
this.systems = null;
}, },
// Scene Level ... // Scene Level ...
/** /**
* This method is called automatically, only once, when the Scene is first created. * This method is called automatically, only once, when the Scene is first created.
* Do not invoke it directly. * It's only called if this is a Scene Plugin.
* *
* @method Phaser.Time.Clock#boot * @method Phaser.Plugins.Plugin#sceneBoot
* @private * @since 3.8.0
* @since 3.5.1
*/ */
boot: function () sceneBoot: function (scene)
{ {
if (this.systems) this.scene = scene;
{ this.systems = scene.sys;
this.systems.events.once('destroy', this.destroy, this);
} var eventEmitter = scene.sys.events;
eventEmitter.once('destroy', this.sceneDestroy, this);
// Listening to the following events is entirely optional, although we would recommend cleanly shutting down and destroying at least.
// If you don't need any of these events then remove the listeners and the relevant methods too.
eventEmitter.on('start', this.start, this);
eventEmitter.on('preupdate', this.preUpdate, this);
eventEmitter.on('update', this.update, this);
eventEmitter.on('postupdate', this.postUpdate, this);
eventEmitter.on('pause', this.pause, this);
eventEmitter.on('resume', this.resume, this);
eventEmitter.on('sleep', this.sleep, this);
eventEmitter.on('wake', this.wake, this);
eventEmitter.on('shutdown', this.shutdown, this);
eventEmitter.on('destroy', this.destroy, this);
},
/**
* Game instance has been destroyed.
* You must release everything in here, all references, all objects, free it all up.
*
* @method Phaser.Plugins.Plugin#destroy
* @since 3.8.0
*/
destroy: function ()
{
this.game = null;
this.scene = null;
this.systems = null;
}, },

View file

@ -5,9 +5,15 @@
*/ */
var Class = require('../utils/Class'); var Class = require('../utils/Class');
var EventEmitter = require('eventemitter3');
var IsPlainObject = require('../utils/object/IsPlainObject');
var GetFastValue = require('../utils/object/GetFastValue');
// Contains the plugins that Phaser uses globally and locally. // Contains the plugins that Phaser uses globally and locally.
// These are the source objects, not instantiated. // These are the source objects, not instantiated.
var corePlugins = {};
// Contains the plugins that the dev has loaded into their game
var plugins = {}; var plugins = {};
/** /**
@ -25,10 +31,14 @@ var plugins = {};
*/ */
var PluginManager = new Class({ var PluginManager = new Class({
Extends: EventEmitter,
initialize: initialize:
function PluginManager (game) function PluginManager (game)
{ {
EventEmitter.call(this);
/** /**
* [description] * [description]
* *
@ -38,10 +48,13 @@ var PluginManager = new Class({
*/ */
this.game = game; this.game = game;
// Plugins currently running and managed by this Plugin Manager // Plugins currently running and managed by this Plugin Manager.
// These are Game instance specific // These are Game instance specific.
this.activePlugins = []; this.activePlugins = [];
// Plugins that should be installed into Scenes
this.scenePlugins = [];
if (game.isBooted) if (game.isBooted)
{ {
this.boot(); this.boot();
@ -63,17 +76,15 @@ var PluginManager = new Class({
this.game.events.once('destroy', this.destroy, this); this.game.events.once('destroy', this.destroy, this);
// Any plugins to install? // Any plugins to install?
/*
var list = this.game.config.installPlugins; var list = this.game.config.installPlugins;
if (list) if (list)
{ {
for (var key in list) for (var key in list)
{ {
this.add(key, list[key]); // this.register(key, list[key]);
} }
} }
*/
}, },
/** /**
@ -87,7 +98,7 @@ var PluginManager = new Class({
*/ */
installGlobal: function (sys, globalPlugins) installGlobal: function (sys, globalPlugins)
{ {
var game = sys.game; var game = this.game;
var scene = sys.scene; var scene = sys.scene;
var map = sys.settings.map; var map = sys.settings.map;
@ -130,12 +141,12 @@ var PluginManager = new Class({
{ {
var pluginKey = scenePlugins[i]; var pluginKey = scenePlugins[i];
if (!plugins[pluginKey]) if (!corePlugins[pluginKey])
{ {
continue; continue;
} }
var source = plugins[pluginKey]; var source = corePlugins[pluginKey];
var plugin = new source.plugin(scene); var plugin = new source.plugin(scene);
@ -156,38 +167,80 @@ var PluginManager = new Class({
}, },
/** /**
* Register a plugin with the PluginManager. This is the same as calling the * Registers a plugin with the PluginManager.
* static function, but is available via the game pluginManager instance.
* *
* Key is a reference used to get the plugin from the plugins object (i.e. InputPlugin) * Key is a reference used to get the plugin from the plugins object (i.e. MyPlugin)
* Plugin is the object to instantiate to create the plugin * Plugin is the function to instantiate to create a plugin instance.
* Mapping is what the plugin is injected into the Scene.Systems as (i.e. input)
* *
* @method Phaser.Plugins.PluginManager#register * @method Phaser.Plugins.PluginManager#register
* @since 3.8.0 * @since 3.8.0
* *
* @param {string} key - [description] * @param {string} key - [description]
* @param {object} plugin - [description] * @param {function} plugin - [description]
* @param {string} mapping - [description]
*/ */
register: function (key, plugin, mapping) register: function (key, plugin, start, isScenePlugin)
{ {
plugins[key] = { plugin: plugin, mapping: mapping }; if (start === undefined) { start = false; }
if (isScenePlugin === undefined) { isScenePlugin = false; }
if (typeof plugin !== 'function')
{
console.warn('Invalid Plugin: ' + key);
return;
}
if (plugins.hasOwnProperty(key))
{
console.warn('Plugin key in use: ' + key);
return;
}
// Add it to the plugin store
plugins[key] = plugin;
if (start)
{
this.start(key);
}
if (isScenePlugin)
{
}
return this;
}, },
add: function (plugin) start: function (key)
{ {
var instance = new plugin(this.game); var instance;
var plugin = this.get(key);
var key = instance.key; if (plugin)
{
instance = new plugin(this);
plugins[key] = { plugin: plugin }; this.activePlugins.push(instance);
}
this.activePlugins.push(instance);
return instance; return instance;
}, },
setScenePlugin: function (scene)
{
},
addGameObject: function ()
{
},
addFileType: function ()
{
},
/** /**
* [description] * [description]
* *
@ -200,22 +253,7 @@ var PluginManager = new Class({
*/ */
get: function (key) get: function (key)
{ {
return (plugins[key]) ? plugins[key].plugin : null; return (plugins.hasOwnProperty(key)) ? plugins[key] : null;
},
update: function (time, delta)
{
var activePlugins = this.activePlugins;
for (var i = 0; i < activePlugins.length; i++)
{
var plugin = activePlugins[i];
if (plugin.active)
{
plugin.step(time, delta);
}
}
}, },
/** /**
@ -245,7 +283,7 @@ var PluginManager = new Class({
}); });
/** /**
* Static method called directly by the Plugins * Static method called directly by the Core internal Plugins.
* Key is a reference used to get the plugin from the plugins object (i.e. InputPlugin) * Key is a reference used to get the plugin from the plugins object (i.e. InputPlugin)
* Plugin is the object to instantiate to create the plugin * Plugin is the object to instantiate to create the plugin
* Mapping is what the plugin is injected into the Scene.Systems as (i.e. input) * Mapping is what the plugin is injected into the Scene.Systems as (i.e. input)
@ -259,7 +297,7 @@ var PluginManager = new Class({
*/ */
PluginManager.register = function (key, plugin, mapping) PluginManager.register = function (key, plugin, mapping)
{ {
plugins[key] = { plugin: plugin, mapping: mapping }; corePlugins[key] = { plugin: plugin, mapping: mapping };
}; };
module.exports = PluginManager; module.exports = PluginManager;