Iavra

Iavra Event Popup

Oct 27th, 2015 (edited)
2,109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*:
  2.  * @plugindesc Allows to display popups messages above events, which can be used for speech bubbles or on chests.
  3.  * <Iavra Event Popup>
  4.  * @author Iavra
  5.  *
  6.  * =============================================================================
  7.  *
  8.  * @param Popup Width
  9.  * @desc Default width for the popup window. Overflowing text will be cut away. Default: 200
  10.  * @default 200
  11.  *
  12.  * @param Offset X
  13.  * @desc By default, popups are centered on event.screenX(). This is the X offset. Default: 0
  14.  * @default 0
  15.  *
  16.  * @param Offset Y
  17.  * @desc By default, popups are centered on event.screenY(). This is the Y offset. Default: 0
  18.  * @default 0
  19.  *
  20.  * @param Display Duration
  21.  * @desc How long the popup will be displayed after fading in and before fading out. Default: 200
  22.  * @default 200
  23.  *
  24.  * @param Fade In Duration
  25.  * @desc How long it takes for the popup to fade in. Default: 10
  26.  * @default 10
  27.  *
  28.  * @param Fade Out Duration
  29.  * @desc How long it takes for the popup to fade out. Default: 60
  30.  * @default 60
  31.  *
  32.  * @param Font Name
  33.  * @desc Name of the font to be used. If left empty, default is used instead. Default: (empty)
  34.  * @default
  35.  *
  36.  * @param Font Size
  37.  * @desc Font size to be used. Default: 12
  38.  * @default 12
  39.  *
  40.  * @param Line Height
  41.  * @desc Line height to be used. Should be a bit higher than font size. Default: 18
  42.  * @default 18
  43.  *
  44.  * @param Retain On Scene
  45.  * @desc When one of these scenes becomes active, popups will be hidden, instead of destroyed. Default: Scene_Menu, Scene_Battle
  46.  * @default Scene_Menu, Scene_Battle
  47.  *
  48.  * =============================================================================
  49.  *
  50.  * @help
  51.  * To create a popup, call the following function in a "Script" event command:
  52.  *
  53.  * IAVRA.EVENTPOPUP.popup(eventId, text, options);
  54.  *
  55.  * Where "eventId" is the id of the event you want to show the popup on, "text" is the message you want to show and
  56.  * "options" is an optional object, that can be used to override the default values set via plugin parameters.
  57.  *
  58.  * The following list shows all possible options:
  59.  *
  60.  * width      The width of the popup window. By default, popups will be horizontally centered on the event.
  61.  * x          An offset on the x axis. By default, popups are centered on the event.
  62.  * y          An offset on the y axis. By default, popups are centered on the event.
  63.  * duration   How long the popup should stay visible after it has faded in and before it starts to fade out.
  64.  * fadeIn     How long it takes for the popup to fade in.
  65.  * fadeOut    How long it takes for the popup to fade out.
  66.  * fontName   The font to be used.
  67.  * fontSize   The font size to be used.
  68.  * lineHeight Height of a single text line. This should be slightly higher than fontSize.
  69.  *
  70.  * The "text" parameter can contain any special characters. Beware that icons have a fixed size and might look strange
  71.  * depending on the fontSize. Also remember that you need to double backslashes on certain escape codes. To display the
  72.  * value of variable 10, you would use \\V[10], for example.
  73.  *
  74.  * If you want to remove popups, before they have faded out, you can do so by calling this function:
  75.  *
  76.  * IAVRA.EVENTPOPUP.clear(eventId);
  77.  *
  78.  * This will remove all popups shown for a specific event or all popups if the "eventId" parameter is left out.
  79.  *
  80.  * If you don't want to use script calls, you can use the following plugin commands, instead, but note that it's not
  81.  * possible to specify options for the "popup" command:
  82.  *
  83.  * EventPopup popup eventId text
  84.  * EventPopup clean eventId
  85.  *
  86.  * Inside plugin commands, you can use the keyword "this" (without quotes) to show or clear popups on the current event.
  87.  */
  88.  
  89. var Imported = Imported || {};
  90. Imported.iavra_event_popup = true;
  91.  
  92. //=============================================================================
  93. // namespace IAVRA
  94. //=============================================================================
  95.  
  96. var IAVRA = IAVRA || {};
  97.  
  98. (function() {
  99.     "use strict";
  100.    
  101.     /**
  102.      * Since PluginManager.parameters() breaks when the plugin file is renamed, we are using our own solution.
  103.      */
  104.     var _params = $plugins.filter(function(p) { return p.description.contains('<Iavra Event Popup'); })[0].parameters;
  105.    
  106.     /**
  107.      * Usually, popups are destroyed when a new scene becomes active. Specific scenes can be marked in "Retain On Scene"
  108.      * so popups still won't be displayed, but are still there and will be shown once Scene_Map becomes active again.
  109.      */
  110.     var _paramRetainOnscene = _params['Retain On Scene'].split(/\s*,\s*/).filter(function(scene) {
  111.         return !!scene;
  112.     }).map(function(scene) { return eval(scene); });
  113.     _paramRetainOnscene.push(Scene_Map);
  114.    
  115.     /**
  116.      * Our default options as given in the plugin's parameters. We default to 0, since otherwise it wouldn't be possible
  117.      * to give 0 as a parameter unless we do a more complicated check.
  118.      */
  119.     var _defaultOptions = {
  120.         width: parseInt(_params['Popup Width']) || 0,
  121.         x: parseInt(_params['Offset X']) || 0,
  122.         y: parseInt(_params['Offset Y']) || 0,
  123.         duration: parseInt(_params['Display Duration']) || 0,
  124.         fadeIn: parseInt(_params['Fade In Duration']) || 0,
  125.         fadeOut: parseInt(_params['Fade Out Duration']) || 0,
  126.         fontName: _params['Font Name'] || null,
  127.         fontSize: parseInt(_params['Font Size']) || 0,
  128.         lineHeight: parseInt(_params['Line Height']) || 0
  129.     };
  130.    
  131.     /**
  132.      * Container for all created popup windows. Using WindowLayer would cause overlapping popups to cut each other and
  133.      * inserting directly in Scene_Map causes all popups to vanish when entering the menu (which i don't want). So we
  134.      * are using Pixi's base class with an added update() function to be compatible with Scene_Base.
  135.      */
  136.     var _container = (function($) {
  137.         $.update = function() {
  138.             this.children.forEach(function(child) { if(child.update) child.update(); });
  139.         };
  140.         return $;
  141.     })(new PIXI.DisplayObjectContainer());
  142.    
  143.     /**
  144.      * Utility function that takes 2 objects and iterates over all keys in the first one. If the second object contains
  145.      * that key, its value is taken, otherwise we take the default. The result is merged to a new object and returned.
  146.      */
  147.     var mergeOptions = function(defaults, options) {
  148.         options || (options = {});
  149.         return Object.keys(defaults).reduce(function(map, key) {
  150.             map[key] = options[key] !== undefined ? options[key] : defaults[key];
  151.             return map;
  152.         }, {});
  153.     };
  154.    
  155.     /**
  156.      * Removes a popup from the container, so the popup doesn't have to reference the container directly.
  157.      */
  158.     var removePopup = function(popup) { _container.removeChild(popup); };
  159.    
  160.     //=============================================================================
  161.     // module IAVRA.EVENTPOPUP
  162.     //=============================================================================
  163.    
  164.     IAVRA.EVENTPOPUP = {
  165.        
  166.         /**
  167.          * Creates a new popup displaying the given text on the given event. An optional object can be used to override
  168.          * some or all of the default options.
  169.          */
  170.         popup: function(eventId, text, options) {
  171.             _container.addChild(new IAVRA.EVENTPOPUP.Window_Popup(eventId, text, options));
  172.         },
  173.        
  174.         /**
  175.          * Clears either all popups (if eventId is undefined) or only those belonging to the given eventId.
  176.          */
  177.         clear: function(eventId) {
  178.             if(eventId === undefined) {
  179.                 _container.removeChildren();
  180.             } else {
  181.                 _container.children.filter(function(child) {
  182.                     return child._eventId === eventId;
  183.                 }).forEach(function(child) {
  184.                     _container.removeChild(child);
  185.                 });
  186.             }
  187.         },
  188.        
  189.         /**
  190.          * Callbacks for drawing the popup background as well as fading in and out the popups. I put these in the public
  191.          * scope, so it's easy to override them in other plugins.
  192.          */
  193.         _callbacks: {
  194.             drawBackground: function(popup) {
  195.                 var color1 = popup.dimColor1();
  196.                 var color2 = popup.dimColor2();
  197.                 var width = popup.contentsWidth();
  198.                 var height = popup.contentsHeight();
  199.                 popup.opacity = 0;
  200.                 popup.contents.gradientFillRect(0, 0, width / 2, height, color2, color1);
  201.                 popup.contents.gradientFillRect(width / 2, 0, width / 2, height, color1, color2);
  202.             },
  203.             fadeIn: function(popup) {
  204.                 return (popup.contentsOpacity += 255 / (popup._options.fadeIn || 1)) >= 255;
  205.             },
  206.             fadeOut: function(popup) {
  207.                 return (popup.contentsOpacity -= 255 / (popup._options.fadeOut || 1)) <= 0;
  208.             }
  209.         }
  210.        
  211.     };
  212.    
  213.     //=============================================================================
  214.     // class IAVRA.EVENTPOPUP.Window_Popup
  215.     //=============================================================================
  216.    
  217.     IAVRA.EVENTPOPUP.Window_Popup = function() { this.initialize.apply(this, arguments); };
  218.     (function($) {
  219.         ($.prototype = Object.create(Window_Base.prototype)).constructor = $;
  220.        
  221.         /**
  222.          * Creates a new popup displaying the given text on the given event. An optional object can be used to override
  223.          * some or all of the default options.
  224.          */
  225.         $.prototype.initialize = function(eventId, text, options) {
  226.             this._options = mergeOptions(_defaultOptions, options);
  227.             this._eventId = eventId;
  228.             var height = this.fittingHeight(text.split('\n').length);
  229.             Window_Base.prototype.initialize.call(this, 0, 0, this._options.width, height);
  230.             IAVRA.EVENTPOPUP._callbacks.drawBackground(this);
  231.             this.drawTextEx(text, 0, 0);
  232.             this.contentsOpacity = 0;
  233.         };
  234.        
  235.         /**
  236.          * If the event we are referencing doesn't exist, we remove the popup from our container and return. Otherwise we
  237.          * update our position according to the event's screen position.
  238.          */
  239.         $.prototype.update = function() {
  240.             Window_Base.prototype.update.call(this);
  241.             var event = $gameMap.event(this._eventId);
  242.             if(event === undefined) { removePopup(this); return; }
  243.             this.x = event.screenX() + this._options.x - this.width / 2;
  244.             this.y = event.screenY() + this._options.y - this.height;
  245.             if(!this._finishedFadeIn) {
  246.                 this._finishedFadeIn = IAVRA.EVENTPOPUP._callbacks.fadeIn(this);
  247.             } else if(--this._options.duration <= 0 && IAVRA.EVENTPOPUP._callbacks.fadeOut(this)) {
  248.                 removePopup(this);
  249.             }
  250.         };
  251.        
  252.         /**
  253.          * Using our own font or fall back to the default, if none was specified.
  254.          */
  255.         $.prototype.standardFontFace = function() {
  256.             return this._options.fontName || Window_Base.prototype.standardFontFace.call(this);
  257.         };
  258.        
  259.         /**
  260.          * Using our own font size.
  261.          */
  262.         $.prototype.standardFontSize = function() { return this._options.fontSize; };
  263.        
  264.         /**
  265.          * Using our own line height.
  266.          */
  267.         $.prototype.lineHeight = function() { return this._options.lineHeight; };
  268.        
  269.         return $;
  270.     })(IAVRA.EVENTPOPUP.Window_Popup);
  271.    
  272.     //=============================================================================
  273.     // class Scene_Base
  274.     //=============================================================================
  275.    
  276.     (function($) {
  277.        
  278.         /**
  279.          * When one of the scenes not listed in "Retain on Scene" becomes active, all popups are destroyed.
  280.          */
  281.         var _alias_terminate = $.prototype.terminate;
  282.         $.prototype.terminate = function() {
  283.             _alias_terminate.apply(this, arguments);
  284.             _paramRetainOnscene.some(function(scene) { return SceneManager.isNextScene(scene); }) || _container.removeChildren();
  285.         };
  286.        
  287.     })(Scene_Base);
  288.    
  289.     //=============================================================================
  290.     // class Scene_Map
  291.     //=============================================================================
  292.    
  293.     (function($) {
  294.        
  295.         /**
  296.          * We add our own container before the windowlayer, so windows are still being displayed on top of popups.
  297.          */
  298.         var _alias_createWindowLayer = $.prototype.createWindowLayer;
  299.         $.prototype.createWindowLayer = function() {
  300.             this.addChild(_container);
  301.             _alias_createWindowLayer.apply(this, arguments);
  302.         };
  303.        
  304.     })(Scene_Map);
  305.    
  306.     //=============================================================================
  307.     // class Game_Interpreter
  308.     //=============================================================================
  309.    
  310.     (function($) {
  311.        
  312.         /**
  313.          * When our plugin command is called, we take the first parameter to determine the actual command and the second
  314.          * parameter to determine the eventId. The special case "this" is used to point to the id of the current event.
  315.          * In case of the "popup" command, we also need to join the remaining arguments to get the complete String and
  316.          * pass it to eval(), so special characters are properly formatted.
  317.          */
  318.         var _alias_pluginCommand = $.prototype.pluginCommand;
  319.         $.prototype.pluginCommand = function(command, args) {
  320.             _alias_pluginCommand.apply(this, arguments);
  321.             if(command === 'EventPopup') {
  322.                 var actualCommand = args.shift();
  323.                 var eventId = args.shift();
  324.                 (eventId !== 'this') || (eventId = this.eventId());
  325.                 switch(actualCommand) {
  326.                     case 'popup':
  327.                         IAVRA.EVENTPOPUP.popup(eventId, eval(args.join(' ')));
  328.                         break;
  329.                     case 'clear':
  330.                         IAVRA.EVENTPOPUP.clear(eventId);
  331.                         break;
  332.                 };
  333.             }
  334.         };
  335.        
  336.     })(Game_Interpreter);
  337.    
  338. })();
Add Comment
Please, Sign In to add comment