Merge pull request from tmickel/modules

Modules
This commit is contained in:
Tim Mickel 2016-02-03 15:26:32 -05:00
commit b7c5a92f51
1018 changed files with 23741 additions and 33539 deletions

View file

@ -1 +1,2 @@
src/external/
src/build/

103
.eslintrc
View file

@ -1,5 +1,7 @@
{
"parser": "babel-eslint",
"rules": {
"strict": 0,
"curly": [2, "multi-line"],
"eol-last": [2],
"indent": [2, 4],
@ -19,106 +21,9 @@
"globals": {
"AndroidInterface": true,
"window": true,
"Cookie": true,
"getUrlVars": true,
"libInit": true,
"vlen": true,
"gn": true,
"CSSTransition": true,
"CSSTransition3D": true,
"WebKitCSSMatrix": true,
"globalx": true,
"globaly": true,
"localx": true,
"localy": true,
"getIdFor": true,
"hitRect": true,
"hit3DRect": true,
"rgb2hsb": true,
"colorToRGBA": true,
"drawScaled": true,
"getDocumentHeight": true,
"getDocumentWidth": true,
"setCanvasSizeScaledToWindowDocumentHeight": true,
"newHTML": true,
"newCanvas": true,
"newDiv": true,
"newP": true,
"newTextInput": true,
"newImage": true,
"getStringSize": true,
"setCanvasSize": true,
"setProps": true,
"frame": true,
"writeText": true,
"fitInRect": true,
"rgbToHex": true,
"Vector": true,
"DrawPath": true,
"drawThumbnail": true,
"ScratchJr": true,
"Runtime": true,
"Localization": true,
"iOS": true,
"Settings": true,
"BlockSpecs": true,
"Block": true,
"BlockArg": true,
"Stage": true,
"Project": true,
"Scroll": true,
"Thread": true,
"Scripts": true,
"ScratchAudio": true,
"Library": true,
"Paint": true,
"Record": true,
"Prims": true,
"Undo": true,
"Events": true,
"Menu": true,
"IO": true,
"UI": true,
"Thumbs": true,
"Grid": true,
"Alert": true,
"Palette": true,
"ScriptsPane": true,
"MediaLib": true,
"Sprite": true,
"Rectangle": true,
"Matrix": true,
"Page": true,
"Home": true,
"Lobby": true,
"Samples": true,
"Camera": true,
"getIdForCamera": true,
"Ghost": true,
"Layers": true,
"Paint": true,
"PaintAction": true,
"PaintIO": true,
"PaintLayout": true,
"PaintUndo": true,
"SVGTools": true,
"SVGImage": true,
"Transform": true,
"Layer": true,
"Path": true,
"DEGTOR": true,
"xform": true,
"selxform": true,
"SVG2Canvas": true,
"isTablet": true,
"isiOS": true,
"isAndroid": true,
"scaleMultiplier": true,
"JSZip": true,
"Snap": true,
"IntlMessageFormat": true,
"Sound": true,
"webkitAudioContext": true
"webkitAudioContext": true,
"require": true
},
"extends": "eslint:recommended"
}

1
.gitignore vendored
View file

@ -1,4 +1,5 @@
/android/ScratchJr/app/src/main/gen/
/node_modules
/src/build/
.DS_Store
*.iml

View file

@ -22,7 +22,7 @@ android {
minSdkVersion 17
targetSdkVersion 23
versionCode 20
versionName "1.1"
versionName "1.2.0"
}
}
}
@ -52,6 +52,11 @@ task switchToFreeGA(type: Copy) {
into "$appModuleRootFolder"
}
task generateWebpackBundle(type: Exec) {
workingDir '../../../bin'
commandLine './bundle-compile.sh'
}
class GenerateScratchJrPNGsTask extends DefaultTask {
File commonHome = project.file("../../..")
File binDir = project.file("${commonHome}/bin")
@ -86,6 +91,7 @@ task generateScratchJrPNGs(type: GenerateScratchJrPNGsTask)
task cleanScratchJrResources(type: CleanScratchJrResourcesTask)
afterEvaluate {
preBuild.dependsOn generateWebpackBundle
processFreeDebugGoogleServices.dependsOn switchToFreeGA
processFreeReleaseGoogleServices.dependsOn switchToFreeGA
prepareFreeDebugDependencies.dependsOn switchToFree

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
<string name="app_name">ScratchJr Free</string>
<string name="app_version">1.1</string>
<string name="app_version">1.2.0</string>
<string name="share_extension_filter">.*\\.sjr</string>
<string name="share_mimetype">application/x-scratchjr-project</string>
</resources>

3
bin/bundle-compile.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
cd ..;
/usr/local/bin/node ./node_modules/webpack/bin/webpack.js

View file

@ -49,7 +49,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.1</string>
<string>1.2.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>

View file

@ -1,43 +0,0 @@
var MediaLib = function() {};
MediaLib.path ="./svglibrary/";
// Sample project names are localized in Samples.js
MediaLib.samples = [
"samples/Star.txt"
]
// The names here are only for compatibility with the asset tool - they are localized below
MediaLib.backgrounds = [
{"md5":"Farm.svg","width":480,"height":360,"ext":"svg","name":"Farm"}
]
// The names here are only for compatibility with the asset tool - they are localized below
MediaLib.sprites = [
{"md5":"Star.svg","width":80,"height":101,"ext":"svg","name":"Star","order":"characters,07 weather","tags":["characters","07 weather"]}
];
// Localize names of sprites
for (var i = 0; i < MediaLib.sprites.length; i++) {
MediaLib.sprites[i].name = Localization.localize("CHARACTER_" + MediaLib.sprites[i].md5);
}
// Localize names of backgrounds
for (var i = 0; i < MediaLib.backgrounds.length; i++) {
MediaLib.backgrounds[i].name = Localization.localize("BACKGROUND_" + MediaLib.backgrounds[i].md5);
}
// Generate dictionary references to sprites and backgrounds (MediaLib.keys)
MediaLib.keys = {};
for (var i = 0; i < MediaLib.backgrounds.length; i++) {
var bg = MediaLib.backgrounds[i];
MediaLib.keys[bg.md5] = {width: bg.width, height: bg.height, name: bg.name};
}
for (var i = 0; i < MediaLib.sprites.length; i++) {
var spr = MediaLib.sprites[i];
MediaLib.keys[spr.md5] = {width: spr.width, height: spr.height, name: spr.name};
}
MediaLib.sounds = ["pop.mp3"];

View file

@ -1,26 +0,0 @@
window.Settings = {
edition: 'free',
scratchJrVersion: 'iOSv01',
useStoryStarters: false,
shareEnabled: true,
defaultSprite: 'Star.svg',
spriteOutlineColor: 'white',
stageColor: '#F5F2F7',
textSpriteFont: 'Helvetica',
blockArgFont: 'Verdana',
paletteBalloonFont: 'Roboto',
categoryStartColor: '#FFE75A',
categoryMotionColor: '#4B8CC2',
categoryLooksColor: '#CD7CD1',
categorySoundColor: '#48CC7E',
categoryFlowColor: '#FFBE57',
categoryStopColor: '#D62222',
paletteBlockShadowOpacity: 0.8,
autoSaveInterval: 30 * 1000,
defaultLocale: 'en',
defaultLocaleShort: 'en',
supportedLocales: {
'English': 'en',
'Español': 'es'
}
};

View file

@ -7,107 +7,13 @@
<head>
<title>Junior</title>
<script type="text/javascript" src="./Settings.js"></script>
<script type="text/javascript" src="jssource/utils/Cookie.js"></script>
<script type="text/javascript" src="jssource/utils/lib.js"></script>
<script>
preprocessAndLoadCss("css", "css/font.css");
preprocessAndLoadCss("css", "css/base.css");
preprocessAndLoadCss("css", "css/editor.css");
preprocessAndLoadCss("css", "css/editorleftpanel.css");
preprocessAndLoadCss("css", "css/editorstage.css");
preprocessAndLoadCss("css", "css/editormodal.css");
preprocessAndLoadCss("css", "css/librarymodal.css");
preprocessAndLoadCss("css", "css/paintlook.css");
window.scratchJrPage = 'editor';
</script>
<!-- Localization includes -->
<script type="text/javascript" src="jssource/external/Intl/Intl.min.js"></script>
<script type="text/javascript" src="jssource/external/intl-messageformat/intl-messageformat.min.js"></script>
<script type="text/javascript" src="jssource/utils/Localization.js"></script>
<script>
Localization.includeLocales();
</script>
<!-- End localization includes -->
<script type="text/javascript" src="jssource/external/snap.svg-min.js"></script>
<script type="text/javascript" src="./MediaLib.js"></script>
<script type="text/javascript" src="jssource/iPad/iOS.js"></script>
<script type="text/javascript" src="jssource/iPad/IO.js"></script>
<script type="text/javascript" src="jssource/utils/ScratchAudio.js"></script>
<script type="text/javascript" src="jssource/utils/Sound.js"></script>
<script type="text/javascript" src="jssource/utils/DrawPath.js"></script>
<script type="text/javascript" src="jssource/utils/SVG2Canvas.js"></script>
<script type="text/javascript" src="jssource/utils/Events.js"></script>
<script type="text/javascript" src="jssource/external/jszip.js"></script>
<script type="text/javascript" src="jssource/editor/blocks/Block.js"></script>
<script type="text/javascript" src="jssource/editor/blocks/BlockArg.js"></script>
<script type="text/javascript" src="jssource/editor/blocks/Menu.js"></script>
<script type="text/javascript" src="jssource/editor/blocks/BlockSpecs.js"></script>
<script type="text/javascript" src="jssource/editor/ScratchJr.js"></script>
<script type="text/javascript" src="jssource/editor/ui/Thumbs.js"></script>
<script type="text/javascript" src="jssource/editor/ui/Alert.js"></script>
<script type="text/javascript" src="jssource/editor/ui/Palette.js"></script>
<script type="text/javascript" src="jssource/editor/ui/Project.js"></script>
<script type="text/javascript" src="jssource/editor/ui/Grid.js"></script>
<script type="text/javascript" src="jssource/editor/ui/Undo.js"></script>
<script type="text/javascript" src="jssource/editor/ui/UI.js"></script>
<script type="text/javascript" src="jssource/editor/ui/Library.js"></script>
<script type="text/javascript" src="jssource/editor/ui/Record.js"></script>
<script type="text/javascript" src="jssource/editor/ui/Scripts.js"></script>
<script type="text/javascript" src="jssource/editor/ui/Scroll.js"></script>
<script type="text/javascript" src="jssource/editor/ui/ScriptsPane.js"></script>
<script type="text/javascript" src="jssource/editor/engine/Stage.js"></script>
<script type="text/javascript" src="jssource/editor/engine/Page.js"></script>
<script type="text/javascript" src="jssource/editor/engine/Sprite.js"></script>
<script type="text/javascript" src="jssource/editor/engine/Runtime.js"></script>
<script type="text/javascript" src="jssource/editor/engine/Prims.js"></script>
<script type="text/javascript" src="jssource/editor/engine/Thread.js"></script>
<script type="text/javascript" src="jssource/geom/Matrix.js"></script>
<script type="text/javascript" src="jssource/geom/Vector.js"></script>
<script type="text/javascript" src="jssource/geom/Rectangle.js"></script>
<script type="text/javascript" src="jssource/painteditor/Paint.js"></script>
<script type="text/javascript" src="jssource/painteditor/PaintLayout.js"></script>
<script type="text/javascript" src="jssource/painteditor/PaintIO.js"></script>
<script type="text/javascript" src="jssource/painteditor/Camera.js"></script>
<script type="text/javascript" src="jssource/painteditor/SVGImage.js"></script>
<script type="text/javascript" src="jssource/painteditor/PaintUndo.js"></script>
<script type="text/javascript" src="jssource/painteditor/SVGTools.js"></script>
<script type="text/javascript" src="jssource/painteditor/Transform.js"></script>
<script type="text/javascript" src="jssource/painteditor/PaintAction.js"></script>
<script type="text/javascript" src="jssource/painteditor/PathMgmt.js"></script>
<script type="text/javascript" src="jssource/painteditor/PathEdit.js"></script>
<script type="text/javascript" src="jssource/painteditor/PathTools.js"></script>
<script type="text/javascript" src="jssource/painteditor/PathBkg.js"></script>
<script type="text/javascript" src="jssource/painteditor/Layers.js"></script>
<script type="text/javascript" src="jssource/painteditor/Ghost.js"></script>
<script language="javascript">
function createScratchJr(){
iOS.getsettings(doNext);
function doNext (str){
var list = str.split(",");
iOS.path =list[1] == "0" ? list[0] + "/" : undefined ;
if (list.length > 2) Record.available = list[2] == "YES" ? true : false;
if (list.length > 3) Camera.available = list[3] == "YES" ? true : false;
ScratchJr.appinit(Settings.scratchJrVersion);
}
}
</script>
<script type="text/javascript" src="jssource/build/bundles/app.bundle.js"></script>
</head>
<body onload="iOS.waitForInterface(createScratchJr);" style="background: white;">
<body style="background: white;">
<div class="frame" id="frame"></div>
<div class="libframe" id="libframe"></div>
<div class="paintframe" id="paintframe"></div>

View file

@ -7,70 +7,19 @@
<head>
<title>Junior</title>
<script type="text/javascript" src="./Settings.js"></script>
<script type="text/javascript" src="jssource/utils/Cookie.js"></script>
<script type="text/javascript" src="jssource/utils/lib.js"></script>
<!-- Localization includes -->
<script type="text/javascript" src="jssource/external/Intl/Intl.min.js"></script>
<script type="text/javascript" src="jssource/external/intl-messageformat/intl-messageformat.min.js"></script>
<script type="text/javascript" src="jssource/utils/Localization.js"></script>
<script>
Localization.includeLocales();
</script>
<!-- End localization includes -->
<!-- In case we receive a project on this page -->
<script type="text/javascript" src="jssource/utils/DrawPath.js"></script>
<script type="text/javascript" src="jssource/editor/ui/Alert.js"></script>
<script type="text/javascript" src="jssource/iPad/iOS.js"></script>
<script type="text/javascript" src="jssource/iPad/IO.js"></script>
<script type="text/javascript" src="./MediaLib.js"></script>
<script type="text/javascript" src="jssource/external/jszip.js"></script>
<script>
preprocessAndLoadCss("css", "css/font.css");
preprocessAndLoadCss("css", "css/base.css");
preprocessAndLoadCss("css", "css/gs.css");
</script>
<script language="javascript">
var place;
function tutorialScratchJr(){
var urlvars = getUrlVars();
place = urlvars['place'];
document.ontouchmove = function(e){e.preventDefault()};
}
function closeme (){
window.location.href = "home.html?place=" + place;
}
window.scratchJrPage = 'gettingStarted';
</script>
<script type="text/javascript" src="jssource/build/bundles/app.bundle.js"></script>
</head>
<body onload="iOS.waitForInterface(tutorialScratchJr);">
<body>
<div class="tutorial" id="tutorialmode">
<div class="closehelp" onclick="closeme()" ontouchstart="closeme()"></div>
<div class="closehelp" id="closeHelp"></div>
<div class="introvideocontainer">
<video class="introvideo" id="myVideo" controls></video>
</div>
</div>
<script>
var videoObj = document.getElementById("myVideo");
if (isiOS) {
// On iOS we can load from server
videoObj.src = "assets/lobby/intro.mp4";
} else {
// On Android we need to copy to a temporary directory first:
setTimeout(function() {
videoObj.type = "video/mp4";
videoObj.src = AndroidInterface.scratchjr_getgettingstartedvideopath();
}, 1000);
}
videoObj.poster = "assets/lobby/poster.png";
</script>
</body>
</html>

View file

@ -7,73 +7,18 @@
<head>
<title>Scratch Jr</title>
<script type="text/javascript" src="./Settings.js"></script>
<script type="text/javascript" src="jssource/utils/Cookie.js"></script>
<script type="text/javascript" src="jssource/utils/lib.js"></script>
<!-- Localization includes -->
<script type="text/javascript" src="jssource/external/Intl/Intl.min.js"></script>
<script type="text/javascript" src="jssource/external/intl-messageformat/intl-messageformat.min.js"></script>
<script type="text/javascript" src="jssource/utils/Localization.js"></script>
<script>
Localization.includeLocales();
</script>
<!-- End localization includes -->
<script type="text/javascript">
preprocessAndLoadCss("css", "css/font.css");
preprocessAndLoadCss("css", "css/base.css");
preprocessAndLoadCss("css", "css/lobby.css");
preprocessAndLoadCss("css", "css/thumbs.css");
</script>
<script type="text/javascript" src="jssource/lobby/Lobby.js"></script>
<script type="text/javascript" src="jssource/lobby/Home.js"></script>
<script type="text/javascript" src="jssource/lobby/Samples.js"></script>
<script type="text/javascript" src="jssource/utils/Events.js"></script>
<script type="text/javascript" src="jssource/utils/SVG2Canvas.js"></script>
<script type="text/javascript" src="jssource/utils/ScratchAudio.js"></script>
<script type="text/javascript" src="jssource/utils/Sound.js"></script>
<script type="text/javascript" src="jssource/external/jszip.js"></script>
<script type="text/javascript" src="jssource/editor/ui/Project.js"></script>
<script type="text/javascript" src="jssource/utils/DrawPath.js"></script>
<script type="text/javascript" src="jssource/editor/ui/Alert.js"></script>
<script type="text/javascript" src="jssource/iPad/iOS.js"></script>
<script type="text/javascript" src="jssource/iPad/IO.js"></script>
<script type="text/javascript" src="./MediaLib.js"></script>
<script type="text/javascript" src="jssource/geom/Vector.js"></script>
<script type="text/javascript" src="jssource/geom/Matrix.js"></script>
<script type="text/javascript" src="jssource/geom/Rectangle.js"></script>
<script type="text/javascript" src="jssource/painteditor/SVGImage.js"></script>
<script type="text/javascript" src="jssource/painteditor/Transform.js"></script>
<script type="text/javascript" src="jssource/painteditor/SVGTools.js"></script>
<script language="javascript">
function startup(){
iOS.getsettings(doNext);
function doNext (str){
var list = str.split(",");
iOS.path =list[1] == "0" ? list[0] + "/" : undefined ;
Lobby.appinit(Settings.scratchJrVersion);
}
}
function goBack(){window.location.href = "index.html?back=yes";}
window.scratchJrPage = 'home';
</script>
<script type="text/javascript" src="jssource/build/bundles/app.bundle.js"></script>
</head>
<body onload="iOS.waitForInterface(startup);">
<body>
<div class="frame" id="frame">
<div class="topbar" id="topbar">
<ul class="topbar-nav" id="nav">
<li class="logo" id="logotab" ontouchend="goBack();">
<li class="logo" id="logotab">
<span class="logo-icon"></span>
</li>
<div></div>
@ -113,19 +58,19 @@ function goBack(){window.location.href = "index.html?back=yes";}
<ul class="footer-nav" id="footernav">
<li class="tab" id="abouttab" >
<div class="about-icon"></div>
<span><script>document.write(Localization.localize("ABOUT_SCRATCHJR"));</script></span>
<span id="abouttab-text"></span>
</li>
<li class="tab" id="interfacetab">
<div class="interface-icon"></div>
<span><script>document.write(Localization.localize("INTERFACE_GUIDE"));</script></span>
<span id="interfacetab-text"></span>
</li>
<li class="tab" id="painttab">
<div class="paint-icon"></div>
<span><script>document.write(Localization.localize("PAINT_EDITOR_GUIDE"));</script></span>
<span id="painttab-text"></span>
</li>
<li class="tab2" id="blockstab">
<div class="blocks-icon"></div>
<span><script>document.write(Localization.localize("BLOCKS_GUIDE"));</script></span>
<span id="blockstab-text"></span>
</li>
<div></div>
</ul>

File diff suppressed because one or more lines are too long

View file

@ -1,25 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="../Settings.js"></script>
<script type="text/javascript" src="../jssource/utils/Cookie.js"></script>
<script type="text/javascript" src="../jssource/utils/lib.js"></script>
<script type="text/javascript" src="../jssource/iPad/iOS.js"></script>
<script>
preprocessAndLoadCss("style", "style/style.css");
preprocessAndLoadCss("style", "style/blocks.css");
</script>
<!-- Localization includes -->
<script type="text/javascript" src="../jssource/external/Intl/Intl.min.js"></script>
<script type="text/javascript" src="../jssource/external/intl-messageformat/intl-messageformat.min.js"></script>
<script type="text/javascript" src="../jssource/utils/Localization.js"></script>
<script>
Localization.root = "../";
Localization.includeLocales();
</script>
<!-- End localization includes -->
<meta charset="utf-8">
<script>
window.scratchJrPage = 'inappBlocksGuide';
</script>
<script type="text/javascript" src="../jssource/build/bundles/app.bundle.js"></script>
</head>
<body>
@ -28,366 +14,304 @@
<div class="learn-tab learn-blocks">
<!-- Yellow Blocks -->
<div class="block-category-header" id="yellow-block-category-header">
<script>document.write(Localization.localize("BLOCKS_TRIGGERING_BLOCKS"));</script>
</div>
<div class="block-category-header-line" id="yellow-block-category-header-line"></div>
<div class="block-wrapper">
<div class="block-wrapper-left">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_GREEN_FLAG"));</script>
<div class="block-title" id="BLOCKS_GREEN_FLAG">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/onflag.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_GREEN_FLAG_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_GREEN_FLAG_DESCRIPTION">
</div>
</div>
<div class="block-wrapper-right">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_ON_TAP"));</script>
<div class="block-title" id="BLOCKS_ON_TAP">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/ontap.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_ON_TAP_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_ON_TAP_DESCRIPTION">
</div>
</div>
</div>
<div class="block-wrapper">
<div class="block-wrapper-left">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_ON_TOUCH"));</script>
<div class="block-title" id="BLOCKS_ON_TOUCH">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/onbump.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_ON_TOUCH_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_ON_TOUCH_DESCRIPTION">
</div>
</div>
<div class="block-wrapper-right">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_ON_MESSAGE"));</script>
<div class="block-title" id="BLOCKS_ON_MESSAGE">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/messagereceive.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_ON_MESSAGE_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_ON_MESSAGE_DESCRIPTION">
</div>
</div>
</div>
<div class="block-wrapper">
<div class="block-wrapper-left">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_SEND_MESSAGE"));</script>
<div class="block-title" id="BLOCKS_SEND_MESSAGE">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/messagesend.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_SEND_MESSAGE_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_SEND_MESSAGE_DESCRIPTION">
</div>
</div>
</div>
<!-- Blue Blocks -->
<div class="block-category-header" id="blue-block-category-header">
<script>document.write(Localization.localize("BLOCKS_MOTION_BLOCKS"));</script>
</div>
<div class="block-category-header-line" id="blue-block-category-header-line"></div>
<div class="block-wrapper">
<div class="block-wrapper-left">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_MOVE_RIGHT"));</script>
<div class="block-title" id="BLOCKS_MOVE_RIGHT">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/right.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_MOVE_RIGHT_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_MOVE_RIGHT_DESCRIPTION">
</div>
</div>
<div class="block-wrapper-right">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_MOVE_LEFT"));</script>
<div class="block-title" id="BLOCKS_MOVE_LEFT">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/left.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_MOVE_LEFT_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_MOVE_LEFT_DESCRIPTION">
</div>
</div>
</div>
<div class="block-wrapper">
<div class="block-wrapper-left">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_MOVE_UP"));</script>
<div class="block-title" id="BLOCKS_MOVE_UP">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/up.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_MOVE_UP_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_MOVE_UP_DESCRIPTION">
</div>
</div>
<div class="block-wrapper-right">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_MOVE_DOWN"));</script>
<div class="block-title" id="BLOCKS_MOVE_DOWN">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/down.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_MOVE_DOWN_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_MOVE_DOWN_DESCRIPTION">
</div>
</div>
</div>
<div class="block-wrapper">
<div class="block-wrapper-left">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_TURN_RIGHT"));</script>
<div class="block-title" id="BLOCKS_TURN_RIGHT">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/turnright.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_TURN_RIGHT_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_TURN_RIGHT_DESCRIPTION">
</div>
</div>
<div class="block-wrapper-right">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_TURN_LEFT"));</script>
<div class="block-title" id="BLOCKS_TURN_LEFT">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/turnleft.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_TURN_LEFT_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_TURN_LEFT_DESCRIPTION">
</div>
</div>
</div>
<div class="block-wrapper">
<div class="block-wrapper-left">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_HOP"));</script>
<div class="block-title" id="BLOCKS_HOP">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/hop.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_HOP_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_HOP_DESCRIPTION">
</div>
</div>
<div class="block-wrapper-right">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_GO_HOME"));</script>
<div class="block-title" id="BLOCKS_GO_HOME">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/gohome.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_GO_HOME_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_GO_HOME_DESCRIPTION">
</div>
</div>
</div>
<!-- Purple Blocks -->
<div class="block-category-header" id="purple-block-category-header">
<script>document.write(Localization.localize("BLOCKS_LOOKS_BLOCKS"));</script>
</div>
<div class="block-category-header-line" id="purple-block-category-header-line"></div>
<div class="block-wrapper">
<div class="block-wrapper-left">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_SAY"));</script>
<div class="block-title" id="BLOCKS_SAY">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/say.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_SAY_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_SAY_DESCRIPTION">
</div>
</div>
<div class="block-wrapper-right">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_GROW"));</script>
<div class="block-title" id="BLOCKS_GROW">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/grow.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_GROW_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_GROW_DESCRIPTION">
</div>
</div>
</div>
<div class="block-wrapper">
<div class="block-wrapper-left">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_SHRINK"));</script>
<div class="block-title" id="BLOCKS_SHRINK">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/shrink.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_SHRINK_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_SHRINK_DESCRIPTION">
</div>
</div>
<div class="block-wrapper-right">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_RESET_SIZE"));</script>
<div class="block-title" id="BLOCKS_RESET_SIZE">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/reset.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_RESET_SIZE_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_RESET_SIZE_DESCRIPTION">
</div>
</div>
</div>
<div class="block-wrapper">
<div class="block-wrapper-left">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_HIDE"));</script>
<div class="block-title" id="BLOCKS_HIDE">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/hide.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_HIDE_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_HIDE_DESCRIPTION">
</div>
</div>
<div class="block-wrapper-right">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_SHOW"));</script>
<div class="block-title" id="BLOCKS_SHOW">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/show.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_SHOW_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_SHOW_DESCRIPTION">
</div>
</div>
</div>
<div class="block-category-header" id="green-block-category-header">
<script>document.write(Localization.localize("BLOCKS_SOUND_BLOCKS"));</script>
</div>
<div class="block-category-header-line" id="green-block-category-header-line"></div>
<div class="block-wrapper">
<div class="block-wrapper-left">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_POP"));</script>
<div class="block-title" id="BLOCKS_POP">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/pop.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_POP_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_POP_DESCRIPTION">
</div>
</div>
<div class="block-wrapper-right">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_PLAY_RECORDED"));</script>
<div class="block-title" id="BLOCKS_PLAY_RECORDED">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/playsound.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_PLAY_RECORDED_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_PLAY_RECORDED_DESCRIPTION">
</div>
</div>
</div>
<div class="block-category-header" id="orange-block-category-header">
<script>document.write(Localization.localize("BLOCKS_CONTROL_BLOCKS"));</script>
</div>
<div class="block-category-header-line" id="orange-block-category-header-line"></div>
<div class="block-wrapper">
<div class="block-wrapper-left">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_WAIT"));</script>
<div class="block-title" id="BLOCKS_WAIT">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/wait.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_WAIT_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_WAIT_DESCRIPTION">
</div>
</div>
<div class="block-wrapper-right">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_STOP"));</script>
<div class="block-title" id="BLOCKS_STOP">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/stop.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_STOP_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_STOP_DESCRIPTION">
</div>
</div>
</div>
<div class="block-wrapper">
<div class="block-wrapper-left">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_SET_SPEED"));</script>
<div class="block-title" id="BLOCKS_SET_SPEED">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/speed.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_SET_SPEED_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_SET_SPEED_DESCRIPTION">
</div>
</div>
<div class="block-wrapper-right">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_REPEAT"));</script>
<div class="block-title" id="BLOCKS_REPEAT">
</div>
<div class="block-image-wrapper">
<img class="block-image-repeat" src="images/repeat.png" />
</div>
<div class="block-description-repeat">
<script>document.write(Localization.localize("BLOCKS_REPEAT_DESCRIPTION"));</script>
<div class="block-description-repeat" id="BLOCKS_REPEAT_DESCRIPTION">
</div>
</div>
</div>
<div class="block-category-header" id="red-block-category-header">
<script>document.write(Localization.localize("BLOCKS_END_BLOCKS"));</script>
</div>
<div class="block-category-header-line" id="red-block-category-header-line"></div>
<div class="block-wrapper">
<div class="block-wrapper-left">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_END"));</script>
<div class="block-title" id="BLOCKS_END">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/end.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_END_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_END_DESCRIPTION">
</div>
</div>
<div class="block-wrapper-right">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_REPEAT_FOREVER"));</script>
<div class="block-title" id="BLOCKS_REPEAT_FOREVER">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/forever.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_REPEAT_FOREVER_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_REPEAT_FOREVER_DESCRIPTION">
</div>
</div>
</div>
<div class="block-wrapper">
<div class="block-wrapper-left">
<div class="block-title">
<script>document.write(Localization.localize("BLOCKS_GO_TO_PAGE"));</script>
<div class="block-title" id="BLOCKS_GO_TO_PAGE">
</div>
<div class="block-image-wrapper">
<img class="block-image" src="images/page.png" />
</div>
<div class="block-description">
<script>document.write(Localization.localize("BLOCKS_GO_TO_PAGE_DESCRIPTION"));</script>
<div class="block-description" id="BLOCKS_GO_TO_PAGE_DESCRIPTION">
</div>
</div>
</div>

View file

@ -1,24 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="../Settings.js"></script>
<script type="text/javascript" src="../jssource/utils/Cookie.js"></script>
<script type="text/javascript" src="../jssource/utils/lib.js"></script>
<script>
preprocessAndLoadCss("style", "style/style.css");
preprocessAndLoadCss("style", "style/interface.css");
</script>
<!-- Localization includes -->
<script type="text/javascript" src="../jssource/external/Intl/Intl.min.js"></script>
<script type="text/javascript" src="../jssource/external/intl-messageformat/intl-messageformat.min.js"></script>
<script type="text/javascript" src="../jssource/utils/Localization.js"></script>
<script>
Localization.root = "../";
Localization.includeLocales();
</script>
<!-- End localization includes -->
<meta charset="utf-8">
<script>
window.scratchJrPage = 'inappInterfaceGuide';
</script>
<script type="text/javascript" src="../jssource/build/bundles/app.bundle.js"></script>
</head>
<body>
<div id="content">
@ -28,13 +15,13 @@
<div class="learn-tab learn-tab-selected learn-interface">
<!-- 1. Save -->
<div class="interface-button interface-button-selected" id="interface-button-save">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 1}));</script></div>
<div class="interface-button-text">1</div>
</div>
<div class="interface-vertical-line" id="interface-vertical-line-save"></div>
<div class="interface-dot" id="interface-dot-save"></div>
<!-- 2. Stage -->
<div class="interface-button" id="interface-button-stage">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 2}));</script></div>
<div class="interface-button-text">2</div>
</div>
<div class="interface-vertical-line" id="interface-vertical-line-stage-1"></div>
<div class="interface-horizontal-line" id="interface-horizontal-line-stage-1"></div>
@ -43,55 +30,55 @@
<div class="interface-horizontal-line" id="interface-horizontal-line-stage-3"></div>
<!-- 3. Presentation Mode -->
<div class="interface-button" id="interface-button-presentation-mode">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 3}));</script></div>
<div class="interface-button-text">3</div>
</div>
<div class="interface-vertical-line" id="interface-vertical-line-presentation-mode"></div>
<div class="interface-dot" id="interface-dot-presentation-mode"></div>
<!-- 4. Grid -->
<div class="interface-button" id="interface-button-grid">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 4}));</script></div>
<div class="interface-button-text">4</div>
</div>
<div class="interface-vertical-line" id="interface-vertical-line-grid"></div>
<div class="interface-dot" id="interface-dot-grid"></div>
<!-- 5. Change Background -->
<div class="interface-button" id="interface-button-add-text">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 5}));</script></div>
<div class="interface-button-text">5</div>
</div>
<div class="interface-vertical-line" id="interface-vertical-line-add-text"></div>
<div class="interface-dot" id="interface-dot-add-text"></div>
<!-- 6. Add Text -->
<div class="interface-button" id="interface-button-change-background">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 6}));</script></div>
<div class="interface-button-text">6</div>
</div>
<div class="interface-vertical-line" id="interface-vertical-line-change-background"></div>
<div class="interface-dot" id="interface-dot-change-background"></div>
<!-- 7. Reset Characters -->
<div class="interface-button" id="interface-button-reset-characters">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 7}));</script></div>
<div class="interface-button-text">7</div>
</div>
<div class="interface-vertical-line" id="interface-vertical-line-reset-characters"></div>
<div class="interface-dot" id="interface-dot-reset-characters"></div>
<!-- 8. Green Flag -->
<div class="interface-button" id="interface-button-green-flag">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 8}));</script></div>
<div class="interface-button-text">8</div>
</div>
<div class="interface-vertical-line" id="interface-vertical-line-green-flag"></div>
<div class="interface-dot" id="interface-dot-green-flag"></div>
<!-- 9. Pages -->
<div class="interface-button" id="interface-button-pages">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 9}));</script></div>
<div class="interface-button-text">9</div>
</div>
<div class="interface-vertical-line" id="interface-vertical-line-pages"></div>
<div class="interface-dot" id="interface-dot-pages"></div>
<!-- 10. Project Information -->
<div class="interface-button" id="interface-button-project-information">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 10}));</script></div>
<div class="interface-button-text">10</div>
</div>
<div class="interface-vertical-line" id="interface-vertical-line-project-information"></div>
<div class="interface-dot" id="interface-dot-project-information"></div>
<!-- 16. Characters -->
<div class="interface-button" id="interface-button-characters">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 16}));</script></div>
<div class="interface-button-text">16</div>
</div>
<div class="interface-vertical-line" id="interface-vertical-line-characters-1"></div>
<div class="interface-vertical-line" id="interface-vertical-line-characters-3"></div>
@ -99,7 +86,7 @@
<div class="interface-vertical-line" id="interface-vertical-line-characters-2"></div>
<!-- 15. Block Categories -->
<div class="interface-button" id="interface-button-block-categories">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 15}));</script></div>
<div class="interface-button-text">15</div>
</div>
<div class="interface-vertical-line" id="interface-vertical-line-block-categories-1"></div>
<div class="interface-horizontal-line" id="interface-horizontal-line-block-categories"></div>
@ -107,7 +94,7 @@
<div class="interface-vertical-line" id="interface-vertical-line-block-categories-3"></div>
<!-- 14. Blocks Palette -->
<div class="interface-button" id="interface-button-block-palette">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 14}));</script></div>
<div class="interface-button-text">14</div>
</div>
<div class="interface-horizontal-line" id="interface-horizontal-line-blocks-palette"></div>
<div class="interface-vertical-line" id="interface-vertical-line-blocks-palette-1"></div>
@ -115,13 +102,13 @@
<div class="interface-vertical-line" id="interface-vertical-line-blocks-palette-3"></div>
<!-- 13. Programming Area -->
<div class="interface-button" id="interface-button-programming-area">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 13}));</script></div>
<div class="interface-button-text">13</div>
</div>
<div class="interface-vertical-line" id="interface-vertical-line-programming-area"></div>
<div class="interface-dot" id="interface-dot-programming-area"></div>
<!-- 12. Programming Script -->
<div class="interface-button" id="interface-button-programming-script">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 12}));</script></div>
<div class="interface-button-text">12</div>
</div>
<div class="interface-vertical-line" id="interface-vertical-line-programming-script-1"></div>
<div class="interface-horizontal-line" id="interface-horizontal-line-programming-script"></div>
@ -129,7 +116,7 @@
<div class="interface-vertical-line" id="interface-vertical-line-programming-script-3"></div>
<!-- 11. Undo Redo -->
<div class="interface-button" id="interface-button-undo-redo">
<div class="interface-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 11}));</script></div>
<div class="interface-button-text">11</div>
</div>
<div class="interface-vertical-line" id="interface-vertical-line-undo-redo-1"></div>
<div class="interface-horizontal-line" id="interface-horizontal-line-undo-redo"></div>
@ -139,10 +126,8 @@
<div id="right-column">
<div id="interface-key">
<div id="interface-key-header">
<script>document.write(Localization.localize("INTERFACE_GUIDE_SAVE", {N:1}));</script>
</div>
<div id="interface-key-description">
<script>document.write(Localization.localize("INTERFACE_GUIDE_SAVE_DESCRIPTION"));</script>
</div>
</div>
<div id="video-wrapper">
@ -151,53 +136,5 @@
</div>
</div>
</div>
<script type="text/javascript">
var interfaceKeys = [
"SAVE",
"STAGE",
"PRESENTATION_MODE",
"GRID",
"CHANGE_BG",
"ADD_TEXT",
"RESET_CHAR",
"GREEN_FLAG",
"PAGES",
"PROJECT_INFO",
"UNDO_REDO",
"PROGRAMMING_SCRIPT",
"PROGRAMMING_AREA",
"BLOCKS_PALETTE",
"BLOCKS_CATEGORIES",
"CHARACTERS"
];
var interfaceDescriptions = [];
for (var i = 0; i < interfaceKeys.length; i++) {
var key = interfaceKeys[i];
interfaceDescriptions.push([
Localization.localize("INTERFACE_GUIDE_" + key, {N: i+1}),
Localization.localize("INTERFACE_GUIDE_" + key + "_DESCRIPTION")
]);
}
var interfaceKeyHeaderNode = document.getElementById('interface-key-header');
var interfaceKeyDescriptionNode = document.getElementById('interface-key-description');
var currentButton = document.getElementById('interface-button-save');
var switchHelp = function(e) {
var target = e.target;
if (target.className == 'interface-button-text') {
descriptionId = parseInt(target.innerText - 1);
interfaceKeyHeaderNode.textContent = interfaceDescriptions[descriptionId][0];
interfaceKeyDescriptionNode.textContent = interfaceDescriptions[descriptionId][1];
currentButton.className = 'interface-button';
currentButton = target.parentNode;
currentButton.className = currentButton.className + ' interface-button-selected';
parent.ScratchAudio.sndFXWithVolume("keydown.wav", 0.3);
}
};
document.addEventListener('touchstart', switchHelp, false);
</script>
</body>
</html>

View file

@ -1,24 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="../Settings.js"></script>
<script type="text/javascript" src="../jssource/utils/Cookie.js"></script>
<script type="text/javascript" src="../jssource/utils/lib.js"></script>
<script>
preprocessAndLoadCss("style", "style/style.css");
preprocessAndLoadCss("style", "style/paint.css");
</script>
<!-- Localization includes -->
<script type="text/javascript" src="../jssource/external/Intl/Intl.min.js"></script>
<script type="text/javascript" src="../jssource/external/intl-messageformat/intl-messageformat.min.js"></script>
<script type="text/javascript" src="../jssource/utils/Localization.js"></script>
<script>
Localization.root = "../";
Localization.includeLocales();
</script>
<!-- End localization includes -->
<meta charset="utf-8">
<script>
window.scratchJrPage = 'inappPaintEditorGuide';
</script>
<script type="text/javascript" src="../jssource/build/bundles/app.bundle.js"></script>
</head>
<body>
<div id="content">
@ -28,19 +15,19 @@
<div class="learn-tab learn-tab-selected learn-paint">
<!-- 1. Undo -->
<div class="paint-button paint-button-selected" id="paint-button-undo">
<div class="paint-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 1}));</script></div>
<div class="paint-button-text">1</div>
</div>
<div class="paint-vertical-line" id="paint-vertical-line-undo"></div>
<div class="paint-dot" id="paint-dot-undo"></div>
<!-- 2. Redo -->
<div class="paint-button" id="paint-button-redo">
<div class="paint-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 2}));</script></div>
<div class="paint-button-text">2</div>
</div>
<div class="paint-vertical-line" id="paint-vertical-line-redo"></div>
<div class="paint-dot" id="paint-dot-redo"></div>
<!-- 3. Select Shape -->
<div class="paint-button" id="paint-button-select-shape">
<div class="paint-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 3}));</script></div>
<div class="paint-button-text">3</div>
</div>
<div class="paint-vertical-line" id="paint-vertical-line-select-shape-1"></div>
<div class="paint-horizontal-line" id="paint-horizontal-line-select-shape-1"></div>
@ -49,13 +36,13 @@
<div class="paint-horizontal-line" id="paint-horizontal-line-select-shape-3"></div>
<!-- 4. Character Name -->
<div class="paint-button" id="paint-button-character-name">
<div class="paint-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 4}));</script></div>
<div class="paint-button-text">4</div>
</div>
<div class="paint-vertical-line" id="paint-vertical-line-character-name"></div>
<div class="paint-dot" id="paint-dot-character-name"></div>
<!-- 5. Cut -->
<div class="paint-button" id="paint-button-cut">
<div class="paint-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 5}));</script></div>
<div class="paint-button-text">5</div>
</div>
<div class="paint-vertical-line" id="paint-vertical-line-cut"></div>
<div class="paint-horizontal-line" id="paint-horizontal-line-cut"></div>
@ -63,48 +50,48 @@
<img class="ipad-project-view" src="images/paint.png" />
<!-- 6. Duplicate -->
<div class="paint-button" id="paint-button-duplicate">
<div class="paint-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 6}));</script></div>
<div class="paint-button-text">6</div>
</div>
<div class="paint-vertical-line" id="paint-vertical-line-duplicate"></div>
<div class="paint-horizontal-line" id="paint-horizontal-line-duplicate"></div>
<div class="paint-dot" id="paint-dot-duplicate"></div>
<!-- 7. Rotate -->
<div class="paint-button" id="paint-button-rotate">
<div class="paint-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 7}));</script></div>
<div class="paint-button-text">7</div>
</div>
<div class="paint-vertical-line" id="paint-vertical-line-rotate"></div>
<div class="paint-horizontal-line" id="paint-horizontal-line-rotate"></div>
<div class="paint-dot" id="paint-dot-rotate"></div>
<!-- 8. Drag -->
<div class="paint-button" id="paint-button-drag">
<div class="paint-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 8}));</script></div>
<div class="paint-button-text">8</div>
</div>
<div class="paint-vertical-line" id="paint-vertical-line-drag"></div>
<div class="paint-horizontal-line" id="paint-horizontal-line-drag"></div>
<div class="paint-dot" id="paint-dot-drag"></div>
<!-- 9. Save -->
<div class="paint-button" id="paint-button-save">
<div class="paint-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 9}));</script></div>
<div class="paint-button-text">9</div>
</div>
<div class="paint-vertical-line" id="paint-vertical-line-save"></div>
<div class="paint-dot" id="paint-dot-save"></div>
<!-- 10. Fill -->
<div class="paint-button" id="paint-button-fill">
<div class="paint-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 10}));</script></div>
<div class="paint-button-text">10</div>
</div>
<div class="paint-vertical-line" id="paint-vertical-line-fill"></div>
<div class="paint-horizontal-line" id="paint-horizontal-line-fill"></div>
<div class="paint-dot" id="paint-dot-fill"></div>
<!-- 11. Camera -->
<div class="paint-button" id="paint-button-camera">
<div class="paint-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 11}));</script></div>
<div class="paint-button-text">11</div>
</div>
<div class="paint-vertical-line" id="paint-vertical-line-camera"></div>
<div class="paint-horizontal-line" id="paint-horizontal-line-camera"></div>
<div class="paint-dot" id="paint-dot-camera"></div>
<!-- 12. Select Color -->
<div class="paint-button" id="paint-button-select-color">
<div class="paint-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 12}));</script></div>
<div class="paint-button-text">12</div>
</div>
<div class="paint-vertical-line" id="paint-vertical-line-select-color-1"></div>
<div class="paint-horizontal-line" id="paint-horizontal-line-select-color-1"></div>
@ -112,7 +99,7 @@
<div class="paint-vertical-line" id="paint-vertical-line-select-color-3"></div>
<!-- 13. Select Line Size -->
<div class="paint-button" id="paint-button-select-line-size">
<div class="paint-button-text"><script>document.write(Localization.localize("INTERFACE_GUIDE_NUMBER", {N: 13}));</script></div>
<div class="paint-button-text">13</div>
</div>
<div class="paint-vertical-line" id="paint-vertical-line-select-line-size-1"></div>
<div class="paint-horizontal-line" id="paint-horizontal-line-select-line-size-1"></div>
@ -121,58 +108,12 @@
<div class="paint-horizontal-line" id="paint-horizontal-line-select-line-size-3"></div>
<div id="paint-key">
<div id="paint-key-header">
<script>document.write(Localization.localize("PAINT_GUIDE_UNDO", {N:1}));</script>
</div>
<div id="paint-key-description">
<script>document.write(Localization.localize("PAINT_GUIDE_UNDO_DESCRIPTION"));</script>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var paintKeys = [
"UNDO",
"REDO",
"SHAPE",
"CHARACTER_NAME",
"CUT",
"DUPLICATE",
"ROTATE",
"DRAG",
"SAVE",
"FILL",
"CAMERA",
"COLOR",
"LINE_WIDTH"
];
var paintDescriptions = [];
for (var i = 0; i < paintKeys.length; i++) {
var key = paintKeys[i];
paintDescriptions.push([
Localization.localize("PAINT_GUIDE_" + key, {N: i+1}),
Localization.localize("PAINT_GUIDE_" + key + "_DESCRIPTION")
]);
}
var paintKeyHeaderNode = document.getElementById('paint-key-header');
var paintKeyDescriptionNode = document.getElementById('paint-key-description');
var currentButton = document.getElementById('paint-button-undo');
var switchHelp = function(e) {
var target = e.target;
if (target.className == 'paint-button-text') {
descriptionId = parseInt(target.innerText - 1);
paintKeyHeaderNode.textContent = paintDescriptions[descriptionId][0];
paintKeyDescriptionNode.textContent = paintDescriptions[descriptionId][1];
currentButton.className = 'paint-button';
currentButton = target.parentNode;
currentButton.className = currentButton.className + ' paint-button-selected';
parent.ScratchAudio.sndFXWithVolume("keydown.wav", 0.3);
}
};
document.addEventListener('touchstart', switchHelp, false);
</script>
</body>
</html>

View file

@ -9,111 +9,33 @@
<head>
<title>ScratchJr Intro</title>
<script type="text/javascript" src="./Settings.js"></script>
<script type="text/javascript" src="jssource/utils/Cookie.js"></script>
<script type="text/javascript" src="jssource/utils/lib.js"></script>
<!-- Localization includes -->
<script type="text/javascript" src="jssource/external/Intl/Intl.min.js"></script>
<script type="text/javascript" src="jssource/external/intl-messageformat/intl-messageformat.min.js"></script>
<script type="text/javascript" src="jssource/utils/Localization.js"></script>
<script>
Localization.includeLocales();
window.scratchJrPage = 'index';
</script>
<!-- End localization includes -->
<script type="text/javascript">
preprocessAndLoadCss("css", "css/font.css");
preprocessAndLoadCss("css", "css/base.css");
preprocessAndLoadCss("css", "css/start.css");
preprocessAndLoadCss("css", "css/thumbs.css");
</script>
<script type="text/javascript" src="jssource/utils/DrawPath.js"></script>
<script type="text/javascript" src="jssource/editor/ui/Alert.js"></script>
<script type="text/javascript" src="jssource/iPad/iOS.js"></script>
<script type="text/javascript" src="jssource/iPad/IO.js"></script>
<script type="text/javascript" src="./MediaLib.js"></script>
<script type="text/javascript" src="jssource/utils/ScratchAudio.js"></script>
<script type="text/javascript" src="jssource/utils/Sound.js"></script>
<script type="text/javascript" src="jssource/utils/SVG2Canvas.js"></script>
<script type="text/javascript" src="jssource/external/jszip.js"></script>
<script type="text/javascript" src="jssource/painteditor/SVGImage.js"></script>
<script type="text/javascript" src="jssource/painteditor/Transform.js"></script>
<script type="text/javascript" src="jssource/painteditor/SVGTools.js"></script>
<script type="text/javascript" src="jssource/geom/Rectangle.js"></script>
<script language="javascript">
function startup(){
ScratchAudio.init();
var urlvars = getUrlVars();
if (urlvars["back"]) loadOptions();
else firstTime();
setTimeout(function(){gn('rays').className = "rays spinme";}, 250);
}
function firstTime() {
gn('authors').className = "credits show";
gn('authorsText').className = "creditsText show";
gn('purpleguy').className = "purple show";
gn('blueguy').className = "blue show";
gn('redguy').className = "red show";
iOS.askpermission(); // ask for sound recording
setTimeout(function(){iOS.hidesplash(doit);}, 500);
function doit (str){
ScratchAudio.sndFX("tap.wav");
window.ontouchend = function () {loadOptions();};
}
setTimeout(function(){loadOptions();}, 2000);
}
function loadOptions(){
gn('authors').className = "credits hide";
gn('authorsText').className = "creditsText hide";
gn('purpleguy').className = "purple hide";
gn('blueguy').className = "blue hide";
gn('redguy').className = "red hide";
gn('gettings').className = "gettings show";
gn('startcode').className = "startcode show";
document.ontouchmove = function(e){e.preventDefault()};
if (isAndroid) AndroidInterface.notifySplashDone();
}
function gohome(){
rays.className = 'rays';
// On iOS, sounds are loaded async, but the code as written expects to play tap.wav when we enter home.html
// (but since it isn't loaded yet, no sound is played).
// On Android, sync sounds means both calls to tap.wav result in a sound play.
// XXX: we should re-write the lobby loading to wait for the sounds to load, and not play a sound here.
if (isiOS) {
ScratchAudio.sndFX("tap.wav");
}
iOS.setfile("homescroll.sjr", 0, function (str) {doNext()});
function doNext() {window.location.href = "home.html";}
}
function gettingstarted(){
rays.className = 'rays';
ScratchAudio.sndFX("tap.wav");
window.location.href = "gettingstarted.html?place=home";
}
</script>
<script type="text/javascript" src="jssource/build/bundles/app.bundle.js"></script>
</head>
<body onload="iOS.waitForInterface(startup);" style="margin:0px; background: black;">
<div class="frame" id="frame">
<div class="credits hide" id="authors"></div>
<div class="creditsText hide" id="authorsText"></div>
<div class="rays" id="rays"></div>
<div class="catface"></div>
<div class="jrlogo"></div>
<div class="purple hide" id="purpleguy"></div>
<div class="red hide" id="redguy"></div>
<div class="blue hide" id="blueguy"></div>
<div class="gettings hide" id="gettings" ontouchend="gettingstarted()"></div>
<div class="startcode hide" id="startcode" ontouchend="gohome()"></div>
</div>
</div>
<body style="margin:0px; background: black;">
<div class="frame" id="frame">
<div class="topbar" id="topbar">
<div class="topbar-button" id="topbar-info"></div>
<div class="topbar-button" id="topbar-moreapps">
</div>
</div>
<div class="credits hide" id="authors"></div>
<div class="creditsText hide" id="authorsText"></div>
<div class="rays" id="rays"></div>
<div class="catface" id="catface"></div>
<div class="jrlogo"></div>
<div class="purple hide" id="purpleguy"></div>
<div class="red hide" id="redguy"></div>
<div class="blue hide" id="blueguy"></div>
<div class="startButton hide" id="startButton"></div>
<div class="pbschars hide" id="pbschars"></div>
<div class="gettings hide" id="gettings"></div>
<div class="startcode hide" id="startcode"></div>
</div>
</body>
</html>

View file

@ -0,0 +1,13 @@
{
"path": "./svglibrary/",
"samples": [
"samples/Star.txt"
],
"backgrounds": [
{"md5":"Farm.svg","width":480,"height":360,"ext":"svg","name":"Farm"}
],
"sprites": [
{"md5":"Star.svg","width":80,"height":101,"ext":"svg","name":"Star","order":"characters,07 weather","tags":["characters","07 weather"]}
],
"sounds": ["pop.mp3"]
}

View file

@ -0,0 +1,26 @@
{
"edition": "free",
"scratchJrVersion": "iOSv01",
"useStoryStarters": false,
"shareEnabled": true,
"defaultSprite": "Star.svg",
"spriteOutlineColor": "white",
"stageColor": "#F5F2F7",
"textSpriteFont": "Helvetica",
"blockArgFont": "Verdana",
"paletteBalloonFont": "Roboto",
"categoryStartColor": "#FFE75A",
"categoryMotionColor": "#4B8CC2",
"categoryLooksColor": "#CD7CD1",
"categorySoundColor": "#48CC7E",
"categoryFlowColor": "#FFBE57",
"categoryStopColor": "#D62222",
"paletteBlockShadowOpacity": 0.8,
"autoSaveInterval": 30000,
"defaultLocale": "en",
"defaultLocaleShort": "en",
"supportedLocales": {
"English": "en",
"Español": "es"
}
}

View file

@ -377,7 +377,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "EDITION=free;\n\nrsync -pvtrlL --cvs-exclude \\\n ../editions/$EDITION/ios-resources/* \\\n \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/\";\n\nrsync -pvtrlL --cvs-exclude \\\n ../editions/$EDITION/src/* \\\n \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/HTML5\";\n \nmkdir -p \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/HTML5/pnglibrary\";\n\n../bin/convert-svg-to-png.py -i \"../editions/$EDITION/src/svglibrary/\" -o \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/HTML5/pnglibrary\";";
shellScript = "EDITION=free;\n\n../bin/bundle-compile.sh;\n\nrsync -pvtrlL --cvs-exclude \\\n ../editions/$EDITION/ios-resources/* \\\n \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/\";\n\nrsync -pvtrlL --cvs-exclude \\\n ../editions/$EDITION/src/* \\\n \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/HTML5\";\n \nmkdir -p \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/HTML5/pnglibrary\";\n\n../bin/convert-svg-to-png.py -i \"../editions/$EDITION/src/svglibrary/\" -o \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/HTML5/pnglibrary\";";
};
D92D0FA11C33381B00C573AD /* Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;

View file

@ -1,20 +1,33 @@
{
"name": "scratchjr",
"version": "1.1.0",
"version": "1.2.0",
"description": "ScratchJr",
"private": "true",
"scripts": {
"lint": "eslint src/**"
"lint": "eslint src/**",
"build": "webpack"
},
"author": "MIT Media Lab",
"license": "MIT",
"devDependencies": {
"babel-core": "^6.4.0",
"babel-eslint": "^4.1.6",
"babel-loader": "^6.2.1",
"babel-preset-es2015": "^6.3.13",
"esformatter": "^0.8.1",
"esformatter-braces": "^1.2.1",
"esformatter-dot-notation": "^1.3.1",
"esformatter-quotes": "^1.0.3",
"esformatter-semicolons": "^1.1.2",
"eslint": "^1.10.3"
"eslint": "^1.10.3",
"expose-loader": "^0.7.1",
"strip-sourcemap-loader": "0.0.1",
"webpack": "^1.12.11"
},
"dependencies": {}
"dependencies": {
"intl": "^1.0.1",
"intl-messageformat": "^1.2.0",
"jszip": "^2.5.0",
"snapsvg": "^0.3.0"
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,12 @@
import ScratchJr from '../ScratchJr';
import BlockSpecs from './BlockSpecs';
import Menu from './Menu';
import Undo from '../ui/Undo';
import {setCanvasSize, setProps, writeText, scaleMultiplier,
newHTML, newDiv, newCanvas, getStringSize, isTablet,
newP, globalx, globaly} from '../../utils/lib';
import Localization from '../../utils/Localization';
/*
Argument types
@ -9,442 +18,449 @@ r: number for recorded sound block
p: page icons
*/
var BlockArg = function (block) {
this.daddy = block;
this.type = 'blockarg';
this.argType = block.spec[3];
switch (this.argType) {
case 'n':
this.argValue = block.spec[4];
this.div = this.addNumArg();
break;
case 't':
this.argValue = block.spec[4];
if (Localization.isSampleLocalizedKey(this.argValue) && ScratchJr.isSampleOrStarter()) {
this.argValue = Localization.localize('SAMPLE_TEXT_' + this.argValue);
export default class BlockArg {
constructor (block) {
this.daddy = block;
this.type = 'blockarg';
this.argType = block.spec[3];
switch (this.argType) {
case 'n':
this.argValue = block.spec[4];
this.div = this.addNumArg();
break;
case 't':
this.argValue = block.spec[4];
if (Localization.isSampleLocalizedKey(this.argValue) && ScratchJr.isSampleOrStarter()) {
this.argValue = Localization.localize('SAMPLE_TEXT_' + this.argValue);
}
this.div = this.addTextArg();
break;
case 'm':
this.argValue = block.spec[4];
this.list = JSON.stringify(block.spec[1]);
this.numperrow = 3;
this.icon = this.getIconFrom(block.spec[4], block.spec[1]);
this.div = this.addImageMenu(this.closePictureMenu);
break;
case 'd':
this.argValue = block.spec[4];
this.list = JSON.stringify(block.spec[1]);
this.numperrow = 3;
this.icon = BlockSpecs.speeds[this.argValue];
this.div = this.addImageMenu(this.menuCloseSpeeds);
break;
case 'p':
this.argValue = block.spec[4];
this.div = this.pageIcon(this.argValue);
var ctx = block.blockshape.getContext('2d');
ctx.drawImage(this.div, 0, 0, this.div.width, this.div.height, 0, 0,
this.div.width * block.scale, this.div.height * block.scale);
break;
case 's':
this.argValue = block.spec[4];
this.div = newDiv(block.div, 2, 46, 60, 20, {
position: 'absolute',
zoom: (block.scale * 100) + '%'
});
var p = newP(this.div, this.argValue.split('.')[0], {
width: '60px'
});
p.setAttribute('class', 'soundname');
break;
case 'r':
this.argValue = block.spec[4];
this.div = newHTML('div', 'recordedCircle', block.div);
setProps(this.div.style, {
zoom: (block.scale * 100) + '%'
});
var num = newHTML('p', 'recordedNumber', this.div);
num.textContent = this.daddy.inpalette ? this.argValue : '?';
break;
default:
break;
}
this.div = this.addTextArg();
break;
case 'm':
this.argValue = block.spec[4];
this.list = JSON.stringify(block.spec[1]);
this.numperrow = 3;
this.icon = this.getIconFrom(block.spec[4], block.spec[1]);
this.div = this.addImageMenu(this.closePictureMenu);
break;
case 'd':
this.argValue = block.spec[4];
this.list = JSON.stringify(block.spec[1]);
this.numperrow = 3;
this.icon = BlockSpecs.speeds[this.argValue];
this.div = this.addImageMenu(this.menuCloseSpeeds);
break;
case 'p':
this.argValue = block.spec[4];
this.div = this.pageIcon(this.argValue);
var ctx = block.blockshape.getContext('2d');
ctx.drawImage(this.div, 0, 0, this.div.width, this.div.height, 0, 0,
this.div.width * block.scale, this.div.height * block.scale);
break;
case 's':
this.argValue = block.spec[4];
this.div = newDiv(block.div, 2, 46, 60, 20, {
position: 'absolute',
zoom: (block.scale * 100) + '%'
});
var p = newP(this.div, this.argValue.split('.')[0], {
width: '60px'
});
p.setAttribute('class', 'soundname');
break;
case 'r':
this.argValue = block.spec[4];
this.div = newHTML('div', 'recordedCircle', block.div);
setProps(this.div.style, {
zoom: (block.scale * 100) + '%'
});
var num = newHTML('p', 'recordedNumber', this.div);
num.textContent = this.daddy.inpalette ? this.argValue : '?';
break;
default:
break;
}
};
BlockArg.prototype.update = function () {
if (this.argType == 'r') {
this.div.childNodes[0].textContent = this.argValue;
update () {
if (this.argType == 'r') {
this.div.childNodes[0].textContent = this.argValue;
}
if (this.arg && (this.argType == 'p')) {
this.arg.updateIcon();
}
}
if (this.arg && (this.argType == 'p')) {
this.arg.updateIcon();
}
};
BlockArg.prototype.getScreenPt = function () {
return {
x: globalx(this.daddy.div),
y: globaly(this.daddy.div)
};
};
BlockArg.prototype.addNumArg = function () {
var str = this.argValue.toString();
if (this.daddy.inpalette) {
return this.addLabel(str, false);
} else {
return this.addNumArgument(str);
}
};
BlockArg.prototype.addTextArg = function () {
var str = this.argValue.toString();
if (this.daddy.inpalette) {
return this.addLabel(str, true);
} else {
return this.addTextArgument(str, true);
}
};
BlockArg.prototype.addLabel = function (str, isText) {
var scale = this.daddy.scale;
var dx = isText ? 8 : 16;
var dy = 57;
if (this.daddy.blocktype == 'repeat') {
dx = Math.round(this.daddy.blockshape.width / window.devicePixelRatio / scale) - 60;
dy = Math.round(this.daddy.blockshape.height / window.devicePixelRatio / scale) - 10;
}
var img = isText ? BlockSpecs.textfieldimg : BlockSpecs.numfieldimg;
var w = isText ? 53 : 36;
var h = 17;
var field = newCanvas(this.daddy.div, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio, {
position: 'absolute',
webkitTransform: 'translate(' + (-w * window.devicePixelRatio / 2) + 'px, ' +
(-h * window.devicePixelRatio / 2) + 'px) ' +
'scale(' + (scale / window.devicePixelRatio) + ') ' +
'translate(' + (dx * window.devicePixelRatio + (w * window.devicePixelRatio / 2)) + 'px, ' +
(dy * window.devicePixelRatio + (h * window.devicePixelRatio / 2)) + 'px)',
pointerEvents: 'all'
});
var ctx = field.getContext('2d');
if (!img.complete) {
img.onload = function () {
ctx.drawImage(img, 0, 0, w, h, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio);
getScreenPt () {
return {
x: globalx(this.daddy.div),
y: globaly(this.daddy.div)
};
} else {
ctx.drawImage(img, 0, 0, w, h, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio);
}
var div = newDiv(this.daddy.div, dx, dy, w, h, {
position: 'absolute',
zoom: (scale * 100) + '%',
margin: '0px',
padding: '0px'
});
var cnv = newCanvas(div, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio, {
position: 'absolute',
webkitTransform: 'translate(' + (-w * window.devicePixelRatio / 2) + 'px, ' +
(-h * window.devicePixelRatio / 2) + 'px) ' +
'scale(' + (1 / window.devicePixelRatio) + ') ' +
'translate(' + (w * window.devicePixelRatio / 2) + 'px, ' + (h * window.devicePixelRatio / 2) + 'px)'
});
ctx = cnv.getContext('2d');
var font = (12 * window.devicePixelRatio) + 'px ' + Settings.blockArgFont;
var lsize = getStringSize(ctx, font, str).width;
writeText(ctx, font, '#77787b', str, h * window.devicePixelRatio - 3,
Math.round((w * window.devicePixelRatio - lsize) / 2));
return div;
};
BlockArg.prototype.addNumArgument = function (str) {
var div = newHTML('div', 'numfield', this.daddy.div);
if (this.daddy.blocktype == 'repeat') {
setProps(div.style, {
left: (this.daddy.blockshape.width / window.devicePixelRatio - 62 * this.daddy.scale) + 'px',
top: (this.daddy.blockshape.height / window.devicePixelRatio - 11 * this.daddy.scale) + 'px'
});
}
var ti = newHTML('h3', undefined, div);
this.input = ti;
ti.owner = this;
ti.textContent = str;
this.arg = div;
// Expand the parent div to incorporate the size of the button, else on Android 4.2 the bottom part of the button
// will not be clickable.
div.parentNode.height += 10 * window.devicePixelRatio;
setCanvasSize(div.parentNode, div.parentNode.width, div.parentNode.height);
return div;
};
BlockArg.prototype.addTextArgument = function (str) {
var div = newHTML('div', 'textfield', this.daddy.div);
var ti = newHTML('h3', undefined, div);
this.input = ti;
ti.owner = this;
ti.textContent = str;
this.arg = div;
// Expand the parent div to incorporate the size of the button, else on Android 4.2 the bottom part of the button
// will not be clickable.
div.parentNode.height += 10 * window.devicePixelRatio;
setCanvasSize(div.parentNode, div.parentNode.width, div.parentNode.height);
return div;
};
BlockArg.prototype.setValue = function (val) {
if (!this.input) {
return;
}
this.argValue = val;
this.input.textContent = val;
};
BlockArg.prototype.isText = function () {
return (this.argType != 'n');
};
/////////////////////////////////
// Menu drop downs
//////////////////////////////
BlockArg.prototype.getIconFrom = function (key, list) {
for (var i = 0; i < list.length; i++) {
if (list[i].indexOf(key) > -1) {
return list[i];
addNumArg () {
var str = this.argValue.toString();
if (this.daddy.inpalette) {
return this.addLabel(str, false);
} else {
return this.addNumArgument(str);
}
}
return list[0];
};
BlockArg.prototype.addImageMenu = function (fcn) {
this.drawChoice(this.daddy.blockicon);
this.button = this.addPressButton();
if (!this.daddy.inpalette) {
var ba = this;
if (isTablet) {
ba.button.ontouchstart = function (evt) {
ba.pressDropDown(evt, fcn);
addTextArg () {
var str = this.argValue.toString();
if (this.daddy.inpalette) {
return this.addLabel(str, true);
} else {
return this.addTextArgument(str, true);
}
}
addLabel (str, isText) {
var scale = this.daddy.scale;
var dx = isText ? 8 : 16;
var dy = 57;
if (this.daddy.blocktype == 'repeat') {
dx = Math.round(this.daddy.blockshape.width / window.devicePixelRatio / scale) - 60;
dy = Math.round(this.daddy.blockshape.height / window.devicePixelRatio / scale) - 10;
}
var img = isText ? BlockSpecs.textfieldimg : BlockSpecs.numfieldimg;
var w = isText ? 53 : 36;
var h = 17;
var field = newCanvas(this.daddy.div, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio, {
position: 'absolute',
webkitTransform: 'translate(' + (-w * window.devicePixelRatio / 2) + 'px, ' +
(-h * window.devicePixelRatio / 2) + 'px) ' +
'scale(' + (scale / window.devicePixelRatio) + ') ' +
'translate(' + (dx * window.devicePixelRatio + (w * window.devicePixelRatio / 2)) + 'px, ' +
(dy * window.devicePixelRatio + (h * window.devicePixelRatio / 2)) + 'px)',
pointerEvents: 'all'
});
var ctx = field.getContext('2d');
if (!img.complete) {
img.onload = function () {
ctx.drawImage(img, 0, 0, w, h, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio);
};
} else {
ba.button.onmousedown = function (evt) {
ba.pressDropDown(evt, fcn);
};
ctx.drawImage(img, 0, 0, w, h, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio);
}
var div = newDiv(this.daddy.div, dx, dy, w, h, {
position: 'absolute',
zoom: (scale * 100) + '%',
margin: '0px',
padding: '0px'
});
var cnv = newCanvas(div, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio, {
position: 'absolute',
webkitTransform: 'translate(' + (-w * window.devicePixelRatio / 2) + 'px, ' +
(-h * window.devicePixelRatio / 2) + 'px) ' +
'scale(' + (1 / window.devicePixelRatio) + ') ' +
'translate(' + (w * window.devicePixelRatio / 2) + 'px, ' + (h * window.devicePixelRatio / 2) + 'px)'
});
ctx = cnv.getContext('2d');
var font = (12 * window.devicePixelRatio) + 'px ' + window.Settings.blockArgFont;
var lsize = getStringSize(ctx, font, str).width;
writeText(ctx, font, '#77787b', str, h * window.devicePixelRatio - 3,
Math.round((w * window.devicePixelRatio - lsize) / 2));
return div;
}
addNumArgument (str) {
var div = newHTML('div', 'numfield', this.daddy.div);
if (this.daddy.blocktype == 'repeat') {
setProps(div.style, {
left: (this.daddy.blockshape.width / window.devicePixelRatio - 62 * this.daddy.scale) + 'px',
top: (this.daddy.blockshape.height / window.devicePixelRatio - 11 * this.daddy.scale) + 'px'
});
}
var ti = newHTML('h3', undefined, div);
this.input = ti;
ti.owner = this;
ti.textContent = str;
this.arg = div;
// Expand the parent div to incorporate the size of the button,
// else on Android 4.2 the bottom part of the button
// will not be clickable.
}
this.button.parentNode.height += this.button.height / 2;
setCanvasSize(this.button.parentNode, this.button.parentNode.width, this.button.parentNode.height);
div.parentNode.height += 10 * window.devicePixelRatio;
setCanvasSize(div.parentNode, div.parentNode.width, div.parentNode.height);
return div;
}
return this.daddy.blockicon;
};
BlockArg.prototype.drawChoice = function (cnv) {
var ctx = cnv.getContext('2d');
ctx.clearRect(0, 0, cnv.width, cnv.height);
var icon = BlockSpecs.getImageFrom('assets/blockicons/' + this.icon, 'svg');
var scale = this.daddy.scale;
if (!icon.complete) {
icon.onload = function () {
addTextArgument (str) {
var div = newHTML('div', 'textfield', this.daddy.div);
var ti = newHTML('h3', undefined, div);
this.input = ti;
ti.owner = this;
ti.textContent = str;
this.arg = div;
// Expand the parent div to incorporate the size of the button,
// else on Android 4.2 the bottom part of the button
// will not be clickable.
div.parentNode.height += 10 * window.devicePixelRatio;
setCanvasSize(div.parentNode, div.parentNode.width, div.parentNode.height);
return div;
}
setValue (val) {
if (!this.input) {
return;
}
this.argValue = val;
this.input.textContent = val;
}
isText () {
return (this.argType != 'n');
}
/////////////////////////////////
// Menu drop downs
//////////////////////////////
getIconFrom (key, list) {
for (var i = 0; i < list.length; i++) {
if (list[i].indexOf(key) > -1) {
return list[i];
}
}
return list[0];
}
addImageMenu (fcn) {
this.drawChoice(this.daddy.blockicon);
this.button = this.addPressButton();
if (!this.daddy.inpalette) {
var ba = this;
if (isTablet) {
ba.button.ontouchstart = function (evt) {
ba.pressDropDown(evt, fcn);
};
} else {
ba.button.onmousedown = function (evt) {
ba.pressDropDown(evt, fcn);
};
// Expand the parent div to incorporate the size of the button,
// else on Android 4.2 the bottom part of the button
// will not be clickable.
}
this.button.parentNode.height += this.button.height / 2;
setCanvasSize(this.button.parentNode, this.button.parentNode.width, this.button.parentNode.height);
}
return this.daddy.blockicon;
}
drawChoice (cnv) {
var ctx = cnv.getContext('2d');
ctx.clearRect(0, 0, cnv.width, cnv.height);
var icon = BlockSpecs.getImageFrom('assets/blockicons/' + this.icon, 'svg');
var scale = this.daddy.scale;
if (!icon.complete) {
icon.onload = function () {
ctx.drawImage(icon, 0, 0, icon.width, icon.height,
0, 0, icon.width * scale * window.devicePixelRatio,
icon.height * scale * window.devicePixelRatio);
};
} else {
ctx.drawImage(icon, 0, 0, icon.width, icon.height,
0, 0, icon.width * scale * window.devicePixelRatio,
icon.height * scale * window.devicePixelRatio);
};
} else {
ctx.drawImage(icon, 0, 0, icon.width, icon.height,
0, 0, icon.width * scale * window.devicePixelRatio,
icon.height * scale * window.devicePixelRatio);
}
return cnv;
}
return cnv;
};
BlockArg.prototype.addPressButton = function () {
var scale = this.daddy.scale;
var dx;
if (this.daddy.inpalette) {
dx = this.daddy.aStart ? 26 : 16;
} else {
dx = this.daddy.aStart ? 20 : 10;
}
var dy = 56;
var w = (this.daddy.inpalette) ? 36 : 48;
var h = (this.daddy.inpalette) ? 20 : 27;
var img = (this.daddy.inpalette) ? BlockSpecs.pressbuttonSmall : BlockSpecs.pressbutton;
var field = newCanvas(this.daddy.div, dx, dy, w, h, {
position: 'absolute',
zoom: (scale * 100) + '%',
pointerEvents: 'all',
webkitTransform: 'translateZ(0)'
});
var ctx = field.getContext('2d');
if (!img.complete) {
img.onload = function () {
addPressButton () {
var scale = this.daddy.scale;
var dx;
if (this.daddy.inpalette) {
dx = this.daddy.aStart ? 26 : 16;
} else {
dx = this.daddy.aStart ? 20 : 10;
}
var dy = 56;
var w = (this.daddy.inpalette) ? 36 : 48;
var h = (this.daddy.inpalette) ? 20 : 27;
var img = (this.daddy.inpalette) ? BlockSpecs.pressbuttonSmall : BlockSpecs.pressbutton;
var field = newCanvas(this.daddy.div, dx, dy, w, h, {
position: 'absolute',
zoom: (scale * 100) + '%',
pointerEvents: 'all',
webkitTransform: 'translateZ(0)'
});
var ctx = field.getContext('2d');
if (!img.complete) {
img.onload = function () {
ctx.drawImage(img, 0, 0);
};
} else {
ctx.drawImage(img, 0, 0);
};
} else {
ctx.drawImage(img, 0, 0);
}
return field;
}
return field;
};
BlockArg.prototype.pressDropDown = function (e, fcn) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
pressDropDown (e, fcn) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
if (ScratchJr.onHold) {
return;
}
e.preventDefault();
e.stopPropagation();
ScratchJr.unfocus(e);
if (!this.daddy) {
return;
}
Menu.openDropDown(this.daddy.div, fcn);
}
if (ScratchJr.onHold) {
return;
}
e.preventDefault();
e.stopPropagation();
ScratchJr.unfocus(e);
if (!this.daddy) {
return;
}
Menu.openDropDown(this.daddy.div, fcn);
};
BlockArg.prototype.closePictureMenu = function (e, mu, b, c) {
e.preventDefault();
var value = b.owner.arg.argValue;
b.owner.arg.argValue = c.substring(c.indexOf('_') + 1, c.length);
var ctx = b.owner.blockicon.getContext('2d');
b.icon = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg');
ctx.clearRect(0, 0, 85 * scaleMultiplier * window.devicePixelRatio, 66 * scaleMultiplier * window.devicePixelRatio);
if (!b.icon.complete) {
b.icon.onload = function () {
closePictureMenu (e, mu, b, c) {
e.preventDefault();
var value = b.owner.arg.argValue;
b.owner.arg.argValue = c.substring(c.indexOf('_') + 1, c.length);
var ctx = b.owner.blockicon.getContext('2d');
b.icon = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg');
ctx.clearRect(0, 0, 85 * scaleMultiplier * window.devicePixelRatio,
66 * scaleMultiplier * window.devicePixelRatio);
if (!b.icon.complete) {
b.icon.onload = function () {
var w = b.icon.width;
var h = b.icon.height;
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0,
w * scaleMultiplier * window.devicePixelRatio,
h * scaleMultiplier * window.devicePixelRatio);
};
} else {
var w = b.icon.width;
var h = b.icon.height;
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0,
w * scaleMultiplier * window.devicePixelRatio,
h * scaleMultiplier * window.devicePixelRatio);
};
} else {
var w = b.icon.width;
var h = b.icon.height;
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0,
w * scaleMultiplier * window.devicePixelRatio,
h * scaleMultiplier * window.devicePixelRatio);
}
if (Menu.openMenu) {
Menu.openMenu.parentNode.removeChild(Menu.openMenu);
}
if (b.owner.arg.argValue != value) {
var spr = b.parentNode.owner.spr;
var action = {
action: 'scripts',
where: spr.div.parentNode.owner.id,
who: spr.id
};
Undo.record(action);
ScratchJr.storyStart('BlockArg.prototype.closePictureMenu');
}
Menu.openMenu = undefined;
}
if (Menu.openMenu) {
Menu.openMenu.parentNode.removeChild(Menu.openMenu);
}
if (b.owner.arg.argValue != value) {
var spr = b.parentNode.owner.spr;
var action = {
action: 'scripts',
where: spr.div.parentNode.owner.id,
who: spr.id
};
Undo.record(action);
ScratchJr.storyStart('BlockArg.prototype.closePictureMenu');
}
Menu.openMenu = undefined;
};
BlockArg.prototype.menuCloseSpeeds = function (e, mu, b, c) {
e.preventDefault();
var value = b.owner.arg.argValue;
b.owner.arg.argValue = BlockSpecs.speeds.indexOf(c);
var ctx = b.owner.blockicon.getContext('2d');
b.icon = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg');
ctx.clearRect(0, 0, 64 * scaleMultiplier * window.devicePixelRatio, 64 * scaleMultiplier * window.devicePixelRatio);
// On Android 4.2, clearRect does not work right away. Need to tickle the DOM
b.owner.blockicon.style.display = 'none';
b.owner.blockicon.offsetHeight;
b.owner.blockicon.style.display = 'inherit';
if (!b.icon.complete) {
b.icon.onload = function () {
menuCloseSpeeds (e, mu, b, c) {
e.preventDefault();
var value = b.owner.arg.argValue;
b.owner.arg.argValue = BlockSpecs.speeds.indexOf(c);
var ctx = b.owner.blockicon.getContext('2d');
b.icon = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg');
ctx.clearRect(0, 0, 64 * scaleMultiplier * window.devicePixelRatio,
64 * scaleMultiplier * window.devicePixelRatio);
// On Android 4.2, clearRect does not work right away. Need to tickle the DOM
b.owner.blockicon.style.display = 'none';
b.owner.blockicon.offsetHeight;
b.owner.blockicon.style.display = 'inherit';
if (!b.icon.complete) {
b.icon.onload = function () {
var w = b.icon.width;
var h = b.icon.height;
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0,
w * scaleMultiplier * window.devicePixelRatio, h * scaleMultiplier * window.devicePixelRatio);
};
} else {
var w = b.icon.width;
var h = b.icon.height;
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0,
w * scaleMultiplier * window.devicePixelRatio, h * scaleMultiplier * window.devicePixelRatio);
};
} else {
var w = b.icon.width;
var h = b.icon.height;
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0,
w * scaleMultiplier * window.devicePixelRatio, h * scaleMultiplier * window.devicePixelRatio);
}
if (Menu.openMenu) {
Menu.openMenu.parentNode.removeChild(Menu.openMenu);
}
if (b.owner.arg.argValue != value) {
var spr = b.parentNode.owner.spr;
var action = {
action: 'scripts',
where: spr.div.parentNode.owner.id,
who: spr.id
};
Undo.record(action);
ScratchJr.storyStart('BlockArg.prototype.menuCloseSpeeds');
}
Menu.openMenu = undefined;
}
if (Menu.openMenu) {
Menu.openMenu.parentNode.removeChild(Menu.openMenu);
}
if (b.owner.arg.argValue != value) {
var spr = b.parentNode.owner.spr;
var action = {
action: 'scripts',
where: spr.div.parentNode.owner.id,
who: spr.id
};
Undo.record(action);
ScratchJr.storyStart('BlockArg.prototype.menuCloseSpeeds');
}
Menu.openMenu = undefined;
};
//////////////////////////
// Page Icon
//////////////////////////
//////////////////////////
// Page Icon
//////////////////////////
BlockArg.prototype.pageIcon = function (num) {
var dpr = window.devicePixelRatio;
var page = ScratchJr.stage.pages[num - 1];
var icon = document.createElement('canvas');
setCanvasSize(icon, 86 * dpr, 66 * dpr);
if (!page) {
pageIcon (num) {
var dpr = window.devicePixelRatio;
var page = ScratchJr.stage.pages[num - 1];
var icon = document.createElement('canvas');
setCanvasSize(icon, 86 * dpr, 66 * dpr);
if (!page) {
return icon;
}
var canvas = document.createElement('canvas');
setCanvasSize(canvas, 52 * dpr, 42 * dpr);
var mainctx = canvas.getContext('2d');
mainctx.fillStyle = '#AE1F24';
mainctx.fillRect(0, 0, canvas.width, canvas.height);
mainctx.fillStyle = '#28A5DA';
mainctx.fillRect(1 * dpr, 1 * dpr, 50 * dpr, 40 * dpr);
var c = document.createElement('canvas');
var w = (52 - 6) * dpr;
var h = (42 - 6) * dpr;
setCanvasSize(c, w, h);
var ctx = c.getContext('2d');
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, c.width, c.height);
if (page.bkg.childElementCount > 0) {
var img = page.bkg.childNodes[0];
var imgw = img.naturalWidth ? img.naturalWidth : img.width;
var imgh = img.naturalHeight ? img.naturalHeight : img.height;
ctx.drawImage(img, 0, 0, imgw, imgh, 0, 0, w, h);
}
var scale = w / 480;
for (var i = 0; i < page.div.childElementCount; i++) {
var spr = page.div.childNodes[i].owner;
if (!spr) {
continue;
}
page.stampSpriteAt(ctx, spr, scale);
}
mainctx.drawImage(c, 3 * dpr, 3 * dpr);
var ictx = icon.getContext('2d');
ictx.fillStyle = '#AE1F24';
ictx.beginPath();
ictx.arc(63 * dpr, 19 * dpr, 10 * dpr, 0 * dpr, Math.PI * 2, true);
ictx.closePath();
ictx.fill();
ictx.drawImage(canvas, 14 * dpr, 16 * dpr);
ictx.beginPath();
ictx.fillStyle = '#28A5DA';
ictx.strokeStyle = '#355E7C';
ictx.arc(63 * dpr, 19 * dpr, 8 * dpr, 0 * dpr, Math.PI * 2, true);
ictx.closePath();
ictx.stroke();
ictx.fill();
writeText(ictx, 'bold ' + (12 * dpr) + 'px ' +
window.Settings.blockArgFont, 'white', page.num, 26 * dpr, 58 * dpr);
return icon;
}
var canvas = document.createElement('canvas');
setCanvasSize(canvas, 52 * dpr, 42 * dpr);
var mainctx = canvas.getContext('2d');
mainctx.fillStyle = '#AE1F24';
mainctx.fillRect(0, 0, canvas.width, canvas.height);
mainctx.fillStyle = '#28A5DA';
mainctx.fillRect(1 * dpr, 1 * dpr, 50 * dpr, 40 * dpr);
var c = document.createElement('canvas');
var w = (52 - 6) * dpr;
var h = (42 - 6) * dpr;
setCanvasSize(c, w, h);
var ctx = c.getContext('2d');
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, c.width, c.height);
if (page.bkg.childElementCount > 0) {
var img = page.bkg.childNodes[0];
var imgw = img.naturalWidth ? img.naturalWidth : img.width;
var imgh = img.naturalHeight ? img.naturalHeight : img.height;
ctx.drawImage(img, 0, 0, imgw, imgh, 0, 0, w, h);
}
var scale = w / 480;
for (var i = 0; i < page.div.childElementCount; i++) {
var spr = page.div.childNodes[i].owner;
if (!spr) {
continue;
}
page.stampSpriteAt(ctx, spr, scale);
}
mainctx.drawImage(c, 3 * dpr, 3 * dpr);
var ictx = icon.getContext('2d');
ictx.fillStyle = '#AE1F24';
ictx.beginPath();
ictx.arc(63 * dpr, 19 * dpr, 10 * dpr, 0 * dpr, Math.PI * 2, true);
ictx.closePath();
ictx.fill();
ictx.drawImage(canvas, 14 * dpr, 16 * dpr);
ictx.beginPath();
ictx.fillStyle = '#28A5DA';
ictx.strokeStyle = '#355E7C';
ictx.arc(63 * dpr, 19 * dpr, 8 * dpr, 0 * dpr, Math.PI * 2, true);
ictx.closePath();
ictx.stroke();
ictx.fill();
writeText(ictx, 'bold ' + (12 * dpr) + 'px ' + Settings.blockArgFont, 'white', page.num, 26 * dpr, 58 * dpr);
return icon;
};
BlockArg.prototype.updateIcon = function () {
var num = this.argValue;
var page = ScratchJr.stage.pages[num - 1];
page.num = num;
this.div = this.pageIcon(num);
var block = this.daddy;
var ctx = block.blockshape.getContext('2d');
ctx.drawImage(this.div, 0, 0, this.div.width, this.div.height, 0, 0,
this.div.width * block.scale, this.div.height * block.scale);
};
updateIcon () {
var num = this.argValue;
var page = ScratchJr.stage.pages[num - 1];
page.num = num;
this.div = this.pageIcon(num);
var block = this.daddy;
var ctx = block.blockshape.getContext('2d');
ctx.drawImage(this.div, 0, 0, this.div.width, this.div.height, 0, 0,
this.div.width * block.scale, this.div.height * block.scale);
}
}

View file

@ -1,306 +1,331 @@
var BlockSpecs = function () {};
import Localization from '../../utils/Localization';
import IO from '../../iPad/IO';
BlockSpecs.loadCount = 0;
BlockSpecs.loadassets = {};
BlockSpecs.fontwhite = '#f2f3f2';
BlockSpecs.fontpink = '#ff8ae9';
BlockSpecs.fontdarkgray = '#6d6e6c';
BlockSpecs.fontblack = '#1b2a34';
BlockSpecs.fontyellow = '#ffdd33';
BlockSpecs.fontdarkgreen = '#287f46';
BlockSpecs.fontpurple = '#8f56e3';
BlockSpecs.fontblue = '#0d50ab';
BlockSpecs.fontred = '#c4281b';
BlockSpecs.fontorange = '#da8540';
let loadCount = 0;
BlockSpecs.fontcolors = [BlockSpecs.fontred, BlockSpecs.fontorange, BlockSpecs.fontyellow,
BlockSpecs.fontdarkgreen, BlockSpecs.fontblue, BlockSpecs.fontpink, BlockSpecs.fontpurple,
BlockSpecs.fontwhite, BlockSpecs.fontdarkgray, BlockSpecs.fontblack];
let loadassets = {};
let fontwhite = '#f2f3f2';
let fontpink = '#ff8ae9';
let fontdarkgray = '#6d6e6c';
let fontblack = '#1b2a34';
let fontyellow = '#ffdd33';
let fontdarkgreen = '#287f46';
let fontpurple = '#8f56e3';
let fontblue = '#0d50ab';
let fontred = '#c4281b';
let fontorange = '#da8540';
BlockSpecs.fontsizes = [16, 24, 36, 48, 56, 72];
let fontcolors = [fontred, fontorange, fontyellow,
fontdarkgreen, fontblue, fontpink, fontpurple,
fontwhite, fontdarkgray, fontblack];
BlockSpecs.getshapes = ['LetterGet_Orange', 'LetterGet_Red', 'LetterGet_Yellow', 'LetterGet_Green',
let fontsizes = [16, 24, 36, 48, 56, 72];
let getshapes = ['LetterGet_Orange', 'LetterGet_Red', 'LetterGet_Yellow', 'LetterGet_Green',
'LetterGet_Blue', 'LetterGet_Purple'];
BlockSpecs.sendshapes = ['LetterSend_Orange', 'LetterSend_Red', 'LetterSend_Yellow', 'LetterSend_Green',
let sendshapes = ['LetterSend_Orange', 'LetterSend_Red', 'LetterSend_Yellow', 'LetterSend_Green',
'LetterSend_Blue', 'LetterSend_Purple'];
BlockSpecs.speeds = ['speed0', 'speed1', 'speed2'];
let speeds = ['speed0', 'speed1', 'speed2'];
BlockSpecs.initBlocks = function () {
BlockSpecs.loadassets = new Object();
BlockSpecs.loadGraphics();
BlockSpecs.defs = BlockSpecs.setupBlocksSpecs();
BlockSpecs.palettes = BlockSpecs.setupPalettesDef();
BlockSpecs.categories = BlockSpecs.setupCategories();
if (Settings.edition == 'PBS') {
BlockSpecs.canvasMask = BlockSpecs.getImageFrom('assets/ui/canvasmask', 'svg');
} else {
BlockSpecs.canvasMask = BlockSpecs.getImageFrom('assets/ui/canvasmask');
export default class BlockSpecs {
static get loadCount () {
return loadCount;
}
if (Settings.edition != 'PBS') {
BlockSpecs.projectThumb = BlockSpecs.getImageFrom('assets/lobby/pmask');
static set loadCount (newLoadCount) {
loadCount = newLoadCount;
}
IO.requestFromServer('assets/balloon.svg', BlockSpecs.setBalloon);
BlockSpecs.loadCount++;
};
BlockSpecs.setBalloon = function (str) {
BlockSpecs.loadCount--;
BlockSpecs.balloon = str;
};
BlockSpecs.loadGraphics = function () {
BlockSpecs.mic = BlockSpecs.getImageFrom('assets/ui/recordslot', 'svg');
BlockSpecs.yellowStart = BlockSpecs.getImageFrom('assets/blocks/start', 'svg');
BlockSpecs.yellowStartH = BlockSpecs.getImageFrom('assets/blocks/eh/startH');
BlockSpecs.yellowCmd = BlockSpecs.getImageFrom('assets/blocks/yellowCmd', 'svg');
BlockSpecs.yellowCmdH = BlockSpecs.getImageFrom('assets/blocks/eh/yellowCmdH');
BlockSpecs.redEnd = BlockSpecs.getImageFrom('assets/blocks/endshort', 'svg');
BlockSpecs.redEndH = BlockSpecs.getImageFrom('assets/blocks/eh/stopH');
BlockSpecs.orangeCmd = BlockSpecs.getImageFrom('assets/blocks/flow', 'svg');
BlockSpecs.orangeCmdH = BlockSpecs.getImageFrom('assets/blocks/eh/flowH');
BlockSpecs.limeCmd = BlockSpecs.getImageFrom('assets/blocks/sounds', 'svg');
BlockSpecs.limeCmdH = BlockSpecs.getImageFrom('assets/blocks/eh/soundsH');
BlockSpecs.pinkCmd = BlockSpecs.getImageFrom('assets/blocks/looks', 'svg');
BlockSpecs.pinkCmdH = BlockSpecs.getImageFrom('assets/blocks/eh/looksH');
BlockSpecs.redEndLong = BlockSpecs.getImageFrom('assets/blocks/endlong', 'svg');
BlockSpecs.redEndLongH = BlockSpecs.getImageFrom('assets/blocks/eh/stoplongH');
BlockSpecs.cShape = BlockSpecs.getImageFrom('assets/blocks/repeat');
BlockSpecs.cShapeH = BlockSpecs.getImageFrom('assets/blocks/eh/repeatH');
BlockSpecs.blueCmd = BlockSpecs.getImageFrom('assets/blocks/blueCmd', 'svg');
BlockSpecs.blueCmdH = BlockSpecs.getImageFrom('assets/blocks/eh/blueCmdH');
BlockSpecs.textfieldimg = BlockSpecs.getImageFrom('assets/misc/Text-01');
BlockSpecs.numfieldimg = BlockSpecs.getImageFrom('assets/misc/Number-01');
BlockSpecs.pressbutton = BlockSpecs.getImageFrom('assets/misc/pushbutton-01', 'svg');
BlockSpecs.pressbuttonSmall = BlockSpecs.getImageFrom('assets/misc/pushbutton', 'svg');
BlockSpecs.caretrepeat = BlockSpecs.getImageFrom('assets/blocks/caretrepeat');
BlockSpecs.cmdS = BlockSpecs.getImageFrom('assets/blocks/shadowCmd', 'svg');
BlockSpecs.startS = BlockSpecs.getImageFrom('assets/blocks/shadowStart', 'svg');
BlockSpecs.endS = BlockSpecs.getImageFrom('assets/blocks/shadowEndShort', 'svg');
BlockSpecs.endLongS = BlockSpecs.getImageFrom('assets/blocks/shadowEndLong', 'svg');
BlockSpecs.repeatS = BlockSpecs.getImageFrom('assets/blocks/shadowRepeat');
};
BlockSpecs.getImageFrom = function (url, ext) {
var img = document.createElement('img');
img.src = url + (ext ? '.' + ext : '.png');
if (!img.complete) {
BlockSpecs.loadassets[img.src] = img;
BlockSpecs.loadCount++;
img.onload = function () {
delete BlockSpecs.loadassets[img.src];
BlockSpecs.loadCount--;
};
static get fontcolors () {
return fontcolors;
}
static get fontsizes () {
return fontsizes;
}
static get speeds () {
return speeds;
}
static initBlocks () {
loadassets = new Object();
BlockSpecs.loadGraphics();
BlockSpecs.defs = BlockSpecs.setupBlocksSpecs();
BlockSpecs.palettes = BlockSpecs.setupPalettesDef();
BlockSpecs.categories = BlockSpecs.setupCategories();
if (window.Settings.edition == 'PBS') {
BlockSpecs.canvasMask = BlockSpecs.getImageFrom('assets/ui/canvasmask', 'svg');
} else {
BlockSpecs.canvasMask = BlockSpecs.getImageFrom('assets/ui/canvasmask');
}
if (window.Settings.edition != 'PBS') {
BlockSpecs.projectThumb = BlockSpecs.getImageFrom('assets/lobby/pmask');
}
IO.requestFromServer('assets/balloon.svg', BlockSpecs.setBalloon);
loadCount++;
}
static setBalloon (str) {
loadCount--;
BlockSpecs.balloon = str;
}
return img;
};
BlockSpecs.refreshLoading = function () {
for (var key in BlockSpecs.loadassets) {
if (BlockSpecs.loadassets[key].complete) {
BlockSpecs.loadCount--;
static loadGraphics () {
BlockSpecs.mic = BlockSpecs.getImageFrom('assets/ui/recordslot', 'svg');
BlockSpecs.yellowStart = BlockSpecs.getImageFrom('assets/blocks/start', 'svg');
BlockSpecs.yellowStartH = BlockSpecs.getImageFrom('assets/blocks/eh/startH');
BlockSpecs.yellowCmd = BlockSpecs.getImageFrom('assets/blocks/yellowCmd', 'svg');
BlockSpecs.yellowCmdH = BlockSpecs.getImageFrom('assets/blocks/eh/yellowCmdH');
BlockSpecs.redEnd = BlockSpecs.getImageFrom('assets/blocks/endshort', 'svg');
BlockSpecs.redEndH = BlockSpecs.getImageFrom('assets/blocks/eh/stopH');
BlockSpecs.orangeCmd = BlockSpecs.getImageFrom('assets/blocks/flow', 'svg');
BlockSpecs.orangeCmdH = BlockSpecs.getImageFrom('assets/blocks/eh/flowH');
BlockSpecs.limeCmd = BlockSpecs.getImageFrom('assets/blocks/sounds', 'svg');
BlockSpecs.limeCmdH = BlockSpecs.getImageFrom('assets/blocks/eh/soundsH');
BlockSpecs.pinkCmd = BlockSpecs.getImageFrom('assets/blocks/looks', 'svg');
BlockSpecs.pinkCmdH = BlockSpecs.getImageFrom('assets/blocks/eh/looksH');
BlockSpecs.redEndLong = BlockSpecs.getImageFrom('assets/blocks/endlong', 'svg');
BlockSpecs.redEndLongH = BlockSpecs.getImageFrom('assets/blocks/eh/stoplongH');
BlockSpecs.cShape = BlockSpecs.getImageFrom('assets/blocks/repeat');
BlockSpecs.cShapeH = BlockSpecs.getImageFrom('assets/blocks/eh/repeatH');
BlockSpecs.blueCmd = BlockSpecs.getImageFrom('assets/blocks/blueCmd', 'svg');
BlockSpecs.blueCmdH = BlockSpecs.getImageFrom('assets/blocks/eh/blueCmdH');
BlockSpecs.textfieldimg = BlockSpecs.getImageFrom('assets/misc/Text-01');
BlockSpecs.numfieldimg = BlockSpecs.getImageFrom('assets/misc/Number-01');
BlockSpecs.pressbutton = BlockSpecs.getImageFrom('assets/misc/pushbutton-01', 'svg');
BlockSpecs.pressbuttonSmall = BlockSpecs.getImageFrom('assets/misc/pushbutton', 'svg');
BlockSpecs.caretrepeat = BlockSpecs.getImageFrom('assets/blocks/caretrepeat');
BlockSpecs.cmdS = BlockSpecs.getImageFrom('assets/blocks/shadowCmd', 'svg');
BlockSpecs.startS = BlockSpecs.getImageFrom('assets/blocks/shadowStart', 'svg');
BlockSpecs.endS = BlockSpecs.getImageFrom('assets/blocks/shadowEndShort', 'svg');
BlockSpecs.endLongS = BlockSpecs.getImageFrom('assets/blocks/shadowEndLong', 'svg');
BlockSpecs.repeatS = BlockSpecs.getImageFrom('assets/blocks/shadowRepeat');
}
static getImageFrom (url, ext) {
var img = document.createElement('img');
img.src = url + (ext ? '.' + ext : '.png');
if (!img.complete) {
loadassets[img.src] = img;
loadCount++;
img.onload = function () {
delete loadassets[img.src];
loadCount--;
};
}
return img;
}
static refreshLoading () {
for (var key in loadassets) {
if (loadassets[key].complete) {
loadCount--;
}
}
}
};
BlockSpecs.setupCategories = function () {
return new Array(
[
BlockSpecs.getImageFrom('assets/categories/StartOn', 'svg'),
BlockSpecs.getImageFrom('assets/categories/StartOff', 'svg'),
Settings.categoryStartColor
],
[
BlockSpecs.getImageFrom('assets/categories/MotionOn', 'svg'),
BlockSpecs.getImageFrom('assets/categories/MotionOff', 'svg'),
Settings.categoryMotionColor
],
[
BlockSpecs.getImageFrom('assets/categories/LooksOn', 'svg'),
BlockSpecs.getImageFrom('assets/categories/LooksOff', 'svg'),
Settings.categoryLooksColor
],
[
BlockSpecs.getImageFrom('assets/categories/SoundOn', 'svg'),
BlockSpecs.getImageFrom('assets/categories/SoundOff', 'svg'),
Settings.categorySoundColor
],
[
BlockSpecs.getImageFrom('assets/categories/FlowOn', 'svg'),
BlockSpecs.getImageFrom('assets/categories/FlowOff', 'svg'),
Settings.categoryFlowColor
],
[
BlockSpecs.getImageFrom('assets/categories/StopOn', 'svg'),
BlockSpecs.getImageFrom('assets/categories/StopOff', 'svg'),
Settings.categoryStopColor
]
);
};
static setupCategories () {
return new Array(
[
BlockSpecs.getImageFrom('assets/categories/StartOn', 'svg'),
BlockSpecs.getImageFrom('assets/categories/StartOff', 'svg'),
window.Settings.categoryStartColor
],
[
BlockSpecs.getImageFrom('assets/categories/MotionOn', 'svg'),
BlockSpecs.getImageFrom('assets/categories/MotionOff', 'svg'),
window.Settings.categoryMotionColor
],
[
BlockSpecs.getImageFrom('assets/categories/LooksOn', 'svg'),
BlockSpecs.getImageFrom('assets/categories/LooksOff', 'svg'),
window.Settings.categoryLooksColor
],
[
BlockSpecs.getImageFrom('assets/categories/SoundOn', 'svg'),
BlockSpecs.getImageFrom('assets/categories/SoundOff', 'svg'),
window.Settings.categorySoundColor
],
[
BlockSpecs.getImageFrom('assets/categories/FlowOn', 'svg'),
BlockSpecs.getImageFrom('assets/categories/FlowOff', 'svg'),
window.Settings.categoryFlowColor
],
[
BlockSpecs.getImageFrom('assets/categories/StopOn', 'svg'),
BlockSpecs.getImageFrom('assets/categories/StopOff', 'svg'),
window.Settings.categoryStopColor
]
);
}
BlockSpecs.setupPalettesDef = function () {
return [['onflag', 'onclick', 'ontouch', 'onmessage', 'message'],
['forward', 'back', 'up', 'down', 'right', 'left', 'hop', 'home'],
['say', 'space', 'grow', 'shrink', 'same', 'space', 'hide', 'show'],
[],
['wait', 'stopmine', 'setspeed', 'repeat'],
['endstack', 'forever']];
};
static setupPalettesDef () {
return [['onflag', 'onclick', 'ontouch', 'onmessage', 'message'],
['forward', 'back', 'up', 'down', 'right', 'left', 'hop', 'home'],
['say', 'space', 'grow', 'shrink', 'same', 'space', 'hide', 'show'],
[],
['wait', 'stopmine', 'setspeed', 'repeat'],
['endstack', 'forever']];
}
///////////////////////////////
// Data Structure
//
// name - blocktype, icon or datastructure, blockshape, argtype, initial value, highlight, min, max, shadow
//
// arg types:
// null
// n -> number field;
// t -> text field
// m --> image menu with argvalue equal to name;
// d --> image menu with argvalue equal to number;
// c -- > color drop down
// s --> sound name
// p --> page icon
//
////////////////////////////////
///////////////////////////////
// Data Structure
//
// name - blocktype, icon or datastructure, blockshape, argtype, initial value, highlight, min, max, shadow
//
// arg types:
// null
// n -> number field;
// t -> text field
// m --> image menu with argvalue equal to name;
// d --> image menu with argvalue equal to number;
// c -- > color drop down
// s --> sound name
// p --> page icon
//
////////////////////////////////
BlockSpecs.setupBlocksSpecs = function () {
return {
'onflag': ['onflag', BlockSpecs.getImageFrom('assets/blockicons/greenFlag', 'svg'),
BlockSpecs.yellowStart, null, null, BlockSpecs.yellowStartH, null, null, BlockSpecs.startS],
'onmessage': ['onmessage', BlockSpecs.getshapes, BlockSpecs.yellowStart, 'm', 'Orange',
BlockSpecs.yellowStartH, null, null, BlockSpecs.startS],
'onclick': ['onclick', BlockSpecs.getImageFrom('assets/blockicons/OnTouch', 'svg'),
BlockSpecs.yellowStart, null, null, BlockSpecs.yellowStartH, null, null, BlockSpecs.startS],
'ontouch': ['ontouch', BlockSpecs.getImageFrom('assets/blockicons/Bump', 'svg'),
BlockSpecs.yellowStart, null, null, BlockSpecs.yellowStartH, null, null, BlockSpecs.startS],
'message': ['message', BlockSpecs.sendshapes, BlockSpecs.yellowCmd, 'm', 'Orange',
BlockSpecs.yellowCmdH, null, null, BlockSpecs.cmdS],
static setupBlocksSpecs () {
return {
'onflag': ['onflag', BlockSpecs.getImageFrom('assets/blockicons/greenFlag', 'svg'),
BlockSpecs.yellowStart, null, null, BlockSpecs.yellowStartH, null, null, BlockSpecs.startS],
'onmessage': ['onmessage', getshapes, BlockSpecs.yellowStart, 'm', 'Orange',
BlockSpecs.yellowStartH, null, null, BlockSpecs.startS],
'onclick': ['onclick', BlockSpecs.getImageFrom('assets/blockicons/OnTouch', 'svg'),
BlockSpecs.yellowStart, null, null, BlockSpecs.yellowStartH, null, null, BlockSpecs.startS],
'ontouch': ['ontouch', BlockSpecs.getImageFrom('assets/blockicons/Bump', 'svg'),
BlockSpecs.yellowStart, null, null, BlockSpecs.yellowStartH, null, null, BlockSpecs.startS],
'message': ['message', sendshapes, BlockSpecs.yellowCmd, 'm', 'Orange',
BlockSpecs.yellowCmdH, null, null, BlockSpecs.cmdS],
'repeat': ['repeat', BlockSpecs.getImageFrom('assets/blockicons/Repeat', 'svg'),
BlockSpecs.cShape, 'n', 4, BlockSpecs.cShapeH, 0, 24, BlockSpecs.repeatS],
'repeat': ['repeat', BlockSpecs.getImageFrom('assets/blockicons/Repeat', 'svg'),
BlockSpecs.cShape, 'n', 4, BlockSpecs.cShapeH, 0, 24, BlockSpecs.repeatS],
'forward': ['forward', BlockSpecs.getImageFrom('assets/blockicons/Foward', 'svg'),
BlockSpecs.blueCmd, 'n', 1, BlockSpecs.blueCmdH, -20, 20, BlockSpecs.cmdS],
'back': ['back', BlockSpecs.getImageFrom('assets/blockicons/Back', 'svg'),
BlockSpecs.blueCmd, 'n', 1, BlockSpecs.blueCmdH, -20, 20, BlockSpecs.cmdS],
'up': ['up', BlockSpecs.getImageFrom('assets/blockicons/Up', 'svg'),
BlockSpecs.blueCmd, 'n', 1, BlockSpecs.blueCmdH, -15, 15, BlockSpecs.cmdS],
'down': ['down', BlockSpecs.getImageFrom('assets/blockicons/Down', 'svg'),
BlockSpecs.blueCmd, 'n', 1, BlockSpecs.blueCmdH, -15, 15, BlockSpecs.cmdS],
'right': ['right', BlockSpecs.getImageFrom('assets/blockicons/Right', 'svg'),
BlockSpecs.blueCmd, 'n', 1, BlockSpecs.blueCmdH, -12, 12, BlockSpecs.cmdS],
'left': ['left', BlockSpecs.getImageFrom('assets/blockicons/Left', 'svg'),
BlockSpecs.blueCmd, 'n', 1, BlockSpecs.blueCmdH, -12, 12, BlockSpecs.cmdS],
'home': ['home', BlockSpecs.getImageFrom('assets/blockicons/Home', 'svg'),
BlockSpecs.blueCmd, null, null, BlockSpecs.blueCmdH, null, null, BlockSpecs.cmdS],
'hop': ['hop', BlockSpecs.getImageFrom('assets/blockicons/Hop', 'svg'),
BlockSpecs.blueCmd, 'n', 2, BlockSpecs.blueCmdH, -15, 15, BlockSpecs.cmdS],
'forward': ['forward', BlockSpecs.getImageFrom('assets/blockicons/Foward', 'svg'),
BlockSpecs.blueCmd, 'n', 1, BlockSpecs.blueCmdH, -20, 20, BlockSpecs.cmdS],
'back': ['back', BlockSpecs.getImageFrom('assets/blockicons/Back', 'svg'),
BlockSpecs.blueCmd, 'n', 1, BlockSpecs.blueCmdH, -20, 20, BlockSpecs.cmdS],
'up': ['up', BlockSpecs.getImageFrom('assets/blockicons/Up', 'svg'),
BlockSpecs.blueCmd, 'n', 1, BlockSpecs.blueCmdH, -15, 15, BlockSpecs.cmdS],
'down': ['down', BlockSpecs.getImageFrom('assets/blockicons/Down', 'svg'),
BlockSpecs.blueCmd, 'n', 1, BlockSpecs.blueCmdH, -15, 15, BlockSpecs.cmdS],
'right': ['right', BlockSpecs.getImageFrom('assets/blockicons/Right', 'svg'),
BlockSpecs.blueCmd, 'n', 1, BlockSpecs.blueCmdH, -12, 12, BlockSpecs.cmdS],
'left': ['left', BlockSpecs.getImageFrom('assets/blockicons/Left', 'svg'),
BlockSpecs.blueCmd, 'n', 1, BlockSpecs.blueCmdH, -12, 12, BlockSpecs.cmdS],
'home': ['home', BlockSpecs.getImageFrom('assets/blockicons/Home', 'svg'),
BlockSpecs.blueCmd, null, null, BlockSpecs.blueCmdH, null, null, BlockSpecs.cmdS],
'hop': ['hop', BlockSpecs.getImageFrom('assets/blockicons/Hop', 'svg'),
BlockSpecs.blueCmd, 'n', 2, BlockSpecs.blueCmdH, -15, 15, BlockSpecs.cmdS],
'wait': ['wait', BlockSpecs.getImageFrom('assets/blockicons/Wait', 'svg'),
BlockSpecs.orangeCmd, 'n', 10, BlockSpecs.orangeCmdH, 0, 50, BlockSpecs.cmdS],
'setspeed': ['setspeed', BlockSpecs.speeds, BlockSpecs.orangeCmd, 'd', 1,
BlockSpecs.orangeCmdH, null, null, BlockSpecs.cmdS],
'stopmine': ['stopmine', BlockSpecs.getImageFrom('assets/blockicons/Stop', 'svg'),
BlockSpecs.orangeCmd, null, null, BlockSpecs.orangeCmdH, null, null, BlockSpecs.cmdS],
'wait': ['wait', BlockSpecs.getImageFrom('assets/blockicons/Wait', 'svg'),
BlockSpecs.orangeCmd, 'n', 10, BlockSpecs.orangeCmdH, 0, 50, BlockSpecs.cmdS],
'setspeed': ['setspeed', speeds, BlockSpecs.orangeCmd, 'd', 1,
BlockSpecs.orangeCmdH, null, null, BlockSpecs.cmdS],
'stopmine': ['stopmine', BlockSpecs.getImageFrom('assets/blockicons/Stop', 'svg'),
BlockSpecs.orangeCmd, null, null, BlockSpecs.orangeCmdH, null, null, BlockSpecs.cmdS],
'say': ['say', BlockSpecs.getImageFrom('assets/blockicons/Say', 'svg'),
BlockSpecs.pinkCmd, 't',
Localization.localize('SAY_BLOCK_DEFAULT_ARGUMENT'), BlockSpecs.pinkCmdH, null, null, BlockSpecs.cmdS],
'show': ['show', BlockSpecs.getImageFrom('assets/blockicons/Appear', 'svg'),
BlockSpecs.pinkCmd, null, null, BlockSpecs.pinkCmdH, null, null, BlockSpecs.cmdS],
'hide': ['hide', BlockSpecs.getImageFrom('assets/blockicons/Disappear', 'svg'),
BlockSpecs.pinkCmd, null, null, BlockSpecs.pinkCmdH, null, null, BlockSpecs.cmdS],
'grow': ['grow', BlockSpecs.getImageFrom('assets/blockicons/Grow', 'svg'),
BlockSpecs.pinkCmd, 'n', 2, BlockSpecs.pinkCmdH, -10, 10, BlockSpecs.cmdS],
'shrink': ['shrink', BlockSpecs.getImageFrom('assets/blockicons/Shrink', 'svg'),
BlockSpecs.pinkCmd, 'n', 2, BlockSpecs.pinkCmdH, -10, 10, BlockSpecs.cmdS],
'same': ['same', BlockSpecs.getImageFrom('assets/blockicons/Reset', 'svg'),
BlockSpecs.pinkCmd, null, null, BlockSpecs.pinkCmdH, null, null, BlockSpecs.cmdS],
'say': ['say', BlockSpecs.getImageFrom('assets/blockicons/Say', 'svg'),
BlockSpecs.pinkCmd, 't',
Localization.localize('SAY_BLOCK_DEFAULT_ARGUMENT'), BlockSpecs.pinkCmdH, null, null, BlockSpecs.cmdS],
'show': ['show', BlockSpecs.getImageFrom('assets/blockicons/Appear', 'svg'),
BlockSpecs.pinkCmd, null, null, BlockSpecs.pinkCmdH, null, null, BlockSpecs.cmdS],
'hide': ['hide', BlockSpecs.getImageFrom('assets/blockicons/Disappear', 'svg'),
BlockSpecs.pinkCmd, null, null, BlockSpecs.pinkCmdH, null, null, BlockSpecs.cmdS],
'grow': ['grow', BlockSpecs.getImageFrom('assets/blockicons/Grow', 'svg'),
BlockSpecs.pinkCmd, 'n', 2, BlockSpecs.pinkCmdH, -10, 10, BlockSpecs.cmdS],
'shrink': ['shrink', BlockSpecs.getImageFrom('assets/blockicons/Shrink', 'svg'),
BlockSpecs.pinkCmd, 'n', 2, BlockSpecs.pinkCmdH, -10, 10, BlockSpecs.cmdS],
'same': ['same', BlockSpecs.getImageFrom('assets/blockicons/Reset', 'svg'),
BlockSpecs.pinkCmd, null, null, BlockSpecs.pinkCmdH, null, null, BlockSpecs.cmdS],
'playsnd': ['playsnd', BlockSpecs.getImageFrom('assets/blockicons/Speaker', 'svg'),
BlockSpecs.limeCmd, 's', 'pop.mp3', BlockSpecs.limeCmdH, null, null, BlockSpecs.cmdS],
'playusersnd': ['playusersnd', BlockSpecs.getImageFrom('assets/blockicons/Microphone', 'svg'),
BlockSpecs.limeCmd, 'r', '1', BlockSpecs.limeCmdH, null, null, BlockSpecs.cmdS],
'endstack': ['endstack', null, BlockSpecs.redEnd, null, null, BlockSpecs.redEndH, null, null, BlockSpecs.endS],
'forever': ['forever', BlockSpecs.getImageFrom('assets/blockicons/Forever', 'svg'),
BlockSpecs.redEnd, null, null, BlockSpecs.redEndH, null, null, BlockSpecs.endS],
'gotopage': ['gotopage', null,
BlockSpecs.redEndLong, 'p', '2', BlockSpecs.redEndLongH, null, null, BlockSpecs.endLongS],
'caretstart': ['caretstart', null,
BlockSpecs.getImageFrom('assets/blocks/caretstart', 'svg'), null, null, null, null, null],
'caretend': ['caretend', null,
BlockSpecs.getImageFrom('assets/blocks/caretend', 'svg'), null, null, null, null, null],
'caretrepeat': ['caretrepeat', null,
BlockSpecs.getImageFrom('assets/blocks/caretrepeat'), null, null, null, null, null],
'caretcmd': ['caretcmd', null,
BlockSpecs.getImageFrom('assets/blocks/caretcmd', 'svg'), null, null, null, null, null]
'playsnd': ['playsnd', BlockSpecs.getImageFrom('assets/blockicons/Speaker', 'svg'),
BlockSpecs.limeCmd, 's', 'pop.mp3', BlockSpecs.limeCmdH, null, null, BlockSpecs.cmdS],
'playusersnd': ['playusersnd', BlockSpecs.getImageFrom('assets/blockicons/Microphone', 'svg'),
BlockSpecs.limeCmd, 'r', '1', BlockSpecs.limeCmdH, null, null, BlockSpecs.cmdS],
'endstack': ['endstack', null, BlockSpecs.redEnd, null, null,
BlockSpecs.redEndH, null, null, BlockSpecs.endS],
'forever': ['forever', BlockSpecs.getImageFrom('assets/blockicons/Forever', 'svg'),
BlockSpecs.redEnd, null, null, BlockSpecs.redEndH, null, null, BlockSpecs.endS],
'gotopage': ['gotopage', null,
BlockSpecs.redEndLong, 'p', '2', BlockSpecs.redEndLongH, null, null, BlockSpecs.endLongS],
'caretstart': ['caretstart', null,
BlockSpecs.getImageFrom('assets/blocks/caretstart', 'svg'), null, null, null, null, null],
'caretend': ['caretend', null,
BlockSpecs.getImageFrom('assets/blocks/caretend', 'svg'), null, null, null, null, null],
'caretrepeat': ['caretrepeat', null,
BlockSpecs.getImageFrom('assets/blocks/caretrepeat'), null, null, null, null, null],
'caretcmd': ['caretcmd', null,
BlockSpecs.getImageFrom('assets/blocks/caretcmd', 'svg'), null, null, null, null, null]
};
};
};
}
BlockSpecs.blockDesc = function (b, spr) {
var str = b.getArgValue() ? b.getArgValue().toString() : (b.blocktype == 'playsnd') ? 'SOUND' : '';
static blockDesc (b, spr) {
var str = b.getArgValue() ? b.getArgValue().toString() : (b.blocktype == 'playsnd') ? 'SOUND' : '';
return {
'onflag': Localization.localize('BLOCK_DESC_GREEN_FLAG'),
'onclick': Localization.localize('BLOCK_DESC_ON_TAP', {
CHARACTER_NAME: spr.name
}),
'ontouch': Localization.localize('BLOCK_DESC_ON_BUMP', {
CHARACTER_NAME: spr.name ? spr.name : ''
}),
'onmessage': Localization.localize('BLOCK_DESC_ON_MESSAGE', {
COLOR: Localization.localize('BLOCK_DESC_MESSAGE_COLOR_ORANGE')
}),
'repeat': Localization.localize('BLOCK_DESC_REPEAT'),
'forward': Localization.localize('BLOCK_DESC_MOVE_RIGHT'),
'back': Localization.localize('BLOCK_DESC_MOVE_LEFT'),
'up': Localization.localize('BLOCK_DESC_MOVE_UP'),
'down': Localization.localize('BLOCK_DESC_MOVE_DOWN'),
'home': Localization.localize('BLOCK_DESC_GO_HOME'),
'left': Localization.localize('BLOCK_DESC_TURN_LEFT'),
'right': Localization.localize('BLOCK_DESC_TURN_RIGHT'),
'hop': Localization.localize('BLOCK_DESC_HOP'),
'wait': Localization.localize('BLOCK_DESC_WAIT'),
'setspeed': Localization.localize('BLOCK_DESC_SET_SPEED'),
'stopmine': Localization.localize('BLOCK_DESC_STOP', {
CHARACTER_NAME: spr.name ? spr.name : spr.str
}),
'say': Localization.localize('BLOCK_DESC_SAY'),
'show': Localization.localize('BLOCK_DESC_SHOW'),
'hide': Localization.localize('BLOCK_DESC_HIDE'),
'grow': Localization.localize('BLOCK_DESC_GROW'),
'shrink': Localization.localize('BLOCK_DESC_SHRINK'),
'same': Localization.localize('BLOCK_DESC_RESET_SIZE'),
'playsnd': Localization.localize('BLOCK_DESC_PLAY_SOUND', {
SOUND_NAME: Localization.localize('BLOCK_DESC_PLAY_SOUND_POP')
}),
'playusersnd': Localization.localize('BLOCK_DESC_PLAY_RECORDED_SOUND'),
'endstack': Localization.localize('BLOCK_DESC_END'),
'stopall': Localization.localize('BLOCK_DESC_STOP', {
CHARACTER_NAME: spr.name ? spr.name : ''
}),
'forever': Localization.localize('BLOCK_DESC_REPEAT_FOREVER'),
'gotopage': Localization.localize('BLOCK_DESC_GO_TO_PAGE', {
PAGE: str
}),
'message': Localization.localize('BLOCK_DESC_SEND_MESSAGE', {
COLOR: Localization.localize('BLOCK_DESC_MESSAGE_COLOR_ORANGE')
})
};
};
return {
'onflag': Localization.localize('BLOCK_DESC_GREEN_FLAG'),
'onclick': Localization.localize('BLOCK_DESC_ON_TAP', {
CHARACTER_NAME: spr.name
}),
'ontouch': Localization.localize('BLOCK_DESC_ON_BUMP', {
CHARACTER_NAME: spr.name ? spr.name : ''
}),
'onmessage': Localization.localize('BLOCK_DESC_ON_MESSAGE', {
COLOR: Localization.localize('BLOCK_DESC_MESSAGE_COLOR_ORANGE')
}),
'repeat': Localization.localize('BLOCK_DESC_REPEAT'),
'forward': Localization.localize('BLOCK_DESC_MOVE_RIGHT'),
'back': Localization.localize('BLOCK_DESC_MOVE_LEFT'),
'up': Localization.localize('BLOCK_DESC_MOVE_UP'),
'down': Localization.localize('BLOCK_DESC_MOVE_DOWN'),
'home': Localization.localize('BLOCK_DESC_GO_HOME'),
'left': Localization.localize('BLOCK_DESC_TURN_LEFT'),
'right': Localization.localize('BLOCK_DESC_TURN_RIGHT'),
'hop': Localization.localize('BLOCK_DESC_HOP'),
'wait': Localization.localize('BLOCK_DESC_WAIT'),
'setspeed': Localization.localize('BLOCK_DESC_SET_SPEED'),
'stopmine': Localization.localize('BLOCK_DESC_STOP', {
CHARACTER_NAME: spr.name ? spr.name : spr.str
}),
'say': Localization.localize('BLOCK_DESC_SAY'),
'show': Localization.localize('BLOCK_DESC_SHOW'),
'hide': Localization.localize('BLOCK_DESC_HIDE'),
'grow': Localization.localize('BLOCK_DESC_GROW'),
'shrink': Localization.localize('BLOCK_DESC_SHRINK'),
'same': Localization.localize('BLOCK_DESC_RESET_SIZE'),
'playsnd': Localization.localize('BLOCK_DESC_PLAY_SOUND', {
SOUND_NAME: Localization.localize('BLOCK_DESC_PLAY_SOUND_POP')
}),
'playusersnd': Localization.localize('BLOCK_DESC_PLAY_RECORDED_SOUND'),
'endstack': Localization.localize('BLOCK_DESC_END'),
'stopall': Localization.localize('BLOCK_DESC_STOP', {
CHARACTER_NAME: spr.name ? spr.name : ''
}),
'forever': Localization.localize('BLOCK_DESC_REPEAT_FOREVER'),
'gotopage': Localization.localize('BLOCK_DESC_GO_TO_PAGE', {
PAGE: str
}),
'message': Localization.localize('BLOCK_DESC_SEND_MESSAGE', {
COLOR: Localization.localize('BLOCK_DESC_MESSAGE_COLOR_ORANGE')
})
};
}
}

View file

@ -1,92 +1,104 @@
var Menu = function () {};
import BlockSpecs from './BlockSpecs';
import {scaleMultiplier, setProps, setCanvasSize, newHTML, isTablet,
newDiv, getDocumentHeight, drawThumbnail, frame, globalx, globaly} from '../../utils/lib';
Menu.openMenu = undefined;
let openMenu = undefined;
Menu.openDropDown = function (b, fcn) {
var size = 50;
var color = b.owner.blocktype == 'setspeed' ? 'orange' : 'yellow';
var list = JSON.parse(b.owner.arg.list);
var num = b.owner.arg.numperrow;
var p = b.parentNode;
var dh = size * Math.round(list.length / num);
var rows = list.length / num;
var w = size * list.length / rows;
var scaledWidth = w * scaleMultiplier;
var dx = b.left + (b.offsetWidth - scaledWidth) / 2;
if ((dx + scaledWidth) > p.width) {
dx -= ((dx + scaledWidth) - p.width);
export default class Menu {
static get openMenu () {
return openMenu;
}
if (dx < 5) {
dx = 5;
}
dx += globalx(p, 0);
var dy = b.top + b.offsetHeight - ((10 + 18) * scaleMultiplier) + globaly(p, 0);
if ((dy + ((10 + dh) * scaleMultiplier)) > getDocumentHeight()) {
dy = getDocumentHeight() - ((15 + dh) * scaleMultiplier);
}
var mu = newDiv(frame, dx, dy, w, dh, {
position: 'absolute',
zIndex: 100000,
webkitTransform: 'translate(' + (-w / 2) + 'px,' + (-dh / 2) + 'px) ' +
'scale(' + scaleMultiplier + ', ' + scaleMultiplier + ') ' +
'translate(' + (w / 2) + 'px, ' + (dh / 2) + 'px)'
});
mu.setAttribute('class', 'menustyle ' + color);
mu.active = b;
for (var i = 0; i < list.length; i++) {
Menu.addImageToDropDown(mu, list[i], b, fcn);
}
Menu.openMenu = mu;
};
Menu.addImageToDropDown = function (mu, c, block, fcn) {
var img = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg');
var cs = newHTML('div', 'ddchoice', mu);
var micon = newHTML('canvas', undefined, cs);
var iconSize = 42;
var scaledIconSize = iconSize * window.devicePixelRatio;
setCanvasSize(micon, scaledIconSize, scaledIconSize);
setProps(micon.style, {
webkitTransform: 'translate(' + (-scaledIconSize / 2) + 'px, ' + (-scaledIconSize / 2) + 'px) ' +
'scale(' + (1 / window.devicePixelRatio) + ', ' + (1 / window.devicePixelRatio) + ') ' +
'translate(' + (scaledIconSize / 2) + 'px, ' + (scaledIconSize / 2) + 'px)'
});
if (!img.complete) {
img.onload = function () {
static set openMenu (newOpenMenu) {
openMenu = newOpenMenu;
}
static openDropDown (b, fcn) {
var size = 50;
var color = b.owner.blocktype == 'setspeed' ? 'orange' : 'yellow';
var list = JSON.parse(b.owner.arg.list);
var num = b.owner.arg.numperrow;
var p = b.parentNode;
var dh = size * Math.round(list.length / num);
var rows = list.length / num;
var w = size * list.length / rows;
var scaledWidth = w * scaleMultiplier;
var dx = b.left + (b.offsetWidth - scaledWidth) / 2;
if ((dx + scaledWidth) > p.width) {
dx -= ((dx + scaledWidth) - p.width);
}
if (dx < 5) {
dx = 5;
}
dx += globalx(p, 0);
var dy = b.top + b.offsetHeight - ((10 + 18) * scaleMultiplier) + globaly(p, 0);
if ((dy + ((10 + dh) * scaleMultiplier)) > getDocumentHeight()) {
dy = getDocumentHeight() - ((15 + dh) * scaleMultiplier);
}
var mu = newDiv(frame, dx, dy, w, dh, {
position: 'absolute',
zIndex: 100000,
webkitTransform: 'translate(' + (-w / 2) + 'px,' + (-dh / 2) + 'px) ' +
'scale(' + scaleMultiplier + ', ' + scaleMultiplier + ') ' +
'translate(' + (w / 2) + 'px, ' + (dh / 2) + 'px)'
});
mu.setAttribute('class', 'menustyle ' + color);
mu.active = b;
for (var i = 0; i < list.length; i++) {
Menu.addImageToDropDown(mu, list[i], b, fcn);
}
openMenu = mu;
}
static addImageToDropDown (mu, c, block, fcn) {
var img = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg');
var cs = newHTML('div', 'ddchoice', mu);
var micon = newHTML('canvas', undefined, cs);
var iconSize = 42;
var scaledIconSize = iconSize * window.devicePixelRatio;
setCanvasSize(micon, scaledIconSize, scaledIconSize);
setProps(micon.style, {
webkitTransform: 'translate(' + (-scaledIconSize / 2) + 'px, ' + (-scaledIconSize / 2) + 'px) ' +
'scale(' + (1 / window.devicePixelRatio) + ', ' + (1 / window.devicePixelRatio) + ') ' +
'translate(' + (scaledIconSize / 2) + 'px, ' + (scaledIconSize / 2) + 'px)'
});
if (!img.complete) {
img.onload = function () {
drawThumbnail(img, micon);
};
} else {
drawThumbnail(img, micon);
};
} else {
drawThumbnail(img, micon);
}
if (isTablet) {
cs.ontouchstart = function (evt) {
handleTouchStart(evt);
};
} else {
cs.onmouseover = function (evt) {
Menu.highlightdot(evt);
};
cs.onmouseout = function (evt) {
Menu.unhighlightdot(evt);
};
cs.onmousedown = function (evt) {
fcn(evt, mu, block, c);
};
}
function handleTouchStart (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
fcn(e, mu, block, c);
}
}
if (isTablet) {
cs.ontouchstart = function (evt) {
handleTouchStart(evt);
};
} else {
cs.onmouseover = function (evt) {
Menu.highlightdot(evt);
};
cs.onmouseout = function (evt) {
Menu.unhighlightdot(evt);
};
cs.onmousedown = function (evt) {
fcn(evt, mu, block, c);
};
}
function handleTouchStart (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
static closeMyOpenMenu () {
if (!openMenu) {
return;
}
e.preventDefault();
e.stopPropagation();
fcn(e, mu, block, c);
openMenu.parentNode.removeChild(openMenu);
openMenu = undefined;
}
};
Menu.closeMyOpenMenu = function () {
if (!Menu.openMenu) {
return;
}
Menu.openMenu.parentNode.removeChild(Menu.openMenu);
Menu.openMenu = undefined;
};
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,179 +1,187 @@
var Runtime = function () {
this.threadsRunning = [];
this.thread = undefined;
this.intervalId = undefined;
this.yield = false;
};
import ScratchJr from '../ScratchJr';
import Project from '../ui/Project';
import Prims from './Prims';
import Thread from './Thread';
Runtime.prototype.beginTimer = function () {
if (this.intervalId != null) {
window.clearInterval(this.intervalId);
export default class Runtime {
constructor () {
this.threadsRunning = [];
this.thread = undefined;
this.intervalId = undefined;
this.yield = false;
}
var rt = this;
this.intervalId = window.setInterval(function () {
rt.tickTask();
}, 32);
Project.saving = false;
// Prims.time = (new Date() - 0);
this.threadsRunning = [];
};
Runtime.prototype.tickTask = function () {
ScratchJr.updateRunStopButtons();
if (this.threadsRunning.length < 1) {
return;
}
var activeThreads = [];
for (var i = 0; i < this.threadsRunning.length; i++) {
if (this.threadsRunning[i].isRunning) {
activeThreads.push(this.threadsRunning[i]);
beginTimer () {
if (this.intervalId != null) {
window.clearInterval(this.intervalId);
}
var rt = this;
this.intervalId = window.setInterval(function () {
rt.tickTask();
}, 32);
Project.saving = false;
// Prims.time = (new Date() - 0);
this.threadsRunning = [];
}
this.threadsRunning = activeThreads;
for (var j = 0; j < this.threadsRunning.length; j++) {
this.step(j);
}
};
Runtime.prototype.inactive = function () {
if (this.threadsRunning.length < 1) {
return true;
}
var inactive = true;
for (var i = 0; i < this.threadsRunning.length; i++) {
var t = this.threadsRunning[i];
if (!t) {
continue;
}
if (t.isRunning && (t.firstBlock.blocktype != 'ontouch')) {
inactive = false;
}
if ((t.firstBlock.blocktype == 'ontouch') && (t.thisblock != null) && (t.thisblock.blocktype != 'ontouch')) {
inactive = false;
}
}
return inactive;
};
Runtime.prototype.step = function (n) {
this.yield = false;
this.thread = this.threadsRunning[n];
while (true) { // eslint-disable-line no-constant-condition
if (!this.thread.isRunning) {
tickTask () {
ScratchJr.updateRunStopButtons();
if (this.threadsRunning.length < 1) {
return;
}
if (this.thread.waitTimer > 0) {
this.thread.waitTimer += -1;
return;
}
// if (this.thread.spr.parentNode.id == "frame") return; // object is being dragged
if (this.yield) {
return;
}
if (this.thread.thisblock == null) {
this.endCase();
this.yield = true;
} else {
this.runPrim();
}
}
};
Runtime.prototype.addRunScript = function (spr, b) {
this.restartThread(spr, b);
};
Runtime.prototype.stopThreads = function () {
for (var i in this.threadsRunning) {
this.threadsRunning[i].stop();
}
this.threadsRunning = [];
};
Runtime.prototype.stopThreadBlock = function (b) {
for (var i in this.threadsRunning) {
if (this.threadsRunning[i].firstBlock == b) {
this.threadsRunning[i].stop();
}
}
};
Runtime.prototype.stopThreadSprite = function (spr) {
for (var i in this.threadsRunning) {
if (this.threadsRunning[i].spr == spr) {
this.threadsRunning[i].stop();
}
}
};
Runtime.prototype.removeRunScript = function (spr) {
var res = [];
for (var i in this.threadsRunning) {
if (this.threadsRunning[i].spr == spr) {
var activeThreads = [];
for (var i = 0; i < this.threadsRunning.length; i++) {
if (this.threadsRunning[i].isRunning) {
if (this.threadsRunning[i].thisblock != null) {
this.threadsRunning[i].endPrim();
activeThreads.push(this.threadsRunning[i]);
}
}
this.threadsRunning = activeThreads;
for (var j = 0; j < this.threadsRunning.length; j++) {
this.step(j);
}
}
inactive () {
if (this.threadsRunning.length < 1) {
return true;
}
var inactive = true;
for (var i = 0; i < this.threadsRunning.length; i++) {
var t = this.threadsRunning[i];
if (!t) {
continue;
}
if (t.isRunning && (t.firstBlock.blocktype != 'ontouch')) {
inactive = false;
}
if ((t.firstBlock.blocktype == 'ontouch') && (t.thisblock != null)
&& (t.thisblock.blocktype != 'ontouch')) {
inactive = false;
}
}
return inactive;
}
step (n) {
this.yield = false;
this.thread = this.threadsRunning[n];
while (true) { // eslint-disable-line no-constant-condition
if (!this.thread.isRunning) {
return;
}
if (this.thread.waitTimer > 0) {
this.thread.waitTimer += -1;
return;
}
// if (this.thread.spr.parentNode.id == "frame") return; // object is being dragged
if (this.yield) {
return;
}
if (this.thread.thisblock == null) {
this.endCase();
this.yield = true;
} else {
this.runPrim();
}
}
}
addRunScript (spr, b) {
this.restartThread(spr, b);
}
stopThreads () {
for (var i in this.threadsRunning) {
this.threadsRunning[i].stop();
}
this.threadsRunning = [];
}
stopThreadBlock (b) {
for (var i in this.threadsRunning) {
if (this.threadsRunning[i].firstBlock == b) {
this.threadsRunning[i].stop();
}
}
}
stopThreadSprite (spr) {
for (var i in this.threadsRunning) {
if (this.threadsRunning[i].spr == spr) {
this.threadsRunning[i].stop();
}
}
}
removeRunScript (spr) {
var res = [];
for (var i in this.threadsRunning) {
if (this.threadsRunning[i].spr == spr) {
if (this.threadsRunning[i].isRunning) {
if (this.threadsRunning[i].thisblock != null) {
this.threadsRunning[i].endPrim();
}
res.push(this.threadsRunning[i].duplicate());
}
res.push(this.threadsRunning[i].duplicate());
}
this.threadsRunning[i].isRunning = false;
if (this.threadsRunning[i].oldblock != null) {
this.threadsRunning[i].oldblock.unhighlight();
}
}
}
return res;
};
Runtime.prototype.runPrim = function () {
if (this.thread.oldblock != null) {
this.thread.oldblock.unhighlight();
}
this.thread.oldblock = null;
var token = Prims.table[this.thread.thisblock.blocktype];
if (token == null) {
token = Prims.table.missing;
} else {
var noh = ['repeat', 'gotopage'];
if (noh.indexOf(this.thread.thisblock.blocktype) < 0) {
this.thread.thisblock.highlight();
this.thread.oldblock = this.thread.thisblock;
}
Prims.time = (new Date() - 0);
token(this.thread);
}
};
Runtime.prototype.endCase = function () {
if (this.thread.oldblock != null) {
this.thread.oldblock.unhighlight();
}
if (this.thread.stack.length == 0) {
Prims.Done(this.thread);
} else {
var thing = (this.thread.stack).pop();
this.thread.thisblock = thing;
this.runPrim();
}
};
Runtime.prototype.restartThread = function (spr, b, active) {
var newThread = new Thread(spr, b);
var wasRunning = false;
for (var i = 0; i < this.threadsRunning.length; i++) {
if (this.threadsRunning[i].firstBlock == b) {
wasRunning = true;
if (b.blocktype != 'ontouch') { // on touch demons are special - they are not interruptable
this.threadsRunning[i].isRunning = false;
if (this.threadsRunning[i].oldblock != null) {
this.threadsRunning[i].oldblock.unhighlight();
}
this.threadsRunning[i].stopping(active);
newThread = this.threadsRunning[i];
}
}
return res;
}
if (!wasRunning) {
this.threadsRunning.push(newThread);
runPrim () {
if (this.thread.oldblock != null) {
this.thread.oldblock.unhighlight();
}
this.thread.oldblock = null;
var token = Prims.table[this.thread.thisblock.blocktype];
if (token == null) {
token = Prims.table.missing;
} else {
var noh = ['repeat', 'gotopage'];
if (noh.indexOf(this.thread.thisblock.blocktype) < 0) {
this.thread.thisblock.highlight();
this.thread.oldblock = this.thread.thisblock;
}
Prims.time = (new Date() - 0);
token(this.thread);
}
}
return newThread;
};
endCase () {
if (this.thread.oldblock != null) {
this.thread.oldblock.unhighlight();
}
if (this.thread.stack.length == 0) {
Prims.Done(this.thread);
} else {
var thing = (this.thread.stack).pop();
this.thread.thisblock = thing;
this.runPrim();
}
}
restartThread (spr, b, active) {
var newThread = new Thread(spr, b);
var wasRunning = false;
for (var i = 0; i < this.threadsRunning.length; i++) {
if (this.threadsRunning[i].firstBlock == b) {
wasRunning = true;
if (b.blocktype != 'ontouch') { // on touch demons are special - they are not interruptable
if (this.threadsRunning[i].oldblock != null) {
this.threadsRunning[i].oldblock.unhighlight();
}
this.threadsRunning[i].stopping(active);
newThread = this.threadsRunning[i];
}
}
}
if (!wasRunning) {
this.threadsRunning.push(newThread);
}
return newThread;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,159 +1,165 @@
var Thread = function (s, block) {
this.firstBlock = block.findFirst();
this.thisblock = block;
this.oldblock = null;
this.spr = s;
this.audio = undefined;
this.stack = [];
this.firstTime = true;
this.count = -1;
this.waitTimer = 0;
this.distance = -1;
this.called = [];
this.vector = {
x: 0,
y: 0
};
this.isRunning = true;
this.time = 0; // for debugging purposes
return this;
};
import Prims from './Prims';
import Grid from '../ui/Grid';
import Vector from '../../geom/Vector';
Thread.prototype.clear = function () {
this.stack = [];
this.firstTime = true;
this.count = -1;
this.waitTimer = 0;
this.vector = {
x: 0,
y: 0
};
this.distance = -1;
this.called = [];
this.thisblock = this.firstBlock;
};
Thread.prototype.duplicate = function () {
var thread = new Thread(this.spr, this.firstBlock);
thread.count = -1;
thread.firstBlock = this.firstBlock;
thread.thisblock = this.thisblock;
thread.oldblock = null;
thread.spr = this.spr;
thread.stack = this.stack;
thread.firstTime = this.firstTime;
thread.vector = {
x: 0,
y: 0
};
thread.waitTimer = 0;
thread.distance = -1;
thread.called = this.called;
thread.isRunning = this.isRunning;
return thread;
};
Thread.prototype.deselect = function (b) {
while (b != null) {
b.unhighlight();
if (b.inside) {
b.repeatCounter = -1;
this.deselect(b.inside);
}
b = b.next;
export default class Thread {
constructor (s, block) {
this.firstBlock = block.findFirst();
this.thisblock = block;
this.oldblock = null;
this.spr = s;
this.audio = undefined;
this.stack = [];
this.firstTime = true;
this.count = -1;
this.waitTimer = 0;
this.distance = -1;
this.called = [];
this.vector = {
x: 0,
y: 0
};
this.isRunning = true;
this.time = 0; // for debugging purposes
return this;
}
};
Thread.prototype.stop = function (b) {
this.stopping(b);
this.isRunning = false;
};
Thread.prototype.stopping = function (b) {
this.endPrim(b);
this.deselect(this.firstBlock);
this.clear();
this.spr.closeBalloon();
};
Thread.prototype.endPrim = function (stopMine) {
if (!this.thisblock) {
return;
clear () {
this.stack = [];
this.firstTime = true;
this.count = -1;
this.waitTimer = 0;
this.vector = {
x: 0,
y: 0
};
this.distance = -1;
this.called = [];
this.thisblock = this.firstBlock;
}
var b = this.thisblock;
var s = this.spr;
switch (b.blocktype) {
case 'down':
case 'back':
case 'forward':
case 'up':
if ((this.distance > -1) && !stopMine) {
var vector = Vector.scale(this.vector, this.distance % 24);
s.setPos(s.xcoor + vector.x, s.ycoor + vector.y);
}
break;
case 'hop':
var count = this.count;
var n = Number(b.getArgValue());
count--;
if (count > 0) {
var delta = 0;
for (var i = count; i > -1; i--) {
delta += Prims.hopList[count];
}
this.vector = {
x: 0,
y: delta
};
var dy = s.ycoor - this.vector.y / 5 * n;
if (dy < 0) {
dy = 0;
}
if (dy >= (360 - Grid.size)) {
dy = (360 - Grid.size);
}
s.setPos(s.xcoor + this.vector.x, dy);
}
break;
case 'playsnd':
if (this.audio) {
this.audio.stop();
this.audio = undefined;
}
break;
case 'playusersnd':
if (this.audio) {
this.audio.stop();
this.audio = undefined;
}
break;
case 'hide':
s.div.style.opacity = 0;
if (!this.firstBlock.aStart && !stopMine) {
s.homeshown = false;
}
break;
case 'show':
s.div.style.opacity = 1;
if (!this.firstBlock.aStart && !stopMine) {
s.homeshown = true;
}
break;
case 'same': s.noScaleFor();
break;
case 'grow':
case 'shrink':
if (!this.firstBlock.aStart && !stopMine) {
s.homescale = s.scale;
}
break;
case 'right':
case 'left':
var angle = s.angle;
if ((angle % 30) != 0) {
angle = (Math.floor(angle / 30) + 1) * 30;
}
s.setHeading(angle);
break;
duplicate () {
var thread = new Thread(this.spr, this.firstBlock);
thread.count = -1;
thread.firstBlock = this.firstBlock;
thread.thisblock = this.thisblock;
thread.oldblock = null;
thread.spr = this.spr;
thread.stack = this.stack;
thread.firstTime = this.firstTime;
thread.vector = {
x: 0,
y: 0
};
thread.waitTimer = 0;
thread.distance = -1;
thread.called = this.called;
thread.isRunning = this.isRunning;
return thread;
}
};
deselect (b) {
while (b != null) {
b.unhighlight();
if (b.inside) {
b.repeatCounter = -1;
this.deselect(b.inside);
}
b = b.next;
}
}
stop (b) {
this.stopping(b);
this.isRunning = false;
}
stopping (b) {
this.endPrim(b);
this.deselect(this.firstBlock);
this.clear();
this.spr.closeBalloon();
}
endPrim (stopMine) {
if (!this.thisblock) {
return;
}
var b = this.thisblock;
var s = this.spr;
switch (b.blocktype) {
case 'down':
case 'back':
case 'forward':
case 'up':
if ((this.distance > -1) && !stopMine) {
var vector = Vector.scale(this.vector, this.distance % 24);
s.setPos(s.xcoor + vector.x, s.ycoor + vector.y);
}
break;
case 'hop':
var count = this.count;
var n = Number(b.getArgValue());
count--;
if (count > 0) {
var delta = 0;
for (var i = count; i > -1; i--) {
delta += Prims.hopList[count];
}
this.vector = {
x: 0,
y: delta
};
var dy = s.ycoor - this.vector.y / 5 * n;
if (dy < 0) {
dy = 0;
}
if (dy >= (360 - Grid.size)) {
dy = (360 - Grid.size);
}
s.setPos(s.xcoor + this.vector.x, dy);
}
break;
case 'playsnd':
if (this.audio) {
this.audio.stop();
this.audio = undefined;
}
break;
case 'playusersnd':
if (this.audio) {
this.audio.stop();
this.audio = undefined;
}
break;
case 'hide':
s.div.style.opacity = 0;
if (!this.firstBlock.aStart && !stopMine) {
s.homeshown = false;
}
break;
case 'show':
s.div.style.opacity = 1;
if (!this.firstBlock.aStart && !stopMine) {
s.homeshown = true;
}
break;
case 'same': s.noScaleFor();
break;
case 'grow':
case 'shrink':
if (!this.firstBlock.aStart && !stopMine) {
s.homescale = s.scale;
}
break;
case 'right':
case 'left':
var angle = s.angle;
if ((angle % 30) != 0) {
angle = (Math.floor(angle / 30) + 1) * 30;
}
s.setHeading(angle);
break;
}
}
}

View file

@ -1,66 +1,74 @@
var Alert = function () {};
import DrawPath from '../../utils/DrawPath';
import {globalx, globaly, scaleMultiplier, newCanvas,
setCanvasSize, setProps, writeText, getStringSize} from '../../utils/lib';
Alert.balloon = undefined;
let balloon = undefined;
Alert.close = function () {
if (!Alert.balloon) {
return;
}
Alert.balloon.parentNode.removeChild(Alert.balloon);
Alert.balloon = undefined;
};
Alert.open = function (p, obj, label, color) {
if (Alert.balloon) {
Alert.close();
}
var scale = scaleMultiplier;
var w = 80;
var h = 24;
var dx = (globalx(obj, obj.offsetLeft) + (obj.offsetWidth / 2)) - (w + 7 * 2 + 4) * scale / 2;
var dy = globaly(obj, obj.offsetTop) - (24 * scale);
if (dy < 5 * scale) {
dy = 5 * scale;
export default class Alert {
static get balloon () {
return balloon;
}
Alert.balloon = newCanvas(p, dx, dy, w, h, {
position: 'absolute',
zIndex: 2
});
Alert.balloon.icon = obj;
var ctx = Alert.balloon.getContext('2d');
w = 16 + getStringSize(ctx, 'bold 14px Verdana', label).width;
if (w < 36) {
w = 36;
static close () {
if (!balloon) {
return;
}
balloon.parentNode.removeChild(balloon);
balloon = undefined;
}
dx = (globalx(obj, obj.offsetLeft) + (obj.offsetWidth / 2)) - (w + 7 * 2 + 4) * scale / 2;
if (dx < 5 * scale) {
dx = 5 * scale;
}
dx = Math.floor(dx);
setCanvasSize(Alert.balloon, w, 36);
setProps(Alert.balloon.style, {
position: 'absolute',
left: dx + 'px',
zIndex: 1000,
webkitTransform: 'translate(' + (-w / 2) + 'px, ' + (-h / 2) + 'px) ' +
'scale(' + scale + ', ' + scale + ') ' +
'translate(' + (w / 2) + 'px, ' + (h / 2) + 'px) '
});
Alert.draw(Alert.balloon.getContext('2d'), 6, w, h, color);
writeText(ctx, 'bold 14px Verdana', 'white', label, 20, 8);
};
Alert.draw = function (ctx, curve, w, h, color) {
curve = 10;
var path = new Array(['M', 0, curve], ['q', 0, -curve, curve, -curve], ['h', w - curve * 2],
['q', curve, 0, curve, curve], ['v', h - curve * 2], ['q', 0, curve, -curve, curve],
['h', -(w / 2) + 7 + curve], ['l', -7, 7], ['l', -7, -7], ['h', -(w / 2) + 7 + curve],
['q', -curve, 0, -curve, -curve], ['Z']
);
ctx.clearRect(0, 0, Math.max(ctx.canvas.width, w), Math.max(ctx.canvas.height, h));
ctx.fillStyle = color;
ctx.beginPath();
DrawPath.render(ctx, path);
ctx.fill();
};
static open (p, obj, label, color) {
if (balloon) {
Alert.close();
}
var scale = scaleMultiplier;
var w = 80;
var h = 24;
var dx = (globalx(obj, obj.offsetLeft) + (obj.offsetWidth / 2)) - (w + 7 * 2 + 4) * scale / 2;
var dy = globaly(obj, obj.offsetTop) - (24 * scale);
if (dy < 5 * scale) {
dy = 5 * scale;
}
balloon = newCanvas(p, dx, dy, w, h, {
position: 'absolute',
zIndex: 2
});
balloon.icon = obj;
var ctx = balloon.getContext('2d');
w = 16 + getStringSize(ctx, 'bold 14px Verdana', label).width;
if (w < 36) {
w = 36;
}
dx = (globalx(obj, obj.offsetLeft) + (obj.offsetWidth / 2)) - (w + 7 * 2 + 4) * scale / 2;
if (dx < 5 * scale) {
dx = 5 * scale;
}
dx = Math.floor(dx);
setCanvasSize(balloon, w, 36);
setProps(balloon.style, {
position: 'absolute',
left: dx + 'px',
zIndex: 1000,
webkitTransform: 'translate(' + (-w / 2) + 'px, ' + (-h / 2) + 'px) ' +
'scale(' + scale + ', ' + scale + ') ' +
'translate(' + (w / 2) + 'px, ' + (h / 2) + 'px) '
});
Alert.draw(balloon.getContext('2d'), 6, w, h, color);
writeText(ctx, 'bold 14px Verdana', 'white', label, 20, 8);
}
static draw (ctx, curve, w, h, color) {
curve = 10;
var path = new Array(['M', 0, curve], ['q', 0, -curve, curve, -curve], ['h', w - curve * 2],
['q', curve, 0, curve, curve], ['v', h - curve * 2], ['q', 0, curve, -curve, curve],
['h', -(w / 2) + 7 + curve], ['l', -7, 7], ['l', -7, -7], ['h', -(w / 2) + 7 + curve],
['q', -curve, 0, -curve, -curve], ['Z']
);
ctx.clearRect(0, 0, Math.max(ctx.canvas.width, w), Math.max(ctx.canvas.height, h));
ctx.fillStyle = color;
ctx.beginPath();
DrawPath.render(ctx, path);
ctx.fill();
}
}

View file

@ -2,264 +2,276 @@
// Stage grid
//////////////////////////////
var Grid = function () {};
import ScratchJr from '../ScratchJr';
import Events from '../../utils/Events';
import Localization from '../../utils/Localization';
import {gn, scaleMultiplier, isTablet, newDiv, setProps, newP, newCanvas} from '../../utils/lib';
Grid.width = 482;
Grid.height = 362;
Grid.size = 24;
let width = 482;
let height = 362;
let size = 24;
let hidden = true;
Grid.hidden = true;
Grid.init = function (div) {
var w = div.offsetWidth;
var h = div.offsetHeight;
var grid = newDiv(div, 0, 0, Grid.width, Grid.height, {
position: 'absolute',
zIndex: ScratchJr.layerTop
});
Grid.setScaleAndPosition(grid, scaleMultiplier, 47, 75, Grid.width, Grid.height);
grid.setAttribute('id', 'livegrid');
Grid.drawLines(grid, Grid.width, Grid.height);
Grid.createNumbering(w, h);
Grid.createCursor();
Grid.createYcursor();
Grid.createXcursor();
};
Grid.setScaleAndPosition = function (grid, scale, x, y, w, h) {
setProps(grid.style, {
webkitTransform: 'translate(' + (-w / 2) + 'px, ' + (-h / 2) + 'px) ' +
'scale(' + scale + ') ' +
'translate(' + (w / 2 + x) + 'px, ' + (h / 2 + y) + 'px)'
});
};
Grid.drawLines = function (grid, w, h) {
var cnv = newCanvas(grid, 0, 0, w, h, {
position: 'absolute'
});
cnv.style.opacity = 0.5;
var ctx = cnv.getContext('2d');
ctx.strokeStyle = '#B3B3B3';
ctx.lineWidth = 1;
var dx = Grid.size;
// vertical
for (var i = 0; i < 480 / Grid.size; i++) {
ctx.moveTo(dx, 0);
ctx.lineTo(dx, 360);
ctx.stroke();
dx += Grid.size;
export default class Grid {
static get size () {
return size;
}
var dy = Grid.size;
// horizontal
for (i = 0; i < 360 / Grid.size; i++) {
ctx.moveTo(0, dy);
ctx.lineTo(480, dy);
ctx.stroke();
dy += Grid.size;
}
if (isTablet) {
cnv.ontouchstart = function (evt) {
ScratchJr.stage.mouseDown(evt);
};
} else {
cnv.onmousedown = function (evt) {
ScratchJr.stage.mouseDown(evt);
};
}
};
Grid.createNumbering = function (w, h) {
var row = newDiv(gn('stageframe'), 0, 0, w - 46 - 30, 24, {
position: 'absolute',
zIndex: ScratchJr.layerTop
});
row.setAttribute('id', 'rownum');
Grid.setScaleAndPosition(row, scaleMultiplier, 46 - 24, 75 + Grid.height, w - 46 - 30, 24);
var offset = Grid.size;
var dx = offset;
for (var i = 0; i < 480 / offset; i++) {
var num = newDiv(row, dx, 0, Grid.size, Grid.size, {
static get hidden () {
return hidden;
}
static init (div) {
var w = div.offsetWidth;
var h = div.offsetHeight;
var grid = newDiv(div, 0, 0, width, height, {
position: 'absolute',
zIndex: 10
zIndex: ScratchJr.layerTop
});
var p = newP(num, Localization.localize('GRID_NUMBER', {
N: (i + 1)
}), {});
p.setAttribute('class', 'stylelabel');
dx += offset;
Grid.setScaleAndPosition(grid, scaleMultiplier, 47, 75, width, height);
grid.setAttribute('id', 'livegrid');
Grid.drawLines(grid, width, height);
Grid.createNumbering(w, h);
Grid.createCursor();
Grid.createYcursor();
Grid.createXcursor();
}
var column = newDiv(gn('stageframe'), 0, 0, 24, h + 24, {
position: 'absolute',
zIndex: ScratchJr.layerTop
});
column.setAttribute('id', 'colnum');
Grid.setScaleAndPosition(column, scaleMultiplier, 46 - 24, 74 + 1, 24, h + 24);
var dy = 360 - offset;
for (var j = 0; j < 360 / offset; j++) {
var numj = newDiv(column, 0, dy, Grid.size, Grid.size, {
static setScaleAndPosition (grid, scale, x, y, w, h) {
setProps(grid.style, {
webkitTransform: 'translate(' + (-w / 2) + 'px, ' + (-h / 2) + 'px) ' +
'scale(' + scale + ') ' +
'translate(' + (w / 2 + x) + 'px, ' + (h / 2 + y) + 'px)'
});
}
static drawLines (grid, w, h) {
var cnv = newCanvas(grid, 0, 0, w, h, {
position: 'absolute'
});
cnv.style.opacity = 0.5;
var ctx = cnv.getContext('2d');
ctx.strokeStyle = '#B3B3B3';
ctx.lineWidth = 1;
var dx = size;
// vertical
for (var i = 0; i < 480 / size; i++) {
ctx.moveTo(dx, 0);
ctx.lineTo(dx, 360);
ctx.stroke();
dx += size;
}
var dy = size;
// horizontal
for (i = 0; i < 360 / size; i++) {
ctx.moveTo(0, dy);
ctx.lineTo(480, dy);
ctx.stroke();
dy += size;
}
if (isTablet) {
cnv.ontouchstart = function (evt) {
ScratchJr.stage.mouseDown(evt);
};
} else {
cnv.onmousedown = function (evt) {
ScratchJr.stage.mouseDown(evt);
};
}
}
static createNumbering (w, h) {
var row = newDiv(gn('stageframe'), 0, 0, w - 46 - 30, 24, {
position: 'absolute',
zIndex: 10
zIndex: ScratchJr.layerTop
});
var py = newP(numj, Localization.localize('GRID_NUMBER', {
N: j + 1
}), {});
py.setAttribute('class', 'stylelabel');
dy -= offset;
}
};
Grid.createYcursor = function () {
var num = newDiv(gn('colnum'), 0, 0, Grid.size, Grid.size, {
position: 'absolute',
zIndex: 20
});
num.setAttribute('class', 'circle');
num.style.background = '#6a99c1';
num.setAttribute('id', 'ycursor');
var p = newP(num, 15, {});
p.setAttribute('class', 'circlenum');
};
Grid.createXcursor = function () {
var num = newDiv(gn('rownum'), Grid.size, 0, Grid.size, Grid.size, {
position: 'absolute',
zIndex: 20
});
num.setAttribute('class', 'circle');
num.style.background = '#6a99c1';
num.setAttribute('id', 'xcursor');
var p = newP(num, 1, {});
p.setAttribute('class', 'circlenum');
};
Grid.createCursor = function () {
var gc = newDiv(gn('livegrid'), 0, 0, Grid.size + 2, Grid.size + 2, {
position: 'absolute',
zIndex: ScratchJr.layerAboveBottom
});
gc.setAttribute('id', 'circlenum');
var cnv = newCanvas(gc, 0, 0, Grid.size + 2, Grid.size + 2, {
position: 'absolute'
});
if (isTablet) {
cnv.ontouchstart = function (evt) {
Grid.mouseDownOnCursor(evt);
};
} else {
cnv.onmousedown = function (evt) {
Grid.mouseDownOnCursor(evt);
};
}
var ctx = cnv.getContext('2d');
ctx.globalAlpha = 0.5;
ctx.fillStyle = '#28A5DA';
ctx.strokeStyle = '#656e73';
ctx.lineWidth = 3;
ctx.strokeRect(3, 3, Grid.size - 6, Grid.size - 6);
ctx.fillRect(3, 3, Grid.size - 6, Grid.size - 6);
if (isTablet) {
gc.ontouchstart = Grid.mouseDownOnCursor;
} else {
gc.onmousedown = Grid.mouseDownOnCursor;
}
};
Grid.mouseDownOnCursor = function (e) {
e.preventDefault();
e.stopPropagation();
var pt = ScratchJr.stage.getStagePt(e);
var spr = ScratchJr.getSprite();
ScratchJr.stage.initialPoint = {
x: pt.x,
y: pt.y
};
Events.dragthumbnail = spr.div;
Events.clearEvents();
if (!ScratchJr.inFullscreen && spr) {
Events.holdit(spr.div, ScratchJr.stage.startShaking);
}
ScratchJr.stage.setEvents();
};
Grid.updateCursor = function () {
if (Grid.hidden) {
return;
}
if (ScratchJr.inFullscreen) {
return;
}
if (!ScratchJr.stage.currentPage) {
return;
}
if (!ScratchJr.getSprite()) {
gn('circlenum').style.visibility = 'hidden';
gn('xcursor').style.visibility = 'hidden';
gn('ycursor').style.visibility = 'hidden';
return;
}
var spr = gn(ScratchJr.stage.currentPage.currentSpriteName);
if (!spr) {
return;
}
var obj = spr.owner;
var c = gn('circlenum');
if (!c) {
return;
}
var dx = obj.xcoor + Grid.size / 2;
var dy = obj.ycoor - Grid.size / 2;
gn('xcursor').style.visibility = 'visible';
gn('ycursor').style.visibility = 'visible';
gn('circlenum').style.visibility = 'visible';
Grid.setCursorsValues(dx, dy);
};
Grid.setCursorsValues = function (dx, dy) {
var c = gn('circlenum');
var numX = Math.round(dx / Grid.size);
var numY = Math.round(dy / Grid.size);
if (c.offsetLeft != (numX * 24)) {
var xc = gn('xcursor');
var xstate = ((numX < 1) || (numX > 20)) ? 'hidden' : 'visible';
setProps(xc.style, {
row.setAttribute('id', 'rownum');
Grid.setScaleAndPosition(row, scaleMultiplier, 46 - 24, 75 + height, w - 46 - 30, 24);
var offset = size;
var dx = offset;
for (var i = 0; i < 480 / offset; i++) {
var num = newDiv(row, dx, 0, size, size, {
position: 'absolute',
zIndex: 10
});
var p = newP(num, Localization.localize('GRID_NUMBER', {
N: (i + 1)
}), {});
p.setAttribute('class', 'stylelabel');
dx += offset;
}
var column = newDiv(gn('stageframe'), 0, 0, 24, h + 24, {
position: 'absolute',
left: (numX * 24) + 'px',
visibility: xstate
});
xc.childNodes[0].textContent = Localization.localize('GRID_NUMBER', {
N: numX
zIndex: ScratchJr.layerTop
});
column.setAttribute('id', 'colnum');
Grid.setScaleAndPosition(column, scaleMultiplier, 46 - 24, 74 + 1, 24, h + 24);
var dy = 360 - offset;
for (var j = 0; j < 360 / offset; j++) {
var numj = newDiv(column, 0, dy, size, size, {
position: 'absolute',
zIndex: 10
});
var py = newP(numj, Localization.localize('GRID_NUMBER', {
N: j + 1
}), {});
py.setAttribute('class', 'stylelabel');
dy -= offset;
}
}
if (c.offsetTop != (numY * 24)) {
var yc = gn('ycursor');
var ystate = ((numY < 0) || (numY > 14)) ? 'hidden' : 'visible';
setProps(yc.style, {
static createYcursor () {
var num = newDiv(gn('colnum'), 0, 0, size, size, {
position: 'absolute',
zIndex: 20
});
num.setAttribute('class', 'circle');
num.style.background = '#6a99c1';
num.setAttribute('id', 'ycursor');
var p = newP(num, 15, {});
p.setAttribute('class', 'circlenum');
}
static createXcursor () {
var num = newDiv(gn('rownum'), size, 0, size, size, {
position: 'absolute',
zIndex: 20
});
num.setAttribute('class', 'circle');
num.style.background = '#6a99c1';
num.setAttribute('id', 'xcursor');
var p = newP(num, 1, {});
p.setAttribute('class', 'circlenum');
}
static createCursor () {
var gc = newDiv(gn('livegrid'), 0, 0, size + 2, size + 2, {
position: 'absolute',
zIndex: ScratchJr.layerAboveBottom
});
gc.setAttribute('id', 'circlenum');
var cnv = newCanvas(gc, 0, 0, size + 2, size + 2, {
position: 'absolute'
});
if (isTablet) {
cnv.ontouchstart = function (evt) {
Grid.mouseDownOnCursor(evt);
};
} else {
cnv.onmousedown = function (evt) {
Grid.mouseDownOnCursor(evt);
};
}
var ctx = cnv.getContext('2d');
ctx.globalAlpha = 0.5;
ctx.fillStyle = '#28A5DA';
ctx.strokeStyle = '#656e73';
ctx.lineWidth = 3;
ctx.strokeRect(3, 3, size - 6, size - 6);
ctx.fillRect(3, 3, size - 6, size - 6);
if (isTablet) {
gc.ontouchstart = Grid.mouseDownOnCursor;
} else {
gc.onmousedown = Grid.mouseDownOnCursor;
}
}
static mouseDownOnCursor (e) {
e.preventDefault();
e.stopPropagation();
var pt = ScratchJr.stage.getStagePt(e);
var spr = ScratchJr.getSprite();
ScratchJr.stage.initialPoint = {
x: pt.x,
y: pt.y
};
Events.dragthumbnail = spr.div;
Events.clearEvents();
if (!ScratchJr.inFullscreen && spr) {
Events.holdit(spr.div, ScratchJr.stage.startShaking);
}
ScratchJr.stage.setEvents();
}
static updateCursor () {
if (hidden) {
return;
}
if (ScratchJr.inFullscreen) {
return;
}
if (!ScratchJr.stage.currentPage) {
return;
}
if (!ScratchJr.getSprite()) {
gn('circlenum').style.visibility = 'hidden';
gn('xcursor').style.visibility = 'hidden';
gn('ycursor').style.visibility = 'hidden';
return;
}
var spr = gn(ScratchJr.stage.currentPage.currentSpriteName);
if (!spr) {
return;
}
var obj = spr.owner;
var c = gn('circlenum');
if (!c) {
return;
}
var dx = obj.xcoor + size / 2;
var dy = obj.ycoor - size / 2;
gn('xcursor').style.visibility = 'visible';
gn('ycursor').style.visibility = 'visible';
gn('circlenum').style.visibility = 'visible';
Grid.setCursorsValues(dx, dy);
}
static setCursorsValues (dx, dy) {
var c = gn('circlenum');
var numX = Math.round(dx / size);
var numY = Math.round(dy / size);
if (c.offsetLeft != (numX * 24)) {
var xc = gn('xcursor');
var xstate = ((numX < 1) || (numX > 20)) ? 'hidden' : 'visible';
setProps(xc.style, {
position: 'absolute',
left: (numX * 24) + 'px',
visibility: xstate
});
xc.childNodes[0].textContent = Localization.localize('GRID_NUMBER', {
N: numX
});
}
if (c.offsetTop != (numY * 24)) {
var yc = gn('ycursor');
var ystate = ((numY < 0) || (numY > 14)) ? 'hidden' : 'visible';
setProps(yc.style, {
position: 'absolute',
top: (numY * 24) + 'px',
visibility: ystate
});
yc.childNodes[0].textContent = Localization.localize('GRID_NUMBER', {
N: 15 - numY
});
}
setProps(c.style, {
position: 'absolute',
top: (numY * 24) + 'px',
visibility: ystate
});
yc.childNodes[0].textContent = Localization.localize('GRID_NUMBER', {
N: 15 - numY
left: ((numX - 1) * 24) + 'px'
});
}
setProps(c.style, {
position: 'absolute',
top: (numY * 24) + 'px',
left: ((numX - 1) * 24) + 'px'
});
};
Grid.hide = function (b) {
Grid.hidden = b;
var mystate = Grid.hidden ? 'hidden' : 'visible';
gn('livegrid').style.visibility = mystate;
gn('rownum').style.visibility = mystate;
gn('colnum').style.visibility = mystate;
if (ScratchJr.stage.currentPage) {
mystate = !ScratchJr.getSprite() ? 'hidden' : mystate;
static hide (b) {
hidden = b;
var mystate = hidden ? 'hidden' : 'visible';
gn('livegrid').style.visibility = mystate;
gn('rownum').style.visibility = mystate;
gn('colnum').style.visibility = mystate;
if (ScratchJr.stage.currentPage) {
mystate = !ScratchJr.getSprite() ? 'hidden' : mystate;
}
gn('circlenum').style.visibility = mystate;
gn('xcursor').style.visibility = mystate;
gn('ycursor').style.visibility = mystate;
}
gn('circlenum').style.visibility = mystate;
gn('xcursor').style.visibility = mystate;
gn('ycursor').style.visibility = mystate;
};
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,349 +1,367 @@
var Record = function () {};
import ScratchJr from '../ScratchJr';
import Palette from './Palette';
import Undo from './Undo';
import iOS from '../../iPad/iOS';
import ScratchAudio from '../../utils/ScratchAudio';
import {frame, gn, newHTML, isTablet, isAndroid, setProps} from '../../utils/lib';
Record.isAndroid = isAndroid;
Record.interval = null;
Record.recordedSound = null;
Record.isRecording = false;
Record.isPlaying = false;
Record.available = true;
Record.error = false;
Record.dialogOpen = false;
Record.timeLimit = null;
Record.playTimeLimit = null;
let interval = null;
let recordedSound = null;
let isRecording = false;
let isPlaying = false;
let available = true;
let error = false;
let dialogOpen = false;
let timeLimit = null;
let playTimeLimit = null;
// Create the recording window, including buttons and volume indicators
Record.init = function () {
var modal = newHTML('div', 'record fade', frame);
modal.setAttribute('id', 'recorddialog');
var topbar = newHTML('div', 'toolbar', modal);
var actions = newHTML('div', 'actions', topbar);
newHTML('div', 'microphone', actions);
var buttons = newHTML('div', 'recordbuttons', actions);
var okbut = newHTML('div', 'recorddone', buttons);
if (isTablet) {
okbut.ontouchstart = Record.saveSoundAndClose;
} else {
okbut.onmousedown = Record.saveSoundAndClose;
export default class Record {
static get available () {
return available;
}
var sc = newHTML('div', 'soundbox', modal);
sc.setAttribute('id', 'soundbox');
var sv = newHTML('div', 'soundvolume', sc);
sv.setAttribute('id', 'soundvolume');
for (var i = 0; i < 13; i++) {
var si = newHTML('div', 'indicator', sv);
newHTML('div', 'soundlevel', si);
static set available (newAvailable) {
available = newAvailable;
}
var ctrol = newHTML('div', 'soundcontrols', sc);
ctrol.setAttribute('id', 'soundcontrols');
var lib = [['record', Record.record], ['stop', Record.stopSnd], ['play', Record.playSnd]];
for (var j = 0; j < lib.length; j++) {
Record.newToggleClicky(ctrol, 'id_', lib[j][0], lib[j][1]);
static get dialogOpen () {
return dialogOpen;
}
};
// Dialog box hide/show
Record.appear = function () {
gn('backdrop').setAttribute('class', 'modal-backdrop fade in');
setProps(gn('backdrop').style, {
display: 'block'
});
gn('recorddialog').setAttribute('class', 'record fade in');
ScratchJr.stopStrips();
Record.dialogOpen = true;
ScratchJr.onBackButtonCallback.push(Record.saveSoundandClose);
};
Record.disappear = function () {
setTimeout(function () {
gn('backdrop').setAttribute('class', 'modal-backdrop fade');
setProps(gn('backdrop').style, {
display: 'none'
});
gn('recorddialog').setAttribute('class', 'record fade');
}, 333);
Record.dialogOpen = false;
ScratchJr.onBackButtonCallback.pop();
};
// Register toggle buttons and handlers
Record.newToggleClicky = function (p, prefix, key, fcn) {
var button = newHTML('div', 'controlwrap', p);
newHTML('div', key + 'snd off', button);
button.setAttribute('type', 'toggleclicky');
button.setAttribute('id', prefix + key);
if (fcn) {
// Create the recording window, including buttons and volume indicators
static init () {
var modal = newHTML('div', 'record fade', frame);
modal.setAttribute('id', 'recorddialog');
var topbar = newHTML('div', 'toolbar', modal);
var actions = newHTML('div', 'actions', topbar);
newHTML('div', 'microphone', actions);
var buttons = newHTML('div', 'recordbuttons', actions);
var okbut = newHTML('div', 'recorddone', buttons);
if (isTablet) {
button.ontouchstart = function (evt) {
fcn(evt);
};
okbut.ontouchstart = Record.saveSoundAndClose;
} else {
button.onmousedown = function (evt) {
fcn(evt);
};
okbut.onmousedown = Record.saveSoundAndClose;
}
var sc = newHTML('div', 'soundbox', modal);
sc.setAttribute('id', 'soundbox');
var sv = newHTML('div', 'soundvolume', sc);
sv.setAttribute('id', 'soundvolume');
for (var i = 0; i < 13; i++) {
var si = newHTML('div', 'indicator', sv);
newHTML('div', 'soundlevel', si);
}
var ctrol = newHTML('div', 'soundcontrols', sc);
ctrol.setAttribute('id', 'soundcontrols');
var lib = [['record', Record.record], ['stop', Record.stopSnd], ['play', Record.playSnd]];
for (var j = 0; j < lib.length; j++) {
Record.newToggleClicky(ctrol, 'id_', lib[j][0], lib[j][1]);
}
}
return button;
};
// Toggle button appearance on/off
Record.toggleButtonUI = function (button, newState) {
var element = 'id_' + button;
var newStateStr = (newState) ? 'on' : 'off';
var attrclass = button + 'snd';
gn(element).childNodes[0].setAttribute('class', attrclass + ' ' + newStateStr);
};
// Dialog box hide/show
static appear () {
gn('backdrop').setAttribute('class', 'modal-backdrop fade in');
setProps(gn('backdrop').style, {
display: 'block'
});
gn('recorddialog').setAttribute('class', 'record fade in');
ScratchJr.stopStrips();
dialogOpen = true;
ScratchJr.onBackButtonCallback.push(Record.saveSoundandClose);
}
// Volume UI updater
Record.updateVolume = function (f) {
var num = Math.round(f * 13);
var div = gn('soundvolume');
if (!Record.isRecording) {
num = 0;
}
for (var i = 0; i < 13; i++) {
div.childNodes[i].childNodes[0].setAttribute('class', ((i > num) ? 'soundlevel off' : 'soundlevel on'));
}
};
// Stop recording UI and turn off volume levels
Record.recordUIoff = function () {
Record.toggleButtonUI('record', false);
var div = gn('soundvolume');
for (var i = 0; i < gn('soundvolume').childElementCount; i++) {
div.childNodes[i].childNodes[0].setAttribute('class', 'soundlevel off');
}
};
// On press record button
Record.record = function (e) {
if (Record.error) {
Record.killRecorder(e);
return;
}
if (Record.isPlaying) {
Record.stopPlayingSound(doRecord);
} else {
doRecord();
}
function doRecord () {
if (Record.isRecording) {
Record.stopRecording(); // Stop if we're already recording
} else {
iOS.sndrecord(Record.startRecording); // Start a recording
}
}
};
Record.startRecording = function (filename) {
if (parseInt(filename) < 0) {
// Error in getting record filename - go back to editor
Record.recordedSound = undefined;
Record.isRecording = false;
Record.killRecorder();
Palette.selectCategory(3);
} else {
// Save recording's filename for later
Record.recordedSound = filename;
Record.isRecording = true;
Record.error = false;
Record.soundname = filename;
Record.toggleButtonUI('record', true);
var poll = function () {
iOS.volume(Record.updateVolume, Record.recordError);
};
Record.interval = setInterval(poll, 33);
Record.timeLimit = setTimeout(function () {
if (Record.isRecording) {
Record.stopRecording();
}
}, 60000);
}
};
// Press the play button
Record.playSnd = function (e) {
if (Record.error) {
Record.killRecorder(e);
return;
}
if (!Record.recordedSound) {
return;
}
if (Record.isPlaying) {
Record.stopPlayingSound();
} else {
if (Record.isRecording) {
Record.stopRecording(Record.startPlaying);
} else {
Record.startPlaying();
}
}
};
// Start playing the sound and switch UI appropriately
Record.startPlaying = function () {
iOS.startplay(Record.timeOutPlay);
Record.toggleButtonUI('play', true);
Record.isPlaying = true;
};
// Gets the sound duration from iOS and changes play UI state after time
Record.timeOutPlay = function (timeout) {
if (parseInt(timeout) < 0) {
timeout = 0.1; // Error - stop playing immediately
}
Record.playTimeLimit = setTimeout(function () {
Record.toggleButtonUI('play', false);
Record.isPlaying = false;
}, timeout * 1000);
};
// Press on stop
Record.stopSnd = function (e) {
if (Record.error) {
Record.killRecorder(e);
return;
}
if (!Record.recordedSound) {
return;
}
Record.flashStopButton();
if (Record.isRecording) {
Record.stopRecording();
} else if (Record.isPlaying) {
Record.stopPlayingSound();
}
};
Record.flashStopButton = function () {
Record.toggleButtonUI('stop', true);
setTimeout(function () {
Record.toggleButtonUI('stop', false);
}, 200);
};
// Stop playing the sound and switch UI appropriately
Record.stopPlayingSound = function (fcn) {
iOS.stopplay(fcn);
Record.toggleButtonUI('play', false);
Record.isPlaying = false;
window.clearTimeout(Record.playTimeLimit);
Record.playTimeLimit = null;
};
// Stop the volume monitor and recording
Record.stopRecording = function (fcn) {
if (Record.timeLimit != null) {
clearTimeout(Record.timeLimit);
Record.timeLimit = null;
}
if (Record.interval != null) {
window.clearInterval(Record.interval);
Record.interval = null;
static disappear () {
setTimeout(function () {
Record.volumeCheckStopped(fcn);
}, 33);
} else {
Record.volumeCheckStopped(fcn);
gn('backdrop').setAttribute('class', 'modal-backdrop fade');
setProps(gn('backdrop').style, {
display: 'none'
});
gn('recorddialog').setAttribute('class', 'record fade');
}, 333);
dialogOpen = false;
ScratchJr.onBackButtonCallback.pop();
}
};
Record.volumeCheckStopped = function (fcn) {
Record.isRecording = false;
Record.recordUIoff();
iOS.recordstop(fcn);
};
// Press OK (check)
Record.saveSoundAndClose = function () {
if (Record.error || !Record.recordedSound) {
Record.killRecorder();
} else {
if (Record.isPlaying) {
Record.stopPlayingSound(Record.closeContinueSave);
} else {
if (Record.isRecording) {
Record.stopRecording(Record.closeContinueSave);
// Register toggle buttons and handlers
static newToggleClicky (p, prefix, key, fcn) {
var button = newHTML('div', 'controlwrap', p);
newHTML('div', key + 'snd off', button);
button.setAttribute('type', 'toggleclicky');
button.setAttribute('id', prefix + key);
if (fcn) {
if (isTablet) {
button.ontouchstart = function (evt) {
fcn(evt);
};
} else {
Record.closeContinueSave();
button.onmousedown = function (evt) {
fcn(evt);
};
}
}
return button;
}
// Toggle button appearance on/off
static toggleButtonUI (button, newState) {
var element = 'id_' + button;
var newStateStr = (newState) ? 'on' : 'off';
var attrclass = button + 'snd';
gn(element).childNodes[0].setAttribute('class', attrclass + ' ' + newStateStr);
}
// Volume UI updater
static updateVolume (f) {
var num = Math.round(f * 13);
var div = gn('soundvolume');
if (!isRecording) {
num = 0;
}
for (var i = 0; i < 13; i++) {
div.childNodes[i].childNodes[0].setAttribute('class', ((i > num) ? 'soundlevel off' : 'soundlevel on'));
}
}
// Stop recording UI and turn off volume levels
static recordUIoff () {
Record.toggleButtonUI('record', false);
var div = gn('soundvolume');
for (var i = 0; i < gn('soundvolume').childElementCount; i++) {
div.childNodes[i].childNodes[0].setAttribute('class', 'soundlevel off');
}
}
// On press record button
static record (e) {
if (error) {
Record.killRecorder(e);
return;
}
if (isPlaying) {
Record.stopPlayingSound(doRecord);
} else {
doRecord();
}
function doRecord () {
if (isRecording) {
Record.stopRecording(); // Stop if we're already recording
} else {
iOS.sndrecord(Record.startRecording); // Start a recording
}
}
}
};
Record.closeContinueSave = function () {
iOS.recorddisappear('YES', Record.getUserSound);
};
Record.closeContinueRemove = function () {
// don't get the sound - proceed right to tearDown
iOS.recorddisappear('NO', Record.tearDownRecorder);
};
Record.getUserSound = function () {
Record.isRecording = false;
if (!Record.isAndroid) {
iOS.getmedia(Record.recordedSound, Record.registerProjectSound);
} else {
// On Android, just pass URL
Record.registerProjectSound(null);
}
};
Record.registerProjectSound = function (data) {
function loadingDone (snd) {
if (snd != 'error') {
var spr = ScratchJr.getSprite();
var page = spr.div.parentNode.owner;
spr.sounds.push(Record.recordedSound);
Undo.record({
action: 'recordsound',
who: spr.id,
where: page.id,
sound: Record.recordedSound
});
ScratchJr.storyStart('Record.registerProjectSound');
}
Record.tearDownRecorder();
Palette.selectCategory(3);
}
if (!Record.isAndroid) {
ScratchAudio.loadFromData(Record.recordedSound, data, loadingDone);
} else {
// On Android, just pass URL
ScratchAudio.loadFromLocal(Record.recordedSound, loadingDone);
}
};
// Called on error - remove everything and hide the recorder
Record.killRecorder = function () {
// Inform iOS and then tear-down
if (Record.isPlaying) {
Record.stopPlayingSound(Record.closeContinueRemove); // stop playing and tear-down
} else {
if (Record.isRecording) {
Record.stopRecording(Record.closeContinueRemove); // stop recording and tear-down
static startRecording (filename) {
if (parseInt(filename) < 0) {
// Error in getting record filename - go back to editor
recordedSound = undefined;
isRecording = false;
Record.killRecorder();
Palette.selectCategory(3);
} else {
Record.closeContinueRemove();
// Save recording's filename for later
recordedSound = filename;
isRecording = true;
error = false;
Record.soundname = filename;
Record.toggleButtonUI('record', true);
var poll = function () {
iOS.volume(Record.updateVolume, Record.recordError);
};
interval = setInterval(poll, 33);
timeLimit = setTimeout(function () {
if (isRecording) {
Record.stopRecording();
}
}, 60000);
}
}
};
Record.tearDownRecorder = function () {
// Clear errors
if (Record.error) {
Record.error = false;
// Press the play button
static playSnd (e) {
if (error) {
Record.killRecorder(e);
return;
}
if (!recordedSound) {
return;
}
if (isPlaying) {
Record.stopPlayingSound();
} else {
if (isRecording) {
Record.stopRecording(Record.startPlaying);
} else {
Record.startPlaying();
}
}
}
// Refresh audio context
ScratchAudio.firstTime = true;
Record.isRecording = false;
Record.recordedSound = null;
// Hide the dialog
Record.disappear();
};
// Called when the app is put into the background
Record.recordError = function () {
Record.error = true;
Record.killRecorder();
};
// Start playing the sound and switch UI appropriately
static startPlaying () {
iOS.startplay(Record.timeOutPlay);
Record.toggleButtonUI('play', true);
isPlaying = true;
}
// Gets the sound duration from iOS and changes play UI state after time
static timeOutPlay (timeout) {
if (parseInt(timeout) < 0) {
timeout = 0.1; // Error - stop playing immediately
}
playTimeLimit = setTimeout(function () {
Record.toggleButtonUI('play', false);
isPlaying = false;
}, timeout * 1000);
}
// Press on stop
static stopSnd (e) {
if (error) {
Record.killRecorder(e);
return;
}
if (!recordedSound) {
return;
}
Record.flashStopButton();
if (isRecording) {
Record.stopRecording();
} else if (isPlaying) {
Record.stopPlayingSound();
}
}
static flashStopButton () {
Record.toggleButtonUI('stop', true);
setTimeout(function () {
Record.toggleButtonUI('stop', false);
}, 200);
}
// Stop playing the sound and switch UI appropriately
static stopPlayingSound (fcn) {
iOS.stopplay(fcn);
Record.toggleButtonUI('play', false);
isPlaying = false;
window.clearTimeout(playTimeLimit);
playTimeLimit = null;
}
// Stop the volume monitor and recording
static stopRecording (fcn) {
if (timeLimit != null) {
clearTimeout(timeLimit);
timeLimit = null;
}
if (interval != null) {
window.clearInterval(interval);
interval = null;
setTimeout(function () {
Record.volumeCheckStopped(fcn);
}, 33);
} else {
Record.volumeCheckStopped(fcn);
}
}
static volumeCheckStopped (fcn) {
isRecording = false;
Record.recordUIoff();
iOS.recordstop(fcn);
}
// Press OK (check)
static saveSoundAndClose () {
if (error || !recordedSound) {
Record.killRecorder();
} else {
if (isPlaying) {
Record.stopPlayingSound(Record.closeContinueSave);
} else {
if (isRecording) {
Record.stopRecording(Record.closeContinueSave);
} else {
Record.closeContinueSave();
}
}
}
}
static closeContinueSave () {
iOS.recorddisappear('YES', Record.getUserSound);
}
static closeContinueRemove () {
// don't get the sound - proceed right to tearDown
iOS.recorddisappear('NO', Record.tearDownRecorder);
}
static getUserSound () {
isRecording = false;
if (!isAndroid) {
iOS.getmedia(recordedSound, Record.registerProjectSound);
} else {
// On Android, just pass URL
Record.registerProjectSound(null);
}
}
static registerProjectSound (data) {
function loadingDone (snd) {
if (snd != 'error') {
var spr = ScratchJr.getSprite();
var page = spr.div.parentNode.owner;
spr.sounds.push(recordedSound);
Undo.record({
action: 'recordsound',
who: spr.id,
where: page.id,
sound: recordedSound
});
ScratchJr.storyStart('Record.registerProjectSound');
}
Record.tearDownRecorder();
Palette.selectCategory(3);
}
if (!isAndroid) {
ScratchAudio.loadFromData(recordedSound, data, loadingDone);
} else {
// On Android, just pass URL
ScratchAudio.loadFromLocal(recordedSound, loadingDone);
}
}
// Called on error - remove everything and hide the recorder
static killRecorder () {
// Inform iOS and then tear-down
if (isPlaying) {
Record.stopPlayingSound(Record.closeContinueRemove); // stop playing and tear-down
} else {
if (isRecording) {
Record.stopRecording(Record.closeContinueRemove); // stop recording and tear-down
} else {
Record.closeContinueRemove();
}
}
}
static tearDownRecorder () {
// Clear errors
if (error) {
error = false;
}
// Refresh audio context
ScratchAudio.firstTime = true;
isRecording = false;
recordedSound = null;
// Hide the dialog
Record.disappear();
}
// Called when the app is put into the background
static recordError () {
error = true;
Record.killRecorder();
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,308 +1,328 @@
var ScriptsPane = function () {};
ScriptsPane.scroll = undefined;
import ScratchJr from '../ScratchJr';
import Project from './Project';
import Thumbs from './Thumbs';
import Palette from './Palette';
import Undo from './Undo';
import Events from '../../utils/Events';
import Scroll from './Scroll';
import Menu from '../blocks/Menu';
import ScratchAudio from '../../utils/ScratchAudio';
import {gn, localx, localy, newHTML, isTablet,
globalx, globaly, setCanvasSize, getDocumentHeight, frame} from '../../utils/lib';
ScriptsPane.watermark;
let scroll = undefined;
let watermark;
ScriptsPane.createScripts = function (parent) {
var div = newHTML('div', 'scripts', parent);
div.setAttribute('id', 'scripts');
ScriptsPane.watermark = newHTML('div', 'watermark', div);
var h = Math.max(getDocumentHeight(), frame.offsetHeight);
setCanvasSize(div, div.offsetWidth, h - div.offsetTop);
ScriptsPane.scroll = new Scroll(div, 'scriptscontainer', div.offsetWidth,
h - div.offsetTop, ScratchJr.getActiveScript, ScratchJr.getBlocks);
};
ScriptsPane.setActiveScript = function (sprname) {
var currentsc = gn(sprname + '_scripts');
if (!currentsc) {
// Sprite not found
return;
export default class ScriptsPane {
static get scroll () {
return scroll;
}
ScratchJr.stage.currentPage.setCurrentSprite(gn(sprname).owner);
currentsc.owner.activate();
currentsc.parentNode.ontouchstart = function (evt) {
currentsc.owner.scriptsMouseDown(evt);
};
ScriptsPane.scroll.update();
};
ScriptsPane.runBlock = function (e, div) {
e.preventDefault();
e.stopPropagation();
var b = div.owner.findFirst();
// if (b.aStart) b = b.next;
if (!b) {
return;
static get watermark () {
return watermark;
}
ScratchJr.runtime.addRunScript(ScratchJr.getSprite(), b);
ScratchJr.startCurrentPageStrips(['ontouch']);
ScratchJr.userStart = true;
};
ScriptsPane.prepareToDrag = function (e) {
e.preventDefault();
var pt = Events.getTargetPoint(e);
ScriptsPane.pickBlock(pt.x, pt.y, e);
};
static createScripts (parent) {
var div = newHTML('div', 'scripts', parent);
div.setAttribute('id', 'scripts');
watermark = newHTML('div', 'watermark', div);
var h = Math.max(getDocumentHeight(), frame.offsetHeight);
setCanvasSize(div, div.offsetWidth, h - div.offsetTop);
scroll = new Scroll(div, 'scriptscontainer', div.offsetWidth,
h - div.offsetTop, ScratchJr.getActiveScript, ScratchJr.getBlocks);
}
ScriptsPane.pickBlock = function (x, y, e) {
if (!ScratchJr.runtime.inactive()) {
ScratchJr.stopStrips();
}
ScriptsPane.cleanCarets();
ScratchJr.unfocus(e);
var sc = ScratchJr.getActiveScript().owner;
sc.dragList = sc.findGroup(Events.dragthumbnail.owner);
sc.flowCaret = null;
var sy = Events.dragthumbnail.parentNode.scrollTop;
var sx = Events.dragthumbnail.parentNode.scrollLeft;
Events.dragmousex = x;
Events.dragmousey = y;
var lpt = {
x: localx(Events.dragthumbnail.parentNode, x),
y: localy(Events.dragthumbnail.parentNode, y)
};
var mx = Events.dragmousex - globalx(Events.dragDiv) - lpt.x + Events.dragthumbnail.left;
var my = Events.dragmousey - globaly(Events.dragDiv) - lpt.y + Events.dragthumbnail.top;
var mtx = new WebKitCSSMatrix(window.getComputedStyle(Events.dragthumbnail).webkitTransform);
my -= sy;
mx -= sx;
Events.dragcanvas = Events.dragthumbnail;
Events.dragcanvas.origin = 'scripts';
Events.dragcanvas.startx = mtx.m41;
Events.dragcanvas.starty = mtx.m42;
if (!Events.dragcanvas.isReporter && Events.dragcanvas.parentNode) {
Events.dragcanvas.parentNode.removeChild(Events.dragcanvas);
}
Events.move3D(Events.dragcanvas, mx, my);
Events.dragcanvas.style.zIndex = ScratchJr.dragginLayer;
Events.dragDiv.appendChild(Events.dragcanvas);
var b = Events.dragcanvas.owner;
b.detachBlock();
// b.lift();
if (Events.dragcanvas.isReporter) {
return;
}
ScratchJr.getActiveScript().owner.prepareCaret(b);
for (var i = 1; i < sc.dragList.length; i++) {
b = sc.dragList[i];
var pos = new WebKitCSSMatrix(window.getComputedStyle(b.div).webkitTransform);
var dx = pos.m41 - mtx.m41;
var dy = pos.m42 - mtx.m42;
b.moveBlock(dx, dy);
// b.lift();
Events.dragcanvas.appendChild(b.div);
}
};
////////////////////////////////////////////////
// Events MouseMove
////////////////////////////////////////////////
ScriptsPane.draggingBlock = function (e) {
e.preventDefault();
var pt = Events.getTargetPoint(e);
var dx = pt.x - Events.dragmousex;
var dy = pt.y - Events.dragmousey;
Events.move3D(Events.dragcanvas, dx, dy);
ScriptsPane.blockFeedback(Events.dragcanvas.left, Events.dragcanvas.top, e);
};
ScriptsPane.blockFeedback = function (dx, dy, e) {
var script = ScratchJr.getActiveScript().owner;
var limit = gn('palette').parentNode.offsetTop + gn('palette').parentNode.offsetHeight;
var ycor = dy + Events.dragcanvas.offsetHeight;
if (ycor < limit) {
script.removeCaret();
} else {
script.removeCaret();
script.insertCaret(dx, dy);
}
var thumb;
switch (Palette.getLandingPlace(script.dragList[0].div, e)) {
case 'library':
thumb = Palette.getHittedThumb(script.dragList[0].div, gn('spritecc'));
if (thumb && (gn(thumb.owner).owner.type == ScratchJr.getSprite().type)) {
Thumbs.quickHighlight(thumb);
} else {
thumb = undefined;
static setActiveScript (sprname) {
var currentsc = gn(sprname + '_scripts');
if (!currentsc) {
// Sprite not found
return;
}
ScratchJr.stage.currentPage.setCurrentSprite(gn(sprname).owner);
currentsc.owner.activate();
currentsc.parentNode.ontouchstart = function (evt) {
currentsc.owner.scriptsMouseDown(evt);
};
scroll.update();
}
static runBlock (e, div) {
e.preventDefault();
e.stopPropagation();
var b = div.owner.findFirst();
// if (b.aStart) b = b.next;
if (!b) {
return;
}
ScratchJr.runtime.addRunScript(ScratchJr.getSprite(), b);
ScratchJr.startCurrentPageStrips(['ontouch']);
ScratchJr.userStart = true;
}
static prepareToDrag (e) {
e.preventDefault();
var pt = Events.getTargetPoint(e);
ScriptsPane.pickBlock(pt.x, pt.y, e);
}
static pickBlock (x, y, e) {
if (!ScratchJr.runtime.inactive()) {
ScratchJr.stopStrips();
}
ScriptsPane.cleanCarets();
ScratchJr.unfocus(e);
var sc = ScratchJr.getActiveScript().owner;
sc.dragList = sc.findGroup(Events.dragthumbnail.owner);
sc.flowCaret = null;
var sy = Events.dragthumbnail.parentNode.scrollTop;
var sx = Events.dragthumbnail.parentNode.scrollLeft;
Events.dragmousex = x;
Events.dragmousey = y;
var lpt = {
x: localx(Events.dragthumbnail.parentNode, x),
y: localy(Events.dragthumbnail.parentNode, y)
};
var mx = Events.dragmousex - globalx(Events.dragDiv) - lpt.x + Events.dragthumbnail.left;
var my = Events.dragmousey - globaly(Events.dragDiv) - lpt.y + Events.dragthumbnail.top;
var mtx = new WebKitCSSMatrix(window.getComputedStyle(Events.dragthumbnail).webkitTransform);
my -= sy;
mx -= sx;
Events.dragcanvas = Events.dragthumbnail;
Events.dragcanvas.origin = 'scripts';
Events.dragcanvas.startx = mtx.m41;
Events.dragcanvas.starty = mtx.m42;
if (!Events.dragcanvas.isReporter && Events.dragcanvas.parentNode) {
Events.dragcanvas.parentNode.removeChild(Events.dragcanvas);
}
Events.move3D(Events.dragcanvas, mx, my);
Events.dragcanvas.style.zIndex = ScratchJr.dragginLayer;
Events.dragDiv.appendChild(Events.dragcanvas);
var b = Events.dragcanvas.owner;
b.detachBlock();
// b.lift();
if (Events.dragcanvas.isReporter) {
return;
}
ScratchJr.getActiveScript().owner.prepareCaret(b);
for (var i = 1; i < sc.dragList.length; i++) {
b = sc.dragList[i];
var pos = new WebKitCSSMatrix(window.getComputedStyle(b.div).webkitTransform);
var dx = pos.m41 - mtx.m41;
var dy = pos.m42 - mtx.m42;
b.moveBlock(dx, dy);
// b.lift();
Events.dragcanvas.appendChild(b.div);
}
}
////////////////////////////////////////////////
// Events MouseMove
////////////////////////////////////////////////
static draggingBlock (e) {
e.preventDefault();
var pt = Events.getTargetPoint(e);
var dx = pt.x - Events.dragmousex;
var dy = pt.y - Events.dragmousey;
Events.move3D(Events.dragcanvas, dx, dy);
ScriptsPane.blockFeedback(Events.dragcanvas.left, Events.dragcanvas.top, e);
}
static blockFeedback (dx, dy, e) {
var script = ScratchJr.getActiveScript().owner;
var limit = gn('palette').parentNode.offsetTop + gn('palette').parentNode.offsetHeight;
var ycor = dy + Events.dragcanvas.offsetHeight;
if (ycor < limit) {
script.removeCaret();
} else {
script.removeCaret();
script.insertCaret(dx, dy);
}
var thumb;
switch (Palette.getLandingPlace(script.dragList[0].div, e)) {
case 'library':
thumb = Palette.getHittedThumb(script.dragList[0].div, gn('spritecc'));
if (thumb && (gn(thumb.owner).owner.type == ScratchJr.getSprite().type)) {
Thumbs.quickHighlight(thumb);
} else {
thumb = undefined;
}
for (var i = 0; i < gn('spritecc').childElementCount; i++) {
var spr = gn('spritecc').childNodes[i];
if (spr.nodeName == 'FORM') {
continue;
}
if (thumb && (thumb.id != spr.id)) {
Thumbs.quickRestore(spr);
}
}
break;
default:
ScriptsPane.removeLibCaret();
break;
}
}
////////////////////////////////////////////////
// Events MouseUP
////////////////////////////////////////////////
static dropBlock (e, el) {
e.preventDefault();
var sc = ScratchJr.getActiveScript();
var spr = sc.owner.spr.id;
var page = ScratchJr.stage.currentPage;
switch (Palette.getLandingPlace(el, e)) {
case 'scripts':
var dx = localx(sc, el.left);
var dy = localy(sc, el.top);
ScriptsPane.blockDropped(sc, dx, dy);
break;
case 'library':
var thumb = Palette.getHittedThumb(el, gn('spritecc'));
ScriptsPane.blockDropped(ScratchJr.getActiveScript(), el.startx, el.starty);
if (thumb && (gn(thumb.owner).owner.type == gn(page.currentSpriteName).owner.type)) {
ScratchJr.storyStart('ScriptsPane.dropBlock:library');
ScratchAudio.sndFX('copy.wav');
Thumbs.quickHighlight(thumb);
setTimeout(function () {
Thumbs.quickRestore(thumb);
}, 300);
sc = gn(thumb.owner + '_scripts').owner;
var strip = Project.encodeStrip(el.owner);
var firstblock = strip[0];
var delta = sc.gettopblocks().length * 3;
firstblock[2] = firstblock[2] + delta;
firstblock[3] = firstblock[3] + delta;
sc.recreateStrip(strip);
spr = thumb.owner;
}
break;
default:
ScratchJr.getActiveScript().owner.deleteBlocks();
scroll.adjustCanvas();
scroll.refresh();
scroll.fitToScreen();
break;
}
Undo.record({
action: 'scripts',
where: page.id,
who: spr
});
ScratchJr.getActiveScript().owner.dragList = [];
}
static blockDropped (sc, dx, dy) {
Events.dragcanvas.style.zIndex = '';
var script = ScratchJr.getActiveScript().owner;
ScriptsPane.cleanCarets();
script.addBlockToScripts(Events.dragcanvas, dx, dy);
script.layout(Events.dragcanvas.owner);
if (sc.id == ScratchJr.getActiveScript().id) {
scroll.adjustCanvas();
scroll.refresh();
scroll.bounceBack();
}
}
static cleanCarets () {
ScratchJr.getActiveScript().owner.removeCaret();
ScriptsPane.removeLibCaret();
}
static removeLibCaret () {
for (var i = 0; i < gn('spritecc').childElementCount; i++) {
var spr = gn('spritecc').childNodes[i];
if (spr.nodeName == 'FORM') {
continue;
}
if (thumb && (thumb.id != spr.id)) {
Thumbs.quickRestore(spr);
Thumbs.quickRestore(spr);
}
}
//----------------------------------
// Drag Script Background
//----------------------------------
static dragBackground (e) {
if (Menu.openMenu) {
return;
}
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
var sc = ScratchJr.getActiveScript();
sc.top = sc.offsetTop;
sc.left = sc.offsetLeft;
var pt = Events.getTargetPoint(e);
Events.dragmousex = pt.x;
Events.dragmousey = pt.y;
Events.dragged = false;
ScriptsPane.setDragBackgroundEvents(ScriptsPane.dragMove, ScriptsPane.dragEnd);
}
static setDragBackgroundEvents (fcnmove, fcnup) {
if (isTablet) { // setDragBackgroundEvents
window.ontouchmove = function (evt) {
fcnmove(evt);
};
window.ontouchend = function (evt) {
fcnup(evt);
};
} else {
window.onmousemove = function (evt) {
fcnmove(evt);
};
window.onmouseup = function (evt) {
fcnup(evt);
};
}
}
static dragMove (e) {
var pt = Events.getTargetPoint(e);
if (!Events.dragged && (Events.distance(Events.dragmousex - pt.x, Events.dragmousey - pt.y) < 5)) {
return;
}
Events.dragged = true;
var dx = pt.x - Events.dragmousex;
var dy = pt.y - Events.dragmousey;
Events.dragmousex = pt.x;
Events.dragmousey = pt.y;
Events.move3D(ScratchJr.getActiveScript(), dx, dy);
scroll.refresh();
e.preventDefault();
}
static dragEnd (e) {
Events.dragged = false;
e.preventDefault();
Events.clearEvents();
scroll.bounceBack();
}
//////////////////////
//
//////////////////////
static updateScriptsPageBlocks (list) {
for (var j = 0; j < list.length; j++) {
if (!gn(list[j] + '_scripts')) {
continue;
}
var sc = gn(list[j] + '_scripts').owner;
if (!sc) {
continue;
}
var allblocks = sc.getBlocks();
for (var i = 0; i < allblocks.length; i++) {
allblocks[i].updateBlock();
}
}
break;
default:
ScriptsPane.removeLibCaret();
break;
}
};
////////////////////////////////////////////////
// Events MouseUP
////////////////////////////////////////////////
ScriptsPane.dropBlock = function (e, el) {
e.preventDefault();
var sc = ScratchJr.getActiveScript();
var spr = sc.owner.spr.id;
var page = ScratchJr.stage.currentPage;
switch (Palette.getLandingPlace(el, e)) {
case 'scripts':
var dx = localx(sc, el.left);
var dy = localy(sc, el.top);
ScriptsPane.blockDropped(sc, dx, dy);
break;
case 'library':
var thumb = Palette.getHittedThumb(el, gn('spritecc'));
ScriptsPane.blockDropped(ScratchJr.getActiveScript(), el.startx, el.starty);
if (thumb && (gn(thumb.owner).owner.type == gn(page.currentSpriteName).owner.type)) {
ScratchJr.storyStart('ScriptsPane.dropBlock:library');
ScratchAudio.sndFX('copy.wav');
Thumbs.quickHighlight(thumb);
setTimeout(function () {
Thumbs.quickRestore(thumb);
}, 300);
sc = gn(thumb.owner + '_scripts').owner;
var strip = Project.encodeStrip(el.owner);
var firstblock = strip[0];
var delta = sc.gettopblocks().length * 3;
firstblock[2] = firstblock[2] + delta;
firstblock[3] = firstblock[3] + delta;
sc.recreateStrip(strip);
spr = thumb.owner;
}
break;
default:
ScratchJr.getActiveScript().owner.deleteBlocks();
ScriptsPane.scroll.adjustCanvas();
ScriptsPane.scroll.refresh();
ScriptsPane.scroll.fitToScreen();
break;
}
Undo.record({
action: 'scripts',
where: page.id,
who: spr
});
ScratchJr.getActiveScript().owner.dragList = [];
};
ScriptsPane.blockDropped = function (sc, dx, dy) {
Events.dragcanvas.style.zIndex = '';
var script = ScratchJr.getActiveScript().owner;
ScriptsPane.cleanCarets();
script.addBlockToScripts(Events.dragcanvas, dx, dy);
script.layout(Events.dragcanvas.owner);
if (sc.id == ScratchJr.getActiveScript().id) {
ScriptsPane.scroll.adjustCanvas();
ScriptsPane.scroll.refresh();
ScriptsPane.scroll.bounceBack();
}
};
ScriptsPane.cleanCarets = function () {
ScratchJr.getActiveScript().owner.removeCaret();
ScriptsPane.removeLibCaret();
};
ScriptsPane.removeLibCaret = function () {
for (var i = 0; i < gn('spritecc').childElementCount; i++) {
var spr = gn('spritecc').childNodes[i];
if (spr.nodeName == 'FORM') {
continue;
}
Thumbs.quickRestore(spr);
}
};
//----------------------------------
// Drag Script Background
//----------------------------------
ScriptsPane.dragBackground = function (e) {
if (Menu.openMenu) {
return;
}
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
var sc = ScratchJr.getActiveScript();
sc.top = sc.offsetTop;
sc.left = sc.offsetLeft;
var pt = Events.getTargetPoint(e);
Events.dragmousex = pt.x;
Events.dragmousey = pt.y;
Events.dragged = false;
ScriptsPane.setDragBackgroundEvents(ScriptsPane.dragMove, ScriptsPane.dragEnd);
};
ScriptsPane.setDragBackgroundEvents = function (fcnmove, fcnup) {
if (isTablet) { // setDragBackgroundEvents
window.ontouchmove = function (evt) {
fcnmove(evt);
};
window.ontouchend = function (evt) {
fcnup(evt);
};
} else {
window.onmousemove = function (evt) {
fcnmove(evt);
};
window.onmouseup = function (evt) {
fcnup(evt);
};
}
};
ScriptsPane.dragMove = function (e) {
var pt = Events.getTargetPoint(e);
if (!Events.dragged && (Events.distance(Events.dragmousex - pt.x, Events.dragmousey - pt.y) < 5)) {
return;
}
Events.dragged = true;
var dx = pt.x - Events.dragmousex;
var dy = pt.y - Events.dragmousey;
Events.dragmousex = pt.x;
Events.dragmousey = pt.y;
Events.move3D(ScratchJr.getActiveScript(), dx, dy);
ScriptsPane.scroll.refresh();
e.preventDefault();
};
ScriptsPane.dragEnd = function (e) {
Events.dragged = false;
e.preventDefault();
Events.clearEvents();
ScriptsPane.scroll.bounceBack();
};
//////////////////////
//
//////////////////////
ScriptsPane.updateScriptsPageBlocks = function (list) {
for (var j = 0; j < list.length; j++) {
if (!gn(list[j] + '_scripts')) {
continue;
}
var sc = gn(list[j] + '_scripts').owner;
if (!sc) {
continue;
}
var allblocks = sc.getBlocks();
for (var i = 0; i < allblocks.length; i++) {
allblocks[i].updateBlock();
}
}
};
}

View file

@ -2,481 +2,486 @@
// Scrolling Pane
////////////////////////////////////////////////
var Scroll = function (div, id, w, h, cfcn, ofcn) {
this.hasHorizontal = true;
this.hasVertical = true;
this.arrowDistance = 6;
this.aleft = undefined;
this.aright = undefined;
this.aup = undefined;
this.adown = undefined;
this.contents = newDiv(div, 0, 0, w, h, {});
this.contents.setAttribute('id', id);
this.contents.owner = this;
this.addArrows(div, w, h);
this.getContent = cfcn;
this.getObjects = ofcn;
div.scroll = this; // for now;
};
import Events from '../../utils/Events';
import {newDiv, newHTML, CSSTransition3D, isTablet, setCanvasSize} from '../../utils/lib';
Scroll.prototype.update = function () {
this.adjustCanvas();
this.refresh();
this.bounceBack();
};
/////////////////////////////////////////////////////////////
// Arrows
////////////////////////////////////////////////////////////
Scroll.prototype.addArrows = function (sc, w, h) {
this.aleft = newHTML('div', 'leftarrow', sc);
this.aleft.style.height = h + 'px';
var larrow = newHTML('span', undefined, this.aleft);
larrow.style.top = Math.floor((h - larrow.offsetHeight) / 2) + 'px';
this.aright = newHTML('div', 'rightarrow', sc);
this.aright.style.height = h + 'px';
var rarrow = newHTML('span', undefined, this.aright);
rarrow.style.top = Math.floor((h - rarrow.offsetHeight) / 2) + 'px';
this.aup = newHTML('div', 'toparrow', sc);
this.adown = newHTML('div', 'bottomarrow', sc);
newHTML('div', 'halign up', this.aup);
newHTML('div', 'halign down', this.adown);
var me = this;
if (isTablet) {
this.aup.ontouchstart = function (e) {
me.scrolldown(e);
};
} else {
this.aup.onmousedown = function (e) {
me.scrolldown(e);
};
export default class Scroll {
constructor (div, id, w, h, cfcn, ofcn) {
this.hasHorizontal = true;
this.hasVertical = true;
this.arrowDistance = 6;
this.aleft = undefined;
this.aright = undefined;
this.aup = undefined;
this.adown = undefined;
this.contents = newDiv(div, 0, 0, w, h, {});
this.contents.setAttribute('id', id);
this.contents.owner = this;
this.addArrows(div, w, h);
this.getContent = cfcn;
this.getObjects = ofcn;
div.scroll = this; // for now;
}
if (isTablet) {
this.adown.ontouchstart = function (e) {
me.scrollup(e);
};
} else {
this.adown.onmousedown = function (e) {
me.scrollup(e);
};
update () {
this.adjustCanvas();
this.refresh();
this.bounceBack();
}
if (isTablet) {
this.aleft.ontouchstart = function (e) {
me.scrollright(e);
};
} else {
this.aleft.onmousedown = function (e) {
me.scrollright(e);
};
}
/////////////////////////////////////////////////////////////
// Arrows
////////////////////////////////////////////////////////////
if (isTablet) {
this.aright.ontouchstart = function (e) {
me.scrollleft(e);
};
} else {
this.aright.onmousedown = function (e) {
me.scrollleft(e);
};
}
addArrows (sc, w, h) {
this.aleft = newHTML('div', 'leftarrow', sc);
this.aleft.style.height = h + 'px';
var larrow = newHTML('span', undefined, this.aleft);
larrow.style.top = Math.floor((h - larrow.offsetHeight) / 2) + 'px';
};
this.aright = newHTML('div', 'rightarrow', sc);
this.aright.style.height = h + 'px';
var rarrow = newHTML('span', undefined, this.aright);
rarrow.style.top = Math.floor((h - rarrow.offsetHeight) / 2) + 'px';
/////////////////////////////////////////////////////////////
// Scrolling
////////////////////////////////////////////////////////////
this.aup = newHTML('div', 'toparrow', sc);
this.adown = newHTML('div', 'bottomarrow', sc);
newHTML('div', 'halign up', this.aup);
newHTML('div', 'halign down', this.adown);
Scroll.prototype.repositionArrows = function (h) {
this.aleft.style.height = h + 'px';
this.aleft.childNodes[0].style.top = Math.floor((h - this.aleft.childNodes[0].offsetHeight) / 2) + 'px';
this.aright.style.height = h + 'px';
this.aright.childNodes[0].style.top = Math.floor((h - this.aright.childNodes[0].offsetHeight) / 2) + 'px';
};
Scroll.prototype.getAdjustment = function (rect) { // rect of the dragg block canvas
var d = this.contents.parentNode; // scripts
var w = d.offsetWidth;
var h = d.offsetHeight;
if ((rect.x > 0) && (rect.y > 0)) {
return 'topleft';
}
if (((rect.x + rect.width) < w) && ((rect.y + rect.height) < h)) {
return 'bottomright';
}
if ((rect.x > 0) && ((rect.y + rect.height) < h)) {
return 'bottomleft';
}
if (((rect.x + rect.width) < w) && (rect.y > 0)) {
return 'topright';
}
if ((rect.x + rect.width) < w) {
return 'right';
}
if ((rect.y + rect.height) < h) {
return 'down';
}
if (rect.y > 0) {
return 'up';
}
if (rect.x > 0) {
return 'left';
}
return 'none';
};
Scroll.prototype.bounceBack = function () {
var owner = this;
var p = this.contents; // scriptscontainer
var bc = this.getContent(); // blockcanvas
var valx = bc.left;
var valy = bc.top;
var h = p.offsetHeight;
var w = p.offsetWidth;
var rect = {
x: valx,
y: valy,
width: bc.offsetWidth,
height: bc.offsetHeight
};
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {},
onComplete: function () {
owner.refresh();
var me = this;
if (isTablet) {
this.aup.ontouchstart = function (e) {
me.scrolldown(e);
};
} else {
this.aup.onmousedown = function (e) {
me.scrolldown(e);
};
}
};
switch (this.getAdjustment(rect)) {
case 'topright':
transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px';
transition.style.top = '0px';
CSSTransition3D(bc, transition);
break;
case 'bottomright':
transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px';
transition.style.top = (this.hasVertical ? h - rect.height : 0) + 'px';
CSSTransition3D(bc, transition);
break;
case 'topleft':
transition.style.top = '0px';
transition.style.left = '0px';
CSSTransition3D(bc, transition);
break;
case 'bottomleft':
transition.style.top = (this.hasVertical ? h - rect.height : 0) + 'px';
transition.style.left = '0px';
CSSTransition3D(bc, transition);
break;
case 'right':
transition.style.top = valy + 'px';
transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px';
CSSTransition3D(bc, transition);
break;
case 'left':
if (this.hasHorizontal) {
transition.style.top = valy + 'px';
if (isTablet) {
this.adown.ontouchstart = function (e) {
me.scrollup(e);
};
} else {
this.adown.onmousedown = function (e) {
me.scrollup(e);
};
}
if (isTablet) {
this.aleft.ontouchstart = function (e) {
me.scrollright(e);
};
} else {
this.aleft.onmousedown = function (e) {
me.scrollright(e);
};
}
if (isTablet) {
this.aright.ontouchstart = function (e) {
me.scrollleft(e);
};
} else {
this.aright.onmousedown = function (e) {
me.scrollleft(e);
};
}
}
/////////////////////////////////////////////////////////////
// Scrolling
////////////////////////////////////////////////////////////
repositionArrows (h) {
this.aleft.style.height = h + 'px';
this.aleft.childNodes[0].style.top = Math.floor((h - this.aleft.childNodes[0].offsetHeight) / 2) + 'px';
this.aright.style.height = h + 'px';
this.aright.childNodes[0].style.top = Math.floor((h - this.aright.childNodes[0].offsetHeight) / 2) + 'px';
}
getAdjustment (rect) { // rect of the dragg block canvas
var d = this.contents.parentNode; // scripts
var w = d.offsetWidth;
var h = d.offsetHeight;
if ((rect.x > 0) && (rect.y > 0)) {
return 'topleft';
}
if (((rect.x + rect.width) < w) && ((rect.y + rect.height) < h)) {
return 'bottomright';
}
if ((rect.x > 0) && ((rect.y + rect.height) < h)) {
return 'bottomleft';
}
if (((rect.x + rect.width) < w) && (rect.y > 0)) {
return 'topright';
}
if ((rect.x + rect.width) < w) {
return 'right';
}
if ((rect.y + rect.height) < h) {
return 'down';
}
if (rect.y > 0) {
return 'up';
}
if (rect.x > 0) {
return 'left';
}
return 'none';
}
bounceBack () {
var owner = this;
var p = this.contents; // scriptscontainer
var bc = this.getContent(); // blockcanvas
var valx = bc.left;
var valy = bc.top;
var h = p.offsetHeight;
var w = p.offsetWidth;
var rect = {
x: valx,
y: valy,
width: bc.offsetWidth,
height: bc.offsetHeight
};
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {},
onComplete: function () {
owner.refresh();
}
};
switch (this.getAdjustment(rect)) {
case 'topright':
transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px';
transition.style.top = '0px';
CSSTransition3D(bc, transition);
break;
case 'bottomright':
transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px';
transition.style.top = (this.hasVertical ? h - rect.height : 0) + 'px';
CSSTransition3D(bc, transition);
break;
case 'topleft':
transition.style.top = '0px';
transition.style.left = '0px';
CSSTransition3D(bc, transition);
}
break;
case 'down':
transition.style.top = (h - rect.height) + 'px';
transition.style.left = valx + 'px';
CSSTransition3D(bc, transition);
break;
case 'up':
if (this.hasVertical) {
transition.style.top = '0px';
break;
case 'bottomleft':
transition.style.top = (this.hasVertical ? h - rect.height : 0) + 'px';
transition.style.left = '0px';
CSSTransition3D(bc, transition);
break;
case 'right':
transition.style.top = valy + 'px';
transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px';
CSSTransition3D(bc, transition);
break;
case 'left':
if (this.hasHorizontal) {
transition.style.top = valy + 'px';
transition.style.left = '0px';
CSSTransition3D(bc, transition);
}
break;
case 'down':
transition.style.top = (h - rect.height) + 'px';
transition.style.left = valx + 'px';
CSSTransition3D(bc, transition);
break;
case 'up':
if (this.hasVertical) {
transition.style.top = '0px';
transition.style.left = valx + 'px';
CSSTransition3D(bc, transition);
}
break;
}
break;
}
};
/////////////////////////////////////////////////////////////
// Refreshing
////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
// Refreshing
////////////////////////////////////////////////////////////
Scroll.prototype.refresh = function () {
var p = this.contents; // scriptscontainer
var bc = this.getContent(); // blockcanvas
var w = p.offsetWidth;
var h = p.offsetHeight;
var you;
var needleft = 'hidden';
var needright = 'hidden';
var needup = 'hidden';
var needdown = 'hidden';
var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) {
you = allblocks[i].div;
if (you == null) {
continue;
}
if (!you.owner) {
continue;
}
if (you.style.visibility == 'hidden') {
continue;
}
if (you.left + bc.left < 0) {
needleft = 'visible';
}
if ((you.left + you.offsetWidth + bc.left) > w) {
needright = 'visible';
}
if (you.top + bc.top + 10 < 0) {
needup = 'visible';
}
if ((you.top + you.offsetHeight + bc.top) > h) {
needdown = 'visible';
refresh () {
var p = this.contents; // scriptscontainer
var bc = this.getContent(); // blockcanvas
var w = p.offsetWidth;
var h = p.offsetHeight;
var you;
var needleft = 'hidden';
var needright = 'hidden';
var needup = 'hidden';
var needdown = 'hidden';
var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) {
you = allblocks[i].div;
if (you == null) {
continue;
}
if (!you.owner) {
continue;
}
if (you.style.visibility == 'hidden') {
continue;
}
if (you.left + bc.left < 0) {
needleft = 'visible';
}
if ((you.left + you.offsetWidth + bc.left) > w) {
needright = 'visible';
}
if (you.top + bc.top + 10 < 0) {
needup = 'visible';
}
if ((you.top + you.offsetHeight + bc.top) > h) {
needdown = 'visible';
}
}
this.aleft.style.visibility = needleft;
this.aright.style.visibility = needright;
this.aup.style.visibility = needup;
this.adown.style.visibility = needdown;
}
this.aleft.style.visibility = needleft;
this.aright.style.visibility = needright;
this.aup.style.visibility = needup;
this.adown.style.visibility = needdown;
};
Scroll.prototype.adjustCanvas = function () {
var bc = this.getContent(); // blockcanvas
var p = this.contents; // scriptscontainer
var w = p.offsetWidth;
var h = p.offsetHeight;
var ow = bc.offsetWidth;
var oh = bc.offsetHeight;
var you;
var minx = 99999;
var maxwidth = 0;
var miny = 99999;
var maxheight = 0;
var padding = 0;
var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) {
you = allblocks[i].div;
if (you == null) {
continue;
adjustCanvas () {
var bc = this.getContent(); // blockcanvas
var p = this.contents; // scriptscontainer
var w = p.offsetWidth;
var h = p.offsetHeight;
var ow = bc.offsetWidth;
var oh = bc.offsetHeight;
var you;
var minx = 99999;
var maxwidth = 0;
var miny = 99999;
var maxheight = 0;
var padding = 0;
var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) {
you = allblocks[i].div;
if (you == null) {
continue;
}
if (!you.owner) {
continue;
}
if (you.style.visibility == 'hidden') {
continue;
}
if (you.left < minx) {
minx = you.left;
}
if ((you.left + you.offsetWidth + padding) > maxwidth) {
maxwidth = you.left + you.offsetWidth + padding;
}
if (you.top < miny) {
miny = you.top;
}
if ((you.top + you.offsetHeight + 20) > maxheight) {
maxheight = you.top + you.offsetHeight + 20;
}
}
if (!you.owner) {
continue;
if (minx < 0) {
minx -= padding;
minx += bc.left;
w -= minx;
} else {
minx = 0;
}
if (you.style.visibility == 'hidden') {
continue;
if (miny < 0) {
miny -= 20;
miny += bc.top;
h -= miny;
} else {
miny = 0;
}
if (you.left < minx) {
minx = you.left;
if ((maxwidth - minx) > w) {
w = Math.round(maxwidth - minx);
}
if ((you.left + you.offsetWidth + padding) > maxwidth) {
maxwidth = you.left + you.offsetWidth + padding;
if ((maxheight - miny) > h) {
h = Math.round(maxheight - miny);
}
if (you.top < miny) {
miny = you.top;
if ((ow != w) || (oh != h)) {
setCanvasSize(bc, w, h);
}
if ((you.top + you.offsetHeight + 20) > maxheight) {
maxheight = you.top + you.offsetHeight + 20;
if ((minx < 0) || (miny < 0)) {
this.moveBlocks(-minx, -miny);
Events.move3D(bc, minx, miny);
}
}
if (minx < 0) {
minx -= padding;
minx += bc.left;
w -= minx;
} else {
minx = 0;
}
if (miny < 0) {
miny -= 20;
miny += bc.top;
h -= miny;
} else {
miny = 0;
}
if ((maxwidth - minx) > w) {
w = Math.round(maxwidth - minx);
}
if ((maxheight - miny) > h) {
h = Math.round(maxheight - miny);
}
if ((ow != w) || (oh != h)) {
setCanvasSize(bc, w, h);
}
if ((minx < 0) || (miny < 0)) {
this.moveBlocks(-minx, -miny);
Events.move3D(bc, minx, miny);
}
};
Scroll.prototype.moveBlocks = function (dx, dy) {
var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) {
var b = allblocks[i];
b.moveBlock(b.div.left + dx, b.div.top + dy);
}
};
/////////////////////////////////////////////////////////////
// Scrolling
////////////////////////////////////////////////////////////
Scroll.prototype.scrolldown = function (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var h = p.offsetHeight;
var valy = sc.top + h;
if (valy > 0) {
valy = 0;
}
valy = Math.round(valy);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
top: valy + 'px'
},
onComplete: function () {
owner.refresh();
moveBlocks (dx, dy) {
var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) {
var b = allblocks[i];
b.moveBlock(b.div.left + dx, b.div.top + dy);
}
};
CSSTransition3D(sc, transition);
};
}
Scroll.prototype.scrollup = function (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var h = p.offsetHeight;
var valy = sc.top - h;
if ((valy + sc.offsetHeight) < h) {
valy = h - sc.offsetHeight;
}
valy = Math.round(valy);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
top: valy + 'px'
},
onComplete: function () {
owner.refresh();
/////////////////////////////////////////////////////////////
// Scrolling
////////////////////////////////////////////////////////////
scrolldown (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
};
CSSTransition3D(sc, transition);
};
Scroll.prototype.scrollright = function (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var w = p.offsetWidth;
var valx = sc.left + w;
if (valx > 0) {
valx = 0;
}
valx = Math.round(valx);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
left: valx + 'px'
},
onComplete: function () {
owner.refresh();
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var h = p.offsetHeight;
var valy = sc.top + h;
if (valy > 0) {
valy = 0;
}
};
CSSTransition3D(sc, transition);
};
valy = Math.round(valy);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
top: valy + 'px'
},
onComplete: function () {
owner.refresh();
}
};
CSSTransition3D(sc, transition);
}
Scroll.prototype.scrollleft = function (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var w = p.offsetWidth;
var valx = sc.left - w;
if ((valx + sc.offsetWidth) < w) {
valx = w - sc.offsetWidth;
}
valx = Math.round(valx);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
left: valx + 'px'
},
onComplete: function () {
owner.refresh();
scrollup (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
};
CSSTransition3D(sc, transition);
};
Scroll.prototype.fitToScreen = function () {
var p = this.contents;
var sc = this.getContent();
var valx = sc.left;
var valy = sc.top;
var h = p.offsetHeight;
var w = p.offsetWidth;
var rect = {
x: valx,
y: valy,
width: sc.offsetWidth,
height: sc.offsetHeight
};
switch (this.getAdjustment(rect)) {
case 'topright':
valx = w - rect.width;
valy = 0;
break;
case 'bottomright':
valx = w - rect.width;
valy = h - rect.height;
break;
case 'topleft':
valx = 0; valy = 0;
break;
case 'bottomleft':
valy = h - rect.height;
valx = 0;
break;
case 'right':
valx = w - rect.width;
break;
case 'left':
valx = 0;
break;
case 'down':
valy = h - rect.height;
break;
case 'up':
valy = 0;
break;
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var h = p.offsetHeight;
var valy = sc.top - h;
if ((valy + sc.offsetHeight) < h) {
valy = h - sc.offsetHeight;
}
valy = Math.round(valy);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
top: valy + 'px'
},
onComplete: function () {
owner.refresh();
}
};
CSSTransition3D(sc, transition);
}
Events.move3D(sc, valx, valy);
};
scrollright (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var w = p.offsetWidth;
var valx = sc.left + w;
if (valx > 0) {
valx = 0;
}
valx = Math.round(valx);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
left: valx + 'px'
},
onComplete: function () {
owner.refresh();
}
};
CSSTransition3D(sc, transition);
}
scrollleft (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var w = p.offsetWidth;
var valx = sc.left - w;
if ((valx + sc.offsetWidth) < w) {
valx = w - sc.offsetWidth;
}
valx = Math.round(valx);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
left: valx + 'px'
},
onComplete: function () {
owner.refresh();
}
};
CSSTransition3D(sc, transition);
}
fitToScreen () {
var p = this.contents;
var sc = this.getContent();
var valx = sc.left;
var valy = sc.top;
var h = p.offsetHeight;
var w = p.offsetWidth;
var rect = {
x: valx,
y: valy,
width: sc.offsetWidth,
height: sc.offsetHeight
};
switch (this.getAdjustment(rect)) {
case 'topright':
valx = w - rect.width;
valy = 0;
break;
case 'bottomright':
valx = w - rect.width;
valy = h - rect.height;
break;
case 'topleft':
valx = 0; valy = 0;
break;
case 'bottomleft':
valy = h - rect.height;
valx = 0;
break;
case 'right':
valx = w - rect.width;
break;
case 'left':
valx = 0;
break;
case 'down':
valy = h - rect.height;
break;
case 'up':
valy = 0;
break;
}
Events.move3D(sc, valx, valy);
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,423 +1,431 @@
//////////////////////////////////
// Undo / Redo Functions
//////////////////////////////////
var Undo = function () {};
Undo.buffer = [];
Undo.index = 0;
Undo.aux = '';
Undo.tryCounter;
import ScratchJr from '../ScratchJr';
import Thumbs from './Thumbs';
import Project from './Project';
import Palette from './Palette';
import UI from './UI';
import ScratchAudio from '../../utils/ScratchAudio';
import {newHTML, isTablet, gn} from '../../utils/lib';
Undo.init = function () {
Undo.index = Undo.buffer.length;
Undo.update();
};
let buffer = [];
let index = 0;
let tryCounter;
Undo.setup = function (p) {
var div = newHTML('div', 'controlundo', p);
div.setAttribute('id', 'undocontrols');
var lib = [['undo', Undo.prevStep], ['redo', Undo.nextStep]];
for (var i = 0; i < lib.length; i++) {
Undo.newToggleClicky(div, 'id_', lib[i][0], lib[i][1]);
export default class Undo {
static init () {
index = buffer.length;
Undo.update();
}
Undo.update();
};
Undo.newToggleClicky = function (p, prefix, key, fcn) {
var div = newHTML('div', key + 'button', p);
div.setAttribute('type', 'toggleclicky');
div.setAttribute('id', prefix + key);
if (fcn) {
if (isTablet) {
div.ontouchstart = function (evt) {
fcn(evt);
};
} else {
div.onmousedown = function (evt) {
fcn(evt);
};
static setup (p) {
var div = newHTML('div', 'controlundo', p);
div.setAttribute('id', 'undocontrols');
var lib = [['undo', Undo.prevStep], ['redo', Undo.nextStep]];
for (var i = 0; i < lib.length; i++) {
Undo.newToggleClicky(div, 'id_', lib[i][0], lib[i][1]);
}
Undo.update();
}
return div;
};
Undo.record = function (obj) {
//console.log ("record", Undo.index, JSON.stringify(obj));
if (ScratchJr.getActiveScript()) {
ScratchJr.getActiveScript().owner.removeCaret();
}
if ((Undo.index + 1) <= Undo.buffer.length) {
Undo.buffer.splice(Undo.index + 1, Undo.buffer.length);
}
var data = Project.getUndo();
for (var key in obj) {
data[key] = obj[key];
}
Undo.buffer.push(data);
Undo.index++;
Undo.update();
// Project change state is usually tracked by looking if a particular action would record an undo
// We need slightly more specific behavior for story starters, so storyStarted is unaffected here.
ScratchJr.changed = true;
};
//////////////////////////////////
// Control buttons callbacks
//
////////////////////////////////
Undo.prevStep = function (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
ScratchJr.unfocus();
ScratchJr.time = e.timeStamp;
while (Undo.index >= Undo.buffer.length) {
Undo.index--;
}
Undo.index--;
var snd = (Undo.index < 0) ? 'boing.wav' : 'tap.wav';
ScratchAudio.sndFX(snd);
if (Undo.index < 0) {
Undo.index = 0;
} else {
Undo.smartRecreate('prev', Undo.buffer[Undo.index + 1], Undo.buffer[Undo.index]);
}
};
Undo.nextStep = function (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
ScratchJr.unfocus();
ScratchJr.time = e.timeStamp;
Undo.index++;
var snd = (Undo.index > Undo.buffer.length - 1) ? 'boing.wav' : 'tap.wav';
ScratchAudio.sndFX(snd);
if (Undo.index > Undo.buffer.length - 1) {
Undo.index = Undo.buffer.length - 1;
} else {
Undo.smartRecreate('next', Undo.buffer[Undo.index], Undo.buffer[Undo.index]);
}
};
Undo.smartRecreate = function (cmd, elem, data) {
ScratchJr.stopStrips();
var action = elem.action;
var page = elem.where;
var spr = elem.who;
// console.log (action, page, spr);
switch (action) {
case 'pageorder':
ScratchJr.stage.pages = Undo.getPageOrder(data);
Undo.recreateAllScripts(data);
ScratchJr.stage.setPage(gn(data.currentPage).owner, false);
if (Palette.numcat == 5) {
Palette.selectCategory(5);
}
break;
case 'changepage':
ScratchJr.stage.setPage(gn(data.currentPage).owner, false);
break;
case 'changebkg':
gn(page).owner.redoChangeBkg(data);
break;
case 'scripts':
Undo.redoScripts(data, page, spr);
if (spr && gn(spr)) {
gn(page).owner.setCurrentSprite(gn(spr).owner); // sets the variables
Thumbs.selectThisSprite(gn(spr).owner); // sets the UI
UI.resetSpriteLibrary();
}
break;
case 'deletepage':
case 'addpage':
if (data[page]) {
Undo.copyPage(data, page);
} else {
Undo.removePage(data, page);
}
break;
case 'deletesprite':
case 'copy':
if (data[page][spr]) {
Undo.copySprite(data, page, spr);
} else {
Undo.removeSprite(data, page, spr);
}
break;
case 'deletesound':
var sounds = data[page][spr].sounds.concat();
gn(spr).owner.sounds = sounds;
Undo.redoScripts(data, page, spr);
if (Palette.numcat == 3) {
Palette.selectCategory(3);
}
break;
case 'recordsound':
spr = gn((data[page][spr]).id).owner;
if (elem.sound && (spr.sounds.indexOf(elem.sound) > -1)) {
var indx = spr.sounds.indexOf(elem.sound);
if (indx > -1) {
spr.sounds.splice(indx, 1);
static newToggleClicky (p, prefix, key, fcn) {
var div = newHTML('div', key + 'button', p);
div.setAttribute('type', 'toggleclicky');
div.setAttribute('id', prefix + key);
if (fcn) {
if (isTablet) {
div.ontouchstart = function (evt) {
fcn(evt);
};
} else {
div.onmousedown = function (evt) {
fcn(evt);
};
}
} else {
spr.sounds.push(elem.sound);
}
if (Palette.numcat == 3) {
Palette.selectCategory(3);
}
break;
case 'edittext': // sprite delete or add
case 'modify':
Undo.removeSprite(data, page, spr);
if (data[page][spr]) {
Undo.copySprite(data, page, spr);
}
break;
default:
Project.clear();
Undo.recreate(Undo.buffer[Undo.index]);
break;
return div;
}
Undo.update();
};
Undo.copyPage = function (obj, page) {
var sc = ScratchJr.getSprite() ? gn(ScratchJr.stage.currentPage.currentSpriteName + '_scripts') : undefined;
if (sc) {
sc.owner.deactivate();
static record (obj) {
//console.log ("record", index, JSON.stringify(obj));
if (ScratchJr.getActiveScript()) {
ScratchJr.getActiveScript().owner.removeCaret();
}
if ((index + 1) <= buffer.length) {
buffer.splice(index + 1, buffer.length);
}
var data = Project.getUndo();
for (var key in obj) {
data[key] = obj[key];
}
buffer.push(data);
index++;
Undo.update();
// Project change state is usually tracked by looking if a particular action would record an undo
// We need slightly more specific behavior for story starters, so storyStarted is unaffected here.
ScratchJr.changed = true;
}
Project.recreatePage(page, obj[page], nextStep2);
function nextStep2 () {
ScratchJr.stage.pages = Undo.getPageOrder(obj);
ScratchJr.stage.setPage(gn(obj.currentPage).owner, false);
Undo.recreateAllScripts(obj);
var spritename = obj[obj.currentPage].lastSprite;
if (spritename && gn(spritename)) {
var spr = gn(spritename).owner;
var page = spr.div.parentNode.owner;
page.setCurrentSprite(spr);
Thumbs.selectThisSprite(spr);
//////////////////////////////////
// Control buttons callbacks
//
////////////////////////////////
static prevStep (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
ScratchJr.unfocus();
ScratchJr.time = e.timeStamp;
while (index >= buffer.length) {
index--;
}
index--;
var snd = (index < 0) ? 'boing.wav' : 'tap.wav';
ScratchAudio.sndFX(snd);
if (index < 0) {
index = 0;
} else {
Undo.smartRecreate('prev', buffer[index + 1], buffer[index]);
}
}
static nextStep (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
ScratchJr.unfocus();
ScratchJr.time = e.timeStamp;
index++;
var snd = (index > buffer.length - 1) ? 'boing.wav' : 'tap.wav';
ScratchAudio.sndFX(snd);
if (index > buffer.length - 1) {
index = buffer.length - 1;
} else {
Undo.smartRecreate('next', buffer[index], buffer[index]);
}
}
static smartRecreate (cmd, elem, data) {
ScratchJr.stopStrips();
var action = elem.action;
var page = elem.where;
var spr = elem.who;
// console.log (action, page, spr);
switch (action) {
case 'pageorder':
ScratchJr.stage.pages = Undo.getPageOrder(data);
Undo.recreateAllScripts(data);
ScratchJr.stage.setPage(gn(data.currentPage).owner, false);
if (Palette.numcat == 5) {
Palette.selectCategory(5);
}
break;
case 'changepage':
ScratchJr.stage.setPage(gn(data.currentPage).owner, false);
break;
case 'changebkg':
gn(page).owner.redoChangeBkg(data);
break;
case 'scripts':
Undo.redoScripts(data, page, spr);
if (spr && gn(spr)) {
gn(page).owner.setCurrentSprite(gn(spr).owner); // sets the variables
Thumbs.selectThisSprite(gn(spr).owner); // sets the UI
UI.resetSpriteLibrary();
}
break;
case 'deletepage':
case 'addpage':
if (data[page]) {
Undo.copyPage(data, page);
} else {
Undo.removePage(data, page);
}
break;
case 'deletesprite':
case 'copy':
if (data[page][spr]) {
Undo.copySprite(data, page, spr);
} else {
Undo.removeSprite(data, page, spr);
}
break;
case 'deletesound':
var sounds = data[page][spr].sounds.concat();
gn(spr).owner.sounds = sounds;
Undo.redoScripts(data, page, spr);
if (Palette.numcat == 3) {
Palette.selectCategory(3);
}
break;
case 'recordsound':
spr = gn((data[page][spr]).id).owner;
if (elem.sound && (spr.sounds.indexOf(elem.sound) > -1)) {
var indx = spr.sounds.indexOf(elem.sound);
if (indx > -1) {
spr.sounds.splice(indx, 1);
}
} else {
spr.sounds.push(elem.sound);
}
if (Palette.numcat == 3) {
Palette.selectCategory(3);
}
break;
case 'edittext': // sprite delete or add
case 'modify':
Undo.removeSprite(data, page, spr);
if (data[page][spr]) {
Undo.copySprite(data, page, spr);
}
break;
default:
Project.clear();
Undo.recreate(buffer[index]);
break;
}
Undo.update();
}
static copyPage (obj, page) {
var sc = ScratchJr.getSprite() ? gn(ScratchJr.stage.currentPage.currentSpriteName + '_scripts') : undefined;
if (sc) {
sc.owner.deactivate();
}
Project.recreatePage(page, obj[page], nextStep2);
function nextStep2 () {
ScratchJr.stage.pages = Undo.getPageOrder(obj);
ScratchJr.stage.setPage(gn(obj.currentPage).owner, false);
Undo.recreateAllScripts(obj);
var spritename = obj[obj.currentPage].lastSprite;
if (spritename && gn(spritename)) {
var spr = gn(spritename).owner;
var page = spr.div.parentNode.owner;
page.setCurrentSprite(spr);
Thumbs.selectThisSprite(spr);
if (Palette.numcat == 5) {
Palette.selectCategory(5);
}
}
}
}
};
Undo.getPageOrder = function (data) {
var pages = data.pages;
var res = [];
for (var i = 0; i < pages.length; i++) {
res.push(gn(pages[i]).owner);
static getPageOrder (data) {
var pages = data.pages;
var res = [];
for (var i = 0; i < pages.length; i++) {
res.push(gn(pages[i]).owner);
}
return res;
}
return res;
};
Undo.recreateAllScripts = function (data) {
for (var n = 0; n < data.pages.length; n++) {
var page = data[data.pages[n]];
var sprnames = page.sprites;
for (var i = 0; i < sprnames.length; i++) {
var spr = page[sprnames[i]];
if (!spr) {
continue;
static recreateAllScripts (data) {
for (var n = 0; n < data.pages.length; n++) {
var page = data[data.pages[n]];
var sprnames = page.sprites;
for (var i = 0; i < sprnames.length; i++) {
var spr = page[sprnames[i]];
if (!spr) {
continue;
}
if (spr.type != 'sprite') {
continue;
}
var sc = gn(spr.id + '_scripts');
if (!sc) {
continue;
}
Undo.redoScripts(data, data.pages[n], sprnames[i]);
}
if (spr.type != 'sprite') {
continue;
}
var sc = gn(spr.id + '_scripts');
if (!sc) {
continue;
}
Undo.redoScripts(data, data.pages[n], sprnames[i]);
}
}
};
Undo.removePage = function (data, str) {
if (!gn(str)) {
return;
}
var page = gn(str).owner;
if (!page) {
return;
}
ScratchJr.stage.removePageBlocks(str);
ScratchJr.stage.removePage(page);
ScratchJr.stage.pages = Undo.getPageOrder(data);
if (ScratchJr.stage.pages.length == 0) {
Undo.copyPage(data, data.currentPage);
} else {
ScratchJr.stage.setViewPage(gn(data.currentPage).owner);
Thumbs.updateSprites();
Thumbs.updatePages();
}
};
Undo.redoScripts = function (data, page, spr) {
var div = gn(spr + '_scripts');
while (div.childElementCount > 0) {
div.removeChild(div.childNodes[0]);
}
var sc = div.owner;
var list = data[page][spr].scripts;
for (var j = 0; j < list.length; j++) {
sc.recreateStrip(list[j]);
}
};
Undo.copySprite = function (data, page, spr) {
var obj = data[page][spr];
var fcn = function (spr) {
if (spr.type == 'sprite') {
if (page == ScratchJr.stage.currentPage.id) {
spr.div.style.visibility = 'visible';
}
Undo.setSprite(page, data);
static removePage (data, str) {
if (!gn(str)) {
return;
}
var page = gn(str).owner;
if (!page) {
return;
}
ScratchJr.stage.removePageBlocks(str);
ScratchJr.stage.removePage(page);
ScratchJr.stage.pages = Undo.getPageOrder(data);
if (ScratchJr.stage.pages.length == 0) {
Undo.copyPage(data, data.currentPage);
} else {
var delta = spr.fontsize * 1.35;
if (spr.homey == spr.page.textstartat) {
spr.page.textstartat += delta;
}
ScratchJr.stage.setViewPage(gn(data.currentPage).owner);
Thumbs.updateSprites();
Thumbs.updatePages();
}
};
Project.recreateObject(gn(page).owner, spr, obj, fcn, (data[page].lastSprite == spr));
};
}
Undo.setSprite = function (page, data) {
Thumbs.updatePages();
if (page != ScratchJr.stage.currentPage.id) {
return;
static redoScripts (data, page, spr) {
var div = gn(spr + '_scripts');
while (div.childElementCount > 0) {
div.removeChild(div.childNodes[0]);
}
var sc = div.owner;
var list = data[page][spr].scripts;
for (var j = 0; j < list.length; j++) {
sc.recreateStrip(list[j]);
}
}
var pageobj = gn(page).owner;
var lastspritename = data[page].lastSprite;
var lastsprite = lastspritename ? gn(lastspritename) : undefined;
if (!lastsprite) {
pageobj.setCurrentSprite(undefined);
} else {
var cs = lastsprite.owner;
pageobj.setCurrentSprite(cs);
UI.needsScroll();
Thumbs.updateSprites();
}
};
Undo.removeSprite = function (data, page, spr) {
if (!gn(spr)) {
return;
static copySprite (data, page, spr) {
var obj = data[page][spr];
var fcn = function (spr) {
if (spr.type == 'sprite') {
if (page == ScratchJr.stage.currentPage.id) {
spr.div.style.visibility = 'visible';
}
Undo.setSprite(page, data);
} else {
var delta = spr.fontsize * 1.35;
if (spr.homey == spr.page.textstartat) {
spr.page.textstartat += delta;
}
Thumbs.updatePages();
}
};
Project.recreateObject(gn(page).owner, spr, obj, fcn, (data[page].lastSprite == spr));
}
var sprite = gn(spr).owner;
var th = sprite.thumbnail;
ScratchJr.runtime.stopThreadSprite(sprite);
var pageobj = gn(page).owner;
var list = JSON.parse(pageobj.sprites);
var n = list.indexOf(spr);
list.splice(n, 1);
pageobj.sprites = JSON.stringify(list);
gn(spr).parentNode.removeChild(gn(spr));
if (!gn(spr + '_scripts')) {
static setSprite (page, data) {
Thumbs.updatePages();
return;
}
var sc = gn(spr + '_scripts');
if (sc) {
sc.parentNode.removeChild(sc);
}
if (th && th.parentNode) {
th.parentNode.removeChild(th);
}
Undo.setSprite(page, data);
};
Undo.recreate = function (data) {
Project.mediaCount = 0;
ScratchJr.stage.pages = [];
var pages = data.pages;
if (data.projectsounds) {
ScratchAudio.projectsounds = data.projectsounds;
}
for (var i = 0; i < pages.length; i++) {
Project.recreatePage(pages[i], data[pages[i]]);
}
Undo.loadPage(data.currentPage);
};
Undo.loadPage = function (pageid) {
var pages = ScratchJr.stage.getPagesID();
if (pages.indexOf(pageid) < 0) {
ScratchJr.stage.currentPage = ScratchJr.stage.pages[0];
} else {
ScratchJr.stage.currentPage = ScratchJr.stage.getPage(pageid);
}
ScratchJr.stage.currentPage.div.style.visibility = 'visible';
ScratchJr.stage.currentPage.setPageSprites('visible');
Undo.tryCounter = 100;
if (Project.mediaCount > 0) {
setTimeout(function () {
Undo.updateImages();
}, 20);
} else {
Undo.doneLoading();
}
};
Undo.updateImages = function () {
Undo.tryCounter--;
var done = (Project.mediaCount < 1) || (Undo.tryCounter < 1);
if (done) {
Undo.doneLoading();
} else {
setTimeout(function () {
Undo.updateImages();
}, 20);
}
};
Undo.flashIcon = function (div, press) {
div.setAttribute('class', press);
setTimeout(function () {
Undo.update();
}, 1000);
};
Undo.doneLoading = function () {
Thumbs.updateSprites();
Thumbs.updatePages();
};
Undo.update = function () {
if (gn('id_undo')) {
if (Undo.buffer.length == 1) {
Undo.tunOffButton(gn('id_undo'));
if (page != ScratchJr.stage.currentPage.id) {
return;
}
var pageobj = gn(page).owner;
var lastspritename = data[page].lastSprite;
var lastsprite = lastspritename ? gn(lastspritename) : undefined;
if (!lastsprite) {
pageobj.setCurrentSprite(undefined);
} else {
if (Undo.index < 1) {
var cs = lastsprite.owner;
pageobj.setCurrentSprite(cs);
UI.needsScroll();
Thumbs.updateSprites();
}
}
static removeSprite (data, page, spr) {
if (!gn(spr)) {
return;
}
var sprite = gn(spr).owner;
var th = sprite.thumbnail;
ScratchJr.runtime.stopThreadSprite(sprite);
var pageobj = gn(page).owner;
var list = JSON.parse(pageobj.sprites);
var n = list.indexOf(spr);
list.splice(n, 1);
pageobj.sprites = JSON.stringify(list);
gn(spr).parentNode.removeChild(gn(spr));
if (!gn(spr + '_scripts')) {
Thumbs.updatePages();
return;
}
var sc = gn(spr + '_scripts');
if (sc) {
sc.parentNode.removeChild(sc);
}
if (th && th.parentNode) {
th.parentNode.removeChild(th);
}
Undo.setSprite(page, data);
}
static recreate (data) {
Project.mediaCount = 0;
ScratchJr.stage.pages = [];
var pages = data.pages;
if (data.projectsounds) {
ScratchAudio.projectsounds = data.projectsounds;
}
for (var i = 0; i < pages.length; i++) {
Project.recreatePage(pages[i], data[pages[i]]);
}
Undo.loadPage(data.currentPage);
}
static loadPage (pageid) {
var pages = ScratchJr.stage.getPagesID();
if (pages.indexOf(pageid) < 0) {
ScratchJr.stage.currentPage = ScratchJr.stage.pages[0];
} else {
ScratchJr.stage.currentPage = ScratchJr.stage.getPage(pageid);
}
ScratchJr.stage.currentPage.div.style.visibility = 'visible';
ScratchJr.stage.currentPage.setPageSprites('visible');
tryCounter = 100;
if (Project.mediaCount > 0) {
setTimeout(function () {
Undo.updateImages();
}, 20);
} else {
Undo.doneLoading();
}
}
static updateImages () {
tryCounter--;
var done = (Project.mediaCount < 1) || (tryCounter < 1);
if (done) {
Undo.doneLoading();
} else {
setTimeout(function () {
Undo.updateImages();
}, 20);
}
}
static flashIcon (div, press) {
div.setAttribute('class', press);
setTimeout(function () {
Undo.update();
}, 1000);
}
static doneLoading () {
Thumbs.updateSprites();
Thumbs.updatePages();
}
static update () {
if (gn('id_undo')) {
if (buffer.length == 1) {
Undo.tunOffButton(gn('id_undo'));
} else {
Undo.tunOnButton(gn('id_undo'));
if (index < 1) {
Undo.tunOffButton(gn('id_undo'));
} else {
Undo.tunOnButton(gn('id_undo'));
}
}
if (index >= buffer.length - 1) {
Undo.tunOffButton(gn('id_redo'));
} else {
Undo.tunOnButton(gn('id_redo'));
}
}
if (Undo.index >= Undo.buffer.length - 1) {
Undo.tunOffButton(gn('id_redo'));
} else {
Undo.tunOnButton(gn('id_redo'));
}
}
};
Undo.tunOnButton = function (kid) {
var kclass = kid.getAttribute('class').split(' ')[0];
kid.setAttribute('class', kclass + ' enable');
};
static tunOnButton (kid) {
var kclass = kid.getAttribute('class').split(' ')[0];
kid.setAttribute('class', kclass + ' enable');
}
Undo.tunOffButton = function (kid) {
var kclass = kid.getAttribute('class').split(' ')[0];
kid.setAttribute('class', kclass + ' disable');
};
static tunOffButton (kid) {
var kclass = kid.getAttribute('class').split(' ')[0];
kid.setAttribute('class', kclass + ' disable');
}
}

113
src/entry/app.js Normal file
View file

@ -0,0 +1,113 @@
import {preprocessAndLoadCss} from '../utils/lib';
import Localization from '../utils/Localization';
import iOS from '../iPad/iOS';
import IO from '../iPad/IO';
import MediaLib from '../iPad/MediaLib';
import {indexMain} from './index';
import {homeMain} from './home';
import {editorMain} from './editor';
import {gettingStartedMain} from './gettingstarted';
import {inappInterfaceGuide, inappAbout, inappBlocksGuide, inappPaintEditorGuide} from './inapp';
function loadSettings (settingsRoot, whenDone) {
IO.requestFromServer(settingsRoot + 'settings.json', (result) => {
window.Settings = JSON.parse(result);
whenDone();
});
}
// App-wide entry-point
window.onload = () => {
// Function to be called after settings, locale strings, and Media Lib
// are asynchronously loaded. This is overwritten per HTML page below.
let entryFunction = () => {};
// Root directory for includes. Needed in case we are in the inapp-help
// directory (and root becomes '../')
let root = './';
// scratchJrPage is defined in the HTML pages
let page = window.scratchJrPage;
// Load CSS and set root/entryFunction for all pages
switch (page) {
case 'index':
// Index page (splash screen)
preprocessAndLoadCss('css', 'css/font.css');
preprocessAndLoadCss('css', 'css/base.css');
preprocessAndLoadCss('css', 'css/start.css');
preprocessAndLoadCss('css', 'css/thumbs.css');
/* For parental gate. These CSS properties should be refactored */
preprocessAndLoadCss('css', 'css/editor.css');
entryFunction = () => iOS.waitForInterface(indexMain);
break;
case 'home':
// Lobby pages
preprocessAndLoadCss('css', 'css/font.css');
preprocessAndLoadCss('css', 'css/base.css');
preprocessAndLoadCss('css', 'css/lobby.css');
preprocessAndLoadCss('css', 'css/thumbs.css');
entryFunction = () => iOS.waitForInterface(homeMain);
break;
case 'editor':
// Editor pages
preprocessAndLoadCss('css', 'css/font.css');
preprocessAndLoadCss('css', 'css/base.css');
preprocessAndLoadCss('css', 'css/editor.css');
preprocessAndLoadCss('css', 'css/editorleftpanel.css');
preprocessAndLoadCss('css', 'css/editorstage.css');
preprocessAndLoadCss('css', 'css/editormodal.css');
preprocessAndLoadCss('css', 'css/librarymodal.css');
preprocessAndLoadCss('css', 'css/paintlook.css');
entryFunction = () => iOS.waitForInterface(editorMain);
break;
case 'gettingStarted':
// Getting started video page
preprocessAndLoadCss('css', 'css/font.css');
preprocessAndLoadCss('css', 'css/base.css');
preprocessAndLoadCss('css', 'css/gs.css');
entryFunction = () => iOS.waitForInterface(gettingStartedMain);
break;
case 'inappAbout':
// About ScratchJr in-app help frame
preprocessAndLoadCss('style', 'style/about.css');
entryFunction = () => inappAbout();
root = '../';
break;
case 'inappInterfaceGuide':
// Interface guide in-app help frame
preprocessAndLoadCss('style', 'style/style.css');
preprocessAndLoadCss('style', 'style/interface.css');
entryFunction = () => inappInterfaceGuide();
root = '../';
break;
case 'inappPaintEditorGuide':
// Paint editor guide in-app help frame
preprocessAndLoadCss('style', 'style/style.css');
preprocessAndLoadCss('style', 'style/paint.css');
entryFunction = () => inappPaintEditorGuide();
root = '../';
break;
case 'inappBlocksGuide':
// Blocks guide in-app help frame
preprocessAndLoadCss('style', 'style/style.css');
preprocessAndLoadCss('style', 'style/blocks.css');
entryFunction = () => inappBlocksGuide();
root = '../';
break;
}
// Start up sequence
// Load settings from JSON
loadSettings(root, () => {
// Load locale strings from JSON
Localization.includeLocales(root, () => {
// Load Media Lib from JSON
MediaLib.loadMediaLib(root, () => {
entryFunction();
});
});
});
};

19
src/entry/editor.js Normal file
View file

@ -0,0 +1,19 @@
import ScratchJr from '../editor/ScratchJr';
import iOS from '../iPad/iOS';
import Camera from '../painteditor/Camera';
import Record from '../editor/ui/Record';
export function editorMain () {
iOS.getsettings(doNext);
function doNext (str) {
var list = str.split(',');
iOS.path = list[1] == '0' ? list[0] + '/' : undefined;
if (list.length > 2) {
Record.available = list[2] == 'YES' ? true : false;
}
if (list.length > 3) {
Camera.available = list[3] == 'YES' ? true : false;
}
ScratchJr.appinit(window.Settings.scratchJrVersion);
}
}

View file

@ -0,0 +1,31 @@
import {gn, isiOS, getUrlVars} from '../utils/lib';
let place;
export function gettingStartedMain () {
gn('closeHelp').onclick = gettingStartedCloseMe;
gn('closeHelp').ontouchstart = gettingStartedCloseMe;
var videoObj = gn('myVideo');
if (isiOS) {
// On iOS we can load from server
videoObj.src = 'assets/lobby/intro.mp4';
} else {
// On Android we need to copy to a temporary directory first:
setTimeout(function () {
videoObj.type = 'video/mp4';
videoObj.src = AndroidInterface.scratchjr_getgettingstartedvideopath();
}, 1000);
}
videoObj.poster = 'assets/lobby/poster.png';
var urlvars = getUrlVars();
place = urlvars['place'];
document.ontouchmove = function (e){
e.preventDefault();
};
}
function gettingStartedCloseMe () {
window.location.href = 'home.html?place=' + place;
}

26
src/entry/home.js Normal file
View file

@ -0,0 +1,26 @@
import {gn} from '../utils/lib';
import Localization from '../utils/Localization';
import iOS from '../iPad/iOS';
import Lobby from '../lobby/Lobby';
export function homeMain () {
gn('logotab').ontouchend = homeGoBack;
homeStrings();
iOS.getsettings(doNext);
function doNext (str) {
var list = str.split(',');
iOS.path = list[1] == '0' ? list[0] + '/' : undefined;
Lobby.appinit(window.Settings.scratchJrVersion);
}
}
function homeGoBack () {
window.location.href = 'index.html?back=yes';
}
function homeStrings () {
gn('abouttab-text').textContent = Localization.localize('ABOUT_SCRATCHJR');
gn('interfacetab-text').textContent = Localization.localize('INTERFACE_GUIDE');
gn('painttab-text').textContent = Localization.localize('PAINT_EDITOR_GUIDE');
gn('blockstab-text').textContent = Localization.localize('BLOCKS_GUIDE');
}

202
src/entry/inapp.js Normal file
View file

@ -0,0 +1,202 @@
import {gn} from '../utils/lib';
import Localization from '../utils/Localization';
export function inappAbout () {
gn('aboutScratchjrTitle').textContent = Localization.localize('ABOUT_SCRATCHJR');
gn('aboutWhatIs').textContent = Localization.localize('ABOUT_WHAT_IS');
gn('aboutDescription').innerHTML = Localization.localize('ABOUT_DESCRIPTION') + '<br/><br/>' +
Localization.localize('ABOUT_INSPIRED_BY');
gn('aboutWhyCreate').textContent = Localization.localize('ABOUT_WHY_CREATE');
gn('aboutWhyCreateDescription').innerHTML = Localization.localize('ABOUT_WHY_CREATE_DESCRIPTION');
gn('aboutWhoCreated').textContent = Localization.localize('ABOUT_WHO_CREATED');
gn('aboutWhoCreatedDescription').innerHTML = (
Localization.localize('ABOUT_WHO_CREATED_DESCRIPTION'));
gn('aboutWhoSupported').textContent = Localization.localize('ABOUT_WHO_SUPPORTED');
gn('aboutWhoSupportedDescription').innerHTML = (
Localization.localize('ABOUT_WHO_SUPPORTED_DESCRIPTION')
);
// PBS-only
if (window.Settings.edition == 'PBS') {
gn('aboutWhatIsPbs').innerHTML = Localization.localize('ABOUT_WHAT_IS_PBS');
gn('aboutWhatIsPbsDescription').innerHTML = Localization.localize('ABOUT_WHAT_IS_PBS_DESCRIPTION');
gn('aboutPbsShows').innerHTML = Localization.localize('ABOUT_PBS_SHOWS');
gn('aboutPbsShowsDescription').innerHTML = Localization.localize('ABOUT_PBS_SHOWS_DESCRIPTION');
}
}
export function inappInterfaceGuide () {
var interfaceKeyHeaderNode = gn('interface-key-header');
var interfaceKeyDescriptionNode = gn('interface-key-description');
interfaceKeyHeaderNode.textContent = Localization.localize('INTERFACE_GUIDE_SAVE', {N: 1});
interfaceKeyDescriptionNode.textContent = Localization.localize('INTERFACE_GUIDE_SAVE_DESCRIPTION');
var interfaceKeys = [
'SAVE',
'STAGE',
'PRESENTATION_MODE',
'GRID',
'CHANGE_BG',
'ADD_TEXT',
'RESET_CHAR',
'GREEN_FLAG',
'PAGES',
'PROJECT_INFO',
'UNDO_REDO',
'PROGRAMMING_SCRIPT',
'PROGRAMMING_AREA',
'BLOCKS_PALETTE',
'BLOCKS_CATEGORIES',
'CHARACTERS'
];
var interfaceDescriptions = [];
for (var i = 0; i < interfaceKeys.length; i++) {
var key = interfaceKeys[i];
interfaceDescriptions.push([
Localization.localize('INTERFACE_GUIDE_' + key, {N: i+1}),
Localization.localize('INTERFACE_GUIDE_' + key + '_DESCRIPTION')
]);
}
var currentButton = document.getElementById('interface-button-save');
var switchHelp = function (e) {
var target = e.target;
if (target.className == 'interface-button-text') {
var descriptionId = parseInt(target.innerText - 1);
interfaceKeyHeaderNode.textContent = interfaceDescriptions[descriptionId][0];
interfaceKeyDescriptionNode.textContent = interfaceDescriptions[descriptionId][1];
currentButton.className = 'interface-button';
currentButton = target.parentNode;
currentButton.className = currentButton.className + ' interface-button-selected';
window.parent.ScratchAudio.sndFXWithVolume('keydown.wav', 0.3);
}
};
document.addEventListener('touchstart', switchHelp, false);
}
export function inappPaintEditorGuide () {
var paintKeyHeaderNode = gn('paint-key-header');
var paintKeyDescriptionNode = gn('paint-key-description');
paintKeyHeaderNode.textContent = Localization.localize('PAINT_GUIDE_UNDO', {N:1});
paintKeyDescriptionNode.textContent = Localization.localize('PAINT_GUIDE_UNDO_DESCRIPTION');
var paintKeys = [
'UNDO',
'REDO',
'SHAPE',
'CHARACTER_NAME',
'CUT',
'DUPLICATE',
'ROTATE',
'DRAG',
'SAVE',
'FILL',
'CAMERA',
'COLOR',
'LINE_WIDTH'
];
var paintDescriptions = [];
for (var i = 0; i < paintKeys.length; i++) {
var key = paintKeys[i];
paintDescriptions.push([
Localization.localize('PAINT_GUIDE_' + key, {N: i+1}),
Localization.localize('PAINT_GUIDE_' + key + '_DESCRIPTION')
]);
}
var currentButton = document.getElementById('paint-button-undo');
var switchHelp = function (e) {
var target = e.target;
if (target.className == 'paint-button-text') {
var descriptionId = parseInt(target.innerText - 1);
paintKeyHeaderNode.textContent = paintDescriptions[descriptionId][0];
paintKeyDescriptionNode.textContent = paintDescriptions[descriptionId][1];
currentButton.className = 'paint-button';
currentButton = target.parentNode;
currentButton.className = currentButton.className + ' paint-button-selected';
window.parent.ScratchAudio.sndFXWithVolume('keydown.wav', 0.3);
}
};
document.addEventListener('touchstart', switchHelp, false);
}
export function inappBlocksGuide () {
// Localized category names
gn('yellow-block-category-header').textContent = Localization.localize('BLOCKS_TRIGGERING_BLOCKS');
gn('blue-block-category-header').textContent = Localization.localize('BLOCKS_MOTION_BLOCKS');
gn('purple-block-category-header').textContent = Localization.localize('BLOCKS_LOOKS_BLOCKS');
gn('green-block-category-header').textContent = Localization.localize('BLOCKS_SOUND_BLOCKS');
gn('orange-block-category-header').textContent = Localization.localize('BLOCKS_CONTROL_BLOCKS');
gn('red-block-category-header').textContent = Localization.localize('BLOCKS_END_BLOCKS');
var blockDescriptionKeys = [
'BLOCKS_GREEN_FLAG',
'BLOCKS_GREEN_FLAG_DESCRIPTION',
'BLOCKS_ON_TAP',
'BLOCKS_ON_TAP_DESCRIPTION',
'BLOCKS_ON_TOUCH',
'BLOCKS_ON_TOUCH_DESCRIPTION',
'BLOCKS_ON_MESSAGE',
'BLOCKS_ON_MESSAGE_DESCRIPTION',
'BLOCKS_SEND_MESSAGE',
'BLOCKS_SEND_MESSAGE_DESCRIPTION',
'BLOCKS_MOVE_RIGHT',
'BLOCKS_MOVE_RIGHT_DESCRIPTION',
'BLOCKS_MOVE_LEFT',
'BLOCKS_MOVE_LEFT_DESCRIPTION',
'BLOCKS_MOVE_UP',
'BLOCKS_MOVE_UP_DESCRIPTION',
'BLOCKS_MOVE_DOWN',
'BLOCKS_MOVE_DOWN_DESCRIPTION',
'BLOCKS_TURN_RIGHT',
'BLOCKS_TURN_RIGHT_DESCRIPTION',
'BLOCKS_TURN_LEFT',
'BLOCKS_TURN_LEFT_DESCRIPTION',
'BLOCKS_HOP',
'BLOCKS_HOP_DESCRIPTION',
'BLOCKS_GO_HOME',
'BLOCKS_GO_HOME_DESCRIPTION',
'BLOCKS_SAY',
'BLOCKS_SAY_DESCRIPTION',
'BLOCKS_GROW',
'BLOCKS_GROW_DESCRIPTION',
'BLOCKS_SHRINK',
'BLOCKS_SHRINK_DESCRIPTION',
'BLOCKS_RESET_SIZE',
'BLOCKS_RESET_SIZE_DESCRIPTION',
'BLOCKS_HIDE',
'BLOCKS_HIDE_DESCRIPTION',
'BLOCKS_SHOW',
'BLOCKS_SHOW_DESCRIPTION',
'BLOCKS_POP',
'BLOCKS_POP_DESCRIPTION',
'BLOCKS_PLAY_RECORDED',
'BLOCKS_PLAY_RECORDED_DESCRIPTION',
'BLOCKS_WAIT',
'BLOCKS_WAIT_DESCRIPTION',
'BLOCKS_STOP',
'BLOCKS_STOP_DESCRIPTION',
'BLOCKS_SET_SPEED',
'BLOCKS_SET_SPEED_DESCRIPTION',
'BLOCKS_REPEAT',
'BLOCKS_REPEAT_DESCRIPTION',
'BLOCKS_END',
'BLOCKS_END_DESCRIPTION',
'BLOCKS_REPEAT_FOREVER',
'BLOCKS_REPEAT_FOREVER_DESCRIPTION',
'BLOCKS_GO_TO_PAGE',
'BLOCKS_GO_TO_PAGE_DESCRIPTION'
];
for (let key of blockDescriptionKeys) {
gn(key).textContent = Localization.localize(key);
}
}

123
src/entry/index.js Normal file
View file

@ -0,0 +1,123 @@
import ScratchAudio from '../utils/ScratchAudio';
import {gn, getUrlVars, isAndroid, isiOS} from '../utils/lib';
import iOS from '../iPad/iOS';
import UI from '../editor/ui/UI';
import Localization from '../utils/Localization';
export function indexMain () {
gn('gettings').ontouchend = indexGettingstarted;
gn('startcode').ontouchend = indexGohome;
ScratchAudio.init();
var urlvars = getUrlVars();
if (urlvars.back) {
indexLoadOptions();
} else {
indexFirstTime();
}
if (window.Settings.edition == 'PBS') {
gn('topbar-moreapps').textContent = Localization.localize('PBS_MORE_APPS');
gn('startButton').textContent = Localization.localize('PBS_START');
gn('gettings').textContent = Localization.localize('PBS_HOW_TO');
gn('startButton').ontouchend = indexGohome;
gn('pbschars').ontouchend = indexGohome;
gn('topbar-moreapps').ontouchstart = indexMoreApps;
gn('topbar-info').ontouchstart = indexInfo;
}
setTimeout(function () {
gn('rays').className = 'rays spinme';
}, 250);
}
function indexFirstTime () {
gn('authors').className = 'credits show';
gn('authorsText').className = 'creditsText show';
if (window.Settings.edition == 'PBS') {
gn('pbschars').className = 'characters hide';
gn('startcode').className = 'catlogo show';
gn('topbar').className = 'topbar hide';
gn('startButton').className = 'startButton hide';
} else {
gn('purpleguy').className = 'purple show';
gn('blueguy').className = 'blue show';
gn('redguy').className = 'red show';
}
iOS.askpermission(); // ask for sound recording
setTimeout(function () {
iOS.hidesplash(doit);
}, 500);
function doit () {
ScratchAudio.sndFX('tap.wav');
window.ontouchend = function () {
indexLoadOptions();
};
}
setTimeout(function () {
indexLoadOptions();
}, 2000);
}
function indexLoadOptions () {
gn('authors').className = 'credits hide';
gn('authorsText').className = 'creditsText hide';
if (window.Settings.edition == 'PBS') {
gn('pbschars').className = 'characters show';
gn('topbar').className = 'topbar show';
gn('startButton').className = 'startButton show';
} else {
gn('purpleguy').className = 'purple hide';
gn('blueguy').className = 'blue hide';
gn('redguy').className = 'red hide';
}
gn('gettings').className = 'gettings show';
gn('startcode').className = 'startcode show';
document.ontouchmove = function (e) {
e.preventDefault();
};
if (isAndroid) {
AndroidInterface.notifySplashDone();
}
}
function indexGohome () {
// On iOS, sounds are loaded async, but the code as written expects to play tap.wav when we enter home.html
// (but since it isn't loaded yet, no sound is played).
// On Android, sync sounds means both calls to tap.wav result in a sound play.
// XXX: we should re-write the lobby loading to wait for the sounds to load, and not play a sound here.
if (isiOS) {
ScratchAudio.sndFX('tap.wav');
}
iOS.setfile('homescroll.sjr', 0, function () {
doNext();
});
function doNext () {
window.location.href = 'home.html';
}
}
function indexGettingstarted () {
ScratchAudio.sndFX('tap.wav');
window.location.href = 'gettingstarted.html?place=home';
}
// For PBS KIDS edition only
function indexInfo () {
ScratchAudio.sndFX('tap.wav');
window.location.href = 'home.html?place=book';
}
function indexMoreApps () {
ScratchAudio.sndFX('tap.wav');
UI.parentalGate(null, function () {
if (isiOS) {
window.location.href = 'https://itunes.apple.com/us/developer/pbs-kids/id324323339?mt=8';
} else {
window.location.href = 'http://to.pbs.org/ScJr_GPlay';
}
});
}

View file

@ -1,66 +0,0 @@
The MIT License (MIT)
Copyright (c) 2013 Andy Earnshaw
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
------------------------------------------------------------------------------
Contents of the `locale-data` directory are a modified form of the Unicode CLDR
data found at http://www.unicode.org/cldr/data/. It comes with the following
license.
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1991-2013 Unicode, Inc. All rights reserved. Distributed under
the Terms of Use in http://www.unicode.org/copyright.html.
Permission is hereby granted, free of charge, to any person obtaining a copy of
the Unicode data files and any associated documentation (the "Data Files") or
Unicode software and any associated documentation (the "Software") to deal in
the Data Files or Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, and/or sell copies
of the Data Files or Software, and to permit persons to whom the Data Files or
Software are furnished to do so, provided that (a) the above copyright
notice(s) and this permission notice appear with all copies of the Data Files
or Software, (b) both the above copyright notice(s) and this permission notice
appear in associated documentation, and (c) there is clear notice in each
modified Data File or in the Software as well as in the documentation
associated with the Data File(s) or Software that the data or software has been
modified.
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD
PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA FILES OR
SOFTWARE.
Except as contained in this notice, the name of a copyright holder shall not be
used in advertising or otherwise to promote the sale, use or other dealings in
these Data Files or Software without prior written authorization of the
copyright holder.
Unicode and the Unicode logo are trademarks of Unicode, Inc. in the United
States and other countries. All third party trademarks referenced herein are
the property of their respective owners.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show more