UI编辑器完善多树创建与文档契约

统一识别和合并结果的 createTree 流程

按选中节点所属树驱动 Inspector 编辑

补充多树预览与树级偏移权威文档
This commit is contained in:
2026-09-14 18:11:10 +08:00
parent f68ffcfecd
commit f679cfa179
3 changed files with 22 additions and 7 deletions
@@ -3,7 +3,6 @@ use crate::config::load_game_creator_app_config;
use crate::ui_editor::commands::utils::{
parse_limited_llm_tool_arguments, request_ui_editor_llm, strict_json_schema,
};
use crate::ui_editor::layout::offset::NodeOffset;
use crate::ui_editor::state::{State, UITree};
use platform_llm::{LlmFunctionTool, LlmMessage, LlmRunRequest, LlmToolChoice};
use serde::{Deserialize, Serialize};
@@ -1028,9 +1028,13 @@ export function useUiEditorSession(
state: snapshot,
});
const nextState = applyRecognitionResult(snapshot, result);
nextState.ui_trees = nextState.ui_trees.map((tree) =>
createTree(nextState, tree.src_ui_design, tree.root),
);
const recognizedTrees = nextState.ui_trees;
nextState.ui_trees = [];
for (const tree of recognizedTrees) {
nextState.ui_trees.push(
createTree(nextState, tree.src_ui_design, tree.root),
);
}
editor.replaceState(nextState);
setHasRecognized(true);
setSelectedNodeId(null);
@@ -1066,9 +1070,13 @@ export function useUiEditorSession(
await editor.runWithStateLocked(async (snapshot) => {
const result = await invoke<MergeDTO>('merge_ui', { state: snapshot });
const nextState = applyMergeResult(snapshot, result);
nextState.ui_trees = nextState.ui_trees.map((tree) =>
createTree(nextState, tree.src_ui_design, tree.root),
);
const mergedTrees = nextState.ui_trees;
nextState.ui_trees = [];
for (const tree of mergedTrees) {
nextState.ui_trees.push(
createTree(nextState, tree.src_ui_design, tree.root),
);
}
editor.replaceState(nextState);
setSelectedNodeId(null);
setMergeStatus('已生成合并后的单棵界面树。');
@@ -19,6 +19,14 @@
保存与代码生成共享同一份持久化 State/revision。会话层在保存或生成进行期间互斥拦截,且代码生成必须基于已加载的持久化 revision;视图层的保存按钮和“保存并返回”按钮同步遵守该互斥状态。
## 2026-09-14 多树预览与树级偏移
UI 编辑器预览同时渲染 State 中全部 `ui_trees`。每棵树的 `root.offset` 包含 `min` / `max`;当前仅读取 `min` 作为树 wrapper 的左上角,`max``min + 对应界面图 pixel_size / pixels_per_unit` 派生。所有新树必须经 `createTree` 创建:首棵树位置为 `[0, 0]`,后续树按现有树实际右边界最大值加固定 padding 横向排列,并与现有树最小 top 对齐。删除或排序不重排已有树。
预览中原图与树 root 共享同一空间,root 空白区域可拖动整树,拖动结束一次性写回 root offset 并进入撤销/重做;root 不提供 resize,子节点沿用既有手势。预览选中节点不改变左侧图片面板的 `activeImageId`,Inspector 通过节点所属树反查编辑目标。只有首次进入预览和用户手动点击“适配画布”使用全部树联合边界进行 fit。
原有 render mode 已拆为三个会话级临时开关:`showFrame=true``showOriginImage=true``showComponent=false`。普通节点框线/名称受 `showFrame` 控制,选中节点强调始终保留;原图和组件显示互不耦合。
`UiDesignStateStore``generateCode(assetId)` 是必需能力,返回成功结果时不得为 nullable;所有注入的 adapter 与测试替身都必须实现该方法。
资源切换时,会话必须清理上一资源的保存/生成错误和生成中状态;普通保存开始时也清理代码生成错误。生成请求若因加载、锁定或 revision 等前置条件被拦截,必须向视图提供可见错误,而不是静默返回。