Iavra

Iavra Generic Popup

Oct 24th, 2015 (edited)
1,735
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*:
  2.  * @plugindesc Allows to display generic popups messages on the screen.
  3.  * <Iavra Generic Popup>
  4.  * @author Iavra
  5.  *
  6.  * @param Display On Scene
  7.  * @desc A comma-separated list of scenes where popups are allowed.
  8.  * @default Scene_Map, Scene_Menu
  9.  *
  10.  * @help
  11.  * To display a new popup, call the following function:
  12.  *
  13.  * IAVRA.POPUP.popup(text, options, callbacks);
  14.  *
  15.  * Where "text" is the text to be displayed, "options" is an optional object to override some or all of the default
  16.  * options and "callbacks" is an optional object to override some or all of the default callbacks. Any escape characters
  17.  * can be used inside the "text" parameter, but most will need to have their backslashes doubled.
  18.  *
  19.  * The following options can be specified:
  20.  *
  21.  * width         Width of the popup window. It's height will be autofit to its content. Default: 200
  22.  * duration      How long the popup should be visible. The update callback can choose to ignore this value. Default: 100
  23.  * lineHeight    Overwrite lineHeight() in Window_Base, use default if empty. Default: (empty)
  24.  * fontName      Overwrite standardFontFace() in Window_Base, use default if empty. Default: (empty)
  25.  * fontSize      Overwrite standardFontSize() in Window_Base, use default if empty. Default: (empty)
  26.  * padding       Overwrite standardPadding() in Window_Base, use default if empty. Default: (empty)
  27.  * textPadding   Overwrite textPadding() in Window_Base, use default if empty. Default: (empty)
  28.  * backOpacity   Overwrite standardBackOpacity() in Window_Base, use default if empty. Default: (empty)
  29.  * windowskin    Overwrite loadWindowskin() in Window_Base, use default if empty. Default: (empty)
  30.  * scenes        Takes an array of scene classes and overwrites the value specified in "Display On Scene".
  31.  *
  32.  * The following callbacks can be specified:
  33.  *
  34.  * init(popup)   Called after the popup has been created, but before text has been drawn on it.
  35.  * update(popup) Called every frame. If this function returns a falsy value, the popup is removed. It has access to the
  36.  *               popup duration and can either work with or ignore it.
  37.  * remove(popup) Called when the popup is removed either by running out, clear() or because update() returned false.
  38.  *
  39.  * To clear all popups, call the following function:
  40.  *
  41.  * IAVRA.POPUP.clear();
  42.  */
  43.  
  44. var Imported = Imported || {};
  45. Imported.iavra_generic_popup = true;
  46.  
  47. //=============================================================================
  48. // namespace IAVRA
  49. //=============================================================================
  50.  
  51. var IAVRA = IAVRA || {};
  52.  
  53. (function() {
  54.     "use strict";
  55.    
  56.     /**
  57.      * Since PluginManager.parameters() breaks when the plugin file is renamed, we are using our own solution.
  58.      */
  59.     var _params = $plugins.filter(function(p) { return p.description.contains('<Iavra Generic Popup>'); })[0].parameters;
  60.    
  61.     /**
  62.      * All scenes where popups should be displayed. Whenever a scene gets active that isn't in this list, all popups
  63.      * will be removed.
  64.      */
  65.     var _displayOnScene = _params['Display On Scene'].split(/\s*,\s*/).filter(function(scene) {
  66.         return !!scene;
  67.     }).map(function(scene) { return eval(scene); });
  68.    
  69.     /**
  70.      * Default options to be used when a new popup is created. Can be overwritten for every popup by passing an object
  71.      * containing some or all of the keys.
  72.      */
  73.     var _defaultOptions = {
  74.         width: 200,
  75.         duration: 100,
  76.         lineHeight: undefined,
  77.         fontName: undefined,
  78.         fontSize: undefined,
  79.         padding: undefined,
  80.         textPadding: undefined,
  81.         backOpacity: undefined,
  82.         windowskin: undefined,
  83.         scenes: _displayOnScene
  84.     };
  85.    
  86.     /**
  87.      * Default callbacks to be used. Can be overwritten for every popup by passing an object containing some or all of
  88.      * the keys.
  89.      */
  90.     var _defaultCallbacks = {
  91.         init: function(popup) {},
  92.         update: function(popup) { return popup.duration-- > 0; },
  93.         remove: function(popup) {}
  94.     };
  95.    
  96.     /**
  97.      * MV's WindowLayer has issues with windows that are overlapping each other, so we use Pixi's base class directly.
  98.      * We declare the following methods on the container:
  99.      * update()      Calls update() on all popups. Integrates the container in MV's engine.
  100.      * remove(popup) Removes a popup from the container and calls its "remove()" callback, if any.
  101.      * clear()       Removes all popups from the container and calls their "remove()" callbacks, if any.
  102.      */
  103.     var _container = (function($) {
  104.    
  105.         $.update = function() {
  106.             this.children.forEach(function(popup) { popup.update(); });
  107.         };
  108.        
  109.         $.remove = function(popup) {
  110.             popup._callbacks.remove(popup);
  111.             this.removeChild(popup);
  112.         };
  113.        
  114.         $.clear = function() {
  115.             this.children.forEach(function(popup) { popup._callbacks.remove(popup); });
  116.             this.removeChildren();
  117.         };
  118.        
  119.         return $;
  120.     })(new PIXI.DisplayObjectContainer());
  121.    
  122.     /**
  123.      * Utility function that takes 2 objects and iterates over all keys in the first one. If the second object contains
  124.      * that key, its value is taken, otherwise we take the default. The result is merged to a new object and returned.
  125.      */
  126.     var mergeOptions = function(defaults, options) {
  127.         options || (options = {});
  128.         return Object.keys(defaults).reduce(function(map, key) {
  129.             map[key] = options[key] !== undefined ? options[key] : defaults[key];
  130.             return map;
  131.         }, {});
  132.     };
  133.    
  134.     //=============================================================================
  135.     // module IAVRA.POPUP
  136.     //=============================================================================
  137.    
  138.     IAVRA.POPUP = {
  139.        
  140.         /**
  141.          * Adds a new popup with the given text to the container. "options" and "callbacks" are optional objects, that can
  142.          * be used to overwrite the default options and callbacks.
  143.          */
  144.         popup: function(text, options, callbacks) {
  145.             _container.addChild(new IAVRA.POPUP.Window_Popup(text, options, callbacks));
  146.         },
  147.        
  148.         /**
  149.          * Clears all popups, calling their "remove()" callbacks, if specified.
  150.          */
  151.         clear: function() {
  152.             _container.clear();
  153.         }
  154.        
  155.     };
  156.    
  157.     //=============================================================================
  158.     // class IAVRA.POPUP.Window_Popup
  159.     //=============================================================================
  160.    
  161.     IAVRA.POPUP.Window_Popup = function() { this.initialize.apply(this, arguments); };
  162.     (function($) {
  163.         ($.prototype = Object.create(Window_Base.prototype)).constructor = $;
  164.    
  165.         /**
  166.          * Creates a new popup window. The given options and callbacks (if any) are merged with the default values and the
  167.          * popup height is calculated by splitting the given text at newlines.
  168.          */
  169.         $.prototype.initialize = function(text, options, callbacks) {
  170.             this._options = mergeOptions(_defaultOptions, options);
  171.             this._callbacks = mergeOptions(_defaultCallbacks, callbacks);
  172.             var height = this.fittingHeight(text.split('\n').length);
  173.             Window_Base.prototype.initialize.call(this, 0, 0, this._options.width, height);
  174.             this._callbacks.init(this);
  175.             this.drawTextEx(text, 0, 0);
  176.         };
  177.        
  178.         /**
  179.          * Calls the update callback and decreases the popup duration by one. If either the callback returns false or the
  180.          * duration has run out, the popup is removed. It's up to the callback to handle any kind of fading or positioning
  181.          * needed.
  182.          */
  183.         $.prototype.update = function() {
  184.             Window_Base.prototype.update.call(this);
  185.             this._callbacks.update(this) || _container.remove(this);
  186.         };
  187.        
  188.         /**
  189.          * Accessor for the duration of the popup.
  190.          */
  191.         Object.defineProperty($.prototype, 'duration', {
  192.             get: function() { return this._options.duration; },
  193.             set: function(value) { this._options.duration = value; }
  194.         });
  195.        
  196.         /**
  197.          * Overwrite lineHeight
  198.          */
  199.         $.prototype.lineHeight = function() {
  200.             return this._options.lineHeight !== undefined ? this._options.lineHeight : Window_Base.prototype.lineHeight.call(this);
  201.         };
  202.        
  203.         /**
  204.          * Overwrite standardFontFace
  205.          */
  206.         $.prototype.standardFontFace = function() {
  207.             return this._options.fontName !== undefined ? this._options.fontName : Window_Base.prototype.standardFontFace.call(this);
  208.         };
  209.        
  210.         /**
  211.          * Overwrite standardFontSize
  212.          */
  213.         $.prototype.standardFontSize = function() {
  214.             return this._options.fontSize !== undefined ? this._options.fontSize : Window_Base.prototype.standardFontSize.call(this);
  215.         };
  216.        
  217.         /**
  218.          * Overwrite standardPadding
  219.          */
  220.         $.prototype.standardPadding = function() {
  221.             return this._options.padding !== undefined ? this._options.padding : Window_Base.prototype.standardPadding.call(this);
  222.         };
  223.        
  224.         /**
  225.          * Overwrite textPadding
  226.          */
  227.         $.prototype.textPadding = function() {
  228.             return this._options.textPadding !== undefined ? this._options.textPadding : Window_Base.prototype.textPadding.call(this);
  229.         };
  230.        
  231.         /**
  232.          * Overwrite standardBackOpacity
  233.          */
  234.         $.prototype.standardBackOpacity = function() {
  235.             return this._options.backOpacity !== undefined ? this._options.backOpacity : Window_Base.prototype.standardBackOpacity.call(this);
  236.         };
  237.        
  238.         /**
  239.          * Overwrite loadWindowskin
  240.          */
  241.         $.prototype.loadWindowskin = function() {
  242.             if(this._options.windowskin !== undefined) {
  243.                 this.windowskin = ImageManager.load(this._options.windowskin);
  244.             } else {
  245.                 Window_Base.prototype.loadWindowskin.call(this);
  246.             }
  247.         };
  248.        
  249.         return $;
  250.     })(IAVRA.POPUP.Window_Popup);
  251.    
  252.     //=============================================================================
  253.     // class Scene_Base
  254.     //=============================================================================
  255.    
  256.     (function($) {
  257.        
  258.         /**
  259.          * Registering our container in every scene, on top of regular windows.
  260.          */
  261.         var _alias_createWindowLayer = $.prototype.createWindowLayer;
  262.         $.prototype.createWindowLayer = function() {
  263.             _alias_createWindowLayer.apply(this, arguments);
  264.             this.addChild(_container);
  265.         };
  266.        
  267.         /**
  268.          * When terminating the scene, we remove all popups, that shouldn't be displayed on the next scene.
  269.          */
  270.         var _alias_terminate = $.prototype.terminate;
  271.         $.prototype.terminate = function() {
  272.             _alias_terminate.apply(this, arguments);
  273.             _container.children.forEach(function(popup) {
  274.                 popup._options.scenes.some(function(scene) { return SceneManager.isNextScene(scene); }) || _container.remove(popup);
  275.             });
  276.         };
  277.        
  278.     })(Scene_Base);
  279.    
  280.     //=============================================================================
  281.     // module SceneManager
  282.     //=============================================================================
  283.    
  284.     (function($) {
  285.        
  286.         /**
  287.          * We don't want popups to appear on background images, since they are either removed by Scene_Base.terminate() or
  288.          * will probably fade our while the background still shows them. So we hide the container during the snapshot.
  289.          */
  290.         var _alias_snapForBackground = $.snapForBackground;
  291.         $.snapForBackground = function() {
  292.             _container.visible = false;
  293.             _alias_snapForBackground.apply(this, arguments);
  294.             _container.visible = true;
  295.         };
  296.        
  297.     })(SceneManager);
  298.    
  299. })();
Add Comment
Please, Sign In to add comment