Chapter 65 · ShapeEx 场景图

子节点查询与遍历

GetCount/GetAt 按索引访问子节点,Traverse 深度优先遍历整棵场景树。

65

API 速查

函数说明
int xgeShapeExSceneGetCount(xge_shape_ex_scene pScene, int* pCount)获取子节点数量
int xgeShapeExSceneGetAt(xge_shape_ex_scene pScene, int iIndex, xge_shape_ex* ppShape)按索引获取 Shape
int xgeShapeExSceneChildGetAt(xge_shape_ex_scene pScene, int iIndex, xge_shape_ex_scene_child_t* pChild)获取子节点(含类型)
int xgeShapeExSceneTraverse(xge_shape_ex_scene pScene, xge_shape_ex_scene_visit_proc onPaint, void* pUser)深度优先遍历

编译本章示例

gcc -O2 -I. -o ch65.exe ch65_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch65.exe

示例:遍历场景树

// 遍历回调:统计所有 Shape 数量
static int s_iCount = 0;
static void OnVisit(xge_shape_ex pShape, void* pUser) {
    s_iCount++;
}

int iTotal;
xgeShapeExSceneGetCount(root, &iTotal);

s_iCount = 0;
xgeShapeExSceneTraverse(root, OnVisit, NULL);
// s_iCount = 场景中所有 Shape 总数

完整代码

将以下代码保存为 ch65_main.c,编译后运行即可看到场景树遍历效果:

#include "xge.h"

static int s_iCount = 0;

static void OnVisit(xge_shape_ex pShape, void* pUser) {
    (void)pUser;
    s_iCount++;
    // 遍历时修改每个 Shape 的透明度
    xgeShapeExOpacity(pShape, 0.5f + 0.5f * (s_iCount % 2));
}

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);

    // 构建场景树
    xge_shape_ex_scene root = NULL;
    xgeShapeExSceneCreate(&root);

    for (int i = 0; i < 5; i++) {
        xge_shape_ex s = NULL;
        xgeShapeExCreate(&s);
        xgeShapeExAppendRect(s, 80+i*130,200, 100,200, 8,8, 1);
        xgeShapeExFillColor(s, 0x4FD8C2FF);
        xgeShapeExSceneAdd(root, s);
        xgeShapeExDestroy(s);
    }

    // 遍历场景树
    s_iCount = 0;
    xgeShapeExSceneTraverse(root, OnVisit, NULL);

    xgeShapeExSceneDraw(root, 0.25f);
    xgeShapeExSceneDestroy(root);
    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch65 - Scene Traverse";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);
    xgeRun(onFrame, NULL);
    xgeUnit();
    return 0;
}

代码讲解

  • SceneTraverse:深度优先遍历所有 Shape,回调中可修改属性。
  • GetCount:返回直接子节点数(Shape + 子 Scene)。
  • ChildGetAt:返回 child_t 结构,包含类型和指针。
  • 遍历中不修改结构:回调中不应 Add/Remove 子节点。

要点与陷阱

  • GetCount:返回直接子节点数(Shape + 子 Scene)。
  • ChildGetAt:返回 child_t 结构,包含类型(Shape/Scene)和指针。
  • Traverse 深度优先:先访问当前节点的 Shape,再递归子 Scene。
  • 遍历中不修改:回调中不应 Add/Remove 子节点。

进阶练习

  1. 用 Traverse 实现"全部隐藏"功能。
  2. 按 ID 查找场景中的特定 Shape。
子节点查询与遍历效果
图:子节点查询与遍历渲染效果