From 369a80fc1085e84155c62168636aecd5fc7c2fa4 Mon Sep 17 00:00:00 2001 From: shenlei Date: Wed, 23 Sep 2026 10:50:24 +0900 Subject: [PATCH] =?UTF-8?q?port(2V0-a):=20EterPythonLib=20=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E7=B3=BB=E7=BB=9F=E7=9A=84=E5=A4=B4=E8=BF=9B=E9=95=9C?= =?UTF-8?q?=E5=83=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2V0 的入口实测:audit/slices/2V0.json 的 212 个头里 164 个已经在镜像中,缺 48 个 (1 个 EterLib、5 个 EterPythonLib、42 个 UserInterface);10 个单元里已移植 2 个。 本轮补 EterPythonLib 这 5 个,外加必须先有的 EterPythonLib/StdAfx.h —— port_header_gate 按 40250 的做法把每个头放在所属库的 StdAfx.h 后面编译,没有它这五个既看不到 也看不到 STL 和 CSingleton。 6 个文件全是 port_copy.py 的机械拷贝,0 处手改。 顺带修正清单的一处误报:EterLib/Dimm.h 不是 40250 的源文件,是 Windows SDK 的 MIDL 产物,port/common/shim/win32/Dimm.h 已经顶掉了;镜像一份反而遮住 shim, EterLib/IME.h 的 #include "Dimm.h" 会去找 rpc.h。拷进来验证后删掉。 只有头,没有 .cpp,所以没有 port-map 条目 —— 只有声明,没有可调用的东西。 port_header_gate 新增 6 个 TU 全绿;ctest 27/27。 Co-Authored-By: Claude Opus 5 --- audit/history.jsonl | 1 + docs/PORT-PLAN.md | 16 + .../src/port/EterPythonLib/PythonGraphic.h | 68 +++ .../port/EterPythonLib/PythonGridSlotWindow.h | 40 ++ .../src/port/EterPythonLib/PythonSlotWindow.h | 211 +++++++ .../src/port/EterPythonLib/PythonWindow.h | 525 ++++++++++++++++++ .../port/EterPythonLib/PythonWindowManager.h | 187 +++++++ extension/src/port/EterPythonLib/StdAfx.h | 17 + 8 files changed, 1065 insertions(+) create mode 100644 extension/src/port/EterPythonLib/PythonGraphic.h create mode 100644 extension/src/port/EterPythonLib/PythonGridSlotWindow.h create mode 100644 extension/src/port/EterPythonLib/PythonSlotWindow.h create mode 100644 extension/src/port/EterPythonLib/PythonWindow.h create mode 100644 extension/src/port/EterPythonLib/PythonWindowManager.h create mode 100644 extension/src/port/EterPythonLib/StdAfx.h diff --git a/audit/history.jsonl b/audit/history.jsonl index 35cbff0b..ad19678c 100644 --- a/audit/history.jsonl +++ b/audit/history.jsonl @@ -500,3 +500,4 @@ {"time": "2026-09-23T22:35:00Z", "event": "known_issue", "unit": "Android GBK 编解码挂起;优先保证 macOS 可用", "ported": [], "adapted": [], "deleted": [], "divergent": [], "needs_live": [], "decision": {"by": "user", "statement": "先不管这个问题了,先保证 macOS 能正常使用,Android 后期再想办法"}, "finding": {"symptom": "build-android.sh 默认 API 24 下 extension/src/net/text_codec.cpp 编译失败:use of undeclared identifier 'iconv_open' / 'iconv' / 'iconv_close'", "root_cause": "text_codec.cpp:10 用 __has_include() 探测。NDK 里该头在任何 API 等级都存在,但声明被 __BIONIC_AVAILABILITY_GUARD(28) 挡住,探测方式与 bionic 的可用性模型不匹配", "measured": "NDK 28.2.13676358 clang++ -fsyntax-only:--target=aarch64-linux-android24 报 3 处 undeclared;android28 通过", "why_api_bump_is_wrong": "NDK iconv.h 注释写明 bionic 只支持 utf8/ascii/usascii/utf16be/utf16le/utf32be/utf32le/wchart,没有 GB2312/GBK。升到 28 后 iconv_open(\"GB2312\",\"UTF-8\") 运行期返回 -1,encode_one()/decode_wire() 对所有输入都返回 false,连纯 ASCII 也被拒,比现有 #else 的 ASCII 回退分支(text_codec.cpp:104-127)更糟。附带成本:APK min_sdk 需 >=28;config/android/pyconfig.h 是 API 24 下 configure 的(HAVE_LANGINFO_H 因 nl_langinfo 需 API 26 被关掉),要重跑 gen_pyconfig.sh android 并重验内建模块表", "future_fix": "1) 探测改为 #if __has_include() && !defined(__ANDROID__),不要写 __ANDROID_API__ >= 28;2) Android 自带 GBK<->Unicode 表(约 22k 码位)。40250 原客户端走 Windows MultiByteToWideChar(CP949/CP936),跨平台无对应物;macOS 能用只是系统 libiconv 恰好带 GBK"}, "docs": ["docs/PORT-PLAN.md 新增「已知问题:Android 的 GBK 编解码(挂起,2026-09-23)」小节"], "tests": "仅文档改动;诊断由 NDK clang++ -fsyntax-only 双 API 等级实测得出", "not_done": "text_codec.cpp 未改动;Android 扩展构建目前仍是红的"} {"time": "2026-09-23T23:30:00Z", "event": "test_fix", "unit": "net 测试去 flaky:net_classic_session_test + net_loopback_test", "ported": [], "adapted": [], "deleted": [], "divergent": [], "needs_live": [], "trigger": "macOS 全量 ctest 连续两次各挂 1 个 net 测试,且每次挂的不是同一个(第一次 net.loopback_flow,第二次 net.classic_session)", "root_causes": ["accept_loopback(): poll() 的 `<= 0` 把 EINTR 当成对端从未连接;且单片 500ms 超时在有负载时不够。50 轮压测里 4 次失败全部源于此", "net_classic_session_test.cpp:570 的 pump 循环条件抄自上面的死端口用例,但此处 connect 会成功,stage 先经过 LoggingIn,循环提前一步退出", "同文件 5 处手写 pump 循环只给 10-20ms 等真实 loopback socket(非阻塞 connect 完成 / connect 被拒 / 对端 FIN)", "net_loopback_test.cpp 10 处 run(..., N, []{return false;}) 是固定空转而非等待条件,等不够就断言失败"], "fixes": ["accept_loopback() 改为 EINTR 重试 + 5s 截止时间(listener 本就是非阻塞,超时后 accept 不会挂住)", "新增 pump_until(session, want, max_ms=2000),替换全部 5 处手写循环;等的是断言真正关心的那个状态", "替换 replacement PHASE_LOGIN 处的单次 pump(前一条 CHECK 已经断言过「不在同一帧」,这里只需要后续某次 pump 收到)", "net_loopback_test 的 10 处固定空转改为条件等待;服务端批量收包用该批最后一个包的标志作条件(TCP 有序,最后一个到了说明前面都到了),客户端事件用 decltype 声明的本地累加器在谓词里 drain"], "speedup": {"net_classic_session_test": "61.2s -> 3.5s:两处 this-*-host-must-not-resolve.invalid 换成带空标签的名字。本机解析器不按 RFC 6761 本地拒绝 .invalid,每次发往上游等满 30s 超时;空标签让 getaddrinfo 在语法层返回同一个 EAI_NONAME,实测 <10ms", "net_loopback_test": "固定空转改条件退出后单跑 0.94s", "ctest_total": "78.7s -> 8.7s"}, "tests": "net_classic_session_test 100/100(修复前 50 轮挂 4 轮);net_loopback_test 100/100(修复前单独跑第 7 轮即挂);全量 ctest 27/27;port_map.py check 0 error;参考 EterPack.cpp 的 8 个 pack key 值逐个 git grep --cached -w,均未入库", "not_done": "只改测试,未改产品代码。这些都是测试自身的计时/错误处理缺陷,不是 mtnet 的行为问题"} {"time": "2026-09-23T11:00:00Z", "event": "port_round", "unit": "PORT-PLAN 批次 2P step 4 (macOS): the 40250 script layer starts inside the Godot process", "ported": [], "adapted": ["UserInterface/UserInterface.cpp:RunMainScript -> extension/src/platform/ScriptLib/PythonBoot.cpp (Start/RunMainScript/RunLine/Stop; 40250 keeps CPythonLauncher on Main()'s stack, Godot owns this process so the launcher has to outlive the call that starts it)", "EterBase/Debug.cpp:LogBox, EterBase/Debug.cpp:LogBoxf -> extension/src/platform/EterBase/Debug.cpp (stderr plus LastLogBoxMessage(); ScriptLib Traceback() reports through LogBoxf after PyErr_Fetch has cleared the exception, so this is the only place a script traceback survives)"], "deleted": [], "divergent": ["RunMainScript RegisterCommandLine passes the command line through unchanged: the -cs/-ncs auto-login decoding needs EterBase/Utils.cpp SplitLine and EterLib/Util.cpp base64_decode, both declared but not ported (批次 2V1). Nothing in this host passes -cs today.", "RunMainScript drops '--pause-before-create-window' (system(\"pause\")) and the XTrap init check: no console and no XTrap on macOS/Android.", "Of the 37 module initializers RunMainScript calls, only initpack() is called — the other 36 are 2V slices."], "needs_live": [], "staging": {"native": "extension/src/platform/ScriptLib/PythonBoot.{h,cpp} (godot-free, placed under ScriptLib because that is the directory port_logic/port_platform drop when `mtpython` is absent; compiled with the UserInterface library's definitions so its `#ifdef _DISTRIBUTE` gives __DEBUG__ = 0). extension/src/platform/EterBase/LogBox.h. extension/src/python_host_node.{h,cpp} -> GDScript class Metin2PythonHost (start/is_running/run_main_script/run_line/stop; each returns \"\" or the reason, and a build without the interpreter answers with a distinguishable message instead of failing to register).", "gdscript": "project/python_host_check.gd in two halves — the interpreter + stdlib half needs no 40250 pack and runs on any platform, the system.py half needs the pack and is skipped without it. project/python_host_test.gd (--script) is the desktop entry; MT_TEST_MODE=python in project/client_main.gd is the on-device entry, since export templates do not accept --script.", "boot": "Metin2PythonHost.start(\"\") stages the stdlib through Metin2Python.stdlib_path(), which until now had no caller outside python_stdlib_test.gd."}, "status_note": "macOS only. Android/iOS in-process is untouched: the APK cross-build is blocked on the GBK iconv issue (see the PORT-PLAN known-issue section, deferred by the user 2026-09-23), and a device has no 40250 Client/pack, so on a phone only the interpreter + stdlib half of the check can run. prototype.RunApp() is 2V0: system.py still stops at its first import. The real boot path (AppFlow) does not start the interpreter.", "tests": ["godot --headless --path project --script python_host_test.gd -> PASS: interpreter starts in-process, is_running(), a second start() is a no-op, `import os, string, types, codecs`, u'\\xe4'.encode('cp1252'), sys.path non-empty, system.py stops at ImportError: No module named app (identical to ctest port.python_launcher), stop() tears it down", "MT_TEST_MODE=python godot --headless --path project -> same result through client_main.gd", "ctest --test-dir build -> 27/27 passed (14.51s)"], "not_done": "Android/iOS 进程内验证;正式启动路径起解释器(2V0);RunMainScript 的 -cs 命令行解码(2V1)", "commit": "2P-step4-macos"} +{"time": "2026-09-23T11:40:00Z", "event": "port_round", "unit": "PORT-PLAN 批次 2V0-a: the EterPythonLib window-system headers enter the mirror", "ported": ["EterPythonLib/StdAfx.h", "EterPythonLib/PythonGraphic.h", "EterPythonLib/PythonWindow.h", "EterPythonLib/PythonWindowManager.h", "EterPythonLib/PythonSlotWindow.h", "EterPythonLib/PythonGridSlotWindow.h"], "adapted": [], "deleted": [], "divergent": [], "needs_live": [], "staging": {"scope": "headers only; no .cpp unit and therefore no port-map entry — declarations, nothing to call. The EterPythonLib .cpp units are 2V0-b.", "mechanical": "port_copy.py copy, 0 of 6 with manual edits: every one compiles as a mechanical CP949->UTF-8 / CRLF->LF / include-case copy.", "stdafx": "EterPythonLib/StdAfx.h had to come first: port_header_gate compiles each header behind its library's StdAfx.h, as 40250 does, and without it these five see neither , the STL, nor CSingleton.", "slice_list_correction": "audit/slices/2V0.json lists EterLib/Dimm.h as a missing header. It is not: 40250 vendors the MIDL output of the Windows SDK as EterLib/Dimm.h, and extension/src/port/common/shim/win32/Dimm.h already shims it (a mirror copy shadows the shim for EterLib/IME.h's quoted include and breaks the build on 'rpc.h'). Copied, found, and removed again."}, "status_note": "2V0 entry state measured: of the slice's 212 headers 164 were already in the mirror, 48 were not (1 EterLib = the SDK shim above, 5 EterPythonLib = this round, 42 UserInterface = 2V0-d, all behind UserInterface/PythonApplication.h). Of the 10 units, 2 are ported (ScriptLib/PythonLauncher.cpp, UserInterface/PythonPackModule.cpp) and 8 are not.", "tests": ["cmake --build build --target port_header_gate -> the 6 new gate translation units compile (each header alone, twice, behind EterPythonLib/StdAfx.h)", "ctest --test-dir build -> 27/27 passed"], "not_done": "EterPythonLib/*.cpp(2V0-b);wndMgr/grp/grpImage/grpText 模块(2V0-c);42 个 UserInterface 头 + PythonApplicationModule.cpp(2V0-d)", "commit": "2V0-a"} diff --git a/docs/PORT-PLAN.md b/docs/PORT-PLAN.md index 387bde1d..4610783e 100644 --- a/docs/PORT-PLAN.md +++ b/docs/PORT-PLAN.md @@ -385,6 +385,22 @@ extension/third_party/cpython-2.7.18/ # 静态库(2P 批次 `EterPythonLib/PythonWindow*.cpp`、`PythonWindowManager*.cpp`、`PythonGraphic*Module.cpp`、 `PythonApplicationModule.cpp` 和所需 platform UI adapter;玩法模块先用桩。验收为 app 进程内运行 `system.py`,显示并可操作 Logo/Popup,输入、焦点、裁剪、文本和图片至少各有一个运行测试。 + + **入口状态(2026-09-23 实测)**:`audit/slices/2V0.json` 的 212 个头里 164 个已在镜像中,缺 48 个; + 10 个单元里 `ScriptLib/PythonLauncher.cpp`、`UserInterface/PythonPackModule.cpp` 已移植,缺 8 个。 + (清单里的 `EterLib/Dimm.h` 是误报:那是 Windows SDK `` 的 MIDL 产物,40250 把它放在 EterLib 下, + `port/common/shim/win32/Dimm.h` 已经顶掉了;镜像一份反而会遮住 shim,`IME.h` 就找不到 `rpc.h`。) + + 子步骤,按依赖从下往上: + + | 子步骤 | 内容 | 状态 | + | --- | --- | --- | + | 2V0-a | `EterPythonLib/StdAfx.h` + 5 个窗口系统头进镜像,门禁绿 | 完成 | + | 2V0-b | `EterPythonLib/PythonWindow.cpp`、`PythonWindowManager.cpp`(窗口树逻辑) | 未做 | + | 2V0-c | `wndMgr` / `grp` / `grpImage` / `grpText` / `grpThing` 模块 | 未做 | + | 2V0-d | 42 个 `UserInterface` 头(都在 `PythonApplication.h` 后面)+ `PythonApplicationModule.cpp`(`app`) | 未做 | + | 2V0-e | `dbg` 等桩模块补齐,`system.py` 跑到 `prototype.RunApp()` | 未做 | + | 2V0-f | Godot 渲染器上的 platform UI adapter;Logo/Popup 可显示可操作 | 未做 | 2. **2V1 — 登录/选角**:加入 `PythonNetworkStream{,PhaseHandShake,PhaseLogin,PhaseSelect,PhaseLoading}.cpp`、 `PythonNetworkStreamModule.cpp`、AccountConnector 及登录/选角脚本真实调用到的模块。验收为 FakeServer 离线完成 phase 顺序, 再以真服 smoke 证明登录、角色列表和选择进入 Loading;未验证的服务器分支记 `NEEDS_LIVE`。 diff --git a/extension/src/port/EterPythonLib/PythonGraphic.h b/extension/src/port/EterPythonLib/PythonGraphic.h new file mode 100644 index 00000000..42e2e006 --- /dev/null +++ b/extension/src/port/EterPythonLib/PythonGraphic.h @@ -0,0 +1,68 @@ +#pragma once + +#include "../EterLib/GrpTextInstance.h" +#include "../EterLib/GrpMarkInstance.h" +#include "../EterLib/GrpImageInstance.h" +#include "../EterLib/GrpExpandedImageInstance.h" + +#include "../EterGrnLib/ThingInstance.h" + +class CPythonGraphic : public CScreen, public CSingleton +{ + public: + CPythonGraphic(); + virtual ~CPythonGraphic(); + + void Destroy(); + + void PushState(); + void PopState(); + + LPDIRECT3D8 GetD3D(); + + float GetOrthoDepth(); + void SetInterfaceRenderState(); + void SetGameRenderState(); + + void SetCursorPosition(int x, int y); + + void SetOmniLight(); + + void SetViewport(float fx, float fy, float fWidth, float fHeight); + void RestoreViewport(); + + long GenerateColor(float r, float g, float b, float a); + void RenderDownButton(float sx, float sy, float ex, float ey); + void RenderUpButton(float sx, float sy, float ex, float ey); + + void RenderImage(CGraphicImageInstance* pImageInstance, float x, float y); + void RenderAlphaImage(CGraphicImageInstance* pImageInstance, float x, float y, float aLeft, float aRight); + void RenderCoolTimeBox(float fxCenter, float fyCenter, float fRadius, float fTime); + + bool SaveJPEG(const char * pszFileName, LPBYTE pbyBuffer, UINT uWidth, UINT uHeight); + bool SaveScreenShot(const char *szFileName); + + DWORD GetAvailableMemory(); + void SetGamma(float fGammaFactor = 1.0f); + + protected: + typedef struct SState + { + D3DXMATRIX matView; + D3DXMATRIX matProj; + } TState; + + DWORD m_lightColor; + DWORD m_darkColor; + + protected: + std::stack m_stateStack; + + D3DXMATRIX m_SaveWorldMatrix; + + CCullingManager m_CullingManager; + + D3DVIEWPORT8 m_backupViewport; + + float m_fOrthoDepth; +}; \ No newline at end of file diff --git a/extension/src/port/EterPythonLib/PythonGridSlotWindow.h b/extension/src/port/EterPythonLib/PythonGridSlotWindow.h new file mode 100644 index 00000000..a07ba832 --- /dev/null +++ b/extension/src/port/EterPythonLib/PythonGridSlotWindow.h @@ -0,0 +1,40 @@ +#pragma once + +#include "PythonSlotWindow.h" + +namespace UI +{ + class CGridSlotWindow : public CSlotWindow + { + public: + static DWORD Type(); + + public: + CGridSlotWindow(PyObject * ppyObject); + virtual ~CGridSlotWindow(); + + void Destroy(); + + void ArrangeGridSlot(DWORD dwStartIndex, DWORD dwxCount, DWORD dwyCount, int ixSlotSize, int iySlotSize, int ixTemporarySize, int iyTemporarySize); + + protected: + void __Initialize(); + + BOOL GetPickedSlotPointer(TSlot ** ppSlot); + BOOL GetPickedSlotList(int iWidth, int iHeight, std::list * pSlotPointerList); + BOOL GetGridSlotPointer(int ix, int iy, TSlot ** ppSlot); + BOOL GetPickedGridSlotPosition(int ixLocal, int iyLocal, int * pix, int * piy); + BOOL CheckMoving(DWORD dwSlotNumber, DWORD dwItemIndex, const std::list & c_rSlotList); + + BOOL OnIsType(DWORD dwType); + + void OnRefreshSlot(); + void OnRenderPickingSlot(); + + protected: + DWORD m_dwxCount; + DWORD m_dwyCount; + + std::vector m_SlotVector; + }; +}; diff --git a/extension/src/port/EterPythonLib/PythonSlotWindow.h b/extension/src/port/EterPythonLib/PythonSlotWindow.h new file mode 100644 index 00000000..ba45ac7e --- /dev/null +++ b/extension/src/port/EterPythonLib/PythonSlotWindow.h @@ -0,0 +1,211 @@ +#pragma once + +#include "PythonWindow.h" + +namespace UI +{ + enum + { + ITEM_WIDTH = 32, + ITEM_HEIGHT = 32, + + SLOT_NUMBER_NONE = 0xffffffff, + }; + + enum ESlotStyle + { + SLOT_STYLE_NONE, + SLOT_STYLE_PICK_UP, + SLOT_STYLE_SELECT, + }; + + enum ESlotState + { + SLOT_STATE_LOCK = (1 << 0), + SLOT_STATE_CANT_USE = (1 << 1), + SLOT_STATE_DISABLE = (1 << 2), + SLOT_STATE_ALWAYS_RENDER_COVER = (1 << 3), // 현재 Cover 버튼은 슬롯에 무언가 들어와 있을 때에만 렌더링 하는데, 이 flag가 있으면 빈 슬롯이어도 커버 렌더링 + }; + + class CSlotWindow : public CWindow + { + public: + static DWORD Type(); + + public: + class CSlotButton; + class CCoverButton; + class CCoolTimeFinishEffect; + + friend class CSlotButton; + friend class CCoverButton; + + typedef struct SSlot + { + DWORD dwState; + DWORD dwSlotNumber; + DWORD dwCenterSlotNumber; // NOTE : 사이즈가 큰 아이템의 경우 아이템의 실제 위치 번호 + DWORD dwItemIndex; // NOTE : 여기서 사용되는 Item이라는 단어는 좁은 개념의 것이 아닌, + BOOL isItem; // "슬롯의 내용물"이라는 포괄적인 개념어. 더 좋은 것이 있을까? - [levites] + + // CoolTime + float fCoolTime; + float fStartCoolTime; + + // Toggle + BOOL bActive; + + int ixPosition; + int iyPosition; + + int ixCellSize; + int iyCellSize; + + BYTE byxPlacedItemSize; + BYTE byyPlacedItemSize; + + CGraphicImageInstance * pInstance; + CNumberLine * pNumberLine; + + bool bRenderBaseSlotImage; + CCoverButton * pCoverButton; + CSlotButton * pSlotButton; + CImageBox * pSignImage; + CAniImageBox * pFinishCoolTimeEffect; + } TSlot; + typedef std::list TSlotList; + typedef TSlotList::iterator TSlotListIterator; + + public: + CSlotWindow(PyObject * ppyObject); + virtual ~CSlotWindow(); + + void Destroy(); + + // Manage Slot + void SetSlotType(DWORD dwType); + void SetSlotStyle(DWORD dwStyle); + + void AppendSlot(DWORD dwIndex, int ixPosition, int iyPosition, int ixCellSize, int iyCellSize); + void SetCoverButton(DWORD dwIndex, const char * c_szUpImageName, const char * c_szOverImageName, const char * c_szDownImageName, const char * c_szDisableImageName, BOOL bLeftButtonEnable, BOOL bRightButtonEnable); + void SetSlotBaseImage(const char * c_szFileName, float fr, float fg, float fb, float fa); + void AppendSlotButton(const char * c_szUpImageName, const char * c_szOverImageName, const char * c_szDownImageName); + void AppendRequirementSignImage(const char * c_szImageName); + + void EnableCoverButton(DWORD dwIndex); + void DisableCoverButton(DWORD dwIndex); + void SetAlwaysRenderCoverButton(DWORD dwIndex, bool bAlwaysRender = false); + + void ShowSlotBaseImage(DWORD dwIndex); + void HideSlotBaseImage(DWORD dwIndex); + BOOL IsDisableCoverButton(DWORD dwIndex); + BOOL HasSlot(DWORD dwIndex); + + void ClearAllSlot(); + void ClearSlot(DWORD dwIndex); + void SetSlot(DWORD dwIndex, DWORD dwVirtualNumber, BYTE byWidth, BYTE byHeight, CGraphicImage * pImage, D3DXCOLOR& diffuseColor); + void SetSlotCount(DWORD dwIndex, DWORD dwCount); + void SetSlotCountNew(DWORD dwIndex, DWORD dwGrade, DWORD dwCount); + void SetSlotCoolTime(DWORD dwIndex, float fCoolTime, float fElapsedTime = 0.0f); + void ActivateSlot(DWORD dwIndex); + void DeactivateSlot(DWORD dwIndex); + void RefreshSlot(); + + DWORD GetSlotCount(); + + void LockSlot(DWORD dwIndex); + void UnlockSlot(DWORD dwIndex); + BOOL IsLockSlot(DWORD dwIndex); + void SetCantUseSlot(DWORD dwIndex); + void SetUseSlot(DWORD dwIndex); + BOOL IsCantUseSlot(DWORD dwIndex); + void EnableSlot(DWORD dwIndex); + void DisableSlot(DWORD dwIndex); + BOOL IsEnableSlot(DWORD dwIndex); + + // Select + void ClearSelected(); + void SelectSlot(DWORD dwSelectingIndex); + BOOL isSelectedSlot(DWORD dwIndex); + DWORD GetSelectedSlotCount(); + DWORD GetSelectedSlotNumber(DWORD dwIndex); + + // Slot Button + void ShowSlotButton(DWORD dwSlotNumber); + void HideAllSlotButton(); + void OnPressedSlotButton(DWORD dwType, DWORD dwSlotNumber, BOOL isLeft = TRUE); + + // Requirement Sign + void ShowRequirementSign(DWORD dwSlotNumber); + void HideRequirementSign(DWORD dwSlotNumber); + + // ToolTip + BOOL OnOverInItem(DWORD dwSlotNumber); + void OnOverOutItem(); + + // For Usable Item + void SetUseMode(BOOL bFlag); + void SetUsableItem(BOOL bFlag); + + // CallBack + void ReserveDestroyCoolTimeFinishEffect(DWORD dwSlotIndex); + + protected: + void __Initialize(); + void __CreateToggleSlotImage(); + void __CreateSlotEnableEffect(); + void __CreateFinishCoolTimeEffect(TSlot * pSlot); + void __CreateBaseImage(const char * c_szFileName, float fr, float fg, float fb, float fa); + + void __DestroyToggleSlotImage(); + void __DestroySlotEnableEffect(); + void __DestroyFinishCoolTimeEffect(TSlot * pSlot); + void __DestroyBaseImage(); + + // Event + void OnUpdate(); + void OnRender(); + BOOL OnMouseLeftButtonDown(); + BOOL OnMouseLeftButtonUp(); + BOOL OnMouseRightButtonDown(); + BOOL OnMouseLeftButtonDoubleClick(); + void OnMouseOverOut(); + void OnMouseOver(); + void RenderSlotBaseImage(); + void RenderLockedSlot(); + virtual void OnRenderPickingSlot(); + virtual void OnRenderSelectedSlot(); + + // Select + void OnSelectEmptySlot(int iSlotNumber); + void OnSelectItemSlot(int iSlotNumber); + void OnUnselectEmptySlot(int iSlotNumber); + void OnUnselectItemSlot(int iSlotNumber); + void OnUseSlot(); + + // Manage Slot + BOOL GetSlotPointer(DWORD dwIndex, TSlot ** ppSlot); + BOOL GetSelectedSlotPointer(TSlot ** ppSlot); + virtual BOOL GetPickedSlotPointer(TSlot ** ppSlot); + void ClearSlot(TSlot * pSlot); + virtual void OnRefreshSlot(); + + // ETC + BOOL OnIsType(DWORD dwType); + + protected: + DWORD m_dwSlotType; + DWORD m_dwSlotStyle; + std::list m_dwSelectedSlotIndexList; + TSlotList m_SlotList; + DWORD m_dwToolTipSlotNumber; + + BOOL m_isUseMode; + BOOL m_isUsableItem; + + CGraphicImageInstance * m_pBaseImageInstance; + CImageBox * m_pToggleSlotImage; + CAniImageBox * m_pSlotActiveEffect; + std::deque m_ReserveDestroyEffectDeque; + }; +}; \ No newline at end of file diff --git a/extension/src/port/EterPythonLib/PythonWindow.h b/extension/src/port/EterPythonLib/PythonWindow.h new file mode 100644 index 00000000..6cbfcb08 --- /dev/null +++ b/extension/src/port/EterPythonLib/PythonWindow.h @@ -0,0 +1,525 @@ +#pragma once + +#include "../EterBase/Utils.h" + +namespace UI +{ + class CWindow + { + public: + typedef std::list TWindowContainer; + + static DWORD Type(); + BOOL IsType(DWORD dwType); + + enum EHorizontalAlign + { + HORIZONTAL_ALIGN_LEFT = 0, + HORIZONTAL_ALIGN_CENTER = 1, + HORIZONTAL_ALIGN_RIGHT = 2, + }; + + enum EVerticalAlign + { + VERTICAL_ALIGN_TOP = 0, + VERTICAL_ALIGN_CENTER = 1, + VERTICAL_ALIGN_BOTTOM = 2, + }; + + enum EFlags + { + FLAG_MOVABLE = (1 << 0), // 움직일 수 있는 창 + FLAG_LIMIT = (1 << 1), // 창이 화면을 벗어나지 않음 + FLAG_SNAP = (1 << 2), // 스냅 될 수 있는 창 + FLAG_DRAGABLE = (1 << 3), + FLAG_ATTACH = (1 << 4), // 완전히 부모에 붙어 있는 창 (For Drag / ex. ScriptWindow) + FLAG_RESTRICT_X = (1 << 5), // 좌우 이동 제한 + FLAG_RESTRICT_Y = (1 << 6), // 상하 이동 제한 + FLAG_NOT_CAPTURE = (1 << 7), + FLAG_FLOAT = (1 << 8), // 공중에 떠있어서 순서 재배치가 되는 창 + FLAG_NOT_PICK = (1 << 9), // 마우스에 의해 Pick되지 않는 창 + FLAG_IGNORE_SIZE = (1 << 10), + FLAG_RTL = (1 << 11), // Right-to-left + }; + + public: + CWindow(PyObject * ppyObject); + virtual ~CWindow(); + + void AddChild(CWindow * pWin); + + void Clear(); + void DestroyHandle(); + void Update(); + void Render(); + + void SetName(const char * c_szName); + const char * GetName() { return m_strName.c_str(); } + void SetSize(long width, long height); + long GetWidth() { return m_lWidth; } + long GetHeight() { return m_lHeight; } + + void SetHorizontalAlign(DWORD dwAlign); + void SetVerticalAlign(DWORD dwAlign); + void SetPosition(long x, long y); + void GetPosition(long * plx, long * ply); + long GetPositionX( void ) const { return m_x; } + long GetPositionY( void ) const { return m_y; } + RECT & GetRect() { return m_rect; } + void GetLocalPosition(long & rlx, long & rly); + void GetMouseLocalPosition(long & rlx, long & rly); + long UpdateRect(); + + RECT & GetLimitBias() { return m_limitBiasRect; } + void SetLimitBias(long l, long r, long t, long b) { m_limitBiasRect.left = l, m_limitBiasRect.right = r, m_limitBiasRect.top = t, m_limitBiasRect.bottom = b; } + + void Show(); + void Hide(); + bool IsShow() { return m_bShow; } + bool IsRendering(); + + bool HasParent() { return m_pParent ? true : false; } + bool HasChild() { return m_pChildList.empty() ? false : true; } + int GetChildCount() { return m_pChildList.size(); } + + CWindow * GetRoot(); + CWindow * GetParent(); + bool IsChild(CWindow * pWin); + void DeleteChild(CWindow * pWin); + void SetTop(CWindow * pWin); + + bool IsIn(long x, long y); + bool IsIn(); + CWindow * PickWindow(long x, long y); + CWindow * PickTopWindow(long x, long y); // NOTE : Children으로 내려가지 않고 상위에서만 + // 체크 하는 특화된 함수 + + void __RemoveReserveChildren(); + + void AddFlag(DWORD flag) { SET_BIT(m_dwFlag, flag); } + void RemoveFlag(DWORD flag) { REMOVE_BIT(m_dwFlag, flag); } + bool IsFlag(DWORD flag) { return (m_dwFlag & flag) ? true : false; } + ///////////////////////////////////// + + virtual void OnRender(); + virtual void OnUpdate(); + virtual void OnChangePosition(){} + + virtual void OnSetFocus(); + virtual void OnKillFocus(); + + virtual void OnMouseDrag(long lx, long ly); + virtual void OnMouseOverIn(); + virtual void OnMouseOverOut(); + virtual void OnMouseOver(); + virtual void OnDrop(); + virtual void OnTop(); + virtual void OnIMEUpdate(); + + virtual void OnMoveWindow(long x, long y); + + /////////////////////////////////////// + + BOOL RunIMETabEvent(); + BOOL RunIMEReturnEvent(); + BOOL RunIMEKeyDownEvent(int ikey); + + CWindow * RunKeyDownEvent(int ikey); + BOOL RunKeyUpEvent(int ikey); + BOOL RunPressEscapeKeyEvent(); + BOOL RunPressExitKeyEvent(); + + virtual BOOL OnIMETabEvent(); + virtual BOOL OnIMEReturnEvent(); + virtual BOOL OnIMEKeyDownEvent(int ikey); + + virtual BOOL OnIMEChangeCodePage(); + virtual BOOL OnIMEOpenCandidateListEvent(); + virtual BOOL OnIMECloseCandidateListEvent(); + virtual BOOL OnIMEOpenReadingWndEvent(); + virtual BOOL OnIMECloseReadingWndEvent(); + + virtual BOOL OnMouseLeftButtonDown(); + virtual BOOL OnMouseLeftButtonUp(); + virtual BOOL OnMouseLeftButtonDoubleClick(); + virtual BOOL OnMouseRightButtonDown(); + virtual BOOL OnMouseRightButtonUp(); + virtual BOOL OnMouseRightButtonDoubleClick(); + virtual BOOL OnMouseMiddleButtonDown(); + virtual BOOL OnMouseMiddleButtonUp(); + + virtual BOOL OnKeyDown(int ikey); + virtual BOOL OnKeyUp(int ikey); + virtual BOOL OnPressEscapeKey(); + virtual BOOL OnPressExitKey(); + /////////////////////////////////////// + + virtual void SetColor(DWORD dwColor){} + virtual BOOL OnIsType(DWORD dwType); + ///////////////////////////////////// + + virtual BOOL IsWindow() { return TRUE; } + ///////////////////////////////////// + + protected: + std::string m_strName; + + EHorizontalAlign m_HorizontalAlign; + EVerticalAlign m_VerticalAlign; + long m_x, m_y; // X,Y 상대좌표 + long m_lWidth, m_lHeight; // 크기 + RECT m_rect; // Global 좌표 + RECT m_limitBiasRect; // limit bias 값 + + bool m_bMovable; + bool m_bShow; + + DWORD m_dwFlag; + + PyObject * m_poHandler; + + CWindow * m_pParent; + TWindowContainer m_pChildList; + + BOOL m_isUpdatingChildren; + TWindowContainer m_pReserveChildList; + +#ifdef _DEBUG + public: + DWORD DEBUG_dwCounter; +#endif + }; + + class CLayer : public CWindow + { + public: + CLayer(PyObject * ppyObject) : CWindow(ppyObject) {} + virtual ~CLayer() {} + + BOOL IsWindow() { return FALSE; } + }; + + class CBox : public CWindow + { + public: + CBox(PyObject * ppyObject); + virtual ~CBox(); + + void SetColor(DWORD dwColor); + + protected: + void OnRender(); + + protected: + DWORD m_dwColor; + }; + + class CBar : public CWindow + { + public: + CBar(PyObject * ppyObject); + virtual ~CBar(); + + void SetColor(DWORD dwColor); + + protected: + void OnRender(); + + protected: + DWORD m_dwColor; + }; + + class CLine : public CWindow + { + public: + CLine(PyObject * ppyObject); + virtual ~CLine(); + + void SetColor(DWORD dwColor); + + protected: + void OnRender(); + + protected: + DWORD m_dwColor; + }; + + class CBar3D : public CWindow + { + public: + static DWORD Type(); + + public: + CBar3D(PyObject * ppyObject); + virtual ~CBar3D(); + + void SetColor(DWORD dwLeft, DWORD dwRight, DWORD dwCenter); + + protected: + void OnRender(); + + protected: + DWORD m_dwLeftColor; + DWORD m_dwRightColor; + DWORD m_dwCenterColor; + }; + + // Text + class CTextLine : public CWindow + { + public: + CTextLine(PyObject * ppyObject); + virtual ~CTextLine(); + + void SetMax(int iMax); + void SetHorizontalAlign(int iType); + void SetVerticalAlign(int iType); + void SetSecret(BOOL bFlag); + void SetOutline(BOOL bFlag); + void SetFeather(BOOL bFlag); + void SetMultiLine(BOOL bFlag); + void SetFontName(const char * c_szFontName); + void SetFontColor(DWORD dwColor); + void SetLimitWidth(float fWidth); + + void ShowCursor(); + void HideCursor(); + int GetCursorPosition(); + + void SetText(const char * c_szText); + const char * GetText(); + + void GetTextSize(int* pnWidth, int* pnHeight); + + protected: + void OnUpdate(); + void OnRender(); + void OnChangePosition(); + + virtual void OnSetText(const char * c_szText); + + protected: + CGraphicTextInstance m_TextInstance; + }; + + class CNumberLine : public CWindow + { + public: + CNumberLine(PyObject * ppyObject); + CNumberLine(CWindow * pParent); + virtual ~CNumberLine(); + + void SetPath(const char * c_szPath); + void SetHorizontalAlign(int iType); + void SetNumber(const char * c_szNumber); + + protected: + void ClearNumber(); + void OnRender(); + void OnChangePosition(); + + protected: + std::string m_strPath; + std::string m_strNumber; + std::vector m_ImageInstanceVector; + + int m_iHorizontalAlign; + DWORD m_dwWidthSummary; + }; + + // Image + class CImageBox : public CWindow + { + public: + CImageBox(PyObject * ppyObject); + virtual ~CImageBox(); + + BOOL LoadImage(const char * c_szFileName); + void SetDiffuseColor(float fr, float fg, float fb, float fa); + + int GetWidth(); + int GetHeight(); + + protected: + virtual void OnCreateInstance(); + virtual void OnDestroyInstance(); + + virtual void OnUpdate(); + virtual void OnRender(); + void OnChangePosition(); + + protected: + CGraphicImageInstance * m_pImageInstance; + }; + class CMarkBox : public CWindow + { + public: + CMarkBox(PyObject * ppyObject); + virtual ~CMarkBox(); + + void LoadImage(const char * c_szFilename); + void SetDiffuseColor(float fr, float fg, float fb, float fa); + void SetIndex(UINT uIndex); + void SetScale(FLOAT fScale); + + protected: + virtual void OnCreateInstance(); + virtual void OnDestroyInstance(); + + virtual void OnUpdate(); + virtual void OnRender(); + void OnChangePosition(); + protected: + CGraphicMarkInstance * m_pMarkInstance; + }; + class CExpandedImageBox : public CImageBox + { + public: + static DWORD Type(); + + public: + CExpandedImageBox(PyObject * ppyObject); + virtual ~CExpandedImageBox(); + + void SetScale(float fx, float fy); + void SetOrigin(float fx, float fy); + void SetRotation(float fRotation); + void SetRenderingRect(float fLeft, float fTop, float fRight, float fBottom); + void SetRenderingMode(int iMode); + + protected: + void OnCreateInstance(); + void OnDestroyInstance(); + + virtual void OnUpdate(); + virtual void OnRender(); + + BOOL OnIsType(DWORD dwType); + }; + class CAniImageBox : public CWindow + { + public: + static DWORD Type(); + + public: + CAniImageBox(PyObject * ppyObject); + virtual ~CAniImageBox(); + + void SetDelay(int iDelay); + void AppendImage(const char * c_szFileName); + void SetRenderingRect(float fLeft, float fTop, float fRight, float fBottom); + void SetRenderingMode(int iMode); + + void ResetFrame(); + + protected: + void OnUpdate(); + void OnRender(); + void OnChangePosition(); + virtual void OnEndFrame(); + + BOOL OnIsType(DWORD dwType); + + protected: + BYTE m_bycurDelay; + BYTE m_byDelay; + BYTE m_bycurIndex; + std::vector m_ImageVector; + }; + + // Button + class CButton : public CWindow + { + public: + CButton(PyObject * ppyObject); + virtual ~CButton(); + + BOOL SetUpVisual(const char * c_szFileName); + BOOL SetOverVisual(const char * c_szFileName); + BOOL SetDownVisual(const char * c_szFileName); + BOOL SetDisableVisual(const char * c_szFileName); + + const char * GetUpVisualFileName(); + const char * GetOverVisualFileName(); + const char * GetDownVisualFileName(); + + void Flash(); + void Enable(); + void Disable(); + + void SetUp(); + void Up(); + void Over(); + void Down(); + + BOOL IsDisable(); + BOOL IsPressed(); + + protected: + void OnUpdate(); + void OnRender(); + void OnChangePosition(); + + BOOL OnMouseLeftButtonDown(); + BOOL OnMouseLeftButtonDoubleClick(); + BOOL OnMouseLeftButtonUp(); + void OnMouseOverIn(); + void OnMouseOverOut(); + + BOOL IsEnable(); + + void SetCurrentVisual(CGraphicImageInstance * pVisual); + + protected: + BOOL m_bEnable; + BOOL m_isPressed; + BOOL m_isFlash; + CGraphicImageInstance * m_pcurVisual; + CGraphicImageInstance m_upVisual; + CGraphicImageInstance m_overVisual; + CGraphicImageInstance m_downVisual; + CGraphicImageInstance m_disableVisual; + }; + class CRadioButton : public CButton + { + public: + CRadioButton(PyObject * ppyObject); + virtual ~CRadioButton(); + + protected: + BOOL OnMouseLeftButtonDown(); + BOOL OnMouseLeftButtonUp(); + void OnMouseOverIn(); + void OnMouseOverOut(); + }; + class CToggleButton : public CButton + { + public: + CToggleButton(PyObject * ppyObject); + virtual ~CToggleButton(); + + protected: + BOOL OnMouseLeftButtonDown(); + BOOL OnMouseLeftButtonUp(); + void OnMouseOverIn(); + void OnMouseOverOut(); + }; + class CDragButton : public CButton + { + public: + CDragButton(PyObject * ppyObject); + virtual ~CDragButton(); + + void SetRestrictMovementArea(int ix, int iy, int iwidth, int iheight); + + protected: + void OnChangePosition(); + void OnMouseOverIn(); + void OnMouseOverOut(); + + protected: + RECT m_restrictArea; + }; +}; + +extern BOOL g_bOutlineBoxEnable; diff --git a/extension/src/port/EterPythonLib/PythonWindowManager.h b/extension/src/port/EterPythonLib/PythonWindowManager.h new file mode 100644 index 00000000..d7681a21 --- /dev/null +++ b/extension/src/port/EterPythonLib/PythonWindowManager.h @@ -0,0 +1,187 @@ +#pragma once + +namespace UI +{ + class CWindow; + + class CWindowManager : public CSingleton + { + public: + typedef std::map TLayerContainer; + typedef std::list TWindowContainer; + typedef std::map TKeyCaptureWindowMap; + + public: + CWindowManager(); + virtual ~CWindowManager(); + + void Destroy(); + + float GetAspect(); + void SetScreenSize(long lWidth, long lHeight); + void SetResolution(int hres, int vres); + + void GetResolution(long & rx, long & ry) + { + rx=m_iHres; + ry=m_iVres; + } + + void SetMouseHandler(PyObject * poMouseHandler); + long GetScreenWidth() { return m_lWidth; } + long GetScreenHeight() { return m_lHeight; } + void GetMousePosition(long & rx, long & ry); + BOOL IsDragging(); + + CWindow * GetLockWindow() { return m_pLockWindow; } + CWindow * GetPointWindow() { return m_pPointWindow; } + bool IsFocus() { return (m_pActiveWindow || m_pLockWindow); } + bool IsFocusWindow(CWindow * pWindow) { return pWindow == m_pActiveWindow; } + + void SetParent(CWindow * pWindow, CWindow * pParentWindow); + void SetPickAlways(CWindow * pWindow); + + enum + { + WT_NORMAL, + WT_SLOT, + WT_GRIDSLOT, + WT_TEXTLINE, + WT_MARKBOX, + WT_IMAGEBOX, + WT_EXP_IMAGEBOX, + WT_ANI_IMAGEBOX, + WT_BUTTON, + WT_RATIOBUTTON, + WT_TOGGLEBUTTON, + WT_DRAGBUTTON, + WT_BOX, + WT_BAR, + WT_LINE, + WT_BAR3D, + WT_NUMLINE, + }; + + CWindow * RegisterWindow(PyObject * po, const char * c_szLayer); + CWindow * RegisterTypeWindow(PyObject * po, DWORD dwWndType, const char * c_szLayer); + + CWindow * RegisterSlotWindow(PyObject * po, const char * c_szLayer); + CWindow * RegisterGridSlotWindow(PyObject * po, const char * c_szLayer); + CWindow * RegisterTextLine(PyObject * po, const char * c_szLayer); + CWindow * RegisterMarkBox(PyObject * po, const char * c_szLayer); + CWindow * RegisterImageBox(PyObject * po, const char * c_szLayer); + CWindow * RegisterExpandedImageBox(PyObject * po, const char * c_szLayer); + CWindow * RegisterAniImageBox(PyObject * po, const char * c_szLayer); + CWindow * RegisterButton(PyObject * po, const char * c_szLayer); + CWindow * RegisterRadioButton(PyObject * po, const char * c_szLayer); + CWindow * RegisterToggleButton(PyObject * po, const char * c_szLayer); + CWindow * RegisterDragButton(PyObject * po, const char * c_szLayer); + CWindow * RegisterBox(PyObject * po, const char * c_szLayer); + CWindow * RegisterBar(PyObject * po, const char * c_szLayer); + CWindow * RegisterLine(PyObject * po, const char * c_szLayer); + CWindow * RegisterBar3D(PyObject * po, const char * c_szLayer); + CWindow * RegisterNumberLine(PyObject * po, const char * c_szLayer); + + void DestroyWindow(CWindow * pWin); + void NotifyDestroyWindow(CWindow * pWindow); + + // Attaching Icon + BOOL IsAttaching(); + DWORD GetAttachingType(); + DWORD GetAttachingIndex(); + DWORD GetAttachingSlotNumber(); + void GetAttachingIconSize(BYTE * pbyWidth, BYTE * pbyHeight); + void AttachIcon(DWORD dwType, DWORD dwIndex, DWORD dwSlotNumber, BYTE byWidth, BYTE byHeight); + void DeattachIcon(); + void SetAttachingFlag(BOOL bFlag); + // Attaching Icon + + void OnceIgnoreMouseLeftButtonUpEvent(); + void LockWindow(CWindow * pWin); + void UnlockWindow(); + + void ActivateWindow(CWindow * pWin); + void DeactivateWindow(); + CWindow * GetActivateWindow(); + void SetTop(CWindow * pWin); + void SetTopUIWindow(); + void ResetCapture(); + + void Update(); + void Render(); + + void RunMouseMove(long x, long y); + void RunMouseLeftButtonDown(long x, long y); + void RunMouseLeftButtonUp(long x, long y); + void RunMouseLeftButtonDoubleClick(long x, long y); + void RunMouseRightButtonDown(long x, long y); + void RunMouseRightButtonUp(long x, long y); + void RunMouseRightButtonDoubleClick(long x, long y); + void RunMouseMiddleButtonDown(long x, long y); + void RunMouseMiddleButtonUp(long x, long y); + + void RunIMEUpdate(); + void RunIMETabEvent(); + void RunIMEReturnEvent(); + void RunIMEKeyDown(int vkey); + void RunChangeCodePage(); + void RunOpenCandidate(); + void RunCloseCandidate(); + void RunOpenReading(); + void RunCloseReading(); + + void RunKeyDown(int vkey); + void RunKeyUp(int vkey); + void RunPressEscapeKey(); + void RunPressExitKey(); + + private: + void SetMousePosition(long x, long y); + CWindow * __PickWindow(long x, long y); + + CWindow * __NewWindow(PyObject * po, DWORD dwWndType); + void __ClearReserveDeleteWindowList(); + + private: + long m_lWidth; + long m_lHeight; + + int m_iVres; + int m_iHres; + + long m_lMouseX, m_lMouseY; + long m_lDragX, m_lDragY; + long m_lPickedX, m_lPickedY; + + BOOL m_bOnceIgnoreMouseLeftButtonUpEventFlag; + int m_iIgnoreEndTime; + + // Attaching Icon + PyObject * m_poMouseHandler; + BOOL m_bAttachingFlag; + DWORD m_dwAttachingType; + DWORD m_dwAttachingIndex; + DWORD m_dwAttachingSlotNumber; + BYTE m_byAttachingIconWidth; + BYTE m_byAttachingIconHeight; + // Attaching Icon + + CWindow * m_pActiveWindow; + TWindowContainer m_ActiveWindowList; + CWindow * m_pLockWindow; + TWindowContainer m_LockWindowList; + CWindow * m_pPointWindow; + CWindow * m_pLeftCaptureWindow; + CWindow * m_pRightCaptureWindow; + CWindow * m_pMiddleCaptureWindow; + TKeyCaptureWindowMap m_KeyCaptureWindowMap; + TWindowContainer m_ReserveDeleteWindowList; + TWindowContainer m_PickAlwaysWindowList; + + CWindow * m_pRootWindow; + TWindowContainer m_LayerWindowList; + TLayerContainer m_LayerWindowMap; + }; + + PyObject * BuildEmptyTuple(); +}; diff --git a/extension/src/port/EterPythonLib/StdAfx.h b/extension/src/port/EterPythonLib/StdAfx.h new file mode 100644 index 00000000..6b9274de --- /dev/null +++ b/extension/src/port/EterPythonLib/StdAfx.h @@ -0,0 +1,17 @@ +#pragma once + +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif +#include "../EterLib/StdAfx.h" +#include "../ScriptLib/StdAfx.h" + +#include "PythonGraphic.h" +#include "PythonWindowManager.h" + +void initgrp(); +void initgrpImage(); +void initgrpText(); +void initgrpThing(); +void initscriptWindow(); +void initwndMgr(); \ No newline at end of file