From a2ef00eafd5b4629144746c6124365f7dd0a98f3 Mon Sep 17 00:00:00 2001 From: changdunwei Date: Fri, 26 Jun 2026 16:48:36 +0800 Subject: [PATCH] fix(assets): align property schema with config schema --- .../__snapshots__/dts-snapshot.test.ts.snap | 65 ++--- src/api/assets/assets.ts | 2 +- src/api/assets/schema.ts | 39 ++- .../@types/protected/asset-handler.d.ts | 5 +- src/core/assets/@types/public.d.ts | 27 +- .../assets/asset-handler/assets/auto-atlas.ts | 102 ++++---- src/core/assets/asset-handler/assets/fbx.ts | 48 ++-- src/core/assets/asset-handler/assets/gltf.ts | 226 ++++++++-------- .../asset-handler/assets/image/index.ts | 13 + .../asset-handler/assets/sprite-frame.ts | 85 +++--- .../asset-handler/assets/texture-base.ts | 77 ++---- .../assets/asset-handler/assets/texture.ts | 19 +- src/core/assets/manager/asset-handler.ts | 8 +- src/core/assets/property-schema.ts | 245 +----------------- src/core/assets/test/property-schema.test.ts | 222 ++++------------ .../assets-query-property-schema-api.test.ts | 6 +- tests/lib/assets-api.test.ts | 6 +- 17 files changed, 382 insertions(+), 813 deletions(-) diff --git a/packages/cocos-cli-types/__tests__/__snapshots__/dts-snapshot.test.ts.snap b/packages/cocos-cli-types/__tests__/__snapshots__/dts-snapshot.test.ts.snap index 2825232b8..a97f8ed35 100644 --- a/packages/cocos-cli-types/__tests__/__snapshots__/dts-snapshot.test.ts.snap +++ b/packages/cocos-cli-types/__tests__/__snapshots__/dts-snapshot.test.ts.snap @@ -118,28 +118,7 @@ export declare interface AssetOperationOption { overwrite?: boolean; rename?: boolean; } -export declare interface AssetPropertySchema { - label: string; - description?: string; - type: AssetPropertySchemaType; - default?: unknown; - options?: AssetPropertySchemaOption[]; - assetType?: string; - min?: number; - max?: number; - step?: number; - readOnly?: boolean; - order?: number; - properties?: Record; - items?: AssetPropertySchema | AssetPropertySchema[]; - raw?: unknown; -} -export declare type AssetPropertySchemaMap = Record; -export declare interface AssetPropertySchemaOption { - label: string; - value: string | number | boolean; -} -export declare type AssetPropertySchemaType = 'string' | 'number' | 'boolean' | 'enum' | 'asset' | 'array' | 'object'; +export declare type AssetPropertySchemaMap = Record; export declare interface AssetUserDataMap { 'animation-clip': AnimationClipAssetUserData; 'auto-atlas': AutoAtlasAssetUserData; @@ -460,6 +439,22 @@ export declare interface IAssetWriteFileOptions extends IAssetOperationOptionsBa create?: boolean; overwrite?: boolean; } +export declare interface ICocosConfigurationPropertySchema { + type: 'string' | 'number' | 'boolean' | 'object' | 'array'; + default?: unknown; + title?: string; + description?: string; + enum?: Array; + enumDescriptions?: string[]; + minimum?: number; + maximum?: number; + step?: number; + order?: number; + properties?: Record; + items?: ICocosConfigurationPropertySchema | ICocosConfigurationPropertySchema[]; + additionalProperties?: boolean | ICocosConfigurationPropertySchema; + required?: string[]; +} export declare interface ICreateMenuInfo { label: string; name: string; @@ -7011,28 +7006,7 @@ export declare interface AssetOperationOption { overwrite?: boolean; rename?: boolean; } -export declare interface AssetPropertySchema { - label: string; - description?: string; - type: AssetPropertySchemaType; - default?: unknown; - options?: AssetPropertySchemaOption[]; - assetType?: string; - min?: number; - max?: number; - step?: number; - readOnly?: boolean; - order?: number; - properties?: Record; - items?: AssetPropertySchema | AssetPropertySchema[]; - raw?: unknown; -} -export declare type AssetPropertySchemaMap = Record; -export declare interface AssetPropertySchemaOption { - label: string; - value: string | number | boolean; -} -export declare type AssetPropertySchemaType = 'string' | 'number' | 'boolean' | 'enum' | 'asset' | 'array' | 'object'; +export declare type AssetPropertySchemaMap = Record; export declare namespace Assets { export { init, @@ -7097,9 +7071,6 @@ export declare namespace Assets { SerializedAssetDump, SerializedAssetPatch, SerializedAssetQueryResult, - AssetPropertySchemaType, - AssetPropertySchemaOption, - AssetPropertySchema, AssetPropertySchemaMap, IAssetInfo, AssetOperationOption, diff --git a/src/api/assets/assets.ts b/src/api/assets/assets.ts index 54822262d..5c94ab2ac 100644 --- a/src/api/assets/assets.ts +++ b/src/api/assets/assets.ts @@ -1018,7 +1018,7 @@ export class AssetsApi { */ @tool('assets-query-property-schema') @title('Query Asset Import Property Schema') // 查询资源导入属性 schema - @description('Query the standardized import property schema for a specific asset importer. The result is designed for panels to render import settings automatically and includes stable fields such as label, type, default, options, assetType, min, max, step, readOnly, and order. The raw field is only for debugging and should not be used as a UI contract.') // 查询指定资源导入器的标准化导入属性 schema,用于面板自动渲染导入设置。 + @description('Query the import property schema map for a specific asset importer. The result value follows ICocosConfigurationPropertySchema, using fields such as title, type, default, enum, enumDescriptions, minimum, maximum, step, properties, and items.') // 查询指定资源导入器的标准化导入属性 schema,用于面板自动渲染导入设置。 @result(SchemaAssetPropertySchemaResult) async queryPropertySchema( @param(SchemaUserDataHandler) importer: TUserDataHandler diff --git a/src/api/assets/schema.ts b/src/api/assets/schema.ts index ec64aaded..b716b4edc 100644 --- a/src/api/assets/schema.ts +++ b/src/api/assets/schema.ts @@ -343,29 +343,24 @@ export const SchemaAssetConfig = z.object({ export const SchemaAssetConfigMapResult = z.record(z.string(), SchemaAssetConfig).describe('Asset configuration map, key is asset handler name, value is corresponding configuration information'); // 资源配置映射表,键为资源处理器名称,值为对应的配置信息 export type TAssetConfigMapResult = z.infer; -export const SchemaAssetPropertySchemaOption = z.object({ - label: z.string().describe('Option display label'), // 选项显示名称 - value: z.union([z.string(), z.number(), z.boolean()]).describe('Option value'), // 选项值 -}).describe('Asset property schema option'); // 资源属性 schema 选项 - export const SchemaAssetPropertySchema: z.ZodType = z.lazy(() => z.object({ - label: z.string().describe('Property display label'), // 属性显示名称 - description: z.string().optional().describe('Property description'), // 属性描述 - type: z.enum(['string', 'number', 'boolean', 'enum', 'asset', 'array', 'object']).describe('Property value/control type'), // 属性值或控件类型 - default: z.any().optional().describe('Static default value'), // 静态默认值 - options: z.array(SchemaAssetPropertySchemaOption).optional().describe('Enum/select options'), // 枚举/下拉选项 - assetType: z.string().optional().describe('Allowed Cocos asset type for asset picker'), // Asset Picker 允许的 Cocos 资源类型 - min: z.number().optional().describe('Minimum number value'), // 数值最小值 - max: z.number().optional().describe('Maximum number value'), // 数值最大值 - step: z.number().optional().describe('Number input step'), // 数值步进 - readOnly: z.boolean().optional().describe('Whether the property is read-only'), // 是否只读 - order: z.number().optional().describe('Display order'), // 展示顺序 - properties: z.record(z.string(), SchemaAssetPropertySchema).optional().describe('Nested object properties'), // 嵌套对象属性 - items: z.union([SchemaAssetPropertySchema, z.array(SchemaAssetPropertySchema)]).optional().describe('Array item schema'), // 数组元素 schema - raw: z.any().optional().describe('Original legacy userDataConfig item for debugging only'), // 原始旧配置,仅用于调试 -}).describe('Standardized asset import property schema')); // 标准化资源导入属性 schema - -export const SchemaAssetPropertySchemaResult = z.record(z.string(), SchemaAssetPropertySchema).describe('Asset import property schema map, key is property name'); // 资源导入属性 schema 映射 + type: z.enum(['string', 'number', 'boolean', 'object', 'array']).describe('Configuration property value type'), + default: z.any().optional().describe('Default value'), + title: z.string().optional().describe('Display title'), + description: z.string().optional().describe('Property description'), + enum: z.array(z.union([z.string(), z.number(), z.boolean()])).optional().describe('Allowed enum values'), + enumDescriptions: z.array(z.string()).optional().describe('Display text for enum values'), + minimum: z.number().optional().describe('Minimum number value'), + maximum: z.number().optional().describe('Maximum number value'), + step: z.number().optional().describe('Number input step'), + order: z.number().optional().describe('Display order'), + properties: z.record(z.string(), SchemaAssetPropertySchema).optional().describe('Nested object properties'), + items: z.union([SchemaAssetPropertySchema, z.array(SchemaAssetPropertySchema)]).optional().describe('Array item schema'), + additionalProperties: z.union([z.boolean(), SchemaAssetPropertySchema]).optional().describe('Additional object property schema'), + required: z.array(z.string()).optional().describe('Required nested object property keys'), +})).describe('Cocos configuration property schema for asset import properties'); + +export const SchemaAssetPropertySchemaResult = z.record(z.string(), SchemaAssetPropertySchema).describe('Asset import property schema map, key is property name, value follows ICocosConfigurationPropertySchema'); export type TAssetPropertySchemaResult = z.infer; export const SchemaAnimationGraphVariantDump = z.object({ diff --git a/src/core/assets/@types/protected/asset-handler.d.ts b/src/core/assets/@types/protected/asset-handler.d.ts index 12983a317..26fdb618f 100644 --- a/src/core/assets/@types/protected/asset-handler.d.ts +++ b/src/core/assets/@types/protected/asset-handler.d.ts @@ -1,6 +1,7 @@ import { type } from 'os'; import { IAsset, IAssetInfo, VirtualAsset, Asset, IExportData, IAssetType } from './asset'; import { Migrate } from '@cocos/asset-db/libs/importer'; +import type { AssetPropertySchemaMap } from '../public'; export interface CustomOperator { label?: string; // 处理方法名,displayName 将会出现在一些文档定义上 @@ -93,8 +94,8 @@ export interface AssetHandlerBase extends CustomHandlerBase { // 对应导入资源在导入后的资源类型信息,未传递默认为 cc.Asset assetType?: IAssetType; - // Schema-only userData config. It is not registered as runtime default userData. - propertySchemaConfig?: Record; + // Schema-only userData property schema. It is not registered as runtime default userData. + propertySchemaConfig?: AssetPropertySchemaMap; // 指定资源的 userData 配置 userDataConfig?: { diff --git a/src/core/assets/@types/public.d.ts b/src/core/assets/@types/public.d.ts index 751ff1290..e344f50d9 100644 --- a/src/core/assets/@types/public.d.ts +++ b/src/core/assets/@types/public.d.ts @@ -1,5 +1,6 @@ import { AssetHandlerType, ISupportCreateType, AssetUserDataMap, IAssetType } from './asset-types'; import type { IProperty } from '../../scene/@types/public'; +import type { ICocosConfigurationPropertySchema } from '../../configuration/script/metadata'; export type { IProperty } from '../../scene/@types/public'; export type { IAssetDeleteOptions, @@ -37,31 +38,7 @@ export interface SerializedAssetQueryResult { dump: SerializedAssetDump; } -export type AssetPropertySchemaType = 'string' | 'number' | 'boolean' | 'enum' | 'asset' | 'array' | 'object'; - -export interface AssetPropertySchemaOption { - label: string; - value: string | number | boolean; -} - -export interface AssetPropertySchema { - label: string; - description?: string; - type: AssetPropertySchemaType; - default?: unknown; - options?: AssetPropertySchemaOption[]; - assetType?: string; - min?: number; - max?: number; - step?: number; - readOnly?: boolean; - order?: number; - properties?: Record; - items?: AssetPropertySchema | AssetPropertySchema[]; - raw?: unknown; -} - -export type AssetPropertySchemaMap = Record; +export type AssetPropertySchemaMap = Record; // 如果使用了 datakeys 过滤,请使用此接口定义 export interface IAssetInfo { diff --git a/src/core/assets/asset-handler/assets/auto-atlas.ts b/src/core/assets/asset-handler/assets/auto-atlas.ts index 83d1e48e8..41f54afdc 100644 --- a/src/core/assets/asset-handler/assets/auto-atlas.ts +++ b/src/core/assets/asset-handler/assets/auto-atlas.ts @@ -1,5 +1,5 @@ import { Asset } from '@cocos/asset-db'; -import { createTextureBaseUserDataConfig, makeDefaultTextureBaseAssetUserData } from './texture-base'; +import { createTextureBasePropertySchema, makeDefaultTextureBaseAssetUserData } from './texture-base'; import { getDependUUIDList } from '../utils'; import { AssetHandler } from '../../@types/protected'; @@ -36,108 +36,98 @@ const AutoAtlasHandler: AssetHandler = { assetType: 'cc.SpriteAtlas', propertySchemaConfig: { maxWidth: { - label: 'Max Width', + title: 'Max Width', + type: 'number', default: defaultAutoAtlasUserData.maxWidth, - render: { - ui: 'ui-number-input', - attributes: { min: 1, step: 1 }, - }, + minimum: 1, + step: 1, }, maxHeight: { - label: 'Max Height', + title: 'Max Height', + type: 'number', default: defaultAutoAtlasUserData.maxHeight, - render: { - ui: 'ui-number-input', - attributes: { min: 1, step: 1 }, - }, + minimum: 1, + step: 1, }, padding: { - label: 'Padding', + title: 'Padding', + type: 'number', default: defaultAutoAtlasUserData.padding, - render: { - ui: 'ui-number-input', - attributes: { min: 0, step: 1 }, - }, + minimum: 0, + step: 1, }, allowRotation: { - label: 'Allow Rotation', + title: 'Allow Rotation', + type: 'boolean', default: defaultAutoAtlasUserData.allowRotation, - render: { ui: 'ui-checkbox' }, }, forceSquared: { - label: 'Force Squared', + title: 'Force Squared', + type: 'boolean', default: defaultAutoAtlasUserData.forceSquared, - render: { ui: 'ui-checkbox' }, }, powerOfTwo: { - label: 'Power Of Two', + title: 'Power Of Two', + type: 'boolean', default: defaultAutoAtlasUserData.powerOfTwo, - render: { ui: 'ui-checkbox' }, }, algorithm: { - label: 'Algorithm', + title: 'Algorithm', + type: 'string', default: defaultAutoAtlasUserData.algorithm, - render: { - ui: 'ui-select', - items: [ - { label: 'MaxRects', value: 'MaxRects' }, - ], - }, + enum: ['MaxRects'], + enumDescriptions: ['MaxRects'], }, format: { - label: 'Format', + title: 'Format', + type: 'string', default: defaultAutoAtlasUserData.format, - render: { - ui: 'ui-select', - items: [ - { label: 'PNG', value: 'png' }, - { label: 'JPG', value: 'jpg' }, - ], - }, + enum: ['png', 'jpg'], + enumDescriptions: ['PNG', 'JPG'], }, quality: { - label: 'Quality', + title: 'Quality', + type: 'number', default: defaultAutoAtlasUserData.quality, - render: { - ui: 'ui-number-input', - attributes: { min: 0, max: 100, step: 1 }, - }, + minimum: 0, + maximum: 100, + step: 1, }, contourBleed: { - label: 'Contour Bleed', + title: 'Contour Bleed', + type: 'boolean', default: defaultAutoAtlasUserData.contourBleed, - render: { ui: 'ui-checkbox' }, }, paddingBleed: { - label: 'Padding Bleed', + title: 'Padding Bleed', + type: 'boolean', default: defaultAutoAtlasUserData.paddingBleed, - render: { ui: 'ui-checkbox' }, }, filterUnused: { - label: 'Filter Unused', + title: 'Filter Unused', + type: 'boolean', default: defaultAutoAtlasUserData.filterUnused, - render: { ui: 'ui-checkbox' }, }, removeTextureInBundle: { - label: 'Remove Texture In Bundle', + title: 'Remove Texture In Bundle', + type: 'boolean', default: defaultAutoAtlasUserData.removeTextureInBundle, - render: { ui: 'ui-checkbox' }, }, removeImageInBundle: { - label: 'Remove Image In Bundle', + title: 'Remove Image In Bundle', + type: 'boolean', default: defaultAutoAtlasUserData.removeImageInBundle, - render: { ui: 'ui-checkbox' }, }, removeSpriteAtlasInBundle: { - label: 'Remove SpriteAtlas In Bundle', + title: 'Remove SpriteAtlas In Bundle', + type: 'boolean', default: defaultAutoAtlasUserData.removeSpriteAtlasInBundle, - render: { ui: 'ui-checkbox' }, }, textureSetting: { - label: 'Texture Setting', + title: 'Texture Setting', type: 'object', default: defaultAutoAtlasUserData.textureSetting, - itemConfigs: createTextureBaseUserDataConfig(), + properties: createTextureBasePropertySchema(), }, }, createInfo: { diff --git a/src/core/assets/asset-handler/assets/fbx.ts b/src/core/assets/asset-handler/assets/fbx.ts index 93d39be49..625b5a128 100644 --- a/src/core/assets/asset-handler/assets/fbx.ts +++ b/src/core/assets/asset-handler/assets/fbx.ts @@ -10,12 +10,12 @@ export const FbxHandler: AssetHandlerBase = { propertySchemaConfig: { ...(GltfHandler.propertySchemaConfig ?? {}), legacyFbxImporter: { - label: 'Legacy FBX Importer', + title: 'Legacy FBX Importer', + type: 'boolean', default: false, - render: { ui: 'ui-checkbox' }, }, fbx: { - label: 'FBX', + title: 'FBX', type: 'object', default: { unitConversion: 'geometry-level', @@ -24,47 +24,35 @@ export const FbxHandler: AssetHandlerBase = { smartMaterialEnabled: false, matchMeshNames: false, }, - itemConfigs: { + properties: { unitConversion: { - label: 'Unit Conversion', + title: 'Unit Conversion', + type: 'string', default: 'geometry-level', - render: { - ui: 'ui-select', - items: [ - { label: 'Geometry Level', value: 'geometry-level' }, - { label: 'Hierarchy Level', value: 'hierarchy-level' }, - { label: 'Disabled', value: 'disabled' }, - ], - }, + enum: ['geometry-level', 'hierarchy-level', 'disabled'], + enumDescriptions: ['Geometry Level', 'Hierarchy Level', 'Disabled'], }, animationBakeRate: { - label: 'Animation Bake Rate', + title: 'Animation Bake Rate', + type: 'number', default: 24, - render: { - ui: 'ui-select', - items: [ - { label: 'Original', value: '0' }, - { label: '24 FPS', value: '24' }, - { label: '25 FPS', value: '25' }, - { label: '30 FPS', value: '30' }, - { label: '60 FPS', value: '60' }, - ], - }, + enum: [0, 24, 25, 30, 60], + enumDescriptions: ['Original', '24 FPS', '25 FPS', '30 FPS', '60 FPS'], }, preferLocalTimeSpan: { - label: 'Prefer Local Time Span', + title: 'Prefer Local Time Span', + type: 'boolean', default: true, - render: { ui: 'ui-checkbox' }, }, smartMaterialEnabled: { - label: 'Smart Material', + title: 'Smart Material', + type: 'boolean', default: false, - render: { ui: 'ui-checkbox' }, }, matchMeshNames: { - label: 'Match Mesh Names', + title: 'Match Mesh Names', + type: 'boolean', default: false, - render: { ui: 'ui-checkbox' }, }, }, }, diff --git a/src/core/assets/asset-handler/assets/gltf.ts b/src/core/assets/asset-handler/assets/gltf.ts index d0871ba45..67395b505 100644 --- a/src/core/assets/asset-handler/assets/gltf.ts +++ b/src/core/assets/asset-handler/assets/gltf.ts @@ -49,127 +49,127 @@ export const GltfHandler: AssetHandlerBase = { name: 'gltf', propertySchemaConfig: { - dumpMaterials: { - label: 'Dump Materials', - default: false, - render: { ui: 'ui-checkbox' }, - }, - mountAllAnimationsOnPrefab: { - label: 'Mount All Animations On Prefab', - default: false, - render: { ui: 'ui-checkbox' }, - }, - allowMeshDataAccess: { - label: 'Allow Mesh Data Access', - default: true, - render: { ui: 'ui-checkbox' }, - }, - addVertexColor: { - label: 'Add Vertex Color', - default: false, - render: { ui: 'ui-checkbox' }, - }, - promoteSingleRootNode: { - label: 'Promote Single Root Node', - default: false, - render: { ui: 'ui-checkbox' }, - }, - generateLightmapUVNode: { - label: 'Generate Lightmap UV', - default: false, - render: { ui: 'ui-checkbox' }, - }, - normals: { - label: 'Normals', - default: NormalImportSetting.require, - render: { - ui: 'ui-select', - items: [ - { label: 'Optional', value: String(NormalImportSetting.optional) }, - { label: 'Exclude', value: String(NormalImportSetting.exclude) }, - { label: 'Require', value: String(NormalImportSetting.require) }, - { label: 'Recalculate', value: String(NormalImportSetting.recalculate) }, - ], - }, - }, - tangents: { - label: 'Tangents', - default: TangentImportSetting.require, - render: { - ui: 'ui-select', - items: [ - { label: 'Exclude', value: String(TangentImportSetting.exclude) }, - { label: 'Optional', value: String(TangentImportSetting.optional) }, - { label: 'Require', value: String(TangentImportSetting.require) }, - { label: 'Recalculate', value: String(TangentImportSetting.recalculate) }, - ], - }, + dumpMaterials: { + title: 'Dump Materials', + type: 'boolean', + default: false, + }, + mountAllAnimationsOnPrefab: { + title: 'Mount All Animations On Prefab', + type: 'boolean', + default: false, + }, + allowMeshDataAccess: { + title: 'Allow Mesh Data Access', + type: 'boolean', + default: true, + }, + addVertexColor: { + title: 'Add Vertex Color', + type: 'boolean', + default: false, + }, + promoteSingleRootNode: { + title: 'Promote Single Root Node', + type: 'boolean', + default: false, + }, + generateLightmapUVNode: { + title: 'Generate Lightmap UV', + type: 'boolean', + default: false, + }, + normals: { + title: 'Normals', + type: 'number', + default: NormalImportSetting.require, + enum: [ + NormalImportSetting.optional, + NormalImportSetting.exclude, + NormalImportSetting.require, + NormalImportSetting.recalculate, + ], + enumDescriptions: ['Optional', 'Exclude', 'Require', 'Recalculate'], + }, + tangents: { + title: 'Tangents', + type: 'number', + default: TangentImportSetting.require, + enum: [ + TangentImportSetting.exclude, + TangentImportSetting.optional, + TangentImportSetting.require, + TangentImportSetting.recalculate, + ], + enumDescriptions: ['Exclude', 'Optional', 'Require', 'Recalculate'], + }, + morphNormals: { + title: 'Morph Normals', + type: 'number', + default: NormalImportSetting.exclude, + enum: [ + NormalImportSetting.exclude, + NormalImportSetting.optional, + ], + enumDescriptions: ['Exclude', 'Optional'], + }, + meshOptimizer: { + title: 'Mesh Optimizer', + type: 'object', + default: { + enable: false, + algorithm: 'simplify', + simplifyOptions: getDefaultSimplifyOptions(), }, - morphNormals: { - label: 'Morph Normals', - default: NormalImportSetting.exclude, - render: { - ui: 'ui-select', - items: [ - { label: 'Exclude', value: String(NormalImportSetting.exclude) }, - { label: 'Optional', value: String(NormalImportSetting.optional) }, - ], + properties: { + enable: { + title: 'Enable', + type: 'boolean', + default: false, }, - }, - meshOptimizer: { - label: 'Mesh Optimizer', - type: 'object', - default: { - enable: false, - algorithm: 'simplify', - simplifyOptions: getDefaultSimplifyOptions(), + algorithm: { + title: 'Algorithm', + type: 'string', + default: 'simplify', + enum: ['simplify', 'gltfpack'], + enumDescriptions: ['Simplify', 'gltfpack'], }, - itemConfigs: { - enable: { - label: 'Enable', - default: false, - render: { ui: 'ui-checkbox' }, - }, - algorithm: { - label: 'Algorithm', - default: 'simplify', - render: { - ui: 'ui-select', - items: [ - { label: 'Simplify', value: 'simplify' }, - { label: 'gltfpack', value: 'gltfpack' }, - ], + simplifyOptions: { + title: 'Simplify Options', + type: 'object', + default: getDefaultSimplifyOptions(), + properties: { + targetRatio: { + title: 'Target Ratio', + type: 'number', + default: 1, + minimum: 0, + maximum: 1, + step: 0.01, }, - }, - simplifyOptions: { - label: 'Simplify Options', - type: 'object', - default: getDefaultSimplifyOptions(), - itemConfigs: { - targetRatio: { - label: 'Target Ratio', - default: 1, - render: { ui: 'ui-number-input', attributes: { min: 0, max: 1, step: 0.01 } }, - }, - enableSmartLink: { - label: 'Enable Smart Link', - default: true, - render: { ui: 'ui-checkbox' }, - }, - agressiveness: { - label: 'Agressiveness', - default: 7, - render: { ui: 'ui-number-input', attributes: { min: 0, step: 1 } }, - }, - maxIterationCount: { - label: 'Max Iteration Count', - default: 100, - render: { ui: 'ui-number-input', attributes: { min: 1, step: 1 } }, - }, + enableSmartLink: { + title: 'Enable Smart Link', + type: 'boolean', + default: true, + }, + agressiveness: { + title: 'Agressiveness', + type: 'number', + default: 7, + minimum: 0, + step: 1, + }, + maxIterationCount: { + title: 'Max Iteration Count', + type: 'number', + default: 100, + minimum: 1, + step: 1, }, }, }, }, + }, }, importer: { diff --git a/src/core/assets/asset-handler/assets/image/index.ts b/src/core/assets/asset-handler/assets/image/index.ts index 1319462db..13d15f834 100644 --- a/src/core/assets/asset-handler/assets/image/index.ts +++ b/src/core/assets/asset-handler/assets/image/index.ts @@ -25,6 +25,19 @@ export const ImageHandler: AssetHandler = { // 引擎内对应的类型 assetType: 'cc.ImageAsset', open: openImageAsset, + propertySchemaConfig: { + type: { + title: 'i18n:ENGINE.assets.image.type', + type: 'string', + default: 'sprite-frame', + enum: ['raw', 'texture', 'normal map', 'sprite-frame', 'texture cube'], + enumDescriptions: ['raw', 'texture', 'normal map', 'sprite-frame', 'texture cube'], + }, + flipVertical: { + title: 'i18n:ENGINE.assets.image.flipVertical', + type: 'boolean', + }, + }, importer: { // 版本号如果变更,则会强制重新导入 version: '1.0.27', diff --git a/src/core/assets/asset-handler/assets/sprite-frame.ts b/src/core/assets/asset-handler/assets/sprite-frame.ts index 7401ac3f0..c7d7d7da8 100644 --- a/src/core/assets/asset-handler/assets/sprite-frame.ts +++ b/src/core/assets/asset-handler/assets/sprite-frame.ts @@ -54,73 +54,82 @@ export const SpriteFrameHandler: AssetHandler = { }, }, propertySchemaConfig: { + trimType: { + title: 'i18n:ENGINE.assets.spriteFrame.trimType', + type: 'string', + default: 'auto', + enum: ['auto', 'custom', 'none'], + enumDescriptions: ['auto', 'custom', 'none'], + }, trimThreshold: { default: defaultSpriteFrameUserData.trimThreshold, - label: 'Trim Threshold', - render: { - ui: 'ui-number-input', - attributes: { min: 0, step: 1 }, - }, + title: 'Trim Threshold', + type: 'number', + minimum: 0, + step: 1, }, packable: { default: defaultSpriteFrameUserData.packable, - label: 'Packable', - render: { ui: 'ui-checkbox' }, + title: 'Packable', + type: 'boolean', }, pixelsToUnit: { default: defaultSpriteFrameUserData.pixelsToUnit, - label: 'Pixels To Unit', - render: { - ui: 'ui-number-input', - attributes: { min: 1, step: 1 }, - }, + title: 'Pixels To Unit', + type: 'number', + minimum: 1, + step: 1, }, pivotX: { default: defaultSpriteFrameUserData.pivotX, - label: 'Pivot X', - render: { - ui: 'ui-number-input', - attributes: { min: 0, max: 1, step: 0.01 }, - }, + title: 'Pivot X', + type: 'number', + minimum: 0, + maximum: 1, + step: 0.01, }, pivotY: { default: defaultSpriteFrameUserData.pivotY, - label: 'Pivot Y', - render: { - ui: 'ui-number-input', - attributes: { min: 0, max: 1, step: 0.01 }, - }, + title: 'Pivot Y', + type: 'number', + minimum: 0, + maximum: 1, + step: 0.01, }, meshType: { default: defaultSpriteFrameUserData.meshType, - label: 'Mesh Type', - render: { - ui: 'ui-select', - items: [ - { label: 'Rect', value: '0' }, - { label: 'Polygon', value: '1' }, - ], - }, + title: 'Mesh Type', + type: 'number', + enum: [0, 1], + enumDescriptions: ['Rect', 'Polygon'], }, borderTop: { default: defaultSpriteFrameUserData.borderTop, - label: 'Border Top', - render: { ui: 'ui-number-input', attributes: { min: 0, step: 1 } }, + title: 'Border Top', + type: 'number', + minimum: 0, + step: 1, }, borderBottom: { default: defaultSpriteFrameUserData.borderBottom, - label: 'Border Bottom', - render: { ui: 'ui-number-input', attributes: { min: 0, step: 1 } }, + title: 'Border Bottom', + type: 'number', + minimum: 0, + step: 1, }, borderLeft: { default: defaultSpriteFrameUserData.borderLeft, - label: 'Border Left', - render: { ui: 'ui-number-input', attributes: { min: 0, step: 1 } }, + title: 'Border Left', + type: 'number', + minimum: 0, + step: 1, }, borderRight: { default: defaultSpriteFrameUserData.borderRight, - label: 'Border Right', - render: { ui: 'ui-number-input', attributes: { min: 0, step: 1 } }, + title: 'Border Right', + type: 'number', + minimum: 0, + step: 1, }, }, importer: { diff --git a/src/core/assets/asset-handler/assets/texture-base.ts b/src/core/assets/asset-handler/assets/texture-base.ts index 44b7763a1..62f1330a3 100644 --- a/src/core/assets/asset-handler/assets/texture-base.ts +++ b/src/core/assets/asset-handler/assets/texture-base.ts @@ -2,7 +2,7 @@ import { Asset } from '@cocos/asset-db'; import { Filter, SpriteFrameBaseAssetUserData, TextureBaseAssetUserData, WrapMode } from '../../@types/userDatas'; -import type { IUerDataConfigItem } from '../../@types/protected'; +import type { ICocosConfigurationPropertySchema } from '../../../configuration/script/metadata'; export const defaultMinFilter: Filter = 'linear'; export const defaultMagFilter: Filter = 'linear'; @@ -21,58 +21,49 @@ export function makeDefaultTextureBaseAssetUserData(): TextureBaseAssetUserData }; } -export function createTextureBaseUserDataConfig(): Record { +export function createTextureBasePropertySchema(): Record { return { wrapModeS: { - label: 'Wrap Mode S', + title: 'Wrap Mode S', + type: 'string', default: defaultWrapModeS, - render: { - ui: 'ui-select', - items: createWrapModeOptions(), - }, + enum: ['repeat', 'clamp-to-edge', 'mirrored-repeat'], + enumDescriptions: ['Repeat', 'Clamp To Edge', 'Mirrored Repeat'], }, wrapModeT: { - label: 'Wrap Mode T', + title: 'Wrap Mode T', + type: 'string', default: defaultWrapModeT, - render: { - ui: 'ui-select', - items: createWrapModeOptions(), - }, + enum: ['repeat', 'clamp-to-edge', 'mirrored-repeat'], + enumDescriptions: ['Repeat', 'Clamp To Edge', 'Mirrored Repeat'], }, minfilter: { - label: 'Min Filter', + title: 'Min Filter', + type: 'string', default: defaultMinFilter, - render: { - ui: 'ui-select', - items: createFilterOptions(), - }, + enum: ['none', 'nearest', 'linear'], + enumDescriptions: ['None', 'Nearest', 'Linear'], }, magfilter: { - label: 'Mag Filter', + title: 'Mag Filter', + type: 'string', default: defaultMagFilter, - render: { - ui: 'ui-select', - items: createFilterOptions().filter((item) => item.value !== 'none'), - }, + enum: ['nearest', 'linear'], + enumDescriptions: ['Nearest', 'Linear'], }, mipfilter: { - label: 'Mip Filter', + title: 'Mip Filter', + type: 'string', default: defaultMipFilter, - render: { - ui: 'ui-select', - items: createFilterOptions(), - }, + enum: ['none', 'nearest', 'linear'], + enumDescriptions: ['None', 'Nearest', 'Linear'], }, anisotropy: { - label: 'Anisotropy', + title: 'Anisotropy', + type: 'number', default: 0, - render: { - ui: 'ui-number-input', - attributes: { - min: 0, - step: 1, - }, - }, + minimum: 0, + step: 1, }, }; } @@ -118,22 +109,6 @@ export function makeDefaultSpriteFrameBaseAssetUserData(): SpriteFrameBaseAssetU }; } -function createWrapModeOptions() { - return [ - { label: 'Repeat', value: 'repeat' }, - { label: 'Clamp To Edge', value: 'clamp-to-edge' }, - { label: 'Mirrored Repeat', value: 'mirrored-repeat' }, - ]; -} - -function createFilterOptions() { - return [ - { label: 'None', value: 'none' }, - { label: 'Nearest', value: 'nearest' }, - { label: 'Linear', value: 'linear' }, - ]; -} - export function getWrapMode(wrapMode: WrapMode) { switch (wrapMode) { // @ts-ignore diff --git a/src/core/assets/asset-handler/assets/texture.ts b/src/core/assets/asset-handler/assets/texture.ts index 6d7f06fed..57c1334c6 100644 --- a/src/core/assets/asset-handler/assets/texture.ts +++ b/src/core/assets/asset-handler/assets/texture.ts @@ -6,7 +6,7 @@ import { AssetHandler } from '../../@types/protected'; import { Texture2DAssetUserData } from '../../@types/userDatas'; import { getDependUUIDList } from '../utils'; import { makeDefaultTexture2DAssetUserData } from './image/utils'; -import { applyTextureBaseAssetUserData, createTextureBaseUserDataConfig } from './texture-base'; +import { applyTextureBaseAssetUserData, createTextureBasePropertySchema } from './texture-base'; import { url2uuid } from '../../utils'; export const TextureHandler: AssetHandler = { @@ -17,23 +17,16 @@ export const TextureHandler: AssetHandler = { assetType: 'cc.Texture2D', propertySchemaConfig: { - ...createTextureBaseUserDataConfig(), + ...createTextureBasePropertySchema(), imageUuidOrDatabaseUri: { - label: 'Image', + title: 'Image', + type: 'string', default: '', - render: { - ui: 'ui-asset', - attributes: { - assetType: 'cc.ImageAsset', - }, - }, }, isUuid: { - label: 'Use UUID', + title: 'Use UUID', + type: 'boolean', default: true, - render: { - ui: 'ui-checkbox', - }, }, }, diff --git a/src/core/assets/manager/asset-handler.ts b/src/core/assets/manager/asset-handler.ts index c90ae0840..9954f4fd3 100644 --- a/src/core/assets/manager/asset-handler.ts +++ b/src/core/assets/manager/asset-handler.ts @@ -12,7 +12,7 @@ import type { AssetHandlerInfo } from '../asset-handler/config'; import assetConfig from '../asset-config'; import { copyPath, createDirectoryPath, writePath } from './filesystem'; import eol from 'eol'; -import { convertUserDataConfigToPropertySchema, mergeUserDataConfigForPropertySchema } from '../property-schema'; +import { createAssetPropertySchemaMap } from '../property-schema'; import type { AssetPropertySchemaMap } from '../@types/public'; interface HandlerInfo extends AssetHandlerInfo { @@ -554,11 +554,7 @@ class AssetHandlerManager { throw new Error(`Asset handler not found: ${importer}`); } - const propertyConfig = mergeUserDataConfigForPropertySchema( - assetHandler.userDataConfig?.default, - assetHandler.propertySchemaConfig, - ); - return convertUserDataConfigToPropertySchema(propertyConfig); + return createAssetPropertySchemaMap(assetHandler.propertySchemaConfig); } async runImporterHook(asset: IAsset, hookName: 'before' | 'after') { diff --git a/src/core/assets/property-schema.ts b/src/core/assets/property-schema.ts index 875ecd86f..6a8537c15 100644 --- a/src/core/assets/property-schema.ts +++ b/src/core/assets/property-schema.ts @@ -1,250 +1,17 @@ -import type { AssetPropertySchema, AssetPropertySchemaMap, AssetPropertySchemaOption } from './@types/public'; -import type { IUerDataConfigItem } from './@types/protected'; -import { - createTitleFromKey, - normalizeDisplayText, - translateMetadataText, -} from '../configuration/script/metadata'; +import type { AssetPropertySchemaMap } from './@types/public'; +import { createPropertySchema } from '../configuration/script/metadata'; -type LegacyConfigItem = IUerDataConfigItem & { - assetType?: string; - readOnly?: boolean; - readonly?: boolean; - order?: number; -}; - -type LegacyRenderAttributes = Record; - -const UI_TYPE_MAP: Record = { - 'ui-checkbox': 'boolean', - 'ui-number-input': 'number', - 'ui-num-input': 'number', - 'ui-slider': 'number', - 'ui-input': 'string', - 'ui-textarea': 'string', - 'ui-select': 'enum', - 'ui-asset': 'asset', - 'ui-asset-picker': 'asset', -}; - -export function convertUserDataConfigToPropertySchema( - config: Record | undefined +export function createAssetPropertySchemaMap( + config: AssetPropertySchemaMap | undefined ): AssetPropertySchemaMap { const result: AssetPropertySchemaMap = {}; if (!config) { return result; } - for (const [key, item] of Object.entries(config)) { - const fieldName = item.key || key; - result[fieldName] = convertUserDataConfigItemToPropertySchema(fieldName, item); + for (const [key, schema] of Object.entries(config)) { + result[key] = createPropertySchema(schema); } return result; } - -export function mergeUserDataConfigForPropertySchema( - runtimeConfig: Record | undefined, - schemaOnlyConfig: Record | undefined -): Record | undefined { - if (!runtimeConfig && !schemaOnlyConfig) { - return undefined; - } - - return { - ...(runtimeConfig ?? {}), - ...(schemaOnlyConfig ?? {}), - }; -} - -export function convertUserDataConfigItemToPropertySchema( - key: string, - item: IUerDataConfigItem -): AssetPropertySchema { - const legacyItem = item as LegacyConfigItem; - const attributes = item.render?.attributes; - const schema: AssetPropertySchema = { - label: normalizeDisplayText(item.label, createTitleFromKey(key)), - type: inferSchemaType(item), - raw: item, - }; - - const description = translateMetadataText(item.description); - if (description) { - schema.description = description; - } - - if (item.default !== undefined) { - schema.default = item.default; - } - - const options = convertOptions(item, schema.default); - if (options.length) { - schema.options = options; - schema.type = 'enum'; - } - - const assetType = readStringAttribute(attributes, 'assetType') ?? legacyItem.assetType; - if (assetType) { - schema.type = 'asset'; - schema.assetType = assetType; - } - - const min = readNumberAttribute(attributes, 'min') ?? readNumberAttribute(attributes, 'minimum'); - if (min !== undefined) { - schema.min = min; - } - - const max = readNumberAttribute(attributes, 'max') ?? readNumberAttribute(attributes, 'maximum'); - if (max !== undefined) { - schema.max = max; - } - - const step = readNumberAttribute(attributes, 'step'); - if (step !== undefined) { - schema.step = step; - } - - const readOnly = readBooleanAttribute(attributes, 'readOnly') - ?? readBooleanAttribute(attributes, 'readonly') - ?? legacyItem.readOnly - ?? legacyItem.readonly; - if (readOnly !== undefined) { - schema.readOnly = readOnly; - } - - const order = readNumberAttribute(attributes, 'order') ?? legacyItem.order; - if (order !== undefined) { - schema.order = order; - } - - applyNestedConfig(schema, item); - - return schema; -} - -function inferSchemaType(item: IUerDataConfigItem): AssetPropertySchema['type'] { - if (item.type === 'array' || item.type === 'object') { - return item.type; - } - - const uiType = item.render?.ui?.toLowerCase(); - if (uiType && UI_TYPE_MAP[uiType]) { - return UI_TYPE_MAP[uiType]; - } - - const value = item.default; - if (Array.isArray(value)) { - return 'array'; - } - - if (value !== null && typeof value === 'object') { - return 'object'; - } - - if (typeof value === 'number') { - return 'number'; - } - - if (typeof value === 'boolean') { - return 'boolean'; - } - - return 'string'; -} - -function convertOptions(item: IUerDataConfigItem, defaultValue: unknown): AssetPropertySchemaOption[] { - return (item.render?.items ?? []).map((option) => ({ - label: normalizeDisplayText(option.label, String(option.value)), - value: normalizeOptionValue(option.value, defaultValue), - })); -} - -function normalizeOptionValue(value: string | number | boolean, defaultValue: unknown): string | number | boolean { - if (typeof value !== 'string') { - return value; - } - - if (typeof defaultValue === 'boolean') { - if (value === 'true') { - return true; - } - if (value === 'false') { - return false; - } - } - - if (typeof defaultValue === 'number') { - const numericValue = Number(value); - if (Number.isFinite(numericValue)) { - return numericValue; - } - } - - return value; -} - -function applyNestedConfig(schema: AssetPropertySchema, item: IUerDataConfigItem): void { - const { itemConfigs } = item; - if (!itemConfigs) { - return; - } - - if (Array.isArray(itemConfigs)) { - const children = itemConfigs.map((child, index) => ( - convertUserDataConfigItemToPropertySchema(child.key || String(index), child) - )); - if (schema.type === 'array') { - schema.items = children.length === 1 ? children[0] : children; - } else { - schema.type = 'object'; - schema.properties = Object.fromEntries(children.map((child, index) => [itemConfigs[index].key || String(index), child])); - } - return; - } - - const children = convertUserDataConfigToPropertySchema(itemConfigs); - if (schema.type === 'array') { - schema.items = { - label: 'Item', - type: 'object', - default: {}, - properties: children, - }; - return; - } - - schema.type = 'object'; - schema.properties = children; -} - -function readStringAttribute(attributes: LegacyRenderAttributes | undefined, name: string): string | undefined { - const value = attributes?.[name]; - return typeof value === 'string' && value ? value : undefined; -} - -function readNumberAttribute(attributes: LegacyRenderAttributes | undefined, name: string): number | undefined { - const value = attributes?.[name]; - if (typeof value === 'number' && Number.isFinite(value)) { - return value; - } - if (typeof value === 'string' && value !== '') { - const numericValue = Number(value); - return Number.isFinite(numericValue) ? numericValue : undefined; - } - return undefined; -} - -function readBooleanAttribute(attributes: LegacyRenderAttributes | undefined, name: string): boolean | undefined { - const value = attributes?.[name]; - if (typeof value === 'boolean') { - return value; - } - if (value === 'true') { - return true; - } - if (value === 'false') { - return false; - } - return undefined; -} diff --git a/src/core/assets/test/property-schema.test.ts b/src/core/assets/test/property-schema.test.ts index 98c9b7f54..cd5bb4172 100644 --- a/src/core/assets/test/property-schema.test.ts +++ b/src/core/assets/test/property-schema.test.ts @@ -1,190 +1,80 @@ -import { - convertUserDataConfigItemToPropertySchema, - convertUserDataConfigToPropertySchema, - mergeUserDataConfigForPropertySchema, -} from '../property-schema'; +import { createAssetPropertySchemaMap } from '../property-schema'; +import { ImageHandler } from '../asset-handler/assets/image'; +import { SpriteFrameHandler } from '../asset-handler/assets/sprite-frame'; -describe('asset property schema conversion', () => { - it('maps legacy userDataConfig controls to stable property schema fields', () => { - const schema = convertUserDataConfigToPropertySchema({ - type: { - label: 'Import Type', - default: 'sprite-frame', - render: { - ui: 'ui-select', - items: [ - { label: 'Raw', value: 'raw' }, - { label: 'Sprite Frame', value: 'sprite-frame' }, - ], - }, +describe('asset property schema map', () => { + it('keeps asset property schema aligned with configuration property schema', () => { + const schema = createAssetPropertySchemaMap({ + meshType: { + title: 'Mesh Type', + type: 'number', + default: 0, + enum: [0, 1], + enumDescriptions: ['Rect', 'Polygon'], }, - flipVertical: { - label: 'Flip Vertical', - render: { - ui: 'ui-checkbox', + textureSetting: { + title: 'Texture Setting', + type: 'object', + default: { + anisotropy: 0, }, - }, - quality: { - label: 'Quality', - default: 80, - render: { - ui: 'ui-number-input', - attributes: { - min: 0, - max: 100, + properties: { + anisotropy: { + title: 'Anisotropy', + type: 'number', + default: 0, + minimum: 0, step: 1, }, }, }, - image: { - label: 'Image', - default: '', - render: { - ui: 'ui-asset', - attributes: { - assetType: 'cc.ImageAsset', - }, - }, - }, }); - expect(schema.type).toMatchObject({ - label: 'Import Type', - type: 'enum', - default: 'sprite-frame', - options: [ - { label: 'Raw', value: 'raw' }, - { label: 'Sprite Frame', value: 'sprite-frame' }, - ], + expect(schema.meshType).toEqual({ + title: 'Mesh Type', + type: 'number', + default: 0, + enum: [0, 1], + enumDescriptions: ['Rect', 'Polygon'], }); - expect(schema.flipVertical.type).toBe('boolean'); - expect(schema.quality).toMatchObject({ + expect(schema.textureSetting.properties?.anisotropy).toEqual({ + title: 'Anisotropy', type: 'number', - min: 0, - max: 100, + default: 0, + minimum: 0, step: 1, }); - expect(schema.image).toMatchObject({ - type: 'asset', - assetType: 'cc.ImageAsset', - }); + expect(schema.meshType).not.toHaveProperty('label'); + expect(schema.meshType).not.toHaveProperty('options'); + expect(schema.meshType).not.toHaveProperty('raw'); }); - it('normalizes numeric enum option values when the default is numeric', () => { - const schema = convertUserDataConfigItemToPropertySchema('meshType', { - label: 'Mesh Type', - default: 0, - render: { - ui: 'ui-select', - items: [ - { label: 'Rect', value: '0' }, - { label: 'Polygon', value: '1' }, - ], - }, - }); - - expect(schema.type).toBe('enum'); - expect(schema.options).toEqual([ - { label: 'Rect', value: 0 }, - { label: 'Polygon', value: 1 }, - ]); + it('returns an empty map when a handler has no explicit property schema config', () => { + expect(createAssetPropertySchemaMap(undefined)).toEqual({}); }); - it('keeps nested object itemConfigs as nested properties', () => { - const schema = convertUserDataConfigItemToPropertySchema('textureSetting', { - label: 'Texture Setting', - type: 'object', - default: { - anisotropy: 0, - }, - itemConfigs: { - anisotropy: { - label: 'Anisotropy', - default: 0, - render: { - ui: 'ui-number-input', - attributes: { - min: 0, - step: 1, - }, - }, - }, - }, - }); - - expect(schema).toMatchObject({ - label: 'Texture Setting', - type: 'object', - properties: { - anisotropy: { - label: 'Anisotropy', - type: 'number', - default: 0, - min: 0, - step: 1, - }, - }, - }); - }); + it('builds config-style property schema from built-in asset handler declarations', () => { + const imageSchema = createAssetPropertySchemaMap(ImageHandler.propertySchemaConfig); + const spriteFrameSchema = createAssetPropertySchemaMap(SpriteFrameHandler.propertySchemaConfig); - it('treats array-form itemConfigs as object properties when the parent is not an array', () => { - const schema = convertUserDataConfigItemToPropertySchema('rect', { - label: 'Rect', - itemConfigs: [ - { - key: 'x', - label: 'X', - default: 0, - render: { ui: 'ui-number-input' }, - }, - ], + expect(imageSchema.type).toMatchObject({ + type: 'string', + default: 'sprite-frame', + enum: ['raw', 'texture', 'normal map', 'sprite-frame', 'texture cube'], }); + expect(imageSchema.type).not.toHaveProperty('label'); + expect(imageSchema.type).not.toHaveProperty('options'); - expect(schema).toMatchObject({ - label: 'Rect', - type: 'object', - properties: { - x: { - label: 'X', - type: 'number', - default: 0, - }, - }, + expect(spriteFrameSchema.trimType).toMatchObject({ + type: 'string', + default: 'auto', + enum: ['auto', 'custom', 'none'], }); - }); - - it('merges schema-only config for property schema without mutating runtime userDataConfig', () => { - const runtimeConfig = { - runtimeOnly: { - label: 'Runtime Only', - default: true, - render: { ui: 'ui-checkbox' }, - }, - }; - const schemaOnlyConfig = { - schemaOnly: { - label: 'Schema Only', - default: 1, - render: { ui: 'ui-number-input' }, - }, - }; - - const mergedConfig = mergeUserDataConfigForPropertySchema(runtimeConfig, schemaOnlyConfig); - const schema = convertUserDataConfigToPropertySchema(mergedConfig); - - expect(schema).toMatchObject({ - runtimeOnly: { - label: 'Runtime Only', - type: 'boolean', - default: true, - }, - schemaOnly: { - label: 'Schema Only', - type: 'number', - default: 1, - }, + expect(spriteFrameSchema.trimThreshold).toMatchObject({ + type: 'number', + minimum: 0, + step: 1, }); - expect(runtimeConfig).toHaveProperty('runtimeOnly'); - expect(runtimeConfig).not.toHaveProperty('schemaOnly'); + expect(spriteFrameSchema.trimType).not.toHaveProperty('raw'); }); }); diff --git a/tests/assets-query-property-schema-api.test.ts b/tests/assets-query-property-schema-api.test.ts index 3cc420e2a..c9d4ffd5b 100644 --- a/tests/assets-query-property-schema-api.test.ts +++ b/tests/assets-query-property-schema-api.test.ts @@ -28,9 +28,11 @@ describe('assets-query-property-schema api', () => { it('delegates to assetManager.queryPropertySchema', async () => { const schema = { type: { - label: 'Import Type', - type: 'enum', + title: 'Import Type', + type: 'string', default: 'sprite-frame', + enum: ['raw', 'sprite-frame'], + enumDescriptions: ['Raw', 'Sprite Frame'], }, }; mockQueryPropertySchema.mockResolvedValue(schema); diff --git a/tests/lib/assets-api.test.ts b/tests/lib/assets-api.test.ts index 2fa265d46..6e14c7501 100644 --- a/tests/lib/assets-api.test.ts +++ b/tests/lib/assets-api.test.ts @@ -58,9 +58,11 @@ describe('lib assets api', () => { it('exposes queryPropertySchema and delegates to assetManager', async () => { const schema = { type: { - label: 'Import Type', - type: 'enum' as const, + title: 'Import Type', + type: 'string' as const, default: 'sprite-frame', + enum: ['raw', 'sprite-frame'], + enumDescriptions: ['Raw', 'Sprite Frame'], }, }; const spy = jest.spyOn(assetManager, 'queryPropertySchema').mockResolvedValue(schema);