diff --git a/.github/workflows/sync_crowdin.yml b/.github/workflows/sync_crowdin.yml new file mode 100644 index 00000000000..842815cc4b6 --- /dev/null +++ b/.github/workflows/sync_crowdin.yml @@ -0,0 +1,58 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ** Synchronize Crowdin translation ** +# +# Crowdin is a platform to manage the translation process in the Catroweb project: +# +# 1. We upload our english (base) translation files +# 2. Users worldwide translate our provided strings +# 3. We download the translations (In case translations are missing english is the fallback) +# +# This GitHub Action uses the official action from Crowdin to automate step 1 and 2. +# A pull request is created/updated automatically containing all new translations. +# +# - Secrets required! +# +name: Synchronize Crowdin + +# +# New base strings could be uploaded on the merge of a new feature. +# However, the translation download process is independent from a pull request. +# Hence, keeping a consistent schedule once a day is more than enough. +# +# In case, an additional run is required, a manual dispatch trigger is also enabled. +# +on: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + +jobs: + + # + # - Two-way synchronization: + # -- In case of new strings in the repo, they are uploaded to Crowdin + # -- In case of new translation, a pull request containing all changes will be created or updated + # + # - The crowdin configuration is in `crowdin.yml`. However, without credentials! + # + # - The credentials are provided as secrets to the action as environment variables. + # In case they must be updated, talk to a product owner. + # + synchronize-with-crowdin: + # Only should run on the main repo. (Running without the secrets would result in a fail anyway!) + if: github.repository == 'Catrobat/Catroid' + + name: Synchronize Crowdin Translations + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: crowdin/github-action@1.0.10 + with: + upload_translations: true + download_translations: true + config: 'crowdin.yml' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} diff --git a/Jenkinsfile b/Jenkinsfile index 9d38455b645..79616a4b1dd 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -45,7 +45,8 @@ def webTestUrlParameter() { def allFlavoursParameters() { return env.BUILD_ALL_FLAVOURS?.toBoolean() ? 'assembleCreateAtSchoolDebug ' + - 'assembleLunaAndCatDebug assemblePhiroDebug assembleEmbroideryDesignerDebug' : '' + 'assembleLunaAndCatDebug assemblePhiroDebug assembleEmbroideryDesignerDebug ' + + 'assemblePocketCodeBetaDebug' : '' } def useDebugLabelParameter(defaultLabel) { @@ -126,7 +127,7 @@ pipeline { stage('Static Analysis') { steps { - catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { + catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { sh './gradlew pmd checkstyle lintCatroidDebug detekt' } } @@ -144,13 +145,10 @@ pipeline { stage('Unit Tests') { steps { - catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { - sh './gradlew -PenableCoverage jacocoTestCatroidDebugUnitTestReport' - } - } - - post { - always { + catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { + sh './gradlew -PenableCoverage jacocoTestCatroidDebugUnitTestReport --full-stacktrace' + sh 'mkdir -p catroid/build/reports/jacoco/jacocoTestCatroidDebugUnitTestReport/' + sh 'touch catroid/build/reports/jacoco/jacocoTestCatroidDebugUnitTestReport/jacocoTestCatroidDebugUnitTestReport.xml' junitAndCoverage 'catroid/build/reports/jacoco/jacocoTestCatroidDebugUnitTestReport', 'jacocoTestCatroidDebugUnitTestReport.xml', 'unit' } } @@ -158,7 +156,7 @@ pipeline { stage('Instrumented Unit Tests') { steps { - catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { + catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { sh '''./gradlew -PenableCoverage -PlogcatFile=instrumented_unit_logcat.txt -Pemulator=android28 \ startEmulator createCatroidDebugAndroidTestCoverageReport \ -Pandroid.testInstrumentationRunnerArguments.class=org.catrobat.catroid.testsuites.LocalHeadlessTestSuite''' @@ -174,7 +172,7 @@ pipeline { stage('Testrunner Tests') { steps { - catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { + catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { sh '''./gradlew -PenableCoverage -PlogcatFile=testrunner_logcat.txt -Pemulator=android28 \ startEmulator createCatroidDebugAndroidTestCoverageReport \ -Pandroid.testInstrumentationRunnerArguments.package=org.catrobat.catroid.catrobattestrunner''' @@ -194,7 +192,7 @@ pipeline { } steps { - catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { + catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { sh '''./gradlew -PenableCoverage -PlogcatFile=quarantined_logcat.txt -Pemulator=android28 \ startEmulator createCatroidDebugAndroidTestCoverageReport \ -Pandroid.testInstrumentationRunnerArguments.class=org.catrobat.catroid.testsuites.UiEspressoQuarantineTestSuite''' @@ -210,8 +208,8 @@ pipeline { stage('RTL Tests') { steps { - catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { - sh '''./gradlew -PenableCoverage -PlogcatFile=rtltests_logcat.txt -Pemulator=android24 \ + catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { + sh '''./gradlew -PenableCoverage -PlogcatFile=rtltests_logcat.txt -Pemulator=android28 \ startEmulator createCatroidDebugAndroidTestCoverageReport \ -Pandroid.testInstrumentationRunnerArguments.class=org.catrobat.catroid.testsuites.UiEspressoRtlTestSuite''' } diff --git a/Jenkinsfile.buildMetadata b/Jenkinsfile.buildMetadata index 82f0dcbeebf..0d2be90f2d9 100644 --- a/Jenkinsfile.buildMetadata +++ b/Jenkinsfile.buildMetadata @@ -27,7 +27,7 @@ pipeline { stage('Setup Translations') { steps { script { - if (env.flavor == 'Playground') { + if (env.flavor == 'PocketCodeBeta') { sh ''' set +x ./gradlew generateCrowdinMetadataCatroid -PcrowdinKey=$crowdinKey @@ -51,7 +51,7 @@ pipeline { stage('Create Screenshots') { steps { script { - if (env.flavor == 'Playground') { + if (env.flavor == 'PocketCodeBeta') { sh './gradlew generateScreenshotsCatroid' } else { sh './gradlew generateScreenshots${flavor}' @@ -107,8 +107,8 @@ pipeline { } steps { script { - if (env.flavor == 'Playground') { - echo 'Playground cannot be promoted to production!' + if (env.flavor == 'PocketCodeBeta') { + echo 'PocketCodeBeta cannot be promoted to production!' } else { // deactivated for testing to not publish by accident //sh 'fastlane android promote_${flavor}' diff --git a/Jenkinsfile.releaseAPK b/Jenkinsfile.releaseAPK index 0baea16e60d..6ed1cba7988 100644 --- a/Jenkinsfile.releaseAPK +++ b/Jenkinsfile.releaseAPK @@ -38,7 +38,7 @@ pipeline { -PsigningKeyAlias=$signingKeyAlias \ -PsigningKeyPassword=$signingKeyPassword \ ''' - } else if (env.flavor == 'Playground') { + } else if (env.flavor == 'PocketCodeBeta') { sh ''' set +x ./gradlew copyAndroidNatives assembleCatroidSignedRelease \ @@ -46,7 +46,7 @@ pipeline { -PsigningKeystorePassword=$signingKeystorePassword \ -PsigningKeyAlias=$signingKeyAlias \ -PsigningKeyPassword=$signingKeyPassword \ - -Pplayground=true + -PpocketCodeBeta=true ''' } else { sh ''' @@ -89,7 +89,8 @@ pipeline { fastlane android upload_APK_CreateAtSchool fastlane android upload_APK_EmbroideryDesigner fastlane android upload_APK_LunaAndCat - fastlane android upload_APK_Phiro + fastlane android upload_APK_Phiro + fastlane android upload_APK_PocketCodeBeta ''' } else { sh 'fastlane android upload_APK_${flavor}' diff --git a/README.md b/README.md index ea7e414f4cc..b4573b699da 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ Start setting up the working environment by following the instructions: https:// Also make sure to read our guidelines for [creating a pull request](https://github.com/Catrobat/Catroid/wiki/Creating-a-pull-request) +A first training ticket usually consists of writing a new Catrobat language test, see https://jira.catrob.at/browse/CATROID-390 for details. + # Resources and links # * [Google Play Store Download](https://catrob.at/gp) diff --git a/build.gradle b/build.gradle index 1c91b41384c..39c90e99512 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,9 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.60' + ext.kotlin_version = '1.4.10' + ext.koin_version = '2.1.5' + ext.lifecycle_version = '2.2.0' repositories { google() jcenter() diff --git a/catroid/PARROT_License_JUNE_2011_v2_1.txt b/catroid/PARROT_License_JUNE_2011_v2_1.txt deleted file mode 100644 index c025479b818..00000000000 --- a/catroid/PARROT_License_JUNE_2011_v2_1.txt +++ /dev/null @@ -1,243 +0,0 @@ -IMPORTANT: INSTRUCTION TO USE AND TO APPLY THE TERMS OF THE LICENSE TO ANY NEW PROGRAM - -READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING -    - -Copyright (C) 2007-2011, PARROT SA, all rights reserved. - - -You may use, copy, modify the PARROT AR.Drone SDK and APIs or any portion of it, and thus form a work based on Parrot SDK and APIs, and copy and redistribute in source code and binary forms, with or without modification, provided that you comply with following conditions: - -* Redistribution in source code, with or without modification, must retain Parrot copyright notice, the following disclaimer and the license to develop and use in a text file named “Parrot License”. - -* Redistribution in binary form must reproduce Parrot copyright notice, the following disclaimer in the product documentation or legal notice. - -* The name of Parrot may not be used to endorse or promote products derived from the APIs without specific prior written permission. - - -DISCLAIMER -The APIs is provided by PARROT and contributors "AS IS" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall PARROT and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.  - - -DEVELOPMENT LICENSE OF THE PARROT AR.DRONE SDK and APIs V2.0 -(Creation of games for the Parrot AR.DRONE) - - - - -Article 1: Purpose  -The purpose of the present Development License is to define the terms and conditions under which the Developer is authorized to use the source codes of the PARROT SDK and APIs to create under its own responsibility a Game for the AR.Drone and to market it for free or against payment. - -Article 2: Definitions -The terms defined hereunder, used in singular or plural, shall have the following meaning: - -- «PARROT SDK and APIs »: means the AR.Drone software development kit and AR.Drone APIs and associated documentation, allowing to pilot the PARROT AR.Drone, from a mobile phone, a console game, a computer or any other electronic device, and which source codes are provided for free to the Developer; -- « Developer » means a physical person, of age, having the capacity to accept the terms of the present License or a person, representing a company and having all powers to that effect to bind the company; -- “PARROT AR.Drone” or “PARROT AR.Drone” or « PARROT Drone» means the augmented reality drone developed by PARROT, without pilot, remote-controlled by a mobile phone, a console game, a computer or any other electronic device; -- « Interoperability »: means the ability of an application to exchange information with the Parrot AR.Drone or any it’s accessories; -- “ Game for AR.Drone” : means a software or a video game, created by the Developer from the PARROT SDK and APIs  or any modified version, and which functionalities shall exclusively be dedicated to the use of the PARROT AR.Drone for entertaining, game, leisure or training purpose or any other purpose compatible with the terms of the present license; -- « License » means the present license of development and use of the API’s; -- « User Account» means the information relating to the identification of a Developer, such as first name, surname, email address, login, password, company, title; -- « User »: means any physical person using the PARROT Drone or a Game for AR.Drone. - -ARTICLE 3 – Identification -3.1 The downloading of the API’s is subject to the Identification of the Developer by filling in the online registration form and accept the terms of the License by clicking the acceptance box on https://projects.ardrone.org . -3.2 The Developer commits to provide accurate information and to update the information, if necessary. - -3.4 The User Account is personal and confidential; it cannot be assigned to a third party. - -3.5 The Developer commits to inform PARROT immediately of any disclosure, non authorized use by a third party of the login and/or password of its User Account. In such case, PARROT shall be entitled to invalid the login and the password. - - -ARTICLE 4 – Conditions of Use -Notwithstanding the limitation and restrictions mentioned in article 5, PARROT grants to the Developer, who accepts, a personal, non-assignable, non-exclusive, worldwide, free license of development of the PARROT SDK and APIs authorizing the Developer to: -* reproduce, without number limitation, the API’s on any device under its responsibility, and necessary to create the Game for AR.Drone; -* translate, adapt, arrange, modify the API’s  in order to create a Game for AR.Drone in the software and hardware environment chosen by the Developer; -* to market, for free or against fees, copies of the Game for AR.Drone created ; -* to grant licenses of the Game for AR.Drone to the Users of the PARROT Drone. - - -ARTICLE 5 – Restrictions to the license -5.1 The License of development and use of the API’s is subject to the acceptance and to the respect by the Developer without any reserves of all restrictions and limitations listed hereafter: - -Consequently, PARROT expressly forbids the Developer: -i. To do reverse engineering, decompile or attempt to extract the Source Codes of the PARROT Drone; under special legal conditions, necessary information for interoperability purpose might be requested from PARROT ; -ii. To destroy, or alter any warning and copyrights notices; -iii. To use the PARROT SDK and APIs to develop an application other than a Game for AR.Drone. The Game for AR.Drone shall have for sole purpose to be used by a User for entertaining, game, leisure or training. The creation of applications for the use of the PARROT AR.Drone for professional use or use such as but not limited to military, and, without limitation, security, watching, spying, defence, cartography, is strictly forbidden. -iv. To use the PARROT SDK and APIs or to create a Game for AR.Drone breaching the terms of: -(1) The License; -(2) Third party rights; -(3) Applicable laws and regulations; -(4) Any instruction provided by PARROT. - -5.2 Therefore, and without limitation, the Developer commits when using the API’s or when creating a Game for AR.Drone: -a) not to infringe any applicable laws and regulation which the Developer shall determine whatever the country where he intends to develop and/or market the Game for AR.Drone ; -b) not to reproduce, represent, put contents which infringe copyrights, patents, trademarks, design, model, know-how, commercial secret and any intellectual property rights belonging to PARROT or to third parties ; -c) not to falsify or remove copyrights, trademarks notices of any other proprietary rights of PARROT figuring in the Application; -d) not to display a Game for AR.Drone which falsely or implied would suggest an endorsement or any approbation from PARROT ; -e) not to collect or treat, or store, with the Game for AR.Drone, personal data from third, especially User of the Game for AR.Drone without having previously asked for their consent. Shall the Game for AR.Drone store personal data, it should be in compliance with the applicable law - -5.3 PARROT is sole judge of the compliance of the Game for AR.Drone with the terms and conditions of the present License. - -5.5 PARROT reserves the right to correct or modify the PARROT SDK and APIs during the License duration. - -ARTICLE 6 – Duration of the License - -The License of the PARROT SDK and APIs is granted for the duration of the intellectual property rights of the Game for AR.Drone. It enters into force upon acceptance by the Developers by clicking the acceptance box or using a modified release of the PARROT SDK and APIs. - - -ARTICLE 7 – Termination of the License - -7.1. Termination of the License  -7.1.1 PARROT reserves the right to terminate the present License, without notice, in following cases: - -i. The Developer  has created a Game for AR.Drone in violation of the present License terms, any applicable law and regulation or PARROT has objective reasons to believe that the Game for AR.Drone is infringing the License or any applicable law and regulation ; -ii. The Developer has created a Game for AR.Drone in violation of PARROT’s intellectual property rights or PARROT has objective reasons to believe that the Game for AR.Drone is infringing it’s rights ;  -iii. The Developer  has created a Game for AR.Drone in violation of a third party’s intellectual property rights or PARROT has objective reasons to believe that the Game for AR.Drone is infringing a third party’s rights ;  -iv. The Developer has created a Game for AR.Drone containing bugs, viruses, worms, defects, Trojan horses, or any items of a destructive nature or PARROT has objective reasons to believe that the Game for AR.Drone contains of this item; - -7.1.2 Termination of the License shall be notified by email to any user breaching the terms of the License. - -7.1.3 In case of closing of a User Account or termination of the License, for whatever reason, articles which by their nature shall survive shall continue to be applicable, in particular articles 11.RIGHTS OF PARROT; 12.EXCLUSION OF WARRANTIES; 13.LIMITATION OF RESPONSIBILITY; 14.INDEMNITY; 15.GENERALS TERMS. - -ARTICLE 8 – Specific Development - -Upon request of a video game editor, PARROT may perform specific development of the PARROT SDK and APIs, in order to enable the creation of a Game for AR.Drone for commercial purpose by such editor. The development services provide by PARROT shall be subject to a separate agreement between PARROT and the editor. PARROT and the editor shall share the revenues gained from the sale of games created thanks to the specific development for an amount to be determined by agreement between the parties. - - -ARTICLE 9 – Upgrade of the API’s  -9.1 Due to technological innovations and for quality and/ or security reasons, the Developer acknowledges and agrees that PARROT may at any time modify the API’s, namely by adjunction, removal, improvement of functionalities, or that PARROT may temporarily or definitely suspend the access to the API’s, at its sole discretion and without notice. PARROT warrants – as far as possible and with no result obligation, the ascendant compatibility of the API’s. - -9.2 PARROT shall notify any modification by publication on https://projects.ardrone.org, or per email, or by any other appropriate mean in PARROT judgment. From the notification, the use of the API’s by the Developer to create new Game for AR.Drone shall be deemed as the acceptance by the Developer of the modified License of the PARROT SDK and APIs. - - -ARTICLE 10 – License granted to Parrot by the Developper -10.1 The Developer is owner of all copyrights and other intellectual property rights on the Game for AR.Drone that he creates. If the Developer is posting his Game for AR.Drone on https://projects.ardrone.org , he grants PARROT a perpetual, irrevocable, worldwide, free and non-exclusive license to reproduce, represent, adapt, arrange , modify, translate, publish, operate and display the Game for AR.Drone by any means of communication, numerical, analogical, electronic..to the public and namely by any network(internet, intranet), wireless or not, by mobile phone, email, by satellite, par optical fibre, par television and on any media. - -10.2 This license shall be granted in order to allow PARROT to display, promote, and distribute the PARROT SDK and APIs and/or the PARROT AR.Drone. - -10.3 This license includes the right for PARROT to make the Game for AR.Drone available – totally or partially – to any Users of the AR.DRONE PARROT or to any person with who PARROT is in relationship, and to use the Game for AR.Drone for information or advertisement purpose. - -10.4 The Developer agrees that PARROT for technical or for improvement purpose, may (a) transmit or communicate the Game for AR.Drone on public network others than internet (wireless or not, namely mobile telephony) and various media (graphic, magnetic, optical, numerical, analogical); and (b) make any modification necessary to adapt and make the Game for AR.Drone compliant to technical specifications so to make it interoperable with networks or devices. - -10.5 The Developer warrants PARROT that he has the rights to grant the license. - - -ARTICLE 11: Parrot Rights -11.1 Intellectual and industrial property rights. -PARROT is and remains the owner of all rights and interests on the PARROT SDK and APIs and on the PARROT AR.Drone, including without limitation all rights of intellectual and industrial property (copyrights, database rights, patents, trademark, design and model, semi-conductor topography) and/or any rights on the know-how, schemes, plans, algorythme, technologies, ideas, concepts. - -It is expressly specified that PARROT is owner of patents on the PARROT AR.Drone and that a right to use such patent is granted within the frame of the present License. No other rights on the patents are granted to the Developer who commits no to use the technologies issued from those patents for purpose not in the scope of the present License. - - - - - - -11.2 Trademarks and logos. -11.2.1 PARROT is owner of the intellectual property rights on its commercial trade name, trademarks, logos, domain names and any others brand features. PARROT grants the Developer a non-exclusive, non assignable, non transferable, non sub-licensable, free license to use PARROT trademarks and logos for the sole purpose of mentioning that he uses the PARROT SDK and APIs. - -11.2.2 When using PARROT’s trademarks and logos, the Developer undertakes: -i. Not to display a trademark or a logo in any manner that implies a relationship or affiliation with, sponsorship, or endorsement by PARROT or that can be reasonably interpreted to suggest editorial content has been authored by, or represents the views or opinions of PARROT; -ii. Not to use PARROT brand features to disparage PARROT or its products; -iii. Not to display a trademark or a logo on its website if it contains or displays adult content or promotes illegal activities, gambling, or the sale of tobacco or alcohol to persons under eighteen (18) years of age; -iv. Not to display the PARROT trademark and logo as the most prominent element in any part of the Game for AR.Drone created by the Developer or its packaging; -v. Not to display the PARROT logo as the most prominent logo in the Game for AR.Drone ; -vi. Not to display PARROT trademark or logo in a manner that is misleading, defamatory, infringing, libelous, disparaging, obscene or otherwise objectionable to PARROT; -vii. Not to display a PARROT trademark or logo on a site that violates any law or regulation ; -viii. Not to remove, distort or alter any element of a PARROT brand feature (including squeezing, stretching, inverting, discoloring, etc.). - -11.3 The Developer undertakes during the term of the License and after its expiration, not to register or attempt to register any trademark, logo, domain name similar to or confusing with PARROT trademark or logo, in any manner (phonetic, intellectual, visual). PARROT reserves the right to sue for counterfeiting and unfair competition, any Developer who would not respect this commitment and use the trademarks and/or domain name PARROT AR.DRONE OU AR.DRONE in breach of the License. - -11.4 The Developer undertakes to immediately remedy to any breach notified by PARROT per email or any other mean concerning any infringement to PARROT intellectual property rights. - -11.5 The Developer, company or physical person, is owner, as applicable, on the intellectual property rights on his name, commercial name, trademarks, logos and any other brand features. He expressly grants PARROT a non exclusive, worldwide and free license to mention his name, commercial name, trademarks, logos, as applicable, to mention that he uses the PARROT SDK and APIs and/or that he has created a Game for AR.Drone. - - -ARTICLE 12: DISCLAIMER -12.1 THE PARROT SDK AND APIs IS PROVIDED «AS IS ». IN PARTICULAR, PARROT, IT’S SUBSIDIARIES, LICENSORS AND THEIR SUPPLIERS, DO NOT REPRESENT OR WARRANT THE DEVELOPER THAT: -1. ITS USE OF THE API’s WILL MEET ITS REQUIREMENTS; -2. ITS USE OF THE API’s WILL BE UNINTERRUPTED, TIMELY, SECURE OR FREE FROM ERROR OR WILL OFFER CONSTANT PERFORMANCE; -3. THAT DEFECTS OR ERRORS WILL BE CORRECTED OR THAT THE API’s WILL BE UPGRADE, PARROT HAVING NO OBLIGATION TO PROVIDE CURATIVE OR EVOLUTIVE SUPPORT; -4. THE API’s IS COMPLIANT TO ANY SPECIFICATIONS; - 5. ANY UPGRADE OF THE PARROT SDK AND APIs WILL BE COMPATIBLE WITH PREVIOUS RELEASE. - -12.2 PARROT, ITS SUBSIDIARIES, LICENSORS AND THEIR SUPPLIERS, DO NOT REPRESENT OR WARRANT THE DEVELOPER THAT ITS USER ACCOUNT WILL BE AVAILABLE WITHOUT INTERRUPTION. - -12.3 NO ADVICE OR INFORMATION, WHETHER ORAL OR WRITTEN, OBTAINED BY THE DEVELOPER FROM PARROT, ITS SUBSIDIARERIES, OR THROUGH THE API’s, SHALL BE CONSTRUED A WARRANTY PROVIDED BY PARROT. - -12.4 PARROT, IT’S SUBSIDIARIES, ITS LICENSORS DO NOT WARRANT, ANY RESULT, EXPRESS OR IMPLIED, OF ANY NATURE (TECHNICAL, COMMERCIAL, FINANCIAL OR OTHER) FROM THE USE OF THE APPLICATION. - -12.5 PARROT DECLARES THAT TO THE BEST OF ITS KNOWLEDGE THE PARROT SDK AND APIs DOES NOT INFRINGE ANY THIRD PARTY INTELLECTUAL PROPERTY RIGHTS. - - -ARTICLE 13: LIMITATION OF RESPONSABILITY -13.1 THE PROVISION EXCLUSING OR LIMITING PARROT’S LIABILITY SHALL ONLY BE APPLICABLE IN COUNTRIES WHERE SUCH PROVISIONS ARE LEGAL. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF CERTAIN WARRANTIES OR THE LIMITATION OR EXCLUSION OF LIABILITY FOR CERTAIN TYPES OF LOSS OR DAMAGES. ACCORDINGLY, PARROT’S LIABILITY WILL BE LIMITED TO THE MAXIMUM EXTENT PERMITTED BY LAW. - - - - -13.2 THE DEVELOPER EXPRESSLY ACKNOWLEDGES AND AGREES THAT THE USE HE DOES OF ITS USER ACCOUNT, THE API’s, THE GAME FOR AR.DRONE THAT HE CREATES, ARE AT ITS SOLE RISK AND RESPONSABILITY. IN PARTICULAR, THE DEVELOPER SHALL BE SOLELY RESPONSIBLE FOR ANY DAMAGE TO ITS COMPUTER SYSTEM OR OTHER DEVICE, LOSS OF DATA, OR ANY OTHER DAMAGE OR INJURY THAT RESULTS FROM THE DOWNLOAD OR USE OF THE API’s. - -13.3 THE DEVELOPER EXPRESSLY ACKNOWLEDGES AND AGREES THAT HE SHALL BE SOLELY RESPONSIBLE FOR ALL COSTS, EXPENSES INCURRING FOR THE USE OF ITEMS MENTIONED ABOVE AS WELL AS ANY DEVELOPMENT AND PRODUCTION COSTS ASSOCIATED TO THE GAME OF AR.DRONE THAT HE IS CREATING. - -13.4 PARROT, ITS SUPPLIERS, LICENSORS, AFFILIATES, ARE NOT RESPONSIBLE FOR ANY DIRECTS OR INDIRECTS, MATERIALS OR IMMATERIALS, CONSECUTIVES OR NON CONSECUTIVES DAMAGES, INCLUDING, BUT NOT BE LIMITED TO, ANY LOSS OF PROFIT (WHETHER INCURRED DIRECTLY OR INDIRECTLY), ANY LOSS OF GOODWILL OR BUSINESS REPUTATION, ANY LOSS OF DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR OTHER INTANGIBLE LOSS, THAT DEVELOPER OR A THIRD PARTY MAY INCURR FROM: - -1- THE USE BY THE DEVELOPER OF ITS USER ACCOUNT, THE PARROT SDK AND APIs, THE GAME FOR AR.DRONE THAT HE CREATES; -2- THE MARKETING OF THE GAME FOR AR.DRONE FOR FREE OR AGAINST FEES; -3- THE MODIFICATION OF THE API’s BY PARROT; -4- THE CLOSING OF THE USER ACCOUNT, THE MODIFICATION OR THE EXPIRATION OR TERMINATION OF THE LICENSE; -5- ANY NON ACCURATE OR NON UPDATED INFORMATION PROVIDED BY PARROT, - -ARTICLE 15: Indemnification -The Developer warrants and hereby agrees to indemnify, defend and hold PARROT harmless from and against any claim or liability arising out of: (a) the use of the API’s in breach of the License and/or any instruction provided by PARROT; (b) the Game for AR.Drone; (c) any use by Users of the Game for AR.Drone; (d) any claim that the Game for AR.Drone breaches laws or infringes third party rights; consequently, assume all costs and damages to which PARROT could be condemned by a jurisdiction on such a basis. The Developer shall cooperate as fully as reasonably required in the defence of any claim and PARROT reserves the right, at its own expense, to assume the exclusive defence and control of any matter subject to indemnification by the Developer. And if necessary, to seek equitable relief, including but not limited to preliminary injunction and injunction, in addition to all other remedies. - -ARTICLE 16: Hyperlinks -16.1. The https://project.ardrone.org ardrone.org website may include hyperlinks to other web sites or content or resources provided by third parties and companies. PARROT has no control or authority over any web sites, resources, third parties. The Developer acknowledges and agrees that PARROT is not responsible for the availability of any such external sites or resources, and does not endorse any advertising, products or other materials on or available from such web sites or resources. - -16.2. The Developer acknowledges and agrees that PARROT is not liable for any loss or damage that may be incurred by the Developer as a result of the availability of those external sites or resources, or as a result of any reliance placed by you on the completeness, accuracy or existence of any advertising, products, or other materials on, or available from, such web sites or resources. - - -ARTICLE 17: Language and interpretation -17.1 The English version of the License shall prevail over any translation, which might only be provided for convenience purpose. Therefore any translation might be provided only for convenience purpose. - -17.2 If there is any contradiction between the English language version of the License and a translation of the License, the English language version will take precedence. - -17.3 Titles are provided for convenience purpose only; the content of an article shall have precedence on the title. - -ARTICLE 18: General provisions -18.1 The License constitutes the entire legal agreement between Parrot and the Developer and completely replace and supersede any prior agreements between PARROT and the Developer. - -18.2 The waiver by PARROT to prevail itself from a provision of the License shall not be construed as a waiver to prevail itself of any right obligation under the License in the future. - -18.3 If any court of law having jurisdiction rules that any provision of this License is invalid, then that provision will be removed from the License without affecting the rest of the License. The remaining provisions of the License will continue to be valid and enforceable. - -18.4 Any notice sent by PARROT to the Developer or exchange between the Parties will be validly delivered per email at the address provided by the Developer in its User Account and at legal@ardrone.org for PARROT. - - -ARTICLE 19: Applicable law and jurisdiction -The License is governed by French Law, without regard to its conflict of Laws provisions. Any dispute arising out of its interpretation, execution or termination shall be submitted to the exclusive jurisdiction of the relevant court of Paris, even for urgency proceedings or plurality of defendants. Notwithstanding this, PARROT shall be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction - - -ARTICLE 20 - Privacy -20.1 All information about our privacy policy are provided on www.parrot.com . This policy explains how PARROT treats any personal data which are disclosed to her and protect your privacy. - -20.2 The Developer agrees that PARROT may use its personal data in compliance with its privacy policy. - - -ARTICLE 21 – Acceptance of the license -By clicking the acceptance box, downloading or using the PARROT SDK and APIs or an adapted or modified release of the PARROT SDK and APIs, the Developer or any user accepts without reserve all terms and conditions of the License concluded between him and PARROT SA – registered under N° 394 149 496 and located 174 quai de Jemmapes FRANCE - which he commits to respect. - - - -Last update: June 2011 -Document revision V2.1 - - - - -1 - -PARROT SA – Capital 1 961 863,21 € - RCS B 394 149 496 – 174 QUAI DE JEMMAPES 75010 FRANCE - - diff --git a/catroid/build.gradle b/catroid/build.gradle index efd7c775823..7a56db78dff 100644 --- a/catroid/build.gradle +++ b/catroid/build.gradle @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2020 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -50,7 +50,6 @@ ext { gdxVersion = "1.9.10" mockitoVersion = "2.8.47" espressoVersion = "3.1.0" - paintroidVersion = "2.5.2" playServicesVersion = "17.0.0" cameraXVersion = "1.0.0-beta07" } @@ -59,6 +58,7 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' apply plugin: 'jacoco-android' +apply plugin: 'kotlin-android-extensions' apply from: 'gradle/code_quality_tasks.gradle' apply from: 'gradle/emulator_tasks.gradle' @@ -66,10 +66,6 @@ apply from: 'gradle/release_crowdin_tasks.gradle' apply from: 'gradle/release_fastlane_tasks.gradle' apply from: 'gradle/standalone_apk_tasks.gradle' -if(rootProject.hasProperty('paintroidLocal')) { - paintroidVersion = paintroidVersion + "-LOCAL" -} - if (rootProject.hasProperty('independent')) { println "Independent build" def today = new Date() @@ -78,13 +74,6 @@ if (rootProject.hasProperty('independent')) { manifestAppName = appName } -if (rootProject.hasProperty('playground') && rootProject.property('playground').toBoolean()) { - println "Playground build" - appId = 'org.catrobat.catroid.test' - appName = 'Catrobat Playground' - manifestAppName = appName -} - if (!rootProject.hasProperty("signingKeystore")) { ext.signingKeystore = "dummyKeystore" } @@ -116,17 +105,20 @@ jacocoAndroidUnitTestReport { xml.enabled true } +def defaultVersionCode = 83 +def defaultVersionName = "1.0.1" + android { compileSdkVersion 29 defaultConfig { - minSdkVersion 21 + minSdkVersion 23 targetSdkVersion 29 applicationId appId testInstrumentationRunner 'org.catrobat.catroid.runner.UiTestApplicationRunner' - versionCode 80 - versionName "0.9.75" + versionCode defaultVersionCode + versionName defaultVersionName println "VersionCode is $versionCode" println "VersionName is $versionName" multiDexEnabled true @@ -160,10 +152,11 @@ android { buildConfigField "boolean", "FEATURE_POCKETMUSIC_ENABLED", "true" buildConfigField "boolean", "FEATURE_RASPI_ENABLED", "true" buildConfigField "boolean", "FEATURE_SCRATCH_CONVERTER_ENABLED", "true" - buildConfigField "boolean", "FEATURE_USERBRICKS_ENABLED", "true" - buildConfigField "boolean", "FEATURE_WEBREQUEST_BRICK_ENABLED", "true" + buildConfigField "boolean", "FEATURE_USER_REPORTERS_ENABLED", "true" buildConfigField "boolean", "FEATURE_MULTIPLAYER_VARIABLES_ENABLED", "true" buildConfigField "boolean", "FEATURE_TESTBRICK_ENABLED", "true" + buildConfigField "boolean", "FEATURE_CATBLOCKS_ENABLED", "false" + buildConfigField "boolean", "FEATURE_CATBLOCKS_DEBUGABLE", "false" resValue "string", "FEATURE_EMBROIDERY_PREFERENCES_ENABLED", "false" resValue "string", "FEATURE_PHIRO_PREFERENCES_ENABLED", "false" resValue "string", "SNACKBAR_HINTS_ENABLED", "false" @@ -205,7 +198,6 @@ android { exclude 'LICENSE.txt' exclude 'META-INF/maven/com.google.guava/guava/pom.properties' exclude 'META-INF/maven/com.google.guava/guava/pom.xml' - exclude 'META-INF/INDEX.LIST' //compile problem with parrot arsdk exclude 'lib/mips/*' // Mips devices are deprecated exclude 'lib/armeabi/*' // armeabiv5 & v6 are deprecated } @@ -240,6 +232,8 @@ android { debug { buildConfigField "boolean", "USE_ANDROID_LOCALES_FOR_SCREENSHOTS", useAndroidLocales() resValue "string", "DEBUG_MODE", "true" + buildConfigField "boolean", "FEATURE_CATBLOCKS_ENABLED", "true" + buildConfigField "boolean", "FEATURE_CATBLOCKS_DEBUGABLE", "true" testCoverageEnabled = rootProject.hasProperty('enableCoverage') signingConfig signingConfigs.debug } @@ -247,8 +241,8 @@ android { release { buildConfigField "boolean", "FEATURE_MERGE_ENABLED", "false" buildConfigField "boolean", "FEATURE_POCKETMUSIC_ENABLED", "false" - buildConfigField "boolean", "FEATURE_USERBRICKS_ENABLED", "false" buildConfigField "boolean", "FEATURE_MULTIPLAYER_VARIABLES_ENABLED", "false" + buildConfigField "boolean", "FEATURE_USER_REPORTERS_ENABLED", "false" resValue "string", "SNACKBAR_HINTS_ENABLED", "true" signingConfig signingConfigs.debug } @@ -283,6 +277,10 @@ android { applicationIdSuffix '.phiro' resValue "string", "FEATURE_PHIRO_PREFERENCES_ENABLED", "true" } + pocketCodeBeta { + applicationIdSuffix '.test' + manifestPlaceholders.appName = "Pocket Code BETA-" + defaultVersionCode + } standalone { if (!project.hasProperty('packageName')) { applicationIdSuffix '.standalone' @@ -325,7 +323,6 @@ android { } configurations { - implementation.exclude group: 'org.apache.sanselan' //compile problem with parrot arsdk implementation.exclude group: 'xpp3' //compile problem with xstream natives } @@ -333,15 +330,18 @@ configurations { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) + // Paintroid local aar lib files + implementation fileTree(dir: 'src/main/libs', include: ['*.aar']) + // Kotlin implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8' // Support libraries - implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.mediarouter:mediarouter:1.1.0' implementation 'androidx.cardview:cardview:1.0.0' - implementation 'com.google.android.material:material:1.0.0' + implementation 'com.google.android.material:material:1.2.1' implementation 'androidx.browser:browser:1.2.0' implementation "androidx.test.espresso:espresso-idling-resource:$espressoVersion" @@ -352,14 +352,26 @@ dependencies { exclude group: 'commons-logging', module: 'commons-logging' } - // Dagger - implementation 'com.google.dagger:dagger:2.21' - implementation 'com.google.dagger:dagger-android:2.21' - kapt 'com.google.dagger:dagger-compiler:2.21' - kapt 'com.google.dagger:dagger-android-processor:2.21' + // Dependency Injection + implementation "org.koin:koin-core:$koin_version" + implementation "org.koin:koin-androidx-scope:$koin_version" + implementation "org.koin:koin-androidx-viewmodel:$koin_version" + implementation "org.koin:koin-androidx-fragment:$koin_version" + + // Retrofit + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + // retrofit moshi converter + implementation 'com.squareup.retrofit2:converter-moshi:2.7.1' + // Glide (Images downloader) + implementation 'com.github.bumptech.glide:glide:4.11.0' - // Drone - implementation 'com.parrot:arsdk:3.12.6' + // Shimmer effect + implementation 'com.facebook.shimmer:shimmer:0.5.0' + + // Lifecycle + implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" // CAST implementation "com.google.android.gms:play-services-cast:$playServicesVersion" @@ -378,18 +390,13 @@ dependencies { exclude group: 'xmlpull' } + // Catblocks + implementation "androidx.webkit:webkit:1.2.0" + // Pocket Music implementation 'com.github.oliewa92:MidiDroid:v1.1' implementation 'com.github.billthefarmer:mididriver:v1.16' - // Pocket Paint - catroidImplementation "org.catrobat.paintroid:paintroid:$paintroidVersion" - createAtSchoolImplementation "org.catrobat.paintroid:paintroid:$paintroidVersion" - embroideryDesignerImplementation "org.catrobat.paintroid:paintroid:$paintroidVersion" - lunaAndCatImplementation "org.catrobat.paintroid:paintroid:$paintroidVersion" - phiroImplementation "org.catrobat.paintroid:paintroid:$paintroidVersion" - implementation "org.catrobat.paintroid:colorpicker:$paintroidVersion" - // CameraX implementation "androidx.camera:camera-camera2:$cameraXVersion" implementation "androidx.camera:camera-lifecycle:${cameraXVersion}" @@ -397,6 +404,7 @@ dependencies { // ML Kit implementation 'com.google.android.gms:play-services-mlkit-face-detection:16.0.0' implementation 'com.google.android.gms:play-services-mlkit-text-recognition:16.1.0' + implementation 'com.google.mlkit:language-id:16.1.0' // libGDX implementation "com.badlogicgames.gdx:gdx:$gdxVersion" @@ -433,6 +441,12 @@ dependencies { testImplementation 'org.reflections:reflections:0.9.11' testImplementation 'org.json:json:20190722' + // Retrofit testing + androidTestImplementation 'com.squareup.okhttp3:mockwebserver:3.14.9' + + // Koin for Unit tests + androidTestImplementation "org.koin:koin-test:$koin_version" + androidTestImplementation 'com.linkedin.dexmaker:dexmaker-mockito:2.2.0' androidTestImplementation "org.mockito:mockito-core:$mockitoVersion" diff --git a/catroid/config/detekt.yml b/catroid/config/detekt.yml index f2a5304b169..b06a9c457a2 100644 --- a/catroid/config/detekt.yml +++ b/catroid/config/detekt.yml @@ -67,7 +67,7 @@ complexity: threshold: 600 LongMethod: active: true - threshold: 60 + threshold: 80 LongParameterList: active: true threshold: 6 diff --git a/catroid/config/lint-baseline.xml b/catroid/config/lint-baseline.xml index 265236dd3ff..624d3f344e3 100644 --- a/catroid/config/lint-baseline.xml +++ b/catroid/config/lint-baseline.xml @@ -1,7 +1,7 @@ + + + Покет Код + diff --git a/catroid/src/createAtSchool/java/org/catrobat/catroid/common/FlavoredConstants.java b/catroid/src/createAtSchool/java/org/catrobat/catroid/common/FlavoredConstants.java index 7e7bc18f780..bda00f1c259 100644 --- a/catroid/src/createAtSchool/java/org/catrobat/catroid/common/FlavoredConstants.java +++ b/catroid/src/createAtSchool/java/org/catrobat/catroid/common/FlavoredConstants.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -35,8 +35,12 @@ public final class FlavoredConstants { // Web: public static final String BASE_URL_HTTPS = MAIN_URL_HTTPS + "/create@school/"; + public static final String CATEGORY_URL = BASE_URL_HTTPS + "#home-projects__"; + public static final String POCKET_CODE_EXTERNAL_STORAGE_FOLDER_NAME = "Create@School"; + public static final String FLAVOR_NAME = "create@school"; + public static final File DEFAULT_ROOT_DIRECTORY = CatroidApplication.getAppContext().getFilesDir(); public static final File EXTERNAL_STORAGE_ROOT_DIRECTORY = new File( @@ -48,6 +52,7 @@ public final class FlavoredConstants { public static final String LIBRARY_BACKGROUNDS_URL_PORTRAIT = BASE_URL_HTTPS + "media-library/backgrounds-portrait"; public static final String LIBRARY_BACKGROUNDS_URL_LANDSCAPE = BASE_URL_HTTPS + "media-library/backgrounds-landscape"; public static final String LIBRARY_SOUNDS_URL = BASE_URL_HTTPS + "media-library/sounds"; + public static final String PRIVACY_POLICY_URL = "https://catrob.at/createatschoolprivacy"; private FlavoredConstants() { throw new AssertionError("No."); diff --git a/catroid/src/embroideryDesigner/java/org/catrobat/catroid/common/FlavoredConstants.java b/catroid/src/embroideryDesigner/java/org/catrobat/catroid/common/FlavoredConstants.java index a8b8761d0db..53f739d9288 100644 --- a/catroid/src/embroideryDesigner/java/org/catrobat/catroid/common/FlavoredConstants.java +++ b/catroid/src/embroideryDesigner/java/org/catrobat/catroid/common/FlavoredConstants.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -35,8 +35,12 @@ public final class FlavoredConstants { // Web: public static final String BASE_URL_HTTPS = MAIN_URL_HTTPS + "/embroidery/"; + public static final String CATEGORY_URL = BASE_URL_HTTPS + "#home-projects__"; + public static final String POCKET_CODE_EXTERNAL_STORAGE_FOLDER_NAME = "EmbroideryDesigner"; + public static final String FLAVOR_NAME = "embroidery"; + public static final File DEFAULT_ROOT_DIRECTORY = CatroidApplication.getAppContext().getFilesDir(); public static final File EXTERNAL_STORAGE_ROOT_DIRECTORY = new File( @@ -48,6 +52,7 @@ public final class FlavoredConstants { public static final String LIBRARY_BACKGROUNDS_URL_PORTRAIT = BASE_URL_HTTPS + "media-library/backgrounds-portrait"; public static final String LIBRARY_BACKGROUNDS_URL_LANDSCAPE = BASE_URL_HTTPS + "media-library/backgrounds-landscape"; public static final String LIBRARY_SOUNDS_URL = BASE_URL_HTTPS + "media-library/sounds"; + public static final String PRIVACY_POLICY_URL = "https://catrob.at/privacypolicy"; private FlavoredConstants() { throw new AssertionError("No."); diff --git a/catroid/src/embroideryDesigner/res/values-ru/strings.xml b/catroid/src/embroideryDesigner/res/values-ru/strings.xml new file mode 100644 index 00000000000..bb75bb72549 --- /dev/null +++ b/catroid/src/embroideryDesigner/res/values-ru/strings.xml @@ -0,0 +1,27 @@ + + + + + Дизайнер по Đ’Ń‹Ńивке + diff --git a/catroid/src/lunaAndCat/java/org/catrobat/catroid/common/FlavoredConstants.java b/catroid/src/lunaAndCat/java/org/catrobat/catroid/common/FlavoredConstants.java index 7414b218689..3475b4c074d 100644 --- a/catroid/src/lunaAndCat/java/org/catrobat/catroid/common/FlavoredConstants.java +++ b/catroid/src/lunaAndCat/java/org/catrobat/catroid/common/FlavoredConstants.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -35,8 +35,12 @@ public final class FlavoredConstants { // Web: public static final String BASE_URL_HTTPS = MAIN_URL_HTTPS + "/luna/"; + public static final String CATEGORY_URL = BASE_URL_HTTPS + "#home-projects__"; + public static final String POCKET_CODE_EXTERNAL_STORAGE_FOLDER_NAME = "Luna&Cat"; + public static final String FLAVOR_NAME = "luna"; + public static final File DEFAULT_ROOT_DIRECTORY = CatroidApplication.getAppContext().getFilesDir(); public static final File EXTERNAL_STORAGE_ROOT_DIRECTORY = new File( @@ -48,6 +52,7 @@ public final class FlavoredConstants { public static final String LIBRARY_BACKGROUNDS_URL_PORTRAIT = BASE_URL_HTTPS + "media-library/backgrounds-portrait"; public static final String LIBRARY_BACKGROUNDS_URL_LANDSCAPE = BASE_URL_HTTPS + "media-library/backgrounds-landscape"; public static final String LIBRARY_SOUNDS_URL = BASE_URL_HTTPS + "media-library/sounds"; + public static final String PRIVACY_POLICY_URL = "https://catrob.at/privacypolicy"; private FlavoredConstants() { throw new AssertionError("No."); diff --git a/catroid/src/lunaAndCat/res/values-ru/strings.xml b/catroid/src/lunaAndCat/res/values-ru/strings.xml new file mode 100644 index 00000000000..cb469bc8690 --- /dev/null +++ b/catroid/src/lunaAndCat/res/values-ru/strings.xml @@ -0,0 +1,27 @@ + + + + + Đ›Ńна и КоŃка + diff --git a/catroid/src/main/AndroidManifest.xml b/catroid/src/main/AndroidManifest.xml index 8c427243937..d83e1db14ed 100644 --- a/catroid/src/main/AndroidManifest.xml +++ b/catroid/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ - - - - - - - - @@ -92,6 +79,7 @@ android:theme="@style/Catroid" android:supportsRtl="true" android:requestLegacyExternalStorage="true" + tools:ignore="UnusedAttribute" tools:replace="android:label,android:allowBackup" android:usesCleartextTraffic="true"> @@ -130,6 +118,10 @@ android:name=".ui.MarketingActivity" android:screenOrientation="portrait" /> + + @@ -177,11 +169,6 @@ android:screenOrientation="portrait" android:windowSoftInputMode="adjustNothing" /> - - - diff --git a/catroid/src/main/assets/catblocks/CatBlocks.js b/catroid/src/main/assets/catblocks/CatBlocks.js new file mode 100644 index 00000000000..8b87dd9fe52 --- /dev/null +++ b/catroid/src/main/assets/catblocks/CatBlocks.js @@ -0,0 +1,46 @@ +var CatBlocks=function(t){var e={};function o(i){if(e[i])return e[i].exports;var n=e[i]={i:i,l:!1,exports:{}};return t[i].call(n.exports,n,n.exports,o),n.l=!0,n.exports}return o.m=t,o.c=e,o.d=function(t,e,i){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(t,e){if(1&e&&(t=o(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(o.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)o.d(i,n,function(e){return t[e]}.bind(null,n));return i},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="",o(o.s=72)}([function(t,e,o){var i,n,s;n=[o(111)],void 0===(s="function"==typeof(i=function(t){ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +"use strict";return t})?i.apply(e,n):i)||(t.exports=s)},function(t,e,o){(function(e){var o=function(t){return t&&t.Math==Math&&t};t.exports=o("object"==typeof globalThis&&globalThis)||o("object"==typeof window&&window)||o("object"==typeof self&&self)||o("object"==typeof e&&e)||Function("return this")()}).call(this,o(24))},function(t,e,o){var i=o(1),n=o(46),s=o(6),r=o(47),a=o(51),l=o(82),c=n("wks"),u=i.Symbol,h=l?u:u&&u.withoutSetter||r;t.exports=function(t){return s(c,t)||(a&&s(u,t)?c[t]=u[t]:c[t]=h("Symbol."+t)),c[t]}},function(t,e,o){var i=o(8);t.exports=function(t){if(!i(t))throw TypeError(String(t)+" is not an object");return t}},function(t,e){t.exports=function(t){try{return!!t()}catch(t){return!0}}},function(t,e){t.exports=function(t){if(null==t)throw TypeError("Can't call method on "+t);return t}},function(t,e){var o={}.hasOwnProperty;t.exports=function(t,e){return o.call(t,e)}},function(t,e,o){var i=o(1),n=o(16).f,s=o(9),r=o(13),a=o(27),l=o(74),c=o(50);t.exports=function(t,e){var o,u,h,p,_,d=t.target,g=t.global,T=t.stat;if(o=g?i:T?i[d]||a(d,{}):(i[d]||{}).prototype)for(u in e){if(p=e[u],h=t.noTargetGet?(_=n(o,u))&&_.value:o[u],!c(g?u:d+(T?".":"#")+u,t.forced)&&void 0!==h){if(typeof p==typeof h)continue;l(p,h)}(t.sham||h&&h.sham)&&s(p,"sham",!0),r(o,u,p,t)}}},function(t,e){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,e,o){var i=o(10),n=o(12),s=o(25);t.exports=i?function(t,e,o){return n.f(t,e,s(1,o))}:function(t,e,o){return t[e]=o,t}},function(t,e,o){var i=o(4);t.exports=!i((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},function(t,e){var o={}.toString;t.exports=function(t){return o.call(t).slice(8,-1)}},function(t,e,o){var i=o(10),n=o(44),s=o(3),r=o(43),a=Object.defineProperty;e.f=i?a:function(t,e,o){if(s(t),e=r(e,!0),s(o),n)try{return a(t,e,o)}catch(t){}if("get"in o||"set"in o)throw TypeError("Accessors not supported");return"value"in o&&(t[e]=o.value),t}},function(t,e,o){var i=o(1),n=o(9),s=o(6),r=o(27),a=o(28),l=o(29),c=l.get,u=l.enforce,h=String(String).split("String");(t.exports=function(t,e,o,a){var l=!!a&&!!a.unsafe,c=!!a&&!!a.enumerable,p=!!a&&!!a.noTargetGet;"function"==typeof o&&("string"!=typeof e||s(o,"name")||n(o,"name",e),u(o).source=h.join("string"==typeof e?e:"")),t!==i?(l?!p&&t[e]&&(c=!0):delete t[e],c?t[e]=o:n(t,e,o)):c?t[e]=o:r(e,o)})(Function.prototype,"toString",(function(){return"function"==typeof this&&c(this).source||a(this)}))},function(t,e){t.exports=!1},function(t,e,o){var i=o(21),n=Math.min;t.exports=function(t){return t>0?n(i(t),9007199254740991):0}},function(t,e,o){var i=o(10),n=o(41),s=o(25),r=o(20),a=o(43),l=o(6),c=o(44),u=Object.getOwnPropertyDescriptor;e.f=i?u:function(t,e){if(t=r(t),e=a(e,!0),c)try{return u(t,e)}catch(t){}if(l(t,e))return s(!n.f.call(t,e),t[e])}},function(t,e,o){var i=o(76),n=o(1),s=function(t){return"function"==typeof t?t:void 0};t.exports=function(t,e){return arguments.length<2?s(i[t])||s(n[t]):i[t]&&i[t][e]||n[t]&&n[t][e]}},function(t,e){t.exports={}},function(t,e,o){"use strict";var i=o(58),n=o(3),s=o(35),r=o(15),a=o(21),l=o(5),c=o(60),u=o(61),h=Math.max,p=Math.min,_=Math.floor,d=/\$([$&'`]|\d\d?|<[^>]*>)/g,g=/\$([$&'`]|\d\d?)/g;i("replace",2,(function(t,e,o,i){var T=i.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE,f=i.REPLACE_KEEPS_$0,E=T?"$":"$0";return[function(o,i){var n=l(this),s=null==o?void 0:o[t];return void 0!==s?s.call(o,n,i):e.call(String(n),o,i)},function(t,i){if(!T&&f||"string"==typeof i&&-1===i.indexOf(E)){var s=o(e,t,this,i);if(s.done)return s.value}var l=n(t),_=String(this),d="function"==typeof i;d||(i=String(i));var g=l.global;if(g){var v=l.unicode;l.lastIndex=0}for(var y=[];;){var S=u(l,_);if(null===S)break;if(y.push(S),!g)break;""===String(S[0])&&(l.lastIndex=c(_,r(l.lastIndex),v))}for(var I,R="",b=0,O=0;O=b&&(R+=_.slice(b,k)+M,b=k+C.length)}return R+_.slice(b)}];function m(t,o,i,n,r,a){var l=i+t.length,c=n.length,u=g;return void 0!==r&&(r=s(r),u=d),e.call(a,u,(function(e,s){var a;switch(s.charAt(0)){case"$":return"$";case"&":return t;case"`":return o.slice(0,i);case"'":return o.slice(l);case"<":a=r[s.slice(1,-1)];break;default:var u=+s;if(0===u)return e;if(u>c){var h=_(u/10);return 0===h?e:h<=c?void 0===n[h-1]?s.charAt(1):n[h-1]+s.charAt(1):e}a=n[u-1]}return void 0===a?"":a}))}}))},function(t,e,o){var i=o(42),n=o(5);t.exports=function(t){return i(n(t))}},function(t,e){var o=Math.ceil,i=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?i:o)(t)}},function(t,e){t.exports=function(t){if("function"!=typeof t)throw TypeError(String(t)+" is not a function");return t}},function(t,e,o){var i=o(1),n=o(102),s=o(103),r=o(9),a=o(2),l=a("iterator"),c=a("toStringTag"),u=s.values;for(var h in n){var p=i[h],_=p&&p.prototype;if(_){if(_[l]!==u)try{r(_,l,u)}catch(t){_[l]=u}if(_[c]||r(_,c,h),n[h])for(var d in s)if(_[d]!==s[d])try{r(_,d,s[d])}catch(t){_[d]=s[d]}}}},function(t,e){var o;o=function(){return this}();try{o=o||new Function("return this")()}catch(t){"object"==typeof window&&(o=window)}t.exports=o},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,o){var i=o(1),n=o(8),s=i.document,r=n(s)&&n(s.createElement);t.exports=function(t){return r?s.createElement(t):{}}},function(t,e,o){var i=o(1),n=o(9);t.exports=function(t,e){try{n(i,t,e)}catch(o){i[t]=e}return e}},function(t,e,o){var i=o(45),n=Function.toString;"function"!=typeof i.inspectSource&&(i.inspectSource=function(t){return n.call(t)}),t.exports=i.inspectSource},function(t,e,o){var i,n,s,r=o(73),a=o(1),l=o(8),c=o(9),u=o(6),h=o(30),p=o(31),_=a.WeakMap;if(r){var d=new _,g=d.get,T=d.has,f=d.set;i=function(t,e){return f.call(d,t,e),e},n=function(t){return g.call(d,t)||{}},s=function(t){return T.call(d,t)}}else{var E=h("state");p[E]=!0,i=function(t,e){return c(t,E,e),e},n=function(t){return u(t,E)?t[E]:{}},s=function(t){return u(t,E)}}t.exports={set:i,get:n,has:s,enforce:function(t){return s(t)?n(t):i(t,{})},getterFor:function(t){return function(e){var o;if(!l(e)||(o=n(e)).type!==t)throw TypeError("Incompatible receiver, "+t+" required");return o}}}},function(t,e,o){var i=o(46),n=o(47),s=i("keys");t.exports=function(t){return s[t]||(s[t]=n(t))}},function(t,e){t.exports={}},function(t,e){t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},function(t,e,o){var i=o(12).f,n=o(6),s=o(2)("toStringTag");t.exports=function(t,e,o){t&&!n(t=o?t:t.prototype,s)&&i(t,s,{configurable:!0,value:e})}},function(t,e,o){"use strict";var i,n,s=o(59),r=o(99),a=RegExp.prototype.exec,l=String.prototype.replace,c=a,u=(i=/a/,n=/b*/g,a.call(i,"a"),a.call(n,"a"),0!==i.lastIndex||0!==n.lastIndex),h=r.UNSUPPORTED_Y||r.BROKEN_CARET,p=void 0!==/()??/.exec("")[1];(u||p||h)&&(c=function(t){var e,o,i,n,r=this,c=h&&r.sticky,_=s.call(r),d=r.source,g=0,T=t;return c&&(-1===(_=_.replace("y","")).indexOf("g")&&(_+="g"),T=String(t).slice(r.lastIndex),r.lastIndex>0&&(!r.multiline||r.multiline&&"\n"!==t[r.lastIndex-1])&&(d="(?: "+d+")",T=" "+T,g++),o=new RegExp("^(?:"+d+")",_)),p&&(o=new RegExp("^"+d+"$(?!\\s)",_)),u&&(e=r.lastIndex),i=a.call(c?o:r,T),c?i?(i.input=i.input.slice(g),i[0]=i[0].slice(g),i.index=r.lastIndex,r.lastIndex+=i[0].length):r.lastIndex=0:u&&i&&(r.lastIndex=r.global?i.index+i[0].length:e),p&&i&&i.length>1&&l.call(i[0],o,(function(){for(n=1;ne&&0<=o&&256>o&&0<=i&&256>i)?t.utils.colour.rgbToHex(e,o,i):null},t.utils.colour.rgbToHex=function(t,e,o){return e=t<<16|e<<8|o,16>t?"#"+(16777216|e).toString(16).substr(1):"#"+e.toString(16)},t.utils.colour.hexToRgb=function(e){return(e=t.utils.colour.parse(e))?[(e=parseInt(e.substr(1),16))>>16,e>>8&255,255&e]:[0,0,0]},t.utils.colour.hsvToHex=function(e,o,i){var n=0,s=0,r=0;if(0==o)r=s=n=i;else{var a=Math.floor(e/60),l=e/60-a;e=i*(1-o);var c=i*(1-o*l);switch(o=i*(1-o*(1-l)),a){case 1:n=c,s=i,r=e;break;case 2:n=e,s=i,r=o;break;case 3:n=e,s=c,r=i;break;case 4:n=o,s=e,r=i;break;case 5:n=i,s=e,r=c;break;case 6:case 0:n=i,s=o,r=e}}return t.utils.colour.rgbToHex(Math.floor(n),Math.floor(s),Math.floor(r))},t.utils.colour.blend=function(e,o,i){return(e=t.utils.colour.parse(e))&&(o=t.utils.colour.parse(o))?(e=t.utils.colour.hexToRgb(e),o=t.utils.colour.hexToRgb(o),t.utils.colour.rgbToHex(Math.round(o[0]+i*(e[0]-o[0])),Math.round(o[1]+i*(e[1]-o[1])),Math.round(o[2]+i*(e[2]-o[2])))):null},t.utils.colour.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00"},t.utils.Coordinate=function(t,e){this.x=t,this.y=e},t.utils.Coordinate.equals=function(t,e){return t==e||!(!t||!e)&&t.x==e.x&&t.y==e.y},t.utils.Coordinate.distance=function(t,e){var o=t.x-e.x;return t=t.y-e.y,Math.sqrt(o*o+t*t)},t.utils.Coordinate.magnitude=function(t){return Math.sqrt(t.x*t.x+t.y*t.y)},t.utils.Coordinate.difference=function(e,o){return new t.utils.Coordinate(e.x-o.x,e.y-o.y)},t.utils.Coordinate.sum=function(e,o){return new t.utils.Coordinate(e.x+o.x,e.y+o.y)},t.utils.Coordinate.prototype.scale=function(t){return this.x*=t,this.y*=t,this},t.utils.Coordinate.prototype.translate=function(t,e){return this.x+=t,this.y+=e,this},t.utils.Rect=function(t,e,o,i){this.top=t,this.bottom=e,this.left=o,this.right=i},t.utils.Rect.prototype.contains=function(t,e){return t>=this.left&&t<=this.right&&e>=this.top&&e<=this.bottom},t.utils.string={},t.utils.string.startsWith=function(t,e){return 0==t.lastIndexOf(e,0)},t.utils.string.shortestStringLength=function(t){return t.length?t.reduce((function(t,e){return t.lengtho&&(o=i[n].length);n=-1/0;var s=1;do{var r=n,a=e;e=[];var l=i.length/s,c=1;for(n=0;nr);return a},t.utils.string.wrapScore_=function(t,e,o){for(var i=[0],n=[],s=0;ss&&(s=l,n=a)}return n?t.utils.string.wrapMutate_(e,n,i):o},t.utils.string.wrapToText_=function(t,e){for(var o=[],i=0;i=l?(s=2,r=l,(l=e.join(""))&&i.push(l),e.length=0):"{"==l?s=3:(e.push("%",l),s=0):2==s?"0"<=l&&"9">=l?r+=l:(i.push(parseInt(r,10)),a--,s=0):3==s&&(""==l?(e.splice(0,0,"%{"),a--,s=0):"}"!=l?e.push(l):(s=e.join(""),/[A-Z]\w*/i.test(s)?(l=s.toUpperCase(),(l=t.utils.string.startsWith(l,"BKY_")?l.substring(4):null)&&l in t.Msg?"string"==typeof(s=t.Msg[l])?Array.prototype.push.apply(i,t.utils.tokenizeInterpolation_(s,o)):o?i.push(String(s)):i.push(s):i.push("%{"+s+"}")):i.push("%{"+s+"}"),s=e.length=0))}for((l=e.join(""))&&i.push(l),o=[],a=e.length=0;ai;i++)o[i]=t.utils.genUid.soup_.charAt(Math.random()*e);return o.join("")},t.utils.genUid.soup_="!#$%()*+,-./:;=?@[]^_`{|}~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",t.utils.is3dSupported=function(){if(void 0!==t.utils.is3dSupported.cached_)return t.utils.is3dSupported.cached_;if(!t.utils.global.getComputedStyle)return!1;var e=document.createElement("p"),o="none",i={webkitTransform:"-webkit-transform",OTransform:"-o-transform",msTransform:"-ms-transform",MozTransform:"-moz-transform",transform:"transform"};for(var n in document.body.insertBefore(e,null),i)if(void 0!==e.style[n]){if(e.style[n]="translate3d(1px,1px,1px)",!(o=t.utils.global.getComputedStyle(e)))return document.body.removeChild(e),!1;o=o.getPropertyValue(i[n])}return document.body.removeChild(e),t.utils.is3dSupported.cached_="none"!==o,t.utils.is3dSupported.cached_},t.utils.runAfterPageLoad=function(t){if("object"!=typeof document)throw Error("Blockly.utils.runAfterPageLoad() requires browser document.");if("complete"==document.readyState)t();else var e=setInterval((function(){"complete"==document.readyState&&(clearInterval(e),t())}),10)},t.utils.getViewportBBox=function(){var e=t.utils.style.getViewportPageOffset();return new t.utils.Rect(e.y,document.documentElement.clientHeight+e.y,e.x,document.documentElement.clientWidth+e.x)},t.utils.arrayRemove=function(t,e){return-1!=(e=t.indexOf(e))&&(t.splice(e,1),!0)},t.utils.getDocumentScroll=function(){var e=document.documentElement,o=window;return t.utils.userAgent.IE&&o.pageYOffset!=e.scrollTop?new t.utils.Coordinate(e.scrollLeft,e.scrollTop):new t.utils.Coordinate(o.pageXOffset||e.scrollLeft,o.pageYOffset||e.scrollTop)},t.utils.getBlockTypeCounts=function(t,e){var o=Object.create(null),i=t.getDescendants(!0);for(e&&(t=t.getNextBlock())&&(t=i.indexOf(t),i.splice(t,i.length-t)),t=0;e=i[t];t++)o[e.type]?o[e.type]++:o[e.type]=1;return o},t.utils.screenToWsCoordinates=function(e,o){var i=o.x;o=o.y;var n=e.getInjectionDiv().getBoundingClientRect();return i=new t.utils.Coordinate(i-n.left,o-n.top),o=e.getOriginOffsetInPixels(),t.utils.Coordinate.difference(i,o).scale(1/e.scale)},t.utils.parseBlockColour=function(e){var o="string"==typeof e?t.utils.replaceMessageReferences(e):e,i=Number(o);if(!isNaN(i)&&0<=i&&360>=i)return{hue:i,hex:t.utils.colour.hsvToHex(i,t.HSV_SATURATION,255*t.HSV_VALUE)};if(i=t.utils.colour.parse(o))return{hue:null,hex:i};throw i='Invalid colour: "'+o+'"',e!=o&&(i+=' (from "'+e+'")'),Error(i)},t.Events={},t.Events.group_="",t.Events.recordUndo=!0,t.Events.disabled_=0,t.Events.CREATE="create",t.Events.BLOCK_CREATE=t.Events.CREATE,t.Events.DELETE="delete",t.Events.BLOCK_DELETE=t.Events.DELETE,t.Events.CHANGE="change",t.Events.BLOCK_CHANGE=t.Events.CHANGE,t.Events.MOVE="move",t.Events.BLOCK_MOVE=t.Events.MOVE,t.Events.VAR_CREATE="var_create",t.Events.VAR_DELETE="var_delete",t.Events.VAR_RENAME="var_rename",t.Events.UI="ui",t.Events.COMMENT_CREATE="comment_create",t.Events.COMMENT_DELETE="comment_delete",t.Events.COMMENT_CHANGE="comment_change",t.Events.COMMENT_MOVE="comment_move",t.Events.FINISHED_LOADING="finished_loading",t.Events.BUMP_EVENTS=[t.Events.BLOCK_CREATE,t.Events.BLOCK_MOVE,t.Events.COMMENT_CREATE,t.Events.COMMENT_MOVE],t.Events.FIRE_QUEUE_=[],t.Events.fire=function(e){t.Events.isEnabled()&&(t.Events.FIRE_QUEUE_.length||setTimeout(t.Events.fireNow_,0),t.Events.FIRE_QUEUE_.push(e))},t.Events.fireNow_=function(){for(var e,o=t.Events.filter(t.Events.FIRE_QUEUE_,!0),i=t.Events.FIRE_QUEUE_.length=0;e=o[i];i++)if(e.workspaceId){var n=t.Workspace.getById(e.workspaceId);n&&n.fireChangeListener(e)}},t.Events.filter=function(e,o){e=e.slice(),o||e.reverse();for(var i,n=[],s=Object.create(null),r=0;i=e[r];r++)if(!i.isNull()){var a=[i.type,i.blockId,i.workspaceId].join(" "),l=s[a],c=l?l.event:null;l?i.type==t.Events.MOVE&&l.index==r-1?(c.newParentId=i.newParentId,c.newInputName=i.newInputName,c.newCoordinate=i.newCoordinate,l.index=r):i.type==t.Events.CHANGE&&i.element==c.element&&i.name==c.name?c.newValue=i.newValue:(i.type!=t.Events.UI||"click"!=i.element||"commentOpen"!=c.element&&"mutatorOpen"!=c.element&&"warningOpen"!=c.element)&&(s[a]={event:i,index:1},n.push(i)):(s[a]={event:i,index:r},n.push(i))}for(e=n.filter((function(t){return!t.isNull()})),o||e.reverse(),r=1;i=e[r];r++)i.type==t.Events.CHANGE&&"mutation"==i.element&&e.unshift(e.splice(r,1)[0]);return e},t.Events.clearPendingUndo=function(){for(var e,o=0;e=t.Events.FIRE_QUEUE_[o];o++)e.recordUndo=!1},t.Events.disable=function(){t.Events.disabled_++},t.Events.enable=function(){t.Events.disabled_--},t.Events.isEnabled=function(){return 0==t.Events.disabled_},t.Events.getGroup=function(){return t.Events.group_},t.Events.setGroup=function(e){t.Events.group_="boolean"==typeof e?e?t.utils.genUid():"":e},t.Events.getDescendantIds=function(t){var e=[];t=t.getDescendants(!1);for(var o,i=0;o=t[i];i++)e[i]=o.id;return e},t.Events.fromJson=function(e,o){var i=t.registry.getClass(t.registry.Type.EVENT,e.type);if(!i)throw Error("Unknown event type.");return(i=new i).fromJson(e),i.workspaceId=o.id,i},t.Events.disableOrphans=function(e){if((e.type==t.Events.MOVE||e.type==t.Events.CREATE)&&e.workspaceId){var o=t.Workspace.getById(e.workspaceId);if(e=o.getBlockById(e.blockId)){var i=e.getParent();if(i&&i.isEnabled())for(o=e.getDescendants(!1),e=0;i=o[e];e++)i.setEnabled(!0);else if((e.outputConnection||e.previousConnection)&&!o.isDragging())do{e.setEnabled(!1),e=e.getNextBlock()}while(e)}}},t.Events.Abstract=function(){this.isBlank=null,this.workspaceId=void 0,this.group=t.Events.getGroup(),this.recordUndo=t.Events.recordUndo},t.Events.Abstract.prototype.toJson=function(){var t={type:this.type};return this.group&&(t.group=this.group),t},t.Events.Abstract.prototype.fromJson=function(t){this.isBlank=!1,this.group=t.group},t.Events.Abstract.prototype.isNull=function(){return!1},t.Events.Abstract.prototype.run=function(t){},t.Events.Abstract.prototype.getEventWorkspace_=function(){if(this.workspaceId)var e=t.Workspace.getById(this.workspaceId);if(!e)throw Error("Workspace is null. Event must have been generated from real Blockly events.");return e},t.utils.object={},t.utils.object.inherits=function(t,e){t.superClass_=e.prototype,t.prototype=Object.create(e.prototype),t.prototype.constructor=t},t.utils.object.mixin=function(t,e){for(var o in e)t[o]=e[o]},t.utils.object.deepMerge=function(e,o){for(var i in o)e[i]=null!=o[i]&&"object"==typeof o[i]?t.utils.object.deepMerge(e[i]||Object.create(null),o[i]):o[i];return e},t.utils.object.values=function(t){return Object.values?Object.values(t):Object.keys(t).map((function(e){return t[e]}))},t.Events.Ui=function(e,o,i,n){t.Events.Ui.superClass_.constructor.call(this),this.isBlank=void 0===e,this.blockId=e?e.id:null,this.workspaceId=e?e.workspace.id:void 0,this.element=void 0===o?"":o,this.oldValue=void 0===i?"":i,this.newValue=void 0===n?"":n,this.recordUndo=!1},t.utils.object.inherits(t.Events.Ui,t.Events.Abstract),t.Events.Ui.prototype.type=t.Events.UI,t.Events.Ui.prototype.toJson=function(){var e=t.Events.Ui.superClass_.toJson.call(this);return e.element=this.element,void 0!==this.newValue&&(e.newValue=this.newValue),this.blockId&&(e.blockId=this.blockId),e},t.Events.Ui.prototype.fromJson=function(e){t.Events.Ui.superClass_.fromJson.call(this,e),this.element=e.element,this.newValue=e.newValue,this.blockId=e.blockId},t.registry.register(t.registry.Type.EVENT,t.Events.UI,t.Events.Ui),t.utils.Svg=function(t){this.tagName_=t},t.utils.Svg.prototype.toString=function(){return this.tagName_},t.utils.Svg.ANIMATE=new t.utils.Svg("animate"),t.utils.Svg.CIRCLE=new t.utils.Svg("circle"),t.utils.Svg.CLIPPATH=new t.utils.Svg("clipPath"),t.utils.Svg.DEFS=new t.utils.Svg("defs"),t.utils.Svg.FECOMPOSITE=new t.utils.Svg("feComposite"),t.utils.Svg.FECOMPONENTTRANSFER=new t.utils.Svg("feComponentTransfer"),t.utils.Svg.FEFLOOD=new t.utils.Svg("feFlood"),t.utils.Svg.FEFUNCA=new t.utils.Svg("feFuncA"),t.utils.Svg.FEGAUSSIANBLUR=new t.utils.Svg("feGaussianBlur"),t.utils.Svg.FEPOINTLIGHT=new t.utils.Svg("fePointLight"),t.utils.Svg.FESPECULARLIGHTING=new t.utils.Svg("feSpecularLighting"),t.utils.Svg.FILTER=new t.utils.Svg("filter"),t.utils.Svg.FOREIGNOBJECT=new t.utils.Svg("foreignObject"),t.utils.Svg.G=new t.utils.Svg("g"),t.utils.Svg.IMAGE=new t.utils.Svg("image"),t.utils.Svg.LINE=new t.utils.Svg("line"),t.utils.Svg.PATH=new t.utils.Svg("path"),t.utils.Svg.PATTERN=new t.utils.Svg("pattern"),t.utils.Svg.POLYGON=new t.utils.Svg("polygon"),t.utils.Svg.RECT=new t.utils.Svg("rect"),t.utils.Svg.SVG=new t.utils.Svg("svg"),t.utils.Svg.TEXT=new t.utils.Svg("text"),t.utils.Svg.TSPAN=new t.utils.Svg("tspan"),t.utils.dom={},t.utils.dom.SVG_NS="http://www.w3.org/2000/svg",t.utils.dom.HTML_NS="http://www.w3.org/1999/xhtml",t.utils.dom.XLINK_NS="http://www.w3.org/1999/xlink",t.utils.dom.NodeType={ELEMENT_NODE:1,TEXT_NODE:3,COMMENT_NODE:8,DOCUMENT_POSITION_CONTAINED_BY:16},t.utils.dom.cacheWidths_=null,t.utils.dom.cacheReference_=0,t.utils.dom.canvasContext_=null,t.utils.dom.createSvgElement=function(e,o,i){for(var n in e=document.createElementNS(t.utils.dom.SVG_NS,String(e)),o)e.setAttribute(n,o[n]);return document.body.runtimeStyle&&(e.runtimeStyle=e.currentStyle=e.style),i&&i.appendChild(e),e},t.utils.dom.addClass=function(t,e){var o=t.getAttribute("class")||"";return-1==(" "+o+" ").indexOf(" "+e+" ")&&(o&&(o+=" "),t.setAttribute("class",o+e),!0)},t.utils.dom.removeClasses=function(e,o){o=o.split(" ");for(var i=0;io||o>this.getChildCount())throw Error(t.Component.Error.CHILD_INDEX_OUT_OF_BOUNDS);if(this.childIndex_[e.getId()]=e,e.getParent()==this){var n=this.children_.indexOf(e);-1>>/g,e),(e=document.createElement("style")).id="blockly-common-style",i=document.createTextNode(i),e.appendChild(i),document.head.insertBefore(e,document.head.firstChild))}},t.Css.CONTENT=[".blocklySvg {","background-color: #fff;","outline: none;","overflow: hidden;","position: absolute;","display: block;","}",".blocklyWidgetDiv {","display: none;","position: absolute;","z-index: 99999;","}",".injectionDiv {","height: 100%;","position: relative;","overflow: hidden;","touch-action: none;","}",".blocklyNonSelectable {","user-select: none;","-ms-user-select: none;","-webkit-user-select: none;","}",".blocklyWsDragSurface {","display: none;","position: absolute;","top: 0;","left: 0;","}",".blocklyWsDragSurface.blocklyOverflowVisible {","overflow: visible;","}",".blocklyBlockDragSurface {","display: none;","position: absolute;","top: 0;","left: 0;","right: 0;","bottom: 0;","overflow: visible !important;","z-index: 50;","}",".blocklyBlockCanvas.blocklyCanvasTransitioning,",".blocklyBubbleCanvas.blocklyCanvasTransitioning {","transition: transform .5s;","}",".blocklyTooltipDiv {","background-color: #ffffc7;","border: 1px solid #ddc;","box-shadow: 4px 4px 20px 1px rgba(0,0,0,.15);","color: #000;","display: none;","font: 9pt sans-serif;","opacity: .9;","padding: 2px;","position: absolute;","z-index: 100000;","}",".blocklyDropDownDiv {","position: absolute;","left: 0;","top: 0;","z-index: 1000;","display: none;","border: 1px solid;","border-color: #dadce0;","background-color: #fff;","border-radius: 2px;","padding: 4px;","box-shadow: 0 0 3px 1px rgba(0,0,0,.3);","}",".blocklyDropDownDiv.blocklyFocused {","box-shadow: 0 0 6px 1px rgba(0,0,0,.3);","}",".blocklyDropDownContent {","max-height: 300px;","overflow: auto;","overflow-x: hidden;","position: relative;","}",".blocklyDropDownArrow {","position: absolute;","left: 0;","top: 0;","width: 16px;","height: 16px;","z-index: -1;","background-color: inherit;","border-color: inherit;","}",".blocklyDropDownButton {","display: inline-block;","float: left;","padding: 0;","margin: 4px;","border-radius: 4px;","outline: none;","border: 1px solid;","transition: box-shadow .1s;","cursor: pointer;","}",".blocklyArrowTop {","border-top: 1px solid;","border-left: 1px solid;","border-top-left-radius: 4px;","border-color: inherit;","}",".blocklyArrowBottom {","border-bottom: 1px solid;","border-right: 1px solid;","border-bottom-right-radius: 4px;","border-color: inherit;","}",".blocklyResizeSE {","cursor: se-resize;","fill: #aaa;","}",".blocklyResizeSW {","cursor: sw-resize;","fill: #aaa;","}",".blocklyResizeLine {","stroke: #515A5A;","stroke-width: 1;","}",".blocklyHighlightedConnectionPath {","fill: none;","stroke: #fc3;","stroke-width: 4px;","}",".blocklyPathLight {","fill: none;","stroke-linecap: round;","stroke-width: 1;","}",".blocklySelected>.blocklyPathLight {","display: none;","}",".blocklyDraggable {",'cursor: url("<<>>/handopen.cur"), auto;',"cursor: grab;","cursor: -webkit-grab;","}",".blocklyDragging {",'cursor: url("<<>>/handclosed.cur"), auto;',"cursor: grabbing;","cursor: -webkit-grabbing;","}",".blocklyDraggable:active {",'cursor: url("<<>>/handclosed.cur"), auto;',"cursor: grabbing;","cursor: -webkit-grabbing;","}",".blocklyBlockDragSurface .blocklyDraggable {",'cursor: url("<<>>/handclosed.cur"), auto;',"cursor: grabbing;","cursor: -webkit-grabbing;","}",".blocklyDragging.blocklyDraggingDelete {",'cursor: url("<<>>/handdelete.cur"), auto;',"}",".blocklyDragging>.blocklyPath,",".blocklyDragging>.blocklyPathLight {","fill-opacity: .8;","stroke-opacity: .8;","}",".blocklyDragging>.blocklyPathDark {","display: none;","}",".blocklyDisabled>.blocklyPath {","fill-opacity: .5;","stroke-opacity: .5;","}",".blocklyDisabled>.blocklyPathLight,",".blocklyDisabled>.blocklyPathDark {","display: none;","}",".blocklyInsertionMarker>.blocklyPath,",".blocklyInsertionMarker>.blocklyPathLight,",".blocklyInsertionMarker>.blocklyPathDark {","fill-opacity: .2;","stroke: none;","}",".blocklyMultilineText {","font-family: monospace;","}",".blocklyNonEditableText>text {","pointer-events: none;","}",".blocklyFlyout {","position: absolute;","z-index: 20;","}",".blocklyText text {","cursor: default;","}",".blocklySvg text,",".blocklyBlockDragSurface text {","user-select: none;","-ms-user-select: none;","-webkit-user-select: none;","cursor: inherit;","}",".blocklyHidden {","display: none;","}",".blocklyFieldDropdown:not(.blocklyHidden) {","display: block;","}",".blocklyIconGroup {","cursor: default;","}",".blocklyIconGroup:not(:hover),",".blocklyIconGroupReadonly {","opacity: .6;","}",".blocklyIconShape {","fill: #00f;","stroke: #fff;","stroke-width: 1px;","}",".blocklyIconSymbol {","fill: #fff;","}",".blocklyMinimalBody {","margin: 0;","padding: 0;","}",".blocklyHtmlInput {","border: none;","border-radius: 4px;","height: 100%;","margin: 0;","outline: none;","padding: 0;","width: 100%;","text-align: center;","display: block;","box-sizing: border-box;","}",".blocklyHtmlInput::-ms-clear {","display: none;","}",".blocklyMainBackground {","stroke-width: 1;","stroke: #c6c6c6;","}",".blocklyMutatorBackground {","fill: #fff;","stroke: #ddd;","stroke-width: 1;","}",".blocklyFlyoutBackground {","fill: #ddd;","fill-opacity: .8;","}",".blocklyMainWorkspaceScrollbar {","z-index: 20;","}",".blocklyFlyoutScrollbar {","z-index: 30;","}",".blocklyScrollbarHorizontal,",".blocklyScrollbarVertical {","position: absolute;","outline: none;","}",".blocklyScrollbarBackground {","opacity: 0;","}",".blocklyScrollbarHandle {","fill: #ccc;","}",".blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,",".blocklyScrollbarHandle:hover {","fill: #bbb;","}",".blocklyFlyout .blocklyScrollbarHandle {","fill: #bbb;","}",".blocklyFlyout .blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,",".blocklyFlyout .blocklyScrollbarHandle:hover {","fill: #aaa;","}",".blocklyInvalidInput {","background: #faa;","}",".blocklyVerticalMarker {","stroke-width: 3px;","fill: rgba(255,255,255,.5);","pointer-events: none;","}",".blocklyComputeCanvas {","position: absolute;","width: 0;","height: 0;","}",".blocklyNoPointerEvents {","pointer-events: none;","}",".blocklyContextMenu {","border-radius: 4px;","max-height: 100%;","}",".blocklyDropdownMenu {","border-radius: 2px;","padding: 0 !important;","}",".blocklyDropdownMenu .blocklyMenuItem {","padding-left: 28px;","}",".blocklyDropdownMenu .blocklyMenuItemRtl {","padding-left: 5px;","padding-right: 28px;","}",".blocklyWidgetDiv .blocklyMenu {","background: #fff;","border: 1px solid transparent;","box-shadow: 0 0 3px 1px rgba(0,0,0,.3);","font: normal 13px Arial, sans-serif;","margin: 0;","outline: none;","padding: 4px 0;","position: absolute;","overflow-y: auto;","overflow-x: hidden;","max-height: 100%;","z-index: 20000;","}",".blocklyWidgetDiv .blocklyMenu.blocklyFocused {","box-shadow: 0 0 6px 1px rgba(0,0,0,.3);","}",".blocklyDropDownDiv .blocklyMenu {",'font: normal 13px "Helvetica Neue", Helvetica, sans-serif;',"outline: none;","z-index: 20000;","}",".blocklyMenuItem {","border: none;","color: #000;","cursor: pointer;","list-style: none;","margin: 0;","min-width: 7em;","padding: 6px 15px;","white-space: nowrap;","}",".blocklyMenuItemDisabled {","color: #ccc;","cursor: inherit;","}",".blocklyMenuItemHighlight {","background-color: rgba(0,0,0,.1);","}",".blocklyMenuItemCheckbox {","height: 16px;","position: absolute;","width: 16px;","}",".blocklyMenuItemSelected .blocklyMenuItemCheckbox {","background: url(<<>>/sprites.png) no-repeat -48px -16px;","float: left;","margin-left: -24px;","position: static;","}",".blocklyMenuItemRtl .blocklyMenuItemCheckbox {","float: right;","margin-right: -24px;","}"],t.utils.math={},t.utils.math.toRadians=function(t){return t*Math.PI/180},t.utils.math.toDegrees=function(t){return 180*t/Math.PI},t.utils.math.clamp=function(t,e,o){if(os.top?t.DropDownDiv.getPositionAboveMetrics_(i,n,s,r):o+r.heightdocument.documentElement.clientTop?t.DropDownDiv.getPositionAboveMetrics_(i,n,s,r):t.DropDownDiv.getPositionTopOfPageMetrics_(e,s,r)},t.DropDownDiv.getPositionBelowMetrics_=function(e,o,i,n){return{initialX:(e=t.DropDownDiv.getPositionX(e,i.left,i.right,n.width)).divX,initialY:o,finalX:e.divX,finalY:o+t.DropDownDiv.PADDING_Y,arrowX:e.arrowX,arrowY:-(t.DropDownDiv.ARROW_SIZE/2+t.DropDownDiv.BORDER_SIZE),arrowAtTop:!0,arrowVisible:!0}},t.DropDownDiv.getPositionAboveMetrics_=function(e,o,i,n){return{initialX:(e=t.DropDownDiv.getPositionX(e,i.left,i.right,n.width)).divX,initialY:o-n.height,finalX:e.divX,finalY:o-n.height-t.DropDownDiv.PADDING_Y,arrowX:e.arrowX,arrowY:n.height-2*t.DropDownDiv.BORDER_SIZE-t.DropDownDiv.ARROW_SIZE/2,arrowAtTop:!1,arrowVisible:!0}},t.DropDownDiv.getPositionTopOfPageMetrics_=function(e,o,i){return{initialX:(e=t.DropDownDiv.getPositionX(e,o.left,o.right,i.width)).divX,initialY:0,finalX:e.divX,finalY:0,arrowAtTop:null,arrowX:null,arrowY:null,arrowVisible:!1}},t.DropDownDiv.getPositionX=function(e,o,i,n){var s=e;return e=t.utils.math.clamp(o,e-n/2,i-n),s-=t.DropDownDiv.ARROW_SIZE/2,o=t.DropDownDiv.ARROW_HORIZONTAL_PADDING,{arrowX:n=t.utils.math.clamp(o,s-e,n-o-t.DropDownDiv.ARROW_SIZE),divX:e}},t.DropDownDiv.isVisible=function(){return!!t.DropDownDiv.owner_},t.DropDownDiv.hideIfOwner=function(e,o){return t.DropDownDiv.owner_===e&&(o?t.DropDownDiv.hideWithoutAnimation():t.DropDownDiv.hide(),!0)},t.DropDownDiv.hide=function(){var e=t.DropDownDiv.DIV_;e.style.transform="translate(0, 0)",e.style.opacity=0,t.DropDownDiv.animateOutTimer_=setTimeout((function(){t.DropDownDiv.hideWithoutAnimation()}),1e3*t.DropDownDiv.ANIMATION_TIME),t.DropDownDiv.onHide_&&(t.DropDownDiv.onHide_(),t.DropDownDiv.onHide_=null)},t.DropDownDiv.hideWithoutAnimation=function(){if(t.DropDownDiv.isVisible()){t.DropDownDiv.animateOutTimer_&&clearTimeout(t.DropDownDiv.animateOutTimer_);var e=t.DropDownDiv.DIV_;e.style.transform="",e.style.left="",e.style.top="",e.style.opacity=0,e.style.display="none",e.style.backgroundColor="",e.style.borderColor="",t.DropDownDiv.onHide_&&(t.DropDownDiv.onHide_(),t.DropDownDiv.onHide_=null),t.DropDownDiv.clearContent(),t.DropDownDiv.owner_=null,t.DropDownDiv.rendererClassName_&&(t.utils.dom.removeClass(e,t.DropDownDiv.rendererClassName_),t.DropDownDiv.rendererClassName_=""),t.DropDownDiv.themeClassName_&&(t.utils.dom.removeClass(e,t.DropDownDiv.themeClassName_),t.DropDownDiv.themeClassName_=""),t.getMainWorkspace().markFocused()}},t.DropDownDiv.positionInternal_=function(e,o,i,n){(e=t.DropDownDiv.getPositionMetrics_(e,o,i,n)).arrowVisible?(t.DropDownDiv.arrow_.style.display="",t.DropDownDiv.arrow_.style.transform="translate("+e.arrowX+"px,"+e.arrowY+"px) rotate(45deg)",t.DropDownDiv.arrow_.setAttribute("class",e.arrowAtTop?"blocklyDropDownArrow blocklyArrowTop":"blocklyDropDownArrow blocklyArrowBottom")):t.DropDownDiv.arrow_.style.display="none",o=Math.floor(e.initialX),i=Math.floor(e.initialY),n=Math.floor(e.finalX);var s=Math.floor(e.finalY),r=t.DropDownDiv.DIV_;return r.style.left=o+"px",r.style.top=i+"px",r.style.display="block",r.style.opacity=1,r.style.transform="translate("+(n-o)+"px,"+(s-i)+"px)",!!e.arrowAtTop},t.DropDownDiv.repositionForWindowResize=function(){if(t.DropDownDiv.owner_){var e=t.DropDownDiv.owner_,o=e.getSourceBlock();o=(e=t.DropDownDiv.positionToField_?t.DropDownDiv.getScaledBboxOfField_(e):t.DropDownDiv.getScaledBboxOfBlock_(o)).left+(e.right-e.left)/2,t.DropDownDiv.positionInternal_(o,e.bottom,o,e.top)}else t.DropDownDiv.hide()},t.Grid=function(t,e){this.gridPattern_=t,this.spacing_=e.spacing,this.length_=e.length,this.line2_=(this.line1_=t.firstChild)&&this.line1_.nextSibling,this.snapToGrid_=e.snap},t.Grid.prototype.scale_=1,t.Grid.prototype.dispose=function(){this.gridPattern_=null},t.Grid.prototype.shouldSnap=function(){return this.snapToGrid_},t.Grid.prototype.getSpacing=function(){return this.spacing_},t.Grid.prototype.getPatternId=function(){return this.gridPattern_.id},t.Grid.prototype.update=function(t){this.scale_=t;var e=this.spacing_*t||100;this.gridPattern_.setAttribute("width",e),this.gridPattern_.setAttribute("height",e);var o=(e=Math.floor(this.spacing_/2)+.5)-this.length_/2,i=e+this.length_/2;e*=t,o*=t,i*=t,this.setLineAttributes_(this.line1_,t,o,i,e,e),this.setLineAttributes_(this.line2_,t,e,e,o,i)},t.Grid.prototype.setLineAttributes_=function(t,e,o,i,n,s){t&&(t.setAttribute("stroke-width",e),t.setAttribute("x1",o),t.setAttribute("y1",n),t.setAttribute("x2",i),t.setAttribute("y2",s))},t.Grid.prototype.moveTo=function(e,o){this.gridPattern_.setAttribute("x",e),this.gridPattern_.setAttribute("y",o),(t.utils.userAgent.IE||t.utils.userAgent.EDGE)&&this.update(this.scale_)},t.Grid.createDom=function(e,o,i){return e=t.utils.dom.createSvgElement(t.utils.Svg.PATTERN,{id:"blocklyGridPattern"+e,patternUnits:"userSpaceOnUse"},i),0e.indexOf(o))throw Error(o+" is not a valid modifier key.")},t.user.keyMap.createSerializedKey=function(e,o){var i="",n=t.utils.object.values(t.user.keyMap.modifierKeys);t.user.keyMap.checkModifiers_(o,n);for(var s,r=0;s=n[r];r++)-1 document.")}else e=null;return e},t.utils.xml={},t.utils.xml.NAME_SPACE="https://developers.google.com/blockly/xml",t.utils.xml.document=function(){return document},t.utils.xml.createElement=function(e){return t.utils.xml.document().createElementNS(t.utils.xml.NAME_SPACE,e)},t.utils.xml.createTextNode=function(e){return t.utils.xml.document().createTextNode(e)},t.utils.xml.textToDomDocument=function(t){return(new DOMParser).parseFromString(t,"text/xml")},t.utils.xml.domToText=function(t){return(new XMLSerializer).serializeToString(t)},t.Events.BlockBase=function(e){t.Events.BlockBase.superClass_.constructor.call(this),this.blockId=(this.isBlank=void 0===e)?"":e.id,this.workspaceId=this.isBlank?"":e.workspace.id},t.utils.object.inherits(t.Events.BlockBase,t.Events.Abstract),t.Events.BlockBase.prototype.toJson=function(){var e=t.Events.BlockBase.superClass_.toJson.call(this);return e.blockId=this.blockId,e},t.Events.BlockBase.prototype.fromJson=function(e){t.Events.BlockBase.superClass_.fromJson.call(this,e),this.blockId=e.blockId},t.Events.Change=function(e,o,i,n,s){t.Events.Change.superClass_.constructor.call(this,e),e&&(this.element=void 0===o?"":o,this.name=void 0===i?"":i,this.oldValue=void 0===n?"":n,this.newValue=void 0===s?"":s)},t.utils.object.inherits(t.Events.Change,t.Events.BlockBase),t.Events.BlockChange=t.Events.Change,t.Events.Change.prototype.type=t.Events.CHANGE,t.Events.Change.prototype.toJson=function(){var e=t.Events.Change.superClass_.toJson.call(this);return e.element=this.element,this.name&&(e.name=this.name),e.newValue=this.newValue,e},t.Events.Change.prototype.fromJson=function(e){t.Events.Change.superClass_.fromJson.call(this,e),this.element=e.element,this.name=e.name,this.newValue=e.newValue},t.Events.Change.prototype.isNull=function(){return this.oldValue==this.newValue},t.Events.Change.prototype.run=function(e){var o=this.getEventWorkspace_().getBlockById(this.blockId);if(o)switch(o.mutator&&o.mutator.setVisible(!1),e=e?this.newValue:this.oldValue,this.element){case"field":(o=o.getField(this.name))?o.setValue(e):console.warn("Can't set non-existent field: "+this.name);break;case"comment":o.setCommentText(e||null);break;case"collapsed":o.setCollapsed(!!e);break;case"disabled":o.setEnabled(!e);break;case"inline":o.setInputsInline(!!e);break;case"mutation":var i="";if(o.mutationToDom&&(i=(i=o.mutationToDom())&&t.Xml.domToText(i)),o.domToMutation){var n=t.Xml.textToDom(e||"");o.domToMutation(n)}t.Events.fire(new t.Events.Change(o,"mutation",null,i,e));break;default:console.warn("Unknown change type: "+this.element)}else console.warn("Can't change non-existent block: "+this.blockId)},t.Events.Create=function(e){t.Events.Create.superClass_.constructor.call(this,e),e&&(e.isShadow()&&(this.recordUndo=!1),this.xml=e.workspace.rendered?t.Xml.blockToDomWithXY(e):t.Xml.blockToDom(e),this.ids=t.Events.getDescendantIds(e))},t.utils.object.inherits(t.Events.Create,t.Events.BlockBase),t.Events.BlockCreate=t.Events.Create,t.Events.Create.prototype.type=t.Events.CREATE,t.Events.Create.prototype.toJson=function(){var e=t.Events.Create.superClass_.toJson.call(this);return e.xml=t.Xml.domToText(this.xml),e.ids=this.ids,e},t.Events.Create.prototype.fromJson=function(e){t.Events.Create.superClass_.fromJson.call(this,e),this.xml=t.Xml.textToDom(e.xml),this.ids=e.ids},t.Events.Create.prototype.run=function(e){var o=this.getEventWorkspace_();if(e)(e=t.utils.xml.createElement("xml")).appendChild(this.xml),t.Xml.domToWorkspace(e,o);else{e=0;for(var i;i=this.ids[e];e++){var n=o.getBlockById(i);n?n.dispose(!1):i==this.blockId&&console.warn("Can't uncreate non-existent block: "+i)}}},t.Events.Delete=function(e){if(t.Events.Delete.superClass_.constructor.call(this,e),e){if(e.getParent())throw Error("Connected blocks cannot be deleted.");e.isShadow()&&(this.recordUndo=!1),this.oldXml=e.workspace.rendered?t.Xml.blockToDomWithXY(e):t.Xml.blockToDom(e),this.ids=t.Events.getDescendantIds(e)}},t.utils.object.inherits(t.Events.Delete,t.Events.BlockBase),t.Events.BlockDelete=t.Events.Delete,t.Events.Delete.prototype.type=t.Events.DELETE,t.Events.Delete.prototype.toJson=function(){var e=t.Events.Delete.superClass_.toJson.call(this);return e.ids=this.ids,e},t.Events.Delete.prototype.fromJson=function(e){t.Events.Delete.superClass_.fromJson.call(this,e),this.ids=e.ids},t.Events.Delete.prototype.run=function(e){var o=this.getEventWorkspace_();if(e){e=0;for(var i;i=this.ids[e];e++){var n=o.getBlockById(i);n?n.dispose(!1):i==this.blockId&&console.warn("Can't delete non-existent block: "+i)}}else(e=t.utils.xml.createElement("xml")).appendChild(this.oldXml),t.Xml.domToWorkspace(e,o)},t.Events.Move=function(e){t.Events.Move.superClass_.constructor.call(this,e),e&&(e.isShadow()&&(this.recordUndo=!1),e=this.currentLocation_(),this.oldParentId=e.parentId,this.oldInputName=e.inputName,this.oldCoordinate=e.coordinate)},t.utils.object.inherits(t.Events.Move,t.Events.BlockBase),t.Events.BlockMove=t.Events.Move,t.Events.Move.prototype.type=t.Events.MOVE,t.Events.Move.prototype.toJson=function(){var e=t.Events.Move.superClass_.toJson.call(this);return this.newParentId&&(e.newParentId=this.newParentId),this.newInputName&&(e.newInputName=this.newInputName),this.newCoordinate&&(e.newCoordinate=Math.round(this.newCoordinate.x)+","+Math.round(this.newCoordinate.y)),e},t.Events.Move.prototype.fromJson=function(e){t.Events.Move.superClass_.fromJson.call(this,e),this.newParentId=e.newParentId,this.newInputName=e.newInputName,e.newCoordinate&&(e=e.newCoordinate.split(","),this.newCoordinate=new t.utils.Coordinate(Number(e[0]),Number(e[1])))},t.Events.Move.prototype.recordNew=function(){var t=this.currentLocation_();this.newParentId=t.parentId,this.newInputName=t.inputName,this.newCoordinate=t.coordinate},t.Events.Move.prototype.currentLocation_=function(){var t=this.getEventWorkspace_().getBlockById(this.blockId),e={},o=t.getParent();return o?(e.parentId=o.id,(t=o.getInputWithBlock(t))&&(e.inputName=t.name)):e.coordinate=t.getRelativeToSurfaceXY(),e},t.Events.Move.prototype.isNull=function(){return this.oldParentId==this.newParentId&&this.oldInputName==this.newInputName&&t.utils.Coordinate.equals(this.oldCoordinate,this.newCoordinate)},t.Events.Move.prototype.run=function(e){var o=this.getEventWorkspace_(),i=o.getBlockById(this.blockId);if(i){var n=e?this.newParentId:this.oldParentId,s=e?this.newInputName:this.oldInputName;e=e?this.newCoordinate:this.oldCoordinate;var r=null;if(n&&!(r=o.getBlockById(n)))return void console.warn("Can't connect to non-existent block: "+n);if(i.getParent()&&i.unplug(),e)s=i.getRelativeToSurfaceXY(),i.moveBy(e.x-s.x,e.y-s.y);else{if(i=i.outputConnection||i.previousConnection,s){if(o=r.getInput(s))var a=o.connection}else i.type==t.PREVIOUS_STATEMENT&&(a=r.nextConnection);a?i.connect(a):console.warn("Can't connect to non-existent input: "+s)}}else console.warn("Can't move non-existent block: "+this.blockId)},t.registry.register(t.registry.Type.EVENT,t.Events.CREATE,t.Events.Create),t.registry.register(t.registry.Type.EVENT,t.Events.DELETE,t.Events.Delete),t.registry.register(t.registry.Type.EVENT,t.Events.CHANGE,t.Events.Change),t.registry.register(t.registry.Type.EVENT,t.Events.MOVE,t.Events.Move),t.Events.FinishedLoading=function(e){this.isBlank=void 0===e,this.workspaceId=e?e.id:"",this.group=t.Events.getGroup(),this.recordUndo=!1},t.utils.object.inherits(t.Events.FinishedLoading,t.Events.Ui),t.Events.FinishedLoading.prototype.type=t.Events.FINISHED_LOADING,t.Events.FinishedLoading.prototype.toJson=function(){var t={type:this.type};return this.group&&(t.group=this.group),this.workspaceId&&(t.workspaceId=this.workspaceId),t},t.Events.FinishedLoading.prototype.fromJson=function(t){this.isBlank=!1,this.workspaceId=t.workspaceId,this.group=t.group},t.registry.register(t.registry.Type.EVENT,t.Events.FINISHED_LOADING,t.Events.FinishedLoading),t.Events.VarBase=function(e){t.Events.VarBase.superClass_.constructor.call(this),this.varId=(this.isBlank=void 0===e)?"":e.getId(),this.workspaceId=this.isBlank?"":e.workspace.id},t.utils.object.inherits(t.Events.VarBase,t.Events.Abstract),t.Events.VarBase.prototype.toJson=function(){var e=t.Events.VarBase.superClass_.toJson.call(this);return e.varId=this.varId,e},t.Events.VarBase.prototype.fromJson=function(e){t.Events.VarBase.superClass_.toJson.call(this),this.varId=e.varId},t.Events.VarCreate=function(e){t.Events.VarCreate.superClass_.constructor.call(this,e),e&&(this.varType=e.type,this.varName=e.name)},t.utils.object.inherits(t.Events.VarCreate,t.Events.VarBase),t.Events.VarCreate.prototype.type=t.Events.VAR_CREATE,t.Events.VarCreate.prototype.toJson=function(){var e=t.Events.VarCreate.superClass_.toJson.call(this);return e.varType=this.varType,e.varName=this.varName,e},t.Events.VarCreate.prototype.fromJson=function(e){t.Events.VarCreate.superClass_.fromJson.call(this,e),this.varType=e.varType,this.varName=e.varName},t.Events.VarCreate.prototype.run=function(t){var e=this.getEventWorkspace_();t?e.createVariable(this.varName,this.varType,this.varId):e.deleteVariableById(this.varId)},t.Events.VarDelete=function(e){t.Events.VarDelete.superClass_.constructor.call(this,e),e&&(this.varType=e.type,this.varName=e.name)},t.utils.object.inherits(t.Events.VarDelete,t.Events.VarBase),t.Events.VarDelete.prototype.type=t.Events.VAR_DELETE,t.Events.VarDelete.prototype.toJson=function(){var e=t.Events.VarDelete.superClass_.toJson.call(this);return e.varType=this.varType,e.varName=this.varName,e},t.Events.VarDelete.prototype.fromJson=function(e){t.Events.VarDelete.superClass_.fromJson.call(this,e),this.varType=e.varType,this.varName=e.varName},t.Events.VarDelete.prototype.run=function(t){var e=this.getEventWorkspace_();t?e.deleteVariableById(this.varId):e.createVariable(this.varName,this.varType,this.varId)},t.Events.VarRename=function(e,o){t.Events.VarRename.superClass_.constructor.call(this,e),e&&(this.oldName=e.name,this.newName=void 0===o?"":o)},t.utils.object.inherits(t.Events.VarRename,t.Events.VarBase),t.Events.VarRename.prototype.type=t.Events.VAR_RENAME,t.Events.VarRename.prototype.toJson=function(){var e=t.Events.VarRename.superClass_.toJson.call(this);return e.oldName=this.oldName,e.newName=this.newName,e},t.Events.VarRename.prototype.fromJson=function(e){t.Events.VarRename.superClass_.fromJson.call(this,e),this.oldName=e.oldName,this.newName=e.newName},t.Events.VarRename.prototype.run=function(t){var e=this.getEventWorkspace_();t?e.renameVariableById(this.varId,this.newName):e.renameVariableById(this.varId,this.oldName)},t.registry.register(t.registry.Type.EVENT,t.Events.VAR_CREATE,t.Events.VarCreate),t.registry.register(t.registry.Type.EVENT,t.Events.VAR_DELETE,t.Events.VarDelete),t.registry.register(t.registry.Type.EVENT,t.Events.VAR_RENAME,t.Events.VarRename),t.Xml={},t.Xml.workspaceToDom=function(e,o){var i=t.utils.xml.createElement("xml"),n=t.Xml.variablesToDom(t.Variables.allUsedVarModels(e));n.hasChildNodes()&&i.appendChild(n);var s,r=e.getTopComments(!0);for(n=0;s=r[n];n++)i.appendChild(s.toXmlWithXY(o));for(e=e.getTopBlocks(!0),n=0;r=e[n];n++)i.appendChild(t.Xml.blockToDomWithXY(r,o));return i},t.Xml.variablesToDom=function(e){for(var o,i=t.utils.xml.createElement("variables"),n=0;o=e[n];n++){var s=t.utils.xml.createElement("variable");s.appendChild(t.utils.xml.createTextNode(o.name)),o.type&&s.setAttribute("type",o.type),s.id=o.getId(),i.appendChild(s)}return i},t.Xml.blockToDomWithXY=function(e,o){if(e.isInsertionMarker()&&!(e=e.getChildren(!1)[0]))return new DocumentFragment;var i;e.workspace.RTL&&(i=e.workspace.getWidth()),o=t.Xml.blockToDom(e,o);var n=e.getRelativeToSurfaceXY();return o.setAttribute("x",Math.round(e.workspace.RTL?i-n.x:n.x)),o.setAttribute("y",Math.round(n.y)),o},t.Xml.fieldToDom_=function(e){if(e.isSerializable()){var o=t.utils.xml.createElement("field");return o.setAttribute("name",e.name||""),e.toXml(o)}return null},t.Xml.allFieldsToDom_=function(e,o){for(var i,n=0;i=e.inputList[n];n++)for(var s,r=0;s=i.fieldRow[r];r++)(s=t.Xml.fieldToDom_(s))&&o.appendChild(s)},t.Xml.blockToDom=function(e,o){if(e.isInsertionMarker())return(e=e.getChildren(!1)[0])?t.Xml.blockToDom(e):new DocumentFragment;var i=t.utils.xml.createElement(e.isShadow()?"shadow":"block");if(i.setAttribute("type",e.type),o||i.setAttribute("id",e.id),e.mutationToDom){var n=e.mutationToDom();n&&(n.hasChildNodes()||n.hasAttributes())&&i.appendChild(n)}if(t.Xml.allFieldsToDom_(e,i),n=e.getCommentText()){var s=e.commentModel.size,r=e.commentModel.pinned,a=t.utils.xml.createElement("comment");a.appendChild(t.utils.xml.createTextNode(n)),a.setAttribute("pinned",r),a.setAttribute("h",s.height),a.setAttribute("w",s.width),i.appendChild(a)}for(e.data&&((n=t.utils.xml.createElement("data")).appendChild(t.utils.xml.createTextNode(e.data)),i.appendChild(n)),n=0;s=e.inputList[n];n++){var l;if(r=!0,s.type!=t.DUMMY_INPUT){var c=s.connection.targetBlock();s.type==t.INPUT_VALUE?l=t.utils.xml.createElement("value"):s.type==t.NEXT_STATEMENT&&(l=t.utils.xml.createElement("statement")),!(a=s.connection.getShadowDom())||c&&c.isShadow()||l.appendChild(t.Xml.cloneShadow_(a,o)),c&&(a=t.Xml.blockToDom(c,o)).nodeType==t.utils.dom.NodeType.ELEMENT_NODE&&(l.appendChild(a),r=!1),l.setAttribute("name",s.name),r||i.appendChild(l)}}return null!=e.inputsInline&&e.inputsInline!=e.inputsInlineDefault&&i.setAttribute("inline",e.inputsInline),e.isCollapsed()&&i.setAttribute("collapsed",!0),e.isEnabled()||i.setAttribute("disabled",!0),e.isDeletable()||e.isShadow()||i.setAttribute("deletable",!1),e.isMovable()||e.isShadow()||i.setAttribute("movable",!1),e.isEditable()||i.setAttribute("editable",!1),(n=e.getNextBlock())&&(a=t.Xml.blockToDom(n,o)).nodeType==t.utils.dom.NodeType.ELEMENT_NODE&&((l=t.utils.xml.createElement("next")).appendChild(a),i.appendChild(l)),!(a=e.nextConnection&&e.nextConnection.getShadowDom())||n&&n.isShadow()||l.appendChild(t.Xml.cloneShadow_(a,o)),i},t.Xml.cloneShadow_=function(e,o){for(var i,n=e=e.cloneNode(!0);n;)if(o&&"shadow"==n.nodeName&&n.removeAttribute("id"),n.firstChild)n=n.firstChild;else{for(;n&&!n.nextSibling;)i=n,n=n.parentNode,i.nodeType==t.utils.dom.NodeType.TEXT_NODE&&""==i.data.trim()&&n.firstChild!=i&&t.utils.dom.removeNode(i);n&&(i=n,n=n.nextSibling,i.nodeType==t.utils.dom.NodeType.TEXT_NODE&&""==i.data.trim()&&t.utils.dom.removeNode(i))}return e},t.Xml.domToText=function(e){return t.utils.xml.domToText(e).replace(/<(\w+)([^<]*)\/>/g,"<$1$2>")},t.Xml.domToPrettyText=function(e){e=t.Xml.domToText(e).split("<");for(var o="",i=1;i"!=n.slice(-2)&&(o+=" ")}return(e=(e=e.join("\n")).replace(/(<(\w+)\b[^>]*>[^\n]*)\n *<\/\2>/g,"$1")).replace(/^\n/,"")},t.Xml.textToDom=function(e){var o=t.utils.xml.textToDomDocument(e);if(!o||!o.documentElement||o.getElementsByTagName("parsererror").length)throw Error("textToDom was unable to parse: "+e);return o.documentElement},t.Xml.clearWorkspaceAndLoadFromXml=function(e,o){return o.setResizesEnabled(!1),o.clear(),e=t.Xml.domToWorkspace(e,o),o.setResizesEnabled(!0),e},t.Xml.domToWorkspace=function(e,o){if(e instanceof t.Workspace){var i=e;e=o,o=i,console.warn("Deprecated call to Blockly.Xml.domToWorkspace, swap the arguments.")}var n;o.RTL&&(n=o.getWidth()),i=[],t.utils.dom.startTextWidthCache();var s=t.Events.getGroup();s||t.Events.setGroup(!0),o.setResizesEnabled&&o.setResizesEnabled(!1);var r=!0;try{for(var a,l=0;a=e.childNodes[l];l++){var c=a.nodeName.toLowerCase(),u=a;if("block"==c||"shadow"==c&&!t.Events.recordUndo){var h=t.Xml.domToBlock(u,o);i.push(h.id);var p=u.hasAttribute("x")?parseInt(u.getAttribute("x"),10):10,_=u.hasAttribute("y")?parseInt(u.getAttribute("y"),10):10;isNaN(p)||isNaN(_)||h.moveBy(o.RTL?n-p:p,_),r=!1}else{if("shadow"==c)throw TypeError("Shadow block cannot be a top-level block.");if("comment"==c)o.rendered?t.WorkspaceCommentSvg?t.WorkspaceCommentSvg.fromXml(u,o,n):console.warn("Missing require for Blockly.WorkspaceCommentSvg, ignoring workspace comment."):t.WorkspaceComment?t.WorkspaceComment.fromXml(u,o):console.warn("Missing require for Blockly.WorkspaceComment, ignoring workspace comment.");else if("variables"==c){if(!r)throw Error("'variables' tag must exist once before block and shadow tag elements in the workspace XML, but it was found in another location.");t.Xml.domToVariables(u,o),r=!1}}}}finally{s||t.Events.setGroup(!1),t.utils.dom.stopTextWidthCache()}return o.setResizesEnabled&&o.setResizesEnabled(!0),t.Events.fire(new t.Events.FinishedLoading(o)),i},t.Xml.appendDomToWorkspace=function(e,o){var i;if(Object.prototype.hasOwnProperty.call(o,"scale")&&(i=o.getBlocksBoundingBox()),e=t.Xml.domToWorkspace(e,o),i&&i.top!=i.bottom){var n=i.bottom,s=o.RTL?i.right:i.left,r=1/0,a=-1/0,l=1/0;for(i=0;ia&&(a=c.x)}for(n=n-l+10,s=o.RTL?s-a:s-r,i=0;i=i+this.handleLength_&&(n+=s),this.setHandlePosition(this.constrainHandle_(n)),this.onScroll_(),e.stopPropagation(),e.preventDefault()}},t.Scrollbar.prototype.onMouseDownHandle_=function(e){this.workspace_.markFocused(),this.cleanUp_(),t.utils.isRightButton(e)?e.stopPropagation():(this.startDragHandle=this.handlePosition_,this.workspace_.setupDragSurface(),this.startDragMouse_=this.horizontal_?e.clientX:e.clientY,t.Scrollbar.onMouseUpWrapper_=t.bindEventWithChecks_(document,"mouseup",this,this.onMouseUpHandle_),t.Scrollbar.onMouseMoveWrapper_=t.bindEventWithChecks_(document,"mousemove",this,this.onMouseMoveHandle_),e.stopPropagation(),e.preventDefault())},t.Scrollbar.prototype.onMouseMoveHandle_=function(t){this.setHandlePosition(this.constrainHandle_(this.startDragHandle+((this.horizontal_?t.clientX:t.clientY)-this.startDragMouse_))),this.onScroll_()},t.Scrollbar.prototype.onMouseUpHandle_=function(){this.workspace_.resetDragSurface(),t.Touch.clearTouchIdentifier(),this.cleanUp_()},t.Scrollbar.prototype.cleanUp_=function(){t.hideChaff(!0),t.Scrollbar.onMouseUpWrapper_&&(t.unbindEvent_(t.Scrollbar.onMouseUpWrapper_),t.Scrollbar.onMouseUpWrapper_=null),t.Scrollbar.onMouseMoveWrapper_&&(t.unbindEvent_(t.Scrollbar.onMouseMoveWrapper_),t.Scrollbar.onMouseMoveWrapper_=null)},t.Scrollbar.prototype.constrainHandle_=function(t){return 0>=t||isNaN(t)||this.scrollViewSize_t.Tooltip.RADIUS_OK&&t.Tooltip.hide()}else t.Tooltip.poisonedElement_!=t.Tooltip.element_&&(clearTimeout(t.Tooltip.showPid_),t.Tooltip.lastX_=e.pageX,t.Tooltip.lastY_=e.pageY,t.Tooltip.showPid_=setTimeout(t.Tooltip.show_,t.Tooltip.HOVER_MS))},t.Tooltip.dispose=function(){t.Tooltip.element_=null,t.Tooltip.poisonedElement_=null,t.Tooltip.hide()},t.Tooltip.hide=function(){t.Tooltip.visible&&(t.Tooltip.visible=!1,t.Tooltip.DIV&&(t.Tooltip.DIV.style.display="none")),t.Tooltip.showPid_&&clearTimeout(t.Tooltip.showPid_)},t.Tooltip.block=function(){t.Tooltip.hide(),t.Tooltip.blocked_=!0},t.Tooltip.unblock=function(){t.Tooltip.blocked_=!1},t.Tooltip.show_=function(){if(!t.Tooltip.blocked_&&(t.Tooltip.poisonedElement_=t.Tooltip.element_,t.Tooltip.DIV)){t.Tooltip.DIV.textContent="";var e=t.Tooltip.getTooltipOfObject(t.Tooltip.element_);e=(e=t.utils.string.wrap(e,t.Tooltip.LIMIT)).split("\n");for(var o=0;oi+window.scrollY&&(s-=t.Tooltip.DIV.offsetHeight+2*t.Tooltip.OFFSET_Y),e?n=Math.max(t.Tooltip.MARGINS-window.scrollX,n):n+t.Tooltip.DIV.offsetWidth>o+window.scrollX-2*t.Tooltip.MARGINS&&(n=o-t.Tooltip.DIV.offsetWidth-2*t.Tooltip.MARGINS),t.Tooltip.DIV.style.top=s+"px",t.Tooltip.DIV.style.left=n+"px"}},t.WorkspaceDragSurfaceSvg=function(t){this.container_=t,this.createDom()},t.WorkspaceDragSurfaceSvg.prototype.SVG_=null,t.WorkspaceDragSurfaceSvg.prototype.container_=null,t.WorkspaceDragSurfaceSvg.prototype.createDom=function(){this.SVG_||(this.SVG_=t.utils.dom.createSvgElement(t.utils.Svg.SVG,{xmlns:t.utils.dom.SVG_NS,"xmlns:html":t.utils.dom.HTML_NS,"xmlns:xlink":t.utils.dom.XLINK_NS,version:"1.1",class:"blocklyWsDragSurface blocklyOverflowVisible"},null),this.container_.appendChild(this.SVG_))},t.WorkspaceDragSurfaceSvg.prototype.translateSurface=function(e,o){e=e.toFixed(0),o=o.toFixed(0),this.SVG_.style.display="block",t.utils.dom.setCssTransform(this.SVG_,"translate3d("+e+"px, "+o+"px, 0px)")},t.WorkspaceDragSurfaceSvg.prototype.getSurfaceTranslation=function(){return t.utils.getRelativeXY(this.SVG_)},t.WorkspaceDragSurfaceSvg.prototype.clearAndHide=function(e){if(!e)throw Error("Couldn't clear and hide the drag surface: missing new surface.");var o=this.SVG_.childNodes[0],i=this.SVG_.childNodes[1];if(!(o&&i&&t.utils.dom.hasClass(o,"blocklyBlockCanvas")&&t.utils.dom.hasClass(i,"blocklyBubbleCanvas")))throw Error("Couldn't clear and hide the drag surface. A node was missing.");if(null!=this.previousSibling_?t.utils.dom.insertAfter(o,this.previousSibling_):e.insertBefore(o,e.firstChild),t.utils.dom.insertAfter(i,o),this.SVG_.style.display="none",this.SVG_.childNodes.length)throw Error("Drag surface was not cleared.");t.utils.dom.setCssTransform(this.SVG_,""),this.previousSibling_=null},t.WorkspaceDragSurfaceSvg.prototype.setContentsAndShow=function(t,e,o,i,n,s){if(this.SVG_.childNodes.length)throw Error("Already dragging a block.");this.previousSibling_=o,t.setAttribute("transform","translate(0, 0) scale("+s+")"),e.setAttribute("transform","translate(0, 0) scale("+s+")"),this.SVG_.setAttribute("width",i),this.SVG_.setAttribute("height",n),this.SVG_.appendChild(t),this.SVG_.appendChild(e),this.SVG_.style.display="block"},t.ASTNode=function(e,o,i){if(!o)throw Error("Cannot create a node without a location.");this.type_=e,this.isConnection_=t.ASTNode.isConnectionType_(e),this.location_=o,this.wsCoordinate_=null,this.processParams_(i||null)},t.ASTNode.types={FIELD:"field",BLOCK:"block",INPUT:"input",OUTPUT:"output",NEXT:"next",PREVIOUS:"previous",STACK:"stack",WORKSPACE:"workspace"},t.ASTNode.NAVIGATE_ALL_FIELDS=!1,t.ASTNode.DEFAULT_OFFSET_Y=-20,t.ASTNode.isConnectionType_=function(e){switch(e){case t.ASTNode.types.PREVIOUS:case t.ASTNode.types.NEXT:case t.ASTNode.types.INPUT:case t.ASTNode.types.OUTPUT:return!0}return!1},t.ASTNode.createFieldNode=function(e){return e?new t.ASTNode(t.ASTNode.types.FIELD,e):null},t.ASTNode.createConnectionNode=function(e){return e?e.type==t.INPUT_VALUE||e.type==t.NEXT_STATEMENT&&e.getParentInput()?t.ASTNode.createInputNode(e.getParentInput()):e.type==t.NEXT_STATEMENT?new t.ASTNode(t.ASTNode.types.NEXT,e):e.type==t.OUTPUT_VALUE?new t.ASTNode(t.ASTNode.types.OUTPUT,e):e.type==t.PREVIOUS_STATEMENT?new t.ASTNode(t.ASTNode.types.PREVIOUS,e):null:null},t.ASTNode.createInputNode=function(e){return e&&e.connection?new t.ASTNode(t.ASTNode.types.INPUT,e.connection):null},t.ASTNode.createBlockNode=function(e){return e?new t.ASTNode(t.ASTNode.types.BLOCK,e):null},t.ASTNode.createStackNode=function(e){return e?new t.ASTNode(t.ASTNode.types.STACK,e):null},t.ASTNode.createWorkspaceNode=function(e,o){return o&&e?new t.ASTNode(t.ASTNode.types.WORKSPACE,e,{wsCoordinate:o}):null},t.ASTNode.createTopNode=function(e){var o=e.previousConnection||e.outputConnection;return o?t.ASTNode.createConnectionNode(o):t.ASTNode.createBlockNode(e)},t.ASTNode.prototype.processParams_=function(t){t&&t.wsCoordinate&&(this.wsCoordinate_=t.wsCoordinate)},t.ASTNode.prototype.getLocation=function(){return this.location_},t.ASTNode.prototype.getType=function(){return this.type_},t.ASTNode.prototype.getWsCoordinate=function(){return this.wsCoordinate_},t.ASTNode.prototype.isConnection=function(){return this.isConnection_},t.ASTNode.prototype.findNextForInput_=function(){var e,o=this.location_.getParentInput(),i=o.getSourceBlock();for(o=i.inputList.indexOf(o)+1;e=i.inputList[o];o++){for(var n,s=e.fieldRow,r=0;n=s[r];r++)if(n.isClickable()||t.ASTNode.NAVIGATE_ALL_FIELDS)return t.ASTNode.createFieldNode(n);if(e.connection)return t.ASTNode.createInputNode(e)}return null},t.ASTNode.prototype.findNextForField_=function(){var e=this.location_,o=e.getParentInput(),i=e.getSourceBlock(),n=i.inputList.indexOf(o);for(e=o.fieldRow.indexOf(e)+1;o=i.inputList[n];n++){for(var s=o.fieldRow;ei)){var n=o.getSvgXY(e.getSvgRoot());e.outputConnection?(n.x+=(e.RTL?3:-3)*i,n.y+=13*i):e.previousConnection&&(n.x+=(e.RTL?-23:23)*i,n.y+=3*i),e=t.utils.dom.createSvgElement(t.utils.Svg.CIRCLE,{cx:n.x,cy:n.y,r:0,fill:"none",stroke:"#888","stroke-width":10},o.getParentSvg()),t.blockAnimations.connectionUiStep_(e,new Date,i)}},t.blockAnimations.connectionUiStep_=function(e,o,i){var n=(new Date-o)/150;1e.workspace.scale)){var o=e.getHeightWidth().height;o=Math.atan(10/o)/Math.PI*180,e.RTL||(o*=-1),t.blockAnimations.disconnectUiStep_(e.getSvgRoot(),o,new Date)}},t.blockAnimations.disconnectUiStep_=function(e,o,i){var n=(new Date-i)/200;1o-t.CURRENT_CONNECTION_PREFERENCE)):!this.localConnection_&&!this.closestConnection_||(console.error("Only one of localConnection_ and closestConnection_ was set."),console.error("Returning true from shouldUpdatePreviews, but it's not clear why."),!0):!(!this.localConnection_||!this.closestConnection_)},t.InsertionMarkerManager.prototype.getCandidate_=function(t){for(var e=this.getStartRadius_(),o=null,i=null,n=0;ni||o.getSourceBlock().isInsertionMarker())return!1;switch(o.type){case t.PREVIOUS_STATEMENT:return this.canConnectToPrevious_(e,o);case t.OUTPUT_VALUE:if(o.isConnected()&&!o.targetBlock().isInsertionMarker()||e.isConnected())return!1;break;case t.INPUT_VALUE:if(o.isConnected()&&!o.targetBlock().isMovable()&&!o.targetBlock().isShadow())return!1;break;case t.NEXT_STATEMENT:if(o.isConnected()&&!e.getSourceBlock().nextConnection&&!o.targetBlock().isShadow()&&o.targetBlock().nextConnection)return!1;break;default:return!1}return-1==t.draggingConnections.indexOf(o)},t.ConnectionChecker.prototype.canConnectToPrevious_=function(e,o){return!(e.targetConnection||-1!=t.draggingConnections.indexOf(o)||o.targetConnection&&(!(e=o.targetBlock()).isInsertionMarker()||e.getPreviousBlock()))},t.registry.register(t.registry.Type.CONNECTION_CHECKER,t.registry.DEFAULT,t.ConnectionChecker),t.VariableMap=function(t){this.variableMap_=Object.create(null),this.workspace=t},t.VariableMap.prototype.clear=function(){this.variableMap_=Object.create(null)},t.VariableMap.prototype.renameVariable=function(e,o){var i=this.getVariable(o,e.type),n=this.workspace.getAllBlocks(!1);t.Events.setGroup(!0);try{i&&i.getId()!=e.getId()?this.renameVariableWithConflict_(e,o,i,n):this.renameVariableAndUses_(e,o,n)}finally{t.Events.setGroup(!1)}},t.VariableMap.prototype.renameVariableById=function(t,e){var o=this.getVariableById(t);if(!o)throw Error("Tried to rename a variable that didn't exist. ID: "+t);this.renameVariable(o,e)},t.VariableMap.prototype.renameVariableAndUses_=function(e,o,i){for(t.Events.fire(new t.Events.VarRename(e,o)),e.name=o,o=0;othis.remainingCapacityOfType(e))return!1;o+=t[e]}return!(o>this.remainingCapacity())},t.Workspace.prototype.hasBlockLimits=function(){return 1/0!=this.options.maxBlocks||!!this.options.maxInstances},t.Workspace.prototype.getUndoStack=function(){return this.undoStack_},t.Workspace.prototype.getRedoStack=function(){return this.redoStack_},t.Workspace.prototype.undo=function(e){var o=e?this.redoStack_:this.undoStack_,i=e?this.undoStack_:this.redoStack_,n=o.pop();if(n){for(var s=[n];o.length&&n.group&&n.group==o[o.length-1].group;)s.push(o.pop());for(o=0;n=s[o];o++)i.push(n);s=t.Events.filter(s,e),t.Events.recordUndo=!1;try{for(o=0;n=s[o];o++)n.run(e)}finally{t.Events.recordUndo=!0}}},t.Workspace.prototype.clearUndo=function(){this.undoStack_.length=0,this.redoStack_.length=0,t.Events.clearPendingUndo()},t.Workspace.prototype.addChangeListener=function(t){return this.listeners_.push(t),t},t.Workspace.prototype.removeChangeListener=function(e){t.utils.arrayRemove(this.listeners_,e)},t.Workspace.prototype.fireChangeListener=function(t){if(t.recordUndo)for(this.undoStack_.push(t),this.redoStack_.length=0;this.undoStack_.length>this.MAX_UNDO&&0<=this.MAX_UNDO;)this.undoStack_.shift();for(var e,o=0;e=this.listeners_[o];o++)e(t)},t.Workspace.prototype.getBlockById=function(t){return this.blockDB_[t]||null},t.Workspace.prototype.setBlockById=function(t,e){this.blockDB_[t]=e},t.Workspace.prototype.removeBlockById=function(t){delete this.blockDB_[t]},t.Workspace.prototype.getCommentById=function(t){return this.commentDB_[t]||null},t.Workspace.prototype.allInputsFilled=function(t){for(var e,o=this.getTopBlocks(!1),i=0;e=o[i];i++)if(!e.allInputsFilled(t))return!1;return!0},t.Workspace.prototype.getPotentialVariableMap=function(){return this.potentialVariableMap_},t.Workspace.prototype.createPotentialVariableMap=function(){this.potentialVariableMap_=new t.VariableMap(this)},t.Workspace.prototype.getVariableMap=function(){return this.variableMap_},t.Workspace.prototype.setVariableMap=function(t){this.variableMap_=t},t.Workspace.WorkspaceDB_=Object.create(null),t.Workspace.getById=function(e){return t.Workspace.WorkspaceDB_[e]||null},t.Workspace.getAll=function(){var e,o=[];for(e in t.Workspace.WorkspaceDB_)o.push(t.Workspace.WorkspaceDB_[e]);return o},t.Bubble=function(e,o,i,n,s,r){this.workspace_=e,this.content_=o,this.shape_=i,this.onMouseDownResizeWrapper_=this.onMouseDownBubbleWrapper_=this.moveCallback_=this.resizeCallback_=null,this.disposed=!1,i=t.Bubble.ARROW_ANGLE,this.workspace_.RTL&&(i=-i),this.arrow_radians_=t.utils.math.toRadians(i),e.getBubbleCanvas().appendChild(this.createDom_(o,!(!s||!r))),this.setAnchorLocation(n),s&&r||(s=(e=this.content_.getBBox()).width+2*t.Bubble.BORDER_WIDTH,r=e.height+2*t.Bubble.BORDER_WIDTH),this.setBubbleSize(s,r),this.positionBubble_(),this.renderArrow_(),this.rendered_=!0},t.Bubble.BORDER_WIDTH=6,t.Bubble.ARROW_THICKNESS=5,t.Bubble.ARROW_ANGLE=20,t.Bubble.ARROW_BEND=4,t.Bubble.ANCHOR_RADIUS=8,t.Bubble.onMouseUpWrapper_=null,t.Bubble.onMouseMoveWrapper_=null,t.Bubble.unbindDragEvents_=function(){t.Bubble.onMouseUpWrapper_&&(t.unbindEvent_(t.Bubble.onMouseUpWrapper_),t.Bubble.onMouseUpWrapper_=null),t.Bubble.onMouseMoveWrapper_&&(t.unbindEvent_(t.Bubble.onMouseMoveWrapper_),t.Bubble.onMouseMoveWrapper_=null)},t.Bubble.bubbleMouseUp_=function(e){t.Touch.clearTouchIdentifier(),t.Bubble.unbindDragEvents_()},t.Bubble.prototype.rendered_=!1,t.Bubble.prototype.anchorXY_=null,t.Bubble.prototype.relativeLeft_=0,t.Bubble.prototype.relativeTop_=0,t.Bubble.prototype.width_=0,t.Bubble.prototype.height_=0,t.Bubble.prototype.autoLayout_=!0,t.Bubble.prototype.createDom_=function(e,o){this.bubbleGroup_=t.utils.dom.createSvgElement(t.utils.Svg.G,{},null);var i={filter:"url(#"+this.workspace_.getRenderer().getConstants().embossFilterId+")"};return t.utils.userAgent.JAVA_FX&&(i={}),i=t.utils.dom.createSvgElement(t.utils.Svg.G,i,this.bubbleGroup_),this.bubbleArrow_=t.utils.dom.createSvgElement(t.utils.Svg.PATH,{},i),this.bubbleBack_=t.utils.dom.createSvgElement(t.utils.Svg.RECT,{class:"blocklyDraggable",x:0,y:0,rx:t.Bubble.BORDER_WIDTH,ry:t.Bubble.BORDER_WIDTH},i),o?(this.resizeGroup_=t.utils.dom.createSvgElement(t.utils.Svg.G,{class:this.workspace_.RTL?"blocklyResizeSW":"blocklyResizeSE"},this.bubbleGroup_),o=2*t.Bubble.BORDER_WIDTH,t.utils.dom.createSvgElement(t.utils.Svg.POLYGON,{points:"0,x x,x x,0".replace(/x/g,o.toString())},this.resizeGroup_),t.utils.dom.createSvgElement(t.utils.Svg.LINE,{class:"blocklyResizeLine",x1:o/3,y1:o-1,x2:o-1,y2:o/3},this.resizeGroup_),t.utils.dom.createSvgElement(t.utils.Svg.LINE,{class:"blocklyResizeLine",x1:2*o/3,y1:o-1,x2:o-1,y2:2*o/3},this.resizeGroup_)):this.resizeGroup_=null,this.workspace_.options.readOnly||(this.onMouseDownBubbleWrapper_=t.bindEventWithChecks_(this.bubbleBack_,"mousedown",this,this.bubbleMouseDown_),this.resizeGroup_&&(this.onMouseDownResizeWrapper_=t.bindEventWithChecks_(this.resizeGroup_,"mousedown",this,this.resizeMouseDown_))),this.bubbleGroup_.appendChild(e),this.bubbleGroup_},t.Bubble.prototype.getSvgRoot=function(){return this.bubbleGroup_},t.Bubble.prototype.setSvgId=function(t){this.bubbleGroup_.dataset&&(this.bubbleGroup_.dataset.blockId=t)},t.Bubble.prototype.bubbleMouseDown_=function(t){var e=this.workspace_.getGesture(t);e&&e.handleBubbleStart(t,this)},t.Bubble.prototype.showContextMenu=function(t){},t.Bubble.prototype.isDeletable=function(){return!1},t.Bubble.prototype.setDeleteStyle=function(t){},t.Bubble.prototype.resizeMouseDown_=function(e){this.promote(),t.Bubble.unbindDragEvents_(),t.utils.isRightButton(e)||(this.workspace_.startDrag(e,new t.utils.Coordinate(this.workspace_.RTL?-this.width_:this.width_,this.height_)),t.Bubble.onMouseUpWrapper_=t.bindEventWithChecks_(document,"mouseup",this,t.Bubble.bubbleMouseUp_),t.Bubble.onMouseMoveWrapper_=t.bindEventWithChecks_(document,"mousemove",this,this.resizeMouseMove_),t.hideChaff()),e.stopPropagation()},t.Bubble.prototype.resizeMouseMove_=function(t){this.autoLayout_=!1,t=this.workspace_.moveDrag(t),this.setBubbleSize(this.workspace_.RTL?-t.x:t.x,t.y),this.workspace_.RTL&&this.positionBubble_()},t.Bubble.prototype.registerResizeEvent=function(t){this.resizeCallback_=t},t.Bubble.prototype.registerMoveEvent=function(t){this.moveCallback_=t},t.Bubble.prototype.promote=function(){var t=this.bubbleGroup_.parentNode;return t.lastChild!==this.bubbleGroup_&&(t.appendChild(this.bubbleGroup_),!0)},t.Bubble.prototype.setAnchorLocation=function(t){this.anchorXY_=t,this.rendered_&&this.positionBubble_()},t.Bubble.prototype.layoutBubble_=function(){var t=this.workspace_.getMetrics();t.viewLeft/=this.workspace_.scale,t.viewWidth/=this.workspace_.scale,t.viewTop/=this.workspace_.scale,t.viewHeight/=this.workspace_.scale;var e=this.getOptimalRelativeLeft_(t),o=this.getOptimalRelativeTop_(t),i=this.shape_.getBBox(),n={x:e,y:-this.height_-this.workspace_.getRenderer().getConstants().MIN_BLOCK_HEIGHT},s={x:-this.width_-30,y:o};o={x:i.width,y:o};var r={x:e,y:i.height};e=i.widthe.viewWidth)return o;if(this.workspace_.RTL)var i=this.anchorXY_.x-o,n=i-this.width_,s=e.viewLeft+e.viewWidth,r=e.viewLeft+t.Scrollbar.scrollbarThickness/this.workspace_.scale;else i=(n=o+this.anchorXY_.x)+this.width_,r=e.viewLeft,s=e.viewLeft+e.viewWidth-t.Scrollbar.scrollbarThickness/this.workspace_.scale;return this.workspace_.RTL?ns&&(o=-(s-this.anchorXY_.x)):ns&&(o=s-this.anchorXY_.x-this.width_),o},t.Bubble.prototype.getOptimalRelativeTop_=function(e){var o=-this.height_/4;if(this.height_>e.viewHeight)return o;var i=this.anchorXY_.y+o,n=i+this.height_,s=e.viewTop;e=e.viewTop+e.viewHeight-t.Scrollbar.scrollbarThickness/this.workspace_.scale;var r=this.anchorXY_.y;return ie&&(o=e-r-this.height_),o},t.Bubble.prototype.positionBubble_=function(){var t=this.anchorXY_.x;t=this.workspace_.RTL?t-(this.relativeLeft_+this.width_):t+this.relativeLeft_,this.moveTo(t,this.relativeTop_+this.anchorXY_.y)},t.Bubble.prototype.moveTo=function(t,e){this.bubbleGroup_.setAttribute("transform","translate("+t+","+e+")")},t.Bubble.prototype.setDragging=function(t){!t&&this.moveCallback_&&this.moveCallback_()},t.Bubble.prototype.getBubbleSize=function(){return new t.utils.Size(this.width_,this.height_)},t.Bubble.prototype.setBubbleSize=function(e,o){var i=2*t.Bubble.BORDER_WIDTH;e=Math.max(e,i+45),o=Math.max(o,i+20),this.width_=e,this.height_=o,this.bubbleBack_.setAttribute("width",e),this.bubbleBack_.setAttribute("height",o),this.resizeGroup_&&(this.workspace_.RTL?this.resizeGroup_.setAttribute("transform","translate("+2*t.Bubble.BORDER_WIDTH+","+(o-i)+") scale(-1 1)"):this.resizeGroup_.setAttribute("transform","translate("+(e-i)+","+(o-i)+")")),this.autoLayout_&&this.layoutBubble_(),this.positionBubble_(),this.renderArrow_(),this.resizeCallback_&&this.resizeCallback_()},t.Bubble.prototype.renderArrow_=function(){var e=[],o=this.width_/2,i=this.height_/2,n=-this.relativeLeft_,s=-this.relativeTop_;if(o==n&&i==s)e.push("M "+o+","+i);else{s-=i,n-=o,this.workspace_.RTL&&(n*=-1);var r=Math.sqrt(s*s+n*n),a=Math.acos(n/r);0>s&&(a=2*Math.PI-a);var l=a+Math.PI/2;l>2*Math.PI&&(l-=2*Math.PI);var c=Math.sin(l),u=Math.cos(l),h=this.getBubbleSize();l=(h.width+h.height)/t.Bubble.ARROW_THICKNESS,l=Math.min(l,h.width,h.height)/4,n=o+(h=1-t.Bubble.ANCHOR_RADIUS/r)*n,s=i+h*s,h=o+l*u;var p=i+l*c;o-=l*u,i-=l*c,(c=a+this.arrow_radians_)>2*Math.PI&&(c-=2*Math.PI),a=Math.sin(c)*r/t.Bubble.ARROW_BEND,r=Math.cos(c)*r/t.Bubble.ARROW_BEND,e.push("M"+h+","+p),e.push("C"+(h+r)+","+(p+a)+" "+n+","+s+" "+n+","+s),e.push("C"+n+","+s+" "+(o+r)+","+(i+a)+" "+o+","+i)}e.push("z"),this.bubbleArrow_.setAttribute("d",e.join(" "))},t.Bubble.prototype.setColour=function(t){this.bubbleBack_.setAttribute("fill",t),this.bubbleArrow_.setAttribute("fill",t)},t.Bubble.prototype.dispose=function(){this.onMouseDownBubbleWrapper_&&t.unbindEvent_(this.onMouseDownBubbleWrapper_),this.onMouseDownResizeWrapper_&&t.unbindEvent_(this.onMouseDownResizeWrapper_),t.Bubble.unbindDragEvents_(),t.utils.dom.removeNode(this.bubbleGroup_),this.disposed=!0},t.Bubble.prototype.moveDuringDrag=function(t,e){t?t.translateSurface(e.x,e.y):this.moveTo(e.x,e.y),this.relativeLeft_=this.workspace_.RTL?this.anchorXY_.x-e.x-this.width_:e.x-this.anchorXY_.x,this.relativeTop_=e.y-this.anchorXY_.y,this.renderArrow_()},t.Bubble.prototype.getRelativeToSurfaceXY=function(){return new t.utils.Coordinate(this.workspace_.RTL?-this.relativeLeft_+this.anchorXY_.x-this.width_:this.anchorXY_.x+this.relativeLeft_,this.anchorXY_.y+this.relativeTop_)},t.Bubble.prototype.setAutoLayout=function(t){this.autoLayout_=t},t.Events.CommentBase=function(e){this.commentId=(this.isBlank=void 0===e)?"":e.id,this.workspaceId=this.isBlank?"":e.workspace.id,this.group=t.Events.getGroup(),this.recordUndo=t.Events.recordUndo},t.utils.object.inherits(t.Events.CommentBase,t.Events.Abstract),t.Events.CommentBase.prototype.toJson=function(){var e=t.Events.CommentBase.superClass_.toJson.call(this);return this.commentId&&(e.commentId=this.commentId),e},t.Events.CommentBase.prototype.fromJson=function(e){t.Events.CommentBase.superClass_.fromJson.call(this,e),this.commentId=e.commentId},t.Events.CommentChange=function(e,o,i){t.Events.CommentChange.superClass_.constructor.call(this,e),e&&(this.oldContents_=void 0===o?"":o,this.newContents_=void 0===i?"":i)},t.utils.object.inherits(t.Events.CommentChange,t.Events.CommentBase),t.Events.CommentChange.prototype.type=t.Events.COMMENT_CHANGE,t.Events.CommentChange.prototype.toJson=function(){var e=t.Events.CommentChange.superClass_.toJson.call(this);return e.newContents=this.newContents_,e},t.Events.CommentChange.prototype.fromJson=function(e){t.Events.CommentChange.superClass_.fromJson.call(this,e),this.newContents_=e.newValue},t.Events.CommentChange.prototype.isNull=function(){return this.oldContents_==this.newContents_},t.Events.CommentChange.prototype.run=function(t){var e=this.getEventWorkspace_().getCommentById(this.commentId);e?e.setContent(t?this.newContents_:this.oldContents_):console.warn("Can't change non-existent comment: "+this.commentId)},t.Events.CommentCreate=function(e){t.Events.CommentCreate.superClass_.constructor.call(this,e),e&&(this.xml=e.toXmlWithXY())},t.utils.object.inherits(t.Events.CommentCreate,t.Events.CommentBase),t.Events.CommentCreate.prototype.type=t.Events.COMMENT_CREATE,t.Events.CommentCreate.prototype.toJson=function(){var e=t.Events.CommentCreate.superClass_.toJson.call(this);return e.xml=t.Xml.domToText(this.xml),e},t.Events.CommentCreate.prototype.fromJson=function(e){t.Events.CommentCreate.superClass_.fromJson.call(this,e),this.xml=t.Xml.textToDom(e.xml)},t.Events.CommentCreate.prototype.run=function(e){t.Events.CommentCreateDeleteHelper(this,e)},t.Events.CommentCreateDeleteHelper=function(e,o){var i=e.getEventWorkspace_();o?((o=t.utils.xml.createElement("xml")).appendChild(e.xml),t.Xml.domToWorkspace(o,i)):(i=i.getCommentById(e.commentId))?i.dispose(!1,!1):console.warn("Can't uncreate non-existent comment: "+e.commentId)},t.Events.CommentDelete=function(e){t.Events.CommentDelete.superClass_.constructor.call(this,e),e&&(this.xml=e.toXmlWithXY())},t.utils.object.inherits(t.Events.CommentDelete,t.Events.CommentBase),t.Events.CommentDelete.prototype.type=t.Events.COMMENT_DELETE,t.Events.CommentDelete.prototype.toJson=function(){return t.Events.CommentDelete.superClass_.toJson.call(this)},t.Events.CommentDelete.prototype.fromJson=function(e){t.Events.CommentDelete.superClass_.fromJson.call(this,e)},t.Events.CommentDelete.prototype.run=function(e){t.Events.CommentCreateDeleteHelper(this,!e)},t.Events.CommentMove=function(e){t.Events.CommentMove.superClass_.constructor.call(this,e),e&&(this.comment_=e,this.oldCoordinate_=e.getXY(),this.newCoordinate_=null)},t.utils.object.inherits(t.Events.CommentMove,t.Events.CommentBase),t.Events.CommentMove.prototype.recordNew=function(){if(!this.comment_)throw Error("Tried to record the new position of a comment on the same event twice.");this.newCoordinate_=this.comment_.getXY(),this.comment_=null},t.Events.CommentMove.prototype.type=t.Events.COMMENT_MOVE,t.Events.CommentMove.prototype.setOldCoordinate=function(t){this.oldCoordinate_=t},t.Events.CommentMove.prototype.toJson=function(){var e=t.Events.CommentMove.superClass_.toJson.call(this);return this.newCoordinate_&&(e.newCoordinate=Math.round(this.newCoordinate_.x)+","+Math.round(this.newCoordinate_.y)),e},t.Events.CommentMove.prototype.fromJson=function(e){t.Events.CommentMove.superClass_.fromJson.call(this,e),e.newCoordinate&&(e=e.newCoordinate.split(","),this.newCoordinate_=new t.utils.Coordinate(Number(e[0]),Number(e[1])))},t.Events.CommentMove.prototype.isNull=function(){return t.utils.Coordinate.equals(this.oldCoordinate_,this.newCoordinate_)},t.Events.CommentMove.prototype.run=function(t){var e=this.getEventWorkspace_().getCommentById(this.commentId);if(e){t=t?this.newCoordinate_:this.oldCoordinate_;var o=e.getXY();e.moveBy(t.x-o.x,t.y-o.y)}else console.warn("Can't move non-existent comment: "+this.commentId)},t.registry.register(t.registry.Type.EVENT,t.Events.COMMENT_CREATE,t.Events.CommentCreate),t.registry.register(t.registry.Type.EVENT,t.Events.COMMENT_CHANGE,t.Events.CommentChange),t.registry.register(t.registry.Type.EVENT,t.Events.COMMENT_MOVE,t.Events.CommentMove),t.registry.register(t.registry.Type.EVENT,t.Events.COMMENT_DELETE,t.Events.CommentDelete),t.BubbleDragger=function(e,o){this.draggingBubble_=e,this.workspace_=o,this.deleteArea_=null,this.wouldDeleteBubble_=!1,this.startXY_=this.draggingBubble_.getRelativeToSurfaceXY(),this.dragSurface_=t.utils.is3dSupported()&&o.getBlockDragSurface()?o.getBlockDragSurface():null},t.BubbleDragger.prototype.dispose=function(){this.dragSurface_=this.workspace_=this.draggingBubble_=null},t.BubbleDragger.prototype.startBubbleDrag=function(){t.Events.getGroup()||t.Events.setGroup(!0),this.workspace_.setResizesEnabled(!1),this.draggingBubble_.setAutoLayout(!1),this.dragSurface_&&this.moveToDragSurface_(),this.draggingBubble_.setDragging&&this.draggingBubble_.setDragging(!0);var e=this.workspace_.getToolbox();if(e&&"function"==typeof e.addStyle){var o=this.draggingBubble_.isDeletable()?"blocklyToolboxDelete":"blocklyToolboxGrab";e.addStyle(o)}},t.BubbleDragger.prototype.dragBubble=function(e,o){o=this.pixelsToWorkspaceUnits_(o),o=t.utils.Coordinate.sum(this.startXY_,o),this.draggingBubble_.moveDuringDrag(this.dragSurface_,o),this.draggingBubble_.isDeletable()&&(this.deleteArea_=this.workspace_.isDeleteArea(e),this.updateCursorDuringBubbleDrag_())},t.BubbleDragger.prototype.maybeDeleteBubble_=function(){var t=this.workspace_.trashcan;return this.wouldDeleteBubble_?(t&&setTimeout(t.closeLid.bind(t),100),this.fireMoveEvent_(),this.draggingBubble_.dispose(!1,!0)):t&&t.closeLid(),this.wouldDeleteBubble_},t.BubbleDragger.prototype.updateCursorDuringBubbleDrag_=function(){this.wouldDeleteBubble_=this.deleteArea_!=t.DELETE_AREA_NONE;var e=this.workspace_.trashcan;this.wouldDeleteBubble_?(this.draggingBubble_.setDeleteStyle(!0),this.deleteArea_==t.DELETE_AREA_TRASH&&e&&e.setLidOpen(!0)):(this.draggingBubble_.setDeleteStyle(!1),e&&e.setLidOpen(!1))},t.BubbleDragger.prototype.endBubbleDrag=function(e,o){this.dragBubble(e,o),e=this.pixelsToWorkspaceUnits_(o),e=t.utils.Coordinate.sum(this.startXY_,e),this.draggingBubble_.moveTo(e.x,e.y),this.maybeDeleteBubble_()||(this.dragSurface_&&this.dragSurface_.clearAndHide(this.workspace_.getBubbleCanvas()),this.draggingBubble_.setDragging&&this.draggingBubble_.setDragging(!1),this.fireMoveEvent_()),this.workspace_.setResizesEnabled(!0),(e=this.workspace_.getToolbox())&&"function"==typeof e.removeStyle&&(o=this.draggingBubble_.isDeletable()?"blocklyToolboxDelete":"blocklyToolboxGrab",e.removeStyle(o)),t.Events.setGroup(!1)},t.BubbleDragger.prototype.fireMoveEvent_=function(){if(this.draggingBubble_.isComment){var e=new t.Events.CommentMove(this.draggingBubble_);e.setOldCoordinate(this.startXY_),e.recordNew(),t.Events.fire(e)}},t.BubbleDragger.prototype.pixelsToWorkspaceUnits_=function(e){return e=new t.utils.Coordinate(e.x/this.workspace_.scale,e.y/this.workspace_.scale),this.workspace_.isMutator&&e.scale(1/this.workspace_.options.parentWorkspace.scale),e},t.BubbleDragger.prototype.moveToDragSurface_=function(){this.draggingBubble_.moveTo(0,0),this.dragSurface_.translateSurface(this.startXY_.x,this.startXY_.y),this.dragSurface_.setBlocksAndShow(this.draggingBubble_.getSvgRoot())},t.WorkspaceDragger=function(e){this.workspace_=e,this.startScrollXY_=new t.utils.Coordinate(e.scrollX,e.scrollY)},t.WorkspaceDragger.prototype.dispose=function(){this.workspace_=null},t.WorkspaceDragger.prototype.startDrag=function(){t.selected&&t.selected.unselect(),this.workspace_.setupDragSurface()},t.WorkspaceDragger.prototype.endDrag=function(t){this.drag(t),this.workspace_.resetDragSurface()},t.WorkspaceDragger.prototype.drag=function(e){e=t.utils.Coordinate.sum(this.startScrollXY_,e),this.workspace_.scroll(e.x,e.y)},t.FlyoutDragger=function(e){t.FlyoutDragger.superClass_.constructor.call(this,e.getWorkspace()),this.scrollbar_=e.scrollbar,this.horizontalLayout_=e.horizontalLayout},t.utils.object.inherits(t.FlyoutDragger,t.WorkspaceDragger),t.FlyoutDragger.prototype.drag=function(e){e=t.utils.Coordinate.sum(this.startScrollXY_,e),this.horizontalLayout_?this.scrollbar_.set(-e.x):this.scrollbar_.set(-e.y)},t.Action=function(t,e){this.name=t,this.desc=e},t.navigation={},t.navigation.loggingCallback=null,t.navigation.STATE_FLYOUT=1,t.navigation.STATE_WS=2,t.navigation.STATE_TOOLBOX=3,t.navigation.WS_MOVE_DISTANCE=40,t.navigation.currentState_=t.navigation.STATE_WS,t.navigation.actionNames={PREVIOUS:"previous",NEXT:"next",IN:"in",OUT:"out",INSERT:"insert",MARK:"mark",DISCONNECT:"disconnect",TOOLBOX:"toolbox",EXIT:"exit",TOGGLE_KEYBOARD_NAV:"toggle_keyboard_nav",MOVE_WS_CURSOR_UP:"move workspace cursor up",MOVE_WS_CURSOR_DOWN:"move workspace cursor down",MOVE_WS_CURSOR_LEFT:"move workspace cursor left",MOVE_WS_CURSOR_RIGHT:"move workspace cursor right"},t.navigation.MARKER_NAME="local_marker_1",t.navigation.getMarker=function(){return t.navigation.getNavigationWorkspace().getMarker(t.navigation.MARKER_NAME)},t.navigation.getNavigationWorkspace=function(){return t.getMainWorkspace()},t.navigation.focusToolbox_=function(){var e=t.navigation.getNavigationWorkspace().getToolbox();e&&(t.navigation.currentState_=t.navigation.STATE_TOOLBOX,t.navigation.resetFlyout_(!1),t.navigation.getMarker().getCurNode()||t.navigation.markAtCursor_(),e.getSelectedItem()||e.selectItemByPosition(0))},t.navigation.focusFlyout_=function(){t.navigation.currentState_=t.navigation.STATE_FLYOUT;var e=t.navigation.getNavigationWorkspace(),o=e.getToolbox();e=o?o.getFlyout():e.getFlyout(),t.navigation.getMarker().getCurNode()||t.navigation.markAtCursor_(),e&&e.getWorkspace()&&0<(e=e.getWorkspace().getTopBlocks(!0)).length&&(e=e[0],e=t.ASTNode.createStackNode(e),t.navigation.getFlyoutCursor_().setCurNode(e))},t.navigation.focusWorkspace_=function(){t.hideChaff();var e=t.navigation.getNavigationWorkspace(),o=e.getCursor(),i=!!e.getToolbox(),n=e.getTopBlocks(!0);t.navigation.resetFlyout_(i),t.navigation.currentState_=t.navigation.STATE_WS,0(this.flyout_?t.FLYOUT_DRAG_RADIUS:t.DRAG_RADIUS))},t.Gesture.prototype.updateIsDraggingFromFlyout_=function(){return!(!this.targetBlock_||!this.flyout_.isBlockCreatable_(this.targetBlock_)||this.flyout_.isScrollable()&&!this.flyout_.isDragTowardWorkspace(this.currentDragDeltaXY_)||(this.startWorkspace_=this.flyout_.targetWorkspace,this.startWorkspace_.updateScreenCalculationsIfScrolled(),t.Events.getGroup()||t.Events.setGroup(!0),this.startBlock_=null,this.targetBlock_=this.flyout_.createBlock(this.targetBlock_),this.targetBlock_.select(),0))},t.Gesture.prototype.updateIsDraggingBubble_=function(){return!!this.startBubble_&&(this.isDraggingBubble_=!0,this.startDraggingBubble_(),!0)},t.Gesture.prototype.updateIsDraggingBlock_=function(){return!!this.targetBlock_&&(this.flyout_?this.isDraggingBlock_=this.updateIsDraggingFromFlyout_():this.targetBlock_.isMovable()&&(this.isDraggingBlock_=!0),!!this.isDraggingBlock_&&(this.startDraggingBlock_(),!0))},t.Gesture.prototype.updateIsDraggingWorkspace_=function(){(this.flyout_?this.flyout_.isScrollable():this.startWorkspace_&&this.startWorkspace_.isDraggable())&&(this.workspaceDragger_=this.flyout_?new t.FlyoutDragger(this.flyout_):new t.WorkspaceDragger(this.startWorkspace_),this.isDraggingWorkspace_=!0,this.workspaceDragger_.startDrag())},t.Gesture.prototype.updateIsDragging_=function(){if(this.calledUpdateIsDragging_)throw Error("updateIsDragging_ should only be called once per gesture.");this.calledUpdateIsDragging_=!0,this.updateIsDraggingBubble_()||this.updateIsDraggingBlock_()||this.updateIsDraggingWorkspace_()},t.Gesture.prototype.startDraggingBlock_=function(){this.blockDragger_=new t.BlockDragger(this.targetBlock_,this.startWorkspace_),this.blockDragger_.startBlockDrag(this.currentDragDeltaXY_,this.healStack_),this.blockDragger_.dragBlock(this.mostRecentEvent_,this.currentDragDeltaXY_)},t.Gesture.prototype.startDraggingBubble_=function(){this.bubbleDragger_=new t.BubbleDragger(this.startBubble_,this.startWorkspace_),this.bubbleDragger_.startBubbleDrag(),this.bubbleDragger_.dragBubble(this.mostRecentEvent_,this.currentDragDeltaXY_)},t.Gesture.prototype.doStart=function(e){t.utils.isTargetInput(e)?this.cancel():(this.hasStarted_=!0,t.blockAnimations.disconnectUiStop(),this.startWorkspace_.updateScreenCalculationsIfScrolled(),this.startWorkspace_.isMutator&&this.startWorkspace_.resize(),t.hideChaff(!!this.flyout_),this.startWorkspace_.markFocused(),this.mostRecentEvent_=e,t.Tooltip.block(),this.targetBlock_&&(!this.targetBlock_.isInFlyout&&e.shiftKey&&this.targetBlock_.workspace.keyboardAccessibilityMode?this.creatorWorkspace_.getCursor().setCurNode(t.ASTNode.createTopNode(this.targetBlock_)):this.targetBlock_.select()),t.utils.isRightButton(e)?this.handleRightClick(e):("touchstart"!=e.type.toLowerCase()&&"pointerdown"!=e.type.toLowerCase()||"mouse"==e.pointerType||t.longStart(e,this),this.mouseDownXY_=new t.utils.Coordinate(e.clientX,e.clientY),this.healStack_=e.altKey||e.ctrlKey||e.metaKey,this.bindMouseEvents(e)))},t.Gesture.prototype.bindMouseEvents=function(e){this.onMoveWrapper_=t.bindEventWithChecks_(document,"mousemove",null,this.handleMove.bind(this)),this.onUpWrapper_=t.bindEventWithChecks_(document,"mouseup",null,this.handleUp.bind(this)),e.preventDefault(),e.stopPropagation()},t.Gesture.prototype.handleMove=function(t){this.updateFromEvent_(t),this.isDraggingWorkspace_?this.workspaceDragger_.drag(this.currentDragDeltaXY_):this.isDraggingBlock_?this.blockDragger_.dragBlock(this.mostRecentEvent_,this.currentDragDeltaXY_):this.isDraggingBubble_&&this.bubbleDragger_.dragBubble(this.mostRecentEvent_,this.currentDragDeltaXY_),t.preventDefault(),t.stopPropagation()},t.Gesture.prototype.handleUp=function(e){this.updateFromEvent_(e),t.longStop_(),this.isEnding_?console.log("Trying to end a gesture recursively."):(this.isEnding_=!0,this.isDraggingBubble_?this.bubbleDragger_.endBubbleDrag(e,this.currentDragDeltaXY_):this.isDraggingBlock_?this.blockDragger_.endBlockDrag(e,this.currentDragDeltaXY_):this.isDraggingWorkspace_?this.workspaceDragger_.endDrag(this.currentDragDeltaXY_):this.isBubbleClick_()?this.doBubbleClick_():this.isFieldClick_()?this.doFieldClick_():this.isBlockClick_()?this.doBlockClick_():this.isWorkspaceClick_()&&this.doWorkspaceClick_(e),e.preventDefault(),e.stopPropagation(),this.dispose())},t.Gesture.prototype.cancel=function(){this.isEnding_||(t.longStop_(),this.isDraggingBubble_?this.bubbleDragger_.endBubbleDrag(this.mostRecentEvent_,this.currentDragDeltaXY_):this.isDraggingBlock_?this.blockDragger_.endBlockDrag(this.mostRecentEvent_,this.currentDragDeltaXY_):this.isDraggingWorkspace_&&this.workspaceDragger_.endDrag(this.currentDragDeltaXY_),this.dispose())},t.Gesture.prototype.handleRightClick=function(e){this.targetBlock_?(this.bringBlockToFront_(),t.hideChaff(!!this.flyout_),this.targetBlock_.showContextMenu(e)):this.startBubble_?this.startBubble_.showContextMenu(e):this.startWorkspace_&&!this.flyout_&&(t.hideChaff(),this.startWorkspace_.showContextMenu(e)),e.preventDefault(),e.stopPropagation(),this.dispose()},t.Gesture.prototype.handleWsStart=function(e,o){if(this.hasStarted_)throw Error("Tried to call gesture.handleWsStart, but the gesture had already been started.");this.setStartWorkspace_(o),this.mostRecentEvent_=e,this.doStart(e),this.startWorkspace_.keyboardAccessibilityMode&&t.navigation.setState(t.navigation.STATE_WS)},t.Gesture.prototype.fireWorkspaceClick_=function(e){var o=new t.Events.Ui(null,"click",null,"workspace");o.workspaceId=e.id,t.Events.fire(o)},t.Gesture.prototype.handleFlyoutStart=function(t,e){if(this.hasStarted_)throw Error("Tried to call gesture.handleFlyoutStart, but the gesture had already been started.");this.setStartFlyout_(e),this.handleWsStart(t,e.getWorkspace())},t.Gesture.prototype.handleBlockStart=function(t,e){if(this.hasStarted_)throw Error("Tried to call gesture.handleBlockStart, but the gesture had already been started.");this.setStartBlock(e),this.mostRecentEvent_=t},t.Gesture.prototype.handleBubbleStart=function(t,e){if(this.hasStarted_)throw Error("Tried to call gesture.handleBubbleStart, but the gesture had already been started.");this.setStartBubble(e),this.mostRecentEvent_=t},t.Gesture.prototype.doBubbleClick_=function(){this.startBubble_.setFocus&&this.startBubble_.setFocus(),this.startBubble_.select&&this.startBubble_.select()},t.Gesture.prototype.doFieldClick_=function(){this.startField_.showEditor(this.mostRecentEvent_),this.bringBlockToFront_()},t.Gesture.prototype.doBlockClick_=function(){this.flyout_&&this.flyout_.autoClose?this.targetBlock_.isEnabled()&&(t.Events.getGroup()||t.Events.setGroup(!0),this.flyout_.createBlock(this.targetBlock_).scheduleSnapAndBump()):t.Events.fire(new t.Events.Ui(this.startBlock_,"click",void 0,"block")),this.bringBlockToFront_(),t.Events.setGroup(!1)},t.Gesture.prototype.doWorkspaceClick_=function(e){var o=this.creatorWorkspace_;e.shiftKey&&o.keyboardAccessibilityMode?(e=new t.utils.Coordinate(e.clientX,e.clientY),e=t.utils.screenToWsCoordinates(o,e),e=t.ASTNode.createWorkspaceNode(o,e),o.getCursor().setCurNode(e)):t.selected&&t.selected.unselect(),this.fireWorkspaceClick_(this.startWorkspace_||o)},t.Gesture.prototype.bringBlockToFront_=function(){this.targetBlock_&&!this.flyout_&&this.targetBlock_.bringToFront()},t.Gesture.prototype.setStartField=function(t){if(this.hasStarted_)throw Error("Tried to call gesture.setStartField, but the gesture had already been started.");this.startField_||(this.startField_=t)},t.Gesture.prototype.setStartBubble=function(t){this.startBubble_||(this.startBubble_=t)},t.Gesture.prototype.setStartBlock=function(t){this.startBlock_||this.startBubble_||(this.startBlock_=t,t.isInFlyout&&t!=t.getRootBlock()?this.setTargetBlock_(t.getRootBlock()):this.setTargetBlock_(t))},t.Gesture.prototype.setTargetBlock_=function(t){t.isShadow()?this.setTargetBlock_(t.getParent()):this.targetBlock_=t},t.Gesture.prototype.setStartWorkspace_=function(t){this.startWorkspace_||(this.startWorkspace_=t)},t.Gesture.prototype.setStartFlyout_=function(t){this.flyout_||(this.flyout_=t)},t.Gesture.prototype.isBubbleClick_=function(){return!!this.startBubble_&&!this.hasExceededDragRadius_},t.Gesture.prototype.isBlockClick_=function(){return!!this.startBlock_&&!this.hasExceededDragRadius_&&!this.isFieldClick_()},t.Gesture.prototype.isFieldClick_=function(){return!!this.startField_&&this.startField_.isClickable()&&!this.hasExceededDragRadius_&&(!this.flyout_||!this.flyout_.autoClose)},t.Gesture.prototype.isWorkspaceClick_=function(){return!(this.startBlock_||this.startBubble_||this.startField_||this.hasExceededDragRadius_)},t.Gesture.prototype.isDragging=function(){return this.isDraggingWorkspace_||this.isDraggingBlock_||this.isDraggingBubble_},t.Gesture.prototype.hasStarted=function(){return this.hasStarted_},t.Gesture.prototype.getInsertionMarkers=function(){return this.blockDragger_?this.blockDragger_.getInsertionMarkers():[]},t.Gesture.inProgress=function(){for(var e,o=t.Workspace.getAll(),i=0;e=o[i];i++)if(e.currentGesture_)return!0;return!1},t.Field=function(e,o,i){this.value_=this.DEFAULT_VALUE,this.tooltip_=this.validator_=null,this.size_=new t.utils.Size(0,0),this.constants_=this.mouseDownWrapper_=this.textContent_=this.textElement_=this.borderRect_=this.fieldGroup_=this.markerSvg_=this.cursorSvg_=null,i&&this.configure_(i),this.setValue(e),o&&this.setValidator(o)},t.Field.prototype.DEFAULT_VALUE=null,t.Field.prototype.name=void 0,t.Field.prototype.disposed=!1,t.Field.prototype.maxDisplayLength=50,t.Field.prototype.sourceBlock_=null,t.Field.prototype.isDirty_=!0,t.Field.prototype.visible_=!0,t.Field.prototype.clickTarget_=null,t.Field.NBSP=" ",t.Field.prototype.EDITABLE=!0,t.Field.prototype.SERIALIZABLE=!1,t.Field.prototype.configure_=function(e){var o=e.tooltip;"string"==typeof o&&(o=t.utils.replaceMessageReferences(e.tooltip)),o&&this.setTooltip(o)},t.Field.prototype.setSourceBlock=function(t){if(this.sourceBlock_)throw Error("Field already bound to a block.");this.sourceBlock_=t},t.Field.prototype.getConstants=function(){return!this.constants_&&this.sourceBlock_&&this.sourceBlock_.workspace&&this.sourceBlock_.workspace.rendered&&(this.constants_=this.sourceBlock_.workspace.getRenderer().getConstants()),this.constants_},t.Field.prototype.getSourceBlock=function(){return this.sourceBlock_},t.Field.prototype.init=function(){this.fieldGroup_||(this.fieldGroup_=t.utils.dom.createSvgElement(t.utils.Svg.G,{},null),this.isVisible()||(this.fieldGroup_.style.display="none"),this.sourceBlock_.getSvgRoot().appendChild(this.fieldGroup_),this.initView(),this.updateEditable(),this.setTooltip(this.tooltip_),this.bindEvents_(),this.initModel())},t.Field.prototype.initView=function(){this.createBorderRect_(),this.createTextElement_()},t.Field.prototype.initModel=function(){},t.Field.prototype.createBorderRect_=function(){this.borderRect_=t.utils.dom.createSvgElement(t.utils.Svg.RECT,{rx:this.getConstants().FIELD_BORDER_RECT_RADIUS,ry:this.getConstants().FIELD_BORDER_RECT_RADIUS,x:0,y:0,height:this.size_.height,width:this.size_.width,class:"blocklyFieldRect"},this.fieldGroup_)},t.Field.prototype.createTextElement_=function(){this.textElement_=t.utils.dom.createSvgElement(t.utils.Svg.TEXT,{class:"blocklyText"},this.fieldGroup_),this.getConstants().FIELD_TEXT_BASELINE_CENTER&&this.textElement_.setAttribute("dominant-baseline","central"),this.textContent_=document.createTextNode(""),this.textElement_.appendChild(this.textContent_)},t.Field.prototype.bindEvents_=function(){t.Tooltip.bindMouseEvents(this.getClickTarget_()),this.mouseDownWrapper_=t.bindEventWithChecks_(this.getClickTarget_(),"mousedown",this,this.onMouseDown_)},t.Field.prototype.fromXml=function(t){this.setValue(t.textContent)},t.Field.prototype.toXml=function(t){return t.textContent=this.getValue(),t},t.Field.prototype.dispose=function(){t.DropDownDiv.hideIfOwner(this),t.WidgetDiv.hideIfOwner(this),t.Tooltip.unbindMouseEvents(this.getClickTarget_()),this.mouseDownWrapper_&&t.unbindEvent_(this.mouseDownWrapper_),t.utils.dom.removeNode(this.fieldGroup_),this.disposed=!0},t.Field.prototype.updateEditable=function(){var e=this.fieldGroup_;this.EDITABLE&&e&&(this.sourceBlock_.isEditable()?(t.utils.dom.addClass(e,"blocklyEditableText"),t.utils.dom.removeClass(e,"blocklyNonEditableText"),e.style.cursor=this.CURSOR):(t.utils.dom.addClass(e,"blocklyNonEditableText"),t.utils.dom.removeClass(e,"blocklyEditableText"),e.style.cursor=""))},t.Field.prototype.isClickable=function(){return!!this.sourceBlock_&&this.sourceBlock_.isEditable()&&!!this.showEditor_&&"function"==typeof this.showEditor_},t.Field.prototype.isCurrentlyEditable=function(){return this.EDITABLE&&!!this.sourceBlock_&&this.sourceBlock_.isEditable()},t.Field.prototype.isSerializable=function(){var t=!1;return this.name&&(this.SERIALIZABLE?t=!0:this.EDITABLE&&(console.warn("Detected an editable field that was not serializable. Please define SERIALIZABLE property as true on all editable custom fields. Proceeding with serialization."),t=!0)),t},t.Field.prototype.isVisible=function(){return this.visible_},t.Field.prototype.setVisible=function(t){if(this.visible_!=t){this.visible_=t;var e=this.getSvgRoot();e&&(e.style.display=t?"block":"none")}},t.Field.prototype.setValidator=function(t){this.validator_=t},t.Field.prototype.getValidator=function(){return this.validator_},t.Field.prototype.classValidator=function(e){return t.utils.deprecation.warn("Field.prototype.classValidator","May 2019","December 2020","Blockly.Field.prototype.doClassValidation_"),e},t.Field.prototype.callValidator=function(e){t.utils.deprecation.warn("Field.prototype.callValidator","May 2019","December 2020");var o=this.classValidator(e);if(null===o)return null;if(void 0!==o&&(e=o),o=this.getValidator()){if(null===(o=o.call(this,e)))return null;void 0!==o&&(e=o)}return e},t.Field.prototype.getSvgRoot=function(){return this.fieldGroup_},t.Field.prototype.applyColour=function(){},t.Field.prototype.render_=function(){this.textContent_&&(this.textContent_.nodeValue=this.getDisplayText_()),this.updateSize_()},t.Field.prototype.showEditor=function(t){this.isClickable()&&this.showEditor_(t)},t.Field.prototype.updateWidth=function(){t.utils.deprecation.warn("Field.prototype.updateWidth","May 2019","December 2020","Blockly.Field.prototype.updateSize_ or Blockly.utils.dom.getTextWidth"),this.updateSize_()},t.Field.prototype.updateSize_=function(e){var o=this.getConstants(),i=2*(e=null!=e?e:this.borderRect_?this.getConstants().FIELD_BORDER_RECT_X_PADDING:0),n=o.FIELD_TEXT_HEIGHT,s=0;this.textElement_&&(i+=s=t.utils.dom.getFastTextWidth(this.textElement_,o.FIELD_TEXT_FONTSIZE,o.FIELD_TEXT_FONTWEIGHT,o.FIELD_TEXT_FONTFAMILY)),this.borderRect_&&(n=Math.max(n,o.FIELD_BORDER_RECT_HEIGHT)),this.size_.height=n,this.size_.width=i,this.positionTextElement_(e,s),this.positionBorderRect_()},t.Field.prototype.positionTextElement_=function(t,e){if(this.textElement_){var o=this.getConstants(),i=this.size_.height/2;this.textElement_.setAttribute("x",this.sourceBlock_.RTL?this.size_.width-e-t:t),this.textElement_.setAttribute("y",o.FIELD_TEXT_BASELINE_CENTER?i:i-o.FIELD_TEXT_HEIGHT/2+o.FIELD_TEXT_BASELINE)}},t.Field.prototype.positionBorderRect_=function(){this.borderRect_&&(this.borderRect_.setAttribute("width",this.size_.width),this.borderRect_.setAttribute("height",this.size_.height),this.borderRect_.setAttribute("rx",this.getConstants().FIELD_BORDER_RECT_RADIUS),this.borderRect_.setAttribute("ry",this.getConstants().FIELD_BORDER_RECT_RADIUS))},t.Field.prototype.getSize=function(){return this.isVisible()?(this.isDirty_?(this.render_(),this.isDirty_=!1):this.visible_&&0==this.size_.width&&(console.warn("Deprecated use of setting size_.width to 0 to rerender a field. Set field.isDirty_ to true instead."),this.render_()),this.size_):new t.utils.Size(0,0)},t.Field.prototype.getScaledBBox=function(){if(this.borderRect_)e=this.borderRect_.getBoundingClientRect(),i=t.utils.style.getPageOffset(this.borderRect_),n=e.width,e=e.height;else{var e=this.sourceBlock_.getHeightWidth(),o=this.sourceBlock_.workspace.scale,i=this.getAbsoluteXY_(),n=e.width*o;e=e.height*o,t.utils.userAgent.GECKO?(i.x+=1.5*o,i.y+=1.5*o):t.utils.userAgent.EDGE||t.utils.userAgent.IE||(i.x-=.5*o,i.y-=.5*o),n+=1*o,e+=1*o}return new t.utils.Rect(i.y,i.y+e,i.x,i.x+n)},t.Field.prototype.getDisplayText_=function(){var e=this.getText();return e?(e.length>this.maxDisplayLength&&(e=e.substring(0,this.maxDisplayLength-2)+"…"),e=e.replace(/\s/g,t.Field.NBSP),this.sourceBlock_&&this.sourceBlock_.RTL&&(e+="‏"),e):t.Field.NBSP},t.Field.prototype.getText=function(){if(this.getText_){var t=this.getText_.call(this);if(null!==t)return String(t)}return String(this.getValue())},t.Field.prototype.setText=function(e){throw t.utils.deprecation.warn("Field.prototype.setText","May 2019","December 2020","Blockly.Field.prototype.setValue"),Error("setText method is deprecated")},t.Field.prototype.markDirty=function(){this.isDirty_=!0,this.constants_=null},t.Field.prototype.forceRerender=function(){this.isDirty_=!0,this.sourceBlock_&&this.sourceBlock_.rendered&&(this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours(),this.updateMarkers_())},t.Field.prototype.setValue=function(e){if(null!==e){var o=this.doClassValidation_(e);if(!((e=this.processValidation_(e,o))instanceof Error)){if((o=this.getValidator())&&(o=o.call(this,e),(e=this.processValidation_(e,o))instanceof Error))return;if(!(o=this.sourceBlock_)||!o.disposed){var i=this.getValue();i!==e&&(o&&t.Events.isEnabled()&&t.Events.fire(new t.Events.BlockChange(o,"field",this.name||null,i,e)),this.doValueUpdate_(e),this.isDirty_&&this.forceRerender())}}}},t.Field.prototype.processValidation_=function(t,e){return null===e?(this.doValueInvalid_(t),this.isDirty_&&this.forceRerender(),Error()):(void 0!==e&&(t=e),t)},t.Field.prototype.getValue=function(){return this.value_},t.Field.prototype.doClassValidation_=function(t){return null==t?null:t=this.classValidator(t)},t.Field.prototype.doValueUpdate_=function(t){this.value_=t,this.isDirty_=!0},t.Field.prototype.doValueInvalid_=function(t){},t.Field.prototype.onMouseDown_=function(t){this.sourceBlock_&&this.sourceBlock_.workspace&&(t=this.sourceBlock_.workspace.getGesture(t))&&t.setStartField(this)},t.Field.prototype.setTooltip=function(t){t||""===t||(t=this.sourceBlock_);var e=this.getClickTarget_();e?e.tooltip=t:this.tooltip_=t},t.Field.prototype.getTooltip=function(){var e=this.getClickTarget_();return e?t.Tooltip.getTooltipOfObject(e):t.Tooltip.getTooltipOfObject({tooltip:this.tooltip_})},t.Field.prototype.getClickTarget_=function(){return this.clickTarget_||this.getSvgRoot()},t.Field.prototype.getAbsoluteXY_=function(){return t.utils.style.getPageOffset(this.getClickTarget_())},t.Field.prototype.referencesVariables=function(){return!1},t.Field.prototype.getParentInput=function(){for(var t=null,e=this.sourceBlock_,o=e.inputList,i=0;ie||e>this.fieldRow.length)throw Error("index "+e+" out of bounds.");return o||""==o&&i?("string"==typeof o&&(o=new t.FieldLabel(o)),o.setSourceBlock(this.sourceBlock_),this.sourceBlock_.rendered&&(o.init(),o.applyColour()),o.name=i,o.setVisible(this.isVisible()),(i=o).prefixField&&(e=this.insertFieldAt(e,i.prefixField)),this.fieldRow.splice(e,0,o),++e,i.suffixField&&(e=this.insertFieldAt(e,i.suffixField)),this.sourceBlock_.rendered&&(this.sourceBlock_=this.sourceBlock_,this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours()),e):e},t.Input.prototype.removeField=function(t,e){for(var o,i=0;o=this.fieldRow[i];i++)if(o.name===t)return o.dispose(),this.fieldRow.splice(i,1),this.sourceBlock_.rendered&&(this.sourceBlock_=this.sourceBlock_,this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours()),!0;if(e)return!1;throw Error('Field "'+t+'" not found.')},t.Input.prototype.isVisible=function(){return this.visible_},t.Input.prototype.setVisible=function(t){var e=[];if(this.visible_==t)return e;this.visible_=t;for(var o,i=0;o=this.fieldRow[i];i++)o.setVisible(t);return this.connection&&(this.connection=this.connection,t?e=this.connection.startTrackingAll():this.connection.stopTrackingAll(),i=this.connection.targetBlock())&&(i.getSvgRoot().style.display=t?"block":"none"),e},t.Input.prototype.markDirty=function(){for(var t,e=0;t=this.fieldRow[e];e++)t.markDirty()},t.Input.prototype.setCheck=function(t){if(!this.connection)throw Error("This input does not have a connection.");return this.connection.setCheck(t),this},t.Input.prototype.setAlign=function(t){return this.align=t,this.sourceBlock_.rendered&&(this.sourceBlock_=this.sourceBlock_,this.sourceBlock_.render()),this},t.Input.prototype.setShadowDom=function(t){if(!this.connection)throw Error("This input does not have a connection.");return this.connection.setShadowDom(t),this},t.Input.prototype.getShadowDom=function(){if(!this.connection)throw Error("This input does not have a connection.");return this.connection.getShadowDom()},t.Input.prototype.init=function(){if(this.sourceBlock_.workspace.rendered)for(var t=0;te&&(s=s.substring(0,e-3)+"..."),s},t.Block.prototype.appendValueInput=function(e){return this.appendInput_(t.INPUT_VALUE,e)},t.Block.prototype.appendStatementInput=function(e){return this.appendInput_(t.NEXT_STATEMENT,e)},t.Block.prototype.appendDummyInput=function(e){return this.appendInput_(t.DUMMY_INPUT,e||"")},t.Block.prototype.jsonInit=function(e){var o=e.type?'Block "'+e.type+'": ':"";if(e.output&&e.previousStatement)throw Error(o+"Must not have both an output and a previousStatement.");if(e.style&&e.style.hat&&(this.hat=e.style.hat,e.style=null),e.style&&e.colour)throw Error(o+"Must not have both a colour and a style.");e.style?this.jsonInitStyle_(e,o):this.jsonInitColour_(e,o);for(var i=0;void 0!==e["message"+i];)this.interpolate_(e["message"+i],e["args"+i]||[],e["lastDummyAlign"+i],o),i++;if(void 0!==e.inputsInline&&this.setInputsInline(e.inputsInline),void 0!==e.output&&this.setOutput(!0,e.output),void 0!==e.outputShape&&this.setOutputShape(e.outputShape),void 0!==e.previousStatement&&this.setPreviousStatement(!0,e.previousStatement),void 0!==e.nextStatement&&this.setNextStatement(!0,e.nextStatement),void 0!==e.tooltip&&(i=e.tooltip,i=t.utils.replaceMessageReferences(i),this.setTooltip(i)),void 0!==e.enableContextMenu&&(i=e.enableContextMenu,this.contextMenu=!!i),void 0!==e.helpUrl&&(i=e.helpUrl,i=t.utils.replaceMessageReferences(i),this.setHelpUrl(i)),"string"==typeof e.extensions&&(console.warn(o+"JSON attribute 'extensions' should be an array of strings. Found raw string in JSON for '"+e.type+"' block."),e.extensions=[e.extensions]),void 0!==e.mutator&&t.Extensions.apply(e.mutator,this,!0),Array.isArray(e.extensions))for(e=e.extensions,o=0;o=c||c>o.length)throw Error('Block "'+this.type+'": Message index %'+c+" out of range.");if(r[c])throw Error('Block "'+this.type+'": Message index %'+c+" duplicated.");r[c]=!0,a++,e.push(o[c-1])}else(c=c.trim())&&e.push(c)}if(a!=o.length)throw Error('Block "'+this.type+'": Message does not reference all '+o.length+" arg(s).");for(e.length&&("string"==typeof e[e.length-1]||t.utils.string.startsWith(e[e.length-1].type,"field_"))&&(l={type:"input_dummy"},i&&(l.align=i),e.push(l)),i={LEFT:t.ALIGN_LEFT,RIGHT:t.ALIGN_RIGHT,CENTRE:t.ALIGN_CENTRE,CENTER:t.ALIGN_CENTRE},o=[],l=0;l=this.inputList.length)throw RangeError("Input index "+t+" out of bounds.");if(e>this.inputList.length)throw RangeError("Reference input "+e+" out of bounds.");var o=this.inputList[t];this.inputList.splice(t,1),tt?this.menuItems_.length:t,-1)},t.Menu.prototype.highlightFirst_=function(){this.highlightHelper_(-1,1)},t.Menu.prototype.highlightLast_=function(){this.highlightHelper_(this.menuItems_.length,-1)},t.Menu.prototype.highlightHelper_=function(t,e){t+=e;for(var o;o=this.menuItems_[t];){if(o.isEnabled()){this.setHighlighted(o);break}t+=e}},t.Menu.prototype.handleMouseOver_=function(t){(t=this.getMenuItem_(t.target))&&(t.isEnabled()?this.highlightedItem_!=t&&this.setHighlighted(t):this.setHighlighted(null))},t.Menu.prototype.handleClick_=function(e){var o=this.openingCoords;if(this.openingCoords=null,o&&"number"==typeof e.clientX){var i=new t.utils.Coordinate(e.clientX,e.clientY);if(1>t.utils.Coordinate.distance(o,i))return}(e=this.getMenuItem_(e.target))&&e.performAction()},t.Menu.prototype.handleMouseEnter_=function(t){this.focus()},t.Menu.prototype.handleMouseLeave_=function(t){this.getElement()&&(this.blur_(),this.setHighlighted(null))},t.Menu.prototype.handleKeyEvent_=function(e){if(this.menuItems_.length&&!(e.shiftKey||e.ctrlKey||e.metaKey||e.altKey)){var o=this.highlightedItem_;switch(e.keyCode){case t.utils.KeyCodes.ENTER:case t.utils.KeyCodes.SPACE:o&&o.performAction();break;case t.utils.KeyCodes.UP:this.highlightPrevious();break;case t.utils.KeyCodes.DOWN:this.highlightNext();break;case t.utils.KeyCodes.PAGE_UP:case t.utils.KeyCodes.HOME:this.highlightFirst_();break;case t.utils.KeyCodes.PAGE_DOWN:case t.utils.KeyCodes.END:this.highlightLast_();break;default:return}e.preventDefault(),e.stopPropagation()}},t.Menu.prototype.getSize=function(){var e=this.getElement(),o=t.utils.style.getSize(e);return o.height=e.scrollHeight,o},t.MenuItem=function(t,e){this.content_=t,this.value_=e,this.enabled_=!0,this.element_=null,this.rightToLeft_=!1,this.roleName_=null,this.highlight_=this.checked_=this.checkable_=!1,this.actionHandler_=null},t.MenuItem.prototype.createDom=function(){var e=document.createElement("div");e.id=t.utils.IdGenerator.getNextUniqueId(),this.element_=e,e.className="blocklyMenuItem goog-menuitem "+(this.enabled_?"":"blocklyMenuItemDisabled goog-menuitem-disabled ")+(this.checked_?"blocklyMenuItemSelected goog-option-selected ":"")+(this.highlight_?"blocklyMenuItemHighlight goog-menuitem-highlight ":"")+(this.rightToLeft_?"blocklyMenuItemRtl goog-menuitem-rtl ":"");var o=document.createElement("div");if(o.className="blocklyMenuItemContent goog-menuitem-content",this.checkable_){var i=document.createElement("div");i.className="blocklyMenuItemCheckbox goog-menuitem-checkbox",o.appendChild(i)}return i=this.content_,"string"==typeof this.content_&&(i=document.createTextNode(this.content_)),o.appendChild(i),e.appendChild(o),this.roleName_&&t.utils.aria.setRole(e,this.roleName_),t.utils.aria.setState(e,t.utils.aria.State.SELECTED,this.checkable_&&this.checked_||!1),t.utils.aria.setState(e,t.utils.aria.State.DISABLED,!this.enabled_),e},t.MenuItem.prototype.dispose=function(){this.element_=null},t.MenuItem.prototype.getElement=function(){return this.element_},t.MenuItem.prototype.getId=function(){return this.element_.id},t.MenuItem.prototype.getValue=function(){return this.value_},t.MenuItem.prototype.setRightToLeft=function(t){this.rightToLeft_=t},t.MenuItem.prototype.setRole=function(t){this.roleName_=t},t.MenuItem.prototype.setCheckable=function(t){this.checkable_=t},t.MenuItem.prototype.setChecked=function(t){this.checked_=t},t.MenuItem.prototype.setHighlighted=function(e){this.highlight_=e;var o=this.getElement();o&&this.isEnabled()&&(e?(t.utils.dom.addClass(o,"blocklyMenuItemHighlight"),t.utils.dom.addClass(o,"goog-menuitem-highlight")):(t.utils.dom.removeClass(o,"blocklyMenuItemHighlight"),t.utils.dom.removeClass(o,"goog-menuitem-highlight")))},t.MenuItem.prototype.isEnabled=function(){return this.enabled_},t.MenuItem.prototype.setEnabled=function(t){this.enabled_=t},t.MenuItem.prototype.performAction=function(){this.isEnabled()&&this.actionHandler_&&this.actionHandler_(this)},t.MenuItem.prototype.onAction=function(t,e){this.actionHandler_=t.bind(e)},t.ContextMenu={},t.ContextMenu.currentBlock=null,t.ContextMenu.menu_=null,t.ContextMenu.show=function(e,o,i){if(t.WidgetDiv.show(t.ContextMenu,i,t.ContextMenu.dispose),o.length){var n=t.ContextMenu.populate_(o,i);t.ContextMenu.menu_=n,t.ContextMenu.position_(n,e,i),setTimeout((function(){n.focus()}),1),t.ContextMenu.currentBlock=null}else t.ContextMenu.hide()},t.ContextMenu.populate_=function(e,o){var i=new t.Menu;i.setRole(t.utils.aria.Role.MENU);for(var n,s=0;n=e[s];s++){var r=new t.MenuItem(n.text);r.setRightToLeft(o),r.setRole(t.utils.aria.Role.MENUITEM),i.addChild(r),r.setEnabled(n.enabled),n.enabled&&r.onAction((function(e){t.ContextMenu.hide(),this.callback(this.scope)}),n)}return i},t.ContextMenu.position_=function(e,o,i){var n=t.utils.getViewportBBox();o=new t.utils.Rect(o.clientY+n.top,o.clientY+n.top,o.clientX+n.left,o.clientX+n.left),t.ContextMenu.createWidget_(e);var s=e.getSize();i&&(o.left+=s.width,o.right+=s.width,n.left+=s.width,n.right+=s.width),t.WidgetDiv.positionWithAnchor(n,o,s,i),e.focus()},t.ContextMenu.createWidget_=function(e){e.render(t.WidgetDiv.DIV);var o=e.getElement();t.utils.dom.addClass(o,"blocklyContextMenu"),t.bindEventWithChecks_(o,"contextmenu",null,t.utils.noEvent),e.focus()},t.ContextMenu.hide=function(){t.WidgetDiv.hideIfOwner(t.ContextMenu),t.ContextMenu.currentBlock=null},t.ContextMenu.dispose=function(){t.ContextMenu.menu_&&(t.ContextMenu.menu_.dispose(),t.ContextMenu.menu_=null)},t.ContextMenu.callbackFactory=function(e,o){return function(){t.Events.disable();try{var i=t.Xml.domToBlock(o,e.workspace),n=e.getRelativeToSurfaceXY();n.x=e.RTL?n.x-t.SNAP_RADIUS:n.x+t.SNAP_RADIUS,n.y+=2*t.SNAP_RADIUS,i.moveBy(n.x,n.y)}finally{t.Events.enable()}t.Events.isEnabled()&&!i.isShadow()&&t.Events.fire(new t.Events.BlockCreate(i)),i.select()}},t.ContextMenu.commentDeleteOption=function(e){return{text:t.Msg.REMOVE_COMMENT,enabled:!0,callback:function(){t.Events.setGroup(!0),e.dispose(!0,!0),t.Events.setGroup(!1)}}},t.ContextMenu.commentDuplicateOption=function(e){return{text:t.Msg.DUPLICATE_COMMENT,enabled:!0,callback:function(){t.duplicate(e)}}},t.ContextMenu.workspaceCommentOption=function(e,o){if(!t.WorkspaceCommentSvg)throw Error("Missing require for Blockly.WorkspaceCommentSvg");var i={enabled:!t.utils.userAgent.IE};return i.text=t.Msg.ADD_COMMENT,i.callback=function(){var i=new t.WorkspaceCommentSvg(e,t.Msg.WORKSPACE_COMMENT_DEFAULT_TEXT,t.WorkspaceCommentSvg.DEFAULT_SIZE,t.WorkspaceCommentSvg.DEFAULT_SIZE),n=e.getInjectionDiv().getBoundingClientRect();n=new t.utils.Coordinate(o.clientX-n.left,o.clientY-n.top);var s=e.getOriginOffsetInPixels();(n=t.utils.Coordinate.difference(n,s)).scale(1/e.scale),i.moveBy(n.x,n.y),e.rendered&&(i.initSvg(),i.render(),i.select())},i},t.ContextMenuItems={},t.ContextMenuItems.registerUndo=function(){t.ContextMenuRegistry.registry.register({displayText:function(){return t.Msg.UNDO},preconditionFn:function(t){return 0o.length?t.ContextMenuItems.deleteNext_(o,i):t.confirm(t.Msg.DELETE_ALL_BLOCKS.replace("%1",o.length),(function(e){e&&t.ContextMenuItems.deleteNext_(o,i)}))}},scopeType:t.ContextMenuRegistry.ScopeType.WORKSPACE,id:"workspaceDelete",weight:0})},t.ContextMenuItems.registerWorkspaceOptions_=function(){t.ContextMenuItems.registerUndo(),t.ContextMenuItems.registerRedo(),t.ContextMenuItems.registerCleanup(),t.ContextMenuItems.registerCollapse(),t.ContextMenuItems.registerExpand(),t.ContextMenuItems.registerDeleteAll()},t.ContextMenuItems.registerDuplicate=function(){t.ContextMenuRegistry.registry.register({displayText:function(){return t.Msg.DUPLICATE_BLOCK},preconditionFn:function(t){return!(t=t.block).isInFlyout&&t.isDeletable()&&t.isMovable()?t.isDuplicatable()?"enabled":"disabled":"hidden"},callback:function(e){e.block&&t.duplicate(e.block)},scopeType:t.ContextMenuRegistry.ScopeType.BLOCK,id:"blockDuplicate",weight:0})},t.ContextMenuItems.registerComment=function(){t.ContextMenuRegistry.registry.register({displayText:function(e){return e.block.getCommentIcon()?t.Msg.REMOVE_COMMENT:t.Msg.ADD_COMMENT},preconditionFn:function(e){return e=e.block,t.utils.userAgent.IE||e.isInFlyout||!e.workspace.options.comments||e.isCollapsed()||!e.isEditable()?"hidden":"enabled"},callback:function(t){(t=t.block).getCommentIcon()?t.setCommentText(null):t.setCommentText("")},scopeType:t.ContextMenuRegistry.ScopeType.BLOCK,id:"blockComment",weight:0})},t.ContextMenuItems.registerInline=function(){t.ContextMenuRegistry.registry.register({displayText:function(e){return e.block.getInputsInline()?t.Msg.EXTERNAL_INPUTS:t.Msg.INLINE_INPUTS},preconditionFn:function(e){if(!(e=e.block).isInFlyout&&e.isMovable()&&!e.isCollapsed())for(var o=1;oo)&&t.RenderedConnection.superClass_.isConnectionAllowed.call(this,e)},t.RenderedConnection.prototype.onFailedConnect=function(t){this.bumpAwayFrom(t)},t.RenderedConnection.prototype.disconnectInternal_=function(e,o){t.RenderedConnection.superClass_.disconnectInternal_.call(this,e,o),e.rendered&&e.render(),o.rendered&&(o.updateDisabled(),o.render(),o.getSvgRoot().style.display="block")},t.RenderedConnection.prototype.respawnShadow_=function(){t.RenderedConnection.superClass_.respawnShadow_.call(this);var e=this.targetBlock();e&&(e.initSvg(),e.render(!1),(e=this.getSourceBlock()).rendered&&e.render())},t.RenderedConnection.prototype.neighbours=function(t){return this.dbOpposite_.getNeighbours(this,t)},t.RenderedConnection.prototype.connect_=function(e){t.RenderedConnection.superClass_.connect_.call(this,e);var o=this.getSourceBlock();e=e.getSourceBlock();var i=o.rendered,n=e.rendered;i&&o.updateDisabled(),n&&e.updateDisabled(),i&&n&&(this.type==t.NEXT_STATEMENT||this.type==t.PREVIOUS_STATEMENT?e.render():o.render()),(o=o.getInputWithBlock(e))&&(o=o.isVisible(),e.getSvgRoot().style.display=o?"block":"none")},t.RenderedConnection.prototype.onCheckChanged_=function(){!this.isConnected()||this.targetConnection&&this.getConnectionChecker().canConnect(this,this.targetConnection,!1)||((this.isSuperior()?this.targetBlock():this.sourceBlock_).unplug(),this.sourceBlock_.bumpNeighbours())},t.Marker=function(){this.drawer_=this.curNode_=this.colour=null,this.type="marker"},t.Marker.prototype.setDrawer=function(t){this.drawer_=t},t.Marker.prototype.getDrawer=function(){return this.drawer_},t.Marker.prototype.getCurNode=function(){return this.curNode_},t.Marker.prototype.setCurNode=function(t){var e=this.curNode_;this.curNode_=t,this.drawer_&&this.drawer_.draw(e,this.curNode_)},t.Marker.prototype.draw=function(){this.drawer_&&this.drawer_.draw(this.curNode_,this.curNode_)},t.Marker.prototype.hide=function(){this.drawer_&&this.drawer_.hide()},t.Marker.prototype.dispose=function(){this.getDrawer()&&this.getDrawer().dispose()},t.Cursor=function(){t.Cursor.superClass_.constructor.call(this),this.type="cursor"},t.utils.object.inherits(t.Cursor,t.Marker),t.Cursor.prototype.next=function(){var e=this.getCurNode();if(!e)return null;for(e=e.next();e&&e.next()&&(e.getType()==t.ASTNode.types.NEXT||e.getType()==t.ASTNode.types.BLOCK);)e=e.next();return e&&this.setCurNode(e),e},t.Cursor.prototype.in=function(){var e=this.getCurNode();return e?(e.getType()!=t.ASTNode.types.PREVIOUS&&e.getType()!=t.ASTNode.types.OUTPUT||(e=e.next()),(e=e.in())&&this.setCurNode(e),e):null},t.Cursor.prototype.prev=function(){var e=this.getCurNode();if(!e)return null;for(e=e.prev();e&&e.prev()&&(e.getType()==t.ASTNode.types.NEXT||e.getType()==t.ASTNode.types.BLOCK);)e=e.prev();return e&&this.setCurNode(e),e},t.Cursor.prototype.out=function(){var e=this.getCurNode();return e?((e=e.out())&&e.getType()==t.ASTNode.types.BLOCK&&(e=e.prev()||e),e&&this.setCurNode(e),e):null},t.Cursor.prototype.onBlocklyAction=function(e){if(this.getCurNode()&&this.getCurNode().getType()===t.ASTNode.types.FIELD&&this.getCurNode().getLocation().onBlocklyAction(e))return!0;switch(e.name){case t.navigation.actionNames.PREVIOUS:return this.prev(),!0;case t.navigation.actionNames.OUT:return this.out(),!0;case t.navigation.actionNames.NEXT:return this.next(),!0;case t.navigation.actionNames.IN:return this.in(),!0;default:return!1}},t.BasicCursor=function(){t.BasicCursor.superClass_.constructor.call(this)},t.utils.object.inherits(t.BasicCursor,t.Cursor),t.BasicCursor.prototype.next=function(){var t=this.getCurNode();return t?((t=this.getNextNode_(t,this.validNode_))&&this.setCurNode(t),t):null},t.BasicCursor.prototype.in=function(){return this.next()},t.BasicCursor.prototype.prev=function(){var t=this.getCurNode();return t?((t=this.getPreviousNode_(t,this.validNode_))&&this.setCurNode(t),t):null},t.BasicCursor.prototype.out=function(){return this.prev()},t.BasicCursor.prototype.getNextNode_=function(t,e){if(!t)return null;var o=t.in()||t.next();return e(o)?o:o?this.getNextNode_(o,e):e(t=this.findSiblingOrParent_(t.out()))?t:t?this.getNextNode_(t,e):null},t.BasicCursor.prototype.getPreviousNode_=function(t,e){if(!t)return null;var o=t.prev();return e(o=o?this.getRightMostChild_(o):t.out())?o:o?this.getPreviousNode_(o,e):null},t.BasicCursor.prototype.validNode_=function(e){var o=!1;return(e=e&&e.getType())!=t.ASTNode.types.OUTPUT&&e!=t.ASTNode.types.INPUT&&e!=t.ASTNode.types.FIELD&&e!=t.ASTNode.types.NEXT&&e!=t.ASTNode.types.PREVIOUS&&e!=t.ASTNode.types.WORKSPACE||(o=!0),o},t.BasicCursor.prototype.findSiblingOrParent_=function(t){if(!t)return null;var e=t.next();return e||this.findSiblingOrParent_(t.out())},t.BasicCursor.prototype.getRightMostChild_=function(t){if(!t.in())return t;for(t=t.in();t.next();)t=t.next();return this.getRightMostChild_(t)},t.TabNavigateCursor=function(){t.TabNavigateCursor.superClass_.constructor.call(this)},t.utils.object.inherits(t.TabNavigateCursor,t.BasicCursor),t.TabNavigateCursor.prototype.validNode_=function(e){var o=!1,i=e&&e.getType();return e&&(e=e.getLocation(),i==t.ASTNode.types.FIELD&&e&&e.isTabNavigable()&&e.isClickable()&&(o=!0)),o},t.BlockSvg=function(e,o,i){this.svgGroup_=t.utils.dom.createSvgElement(t.utils.Svg.G,{},null),this.svgGroup_.translate_="",this.style=e.getRenderer().getConstants().getBlockStyle(null),this.pathObject=e.getRenderer().makePathObject(this.svgGroup_,this.style),this.renderIsInProgress_=this.rendered=!1,this.workspace=e,this.previousConnection=this.nextConnection=this.outputConnection=null,this.useDragSurface_=t.utils.is3dSupported()&&!!e.getBlockDragSurface();var n=this.pathObject.svgPath;n.tooltip=this,t.Tooltip.bindMouseEvents(n),t.BlockSvg.superClass_.constructor.call(this,e,o,i),this.svgGroup_.dataset&&(this.svgGroup_.dataset.id=this.id)},t.utils.object.inherits(t.BlockSvg,t.Block),t.BlockSvg.prototype.height=0,t.BlockSvg.prototype.width=0,t.BlockSvg.prototype.warningTextDb_=null,t.BlockSvg.INLINE=-1,t.BlockSvg.COLLAPSED_WARNING_ID="TEMP_COLLAPSED_WARNING_",t.BlockSvg.prototype.initSvg=function(){if(!this.workspace.rendered)throw TypeError("Workspace is headless.");for(var e,o=0;e=this.inputList[o];o++)e.init();for(e=this.getIcons(),o=0;o=this.connections_.length)return-1;e=t.y;for(var i=o;0<=i&&this.connections_[i].y==e;){if(this.connections_[i]==t)return i;i--}for(;ot)){e=i;break}o=i}}return e},t.ConnectionDB.prototype.removeConnection=function(t,e){if(-1==(t=this.findIndexOfConnection_(t,e)))throw Error("Unable to find connection in connectionDB.");this.connections_.splice(t,1)},t.ConnectionDB.prototype.getNeighbours=function(t,e){function o(t){var o=n-i[t].x,r=s-i[t].y;return Math.sqrt(o*o+r*r)<=e&&l.push(i[t]),r(t=this.subscribedWorkspaces_.indexOf(t)))throw Error("Cannot unsubscribe a workspace that hasn't been subscribed.");this.subscribedWorkspaces_.splice(t,1)},t.ThemeManager.prototype.subscribe=function(t,e,o){this.componentDB_[e]||(this.componentDB_[e]=[]),this.componentDB_[e].push({element:t,propertyName:o}),e=this.theme_&&this.theme_.getComponentStyle(e),t.style[o]=e||""},t.ThemeManager.prototype.unsubscribe=function(t){if(t)for(var e,o=Object.keys(this.componentDB_),i=0;e=o[i];i++){for(var n=this.componentDB_[e],s=n.length-1;0<=s;s--)n[s].element===t&&n.splice(s,1);this.componentDB_[e].length||delete this.componentDB_[e]}},t.ThemeManager.prototype.dispose=function(){this.componentDB_=this.subscribedWorkspaces_=this.theme_=this.owner_=null},t.TouchGesture=function(e,o){t.TouchGesture.superClass_.constructor.call(this,e,o),this.isMultiTouch_=!1,this.cachedPoints_=Object.create(null),this.startDistance_=this.previousScale_=0,this.isPinchZoomEnabled_=this.onStartWrapper_=null},t.utils.object.inherits(t.TouchGesture,t.Gesture),t.TouchGesture.ZOOM_IN_MULTIPLIER=5,t.TouchGesture.ZOOM_OUT_MULTIPLIER=6,t.TouchGesture.prototype.doStart=function(e){this.isPinchZoomEnabled_=this.startWorkspace_.options.zoomOptions&&this.startWorkspace_.options.zoomOptions.pinch,t.TouchGesture.superClass_.doStart.call(this,e),!this.isEnding_&&t.Touch.isTouchEvent(e)&&this.handleTouchStart(e)},t.TouchGesture.prototype.bindMouseEvents=function(e){this.onStartWrapper_=t.bindEventWithChecks_(document,"mousedown",null,this.handleStart.bind(this),!0),this.onMoveWrapper_=t.bindEventWithChecks_(document,"mousemove",null,this.handleMove.bind(this),!0),this.onUpWrapper_=t.bindEventWithChecks_(document,"mouseup",null,this.handleUp.bind(this),!0),e.preventDefault(),e.stopPropagation()},t.TouchGesture.prototype.handleStart=function(e){!this.isDragging()&&t.Touch.isTouchEvent(e)&&(this.handleTouchStart(e),this.isMultiTouch()&&t.longStop_())},t.TouchGesture.prototype.handleMove=function(e){this.isDragging()?t.Touch.shouldHandleEvent(e)&&t.TouchGesture.superClass_.handleMove.call(this,e):this.isMultiTouch()?(t.Touch.isTouchEvent(e)&&this.handleTouchMove(e),t.longStop_()):t.TouchGesture.superClass_.handleMove.call(this,e)},t.TouchGesture.prototype.handleUp=function(e){t.Touch.isTouchEvent(e)&&!this.isDragging()&&this.handleTouchEnd(e),!this.isMultiTouch()||this.isDragging()?t.Touch.shouldHandleEvent(e)&&t.TouchGesture.superClass_.handleUp.call(this,e):(e.preventDefault(),e.stopPropagation(),this.dispose())},t.TouchGesture.prototype.isMultiTouch=function(){return this.isMultiTouch_},t.TouchGesture.prototype.dispose=function(){t.TouchGesture.superClass_.dispose.call(this),this.onStartWrapper_&&t.unbindEvent_(this.onStartWrapper_)},t.TouchGesture.prototype.handleTouchStart=function(e){var o=t.Touch.getTouchIdentifierFromEvent(e);this.cachedPoints_[o]=this.getTouchPoint(e),2==(o=Object.keys(this.cachedPoints_)).length&&(this.startDistance_=t.utils.Coordinate.distance(this.cachedPoints_[o[0]],this.cachedPoints_[o[1]]),this.isMultiTouch_=!0,e.preventDefault())},t.TouchGesture.prototype.handleTouchMove=function(e){var o=t.Touch.getTouchIdentifierFromEvent(e);this.cachedPoints_[o]=this.getTouchPoint(e),o=Object.keys(this.cachedPoints_),this.isPinchZoomEnabled_&&2===o.length?this.handlePinch_(e):t.TouchGesture.superClass_.handleMove.call(this,e)},t.TouchGesture.prototype.handlePinch_=function(e){var o=Object.keys(this.cachedPoints_);if(o=t.utils.Coordinate.distance(this.cachedPoints_[o[0]],this.cachedPoints_[o[1]])/this.startDistance_,0this.previousScale_){var i=o-this.previousScale_;i=0Object.keys(this.cachedPoints_).length&&(this.cachedPoints_=Object.create(null),this.previousScale_=0)},t.TouchGesture.prototype.getTouchPoint=function(e){return this.startWorkspace_?new t.utils.Coordinate(e.pageX?e.pageX:e.changedTouches[0].pageX,e.pageY?e.pageY:e.changedTouches[0].pageY):null},t.WorkspaceAudio=function(t){this.parentWorkspace_=t,this.SOUNDS_=Object.create(null)},t.WorkspaceAudio.prototype.lastSound_=null,t.WorkspaceAudio.prototype.dispose=function(){this.SOUNDS_=this.parentWorkspace_=null},t.WorkspaceAudio.prototype.load=function(e,o){if(e.length){try{var i=new t.utils.global.Audio}catch(t){return}for(var n,s=0;s=this.remainingCapacity()||(this.currentGesture_&&this.currentGesture_.cancel(),"comment"==t.tagName.toLowerCase()?this.pasteWorkspaceComment_(t):this.pasteBlock_(t))},t.WorkspaceSvg.prototype.pasteBlock_=function(e){t.Events.disable();try{var o=t.Xml.domToBlock(e,this),i=this.getMarker(t.navigation.MARKER_NAME).getCurNode();if(this.keyboardAccessibilityMode&&i&&i.isConnection()){var n=i.getLocation();return void t.navigation.insertBlock(o,n)}var s=parseInt(e.getAttribute("x"),10),r=parseInt(e.getAttribute("y"),10);if(!isNaN(s)&&!isNaN(r)){this.RTL&&(s=-s);do{e=!1;var a,l=this.getAllBlocks(!1);for(i=0;a=l[i];i++){var c=a.getRelativeToSurfaceXY();if(1>=Math.abs(s-c.x)&&1>=Math.abs(r-c.y)){e=!0;break}}if(!e){var u,h=o.getConnections_(!1);for(i=0;u=h[i];i++)if(u.closest(t.SNAP_RADIUS,new t.utils.Coordinate(s,r)).connection){e=!0;break}}e&&(s=this.RTL?s-t.SNAP_RADIUS:s+t.SNAP_RADIUS,r+=2*t.SNAP_RADIUS)}while(e);o.moveBy(s,r)}}finally{t.Events.enable()}t.Events.isEnabled()&&!o.isShadow()&&t.Events.fire(new t.Events.BlockCreate(o)),o.select()},t.WorkspaceSvg.prototype.pasteWorkspaceComment_=function(e){t.Events.disable();try{var o=t.WorkspaceCommentSvg.fromXml(e,this),i=parseInt(e.getAttribute("x"),10),n=parseInt(e.getAttribute("y"),10);isNaN(i)||isNaN(n)||(this.RTL&&(i=-i),o.moveBy(i+50,n+50))}finally{t.Events.enable()}t.Events.isEnabled(),o.select()},t.WorkspaceSvg.prototype.refreshToolboxSelection=function(){var t=this.isFlyout?this.targetWorkspace:this;t&&!t.currentGesture_&&t.toolbox_&&t.toolbox_.getFlyout()&&t.toolbox_.refreshSelection()},t.WorkspaceSvg.prototype.renameVariableById=function(e,o){t.WorkspaceSvg.superClass_.renameVariableById.call(this,e,o),this.refreshToolboxSelection()},t.WorkspaceSvg.prototype.deleteVariableById=function(e){t.WorkspaceSvg.superClass_.deleteVariableById.call(this,e),this.refreshToolboxSelection()},t.WorkspaceSvg.prototype.createVariable=function(e,o,i){return e=t.WorkspaceSvg.superClass_.createVariable.call(this,e,o,i),this.refreshToolboxSelection(),e},t.WorkspaceSvg.prototype.recordDeleteAreas=function(){this.deleteAreaTrash_=this.trashcan&&this.svgGroup_.parentNode?this.trashcan.getClientRect():null,this.deleteAreaToolbox_=this.flyout_?this.flyout_.getClientRect():this.toolbox_&&"function"==typeof this.toolbox_.getClientRect?this.toolbox_.getClientRect():null},t.WorkspaceSvg.prototype.isDeleteArea=function(e){return this.deleteAreaTrash_&&this.deleteAreaTrash_.contains(e.clientX,e.clientY)?t.DELETE_AREA_TRASH:this.deleteAreaToolbox_&&this.deleteAreaToolbox_.contains(e.clientX,e.clientY)?t.DELETE_AREA_TOOLBOX:t.DELETE_AREA_NONE},t.WorkspaceSvg.prototype.onMouseDown_=function(t){var e=this.getGesture(t);e&&e.handleWsStart(t,this)},t.WorkspaceSvg.prototype.startDrag=function(e,o){(e=t.utils.mouseToSvg(e,this.getParentSvg(),this.getInverseScreenCTM())).x/=this.scale,e.y/=this.scale,this.dragDeltaXY_=t.utils.Coordinate.difference(o,e)},t.WorkspaceSvg.prototype.moveDrag=function(e){return(e=t.utils.mouseToSvg(e,this.getParentSvg(),this.getInverseScreenCTM())).x/=this.scale,e.y/=this.scale,t.utils.Coordinate.sum(this.dragDeltaXY_,e)},t.WorkspaceSvg.prototype.isDragging=function(){return null!=this.currentGesture_&&this.currentGesture_.isDragging()},t.WorkspaceSvg.prototype.isDraggable=function(){return this.options.moveOptions&&this.options.moveOptions.drag},t.WorkspaceSvg.prototype.isContentBounded=function(){return this.options.moveOptions&&this.options.moveOptions.scrollbars||this.options.moveOptions&&this.options.moveOptions.wheel||this.options.moveOptions&&this.options.moveOptions.drag||this.options.zoomOptions&&this.options.zoomOptions.controls||this.options.zoomOptions&&this.options.zoomOptions.wheel||this.options.zoomOptions&&this.options.zoomOptions.pinch},t.WorkspaceSvg.prototype.isMovable=function(){return this.options.moveOptions&&this.options.moveOptions.scrollbars||this.options.moveOptions&&this.options.moveOptions.wheel||this.options.moveOptions&&this.options.moveOptions.drag||this.options.zoomOptions&&this.options.zoomOptions.wheel||this.options.zoomOptions&&this.options.zoomOptions.pinch},t.WorkspaceSvg.prototype.onMouseWheel_=function(e){if(t.Gesture.inProgress())e.preventDefault(),e.stopPropagation();else{var o=this.options.zoomOptions&&this.options.zoomOptions.wheel,i=this.options.moveOptions&&this.options.moveOptions.wheel;if(o||i){var n=t.utils.getScrollDeltaPixels(e);!o||!e.ctrlKey&&i?(o=this.scrollX-n.x,i=this.scrollY-n.y,e.shiftKey&&!n.x&&(o=this.scrollX-n.y,i=this.scrollY),this.scroll(o,i)):(n=-n.y/50,o=t.utils.mouseToSvg(e,this.getParentSvg(),this.getInverseScreenCTM()),this.zoom(o.x,o.y,n)),e.preventDefault()}}},t.WorkspaceSvg.prototype.getBlocksBoundingBox=function(){var e=this.getTopBoundedElements();if(!e.length)return new t.utils.Rect(0,0,0,0);for(var o=e[0].getBoundingRectangle(),i=1;io.bottom&&(o.bottom=n.bottom),n.lefto.right&&(o.right=n.right)}return o},t.WorkspaceSvg.prototype.cleanUp=function(){this.setResizesEnabled(!1),t.Events.setGroup(!0);for(var e,o=this.getTopBlocks(!0),i=0,n=0;e=o[n];n++)if(e.isMovable()){var s=e.getRelativeToSurfaceXY();e.moveBy(-s.x,i-s.y),e.snapToGrid(),i=e.getRelativeToSurfaceXY().y+e.getHeightWidth().height+this.renderer_.getConstants().MIN_BLOCK_HEIGHT}t.Events.setGroup(!1),this.setResizesEnabled(!0)},t.WorkspaceSvg.prototype.showContextMenu=function(e){if(!this.options.readOnly&&!this.isFlyout){var o=t.ContextMenuRegistry.registry.getContextMenuOptions(t.ContextMenuRegistry.ScopeType.WORKSPACE,{workspace:this});this.configureContextMenu&&this.configureContextMenu(o,e),t.ContextMenu.show(e,o,this.RTL)}},t.WorkspaceSvg.prototype.updateToolbox=function(e){if(e=t.utils.toolbox.convertToolboxDefToJson(e)){if(!this.options.languageTree)throw Error("Existing toolbox is null. Can't create new toolbox.");if(t.utils.toolbox.hasCategories(e)){if(!this.toolbox_)throw Error("Existing toolbox has no categories. Can't change mode.");this.options.languageTree=e,this.toolbox_.render(e)}else{if(!this.flyout_)throw Error("Existing toolbox has categories. Can't change mode.");this.options.languageTree=e,this.flyout_.show(e)}}else if(this.options.languageTree)throw Error("Can't nullify an existing toolbox.")},t.WorkspaceSvg.prototype.markFocused=function(){this.options.parentWorkspace?this.options.parentWorkspace.markFocused():(t.mainWorkspace=this,this.setBrowserFocus())},t.WorkspaceSvg.prototype.setBrowserFocus=function(){document.activeElement&&document.activeElement.blur();try{this.getParentSvg().focus({preventScroll:!0})}catch(t){try{this.getParentSvg().parentNode.setActive()}catch(t){this.getParentSvg().parentNode.focus({preventScroll:!0})}}},t.WorkspaceSvg.prototype.zoom=function(t,e,o){o=Math.pow(this.options.zoomOptions.scaleSpeed,o);var i=this.scale*o;if(this.scale!=i){i>this.options.zoomOptions.maxScale?o=this.options.zoomOptions.maxScale/this.scale:ithis.options.zoomOptions.maxScale?e=this.options.zoomOptions.maxScale:this.options.zoomOptions.minScale&&eo.viewBottom||o.contentLefto.viewRight){switch(i=null,e&&(i=t.Events.getGroup(),t.Events.setGroup(e.group)),e.type){case t.Events.BLOCK_CREATE:case t.Events.BLOCK_MOVE:var r=s.getBlockById(e.blockId);r&&(r=r.getRootBlock());break;case t.Events.COMMENT_CREATE:case t.Events.COMMENT_MOVE:r=s.getCommentById(e.commentId)}if(r){(n=r.getBoundingRectangle()).height=n.bottom-n.top,n.width=n.right-n.left;var a=o.viewTop,l=o.viewBottom-n.height;l=Math.max(a,l),a=t.utils.math.clamp(a,n.top,l)-n.top,l=o.viewLeft;var c=o.viewRight-n.width;o.RTL?l=Math.min(c,l):c=Math.max(l,c),o=t.utils.math.clamp(l,n.left,c)-n.left,r.moveBy(o,a)}e&&(!e.group&&r&&console.warn("Moved object in bounds but there was no event group. This may break undo."),null!==i&&t.Events.setGroup(i))}}})),t.svgResize(s),t.WidgetDiv.createDom(),t.DropDownDiv.createDom(),t.Tooltip.createDom(),s},t.init_=function(e){var o=e.options,i=e.getParentSvg();if(t.bindEventWithChecks_(i.parentNode,"contextmenu",null,(function(e){t.utils.isTargetInput(e)||e.preventDefault()})),i=t.bindEventWithChecks_(window,"resize",null,(function(){t.hideChaff(!0),t.svgResize(e)})),e.setResizeHandlerWrapper(i),t.inject.bindDocumentEvents_(),o.languageTree){i=e.getToolbox();var n=e.getFlyout(!0);i?i.init():n&&(n.init(e),n.show(o.languageTree),"function"==typeof n.scrollToStart&&n.scrollToStart())}i=t.Scrollbar.scrollbarThickness,o.hasTrashcan&&(i=e.trashcan.init(i)),o.zoomOptions&&o.zoomOptions.controls&&e.zoomControls_.init(i),o.moveOptions&&o.moveOptions.scrollbars?(e.scrollbar=new t.ScrollbarPair(e),e.scrollbar.resize()):e.setMetrics({x:.5,y:.5}),o.hasSounds&&t.inject.loadSounds_(o.pathToMedia,e)},t.inject.bindDocumentEvents_=function(){t.documentEventsBound_||(t.bindEventWithChecks_(document,"scroll",null,(function(){for(var e,o=t.Workspace.getAll(),i=0;e=o[i];i++)e.updateInverseScreenCTM&&e.updateInverseScreenCTM()})),t.bindEventWithChecks_(document,"keydown",null,t.onKeyDown),t.bindEvent_(document,"touchend",null,t.longStop_),t.bindEvent_(document,"touchcancel",null,t.longStop_),t.utils.userAgent.IPAD&&t.bindEventWithChecks_(window,"orientationchange",document,(function(){t.svgResize(t.getMainWorkspace())}))),t.documentEventsBound_=!0},t.inject.loadSounds_=function(e,o){var i=o.getAudioManager();i.load([e+"click.mp3",e+"click.wav",e+"click.ogg"],"click"),i.load([e+"disconnect.wav",e+"disconnect.mp3",e+"disconnect.ogg"],"disconnect"),i.load([e+"delete.mp3",e+"delete.ogg",e+"delete.wav"],"delete");var n=[];e=function(){for(;n.length;)t.unbindEvent_(n.pop());i.preload()},n.push(t.bindEventWithChecks_(document,"mousemove",null,e,!0)),n.push(t.bindEventWithChecks_(document,"touchstart",null,e,!0))},t.Names=function(t,e){if(this.variablePrefix_=e||"",this.reservedDict_=Object.create(null),t)for(t=t.split(","),e=0;e1'),n.appendChild(i),o.push(n)),t.Blocks.variables_get){e.sort(t.VariableModel.compareByName),i=0;for(var s;s=e[i];i++)(n=t.utils.xml.createElement("block")).setAttribute("type","variables_get"),n.setAttribute("gap",8),n.appendChild(t.Variables.generateVariableFieldDom(s)),o.push(n)}}return o},t.Variables.VAR_LETTER_OPTIONS="ijkmnopqrstuvwxyzabcdefgh",t.Variables.generateUniqueName=function(e){return t.Variables.generateUniqueNameFromOptions(t.Variables.VAR_LETTER_OPTIONS.charAt(0),e.getAllVariableNames())},t.Variables.generateUniqueNameFromOptions=function(e,o){if(!o.length)return e;for(var i=t.Variables.VAR_LETTER_OPTIONS,n="",s=i.indexOf(e);;){for(var r=!1,a=0;as?t.WidgetDiv.positionInternal_(e,0,i.height+s):t.WidgetDiv.positionInternal_(e,s,i.height)},t.WidgetDiv.calculateX_=function(t,e,o,i){return i?(e=Math.max(e.right-o.width,t.left),Math.min(e,t.right-o.width)):(e=Math.min(e.left,t.right-o.width),Math.max(e,t.left))},t.WidgetDiv.calculateY_=function(t,e,o){return e.bottom+o.height>=t.bottom?e.top-o.height:e.bottom},t.VERSION="3.20200924.4",t.mainWorkspace=null,t.selected=null,t.draggingConnections=[],t.clipboardXml_=null,t.clipboardSource_=null,t.clipboardTypeCounts_=null,t.cache3dSupported_=null,t.parentContainer=null,t.svgSize=function(e){return new t.utils.Size(e.cachedWidth_,e.cachedHeight_)},t.resizeSvgContents=function(t){t.resizeContents()},t.svgResize=function(t){for(;t.options.parentWorkspace;)t=t.options.parentWorkspace;var e=t.getParentSvg(),o=e.parentNode;if(o){var i=o.offsetWidth;o=o.offsetHeight,e.cachedWidth_!=i&&(e.setAttribute("width",i+"px"),e.cachedWidth_=i),e.cachedHeight_!=o&&(e.setAttribute("height",o+"px"),e.cachedHeight_=o),t.resize()}},t.onKeyDown=function(e){var o=t.mainWorkspace;if(o&&!(t.utils.isTargetInput(e)||o.rendered&&!o.isVisible()))if(o.options.readOnly)t.navigation.onKeyPress(e);else{var i=!1;if(e.keyCode==t.utils.KeyCodes.ESC)t.hideChaff(),t.navigation.onBlocklyAction(t.navigation.ACTION_EXIT);else{if(!t.Gesture.inProgress()&&t.navigation.onKeyPress(e))return;if(e.keyCode==t.utils.KeyCodes.BACKSPACE||e.keyCode==t.utils.KeyCodes.DELETE){if(e.preventDefault(),t.Gesture.inProgress())return;t.selected&&t.selected.isDeletable()&&(i=!0)}else if(e.altKey||e.ctrlKey||e.metaKey){if(t.Gesture.inProgress())return;t.selected&&t.selected.isDeletable()&&t.selected.isMovable()&&(e.keyCode==t.utils.KeyCodes.C?(t.hideChaff(),t.copy_(t.selected)):e.keyCode!=t.utils.KeyCodes.X||t.selected.workspace.isFlyout||(t.copy_(t.selected),i=!0)),e.keyCode==t.utils.KeyCodes.V?t.clipboardXml_&&((e=t.clipboardSource_).isFlyout&&(e=e.targetWorkspace),t.clipboardTypeCounts_&&e.isCapacityAvailable(t.clipboardTypeCounts_)&&(t.Events.setGroup(!0),e.paste(t.clipboardXml_),t.Events.setGroup(!1))):e.keyCode==t.utils.KeyCodes.Z?(t.hideChaff(),o.undo(e.shiftKey)):e.ctrlKey&&e.keyCode==t.utils.KeyCodes.Y&&(t.hideChaff(),o.undo(!0))}}i&&!t.selected.workspace.isFlyout&&(t.Events.setGroup(!0),t.hideChaff(),t.selected.dispose(!0,!0),t.Events.setGroup(!1))}},t.copy_=function(e){(e=e.toCopyData())&&(t.clipboardXml_=e.xml,t.clipboardSource_=e.source,t.clipboardTypeCounts_=e.typeCounts)},t.duplicate=function(e){var o=t.clipboardXml_,i=t.clipboardSource_;t.copy_(e),e.workspace.paste(t.clipboardXml_),t.clipboardXml_=o,t.clipboardSource_=i},t.onContextMenu_=function(e){t.utils.isTargetInput(e)||e.preventDefault()},t.hideChaff=function(e){t.Tooltip.hide(),t.WidgetDiv.hide(),t.DropDownDiv.hideWithoutAnimation(),e||((e=t.getMainWorkspace()).trashcan&&e.trashcan.flyout&&e.trashcan.closeFlyout(),(e=e.getToolbox())&&e.getFlyout()&&e.getFlyout().autoClose&&e.clearSelection())},t.getMainWorkspace=function(){return t.mainWorkspace},t.alert=function(t,e){alert(t),e&&e()},t.confirm=function(t,e){e(confirm(t))},t.prompt=function(t,e,o){o(prompt(t,e))},t.jsonInitFactory_=function(t){return function(){this.jsonInit(t)}},t.defineBlocksWithJsonArray=function(e){for(var o=0;o90-e||t>-90-e&&t<-90+e},t.HorizontalFlyout.prototype.getClientRect=function(){if(!this.svgGroup_)return null;var e=this.svgGroup_.getBoundingClientRect(),o=e.top;return this.toolboxPosition_==t.TOOLBOX_AT_TOP?new t.utils.Rect(-1e9,o+e.height,-1e9,1e9):new t.utils.Rect(o,1e9,-1e9,1e9)},t.HorizontalFlyout.prototype.reflowInternal_=function(){this.workspace_.scale=this.targetWorkspace.scale;for(var e,o=0,i=this.workspace_.getTopBlocks(!1),n=0;e=i[n];n++)o=Math.max(o,e.getHeightWidth().height);if(o+=1.5*this.MARGIN,o*=this.workspace_.scale,o+=t.Scrollbar.scrollbarThickness,this.height_!=o){for(n=0;e=i[n];n++)e.flyoutRect_&&this.moveRectToBlock_(e.flyoutRect_,e);this.targetWorkspace.toolboxPosition!=this.toolboxPosition_||this.toolboxPosition_!=t.TOOLBOX_AT_TOP||this.targetWorkspace.getToolbox()||this.targetWorkspace.translate(this.targetWorkspace.scrollX,this.targetWorkspace.scrollY+o),this.height_=o,this.position()}},t.registry.register(t.registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX,t.registry.DEFAULT,t.HorizontalFlyout),t.VerticalFlyout=function(e){t.VerticalFlyout.superClass_.constructor.call(this,e)},t.utils.object.inherits(t.VerticalFlyout,t.Flyout),t.VerticalFlyout.registryName="verticalFlyout",t.VerticalFlyout.prototype.getMetrics_=function(){if(!this.isVisible())return null;try{var t=this.workspace_.getCanvas().getBBox()}catch(e){t={height:0,y:0,width:0,x:0}}var e=this.SCROLLBAR_PADDING,o=this.height_-2*this.SCROLLBAR_PADDING,i=this.width_;return this.RTL||(i-=this.SCROLLBAR_PADDING),{contentHeight:t.height*this.workspace_.scale+2*this.MARGIN,contentWidth:t.width*this.workspace_.scale+2*this.MARGIN,contentTop:t.y,contentLeft:t.x,viewHeight:o,viewWidth:i,viewTop:-this.workspace_.scrollY+t.y,viewLeft:-this.workspace_.scrollX,absoluteTop:e,absoluteLeft:0}},t.VerticalFlyout.prototype.setMetrics_=function(t){var e=this.getMetrics_();e&&("number"==typeof t.y&&(this.workspace_.scrollY=-e.contentHeight*t.y),this.workspace_.translate(this.workspace_.scrollX+e.absoluteLeft,this.workspace_.scrollY+e.absoluteTop))},t.VerticalFlyout.prototype.position=function(){if(this.isVisible()){var e=this.targetWorkspace.getMetrics();e&&(this.height_=e.viewHeight,this.setBackgroundPath_(this.width_-this.CORNER_RADIUS,e.viewHeight-2*this.CORNER_RADIUS),this.positionAt_(this.width_,this.height_,this.targetWorkspace.toolboxPosition==this.toolboxPosition_?e.toolboxWidth?this.toolboxPosition_==t.TOOLBOX_AT_LEFT?e.toolboxWidth:e.viewWidth-this.width_:this.toolboxPosition_==t.TOOLBOX_AT_LEFT?0:e.viewWidth:this.toolboxPosition_==t.TOOLBOX_AT_LEFT?0:e.viewWidth+e.absoluteLeft-this.width_,0))}},t.VerticalFlyout.prototype.setBackgroundPath_=function(e,o){var i=this.toolboxPosition_==t.TOOLBOX_AT_RIGHT,n=e+this.CORNER_RADIUS;(n=["M "+(i?n:0)+",0"]).push("h",i?-e:e),n.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,i?0:1,i?-this.CORNER_RADIUS:this.CORNER_RADIUS,this.CORNER_RADIUS),n.push("v",Math.max(0,o)),n.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,i?0:1,i?this.CORNER_RADIUS:-this.CORNER_RADIUS,this.CORNER_RADIUS),n.push("h",i?e:-e),n.push("z"),this.svgBackground_.setAttribute("d",n.join(" "))},t.VerticalFlyout.prototype.scrollToStart=function(){this.scrollbar.set(0)},t.VerticalFlyout.prototype.wheel_=function(e){var o=t.utils.getScrollDeltaPixels(e);if(o.y){var i=this.getMetrics_();o=i.viewTop-i.contentTop+o.y,o=Math.min(o,i.contentHeight-i.viewHeight),o=Math.max(o,0),this.scrollbar.set(o),t.WidgetDiv.hide(),t.DropDownDiv.hideWithoutAnimation()}e.preventDefault(),e.stopPropagation()},t.VerticalFlyout.prototype.layout_=function(t,e){this.workspace_.scale=this.targetWorkspace.scale;for(var o,i=this.MARGIN,n=this.RTL?i:i+this.tabWidth_,s=0;o=t[s];s++)if("block"==o.type){for(var r,a=(o=o.block).getDescendants(!1),l=0;r=a[l];l++)r.isInFlyout=!0;o.render(),a=o.getSvgRoot(),l=o.getHeightWidth(),r=o.outputConnection?n-this.tabWidth_:n,o.moveBy(r,i),r=this.createRect_(o,this.RTL?r-l.width:r,i,l,s),this.addBlockListeners_(a,o,r),i+=l.height+e[s]}else"button"==o.type&&(this.initFlyoutButton_(o.button,n,i),i+=o.button.height+e[s])},t.VerticalFlyout.prototype.isDragTowardWorkspace=function(t){t=Math.atan2(t.y,t.x)/Math.PI*180;var e=this.dragAngleRange_;return t-e||t<-180+e||t>180-e},t.VerticalFlyout.prototype.getClientRect=function(){if(!this.svgGroup_)return null;var e=this.svgGroup_.getBoundingClientRect(),o=e.left;return this.toolboxPosition_==t.TOOLBOX_AT_LEFT?new t.utils.Rect(-1e9,1e9,-1e9,o+e.width):new t.utils.Rect(-1e9,1e9,o,1e9)},t.VerticalFlyout.prototype.reflowInternal_=function(){this.workspace_.scale=this.targetWorkspace.scale;for(var e,o=0,i=this.workspace_.getTopBlocks(!1),n=0;e=i[n];n++){var s=e.getHeightWidth().width;e.outputConnection&&(s-=this.tabWidth_),o=Math.max(o,s)}for(n=0;e=this.buttons_[n];n++)o=Math.max(o,e.width);if(o+=1.5*this.MARGIN+this.tabWidth_,o*=this.workspace_.scale,o+=t.Scrollbar.scrollbarThickness,this.width_!=o){for(n=0;e=i[n];n++){if(this.RTL){s=e.getRelativeToSurfaceXY().x;var r=o/this.workspace_.scale-this.MARGIN;e.outputConnection||(r-=this.tabWidth_),e.moveBy(r-s,0)}e.flyoutRect_&&this.moveRectToBlock_(e.flyoutRect_,e)}if(this.RTL)for(n=0;e=this.buttons_[n];n++)i=e.getPosition().y,e.moveTo(o/this.workspace_.scale-e.width-this.MARGIN-this.tabWidth_,i);this.targetWorkspace.toolboxPosition!=this.toolboxPosition_||this.toolboxPosition_!=t.TOOLBOX_AT_LEFT||this.targetWorkspace.getToolbox()||this.targetWorkspace.translate(this.targetWorkspace.scrollX+o,this.targetWorkspace.scrollY),this.width_=o,this.position()}},t.registry.register(t.registry.Type.FLYOUTS_VERTICAL_TOOLBOX,t.registry.DEFAULT,t.VerticalFlyout),t.FlyoutButton=function(e,o,i,n){this.workspace_=e,this.targetWorkspace_=o,this.text_=i.text,this.position_=new t.utils.Coordinate(0,0),this.isLabel_=n,this.callbackKey_=i.callbackKey||i.callbackkey,this.cssClass_=i["web-class"]||null,this.onMouseUpWrapper_=null,this.info=i},t.FlyoutButton.MARGIN_X=5,t.FlyoutButton.MARGIN_Y=2,t.FlyoutButton.prototype.width=0,t.FlyoutButton.prototype.height=0,t.FlyoutButton.prototype.createDom=function(){var e=this.isLabel_?"blocklyFlyoutLabel":"blocklyFlyoutButton";if(this.cssClass_&&(e+=" "+this.cssClass_),this.svgGroup_=t.utils.dom.createSvgElement(t.utils.Svg.G,{class:e},this.workspace_.getCanvas()),!this.isLabel_)var o=t.utils.dom.createSvgElement(t.utils.Svg.RECT,{class:"blocklyFlyoutButtonShadow",rx:4,ry:4,x:1,y:1},this.svgGroup_);e=t.utils.dom.createSvgElement(t.utils.Svg.RECT,{class:this.isLabel_?"blocklyFlyoutLabelBackground":"blocklyFlyoutButtonBackground",rx:4,ry:4},this.svgGroup_);var i=t.utils.dom.createSvgElement(t.utils.Svg.TEXT,{class:this.isLabel_?"blocklyFlyoutLabelText":"blocklyText",x:0,y:0,"text-anchor":"middle"},this.svgGroup_),n=t.utils.replaceMessageReferences(this.text_);this.workspace_.RTL&&(n+="‏"),i.textContent=n,this.isLabel_&&(this.svgText_=i,this.workspace_.getThemeManager().subscribe(this.svgText_,"flyoutForegroundColour","fill"));var s=t.utils.style.getComputedStyle(i,"fontSize"),r=t.utils.style.getComputedStyle(i,"fontWeight"),a=t.utils.style.getComputedStyle(i,"fontFamily");return this.width=t.utils.dom.getFastTextWidthWithSizeString(i,s,r,a),n=t.utils.dom.measureFontMetrics(n,s,r,a),this.height=n.height,this.isLabel_||(this.width+=2*t.FlyoutButton.MARGIN_X,this.height+=2*t.FlyoutButton.MARGIN_Y,o.setAttribute("width",this.width),o.setAttribute("height",this.height)),e.setAttribute("width",this.width),e.setAttribute("height",this.height),i.setAttribute("x",this.width/2),i.setAttribute("y",this.height/2-n.height/2+n.baseline),this.updateTransform_(),this.onMouseUpWrapper_=t.bindEventWithChecks_(this.svgGroup_,"mouseup",this,this.onMouseUp_),this.svgGroup_},t.FlyoutButton.prototype.show=function(){this.updateTransform_(),this.svgGroup_.setAttribute("display","block")},t.FlyoutButton.prototype.updateTransform_=function(){this.svgGroup_.setAttribute("transform","translate("+this.position_.x+","+this.position_.y+")")},t.FlyoutButton.prototype.moveTo=function(t,e){this.position_.x=t,this.position_.y=e,this.updateTransform_()},t.FlyoutButton.prototype.isLabel=function(){return this.isLabel_},t.FlyoutButton.prototype.getPosition=function(){return this.position_},t.FlyoutButton.prototype.getButtonText=function(){return this.text_},t.FlyoutButton.prototype.getTargetWorkspace=function(){return this.targetWorkspace_},t.FlyoutButton.prototype.dispose=function(){this.onMouseUpWrapper_&&t.unbindEvent_(this.onMouseUpWrapper_),this.svgGroup_&&t.utils.dom.removeNode(this.svgGroup_),this.svgText_&&this.workspace_.getThemeManager().unsubscribe(this.svgText_)},t.FlyoutButton.prototype.onMouseUp_=function(t){(t=this.targetWorkspace_.getGesture(t))&&t.cancel(),this.isLabel_&&this.callbackKey_?console.warn("Labels should not have callbacks. Label text: "+this.text_):this.isLabel_||this.callbackKey_&&this.targetWorkspace_.getButtonCallback(this.callbackKey_)?this.isLabel_||this.targetWorkspace_.getButtonCallback(this.callbackKey_)(this):console.warn("Buttons should have callbacks. Button text: "+this.text_)},t.Css.register(".blocklyFlyoutButton {,fill: #888;,cursor: default;,},.blocklyFlyoutButtonShadow {,fill: #666;,},.blocklyFlyoutButton:hover {,fill: #aaa;,},.blocklyFlyoutLabel {,cursor: default;,},.blocklyFlyoutLabelBackground {,opacity: 0;,}".split(",")),t.Generator=function(t){this.name_=t,this.FUNCTION_NAME_PLACEHOLDER_REGEXP_=new RegExp(this.FUNCTION_NAME_PLACEHOLDER_,"g")},t.Generator.NAME_TYPE="generated_function",t.Generator.prototype.INFINITE_LOOP_TRAP=null,t.Generator.prototype.STATEMENT_PREFIX=null,t.Generator.prototype.STATEMENT_SUFFIX=null,t.Generator.prototype.INDENT=" ",t.Generator.prototype.COMMENT_WRAP=60,t.Generator.prototype.ORDER_OVERRIDES=[],t.Generator.prototype.workspaceToCode=function(e){e||(console.warn("No workspace specified in workspaceToCode call. Guessing."),e=t.getMainWorkspace());var o=[];this.init(e),e=e.getTopBlocks(!0);for(var i,n=0;i=e[n];n++){var s=this.blockToCode(i);Array.isArray(s)&&(s=s[0]),s&&(i.outputConnection&&(s=this.scrubNakedValue(s),this.STATEMENT_PREFIX&&!i.suppressPrefixSuffix&&(s=this.injectId(this.STATEMENT_PREFIX,i)+s),this.STATEMENT_SUFFIX&&!i.suppressPrefixSuffix&&(s+=this.injectId(this.STATEMENT_SUFFIX,i))),o.push(s))}return o=o.join("\n"),(o=(o=(o=this.finish(o)).replace(/^\s+\n/,"")).replace(/\n\s+$/,"\n")).replace(/[ \t]+\n/g,"\n")},t.Generator.prototype.prefixLines=function(t,e){return e+t.replace(/(?!\n$)\n/g,"\n"+e)},t.Generator.prototype.allNestedComments=function(t){var e=[];t=t.getDescendants(!0);for(var o=0;o>>/sprites.png);","height: 16px;","vertical-align: middle;","visibility: hidden;","width: 16px;","}",".blocklyTreeIconClosed {","background-position: -32px -1px;","}",'.blocklyToolboxDiv[dir="RTL"] .blocklyTreeIconClosed {',"background-position: 0 -1px;","}",".blocklyTreeSelected>.blocklyTreeIconClosed {","background-position: -32px -17px;","}",'.blocklyToolboxDiv[dir="RTL"] .blocklyTreeSelected>.blocklyTreeIconClosed {',"background-position: 0 -17px;","}",".blocklyTreeIconOpen {","background-position: -16px -1px;","}",".blocklyTreeSelected>.blocklyTreeIconOpen {","background-position: -16px -17px;","}",".blocklyTreeLabel {","cursor: default;","font: 16px sans-serif;","padding: 0 3px;","vertical-align: middle;","}",".blocklyToolboxDelete .blocklyTreeLabel {",'cursor: url("<<>>/handdelete.cur"), auto;',"}",".blocklyTreeSelected .blocklyTreeLabel {","color: #fff;","}"]),t.registry.register(t.registry.Type.TOOLBOX_ITEM,t.ToolboxCategory.registrationName,t.ToolboxCategory),t.ToolboxSeparator=function(e,o){t.ToolboxSeparator.superClass_.constructor.call(this,e,o),this.cssConfig_={container:"blocklyTreeSeparator"},t.utils.object.mixin(this.cssConfig_,e.cssconfig||e.cssConfig)},t.utils.object.inherits(t.ToolboxSeparator,t.ToolboxItem),t.ToolboxSeparator.registrationName="sep",t.ToolboxSeparator.prototype.init=function(){this.createDom_()},t.ToolboxSeparator.prototype.createDom_=function(){var e=document.createElement("div");return t.utils.dom.addClass(e,this.cssConfig_.container),this.htmlDiv_=e},t.ToolboxSeparator.prototype.getDiv=function(){return this.htmlDiv_},t.ToolboxSeparator.prototype.dispose=function(){t.utils.dom.removeNode(this.htmlDiv_)},t.Css.register('.blocklyTreeSeparator {,border-bottom: solid #e5e5e5 1px;,height: 0;,margin: 5px 0;,},.blocklyToolboxDiv[layout="h"] .blocklyTreeSeparator {,border-right: solid #e5e5e5 1px;,border-bottom: none;,height: auto;,margin: 0 5px 0 5px;,padding: 5px 0;,width: 0;,}'.split(",")),t.registry.register(t.registry.Type.TOOLBOX_ITEM,t.ToolboxSeparator.registrationName,t.ToolboxSeparator),t.CollapsibleToolboxCategory=function(e,o,i){this.subcategoriesDiv_=null,this.expanded_=!1,this.toolboxItems_=[],t.CollapsibleToolboxCategory.superClass_.constructor.call(this,e,o,i)},t.utils.object.inherits(t.CollapsibleToolboxCategory,t.ToolboxCategory),t.CollapsibleToolboxCategory.registrationName="collapsibleCategory",t.CollapsibleToolboxCategory.prototype.makeDefaultCssConfig_=function(){var e=t.CollapsibleToolboxCategory.superClass_.makeDefaultCssConfig_.call(this);return e.contents="blocklyToolboxContents",e},t.CollapsibleToolboxCategory.prototype.parseContents_=function(e){var o=e.contents,i=!0;if(e.custom)this.flyoutItems_=e.custom;else if(o){e=0;for(var n;n=o[e];e++)!t.registry.hasItem(t.registry.Type.TOOLBOX_ITEM,n.kind)||n.kind.toLowerCase()==t.ToolboxSeparator.registrationName&&i?(this.flyoutItems_.push(n),i=!0):(this.createToolboxItem_(n),i=!1)}},t.CollapsibleToolboxCategory.prototype.createToolboxItem_=function(e){var o=e.kind;"CATEGORY"==o.toUpperCase()&&t.utils.toolbox.isCategoryCollapsible(e)&&(o=t.CollapsibleToolboxCategory.registrationName),e=new(t.registry.getClass(t.registry.Type.TOOLBOX_ITEM,o))(e,this.parentToolbox_,this),this.toolboxItems_.push(e)},t.CollapsibleToolboxCategory.prototype.init=function(){t.CollapsibleToolboxCategory.superClass_.init.call(this),this.setExpanded("true"==this.toolboxItemDef_.expanded||this.toolboxItemDef_.expanded)},t.CollapsibleToolboxCategory.prototype.createDom_=function(){t.CollapsibleToolboxCategory.superClass_.createDom_.call(this);var e=this.getChildToolboxItems();return this.subcategoriesDiv_=this.createSubCategoriesDom_(e),t.utils.aria.setRole(this.subcategoriesDiv_,t.utils.aria.Role.GROUP),this.htmlDiv_.appendChild(this.subcategoriesDiv_),this.htmlDiv_},t.CollapsibleToolboxCategory.prototype.createIconDom_=function(){var e=document.createElement("span");return this.parentToolbox_.isHorizontal()||(t.utils.dom.addClass(e,this.cssConfig_.icon),e.style.visibility="visible"),e.style.display="inline-block",e},t.CollapsibleToolboxCategory.prototype.createSubCategoriesDom_=function(e){var o=document.createElement("div");t.utils.dom.addClass(o,this.cssConfig_.contents);for(var i=0;i>>/handdelete.cur"), auto;',"}",".blocklyToolboxGrab {",'cursor: url("<<>>/handclosed.cur"), auto;',"cursor: grabbing;","cursor: -webkit-grabbing;","}",".blocklyToolboxDiv {","background-color: #ddd;","overflow-x: visible;","overflow-y: auto;","padding: 4px 0 4px 0;","position: absolute;","z-index: 70;","-webkit-tap-highlight-color: transparent;","}",".blocklyToolboxContents {","display: flex;","flex-wrap: wrap;","flex-direction: column;","}",".blocklyToolboxContents:focus {","outline: none;","}"]),t.registry.register(t.registry.Type.TOOLBOX,t.registry.DEFAULT,t.Toolbox),t.Trashcan=function(e){if(this.workspace_=e,this.contents_=[],this.flyout=null,!(0>=this.workspace_.options.maxTrashcanContents)){if(e=new t.Options({scrollbars:!0,parentWorkspace:this.workspace_,rtl:this.workspace_.RTL,oneBasedIndex:this.workspace_.options.oneBasedIndex,renderer:this.workspace_.options.renderer,rendererOverrides:this.workspace_.options.rendererOverrides}),this.workspace_.horizontalLayout){if(e.toolboxPosition=this.workspace_.toolboxPosition==t.utils.toolbox.Position.TOP?t.utils.toolbox.Position.BOTTOM:t.utils.toolbox.Position.TOP,!t.HorizontalFlyout)throw Error("Missing require for Blockly.HorizontalFlyout");this.flyout=new t.HorizontalFlyout(e)}else{if(e.toolboxPosition=this.workspace_.toolboxPosition==t.utils.toolbox.Position.RIGHT?t.utils.toolbox.Position.LEFT:t.utils.toolbox.Position.RIGHT,!t.VerticalFlyout)throw Error("Missing require for Blockly.VerticalFlyout");this.flyout=new t.VerticalFlyout(e)}this.workspace_.addChangeListener(this.onDelete_.bind(this))}},t.Trashcan.prototype.WIDTH_=47,t.Trashcan.prototype.BODY_HEIGHT_=44,t.Trashcan.prototype.LID_HEIGHT_=16,t.Trashcan.prototype.MARGIN_BOTTOM_=20,t.Trashcan.prototype.MARGIN_SIDE_=20,t.Trashcan.prototype.MARGIN_HOTSPOT_=10,t.Trashcan.prototype.SPRITE_LEFT_=0,t.Trashcan.prototype.SPRITE_TOP_=32,t.Trashcan.prototype.HAS_BLOCKS_LID_ANGLE_=.1,t.Trashcan.ANIMATION_LENGTH_=80,t.Trashcan.ANIMATION_FRAMES_=4,t.Trashcan.OPACITY_MIN_=.4,t.Trashcan.OPACITY_MAX_=.8,t.Trashcan.MAX_LID_ANGLE_=45,t.Trashcan.prototype.isLidOpen=!1,t.Trashcan.prototype.minOpenness_=0,t.Trashcan.prototype.svgGroup_=null,t.Trashcan.prototype.svgLid_=null,t.Trashcan.prototype.lidTask_=0,t.Trashcan.prototype.lidOpen_=0,t.Trashcan.prototype.left_=0,t.Trashcan.prototype.top_=0,t.Trashcan.prototype.createDom=function(){this.svgGroup_=t.utils.dom.createSvgElement(t.utils.Svg.G,{class:"blocklyTrash"},null);var e=String(Math.random()).substring(2),o=t.utils.dom.createSvgElement(t.utils.Svg.CLIPPATH,{id:"blocklyTrashBodyClipPath"+e},this.svgGroup_);t.utils.dom.createSvgElement(t.utils.Svg.RECT,{width:this.WIDTH_,height:this.BODY_HEIGHT_,y:this.LID_HEIGHT_},o);var i=t.utils.dom.createSvgElement(t.utils.Svg.IMAGE,{width:t.SPRITE.width,x:-this.SPRITE_LEFT_,height:t.SPRITE.height,y:-this.SPRITE_TOP_,"clip-path":"url(#blocklyTrashBodyClipPath"+e+")"},this.svgGroup_);return i.setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",this.workspace_.options.pathToMedia+t.SPRITE.url),o=t.utils.dom.createSvgElement(t.utils.Svg.CLIPPATH,{id:"blocklyTrashLidClipPath"+e},this.svgGroup_),t.utils.dom.createSvgElement(t.utils.Svg.RECT,{width:this.WIDTH_,height:this.LID_HEIGHT_},o),this.svgLid_=t.utils.dom.createSvgElement(t.utils.Svg.IMAGE,{width:t.SPRITE.width,x:-this.SPRITE_LEFT_,height:t.SPRITE.height,y:-this.SPRITE_TOP_,"clip-path":"url(#blocklyTrashLidClipPath"+e+")"},this.svgGroup_),this.svgLid_.setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",this.workspace_.options.pathToMedia+t.SPRITE.url),t.bindEventWithChecks_(this.svgGroup_,"mouseup",this,this.click),t.bindEvent_(i,"mouseover",this,this.mouseOver_),t.bindEvent_(i,"mouseout",this,this.mouseOut_),this.animateLid_(),this.svgGroup_},t.Trashcan.prototype.init=function(e){return 0this.minOpenness_&&1>this.lidOpen_&&(this.lidTask_=setTimeout(this.animateLid_.bind(this),t.Trashcan.ANIMATION_LENGTH_/e))},t.Trashcan.prototype.setLidAngle_=function(e){var o=this.workspace_.toolboxPosition==t.TOOLBOX_AT_RIGHT||this.workspace_.horizontalLayout&&this.workspace_.RTL;this.svgLid_.setAttribute("transform","rotate("+(o?-e:e)+","+(o?4:this.WIDTH_-4)+","+(this.LID_HEIGHT_-2)+")")},t.Trashcan.prototype.setMinOpenness_=function(e){this.minOpenness_=e,this.isLidOpen||this.setLidAngle_(e*t.Trashcan.MAX_LID_ANGLE_)},t.Trashcan.prototype.closeLid=function(){this.setLidOpen(!1)},t.Trashcan.prototype.click=function(){this.hasContents_()&&this.openFlyout()},t.Trashcan.prototype.fireUiEvent_=function(e){(e=new t.Events.Ui(null,"trashcanOpen",null,e)).workspaceId=this.workspace_.id,t.Events.fire(e)},t.Trashcan.prototype.mouseOver_=function(){this.hasContents_()&&this.setLidOpen(!0)},t.Trashcan.prototype.mouseOut_=function(){this.setLidOpen(!1)},t.Trashcan.prototype.onDelete_=function(e){if(!(0>=this.workspace_.options.maxTrashcanContents)&&e.type==t.Events.BLOCK_DELETE&&e.oldXml.tagName&&"shadow"!=e.oldXml.tagName.toLowerCase()&&(e=this.cleanBlockXML_(e.oldXml),-1==this.contents_.indexOf(e))){for(this.contents_.unshift(e);this.contents_.length>this.workspace_.options.maxTrashcanContents;)this.contents_.pop();this.setMinOpenness_(this.HAS_BLOCKS_LID_ANGLE_)}},t.Trashcan.prototype.cleanBlockXML_=function(e){for(var o=e=e.cloneNode(!0);o;){o.removeAttribute&&(o.removeAttribute("x"),o.removeAttribute("y"),o.removeAttribute("id"),o.removeAttribute("disabled"),"comment"==o.nodeName&&(o.removeAttribute("h"),o.removeAttribute("w"),o.removeAttribute("pinned")));var i=o.firstChild||o.nextSibling;if(!i)for(i=o.parentNode;i;){if(i.nextSibling){i=i.nextSibling;break}i=i.parentNode}o=i}return t.Xml.domToText(e)},t.VariablesDynamic={},t.VariablesDynamic.onCreateVariableButtonClick_String=function(e){t.Variables.createVariableButtonHandler(e.getTargetWorkspace(),void 0,"String")},t.VariablesDynamic.onCreateVariableButtonClick_Number=function(e){t.Variables.createVariableButtonHandler(e.getTargetWorkspace(),void 0,"Number")},t.VariablesDynamic.onCreateVariableButtonClick_Colour=function(e){t.Variables.createVariableButtonHandler(e.getTargetWorkspace(),void 0,"Colour")},t.VariablesDynamic.flyoutCategory=function(e){var o=[],i=document.createElement("button");return i.setAttribute("text",t.Msg.NEW_STRING_VARIABLE),i.setAttribute("callbackKey","CREATE_VARIABLE_STRING"),o.push(i),(i=document.createElement("button")).setAttribute("text",t.Msg.NEW_NUMBER_VARIABLE),i.setAttribute("callbackKey","CREATE_VARIABLE_NUMBER"),o.push(i),(i=document.createElement("button")).setAttribute("text",t.Msg.NEW_COLOUR_VARIABLE),i.setAttribute("callbackKey","CREATE_VARIABLE_COLOUR"),o.push(i),e.registerButtonCallback("CREATE_VARIABLE_STRING",t.VariablesDynamic.onCreateVariableButtonClick_String),e.registerButtonCallback("CREATE_VARIABLE_NUMBER",t.VariablesDynamic.onCreateVariableButtonClick_Number),e.registerButtonCallback("CREATE_VARIABLE_COLOUR",t.VariablesDynamic.onCreateVariableButtonClick_Colour),e=t.VariablesDynamic.flyoutCategoryBlocks(e),o.concat(e)},t.VariablesDynamic.flyoutCategoryBlocks=function(e){var o=[];if(0<(e=e.getAllVariables()).length){if(t.Blocks.variables_set_dynamic){var i=e[e.length-1],n=t.utils.xml.createElement("block");n.setAttribute("type","variables_set_dynamic"),n.setAttribute("gap",24),n.appendChild(t.Variables.generateVariableFieldDom(i)),o.push(n)}if(t.Blocks.variables_get_dynamic){e.sort(t.VariableModel.compareByName),i=0;for(var s;s=e[i];i++)(n=t.utils.xml.createElement("block")).setAttribute("type","variables_get_dynamic"),n.setAttribute("gap",8),n.appendChild(t.Variables.generateVariableFieldDom(s)),o.push(n)}}return o},t.ZoomControls=function(t){this.workspace_=t,this.zoomResetGroup_=this.zoomOutGroup_=this.zoomInGroup_=this.verticalSpacing_=this.onZoomOutWrapper_=this.onZoomInWrapper_=this.onZoomResetWrapper_=null},t.ZoomControls.prototype.WIDTH_=32,t.ZoomControls.prototype.HEIGHT_=110,t.ZoomControls.prototype.MARGIN_BOTTOM_=20,t.ZoomControls.prototype.MARGIN_SIDE_=20,t.ZoomControls.prototype.svgGroup_=null,t.ZoomControls.prototype.left_=0,t.ZoomControls.prototype.top_=0,t.ZoomControls.prototype.createDom=function(){this.svgGroup_=t.utils.dom.createSvgElement(t.utils.Svg.G,{},null);var e=String(Math.random()).substring(2);return this.createZoomOutSvg_(e),this.createZoomInSvg_(e),this.workspace_.isMovable()&&this.createZoomResetSvg_(e),this.svgGroup_},t.ZoomControls.prototype.init=function(t){return this.verticalSpacing_=this.MARGIN_BOTTOM_+t,this.verticalSpacing_+this.HEIGHT_},t.ZoomControls.prototype.dispose=function(){this.svgGroup_&&t.utils.dom.removeNode(this.svgGroup_),this.onZoomResetWrapper_&&t.unbindEvent_(this.onZoomResetWrapper_),this.onZoomInWrapper_&&t.unbindEvent_(this.onZoomInWrapper_),this.onZoomOutWrapper_&&t.unbindEvent_(this.onZoomOutWrapper_)},t.ZoomControls.prototype.position=function(){if(this.verticalSpacing_){var e=this.workspace_.getMetrics();e&&(this.left_=e.toolboxPosition==t.TOOLBOX_AT_LEFT||this.workspace_.horizontalLayout&&!this.workspace_.RTL?e.viewWidth+e.absoluteLeft-this.WIDTH_-this.MARGIN_SIDE_-t.Scrollbar.scrollbarThickness:this.MARGIN_SIDE_+t.Scrollbar.scrollbarThickness,e.toolboxPosition==t.TOOLBOX_AT_BOTTOM?(this.top_=this.verticalSpacing_,this.zoomInGroup_.setAttribute("transform","translate(0, 34)"),this.zoomResetGroup_&&this.zoomResetGroup_.setAttribute("transform","translate(0, 77)")):(this.top_=e.viewHeight+e.absoluteTop-this.HEIGHT_-this.verticalSpacing_,this.zoomInGroup_.setAttribute("transform","translate(0, 43)"),this.zoomOutGroup_.setAttribute("transform","translate(0, 77)")),this.svgGroup_.setAttribute("transform","translate("+this.left_+","+this.top_+")"))}},t.ZoomControls.prototype.createZoomOutSvg_=function(e){this.zoomOutGroup_=t.utils.dom.createSvgElement(t.utils.Svg.G,{class:"blocklyZoom"},this.svgGroup_);var o=t.utils.dom.createSvgElement(t.utils.Svg.CLIPPATH,{id:"blocklyZoomoutClipPath"+e},this.zoomOutGroup_);t.utils.dom.createSvgElement(t.utils.Svg.RECT,{width:32,height:32},o),t.utils.dom.createSvgElement(t.utils.Svg.IMAGE,{width:t.SPRITE.width,height:t.SPRITE.height,x:-64,y:-92,"clip-path":"url(#blocklyZoomoutClipPath"+e+")"},this.zoomOutGroup_).setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",this.workspace_.options.pathToMedia+t.SPRITE.url),this.onZoomOutWrapper_=t.bindEventWithChecks_(this.zoomOutGroup_,"mousedown",null,this.zoom_.bind(this,-1))},t.ZoomControls.prototype.createZoomInSvg_=function(e){this.zoomInGroup_=t.utils.dom.createSvgElement(t.utils.Svg.G,{class:"blocklyZoom"},this.svgGroup_);var o=t.utils.dom.createSvgElement(t.utils.Svg.CLIPPATH,{id:"blocklyZoominClipPath"+e},this.zoomInGroup_);t.utils.dom.createSvgElement(t.utils.Svg.RECT,{width:32,height:32},o),t.utils.dom.createSvgElement(t.utils.Svg.IMAGE,{width:t.SPRITE.width,height:t.SPRITE.height,x:-32,y:-92,"clip-path":"url(#blocklyZoominClipPath"+e+")"},this.zoomInGroup_).setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",this.workspace_.options.pathToMedia+t.SPRITE.url),this.onZoomInWrapper_=t.bindEventWithChecks_(this.zoomInGroup_,"mousedown",null,this.zoom_.bind(this,1))},t.ZoomControls.prototype.zoom_=function(e,o){this.workspace_.markFocused();var i=this.workspace_.scale;this.workspace_.zoomCenter(e),this.fireZoomEvent_(i),t.Touch.clearTouchIdentifier(),o.stopPropagation(),o.preventDefault()},t.ZoomControls.prototype.createZoomResetSvg_=function(e){this.zoomResetGroup_=t.utils.dom.createSvgElement(t.utils.Svg.G,{class:"blocklyZoom"},this.svgGroup_);var o=t.utils.dom.createSvgElement(t.utils.Svg.CLIPPATH,{id:"blocklyZoomresetClipPath"+e},this.zoomResetGroup_);t.utils.dom.createSvgElement(t.utils.Svg.RECT,{width:32,height:32},o),t.utils.dom.createSvgElement(t.utils.Svg.IMAGE,{width:t.SPRITE.width,height:t.SPRITE.height,y:-92,"clip-path":"url(#blocklyZoomresetClipPath"+e+")"},this.zoomResetGroup_).setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",this.workspace_.options.pathToMedia+t.SPRITE.url),this.onZoomResetWrapper_=t.bindEventWithChecks_(this.zoomResetGroup_,"mousedown",null,this.resetZoom_.bind(this))},t.ZoomControls.prototype.resetZoom_=function(e){this.workspace_.markFocused();var o=this.workspace_.scale;this.workspace_.setScale(this.workspace_.options.zoomOptions.startScale),this.workspace_.beginCanvasTransition(),this.workspace_.scrollCenter(),setTimeout(this.workspace_.endCanvasTransition.bind(this.workspace_),500),this.fireZoomEvent_(o),t.Touch.clearTouchIdentifier(),e.stopPropagation(),e.preventDefault()},t.ZoomControls.prototype.fireZoomEvent_=function(e){(e=new t.Events.Ui(null,"zoom",e,this.workspace_.scale)).workspaceId=this.workspace_.id,t.Events.fire(e)},t.Css.register([".blocklyZoom>image, .blocklyZoom>svg>image {","opacity: .4;","}",".blocklyZoom>image:hover, .blocklyZoom>svg>image:hover {","opacity: .6;","}",".blocklyZoom>image:active, .blocklyZoom>svg>image:active {","opacity: .8;","}"]),t.Mutator=function(e){t.Mutator.superClass_.constructor.call(this,null),this.quarkNames_=e},t.utils.object.inherits(t.Mutator,t.Icon),t.Mutator.prototype.workspaceWidth_=0,t.Mutator.prototype.workspaceHeight_=0,t.Mutator.prototype.setBlock=function(t){this.block_=t},t.Mutator.prototype.getWorkspace=function(){return this.workspace_},t.Mutator.prototype.drawIcon_=function(e){t.utils.dom.createSvgElement(t.utils.Svg.RECT,{class:"blocklyIconShape",rx:"4",ry:"4",height:"16",width:"16"},e),t.utils.dom.createSvgElement(t.utils.Svg.PATH,{class:"blocklyIconSymbol",d:"m4.203,7.296 0,1.368 -0.92,0.677 -0.11,0.41 0.9,1.559 0.41,0.11 1.043,-0.457 1.187,0.683 0.127,1.134 0.3,0.3 1.8,0 0.3,-0.299 0.127,-1.138 1.185,-0.682 1.046,0.458 0.409,-0.11 0.9,-1.559 -0.11,-0.41 -0.92,-0.677 0,-1.366 0.92,-0.677 0.11,-0.41 -0.9,-1.559 -0.409,-0.109 -1.046,0.458 -1.185,-0.682 -0.127,-1.138 -0.3,-0.299 -1.8,0 -0.3,0.3 -0.126,1.135 -1.187,0.682 -1.043,-0.457 -0.41,0.11 -0.899,1.559 0.108,0.409z"},e),t.utils.dom.createSvgElement(t.utils.Svg.CIRCLE,{class:"blocklyIconShape",r:"2.7",cx:"8",cy:"8"},e)},t.Mutator.prototype.iconClick_=function(e){this.block_.isEditable()&&t.Icon.prototype.iconClick_.call(this,e)},t.Mutator.prototype.createEditor_=function(){if(this.svgDialog_=t.utils.dom.createSvgElement(t.utils.Svg.SVG,{x:t.Bubble.BORDER_WIDTH,y:t.Bubble.BORDER_WIDTH},null),this.quarkNames_.length)for(var e,o=t.utils.xml.createElement("xml"),i=0;e=this.quarkNames_[i];i++){var n=t.utils.xml.createElement("block");n.setAttribute("type",e),o.appendChild(n)}else o=null;return(i=new t.Options({disable:!1,parentWorkspace:this.block_.workspace,media:this.block_.workspace.options.pathToMedia,rtl:this.block_.RTL,horizontalLayout:!1,renderer:this.block_.workspace.options.renderer,rendererOverrides:this.block_.workspace.options.rendererOverrides})).toolboxPosition=this.block_.RTL?t.utils.toolbox.Position.RIGHT:t.utils.toolbox.Position.LEFT,(e=!!o)&&(i.languageTree=t.utils.toolbox.convertToolboxDefToJson(o),i.getMetrics=this.getFlyoutMetrics_.bind(this)),this.workspace_=new t.WorkspaceSvg(i),this.workspace_.isMutator=!0,this.workspace_.addChangeListener(t.Events.disableOrphans),o=e?this.workspace_.addFlyout(t.utils.Svg.G):null,i=this.workspace_.createDom("blocklyMutatorBackground"),o&&i.insertBefore(o,this.workspace_.svgBlockCanvas_),this.svgDialog_.appendChild(i),this.svgDialog_},t.Mutator.prototype.updateEditable=function(){t.Mutator.superClass_.updateEditable.call(this),this.block_.isInFlyout||(this.block_.isEditable()?this.iconGroup_&&t.utils.dom.removeClass(this.iconGroup_,"blocklyIconGroupReadonly"):(this.setVisible(!1),this.iconGroup_&&t.utils.dom.addClass(this.iconGroup_,"blocklyIconGroupReadonly")))},t.Mutator.prototype.resizeBubble_=function(){var e=2*t.Bubble.BORDER_WIDTH,o=this.workspace_.getCanvas().getBBox(),i=o.width+o.x,n=o.height+3*e,s=this.workspace_.getFlyout();if(s){var r=s.getMetrics_();n=Math.max(n,r.contentHeight+20),i+=s.getWidth()}this.block_.RTL&&(i=-o.x),i+=3*e,(Math.abs(this.workspaceWidth_-i)>e||Math.abs(this.workspaceHeight_-n)>e)&&(this.workspaceWidth_=i,this.workspaceHeight_=n,this.bubble_.setBubbleSize(i+e,n+e),this.svgDialog_.setAttribute("width",this.workspaceWidth_),this.svgDialog_.setAttribute("height",this.workspaceHeight_)),this.block_.RTL&&(e="translate("+this.workspaceWidth_+",0)",this.workspace_.getCanvas().setAttribute("transform",e)),this.workspace_.resize()},t.Mutator.prototype.onBubbleMove_=function(){this.workspace_&&this.workspace_.recordDeleteAreas()},t.Mutator.prototype.setVisible=function(e){if(e!=this.isVisible())if(t.Events.fire(new t.Events.Ui(this.block_,"mutatorOpen",!e,e)),e){this.bubble_=new t.Bubble(this.block_.workspace,this.createEditor_(),this.block_.pathObject.svgPath,this.iconXY_,null,null),this.bubble_.setSvgId(this.block_.id),this.bubble_.registerMoveEvent(this.onBubbleMove_.bind(this));var o=this.workspace_.options.languageTree;e=this.workspace_.getFlyout(),o&&(e.init(this.workspace_),e.show(o)),this.rootBlock_=this.block_.decompose(this.workspace_),o=this.rootBlock_.getDescendants(!1);for(var i,n=0;i=o[n];n++)i.render();if(this.rootBlock_.setMovable(!1),this.rootBlock_.setDeletable(!1),e?(o=2*e.CORNER_RADIUS,e=this.rootBlock_.RTL?e.getWidth()+o:o):e=o=16,this.block_.RTL&&(e=-e),this.rootBlock_.moveBy(e,o),this.block_.saveConnections){var s=this,r=this.block_;r.saveConnections(this.rootBlock_),this.sourceListener_=function(){r.saveConnections(s.rootBlock_)},this.block_.workspace.addChangeListener(this.sourceListener_)}this.resizeBubble_(),this.workspace_.addChangeListener(this.workspaceChanged_.bind(this)),this.applyColour()}else this.svgDialog_=null,this.workspace_.dispose(),this.rootBlock_=this.workspace_=null,this.bubble_.dispose(),this.bubble_=null,this.workspaceHeight_=this.workspaceWidth_=0,this.sourceListener_&&(this.block_.workspace.removeChangeListener(this.sourceListener_),this.sourceListener_=null)},t.Mutator.prototype.workspaceChanged_=function(e){if(e.type!=t.Events.UI&&(e.type!=t.Events.CHANGE||"disabled"!=e.element)){if(!this.workspace_.isDragging())for(var o=this.workspace_.getTopBlocks(!1),i=0;e=o[i];i++){var n=e.getRelativeToSurfaceXY();if(20>n.y&&e.moveBy(0,20-n.y),e.RTL){var s=-20,r=this.workspace_.getFlyout();r&&(s-=r.getWidth()),n.x>s&&e.moveBy(s-n.x,0)}else 20>n.x&&e.moveBy(20-n.x,0)}this.rootBlock_.workspace==this.workspace_&&(t.Events.setGroup(!0),o=(o=(e=this.block_).mutationToDom())&&t.Xml.domToText(o),i=e.rendered,e.rendered=!1,e.compose(this.rootBlock_),e.rendered=i,e.initSvg(),t.getMainWorkspace().keyboardAccessibilityMode&&t.navigation.moveCursorOnBlockMutation(e),e.rendered&&e.render(),o!=(i=(i=e.mutationToDom())&&t.Xml.domToText(i))&&t.Events.fire(new t.Events.BlockChange(e,"mutation",null,o,i)),this.workspace_.isDragging()||this.resizeBubble_(),t.Events.setGroup(!1))}},t.Mutator.prototype.getFlyoutMetrics_=function(){var t=this.workspace_.getFlyout();return t=t?t.getWidth():0,{contentHeight:0,contentWidth:0,contentTop:0,contentLeft:0,viewHeight:this.workspaceHeight_,viewWidth:this.workspaceWidth_-t,viewTop:0,viewLeft:0,absoluteTop:0,absoluteLeft:this.workspace_.RTL?0:t}},t.Mutator.prototype.dispose=function(){this.block_.mutator=null,t.Icon.prototype.dispose.call(this)},t.Mutator.prototype.updateBlockStyle=function(){var t=this.workspace_;if(t&&t.getAllBlocks(!1)){for(var e=t.getAllBlocks(!1),o=0;o=e&&this.sourceBlock_.outputConnection&&!o}else this.fullBlockClickTarget_=!1;this.fullBlockClickTarget_?this.clickTarget_=this.sourceBlock_.getSvgRoot():this.createBorderRect_(),this.createTextElement_()},t.FieldTextInput.prototype.doClassValidation_=function(t){return null==t?null:String(t)},t.FieldTextInput.prototype.doValueInvalid_=function(e){this.isBeingEdited_&&(this.isTextValid_=!1,e=this.value_,this.value_=this.htmlInput_.untypedDefaultValue_,this.sourceBlock_&&t.Events.isEnabled()&&t.Events.fire(new t.Events.BlockChange(this.sourceBlock_,"field",this.name||null,e,this.value_)))},t.FieldTextInput.prototype.doValueUpdate_=function(t){this.isTextValid_=!0,this.value_=t,this.isBeingEdited_||(this.isDirty_=!0)},t.FieldTextInput.prototype.applyColour=function(){this.sourceBlock_&&this.getConstants().FULL_BLOCK_FIELDS&&(this.borderRect_?this.borderRect_.setAttribute("stroke",this.sourceBlock_.style.colourTertiary):this.sourceBlock_.pathObject.svgPath.setAttribute("fill",this.getConstants().FIELD_BORDER_RECT_COLOUR))},t.FieldTextInput.prototype.render_=function(){if(t.FieldTextInput.superClass_.render_.call(this),this.isBeingEdited_){this.resizeEditor_();var e=this.htmlInput_;this.isTextValid_?(t.utils.dom.removeClass(e,"blocklyInvalidInput"),t.utils.aria.setState(e,t.utils.aria.State.INVALID,!1)):(t.utils.dom.addClass(e,"blocklyInvalidInput"),t.utils.aria.setState(e,t.utils.aria.State.INVALID,!0))}},t.FieldTextInput.prototype.setSpellcheck=function(t){t!=this.spellcheck_&&(this.spellcheck_=t,this.htmlInput_&&this.htmlInput_.setAttribute("spellcheck",this.spellcheck_))},t.FieldTextInput.prototype.showEditor_=function(e,o){this.workspace_=this.sourceBlock_.workspace,!(e=o||!1)&&(t.utils.userAgent.MOBILE||t.utils.userAgent.ANDROID||t.utils.userAgent.IPAD)?this.showPromptEditor_():this.showInlineEditor_(e)},t.FieldTextInput.prototype.showPromptEditor_=function(){var e=this;t.prompt(t.Msg.CHANGE_VALUE_TITLE,this.getText(),(function(t){e.setValue(t)}))},t.FieldTextInput.prototype.showInlineEditor_=function(e){t.WidgetDiv.show(this,this.sourceBlock_.RTL,this.widgetDispose_.bind(this)),this.htmlInput_=this.widgetCreate_(),this.isBeingEdited_=!0,e||(this.htmlInput_.focus({preventScroll:!0}),this.htmlInput_.select())},t.FieldTextInput.prototype.widgetCreate_=function(){var e=t.WidgetDiv.DIV;t.utils.dom.addClass(this.getClickTarget_(),"editing");var o=document.createElement("input");o.className="blocklyHtmlInput",o.setAttribute("spellcheck",this.spellcheck_);var i=this.workspace_.getScale(),n=this.getConstants().FIELD_TEXT_FONTSIZE*i+"pt";if(e.style.fontSize=n,o.style.fontSize=n,n=t.FieldTextInput.BORDERRADIUS*i+"px",this.fullBlockClickTarget_){n=((n=this.getScaledBBox()).bottom-n.top)/2+"px";var s=this.sourceBlock_.getParent()?this.sourceBlock_.getParent().style.colourTertiary:this.sourceBlock_.style.colourTertiary;o.style.border=1*i+"px solid "+s,e.style.borderRadius=n,e.style.transition="box-shadow 0.25s ease 0s",this.getConstants().FIELD_TEXTINPUT_BOX_SHADOW&&(e.style.boxShadow="rgba(255, 255, 255, 0.3) 0px 0px 0px "+4*i+"px")}return o.style.borderRadius=n,e.appendChild(o),o.value=o.defaultValue=this.getEditorText_(this.value_),o.untypedDefaultValue_=this.value_,o.oldValue_=null,this.resizeEditor_(),this.bindInputEvents_(o),o},t.FieldTextInput.prototype.widgetDispose_=function(){this.isBeingEdited_=!1,this.isTextValid_=!0,this.forceRerender(),this.onFinishEditing_&&this.onFinishEditing_(this.value_),this.unbindInputEvents_();var e=t.WidgetDiv.DIV.style;e.width="auto",e.height="auto",e.fontSize="",e.transition="",e.boxShadow="",this.htmlInput_=null,t.utils.dom.removeClass(this.getClickTarget_(),"editing")},t.FieldTextInput.prototype.bindInputEvents_=function(e){this.onKeyDownWrapper_=t.bindEventWithChecks_(e,"keydown",this,this.onHtmlInputKeyDown_),this.onKeyInputWrapper_=t.bindEventWithChecks_(e,"input",this,this.onHtmlInputChange_)},t.FieldTextInput.prototype.unbindInputEvents_=function(){this.onKeyDownWrapper_&&(t.unbindEvent_(this.onKeyDownWrapper_),this.onKeyDownWrapper_=null),this.onKeyInputWrapper_&&(t.unbindEvent_(this.onKeyInputWrapper_),this.onKeyInputWrapper_=null)},t.FieldTextInput.prototype.onHtmlInputKeyDown_=function(e){e.keyCode==t.utils.KeyCodes.ENTER?(t.WidgetDiv.hide(),t.DropDownDiv.hideWithoutAnimation()):e.keyCode==t.utils.KeyCodes.ESC?(this.htmlInput_.value=this.htmlInput_.defaultValue,t.WidgetDiv.hide(),t.DropDownDiv.hideWithoutAnimation()):e.keyCode==t.utils.KeyCodes.TAB&&(t.WidgetDiv.hide(),t.DropDownDiv.hideWithoutAnimation(),this.sourceBlock_.tab(this,!e.shiftKey),e.preventDefault())},t.FieldTextInput.prototype.onHtmlInputChange_=function(e){(e=this.htmlInput_.value)!==this.htmlInput_.oldValue_&&(this.htmlInput_.oldValue_=e,t.Events.setGroup(!0),e=this.getValueFromEditorText_(e),this.setValue(e),this.forceRerender(),this.resizeEditor_(),t.Events.setGroup(!1))},t.FieldTextInput.prototype.setEditorValue_=function(t){this.isDirty_=!0,this.isBeingEdited_&&(this.htmlInput_.value=this.getEditorText_(t)),this.setValue(t)},t.FieldTextInput.prototype.resizeEditor_=function(){var e=t.WidgetDiv.DIV,o=this.getScaledBBox();e.style.width=o.right-o.left+"px",e.style.height=o.bottom-o.top+"px",o=new t.utils.Coordinate(this.sourceBlock_.RTL?o.right-e.offsetWidth:o.left,o.top),e.style.left=o.x+"px",e.style.top=o.y+"px"},t.FieldTextInput.numberValidator=function(t){return console.warn("Blockly.FieldTextInput.numberValidator is deprecated. Use Blockly.FieldNumber instead."),null===t?null:(t=(t=(t=String(t)).replace(/O/gi,"0")).replace(/,/g,""),t=Number(t||0),isNaN(t)?null:String(t))},t.FieldTextInput.nonnegativeIntegerValidator=function(e){return(e=t.FieldTextInput.numberValidator(e))&&(e=String(Math.max(0,Math.floor(e)))),e},t.FieldTextInput.prototype.isTabNavigable=function(){return!0},t.FieldTextInput.prototype.getText_=function(){return this.isBeingEdited_&&this.htmlInput_?this.htmlInput_.value:null},t.FieldTextInput.prototype.getEditorText_=function(t){return String(t)},t.FieldTextInput.prototype.getValueFromEditorText_=function(t){return t},t.fieldRegistry.register("field_input",t.FieldTextInput),t.FieldAngle=function(e,o,i){this.clockwise_=t.FieldAngle.CLOCKWISE,this.offset_=t.FieldAngle.OFFSET,this.wrap_=t.FieldAngle.WRAP,this.round_=t.FieldAngle.ROUND,t.FieldAngle.superClass_.constructor.call(this,e,o,i),this.moveSurfaceWrapper_=this.clickSurfaceWrapper_=this.clickWrapper_=this.line_=this.gauge_=null},t.utils.object.inherits(t.FieldAngle,t.FieldTextInput),t.FieldAngle.prototype.DEFAULT_VALUE=0,t.FieldAngle.fromJson=function(e){return new t.FieldAngle(e.angle,void 0,e)},t.FieldAngle.prototype.SERIALIZABLE=!0,t.FieldAngle.ROUND=15,t.FieldAngle.HALF=50,t.FieldAngle.CLOCKWISE=!1,t.FieldAngle.OFFSET=0,t.FieldAngle.WRAP=360,t.FieldAngle.RADIUS=t.FieldAngle.HALF-1,t.FieldAngle.prototype.configure_=function(e){switch(t.FieldAngle.superClass_.configure_.call(this,e),e.mode){case"compass":this.clockwise_=!0,this.offset_=90;break;case"protractor":this.clockwise_=!1,this.offset_=0}var o=e.clockwise;"boolean"==typeof o&&(this.clockwise_=o),null!=(o=e.offset)&&(o=Number(o),isNaN(o)||(this.offset_=o)),null!=(o=e.wrap)&&(o=Number(o),isNaN(o)||(this.wrap_=o)),null!=(e=e.round)&&(e=Number(e),isNaN(e)||(this.round_=e))},t.FieldAngle.prototype.initView=function(){t.FieldAngle.superClass_.initView.call(this),this.symbol_=t.utils.dom.createSvgElement(t.utils.Svg.TSPAN,{},null),this.symbol_.appendChild(document.createTextNode("°")),this.textElement_.appendChild(this.symbol_)},t.FieldAngle.prototype.render_=function(){t.FieldAngle.superClass_.render_.call(this),this.updateGraph_()},t.FieldAngle.prototype.showEditor_=function(e){t.FieldAngle.superClass_.showEditor_.call(this,e,t.utils.userAgent.MOBILE||t.utils.userAgent.ANDROID||t.utils.userAgent.IPAD),e=this.dropdownCreate_(),t.DropDownDiv.getContentDiv().appendChild(e),t.DropDownDiv.setColour(this.sourceBlock_.style.colourPrimary,this.sourceBlock_.style.colourTertiary),t.DropDownDiv.showPositionedByField(this,this.dropdownDispose_.bind(this)),this.updateGraph_()},t.FieldAngle.prototype.dropdownCreate_=function(){var e=t.utils.dom.createSvgElement(t.utils.Svg.SVG,{xmlns:t.utils.dom.SVG_NS,"xmlns:html":t.utils.dom.HTML_NS,"xmlns:xlink":t.utils.dom.XLINK_NS,version:"1.1",height:2*t.FieldAngle.HALF+"px",width:2*t.FieldAngle.HALF+"px",style:"touch-action: none"},null),o=t.utils.dom.createSvgElement(t.utils.Svg.CIRCLE,{cx:t.FieldAngle.HALF,cy:t.FieldAngle.HALF,r:t.FieldAngle.RADIUS,class:"blocklyAngleCircle"},e);this.gauge_=t.utils.dom.createSvgElement(t.utils.Svg.PATH,{class:"blocklyAngleGauge"},e),this.line_=t.utils.dom.createSvgElement(t.utils.Svg.LINE,{x1:t.FieldAngle.HALF,y1:t.FieldAngle.HALF,class:"blocklyAngleLine"},e);for(var i=0;360>i;i+=15)t.utils.dom.createSvgElement(t.utils.Svg.LINE,{x1:t.FieldAngle.HALF+t.FieldAngle.RADIUS,y1:t.FieldAngle.HALF,x2:t.FieldAngle.HALF+t.FieldAngle.RADIUS-(0==i%45?10:5),y2:t.FieldAngle.HALF,class:"blocklyAngleMarks",transform:"rotate("+i+","+t.FieldAngle.HALF+","+t.FieldAngle.HALF+")"},e);return this.clickWrapper_=t.bindEventWithChecks_(e,"click",this,this.hide_),this.clickSurfaceWrapper_=t.bindEventWithChecks_(o,"click",this,this.onMouseMove_,!0,!0),this.moveSurfaceWrapper_=t.bindEventWithChecks_(o,"mousemove",this,this.onMouseMove_,!0,!0),e},t.FieldAngle.prototype.dropdownDispose_=function(){this.clickWrapper_&&(t.unbindEvent_(this.clickWrapper_),this.clickWrapper_=null),this.clickSurfaceWrapper_&&(t.unbindEvent_(this.clickSurfaceWrapper_),this.clickSurfaceWrapper_=null),this.moveSurfaceWrapper_&&(t.unbindEvent_(this.moveSurfaceWrapper_),this.moveSurfaceWrapper_=null),this.line_=this.gauge_=null},t.FieldAngle.prototype.hide_=function(){t.DropDownDiv.hideIfOwner(this),t.WidgetDiv.hide()},t.FieldAngle.prototype.onMouseMove_=function(e){var o=this.gauge_.ownerSVGElement.getBoundingClientRect(),i=e.clientX-o.left-t.FieldAngle.HALF;e=e.clientY-o.top-t.FieldAngle.HALF,o=Math.atan(-e/i),isNaN(o)||(o=t.utils.math.toDegrees(o),0>i?o+=180:0(t%=360)&&(t+=360),t>this.wrap_&&(t-=360),t},t.Css.register(".blocklyAngleCircle {,stroke: #444;,stroke-width: 1;,fill: #ddd;,fill-opacity: .8;,},.blocklyAngleMarks {,stroke: #444;,stroke-width: 1;,},.blocklyAngleGauge {,fill: #f88;,fill-opacity: .8;,pointer-events: none;,},.blocklyAngleLine {,stroke: #f00;,stroke-width: 2;,stroke-linecap: round;,pointer-events: none;,}".split(",")),t.fieldRegistry.register("field_angle",t.FieldAngle),t.FieldCheckbox=function(e,o,i){this.checkChar_=null,t.FieldCheckbox.superClass_.constructor.call(this,e,o,i)},t.utils.object.inherits(t.FieldCheckbox,t.Field),t.FieldCheckbox.prototype.DEFAULT_VALUE=!1,t.FieldCheckbox.fromJson=function(e){return new t.FieldCheckbox(e.checked,void 0,e)},t.FieldCheckbox.CHECK_CHAR="âś“",t.FieldCheckbox.prototype.SERIALIZABLE=!0,t.FieldCheckbox.prototype.CURSOR="default",t.FieldCheckbox.prototype.configure_=function(e){t.FieldCheckbox.superClass_.configure_.call(this,e),e.checkCharacter&&(this.checkChar_=e.checkCharacter)},t.FieldCheckbox.prototype.initView=function(){t.FieldCheckbox.superClass_.initView.call(this),t.utils.dom.addClass(this.textElement_,"blocklyCheckbox"),this.textElement_.style.display=this.value_?"block":"none"},t.FieldCheckbox.prototype.render_=function(){this.textContent_&&(this.textContent_.nodeValue=this.getDisplayText_()),this.updateSize_(this.getConstants().FIELD_CHECKBOX_X_OFFSET)},t.FieldCheckbox.prototype.getDisplayText_=function(){return this.checkChar_||t.FieldCheckbox.CHECK_CHAR},t.FieldCheckbox.prototype.setCheckCharacter=function(t){this.checkChar_=t,this.forceRerender()},t.FieldCheckbox.prototype.showEditor_=function(){this.setValue(!this.value_)},t.FieldCheckbox.prototype.doClassValidation_=function(t){return!0===t||"TRUE"===t?"TRUE":!1===t||"FALSE"===t?"FALSE":null},t.FieldCheckbox.prototype.doValueUpdate_=function(t){this.value_=this.convertValueToBool_(t),this.textElement_&&(this.textElement_.style.display=this.value_?"block":"none")},t.FieldCheckbox.prototype.getValue=function(){return this.value_?"TRUE":"FALSE"},t.FieldCheckbox.prototype.getValueBoolean=function(){return this.value_},t.FieldCheckbox.prototype.getText=function(){return String(this.convertValueToBool_(this.value_))},t.FieldCheckbox.prototype.convertValueToBool_=function(t){return"string"==typeof t?"TRUE"==t:!!t},t.fieldRegistry.register("field_checkbox",t.FieldCheckbox),t.FieldColour=function(e,o,i){t.FieldColour.superClass_.constructor.call(this,e,o,i),this.onKeyDownWrapper_=this.onMouseLeaveWrapper_=this.onMouseEnterWrapper_=this.onMouseMoveWrapper_=this.onClickWrapper_=this.highlightedIndex_=this.picker_=null},t.utils.object.inherits(t.FieldColour,t.Field),t.FieldColour.fromJson=function(e){return new t.FieldColour(e.colour,void 0,e)},t.FieldColour.prototype.SERIALIZABLE=!0,t.FieldColour.prototype.CURSOR="default",t.FieldColour.prototype.isDirty_=!1,t.FieldColour.prototype.colours_=null,t.FieldColour.prototype.titles_=null,t.FieldColour.prototype.columns_=0,t.FieldColour.prototype.configure_=function(e){t.FieldColour.superClass_.configure_.call(this,e),e.colourOptions&&(this.colours_=e.colourOptions,this.titles_=e.colourTitles),e.columns&&(this.columns_=e.columns)},t.FieldColour.prototype.initView=function(){this.size_=new t.utils.Size(this.getConstants().FIELD_COLOUR_DEFAULT_WIDTH,this.getConstants().FIELD_COLOUR_DEFAULT_HEIGHT),this.getConstants().FIELD_COLOUR_FULL_BLOCK?this.clickTarget_=this.sourceBlock_.getSvgRoot():(this.createBorderRect_(),this.borderRect_.style.fillOpacity="1")},t.FieldColour.prototype.applyColour=function(){this.getConstants().FIELD_COLOUR_FULL_BLOCK?(this.sourceBlock_.pathObject.svgPath.setAttribute("fill",this.getValue()),this.sourceBlock_.pathObject.svgPath.setAttribute("stroke","#fff")):this.borderRect_&&(this.borderRect_.style.fill=this.getValue())},t.FieldColour.prototype.doClassValidation_=function(e){return"string"!=typeof e?null:t.utils.colour.parse(e)},t.FieldColour.prototype.doValueUpdate_=function(t){this.value_=t,this.borderRect_?this.borderRect_.style.fill=t:this.sourceBlock_&&this.sourceBlock_.rendered&&(this.sourceBlock_.pathObject.svgPath.setAttribute("fill",t),this.sourceBlock_.pathObject.svgPath.setAttribute("stroke","#fff"))},t.FieldColour.prototype.getText=function(){var t=this.value_;return/^#(.)\1(.)\2(.)\3$/.test(t)&&(t="#"+t[1]+t[3]+t[5]),t},t.FieldColour.COLOURS="#ffffff #cccccc #c0c0c0 #999999 #666666 #333333 #000000 #ffcccc #ff6666 #ff0000 #cc0000 #990000 #660000 #330000 #ffcc99 #ff9966 #ff9900 #ff6600 #cc6600 #993300 #663300 #ffff99 #ffff66 #ffcc66 #ffcc33 #cc9933 #996633 #663333 #ffffcc #ffff33 #ffff00 #ffcc00 #999900 #666600 #333300 #99ff99 #66ff99 #33ff33 #33cc00 #009900 #006600 #003300 #99ffff #33ffff #66cccc #00cccc #339999 #336666 #003333 #ccffff #66ffff #33ccff #3366ff #3333ff #000099 #000066 #ccccff #9999ff #6666cc #6633ff #6600cc #333399 #330099 #ffccff #ff99ff #cc66cc #cc33cc #993399 #663366 #330033".split(" "),t.FieldColour.prototype.DEFAULT_VALUE=t.FieldColour.COLOURS[0],t.FieldColour.TITLES=[],t.FieldColour.COLUMNS=7,t.FieldColour.prototype.setColours=function(t,e){return this.colours_=t,e&&(this.titles_=e),this},t.FieldColour.prototype.setColumns=function(t){return this.columns_=t,this},t.FieldColour.prototype.showEditor_=function(){this.picker_=this.dropdownCreate_(),t.DropDownDiv.getContentDiv().appendChild(this.picker_),t.DropDownDiv.showPositionedByField(this,this.dropdownDispose_.bind(this)),this.picker_.focus({preventScroll:!0})},t.FieldColour.prototype.onClick_=function(e){null!==(e=(e=e.target)&&e.label)&&(this.setValue(e),t.DropDownDiv.hideIfOwner(this))},t.FieldColour.prototype.onKeyDown_=function(e){var o=!1;e.keyCode===t.utils.KeyCodes.UP?(this.moveHighlightBy_(0,-1),o=!0):e.keyCode===t.utils.KeyCodes.DOWN?(this.moveHighlightBy_(0,1),o=!0):e.keyCode===t.utils.KeyCodes.LEFT?(this.moveHighlightBy_(-1,0),o=!0):e.keyCode===t.utils.KeyCodes.RIGHT?(this.moveHighlightBy_(1,0),o=!0):e.keyCode===t.utils.KeyCodes.ENTER&&((o=this.getHighlighted_())&&null!==(o=o&&o.label)&&this.setValue(o),t.DropDownDiv.hideWithoutAnimation(),o=!0),o&&e.stopPropagation()},t.FieldColour.prototype.onBlocklyAction=function(e){if(this.picker_){if(e===t.navigation.ACTION_PREVIOUS)return this.moveHighlightBy_(0,-1),!0;if(e===t.navigation.ACTION_NEXT)return this.moveHighlightBy_(0,1),!0;if(e===t.navigation.ACTION_OUT)return this.moveHighlightBy_(-1,0),!0;if(e===t.navigation.ACTION_IN)return this.moveHighlightBy_(1,0),!0}return t.FieldColour.superClass_.onBlocklyAction.call(this,e)},t.FieldColour.prototype.moveHighlightBy_=function(e,o){var i=this.colours_||t.FieldColour.COLOURS,n=this.columns_||t.FieldColour.COLUMNS,s=this.highlightedIndex_%n,r=Math.floor(this.highlightedIndex_/n);s+=e,r+=o,0>e?0>s&&0s&&(s=0):0n-1&&rn-1&&s--:0>o?0>r&&(r=0):0Math.floor(i.length/n)-1&&(r=Math.floor(i.length/n)-1),this.setHighlightedCell_(this.picker_.childNodes[r].childNodes[s],r*n+s)},t.FieldColour.prototype.onMouseMove_=function(t){var e=(t=t.target)&&Number(t.getAttribute("data-index"));null!==e&&e!==this.highlightedIndex_&&this.setHighlightedCell_(t,e)},t.FieldColour.prototype.onMouseEnter_=function(){this.picker_.focus({preventScroll:!0})},t.FieldColour.prototype.onMouseLeave_=function(){this.picker_.blur();var e=this.getHighlighted_();e&&t.utils.dom.removeClass(e,"blocklyColourHighlighted")},t.FieldColour.prototype.getHighlighted_=function(){var e=this.columns_||t.FieldColour.COLUMNS,o=this.picker_.childNodes[Math.floor(this.highlightedIndex_/e)];return o?o.childNodes[this.highlightedIndex_%e]:null},t.FieldColour.prototype.setHighlightedCell_=function(e,o){var i=this.getHighlighted_();i&&t.utils.dom.removeClass(i,"blocklyColourHighlighted"),t.utils.dom.addClass(e,"blocklyColourHighlighted"),this.highlightedIndex_=o,t.utils.aria.setState(this.picker_,t.utils.aria.State.ACTIVEDESCENDANT,e.getAttribute("id"))},t.FieldColour.prototype.dropdownCreate_=function(){var e=this.columns_||t.FieldColour.COLUMNS,o=this.colours_||t.FieldColour.COLOURS,i=this.titles_||t.FieldColour.TITLES,n=this.getValue(),s=document.createElement("table");s.className="blocklyColourTable",s.tabIndex=0,s.dir="ltr",t.utils.aria.setRole(s,t.utils.aria.Role.GRID),t.utils.aria.setState(s,t.utils.aria.State.EXPANDED,!0),t.utils.aria.setState(s,t.utils.aria.State.ROWCOUNT,Math.floor(o.length/e)),t.utils.aria.setState(s,t.utils.aria.State.COLCOUNT,e);for(var r,a=0;atr>td {","border: .5px solid #888;","box-sizing: border-box;","cursor: pointer;","display: inline-block;","height: 20px;","padding: 0;","width: 20px;","}",".blocklyColourTable>tr>td.blocklyColourHighlighted {","border-color: #eee;","box-shadow: 2px 2px 7px 2px rgba(0,0,0,.3);","position: relative;","}",".blocklyColourSelected, .blocklyColourSelected:hover {","border-color: #eee !important;","outline: 1px solid #333;","position: relative;","}"]),t.fieldRegistry.register("field_colour",t.FieldColour),t.FieldDropdown=function(e,o,i){"function"!=typeof e&&t.FieldDropdown.validateOptions_(e),this.menuGenerator_=e,this.suffixField=this.prefixField=this.generatedOptions_=null,this.trimOptions_(),this.selectedOption_=this.getOptions(!1)[0],t.FieldDropdown.superClass_.constructor.call(this,this.selectedOption_[1],o,i),this.svgArrow_=this.arrow_=this.imageElement_=this.menu_=this.selectedMenuItem_=null},t.utils.object.inherits(t.FieldDropdown,t.Field),t.FieldDropdown.fromJson=function(e){return new t.FieldDropdown(e.options,void 0,e)},t.FieldDropdown.prototype.SERIALIZABLE=!0,t.FieldDropdown.CHECKMARK_OVERHANG=25,t.FieldDropdown.MAX_MENU_HEIGHT_VH=.45,t.FieldDropdown.IMAGE_Y_OFFSET=5,t.FieldDropdown.IMAGE_Y_PADDING=2*t.FieldDropdown.IMAGE_Y_OFFSET,t.FieldDropdown.ARROW_CHAR=t.utils.userAgent.ANDROID?"â–Ľ":"â–ľ",t.FieldDropdown.prototype.CURSOR="default",t.FieldDropdown.prototype.initView=function(){this.shouldAddBorderRect_()?this.createBorderRect_():this.clickTarget_=this.sourceBlock_.getSvgRoot(),this.createTextElement_(),this.imageElement_=t.utils.dom.createSvgElement(t.utils.Svg.IMAGE,{},this.fieldGroup_),this.getConstants().FIELD_DROPDOWN_SVG_ARROW?this.createSVGArrow_():this.createTextArrow_(),this.borderRect_&&t.utils.dom.addClass(this.borderRect_,"blocklyDropdownRect")},t.FieldDropdown.prototype.shouldAddBorderRect_=function(){return!this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW||this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW&&!this.sourceBlock_.isShadow()},t.FieldDropdown.prototype.createTextArrow_=function(){this.arrow_=t.utils.dom.createSvgElement(t.utils.Svg.TSPAN,{},this.textElement_),this.arrow_.appendChild(document.createTextNode(this.sourceBlock_.RTL?t.FieldDropdown.ARROW_CHAR+" ":" "+t.FieldDropdown.ARROW_CHAR)),this.sourceBlock_.RTL?this.textElement_.insertBefore(this.arrow_,this.textContent_):this.textElement_.appendChild(this.arrow_)},t.FieldDropdown.prototype.createSVGArrow_=function(){this.svgArrow_=t.utils.dom.createSvgElement(t.utils.Svg.IMAGE,{height:this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE+"px",width:this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE+"px"},this.fieldGroup_),this.svgArrow_.setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",this.getConstants().FIELD_DROPDOWN_SVG_ARROW_DATAURI)},t.FieldDropdown.prototype.showEditor_=function(e){if(this.menu_=this.dropdownCreate_(),this.menu_.openingCoords=e&&"number"==typeof e.clientX?new t.utils.Coordinate(e.clientX,e.clientY):null,this.menu_.render(t.DropDownDiv.getContentDiv()),e=this.menu_.getElement(),t.utils.dom.addClass(e,"blocklyDropdownMenu"),this.getConstants().FIELD_DROPDOWN_COLOURED_DIV){e=this.sourceBlock_.isShadow()?this.sourceBlock_.getParent().getColour():this.sourceBlock_.getColour();var o=this.sourceBlock_.isShadow()?this.sourceBlock_.getParent().style.colourTertiary:this.sourceBlock_.style.colourTertiary;t.DropDownDiv.setColour(e,o)}t.DropDownDiv.showPositionedByField(this,this.dropdownDispose_.bind(this)),this.menu_.focus(),this.selectedMenuItem_&&this.menu_.setHighlighted(this.selectedMenuItem_),this.applyColour()},t.FieldDropdown.prototype.dropdownCreate_=function(){var e=new t.Menu;e.setRole(t.utils.aria.Role.LISTBOX);var o=this.getOptions(!1);this.selectedMenuItem_=null;for(var i=0;ie.length)){for(o=[],i=0;i=i||0>=o)throw Error("Height and width values of an image field must be greater than 0.");this.flipRtl_=!1,this.altText_="",t.FieldImage.superClass_.constructor.call(this,e,null,a),a||(this.flipRtl_=!!r,this.altText_=t.utils.replaceMessageReferences(n)||""),this.size_=new t.utils.Size(o,i+t.FieldImage.Y_PADDING),this.imageHeight_=i,this.clickHandler_=null,"function"==typeof s&&(this.clickHandler_=s),this.imageElement_=null},t.utils.object.inherits(t.FieldImage,t.Field),t.FieldImage.prototype.DEFAULT_VALUE="",t.FieldImage.fromJson=function(e){return new t.FieldImage(e.src,e.width,e.height,void 0,void 0,void 0,e)},t.FieldImage.Y_PADDING=1,t.FieldImage.prototype.EDITABLE=!1,t.FieldImage.prototype.isDirty_=!1,t.FieldImage.prototype.configure_=function(e){t.FieldImage.superClass_.configure_.call(this,e),this.flipRtl_=!!e.flipRtl,this.altText_=t.utils.replaceMessageReferences(e.alt)||""},t.FieldImage.prototype.initView=function(){this.imageElement_=t.utils.dom.createSvgElement(t.utils.Svg.IMAGE,{height:this.imageHeight_+"px",width:this.size_.width+"px",alt:this.altText_},this.fieldGroup_),this.imageElement_.setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",this.value_),this.clickHandler_&&(this.imageElement_.style.cursor="pointer")},t.FieldImage.prototype.updateSize_=function(){},t.FieldImage.prototype.doClassValidation_=function(t){return"string"!=typeof t?null:t},t.FieldImage.prototype.doValueUpdate_=function(e){this.value_=e,this.imageElement_&&this.imageElement_.setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",String(this.value_))},t.FieldImage.prototype.getFlipRtl=function(){return this.flipRtl_},t.FieldImage.prototype.setAlt=function(t){t!=this.altText_&&(this.altText_=t||"",this.imageElement_&&this.imageElement_.setAttribute("alt",this.altText_))},t.FieldImage.prototype.showEditor_=function(){this.clickHandler_&&this.clickHandler_(this)},t.FieldImage.prototype.setOnClickHandler=function(t){this.clickHandler_=t},t.FieldImage.prototype.getText_=function(){return this.altText_},t.fieldRegistry.register("field_image",t.FieldImage),t.FieldMultilineInput=function(e,o,i){t.FieldMultilineInput.superClass_.constructor.call(this,e,o,i),this.textGroup_=null},t.utils.object.inherits(t.FieldMultilineInput,t.FieldTextInput),t.FieldMultilineInput.fromJson=function(e){var o=t.utils.replaceMessageReferences(e.text);return new t.FieldMultilineInput(o,void 0,e)},t.FieldMultilineInput.prototype.toXml=function(t){return t.textContent=this.getValue().replace(/\n/g," "),t},t.FieldMultilineInput.prototype.fromXml=function(t){this.setValue(t.textContent.replace(/ /g,"\n"))},t.FieldMultilineInput.prototype.initView=function(){this.createBorderRect_(),this.textGroup_=t.utils.dom.createSvgElement(t.utils.Svg.G,{class:"blocklyEditableText"},this.fieldGroup_)},t.FieldMultilineInput.prototype.getDisplayText_=function(){var e=this.value_;if(!e)return t.Field.NBSP;var o=e.split("\n");e="";for(var i=0;ithis.maxDisplayLength&&(n=n.substring(0,this.maxDisplayLength-4)+"..."),e+=n=n.replace(/\s/g,t.Field.NBSP),i!==o.length-1&&(e+="\n")}return this.sourceBlock_.RTL&&(e+="‏"),e},t.FieldMultilineInput.prototype.render_=function(){for(var e;e=this.textGroup_.firstChild;)this.textGroup_.removeChild(e);e=this.getDisplayText_().split("\n");for(var o=0,i=0;io&&(o=s),i+=this.getConstants().FIELD_TEXT_HEIGHT+(0this.max_&&t.utils.aria.setState(e,t.utils.aria.State.VALUEMAX,this.max_),e},t.fieldRegistry.register("field_number",t.FieldNumber),t.FieldVariable=function(e,o,i,n,s){this.menuGenerator_=t.FieldVariable.dropdownCreate,this.defaultVariableName=e||"",this.size_=new t.utils.Size(0,0),s&&this.configure_(s),o&&this.setValidator(o),s||this.setTypes_(i,n)},t.utils.object.inherits(t.FieldVariable,t.FieldDropdown),t.FieldVariable.fromJson=function(e){var o=t.utils.replaceMessageReferences(e.variable);return new t.FieldVariable(o,void 0,void 0,void 0,e)},t.FieldVariable.prototype.SERIALIZABLE=!0,t.FieldVariable.prototype.configure_=function(e){t.FieldVariable.superClass_.configure_.call(this,e),this.setTypes_(e.variableTypes,e.defaultType)},t.FieldVariable.prototype.initModel=function(){if(!this.variable_){var e=t.Variables.getOrCreateVariablePackage(this.sourceBlock_.workspace,null,this.defaultVariableName,this.defaultType_);this.doValueUpdate_(e.getId())}},t.FieldVariable.prototype.shouldAddBorderRect_=function(){return t.FieldVariable.superClass_.shouldAddBorderRect_.call(this)&&(!this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW||"variables_get"!=this.sourceBlock_.type)},t.FieldVariable.prototype.fromXml=function(e){var o=e.getAttribute("id"),i=e.textContent,n=e.getAttribute("variabletype")||e.getAttribute("variableType")||"";if(o=t.Variables.getOrCreateVariablePackage(this.sourceBlock_.workspace,o,i,n),null!=n&&n!==o.type)throw Error("Serialized variable type with id '"+o.getId()+"' had type "+o.type+", and does not match variable field that references it: "+t.Xml.domToText(e)+".");this.setValue(o.getId())},t.FieldVariable.prototype.toXml=function(t){return this.initModel(),t.id=this.variable_.getId(),t.textContent=this.variable_.name,this.variable_.type&&t.setAttribute("variabletype",this.variable_.type),t},t.FieldVariable.prototype.setSourceBlock=function(e){if(e.isShadow())throw Error("Variable fields are not allowed to exist on shadow blocks.");t.FieldVariable.superClass_.setSourceBlock.call(this,e)},t.FieldVariable.prototype.getValue=function(){return this.variable_?this.variable_.getId():null},t.FieldVariable.prototype.getText=function(){return this.variable_?this.variable_.name:""},t.FieldVariable.prototype.getVariable=function(){return this.variable_},t.FieldVariable.prototype.getValidator=function(){return this.variable_?this.validator_:null},t.FieldVariable.prototype.doClassValidation_=function(e){if(null===e)return null;var o=t.Variables.getVariable(this.sourceBlock_.workspace,e);return o?(o=o.type,this.typeIsAllowed_(o)?e:(console.warn("Variable type doesn't match this field! Type was "+o),null)):(console.warn("Variable id doesn't point to a real variable! ID was "+e),null)},t.FieldVariable.prototype.doValueUpdate_=function(e){this.variable_=t.Variables.getVariable(this.sourceBlock_.workspace,e),t.FieldVariable.superClass_.doValueUpdate_.call(this,e)},t.FieldVariable.prototype.typeIsAllowed_=function(t){var e=this.getVariableTypes_();if(!e)return!0;for(var o=0;orect,",t+" .blocklyEditableText>rect {","fill: "+this.FIELD_BORDER_RECT_COLOUR+";","fill-opacity: .6;","stroke: none;","}",t+" .blocklyNonEditableText>text,",t+" .blocklyEditableText>text {","fill: #000;","}",t+" .blocklyFlyoutLabelText {","fill: #000;","}",t+" .blocklyText.blocklyBubbleText {","fill: #000;","}",t+" .blocklyEditableText:not(.editing):hover>rect {","stroke: #fff;","stroke-width: 2;","}",t+" .blocklyHtmlInput {","font-family: "+this.FIELD_TEXT_FONTFAMILY+";","font-weight: "+this.FIELD_TEXT_FONTWEIGHT+";","}",t+" .blocklySelected>.blocklyPath {","stroke: #fc3;","stroke-width: 3px;","}",t+" .blocklyHighlightedConnectionPath {","stroke: #fc3;","}",t+" .blocklyReplaceable .blocklyPath {","fill-opacity: .5;","}",t+" .blocklyReplaceable .blocklyPathLight,",t+" .blocklyReplaceable .blocklyPathDark {","display: none;","}",t+" .blocklyInsertionMarker>.blocklyPath {","fill-opacity: "+this.INSERTION_MARKER_OPACITY+";","stroke: none;","}"]},t.blockRendering.MarkerSvg=function(t,e,o){this.workspace_=t,this.marker_=o,this.parent_=null,this.constants_=e,this.currentMarkerSvg=null,t=this.isCursor()?this.constants_.CURSOR_COLOUR:this.constants_.MARKER_COLOUR,this.colour_=o.colour||t},t.blockRendering.MarkerSvg.CURSOR_CLASS="blocklyCursor",t.blockRendering.MarkerSvg.MARKER_CLASS="blocklyMarker",t.blockRendering.MarkerSvg.HEIGHT_MULTIPLIER=.75,t.blockRendering.MarkerSvg.prototype.getSvgRoot=function(){return this.svgGroup_},t.blockRendering.MarkerSvg.prototype.getMarker=function(){return this.marker_},t.blockRendering.MarkerSvg.prototype.isCursor=function(){return"cursor"==this.marker_.type},t.blockRendering.MarkerSvg.prototype.createDom=function(){var e=this.isCursor()?t.blockRendering.MarkerSvg.CURSOR_CLASS:t.blockRendering.MarkerSvg.MARKER_CLASS;return this.svgGroup_=t.utils.dom.createSvgElement(t.utils.Svg.G,{class:e},null),this.createDomInternal_(),this.svgGroup_},t.blockRendering.MarkerSvg.prototype.setParent_=function(t){this.isCursor()?(this.parent_&&this.parent_.setCursorSvg(null),t.setCursorSvg(this.getSvgRoot())):(this.parent_&&this.parent_.setMarkerSvg(null),t.setMarkerSvg(this.getSvgRoot())),this.parent_=t},t.blockRendering.MarkerSvg.prototype.draw=function(t,e){if(e){this.constants_=this.workspace_.getRenderer().getConstants();var o=this.isCursor()?this.constants_.CURSOR_COLOUR:this.constants_.MARKER_COLOUR;this.colour_=this.marker_.colour||o,this.applyColour_(e),this.showAtLocation_(e),this.fireMarkerEvent_(t,e),void 0!==(t=this.currentMarkerSvg.childNodes[0])&&t.beginElement&&t.beginElement()}else this.hide()},t.blockRendering.MarkerSvg.prototype.showAtLocation_=function(e){var o=e.getLocation();e.getType()==t.ASTNode.types.BLOCK?this.showWithBlock_(e):e.getType()==t.ASTNode.types.OUTPUT?this.showWithOutput_(e):o.type==t.INPUT_VALUE?this.showWithInput_(e):o.type==t.NEXT_STATEMENT?this.showWithNext_(e):e.getType()==t.ASTNode.types.PREVIOUS?this.showWithPrevious_(e):e.getType()==t.ASTNode.types.FIELD?this.showWithField_(e):e.getType()==t.ASTNode.types.WORKSPACE?this.showWithCoordinates_(e):e.getType()==t.ASTNode.types.STACK&&this.showWithStack_(e)},t.blockRendering.MarkerSvg.prototype.showWithBlockPrevOutput_=function(e){var o=(e=e.getSourceBlock()).width,i=e.height,n=i*t.blockRendering.MarkerSvg.HEIGHT_MULTIPLIER,s=this.constants_.CURSOR_BLOCK_PADDING;if(e.previousConnection){var r=this.constants_.shapeFor(e.previousConnection);this.positionPrevious_(o,s,n,r)}else e.outputConnection?(r=this.constants_.shapeFor(e.outputConnection),this.positionOutput_(o,i,r)):this.positionBlock_(o,s,n);this.setParent_(e),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showWithBlock_=function(t){this.showWithBlockPrevOutput_(t)},t.blockRendering.MarkerSvg.prototype.showWithPrevious_=function(t){this.showWithBlockPrevOutput_(t)},t.blockRendering.MarkerSvg.prototype.showWithOutput_=function(t){this.showWithBlockPrevOutput_(t)},t.blockRendering.MarkerSvg.prototype.showWithCoordinates_=function(t){var e=t.getWsCoordinate();t=e.x,e=e.y,this.workspace_.RTL&&(t-=this.constants_.CURSOR_WS_WIDTH),this.positionLine_(t,e,this.constants_.CURSOR_WS_WIDTH),this.setParent_(this.workspace_),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showWithField_=function(t){var e=(t=t.getLocation()).getSize().width,o=t.getSize().height;this.positionRect_(0,0,e,o),this.setParent_(t),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showWithInput_=function(t){var e=(t=t.getLocation()).getSourceBlock();this.positionInput_(t),this.setParent_(e),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showWithNext_=function(t){var e=t.getLocation();t=e.getSourceBlock();var o=0;e=e.getOffsetInBlock().y;var i=t.getHeightWidth().width;this.workspace_.RTL&&(o=-i),this.positionLine_(o,e,i),this.setParent_(t),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showWithStack_=function(t){var e=(t=t.getLocation()).getHeightWidth(),o=e.width+this.constants_.CURSOR_STACK_PADDING;e=e.height+this.constants_.CURSOR_STACK_PADDING;var i=-this.constants_.CURSOR_STACK_PADDING/2,n=-this.constants_.CURSOR_STACK_PADDING/2,s=i;this.workspace_.RTL&&(s=-(o+i)),this.positionRect_(s,n,o,e),this.setParent_(t),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showCurrent_=function(){this.hide(),this.currentMarkerSvg.style.display=""},t.blockRendering.MarkerSvg.prototype.positionBlock_=function(e,o,i){e=t.utils.svgPaths.moveBy(-o,i)+t.utils.svgPaths.lineOnAxis("V",-o)+t.utils.svgPaths.lineOnAxis("H",e+2*o)+t.utils.svgPaths.lineOnAxis("V",i),this.markerBlock_.setAttribute("d",e),this.workspace_.RTL&&this.flipRtl_(this.markerBlock_),this.currentMarkerSvg=this.markerBlock_},t.blockRendering.MarkerSvg.prototype.positionInput_=function(e){var o=e.getOffsetInBlock().x,i=e.getOffsetInBlock().y;e=t.utils.svgPaths.moveTo(0,0)+this.constants_.shapeFor(e).pathDown,this.markerInput_.setAttribute("d",e),this.markerInput_.setAttribute("transform","translate("+o+","+i+")"+(this.workspace_.RTL?" scale(-1 1)":"")),this.currentMarkerSvg=this.markerInput_},t.blockRendering.MarkerSvg.prototype.positionLine_=function(t,e,o){this.markerSvgLine_.setAttribute("x",t),this.markerSvgLine_.setAttribute("y",e),this.markerSvgLine_.setAttribute("width",o),this.currentMarkerSvg=this.markerSvgLine_},t.blockRendering.MarkerSvg.prototype.positionOutput_=function(e,o,i){e=t.utils.svgPaths.moveBy(e,0)+t.utils.svgPaths.lineOnAxis("h",-(e-i.width))+t.utils.svgPaths.lineOnAxis("v",this.constants_.TAB_OFFSET_FROM_TOP)+i.pathDown+t.utils.svgPaths.lineOnAxis("V",o)+t.utils.svgPaths.lineOnAxis("H",e),this.markerBlock_.setAttribute("d",e),this.workspace_.RTL&&this.flipRtl_(this.markerBlock_),this.currentMarkerSvg=this.markerBlock_},t.blockRendering.MarkerSvg.prototype.positionPrevious_=function(e,o,i,n){e=t.utils.svgPaths.moveBy(-o,i)+t.utils.svgPaths.lineOnAxis("V",-o)+t.utils.svgPaths.lineOnAxis("H",this.constants_.NOTCH_OFFSET_LEFT)+n.pathLeft+t.utils.svgPaths.lineOnAxis("H",e+2*o)+t.utils.svgPaths.lineOnAxis("V",i),this.markerBlock_.setAttribute("d",e),this.workspace_.RTL&&this.flipRtl_(this.markerBlock_),this.currentMarkerSvg=this.markerBlock_},t.blockRendering.MarkerSvg.prototype.positionRect_=function(t,e,o,i){this.markerSvgRect_.setAttribute("x",t),this.markerSvgRect_.setAttribute("y",e),this.markerSvgRect_.setAttribute("width",o),this.markerSvgRect_.setAttribute("height",i),this.currentMarkerSvg=this.markerSvgRect_},t.blockRendering.MarkerSvg.prototype.flipRtl_=function(t){t.setAttribute("transform","scale(-1 1)")},t.blockRendering.MarkerSvg.prototype.hide=function(){this.markerSvgLine_.style.display="none",this.markerSvgRect_.style.display="none",this.markerInput_.style.display="none",this.markerBlock_.style.display="none"},t.blockRendering.MarkerSvg.prototype.fireMarkerEvent_=function(e,o){var i=o.getSourceBlock(),n=this.isCursor()?"cursorMove":"markerMove";e=new t.Events.Ui(i,n,e,o),o.getType()==t.ASTNode.types.WORKSPACE&&(e.workspaceId=o.getLocation().id),t.Events.fire(e)},t.blockRendering.MarkerSvg.prototype.getBlinkProperties_=function(){return{attributeType:"XML",attributeName:"fill",dur:"1s",values:this.colour_+";transparent;transparent;",repeatCount:"indefinite"}},t.blockRendering.MarkerSvg.prototype.createDomInternal_=function(){if(this.markerSvg_=t.utils.dom.createSvgElement(t.utils.Svg.G,{width:this.constants_.CURSOR_WS_WIDTH,height:this.constants_.WS_CURSOR_HEIGHT},this.svgGroup_),this.markerSvgLine_=t.utils.dom.createSvgElement(t.utils.Svg.RECT,{width:this.constants_.CURSOR_WS_WIDTH,height:this.constants_.WS_CURSOR_HEIGHT,style:"display: none"},this.markerSvg_),this.markerSvgRect_=t.utils.dom.createSvgElement(t.utils.Svg.RECT,{class:"blocklyVerticalMarker",rx:10,ry:10,style:"display: none"},this.markerSvg_),this.markerInput_=t.utils.dom.createSvgElement(t.utils.Svg.PATH,{transform:"",style:"display: none"},this.markerSvg_),this.markerBlock_=t.utils.dom.createSvgElement(t.utils.Svg.PATH,{transform:"",style:"display: none",fill:"none","stroke-width":this.constants_.CURSOR_STROKE_WIDTH},this.markerSvg_),this.isCursor()){var e=this.getBlinkProperties_();t.utils.dom.createSvgElement(t.utils.Svg.ANIMATE,e,this.markerSvgLine_),t.utils.dom.createSvgElement(t.utils.Svg.ANIMATE,e,this.markerInput_),e.attributeName="stroke",t.utils.dom.createSvgElement(t.utils.Svg.ANIMATE,e,this.markerBlock_)}return this.markerSvg_},t.blockRendering.MarkerSvg.prototype.applyColour_=function(t){this.markerSvgLine_.setAttribute("fill",this.colour_),this.markerSvgRect_.setAttribute("stroke",this.colour_),this.markerInput_.setAttribute("fill",this.colour_),this.markerBlock_.setAttribute("stroke",this.colour_),this.isCursor()&&(t=this.colour_+";transparent;transparent;",this.markerSvgLine_.firstChild.setAttribute("values",t),this.markerInput_.firstChild.setAttribute("values",t),this.markerBlock_.firstChild.setAttribute("values",t))},t.blockRendering.MarkerSvg.prototype.dispose=function(){this.svgGroup_&&t.utils.dom.removeNode(this.svgGroup_)},t.blockRendering.Types={NONE:0,FIELD:1,HAT:2,ICON:4,SPACER:8,BETWEEN_ROW_SPACER:16,IN_ROW_SPACER:32,EXTERNAL_VALUE_INPUT:64,INPUT:128,INLINE_INPUT:256,STATEMENT_INPUT:512,CONNECTION:1024,PREVIOUS_CONNECTION:2048,NEXT_CONNECTION:4096,OUTPUT_CONNECTION:8192,CORNER:16384,LEFT_SQUARE_CORNER:32768,LEFT_ROUND_CORNER:65536,RIGHT_SQUARE_CORNER:131072,RIGHT_ROUND_CORNER:262144,JAGGED_EDGE:524288,ROW:1048576,TOP_ROW:2097152,BOTTOM_ROW:4194304,INPUT_ROW:8388608},t.blockRendering.Types.LEFT_CORNER=t.blockRendering.Types.LEFT_SQUARE_CORNER|t.blockRendering.Types.LEFT_ROUND_CORNER,t.blockRendering.Types.RIGHT_CORNER=t.blockRendering.Types.RIGHT_SQUARE_CORNER|t.blockRendering.Types.RIGHT_ROUND_CORNER,t.blockRendering.Types.nextTypeValue_=16777216,t.blockRendering.Types.getType=function(e){return Object.prototype.hasOwnProperty.call(t.blockRendering.Types,e)||(t.blockRendering.Types[e]=t.blockRendering.Types.nextTypeValue_,t.blockRendering.Types.nextTypeValue_<<=1),t.blockRendering.Types[e]},t.blockRendering.Types.isField=function(e){return e.type&t.blockRendering.Types.FIELD},t.blockRendering.Types.isHat=function(e){return e.type&t.blockRendering.Types.HAT},t.blockRendering.Types.isIcon=function(e){return e.type&t.blockRendering.Types.ICON},t.blockRendering.Types.isSpacer=function(e){return e.type&t.blockRendering.Types.SPACER},t.blockRendering.Types.isInRowSpacer=function(e){return e.type&t.blockRendering.Types.IN_ROW_SPACER},t.blockRendering.Types.isInput=function(e){return e.type&t.blockRendering.Types.INPUT},t.blockRendering.Types.isExternalInput=function(e){return e.type&t.blockRendering.Types.EXTERNAL_VALUE_INPUT},t.blockRendering.Types.isInlineInput=function(e){return e.type&t.blockRendering.Types.INLINE_INPUT},t.blockRendering.Types.isStatementInput=function(e){return e.type&t.blockRendering.Types.STATEMENT_INPUT},t.blockRendering.Types.isPreviousConnection=function(e){return e.type&t.blockRendering.Types.PREVIOUS_CONNECTION},t.blockRendering.Types.isNextConnection=function(e){return e.type&t.blockRendering.Types.NEXT_CONNECTION},t.blockRendering.Types.isPreviousOrNextConnection=function(e){return e.type&(t.blockRendering.Types.PREVIOUS_CONNECTION|t.blockRendering.Types.NEXT_CONNECTION)},t.blockRendering.Types.isLeftRoundedCorner=function(e){return e.type&t.blockRendering.Types.LEFT_ROUND_CORNER},t.blockRendering.Types.isRightRoundedCorner=function(e){return e.type&t.blockRendering.Types.RIGHT_ROUND_CORNER},t.blockRendering.Types.isLeftSquareCorner=function(e){return e.type&t.blockRendering.Types.LEFT_SQUARE_CORNER},t.blockRendering.Types.isRightSquareCorner=function(e){return e.type&t.blockRendering.Types.RIGHT_SQUARE_CORNER},t.blockRendering.Types.isCorner=function(e){return e.type&t.blockRendering.Types.CORNER},t.blockRendering.Types.isJaggedEdge=function(e){return e.type&t.blockRendering.Types.JAGGED_EDGE},t.blockRendering.Types.isRow=function(e){return e.type&t.blockRendering.Types.ROW},t.blockRendering.Types.isBetweenRowSpacer=function(e){return e.type&t.blockRendering.Types.BETWEEN_ROW_SPACER},t.blockRendering.Types.isTopRow=function(e){return e.type&t.blockRendering.Types.TOP_ROW},t.blockRendering.Types.isBottomRow=function(e){return e.type&t.blockRendering.Types.BOTTOM_ROW},t.blockRendering.Types.isTopOrBottomRow=function(e){return e.type&(t.blockRendering.Types.TOP_ROW|t.blockRendering.Types.BOTTOM_ROW)},t.blockRendering.Types.isInputRow=function(e){return e.type&t.blockRendering.Types.INPUT_ROW},t.blockRendering.Measurable=function(e){this.height=this.width=0,this.type=t.blockRendering.Types.NONE,this.centerline=this.xPos=0,this.constants_=e,this.notchOffset=this.constants_.NOTCH_OFFSET_LEFT},t.blockRendering.Connection=function(e,o){t.blockRendering.Connection.superClass_.constructor.call(this,e),this.connectionModel=o,this.shape=this.constants_.shapeFor(o),this.isDynamicShape=!!this.shape.isDynamic,this.type|=t.blockRendering.Types.CONNECTION},t.utils.object.inherits(t.blockRendering.Connection,t.blockRendering.Measurable),t.blockRendering.OutputConnection=function(e,o){t.blockRendering.OutputConnection.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.OUTPUT_CONNECTION,this.height=this.isDynamicShape?0:this.shape.height,this.startX=this.width=this.isDynamicShape?0:this.shape.width,this.connectionOffsetY=this.constants_.TAB_OFFSET_FROM_TOP,this.connectionOffsetX=0},t.utils.object.inherits(t.blockRendering.OutputConnection,t.blockRendering.Connection),t.blockRendering.PreviousConnection=function(e,o){t.blockRendering.PreviousConnection.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.PREVIOUS_CONNECTION,this.height=this.shape.height,this.width=this.shape.width},t.utils.object.inherits(t.blockRendering.PreviousConnection,t.blockRendering.Connection),t.blockRendering.NextConnection=function(e,o){t.blockRendering.NextConnection.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.NEXT_CONNECTION,this.height=this.shape.height,this.width=this.shape.width},t.utils.object.inherits(t.blockRendering.NextConnection,t.blockRendering.Connection),t.blockRendering.InputConnection=function(e,o){t.blockRendering.InputConnection.superClass_.constructor.call(this,e,o.connection),this.type|=t.blockRendering.Types.INPUT,this.input=o,this.align=o.align,(this.connectedBlock=o.connection&&o.connection.targetBlock()?o.connection.targetBlock():null)?(e=this.connectedBlock.getHeightWidth(),this.connectedBlockWidth=e.width,this.connectedBlockHeight=e.height):this.connectedBlockHeight=this.connectedBlockWidth=0,this.connectionOffsetY=this.connectionOffsetX=0},t.utils.object.inherits(t.blockRendering.InputConnection,t.blockRendering.Connection),t.blockRendering.InlineInput=function(e,o){t.blockRendering.InlineInput.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.INLINE_INPUT,this.connectedBlock?(this.width=this.connectedBlockWidth,this.height=this.connectedBlockHeight):(this.height=this.constants_.EMPTY_INLINE_INPUT_HEIGHT,this.width=this.constants_.EMPTY_INLINE_INPUT_PADDING),this.connectionHeight=this.isDynamicShape?this.shape.height(this.height):this.shape.height,this.connectionWidth=this.isDynamicShape?this.shape.width(this.height):this.shape.width,this.connectedBlock||(this.width+=this.connectionWidth*(this.isDynamicShape?2:1)),this.connectionOffsetY=this.isDynamicShape?this.shape.connectionOffsetY(this.connectionHeight):this.constants_.TAB_OFFSET_FROM_TOP,this.connectionOffsetX=this.isDynamicShape?this.shape.connectionOffsetX(this.connectionWidth):0},t.utils.object.inherits(t.blockRendering.InlineInput,t.blockRendering.InputConnection),t.blockRendering.StatementInput=function(e,o){t.blockRendering.StatementInput.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.STATEMENT_INPUT,this.height=this.connectedBlock?this.connectedBlockHeight+this.constants_.STATEMENT_BOTTOM_SPACER:this.constants_.EMPTY_STATEMENT_INPUT_HEIGHT,this.width=this.constants_.STATEMENT_INPUT_NOTCH_OFFSET+this.shape.width},t.utils.object.inherits(t.blockRendering.StatementInput,t.blockRendering.InputConnection),t.blockRendering.ExternalValueInput=function(e,o){t.blockRendering.ExternalValueInput.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.EXTERNAL_VALUE_INPUT,this.height=this.connectedBlock?this.connectedBlockHeight-this.constants_.TAB_OFFSET_FROM_TOP-this.constants_.MEDIUM_PADDING:this.shape.height,this.width=this.shape.width+this.constants_.EXTERNAL_VALUE_INPUT_PADDING,this.connectionOffsetY=this.constants_.TAB_OFFSET_FROM_TOP,this.connectionHeight=this.shape.height,this.connectionWidth=this.shape.width},t.utils.object.inherits(t.blockRendering.ExternalValueInput,t.blockRendering.InputConnection),t.blockRendering.Icon=function(e,o){t.blockRendering.Icon.superClass_.constructor.call(this,e),this.icon=o,this.isVisible=o.isVisible(),this.type|=t.blockRendering.Types.ICON,e=o.getCorrectedSize(),this.height=e.height,this.width=e.width},t.utils.object.inherits(t.blockRendering.Icon,t.blockRendering.Measurable),t.blockRendering.JaggedEdge=function(e){t.blockRendering.JaggedEdge.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.JAGGED_EDGE,this.height=this.constants_.JAGGED_TEETH.height,this.width=this.constants_.JAGGED_TEETH.width},t.utils.object.inherits(t.blockRendering.JaggedEdge,t.blockRendering.Measurable),t.blockRendering.Field=function(e,o,i){t.blockRendering.Field.superClass_.constructor.call(this,e),this.field=o,this.isEditable=o.EDITABLE,this.flipRtl=o.getFlipRtl(),this.type|=t.blockRendering.Types.FIELD,e=this.field.getSize(),this.height=e.height,this.width=e.width,this.parentInput=i},t.utils.object.inherits(t.blockRendering.Field,t.blockRendering.Measurable),t.blockRendering.Hat=function(e){t.blockRendering.Hat.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.HAT,this.height=this.constants_.START_HAT.height,this.width=this.constants_.START_HAT.width,this.ascenderHeight=this.height},t.utils.object.inherits(t.blockRendering.Hat,t.blockRendering.Measurable),t.blockRendering.SquareCorner=function(e,o){t.blockRendering.SquareCorner.superClass_.constructor.call(this,e),this.type=(o&&"left"!=o?t.blockRendering.Types.RIGHT_SQUARE_CORNER:t.blockRendering.Types.LEFT_SQUARE_CORNER)|t.blockRendering.Types.CORNER,this.width=this.height=this.constants_.NO_PADDING},t.utils.object.inherits(t.blockRendering.SquareCorner,t.blockRendering.Measurable),t.blockRendering.RoundCorner=function(e,o){t.blockRendering.RoundCorner.superClass_.constructor.call(this,e),this.type=(o&&"left"!=o?t.blockRendering.Types.RIGHT_ROUND_CORNER:t.blockRendering.Types.LEFT_ROUND_CORNER)|t.blockRendering.Types.CORNER,this.width=this.constants_.CORNER_RADIUS,this.height=this.constants_.CORNER_RADIUS/2},t.utils.object.inherits(t.blockRendering.RoundCorner,t.blockRendering.Measurable),t.blockRendering.InRowSpacer=function(e,o){t.blockRendering.InRowSpacer.superClass_.constructor.call(this,e),this.type=this.type|t.blockRendering.Types.SPACER|t.blockRendering.Types.IN_ROW_SPACER,this.width=o,this.height=this.constants_.SPACER_DEFAULT_HEIGHT},t.utils.object.inherits(t.blockRendering.InRowSpacer,t.blockRendering.Measurable),t.blockRendering.Row=function(e){this.type=t.blockRendering.Types.ROW,this.elements=[],this.xPos=this.yPos=this.widthWithConnectedBlocks=this.minWidth=this.minHeight=this.width=this.height=0,this.hasJaggedEdge=this.hasDummyInput=this.hasInlineInput=this.hasStatement=this.hasExternalInput=!1,this.constants_=e,this.notchOffset=this.constants_.NOTCH_OFFSET_LEFT,this.align=null},t.blockRendering.Row.prototype.measure=function(){throw Error("Unexpected attempt to measure a base Row.")},t.blockRendering.Row.prototype.getLastInput=function(){for(var e,o=this.elements.length-1;e=this.elements[o];o--)if(t.blockRendering.Types.isInput(e))return e;return null},t.blockRendering.Row.prototype.startsWithElemSpacer=function(){return!0},t.blockRendering.Row.prototype.endsWithElemSpacer=function(){return!0},t.blockRendering.Row.prototype.getFirstSpacer=function(){for(var e,o=0;e=this.elements[o];o++)if(t.blockRendering.Types.isSpacer(e))return e;return null},t.blockRendering.Row.prototype.getLastSpacer=function(){for(var e,o=this.elements.length-1;e=this.elements[o];o--)if(t.blockRendering.Types.isSpacer(e))return e;return null},t.blockRendering.TopRow=function(e){t.blockRendering.TopRow.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.TOP_ROW,this.ascenderHeight=this.capline=0,this.hasPreviousConnection=!1,this.connection=null},t.utils.object.inherits(t.blockRendering.TopRow,t.blockRendering.Row),t.blockRendering.TopRow.prototype.hasLeftSquareCorner=function(t){var e=(t.hat?"cap"===t.hat:this.constants_.ADD_START_HATS)&&!t.outputConnection&&!t.previousConnection,o=t.getPreviousBlock();return!!t.outputConnection||e||!!o&&o.getNextBlock()==t},t.blockRendering.TopRow.prototype.hasRightSquareCorner=function(t){return!0},t.blockRendering.TopRow.prototype.measure=function(){for(var e,o=0,i=0,n=0,s=0;e=this.elements[s];s++)i+=e.width,t.blockRendering.Types.isSpacer(e)||(t.blockRendering.Types.isHat(e)?n=Math.max(n,e.ascenderHeight):o=Math.max(o,e.height));this.width=Math.max(this.minWidth,i),this.height=Math.max(this.minHeight,o)+n,this.capline=this.ascenderHeight=n,this.widthWithConnectedBlocks=this.width},t.blockRendering.TopRow.prototype.startsWithElemSpacer=function(){return!1},t.blockRendering.TopRow.prototype.endsWithElemSpacer=function(){return!1},t.blockRendering.BottomRow=function(e){t.blockRendering.BottomRow.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.BOTTOM_ROW,this.hasNextConnection=!1,this.connection=null,this.baseline=this.descenderHeight=0},t.utils.object.inherits(t.blockRendering.BottomRow,t.blockRendering.Row),t.blockRendering.BottomRow.prototype.hasLeftSquareCorner=function(t){return!!t.outputConnection||!!t.getNextBlock()},t.blockRendering.BottomRow.prototype.hasRightSquareCorner=function(t){return!0},t.blockRendering.BottomRow.prototype.measure=function(){for(var e,o=0,i=0,n=0,s=0;e=this.elements[s];s++)i+=e.width,t.blockRendering.Types.isSpacer(e)||(t.blockRendering.Types.isNextConnection(e)?n=Math.max(n,e.height):o=Math.max(o,e.height));this.width=Math.max(this.minWidth,i),this.height=Math.max(this.minHeight,o)+n,this.descenderHeight=n,this.widthWithConnectedBlocks=this.width},t.blockRendering.BottomRow.prototype.startsWithElemSpacer=function(){return!1},t.blockRendering.BottomRow.prototype.endsWithElemSpacer=function(){return!1},t.blockRendering.SpacerRow=function(e,o,i){t.blockRendering.SpacerRow.superClass_.constructor.call(this,e),this.type=this.type|t.blockRendering.Types.SPACER|t.blockRendering.Types.BETWEEN_ROW_SPACER,this.width=i,this.height=o,this.followsStatement=!1,this.widthWithConnectedBlocks=0,this.elements=[new t.blockRendering.InRowSpacer(this.constants_,i)]},t.utils.object.inherits(t.blockRendering.SpacerRow,t.blockRendering.Row),t.blockRendering.SpacerRow.prototype.measure=function(){},t.blockRendering.InputRow=function(e){t.blockRendering.InputRow.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.INPUT_ROW,this.connectedBlockWidths=0},t.utils.object.inherits(t.blockRendering.InputRow,t.blockRendering.Row),t.blockRendering.InputRow.prototype.measure=function(){this.width=this.minWidth,this.height=this.minHeight;for(var e,o=0,i=0;e=this.elements[i];i++)this.width+=e.width,t.blockRendering.Types.isInput(e)&&(t.blockRendering.Types.isStatementInput(e)?o+=e.connectedBlockWidth:t.blockRendering.Types.isExternalInput(e)&&0!=e.connectedBlockWidth&&(o+=e.connectedBlockWidth-e.connectionWidth)),t.blockRendering.Types.isSpacer(e)||(this.height=Math.max(this.height,e.height));this.connectedBlockWidths=o,this.widthWithConnectedBlocks=this.width+o},t.blockRendering.InputRow.prototype.endsWithElemSpacer=function(){return!this.hasExternalInput&&!this.hasStatement},t.blockRendering.RenderInfo=function(e,o){this.block_=o,this.renderer_=e,this.constants_=this.renderer_.getConstants(),this.outputConnection=o.outputConnection?new t.blockRendering.OutputConnection(this.constants_,o.outputConnection):null,this.isInline=o.getInputsInline()&&!o.isCollapsed(),this.isCollapsed=o.isCollapsed(),this.isInsertionMarker=o.isInsertionMarker(),this.RTL=o.RTL,this.statementEdge=this.width=this.widthWithChildren=this.height=0,this.rows=[],this.inputRows=[],this.hiddenIcons=[],this.topRow=new t.blockRendering.TopRow(this.constants_),this.bottomRow=new t.blockRendering.BottomRow(this.constants_),this.startY=this.startX=0},t.blockRendering.RenderInfo.prototype.getRenderer=function(){return this.renderer_},t.blockRendering.RenderInfo.prototype.measure=function(){this.createRows_(),this.addElemSpacing_(),this.addRowSpacing_(),this.computeBounds_(),this.alignRowElements_(),this.finalize_()},t.blockRendering.RenderInfo.prototype.createRows_=function(){this.populateTopRow_(),this.rows.push(this.topRow);var e=new t.blockRendering.InputRow(this.constants_);this.inputRows.push(e);var o=this.block_.getIcons();if(o.length)for(var i,n=0;i=o[n];n++){var s=new t.blockRendering.Icon(this.constants_,i);this.isCollapsed&&i.collapseHidden?this.hiddenIcons.push(s):e.elements.push(s)}for(i=null,n=0;o=this.block_.inputList[n];n++)if(o.isVisible()){for(this.shouldStartNewRow_(o,i)&&(this.rows.push(e),e=new t.blockRendering.InputRow(this.constants_),this.inputRows.push(e)),i=0;s=o.fieldRow[i];i++)e.elements.push(new t.blockRendering.Field(this.constants_,s,o));this.addInput_(o,e),i=o}this.isCollapsed&&(e.hasJaggedEdge=!0,e.elements.push(new t.blockRendering.JaggedEdge(this.constants_))),(e.elements.length||e.hasDummyInput)&&this.rows.push(e),this.populateBottomRow_(),this.rows.push(this.bottomRow)},t.blockRendering.RenderInfo.prototype.populateTopRow_=function(){var e=!!this.block_.previousConnection,o=(this.block_.hat?"cap"===this.block_.hat:this.constants_.ADD_START_HATS)&&!this.outputConnection&&!e;this.topRow.hasLeftSquareCorner(this.block_)?this.topRow.elements.push(new t.blockRendering.SquareCorner(this.constants_)):this.topRow.elements.push(new t.blockRendering.RoundCorner(this.constants_)),o?(e=new t.blockRendering.Hat(this.constants_),this.topRow.elements.push(e),this.topRow.capline=e.ascenderHeight):e&&(this.topRow.hasPreviousConnection=!0,this.topRow.connection=new t.blockRendering.PreviousConnection(this.constants_,this.block_.previousConnection),this.topRow.elements.push(this.topRow.connection)),this.block_.inputList.length&&this.block_.inputList[0].type==t.NEXT_STATEMENT&&!this.block_.isCollapsed()?this.topRow.minHeight=this.constants_.TOP_ROW_PRECEDES_STATEMENT_MIN_HEIGHT:this.topRow.minHeight=this.constants_.TOP_ROW_MIN_HEIGHT,this.topRow.hasRightSquareCorner(this.block_)?this.topRow.elements.push(new t.blockRendering.SquareCorner(this.constants_,"right")):this.topRow.elements.push(new t.blockRendering.RoundCorner(this.constants_,"right"))},t.blockRendering.RenderInfo.prototype.populateBottomRow_=function(){this.bottomRow.hasNextConnection=!!this.block_.nextConnection,this.bottomRow.minHeight=this.block_.inputList.length&&this.block_.inputList[this.block_.inputList.length-1].type==t.NEXT_STATEMENT?this.constants_.BOTTOM_ROW_AFTER_STATEMENT_MIN_HEIGHT:this.constants_.BOTTOM_ROW_MIN_HEIGHT,this.bottomRow.hasLeftSquareCorner(this.block_)?this.bottomRow.elements.push(new t.blockRendering.SquareCorner(this.constants_)):this.bottomRow.elements.push(new t.blockRendering.RoundCorner(this.constants_)),this.bottomRow.hasNextConnection&&(this.bottomRow.connection=new t.blockRendering.NextConnection(this.constants_,this.block_.nextConnection),this.bottomRow.elements.push(this.bottomRow.connection)),this.bottomRow.hasRightSquareCorner(this.block_)?this.bottomRow.elements.push(new t.blockRendering.SquareCorner(this.constants_,"right")):this.bottomRow.elements.push(new t.blockRendering.RoundCorner(this.constants_,"right"))},t.blockRendering.RenderInfo.prototype.addInput_=function(e,o){this.isInline&&e.type==t.INPUT_VALUE?(o.elements.push(new t.blockRendering.InlineInput(this.constants_,e)),o.hasInlineInput=!0):e.type==t.NEXT_STATEMENT?(o.elements.push(new t.blockRendering.StatementInput(this.constants_,e)),o.hasStatement=!0):e.type==t.INPUT_VALUE?(o.elements.push(new t.blockRendering.ExternalValueInput(this.constants_,e)),o.hasExternalInput=!0):e.type==t.DUMMY_INPUT&&(o.minHeight=Math.max(o.minHeight,e.getSourceBlock()&&e.getSourceBlock().isShadow()?this.constants_.DUMMY_INPUT_SHADOW_MIN_HEIGHT:this.constants_.DUMMY_INPUT_MIN_HEIGHT),o.hasDummyInput=!0),null==o.align&&(o.align=e.align)},t.blockRendering.RenderInfo.prototype.shouldStartNewRow_=function(e,o){return!(!o||e.type!=t.NEXT_STATEMENT&&o.type!=t.NEXT_STATEMENT&&(e.type!=t.INPUT_VALUE&&e.type!=t.DUMMY_INPUT||this.isInline))},t.blockRendering.RenderInfo.prototype.addElemSpacing_=function(){for(var e,o=0;e=this.rows[o];o++){var i=e.elements;if(e.elements=[],e.startsWithElemSpacer()&&e.elements.push(new t.blockRendering.InRowSpacer(this.constants_,this.getInRowSpacing_(null,i[0]))),i.length){for(var n=0;n.blocklyPathLight,",e+" .blocklyInsertionMarker>.blocklyPathDark {","fill-opacity: "+this.INSERTION_MARKER_OPACITY+";","stroke: none;","}"])},t.geras.Highlighter=function(t){this.info_=t,this.inlineSteps_=this.steps_="",this.RTL_=this.info_.RTL,t=t.getRenderer(),this.constants_=t.getConstants(),this.highlightConstants_=t.getHighlightConstants(),this.highlightOffset_=this.highlightConstants_.OFFSET,this.outsideCornerPaths_=this.highlightConstants_.OUTSIDE_CORNER,this.insideCornerPaths_=this.highlightConstants_.INSIDE_CORNER,this.puzzleTabPaths_=this.highlightConstants_.PUZZLE_TAB,this.notchPaths_=this.highlightConstants_.NOTCH,this.startPaths_=this.highlightConstants_.START_HAT,this.jaggedTeethPaths_=this.highlightConstants_.JAGGED_TEETH},t.geras.Highlighter.prototype.getPath=function(){return this.steps_+"\n"+this.inlineSteps_},t.geras.Highlighter.prototype.drawTopCorner=function(e){this.steps_+=t.utils.svgPaths.moveBy(e.xPos,this.info_.startY);for(var o,i=0;o=e.elements[i];i++)t.blockRendering.Types.isLeftSquareCorner(o)?this.steps_+=this.highlightConstants_.START_POINT:t.blockRendering.Types.isLeftRoundedCorner(o)?this.steps_+=this.outsideCornerPaths_.topLeft(this.RTL_):t.blockRendering.Types.isPreviousConnection(o)?this.steps_+=this.notchPaths_.pathLeft:t.blockRendering.Types.isHat(o)?this.steps_+=this.startPaths_.path(this.RTL_):t.blockRendering.Types.isSpacer(o)&&0!=o.width&&(this.steps_+=t.utils.svgPaths.lineOnAxis("H",o.xPos+o.width-this.highlightOffset_));this.steps_+=t.utils.svgPaths.lineOnAxis("H",e.xPos+e.width-this.highlightOffset_)},t.geras.Highlighter.prototype.drawJaggedEdge_=function(e){this.info_.RTL&&(this.steps_+=this.jaggedTeethPaths_.pathLeft+t.utils.svgPaths.lineOnAxis("v",e.height-this.jaggedTeethPaths_.height-this.highlightOffset_))},t.geras.Highlighter.prototype.drawValueInput=function(e){var o=e.getLastInput();if(this.RTL_){var i=e.height-o.connectionHeight;this.steps_+=t.utils.svgPaths.moveTo(o.xPos+o.width-this.highlightOffset_,e.yPos)+this.puzzleTabPaths_.pathDown(this.RTL_)+t.utils.svgPaths.lineOnAxis("v",i)}else this.steps_+=t.utils.svgPaths.moveTo(o.xPos+o.width,e.yPos)+this.puzzleTabPaths_.pathDown(this.RTL_)},t.geras.Highlighter.prototype.drawStatementInput=function(e){var o=e.getLastInput();if(this.RTL_){var i=e.height-2*this.insideCornerPaths_.height;this.steps_+=t.utils.svgPaths.moveTo(o.xPos,e.yPos)+this.insideCornerPaths_.pathTop(this.RTL_)+t.utils.svgPaths.lineOnAxis("v",i)+this.insideCornerPaths_.pathBottom(this.RTL_)+t.utils.svgPaths.lineTo(e.width-o.xPos-this.insideCornerPaths_.width,0)}else this.steps_+=t.utils.svgPaths.moveTo(o.xPos,e.yPos+e.height)+this.insideCornerPaths_.pathBottom(this.RTL_)+t.utils.svgPaths.lineTo(e.width-o.xPos-this.insideCornerPaths_.width,0)},t.geras.Highlighter.prototype.drawRightSideRow=function(e){var o=e.xPos+e.width-this.highlightOffset_;e.followsStatement&&(this.steps_+=t.utils.svgPaths.lineOnAxis("H",o)),this.RTL_&&(this.steps_+=t.utils.svgPaths.lineOnAxis("H",o),e.height>this.highlightOffset_&&(this.steps_+=t.utils.svgPaths.lineOnAxis("V",e.yPos+e.height-this.highlightOffset_)))},t.geras.Highlighter.prototype.drawBottomRow=function(e){if(this.RTL_)this.steps_+=t.utils.svgPaths.lineOnAxis("V",e.baseline-this.highlightOffset_);else{var o=this.info_.bottomRow.elements[0];t.blockRendering.Types.isLeftSquareCorner(o)?this.steps_+=t.utils.svgPaths.moveTo(e.xPos+this.highlightOffset_,e.baseline-this.highlightOffset_):t.blockRendering.Types.isLeftRoundedCorner(o)&&(this.steps_+=t.utils.svgPaths.moveTo(e.xPos,e.baseline),this.steps_+=this.outsideCornerPaths_.bottomLeft())}},t.geras.Highlighter.prototype.drawLeft=function(){var e=this.info_.outputConnection;e&&(e=e.connectionOffsetY+e.height,this.RTL_?this.steps_+=t.utils.svgPaths.moveTo(this.info_.startX,e):(this.steps_+=t.utils.svgPaths.moveTo(this.info_.startX+this.highlightOffset_,this.info_.bottomRow.baseline-this.highlightOffset_),this.steps_+=t.utils.svgPaths.lineOnAxis("V",e)),this.steps_+=this.puzzleTabPaths_.pathUp(this.RTL_)),this.RTL_||(e=this.info_.topRow,t.blockRendering.Types.isLeftRoundedCorner(e.elements[0])?this.steps_+=t.utils.svgPaths.lineOnAxis("V",this.outsideCornerPaths_.height):this.steps_+=t.utils.svgPaths.lineOnAxis("V",e.capline+this.highlightOffset_))},t.geras.Highlighter.prototype.drawInlineInput=function(e){var o=this.highlightOffset_,i=e.xPos+e.connectionWidth,n=e.centerline-e.height/2,s=e.width-e.connectionWidth,r=n+o;this.RTL_?(n=e.connectionOffsetY-o,e=e.height-(e.connectionOffsetY+e.connectionHeight)+o,this.inlineSteps_+=t.utils.svgPaths.moveTo(i-o,r)+t.utils.svgPaths.lineOnAxis("v",n)+this.puzzleTabPaths_.pathDown(this.RTL_)+t.utils.svgPaths.lineOnAxis("v",e)+t.utils.svgPaths.lineOnAxis("h",s)):this.inlineSteps_+=t.utils.svgPaths.moveTo(e.xPos+e.width+o,r)+t.utils.svgPaths.lineOnAxis("v",e.height)+t.utils.svgPaths.lineOnAxis("h",-s)+t.utils.svgPaths.moveTo(i,n+e.connectionOffsetY)+this.puzzleTabPaths_.pathDown(this.RTL_)},t.geras.InlineInput=function(e,o){t.geras.InlineInput.superClass_.constructor.call(this,e,o),this.connectedBlock&&(this.width+=this.constants_.DARK_PATH_OFFSET,this.height+=this.constants_.DARK_PATH_OFFSET)},t.utils.object.inherits(t.geras.InlineInput,t.blockRendering.InlineInput),t.geras.StatementInput=function(e,o){t.geras.StatementInput.superClass_.constructor.call(this,e,o),this.connectedBlock&&(this.height+=this.constants_.DARK_PATH_OFFSET)},t.utils.object.inherits(t.geras.StatementInput,t.blockRendering.StatementInput),t.geras.RenderInfo=function(e,o){t.geras.RenderInfo.superClass_.constructor.call(this,e,o)},t.utils.object.inherits(t.geras.RenderInfo,t.blockRendering.RenderInfo),t.geras.RenderInfo.prototype.getRenderer=function(){return this.renderer_},t.geras.RenderInfo.prototype.populateBottomRow_=function(){t.geras.RenderInfo.superClass_.populateBottomRow_.call(this),this.block_.inputList.length&&this.block_.inputList[this.block_.inputList.length-1].type==t.NEXT_STATEMENT||(this.bottomRow.minHeight=this.constants_.MEDIUM_PADDING-this.constants_.DARK_PATH_OFFSET)},t.geras.RenderInfo.prototype.addInput_=function(e,o){this.isInline&&e.type==t.INPUT_VALUE?(o.elements.push(new t.geras.InlineInput(this.constants_,e)),o.hasInlineInput=!0):e.type==t.NEXT_STATEMENT?(o.elements.push(new t.geras.StatementInput(this.constants_,e)),o.hasStatement=!0):e.type==t.INPUT_VALUE?(o.elements.push(new t.blockRendering.ExternalValueInput(this.constants_,e)),o.hasExternalInput=!0):e.type==t.DUMMY_INPUT&&(o.minHeight=Math.max(o.minHeight,this.constants_.DUMMY_INPUT_MIN_HEIGHT),o.hasDummyInput=!0),this.isInline||null!=o.align||(o.align=e.align)},t.geras.RenderInfo.prototype.addElemSpacing_=function(){for(var e,o=!1,i=0;e=this.rows[i];i++)e.hasExternalInput&&(o=!0);for(i=0;e=this.rows[i];i++){var n=e.elements;if(e.elements=[],e.startsWithElemSpacer()&&e.elements.push(new t.blockRendering.InRowSpacer(this.constants_,this.getInRowSpacing_(null,n[0]))),n.length){for(var s=0;so?o:s,n=n?-1:1,e=(i?-1:1)*e/2,t.utils.svgPaths.lineTo(-n*s,e)+t.utils.svgPaths.lineTo(n*s,e)}var o=this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH;return{type:this.SHAPES.HEXAGONAL,isDynamic:!0,width:function(t){return(t/=2)>o?o:t},height:function(t){return t},connectionOffsetY:function(t){return t/2},connectionOffsetX:function(t){return-t},pathDown:function(t){return e(t,!1,!1)},pathUp:function(t){return e(t,!0,!1)},pathRightDown:function(t){return e(t,!1,!0)},pathRightUp:function(t){return e(t,!1,!0)}}},t.zelos.ConstantProvider.prototype.makeRounded=function(){function e(e,o,n){var s=e>i?e-i:0;return e=(e>i?i:e)/2,t.utils.svgPaths.arc("a","0 0,1",e,t.utils.svgPaths.point((o?-1:1)*e,(o?-1:1)*e))+t.utils.svgPaths.lineOnAxis("v",(n?1:-1)*s)+t.utils.svgPaths.arc("a","0 0,1",e,t.utils.svgPaths.point((o?1:-1)*e,(o?-1:1)*e))}var o=this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH,i=2*o;return{type:this.SHAPES.ROUND,isDynamic:!0,width:function(t){return(t/=2)>o?o:t},height:function(t){return t},connectionOffsetY:function(t){return t/2},connectionOffsetX:function(t){return-t},pathDown:function(t){return e(t,!1,!1)},pathUp:function(t){return e(t,!0,!1)},pathRightDown:function(t){return e(t,!1,!0)},pathRightUp:function(t){return e(t,!1,!0)}}},t.zelos.ConstantProvider.prototype.makeSquared=function(){function e(e,i,n){return e-=2*o,t.utils.svgPaths.arc("a","0 0,1",o,t.utils.svgPaths.point((i?-1:1)*o,(i?-1:1)*o))+t.utils.svgPaths.lineOnAxis("v",(n?1:-1)*e)+t.utils.svgPaths.arc("a","0 0,1",o,t.utils.svgPaths.point((i?1:-1)*o,(i?-1:1)*o))}var o=this.CORNER_RADIUS;return{type:this.SHAPES.SQUARE,isDynamic:!0,width:function(t){return o},height:function(t){return t},connectionOffsetY:function(t){return t/2},connectionOffsetX:function(t){return-t},pathDown:function(t){return e(t,!1,!1)},pathUp:function(t){return e(t,!0,!1)},pathRightDown:function(t){return e(t,!1,!0)},pathRightUp:function(t){return e(t,!1,!0)}}},t.zelos.ConstantProvider.prototype.shapeFor=function(e){var o=e.getCheck();switch(!o&&e.targetConnection&&(o=e.targetConnection.getCheck()),e.type){case t.INPUT_VALUE:case t.OUTPUT_VALUE:if(null!=(e=e.getSourceBlock().getOutputShape()))switch(e){case this.SHAPES.HEXAGONAL:return this.HEXAGONAL;case this.SHAPES.ROUND:return this.ROUNDED;case this.SHAPES.SQUARE:return this.SQUARED}return o&&-1!=o.indexOf("Boolean")?this.HEXAGONAL:(o&&-1!=o.indexOf("Number")||o&&o.indexOf("String"),this.ROUNDED);case t.PREVIOUS_STATEMENT:case t.NEXT_STATEMENT:return this.NOTCH;default:throw Error("Unknown type")}},t.zelos.ConstantProvider.prototype.makeNotch=function(){function e(e){return t.utils.svgPaths.curve("c",[t.utils.svgPaths.point(e*s/2,0),t.utils.svgPaths.point(e*s*3/4,a/2),t.utils.svgPaths.point(e*s,a)])+t.utils.svgPaths.line([t.utils.svgPaths.point(e*s,r)])+t.utils.svgPaths.curve("c",[t.utils.svgPaths.point(e*s/4,a/2),t.utils.svgPaths.point(e*s/2,a),t.utils.svgPaths.point(e*s,a)])+t.utils.svgPaths.lineOnAxis("h",e*n)+t.utils.svgPaths.curve("c",[t.utils.svgPaths.point(e*s/2,0),t.utils.svgPaths.point(e*s*3/4,-a/2),t.utils.svgPaths.point(e*s,-a)])+t.utils.svgPaths.line([t.utils.svgPaths.point(e*s,-r)])+t.utils.svgPaths.curve("c",[t.utils.svgPaths.point(e*s/4,-a/2),t.utils.svgPaths.point(e*s/2,-a),t.utils.svgPaths.point(e*s,-a)])}var o=this.NOTCH_WIDTH,i=this.NOTCH_HEIGHT,n=o/3,s=n/3,r=i/2,a=r/2,l=e(1),c=e(-1);return{type:this.SHAPES.NOTCH,width:o,height:i,pathLeft:l,pathRight:c}},t.zelos.ConstantProvider.prototype.makeInsideCorners=function(){var e=this.CORNER_RADIUS,o=t.utils.svgPaths.arc("a","0 0,0",e,t.utils.svgPaths.point(-e,e)),i=t.utils.svgPaths.arc("a","0 0,1",e,t.utils.svgPaths.point(-e,e));return{width:e,height:e,pathTop:o,pathBottom:t.utils.svgPaths.arc("a","0 0,0",e,t.utils.svgPaths.point(e,e)),rightWidth:e,rightHeight:e,pathTopRight:i,pathBottomRight:t.utils.svgPaths.arc("a","0 0,1",e,t.utils.svgPaths.point(e,e))}},t.zelos.ConstantProvider.prototype.generateSecondaryColour_=function(e){return t.utils.colour.blend("#000",e,.15)||e},t.zelos.ConstantProvider.prototype.generateTertiaryColour_=function(e){return t.utils.colour.blend("#000",e,.25)||e},t.zelos.ConstantProvider.prototype.createDom=function(e,o,i){t.zelos.ConstantProvider.superClass_.createDom.call(this,e,o,i),e=t.utils.dom.createSvgElement(t.utils.Svg.DEFS,{},e),o=t.utils.dom.createSvgElement(t.utils.Svg.FILTER,{id:"blocklySelectedGlowFilter"+this.randomIdentifier,height:"160%",width:"180%",y:"-30%",x:"-40%"},e),t.utils.dom.createSvgElement(t.utils.Svg.FEGAUSSIANBLUR,{in:"SourceGraphic",stdDeviation:this.SELECTED_GLOW_SIZE},o),i=t.utils.dom.createSvgElement(t.utils.Svg.FECOMPONENTTRANSFER,{result:"outBlur"},o),t.utils.dom.createSvgElement(t.utils.Svg.FEFUNCA,{type:"table",tableValues:"0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"},i),t.utils.dom.createSvgElement(t.utils.Svg.FEFLOOD,{"flood-color":this.SELECTED_GLOW_COLOUR,"flood-opacity":1,result:"outColor"},o),t.utils.dom.createSvgElement(t.utils.Svg.FECOMPOSITE,{in:"outColor",in2:"outBlur",operator:"in",result:"outGlow"},o),this.selectedGlowFilterId=o.id,this.selectedGlowFilter_=o,e=t.utils.dom.createSvgElement(t.utils.Svg.FILTER,{id:"blocklyReplacementGlowFilter"+this.randomIdentifier,height:"160%",width:"180%",y:"-30%",x:"-40%"},e),t.utils.dom.createSvgElement(t.utils.Svg.FEGAUSSIANBLUR,{in:"SourceGraphic",stdDeviation:this.REPLACEMENT_GLOW_SIZE},e),o=t.utils.dom.createSvgElement(t.utils.Svg.FECOMPONENTTRANSFER,{result:"outBlur"},e),t.utils.dom.createSvgElement(t.utils.Svg.FEFUNCA,{type:"table",tableValues:"0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"},o),t.utils.dom.createSvgElement(t.utils.Svg.FEFLOOD,{"flood-color":this.REPLACEMENT_GLOW_COLOUR,"flood-opacity":1,result:"outColor"},e),t.utils.dom.createSvgElement(t.utils.Svg.FECOMPOSITE,{in:"outColor",in2:"outBlur",operator:"in",result:"outGlow"},e),t.utils.dom.createSvgElement(t.utils.Svg.FECOMPOSITE,{in:"SourceGraphic",in2:"outGlow",operator:"over"},e),this.replacementGlowFilterId=e.id,this.replacementGlowFilter_=e},t.zelos.ConstantProvider.prototype.getCSS_=function(t){return[t+" .blocklyText,",t+" .blocklyFlyoutLabelText {","font: "+this.FIELD_TEXT_FONTWEIGHT+" "+this.FIELD_TEXT_FONTSIZE+"pt "+this.FIELD_TEXT_FONTFAMILY+";","}",t+" .blocklyText {","fill: #fff;","}",t+" .blocklyNonEditableText>rect:not(.blocklyDropdownRect),",t+" .blocklyEditableText>rect:not(.blocklyDropdownRect) {","fill: "+this.FIELD_BORDER_RECT_COLOUR+";","}",t+" .blocklyNonEditableText>text,",t+" .blocklyEditableText>text,",t+" .blocklyNonEditableText>g>text,",t+" .blocklyEditableText>g>text {","fill: #575E75;","}",t+" .blocklyFlyoutLabelText {","fill: #575E75;","}",t+" .blocklyText.blocklyBubbleText {","fill: #575E75;","}",t+" .blocklyDraggable:not(.blocklyDisabled)"," .blocklyEditableText:not(.editing):hover>rect,",t+" .blocklyDraggable:not(.blocklyDisabled)"," .blocklyEditableText:not(.editing):hover>.blocklyPath {","stroke: #fff;","stroke-width: 2;","}",t+" .blocklyHtmlInput {","font-family: "+this.FIELD_TEXT_FONTFAMILY+";","font-weight: "+this.FIELD_TEXT_FONTWEIGHT+";","color: #575E75;","}",t+" .blocklyDropdownText {","fill: #fff !important;","}",t+".blocklyWidgetDiv .goog-menuitem,",t+".blocklyDropDownDiv .goog-menuitem {","font-family: "+this.FIELD_TEXT_FONTFAMILY+";","}",t+".blocklyDropDownDiv .goog-menuitem-content {","color: #fff;","}",t+" .blocklyHighlightedConnectionPath {","stroke: "+this.SELECTED_GLOW_COLOUR+";","}",t+" .blocklyDisabled > .blocklyOutlinePath {","fill: url(#blocklyDisabledPattern"+this.randomIdentifier+")","}",t+" .blocklyInsertionMarker>.blocklyPath {","fill-opacity: "+this.INSERTION_MARKER_OPACITY+";","stroke: none;","}"]},t.zelos.TopRow=function(e){t.zelos.TopRow.superClass_.constructor.call(this,e)},t.utils.object.inherits(t.zelos.TopRow,t.blockRendering.TopRow),t.zelos.TopRow.prototype.endsWithElemSpacer=function(){return!1},t.zelos.TopRow.prototype.hasLeftSquareCorner=function(t){var e=(t.hat?"cap"===t.hat:this.constants_.ADD_START_HATS)&&!t.outputConnection&&!t.previousConnection;return!!t.outputConnection||e},t.zelos.TopRow.prototype.hasRightSquareCorner=function(t){return!!t.outputConnection&&!t.statementInputCount&&!t.nextConnection},t.zelos.BottomRow=function(e){t.zelos.BottomRow.superClass_.constructor.call(this,e)},t.utils.object.inherits(t.zelos.BottomRow,t.blockRendering.BottomRow),t.zelos.BottomRow.prototype.endsWithElemSpacer=function(){return!1},t.zelos.BottomRow.prototype.hasLeftSquareCorner=function(t){return!!t.outputConnection},t.zelos.BottomRow.prototype.hasRightSquareCorner=function(t){return!!t.outputConnection&&!t.statementInputCount&&!t.nextConnection},t.zelos.RightConnectionShape=function(e){t.zelos.RightConnectionShape.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.getType("RIGHT_CONNECTION"),this.width=this.height=0},t.utils.object.inherits(t.zelos.RightConnectionShape,t.blockRendering.Measurable),t.zelos.StatementInput=function(e,o){if(t.zelos.StatementInput.superClass_.constructor.call(this,e,o),this.connectedBlock){for(e=this.connectedBlock;e.getNextBlock();)e=e.getNextBlock();e.nextConnection||(this.height=this.connectedBlockHeight,this.connectedBottomNextConnection=!0)}},t.utils.object.inherits(t.zelos.StatementInput,t.blockRendering.StatementInput),t.zelos.RenderInfo=function(e,o){t.zelos.RenderInfo.superClass_.constructor.call(this,e,o),this.topRow=new t.zelos.TopRow(this.constants_),this.bottomRow=new t.zelos.BottomRow(this.constants_),this.isInline=!0,this.isMultiRow=!o.getInputsInline()||o.isCollapsed(),this.hasStatementInput=0=this.rows.length-1?!!this.bottomRow.hasNextConnection:!!r.precedesStatement,t.blockRendering.Types.isInputRow(s)&&s.hasStatement)s.measure(),o=s.width-s.getLastInput().width+e;else if(n&&(2==i||r)&&t.blockRendering.Types.isInputRow(s)&&!s.hasStatement){r=s.xPos,n=null;for(var a,l=0;a=s.elements[l];l++)t.blockRendering.Types.isSpacer(a)&&(n=a),!(n&&(t.blockRendering.Types.isField(a)||t.blockRendering.Types.isInput(a))&&ri?i:this.height/2)*(1-Math.sin(Math.acos((i-this.constants_.SMALL_PADDING)/i)));default:return 0}if(t.blockRendering.Types.isInlineInput(e)){var s=e.connectedBlock;return e=s?s.pathObject.outputShapeType:e.shape.type,s&&s.outputConnection&&(s.statementInputCount||s.nextConnection)||i==n.SHAPES.HEXAGONAL&&i!=e?0:o-this.constants_.SHAPE_IN_SHAPE_PADDING[i][e]}return t.blockRendering.Types.isField(e)?i==n.SHAPES.ROUND&&e.field instanceof t.FieldTextInput?o-2.75*n.GRID_UNIT:o-this.constants_.SHAPE_IN_SHAPE_PADDING[i][0]:t.blockRendering.Types.isIcon(e)?this.constants_.SMALL_PADDING:0},t.zelos.RenderInfo.prototype.finalizeVerticalAlignment_=function(){if(!this.outputConnection)for(var e=2;e=this.rows.length-1?!!this.bottomRow.hasNextConnection:!!n.precedesStatement;if(s?this.topRow.hasPreviousConnection:o.followsStatement){var a=3==i.elements.length&&(i.elements[1].field instanceof t.FieldLabel||i.elements[1].field instanceof t.FieldImage);if(!s&&a)o.height-=this.constants_.SMALL_PADDING,n.height-=this.constants_.SMALL_PADDING,i.height-=this.constants_.MEDIUM_PADDING;else if(s||r){if(r){for(s=!1,r=0;a=i.elements[r];r++)if(t.blockRendering.Types.isInlineInput(a)&&a.connectedBlock&&!a.connectedBlock.isShadow()&&40<=a.connectedBlock.getHeightWidth().height){s=!0;break}s&&(o.height-=this.constants_.SMALL_PADDING,n.height-=this.constants_.SMALL_PADDING)}}else o.height+=this.constants_.SMALL_PADDING}}},t.zelos.RenderInfo.prototype.finalize_=function(){this.finalizeOutputConnection_(),this.finalizeHorizontalAlignment_(),this.finalizeVerticalAlignment_(),t.zelos.RenderInfo.superClass_.finalize_.call(this),this.rightSide&&(this.widthWithChildren+=this.rightSide.width)},t.zelos.Drawer=function(e,o){t.zelos.Drawer.superClass_.constructor.call(this,e,o)},t.utils.object.inherits(t.zelos.Drawer,t.blockRendering.Drawer),t.zelos.Drawer.prototype.draw=function(){var e=this.block_.pathObject;e.beginDrawing(),this.hideHiddenIcons_(),this.drawOutline_(),this.drawInternals_(),e.setPath(this.outlinePath_+"\n"+this.inlinePath_),this.info_.RTL&&e.flipRTL(),t.blockRendering.useDebugger&&this.block_.renderingDebugger.drawDebug(this.block_,this.info_),this.recordSizeOnBlock_(),this.info_.outputConnection&&(e.outputShapeType=this.info_.outputConnection.shape.type),e.endDrawing()},t.zelos.Drawer.prototype.drawOutline_=function(){this.info_.outputConnection&&this.info_.outputConnection.isDynamicShape&&!this.info_.hasStatementInput&&!this.info_.bottomRow.hasNextConnection?(this.drawFlatTop_(),this.drawRightDynamicConnection_(),this.drawFlatBottom_(),this.drawLeftDynamicConnection_()):t.zelos.Drawer.superClass_.drawOutline_.call(this)},t.zelos.Drawer.prototype.drawLeft_=function(){this.info_.outputConnection&&this.info_.outputConnection.isDynamicShape?this.drawLeftDynamicConnection_():t.zelos.Drawer.superClass_.drawLeft_.call(this)},t.zelos.Drawer.prototype.drawRightSideRow_=function(e){if(!(0>=e.height))if(e.precedesStatement||e.followsStatement){var o=this.constants_.INSIDE_CORNERS.rightHeight;o=e.height-(e.precedesStatement?o:0),this.outlinePath_+=(e.followsStatement?this.constants_.INSIDE_CORNERS.pathBottomRight:"")+(0=51&&/native code/.test(U))return!1;var t=U.resolve(1),e=function(t){t((function(){}),(function(){}))};return(t.constructor={})[w]=e,!(t.then((function(){}))instanceof e)})),j=z||!S((function(t){U.all(t).catch((function(){}))})),Z=function(t){var e;return!(!T(t)||"function"!=typeof(e=t.then))&&e},q=function(t,e,o){if(!e.notified){e.notified=!0;var i=e.reactions;b((function(){for(var n=e.value,s=1==e.state,r=0;i.length>r;){var a,l,c,u=i[r++],h=s?u.ok:u.fail,p=u.resolve,_=u.reject,d=u.domain;try{h?(s||(2===e.rejection&&et(t,e),e.rejection=1),!0===h?a=n:(d&&d.enter(),a=h(n),d&&(d.exit(),c=!0)),a===u.promise?_(H("Promise-chain cycle")):(l=Z(a))?l.call(a,p,_):p(a)):_(n)}catch(t){d&&!c&&d.exit(),_(t)}}e.reactions=[],e.notified=!1,o&&!e.rejection&&$(t,e)}))}},Q=function(t,e,o){var i,n;J?((i=G.createEvent("Event")).promise=e,i.reason=o,i.initEvent(t,!1,!0),c.dispatchEvent(i)):i={promise:e,reason:o},(n=c["on"+t])?n(i):"unhandledrejection"===t&&C("Unhandled promise rejection",o)},$=function(t,e){R.call(c,(function(){var o,i=e.value;if(tt(e)&&(o=N((function(){K?W.emit("unhandledRejection",i,t):Q("unhandledrejection",t,i)})),e.rejection=K||tt(e)?2:1,o.error))throw o.value}))},tt=function(t){return 1!==t.rejection&&!t.parent},et=function(t,e){R.call(c,(function(){K?W.emit("rejectionHandled",t):Q("rejectionhandled",t,e.value)}))},ot=function(t,e,o,i){return function(n){t(e,o,n,i)}},it=function(t,e,o,i){e.done||(e.done=!0,i&&(e=i),e.value=o,e.state=2,q(t,e,!0))},nt=function(t,e,o,i){if(!e.done){e.done=!0,i&&(e=i);try{if(t===o)throw H("Promise can't be resolved itself");var n=Z(o);n?b((function(){var i={done:!1};try{n.call(o,ot(nt,t,i,e),ot(it,t,i,e))}catch(o){it(t,i,o,e)}})):(e.value=o,e.state=1,q(t,e,!1))}catch(o){it(t,{done:!1},o,e)}}};z&&(U=function(t){E(this,U,B),f(t),i.call(this);var e=P(this);try{t(ot(nt,this,e),ot(it,this,e))}catch(t){it(this,e,t)}},(i=function(t){x(this,{type:B,done:!1,notified:!1,parent:!1,reactions:[],rejection:!1,state:0,value:void 0})}).prototype=_(U.prototype,{then:function(t,e){var o=F(this),i=X(I(this,U));return i.ok="function"!=typeof t||t,i.fail="function"==typeof e&&e,i.domain=K?W.domain:void 0,o.parent=!0,o.reactions.push(i),0!=o.state&&q(this,o,!1),i.promise},catch:function(t){return this.then(void 0,t)}}),n=function(){var t=new i,e=P(t);this.promise=t,this.resolve=ot(nt,t,e),this.reject=ot(it,t,e)},k.f=X=function(t){return t===U||t===s?new n(t):Y(t)},l||"function"!=typeof h||(r=h.prototype.then,p(h.prototype,"then",(function(t,e){var o=this;return new U((function(t,e){r.call(o,t,e)})).then(t,e)}),{unsafe:!0}),"function"==typeof V&&a({global:!0,enumerable:!0,forced:!0},{fetch:function(t){return O(U,V.apply(c,arguments))}}))),a({global:!0,wrap:!0,forced:z},{Promise:U}),d(U,B,!1,!0),g(B),s=u(B),a({target:B,stat:!0,forced:z},{reject:function(t){var e=X(this);return e.reject.call(void 0,t),e.promise}}),a({target:B,stat:!0,forced:l||z},{resolve:function(t){return O(l&&this===s?U:this,t)}}),a({target:B,stat:!0,forced:j},{all:function(t){var e=this,o=X(e),i=o.resolve,n=o.reject,s=N((function(){var o=f(e.resolve),s=[],r=0,a=1;y(t,(function(t){var l=r++,c=!1;s.push(void 0),a++,o.call(e,t).then((function(t){c||(c=!0,s[l]=t,--a||i(s))}),n)})),--a||i(s)}));return s.error&&n(s.value),o.promise},race:function(t){var e=this,o=X(e),i=o.reject,n=N((function(){var n=f(e.resolve);y(t,(function(t){n.call(e,t).then(o.resolve,i)}))}));return n.error&&i(n.value),o.promise}})},function(t,e,o){"use strict";var i={}.propertyIsEnumerable,n=Object.getOwnPropertyDescriptor,s=n&&!i.call({1:2},1);e.f=s?function(t){var e=n(this,t);return!!e&&e.enumerable}:i},function(t,e,o){var i=o(4),n=o(11),s="".split;t.exports=i((function(){return!Object("z").propertyIsEnumerable(0)}))?function(t){return"String"==n(t)?s.call(t,""):Object(t)}:Object},function(t,e,o){var i=o(8);t.exports=function(t,e){if(!i(t))return t;var o,n;if(e&&"function"==typeof(o=t.toString)&&!i(n=o.call(t)))return n;if("function"==typeof(o=t.valueOf)&&!i(n=o.call(t)))return n;if(!e&&"function"==typeof(o=t.toString)&&!i(n=o.call(t)))return n;throw TypeError("Can't convert object to primitive value")}},function(t,e,o){var i=o(10),n=o(4),s=o(26);t.exports=!i&&!n((function(){return 7!=Object.defineProperty(s("div"),"a",{get:function(){return 7}}).a}))},function(t,e,o){var i=o(1),n=o(27),s=i["__core-js_shared__"]||n("__core-js_shared__",{});t.exports=s},function(t,e,o){var i=o(14),n=o(45);(t.exports=function(t,e){return n[t]||(n[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.6.5",mode:i?"pure":"global",copyright:"© 2020 Denis Pushkarev (zloirock.ru)"})},function(t,e){var o=0,i=Math.random();t.exports=function(t){return"Symbol("+String(void 0===t?"":t)+")_"+(++o+i).toString(36)}},function(t,e,o){var i=o(6),n=o(20),s=o(78).indexOf,r=o(31);t.exports=function(t,e){var o,a=n(t),l=0,c=[];for(o in a)!i(r,o)&&i(a,o)&&c.push(o);for(;e.length>l;)i(a,o=e[l++])&&(~s(c,o)||c.push(o));return c}},function(t,e){e.f=Object.getOwnPropertySymbols},function(t,e,o){var i=o(4),n=/#|\.prototype\./,s=function(t,e){var o=a[r(t)];return o==c||o!=l&&("function"==typeof e?i(e):!!e)},r=s.normalize=function(t){return String(t).replace(n,".").toLowerCase()},a=s.data={},l=s.NATIVE="N",c=s.POLYFILL="P";t.exports=s},function(t,e,o){var i=o(4);t.exports=!!Object.getOwnPropertySymbols&&!i((function(){return!String(Symbol())}))},function(t,e,o){var i=o(22);t.exports=function(t,e,o){if(i(t),void 0===e)return t;switch(o){case 0:return function(){return t.call(e)};case 1:return function(o){return t.call(e,o)};case 2:return function(o,i){return t.call(e,o,i)};case 3:return function(o,i,n){return t.call(e,o,i,n)}}return function(){return t.apply(e,arguments)}}},function(t,e,o){var i,n,s,r=o(1),a=o(4),l=o(11),c=o(52),u=o(54),h=o(26),p=o(55),_=r.location,d=r.setImmediate,g=r.clearImmediate,T=r.process,f=r.MessageChannel,E=r.Dispatch,m=0,v={},y=function(t){if(v.hasOwnProperty(t)){var e=v[t];delete v[t],e()}},S=function(t){return function(){y(t)}},I=function(t){y(t.data)},R=function(t){r.postMessage(t+"",_.protocol+"//"+_.host)};d&&g||(d=function(t){for(var e=[],o=1;arguments.length>o;)e.push(arguments[o++]);return v[++m]=function(){("function"==typeof t?t:Function(t)).apply(void 0,e)},i(m),m},g=function(t){delete v[t]},"process"==l(T)?i=function(t){T.nextTick(S(t))}:E&&E.now?i=function(t){E.now(S(t))}:f&&!p?(s=(n=new f).port2,n.port1.onmessage=I,i=c(s.postMessage,s,1)):!r.addEventListener||"function"!=typeof postMessage||r.importScripts||a(R)||"file:"===_.protocol?i="onreadystatechange"in h("script")?function(t){u.appendChild(h("script")).onreadystatechange=function(){u.removeChild(this),y(t)}}:function(t){setTimeout(S(t),0)}:(i=R,r.addEventListener("message",I,!1))),t.exports={set:d,clear:g}},function(t,e,o){var i=o(17);t.exports=i("document","documentElement")},function(t,e,o){var i=o(56);t.exports=/(iphone|ipod|ipad).*applewebkit/i.test(i)},function(t,e,o){var i=o(17);t.exports=i("navigator","userAgent")||""},function(t,e,o){"use strict";var i=o(22),n=function(t){var e,o;this.promise=new t((function(t,i){if(void 0!==e||void 0!==o)throw TypeError("Bad Promise constructor");e=t,o=i})),this.resolve=i(e),this.reject=i(o)};t.exports.f=function(t){return new n(t)}},function(t,e,o){"use strict";o(98);var i=o(13),n=o(4),s=o(2),r=o(34),a=o(9),l=s("species"),c=!n((function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$")})),u="$0"==="a".replace(/./,"$0"),h=s("replace"),p=!!/./[h]&&""===/./[h]("a","$0"),_=!n((function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var o="ab".split(t);return 2!==o.length||"a"!==o[0]||"b"!==o[1]}));t.exports=function(t,e,o,h){var d=s(t),g=!n((function(){var e={};return e[d]=function(){return 7},7!=""[t](e)})),T=g&&!n((function(){var e=!1,o=/a/;return"split"===t&&((o={}).constructor={},o.constructor[l]=function(){return o},o.flags="",o[d]=/./[d]),o.exec=function(){return e=!0,null},o[d](""),!e}));if(!g||!T||"replace"===t&&(!c||!u||p)||"split"===t&&!_){var f=/./[d],E=o(d,""[t],(function(t,e,o,i,n){return e.exec===r?g&&!n?{done:!0,value:f.call(e,o,i)}:{done:!0,value:t.call(o,e,i)}:{done:!1}}),{REPLACE_KEEPS_$0:u,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:p}),m=E[0],v=E[1];i(String.prototype,t,m),i(RegExp.prototype,d,2==e?function(t,e){return v.call(t,this,e)}:function(t){return v.call(t,this)})}h&&a(RegExp.prototype[d],"sham",!0)}},function(t,e,o){"use strict";var i=o(3);t.exports=function(){var t=i(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.dotAll&&(e+="s"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},function(t,e,o){"use strict";var i=o(100).charAt;t.exports=function(t,e,o){return e+(o?i(t,e).length:1)}},function(t,e,o){var i=o(11),n=o(34);t.exports=function(t,e){var o=t.exec;if("function"==typeof o){var s=o.call(t,e);if("object"!=typeof s)throw TypeError("RegExp exec method returned something other than an Object or null");return s}if("RegExp"!==i(t))throw TypeError("RegExp#exec called on incompatible receiver");return n.call(t,e)}},function(t,e,o){"use strict";var i,n=o(7),s=o(16).f,r=o(15),a=o(36),l=o(5),c=o(37),u=o(14),h="".startsWith,p=Math.min,_=c("startsWith");n({target:"String",proto:!0,forced:!!(u||_||(i=s(String.prototype,"startsWith"),!i||i.writable))&&!_},{startsWith:function(t){var e=String(l(this));a(t);var o=r(p(arguments.length>1?arguments[1]:void 0,e.length)),i=String(t);return h?h.call(e,i,o):e.slice(o,o+i.length)===i}})},function(t,e,o){var i,n=o(3),s=o(105),r=o(32),a=o(31),l=o(54),c=o(26),u=o(30),h=u("IE_PROTO"),p=function(){},_=function(t){return" + + + + + diff --git a/catroid/src/main/assets/catblocks/main.css b/catroid/src/main/assets/catblocks/main.css new file mode 100644 index 00000000000..9b34d40f6a8 --- /dev/null +++ b/catroid/src/main/assets/catblocks/main.css @@ -0,0 +1,52 @@ +.blocklyText { + fill: #fff; + font-family: 'Helvetica Neue', 'Segoe UI', Helvetica, sans-serif; + font-size: 12pt; + font-weight: bold; +} + +.blocklyNonEditableText > rect:not(.blocklyDropdownRect), +.blocklyEditableText > rect:not(.blocklyDropdownRect) { + fill: #fff; +} + +.blocklyNonEditableText > text, +.blocklyEditableText > text, +.blocklyNonEditableText > g > text, +.blocklyEditableText > g > text { + fill: #575e75; +} + +.blocklyDropdownText { + fill: #fff !important; +} + +.search { + border: none; +} + +#formulaPopupContent { + word-wrap: break-word; +} + +.catblockls-blockly-invisible > .blocklyPath { + fill-opacity: 0; + stroke-opacity: 0; +} + +html, +body { + height: 100vh; + width: 100%; +} + +#catroid-catblocks-container { + height: 100vh; + width: 100%; +} + +#catroid-catblocks-container.blocklySvg { + height: 100vh; + width: 100%; +} + diff --git a/catroid/src/main/assets/catblocks/media/1x1.gif b/catroid/src/main/assets/catblocks/media/1x1.gif new file mode 100644 index 00000000000..3085511236c Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/1x1.gif differ diff --git a/catroid/src/main/assets/catblocks/media/click.mp3 b/catroid/src/main/assets/catblocks/media/click.mp3 new file mode 100644 index 00000000000..4534b0ddca7 Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/click.mp3 differ diff --git a/catroid/src/main/assets/catblocks/media/click.ogg b/catroid/src/main/assets/catblocks/media/click.ogg new file mode 100644 index 00000000000..e8ae42a6106 Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/click.ogg differ diff --git a/catroid/src/main/assets/catblocks/media/click.wav b/catroid/src/main/assets/catblocks/media/click.wav new file mode 100644 index 00000000000..41a50cd76f5 Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/click.wav differ diff --git a/catroid/src/main/assets/catblocks/media/delete.mp3 b/catroid/src/main/assets/catblocks/media/delete.mp3 new file mode 100644 index 00000000000..442bd9c1f4c Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/delete.mp3 differ diff --git a/catroid/src/main/assets/catblocks/media/delete.ogg b/catroid/src/main/assets/catblocks/media/delete.ogg new file mode 100644 index 00000000000..67f84ac19a0 Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/delete.ogg differ diff --git a/catroid/src/main/assets/catblocks/media/delete.wav b/catroid/src/main/assets/catblocks/media/delete.wav new file mode 100644 index 00000000000..18debcf96d6 Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/delete.wav differ diff --git a/catroid/src/main/assets/catblocks/media/disconnect.mp3 b/catroid/src/main/assets/catblocks/media/disconnect.mp3 new file mode 100644 index 00000000000..8cfaff6c062 Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/disconnect.mp3 differ diff --git a/catroid/src/main/assets/catblocks/media/disconnect.ogg b/catroid/src/main/assets/catblocks/media/disconnect.ogg new file mode 100644 index 00000000000..467b527b4d0 Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/disconnect.ogg differ diff --git a/catroid/src/main/assets/catblocks/media/disconnect.wav b/catroid/src/main/assets/catblocks/media/disconnect.wav new file mode 100644 index 00000000000..af5c25447ca Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/disconnect.wav differ diff --git a/catroid/src/main/assets/catblocks/media/dropdown-arrow.svg b/catroid/src/main/assets/catblocks/media/dropdown-arrow.svg new file mode 100644 index 00000000000..4e6ce19ec0f --- /dev/null +++ b/catroid/src/main/assets/catblocks/media/dropdown-arrow.svg @@ -0,0 +1 @@ +dropdown-arrow \ No newline at end of file diff --git a/catroid/src/main/assets/catblocks/media/handclosed.cur b/catroid/src/main/assets/catblocks/media/handclosed.cur new file mode 100644 index 00000000000..4851755a169 Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/handclosed.cur differ diff --git a/catroid/src/main/assets/catblocks/media/handdelete.cur b/catroid/src/main/assets/catblocks/media/handdelete.cur new file mode 100644 index 00000000000..170320fc281 Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/handdelete.cur differ diff --git a/catroid/src/main/assets/catblocks/media/handopen.cur b/catroid/src/main/assets/catblocks/media/handopen.cur new file mode 100644 index 00000000000..da44588b2fa Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/handopen.cur differ diff --git a/catroid/src/main/assets/catblocks/media/info_icon.svg b/catroid/src/main/assets/catblocks/media/info_icon.svg new file mode 100644 index 00000000000..99ebf9df86d --- /dev/null +++ b/catroid/src/main/assets/catblocks/media/info_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/catroid/src/main/assets/catblocks/media/pilcrow.png b/catroid/src/main/assets/catblocks/media/pilcrow.png new file mode 100644 index 00000000000..f224c35868a Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/pilcrow.png differ diff --git a/catroid/src/main/assets/catblocks/media/quote0.png b/catroid/src/main/assets/catblocks/media/quote0.png new file mode 100644 index 00000000000..c7820d6077e Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/quote0.png differ diff --git a/catroid/src/main/assets/catblocks/media/quote1.png b/catroid/src/main/assets/catblocks/media/quote1.png new file mode 100644 index 00000000000..826583e0ad7 Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/quote1.png differ diff --git a/catroid/src/main/assets/catblocks/media/repeat.svg b/catroid/src/main/assets/catblocks/media/repeat.svg new file mode 100644 index 00000000000..e51234e7119 --- /dev/null +++ b/catroid/src/main/assets/catblocks/media/repeat.svg @@ -0,0 +1,18 @@ + + + + +repeat + + + diff --git a/catroid/src/main/assets/catblocks/media/sprites.png b/catroid/src/main/assets/catblocks/media/sprites.png new file mode 100644 index 00000000000..20aadb6c4c3 Binary files /dev/null and b/catroid/src/main/assets/catblocks/media/sprites.png differ diff --git a/catroid/src/main/assets/catblocks/media/sprites.svg b/catroid/src/main/assets/catblocks/media/sprites.svg new file mode 100644 index 00000000000..3f09ef3a4d6 --- /dev/null +++ b/catroid/src/main/assets/catblocks/media/sprites.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/catroid/src/main/java/org/catrobat/catroid/CatroidApplication.java b/catroid/src/main/java/org/catrobat/catroid/CatroidApplication.java index 5f26f4b543f..c02e2d9d33b 100644 --- a/catroid/src/main/java/org/catrobat/catroid/CatroidApplication.java +++ b/catroid/src/main/java/org/catrobat/catroid/CatroidApplication.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -23,7 +23,6 @@ package org.catrobat.catroid; import android.annotation.TargetApi; -import android.app.Activity; import android.app.Application; import android.content.Context; import android.os.Build; @@ -33,38 +32,23 @@ import com.google.android.gms.analytics.GoogleAnalytics; import com.google.android.gms.analytics.Tracker; -import org.catrobat.catroid.dagger.AppComponent; -import org.catrobat.catroid.dagger.CatroidModule; -import org.catrobat.catroid.dagger.DaggerAppComponent; +import org.catrobat.catroid.koin.CatroidKoinHelperKt; import org.catrobat.catroid.utils.Utils; import java.util.Locale; -import javax.inject.Inject; - import androidx.multidex.MultiDex; -import dagger.android.AndroidInjector; -import dagger.android.DispatchingAndroidInjector; -import dagger.android.HasActivityInjector; -public class CatroidApplication extends Application implements HasActivityInjector { +public class CatroidApplication extends Application { private static final String TAG = CatroidApplication.class.getSimpleName(); private static Context context; public static String defaultSystemLanguage; - public static final String OS_ARCH = System.getProperty("os.arch"); - public static boolean parrotLibrariesLoaded = false; - public static boolean parrotJSLibrariesLoaded = false; - private static GoogleAnalytics googleAnalytics; private static Tracker googleTracker; - @Inject - DispatchingAndroidInjector dispatchingActivityInjector; - protected AppComponent appComponents; - @TargetApi(29) @Override public void onCreate() { @@ -83,9 +67,7 @@ public void onCreate() { context = getApplicationContext(); - createApplicationComponents(); - appComponents.initializeEagerSingletons(); - appComponents.inject(this); + CatroidKoinHelperKt.start(this, CatroidKoinHelperKt.getMyModules()); defaultSystemLanguage = Locale.getDefault().toLanguageTag(); @@ -93,17 +75,6 @@ public void onCreate() { googleAnalytics.setDryRun(BuildConfig.DEBUG); } - protected void createApplicationComponents() { - appComponents = DaggerAppComponent.builder() - .catroidModule(new CatroidModule(this)) - .build(); - } - - @Override - public AndroidInjector activityInjector() { - return dispatchingActivityInjector; - } - @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); @@ -118,71 +89,6 @@ public synchronized Tracker getDefaultTracker() { return googleTracker; } - @SuppressWarnings("PMD.AvoidUsingNativeCode") - public static synchronized boolean loadNativeLibs() { - if (parrotLibrariesLoaded) { - return true; - } - - try { - System.loadLibrary("avutil"); - System.loadLibrary("swscale"); - System.loadLibrary("avcodec"); - System.loadLibrary("avfilter"); - System.loadLibrary("avformat"); - System.loadLibrary("avdevice"); - System.loadLibrary("adfreeflight"); - parrotLibrariesLoaded = true; - } catch (UnsatisfiedLinkError e) { - Log.e(TAG, Log.getStackTraceString(e)); - parrotLibrariesLoaded = false; - } - return parrotLibrariesLoaded; - } - - @SuppressWarnings("PMD.AvoidUsingNativeCode") - public static synchronized boolean loadJumpingSumoSDKLib() { - if (parrotJSLibrariesLoaded) { - return true; - } - - try { - System.loadLibrary("curl"); - System.loadLibrary("json"); - System.loadLibrary("arsal"); - System.loadLibrary("arsal_android"); - System.loadLibrary("arnetworkal"); - System.loadLibrary("arnetworkal_android"); - System.loadLibrary("arnetwork"); - System.loadLibrary("arnetwork_android"); - System.loadLibrary("arcommands"); - System.loadLibrary("arcommands_android"); - System.loadLibrary("arstream"); - System.loadLibrary("arstream_android"); - System.loadLibrary("arstream2"); - System.loadLibrary("arstream2_android"); - System.loadLibrary("ardiscovery"); - System.loadLibrary("ardiscovery_android"); - System.loadLibrary("arutils"); - System.loadLibrary("arutils_android"); - System.loadLibrary("ardatatransfer"); - System.loadLibrary("ardatatransfer_android"); - System.loadLibrary("armedia"); - System.loadLibrary("armedia_android"); - System.loadLibrary("arupdater"); - System.loadLibrary("arupdater_android"); - System.loadLibrary("armavlink"); - System.loadLibrary("armavlink_android"); - System.loadLibrary("arcontroller"); - System.loadLibrary("arcontroller_android"); - parrotJSLibrariesLoaded = true; - } catch (UnsatisfiedLinkError e) { - Log.e(TAG, Log.getStackTraceString(e)); - parrotJSLibrariesLoaded = false; - } - return parrotJSLibrariesLoaded; - } - public static Context getAppContext() { return CatroidApplication.context; } diff --git a/catroid/src/main/java/org/catrobat/catroid/ProjectManager.java b/catroid/src/main/java/org/catrobat/catroid/ProjectManager.java index d9da1605f13..360dadd7baa 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ProjectManager.java +++ b/catroid/src/main/java/org/catrobat/catroid/ProjectManager.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -41,8 +41,9 @@ import org.catrobat.catroid.content.bricks.ArduinoSendPWMValueBrick; import org.catrobat.catroid.content.bricks.Brick; import org.catrobat.catroid.content.bricks.FormulaBrick; +import org.catrobat.catroid.content.bricks.SetBackgroundByIndexAndWaitBrick; +import org.catrobat.catroid.content.bricks.SetBackgroundByIndexBrick; import org.catrobat.catroid.content.bricks.SetPenColorBrick; -import org.catrobat.catroid.dagger.EagerSingleton; import org.catrobat.catroid.exceptions.CompatibilityProjectException; import org.catrobat.catroid.exceptions.LoadingProjectException; import org.catrobat.catroid.exceptions.OutdatedVersionProjectException; @@ -66,7 +67,7 @@ import static org.catrobat.catroid.common.Constants.CURRENT_CATROBAT_LANGUAGE_VERSION; import static org.catrobat.catroid.common.Constants.PERMISSIONS_FILE_NAME; -public final class ProjectManager implements EagerSingleton { +public final class ProjectManager { private static ProjectManager instance; private static final String TAG = ProjectManager.class.getSimpleName(); @@ -84,17 +85,16 @@ public Context getApplicationContext() { } public ProjectManager(Context applicationContext) { - if (instance != null) { - throw new RuntimeException("ProjectManager should be instantiated only once"); - } this.applicationContext = applicationContext; - instance = this; + if (instance == null) { + instance = this; + } } /** * Replaced with dependency injection * - * @deprecated use dependency injection with Dagger instead. + * @deprecated use dependency injection with koin instead. */ @Deprecated public static ProjectManager getInstance() { @@ -154,6 +154,9 @@ public void loadProject(File projectDir, Context context) throws ProjectExceptio if (project.getCatrobatLanguageVersion() <= 0.99992) { removePermissionsFile(project); } + if (project.getCatrobatLanguageVersion() <= 0.9999995) { + updateBackgroundIndexTo9999995(project); + } project.setCatrobatLanguageVersion(CURRENT_CATROBAT_LANGUAGE_VERSION); localizeBackgroundSprites(project, context.getString(R.string.background)); @@ -168,10 +171,6 @@ public void loadProject(File projectDir, Context context) throws ProjectExceptio SettingsFragment.setPhiroSharedPreferenceEnabled(context, true); } - if (resourcesSet.contains(Brick.JUMPING_SUMO)) { - SettingsFragment.setJumpingSumoSharedPreferenceEnabled(context, true); - } - if (resourcesSet.contains(Brick.BLUETOOTH_SENSORS_ARDUINO)) { SettingsFragment.setArduinoSharedPreferenceEnabled(context, true); } @@ -237,7 +236,7 @@ private void localizeBackgroundSprites(Project project, String localizedBackgrou for (Scene scene : project.getSceneList()) { if (!scene.getSpriteList().isEmpty()) { Sprite background = scene.getSpriteList().get(0); - background.setName(localizedBackgroundName); + background.renameSpriteAndUpdateCollisionFormulas(localizedBackgroundName, scene); background.look.setZIndex(0); } } @@ -381,6 +380,27 @@ public static void updateCollisionScriptsTo996(Project project) { } } + @VisibleForTesting + public static void updateBackgroundIndexTo9999995(Project project) { + for (Scene scene : project.getSceneList()) { + for (Sprite sprite : scene.getSpriteList()) { + for (Script script : sprite.getScriptList()) { + for (Brick brick : script.getBrickList()) { + if (brick instanceof SetBackgroundByIndexBrick) { + FormulaBrick formulaBrick = (FormulaBrick) brick; + formulaBrick.replaceFormulaBrickField(Brick.BrickField.LOOK_INDEX, + Brick.BrickField.BACKGROUND_INDEX); + } else if (brick instanceof SetBackgroundByIndexAndWaitBrick) { + FormulaBrick formulaBrick = (FormulaBrick) brick; + formulaBrick.replaceFormulaBrickField(Brick.BrickField.LOOK_INDEX, + Brick.BrickField.BACKGROUND_WAIT_INDEX); + } + } + } + } + } + } + @VisibleForTesting public static void updateScriptsToTreeStructure(Project project) { for (Scene scene : project.getSceneList()) { @@ -517,6 +537,21 @@ public void setCurrentSprite(Sprite sprite) { currentSprite = sprite; } + public boolean setCurrentSceneAndSprite(String sceneName, String spriteName) { + for (Scene scene : project.getSceneList()) { + if (scene.getName().equals(sceneName)) { + setCurrentlyEditedScene(scene); + for (Sprite sprite : scene.getSpriteList()) { + if (sprite.getName().equals(spriteName)) { + currentSprite = sprite; + return true; + } + } + } + } + return false; + } + public void setCurrentlyEditedScene(Scene scene) { currentlyEditedScene = scene; currentlyPlayingScene = scene; diff --git a/catroid/src/main/java/org/catrobat/catroid/camera/CameraManager.kt b/catroid/src/main/java/org/catrobat/catroid/camera/CameraManager.kt index c984dd2f356..a1454c849d8 100644 --- a/catroid/src/main/java/org/catrobat/catroid/camera/CameraManager.kt +++ b/catroid/src/main/java/org/catrobat/catroid/camera/CameraManager.kt @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -46,7 +46,7 @@ import java.util.concurrent.Executors class CameraManager(private val stageActivity: StageActivity) : LifecycleOwner { private val cameraProvider = ProcessCameraProvider.getInstance(stageActivity).get() private val lifecycle = LifecycleRegistry(this) - private val previewView = PreviewView(stageActivity).apply { + val previewView = PreviewView(stageActivity).apply { visibility = View.INVISIBLE } @@ -64,10 +64,7 @@ class CameraManager(private val stageActivity: StageActivity) : LifecycleOwner { var previewVisible = false private set - var faceDetectionOn = false - private set - - var textDetectionOn = false + var detectionOn = false private set var flashOn = false @@ -105,8 +102,7 @@ class CameraManager(private val stageActivity: StageActivity) : LifecycleOwner { fun reset() { flashOn = false previewVisible = false - faceDetectionOn = false - textDetectionOn = false + detectionOn = false unbindPreview() switchToDefaultCamera() } @@ -147,14 +143,9 @@ class CameraManager(private val stageActivity: StageActivity) : LifecycleOwner { if (currentCameraSelector != cameraSelector) { currentCameraSelector = cameraSelector currentCamera = null - - if (cameraProvider.isBound(previewUseCase)) { - bindPreview() - } - if (cameraProvider.isBound(analysisUseCase)) { - bindFaceDetector() - bindTextDetector() - } + cameraProvider.unbindAll() + bindPreview() + bindFaceAndTextDetector() return true } return false @@ -213,19 +204,10 @@ class CameraManager(private val stageActivity: StageActivity) : LifecycleOwner { } @Synchronized - fun startFaceDetection(): Boolean { - if (faceDetectionOn.not()) { - faceDetectionOn = true - bindFaceDetector() - } - return true - } - - @Synchronized - fun startTextDetection(): Boolean { - if (textDetectionOn.not()) { - textDetectionOn = true - bindTextDetector() + fun startDetection(): Boolean { + if (detectionOn.not()) { + detectionOn = true + bindFaceAndTextDetector() } return true } @@ -249,12 +231,8 @@ class CameraManager(private val stageActivity: StageActivity) : LifecycleOwner { } @UiThread - private fun bindFaceDetector() = bindUseCase(analysisUseCase).also { - analysisUseCase.setAnalyzer(Executors.newSingleThreadExecutor(), FaceDetector) - } - - private fun bindTextDetector() = bindUseCase(analysisUseCase).also { - analysisUseCase.setAnalyzer(Executors.newSingleThreadExecutor(), TextDetector) + private fun bindFaceAndTextDetector() = bindUseCase(analysisUseCase).also { + analysisUseCase.setAnalyzer(Executors.newSingleThreadExecutor(), FaceAndTextDetector) } @UiThread diff --git a/catroid/src/main/java/org/catrobat/catroid/camera/FaceAndTextDetector.kt b/catroid/src/main/java/org/catrobat/catroid/camera/FaceAndTextDetector.kt new file mode 100644 index 00000000000..f200459f013 --- /dev/null +++ b/catroid/src/main/java/org/catrobat/catroid/camera/FaceAndTextDetector.kt @@ -0,0 +1,281 @@ +/* + * Catroid: An on-device visual programming system for Android devices + * Copyright (C) 2010-2021 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * http://developer.catrobat.org/license_additional_term + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.catrobat.catroid.camera + +import android.graphics.Point +import android.util.Log +import androidx.annotation.VisibleForTesting +import androidx.camera.core.ExperimentalGetImage +import androidx.camera.core.ImageAnalysis +import androidx.camera.core.ImageProxy +import com.google.mlkit.vision.common.InputImage +import com.google.mlkit.vision.face.Face +import com.google.mlkit.vision.face.FaceDetection +import com.google.mlkit.vision.face.FaceDetectorOptions +import com.google.mlkit.vision.text.Text +import com.google.mlkit.vision.text.TextRecognition +import org.catrobat.catroid.CatroidApplication +import org.catrobat.catroid.ProjectManager +import org.catrobat.catroid.R +import org.catrobat.catroid.common.Constants.COORDINATE_TRANSFORMATION_OFFSET +import org.catrobat.catroid.common.ScreenValues.SCREEN_HEIGHT +import org.catrobat.catroid.common.ScreenValues.SCREEN_WIDTH +import org.catrobat.catroid.formulaeditor.SensorCustomEvent +import org.catrobat.catroid.formulaeditor.SensorCustomEventListener +import org.catrobat.catroid.formulaeditor.Sensors +import org.catrobat.catroid.stage.StageActivity +import org.catrobat.catroid.utils.TextBlockUtil +import kotlin.math.roundToInt + +object FaceAndTextDetector : ImageAnalysis.Analyzer { + private const val MAX_FACE_SIZE = 100 + private const val FACE_SENSORS = 2 + private val sensorListeners = mutableSetOf() + + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + var facesForSensors: Array = Array(FACE_SENSORS) { _ -> null } + private var faceIds: IntArray = IntArray(FACE_SENSORS) { _ -> -1 } + private val faceDetectionClient by lazy { + FaceDetection.getClient( + FaceDetectorOptions.Builder() + .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL) + .enableTracking() + .build() + ) + } + private val textDetectionClient = TextRecognition.getClient() + + private var textDetected = false + private var faceDetected = false + + @JvmStatic + fun addListener(listener: SensorCustomEventListener) { + sensorListeners.add(listener) + } + + @JvmStatic + fun removeListener(listener: SensorCustomEventListener) { + sensorListeners.remove(listener) + } + + @ExperimentalGetImage + override fun analyze(imageProxy: ImageProxy) { + imageProxy.image?.let { mediaImage -> + val image = InputImage.fromMediaImage( + mediaImage, + imageProxy.imageInfo.rotationDegrees + ) + + faceDetected = false + textDetected = false + + textDetectionClient.process(image) + .addOnSuccessListener { text -> + updateTextSensorValues(text, mediaImage.width, mediaImage.height) + textDetected = true + if (faceDetected) { + imageProxy.close() + } + } + .addOnFailureListener { e -> + val context = StageActivity.activeStageActivity.get() + StageActivity.messageHandler.obtainMessage( + StageActivity.SHOW_TOAST, + arrayListOf(context?.getString(R.string.camera_error_text_detection)) + ).sendToTarget() + Log.e(javaClass.simpleName, "Could not analyze image.", e) + } + + faceDetectionClient.process(image) + .addOnSuccessListener { faces -> + updateFaceSensorValues(faces, mediaImage.width, mediaImage.height) + faceDetected = true + if (textDetected) { + imageProxy.close() + } + } + .addOnFailureListener { e -> + updateDetectionStatus() + val context = CatroidApplication.getAppContext() + StageActivity.messageHandler.obtainMessage( + StageActivity.SHOW_TOAST, + arrayListOf(context.getString(R.string.camera_error_face_detection)) + ).sendToTarget() + Log.e(javaClass.simpleName, "Could not analyze image.", e) + } + } + } + + private fun updateTextSensorValues(text: Text, imageWidth: Int, imageHeight: Int) { + val detected = text.textBlocks.isEmpty().not() + if (detected) { + translateTextToSensorValues(text, imageWidth, imageHeight) + } + } + + private fun translateTextToSensorValues(text: Text, imageWidth: Int, imageHeight: Int) { + val textFromCamera = text.text + + val textBlocksNumber = text.textBlocks.size + + TextBlockUtil.setTextBlocks(text.textBlocks, imageWidth, imageHeight) + + onTextDetected(textFromCamera, textBlocksNumber) + } + + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + fun onTextDetected(text: String, size: Int) { + sensorListeners.forEach { + it.onCustomSensorChanged( + SensorCustomEvent(Sensors.TEXT_FROM_CAMERA, arrayOf(text)) + ) + it.onCustomSensorChanged( + SensorCustomEvent(Sensors.TEXT_BLOCKS_NUMBER, floatArrayOf(size.toFloat())) + ) + } + } + + private fun updateFaceSensorValues(faces: List, imageWidth: Int, imageHeight: Int) { + handleAlreadyExistingFaces(faces) + facesForSensors.forEachIndexed { index, face -> + if (face == null) { + attachNewFaceIfExisting(faces, index) + } + } + updateDetectionStatus() + facesForSensors.forEachIndexed { index, face -> + face?.let { translateFaceToSensorValues(face, index, imageWidth, imageHeight) } + } + facesForSensors.fill(null) + } + + private fun handleAlreadyExistingFaces(faces: List) { + for (face in faces) { + when (face.trackingId) { + faceIds[0] -> facesForSensors[0] = face + faceIds[1] -> facesForSensors[1] = face + } + } + } + + private fun attachNewFaceIfExisting(faces: List, index: Int) { + for (face in faces) { + if (face.trackingId?.let { faceIds.contains(it) } == false) { + faceIds[index] = face.trackingId ?: -1 + facesForSensors[index] = face + break + } + } + } + + private fun translateFaceToSensorValues( + face: Face, + faceNumber: Int, + imageWidth: Int, + imageHeight: Int + ) { + val frontCamera = StageActivity.getActiveCameraManager().isCameraFacingFront + val aspectRatio = imageWidth.toFloat() / imageHeight + val faceBounds = face.boundingBox + + val facePosition = if (ProjectManager.getInstance().isCurrentProjectLandscapeMode) { + val relativeX = faceBounds.exactCenterY() / imageHeight + val relativeY = faceBounds.exactCenterX() / imageWidth + coordinatesFromRelativePosition( + 1 - relativeX, + SCREEN_WIDTH / aspectRatio, + if (frontCamera) relativeY else 1 - relativeY, + SCREEN_WIDTH.toFloat() + ) + } else { + val relativeX = faceBounds.exactCenterX() / imageHeight + coordinatesFromRelativePosition( + if (frontCamera) 1 - relativeX else relativeX, + SCREEN_HEIGHT / aspectRatio, + 1 - faceBounds.exactCenterY() / imageWidth, + SCREEN_HEIGHT.toFloat() + ) + } + + val relativeFaceSize = (faceBounds.height().toFloat() / imageHeight).coerceAtMost(1f) + val faceSize = (MAX_FACE_SIZE * relativeFaceSize).roundToInt() + onFaceDetected(facePosition, faceSize, faceNumber) + } + + private fun coordinatesFromRelativePosition( + relativeX: Float, + width: Float, + relativeY: Float, + height: Float + ) = Point( + (width * (relativeX - COORDINATE_TRANSFORMATION_OFFSET)).roundToInt(), + (height * (relativeY - COORDINATE_TRANSFORMATION_OFFSET)).roundToInt() + ) + + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + fun updateDetectionStatus() { + val firstSensorValue = if (facesForSensors[0] != null) 1f else 0f + val secondSensorValue = if (facesForSensors[1] != null) 1f else 0f + sensorListeners.forEach { + it.onCustomSensorChanged( + SensorCustomEvent(Sensors.FACE_DETECTED, floatArrayOf(firstSensorValue)) + ) + it.onCustomSensorChanged( + SensorCustomEvent(Sensors.SECOND_FACE_DETECTED, floatArrayOf(secondSensorValue)) + ) + } + } + + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + fun onFaceDetected(position: Point, size: Int, faceNumber: Int) { + sensorListeners.forEach { + if (faceNumber == 0) { + it.onCustomSensorChanged( + SensorCustomEvent(Sensors.FACE_X_POSITION, floatArrayOf(position.x.toFloat())) + ) + it.onCustomSensorChanged( + SensorCustomEvent(Sensors.FACE_Y_POSITION, floatArrayOf(position.y.toFloat())) + ) + it.onCustomSensorChanged( + SensorCustomEvent(Sensors.FACE_SIZE, floatArrayOf(size.toFloat())) + ) + } else if (faceNumber == 1) { + it.onCustomSensorChanged( + SensorCustomEvent( + Sensors.SECOND_FACE_X_POSITION, floatArrayOf(position.x.toFloat()) + ) + ) + it.onCustomSensorChanged( + SensorCustomEvent( + Sensors.SECOND_FACE_Y_POSITION, floatArrayOf(position.y.toFloat()) + ) + ) + it.onCustomSensorChanged( + SensorCustomEvent( + Sensors.SECOND_FACE_SIZE, floatArrayOf(size.toFloat()) + ) + ) + } + } + } +} diff --git a/catroid/src/main/java/org/catrobat/catroid/camera/FaceDetector.kt b/catroid/src/main/java/org/catrobat/catroid/camera/FaceDetector.kt deleted file mode 100644 index fe2e7e1a429..00000000000 --- a/catroid/src/main/java/org/catrobat/catroid/camera/FaceDetector.kt +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team - * () - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * An additional term exception under section 7 of the GNU Affero - * General Public License, version 3, is available at - * http://developer.catrobat.org/license_additional_term - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.catrobat.catroid.camera - -import android.graphics.Point -import android.os.Build -import android.util.Log -import androidx.annotation.VisibleForTesting -import androidx.camera.core.ExperimentalGetImage -import androidx.camera.core.ImageAnalysis -import androidx.camera.core.ImageProxy -import com.google.mlkit.vision.common.InputImage -import com.google.mlkit.vision.face.Face -import com.google.mlkit.vision.face.FaceDetection -import com.google.mlkit.vision.face.FaceDetectorOptions -import org.catrobat.catroid.CatroidApplication -import org.catrobat.catroid.ProjectManager -import org.catrobat.catroid.R -import org.catrobat.catroid.common.Constants.COORDINATE_TRANSFORMATION_OFFSET -import org.catrobat.catroid.common.ScreenValues.SCREEN_HEIGHT -import org.catrobat.catroid.common.ScreenValues.SCREEN_WIDTH -import org.catrobat.catroid.formulaeditor.SensorCustomEvent -import org.catrobat.catroid.formulaeditor.SensorCustomEventListener -import org.catrobat.catroid.formulaeditor.Sensors -import org.catrobat.catroid.stage.StageActivity -import kotlin.math.roundToInt - -object FaceDetector : ImageAnalysis.Analyzer { - private const val MAX_FACE_SIZE = 100 - private val sensorListeners = mutableSetOf() - private val detectionClient by lazy { - FaceDetection.getClient( - FaceDetectorOptions.Builder() - .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL) - .enableTracking() - .build() - ) - } - - @JvmStatic - fun addListener(listener: SensorCustomEventListener) { - sensorListeners.add(listener) - } - - @JvmStatic - fun removeListener(listener: SensorCustomEventListener) { - sensorListeners.remove(listener) - } - - @ExperimentalGetImage - override fun analyze(imageProxy: ImageProxy) { - imageProxy.image?.let { mediaImage -> - val image = InputImage.fromMediaImage( - mediaImage, - imageProxy.imageInfo.rotationDegrees - ) - - detectionClient.process(image) - .addOnSuccessListener { faces -> - updateSensorValues(faces, mediaImage.width, mediaImage.height) - imageProxy.close() - } - .addOnFailureListener { e -> - updateDetectionStatus(false) - val context = CatroidApplication.getAppContext() - StageActivity.messageHandler.obtainMessage( - StageActivity.SHOW_TOAST, - arrayListOf(context.getString(R.string.camera_error_face_detection)) - ).sendToTarget() - Log.e(javaClass.simpleName, "Could not analyze image.", e) - } - } - } - - private fun updateSensorValues(faces: List, imageWidth: Int, imageHeight: Int) { - val detected = faces.isNotEmpty() - - updateDetectionStatus(detected) - if (detected) { - translateFaceToSensorValues(faces[0], imageWidth, imageHeight) - } - } - - private fun translateFaceToSensorValues(face: Face, imageWidth: Int, imageHeight: Int) { - val frontCamera = StageActivity.getActiveCameraManager().isCameraFacingFront - val oldAPI = Build.VERSION.SDK_INT < Build.VERSION_CODES.M - val aspectRatio = imageWidth.toFloat() / imageHeight - val faceBounds = face.boundingBox - - val facePosition = if (ProjectManager.getInstance().isCurrentProjectLandscapeMode) { - val relativeX = faceBounds.exactCenterY() / imageHeight - val relativeY = faceBounds.exactCenterX() / imageWidth - coordinatesFromRelativePosition( - if (oldAPI) relativeX else 1 - relativeX, - SCREEN_WIDTH / aspectRatio, - if (frontCamera) relativeY else 1 - relativeY, - SCREEN_WIDTH.toFloat() - ) - } else { - val relativeX = faceBounds.exactCenterX() / imageHeight - coordinatesFromRelativePosition( - if (frontCamera.xor(oldAPI)) 1 - relativeX else relativeX, - SCREEN_HEIGHT / aspectRatio, - 1 - faceBounds.exactCenterY() / imageWidth, - SCREEN_HEIGHT.toFloat() - ) - } - - val relativeFaceSize = (faceBounds.height().toFloat() / imageHeight).coerceAtMost(1f) - val faceSize = (MAX_FACE_SIZE * relativeFaceSize).roundToInt() - onFaceDetected(facePosition, faceSize) - } - - private fun coordinatesFromRelativePosition( - relativeX: Float, - width: Float, - relativeY: Float, - height: Float - ) = Point( - (width * (relativeX - COORDINATE_TRANSFORMATION_OFFSET)).roundToInt(), - (height * (relativeY - COORDINATE_TRANSFORMATION_OFFSET)).roundToInt() - ) - - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - fun updateDetectionStatus(faceDetected: Boolean) { - val sensorValue = if (faceDetected) 1f else 0f - sensorListeners.forEach { - it.onCustomSensorChanged( - SensorCustomEvent(Sensors.FACE_DETECTED, floatArrayOf(sensorValue))) - } - } - - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - fun onFaceDetected(position: Point, size: Int) { - sensorListeners.forEach { - it.onCustomSensorChanged( - SensorCustomEvent(Sensors.FACE_X_POSITION, floatArrayOf(position.x.toFloat()))) - it.onCustomSensorChanged( - SensorCustomEvent(Sensors.FACE_Y_POSITION, floatArrayOf(position.y.toFloat()))) - it.onCustomSensorChanged( - SensorCustomEvent(Sensors.FACE_SIZE, floatArrayOf(size.toFloat()))) - } - } -} diff --git a/catroid/src/main/java/org/catrobat/catroid/camera/PreviewView.kt b/catroid/src/main/java/org/catrobat/catroid/camera/PreviewView.kt index db08f82016e..ab124723bdc 100644 --- a/catroid/src/main/java/org/catrobat/catroid/camera/PreviewView.kt +++ b/catroid/src/main/java/org/catrobat/catroid/camera/PreviewView.kt @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2020 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -32,7 +32,7 @@ import java.util.concurrent.Executors import kotlin.math.roundToInt class PreviewView(context: Context) : FrameLayout(context) { - private val surfaceView = SurfaceView(context) + val surfaceView = SurfaceView(context) init { addView(surfaceView) @@ -56,19 +56,13 @@ class PreviewView(context: Context) : FrameLayout(context) { if (screenAspectRatio < 1) { // portrait mode val scalingFactor = imageAspectRatio / screenAspectRatio - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - val scaledWidth = (imageWidth * scalingFactor).roundToInt() - surfaceView.layoutParams = LayoutParams(scaledWidth, imageHeight) - } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M) { + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M) { surfaceView.layoutParams.width = (this.width * scalingFactor).roundToInt() } surfaceView.scaleX = scalingFactor } else { // landscape mode val scalingFactor = imageAspectRatio * screenAspectRatio - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - val scaledHeight = (imageHeight * scalingFactor).roundToInt() - surfaceView.layoutParams = LayoutParams(imageWidth, scaledHeight) - } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M) { + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M) { surfaceView.layoutParams.height = (this.height * scalingFactor).roundToInt() } surfaceView.scaleY = scalingFactor diff --git a/catroid/src/main/java/org/catrobat/catroid/camera/TextDetector.kt b/catroid/src/main/java/org/catrobat/catroid/camera/TextDetector.kt deleted file mode 100644 index 8ab70bdc442..00000000000 --- a/catroid/src/main/java/org/catrobat/catroid/camera/TextDetector.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2020 The Catrobat Team - * () - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * An additional term exception under section 7 of the GNU Affero - * General Public License, version 3, is available at - * http://developer.catrobat.org/license_additional_term - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.catrobat.catroid.camera - -import android.util.Log -import androidx.annotation.VisibleForTesting -import androidx.camera.core.ExperimentalGetImage -import androidx.camera.core.ImageAnalysis -import androidx.camera.core.ImageProxy -import com.google.mlkit.vision.common.InputImage -import com.google.mlkit.vision.text.TextRecognition -import com.google.mlkit.vision.text.Text -import org.catrobat.catroid.R -import org.catrobat.catroid.formulaeditor.SensorCustomEvent -import org.catrobat.catroid.formulaeditor.SensorCustomEventListener -import org.catrobat.catroid.formulaeditor.Sensors -import org.catrobat.catroid.stage.StageActivity -import org.catrobat.catroid.utils.TextBlockUtil - -object TextDetector : ImageAnalysis.Analyzer { - private val detectionClient = TextRecognition.getClient() - private val sensorListeners = mutableSetOf() - - @JvmStatic - fun addListener(listener: SensorCustomEventListener) { - sensorListeners.add(listener) - } - - @JvmStatic - fun removeListener(listener: SensorCustomEventListener) { - sensorListeners.remove(listener) - } - - @ExperimentalGetImage - override fun analyze(imageProxy: ImageProxy) { - imageProxy.image?.let { mediaImage -> - val image = InputImage.fromMediaImage( - mediaImage, - imageProxy.imageInfo.rotationDegrees - ) - - detectionClient.process(image) - .addOnSuccessListener { text -> - updateSensorValues(text, mediaImage.width, mediaImage.height) - imageProxy.close() - } - .addOnFailureListener { e -> - val context = StageActivity.activeStageActivity.get() - StageActivity.messageHandler.obtainMessage( - StageActivity.SHOW_TOAST, - arrayListOf(context?.getString(R.string.camera_error_text_detection)) - ).sendToTarget() - Log.e(javaClass.simpleName, "Could not analyze image.", e) - } - } - } - - private fun updateSensorValues(text: Text, imageWidth: Int, imageHeight: Int) { - val detected = text.textBlocks.isEmpty().not() - if (detected) { - translateTextToSensorValues(text, imageWidth, imageHeight) - } - } - - private fun translateTextToSensorValues(text: Text, imageWidth: Int, imageHeight: Int) { - val textFromCamera = text.text - - val textBlocksNumber = text.textBlocks.size - - TextBlockUtil.setTextBlocks(text.textBlocks, imageWidth, imageHeight) - - onTextDetected(textFromCamera, textBlocksNumber) - } - - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - fun onTextDetected(text: String, size: Int) { - sensorListeners.forEach { - it.onCustomSensorChanged( - SensorCustomEvent(Sensors.TEXT_FROM_CAMERA, arrayOf(text))) - it.onCustomSensorChanged( - SensorCustomEvent(Sensors.TEXT_BLOCKS_NUMBER, floatArrayOf(size.toFloat()))) - } - } -} diff --git a/catroid/src/main/java/org/catrobat/catroid/common/BrickValues.java b/catroid/src/main/java/org/catrobat/catroid/common/BrickValues.java index 8402c49daf7..6cb23964476 100644 --- a/catroid/src/main/java/org/catrobat/catroid/common/BrickValues.java +++ b/catroid/src/main/java/org/catrobat/catroid/common/BrickValues.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -181,6 +181,20 @@ public final class BrickValues { public static final int ZIGZAG_STITCH_LENGTH = 2; public static final int ZIGZAG_STITCH_WIDTH = 10; + //Constants Device + public static final double TOUCH_DURATION = 0.3; + public static final int TOUCH_X_START = -100; + public static final int TOUCH_Y_START = -200; + public static final int TOUCH_X_GOAL = 100; + public static final int TOUCH_Y_GOAL = 200; + + //Constants Web + public static final String OPEN_IN_BROWSER = "https://catrobat.org/"; + public static final String LOOK_REQUEST = "https://catrob.at/penguin"; + public static final String BACKGROUND_REQUEST = "https://catrob.at/HalloweenPortrait"; + public static final String BACKGROUND_REQUEST_LANDSCAPE = "https://catrob.at/HalloweenLandscape"; + // Note: No constant default value for the "Send web request" brick, as it is localized in strings.xml + private BrickValues() { throw new AssertionError("No."); } diff --git a/catroid/src/main/java/org/catrobat/catroid/common/BroadcastMessageContainer.java b/catroid/src/main/java/org/catrobat/catroid/common/BroadcastMessageContainer.java index 113354e8617..44d5dd1b162 100644 --- a/catroid/src/main/java/org/catrobat/catroid/common/BroadcastMessageContainer.java +++ b/catroid/src/main/java/org/catrobat/catroid/common/BroadcastMessageContainer.java @@ -50,6 +50,13 @@ public boolean addBroadcastMessage(String messageToAdd) { && broadcastMessages.add(messageToAdd); } + public boolean removeBroadcastMessage(String messageToRemove) { + return messageToRemove != null + && !messageToRemove.isEmpty() + && broadcastMessages.contains(messageToRemove) + && broadcastMessages.remove(messageToRemove); + } + public List getBroadcastMessages() { if (broadcastMessages.size() == 0) { update(); diff --git a/catroid/src/main/java/org/catrobat/catroid/common/Constants.java b/catroid/src/main/java/org/catrobat/catroid/common/Constants.java index 84ac02a9e28..4eacb03caa3 100644 --- a/catroid/src/main/java/org/catrobat/catroid/common/Constants.java +++ b/catroid/src/main/java/org/catrobat/catroid/common/Constants.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -30,20 +30,23 @@ import java.io.File; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import androidx.annotation.IntDef; +import androidx.exifinterface.media.ExifInterface; import static org.catrobat.catroid.common.FlavoredConstants.BASE_URL_HTTPS; import static org.catrobat.catroid.common.FlavoredConstants.DEFAULT_ROOT_DIRECTORY; public final class Constants { - public static final double CURRENT_CATROBAT_LANGUAGE_VERSION = 0.99999991; - + public static final double CURRENT_CATROBAT_LANGUAGE_VERSION = 1.01; public static final String REMOTE_DISPLAY_APP_ID = "CEBB9229"; public static final int CAST_CONNECTION_TIMEOUT = 5000; //in milliseconds public static final int CAST_NOT_SEEING_DEVICE_TIMEOUT = 3000; //in milliseconds + public static final long RETROFIT_WRITE_TIMEOUT = 15; public static final String PLATFORM_NAME = "Android"; public static final int APPLICATION_BUILD_NUMBER = 0; // updated from jenkins nightly/release build @@ -51,6 +54,7 @@ public final class Constants { public static final String CODE_XML_FILE_NAME = "code.xml"; public static final String PERMISSIONS_FILE_NAME = "permissions.txt"; public static final String TMP_CODE_XML_FILE_NAME = "tmp_" + CODE_XML_FILE_NAME; + public static final String UNDO_CODE_XML_FILE_NAME = "undo_" + CODE_XML_FILE_NAME; public static final String DEVICE_VARIABLE_JSON_FILENAME = "DeviceVariables.json"; public static final String DEVICE_LIST_JSON_FILENAME = "DeviceLists.json"; @@ -61,6 +65,7 @@ public final class Constants { public static final String CATROBAT_EXTENSION = ".catrobat"; public static final String DEFAULT_IMAGE_EXTENSION = ".png"; + public static final String JPEG_IMAGE_EXTENSION = ".jpg"; public static final String DEFAULT_SOUND_EXTENSION = ".wav"; public static final String EMBROIDERY_FILE_EXTENSION = ".dst"; public static final char REMIX_URL_PREFIX_INDICATOR = '['; @@ -77,6 +82,12 @@ public final class Constants { public static final String SOUND_DIRECTORY_NAME = "sounds"; public static final String SCREENSHOT_AUTOMATIC_FILE_NAME = "automatic_screenshot" + DEFAULT_IMAGE_EXTENSION; public static final String SCREENSHOT_MANUAL_FILE_NAME = "manual_screenshot" + DEFAULT_IMAGE_EXTENSION; + public static final File TEMP_LOOK_FILE = + new File(DEFAULT_ROOT_DIRECTORY, "temporary_look_file" + DEFAULT_IMAGE_EXTENSION); + + // Recent Bricks Directory + public static final String RECENT_BRICKS_DIRECTORY = "recent_bricks"; + public static final String RECENT_BRICKS_FILE = "recent_bricks.json"; // Backpack Directories public static final String BACKPACK_DIRECTORY_NAME = "backpack"; @@ -85,7 +96,7 @@ public final class Constants { public static final String BACKPACK_SOUND_DIRECTORY_NAME = "backpack_sound"; public static final String BACKPACK_IMAGE_DIRECTORY_NAME = "backpack_image"; - // Trusted domains + // Trusted domains for Web access bricks public static final String TRUSTED_DOMAINS_FILE_NAME = "trustedDomains.json"; public static final String TRUSTED_USER_DOMAINS_FILE_NAME = "trustedUserDomains.json"; public static final String TRUST_LIST_JSON_ARRAY_NAME = "domains"; @@ -119,13 +130,21 @@ public final class Constants { public static final String SHARE_PROJECT_URL = BASE_URL_HTTPS + "/project/"; public static final String CATROBAT_ABOUT_URL = "https://www.catrobat.org/"; + public static final String CATROBAT_FORMULA_WIKI_URL = "https://wiki.catrobat.org/bin/view/Documentation/FormulaEditor"; public static final String ABOUT_POCKETCODE_LICENSE_URL = "https://catrob.at/licenses"; public static final String WEB_REQUEST_WIKI_URL = "https://catrob.at/webbricks"; public static final String CATROBAT_TERMS_OF_USE_URL = BASE_URL_HTTPS + "termsOfUse"; public static final String CATROBAT_HELP_URL = "https://catrob.at/help"; + public static final String CATROBAT_FUNCTIONS_WIKI_URL = CATROBAT_FORMULA_WIKI_URL + "/Functions/"; + public static final String CATROBAT_LOGIC_WIKI_URL = CATROBAT_FORMULA_WIKI_URL + "/Logic/"; + public static final String CATROBAT_SENSORS_WIKI_URL = CATROBAT_FORMULA_WIKI_URL + "/Sensors/"; + public static final String CATROBAT_OBJECT_WIKI_URL = CATROBAT_FORMULA_WIKI_URL + "/Properties/"; public static final String CATROBAT_TOKEN_LOGIN_URL = BASE_URL_HTTPS + "tokenlogin?username="; public static final String CATROBAT_DELETE_ACCOUNT_URL = BASE_URL_HTTPS + "profile/edit"; + public static final String CATROBAT_TERMS_OF_USE_TOKEN_FLAVOR_URL = "?flavorName="; + public static final String CATROBAT_TERMS_OF_USE_TOKEN_VERSION_URL = "&versionCode="; + public static final int CATROBAT_TERMS_OF_USE_ACCEPTED = 1; public static final String PLAY_STORE_PAGE_LINK = "https://play.google.com/store/apps/details?id="; @@ -143,7 +162,6 @@ public final class Constants { // XStream: public static final String BLUETOOTH_LEGO_NXT = "BLUETOOTH_LEGO_NXT"; - public static final String ARDRONE_SUPPORT = "ARDRONE_SUPPORT"; public static final String NFC = "NFC"; //Broadcast system: @@ -264,7 +282,6 @@ public final class Constants { public static final int Z_INDEX_FIRST_SPRITE = Z_INDEX_BACKGROUND + Z_INDEX_NUMBER_VIRTUAL_LAYERS + 1; - public static final String NO_VARIABLE_SELECTED = "No variable set"; public static final int SAY_BRICK = 0; public static final int THINK_BRICK = 1; public static final int MAX_STRING_LENGTH_BUBBLES = 16; @@ -279,6 +296,8 @@ public final class Constants { public static final int TEXT_FROM_CAMERA_SENSOR_HASHCODE = 1613638780; + public static final int MAX_NUMBER_OF_CHECKED_TAGS = 3; + //Services + Notifications public static final int UPDATE_DOWNLOAD_PROGRESS = 101; public static final int UPDATE_DOWNLOAD_ERROR = 105; @@ -297,6 +316,45 @@ public final class Constants { public static final int STATUS_CODE_UPLOAD_OLD_CATROBAT_LANGUAGE = 518; public static final int STATUS_CODE_UPLOAD_OLD_CATROBAT_VERSION = 519; + //ExifTags for Exifremover + public static final ArrayList EXIFTAGS_FOR_EXIFREMOVER = + new ArrayList(Arrays.asList( + ExifInterface.TAG_ARTIST, + ExifInterface.TAG_DATETIME, + ExifInterface.TAG_DATETIME_ORIGINAL, + ExifInterface.TAG_DATETIME_DIGITIZED, + ExifInterface.TAG_EXPOSURE_TIME, + ExifInterface.TAG_FLASH, + ExifInterface.TAG_FILE_SOURCE, + ExifInterface.TAG_GPS_ALTITUDE, + ExifInterface.TAG_GPS_ALTITUDE_REF, + ExifInterface.TAG_GPS_AREA_INFORMATION, + ExifInterface.TAG_GPS_DATESTAMP, + ExifInterface.TAG_GPS_DEST_BEARING, + ExifInterface.TAG_GPS_DEST_BEARING_REF, + ExifInterface.TAG_GPS_DEST_DISTANCE, + ExifInterface.TAG_GPS_DEST_DISTANCE_REF, + ExifInterface.TAG_GPS_DEST_LATITUDE, + ExifInterface.TAG_GPS_DEST_LATITUDE_REF, + ExifInterface.TAG_GPS_DEST_LONGITUDE, + ExifInterface.TAG_GPS_DEST_LONGITUDE_REF, + ExifInterface.TAG_GPS_LATITUDE, + ExifInterface.TAG_GPS_LATITUDE_REF, + ExifInterface.TAG_GPS_LONGITUDE, + ExifInterface.TAG_GPS_LONGITUDE_REF, + ExifInterface.TAG_GPS_MAP_DATUM, + ExifInterface.TAG_GPS_SATELLITES, + ExifInterface.TAG_GPS_TIMESTAMP, + ExifInterface.TAG_GPS_PROCESSING_METHOD, + ExifInterface.TAG_GPS_DATESTAMP, + ExifInterface.TAG_MAKE, + ExifInterface.TAG_MODEL, + ExifInterface.TAG_IMAGE_DESCRIPTION, + ExifInterface.TAG_STRIP_OFFSETS, + ExifInterface.TAG_SOFTWARE, + ExifInterface.TAG_CAMARA_OWNER_NAME + )); + private Constants() { throw new AssertionError("No."); } diff --git a/catroid/src/main/java/org/catrobat/catroid/common/DefaultProjectHandler.java b/catroid/src/main/java/org/catrobat/catroid/common/DefaultProjectHandler.java index df18d57cd5a..b5f048bbbbb 100644 --- a/catroid/src/main/java/org/catrobat/catroid/common/DefaultProjectHandler.java +++ b/catroid/src/main/java/org/catrobat/catroid/common/DefaultProjectHandler.java @@ -25,10 +25,8 @@ import android.content.Context; import org.catrobat.catroid.BuildConfig; -import org.catrobat.catroid.common.defaultprojectcreators.ArDroneProjectCreator; import org.catrobat.catroid.common.defaultprojectcreators.ChromeCastProjectCreator; import org.catrobat.catroid.common.defaultprojectcreators.DefaultExampleProject; -import org.catrobat.catroid.common.defaultprojectcreators.JumpingSumoProjectCreator; import org.catrobat.catroid.common.defaultprojectcreators.ProjectCreator; import org.catrobat.catroid.content.Project; import org.catrobat.catroid.io.XstreamSerializer; @@ -39,9 +37,7 @@ public final class DefaultProjectHandler { public enum ProjectCreatorType { PROJECT_CREATOR_DEFAULT, - PROJECT_CREATOR_DRONE, - PROJECT_CREATOR_CAST, - PROJECT_CREATOR_JUMPING_SUMO + PROJECT_CREATOR_CAST } private static DefaultProjectHandler instance = null; @@ -86,20 +82,6 @@ public void setDefaultProjectCreator(ProjectCreatorType type) { case PROJECT_CREATOR_DEFAULT: defaultProjectCreator = new DefaultExampleProject(); break; - case PROJECT_CREATOR_DRONE: - if (BuildConfig.FEATURE_PARROT_AR_DRONE_ENABLED) { - defaultProjectCreator = new ArDroneProjectCreator(); - } else { - defaultProjectCreator = new DefaultExampleProject(); - } - break; - case PROJECT_CREATOR_JUMPING_SUMO: - if (BuildConfig.FEATURE_PARROT_JUMPING_SUMO_ENABLED) { - defaultProjectCreator = new JumpingSumoProjectCreator(); - } else { - defaultProjectCreator = new DefaultExampleProject(); - } - break; case PROJECT_CREATOR_CAST: if (BuildConfig.FEATURE_CAST_ENABLED) { defaultProjectCreator = new ChromeCastProjectCreator(); diff --git a/catroid/src/main/java/org/catrobat/catroid/common/DroneConfigPreference.java b/catroid/src/main/java/org/catrobat/catroid/common/DroneConfigPreference.java index f8248a38902..e46b56e22f8 100644 --- a/catroid/src/main/java/org/catrobat/catroid/common/DroneConfigPreference.java +++ b/catroid/src/main/java/org/catrobat/catroid/common/DroneConfigPreference.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -42,14 +42,6 @@ public static String[] getPreferenceCodes() { return valueStrings; } - public String getPreferenceCode() { - return getPreferenceCode(this); - } - - public static String getPreferenceCode(DroneConfigPreference.Preferences preference) { - return preference.name(); - } - public static DroneConfigPreference.Preferences getPreferenceFromPreferenceCode(String preferenceCode) { Preferences preferences = EnumUtils.getEnum(Preferences.class, preferenceCode); return preferences != null ? preferences : Preferences.FIRST; diff --git a/catroid/src/main/java/org/catrobat/catroid/common/DroneVideoLookData.java b/catroid/src/main/java/org/catrobat/catroid/common/DroneVideoLookData.java deleted file mode 100644 index 235b50edc1f..00000000000 --- a/catroid/src/main/java/org/catrobat/catroid/common/DroneVideoLookData.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team - * () - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * An additional term exception under section 7 of the GNU Affero - * General Public License, version 3, is available at - * http://developer.catrobat.org/license_additional_term - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.catrobat.catroid.common; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.GL20; -import com.badlogic.gdx.graphics.Pixmap; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.parrot.freeflight.ui.gl.GLBGVideoSprite; - -import org.catrobat.catroid.content.bricks.Brick; -import org.catrobat.catroid.io.StorageOperations; - -import java.io.File; -import java.io.IOException; - -public class DroneVideoLookData extends LookData { - - private static final String TAG = DroneVideoLookData.class.getSimpleName(); - - private transient boolean firstStart = true; - private transient GLBGVideoSprite videoTexture; - private transient int[] videoSize = {0, 0}; - private transient int[] defaultVideoTextureSize; - - public DroneVideoLookData() { - super(); - } - - public DroneVideoLookData(String name, File file) { - super(name, file); - } - - @Override - public DroneVideoLookData clone() { - try { - return new DroneVideoLookData(name, StorageOperations.duplicateFile(file)); - } catch (IOException e) { - throw new RuntimeException(TAG + ": Could not copy file: " + file.getAbsolutePath()); - } - } - - @Override - public int[] getMeasure() { - return defaultVideoTextureSize.clone(); - } - - @Override - public Pixmap getPixmap() { - // BUG: Height() should be 1280, but it is 1184, so we need an scaling factor of 1.081081 - int virtualScreenHeight = (int) Math.round(1.081081 * ScreenValues.SCREEN_HEIGHT); - - defaultVideoTextureSize = new int[] {virtualScreenHeight, ScreenValues.SCREEN_WIDTH}; - - if (pixmap == null) { - pixmap = new Pixmap(virtualScreenHeight, ScreenValues.SCREEN_WIDTH, Pixmap.Format.RGB888); - pixmap.setColor(Color.BLUE); - pixmap.fill(); - pixmap.setBlending(Pixmap.Blending.None); - } - return pixmap; - } - - @Override - public void draw(Batch batch, float parentAlpha) { - if (firstStart) { - videoTexture = new GLBGVideoSprite(); - onSurfaceChanged(); - firstStart = false; - } - - if (videoSize[0] != videoTexture.imageWidth || videoSize[1] != videoTexture.imageHeight) { - onSurfaceChanged(); - } - - Gdx.gl20.glBindTexture(GL20.GL_TEXTURE_2D, textureRegion.getTexture().getTextureObjectHandle()); - videoTexture.onUpdateVideoTexture(); - } - - private void onSurfaceChanged() { - videoSize[0] = videoTexture.imageWidth; - videoSize[1] = videoTexture.imageHeight; - videoTexture.onSurfaceChanged(videoSize[0], videoSize[1]); - } - - @Override - public void addRequiredResources(final Brick.ResourcesSet requiredResourcesSet) { - requiredResourcesSet.add(Brick.ARDRONE_SUPPORT); - } -} diff --git a/catroid/src/main/java/org/catrobat/catroid/common/LookData.java b/catroid/src/main/java/org/catrobat/catroid/common/LookData.java index ed46a7744a5..8145361b3ae 100644 --- a/catroid/src/main/java/org/catrobat/catroid/common/LookData.java +++ b/catroid/src/main/java/org/catrobat/catroid/common/LookData.java @@ -71,6 +71,8 @@ public class LookData implements Cloneable, Nameable, Serializable { private transient CollisionInformation collisionInformation = null; + private boolean valid = true; + public LookData() { } @@ -230,4 +232,12 @@ public String getImageMimeType() { BitmapFactory.decodeFile(pathName, options); return options.outMimeType; } + + public boolean isValid() { + return valid; + } + + public void invalidate() { + valid = false; + } } diff --git a/catroid/src/main/java/org/catrobat/catroid/common/ProjectData.java b/catroid/src/main/java/org/catrobat/catroid/common/ProjectData.java index 183d6530673..896df86f144 100644 --- a/catroid/src/main/java/org/catrobat/catroid/common/ProjectData.java +++ b/catroid/src/main/java/org/catrobat/catroid/common/ProjectData.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -30,7 +30,7 @@ import static org.catrobat.catroid.common.Constants.CODE_XML_FILE_NAME; import static org.catrobat.catroid.common.FlavoredConstants.DEFAULT_ROOT_DIRECTORY; -public class ProjectData implements Nameable, Serializable { +public class ProjectData implements Nameable, Serializable, Comparable { private static final long serialVersionUID = 1L; @@ -69,4 +69,9 @@ public long getLastUsed() { public File getDirectory() { return new File(DEFAULT_ROOT_DIRECTORY, FileMetaDataExtractor.encodeSpecialCharsForFileSystem(getName())); } + + @Override + public int compareTo(ProjectData projectData) { + return name.compareTo(projectData.getName()); + } } diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/dialog/textwatcher/UniqueStringTextWatcher.java b/catroid/src/main/java/org/catrobat/catroid/common/RecentBricksHolder.java similarity index 53% rename from catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/dialog/textwatcher/UniqueStringTextWatcher.java rename to catroid/src/main/java/org/catrobat/catroid/common/RecentBricksHolder.java index 66148b43c91..83d741a3171 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/dialog/textwatcher/UniqueStringTextWatcher.java +++ b/catroid/src/main/java/org/catrobat/catroid/common/RecentBricksHolder.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -21,42 +21,48 @@ * along with this program. If not, see . */ -package org.catrobat.catroid.ui.recyclerview.dialog.textwatcher; +package org.catrobat.catroid.common; -import android.content.Context; - -import org.catrobat.catroid.R; -import org.catrobat.catroid.ui.recyclerview.dialog.TextInputDialog; +import org.catrobat.catroid.content.bricks.Brick; +import java.io.Serializable; +import java.util.ArrayList; import java.util.List; -import androidx.annotation.Nullable; - -public class UniqueStringTextWatcher extends TextInputDialog.TextWatcher { - - private List scope; +public class RecentBricksHolder implements Serializable { + private List recentBricks; - public UniqueStringTextWatcher(List scope) { - this.scope = scope; + public RecentBricksHolder() { + recentBricks = new ArrayList<>(); } - @Nullable - @Override - public String validateInput(String input, Context context) { - String error = null; + public List getRecentBricks() { + return recentBricks; + } - if (input.isEmpty()) { - return context.getString(R.string.name_empty); + public int find(Brick brick) { + for (int i = 0; i < recentBricks.size(); i++) { + Brick b = recentBricks.get(i); + if (b.getClass().equals(brick.getClass())) { + return i; + } } + return -1; + } - input = input.trim(); + public int size() { + return recentBricks.size(); + } - if (input.isEmpty()) { - error = context.getString(R.string.name_consists_of_spaces_only); - } else if (scope.contains(input)) { - error = context.getString(R.string.name_already_exists); - } + public void remove() { + recentBricks.remove(size() - 1); + } + + public void remove(int index) { + recentBricks.remove(index); + } - return error; + public void insert(Brick brick) { + recentBricks.add(0, brick); } } diff --git a/catroid/src/main/java/org/catrobat/catroid/common/SharedPreferenceKeys.java b/catroid/src/main/java/org/catrobat/catroid/common/SharedPreferenceKeys.java index ed35a89c0e0..1b79d52e985 100644 --- a/catroid/src/main/java/org/catrobat/catroid/common/SharedPreferenceKeys.java +++ b/catroid/src/main/java/org/catrobat/catroid/common/SharedPreferenceKeys.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -48,7 +48,15 @@ private SharedPreferenceKeys() { public static final String SHOW_DETAILS_SOUNDS_PREFERENCE_KEY = "showDetailsSoundList"; public static final String SHOW_DETAILS_SPRITES_PREFERENCE_KEY = "showDetailsSpriteList"; + public static final String SORT_PROJECTS_PREFERENCE_KEY = "sortProjectsList"; + public static final String SCRATCH_CONVERTER_CLIENT_ID_PREFERENCE_KEY = "scratchconverter.clientID"; public static final String SCRATCH_CONVERTER_DOWNLOAD_STATE_PREFERENCE_KEY = "scratchconverter" + ".downloadStatePref"; + + public static final String TIME_SPENT_IN_APP_IN_SECONDS_KEY = "timeSpentInApp"; + public static final String LAST_USED_DATE_KEY = "lastUsedDate"; + public static final String SHOW_SURVEY_KEY = "showSurvey"; + public static final String SURVEY_URL1_HASH_KEY = "surveyUrl1Hash"; + public static final String SURVEY_URL2_HASH_KEY = "surveyUrl2Hash"; } diff --git a/catroid/src/main/java/org/catrobat/catroid/common/Survey.java b/catroid/src/main/java/org/catrobat/catroid/common/Survey.java new file mode 100644 index 00000000000..3b89a810d96 --- /dev/null +++ b/catroid/src/main/java/org/catrobat/catroid/common/Survey.java @@ -0,0 +1,201 @@ +/* + * Catroid: An on-device visual programming system for Android devices + * Copyright (C) 2010-2021 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * http://developer.catrobat.org/license_additional_term + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.catrobat.catroid.common; + +import android.content.Context; +import android.content.Intent; +import android.preference.PreferenceManager; +import android.text.format.DateUtils; + +import org.catrobat.catroid.transfers.GetSurveyTask; +import org.catrobat.catroid.ui.WebViewActivity; +import org.catrobat.catroid.utils.Utils; + +import java.util.Date; + +import androidx.annotation.VisibleForTesting; + +import static org.catrobat.catroid.common.SharedPreferenceKeys.LAST_USED_DATE_KEY; +import static org.catrobat.catroid.common.SharedPreferenceKeys.SHOW_SURVEY_KEY; +import static org.catrobat.catroid.common.SharedPreferenceKeys.SURVEY_URL1_HASH_KEY; +import static org.catrobat.catroid.common.SharedPreferenceKeys.SURVEY_URL2_HASH_KEY; +import static org.catrobat.catroid.common.SharedPreferenceKeys.TIME_SPENT_IN_APP_IN_SECONDS_KEY; + +public class Survey implements GetSurveyTask.SurveyResponseListener { + @VisibleForTesting + public static final int MINIMUM_TIME_SPENT_IN_APP_IN_SECONDS = 60 * 60; + + long sessionTimeSpentInIdeInSeconds; + long sessionStartTimeInMilliseconds; + long sessionTimeSpentInStageInMilliseconds; + long stageStartTimeInMilliseconds; + boolean fulfilledSurveyRequirements; + boolean uploadFlag; + + public Survey(Context context) { + fulfilledSurveyRequirements = false; + uploadFlag = false; + sessionTimeSpentInStageInMilliseconds = 0; + sessionStartTimeInMilliseconds = 0; + + checkSurveyRequirement(context); + } + + public void startAppTime(Context context) { + checkSurveyRequirement(context); + + PreferenceManager.getDefaultSharedPreferences(context) + .edit() + .putLong(LAST_USED_DATE_KEY, new Date(System.currentTimeMillis()).getTime()) + .apply(); + + if (!fulfilledSurveyRequirements && sessionStartTimeInMilliseconds == 0) { + sessionStartTimeInMilliseconds = System.currentTimeMillis(); + } + } + + public void endAppTime(Context context) { + if (!fulfilledSurveyRequirements) { + sessionTimeSpentInIdeInSeconds = (System.currentTimeMillis() - sessionStartTimeInMilliseconds - sessionTimeSpentInStageInMilliseconds) / 1000; + sessionStartTimeInMilliseconds = 0; + + long oldTimeSpentInApp = PreferenceManager.getDefaultSharedPreferences(context) + .getLong(TIME_SPENT_IN_APP_IN_SECONDS_KEY, 0); + + PreferenceManager.getDefaultSharedPreferences(context) + .edit() + .putLong(TIME_SPENT_IN_APP_IN_SECONDS_KEY, oldTimeSpentInApp + sessionTimeSpentInIdeInSeconds) + .apply(); + } + } + + public void startStageTime() { + if (!fulfilledSurveyRequirements) { + stageStartTimeInMilliseconds = System.currentTimeMillis(); + } + } + + public void endStageTime() { + if (!fulfilledSurveyRequirements) { + sessionTimeSpentInStageInMilliseconds += System.currentTimeMillis() - stageStartTimeInMilliseconds; + } + } + + private void checkSurveyRequirement(Context context) { + if (!fulfilledSurveyRequirements) { + long timeSpentInApp = PreferenceManager.getDefaultSharedPreferences(context) + .getLong(TIME_SPENT_IN_APP_IN_SECONDS_KEY, 0); + + fulfilledSurveyRequirements = timeSpentInApp > MINIMUM_TIME_SPENT_IN_APP_IN_SECONDS; + } + } + + @VisibleForTesting + public boolean getUploadFlag() { + return uploadFlag; + } + + public void setUploadFlag(boolean value) { + uploadFlag = value; + } + + public void showSurvey(Context context) { + if (fulfilledSurveyRequirements) { + long oldDate = PreferenceManager.getDefaultSharedPreferences(context) + .getLong(LAST_USED_DATE_KEY, new Date(System.currentTimeMillis()).getTime()); + + boolean showSurvey = PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(SHOW_SURVEY_KEY, false); + + if (!DateUtils.isToday(oldDate) || (showSurvey && getUploadFlag())) { + if (Utils.isNetworkAvailable(context)) { + getSurvey(context); + } else { + PreferenceManager.getDefaultSharedPreferences(context) + .edit() + .putBoolean(SHOW_SURVEY_KEY, true) + .apply(); + } + } + } + + uploadFlag = false; + } + + @VisibleForTesting + public void getSurvey(Context context) { + GetSurveyTask getSurveyTask = new GetSurveyTask(context); + getSurveyTask.setOnSurveyResponseListener(this); + getSurveyTask.execute(); + } + + @Override + public void onSurveyReceived(Context context, String surveyUrl) { + if (isUrlNew(context, surveyUrl)) { + Intent intent = new Intent(context, WebViewActivity.class); + intent.putExtra(WebViewActivity.INTENT_PARAMETER_URL, surveyUrl); + intent.putExtra(WebViewActivity.INTENT_FORCE_OPEN_IN_APP, true); + context.startActivity(intent); + + saveUrlHash(context, surveyUrl); + + PreferenceManager.getDefaultSharedPreferences(context) + .edit() + .putLong(LAST_USED_DATE_KEY, new Date(System.currentTimeMillis()).getTime()) + .apply(); + + PreferenceManager.getDefaultSharedPreferences(context) + .edit() + .putBoolean(SHOW_SURVEY_KEY, false) + .apply(); + } + } + + @VisibleForTesting + public void saveUrlHash(Context context, String surveyUrl) { + long firstSurveyHash = PreferenceManager.getDefaultSharedPreferences(context) + .getLong(SURVEY_URL1_HASH_KEY, 0); + + PreferenceManager.getDefaultSharedPreferences(context) + .edit() + .putLong(SURVEY_URL2_HASH_KEY, firstSurveyHash) + .apply(); + + PreferenceManager.getDefaultSharedPreferences(context) + .edit() + .putLong(SURVEY_URL1_HASH_KEY, surveyUrl.hashCode()) + .apply(); + } + + @VisibleForTesting + public boolean isUrlNew(Context context, String surveyUrl) { + long firstSurveyHash = PreferenceManager.getDefaultSharedPreferences(context) + .getLong(SURVEY_URL1_HASH_KEY, 0); + + long secondSurveyHash = PreferenceManager.getDefaultSharedPreferences(context) + .getLong(SURVEY_URL2_HASH_KEY, 0); + + return surveyUrl.hashCode() != firstSurveyHash && surveyUrl.hashCode() != secondSurveyHash; + } +} diff --git a/catroid/src/main/java/org/catrobat/catroid/common/defaultprojectcreators/ArDroneProjectCreator.java b/catroid/src/main/java/org/catrobat/catroid/common/defaultprojectcreators/ArDroneProjectCreator.java deleted file mode 100644 index 246bf48d3f1..00000000000 --- a/catroid/src/main/java/org/catrobat/catroid/common/defaultprojectcreators/ArDroneProjectCreator.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team - * () - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * An additional term exception under section 7 of the GNU Affero - * General Public License, version 3, is available at - * http://developer.catrobat.org/license_additional_term - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.catrobat.catroid.common.defaultprojectcreators; - -import android.content.Context; -import android.graphics.BitmapFactory; - -import org.catrobat.catroid.R; -import org.catrobat.catroid.common.LookData; -import org.catrobat.catroid.content.Project; -import org.catrobat.catroid.content.Scene; -import org.catrobat.catroid.content.Script; -import org.catrobat.catroid.content.Sprite; -import org.catrobat.catroid.content.StartScript; -import org.catrobat.catroid.content.WhenScript; -import org.catrobat.catroid.content.bricks.Brick; -import org.catrobat.catroid.content.bricks.DroneEmergencyBrick; -import org.catrobat.catroid.content.bricks.DroneFlipBrick; -import org.catrobat.catroid.content.bricks.DroneMoveBackwardBrick; -import org.catrobat.catroid.content.bricks.DroneMoveDownBrick; -import org.catrobat.catroid.content.bricks.DroneMoveForwardBrick; -import org.catrobat.catroid.content.bricks.DroneMoveLeftBrick; -import org.catrobat.catroid.content.bricks.DroneMoveRightBrick; -import org.catrobat.catroid.content.bricks.DroneMoveUpBrick; -import org.catrobat.catroid.content.bricks.DroneSwitchCameraBrick; -import org.catrobat.catroid.content.bricks.DroneTakeOffLandBrick; -import org.catrobat.catroid.content.bricks.DroneTurnLeftBrick; -import org.catrobat.catroid.content.bricks.DroneTurnRightBrick; -import org.catrobat.catroid.content.bricks.PlaceAtBrick; -import org.catrobat.catroid.content.bricks.SetLookBrick; -import org.catrobat.catroid.content.bricks.SetSizeToBrick; -import org.catrobat.catroid.content.bricks.TurnLeftBrick; -import org.catrobat.catroid.formulaeditor.Formula; -import org.catrobat.catroid.io.ResourceImporter; -import org.catrobat.catroid.io.XstreamSerializer; -import org.catrobat.catroid.utils.ImageEditing; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; - -import static org.catrobat.catroid.common.Constants.DEFAULT_IMAGE_EXTENSION; -import static org.catrobat.catroid.common.Constants.IMAGE_DIRECTORY_NAME; -import static org.catrobat.catroid.common.ScreenValues.SCREEN_HEIGHT; -import static org.catrobat.catroid.common.ScreenValues.SCREEN_WIDTH; - -public class ArDroneProjectCreator extends ProjectCreator { - - public ArDroneProjectCreator() { - defaultProjectNameResourceId = R.string.default_drone_project_name; - } - - @Override - public Project createDefaultProject(String name, Context context, boolean landscapeMode) throws IOException { - Project project = new Project(context, name, landscapeMode); - - if (project.getDirectory().exists()) { - throw new IOException("Cannot create new project at " - + project.getDirectory().getAbsolutePath() - + ", directory already exists."); - } - - XstreamSerializer.getInstance().saveProject(project); - - if (!project.getDirectory().isDirectory()) { - throw new FileNotFoundException("Cannot create project at " + project.getDirectory().getAbsolutePath()); - } - - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeResource(context.getResources(), R.drawable.drone_project_background, options); - - backgroundImageScaleFactor = ImageEditing.calculateScaleFactor( - options.outWidth, - options.outHeight, - SCREEN_WIDTH, - SCREEN_HEIGHT); - - Scene scene = project.getDefaultScene(); - - File imageDir = new File(scene.getDirectory(), IMAGE_DIRECTORY_NAME); - String imageFileName = "img" + DEFAULT_IMAGE_EXTENSION; - - File backgroundFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.ic_video, - imageDir, - imageFileName, - backgroundImageScaleFactor); - - Sprite background = scene.getSpriteList().get(0); - background.getLookList() - .add(new LookData(context.getString(R.string.add_look_drone_video), backgroundFile)); - - Script script = new StartScript(); - SetLookBrick setLookBrick = new SetLookBrick(); - setLookBrick.setLook(background.getLookList().get(0)); - background.addScript(script); - - script = new StartScript(); - script.addBrick(new TurnLeftBrick(new Formula(90d))); - script.addBrick(new SetSizeToBrick(new Formula(100.0d))); - background.addScript(script); - - script = new WhenScript(); - script.addBrick(new DroneSwitchCameraBrick()); - background.addScript(script); - - String spriteName = context.getString(R.string.default_drone_project_sprites_takeoff); - File imageFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_drone_project_orange_takeoff_2, - imageDir, - imageFileName, - backgroundImageScaleFactor); - - scene.addSprite(createDroneSprite(spriteName, - -280, -200, imageFile, new DroneTakeOffLandBrick())); - - String upSpriteName = context.getString(R.string.default_drone_project_sprites_up); - File upFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_drone_project_orange_arrow_up, - imageDir, - imageFileName, - backgroundImageScaleFactor); - - scene.addSprite(createDroneSprite(upSpriteName, - -25, 335, upFile, new DroneMoveUpBrick(2000, 20))); - - String downSpriteName = context.getString(R.string.default_drone_project_sprites_down); - File downFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_drone_project_orange_arrow_down, - imageDir, - imageFileName, - backgroundImageScaleFactor); - - scene.addSprite(createDroneSprite(downSpriteName, - 225, 335, downFile, new DroneMoveDownBrick(2000, 20))); - - String forwardSpriteName = context.getString(R.string.default_drone_project_sprites_forward); - File forwardFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_drone_project_orange_go_forward, - imageDir, - imageFileName, - backgroundImageScaleFactor); - - scene.addSprite(createDroneSprite(forwardSpriteName, - -25, -335, forwardFile, new DroneMoveForwardBrick(2000, 20))); - - String backwardSpriteName = context.getString(R.string.default_drone_project_sprites_back); - File backwardFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_drone_project_orange_go_back, - imageDir, - imageFileName, - backgroundImageScaleFactor); - - scene.addSprite(createDroneSprite(backwardSpriteName, - 225, -335, backwardFile, new DroneMoveBackwardBrick(2000, 20))); - - String leftSpriteName = context.getString(R.string.default_drone_project_sprites_left); - File leftFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_drone_project_orange_go_left, - imageDir, - imageFileName, - backgroundImageScaleFactor); - - scene.addSprite(createDroneSprite(leftSpriteName, - 100, -475, leftFile, new DroneMoveLeftBrick(2000, 20))); - - String rightSpriteName = context.getString(R.string.default_drone_project_sprites_right); - File rightFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_drone_project_orange_go_right, - imageDir, - imageFileName, - backgroundImageScaleFactor); - - scene.addSprite(createDroneSprite(rightSpriteName, - 100, -200, rightFile, new DroneMoveRightBrick(2000, 20))); - - String turnLeftSpriteName = context.getString(R.string.default_drone_project_sprites_turn_left); - File turnLeftFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_drone_project_orange_turn_left, - imageDir, - imageFileName, - backgroundImageScaleFactor); - - scene.addSprite(createDroneSprite(turnLeftSpriteName, - 100, 200, turnLeftFile, new DroneTurnLeftBrick(2000, 20))); - - String turnRightSpriteName = context.getString(R.string.default_drone_project_sprites_turn_right); - File turnRightFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_drone_project_orange_turn_right, - imageDir, - imageFileName, - backgroundImageScaleFactor); - - scene.addSprite(createDroneSprite(turnRightSpriteName, - 100, 475, turnRightFile, new DroneTurnRightBrick(2000, 20))); - - String flipSpriteName = context.getString(R.string.default_drone_project_sprites_flip); - File flipFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_drone_project_orange_flip, - imageDir, - imageFileName, - backgroundImageScaleFactor); - - scene.addSprite(createDroneSprite(flipSpriteName, - -280, 200, flipFile, new DroneFlipBrick())); - - String emergencySpriteName = context.getString(R.string.default_drone_project_sprites_emergency); - File emergencyFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_drone_project_orange_go_emergency, - imageDir, - imageFileName, - backgroundImageScaleFactor); - - scene.addSprite(createDroneSprite(emergencySpriteName, - -280, 0, emergencyFile, new DroneEmergencyBrick())); - - XstreamSerializer.getInstance().saveProject(project); - return project; - } - - private Sprite createDroneSprite(String spriteName, int xPosition, int yPosition, File lookFile, Brick droneBrick) { - Sprite sprite = new Sprite(spriteName); - sprite.getLookList() - .add(new LookData(spriteName, lookFile)); - - Script script = new WhenScript(); - script.addBrick(droneBrick); - sprite.addScript(script); - - script = new StartScript(); - script.addBrick(new PlaceAtBrick( - calculateValueRelativeToScaledBackground(xPosition), - calculateValueRelativeToScaledBackground(yPosition))); - - script.addBrick(new SetSizeToBrick(new Formula(50.0d))); - script.addBrick(new TurnLeftBrick(new Formula(90d))); - sprite.addScript(script); - - return sprite; - } -} diff --git a/catroid/src/main/java/org/catrobat/catroid/common/defaultprojectcreators/ChromeCastProjectCreator.java b/catroid/src/main/java/org/catrobat/catroid/common/defaultprojectcreators/ChromeCastProjectCreator.java index 8625ba43ddb..db8b8f0e5ef 100644 --- a/catroid/src/main/java/org/catrobat/catroid/common/defaultprojectcreators/ChromeCastProjectCreator.java +++ b/catroid/src/main/java/org/catrobat/catroid/common/defaultprojectcreators/ChromeCastProjectCreator.java @@ -61,6 +61,7 @@ import static org.catrobat.catroid.common.Constants.DEFAULT_IMAGE_EXTENSION; import static org.catrobat.catroid.common.Constants.DEFAULT_SOUND_EXTENSION; import static org.catrobat.catroid.common.Constants.IMAGE_DIRECTORY_NAME; +import static org.catrobat.catroid.common.Constants.SCREENSHOT_AUTOMATIC_FILE_NAME; import static org.catrobat.catroid.common.Constants.SOUND_DIRECTORY_NAME; import static org.catrobat.catroid.common.ScreenValues.CAST_SCREEN_HEIGHT; import static org.catrobat.catroid.common.ScreenValues.CAST_SCREEN_WIDTH; @@ -69,7 +70,6 @@ import static org.catrobat.catroid.formulaeditor.FormulaElement.ElementType.OPERATOR; import static org.catrobat.catroid.formulaeditor.FormulaElement.ElementType.SENSOR; import static org.catrobat.catroid.formulaeditor.FormulaElement.ElementType.USER_VARIABLE; -import static org.catrobat.catroid.common.Constants.SCREENSHOT_AUTOMATIC_FILE_NAME; public class ChromeCastProjectCreator extends ProjectCreator { diff --git a/catroid/src/main/java/org/catrobat/catroid/common/defaultprojectcreators/DefaultProjectCreator.java b/catroid/src/main/java/org/catrobat/catroid/common/defaultprojectcreators/DefaultProjectCreator.java index a685ef8e38b..29d9d079ddf 100644 --- a/catroid/src/main/java/org/catrobat/catroid/common/defaultprojectcreators/DefaultProjectCreator.java +++ b/catroid/src/main/java/org/catrobat/catroid/common/defaultprojectcreators/DefaultProjectCreator.java @@ -56,13 +56,13 @@ import static org.catrobat.catroid.common.Constants.DEFAULT_IMAGE_EXTENSION; import static org.catrobat.catroid.common.Constants.DEFAULT_SOUND_EXTENSION; import static org.catrobat.catroid.common.Constants.IMAGE_DIRECTORY_NAME; +import static org.catrobat.catroid.common.Constants.SCREENSHOT_AUTOMATIC_FILE_NAME; import static org.catrobat.catroid.common.Constants.SOUND_DIRECTORY_NAME; import static org.catrobat.catroid.common.ScreenValues.SCREEN_HEIGHT; import static org.catrobat.catroid.common.ScreenValues.SCREEN_WIDTH; import static org.catrobat.catroid.formulaeditor.FormulaElement.ElementType.FUNCTION; import static org.catrobat.catroid.formulaeditor.FormulaElement.ElementType.NUMBER; import static org.catrobat.catroid.formulaeditor.FormulaElement.ElementType.OPERATOR; -import static org.catrobat.catroid.common.Constants.SCREENSHOT_AUTOMATIC_FILE_NAME; public class DefaultProjectCreator extends ProjectCreator { diff --git a/catroid/src/main/java/org/catrobat/catroid/common/defaultprojectcreators/JumpingSumoProjectCreator.java b/catroid/src/main/java/org/catrobat/catroid/common/defaultprojectcreators/JumpingSumoProjectCreator.java deleted file mode 100644 index 8eb740555ea..00000000000 --- a/catroid/src/main/java/org/catrobat/catroid/common/defaultprojectcreators/JumpingSumoProjectCreator.java +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team - * () - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * An additional term exception under section 7 of the GNU Affero - * General Public License, version 3, is available at - * http://developer.catrobat.org/license_additional_term - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.catrobat.catroid.common.defaultprojectcreators; - -import android.content.Context; -import android.graphics.BitmapFactory; - -import org.catrobat.catroid.R; -import org.catrobat.catroid.common.LookData; -import org.catrobat.catroid.content.Project; -import org.catrobat.catroid.content.Scene; -import org.catrobat.catroid.content.Script; -import org.catrobat.catroid.content.Sprite; -import org.catrobat.catroid.content.StartScript; -import org.catrobat.catroid.content.WhenScript; -import org.catrobat.catroid.content.bricks.Brick; -import org.catrobat.catroid.content.bricks.JumpingSumoAnimationsBrick; -import org.catrobat.catroid.content.bricks.JumpingSumoJumpHighBrick; -import org.catrobat.catroid.content.bricks.JumpingSumoJumpLongBrick; -import org.catrobat.catroid.content.bricks.JumpingSumoMoveBackwardBrick; -import org.catrobat.catroid.content.bricks.JumpingSumoMoveForwardBrick; -import org.catrobat.catroid.content.bricks.JumpingSumoNoSoundBrick; -import org.catrobat.catroid.content.bricks.JumpingSumoRotateLeftBrick; -import org.catrobat.catroid.content.bricks.JumpingSumoRotateRightBrick; -import org.catrobat.catroid.content.bricks.JumpingSumoSoundBrick; -import org.catrobat.catroid.content.bricks.JumpingSumoTakingPictureBrick; -import org.catrobat.catroid.content.bricks.JumpingSumoTurnBrick; -import org.catrobat.catroid.content.bricks.PlaceAtBrick; -import org.catrobat.catroid.content.bricks.SetLookBrick; -import org.catrobat.catroid.content.bricks.SetSizeToBrick; -import org.catrobat.catroid.formulaeditor.Formula; -import org.catrobat.catroid.io.ResourceImporter; -import org.catrobat.catroid.io.XstreamSerializer; -import org.catrobat.catroid.ui.fragment.SpriteFactory; -import org.catrobat.catroid.utils.ImageEditing; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; - -import static org.catrobat.catroid.common.BrickValues.JUMPING_SUMO_MOVE_BRICK_DEFAULT_MOVE_POWER_PERCENT; -import static org.catrobat.catroid.common.BrickValues.JUMPING_SUMO_MOVE_BRICK_DEFAULT_TIME_MILLISECONDS; -import static org.catrobat.catroid.common.Constants.DEFAULT_IMAGE_EXTENSION; -import static org.catrobat.catroid.common.Constants.IMAGE_DIRECTORY_NAME; -import static org.catrobat.catroid.common.ScreenValues.SCREEN_HEIGHT; -import static org.catrobat.catroid.common.ScreenValues.SCREEN_WIDTH; -import static org.catrobat.catroid.content.bricks.JumpingSumoAnimationsBrick.Animation; - -public class JumpingSumoProjectCreator extends ProjectCreator { - - private static SpriteFactory spriteFactory = new SpriteFactory(); - - public JumpingSumoProjectCreator() { - defaultProjectNameResourceId = R.string.default_jumping_sumo_project_name; - } - - @Override - public Project createDefaultProject(String name, Context context, boolean landscapeMode) throws IOException { - Project project = new Project(context, name, landscapeMode); - - if (project.getDirectory().exists()) { - throw new IOException("Cannot create new project at " - + project.getDirectory().getAbsolutePath() - + ", directory already exists."); - } - - XstreamSerializer.getInstance().saveProject(project); - - if (!project.getDirectory().isDirectory()) { - throw new FileNotFoundException("Cannot create project at " + project.getDirectory().getAbsolutePath()); - } - - Scene scene = project.getDefaultScene(); - - File sceneDir = scene.getDirectory(); - File imageDir = new File(sceneDir, IMAGE_DIRECTORY_NAME); - String imageFileName = "img" + DEFAULT_IMAGE_EXTENSION; - - double landscapePortraitFactor = 1.63; - - String backgroundName = context.getString(R.string.add_look_jumping_sumo_video); - - SetSizeToBrick setSizeBrick = new SetSizeToBrick(60.0); - - Script whenProjectStartsScript = new StartScript(); - whenProjectStartsScript.addBrick(setSizeBrick); - - Script whenSpriteTappedScript = new WhenScript(); - - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeResource(context.getResources(), R.drawable.drone_project_background, options); - - backgroundImageScaleFactor = ImageEditing.calculateScaleFactor( - options.outWidth, - options.outHeight, - SCREEN_WIDTH, - SCREEN_HEIGHT); - - File backgroundFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.ic_video, - imageDir, - imageFileName, - backgroundImageScaleFactor); - - Sprite sprite = spriteFactory.newInstance(Sprite.class.getSimpleName(), backgroundName); - - LookData backgroundLookData = new LookData(backgroundName, backgroundFile); - sprite.getLookList().add(backgroundLookData); - - Sprite backgroundSprite = scene.getSpriteList().get(0); - - backgroundSprite.getLookList().add(backgroundLookData); - Script backgroundStartScript = new StartScript(); - - SetLookBrick setLookBrick = new SetLookBrick(); - setLookBrick.setLook(backgroundLookData); - backgroundStartScript.addBrick(setLookBrick); - - backgroundSprite.addScript(backgroundStartScript); - backgroundSprite.addScript(whenProjectStartsScript); - backgroundSprite.addScript(whenSpriteTappedScript); - - double iconImageScaleFactor = 1.8; - - String forwardName = context.getString(R.string.default_jumping_sumo_project_sprites_forward); - File forwardFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_jumping_sumo_project_forward, - imageDir, - imageFileName, - iconImageScaleFactor); - - scene.addSprite(createDroneSprite(forwardName, - (int) (-350 / landscapePortraitFactor), - (int) (150 / landscapePortraitFactor), - forwardFile, - new JumpingSumoMoveForwardBrick( - JUMPING_SUMO_MOVE_BRICK_DEFAULT_TIME_MILLISECONDS, - JUMPING_SUMO_MOVE_BRICK_DEFAULT_MOVE_POWER_PERCENT))); - - String backwardName = context.getString(R.string.default_jumping_sumo_project_sprites_backward); - File backwardFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_jumping_sumo_project_backward, imageDir, - imageFileName, - iconImageScaleFactor); - - scene.addSprite(createDroneSprite(backwardName, - (int) (-350 / landscapePortraitFactor), - (int) (-150 / landscapePortraitFactor), - backwardFile, - new JumpingSumoMoveBackwardBrick( - JUMPING_SUMO_MOVE_BRICK_DEFAULT_TIME_MILLISECONDS, - JUMPING_SUMO_MOVE_BRICK_DEFAULT_MOVE_POWER_PERCENT))); - - String animationName = context.getString(R.string.default_jumping_sumo_project_sprites_animation); - File animationFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_jumping_sumo_project_animations, - imageDir, - imageFileName, - 0.75); - - scene.addSprite(createDroneSprite(animationName, - 0, - (int) (325 / landscapePortraitFactor), - animationFile, - new JumpingSumoAnimationsBrick(Animation.SPIN))); - - String soundName = context.getString(R.string.default_jumping_sumo_project_sprites_sound); - File soundFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_jumping_sumo_project_sound, - imageDir, - imageFileName, - iconImageScaleFactor); - - scene.addSprite(createDroneSprite(soundName, - (int) (250 / landscapePortraitFactor), - (int) (325 / landscapePortraitFactor), soundFile, new JumpingSumoSoundBrick())); - - String noSoundName = context.getString(R.string.default_jumping_sumo_project_sprites_no_sound); - File noSoundFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_jumping_sumo_project_sound_off, - imageDir, - imageFileName, - iconImageScaleFactor); - - scene.addSprite(createDroneSprite(noSoundName, - (int) (375 / landscapePortraitFactor), - (int) (325 / landscapePortraitFactor), - noSoundFile, - new JumpingSumoNoSoundBrick())); - - String jumpLongName = context.getString(R.string.default_jumping_sumo_project_sprites_jump_long); - File jumpLongFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_jumping_sumo_project_jump_long, - imageDir, - imageFileName, - iconImageScaleFactor); - - scene.addSprite(createDroneSprite(jumpLongName, - (int) (500 / landscapePortraitFactor), - (int) (-100 / landscapePortraitFactor), - jumpLongFile, - new JumpingSumoJumpLongBrick())); - - String jumpHighName = context.getString(R.string.default_jumping_sumo_project_sprites_jump_high); - File jumpHighFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_jumping_sumo_project_jump_high, - imageDir, - imageFileName, - iconImageScaleFactor); - - scene.addSprite(createDroneSprite(jumpHighName, - (int) (500 / landscapePortraitFactor), - (int) (50 / landscapePortraitFactor), jumpHighFile, - new JumpingSumoJumpHighBrick())); - - String turnLeftName = context.getString(R.string.default_jumping_sumo_project_sprites_turn_left); - File turnLeftFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_jumping_sumo_project_left, - imageDir, - imageFileName, - iconImageScaleFactor); - - scene.addSprite(createDroneSprite(turnLeftName, - (int) (-500 / landscapePortraitFactor), - 0, - turnLeftFile, - new JumpingSumoRotateLeftBrick(new Formula(90.0f)))); - - String turnRightName = context.getString(R.string.default_jumping_sumo_project_sprites_turn_right); - File turnRightFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_jumping_sumo_project_right, - imageDir, - imageFileName, - iconImageScaleFactor); - - scene.addSprite(createDroneSprite(turnRightName, - (int) (-200 / landscapePortraitFactor), - 0, - turnRightFile, - new JumpingSumoRotateRightBrick(new Formula(90.0f)))); - - String flipName = context.getString(R.string.default_jumping_sumo_project_sprites_flip); - File flipFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_jumping_sumo_project_flip, - imageDir, - imageFileName, - iconImageScaleFactor); - - scene.addSprite(createDroneSprite(flipName, - (int) (500 / landscapePortraitFactor), - (int) (-250 / landscapePortraitFactor), - flipFile, - new JumpingSumoTurnBrick())); - - String pictureName = context.getString(R.string.default_jumping_sumo_project_sprites_picture); - File pictureFile = ResourceImporter.createImageFileFromResourcesInDirectory(context.getResources(), - R.drawable.default_jumping_sumo_project_camera, - imageDir, - imageFileName, - iconImageScaleFactor); - - scene.addSprite(createDroneSprite(pictureName, - (int) (500 / landscapePortraitFactor), - (int) (325 / landscapePortraitFactor), - pictureFile, - new JumpingSumoTakingPictureBrick())); - - XstreamSerializer.getInstance().saveProject(project); - return project; - } - - private Sprite createDroneSprite(String spriteName, int xPosition, int yPosition, File lookFile, Brick droneBrick) { - Sprite sprite = new Sprite(spriteName); - sprite.getLookList() - .add(new LookData(spriteName, lookFile)); - - Script script = new WhenScript(); - script.addBrick(droneBrick); - sprite.addScript(script); - - script = new StartScript(); - script.addBrick(new PlaceAtBrick( - calculateValueRelativeToScaledBackground(xPosition), - calculateValueRelativeToScaledBackground(yPosition))); - - script.addBrick(new SetSizeToBrick(new Formula(40.0d))); - sprite.addScript(script); - - return sprite; - } -} diff --git a/catroid/src/main/java/org/catrobat/catroid/content/ActionFactory.java b/catroid/src/main/java/org/catrobat/catroid/content/ActionFactory.java index 9200091d024..5e053f658eb 100644 --- a/catroid/src/main/java/org/catrobat/catroid/content/ActionFactory.java +++ b/catroid/src/main/java/org/catrobat/catroid/content/ActionFactory.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -22,10 +22,9 @@ */ package org.catrobat.catroid.content; -import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.scenes.scene2d.Action; import com.badlogic.gdx.scenes.scene2d.actions.Actions; -import com.parrot.freeflight.drone.DroneProxy.ARDRONE_LED_ANIMATION; +import com.badlogic.gdx.scenes.scene2d.actions.SequenceAction; import org.catrobat.catroid.ProjectManager; import org.catrobat.catroid.common.BrickValues; @@ -44,6 +43,7 @@ import org.catrobat.catroid.content.actions.ChangeBrightnessByNAction; import org.catrobat.catroid.content.actions.ChangeColorByNAction; import org.catrobat.catroid.content.actions.ChangeSizeByNAction; +import org.catrobat.catroid.content.actions.ChangeTempoByAction; import org.catrobat.catroid.content.actions.ChangeTransparencyByNAction; import org.catrobat.catroid.content.actions.ChangeVariableAction; import org.catrobat.catroid.content.actions.ChangeVolumeByNAction; @@ -55,28 +55,17 @@ import org.catrobat.catroid.content.actions.ClearUserListAction; import org.catrobat.catroid.content.actions.CloneAction; import org.catrobat.catroid.content.actions.ComeToFrontAction; +import org.catrobat.catroid.content.actions.CopyLookAction; import org.catrobat.catroid.content.actions.DeleteItemOfUserListAction; +import org.catrobat.catroid.content.actions.DeleteLookAction; import org.catrobat.catroid.content.actions.DeleteThisCloneAction; -import org.catrobat.catroid.content.actions.DroneEmergencyAction; -import org.catrobat.catroid.content.actions.DroneFlipAction; -import org.catrobat.catroid.content.actions.DroneMoveBackwardAction; -import org.catrobat.catroid.content.actions.DroneMoveDownAction; -import org.catrobat.catroid.content.actions.DroneMoveForwardAction; -import org.catrobat.catroid.content.actions.DroneMoveLeftAction; -import org.catrobat.catroid.content.actions.DroneMoveRightAction; -import org.catrobat.catroid.content.actions.DroneMoveUpAction; -import org.catrobat.catroid.content.actions.DronePlayLedAnimationAction; -import org.catrobat.catroid.content.actions.DroneSwitchCameraAction; -import org.catrobat.catroid.content.actions.DroneTakeoffAndLandAction; -import org.catrobat.catroid.content.actions.DroneTurnLeftAction; -import org.catrobat.catroid.content.actions.DroneTurnLeftWithMagnetometerAction; -import org.catrobat.catroid.content.actions.DroneTurnRightAction; -import org.catrobat.catroid.content.actions.DroneTurnRightWithMagnetometerAction; +import org.catrobat.catroid.content.actions.EditLookAction; import org.catrobat.catroid.content.actions.EventAction; import org.catrobat.catroid.content.actions.FinishStageAction; import org.catrobat.catroid.content.actions.FlashAction; import org.catrobat.catroid.content.actions.ForItemInUserListAction; import org.catrobat.catroid.content.actions.ForVariableFromToAction; +import org.catrobat.catroid.content.actions.GlideToPhysicsAction; import org.catrobat.catroid.content.actions.GoNStepsBackAction; import org.catrobat.catroid.content.actions.GoToOtherSpritePositionAction; import org.catrobat.catroid.content.actions.GoToRandomPositionAction; @@ -84,17 +73,6 @@ import org.catrobat.catroid.content.actions.HideTextAction; import org.catrobat.catroid.content.actions.IfLogicAction; import org.catrobat.catroid.content.actions.InsertItemIntoUserListAction; -import org.catrobat.catroid.content.actions.JumpingSumoAnimationAction; -import org.catrobat.catroid.content.actions.JumpingSumoJumpHighAction; -import org.catrobat.catroid.content.actions.JumpingSumoJumpLongAction; -import org.catrobat.catroid.content.actions.JumpingSumoMoveBackwardAction; -import org.catrobat.catroid.content.actions.JumpingSumoMoveForwardAction; -import org.catrobat.catroid.content.actions.JumpingSumoNoSoundAction; -import org.catrobat.catroid.content.actions.JumpingSumoRotateLeftAction; -import org.catrobat.catroid.content.actions.JumpingSumoRotateRightAction; -import org.catrobat.catroid.content.actions.JumpingSumoSoundAction; -import org.catrobat.catroid.content.actions.JumpingSumoTakingPictureAction; -import org.catrobat.catroid.content.actions.JumpingSumoTurnAction; import org.catrobat.catroid.content.actions.LegoEv3MotorMoveAction; import org.catrobat.catroid.content.actions.LegoEv3MotorStopAction; import org.catrobat.catroid.content.actions.LegoEv3MotorTurnAngleAction; @@ -106,6 +84,8 @@ import org.catrobat.catroid.content.actions.LegoNxtPlayToneAction; import org.catrobat.catroid.content.actions.LookRequestAction; import org.catrobat.catroid.content.actions.MoveNStepsAction; +import org.catrobat.catroid.content.actions.OpenUrlAction; +import org.catrobat.catroid.content.actions.PaintNewLookAction; import org.catrobat.catroid.content.actions.ParameterizedAssertAction; import org.catrobat.catroid.content.actions.PauseForBeatsAction; import org.catrobat.catroid.content.actions.PenDownAction; @@ -116,6 +96,8 @@ import org.catrobat.catroid.content.actions.PhiroPlayToneAction; import org.catrobat.catroid.content.actions.PhiroRGBLightAction; import org.catrobat.catroid.content.actions.PhiroSensorAction; +import org.catrobat.catroid.content.actions.PlayDrumForBeatsAction; +import org.catrobat.catroid.content.actions.PlayNoteForBeatsAction; import org.catrobat.catroid.content.actions.PlaySoundAction; import org.catrobat.catroid.content.actions.PointInDirectionAction; import org.catrobat.catroid.content.actions.PointToAction; @@ -129,6 +111,8 @@ import org.catrobat.catroid.content.actions.RepeatParameterizedAction; import org.catrobat.catroid.content.actions.RepeatUntilAction; import org.catrobat.catroid.content.actions.ReplaceItemInUserListAction; +import org.catrobat.catroid.content.actions.ReportAction; +import org.catrobat.catroid.content.actions.ResetTimerAction; import org.catrobat.catroid.content.actions.RunningStitchAction; import org.catrobat.catroid.content.actions.SceneStartAction; import org.catrobat.catroid.content.actions.SceneTransitionAction; @@ -154,6 +138,7 @@ import org.catrobat.catroid.content.actions.SetVolumeToAction; import org.catrobat.catroid.content.actions.SetXAction; import org.catrobat.catroid.content.actions.SetYAction; +import org.catrobat.catroid.content.actions.SewUpAction; import org.catrobat.catroid.content.actions.ShowTextAction; import org.catrobat.catroid.content.actions.ShowTextColorSizeAlignmentAction; import org.catrobat.catroid.content.actions.SpeakAction; @@ -172,6 +157,7 @@ import org.catrobat.catroid.content.actions.TripleStitchAction; import org.catrobat.catroid.content.actions.TurnLeftAction; import org.catrobat.catroid.content.actions.TurnRightAction; +import org.catrobat.catroid.content.actions.UserDefinedBrickAction; import org.catrobat.catroid.content.actions.VibrateAction; import org.catrobat.catroid.content.actions.WaitAction; import org.catrobat.catroid.content.actions.WaitForBubbleBrickAction; @@ -186,8 +172,6 @@ import org.catrobat.catroid.content.actions.ZigZagStitchAction; import org.catrobat.catroid.content.actions.conditional.GlideToAction; import org.catrobat.catroid.content.actions.conditional.IfOnEdgeBounceAction; -import org.catrobat.catroid.content.bricks.JumpingSumoAnimationsBrick; -import org.catrobat.catroid.content.bricks.JumpingSumoSoundBrick; import org.catrobat.catroid.content.bricks.LegoEv3MotorMoveBrick; import org.catrobat.catroid.content.bricks.LegoEv3MotorStopBrick; import org.catrobat.catroid.content.bricks.LegoEv3MotorTurnAngleBrick; @@ -200,18 +184,35 @@ import org.catrobat.catroid.content.bricks.PhiroMotorStopBrick; import org.catrobat.catroid.content.bricks.PhiroPlayToneBrick; import org.catrobat.catroid.content.bricks.PhiroRGBLightBrick; +import org.catrobat.catroid.content.bricks.brickspinner.PickableDrum; import org.catrobat.catroid.content.bricks.brickspinner.PickableMusicalInstrument; import org.catrobat.catroid.formulaeditor.Formula; import org.catrobat.catroid.formulaeditor.UserList; import org.catrobat.catroid.formulaeditor.UserVariable; +import org.catrobat.catroid.physics.PhysicsLook; import org.catrobat.catroid.physics.PhysicsObject; +import org.catrobat.catroid.userbrick.UserDefinedBrickInput; import java.util.List; +import java.util.UUID; import kotlin.Pair; public class ActionFactory extends Actions { + public EventAction createUserBrickAction(Sprite sprite, SequenceAction sequence, + List userDefinedBrickInputs, UUID userDefinedBrickID) { + UserDefinedBrickAction action = action(UserDefinedBrickAction.class); + + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); + action.setInputs(userDefinedBrickInputs); + action.setUserDefinedBrickID(userDefinedBrickID); + action.setSprite(sprite); + action.setWait(true); + return action; + } + public EventAction createBroadcastAction(String broadcastMessage, boolean wait) { BroadcastAction action = action(BroadcastAction.class); action.setBroadcastMessage(broadcastMessage); @@ -219,73 +220,87 @@ public EventAction createBroadcastAction(String broadcastMessage, boolean wait) return action; } - public Action createWaitAction(Sprite sprite, Formula delay) { + public Action createWaitAction(Sprite sprite, SequenceAction sequence, Formula delay) { WaitAction action = action(WaitAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setDelay(delay); return action; } - public Action createWaitForSoundAction(Sprite sprite, Formula delay, String soundFilePath) { + public Action createWaitForSoundAction(Sprite sprite, SequenceAction sequence, Formula delay, + String soundFilePath) { WaitForSoundAction action = action(WaitForSoundAction.class); action.setSoundFilePath(soundFilePath); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setDelay(delay); return action; } - public Action createWaitForBubbleBrickAction(Sprite sprite, Formula delay) { + public Action createWaitForBubbleBrickAction(Sprite sprite, SequenceAction sequence, Formula delay) { WaitForBubbleBrickAction action = Actions.action(WaitForBubbleBrickAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setDelay(delay); return action; } - public Action createChangeBrightnessByNAction(Sprite sprite, Formula changeBrightness) { + public Action createChangeBrightnessByNAction(Sprite sprite, SequenceAction sequence, + Formula changeBrightness) { ChangeBrightnessByNAction action = Actions.action(ChangeBrightnessByNAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setBrightness(changeBrightness); return action; } - public Action createChangeColorByNAction(Sprite sprite, Formula changeColor) { + public Action createChangeColorByNAction(Sprite sprite, SequenceAction sequence, + Formula changeColor) { ChangeColorByNAction action = Actions.action(ChangeColorByNAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setColor(changeColor); return action; } - public Action createChangeTransparencyByNAction(Sprite sprite, Formula transparency) { + public Action createChangeTransparencyByNAction(Sprite sprite, SequenceAction sequence, + Formula transparency) { ChangeTransparencyByNAction action = Actions.action(ChangeTransparencyByNAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setTransparency(transparency); return action; } - public Action createChangeSizeByNAction(Sprite sprite, Formula size) { + public Action createChangeSizeByNAction(Sprite sprite, SequenceAction sequence, Formula size) { ChangeSizeByNAction action = Actions.action(ChangeSizeByNAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setSize(size); return action; } - public Action createChangeVolumeByNAction(Sprite sprite, Formula volume) { + public Action createChangeVolumeByNAction(Sprite sprite, SequenceAction sequence, Formula volume) { ChangeVolumeByNAction action = Actions.action(ChangeVolumeByNAction.class); action.setVolume(volume); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); return action; } - public Action createChangeXByNAction(Sprite sprite, Formula xMovement) { + public Action createChangeXByNAction(Sprite sprite, SequenceAction sequence, Formula xMovement) { ChangeXByNAction action = Actions.action(ChangeXByNAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setxMovement(xMovement); return action; } - public Action createChangeYByNAction(Sprite sprite, Formula yMovement) { + public Action createChangeYByNAction(Sprite sprite, SequenceAction sequence, Formula yMovement) { ChangeYByNAction action = Actions.action(ChangeYByNAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setyMovement(yMovement); return action; } @@ -309,29 +324,23 @@ public Action createComeToFrontAction(Sprite sprite) { return action; } - public Action createGlideToAction(Sprite sprite, Formula x, Formula y, Formula duration) { + public Action createGlideToAction(Sprite sprite, SequenceAction sequence, Formula x, Formula y, + Formula duration) { GlideToAction action = Actions.action(GlideToAction.class); action.setPosition(x, y); action.setDuration(duration); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); return action; } - public Action createGlideToAction(Sprite sprite, Formula x, Formula y, Formula duration, Interpolation interpolation) { - GlideToAction action = Actions.action(GlideToAction.class); - action.setPosition(x, y); - action.setDuration(duration); - action.setInterpolation(interpolation); - action.setSprite(sprite); - return action; - } - - public Action createPlaceAtAction(Sprite sprite, Formula x, Formula y) { + public Action createPlaceAtAction(Sprite sprite, SequenceAction sequence, Formula x, Formula y) { GlideToAction action = Actions.action(GlideToAction.class); action.setPosition(x, y); action.setDuration(0); action.setInterpolation(null); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); return action; } @@ -356,9 +365,10 @@ public Action createGoToAction(Sprite sprite, Sprite destinationSprite, int spin } } - public Action createGoNStepsBackAction(Sprite sprite, Formula steps) { + public Action createGoNStepsBackAction(Sprite sprite, SequenceAction sequence, Formula steps) { GoNStepsBackAction action = Actions.action(GoNStepsBackAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setSteps(steps); return action; } @@ -376,10 +386,12 @@ public Action createIfOnEdgeBounceAction(Sprite sprite) { return action; } - public Action createLegoNxtMotorMoveAction(Sprite sprite, LegoNxtMotorMoveBrick.Motor motorEnum, Formula speed) { + public Action createLegoNxtMotorMoveAction(Sprite sprite, SequenceAction sequence, + LegoNxtMotorMoveBrick.Motor motorEnum, Formula speed) { LegoNxtMotorMoveAction action = Actions.action(LegoNxtMotorMoveAction.class); action.setMotorEnum(motorEnum); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setSpeed(speed); return action; } @@ -390,27 +402,31 @@ public Action createLegoNxtMotorStopAction(LegoNxtMotorStopBrick.Motor motorEnum return action; } - public Action createLegoNxtMotorTurnAngleAction(Sprite sprite, + public Action createLegoNxtMotorTurnAngleAction(Sprite sprite, SequenceAction sequence, LegoNxtMotorTurnAngleBrick.Motor motorEnum, Formula degrees) { LegoNxtMotorTurnAngleAction action = Actions.action(LegoNxtMotorTurnAngleAction.class); action.setMotorEnum(motorEnum); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setDegrees(degrees); return action; } - public Action createLegoNxtPlayToneAction(Sprite sprite, Formula hertz, Formula durationInSeconds) { + public Action createLegoNxtPlayToneAction(Sprite sprite, SequenceAction sequence, Formula hertz, + Formula durationInSeconds) { LegoNxtPlayToneAction action = Actions.action(LegoNxtPlayToneAction.class); action.setHertz(hertz); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setDurationInSeconds(durationInSeconds); return action; } - public Action createLegoEv3SingleMotorMoveAction(Sprite sprite, + public Action createLegoEv3SingleMotorMoveAction(Sprite sprite, SequenceAction sequence, LegoEv3MotorMoveBrick.Motor motorEnum, Formula speed) { LegoEv3MotorMoveAction action = action(LegoEv3MotorMoveAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setMotorEnum(motorEnum); action.setSpeed(speed); return action; @@ -428,56 +444,62 @@ public Action createLegoEv3SetLedAction(LegoEv3SetLedBrick.LedStatus ledStatusEn return action; } - public Action createLegoEv3PlayToneAction(Sprite sprite, Formula hertz, Formula - durationInSeconds, Formula volumeInPercent) { + public Action createLegoEv3PlayToneAction(Sprite sprite, SequenceAction sequence, + Formula hertz, Formula durationInSeconds, Formula volumeInPercent) { LegoEv3PlayToneAction action = action(LegoEv3PlayToneAction.class); action.setHertz(hertz); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setDurationInSeconds(durationInSeconds); action.setVolumeInPercent(volumeInPercent); return action; } - public Action createLegoEv3MotorTurnAngleAction(Sprite sprite, + public Action createLegoEv3MotorTurnAngleAction(Sprite sprite, SequenceAction sequence, LegoEv3MotorTurnAngleBrick.Motor motorEnum, Formula degrees) { LegoEv3MotorTurnAngleAction action = action(LegoEv3MotorTurnAngleAction.class); action.setMotorEnum(motorEnum); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setDegrees(degrees); return action; } - public Action createPhiroPlayToneActionAction(Sprite sprite, PhiroPlayToneBrick.Tone toneEnum, - Formula duration) { + public Action createPhiroPlayToneActionAction(Sprite sprite, SequenceAction sequence, + PhiroPlayToneBrick.Tone toneEnum, Formula duration) { PhiroPlayToneAction action = action(PhiroPlayToneAction.class); action.setSelectedTone(toneEnum); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setDurationInSeconds(duration); return action; } - public Action createPhiroMotorMoveForwardActionAction(Sprite sprite, PhiroMotorMoveForwardBrick.Motor motorEnum, - Formula speed) { + public Action createPhiroMotorMoveForwardActionAction(Sprite sprite, SequenceAction sequence, + PhiroMotorMoveForwardBrick.Motor motorEnum, Formula speed) { PhiroMotorMoveForwardAction action = action(PhiroMotorMoveForwardAction.class); action.setMotorEnum(motorEnum); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setSpeed(speed); return action; } - public Action createPhiroMotorMoveBackwardActionAction(Sprite sprite, PhiroMotorMoveBackwardBrick.Motor motorEnum, - Formula speed) { + public Action createPhiroMotorMoveBackwardActionAction(Sprite sprite, SequenceAction sequence, + PhiroMotorMoveBackwardBrick.Motor motorEnum, Formula speed) { PhiroMotorMoveBackwardAction action = action(PhiroMotorMoveBackwardAction.class); action.setMotorEnum(motorEnum); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setSpeed(speed); return action; } - public Action createPhiroRgbLedEyeActionAction(Sprite sprite, PhiroRGBLightBrick.Eye eye, - Formula red, Formula green, Formula blue) { + public Action createPhiroRgbLedEyeActionAction(Sprite sprite, SequenceAction sequence, + PhiroRGBLightBrick.Eye eye, Formula red, Formula green, Formula blue) { PhiroRGBLightAction action = action(PhiroRGBLightAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setEyeEnum(eye); action.setRed(red); action.setGreen(green); @@ -485,10 +507,11 @@ public Action createPhiroRgbLedEyeActionAction(Sprite sprite, PhiroRGBLightBrick return action; } - public Action createPhiroSendSelectedSensorAction(Sprite sprite, int sensorNumber, Action ifAction, Action - elseAction) { + public Action createPhiroSendSelectedSensorAction(Sprite sprite, SequenceAction sequence, + int sensorNumber, Action ifAction, Action elseAction) { PhiroSensorAction action = action(PhiroSensorAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setSensor(sensorNumber); action.setIfAction(ifAction); action.setElseAction(elseAction); @@ -501,9 +524,10 @@ public Action createPhiroMotorStopActionAction(PhiroMotorStopBrick.Motor motorEn return action; } - public Action createMoveNStepsAction(Sprite sprite, Formula steps) { + public Action createMoveNStepsAction(Sprite sprite, SequenceAction sequence, Formula steps) { MoveNStepsAction action = Actions.action(MoveNStepsAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setSteps(steps); return action; } @@ -520,16 +544,19 @@ public Action createPenUpAction(Sprite sprite) { return action; } - public Action createSetPenSizeAction(Sprite sprite, Formula penSize) { + public Action createSetPenSizeAction(Sprite sprite, SequenceAction sequence, Formula penSize) { SetPenSizeAction action = Actions.action(SetPenSizeAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setPenSize(penSize); return action; } - public Action createSetPenColorAction(Sprite sprite, Formula red, Formula green, Formula blue) { + public Action createSetPenColorAction(Sprite sprite, SequenceAction sequence, Formula red, + Formula green, Formula blue) { SetPenColorAction action = Actions.action(SetPenColorAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setRed(red); action.setGreen(green); action.setBlue(blue); @@ -560,9 +587,10 @@ public Action createStopSoundAction(Sprite sprite, SoundInfo sound) { return action; } - public Action createPointInDirectionAction(Sprite sprite, Formula degrees) { + public Action createPointInDirectionAction(Sprite sprite, SequenceAction sequence, Formula degrees) { PointInDirectionAction action = Actions.action(PointInDirectionAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setDegreesInUserInterfaceDimensionUnit(degrees); return action; } @@ -586,23 +614,27 @@ public Action createDeleteThisCloneAction(Sprite sprite) { return action; } - public Action createSetBrightnessAction(Sprite sprite, Formula brightness) { + public Action createSetBrightnessAction(Sprite sprite, SequenceAction sequence, Formula brightness) { SetBrightnessAction action = Actions.action(SetBrightnessAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setBrightness(brightness); return action; } - public Action createSetColorAction(Sprite sprite, Formula color) { + public Action createSetColorAction(Sprite sprite, SequenceAction sequence, Formula color) { SetColorAction action = Actions.action(SetColorAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setColor(color); return action; } - public Action createSetTransparencyAction(Sprite sprite, Formula transparency) { + public Action createSetTransparencyAction(Sprite sprite, SequenceAction sequence, + Formula transparency) { SetTransparencyAction action = Actions.action(SetTransparencyAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setTransparency(transparency); return action; } @@ -619,9 +651,11 @@ public Action createSetLookAction(Sprite sprite, LookData lookData, boolean wait return action; } - public Action createSetLookByIndexAction(Sprite sprite, Formula formula) { + public Action createSetLookByIndexAction(Sprite sprite, SequenceAction sequence, Formula formula) { SetLookByIndexAction action = Actions.action(SetLookByIndexAction.class); action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setFormula(formula); return action; } @@ -634,51 +668,81 @@ public Action createSetBackgroundAction(LookData lookData, boolean wait) { return action; } - public Action createSetBackgroundByIndexAction(Sprite sprite, Formula formula, boolean wait) { + public Action createSetBackgroundByIndexAction(Sprite sprite, SequenceAction sequence, + Formula formula, boolean wait) { SetLookByIndexAction action = Actions.action(SetLookByIndexAction.class); action.setSprite(ProjectManager.getInstance().getCurrentlyPlayingScene().getBackgroundSprite()); - action.setScopeSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setFormula(formula); action.setWait(wait); return action; } - public Action createSetNextLookAction(Sprite sprite) { + public Action createSetNextLookAction(Sprite sprite, SequenceAction sequence) { SetNextLookAction action = Actions.action(SetNextLookAction.class); action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); return action; } - public Action createSetPreviousLookAction(Sprite sprite) { + public Action createSetPreviousLookAction(Sprite sprite, SequenceAction sequence) { SetPreviousLookAction action = action(SetPreviousLookAction.class); action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); return action; } - public Action createSetSizeToAction(Sprite sprite, Formula size) { - SetSizeToAction action = Actions.action(SetSizeToAction.class); + public Action createDeleteLookAction(Sprite sprite) { + DeleteLookAction action = Actions.action(DeleteLookAction.class); action.setSprite(sprite); + return action; + } + + public Action createSetSizeToAction(Sprite sprite, SequenceAction sequence, Formula size) { + SetSizeToAction action = Actions.action(SetSizeToAction.class); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setSize(size); return action; } - public Action createSetVolumeToAction(Sprite sprite, Formula volume) { + public Action createGlideToPhysicsAction(Sprite sprite, PhysicsLook physicsLook, + SequenceAction sequence, Formula x, + Formula y, float duration, float delta) { + + GlideToPhysicsAction action = Actions.action(GlideToPhysicsAction.class); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); + action.setPhysicsLook(physicsLook); + action.setPosition(x, y); + action.setDuration(duration); + action.act(delta); + return action; + } + + public Action createSetVolumeToAction(Sprite sprite, SequenceAction sequence, Formula volume) { SetVolumeToAction action = Actions.action(SetVolumeToAction.class); action.setVolume(volume); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); return action; } - public Action createSetXAction(Sprite sprite, Formula x) { + public Action createSetXAction(Sprite sprite, SequenceAction sequence, Formula x) { SetXAction action = Actions.action(SetXAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setX(x); return action; } - public Action createSetYAction(Sprite sprite, Formula y) { + public Action createSetYAction(Sprite sprite, SequenceAction sequence, Formula y) { SetYAction action = Actions.action(SetYAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setY(y); return action; } @@ -690,9 +754,10 @@ public Action createShowAction(Sprite sprite) { return action; } - public Action createSpeakAction(Sprite sprite, Formula text) { + public Action createSpeakAction(Sprite sprite, SequenceAction sequence, Formula text) { SpeakAction action = action(SpeakAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setText(text); return action; } @@ -701,9 +766,20 @@ public Action createStopAllSoundsAction() { return Actions.action(StopAllSoundsAction.class); } - public Action createPauseForBeatsAction(Sprite sprite, Formula beats) { + public Action createPauseForBeatsAction(Sprite sprite, SequenceAction sequence, Formula beats) { PauseForBeatsAction action = action(PauseForBeatsAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); + action.setBeats(beats); + return action; + } + + public Action createPlayNoteForBeatsAction(Sprite sprite, SequenceAction sequence, Formula note, + Formula beats) { + PlayNoteForBeatsAction action = action(PlayNoteForBeatsAction.class); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); + action.setMidiValue(note); action.setBeats(beats); return action; } @@ -714,62 +790,92 @@ public Action createSetInstrumentAction(PickableMusicalInstrument instrument) { return action; } - public Action createSetTempoAction(Sprite sprite, Formula tempo) { + public Action createSetTempoAction(Sprite sprite, SequenceAction sequence, Formula tempo) { SetTempoAction action = action(SetTempoAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setTempo(tempo); return action; } - public Action createTurnLeftAction(Sprite sprite, Formula degrees) { + public Action createChangeTempoAction(Sprite sprite, SequenceAction sequence, Formula tempo) { + ChangeTempoByAction action = action(ChangeTempoByAction.class); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); + action.setTempo(tempo); + return action; + } + + public Action createPlayDrumForBeatsAction(Sprite sprite, SequenceAction sequence, Formula beats, + PickableDrum drum) { + PlayDrumForBeatsAction action = action(PlayDrumForBeatsAction.class); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); + action.setBeats(beats); + action.setDrum(drum); + return action; + } + + public Action createTurnLeftAction(Sprite sprite, SequenceAction sequence, Formula degrees) { TurnLeftAction action = Actions.action(TurnLeftAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setDegrees(degrees); return action; } - public Action createTurnRightAction(Sprite sprite, Formula degrees) { + public Action createTurnRightAction(Sprite sprite, SequenceAction sequence, Formula degrees) { TurnRightAction action = Actions.action(TurnRightAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setDegrees(degrees); return action; } - public Action createChangeVariableAction(Sprite sprite, Formula variableFormula, UserVariable userVariable) { + public Action createChangeVariableAction(Sprite sprite, SequenceAction sequence, Formula variableFormula, UserVariable userVariable) { ChangeVariableAction action = Actions.action(ChangeVariableAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setChangeVariable(variableFormula); action.setUserVariable(userVariable); return action; } - public Action createSetVariableAction(Sprite sprite, Formula variableFormula, UserVariable userVariable) { + public Action createSetVariableAction(Sprite sprite, SequenceAction sequence, Formula variableFormula, + UserVariable userVariable) { SetVariableAction action = Actions.action(SetVariableAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setChangeVariable(variableFormula); action.setUserVariable(userVariable); return action; } - public Action createAskAction(Sprite sprite, Formula questionFormula, UserVariable answerVariable) { + public Action createAskAction(Sprite sprite, SequenceAction sequence, Formula questionFormula, + UserVariable answerVariable) { AskAction action = Actions.action(AskAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setQuestionFormula(questionFormula); action.setAnswerVariable(answerVariable); return action; } - public Action createAskSpeechAction(Sprite sprite, Formula questionFormula, UserVariable answerVariable) { + public Action createAskSpeechAction(Sprite sprite, SequenceAction sequence, Formula questionFormula, + UserVariable answerVariable) { AskSpeechAction action = Actions.action(AskSpeechAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setQuestionFormula(questionFormula); action.setAnswerVariable(answerVariable); return action; } - public Action createDeleteItemOfUserListAction(Sprite sprite, Formula userListFormula, UserList userList) { + public Action createDeleteItemOfUserListAction(Sprite sprite, SequenceAction sequence, + Formula userListFormula, UserList userList) { DeleteItemOfUserListAction action = action(DeleteItemOfUserListAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setFormulaIndexToDelete(userListFormula); action.setUserList(userList); return action; @@ -781,56 +887,69 @@ public Action createClearUserListAction(UserList userList) { return action; } - public Action createAddItemToUserListAction(Sprite sprite, Formula userListFormula, UserList userList) { + public Action createAddItemToUserListAction(Sprite sprite, SequenceAction sequence, + Formula userListFormula, UserList userList) { AddItemToUserListAction action = action(AddItemToUserListAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setFormulaItemToAdd(userListFormula); action.setUserList(userList); return action; } - public Action createInsertItemIntoUserListAction(Sprite sprite, Formula userListFormulaIndexToInsert, + public Action createInsertItemIntoUserListAction(Sprite sprite, SequenceAction sequence, + Formula userListFormulaIndexToInsert, Formula userListFormulaItemToInsert, UserList userList) { InsertItemIntoUserListAction action = action(InsertItemIntoUserListAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setFormulaIndexToInsert(userListFormulaIndexToInsert); action.setFormulaItemToInsert(userListFormulaItemToInsert); action.setUserList(userList); return action; } - public Action createStoreCSVIntoUserListAction(Sprite sprite, Formula userListFormulaColumn, - Formula userListFormulaCSV, UserList userList) { + public Action createStoreCSVIntoUserListAction(Sprite sprite, SequenceAction sequence, + Formula userListFormulaColumn, Formula userListFormulaCSV, UserList userList) { StoreCSVIntoUserListAction action = action(StoreCSVIntoUserListAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setFormulaColumnToExtract(userListFormulaColumn); action.setFormulaCSVData(userListFormulaCSV); action.setUserList(userList); return action; } - public Action createReplaceItemInUserListAction(Sprite sprite, Formula userListFormulaIndexToReplace, + public Action createReplaceItemInUserListAction(Sprite sprite, SequenceAction sequence, + Formula userListFormulaIndexToReplace, Formula userListFormulaItemToInsert, UserList userList) { ReplaceItemInUserListAction action = action(ReplaceItemInUserListAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setFormulaIndexToReplace(userListFormulaIndexToReplace); action.setFormulaItemToInsert(userListFormulaItemToInsert); action.setUserList(userList); return action; } - public Action createThinkSayBubbleAction(Sprite sprite, Formula text, int type) { + public Action createResetTimerAction() { + return Actions.action(ResetTimerAction.class); + } + + public Action createThinkSayBubbleAction(Sprite sprite, SequenceAction sequence, Formula text, int type) { ThinkSayBubbleAction action = action(ThinkSayBubbleAction.class); action.setText(text); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setType(type); return action; } - public Action createThinkSayForBubbleAction(Sprite sprite, Formula text, int type) { + public Action createThinkSayForBubbleAction(Sprite sprite, SequenceAction sequence, Formula text, int type) { ThinkSayBubbleAction action = action(ThinkSayBubbleAction.class); action.setText(text); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setType(type); return action; } @@ -849,69 +968,86 @@ public Action createSceneStartAction(String sceneName, Sprite sprite) { return action; } - public Action createIfLogicAction(Sprite sprite, Formula condition, Action ifAction, Action elseAction) { + public Action createIfLogicAction(Sprite sprite, SequenceAction sequence, Formula condition, + Action ifAction, Action elseAction) { IfLogicAction action = Actions.action(IfLogicAction.class); action.setIfAction(ifAction); action.setIfCondition(condition); action.setElseAction(elseAction); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); return action; } - public Action createRepeatAction(Sprite sprite, Formula count, Action repeatedAction) { + public Action createRepeatAction(Sprite sprite, SequenceAction sequence, Formula count, Action repeatedAction, + boolean isLoopDelay) { RepeatAction action = Actions.action(RepeatAction.class); action.setRepeatCount(count); action.setAction(repeatedAction); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); + action.setLoopDelay(isLoopDelay); return action; } - public Action createForVariableFromToAction(Sprite sprite, UserVariable controlVariable, - Formula from, Formula to, Action repeatedAction) { + public Action createForVariableFromToAction(Sprite sprite, + SequenceAction sequence, UserVariable controlVariable, + Formula from, Formula to, Action repeatedAction, boolean isLoopDelay) { ForVariableFromToAction action = Actions.action(ForVariableFromToAction.class); action.setRange(from, to); action.setControlVariable(controlVariable); action.setAction(repeatedAction); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); + action.setLoopDelay(isLoopDelay); return action; } public Action createForItemInUserListAction(UserList userList, - UserVariable userVariable, Action repeatedAction) { + UserVariable userVariable, Action repeatedAction, boolean isLoopDelay) { ForItemInUserListAction action = Actions.action(ForItemInUserListAction.class); action.setAction(repeatedAction); action.setUserList(userList); action.setCurrentItemVariable(userVariable); + action.setLoopDelay(isLoopDelay); return action; } - public Action createWaitUntilAction(Sprite sprite, Formula condition) { + public Action createWaitUntilAction(Sprite sprite, SequenceAction sequence, Formula condition) { WaitUntilAction action = Actions.action(WaitUntilAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setCondition(condition); return action; } - public Action createRepeatUntilAction(Sprite sprite, Formula condition, Action repeatedAction) { + public Action createRepeatUntilAction(Sprite sprite, SequenceAction sequence, Formula condition, Action repeatedAction, + boolean isLoopDelay) { RepeatUntilAction action = action(RepeatUntilAction.class); action.setRepeatCondition(condition); action.setAction(repeatedAction); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); + action.setLoopDelay(isLoopDelay); return action; } - public Action createDelayAction(Sprite sprite, Formula delay) { + public Action createDelayAction(Sprite sprite, SequenceAction sequence, Formula delay) { WaitAction action = Actions.action(WaitAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setDelay(delay); return action; } - public Action createForeverAction(Sprite sprite, ScriptSequenceAction foreverSequence) { + public Action createForeverAction(Sprite sprite, SequenceAction sequence, ScriptSequenceAction foreverSequence, + boolean isLoopDelay) { RepeatAction action = Actions.action(RepeatAction.class); action.setForeverRepeat(true); action.setAction(foreverSequence); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); + action.setLoopDelay(isLoopDelay); return action; } @@ -921,23 +1057,27 @@ public static Action createStitchAction(Sprite sprite) { return action; } - public Action createRunningStitchAction(Sprite sprite, Formula length) { + public Action createRunningStitchAction(Sprite sprite, SequenceAction sequence, Formula length) { RunningStitchAction action = Actions.action(RunningStitchAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setLength(length); return action; } - public Action createTripleStitchAction(Sprite sprite, Formula steps) { + public Action createTripleStitchAction(Sprite sprite, SequenceAction sequence, Formula steps) { TripleStitchAction action = Actions.action(TripleStitchAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setSteps(steps); return action; } - public Action createZigZagStitchAction(Sprite sprite, Formula length, Formula width) { + public Action createZigZagStitchAction(Sprite sprite, SequenceAction sequence, Formula length, + Formula width) { ZigZagStitchAction action = Actions.action(ZigZagStitchAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setLength(length); action.setWidth(width); return action; @@ -949,31 +1089,43 @@ public static Action createStopRunningStitchAction(Sprite sprite) { return action; } - public Action createWriteEmbroideryToFileAction(Sprite sprite, Formula fileName) { + public Action createWriteEmbroideryToFileAction(Sprite sprite, SequenceAction sequence, + Formula fileName) { WriteEmbroideryToFileAction action = Actions.action(WriteEmbroideryToFileAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setFormula(fileName); return action; } + public Action createSewUpAction(Sprite sprite) { + SewUpAction action = Actions.action(SewUpAction.class); + action.setSprite(sprite); + return action; + } + public static Action createScriptSequenceAction(Script script) { return new ScriptSequenceAction(script); } - public Action createSetBounceFactorAction(Sprite sprite, Formula bounceFactor) { + public Action createSetBounceFactorAction(Sprite sprite, SequenceAction sequence, + Formula bounceFactor) { throw new RuntimeException("No physics action available in non-physics sprite!"); } - public Action createTurnRightSpeedAction(Sprite sprite, Formula degreesPerSecond) { + public Action createTurnRightSpeedAction(Sprite sprite, SequenceAction sequence, + Formula degreesPerSecond) { throw new RuntimeException("No physics action available in non-physics sprite!"); } - public Action createTurnLeftSpeedAction(Sprite sprite, Formula degreesPerSecond) { + public Action createTurnLeftSpeedAction(Sprite sprite, SequenceAction sequence, + Formula degreesPerSecond) { throw new RuntimeException("No physics action available in non-physics sprite!"); } - public Action createSetVelocityAction(Sprite sprite, Formula velocityX, Formula velocityY) { + public Action createSetVelocityAction(Sprite sprite, SequenceAction sequence, Formula velocityX, + Formula velocityY) { throw new RuntimeException("No physics action available in non-physics sprite!"); } @@ -981,210 +1133,51 @@ public Action createSetPhysicsObjectTypeAction(Sprite sprite, PhysicsObject.Type throw new RuntimeException("No physics action available in non-physics sprite!"); } - public Action createSetMassAction(Sprite sprite, Formula mass) { + public Action createSetMassAction(Sprite sprite, SequenceAction sequence, Formula mass) { throw new RuntimeException("No physics action available in non-physics sprite!"); } - public Action createSetGravityAction(Sprite sprite, Formula gravityX, Formula gravityY) { + public Action createSetGravityAction(Sprite sprite, SequenceAction sequence, Formula gravityX, + Formula gravityY) { throw new RuntimeException("No physics action available in non-physics sprite!"); } - public Action createSetFrictionAction(Sprite sprite, Formula friction) { + public Action createSetFrictionAction(Sprite sprite, SequenceAction sequence, + Formula friction) { throw new RuntimeException("No physics action available in non-physics sprite!"); } - public Action createDroneTakeOffAndLandAction() { - return action(DroneTakeoffAndLandAction.class); - } - - public Action createDroneFlipAction() { - return action(DroneFlipAction.class); - } - - public Action createDroneMoveUpAction(Sprite sprite, Formula seconds, Formula powerInPercent) { - DroneMoveUpAction action = action(DroneMoveUpAction.class); - action.setSprite(sprite); - action.setDelay(seconds); - action.setPower(powerInPercent); - return action; - } - - public Action createDroneMoveDownAction(Sprite sprite, Formula seconds, Formula powerInPercent) { - DroneMoveDownAction action = action(DroneMoveDownAction.class); - action.setSprite(sprite); - action.setDelay(seconds); - action.setPower(powerInPercent); - return action; - } - - public Action createDroneMoveLeftAction(Sprite sprite, Formula seconds, Formula powerInPercent) { - DroneMoveLeftAction action = action(DroneMoveLeftAction.class); - action.setSprite(sprite); - action.setDelay(seconds); - action.setPower(powerInPercent); - return action; - } - - public Action createDroneMoveRightAction(Sprite sprite, Formula seconds, Formula powerInPercent) { - DroneMoveRightAction action = action(DroneMoveRightAction.class); - action.setSprite(sprite); - action.setDelay(seconds); - action.setPower(powerInPercent); - return action; - } - - public Action createDroneMoveForwardAction(Sprite sprite, Formula seconds, Formula powerInPercent) { - DroneMoveForwardAction action = action(DroneMoveForwardAction.class); - action.setSprite(sprite); - action.setDelay(seconds); - action.setPower(powerInPercent); - return action; - } - - public Action createDroneMoveBackwardAction(Sprite sprite, Formula seconds, Formula powerInPercent) { - DroneMoveBackwardAction action = action(DroneMoveBackwardAction.class); - action.setSprite(sprite); - action.setDelay(seconds); - action.setPower(powerInPercent); - return action; - } - - public Action createDroneTurnRightAction(Sprite sprite, Formula seconds, Formula powerInPercent) { - DroneTurnRightAction action = action(DroneTurnRightAction.class); - action.setSprite(sprite); - action.setDelay(seconds); - action.setPower(powerInPercent); - return action; - } - - public Action createDroneTurnLeftAction(Sprite sprite, Formula seconds, Formula powerInPercent) { - DroneTurnLeftAction action = action(DroneTurnLeftAction.class); - action.setSprite(sprite); - action.setDelay(seconds); - action.setPower(powerInPercent); - return action; - } - - public Action createDroneTurnLeftMagnetoAction(Sprite sprite, Formula seconds, Formula powerInPercent) { - DroneTurnLeftWithMagnetometerAction action = action(DroneTurnLeftWithMagnetometerAction.class); - action.setSprite(sprite); - action.setDelay(seconds); - action.setPower(powerInPercent); - return action; - } - - public Action createDroneTurnRightMagnetoAction(Sprite sprite, Formula seconds, Formula powerInPercent) { - DroneTurnRightWithMagnetometerAction action = action(DroneTurnRightWithMagnetometerAction.class); - action.setSprite(sprite); - action.setDelay(seconds); - action.setPower(powerInPercent); - return action; - } - - public Action createDronePlayLedAnimationAction(ARDRONE_LED_ANIMATION ledAnimationType) { - DronePlayLedAnimationAction action = action(DronePlayLedAnimationAction.class); - action.setAnimationType(ledAnimationType); - return action; - } - - public Action createDroneSwitchCameraAction() { - return action(DroneSwitchCameraAction.class); - } - - public Action createDroneGoEmergencyAction() { - return action(DroneEmergencyAction.class); - } - - public Action createJumpingSumoMoveForwardAction(Sprite sprite, Formula seconds, Formula powerInPercent) { - JumpingSumoMoveForwardAction action = action(JumpingSumoMoveForwardAction.class); - action.setSprite(sprite); - action.setDelay(seconds); - action.setPower(powerInPercent); - return action; - } - - public Action createJumpingSumoMoveBackwardAction(Sprite sprite, Formula seconds, Formula powerInPercent) { - JumpingSumoMoveBackwardAction action = action(JumpingSumoMoveBackwardAction.class); - action.setSprite(sprite); - action.setDelay(seconds); - action.setPower(powerInPercent); - return action; - } - - public Action createJumpingSumoAnimationAction(JumpingSumoAnimationsBrick.Animation animationType) { - JumpingSumoAnimationAction action = action(JumpingSumoAnimationAction.class); - action.setAnimationType(animationType); - return action; - } - - public Action createJumpingSumoNoSoundAction() { - return action(JumpingSumoNoSoundAction.class); - } - - public Action createJumpingSumoSoundAction(Sprite sprite, JumpingSumoSoundBrick.Sounds soundType, Formula volume) { - JumpingSumoSoundAction action = action(JumpingSumoSoundAction.class); - action.setSoundType(soundType); - action.setSprite(sprite); - action.setVolume(volume); - return action; - } - - public Action createJumpingSumoJumpLongAction() { - return action(JumpingSumoJumpLongAction.class); - } - - public Action createJumpingSumoJumpHighAction() { - return action(JumpingSumoJumpHighAction.class); - } - - public Action createJumpingSumoRotateLeftAction(Sprite sprite, Formula degree) { - JumpingSumoRotateLeftAction action = action(JumpingSumoRotateLeftAction.class); - action.setSprite(sprite); - action.setDegree(degree); - return action; - } - - public Action createJumpingSumoRotateRightAction(Sprite sprite, Formula degree) { - JumpingSumoRotateRightAction action = action(JumpingSumoRotateRightAction.class); - action.setSprite(sprite); - action.setDegree(degree); - return action; - } - - public Action createJumpingSumoTurnAction() { - return action(JumpingSumoTurnAction.class); - } - - public Action createJumpingSumoTakingPictureAction() { - return action(JumpingSumoTakingPictureAction.class); - } - - public Action createSetTextAction(Sprite sprite, Formula x, Formula y, Formula text) { + public Action createSetTextAction(Sprite sprite, SequenceAction sequence, Formula x, Formula y, Formula text) { SetTextAction action = action(SetTextAction.class); action.setPosition(x, y); action.setText(text); action.setDuration(5); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); return action; } - public Action createShowVariableAction(Sprite sprite, Formula xPosition, Formula yPosition, UserVariable userVariable) { + public Action createShowVariableAction(Sprite sprite, SequenceAction sequence, Formula xPosition, + Formula yPosition, UserVariable userVariable) { ShowTextAction action = action(ShowTextAction.class); action.setPosition(xPosition, yPosition); action.setVariableToShow(userVariable); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); return action; } - public Action createShowVariableColorAndSizeAction(Sprite sprite, Formula xPosition, Formula yPosition, - Formula relativeTextSize, Formula color, UserVariable userVariable, int alignment) { + public Action createShowVariableColorAndSizeAction(Sprite sprite, SequenceAction sequence, + Formula xPosition, Formula yPosition, Formula relativeTextSize, Formula color, + UserVariable userVariable, int alignment) { ShowTextColorSizeAlignmentAction action = action(ShowTextColorSizeAlignmentAction.class); action.setPosition(xPosition, yPosition); action.setRelativeTextSize(relativeTextSize); action.setColor(color); action.setVariableToShow(userVariable); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setAlignment(alignment); return action; } @@ -1202,9 +1195,10 @@ public Action createFlashAction(boolean flashOn) { return action; } - public Action createVibrateAction(Sprite sprite, Formula duration) { + public Action createVibrateAction(Sprite sprite, SequenceAction sequence, Formula duration) { VibrateAction action = action(VibrateAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setDuration(duration); return action; } @@ -1227,48 +1221,52 @@ public Action createSetBackCameraAction() { return action; } - public Action createSendDigitalArduinoValueAction(Sprite sprite, Formula pinNumber, - Formula - pinValue) { + public Action createSendDigitalArduinoValueAction(Sprite sprite, SequenceAction sequence, + Formula pinNumber, Formula pinValue) { ArduinoSendDigitalValueAction action = action(ArduinoSendDigitalValueAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setPinNumber(pinNumber); action.setPinValue(pinValue); return action; } - public Action createSendPWMArduinoValueAction(Sprite sprite, Formula pinNumber, Formula - pinValue) { + public Action createSendPWMArduinoValueAction(Sprite sprite, SequenceAction sequence, + Formula pinNumber, Formula pinValue) { ArduinoSendPWMValueAction action = action(ArduinoSendPWMValueAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setPinNumber(pinNumber); action.setPinValue(pinValue); return action; } - public Action createSendDigitalRaspiValueAction(Sprite sprite, Formula pinNumber, - Formula pinValue) { + public Action createSendDigitalRaspiValueAction(Sprite sprite, SequenceAction sequence, + Formula pinNumber, Formula pinValue) { RaspiSendDigitalValueAction action = action(RaspiSendDigitalValueAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setPinNumber(pinNumber); action.setPinValue(pinValue); return action; } - public Action createSendRaspiPwmValueAction(Sprite sprite, Formula pinNumber, Formula - pwmFrequency, Formula pwmPercentage) { + public Action createSendRaspiPwmValueAction(Sprite sprite, SequenceAction sequence, + Formula pinNumber, Formula pwmFrequency, Formula pwmPercentage) { RaspiPwmAction action = action(RaspiPwmAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setPinNumberFormula(pinNumber); action.setPwmFrequencyFormula(pwmFrequency); action.setPwmPercentageFormula(pwmPercentage); return action; } - public Action createRaspiIfLogicActionAction(Sprite sprite, Formula pinNumber, Action ifAction, - Action elseAction) { + public Action createRaspiIfLogicActionAction(Sprite sprite, SequenceAction sequence, + Formula pinNumber, Action ifAction, Action elseAction) { RaspiIfLogicAction action = action(RaspiIfLogicAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setPinNumber(pinNumber); action.setIfAction(ifAction); action.setElseAction(elseAction); @@ -1291,32 +1289,52 @@ public Action createStopScriptAction(int spinnerSelection, Script currentScript, } } - public Action createSetNfcTagAction(Sprite sprite, Formula nfcNdefMessage, int nfcNdefSpinnerSelection) { + public Action createReportAction(Sprite sprite, SequenceAction sequence, Script currentScript, Formula reportFormula) { + if (currentScript instanceof UserDefinedScript) { + ReportAction reportAction = Actions.action(ReportAction.class); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + reportAction.setScope(scope); + reportAction.setCurrentScript(currentScript); + reportAction.setReportFormula(reportFormula); + return reportAction; + } else { + StopThisScriptAction stopThisScriptAction = Actions.action(StopThisScriptAction.class); + stopThisScriptAction.setCurrentScript(currentScript); + return stopThisScriptAction; + } + } + + public Action createSetNfcTagAction(Sprite sprite, SequenceAction sequence, Formula nfcNdefMessage, int nfcNdefSpinnerSelection) { SetNfcTagAction setNfcTagAction = Actions.action(SetNfcTagAction.class); - setNfcTagAction.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + setNfcTagAction.setScope(scope); setNfcTagAction.setNfcTagNdefSpinnerSelection(nfcNdefSpinnerSelection); setNfcTagAction.setNfcNdefMessage(nfcNdefMessage); return setNfcTagAction; } - public Action createAssertEqualsAction(Sprite sprite, Formula actual, Formula expected, String position) { + public Action createAssertEqualsAction(Sprite sprite, SequenceAction sequence, Formula actual, + Formula expected, + String position) { AssertEqualsAction action = action(AssertEqualsAction.class); action.setActualFormula(actual); action.setExpectedFormula(expected); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setPosition(position); return action; } - public Action createAssertUserListsAction(Sprite sprite, UserList actual, UserList expected, + public Action createAssertUserListsAction(Sprite sprite, SequenceAction sequence, UserList actual, UserList expected, String position) { AssertUserListAction action = action(AssertUserListAction.class); action.setActualUserList(actual); action.setExpectedUserList(expected); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setPosition(position); return action; @@ -1324,11 +1342,12 @@ public Action createAssertUserListsAction(Sprite sprite, UserList actual, UserLi public Action createRepeatParameterizedAction(Sprite sprite, ParameterizedData data, List> parameters, - String position, Action repeatedAction) { + String position, Action repeatedAction, boolean isLoopDelay) { RepeatParameterizedAction action = action(RepeatParameterizedAction.class); action.setParameterizedData(data); action.setParameters(parameters); action.setAction(repeatedAction); + action.setLoopDelay(isLoopDelay); action.setSprite(sprite); action.setPosition(position); @@ -1336,14 +1355,15 @@ public Action createRepeatParameterizedAction(Sprite sprite, ParameterizedData d return action; } - public Action createParameterizedAssertAction(Sprite sprite, Formula actual, UserList expected, + public Action createParameterizedAssertAction(Sprite sprite, SequenceAction sequence, Formula actual, UserList expected, ParameterizedData data, String position) { ParameterizedAssertAction action = action(ParameterizedAssertAction.class); action.setActualFormula(actual); action.setExpectedList(expected); action.setParameterizedData(data); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setPosition(position); return action; @@ -1355,23 +1375,39 @@ public Action createFinishStageAction(boolean silent) { return action; } - public Action createTapAtAction(Sprite sprite, Formula x, Formula y) { + public Action createTapAtAction(Sprite sprite, SequenceAction sequence, Formula x, Formula y) { TapAtAction action = Actions.action(TapAtAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setStartX(x); action.setStartY(y); return action; } - public Action createTapForAction(Sprite sprite, Formula x, Formula y, Formula duration) { + public Action createTapForAction(Sprite sprite, SequenceAction sequence, Formula x, Formula y, + Formula duration) { TapAtAction action = Actions.action(TapAtAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setDurationFormula(duration); action.setStartX(x); action.setStartY(y); return action; } + public Action createTouchAndSlideAction(Sprite sprite, SequenceAction sequence, Formula x, Formula y, + Formula xChange, Formula yChange, Formula duration) { + TapAtAction action = Actions.action(TapAtAction.class); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); + action.setDurationFormula(duration); + action.setStartX(x); + action.setStartY(y); + action.setChangeX(xChange); + action.setChangeY(yChange); + return action; + } + public Action createWriteVariableOnDeviceAction(UserVariable userVariable) { WriteVariableOnDeviceAction action = Actions.action(WriteVariableOnDeviceAction.class); action.setUserVariable(userVariable); @@ -1379,19 +1415,22 @@ public Action createWriteVariableOnDeviceAction(UserVariable userVariable) { return action; } - public Action createWriteVariableToFileAction(Sprite sprite, Formula variableFormula, UserVariable userVariable) { + public Action createWriteVariableToFileAction(Sprite sprite, SequenceAction sequence, + Formula variableFormula, UserVariable userVariable) { WriteVariableToFileAction action = Actions.action(WriteVariableToFileAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setUserVariable(userVariable); action.setFormula(variableFormula); return action; } - public Action createReadVariableFromFileAction( - Sprite sprite, Formula variableFormula, UserVariable userVariable, boolean deleteFile) { + public Action createReadVariableFromFileAction(Sprite sprite, SequenceAction sequence, Formula variableFormula, + UserVariable userVariable, boolean deleteFile) { ReadVariableFromFileAction action = Actions.action(ReadVariableFromFileAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setUserVariable(userVariable); action.setFormula(variableFormula); action.setDeleteFile(deleteFile); @@ -1424,17 +1463,29 @@ public Action createReadListFromDeviceAction(UserList userList) { return action; } - public Action createWebRequestAction(Sprite sprite, Formula variableFormula, UserVariable userVariable) { + public Action createWebRequestAction(Sprite sprite, SequenceAction sequence, Formula variableFormula, + UserVariable userVariable) { WebRequestAction action = action(WebRequestAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setFormula(variableFormula); action.setUserVariable(userVariable); return action; } - public Action createLookRequestAction(Sprite sprite, Formula variableFormula) { + public Action createLookRequestAction(Sprite sprite, SequenceAction sequence, + Formula variableFormula) { LookRequestAction action = action(LookRequestAction.class); - action.setSprite(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); + action.setFormula(variableFormula); + return action; + } + + public Action createOpenUrlAction(Sprite sprite, SequenceAction sequence, Formula variableFormula) { + OpenUrlAction action = action(OpenUrlAction.class); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); action.setFormula(variableFormula); return action; } @@ -1450,4 +1501,33 @@ public Action createSetListeningLanguageAction(String listeningLanguageTag) { action.listeningLanguageTag = listeningLanguageTag; return action; } + + public Action createPaintNewLookAction(Sprite sprite, SequenceAction sequence, + Formula variableFormula, SetNextLookAction nextLookAction) { + PaintNewLookAction action = action(PaintNewLookAction.class); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); + action.setFormula(variableFormula); + action.nextLookAction(nextLookAction); + return action; + } + + public Action createCopyLookAction(Sprite sprite, SequenceAction sequence, Formula variableFormula, + SetNextLookAction nextLookAction) { + CopyLookAction action = action(CopyLookAction.class); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); + action.setFormula(variableFormula); + action.nextLookAction(nextLookAction); + return action; + } + + public Action createEditLookAction(Sprite sprite, SequenceAction sequence, + SetNextLookAction nextLookAction) { + EditLookAction action = action(EditLookAction.class); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, sequence); + action.setScope(scope); + action.nextLookAction(nextLookAction); + return action; + } } diff --git a/catroid/src/main/java/org/catrobat/catroid/content/ConditionScriptTrigger.java b/catroid/src/main/java/org/catrobat/catroid/content/ConditionScriptTrigger.java index 69db6563346..bb8af659201 100644 --- a/catroid/src/main/java/org/catrobat/catroid/content/ConditionScriptTrigger.java +++ b/catroid/src/main/java/org/catrobat/catroid/content/ConditionScriptTrigger.java @@ -25,6 +25,7 @@ import android.util.Log; +import org.catrobat.catroid.ProjectManager; import org.catrobat.catroid.content.eventids.WhenConditionEventId; import org.catrobat.catroid.formulaeditor.Formula; import org.catrobat.catroid.formulaeditor.InterpretationException; @@ -54,7 +55,8 @@ public class ConditionScriptTrigger { void evaluateAndTriggerActions(Sprite sprite) { try { - boolean conditionValue = formula.interpretBoolean(sprite); + Scope scope = new Scope(ProjectManager.getInstance().getCurrentProject(), sprite, null); + boolean conditionValue = formula.interpretBoolean(scope); if (conditionValue) { triggerScript(sprite); } else { diff --git a/catroid/src/main/java/org/catrobat/catroid/content/actions/DroneTurnLeftAction.java b/catroid/src/main/java/org/catrobat/catroid/content/EmptyScript.java similarity index 67% rename from catroid/src/main/java/org/catrobat/catroid/content/actions/DroneTurnLeftAction.java rename to catroid/src/main/java/org/catrobat/catroid/content/EmptyScript.java index dec76a52cb9..dcd7b59b998 100644 --- a/catroid/src/main/java/org/catrobat/catroid/content/actions/DroneTurnLeftAction.java +++ b/catroid/src/main/java/org/catrobat/catroid/content/EmptyScript.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -20,23 +20,24 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -package org.catrobat.catroid.content.actions; +package org.catrobat.catroid.content; -public class DroneTurnLeftAction extends DroneMoveAction { +import org.catrobat.catroid.content.bricks.EmptyEventBrick; +import org.catrobat.catroid.content.bricks.ScriptBrick; +import org.catrobat.catroid.content.eventids.EventId; + +public class EmptyScript extends Script { @Override - protected void move() { - if (getDroneService() != null) { - super.setCommandAndYawEnabled(true); - super.getDroneService().turnLeft(super.getPowerNormalized()); + public ScriptBrick getScriptBrick() { + if (scriptBrick == null) { + scriptBrick = new EmptyEventBrick(this); } + return scriptBrick; } @Override - protected void moveEnd() { - if (getDroneService() != null) { - super.setCommandAndYawEnabled(false); - super.getDroneService().turnLeft(DRONE_MOVE_SPEED_STOP); - } + public EventId createEventId(Sprite sprite) { + return null; } } diff --git a/catroid/src/main/java/org/catrobat/catroid/content/EventWrapper.kt b/catroid/src/main/java/org/catrobat/catroid/content/EventWrapper.kt index 08c476255a3..04873387eba 100644 --- a/catroid/src/main/java/org/catrobat/catroid/content/EventWrapper.kt +++ b/catroid/src/main/java/org/catrobat/catroid/content/EventWrapper.kt @@ -26,14 +26,24 @@ import com.badlogic.gdx.scenes.scene2d.Event import org.catrobat.catroid.content.eventids.EventId class EventWrapper(internal val eventId: EventId, private val wait: Boolean) : Event() { - private val spriteWaitList = mutableSetOf() + private val spriteWaitList = mutableMapOf() fun notify(sprite: Sprite) { - spriteWaitList.remove(sprite) + spriteWaitList[sprite] = spriteWaitList[sprite]?.minus(1) + + if (spriteWaitList[sprite] == 0) { + spriteWaitList.remove(sprite) + } } internal fun addSpriteToWaitList(sprite: Sprite) = wait.also { - if (it) spriteWaitList.add(sprite) + if (it) { + if (!spriteWaitList.containsKey(sprite)) { + spriteWaitList[sprite] = 1 + } else { + spriteWaitList[sprite] = spriteWaitList[sprite]?.plus(1) + } + } } fun isWaitingForSprite() = spriteWaitList.isNotEmpty() diff --git a/catroid/src/main/java/org/catrobat/catroid/content/EventWrapperListener.kt b/catroid/src/main/java/org/catrobat/catroid/content/EventWrapperListener.kt index 4d6086b0016..6c53119efab 100644 --- a/catroid/src/main/java/org/catrobat/catroid/content/EventWrapperListener.kt +++ b/catroid/src/main/java/org/catrobat/catroid/content/EventWrapperListener.kt @@ -24,7 +24,9 @@ package org.catrobat.catroid.content import com.badlogic.gdx.scenes.scene2d.Event import com.badlogic.gdx.scenes.scene2d.EventListener +import org.catrobat.catroid.content.actions.ScriptSequenceAction import org.catrobat.catroid.content.actions.ScriptSequenceActionWithWaiter +import org.catrobat.catroid.content.eventids.UserDefinedBrickEventId class EventWrapperListener internal constructor(private val look: Look) : EventListener { @@ -37,6 +39,10 @@ class EventWrapperListener internal constructor(private val look: Look) : EventL private fun handleEvent(event: EventWrapper) { with(look) { sprite.idToEventThreadMap[event.eventId].forEach { sequenceAction -> + if (event.eventId is UserDefinedBrickEventId) { + handleUserBrickEvent(sequenceAction, event) + return + } stopThreadWithScript(sequenceAction.script) if (event.addSpriteToWaitList(sprite)) { startThread(ScriptSequenceActionWithWaiter(sequenceAction, event, sprite)) @@ -46,4 +52,17 @@ class EventWrapperListener internal constructor(private val look: Look) : EventL } } } + + private fun handleUserBrickEvent(sequenceAction: ScriptSequenceAction, event: EventWrapper) { + with(look) { + val scriptClone = (sequenceAction.script as UserDefinedScript).clone() as + UserDefinedScript + scriptClone.setUserDefinedBrickInputs((event.eventId as + UserDefinedBrickEventId).userBrickParameters) + val sequenceClone: ScriptSequenceAction = sequenceAction.cloneAndChangeScript(scriptClone) + sequenceClone.script.run(sprite, sequenceClone) + event.addSpriteToWaitList(sprite) + startThread(ScriptSequenceActionWithWaiter(sequenceClone, event, sprite)) + } + } } diff --git a/catroid/src/main/java/org/catrobat/catroid/content/Look.java b/catroid/src/main/java/org/catrobat/catroid/content/Look.java index ae65e7fc89f..f9a1db47eaf 100644 --- a/catroid/src/main/java/org/catrobat/catroid/content/Look.java +++ b/catroid/src/main/java/org/catrobat/catroid/content/Look.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -40,7 +40,6 @@ import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.badlogic.gdx.utils.Array; -import org.catrobat.catroid.common.DroneVideoLookData; import org.catrobat.catroid.common.LookData; import org.catrobat.catroid.common.ThreadScheduler; import org.catrobat.catroid.content.actions.ScriptSequenceAction; @@ -68,6 +67,7 @@ public class Look extends Image { private static final float COLOR_SCALE = 200.0f; private boolean lookVisible = true; private boolean simultaneousMovementXY = false; + private int lookListIndexBeforeLookRequest = -1; protected LookData lookData; protected Sprite sprite; protected float alpha = 1f; @@ -119,6 +119,14 @@ public synchronized void setLookVisible(boolean lookVisible) { this.lookVisible = lookVisible; } + public synchronized int getLookListIndexBeforeLookRequest() { + return lookListIndexBeforeLookRequest; + } + + public synchronized void setLookListIndexBeforeLookRequest(int lookListIndexBeforeLookRequest) { + this.lookListIndexBeforeLookRequest = lookListIndexBeforeLookRequest; + } + @Override public boolean remove() { notifyAllWaiters(); @@ -183,10 +191,6 @@ public synchronized void draw(Batch batch, float parentAlpha) { super.setVisible(true); } - if (lookData instanceof DroneVideoLookData) { - lookData.draw(batch, alpha); - } - if (isLookVisible() && this.getDrawable() != null) { super.draw(batch, this.alpha); } diff --git a/catroid/src/main/java/org/catrobat/catroid/content/Project.java b/catroid/src/main/java/org/catrobat/catroid/content/Project.java index 2181fa32c61..f0f6d4e6b7b 100644 --- a/catroid/src/main/java/org/catrobat/catroid/content/Project.java +++ b/catroid/src/main/java/org/catrobat/catroid/content/Project.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -89,6 +89,7 @@ public Project() { public Project(Context context, String name, boolean landscapeMode, boolean isCastProject) { xmlHeader.setProjectName(name); xmlHeader.setDescription(""); + xmlHeader.setNotesAndCredits(""); xmlHeader.setlandscapeMode(landscapeMode); if (ScreenValues.SCREEN_HEIGHT == 0 || ScreenValues.SCREEN_WIDTH == 0) { @@ -165,10 +166,44 @@ public void removeScene(Scene scene) { sceneList.remove(scene); } + public boolean hasScene() { + return (sceneList.size() > 0); + } + public Scene getDefaultScene() { return sceneList.get(0); } + public boolean hasUserDataChanged(List newUserData, List oldUserData) { + if (newUserData.size() != oldUserData.size()) { + return true; + } + + for (T userData : newUserData) { + if (!checkEquality(userData, oldUserData)) { + return true; + } + } + + return false; + } + + public boolean checkEquality(T newUserData, List oldUserData) { + for (T userData : oldUserData) { + if (userData.equals(newUserData)) { + if (userData.getClass() == UserVariable.class) { + UserVariable userVariable = (UserVariable) userData; + return userVariable.hasSameValue((UserVariable) newUserData); + } else { + UserList userList = (UserList) userData; + return userList.hasSameListSize((UserList) newUserData); + } + } + } + + return false; + } + public List getUserVariables() { if (userVariables == null) { userVariables = new ArrayList<>(); @@ -176,6 +211,24 @@ public List getUserVariables() { return userVariables; } + public List getUserVariablesCopy() { + if (userVariables == null) { + userVariables = new ArrayList<>(); + } + + List userVariablesCopy = new ArrayList<>(); + for (UserVariable userVariable : userVariables) { + userVariablesCopy.add(new UserVariable(userVariable.getName(), + userVariable.getValue())); + } + + return userVariablesCopy; + } + + public void setUserVariables(List newUserVariables) { + userVariables = newUserVariables; + } + public UserVariable getUserVariable(String name) { for (UserVariable variable : userVariables) { if (variable.getName().equals(name)) { @@ -205,6 +258,23 @@ public List getUserLists() { return userLists; } + public void setUserLists(List newUserLists) { + userLists = newUserLists; + } + + public List getUserListsCopy() { + if (userLists == null) { + userLists = new ArrayList<>(); + } + + List userListsCopy = new ArrayList<>(); + for (UserList userList : userLists) { + userListsCopy.add(new UserList(userList.getName(), userList.getValue())); + } + + return userListsCopy; + } + public UserList getUserList(String name) { for (UserList list : userLists) { if (list.getName().equals(name)) { @@ -227,6 +297,23 @@ public boolean removeUserList(String name) { return false; } + public void setMultiplayerVariables(List newMultiplayerVariables) { + multiplayerVariables = newMultiplayerVariables; + } + + public List getMultiplayerVariablesCopy() { + if (multiplayerVariables == null) { + multiplayerVariables = new ArrayList<>(); + } + + List multiplayerVariablesCopy = new ArrayList<>(); + for (UserVariable userVariable : multiplayerVariables) { + multiplayerVariablesCopy.add(new UserVariable(userVariable.getName(), userVariable.getValue())); + } + + return multiplayerVariablesCopy; + } + public List getMultiplayerVariables() { if (multiplayerVariables == null) { multiplayerVariables = new ArrayList<>(); @@ -364,6 +451,10 @@ public void setDeviceData(Context context) { } } + public List getTags() { + return xmlHeader.getTags(); + } + public void setTags(List tags) { xmlHeader.setTags(tags); } diff --git a/catroid/src/main/java/org/catrobat/catroid/content/Scene.java b/catroid/src/main/java/org/catrobat/catroid/content/Scene.java index 45f1b8197a6..29b73f5d618 100644 --- a/catroid/src/main/java/org/catrobat/catroid/content/Scene.java +++ b/catroid/src/main/java/org/catrobat/catroid/content/Scene.java @@ -172,6 +172,29 @@ public Set getBroadcastMessagesInUse() { return messagesInUse; } + public void editBroadcastMessagesInUse(String oldMessage, String newMessage) { + for (Sprite currentSprite : spriteList) { + for (Script currentScript : currentSprite.getScriptList()) { + if (currentScript instanceof BroadcastScript) { + BroadcastScript broadcastScript = (BroadcastScript) currentScript; + if (broadcastScript.getBroadcastMessage().equals(oldMessage)) { + broadcastScript.setBroadcastMessage(newMessage); + } + } + List flatList = new ArrayList(); + currentScript.addToFlatList(flatList); + for (Brick currentBrick : flatList) { + if (currentBrick instanceof BroadcastMessageBrick) { + BroadcastMessageBrick broadcastMessageBrick = (BroadcastMessageBrick) currentBrick; + if (broadcastMessageBrick.getBroadcastMessage().equals(oldMessage)) { + broadcastMessageBrick.setBroadcastMessage(newMessage); + } + } + } + } + } + } + public void updateUserDataReferences(String oldName, String newName, UserData item) { if (ProjectManager.getInstance().getCurrentProject().isGlobalVariable(item)) { for (Sprite sprite : spriteList) { diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/ProjectListener.java b/catroid/src/main/java/org/catrobat/catroid/content/Scope.kt similarity index 83% rename from catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/ProjectListener.java rename to catroid/src/main/java/org/catrobat/catroid/content/Scope.kt index 97e66861c17..add68735eca 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/ProjectListener.java +++ b/catroid/src/main/java/org/catrobat/catroid/content/Scope.kt @@ -21,10 +21,12 @@ * along with this program. If not, see . */ -package org.catrobat.catroid.ui.recyclerview; +package org.catrobat.catroid.content -public class ProjectListener { - public interface OnProjectListener { - void onProjectClick(int position); - } -} +import com.badlogic.gdx.scenes.scene2d.actions.SequenceAction + +data class Scope( + val project: Project, + val sprite: Sprite, + val sequence: SequenceAction? +) diff --git a/catroid/src/main/java/org/catrobat/catroid/content/Script.java b/catroid/src/main/java/org/catrobat/catroid/content/Script.java index dfe27631a08..bdcd3da7b91 100644 --- a/catroid/src/main/java/org/catrobat/catroid/content/Script.java +++ b/catroid/src/main/java/org/catrobat/catroid/content/Script.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -22,6 +22,8 @@ */ package org.catrobat.catroid.content; +import com.thoughtworks.xstream.annotations.XStreamAsAttribute; + import org.catrobat.catroid.content.actions.ScriptSequenceAction; import org.catrobat.catroid.content.bricks.Brick; import org.catrobat.catroid.content.bricks.CompositeBrick; @@ -35,6 +37,7 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import java.util.UUID; public abstract class Script implements Serializable, Cloneable { @@ -43,6 +46,13 @@ public abstract class Script implements Serializable, Cloneable { protected List brickList = new ArrayList<>(); protected boolean commentedOut = false; + @XStreamAsAttribute + protected float posX; + @XStreamAsAttribute + protected float posY; + + protected UUID scriptId = UUID.randomUUID(); + protected transient ScriptBrick scriptBrick; public List getBrickList() { @@ -62,9 +72,32 @@ public Script clone() throws CloneNotSupportedException { clone.commentedOut = commentedOut; clone.scriptBrick = null; + clone.posX = posX; + clone.posY = posY; + clone.scriptId = UUID.randomUUID(); return clone; } + public float getPosX() { + return posX; + } + + public void setPosX(float posX) { + this.posX = posX; + } + + public float getPosY() { + return posY; + } + + public void setPosY(float posY) { + this.posY = posY; + } + + public UUID getScriptId() { + return scriptId; + } + public boolean isCommentedOut() { return commentedOut; } @@ -186,4 +219,71 @@ public void deselectElements(List> elements) { } } } + + public List findBricksInScript(List brickIds) { + List bricks = new ArrayList<>(); + + for (Brick brick : brickList) { + if (brickIds.contains(brick.getBrickID())) { + bricks.add(brick); + } else if (brick instanceof CompositeBrick) { + List tmpBricks = brick.findBricksInNestedBricks(brickIds); + if (tmpBricks != null) { + return tmpBricks; + } + } + + if (bricks.size() == brickIds.size()) { + return bricks; + } + } + + if (bricks.size() > 0) { + return bricks; + } + return null; + } + + public List removeBricksFromScript(List brickIds) { + List bricks = findBricksInScript(brickIds); + + if (bricks != null) { + for (Brick brick : bricks) { + removeBrick(brick); + } + } + + return bricks; + } + + public boolean insertBrickAfter(UUID parentId, int subStackIndex, List bricksToAdd) { + + if (subStackIndex == -1) { + if (scriptId.equals(parentId) || getScriptBrick().getBrickID().equals(parentId)) { + brickList.addAll(0, bricksToAdd); + return true; + } + + boolean found = false; + int index = 0; + for (Brick brick : brickList) { + ++index; + if (brick.getBrickID().equals(parentId)) { + found = true; + break; + } + } + if (found) { + brickList.addAll(index, bricksToAdd); + return true; + } + } + + for (Brick brick : brickList) { + if (brick.addBrickInNestedBrick(parentId, subStackIndex, bricksToAdd)) { + return true; + } + } + return false; + } } diff --git a/catroid/src/main/java/org/catrobat/catroid/content/Sprite.java b/catroid/src/main/java/org/catrobat/catroid/content/Sprite.java index e0142c4521e..b3a3324f53d 100644 --- a/catroid/src/main/java/org/catrobat/catroid/content/Sprite.java +++ b/catroid/src/main/java/org/catrobat/catroid/content/Sprite.java @@ -1,6 +1,6 @@ /* * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2018 The Catrobat Team + * Copyright (C) 2010-2021 The Catrobat Team * () * * This program is free software: you can redistribute it and/or modify @@ -152,7 +152,7 @@ public UserDefinedBrick getUserDefinedBrickWithSameUserData(UserDefinedBrick use if (userDefinedBrick == null) { return null; } - for (Brick brick: userDefinedBrickList) { + for (Brick brick : userDefinedBrickList) { if (((UserDefinedBrick) brick).isUserDefinedBrickDataEqual(userDefinedBrick)) { return (UserDefinedBrick) brick; } @@ -196,6 +196,53 @@ public void addClonesOfUserDefinedBrickList(List userDefinedBr } } + public boolean hasUserDataChanged(List newUserData, List oldUserData) { + if (newUserData.size() != oldUserData.size()) { + return true; + } + + for (T userData : newUserData) { + if (!checkUserData(userData, oldUserData)) { + return true; + } + } + + return false; + } + + public boolean checkUserData(T newUserData, List oldUserData) { + for (T userData : oldUserData) { + if (userData.equals(newUserData)) { + if (userData.getClass() == UserVariable.class) { + UserVariable userVariable = (UserVariable) userData; + return userVariable.hasSameValue((UserVariable) newUserData); + } else { + UserList userList = (UserList) userData; + return userList.hasSameListSize((UserList) newUserData); + } + } + } + + return false; + } + + public void setUserVariables(List newUserVariables) { + userVariables = newUserVariables; + } + + public List getUserVariablesCopy() { + if (userVariables == null) { + userVariables = new ArrayList<>(); + } + + List userVariablesCopy = new ArrayList<>(); + for (UserVariable userVariable : userVariables) { + userVariablesCopy.add(new UserVariable(userVariable.getName(), userVariable.getValue())); + } + + return userVariablesCopy; + } + public List getUserVariables() { return userVariables; } @@ -213,6 +260,23 @@ public boolean addUserVariable(UserVariable userVariable) { return userVariables.add(userVariable); } + public void setUserLists(List newUserLists) { + userLists = newUserLists; + } + + public List getUserListsCopy() { + if (userLists == null) { + userLists = new ArrayList<>(); + } + + List userListsCopy = new ArrayList<>(); + for (UserList userList : userLists) { + userListsCopy.add(new UserList(userList.getName(), userList.getValue())); + } + + return userListsCopy; + } + public List getUserLists() { return userLists; } @@ -346,9 +410,11 @@ public Sprite convert() { return convertedSprite; } - private ScriptSequenceAction createSequenceAction(Script script) { + public ScriptSequenceAction createSequenceAction(Script script) { ScriptSequenceAction sequence = (ScriptSequenceAction) ActionFactory.createScriptSequenceAction(script); - script.run(this, sequence); + if (!script.getClass().equals(UserDefinedScript.class)) { + script.run(this, sequence); + } return sequence; } @@ -434,19 +500,23 @@ public String toString() { } public void rename(String newSpriteName) { - if (hasCollision()) { - renameSpriteInCollisionFormulas(newSpriteName, CatroidApplication.getAppContext()); + Scene scene = ProjectManager.getInstance().getCurrentlyEditedScene(); + renameSpriteAndUpdateCollisionFormulas(newSpriteName, scene); + } + + public void renameSpriteAndUpdateCollisionFormulas(String newSpriteName, Scene scene) { + if (hasCollision(scene)) { + renameSpriteInCollisionFormulas(newSpriteName, scene); } setName(newSpriteName); } - public boolean hasCollision() { + public boolean hasCollision(Scene scene) { Brick.ResourcesSet resourcesSet = new Brick.ResourcesSet(); addRequiredResources(resourcesSet); if (resourcesSet.contains(Brick.COLLISION)) { return true; } - Scene scene = ProjectManager.getInstance().getCurrentlyEditedScene(); for (Sprite sprite : scene.getSpriteList()) { if (sprite.hasToCollideWith(this)) { return true; @@ -473,9 +543,9 @@ private boolean hasToCollideWith(Sprite other) { return false; } - private void renameSpriteInCollisionFormulas(String newName, Context context) { + private void renameSpriteInCollisionFormulas(String newName, Scene scene) { String oldName = getName(); - List spriteList = ProjectManager.getInstance().getCurrentlyEditedScene().getSpriteList(); + List spriteList = scene.getSpriteList(); for (Sprite sprite : spriteList) { for (Script currentScript : sprite.getScriptList()) { if (currentScript == null) { @@ -487,7 +557,7 @@ private void renameSpriteInCollisionFormulas(String newName, Context context) { if (brick instanceof FormulaBrick) { List formulaList = ((FormulaBrick) brick).getFormulas(); for (Formula formula : formulaList) { - formula.updateCollisionFormulas(oldName, newName, context); + formula.updateCollisionFormulas(oldName, newName, CatroidApplication.getAppContext()); } } } @@ -571,4 +641,41 @@ public void releaseAllPointers() { } usedTouchPointer.clear(); } + + public Brick findBrickInSprite(UUID brickId) { + for (Script script : scriptList) { + if (script.getScriptId().equals(brickId)) { + return script.getScriptBrick(); + } + } + + List brickIdList = new ArrayList<>(); + brickIdList.add(brickId); + for (Script script : scriptList) { + List foundBricks = script.findBricksInScript(brickIdList); + if (foundBricks != null && !foundBricks.isEmpty()) { + return foundBricks.get(0); + } + } + + return null; + } + + public List removeAllEmptyScriptBricks() { + List idsToRemove = new ArrayList<>(); + List