//============================================================================== // Komado.js ver.1.01 //============================================================================== /*: * @plugindesc 子窓プラグイン * @author 奏ねこま(おとぶきねこま) * @url http://makonet.sakura.ne.jp/rpg_tkool * @target MZ * * @param exclude plugin * @type string[] * @default [] * @desc 子窓で無効にするプラグイン * * @help * 本プラグインの利用方法については下記マニュアルをご参照ください。 * http://makonet.sakura.ne.jp/rpg_tkool/MVMZ/Komado/document.html * * ------------------------------------------------------------------------------ * 本プラグインの利用はRPGツクール/RPG Makerの正規ユーザーに限られます。 * 商用、非商用、有償、無償、一般向け、成人向けを問わず利用可能です。 * ご利用の際に連絡や報告は必要ありません。また、製作者名の記載等も不要です。 * プラグインを導入した作品に同梱する形以外での再配布、転載はご遠慮ください。 * 本プラグインにより生じたいかなる問題についても一切の責任を負いかねます。 * ------------------------------------------------------------------------------ * Copylight (c) 2020 Nekoma Otobuki * http://makonet.sakura.ne.jp/rpg_tkool/ * https://twitter.com/maconetto_labo */ (()=>{ 'use strict'; if (!Utils.isNwjs()) { return; } let $p = (p => ({ 'exclude plugin': eval(p['exclude plugin']), 'index.html': '', 'js/main.js': '', 'resetListener': [], 'render count': 0 }))(PluginManager.parameters('Komado')); function addResetListener(listener) { $p['resetListener'].push(listener); } function callResetListener() { let listener; while (listener = $p['resetListener'].shift()) { listener(); } } if (!opener || opener == global) { /* Main Window */ (fs => { let html = process.mainModule.filename; let js = html.replace(/\/index.html/, '/js/main.js'); fs.readFile(html, 'utf8', (err, data) => $p['index.html'] = data); fs.readFile(js, 'utf8', (err, data) => $p['js/main.js'] = data); })(require('fs')); //============================================================================== // DataManager //============================================================================== (__extractSaveContents => { DataManager.extractSaveContents = function(contents) { __extractSaveContents.apply(this, arguments); $gameScreen._komados = $gameScreen._komados || []; }; })(DataManager.extractSaveContents); //============================================================================== // SceneManager //============================================================================== (__updateScene => { SceneManager.updateScene = function() { __updateScene.apply(this, arguments); if (this.isNextScene(Scene_Title) && !this._scene.isBusy() || this._scene instanceof Scene_Load && this.isNextScene(Scene_Map) && !this._scene.isBusy()) { callResetListener(); } }; })(SceneManager.updateScene); //============================================================================== // Game_Temp //============================================================================== (__initialize => { Game_Temp.prototype.initialize = function() { __initialize.apply(this, arguments); this._isReadyKomado = false; this._reservedKomadoEvent = {}; this._requestRefreshCount = 0; }; })(Game_Temp.prototype.initialize); //============================================================================== // Game_System //============================================================================== (__initialize => { Game_System.prototype.initialize = function() { __initialize.apply(this, arguments); this._komados = []; }; })(Game_System.prototype.initialize); Game_System.prototype.createKomado = function(mapId, x, y, width, height, options = {}) { let komado = new Game_Komado(mapId, x, y, width, height, options); this._komados.push(komado); }; Game_System.prototype.updateKomado = function() { if (!$gameTemp._isReadyKomado) { let komados = [...this._komados].sort((a,b) => a._sortId - b._sortId); komados.forEach(komado => komado.open()); $gameTemp._isReadyKomado = true; } if (this._komados.find(komado => komado.isClosed())) { this._komados = this._komados.filter(komado => !komado.isClosed()); } }; Game_System.prototype.callKomadoEvent = function(mapId, eventId) { let list = $gameTemp._reservedKomadoEvent[mapId] || []; list.push(eventId); $gameTemp._reservedKomadoEvent[mapId] = list; }; //============================================================================== // Game_Screen //============================================================================== (__update => { Game_Screen.prototype.update = function() { __update.apply(this, arguments); $gameSystem.updateKomado(); }; })(Game_Screen.prototype.update); //============================================================================== // Gsme_Map //============================================================================== (__requestRefresh => { Game_Map.prototype.requestRefresh = function(mapId) { __requestRefresh.apply(this, arguments); $gameTemp._requestRefreshCount++; }; })(Game_Map.prototype.requestRefresh); //============================================================================== // Game_Komado //============================================================================== class Game_Komado { constructor(mapId, x, y, width, height, options = {}) { this._mapId = mapId; this._x = x; this._y = y; this._width = width; this._height = height; this._player = options.player || { x: 0, y: 0, transparent: false }; this._title = options.title || ''; this._alwaysOnTop = options.alwaysOnTop == null ? true : options.alwaysOnTop; this._frame = options.frame == null ? true : options.frame; this._show = options.show == null ? true : options.show; this._transparent = options.transparent && !this._frame; this._dragBox = this._frame ? null : options.dragBox; this._minimizeBox = this._frame ? null : options.minimizeBox; this._closeBox = this._frame ? null : options.closeBox; this._excludePlugin = options.excludePlugin || []; this._closed = false; this._sortId = Date.now(); this.open(); } open() { let js = this.createMainJs(); let html = this.createIndexHtml(js); let options = { width: this._width, height: this._height, frame: this._frame, transparent: this._transparent, show: false, resizable: false, show_in_taskbar: false }; nw.Window.open(html, options, win => { (fs => { fs.unlinkSync(html); win.window.addEventListener('load', () => fs.unlinkSync(js)); })(require('fs')); this.setup(win); }); } createMainJs() { let file = (path => path.join(path.dirname(location.pathname), `${Date.now()}.js`))(require('path')).replace(/^[\\/]/, ''); let js = $p['js/main.js']; let plugins = JSON.stringify($plugins.filter(plugin => ![...$p['exclude plugin'],...this._excludePlugin].includes(plugin.name))); let dataKomado = JSON.stringify({ width: this._width, height: this._height, mapId: this._mapId, player: this._player, show: this._show, transparent: this._transparent, minimizeBox: this._minimizeBox, closeBox: this._closeBox }); let script = `\$plugins = ${plugins}; window.\$dataKomado = ${dataKomado};`; js = js.replace(/(?=PluginManager.setup)/, script); require('fs').writeFileSync(file, js); return file; } createIndexHtml(jsFile) { let file = (path => path.join(path.dirname(location.pathname), `${Date.now()}.html`))(require('path')).replace(/^[\\/]/, ''); let html = $p['index.html']; let title = this._title || $dataSystem.gameTitle; html = html.replace(/(?<=).*(?=<\/title>)/, title) .replace(/js\/main.js/, jsFile); require('fs').writeFileSync(file, html); return file; } setup(win) { this.setupWindow(win); this.setupEvent(win); } setupWindow(win) { win.x = this._x - (this._frame ? 2 : 0); win.y = this._y; let frameWidth = win.window.outerWidth - win.window.innerWidth; let frameHeight = win.window.outerHeight - win.window.innerHeight; let width = this._width - (win.width - this._width) + frameWidth; let height = this._height - (win.height - this._height) + frameHeight; win.resizeTo(width, height); } setupEvent(win) { let main = nw.Window.get(); let onfocus = () => { if (this._alwaysOnTop) { win.setAlwaysOnTop(true); win.setAlwaysOnTop(false); } }; let onminimize = () => win.minimize(); let onmaximize = () => onfocus(); let onrestore = () => win.restore(); let onresize = () => onfocus(); let onmousedown = () => this._alwaysOnTop && win.setAlwaysOnTop(true); let onmouseup = () => onfocus(); let onclosed = () => { if (!this._closed) { win.close(); } main.removeListener('minimize', onminimize); main.removeListener('maximize', onmaximize); main.removeListener('resize', onresize); main.removeListener('restore', onrestore); main.removeListener('closed', onclosed); removeEventListener('focus', onfocus); removeEventListener('mousedown', onmousedown); removeEventListener('mouseup', onmouseup); removeEventListener('unload', onunload); }; let onunload = () => onclosed(); let onend = () => onclosed(); win.on('loaded', () => { let document = win.window.document; if (!this._frame) { if (this._dragBox) { let div = document.createElement('div'); div.style.position = 'absolute'; div.style.left = this._dragBox.x + 'px'; div.style.top = this._dragBox.y + 'px'; div.style.width = this._dragBox.width + 'px'; div.style.height = this._dragBox.height + 'px'; div.style.zIndex = 100; div.style['-webkit-app-region'] = 'drag'; document.body.appendChild(div); } if (this._minimizeBox) { let left = this._minimizeBox.x; let top = this._minimizeBox.y; let right = left + this._minimizeBox.width; let bottom = top + this._minimizeBox.height; document.addEventListener('click', event => { let x = event.pageX; let y = event.pageY; if (x >= left && y >= top && x <= right && y <= bottom) { win.minimize(); } }); } if (this._closeBox) { let left = this._closeBox.x; let top = this._closeBox.y; let right = left + this._closeBox.width; let bottom = top + this._closeBox.height; document.addEventListener('click', event => { let x = event.pageX; let y = event.pageY; if (x >= left && y >= top && x <= right && y <= bottom) { win.close(); } }); } } if (this._transparent) { document.body.style.backgroundColor = ''; } }); win.on('focus', () => { main.removeListener('resize', onresize); removeEventListener('focus', onfocus); removeEventListener('mousedown', onmousedown); removeEventListener('mouseup', onmouseup); main.on('resize', onresize); addEventListener('focus', onfocus); addEventListener('mousedown', onmousedown); addEventListener('mouseup', onmouseup); this._sortId = Date.now(); }); win.on('move', (x, y) => { this._x = x + (this._frame ? 2 : 0); this._y = y; }); win.on('minimize', () => main.minimize()); win.on('closed', () => { this._closed = true; onclosed(); }); main.on('minimize', onminimize); main.on('maximize', onmaximize); main.on('resize', onresize); main.on('restore', onrestore); main.on('closed', onclosed); addEventListener('focus', onfocus); addEventListener('mousedown', onmousedown); addEventListener('mouseup', onmouseup); addEventListener('unload', onunload); addResetListener(onend); } isClosed() { return this._closed; } } window.Game_Komado = Game_Komado; } else { /* Sub Window */ if (Utils.RPGMAKER_NAME == 'MV') { SceneManager._screenWidth = $dataKomado.width; SceneManager._screenHeight = $dataKomado.height; SceneManager._boxWidth = $dataKomado.width; SceneManager._boxHeight = $dataKomado.height; } function isControlBox(x, y) { if (!$dataKomado.transparent) return false; let minimizeBox = $dataKomado.minimizeBox; if (minimizeBox) { let left = minimizeBox.x; let top = minimizeBox.y; let right = left + minimizeBox.width; let bottom = top + minimizeBox.height; if (x >= left && y >= top && x <= right && y <= bottom) { return true; } } let closeBox = $dataKomado.closeBox; if (closeBox) { let left = closeBox.x; let top = closeBox.y; let right = left + closeBox.width; let bottom = top + closeBox.height; if (x >= left && y >= top && x <= right && y <= bottom) { return true; } } return false; } //============================================================================== // PIXI //============================================================================== (() => { let _renderer = {}; function CanvasWebGLRenderer(target, prop) { if (!_renderer[prop]) { let renderer = function(options, arg2, arg3) { if ($dataKomado.transparent) { arg3.transparent = true; } target[prop].call(this, options, arg2, arg3); }; renderer.prototype = Object.create(target[prop].prototype); renderer.prototype.constructor = renderer; _renderer[prop] = renderer; } return _renderer[prop]; } function autoDetectRenderer(target, prop) { if (!_renderer[prop]) { let renderer = function(options, arg1, arg2, arg3) { if ($dataKomado.transparent) { arg2.transparent = true; } return target[prop].call(this, options, arg1, arg2, arg3); }; _renderer[prop] = renderer; } return _renderer[prop]; } function Application(target, prop) { if (!_renderer[prop]) { let renderer = function(options) { if ($dataKomado.transparent) { options.transparent = true; } return target[prop].call(this, options); }; renderer.prototype = Object.create(target[prop].prototype); renderer.prototype.constructor = renderer; _renderer[prop] = renderer; } return _renderer[prop]; } PIXI = new Proxy(PIXI, { get: (target, prop) => { if (Utils.RPGMAKER_NAME == 'MV') { if (['CanvasRenderer','WebGLRenderer'].includes(prop)) { return CanvasWebGLRenderer(target, prop); } if (prop == 'autoDetectRenderer') { return autoDetectRenderer(target, prop); } } if (Utils.RPGMAKER_NAME == 'MZ') { if (prop == 'Application') { return Application(target, prop); } } return target[prop]; } }); })(); //============================================================================== // Graphics //============================================================================== Graphics._defaultStretchMode = function() { return false; }; Graphics._switchStretchMode = function() { }; Graphics._switchFullScreen = function() { }; if (Utils.RPGMAKER_NAME == 'MZ') { Graphics._createErrorPrinter = function() { this._errorPrinter = document.createElement("div"); this._errorPrinter.id = "errorPrinter"; this._errorPrinter.innerHTML = this._makeErrorHtml(); this._updateErrorPrinter(); document.body.appendChild(this._errorPrinter); }; Graphics._updateErrorPrinter = function() { const width = this._width * this._realScale; const height = Math.min(this._height, 100) * this._realScale; this._errorPrinter.style.width = width + "px"; this._errorPrinter.style.height = height + "px"; }; } //============================================================================== // TouchInput //============================================================================== (___onMouseDown => { TouchInput._onMouseDown = function(event) { if (isControlBox(event.pageX, event.pageY)) return; ___onMouseDown.apply(this, arguments); }; })(TouchInput._onMouseDown); (___onWheel => { TouchInput._onWheel = function(event) { if (isControlBox(event.pageX, event.pageY)) { event.preventDefault(); return; } ___onWheel.apply(this, arguments); }; })(TouchInput._onWheel); (___onTouchStart => { TouchInput._onTouchStart = function(event) { if (isControlBox(event.pageX, event.pageY)) { event.preventDefault(); return; } ___onTouchStart.apply(this, arguments); }; })(TouchInput._onTouchStart); //============================================================================== // DataManager //============================================================================== (__isSkill => { DataManager.isSkill = function(item) { return __isSkill.apply(this, arguments) || (item && opener.$dataSkills.contains(item)); }; })(DataManager.isSkill); (__isItem => { DataManager.isItem = function(item) { return __isItem.apply(this, arguments) || (item && opener.$dataItems.contains(item)); }; })(DataManager.isItem); (__isWeapon => { DataManager.isWeapon = function(item) { return __isWeapon.apply(this, arguments) || (item && opener.$dataWeapons.contains(item)); }; })(DataManager.isWeapon); (__isArmor => { DataManager.isArmor = function(item) { return __isArmor.apply(this, arguments) || (item && opener.$dataArmors.contains(item)); }; })(DataManager.isArmor); (__makeSaveContents => { DataManager.makeSaveContents = function() { let contents = __makeSaveContents.apply(this, arguments); contents.actors = opener.$gameActors; return contents; }; })(DataManager.makeSaveContents); (__extractSaveContents => { DataManager.extractSaveContents = function(contents) { __extractSaveContents.apply(this, arguments); $gameVariables = opener.$gameVariables; $gameSwitches = opener.$gameSwitches; $gameSelfSwitches = opener.$gameSelfSwitches; $gameActors._data = []; }; })(DataManager.extractSaveContents); //============================================================================== // SceneManager //============================================================================== (__isGameActive => { SceneManager.isGameActive = function() { __isGameActive.apply(this, arguments); return true; }; })(SceneManager.isGameActive); (__update => { SceneManager.update = function() { if (this._scene instanceof Scene_Map) { if ($p['render count'] == 1) { if ($dataKomado.show) { nw.Window.get().show(); } } if ($p['render count'] < 2) { if (Utils.RPGMAKER_NAME == 'MV' && this.isCurrentSceneStarted() && Graphics._rendered || Utils.RPGMAKER_NAME == 'MZ' && this._scene.isStarted()) { $p['render count']++; } } } __update.apply(this, arguments); }; })(SceneManager.update); (__onKeyDown => { SceneManager.onKeyDown = function(event) { if (![116,119].includes(event.keyCode) || event.ctrlKey || event.altKey) { __onKeyDown.apply(this, arguments); } }; })(SceneManager.onKeyDown); //============================================================================== // Scene_Boot //============================================================================== Scene_Boot.prototype.start = function() { $dataSystem.startMapId = $dataKomado.mapId; $dataSystem.startX = $dataKomado.player.x || 0; $dataSystem.startY = $dataKomado.player.y || 0; $dataSystem.optTransparent = !!$dataKomado.player.transparent; Scene_Base.prototype.start.call(this); SoundManager.preloadImportantSounds(); this.checkPlayerLocation(); DataManager.setupNewGame(); $gameVariables = opener.$gameVariables; $gameSwitches = opener.$gameSwitches; $gameSelfSwitches = opener.$gameSelfSwitches; $gamePlayer._fadeType = 2; SceneManager.goto(Scene_Map); if (Utils.RPGMAKER_NAME == 'MZ') { $dataSystem.advanced.screenWidth = $dataKomado.width; $dataSystem.advanced.screenHeight = $dataKomado.height; $dataSystem.advanced.uiAreaWidth = $dataKomado.width; $dataSystem.advanced.uiAreaHeight = $dataKomado.height; this.resizeScreen(); } }; //============================================================================== // Spriteset_Base //============================================================================== (__createBaseSprite => { Spriteset_Base.prototype.createBaseSprite = function() { __createBaseSprite.apply(this, arguments); if ($dataKomado.transparent) { this._blackScreen.opacity = 0; } }; })(Spriteset_Base.prototype.createBaseSprite); //============================================================================== // Game_Temp //============================================================================== (__initialize => { Game_Temp.prototype.initialize = function() { __initialize.apply(this, arguments); this._requestRefreshCount = 0; }; })(Game_Temp.prototype.initialize); //============================================================================== // Game_Actors //============================================================================== (__actor => { Game_Actors.prototype.actor = function(actorId) { let isNew = !this._data[actorId]; let actor = __actor.apply(this, arguments); if (actor && isNew) { this._data[actorId] = new Proxy(actor, { get: (target, prop) => { if (typeof target[prop] != 'function') { return opener.$gameActors.actor(target._actorId)[prop]; } return target[prop]; }, set: (target, prop, value) => { if (typeof value != 'function') { opener.$gameActors.actor(target._actorId)[prop] = value; } else { target[prop] = value;; } } }); } return actor; }; })(Game_Actors.prototype.actor); //============================================================================== // Game_Map //============================================================================== (__update => { Game_Map.prototype.update = function(sceneActive) { let list = opener.$gameTemp._reservedKomadoEvent[this._mapId]; if (list) { delete opener.$gameTemp._reservedKomadoEvent[this._mapId]; list.forEach(eventId => { let event; if (typeof eventId == 'number') { event = this.event(eventId); } else { event = this.events().filter(event => { return (event.event().meta['komadoevent'] || event.event().meta['KomadoEvent']) == eventId; })[0]; } if (event) { event.start(); } }); } if ($gameTemp._requestRefreshCount != opener.$gameTemp._requestRefreshCount) { $gameTemp._requestRefreshCount = opener.$gameTemp._requestRefreshCount; this._needsRefresh = true; } __update.apply(this, arguments); }; })(Game_Map.prototype.update); } })();