WIP: UI编辑器自动分图层切图标 #304
@@ -524,6 +524,40 @@ function spriteResourceValidationError(sprite: SpriteAsset) {
|
||||
return border.ok ? null : border.message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the SpriteAsset resource checks without acquiring the editor mutation
|
||||
* guard. Workflow adapters use this while a State lock is already held so
|
||||
* resource insertion and component backfill can be committed atomically.
|
||||
*/
|
||||
export function addSpriteAssetsToState(
|
||||
current: State,
|
||||
assets: readonly SpriteAsset[],
|
||||
): UiEditorOperationResult<State> {
|
||||
const unique = new Map<SpriteAssetId, SpriteAsset>();
|
||||
for (const asset of assets) {
|
||||
const candidate =
|
||||
unique.get(asset.asset_id) ?? current.sprite_assets[asset.asset_id];
|
||||
if (candidate && !sameResource(candidate, asset)) {
|
||||
return { ok: false, reason: 'duplicate' };
|
||||
}
|
||||
unique.set(asset.asset_id, asset);
|
||||
}
|
||||
const invalidSprite = [...unique.values()]
|
||||
.map((asset) => ({ asset, error: spriteResourceValidationError(asset) }))
|
||||
.find((item) => item.error);
|
||||
if (invalidSprite?.error) {
|
||||
return {
|
||||
ok: false,
|
||||
reason: `invalid:${invalidSprite.asset.asset_id}:${invalidSprite.error}`,
|
||||
};
|
||||
}
|
||||
const next = cloneState(current);
|
||||
for (const asset of unique.values()) {
|
||||
next.sprite_assets[asset.asset_id] = structuredClone(asset);
|
||||
}
|
||||
return { ok: true, value: next };
|
||||
}
|
||||
|
||||
function fontResourceValidationError(font: FontAsset) {
|
||||
if (font.asset_id.trim().length === 0) return '缺少字体 ID';
|
||||
if (font.path.trim().length === 0) return '缺少字体路径';
|
||||
@@ -782,32 +816,9 @@ export function useUiEditorState(initialState: State = EMPTY_UI_EDITOR_STATE) {
|
||||
const blocked = guard();
|
||||
if (blocked) return blocked;
|
||||
const current = stateRef.current;
|
||||
const unique = new Map<SpriteAssetId, SpriteAsset>();
|
||||
for (const asset of assets) {
|
||||
const candidate =
|
||||
unique.get(asset.asset_id) ?? current.sprite_assets[asset.asset_id];
|
||||
if (candidate && !sameResource(candidate, asset)) {
|
||||
return { ok: false, reason: 'duplicate' };
|
||||
}
|
||||
unique.set(asset.asset_id, asset);
|
||||
}
|
||||
const invalidSprite = [...unique.values()]
|
||||
.map((asset) => ({
|
||||
asset,
|
||||
error: spriteResourceValidationError(asset),
|
||||
}))
|
||||
.find((item) => item.error);
|
||||
if (invalidSprite?.error) {
|
||||
return {
|
||||
ok: false,
|
||||
reason: `invalid:${invalidSprite.asset.asset_id}:${invalidSprite.error}`,
|
||||
};
|
||||
}
|
||||
const next = cloneState(current);
|
||||
for (const asset of unique.values()) {
|
||||
next.sprite_assets[asset.asset_id] = structuredClone(asset);
|
||||
}
|
||||
commit(next);
|
||||
const result = addSpriteAssetsToState(current, assets);
|
||||
if (!result.ok) return result;
|
||||
commit(result.value);
|
||||
return { ok: true, value: undefined };
|
||||
},
|
||||
[commit, guard],
|
||||
|
||||
Reference in New Issue
Block a user