# CycleGUI API 参考

> **颜色字段统一为 `System.Drawing.Color`**（2026-05 改造）：所有公开 API 的 color/colors/_shine/_border_color/team_color/shine_color 字段都是 `Color`，不再有 `uint` 入口。详见 `SKILL.md` `## 颜色契约` 章节。如果你拿到的是引擎 wire-format `uint`（bit0..7=R），用 `Extensions.FromRgba8(uint)` 升回 `Color`；System.Drawing ARGB 布局（`0xAARRGGBB`）则用 `Color.FromArgb(unchecked((int)argb))`。

## PanelBuilder 控件完整签名

维护者核对路径：`D:\MDCS\Source\Core\CycleGUI\CycleGUI\PanelBuilder.Controls.cs`

### 布局

```csharp
void Label(string text)
void Separator()
void SeparatorText(string text)
void SameLine(int spacing = 0)
void CollapsingHeaderStart(string label)  // 必须与 End 配对；不可嵌套
void CollapsingHeaderEnd()
```

> CycleGUI **没有** `BeginChild` / `ChildWindow` / `BeginTabBar` / `BeginTabItem`。容器分区用 `Table(height:)` + `CollapsingHeader`；Tab 切换用 `TabButtons`（见下方"列表与选择"）。

### 按钮与切换

```csharp
// 返回 true 表示被点击
bool Button(string text, string shortcut = "", string hint = "", string distinct = "", bool disabled = false)

// 弹出菜单按钮
void PopMenuButton(string buttonTxt, MenuItem[] menu, Action clickBtn = null)

// 按钮组，返回 true 表示有选择，selecting 为选中索引
bool ButtonGroup(string prompt, string[] buttonText, out int selecting, bool sameLine = false)

// 复选框，返回 true 表示值改变
bool CheckBox(string desc, ref bool chk)

// 开关，返回 true 表示值改变
bool Toggle(string desc, ref bool on)

// 单选按钮，返回 true 表示选择改变
bool RadioButtons(string prompt, string[] items, ref int selected, bool sameLine = false)
```

### 输入

```csharp
// 文本输入。ret 为当前文本，doneInput 为 true 表示按下回车
(string ret, bool doneInput) TextInput(string prompt, string defaultText = "",
    string hintText = "", bool focusOnAppearing = false,
    bool hidePrompt = false, bool alwaysReturnString = false)
```

### 数值控件

```csharp
bool DragFloat(string prompt, ref float valf, float step,
    float min = float.MinValue, float max = float.MaxValue, bool disableCache = false)

bool SliderInt(string prompt, ref int val, int min, int max, bool disableCache = false)

bool SliderFloat(string prompt, ref float val, float min, float max, bool disableCache = false)

bool DragVector2(string prompt, ref Vector2 vector, float step = 0.01f,
    float min = float.MinValue, float max = float.MaxValue)

bool DragMatrix(int m, int n, float[] vals)

bool BezierEditor(string prompt, ref Vector4 controlPoints, ref float startY, ref float endY)
```

### 颜色

```csharp
bool ColorEdit(string label, ref Color color, bool alphaEnabled = true)
```

### 列表与选择

```csharp
// 返回选中索引，-1 无选择
int ListBox(string prompt, string[] items, int height = 5,
    bool persistentSelecting = false, int preselected = -1)

bool DropdownBox(string prompt, string[] items, ref int selected)

// 返回选中标签页索引
int TabButtons(string prompt, string[] items, int forceSelect = -1)
```

`forceSelect`：希望激活的标签页索引（0-based）；`-1` 不强制。API 内建变化检测：仅当该值相对上次变化时才下发 `ImGuiTabItemFlags_SetSelected`，调用方可每帧传入当前目标 Tab，无需自己做 one-shot 门控。用户手动切换 Tab 后，只要 `forceSelect` 不变就不会再被拉回。

### 表格

```csharp
unsafe void Table(string strId, string[] header, int rows,
    Action<Row, int> content, int height = 0,
    bool enableSearch = false, string title = "",
    bool freezeFirstCol = false, int scrollToRow = -1,
    Action<int, bool>? onHeaderSort = null)
```

`height`：可见数据行数；`<=0` 表示不限制高度、显示全部行。`scrollToRow`：希望滚动到可见的数据行索引（0-based）；`-1` 不滚动。API 内建变化检测：仅当该值相对上次变化时才下发 `ImGui::SetScrollHereY`，调用方可每帧传入当前选中行，用户之后可自由滚动列表。传入 `-1` 会复位持久态，便于「取消选中后再选同一行」能重新触发滚动。

Row 对象可用方法：`Label`, `ButtonGroup`, `Checkbox`, `SetColor`, `Image`

### 图表

```csharp
// 实时折线图，返回可选按钮索引
int RealtimePlot(string prompt, float val, bool freeze = false, string[] optionalButtons = null)

// 迷你指标
bool MiniPlot(string name, float value)
bool MiniPlot(string name, string value)
bool MiniPlot<TEnum>(string name, TEnum value) where TEnum : Enum

// 静态折线图
void Plot2D(string prompt, float[] vals, int height = 200)

// ⚠️ 以下为占位/空壳（源码 body 为空，调用无效果，请勿依赖）：
//   Progress, BulletText, Indent / UnIndent, QuestionMark, ToolTip
//   - 需要进度展示：用 RealtimePlot 或 Label 渲染百分比
//   - 需要 tooltip：用 Button(hint:) / Table.Row.Label(hint:) 等已实现的入口
void Progress(float val, float max = 1)        // 空壳，无效果
```

### 图像

```csharp
void Image(string prompt, string rgba, int height = -1)

// 图像列表，返回选中索引
int ImageList(string prompt, (string rgba, string top_title, string bottom_title)[] items,
    bool persistentSelecting = false, int height_px = 100,
    bool hideSeparator = false, int selecting = -1)
```

### 聊天框

```csharp
(bool ret, string sending) ChatBox(string prompt, string[] appending,
    int lines = 18, bool input = true)
```

### 文本展示

```csharp
void SelectableText(string prompt, string content, bool copyButton = true)
```

### 文件对话框

```csharp
bool OpenFile(string prompt, string filters, out string dir, string defaultFn = "")
bool SaveFile(string prompt, string filter, out string dir, string defaultFn = "")
bool SelectFolder(string prompt, out string dir)
```

### Web 与链接

```csharp
void OpenWebview(string name, string url, string hint = "")
void DisplayFileLink(string localfilename, string displayName)
```

### 菜单栏

```csharp
void MenuBar(List<MenuItem> menu)
```

MenuItem 构造：
```csharp
new MenuItem(string label, Action onClick = null, string shortcut = null,
    bool selected = false, bool enabled = true, List<MenuItem> subItems = null)
// label = "-" 表示分隔线
```

### 面板控制

```csharp
bool Closing()  // 返回 true 表示用户点击关闭或终端断开
void DelegateUI()  // 执行通过 Panel.dels 注入的委托 UI
```

---

## Panel 配置方法

维护者核对路径：`D:\MDCS\Source\Core\CycleGUI\CycleGUI\Panel.cs`

```csharp
Panel ShowTitle(string title)        // null 隐藏标题栏
Panel InitSize(int w = 320, int h = 240)
Panel FixSize(int w, int h)          // 固定不可调整大小
Panel AutoSize(bool set)
Panel InitPos(bool pin, int left, int top,
    float myPivotX = 0, float myPivotY = 0,
    float screenPivotX = 0, float screenPivotY = 0)
Panel InitPosRelative(Panel panel, int left, int top,
    float relPivotX = 0, float relPivotY = 0,
    float myPivotX = 0, float myPivotY = 0)
Panel SetDefaultDocking(Docking docking, bool auxiliary = false)
Panel Modal(bool set)
Panel TopMost(bool set)
Panel AsToolbarPanel(int height = 38, ToolbarAnchor anchor = ToolbarAnchor.RightTop)
```

枚举：
- `Panel.Docking`：`Left`, `Top`, `Right`, `Bottom`, `None`, `Full`
- `Panel.ToolbarAnchor`：`RightTop`, `LeftBottom`

实例方法：
```csharp
void Define(CycleGUIHandler handler)
void Repaint(bool dropCurrent = false, int repaintTimeMs = 30)
// dropCurrent=true：丢弃当前帧，立即重绘（编辑后同步 UI 时用）
// repaintTimeMs：持续 Repaint 时的间隔，默认 30ms
// 只在有实时数据的面板持续调用；静态面板不要无条件 Repaint
void BringToFront()
void Exit()
void Freeze() / void UnFreeze()
void SwitchTerminal(Terminal newTerminal)
bool Probe<T>(CycleGUIProber<T> prober, out T val)
void FireAndForget(...)
```

---

## HoverMenu

维护者核对路径：`D:\MDCS\Source\Core\CycleGUI\CycleGUI\API\HoverMenu.cs`

```csharp
HoverMenu GUI.DeclareHoverMenu()

enum HoverMenuPlacement {
    Cursor = 0,
    ObjectScreenAnchor = 1,  // 默认；使用 hovered object 的屏幕投影锚点
    ObjectBounds = 2,        // 预留，v1 不支持
}

class HoverMenu : IDisposable {
    string Name { get; set; }
    string TargetObjectName { get; set; }
    HoverMenuPlacement Placement { get; set; }  // 默认 ObjectScreenAnchor
    int OffsetX { get; set; }                   // 默认 12
    int OffsetY { get; set; }                   // 默认 12
    int CloseDelayMs { get; set; }              // 默认 180
    PanelBuilder.CycleGUIHandler Build { get; set; }
    Terminal Terminal { get; }
    void Start()
    void StartOnTerminal(Terminal terminal)
    void Stop()
    void Dispose()
}
```

实现语义：每个 terminal 一个 manager/native listener，同一时间复用一个 transient panel；C# 侧按 `TargetObjectName` 字典匹配，暂假设一个 object 一个 HoverMenu，重复注册同一 object 会抛异常。native feedback 按 hovered object、object anchor、dragging 去重，不按鼠标移动持续推送。

---

## Workspace Props 完整列表

维护者核对路径：`D:\MDCS\Source\Core\CycleGUI\CycleGUI\API\Workspace.Props.cs`

### 模型

```csharp
// 加载 GLTF 模型类（不可 Remove）
LoadModel { name, detail: ModelDetail }

// ModelDetail 结构
ModelDetail(byte[] gltfBytes) {
    Center = Vector3,
    Rotate = Quaternion,
    Scale = float,
    ColorBias = Vector3,
    ColorScale = float,
    Brightness = float,
    ForceDblFace = bool,
    NormalShading = float,
}

// 更新已加载模型的参数（不重新传 GLTF 数据）
ReloadModel { name, detail: ModelDetail }

// 放置模型实例
PutModelObject { name, clsName, newPosition: Vector3, newQuaternion: Quaternion, baseColor?: Color /* 预留，引擎当前忽略 */ }

// 自定义网格
DefineMesh { clsname, positions: float[] /* 三角面顶点，长度必须是9的倍数 */, color: Color, smooth: bool }
```

### 点云

```csharp
PutPointCloud {
    name: string,
    xyzSzs: Vector4[],      // xyz + size
    colors: Color[],        // 每点一个 System.Drawing.Color
    newPosition: Vector3,
    newQuaternion: Quaternion,
    handleString: string,   // 空=无句柄, 单字符=字符句柄, 多字符=PNG图标
    type: int,              // 0=普通, 1=SLAM地图
}
```

### 线和曲线

```csharp
PutStraightLine {
    name, start: Vector3, end: Vector3,
    propStart: string, propEnd: string,  // 绑定到对象（空则用 start/end）
    arrowType: Painter.ArrowType, width: int, color: Color, dashDensity: int,
}

PutBezierCurve {
    name, start: Vector3, end: Vector3,
    control1: Vector3, control2: Vector3,
    width: int, color: Color,
}

PutVector { name, from: Vector3, dir: Vector3, color: Color, length: int }
```

### 图像与纹理

```csharp
// 静态图像
PutImage { name, rgbaName, displayType, displayH, displayW, /* transform fields */ }

// 可更新 RGBA 纹理
PutRGBA { name, width, height, requestRGBA / rgba }
    .StartStreaming() -> Action<byte[]>  // 返回更新函数
    .Invalidate()
    .UpdateRGBA(byte[])

// SVG
DeclareSVG { name, svgContent: string }
```

### 对象操作

```csharp
// 变换对象位置/旋转
TransformObject { name, pos: Vector3, quat: Quaternion, timeMs: int, coord: Coord }
// Coord: Absolute / Relative

// 变换子对象
TransformSubObject { objectNamePattern, subObjectName/subObjectId, translation, rotation, timeMs }

// 对象锚定（moon 跟随 earth）
SetObjectMoonTo { name: "moon", earth: "earth_obj", pos: Vector3, quat: Quaternion }

// 删除对象（通配符）
WorkspaceProp.RemoveNamePattern(string namePattern)  // 支持 * 和 ?
```

### 文本与图标

```csharp
PutHandleIcon { name, ... }
PutTextAlongLine { name, ... }
SpotText { /* fluent builder */ }
```

### 高斯溅射（Gaussian Splatting）

```csharp
PutGaussianSplats {
    name, splats: GaussianSplat[],
    globalOpacityScale, globalSizeScale, renderMode, ...
}
PutGaussianSplats.FromPLY(path, name, axisPreset)
PutGaussianSplats.FromPointCloud(...)
PutGaussianSplats4D { /* 4D 时序数据 */ }
```

---

## Workspace UI 操作

维护者核对路径：`D:\MDCS\Source\Core\CycleGUI\CycleGUI\API\Workspace.UIOps.cs`

### 相机

```csharp
SetCamera {
    lookAt: Vector3,
    azimuth: float,           // 默认 -PI/2
    altitude: float,          // 默认 PI/2
    distance: float,
    fov: float,
    projectionMode: Perspective / Orthographic,
    displayMode: Normal / VR / EyeTrackedHolography / EyeTrackedLenticular,
    anchor_type: Both / StareOnly / PositionOnly / CopyCamera,
    azimuth_range: Vector2,   // 限制旋转范围
    altitude_range: Vector2,
    pan_range: Vector3,       // 限制平移范围
    mmb_freelook: bool,       // 中键自由视角
}
// 提交方式：.IssueToDefault() / .IssueToAllTerminals() / .IssueToTerminal(t)
```

### 外观

```csharp
SetAppearance {
    useEDL: bool,             // Eye-Dome Lighting
    useSSAO: bool,            // 环境光遮蔽
    useGround: bool,          // 地面
    useBorder: bool,          // 边框
    useBloom: bool,           // 泛光
    drawGroundGrid: bool,     // 地面网格
    drawGuizmo: bool,         // 坐标轴指示器
    useDefaultSky: bool,      // 默认天空盒
    sun_altitude: float,      // 太阳高度
    hover_shine: Color,           // 悬停高亮色
    selected_shine: Color,        // 选中高亮色
    hover_border_color: Color,
    selected_border_color: Color,
    world_border_color: Color,
    voxel_quantize: float,        // 体素量化
    voxel_opacity: float,         // 体素不透明度
    clippingPlanes: (Vector3 center, Vector3 direction)[],  // 最多4个裁剪面
    bring2front_onhovering: bool,
}
```

### 对象外观

```csharp
SetObjectApperance { namePattern, bring_to_front, shine_color: Color, use_border, transparency }
SetModelObjectProperty { namePattern, baseAnimId, nextAnimId, material_variant, team_color: Color,
    base_stopatend, next_stopatend, animate_asap }
SetPropShowHide { namePattern, show: bool }              // sticky pattern (2026-05+)
SetPropApplyCrossSection { namePattern, apply: bool }    // sticky pattern (2026-05+)
```

> **Sticky pattern 语义**（适用于 `SetPropShowHide` / `SetPropApplyCrossSection` /
> `SelectObject.SetObjectSelectable` / `SelectObject.SetObjectSubSelectable`）：每次调用先按
> pattern 扫一遍 `global_name_map` 立即生效，**同时**把 pattern 字符串记入当前 viewport 的
> `workspace_state.*_patterns`。之后 `Workspace.AddProp` 加入的新对象会被引擎在 `indexier::add`
> 自动按 memo 重匹配并设位/隐藏/纳入 selectables。要取消粘性，用**同一 pattern 字符串**反向调
> 一次（`SetPropShowHide{show=true}` / `SetObjectUnselectable(pattern)` 等）。
>
> **Pattern 是 glob**（`*` / `?`），引擎全栈唯一语义。底层是 `libVRender::wildcardMatch`，
> 2026-05 统一化后已删除 `RegexMatcher::match` / `regexMatch` 全套 regex 路径。详见
> SKILL.md 的 `## namePattern 语法 = glob` 章节，那里有完整的 API 列表 + 历史根因 +
> "真要 regex 怎么办" 指引。

### 交互操作

所有交互操作继承 `WorkspaceUIOperation<T>`，通过 `.Start()` 启动，`.End()` 结束，`.feedback` 回调接收结果。

```csharp
// 拾取世界坐标
GetPosition {
    method: PickMode.GridPlane / Holo3D,
    snaps: string[],  // 可吸附对象名
}
// feedback: Action<WorldPosition, op>
// WorldPosition { mouse_pos, snapping_object, object_pos, sub_id }

// 拖拽跟随
FollowMouse {
    method: FollowingMethod.LineOnGrid / RectOnGrid / PointOnGrid / CircleOnGrid / Line3D / ...,
    follower_objects: string[],
    start_snapping_objects: string[],
    end_snapping_objects: string[],
    realtime: bool,
}
// feedback: Action<FollowFeedback, op>

// 对象选择
SelectObject {
    fineSelectOnPointClouds: bool,
    fineSelectOnHandle: bool,
}
// feedback: Action<(string name, BitArray selector, string firstSub)[], op>
// feedback 返回的是“当前完整选中集”（不是 delta），由引擎处理 Shift+加选 / Alt+减选 / 框选
// 运行时切换模式：selectOp.SetSelectionMode(SelectionMode.Rectangle, paintRadius)
// SelectionMode: Click / Rectangle / Paint
//
// SetObjectSelectable(pattern) / SetObjectSubSelectable(pattern)
//   - pattern 是 glob："*" = 任意子串、"?" = 任意单字符；不是 ECMAScript 正则
//   - 立即对已存在对象按 glob 设可选位
//   - 并把 pattern 记入 workspace_state.selectable_patterns（sticky，2026-05 起）
//   - 之后 AddProp 加入的新对象会被引擎自动匹配 + 设位（indexier::add hook）
//   - 取消 sticky：用同一 pattern 调 SetObjectUnselectable / SetObjectSubUnselectable

// Guizmo 操作（移动/旋转 gizmo）
GuizmoAction {
    dof: GuizmoDof, // 默认 TranslateXYZ
    realtimeResult: bool,
}
// GuizmoDof: None, TranslateX/Y/Z, RotateX/Y/Z, Roll, Pitch, Yaw,
//            TranslateXYZ, RotateXYZ, PlanarXY, PlanarXYYaw, All
// feedback: Action<(string name, Vector3 pos, Quaternion rot)[], op>

// 原始鼠标事件
RegisterMouseAction {
    listen_MouseDown, listen_MouseUp, listen_MouseMove, listen_Wheel: bool,
}
// feedback: Action<MouseAction, op>
// MouseAction { mouseX, mouseY, workspaceX, workspaceY, mouseLB/RB/MB, wheelDelta }
```

### 工作区行为

```csharp
SetWorkspaceBehaviour {
    operation_trigger: Mouse.MouseLB,    // 操作触发键
    workspace_pan: Mouse.MouseRB,        // 平移键
    workspace_orbit: Mouse.MouseMB,      // 旋转键
}
// Mouse: MouseLB, MouseMB, MouseRB, CtrlMouseLB, CtrlMouseMB, CtrlMouseRB
```

### 查询操作

```csharp
// 查询视口相机状态
new QueryViewportState { callback = state => {
    // state.CameraPosition, state.LookAt, state.Up
}}.IssueToDefault();

// 捕获渲染画面
new CaptureRenderedViewport { callback = img => {
    // img.bytes (RGB), img.width, img.height
}}.IssueToDefault();

// 查询图形信息
new QueryGraphics { callback = state => {
    // state.MonitorCount, state.Monitors[], state.FPS
}}.IssueToDefault();

// 聚焦到对象
new FrameToFit { name = "objectName", margin = 1.1f }.IssueToDefault();

// 全屏
new SetFullScreen { fullscreen = true, screen_id = -1 }.IssueToDefault();

// 自定义网格
new SetOperatingGridAppearance {
    show = true, pivot = Vector3.Zero,
    unitX = Vector3.UnitX, unitY = Vector3.UnitY,
}.IssueToDefault();

// ImGui 样式
new SetImGUIStyle {
    windowBg = 0xFF171717, button = 0xFF3D3835,
    windowRounding = 6f, frameRounding = 6f,
}.IssueToDefault();

// 主窗口菜单栏
new SetMainMenuBar {
    menu = new List<MenuItem> { ... }, show = true
}.IssueToDefault();

// Viewport 专属菜单栏
var viewport = GUI.PromptWorkspaceViewport();
new SetWorkspaceMenuBar {
    viewport = viewport,
    menu = new List<MenuItem> { ... }, show = true
}.Issue();

// 面板持久菜单栏（从 handler 外部设置，自动注入到每次重绘）
new SetPanelMenuBar {
    panel = myPanel,
    menu = new List<MenuItem> { ... }
}.Issue();
// 清除：new SetPanelMenuBar { panel = myPanel, menu = null }.Issue();
```

---

## Painter 完整 API

维护者核对路径：`D:\MDCS\Source\Core\CycleGUI\CycleGUI\Painter.cs`

```csharp
// 获取/创建命名 Painter（单例）
static Painter GetPainter(string name)

// 清除当前帧数据（双缓冲交换）
void Clear()

// 绘制点（单位：米）
void DrawDot(Color color, Vector3 xyz, float size = 1f)

// 绘制线段
void DrawLine(Color color, Vector3 start, Vector3 end,
    float width = 1f, ArrowType arrow = ArrowType.None, int dashScale = 0)
// ArrowType: None, Start, End

// 绘制方向向量（像素长度）
void DrawVector(Vector3 from, Vector3 dir, Color color,
    float width = 1f, int pixels = 10)

// 绘制 3D 文本
void DrawText(Color color, Vector3 tCenter, string s)

// 绘制区域体素
void DrawRegion3D(Color color, Vector3 center)

// 绘制填充多边形（2D 点 + 3D 变换）
void DrawPolygonFilled(Vector2[] points2D, Vector3 trans, Quaternion quat,
    Color borderColor, Color fillColor, float thickness = 0f)
// thickness=0: 平面多边形; >0: 拉伸立体

// 终端隔离
Painter.terminal = specificTerminal;  // null 则广播到所有终端
```

---

## LeastServer（HTTP/WebSocket 服务）

全局类（无命名空间），维护者核对路径：`D:\MDCS\Source\Core\CycleGUI\CycleGUI\Terminals\LeastServer.cs`

```csharp
static void Listener(int port)                              // 阻塞式启动监听
static void AddGetHandler(string path, Func<string> handler)
static void AddPostTextHandler(string path, Func<string, string> handler)
static void AddPostByteHandler(string path, Func<byte[], byte[]> handler)
static void AddServingFiles(string urlPrefix, string localPath)
static void AddServingResources(string urlPrefix, Assembly, string ns)
static void AddSpecialTreat(string path, Action<...> handler)  // WebSocket 升级
```

---

## Viewport（面板内嵌 3D 视口）

```csharp
// 创建内嵌 Workspace 视口面板
var viewport = GUI.PromptWorkspaceViewport();
```

`Viewport` 继承 `Panel`，拥有独立的 `ViewportSubTerminal`，Workspace 状态与主终端隔离。

