Model preview: AVA2 render-target window on a Vulkan colour target
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>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
32372c2a73
commit
84404cf1f1
@@ -0,0 +1,282 @@
|
||||
// PORT: AVA2 CPythonRenderTargetModule (module renderTarget), the subset the model preview uses. AVA2's window
|
||||
// manager created the target for a registered window and drew it; here Create and RenderTexture do that, called
|
||||
// from the script's own window (ScriptLib/ModelPreviewScript.inc).
|
||||
#include "StdAfx.h"
|
||||
#include "CRenderTargetManager.h"
|
||||
#include "InstanceBase.h"
|
||||
#include "../GameLib/ItemManager.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
// The default of CPythonApplication's camera zoom speed (PythonApplicationCamera.cpp), which AVA2 read.
|
||||
const float c_fRenderTargetZoomSpeed = 0.05f;
|
||||
|
||||
std::shared_ptr<CRenderTarget> Target(PyObject* poArgs)
|
||||
{
|
||||
int iIndex;
|
||||
if (!PyTuple_GetInteger(poArgs, 0, &iIndex))
|
||||
return nullptr;
|
||||
return CRenderTargetManager::Instance().GetRenderTarget(iIndex);
|
||||
}
|
||||
|
||||
bool Integer(PyObject* poArgs, int pos, int* value)
|
||||
{
|
||||
return PyTuple_GetInteger(poArgs, pos, value);
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* renderTargetCreate(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
int iIndex, iWidth, iHeight;
|
||||
if (!Integer(poArgs, 0, &iIndex) || !Integer(poArgs, 1, &iWidth) || !Integer(poArgs, 2, &iHeight))
|
||||
return Py_BadArgument();
|
||||
return Py_BuildValue("i", CRenderTargetManager::Instance().CreateRenderTarget(iIndex, iWidth, iHeight) ? 1 : 0);
|
||||
}
|
||||
|
||||
PyObject* renderTargetRemove(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
int iIndex;
|
||||
if (!Integer(poArgs, 0, &iIndex))
|
||||
return Py_BadArgument();
|
||||
CRenderTargetManager::Instance().RemoveRenderTarget(iIndex);
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject* renderTargetExists(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
int iIndex;
|
||||
if (!Integer(poArgs, 0, &iIndex))
|
||||
return Py_BadArgument();
|
||||
return Py_BuildValue("i", CRenderTargetManager::Instance().GetRenderTarget(iIndex) ? 1 : 0);
|
||||
}
|
||||
|
||||
PyObject* renderTargetRenderTexture(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
int l, t, r, b;
|
||||
if (!Integer(poArgs, 1, &l) || !Integer(poArgs, 2, &t) || !Integer(poArgs, 3, &r) || !Integer(poArgs, 4, &b))
|
||||
return Py_BadArgument();
|
||||
const auto target = Target(poArgs);
|
||||
if (target && target->IsShow())
|
||||
{
|
||||
RECT rect = { l, t, r, b };
|
||||
target->SetRenderingRect(&rect);
|
||||
target->RenderTexture();
|
||||
}
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject* renderTargetSelectModel(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
int modelIndex;
|
||||
if (!Integer(poArgs, 1, &modelIndex))
|
||||
return Py_BadArgument();
|
||||
const auto target = Target(poArgs);
|
||||
if (target)
|
||||
target->SelectModel(modelIndex);
|
||||
return Py_BuildValue("i", target && target->GetModel() ? 1 : 0);
|
||||
}
|
||||
|
||||
PyObject* renderTargetSetArmor(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
int iItemVnum;
|
||||
if (!Integer(poArgs, 1, &iItemVnum))
|
||||
return Py_BadArgument();
|
||||
const auto target = Target(poArgs);
|
||||
if (target && target->IsReady())
|
||||
target->GetModel()->ChangeArmor(iItemVnum);
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject* renderTargetSetWeapon(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
int iItemVnum;
|
||||
if (!Integer(poArgs, 1, &iItemVnum))
|
||||
return Py_BadArgument();
|
||||
const auto target = Target(poArgs);
|
||||
if (target && target->IsReady())
|
||||
target->GetModel()->ChangeWeapon(iItemVnum);
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject* renderTargetSetHair(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
int iItemVnum;
|
||||
if (!Integer(poArgs, 1, &iItemVnum))
|
||||
return Py_BadArgument();
|
||||
bool isValue = false;
|
||||
const auto target = Target(poArgs);
|
||||
if (target)
|
||||
{
|
||||
PyTuple_GetBoolean(poArgs, 2, &isValue);
|
||||
if (!isValue)
|
||||
{
|
||||
CItemData* pItemData;
|
||||
if (!CItemManager::Instance().GetItemDataPointer(iItemVnum, &pItemData))
|
||||
return Py_BuildNone();
|
||||
iItemVnum = pItemData->GetValue(3);
|
||||
}
|
||||
if (target->IsReady())
|
||||
target->GetModel()->SetHair(iItemVnum);
|
||||
}
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject* renderTargetSetMount(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
int iRace;
|
||||
if (!Integer(poArgs, 1, &iRace))
|
||||
return Py_BadArgument();
|
||||
const auto target = Target(poArgs);
|
||||
if (target && target->IsReady())
|
||||
target->GetModel()->MountHorse(iRace);
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject* renderTargetSetRotation(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
bool bRot;
|
||||
if (!PyTuple_GetBoolean(poArgs, 1, &bRot))
|
||||
return Py_BadArgument();
|
||||
const auto target = Target(poArgs);
|
||||
if (target)
|
||||
target->SetRotation(bRot);
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject* renderTargetSetVisibility(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
bool isShow;
|
||||
if (!PyTuple_GetBoolean(poArgs, 1, &isShow))
|
||||
return Py_BadArgument();
|
||||
const auto target = Target(poArgs);
|
||||
if (target)
|
||||
target->SetVisibility(isShow);
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject* renderTargetSetBackground(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
char* szPathName;
|
||||
if (!PyTuple_GetString(poArgs, 1, &szPathName))
|
||||
return Py_BadArgument();
|
||||
const auto target = Target(poArgs);
|
||||
// PORT: the background is stretched over the target when drawn, so the sizes AVA2 passed are unused.
|
||||
return Py_BuildValue("i", target && target->CreateBackground(szPathName, 0, 0) ? 1 : 0);
|
||||
}
|
||||
|
||||
PyObject* renderTargetResetModel(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
const auto target = Target(poArgs);
|
||||
if (target)
|
||||
target->ResetModel();
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject* renderTargetDestroy(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
CRenderTargetManager::Instance().Destroy();
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject* renderTargetSetModelV3Eye(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
float x, y, z;
|
||||
if (!PyTuple_GetFloat(poArgs, 1, &x) || !PyTuple_GetFloat(poArgs, 2, &y) || !PyTuple_GetFloat(poArgs, 3, &z))
|
||||
return Py_BadArgument();
|
||||
const auto target = Target(poArgs);
|
||||
if (target)
|
||||
target->SetModelV3Eye(x, y, z);
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject* renderTargetSetModelV3Target(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
float x, y, z;
|
||||
if (!PyTuple_GetFloat(poArgs, 1, &x) || !PyTuple_GetFloat(poArgs, 2, &y) || !PyTuple_GetFloat(poArgs, 3, &z))
|
||||
return Py_BadArgument();
|
||||
const auto target = Target(poArgs);
|
||||
if (target)
|
||||
target->SetModelV3Target(x, y, z);
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject* renderTargetZoom(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
int iDirection;
|
||||
if (!Integer(poArgs, 1, &iDirection))
|
||||
return Py_BadArgument();
|
||||
const auto target = Target(poArgs);
|
||||
if (target && target->IsReady())
|
||||
target->Zoom(1.0f + c_fRenderTargetZoomSpeed * float(iDirection));
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject* renderTargetRotateEyeAroundTarget(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
float fPitch, fRoll;
|
||||
if (!PyTuple_GetFloat(poArgs, 1, &fPitch) || !PyTuple_GetFloat(poArgs, 2, &fRoll))
|
||||
return Py_BadArgument();
|
||||
const auto target = Target(poArgs);
|
||||
if (target && target->IsReady())
|
||||
target->RotateEyeAroundTarget(fPitch, fRoll);
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject* renderTargetSetScale(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
float fScale;
|
||||
if (!PyTuple_GetFloat(poArgs, 1, &fScale))
|
||||
return Py_BadArgument();
|
||||
const auto target = Target(poArgs);
|
||||
if (target)
|
||||
target->SetScale(fScale);
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject* renderTargetIsShow(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
const auto target = Target(poArgs);
|
||||
return Py_BuildValue("i", target ? target->IsShow() : 0);
|
||||
}
|
||||
|
||||
PyObject* renderTargetSetMotionIndex(PyObject* poSelf, PyObject* poArgs)
|
||||
{
|
||||
int iMotionIndex;
|
||||
if (!Integer(poArgs, 1, &iMotionIndex))
|
||||
return Py_BadArgument();
|
||||
const auto target = Target(poArgs);
|
||||
if (target && target->IsReady())
|
||||
return Py_BuildValue("i", target->GetModel()->GetGraphicThingInstanceRef().InterceptOnceMotion(iMotionIndex) ? 1 : 0);
|
||||
return Py_BuildValue("i", 0);
|
||||
}
|
||||
|
||||
void initRenderTarget()
|
||||
{
|
||||
static PyMethodDef s_methods[] =
|
||||
{
|
||||
{ "Create", renderTargetCreate, METH_VARARGS },
|
||||
{ "Remove", renderTargetRemove, METH_VARARGS },
|
||||
{ "Exists", renderTargetExists, METH_VARARGS },
|
||||
{ "RenderTexture", renderTargetRenderTexture, METH_VARARGS },
|
||||
{ "SelectModel", renderTargetSelectModel, METH_VARARGS },
|
||||
{ "SetVisibility", renderTargetSetVisibility, METH_VARARGS },
|
||||
{ "SetBackground", renderTargetSetBackground, METH_VARARGS },
|
||||
{ "SetArmor", renderTargetSetArmor, METH_VARARGS },
|
||||
{ "SetWeapon", renderTargetSetWeapon, METH_VARARGS },
|
||||
{ "SetHair", renderTargetSetHair, METH_VARARGS },
|
||||
{ "SetMount", renderTargetSetMount, METH_VARARGS },
|
||||
{ "SetRotation", renderTargetSetRotation, METH_VARARGS },
|
||||
{ "ResetModel", renderTargetResetModel, METH_VARARGS },
|
||||
{ "Destroy", renderTargetDestroy, METH_VARARGS },
|
||||
{ "SetModelV3Eye", renderTargetSetModelV3Eye, METH_VARARGS },
|
||||
{ "SetModelV3Target", renderTargetSetModelV3Target, METH_VARARGS },
|
||||
{ "Zoom", renderTargetZoom, METH_VARARGS },
|
||||
{ "RotateEyeAroundTarget", renderTargetRotateEyeAroundTarget, METH_VARARGS },
|
||||
{ "SetScale", renderTargetSetScale, METH_VARARGS },
|
||||
{ "IsShow", renderTargetIsShow, METH_VARARGS },
|
||||
{ "SetMotionIndex", renderTargetSetMotionIndex, METH_VARARGS },
|
||||
{ NULL, NULL, 0 },
|
||||
};
|
||||
|
||||
Py_InitModule("renderTarget", s_methods);
|
||||
}
|
||||
Reference in New Issue
Block a user