From bb9ddfbddf85921989810185e98eb24ad244ead6 Mon Sep 17 00:00:00 2001 From: amelak9 Date: Fri, 6 Aug 2021 15:44:48 +0200 Subject: [PATCH] CATTY-552 Clone object or actor --- src/Catty.xcodeproj/project.pbxproj | 22 ++++ src/Catty/CloneBrick+Instruction.swift | 110 ++++++++++++++++++ .../Arduino/ArduinoSendDigitalValueBrick.m | 10 ++ .../Bricks/Arduino/ArduinoSendPWMValueBrick.m | 10 ++ src/Catty/DataModel/Bricks/Brick.h | 5 +- src/Catty/DataModel/Bricks/Brick.m | 9 ++ .../DataModel/Bricks/Control/BroadcastBrick.m | 9 ++ .../Bricks/Control/BroadcastWaitBrick.m | 9 ++ .../DataModel/Bricks/Control/CloneBrick.swift | 91 +++++++++++++++ .../DataModel/Bricks/Control/ForeverBrick.m | 7 ++ .../Bricks/Control/IfLogicBeginBrick.m | 9 ++ .../Bricks/Control/IfLogicElseBrick.m | 19 +++ .../Bricks/Control/IfLogicEndBrick.m | 27 +++++ .../Bricks/Control/IfThenLogicBeginBrick.m | 9 ++ .../Bricks/Control/IfThenLogicEndBrick.m | 19 +++ .../DataModel/Bricks/Control/LoopEndBrick.m | 19 +++ .../DataModel/Bricks/Control/NoteBrick.m | 9 ++ .../DataModel/Bricks/Control/RepeatBrick.m | 10 ++ .../Bricks/Control/RepeatUntilBrick.m | 9 ++ .../DataModel/Bricks/Control/WaitBrick.m | 9 ++ .../DataModel/Bricks/Control/WaitUntilBrick.m | 9 ++ .../Bricks/Data/AddItemToUserListBrick.m | 14 +++ .../Bricks/Data/ChangeVariableBrick.m | 14 +++ .../Bricks/Data/DeleteItemOfUserListBrick.m | 14 +++ .../DataModel/Bricks/Data/HideTextBrick.m | 13 +++ .../Bricks/Data/InsertItemIntoUserListBrick.m | 15 +++ .../Bricks/Data/ReplaceItemInUserListBrick.m | 15 +++ .../DataModel/Bricks/Data/SetVariableBrick.m | 14 +++ .../DataModel/Bricks/Data/ShowTextBrick.m | 15 +++ .../Bricks/Data/WebRequestBrick.swift | 11 ++ .../Bricks/Embroidery/SewUpBrick.swift | 7 ++ .../Embroidery/StartRunningStitchBrick.swift | 8 ++ .../Bricks/Embroidery/StitchBrick.swift | 7 ++ .../Embroidery/StopCurrentStitchBrick.swift | 7 ++ src/Catty/DataModel/Bricks/IO/FlashBrick.m | 9 ++ .../DataModel/Bricks/IO/VibrationBrick.m | 9 ++ .../DataModel/Bricks/Look/AskBrick.swift | 9 ++ src/Catty/DataModel/Bricks/Look/CameraBrick.m | 9 ++ .../Look/ChangeBrightnessByNBrick.swift | 8 ++ .../Bricks/Look/ChangeColorByNBrick.m | 9 ++ .../Bricks/Look/ChangeTransparencyByNBrick.m | 9 ++ .../DataModel/Bricks/Look/ChooseCameraBrick.m | 9 ++ .../Bricks/Look/ClearGraphicEffectBrick.m | 8 ++ src/Catty/DataModel/Bricks/Look/HideBrick.m | 9 ++ .../DataModel/Bricks/Look/NextLookBrick.swift | 7 ++ .../Bricks/Look/PreviousLookBrick.swift | 7 ++ .../DataModel/Bricks/Look/SayBubbleBrick.m | 9 ++ .../DataModel/Bricks/Look/SayForBubbleBrick.m | 10 ++ .../Look/SetBackgroundAndWaitBrick.swift | 8 ++ .../Bricks/Look/SetBackgroundBrick.swift | 8 ++ .../Look/SetBackgroundByIndexBrick.swift | 8 ++ .../Bricks/Look/SetBrightnessBrick.swift | 8 ++ .../DataModel/Bricks/Look/SetColorBrick.m | 9 ++ .../DataModel/Bricks/Look/SetLookBrick.swift | 8 ++ .../Bricks/Look/SetLookByIndexBrick.swift | 8 ++ .../DataModel/Bricks/Look/SetSizeToBrick.m | 9 ++ .../Bricks/Look/SetTransparencyBrick.m | 9 ++ src/Catty/DataModel/Bricks/Look/ShowBrick.m | 8 ++ .../DataModel/Bricks/Look/ThinkBubbleBrick.m | 9 ++ .../Bricks/Look/ThinkForBubbleBrick.m | 10 ++ .../Bricks/Motion/ChangeSizeByNBrick.m | 9 ++ .../DataModel/Bricks/Motion/ChangeXByNBrick.m | 9 ++ .../DataModel/Bricks/Motion/ChangeYByNBrick.m | 9 ++ .../Bricks/Motion/ComeToFrontBrick.m | 8 ++ .../DataModel/Bricks/Motion/GlideToBrick.m | 10 ++ .../Bricks/Motion/GoNStepsBackBrick.m | 9 ++ src/Catty/DataModel/Bricks/Motion/GoToBrick.m | 10 ++ .../Bricks/Motion/IfOnEdgeBounceBrick.m | 8 ++ .../DataModel/Bricks/Motion/MoveNStepsBrick.m | 9 ++ .../DataModel/Bricks/Motion/PlaceAtBrick.m | 10 ++ .../Bricks/Motion/PointInDirectionBrick.m | 9 ++ .../DataModel/Bricks/Motion/PointToBrick.h | 1 + .../DataModel/Bricks/Motion/PointToBrick.m | 13 +++ .../Bricks/Motion/SetRotationStyleBrick.swift | 8 ++ src/Catty/DataModel/Bricks/Motion/SetXBrick.m | 9 ++ src/Catty/DataModel/Bricks/Motion/SetYBrick.m | 9 ++ .../DataModel/Bricks/Motion/TurnLeftBrick.m | 9 ++ .../DataModel/Bricks/Motion/TurnRightBrick.m | 9 ++ .../DataModel/Bricks/Pen/PenClearBrick.swift | 6 + .../DataModel/Bricks/Pen/PenDownBrick.swift | 6 + .../DataModel/Bricks/Pen/PenUpBrick.swift | 6 + .../Bricks/Pen/SetPenColorBrick.swift | 9 ++ .../Bricks/Pen/SetPenSizeBrick.swift | 7 ++ .../DataModel/Bricks/Pen/StampBrick.swift | 6 + .../Bricks/Phiro/PhiroIfLogicBeginBrick.m | 9 ++ .../Phiro/PhiroMotorMoveBackwardBrick.m | 10 ++ .../Bricks/Phiro/PhiroMotorMoveForwardBrick.m | 10 ++ .../Bricks/Phiro/PhiroMotorStopBrick.m | 9 ++ .../Bricks/Phiro/PhiroPlayToneBrick.m | 10 ++ .../Bricks/Phiro/PhiroRGBLightBrick.m | 12 ++ .../Bricks/Sound/ChangeVolumeByNBrick.m | 9 ++ .../Bricks/Sound/PlaySoundAndWaitBrick.m | 9 ++ .../DataModel/Bricks/Sound/PlaySoundBrick.m | 9 ++ .../Bricks/Sound/SetInstrumentBrick.swift | 8 ++ .../Bricks/Sound/SetTempoToBrick.swift | 10 +- .../DataModel/Bricks/Sound/SetVolumeToBrick.m | 9 ++ .../Bricks/Sound/SpeakAndWaitBrick.m | 9 ++ src/Catty/DataModel/Bricks/Sound/SpeakBrick.m | 9 ++ .../Bricks/Sound/StopAllSoundsBrick.m | 8 ++ src/Catty/DataModel/Scene/Scene.swift | 5 + src/Catty/DataModel/Scripts/BroadcastScript.m | 9 ++ src/Catty/DataModel/Scripts/Script.h | 1 + src/Catty/DataModel/Scripts/Script.m | 9 ++ src/Catty/DataModel/Scripts/StartScript.m | 8 ++ .../Scripts/WhenBackgroundChangesScript.swift | 8 ++ .../Scripts/WhenConditionScript.swift | 10 ++ src/Catty/DataModel/Scripts/WhenScript.m | 9 ++ .../DataModel/Scripts/WhenTouchDownScript.m | 8 ++ .../Defines/LanguageTranslationDefines.h | 1 + .../LanguageTranslationDefinesSwift.swift | 1 + .../BrickObjectWithOutBackgroundProtocol.h | 33 ++++++ .../DataModel/CBSpriteNode/CBSpriteNode.swift | 15 +++ src/Catty/PlayerEngine/Stage/Stage.swift | 86 ++++++++++++++ .../Localization/en.lproj/Localizable.strings | 3 + src/Catty/Setup/CatrobatSetup+Bricks.swift | 1 + .../ScriptCollectionViewController.m | 8 +- .../BrickCellData/BrickCellObjectData.m | 17 +++ .../BrickCells/Control/CloneBrickCell.swift | 53 +++++++++ .../Context/Abstract/CBXMLAbstractContext.h | 1 + .../Context/Abstract/CBXMLAbstractContext.m | 8 ++ .../SpriteObject/SpriteObject+CBXMLHandler.h | 2 + .../SpriteObject/SpriteObject+CBXMLHandler.m | 16 ++- .../Bricks/CloneBrick+CBXMLHandler.swift | 104 +++++++++++++++++ src/CattyTests/Bricks/CloneBrickTests.swift | 104 +++++++++++++++++ .../ValidProjectAllBricks0992.xml | 15 +++ .../XMLParserTests0992.swift | 11 ++ .../LanguageTranslationDefinesUI.swift | 1 + 127 files changed, 1683 insertions(+), 9 deletions(-) create mode 100644 src/Catty/CloneBrick+Instruction.swift create mode 100644 src/Catty/DataModel/Bricks/Control/CloneBrick.swift create mode 100644 src/Catty/Extension&Delegate&Protocol/Protocols/Bricks/BrickData/BrickObjectWithOutBackgroundProtocol.h create mode 100644 src/Catty/Views/Custom/CollectionViewCells/BrickCells/Control/CloneBrickCell.swift create mode 100644 src/CattyTests/Bricks/CloneBrick+CBXMLHandler.swift create mode 100644 src/CattyTests/Bricks/CloneBrickTests.swift diff --git a/src/Catty.xcodeproj/project.pbxproj b/src/Catty.xcodeproj/project.pbxproj index ab1173500a..fb0348c54c 100644 --- a/src/Catty.xcodeproj/project.pbxproj +++ b/src/Catty.xcodeproj/project.pbxproj @@ -1220,6 +1220,11 @@ 972622DD25F51A8F00ABCC7A /* ChangeBrightnessByNBrick+CBXMLHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 972622DC25F51A8F00ABCC7A /* ChangeBrightnessByNBrick+CBXMLHandler.swift */; }; 972622E225F51B4500ABCC7A /* SetBrightnessBrick+CBXMLHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 972622E125F51B4500ABCC7A /* SetBrightnessBrick+CBXMLHandler.swift */; }; 9728AE9E25DEEE5A00708EB6 /* ProjectDetailStoreViewControllerReportExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9728AE9D25DEEE5A00708EB6 /* ProjectDetailStoreViewControllerReportExtension.swift */; }; + 973F1D3226B1923F0043108A /* CloneBrick+CBXMLHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 973F1D3126B1923F0043108A /* CloneBrick+CBXMLHandler.swift */; }; + 9740489026B04FAE0047DEBB /* CloneBrick.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9740488F26B04FAE0047DEBB /* CloneBrick.swift */; }; + 9740489426B052950047DEBB /* CloneBrickCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9740489326B052950047DEBB /* CloneBrickCell.swift */; }; + 9740489626B0547D0047DEBB /* CloneBrick+Instruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9740489526B0547D0047DEBB /* CloneBrick+Instruction.swift */; }; + 9740489E26B097500047DEBB /* CloneBrickTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9740489D26B097500047DEBB /* CloneBrickTests.swift */; }; 97417A9B265284400079A2A2 /* SoundsTableViewController+SelectFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97417A9A265284400079A2A2 /* SoundsTableViewController+SelectFile.swift */; }; 9742DC5B269A2EC600980DE8 /* TouchesFingerSensorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9742DC5A269A2EC600980DE8 /* TouchesFingerSensorTest.swift */; }; 9767BAFA26668ECD009794E8 /* JoinThreeStringsFunctionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767BAF926668ECD009794E8 /* JoinThreeStringsFunctionTest.swift */; }; @@ -3491,6 +3496,11 @@ 972622DC25F51A8F00ABCC7A /* ChangeBrightnessByNBrick+CBXMLHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ChangeBrightnessByNBrick+CBXMLHandler.swift"; sourceTree = ""; }; 972622E125F51B4500ABCC7A /* SetBrightnessBrick+CBXMLHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SetBrightnessBrick+CBXMLHandler.swift"; sourceTree = ""; }; 9728AE9D25DEEE5A00708EB6 /* ProjectDetailStoreViewControllerReportExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectDetailStoreViewControllerReportExtension.swift; sourceTree = ""; }; + 973F1D3126B1923F0043108A /* CloneBrick+CBXMLHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "CloneBrick+CBXMLHandler.swift"; path = "CattyTests/Bricks/CloneBrick+CBXMLHandler.swift"; sourceTree = SOURCE_ROOT; }; + 9740488F26B04FAE0047DEBB /* CloneBrick.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloneBrick.swift; sourceTree = ""; }; + 9740489326B052950047DEBB /* CloneBrickCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloneBrickCell.swift; sourceTree = ""; }; + 9740489526B0547D0047DEBB /* CloneBrick+Instruction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CloneBrick+Instruction.swift"; sourceTree = ""; }; + 9740489D26B097500047DEBB /* CloneBrickTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloneBrickTests.swift; sourceTree = ""; }; 97417A9A265284400079A2A2 /* SoundsTableViewController+SelectFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SoundsTableViewController+SelectFile.swift"; sourceTree = ""; }; 9742DC5A269A2EC600980DE8 /* TouchesFingerSensorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TouchesFingerSensorTest.swift; sourceTree = ""; }; 9767BAF926668ECD009794E8 /* JoinThreeStringsFunctionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinThreeStringsFunctionTest.swift; sourceTree = ""; }; @@ -4152,6 +4162,7 @@ C82FC8DC26964F4A008DFBB8 /* TouchesFingerSensor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchesFingerSensor.swift; sourceTree = ""; }; C84B21702714A2690077CF70 /* TouchesEdgeSensor.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = TouchesEdgeSensor.xml; sourceTree = ""; }; C85A5C9F267A218F009BA454 /* Functions_0993.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Functions_0993.xml; sourceTree = ""; }; + C88FFF5D26B830E100D381D8 /* BrickObjectWithOutBackgroundProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BrickObjectWithOutBackgroundProtocol.h; sourceTree = ""; }; C8A0338226064F3C00702911 /* SetTempoToBrick+CBXMLHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "SetTempoToBrick+CBXMLHandler.swift"; path = "Catty/Views/Custom/CollectionViewCells/BrickCells/Sound/SetTempoToBrick+CBXMLHandler.swift"; sourceTree = SOURCE_ROOT; }; C8CD7DD325E63D0A0018C655 /* BrickCategoryOverviewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrickCategoryOverviewControllerTests.swift; sourceTree = ""; }; C8D010C3264BD2B700896DEB /* JoinThreeStringsFunction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinThreeStringsFunction.swift; sourceTree = ""; }; @@ -5970,6 +5981,7 @@ 9990BB6C1D89D89A0088357A /* BrickStaticChoiceProtocol.h */, 4C1EB20F1AC19B3D0001F431 /* BrickTextProtocol.h */, 4CC0D51F1B01FB73006193C4 /* BrickVariableProtocol.h */, + C88FFF5D26B830E100D381D8 /* BrickObjectWithOutBackgroundProtocol.h */, ); path = BrickData; sourceTree = ""; @@ -6325,6 +6337,7 @@ AA74EEDA1BC057B900D1E954 /* WaitBrick+CBXMLHandler.m */, BA987D042194DDCF002DAA05 /* WaitUntilBrick+CBXMLHandler.h */, BA987D032194DDCF002DAA05 /* WaitUntilBrick+CBXMLHandler.m */, + 973F1D3126B1923F0043108A /* CloneBrick+CBXMLHandler.swift */, ); name = Control; path = ControlBricks; @@ -7169,6 +7182,7 @@ 83F8230725EBA9610093DD9A /* SetBackgroundByIndexBrickTests.swift */, 2E8780A72542BCE200816B52 /* WebRequestBrickTests.swift */, 0580514826EF734F00F719E0 /* StartRunningStitchBrickTests.swift */, + 9740489D26B097500047DEBB /* CloneBrickTests.swift */, ); path = Bricks; sourceTree = ""; @@ -9655,6 +9669,7 @@ AA74EE1F1BC053FD00D1E954 /* BroadcastWaitBrick+Instruction.swift */, AA74EE201BC053FD00D1E954 /* WaitBrick+Instruction.swift */, BA987D0E2194EA1F002DAA05 /* WaitUntilBrick+Instruction.swift */, + 9740489526B0547D0047DEBB /* CloneBrick+Instruction.swift */, ); name = Control; sourceTree = ""; @@ -9788,6 +9803,7 @@ AA74EF951BC05B5F00D1E954 /* WaitBrick.m */, BA987D072194E158002DAA05 /* WaitUntilBrick.h */, BA987D062194E157002DAA05 /* WaitUntilBrick.m */, + 9740488F26B04FAE0047DEBB /* CloneBrick.swift */, ); path = Control; sourceTree = ""; @@ -10028,6 +10044,7 @@ 9EDCD22422886FD90040EFE3 /* WaitBrickCell.swift */, BA987D0A2194E25A002DAA05 /* WaitUntilBrickCell.h */, BA987D092194E25A002DAA05 /* WaitUntilBrickCell.m */, + 9740489326B052950047DEBB /* CloneBrickCell.swift */, ); path = Control; sourceTree = ""; @@ -11950,6 +11967,7 @@ 9E24D7032326E8E600608203 /* TurnLeftBrickTests.swift in Sources */, E57E6D872540414700E775DF /* SetVolumeToBrickTests.swift in Sources */, 4C968C401F00288500355C0D /* BrickTests.swift in Sources */, + 9740489E26B097500047DEBB /* CloneBrickTests.swift in Sources */, E579F10B253D98B0009107C8 /* PhiroPlayToneBrickTests.swift in Sources */, E579F114253DCA96009107C8 /* ThinkBubbleBrickTests.swift in Sources */, 4C0F9FD9204BD3D500E71B2D /* RepeatUntilBrickTests.swift in Sources */, @@ -12293,6 +12311,7 @@ AA74F0BD1BC05FCE00D1E954 /* PlaceAtBrickCell.m in Sources */, 18390A6924D0576100A07DFD /* StampBrick.swift in Sources */, CA3E72E81B0C00A500D6B184 /* CBStack.swift in Sources */, + 9740489426B052950047DEBB /* CloneBrickCell.swift in Sources */, AA74EFFE1BC05B5F00D1E954 /* ComeToFrontBrick.m in Sources */, 057B182A26DC8B6A00C47E60 /* StartRunningStitchBrick.swift in Sources */, 92FF31051A24DCAA00093DA7 /* WhenScript.m in Sources */, @@ -12312,6 +12331,7 @@ 2D6E3F3B210A0AB700FB8139 /* ChartProjectsStoreViewController.swift in Sources */, 92FF2EA41A24C7D800093DA7 /* Util.m in Sources */, AA74EFEC1BC05B5F00D1E954 /* ChangeVariableBrick.m in Sources */, + 973F1D3226B1923F0043108A /* CloneBrick+CBXMLHandler.swift in Sources */, 92FF31031A24DCAA00093DA7 /* Script.m in Sources */, 4C822693213FBC4400F3D750 /* MultiFingerTouchedFunction.swift in Sources */, 4420ACB1250929AE00951328 /* AskBrick+CBXMLHandler.swift in Sources */, @@ -12319,10 +12339,12 @@ 4C0F9F9E204BD2B100E71B2D /* SayBubbleBrickCell.m in Sources */, 4C2EE41E1B555B55006DE9B8 /* CBXMLOpenedNestingBricksStack.m in Sources */, 5EFBD5F92145533B003B3CDC /* ProjectDescriptionViewController.swift in Sources */, + 9740489626B0547D0047DEBB /* CloneBrick+Instruction.swift in Sources */, 92FF31571A24DEB300093DA7 /* ObjectTableViewController.m in Sources */, 4CE3D68F2107B68600005629 /* FaceDetectionManagerProtocol.swift in Sources */, 929CC0EF1BC39B8C0027DEC0 /* PhiroMotorStopBrickCell.m in Sources */, 4C0F9F64204BD18600E71B2D /* SayForBubbleBrick+CBXMLHandler.m in Sources */, + 9740489026B04FAE0047DEBB /* CloneBrick.swift in Sources */, 92FF32BB1A24E2F400093DA7 /* DarkBlueGradientImageCell.m in Sources */, 92FF314E1A24DEB300093DA7 /* LookImageViewController.m in Sources */, AA74F0A41BC05FCE00D1E954 /* LoopEndBrickCell.m in Sources */, diff --git a/src/Catty/CloneBrick+Instruction.swift b/src/Catty/CloneBrick+Instruction.swift new file mode 100644 index 0000000000..9d3a088281 --- /dev/null +++ b/src/Catty/CloneBrick+Instruction.swift @@ -0,0 +1,110 @@ +/** + * 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 CloneBrick: CBInstructionProtocol { + + @nonobjc func instruction() -> CBInstruction { + .action { context in SKAction.run(self.actionBlock(context.formulaInterpreter)) } + } + + func actionBlock(_ formulaInterpreter: FormulaInterpreterProtocol) -> () -> Void { + guard let objectToClone = self.objectToClone + else { fatalError("This should never happen!") } + + return { + let object = SpriteObject() + object.name = objectToClone.name + "Clone " + String(CloneBrick.nameCounter) + CloneBrick.nameCounter += 1 + + guard let scriptList = objectToClone.scriptList as NSMutableArray? as? [Script] else { + //fatalError + debugPrint("!! No script list given in object: \(objectToClone) !!") + return + } + + let context = CBMutableCopyContext() + let variables = objectToClone.userData.variables() + let lists = objectToClone.userData.lists() + + for variable in variables { + let var1 = UserVariable(name: variable.name) + let label = SKLabelNode(fontNamed: SpriteKitDefines.defaultFont) + var1.value = variable.value + var1.textLabel = label + + let value = variable.value as! Int? ?? 0 + var1.textLabel?.text = String(value) + var1.textLabel?.fontColor = variable.textLabel?.fontColor ?? UIColor.black + var1.textLabel?.fontSize = variable.textLabel?.fontSize ?? CGFloat(SpriteKitDefines.defaultLabelFontSize) + var1.textLabel?.position = variable.textLabel?.position ?? CGPoint(x: 0, y: 0) + var1.textLabel?.isHidden = variable.textLabel?.isHidden ?? true + object.userData.add(var1) + } + + for list in lists { + let list1 = list.mutableCopy(with: context) as! UserList + object.userData.add(list1) + } + + for script in scriptList { + let newScript = script.clone(with: object)! + self.setScriptAttributes(script: newScript, oldScript: script) + for brick in script.brickList { + let brickToClone = brick as! Brick + let newBrick = brickToClone.clone(with: newScript)! + self.setBrickAttributes(brick: newBrick, oldBrick: brickToClone) + newScript.brickList.add(newBrick) + } + object.scriptList.add(newScript) + } + + object.soundList = objectToClone.soundList.mutableCopy() as? NSMutableArray + object.lookList = objectToClone.lookList.mutableCopy() as? NSMutableArray + + objectToClone.scene.add(object: object) + let spriteNode = CBSpriteNode(spriteObject: object) + object.spriteNode = spriteNode + + let stage = objectToClone.spriteNode.scene as? Stage + stage?.addChild(object.spriteNode) + object.spriteNode.startAsClone(objectToClone.spriteNode) + stage?.scheduler.registerSpriteNode(object.spriteNode) + stage?.addClonedObjecToProject(spriteObject: object) + } + } + + func setBrickAttributes(brick: Brick, oldBrick: Brick) { + brick.isDisabled = oldBrick.isDisabled + brick.isSelected = oldBrick.isSelected + brick.isAnimatedMoveBrick = oldBrick.isAnimatedMoveBrick + brick.isAnimatedInsertBrick = oldBrick.isAnimatedInsertBrick + brick.isAnimated = oldBrick.isAnimated + } + + func setScriptAttributes(script: Script, oldScript: Script) { + script.isDisabled = oldScript.isDisabled + script.isSelected = oldScript.isSelected + script.isAnimatedMoveBrick = oldScript.isAnimatedMoveBrick + script.isAnimatedInsertBrick = oldScript.isAnimatedInsertBrick + script.isAnimated = oldScript.isAnimated + } +} diff --git a/src/Catty/DataModel/Bricks/Arduino/ArduinoSendDigitalValueBrick.m b/src/Catty/DataModel/Bricks/Arduino/ArduinoSendDigitalValueBrick.m index 48dbcd974d..aa01ce7eea 100644 --- a/src/Catty/DataModel/Bricks/Arduino/ArduinoSendDigitalValueBrick.m +++ b/src/Catty/DataModel/Bricks/Arduino/ArduinoSendDigitalValueBrick.m @@ -58,6 +58,16 @@ - (BOOL)allowsStringFormula return NO; } +- (Brick*)cloneWithScript:(Script *)script +{ + ArduinoSendDigitalValueBrick *clone = [[ArduinoSendDigitalValueBrick alloc] init]; + clone.script = script; + clone.pin = self.pin; + clone.value = self.value; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Arduino/ArduinoSendPWMValueBrick.m b/src/Catty/DataModel/Bricks/Arduino/ArduinoSendPWMValueBrick.m index c01608bce8..e5900df971 100644 --- a/src/Catty/DataModel/Bricks/Arduino/ArduinoSendPWMValueBrick.m +++ b/src/Catty/DataModel/Bricks/Arduino/ArduinoSendPWMValueBrick.m @@ -58,6 +58,16 @@ - (BOOL)allowsStringFormula return NO; } +- (Brick*)cloneWithScript:(Script *)script +{ + ArduinoSendPWMValueBrick *clone = [[ArduinoSendPWMValueBrick alloc] init]; + clone.script = script; + clone.pin = self.pin; + clone.value = self.value; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Brick.h b/src/Catty/DataModel/Bricks/Brick.h index ac6a416029..02b50fddce 100644 --- a/src/Catty/DataModel/Bricks/Brick.h +++ b/src/Catty/DataModel/Bricks/Brick.h @@ -24,8 +24,7 @@ #import "SpriteObject.h" #import "UIDefines.h" #import "BrickProtocol.h" - -@class Script; +#import "Script.h" @interface Brick : NSObject @@ -72,4 +71,6 @@ - (Class)brickCell; +- (Brick*)cloneWithScript:(Script *) script; + @end diff --git a/src/Catty/DataModel/Bricks/Brick.m b/src/Catty/DataModel/Bricks/Brick.m index 3bb3682a9a..fa18892b2a 100644 --- a/src/Catty/DataModel/Bricks/Brick.m +++ b/src/Catty/DataModel/Bricks/Brick.m @@ -126,6 +126,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject // Override this method in Brick implementation } +- (Brick*)cloneWithScript:(Script *)script +{ + // Override this method in Brick implementation + Brick *clone = [[Brick alloc] init]; + clone.script = script; + + return clone; +} + #pragma mark - Copy // This function must be overriden by Bricks with references to other Bricks (e.g. ForeverBrick) - (id)mutableCopyWithContext:(CBMutableCopyContext*)context diff --git a/src/Catty/DataModel/Bricks/Control/BroadcastBrick.m b/src/Catty/DataModel/Bricks/Control/BroadcastBrick.m index 1ab978577a..a6008ea131 100644 --- a/src/Catty/DataModel/Bricks/Control/BroadcastBrick.m +++ b/src/Catty/DataModel/Bricks/Control/BroadcastBrick.m @@ -67,6 +67,15 @@ - (NSString*)messageForLineNumber:(NSInteger)lineNumber andParameterNumber:(NSIn return self.broadcastMessage; } +- (Brick*)cloneWithScript:(Script *)script +{ + BroadcastBrick *clone = [[BroadcastBrick alloc] init]; + clone.script = script; + clone.broadcastMessage = self.broadcastMessage; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Control/BroadcastWaitBrick.m b/src/Catty/DataModel/Bricks/Control/BroadcastWaitBrick.m index a62100117f..c3f20bfee4 100644 --- a/src/Catty/DataModel/Bricks/Control/BroadcastWaitBrick.m +++ b/src/Catty/DataModel/Bricks/Control/BroadcastWaitBrick.m @@ -66,6 +66,15 @@ - (NSString*)messageForLineNumber:(NSInteger)lineNumber andParameterNumber:(NSIn return self.broadcastMessage; } +- (Brick*)cloneWithScript:(Script *)script +{ + BroadcastWaitBrick *clone = [[BroadcastWaitBrick alloc] init]; + clone.script = script; + clone.broadcastMessage = self.broadcastMessage; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Control/CloneBrick.swift b/src/Catty/DataModel/Bricks/Control/CloneBrick.swift new file mode 100644 index 0000000000..d572fe222d --- /dev/null +++ b/src/Catty/DataModel/Bricks/Control/CloneBrick.swift @@ -0,0 +1,91 @@ +/** + * 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(CloneBrick) +@objcMembers class CloneBrick: Brick, BrickObjectWithOutBackgroundProtocol { + + var objectToClone: SpriteObject? + static var nameCounter: Int = 1 + + override required init() { + super.init() + } + + func category() -> kBrickCategoryType { + kBrickCategoryType.eventBrick + } + + override class func description() -> String { + "CloneBrick" + } + + override func getRequiredResources() -> Int { + ResourceType.noResources.rawValue + } + + override func brickCell() -> BrickCellProtocol.Type! { + CloneBrickCell.self as BrickCellProtocol.Type + } + + func setObject(_ object: SpriteObject?, forLineNumber lineNumber: Int, andParameterNumber paramNumber: Int) { + if let object = object { + objectToClone = object + } + } + + func object(forLineNumber lineNumber: Int, andParameterNumber paramNumber: Int) -> SpriteObject? { + self.objectToClone + } + + override func setDefaultValuesFor(_ spriteObject: SpriteObject!) { + if spriteObject != nil { + objectToClone = spriteObject + } else { + objectToClone = self.script.object + } + } + + override func isDisabledForBackground() -> Bool { + true + } + + @objc(mutableCopyWithContext:) + override func mutableCopy(with context: CBMutableCopyContext) -> Any { + let brick = CloneBrick() + if self.objectToClone != nil { + brick.objectToClone = self.objectToClone + } + return brick + } + + override func clone(with script: Script!) -> Brick! { + let clone = CloneBrick() + clone.script = script + if self.objectToClone == self.script.object { + clone.objectToClone = clone.script.object + } else { + clone.objectToClone = self.objectToClone + } + + return clone + } +} diff --git a/src/Catty/DataModel/Bricks/Control/ForeverBrick.m b/src/Catty/DataModel/Bricks/Control/ForeverBrick.m index 42b896293a..9359853cbf 100644 --- a/src/Catty/DataModel/Bricks/Control/ForeverBrick.m +++ b/src/Catty/DataModel/Bricks/Control/ForeverBrick.m @@ -34,6 +34,13 @@ - (BOOL)isAnimateable return YES; } +- (Brick*)cloneWithScript:(Script *)script +{ + ForeverBrick *clone = [[ForeverBrick alloc] init]; + clone.script = script; + + return clone; +} #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Control/IfLogicBeginBrick.m b/src/Catty/DataModel/Bricks/Control/IfLogicBeginBrick.m index 43f4281764..3ac40821d5 100644 --- a/src/Catty/DataModel/Bricks/Control/IfLogicBeginBrick.m +++ b/src/Catty/DataModel/Bricks/Control/IfLogicBeginBrick.m @@ -68,6 +68,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.ifCondition = [[Formula alloc] initWithInteger:1]; } +- (Brick*)cloneWithScript:(Script *)script +{ + IfLogicBeginBrick *clone = [[IfLogicBeginBrick alloc] init]; + clone.script = script; + clone.ifCondition = self.ifCondition; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Control/IfLogicElseBrick.m b/src/Catty/DataModel/Bricks/Control/IfLogicElseBrick.m index f457957111..b582d02119 100644 --- a/src/Catty/DataModel/Bricks/Control/IfLogicElseBrick.m +++ b/src/Catty/DataModel/Bricks/Control/IfLogicElseBrick.m @@ -52,6 +52,25 @@ - (void)performFromScript:(Script*)script NSDebug(@"Performing: %@", self.description); } +- (Brick*)cloneWithScript:(Script *)script +{ + IfLogicElseBrick *clone = [[IfLogicElseBrick alloc] init]; + clone.script = script; + + for (Brick *brick in script.brickList.reverseObjectEnumerator) { + if ([brick isKindOfClass: [IfLogicBeginBrick class]]) { + IfLogicBeginBrick *beginBrick = (IfLogicBeginBrick*) brick; + if (beginBrick.ifElseBrick == nil) { + beginBrick.ifElseBrick = clone; + clone.ifBeginBrick = beginBrick; + break; + } + } + } + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Control/IfLogicEndBrick.m b/src/Catty/DataModel/Bricks/Control/IfLogicEndBrick.m index eddfc9a908..cc766f5ea2 100644 --- a/src/Catty/DataModel/Bricks/Control/IfLogicEndBrick.m +++ b/src/Catty/DataModel/Bricks/Control/IfLogicEndBrick.m @@ -99,6 +99,33 @@ - (id)mutableCopyWithContext:(CBMutableCopyContext*)context return endBrick; } +- (Brick*)cloneWithScript:(Script *)script +{ + IfLogicEndBrick *clone = [[IfLogicEndBrick alloc] init]; + clone.script = script; + + for (Brick *brick in script.brickList.reverseObjectEnumerator) { + if ([brick isKindOfClass: [IfLogicBeginBrick class]]) { + IfLogicBeginBrick *beginBrick = (IfLogicBeginBrick*) brick; + if (beginBrick.ifEndBrick == nil && beginBrick.ifElseBrick != nil) { + beginBrick.ifEndBrick = clone; + clone.ifBeginBrick = beginBrick; + break; + } + } + + if ([brick isKindOfClass: [IfLogicElseBrick class]]) { + IfLogicElseBrick *elseBrick = (IfLogicElseBrick*) brick; + if (elseBrick.ifEndBrick == nil && elseBrick.ifBeginBrick != nil) { + elseBrick.ifEndBrick = clone; + clone.ifElseBrick = elseBrick; + } + } + } + + return clone; +} + #pragma mark - Resources - (NSInteger)getRequiredResources { diff --git a/src/Catty/DataModel/Bricks/Control/IfThenLogicBeginBrick.m b/src/Catty/DataModel/Bricks/Control/IfThenLogicBeginBrick.m index 360eee74f1..7df11e3588 100644 --- a/src/Catty/DataModel/Bricks/Control/IfThenLogicBeginBrick.m +++ b/src/Catty/DataModel/Bricks/Control/IfThenLogicBeginBrick.m @@ -67,6 +67,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.ifCondition = [[Formula alloc] initWithInteger:1]; } +- (Brick*)cloneWithScript:(Script *)script +{ + IfThenLogicBeginBrick *clone = [[IfThenLogicBeginBrick alloc] init]; + clone.script = script; + clone.ifCondition = self.ifCondition; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Control/IfThenLogicEndBrick.m b/src/Catty/DataModel/Bricks/Control/IfThenLogicEndBrick.m index f8d217f0f0..4b495d016c 100644 --- a/src/Catty/DataModel/Bricks/Control/IfThenLogicEndBrick.m +++ b/src/Catty/DataModel/Bricks/Control/IfThenLogicEndBrick.m @@ -52,6 +52,25 @@ - (void)performFromScript:(Script*)script } +- (Brick*)cloneWithScript:(Script *)script +{ + IfThenLogicEndBrick *clone = [[IfThenLogicEndBrick alloc] init]; + clone.script = script; + + for (Brick *brick in script.brickList.reverseObjectEnumerator) { + if ([brick isKindOfClass: [IfThenLogicBeginBrick class]]) { + IfThenLogicBeginBrick *beginBrick = (IfThenLogicBeginBrick*) brick; + if (beginBrick.ifEndBrick == nil) { + beginBrick.ifEndBrick = clone; + clone.ifBeginBrick = beginBrick; + break; + } + } + } + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Control/LoopEndBrick.m b/src/Catty/DataModel/Bricks/Control/LoopEndBrick.m index 0f28fbbc77..564095c460 100644 --- a/src/Catty/DataModel/Bricks/Control/LoopEndBrick.m +++ b/src/Catty/DataModel/Bricks/Control/LoopEndBrick.m @@ -52,6 +52,25 @@ - (void)performFromScript:(Script*)script NSDebug(@"Performing: %@", self.description); } +- (Brick*)cloneWithScript:(Script *)script +{ + LoopEndBrick *clone = [[LoopEndBrick alloc] init]; + clone.script = script; + + for (Brick *brick in script.brickList.reverseObjectEnumerator) { + if ([brick isKindOfClass: [LoopBeginBrick class]]) { + LoopBeginBrick *loopBeginBrick = (LoopBeginBrick*) brick; + if (loopBeginBrick.loopEndBrick == nil) { + loopBeginBrick.loopEndBrick = clone; + clone.loopBeginBrick = loopBeginBrick; + break; + } + } + } + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Control/NoteBrick.m b/src/Catty/DataModel/Bricks/Control/NoteBrick.m index 17524d6348..fe03de89da 100644 --- a/src/Catty/DataModel/Bricks/Control/NoteBrick.m +++ b/src/Catty/DataModel/Bricks/Control/NoteBrick.m @@ -50,6 +50,15 @@ - (NSString*)textForLineNumber:(NSInteger)lineNumber andParameterNumber:(NSInteg return self.note; } +- (Brick*)cloneWithScript:(Script *)script +{ + NoteBrick *clone = [[NoteBrick alloc] init]; + clone.script = script; + clone.note = self.note; + + return clone; +} + #pragma mark - Resources - (NSInteger)getRequiredResources { diff --git a/src/Catty/DataModel/Bricks/Control/RepeatBrick.m b/src/Catty/DataModel/Bricks/Control/RepeatBrick.m index 350500bf7c..e400a664a5 100644 --- a/src/Catty/DataModel/Bricks/Control/RepeatBrick.m +++ b/src/Catty/DataModel/Bricks/Control/RepeatBrick.m @@ -66,6 +66,16 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.timesToRepeat = [[Formula alloc] initWithInteger:10]; } +- (Brick*)cloneWithScript:(Script *)script +{ + RepeatBrick *clone = [[RepeatBrick alloc] init]; + clone.script = script; + clone.timesToRepeat = self.timesToRepeat; + clone.repetitions = self.repetitions; + clone.maxRepetitions = self.maxRepetitions; + + return clone; +} #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Control/RepeatUntilBrick.m b/src/Catty/DataModel/Bricks/Control/RepeatUntilBrick.m index 5fd2146269..fed384494e 100644 --- a/src/Catty/DataModel/Bricks/Control/RepeatUntilBrick.m +++ b/src/Catty/DataModel/Bricks/Control/RepeatUntilBrick.m @@ -63,6 +63,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.repeatCondition = [[Formula alloc] initWithInteger:1]; } +- (Brick*)cloneWithScript:(Script *)script +{ + RepeatUntilBrick *clone = [[RepeatUntilBrick alloc] init]; + clone.script = script; + clone.repeatCondition = self.repeatCondition; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Control/WaitBrick.m b/src/Catty/DataModel/Bricks/Control/WaitBrick.m index 309db7dbd0..c4a08f9d56 100644 --- a/src/Catty/DataModel/Bricks/Control/WaitBrick.m +++ b/src/Catty/DataModel/Bricks/Control/WaitBrick.m @@ -56,6 +56,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.timeToWaitInSeconds = [[Formula alloc] initWithInteger:1]; } +- (Brick*)cloneWithScript:(Script *)script +{ + WaitBrick *clone = [[WaitBrick alloc] init]; + clone.script = script; + clone.timeToWaitInSeconds = self.timeToWaitInSeconds; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Control/WaitUntilBrick.m b/src/Catty/DataModel/Bricks/Control/WaitUntilBrick.m index 1fb76f651c..2179b26dac 100644 --- a/src/Catty/DataModel/Bricks/Control/WaitUntilBrick.m +++ b/src/Catty/DataModel/Bricks/Control/WaitUntilBrick.m @@ -63,6 +63,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.waitCondition = [[Formula alloc] initWithInteger:1]; } +- (Brick*)cloneWithScript:(Script *)script +{ + WaitUntilBrick *clone = [[WaitUntilBrick alloc] init]; + clone.script = script; + clone.waitCondition = self.waitCondition; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Data/AddItemToUserListBrick.m b/src/Catty/DataModel/Bricks/Data/AddItemToUserListBrick.m index d729c27078..a72ff350db 100644 --- a/src/Catty/DataModel/Bricks/Data/AddItemToUserListBrick.m +++ b/src/Catty/DataModel/Bricks/Data/AddItemToUserListBrick.m @@ -75,6 +75,20 @@ - (BOOL)allowsStringFormula return YES; } +- (Brick*)cloneWithScript:(Script *)script +{ + AddItemToUserListBrick *clone = [[AddItemToUserListBrick alloc] init]; + clone.script = script; + for (UserList *userList in script.object.userData.lists) { + if (userList.name == self.userList.name) { + clone.userList = userList; + } + } + clone.listFormula = self.listFormula; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Data/ChangeVariableBrick.m b/src/Catty/DataModel/Bricks/Data/ChangeVariableBrick.m index b352ceb143..4110fac714 100644 --- a/src/Catty/DataModel/Bricks/Data/ChangeVariableBrick.m +++ b/src/Catty/DataModel/Bricks/Data/ChangeVariableBrick.m @@ -73,6 +73,20 @@ - (BOOL)allowsStringFormula return YES; } +- (Brick*)cloneWithScript:(Script *)script +{ + ChangeVariableBrick *clone = [[ChangeVariableBrick alloc] init]; + clone.script = script; + for (UserVariable *variable in script.object.userData.variables) { + if (variable.name == self.userVariable.name) { + clone.userVariable = variable; + } + } + clone.variableFormula = self.variableFormula; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Data/DeleteItemOfUserListBrick.m b/src/Catty/DataModel/Bricks/Data/DeleteItemOfUserListBrick.m index b930d43ff9..62a2313406 100644 --- a/src/Catty/DataModel/Bricks/Data/DeleteItemOfUserListBrick.m +++ b/src/Catty/DataModel/Bricks/Data/DeleteItemOfUserListBrick.m @@ -75,6 +75,20 @@ - (BOOL)allowsStringFormula return YES; } +- (Brick*)cloneWithScript:(Script *)script +{ + DeleteItemOfUserListBrick *clone = [[DeleteItemOfUserListBrick alloc] init]; + clone.script = script; + for (UserList *userList in script.object.userData.lists) { + if (userList.name == self.userList.name) { + clone.userList = userList; + } + } + clone.listFormula = self.listFormula; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Data/HideTextBrick.m b/src/Catty/DataModel/Bricks/Data/HideTextBrick.m index 9116641151..0923e78e74 100644 --- a/src/Catty/DataModel/Bricks/Data/HideTextBrick.m +++ b/src/Catty/DataModel/Bricks/Data/HideTextBrick.m @@ -53,6 +53,19 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject } } +- (Brick*)cloneWithScript:(Script *)script +{ + HideTextBrick *clone = [[HideTextBrick alloc] init]; + clone.script = script; + for (UserVariable *variable in script.object.userData.variables) { + if (variable.name == self.userVariable.name) { + clone.userVariable = variable; + } + } + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Data/InsertItemIntoUserListBrick.m b/src/Catty/DataModel/Bricks/Data/InsertItemIntoUserListBrick.m index 616a06f028..2d7d25fe92 100644 --- a/src/Catty/DataModel/Bricks/Data/InsertItemIntoUserListBrick.m +++ b/src/Catty/DataModel/Bricks/Data/InsertItemIntoUserListBrick.m @@ -84,6 +84,21 @@ - (BOOL)allowsStringFormula return YES; } +- (Brick*)cloneWithScript:(Script *)script +{ + InsertItemIntoUserListBrick *clone = [[InsertItemIntoUserListBrick alloc] init]; + clone.script = script; + for (UserList *userList in script.object.userData.lists) { + if (userList.name == self.userList.name) { + clone.userList = userList; + } + } + clone.elementFormula = self.elementFormula; + clone.index = self.index; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Data/ReplaceItemInUserListBrick.m b/src/Catty/DataModel/Bricks/Data/ReplaceItemInUserListBrick.m index 7d2ac07f99..06e5cc581a 100644 --- a/src/Catty/DataModel/Bricks/Data/ReplaceItemInUserListBrick.m +++ b/src/Catty/DataModel/Bricks/Data/ReplaceItemInUserListBrick.m @@ -84,6 +84,21 @@ - (BOOL)allowsStringFormula return YES; } +- (Brick*)cloneWithScript:(Script *)script +{ + ReplaceItemInUserListBrick *clone = [[ReplaceItemInUserListBrick alloc] init]; + clone.script = script; + for (UserList *userList in script.object.userData.lists) { + if (userList.name == self.userList.name) { + clone.userList = userList; + } + } + clone.elementFormula = self.elementFormula; + clone.index = self.index; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Data/SetVariableBrick.m b/src/Catty/DataModel/Bricks/Data/SetVariableBrick.m index b92f3ecd52..231d5f4f41 100644 --- a/src/Catty/DataModel/Bricks/Data/SetVariableBrick.m +++ b/src/Catty/DataModel/Bricks/Data/SetVariableBrick.m @@ -73,6 +73,20 @@ - (BOOL)allowsStringFormula return YES; } +- (Brick*)cloneWithScript:(Script *)script +{ + SetVariableBrick *clone = [[SetVariableBrick alloc] init]; + clone.script = script; + for (UserVariable *variable in script.object.userData.variables) { + if (variable.name == self.userVariable.name) { + clone.userVariable = variable; + } + } + clone.variableFormula = self.variableFormula; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Data/ShowTextBrick.m b/src/Catty/DataModel/Bricks/Data/ShowTextBrick.m index d53bc8292c..b55da206d8 100644 --- a/src/Catty/DataModel/Bricks/Data/ShowTextBrick.m +++ b/src/Catty/DataModel/Bricks/Data/ShowTextBrick.m @@ -81,6 +81,21 @@ - (kBrickCategoryType)category return kDataBrick; } +- (Brick*)cloneWithScript:(Script *)script +{ + ShowTextBrick *clone = [[ShowTextBrick alloc] init]; + clone.script = script; + for (UserVariable *variable in script.object.userData.variables) { + if (variable.name == self.userVariable.name) { + clone.userVariable = variable; + } + } + clone.xFormula = self.xFormula; + clone.yFormula = self.yFormula; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Data/WebRequestBrick.swift b/src/Catty/DataModel/Bricks/Data/WebRequestBrick.swift index fdc5c0c0d2..fcedd04b61 100644 --- a/src/Catty/DataModel/Bricks/Data/WebRequestBrick.swift +++ b/src/Catty/DataModel/Bricks/Data/WebRequestBrick.swift @@ -91,4 +91,15 @@ override func isDisabledForBackground() -> Bool { false } + + override func clone(with script: Script!) -> Brick! { + let clone = WebRequestBrick() + clone.script = script + clone.request = self.request + clone.userVariable = script.object.userData.variables().first(where: { $0.name == self.userVariable?.name }) + clone.downloaderFactory = self.downloaderFactory + clone.alertControllerBuilder = self.alertControllerBuilder + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Embroidery/SewUpBrick.swift b/src/Catty/DataModel/Bricks/Embroidery/SewUpBrick.swift index a8eba4b52f..c17d34a71c 100644 --- a/src/Catty/DataModel/Bricks/Embroidery/SewUpBrick.swift +++ b/src/Catty/DataModel/Bricks/Embroidery/SewUpBrick.swift @@ -46,4 +46,11 @@ override func isSelectableForObject() -> Bool { UserDefaults.standard.bool(forKey: kUseEmbroideryBricks) } + + override func clone(with script: Script!) -> Brick! { + let clone = SewUpBrick() + clone.script = script + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Embroidery/StartRunningStitchBrick.swift b/src/Catty/DataModel/Bricks/Embroidery/StartRunningStitchBrick.swift index 393272e648..c5c5cf8bc6 100644 --- a/src/Catty/DataModel/Bricks/Embroidery/StartRunningStitchBrick.swift +++ b/src/Catty/DataModel/Bricks/Embroidery/StartRunningStitchBrick.swift @@ -68,4 +68,12 @@ import Foundation func allowsStringFormula() -> Bool { false } + + override func clone(with script: Script!) -> Brick! { + let clone = StartRunningStitchBrick() + clone.script = script + clone.stitchLength = self.stitchLength + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Embroidery/StitchBrick.swift b/src/Catty/DataModel/Bricks/Embroidery/StitchBrick.swift index fbb464c35c..a7ee3df63b 100644 --- a/src/Catty/DataModel/Bricks/Embroidery/StitchBrick.swift +++ b/src/Catty/DataModel/Bricks/Embroidery/StitchBrick.swift @@ -46,4 +46,11 @@ override func isSelectableForObject() -> Bool { UserDefaults.standard.bool(forKey: kUseEmbroideryBricks) } + + override func clone(with script: Script!) -> Brick! { + let clone = StitchBrick() + clone.script = script + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Embroidery/StopCurrentStitchBrick.swift b/src/Catty/DataModel/Bricks/Embroidery/StopCurrentStitchBrick.swift index d18e79fe8b..ad369d5ff7 100644 --- a/src/Catty/DataModel/Bricks/Embroidery/StopCurrentStitchBrick.swift +++ b/src/Catty/DataModel/Bricks/Embroidery/StopCurrentStitchBrick.swift @@ -48,4 +48,11 @@ import Foundation override func isSelectableForObject() -> Bool { UserDefaults.standard.bool(forKey: kUseEmbroideryBricks) } + + override func clone(with script: Script!) -> Brick! { + let clone = StopCurrentStitchBrick() + clone.script = script + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/IO/FlashBrick.m b/src/Catty/DataModel/Bricks/IO/FlashBrick.m index cea46c3b96..6df57667e8 100644 --- a/src/Catty/DataModel/Bricks/IO/FlashBrick.m +++ b/src/Catty/DataModel/Bricks/IO/FlashBrick.m @@ -66,6 +66,15 @@ - (NSString*)choiceForLineNumber:(NSInteger)lineNumber andParameterNumber:(NSInt return choices; } +- (Brick*)cloneWithScript:(Script *)script +{ + FlashBrick *clone = [[FlashBrick alloc] init]; + clone.script = script; + clone.flashChoice = self.flashChoice; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/IO/VibrationBrick.m b/src/Catty/DataModel/Bricks/IO/VibrationBrick.m index 71cab94800..0e388ebd9a 100644 --- a/src/Catty/DataModel/Bricks/IO/VibrationBrick.m +++ b/src/Catty/DataModel/Bricks/IO/VibrationBrick.m @@ -55,6 +55,15 @@ - (BOOL)allowsStringFormula return NO; } +- (Brick*)cloneWithScript:(Script *)script +{ + VibrationBrick *clone = [[VibrationBrick alloc] init]; + clone.script = script; + clone.durationInSeconds = self.durationInSeconds; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Look/AskBrick.swift b/src/Catty/DataModel/Bricks/Look/AskBrick.swift index 65c15fa57b..6528fe3167 100644 --- a/src/Catty/DataModel/Bricks/Look/AskBrick.swift +++ b/src/Catty/DataModel/Bricks/Look/AskBrick.swift @@ -78,4 +78,13 @@ override func isDisabledForBackground() -> Bool { false } + + override func clone(with script: Script!) -> Brick! { + let clone = AskBrick() + clone.script = script + clone.question = self.question + clone.userVariable = script.object.userData.variables().first(where: { $0.name == self.userVariable?.name }) + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Look/CameraBrick.m b/src/Catty/DataModel/Bricks/Look/CameraBrick.m index 304de0c7b5..2988a6a18d 100644 --- a/src/Catty/DataModel/Bricks/Look/CameraBrick.m +++ b/src/Catty/DataModel/Bricks/Look/CameraBrick.m @@ -66,6 +66,15 @@ - (NSString*)choiceForLineNumber:(NSInteger)lineNumber andParameterNumber:(NSInt return choices; } +- (Brick*)cloneWithScript:(Script *)script +{ + CameraBrick *clone = [[CameraBrick alloc] init]; + clone.script = script; + clone.cameraChoice = self.cameraChoice; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Look/ChangeBrightnessByNBrick.swift b/src/Catty/DataModel/Bricks/Look/ChangeBrightnessByNBrick.swift index ba2e1decab..fd66317cc7 100644 --- a/src/Catty/DataModel/Bricks/Look/ChangeBrightnessByNBrick.swift +++ b/src/Catty/DataModel/Bricks/Look/ChangeBrightnessByNBrick.swift @@ -70,4 +70,12 @@ override func brickCell() -> BrickCellProtocol.Type! { ChangeBrightnessByNBrickCell.self as BrickCellProtocol.Type } + + override func clone(with script: Script!) -> Brick! { + let clone = ChangeBrightnessByNBrick() + clone.script = script + clone.changeBrightness = self.changeBrightness + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Look/ChangeColorByNBrick.m b/src/Catty/DataModel/Bricks/Look/ChangeColorByNBrick.m index 0a2671b623..03d6320367 100644 --- a/src/Catty/DataModel/Bricks/Look/ChangeColorByNBrick.m +++ b/src/Catty/DataModel/Bricks/Look/ChangeColorByNBrick.m @@ -56,6 +56,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.changeColor = [[Formula alloc] initWithInteger:25]; } +- (Brick*)cloneWithScript:(Script *)script +{ + ChangeColorByNBrick *clone = [[ChangeColorByNBrick alloc] init]; + clone.script = script; + clone.changeColor = self.changeColor; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Look/ChangeTransparencyByNBrick.m b/src/Catty/DataModel/Bricks/Look/ChangeTransparencyByNBrick.m index bc55b91977..5afc537f87 100644 --- a/src/Catty/DataModel/Bricks/Look/ChangeTransparencyByNBrick.m +++ b/src/Catty/DataModel/Bricks/Look/ChangeTransparencyByNBrick.m @@ -58,6 +58,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.changeTransparency = [[Formula alloc] initWithInteger:25]; } +- (Brick*)cloneWithScript:(Script *)script +{ + ChangeTransparencyByNBrick *clone = [[ChangeTransparencyByNBrick alloc] init]; + clone.script = script; + clone.changeTransparency = self.changeTransparency; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Look/ChooseCameraBrick.m b/src/Catty/DataModel/Bricks/Look/ChooseCameraBrick.m index 409424c4a1..00d306872b 100644 --- a/src/Catty/DataModel/Bricks/Look/ChooseCameraBrick.m +++ b/src/Catty/DataModel/Bricks/Look/ChooseCameraBrick.m @@ -66,6 +66,15 @@ - (NSString*)choiceForLineNumber:(NSInteger)lineNumber andParameterNumber:(NSInt return choices; } +- (Brick*)cloneWithScript:(Script *)script +{ + ChooseCameraBrick *clone = [[ChooseCameraBrick alloc] init]; + clone.script = script; + clone.cameraPosition = self.cameraPosition; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Look/ClearGraphicEffectBrick.m b/src/Catty/DataModel/Bricks/Look/ClearGraphicEffectBrick.m index 298d6014c7..347057d858 100644 --- a/src/Catty/DataModel/Bricks/Look/ClearGraphicEffectBrick.m +++ b/src/Catty/DataModel/Bricks/Look/ClearGraphicEffectBrick.m @@ -36,6 +36,14 @@ - (NSString*)pathForLook:(Look*)look return [look pathForScene:self.script.object.scene]; } +- (Brick*)cloneWithScript:(Script *)script +{ + ClearGraphicEffectBrick *clone = [[ClearGraphicEffectBrick alloc] init]; + clone.script = script; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Look/HideBrick.m b/src/Catty/DataModel/Bricks/Look/HideBrick.m index 2aced13171..1a8b93fd24 100644 --- a/src/Catty/DataModel/Bricks/Look/HideBrick.m +++ b/src/Catty/DataModel/Bricks/Look/HideBrick.m @@ -40,4 +40,13 @@ - (NSInteger)getRequiredResources { return kNoResources; } + +- (Brick*)cloneWithScript:(Script *)script +{ + HideBrick *clone = [[HideBrick alloc] init]; + clone.script = script; + + return clone; +} + @end diff --git a/src/Catty/DataModel/Bricks/Look/NextLookBrick.swift b/src/Catty/DataModel/Bricks/Look/NextLookBrick.swift index 7ac9981a97..2504393364 100644 --- a/src/Catty/DataModel/Bricks/Look/NextLookBrick.swift +++ b/src/Catty/DataModel/Bricks/Look/NextLookBrick.swift @@ -45,4 +45,11 @@ override func getRequiredResources() -> Int { ResourceType.noResources.rawValue } + + override func clone(with script: Script!) -> Brick! { + let clone = NextLookBrick() + clone.script = script + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Look/PreviousLookBrick.swift b/src/Catty/DataModel/Bricks/Look/PreviousLookBrick.swift index 8c54eabcd7..56c2a3ab4b 100644 --- a/src/Catty/DataModel/Bricks/Look/PreviousLookBrick.swift +++ b/src/Catty/DataModel/Bricks/Look/PreviousLookBrick.swift @@ -45,4 +45,11 @@ override func getRequiredResources() -> Int { ResourceType.noResources.rawValue } + + override func clone(with script: Script!) -> Brick! { + let clone = PreviousLookBrick() + clone.script = script + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Look/SayBubbleBrick.m b/src/Catty/DataModel/Bricks/Look/SayBubbleBrick.m index eaf4b2286a..ac1f7db71e 100644 --- a/src/Catty/DataModel/Bricks/Look/SayBubbleBrick.m +++ b/src/Catty/DataModel/Bricks/Look/SayBubbleBrick.m @@ -44,6 +44,15 @@ -(BOOL)isDisabledForBackground return YES; } +- (Brick*)cloneWithScript:(Script *)script +{ + SayBubbleBrick *clone = [[SayBubbleBrick alloc] init]; + clone.script = script; + clone.formula = self.formula; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Look/SayForBubbleBrick.m b/src/Catty/DataModel/Bricks/Look/SayForBubbleBrick.m index 5a5b209244..a9c11d9eb4 100644 --- a/src/Catty/DataModel/Bricks/Look/SayForBubbleBrick.m +++ b/src/Catty/DataModel/Bricks/Look/SayForBubbleBrick.m @@ -54,6 +54,16 @@ -(BOOL)isDisabledForBackground return YES; } +- (Brick*)cloneWithScript:(Script *)script +{ + SayForBubbleBrick *clone = [[SayForBubbleBrick alloc] init]; + clone.script = script; + clone.stringFormula = self.stringFormula; + clone.intFormula = self.intFormula; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Look/SetBackgroundAndWaitBrick.swift b/src/Catty/DataModel/Bricks/Look/SetBackgroundAndWaitBrick.swift index f098dcf606..da05428ebc 100644 --- a/src/Catty/DataModel/Bricks/Look/SetBackgroundAndWaitBrick.swift +++ b/src/Catty/DataModel/Bricks/Look/SetBackgroundAndWaitBrick.swift @@ -111,4 +111,12 @@ return brick } + + override func clone(with script: Script!) -> Brick! { + let clone = SetBackgroundAndWaitBrick() + clone.script = script + clone.look = self.look + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Look/SetBackgroundBrick.swift b/src/Catty/DataModel/Bricks/Look/SetBackgroundBrick.swift index 0f5682a2f1..57f85ec01b 100644 --- a/src/Catty/DataModel/Bricks/Look/SetBackgroundBrick.swift +++ b/src/Catty/DataModel/Bricks/Look/SetBackgroundBrick.swift @@ -105,4 +105,12 @@ return brick } + + override func clone(with script: Script!) -> Brick! { + let clone = SetBackgroundBrick() + clone.script = script + clone.look = self.look + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Look/SetBackgroundByIndexBrick.swift b/src/Catty/DataModel/Bricks/Look/SetBackgroundByIndexBrick.swift index 5ef4e99741..bc086be91d 100644 --- a/src/Catty/DataModel/Bricks/Look/SetBackgroundByIndexBrick.swift +++ b/src/Catty/DataModel/Bricks/Look/SetBackgroundByIndexBrick.swift @@ -70,4 +70,12 @@ func path(for look: Look?) -> String? { look?.path(for: script.object.scene) } + + override func clone(with script: Script!) -> Brick! { + let clone = SetBackgroundByIndexBrick() + clone.script = script + clone.backgroundIndex = self.backgroundIndex + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Look/SetBrightnessBrick.swift b/src/Catty/DataModel/Bricks/Look/SetBrightnessBrick.swift index 6a8cf35cf9..80702cd4b1 100644 --- a/src/Catty/DataModel/Bricks/Look/SetBrightnessBrick.swift +++ b/src/Catty/DataModel/Bricks/Look/SetBrightnessBrick.swift @@ -70,4 +70,12 @@ override func brickCell() -> BrickCellProtocol.Type! { SetBrightnessBrickCell.self as BrickCellProtocol.Type } + + override func clone(with script: Script!) -> Brick! { + let clone = SetBrightnessBrick() + clone.script = script + clone.brightness = self.brightness + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Look/SetColorBrick.m b/src/Catty/DataModel/Bricks/Look/SetColorBrick.m index 9cabd804f4..bf3dc23fe4 100644 --- a/src/Catty/DataModel/Bricks/Look/SetColorBrick.m +++ b/src/Catty/DataModel/Bricks/Look/SetColorBrick.m @@ -63,6 +63,15 @@ - (NSString*)pathForLook:(Look*)look return [look pathForScene:self.script.object.scene]; } +- (Brick*)cloneWithScript:(Script *)script +{ + SetColorBrick *clone = [[SetColorBrick alloc] init]; + clone.script = script; + clone.color = self.color; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Look/SetLookBrick.swift b/src/Catty/DataModel/Bricks/Look/SetLookBrick.swift index 35671e1271..3f26395ad0 100644 --- a/src/Catty/DataModel/Bricks/Look/SetLookBrick.swift +++ b/src/Catty/DataModel/Bricks/Look/SetLookBrick.swift @@ -108,4 +108,12 @@ return brick } + + override func clone(with script: Script!) -> Brick! { + let clone = SetLookBrick() + clone.script = script + clone.look = self.look + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Look/SetLookByIndexBrick.swift b/src/Catty/DataModel/Bricks/Look/SetLookByIndexBrick.swift index 3351f9eab5..6e9b54f915 100644 --- a/src/Catty/DataModel/Bricks/Look/SetLookByIndexBrick.swift +++ b/src/Catty/DataModel/Bricks/Look/SetLookByIndexBrick.swift @@ -74,4 +74,12 @@ func pathForLook(look: Look?) -> String? { look?.path(for: script.object.scene) } + + override func clone(with script: Script!) -> Brick! { + let clone = SetLookByIndexBrick() + clone.script = script + clone.lookIndex = self.lookIndex + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Look/SetSizeToBrick.m b/src/Catty/DataModel/Bricks/Look/SetSizeToBrick.m index 9e73250ec4..074dbeb504 100644 --- a/src/Catty/DataModel/Bricks/Look/SetSizeToBrick.m +++ b/src/Catty/DataModel/Bricks/Look/SetSizeToBrick.m @@ -55,6 +55,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.size = [[Formula alloc] initWithInteger:60]; } +- (Brick*)cloneWithScript:(Script *)script +{ + SetSizeToBrick *clone = [[SetSizeToBrick alloc] init]; + clone.script = script; + clone.size = self.size; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Look/SetTransparencyBrick.m b/src/Catty/DataModel/Bricks/Look/SetTransparencyBrick.m index 5e46bc556c..30aedc5080 100644 --- a/src/Catty/DataModel/Bricks/Look/SetTransparencyBrick.m +++ b/src/Catty/DataModel/Bricks/Look/SetTransparencyBrick.m @@ -58,6 +58,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.transparency = [[Formula alloc] initWithInteger:50]; } +- (Brick*)cloneWithScript:(Script *)script +{ + SetTransparencyBrick *clone = [[SetTransparencyBrick alloc] init]; + clone.script = script; + clone.transparency = self.transparency; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Look/ShowBrick.m b/src/Catty/DataModel/Bricks/Look/ShowBrick.m index a7110a2348..6b4cb60d11 100644 --- a/src/Catty/DataModel/Bricks/Look/ShowBrick.m +++ b/src/Catty/DataModel/Bricks/Look/ShowBrick.m @@ -30,6 +30,14 @@ - (kBrickCategoryType)category return kLookBrick; } +- (Brick*)cloneWithScript:(Script *)script +{ + ShowBrick *clone = [[ShowBrick alloc] init]; + clone.script = script; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Look/ThinkBubbleBrick.m b/src/Catty/DataModel/Bricks/Look/ThinkBubbleBrick.m index 203ffcb23a..2408662162 100644 --- a/src/Catty/DataModel/Bricks/Look/ThinkBubbleBrick.m +++ b/src/Catty/DataModel/Bricks/Look/ThinkBubbleBrick.m @@ -44,6 +44,15 @@ -(BOOL)isDisabledForBackground return YES; } +- (Brick*)cloneWithScript:(Script *)script +{ + ThinkBubbleBrick *clone = [[ThinkBubbleBrick alloc] init]; + clone.script = script; + clone.formula = self.formula; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Look/ThinkForBubbleBrick.m b/src/Catty/DataModel/Bricks/Look/ThinkForBubbleBrick.m index 8617e83b2a..faefd31f60 100644 --- a/src/Catty/DataModel/Bricks/Look/ThinkForBubbleBrick.m +++ b/src/Catty/DataModel/Bricks/Look/ThinkForBubbleBrick.m @@ -46,6 +46,16 @@ -(BOOL)isDisabledForBackground return YES; } +- (Brick*)cloneWithScript:(Script *)script +{ + ThinkForBubbleBrick *clone = [[ThinkForBubbleBrick alloc] init]; + clone.script = script; + clone.stringFormula = self.stringFormula; + clone.intFormula = self.intFormula; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Motion/ChangeSizeByNBrick.m b/src/Catty/DataModel/Bricks/Motion/ChangeSizeByNBrick.m index e679aa3f76..4223d3bd9b 100644 --- a/src/Catty/DataModel/Bricks/Motion/ChangeSizeByNBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/ChangeSizeByNBrick.m @@ -56,6 +56,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.size = [[Formula alloc] initWithInteger:10]; } +- (Brick*)cloneWithScript:(Script *)script +{ + ChangeSizeByNBrick *clone = [[ChangeSizeByNBrick alloc] init]; + clone.script = script; + clone.size = self.size; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Motion/ChangeXByNBrick.m b/src/Catty/DataModel/Bricks/Motion/ChangeXByNBrick.m index f5bd47dc8a..a29f55382e 100644 --- a/src/Catty/DataModel/Bricks/Motion/ChangeXByNBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/ChangeXByNBrick.m @@ -56,6 +56,15 @@ - (kBrickCategoryType)category return kMotionBrick; } +- (Brick*)cloneWithScript:(Script *)script +{ + ChangeXByNBrick *clone = [[ChangeXByNBrick alloc] init]; + clone.script = script; + clone.xMovement = self.xMovement; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Motion/ChangeYByNBrick.m b/src/Catty/DataModel/Bricks/Motion/ChangeYByNBrick.m index 3a04849928..5cd61e76d6 100644 --- a/src/Catty/DataModel/Bricks/Motion/ChangeYByNBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/ChangeYByNBrick.m @@ -56,6 +56,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.yMovement = [[Formula alloc] initWithInteger:10]; } +- (Brick*)cloneWithScript:(Script *)script +{ + ChangeYByNBrick *clone = [[ChangeYByNBrick alloc] init]; + clone.script = script; + clone.yMovement = self.yMovement; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Motion/ComeToFrontBrick.m b/src/Catty/DataModel/Bricks/Motion/ComeToFrontBrick.m index 467c8f7e73..7f4df6537b 100644 --- a/src/Catty/DataModel/Bricks/Motion/ComeToFrontBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/ComeToFrontBrick.m @@ -36,6 +36,14 @@ - (BOOL)isDisabledForBackground return YES; } +- (Brick*)cloneWithScript:(Script *)script +{ + ComeToFrontBrick *clone = [[ComeToFrontBrick alloc] init]; + clone.script = script; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Motion/GlideToBrick.m b/src/Catty/DataModel/Bricks/Motion/GlideToBrick.m index 06922e8e1b..11c7aa0fe5 100644 --- a/src/Catty/DataModel/Bricks/Motion/GlideToBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/GlideToBrick.m @@ -78,6 +78,16 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.yDestination = [[Formula alloc] initWithInteger:200]; } +- (Brick*)cloneWithScript:(Script *)script +{ + GlideToBrick *clone = [[GlideToBrick alloc] init]; + clone.script = script; + clone.durationInSeconds = self.durationInSeconds; + clone.xDestination = self.xDestination; + clone.yDestination = self.yDestination; + + return clone; +} #pragma mark - Description - (NSString*)description diff --git a/src/Catty/DataModel/Bricks/Motion/GoNStepsBackBrick.m b/src/Catty/DataModel/Bricks/Motion/GoNStepsBackBrick.m index edf62009bc..474ddea75c 100644 --- a/src/Catty/DataModel/Bricks/Motion/GoNStepsBackBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/GoNStepsBackBrick.m @@ -61,6 +61,15 @@ - (kBrickCategoryType)category return kMotionBrick; } +- (Brick*)cloneWithScript:(Script *)script +{ + GoNStepsBackBrick *clone = [[GoNStepsBackBrick alloc] init]; + clone.script = script; + clone.steps = self.steps; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Motion/GoToBrick.m b/src/Catty/DataModel/Bricks/Motion/GoToBrick.m index 65cd779b55..20fb8494b3 100644 --- a/src/Catty/DataModel/Bricks/Motion/GoToBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/GoToBrick.m @@ -100,6 +100,16 @@ - (NSString *)choiceForLineNumber:(NSInteger)lineNumber andParameterNumber:(NSIn return choices; } +- (Brick*)cloneWithScript:(Script *)script +{ + GoToBrick *clone = [[GoToBrick alloc] init]; + clone.script = script; + clone.spinnerSelection = self.spinnerSelection; + clone.goToObject = self.goToObject; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Motion/IfOnEdgeBounceBrick.m b/src/Catty/DataModel/Bricks/Motion/IfOnEdgeBounceBrick.m index 6203a83990..2e62bc19e3 100644 --- a/src/Catty/DataModel/Bricks/Motion/IfOnEdgeBounceBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/IfOnEdgeBounceBrick.m @@ -44,6 +44,14 @@ - (void)performFromScript:(Script*)script; } +- (Brick*)cloneWithScript:(Script *)script +{ + IfOnEdgeBounceBrick *clone = [[IfOnEdgeBounceBrick alloc] init]; + clone.script = script; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Motion/MoveNStepsBrick.m b/src/Catty/DataModel/Bricks/Motion/MoveNStepsBrick.m index 6ec6f59f4c..f9bfee8572 100644 --- a/src/Catty/DataModel/Bricks/Motion/MoveNStepsBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/MoveNStepsBrick.m @@ -64,6 +64,15 @@ - (NSString*)description return [NSString stringWithFormat:@"MoveNStepsBrick"]; } +- (Brick*)cloneWithScript:(Script *)script +{ + MoveNStepsBrick *clone = [[MoveNStepsBrick alloc] init]; + clone.script = script; + clone.steps = self.steps; + + return clone; +} + #pragma mark - Resources - (NSInteger)getRequiredResources { diff --git a/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick.m b/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick.m index 2d319ddf0f..748ff8e9e2 100644 --- a/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick.m @@ -64,6 +64,16 @@ - (kBrickCategoryType)category return kMotionBrick; } +- (Brick*)cloneWithScript:(Script *)script +{ + PlaceAtBrick *clone = [[PlaceAtBrick alloc] init]; + clone.script = script; + clone.xPosition = self.xPosition; + clone.yPosition = self.yPosition; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Motion/PointInDirectionBrick.m b/src/Catty/DataModel/Bricks/Motion/PointInDirectionBrick.m index 450812a9c4..4e685bf3a7 100644 --- a/src/Catty/DataModel/Bricks/Motion/PointInDirectionBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/PointInDirectionBrick.m @@ -55,6 +55,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.degrees = [[Formula alloc] initWithInteger:90]; } +- (Brick*)cloneWithScript:(Script *)script +{ + PointInDirectionBrick *clone = [[PointInDirectionBrick alloc] init]; + clone.script = script; + clone.degrees = self.degrees; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Motion/PointToBrick.h b/src/Catty/DataModel/Bricks/Motion/PointToBrick.h index 841eea04b0..e0ab6e9caf 100644 --- a/src/Catty/DataModel/Bricks/Motion/PointToBrick.h +++ b/src/Catty/DataModel/Bricks/Motion/PointToBrick.h @@ -23,6 +23,7 @@ #import "Brick.h" #import "BrickObjectProtocol.h" +#import "BrickObjectWithOutBackgroundProtocol.h" @class SpriteObject; diff --git a/src/Catty/DataModel/Bricks/Motion/PointToBrick.m b/src/Catty/DataModel/Bricks/Motion/PointToBrick.m index 8fd4151b08..3cc1f21cf3 100644 --- a/src/Catty/DataModel/Bricks/Motion/PointToBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/PointToBrick.m @@ -33,6 +33,19 @@ - (SpriteObject*) pointedObject return _pointedObject; } +- (Brick*)cloneWithScript:(Script *)script +{ + PointToBrick *clone = [[PointToBrick alloc] init]; + clone.script = script; + if (self.pointedObject == self.script.object) { + clone.pointedObject = clone.script.object; + } else { + clone.pointedObject = self.pointedObject; + } + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Motion/SetRotationStyleBrick.swift b/src/Catty/DataModel/Bricks/Motion/SetRotationStyleBrick.swift index 45f80bbd9f..9b63f3b6f6 100644 --- a/src/Catty/DataModel/Bricks/Motion/SetRotationStyleBrick.swift +++ b/src/Catty/DataModel/Bricks/Motion/SetRotationStyleBrick.swift @@ -63,4 +63,12 @@ func possibleChoices(forLineNumber lineNumber: Int, andParameterNumber paramNumber: Int) -> [String] { RotationStyle.allCases.map { $0.localizedString() } } + + override func clone(with script: Script!) -> Brick! { + let clone = SetRotationStyleBrick() + clone.script = script + clone.selection = self.selection + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Motion/SetXBrick.m b/src/Catty/DataModel/Bricks/Motion/SetXBrick.m index 3862fe51ae..c991fc4115 100644 --- a/src/Catty/DataModel/Bricks/Motion/SetXBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/SetXBrick.m @@ -56,6 +56,15 @@ - (kBrickCategoryType)category return kMotionBrick; } +- (Brick*)cloneWithScript:(Script *)script +{ + SetXBrick *clone = [[SetXBrick alloc] init]; + clone.script = script; + clone.xPosition = self.xPosition; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Motion/SetYBrick.m b/src/Catty/DataModel/Bricks/Motion/SetYBrick.m index a2846db3a0..d16ba0641f 100644 --- a/src/Catty/DataModel/Bricks/Motion/SetYBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/SetYBrick.m @@ -55,6 +55,15 @@ - (kBrickCategoryType)category return kMotionBrick; } +- (Brick*)cloneWithScript:(Script *)script +{ + SetYBrick *clone = [[SetYBrick alloc] init]; + clone.script = script; + clone.yPosition = self.yPosition; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Motion/TurnLeftBrick.m b/src/Catty/DataModel/Bricks/Motion/TurnLeftBrick.m index 192a57fd5c..c2e197d9be 100644 --- a/src/Catty/DataModel/Bricks/Motion/TurnLeftBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/TurnLeftBrick.m @@ -55,6 +55,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.degrees = [[Formula alloc] initWithInteger:15]; } +- (Brick*)cloneWithScript:(Script *)script +{ + TurnLeftBrick *clone = [[TurnLeftBrick alloc] init]; + clone.script = script; + clone.degrees = self.degrees; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Motion/TurnRightBrick.m b/src/Catty/DataModel/Bricks/Motion/TurnRightBrick.m index 2f6b6963ba..f51d3ba318 100644 --- a/src/Catty/DataModel/Bricks/Motion/TurnRightBrick.m +++ b/src/Catty/DataModel/Bricks/Motion/TurnRightBrick.m @@ -55,6 +55,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.degrees = [[Formula alloc] initWithInteger:15]; } +- (Brick*)cloneWithScript:(Script *)script +{ + TurnRightBrick *clone = [[TurnRightBrick alloc] init]; + clone.script = script; + clone.degrees = self.degrees; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Pen/PenClearBrick.swift b/src/Catty/DataModel/Bricks/Pen/PenClearBrick.swift index 8d795b624e..41b4c332ed 100644 --- a/src/Catty/DataModel/Bricks/Pen/PenClearBrick.swift +++ b/src/Catty/DataModel/Bricks/Pen/PenClearBrick.swift @@ -43,4 +43,10 @@ PenClearBrickCell.self as BrickCellProtocol.Type } + override func clone(with script: Script!) -> Brick! { + let clone = PenClearBrick() + clone.script = script + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Pen/PenDownBrick.swift b/src/Catty/DataModel/Bricks/Pen/PenDownBrick.swift index a96703a725..776a7000de 100644 --- a/src/Catty/DataModel/Bricks/Pen/PenDownBrick.swift +++ b/src/Catty/DataModel/Bricks/Pen/PenDownBrick.swift @@ -47,4 +47,10 @@ true } + override func clone(with script: Script!) -> Brick! { + let clone = PenDownBrick() + clone.script = script + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Pen/PenUpBrick.swift b/src/Catty/DataModel/Bricks/Pen/PenUpBrick.swift index 85db9daeea..90f3bb9fd3 100644 --- a/src/Catty/DataModel/Bricks/Pen/PenUpBrick.swift +++ b/src/Catty/DataModel/Bricks/Pen/PenUpBrick.swift @@ -48,4 +48,10 @@ true } + override func clone(with script: Script!) -> Brick! { + let clone = PenUpBrick() + clone.script = script + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Pen/SetPenColorBrick.swift b/src/Catty/DataModel/Bricks/Pen/SetPenColorBrick.swift index 4a265afd86..65a7d71c5b 100644 --- a/src/Catty/DataModel/Bricks/Pen/SetPenColorBrick.swift +++ b/src/Catty/DataModel/Bricks/Pen/SetPenColorBrick.swift @@ -114,4 +114,13 @@ true } + override func clone(with script: Script!) -> Brick! { + let clone = SetPenColorBrick() + clone.script = script + clone.red = self.red + clone.blue = self.blue + clone.green = self.green + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Pen/SetPenSizeBrick.swift b/src/Catty/DataModel/Bricks/Pen/SetPenSizeBrick.swift index 05bd6501ce..5c227cd85e 100644 --- a/src/Catty/DataModel/Bricks/Pen/SetPenSizeBrick.swift +++ b/src/Catty/DataModel/Bricks/Pen/SetPenSizeBrick.swift @@ -69,4 +69,11 @@ true } + override func clone(with script: Script!) -> Brick! { + let clone = SetPenSizeBrick() + clone.script = script + clone.penSize = self.penSize + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Pen/StampBrick.swift b/src/Catty/DataModel/Bricks/Pen/StampBrick.swift index d5fac681a6..de2a6bc9f8 100644 --- a/src/Catty/DataModel/Bricks/Pen/StampBrick.swift +++ b/src/Catty/DataModel/Bricks/Pen/StampBrick.swift @@ -47,4 +47,10 @@ true } + override func clone(with script: Script!) -> Brick! { + let clone = StampBrick() + clone.script = script + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Phiro/PhiroIfLogicBeginBrick.m b/src/Catty/DataModel/Bricks/Phiro/PhiroIfLogicBeginBrick.m index bdeeae1333..1cc5600077 100644 --- a/src/Catty/DataModel/Bricks/Phiro/PhiroIfLogicBeginBrick.m +++ b/src/Catty/DataModel/Bricks/Phiro/PhiroIfLogicBeginBrick.m @@ -50,6 +50,15 @@ - (void)setSensor:(NSString*)sensor forLineNumber:(NSInteger)lineNumber andParam self.sensor = sensor; } +- (Brick*)cloneWithScript:(Script *)script +{ + PhiroIfLogicBeginBrick *clone = [[PhiroIfLogicBeginBrick alloc] init]; + clone.script = script; + clone.sensor = self.sensor; + + return clone; +} + #pragma mark - Default values - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject { diff --git a/src/Catty/DataModel/Bricks/Phiro/PhiroMotorMoveBackwardBrick.m b/src/Catty/DataModel/Bricks/Phiro/PhiroMotorMoveBackwardBrick.m index 216dd78149..5beaec3fbb 100644 --- a/src/Catty/DataModel/Bricks/Phiro/PhiroMotorMoveBackwardBrick.m +++ b/src/Catty/DataModel/Bricks/Phiro/PhiroMotorMoveBackwardBrick.m @@ -78,6 +78,16 @@ - (BOOL)allowsStringFormula return NO; } +- (Brick*)cloneWithScript:(Script *)script +{ + PhiroMotorMoveBackwardBrick *clone = [[PhiroMotorMoveBackwardBrick alloc] init]; + clone.script = script; + clone.motor = self.motor; + clone.formula = self.formula; + + return clone; +} + #pragma mark - Default values - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject { diff --git a/src/Catty/DataModel/Bricks/Phiro/PhiroMotorMoveForwardBrick.m b/src/Catty/DataModel/Bricks/Phiro/PhiroMotorMoveForwardBrick.m index df967e78d3..02e415dd46 100644 --- a/src/Catty/DataModel/Bricks/Phiro/PhiroMotorMoveForwardBrick.m +++ b/src/Catty/DataModel/Bricks/Phiro/PhiroMotorMoveForwardBrick.m @@ -78,6 +78,16 @@ - (BOOL)allowsStringFormula return NO; } +- (Brick*)cloneWithScript:(Script *)script +{ + PhiroMotorMoveForwardBrick *clone = [[PhiroMotorMoveForwardBrick alloc] init]; + clone.script = script; + clone.motor = self.motor; + clone.formula = self.formula; + + return clone; +} + #pragma mark - Default values - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject { diff --git a/src/Catty/DataModel/Bricks/Phiro/PhiroMotorStopBrick.m b/src/Catty/DataModel/Bricks/Phiro/PhiroMotorStopBrick.m index a268816691..cc03f71327 100644 --- a/src/Catty/DataModel/Bricks/Phiro/PhiroMotorStopBrick.m +++ b/src/Catty/DataModel/Bricks/Phiro/PhiroMotorStopBrick.m @@ -54,6 +54,15 @@ - (void)setMotor:(NSString*)motor forLineNumber:(NSInteger)lineNumber andParamet self.motor = motor; } +- (Brick*)cloneWithScript:(Script *)script +{ + PhiroMotorStopBrick *clone = [[PhiroMotorStopBrick alloc] init]; + clone.script = script; + clone.motor = self.motor; + + return clone; +} + #pragma mark - Default values - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject { diff --git a/src/Catty/DataModel/Bricks/Phiro/PhiroPlayToneBrick.m b/src/Catty/DataModel/Bricks/Phiro/PhiroPlayToneBrick.m index 4f36630960..980ffc6561 100644 --- a/src/Catty/DataModel/Bricks/Phiro/PhiroPlayToneBrick.m +++ b/src/Catty/DataModel/Bricks/Phiro/PhiroPlayToneBrick.m @@ -74,6 +74,16 @@ - (void)setTone:(NSString*)tone forLineNumber:(NSInteger)lineNumber andParameter self.tone = tone; } +- (Brick*)cloneWithScript:(Script *)script +{ + PhiroPlayToneBrick *clone = [[PhiroPlayToneBrick alloc] init]; + clone.script = script; + clone.durationFormula = self.durationFormula; + clone.tone = self.tone; + + return clone; +} + #pragma mark - Default values - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject { diff --git a/src/Catty/DataModel/Bricks/Phiro/PhiroRGBLightBrick.m b/src/Catty/DataModel/Bricks/Phiro/PhiroRGBLightBrick.m index 152cbe6b02..d4c141ca42 100644 --- a/src/Catty/DataModel/Bricks/Phiro/PhiroRGBLightBrick.m +++ b/src/Catty/DataModel/Bricks/Phiro/PhiroRGBLightBrick.m @@ -94,6 +94,18 @@ - (void)setLight:(NSString*)light forLineNumber:(NSInteger)lineNumber andParamet self.light = light; } +- (Brick*)cloneWithScript:(Script *)script +{ + PhiroRGBLightBrick *clone = [[PhiroRGBLightBrick alloc] init]; + clone.script = script; + clone.light = self.light; + clone.redFormula = self.redFormula; + clone.greenFormula = self.greenFormula; + clone.blueFormula = self.blueFormula; + + return clone; +} + #pragma mark - Default values - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject { diff --git a/src/Catty/DataModel/Bricks/Sound/ChangeVolumeByNBrick.m b/src/Catty/DataModel/Bricks/Sound/ChangeVolumeByNBrick.m index 29cdfc4cc1..8e298505a4 100644 --- a/src/Catty/DataModel/Bricks/Sound/ChangeVolumeByNBrick.m +++ b/src/Catty/DataModel/Bricks/Sound/ChangeVolumeByNBrick.m @@ -57,6 +57,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.volume = [[Formula alloc] initWithInteger:-10]; } +- (Brick*)cloneWithScript:(Script *)script +{ + ChangeVolumeByNBrick *clone = [[ChangeVolumeByNBrick alloc] init]; + clone.script = script; + clone.volume = self.volume; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Sound/PlaySoundAndWaitBrick.m b/src/Catty/DataModel/Bricks/Sound/PlaySoundAndWaitBrick.m index 2735d92ca2..addd77b239 100644 --- a/src/Catty/DataModel/Bricks/Sound/PlaySoundAndWaitBrick.m +++ b/src/Catty/DataModel/Bricks/Sound/PlaySoundAndWaitBrick.m @@ -48,6 +48,15 @@ - (id)mutableCopyWithContext:(CBMutableCopyContext*)context return brick; } +- (Brick*)cloneWithScript:(Script *)script +{ + PlaySoundAndWaitBrick *clone = [[PlaySoundAndWaitBrick alloc] init]; + clone.script = script; + clone.sound = self.sound; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Sound/PlaySoundBrick.m b/src/Catty/DataModel/Bricks/Sound/PlaySoundBrick.m index 35590fd897..2403116ab1 100644 --- a/src/Catty/DataModel/Bricks/Sound/PlaySoundBrick.m +++ b/src/Catty/DataModel/Bricks/Sound/PlaySoundBrick.m @@ -48,6 +48,15 @@ - (id)mutableCopyWithContext:(CBMutableCopyContext*)context return brick; } +- (Brick*)cloneWithScript:(Script *)script +{ + PlaySoundBrick *clone = [[PlaySoundBrick alloc] init]; + clone.script = script; + clone.sound = self.sound; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Sound/SetInstrumentBrick.swift b/src/Catty/DataModel/Bricks/Sound/SetInstrumentBrick.swift index e121d82a9d..00539e7b7c 100644 --- a/src/Catty/DataModel/Bricks/Sound/SetInstrumentBrick.swift +++ b/src/Catty/DataModel/Bricks/Sound/SetInstrumentBrick.swift @@ -68,4 +68,12 @@ import Foundation brick.instrument = self.instrument return brick } + + override func clone(with script: Script!) -> Brick! { + let clone = SetInstrumentBrick() + clone.script = script + clone.instrument = self.instrument + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Sound/SetTempoToBrick.swift b/src/Catty/DataModel/Bricks/Sound/SetTempoToBrick.swift index 314e066840..9403333f1d 100644 --- a/src/Catty/DataModel/Bricks/Sound/SetTempoToBrick.swift +++ b/src/Catty/DataModel/Bricks/Sound/SetTempoToBrick.swift @@ -23,7 +23,7 @@ @objc(SetTempoToBrick) @objcMembers class SetTempoToBrick: Brick, BrickFormulaProtocol { - private var tempo: Formula + var tempo: Formula override required init() { self.tempo = Formula(integer: Int32(AudioEngineDefines.defaultTempo)) @@ -83,4 +83,12 @@ brick.tempo = self.tempo return brick } + + override func clone(with script: Script!) -> Brick! { + let clone = SetTempoToBrick() + clone.script = script + clone.tempo = self.tempo + + return clone + } } diff --git a/src/Catty/DataModel/Bricks/Sound/SetVolumeToBrick.m b/src/Catty/DataModel/Bricks/Sound/SetVolumeToBrick.m index e14f2639b3..aa44188747 100644 --- a/src/Catty/DataModel/Bricks/Sound/SetVolumeToBrick.m +++ b/src/Catty/DataModel/Bricks/Sound/SetVolumeToBrick.m @@ -55,6 +55,15 @@ - (void)setDefaultValuesForObject:(SpriteObject*)spriteObject self.volume = [[Formula alloc] initWithInteger:60]; } +- (Brick*)cloneWithScript:(Script *)script +{ + SetVolumeToBrick *clone = [[SetVolumeToBrick alloc] init]; + clone.script = script; + clone.volume = self.volume; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Sound/SpeakAndWaitBrick.m b/src/Catty/DataModel/Bricks/Sound/SpeakAndWaitBrick.m index 52d510c7ab..22653d70d7 100644 --- a/src/Catty/DataModel/Bricks/Sound/SpeakAndWaitBrick.m +++ b/src/Catty/DataModel/Bricks/Sound/SpeakAndWaitBrick.m @@ -50,6 +50,15 @@ - (NSString*)text return nil; } +- (Brick*)cloneWithScript:(Script *)script +{ + SpeakAndWaitBrick *clone = [[SpeakAndWaitBrick alloc] init]; + clone.script = script; + clone.formula = self.formula; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Sound/SpeakBrick.m b/src/Catty/DataModel/Bricks/Sound/SpeakBrick.m index 8b1926128b..90df008594 100644 --- a/src/Catty/DataModel/Bricks/Sound/SpeakBrick.m +++ b/src/Catty/DataModel/Bricks/Sound/SpeakBrick.m @@ -50,6 +50,15 @@ - (NSString*)text return nil; } +- (Brick*)cloneWithScript:(Script *)script +{ + SpeakBrick *clone = [[SpeakBrick alloc] init]; + clone.script = script; + clone.formula = self.formula; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Bricks/Sound/StopAllSoundsBrick.m b/src/Catty/DataModel/Bricks/Sound/StopAllSoundsBrick.m index 2aabd9c540..db3ee09627 100644 --- a/src/Catty/DataModel/Bricks/Sound/StopAllSoundsBrick.m +++ b/src/Catty/DataModel/Bricks/Sound/StopAllSoundsBrick.m @@ -29,6 +29,14 @@ - (kBrickCategoryType)category return kSoundBrick; } +- (Brick*)cloneWithScript:(Script *)script +{ + StopAllSoundsBrick *clone = [[StopAllSoundsBrick alloc] init]; + clone.script = script; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Scene/Scene.swift b/src/Catty/DataModel/Scene/Scene.swift index 42ed4a3f04..f61772997d 100644 --- a/src/Catty/DataModel/Scene/Scene.swift +++ b/src/Catty/DataModel/Scene/Scene.swift @@ -78,6 +78,11 @@ self._objects } + func objectsWithoutBackground() -> [SpriteObject] { + let backgroundObjects = self.numberOfBackgroundObjects() + return [SpriteObject](self._objects[backgroundObjects...]) + } + @objc(objectAtIndex:) func object(at index: Int) -> SpriteObject? { if index >= 0 && index < self._objects.count { diff --git a/src/Catty/DataModel/Scripts/BroadcastScript.m b/src/Catty/DataModel/Scripts/BroadcastScript.m index 1d289e9414..405afe0fff 100644 --- a/src/Catty/DataModel/Scripts/BroadcastScript.m +++ b/src/Catty/DataModel/Scripts/BroadcastScript.m @@ -56,4 +56,13 @@ - (NSString*)messageForLineNumber:(NSInteger)lineNumber andParameterNumber:(NSIn return self.receivedMessage; } +- (Script*)cloneWithObject:(SpriteObject *)object +{ + BroadcastScript *clone = [[BroadcastScript alloc] init]; + clone.object = object; + clone.receivedMessage = self.receivedMessage; + + return clone; +} + @end diff --git a/src/Catty/DataModel/Scripts/Script.h b/src/Catty/DataModel/Scripts/Script.h index c714b700dd..8c0483f31e 100644 --- a/src/Catty/DataModel/Scripts/Script.h +++ b/src/Catty/DataModel/Scripts/Script.h @@ -55,5 +55,6 @@ - (NSInteger)getRequiredResources; - (Class)brickCell; +- (Script*) cloneWithObject: (SpriteObject *) object; @end diff --git a/src/Catty/DataModel/Scripts/Script.m b/src/Catty/DataModel/Scripts/Script.m index 1d0d3899b0..af32389246 100644 --- a/src/Catty/DataModel/Scripts/Script.m +++ b/src/Catty/DataModel/Scripts/Script.m @@ -100,6 +100,15 @@ - (id)mutableCopyWithContext:(CBMutableCopyContext*)context return copiedScript; } +- (Script*)cloneWithObject:(SpriteObject *)object { + + // Override this method in Script implementation + WhenScript *clone = [[WhenScript alloc] init]; + clone.object = object; + + return clone; +} + #pragma mark - Description - (NSString*)description { diff --git a/src/Catty/DataModel/Scripts/StartScript.m b/src/Catty/DataModel/Scripts/StartScript.m index 5ea8f1373f..472c91fe9b 100644 --- a/src/Catty/DataModel/Scripts/StartScript.m +++ b/src/Catty/DataModel/Scripts/StartScript.m @@ -29,4 +29,12 @@ - (kBrickCategoryType)category return kEventBrick; } +- (Script*)cloneWithObject:(SpriteObject *)object +{ + StartScript *clone = [[StartScript alloc] init]; + clone.object = object; + + return clone; +} + @end diff --git a/src/Catty/DataModel/Scripts/WhenBackgroundChangesScript.swift b/src/Catty/DataModel/Scripts/WhenBackgroundChangesScript.swift index b55988d8ec..cb6e2a03c3 100644 --- a/src/Catty/DataModel/Scripts/WhenBackgroundChangesScript.swift +++ b/src/Catty/DataModel/Scripts/WhenBackgroundChangesScript.swift @@ -95,4 +95,12 @@ class WhenBackgroundChangesScript: Script, BrickLookProtocol { return brick } + + override func clone(with object: SpriteObject!) -> Script! { + let clone = WhenBackgroundChangesScript() + clone.object = object + clone.look = self.look + + return clone + } } diff --git a/src/Catty/DataModel/Scripts/WhenConditionScript.swift b/src/Catty/DataModel/Scripts/WhenConditionScript.swift index f61147d79b..5bffe87d29 100644 --- a/src/Catty/DataModel/Scripts/WhenConditionScript.swift +++ b/src/Catty/DataModel/Scripts/WhenConditionScript.swift @@ -94,4 +94,14 @@ class WhenConditionScript: Script, BrickFormulaProtocol { return brick } + + override func clone(with object: SpriteObject!) -> Script! { + let clone = WhenConditionScript() + clone.object = object + clone.condition = self.condition + clone.preCondition = self.preCondition + + return clone + } + } diff --git a/src/Catty/DataModel/Scripts/WhenScript.m b/src/Catty/DataModel/Scripts/WhenScript.m index 174408091c..bd289ae6c8 100644 --- a/src/Catty/DataModel/Scripts/WhenScript.m +++ b/src/Catty/DataModel/Scripts/WhenScript.m @@ -50,4 +50,13 @@ - (BOOL)isEqualToScript:(Script *)script return [super isEqualToScript:script]; } +- (Script*)cloneWithObject:(SpriteObject *)object +{ + WhenScript *clone = [[WhenScript alloc] init]; + clone.object = object; + clone.action = self.action; + + return clone; +} + @end diff --git a/src/Catty/DataModel/Scripts/WhenTouchDownScript.m b/src/Catty/DataModel/Scripts/WhenTouchDownScript.m index c6381aa9b0..5a96f5a10d 100644 --- a/src/Catty/DataModel/Scripts/WhenTouchDownScript.m +++ b/src/Catty/DataModel/Scripts/WhenTouchDownScript.m @@ -29,4 +29,12 @@ - (kBrickCategoryType)category return kEventBrick; } +- (Script*)cloneWithObject:(SpriteObject *)object +{ + WhenTouchDownScript *clone = [[WhenTouchDownScript alloc] init]; + clone.object = object; + + return clone; +} + @end diff --git a/src/Catty/Defines/LanguageTranslationDefines.h b/src/Catty/Defines/LanguageTranslationDefines.h index 66ee4a9f18..67c805f891 100644 --- a/src/Catty/Defines/LanguageTranslationDefines.h +++ b/src/Catty/Defines/LanguageTranslationDefines.h @@ -382,6 +382,7 @@ #define kLocalizedEndOfLoop NSLocalizedString(@"End of Loop", nil) #define kLocalizedWhen NSLocalizedString(@"When", nil) #define kLocalizedBecomesTrue NSLocalizedString(@"becomes true", nil) +#define kLocalizedCreateCloneOf NSLocalizedString(@"Create clone of", nil) // motion bricks #define kLocalizedPlaceAt NSLocalizedString(@"Place at ", nil) diff --git a/src/Catty/Defines/LanguageTranslationDefinesSwift.swift b/src/Catty/Defines/LanguageTranslationDefinesSwift.swift index f43e4043e1..33d0b05e25 100644 --- a/src/Catty/Defines/LanguageTranslationDefinesSwift.swift +++ b/src/Catty/Defines/LanguageTranslationDefinesSwift.swift @@ -382,6 +382,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 kLocalizedCreateCloneOf = NSLocalizedString("Create clone of", comment: "") // motion bricks let kLocalizedPlaceAt = NSLocalizedString("Place at ", comment: "") diff --git a/src/Catty/Extension&Delegate&Protocol/Protocols/Bricks/BrickData/BrickObjectWithOutBackgroundProtocol.h b/src/Catty/Extension&Delegate&Protocol/Protocols/Bricks/BrickData/BrickObjectWithOutBackgroundProtocol.h new file mode 100644 index 0000000000..cdd1a2f3a7 --- /dev/null +++ b/src/Catty/Extension&Delegate&Protocol/Protocols/Bricks/BrickData/BrickObjectWithOutBackgroundProtocol.h @@ -0,0 +1,33 @@ +/** + * 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 + +@class Brick; +@class SpriteObject; + +@protocol BrickObjectWithOutBackgroundProtocol + +- (SpriteObject*)objectForLineNumber:(NSInteger)lineNumber andParameterNumber:(NSInteger)paramNumber; +- (void)setObject:(SpriteObject*)object forLineNumber:(NSInteger)lineNumber andParameterNumber:(NSInteger)paramNumber; + +@end diff --git a/src/Catty/PlayerEngine/DataModel/CBSpriteNode/CBSpriteNode.swift b/src/Catty/PlayerEngine/DataModel/CBSpriteNode/CBSpriteNode.swift index 85b81de6c9..68f608d5c1 100644 --- a/src/Catty/PlayerEngine/DataModel/CBSpriteNode/CBSpriteNode.swift +++ b/src/Catty/PlayerEngine/DataModel/CBSpriteNode/CBSpriteNode.swift @@ -249,6 +249,21 @@ class CBSpriteNode: SKSpriteNode { return self.contains(globalTouchPosition) && !imageLook.isTransparentPixel(atScenePoint: localTouchPosition) } + @objc func startAsClone(_ spriteNodeToClone: CBSpriteNode) { + + self.catrobatPosition = CBPosition(x: spriteNodeToClone.catrobatPosition.x, y: spriteNodeToClone.catrobatPosition.y) + self.changeLook(spriteNodeToClone.currentLook) + self.isHidden = spriteNodeToClone.isHidden + self.zRotation = CGFloat(spriteNodeToClone.zRotation) + self.xScale = CGFloat(spriteNodeToClone.xScale) + self.yScale = CGFloat(spriteNodeToClone.yScale) + self.isUserInteractionEnabled = spriteNodeToClone.isUserInteractionEnabled + self.ciBrightness = CGFloat(spriteNodeToClone.ciBrightness) + + self.zPosition = spriteNodeToClone.zPosition + spriteNodeToClone.zPosition += 1 + } + @objc func isFlipped() -> Bool { if self.xScale < 0 { return true diff --git a/src/Catty/PlayerEngine/Stage/Stage.swift b/src/Catty/PlayerEngine/Stage/Stage.swift index 067b248643..a255212cbc 100644 --- a/src/Catty/PlayerEngine/Stage/Stage.swift +++ b/src/Catty/PlayerEngine/Stage/Stage.swift @@ -281,6 +281,92 @@ final class Stage: SKScene, StageProtocol { return true } + @objc func addClonedObjecToProject(spriteObject: SpriteObject) { + let spriteNode = spriteObject.spriteNode! + + guard let scriptList = spriteObject.scriptList as NSArray? as? [Script] else { + //fatalError + debugPrint("!! No script list given in object: \(spriteObject) !!") + return + } + let variableList = UserDataContainer.objectVariables(for: spriteObject) + for script in scriptList { + let scriptSequence = frontend.computeSequenceListForScript(script) + let instructions = backend.instructionsForSequence(scriptSequence.sequenceList) + + logger.info("Generating Context of \(script)") + var context: CBScriptContext? + switch script { + case let startScript as StartScript: + context = CBStartScriptContext( + startScript: startScript, + spriteNode: spriteNode, + formulaInterpreter: formulaManager, + touchManager: formulaManager.touchManager, + state: .runnable) + + case let whenScript as WhenScript: + context = CBWhenScriptContext( + whenScript: whenScript, + spriteNode: spriteNode, + formulaInterpreter: formulaManager, + touchManager: formulaManager.touchManager, + state: .runnable) + + case let whenTouchDownScript as WhenTouchDownScript: + context = CBWhenTouchDownScriptContext( + whenTouchDownScript: whenTouchDownScript, + spriteNode: spriteNode, + formulaInterpreter: formulaManager, + touchManager: formulaManager.touchManager, + state: .runnable) + + case let whenBackgroundChangesScript as WhenBackgroundChangesScript: + context = CBWhenBackgroundChangesScriptContext( + whenBackgroundChangesScript: whenBackgroundChangesScript, + spriteNode: spriteNode, + formulaInterpreter: formulaManager, + touchManager: formulaManager.touchManager, + state: .runnable) + + case let bcScript as BroadcastScript: + context = CBBroadcastScriptContext( + broadcastScript: bcScript, + spriteNode: spriteNode, + formulaInterpreter: formulaManager, + touchManager: formulaManager.touchManager, + state: .runnable) + if let broadcastContext = context as? CBBroadcastScriptContext { + broadcastHandler.subscribeBroadcastContext(broadcastContext) + } + + case let whenConditionScript as WhenConditionScript: + context = CBWhenConditionScriptContext( + whenConditionScript: whenConditionScript, + spriteNode: spriteNode, + formulaInterpreter: formulaManager, + touchManager: formulaManager.touchManager, + state: .runnable) + + default: + break + } + guard var scriptContext = context else { + //fatalError + debugPrint("Unknown script! THIS SHOULD NEVER HAPPEN!") + return + } + scriptContext += instructions // generate instructions and add them to script context + scheduler.registerContext(scriptContext) + } + + for variable: UserVariable in variableList { + variable.textLabel?.zPosition = CGFloat(zPosition + 1) + addChild(variable.textLabel!) + } + return + } + @objc func pauseScheduler() { scheduler.pause() formulaManager.pause() diff --git a/src/Catty/Resources/Localization/en.lproj/Localizable.strings b/src/Catty/Resources/Localization/en.lproj/Localizable.strings index 27b6349218..fb3a798efd 100644 --- a/src/Catty/Resources/Localization/en.lproj/Localizable.strings +++ b/src/Catty/Resources/Localization/en.lproj/Localizable.strings @@ -391,6 +391,9 @@ /* No comment provided by engineer. */ "Create account" = "Create account"; +/* No comment provided by engineer. */ +"Create clone of" = "Create clone of"; + /* No comment provided by engineer. */ "Create patterns for stiching machines" = "Create patterns for stiching machines"; diff --git a/src/Catty/Setup/CatrobatSetup+Bricks.swift b/src/Catty/Setup/CatrobatSetup+Bricks.swift index 7c473cd533..b357de767c 100644 --- a/src/Catty/Setup/CatrobatSetup+Bricks.swift +++ b/src/Catty/Setup/CatrobatSetup+Bricks.swift @@ -33,6 +33,7 @@ BroadcastBrick(), BroadcastWaitBrick(), WhenBackgroundChangesScript(), + CloneBrick(), // control bricks WaitBrick(), IfThenLogicBeginBrick(), diff --git a/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/ScriptCollectionViewController.m b/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/ScriptCollectionViewController.m index 6d9dbc5f3d..fe06797699 100644 --- a/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/ScriptCollectionViewController.m +++ b/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/ScriptCollectionViewController.m @@ -38,6 +38,7 @@ #import "BrickLookProtocol.h" #import "BrickSoundProtocol.h" #import "BrickObjectProtocol.h" +#import "BrickObjectWithOutBackgroundProtocol.h" #import "BrickMessageProtocol.h" #import "BrickStaticChoiceProtocol.h" #import "BrickVariableProtocol.h" @@ -1111,7 +1112,7 @@ - (void)updateBrickCellData:(id)brickCellData withValue:( [soundBrick setSound:[Util soundWithName:(NSString*)value forObject:self.object] forLineNumber:line andParameterNumber:parameter]; } } else - if ([brickCellData isKindOfClass:[BrickCellObjectData class]] && [brick conformsToProtocol:@protocol(BrickObjectProtocol)]) { + if (([brickCellData isKindOfClass:[BrickCellObjectData class]] && [brick conformsToProtocol:@protocol(BrickObjectProtocol)]) || ([brickCellData isKindOfClass:[BrickCellObjectData class]] && [brick conformsToProtocol:@protocol(BrickObjectWithOutBackgroundProtocol)])) { Brick *objectBrick = (Brick*)brick; if([(NSString*)value isEqualToString:kLocalizedNewElement]) { SceneTableViewController *ptvc = [self.storyboard instantiateViewControllerWithIdentifier:kSceneTableViewControllerIdentifier]; @@ -1125,7 +1126,10 @@ - (void)updateBrickCellData:(id)brickCellData withValue:( [self.navigationController pushViewController:ptvc animated:YES]; return; } else { - [objectBrick setObject:[Util objectWithName:(NSString*)value forScene:self.object.scene] forLineNumber:line andParameterNumber:parameter]; + if ([value isEqualToString:@"yourself"]) + [objectBrick setObject:objectBrick.script.object forLineNumber:line andParameterNumber:parameter]; + else + [objectBrick setObject:[Util objectWithName:(NSString*)value forScene:self.object.scene] forLineNumber:line andParameterNumber:parameter]; } } else if ([brickCellData isKindOfClass:[BrickCellFormulaData class]] && [brick conformsToProtocol:@protocol(BrickFormulaProtocol)]) { diff --git a/src/Catty/Views/Custom/CollectionViewCells/BrickCellData/BrickCellObjectData.m b/src/Catty/Views/Custom/CollectionViewCells/BrickCellData/BrickCellObjectData.m index 2183825591..6d9bf886f6 100644 --- a/src/Catty/Views/Custom/CollectionViewCells/BrickCellData/BrickCellObjectData.m +++ b/src/Catty/Views/Custom/CollectionViewCells/BrickCellData/BrickCellObjectData.m @@ -25,6 +25,7 @@ #import "Script.h" #import "Brick.h" #import "BrickObjectProtocol.h" +#import "BrickObjectWithOutBackgroundProtocol.h" #import "Pocket_Code-Swift.h" @implementation BrickCellObjectData @@ -54,6 +55,22 @@ - (instancetype)initWithFrame:(CGRect)frame andBrickCell:(BrickCell*)brickCell a currentOptionIndex = optionIndex; } } + if([self.brickCell.scriptOrBrick conformsToProtocol:@protocol(BrickObjectWithOutBackgroundProtocol)]) { + Brick *objectBrick = (Brick*)self.brickCell.scriptOrBrick; + SpriteObject *currentObject = [objectBrick objectForLineNumber:self.lineNumber andParameterNumber:self.parameterNumber]; + for(SpriteObject *object in objectBrick.script.object.scene.objectsWithoutBackground) { + if([objectBrick.script.object.name isEqualToString:object.name]) { + [options addObject:@"yourself"]; + if([currentObject.name isEqualToString:objectBrick.script.object.name]) + currentOptionIndex = optionIndex; + } + else + [options addObject:object.name]; + if([currentObject.name isEqualToString:object.name]) + currentOptionIndex = optionIndex; + optionIndex++; + } + } } [self setValues:options]; [self setCurrentValue:options[currentOptionIndex]]; diff --git a/src/Catty/Views/Custom/CollectionViewCells/BrickCells/Control/CloneBrickCell.swift b/src/Catty/Views/Custom/CollectionViewCells/BrickCells/Control/CloneBrickCell.swift new file mode 100644 index 0000000000..2d63387b12 --- /dev/null +++ b/src/Catty/Views/Custom/CollectionViewCells/BrickCells/Control/CloneBrickCell.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/. + */ +import Foundation + +@objc(CloneBrickCell) class CloneBrickCell: BrickCell, BrickCellProtocol { + + public var textLabel: UILabel? + public var objectComboBoxView: iOSCombobox? + + override init(frame: CGRect) { + super.init(frame: frame) + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + static func cellHeight() -> CGFloat { + UIDefines.brickHeight2h + } + + override func hookUpSubViews(_ inlineViewSubViews: [Any]!) { + self.textLabel = inlineViewSubViews[0] as? UILabel + self.objectComboBoxView = inlineViewSubViews[1] as? iOSCombobox + } + + func brickTitle(forBackground isBackground: Bool, andInsertionScreen isInsertion: Bool) -> String! { + kLocalizedCreateCloneOf.appending("\n%@") + } + + override func parameters() -> [String] { + ["{OBJECT}"] + } +} diff --git a/src/Catty/XML/Context/Abstract/CBXMLAbstractContext.h b/src/Catty/XML/Context/Abstract/CBXMLAbstractContext.h index 371e6502eb..dd5542ab02 100644 --- a/src/Catty/XML/Context/Abstract/CBXMLAbstractContext.h +++ b/src/Catty/XML/Context/Abstract/CBXMLAbstractContext.h @@ -38,6 +38,7 @@ // ressources data used while traversing the tree //------------------------------------------------------------------------------------------------------------ @property (nonatomic, strong) NSMutableArray *pointedSpriteObjectList; // contains all already parsed pointed (!!) SpriteObjects +@property (nonatomic, strong) NSMutableArray *clonedSpriteObjectList; // contains all already parsed cloned (!!) SpriteObjects @property (nonatomic, strong) NSMutableArray *spriteObjectList; // contains all known SpriteObjects @property (nonatomic, strong) SpriteObject *spriteObject; // contains all looks, sounds, bricks, ... of currently parsed/serialized SpriteObject // TODO: refactor this later: remove brickList here and dynamically find brick in scriptList. maybe scripts should be referenced in bricks as well!! diff --git a/src/Catty/XML/Context/Abstract/CBXMLAbstractContext.m b/src/Catty/XML/Context/Abstract/CBXMLAbstractContext.m index f43cdbdf0b..92a21e629e 100644 --- a/src/Catty/XML/Context/Abstract/CBXMLAbstractContext.m +++ b/src/Catty/XML/Context/Abstract/CBXMLAbstractContext.m @@ -42,6 +42,14 @@ - (NSMutableArray*)pointedSpriteObjectList return _pointedSpriteObjectList; } +- (NSMutableArray*)clonedSpriteObjectList +{ + if (! _clonedSpriteObjectList) { + _clonedSpriteObjectList = [NSMutableArray array]; + } + return _clonedSpriteObjectList; +} + - (NSMutableArray*)spriteObjectList { if (! _spriteObjectList) { diff --git a/src/Catty/XML/XMLHandler/SpriteObject/SpriteObject+CBXMLHandler.h b/src/Catty/XML/XMLHandler/SpriteObject/SpriteObject+CBXMLHandler.h index c811ef90b8..5e6797098c 100644 --- a/src/Catty/XML/XMLHandler/SpriteObject/SpriteObject+CBXMLHandler.h +++ b/src/Catty/XML/XMLHandler/SpriteObject/SpriteObject+CBXMLHandler.h @@ -30,6 +30,8 @@ + (NSMutableArray*)parseAndCreateSounds:(GDataXMLElement*)objectElement withContext:(CBXMLParserContext*)context; #endif +- (GDataXMLElement*)xmlElementWithContext:(CBXMLSerializerContext*)context asPointedObject:(BOOL)asPointedObject asGoToObject:(BOOL)asGoToObject asCloneOfObject:(BOOL )asCloneOfObject; + - (GDataXMLElement*)xmlElementWithContext:(CBXMLSerializerContext*)context asPointedObject:(BOOL)asPointedObject asGoToObject:(BOOL)asGoToObject; @end diff --git a/src/Catty/XML/XMLHandler/SpriteObject/SpriteObject+CBXMLHandler.m b/src/Catty/XML/XMLHandler/SpriteObject/SpriteObject+CBXMLHandler.m index e0fabd5c3b..8036c5affc 100644 --- a/src/Catty/XML/XMLHandler/SpriteObject/SpriteObject+CBXMLHandler.m +++ b/src/Catty/XML/XMLHandler/SpriteObject/SpriteObject+CBXMLHandler.m @@ -40,11 +40,11 @@ @implementation SpriteObject (CBXMLHandler) + (instancetype)parseFromElement:(GDataXMLElement*)xmlElement withContext:(CBXMLParserContext*)context { [XMLError exceptionIfNil:xmlElement message:@"The rootElement nil"]; - if (! [xmlElement.name isEqualToString:@"object"] && ![xmlElement.name isEqualToString:@"pointedObject"] && ! [xmlElement.name isEqualToString:@"destinationSprite"]) { + if (! [xmlElement.name isEqualToString:@"object"] && ![xmlElement.name isEqualToString:@"pointedObject"] && ! [xmlElement.name isEqualToString:@"destinationSprite"] && ![xmlElement.name isEqualToString:@"objectToClone"]) { [XMLError exceptionIfString:xmlElement.name isNotEqualToString:@"object" message:@"The name of the rootElement is '%@' but should be '%@'", - xmlElement.name, @"object, pointedObject or destinationSprite"]; + xmlElement.name, @"object, pointedObject, destinationSprite or objectToClone"]; } NSArray *attributes = [xmlElement attributes]; @@ -79,6 +79,8 @@ + (instancetype)parseFromElement:(GDataXMLElement*)xmlElement withContext:(CBXML [XMLError exceptionIfNode:referencedObjectElement isNilOrNodeNameNotEquals:@"object"]; } else if([referencedObjectElement.name isEqualToString:@"destinationSprite"]) { [XMLError exceptionIfNode:referencedObjectElement isNilOrNodeNameNotEquals:@"destinationSprite"]; + } else if ([referencedObjectElement.name isEqualToString:@"objectToClone"]) { + [XMLError exceptionIfNode:referencedObjectElement isNilOrNodeNameNotEquals:@"objectToClone"]; } else { [XMLError exceptionIfNode:referencedObjectElement isNilOrNodeNameNotEquals:@"pointedObject"]; } @@ -175,10 +177,15 @@ + (NSMutableArray*)parseAndCreateScripts:(GDataXMLElement*)objectElement #pragma mark - Serialization - (GDataXMLElement*)xmlElementWithContext:(CBXMLSerializerContext*)context { - return [self xmlElementWithContext:context asPointedObject:NO asGoToObject:NO]; + return [self xmlElementWithContext:context asPointedObject:NO asGoToObject:NO asCloneOfObject:NO]; } - (GDataXMLElement*)xmlElementWithContext:(CBXMLSerializerContext*)context asPointedObject:(BOOL)asPointedObject asGoToObject:(BOOL)asGoToObject +{ + return [self xmlElementWithContext:context asPointedObject:asPointedObject asGoToObject:asGoToObject asCloneOfObject:NO]; +} + +- (GDataXMLElement*)xmlElementWithContext:(CBXMLSerializerContext*)context asPointedObject:(BOOL)asPointedObject asGoToObject:(BOOL)asGoToObject asCloneOfObject:(BOOL )asCloneOfObject { SpriteObject *previousObject = context.spriteObject; [context.soundNamePositions removeAllObjects]; @@ -188,11 +195,12 @@ - (GDataXMLElement*)xmlElementWithContext:(CBXMLSerializerContext*)context asPoi // generate xml element for sprite object GDataXMLElement *xmlElement = nil; - if (! asPointedObject && !asGoToObject) { + if (! asPointedObject && !asGoToObject && !asCloneOfObject) { NSUInteger indexOfSpriteObject = [CBXMLSerializerHelper indexOfElement:self inArray:context.spriteObjectList]; xmlElement = [GDataXMLElement elementWithName:@"object" xPathIndex:(indexOfSpriteObject+1) context:context]; } else { NSString* elementName = asGoToObject ? @"destinationSprite" : @"pointedObject"; + elementName = asCloneOfObject ? @"objectToClone" : elementName; xmlElement = [GDataXMLElement elementWithName:elementName context:context]; } diff --git a/src/CattyTests/Bricks/CloneBrick+CBXMLHandler.swift b/src/CattyTests/Bricks/CloneBrick+CBXMLHandler.swift new file mode 100644 index 0000000000..bca7fe2be4 --- /dev/null +++ b/src/CattyTests/Bricks/CloneBrick+CBXMLHandler.swift @@ -0,0 +1,104 @@ +/** + * 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 CloneBrick: CBXMLNodeProtocol { + static func parse(from xmlElement: GDataXMLElement, with context: CBXMLParserContext) -> Self { + let childCount = xmlElement.childrenWithoutCommentsAndCommentedOutTag().count + if childCount > 1 { + fatalError("Too many child nodes found... (0 or 1 expected, actual \(childCount)") + } + let cloneBrick = self.init() + + if childCount == 1 { + CBXMLParserHelper.validate(xmlElement, forNumberOfChildNodes: 1) + + let objectToCloneElement = xmlElement.child(withElementName: "objectToClone") + guard let _ = objectToCloneElement else { + fatalError("No clonedObject element found...") + } + let newContext = context + var spriteObject = newContext.parse(from: objectToCloneElement, withClass: SpriteObject.self) as! SpriteObject + context.spriteObjectList = newContext.spriteObjectList + context.clonedSpriteObjectList = newContext.clonedSpriteObjectList + let alreadyExistantSpriteObject = CBXMLParserHelper.findSpriteObject(in: context.clonedSpriteObjectList as? [Any], withName: spriteObject.name) + + if alreadyExistantSpriteObject != nil { + spriteObject = alreadyExistantSpriteObject! + } else { + context.clonedSpriteObjectList.add(spriteObject) + } + + cloneBrick.objectToClone = spriteObject + + } else { + cloneBrick.objectToClone = context.spriteObject + } + return cloneBrick + } + + func xmlElement(with context: CBXMLSerializerContext) -> GDataXMLElement? { + let brick = super.xmlElement(for: "CloneBrick", with: context) + + guard let _ = self.objectToClone else { + fatalError("No sprite object given in CloneBrick") + } + + guard let _ = self.script.object else { + fatalError("Missing reference to brick's sprite object") + } + + if self.objectToClone != self.script.object { + let indexOfClonedObject = CBXMLSerializerHelper.index(ofElement: self.objectToClone, in: context.spriteObjectList as? [Any]) + let indexOfSpriteObject = CBXMLSerializerHelper.index(ofElement: self.script.object, in: context.spriteObjectList as? [Any]) + if indexOfClonedObject == Foundation.NSNotFound { + fatalError("Cloned object does not exist in spriteObject list") + } + if indexOfSpriteObject == Foundation.NSNotFound { + fatalError("Sprite object does not exist in spriteObject list") + } + + let positionStackOfSpriteObject = context.spriteObjectNamePositions[self.objectToClone!.name as Any] + if positionStackOfSpriteObject != nil { + let clonedObjectXmlElement = GDataXMLElement.init(name: "objectToClone", context: context) + let currentPositionStack = context.currentPositionStack + + let refPath = CBXMLSerializerHelper.relativeXPath(fromSourcePositionStack: currentPositionStack, toDestinationPositionStack: positionStackOfSpriteObject as? CBXMLPositionStack) + + clonedObjectXmlElement?.addAttribute(GDataXMLElement.attribute(withName: "reference", escapedStringValue: refPath) as? GDataXMLNode) + brick?.addChild(clonedObjectXmlElement, context: context) + + } else { + let newContext = context + newContext.currentPositionStack = context.currentPositionStack + let clonedObjectXmlElement = self.objectToClone?.xmlElement(with: newContext, asPointedObject: false, asGoToObject: false, asCloneOfObject: true) + context.spriteObjectNamePositions = newContext.spriteObjectNamePositions + context.spriteObjectNameUserVariableListPositions = newContext.spriteObjectNameUserVariableListPositions + context.projectUserVariableNamePositions = newContext.projectUserVariableNamePositions + context.projectUserListNamePositions = newContext.projectUserListNamePositions + context.clonedSpriteObjectList = newContext.clonedSpriteObjectList + brick?.addChild(clonedObjectXmlElement, context: context) + context.clonedSpriteObjectList.add(self.objectToClone!) + } + } + return brick + } +} diff --git a/src/CattyTests/Bricks/CloneBrickTests.swift b/src/CattyTests/Bricks/CloneBrickTests.swift new file mode 100644 index 0000000000..5cd171774f --- /dev/null +++ b/src/CattyTests/Bricks/CloneBrickTests.swift @@ -0,0 +1,104 @@ +/** + * 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 XCTest + +@testable import Pocket_Code + +final class CloneBrickTests: AbstractBrickTest { + + var firstSpriteNode: CBSpriteNode! + var script: Script! + var brick: CloneBrick! + var scene: Scene! + + override func setUp() { + super.setUp() + self.stage = StageBuilder(project: ProjectMock()).build() + + let firstObject = SpriteObject() + scene = Scene(name: "testScene") + firstObject.scene = scene + firstSpriteNode = CBSpriteNode(spriteObject: firstObject) + firstObject.spriteNode = firstSpriteNode + + self.stage.addChild(firstSpriteNode) + scene.add(object: firstObject) + + script = WhenScript() + script.object = firstObject + + brick = CloneBrick() + brick.script = script + brick.objectToClone = firstObject + } + + func testCreateClone() { + XCTAssertEqual(brick.objectToClone!.scene.objects().count, 1) + let name = "test" + brick.objectToClone?.name = name + let userData = UserDataContainer() + brick.objectToClone?.userData = userData + let scriptList: NSMutableArray = [Script()] + brick.objectToClone?.scriptList = scriptList + let soundList: NSMutableArray = [Sound(name: "test", fileName: "testName")] + brick.objectToClone?.soundList = soundList + let lookList: NSMutableArray = [Look(name: "test", filePath: "testPath")] + brick.objectToClone?.lookList = lookList + + let action = brick.actionBlock(self.formulaInterpreter) + action() + + XCTAssertEqual(brick.objectToClone!.scene.objects().count, 2) + + let firstObject = brick.objectToClone!.scene.object(at: 0) + let secondObject = brick.objectToClone!.scene.object(at: 1) + + XCTAssertEqual(firstObject?.userData, userData) + XCTAssertEqual(secondObject?.userData, userData) + XCTAssertEqual(firstObject?.lookList, lookList) + XCTAssertEqual(secondObject?.lookList, lookList) + XCTAssertEqual(firstObject?.soundList, soundList) + XCTAssertEqual(secondObject?.soundList, soundList) + } + + func testMutableCopy() { + let brick = CloneBrick() + let script = Script() + let object = SpriteObject() + let scene = Scene(name: "testScene") + object.scene = scene + + script.object = object + brick.script = script + let clonedObject = SpriteObject() + clonedObject.name = "clonedObject" + brick.objectToClone = clonedObject + + let copiedBrick: CloneBrick = brick.mutableCopy(with: CBMutableCopyContext()) as! CloneBrick + + XCTAssertTrue(brick.isEqual(to: copiedBrick)) + XCTAssertFalse(brick === copiedBrick) + XCTAssertTrue(brick.objectToClone!.isEqual(to: copiedBrick.objectToClone)) + XCTAssertTrue(brick.objectToClone === copiedBrick.objectToClone) + } +} diff --git a/src/CattyTests/Resources/ParserTests/Custom/ValidProjectAllBricks/ValidProjectAllBricks0992.xml b/src/CattyTests/Resources/ParserTests/Custom/ValidProjectAllBricks/ValidProjectAllBricks0992.xml index 369f2e9873..27a73c00a3 100644 --- a/src/CattyTests/Resources/ParserTests/Custom/ValidProjectAllBricks/ValidProjectAllBricks0992.xml +++ b/src/CattyTests/Resources/ParserTests/Custom/ValidProjectAllBricks/ValidProjectAllBricks0992.xml @@ -772,6 +772,13 @@ + + false + + + false + + false false @@ -805,6 +812,10 @@ + + + + @@ -829,6 +840,10 @@ + + + + diff --git a/src/CattyTests/XML/Parser/CatrobatLanguage0.992/XMLParserTests0992.swift b/src/CattyTests/XML/Parser/CatrobatLanguage0.992/XMLParserTests0992.swift index b8b16cf888..8505f9ae49 100644 --- a/src/CattyTests/XML/Parser/CatrobatLanguage0.992/XMLParserTests0992.swift +++ b/src/CattyTests/XML/Parser/CatrobatLanguage0.992/XMLParserTests0992.swift @@ -411,4 +411,15 @@ class XMLParserTests0992: XMLAbstractTest { XCTAssertTrue(setTempoToBrick.isKind(of: SetTempoToBrick.self), "Invalid brick type") } + + func testCreateCloneOfBrick() { + let project = self.getProjectForXML(xmlFile: "ValidProjectAllBricks0992") + var createCloneOfBrick = (project.scene.object(at: 1)!.scriptList.object(at: 0) as! Script).brickList.object(at: 6) as! Brick + + XCTAssertTrue(createCloneOfBrick.isKind(of: CloneBrick.self), "Invalid brick type") + + createCloneOfBrick = (project.scene.object(at: 1)!.scriptList.object(at: 0) as! Script).brickList.object(at: 7) as! Brick + + XCTAssertTrue(createCloneOfBrick.isKind(of: CloneBrick.self), "Invalid brick type") + } } diff --git a/src/CattyUITests/Defines/LanguageTranslationDefinesUI.swift b/src/CattyUITests/Defines/LanguageTranslationDefinesUI.swift index 55ce94c82b..814287bf4c 100644 --- a/src/CattyUITests/Defines/LanguageTranslationDefinesUI.swift +++ b/src/CattyUITests/Defines/LanguageTranslationDefinesUI.swift @@ -382,6 +382,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 kLocalizedCreateCloneOf = NSLocalizedString("Create clone of", bundle: Bundle(for: LanguageTranslation.self), comment: "") // motion bricks let kLocalizedPlaceAt = NSLocalizedString("Place at ", bundle: Bundle(for: LanguageTranslation.self), comment: "")