Compare commits

...
Author SHA1 Message Date
Ray Schamp a08bb42658 Merge pull request #5537 from adroitwhiz/hotfix/totally-normal-2020
Demystify non-editor mode
2020-03-25 15:46:59 -04:00
adroitwhiz 3e5f7e917a Demystify editor mode 2020-03-24 15:43:27 -04:00
rschamp 3014e56e24 Merge branch 'very-normal' of github.com:zoebentley/scratch-gui into hotfix/totally-normal-2020 2020-03-24 09:38:48 -04:00
Ray Schamp a8cd6f9c69 Update package.json 2020-03-24 09:35:59 -04:00
adroitwhiz c04acb513a Fix mystery on Edge 2020-03-24 09:34:27 -04:00
adroitwhiz 8ce4322051 Enhance mysterious atmosphere 2020-03-24 09:34:27 -04:00
rschamp f0637a40c5 Add mystery mode 2020-03-24 09:29:23 -04:00
Zoë Bentley a6cd49d400 Totally normal 2020-03-20 13:40:22 -04:00
13 changed files with 214 additions and 4 deletions

No files matched your search

+1 -1
View File
@@ -111,7 +111,7 @@
"scratch-blocks": "0.1.0-prerelease.1584453125",
"scratch-l10n": "3.7.20200317213230",
"scratch-paint": "0.2.0-prerelease.20200213174123",
"scratch-render": "0.1.0-prerelease.20200228152431",
"scratch-render": "0.1.0-prerelease.20200324022200",
"scratch-storage": "1.3.2",
"scratch-svg-renderer": "0.2.0-prerelease.20200205003400",
"scratch-vm": "0.2.0-prerelease.20200319175700",
+2
View File
@@ -18,6 +18,7 @@ import StageWrapper from '../../containers/stage-wrapper.jsx';
import Loader from '../loader/loader.jsx';
import Box from '../box/box.jsx';
import MenuBar from '../menu-bar/menu-bar.jsx';
import MysteryMode from '../mystery-mode/mystery-mode.jsx';
import CostumeLibrary from '../../containers/costume-library.jsx';
import BackdropLibrary from '../../containers/backdrop-library.jsx';
import Watermark from '../../containers/watermark.jsx';
@@ -156,6 +157,7 @@ const GUIComponent = props => {
dir={isRtl ? 'rtl' : 'ltr'}
{...componentProps}
>
<MysteryMode />
{telemetryModalVisible ? (
<TelemetryModal
onCancel={onTelemetryModalCancel}
+20
View File
@@ -32,6 +32,7 @@ import MenuBarHOC from '../../containers/menu-bar-hoc.jsx';
import {openTipsLibrary} from '../../reducers/modals';
import {setPlayer} from '../../reducers/mode';
import {toggleMysteryMode} from '../../reducers/mystery-mode';
import {
autoUpdateProject,
getIsUpdating,
@@ -469,6 +470,21 @@ class MenuBar extends React.Component {
)}
</MenuItem>
)}</TurboMode>
<MenuItem onClick={this.props.onClickToggleMysteryMode}>
{this.props.mysteryMode ? (
<FormattedMessage
defaultMessage="Turn off Mystery Mode"
description="Menu bar item for turning off dark mode"
id="gui.menuBar.mysteryModeOff"
/>
) : (
<FormattedMessage
defaultMessage="Turn on Mystery Mode"
description="Menu bar item for turning on dark mode"
id="gui.menuBar.mysteryModeOn"
/>
)}
</MenuItem>
</MenuSection>
</MenuBarMenu>
</div>
@@ -722,6 +738,7 @@ MenuBar.propTypes = {
locale: PropTypes.string.isRequired,
loginMenuOpen: PropTypes.bool,
logo: PropTypes.string,
mysteryMode: PropTypes.bool,
onClickAccount: PropTypes.func,
onClickEdit: PropTypes.func,
onClickFile: PropTypes.func,
@@ -732,6 +749,7 @@ MenuBar.propTypes = {
onClickRemix: PropTypes.func,
onClickSave: PropTypes.func,
onClickSaveAsCopy: PropTypes.func,
onClickToggleMysteryMode: PropTypes.func,
onLogOut: PropTypes.func,
onOpenRegistration: PropTypes.func,
onOpenTipLibrary: PropTypes.func,
@@ -772,6 +790,7 @@ const mapStateToProps = (state, ownProps) => {
languageMenuOpen: languageMenuOpen(state),
locale: state.locales.locale,
loginMenuOpen: loginMenuOpen(state),
mysteryMode: state.scratchGui.mysteryMode,
projectTitle: state.scratchGui.projectTitle,
sessionExists: state.session && typeof state.session.session !== 'undefined',
username: user ? user.username : null,
@@ -798,6 +817,7 @@ const mapDispatchToProps = dispatch => ({
onClickRemix: () => dispatch(remixProject()),
onClickSave: () => dispatch(manualUpdateProject()),
onClickSaveAsCopy: () => dispatch(saveProjectAsCopy()),
onClickToggleMysteryMode: () => dispatch(toggleMysteryMode()),
onSeeCommunity: () => dispatch(setPlayer(true))
});
@@ -0,0 +1,9 @@
.mystery-mode {
position: absolute;
width: 100%;
height: 100%;
opacity: 0.9;
background: transparent url('./mystery.png') center center;
z-index: 50;
pointer-events: none;
}
@@ -0,0 +1,55 @@
import PropTypes from 'prop-types';
import React from 'react';
import bindAll from 'lodash.bindall';
import styles from './mystery-mode.css';
import {connect} from 'react-redux';
class MysteryMode extends React.Component {
constructor (props) {
super(props);
bindAll(this, [
'handleMouseMove'
]);
this.state = {
x: window.innerWidth / 2,
y: window.innerHeight / 2
};
}
componentDidMount () {
document.addEventListener('mousemove', this.handleMouseMove);
}
componentWillUnmount () {
document.removeEventListener('mousemove', this.handleMouseMove);
}
handleMouseMove (event) {
this.setState({x: event.clientX, y: event.clientY});
}
render () {
if (!this.props.show) return null;
return (
<div
className={styles.mysteryMode}
style={{
backgroundPosition: `${this.state.x + 2000}px ${this.state.y + 2000}px`
}}
/>
);
}
}
MysteryMode.propTypes = {
show: PropTypes.bool
};
const mapStateToProps = state => ({
// This is the button's mode, as opposed to the actual current state
show: state.scratchGui.mysteryMode
});
export default connect(
mapStateToProps
)(MysteryMode);
Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

+60
View File
@@ -0,0 +1,60 @@
import bindAll from 'lodash.bindall';
import PropTypes from 'prop-types';
import React from 'react';
import {connect} from 'react-redux';
/**
* Turbo Mode component passes toggleTurboMode function to its child.
* It also includes `turboMode` in the props passed to the children.
* It expects this child to be a function with the signature
* function (toggleTurboMode, {turboMode, ...props}) {}
* The component can then be used to attach turbo mode setting functionality
* to any other component:
*
* <TurboMode>{(toggleTurboMode, props) => (
* <MyCoolComponent
* turboEnabled={props.turboMode}
* onClick={toggleTurboMode}
* {...props}
* />
* )}</TurboMode>
*/
class TurboMode extends React.Component {
constructor (props) {
super(props);
bindAll(this, [
'toggleTurboMode'
]);
}
toggleTurboMode () {
this.props.vm.setTurboMode(!this.props.turboMode);
}
render () {
const {
/* eslint-disable no-unused-vars */
children,
vm,
/* eslint-enable no-unused-vars */
...props
} = this.props;
return this.props.children(this.toggleTurboMode, props);
}
}
TurboMode.propTypes = {
children: PropTypes.func,
turboMode: PropTypes.bool,
vm: PropTypes.shape({
setTurboMode: PropTypes.func
})
};
const mapStateToProps = state => ({
vm: state.scratchGui.vm,
turboMode: state.scratchGui.vmStatus.turbo
});
export default connect(
mapStateToProps,
() => ({}) // omit dispatch prop
)(TurboMode);
+17 -3
View File
@@ -77,6 +77,13 @@ class Stage extends React.Component {
this.attachMouseEvents(this.canvas);
this.updateRect();
this.props.vm.runtime.addListener('QUESTION', this.questionListener);
// The GUI component seems to be recreated when entering/exiting editor mode.
// If we only update mystery mode in componentDidUpdate, it won't
// update when switching between editor and player mode.
if (this.props.mysteryMode !== this.renderer._mystery.modeActive) {
this.renderer.setMysteryMode(this.props.mysteryMode);
}
}
shouldComponentUpdate (nextProps, nextState) {
return this.props.stageSize !== nextProps.stageSize ||
@@ -85,7 +92,8 @@ class Stage extends React.Component {
this.props.isFullScreen !== nextProps.isFullScreen ||
this.state.question !== nextState.question ||
this.props.micIndicator !== nextProps.micIndicator ||
this.props.isStarted !== nextProps.isStarted;
this.props.isStarted !== nextProps.isStarted ||
this.props.mysteryMode !== nextProps.mysteryMode;
}
componentDidUpdate (prevProps) {
if (this.props.isColorPicking && !prevProps.isColorPicking) {
@@ -93,6 +101,9 @@ class Stage extends React.Component {
} else if (!this.props.isColorPicking && prevProps.isColorPicking) {
this.stopColorPickingLoop();
}
if (this.props.mysteryMode !== prevProps.mysteryMode) {
this.renderer.setMysteryMode(this.props.mysteryMode);
}
this.updateRect();
this.renderer.resize(this.rect.width, this.rect.height);
}
@@ -429,7 +440,8 @@ Stage.propTypes = {
onDeactivateColorPicker: PropTypes.func,
stageSize: PropTypes.oneOf(Object.keys(STAGE_DISPLAY_SIZES)).isRequired,
useEditorDragStyle: PropTypes.bool,
vm: PropTypes.instanceOf(VM).isRequired
vm: PropTypes.instanceOf(VM).isRequired,
mysteryMode: PropTypes.bool
};
Stage.defaultProps = {
@@ -442,7 +454,9 @@ const mapStateToProps = state => ({
isStarted: state.scratchGui.vmStatus.started,
micIndicator: state.scratchGui.micIndicator,
// Do not use editor drag style in fullscreen or player mode.
useEditorDragStyle: !(state.scratchGui.mode.isFullScreen || state.scratchGui.mode.isPlayerOnly)
useEditorDragStyle: !(state.scratchGui.mode.isFullScreen || state.scratchGui.mode.isPlayerOnly),
mysteryMode: state.scratchGui.mysteryMode && !(
state.scratchGui.mode.isFullScreen || state.scratchGui.mode.isPlayerOnly)
});
const mapDispatchToProps = dispatch => ({
+18
View File
@@ -51,6 +51,9 @@ import libraryCodeCartoon from './thumbnails/code-a-cartoon.jpg';
// Talking Tales
import libraryTalking from './thumbnails/talking.png';
// Sprite Mystery
import librarySpriteMystery from './thumbnails/sprite-mystery.png';
// Videos
import recordASound from './thumbnails/record-a-sound.jpg';
import glideAroundThumb from './thumbnails/glide-around.jpg';
@@ -497,6 +500,21 @@ export default {
urlId: 'animations-that-talk'
},
'sprite-mystery': {
name: 'How to Find a Sprite',
img: librarySpriteMystery,
steps: [{
video: 'sprite-mystery'
}, {
deckIds: [
'intro-move-sayhello',
'add-sprite'
]
}
],
urlId: 'sprite-mystery'
},
'talking': {
name: (
<FormattedMessage
Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

@@ -129,6 +129,9 @@ const videos = {
},
'talking': {
en: 'j0208mq4qi'
},
'sprite-mystery': {
en: 's69h0y6cs4'
}
};
+3
View File
@@ -14,6 +14,7 @@ import modalReducer, {modalsInitialState} from './modals';
import modeReducer, {modeInitialState} from './mode';
import monitorReducer, {monitorsInitialState} from './monitors';
import monitorLayoutReducer, {monitorLayoutInitialState} from './monitor-layout';
import mysteryModeReducer, {mysteryModeInitialState} from './mystery-mode';
import projectChangedReducer, {projectChangedInitialState} from './project-changed';
import projectStateReducer, {projectStateInitialState} from './project-state';
import projectTitleReducer, {projectTitleInitialState} from './project-title';
@@ -48,6 +49,7 @@ const guiInitialState = {
modals: modalsInitialState,
monitors: monitorsInitialState,
monitorLayout: monitorLayoutInitialState,
mysteryMode: mysteryModeInitialState,
projectChanged: projectChangedInitialState,
projectState: projectStateInitialState,
projectTitle: projectTitleInitialState,
@@ -146,6 +148,7 @@ const guiReducer = combineReducers({
modals: modalReducer,
monitors: monitorReducer,
monitorLayout: monitorLayoutReducer,
mysteryMode: mysteryModeReducer,
projectChanged: projectChangedReducer,
projectState: projectStateReducer,
projectTitle: projectTitleReducer,
+26
View File
@@ -0,0 +1,26 @@
const TOGGLE_MYSTERY_MODE = 'scratch-gui/mystery-mode/TOGGLE_MYSTERY_MODE';
const initialState = false;
const reducer = function (state, action) {
if (typeof state === 'undefined') state = initialState;
switch (action.type) {
case TOGGLE_MYSTERY_MODE:
return !state;
default:
return state;
}
};
const toggleMysteryMode = function () {
return {
type: TOGGLE_MYSTERY_MODE
};
};
export {
reducer as default,
initialState as mysteryModeInitialState,
toggleMysteryMode
};