【不负责翻译】PMXE内自带解说文件——插件解说_UI模型
※本文不保证百分之百的翻译准确,仅供参考,具体内容依然以日文原版为准。
本文内容来自于PMXE自带的Lib/PEPlugin/doc中的“プラグイン解説_UIモデル.txt”,翻译于2018年12月末。今日偶然找到存稿后,也算是为了警醒自己不能再识人不善,故进行公开发布。当时日语水平有限,可能有语句不顺或错译等情况,但已无心力修正,敬请谅解。关于对本文翻译内容玩文字游戏、钻空子,从而违反原文使用规约的行为,本人概不负责。
※非原文部分会使用灰色字色。对一些个人认为重要的部分会进行加粗/变色强调。
PMXe相关名词以Emil制作的“多功能信息处理与汉化插件”中的文本为准。
对个别词的理解有一定的主观成分,且本文有编程相关专业名词可能会有误译,欢迎评论区理性讨论。
※本篇翻译文章并未获得原作者授权/知悉,仅做交流用途。如有不妥,请评论区留言告知,我会立刻进行删除。
※请勿使用本文章内任何文本/图片做个人参考以外的其他用途,包括但不限于用于汉化文本,二次上传至公共网络等。
○请自由地取用文章中的代码部分文本。对代码中的注释都进行了翻译,虽然并不专业,但希望能为中文使用者提供些许的便利。

■UI模型功能解说
○关于UI模型
通过将从View上追加配置的 PMX模型数据(从外部文件读取或者用插件直接做成)
用plugin中的各event进行控制和组合的行为,就可以让其作为UI(user interface)发挥作用。
UI模型是对被这一系列plugin功能被追加配置的 PMX模型数据的称呼。
○使用方法
UI模型可以用Cplugin做成。
关于Cplugin的基本使用方法,请参照「插件解说_Cplugin.txt」等sample script。
●生成方法
PXCBridge.RegisterUIModel()
由此进行生成/注册。事先需要先准备好作为基本构造的PMX文件。
UI模型生成后,尽管改动指定的PMX文件,UI模型一侧也不会有所反映。
注册过一次的UI模型,有必要在本体一侧进行管理,并调用关于更新的专用处理(能够更新的只有一部分数据)
●废除
IPXUIModel.Release()
将其直接调出,或者
IPXUIModel.SetAutoRelease()
需要将其在事先进行设定。
※
SetAutoRelease()是需要设定成在plugin结束时自动废除的,
但PmxEditor通常设置的插件的结束时间是"与PmxEditor同时结束",
所以保持不设定的样子也可能不会发现什么问题。
并且 设置 SetAutoRelease() 时将 Release()调出的话,在自动废除时可能出现错误。
通常推荐单独设定废除(Release())。
○性能
UI模型中,被设定的PMX的一些功能会无法使用。
并且,本体一侧的PMX中,也可以使用一些没有实装的功能。
●非对应
物理演算关系
本影
地面影
●追加性能
使用world矩阵的变换
Billboard(全轴=正面表示 / Y轴固定)
材质(颜色等)的直接更新(非材质表情)
深度(Z)的有效状态
模型前面一侧的描绘
材质贴图的存储器内的配置(可任意编辑)
文字表示功能
除此之外,也可进行与通常的PMX进行相同的骨骼、表情变形。
※以下省略IPXUIModel interface的记述(IPXUIModel.SetWorld()等)。自变量等函数的详细请确认ObjectBrowser等。
○基本特性
Visible : 表示状态
Light : 照明的有效状态
Depth : 深度(Z)的有效状态 | 无效时,在描画时会无视Zbuffer(=前后关系)
TopMost : 最前面描画 | PMX模型和其他的UI模型之中,(UI模型)会在最前侧描绘(无法描绘于骨骼等追加表示物体的前侧)
SetBillboard() : Billboard设定 | 无效/全轴/Y轴
Billboard中被设定的UI模型,会变为总是面向画面正面的物体(全轴的情况下)
数值或图片表示等需要总是面向特定方向的情况下会派上用场。
※Billboard与2D表示是不同的,所以无法做到与视点无关地总是在同样位置以同样大小描画(需要特别设定)
○変形/更新
●初期化
PXCBridge.RegisterUIModel(..., bool transform = false)
: 指定初期化时可 / 不可变形
●World矩阵 | 不可变形时也适用
SetWorld() : 矩阵设定
GetWorld() : 矩阵取得
●骨骼
SetBone() : 对单独骨骼进行下述三种类(S/R/T)的总括设定
SetBoneScale() : 单独骨骼的scale(x/y/z)的设定
SetBoneRotate() : 单独骨骼旋转量(quaternion)的设定
SetBoneTranslate() : 单独骨骼的移动量(x/y/z)的设定
ResetBone() : 将所有骨骼初始化
●表情
SetMorph() : 对单独表情的Morph值的设定
ResetMorph() : 将所有表情初始化
●変形更新
UpdateTransform() : 変形的更新 | 去除World矩阵的骨骼 / 表情的变形适用(对于不可变形的模型,只会进行画面的再描绘)
●变形适用后的状态取得
GetTransformedVertexPosition() : 顶点位置的取得
GetTransformedVertexNormal() : 顶点法线的取得
GetTransformedBonePosition() : 骨骼位置的取得
GetTransformedBoneMatrix() : 骨骼变形矩阵的取得(可以照原样使用顶点变形的矩阵量)
●材质更新 | 不可变形时也适用
UpdateMaterialColor() : 材质色的更新
UpdateMaterialEdge() : 轮廓线的更新 | 轮廓线颜色对应于材质色的更新
UpdateMaterialFlags() : 材质flag的更新 | 只有双面描绘
※材质表情以更新后的材质为基准适用。
※负荷
骨骼/表情変形 -> 占内存大(直接改变内部的模型数据)
world矩阵/材质的更新 -> 占内存小(只设置描绘用的参数)
○特殊材质贴图
普通的 PMX的材质贴图只能使用以模型文件为对象的固定文件,
但UI模型可以指定存储器中的Bitmap文件。
SetBitmapTexture() : 将指定的材质贴图设定为Bitmap贴图
UpdateBitmapTexture() : 更新材质贴图
能够这样使用的 Bitmap的形式只有 32bitARGB
Toon和高光贴图不可以改变
当然的,图像文件的更新非常占内存,使用时请注意。
※
与Bitmap图像相对的是,通过对文字进行描绘→更新,可以在View内随意地表示字符串。
关于text表示,作为简单的支援class,准备了PXUIModelHelper.TextControl。
○event
与UI模型相对的,也可以注册与mouse相关的event。
首先需要做成注册event的listener。
CreateEventListener() : event listener的做成
ReleaseEventListener() : event listener的废除
※初始化中所必要的event connector可以在 PXCBridge.CreateEventConnector() 中做成(与View event共通)
event listener是将指定的材质(可指定多个)看做一个event领域,调出下文的event。
※
listener虽然可以做成多个,但指定了已经成为其他listener对象的材质时,
材质会从那个对象领域排除,转移到新指定的listener。
================================
例) 材質0,1,2 的模型的情况下 :
var listener_all = uim.CreateEventListener(c); // 以全部领域为对象的listener [0,1,2]
var listener_2 = uim.CreateEventListener(c, 2); // 以材质[2]为对象的listener
-> listener_all中 [2] 会被排除以 [0,1] 为对象
================================
●mouse event详细
IPXUIModelEventListener
MouseOver : 鼠标光标在领域上移动的情况时会被调出
MouseDown : 鼠标光标在领域上的情况时按下鼠标时会被调出
MouseUp : 鼠标光标在领域上的情况时松开鼠标时会被调出
MouseEnter : 鼠标光标从领域外移动到领域上的情况时会被调出
MouseLeave : 鼠标光标从领域上移动到领域外的情况时会被调出
MouseDrag : MouseDown后持续拖拽操作的情况时会被调出
MouseDragEnd : 拖拽操作停止时会被调出
MouseClick : 鼠标光标在领域上的情况时单击会被调出(※)
MouseDoubleClick : 鼠标光标在领域上的情况时双击操作会被调出
※关于MouseClickに的注意点
普通的 Click操作,是在控制范围内进行MouseDown→MouseUp 的操作会被识别,
但UI模型方面, 由于使用了View画面上的event处理,
几乎全部范围内的 MouseDown→MouseUp 都会被判定为单击。
例)在中央MouseDown→保持拖拽状态移动到边缘→MouseUp 的操作也会被判定为单击。
从使用者来看操作方法的话,自己预想到希望将同一坐标内的 MouseDown→MouseUp
判定为单击的情况会有很多,这种情况下请进行以下的event处理。
================================
// Click相应event
listener.MouseDragEnd += (object sender, PXEventArgs.UIModelMouseDrag e) => {
// Left | 在同一坐标上的 MouseDown→MouseUp
if (e.Button == MouseButtons.Left && e.X == e.StX && e.Y == e.StY) {
// 处理
}
};
================================
※注意点等
MouseEnter 或 MouseLeave 可能会根据event处理或更新方法而不正常运作(仕様)
●event作成補助
PXUIModelHelper 通过class可以做成简单的event处理
※PXUIModelHelper class只是单纯地进行了event处理的追加,多次调出是可能不会正常运作。
■由mouse over引起的颜色变化(MouseEnter/MouseLeave event处理追加)
向MaterialColorEvPara 设定对象材质 和变化颜色A→B 以及判定为有效的颜色(在PMX指定中初始化的话A会自动设定)
以PXUIModelHelper.SetMouseOverColor() 为调出对象材质的listener和指定的参数的设定
■由鼠标拖拽引起的物体移动(World矩阵移动)
做成移动操作用的listener后,
以PXUIModelHelper.SetMouseDragMove() 为调出设定(指定IPXViewControl 的话,移动场所会更加正确)
================================
// SetMouseDragMove() 内部方法
static public void SetMouseDragMove(IPXUIModel uim, IPXUIModelEventListener listener, IPXViewControl viewCtrl = null)
{
M stm = new M();
V3 vp = new V3();
listener.MouseDown += (object sender, PXEventArgs.UIModelMouse e) => {
try {
if (e.Button == System.Windows.Forms.MouseButtons.Left) {
// 拖拽用
stm = uim.GetWorld();
if (viewCtrl != null) {
vp = viewCtrl.VCursorPosition;
viewCtrl.VCursorPosition = new V3(stm.M41, stm.M42, stm.M43);
}
}
}
catch (Exception ex) {
System.Diagnostics.Debug.Assert(false, ex.Message);
}
};
// 拖拽移动
listener.MouseDrag += (object sender, PXEventArgs.UIModelMouseDrag e) => {
try {
if (e.Button == System.Windows.Forms.MouseButtons.Left) {
M m = new M(stm);
m.M41 += e.VDrag.X;
m.M42 += e.VDrag.Y;
m.M43 += e.VDrag.Z;
uim.SetWorld(m);
}
}
catch (Exception ex) {
System.Diagnostics.Debug.Assert(false, ex.Message);
}
};
if (viewCtrl != null) {
// 拖拽移动
listener.MouseDragEnd += (object sender, PXEventArgs.UIModelMouseDrag e) => {
try {
if (e.Button == System.Windows.Forms.MouseButtons.Left) {
viewCtrl.VCursorPosition = vp;
}
}
catch (Exception ex) {
System.Diagnostics.Debug.Assert(false, ex.Message);
}
};
}
}
※稍微改动一些的话也可以应用于骨骼移动。
================================
■text表示
由PXUIModelHelper.CreateTextControl() 生成 TextControl class (不需要事先进行 Bitmap贴图的设定)
textCtrl.Clear(); // 背景色clear
textCtrl.DrawText("Hello."); // text描画
textCtrl.UpdateTextImage(); // 更新
不需要的话就 textCtrl.Dispose();
※也可以做到直接描画TextControl class的 Image property(Bitmap) 。

