Duplicate an asset from its right-click menu (#297)
A new asset that starts out like an existing one (a death animation
next to "Break", a second slime) had to be built again by hand. Now
the asset panel's right-click menu has Duplicate.
- The copy lands right below the original and is named the way a new
asset would be ("Crate 2"). It is selected and its tab opens where
it has one. A copied scene does not become the active one.
- One undo step takes it out again. A redo brings back the same id.
- The copy is a deep copy: values, graph, tracks, layers and objects
are its own, and editing it leaves the original alone.
- Frames of a texture or of pixel art get fresh ids, because a sprite
names a frame across the whole document.
- Objects of a scene or container get fresh ids the way pasted ones
do. Parents and object references among them follow the copy.
- Whatever pointed at the original keeps pointing at the original: a
sprite wearing it, an animation's root, a placed object.
Tests:
- 3 new unit tests (DuplicateAssetCommand). One counter-check run:
without renaming the references the scene test fails.
- e2e 04: 2 new checks with the real menu (copy named "Crate 2" right
behind the Crate and selected, one undo removes it).
- Gate: 221 files, 3445 tests, CHECK EXIT 0.
- e2e total 1703 is computed (1701 + 2). Full suite left to CI.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0dda6a012a
commit
4f4c149211
5 files changed
+128
-3
No files matched your search
@@ -5,6 +5,7 @@ import {
|
||||
} from '../../core/commands/animationCommands';
|
||||
import {
|
||||
CreateAssetCommand,
|
||||
DuplicateAssetCommand,
|
||||
SetActiveSceneCommand,
|
||||
SetStartSceneCommand,
|
||||
} from '../../core/commands/assetCommands';
|
||||
@@ -214,6 +215,11 @@ export class AssetPanel extends Panel {
|
||||
if (this.state.execute(command)) this.state.openAsset(command.asset.id);
|
||||
}
|
||||
|
||||
private duplicateAsset(id: string): void {
|
||||
const command = new DuplicateAssetCommand(id);
|
||||
if (this.state.execute(command)) this.state.openAsset(command.copyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* A sprite wearing the texture and an animation over it whose one row keys the frames in order,
|
||||
* one per frame – what a picture sequence is on a timeline. One undo step for all of it.
|
||||
@@ -364,6 +370,7 @@ export class AssetPanel extends Panel {
|
||||
if (asset.type === 'pixelart' && asset.frames.length > 1)
|
||||
items.push({ label: 'Create animation from frames', onSelect: () => this.createAnimation(asset) });
|
||||
}
|
||||
items.push({ label: 'Duplicate', onSelect: () => this.duplicateAsset(id) });
|
||||
items.push({ label: 'Delete…', danger: true, onSelect: () => confirmDeleteAsset(this.state, id) });
|
||||
const menu = new Menu(items);
|
||||
menu.open(x, y);
|
||||
|
||||
Reference in new issue
Block a user