烁灵 发表于 2024-5-31 13:02:26

【汉化】Sigureya存档界面

本帖最后由 烁灵 于 2024-5-31 18:24 编辑

在存档界面显示额外的内容

・游戏时间
・地图名(显示名称)
・地图名(编辑名称)
・存档时间
・变量值
・最后一次显示文章内容
・图片


原地址:Sigureya/RPGmakerMZ: RPGmakerMZ plugins (github.com)

预览:



范例:https://www.123pan.com/s/uBKyVv-YzF3A.html 提取码:9Nst

脚本:
//@ts-check

//=============================================================================
// Mano_SaveFileInfo.js
// ----------------------------------------------------------------------------
// Copyright (c) 2022-2022 Sigureya
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 1.0.0 2022/04/14 初版
// ----------------------------------------------------------------------------
// : https://twitter.com/Sigureya/
//=============================================================================

/*:
* @plugindesc 在存档界面显示额外的内容。
* 汉化 by 烁灵 更多脚本请访问 www.hknmtt.com
* @author しぐれん
*
* @target MZ
* @orderAfter NUUN_SaveScreen
* @orderAfter AltSaveScreen
*
* @command SetText
* @desc 指定变量保存文本,支持换行符 \n
* @arg variableId
* @text 变量ID
* @type variable
* @default 0
*
* @arg text
* @text 显示的文本
* @type multiline_string
*
* @param listWindow
* @text 文件列表窗口设置
* @type struct<Rect>
* @default {"x":"270","y":"112","width":"616","height":"340"}
*
* @param numVisibleRows
* @text 行数
* @desc 如果用其他脚本指定存档文件数量,请填 99
* @type number
* @min 1
* @default 3
*
* @param maxCols
* @text 列数
* @type number
* @min 1
* @default 2
*
* @param leftWindow
* @text 左侧窗口设置
* @type struct<Rect>
* @default {"x":"0","y":"112","width":"270","height":"340"}
*
* @param leftSpriteList
* @text 左侧图片设置
* @type struct<SpriteV2>[]
* @parent leftWindow
* @default ["{\"table\":\"[]\",\"variableId\":\"1\",\"bitmap\":\"\",\"x\":\"0\",\"y\":\"0\",\"width\":\"200\",\"height\":\"200\",\"anthorX\":\"0\",\"anthorY\":\"0\",\"isUpper\":\"false\"}"]
*
* @param leftTextList
* @text 左侧文字设置
* @type struct<TextFormat>[]
* @parent leftWindow
* @default ["{\"symbol\":\"variable\",\"variableId\":\"1\",\"nameFormat\":\"立绘变量:\",\"valueFormat\":\"%1\",\"valueColor\":\"\",\"indentLevel\":\"32\",\"numLines\":\"1\"}","{\"symbol\":\"playtime\",\"variableId\":\"0\",\"nameFormat\":\"游戏时间\",\"valueFormat\":\"%1\",\"valueColor\":\"\",\"indentLevel\":\"0\",\"numLines\":\"1\"}","{\"symbol\":\"timestamp\",\"variableId\":\"0\",\"nameFormat\":\"%1\",\"valueFormat\":\"\",\"valueColor\":\"\",\"indentLevel\":\"0\",\"numLines\":\"1\"}","{\"symbol\":\"mapname\",\"variableId\":\"0\",\"nameFormat\":\"\",\"valueFormat\":\"%1\",\"valueColor\":\"\",\"indentLevel\":\"0\",\"numLines\":\"1\"}","{\"symbol\":\"mapinfo\",\"variableId\":\"0\",\"nameFormat\":\"\",\"valueFormat\":\"%1\",\"valueColor\":\"\",\"indentLevel\":\"0\",\"numLines\":\"1\"}"]
*
* @param leftTextPosition
* @text 左侧文字窗口配置
* @parent leftWindow
* @type struct<Rect>
* @default {"x":"0","y":"140","width":"270","height":"340"}
*
* @param bottomWindow
* @type struct<Rect>
* @default {"x":"0","y":"452","width":"808","height":"180"}
*
* @param bottomSpriteList
* @text 下方图像列表配置
* @type struct<SpriteV2>[]
* @parent bottomWindow
* @default []
*
* @param bottomTextList
* @text 下方文字列表配置
* @type struct<TextFormat>[]
* @parent bottomWindow
* @default ["{\"symbol\":\"lastmsg\",\"variableId\":\"0\",\"nameFormat\":\"%1\",\"valueFormat\":\"\",\"valueColor\":\"\",\"indentLevel\":\"0\",\"numLines\":\"4\"}"]
*
* @param bottomTextPosition
* @text 下方文字位置
* @parent bottomWindow
* @type struct<Rect>
* @default {"x":"0","y":"0","width":"808","height":"130"}
*
* @param lastMessageSwitch
* @text 最后一次显示文章记录
* @desc 为 ON 的时候会自动记录最后一次显示文章的内容。游戏开始时会设置为 ON
* @type switch
* @default 0
*
* @help
* 启用插件后需要保存一次
* 插件无效的情况下不会引起错误。
*
* 在两个位置添加一个信息窗口,一个在文件列表的左侧,一个在底部。。
* 以下信息可以显示在信息窗口中
* 这些设置是在插件参数中进行。
* ・游戏时间
* ・地图名(显示名称)
* ・地图名(编辑名称)
* ・存档时间
* ・变量值
* ・最后一次显示文章内容
* ・图片
*
* ■与其他插件的关系
* ・NUUN_SaveScreen
* 可以同时使用。
*
* ■AltSaveScreen
* 由于都修改了存档布局,不能同时使用
* 可通过技术自行解决
*
* ■利用規約
* MIT Licenseです。
* ご自由にお使いください。
*/
/*~struct~Rect:
* @param x
* @type number
* @default 0
*
* @param y
* @type number
* @default 0
*
* @param width
* @text 宽度
* @type number
* @default 200
*
* @param height
* @text 高度
* @type number
* @default 200
*/
/*~struct~ActorImage:
* @param dataType
* @type select
* @param memberIndex
* @type number
* @default 0
*/
/*~struct~TextTableItem:
* @param value
* @type number
* @default 1
*
* @param item
* @type multiline_string
* @text 显示的文章
* @desc 不能使用控制字符。
*
*/

/*~struct~TextV2:
* @param table
* @text 文本列表
* @desc 使用指定变量的值
* 从这个类型中取图片
* @type struct<TextTableItem>[]
* @default []
*
* @param variableid
* @text 变量ID
* @type variable
* @desc 根据变量的值切换图片
* @default 0
*
* @param numLines
* @type number
* @default 1
* @min 1
*/
/*~struct~TextFormat:
* @param symbol
* @text 显示的文本种类
* @type select
* @option 无
* @value
* @option 游戏时间
* @value playtime
* @option 地图名称(显示名称)
* @value mapname
* @option 地图名称(编辑名称)
* @value mapinfo
* @option 存档时间
* @value timestamp
* @option 变量值
* @value variable
* @option 最后的显示文章
* @value lastmsg
* @default
*
* @param variableId
* @text 变量ID
* @type variable
* @desc 显示的文字种类
* 变量指定的场合使用的变量ID
* @default 0
*
* @param nameFormat
* @text 左侧项目显示格式
* @desc 使用 %1 来取得指定的参数。
* 可以使用控制字符
* @type string
* @default 项目
*
* @param valueFormat
* @text 右侧项目显示格式
* @desc 使用 %1 来取得指定的参数。
* 不可以使用控制字符,换行无效
* @type string
* @default %1
*
* @param valueColor
* @text 右侧文字颜色
* @type string
* @desd 使用 #FF00FF 这种格式
* @default
*
* @param indentLevel
* @text 向右缩进
* @desc 向右缩进
* 可能会与右侧文字重叠。
* @type number
* @default 0
*
* @param numLines
* @text 行数
* @desc 指定显示行数
* 用于防止与图像重叠
* @type number
* @default 1
*
*/

/*~struct~SpriteTableItem:
* @param value
* @text 对应数值
* @desc 指定变量与此值相同时显示图像
* @type number
* @default 1
*
* @param item
* @text 图片
* @type file
* @dir img/pictures/
* @desc 指定的图像将按比例缩小以适合窗体。
*
*/

/*~struct~SpriteV2:
* @param table
* @text 图片列表
* @desc 使用指定变量的值取得图像
* @type struct<SpriteTableItem>[]
* @default []
*
* @param variableId
* @text 变量ID
* @type variable
* @desc 根据变量的值取图片
* @default 0
*
* @param bitmap
* @desc 如果找不到,则要显示的图片
* @type file
* @dir img/picutures/
*
* @param x
* @type number
* @default 0
*
* @param y
* @type number
* @default 0
*
* @param width
* @text 宽度
* @desc 图片大于此值时将会缩小
* @type number
* @default 200
*
* @param height
* @text 高度
* @desc 图片大于此值时将会缩小
* @type number
* @default 200
*
* @param anthorX
* @text 图像中心X坐标
* @desc 0:左侧边・0.5:中心・1:右侧边
* @type number
* @default 0
* @min -1
* @max 1
* @decimals 2
*
* @param anthorY
* @text 图像中心Y坐标
* @desc 0:上边・0.5:中心・1:下边
* @type number
* @default 0
* @min -1
* @max 1
* @decimals 2
*
* @param isUpper
* @type boolean
* @on 文字上放
* @off 文字下方
* @default false
*/

/*~struct~Sprite:
* @param symbol
* @type select
* @option 战斗图
* @value BattlerImage
* @default BattlerImage
* @text 【标识】
* @desc 图像种类
*
* @param bitmap
* @desc 找不到的场合使用的图片
* @type file
* @dir img/
*
* @param x
* @type number
* @default 0
*
* @param y
* @type number
* @default 0
*
* @param width
* @text 宽度
* @desc 图片大于此值时将会缩小
* @type number
* @default 200
*
* @param height
* @text 高度
* @desc 图片大于此值时将会缩小
* @type number
* @default 200
*
* @param anthorX
* @text 图像中心X坐标
* @desc 0:左侧边・0.5:中心・1:右侧边
* @type number
* @default 0
* @min -1
* @max 1
* @decimals 2
*
* @param anthorY
* @text 图像中心Y坐标
* @desc 0:上边・0.5:中心・1:下边
* @type number
* @default 0
* @min -1
* @max 1
* @decimals 2
*
* @param isUpper
* @type boolean
* @on 文字上放
* @off 文字下方
* @default false
*/



(function(){
    'use strict';
/**
* @param {string} objText
*/
function parseRect(objText){
    const obj = JSON.parse(objText);
    return new Rectangle(
      Number(obj.x),Number(obj.y),Number(obj.width),Number(obj.height)
    );
}
/**
* @typedef {PIXI.Rectangle} RectangleP
*/

/**
* @type {String}
*/
constPLUGIN_NAME= ('Mano_SaveFileInfo');
function getParam(){ return PluginManager.parameters(PLUGIN_NAME);}


/**
* @typedef {Object} SaveFileInfo
* @property {string} playtime
* @property {Number} timestamp
* @property {string} title
* @property {Array<>} faces
* @property {Array<>} characters
* @property {Record< string,(string|number)>}
*/

//専用のレコードへ保存するためのやつ
class KVP_Base{
    /**
   *
   * @returns {string}
   */
    key(){
      return null;
    }
    /**
   *
   * @returns {string|number}
   */
    value(){
      return 0;
    }
    /**
   * @param {SaveFileInfo} info
   */
    read(info){
      if(info.uzssrecord){
            const key =this.key();
            if(key){
                return info.uzssrecord;
            }
      }
      return null;
    }
    /**
   * @param {SaveFileInfo} info
   */
   readToText(info){
      const t= this.read(info);
      if(t){
            return String(t);
      }
      return "";
    }
}
class RecordTemporay{
    constructor(){
      /**
         * @type {Record<(string),(Number|string)>}
         */
      this._record={};
    }
    /**
   * @param {KVP_Base} kvp
   */
    writeV2(kvp){
      const key = kvp.key();
      //キーが有効なら書き込み
      if(key){
            const value =kvp.value();
            this._record =value;
      }
    }
    get(){
      return this._record;
    }
}

class KVP_Variable extends KVP_Base{
    /**
   * @param {number} variableId
   */
    constructor(variableId){
      super();
      this._variableId =variableId;
    }
    value(){
      return $gameVariables.value(this._variableId);
    }
    key(){
      return `V${this._variableId}`;
    }
}
class KVP_Mapname extends KVP_Base{
    key(){
      return "mapname";
    }
    value(){      
      return $gameMap.displayName();
    }
}
class KVP_Mapinfo extends KVP_Base{
    key(){
      return "mapinfo";
    }
    value(){
      const mapId = $gameMap.mapId();
      const mapInfo =$dataMapInfos;
      if(mapInfo){
            return mapInfo.name;
      }
      return "";
    }
}
class KVP_Playtime extends KVP_Base{
    /**
   * @param {SaveFileInfo} info
   */
    read(info){
      return info.playtime;
    }
}

class KVP_Timestamp extends KVP_Base{

    /**
   * @param {SaveFileInfo} info
   */
    read(info){
      const d= new Date(info.timestamp);
      return `${d.toLocaleDateString()} ${d.toLocaleTimeString()} `
    }
}
class KVP_LastMessage extends KVP_Base{
    key(){
      return "lastmsg";
    }
    value(){
      return SavaDataManager_V2.getLastMessage();
    }
}

class TextItemDictionary_T{
    constructor(){
      /**
         * @type {Map<string,KVP_Base>}
         */
      this._table=new Map();
      this._table.set("timestamp",new KVP_Timestamp());
      this._table.set("mapname",new KVP_Mapname());
      this._table.set("playtime",new KVP_Playtime());
      this._table.set("mapinfo",new KVP_Mapinfo());
      this._table.set("lastmsg",new KVP_LastMessage());
    }
    /**
   * @private
   * @param {string} symbol
   * @param {number} variableId
   */
    createKVP(symbol,variableId){
      if(symbol ==="variable"){
            return new KVP_Variable(variableId);
      }
      const t = this._table.get(symbol);
      if(t){
            return t;
      }
      return null;
    }
    /**
   *
   * @param {string} text
   */
    createByText(text){
      const obj =JSON.parse(text);
      const param =(
            {
                indentLevel:Number(obj.indentLevel||0),
                valueColor:String(obj.valueColor),
                valueFormat:String(obj.valueFormat),
                symbol:String(obj.symbol),
                nameFormat:String(obj.nameFormat),
                numLines:Number(obj.numLines||1),
            }
      );
      const vid =Number(obj.variableId);
      const kvp = this.createKVP(param.symbol,vid);
      return new TextContents(kvp,param);
    }
}
const TextItemDictionary=( ()=>{   
    return new TextItemDictionary_T();
})();

class I_BitmapSelector{
    /**
   * @returns {Bitmap}
   * @param {SaveFileInfo} info
   */
    getBitmap(info){
      return null;
    }
    /**
   * @returns {KVP_Base}
   */
    kvp(){
      return null;
    }
}
class KVPXXX_BitmapTable extends I_BitmapSelector{
    /**
   * @param {number} variableId
   * @param { Map<number,string> } table
   */
    constructor(variableId,table){
      super();
      this._kvp = new KVP_Variable(variableId);
      this._table=table;
    }
    kvp(){
      return this._kvp;
    }
    /**
   * @param {SaveFileInfo} info
   */
    getBitmap(info){
      const value = Number( this._kvp.read(info));
      if(!isNaN(value)){
            const filename = this._table.get(value);
            if(filename){
                return ImageManager.loadPicture(filename);
            }
      }
      return null;
    }
}
/**
* @typedef {Object} TextParamator
* @property {String} symbol
* @property {Number} indentLevel
* @property {String} valueFormat
* @property {String} nameFormat
* @property {String} valueColor
* @property {number} numLines
*/
class TextContents{
    /**
   * @param {KVP_Base} kvp
   * @param {TextParamator} param
   */
    constructor(kvp,param){
      this._kvp =kvp;
      this._param =param;
    }
    kvp(){
      return this._kvp;
    }

    /**
   * @param {SaveFileInfo} data
   */
   kvpText(data){
      if(data){
            if(this._kvp){
                return
            }
      }
      return null;
    }
    /**
   * @param {SaveFileInfo} data
   */
    getTextXXX(data){
      const textArray = this.kvpText(data);
      return {
            left:this.createParamText(this._param.nameFormat,textArray),
            right :this.createParamText(this._param.valueFormat,textArray),
      }
    }
    /**
   * @param {String} format
   * @param {String[]|null} param
   */
    createParamText(format,param){
      const reg =/%(+)/g;
      return format.replace(reg,(s,n)=>{
            if(!param){
                return "";
            }
            const text = param;
            return text ||"";
      });
    }
    indentLevel(){
      return this._param.indentLevel;
    }
    valueTextColor(){
      return this._param.valueColor;
    }
    numLines(){
      return this._param.numLines;
    }
}
/**
* @typedef {Object} AreaObject
* @property {RectangleP} rect
* @property {TextContents[]} textList
*/

// class FaceBitmapSelector extends I_BitmapSelector{
//   /**
//      * @param {Number} index
//      */
//   constructor(index){
//         super();
//         this._index=index;
//   }
//   /**
//      * @param {SaveFileInfo} info
//      */
//   getBitmap(info){
//         const face=(info.faces);
//         if(face){
//             return ImageManager.loadFace(face);
//         }
//         return null;
//   }
//   /**
//      * @param {SaveFileInfo} info
//      */
//   frameRect(info){
//         const face = (info.faces);
//         if(face){
//             const index = face;
//             return this.faceRect(index);
//         }
//         return null;
//   }
//   /**
//      * @param {Number} index
//      */
//   faceRect(index){
//         const pw =ImageManager.faceWidth
//         const ph =ImageManager.faceHeight;
//         const sx =Math.floor((index % 4) * pw + (0) / 2);
//         const sy = Math.floor(Math.floor(index / 4) * ph + (0) / 2);
//         return new Rectangle(
//             sx,sy,
//             pw,
//             ph
//         );
//   }
// }
/**
* @typedef {Object} SpriteRecipe
* @property {RectangleP} positionRect
* @property {number} anthorX
* @property {Number} anthorY
* @property {boolean} isUpper
*/
class SpriteContents{
    /**
   * @param {I_BitmapSelector} xxx
   * @param {SpriteRecipe} recipe
   */
    constructor(xxx,recipe){
      this._xxx =xxx;
      this._recipe =recipe;
    }
    /**
   * @returns {KVP_Base}
   */
    kvp(){
      return this._xxx.kvp();
    }
    hue(data){
      return 0;
    }
    anthorX(){
      return this._recipe.anthorX;
    }
    anthorY(){
      return this._recipe.anthorY;
    }
    positionRect(){
      return this._recipe.positionRect.clone();
    }
    alpha(){
      return 1;
    }
    /**
   * @param {SaveFileInfo} info
   */
    getBitmap(info){
      if(info){
            return this._xxx.getBitmap(info);
      }
      return null;
    }
    /**
   * @param {SaveFileInfo} info
   */
    frameRect(info){
      return null;
      //return this._xxx.frameRect(info);
    }
    isUpper(){
      return this._recipe.isUpper;
    }
}
/**
* @template T_DataType
* @typedef {Object} SuperView_SpriteContentsConcept
* @property {()=>RectangleP} positionRect
* @property {()=>number} anthorX
* @property {()=>number} anthorY
* @property {(data:T_DataType)=>RectangleP} frameRect
* @property {(data:T_DataType)=>number} hue
* @property {(data:T_DataType)=>Bitmap} getBitmap
* @property {(data:T_DataType)=>number} alpha
*/

/**
* @template {SaveFileInfo} T_DataType
*/
class Sprite_SuperView extends Sprite{
    constructor(){
         super();
         this._data=null;
         this.visible =false;
         this.setContents(null);
    }
    clear(){
      this.visible=false;
      this._elment=null;
    }
    /**
   * @param {SuperView_SpriteContentsConcept<T_DataType>} contents
   */
    setContents(contents){
      this._elment =(contents ||null);
      this.refresh();
    }
    updateVisible(){
      //this.visible=true;
      this.visible = !!this._elment;
    }
    updatePosition(){
      if(this._elment){
            const rect =this._elment.positionRect()
            this.x = rect.x;
            this.y = rect.y;
            this.anchor.x = this._elment.anthorX();
            this.anchor.y = this._elment.anthorY();
      }
    }
    updateFrame(){
      const rect = this._elment.frameRect(this._data);
      if(rect){
            this.setFrame(rect.x,rect.y,rect.width,rect.height);
            return;
      }
      const orig=this.bitmap.rect;
      this.setFrame(orig.x,orig.y,orig.width,orig.height);
      this;
    }
    refresh(){
      this.updateVisible();
      this.loadBitmap();
      this.updatePosition();
      this.updateOpacity();
      this.updateHue();
    }
    updateHue(){
      if(this._elment){
            this.setHue(this._elment.hue(this._data));
      }
    }
    updateOpacity(){
      if(this._elment){
            this.alpha =this._elment.alpha(this._data);
      }
    }
    loadBitmap(){
      if(!this._elment ){
            this.bitmap=null;
            return;
      }

      //フォールバック画像を返す可能性があるので、nullでも渡す
      const bitmap =this._elment.getBitmap(this._data||null);
      this.bitmap = bitmap;
      if(bitmap){
            //TODO:hueがMV/MZで設定方法が違う
            //MZはspriteが持っているので、何らかの対応を行う
            bitmap.addLoadListener(this.onBitmapLoadead.bind(this));
      }
    }
    onBitmapLoadead(){
      this.updateFrame();
      this.resetScale();
    }
    resetScale(){
      const s=this.calcScale();
      this.scale.set(s,s);
    }
    calcScale(){
      const bitmap =this.bitmap;
      if(bitmap && bitmap.isReady()){
            const posRect =this._elment.positionRect();
            const scaleA =posRect.width   /this._frame.width ;
            const scaleB =posRect.height / this._frame.height;
            return Math.min(1,scaleA,scaleB);   
      }
      return 0;
    }
    /**
   * @param {T_DataType} data
   */
    setData(data){
      const dd= data||null;
      if(dd!==this._data){
            this._data=dd;
            this.refresh();   
      }

    }
}
/**
* @template {SaveFileInfo} T_DataType
*/
class Spriteset_SuperView extends PIXI.Container{
    /**
   *
   * @param {SpriteContents[]} constents
   */
    constructor(constents){
      super();
      /**
         * @type {Sprite_SuperView<T_DataType>[]}
         */
      this._list =[];
      this.setContents(constents);
    }
    /**
   * @param {Number} num
   */
    reserveSprite(num){
      const alocate= num - this._list.length;
      if(alocate >0){
            for (let i = 0; i < alocate; i++) {
                /**
               * @type {Sprite_SuperView<T_DataType>}
               */
                const sprite = new Sprite_SuperView();
                this._list.push(sprite);
                this.addChild(sprite);
            }
      }
    }
    /**
   * @param {SpriteContents[]} contentsList
   */
    setContents(contentsList){
      this.reserveSprite(contentsList.length);
      this._list.forEach((sprite,index)=>{
            const contents =contentsList;
            sprite.setContents(contents||null);
      });
    }
    /**
   * @param {T_DataType} data
   */
    setData(data){
      for (const iterator of this._list) {
            iterator.setData(data);
      }
    }
}

class DataWindowLayout_V2{
    /**
   *
   * @param {SpriteContents[]} casset
   * @param {AreaObject[]} area
   * @param {RectangleP} rect
   */
    constructor(casset,area,rect){
      this._rect =rect;

      const upper =[];
      const lower =[];
      for (const iterator of casset) {
            if(iterator.isUpper()){
                upper.push(iterator);
            }else{
                lower.push(iterator);
            }
      }
      this._upperSprite = upper;
      this._lowerSprite = lower;
      this._areaList=area;
    }
    rect(){
      return this._rect;
    }
    createSprites(){
      const result= {
            upper:new Spriteset_SuperView(this._upperSprite),
            lower:new Spriteset_SuperView(this._lowerSprite),
      };
      return result;
    }
    area(){
      return this._areaList;
    }
    *allVariableElements(){
      for (const iterator of this._upperSprite) {
            yield iterator.kvp();
      }
      for (const iterator of this._lowerSprite) {
            yield iterator.kvp();
      }
      for (const area of this._areaList) {
            for (const iterator of area.textList) {
                yield iterator.kvp();
            }
      }
    }
}

/**
* @param {DataWindowLayout_V2[]} layoutList
*/
function *allKVP(layoutList){
    for (const iterator of layoutList) {
      for (const aa of iterator.allVariableElements()) {
            yield aa;
      }
    }
}
/**
*
* @param {RectangleP} rect
*/
function boxFit(rect){
    const box= new Rectangle(0,0,Graphics.boxWidth,Graphics.boxHeight);
    const result = rect.clone();
    return result.fit(box);
}
//TODO:infoは2個用意する
//numvisibleRowsはminで制御する
class Window_SaveFileInfo extends Window_Base{
    /**
   *
   * @param {DataWindowLayout_V2} layout
   */
    constructor(layout){
      const rect = boxFit(layout.rect());
      super(rect);
      const sprites= layout.createSprites();
      this._upper =sprites.upper;
      this._lower =sprites.lower;
      this._layout=layout;
      this.addChild(this._upper);
      this.addChildToBack(this._lower);
    }
    /**
   * @param {SaveFileInfo} data
   */
    setData(data){
      this._upper.setData(data);
      this._lower.setData(data);
      this.pppText(data);
    }
    /**
   * @param {SaveFileInfo} info
   */
    pppText(info){
      this.contents.clear();
      for (const iterator of this._layout._areaList) {
            this.paintText(info,iterator);
      }
    }

    /**
   * @param {SaveFileInfo} info
   * @param {AreaObject} area
   */
    paintText(info,area){
      const lineHeight =this.lineHeight();
      let y =area.rect.y;
      for (const iterator of area.textList) {
            const indentLevel =iterator.indentLevel();
            const x = area.rect.x +indentLevel;
            const width= Math.min(this.innerWidth,area.rect.width)-indentLevel;
            this.drawContents(info,iterator,x,y,width,area.rect.height);
            y += iterator.numLines() * lineHeight;
      }
    }
    /**
   * @param {SaveFileInfo} data
   * @param {TextContents} contents
   * @param {Number} x
   * @param {Number} y
   * @param {Number} w
   * @param {Number} h
   */
    drawContents(data,contents,x,y,w,h){
      const indentWidth= contents.indentLevel();
      const textXXX = contents.getTextXXX(data);
      this.drawTextEx(textXXX.left,x +indentWidth,y,w-indentWidth);

      const color = contents.valueTextColor();
      if(color){
            this.changeTextColor(color);
      }else{
            this.resetTextColor();
      }
      //TODO:項目の色変更パラメータ
      this.drawText(textXXX.right,x,y,w,"right");   
    }
}

class SaveTemporaly{
    constructor(){
      this.setLastMessage("");
    }
    /**
   * @param {string} msg
   */
    setLastMessage(msg){
      this._lastMessage=msg;
    }
    getLastMessage(){
      return this._lastMessage;
    }
}

class ReadonlyFlags{
    /**
   *
   * @param {Iterable<KVP_Base>} kvpList
   */
    constructor(kvpList){
      this._lastMessage=false;
      //スクショ保存フラグ
      this._needsSnap =false;

      for (const iterator of kvpList) {
            if(iterator){
                this.xxxFlag(iterator);
            }
      }
    }
    /**
   * @param {KVP_Base} kvp
   */
    xxxFlag(kvp){
      switch (kvp.key()) {
            case "lastmsg":
                this._lastMessage=true;
                break;      
            default:
                break;
      }
    }

    needLastMessageSave(){
      return this._lastMessage;
    }

}
/**
* @typedef {Object} MainWindowLayout
* @property {number} numVisibleRows
* @property {number} maxCols
* @property {Rectangle} rect
*/

class SaveDataReadonly{
    /**
   * @param {DataWindowLayout_V2[]} dataList
   * @param {MainWindowLayout} mainWindowLayout
   * @param {Number} lastMessageSwitch
   */
    constructor(dataList,mainWindowLayout,lastMessageSwitch){
      this._dataLayoutList=dataList;
      this._mainWindow =mainWindowLayout;
      this._lastMessageSwitch=lastMessageSwitch;

      this._flags = new ReadonlyFlags(allKVP(dataList));
    }
    needsLastMessage(){

      if(!this._flags.needLastMessageSave()){
            return false;
      }
      if(this._lastMessageSwitch >0){
            return$gameSwitches.value(this._lastMessageSwitch);
      }
      return true;
    }
    setupSwitchs() {
      $gameSwitches.setValue(this._lastMessageSwitch,true);
    }

    createInfoRecord_V2(){
         const record =new RecordTemporay();
         for (const iterator of allKVP(this._dataLayoutList)) {
             if(iterator){
                record.writeV2(iterator);
             }
         }
         const result= record.get();
         return result;
    }
    createDataWindows(){
      return this._dataLayoutList.map( (data)=>{
            return new Window_SaveFileInfo(data);
      });
    }
    needsChangeLayoutForListWindow(){
      return true;
    }
    fileListWindowRect(){
      return this._mainWindow.rect.clone();
    }
    fileNumVisivleRows(){
      return this._mainWindow.numVisibleRows;
    }
    fileMaxCols(){
      return this._mainWindow.maxCols;
    }
}

class SaveWindowManager_T3{
    maxCols() {
      return this._readonly.fileMaxCols();
    }

    /**
   * @param {SaveDataReadonly} readonlyData
   */
    constructor(readonlyData){
      this._readonly=readonlyData;
      this._temporary=null;
    }
    resetTemporary(){
      this._temporary = new SaveTemporaly();
    }
    onLoad(){
      this.resetTemporary();
    }
    onNewgame(){
      this.resetTemporary();
      this._readonly.setupSwitchs();
    }
    createaInfo(){
      return this._readonly.createInfoRecord_V2();
    }
    createDataWindows() {
      return this._readonly.createDataWindows();
    }
    fileListWindowRect() {
      return this._readonly.fileListWindowRect();
    }
    fileNumVisivleRows() {
      return this._readonly.fileNumVisivleRows();
    }
    /**
   *
   * @param {string} text
   */
    setLastMessage(text){
      if(this._readonly.needsLastMessage()){
            if(this._temporary){
                this._temporary.setLastMessage(text);
            }
      }
    }
    getLastMessage(){
      return this._temporary._lastMessage;
    }
}

/**
* @param {String} objText
*/
function createItemTabel(objText){
    /**
   * @type {Map<Number,String>}
   */
    const result = new Map();
    /**
   * @type {string[]}
   */
    const paramList =JSON.parse(objText);
    for (const iterator of paramList) {
      const obj =JSON.parse(iterator);
      const value =Number(obj.value);
      if(!isNaN(value)){
            if(obj.item){
                const itemText = String(obj.item);
                result.set(value,itemText);   
            }
      }
    }
    return result;
}

/**
*
* @param {string} spriteList
* @returns
*/
function createContentsSpriteList(spriteList){
    /**
   * @type {string[]}
   */
    const spriteV2 =JSON.parse(spriteList||"[]");
    const sp2= spriteV2.map( (text)=>{
      const obj =JSON.parse(text);
      const rect =new Rectangle( Number(obj.x),Number(obj.y),Number(obj.width),Number(obj.height));
      const table = createItemTabel(obj.table);
      const variableId =Number(obj.variableId);
      const bmp =newKVPXXX_BitmapTable(variableId,table);
      return new SpriteContents(bmp,{
            positionRect:rect,
            anthorX:Number(obj.anthorX),
            anthorY:Number(obj.anthorY),
            isUpper:(obj.isUpper==="true"),
      });
    });
    return sp2;
}

/**
* @param {string} rect
* @param {string} textList
* @param {string} areaRectText
* @param {string} spriteList
*/
function createPage(rect,textList,areaRectText,spriteList){

    const sp = createContentsSpriteList(spriteList);
    const upper =[];
    const lower =[];
    for (const iterator of sp) {
      if(iterator.isUpper()){
         upper.push(iterator);
      }else{
            lower.push(iterator);
      }
    }
    const windowRect =parseRect(rect);
    /**
   * @type {string[]}
   */
    const paramList =JSON.parse(textList||"[]");
    const textObj = paramList.map( (t)=>{
      return TextItemDictionary.createByText(t);
    }).filter((v)=>{ return !!v });
    const wwRect = windowRect.clone();
    wwRect.x =0;
    wwRect.y =0;
    const areaRectV2 =parseRect(areaRectText);
    areaRectV2.fit(wwRect);
    return new DataWindowLayout_V2(sp,[
      {
            rect:areaRectV2,
            textList:textObj,
      }
    ],windowRect);
}
const SavaDataManager_V2 =(()=>{
    const param =getParam();
    const leftPage = createPage( param.leftWindow,param.leftTextList,param.leftTextPosition,param.leftSpriteList);
    const bottomPage =createPage(param.bottomWindow,param.bottomTextList,param.bottomTextPosition,param.bottomSpriteList);
    const listRect =parseRect(param.listWindow);
    const lastMessageSwitch =Number(param.lastMessageSwitch);
    const readonlyData = new SaveDataReadonly(,{
      rect:listRect,
      numVisibleRows:Number(param.numVisibleRows||3),
      maxCols:Number(param.maxCols||2),
    },lastMessageSwitch);

    const manager =new SaveWindowManager_T3(readonlyData);

    return manager;

})();
const Window_Message_startMessage=Window_Message.prototype.startMessage;
Window_Message.prototype.startMessage =function(){
    Window_Message_startMessage.call(this);
    SavaDataManager_V2.setLastMessage(this._textState.text);
};
const DataManager_loadAllSavefileImages =DataManager.loadAllSavefileImages;
DataManager.loadAllSavefileImages =function(){
    DataManager_loadAllSavefileImages.call(this);
};
constWindow_SavefileList_numVisibleRows =Window_SavefileList.prototype.numVisibleRows;
Window_SavefileList.prototype.numVisibleRows =function(){
    const n= Window_SavefileList_numVisibleRows.call(this);
    return Math.min(n,SavaDataManager_V2.fileNumVisivleRows());
};
const Window_SavefileList_maxCols=Window_SavefileList.prototype.maxCols;
Window_SavefileList.prototype.maxCols =function(){
    const oldValue = Window_SavefileList_maxCols.call(this);
    return Math.min(oldValue,SavaDataManager_V2.maxCols());
};
/**
* @param {Window_SaveFileInfo[]} dataWindows
* @param {Window_SavefileList} fileWindow
*/
function setHelpFunction(dataWindows,fileWindow){
    if(dataWindows.length <=0){
      return;
    }

    const oldFunc =fileWindow.callUpdateHelp;
    fileWindow.callUpdateHelp =function(){
      oldFunc.call(this);
      const fileId = this.savefileId();
      /**
         * @type {SaveFileInfo}
         */
      const info =DataManager.savefileInfo(fileId);
      for (const iterator of dataWindows) {
            iterator.setData(info);
      }
    };

}
const Scene_File_create=Scene_File.prototype.create;
Scene_File.prototype.create =function(){
    Scene_File_create.call(this);
    const dataWindows =SavaDataManager_V2.createDataWindows();

    for (const iterator of dataWindows) {
      this.addWindow(iterator);      
    }
    setHelpFunction(dataWindows,this._listWindow);
    this._listWindow.reselect();
};
const DataManager_makeSavefileInfo=DataManager.makeSavefileInfo;
DataManager.makeSavefileInfo =function(){
    /**
   * @type {SaveFileInfo}
   */
    const result =DataManager_makeSavefileInfo.call(this);
    const record=SavaDataManager_V2.createaInfo();
    result.uzssrecord = record;
    return result;
};
const DataManager_setupNewGame=DataManager.setupNewGame;
DataManager.setupNewGame =function(){
    DataManager_setupNewGame.call(this);
    SavaDataManager_V2.onNewgame();
};
const DataManager_extractSaveContents=DataManager.extractSaveContents;
DataManager.extractSaveContents =function(c){
    DataManager_extractSaveContents.call(this,c);
    SavaDataManager_V2.onLoad();
};

const Scene_File_listWindowRect =Scene_File.prototype.listWindowRect;
Scene_File.prototype.listWindowRect =function(){
    /**
   * @type {Rectangle}
   */
    const base = Scene_File_listWindowRect.call(this);
    const result= SavaDataManager_V2.fileListWindowRect().fit(base);
    return result;
};

PluginManager.registerCommand(PLUGIN_NAME,"SetText",(arg)=>{
    const variableId =Number(arg.variableId);
    const text = String(arg.text);
    $gameVariables.setValue(variableId,text);
});

}());

页: [1]
查看完整版本: 【汉化】Sigureya存档界面