统一 UI 编辑器文档资产类型
新增 ui-design-doc 与 application/json 常量 创建、桥接、工作流和持久化统一使用严格资产类型
This commit is contained in:
@@ -2144,7 +2144,10 @@ pub(crate) fn create_ui_design_resource(
|
||||
let next_index = manifest
|
||||
.assets
|
||||
.iter()
|
||||
.filter(|asset| asset.kind == "UI")
|
||||
.filter(|asset| {
|
||||
asset.kind == crate::ui_editor::persistence::UI_DESIGN_DOC_ASSET_KIND
|
||||
&& asset.media_type == crate::ui_editor::persistence::UI_DESIGN_DOC_MEDIA_TYPE
|
||||
})
|
||||
.count()
|
||||
+ 1;
|
||||
let resource_name = format!("UI 设计 {next_index}");
|
||||
@@ -2178,8 +2181,8 @@ pub(crate) fn create_ui_design_resource(
|
||||
let asset = match register_local_asset_at(
|
||||
root,
|
||||
&relative_path,
|
||||
"UI",
|
||||
"application/json",
|
||||
crate::ui_editor::persistence::UI_DESIGN_DOC_ASSET_KIND,
|
||||
crate::ui_editor::persistence::UI_DESIGN_DOC_MEDIA_TYPE,
|
||||
"generated",
|
||||
GameCreationAppAssetSource {
|
||||
kind: GameCreationAppAssetSourceKind::Generated,
|
||||
|
||||
@@ -19,6 +19,8 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use typed_floats::tf32::StrictlyPositiveFinite;
|
||||
|
||||
const UI_DESIGN_STATE_SCHEMA_VERSION: &str = "game-creator-ui-design-state.v1";
|
||||
pub(crate) const UI_DESIGN_DOC_ASSET_KIND: &str = "ui-design-doc";
|
||||
pub(crate) const UI_DESIGN_DOC_MEDIA_TYPE: &str = "application/json";
|
||||
const UI_DESIGN_STATE_MAX_BYTES: usize = 2 * 1024 * 1024;
|
||||
const UI_DESIGN_CODE_MAX_BYTES: usize = UI_DESIGN_STATE_MAX_BYTES * 8;
|
||||
const UI_DESIGN_STATE_MAX_IMAGES: usize = 4;
|
||||
@@ -321,7 +323,7 @@ fn ui_design_asset(
|
||||
.into_iter()
|
||||
.find(|asset| asset.id == asset_id)
|
||||
.ok_or_else(|| "UI 设计资源不存在".to_string())?;
|
||||
if asset.kind != "UI" || asset.media_type != "application/json" {
|
||||
if asset.kind != UI_DESIGN_DOC_ASSET_KIND || asset.media_type != UI_DESIGN_DOC_MEDIA_TYPE {
|
||||
return Err("目标资源不是 UI 设计 JSON 资产".to_string());
|
||||
}
|
||||
normalize_relative_path(&asset.local_path)?;
|
||||
@@ -815,8 +817,8 @@ mod tests {
|
||||
let asset = register_local_asset_at(
|
||||
directory.path(),
|
||||
relative_path,
|
||||
"UI",
|
||||
"application/json",
|
||||
UI_DESIGN_DOC_ASSET_KIND,
|
||||
UI_DESIGN_DOC_MEDIA_TYPE,
|
||||
"test",
|
||||
GameCreationAppAssetSource {
|
||||
kind: GameCreationAppAssetSourceKind::Generated,
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use crate::ui_editor::persistence::initialize_ui_design_state_with_source_image_at;
|
||||
use crate::ui_editor::persistence::{
|
||||
initialize_ui_design_state_with_source_image_at, UI_DESIGN_DOC_ASSET_KIND,
|
||||
UI_DESIGN_DOC_MEDIA_TYPE,
|
||||
};
|
||||
use crate::{
|
||||
acquire_project_write_lock, advance_agent_runtime_project_revision_locked,
|
||||
enforce_project_permission_policy, read_existing_manifest_for_project,
|
||||
@@ -89,8 +92,8 @@ pub(crate) fn ensure_ui_design_resource_for_prototype(
|
||||
}
|
||||
|
||||
if let Some(asset) = manifest.assets.iter().find(|asset| {
|
||||
asset.kind == "UI"
|
||||
&& asset.media_type == "application/json"
|
||||
asset.kind == UI_DESIGN_DOC_ASSET_KIND
|
||||
&& asset.media_type == UI_DESIGN_DOC_MEDIA_TYPE
|
||||
&& asset.source.reference_resource_ids.iter().any(|reference| {
|
||||
source_reference_ids
|
||||
.iter()
|
||||
@@ -118,8 +121,8 @@ pub(crate) fn ensure_ui_design_resource_for_prototype(
|
||||
let asset = match register_local_asset_at(
|
||||
root,
|
||||
&relative_path,
|
||||
"UI",
|
||||
"application/json",
|
||||
UI_DESIGN_DOC_ASSET_KIND,
|
||||
UI_DESIGN_DOC_MEDIA_TYPE,
|
||||
"generated",
|
||||
GameCreationAppAssetSource {
|
||||
kind: GameCreationAppAssetSourceKind::Generated,
|
||||
@@ -193,7 +196,9 @@ fn next_ui_design_path(
|
||||
let mut index = manifest
|
||||
.assets
|
||||
.iter()
|
||||
.filter(|asset| asset.kind == "UI")
|
||||
.filter(|asset| {
|
||||
asset.kind == UI_DESIGN_DOC_ASSET_KIND && asset.media_type == UI_DESIGN_DOC_MEDIA_TYPE
|
||||
})
|
||||
.count()
|
||||
+ 1;
|
||||
loop {
|
||||
@@ -281,11 +286,9 @@ mod tests {
|
||||
};
|
||||
let first = ensure_ui_design_resource_for_prototype(input.clone()).expect("bridge");
|
||||
assert!(first.created);
|
||||
assert_eq!(first.asset.kind, "UI");
|
||||
assert_eq!(first.asset.kind, UI_DESIGN_DOC_ASSET_KIND);
|
||||
// 写侧 → 分类的端到端断言:这条路径走的是与
|
||||
// `workflow.rs` / `persistence.rs` 完全相同的 `register_local_asset_at(..., "UI", ...)`。
|
||||
// 别名表漏掉大写 `UI` 时,这里会落 unclassified(真机 8 条 UI 资产的表现),
|
||||
// 且派生值本身就是 unclassified,读时自愈也救不回来。
|
||||
// 写侧与 persistence/workflow 共用 UI 文档 kind/media 常量。
|
||||
assert_eq!(
|
||||
first.asset.category,
|
||||
GameCreationAppAssetCategory::UiInteraction
|
||||
@@ -322,7 +325,10 @@ mod tests {
|
||||
.manifest
|
||||
.assets
|
||||
.iter()
|
||||
.filter(|asset| asset.kind == "UI")
|
||||
.filter(|asset| {
|
||||
asset.kind == UI_DESIGN_DOC_ASSET_KIND
|
||||
&& asset.media_type == UI_DESIGN_DOC_MEDIA_TYPE
|
||||
})
|
||||
.count(),
|
||||
1
|
||||
);
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::ui_editor::layout::node::{Node, StageStatus};
|
||||
use crate::ui_editor::persistence::{
|
||||
initialize_ui_design_state_at, load_ui_design_state_at, save_ui_design_state_at,
|
||||
LoadUiDesignStateInput, SaveUiDesignStateInput, SaveUiDesignStateResult,
|
||||
UI_DESIGN_DOC_ASSET_KIND, UI_DESIGN_DOC_MEDIA_TYPE,
|
||||
};
|
||||
use crate::ui_editor::resource::font::FontAsset;
|
||||
use crate::ui_editor::resource::sprite::{SpriteAsset, SpriteAssetMetadata, SpriteBorder};
|
||||
@@ -683,8 +684,8 @@ fn find_page_ui_resource(
|
||||
let Some(asset) = matches.into_iter().next() else {
|
||||
return Ok(None);
|
||||
};
|
||||
if asset.kind != "UI"
|
||||
|| asset.media_type != "application/json"
|
||||
if asset.kind != UI_DESIGN_DOC_ASSET_KIND
|
||||
|| asset.media_type != UI_DESIGN_DOC_MEDIA_TYPE
|
||||
|| asset.local_path != workflow_relative_path(source, &page.page_id)
|
||||
{
|
||||
return Err(format!("页面 {} 的 UI workflow 资源身份冲突", page.page_id));
|
||||
@@ -748,8 +749,8 @@ fn ensure_page_ui_resource(
|
||||
let registered = register_local_asset_at(
|
||||
root,
|
||||
&relative_path,
|
||||
"UI",
|
||||
"application/json",
|
||||
UI_DESIGN_DOC_ASSET_KIND,
|
||||
UI_DESIGN_DOC_MEDIA_TYPE,
|
||||
"ui-workflow",
|
||||
GameCreationAppAssetSource {
|
||||
kind: GameCreationAppAssetSourceKind::Generated,
|
||||
@@ -1179,7 +1180,7 @@ fn update_page_manifest_stage(root: &Path, asset_id: &str, stage: &str) -> Resul
|
||||
.iter_mut()
|
||||
.find(|asset| asset.id == asset_id)
|
||||
.ok_or_else(|| format!("UI workflow 资源 {} 未登记", asset_id))?;
|
||||
if asset.kind != "UI" || asset.media_type != "application/json" {
|
||||
if asset.kind != UI_DESIGN_DOC_ASSET_KIND || asset.media_type != UI_DESIGN_DOC_MEDIA_TYPE {
|
||||
return Err(format!("UI workflow 资源 {} 类型不匹配", asset_id));
|
||||
}
|
||||
let next_kind = format!("ui-workflow.{stage}");
|
||||
|
||||
Reference in New Issue
Block a user