diff --git a/src/components/asset-panel/selector.jsx b/src/components/asset-panel/selector.jsx index 3a8df1475df..d5e8f8e12ac 100644 --- a/src/components/asset-panel/selector.jsx +++ b/src/components/asset-panel/selector.jsx @@ -9,12 +9,14 @@ import SortableHOC from '../../lib/sortable-hoc.jsx'; import DragConstants from '../../lib/drag-constants'; import styles from './selector.css'; +import target_types_enum from '../../lib/target_types_enum.js'; const Selector = props => { const { buttons, containerRef, dragType, + targetType, isRtl, items, selectedItemIndex, @@ -48,7 +50,6 @@ const Selector = props => { ); } - return ( { details={item.details} dragPayload={item.dragPayload} dragType={dragType} + targetType={targetType} id={index} index={index} name={item.name} @@ -98,6 +100,7 @@ Selector.propTypes = { })), containerRef: PropTypes.func, dragType: PropTypes.oneOf(Object.keys(DragConstants)), + targetType: PropTypes.oneOf(Object.keys(target_types_enum)), draggingIndex: PropTypes.number, draggingType: PropTypes.oneOf(Object.keys(DragConstants)), isRtl: PropTypes.bool, diff --git a/src/components/robot-selector-item/robot-selector-item.css b/src/components/robot-selector-item/robot-selector-item.css new file mode 100644 index 00000000000..dffc1890231 --- /dev/null +++ b/src/components/robot-selector-item/robot-selector-item.css @@ -0,0 +1,123 @@ +@import "../../css/units.css"; +@import "../../css/colors.css"; + +/* @todo: refactor this class name, and component: `sprite-selector` to `sprite` */ +.sprite-selector-item { + display: flex; + flex-direction: column; + justify-content: flex-start; + position: relative; + + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 0.8rem; + color: $text-primary; + border-width: 2px; + border-style: solid; + border-color: $ui-black-transparent; + border-radius: $space; + + text-align: center; + cursor: pointer; + + user-select: none; +} + +.sprite-selector-item.is-selected { + box-shadow: 0px 0px 0px 4px $motion-transparent; + border: 2px solid $motion-primary; + background: $ui-white; +} + +.sprite-selector-item:hover { + border: 2px solid $motion-primary; + background: $ui-white; +} + +.sprite-selector-item:hover .sprite-image, .is-selected .sprite-image { + filter: drop-shadow(0px 0px 2px $ui-black-transparent); +} + +/* Outer/Inner chicanery is to prevent layouts when sprite image changes */ +.sprite-image-outer { + position: relative; + width: 100%; + height: 100%; + transform: translateZ(0); +} + +.sprite-image-inner { + position: absolute; + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; +} + +.sprite-image { + user-select: none; + pointer-events: none; + max-width: 32px; + max-height: 32px; +} + +.sprite-info { + padding: 0.25rem; + border-bottom-left-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + + font-size: 0.625rem; + color: $text-primary; + user-select: none; +} + +.sprite-name, .sprite-details { + /* + For truncating overflowing text gracefully + Min-width is for a bug: https://css-tricks.com/flexbox-truncated-text + */ + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + min-width: 0; +} + +.sprite-details { + margin-top: 0.125rem; + font-size: 0.5rem; +} + +.is-selected .sprite-info { + background: $motion-primary; + color: $ui-white; +} + +.delete-button { + position: absolute; + top: -.625rem; + z-index: auto; +} + +[dir="ltr"] .delete-button { + right: -.625rem; +} + +[dir="rtl"] .delete-button { + left: -.625rem; +} + +.number { + position: absolute; + top: 0.15rem; + font-size: 0.625rem; + font-weight: bold; + z-index: 2; +} + +[dir="ltr"] .number { + left: 0.15rem; +} + +[dir="rtl"] .number { + right: 0.15rem; +} diff --git a/src/components/robot-selector-item/robot-selector-item.jsx b/src/components/robot-selector-item/robot-selector-item.jsx new file mode 100644 index 00000000000..bbaf546b7fd --- /dev/null +++ b/src/components/robot-selector-item/robot-selector-item.jsx @@ -0,0 +1,67 @@ +import classNames from "classnames"; +import PropTypes from "prop-types"; +import React from "react"; + +import styles from "./robot-selector-item.css"; +import { ContextMenuTrigger } from "react-contextmenu"; + +// react-contextmenu requires unique id to match trigger and context menu +let contextMenuId = 0; + +const SpriteSelectorItem = (props) => { + return ( + + {typeof props.number === "undefined" ? null : ( +
{props.number}
+ )} + {props.costumeURL ? ( +
+
+ +
+
+ ) : null} +
+
{props.name}
+ {props.details ? ( +
{props.details}
+ ) : null} +
+
+ ); +}; + +SpriteSelectorItem.propTypes = { + className: PropTypes.string, + componentRef: PropTypes.func, + costumeURL: PropTypes.string, + details: PropTypes.string, + name: PropTypes.string, + number: PropTypes.number, + onClick: PropTypes.func, + onMouseDown: PropTypes.func, + onMouseEnter: PropTypes.func, + onMouseLeave: PropTypes.func, + preventContextMenu: PropTypes.bool, + selected: PropTypes.bool.isRequired, +}; + +export default SpriteSelectorItem; diff --git a/src/components/sprite-selector-item/sprite-selector-item.jsx b/src/components/sprite-selector-item/sprite-selector-item.jsx index 458df186f94..b16770fe713 100644 --- a/src/components/sprite-selector-item/sprite-selector-item.jsx +++ b/src/components/sprite-selector-item/sprite-selector-item.jsx @@ -1,108 +1,116 @@ -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import React from 'react'; +import classNames from "classnames"; +import PropTypes from "prop-types"; +import React from "react"; -import DeleteButton from '../delete-button/delete-button.jsx'; -import styles from './sprite-selector-item.css'; -import {ContextMenuTrigger} from 'react-contextmenu'; -import {DangerousMenuItem, ContextMenu, MenuItem} from '../context-menu/context-menu.jsx'; -import {FormattedMessage} from 'react-intl'; +import DeleteButton from "../delete-button/delete-button.jsx"; +import styles from "./sprite-selector-item.css"; +import { ContextMenuTrigger } from "react-contextmenu"; +import { + DangerousMenuItem, + ContextMenu, + MenuItem, +} from "../context-menu/context-menu.jsx"; +import { FormattedMessage } from "react-intl"; // react-contextmenu requires unique id to match trigger and context menu let contextMenuId = 0; -const SpriteSelectorItem = props => ( +const SpriteSelectorItem = (props) => { + return ( - {typeof props.number === 'undefined' ? null : ( -
{props.number}
- )} - {props.costumeURL ? ( -
-
- -
-
- ) : null} -
-
{props.name}
- {props.details ? ( -
{props.details}
- ) : null} -
- {(props.selected && props.onDeleteButtonClick) ? ( - {props.number} + )} + {props.costumeURL ? ( +
+
+ - ) : null } - {props.onDuplicateButtonClick || props.onDeleteButtonClick || props.onExportButtonClick ? ( - - {props.onDuplicateButtonClick ? ( - - - - ) : null} - {props.onExportButtonClick ? ( - - - - ) : null } - {props.onDeleteButtonClick ? ( - - - - ) : null } - +
+
+ ) : null} +
+
{props.name}
+ {props.details ? ( +
{props.details}
) : null} +
+ {props.selected && props.onDeleteButtonClick ? ( + + ) : null} + {props.onDuplicateButtonClick || + props.onDeleteButtonClick || + props.onExportButtonClick ? ( + + {props.onDuplicateButtonClick ? ( + + + + ) : null} + {props.onExportButtonClick ? ( + + + + ) : null} + {props.onDeleteButtonClick ? ( + + + + ) : null} + + ) : null}
-); + ); +}; SpriteSelectorItem.propTypes = { - className: PropTypes.string, - componentRef: PropTypes.func, - costumeURL: PropTypes.string, - details: PropTypes.string, - name: PropTypes.string.isRequired, - number: PropTypes.number, - onClick: PropTypes.func, - onDeleteButtonClick: PropTypes.func, - onDuplicateButtonClick: PropTypes.func, - onExportButtonClick: PropTypes.func, - onMouseDown: PropTypes.func, - onMouseEnter: PropTypes.func, - onMouseLeave: PropTypes.func, - preventContextMenu: PropTypes.bool, - selected: PropTypes.bool.isRequired + className: PropTypes.string, + componentRef: PropTypes.func, + costumeURL: PropTypes.string, + details: PropTypes.string, + name: PropTypes.string.isRequired, + number: PropTypes.number, + onClick: PropTypes.func, + onDeleteButtonClick: PropTypes.func, + onDuplicateButtonClick: PropTypes.func, + onExportButtonClick: PropTypes.func, + onMouseDown: PropTypes.func, + onMouseEnter: PropTypes.func, + onMouseLeave: PropTypes.func, + preventContextMenu: PropTypes.bool, + selected: PropTypes.bool.isRequired, }; export default SpriteSelectorItem; diff --git a/src/components/sprite-selector/robot-list.jsx b/src/components/sprite-selector/robot-list.jsx new file mode 100644 index 00000000000..ded90be8ef7 --- /dev/null +++ b/src/components/sprite-selector/robot-list.jsx @@ -0,0 +1,120 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import classNames from 'classnames'; + +import DragConstants from '../../lib/drag-constants'; + +import Box from '../box/box.jsx'; +import RobotSelectorItem from '../../containers/robot-selector-item.jsx'; +import SortableAsset from '../asset-panel/sortable-asset.jsx'; +import ThrottledPropertyHOC from '../../lib/throttled-property-hoc.jsx'; + +import styles from './sprite-selector.css'; + +const ThrottledRobotSelectorItem = ThrottledPropertyHOC('asset', 500)(RobotSelectorItem); + +const RobotList = function (props) { + const { + containerRef, + editingTarget, + draggingIndex, + draggingType, + hoveredTarget, + onSelectSprite, + ordering, + raised, + selectedId, + items + } = props; + const isSpriteDrag = draggingType === DragConstants.SPRITE; + return ( + + + {items.map((sprite, index) => { + // If the sprite has just received a block drop, used for green highlight + const receivedBlocks = ( + hoveredTarget.sprite === sprite.id && + sprite.id !== editingTarget && + hoveredTarget.receivedBlocks + ); + // If the sprite is indicating it can receive block dropping, used for blue highlight + let isRaised = !receivedBlocks && raised && sprite.id !== editingTarget; + + // A sprite is also raised if a costume or sound is being dragged. + // Note the absence of the self-sharing check: a sprite can share assets with itself. + // This is a quirk of 2.0, but seems worth leaving possible, it + // allows quick (albeit unusual) duplication of assets. + isRaised = isRaised || [ + DragConstants.COSTUME, + DragConstants.SOUND, + DragConstants.BACKPACK_COSTUME, + DragConstants.BACKPACK_SOUND, + DragConstants.BACKPACK_CODE].includes(draggingType); + + return ( + {}} + onRemoveSortable={() => {}} + > + + + ); + })} + + + ); +}; + +RobotList.propTypes = { + containerRef: PropTypes.func, + draggingIndex: PropTypes.number, + draggingType: PropTypes.oneOf(Object.keys(DragConstants)), + editingTarget: PropTypes.string, + hoveredTarget: PropTypes.shape({ + hoveredSprite: PropTypes.string, + receivedBlocks: PropTypes.bool, + sprite: PropTypes.string + }), + items: PropTypes.arrayOf(PropTypes.shape({ + costume: PropTypes.shape({ + url: PropTypes.string, + name: PropTypes.string.isRequired, + bitmapResolution: PropTypes.number.isRequired, + rotationCenterX: PropTypes.number.isRequired, + rotationCenterY: PropTypes.number.isRequired + }), + name: PropTypes.string, + })), + onSelectSprite: PropTypes.func, + ordering: PropTypes.arrayOf(PropTypes.number), + raised: PropTypes.bool, + selectedId: PropTypes.string +}; + +export default RobotList; diff --git a/src/components/sprite-selector/sprite-list.jsx b/src/components/sprite-selector/sprite-list.jsx index 3d191029345..c7d87e2e909 100644 --- a/src/components/sprite-selector/sprite-list.jsx +++ b/src/components/sprite-selector/sprite-list.jsx @@ -32,9 +32,7 @@ const SpriteList = function (props) { selectedId, items } = props; - const isSpriteDrag = draggingType === DragConstants.SPRITE; - return ( - - - - sprites[id])} - raised={raised} - selectedId={selectedId} - onDeleteSprite={onDeleteSprite} - onDrop={onDrop} - onDuplicateSprite={onDuplicateSprite} - onExportSprite={onExportSprite} - onSelectSprite={onSelectSprite} - /> - - - ); + const { + editingTarget, + hoveredTarget, + intl, + onChangeSpriteDirection, + onChangeSpriteName, + onChangeSpriteRotationStyle, + onChangeSpriteSize, + onChangeSpriteVisibility, + onChangeSpriteX, + onChangeSpriteY, + onDrop, + onDeleteSprite, + onDuplicateSprite, + onExportSprite, + onFileUploadClick, + onNewSpriteClick, + onPaintSpriteClick, + onSelectSprite, + onSpriteUpload, + onSurpriseSpriteClick, + raised, + selectedId, + spriteFileInput, + sprites, + robot, + stageSize, + ...componentProps + } = props; + let selectedSprite = sprites[selectedId]; + let spriteInfoDisabled = false; + if (selectedId === robot.id) { + selectedSprite = robot; + } + if (typeof selectedSprite === "undefined" || !selectedSprite.name) { + selectedSprite = {}; + spriteInfoDisabled = true; + } + return ( + + +
+
Your robot
+ +
+
+
Your sprites
+ sprites[id])} + raised={raised} + selectedId={selectedId} + onDeleteSprite={onDeleteSprite} + onDrop={onDrop} + onDuplicateSprite={onDuplicateSprite} + onExportSprite={onExportSprite} + onSelectSprite={onSelectSprite} + /> + +
+ ); }; SpriteSelectorComponent.propTypes = { - editingTarget: PropTypes.string, - hoveredTarget: PropTypes.shape({ - hoveredSprite: PropTypes.string, - receivedBlocks: PropTypes.bool - }), - intl: intlShape.isRequired, - onChangeSpriteDirection: PropTypes.func, - onChangeSpriteName: PropTypes.func, - onChangeSpriteRotationStyle: PropTypes.func, - onChangeSpriteSize: PropTypes.func, - onChangeSpriteVisibility: PropTypes.func, - onChangeSpriteX: PropTypes.func, - onChangeSpriteY: PropTypes.func, - onDeleteSprite: PropTypes.func, - onDrop: PropTypes.func, - onDuplicateSprite: PropTypes.func, - onExportSprite: PropTypes.func, - onFileUploadClick: PropTypes.func, - onNewSpriteClick: PropTypes.func, - onPaintSpriteClick: PropTypes.func, - onSelectSprite: PropTypes.func, - onSpriteUpload: PropTypes.func, - onSurpriseSpriteClick: PropTypes.func, - raised: PropTypes.bool, - selectedId: PropTypes.string, - spriteFileInput: PropTypes.func, - sprites: PropTypes.shape({ - id: PropTypes.shape({ - costume: PropTypes.shape({ - url: PropTypes.string, - name: PropTypes.string.isRequired, - bitmapResolution: PropTypes.number.isRequired, - rotationCenterX: PropTypes.number.isRequired, - rotationCenterY: PropTypes.number.isRequired - }), - name: PropTypes.string.isRequired, - order: PropTypes.number.isRequired - }) + editingTarget: PropTypes.string, + hoveredTarget: PropTypes.shape({ + hoveredSprite: PropTypes.string, + receivedBlocks: PropTypes.bool, + }), + intl: intlShape.isRequired, + onChangeSpriteDirection: PropTypes.func, + onChangeSpriteName: PropTypes.func, + onChangeSpriteRotationStyle: PropTypes.func, + onChangeSpriteSize: PropTypes.func, + onChangeSpriteVisibility: PropTypes.func, + onChangeSpriteX: PropTypes.func, + onChangeSpriteY: PropTypes.func, + onDeleteSprite: PropTypes.func, + onDrop: PropTypes.func, + onDuplicateSprite: PropTypes.func, + onExportSprite: PropTypes.func, + onFileUploadClick: PropTypes.func, + onNewSpriteClick: PropTypes.func, + onPaintSpriteClick: PropTypes.func, + onSelectSprite: PropTypes.func, + onSpriteUpload: PropTypes.func, + onSurpriseSpriteClick: PropTypes.func, + raised: PropTypes.bool, + selectedId: PropTypes.string, + spriteFileInput: PropTypes.func, + robot: PropTypes.any, + sprites: PropTypes.shape({ + id: PropTypes.shape({ + costume: PropTypes.shape({ + url: PropTypes.string, + name: PropTypes.string.isRequired, + bitmapResolution: PropTypes.number.isRequired, + rotationCenterX: PropTypes.number.isRequired, + rotationCenterY: PropTypes.number.isRequired, + }), + name: PropTypes.string.isRequired, + order: PropTypes.number.isRequired, }), - stageSize: PropTypes.oneOf(Object.keys(STAGE_DISPLAY_SIZES)).isRequired + }), + stageSize: PropTypes.oneOf(Object.keys(STAGE_DISPLAY_SIZES)).isRequired, }; export default injectIntl(SpriteSelectorComponent); diff --git a/src/components/target-pane/target-pane.jsx b/src/components/target-pane/target-pane.jsx index bffb876e888..86604b8483a 100644 --- a/src/components/target-pane/target-pane.jsx +++ b/src/components/target-pane/target-pane.jsx @@ -44,6 +44,7 @@ const TargetPane = ({ stage, stageSize, sprites, + robot, vm, ...componentProps }) => ( @@ -59,6 +60,7 @@ const TargetPane = ({ selectedId={editingTarget} spriteFileInput={fileInputRef} sprites={sprites} + robot={robot} stageSize={stageSize} onChangeSpriteDirection={onChangeSpriteDirection} onChangeSpriteName={onChangeSpriteName} @@ -153,6 +155,7 @@ TargetPane.propTypes = { raiseSprites: PropTypes.bool, spriteLibraryVisible: PropTypes.bool, sprites: PropTypes.objectOf(spriteShape), + robot: spriteShape, stage: spriteShape, stageSize: PropTypes.oneOf(Object.keys(STAGE_DISPLAY_SIZES)).isRequired, vm: PropTypes.instanceOf(VM) diff --git a/src/components/watermark/watermark.css b/src/components/watermark/watermark.css index ce3d99d4dcf..ce4a6b3b8cb 100644 --- a/src/components/watermark/watermark.css +++ b/src/components/watermark/watermark.css @@ -1,3 +1,7 @@ +.container { + display: flex; + flex-direction: column; +} .sprite-image { margin: auto; @@ -7,3 +11,8 @@ opacity: 0.35; } +.watermark-space-msg { + margin: 0; + font-size: 8px; + color: #aaa; +} diff --git a/src/components/watermark/watermark.jsx b/src/components/watermark/watermark.jsx index 1579fdbbeb9..1b18448b555 100644 --- a/src/components/watermark/watermark.jsx +++ b/src/components/watermark/watermark.jsx @@ -1,17 +1,35 @@ -import PropTypes from 'prop-types'; -import React from 'react'; +import PropTypes from "prop-types"; +import React from "react"; +import target_types_enum from "../../lib/target_types_enum.js"; +import styles from "./watermark.css"; -import styles from './watermark.css'; +const Watermark = (props) => { + let targetTypeMsg; + switch (props.targetType) { + case target_types_enum.robot: + targetTypeMsg = "Robot space"; + break; + case target_types_enum.sprite: + targetTypeMsg = "Sprite space"; + break; + case target_types_enum.stage: + targetTypeMsg = "Stage space"; + break; + default: + targetTypeMsg = ""; + break; + } -const Watermark = props => ( - -); + return ( +
+

{targetTypeMsg}

+ +
+ ); +}; Watermark.propTypes = { - costumeURL: PropTypes.string, + costumeURL: PropTypes.string, }; export default Watermark; diff --git a/src/containers/blocks.jsx b/src/containers/blocks.jsx index b659cc7145c..a43ccec8e06 100644 --- a/src/containers/blocks.jsx +++ b/src/containers/blocks.jsx @@ -339,7 +339,7 @@ class Blocks extends React.Component { const targetCostumes = target.getCostumes(); const targetSounds = target.getSounds(); const dynamicBlocksXML = this.props.vm.runtime.getBlocksXML(); - return makeToolboxXML(target.isStage, target.id, dynamicBlocksXML, + return makeToolboxXML(target.targetType, target.id, dynamicBlocksXML, targetCostumes[targetCostumes.length - 1].name, stageCostumes[stageCostumes.length - 1].name, targetSounds.length > 0 ? targetSounds[targetSounds.length - 1].name : '' diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index 6be2cf26849..2f4e69484ac 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -329,6 +329,7 @@ class CostumeTab extends React.Component { } ]} dragType={DragConstants.COSTUME} + targetType={target.targetType} isRtl={isRtl} items={costumeData} selectedItemIndex={this.state.selectedCostumeIndex} diff --git a/src/containers/robot-selector-item.jsx b/src/containers/robot-selector-item.jsx new file mode 100644 index 00000000000..2729db1c556 --- /dev/null +++ b/src/containers/robot-selector-item.jsx @@ -0,0 +1,120 @@ +import bindAll from 'lodash.bindall'; +import PropTypes from 'prop-types'; +import React from 'react'; +import {connect} from 'react-redux'; + +import {setHoveredSprite} from '../reducers/hovered-target'; +import {updateAssetDrag} from '../reducers/asset-drag'; +import storage from '../lib/storage'; +import VM from 'scratch-vm'; +import getCostumeUrl from '../lib/get-costume-url'; +import DragRecognizer from '../lib/drag-recognizer'; + +import RobotSelectorItemComponent from '../components/robot-selector-item/robot-selector-item.jsx'; + +class SpriteSelectorItem extends React.PureComponent { + constructor (props) { + super(props); + bindAll(this, [ + 'getCostumeData', + 'setRef', + 'handleClick', + ]); + + this.dragRecognizer = new DragRecognizer({ + onDrag: this.handleDrag, + onDragEnd: this.handleDragEnd + }); + } + componentDidMount () { + document.addEventListener('touchend', this.handleTouchEnd); + } + componentWillUnmount () { + document.removeEventListener('touchend', this.handleTouchEnd); + this.dragRecognizer.reset(); + } + getCostumeData () { + if (this.props.costumeURL) return this.props.costumeURL; + if (!this.props.asset) return null; + + return getCostumeUrl(this.props.asset); + } + handleClick (e) { + e.preventDefault(); + if (!this.noClick) { + this.props.onClick(this.props); + } + } + setRef (component) { + // Access the DOM node using .elem because it is going through ContextMenuTrigger + this.ref = component && component.elem; + } + render () { + const { + /* eslint-disable no-unused-vars */ + asset, + id, + index, + onClick, + dragPayload, + receivedBlocks, + costumeURL, + vm, + /* eslint-enable no-unused-vars */ + ...props + } = this.props; + return ( + + ); + } +} + +SpriteSelectorItem.propTypes = { + asset: PropTypes.instanceOf(storage.Asset), + costumeURL: PropTypes.string, + dispatchSetHoveredSprite: PropTypes.func.isRequired, + dragPayload: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + dragType: PropTypes.string, + targetType: PropTypes.string, + dragging: PropTypes.bool, + id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + index: PropTypes.number, + name: PropTypes.string, + onClick: PropTypes.func, + onDeleteButtonClick: PropTypes.func, + onDrag: PropTypes.func.isRequired, + onDuplicateButtonClick: PropTypes.func, + onExportButtonClick: PropTypes.func, + receivedBlocks: PropTypes.bool.isRequired, + selected: PropTypes.bool, + vm: PropTypes.instanceOf(VM).isRequired +}; + +const mapStateToProps = (state, {id}) => ({ + dragging: state.scratchGui.assetDrag.dragging, + receivedBlocks: state.scratchGui.hoveredTarget.receivedBlocks && + state.scratchGui.hoveredTarget.sprite === id, + vm: state.scratchGui.vm +}); +const mapDispatchToProps = dispatch => ({ + dispatchSetHoveredSprite: spriteId => { + dispatch(setHoveredSprite(spriteId)); + }, + onDrag: data => dispatch(updateAssetDrag(data)) +}); + +const ConnectedComponent = connect( + mapStateToProps, + mapDispatchToProps +)(SpriteSelectorItem); + +export default ConnectedComponent; diff --git a/src/containers/sprite-selector-item.jsx b/src/containers/sprite-selector-item.jsx index f946cf83f1d..e8d85dd68f3 100644 --- a/src/containers/sprite-selector-item.jsx +++ b/src/containers/sprite-selector-item.jsx @@ -39,6 +39,7 @@ class SpriteSelectorItem extends React.PureComponent { componentDidMount () { document.addEventListener('touchend', this.handleTouchEnd); } + componentWillUnmount () { document.removeEventListener('touchend', this.handleTouchEnd); this.dragRecognizer.reset(); @@ -87,7 +88,7 @@ class SpriteSelectorItem extends React.PureComponent { handleClick (e) { e.preventDefault(); if (!this.noClick) { - this.props.onClick(this.props.id); + this.props.onClick(this.props); } } handleDelete (e) { @@ -129,6 +130,7 @@ class SpriteSelectorItem extends React.PureComponent { /* eslint-enable no-unused-vars */ ...props } = this.props; + return ( restoreSprite().then(this.handleActivateBlocksTab); + constructor(props) { + super(props); + bindAll(this, [ + "handleActivateBlocksTab", + "handleBlockDragEnd", + "handleChangeSpriteRotationStyle", + "handleChangeSpriteDirection", + "handleChangeSpriteName", + "handleChangeSpriteSize", + "handleChangeSpriteVisibility", + "handleChangeSpriteX", + "handleChangeSpriteY", + "handleDeleteSprite", + "handleDrop", + "handleDuplicateSprite", + "handleExportSprite", + "handleNewSprite", + "handleSelectSprite", + "handleSurpriseSpriteClick", + "handlePaintSpriteClick", + "handleFileUploadClick", + "handleSpriteUpload", + "setFileInput", + ]); + } + componentDidMount() { + this.props.vm.addListener("BLOCK_DRAG_END", this.handleBlockDragEnd); + } + componentWillUnmount() { + this.props.vm.removeListener("BLOCK_DRAG_END", this.handleBlockDragEnd); + } + handleChangeSpriteDirection(direction) { + this.props.vm.postSpriteInfo({ direction }); + } + handleChangeSpriteRotationStyle(rotationStyle) { + this.props.vm.postSpriteInfo({ rotationStyle }); + } + handleChangeSpriteName(name) { + this.props.vm.renameSprite(this.props.editingTarget, name); + } + handleChangeSpriteSize(size) { + this.props.vm.postSpriteInfo({ size }); + } + handleChangeSpriteVisibility(visible) { + this.props.vm.postSpriteInfo({ visible }); + } + handleChangeSpriteX(x) { + this.props.vm.postSpriteInfo({ x }); + } + handleChangeSpriteY(y) { + this.props.vm.postSpriteInfo({ y }); + } + handleDeleteSprite(id) { + const restoreSprite = this.props.vm.deleteSprite(id); + const restoreFun = () => restoreSprite().then(this.handleActivateBlocksTab); - this.props.dispatchUpdateRestore({ - restoreFun: restoreFun, - deletedItem: 'Sprite' - }); + this.props.dispatchUpdateRestore({ + restoreFun: restoreFun, + deletedItem: "Sprite", + }); + } + handleDuplicateSprite(id) { + this.props.vm.duplicateSprite(id); + } + handleExportSprite(id) { + const spriteName = this.props.vm.runtime.getTargetById(id).getName(); + const saveLink = document.createElement("a"); + document.body.appendChild(saveLink); + this.props.vm.exportSprite(id).then((content) => { + downloadBlob(`${spriteName}.sprite3`, content); + }); + } + handleSelectSprite(target) { + this.props.vm.setEditingTarget(target.id); + // making sure we highlight the target only if it's a sprite + if ((this.props.stage && target.id !== this.props.stage.id) && target.targetType !== target_types_enum.robot) { + this.props.onHighlightTarget(target.id); } - handleDuplicateSprite (id) { - this.props.vm.duplicateSprite(id); - } - handleExportSprite (id) { - const spriteName = this.props.vm.runtime.getTargetById(id).getName(); - const saveLink = document.createElement('a'); - document.body.appendChild(saveLink); - - this.props.vm.exportSprite(id).then(content => { - downloadBlob(`${spriteName}.sprite3`, content); - }); - } - handleSelectSprite (id) { - this.props.vm.setEditingTarget(id); - if (this.props.stage && id !== this.props.stage.id) { - this.props.onHighlightTarget(id); - } - } - handleSurpriseSpriteClick () { - const surpriseSprites = spriteLibraryContent.filter(sprite => - (sprite.tags.indexOf('letters') === -1) && (sprite.tags.indexOf('numbers') === -1) + } + handleSurpriseSpriteClick() { + const surpriseSprites = spriteLibraryContent.filter( + (sprite) => + sprite.tags.indexOf("letters") === -1 && + sprite.tags.indexOf("numbers") === -1 + ); + const item = + surpriseSprites[Math.floor(Math.random() * surpriseSprites.length)]; + randomizeSpritePosition(item); + this.props.vm + .addSprite(JSON.stringify(item.json)) + .then(this.handleActivateBlocksTab); + } + handlePaintSpriteClick() { + const formatMessage = this.props.intl.formatMessage; + const emptyItem = emptySprite( + formatMessage(sharedMessages.sprite, { index: 1 }), + formatMessage(sharedMessages.pop), + formatMessage(sharedMessages.costume, { index: 1 }) + ); + this.props.vm.addSprite(JSON.stringify(emptyItem)).then(() => { + setTimeout(() => { + // Wait for targets update to propagate before tab switching + this.props.onActivateTab(COSTUMES_TAB_INDEX); + }); + }); + } + handleActivateBlocksTab() { + this.props.onActivateTab(BLOCKS_TAB_INDEX); + } + handleNewSprite(spriteJSONString) { + return this.props.vm + .addSprite(spriteJSONString) + .then(this.handleActivateBlocksTab); + } + handleFileUploadClick() { + this.fileInput.click(); + } + handleSpriteUpload(e) { + const storage = this.props.vm.runtime.storage; + this.props.onShowImporting(); + handleFileUpload( + e.target, + (buffer, fileType, fileName, fileIndex, fileCount) => { + spriteUpload( + buffer, + fileType, + fileName, + storage, + (newSprite) => { + this.handleNewSprite(newSprite) + .then(() => { + if (fileIndex === fileCount - 1) { + this.props.onCloseImporting(); + } + }) + .catch(this.props.onCloseImporting); + }, + this.props.onCloseImporting ); - const item = surpriseSprites[Math.floor(Math.random() * surpriseSprites.length)]; - randomizeSpritePosition(item); - this.props.vm.addSprite(JSON.stringify(item.json)) - .then(this.handleActivateBlocksTab); + }, + this.props.onCloseImporting + ); + } + setFileInput(input) { + this.fileInput = input; + } + handleBlockDragEnd(blocks) { + if ( + this.props.hoveredTarget.sprite && + this.props.hoveredTarget.sprite !== this.props.editingTarget + ) { + this.props.vm.shareBlocksToTarget( + blocks, + this.props.hoveredTarget.sprite, + this.props.editingTarget + ); + this.props.onReceivedBlocks(true); } - handlePaintSpriteClick () { - const formatMessage = this.props.intl.formatMessage; - const emptyItem = emptySprite( - formatMessage(sharedMessages.sprite, {index: 1}), - formatMessage(sharedMessages.pop), - formatMessage(sharedMessages.costume, {index: 1}) + } + handleDrop(dragInfo) { + const { sprite: targetId } = this.props.hoveredTarget; + if (dragInfo.dragType === DragConstants.SPRITE) { + // Add one to both new and target index because we are not counting/moving the stage + this.props.vm.reorderTarget(dragInfo.index + 1, dragInfo.newIndex + 1); + } else if (dragInfo.dragType === DragConstants.BACKPACK_SPRITE) { + // TODO storage does not have a way of loading zips right now, and may never need it. + // So for now just grab the zip manually. + fetchSprite(dragInfo.payload.bodyUrl).then((sprite3Zip) => + this.props.vm.addSprite(sprite3Zip) + ); + } else if (targetId) { + // Something is being dragged over one of the sprite tiles or the backdrop. + // Dropping assets like sounds and costumes duplicate the asset on the + // hovered target. Shared costumes also become the current costume on that target. + // However, dropping does not switch the editing target or activate that editor tab. + // This is based on 2.0 behavior, but seems like it keeps confusing switching to a minimum. + // it allows the user to share multiple things without switching back and forth. + if (dragInfo.dragType === DragConstants.COSTUME) { + this.props.vm.shareCostumeToTarget(dragInfo.index, targetId); + } else if (targetId && dragInfo.dragType === DragConstants.SOUND) { + this.props.vm.shareSoundToTarget(dragInfo.index, targetId); + } else if (dragInfo.dragType === DragConstants.BACKPACK_COSTUME) { + // In scratch 2, this only creates a new sprite from the costume. + // We may be able to handle both kinds of drops, depending on where + // the drop happens. For now, just add the costume. + this.props.vm.addCostume( + dragInfo.payload.body, + { + name: dragInfo.payload.name, + }, + targetId ); - this.props.vm.addSprite(JSON.stringify(emptyItem)).then(() => { - setTimeout(() => { // Wait for targets update to propagate before tab switching - this.props.onActivateTab(COSTUMES_TAB_INDEX); - }); - }); - } - handleActivateBlocksTab () { - this.props.onActivateTab(BLOCKS_TAB_INDEX); - } - handleNewSprite (spriteJSONString) { - return this.props.vm.addSprite(spriteJSONString) - .then(this.handleActivateBlocksTab); - } - handleFileUploadClick () { - this.fileInput.click(); - } - handleSpriteUpload (e) { - const storage = this.props.vm.runtime.storage; - this.props.onShowImporting(); - handleFileUpload(e.target, (buffer, fileType, fileName, fileIndex, fileCount) => { - spriteUpload(buffer, fileType, fileName, storage, newSprite => { - this.handleNewSprite(newSprite) - .then(() => { - if (fileIndex === fileCount - 1) { - this.props.onCloseImporting(); - } - }) - .catch(this.props.onCloseImporting); - }, this.props.onCloseImporting); - }, this.props.onCloseImporting); - } - setFileInput (input) { - this.fileInput = input; - } - handleBlockDragEnd (blocks) { - if (this.props.hoveredTarget.sprite && this.props.hoveredTarget.sprite !== this.props.editingTarget) { - this.props.vm.shareBlocksToTarget(blocks, this.props.hoveredTarget.sprite, this.props.editingTarget); - this.props.onReceivedBlocks(true); - } - } - handleDrop (dragInfo) { - const {sprite: targetId} = this.props.hoveredTarget; - if (dragInfo.dragType === DragConstants.SPRITE) { - // Add one to both new and target index because we are not counting/moving the stage - this.props.vm.reorderTarget(dragInfo.index + 1, dragInfo.newIndex + 1); - } else if (dragInfo.dragType === DragConstants.BACKPACK_SPRITE) { - // TODO storage does not have a way of loading zips right now, and may never need it. - // So for now just grab the zip manually. - fetchSprite(dragInfo.payload.bodyUrl) - .then(sprite3Zip => this.props.vm.addSprite(sprite3Zip)); - } else if (targetId) { - // Something is being dragged over one of the sprite tiles or the backdrop. - // Dropping assets like sounds and costumes duplicate the asset on the - // hovered target. Shared costumes also become the current costume on that target. - // However, dropping does not switch the editing target or activate that editor tab. - // This is based on 2.0 behavior, but seems like it keeps confusing switching to a minimum. - // it allows the user to share multiple things without switching back and forth. - if (dragInfo.dragType === DragConstants.COSTUME) { - this.props.vm.shareCostumeToTarget(dragInfo.index, targetId); - } else if (targetId && dragInfo.dragType === DragConstants.SOUND) { - this.props.vm.shareSoundToTarget(dragInfo.index, targetId); - } else if (dragInfo.dragType === DragConstants.BACKPACK_COSTUME) { - // In scratch 2, this only creates a new sprite from the costume. - // We may be able to handle both kinds of drops, depending on where - // the drop happens. For now, just add the costume. - this.props.vm.addCostume(dragInfo.payload.body, { - name: dragInfo.payload.name - }, targetId); - } else if (dragInfo.dragType === DragConstants.BACKPACK_SOUND) { - this.props.vm.addSound({ - md5: dragInfo.payload.body, - name: dragInfo.payload.name - }, targetId); - } else if (dragInfo.dragType === DragConstants.BACKPACK_CODE) { - fetchCode(dragInfo.payload.bodyUrl) - .then(blocks => { - this.props.vm.shareBlocksToTarget(blocks, targetId); - this.props.vm.refreshWorkspace(); - }); - } - } - } - render () { - const { - onActivateTab, // eslint-disable-line no-unused-vars - onReceivedBlocks, // eslint-disable-line no-unused-vars - onHighlightTarget, // eslint-disable-line no-unused-vars - dispatchUpdateRestore, // eslint-disable-line no-unused-vars - onShowImporting, // eslint-disable-line no-unused-vars - onCloseImporting, // eslint-disable-line no-unused-vars - ...componentProps - } = this.props; - return ( - + } else if (dragInfo.dragType === DragConstants.BACKPACK_SOUND) { + this.props.vm.addSound( + { + md5: dragInfo.payload.body, + name: dragInfo.payload.name, + }, + targetId ); + } else if (dragInfo.dragType === DragConstants.BACKPACK_CODE) { + fetchCode(dragInfo.payload.bodyUrl).then((blocks) => { + this.props.vm.shareBlocksToTarget(blocks, targetId); + this.props.vm.refreshWorkspace(); + }); + } } + } + render() { + const { + onActivateTab, // eslint-disable-line no-unused-vars + onReceivedBlocks, // eslint-disable-line no-unused-vars + onHighlightTarget, // eslint-disable-line no-unused-vars + dispatchUpdateRestore, // eslint-disable-line no-unused-vars + onShowImporting, // eslint-disable-line no-unused-vars + onCloseImporting, // eslint-disable-line no-unused-vars + ...componentProps + } = this.props; + + return ( + + ); + } } const { - onSelectSprite, // eslint-disable-line no-unused-vars - onActivateBlocksTab, // eslint-disable-line no-unused-vars - ...targetPaneProps + onSelectSprite, // eslint-disable-line no-unused-vars + onActivateBlocksTab, // eslint-disable-line no-unused-vars + ...targetPaneProps } = TargetPaneComponent.propTypes; TargetPane.propTypes = { - intl: intlShape.isRequired, - onCloseImporting: PropTypes.func, - onShowImporting: PropTypes.func, - ...targetPaneProps + intl: intlShape.isRequired, + onCloseImporting: PropTypes.func, + onShowImporting: PropTypes.func, + ...targetPaneProps, }; -const mapStateToProps = state => ({ - editingTarget: state.scratchGui.targets.editingTarget, - hoveredTarget: state.scratchGui.hoveredTarget, - sprites: state.scratchGui.targets.sprites, - stage: state.scratchGui.targets.stage, - raiseSprites: state.scratchGui.blockDrag, - spriteLibraryVisible: state.scratchGui.modals.spriteLibrary +const mapStateToProps = (state) => ({ + editingTarget: state.scratchGui.targets.editingTarget, + hoveredTarget: state.scratchGui.hoveredTarget, + sprites: state.scratchGui.targets.sprites, + robot: state.scratchGui.targets.robot, + stage: state.scratchGui.targets.stage, + raiseSprites: state.scratchGui.blockDrag, + spriteLibraryVisible: state.scratchGui.modals.spriteLibrary, }); -const mapDispatchToProps = dispatch => ({ - onNewSpriteClick: e => { - e.preventDefault(); - dispatch(openSpriteLibrary()); - }, - onRequestCloseSpriteLibrary: () => { - dispatch(closeSpriteLibrary()); - }, - onActivateTab: tabIndex => { - dispatch(activateTab(tabIndex)); - }, - onReceivedBlocks: receivedBlocks => { - dispatch(setReceivedBlocks(receivedBlocks)); - }, - dispatchUpdateRestore: restoreState => { - dispatch(setRestore(restoreState)); - }, - onHighlightTarget: id => { - dispatch(highlightTarget(id)); - }, - onCloseImporting: () => dispatch(closeAlertWithId('importingAsset')), - onShowImporting: () => dispatch(showStandardAlert('importingAsset')) +const mapDispatchToProps = (dispatch) => ({ + onNewSpriteClick: (e) => { + e.preventDefault(); + dispatch(openSpriteLibrary()); + }, + onRequestCloseSpriteLibrary: () => { + dispatch(closeSpriteLibrary()); + }, + onActivateTab: (tabIndex) => { + dispatch(activateTab(tabIndex)); + }, + onReceivedBlocks: (receivedBlocks) => { + dispatch(setReceivedBlocks(receivedBlocks)); + }, + dispatchUpdateRestore: (restoreState) => { + dispatch(setRestore(restoreState)); + }, + onHighlightTarget: (id) => { + dispatch(highlightTarget(id)); + }, + onCloseImporting: () => dispatch(closeAlertWithId("importingAsset")), + onShowImporting: () => dispatch(showStandardAlert("importingAsset")), }); -export default injectIntl(connect( - mapStateToProps, - mapDispatchToProps -)(TargetPane)); +export default injectIntl( + connect(mapStateToProps, mapDispatchToProps)(TargetPane) +); diff --git a/src/containers/watermark.jsx b/src/containers/watermark.jsx index fcb08ead285..de2f446bf2d 100644 --- a/src/containers/watermark.jsx +++ b/src/containers/watermark.jsx @@ -1,71 +1,74 @@ -import bindAll from 'lodash.bindall'; -import omit from 'lodash.omit'; -import PropTypes from 'prop-types'; -import React from 'react'; -import {connect} from 'react-redux'; +import bindAll from "lodash.bindall"; +import omit from "lodash.omit"; +import PropTypes from "prop-types"; +import React from "react"; +import { connect } from "react-redux"; -import ThrottledPropertyHOC from '../lib/throttled-property-hoc.jsx'; +import ThrottledPropertyHOC from "../lib/throttled-property-hoc.jsx"; -import VM from 'scratch-vm'; -import storage from '../lib/storage'; -import getCostumeUrl from '../lib/get-costume-url'; +import VM from "scratch-vm"; +import storage from "../lib/storage"; +import getCostumeUrl from "../lib/get-costume-url"; -import WatermarkComponent from '../components/watermark/watermark.jsx'; +import WatermarkComponent from "../components/watermark/watermark.jsx"; class Watermark extends React.Component { - constructor (props) { - super(props); - bindAll(this, [ - 'getCostumeData' - ]); - } + constructor(props) { + super(props); + bindAll(this, ["getCostumeData"]); + } - getCostumeData () { - if (!this.props.asset) return null; + getCostumeData() { + if (!this.props.asset) return null; - return getCostumeUrl(this.props.asset); - } + return getCostumeUrl(this.props.asset); + } - render () { - const componentProps = omit(this.props, ['asset', 'vm']); - return ( - - ); - } + render() { + const componentProps = omit(this.props, ["asset", "vm"]); + return ( + + ); + } } Watermark.propTypes = { - asset: PropTypes.instanceOf(storage.Asset), - vm: PropTypes.instanceOf(VM).isRequired + asset: PropTypes.instanceOf(storage.Asset), + vm: PropTypes.instanceOf(VM).isRequired, }; -const mapStateToProps = state => { - const targets = state.scratchGui.targets; - const currentTargetId = targets.editingTarget; +const mapStateToProps = (state) => { + const targets = state.scratchGui.targets; + const currentTargetId = targets.editingTarget; - let asset; - if (currentTargetId) { - if (targets.stage.id === currentTargetId) { - asset = targets.stage.costume.asset; - } else if (targets.sprites.hasOwnProperty(currentTargetId)) { - const currentSprite = targets.sprites[currentTargetId]; - asset = currentSprite.costume.asset; - } + let targetType; + let asset; + if (currentTargetId) { + if (targets.stage.id === currentTargetId) { + asset = targets.stage.costume.asset; + targetType = targets.stage.targetType; + } else if (targets.sprites.hasOwnProperty(currentTargetId)) { + const currentSprite = targets.sprites[currentTargetId]; + asset = currentSprite.costume.asset; + targetType = currentSprite.targetType; + } else if (targets.robot.id === currentTargetId) { + asset = targets.robot.costume.asset; + targetType = targets.robot.targetType; } + } - return { - vm: state.scratchGui.vm, - asset: asset - }; + return { + vm: state.scratchGui.vm, + asset: asset, + targetType: targetType, + }; }; -const ConnectedComponent = connect( - mapStateToProps -)( - ThrottledPropertyHOC('asset', 500)(Watermark) +const ConnectedComponent = connect(mapStateToProps)( + ThrottledPropertyHOC("asset", 500)(Watermark) ); export default ConnectedComponent; diff --git a/src/lib/default-project/8e41346f9e386948096815a9b5d6b3e1-.svg b/src/lib/default-project/8e41346f9e386948096815a9b5d6b3e1-.svg new file mode 100644 index 00000000000..993e0d1fe26 --- /dev/null +++ b/src/lib/default-project/8e41346f9e386948096815a9b5d6b3e1-.svg @@ -0,0 +1,1088 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/lib/default-project/8e41346f9e386948096815a9b5d6b3e1.svg b/src/lib/default-project/8e41346f9e386948096815a9b5d6b3e1.svg new file mode 100644 index 00000000000..86b41a94897 --- /dev/null +++ b/src/lib/default-project/8e41346f9e386948096815a9b5d6b3e1.svg @@ -0,0 +1,1531 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/lib/default-project/index.js b/src/lib/default-project/index.js index 487d457ca36..bb256b03928 100644 --- a/src/lib/default-project/index.js +++ b/src/lib/default-project/index.js @@ -3,6 +3,7 @@ import projectData from './project-data'; /* eslint-disable import/no-unresolved */ import backdrop from '!raw-loader!./cd21514d0531fdffb22204e0ec5ed84a.svg'; import costume1 from '!raw-loader!./8e41346f9e386948096815a9b5d6b3e0.svg'; +import costume2 from '!raw-loader!./8e41346f9e386948096815a9b5d6b3e1.svg'; /* eslint-enable import/no-unresolved */ const defaultProject = translator => { @@ -31,6 +32,12 @@ const defaultProject = translator => { assetType: 'ImageVector', dataFormat: 'SVG', data: encoder.encode(costume1) + }, + { + id: '8e41346f9e386948096815a9b5d6b3e1', + assetType: 'ImageVector', + dataFormat: 'SVG', + data: encoder.encode(costume2) }]; }; diff --git a/src/lib/default-project/project-data.js b/src/lib/default-project/project-data.js index 67c69990794..0deea97c1eb 100644 --- a/src/lib/default-project/project-data.js +++ b/src/lib/default-project/project-data.js @@ -1,5 +1,6 @@ import {defineMessages} from 'react-intl'; import sharedMessages from '../shared-messages'; +import targetTypes from "../target_types_enum"; let messages = defineMessages({ meow: { @@ -30,6 +31,7 @@ const projectData = translateFunction => { targets: [ { isStage: true, + targetType: targetTypes.stage, name: 'Stage', variables: { '`jEk@4|i[#Fk?(8x)AV.-my variable': [ @@ -57,7 +59,39 @@ const projectData = translateFunction => { }, { isStage: false, - name: 'Marty',//translator(messages.sprite, {index: 1}), + targetType: targetTypes.robot, + name: 'Robot',//translator(messages.sprite, {index: 1}), + variables: {}, + lists: {}, + broadcasts: {}, + blocks: {}, + currentCostume: 0, + costumes: [ + { + assetId: '8e41346f9e386948096815a9b5d6b3e1', + name: translator(messages.costume, {index: 1}), + bitmapResolution: 1, + md5ext: '8e41346f9e386948096815a9b5d6b3e1.svg', + dataFormat: 'svg', + rotationCenterX: 48, + rotationCenterY: 50 + } + ], + sounds: [ + ], + volume: 100, + visible: false, + x: 0, + y: 0, + size: 100, + direction: 90, + draggable: false, + rotationStyle: 'all around' + }, + { + isStage: false, + targetType: targetTypes.sprite, + name: 'Sprite',//translator(messages.sprite, {index: 1}), variables: {}, lists: {}, broadcasts: {}, @@ -84,7 +118,7 @@ const projectData = translateFunction => { direction: 90, draggable: false, rotationStyle: 'all around' - } + }, ], meta: { semver: '3.0.0', diff --git a/src/lib/libraries/sprites.json b/src/lib/libraries/sprites.json index 92918ac2c71..d5c067a689b 100644 --- a/src/lib/libraries/sprites.json +++ b/src/lib/libraries/sprites.json @@ -15,6 +15,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Abby", "variables": {}, "lists": {}, @@ -98,6 +99,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Amon", "variables": {}, "lists": {}, @@ -159,6 +161,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Andie", "variables": {}, "lists": {}, @@ -242,6 +245,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Anina Dance", "variables": {}, "lists": {}, @@ -417,6 +421,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Apple", "variables": {}, "lists": {}, @@ -475,6 +480,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Arrow1", "variables": {}, "lists": {}, @@ -557,6 +563,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Avery", "variables": {}, "lists": {}, @@ -622,6 +629,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Avery Walking", "variables": {}, "lists": {}, @@ -713,6 +721,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Ball", "variables": {}, "lists": {}, @@ -814,6 +823,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Ballerina", "variables": {}, "lists": {}, @@ -903,6 +913,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Balloon1", "variables": {}, "lists": {}, @@ -980,6 +991,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Bananas", "variables": {}, "lists": {}, @@ -1047,6 +1059,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Baseball", "variables": {}, "lists": {}, @@ -1104,6 +1117,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Basketball", "variables": {}, "lists": {}, @@ -1173,6 +1187,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Bat", "variables": {}, "lists": {}, @@ -1258,6 +1273,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Batter", "variables": {}, "lists": {}, @@ -1343,6 +1359,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Beachball", "variables": {}, "lists": {}, @@ -1409,6 +1426,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Bear", "variables": {}, "lists": {}, @@ -1475,6 +1493,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Bear-walking", "variables": {}, "lists": {}, @@ -1596,6 +1615,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Beetle", "variables": {}, "lists": {}, @@ -1654,6 +1674,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Bell", "variables": {}, "lists": {}, @@ -1722,6 +1743,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Ben", "variables": {}, "lists": {}, @@ -1814,6 +1836,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Bowl", "variables": {}, "lists": {}, @@ -1871,6 +1894,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Bowtie", "variables": {}, "lists": {}, @@ -1927,6 +1951,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Bread", "variables": {}, "lists": {}, @@ -1985,6 +2010,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Broom", "variables": {}, "lists": {}, @@ -2043,6 +2069,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Buildings", "variables": {}, "lists": {}, @@ -2183,6 +2210,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Butterfly 1", "variables": {}, "lists": {}, @@ -2262,6 +2290,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Butterfly 2", "variables": {}, "lists": {}, @@ -2329,6 +2358,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Button1", "variables": {}, "lists": {}, @@ -2386,6 +2416,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Button2", "variables": {}, "lists": {}, @@ -2453,6 +2484,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Button3", "variables": {}, "lists": {}, @@ -2518,6 +2550,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Button4", "variables": {}, "lists": {}, @@ -2586,6 +2619,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Button5", "variables": {}, "lists": {}, @@ -2657,6 +2691,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Cake", "variables": {}, "lists": {}, @@ -2721,6 +2756,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Calvrett", "variables": {}, "lists": {}, @@ -2788,6 +2824,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Casey", "variables": {}, "lists": {}, @@ -2871,6 +2908,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Cassy Dance", "variables": {}, "lists": {}, @@ -2959,6 +2997,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Cat", "variables": {}, "lists": {}, @@ -3027,6 +3066,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Cat 2", "variables": {}, "lists": {}, @@ -3085,6 +3125,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Cat Flying", "variables": {}, "lists": {}, @@ -3152,6 +3193,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Catcher", "variables": {}, "lists": {}, @@ -3237,6 +3279,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Centaur", "variables": {}, "lists": {}, @@ -3329,6 +3372,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Champ99", "variables": {}, "lists": {}, @@ -3445,6 +3489,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Characters 1", "variables": {}, "lists": {}, @@ -3615,6 +3660,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Characters 2", "variables": {}, "lists": {}, @@ -3751,6 +3797,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Cheesy Puffs", "variables": {}, "lists": {}, @@ -3809,6 +3856,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Chick", "variables": {}, "lists": {}, @@ -3885,6 +3933,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "City Bus", "variables": {}, "lists": {}, @@ -3960,6 +4009,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Cloud", "variables": {}, "lists": {}, @@ -4018,6 +4068,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Clouds", "variables": {}, "lists": {}, @@ -4101,6 +4152,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Convertible", "variables": {}, "lists": {}, @@ -4158,6 +4210,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Convertible 2", "variables": {}, "lists": {}, @@ -4222,6 +4275,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Crab", "variables": {}, "lists": {}, @@ -4288,6 +4342,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Crystal", "variables": {}, "lists": {}, @@ -4362,6 +4417,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "D-Money Dance", "variables": {}, "lists": {}, @@ -4516,6 +4572,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dan", "variables": {}, "lists": {}, @@ -4580,6 +4637,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dani", "variables": {}, "lists": {}, @@ -4653,6 +4711,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dee", "variables": {}, "lists": {}, @@ -4744,6 +4803,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Devin", "variables": {}, "lists": {}, @@ -4828,6 +4888,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dinosaur1", "variables": {}, "lists": {}, @@ -4913,6 +4974,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dinosaur2", "variables": {}, "lists": {}, @@ -4999,6 +5061,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dinosaur3", "variables": {}, "lists": {}, @@ -5095,6 +5158,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dinosaur4", "variables": {}, "lists": {}, @@ -5179,6 +5243,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dinosaur5", "variables": {}, "lists": {}, @@ -5311,6 +5376,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Diver1", "variables": {}, "lists": {}, @@ -5371,6 +5437,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Diver2", "variables": {}, "lists": {}, @@ -5429,6 +5496,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dog1", "variables": {}, "lists": {}, @@ -5496,6 +5564,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dog2", "variables": {}, "lists": {}, @@ -5576,6 +5645,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Donut", "variables": {}, "lists": {}, @@ -5643,6 +5713,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dorian", "variables": {}, "lists": {}, @@ -5728,6 +5799,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dot", "variables": {}, "lists": {}, @@ -5812,6 +5884,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dove", "variables": {}, "lists": {}, @@ -5879,6 +5952,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dragon", "variables": {}, "lists": {}, @@ -5956,6 +6030,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dragonfly", "variables": {}, "lists": {}, @@ -6022,6 +6097,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Dress", "variables": {}, "lists": {}, @@ -6096,6 +6172,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Drum", "variables": {}, "lists": {}, @@ -6170,6 +6247,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Drum Kit", "variables": {}, "lists": {}, @@ -6271,6 +6349,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Drum-cymbal", "variables": {}, "lists": {}, @@ -6363,6 +6442,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Drum-highhat", "variables": {}, "lists": {}, @@ -6428,6 +6508,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Drum-snare", "variables": {}, "lists": {}, @@ -6514,6 +6595,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Drums Conga", "variables": {}, "lists": {}, @@ -6609,6 +6691,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Drums Tabla", "variables": {}, "lists": {}, @@ -6704,6 +6787,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Duck", "variables": {}, "lists": {}, @@ -6762,6 +6846,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Earth", "variables": {}, "lists": {}, @@ -6819,6 +6904,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Easel", "variables": {}, "lists": {}, @@ -6894,6 +6980,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Egg", "variables": {}, "lists": {}, @@ -6996,6 +7083,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Elephant", "variables": {}, "lists": {}, @@ -7063,6 +7151,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Elf", "variables": {}, "lists": {}, @@ -7157,6 +7246,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Fairy", "variables": {}, "lists": {}, @@ -7252,6 +7342,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Fish", "variables": {}, "lists": {}, @@ -7346,6 +7437,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Fishbowl", "variables": {}, "lists": {}, @@ -7414,6 +7506,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Food Truck", "variables": {}, "lists": {}, @@ -7506,6 +7599,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Football", "variables": {}, "lists": {}, @@ -7570,6 +7664,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Fortune Cookie", "variables": {}, "lists": {}, @@ -7627,6 +7722,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Fox", "variables": {}, "lists": {}, @@ -7706,6 +7802,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Frank", "variables": {}, "lists": {}, @@ -7793,6 +7890,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Frog", "variables": {}, "lists": {}, @@ -7852,6 +7950,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Frog 2 ", "variables": {}, "lists": {}, @@ -7925,6 +8024,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Fruit Platter", "variables": {}, "lists": {}, @@ -7981,6 +8081,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Fruit Salad", "variables": {}, "lists": {}, @@ -8041,6 +8142,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Ghost", "variables": {}, "lists": {}, @@ -8124,6 +8226,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Gift", "variables": {}, "lists": {}, @@ -8189,6 +8292,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Giga", "variables": {}, "lists": {}, @@ -8272,6 +8376,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Giga Walking", "variables": {}, "lists": {}, @@ -8347,6 +8452,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Giraffe", "variables": {}, "lists": {}, @@ -8422,6 +8528,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glass Water", "variables": {}, "lists": {}, @@ -8488,6 +8595,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glasses", "variables": {}, "lists": {}, @@ -8573,6 +8681,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Goalie", "variables": {}, "lists": {}, @@ -8666,6 +8775,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Goblin", "variables": {}, "lists": {}, @@ -8751,6 +8861,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Gobo", "variables": {}, "lists": {}, @@ -8828,6 +8939,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Grasshopper", "variables": {}, "lists": {}, @@ -8928,6 +9040,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Green Flag", "variables": {}, "lists": {}, @@ -8986,6 +9099,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Griffin", "variables": {}, "lists": {}, @@ -9069,6 +9183,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Guitar", "variables": {}, "lists": {}, @@ -9197,6 +9312,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Guitar-electric1", "variables": {}, "lists": {}, @@ -9325,6 +9441,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Guitar-electric2", "variables": {}, "lists": {}, @@ -9453,6 +9570,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Hannah", "variables": {}, "lists": {}, @@ -9534,6 +9652,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Hare", "variables": {}, "lists": {}, @@ -9609,6 +9728,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Harper", "variables": {}, "lists": {}, @@ -9684,6 +9804,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Hat1 ", "variables": {}, "lists": {}, @@ -9769,6 +9890,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Hatchling", "variables": {}, "lists": {}, @@ -9846,6 +9968,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Heart", "variables": {}, "lists": {}, @@ -9911,6 +10034,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Heart Candy", "variables": {}, "lists": {}, @@ -9993,6 +10117,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Heart Face", "variables": {}, "lists": {}, @@ -10051,6 +10176,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Hedgehog", "variables": {}, "lists": {}, @@ -10145,6 +10271,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Hen", "variables": {}, "lists": {}, @@ -10234,6 +10361,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Hippo1", "variables": {}, "lists": {}, @@ -10299,6 +10427,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Home Button", "variables": {}, "lists": {}, @@ -10359,6 +10488,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Horse", "variables": {}, "lists": {}, @@ -10432,6 +10562,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Jaime", "variables": {}, "lists": {}, @@ -10544,6 +10675,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Jamal", "variables": {}, "lists": {}, @@ -10637,6 +10769,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Jar", "variables": {}, "lists": {}, @@ -10706,6 +10839,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Jellyfish", "variables": {}, "lists": {}, @@ -10801,6 +10935,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Jordyn", "variables": {}, "lists": {}, @@ -10893,6 +11028,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Jouvi Dance", "variables": {}, "lists": {}, @@ -11056,6 +11192,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Kai", "variables": {}, "lists": {}, @@ -11121,6 +11258,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Key", "variables": {}, "lists": {}, @@ -11177,6 +11315,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Keyboard", "variables": {}, "lists": {}, @@ -11311,6 +11450,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Kia", "variables": {}, "lists": {}, @@ -11386,6 +11526,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Kiran", "variables": {}, "lists": {}, @@ -11488,6 +11629,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Knight", "variables": {}, "lists": {}, @@ -11544,6 +11686,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "LB Dance", "variables": {}, "lists": {}, @@ -11710,6 +11853,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Ladybug1", "variables": {}, "lists": {}, @@ -11769,6 +11913,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Ladybug2", "variables": {}, "lists": {}, @@ -11834,6 +11979,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Laptop", "variables": {}, "lists": {}, @@ -11893,6 +12039,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Lightning", "variables": {}, "lists": {}, @@ -11950,6 +12097,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Line", "variables": {}, "lists": {}, @@ -12009,6 +12157,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Lion", "variables": {}, "lists": {}, @@ -12093,6 +12242,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Llama", "variables": {}, "lists": {}, @@ -12173,6 +12323,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Luca", "variables": {}, "lists": {}, @@ -12248,6 +12399,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Magic Wand", "variables": {}, "lists": {}, @@ -12303,6 +12455,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Marian", "variables": {}, "lists": {}, @@ -12397,6 +12550,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Max", "variables": {}, "lists": {}, @@ -12482,6 +12636,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Mermaid", "variables": {}, "lists": {}, @@ -12565,6 +12720,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Microphone", "variables": {}, "lists": {}, @@ -12703,6 +12859,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Milk", "variables": {}, "lists": {}, @@ -12796,6 +12953,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Monet", "variables": {}, "lists": {}, @@ -12890,6 +13048,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Monkey", "variables": {}, "lists": {}, @@ -12975,6 +13134,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Motorcycle", "variables": {}, "lists": {}, @@ -13068,6 +13228,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Mouse1", "variables": {}, "lists": {}, @@ -13132,6 +13293,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Muffin", "variables": {}, "lists": {}, @@ -13197,6 +13359,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Nano", "variables": {}, "lists": {}, @@ -13280,6 +13443,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Neigh Pony", "variables": {}, "lists": {}, @@ -13342,6 +13506,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Noor", "variables": {}, "lists": {}, @@ -13419,6 +13584,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Octopus", "variables": {}, "lists": {}, @@ -13520,6 +13686,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Orange", "variables": {}, "lists": {}, @@ -13577,6 +13744,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Orange2", "variables": {}, "lists": {}, @@ -13644,6 +13812,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Outfielder", "variables": {}, "lists": {}, @@ -13728,6 +13897,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Owl", "variables": {}, "lists": {}, @@ -13801,6 +13971,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Paddle", "variables": {}, "lists": {}, @@ -13859,6 +14030,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Panther", "variables": {}, "lists": {}, @@ -13934,6 +14106,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Pants", "variables": {}, "lists": {}, @@ -14004,6 +14177,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Parrot", "variables": {}, "lists": {}, @@ -14069,6 +14243,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Party Hats", "variables": {}, "lists": {}, @@ -14143,6 +14318,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Pencil", "variables": {}, "lists": {}, @@ -14215,6 +14391,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Penguin", "variables": {}, "lists": {}, @@ -14291,6 +14468,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Penguin 2", "variables": {}, "lists": {}, @@ -14374,6 +14552,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Pico", "variables": {}, "lists": {}, @@ -14457,6 +14636,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Pico Walking", "variables": {}, "lists": {}, @@ -14542,6 +14722,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Pitcher", "variables": {}, "lists": {}, @@ -14624,6 +14805,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Planet2", "variables": {}, "lists": {}, @@ -14688,6 +14870,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Polar Bear", "variables": {}, "lists": {}, @@ -14763,6 +14946,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Potion", "variables": {}, "lists": {}, @@ -14838,6 +15022,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Prince", "variables": {}, "lists": {}, @@ -14897,6 +15082,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Princess", "variables": {}, "lists": {}, @@ -14992,6 +15178,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Pufferfish", "variables": {}, "lists": {}, @@ -15076,6 +15263,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Puppy", "variables": {}, "lists": {}, @@ -15163,6 +15351,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Rabbit", "variables": {}, "lists": {}, @@ -15257,6 +15446,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Radio", "variables": {}, "lists": {}, @@ -15351,6 +15541,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Rainbow", "variables": {}, "lists": {}, @@ -15409,6 +15600,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Referee", "variables": {}, "lists": {}, @@ -15493,6 +15685,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Reindeer", "variables": {}, "lists": {}, @@ -15548,6 +15741,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Retro Robot", "variables": {}, "lists": {}, @@ -15632,6 +15826,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Ripley", "variables": {}, "lists": {}, @@ -15734,6 +15929,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Robot", "variables": {}, "lists": {}, @@ -15836,6 +16032,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Rocketship", "variables": {}, "lists": {}, @@ -15946,6 +16143,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Rocks", "variables": {}, "lists": {}, @@ -16004,6 +16202,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Rooster", "variables": {}, "lists": {}, @@ -16086,6 +16285,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Ruby", "variables": {}, "lists": {}, @@ -16151,6 +16351,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Sailboat", "variables": {}, "lists": {}, @@ -16206,6 +16407,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Sam", "variables": {}, "lists": {}, @@ -16268,6 +16470,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Sasha", "variables": {}, "lists": {}, @@ -16342,6 +16545,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Saxophone", "variables": {}, "lists": {}, @@ -16470,6 +16674,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Scarf", "variables": {}, "lists": {}, @@ -16546,6 +16751,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Shark", "variables": {}, "lists": {}, @@ -16616,6 +16822,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Shark 2", "variables": {}, "lists": {}, @@ -16708,6 +16915,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Shirt", "variables": {}, "lists": {}, @@ -16766,6 +16974,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Shoes", "variables": {}, "lists": {}, @@ -16851,6 +17060,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Shorts", "variables": {}, "lists": {}, @@ -16925,6 +17135,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Singer1", "variables": {}, "lists": {}, @@ -16985,6 +17196,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Skeleton", "variables": {}, "lists": {}, @@ -17069,6 +17281,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Snake", "variables": {}, "lists": {}, @@ -17142,6 +17355,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Snowflake", "variables": {}, "lists": {}, @@ -17199,6 +17413,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Snowman", "variables": {}, "lists": {}, @@ -17257,6 +17472,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Soccer Ball", "variables": {}, "lists": {}, @@ -17316,6 +17532,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Speaker", "variables": { "R?s=9ue~vmG263RuL6)4-scale degree-": [ @@ -17442,6 +17659,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Squirrel", "variables": {}, "lists": {}, @@ -17498,6 +17716,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Star", "variables": {}, "lists": {}, @@ -17557,6 +17776,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Starfish", "variables": {}, "lists": {}, @@ -17622,6 +17842,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Stop", "variables": {}, "lists": {}, @@ -17679,6 +17900,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Strawberry", "variables": {}, "lists": {}, @@ -17775,6 +17997,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Sun", "variables": {}, "lists": {}, @@ -17831,6 +18054,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Sunglasses1", "variables": {}, "lists": {}, @@ -17896,6 +18120,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Taco", "variables": {}, "lists": {}, @@ -17961,6 +18186,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Takeout", "variables": {}, "lists": {}, @@ -18059,6 +18285,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Tatiana", "variables": {}, "lists": {}, @@ -18148,6 +18375,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Taylor", "variables": {}, "lists": {}, @@ -18231,6 +18459,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Ten80 Dance", "variables": {}, "lists": {}, @@ -18395,6 +18624,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Tennis Ball", "variables": {}, "lists": {}, @@ -18451,6 +18681,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Tera", "variables": {}, "lists": {}, @@ -18535,6 +18766,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Toucan", "variables": {}, "lists": {}, @@ -18608,6 +18840,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Trampoline", "variables": {}, "lists": {}, @@ -18665,6 +18898,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Tree1", "variables": {}, "lists": {}, @@ -18722,6 +18956,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Trees", "variables": {}, "lists": {}, @@ -18793,6 +19028,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Trisha", "variables": {}, "lists": {}, @@ -18878,6 +19114,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Truck", "variables": {}, "lists": {}, @@ -18952,6 +19189,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Trumpet", "variables": {}, "lists": {}, @@ -19081,6 +19319,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Unicorn", "variables": {}, "lists": {}, @@ -19140,6 +19379,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Unicorn 2", "variables": {}, "lists": {}, @@ -19198,6 +19438,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Unicorn Running", "variables": {}, "lists": {}, @@ -19300,6 +19541,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Wand", "variables": {}, "lists": {}, @@ -19355,6 +19597,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Wanda", "variables": {}, "lists": {}, @@ -19415,6 +19658,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Watermelon", "variables": {}, "lists": {}, @@ -19491,6 +19735,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Winter Hat", "variables": {}, "lists": {}, @@ -19551,6 +19796,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Witch", "variables": {}, "lists": {}, @@ -19638,6 +19884,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Wizard", "variables": {}, "lists": {}, @@ -19716,6 +19963,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Wizard Girl", "variables": {}, "lists": {}, @@ -19773,6 +20021,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Wizard Hat", "variables": {}, "lists": {}, @@ -19834,6 +20083,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Wizard-toad", "variables": {}, "lists": {}, @@ -19910,6 +20160,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Zebra", "variables": {}, "lists": {}, @@ -19975,6 +20226,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-A", "variables": {}, "lists": {}, @@ -20031,6 +20283,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-B", "variables": {}, "lists": {}, @@ -20087,6 +20340,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-C", "variables": {}, "lists": {}, @@ -20143,6 +20397,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-D", "variables": {}, "lists": {}, @@ -20199,6 +20454,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-E", "variables": {}, "lists": {}, @@ -20255,6 +20511,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-F", "variables": {}, "lists": {}, @@ -20311,6 +20568,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-G", "variables": {}, "lists": {}, @@ -20367,6 +20625,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-H", "variables": {}, "lists": {}, @@ -20423,6 +20682,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-I", "variables": {}, "lists": {}, @@ -20479,6 +20739,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-J", "variables": {}, "lists": {}, @@ -20535,6 +20796,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-K", "variables": {}, "lists": {}, @@ -20591,6 +20853,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-L", "variables": {}, "lists": {}, @@ -20647,6 +20910,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-M", "variables": {}, "lists": {}, @@ -20703,6 +20967,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-N", "variables": {}, "lists": {}, @@ -20759,6 +21024,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-O", "variables": {}, "lists": {}, @@ -20815,6 +21081,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-P", "variables": {}, "lists": {}, @@ -20871,6 +21138,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-Q", "variables": {}, "lists": {}, @@ -20927,6 +21195,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-R", "variables": {}, "lists": {}, @@ -20983,6 +21252,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-S", "variables": {}, "lists": {}, @@ -21039,6 +21309,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-T", "variables": {}, "lists": {}, @@ -21095,6 +21366,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-U", "variables": {}, "lists": {}, @@ -21151,6 +21423,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-V", "variables": {}, "lists": {}, @@ -21207,6 +21480,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-W", "variables": {}, "lists": {}, @@ -21263,6 +21537,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-X", "variables": {}, "lists": {}, @@ -21319,6 +21594,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-Y", "variables": {}, "lists": {}, @@ -21375,6 +21651,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Block-Z", "variables": {}, "lists": {}, @@ -21431,6 +21708,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-0", "variables": {}, "lists": {}, @@ -21487,6 +21765,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-1", "variables": {}, "lists": {}, @@ -21543,6 +21822,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-2", "variables": {}, "lists": {}, @@ -21599,6 +21879,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-3", "variables": {}, "lists": {}, @@ -21655,6 +21936,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-4", "variables": {}, "lists": {}, @@ -21711,6 +21993,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-5", "variables": {}, "lists": {}, @@ -21767,6 +22050,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-6", "variables": {}, "lists": {}, @@ -21823,6 +22107,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-7", "variables": {}, "lists": {}, @@ -21879,6 +22164,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-8", "variables": {}, "lists": {}, @@ -21935,6 +22221,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-9", "variables": {}, "lists": {}, @@ -21991,6 +22278,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-A", "variables": {}, "lists": {}, @@ -22047,6 +22335,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-B", "variables": {}, "lists": {}, @@ -22103,6 +22392,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-C", "variables": {}, "lists": {}, @@ -22159,6 +22449,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-D", "variables": {}, "lists": {}, @@ -22215,6 +22506,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-E", "variables": {}, "lists": {}, @@ -22271,6 +22563,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-F", "variables": {}, "lists": {}, @@ -22327,6 +22620,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-G", "variables": {}, "lists": {}, @@ -22383,6 +22677,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-H", "variables": {}, "lists": {}, @@ -22439,6 +22734,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-I", "variables": {}, "lists": {}, @@ -22495,6 +22791,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-J", "variables": {}, "lists": {}, @@ -22551,6 +22848,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-K", "variables": {}, "lists": {}, @@ -22607,6 +22905,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-L", "variables": {}, "lists": {}, @@ -22663,6 +22962,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-M", "variables": {}, "lists": {}, @@ -22719,6 +23019,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-N", "variables": {}, "lists": {}, @@ -22775,6 +23076,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-O", "variables": {}, "lists": {}, @@ -22831,6 +23133,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-P", "variables": {}, "lists": {}, @@ -22887,6 +23190,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-Q", "variables": {}, "lists": {}, @@ -22943,6 +23247,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-R", "variables": {}, "lists": {}, @@ -22999,6 +23304,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-S", "variables": {}, "lists": {}, @@ -23055,6 +23361,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-T", "variables": {}, "lists": {}, @@ -23111,6 +23418,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-U", "variables": {}, "lists": {}, @@ -23167,6 +23475,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-V", "variables": {}, "lists": {}, @@ -23223,6 +23532,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-W", "variables": {}, "lists": {}, @@ -23279,6 +23589,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-X", "variables": {}, "lists": {}, @@ -23335,6 +23646,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-Y", "variables": {}, "lists": {}, @@ -23391,6 +23703,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Glow-Z", "variables": {}, "lists": {}, @@ -23447,6 +23760,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-A", "variables": {}, "lists": {}, @@ -23521,6 +23835,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-B", "variables": {}, "lists": {}, @@ -23595,6 +23910,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-C", "variables": {}, "lists": {}, @@ -23669,6 +23985,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-D", "variables": {}, "lists": {}, @@ -23743,6 +24060,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-E", "variables": {}, "lists": {}, @@ -23817,6 +24135,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-F", "variables": {}, "lists": {}, @@ -23891,6 +24210,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-G", "variables": {}, "lists": {}, @@ -23965,6 +24285,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-H", "variables": {}, "lists": {}, @@ -24039,6 +24360,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-I", "variables": {}, "lists": {}, @@ -24113,6 +24435,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-J", "variables": {}, "lists": {}, @@ -24187,6 +24510,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-K", "variables": {}, "lists": {}, @@ -24261,6 +24585,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-L", "variables": {}, "lists": {}, @@ -24335,6 +24660,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-M", "variables": {}, "lists": {}, @@ -24409,6 +24735,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-N", "variables": {}, "lists": {}, @@ -24483,6 +24810,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-O", "variables": {}, "lists": {}, @@ -24557,6 +24885,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-P", "variables": {}, "lists": {}, @@ -24631,6 +24960,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-Q", "variables": {}, "lists": {}, @@ -24705,6 +25035,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-R", "variables": {}, "lists": {}, @@ -24779,6 +25110,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-S", "variables": {}, "lists": {}, @@ -24853,6 +25185,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-T", "variables": {}, "lists": {}, @@ -24927,6 +25260,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-U", "variables": {}, "lists": {}, @@ -25001,6 +25335,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-V", "variables": {}, "lists": {}, @@ -25075,6 +25410,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-W", "variables": {}, "lists": {}, @@ -25149,6 +25485,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-X", "variables": {}, "lists": {}, @@ -25223,6 +25560,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-Y", "variables": {}, "lists": {}, @@ -25297,6 +25635,7 @@ ], "json": { "isStage": false, + "targetType": "SPRITE", "name": "Story-Z", "variables": {}, "lists": {}, diff --git a/src/lib/make-toolbox-xml.js b/src/lib/make-toolbox-xml.js index 15d61e94eac..db23e7a9c9b 100644 --- a/src/lib/make-toolbox-xml.js +++ b/src/lib/make-toolbox-xml.js @@ -1,25 +1,32 @@ -import ScratchBlocks from 'scratch-blocks'; - +import ScratchBlocks from "scratch-blocks"; +import targetTypes from "./target_types_enum"; const categorySeparator = ''; const blockSeparator = ''; // At default scale, about 28px -const motion = function (isStage, targetId) { - const stageSelected = ScratchBlocks.ScratchMsgs.translate( - 'MOTION_STAGE_SELECTED', - 'Stage selected: no motion blocks' - ); - return ` +const motion = function (targetType, targetId) { + const stageSelected = ScratchBlocks.ScratchMsgs.translate( + "MOTION_STAGE_SELECTED", + "Stage selected: no motion blocks" + ); + return ` - ${isStage ? ` + ${ + targetType === targetTypes.stage + ? ` - ` : ` + ` + : ` - + + ${ + targetType === targetTypes.robot && + ` + - + 2 @@ -207,6 +214,10 @@ const motion = function (isStage, targetId) { + + + ` + } @@ -364,7 +375,11 @@ const motion = function (isStage, targetId) { - + ${ + targetType === targetTypes.sprite && + ` + + 10 @@ -482,35 +497,43 @@ const motion = function (isStage, targetId) { ${blockSeparator} - `} + + + ` + } + ` + } ${categorySeparator} `; }; const xmlEscape = function (unsafe) { - return unsafe.replace(/[<>&'"]/g, c => { - switch (c) { - case '<': - return '<'; - case '>': - return '>'; - case '&': - return '&'; - case '\'': - return '''; - case '"': - return '"'; - } - }); + return unsafe.replace(/[<>&'"]/g, (c) => { + switch (c) { + case "<": + return "<"; + case ">": + return ">"; + case "&": + return "&"; + case "'": + return "'"; + case '"': + return """; + } + }); }; -const looks = function (isStage, targetId, costumeName, backdropName) { - const hello = ScratchBlocks.ScratchMsgs.translate('LOOKS_HELLO', 'Hello!'); - const hmm = ScratchBlocks.ScratchMsgs.translate('LOOKS_HMM', 'Hmm...'); - return ` +const looks = function (targetType, targetId, costumeName, backdropName) { + const hello = ScratchBlocks.ScratchMsgs.translate("LOOKS_HELLO", "Hello!"); + const hmm = ScratchBlocks.ScratchMsgs.translate("LOOKS_HMM", "Hmm..."); + return ` - + ${ + targetType === targetTypes.robot && + ` + @@ -540,8 +563,15 @@ const looks = function (isStage, targetId, costumeName, backdropName) { + + ` + } + + ${ + targetType === targetTypes.sprite && + ` + - ${isStage ? '' : ` @@ -554,6 +584,13 @@ const looks = function (isStage, targetId, costumeName, backdropName) { + + + + 10 + + + @@ -561,6 +598,14 @@ const looks = function (isStage, targetId, costumeName, backdropName) { + + + + + 100 + + + @@ -573,6 +618,15 @@ const looks = function (isStage, targetId, costumeName, backdropName) { + ${blockSeparator} + + + + ${costumeName} + + + + @@ -581,15 +635,30 @@ const looks = function (isStage, targetId, costumeName, backdropName) { ${blockSeparator} - `} - ${isStage ? ` - - - - ${backdropName} + + + ${blockSeparator} + + + + + 1 + ${blockSeparator} + + + + `} + + + ${ + targetType === targetTypes.stage && + ` + + + @@ -597,16 +666,16 @@ const looks = function (isStage, targetId, costumeName, backdropName) { - - ` : ` - - - - ${costumeName} - - - - + ${blockSeparator} + + + + ` + } + ${ + targetType !== targetTypes.robot && + ` + @@ -614,23 +683,8 @@ const looks = function (isStage, targetId, costumeName, backdropName) { - - ${blockSeparator} - - - - 10 - - - - - - - 100 - - - - `} + + ${blockSeparator} @@ -647,109 +701,104 @@ const looks = function (isStage, targetId, costumeName, backdropName) { - ${blockSeparator} - ${isStage ? '' : ` - - - ${blockSeparator} - - - - - 1 - - - - `} - ${isStage ? ` - - ` : ` - - - - `} - ${categorySeparator} - - `; + + ` + } + ${categorySeparator} + + `; }; -const sound = function (isStage, targetId, soundName) { - return ` +const sound = function (targetType, targetId, soundName) { + return ` - + ${ + targetType === targetTypes.robot && + ` + - + + + ` + } ${blockSeparator} - - - - - ${soundName} - - - - - - - ${soundName} - - - - - ${blockSeparator} - - - - 10 - - - - - - - 100 - - - - - ${blockSeparator} - - - - -10 - - - - - - - 100 - - - - + ${ + targetType !== targetTypes.robot && ` + + + + + ${soundName} + + + + + + + ${soundName} + + + + + ${blockSeparator} + + + + 10 + + + + + + + 100 + + + + + ${blockSeparator} + + + + -10 + + + + + + + 100 + + + + + + `} ${categorySeparator} `; }; -const events = function (isStage) { - return ` +const events = function (targetType) { + return ` - ${isStage ? ` + ${ + targetType === targetTypes.stage + && ` - ` : ` + `} + ${ targetType === targetTypes.sprite && ` `} @@ -780,8 +829,8 @@ const events = function (isStage) { `; }; -const control = function (isStage) { - return ` +const control = function (targetType) { + return ` @@ -807,33 +856,37 @@ const control = function (isStage) { ${blockSeparator} ${blockSeparator} - ${isStage ? ` + ${ + targetType !== targetTypes.robot + && ` - ` : ` + `} + ${ + targetType === targetTypes.sprite && ` - - - - - - `} + ` + } ${categorySeparator} `; }; - -const sensing = function (isStage) { - const name = ScratchBlocks.ScratchMsgs.translate('SENSING_ASK_TEXT', 'What\'s your name?'); - return ` +const sensing = function (targetType) { + const name = ScratchBlocks.ScratchMsgs.translate( + "SENSING_ASK_TEXT", + "What's your name?" + ); + return ` - ${isStage ? '' : ` - + ${ + targetType === targetTypes.robot && + ` + @@ -883,13 +936,14 @@ const sensing = function (isStage) { --> - +`} ${blockSeparator} - + ${ + targetType === targetTypes.sprite && ` @@ -914,7 +968,8 @@ const sensing = function (isStage) { ${blockSeparator} - `} + ` } + @@ -930,14 +985,21 @@ const sensing = function (isStage) { - - - ${isStage ? '' : ` + ${ + targetType !== targetTypes.robot && ` + + + `} + ${ + targetType === targetTypes.sprite + && ` ${blockSeparator} ''+ ${blockSeparator} `} ${blockSeparator} + ${ + targetType !== targetTypes.robot && ` ${blockSeparator} @@ -951,18 +1013,29 @@ const sensing = function (isStage) { ${blockSeparator} + `} ${blockSeparator} - + ${categorySeparator} `; }; const operators = function () { - const apple = ScratchBlocks.ScratchMsgs.translate('OPERATORS_JOIN_APPLE', 'apple'); - const banana = ScratchBlocks.ScratchMsgs.translate('OPERATORS_JOIN_BANANA', 'banana'); - const letter = ScratchBlocks.ScratchMsgs.translate('OPERATORS_LETTEROF_APPLE', 'a'); - return ` + console.log("adding operators", 'make-toolbox-xml.js', 'line: ', '1024'); + const apple = ScratchBlocks.ScratchMsgs.translate( + "OPERATORS_JOIN_APPLE", + "apple" + ); + const banana = ScratchBlocks.ScratchMsgs.translate( + "OPERATORS_JOIN_BANANA", + "banana" + ); + const letter = ScratchBlocks.ScratchMsgs.translate( + "OPERATORS_LETTEROF_APPLE", + "a" + ); + return ` @@ -1144,7 +1217,7 @@ const operators = function () { }; const variables = function () { - return ` + return ` } categoriesXML - optional array of `{id,xml}` for categories. This can include both core * and other extensions: core extensions will be placed in the normal Scratch order; others will go at the bottom. @@ -1182,53 +1255,72 @@ const xmlClose = ''; * @param {?string} soundName - The name of the default selected sound dropdown. * @returns {string} - a ScratchBlocks-style XML document for the contents of the toolbox. */ -const makeToolboxXML = function (isStage, targetId, categoriesXML = [], - costumeName = '', backdropName = '', soundName = '') { - const gap = [categorySeparator]; - - costumeName = xmlEscape(costumeName); - backdropName = xmlEscape(backdropName); - soundName = xmlEscape(soundName); - - categoriesXML = categoriesXML.slice(); - const moveCategory = categoryId => { - const index = categoriesXML.findIndex(categoryInfo => categoryInfo.id === categoryId); - if (index >= 0) { - // remove the category from categoriesXML and return its XML - const [categoryInfo] = categoriesXML.splice(index, 1); - return categoryInfo.xml; - } - // return `undefined` - }; - const motionXML = moveCategory('motion') || motion(isStage, targetId); - const looksXML = moveCategory('looks') || looks(isStage, targetId, costumeName, backdropName); - const soundXML = moveCategory('sound') || sound(isStage, targetId, soundName); - const eventsXML = moveCategory('event') || events(isStage, targetId); - const controlXML = moveCategory('control') || control(isStage, targetId); - const sensingXML = moveCategory('sensing') || sensing(isStage, targetId); - const operatorsXML = moveCategory('operators') || operators(isStage, targetId); - const variablesXML = moveCategory('data') || variables(isStage, targetId); - const myBlocksXML = moveCategory('procedures') || myBlocks(isStage, targetId); - - const everything = [ - xmlOpen, - motionXML, gap, - looksXML, gap, - soundXML, gap, - eventsXML, gap, - controlXML, gap, - sensingXML, gap, - operatorsXML, gap, - variablesXML, gap, - myBlocksXML - ]; - - for (const extensionCategory of categoriesXML) { - everything.push(gap, extensionCategory.xml); +const makeToolboxXML = function ( + targetType, + targetId, + categoriesXML = [], + costumeName = "", + backdropName = "", + soundName = "" +) { + const gap = [categorySeparator]; + + costumeName = xmlEscape(costumeName); + backdropName = xmlEscape(backdropName); + soundName = xmlEscape(soundName); + + categoriesXML = categoriesXML.slice(); + const moveCategory = (categoryId) => { + const index = categoriesXML.findIndex( + (categoryInfo) => categoryInfo.id === categoryId + ); + if (index >= 0) { + // remove the category from categoriesXML and return its XML + const [categoryInfo] = categoriesXML.splice(index, 1); + return categoryInfo.xml; } - - everything.push(xmlClose); - return everything.join('\n'); + // return `undefined` + }; + const motionXML = moveCategory("motion") || motion(targetType, targetId); + const looksXML = + moveCategory("looks") || + looks(targetType, targetId, costumeName, backdropName); + const soundXML = + moveCategory("sound") || sound(targetType, targetId, soundName); + const eventsXML = moveCategory("event") || events(targetType); + const controlXML = moveCategory("control") || control(targetType); + const sensingXML = moveCategory("sensing") || sensing(targetType); + const operatorsXML = moveCategory("operators") || operators(); + const variablesXML = moveCategory("data") || variables(); + const myBlocksXML = moveCategory("procedures") || myBlocks(); + + const everything = [ + xmlOpen, + motionXML, + gap, + looksXML, + gap, + soundXML, + gap, + eventsXML, + gap, + controlXML, + gap, + sensingXML, + gap, + operatorsXML, + gap, + variablesXML, + gap, + myBlocksXML, + ]; + + for (const extensionCategory of categoriesXML) { + everything.push(gap, extensionCategory.xml); + } + + everything.push(xmlClose); + return everything.join("\n"); }; export default makeToolboxXML; diff --git a/src/lib/target_types_enum.js b/src/lib/target_types_enum.js new file mode 100644 index 00000000000..cdbe0468fc4 --- /dev/null +++ b/src/lib/target_types_enum.js @@ -0,0 +1,5 @@ +export default { +robot: "ROBOT", + sprite: "SPRITE", + stage: "STAGE" +}; \ No newline at end of file diff --git a/src/lib/vm-listener-hoc.jsx b/src/lib/vm-listener-hoc.jsx index d5d46244602..28aa8338f03 100644 --- a/src/lib/vm-listener-hoc.jsx +++ b/src/lib/vm-listener-hoc.jsx @@ -15,6 +15,7 @@ import {setRunningState, setTurboState, setStartedState} from '../reducers/vm-st import {showExtensionAlert} from '../reducers/alerts'; import {updateMicIndicator} from '../reducers/mic-indicator'; import {blobToBase64} from './save-load-utils'; +import { headersToString } from 'selenium-webdriver/http'; /* * Higher Order Component to manage events emitted by the VM diff --git a/src/reducers/targets.js b/src/reducers/targets.js index 7da81982aa4..cf33a607604 100644 --- a/src/reducers/targets.js +++ b/src/reducers/targets.js @@ -1,9 +1,11 @@ +import targetTypes from "../lib/target_types_enum"; const UPDATE_TARGET_LIST = 'scratch-gui/targets/UPDATE_TARGET_LIST'; const HIGHLIGHT_TARGET = 'scratch-gui/targets/HIGHLIGHT_TARGET'; const initialState = { sprites: {}, stage: {}, + robot: {}, highlightedTargetId: null, highlightedTargetTime: null }; @@ -14,7 +16,7 @@ const reducer = function (state, action) { case UPDATE_TARGET_LIST: return Object.assign({}, state, { sprites: action.targets - .filter(target => !target.isStage) + .filter(target => targetTypes.sprite === target.targetType) .reduce( (targets, target, listId) => Object.assign( targets, @@ -24,6 +26,8 @@ const reducer = function (state, action) { ), stage: action.targets .filter(target => target.isStage)[0] || {}, + robot: action.targets + .filter(target => targetTypes.robot === target.targetType)[0] || {}, editingTarget: action.editingTarget }); case HIGHLIGHT_TARGET: