scratch-vm/src/sprites/sprite.js

110 lines
3.5 KiB
JavaScript
Raw Normal View History

2017-04-17 15:10:04 -04:00
const RenderedTarget = require('./rendered-target');
const Blocks = require('../engine/blocks');
2017-09-07 11:51:21 -04:00
const {loadSoundFromAsset} = require('../import/load-sound');
const {loadCostumeFromAsset} = require('../import/load-costume');
const StringUtil = require('../util/string-util');
2017-04-17 19:42:48 -04:00
class Sprite {
/**
2017-04-17 19:42:48 -04:00
* Sprite to be used on the Scratch stage.
* All clones of a sprite have shared blocks, shared costumes, shared variables.
* @param {?Blocks} blocks Shared blocks object for all clones of sprite.
* @param {Runtime} runtime Reference to the runtime.
* @constructor
*/
2017-04-17 19:42:48 -04:00
constructor (blocks, runtime) {
this.runtime = runtime;
if (!blocks) {
// Shared set of blocks for all clones.
blocks = new Blocks();
}
this.blocks = blocks;
/**
* Human-readable name for this sprite (and all clones).
* @type {string}
*/
this.name = '';
/**
* List of costumes for this sprite.
* Each entry is an object, e.g.,
* {
* skinId: 1,
* name: "Costume Name",
* bitmapResolution: 2,
* rotationCenterX: 0,
* rotationCenterY: 0
* }
* @type {Array.<!Object>}
*/
this.costumes = [];
/**
* List of sounds for this sprite.
*/
this.sounds = [];
/**
* List of clones for this sprite, including the original.
* @type {Array.<!RenderedTarget>}
*/
this.clones = [];
}
/**
2017-04-17 19:42:48 -04:00
* Create a clone of this sprite.
* @returns {!RenderedTarget} Newly created clone.
*/
2017-04-17 19:42:48 -04:00
createClone () {
const newClone = new RenderedTarget(this, this.runtime);
newClone.isOriginal = this.clones.length === 0;
this.clones.push(newClone);
if (newClone.isOriginal) {
newClone.initDrawable();
this.runtime.fireTargetWasCreated(newClone);
} else {
this.runtime.fireTargetWasCreated(newClone, this.clones[0]);
2017-04-17 19:42:48 -04:00
}
return newClone;
}
/**
* Disconnect a clone from this sprite. The clone is unmodified.
* In particular, the clone's dispose() method is not called.
* @param {!RenderedTarget} clone - the clone to be removed.
*/
removeClone (clone) {
2017-10-06 13:43:07 -04:00
this.runtime.fireTargetWasRemoved(clone);
const cloneIndex = this.clones.indexOf(clone);
if (cloneIndex >= 0) {
this.clones.splice(cloneIndex, 1);
}
}
2017-09-07 11:51:21 -04:00
duplicate () {
const newSprite = new Sprite(null, this.runtime);
newSprite.blocks = this.blocks.duplicate();
const allNames = this.runtime.targets.map(t => t.name);
newSprite.name = StringUtil.unusedName(this.name, allNames);
const assetPromises = [];
newSprite.costumes = this.costumes.map(costume => {
const newCostume = Object.assign({}, costume);
const costumeAsset = this.runtime.storage.get(costume.assetId);
assetPromises.push(loadCostumeFromAsset(newCostume, costumeAsset, this.runtime));
return newCostume;
});
newSprite.sounds = this.sounds.map(sound => {
const newSound = Object.assign({}, sound);
const soundAsset = this.runtime.storage.get(sound.assetId);
assetPromises.push(loadSoundFromAsset(newSound, soundAsset, this.runtime));
return newSound;
});
return Promise.all(assetPromises).then(() => newSprite);
}
2017-04-17 19:42:48 -04:00
}
module.exports = Sprite;