one-winged-sinope/js/plugins/TRP_MapDecorator.js
2026-02-06 16:16:37 -06:00

11798 lines
No EOL
286 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//=============================================================================
// TRP_MapDecorator.js
//=============================================================================
// SETTING
// Plugin Command
// Start
// Mode / Update
// Undo/Redo
// process ZMap
// processCriff
// Supply Walls
// Supply Ceilings
// supply BackTiles
// Supply Shadows
// Room Select
// MODE: PaintFloor
// MODE: FloorVariationPalette
// MODE: ManualPaint
// MODE: ManualPaintPalette
// MODE: LocateObject
// Dot Shift Objects
// MODE: ManualLocate
// MODE: ObjectPalette
// MODE: ObjectSelect
// MODE: ObjectGrouping
// MODE: UserProcess
// User Process
// ParamEditor
// MapObject
// Util Funcs
// Restore Map
// Auto Tile Connection
// ColorPicker
// Palette
// TilesetEdit
// ParallaxSave
//=============================================================================
/*:
* @author Thirop
* @target MZ
* @plugindesc 自動装飾プラグイン<開発用>
* @base TRP_CORE
* @base TRP_MapDecorator_Template
* @orderAfter TRP_CORE
* @orderAfter TRP_MapObject
*
* @help
* 【導入】
* 以下のプラグインより下に配置
* ・TRP_CORE.js<必須>
* ・TRP_MapObject.js<オプション>
*
* 以下のプラグインより上に配置
* ・TRP_MapDecorator_Template.js<必須>
*
*
* 【更新履歴】
* 1.44 2023/09/04 修正:MapObject不使用時に再編集時のエラー修正
* 1.41 2023/06/08 修正:Windowsでモック保存ができない不具合修正。
* 修正:操作ガイドが正しく表示されていない不具合修正
* 1.36 2023/04/03 追加:置換パラメータ追加
* 1.35 2023/04/01 修正:オブジェクトの縦横比率変更ができない不具合
* 1.34 2023/04/01 修正:他タイルセット画像オブジェのプライオリティ設定
* 1.33 2023/03/25 追加:オブジェグループ、タイルセット画像登録
* 追加:遠景モック表示
* 1.32 2023/03/13 修正:アンドゥ機能のバグ/オブジェ手動配置時のエラー
* 1.31 2023/03/13 追加:複数回前までのバックアップ対応
* 追加:簡易アンドゥ/リドゥ対応
* 追加:装飾種類ロックパレット/手動ペイントパレット
* 修正:装飾種類ロック、水場ロック、チャンク消去のキー変更
* 追加:オブジェクトのドットシフト(要:TRP_MapObject)
* 追加:各モード用のカーソルアイコン設定
* 追加:パラメータ編集機能
* 1.21 2023/01/15 修正:zMap確認後にモードが戻れない不具合修正
* 1.20 2023/01/10 修正:水場ロック後の水場へのオブジェ抽選の不具合修正
* 1.19 2023/01/10 修正:オブジェ配置済みマップを再編集後にオブジェが消える不具合修正
* 1.15 2023/01/09 修正:オブジェドラッグ移動の不具合修正
* 1.14 2022/12/25 拡張:オブジェクトパレット
* 修正:「全処理の取り消し」
* 修正:手動配置時の座標ズレ、ほか細かな不具合
* 1.13 2022/12/19 修正:裏タイル補完時の影プロセスの不具合
* 1.12 2022/12/11 拡張:指定部屋の編集、置換プロセスの手動実行
* 1.11 2022/12/04 不具合修正:B-E天井タイル裏への水タイル塗布に関するバグ修正
* 1.10 2022/12/04 拡張:置換処理拡張
* 設定「autoCeilingSupplyWithEmpty」追加
* 不具合修正:バリエーション置換関連
* 1.09 2022/11/27 拡張:バリエーション置換
* 1.08 2022/11/27 修正:オブジェロック後に手動編集可能に
* 1.07 2022/11/14 拡張:オブジェクトパレット(要:TRP_CORE.js<ver1.07>)
* 1.06 2022/11/14 拡張:オブジェクトの手動配置
* 修正:崖フチへの重ね装飾タイル配置許容
* 1.05 2022/11/13 拡張:床装飾の手動調整モード追加
* 1.01 2022/11/06 保存コマンドのガイド表示
* 1.00 2022/11/05 初版
*
*
* @command start
* @text 開始
* @desc
*
* @arg templateMapId
* @text テンプレートマップID
* @desc 使用するテンプレートマップID。(テンプレートマップ自身から実行時はタイル種別を確認可)
* @type number
* @default 0
*
* @arg disableAutoSupply
* @text 壁・天井・崖の自動補完無効
* @desc ONにすると開始時の壁・天井・崖の自動補完を無効
* @type boolean
* @default false
*
*
*
*
* @param command
* @text コマンド名(MV)
* @desc MV形式プラグインコマンドのコマンド名
* @default decorator
* @type string
*
* @param roomSeparatorRegionId
* @text 部屋区切りリージョンID
* @desc 部屋区切りリージョンID
* @default 1
* @type number
*
* @param objForbiddenRegionId
* @text オブジェ配置禁止リージョンID
* @desc オブジェ配置禁止リージョンID
* @default 2
* @type number
*
*
* @param maxUndoSize
* @text アンドゥ保持サイズ(MB)
* @desc 簡易アンドゥ/リドゥに使用する内部ログデータのおおまかな保持サイズ(MB)。デフォルトは100MB
* @default 100
* @type number
*
* @param cursorIcons
* @text モードカーソル設定
* @desc 各モードのカーソルに表示するアイコンID。カンマつなぎで「床装飾」「手動ペイント」「オブジェ配置」「手動オブジェ配置」の順
* @default 217,246,129,142
* @type string
*
* @param palettePageNum
* @text ページ名表示数
* @desc ページ名の画面内での表示数。デフォ値は20
* @default 20
* @type number
*
*
*
* @param pluginPath
* @text _プラグインパス
* @desc このプラグインのファイルパス。通常は未設定でOK
* @default
*
*
*
*/
//=============================================================================
var TRP_CORE = TRP_CORE || {};
function TRP_MapDecorator(){
this.initialize.apply(this, arguments);
};
TRP_MapDecorator.INFO_CHARACTER_NAME = 'DecorationInfo';
TRP_MapDecorator.INFO_CHARACTER_Z_NAME = 'DecorationZ';
TRP_MapDecorator.INFO_CHARACTER_TYPES = {
/* [characterIndex,direction,pattern]
===================================*/
//tile types
tileTypeBase:[0,4,0],
tileTypeAccessory:[0,4,1],
tileTypeWater:[0,4,2],
wall:[0,6,0],
criff:[0,6,1],
objPalette:[0,8,0],
//obj setting
baseObjEnabled:[1,4,0],
baseObjDisabled:[1,4,1],
bigObjEmptyTile:[1,4,2],
objLocateOnEdgeEnabled:[1,6,0],
objLocateOverEdgeEnabled:[1,6,1],
objUnderLocateEnabled:[1,6,2],
objRate:[1,8,0],
bigObjRate:[1,8,1],
//other settings
variationRate:[2,4,0],
return:[2,8,2],
//process settings
variation:[3,4,0],
variationOneSize:[3,4,1],
processGroup:[3,4,2],
supplyBack:[3,6,0],
condNot:[3,6,1],
noShape:[3,6,2],
noKinds:[3,8,1],
//system
mapObjectSave:[7,4,0],
};
//=============================================================================
// remove Info Character
//=============================================================================
(function(){
'use strict';
var MapDecorator = TRP_MapDecorator;
var _Game_Map_setupEvents = Game_Map.prototype.setupEvents;
Game_Map.prototype.setupEvents = function() {
_Game_Map_setupEvents.call(this,...arguments);
var events = this._events;
for(var i=events.length-1; i>=0; i=(i-1)|0){
var event = events[i];
if(!event)continue;
var charaName = event._characterName;
if(!charaName){
var eventData = event.event();
var page = eventData.pages ? eventData.pages[0] : null;
var image = page ? page.image : null;
charaName = image ? image.characterName : null;
}
if(charaName===MapDecorator.INFO_CHARACTER_NAME
|| charaName===MapDecorator.INFO_CHARACTER_Z_NAME
){
event.erase()
events[i] = null;
}
}
};
})();
//=============================================================================
// main scope
//=============================================================================
(function(){
'use strict';
if(!Utils.isNwjs() || !Utils.isOptionValid('test'))return;
var pluginName = 'TRP_MapDecorator';
var _Dev = TRP_CORE.DevFuncs;
var MapDecorator = TRP_MapDecorator;
var MapObject = TRP_CORE.MapObject||null;
var isMZ = Utils.RPGMAKER_NAME === "MZ";
var isMac = navigator.userAgent.contains('Macintosh');
var ctrlKey = isMac ? 'Cmd' : 'Ctrl';
var supplementDef = TRP_CORE.supplementDef;
var supplementDefNum = TRP_CORE.supplementDefNum;
var parameters = PluginManager.parameters(pluginName);
var palettePageNum = Number(parameters.palettePageNum)||20;
//=============================================================================
// SETTING
//=============================================================================
var SETTING = MapDecorator.SETTING = {
// <<エディタ設定>>
//===================================
//編集時のマップ表示範囲[0以上の数値]
//└2.0とすると2倍の範囲表示(拡大率50%)<unit:0.1>
mapDispRange:1.0,
//編集時のウィンドウ幅。0=リサイズなし<unit:100>
windowWidth:1400,
//編集時のウィンドウ高さ。0=リサイズなし<unit:100>
windowHeight:900,
// <<プロセス設定>>
//===================================
//床の上マスに壁を自動配置[true/false]
autoWallSupply:true,
//壁の上マスに天井を自動配置[true/false]
autoCeilingSupply:true,
//空マスに天井タイル敷き詰め[true/false]
autoCeilingSupplyWithEmpty:false,
//天井設置に失敗しているかチェック[true/false]
checkCeilingCorrect:true,
//影を自動補完(解析したZ値マップから計算)[true/false]
autoShadowSupply:true,
//1以上でビッグオブジェをできるだけ敷き詰めるように配置。処理が重いので徐々に大きくすること
maximizeObjRateTryNum:0,
//割合算出の振れ幅[0.0~1.0]<unit:0.1>
rateRange:0.3,
// <<マップ設定>>
//===================================
//壁なし(主に遠景を使うマップ)[true/false]
noWall:false,
//壁+崖の高さを揃える[true/false]
arrangeTotalHeight:true,
//空マスを天井とみなして接続[true/false]
isEmptySpaceCeiling:false,
//壁・がけに影を落とさない[true/false]
noShadowOnWall:true,
//崖フチのオブジェ配置禁止の辺の数[1~]
criffTopObjForbiddenSideNum:1,
// <<ベース床設定>
//===================================
//床装飾を塗るベース割当[0~1.0]
floorPaintRate:0.4,
//床装飾の1箇所の最小タイル数[1~]
floorPaintChankMin:2,
//床装飾の1箇所の最大タイル数[1~]
floorPaintChankMax:10,
//0以上で床装飾のパターン数を固定、-1で床の広さに応じて算出
floorPaintPatternNum:-1,
//1部屋内で使用する床装飾の種類数の設定
// └設定例:[0,0,30,100,200]
// └29マス以下:2種, 30マス以上:3種, 100マス以上:4種, 200マス以上:5種
floorPaintPatternsWithTiles:[0,0,30,100,200],
//オブジェクトの配置割合[0~1.0]<unit:0.1>
floorObjRate:0.2,
//大オブジェクトの配置割合[0~1.0]<unit:0.1>
floorBigObjRate:0.01,
// <<水場設定>>
//================================================
//水場の配置モード[-1:自動,0:無効,1:強制配置]
waterLocateMode:-1,
//部屋に水場の配置する確率[0~1.0]<unit:0.1>
waterLocateRate:0.4,
//床面積に対する水場のベース割合[0~1.0]<unit:0.1>
waterPaintRate:0.15,
//水場1かたまりのタイル数の最小[1~]
waterChankMin:8,
//水場1かたまりのタイル数の最大[1~]
waterChankMax:18,
//水場の装飾タイルを塗るベース割合[0~1.0]<unit:0.1>
waterAccPaintRate:0.2,
//水場の装飾タイルの1かたまりのタイル数の最小[1~]
waterPaintChankMin:2,
//水場の装飾タイルの1かたまりのタイル数の最大[1~]
waterPaintChankMax:6,
//水場のオブジェクトの配置割合[0~1.0]<unit:0.1>
waterObjRate:0.15,
//水場の大オブジェクトの配置割合[0~1.0]<unit:0.1>
waterBigObjRate:0.0125,
//水場のフチにオブジェ配置許可[true/false]
waterObjOnEdge:true,
//水場の壁への接続を無効化[true/false]
diasbleWaterConnect:false,
// <<その他タイル設定>>
//===================================
//崖フチ上部の裏にタイルを補填(MZデフォタイル用)[true/false]
supplyUpperCriffTopBack:true,
};
//=============================================================================
var DEFAULT_SETTING = MapDecorator.DEFAULT_SETTING = SETTING;
var CURRENT_SETTING = MapDecorator.CURRENT_SETTING = SETTING;
MapDecorator.overwriteSettings = function(setting,validKeys=null){
if(!setting)return;
var keys = Object.keys(setting);
for(const key of keys){
this.overwriteSetting(key,setting[key],validKeys);
}
};
MapDecorator.overwriteSetting = function(key,value,validKeys=null,dstSetting=SETTING){
if(validKeys && !validKeys.contains(key)){
_Dev.showTempAlert('設定「%1」はこのコマンドでは無効です'.format(key));
return;
}
if(dstSetting===SETTING && dstSetting[key]===undefined){
_Dev.showTempAlert('設定「%1」はスペルミスの可能性があります。'.format(key));
}
dstSetting[key] = value;
};
MapDecorator.tryOverwriteSettingsWithList = function(list,index=0,command,validKeys,dstSetting){
if(!list)return;
var length = list.length;
var params = [];
for(var i=index; i<length;){
var command = list[i];
if(command.code === 105){
//scroll text
while(list[++i].code === 405){
params.push(list[i].parameters[0]);
}
}else if(command.code === 355){
//script
while(list[++i].code === 655){
params.push(list[i].parameters[0]);
}
}else{
i++;
}
}
for(var param of params){
if(param.indexOf('//')===0)continue;
var commentIdx = param.indexOf('//');
if(commentIdx>=0){
param = param.substring(0,commentIdx);
}
if(param.indexOf(':')<0)continue;
param = param.trim();
if(!param)continue;
if(param[param.length-1]===','){
param = param.substring(0,param.length-1);
}
var elems = param.split(':');
var key = elems[0];
var value = elems[1];
if(key===undefined || value===undefined)continue;
key = key.trim();
value = value.trim();
if(!isNaN(value)){
value = Number(elems[1]);
}else if(value==='false'){
value = false;
}else if(value==='true'){
value = true;
}else if(value[0]==='['||value[0]==='{'){
value = JSON.parse(value);
}
this.overwriteSetting(key,value,validKeys,dstSetting);
}
};
//=============================================================================
// Plugin Command
//=============================================================================
if(isMZ){
['start'].forEach(command=>PluginManager.registerCommand(pluginName, command, function(args){
var argsArr = Object.values(args)
argsArr.unshift(command);
MapDecorator.pluginCommand(argsArr,this);
}));
}
var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function(command,args){
if(command===parameters.command){
MapDecorator.pluginCommand(args,this);
}else{
_Game_Interpreter_pluginCommand.call(this,...arguments);
}
};
MapDecorator.pluginCommand = function(args,interpreter){
var name = args[0];
var command = "processCommand"+name[0].toUpperCase()+name.substring(1)
this[command](args,interpreter);
};
MapDecorator.processCommandStart = function(args,interpreter){
var idx = 1;
var templateMapId = Number(args[idx++]);
var disableAutoSupply = TRP_CORE.supplementDefBool(false,args[idx++]);
if(!templateMapId || !$dataMapInfos[templateMapId]){
SoundManager.playBuzzer();
window.prompt('テンプレートマップIDが無効です。\ntemplateMapId:'+templateMapId);
return;
}
if(interpreter){
this.tryOverwriteSettingsWithList(interpreter._list,interpreter._index,'start');
}
DEFAULT_SETTING = MapDecorator.DEFAULT_SETTING = JsonEx.makeDeepCopy(SETTING);
CURRENT_SETTING = MapDecorator.CURRENT_SETTING = JsonEx.makeDeepCopy(SETTING);
MapDecorator.start(templateMapId,disableAutoSupply);
};
//=============================================================================
// env variables
//=============================================================================
var allInfo = null;
var info = null;
var ENV_VARS = {};
var data;
var width;
var height;
var zLayerSize;
var zRegion;
var zAcc;
var zObj1;
var zObj2;
var zShadow;
var zRegion;
var proc = null;
var undoLog = [];
var redoLog = [];
var originalData = null;
var baseTileIds = null;
var allFloorLevelTileIds = null;
var criffTopIds = null;
var ceilingBaseIds = null;
var criffWallBaseIds = null;
var allWallIds = null;
var allCeilingIds = null;
var allObjects = null;
var tileW = 48;
var tileH = 48;
function setupEnvVariables(dataMap,allInfo){
data = dataMap.data;
width = dataMap.width;
height = dataMap.height;
zLayerSize = width*height;
zAcc = 1*zLayerSize;
zObj1 = 2*zLayerSize;
zObj2 = 3*zLayerSize;
zShadow = 4*zLayerSize;
zRegion = 5*zLayerSize;
ENV_VARS = {
data,width,height,zLayerSize,zAcc,zObj1,zObj2,zShadow,zRegion
};
tileW = $gameMap.tileWidth();
tileH = $gameMap.tileHeight();
//allInfo cache
ceilingBaseIds = [];
allCeilingIds = [];
criffWallBaseIds = [];
baseTileIds = [];
allFloorLevelTileIds = [];
criffTopIds = [];
allWallIds = [];
allObjects = [];
for(const info of allInfo){
TRP_CORE.uniquePush(baseTileIds,info.floorBaseId);
TRP_CORE.uniquePush(allFloorLevelTileIds,info.floorBaseId);
if(info.floorVariationIds){
TRP_CORE.uniquePushArray(allFloorLevelTileIds,info.floorVariationIds);
}
if(info.dummyFloorVariationIds){
TRP_CORE.uniquePushArray(allFloorLevelTileIds,info.dummyFloorVariationIds);
}
if(info.waterBaseId){
TRP_CORE.uniquePush(allFloorLevelTileIds,info.waterBaseId);
}
if(info.waterAccIds){
TRP_CORE.uniquePushArray(allFloorLevelTileIds,info.waterAccIds);
}
if(info.criffTopBaseId){
criffTopIds.push(info.criffTopBaseId);
TRP_CORE.uniquePush(allFloorLevelTileIds,info.criffTopBaseId);
}
if(info.criffTopSubIds){
TRP_CORE.uniquePushArray(criffTopIds,info.criffTopSubIds);
}
if(info.ceilingBaseId){
TRP_CORE.uniquePush(ceilingBaseIds,info.ceilingBaseId);
TRP_CORE.uniquePush(allCeilingIds,info.ceilingBaseId);
}
if(info.criffWallBaseId){
TRP_CORE.uniquePush(criffWallBaseIds,info.criffWallBaseId);
}
if(info.wallTileIds){
TRP_CORE.uniquePushArray(allWallIds,info.wallTileIds);
}
if(info.allObjIds){
TRP_CORE.uniquePushArray(allObjects,info.allObjIds);
}
}
TRP_CORE.removeArray(allObjects,MapDecorator.paletteObjects);
};
var INFO_SETTINGS = {};
MapDecorator.changeBaseInfo = function(target){
info = target;
if(!INFO_SETTINGS[info.floorBaseId]){
var setting = JsonEx.makeDeepCopy(CURRENT_SETTING);
INFO_SETTINGS[info.floorBaseId] = setting;
SETTING = INFO_SETTINGS[info.floorBaseId];
this.overwriteSettings(info.setting);
}else{
SETTING = INFO_SETTINGS[info.floorBaseId];
}
MapDecorator.SETTING = SETTING;
};
//=============================================================================
// Start
//=============================================================================
MapDecorator._mode = null;
MapDecorator._lastModes = [];
MapDecorator._playerMoveByInput = null;
MapDecorator._sceneUpDate = null;
MapDecorator._keyDownListener = null;
MapDecorator._keyUpListener = null;
MapDecorator._mouseDownListener = null;
MapDecorator._mouseUpListener = null;
MapDecorator._pasteListener = null;
MapDecorator.allInfo = null;
MapDecorator.start = function(templateMapId,disableAutoSupply=false){
this.setupScreen();
if(MapObject){
if(!MapObject.isOverlayEnabled()){
_Dev.showText('mapObjOverlayAlert',[
'MapObjectのオーバーレイ表示が無効です。',
'関連オブジェクトを正しく配置・保存できません。'
],'rgb(255,100,100)');
}
MapObject.disableSpritesheet();
}
var help = [ctrlKey+'+S:マップ保存'];
if(MapObject){
help.push(ctrlKey+'Shift+S:遠景モックで保存');
}
help.push(
'Esc:メニュー呼び出し',
'Space:パラメータ設定',
(isMac?'Opt':'Alt')+'+ドラッグ:スクロール',
);
_Dev.showText('decoratorBase',help);
/* player setting
===================================*/
$gamePlayer._transparent = true;
if($gamePlayer._followers){
$gamePlayer._followers.update();
}
SceneManager._scene._spriteset.update();
this._playerMoveByInput = $gamePlayer.moveByInput;
$gamePlayer.moveByInput = (()=>{});
if($gamePlayer._followers){
$gamePlayer._followers.update();
}
SceneManager._scene._spriteset.update();
/* scene setting
===================================*/
this._sceneUpDate = SceneManager._scene.update;
SceneManager._scene.update = ()=>{
this.update();
if(SceneManager._scene.updateTrpMousePosition){
SceneManager._scene.updateTrpMousePosition();
}
};
/* register listners
===================================*/
this._keyDownListener = this.onKeyDown.bind(this);
this._keyUpListener = (event=>{
this.disableLastStateOverwritable();
if(event.key==='Alt'){
this.onKeyAlt = false;
TRP_CORE.changeMouseCursor(this.CURSOR_BITMAP[this._mode]);
}else if(event.key==='Meta'){
this.onKeyMeta = false;
}else if(event.key==='Control'){
this.onKeyControl = false;
if(this.showingObjOutline){
this.removeObjectsOutline();
}
}
});
this._mouseDownListener = this.onMouseDown.bind(this);
this._mouseUpListener = this.onMouseUp.bind(this);
this._pasteListener = this.onPaste.bind(this);
document.addEventListener('keydown',this._keyDownListener);
document.addEventListener('keyup',this._keyUpListener);
document.addEventListener('mousedown',this._mouseDownListener);
document.addEventListener('mouseup',this._mouseUpListener);
document.addEventListener('paste',this._pasteListener);
/* disable interpreter command
===================================*/
Game_Interpreter.prototype.command105 = function(){
return true;
}
/* prepare variables
===================================*/
allInfo = this.analyzeTemplate(templateMapId);
this.allInfo = allInfo;
this.setupProcessWindowCommands();
setupEnvVariables($dataMap,allInfo);
this._clearSceneFade();
this.executeInitProcess();
/* start room select
===================================*/
this.setMode('paintFloor');
this.saveState('開始');
//check ceiling correct -> tonner error idxes
if(SETTING.checkCeilingCorrect){
this.checkCeilingCorrect();
}
};
MapDecorator.executeInitProcess = function(disableAutoSupply){
this.initProc();
this.analyzeAll();
if(MapObject){
this.analyzeMapObjects();
}
/* supply tiles
===================================*/
this.executeBeforeProcess(disableAutoSupply);
this.analyzeTileObjects();
};
MapDecorator.setupScreen = function(){
var mapDispRange = Number(SETTING.mapDispRange)||1.0
var windowW = Number(SETTING.windowWidth);
var windowH = Number(SETTING.windowHeight);
if(!windowW || windowW<=0){
windowW = Graphics.width;
}
if(!windowH || windowH<=0){
windowH = Graphics.height;
}
SETTING.mapDispRange = mapDispRange;
SETTING.windowWidth = windowW;
SETTING.windowHeight = windowH;
if(windowW!==Graphics.width || windowH!==Graphics.height){
_Dev.resizeWindow(windowW,windowH);
}
var rate = SETTING.mapDispRange;
var zoom = 1/rate;
var sprset = SceneManager._scene._spriteset;
var tilemap = sprset._tilemap;
var width = rate*Graphics.width;
var height = rate*Graphics.height;
tilemap._width = width+tilemap._margin*2;
tilemap._height = height+tilemap._margin*2;
var tileCols = Math.ceil(tilemap._width / tilemap._tileWidth) + 1;
var tileRows = Math.ceil(tilemap._height / tilemap._tileHeight) + 1;
var layerWidth = tilemap._layerWidth = tileCols * tilemap._tileWidth;
var layerHeight = tilemap._layerHeight = tileRows * tilemap._tileHeight;
tilemap._needsRepaint = true;
var container = new TRP_CORE.TRP_Container();
container.addChild(SceneManager._scene._spriteset);
container.scale.set(zoom,zoom);
SceneManager._scene.addChild(container);
if(MapObject){
$dataTrpMapObjects.forEach(obj=>{obj.setupMargin()})
}
};
MapDecorator.analyzeAll = function(){
proc.idxBaseInfoIdxMap = TRP_CORE.packValues([],0,zLayerSize);
this.analyzeRooms();
this.analyzeFloorZMap();
this.analyzeWallIdxes();
this.analyzeCeilingIdxes();
};
MapDecorator.proc = null;
MapDecorator.initProc = function(){
// _Dev.showText('roomInfo','《対象の部屋ID:--》');
originalData = data.concat();
proc = MapDecorator.proc = {};
proc.allRoomIdxes = [];
proc.roomIdxMapForUserProc = [];
proc.allBaseIdxes = [];
proc.idxBaseInfoIdxMap = [];
proc.wallIdxMap = [];
proc.wallIdxes = [];
proc.ceilingIdxes = [];
proc.zMap = [];
proc.floorLevelZMap = [];
proc.minZ = 0;
proc.maxZ = 0;
proc.waterIdxes = [];
proc.waterAccIdxes = [];
proc.passIdxes = [];
proc.criffIdxes = [];
proc.criffTopIdxes = [];
proc.criffWallIdxes = [];
proc.floorSuppliedIdxes = [];
proc.oncePaintFloor = false;
proc.lockedFloorPaintRoomIds = [];
proc.lastFloorPaintInfoArr = [];
proc.lockedFloorVariations = [];
proc.lastFloorVariations = [];
proc.noAccIdxes = [];
proc.noConnectMap = {};
proc.connectFloorIdxes = [];
proc.autoConnectRequestIdxes = [];
proc.lockedWaterRoomIds = [];
proc.lastWaterInfoArr = [];
proc.locateObj = false;
proc.lockedObjRoomIds = [];
proc.lastObjInfoArr = [];
proc.leftObjIdxesArr = [];
proc.objForbiddenIdxes = [];
}
MapDecorator.end = function(){
this.setMode(null);
_Dev.showText('roomInfo',null);
_Dev.showText('mapDec',null);
$gamePlayer._transparent = false;
$gamePlayer.moveByInput = this._playerMoveByInput;
this._playerMoveByInput = null;
SceneManager._scene.update = this._sceneUpDate;
this._sceneUpDate = null;
document.removeEventListener('keydown',this._keyDownListener);
document.removeEventListener('keyup',this._keyUpListener);
document.removeEventListener('mousedown',this._mouseDownListener);
document.removeEventListener('mouseup',this._mouseUpListener);
document.removeEventListener('paste',this._pasteListener);
this._keyDownListener = null;
this._keyUpListener = null;
this._mouseDownListener = null;
this._mouseUpListener = null;
this._pasteListener = null;
};
MapDecorator._clearSceneFade = function(){
var scene = SceneManager._scene;
scene._fadeDuration = 0;
scene._fadeOpacity = 0;
if(scene.updateColorFilter){
scene.updateColorFilter();
}
};
MapDecorator.setupProcessWindowCommands = function(){
var groups = [];
for(var i=1; i<MapDecorator.procGroupId; i=(i+1)|0){
groups.push(['group:'+i,'グループ:'+i]);
}
groups.push(['afterSupply','自動']);
var commands = [];
for(const group of groups){
commands.push({
name:'置換プロセス:'+group[1],
type:'script',
param:"TRP_MapDecorator.startUserProcessMode('%1',true)".format(group[0])
,key:'',
closeWindow:true,
});
commands.push({
name:'└抽選モード',
type:'script',
param:"TRP_MapDecorator.startUserProcessMode('%1')".format(group[0])
,key:'',
closeWindow:true,
});
}
_Dev.registerToolCommands({
key:'',
id:'decorator:processList',
name:'プロセスリスト',
commands,
});
};
MapDecorator.executeBeforeProcess = function(disableAutoSupply){
if(!disableAutoSupply){
this.processMapCriff();
if(SETTING.autoWallSupply){
this.supplyWalls();
}
if(SETTING.autoCeilingSupply){
this.supplyCeilings();
}
if(SETTING.autoShadowSupply){
this.supplyShadows();
}
if(this.processUserProcessList('afterSupply',null,true)){
_Dev.showTempAlert([
'《自動ユーザープロセスを実行しました!》',
'「Esc→手動プロセス実行→前処理の取り消し」で取消'
]);
}
}
originalData = data.concat();
this.requestRefreshTilemap();
};
//=============================================================================
// Mode / Update
//=============================================================================
MapDecorator.MODE_GUIDE = {};
MapDecorator.setMode = function(mode,modeData=null){
if(this._mode === mode)return;
Input.clear();
var lastMode = this._mode;
if(lastMode){
this.endMode();
}
this.modeData = modeData;
this.modeUICache = {};
this.tryReleaseTonnerSprite();
this.clearShowingPalette();
this.cantShowMenu = false;
this.cantScroll = false;
this.showParamEditor(mode);
TRP_CORE.changeMouseCursor(this.CURSOR_BITMAP[mode]);
if(mode==='paintFloor'||mode==='locateObject'){
this._lastModes.length = 0;
}
if(![null,'zMap','zMapError','wallIdx','mapObjectCollision','objectPalette','userProcess','roomSelect',
'objctSelect','objectGrouping',
'playerMove','tilesetEdit'].contains(lastMode))
{
this._lastModes.push(lastMode);
}
if(['objectGrouping','objectSelect','playerMove','tilesetEdit'].contains(mode)){
this.cantShowMenu = true;
}
this._mode = mode;
//refreshGuideText
var refreshGuide = 'refreshGuide'+TRP_CORE.capitalize(mode);
if(this[refreshGuide]){
this[refreshGuide]();
}else{
var guide = MapDecorator.MODE_GUIDE[mode]||null;
_Dev.showText('modeGuide',guide);
}
var setModeFunc = 'setMode'+TRP_CORE.capitalize(mode);
if(this[setModeFunc]){
this[setModeFunc]();
}
};
MapDecorator.endMode = function(){
if(!this._mode)return;
var endHandler = 'endMode'+TRP_CORE.capitalize(this._mode);
if(this[endHandler]){
this[endHandler]();
}
if(this.showingObjOutline){
this.removeObjectsOutline();
}
this._mode = null;
this.hideParamEditor();
};
MapDecorator.restoreMode = function(noSaveState=false){
var mode = this._lastModes.pop();
if(!mode)return;
this.endMode();
this.setMode(mode);
if(!noSaveState){
this.saveState('モード終了');
}
};
MapDecorator.CURSOR_BITMAP = {};
(()=>{
var iconIds = parameters.cursorIcons ? parameters.cursorIcons.split(',') : [217,246,129,142];
if(!iconIds)return;
var iconSet = ImageManager.loadSystem('IconSet');
var w = 24;
var h = 24;
iconSet.addLoadListener(()=>{
for(var i=0; i<4; i=(i+1)|0){
var iconId = Number(iconIds[i]);
if(!iconId)continue;
var mode;
if(i===0)mode = 'paintFloor';
else if(i===1)mode = 'manualPaint';
else if(i===2)mode = 'locateObject';
else mode = 'manualLocate';
var bitmap = new Bitmap(w,h);
var pw = ImageManager.iconWidth;
var ph = ImageManager.iconHeight;
var sx = (iconId % 16) * pw;
var sy = Math.floor(iconId / 16) * ph;
var tw = w-4;
var th = h-4;
var tx = w-tw;
var ty = h-th;
TRP_CORE.bltImage(bitmap,iconSet,sx,sy,pw,ph,tx,ty,tw,th);
var ctx = bitmap._context;
ctx.save();
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(w/2,0);
ctx.lineTo(0,h/2);
ctx.lineTo(0,0);
ctx.closePath();
ctx.strokeStyle = 'white';
ctx.lineWidth = 2;
ctx.fillStyle = 'rgb(50,50,50)';
ctx.fill();
ctx.stroke();
ctx.restore();
bitmap._canvas.toBlob(function(mode,blob){
var url = URL.createObjectURL(blob);;
MapDecorator.CURSOR_BITMAP[mode] = 'url("'+url+'"),auto';
// URL.revokeObjectURL(url)
}.bind(this,mode), 'image/png');
}
});
})();
MapDecorator.onPaste = function(e){
if(this.paramEditor && this.paramEditor.active){
this.onPasteParamEditor(e);
}
};
MapDecorator.onKeyControl = false;
MapDecorator.onKeyMeta = false;
MapDecorator.onKeyAlt = false;
MapDecorator.onKeyDown = function(event){
if(event.key==='Alt'){
this.onKeyAlt = true;
TRP_CORE.changeMouseCursor('move');
}else if(event.key==='Meta'){
this.onKeyMeta = true;
}else if(event.key==='Control'){
this.onKeyControl = true;
}
if(!event.ctrlKey){
this.onKeyControl = false;
}
if(this.onKeyMeta && event.key==='1'){
this.devTest();
}
if(_Dev.showingToolsWindow)return false;
if(this._pickingColor){
return this.onKeyDownPickingColor(event);
}
var exUIActive = false;
if(this.showingPalette){
exUIActive = true;
this.onKeyDownPalette(event);
}
if(this.paramEditor && this.paramEditor.active){
this.onKeyDownParamEditor(event);
return;
}
if(this.onKeyAlt)return;
if(!exUIActive){
if(MapObject && !this.showingObjOutline){
if(event.key==='Control' && !$dataTrpMapObjects.some(obj=>obj&&obj._devOutlineFilter)){
this.setObjectsOutline();
}
}
if(event.code === 'Space'){
//paramEditor
this.tryActivateParamEditor();
}else if(event.metaKey || event.ctrlKey){
if(event.key === 't'){
if(MapObject){
this.tryAnalyzeOtherTilesetObjects();
}
return true;
}else if(event.key.toLowerCase() === 's'){
if(this.isSaveEnabled()){
this.processSave(event.shiftKey);
}else{
SoundManager.playBuzzer();
}
return true;
}else if(event.key.toLowerCase() === 'z'){
if(event.shiftKey){
this.tryRedo();
}else{
this.tryUndo();
}
return true;
}
}
}
var command = this._mode ? 'onKeyDown'+TRP_CORE.capitalize(this._mode) : null;
if(command && this[command]){
this[command](event);
return true;
}
};
MapDecorator.isSaveEnabled = function(){
if(this.showingPalette)return false;
switch(this._mode){
case 'roomSelect':
case 'zMap':
case 'zMapError':
case 'objectSelect':
case 'objectGrouping':
return false;
default:
return true;
}
};
MapDecorator.processSave = function(parallaxSave=false){
if(parallaxSave && !TRP_CORE.isMapMockEnabled()){
SoundManager.playBuzzer();
return;
}
//save mapObject
if(MapObject){
var noLink = parallaxSave;
this.saveMapObjectData(noLink);
}
if(parallaxSave){
this.saveAsParallaxMock();
}else{
_Dev.saveMapFile();
}
};
MapDecorator.restoreFromBackup = function(){
_Dev.restoreFromBackup(()=>{
this.reloadMapData(true);
});
}
MapDecorator.roomIdxOfTouchInput = function(){
var tx = TouchInput.x;
var ty = TouchInput.y;
var dx = Math.floor($gameMap._displayX*tileW + tx*SETTING.mapDispRange);
var dy = Math.floor($gameMap._displayY*tileH + ty*SETTING.mapDispRange);
var x = Math.floor(dx/tileW);
var y = Math.floor(dy/tileH);
var idx = x+y*width;
return idxOfRoom(idx);
};
MapDecorator.mouseScrolling = null;
MapDecorator.onMouseDown = function(event){
if(_Dev.showingToolsWindow)return;
if(this._pickingColor)return;
if(this.paramEditor && this.paramEditor.active)return;
var tx = Graphics.pageToCanvasX(event.pageX);
var ty = Graphics.pageToCanvasY(event.pageY);
if(this.onKeyAlt){
//scrolling
this.mouseScrolling = {tx,ty,spdX:0,spdY:0,spdXArr:[],spdYArr:[]};
return;
}
var dx = Math.floor($gameMap._displayX*tileW + tx*SETTING.mapDispRange);
var dy = Math.floor($gameMap._displayY*tileH + ty*SETTING.mapDispRange);
var x = Math.floor(dx/tileW);
var y = Math.floor(dy/tileH);
dx -= x*tileW;
dy -= y*tileH;
var idx = x+y*width;
var roomId = idxOfRoom(idx);
var name = null;
if(event.button===0)name = 'Left';
else if(event.button===1)name = 'Middle';
else if(event.button===2)name = 'Right';
var command = this._mode ? ('onMouseDown'+name+TRP_CORE.capitalize(this._mode)) : null;
if(!command || !this[command])return;
this[command](event,roomId,x,y,tx,ty,dx,dy);
};
MapDecorator.onMouseUp = function(event){
var tx = Graphics.pageToCanvasX(event.pageX);
var ty = Graphics.pageToCanvasY(event.pageY);
if(event.button!==0)return;
if(this.modeData && this.modeData.onDraggingLocateObj){
this.modeData.onDraggingLocateObj = null;
if(this.draggingGrid){
this.draggingGrid.visible = false;
}
}
this.disableLastStateOverwritable();
if(this.showingPalette){
this.onMouseUpLeftShowingPalette(event,tx,ty);
}
var command = this._mode ? ('onMouseUp'+TRP_CORE.capitalize(this._mode)) : null;
if(!command || !this[command])return;
var dx = Math.floor($gameMap._displayX*tileW + tx*SETTING.mapDispRange);
var dy = Math.floor($gameMap._displayY*tileH + ty*SETTING.mapDispRange);
var x = Math.floor(dx/tileW);
var y = Math.floor(dy/tileH);
dx -= x*tileW;
dy -= y*tileH;
var idx = x+y*width;
var roomId = idxOfRoom(idx);
this[command](event,roomId,x,y,tx,ty,dx,dy);
};
MapDecorator.tryCallOnMousePress = function(){
var tx = TouchInput.x;
var ty = TouchInput.y;
if(this.showingPalette){
this.onMousePressPalette(tx,ty);
return;
}
var command = this._mode ? 'onMousePress'+TRP_CORE.capitalize(this._mode) : null;
if(!command || !this[command])return;
var dx = Math.floor($gameMap._displayX*tileW + tx*SETTING.mapDispRange);
var dy = Math.floor($gameMap._displayY*tileH + ty*SETTING.mapDispRange);
var x = Math.floor(dx/tileW);
var y = Math.floor(dy/tileH);
dx -= x*tileW;
dy -= y*tileH;
// var x = Math.floor($gameMap._displayX+tx/48*SETTING.mapDispRange);
// var y = Math.floor($gameMap._displayY+ty/48*SETTING.mapDispRange);
var idx = x+y*width;
var roomId = idxOfRoom(idx);
this[command](null,roomId,x,y,tx,ty,dx,dy);
}
MapDecorator.updateList = [];
MapDecorator.update = function(){
_Dev.updateTexts();
if(this._pickingColor){
this.updateColorPicker();
return;
}
if(this.paramEditor && this.paramEditor.active){
this.paramEditor.update();
if(TouchInput.isCancelled()
|| (TouchInput.isTriggered() && this.paramEditor.notTouching)
){
this.tryDeactivateParamEditor();
}
return;
}
if(this.draggingGrid && this.draggingGrid.visible){
this.updateDraggingGrid();
}
if(this.mouseScrolling){
this.updateMouseScrolling();
}
this.updateWheel();
/* update input
===================================*/
if(Input._latestButton){
var updateInput = this._mode ? "updateInput"+TRP_CORE.capitalize(this._mode) : null;
if(updateInput && this[updateInput] && this[updateInput]()){
//mode input
}else if(Input.isTriggered('cancel')){
if(!this.cantShowMenu){
this.showMenu();
}
}else if(this.updateScroll()){
//scrolled
}
}
/* update main
===================================*/
var command = 'update'+TRP_CORE.capitalize(this._mode);
if(this[command])this[command]();
/* mouse press
===================================*/
if(TouchInput.isPressed() && !this.mouseScrolling){
this.tryCallOnMousePress();
}
/* main mode update
===================================*/
var command = this._mode ? "update"+TRP_CORE.capitalize(this._mode) : null;
if(command && this[command]){
this[command]();
}
/* extra registered update objects
===================================*/
for(var i=MapDecorator.updateList.length-1; i>=0; i=(i-1)|0){
MapDecorator.updateList[i].update();
}
/* update trpMapObjects
===================================*/
if(MapObject){
SceneManager._scene._spriteset.updateTrpMapObjects();
$dataTrpMapObjects.forEach(obj=>{
if(obj.sprite)obj.sprite.update();
});
}
};
MapDecorator.wheelThreshold = 4;
MapDecorator.updateWheel = function(){
var value = TouchInput.wheelY;
if(!value)return;
var command = 'onWheelValueChange'+TRP_CORE.capitalize(this._mode);
if(this.showingPalette){
this.onWheelValueChangePalette(value);
}else if(this[command]){
this[command](value);
}
var idx = Math.floor(value/this.wheelThreshold);
if(idx){
var command = 'onWheelIdxChange'+TRP_CORE.capitalize(this._mode);
if(this.showingPalette){
// this.onWheelIdxChangePalette(idx);
}else if(this[command]){
this[command](idx);
}
}
};
/* menu
===================================*/
MapDecorator.cantShowMenu = false;
MapDecorator.showMenu = function(){
_Dev.showToolsWindowWithId('decorator:main');
SoundManager.playCancel();
};
(()=>{
//register main menu
var commands = [];
/* category:display analyze values
===================================*/
commands.push({
name:'解析値の表示',
type:'window',
param:'decorator:show'
,key:'',
closeWindow:true,
});
var analyzeCommands = [{
name:'Z値マップの表示',
type:'script',
param:'TRP_MapDecorator.showZMap();'
,key:'',
closeWindow:true,
},{
name:'壁IndexMapの表示',
type:'script',
param:'TRP_MapDecorator.showWallIdxMap();'
,key:'',
closeWindow:true,
}];
if(MapObject){
analyzeCommands.push({
name:'スプライトオブジェ衝突判定',
type:'script',
param:'TRP_MapDecorator.showMapObjectCollisions();'
,key:'',
closeWindow:true,
});
}
_Dev.registerToolCommands({
key:'',
id:'decorator:show',
name:'メインメニュー',
commands:analyzeCommands
});
commands.push({
name:'移動テスト',
type:'script',
param:'TRP_MapDecorator.setMode("playerMove");'
,key:'',
closeWindow:true,
});
//selectRoomTarget
commands.push({
name:'編集対象の部屋を指定',
type:'script',
param:'TRP_MapDecorator.startRoomSelect()'
,key:'',
closeWindow:true,
});
/* category:manual process
===================================*/
commands.push({
name:'手動プロセス実行',
type:'window',
param:'decorator:manual'
,key:'',
closeWindow:true,
});
_Dev.registerToolCommands({
key:'',
id:'decorator:manual',
name:'手動プロセス実行',
commands:[{
name:'全処理の取り消し',
type:'script',
param:'TRP_MapDecorator.reloadMapData(true);'
,key:'',
closeWindow:false,
},{
name:'崖の自動処理',
type:'script',
param:`
TRP_MapDecorator.processMapCriff();
TRP_MapDecorator.requestRefreshTilemap();
TRP_MapDecorator.saveState('崖の自動処理');
`
,key:'',
closeWindow:false,
},{
name:'壁の自動補完',
type:'script',
param:`
TRP_MapDecorator.supplyWalls();
TRP_MapDecorator.requestRefreshTilemap();
TRP_MapDecorator.saveState('壁の自動補完');
`
,key:'',
closeWindow:false,
},{
name:'天井の自動補完',
type:'script',
param:`
TRP_MapDecorator.supplyCeilings();
TRP_MapDecorator.requestRefreshTilemap();
TRP_MapDecorator.saveState('天井の自動補完');
`
,key:'',
closeWindow:false,
},{
name:'影の自動補完/+Shift->クリア',
type:'script',
param:`
TRP_MapDecorator.clearShadows();
if(!Input.isPressed("shift")){
TRP_MapDecorator.supplyShadows();
}
TRP_MapDecorator.saveState('影の処理');
`
,key:'',
closeWindow:false,
}]
});
/* category:processList
===================================*/
commands.push({
name:'置換プロセスの手動実行',
type:'window',
param:'decorator:processList'
,key:'',
closeWindow:true,
});
commands.push({
name:'バックアップから復元',
type:'script',
param:'TRP_MapDecorator.restoreFromBackup();'
,key:'',
closeWindow:true,
});
_Dev.registerToolCommands({
key:'',
id:'decorator:main',
name:'メインメニュー',
commands:commands,
});
})();
MapDecorator.reloadMapData = function(noInitProc=false){
var filePath = TRP_CORE.mapFilePath();
var mapData = JSON.parse(_Dev.readFile(filePath));
data.length = 0;
data.push(...(mapData.data));
originalData = data.concat();
SceneManager._scene._spriteset._tilemap._mapData = data;
this.requestRefreshTilemap();
if(!noInitProc){
this.executeInitProcess();
// this.initProc();
// this.analyzeAll();
// if(MapObject){
// this.analyzeMapObjects();
// }
this._restoreMapObjects();
this.restoreMap(true);
}
SoundManager.playLoad();
this.saveState('マップの再読み込み');
};
/* scroll
===================================*/
MapDecorator.updateScroll = function(){
if(this.cantScroll)return;
if(this.onKeyAlt)return;
var shift = Input.isPressed('shift');
if(Input.isPressed('left')){
processKeyScroll(-1,0,shift);
}else if(Input.isPressed('right')){
processKeyScroll(1,0,shift);
}else if(Input.isPressed('down')){
processKeyScroll(0,1,shift);
}else if(Input.isPressed('up')){
processKeyScroll(0,-1,shift);
}
};
function processKeyScroll(dx,dy,shift){
var speed = 16;
var shiftRate = 2;
dx *= shift ? speed*shiftRate : speed;
dy *= shift ? speed*shiftRate : speed;
processScroll(dx,dy);
}
function processScroll(dx,dy){
$gameMap._displayX += dx/tileW;
$gameMap._displayY += dy/tileH;
var dispW = Graphics.width*SETTING.mapDispRange/tileW;
var dispH = Graphics.height*SETTING.mapDispRange/tileH;
var mx = width-dispW;
var my = height-dispH;
if(mx<0)mx=0;
if(my<0)my=0;
$gameMap._displayX = $gameMap._displayX.clamp(0,mx);
$gameMap._displayY = $gameMap._displayY.clamp(0,my);
SceneManager._scene._spriteset.updateTilemap();
};
MapDecorator.tryEndMouseScrolling = function(){
if(!this.mouseScrolling)return;
this.mouseScrolling = null;
};
MapDecorator.updateMouseScrolling = function(){
var reduceRate = 0.7;
var spdNum = 5;
var scrolling = this.mouseScrolling;
var spdXArr = scrolling.spdXArr;
var spdYArr = scrolling.spdYArr;
var dx,dy;
if(TouchInput.isPressed()){
var tx = TouchInput.x;
var ty = TouchInput.y;
dx = scrolling.tx-tx;
dy = scrolling.ty-ty;
spdXArr.push(dx);
spdYArr.push(dy);
if(spdXArr.length>=spdNum)spdXArr.shift();
if(spdYArr.length>=spdNum)spdYArr.shift();
scrolling.tx = tx;
scrolling.ty = ty;
}else{
if(!scrolling.spdX && !scrolling.spdY){
var spdX = 0;
var spdY = 0;
for(var i=spdXArr.length-1; i>=0; i=(i-1)|0){
spdX += spdXArr[i];
spdY += spdYArr[i];
}
scrolling.spdX = spdX;
scrolling.spdY = spdY;
}
dx = scrolling.spdX = scrolling.spdX*reduceRate;
dy = scrolling.spdY = scrolling.spdY*reduceRate;
if(Math.abs(dx)<0.1 && Math.abs(dy)<0.1){
this.mouseScrolling = null;
}
}
processScroll(dx,dy);
};
//=============================================================================
// Undo/Redo
//=============================================================================
var maxUndoSize = supplementDefNum(10,parameters.maxUndoSize)*1000*1000;
var undoLogSize = 0;
MapDecorator.saveState = function(name,overwritable=false,forceOverwritable=false){
var procStr = JSON.stringify(proc);
var size = procStr.length;
var editorState = {
mode:this._mode,
lastModes:this._lastModes,
modeData:this.modeData?JSON.stringify(this.modeData):null,
};
var lastLog = TRP_CORE.last(undoLog);
if(overwritable && lastLog && lastLog.overwritable && lastLog.name===name){
undoLogSize -= lastLog.size;
undoLog.pop();
}else{
this.disableLastStateOverwritable();
}
undoLog.push({
forceOverwritable,
overwritable,
name,
procStr,
size,
originalData,
editorState,
});
redoLog.length = 0;
undoLogSize += size;
//truncate undoLogs
while(undoLogSize>maxUndoSize && undoLog.length>1){
var state = undoLog.shift();
undoLogSize -= state.size;
}
if(_Dev.inDev){
// console.log('logSize:%1/%2<%3%>'.format(
// undoLogSize,maxUndoSize,Math.ceil(undoLogSize/maxUndoSize*100)
// ));
}
};
MapDecorator.disableLastStateOverwritable = function(name=null){
var lastLog = TRP_CORE.last(undoLog);
if(!lastLog)return;
if(name){
if(lastLog.name !== name)return;
}else if(lastLog.forceOverwritable){
return;
}
lastLog.forceOverwritable = false;
lastLog.overwritable = false;
};
MapDecorator.tryUndo = function(){
this.disableLastStateOverwritable();
if(undoLog.length<=1){
SoundManager.playBuzzer();
return;
}
var state = undoLog.pop();
redoLog.unshift(state);
undoLogSize -= state.size;
var name = '<< '+state.name;
_Dev.showTempText('undo',name);
SoundManager.playCursor();
//restore last
this._restoreState(state);
};
MapDecorator.tryRedo = function(){
this.disableLastStateOverwritable();
var state = redoLog.shift();
if(!state){
SoundManager.playBuzzer();
return;
}
undoLog.push(state);
undoLogSize += state.size;
var name = '>> '+state.name;
_Dev.showTempText('undo',name);
SoundManager.playCursor();
//restore new
this._restoreState();
};
MapDecorator._restoreState = function(){
var state = TRP_CORE.last(undoLog);
proc = JSON.parse(state.procStr);
originalData = state.originalData;
var editorState = state.editorState;
if(this._mode!==editorState.mode){
this.setMode(editorState.mode);
}
this._lastModes = editorState.lastModes.concat();
this.modeData = editorState.modeData ? JSON.parse(editorState.modeData) : null;
if(MapObject){
this._restoreMapObjects();
}
this.restoreMap(true);
if(MapObject){
MapObject.refreshCollisions();
}
var onStateChange = 'onStateChange'+TRP_CORE.capitalize(this._mode);
if(this[onStateChange])this[onStateChange]();
};
MapDecorator._restoreMapObjects = function(){
var objects = [];
//restore MapObjects
for(const objInfoArr of proc.lastObjInfoArr){
if(!objInfoArr)continue;
for(const objInfo of objInfoArr){
objInfo[1] = this._tryRestoreMapObject(objInfo[1],true);
if(objInfo[1] instanceof MapObject){
objects.push(objInfo[1]);
}
}
}
if(this.modeData){
if(this.modeData.lastLocateMapObj){
this.modeData.lastLocateMapObj = this._tryRestoreMapObject(this.modeData.lastLocateMapObj);
}
if(this.modeData.manualLocateObj){
this.modeData.manualLocateObj = this._tryRestoreMapObject(this.modeData.manualLocateObj);
}
}
//cache notUsed
if(MapObject){
for(const obj of $dataTrpMapObjects){
if(!objects.contains(obj)){
MapObject.cache(obj);
}
}
$dataTrpMapObjects = objects;
}
};
MapDecorator._tryRestoreMapObject = function(srcData,addFlag=false){
if(!srcData
|| Array.isArray(srcData)
|| typeof srcData!=='object'
|| srcData instanceof MapObject
){
return srcData;
}
var target = null;
for(var i=$dataTrpMapObjects.length-1; i>=0; i=(i-1)|0){
var obj = $dataTrpMapObjects[i];
if(obj._uid === srcData._uid){
target = obj;
break;
}
}
if(!target){
target = MapObject.object();
if(addFlag){
MapObject.tryAdd(target,true);
}
}
var dx = srcData.x-target.x;
var dy = srcData.y-target.y;
MapObject.copy(srcData,target,true);
if(!target.bitmap){
target.loadBitmap();
}
target.tryRefreshSpriteState();
if(target.sprite){
target.sprite.x += dx;
target.sprite.y += dy;
}
return target;
};
//=============================================================================
// process ZMap
//=============================================================================
MapDecorator.analyzeFloorZMap = function(){
/* analyze proc.zMap prior by eventSetting
===================================*/
var procSuccess = this.analyzeZMapByEventSettings();
if(!procSuccess)return;
/* analyze left tiles
===================================*/
var validIdxes = [];
for(const idxes of proc.allRoomIdxes){
validIdxes = validIdxes.concat(idxes);
}
var floorBaseIdxes = [];
validIdxes = validIdxes.filter(idx=>{
var tileId = data[idx];
if(!tileId)return false;
if(baseTileIds.contains(baseTileId(tileId))){
floorBaseIdxes.push(idx);
return false;
}
if(Tilemap.isWallSideTile(tileId))return false;
if(this.isWallTile(tileId,idx))return false;
if(this.isCeilingTile(tileId))return false;
return true;
});
for(var pi=0; pi<2; pi=(pi+1)|0){
var idxes = pi===0 ? floorBaseIdxes : validIdxes;
for(const idx of idxes){
if(proc.zMap[idx]!==undefined)continue;
proc.zMap[idx] = 0;
var x = idx%width;
var y = Math.floor(idx/width);
this.processZMap(x,y)
}
}
/* analyze proc.minZ
===================================*/
var length = proc.zMap.length;
proc.minZ = Number.MAX_SAFE_INTEGER;
for(var i=0; i<length; i=(i+1)|0){
var z = proc.zMap[i];
if(z!==undefined){
if(z<proc.minZ){
proc.minZ = z;
}
}
}
/* adjust proc.minZ to zero
===================================*/
proc.maxZ = 0;
for(var i=0; i<length; i=(i+1)|0){
var z = proc.zMap[i];
if(z!==undefined){
proc.zMap[i] -= proc.minZ;
proc.maxZ = Math.max(proc.maxZ,proc.zMap[i]);
if(SETTING.writeZ_Region){
data[zRegion+i] = (proc.zMap[i]+1)*10;
}
}
}
proc.minZ = 0;
proc.floorLevelZMap = proc.zMap.concat();
};
MapDecorator.analyzeZMapByEventSettings = function(){
var events = $dataMap.events;
var eventIdxes = [];
for(const event of events){
if(!event)continue;
var image = event.pages[0].image;
if(image.characterName !== MapDecorator.INFO_CHARACTER_Z_NAME)continue;
var col = 3*(image.characterIndex%4)+image.pattern;
var row = 4*Math.floor(image.characterIndex/4)+(image.direction/2-1);
var eventZ = col+row*12;
if(eventZ>=36){
eventZ -= 35;
eventZ *= -1;
}
var eIdx = event.x+event.y*width;
eventIdxes.push(eIdx);
proc.zMap[eIdx] = eventZ;
}
for(const idx of eventIdxes){
var ex = idx%width;
var ey = Math.floor(idx/width);
this.processZMap(ex,ey);
}
return true;
};
MapDecorator.processZMap = function(sx,sy){
var sIdx = sx+sy*width;
var sTileId = baseTileId(data[sIdx]);
if(!sTileId)return;
var sz = proc.zMap[sIdx];
var next = [sIdx];
var current = [];
while(next.length){
var temp = current;
temp.length = 0;
current = next;
next = temp;
if(current.length>1){
//sort by z
current.sort((idxA,idxB)=>{
return (proc.zMap[idxA]||0) - (proc.zMap[idxB]||0);
});
}
for(const idx of current){
var baseZ = proc.zMap[idx];
var tileId = baseTileId(data[idx]);
var x = idx%width;
var y = Math.floor(idx/width);
/* set same floor z
===================================*/
var criffBeginIdxes = [];
this.analyzeNeighbors(x,y,(nx,ny,ox,oy,positions,checkedIdxes)=>{
var nIdx = nx+ny*width;
if(idx===nIdx)return true;
var nId = baseTileId(data[nIdx]);
if(!this.isSameNeighborZTiles(nId,tileId)){
//save criffBeginIdxes
if(criffWallBaseIds.contains(nId)){
if(proc.zMap[nIdx]!==undefined)return false;
if(nx!==ox){
if(checkedIdxes){
TRP_CORE.remove(checkedIdxes,nIdx);
}
}else{
var zSign = ny>oy ? -1 : 1;
TRP_CORE.uniquePush(
criffBeginIdxes,
zSign * nIdx
);
}
}
return false;
}
//same floor tile > neighbor ok
proc.zMap[nIdx] = baseZ;
return true;
});
/* process criff
===================================*/
for(const criffIdx of criffBeginIdxes){
var zSign = criffIdx > 0 ? 1 : -1;
var nIdx = Math.abs(criffIdx);
//criff start
var z = baseZ+zSign*0.5;
proc.zMap[nIdx] = z;
for(;;){
nIdx -= zSign*width;
if(nIdx<0 || nIdx>=zLayerSize)break;
var nId = baseTileId(data[nIdx]);
if(!nId)break;
if(criffWallBaseIds.contains(nId)){
//criff continue
}else{
//found higher or lower floor
if(proc.zMap[nIdx]===undefined){
next.push(nIdx);
proc.zMap[nIdx] = z+0.5*zSign;
}
break;
}
z += zSign;
proc.zMap[nIdx] = z;
}
}
}
}
};
/* helper
===================================*/
MapDecorator.isSameNeighborZTiles = function(tileId1,tileId2){
if(tileId1===tileId2)return true;
//both baseTile (different baseFloor)
if(baseTileIds.contains(tileId1) && baseTileIds.contains(tileId2))return true;
return false;
};
/* proc.zMap mode
===================================*/
MapDecorator._tonnerSprite = null;
MapDecorator.showZMap = function(errorMode){
this.setMode(errorMode ? 'zMapError' : 'zMap');
};
MapDecorator.setModeZMapError = function(){
this.setModeZMapCommon();
};
MapDecorator.setModeZMap = function(){
this.setModeZMapCommon();
};
MapDecorator.setModeZMapCommon = function(){
var positions = [];
var colorMin = 'rgb(0,255,0)';
//color setting [min,max];
var base = 50;
var red = [base,255];
var green = [base,base];
var blue = [255,base];
var alpha = 0.8;
var colorZMin = proc.minZ;
var colorZMax = proc.maxZ;
var texts = [];
var colors = [];
for(var i=proc.zMap.length-1; i>=0; i=(i-1)|0){
var z = proc.zMap[i];
var text = z;
var color;
if(z===undefined)continue;
if(z===Number.MAX_SAFE_INTEGER){
text = '∞';
color = 'rgba(0,0,0,0)';
}else{
var r = red[0] + z/colorZMax * (red[1]-red[0]);
var g = green[0] + z/colorZMax * (green[1]-green[0]);
var b = blue[0] + z/colorZMax * (blue[1]-blue[0]);
color = 'rgb(%1,%2,%3,%4)'.format(r,g,b,alpha);
}
positions.push(i);
texts.push(text);
colors.push(color);
}
this.tonnerTiles(positions,texts,colors);
};
MapDecorator.tonnerTiles = function(positions,texts,color,tonnerTiles,drawText){
var sprite = _Dev.tonnerTiles(positions,false,color,texts,tonnerTiles,drawText);
if(!sprite){
this.tryReleaseTonnerSprite();
return;
}
MapDecorator._tonnerSprite = sprite;
TRP_CORE.uniquePush(this.updateList,sprite);
sprite.update()
}
MapDecorator.MODE_GUIDE.zMap = [
'【Zマップ確認モード】',
'左クリック:確認モード終了'
];
MapDecorator.MODE_GUIDE.zMapError = [
'【Zマップエラー】',
'Z値が衝突しないようにイベント設定・崖の高さを調整してください。'
];
MapDecorator.restoreModeByMouse = function(){
this.restoreMode();
SoundManager.playCancel();
}
MapDecorator.updateInputToCheckRestoreMode = function(){
if(Input.isTriggered('ok')){
this.restoreMode();
SoundManager.playCancel();
return true;
}
return false;
}
MapDecorator.tryReleaseTonnerSprite = function(){
var sprite = this._tonnerSprite;
if(sprite){
if(sprite.parent){
sprite.parent.removeChild(sprite);
}
TRP_CORE.remove(this.updateList,sprite);
}
this._tonnerSprite = null;
};
MapDecorator.onMouseDownRightZMap = MapDecorator.restoreModeByMouse;
MapDecorator.updateInputZMap = MapDecorator.updateInputToCheckRestoreMode;
//=============================================================================
// processCriff
//=============================================================================
MapDecorator.processMapCriff = function(){
var length = allInfo.length;
for(var i=0; i<length; i=(i+1)|0){
this.changeBaseInfo(allInfo[i]);
if(!info.criffTopBaseId)continue;
this.processMapCriffWithInfo(info);
}
this.requestRefreshTilemap();
};
MapDecorator.processMapCriffWithInfo = function(info){
var newData = data.concat();
for(var idx=0; idx<zLayerSize; idx=(idx+1)|0){
var tileId = baseTileId(data[idx]);
if(!tileId)continue;
var z = proc.zMap[idx];
if(info.criffTopAllIds.contains(tileId)){
this.processCriffTop(newData,idx,tileId,z);
}else if(tileId===info.criffWallBaseId && !proc.wallIdxes.contains(idx)){
this.processCriffWall(newData,idx,tileId,z);
}
}
this.replaceCriffTopTiles(newData);
/* apply data
===================================*/
data.length = 0;
Array.prototype.push.apply(data,newData);
newData = null;
};
MapDecorator.processCriffTop = function(newData,idx,tileId,z){
var nf = TRP_CORE.packValues([],0,10);
nf[5] = 1;
var noSupplyBack = this.analyzeCriffTopNeighborFlags(nf,idx,tileId,z);
tileId = connectAutoTile(tileId,nf);
if(!noSupplyBack && SETTING.supplyUpperCriffTopBack && !nf[8]){
/* supply upper criff top back
===================================*/
newData[zAcc+idx] = tileId;
this.supplyBackTile(idx,newData,true);
}else{
newData[idx] = tileId;
}
if(Tilemap.getAutotileShape(tileId)){
proc.criffIdxes.push(idx);
proc.criffTopIdxes.push(idx);
if(
(nf[2]?0:1)+(nf[4]?0:1)+(nf[6]?0:1)+(nf[8]?0:1)>=SETTING.criffTopObjForbiddenSideNum && SETTING.criffTopObjForbiddenSideNum>0
){
proc.objForbiddenIdxes.push(idx);
}
}
};
MapDecorator.analyzeCriffTopNeighborFlags = function(nf,idx,tileId,z){
//return needs supplyBack
var noSupplyBack = false;
for(var ni=1; ni<=9; ni=(ni+1)|0){
//check flag set
if(nf[ni])continue;
if(ni===5){
nf[ni] = 1;
continue;
}
var neighbor = idxForNeighborDir(idx,ni);
if(neighbor<0){
//outside -> connect
nf[ni] = 1;
continue;
}
var neighborId = baseTileId(data[neighbor]);
var neighborZ = !neighborId ? Number.MAX_SAFE_INTEGER : proc.zMap[neighbor];
var y = Math.floor(idx/width)
if(!neighborId){
if(SETTING.noWall){
nf[ni] = 0;
noSupplyBack = true;
continue;
}
if(ni!==2&&ni!==8){
//side
var h = 0;
for(var dy=0; ; dy=(dy+1)|0){
if(y+dy>=height)break;
var tidx = neighbor+dy*width;
if(data[tidx]){
neighborZ = dy + proc.zMap[tidx]-1;
break;
}
}
}
}
if(criffWallBaseIds.contains(neighborId) || proc.wallIdxes.contains(neighborId)){
nf[ni] = neighborZ>z ? 1 : 0;
continue;
}
if(tileId==neighborId){
nf[ni] = 1;
}else{
nf[ni] = neighborZ>=z ? 1 : 0;
}
}
return noSupplyBack;
}
MapDecorator.processCriffWall = function(newData,idx,tileId,z){
proc.criffIdxes.push(idx);
proc.criffWallIdxes.push(idx);
proc.objForbiddenIdxes.push(idx);
//auto shape
var s = 0;
for(var di=0; di<4; di=(di+1)|0){
var dir = (di+1)*2;
var nIdx = idxForNeighborDir(idx,dir);
var nId = data[nIdx];
var nz = proc.zMap[nIdx];
var connect = false;
if(!nId){
if(nIdx<0){
connect = true;
}else if(dir===2 && z<1){
//wall bottom
connect = false;
}else{
connect = true;
}
}else if(dir===4 || dir===6){
//side
connect = nz>=z;
}else if(dir===2 && nz>z+1 && z===0.5){
//z=0.5 & lower criff top
connect = false;
}else if(!Tilemap.isAutotile(nId)){
connect = false;
}else{
nId -= Tilemap.getAutotileShape(nId);
if(nz>z){
//check left or right
if(nIdx%width>0&&nz-1<proc.zMap[nIdx-1]){
//left is lower > maybe bottom
connect = false;
}else if(nIdx%width<width-1&&nz-1<proc.zMap[nIdx+1]){
//right is lower > maybe bottom
connect = false;
}else{
connect = true;
}
}else {
connect = nId===info.criffWallBaseId
}
}
if(!connect){
var powIdx = DIR_SHAPE_POW[dir];
s += Math.pow(2,powIdx);
}
}
newData[idx] = tileId+s;
};
var DIR_SHAPE_POW = [0,0,3,0,0,0,2,0,1];
MapDecorator.replaceCriffTopTiles = function(newData){
for(var idx=0; idx<zLayerSize; idx=(idx+1)|0){
for(var z=0; z<2; z=(z+1)|0){
var zIdx = z*zLayerSize+idx;
var tileId = baseTileId(newData[zIdx]);
if(info.criffTopAllIds.contains(tileId)){
var shape = newData[zIdx]-tileId;
if(shape===0){
newData[zIdx] = info.floorBaseId;
}else{
newData[zIdx] = info.criffTopBaseId+shape;
}
}
}
}
};
//=============================================================================
// Supply Walls
//=============================================================================
MapDecorator.analyzeWallIdxes = function(){
/* <proc.wallIdxMap>
* -1:empty
* 0~:wall
* max:floor
===================================*/
for(var i=0; i<zLayerSize; i=(i+1)|0){
if(proc.wallIdxMap[i]!==undefined)continue;
proc.wallIdxMap[i] = -1;
var x = i%width;
var y = Math.floor(i/width);
if(y>=height-1){
//map bottom
continue;
}
var tileId = data[i];
var lowerIdx = i+width;
var lowerId = lowerIdx<zLayerSize ? data[lowerIdx] : 0;
var lowerFloorZ = proc.zMap[i+width]||0;
var upperIdx = i-width;
var upperId = upperIdx>=0 ? data[upperIdx] : 0;
if(tileId){
if(this.isWallTile(tileId,i)){
//already wall set
// -> will process from top
if(this.isWallTile(upperId,upperIdx))continue;
//supply proc.wallIdxes
var dy = 0;
for(; i+dy*width<zLayerSize; dy=(dy+1)|0){
var cIdx = i+dy*width;
var cTile = data[cIdx];
if(dy>0 && !this.isWallTile(cTile,cIdx))break;
proc.wallIdxMap[cIdx] = dy;
proc.wallIdxes.push(cIdx);
proc.zMap[cIdx] = lowerFloorZ+dy+0.5;
}
//set proc.zMap from bottom
var wallH = dy;
lowerFloorZ = proc.zMap[i+wallH*width]||0;
for(var dy=0; dy<wallH; dy=(dy+1)|0){
proc.zMap[i+dy*width] = lowerFloorZ + (wallH-dy-0.5);
}
}else if(this.isCeilingTile(tileId)){
//ceiling
proc.wallIdxMap[i] = -1;
}else{
//floor
proc.wallIdxMap[i] = Number.MAX_SAFE_INTEGER;
}
continue;
}
//check needs supplyWalls
if(!SETTING.autoWallSupply)continue;
//check lower ground
if(!this.isGroundTile(lowerId,lowerIdx))continue;
var roomId = proc.roomIdxMapForUserProc[lowerIdx];
var baseSetting = this.baseFloorInfoWithTile(tileId);
if(!baseSetting.wallTileIds){
baseSetting = allInfo[0];
}
if(!baseSetting.wallTileIds || !baseSetting.wallTileIds.length){
continue;
}
var wallH = baseSetting.wallTileIds ? baseSetting.wallTileIds.length : 0;
//arrange total height
if(SETTING.arrangeTotalHeight){
wallH = proc.maxZ+wallH-lowerFloorZ;
}
//set idx to wall top ceiling
var idx = i-wallH*width;
//set idx to wall top
idx += width;
for(var dy=0; dy<wallH; dy=(dy+1)|0,idx+=width){
if(idx<0)continue;
if(proc.wallIdxMap[idx]>-1)continue;
var tileId = data[idx];
if(tileId)continue;
proc.wallIdxMap[idx] = dy;
proc.wallIdxes.push(idx);
proc.zMap[idx] = lowerFloorZ+(wallH-dy-0.5);
if(roomId>=0 && proc.roomIdxMapForUserProc[idx]<0){
proc.roomIdxMapForUserProc[idx] = roomId;
}
}
}
};
MapDecorator.isWallTile = function(tileId,idxForCheckNonRegisterWall=-1){
if(SETTING.noWall)return false;
if(idxForCheckNonRegisterWall>=0){
//check nonRegisterWall
if(!Tilemap.isWallSideTile(tileId))return false;
return this.checkWallTopCeilingOrEmpty(idxForCheckNonRegisterWall-width);
}else{
if(allWallIds.contains(baseTileId(tileId)))return true;
return false;
}
};
MapDecorator.checkWallTopCeilingOrEmpty = function(idx){
if(idx<0)return true;
var tileId = data[idx];
if(!tileId)return true;
if(this.isCeilingTile(tileId))return true;
if(Tilemap.isWallSideTile(tileId)){
return this.checkWallTopCeilingOrEmpty(idx-width);
}else{
return false;
}
};
MapDecorator.isCeilingTile = function(tileId){
if(!tileId && SETTING.autoCeilingSupplyWithEmpty){
return true;
}
return allCeilingIds.contains(baseTileId(tileId));
};
MapDecorator.isGroundTile = function(tileId,idx){
return tileId && !this.isWallTile(tileId,idx) && !this.isCeilingTile(tileId);
};
MapDecorator.baseFloorInfoWithTile = function(tileId,allowFailure=false){
tileId = baseTileId(tileId);
for(const info of allInfo){
if(info.floorBaseId===tileId)return info;
if(info.ceilingBaseId===tileId)return info;
if(info.wallTileIds && info.wallTileIds.contains(tileId))return info;
if(info.waterBaseId===tileId)return info;
if(info.waterAccIds && info.waterAccIds.contains(tileId))return info;
if(info.floorVariationIds && info.floorVariationIds.contains(tileId))return info;
if(info.accSettings[tileId])return info;
}
return allowFailure ? null : allInfo[0];
};
/* wallIdx mode
===================================*/
MapDecorator.showWallIdxMap = function(){
this.setMode('wallIdx');
};
MapDecorator.setModeWallIdx = function(){
var positions = [];
var autoRemove = false;
var color = 'rgba(0,0,255,0.2)';
var texts = [];
for(var i=zLayerSize-1; i>=0; i=(i-1)|0){
var wallIdx = proc.wallIdxMap[i];
if(wallIdx===Number.MAX_SAFE_INTEGER)continue;
positions.push(i);
texts.push(wallIdx);
}
this.tonnerTiles(positions,texts,color);
};
MapDecorator.MODE_GUIDE.wallIdx = [
'【壁IndexMap確認モード】',
'左クリック:確認モード終了'
];
MapDecorator.onMouseDownLeftWallIdx = MapDecorator.restoreModeByMouse;
MapDecorator.updateInputWallIdx = MapDecorator.updateInputToCheckRestoreMode;
/* supplyWalls
===================================*/
MapDecorator.supplyWalls = function(){
var floorWallIdx = Number.MAX_SAFE_INTEGER;
for(var idx=0; idx<zLayerSize; idx=(idx+1)|0){
if(invalidIdxes && invalidIdxes.contains(idx))continue;
//proc from floor top
if(proc.wallIdxMap[idx]!==floorWallIdx)continue;
//check upper wall
var upperIdx = idx-width;
var wallIdx = proc.wallIdxMap[upperIdx];
if(upperIdx<0)continue;
if(wallIdx===-1)continue;
if(wallIdx===floorWallIdx)continue;
//prepare wallTileIds
var tileId = data[idx];
var baseInfo = this.baseFloorInfoWithTile(tileId);
if(!baseInfo.wallTileIds)baseInfo = allInfo[0];
if(!baseInfo.wallTileIds)continue;
var wallTileIds = baseInfo.wallTileIds;
var baseInfoIdx = allInfo.indexOf(baseInfo);
var defWallH = wallTileIds.length;
//supply wallTiles
var cIdx = upperIdx;
var wallH = wallIdx+1;
for(; cIdx>=0; cIdx=(cIdx-width)|0){
var cTileId = data[cIdx];
if(cTileId)continue;
var wallIdx = proc.wallIdxMap[cIdx];
if(wallIdx===-1)break;
if(wallIdx===floorWallIdx)break;
//adjust wallIdx
if(wallIdx===wallH-1){
wallIdx = defWallH-1;
}else{
wallIdx = wallIdx.clamp(0,defWallH-2);
}
//supply wall tile
cTileId = data[cIdx] = wallTileIds[wallIdx];
//cache baseInfoIdx
proc.idxBaseInfoIdxMap[cIdx] = baseInfoIdx;
}
}
this.connectWallTiles();
};
MapDecorator.connectWallTiles = function(){
for(var wi=0; wi<proc.wallIdxes.length; wi=(wi+1)|0){
this.connectWallTile(proc.wallIdxes[wi]);
}
};
var FLOOR_WALL_IDX = Number.MAX_SAFE_INTEGER
MapDecorator.connectWallTile = function(idx){
//original loc
if(originalData[idx])return;
var tileId = baseTileId(data[idx]);
if(!Tilemap.isAutotile(tileId))return;
var wallIdx = proc.wallIdxMap[idx];
var z = proc.zMap[idx];
data[idx] = this._connectWallTile(idx,tileId,wallIdx,z);
};
MapDecorator._connectWallTile = function(idx,tileId,wallIdx,z){
var x = idx%width;
var y = Math.floor(idx/width);
/* analyze Left/Right close
===================================*/
var leftClose = 0;
var rightClose = 0;
if(x>0 && !(invalidIdxes&&!invalidIdxes.contains(idx-1))){
var neighborWallIdx = proc.wallIdxMap[idx-1];
var neighborZ = proc.zMap[idx-1];
if(neighborWallIdx<Number.MAX_SAFE_INTEGER){
if(wallIdx<neighborWallIdx){
leftClose = 1;
}
}else{
if(z>neighborZ){
leftClose = 1;
}
}
// if(tileId !== baseTileId(data[idx-1])){
// //diffrent kind wall
// // leftClose = 1;
// }
}
if(x<width-1 && !(invalidIdxes&&!invalidIdxes.contains(idx+1))){
var neighborWallIdx = proc.wallIdxMap[idx+1];
var neighborZ = proc.zMap[idx+1];
if(neighborWallIdx<Number.MAX_SAFE_INTEGER){
if(wallIdx<neighborWallIdx){
rightClose = 1;
}
}else{
if(z>neighborZ){
rightClose = 1;
}
}
// if(tileId !== baseTileId(data[idx+1])){
// //diffrent kind wall
// // rightClose = 1;
// }
}
/* analyze Top/Bottom close
===================================*/
var topClose = 0;
var bottomClose = 0;
if(wallIdx===0){
topClose = 1;
}
var lowerIdx = idx+width;
var lowerWallIdx = proc.wallIdxMap[lowerIdx];
if(lowerWallIdx===FLOOR_WALL_IDX){
bottomClose = 1;
}
/* adjust shape
===================================*/
var s = 0;
if(leftClose)s += 1<<0;
if(topClose)s += 1<<1;
if(rightClose)s += 1<<2;
if(bottomClose)s += 1<<3;
return tileId+s;
}
//=============================================================================
// Supply Ceilings
//=============================================================================
MapDecorator.analyzeCeilingIdxes = function(){
//make ceilingIdxes
for(var idx=0; idx<zLayerSize; idx=(idx+1)|0){
//check is floor or wall
var wallIdx = proc.wallIdxMap[idx];
var tileId = data[idx];
if(wallIdx<0){
//empty
if(this.isCeilingTile(tileId)){
TRP_CORE.uniquePush(proc.ceilingIdxes,idx);
proc.zMap[idx] = Number.MAX_SAFE_INTEGER;
}
continue;
}
if(!SETTING.autoCeilingSupply)continue;
var roomId = proc.roomIdxMapForUserProc[idx];
//auto supply
for(var ni=1; ni<10; ni=(ni+1)|0){
if(ni===5)continue;
var nIdx = idxForNeighborDir(idx,ni);
var nWallIdx = proc.wallIdxMap[nIdx];
//check neighbor empty > ceiling
if(nWallIdx === -1){
var firstPush = TRP_CORE.uniquePush(proc.ceilingIdxes,nIdx);
proc.zMap[nIdx] = Number.MAX_SAFE_INTEGER;
if(roomId>=0 && proc.roomIdxMapForUserProc[nIdx]<0){
proc.roomIdxMapForUserProc[nIdx] = roomId;
}
//cache baseInfoIdx
var forceOverWrite = ni===2||ni===4||ni===6||ni===8;
if(forceOverWrite || !firstPush){
var baseInfo = this.baseFloorInfoWithTile(tileId);
if(!baseInfo.ceilingBaseId)baseInfo = allInfo[0];
var baseInfoIdx = allInfo.indexOf(baseInfo);
proc.idxBaseInfoIdxMap[nIdx] = baseInfoIdx;
}
}
};
}
proc.ceilingIdxes.sort((a,b)=>a-b);
};
MapDecorator.supplyCeilings = function(){
var nf = TRP_CORE.packValues([],0,10);
nf[5] = 1;
for(const idx of proc.ceilingIdxes){
if(invalidIdxes && invalidIdxes.contains(idx))continue;
//check already set
if(originalData[idx])continue;
//supply tile id
var tileId = baseTileId(data[idx]);
if(!tileId){
var baseInfoIdx = proc.idxBaseInfoIdxMap[idx];
var baseInfo = allInfo[baseInfoIdx||0];
tileId = baseInfo.ceilingBaseId;
if(!tileId)continue;
data[idx] = tileId;
}
//check neighbor connection
for(var ni=1; ni<10; ni=(ni+1)|0){
if(ni===5)continue;
var nIdx = idxForNeighborDir(idx,ni);
if(proc.ceilingIdxes.contains(nIdx)){
nf[ni] = 1;
}else{
if(SETTING.isEmptySpaceCeiling){
if(nIdx<0 || proc.wallIdxMap[nIdx]<0 || (invalidIdxes&&invalidIdxes.contains(nIdx))){
nf[ni] = 1;
}else{
nf[ni] = 0;
}
}else{
nf[ni] = 0;
}
}
}
//auto connect
data[idx] = connectAutoTile(tileId,nf)
}
};
MapDecorator.checkCeilingCorrect = function(){
var failureIdxes = [];
var texts = [];
for(const idx of proc.wallIdxes){
var upperIdx = idx-width;
if(upperIdx<0)continue;
if(proc.wallIdxes.contains(upperIdx))continue;
if(proc.ceilingIdxes.contains(upperIdx))continue;
var x = upperIdx%width;
var y = Math.floor(upperIdx/width);
var alert = '天井設置に失敗<x:%1,y:%2>'.format(x,y);
_Dev.showText(null,alert,'red');
failureIdxes.push(upperIdx);
texts.push('x');
}
if(failureIdxes.length){
var color = 'rgba(255,0,0,0.8)';
this.tonnerTiles(failureIdxes,texts,color);
$gamePlayer.locate(x,y);
SceneManager._scene._spriteset.update();
}
};
//=============================================================================
// supply BackTiles
//=============================================================================
MapDecorator.supplyBackTile = function(idx,dstData=data){
var baseIdx = proc.idxBaseInfoIdxMap[idx];
var info = allInfo[baseIdx]||allInfo[0];
//search supply sample directions
var maxZ = proc.minZ-1;
var bestDirs = [];
var z = proc.zMap[idx];
for(var dir=2; dir<=8; dir=(dir+2)|0){
var nz = this.zForSupplyBackTile(idx,z,dir,info);
if(nz>maxZ){
maxZ = nz;
bestDirs.length = 0;
bestDirs.push(dir);
}else if(nz===maxZ){
bestDirs.push(dir);
}
}
maxZ = Math.max(maxZ,proc.minZ);
//prior side dirs
if(TRP_CORE.remove(bestDirs,2))bestDirs.push(2);
if(TRP_CORE.remove(bestDirs,8))bestDirs.push(8);
this.supplyBackTilesWithDirs(idx,bestDirs,maxZ,info,dstData);
};
MapDecorator.zForSupplyBackTile = function(idx,z,dir,info){
var nIdx = idxForNeighborDir(idx,dir);
//check in map
if(nIdx<0)return Number.MIN_SAFE_INTEGER;
//check not ceiling
var nz = proc.zMap[nIdx];
if(nz===Number.MAX_SAFE_INTEGER){
return Number.MIN_SAFE_INTEGER;
}
//check z lower
if(nz>=z){
return Number.MIN_SAFE_INTEGER;
}
//check not sequencial wall
if(dir===2 && proc.ceilingIdxes.contains(idx) && proc.wallIdxes.contains(nIdx)){
//ceiling ~ wall -> sequencial
return Number.MIN_SAFE_INTEGER;
}
if(proc.wallIdxes.contains(idx)){
if((dir===2 && proc.wallIdxMap[idx]+1===proc.wallIdxMap[nIdx])
|| (dir===8 && proc.wallIdxMap[nIdx]+1===proc.wallIdxMap[idx])
){
return Number.MIN_SAFE_INTEGER;
}
}
return nz;
};
MapDecorator.supplyBackTilesWithDirs = function(idx,bestDirs,z,info,dstData){
var bestTileId = -1;
var isCriffTop = false;
for(const dir of bestDirs){
var nIdx = idxForNeighborDir(idx,dir);
var tileId = data[nIdx];
if(proc.wallIdxes.contains(nIdx) ||
(proc.criffWallIdxes&&proc.criffWallIdxes.contains(nIdx))
){
//supply wallTile
if(proc.wallIdxes.contains(nIdx)){
tileId = info.wallTileIds ? info.wallTileIds[0] : tielId;
}
if(Tilemap.isAutotile(tileId)){
var wallIdx = proc.wallIdxMap[nIdx];
var supplyWall = true;
if(dir===2){
wallIdx -= 1;
}else if(dir===8){
if(nIdx%width>0&&z-1<proc.zMap[nIdx-1]){
//bottom -> supply left floor
tileId = baseTileId(data[nIdx-1]);
supplyWall = false;
}else if(nIdx%width<width-1&&z-1<proc.zMap[nIdx+1]){
tileId = baseTileId(data[nIdx+1]);
supplyWall = false;
}else{
wallIdx += 1;
}
}
if(supplyWall){
tileId = this._connectWallTile(idx,baseTileId(tileId),wallIdx,z);
}
}
dstData[idx] = tileId;
return;
}else{
/* try supply criffTop tile
===================================*/
if(proc.criffTopIdxes.contains(nIdx)){
var nf = TRP_CORE.packValues([],0,10);
nf[5] = 1;
for(var di=bestDirs.length-1; di>=0; di=(di-1)|0){
nf[bestDirs[di]] = 1;
}
var noSupplyBack = this.analyzeCriffTopNeighborFlags(nf,idx,baseTileId(tileId),z);
tileId = connectAutoTile(baseTileId(tileId),nf);
//apply backTile
bestTileId = tileId
isCriffTop = true;
break;
}else if(tileId){
bestTileId = bestTileId>=0 ? bestTileId : (baseTileId(tileId)||-1)
}
}
}
//supply normal floor
if(bestTileId<0){
bestTileId = info.floorBaseId;
}
//apply backTile
dstData[idx] = bestTileId;
//register idxes
TRP_CORE.uniquePush(proc.floorSuppliedIdxes,idx);
proc.floorLevelZMap[idx] = z;
if(!isCriffTop && !proc.wallIdxes.contains(idx) && !proc.criffWallIdxes.contains(idx)){
var roomId = idxOfRoom(nIdx);
if(roomId>=0){
TRP_CORE.uniquePush(proc.allRoomIdxes[roomId],idx);
TRP_CORE.uniquePush(proc.allBaseIdxes[roomId],idx);
proc.roomIdxMapForUserProc[idx] = roomId;
}
}
//supply shadow
this.supplyShadow(idx,dstData);
};
//=============================================================================
// Supply Shadows
//=============================================================================
MapDecorator.supplyShadows = function(){
for(var idx=0; idx<zLayerSize; idx=(idx+1)|0){
if(invalidIdxes && invalidIdxes.contains(idx))continue;
this.supplyShadow(idx);
}
this.requestRefreshTilemap();
};
MapDecorator.supplyShadow = function(idx,dstData=data){
var wallIdx = proc.wallIdxMap[idx];
if(wallIdx<0 && !proc.floorSuppliedIdxes.contains(idx)){
//ceiling or empty -> noShadow
dstData[idx+zShadow] = 0;
return
}
//skip wall shadow setting
if(SETTING.noShadowOnWall){
if(wallIdx>=0 && wallIdx!==Number.MAX_SAFE_INTEGER){
return
}else if(proc.criffWallIdxes.contains(idx)){
return
}
}
/* compare zValue to left & leftUp tile
===================================*/
var z = proc.floorLevelZMap[idx];
if(proc.floorLevelZMap[idx] !== proc.zMap[idx]){
// if(!data[idx+zAcc] &&!data[idx+zObj1]&!data[idx+zObj2]){
// //accLayer is not upperTile -> original z
// z = proc.zMap[idx];
if((data[idx+zAcc]&&data[idx+zAcc]<1024)
|| (data[idx+zObj1]&&data[idx+zObj1]<1024)
|| (data[idx+zObj2]&&data[idx+zObj2]<1024)
){
//exists higher tile -> usefloorLevel
}else{
//accLayer is not upperTile -> original z
z = proc.zMap[idx];
}
}
var leftZ = proc.zMap[idx-1];
var leftUpZ = proc.zMap[idx-1-width];
if(idx%width===0){
if(SETTING.autoCeilingSupply){
leftZ = Number.MAX_SAFE_INTEGER;
leftUpZ = Number.MAX_SAFE_INTEGER;
}else{
return;
}
}else if(idx-width-1<0){
leftUpZ = Number.MAX_SAFE_INTEGER;
}
if(z<leftZ && z<leftUpZ){
dstData[idx+zShadow] = 5;
}
}
MapDecorator.clearShadows = function(){
for(var i=0; i<zLayerSize; i=(i+1)|0){
data[i+zShadow] = originalData[i+zShadow] = 0;
}
this.requestRefreshTilemap();
};
//=============================================================================
// Room Select
//=============================================================================
MapDecorator.analyzeRooms = function(){
var checked = [];
var separatorRegionId = Number(parameters.roomSeparatorRegionId)||-1;
var objForbiddenRegionId = Number(parameters.objForbiddenRegionId)||-1;
TRP_CORE.packValues(proc.roomIdxMapForUserProc,-1,zLayerSize);
for(var idx=0; idx<zLayerSize; idx=(idx+1)|0){
if(checked.contains(idx))continue;
if(isEmptyTile(idx))continue;
if(invalidIdxes && invalidIdxes.contains(idx))continue;
var roomIdxes = [];
var roomId = proc.allRoomIdxes.length;
proc.allRoomIdxes.push(roomIdxes);
var x = idx%width;
var y = Math.floor(idx/width);
analyzeNeighbors(x,y,(nx,ny)=>{
var nIdx = nx+ny*width;
if(checked.contains(nIdx))return false;
if(invalidIdxes && invalidIdxes.contains(idx))return false;
checked.push(nIdx);
if(isEmptyTile(nIdx))return false;
roomIdxes.push(nIdx);
proc.roomIdxMapForUserProc[nIdx] = roomId;
var regionId = data[nIdx+zRegion];
if(regionId===separatorRegionId){
return false;
}else if(regionId===objForbiddenRegionId){
TRP_CORE.uniquePush(proc.objForbiddenIdxes,nIdx);
}
return true;
});
}
/* baseIdxes
===================================*/
proc.allBaseIdxes = [];
for(const roomIdxes of proc.allRoomIdxes){
var roomBaseIdxes = [];
proc.allBaseIdxes.push(roomBaseIdxes);
for(var btIdx=baseTileIds.length-1; btIdx>=0; btIdx=(btIdx-1)|0){
roomBaseIdxes.push([]);
}
for(const idx of roomIdxes){
var tileId = baseTileId(data[idx]);
if(!tileId)continue;
var baseIdx = baseTileIds.indexOf(tileId);
if(baseIdx>=0){
roomBaseIdxes[baseIdx].push(idx);
continue;
}
for(var baseIdx=allInfo.length-1; baseIdx>=0; baseIdx=(baseIdx-1)|0){
var tempInfo = allInfo[baseIdx];
if(tempInfo.criffTopAllIds.contains(tileId)){
roomBaseIdxes[baseIdx].push(idx);
break;
}
}
}
};
if(proc.allRoomIdxes.length===0){
_Dev.throwError('部屋が検出できませんでした。');
}
};
//=============================================================================
// MODE: roomSelect
//=============================================================================
MapDecorator.MODE_GUIDE.roomSelect = [
'【編集対象の部屋を選択】',
'左クリ:部屋を選択',
'右クリ/Esc:キャンセル',
'※完成マップに部屋を追加する際に使用',
'※部屋を完全に境界リージョンIDで囲っておくこと',
];
MapDecorator.startRoomSelect = function(){
if(proc.allRoomIdxes.length<=1){
SoundManager.playBuzzer();
confirm('部屋が1つしかないか、すでに編集対象の部屋を指定済みです。')
return;
}
this.setMode('roomSelect');
};
var invalidIdxes = null;
MapDecorator.onMouseDownLeftRoomSelect = function(event,roomId,x,y,tx,ty){
if(roomId<0){
SoundManager.playBuzzer();
return;
}
//search invalidIdxes by regionId
var separatorRegionId = Number(parameters.roomSeparatorRegionId)||-1;
var idxes = proc.allRoomIdxes[roomId];
for(var i=idxes.length-1; i>=0; i=(i-1)|0){
var idx = idxes[i];
var sx = idx%width;
var sy = Math.floor(idx/width);
analyzeNeighbors(sx,sy,(nx,ny,ox,oy)=>{
var nIdx = nx+ny*width;
if(idx!==nIdx && idxes.contains(nIdx))return false;
var oRegionId = data[ox+oy*width+zRegion];
if(oRegionId===separatorRegionId){
//origin:separator -> only allow neighbor:sepearator
if(data[nIdx+zRegion]!==separatorRegionId){
return false;
}
}
idxes.push(nIdx);
return true;
});
}
invalidIdxes = [];
for(var i=0; i<zLayerSize; i=(i+1)|0){
if(!idxes.contains(i)){
invalidIdxes.push(i);
}
}
SoundManager.playOk();
this.restoreMode();
this.initProc();
if(confirm('自動補完をやり直しますか?')){
this.reloadMapData(true);
// this.analyzeAll();
// this.executeBeforeProcess();
}
this.saveState('編集対象の部屋を指定')
};
MapDecorator.onMouseDownRightRoomSelect = function(event,roomId,x,y,tx,ty){
SoundManager.playCancel();
this.restoreMode();
};
MapDecorator.updateInputRoomSelect = function(){
if(Input.isTriggered('cancel')){
SoundManager.playCancel();
this.restoreMode();
return true;
}else{
return false;
}
};
//=============================================================================
// MODE: paintFloor
//=============================================================================
MapDecorator.MODE_GUIDE.paintFloor = [
'【床装飾ペイントモード】',
'左クリ:再抽選',
'右クリ@部屋:確定!',
'Vキー@部屋:装飾種類をロック',
'Wキー@部屋:水場ロック',
'Ctrl+右クリ:装飾種類パレット',
];
MapDecorator.onKeyDownPaintFloor = function(event){
if(event.key==='v'){
var i = this.roomIdxOfTouchInput();
//pattern lock
if(i<0){
SoundManager.playBuzzer();
return;
}
if(proc.lockedFloorVariations[i]){
proc.lockedFloorVariations[i] = null;
var text = '装飾種類をロック解除';
showInfoText(text);
this.saveState(text);
SoundManager.playCancel();
}else{
proc.lockedFloorVariations[i] = proc.lastFloorVariations[i];
var text = '装飾種類をロック';
showInfoText(text+'');
this.saveState(text);
SoundManager.playOk();
}
}else if(event.key==='w'){
var i = this.roomIdxOfTouchInput();
//water lock
if(i<0){
SoundManager.playBuzzer();
return;
}
if(proc.lockedFloorPaintRoomIds.contains(i)){
this.tryShowObjectPalette();
}else if(proc.lockedWaterRoomIds.contains(i)){
TRP_CORE.remove(proc.lockedWaterRoomIds,i);
var text = '水場ロック解除';
showInfoText(text);
this.saveState(text);
SoundManager.playCancel();
}else{
proc.lockedWaterRoomIds.push(i);
var text = '水場ロック!';
showInfoText(text);
this.saveState(text);
SoundManager.playOk();
}
}
};
MapDecorator.onMouseDownLeftPaintFloor = function(event,i,x,y,tx,ty,dx,dy){
if(this.onKeyControl){
if(this.tryStartManualLocateMode(event,i,x,y,tx,ty,dx,dy)){
//manual loc
}else{
this.tryStartManualPaintMode(event,i,x,y,tx,ty);
}
}else if(Input.isPressed('shift')){
// //pattern lock
// if(i<0){
// SoundManager.playBuzzer();
// return;
// }
// if(proc.lockedFloorVariations[i]){
// proc.lockedFloorVariations[i] = null;
// var text = '装飾種類をロック解除';
// showInfoText(text);
// this.saveState(text);
// SoundManager.playCancel();
// }else{
// proc.lockedFloorVariations[i] = proc.lastFloorVariations[i];
// var text = '装飾種類をロック';
// showInfoText(text+'');
// this.saveState(text);
// SoundManager.playOk();
// }
}else{
//repaint
this.paintFloors();
this.saveState('床装飾の抽選');
SoundManager.playCursor();
}
};
MapDecorator.onMouseDownMiddlePaintFloor = function(event,i,x,y,tx,ty){
};
MapDecorator.onMouseDownRightPaintFloor = function(event,i,x,y,tx,ty,dx,dy){
if(i<0){
SoundManager.playBuzzer();
return;
}
if(this.onKeyControl){
this.startFloorVariationPaletteMode(event,i,x,y,tx,ty,dx,dy);
// //water lock
// if(i<0){
// SoundManager.playBuzzer();
// return;
// }
// if(proc.lockedFloorPaintRoomIds.contains(i)){
// this.tryShowObjectPalette();
// }else if(proc.lockedWaterRoomIds.contains(i)){
// TRP_CORE.remove(proc.lockedWaterRoomIds,i);
// var text = '水場ロック解除';
// showInfoText(text);
// this.saveState(text);
// SoundManager.playCancel();
// }else{
// proc.lockedWaterRoomIds.push(i);
// var text = '水場ロック!';
// showInfoText(text);
// this.saveState(text);
// SoundManager.playOk();
// }
}else if(Input.isPressed('shift')){
this.tryUnlockRoomState(i);
}else if(proc.lockedFloorPaintRoomIds.contains(i)){
SoundManager.playBuzzer();
// this.tryUnlockRoomState(i);
}else{
//paint lock
TRP_CORE.uniquePush(proc.lockedFloorPaintRoomIds,i);
TRP_CORE.uniquePush(proc.lockedWaterRoomIds,i);
this.setMode('locateObject');
var text = '装飾ロック!';
showInfoText(text);
this.saveState(text);
SoundManager.playOk();
}
};
MapDecorator.tryUnlockRoomState = function(i){
if(proc.lockedObjRoomIds.contains(i)){
TRP_CORE.remove(proc.lockedObjRoomIds,i);
this.clearLastObjects(i);
this.setMode('locateObject')
this.restoreMap();
var text = 'オブジェロック解除';
showInfoText(text);
this.saveState(text);
SoundManager.playCancel();
}else if(proc.lockedFloorPaintRoomIds.contains(i)){
TRP_CORE.remove(proc.lockedFloorPaintRoomIds,i);
TRP_CORE.remove(proc.lockedWaterRoomIds,i);
proc.lastFloorPaintInfoArr[i] = null;
proc.lastWaterInfoArr[i] = null;
this.clearLastObjects(i);
SoundManager.playCancel();
this.setMode('paintFloor');
this.restoreMap();
var text = '装飾ロック解除';
showInfoText(text);
this.saveState(text);
}else{
SoundManager.playBuzzer();
}
}
MapDecorator.paintFloors = function(){
//clear not locked paint info
var length = proc.allRoomIdxes.length;
for(var i=0; i<length; i=(i+1)|0){
if(!proc.lockedFloorPaintRoomIds.contains(i)){
proc.lastFloorPaintInfoArr[i] = [];
proc.autoConnectRequestIdxes[i] = [];
}
if(!proc.lockedWaterRoomIds.contains(i)){
proc.lastWaterInfoArr[i] = [];
proc.waterAccIdxes[i] = [];
}
};
//restore map
if(proc.oncePaintFloor){
this.restoreMap();
}
//paint floors
proc.waterIdxes = [];
proc.oncePaintFloor = true;
var length = proc.allRoomIdxes.length;
for(var i=0; i<length; i=(i+1)|0){
if(proc.lockedFloorPaintRoomIds.contains(i))continue;
var validIdxes = proc.allRoomIdxes[i];
if(proc.criffIdxes){
validIdxes = validIdxes.concat();
TRP_CORE.removeArray(validIdxes,proc.criffIdxes);
}
TRP_CORE.removeArray(validIdxes,proc.noAccIdxes);
for(const baseInfo of allInfo){
this.changeBaseInfo(baseInfo);
this.paintFloorWithRoom(validIdxes,i);
}
}
};
MapDecorator.paintFloorWithRoom = function(validIdxes,roomId){
/* analyze manual water locate
===================================*/
var waterInfo = proc.lastWaterInfoArr[roomId];
var manualWaterLocate = this.analyzeManualWaterLocate(validIdxes,roomId);
/* analyze floorIdxes
===================================*/
var targetIds = [info.floorBaseId];
var floorIdxes = validIdxes.filter(idx=>{
var tileId = data[idx];
if(!tileId)return false;
tileId = baseTileId(tileId)
return targetIds.contains(tileId);
});
/* draw paint WaterTiles
===================================*/
if(!manualWaterLocate){
this._paintWaterFloors(validIdxes,roomId,floorIdxes);
}
/* draw floor paint variations
===================================*/
this._paintFloors(validIdxes,roomId,floorIdxes);
/* adjust autotile shape
===================================*/
for(var i=floorIdxes.length-1; i>=0; i=(i-1)|0){
var idx = floorIdxes[i];
var tileId = baseTileId(data[idx]);
if(tileId && !info.criffTopAllIds.contains(tileId)){
data[idx] = connectAutoTileWithIdx(idx);
}
idx += zAcc;
data[idx] = connectAutoTileWithIdx(idx);
}
for(const idx of proc.autoConnectRequestIdxes[roomId]){
data[idx] = connectAutoTileWithIdx(idx);
}
/* save paint cache
===================================*/
var paintInfo = proc.lastFloorPaintInfoArr[roomId];
for(const idx of validIdxes){
paintInfo.push(idx);
paintInfo.push(data[idx]);
paintInfo.push(data[idx+zAcc]);
}
this.requestRefreshTilemap();
};
MapDecorator.requestRefreshTilemap = function(){
SceneManager._scene._spriteset._tilemap._needsRepaint = true;
};
MapDecorator.analyzeManualWaterLocate = function(validIdxes,roomId){
var waterInfo = proc.lastWaterInfoArr[roomId];
var hasManualLocate = false;
if(waterInfo.length){
waterInfo = null;
}
for(const idx of validIdxes){
var tileId = baseTileId(data[idx]);
if(tileId === info.waterBaseId){
hasManualLocate = true;
if(!waterInfo){
break;
}
waterInfo.push(idx);
waterInfo.push(data[idx]);
waterInfo.push(data[idx+zAcc]);
}
}
return hasManualLocate;
};
MapDecorator._paintWaterFloors = function(validIdxes,roomId,floorIdxes){
if(!info.waterBaseId)return;
var waterInfo = proc.lastWaterInfoArr[roomId];
/* try locate
===================================*/
var waterLocate = false;
if(proc.lockedFloorVariations[roomId]
&& proc.lockedFloorVariations[roomId][info.floorBaseId]
&& proc.lockedFloorVariations[roomId][info.floorBaseId].contains(MapDecorator.VARIATION_FLAG_WATER)
){
waterLocate = true;
}else if(SETTING.waterLocateMode<0){
waterLocate = Math.random()<=SETTING.waterLocateRate;
}else{
waterLocate = SETTING.waterLocateMode>0;
}
if(proc.lockedWaterRoomIds.contains(roomId)){
//locate on restoreMap
}else if(waterLocate){
//paint water base
var variationIds = [info.waterBaseId];
var waterPaintRate = SETTING.waterPaintRate;
waterPaintRate *= TRP_CORE.randomRateWithRange(SETTING.rateRange);
waterPaintRate = waterPaintRate.clamp(0,1);
var paintNum = Math.ceil(floorIdxes.length*waterPaintRate);
var chankMin = SETTING.waterChankMin;
var chankMax = SETTING.waterChankMax;
var validWaterIdxes = validIdxes.concat();
TRP_CORE.removeArray(validWaterIdxes,proc.passIdxes);
var waterIdxes = this.paintChank(variationIds,paintNum,chankMin,chankMax,validWaterIdxes);
proc.waterIdxes = proc.waterIdxes.concat(waterIdxes);
//paint water accessory
variationIds = info.waterAccIds;
if(variationIds && variationIds.length){
var waterAccPaintRate = SETTING.waterAccPaintRate;
waterAccPaintRate *= TRP_CORE.randomRateWithRange(SETTING.rateRange);
waterAccPaintRate = waterAccPaintRate.clamp(0,1);
paintNum = Math.ceil(waterIdxes.length*waterAccPaintRate);
chankMin = SETTING.waterPaintChankMin;
chankMax = SETTING.waterPaintChankMax;
var waterAccIdxes = this.paintChank(variationIds,paintNum,chankMin,chankMax,waterIdxes,info.waterBaseId);
if(waterAccIdxes){
proc.waterAccIdxes[roomId] = proc.waterAccIdxes[roomId].concat(waterAccIdxes);
}
}
//supply B-ceiling to water
var bCeilingWaters = [];
for(const idx of waterIdxes){
for(var d=0; d<3; d=(d+1)|0){
var dir = d===0 ? width : (d===1 ? -1 : 1);
if(proc.ceilingIdxes.contains(idx+dir)){
if(allFloorLevelTileIds.contains(baseTileId(data[idx+dir])) && data[idx+dir+zObj1]){
data[idx+dir] = info.waterBaseId;
bCeilingWaters.push(idx+dir);
}
}
}
}
waterIdxes = waterIdxes.concat(bCeilingWaters);
bCeilingWaters = null;
/* adjust autotile shape
===================================*/
TRP_CORE.removeArray(floorIdxes,waterIdxes);
for(var i=waterIdxes.length-1; i>=0; i=(i-1)|0){
var idx = waterIdxes[i];
var connectEmpty = 2;
data[idx] = connectAutoTileWithIdx(idx,connectEmpty);
data[idx+zAcc] = connectAutoTileWithIdx(idx+zAcc);
waterInfo.push(idx);
waterInfo.push(data[idx]);
waterInfo.push(data[idx+zAcc]);
}
}
};
MapDecorator._paintFloors = function(validIdxes,roomId,floorIdxes){
var baseId = info.floorBaseId;
var paintRate = SETTING.floorPaintRate;
paintRate *= TRP_CORE.randomRateWithRange(SETTING.rateRange);
paintRate = paintRate.clamp(0,1);
var variationIds;
floorIdxes = floorIdxes.concat();
TRP_CORE.removeArray(floorIdxes,proc.waterIdxes);
var paintNum = Math.ceil(floorIdxes.length*paintRate);
var chankMin = SETTING.floorPaintChankMin;
var chankMax = SETTING.floorPaintChankMax;
//calc variationNum
var variationNum;
if(SETTING.floorPaintPatternNum>=0){
variationNum = SETTING.floorPaintPatternNum;
}else{
variationNum = 1;
for(var pi=2;; pi=(pi+1)|0){
var threshold = SETTING.floorPaintPatternsWithTiles[pi-1];
if(threshold===undefined)break;
if(floorIdxes.length >= threshold){
variationNum = pi;
}else{
break;
}
}
}
var candidates = info.floorVariationIds.concat();
//apply locked variations
var isLocked = proc.lockedFloorVariations[roomId]&&proc.lockedFloorVariations[roomId][info.floorBaseId];
if(isLocked){
variationIds = proc.lockedFloorVariations[roomId][info.floorBaseId];
//process flags
if(variationIds.contains(MapDecorator.VARIATION_FLAG_WATER)
|| variationIds.contains(MapDecorator.VARIATION_FLAG_SUPPLY)
){
variationIds = variationIds.concat();
}
TRP_CORE.remove(variationIds,MapDecorator.VARIATION_FLAG_WATER);
if(TRP_CORE.remove(variationIds,MapDecorator.VARIATION_FLAG_SUPPLY)){
variationNum -= variationIds.length;
TRP_CORE.removeArray(candidates,variationIds);
}else{
variationNum = 0;
}
}else{
variationIds = [];
}
var drawen = false;
for(var i=0; i<variationNum && candidates.length; i=(i+1)|0){
drawen = true;
TRP_CORE.uniquePush(variationIds,TRP_CORE.randomShift(candidates));
}
//add floor fix variation tiles
if(drawen){
if(info.floorFixVariationIds && info.floorFixVariationIds.length){
//adjust draw rate
var chankAve = Math.ceil((chankMin+chankMax)/2);
var srcVariationIds = variationIds.concat();
for(var i=chankAve-1-1; i>=0; i=(i-1)|0){
variationIds = variationIds.concat(srcVariationIds);
}
variationIds = variationIds.concat(info.floorFixVariationIds);
}
proc.lastFloorVariations[roomId] = proc.lastFloorVariations[roomId]||{};
proc.lastFloorVariations[roomId][info.floorBaseId] = variationIds;
}
//paint
var paintedIdxes;
if(variationIds.length>0){
paintedIdxes = this.paintChank(variationIds,paintNum,chankMin,chankMax,floorIdxes);
}else{
paintedIdxes = [];
}
return paintedIdxes;
}
/* helper
===================================*/
MapDecorator.isAccLayerTile = function(tileId){
var kind = Tilemap.getAutotileKind(tileId);
if(Tilemap.isTileA1(tileId)){
return kind>=1&&kind<=3;
}else{
return Math.floor(kind/4)%2===1;
}
};
MapDecorator.paintChank = function(variationIds, paintNum,chankMin,chankMax,idxPool,targetBaseId=info.floorBaseId){
if(!Array.isArray(variationIds)){
_Dev.throwError('invalid variationIds',variationIds);
}
var painted = [];//result
var current = [];
var next = [];
var checked = [];
var dirs = [width,width-1,-1,-1-width,-width,-width+1,1,1+width];
var paintTileId;
var noOverwrap = true;
idxPool = idxPool.concat();
for(var pi=0/*<paintIdx>*/; paintNum>=chankMin; pi=(pi+1)|0){
if(idxPool.length===0)break;
var idx = TRP_CORE.randomShift(idxPool);
if(noOverwrap){
if(baseTileId(data[idx])!==targetBaseId || baseTileId(data[idx+zAcc]))continue;
}else{
if(baseTileId(data[idx])!==targetBaseId && baseTileId(data[idx+zAcc]))continue;
}
//draw paintTileId
TRP_CORE.shuffle(variationIds);
var isAccesory = false;
for(var vi=variationIds.length-1; vi>=0; vi=(vi-1)|0){
paintTileId = variationIds[vi];
if(Tilemap.isAutotile(paintTileId)){
var isAccesory = this.isAccLayerTile(paintTileId);
if(noOverwrap){
break;
}else if(isAccesory){
if(!data[idx+zAcc]){
break;
}
}else{
if(baseTileId(data[idx])===targetBaseId)break;
}
}else{
//simple fix-variation tile
if(baseTileId(data[idx])!==targetBaseId)continue;
if(noOverwrap && data[idx+zAcc])continue;
break;
}
}
painted.push(idx);
//paint if simple fix variation tile
if(!Tilemap.isAutotile(paintTileId)){
data[idx] = paintTileId;
paintNum -= 1;
continue;
}
if(isAccesory){
data[idx+zAcc] = paintTileId;
}else{
data[idx] = paintTileId;
}
checked.length = 0;
current.length = 0;
next.length = 0;
next.push(idx);
//draw chank
var num = chankMin+Math.randomInt(chankMax-chankMin+1);
num = num.clamp(0,paintNum);
while(next.length && num>0){
var temp = TRP_CORE.prepareArray(current);
current = next;
next = temp;
for(const idx of current){
var di0 = 2*Math.randomInt(4);
var baseDi = -1;
for(var di=0; di<8; di=(di+1)|0){
var dirIdx = (di0+di)%8;
if(baseDi<0){
if(dirIdx%2===1){
//opposite
continue
}
}else{
if(dirIdx > baseDi+2){
break;
}
}
var dir = dirs[dirIdx];
var neighbor = idx+dir;
if(checked.contains(neighbor))continue;
checked.push(neighbor);
if(!idxPool.contains(neighbor))continue;
//check already paint with same type tile
if(noOverwrap){
if(baseTileId(data[neighbor])!==targetBaseId || baseTileId(data[neighbor+zAcc]))continue;
if(isAccesory){
data[neighbor+zAcc] = paintTileId;
}else{
data[neighbor] = paintTileId;
}
}else if(!isAccesory){
if(baseTileId(data[neighbor])!==targetBaseId)continue;
data[neighbor] = paintTileId;
}else{//isAccc
if(data[neighbor+zAcc])continue;
data[neighbor+zAcc] = paintTileId;
}
baseDi = di;
next.push(neighbor);
painted.push(neighbor);
num -= 1;
paintNum -= 1;
if(num<=0)break;
}
if(num<=0)break;
}
}
}
return painted;
};
//=============================================================================
// MODE: FloorVariationPalette
//=============================================================================
MapDecorator.MODE_GUIDE.floorVariationPalette = [
'【床装飾種類パレットモード】',
'左クリ:装飾種類のロック/解除',
'右クリ:戻る',
];
MapDecorator.FLOOR_VARIATION_PALETTE_EMPTY_NUM = 5;
MapDecorator.FLOOR_VARIATION_PALETTE_SIZE = 48;
MapDecorator.FLOOR_VARIATION_PALETTE_MARGIN = 12;
MapDecorator.startFloorVariationPaletteMode = function(event,i,x,y,tx,ty,dx,dy){
if(i<0){
SoundManager.playBuzzer();
_Dev.showTempAlert('装飾種類をロックする部屋の上で実行!')
return;
}
this.setMode('floorVariationPalette',{
type:'floorVariationPalette',
roomId:i,
tx,ty,
});
SoundManager.playOk();
};
MapDecorator.setModeFloorVariationPalette = function(){
var roomId = this.modeData.roomId;
proc.lockedFloorVariations[roomId] = proc.lockedFloorVariations[roomId]||{};
var objectsArr = [];
var currentIdsArr = [];
var pageNames = [];
var idx = 0;
for(const _info of allInfo){
var objects = _info.floorVariationIds||null;
if(_info.dummyFloorVariationIds&&_info.dummyFloorVariationIds.length){
objects = objects.concat(_info.dummyFloorVariationIds);
}
pageNames.push('ベース床:%1<tileId=%2>'.format(idx++,_info.floorBaseId))
//supply variation button
var buttons = [
MapDecorator.VARIATION_FLAG_NO_SUPPLY,
MapDecorator.VARIATION_FLAG_WATER,
];
objects = buttons.concat(objects);
objectsArr.push(objects);
var currentIds = proc.lockedFloorVariations[roomId][_info.floorBaseId];
currentIdsArr.push(currentIds||null);
}
//palette setting
var size = MapDecorator.FLOOR_VARIATION_PALETTE_SIZE;
var m = MapDecorator.FLOOR_VARIATION_PALETTE_MARGIN;
var x0Num = MapDecorator.FLOOR_VARIATION_PALETTE_EMPTY_NUM;
//show palette
var pageIdx = 0;
this.showPalette(objectsArr,pageNames,pageIdx,size,m,x0Num,null,currentIdsArr);
};
MapDecorator.updateInputFloorVariationPalette = function(){
return true;
}
MapDecorator.onMouseDownLeftFloorVariationPalette = function(event,i,x,y,tx,ty){
this.onMouseDownLeftPaletteCommon(event,i,x,y,tx,ty);
};
MapDecorator.VARIATION_FLAG_SUPPLY = -1000;
MapDecorator.VARIATION_FLAG_NO_SUPPLY = -1001;
MapDecorator.VARIATION_FLAG_WATER = -1002;
MapDecorator.onMouseDownRightFloorVariationPalette = function(event,i,x,y,tx,ty){
var palette = this.showingPalette;
var objectsArr = palette.objectsArr;
var selectedArr = palette.selected;
var modeData = this.modeData;
var roomId = modeData.roomId;
proc.lockedFloorVariations[roomId] = proc.lockedFloorVariations[roomId]||{};
for(var i=0; i<objectsArr.length; i=(i+1)|0){
var floorBaseId = allInfo[i].floorBaseId;
var objects = objectsArr[i];
var selected = selectedArr[i];
var noSupply = TRP_CORE.remove(selected,0);
var variationIds = selected.map(idx=>{
if(idx===1)return MapDecorator.VARIATION_FLAG_WATER;
return objects[idx];
});
if(!noSupply){
variationIds.unshift(MapDecorator.VARIATION_FLAG_SUPPLY);
}
if(variationIds.length===0){
variationIds = null;
}
proc.lockedFloorVariations[roomId][floorBaseId] = variationIds;
}
this.restoreMode();
showInfoText('装飾種類ロックを変更!',modeData.tx,modeData.ty);
SoundManager.playOk();
};
//=============================================================================
// MODE: ManualPaint
//=============================================================================
MapDecorator.MODE_GUIDE.manualPaint = [
'【手動ペイントモード】',
'左クリ:塗り/消去',
'右クリ:終了',
'Ctrl+左クリ:タイル選択(スポイト)',
'Shift+右クリ:チャンク消去',
'Ctrl+右クリ:パレット表示',
];
MapDecorator.initManualPaintData = function(){
var modeData = this.modeData = {};
modeData.type = 'manualPaint';
modeData.paintTileId = 0;
modeData.paintAccLayer = false;
modeData.paintWater = false;
modeData.lastPaintIdx = -1;
modeData.paintErasing = false;
}
MapDecorator.tryStartManualPaintMode = function(event,roomId,x,y,tx,ty){
var paintTileId = 0;
var paintAccLayer = false;
var obj = null;
var idx = x+y*width;
for(var z=1; z>=0; z=(z-1)|0){
var tileId = baseTileId(data[z*zLayerSize+idx]);
if(!tileId)continue;
if(baseTileIds.contains(tileId))continue;
if(this.isWallTile(tileId))continue;
if(this.isCeilingTile(tileId))continue;
if(z<=1){
paintTileId = tileId;
paintAccLayer = z===1;
}
break;
}
if(!paintTileId){
SoundManager.playBuzzer();
return;
}
this.startManualPaintModeWithTileId(paintTileId);
var modeData = this.modeData;
modeData.paintAccLayer = paintAccLayer;
modeData.lastPaintIdx = idx;
modeData.paintWater = modeData.paintWater || (proc.waterIdxes&&proc.waterIdxes.contains(idx));
SoundManager.playCursor();
};
MapDecorator.startManualPaintModeWithTileId = function(tileId){
this.setMode('manualPaint');
this.initManualPaintData();
var modeData = this.modeData;
modeData.paintTileId = tileId;
modeData.paintWater = Tilemap.isWaterTile(tileId)||Tilemap.isTileA1(tileId);
modeData.paintAccLayer = this.isAccLayerTile(tileId);
this.saveState('手動ペイント開始');
};
MapDecorator.onMousePressManualPaint = function(event,roomId,x,y,tx,ty){
if(!this.modeData)return;
if(!this.modeData.paintTileId)return;
if(roomId<0)return;
if(this.onKeyControl){
}else if(Input.isPressed('shift')){
}else{
this.processManualPaint(...arguments);
}
};
MapDecorator.onMouseDownLeftManualPaint = function(event,roomId,x,y,tx,ty){
if(roomId<0)return;
if(this.onKeyControl){
this.tryStartManualPaintMode(event,roomId,x,y,tx,ty);
}else{
this.processManualPaint(event,roomId,x,y,tx,ty);
}
};
MapDecorator.onMouseDownRightManualPaint = function(event,roomId,x,y,tx,ty){
if(Input.isPressed('shift')){
this.processManualPaintChankDelete(event,roomId,x,y,tx,ty);
}else if(this.onKeyControl){
this.startManualPaintPaletteMode();
}else{
SoundManager.playCancel();
this.restoreMode();
}
};
MapDecorator.processManualPaint = function(event,roomId,x,y,tx,ty){
if(!this.modeData)return;
var idx = x+y*width;
if(this.modeData.lastPaintIdx===idx)return;
var startPainting = this.modeData.lastPaintIdx<0;
this.modeData.lastPaintIdx = idx;
var isAccLayer = this.modeData.paintAccLayer;
var isWater = this.modeData.paintWater;
var targetWater = Tilemap.isWaterTile(data[idx]) || (proc.waterIdxes&&proc.waterIdxes.contains(idx))
var tileId = this.modeData.paintTileId;
var baseInfoIdx = proc.idxBaseInfoIdxMap[idx]||0;
var baseInfo = allInfo[baseInfoIdx];
/* check target tile or idx valid
===================================*/
var failure = false;
if(proc.wallIdxes.contains(idx)){
failure = true;
}else if(isWater!==targetWater && tileId!==baseInfo.waterBaseId){
failure = true;
}else if(isAccLayer&&proc.criffTopIdxes.contains(idx)){
//acc && criffTop
if(criffTopIds.contains(baseTileId(data[zAcc+idx]))){
//accLayer:criff -> fail
failure = true;
}else{
//accLayer:free -> ok
}
}else if(proc.criffTopIdxes.contains(idx)||proc.criffIdxes.contains(idx)){
failure = true;
}
if(failure){
SoundManager.playBuzzer();
return;
}
/* write tileId
===================================*/
var zIdx = isAccLayer ? zAcc : 0;
var paintId = tileId;
if(baseTileId(data[idx+zIdx])===tileId){
//erase
if(startPainting){
this.modeData.paintErasing = true;
}else if(!this.modeData.paintErasing){
return;
}
paintId = 0;
if(isWater && tileId===baseInfo.waterBaseId){
isWater = false;
}
}else{
if(startPainting){
this.modeData.paintErasing = false;
}else if(this.modeData.paintErasing){
return;
}
}
var idxes = [idx];
var waterWrite = isWater!==targetWater;
this.paintTilesWithIdxes(idxes,isAccLayer,roomId,paintId,isWater,waterWrite)
this.saveState('手動ペイント:塗り',true);
SoundManager.playCursor();
};
MapDecorator.processManualPaintChankDelete = function(event,roomId,x,y,tx,ty){
var idx = x+y*width;
var isAccLayer = this.modeData.paintAccLayer;
this.modeData.lastPaintIdx = idx;
this.modeData.paintErasing = true;
/* write tileId
===================================*/
var zIdx = isAccLayer ? zAcc : 0;
var tileId = this.modeData.paintTileId;
if(!tileId || baseTileId(data[idx+zIdx])!==tileId){
SoundManager.playBuzzer();
return;
}
//search chank idxes
var idxes = this.analyzeNeighbors(x,y,(nx,ny,ox,oy)=>{
if(nx===x&&ny===y)return true;
if(proc.zMap[ox+oy*width]!==proc.zMap[nx+ny*width])return false;
if(idxOfRoom(nx+ny*width)!==roomId)return false;
var nIdx = (isAccLayer?zAcc:0)+nx+ny*width;
var nTileId = data[nIdx];
if(baseTileId(nTileId)!==tileId)return false;
return true;
},true);
if(idxes.length===1){
var idxes = this.analyzeNeighbors(x,y,(nx,ny,ox,oy)=>{
if(nx===x&&ny===y)return true;
if(proc.zMap[ox+oy*width]!==proc.zMap[nx+ny*width])return false;
if(idxOfRoom(nx+ny*width)!==roomId)return false;
var nIdx = (isAccLayer?zAcc:0)+nx+ny*width;
var nTileId = data[nIdx];
if(baseTileId(nTileId)!==tileId)return false;
return true;
},true);
}
var baseInfoIdx = proc.idxBaseInfoIdxMap[idx]||0;
var baseInfo = allInfo[baseInfoIdx];
var isWater = this.modeData.paintWater;
var waterWrite = this.modeData.paintTileId===baseInfo.waterBaseId;
if(waterWrite){
isWater = false;
}
this.paintTilesWithIdxes(idxes,isAccLayer,roomId,0,isWater,waterWrite);
SoundManager.playCursor();
this.saveState('手動ペイント:消し');
};
MapDecorator.updateManualPaint = function(){
if(!this.modeData)return;
if(!TouchInput.isPressed() && !TouchInput.isTriggered()){
this.modeData.lastPaintIdx = -1;
}
};
MapDecorator.paintTilesWithIdxes = function(idxes,isAccLayer,roomId,tileId,isWater=false,waterWrite=false){
var zIdx = isAccLayer ? zAcc : 0;
/* water write
===================================*/
proc.lastFloorPaintInfoArr[roomId] = proc.lastFloorPaintInfoArr[roomId]||[];
proc.lastWaterInfoArr[roomId] = proc.lastWaterInfoArr[roomId]||[]
var paintInfo = proc.lastFloorPaintInfoArr[roomId];
var waterInfo = proc.lastWaterInfoArr[roomId];
var srcInfo = isWater ? paintInfo : waterInfo;
if(waterWrite){
//clear all tile
for(const idx of idxes){
data[idx] = 0;
data[idx+zAcc] = 0;
}
//clear paint info
for(var i=0; i<srcInfo.length; i=(i+3)|0){
if(idxes.contains(srcInfo[i])){
srcInfo.splice(i,3);
i -= 3;
}
}
//remove waterIdxes
if(!isWater){
if(proc.waterIdxes){
TRP_CORE.removeArray(proc.waterIdxes,idxes);
}
if(proc.waterAccIdxes){
TRP_CORE.removeArray(proc.waterAccIdxes,idxes);
}
}
}
/* write data
===================================*/
for(const idx of idxes){
var paintId = tileId;
var baseInfoIdx = proc.idxBaseInfoIdxMap[idx]||0;
var baseInfo = allInfo[baseInfoIdx];
if(zIdx===0 && !tileId){
//clear tile
paintId = isWater ? (baseInfo.waterBaseId||allInfo[0].waterBaseId) : baseInfo.floorBaseId;
}
data[idx+zIdx] = paintId;
if(isWater){
TRP_CORE.uniquePush(proc.waterIdxes,idx);
if(baseInfo.waterBaseId!==paintId){
TRP_CORE.uniquePush(proc.waterAccIdxes,idx);
}
}
}
/* around tiles
===================================*/
//search neighbors
var changedIdxes = idxes.concat();
var dirs8 = [-1+width,width,1+width,-1,1,-1-width,-width,1-width];
for(const idx of idxes){
for(var dir=1; dir<=9; dir=(dir+1)|0){
if(dir===5)continue;
var dIdx = idxForNeighborDir(idx,dir);
if(dIdx<0)continue;
if(changedIdxes.contains(dIdx))continue;
var nId = baseTileId(data[dIdx]);
var nIdAcc = baseTileId(data[dIdx+zAcc]);
if(!nId && !nIdAcc)continue;
if(!criffTopIds.contains(nId)&&(Tilemap.isTileA3(nId)||Tilemap.isTileA4(nId)))continue;
if(!criffTopIds.contains(nIdAcc)&&(Tilemap.isTileA3(nIdAcc)||Tilemap.isTileA4(nIdAcc)))continue;
changedIdxes.push(dIdx);
}
}
//auto connect
for(const idx of changedIdxes){
for(var z=0; z<2; z=(z+1)|0){
var tIdx = idx+z*zLayerSize;
var tileId = baseTileId(data[tIdx]);
if(tileId && Tilemap.isAutotile(tileId) && !criffTopIds.contains(tileId)){
data[tIdx] = connectAutoTileWithIdx(tIdx);
}
}
//once delete paint Info
for(var type=0; type<2; type=(type+1)|0){
var info = type===0 ? waterInfo : paintInfo;
for(var i=0; i<info.length; i=(i+3)|0){
if(info[i]===idx){
info.splice(i,3);
break;
}
}
}
//add to info
var water = Tilemap.isWaterTile(data[idx]) || (proc.waterIdxes&&proc.waterIdxes.contains(idx))
var info = water ? waterInfo : paintInfo
info.push(idx);
info.push(data[idx]);
info.push(data[idx+zAcc]);
}
this.requestRefreshTilemap();
};
//=============================================================================
// MODE: ManualPaintPalette
//=============================================================================
MapDecorator.MODE_GUIDE.manualPaintPalette = [
'【手動ペイントパレットモード】',
'左クリ:タイルの選択',
'右クリ:戻る',
];
MapDecorator.startManualPaintPaletteMode = function(event,i,x,y,tx,ty,dx,dy){
this.setMode('manualPaintPalette');
SoundManager.playOk();
};
MapDecorator.setModeManualPaintPalette = function(){
var objectsArr = [];
var pageNames = [];
var idx = 0;
for(const _info of allInfo){
var objects = [];
objectsArr.push(objects);
pageNames.push('ベース床:%1<tileId=%2>'.format(idx++,_info.floorBaseId))
if(_info.floorVariationIds){
objects.push(..._info.floorVariationIds);
}
if(_info.waterBaseId){
objects.push(_info.waterBaseId);
}
if(_info.waterAccIds && _info.waterAccIds.length){
for(const tileId of _info.waterAccIds){
objects.push([_info.waterBaseId,tileId]);
}
}
}
//palette setting
var size = MapDecorator.FLOOR_VARIATION_PALETTE_SIZE;
var m = MapDecorator.FLOOR_VARIATION_PALETTE_MARGIN;
var x0Num = MapDecorator.FLOOR_VARIATION_PALETTE_EMPTY_NUM;
//show palette
var pageIdx = 0;
this.showPalette(objectsArr,pageNames,pageIdx,size,m,x0Num,obj=>{
if(Array.isArray(obj)){
obj = TRP_CORE.last(obj);
}
this.startManualPaintModeWithTileId(obj);
SoundManager.playCursor();
});
};
MapDecorator.updateInputManualPaintPalette = function(){
return true;
}
MapDecorator.onMouseDownLeftManualPaintPalette = function(event,i,x,y,tx,ty){
this.onMouseDownLeftPaletteCommon(event,i,x,y,tx,ty);
};
MapDecorator.onMouseDownRightManualPaintPalette = function(event,i,x,y,tx,ty){
SoundManager.playCancel();
this.restoreMode();
};
//=============================================================================
// MODE: LocateObject
//=============================================================================
MapDecorator.MODE_GUIDE.locateObject = [
'【オブジェクト配置モード】',
'左クリ:再配置',
'右クリ@部屋:確定!',
'Shift+右クリ@部屋:ロック解除',
'Ctrl+左クリ:オブジェ手動調整<スポイト>',
'Ctrl+右クリ:オブジェクトパレット',
];
if(MapObject){
MapDecorator.MODE_GUIDE.locateObject.push(
'Shift+左クリ:ドットシフト'
);
}
MapDecorator.onMouseDownLeftLocateObject = function(event,i,x,y,tx,ty,dx,dy){
if(this.onKeyControl){
if(this.tryStartManualLocateMode(event,i,x,y,tx,ty,dx,dy)){
return;
}
// if(proc.lastObjInfoArr && proc.lastObjInfoArr[i]){
// SoundManager.playBuzzer();
// }else{
this.tryStartManualPaintMode(event,i,x,y,tx,ty);
// }
}else if(Input.isPressed('shift')){
this.tryDotShiftObjects(i);
}else{
//relocate
this.locateObjects();
SoundManager.playCursor();
this.saveState('オブジェクトの抽選');
}
};
MapDecorator.onMouseDownMiddleLocateObject = function(event,i,x,y,tx,ty){
};
MapDecorator.onMouseDownRightLocateObject = function(event,i,x,y,tx,ty){
if(i<0){
SoundManager.playBuzzer();
return;
}
if(Input.isPressed('shift')){
//try back to paintFloor
this.tryUnlockRoomState(i);
}else if(this.onKeyControl){
this.tryShowObjectPalette();
}else if(proc.lockedObjRoomIds.contains(i)){
SoundManager.playBuzzer();
}else if(!proc.lockedFloorPaintRoomIds.contains(i)){
//not lock floor paint yet
SoundManager.playBuzzer();
}else{
//object lock
TRP_CORE.uniquePush(proc.lockedObjRoomIds,i);
TRP_CORE.uniquePush(proc.lockedFloorPaintRoomIds,i);
TRP_CORE.uniquePush(proc.lockedWaterRoomIds,i);
proc.leftObjIdxesArr[i] = null;
this.setMode('paintFloor');
var text = 'オブジェロック!';
showInfoText(text);
this.saveState(text);
SoundManager.playOk();
}
};
MapDecorator.locateObjects = function(){
//restore map
var length = proc.allRoomIdxes.length;
if(proc.locateObj){
this.restoreMap();
}else{
for(var i=0; i<length; i=(i+1)|0){
if(!proc.lockedObjRoomIds.contains(i)){
proc.lastObjInfoArr[i] = [];
}
}
}
proc.locateObj = true;
//locate objects
for(var i=0; i<length; i=(i+1)|0){
if(proc.lockedObjRoomIds.contains(i))continue;
if(!proc.lockedFloorPaintRoomIds.contains(i))continue;
var validIdxes = proc.allRoomIdxes[i];
var roomId = i;
validIdxes = validIdxes.concat();
TRP_CORE.removeArray(validIdxes,proc.objForbiddenIdxes);
TRP_CORE.removeArray(validIdxes,proc.passIdxes);
proc.leftObjIdxesArr[i] = {};
var baseIdx = 0;
var roomBaseIdxes = proc.allBaseIdxes[i];
for(const baseInfo of allInfo){
this.changeBaseInfo(baseInfo);
var baseIdxes = roomBaseIdxes[baseIdx++].concat();
TRP_CORE.removeArray(baseIdxes,proc.objForbiddenIdxes);
TRP_CORE.removeArray(baseIdxes,proc.passIdxes);
proc.leftObjIdxesArr[i][info.floorBaseId] = {};
this.locateObjectsWithRoom(validIdxes,roomId,baseIdxes);
}
}
};
MapDecorator.locateObjectsWithRoom = function(validIdxes,roomId,baseIdxes){
var types = ['base'];
/* prepare accIdxes
===================================*/
var accIds = info.separateLocateObjAccIds;
var accIdxes = {};
for(const accId of accIds){
accIdxes[accId] = this.prepareAccIdxesForLocateObject(baseIdxes,accId);
types.push(accId);
}
/* prepare waterIdxes
===================================*/
var waterInfoArr = proc.lastWaterInfoArr[roomId];
var waterIdxes = null;
if(waterInfoArr){
waterIdxes = prepareWaterIdxesForLocateObject(baseIdxes,waterInfoArr,proc.waterAccIdxes[roomId]);
types.push('water');
}
/* locate objects
===================================*/
var targetIdxes,rate,objIds,floorBaseId,bigObjIds,bigRate;
var objInfo = [];
var maxObjInfo = objInfo;
var typeLen = types.length;
for(var typeIdx=0; typeIdx<typeLen; typeIdx=(typeIdx+1)|0){
var type = types[typeIdx];
if(type==='base'){
//floor
targetIdxes = baseIdxes;
rate = SETTING.floorObjRate;
bigRate = SETTING.floorBigObjRate;
objIds = info.objIds;
bigObjIds = info.bigObjIds;
floorBaseId = info.floorBaseId;
}else if(type==='water'){
//water
targetIdxes = waterIdxes;
if(!targetIdxes || targetIdxes.length===0)continue;
rate = SETTING.waterObjRate;
bigRate = SETTING.waterBigRate;
objIds = info.waterObjIds;
bigObjIds = info.waterBigObjIds;
floorBaseId = info.waterBaseId;
}else{
//accessory
floorBaseId = Number(type);
targetIdxes = accIdxes[floorBaseId];
var accInfo = info.accSettings[floorBaseId];
rate = SETTING.floorObjRate * accInfo.objRate;
bigRate = SETTING.floorBigObjRate * accInfo.bigObjRate;
objIds = accInfo.objIds;
bigObjIds = accInfo.bigObjIds;
}
var maximizeTryNum = SETTING.maximizeObjRateTryNum||1;
var doMaximize = SETTING.maximizeObjRateTryNum >= 1;
var srcTargetIdxes = targetIdxes;
var minLeftTargetIdxesNum = Number.MAX_SAFE_INTEGER;
var srcObjInfo = objInfo;
var srcBigObjIds = bigObjIds;
var floorLen = targetIdxes.length;
if(!doMaximize){
rate *= TRP_CORE.randomRateWithRange(0.3);
bigRate *= TRP_CORE.randomRateWithRange(0.3);
}
var objNum = TRP_CORE.randomRound(rate*floorLen);
var bigObjNum = TRP_CORE.randomRound(bigRate*floorLen);
if(!objIds || objIds.length===0)objNum = 0;
if(!bigObjIds || bigObjIds.length===0)bigObjNum = 0;
/* for loop try maximize packRate
===================================*/
for(var tryIdx=maximizeTryNum-1; tryIdx>=0; tryIdx=(tryIdx-1)|0){
objInfo = srcObjInfo.concat();
targetIdxes = srcTargetIdxes.concat();
TRP_CORE.shuffle(targetIdxes);
/* locate obj
===================================*/
var idx;
for(var i=objNum-1; i>=0; i=(i-1)|0){
var tileIds = TRP_CORE.random(objIds);
var tileId = tileIds[0];
idx = -1;
if(Tilemap.isTileA5(tileId)){
for(const tempIdx of targetIdxes){
if(data[tempIdx]!==floorBaseId && data[tempIdx+zAcc]!==floorBaseId){
idx = tempIdx;
break;
}
}
}else{
idx = TRP_CORE.random(targetIdxes);
}
if(idx>=0 && idx!==null){
if(!Array.isArray(tileIds)){
tileIds = tileIds.copy();
}
TRP_CORE.remove(targetIdxes,idx);
objInfo.push([idx,tileIds]);
}
}
/* locate bigObj
===================================*/
var locateInfo = [];
if(doMaximize){
bigObjIds = srcBigObjIds.concat();
TRP_CORE.shuffle(bigObjIds);
}
var locateSuccess = false;
for(var i=bigObjNum-1; i>=0;i-=1){
var bigObjInfo;
if(doMaximize){
if(locateSuccess || bigObjIds.length===0){
bigObjIds = srcBigObjIds.concat();
TRP_CORE.shuffle(bigObjIds);
}else{
if(i<bigObjNum-1){
i += 1;
}
}
bigObjInfo = bigObjIds.pop();
}else{
bigObjInfo = TRP_CORE.random(bigObjIds);
}
var bigObj = bigObjInfo[0];
var onFloorFlags = bigObjInfo[1];
var bigMapObject = !Array.isArray(bigObj) ? bigObj.copy() : null;
var w = onFloorFlags.length;
var h = onFloorFlags[0].length;
locateSuccess = false;
for(var ti=0; ti<targetIdxes.length; ti=(ti+1)|0){
locateInfo.length = 0;
/* check bigObj locatable
===================================*/
var baseIdx = targetIdxes[ti];
var locateFailed = false;
var floorZ = Number.MAX_SAFE_INTEGER;
for(var dx=0; dx<w; dx=(dx+1)|0){
for(var dy=0; dy<h; dy=(dy+1)|0){
var idx = baseIdx+dx-dy*width;
var tileIds = bigMapObject ? null : bigObj[dx][h-1-dy];
var onFloor = onFloorFlags[dx][h-1-dy];
if(!bigMapObject && !tileIds)continue;
if(onFloor){
//check is floor
if(!targetIdxes.contains(idx)){
locateFailed = true;
break;
}
//check all floor z same
if(floorZ===Number.MAX_SAFE_INTEGER){
floorZ = proc.zMap[idx];
}else if(floorZ !== proc.zMap[idx]){
locateFailed = true;
break;
}
}
locateInfo.push(idx);
locateInfo.push(tileIds);
locateInfo.push(onFloor);
}
if(locateFailed)break;
}
if(locateFailed)continue;
//add objInfo to locate
objInfo.push([baseIdx-(h-1)*width,bigMapObject||bigObj]);
//remove target idxes
var baseY = Math.floor(baseIdx/width);
for(var li=0; li<locateInfo.length; li=(li+3)|0){
var idx = locateInfo[li];
var tileIds = locateInfo[li+1];
var onFloor = locateInfo[li+2];
if(onFloor){
TRP_CORE.remove(targetIdxes,idx);
}
}
locateSuccess = true;
i -= (locateInfo.length/3);
break;
}
}
/* calc packRate
===================================*/
var leftNum = targetIdxes.length;
if(leftNum<minLeftTargetIdxesNum){
minLeftTargetIdxesNum = leftNum;
maxObjInfo = objInfo;
//save leftIdxes
proc.leftObjIdxesArr[roomId][info.floorBaseId][type] = targetIdxes;
}
}
objInfo = maxObjInfo;
}
//sort by "y"
proc.lastObjInfoArr[roomId] = proc.lastObjInfoArr[roomId].concat(
objInfo.sort((a,b)=>{
return a[0]-b[0];
})
);
//apply add objects
addObjTilesWithObjInfoArr(objInfo);
this.requestRefreshTilemap();
if(MapObject){
MapObject.refreshCollisions();
}
};
MapDecorator.prepareAccIdxesForLocateObject = function(validIdxes,accId){
var idxes = [];
for(var i=validIdxes.length-1; i>=0; i=(i-1)|0){
var idx = validIdxes[i];
if(baseTileId(data[idx])===accId
|| baseTileId([data[idx+zAcc]])===accId
){
idxes.unshift(idx);
validIdxes.splice(i,1);
}
}
return idxes;
};
function prepareWaterIdxesForLocateObject(validIdxes,waterInfoArr,waterAccIdxes){
var length = waterInfoArr.length;
var tempIdxes = [];
for(var i=0; i<length; i=(i+3)|0){
tempIdxes.push(waterInfoArr[i])
}
TRP_CORE.removeArray(validIdxes,tempIdxes);
//filter linkNum=4
var dirs = [-width,-1,1,width];
var waterIdxes = [];
for(var i=tempIdxes.length-1; i>=0; i=(i-1)|0){
var idx = tempIdxes[i];
waterIdxes.push(idx);
if(SETTING.waterObjOnEdge){
for(const dir of dirs){
if(!tempIdxes.contains(idx+dir)){
waterIdxes.pop();
break;
}
}
}
}
TRP_CORE.removeArray(waterIdxes,waterAccIdxes);
return waterIdxes;
};
function addObjTilesWithObjInfoArr(objInfoArr){
var infoLen = objInfoArr.length;
for(var i=0; i<infoLen; i=(i+1)|0){
var objInfo = objInfoArr[i];
var idx = objInfo[0];
var obj = objInfo[1];
var exData = objInfo.length>2 ? objInfo.slice(2) : null;
if(Array.isArray(obj[0])){
//bigObj
var cols = obj.length;
for(var dx=0; dx<cols; dx=(dx+1)|0){
var col = obj[dx];
var rows = col.length;
for(var dy=0; dy<rows; dy=(dy+1)|0){
var tileIds = col[dy];
if(!tileIds)continue;
addObjTiles(data,idx+dx+dy*width,tileIds,exData);
}
}
}else{
var tileIds = obj;
addObjTiles(data,idx,tileIds,exData);
}
}
}
function addObjTiles(data,idx,tileIds,exData=null){
if(!Array.isArray(tileIds)){
//trpMapObject
if(MapObject && tileIds instanceof MapObject){
addMapObject(tileIds,idx,exData);
}
return;
}
for(const tileId of tileIds){
addObjTile(data,idx,tileId);
}
};
function addMapObject(mapObj,idx,exData=null){
if(MapObject.tryAdd(mapObj,true)){
var x = idx%width + 0.5;
var y = Math.floor(idx/width) + 1;
if(mapObj.tileId){
x += (mapObj.tileW-1)/2;
y += (mapObj.tileH-1);
}
mapObj.x = x*tileW;
mapObj.y = y*tileH;
if(exData){
mapObj.x += exData[0];
mapObj.y += exData[1];
}
}
};
function addObjTile(data,idx,tileId){
if(isTileAnyA(tileId)){
return addObjTileA(data,idx,tileId);
}
if(data[idx+zObj2]){
if(data[idx+zObj1]){
if(data[idx+zAcc]){
return false;
}
data[idx+zAcc] = data[idx+zObj1];
}
data[idx+zObj1] = data[idx+zObj2];
}
data[idx+zObj2] = tileId;
return true;
};
function addObjTileA(data,idx,tileId){
data[idx+zObj2] = 0;
data[idx+zObj1] = 0;
data[idx+zAcc] = 0;
data[idx] = tileId;
return true;
};
function isTileAnyA(tileId){
return Tilemap.isTileA1(tileId)||Tilemap.isTileA2(tileId)||Tilemap.isTileA3(tileId)||Tilemap.isTileA4(tileId)||Tilemap.isTileA5(tileId);
};
function unshiftObjTileA(data,idx,tileId){
if(data[idx]){
if(data[idx+zAcc]){
if(data[idx+zObj1]){
if(data[idx+zObj2]){
return false;
}
data[idx+zObj2] = data[idx+zObj1];
}
data[idx+zObj1] = data[idx+zAcc];
}
data[idx+zAcc] = data[idx];
}
data[idx] = tileId;
};
function shiftDir(idx,dir){
if(idx<0)return idx;
if(dir===5)return idx;
if(dir===1)return shiftDir(shiftDir(2,idx),4);
if(dir===3)return shiftDir(shiftDir(2,idx),6);
if(dir===7)return shiftDir(shiftDir(8,idx),4);
if(dir===9)return shiftDir(shiftDir(8,idx),6);
var x = idx%width;
var y = Math.floor(idx/width);
var nIdx = idx;
if(dir===2){
if(y>=height-1)return -1;
nIdx += width;
}else if(dir===8){
if(y<=0)return -1;
nIdx-=width;
}else if(dir===4){
if(x<=0)return -1;
nIdx-=1;
}else{
if(x>=width-1)return -1;
nIdx+=1;
}
return nIdx;
};
//=============================================================================
// Dot Shift Objects
//=============================================================================
MapDecorator.tryDotShiftObjects = function(roomId){
if(!MapObject)return;
var objInfoArr = proc.lastObjInfoArr[roomId];
var idxesMap = proc.leftObjIdxesArr[roomId];
if(!objInfoArr || !idxesMap){
SoundManager.playBuzzer();
return;
}
var zMap = proc.floorLevelZMap.concat();
var usedIdxes = [];
for(const objInfo of objInfoArr){
this._tryDotShiftObject(objInfo,zMap,idxesMap,usedIdxes);
}
SoundManager.playCursor();
this.restoreMap(true);
this.saveState('ドットシフト');
};
MapDecorator._tryDotShiftObject = function(objInfo,zMap,idxesMap,usedIdxes){
var idx = objInfo[0];
var obj = objInfo[1];
if(objInfo[2]||objInfo[3]){
if(objInfo[2]<=-tileW/4 || objInfo[2]>=tileW/4)return;
if(objInfo[3]<=-tileH/4 || objInfo[3]>=tileH/4)return;
}
var infoIdx = proc.idxBaseInfoIdxMap[idx];
var _info = allInfo[infoIdx];
var typeResult = this._objectLocateType(obj,_info);
if(!typeResult)return;
var type = typeResult.type;
var onFloorFlags = typeResult.onFloorFlags||null;
var idxes = idxesMap[_info.floorBaseId][type];
if(!idxes)return;
//check 4 dirs
var dirs4 = [];
for(const dir of MapDecorator.DIRS4){
var nIdx = shiftDir(idx,dir);
if(nIdx<0)continue;
if(!this._canShiftObject(idx,nIdx,obj,onFloorFlags,zMap,idxes,usedIdxes))continue;
dirs4.push(dir);
}
//check 8 dirs
var DIRS = MapDecorator.DIRS4.concat();
while(DIRS.length){
var dir = TRP_CORE.randomShift(DIRS);
var dirLeft = this.DIR_LEFT_90[dir];
if(!dirs4.contains(dir) || !dirs4.contains(dirLeft))continue;
var nIdx = shiftDir(idx,dir);
if(nIdx<0)continue;
if(!this._canShiftObject(idx,nIdx,obj,onFloorFlags,zMap,idxes,usedIdxes))continue;
this._execDotShiftObject(objInfo,obj,onFloorFlags,dir,idxes,usedIdxes);
this._execDotShiftObject(objInfo,obj,onFloorFlags,dirLeft,idxes,usedIdxes);
return;
};
while(dirs4.length){
var dir = TRP_CORE.randomShift(dirs4);
this._execDotShiftObject(objInfo,obj,onFloorFlags,dir,idxes,usedIdxes);
return;
}
};
MapDecorator._execDotShiftObject = function(objInfo,obj,onFloorFlags,dir,idxes,usedIdxes){
if(!(obj instanceof MapObject)){
var template = this.mapObjectTemplateWithTileObject(obj,true);
if(!template)return;
obj = objInfo[1] = template.copy();
}
objInfo[2] = objInfo[2]||0;
objInfo[3] = objInfo[3]||0;
var infoIdx = (dir===4||dir===6) ? 2 : 3;
var delta0 = objInfo[infoIdx]||0;
objInfo[infoIdx] = 0;
var tileSize = (dir===2||dir===8) ? tileH : tileH;
var value = Math.randomInt(tileSize/4);
if(dir===2)objInfo[infoIdx] += value;
else if(dir===8)objInfo[infoIdx] -= value;
else if(dir===4)objInfo[infoIdx] -= value;
else if(dir===6)objInfo[infoIdx] += value;
if(MapObject && obj instanceof MapObject){
if(infoIdx===2)obj.x += objInfo[infoIdx]-delta0;
else obj.y += objInfo[infoIdx]-delta0;
obj._lastDispX = Number.MAX_SAFE_INTEGER;
obj._lastDispY = Number.MAX_SAFE_INTEGER;
obj.setupMargin();
}
//reserve idxes
var idx = objInfo[0];
var nIdx = shiftDir(idx,dir);
if(onFloorFlags){
var w = onFloorFlags.length;
var h = onFloorFlags[0].length;
for(var dx=0; dx<w; dx=(dx+1)|0){
for(var dy=0; dy<h; dy=(dy+1)|0){
var onFloor = onFloorFlags[dx][h-1-dy];
if(!onFloor)continue;
var tIdx = nIdx+dx-dy*width;
usedIdxes.push(tIdx);
}
}
}else{
usedIdxes.push(nIdx);
}
};
MapDecorator.DIRS4 = [2,4,6,8];
MapDecorator.DIR_LEFT_90 = [0,0, 4,0, 8,0, 2,0, 6];
MapDecorator._objectLocateType = function(obj,_info){
var types = ['base','water',..._info.separateLocateObjAccIds];
var objIds,bigObjIds,floorBaseId;
var isMapObj = MapObject && obj instanceof MapObject;
for(const type of types){
if(type==='base'){
//floor
objIds = _info.objIds;
bigObjIds = _info.bigObjIds;
floorBaseId = _info.floorBaseId;
}else if(type==='water'){
//water
objIds = _info.waterObjIds;
bigObjIds = _info.waterBigObjIds;
floorBaseId = _info.waterBaseId;
}else{
//accessory
floorBaseId = Number(type);
var accInfo = _info.accSettings[floorBaseId];
objIds = accInfo.objIds;
bigObjIds = accInfo.bigObjIds;
}
if(floorBaseId===obj)return {type};
if(objIds){
if(isMapObj){
if(objIds.some(target=>(target instanceof MapObject)&&target.tag===obj.tag)){
return {type};
}
}else{
if(TRP_CORE.containsEqual(objIds,obj)){
return {type};
}
}
}
if(bigObjIds){
var bigObjIdsData = bigObjIds.map(bo=>bo[0]);
if(isMapObj){
if(bigObjIdsData.some(target=>(target instanceof MapObject)&&target.tag===obj.tag)){
return {type,onFloorFlags};
}
}else{
var idx = TRP_CORE.indexOfEqual(bigObjIdsData,obj)
if(idx>=0){
var onFloorFlags = bigObjIds[idx][1];
return {type,onFloorFlags};
}
}
}
}
if(isMapObj){
//retry with tileIds array data
if(obj.tileId){
var tileIds = obj.tileIds(true);
if(tileIds.length===1 && tileIds[0].length===1){
tileIds = tileIds[0][0];
}
return this._objectLocateType(tileIds,_info);
}
}
return null;
};
MapDecorator._canShiftObject = function(idx,nIdx,obj,onFloorFlags,zMap,idxes,usedIdxes){
if(onFloorFlags){
//check bigObj
var w = onFloorFlags.length;
var h = onFloorFlags[0].length;
var objIdxes = [];
for(var dx=0; dx<w; dx=(dx+1)|0){
for(var dy=0; dy<h; dy=(dy+1)|0){
var onFloor = onFloorFlags[dx][h-1-dy];
if(onFloor){
var tIdx = idx+dx+dy*width;
objIdxes.push(tIdx);
}
}
}
for(var dx=0; dx<w; dx=(dx+1)|0){
for(var dy=0; dy<h; dy=(dy+1)|0){
var onFloor = onFloorFlags[dx][h-1-dy];
if(!onFloor)continue;
var tIdx = nIdx+dx+dy*width;
if(objIdxes.contains(tIdx))continue;
if(!idxes.contains(tIdx))return false;
if(usedIdxes.contains(tIdx))return false;
if(zMap[idx] !== zMap[tIdx])return false;
}
}
}else{
if(!idxes.contains(nIdx))return false;
if(usedIdxes.contains(tIdx))return false;
if(zMap[idx] !== zMap[nIdx])return false;
}
return true;
};
//=============================================================================
// MODE: ManualLocate
//=============================================================================
MapDecorator.MODE_GUIDE.manualLocate = [
'【手動オブジェ配置モード】',
'左クリ:配置/削除',
'右クリ:終了',
'Ctrl+左クリ:オブジェ選択(スポイト)',
];
if(MapObject){
MapDecorator.MODE_GUIDE.manualLocate.push(
'Vキー:オブジェクト範囲選択',
);
}
MapDecorator.setModeManualLocate = function(){
this.tryInitManualLocateData();
}
MapDecorator.endModeManualLocate = function(){
_Dev.showText('dotLocate',null);
_Dev.showText('adjustMapObj',null);
this.releaseLastLocateMapObj();
};
MapDecorator.tryInitManualLocateData = function(){
if(this.modeData && this.modeData.type==='manualLocate'){
if(this.modeData.onDraggingLocateObj)return;
return;
}
var modeData = this.modeData = {};
modeData.type = 'manualLocate';
modeData.manualLocateObj = null;
modeData.onDraggingLocateObj = null;
this.releaseLastLocateMapObj();
};
MapDecorator.releaseLastLocateMapObj = function(){
var modeData = this.modeData;
if(!modeData || !modeData.lastLocateMapObj)return;
modeData.lastLocateMapObj = null;
};
MapDecorator.tryConvertMapObjectToMapData = function(obj){
if(obj.aX || obj.aY || obj.blendMode || obj.opacity!==255
|| obj.scaleX!==1 || obj.scaleY!==1 || obj.rotation
|| obj.mirror || obj.anchorX!==0.5 || obj.anchorY!==1
|| !obj.tileId
|| obj._animations
|| obj.commonIds
|| MapDecorator.mapObjectOriginalTemplateTags.contains(obj.tag)
|| (obj.x-obj.tileW*tileW/2)%tileW!==0
|| obj.y%tileH!==0
){
//obj
}else{
//obj -> tile
var tileIds = obj.tileIds(true);
if(tileIds){
var infoArr = null;
var targetObjInfo = null;
for(const roomObjInfo of proc.lastObjInfoArr){
if(!roomObjInfo)continue;
for(const objInfo of roomObjInfo){
if(obj===objInfo[1]){
targetObjInfo = objInfo;
infoArr = roomObjInfo;
break;
}
}
if(infoArr)break;
}
if(!infoArr)return false;
var w = obj.tileW;
var h = obj.tileH;
var x = Math.floor((obj.x-w/2)/tileW);
var y = Math.floor((obj.y-h)/tileH);
if(!this._tryReplaceTilesWithLocation(tileIds,x,y,w,h))return false;
MapObject.remove(obj);
TRP_CORE.remove(infoArr,targetObjInfo);
return true;
// objInfo[1] = tileIds;
// tileIds = null;
// if(!noRestoreMap){
// this.restoreMap(true);
// }
// return true;
}
}
return false;
};
MapDecorator.tryStartManualLocateMode = function(event,roomId,x,y,tx,ty,dx,dy){
var idx = x+y*width;
var objInfo = this.searchObjInfo(idx,roomId,dx,dy);
_Dev.showText('dotLocate',null);
if(!objInfo){
return false;
}
if(this._mode==='manualLocate'){
if(this.modeData.lastLocateMapObj!==objInfo){
this.releaseLastLocateMapObj();
}
if(!objInfo){
this.modeData.manualLocateObj = null;
}
}
this.startManualLocateMode(objInfo);
return true;
};
MapDecorator.startManualLocateMode = function(obj=null){
var dragging = this.modeData ? this.modeData.onDraggingLocateObj : null;
this.setMode('manualLocate');
this.tryInitManualLocateData();
this.modeData.onDraggingLocateObj = this.modeData.onDraggingLocateObj||dragging||null;
if(!Array.isArray(obj)){
if(this.modeData.lastLocateMapObj!==obj){
this.modeData.lastLocateMapObj = obj;
}
this.refreshAdjustMapObjectHelp(obj);
obj = obj.copy();
_Dev.showText('dotLocate','Shift+左クリ:ドット単位で配置(ドラッグで移動)');
}
this.modeData.manualLocateObj = obj;
var name;
if(this.modeData.onDraggingLocateObj){
name = '手動オブジェ配置:配置&移動';
}else{
name = '手動オブジェ配置:開始';
}
this.disableLastStateOverwritable(name);
this.saveState(name,true,true);
SoundManager.playCursor();
return true;
};
MapDecorator.searchObjInfo = function(idx,roomId,dx,dy){
return this._searchObjInfo(idx,roomId,dx,dy);
};
MapDecorator.checkObjectInfoTouch = function(objInfo,x,y,x1,y1,completion){
var objIdx = objInfo[0];
var obj = objInfo[1];
//check obj touch the idx
var ox,oy,w,h,ax,ay;
if(Array.isArray(obj)){
ox = (objIdx%width)*tileW;
oy = Math.floor(objIdx/width)*tileH;
if(objInfo[2])ox += objInfo[2];
if(objInfo[3])oy += objInfo[3];
if(Array.isArray(obj[0])){
//bigObj
w = obj.length;
h = obj[0].length;
}else{
w = 1;
h = 1;
}
w *= tileW;
h *= tileH;
ax = ox+w/2;
ay = oy+h;
}else{
//mapObject
if(!obj.sprite)return false;
var sprite = obj.sprite;
w = sprite.width*sprite.scale.x;
h = sprite.height*sprite.scale.y;
if(w<0)w*=-1;
if(h<0)h*=-1;
ox = sprite.x - sprite.anchor.x*w + $gameMap._displayX*tileW;
oy = sprite.y - sprite.anchor.y*h + $gameMap._displayY*tileH;
ax = ox + w*sprite.anchor.x;
ay = oy + h*sprite.anchor.y;
// if(sprite.rotation){
// var dx = x -(sprite.x+$gameMap._displayX*tileW);
// var dy = y -(sprite.y+$gameMap._displayY*tileH);
// var theta = -sprite.rotation;
// x = (sprite.x+$gameMap._displayX*tileW) + dx*Math.cos(theta)-dy*Math.sin(theta);
// y = (sprite.y+$gameMap._displayX*tileH) + dx*Math.sin(theta)+dy*Math.cos(theta);
// }
// var bitmap = new Bitmap(w,h);
// var sprite = new Sprite(bitmap);
// bitmap.fillAll('rgba(255,0,0,0.5)');
// sprite.x = ox - $gameMap._displayX*tileW;
// sprite.y = oy - $gameMap._displayY*tileH;
// SceneManager._scene.addChild(sprite);
}
if(x1===undefined){
if(x<ox || x>ox+w)return false;
if(y<oy || y>oy+h)return false;
}else{
if(x1<ox || x>ox+w)return false;
if(y1<oy || y>oy+h)return false;
}
if(completion){
completion(ax,ay);
}
return true;
};
MapDecorator._searchObjInfo = function(idx,roomId,dx=0,dy=0,eraseTarget=null){
var objInfoArr = proc.lastObjInfoArr[roomId];
if(!objInfoArr)return null;
var x = (idx%width)*tileW + dx;
var y = Math.floor(idx/width)*tileH + dy;
var isTargetArray = eraseTarget && Array.isArray(eraseTarget);
var bestTargetInfo = null;
var bestDist = Number.MAX_SAFE_INTEGER;
var bestAx,bestAy;
for(const objInfo of objInfoArr){
var objIdx = objInfo[0];
var obj = objInfo[1];
if(eraseTarget){
if(eraseTarget===obj){
//sameObj
}else if(!isTargetArray&&eraseTarget.equalsMapObjectImage(obj)){
//sameMapObjImage
}else if(isTargetArray&&Array.isArray(obj)&&eraseTarget.equals(obj)){
//equals
}else{
//not match to targetObj
continue;
}
}
this.checkObjectInfoTouch(objInfo,x,y,undefined,undefined,(ax,ay)=>{
var dist = Math.abs(ax-x)+Math.abs(ay-y);
if(dist<bestDist){
bestDist = dist;
bestTargetInfo = objInfo;
bestAx = ax;
bestAy = ay;
}
});
}
if(!bestTargetInfo)return null;
var obj = bestTargetInfo[1];
if(eraseTarget){
TRP_CORE.remove(objInfoArr,bestTargetInfo);
if(!isTargetArray){
MapObject.remove(obj);
}
if(MapObject && obj instanceof MapObject){
if(this.modeData.manualLocateObj===obj){
this.modeData.manualLocateObj = null;
}
}
if(this.modeData.lastLocateMapObj===obj){
this.modeData.lastLocateMapObj = null;
}
}else{
/* register to draggingObj
===================================*/
if(MapObject && !(obj instanceof MapObject)){
var template = MapDecorator.mapObjectTemplateWithTileObject(obj,true);
if(template){
obj = template.copy();
bestTargetInfo[1] = obj;
obj.x = bestAx;
obj.y = bestAy;
MapObject.tryAdd(obj);
SceneManager._scene._spriteset.updateTrpMapObjects();
this.restoreMap(true);
}
}
if(MapObject && obj instanceof MapObject && obj.sprite){
var objInfoArr = null;
var tx = x-tileW/2;
var ty = y-tileH;
var idx;
var targetObj = null;
var objInfo = this.objInfoOfObj(obj);
if(objInfo){
targetObj = objInfo;
idx = objInfo[0];
for(const roomObjInfo of proc.lastObjInfoArr){
if(!roomObjInfo)continue;
if(roomObjInfo.contains(objInfo)){
objInfoArr = roomObjInfo;
break;
}
}
dx = objInfo[2]||0;
dy = objInfo[3]||0;
}
if(objInfoArr){
var sprite = obj.sprite;
var x = idx%width;
var y = Math.floor(idx/width);
var w = obj.tileId ? obj.tileW : 1;
var h = obj.tileId ? obj.tileH : 1;
x += Math.floor((w-1)/2);
y += h-1;
this.tryInitManualLocateData();
this.startObjectDragging({
onLocate:false,
obj,
objInfoArr,
data:targetObj,
tx,
ty,
dx,
dy,
x,
y,
count:6,
});
}
}
}
return obj;
};
MapDecorator.startObjectDragging = function(dragging){
this.modeData.onDraggingLocateObj = dragging;
if(!this.draggingGrid){
var col = Math.ceil(Graphics.width/SETTING.mapDispRange / tileW);
var row = Math.ceil(Graphics.height/SETTING.mapDispRange / tileH);
this.draggingGrid = this.tileGridGraphic(col,row,0xff0000,0.5);
}
SceneManager._scene.addChild(this.draggingGrid);
};
MapDecorator.tileGridGraphic = function(col,row,color=0x000000,alpha=0.8){
var grid = new PIXI.Graphics();
grid.beginFill(color,alpha);
var lineW = 1;
for(var c=0; c<col+1; c=(c+1)|0){
grid.drawRect(c*tileW,0,lineW,row*tileH);
}
for(var r=0; r<row+1; r=(r+1)|0){
grid.drawRect(0,r*tileH,col*tileW,lineW);
}
return grid;
};
MapDecorator.updateDraggingGrid = function(){
var grid = this.draggingGrid;
if(!grid)return;
grid.x = -(($gameMap._displayX*tileW/SETTING.mapDispRange)%tileW)
grid.y = -(($gameMap._displayY*tileH/SETTING.mapDispRange)%tileH)
};
/* manualLocate main proc
===================================*/
MapDecorator.onMouseDownLeftManualLocate = function(event,roomId,x,y,tx,ty,dx,dy){
if(!this.modeData)return;
this.modeData.onDraggingLocateObj = null;
if(this.draggingGrid){
this.draggingGrid.visible = false;
}
if(roomId<0){
roomId = proc.roomIdxMapForUserProc[x+y*width];
}
if(roomId<0 || roomId===undefined)return;
if(this.onKeyControl){
if(!this.tryStartManualLocateMode(event,roomId,x,y,tx,ty,dx,dy)){
SoundManager.playBuzzer();
}
}else{
var dotLoc = (MapObject&&Input.isPressed('shift'));
this.processManualLocate(event,roomId,x,y,dx,dy,dotLoc);
}
};
MapDecorator.onMouseDownRightManualLocate = function(event,roomId,x,y,tx,ty,dx,dy){
if(Input.isPressed('shift')){
}else if(this.onKeyControl){
MapDecorator.tryShowObjectPalette();
}else{
SoundManager.playCancel();
this.restoreMode();
}
};
MapDecorator.processManualLocate = function(event,roomId,x,y,dx,dy,dotLoc=false){
var obj = this.modeData.manualLocateObj;
this.releaseLastLocateMapObj();
_Dev.showText('adjustMapObj',null);
if(!obj){
SoundManager.playBuzzer();
return;
}
if(!MapObject /*|| !(obj instanceof MapObject)*/){
dotLoc = false;
}
if(dotLoc&&!(obj instanceof MapObject)){
var template = this.mapObjectTemplateWithTileObject(obj);
if(template){
obj = template.copy();
}else{
dotLoc = false;
}
}
var idx = x+y*width;
var roomId = idxOfRoom(idx);
if(!proc.lastObjInfoArr[roomId]){
proc.lastObjInfoArr[roomId] = [];
}
var objInfoArr = proc.lastObjInfoArr[roomId];
//try erase
var eraseTarget = obj;
var eraseTarget2 = null;
if(MapObject&&!(obj instanceof MapObject)){
//auto converted mapObjct
eraseTarget2 = MapDecorator._convertedMapObjMap[JSON.stringify(obj)]||null;
}
var erased = false;
if(!dotLoc && this._searchObjInfo(idx,roomId,dx,dy,eraseTarget)){
//erase success
erased = true;
}else if(!dotLoc && eraseTarget2 && this._searchObjInfo(idx,roomId,dx,dy,eraseTarget2)){
//erase success
erased = true;
}else{
//add obj
if(!dotLoc){
dx = 0;
dy = 0;
}else{
dx -= tileW/2;
dy -= tileH;
}
if(!this.tryManualLocateObject(idx,obj,roomId,objInfoArr,dx,dy)){
SoundManager.playBuzzer();
return;
}
}
SoundManager.playCursor();
//restoreMap to apply edit
var lockedObjRoomIds = proc.lockedObjRoomIds;
proc.lockedObjRoomIds = TRP_CORE.packSequence([],proc.allRoomIdxes.length);
this.restoreMap();
proc.lockedObjRoomIds = lockedObjRoomIds;
if(erased){
this.saveState('手動オブジェ配置:消去');
}else{
//saveState on tryManualLocateobject()
}
};
MapDecorator._mapObjTransformCopy = null;
MapDecorator.onKeyDownManualLocate = function(event){
var modeData = this.modeData;
if(!modeData || modeData.type!=='manualLocate')return;
if(modeData.onDraggingLocateObj)return;
if(!MapObject)return;
if(event.key==='v'){
this.startObjectSelectMode();
SoundManager.playCursor();
return true;
}
var obj = modeData.lastLocateMapObj;
if(obj){
if(event.key==='Backspace'){
//delete obj
for(const objInfoArr of proc.lastObjInfoArr){
for(const data of objInfoArr){
if(data.contains(obj)){
TRP_CORE.remove(objInfoArr,data);
MapObject.remove(obj);
this.releaseLastLocateMapObj();
SoundManager.playCursor();
this.saveState('手動オブジェ配置:消去');
return true;
}
}
}
return false;
}else if(!isNaN(event.key)){
var rate = Number(event.key)*0.1||1.0;
obj.opacity = Math.ceil(255*rate);
this.saveState('オブジェ編集:不透明度',true);
}else if(event.key==='m'){
obj.mirror = !obj.mirror;
this.saveState('オブジェ編集:反転');
}else if(event.key==='r'){
obj.scaleX = obj.scaleY = 1;
obj.rotation = 0;
obj.mirror = false;
obj.tint = 0xffffff;
var tx = Math.round((obj.x-obj.tileW*tileW/2)/tileW);
var ty = Math.round(obj.y/tileH)-obj.tileH;
obj.x = tx*tileW+obj.tileW*tileW/2;
obj.y = (ty+obj.tileH)*tileH;
obj._lastDispX = obj._lastDispY = Number.MAX_SAFE_INTEGER;
var objInfo = this.objInfoOfObj(obj);
if(objInfo){
objInfo[0] = tx+ty*width;
}
this.saveState('オブジェ編集:リセット/マス中央');
}else if(event.key==='t'){
this.startPickColor(color=>{
obj.tint = Number(color.replace('#','0x'));
if(obj.sprite){
obj.sprite.tint = obj.tint;
}
this.saveState('オブジェ編集:色味(ティント)',true);
});
// }else if(event.key==='b'){
// var blend = obj.blendMode+1;
// if(blend>=5){
// blend = 0;
// }
// obj.setBlendMode(blend);
// _Dev.showTempText('mapObjBlend','ブレンド > %1'.format(
// blend===0 ? '通常' : (blend===1 ? '加算' : (blend===2 ? '乗算' : 'オーバーレイ'))
// ));
}else if(event.key==='e'||event.key==='E'){
//priority
obj.priority += event.shiftKey ? 0.1 : 1;
obj.priority = Math.round(obj.priority*10)/10;
if(!event.shiftKey && obj.priority>2){
obj.priority = 0;
}
this.saveState('オブジェ編集:プライオリティ変更',true);
}else if(event.key==='c'){
// MapDecorator._mapObjTransformCopy = [
// obj.scaleX,obj.scaleY,obj.rotation,obj.opacity,obj.mirror,obj.tint
// ];
MapDecorator.modeData.manualLocateObj = obj.copy();
SoundManager.playOk();
this.saveState('オブジェ編集:コピー');
// }else if(event.key==='v'){
// if(MapDecorator._mapObjTransformCopy){
// var info = MapDecorator._mapObjTransformCopy
// var idx = 0;
// obj.scaleX = info[idx++];
// obj.scaleY = info[idx++];
// obj.rotation = info[idx++];
// obj.opacity = info[idx++];
// obj.mirror = info[idx++];
// obj.tint = info[idx++];
// SoundManager.playOk();
// }else{
// SoundManager.playBuzzer();
// }
}else{
return;
}
this.refreshAdjustMapObjectHelp(obj);
obj.tryRefreshSpriteState();
SoundManager.playCursor();
}
};
MapDecorator.onStateChangeManualLocate = function(){
var obj = this.modeData.lastLocateMapObj;
if(obj){
obj = this.modeData.lastLocateMapObj = this._tryRestoreMapObject(obj);
}
};
MapDecorator.onMousePressManualLocate = function(event,roomId,x,y,tx,ty,dx,dy){
if(!this.modeData)return;
if(!this.modeData.onDraggingLocateObj)return;
var dragging = this.modeData.onDraggingLocateObj;
if(this.modeData.lastLocateMapObj!==dragging.obj)return;
dragging.count -= 1;
if(dragging.count>0){
return;
}
if(this.draggingGrid){
this.draggingGrid.visible = true;
}
//adjust pos to anchor
dx -= tileW/2;
dy -= tileH;
var offsetX = (x*tileW+dx) - dragging.tx;
var offsetY = (y*tileH+dy) - dragging.ty;
if(!offsetX && !offsetY){
return;
}
//calc real x,y,dx,dy
dx = dragging.x*tileW + dragging.dx + offsetX;
dy = dragging.y*tileH + dragging.dy + offsetY;
x = Math.floor(dx/tileW);
y = Math.floor(dy/tileH);
dx -= x*tileW;
dy -= y*tileH;
var rIdx = x+width*y;
if(rIdx<0)return;
// roomId = idxOfRoom(rIdx);
roomId = proc.roomIdxMapForUserProc[rIdx];
if(roomId<0 || roomId===undefined){
return;
}
// this.tonnerTiles([rIdx]);
dragging.tx += offsetX;
dragging.ty += offsetY;
var idx = x+y*width;
if(idx<0)return;
var objInfoArr = proc.lastObjInfoArr[roomId];
this.tryManualLocateObject(idx,dragging.obj,roomId,objInfoArr,dx,dy,dragging);
var stateName = '手動オブジェ配置:配置&移動';
this.saveState(stateName,true);
};
MapDecorator.updateInputManualLocate = function(){
if(!this.modeData)return false;
var obj = this.modeData.lastLocateMapObj;
if(!obj)return false;
if(Input.isPressed('shift')){
var stateName = null;
if(Input.isTriggered('left')||Input.isLongPressed('left')){
obj.rotation -= 5*Math.PI/180;
stateName = '角度';
}else if(Input.isTriggered('right')||Input.isLongPressed('right')){
obj.rotation += 5*Math.PI/180;
stateName = '角度';
}else if(Input.isTriggered('up')||Input.isLongPressed('up')){
obj.scaleX += 0.05;
obj.scaleY += 0.05;
stateName = '拡大率';
}else if(Input.isTriggered('down')||Input.isLongPressed('down')){
obj.scaleX -= 0.05;
obj.scaleY -= 0.05;
stateName = '拡大率';
}else if(
Input.isPressed('left') || Input.isPressed('right')
|| Input.isPressed('up') || Input.isPressed('down')
){
return true;
}else{
return false;
}
}else if(this.onKeyAlt){
if(Input.isTriggered('left')||Input.isLongPressed('left')){
obj.scaleX -= 0.05;
stateName = '拡大率<X>';
}else if(Input.isTriggered('right')||Input.isLongPressed('right')){
obj.scaleX += 0.05;
stateName = '拡大率<X>';
}else if(Input.isTriggered('up')||Input.isLongPressed('up')){
obj.scaleY += 0.05;
stateName = '拡大率<Y>';
}else if(Input.isTriggered('down')||Input.isLongPressed('down')){
obj.scaleY -= 0.05;
stateName = '拡大率<Y>';
}else if(
Input.isPressed('left') || Input.isPressed('right')
|| Input.isPressed('up') || Input.isPressed('down')
){
return true;
}else{
return false;
}
}else{
if(Input.isTriggered('pagedown')||Input.isLongPressed('pagedown')){
obj.opacity += 5;
stateName = '不透明度';
}else if(Input.isTriggered('pageup')||Input.isLongPressed('pageup')){
obj.opacity -= 5;
stateName = '不透明度';
}else{
return false;
}
obj.opacity = obj.opacity.clamp(0,255);
}
this.saveState(stateName,true);
obj.tryRefreshSpriteState();
this.refreshAdjustMapObjectHelp(obj);
if(Input._pressedTime===0 || Input._pressedTime%4===0){
SoundManager.playCursor();
}
return true;
}
/* processManualLocateObj
===================================*/
MapDecorator.tryManualLocateObject = function(idx,obj,roomId,objInfoArr,dx=0,dy=0,dragging=null){
if(roomId<0)return false;
var roomBaseIdxes = proc.allBaseIdxes[roomId];
var baseIdx = proc.idxBaseInfoIdxMap[idx];
if(baseIdx<0){
return false;
}
var validIdxes = roomBaseIdxes[baseIdx++].concat();
TRP_CORE.removeArray(validIdxes,proc.objForbiddenIdxes);
TRP_CORE.removeArray(validIdxes,proc.passIdxes);
var w = 1;
var h = 1;
var tx,ty;
var isMapObj = false;
var needsSort = true;
if(Array.isArray(obj)){
if(Array.isArray(obj[0])){
//bigObj
w = obj.length;
h = obj[0].length;
}
tx = idx%width-Math.floor((w-1)/2);
ty = Math.floor(idx/width)-(h-1);
}else{
//MapObject
isMapObj;
if(obj.tileId){
w = obj.tileW;
h = obj.tileH;
}
tx = idx%width-(w-1)/2;
ty = Math.floor(idx/width)-(h-1);
if(!dragging){
obj = obj.copy();
}
}
//check target pos valid
if(tx<0||tx>=width)return false;
if(ty<0||ty>=height)return false;
var targetIdx = tx+ty*width;
var targetObj = [targetIdx,obj];
if(dx||dy){
targetObj.push(dx,dy);
}
if(!Array.isArray(obj)){
if(!dragging){
this.startObjectDragging({
onLocate:true,
obj,
objInfoArr,
data:targetObj,
tx:idx%width*tileW+dx,
ty:Math.floor(idx/width)*tileH+dy,
x:idx%width,
y:Math.floor(idx/width),
dx,dy,
count:10,
});
}else{
//dragging obj
TRP_CORE.remove(dragging.objInfoArr,dragging.data);
needsSort = dragging.dy!==dy || dragging.y!==Math.floor(idx/width);
if(obj.sprite){
var deltaX = (dx-dragging.dx)+tileW*(idx%width-dragging.x);
var deltaY = (dy-dragging.dy)+tileH*(Math.floor(idx/width)-dragging.y);
obj.x += deltaX;
obj.y += deltaY;
obj._lastDispX = Number.MAX_SAFE_INTEGER;
obj._lastDispY = Number.MAX_SAFE_INTEGER;
obj.setupMargin();
}
dragging.objInfoArr = objInfoArr;
dragging.data = targetObj;
dragging.dx = dx;
dragging.dy = dy;
dragging.x = idx%width;
dragging.y = Math.floor(idx/width);
}
this.modeData.lastLocateMapObj = obj;
this.refreshAdjustMapObjectHelp(obj);
}
objInfoArr.push(targetObj);
if(needsSort){
objInfoArr.sort((a,b)=>{
if(a[0]-b[0]>0)return true;
if(a[0]===b[0]){
if(a[3]){
if(b[3]){
return a[3]-b[3]>=0;
}else{
return true;
}
}else if(b[3]){
return false;
}else{
return true;
}
}else{
return false;
}
});
}
return true;
};
MapDecorator.HELP_ADJUST_MAP_OBJ = [
'Shift+左右キー:回転<%rotate>',
'Shift+上下キー:拡大率<%scale>',
'Alt/Opt+上下左右キー:XY方向拡大率<%xyScale>',
'M反転<%mirror>',
'Q/W/0~9不透明度<%opacity>',
'T色味<%tint>',
// 'Bブレンドモード',
'(Shift+)Eプライオリティ<%priority>',
'R変形リセット',
'Cコピー',
'Backspace削除',
'(※衝突判定は変形が反映されないので注意)'
];
MapDecorator.refreshAdjustMapObjectHelp = function(obj){
var guide = MapDecorator.HELP_ADJUST_MAP_OBJ.concat();
var params = {
rotate:Math.floor(obj.rotation*180/Math.PI),
scale:Math.floor(obj.scaleX*100)+'%',
xyScale:(obj.scaleY/obj.scaleX||0).toFixed(2),
mirror:obj.mirror,
tint:'%1,%2,%3'.format(obj.tint%255,Math.floor(obj.tint/255)%255,Math.floor(obj.tint/255/255)),
priority:obj.priority
}
for(var i=guide.length-1; i>=0; i=(i-1)|0){
guide[i] = guide[i]
.replace('%rotate',params.rotate)
.replace('%opacity',params.opacity)
.replace('%scale',params.scale)
.replace('%xyScale',params.xyScale)
.replace('%mirror',params.mirror)
.replace('%tint',params.tint)
.replace('%priority',params.priority)
}
_Dev.showText('adjustMapObj',guide);
};
//=============================================================================
// MODE: ObjectPalette
//=============================================================================
MapDecorator.MODE_GUIDE.objectPalette = [
'【オブジェパレット】',
'左クリ:オブジェ選択',
'右クリ:キャンセル',
'Ctrl+A:全タイルセット画像',
];
if(MapObject){
MapDecorator.MODE_GUIDE.objectPalette.push(
'Ctrl+G:グループオブジェ',
);
}
MapDecorator.OBJECT_PALETTE_EMPTY_NUM = 2;
MapDecorator.OBJECT_PALETTE_SIZE = 96;
MapDecorator.OBJECT_PALETTE_MARGIN = 8;
MapDecorator.tryShowObjectPalette = function(){
this.setMode('objectPalette');
SoundManager.playOk();
};
MapDecorator.lastObjPaletteCategory = 'main';
MapDecorator.setModeObjectPalette = function(){
var modeData = this.modeData = {};
modeData.main = this.objectPaletteMain();
if(MapObject){
modeData.all = this.objectPaletteAll();
modeData.group = this.objectPaletteGroup();
}
var category = MapDecorator.lastObjPaletteCategory;
this.showObjectPalette(category);
};
MapDecorator.endModeObjectPalette = function(){
_Dev.showText('objPaletteEx',null);
};
MapDecorator.lastObjPaletteIdxes = {};
MapDecorator.showObjectPalette = function(category='main'){
var modeData = this.modeData;
var palette = modeData[category];
if(!palette){
SoundManager.playBuzzer();
return;
}
MapDecorator.lastObjPaletteCategory = category;
var pageIdx = MapDecorator.lastObjPaletteIdxes[category]||0;
var completion = obj=>{
var palette = this.showingPalette;
if(palette){
MapDecorator.lastObjPaletteIdxes[category] = palette.pageIdx;
}
this.startManualLocateMode(obj);
};
var help = null;
if(category==='group'){
help = ['右クリック:オブジェ編集']
}else if(category==='main'){
help = ['B~Eキー:タイルセット切替'];
}else{
help = [' '];
}
_Dev.showText('objPaletteEx',help);
var keySearchEnable = category!=='main';
this.showPalette(palette.objectsArr,palette.pageNames,pageIdx,palette.size,palette.m,palette.x0Num,completion,null,keySearchEnable);
};
MapDecorator.objectPaletteMain = function(){
var size = MapDecorator.OBJECT_PALETTE_SIZE;
var m = MapDecorator.OBJECT_PALETTE_MARGIN;
var x0Num = MapDecorator.OBJECT_PALETTE_EMPTY_NUM;
var pageNames = [];
var objectsArr = [];
//palette
var objects = MapDecorator.paletteObjects;
if(objects.length){
objectsArr.push(objects);
pageNames.push('パレット登録');
}
//allObject
objectsArr.push(allObjects);
pageNames.push('テンプレ全オブジェ');
//tileset
var tileNames = $gameMap.tileset().tilesetNames;
var tilesetData = [];
for(var i=5; i<tileNames.length; i=(i+1)|0){
var tileName = tileNames[i];
if(!tileName)continue;
tilesetData.push('tileset:'+i+':'+tileName);
pageNames.push(tileName);
}
if(tilesetData.length){
objectsArr.push(...tilesetData);
}
return {
objectsArr,pageNames,size,m,x0Num
};
};
MapDecorator.ALL_TILESET_FILES = null;
MapDecorator.objectPaletteAll = function(){
var size = MapDecorator.OBJECT_PALETTE_SIZE;
var m = MapDecorator.OBJECT_PALETTE_MARGIN;
var x0Num = MapDecorator.OBJECT_PALETTE_EMPTY_NUM;
var pageNames = [];
var objectsArr = [];
if(!MapDecorator.ALL_TILESET_FILES){
MapDecorator.ALL_TILESET_FILES = [];
var files = _Dev.readdirSync('img/tilesets/');
for(const file of files){
if(!file || !/\.png$/.test(file))continue;
if(/_A[1-5]/.test(file))continue;
MapDecorator.ALL_TILESET_FILES.push(file);
}
}
var tilesetData = [];
for(const image of MapDecorator.ALL_TILESET_FILES){
var tileName = image.replace('.png','');
tilesetData.push('tileset:-1:'+tileName)
pageNames.push(tileName);
}
if(tilesetData.length){
objectsArr.push(...tilesetData);
}
return {
objectsArr,pageNames,size,m,x0Num
};
};
MapDecorator.objectPaletteGroup = function(){
var size = MapDecorator.OBJECT_PALETTE_SIZE;
var m = MapDecorator.OBJECT_PALETTE_MARGIN;
var x0Num = MapDecorator.OBJECT_PALETTE_EMPTY_NUM;
var pageNames = [];
var objectsArr = [];
var categories = $dataTrpMapObjectGroups.data;
var keys = Object.keys(categories);
if(keys.length===0)return null;
keys.sort();
//palette
for(const key of keys){
var categoryData = categories[key];
var objects = [];
for(var gi=0; gi<categoryData.length; gi=(gi+1)|0){
// objects.push('G::'+key+'::'+gi);
var data = categoryData[gi];
if(!data)continue;
var obj = MapObject.objectFromGroupData(data);
obj.cachable = true;
objects.push(obj);
}
if(objects.length===0)continue;
objectsArr.push(objects);
pageNames.push(key+' (%1)'.format(categoryData.length));
}
return {
objectsArr,pageNames,size,m,x0Num
};
};
MapDecorator.updateInputObjectPalette = function(){
return true;
}
MapDecorator.onMouseDownLeftObjectPalette = function(event,i,x,y,tx,ty){
this.onMouseDownLeftPaletteCommon(event,i,x,y,tx,ty);
};
MapDecorator.onMouseDownRightObjectPalette = function(event,i,x,y,tx,ty){
var selected = false;
if(MapDecorator.lastObjPaletteCategory==='group'){
this.onMouseDownLeftPaletteCommon(event,i,x,y,tx,ty,(obj,idx)=>{
if(!obj)return;
selected = true;
var palette = this.showingPalette;
TRP_CORE.uniquePush(palette.selected[palette.pageIdx],idx)
this.refreshPaletteBackSprite();
palette.editingObj = obj;
obj.cachable = false;
_Dev.showToolsWindowWithId('decorator:objGroup',()=>{
if(palette.selected){
TRP_CORE.remove(palette.selected[palette.pageIdx],idx);
this.refreshPaletteBackSprite();
}
TouchInput.clear();
palette.editingObj = null;
});
SoundManager.playCancel();
});
}
if(!selected){
SoundManager.playCancel();
this.restoreMode();
}
};
MapDecorator.onSelectEditMapObjectGroup = function(){
var palette = this.showingPalette;
if(!palette || !palette.editingObj)return;
var obj = palette.editingObj;
this.setMode('objectGrouping',{
editObject:obj,
});
}
MapDecorator.onSelectDeleteMapObjectGroup = function(){
var palette = this.showingPalette;
if(!palette || !palette.editingObj)return;
var obj = palette.editingObj;
if(!confirm('本当に画像とデータを削除しますか?\nマップに配置済みのオブジェクトは表示されなくなります。'))return;
var category = obj.characterName.replace('G::','');
var dataIdx = obj.characterIndex;
var categories = $dataTrpMapObjectGroups.data[category];
if(!categories)return;
//save groupData
categories[dataIdx] = null;
_Dev.saveFile($dataTrpMapObjectGroups,MapObject.GROUP_DATA_PATH);
//save image
var fileName = category+'_'+dataIdx.padZero(4)+'.png';
var filePath = MapObject.IMAGE_DIR+fileName;
_Dev.removeFile(filePath);
SoundManager.playSave();
//refresh ui
var idx = palette.objectsArr[palette.pageIdx].indexOf(obj);
TRP_CORE.remove(palette.objectsArr[palette.pageIdx],obj);
TRP_CORE.remove(palette.selected[palette.pageIdx],idx);
this.refreshPaletteObjects();
};
//register main menu
_Dev.registerToolCommands({
key:'',
id:'decorator:objGroup',
name:'グループデータ編集',
commands:[{
name:'衝突判定の編集',
type:'script',
param:'TRP_MapDecorator.onSelectEditMapObjectGroup()'
,key:'',
closeWindow:true,
},{
name:'画像&データ削除',
type:'script',
param:'TRP_MapDecorator.onSelectDeleteMapObjectGroup()'
,key:'',
closeWindow:true,
}],
});
MapDecorator.onKeyDownObjectPalette = function(event){
var modeData = this.modeData;
if(!modeData)return;
if(event.ctrlKey && event.key==='g'){
if(MapObject && $dataTrpMapObjectGroups){
if(MapDecorator.lastObjPaletteCategory==='group'){
this.showObjectPalette('main')
}else{
this.showObjectPalette('group')
}
}
}else if(event.ctrlKey && event.key==='a'){
if(MapDecorator.lastObjPaletteCategory==='all'){
this.showObjectPalette('main')
}else{
this.showObjectPalette('all')
}
}else if(MapDecorator.lastObjPaletteCategory==='main'){
if(event.key==='b'){
this.trySwitchPalettePageForTilesetNumber(5);
}else if(event.key==='c'){
this.trySwitchPalettePageForTilesetNumber(6);
}else if(event.key==='d'){
this.trySwitchPalettePageForTilesetNumber(7);
}else if(event.key==='e'){
this.trySwitchPalettePageForTilesetNumber(8);
}
}
};
//=============================================================================
// MODE: ObjectSelect
//=============================================================================
MapDecorator.MODE_GUIDE.objectSelect = [
'【オブジェクト選択モード】',
'左ドラッグ:オブジェクトをグループ選択',
'左クリック:オブジェクト選択/解除',
'Esc/右クリック:モード終了',
];
MapDecorator.startObjectSelectMode = function(){
this.setMode('objectSelect');
};
MapDecorator.setModeObjectSelect = function(){
if(!this.modeData){
this.modeData = {
type:'objectSelect',
touching:null,
selected:[],
};
}
};
MapDecorator.endModeObjectSelect = function(){
if(!this.modeData)return;
if(this.modeUICache.selectGraphic){
var graphic = this.modeUICache.selectGraphic;
if(graphic.parent){
graphic.parent.removeChild(graphic);
}
}
this.removeObjectsOutline();
_Dev.showText('objectSelected',null);
};
MapDecorator.onMouseDownRightObjectSelect = function(){
SoundManager.playCancel();
this.restoreMode();
};
MapDecorator.onKeyDownObjectSelect = function(event){
if(!this.modeData)return;
if(event.key==='Escape'){
SoundManager.playCancel();
this.restoreMode();
Input.clear();
}else if(event.key==='g'){
this.tryGroupingObjects();
}else if(event.key==='Backspace'){
if(!this.modeData.selected.length){
SoundManager.playBuzzer();
}else{
//removeObjects
this.deleteMapObjects(this.modeData.selected);
this.saveState('オブジェ消去');
SoundManager.playCursor();
this.restoreMode(true);
Input.clear();
}
}
};
MapDecorator.deleteMapObjects = function(objects){
//removeObjects
for(const objInfo of objects){
for(const objInfoArr of proc.lastObjInfoArr){
if(!objInfoArr)continue;
if(TRP_CORE.remove(objInfoArr,objInfo)){
MapObject.remove(objInfo[1]);
break;
}
}
}
}
//leftClick -> start select
MapDecorator.onMouseDownLeftObjectSelect = function(event,roomId,x,y,tx,ty,dx,dy){
if(!this.modeData)return;
if(this.onKeyControl){
if(this.tryStartManualLocateMode(event,roomId,x,y,tx,ty,dx,dy)){
SoundManager.playCursor();
}else{
SoundManager.playBuzzer();
}
return;
}
this.modeData.touching = {
dragging:false,
shift:Input.isPressed('shift'),
dragging:false,
tx0:tx,
ty0:ty,
tx1:tx,
ty1:ty,
};
};
//press
MapDecorator.onMousePressObjectSelect = function(event,roomId,x,y,tx,ty){
if(!this.modeData)return;
var modeData = this.modeData;
var touching = modeData.touching;
if(!touching)return;
var modeUICache = this.modeUICache;
var tx0 = touching.tx0;
var ty0 = touching.ty0;
var tx1 = touching.tx1 = tx;
var ty1 = touching.ty1 = ty;
touching.dragging = touching.dragging||(Math.abs(tx1-tx0)+Math.abs(ty1-ty0)>=3);
if(touching.dragging){
if(!modeUICache.selectGraphic){
modeUICache.selectGraphic = new PIXI.Graphics();
modeUICache.selectGraphic.z = 999;
}
SceneManager._scene._spriteset._tilemap.addChild(modeUICache.selectGraphic);
var graphic = modeUICache.selectGraphic;
graphic.clear();
graphic.beginFill(0x5555ff,0.5)
.drawRect(tx0,ty0,tx-tx0,ty-ty0);
}
}
//keyUp -> execSelect
MapDecorator.onMouseUpObjectSelect = function(){
var modeData = this.modeData;
if(!modeData)return;
var modeUICache = this.modeUICache;
if(modeUICache.selectGraphic){
if(modeUICache.selectGraphic.parent){
modeUICache.selectGraphic.parent.removeChild(modeUICache.selectGraphic);
}
}
var touching = modeData.touching;
if(!touching)return;
var tx0 = Math.min(touching.tx0,touching.tx1);
var tx1 = Math.max(touching.tx0,touching.tx1);
var ty0 = Math.min(touching.ty0,touching.ty1);
var ty1 = Math.max(touching.ty0,touching.ty1);
var x0 = $gameMap._displayX*tileW+tx0/SETTING.mapDispRange;
var y0 = $gameMap._displayY*tileH+ty0/SETTING.mapDispRange;
var x1,y1;
var drag = touching.dragging;
if(drag){
x1 = $gameMap._displayX*tileW+tx1/SETTING.mapDispRange;
y1 = $gameMap._displayY*tileH+ty1/SETTING.mapDispRange;
}
var newSelected = [];
var converted = false;
var bestTargetInfo = null;
var bestDist = Number.MAX_SAFE_INTEGER;
for(const objInfoArr of proc.lastObjInfoArr){
if(!objInfoArr)continue;
for(const objInfo of objInfoArr){
if(Array.isArray(objInfo[1])){
var obj = this._convertTileIdsArrToMapObject(objInfo[1],objInfo[0]);
if(!obj)continue;
MapObject.tryAdd(obj);
SceneManager._scene._spriteset.updateTrpMapObjects();
converted = true;
objInfo[1] = obj;
}
if(this.checkObjectInfoTouch(objInfo,x0,y0,x1,y1,drag ? null : (ax,ay)=>{
//click -> searchBestDist obj
var dist = Math.abs(ax-x0)+Math.abs(ay-y0);
if(dist<bestDist){
bestDist = dist;
bestTargetInfo = objInfo;
}
})){
if(drag){
newSelected.push(objInfo);
}
}
}
}
var selected = this.modeData.selected;
if(drag && !touching.shift){
//once reset selected
this.removeObjectsOutline()
selected.length = 0;
}
if(!drag){
var target = bestTargetInfo;
if(!target)return;
if(selected.contains(target)){
TRP_CORE.remove(selected,target);
}else{
selected.push(target);
}
}else{
selected.push(...newSelected);
}
if(converted){
this.restoreMap(true);
}
this.removeObjectsOutline();
for(const objInfo of selected){
objInfo[1].setOutlineFilter(0x0000ff,2);
}
if(newSelected.length || bestTargetInfo){
SoundManager.playCursor();
}
if(selected.length){
_Dev.showText('objectSelected',[
'Gキーグループ化',
'Backspace削除',
]);
}
this.saveState('オブジェ選択');
};
MapDecorator._convertTileIdsArrToMapObject = function(tileIds,idx=0,refreshMap=false){
if(!tileIds)return null;
var template = this.mapObjectTemplateWithTileObject(tileIds,true);
if(!template)return null;
var obj = template.copy();
var x = idx%width;
var y = Math.floor(idx/width);
obj.x = (x+obj.tileW/2)*tileW;
obj.y = (y+obj.tileH)*tileH;
if(refreshMap){
SceneManager._scene._spriteset.updateTrpMapObjects();
this.restoreMap(true);
}
return obj;
};
/* grouping
===================================*/
MapDecorator.tryGroupingObjects = function(){
var modeData = this.modeData;
if(!modeData || !modeData.selected)return;
var selected = modeData.selected;
if(selected.length===0){
SoundManager.playBuzzer();
return;
}
for(const objInfo of selected){
if(!objInfo[1].sprite){
SoundManager.playBuzzer();
_Dev.showText('すべてのオブジェクトが画面上に入っている必要があります!');
return;
}
}
this.removeObjectsOutline();
this.setMode('objectGrouping',{
selected,
});
};
//=============================================================================
// MODE: ObjectGrouping
//=============================================================================
MapDecorator.MODE_GUIDE.objectGrouping = [
'【オブジェクトグループ登録】',
'Sキーグループ登録&画像保存',
'Tキータイルセット画像に登録',
'└※衝突判定は保存されません',
'右クリック:キャンセル',
];
MapDecorator.HELP_OBJ_GROUPING_PARAMS = [
'左クリック/ドラッグ:衝突判定切り替え',
'Shift+左クリック:水平方向の中心変更',
'Eプライオリティ変更<%priority>',
'Bブレンドモード変更<%blend>',
];
MapDecorator.refreshObjectGroupParamsGuide = function(){
var modeData = this.modeData;
if(!modeData)return;
var guide = MapDecorator.HELP_OBJ_GROUPING_PARAMS.concat();
for(var i=guide.length-1; i>=0; i=(i-1)|0){
guide[i] = guide[i]
.replace('%priority',modeData.priority)
.replace('%blend',modeData.blendMode)
}
_Dev.showText('objGroupingParams',guide);
};
MapDecorator.endModeObjectGrouping = function(){
var screen = this.modeUICache.screen;
if(screen && screen.parent){
screen.parent.removeChild(screen);
}
var screen = this.modeUICache.topScreen;
if(screen && screen.parent){
screen.parent.removeChild(screen);
}
_Dev.showText('objGroupingParams',null);
};
MapDecorator.objectRect = function(s,obj){
var ax = s.anchor.x;
var ay = s.anchor.y;
var ox = obj.x+obj.aX;
var oy = obj.y+obj.aY;
var ox0 = -ax*s.scale.x*s.width;
var ox1 = (1-ax)*s.scale.x*s.width;
var oy0 = -ay*s.scale.y*s.height;
var oy1 = (1-ay)*s.scale.y*s.height;
if(s.rotation){
var cos = Math.cos(s.rotation);
var sin = Math.sin(s.rotation);
var arr = [[ox0,oy0],[ox0,oy1],[ox1,oy0],[ox1,oy1]];
ox0 = oy0 = Number.MAX_SAFE_INTEGER;
ox1 = oy1 = Number.MIN_SAFE_INTEGER;
for(const pos of arr){
var x = cos*pos[0] - sin*pos[1];
var y = sin*pos[0] + cos*pos[1];
if(x<ox0)ox0 = x;
if(x>ox1)ox1 = x;
if(y<oy0)oy0 = y;
if(y>oy1)oy1 = y;
}
}
return [ox+ox0,oy+oy0,ox+ox1,oy+oy1];
};
MapDecorator.setModeObjectGrouping = function(){
if(!this.modeData)return false;
var selected = this.modeData.selected;
var editObj = this.modeData.editObject;
/* confirmScreen
===================================*/
var screen = new PIXI.Graphics();
SceneManager._scene.addChild(screen);
_Dev.prepareDebugTextContainer();
/* calc rects
===================================*/
var objects = [];
var priority = 2;
var blendMode = 0;
var collisions = null;
var originalX,originalY,dx,dy,cx;
var sprite,bitmap;
// var mockMap = null;
// var mock = null;
if(selected){
/* analyze objects
===================================*/
var x0,x1,y0,y1;
x0 = y0 = Number.MAX_SAFE_INTEGER;
x1 = y1 = Number.MIN_SAFE_INTEGER;
// var mock = {tileId:0,w:0,h:0,x0:0,y0:0};
for(const objInfo of selected){
var obj = objInfo[1];
objects.push(obj);
var s = obj.sprite;
var rect = MapDecorator.objectRect(s,obj);
x0 = Math.min(x0,rect[0]);
y0 = Math.min(y0,rect[1]);
x1 = Math.max(x1,rect[2]);
y1 = Math.max(y1,rect[3]);
if(obj.priority===1){
priority = 1;
}else if(priority!==1){
priority = Math.min(priority,obj.priority);
}
if(obj.blendMode){
blendMode = obj.blendMode;
}
//search mock
// if(obj.tileId>0){
// if(obj.tileW*obj.tileH>mock.w*mock.h){
// mock.tileId = obj.tileId;
// mock.w = obj.tileW;
// mock.h = obj.tileH;
// mock.x0 = obj.x-s.width*s.scale.x*s.anchor.x;
// mock.y0 = obj.y-s.height*s.scale.y*s.anchor.y;
// }
// }
}
originalX = x0;
originalY = y0;
/* move objects
===================================*/
dx = -x0;
dy = -y0;
x0 += dx;
x1 += dx;
y0 += dy;
y1 += dy;
var w = Math.ceil(x1-x0);
var h = Math.ceil(y1-y0);
sprite = new Sprite();
var orgParents = [];
for(const obj of objects){
obj.sprite.x = obj.x+obj.aX+dx;
obj.sprite.y = obj.y+obj.aY+dy;
orgParents.push(obj.sprite.parent);
sprite.addChild(obj.sprite);
obj.removeOutlineFilter();
}
sprite.children.sort((a,b)=>{
if(a.z!==b.z)return a.z-b.z;
if(a.y!==b.y)return a.y-b.y;
return (a.spriteId - b.spriteId)||0;
});
/* trim empty pixel
===================================*/
var bitmap = TRP_CORE.snap(sprite,w,h);
var data = bitmap.context.getImageData(0,0,w,h).data;
var trimX0 = w;
var trimY0 = h;
var trimX1 = 0;
var trimY1 = 0;
for(var i=0; i<data.length; i=(i+4)|0){
var x = (i/4)%w;
var y = Math.floor((i/4)/w);
if(data[i+3]){
if(x<trimX0)trimX0 = x;
if(x>trimX1)trimX1 = x;
if(y<trimY0)trimY0 = y;
if(y>trimY1)trimY1 = y;
}
}
dx -= trimX0;
dy -= trimY0;
w = trimX1-trimX0;
h = trimY1-trimY0;
originalX += trimX0;
originalY += trimY0;
// mock.x0 += dx;
// mock.y0 += dy;
// if(mock.tileId){
// mockMap = {};
// var tilesetNumber = 5+Math.floor(mock.tileId/256);
// mock.tileId = mock.tileId%256;
// var tilesetName = $gameMap.tileset().tilesetNames[tilesetNumber];
// MapObject.registerObjectGroupTilesetImage(tilesetName);
// var tilesetImageId = $dataTrpMapObjectGroups.tilesetImageIds.indexOf(tilesetName);
// mockMap[tilesetImageId] = mock;
// }
w = Math.ceil(w/2)*2;
h = Math.ceil(h/2)*2;
cx = Math.floor(w/2);
var trimmedBitmap = new Bitmap(w,h);
// trimmedBitmap.fillAll('rgba(0,255,0,0.5)');
trimmedBitmap.blt(bitmap,trimX0,trimY0,w,h,0,0);
bitmap = trimmedBitmap;
sprite = new Sprite(bitmap);
/* restoreObjects
===================================*/
for(const obj of objects){
obj.sprite.x = obj.x+obj.aX-$gameMap._displayX*tileW;
obj.sprite.y = obj.y+obj.aY-$gameMap._displayY*tileH;
orgParents.shift().addChild(obj.sprite);
}
}else{
priority = editObj.priority;
blendMode = editObj.blendMode;
editObj.setupSprite(null);
sprite = editObj.sprite;
bitmap = sprite.bitmap;
originalX = originalY = 0;
dx = dy = 0;
w = bitmap.width;
h = bitmap.height;
cx = editObj.anchorX*editObj.spriteW;
if(editObj._collisions){
collisions = TRP_CORE.packValues([],0,(width*4)*(height*4));
var rowIdx = 0;
for(const row of editObj._collisions){
var colIdx = 0;
for(const flag of row){
collisions[rowIdx*width*4 + (colIdx++)] = flag;
}
rowIdx++;
}
}
// var category = editObj.characterName.replace('G::','');
// var groupData = $dataTrpMapObjectGroups.data[category][editObj.characterIndex];
// mockMap = groupData[MapObject.GROUP_OBJ_IDXES.indexOf(mock)];
// mock = MapObject.activeMockDataOfMockMap(mockMap);
// if(mock){
// mock.x0 += cx;
// }
}
sprite.anchor.set(0.5,0.5);
sprite.x = Graphics.width/2;
sprite.y = Graphics.height/2;
screen.addChild(sprite);
this.modeData.cx = cx;
this.modeData.originalX = originalX;
this.modeData.originalY = originalY;
this.modeData.w = w;
this.modeData.h = h;
this.modeData.dx = dx;
this.modeData.dy = dy;
this.modeData.collisions = collisions;
this.modeData.objects = objects.map(obj=>obj.copy());
this.modeData.priority = priority;
this.modeData.blendMode = blendMode;
// this.modeData.mockMap = mockMap
// this.modeData.mock = (mock&&mock.tileId) ? mock : null;
this.modeUICache.bitmap = bitmap;
this.modeUICache.sprite = sprite;
this.modeUICache.screen = screen;
this.modeUICache.groupSprite = sprite;
this.modeUICache.groupBitmap = bitmap;
this.modeUICache.topScreen = new PIXI.Graphics();
this.refreshObjectGroupParamsGuide();
this._refreshObjectGroupingScreen();
SoundManager.playCursor();
};
MapDecorator.quitObjectGroupingMode = function(){
var modeData = this.modeData;
if(!modeData)return;
if(modeData.selected){
for(const objInfo of modeData.selected){
objInfo[1].setOutlineFilter(0x0000ff,2);
}
this.setMode('objectSelect',{
type:'objectSelect',
touching:null,
selected:modeData.selected,
});
}else{
this.setMode('manualLocate');
}
};
MapDecorator.onMouseDownRightObjectGrouping = function(){
this.quitObjectGroupingMode();
SoundManager.playCancel();
};
MapDecorator.onMouseDownLeftObjectGrouping = function(event,roomId,x,y,tx,ty,dx,dy){
var modeData = this.modeData;
if(!modeData)return;
modeData.lastEditCollisionIdx = -1;
modeData.lastEditCollisionFlag = false;
if(Input.isPressed('shift')){
//change anchor x
var {w,h} = modeData;
var x0 = Graphics.width/2-w/2;
var y0 = Graphics.height/2-h/2;
if(tx<x0 || tx>x0+w){
SoundManager.playBuzzer();
return;
}
modeData.cx = tx-x0;
SoundManager.playCursor();
modeData.lastEditCollisionIdx = -1;
modeData.collisions = null;
modeData.collisionRects = null;
SoundManager.playCursor();
this._refreshObjectGroupingScreen();
}else{
var idx = this.objectGroupingTouchCollisionPosition(tx,ty);
if(idx<0)return;
var c0 = idx%(width*4);
var r0 = Math.floor(idx/(width*4));
var flag = !modeData.collisions[idx];
this.modeData.collisionEdit = {
flag,
c0:c0,
r0:r0,
c1:c0,
r1:r0,
lastIdx:idx,
collisions0:modeData.collisions.concat(),
};
if(modeData.priority!==1){
modeData.priority = 1;
this.refreshObjectGroupParamsGuide();
}
modeData.collisions[idx] = flag;
SoundManager.playCursor();
this._refreshObjectGroupingScreen();
}
};
MapDecorator.onMousePressObjectGrouping = function(event,roomId,x,y,tx,ty,dx,dy){
var modeData = this.modeData;
if(!modeData)return;
if(Input.isPressed('shift'))return;
if(this.onKeyControl||this.onKeyAlt||this.onKeyMeta)return;
/* edit collisions
===================================*/
var editData = modeData.collisionEdit;
if(editData){
var idx = this.objectGroupingTouchCollisionPosition(tx,ty);
if(idx<0)return;
if(editData.lastIdx===idx)return;
editData.lastIdx = idx;
var tc = idx%(width*4);
var tr = Math.floor(idx/(width*4));
var c0 = Math.min(tc,editData.c0);
var c1 = Math.max(tc,editData.c0);
var r0 = Math.min(tr,editData.r0);
var r1 = Math.max(tr,editData.r0);
//reset collisions
var collisions = modeData.collisions;
collisions.length = 0;
collisions.push(...(editData.collisions0));
//switch collisions
var flag = editData.flag;
for(var c=c0; c<=c1; c=(c+1)|0){
for(var r=r0; r<=r1; r=(r+1)|0){
var i = c+r*width*4;
collisions[i] = flag;
}
}
SoundManager.playCursor();
this._refreshObjectGroupingScreen();
}
};
MapDecorator.onMouseUpObjectGrouping = function(event){
if(this.modeData){
this.modeData.collisionEdit = null;
}
};
MapDecorator.objectGroupingTouchCollisionPosition = function(tx,ty){
var modeData = this.modeData;
if(!modeData)return -1;
var rects = modeData.collisionRects;
for(var i=rects.length-1; i>=0; i=(i-1)|0){
var rect = rects[i];
if(tx<rect[0])continue;
if(tx>=rect[0]+rect[2])continue;
if(ty<rect[1])continue;
if(ty>=rect[1]+rect[3])continue;
var collisionX = tx-modeData.collisionX0;
var collisionY = ty-modeData.collisionY0;
var col = Math.floor(collisionX/(tileW/4));
var row = Math.floor(collisionY/(tileH/4));
var idx = col+row*width*4;
return idx;
};
return -1;
};
MapDecorator.onKeyDownObjectGrouping = function(event){
var refreshParams = false;
if(event.key==='Escape'){
this.quitObjectGroupingMode();
SoundManager.playCancel();
}else if(event.key === 't'){
this.startTilesetEdit(this.modeUICache.bitmap);
SoundManager.playCursor();
}else if(event.key==='s'){
this.saveObjectGroup();
}else if(event.key==='e'){
//changePriority
this.modeData.priority += 1;
if(this.modeData.priority>2){
this.modeData.priority = 0;
}
this._refreshObjectGroupingScreen();
refreshParams = true;
}else if(event.key==='b'){
this.modeData.blendMode += 1;
if(this.modeData.blendMode>4){
this.modeData.blendMode = 0;
}
TRP_CORE.setBlendMode(this.modeUICache.sprite,this.modeData.blendMode);
refreshParams = true;
}
if(refreshParams){
this.refreshObjectGroupParamsGuide();
SoundManager.playCursor();
}
};
MapDecorator._refreshObjectGroupingScreen = function(){
var modeData = this.modeData;
if(!modeData)return;
var screen = this.modeUICache.screen;
var topScreen = this.modeUICache.topScreen;
SceneManager._scene.addChild(topScreen);
topScreen.clear();
screen.clear();
screen.beginFill(0x000000,0.8)
.drawRect(0,0,Graphics.width,Graphics.height);
var {w,h} = modeData;
var uw = tileW/4;
var uh = tileH/4;
var x0 = Graphics.width/2-w/2;
var y0 = Graphics.height/2-h/2;
var y1 = Graphics.height/2+h/2;
var cx = x0 + modeData.cx;
var x = cx-Math.ceil((cx-x0)/uw)*uw;
var y = y1-Math.ceil(h/uh)*uh;
modeData.collisionX0 = x;
modeData.collisionY0 = y;
//anchor line
topScreen.beginFill(0x0000ff)
.drawRect(cx,0,1,Graphics.height);
//calc collisions
var collisions = modeData.collisions;
if(!collisions){
var cacheMapObjects = $dataTrpMapObjects;
var objects = $dataTrpMapObjects = modeData.objects;
var dx = modeData.dx + modeData.cx%uw;
var dy = modeData.dy + y1%uh;
for(const obj of objects){
obj.x += dx;
obj.y += dy;
}
collisions = MapObject.collisionsMap();
modeData.collisions = collisions;
//restore collisions
$dataTrpMapObjects = cacheMapObjects;
for(const obj of objects){
obj.x -= dx;
obj.y -= dy;
}
}
//draw back
var col = 0;
var collisionRects = modeData.collisionRects = [];
for(var tx=x; tx<x0+w; tx+=uw){
var tw = uw;
var row = 0;
for(var ty=y; ty<y0+h; ty+=uh){
var th = uh;
var colorIdx = (row+col)%2;
screen.beginFill(colorIdx===0 ? 0xdcdcdc : 0xffffff)
.drawRect(tx,ty,tw,th);
collisionRects.push([tx,ty,tw,th]);
row++;
}
col++;
}
modeData.collisionRow = row;
modeData.collisionCol = col;
//draw lines
var c = 0;
for(var tx=x; tx<=x0+w; tx+=uw){
if(c%4===0){
topScreen.beginFill(0x000000)
.drawRect(tx,y,1,row*uh);
}
c++;
}
var r = 0;
for(var ty=y; ty<=y0+h; ty+=uh){
if((row-r)%4===0){
topScreen.beginFill(0x000000)
.drawRect(x,ty,col*uh,1);
}
r++;
}
//draw collisions
var length = collisions.length;
for(var i=0; i<length; i=(i+1)|0){
if(!collisions[i])continue;
var c = i%(4*width);
var r = Math.floor(i/(4*width));
if(modeData.priority===1){
topScreen.beginFill(0xff0000,0.6)
.drawRect(x+c*uw,y+r*uh,uw-1,uh-1);
}
}
};
/* saveObjectGroup
===================================*/
MapDecorator.saveObjectGroup = function(){
var modeData = this.modeData;
if(!modeData)return;
var sprite = this.modeUICache.sprite;
var bitmap = this.modeUICache.bitmap;
var dataIdx = -1;
var category,categoryData;
if(modeData.selected){
/* new register
===================================*/
SoundManager.playCursor();
var categories = Object.keys($dataTrpMapObjectGroups.data);
// categories.sort((a,b)=>{
// return $dataTrpMapObjectGroups.data[a].length-$dataTrpMapObjectGroups.data[b].length;
// });
var text = 'カテゴリ名または番号を入力してください。';
var length = Math.min(10,categories.length);
for(var i=0; i<length; i=(i+1)|0){
text += '\n';
var num = 0;
$dataTrpMapObjectGroups.data[categories[i]].forEach(d=>{if(d)num+=1});
text += (i+1)+':'+categories[i]+'%1個'.format(num);
}
var fileName;
while(true){
category = prompt(text,'object');
if(!category){
SoundManager.playCancel();
return;
}
category = fileName = category ? category.trim() : null;
if(!isNaN(category)){
category = fileName = categories[Number(category)-1];
if(!category){
SoundManager.playBuzzer();
continue;
}
}
if(!fileName){
SoundManager.playCancel();
return;
}
categoryData = $dataTrpMapObjectGroups.data[category];
if(categoryData){
fileName += '_'+(categoryData.length).padZero(4)+'.png';
break;
}else{
fileName += '_0000.png';
if(confirm(
'このカテゴリに保存済みのデータはありません。\n'
+ 'ファイル名「'+fileName+'」で保存しますか?'
)){
categoryData = $dataTrpMapObjectGroups.data[category] = [];
break;
}
}
}
//save image
var filePath = MapObject.IMAGE_DIR+fileName;
_Dev.ensureDirectoriesWithFilePath(filePath);
_Dev.saveCanvas(bitmap,filePath);
}else{
var editObject = modeData.editObject;
category = editObject.characterName.replace('G::','');
dataIdx = editObject.characterIndex;
categoryData = $dataTrpMapObjectGroups.data[category];
}
var collisions = null;
if(modeData.priority===1){
var row = modeData.collisionRow;
var col = modeData.collisionCol;
collisions = [];
for(var r=0; r<row; r=(r+1)|0){
var rowFlags = [];
collisions.push(rowFlags);
for(var c=0; c<col; c=(c+1)|0){
var collisionIdx = c+r*width*4;
rowFlags.push(modeData.collisions[collisionIdx]?1:0);
}
}
}
if(dataIdx<0){
dataIdx = categoryData.length;
}
// if(modeData.mock){
// modeData.mock.x0 -= modeData.cx;
// }
var objData = {
characterName:'G::'+category,
characterIndex:dataIdx,
blendMode:modeData.blendMode,
priority:modeData.priority,
cx:modeData.cx,
_collisions:collisions,
tileW:bitmap.width,
tileH:bitmap.height,
// mock:modeData.mockMap,
}
var dataArr = MapObject.GROUP_OBJ_IDXES.map(key=>objData[key]);
categoryData[dataIdx] = dataArr;
// save $dataTrpMapObjectGroups
_Dev.saveFile($dataTrpMapObjectGroups,MapObject.GROUP_DATA_PATH);
//save assets
var assets = [];
var categories = Object.keys($dataTrpMapObjectGroups.data);
for(const category of categories){
var groupArr = $dataTrpMapObjectGroups.data[category];
var groupLen = groupArr.length;
for(var gi=0; gi<groupLen; gi=(gi+1)|0){
if(!groupArr[gi])continue;
assets.push('img/trp_map_objects/'+category+'_'+(gi).padZero(4));
}
}
_Dev.setCategoryAllAssets('mapObjectGroup',assets);
var selected = this.modeData.selected;
//mode -> manualLocate
this.setMode('manualLocate');
// this.quitObjectGroupingMode();
/* replace selected->GroupObj
===================================*/
if(selected){
var obj = MapObject.objectFromGroupData(dataArr,true);
var x = modeData.originalX;
var y = modeData.originalY;
obj.x = x+obj.anchorX*obj.spriteW;
obj.y = y+obj.anchorY*obj.spriteH;
var tx = Math.floor(obj.x/tileW);
var ty = Math.ceil(obj.y/tileH);
var idx = tx+width*ty;
var dx = obj.x - (tx+1/2)*tileW;
var dy = obj.y - (ty+1)*tileH;
var roomId = proc.roomIdxMapForUserProc[idx];
if(roomId>=0){
this.deleteMapObjects(selected);
proc.lastObjInfoArr[roomId] = proc.lastObjInfoArr[roomId]||[];
proc.lastObjInfoArr[roomId].push([idx,obj,dx,dy]);
// this.registerMapObjectTemplateWithMapObject(obj);
obj.setupCommonAfter();
this.restoreMap(true);
}else{
MapObject.cache(obj);
}
}else{
//update objSetting
var editObject = modeData.editObject;
var cx = modeData.cx;
var anchorX = cx/editObject.spriteW;
for(const obj of $dataTrpMapObjects){
if(editObject.characterName!==obj.characterName)continue;
if(editObject.characterIndex!==obj.characterIndex)continue;
obj.blendMode = editObject.blendMode;
obj.priority = editObject.priority;
obj._collisions = collisions ? collisions.concat() : null;
var objCx = obj.anchorX*obj.spriteW;
if(cx!==objCx){
obj.anchorX = anchorX;
obj.x += cx-objCx;
if(obj.sprite){
obj.sprite.x += cx-objCx;
}
}
obj.tryRefreshSpriteState();
}
}
this.saveState('オブジェグループ化');
SoundManager.playSave();
};
//=============================================================================
// MODE: UserProcess
//=============================================================================
MapDecorator.MODE_GUIDE.userProcess = [
'【置換プロセスモード】',
'左クリック:置換やり直し',
'右クリック:ロック',
'Esc:モード終了',
'※置換処理は"抽選作業の途中"に行わないこと',
];
MapDecorator.clearUserProcessParams = function(){
var modeData = this.modeData = this.modeData||{};
modeData.type = 'userProcess';
modeData.timing = null;
modeData.lastProc = null;
modeData.lockedRoomIds = [];
modeData.lockedResults = [];
modeData.lockedAllResults = [];
modeData.lastResults = null;
};
MapDecorator.startUserProcessMode = function(timing,once=false){
if(!MapDecorator.processList[timing]){
SoundManager.playBuzzer();
return;
}
if(once){
this.processUserProcessList(timing);
originalData = data.concat();
SoundManager.playOk();
this.saveState('置換プロセス実行');
}else{
this.setMode('userProcess');
this.clearUserProcessParams();
this.modeData.timing = timing;
this.saveState('置換プロセスモード開始');
}
};
MapDecorator.updateInputUserProcess = function(){
if(Input.isTriggered('cancel')){
originalData = data.concat();
this.restoreMode();
SoundManager.playCancel();
Input.clear();
return true;
}else{
return false;
}
};
MapDecorator.onMouseDownLeftUserProcess = function(event,i,x,y,tx,ty){
if(Input.isPressed('shift')){
}else{
//exec process
var modeData = this.modeData;
if(modeData.lastProc){
data.length = 0;
data.push(...originalData);
proc = modeData.lastProc;
}else{
modeData.lastProc = JsonEx.makeDeepCopy(proc);
}
var allResults = modeData.lockedAllResults;
if(allResults.length){
this.processUserProcessListWithResults(allResults);
}
modeData.lastResults = this.processUserProcessList(modeData.timing,modeData.lockedRoomIds,true);
this.saveState('置換プロセス実行');
SoundManager.playCursor();
}
};
MapDecorator.onMouseDownRightUserProcess = function(event,i,x,y,tx,ty){
var modeData = this.modeData;
if(!this.modeData.lastProc){
SoundManager.playBuzzer();
return;
}
if(i<0){
SoundManager.playBuzzer();
return;
}
if(Input.isPressed('shift')){
//try back to paintFloor
if(modeData.lockedRoomIds.contains(i)){
TRP_CORE.remove(modeData.lockedRoomIds,i);
var results = modeData.lockedResults[i];
TRP_CORE.removeArray(modeData.lockedAllResults,modeData.lockedResults[i]);
modeData.lockedRoomIds[i] = null;
var text = 'プロセスアンロック!';
showInfoText(text);
this.saveState(text);
SoundManager.playCancel();
}else{
SoundManager.playBuzzer();
}
}else if(!modeData.lastProc){
//not processed yet
SoundManager.playBuzzer();
}else if(modeData.lockedRoomIds.contains(i)){
//already locked
SoundManager.playBuzzer();
}else{
//userProc lock
TRP_CORE.uniquePush(modeData.lockedRoomIds,i);
var results = modeData.lockedResults[i] = [];
var allResults = modeData.lockedAllResults;
for(const result of modeData.lastResults){
var idx = result[0];
if(proc.roomIdxMapForUserProc[idx]!==i)continue;
allResults.push(result);
results.push(result);
}
var text = 'プロセスロック!';
showInfoText(text);
this.saveState(text);
SoundManager.playOk();
}
};
//=============================================================================
// User Process
//=============================================================================
var PROCESS_TYPES = MapDecorator.PROCESS_TYPES = {
replace:0,
};
var PROCESS_FLAGS = MapDecorator.PROCESS_FLAGS = {
none:0,
condNot:1,
noShape:2,
noErase:3,
reverseOrder:4,
noConnect:5,
connectFloor:6,
};
MapDecorator.processUserProcessList = function(timing,lockedRoomIds=null,needsResult=false){
var list = MapDecorator.processList[timing];
if(!list)return;
var autoTileIdxes = [];
var resultList = needsResult ? [] : null;
for(const proc of list){
switch(proc.type){
case PROCESS_TYPES.replace:
this.processReplaceTiles(proc,autoTileIdxes,lockedRoomIds,resultList);
break;
}
}
for(const idx of autoTileIdxes){
data[idx] = connectAutoTileWithIdx(idx,1);
}
this.requestRefreshTilemap();
return resultList;
};
MapDecorator.processUserProcessListWithResults = function(results){
var autoTileIdxes = [];
for(const result of results){
var type = result[1];
var params = result[2];
switch(type){
case PROCESS_TYPES.replace:
this.executeReplaceTileIds(...params,autoTileIdxes);
break;
}
}
for(const idx of autoTileIdxes){
data[idx] = connectAutoTileWithIdx(idx,1);
}
};
MapDecorator.quickCheckTileId = function(ids){
if(!ids)return null;
var noShape = false;
var reverseOrder = false;
var tileId = ids[0];
if(Array.isArray(ids[ids.length-1])){
var flags = ids[ids.length-1];
if(flags.contains(PROCESS_FLAGS.condNot)){
return null;
}
if(flags.contains(PROCESS_FLAGS.noShape)){
noShape = true;
tileId = baseTileId(tileId);
}
if(flags.contains(PROCESS_FLAGS.reverseOrder)){
reverseOrder = true;
}
}
if(tileId<=0 || !tileId){
return null;
}
return {
tileId,
noShape,
reverseOrder,
};
}
MapDecorator.processReplaceTiles = function(userProc,autoTileIdxes,lockedRoomIds=null,resultList=null){
var tileIds = userProc.tileIds;
var candidates = userProc.candidates;
var candidatesLen = candidates.length;
var rate = userProc.rate;
if(!candidatesLen || rate<=0)return;
var needsDraw = rate<1;
var w,h;
var isBigObj = Array.isArray(tileIds[0]);
var qIdx = 0;
var quickCheck = null;
var qcFound = false;
var reverseOrder = false;
if(isBigObj){
w = tileIds.length;
h = tileIds[0].length;
for(var dx=0; dx<w&&!qcFound; dx=(dx+1)|0){
for(var dy=0; dy<h&&!qcFound; dy=(dy+1)|0){
var checkInfo = this.quickCheckTileId(tileIds[dx][dy]);
if(!checkInfo)continue;
if(checkInfo.noShape && quickCheck)continue;
qcFound = !checkInfo.noShape;
quickCheck = checkInfo;
qIdx = dx+dy*width;
}
}
}else{
w = h = 1;
quickCheck = this.quickCheckTileId(tileIds);
}
var qcFlag = !!quickCheck;
var qId = quickCheck ? quickCheck.tileId : 0;
var targetTileIds = candidates[0];
var sign = 1;
var x0 = 0;
var y0 = 0;
if(quickCheck && quickCheck.reverseOrder){
sign = -1;
x0 = width-w;
y0 = height-h;
}
for(var xi=0, x=x0; xi<width-w+1; xi=(xi+1)|0, x=(x+sign)|0){
for(var yi=0, y=y0; yi<height-h+1; yi=(yi+1)|0, y=(y+sign)|0){
var idx = x+y*width;
// if(_Dev.inDev && userProc.sx===147 && idx===667){
// debugger;
// }
if(invalidIdxes && invalidIdxes.contains(idx))continue;
if(lockedRoomIds){
var roomId = proc.roomIdxMapForUserProc[idx];
if(roomId>=0 && lockedRoomIds.contains(roomId)){
continue;
}
}
//quick check
if(qcFlag){
if(quickCheck.noShape){
if(!(//noShape
(data[idx+qIdx]&&baseTileId(data[idx+qIdx])===qId)
||(data[idx+qIdx+zAcc]&&baseTileId(data[idx+qIdx+zAcc])===qId)
||(data[idx+qIdx+zObj1]&&baseTileId(data[idx+qIdx+zObj1])===qId)
||(data[idx+qIdx+zObj2]&&baseTileId(data[idx+qIdx+zObj2])===qId))
)continue;
}else{
if(!(data[idx+qIdx]===qId
||data[idx+qIdx+zAcc]===qId
||data[idx+qIdx+zObj1]===qId
||data[idx+qIdx+zObj2]===qId)
)continue;
}
}
//draw rate
if(needsDraw && Math.random()>rate)continue;
//check all tileIds
var checkOk = true;
for(var dx=0; dx<w&&checkOk; dx=(dx+1)|0){
for(var dy=0; dy<h; dy=(dy+1)|0){
if(invalidIdxes && invalidIdxes.contains(idx+dx+dy*width))continue;
if(!this._checkLayeredTileIdsMatchWithFlags(
idx+dx+dy*width,
isBigObj?tileIds[dx][dy]:tileIds,
)){
checkOk = false;
break;
}
}
}
if(!checkOk)continue;
//draw candidates
if(candidatesLen>1){
targetTileIds = candidates[Math.randomInt(candidatesLen)];
}
if(resultList){
resultList.push([idx,PROCESS_TYPES.replace,[isBigObj,tileIds,w,h,targetTileIds,idx,x,y]]);
}
//apply tileIds
this.executeReplaceTileIds(isBigObj,tileIds,w,h,targetTileIds,idx,x,y,autoTileIdxes);
}
}
};
MapDecorator._checkLayeredTileIdsMatchWithFlags = function(idx,tileIds,removeFlag=false){
if(!tileIds)return true;
var flags = Array.isArray(tileIds[tileIds.length-1]) ? tileIds[tileIds.length-1] : null;
var success = true;
var failure = false;
var noShape = false;
if(flags){
if(flags.contains(PROCESS_FLAGS.condNot)){
if(removeFlag)return true;
success = false;
failure = true;
}
if(flags.contains(PROCESS_FLAGS.noShape)){
noShape = true;
}
if(flags.contains(PROCESS_FLAGS.noErase)){
if(removeFlag)return true;
}
}
var usedZ = 0;
var shape = 0;
var bestShape = 0;
var i = tileIds.length-1 - (flags?1:0);
for(; i>=0; i=(i-1)|0){
var tileId = tileIds[i];
if(tileId<0){
if(tileId<=MapDecorator.REGION_ID_BEGIN && tileId>=MapDecorator.REGION_ID_END){
//regionId
if(data[idx+zRegion]!==(-(tileId-MapDecorator.REGION_ID_BEGIN)))return failure;
//match
if(removeFlag)data[idx+zRegion] = 0;
}else if(tileId<=MapDecorator.SHADOW_ID_BEGIN && tileId>=MapDecorator.SHADOW_ID_END){
//shadow
if(data[idx+zShadow]!==(-(tileId-MapDecorator.SHADOW_ID_BEGIN)))return failure;
//match
if(removeFlag)data[idx+zShadow] = 0;
}else{
//invalid tileId
continue;
}
}else{
//normal tile
if(noShape){
tileId = baseTileId(tileId);
}
var found = false;
for(var z=0; z<4; z=(z+1)|0){
if(usedZ & 1<<z)continue;
var tId = data[idx+z*zLayerSize];
if(noShape&&tId){
shape = tId-baseTileId(tId);
tId -= shape;
}
if(tId===tileId){
//match
found = true;
usedZ |= (1<<z);
if(removeFlag){
data[idx+z*zLayerSize] = 0;
}
if(shape){
if(!Tilemap.isWallSideTile(tId)){
bestShape = shape;
}
}
break;
}
}
if(!found)return failure;
}
}
if(removeFlag){
return bestShape;
}else{
return success;
}
};
MapDecorator.executeReplaceTileIds = function(isBigObj,tileIds,w,h,targetTileIds,idx,x,y,autoTileIdxes){
var shapes = null;
var shape = 0;
for(var dx=0; dx<w; dx=(dx+1)|0){
for(var dy=0; dy<h; dy=(dy+1)|0){
shape = this._checkLayeredTileIdsMatchWithFlags(
idx+dx+dy*width,
isBigObj?tileIds[dx][dy]:tileIds,
true//removeFlag
);
if(shape){
//shapes=[deltaIdx,shape,...]
shapes = shapes||[];
shapes.push(dx+dy*width);
shapes.push(shape);
}
}
}
var w1 = isBigObj ? targetTileIds.length : 1;
var h1 = isBigObj ? targetTileIds[0].length : 1;
for(var dx=0; dx<w1; dx=(dx+1)|0){
if(x+dx>=width)continue;
for(var dy=0; dy<h1; dy=(dy+1)|0){
if(y+dy>=height)continue;
if(invalidIdxes && invalidIdxes.contains(idx+dx+dy*width))continue;
if(shapes && shapes[0]===dx+dy*width){
shapes.shift();
shape = shapes.shift();
}
this.applyLayeredTileIdsWithFlags(
idx+dx+dy*width,
isBigObj?targetTileIds[dx][dy]:targetTileIds,
autoTileIdxes,
shape, //for sustainShape(noShape)
);
}
}
};
MapDecorator.applyLayeredTileIdsWithFlags = function(idx,targetTileIds,autoTileIdxes=null,shape=0){
if(!targetTileIds)return;
//flags
var flags = Array.isArray(targetTileIds[targetTileIds.length-1]) ? targetTileIds[targetTileIds.length-1] : null;
var sustainShape=false, noConnect=false;
if(flags){
sustainShape = flags.contains(PROCESS_FLAGS.noShape);
noConnect = flags.contains(PROCESS_FLAGS.noConnect);
if(flags.contains(PROCESS_FLAGS.connectFloor)){
TRP_CORE.uniquePush(proc.connectFloorIdxes,idx);
}
}
//apply
var i = 0;
var maxI = targetTileIds.length-1 - (flags ? 1 : 0);
var needsShadow = false;
for(var z=0; z<4; z=(z+1)|0){
if(data[z*zLayerSize+idx])continue;
var tileId = targetTileIds[i++];
var skip = false;
if(tileId<0){
if(tileId===MapDecorator.SUPPLY_BACK_TILE_ID){
//supply back -> needs z=0 empty
skip = true;
needsShadow = true;
if(z==0){
this.supplyBackTile(idx);
}
}else if(tileId===MapDecorator.NO_ACC_TILE_ID){
//noAcc
TRP_CORE.uniquePush(proc.noAccIdxes,idx);
z -= 1;
continue;
}else if(tileId<=MapDecorator.REGION_ID_BEGIN && tileId>=MapDecorator.REGION_ID_END){
//regionId
data[zRegion+idx] = -(tileId-MapDecorator.REGION_ID_BEGIN);
z -= 1;
continue;
}else if(tileId<=MapDecorator.SHADOW_ID_BEGIN && tileId>=MapDecorator.SHADOW_ID_END){
//shadow
data[zShadow+idx] = -(tileId-MapDecorator.SHADOW_ID_BEGIN);
z -= 1;
continue;
}
}
if(!skip){
var isAutotile = Tilemap.isAutotile(tileId);
if(sustainShape){
if(isAutotile && !Tilemap.isWallSideTile(tileId)){
tileId = baseTileId(tileId)+shape;
}
}
data[z*zLayerSize+idx] = tileId;
if(!sustainShape && autoTileIdxes && isAutotile){
if(Tilemap.isTileA2(tileId)||Tilemap.isWaterTile(tileId)/*||Tilemap.isWallTopTile(tileId)*/){
TRP_CORE.uniquePush(autoTileIdxes,z*zLayerSize+idx);
}
}
if(noConnect && isAutotile){
proc.noConnectMap[idx+':'+tileId] = true;
}
}
if(i>maxI)break;
}
if(needsShadow){
this.supplyShadow(idx);
}
//try make empty with zAcc layer
var tileId = baseTileId(data[idx+zAcc]);
if(tileId && !allFloorLevelTileIds.contains(tileId)){
var isLayerFull = false;
if(data[idx+zAcc]){
if(data[idx+zObj1]){
if(data[idx+zObj2]){
isLayerFull = true;
}
if(!isLayerFull)data[idx+zObj2] = data[idx+zObj1];
}
if(!isLayerFull)data[idx+zObj1] = data[idx+zAcc];
}
if(!isLayerFull){
// if(!allFloorLevelTileIds.contains(data[idx+zAcc])){
data[idx+zAcc] = 0;
// }
}
}
};
//=============================================================================
// ParamEditor
//=============================================================================
var EditorBase = TRP_CORE.EditorBase;
MapDecorator._paramEditors = {};
MapDecorator.paramEditor = null;
MapDecorator.MODE_PARAMS = null;
MapDecorator.MODE_PARAM_KEYS = {
paintFloor:[
'rateRange',
null,
'floorPaintRate',
'floorPaintChankMin',
'floorPaintChankMax',
'floorPaintPatternsWithTiles',
null,
'waterLocateMode',
'waterLocateRate',
'waterPaintRate',
'waterChankMin',
'waterChankMax',
'waterAccPaintRate',
'waterPaintChankMin',
'waterPaintChankMax',
'diasbleWaterConnect',
],
locateObject:[
'rateRange',
null,
'floorObjRate',
'floorBigObjRate',
null,
'waterObjRate',
'waterBigObjRate',
'waterObjOnEdge',
],
};
MapDecorator.editorBack = null;
MapDecorator.showParamEditor = function(mode){
if(this._paramEditors[mode] === undefined){
this._paramEditors[mode] = this._tryCreateParamEditor(mode);
}
var editor = this._paramEditors[mode];
if(!editor)return;
if(this.paramEditor === editor)return;
this.paramEditor = editor;
SceneManager._scene.addChild(editor);
editor.deactivate();
};
MapDecorator.hideParamEditor = function(){
if(!this.paramEditor)return;
this.tryDeactivateParamEditor();
if(this.paramEditor.parent){
this.paramEditor.parent.removeChild(this.paramEditor)
}
this.paramEditor = null;
};
MapDecorator.tryActivateParamEditor = function(){
if(!this.paramEditor){
SoundManager.playBuzzer();
return;
}
if(!this.editorBack){
this.editorBack = new PIXI.Graphics();
this.editorBack.beginFill(0x000000,0.25)
.drawRect(0,0,Graphics.width,Graphics.height);
}
SceneManager._scene.addChild(this.editorBack);
SceneManager._scene.addChild(this.paramEditor);
SoundManager.playCursor();
this.paramEditor.activate(INFO_SETTINGS[allInfo[MapDecorator.paramInfoIdx].floorBaseId]);
};
MapDecorator.tryDeactivateParamEditor = function(){
if(!this.paramEditor || !this.paramEditor.active)return;
SoundManager.playCursor();
this.paramEditor.deactivate();
if(this.editorBack && this.editorBack.parent){
this.editorBack.parent.removeChild(this.editorBack)
}
}
MapDecorator.paramInfoIdx = 0;
MapDecorator._refreshParamInfoIdx = function(){
var container = MapDecorator._paramEditorInfoSprite;
if(!container)return;
var idx = MapDecorator.paramInfoIdx;
var top = container.children[1];
var last = TRP_CORE.last(container.children);
var m = 4;
var x0 = top.x-m;
var y0 = top.y-m;
var w = -x0;
var h = top.y+top.height*top.scale.y+m;
var graphics = container.children[0];
graphics.clear();
graphics.beginFill(0x000000,0.5)
.drawRect(x0,y0,w,h);
var target = container.children[1+MapDecorator.paramInfoIdx];
graphics.beginFill(0xff0000,0.8)
.drawRect(target.x-m,target.y-m,target.width*target.scale.x+2*m,target.height*target.scale.y+2*m);
var editor = this.paramEditor;
if(editor){
editor.setData(INFO_SETTINGS[allInfo[MapDecorator.paramInfoIdx].floorBaseId]);
}
};
MapDecorator.onKeyDownParamEditor = function(event){
if(event.metaKey||event.ctrlKey){
if(event.key==='c'){
this.copyParamsToClipboard();
}
}else{
if(event.code==='Space'){
this.tryDeactivateParamEditor();
Input.clear();
}else if(event.code==='Tab'){
MapDecorator.paramInfoIdx += 1;
if(MapDecorator.paramInfoIdx>=allInfo.length)MapDecorator.paramInfoIdx = 0;
this._refreshParamInfoIdx();
SoundManager.playCursor();
}
}
};
MapDecorator.copyParamsToClipboard = function(){
var src = MapDecorator.SETTING_TEXT;
src = src.substring(
src.indexOf('// <<ベース床設定>'),
src.indexOf('// <<その他タイル設定>>')
).trim();
var setting = INFO_SETTINGS[allInfo[MapDecorator.paramInfoIdx].floorBaseId];
var text = '';
var lines = src.split('\n');
for(var line of lines){
if(text)text+='\n';
line = line.trim();
var match = line.match(/(.+)\:.+,$/);
if(match){
var key = match[1];
var obj = setting;
var keys = key.split('_');
var length = keys.length;
for(var i=0; i<length-1; i=(i+1)|0){
obj = obj[keys[i]];
}
var value = obj[TRP_CORE.last(keys)];
text += key+':'+JSON.stringify(value)+',';
}else{
text += line;
}
}
//add rate range
var param = MapDecorator.ALL_ANALYZED_PARAMS.rateRange;
if(param){
text = '//'+param.help.slice(1,param.help.length-1).join('\n//')+'\n'
+ param.key+':'+setting.rateRange+',\n\n'
+ text;
}
_Dev.copyToClipboard(text);
SoundManager.playSave();
};
MapDecorator.onPasteParamEditor = function(e){
e.preventDefault();
var clipboardData = e.clipboardData;
if(!clipboardData){
SoundManager.playBuzzer();
return;
}
var text = clipboardData.getData("text/plain");
var allParams = this._analyzeSettingParams(text);
Object.keys(allParams).forEach(key=>{
allParams[key] = eval(allParams[key].default);
})
var current = SETTING;
var _info = allInfo[MapDecorator.paramInfoIdx];
SETTING = INFO_SETTINGS[_info.floorBaseId];
this.overwriteSettings(allParams);
if(this.paramEditor){
this.paramEditor.setData(SETTING,true);
}
SETTING = current;
SoundManager.playLoad();
};
/* helper
===================================*/
MapDecorator._paramEditorInfoSprite = null;
MapDecorator._tryCreateParamEditor = function(mode){
if(!MapDecorator.MODE_PARAMS){
this.tryAnalyzeSettingParams();
}
if(!MapDecorator.MODE_PARAMS)return null;
var modeParams = MapDecorator.MODE_PARAMS[mode];
if(!modeParams){
return null;
}
var allData = [];
if(allInfo.length>1){
allData.push({
category:'《ベース床設定:Tabで切り替え》',
});
if(!MapDecorator._paramEditorInfoSprite){
var sprite = new PIXI.Container();
MapDecorator._paramEditorInfoSprite = sprite;
var back = new PIXI.Graphics();
sprite.addChild(back);
var mx = 50;
var x = -allInfo.length*mx;
var y = 4;
for(const info of allInfo){
var tileId = info.floorBaseId;
var tileSprite = this.layeredTilesSprite([tileId]);
tileSprite.x = x;
tileSprite.y = y;
tileSprite.scale.set(2/3,2/3);
sprite.addChild(tileSprite);
x += mx;
}
}
allData.push({
sprite:MapDecorator._paramEditorInfoSprite
});
}
//params
allData.push({
category:'《パラメータ》',
newLine:allInfo.length>1,
});
for(const param of modeParams){
allData.push({
key:param.key,
unit:param.unit,
integer:param.integer,
data:SETTING,
help:param.help,
newLine:param.newLine,
});
}
var editor = new EditorBase(allData);
var help = editor.baseHelpData();
help.unshift('【パラメータ設定】');
help.push('Space:設定終了');
editor.setHelp(help);
this._refreshParamInfoIdx();
return editor;
};
MapDecorator._onceAnalyzeSettingParams = false;
MapDecorator.SETTING_TEXT = null;
MapDecorator.ALL_ANALYZED_PARAMS = null;
MapDecorator.tryAnalyzeSettingParams = function(){
if(this.SETTING_PARAMS)return;
if(MapDecorator._onceAnalyzeSettingParams)return;
MapDecorator._onceAnalyzeSettingParams = true;
var filePath = parameters.pluginPath||'js/plugins/TRP_MapDecorator.js';
var file = _Dev.readFile(filePath);
if(!file)return;
var idx = file.indexOf('var SETTING =');
if(idx<0)return;
file = file.substring(idx,file.indexOf(/^}/));
file = file.substr(file.indexOf('\n')+1);
file = file.trim();
MapDecorator.SETTING_TEXT = file;
var allParams = this._analyzeSettingParams(file);
MapDecorator.ALL_ANALYZED_PARAMS = allParams;
/* setup modeParams
===================================*/
this.MODE_PARAMS = {};
var modes = Object.keys(MapDecorator.MODE_PARAM_KEYS);
for(const mode of modes){
this.MODE_PARAMS[mode] = [];
var newLine = false;
for(const key of MapDecorator.MODE_PARAM_KEYS[mode]){
if(!key){
//category top
newLine = true;
continue;
}
var param = allParams[key];
var help = param.help;
var defStr = param.default;
var unit = param.unit || analyzeParamUnit(param.default);
var defHelp = '(デフォ値:'+defStr+')';
if(!help.contains(defHelp)){
help.push(defHelp);
}
this.MODE_PARAMS[mode].push({
key,
help:param.help,
unit:param.unit||unit,
integer:defStr.indexOf('.')<0,
newLine,
});
newLine = false;
}
};
};
MapDecorator._analyzeSettingParams = function(file){
var lines = file.split('\n');
var allParams = {};
var help = null;
var unit = 0;
for(var line of lines){
line = line.trim();
if(!line
|| line.indexOf('// <<')===0
|| line.indexOf('//==')===0
){
//category header or empty
continue;
}else if(line.indexOf('//')===0){
line = line.replace('//','');
line = line.replace('true/false','1=ON/0=OFF');
var unitMatch = line.match(/\<unit\:([0-9\.]+)\>/);
if(unitMatch){
line = line.replace(unitMatch[0],'');
unit = Number(unitMatch[1]);
}
help = help||[];
help.push(line);
}else if(line.indexOf('}')===0){
//end SETTING define
break;
}else{
line = line.replace(/,$/,'');
var elems = line.split(':');
var key = elems[0];
if(help){
help.unshift('<'+key+'>');
}
allParams[key] = {
key,
default:elems[1],
help,
unit,
};
help = null;
unit = 0;
}
}
return allParams;
};
function analyzeParamUnit(defStr){
var unit;
if(defStr==='true' || defStr==='false'){
unit = 1;
}else if(!isNaN(defStr)){
var unitStr = '';
var validNumFound = false;
var unitAdjust = 10;
for(var idx=0; idx<defStr.length; idx=(idx+1)|0){
switch(defStr[idx]){
case '-':
continue;
case '.':
if(validNumFound)break;
case '0':
unitStr += defStr[idx];
continue;
case '1':
if(!validNumFound){
validNumFound = true;
unitAdjust = 10;
unitStr += defStr[idx];
if(unitStr.indexOf('.')>=0)break;
}else{
unitStr += '0';
}
continue;
default:
if(!validNumFound){
validNumFound = true;
unitAdjust = 1;
unitStr += '1';
if(unitStr.indexOf('.')>=0)break;
}else{
unitStr += '0';
}
continue;
}
if(unitStr[unitStr.length-1]==='1')break;
}
unit = Number(unitStr)/unitAdjust;
if(defStr.indexOf('.')<0){
unit = Math.max(unit,1);
}
}
return unit;
}
//=============================================================================
// MapObject
//=============================================================================
MapDecorator.analyzeMapObjects = function(){
var objects = $dataTrpMapObjects;
if(!objects)return;
var setupTemplates = MapObject._setupEventTemplates;
var templates = this.mapObjectTemplate;
var templateConvertMap = setupTemplates ? {} : null;
/* convert setupEventTemplates
===================================*/
var setupTags = setupTemplates ? Object.keys(setupTemplates) : null;
var length = setupTags ? setupTags.length : 0;
var newRegisterTemplates = [];
var needsRefreshTags = [];
for(var i=0; i<length; i=(i+1)|0){
var tag = setupTags[i];
if(!isNaN(tag))tag = Number(tag);
var target = setupTemplates[tag];
if(!target)continue;
var bestFitValue = Number.MAX_SAFE_INTEGER;
var bestFitTemplate = null;
for(const template of templates){
if(!template)continue;
var fitValue = MapObject.templateFitValue(target,template);
if(fitValue<bestFitValue){
bestFitValue = fitValue;
bestFitTemplate = template;
}
}
if(!bestFitTemplate){
bestFitTemplate = JsonEx.makeDeepCopy(target);
bestFitTemplate.tag = templates.length + newRegisterTemplates.length;
newRegisterTemplates.push(bestFitTemplate);
}else if(bestFitValue>0){
needsRefreshTags.push(tag);
}
templateConvertMap[tag] = bestFitTemplate.tag;
}
if(setupTemplates && newRegisterTemplates && newRegisterTemplates.length){
templates.push(...newRegisterTemplates);
}
/* register located objects
===================================*/
var spriteset = SceneManager._scene._spriteset;
for(const obj of objects){
var x = obj.x/tileW-0.5;
var y = obj.y/tileH-1;
if(obj.tileId){
x -= (obj.tileW-1)/2;
y -= (obj.tileH-1);
}
x = Math.floor(x);
y = Math.floor(y);
if(templateConvertMap && templateConvertMap[obj.tag]){
var needsRefresh = needsRefreshTags.contains(obj.tag);
obj.tag = templateConvertMap[obj.tag];
if(needsRefresh){
obj.setupWithTemplate(templates[obj.tag]);
if(obj.sprite){
obj.releaseSprite();
obj.setupSprite(spriteset);
}
}
}
var idx = x+y*width;
var roomId = idxOfRoom(idx);
if(roomId<0){
continue;
}
var lastRoomObjects = proc.lastObjInfoArr[roomId] = proc.lastObjInfoArr[roomId]||[];
lastRoomObjects.push([idx,obj]);
TRP_CORE.uniquePush(proc.lockedObjRoomIds,roomId);
}
};
MapDecorator.analyzeTileObjects = function(){
/* make initial tileId map
===================================*/
var map = {};
for(const obj of allObjects){
var tileId;
if(MapObject && obj instanceof MapObject){
if(!obj.tileId)continue;
tileId = obj.tileId;
}else{
if(Array.isArray(obj[0])){
tileId = obj[0][0][0];
}else{
tileId = obj[0];
}
}
map[tileId] = map[tileId]||[];
map[tileId].push(obj);
}
var replaced = false;
for(var i=0; i<zLayerSize; i=(i+1)|0){
var roomId = proc.roomIdxMapForUserProc[i];
if(roomId<0)continue;
for(var z=0; z<4; z=(z+1)|0){
var tileId = data[i+z*zLayerSize];
var objects = map[tileId];
if(!objects)continue;
for(const obj of objects){
var tileIds = (MapObject && obj instanceof MapObject) ? obj.tileIds() : obj;
if(MapObject && MapObject._tryReplaceTilesInIdx(tileIds,i)){
//retry this tile
var lastRoomObjects = proc.lastObjInfoArr[roomId] = proc.lastObjInfoArr[roomId]||[];
lastRoomObjects.push([i,obj]);
TRP_CORE.uniquePush(proc.lockedObjRoomIds,roomId);
replaced = true;
z = -1;
break;
}
}
}
}
if(replaced){
originalData = data;
this.restoreMap(true);
}
};
//for manual locate
MapDecorator._convertedMapObjMap = {};
MapDecorator._mapObjTemplateKeys = [];
MapDecorator.mapObjectTemplateWithTileObject = function(objArr,noAlert=false){
if(!objArr)return null;
var key = JSON.stringify(objArr);
if(!this._convertedMapObjMap[key]){
this._convertedMapObjMap[key] = this._mapObjectTemplateWithTileObject(objArr,noAlert);
this._mapObjTemplateKeys.push(key);
}
return this._convertedMapObjMap[key];
};
MapDecorator._mapObjectTemplateWithTileObject = function(objArr,noAlert=false){
var w = 1;
var h = 1;
var tileId;
var isBigObj = false;
if(Array.isArray(objArr[0])){
//bigObj
isBigObj = true;
tileId = objArr[0][0][0];
w = objArr.length;
h = objArr[0].length;
}else{
tileId = objArr[0];
}
if(!tileId){
if(!noAlert){
_Dev.showTempAlert('ドット配置できないオブジェクトです');
SoundManager.playBuzzer();
}
return null;
}
var obj = MapObject.object();
obj.setupCommonBefore();
obj.tileId = tileId;
obj.tileW = w;
obj.tileH = h;
if(isBigObj){
//check tileIds is in sequence
var tileIds = obj.tileIds(true);
if(!tileIds.equals(objArr)){
if(!noAlert){
_Dev.showTempAlert('ドット配置できないオブジェクトです');
SoundManager.playBuzzer();
}
MapObject.cache(obj);
return null;
}
}
var tileId = obj.tileId;
var flags = null;
if(tileId<0){
var otherTilesetData = MapObject.otherTilesetDataWithTileId(tileId);
if(otherTilesetData){
var tileset = otherTilesetData[0];
tileId = otherTilesetData[1];
flags = tileset.flags;
}
}else{
flags = $gameMap.tileset().flags;
}
if(flags){
var bottomId = MapObject.tileIdInImage(tileId,0,h-1);
var bottomFlag = flags[bottomId];
var topId = tileId;
var topFlag = flags[topId];
//check bottom heigher
if(bottomFlag & 0x10){
obj.priority = 2;
}else if(topFlag & 0x10){
//top heigher
obj.priority = 1;
}else{
obj.priority = 0;
}
}else{
obj.priority = 0;
}
obj.setupCommonAfter();
this.registerMapObjectTemplateWithMapObject(obj);
return obj;
};
//save objData to mapEvent
MapDecorator.saveMapObjectData = function(noLink=false){
/* search mapObjectSave event
===================================*/
var event = null;
$dataMap.events.some(e=>{
if(e && this.infoCharacterTypeWithEvent(e)==='mapObjectSave'){
event = e;
return true;
}
return false;
});
/* make mapObjectSave event
===================================*/
if(!event){
event = {"id":0,"name":"EV011","note":"<trpMapObjSetup>","pages":[{"conditions":{"actorId":1,"actorValid":false,"itemId":1,"itemValid":false,"selfSwitchCh":"A","selfSwitchValid":false,"switch1Id":1,"switch1Valid":false,"switch2Id":1,"switch2Valid":false,"variableId":1,"variableValid":false,"variableValue":0},"directionFix":false,"image":{"tileId":0,"characterName":"DecorationInfo","direction":4,"pattern":0,"characterIndex":7},"list":[{"code":0,"indent":0,"parameters":[]}],"moveFrequency":3,"moveRoute":{"list":[{"code":0,"parameters":[]}],"repeat":true,"skippable":false,"wait":false},"moveSpeed":3,"moveType":0,"priorityType":1,"stepAnime":false,"through":false,"trigger":0,"walkAnime":false}],"x":0,"y":0};
event.id = $dataMap.events.length;
$dataMap.events.push(event);
//prepare pos event map
var posEventMap = [];
TRP_CORE.packValues(posEventMap,zLayerSize,0);
$dataMap.events.forEach(event=>{
if(!event)return;
posEventMap[event.x+event.y*width] = event;
});
//search empty pos
for(var i=0; i<zLayerSize; i=(i+1)|0){
if(posEventMap[i])continue;
event.x = i%width;
event.y = Math.floor(i/width);
break;
}
}
/* prepare comment command
===================================*/
var list = event.pages[0].list;
var command = list[0];
if(!command || command.code!==108){
//insert comment
command = {
code:108,
indent:0,
parameters:[''],
};
list.unshift(command);
}
/* make location data
===================================*/
var locations = [];
var template = {};
var objects = $dataTrpMapObjects;
for(var i=objects.length-1; i>=0; i=(i-1)|0){
var obj = objects[i];
if(MapDecorator.tryConvertMapObjectToMapData(obj)){
//obj -> tileData
this.requestRefreshTilemap();
continue;
}
var temp = null;
if(obj.tag && !isNaN(obj.tag)){
temp = template[obj.tag] = this.mapObjectTemplate[obj.tag];
}
var location = obj.locationData(temp);
if(!noLink && this.tryLinkMapObject(obj)){
location.push('LINK');
}
locations.push(location);
}
/* make save data
===================================*/
var saveData = {
template,
locations:locations,
};
command.parameters[0] = JSON.stringify(saveData);
};
MapDecorator.tryLinkMapObject = function(obj){
var tileIds = obj.tileIds();
if(!tileIds)return false;
var w = obj.tileW;
var h = obj.tileH;
// var mock = obj.mockTileData();
// if(!mock)return false;
// var tileIds,w,h;
var dx = 0; var dy = 0;
// if(Array.isArray(mock)){
// tileIds = mock;
// w = obj.tileW;
// h = obj.tileH;
// }else{
// //mock
// tileIds = mock.tileIds;
// w = mock.tileW;
// h = mock.tileH;
// dx = mock.dx;
// dy = mock.dy;
// }
var x = (obj.x/$gameMap.tileWidth())-w/2+dx;
var y = (obj.y/$gameMap.tileHeight())-h+dy;
x = Math.round(x);
y = Math.round(y);
return this._tryReplaceTilesWithLocation(tileIds,x,y,w,h);
};
MapDecorator._tryReplaceTilesWithLocation = function(tileIds,x,y,w,h){
var idx = x+y*width;
if(x<0||x+(w-1)>=$dataMap.width)return false;
if(y<0||y+(h-1)>=$dataMap.height)return false;
//check tileIds
for(var dx=0; dx<w; dx=(dx+1)|0){
for(var dy=0; dy<h; dy=(dy+1)|0){
var tileId = tileIds[dx][dy];
if(!tileId)continue;
var tIdx = idx+dx+dy*width;
var isEmpty = false;
for(var z=0; z<4; z=(z+1)|0){
if(!data[z*zLayerSize+tIdx]){
isEmpty = true;
break;
}
}
if(!isEmpty)return false;
}
}
//addTile
for(var dx=0; dx<w; dx=(dx+1)|0){
for(var dy=0; dy<h; dy=(dy+1)|0){
var tIdx = idx+dx+dy*width;
var tileId = tileIds[dx][dy];
if(tileId){
addObjTile(data,tIdx,tileId);
}
}
}
return true;
};
/* mapObjectCollision mode
===================================*/
MapDecorator.mapObjCollisionMode = 0;
MapDecorator.showMapObjectCollisions = function(){
if(!MapObject || !$dataTrpMapObjectCollisions){
SoundManager.playBuzzer();
_Dev.showTempAlert('衝突判定のあるスプライトオブジェトはありません');
return;
}
if(MapObject){
MapObject.refreshCollisions();
}
this.setMode('mapObjectCollision');
this._showMapObjectCollisionBlocks();
this.setObjectsOutline();
};
MapDecorator.endModeMapObjectCollision = function(){
this.removeObjectsOutline();
};
MapDecorator.setObjectsOutline = function(color=0x0000ff,size=1){
this.showingObjOutline = true;
for(const obj of $dataTrpMapObjects){
obj.setOutlineFilter(color,size);
}
};
MapDecorator.removeObjectsOutline = function(){
this.showingObjOutline = false;
for(const obj of $dataTrpMapObjects){
obj.removeOutlineFilter();
}
};
MapDecorator._showMapObjectCollisionBlocks = function(){
this.mapObjCollisionMode = 0;
var positions = [];
var color = 'rgba(255,0,0,0.5)';
var texts = null;
var width = $dataMap.width;
var zLayerSize = $dataMap.width*$dataMap.height;
var tileW = $gameMap.tileWidth();
var tileH = $gameMap.tileHeight();
var collisions = MapObject.collisionsMap();
var res = MapObject.CollisionResolution;
var rowIdx = width*res;
for(var i=zLayerSize-1; i>=0; i=(i-1)|0){
var baseIdx = (i%width)*res + (Math.floor(i/width))*res*rowIdx;
for(var xi=res-1; xi>=0; xi=(xi-1)|0){
for(var yi=res-1; yi>=0; yi=(yi-1)|0){
if(collisions[baseIdx+xi+yi*rowIdx]){
positions.push(i);
break;
}
}
if(positions.contains(i))break;
}
}
var sw = tileW/res;
var sh = tileH/res;
var tonnerTiles = (ctx,x0,y0)=>{
/* draw blocks
===================================*/
ctx.fillStyle = color;
ctx.beginPath();
for(var i=zLayerSize-1; i>=0; i=(i-1)|0){
var x = i%width;
var y = Math.floor(i/width);
var baseIdx = x*res + y*res*rowIdx;
for(var xi=res-1; xi>=0; xi=(xi-1)|0){
for(var yi=res-1; yi>=0; yi=(yi-1)|0){
if(collisions[baseIdx+xi+yi*rowIdx]){
var tx = ((x-x0)*res+xi)*sw;
var ty = ((y-y0)*res+yi)*sh;
ctx.moveTo(tx,ty);
ctx.lineTo(tx+sw,ty);
ctx.lineTo(tx+sw,ty+sh);
ctx.lineTo(tx,ty+sh);
ctx.lineTo(tx,ty);
}
}
}
}
ctx.closePath();
ctx.fill();
ctx.lineWidth = 1;
ctx.strokeStyle = 'rgb(100,0,0)'
ctx.stroke();
ctx.restore();
/* draw outlines
===================================*/
ctx.beginPath();
ctx.strokeStyle = 'rgb(0,0,0)'
for(const i of positions){
var x = i%width;
var y = Math.floor(i/width);
var tx = (x-x0)*tileW;
var ty = (y-y0)*tileH;
ctx.moveTo(tx,ty);
ctx.lineTo(tx+tileW,ty);
ctx.lineTo(tx+tileW,ty+tileH);
ctx.lineTo(tx,ty+tileH);
ctx.lineTo(tx,ty);
}
ctx.lineWidth = 2;
ctx.closePath();
ctx.stroke();
};
var drawText = (bitmap,x,y,text,i)=>{};
this.tonnerTiles(positions,texts,color,tonnerTiles,drawText);
};
MapDecorator._showMapObjectCollisionDirs = function(){
this.mapObjCollisionMode = 1;
var positions = [];
var color = 'rgba(0,0,255,0.2)';
var texts = [];
for(var i=zLayerSize-1; i>=0; i=(i-1)|0){
var collision = $dataTrpMapObjectCollisions[i];
if(!collision)continue;
positions.push(i);
texts.push(collision);
}
var tonnerTiles = null;
var drawText = (bitmap,x,y,text,i)=>{
if(text===15){
bitmap.fontSize = 32;
bitmap.drawText('x',x,y,48,48,'center');
return;
}
bitmap.fontSize = 20;
if(text&1<<0){
bitmap.drawText('↓',x,y+24,48,24,'center');
bitmap.drawText('x',x,y+24,48,24,'center');
}
if(text&1<<1){
bitmap.drawText('←',x,y,24,48,'center');
bitmap.drawText('x',x,y,24,48,'center');
}
if(text&1<<2){
bitmap.drawText('→',x+24,y,24,48,'center');
bitmap.drawText('x',x+24,y,24,48,'center');
}
if(text&1<<3){
bitmap.drawText('↑',x,y,48,24,'center');
bitmap.drawText('x',x,y,48,24,'center');
}
};
this.tonnerTiles(positions,texts,color,tonnerTiles,drawText);
};
MapDecorator.MODE_GUIDE.mapObjectCollision = [
'【スプライトオブジェの衝突判定確認モード】',
'左クリック:表示切り替え',
'右クリック:確認モード終了',
];
MapDecorator.onMouseDownRightMapObjectCollision = MapDecorator.restoreModeByMouse;
MapDecorator.updateInputMapObjectCollision = MapDecorator.updateInputToCheckRestoreMode;
MapDecorator.onMouseDownLeftMapObjectCollision = function(){
SoundManager.playCursor();
if(this.mapObjCollisionMode===0){
this._showMapObjectCollisionDirs();
}else{
this._showMapObjectCollisionBlocks();
}
};
/* analyzeOtherTilesetObjects
===================================*/
MapDecorator.otherTilesetIdsReplaceMap = {};
MapDecorator.tryAnalyzeOtherTilesetObjects = async function(){
var objects = [];
for(const roomInfoArr of proc.lastObjInfoArr){
for(const objInfo of roomInfoArr){
var obj = objInfo[1];
if(Array.isArray(obj))continue;
if(obj.tileId>=0)continue;
objects.push(obj);
}
}
SoundManager.playCursor();
var executed = false;
var objLeft = false;
for(const obj of objects){
if(MapDecorator.otherTilesetIdsReplaceMap[obj.tileId]){
obj.tileId = MapDecorator.otherTilesetIdsReplaceMap[obj.tileId];
obj.loadBitmap();
continue;
}
executed = true;
var srcTileIds = obj.tileIds();
var bitmap = new Bitmap(tileW*obj.tileW,tileH*obj.tileH);
var src = obj.bitmap;
TRP_CORE.bltImage(bitmap,src,obj.fx,obj.fy,obj.fw,obj.fh,0,0);
await new Promise(resolve=>this.startTilesetEdit(bitmap,(tileIds)=>{
if(tileIds){
obj.tileId = tileIds[0];
obj.loadBitmap();
for(const row of srcTileIds){
for(const tileId of row){
var dstTileId = tileIds.shift();
if(tileId && dstTileId){
MapDecorator.otherTilesetIdsReplaceMap[tileId] = dstTileId;
}
}
}
}else{
objLeft = true;
}
resolve();
}));
}
if(!objLeft){
_Dev.showTempText('decorator:otherTile',null);
}
};
//=============================================================================
// MODE: PlayerMove
//=============================================================================
MapDecorator.MODE_GUIDE.playerMove = [
'Esc移動テストモード終了',
];
MapDecorator.setModePlayerMove = function(){
this.modeData = {
editorUpdate:SceneManager._scene.update,
menuEnabled:SceneManager._scene.isMenuEnabled,
};
SceneManager._scene.update = this._sceneUpDate;
$gamePlayer._transparent = false;
$gamePlayer.moveByInput = this._playerMoveByInput;
SceneManager._scene.isMenuEnabled = ()=>false;
var onKeyDown = this.modeData.onKeyDown = event=>{
if(event.key==='Escape'){
this.restoreMode(true);
SoundManager.playCancel();
}
}
document.addEventListener('keydown',onKeyDown);
if(MapObject){
MapObject.refreshCollisions();
}
};
MapDecorator.endModePlayerMove = function(){
SceneManager._scene.update = this.modeData.editorUpdate;
SceneManager._scene.isMenuEnabled = this.modeData.isMenuEnabled;
document.removeEventListener('keydown',this.modeData.onKeyDown);
$gamePlayer._transparent = true;
if($gamePlayer._followers){
$gamePlayer._followers.update();
}
SceneManager._scene._spriteset.update();
$gamePlayer.moveByInput = ()=>{};
};
//=============================================================================
// Util Funcs
//=============================================================================
var anyTileId = MapDecorator.anyTileId = function(idx,env=ENV_VARS){
return env.data[idx]||env.data[idx+env.zAcc]||env.data[idx+env.zObj1]||env.data[idx+env.zObj2];
};
var layeredTileIds = MapDecorator.layeredTileIds = function(idx,env=ENV_VARS){
var tileIds = null;
for(var z=0; z<4; z=(z+1)|0){
if(!env.data[idx+z*env.zLayerSize])continue;
tileIds = tileIds||[];
tileIds.push(env.data[idx+z*env.zLayerSize]);
}
return tileIds
}
var baseTileId = MapDecorator.baseTileId = function baseTileId(tileId){
if(Tilemap.isAutotile(tileId)){
return tileId - Tilemap.getAutotileShape(tileId);
}else{
return tileId;
}
}
function isEmptyTile(idx){
return isEmptyTileId(anyTileId(idx));
}
function isEmptyTileId(tileId){
if(!tileId)return true;
if(ceilingBaseIds.contains(baseTileId(tileId)))return true;
return false;
}
function idxOfRoom(idx){
for(var i=proc.allRoomIdxes.length-1; i>=0; i=(i-1)|0){
if(proc.allRoomIdxes[i].contains(idx)){
return i;
}
}
return -1;
};
function idxForNeighborDir(idx,ni,zIdx=0){
if(ni<=3){
idx += width;
if(idx>zLayerSize+zIdx)return -1;
}else if(ni>=7){
idx -= width;
if(idx<zIdx)return -1;
}
if(ni%3===1){
if(idx%width===0)return -1;
idx -= 1;
}else if(ni%3===0){
if(idx%width===width-1)return -1;
idx += 1;
}
return idx;
}
/* analyzeNeibors
===================================*/
// analyzer=((nx,ny,ox,oy)=>{})
var analyzeNeighbors = MapDecorator.analyzeNeighbors = function(cx,cy,analyzer,checkTileExists=false,env=ENV_VARS){
var data = env.data;
var width = env.width;
var height = env.height;
var zLayerSize = env.zLayerSize;
cx = Math.floor(cx);
cy = Math.floor(cy);
if(!analyzer(cx,cy)){
return null;
}
var positions = [cx+cy*width];
var foundIdxes = [];
var currentIdxes = [];
var checkedIdxes = [];
var dirs = [width,-1,1,-width];
var dirLen = dirs.length;
var idx = cy*width+cx;
foundIdxes.push(idx);
checkedIdxes.push(idx);
while(foundIdxes.length>0){
var tempIdxes = currentIdxes;
currentIdxes = foundIdxes;
foundIdxes = tempIdxes;
foundIdxes.length = 0;
var length = currentIdxes.length;
for(var i=0; i<length; i=(i+1)|0){
idx = currentIdxes[i];
var tx = idx%width;
var ty = Math.floor(idx/width);
for(var d=0;d<dirLen;d=(d+1)|0){
var neighbor = idx+dirs[d];
if(checkedIdxes.contains(neighbor)){
continue;
}
checkedIdxes.push(neighbor);
if(checkTileExists){
if(!data[neighbor]
&& !data[neighbor+1*zLayerSize]
&& !data[neighbor+2*zLayerSize]
&& !data[neighbor+3*zLayerSize]
){
continue;
}
}
//check neighbor inside map size
if(d===1 && tx===0)continue;
if(d===2 && tx===width-1)continue;
if(neighbor<0 || neighbor>=zLayerSize)continue;
//check regionId same
if(!analyzer(neighbor%width,Math.floor(neighbor/width),tx,ty,positions,checkedIdxes)){
continue;
}
foundIdxes.push(neighbor);
positions.push(neighbor);
}
}
}
return positions;
};
/* show info on touch
===================================*/
var infoTextSpriteCache = [];
function showInfoText(text,x=TouchInput.x,y=TouchInput.y){
var sprite = infoTextSpriteCache.pop();
var bitmap;
if(!sprite){
bitmap = new Bitmap(200,26);
sprite = new TRP_CORE.FadableSprite(bitmap);
sprite.anchor.set(0.5,0.5);
bitmap.fontSize = bitmap.height-4;
bitmap.outlineWidth = 4;
bitmap.outlineColor = 'black';
}else{
bitmap = sprite.bitmap;
bitmap.clear();
}
SceneManager._scene.addChild(sprite);
sprite.x = x;
sprite.y = y;
bitmap.drawText(text,0,0,bitmap.width,bitmap.height,'center');
MapDecorator.updateList.push(sprite);
sprite.startFadeOut(30,10,()=>{
if(sprite.parent){
sprite.parent.removeChild(sprite);
}
infoTextSpriteCache.push(sprite);
TRP_CORE.remove(MapDecorator.updateList,sprite)
});
};
//=============================================================================
// Restore Map
//=============================================================================
MapDecorator.restoreMap = function(noClear=false){
data = originalData.concat();
$dataMap.data = data;
/* restore floor acc
===================================*/
for(const waterInfo of proc.lastWaterInfoArr){
if(!waterInfo)continue;
var infoLen = waterInfo.length;
for(var i=0; i<infoLen; i=(i+3)|0){
var idx = waterInfo[i];
data[idx] = waterInfo[i+1];
data[idx+zAcc] = waterInfo[i+2];
proc.waterIdxes.push(idx);
}
}
for(const paintInfo of proc.lastFloorPaintInfoArr){
if(!paintInfo)continue;
var infoLen = paintInfo.length;
for(var i=0; i<infoLen; i=(i+3)|0){
var idx = paintInfo[i];
data[idx] = paintInfo[i+1];
data[idx+zAcc] = paintInfo[i+2];
}
}
for(const idxes of proc.autoConnectRequestIdxes){
if(!idxes)continue;
for(const idx of idxes){
data[idx] = connectAutoTileWithIdx(idx);
}
}
/* locate obj
===================================*/
if(!noClear && proc.locateObj){
this.clearNonLockedObjects();
}
// data = info.lockedData.concat();
for(const objInfo of proc.lastObjInfoArr){
if(!objInfo)continue;
addObjTilesWithObjInfoArr(objInfo);
}
if(MapObject){
MapObject.refreshCollisions();
}
SceneManager._scene._spriteset._tilemap._mapData = $dataMap.data;
this.requestRefreshTilemap();
}
MapDecorator.clearNonLockedObjects = function(){
//clear non locked info
var length = proc.allRoomIdxes.length;
var mapObjRemoved = false;
for(var i=0; i<length; i=(i+1)|0){
if(!proc.lockedObjRoomIds.contains(i)){
mapObjRemoved = this.clearLastObjects(i) || mapObjRemoved;
}
}
if(mapObjRemoved && MapObject){
MapObject.refreshCollisions();
}
};
MapDecorator.objInfoOfObj = function(obj){
for(const roomObjInfo of proc.lastObjInfoArr){
if(!roomObjInfo)continue;
for(const objInfo of roomObjInfo){
if(obj===objInfo[1]){
return objInfo;
}
}
}
return null;
};
MapDecorator.clearLastObjects = function(roomId){
var mapObjRemoved = false;
if(!proc.lastObjInfoArr[roomId]){
return mapObjRemoved;
}
var roomObjInfo = proc.lastObjInfoArr[roomId];
if(roomObjInfo && MapObject){
for(const objInfo of roomObjInfo){
if(objInfo[1] instanceof MapObject){
var mapObj = objInfo[1];
MapObject.remove(mapObj,true);
if(this.modeData && mapObj===this.modeData.lastLocateMapObj){
this.modeData.lastLocateMapObj = null;
}
mapObjRemoved = true;
}
}
}
proc.lastObjInfoArr[roomId] = [];
return mapObjRemoved
}
MapDecorator.sprite = function(bitmap){
var sprite = MapDecorator._cachedSprites.pop();
sprite = sprite || new Sprite();
sprite.scale.set(1,1);
sprite.anchor.set(0,0);
sprite.x = sprite.y = 0;
sprite.opacity = 255;
sprite._frame.x = sprite._frame.y = 0;
sprite.bitmap = bitmap;
return sprite;
};
MapDecorator.bitmap = function(w,h){
for(const bitmap of MapDecorator._cachedBitmaps){
if(bitmap.width === w && bitmap.height===h){
TRP_CORE.remove(MapDecorator._cachedBitmaps,bitmap);
bitmap.clear();
return bitmap;
}
}
return new Bitmap(w,h);
};
//=============================================================================
// Auto Tile Connection
//=============================================================================
// var CONNECT_TYPE = MapDecorator.CONNECT_TYPE = {
// default:0,
// };
function connectAutoTileWithIdx(idx,connectEmpty=0){
var tid = data[idx];
if(proc.noConnectMap[(idx%zLayerSize)+':'+tid]){
return tid;
}
var baseId = baseTileId(tid);
if(!baseId || !Tilemap.isAutotile(baseId) || Tilemap.isWallSideTile(baseId)){
return baseId;
}
if(baseId === info.waterBaseId){
connectEmpty = 2;
}
if(connectEmpty===2){
if(SETTING.diasbleWaterConnect){
connectEmpty = 0;
}
}
var bottomIdx = idx%zLayerSize;
var layerIdx = idx-bottomIdx;
// var roomId = idxOfRoom(bottomIdx);
var roomId = proc.roomIdxMapForUserProc[bottomIdx];
var z = proc.floorLevelZMap[bottomIdx];
var nf = TRP_CORE.packValues([],0,10);
var noTileIds = connectEmpty ? TRP_CORE.packValues([],0,10) : null;
for(var ni=1; ni<=9; ni=(ni+1)|0){
if(ni===5){
nf[ni] = 1;
continue;
}
var neighbor = idxForNeighborDir(idx,ni,layerIdx);
if(neighbor<0){
//outsideMap -> connect
nf[ni] = 1;
continue;
}
if(proc.connectFloorIdxes.contains(neighbor%zLayerSize)){
//connectFloor flags;
nf[ni] = 1;
continue;
}
var neighborBottomIdx = neighbor%zLayerSize
var neiborBottomId = data[neighborBottomIdx];
var tileId = data[neighbor];
if(connectEmpty){
//connect to ceiling or walls
if(!neiborBottomId || proc.ceilingIdxes.contains(neighborBottomIdx) || proc.wallIdxes.contains(neighborBottomIdx)
|| (invalidIdxes&&invalidIdxes.contains(neighborBottomIdx))
){
if(!proc.floorSuppliedIdxes.contains(neighborBottomIdx)){
noTileIds[ni] = 1;
nf[ni] = 1;
continue;
}
}
}
//check same tile
if(!tileId)continue;
if(baseId !== baseTileId(tileId))continue;
//check same z
if(proc.floorLevelZMap[neighborBottomIdx]!==z){
if(/*proc.ceilingIdxes.contains(neighborBottomIdx) ||*/ proc.wallIdxes.contains(neighborBottomIdx)){
//neighbor is wall or ceiling -> maybe replace any tile -> OK
TRP_CORE.uniquePush(proc.autoConnectRequestIdxes[roomId],neighbor);
}else if(/*proc.ceilingIdxes.contains(bottomIdx) ||*/ proc.wallIdxes.contains(bottomIdx)){
//self is wall or ceiling -> maybe replace any tile -> OK
}else{
continue;
}
}
//check same room
// if(idxOfRoom(neighborBottomIdx)!==roomId){
// continue;
// }
//connect ok
nf[ni] = 1;
}
if(connectEmpty===2){
//water tile
if(nf[2]&&!noTileIds[2]){
if(noTileIds[6] && !noTileIds[3]){
nf[3] = 0;
if(noTileIds[8]){
nf[6] = 0;
}
}
if(noTileIds[4] && !noTileIds[1]){
nf[1] = 0;
if(noTileIds[8]){
nf[4] = 0;
}
}
}
if(noTileIds[8]){
nf[7] = 0;
nf[8] = 0;
nf[9] = 0;
}else if(nf[8]){
if(noTileIds[9] && nf[6]&&!noTileIds[6]){
nf[9] = 0;
}
if(noTileIds[7] && nf[4]&&!noTileIds[4]){
nf[7] = 0;
}
}else if(noTileIds[9]){
nf[9] = 0;
}else if(noTileIds[7]){
nf[7] = 0;
}
}
return connectAutoTile(baseId,nf);
};
function getShape(nf){
var neighborConnectNum = nf[2]+nf[4]+nf[6]+nf[8];
var s;
if(neighborConnectNum===4){
s = 0;
if(!nf[7])s+=1;
if(!nf[9])s+=2;
if(!nf[3])s+=4;
if(!nf[1])s+=8;
}else if(neighborConnectNum===3){
s = 16;
//var link3dirs = [[4,9,3],[8,3,1],[6,1,7],[2,7,9]];
if(!nf[4]){
if(nf[9]&&nf[3])s+=0;
else if(!nf[9]&&nf[3])s+=1;
else if(!nf[3]&&nf[9])s+=2;
else s+=3;
}else if(!nf[8]){
if(nf[3]&&nf[1])s+=4;
else if(!nf[3]&&nf[1])s+=5;
else if(!nf[1]&&nf[3])s+=6;
else s+=7;
}else if(!nf[6]){
if(nf[1]&&nf[7])s+=8;
else if(!nf[1]&&nf[7])s+=9;
else if(!nf[7]&&nf[1])s+=10;
else s+=11;
}else if(!nf[2]){
if(nf[7]&&nf[9])s+=12;
else if(!nf[7]&&nf[9])s+=13;
else if(!nf[9]&&nf[7])s+=14;
else s+=15;
}
}else if(neighborConnectNum===2){
s = 32;
if(nf[2]&&nf[8])s+=0;
else if(nf[4]&&nf[6])s+=1;
else if(nf[2]&&nf[6]){
if(nf[3])s+=2;
else s+=3;
}else if(nf[2]&&nf[4]){
if(nf[1])s+=4;
else s+=5;
}else if(nf[4]&&nf[8]){
if(nf[7])s+=6;
else s+=7;
}else if(nf[8]&&nf[6]){
if(nf[9])s+=8;
else s+=9;
}
}else if(neighborConnectNum===1){
s = 42;
if(nf[2])s+=0;
else if(nf[6])s+=1;
else if(nf[8])s+=2;
else if(nf[4])s+=3;
}else{
s = 46
}
return s;
}
function connectAutoTile(baseId,nf,s=getShape(nf)){
var tileId = baseId + s;
if(!tileId){
connectAutoTile(baseId,nf)
}
return tileId;
}
//=============================================================================
// ColorPicker
//=============================================================================
MapDecorator._colorPicker = null;
MapDecorator._pickingColor = null;
MapDecorator.startPickColor = function(handler){
if(!this._colorPicker){
var size = 144;
this._colorPicker = new ColorPicker(size);
}
var picker = this._colorPicker;
picker.x = 10;
picker.y = 30;
picker.visible = true;
this._pickingColor = {
handler,
color:null,
rgb:[null,null,null],
};
this.refreshColorPickGuideText();
};
MapDecorator.refreshColorPickGuideText = function(){
var rgb = this._pickingColor.rgb;
var color = this._pickingColor.color||'#ffffff';
color = color.substring(1);
var colors = [color.substring(0,2),color.substring(2,4),color.substring(4)];
_Dev.showText('objColorPick',[
'【色味の変更】',
'0~9ランダムな色味',
'Shift+0~9:同種オブジェすべて変更',
'R/G/B各色固定',
'R:%1%4,G:%2%5,B:%3%6'.format(
parseInt(colors[0],16),parseInt(colors[1],16),parseInt(colors[2],16),
rgb[0]?'固':'',
rgb[1]?'固':'',
rgb[2]?'固':'',
)
],'rgb(255,150,150)');
SceneManager._scene.addChild(this._colorPicker);
}
MapDecorator.updateColorPicker = function(){
var picking = this._pickingColor;
this._colorPicker.update();
var color = this._colorPicker.color();
if(color!==picking.color){
picking.color = color;
if(picking.handler){
picking.handler(color);
}
this.refreshColorPickGuideText();
}
if(Input.isTriggered('ok')
|| Input.isTriggered('cancel')
|| TouchInput.isCancelled()
|| (TouchInput.isTriggered()&&!this._colorPicker._touching)
){
_Dev.showText('objColorPick',null);
this._pickingColor = null;
this._colorPicker.visible = false;
SoundManager.playOk();
}
};
MapDecorator.onKeyDownPickingColor = function(event){
if(event.code.indexOf('Digit')===0){
var keyNum = Number(event.code.replace('Digit',''));
var rate = keyNum*0.1;
if(!rate){
rate = 0.05;
}
if(event.shiftKey){
this.setRandomColorsToAllEditingKindMapObjects(rate);
}else{
this.setRandomColor(rate);
}
SoundManager.playCursor();
}else if(event.key==='r'){
this.switchRGBLock(0);
}else if(event.key==='g'){
this.switchRGBLock(1);
}else if(event.key==='b'){
this.switchRGBLock(2);
}
};
MapDecorator.switchRGBLock = function(idx){
if(!this._pickingColor)return;
var rgb = this._pickingColor.rgb;
if(!rgb)return;
if(rgb[idx]){
rgb[idx]=null;
}else{
var color = this._pickingColor.color;
if(!color){
SoundManager.playBuzzer();
return;
}
var value = color.substring(1+idx*2,1+idx*2+2);
rgb[idx] = value;
}
SoundManager.playCursor();
MapDecorator.refreshColorPickGuideText();
};
MapDecorator.setRandomColor = function(rate){
var color = this.randomColorWithRate(rate);
this._colorPicker.setColor(color);
if(this._pickingColor.handler){
this._pickingColor.handler(color);
}
};
MapDecorator.setRandomColorsToAllEditingKindMapObjects = function(rate){
var locObj = this.modeData.lastLocateMapObj;
if(Array.isArray(locObj)){
locObj = this._convertedMapObjMap[JSON.stringify(locObj)];
}
if(!locObj){
SoundManager.playBuzzer();
return;
}
var tag = locObj.tag;
for(const obj of $dataTrpMapObjects){
if(!obj || obj.tag!==tag)continue;
var color = this.randomColorWithRate(rate);
color = Number(color.replace('#','0x'));
obj.tint = color;
if(obj.sprite){
obj.sprite.tint = color;
}
}
};
MapDecorator.randomColorWithRate = function(rate){
var color = '#';
for(var i=0; i<3; i=(i+1)|0){
if(this._pickingColor.rgb[i]){
//locked color
color += this._pickingColor.rgb[i];
}else{
var r10 = 255-Math.floor(Math.randomInt(256)*rate);
var r16 = r10.toString(16);
if(r16.length===0)r16 = '0'+r16;
color += r16;
}
}
return color;
};
/* ColorPicker
===================================*/
function ColorPicker(){
this.initialize.apply(this, arguments);
};
ColorPicker.colorWithHsv = function(h,s,v){
var max = v;
var min = max-((s/255)*max);
var r,g,b;
if(h<=60){
r = max;
g = (h/60)*(max-min)+min;
b = min;
}else if(h<=120){
r = ((120-h)/60)*(max-min)+min;
g = max;
b = min;
}else if(h<=180){
r = min;
g = max;
b = ((h-120)/60)*(max-min)+min;
}else if(h<=240){
r = min;
g = ((240-h)/60)*(max-min)+min;
b = max;
}else if(h<=300){
r = ((h-240)/60)*(max-min)+min;
g = min;
b = max;
}else{
r = max;
g = min;
b = ((360-h)/60)*(max-min)+min;
}
r = Math.round(r).toString(16);
g = Math.round(g).toString(16);
b = Math.round(b).toString(16);
if(r.length===1)r='0'+r;
if(g.length===1)g='0'+g;
if(b.length===1)b='0'+b;
var color = '#'+r+g+b;
return color;
};
ColorPicker.HUE_WIDTH = 20;
ColorPicker.MARGIN = 3;
ColorPicker.prototype = Object.create(PIXI.Container.prototype);
ColorPicker.prototype.constructor = ColorPicker;
ColorPicker.prototype.initialize = function(size){
PIXI.Container.call(this);
this._size = size;
this._hue = -1;
this._saturation = -1;
this._value = -1;
this._color = null;
this._touchingHue = false;
this._touchingSv = false;
this._touching = false;
var margin = ColorPicker.MARGIN;
var hueWidth = ColorPicker.HUE_WIDTH;
var totalWidth = margin*3 + size + hueWidth;
var totalHeight = margin*2 + size;
var bitmap,sprite;
//this > backBitmap
bitmap = new Bitmap(16,16);
bitmap.fillAll('rgba(0,0,0,0.5)');
sprite = new Sprite(bitmap);
this.addChild(sprite);
sprite.scale.set(totalWidth/16,totalHeight/16);
this._backSprite = sprite;
//pickerSprite
bitmap = new Bitmap(size,size);
sprite = new Sprite(bitmap);
this.addChild(sprite);
sprite.x = margin;
sprite.y = margin;
this._pickerSprite = sprite;
this.bitmap = bitmap;
//huePicker
bitmap = new Bitmap(hueWidth,size);
sprite = new Sprite(bitmap);
this.addChild(sprite);
sprite.x = margin*2 + size;
sprite.y = margin;
this._huePicker = sprite;
//pointer
bitmap = new Bitmap(16,16);
sprite = new Sprite(bitmap);
this.addChild(sprite);
sprite.anchor.set(0.5,0.5);
this._pointer = sprite;
var ctx = bitmap._context;
ctx.beginPath();
ctx.arc(8,8,6,0,360*Math.PI/180,false);
ctx.fillStyle = 'rgb(255,255,255)';
ctx.fill();
ctx.beginPath();
ctx.arc(8,8,3,0,360*Math.PI/180,false);
ctx.globalCompositeOperation = "destination-out";
ctx.fill();
//huePointer
var lineWidth = 2;
var spaceHeight = 2;
bitmap = new Bitmap(hueWidth+lineWidth*2,spaceHeight+lineWidth*2);
sprite = new Sprite(bitmap);
this.addChild(sprite);
sprite.anchor.set(0.5,0.5);
this._huePointer = sprite;
bitmap.fillAll('black');
bitmap.clearRect(lineWidth,lineWidth,bitmap.width-lineWidth*2,bitmap.height-lineWidth*2);
this.setupHuePicker();
this.setColor('rgb(255,255,255)');
};
ColorPicker.prototype.setupHuePicker = function(){
var bitmap = this._huePicker.bitmap;
var width = bitmap.width;
var height = bitmap.height;
var s = 255;
var v = 255;
for(var y=0; y<height; y=(y+1)|0){
var h = 360*(y/height);
var color = ColorPicker.colorWithHsv(h,s,v);
bitmap.fillRect(0,y,width,1,color);
}
};
ColorPicker.prototype.setupPalette = function(h){
var bitmap = this._pickerSprite.bitmap;
bitmap.clear();
var width = this.width;
var height = this.height;
var r,g,b;
for(var x=0; x<width; x=(x+1)|0){
var s = 255*x/width;
for(var y=0; y<height; y=(y+1)|0){
var v = 255*y/height;
var color = ColorPicker.colorWithHsv(h,s,v);
bitmap.fillRect(x,height-y-1,1,1,color);
}
}
};
ColorPicker.prototype.setColor = function(color){
var r,g,b;
if(color.indexOf('rgb')!==0){
if(color[0] == "#"){
color = color.substr(1);
}else if(color.indexOf("0x")===0){
color = color.substr(2);
}
if(color.length == 8){
color = color.substr(2);
}
r = parseInt(color.substr(0, 2), 16);
g = parseInt(color.substr(2, 2), 16);
b = parseInt(color.substr(4, 2), 16);
}else{
var args = color.match(/\((.+)\)/)[1].split(',');
r = Number(args[0]);
g = Number(args[1]);
b = Number(args[2]);
}
var h,s,v;
var max = Math.max(r,g,b);
var min = Math.min(r,g,b);
if(r===g && g===b){
h = Math.max(0,this._hue);
}else if(r>=g && r>=b){
h = 60*(g-b)/(max-min);
}else if(g>=r && g>=b){
h = 60*(b-r)/(max-min)+120;
}else{
h = 60*(r-g)/(max-min)+240;
}
s = (max-min)/max*255;
v = max;
if(h<0){
h += 360;
}else if(h>360){
h -= 360;
}
this.setHue(h);
this.setSV(s,v);
};
ColorPicker.prototype.updateResultColor = function(){
this._color = ColorPicker.colorWithHsv(this._hue,this._saturation,this._value);
};
ColorPicker.prototype.color = function(){
return this._color;
};
ColorPicker.prototype.setHue = function(h){
h = h.clamp(0,360);
if(this._hue === h)return;
var dh = h-this._hue;
this._hue = h;
this.setupPalette(this._hue);
var sprite = this._huePicker;
var pointer = this._huePointer;
pointer.x = sprite.x+sprite.width/2;
pointer.y = sprite.y+sprite.height*h/360;
this.updateResultColor();
};
ColorPicker.prototype.setSV = function(s,v){
if(this._saturation===s && this._value===v)return;
this._saturation = s;
this._value = v;
var margin = ColorPicker.MARGIN
var size = this._size;
var pointer = this._pointer;
pointer.x = margin+Math.round((s/255)*size);
pointer.y = margin+Math.round(size-(v/255)*size-1);
this.updateResultColor();
};
ColorPicker.prototype.update = function(){
if(!this.visible){
this._touchingHue = false;
this._touchingSv = false;
return;
}
if(!TouchInput.isTriggered() && !TouchInput.isPressed()){
this._touchingHue = false;
this._touchingSv = false;
return;
}
this._touching = false;
var x = TouchInput.x-this.x;
var y = TouchInput.y-this.y;
var dx,dy,touchInside;
var hPicker = this._huePicker;
dx = x-hPicker.x;
dy = y-hPicker.y;
touchInside = (dx>=0 && dx<=hPicker.width && dy>=0 && dy<=hPicker.height);
if(this._touchingHue || (!this._touchingSv&&touchInside)){
dy = dy.clamp(0,hPicker.height-1);
var hue = Math.round(dy/(hPicker.height-1)*360);
this.setHue(hue);
this._touchingHue = true;
this._touching = true;
return;
}
var svPicker = this._pickerSprite;
dx = x-svPicker.x;
dy = y-svPicker.y;
touchInside = (dx>=0 && dx<=svPicker.width && dy>=0 && dy<=svPicker.height);
if(this._touchingSv || (!this._touchingHue&&touchInside)){
dx = dx.clamp(0,svPicker.width-1);
dy = dy.clamp(0,svPicker.height-1);
var s = Math.round(dx/(svPicker.width-1)*255);
var v = Math.round((svPicker.height-1-dy)/(svPicker.height-1)*255);
this.setSV(s,v);
this._touchingSv = true;
this._touching = true;
return;
}
};
//=============================================================================
// Palette
//=============================================================================
MapDecorator.showingPalette = null;
MapDecorator.paletteBackSprite = null;
MapDecorator.clearShowingPalette = function(notEnd=false){
var palette = this.showingPalette;
this.showingPaldette = null;
if(!palette)return;
this.tryDeletePaletteTilesetCache();
palette.selected = null;
palette.completion = null;
for(const objects of palette.objectsArr){
for(const obj of objects){
if(MapObject && obj instanceof MapObject){
// obj.releaseSprite();
// if(obj.cachable && !notEnd){
// delete obj.cachabe;
// MapObject.cache(obj);
// }
}
}
}
palette.objectsArr = null;
if(palette.sprites){
for(const sprite of palette.sprites){
if(sprite.parent){
sprite.parent.removeChild(sprite);
}
}
}
palette.sprites = null;
if(this.paletteBackSprite && this.paletteBackSprite.parent){
this.paletteBackSprite.parent.removeChild(this.paletteBackSprite);
this.paletteBackSprite.removeChildren();
}
this.showingPalette = null;
_Dev.showText('paletteIndexes',null);
};
MapDecorator.showPalette = function(objectsArr,pageNames,pageIdx,size,m,x0Num,completion,currentIdsArr=null,keySearchEnable=true){
this.clearShowingPalette(true);
this.cantShowMenu = true;
var sprites = null;
/* black sprite
===================================*/
if(!this.paletteBackSprite){
this.paletteBackSprite = new PIXI.Graphics();
}
var backSprite = this.paletteBackSprite;
SceneManager._scene.addChild(backSprite);
_Dev.prepareDebugTextContainer();
/* objects
===================================*/
pageIdx = pageIdx.clamp(0,objectsArr.length-1);
var container = new PIXI.Container();
backSprite.addChild(container);
var selectedArr = this._selectedIdsWithCurrentIds(objectsArr,currentIdsArr);
var cacheKeys = null;
if(isMZ){
cacheKeys = ImageManager._cache ? Object.keys(ImageManager._cache) : null;
}
this.showingPalette = {
objectPaletteMaxY:0,
scrollY:0,
lastWheelFrame:0,
objectsArr,
pageNames,
pageIdx,
sprites,
size,
m,
x0Num,
selected:selectedArr,
completion,
rects:null,
isTileset:false,
tileImageIdx:0,
imageCacheKeys:cacheKeys,
lastTilesetUrl:null,
keySearchEnable,
searchInput:'',
};
/* topSprite
===================================*/
if(!this.topSprite){
this.topSprite = new PIXI.Graphics();
}
this.topSprite.clear();
backSprite.addChild(this.topSprite);
this.refreshPaletteObjects();
SoundManager.playCursor();
return true;
};
MapDecorator._cachedSprites = [];
MapDecorator._cachedBitmaps = [];
MapDecorator._cachePaletteObjects = function(container){
for(var i=container.children.length-1; i>=0; i=(i-1)|0){
var child = container.children[i];
if(child.constructor===Sprite){
MapDecorator._cachedSprites.push(child);
if(child.bitmap){
MapDecorator._cachedBitmaps.push(child.bitmap);
}
child.bitmap = null;
}
container.removeChild(child);
}
};
MapDecorator.refreshPaletteObjects = function(){
var palette = this.showingPalette;
var container = this.paletteBackSprite.children[0];
this._cachePaletteObjects(container);
this.tryDeletePaletteTilesetCache();
var objects = palette.objectsArr[palette.pageIdx];
if(typeof objects ==='string'){
palette.isTileset = true;
this._refreshPaletteTileset(palette,container,objects);
}else{
palette.isTileset = false;
this._refreshPaletteObjects(palette,container,objects);
}
/* pageIndexGuide
===================================*/
if(palette.pageNames && palette.pageNames.length>1){
var texts = ['【表示ページ】'];
texts.push('ホイール/←→:ページ切り替え');
if(palette.objectPaletteMaxY>Graphics.height){
texts.push('Alt+ホイール:スクロール');
}
texts.push('Ctrl+Q/W:ページ±%1'.format(palettePageNum));
if(palette.keySearchEnable){
texts.push('A~Zキー:頭文字検索');
}
var length = palette.pageNames.length;
var i0 = Math.floor(palette.pageIdx/palettePageNum)*palettePageNum;
var i1 = (i0+palettePageNum-1).clamp(0,length-1);
for(var i=i0; i<=i1; i=(i+1)|0){
var name = '%1:%2'.format(i+1,palette.pageNames[i]);
if(i===palette.pageIdx){
name = '\\H[255,50,50,0.9]'+name;
}
texts.push(name);
}
if(i1 !== length-1){
texts.push('      ︙');
}
_Dev.showText('paletteIndexes',texts);
}
};
MapDecorator.tryDeletePaletteTilesetCache = function(){
var palette = this.showingPalette;
if(!palette)return;
if(isMZ && palette.lastTilesetUrl && palette.imageCacheKeys){
if(!palette.imageCacheKeys.contains(palette.lastTilesetUrl)){
var cache = ImageManager._cache[palette.lastTilesetUrl];
if(cache)cache.destroy();
delete ImageManager._cache[palette.lastTilesetUrl];
}
}
palette.lastTilesetUrl = null;
};
MapDecorator._refreshPaletteObjects = function(palette,container,objects){
var size = palette.size;
var m = palette.m;
var x0Num = palette.x0Num;
var x0 = m+(size+m)*x0Num;//avoid guide
var x = x0;
var y = m;
var rects = [];
for(let obj of objects){
var sprite = null;
if(typeof obj==='number'){
if(obj===MapDecorator.VARIATION_FLAG_NO_SUPPLY){
sprite = this._paletteButton('追加\n抽選☓');
}else if(obj===MapDecorator.VARIATION_FLAG_WATER){
sprite = this._paletteButton('水場\n固定','rgb(100,200,255)');
}else{
obj = [obj];
}
// }else if(typeof obj==='string'){
// //category
// var elems = obj.split('::');
// var category = elems[1];
// var idx = Number(elems[2]);
// var data = $dataTrpMapObjectGroups.data[category][idx];
// obj = MapObject.objectFromGroupData(data);
}
if(sprite){
//sprite button
}else if(Array.isArray(obj)){
sprite = this.layeredTilesSprite(obj,size);
}else if(MapObject && obj instanceof MapObject){
//mapObj
sprite = obj.setupSprite(null);
sprite.bitmap.addLoadListener(function(sprite){
var sprSize = Math.max(sprite.width,sprite.height,1);
if(sprSize>size){
sprite.scale.set(size/sprSize,size/sprSize);
}else{
sprite.scale.set(1,1);
}
}.bind(this,sprite));
}
if(x+size>=Graphics.width-m){
x = x0;
y += size+m;
}
if(sprite){
container.addChild(sprite);
sprite.x = x;
sprite.y = y;
if(sprite instanceof PIXI.Sprite){
sprite.anchor.set(0.5,0.5);
sprite.x += size/2;
sprite.y += size/2;
}
}
rects.push([x,y,size,size]);
x += size+m;
}
palette.objectPaletteMaxY = y+size+m;
palette.rects = rects;
this.refreshPaletteBackSprite();
};
MapDecorator._refreshPaletteTileset = function(palette,container,tilesetArg){
var argElems = tilesetArg.split(':');
argElems.shift();
palette.tileImageIdx = Number(argElems.shift());
var name = argElems.join(':');
var bitmap = ImageManager.loadTileset(name);
palette.lastTilesetUrl = 'img/tilesets/'+name+'.png';
var sprite = this.sprite(bitmap);
container.addChild(sprite);
var x0Num = palette.x0Num;
var mx0 = x0Num*palette.size;
sprite.x = mx0;
sprite.y = 0;
var pageIdx = palette.pageIdx;
var rects = [];
palette.objectPaletteMaxY = 0;
palette.rects = rects;
bitmap.addLoadListener(()=>{
if(pageIdx!==palette.pageIdx)return;
this.refreshPaletteBackSprite();
palette.objectPaletteMaxY = bitmap.height;
});
};
MapDecorator.refreshPaletteBackSprite = function(){
var backSprite = this.paletteBackSprite;
backSprite.clear();
backSprite.beginFill(0x888888,0.5)
.drawRect(0,0,Graphics.width,Graphics.height);
var topSprite = this.topSprite;
topSprite.clear();
var palette = this.showingPalette;
if(palette.isTileset){
var x0 = palette.x0Num*palette.size;
//centerline
var sprite = backSprite.children[0].children[0];
topSprite.beginFill(0x000000,1.0)
.drawRect(x0+8*tileW-2,0,4,sprite.height||Graphics.height);
//selected mask
for(const objIdx of palette.selected[palette.pageIdx]){
var col = objIdx%16;
var row = Math.floor(objIdx/16);
topSprite.beginFill(0xffffff,0.5)
.drawRect(x0+col*tileW,row*tileH,tileW,tileH);
};
}else{
var m = 4;
for(const objIdx of palette.selected[palette.pageIdx]){
var rect = palette.rects[objIdx];
backSprite.beginFill(0xff0000,0.8)
.drawRect(rect[0]-m,rect[1]-m,rect[2]+2*m,rect[3]+2*m);
}
}
};
MapDecorator.onWheelValueChangePalette = function(delta){
var palette = this.showingPalette;
if(this.onKeyAlt){
var container = this.paletteBackSprite.children[0];
container.y += delta;
container.y = container.y.clamp(-(palette.objectPaletteMaxY-Graphics.height),0);
palette.scrollY = -container.y;
}else{
if(palette.pageNames.length>1){
if(Graphics.frameCount-palette.lastWheelFrame>=6 || Math.abs(delta)>=50){
if(delta>0){
this.exceedPalettePageIdx(-1);
}else{
this.exceedPalettePageIdx(1);
}
palette.lastWheelFrame = Graphics.frameCount;
}
}
}
};
MapDecorator.onKeyDownPalette = function(event){
var palette = this.showingPalette
if(!palette)return false;
if(event.key==='ArrowLeft'||event.key==='ArrowUp'){
this.exceedPalettePageIdx(-1);
}else if(event.key==='ArrowRight'||event.key==='ArrowDown'){
this.exceedPalettePageIdx(1);
}else if(event.ctrlKey&&event.key==='q'){
this.exceedPalettePageIdx(-palettePageNum);
}else if(event.ctrlKey&&event.key==='w'){
this.exceedPalettePageIdx(palettePageNum);
}else if(!isNaN(event.key)){
var pageIdx = Number(event.key)-1;
if(this.showingPalette.objectsArr[pageIdx]){
this.showingPalette.pageIdx = pageIdx;
this.refreshPaletteObjects();
SoundManager.playCursor();
}else{
SoundManager.playBuzzer();
}
}else if(palette.keySearchEnable && event.key.length===1 && /[a-zA-Z0-9\.\_\- ]/.test(event.key)){
this.trySearchPalettePage(event.key);
}else if(event.key==='q'){
this.exceedPalettePageIdx(-1);
}else if(event.key==='w'){
this.exceedPalettePageIdx(1);
}else{
return false;
}
return true;
};
MapDecorator.exceedPalettePageIdx = function(value=1){
if(this.showingPalette.objectsArr.length<=1){
SoundManager.playBuzzer();
return;
}
var pageIdx = this.showingPalette.pageIdx+value;
if(pageIdx<0)pageIdx = this.showingPalette.objectsArr.length-1;
if(pageIdx>=this.showingPalette.objectsArr.length)pageIdx = 0;
this.showingPalette.pageIdx = pageIdx;
this.refreshPaletteObjects();
SoundManager.playCursor();
};
MapDecorator.trySwitchPalettePageForTilesetNumber = function(number){
var length = this.showingPalette.objectsArr.length;
for(var i=0; i<length; i=(i+1)|0){
var obj = this.showingPalette.objectsArr[i];
if(typeof obj !== 'string')continue;
if(obj.indexOf('tileset:'+number+':')<0)continue;
this.showingPalette.pageIdx = i;
this.refreshPaletteObjects();
SoundManager.playCursor();
return;
}
SoundManager.playBuzzer();
};
MapDecorator.onMouseDownLeftPaletteCommon = function(event,i,x,y,tx,ty,handler=null){
var palette = this.showingPalette;
if(!palette)return;
if(palette.editingObj)return;
ty += palette.scrollY;
if(palette.isTileset){
this._tryTouchPaletteTileset(event,i,x,y,tx,ty,handler);
}else{
this._tryTouchPaletteObjects(event,i,x,y,tx,ty,handler);
}
};
MapDecorator._tryTouchPaletteObjects = function(event,i,x,y,tx,ty,handler){
var palette = this.showingPalette;
var pageIdx = palette.pageIdx;
var rects = palette.rects;
var objIdx = -1;
for(var i=rects.length-1; i>=0; i=(i-1)|0){
var rect = rects[i];
if(tx>=rect[0] && tx<=rect[0]+rect[2]
&& ty>=rect[1] && ty<=rect[1]+rect[3]
){
objIdx = i;
}
}
if(objIdx<0){
if(!handler)SoundManager.playBuzzer();
return;
}
var objects = palette.objectsArr[pageIdx];
var obj = objects[objIdx];
if(handler){
handler(obj,objIdx);
return;
}
var selected = palette.selected[pageIdx];
if(selected.contains(objIdx)){
TRP_CORE.remove(selected,objIdx);
}else{
selected.push(objIdx);
}
this.refreshPaletteBackSprite();
if(palette.completion){
palette.completion(obj,palette.selected.map(idx=>objects[idx]));
}
SoundManager.playCursor();
};
MapDecorator._tryTouchPaletteTileset = function(event,i,x,y,tx,ty,handler=null){
var idx = this._paletteTilesetTouchIdx(tx,ty);
if(idx<0)return;
var palette = this.showingPalette;
palette.selected[palette.pageIdx] = [idx];
SoundManager.playCursor();
this.refreshPaletteBackSprite();
};
MapDecorator.onMousePressPalette = function(tx,ty){
var palette = this.showingPalette;
if(!palette.isTileset)return;
var idx = this._paletteTilesetTouchIdx(tx,ty);
if(idx<0)return;
var selected = palette.selected[palette.pageIdx];
if(selected[selected.length-1]===idx)return;
var idx0 = selected[0];
var col0 = idx0%16;
var row0 = Math.floor(idx0/16);
var halfIdx0 = Math.floor(col0/8);
var col = idx%16;
var row = Math.floor(idx/16);
var halfIdx1 = Math.floor(col/8);
if(halfIdx0!==halfIdx1){
_Dev.showTempText('tilesetPickError','タイルセット画像の左右をまたいだオブジェクトは設定できません','red')
return;
}
selected.length = 1;
if(idx0!==idx){
var dc = col>col0 ? 1 : -1;
var dr = row>row0 ? 1 : -1;
for(var c=col0;; c=(c+dc)|0){
for(var r=row0;; r=(r+dr)|0){
var i = r*16+c;
if(!selected.contains(i)){
selected.push(i);
}
if(r===row)break;
}
if(c===col)break;
}
}
this.refreshPaletteBackSprite();
SoundManager.playCursor();
}
MapDecorator.onMouseUpLeftShowingPalette = function(event,tx,ty){
var palette = this.showingPalette;
if(!palette)return;
if(palette.editingObj)return;
var selected = palette.selected[palette.pageIdx];
if(!selected)return;
if(!selected.length)return;
if(!palette.completion)return;
var baseId;
var tileIdSign = 1;
if(palette.tileImageIdx>=0){
baseId = (palette.tileImageIdx-5)*256;
}else{
var tilesetImage = TRP_CORE.last(palette.objectsArr[palette.pageIdx].split(':'));
MapObject.registerObjectGroupTilesetImage(tilesetImage);
baseId = -256*$dataTrpMapObjectGroups.tilesetImageIds.indexOf(tilesetImage);
tileIdSign = -1;
}
var selected = palette.selected[palette.pageIdx];
var idx0 = selected[0];
var idx1 = selected[selected.length-1];
var col0 = idx0%16;
var row0 = Math.floor(idx0/16);
var col1 = idx1%16;
var row1 = Math.floor(idx1/16);
var col = Math.min(col0,col1);
var row = Math.min(row0,row1);
var w = Math.abs(col1-col0)+1;
var h = Math.abs(row1-row0)+1;
var halfIdx = Math.floor(col/8);
col = col%8;
var innerIdx = halfIdx*128 + row*8+col;
var tileId = baseId + tileIdSign*innerIdx;
var obj;
if(tileIdSign<0){
//other tilesetImage -> mapObj
obj = MapObject.object();
obj.setupCommonBefore();
obj.tileId = tileId;
obj.tileW = w;
obj.tileH = h;
obj.setupCommonAfter();
palette.lastTilesetUrl = null;
MapDecorator.registerMapObjectTemplateWithMapObject(obj);
_Dev.showText('decorator:otherTile',[
'Ctrl+T他のタイルセット画像を登録'
],'red')
}else{
obj = [];
for(var c=0; c<w; c=(c+1)|0){
var col = [];
obj.push(col);
for(var r=0; r<h; r=(r+1)|0){
col.push([tileId+tileIdSign*(c+r*8)]);
}
}
}
palette.completion(obj);
SoundManager.playCursor();
};
/* palette -> helper
===================================*/
MapDecorator._selectedIdsWithCurrentIds = function(objectsArr,currentIdsArr){
var selectedArr = [];
for(var i=objectsArr.length-1; i>=0; i=(i-1)|0){
selectedArr.push([]);
}
if(currentIdsArr){
for(var pi=0; pi<currentIdsArr.length; pi=(pi+1)|0){
var selected = selectedArr[pi];
var objects = objectsArr[pi];
var currentIds = currentIdsArr[pi];
if(currentIds){
for(const ids of currentIds){
var idsStr = JSON.stringify(ids);
for(var i=objects.length-1; i>=0; i=(i-1)|0){
var obj = objects[i];
if(JSON.stringify(obj) === idsStr){
selected.push(i);
break;
}
}
}
if(currentIds.contains(MapDecorator.VARIATION_FLAG_SUPPLY)){
TRP_CORE.remove(selected,0);
}else if(currentIds.length){
selected.push(0);
}
}
}
}
return selectedArr;
};
MapDecorator._paletteButton = function(text,color='white',size=48){
var bitmap = this.bitmap(size,size);
var lines = text.split('\n');
var lineH = (size-2)/lines.length;
var length = lines.length;
bitmap.fontSize = lineH/1;
bitmap.textColor = color;
bitmap.outlineColor = 'black';
bitmap.outlineWidth = 4;
for(var i=0; i<length; i=(i+1)|0){
var line = lines[i];
var y = i*lineH + 1;
bitmap.drawText(line,0,y,size,lineH,'center');
}
var sprite = new Sprite(bitmap);
return sprite;
};
MapDecorator.layeredTilesSprite = function(obj,size=0){
if(!Array.isArray(obj))return null;
if(!Array.isArray(obj[0])){
obj = [[obj]];
}
var w = obj.length;
var h = obj[0].length;
var bitmap = this.bitmap(w*tileW,h*tileH);
var sprite = this.sprite(bitmap);
var sprSize = Math.max(w*tileW,h*tileH);
if(size && sprSize>size){
sprite.scale.set(size/sprSize,size/sprSize);
}else{
sprite.scale.set(1,1);
}
var tilemap = SceneManager._scene._spriteset._tilemap;
var bitmaps = tilemap._bitmaps||tilemap.bitmaps;
for(var c=0; c<w; c=(c+1)|0){
var x = c*tileW;
var col = obj[c];
for(var r=0; r<h; r=(r+1)|0){
var y = r*tileH;
var tileIds = col[r];
if(!tileIds)continue;
var tileLen = tileIds.length;
for(var ti=0; ti<tileLen; ti=(ti+1)|0){
var tileId = tileIds[ti];
if(!tileId)continue;
if(ti===tileLen-1 && Tilemap.isAutotile(tileId) && !Tilemap.isWallTile(tileId)){
//autoTile -> close
tileId = baseTileId(tileId)+47;
}
TRP_CORE._drawTile(bitmap,tileId,x,y,bitmaps);
}
}
}
return sprite;
};
MapDecorator._paletteTilesetTouchIdx = function(tx,ty){
var palette = this.showingPalette;
var pageIdx = palette.pageIdx;
var container = this.paletteBackSprite.children[0];
var sprite = container.children[0];
if(!sprite)return -1;
tx -= sprite.x;
ty -= sprite.y;
if(tx<0 || tx>=sprite.width)return -1;
if(ty<0 || ty>=sprite.height)return -1;
var col = Math.floor(tx/tileW);
var row = Math.floor(ty/tileH);
var idx = col+row*16;
return idx;
};
MapDecorator.trySearchPalettePage = function(key){
var palette = this.showingPalette;
var inputting = palette.searchInput += key;
var files = palette.pageNames;
var length = files.length;
for(var i=0; i<length; i=(i+1)|0){
var file = files[i].toLowerCase();
if(file.indexOf(inputting) === 0){
if(palette.pageIdx!==i){
palette.pageIdx = i;
this.refreshPaletteObjects();
SoundManager.playCursor();
return;
}else{
break;
}
}
}
if(inputting.length>1){
palette.searchInput = '';
this.trySearchPalettePage(key);
}else{
SoundManager.playCursor();
}
};
//=============================================================================
// TilesetEdit
//=============================================================================
MapDecorator.MODE_GUIDE.tilesetEdit = [
'【タイルセット画像登録】',
'左クリック:タイル位置の決定',
'右クリック:キャンセル',
'Q/W画像切り替え',
'\\C[255,255,0]■:現マップで使用中'
];
MapDecorator.showingTilesetEditIdx = 0;
MapDecorator.endModeTilesetEdit = function(){
var uiCache = this.modeUICache;
if(uiCache){
var sprite = uiCache.sprite;
TRP_CORE.removeFromParent(sprite);
MapDecorator._cachedSprites.push(sprite);
sprite = uiCache.canvasSprite;
if(sprite)sprite.removeChildren();
TRP_CORE.removeFromParent(sprite);
MapDecorator._cachedSprites.push(sprite);
var screen = uiCache.screen;
TRP_CORE.removeFromParent(screen);
if(uiCache.completion){
uiCache.completion(null);
uiCache.completion = null;
}
}
_Dev.showText('tilesetEditOnSelect',null);
};
MapDecorator.onKeyDownTilesetEdit = function(event){
if(!this.modeData)return;
if(event.key==='q'){
var idx = MapDecorator.showingTilesetEditIdx-1;
if(idx<0)idx = this.modeData.tilesetNames.length-1;
this.setTilesetCanvasPageIdx(idx);
SoundManager.playCursor();
}else if(event.key=='w'){
var idx = MapDecorator.showingTilesetEditIdx+1;
if(!this.modeData.tilesetNames[idx])idx = 0;
this.setTilesetCanvasPageIdx(idx);
SoundManager.playCursor();
}else if(event.key==='s'){
this.tryExecuteTilesetEdit();
}else if(event.key==='Escape'){
this.restoreMode(true);
SoundManager.playBuzzer();
}else if(event.key==='ArrowLeft'){
this.tryMoveTilesetEditSprite(-1,0);
}else if(event.key==='ArrowRight'){
this.tryMoveTilesetEditSprite(1,0);
}else if(event.key==='ArrowUp'){
this.tryMoveTilesetEditSprite(0,-1);
}else if(event.key==='ArrowDown'){
this.tryMoveTilesetEditSprite(0,1);
}
};
MapDecorator.onWheelValueChangeTilesetEdit = function(delta){
if(!this.modeData)return;
var modeData = this.modeData;
if(modeData.tilesetNames.length>1){
if(Graphics.frameCount-modeData.lastWheelFrame>=6 || Math.abs(delta)>=50){
if(delta>0){
var idx = MapDecorator.showingTilesetEditIdx-1;
if(idx<0)idx = this.modeData.tilesetNames.length-1;
this.setTilesetCanvasPageIdx(idx);
SoundManager.playCursor();
}else{
var idx = MapDecorator.showingTilesetEditIdx+1;
if(!this.modeData.tilesetNames[idx])idx = 0;
this.setTilesetCanvasPageIdx(idx);
SoundManager.playCursor();
}
modeData.lastWheelFrame = Graphics.frameCount;
}
}
};
MapDecorator.tryExecuteTilesetEdit = function(){
var modeData = this.modeData;
var uiCache = this.modeUICache;
if(!modeData || !uiCache || !uiCache.sprite)return;
if(modeData.locateXi<0)return;
var xi = modeData.locateXi;
var yi = modeData.locateYi;
var pageIdx = MapDecorator.showingTilesetEditIdx;
var allEmpty = modeData.allEmptyPositionsArr[pageIdx].contains(xi+yi*16);
if(!allEmpty){
SoundManager.playCursor();
if(!confirm('空じゃないタイルが含まれています。\n本当に画像を上書きしますか')){
return;
}
}
//edit canvas
var canvas = uiCache.canvas;
var bitmap = uiCache.bitmap;
var tx = xi*tileW;
var ty = yi*tileH;
canvas.clearRect(tx,ty,modeData.tileW*tileW,modeData.tileH*tileH);
tx += modeData.locateDx;
ty += modeData.locateDy;
TRP_CORE.bltImage(canvas,bitmap,0,0,bitmap.width,bitmap.height,tx,ty);
//save image
var name = modeData.tilesetNames[MapDecorator.showingTilesetEditIdx];
var filePath = 'img/tilesets/'+name+'.png';
_Dev.saveCanvas(canvas,filePath);
//replace all bitmap
if(isMZ){
if(ImageManager._cache){
ImageManager._cache[filePath] = canvas;
}
}else{
if(ImageManager._imageCache){
ImageManager._imageCache._items[filePath] = canvas;
}
}
var completion = uiCache.completion;
uiCache.completion = null;
var setNumber = modeData.tilesetNumbers[pageIdx];
var tileIds = [];
var tileIdBase = 256*(setNumber-5);
for(var dx=0; dx<modeData.tileW; dx=(dx+1)|0){
for(var dy=0; dy<modeData.tileH; dy=(dy+1)|0){
var x = xi+dx;
var y = yi+dy;
var tileId = tileIdBase+128*Math.floor(x/8)+x%8+y*8;
tileIds.push(tileId);
}
}
//end
SoundManager.playSave();
this.restoreMode(true);
if(completion){
completion(tileIds);
}
};
MapDecorator.tryMoveTilesetEditSprite = function(dx=0,dy=0){
var modeData = this.modeData;
var uiCache = this.modeUICache;
if(!modeData || !uiCache || !uiCache.sprite)return;
if(modeData.locateXi<0)return;
modeData.locateDx += dx;
modeData.locateDy += dy;
var sprite = uiCache.sprite;
var maxX = tileW-(sprite.width-1)%tileW-1;
var maxY = tileH-(sprite.height-1)%tileH-1;
modeData.locateDx = (modeData.locateDx+dx).clamp(0,maxX);
modeData.locateDy = (modeData.locateDy+dy).clamp(0,maxY);
var canvasSprite = uiCache.canvasSprite;
sprite.x = canvasSprite.x + modeData.locateXi*tileW+modeData.locateDx;
sprite.y = canvasSprite.y + modeData.locateYi*tileH+modeData.locateDy;
SoundManager.playCursor();
}
MapDecorator.onMouseDownRightTilesetEdit = function(){
this.restoreMode(true);
SoundManager.playCancel();
};
MapDecorator.onMouseDownLeftTilesetEdit = function(event,roomId,x,y,tx,ty,dx,dy){
var modeData = this.modeData;
var uiCache = this.modeUICache;
if(!modeData || !uiCache || !uiCache.sprite)return;
var sprite = uiCache.sprite;
var canvasSprite = uiCache.canvasSprite;
var targetArea = uiCache.targetArea;
var x = tx-canvasSprite.x;
var y = ty-canvasSprite.y;
var xi = Math.floor(x/tileW);
var yi = Math.floor(y/tileH);
if(modeData.locateXi===xi && modeData.locateYi===yi){
modeData.locateXi = -1;
modeData.locateYi = -1;
SoundManager.playCursor();
targetArea.visible = false;
_Dev.showText('tilesetEditOnSelect',null);
}else if(xi<0 || xi>16-modeData.tileW
|| yi<0 || yi>=16-modeData.tileH
){
SoundManager.playBuzzer();
}else{
var canvasSprite = uiCache.canvasSprite;
modeData.locateXi = xi;
modeData.locateYi = yi;
modeData.locateDx = 0;
modeData.locateDy = 0;
sprite.x = canvasSprite.x+xi*tileW;
sprite.y = canvasSprite.y+yi*tileH;
sprite.opacity = 255;
SoundManager.playCursor();
targetArea.visible = true;
targetArea.clear();
targetArea.beginFill(0xff0000,0.5)
.drawRect(xi*tileW,yi*tileH,tileW*modeData.tileW,tileH*modeData.tileH);
var allEmpty = modeData.allEmptyPositionsArr[MapDecorator.showingTilesetEditIdx].contains(xi+yi*16);
var help = [
'カーソルキー:位置の微調整',
'Sキータイルセット画像に登録',
];
if(!allEmpty){
help.push('\\C[255,0,0]※既存タイルが上書きされます!!');
}
_Dev.showText('tilesetEditOnSelect',help);
}
};
MapDecorator.updateTilesetEdit = function(){
var modeData = this.modeData;
var uiCache = this.modeUICache;
if(!modeData || !uiCache || !uiCache.sprite)return;
if(modeData.locateXi>=0)return;
var canvasSprite = uiCache.canvasSprite;
var sprite = uiCache.sprite;
var x = TouchInput.x-canvasSprite.x;
var y = TouchInput.y-canvasSprite.y;
var xi = Math.floor(x/tileW);
var yi = Math.floor(y/tileH);
if(x<0 || x>=canvasSprite.width
|| y<0 || y>=canvasSprite.height
){
sprite.visible = false;
}else{
sprite.visible = true;
sprite.opacity = 128;
sprite.x = canvasSprite.x + xi*tileW;
sprite.y = canvasSprite.y + yi*tileH;
}
};
MapDecorator.startTilesetEdit = function(bitmap,completion=null){
this.setMode('tilesetEdit');
this.cantScroll = true;
//screen
var screen = new PIXI.Graphics();
screen.beginFill(0x000000,0.8)
.drawRect(0,0,Graphics.width,Graphics.height);
SceneManager._scene.addChild(screen);
//canvas back
var canvasBack = new PIXI.Graphics();
screen.addChild(canvasBack);
for(var c=0; c<16*4; c+=1){
for(var r=0; r<16*4; r+=1){
canvasBack.beginFill((r+c)%2===0 ? 0xdcdcdc : 0xffffff)
.drawRect(c*tileW/4,r*tileH/4,tileW/4,tileH/4);
}
}
//canvas sprite
var canvas = new Bitmap(16*tileW,16*tileH);
var canvasSprite = this.sprite(canvas);
screen.addChild(canvasSprite);
canvasSprite.x = (Graphics.width-canvas.width)/2;
canvasSprite.y = (Graphics.height-canvas.height)/2;
canvasBack.x = canvasSprite.x;
canvasBack.y = canvasSprite.y;
//usingScreen
var usingScreen = new PIXI.Graphics();
canvasSprite.addChild(usingScreen);
//grid
var grid = this.tileGridGraphic(16,16);
canvasSprite.addChild(grid);
//targetArea
var targetArea = new PIXI.Graphics();
canvasSprite.addChild(targetArea);
//prepare tilesetNames
var srcTileNames = $gameMap.tileset().tilesetNames;
var tilesetNames = [];
var tilesetNumbers = [];
for(var i=5; i<srcTileNames.length; i=(i+1)|0){
var tileName = srcTileNames[i];
if(!tileName)continue;
tilesetNames.push(tileName);
tilesetNumbers.push(i);
};
//target sprite
var sprite = this.sprite(bitmap);
screen.addChild(sprite);
//setup modeData
this.modeData = {
tilesetNames,tilesetNumbers,
w:bitmap.width,
h:bitmap.height,
tileW:Math.ceil(bitmap.width/tileW),
tileH:Math.ceil(bitmap.height/tileH),
emptyPositionsArr:[],
usingTilePositionsArr:[],
allEmptyPositionsArr:[],
locateXi:-1,locateYi:-1,
locateDx:0,locateDy:0,
usingTileIds:this.usingTileIds(),
};
this.modeUICache = {
bitmap,sprite,screen,canvas,canvasSprite,usingScreen,grid,targetArea,completion
};
_Dev.prepareDebugTextContainer();
this.setTilesetCanvasPageIdx(MapDecorator.showingTilesetEditIdx,true);
};
MapDecorator.usingTileIds = function(){
var result = [];
var map = {};
for(var i=data.length-1; i>=0; i=(i-1)|0){
var tileId = data[i];
if(tileId && !map[tileId]){
map[tileId] = true;
result.push(tileId);
}
}
for(const event of $dataMap.events){
if(!event)continue;
for(const page of event.pages){
if(!page)continue;
var tileId = page.image.tileId;
if(tileId && !map[tileId]){
map[tileId] = true;
result.push(tileId);
}
}
}
var current = [];
var next = [];
for(const roomObjInfoArr of proc.lastObjInfoArr){
if(!roomObjInfoArr)continue;
for(const objInfo of roomObjInfoArr){
var obj = objInfo[1];
var tileIds;
if(Array.isArray(obj)){
tileIds = obj;
}else if(MapObject){
tileIds = obj.tileIds();
}
if(!tileIds)continue;
current.length = 0;
next.length = 0;
next.push(tileIds);
while(next.length){
var temp = current;
current = next;
next = temp;
next.length = 0;
for(const arr of current){
for(const elem of arr){
if(Array.isArray(elem)){
next.push(elem);
}else{
if(elem && !map[elem]){
map[elem] = true;
result.push(elem);
}
}
}
}
}
}
}
return result;
};
MapDecorator.setTilesetCanvasPageIdx = async function(idx,force=false){
var modeData = this.modeData;
var uiCache = this.modeUICache;
if(!modeData || !uiCache)return;
var name = modeData.tilesetNames[idx];
var tilesetNumber = modeData.tilesetNumbers[idx];
if(!name)return;
if(!force && MapDecorator.showingTilesetEditIdx===idx)return;
MapDecorator.showingTilesetEditIdx = idx;
modeData.locateXi = modeData.locateYi = -1;
modeData.locateDx = modeData.locateDy = 0;
uiCache.targetArea.visible = false;
_Dev.showText('tilesetEditOnSelect',null);
var src = ImageManager.loadTileset(name);
await new Promise(resolve=>src.addLoadListener(resolve));
var canvas = uiCache.canvas;
canvas.clear();
TRP_CORE.bltImage(canvas,src,0,0,Math.min(canvas.width,src.width),Math.min(canvas.height,src.height),0,0);
var usingScreen = uiCache.usingScreen;
usingScreen.clear();
var col = Math.ceil(src.width/tileW);
var row = Math.ceil(src.height/tileH);
var usingTileIds = modeData.usingTileIds;
var emptyPositionsArr = modeData.emptyPositionsArr;
var allEmptyPositionsArr = modeData.allEmptyPositionsArr;
var usingTilePositionsArr = modeData.usingTilePositionsArr;
if(!emptyPositionsArr[idx]){
/* analyze empty tile positions
===================================*/
var emptyPositions = emptyPositionsArr[idx] = [];
var allEmptyPositions = allEmptyPositionsArr[idx] = [];
var usingTilePositions = usingTilePositionsArr[idx] = [];
var width = src.width;
var height = src.height;
var imageData = src.context.getImageData(0,0,width,height);
var data = imageData.data;
var length = data.length;
for(var c=0; c<16; c=(c+1)|0){
for(var r=0; r<16; r=(r+1)|0){
var tileId = 256*(tilesetNumber-5)+128*Math.floor(c/8)+c%8+r*8;
// if(tileId)console.log(tileId);
if(tileId && usingTileIds.contains(tileId)){
usingTilePositions.push(c+r*16);
continue;
}
var baseX = c*tileW;
var baseY = r*tileH;
var baseIdx = (baseX + width*baseY);
var tileUsing = false;
// canvas.drawText(c+','+r,baseX,baseY,tileW,tileH)
for(var dx=0; dx<tileW; dx=(dx+1)|0){
if(baseX+dx >= width){
break;
}
for(var dy=0; dy<tileH; dy=(dy+1)|0){
if(baseY+dy >= height){
// if(stop)debugger;
break;
}
var i = baseIdx + (dx+width*dy);
if(data[4*i+3]>3){
tileUsing = true;
// usingScreen.beginFill(0xff0000,1)
// .drawRect(baseX+dx,baseY+dy,3,3);
break;
}
}
if(tileUsing)break;
}
if(!tileUsing){
emptyPositions.push(c+r*16);
}
}
}
var targetW = Math.ceil(uiCache.sprite.width/tileW);
var targetH = Math.ceil(uiCache.sprite.height/tileH);
for(var c=0; c<=16-targetW; c=(c+1)|0){
for(var r=0; r<=16-targetH; r=(r+1)|0){
var allEmpty = true;
for(var dx=0; dx<targetW; dx=(dx+1)|0){
for(var dy=0; dy<targetH; dy=(dy+1)|0){
if(!emptyPositions.contains(c+dx+(r+dy)*16)){
allEmpty = false;
break;
}
}
if(!allEmpty)break;
}
if(allEmpty){
allEmptyPositions.push(c+r*16);
}
}
}
}
var emptyPositions = emptyPositionsArr[idx];
var usingTilePositions = usingTilePositionsArr[idx];
for(var c=0; c<row; c=(c+1)|0){
for(var r=0; r<col; r=(r+1)|0){
if(emptyPositions.contains(c+r*16))continue;
if(usingTilePositions.contains(c+r*16)){
usingScreen.beginFill(0xffff00,0.5)
.drawRect(c*tileW,r*tileH,tileW,tileH);
}else{
usingScreen.beginFill(0x000000,0.5)
.drawRect(c*tileW,r*tileH,tileW,tileH);
}
}
}
};
//=============================================================================
// ParallaxSave
//=============================================================================
MapDecorator.saveAsParallaxMock = function(){
var visibles = [];
var spriteset = SceneManager._scene._spriteset;
var tilemap = spriteset._tilemap;
var canvasW = width*tileW;
var canvasH = height*tileH;
var saveData = {
displayX:$gameMap._displayX,
displayY:$gameMap._displayY,
mapData:$dataMap.data.concat(),
};
var dx = $gameMap._displayX*tileW;
var dy = $gameMap._displayY*tileH;
$gameMap._displayX = 0;
$gameMap._displayY = 0;
var tilemapSave = {
margin:tilemap._margin,
ox:tilemap.origin.x,
oy:tilemap.origin.y,
};
if(isMZ){
tilemapSave.width = tilemap.width;
tilemapSave.height = tilemap.height;
tilemap.width = canvasW;
tilemap.height = canvasH;
}else{
//MV -> ShaderTilmeap
tilemapSave.width = tilemap._width;
tilemapSave.height = tilemap._height;
tilemap._width = canvasW;
tilemap._height = canvasH;
}
tilemap._margin = 0;
tilemap.origin.x = 0;
tilemap.origin.y = 0;
tilemap._needsRepaint = true;
tilemap.updateTransform();
//clear shadows
for(var i=0; i<zLayerSize; i=(i+1)|0){
$dataMap.data[zLayerSize*4+i] = 0;
}
/* activate mapObjSprite
===================================*/
var dispX = 0;
var dispY = 0;
for(const obj of $dataTrpMapObjects){
var x = obj.x + obj.aX - dispX;
var y = obj.y + obj.aY - dispY;
if(!obj.sprite){
obj.setupSprite(spriteset);
}
var sprite = obj.sprite;
if(sprite.baseX!==x || sprite.baseY!==y){
sprite.setPosition(x,y);
}
}
for(var proc=0; proc<2; proc=(proc+1)|0){
//proc:[0=setVisibility, 1:restoreVisibility]
var nexts = [spriteset];
var currents = [];
while(nexts.length){
var temp = currents;
currents = nexts;
nexts = temp;
nexts.length = 0;
for(const parent of currents){
for(const child of parent.children){
if(child===tilemap){
nexts.push(child);
}else if(child===tilemap._lowerLayer||child===tilemap._upperLayer||child===tilemap.lowerZLayer||child===tilemap.upperZLayer){
//mainLayer -> ok
}else{
switch(child.constructor){
case PIXI.Container:
case TRP_CORE.TRP_Container:
//container -> ok
nexts.push(child);
break;
case TRP_CORE.MapObjectSprite:
//mapObj -> ok
break;
default:
nexts.push(child);
if(proc===0){
visibles.push(child.visible);
child.visible = false;
}else{
child.visible = visibles.shift();
}
}
}
}
}
}
if(proc===0){
//save mock image
var bitmap = TRP_CORE.snap(tilemap,canvasW,canvasH);
bitmap.fontSize = 32;
bitmap.outlineWidth = 6;
bitmap.drawText('モック表示中(遠景)',2,2,canvasW,Math.min(100,canvasH));
var imageName = TRP_CORE.MOCK_IMAGE_DIR+TRP_CORE.mapFileName().replace('.json','');
var imageFilePath = 'img/parallaxes/'+imageName+'.png';
_Dev.ensureDirectoriesWithFilePath(imageFilePath);
_Dev.saveCanvas(bitmap,imageFilePath);
//save mockMapData
_Dev.saveMapFile(undefined,undefined,true);
}
}
/* restore state
===================================*/
$gameMap._displayX = saveData.displayX;
$gameMap._displayY = saveData.displayY;
$dataMap.data = saveData.mapData;
if(isMZ){
tilemap.width = tilemapSave.width;;
tilemap.height = tilemapSave.height;
}else{
tilemap._width = tilemapSave.width;
tilemap._height = tilemapSave.height;
}
tilemap._margin = tilemapSave.margin;
tilemap.origin.x = tilemapSave.ox;
tilemap.origin.y = tilemapSave.oy;
tilemap._needsRepaint = true;
tilemap.updateTransform();
/* restore mapObj
===================================*/
for(const obj of $dataTrpMapObjects){
obj.update(spriteset,$gameMap._displayX,$gameMap._displayY)
}
};
//================================================
// dev test func
//================================================
MapDecorator.devTest = function(){
if(!_Dev.inDev)return;
};
})();