Port of AVA2's CRenderTarget / GrpRenderTargetTexture / renderTarget module. The host gains an RGBA8 offscreen colour pass for D3D colour render targets; mt_preview shows wearable items on every allowed race and monsters with motions, reached by X+click in the inventory and shop and from the wiki. Player races are created as TYPE_PC so their parts exist. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3.9 KiB
3.9 KiB
Model preview
Ported from AVA2's render-target window (EterLib/CRenderTarget*, GrpRenderTargetTexture.*, UserInterface/CPythonRenderTargetModule.cpp, root/uirendertarget.py). The preview shows:
- a wearable item on a character of every race that may wear it;
- a monster, with its motions.
It is client only; the server is not involved.
Entry points
| Where | How |
|---|---|
| Inventory | hold X and left-click the item |
| NPC shop | hold X and left-click the item |
| Wiki detail | the "模型预览" line, on weapon / armor / costume rows that have a model, and on every monster |
Without X the original click path runs unchanged. The inventory wrapper chains onto mt_mobile_inventory's, because mt_preview is installed after it. There is no touch entry other than the wiki.
Window (ScriptLib/ModelPreviewScript.inc, module mt_preview)
Item mode
ItemSpec(vnum)accepts:- a weapon other than an arrow →
SetWeapon; - a body armor or a body costume →
SetArmor; - a hair costume →
SetHair, which reads value3.
- a weapon other than an arrow →
- The races are those not excluded by
ITEM_ANTIFLAG_{MALE,FEMALE,WARRIOR,ASSASSIN,SURA,SHAMAN}, ordered warrior, assassin, sura, shaman, with male first. The window starts on the player's own race if it is allowed. </>step through the allowed races.
Mob mode
SelectModel(vnum).- Motion buttons: 待机 1, 攻击 13, 受击 5, 死亡 11, 技能1–4 33–36 (
InterceptOnceMotion).
Controls
- Dragging with the left button turns the camera: absolute yaw/pitch from the press point, pitch clamped to ±60°.
- 放大 / 缩小 change the zoom in 5 % steps, clamped to −8..+12. Windows have no wheel event.
- 自动旋转 spins the model.
- 复位 rebuilds the model, which also resets the camera.
Lifetime
- Render target index 1 is created at 300×330 when the window opens.
- It is removed on close or Esc, and on every re-open before it is created again.
GameWindow.Closealso callsrenderTarget.Destroy(). - The host frees the GPU image 120 frames after its last use.
Native side
renderTargetPython module (port/UserInterface/PythonRenderTargetModule.cpp) →CRenderTargetManager→CRenderTarget, which owns aCInstanceBaseand aCGraphicRenderTargetTexture.CPythonApplicationcallsDeformModels/UpdateModels/RenderModelsaround the character manager.
Port differences from AVA2
- Player races (0..7) are created as
TYPE_PC. 40250 reserves the armor/weapon/hair parts only for PCs, so AVA2'sTYPE_NPCcrashed on the firstChangeArmor. - The model sits at the world origin, where culling hides it. Instead of AVA2's
SetAlwaysRender, it is shown again beforeDeformandRender. Its text tail is detached. - The background quad is drawn inside the render target, in
RenderModel.RenderBackgroundsis a no-op. - Wiki affects are not ported.
- The texture has 1 mip level.
Host (Vulkan)
- A colour render target is
D3DFMT_X8R8G8B8/A8R8G8B8withD3DUSAGE_RENDERTARGET, namedrt:<id>:<w>x<h>:c. - It gets its own RGBA8 offscreen pass (pipeline key bits 29–30: 0 none, 1 shadow, 2 colour) and is cleared to black.
- Shadow targets keep the previous path.
- Side effect: SnowEnvironment's blur targets now take the colour path. Snow blur is off by default.
Verification
tests/wiki/test_model_preview.pycovers:ItemSpecraces and slots;- race stepping and fallback;
- motions and zoom clamps;
- drag;
- reset;
- the view drawing the target;
- no live target after close, Esc, or 5 re-opens;
- the inventory and shop wrappers;
- wiki links and module order.
- ctest 49/49.
- Live, channel5 13040, macOS client, 2026-10-16:
- armor 11299 on a warrior;
- sword 19 after a 90°/20° turn;
- wild dog 101 with the attack motion;
- boss 691 zoomed in with spin.
- The main scene was unchanged.
- 120 open/close cycles (30 paced, plus 60 in one frame) did not grow RSS: 668 MB before, 593 MB after.