---
name: cyclegui-app-development
description: 构建或修改基于 CycleGUI 框架的 .NET 桌面/Web 应用。CycleGUI 提供 ImGui 式立即模式 UI 面板和 3D Workspace 渲染能力。用于用户提到 CycleGUI、RefCycleGUI.dll、Costura.Fody、SimpleLite、PanelBuilder、GUI.PromptPanel、GUI.DeclarePanel、Workspace、Painter、LocalTerminal、LocalTerminal.Start、MinimizeToTray、HideConsoleOnStart、libVRender、WebTerminal、TCPTerminal、3D 场景、立即模式 UI、LoadModel、PutPointCloud，或需要新建/修改 CycleGUI 应用、示例、面板、工具栏、HoverMenu、菜单栏、视口、对象选择、坐标拾取、调试绘制时。
---

# CycleGUI 应用开发

本 skill 是 CycleGUI 应用开发的启动卡片。普通任务应能在没有 CycleGUI 源码的情况下完成：先用本文搭出正确结构；需要完整签名、长示例或专题规则时，再按主题加载 reference。只有维护 CycleGUI 框架本体、修复底层 bug、或本地仓库已存在且需要核对变更时，才读取源码。

## 按需读取

- 项目引用、宿主/插件边界、启动流程：`references/project-setup-and-packaging.md`
- 面板、工具栏、HoverMenu、控件、菜单栏：`references/panels-controls-menus.md`
- Workspace 模型、点云、相机、视口、Painter：`references/workspace-scene-and-painter.md`
- Workspace 对象选择、坐标拾取、async 操作陷阱：`references/workspace-interaction.md`
- WebTerminal、LocalTerminal、LeastServer：`references/terminals-and-web.md`
- 完整 API 签名：`references/api-signatures.md`
- 完整示例：`references/examples.md`

## 引用策略

先判断项目类型：

1. **同解决方案示例**：例如 `LearnCycleGUI`，可以 `ProjectReference` 到 `CycleGUI\CycleGUI.csproj`。
2. **宿主/调度程序**：例如 `SimpleLite`，引用真实 `CycleGUI.dll`，并用 `Costura.Fody` 把托管程序集包进宿主 Assembly。
3. **插件或二次开发项目**：默认引用 `RefCycleGUI.dll`，不要引用真实 `CycleGUI.dll`。真实 CycleGUI 实现由宿主提供，用于保护 CycleGUI 代码资产并隔离二开项目。

最容易写错的是插件/二开项目：

```xml
<Reference Include="CycleGUI">
  <HintPath>$(CGUILibDir)RefCycleGUI.dll</HintPath>
  <Private>false</Private>
</Reference>
```

不要指导插件二开项目显式部署或打包真实 `CycleGUI.dll`。

## 最小骨架

常用 using：

```csharp
using CycleGUI;
using CycleGUI.API;
using CycleGUI.Terminals;
using System.Drawing;
using System.Numerics;
```

启动本地窗口：

```csharp
Terminal.RegisterRemotePanel(CreateMainPanel);
LocalTerminal.SetTitle("MyApp");
LocalTerminal.Start();
GUI.PromptPanel(CreateMainPanel(GUI.defaultTerminal));
```

最小面板：

```csharp
PanelBuilder.CycleGUIHandler CreateMainPanel(Terminal terminal)
{
    return pb =>
    {
        pb.Panel.ShowTitle("Main").InitSize(400, 300);
        pb.Label("Ready");
        if (pb.Button("Run")) { }
        if (pb.Closing()) pb.Panel.Exit();
    };
}
```

需要保留 panel 引用、控制 dock/toolbar/单实例时，用 `GUI.DeclarePanel().Define(...)`；细节见 `references/panels-controls-menus.md`。

## 常见任务路由

- 新建普通桌面/Web 应用：用本文骨架；需要完整 csproj 和 WebTerminal 细节时读 `references/project-setup-and-packaging.md`、`references/terminals-and-web.md`。
- 做插件二开：先确认引用 `RefCycleGUI.dll`；不要把真实 `CycleGUI.dll` 带进插件。
- 做表单、表格、toolbar、HoverMenu、菜单栏：读 `references/panels-controls-menus.md`。
- 加载模型、点云、相机、Painter 调试绘制：读 `references/workspace-scene-and-painter.md`。
- 做对象选择、坐标拾取、拖拽/放置或 async 交互：读 `references/workspace-interaction.md`。
- 不确定 API 签名：读 `references/api-signatures.md`，不要凭 ImGui 习惯猜 CycleGUI 方法。

## 必须记住

- 普通应用开发不要求用户或下游 agent 读取 CycleGUI 源码。
- CycleGUI 公开颜色字段使用 `System.Drawing.Color`；不要把 ARGB `uint` 直接塞给颜色字段。
- 所有 `namePattern` 是 glob，不是 regex：`"UISite-*"` 正确，`"UISite-.*"` 错。
- `InitPosRelative` 的参数是 `left` / `top`；不要写不存在的 `offsetX` / `offsetY`。
- CycleGUI 没有 `BeginChild` / `ChildWindow` / `BeginTabBar` / `BeginTabItem`；分区用 `Table(height:)`、`CollapsingHeader`，标签页用 `TabButtons`（支持 `forceSelect` 程序化切 Tab；`Table` 支持 `scrollToRow` 程序化滚动到行，变化检测在 API 内部）。
- 不要依赖空壳控件：`Progress`、`BulletText`、`Indent` / `UnIndent`、`QuestionMark`、`ToolTip`。
- 控件 id 由标签经 **ASCII** 哈希得到（中文、全角符号等非 ASCII 字符全部折叠成 `?`）：同一面板内两个「ASCII 折叠后相同」的标签会抛 `Duplicated id`——最典型是**同字数的纯中文**标签（如 `筛选条件` 撞 `设为类型`），或仅中文字符不同、ASCII 部分相同的两个标签（如 `起点筛选（站点ID或名称）` 撞 `终点筛选（站点ID或名称）`）。修法：标签加 `###唯一ASCII后缀`（显示不变，`###` 会重置哈希），`Button` 用唯一 `distinct:`，或加 `1. `/`2. ` 等数字前缀；循环内渲染带状态控件须给每项拼唯一 id（如 `$"启用###en-{item.Id}"`）。详见 `references/panels-controls-menus.md`。
- 立即模式：面板默认**不会**每帧重绘；只在 `pb.Panel.Repaint()` 被调用时重新执行 handler。静态面板（Properties / Actions 等）不要无条件 Repaint；仅实时数据区（Status、MiniPlot、后台线程推送等）才持续 Repaint。延迟回调或跨线程改数据后须显式 Repaint。详见 `references/panels-controls-menus.md`。
- 画布/Workspace 里的业务对象需要点击或选择时，默认用原生 `SelectObject` + 可选 Workspace 对象，不要用 `GetPosition` 手写命中测试。
- `SelectObject` 和 `GetPosition` 是互斥交互；进入拾取前结束选择 op，结束后重新启动选择 op。
- 修改 CycleGUI C# API、维护框架本体、排查 libVRender/协议问题、或发现 reference 缺失时，才核对源码并同步更新 references。

