Chapter 63 · ShapeEx 场景图

场景对象生命周期

Scene 是 Shape 的容器节点,支持树形层级、引用计数、深拷贝和批量管理。

63

概念

  • Scene:可包含 Shape 和子 Scene 的容器,形成树形场景图。
  • 引用计数:与 ShapeEx 相同的 AddRef/Destroy 模型。
  • Clone:深拷贝整个子树(包含所有子节点)。
  • Clear:移除所有子节点但保留 Scene 自身。

API 速查

函数说明
int xgeShapeExSceneCreate(xge_shape_ex_scene* ppScene)创建场景
int xgeShapeExSceneAddRef(xge_shape_ex_scene pScene)增加引用
int xgeShapeExSceneRefCountGet(xge_shape_ex_scene pScene, int* pRefCount)获取引用计数
int xgeShapeExSceneClone(xge_shape_ex_scene pScene, xge_shape_ex_scene* ppClone)深拷贝
void xgeShapeExSceneDestroy(xge_shape_ex_scene pScene)释放引用
int xgeShapeExSceneClear(xge_shape_ex_scene pScene)清除所有子节点
int xgeShapeExSceneId(xge_shape_ex_scene pScene, uint32_t iId)设置 ID
int xgeShapeExSceneParentGet(xge_shape_ex_scene pScene, xge_shape_ex_scene* ppParent)获取父节点

编译本章示例

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

示例:创建与销毁

xge_shape_ex_scene scene = NULL;
xgeShapeExSceneCreate(&scene);
xgeShapeExSceneId(scene, 1001);

// 添加子 Shape
xge_shape_ex shape = NULL;
xgeShapeExCreate(&shape);
xgeShapeExAppendCircle(shape, 0,0, 50,50, 1);
xgeShapeExFillColor(shape, 0x4FD8C2FF);
xgeShapeExSceneAdd(scene, shape);
xgeShapeExDestroy(shape);  // Scene 已 AddRef

// 深拷贝
xge_shape_ex_scene clone = NULL;
xgeShapeExSceneClone(scene, &clone);

// 销毁
xgeShapeExSceneDestroy(clone);
xgeShapeExSceneDestroy(scene);

完整代码

将以下代码保存为 ch63_main.c,编译后运行即可看到 Scene 创建、添加、克隆、销毁的完整流程:

#include "xge.h"

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

    // 创建 Scene
    xge_shape_ex_scene scene = NULL;
    xgeShapeExSceneCreate(&scene);
    xgeShapeExSceneId(scene, 1001);

    // 添加子 Shape
    xge_shape_ex s1 = NULL;
    xgeShapeExCreate(&s1);
    xgeShapeExAppendCircle(s1, 300, 300, 80, 80, 1);
    xgeShapeExFillColor(s1, 0x4FD8C2FF);
    xgeShapeExSceneAdd(scene, s1);
    xgeShapeExDestroy(s1);

    xge_shape_ex s2 = NULL;
    xgeShapeExCreate(&s2);
    xgeShapeExAppendRect(s2, 420,220, 160,160, 12,12, 1);
    xgeShapeExFillColor(s2, 0xFFB454FF);
    xgeShapeExSceneAdd(scene, s2);
    xgeShapeExDestroy(s2);

    // 绘制整棵场景树
    xgeShapeExSceneDraw(scene, 0.25f);
    xgeShapeExSceneDestroy(scene);
    return XGE_OK;
}

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

代码讲解

  • SceneCreate:创建场景节点,引用计数初始为 1。
  • SceneAdd:将 Shape 添加到 Scene,内部 AddRef,本地应 Destroy。
  • SceneDraw:一次调用绘制整棵子树,按添加顺序绘制。
  • SceneDestroy:Release 引用,计数归零时递归释放所有子节点。

要点与陷阱

  • SceneAdd 会 AddRef:添加后应 Destroy 本地引用。
  • Destroy 递归:销毁 Scene 会 Release 所有子节点。
  • Clear vs Destroy:Clear 只移除子节点,Scene 本身仍可用。
  • ParentGet:根节点返回 NULL。

进阶练习

  1. 构建三层场景树:root → group → shapes,验证 Destroy 递归释放。
  2. 用 Clone 实现"复制图层"功能。
场景对象生命周期效果
图:场景对象生命周期渲染效果