2V0-f: run the real system.py app loop in Godot

- system.py runs app.Loop() on the script fiber; each UIUpdate is one
  CPythonApplication::Process(). Logo -> Login, popup ESC/click and
  app.Exit teardown (launcher cleared first, as in 40250 Main) work.
- Image commands are base-texture quads with UVs (a .sub shares its parent
  texture); ImageInstance/ExpandedImageInstance OnRender and SetRenderingRect
  ported verbatim, so scale/rotation/rendering rect are drawn.
- CGraphicBase::GetColor / grp.GenerateColor ported (ThinBoard background).
- port.app_loop test, python_host_test app-loop checks, MT_TEST_MODE=python_ui.
- TODO: .fnt/CGraphicText font pipeline, ExpandedImage blend modes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-09-23 13:38:13 +09:00
co-authored by Claude Opus 5.5
parent 5590714b16
commit 141206cb69
20 changed files with 916 additions and 57 deletions
@@ -5,6 +5,9 @@
#include "../PlatformStub.h"
#include "EterBase/CRC32.h"
#include "UIRenderCommands.h"
#include <cmath>
auto CGraphicExpandedImageInstance::Type() -> DWORD
{
@@ -19,7 +22,7 @@ CGraphicExpandedImageInstance::CGraphicExpandedImageInstance()
CGraphicExpandedImageInstance::~CGraphicExpandedImageInstance()
{
MT_PLATFORM_STUB();
Destroy();
}
auto CGraphicExpandedImageInstance::Destroy() -> void
@@ -53,10 +56,19 @@ auto CGraphicExpandedImageInstance::SetScale(float x, float y) -> void
m_v2Scale = D3DXVECTOR2(x, y);
}
auto CGraphicExpandedImageInstance::SetRenderingRect(float left, float top, float right, float bottom) -> void
// In 40250, the arguments are fractions of the image size (uiToolTip gauges, SetPercentage).
auto CGraphicExpandedImageInstance::SetRenderingRect(float fLeft, float fTop, float fRight, float fBottom) -> void
{
m_RenderingRect = {static_cast<LONG>(left), static_cast<LONG>(top),
static_cast<LONG>(right), static_cast<LONG>(bottom)};
if (IsEmpty())
return;
float fWidth = float(GetWidth());
float fHeight = float(GetHeight());
m_RenderingRect.left = fWidth * fLeft;
m_RenderingRect.top = fHeight * fTop;
m_RenderingRect.right = fWidth * fRight;
m_RenderingRect.bottom = fHeight * fBottom;
}
auto CGraphicExpandedImageInstance::SetRenderingMode(int mode) -> void
@@ -74,9 +86,68 @@ auto CGraphicExpandedImageInstance::Initialize() -> void
m_iRenderingMode = RENDERING_MODE_NORMAL;
}
// 40250 GrpExpandedImageInstance.cpp:29-142. The vertex and texture-coordinate arithmetic is
// verbatim; the D3D stream/blend-state calls become one UIRenderCommand with the four vertices.
auto CGraphicExpandedImageInstance::OnRender() -> void
{
CGraphicImageInstance::OnRender();
CGraphicImage * pImage = m_roImage.GetPointer();
CGraphicTexture * pTexture = pImage->GetTexturePointer();
if (pTexture->GetWidth() <= 0 || pTexture->GetHeight() <= 0)
return;
const RECT& c_rRect = pImage->GetRectReference();
float texReverseWidth = 1.0f / float(pTexture->GetWidth());
float texReverseHeight = 1.0f / float(pTexture->GetHeight());
float su = (c_rRect.left - m_RenderingRect.left) * texReverseWidth;
float sv = (c_rRect.top - m_RenderingRect.top) * texReverseHeight;
float eu = (c_rRect.left + m_RenderingRect.right + (c_rRect.right-c_rRect.left)) * texReverseWidth;
float ev = (c_rRect.top + m_RenderingRect.bottom + (c_rRect.bottom-c_rRect.top)) * texReverseHeight;
float x[4], y[4];
for (int i = 0; i < 4; ++i)
{
x[i] = m_v2Position.x-0.5f;
y[i] = m_v2Position.y-0.5f;
}
if (0.0f == m_fRotation)
{
float fimgWidth = float(pImage->GetWidth()) * m_v2Scale.x;
float fimgHeight = float(pImage->GetHeight()) * m_v2Scale.y;
x[0] -= m_RenderingRect.left;
y[0] -= m_RenderingRect.top;
x[1] += fimgWidth + m_RenderingRect.right;
y[1] -= m_RenderingRect.top;
x[2] -= m_RenderingRect.left;
y[2] += fimgHeight + m_RenderingRect.bottom;
x[3] += fimgWidth + m_RenderingRect.right;
y[3] += fimgHeight + m_RenderingRect.bottom;
// PORT: 40250 flips D3DRS_CULLMODE for a mirrored scale; the Godot canvas has no culling.
}
else
{
float fimgHalfWidth = float(pImage->GetWidth())/2.0f * m_v2Scale.x;
float fimgHalfHeight = float(pImage->GetHeight())/2.0f * m_v2Scale.y;
for (int i = 0; i < 4; ++i)
{
x[i] += m_v2Origin.x;
y[i] += m_v2Origin.y;
}
float fRadian = D3DXToRadian(m_fRotation);
x[0] += (-fimgHalfWidth*cosf(fRadian)) - (-fimgHalfHeight*sinf(fRadian));
y[0] += (-fimgHalfWidth*sinf(fRadian)) + (-fimgHalfHeight*cosf(fRadian));
x[1] += (+fimgHalfWidth*cosf(fRadian)) - (-fimgHalfHeight*sinf(fRadian));
y[1] += (+fimgHalfWidth*sinf(fRadian)) + (-fimgHalfHeight*cosf(fRadian));
x[2] += (-fimgHalfWidth*cosf(fRadian)) - (+fimgHalfHeight*sinf(fRadian));
y[2] += (-fimgHalfWidth*sinf(fRadian)) + (+fimgHalfHeight*cosf(fRadian));
x[3] += (+fimgHalfWidth*cosf(fRadian)) - (+fimgHalfHeight*sinf(fRadian));
y[3] += (+fimgHalfWidth*sinf(fRadian)) + (+fimgHalfHeight*cosf(fRadian));
}
UIRenderAddImage(pTexture, x, y, su, sv, eu, ev, UIRenderColor(m_DiffuseColor), m_iRenderingMode);
}
auto CGraphicExpandedImageInstance::OnSetImagePointer() -> void