diff --git a/src/sprites/rendered-target.js b/src/sprites/rendered-target.js index 2a6a0f7d3..aa1963480 100644 --- a/src/sprites/rendered-target.js +++ b/src/sprites/rendered-target.js @@ -408,6 +408,17 @@ class RenderedTarget extends Target { this.sprite.costumes.push(costumeObject); } + /** + * Add a costume at the given index, taking care to avoid duplicate names. + * @param {!object} costumeObject Object representing the costume. + * @param {!int} index Index at which to add costume + */ + addCostumeAt (costumeObject, index) { + const usedNames = this.sprite.costumes.map(costume => costume.name); + costumeObject.name = StringUtil.unusedName(costumeObject.name, usedNames); + this.sprite.costumes.splice(index, 0, costumeObject); + } + /** * Rename a costume, taking care to avoid duplicate names. * @param {int} costumeIndex - the index of the costume to be renamed. @@ -458,6 +469,17 @@ class RenderedTarget extends Target { this.runtime.requestTargetsUpdate(this); } + /** + * Add a sound, taking care to avoid duplicate names. + * @param {!object} soundObject Object representing the sound. + * @param {!int} index Index at which to add costume + */ + addSoundAt (soundObject, index) { + const usedNames = this.sprite.sounds.map(sound => sound.name); + soundObject.name = StringUtil.unusedName(soundObject.name, usedNames); + this.sprite.sounds.splice(index, 0, soundObject); + } + /** * Add a sound, taking care to avoid duplicate names. * @param {!object} soundObject Object representing the sound. diff --git a/src/virtual-machine.js b/src/virtual-machine.js index d930ad534..6fdb1d0ec 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -322,11 +322,39 @@ class VirtualMachine extends EventEmitter { return loadCostume(md5ext, costumeObject, this.runtime).then(() => { this.editingTarget.addCostume(costumeObject); this.editingTarget.setCostume( - this.editingTarget.sprite.costumes.length - 1 + this.editingTarget.getCostumes().length - 1 ); }); } + /** + * Duplicate the costume at the given index. Add it at that index + 1. + * @param {!int} costumeIndex Index of costume to duplicate + */ + duplicateCostume (costumeIndex) { + const originalCostume = this.editingTarget.getCostumes()[costumeIndex]; + const clone = Object.assign({}, originalCostume); + const md5ext = `${clone.assetId}.${clone.dataFormat}`; + loadCostume(md5ext, clone, this.runtime).then(() => { + this.editingTarget.addCostumeAt(clone, costumeIndex + 1); + this.editingTarget.setCostume(costumeIndex + 1); + this.emitTargetsUpdate(); + }); + } + + /** + * Duplicate the sound at the given index. Add it at that index + 1. + * @param {!int} soundIndex Index of sound to duplicate + */ + duplicateSound (soundIndex) { + const originalSound = this.editingTarget.getSounds()[soundIndex]; + const clone = Object.assign({}, originalSound); + loadSound(clone, this.runtime).then(() => { + this.editingTarget.addSoundAt(clone, soundIndex + 1); + this.emitTargetsUpdate(); + }); + } + /** * Rename a costume on the current editing target. * @param {int} costumeIndex - the index of the costume to be renamed.