【不負(fù)責(zé)翻譯】PMXE內(nèi)自帶解說文件——插件解說_UI模型
※本文不保證百分之百的翻譯準(zhǔn)確,僅供參考,具體內(nèi)容依然以日文原版為準(zhǔn)。
本文內(nèi)容來自于PMXE自帶的Lib/PEPlugin/doc中的“プラグイン解説_UIモデル.txt”,翻譯于2018年12月末。今日偶然找到存稿后,也算是為了警醒自己不能再識人不善,故進(jìn)行公開發(fā)布。當(dāng)時日語水平有限,可能有語句不順或錯譯等情況,但已無心力修正,敬請諒解。關(guān)于對本文翻譯內(nèi)容玩文字游戲、鉆空子,從而違反原文使用規(guī)約的行為,本人概不負(fù)責(zé)。
※非原文部分會使用灰色字色。對一些個人認(rèn)為重要的部分會進(jìn)行加粗/變色強(qiáng)調(diào)。
PMXe相關(guān)名詞以Emil制作的“多功能信息處理與漢化插件”中的文本為準(zhǔn)。
對個別詞的理解有一定的主觀成分,且本文有編程相關(guān)專業(yè)名詞可能會有誤譯,歡迎評論區(qū)理性討論。
※本篇翻譯文章并未獲得原作者授權(quán)/知悉,僅做交流用途。如有不妥,請?jiān)u論區(qū)留言告知,我會立刻進(jìn)行刪除。
※請勿使用本文章內(nèi)任何文本/圖片做個人參考以外的其他用途,包括但不限于用于漢化文本,二次上傳至公共網(wǎng)絡(luò)等。
○請自由地取用文章中的代碼部分文本。對代碼中的注釋都進(jìn)行了翻譯,雖然并不專業(yè),但希望能為中文使用者提供些許的便利。

■UI模型功能解說
○關(guān)于UI模型
通過將從View上追加配置的 PMX模型數(shù)據(jù)(從外部文件讀取或者用插件直接做成)
用plugin中的各event進(jìn)行控制和組合的行為,就可以讓其作為UI(user interface)發(fā)揮作用。
UI模型是對被這一系列plugin功能被追加配置的 PMX模型數(shù)據(jù)的稱呼。
○使用方法
UI模型可以用Cplugin做成。
關(guān)于Cplugin的基本使用方法,請參照「插件解說_Cplugin.txt」等sample script。
●生成方法
PXCBridge.RegisterUIModel()
由此進(jìn)行生成/注冊。事先需要先準(zhǔn)備好作為基本構(gòu)造的PMX文件。
UI模型生成后,盡管改動指定的PMX文件,UI模型一側(cè)也不會有所反映。
注冊過一次的UI模型,有必要在本體一側(cè)進(jìn)行管理,并調(diào)用關(guān)于更新的專用處理(能夠更新的只有一部分?jǐn)?shù)據(jù))
●廢除
IPXUIModel.Release()
將其直接調(diào)出,或者
IPXUIModel.SetAutoRelease()
需要將其在事先進(jìn)行設(shè)定。
※
SetAutoRelease()是需要設(shè)定成在plugin結(jié)束時自動廢除的,
但PmxEditor通常設(shè)置的插件的結(jié)束時間是"與PmxEditor同時結(jié)束",
所以保持不設(shè)定的樣子也可能不會發(fā)現(xiàn)什么問題。
并且 設(shè)置 SetAutoRelease() 時將 Release()調(diào)出的話,在自動廢除時可能出現(xiàn)錯誤。
通常推薦單獨(dú)設(shè)定廢除(Release())。
○性能
UI模型中,被設(shè)定的PMX的一些功能會無法使用。
并且,本體一側(cè)的PMX中,也可以使用一些沒有實(shí)裝的功能。
●非對應(yīng)
物理演算關(guān)系
本影
地面影
●追加性能
使用world矩陣的變換
Billboard(全軸=正面表示 / Y軸固定)
材質(zhì)(顏色等)的直接更新(非材質(zhì)表情)
深度(Z)的有效狀態(tài)
模型前面一側(cè)的描繪
材質(zhì)貼圖的存儲器內(nèi)的配置(可任意編輯)
文字表示功能
除此之外,也可進(jìn)行與通常的PMX進(jìn)行相同的骨骼、表情變形。
※以下省略IPXUIModel interface的記述(IPXUIModel.SetWorld()等)。自變量等函數(shù)的詳細(xì)請確認(rèn)ObjectBrowser等。
○基本特性
Visible : 表示狀態(tài)
Light? ?: 照明的有效狀態(tài)
Depth? ?: 深度(Z)的有效狀態(tài) | 無效時,在描畫時會無視Zbuffer(=前后關(guān)系)
TopMost : 最前面描畫 | PMX模型和其他的UI模型之中,(UI模型)會在最前側(cè)描繪(無法描繪于骨骼等追加表示物體的前側(cè))
SetBillboard() : Billboard設(shè)定 | 無效/全軸/Y軸
Billboard中被設(shè)定的UI模型,會變?yōu)榭偸敲嫦虍嬅嬲娴奈矬w(全軸的情況下)
數(shù)值或圖片表示等需要總是面向特定方向的情況下會派上用場。
※Billboard與2D表示是不同的,所以無法做到與視點(diǎn)無關(guān)地總是在同樣位置以同樣大小描畫(需要特別設(shè)定)
○変形/更新
●初期化
PXCBridge.RegisterUIModel(..., bool transform = false)
?: 指定初期化時可 / 不可變形
●World矩陣 | 不可變形時也適用
SetWorld() : 矩陣設(shè)定
GetWorld() : 矩陣取得
●骨骼
SetBone()? ? ? ? ? : 對單獨(dú)骨骼進(jìn)行下述三種類(S/R/T)的總括設(shè)定
SetBoneScale()? ? ?: 單獨(dú)骨骼的scale(x/y/z)的設(shè)定
SetBoneRotate()? ? : 單獨(dú)骨骼旋轉(zhuǎn)量(quaternion)的設(shè)定
SetBoneTranslate() : 單獨(dú)骨骼的移動量(x/y/z)的設(shè)定
ResetBone()? ? ? ? : 將所有骨骼初始化
●表情
SetMorph()? ? ? ? ?: 對單獨(dú)表情的Morph值的設(shè)定
ResetMorph()? ? ? ?: 將所有表情初始化
●変形更新
UpdateTransform()? : 変形的更新 | 去除World矩陣的骨骼 / 表情的變形適用(對于不可變形的模型,只會進(jìn)行畫面的再描繪)
●變形適用后的狀態(tài)取得
GetTransformedVertexPosition() : 頂點(diǎn)位置的取得
GetTransformedVertexNormal()? ?: 頂點(diǎn)法線的取得
GetTransformedBonePosition()? ?: 骨骼位置的取得
GetTransformedBoneMatrix()? ? ?: 骨骼變形矩陣的取得(可以照原樣使用頂點(diǎn)變形的矩陣量)
●材質(zhì)更新 | 不可變形時也適用
UpdateMaterialColor() : 材質(zhì)色的更新
UpdateMaterialEdge()? : 輪廓線的更新 | 輪廓線顏色對應(yīng)于材質(zhì)色的更新
UpdateMaterialFlags() : 材質(zhì)flag的更新 | 只有雙面描繪
※材質(zhì)表情以更新后的材質(zhì)為基準(zhǔn)適用。
※負(fù)荷
骨骼/表情変形? ? ? ? -> 占內(nèi)存大(直接改變內(nèi)部的模型數(shù)據(jù))
world矩陣/材質(zhì)的更新 -> 占內(nèi)存小(只設(shè)置描繪用的參數(shù))
○特殊材質(zhì)貼圖
普通的 PMX的材質(zhì)貼圖只能使用以模型文件為對象的固定文件,
但UI模型可以指定存儲器中的Bitmap文件。
SetBitmapTexture()? ? : 將指定的材質(zhì)貼圖設(shè)定為Bitmap貼圖
UpdateBitmapTexture() : 更新材質(zhì)貼圖
能夠這樣使用的 Bitmap的形式只有 32bitARGB
Toon和高光貼圖不可以改變
當(dāng)然的,圖像文件的更新非常占內(nèi)存,使用時請注意。
※
與Bitmap圖像相對的是,通過對文字進(jìn)行描繪→更新,可以在View內(nèi)隨意地表示字符串。
關(guān)于text表示,作為簡單的支援class,準(zhǔn)備了PXUIModelHelper.TextControl。
○event
與UI模型相對的,也可以注冊與mouse相關(guān)的event。
首先需要做成注冊event的listener。
CreateEventListener()? : event listener的做成
ReleaseEventListener() : event listener的廢除
※初始化中所必要的event connector可以在 PXCBridge.CreateEventConnector() 中做成(與View event共通)
event listener是將指定的材質(zhì)(可指定多個)看做一個event領(lǐng)域,調(diào)出下文的event。
※
listener雖然可以做成多個,但指定了已經(jīng)成為其他listener對象的材質(zhì)時,
材質(zhì)會從那個對象領(lǐng)域排除,轉(zhuǎn)移到新指定的listener。
================================
例) 材質(zhì)0,1,2 的模型的情況下 :
var listener_all = uim.CreateEventListener(c);? ?// 以全部領(lǐng)域?yàn)閷ο蟮膌istener [0,1,2]
var listener_2 = uim.CreateEventListener(c, 2);? // 以材質(zhì)[2]為對象的listener
-> listener_all中 [2] 會被排除以 [0,1] 為對象
================================
●mouse event詳細(xì)
IPXUIModelEventListener
MouseOver? ? : 鼠標(biāo)光標(biāo)在領(lǐng)域上移動的情況時會被調(diào)出
MouseDown? ? : 鼠標(biāo)光標(biāo)在領(lǐng)域上的情況時按下鼠標(biāo)時會被調(diào)出
MouseUp? ? ? : 鼠標(biāo)光標(biāo)在領(lǐng)域上的情況時松開鼠標(biāo)時會被調(diào)出
MouseEnter? ?: 鼠標(biāo)光標(biāo)從領(lǐng)域外移動到領(lǐng)域上的情況時會被調(diào)出
MouseLeave? ?: 鼠標(biāo)光標(biāo)從領(lǐng)域上移動到領(lǐng)域外的情況時會被調(diào)出
MouseDrag? ? : MouseDown后持續(xù)拖拽操作的情況時會被調(diào)出
MouseDragEnd : 拖拽操作停止時會被調(diào)出
MouseClick? ?: 鼠標(biāo)光標(biāo)在領(lǐng)域上的情況時單擊會被調(diào)出(※)
MouseDoubleClick : 鼠標(biāo)光標(biāo)在領(lǐng)域上的情況時雙擊操作會被調(diào)出
※關(guān)于MouseClickに的注意點(diǎn)
普通的 Click操作,是在控制范圍內(nèi)進(jìn)行MouseDown→MouseUp 的操作會被識別,
但UI模型方面, 由于使用了View畫面上的event處理,
幾乎全部范圍內(nèi)的 MouseDown→MouseUp 都會被判定為單擊。
例)在中央MouseDown→保持拖拽狀態(tài)移動到邊緣→MouseUp 的操作也會被判定為單擊。
從使用者來看操作方法的話,自己預(yù)想到希望將同一坐標(biāo)內(nèi)的 MouseDown→MouseUp
判定為單擊的情況會有很多,這種情況下請進(jìn)行以下的event處理。
================================
// Click相應(yīng)event
listener.MouseDragEnd += (object sender, PXEventArgs.UIModelMouseDrag e) => {
? ? // Left | 在同一坐標(biāo)上的 MouseDown→MouseUp
? ? if (e.Button == MouseButtons.Left && e.X == e.StX && e.Y == e.StY) {
? ? ? ? // 處理
? ? }
};
================================
※注意點(diǎn)等
MouseEnter 或 MouseLeave 可能會根據(jù)event處理或更新方法而不正常運(yùn)作(仕様)
●event作成補(bǔ)助
PXUIModelHelper 通過class可以做成簡單的event處理
※PXUIModelHelper class只是單純地進(jìn)行了event處理的追加,多次調(diào)出是可能不會正常運(yùn)作。
■由mouse over引起的顏色變化(MouseEnter/MouseLeave event處理追加)
向MaterialColorEvPara 設(shè)定對象材質(zhì) 和變化顏色A→B 以及判定為有效的顏色(在PMX指定中初始化的話A會自動設(shè)定)
以PXUIModelHelper.SetMouseOverColor() 為調(diào)出對象材質(zhì)的listener和指定的參數(shù)的設(shè)定
■由鼠標(biāo)拖拽引起的物體移動(World矩陣移動)
做成移動操作用的listener后,
以PXUIModelHelper.SetMouseDragMove() 為調(diào)出設(shè)定(指定IPXViewControl 的話,移動場所會更加正確)
================================
// SetMouseDragMove() 內(nèi)部方法
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);
? ? ? ? ? ? }
? ? ? ? };
? ? }
}
※稍微改動一些的話也可以應(yīng)用于骨骼移動。
================================
■text表示
由PXUIModelHelper.CreateTextControl() 生成 TextControl class (不需要事先進(jìn)行 Bitmap貼圖的設(shè)定)
textCtrl.Clear();? ? ? ? ? ? // 背景色clear
textCtrl.DrawText("Hello."); // text描畫
textCtrl.UpdateTextImage();? // 更新
不需要的話就 textCtrl.Dispose();
※也可以做到直接描畫TextControl class的 Image property(Bitmap) 。