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
@@ -2,6 +2,7 @@
// These modules expose names for script loading; calls record that they still need the real 2V1-2V3 implementation.
#include "ScriptLib/StdAfx.h"
#include <cstdio>
#include "../EterLib/UIRenderCommands.h"
namespace {
PyObject* stub_call_named(const char* name) {
@@ -1629,8 +1630,19 @@ PyMethodDef methods_snd[] = {
const char* ints_snd[] = {NULL};
const char* strings_snd[] = {NULL};
// 40250 UserInterface/PythonSystemModule.cpp: systemSetting export names.
PyObject* stub_systemSetting_GetWidth(PyObject*, PyObject*) { return stub_call_named("systemSetting.GetWidth"); }
PyObject* stub_systemSetting_GetHeight(PyObject*, PyObject*) { return stub_call_named("systemSetting.GetHeight"); }
// 40250 CPythonSystem::GetWidth/GetHeight return metin2.cfg's WIDTH/HEIGHT (default 800x600), which
// RunApp passes to wndMgr.SetScreenSize and app.Create. PORT (2V0-f): the Godot canvas is the window,
// so report its size; the rest of systemSetting stays a stub until CPythonSystem is ported.
PyObject* stub_systemSetting_GetWidth(PyObject*, PyObject*) {
unsigned width = 0;
UIRenderGetSize(&width, nullptr);
return Py_BuildValue("i", width ? int(width) : 800);
}
PyObject* stub_systemSetting_GetHeight(PyObject*, PyObject*) {
unsigned height = 0;
UIRenderGetSize(nullptr, &height);
return Py_BuildValue("i", height ? int(height) : 600);
}
PyObject* stub_systemSetting_SetInterfaceHandler(PyObject*, PyObject*) { return stub_call_named("systemSetting.SetInterfaceHandler"); }
PyObject* stub_systemSetting_DestroyInterfaceHandler(PyObject*, PyObject*) { return stub_call_named("systemSetting.DestroyInterfaceHandler"); }
PyObject* stub_systemSetting_ReserveResource(PyObject*, PyObject*) { return stub_call_named("systemSetting.ReserveResource"); }