From c5d2db6572f42c8dd93f5f4ed8d1b50aa17c8288 Mon Sep 17 00:00:00 2001 From: oetzlinger Date: Sat, 3 Dec 2022 17:23:03 +0100 Subject: [PATCH] CATTY-438 Implement StopScriptBrick --- src/Catty.xcodeproj/project.pbxproj | 20 +++++++ .../Bricks/Control/StopScriptBrick.swift | 60 +++++++++++++++++++ .../StopScriptBrick+CBXMLHandler.swift | 55 +++++++++++++++++ .../DataModel/SpriteObject/StopStyle.swift | 53 ++++++++++++++++ .../Defines/LanguageTranslationDefines.h | 1 + .../LanguageTranslationDefinesSwift.swift | 1 + .../Protocols/CBSchedulerProtocol.swift | 2 + .../PlayerEngine/Scheduler/CBScheduler.swift | 19 +++++- .../Localization/en.lproj/Localizable.strings | 3 + src/Catty/Setup/CatrobatSetup+Bricks.swift | 1 + src/Catty/StopScriptBrick+Instruction.swift | 38 ++++++++++++ .../Control/StopScriptBrickCell.swift | 48 +++++++++++++++ .../PlayerEngine/CBSchedulerTests.swift | 57 +++++++++++++++--- .../ValidProjectAllBricks0991.xml | 12 ++++ .../XMLParserTests0991.swift | 21 +++++++ .../LanguageTranslationDefinesUI.swift | 1 + 16 files changed, 384 insertions(+), 8 deletions(-) create mode 100644 src/Catty/DataModel/Bricks/Control/StopScriptBrick.swift create mode 100644 src/Catty/DataModel/SpriteObject/StopScriptBrick+CBXMLHandler.swift create mode 100644 src/Catty/DataModel/SpriteObject/StopStyle.swift create mode 100644 src/Catty/StopScriptBrick+Instruction.swift create mode 100644 src/Catty/Views/Custom/CollectionViewCells/BrickCells/Control/StopScriptBrickCell.swift diff --git a/src/Catty.xcodeproj/project.pbxproj b/src/Catty.xcodeproj/project.pbxproj index 2dddb92160..7f4c9caf10 100644 --- a/src/Catty.xcodeproj/project.pbxproj +++ b/src/Catty.xcodeproj/project.pbxproj @@ -2057,6 +2057,11 @@ F4E6E5C4210E242D00D86FE6 /* FloorFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E6E5C3210E242D00D86FE6 /* FloorFunction.swift */; }; F4E6E5C6210E24F900D86FE6 /* TrueFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E6E5C5210E24F900D86FE6 /* TrueFunction.swift */; }; F4E6E5C8210E255D00D86FE6 /* FalseFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E6E5C7210E255D00D86FE6 /* FalseFunction.swift */; }; + FE4134F8293B418A0001DA11 /* StopScriptBrick.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE4134F7293B418A0001DA11 /* StopScriptBrick.swift */; }; + FE4134FA293B44E00001DA11 /* StopScriptBrickCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE4134F9293B44E00001DA11 /* StopScriptBrickCell.swift */; }; + FE4134FF293BA41A0001DA11 /* StopScriptBrick+Instruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE4134FE293BA41A0001DA11 /* StopScriptBrick+Instruction.swift */; }; + FE413501293BACEC0001DA11 /* StopStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE413500293BACEC0001DA11 /* StopStyle.swift */; }; + FEDC355B29407F5D00256FAB /* StopScriptBrick+CBXMLHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEDC355A29407F5D00256FAB /* StopScriptBrick+CBXMLHandler.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -4730,6 +4735,11 @@ F4E6E5C7210E255D00D86FE6 /* FalseFunction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FalseFunction.swift; sourceTree = ""; }; F511044FACC2C8E38A678BB4 /* chr */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.strings; name = chr; path = chr.lproj/Localizable.strings; sourceTree = ""; }; FB40BD936AE254501FBA2E03 /* kn */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.strings; name = kn; path = kn.lproj/Localizable.strings; sourceTree = ""; }; + FE4134F7293B418A0001DA11 /* StopScriptBrick.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StopScriptBrick.swift; sourceTree = ""; }; + FE4134F9293B44E00001DA11 /* StopScriptBrickCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StopScriptBrickCell.swift; sourceTree = ""; }; + FE4134FE293BA41A0001DA11 /* StopScriptBrick+Instruction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StopScriptBrick+Instruction.swift"; sourceTree = ""; }; + FE413500293BACEC0001DA11 /* StopStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StopStyle.swift; sourceTree = ""; }; + FEDC355A29407F5D00256FAB /* StopScriptBrick+CBXMLHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "StopScriptBrick+CBXMLHandler.swift"; path = "Catty/DataModel/SpriteObject/StopScriptBrick+CBXMLHandler.swift"; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -6794,6 +6804,7 @@ AA74EEDA1BC057B900D1E954 /* WaitBrick+CBXMLHandler.m */, BA987D042194DDCF002DAA05 /* WaitUntilBrick+CBXMLHandler.h */, BA987D032194DDCF002DAA05 /* WaitUntilBrick+CBXMLHandler.m */, + FEDC355A29407F5D00256FAB /* StopScriptBrick+CBXMLHandler.swift */, ); name = Control; path = ControlBricks; @@ -9050,6 +9061,7 @@ children = ( 181CC10424B750AE004A783E /* CBPosition.swift */, 4C0D2A81254AA2C100A8637F /* RotationStyle.swift */, + FE413500293BACEC0001DA11 /* StopStyle.swift */, 92FF30BF1A24DCAA00093DA7 /* SpriteObject.h */, 92FF30C01A24DCAA00093DA7 /* SpriteObject.m */, ); @@ -10126,6 +10138,7 @@ AA74EE1F1BC053FD00D1E954 /* BroadcastWaitBrick+Instruction.swift */, AA74EE201BC053FD00D1E954 /* WaitBrick+Instruction.swift */, BA987D0E2194EA1F002DAA05 /* WaitUntilBrick+Instruction.swift */, + FE4134FE293BA41A0001DA11 /* StopScriptBrick+Instruction.swift */, ); name = Control; sourceTree = ""; @@ -10255,6 +10268,7 @@ AA74EF931BC05B5F00D1E954 /* RepeatBrick.m */, 4C0F9F27204ADBDF00E71B2D /* RepeatUntilBrick.h */, 4C0F9F26204ADBDF00E71B2D /* RepeatUntilBrick.m */, + FE4134F7293B418A0001DA11 /* StopScriptBrick.swift */, AA74EF941BC05B5F00D1E954 /* WaitBrick.h */, AA74EF951BC05B5F00D1E954 /* WaitBrick.m */, BA987D072194E158002DAA05 /* WaitUntilBrick.h */, @@ -10499,6 +10513,7 @@ 9EDCD22422886FD90040EFE3 /* WaitBrickCell.swift */, BA987D0A2194E25A002DAA05 /* WaitUntilBrickCell.h */, BA987D092194E25A002DAA05 /* WaitUntilBrickCell.m */, + FE4134F9293B44E00001DA11 /* StopScriptBrickCell.swift */, ); path = Control; sourceTree = ""; @@ -13192,6 +13207,7 @@ 46F0D30E25E593F5002252E6 /* SetLookBrick+CBXMLHandler.swift in Sources */, 4CB2CFA61D7AD7E7009F3034 /* SetColorBrick+CBXMLHandler.m in Sources */, AA74EFEB1BC05B5F00D1E954 /* WaitBrick.m in Sources */, + FEDC355B29407F5D00256FAB /* StopScriptBrick+CBXMLHandler.swift in Sources */, 4C0F9FA5204BD2C200E71B2D /* ThinkForBubbleBrickCell.m in Sources */, 4CDA808521366AEA0052FA24 /* FormulaManagerProtocol.swift in Sources */, 49B55F9327E88702000A95B4 /* RightEyebrowInnerXSensor.swift in Sources */, @@ -13453,8 +13469,10 @@ 186E99132488F3FF00627E36 /* PenUpBrick.swift in Sources */, BA9CAB601EC383E800796056 /* AddItemToUserListBrickCell.m in Sources */, 9E2AEA50239887A600CDF58F /* PlaySoundAndWaitBrickCell.swift in Sources */, + FE413501293BACEC0001DA11 /* StopStyle.swift in Sources */, 9218B2051CC4AB75007B4C60 /* LinkedListStack.m in Sources */, F4E6E584210DFD4300D86FE6 /* TanFunction.swift in Sources */, + FE4134F8293B418A0001DA11 /* StopScriptBrick.swift in Sources */, 92B46F931BC7B3E5004980C1 /* ArduinoSendPWMValueBrick.m in Sources */, F4E6E596210E03B700D86FE6 /* AtanFunction.swift in Sources */, F4E6E588210DFE8800D86FE6 /* LogFunction.swift in Sources */, @@ -13609,6 +13627,7 @@ AAF6D9D81BC0BAF300686849 /* ShowBrick+Instruction.swift in Sources */, 593E4DDE1FE11D410016DCB9 /* CatrobatReorderableCollectionViewFlowLayout.m in Sources */, BB9EC0E327D62CBA009FF8CE /* FormCheckTableViewCell.swift in Sources */, + FE4134FA293B44E00001DA11 /* StopScriptBrickCell.swift in Sources */, 4CEFFAD32105DE4800DC5CFE /* ObjectSensor.swift in Sources */, 921D467B1BDF61350086AD20 /* ChangeXByNBrick+Instruction.swift in Sources */, 4420ACB3250929DA00951328 /* AskBrickCell.swift in Sources */, @@ -13643,6 +13662,7 @@ 5E7B5B0D21EC0FCF002E4B57 /* HelpWebViewController.swift in Sources */, 9218B2111CC4AB75007B4C60 /* PointerTool.m in Sources */, AA74F0CE1BC05FCE00D1E954 /* WhenScriptCell.m in Sources */, + FE4134FF293BA41A0001DA11 /* StopScriptBrick+Instruction.swift in Sources */, F4E6E580210DE61900D86FE6 /* PowerFunction.swift in Sources */, 92FF32B91A24E2F400093DA7 /* DarkBlueGradientCell.m in Sources */, 498C158528070C6C00B81C8E /* RightKneeYSensor.swift in Sources */, diff --git a/src/Catty/DataModel/Bricks/Control/StopScriptBrick.swift b/src/Catty/DataModel/Bricks/Control/StopScriptBrick.swift new file mode 100644 index 0000000000..a198d83113 --- /dev/null +++ b/src/Catty/DataModel/Bricks/Control/StopScriptBrick.swift @@ -0,0 +1,60 @@ +/** + * Copyright (C) 2010-2022 The Catrobat Team + * (http://developer.catrobat.org/credits) + * + * 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 http://www.gnu.org/licenses/. + */ + +@objc(StopScriptBrick) class StopScriptBrick: Brick, BrickProtocol, BrickStaticChoiceProtocol { + static let defaultSelection = StopStyle.thisScript + var question: Formula? + var selection: StopStyle + + override required init() { + self.selection = type(of: self).defaultSelection + super.init() + } + + func category() -> kBrickCategoryType { + kBrickCategoryType.controlBrick + } + + override func description() -> String { + "StopScriptBrick" + } + + override func getRequiredResources() -> Int { + ResourceType.noResources.rawValue + } + + override func brickCell() -> BrickCellProtocol.Type! { + StopScriptBrickCell.self as BrickCellProtocol.Type + } + + func choice(forLineNumber lineNumber: Int, andParameterNumber paramNumber: Int) -> String { + selection.localizedString() + } + + func setChoice(_ message: String, forLineNumber lineNumber: Int, andParameterNumber paramNumber: Int) { + self.selection = StopStyle.from(localizedString: message) ?? type(of: self).defaultSelection + } + + func possibleChoices(forLineNumber lineNumber: Int, andParameterNumber paramNumber: Int) -> [String] { + StopStyle.allCases.map { $0.localizedString() } + } +} diff --git a/src/Catty/DataModel/SpriteObject/StopScriptBrick+CBXMLHandler.swift b/src/Catty/DataModel/SpriteObject/StopScriptBrick+CBXMLHandler.swift new file mode 100644 index 0000000000..2bcfde434b --- /dev/null +++ b/src/Catty/DataModel/SpriteObject/StopScriptBrick+CBXMLHandler.swift @@ -0,0 +1,55 @@ +/** + * Copyright (C) 2010-2022 The Catrobat Team + * (http://developer.catrobat.org/credits) + * + * 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 http://www.gnu.org/licenses/. + */ + +extension StopScriptBrick: CBXMLNodeProtocol { + static func parse(from xmlElement: GDataXMLElement!, with context: CBXMLParserContext!) -> Self! { + CBXMLParserHelper.validate(xmlElement, forNumberOfChildNodes: 1) + let brick = self.init() + + let brickType = xmlElement.attribute(forName: "type") + + if brickType?.stringValue() == "StopScriptBrick" { + if let selection: GDataXMLElement = xmlElement.child(withElementName: "selection") { + if let choiceInt = Int(selection.stringValue()), let selection = StopStyle.from(rawValue: choiceInt) { + brick.selection = selection + } else { + fatalError("No or invalid selectionChoice given...") + } + } else { + fatalError("StopStyleBrick element does not contain a selection child element!") + } + } else { + fatalError("StopStyleBrick is faulty!") + } + + return brick + } + + func xmlElement(with context: CBXMLSerializerContext) -> GDataXMLElement? { + let brick = super.xmlElement(for: "StopScriptBrick", with: context) + let numberString = String(format: "%i", arguments: [self.selection.rawValue]) + let selection = GDataXMLElement(name: "selection", stringValue: numberString, context: context) + + brick?.addChild(selection, context: context) + return brick + } +} diff --git a/src/Catty/DataModel/SpriteObject/StopStyle.swift b/src/Catty/DataModel/SpriteObject/StopStyle.swift new file mode 100644 index 0000000000..df5a5283d9 --- /dev/null +++ b/src/Catty/DataModel/SpriteObject/StopStyle.swift @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2010-2022 The Catrobat Team + * (http://developer.catrobat.org/credits) + * + * 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 http://www.gnu.org/licenses/. + */ + +enum StopStyle: Int, CaseIterable { + case thisScript = 0 + case allScripts = 1 + case otherScripts = 2 + + //TODO use kLocalizedLeftRight + func localizedString() -> String { + switch self { + case .thisScript: + return "this script" + case .allScripts: + return "all scripts" + case .otherScripts: + return "other scripts of this actor or object" + } + } + + static func from(rawValue: Int) -> StopStyle? { + for style in StopStyle.allCases where style.rawValue == rawValue { + return style + } + return nil + } + + static func from(localizedString: String) -> StopStyle? { + for style in StopStyle.allCases where style.localizedString() == localizedString { + return style + } + return nil + } +} diff --git a/src/Catty/Defines/LanguageTranslationDefines.h b/src/Catty/Defines/LanguageTranslationDefines.h index 54e44ce2a7..d3b9c6790d 100644 --- a/src/Catty/Defines/LanguageTranslationDefines.h +++ b/src/Catty/Defines/LanguageTranslationDefines.h @@ -389,6 +389,7 @@ #define kLocalizedEndOfLoop NSLocalizedString(@"End of Loop", nil) #define kLocalizedWhen NSLocalizedString(@"When", nil) #define kLocalizedBecomesTrue NSLocalizedString(@"becomes true", nil) +#define kLocalizedStop NSLocalizedString(@"Stop", nil) // motion bricks #define kLocalizedPlaceAt NSLocalizedString(@"Place at ", nil) diff --git a/src/Catty/Defines/LanguageTranslationDefinesSwift.swift b/src/Catty/Defines/LanguageTranslationDefinesSwift.swift index 049baf9283..765ff27e74 100644 --- a/src/Catty/Defines/LanguageTranslationDefinesSwift.swift +++ b/src/Catty/Defines/LanguageTranslationDefinesSwift.swift @@ -389,6 +389,7 @@ let kLocalizedTimes = NSLocalizedString("times", comment: "") let kLocalizedEndOfLoop = NSLocalizedString("End of Loop", comment: "") let kLocalizedWhen = NSLocalizedString("When", comment: "") let kLocalizedBecomesTrue = NSLocalizedString("becomes true", comment: "") +let kLocalizedStop = NSLocalizedString("Stop", comment: "") // motion bricks let kLocalizedPlaceAt = NSLocalizedString("Place at ", comment: "") diff --git a/src/Catty/PlayerEngine/Protocols/CBSchedulerProtocol.swift b/src/Catty/PlayerEngine/Protocols/CBSchedulerProtocol.swift index 5df071bb5d..bc9c1a2a63 100644 --- a/src/Catty/PlayerEngine/Protocols/CBSchedulerProtocol.swift +++ b/src/Catty/PlayerEngine/Protocols/CBSchedulerProtocol.swift @@ -50,6 +50,8 @@ protocol CBSchedulerProtocol: AnyObject { func runNextInstructionsGroup() func scheduleContext(_ context: CBScriptContextProtocol) func stopContext(_ context: CBScriptContextProtocol, continueWaitingBroadcastSenders: Bool) + func stopAllScripts() + func stopAllOtherScripts(_ context: CBScriptContextProtocol) // timers func registerTimer(_ timer: ExtendedTimer) diff --git a/src/Catty/PlayerEngine/Scheduler/CBScheduler.swift b/src/Catty/PlayerEngine/Scheduler/CBScheduler.swift index d436086fbe..2b855688bf 100644 --- a/src/Catty/PlayerEngine/Scheduler/CBScheduler.swift +++ b/src/Catty/PlayerEngine/Scheduler/CBScheduler.swift @@ -383,7 +383,6 @@ final class CBScheduler: CBSchedulerProtocol { if context.state == .running || context.state == .waiting { _broadcastHandler.terminateAllCalledBroadcastContextsAndRemoveWaitingContext(context) } - scheduleContext(context) } @@ -391,6 +390,24 @@ final class CBScheduler: CBSchedulerProtocol { } + func stopAllScripts() { + _scheduledContexts.orderedValues.forEach { + $0.forEach { + stopContext($0, continueWaitingBroadcastSenders: false) + } + } + } + + func stopAllOtherScripts(_ context: CBScriptContextProtocol) { + _scheduledContexts.orderedValues.forEach { + $0.forEach { + if $0.spriteNode.name == context.spriteNode.name && $0.id != context.id { + stopContext($0, continueWaitingBroadcastSenders: false) + } + } + } + } + func stopContext(_ context: CBScriptContextProtocol, continueWaitingBroadcastSenders: Bool) { guard let spriteName = context.spriteNode.name else { fatalError("Sprite node has no name!") } // assert(!_broadcastHandler.isWaitingForCalledBroadcastContexts(context)) diff --git a/src/Catty/Resources/Localization/en.lproj/Localizable.strings b/src/Catty/Resources/Localization/en.lproj/Localizable.strings index 1bc22f70f7..9f97aeacf9 100644 --- a/src/Catty/Resources/Localization/en.lproj/Localizable.strings +++ b/src/Catty/Resources/Localization/en.lproj/Localizable.strings @@ -2089,6 +2089,9 @@ /* No comment provided by engineer. */ "Stitch" = "Stitch"; +/* No comment provided by engineer. */ +"Stop" = "Stop"; + /* No comment provided by engineer. */ "Stop all sounds" = "Stop all sounds"; diff --git a/src/Catty/Setup/CatrobatSetup+Bricks.swift b/src/Catty/Setup/CatrobatSetup+Bricks.swift index 30e1f583b6..290c0755d3 100644 --- a/src/Catty/Setup/CatrobatSetup+Bricks.swift +++ b/src/Catty/Setup/CatrobatSetup+Bricks.swift @@ -46,6 +46,7 @@ NoteBrick(), WaitUntilBrick(), LoopEndBrick(), + StopScriptBrick(), // motion bricks PlaceAtBrick(), GlideToBrick(), diff --git a/src/Catty/StopScriptBrick+Instruction.swift b/src/Catty/StopScriptBrick+Instruction.swift new file mode 100644 index 0000000000..b07f28af57 --- /dev/null +++ b/src/Catty/StopScriptBrick+Instruction.swift @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2010-2022 The Catrobat Team + * (http://developer.catrobat.org/credits) + * + * 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 http://www.gnu.org/licenses/. + */ + +@objc extension StopScriptBrick: CBInstructionProtocol { + + @nonobjc func instruction() -> CBInstruction { + CBInstruction.execClosure { context, scheduler in + switch self.selection { + case .thisScript: + scheduler.stopContext(context, continueWaitingBroadcastSenders: false) + case .allScripts: + scheduler.stopAllScripts() + case .otherScripts: + scheduler.stopAllOtherScripts(context) + scheduler.runNextInstructionOfContext(context) + } + } + } +} diff --git a/src/Catty/Views/Custom/CollectionViewCells/BrickCells/Control/StopScriptBrickCell.swift b/src/Catty/Views/Custom/CollectionViewCells/BrickCells/Control/StopScriptBrickCell.swift new file mode 100644 index 0000000000..ef5c7ccd92 --- /dev/null +++ b/src/Catty/Views/Custom/CollectionViewCells/BrickCells/Control/StopScriptBrickCell.swift @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2010-2022 The Catrobat Team + * (http://developer.catrobat.org/credits) + * + * 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 http://www.gnu.org/licenses/. + */ + +import Foundation + +@objc(StopScriptBrickCell) class StopScriptBrickCell: BrickCell, BrickCellProtocol { + + var titelLabel: UILabel? + var comboBox: iOSCombobox? + + static func cellHeight() -> CGFloat { + UIDefines.brickHeight2h + } + + func brickTitle(forBackground isBackground: Bool, andInsertionScreen isInsertion: Bool) -> String! { + kLocalizedStop + "\n%@" + } + + override func hookUpSubViews(_ inlineViewSubViews: [Any]!) { + self.titelLabel = inlineViewSubViews[0] as? UILabel + self.comboBox = inlineViewSubViews[1] as? iOSCombobox + } + + override func parameters() -> [String]! { + let params = NSArray.init(objects: "{STATICCHOICE}") as? [String] + return params + } + +} diff --git a/src/CattyTests/PlayerEngine/CBSchedulerTests.swift b/src/CattyTests/PlayerEngine/CBSchedulerTests.swift index 34828b0040..3cabb4b842 100644 --- a/src/CattyTests/PlayerEngine/CBSchedulerTests.swift +++ b/src/CattyTests/PlayerEngine/CBSchedulerTests.swift @@ -27,7 +27,8 @@ import XCTest final class CBSchedulerTests: XCTestCase { var spriteObject: SpriteObject! - var spriteNode: CBSpriteNode! + var spriteNode1: CBSpriteNode! + var spriteNode2: CBSpriteNode! var startScript: StartScript! var interpreter: FormulaInterpreterProtocol! var touchManager: TouchManagerProtocol! @@ -37,7 +38,7 @@ final class CBSchedulerTests: XCTestCase { let scene = Scene() spriteObject = SpriteObjectMock(name: "Name", scene: scene) - spriteNode = CBSpriteNodeMock(spriteObject: spriteObject) + spriteNode1 = CBSpriteNodeMock(spriteObject: spriteObject) startScript = StartScript() startScript.object = spriteObject @@ -51,11 +52,53 @@ final class CBSchedulerTests: XCTestCase { scheduler = CBScheduler(logger: logger, broadcastHandler: broadcastHandler, formulaInterpreter: interpreter, audioEngine: audioEngine) - scheduler.registerSpriteNode(spriteNode) + scheduler.registerSpriteNode(spriteNode1) + } + + func testAreAllContextsStoped() { + let context1 = CBScriptContext(script: startScript, spriteNode: spriteNode1, formulaInterpreter: interpreter, touchManager: touchManager)! + let context2 = CBScriptContext(script: startScript, spriteNode: spriteNode2, formulaInterpreter: interpreter, touchManager: touchManager)! + XCTAssertFalse(scheduler.isContextScheduled(context1)) + XCTAssertFalse(scheduler.isContextScheduled(context2)) + + scheduler.registerContext(context1) + scheduler.scheduleContext(context2) + + scheduler.registerContext(context1) + scheduler.scheduleContext(context2) + + XCTAssertTrue(scheduler.isContextScheduled(context1)) + XCTAssertTrue(scheduler.isContextScheduled(context2)) + + scheduler.stopAllScripts() + + XCTAssertFalse(scheduler.isContextScheduled(context1)) + XCTAssertFalse(scheduler.isContextScheduled(context2)) + } + + func testAreOtherContextsStoped() { + let context1 = CBScriptContext(script: startScript, spriteNode: spriteNode1, formulaInterpreter: interpreter, touchManager: touchManager)! + let context2 = CBScriptContext(script: startScript, spriteNode: spriteNode2, formulaInterpreter: interpreter, touchManager: touchManager)! + XCTAssertFalse(scheduler.isContextScheduled(context1)) + XCTAssertFalse(scheduler.isContextScheduled(context2)) + + scheduler.registerContext(context1) + scheduler.scheduleContext(context2) + + scheduler.registerContext(context1) + scheduler.scheduleContext(context2) + + XCTAssertTrue(scheduler.isContextScheduled(context1)) + XCTAssertTrue(scheduler.isContextScheduled(context2)) + + scheduler.stopAllOtherScripts(context1) + + XCTAssertTrue(scheduler.isContextScheduled(context1)) + XCTAssertFalse(scheduler.isContextScheduled(context2)) } func testIsContextScheduled() { - let context = CBScriptContext(script: startScript, spriteNode: spriteNode, formulaInterpreter: interpreter, touchManager: touchManager)! + let context = CBScriptContext(script: startScript, spriteNode: spriteNode1, formulaInterpreter: interpreter, touchManager: touchManager)! XCTAssertFalse(scheduler.isContextScheduled(context)) @@ -66,7 +109,7 @@ final class CBSchedulerTests: XCTestCase { } func testIsContextScheduledForDifferentObjectName() { - let context = CBScriptContext(script: startScript, spriteNode: spriteNode, formulaInterpreter: interpreter, touchManager: touchManager)! + let context = CBScriptContext(script: startScript, spriteNode: spriteNode1, formulaInterpreter: interpreter, touchManager: touchManager)! scheduler.registerContext(context) scheduler.scheduleContext(context) @@ -82,7 +125,7 @@ final class CBSchedulerTests: XCTestCase { script.object = spriteObject script.look = look - let context = CBWhenBackgroundChangesScriptContext(whenBackgroundChangesScript: script, spriteNode: spriteNode, formulaInterpreter: interpreter, touchManager: touchManager, state: .runnable)! + let context = CBWhenBackgroundChangesScriptContext(whenBackgroundChangesScript: script, spriteNode: spriteNode1, formulaInterpreter: interpreter, touchManager: touchManager, state: .runnable)! XCTAssertFalse(scheduler.isWhenBackgroundChangesContextScheduled(look: look)) @@ -100,7 +143,7 @@ final class CBSchedulerTests: XCTestCase { script.object = spriteObject script.look = lookA - let context = CBWhenBackgroundChangesScriptContext(whenBackgroundChangesScript: script, spriteNode: spriteNode, formulaInterpreter: interpreter, touchManager: touchManager, state: .runnable)! + let context = CBWhenBackgroundChangesScriptContext(whenBackgroundChangesScript: script, spriteNode: spriteNode1, formulaInterpreter: interpreter, touchManager: touchManager, state: .runnable)! scheduler.registerContext(context) scheduler.scheduleContext(context) diff --git a/src/CattyTests/Resources/ParserTests/Custom/ValidProjectAllBricks/ValidProjectAllBricks0991.xml b/src/CattyTests/Resources/ParserTests/Custom/ValidProjectAllBricks/ValidProjectAllBricks0991.xml index d3f3f6c3e3..39509242a1 100755 --- a/src/CattyTests/Resources/ParserTests/Custom/ValidProjectAllBricks/ValidProjectAllBricks0991.xml +++ b/src/CattyTests/Resources/ParserTests/Custom/ValidProjectAllBricks/ValidProjectAllBricks0991.xml @@ -674,6 +674,18 @@ + + false + 0 + + + false + 1 + + + false + 2 + false false diff --git a/src/CattyTests/XML/Parser/CatrobatLanguage0.991/XMLParserTests0991.swift b/src/CattyTests/XML/Parser/CatrobatLanguage0.991/XMLParserTests0991.swift index e410f83ea0..91b384342b 100644 --- a/src/CattyTests/XML/Parser/CatrobatLanguage0.991/XMLParserTests0991.swift +++ b/src/CattyTests/XML/Parser/CatrobatLanguage0.991/XMLParserTests0991.swift @@ -581,4 +581,25 @@ class XMLParserTests0991: XMLAbstractTest { XCTAssertEqual((background.lookList.object(at: 0) as! Look), brickWithValidBackgroundReference.look) XCTAssertNil(brickWithInvalidBackgroundReference.look) } + + func testStopBrick() { + let project = self.getProjectForXML(xmlFile: "ValidProjectAllBricks0991") + let background = project.scene.object(at: 0)! + + let backgroundScript = background.scriptList.object(at: 0) as! Script + XCTAssertGreaterThanOrEqual(backgroundScript.brickList.count, 53, "Invalid brick list") + + let stopScriptThisBrick = backgroundScript.brickList.object(at: 50) as! Brick + XCTAssertTrue(stopScriptThisBrick.isKind(of: StopScriptBrick.self), "Invalid brick type") + let stopScriptAllBrick = backgroundScript.brickList.object(at: 51) as! Brick + XCTAssertTrue(stopScriptAllBrick.isKind(of: StopScriptBrick.self), "Invalid brick type") + let stopScriptOtherBrick = backgroundScript.brickList.object(at: 52) as! Brick + XCTAssertTrue(stopScriptOtherBrick.isKind(of: StopScriptBrick.self), "Invalid brick type") + let textThis = (stopScriptThisBrick as! StopScriptBrick).selection + XCTAssertEqual(StopStyle.thisScript, textThis, "Invalid list value") + let textAll = (stopScriptAllBrick as! StopScriptBrick).selection + XCTAssertEqual(StopStyle.allScripts, textAll, "Invalid list value") + let textOther = (stopScriptOtherBrick as! StopScriptBrick).selection + XCTAssertEqual(StopStyle.otherScripts, textOther, "Invalid list value") + } } diff --git a/src/CattyUITests/Defines/LanguageTranslationDefinesUI.swift b/src/CattyUITests/Defines/LanguageTranslationDefinesUI.swift index 8680305e4e..8f603457ca 100644 --- a/src/CattyUITests/Defines/LanguageTranslationDefinesUI.swift +++ b/src/CattyUITests/Defines/LanguageTranslationDefinesUI.swift @@ -389,6 +389,7 @@ let kLocalizedTimes = NSLocalizedString("times", bundle: Bundle(for: LanguageTra let kLocalizedEndOfLoop = NSLocalizedString("End of Loop", bundle: Bundle(for: LanguageTranslation.self), comment: "") let kLocalizedWhen = NSLocalizedString("When", bundle: Bundle(for: LanguageTranslation.self), comment: "") let kLocalizedBecomesTrue = NSLocalizedString("becomes true", bundle: Bundle(for: LanguageTranslation.self), comment: "") +let kLocalizedStop = NSLocalizedString("Stop", bundle: Bundle(for: LanguageTranslation.self), comment: "") // motion bricks let kLocalizedPlaceAt = NSLocalizedString("Place at ", bundle: Bundle(for: LanguageTranslation.self), comment: "")