实现 xui_proxy_t:将 XGE 渲染能力桥接到 XUI 框架,连接图形引擎与 UI 系统。
xui_proxy_t 是 XUI 与底层渲染引擎的桥梁:
• 能力位:声明代理支持的渲染能力(矩形/圆/纹理/裁剪等)
• 回调集:DrawRect/DrawCircle/DrawSurface/ClipBegin/ClipEnd 等
• 桥接:将 XUI 绘制指令翻译为 XGE ShapeEx/SpriteBatch 调用
• Context:创建 XUI 上下文时传入代理,所有控件通过代理渲染
这是整个 XUI 系统运行的基础——没有代理,控件无法绘制。
| 回调 | 说明 |
|---|---|
onDrawRect | 填充/描边矩形 → xgeShapeRectFill/Stroke |
onDrawCircle | 圆形 → xgeShapeCircleFill |
onDrawSurface | 纹理 → xgeDraw/SpriteBatch |
onDrawText | 文本 → xgeTextDraw/GlyphRunDraw |
onClipBegin/End | 裁剪 → xgeClipSet/Clear |
onCreateSurface | 创建纹理 → xgeTextureCreateRGBA |
gcc -O2 -I. -o ch201.exe ch201_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch201.exe
static void ProxyDrawRect(void* pUser,
float fX, float fY, float fW, float fH,
float fRadius, uint32_t iColor)
{
if (fRadius > 0.0f)
xgeShapeRoundRectFill(fX, fY, fW, fH,
fRadius, iColor);
else
xgeShapeRectFill(fX, fY, fW, fH, iColor);
}
static void ProxyClipBegin(void* pUser,
float fX, float fY, float fW, float fH)
{
xgeClipSet(fX, fY, fW, fH);
}
// 组装代理
xui_proxy_t tProxy = { 0 };
tProxy.iCaps = XUI_PROXY_CAP_SURFACE_TARGET |
XUI_PROXY_CAP_SHAPE |
XUI_PROXY_CAP_PATH_FILL |
XUI_PROXY_CAP_PATH_STROKE;
tProxy.drawRectFill = ProxyDrawRect; /* 其余 ops 按 xui_proxy_t 字段填充 */
// ... 其他回调
// 创建 XUI 上下文
xui_context pCtx;
xuiCreate(&pCtx);
xuiSetProxy(pCtx, &tProxy);将以下代码保存为 ch201_main.c,编译后运行即可看到代理架构如何桥接 XGE 渲染与 XUI 控件:
#include "xge.h"
#include "xui.h"
static xui_context g_pCtx;
static int onFrame(void* pUser) {
(void)pUser;
xgeClear(0x1a1a2e);
xui_vec2_t pos;
xgeMouseGet(&pos.x, &pos.y);
xuiInputPointerMove(g_pCtx, pos.x, pos.y);
if (xgeMouseDown(XGE_MOUSE_LEFT))
xuiInputPointerDown(g_pCtx, pos.x, pos.y, 0);
else
xuiInputPointerUp(g_pCtx, pos.x, pos.y, 0);
xuiUpdate(g_pCtx, xgeGetDelta());
xuiLayout(g_pCtx);
xuiRender(g_pCtx, NULL, NULL, 0);
return XGE_OK;
}
int main(void) {
xge_desc_t d = {0};
d.iWidth = 640; d.iHeight = 480;
d.sTitle = "ch201 - Proxy Architecture";
d.iFlags = XGE_INIT_VSYNC;
xgeInit(&d);
xuiCreate(&g_pCtx);
/* 代理桥接:XUI 绘制调用 → XGE 渲染 API */
extern const xui_proxy_t tXgeProxy;
xui_proxy_t tXgeProxy = xuiProxyXge();
xuiSetProxy(g_pCtx, &tXgeProxy);
xuiSetViewportSize(g_pCtx, 640, 480);
xui_widget pRoot;
xuiPanelCreate(g_pCtx, &pRoot, NULL);
xuiWidgetSetRect(pRoot, (xui_rect_t){0, 0, 640, 480});
xui_widget pBtn;
xuiButtonCreate(g_pCtx, &pBtn, NULL);
xuiWidgetAddChild(pRoot, pBtn);
xuiLabelSetText(pBtn, "Rendered via Proxy");
xuiWidgetSetRect(pBtn, (xui_rect_t){220, 200, 200, 48});
xuiWidgetSetRect(pBtn, (xui_rect_t){0, 0, 200, 48});
xui_widget pLbl;
xuiLabelCreate(g_pCtx, &pLbl, NULL);
xuiWidgetAddChild(pRoot, pLbl);
xuiLabelSetText(pLbl, "Proxy: XUI -> XGE rendering");
xuiWidgetSetRect(pLbl, (xui_rect_t){200, 280, 240, 32});
xuiWidgetSetRect(pLbl, (xui_rect_t){0, 0, 240, 32});
xgeRun(onFrame, NULL);
xuiDestroy(g_pCtx);
xgeUnit();
return 0;
}