Merge pull request #257 from paulkaplan/sound-library
Sound library first iteration
This commit is contained in:
commit
c7d7562bb5
7 files changed
+1169
No files matched your search
@@ -17,6 +17,10 @@ class LibraryComponent extends React.Component {
|
||||
// Double select: select as the library's value.
|
||||
this.props.onRequestClose();
|
||||
this.props.onItemSelected(this.props.data[id]);
|
||||
} else {
|
||||
if (this.props.onItemChosen) {
|
||||
this.props.onItemChosen(this.props.data[id]);
|
||||
}
|
||||
}
|
||||
this.setState({selectedItem: id});
|
||||
}
|
||||
@@ -61,6 +65,7 @@ LibraryComponent.propTypes = {
|
||||
})
|
||||
/* eslint-enable react/no-unused-prop-types, lines-around-comment */
|
||||
),
|
||||
onItemChosen: React.PropTypes.func,
|
||||
onItemSelected: React.PropTypes.func,
|
||||
onRequestClose: React.PropTypes.func,
|
||||
title: React.PropTypes.string.isRequired,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1" width="400pt" height="400pt" viewBox="0 0 75 75"><g stroke="#111" stroke-width="5"><path stroke-linejoin="round" fill="#111" d="M39.389 13.769L22.235 28.606H6v19.093h15.989l17.4 15.051V13.769z"/><path d="M48.128 49.03a20.087 20.087 0 0 0-.085-21.453M55.082 20.537a29.86 29.86 0 0 1 5.884 17.84 29.83 29.83 0 0 1-5.788 17.699M61.71 62.611a38.952 38.952 0 0 0 8.418-24.233 38.968 38.968 0 0 0-8.519-24.368" fill="none" stroke-linecap="round"/></g></svg>
|
||||
|
After Width: | Height: | Size: 503 B |
@@ -8,6 +8,7 @@ const VM = require('scratch-vm');
|
||||
const Box = require('../box/box.jsx');
|
||||
const BackdropLibrary = require('../../containers/backdrop-library.jsx');
|
||||
const CostumeLibrary = require('../../containers/costume-library.jsx');
|
||||
const SoundLibrary = require('../../containers/sound-library.jsx');
|
||||
const SpriteLibrary = require('../../containers/sprite-library.jsx');
|
||||
const SpriteSelectorComponent = require('../sprite-selector/sprite-selector.jsx');
|
||||
const StageSelector = require('../../containers/stage-selector.jsx');
|
||||
@@ -36,6 +37,7 @@ class TargetPane extends React.Component {
|
||||
editingTarget,
|
||||
backdropLibraryVisible,
|
||||
costumeLibraryVisible,
|
||||
soundLibraryVisible,
|
||||
spriteLibraryVisible,
|
||||
onChangeSpriteDraggability,
|
||||
onChangeSpriteName,
|
||||
@@ -48,6 +50,7 @@ class TargetPane extends React.Component {
|
||||
onNewBackdropClick,
|
||||
onRequestCloseBackdropLibrary,
|
||||
onRequestCloseCostumeLibrary,
|
||||
onRequestCloseSoundLibrary,
|
||||
onRequestCloseSpriteLibrary,
|
||||
onSelectSprite,
|
||||
stage,
|
||||
@@ -113,6 +116,11 @@ class TargetPane extends React.Component {
|
||||
vm={vm}
|
||||
onRequestClose={onRequestCloseCostumeLibrary}
|
||||
/>
|
||||
<SoundLibrary
|
||||
visible={soundLibraryVisible}
|
||||
vm={vm}
|
||||
onRequestClose={onRequestCloseSoundLibrary}
|
||||
/>
|
||||
<BackdropLibrary
|
||||
visible={backdropLibraryVisible}
|
||||
vm={vm}
|
||||
@@ -154,11 +162,14 @@ TargetPane.propTypes = {
|
||||
onChangeSpriteY: React.PropTypes.func,
|
||||
onDeleteSprite: React.PropTypes.func,
|
||||
onNewBackdropClick: React.PropTypes.func,
|
||||
onNewSoundClick: React.PropTypes.func,
|
||||
onNewSpriteClick: React.PropTypes.func,
|
||||
onRequestCloseBackdropLibrary: React.PropTypes.func,
|
||||
onRequestCloseCostumeLibrary: React.PropTypes.func,
|
||||
onRequestCloseSoundLibrary: React.PropTypes.func,
|
||||
onRequestCloseSpriteLibrary: React.PropTypes.func,
|
||||
onSelectSprite: React.PropTypes.func,
|
||||
soundLibraryVisible: React.PropTypes.bool,
|
||||
spriteLibraryVisible: React.PropTypes.bool,
|
||||
sprites: React.PropTypes.objectOf(spriteShape),
|
||||
stage: spriteShape,
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
const bindAll = require('lodash.bindall');
|
||||
const React = require('react');
|
||||
const VM = require('scratch-vm');
|
||||
const AudioEngine = require('scratch-audio');
|
||||
|
||||
const LibaryComponent = require('../components/library/library.jsx');
|
||||
const soundIcon = require('../components/target-pane/icon--sound-dark.svg');
|
||||
|
||||
const soundLibraryContent = require('../lib/libraries/sounds.json');
|
||||
|
||||
const md5ToUrl = md5 => (`https://cdn.assets.scratch.mit.edu/internalapi/asset/${md5}/get/`);
|
||||
|
||||
class SoundLibrary extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, [
|
||||
'handleItemSelected',
|
||||
'handleItemChosen'
|
||||
]);
|
||||
}
|
||||
componentDidMount () {
|
||||
// @todo lots of architectural questions here
|
||||
// - Should the sound library component own an audio player, or use the VM?
|
||||
// - Should the sound library load up all the sounds or only on demand?
|
||||
// - How can we get a callback for knowing when the sound has been loaded?
|
||||
this.audioEngine = new AudioEngine();
|
||||
this.player = this.audioEngine.createPlayer();
|
||||
this.audioEngine.loadSounds(soundLibraryContent.map(sound => (
|
||||
{
|
||||
fileUrl: md5ToUrl(sound.md5),
|
||||
...sound
|
||||
}
|
||||
)));
|
||||
}
|
||||
handleItemChosen (item) {
|
||||
this.player.playSound(item._md5);
|
||||
}
|
||||
handleItemSelected (item) {
|
||||
// @todo these two props should be handled by a VM.addSound function
|
||||
const nextSoundId = this.props.vm.editingTarget.sprite.sounds.length;
|
||||
const fileUrl = md5ToUrl(item._md5);
|
||||
const vmSound = {
|
||||
fileUrl,
|
||||
format: item.format,
|
||||
md5: item._md5,
|
||||
rate: item.rate,
|
||||
sampleCount: item.sampleCount,
|
||||
soundID: nextSoundId,
|
||||
name: item.name
|
||||
};
|
||||
// @todo awaiting an official VM.addSound function
|
||||
// it will need to both add to sprite and load the sound
|
||||
this.props.vm.editingTarget.sprite.sounds.push(vmSound);
|
||||
this.props.vm.runtime.audioEngine.loadSounds([vmSound]);
|
||||
}
|
||||
render () {
|
||||
// @todo need to use this hack to avoid library using md5 for image
|
||||
const soundLibraryThumbnailData = soundLibraryContent.map(sound => {
|
||||
const {
|
||||
md5,
|
||||
...otherData
|
||||
} = sound;
|
||||
return {
|
||||
_md5: md5,
|
||||
rawURL: soundIcon,
|
||||
...otherData
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<LibaryComponent
|
||||
data={soundLibraryThumbnailData}
|
||||
title="Sound Library"
|
||||
visible={this.props.visible}
|
||||
onItemChosen={this.handleItemChosen}
|
||||
onItemSelected={this.handleItemSelected}
|
||||
onRequestClose={this.props.onRequestClose}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SoundLibrary.propTypes = {
|
||||
onRequestClose: React.PropTypes.func,
|
||||
visible: React.PropTypes.bool,
|
||||
vm: React.PropTypes.instanceOf(VM).isRequired
|
||||
};
|
||||
|
||||
module.exports = SoundLibrary;
|
||||
@@ -5,9 +5,11 @@ const {connect} = require('react-redux');
|
||||
|
||||
const {
|
||||
openBackdropLibrary,
|
||||
openSoundLibrary,
|
||||
openSpriteLibrary,
|
||||
closeBackdropLibrary,
|
||||
closeCostumeLibrary,
|
||||
closeSoundLibrary,
|
||||
closeSpriteLibrary
|
||||
} = require('../reducers/modals');
|
||||
|
||||
@@ -87,6 +89,7 @@ const mapStateToProps = state => ({
|
||||
return sprites;
|
||||
}, {}),
|
||||
stage: state.targets.stage,
|
||||
soundLibraryVisible: state.modals.soundLibrary,
|
||||
spriteLibraryVisible: state.modals.spriteLibrary,
|
||||
costumeLibraryVisible: state.modals.costumeLibrary,
|
||||
backdropLibraryVisible: state.modals.backdropLibrary
|
||||
@@ -96,6 +99,10 @@ const mapDispatchToProps = dispatch => ({
|
||||
e.preventDefault();
|
||||
dispatch(openBackdropLibrary());
|
||||
},
|
||||
onNewSoundClick: e => {
|
||||
e.preventDefault();
|
||||
dispatch(openSoundLibrary());
|
||||
},
|
||||
onNewSpriteClick: e => {
|
||||
e.preventDefault();
|
||||
dispatch(openSpriteLibrary());
|
||||
@@ -106,6 +113,9 @@ const mapDispatchToProps = dispatch => ({
|
||||
onRequestCloseCostumeLibrary: () => {
|
||||
dispatch(closeCostumeLibrary());
|
||||
},
|
||||
onRequestCloseSoundLibrary: () => {
|
||||
dispatch(closeSoundLibrary());
|
||||
},
|
||||
onRequestCloseSpriteLibrary: () => {
|
||||
dispatch(closeSpriteLibrary());
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -3,11 +3,13 @@ const CLOSE_MODAL = 'scratch-gui/modals/CLOSE_MODAL';
|
||||
|
||||
const MODAL_BACKDROP_LIBRARY = 'backdropLibrary';
|
||||
const MODAL_COSTUME_LIBRARY = 'costumeLibrary';
|
||||
const MODAL_SOUND_LIBRARY = 'soundLibrary';
|
||||
const MODAL_SPRITE_LIBRARY = 'spriteLibrary';
|
||||
|
||||
const initialState = {
|
||||
[MODAL_BACKDROP_LIBRARY]: false,
|
||||
[MODAL_COSTUME_LIBRARY]: false,
|
||||
[MODAL_SOUND_LIBRARY]: false,
|
||||
[MODAL_SPRITE_LIBRARY]: false
|
||||
};
|
||||
|
||||
@@ -44,6 +46,9 @@ reducer.openBackdropLibrary = function () {
|
||||
reducer.openCostumeLibrary = function () {
|
||||
return reducer.openModal(MODAL_COSTUME_LIBRARY);
|
||||
};
|
||||
reducer.openSoundLibrary = function () {
|
||||
return reducer.openModal(MODAL_SOUND_LIBRARY);
|
||||
};
|
||||
reducer.openSpriteLibrary = function () {
|
||||
return reducer.openModal(MODAL_SPRITE_LIBRARY);
|
||||
};
|
||||
@@ -56,4 +61,7 @@ reducer.closeCostumeLibrary = function () {
|
||||
reducer.closeSpriteLibrary = function () {
|
||||
return reducer.closeModal(MODAL_SPRITE_LIBRARY);
|
||||
};
|
||||
reducer.closeSoundLibrary = function () {
|
||||
return reducer.closeModal(MODAL_SOUND_LIBRARY);
|
||||
};
|
||||
module.exports = reducer;
|
||||
Reference in new issue
Block a user