diff --git a/src/Catty.xcodeproj/project.pbxproj b/src/Catty.xcodeproj/project.pbxproj index 6e3f4cd05d..f70ceae56a 100644 --- a/src/Catty.xcodeproj/project.pbxproj +++ b/src/Catty.xcodeproj/project.pbxproj @@ -346,6 +346,13 @@ 49519D3727DCE11700E32E88 /* SecondFaceSizeSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49519D3627DCE11700E32E88 /* SecondFaceSizeSensor.swift */; }; 49530A8227FDDADC003A9E24 /* FaceDetectionSensors.xml in Resources */ = {isa = PBXBuildFile; fileRef = 49530A8127FDDADC003A9E24 /* FaceDetectionSensors.xml */; }; 49530A8427FDDC04003A9E24 /* BackwardsCompatibleFaceDetectionSensors.xml in Resources */ = {isa = PBXBuildFile; fileRef = 49530A8327FDDC03003A9E24 /* BackwardsCompatibleFaceDetectionSensors.xml */; }; + 4949720027BE4D4E003D8C7E /* VisualPlacementTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 494971FF27BE4D4E003D8C7E /* VisualPlacementTest.swift */; }; + 495A1EC827B0F579009610F5 /* PlaceAtBrick.swift in Sources */ = {isa = PBXBuildFile; fileRef = 495A1EC727B0F579009610F5 /* PlaceAtBrick.swift */; }; + 495A1ECC27B105B0009610F5 /* PlaceAtBrick+CBXMLHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 495A1ECB27B105B0009610F5 /* PlaceAtBrick+CBXMLHandler.swift */; }; + 497B439E27B24B5E0059091F /* GlideToBrick.swift in Sources */ = {isa = PBXBuildFile; fileRef = 497B439D27B24B5D0059091F /* GlideToBrick.swift */; }; + 49D5D7AC27B2589700B80096 /* GlideToBrick+CBXMLHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49D5D7AB27B2589700B80096 /* GlideToBrick+CBXMLHandler.swift */; }; + 49F0DA1627B3A7A3003E4B3A /* BrickVisualPlacementProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49F0DA1527B3A7A2003E4B3A /* BrickVisualPlacementProtocol.swift */; }; + 49F0DA1A27B3B4A3003E4B3A /* VisualPlacementViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49F0DA1927B3B4A3003E4B3A /* VisualPlacementViewController.swift */; }; 4C0076DA25F6AF79002D754D /* StagePresenterSideMenuViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0076D725F6AF79002D754D /* StagePresenterSideMenuViewTests.swift */; }; 4C03A4BE2133FD05007BFFD2 /* FormulaManager+Resources.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C03A4BD2133FD05007BFFD2 /* FormulaManager+Resources.swift */; }; 4C03A4C22133FDE7007BFFD2 /* FormulaManager+Editor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C03A4C12133FDE7007BFFD2 /* FormulaManager+Editor.swift */; }; @@ -1461,10 +1468,8 @@ AA74EF4D1BC0586F00D1E954 /* ChangeXByNBrick+CBXMLHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EF311BC0586F00D1E954 /* ChangeXByNBrick+CBXMLHandler.m */; }; AA74EF4E1BC0586F00D1E954 /* ChangeYByNBrick+CBXMLHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EF331BC0586F00D1E954 /* ChangeYByNBrick+CBXMLHandler.m */; }; AA74EF4F1BC0586F00D1E954 /* ComeToFrontBrick+CBXMLHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EF351BC0586F00D1E954 /* ComeToFrontBrick+CBXMLHandler.m */; }; - AA74EF501BC0586F00D1E954 /* GlideToBrick+CBXMLHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EF371BC0586F00D1E954 /* GlideToBrick+CBXMLHandler.m */; }; AA74EF511BC0586F00D1E954 /* GoNStepsBackBrick+CBXMLHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EF391BC0586F00D1E954 /* GoNStepsBackBrick+CBXMLHandler.m */; }; AA74EF521BC0586F00D1E954 /* MoveNStepsBrick+CBXMLHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EF3B1BC0586F00D1E954 /* MoveNStepsBrick+CBXMLHandler.m */; }; - AA74EF531BC0586F00D1E954 /* PlaceAtBrick+CBXMLHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EF3D1BC0586F00D1E954 /* PlaceAtBrick+CBXMLHandler.m */; }; AA74EF541BC0586F00D1E954 /* PointInDirectionBrick+CBXMLHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EF3F1BC0586F00D1E954 /* PointInDirectionBrick+CBXMLHandler.m */; }; AA74EF551BC0586F00D1E954 /* PointToBrick+CBXMLHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EF411BC0586F00D1E954 /* PointToBrick+CBXMLHandler.m */; }; AA74EF571BC0586F00D1E954 /* SetXBrick+CBXMLHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EF451BC0586F00D1E954 /* SetXBrick+CBXMLHandler.m */; }; @@ -1504,11 +1509,9 @@ AA74EFFC1BC05B5F00D1E954 /* ChangeXByNBrick.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EFBB1BC05B5F00D1E954 /* ChangeXByNBrick.m */; }; AA74EFFD1BC05B5F00D1E954 /* ChangeYByNBrick.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EFBD1BC05B5F00D1E954 /* ChangeYByNBrick.m */; }; AA74EFFE1BC05B5F00D1E954 /* ComeToFrontBrick.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EFBF1BC05B5F00D1E954 /* ComeToFrontBrick.m */; }; - AA74EFFF1BC05B5F00D1E954 /* GlideToBrick.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EFC11BC05B5F00D1E954 /* GlideToBrick.m */; }; AA74F0001BC05B5F00D1E954 /* GoNStepsBackBrick.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EFC31BC05B5F00D1E954 /* GoNStepsBackBrick.m */; }; AA74F0011BC05B5F00D1E954 /* IfOnEdgeBounceBrick.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EFC51BC05B5F00D1E954 /* IfOnEdgeBounceBrick.m */; }; AA74F0021BC05B5F00D1E954 /* MoveNStepsBrick.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EFC71BC05B5F00D1E954 /* MoveNStepsBrick.m */; }; - AA74F0031BC05B5F00D1E954 /* PlaceAtBrick.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EFC91BC05B5F00D1E954 /* PlaceAtBrick.m */; }; AA74F0041BC05B5F00D1E954 /* PointInDirectionBrick.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EFCB1BC05B5F00D1E954 /* PointInDirectionBrick.m */; }; AA74F0051BC05B5F00D1E954 /* PointToBrick.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EFCD1BC05B5F00D1E954 /* PointToBrick.m */; }; AA74F0061BC05B5F00D1E954 /* SetXBrick.m in Sources */ = {isa = PBXBuildFile; fileRef = AA74EFCF1BC05B5F00D1E954 /* SetXBrick.m */; }; @@ -2346,7 +2349,14 @@ 49519D3627DCE11700E32E88 /* SecondFaceSizeSensor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondFaceSizeSensor.swift; sourceTree = ""; }; 49530A8127FDDADC003A9E24 /* FaceDetectionSensors.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = FaceDetectionSensors.xml; sourceTree = ""; }; 49530A8327FDDC03003A9E24 /* BackwardsCompatibleFaceDetectionSensors.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = BackwardsCompatibleFaceDetectionSensors.xml; sourceTree = ""; }; + 494971FF27BE4D4E003D8C7E /* VisualPlacementTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisualPlacementTest.swift; sourceTree = ""; }; + 495A1EC727B0F579009610F5 /* PlaceAtBrick.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceAtBrick.swift; sourceTree = ""; }; + 495A1ECB27B105B0009610F5 /* PlaceAtBrick+CBXMLHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "PlaceAtBrick+CBXMLHandler.swift"; path = "Catty/DataModel/Bricks/Motion/PlaceAtBrick+CBXMLHandler.swift"; sourceTree = SOURCE_ROOT; }; + 497B439D27B24B5D0059091F /* GlideToBrick.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlideToBrick.swift; sourceTree = ""; }; 4997640FD2AB79927E45C4EF /* ca */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Localizable.strings; sourceTree = ""; }; + 49D5D7AB27B2589700B80096 /* GlideToBrick+CBXMLHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "GlideToBrick+CBXMLHandler.swift"; path = "Catty/DataModel/Bricks/Motion/GlideToBrick+CBXMLHandler.swift"; sourceTree = SOURCE_ROOT; }; + 49F0DA1527B3A7A2003E4B3A /* BrickVisualPlacementProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrickVisualPlacementProtocol.swift; sourceTree = ""; }; + 49F0DA1927B3B4A3003E4B3A /* VisualPlacementViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisualPlacementViewController.swift; sourceTree = ""; }; 4C0076D725F6AF79002D754D /* StagePresenterSideMenuViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StagePresenterSideMenuViewTests.swift; sourceTree = ""; }; 4C03A4BD2133FD05007BFFD2 /* FormulaManager+Resources.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FormulaManager+Resources.swift"; sourceTree = ""; }; 4C03A4C12133FDE7007BFFD2 /* FormulaManager+Editor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FormulaManager+Editor.swift"; sourceTree = ""; }; @@ -3863,14 +3873,10 @@ AA74EF331BC0586F00D1E954 /* ChangeYByNBrick+CBXMLHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "ChangeYByNBrick+CBXMLHandler.m"; path = "Catty/XML/XMLHandler/Bricks/Motion/ChangeYByNBrick+CBXMLHandler.m"; sourceTree = SOURCE_ROOT; }; AA74EF341BC0586F00D1E954 /* ComeToFrontBrick+CBXMLHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ComeToFrontBrick+CBXMLHandler.h"; path = "Catty/XML/XMLHandler/Bricks/Motion/ComeToFrontBrick+CBXMLHandler.h"; sourceTree = SOURCE_ROOT; }; AA74EF351BC0586F00D1E954 /* ComeToFrontBrick+CBXMLHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "ComeToFrontBrick+CBXMLHandler.m"; path = "Catty/XML/XMLHandler/Bricks/Motion/ComeToFrontBrick+CBXMLHandler.m"; sourceTree = SOURCE_ROOT; }; - AA74EF361BC0586F00D1E954 /* GlideToBrick+CBXMLHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "GlideToBrick+CBXMLHandler.h"; path = "Catty/XML/XMLHandler/Bricks/Motion/GlideToBrick+CBXMLHandler.h"; sourceTree = SOURCE_ROOT; }; - AA74EF371BC0586F00D1E954 /* GlideToBrick+CBXMLHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "GlideToBrick+CBXMLHandler.m"; path = "Catty/XML/XMLHandler/Bricks/Motion/GlideToBrick+CBXMLHandler.m"; sourceTree = SOURCE_ROOT; }; AA74EF381BC0586F00D1E954 /* GoNStepsBackBrick+CBXMLHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "GoNStepsBackBrick+CBXMLHandler.h"; path = "Catty/XML/XMLHandler/Bricks/Motion/GoNStepsBackBrick+CBXMLHandler.h"; sourceTree = SOURCE_ROOT; }; AA74EF391BC0586F00D1E954 /* GoNStepsBackBrick+CBXMLHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "GoNStepsBackBrick+CBXMLHandler.m"; path = "Catty/XML/XMLHandler/Bricks/Motion/GoNStepsBackBrick+CBXMLHandler.m"; sourceTree = SOURCE_ROOT; }; AA74EF3A1BC0586F00D1E954 /* MoveNStepsBrick+CBXMLHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "MoveNStepsBrick+CBXMLHandler.h"; path = "Catty/XML/XMLHandler/Bricks/Motion/MoveNStepsBrick+CBXMLHandler.h"; sourceTree = SOURCE_ROOT; }; AA74EF3B1BC0586F00D1E954 /* MoveNStepsBrick+CBXMLHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "MoveNStepsBrick+CBXMLHandler.m"; path = "Catty/XML/XMLHandler/Bricks/Motion/MoveNStepsBrick+CBXMLHandler.m"; sourceTree = SOURCE_ROOT; }; - AA74EF3C1BC0586F00D1E954 /* PlaceAtBrick+CBXMLHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "PlaceAtBrick+CBXMLHandler.h"; path = "Catty/XML/XMLHandler/Bricks/Motion/PlaceAtBrick+CBXMLHandler.h"; sourceTree = SOURCE_ROOT; }; - AA74EF3D1BC0586F00D1E954 /* PlaceAtBrick+CBXMLHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "PlaceAtBrick+CBXMLHandler.m"; path = "Catty/XML/XMLHandler/Bricks/Motion/PlaceAtBrick+CBXMLHandler.m"; sourceTree = SOURCE_ROOT; }; AA74EF3E1BC0586F00D1E954 /* PointInDirectionBrick+CBXMLHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "PointInDirectionBrick+CBXMLHandler.h"; path = "Catty/XML/XMLHandler/Bricks/Motion/PointInDirectionBrick+CBXMLHandler.h"; sourceTree = SOURCE_ROOT; }; AA74EF3F1BC0586F00D1E954 /* PointInDirectionBrick+CBXMLHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "PointInDirectionBrick+CBXMLHandler.m"; path = "Catty/XML/XMLHandler/Bricks/Motion/PointInDirectionBrick+CBXMLHandler.m"; sourceTree = SOURCE_ROOT; }; AA74EF401BC0586F00D1E954 /* PointToBrick+CBXMLHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "PointToBrick+CBXMLHandler.h"; path = "Catty/XML/XMLHandler/Bricks/Motion/PointToBrick+CBXMLHandler.h"; sourceTree = SOURCE_ROOT; }; @@ -3949,16 +3955,12 @@ AA74EFBD1BC05B5F00D1E954 /* ChangeYByNBrick.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChangeYByNBrick.m; sourceTree = ""; }; AA74EFBE1BC05B5F00D1E954 /* ComeToFrontBrick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComeToFrontBrick.h; sourceTree = ""; }; AA74EFBF1BC05B5F00D1E954 /* ComeToFrontBrick.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ComeToFrontBrick.m; sourceTree = ""; }; - AA74EFC01BC05B5F00D1E954 /* GlideToBrick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GlideToBrick.h; sourceTree = ""; }; - AA74EFC11BC05B5F00D1E954 /* GlideToBrick.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GlideToBrick.m; sourceTree = ""; }; AA74EFC21BC05B5F00D1E954 /* GoNStepsBackBrick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GoNStepsBackBrick.h; sourceTree = ""; }; AA74EFC31BC05B5F00D1E954 /* GoNStepsBackBrick.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GoNStepsBackBrick.m; sourceTree = ""; }; AA74EFC41BC05B5F00D1E954 /* IfOnEdgeBounceBrick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IfOnEdgeBounceBrick.h; sourceTree = ""; }; AA74EFC51BC05B5F00D1E954 /* IfOnEdgeBounceBrick.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IfOnEdgeBounceBrick.m; sourceTree = ""; }; AA74EFC61BC05B5F00D1E954 /* MoveNStepsBrick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MoveNStepsBrick.h; sourceTree = ""; }; AA74EFC71BC05B5F00D1E954 /* MoveNStepsBrick.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MoveNStepsBrick.m; sourceTree = ""; }; - AA74EFC81BC05B5F00D1E954 /* PlaceAtBrick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlaceAtBrick.h; sourceTree = ""; }; - AA74EFC91BC05B5F00D1E954 /* PlaceAtBrick.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlaceAtBrick.m; sourceTree = ""; }; AA74EFCA1BC05B5F00D1E954 /* PointInDirectionBrick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PointInDirectionBrick.h; sourceTree = ""; }; AA74EFCB1BC05B5F00D1E954 /* PointInDirectionBrick.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PointInDirectionBrick.m; sourceTree = ""; }; AA74EFCC1BC05B5F00D1E954 /* PointToBrick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PointToBrick.h; sourceTree = ""; }; @@ -6011,6 +6013,7 @@ 9990BB6C1D89D89A0088357A /* BrickStaticChoiceProtocol.h */, 4C1EB20F1AC19B3D0001F431 /* BrickTextProtocol.h */, 4CC0D51F1B01FB73006193C4 /* BrickVariableProtocol.h */, + 49F0DA1527B3A7A2003E4B3A /* BrickVisualPlacementProtocol.swift */, ); path = BrickData; sourceTree = ""; @@ -6429,16 +6432,12 @@ AA74EF331BC0586F00D1E954 /* ChangeYByNBrick+CBXMLHandler.m */, AA74EF341BC0586F00D1E954 /* ComeToFrontBrick+CBXMLHandler.h */, AA74EF351BC0586F00D1E954 /* ComeToFrontBrick+CBXMLHandler.m */, - AA74EF361BC0586F00D1E954 /* GlideToBrick+CBXMLHandler.h */, - AA74EF371BC0586F00D1E954 /* GlideToBrick+CBXMLHandler.m */, AA74EF381BC0586F00D1E954 /* GoNStepsBackBrick+CBXMLHandler.h */, AA74EF391BC0586F00D1E954 /* GoNStepsBackBrick+CBXMLHandler.m */, AA74EF7C1BC05A3400D1E954 /* IfOnEdgeBounceBrick+CBXMLHandler.h */, AA74EF7D1BC05A3400D1E954 /* IfOnEdgeBounceBrick+CBXMLHandler.m */, AA74EF3A1BC0586F00D1E954 /* MoveNStepsBrick+CBXMLHandler.h */, AA74EF3B1BC0586F00D1E954 /* MoveNStepsBrick+CBXMLHandler.m */, - AA74EF3C1BC0586F00D1E954 /* PlaceAtBrick+CBXMLHandler.h */, - AA74EF3D1BC0586F00D1E954 /* PlaceAtBrick+CBXMLHandler.m */, AA74EF3E1BC0586F00D1E954 /* PointInDirectionBrick+CBXMLHandler.h */, AA74EF3F1BC0586F00D1E954 /* PointInDirectionBrick+CBXMLHandler.m */, AA74EF401BC0586F00D1E954 /* PointToBrick+CBXMLHandler.h */, @@ -6453,6 +6452,8 @@ AA74EF4B1BC0586F00D1E954 /* TurnRightBrick+CBXMLHandler.m */, D30359E424445A6B006688F5 /* GoToBrick+CBXMLHandler.h */, D30359E524445ABE006688F5 /* GoToBrick+CBXMLHandler.m */, + 495A1ECB27B105B0009610F5 /* PlaceAtBrick+CBXMLHandler.swift */, + 49D5D7AB27B2589700B80096 /* GlideToBrick+CBXMLHandler.swift */, ); name = Motion; path = MotionBricks; @@ -8139,6 +8140,7 @@ 4C4EE29A210901E70045F890 /* FormulaEditorViewControllerInputExtension.swift */, F4664F9120DD7A1700E1519A /* FormulaEditorViewControllerSectionExtension.swift */, 18957DDE25B8B870001A623F /* FormulaEditorSubsection.swift */, + 49F0DA1927B3B4A3003E4B3A /* VisualPlacementViewController.swift */, ); path = ViewController; sourceTree = ""; @@ -9918,16 +9920,12 @@ AA74EFBD1BC05B5F00D1E954 /* ChangeYByNBrick.m */, AA74EFBE1BC05B5F00D1E954 /* ComeToFrontBrick.h */, AA74EFBF1BC05B5F00D1E954 /* ComeToFrontBrick.m */, - AA74EFC01BC05B5F00D1E954 /* GlideToBrick.h */, - AA74EFC11BC05B5F00D1E954 /* GlideToBrick.m */, AA74EFC21BC05B5F00D1E954 /* GoNStepsBackBrick.h */, AA74EFC31BC05B5F00D1E954 /* GoNStepsBackBrick.m */, AA74EFC41BC05B5F00D1E954 /* IfOnEdgeBounceBrick.h */, AA74EFC51BC05B5F00D1E954 /* IfOnEdgeBounceBrick.m */, AA74EFC61BC05B5F00D1E954 /* MoveNStepsBrick.h */, AA74EFC71BC05B5F00D1E954 /* MoveNStepsBrick.m */, - AA74EFC81BC05B5F00D1E954 /* PlaceAtBrick.h */, - AA74EFC91BC05B5F00D1E954 /* PlaceAtBrick.m */, AA74EFCA1BC05B5F00D1E954 /* PointInDirectionBrick.h */, AA74EFCB1BC05B5F00D1E954 /* PointInDirectionBrick.m */, AA74EFCC1BC05B5F00D1E954 /* PointToBrick.h */, @@ -9942,6 +9940,8 @@ AA74EFD51BC05B5F00D1E954 /* TurnRightBrick.m */, D38F58652441B24C0079F6EA /* GoToBrick.h */, D38F58612441B19F0079F6EA /* GoToBrick.m */, + 495A1EC727B0F579009610F5 /* PlaceAtBrick.swift */, + 497B439D27B24B5D0059091F /* GlideToBrick.swift */, ); path = Motion; sourceTree = ""; @@ -10267,6 +10267,7 @@ 9797CB8225AF7A6000A50444 /* SceneTVCTests.swift */, 18E908A72624995900EF57D6 /* FormulaEditorComputeDialogTest.swift */, 2EB9FAF3269967FF00DBC4FB /* TrustedDomainTVCTests.swift */, + 494971FF27BE4D4E003D8C7E /* VisualPlacementTest.swift */, ); path = CattyUITests; sourceTree = ""; @@ -11786,6 +11787,7 @@ 4CB1FB741BC2D74F0000A2FE /* XCTestCaseExtension.swift in Sources */, BC19327F21186504009DE43A /* CreateProjectTests.swift in Sources */, BCFED6ED2111C04000BE57BF /* BackgroundsTests.swift in Sources */, + 4949720027BE4D4E003D8C7E /* VisualPlacementTest.swift in Sources */, 2EB9FAF4269967FF00DBC4FB /* TrustedDomainTVCTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -12297,6 +12299,7 @@ AABCB3DD1BB364DD009F67D2 /* CBIfConditionalSequence.swift in Sources */, 4C0F9F82204BD20A00E71B2D /* SpeakAndWaitBrick+Instruction.swift in Sources */, AA74EFF21BC05B5F00D1E954 /* ChangeTransparencyByNBrick.m in Sources */, + 49F0DA1627B3A7A3003E4B3A /* BrickVisualPlacementProtocol.swift in Sources */, 929CC0CD1BC39B0A0027DEC0 /* PhiroMotorMoveForwardBrick.m in Sources */, 4C0F9F8E204BD27200E71B2D /* RepeatUntilBrickCell.m in Sources */, AABCB3DB1BB364B9009F67D2 /* CBBroadcastHandlerProtocol.swift in Sources */, @@ -12368,6 +12371,7 @@ 92FF2EA41A24C7D800093DA7 /* Util.m in Sources */, AA74EFEC1BC05B5F00D1E954 /* ChangeVariableBrick.m in Sources */, 92FF31031A24DCAA00093DA7 /* Script.m in Sources */, + 495A1ECC27B105B0009610F5 /* PlaceAtBrick+CBXMLHandler.swift in Sources */, 4C822693213FBC4400F3D750 /* MultiFingerTouchedFunction.swift in Sources */, 4420ACB1250929AE00951328 /* AskBrick+CBXMLHandler.swift in Sources */, 1882475924C84D9C00B01653 /* SetPenColorBrickCell.swift in Sources */, @@ -12565,7 +12569,6 @@ AA74EEDC1BC057B900D1E954 /* BroadcastWaitBrick+CBXMLHandler.m in Sources */, 4C0F9F5A204BD16300E71B2D /* CameraBrick+CBXMLHandler.m in Sources */, AA74EFFA1BC05B5F00D1E954 /* ShowBrick.m in Sources */, - AA74EF501BC0586F00D1E954 /* GlideToBrick+CBXMLHandler.m in Sources */, BACDF3571F1F9BB000346167 /* DeleteItemOfUserListBrick+CBXMLHandler.m in Sources */, 921D468A1BDF698A0086AD20 /* NextLookBrick+Instruction.swift in Sources */, 9218B2141CC4AB75007B4C60 /* BrushPickerViewController.m in Sources */, @@ -12639,6 +12642,7 @@ 4CF072AE20D6753D00F93AB5 /* DateYearSensor.swift in Sources */, 4C994E1C207A55E500C415FD /* CompassDirectionSensor.swift in Sources */, 9200C2D51C8082EF002F5CA4 /* HideTextBrickCell.m in Sources */, + 49D5D7AC27B2589700B80096 /* GlideToBrick+CBXMLHandler.swift in Sources */, 46CF173925E2F53000DADF08 /* SetBackgroundBrickCell.swift in Sources */, AA74EF001BC057C900D1E954 /* ShowBrick+CBXMLHandler.m in Sources */, AA74EFE41BC05B5F00D1E954 /* IfLogicBeginBrick.m in Sources */, @@ -12648,6 +12652,7 @@ 97D015912553392A00B6967D /* RoundedImageView.swift in Sources */, 4C5076D22578DBDC00650440 /* SetInstrumentBrick+CBXMLHandler.swift in Sources */, 181CC10724B750AF004A783E /* CBPosition.swift in Sources */, + 497B439E27B24B5E0059091F /* GlideToBrick.swift in Sources */, AA74EFF91BC05B5F00D1E954 /* SetTransparencyBrick.m in Sources */, 186E99192488F74500627E36 /* PenUpBrick+Instruction.swift in Sources */, 056677F727DEA772006B4477 /* StartZigzagStitchBrick+Instruction.swift in Sources */, @@ -12662,6 +12667,7 @@ 4CF0728C20D659F700F93AB5 /* PhiroSideLeftSensor.swift in Sources */, AA74F0C01BC05FCE00D1E954 /* SetXBrickCell.m in Sources */, 6F1911A124E7CE0D00CF1B4F /* SceneMock.swift in Sources */, + 49F0DA1A27B3B4A3003E4B3A /* VisualPlacementViewController.swift in Sources */, AA74EF6F1BC0588A00D1E954 /* PlaySoundBrick+CBXMLHandler.m in Sources */, 4C9E076B1CD9D47E00B14B2F /* CBSceneHelper.swift in Sources */, 4CB0F9ED20A1731700D1BE2F /* PositionXSensor.swift in Sources */, @@ -12680,7 +12686,6 @@ AA74EF521BC0586F00D1E954 /* MoveNStepsBrick+CBXMLHandler.m in Sources */, 9E78D88B22A9B1D400948AC3 /* IterableCache.swift in Sources */, 921D467E1BDF61350086AD20 /* GoNStepsBackBrick+Instruction.swift in Sources */, - AA74EF531BC0586F00D1E954 /* PlaceAtBrick+CBXMLHandler.m in Sources */, BB9EC0E927D62CBA009FF8CE /* FormItem.swift in Sources */, 4C2EE41F1B555B55006DE9B8 /* CBXMLPositionStack.m in Sources */, AAF6D9D41BC0B9EA00686849 /* HideBrick+Instruction.swift in Sources */, @@ -12955,6 +12960,7 @@ 99B2C3701D884D2900736769 /* FlashBrick.m in Sources */, 4CF0728420D6581900F93AB5 /* PhiroFrontLeftSensor.swift in Sources */, 6F4B2FBB246670C800B5F0ED /* ProjectMigratorProtocol.swift in Sources */, + 495A1EC827B0F579009610F5 /* PlaceAtBrick.swift in Sources */, 9218B2001CC4AB75007B4C60 /* YKImageCropperOverlayView.m in Sources */, 4C0F9F2E204ADC2300E71B2D /* CameraBrick.m in Sources */, 92C631891BC502CB00486958 /* ConnectedDevicesTableViewController.swift in Sources */, @@ -13096,7 +13102,6 @@ 92FF2E8D1A24C7D800093DA7 /* CatrobatAudioPlayer.m in Sources */, 92D56C341BF202E700A54750 /* FirmataDevice.swift in Sources */, 2DA8790E212B444E00FE0585 /* SearchStoreDataSource.swift in Sources */, - AA74EFFF1BC05B5F00D1E954 /* GlideToBrick.m in Sources */, AA74F0081BC05B5F00D1E954 /* TurnLeftBrick.m in Sources */, AA74F0C71BC05FCE00D1E954 /* SpeakBrickCell.m in Sources */, AA74F0091BC05B5F00D1E954 /* TurnRightBrick.m in Sources */, @@ -13125,7 +13130,6 @@ D30359E624445ABE006688F5 /* GoToBrick+CBXMLHandler.m in Sources */, 92C6318B1BC502CB00486958 /* SearchDevicesTableViewController.swift in Sources */, BA3337372195BC6D00DA3505 /* RepeatUntilBrick+CBXMLHandler.m in Sources */, - AA74F0031BC05B5F00D1E954 /* PlaceAtBrick.m in Sources */, AA74F0001BC05B5F00D1E954 /* GoNStepsBackBrick.m in Sources */, 92B46F851BC79585004980C1 /* TermsOfUseOptionTableViewController.m in Sources */, 92FF31071A24DCAA00093DA7 /* SpriteObject.m in Sources */, diff --git a/src/Catty/DataModel/Bricks/Brick.h b/src/Catty/DataModel/Bricks/Brick.h index 92dbefeae9..4c8d58950f 100644 --- a/src/Catty/DataModel/Bricks/Brick.h +++ b/src/Catty/DataModel/Bricks/Brick.h @@ -44,6 +44,8 @@ - (BOOL)isFormulaBrick; +- (BOOL)isVisualPlacementBrick; + - (BOOL)isIfLogicBrick; - (BOOL)isLoopBrick; diff --git a/src/Catty/DataModel/Bricks/Brick.m b/src/Catty/DataModel/Bricks/Brick.m index 5bdd47b8bd..3b613e9b4a 100644 --- a/src/Catty/DataModel/Bricks/Brick.m +++ b/src/Catty/DataModel/Bricks/Brick.m @@ -27,6 +27,7 @@ #import "BroadcastScript.h" #import "CBMutableCopyContext.h" #import "Util.h" +#import "Pocket_Code-Swift.h" @implementation Brick @@ -52,6 +53,11 @@ - (BOOL)isFormulaBrick return ([self conformsToProtocol:@protocol(BrickFormulaProtocol)]); } +- (BOOL)isVisualPlacementBrick +{ + return ([self conformsToProtocol:@protocol(BrickVisualPlacementProtocol)]); +} + - (BOOL)isIfLogicBrick { return NO; diff --git a/src/Catty/DataModel/Bricks/Motion/GlideToBrick+CBXMLHandler.swift b/src/Catty/DataModel/Bricks/Motion/GlideToBrick+CBXMLHandler.swift new file mode 100644 index 0000000000..7e7f52ea82 --- /dev/null +++ b/src/Catty/DataModel/Bricks/Motion/GlideToBrick+CBXMLHandler.swift @@ -0,0 +1,60 @@ +/** + * Copyright (C) 2010-2022 The Catrobat Team + * (http://developer.catrobat.org/credits) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * (http://developer.catrobat.org/license_additional_term) + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ + +extension GlideToBrick: CBXMLNodeProtocol { + static func parse(from xmlElement: GDataXMLElement!, with context: CBXMLParserContext!) -> Self! { + CBXMLParserHelper.validate(xmlElement, forNumberOfChildNodes: 1, andFormulaListWithTotalNumberOfFormulas: 3) + + let glideToBrick = self.init() + if let formulaDuration = CBXMLParserHelper.formula(in: xmlElement, forCategoryName: "DURATION_IN_SECONDS", with: context) { + glideToBrick.durationInSeconds = formulaDuration + } + if let formulaXDestination = CBXMLParserHelper.formula(in: xmlElement, forCategoryName: "X_DESTINATION", with: context) { + glideToBrick.xPosition = formulaXDestination + } + if let formulaYDestination = CBXMLParserHelper.formula(in: xmlElement, forCategoryName: "Y_DESTINATION", with: context) { + glideToBrick.yPosition = formulaYDestination + } + + return glideToBrick + } + + func xmlElement(with context: CBXMLSerializerContext!) -> GDataXMLElement! { + let brick = super.xmlElement(for: "GlideToBrick", with: context) + let formulaList = GDataXMLElement(name: "formulaList", context: context) + + var formula = self.durationInSeconds.xmlElement(with: context) + formula?.addAttribute(GDataXMLElement.attribute(withName: "category", escapedStringValue: "DURATION_IN_SECONDS") as? GDataXMLNode) + formulaList?.addChild(formula, context: context) + + formula = self.yPosition.xmlElement(with: context) + formula?.addAttribute(GDataXMLElement.attribute(withName: "category", escapedStringValue: "Y_DESTINATION") as? GDataXMLNode) + formulaList?.addChild(formula, context: context) + + formula = self.xPosition.xmlElement(with: context) + formula?.addAttribute(GDataXMLElement.attribute(withName: "category", escapedStringValue: "X_DESTINATION") as? GDataXMLNode) + formulaList?.addChild(formula, context: context) + + brick?.addChild(formulaList, context: context) + return brick + } +} diff --git a/src/Catty/DataModel/Bricks/Motion/GlideToBrick.h b/src/Catty/DataModel/Bricks/Motion/GlideToBrick.h deleted file mode 100644 index 1c010eeeaf..0000000000 --- a/src/Catty/DataModel/Bricks/Motion/GlideToBrick.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * 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 "Brick.h" -#import "BrickFormulaProtocol.h" - -@class Formula; - -@interface GlideToBrick : Brick - -@property (nonatomic, strong) Formula *durationInSeconds; -@property (nonatomic, strong) Formula *xDestination; -@property (nonatomic, strong) Formula *yDestination; - - -@end diff --git a/src/Catty/DataModel/Bricks/Motion/GlideToBrick.m b/src/Catty/DataModel/Bricks/Motion/GlideToBrick.m deleted file mode 100644 index 164e0d7dae..0000000000 --- a/src/Catty/DataModel/Bricks/Motion/GlideToBrick.m +++ /dev/null @@ -1,104 +0,0 @@ -/** - * 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 "GlideToBrick.h" -#import "Script.h" -#import "CBMutableCopyContext.h" -#import "Pocket_Code-Swift.h" - -@interface GlideToBrick() -@end - -@implementation GlideToBrick - -@synthesize durationInSeconds = _durationInSeconds; -@synthesize xDestination = _xDestination; -@synthesize yDestination = _yDestination; - -- (kBrickCategoryType)category -{ - return kMotionBrick; -} - -- (Formula*)formulaForLineNumber:(NSInteger)lineNumber andParameterNumber:(NSInteger)paramNumber -{ - if(lineNumber == 0 && paramNumber == 0) - return self.durationInSeconds; - else if(lineNumber == 1 && paramNumber == 0) - return self.xDestination; - else if(lineNumber == 1 && paramNumber == 1) - return self.yDestination; - - return nil; -} - -- (void)setFormula:(Formula*)formula forLineNumber:(NSInteger)lineNumber andParameterNumber:(NSInteger)paramNumber -{ - if(lineNumber == 0 && paramNumber == 0) - self.durationInSeconds = formula; - else if(lineNumber == 1 && paramNumber == 0) - self.xDestination = formula; - else if(lineNumber == 1 && paramNumber == 1) - self.yDestination = formula; -} - -- (NSArray*)getFormulas -{ - return @[self.durationInSeconds,self.xDestination,self.yDestination]; -} - -- (BOOL)allowsStringFormula -{ - return NO; -} - -- (void)setDefaultValuesForObject:(SpriteObject*)spriteObject -{ - self.durationInSeconds = [[Formula alloc] initWithInteger:1]; - self.xDestination = [[Formula alloc] initWithInteger:100]; - self.yDestination = [[Formula alloc] initWithInteger:200]; -} - - -#pragma mark - Description -- (NSString*)description -{ - return [NSString stringWithFormat:@"GlideToBrick"]; -} - -- (BOOL)isEqualToBrick:(Brick*)brick -{ - if(![self.durationInSeconds isEqualToFormula:((GlideToBrick*)brick).durationInSeconds]) - return NO; - if(![self.xDestination isEqualToFormula:((GlideToBrick*)brick).xDestination]) - return NO; - if(![self.yDestination isEqualToFormula:((GlideToBrick*)brick).yDestination]) - return NO; - return YES; -} - -#pragma mark - Resources -- (NSInteger)getRequiredResources -{ - return [self.durationInSeconds getRequiredResources]|[self.xDestination getRequiredResources]|[self.yDestination getRequiredResources]; -} -@end diff --git a/src/Catty/DataModel/Bricks/Motion/GlideToBrick.swift b/src/Catty/DataModel/Bricks/Motion/GlideToBrick.swift new file mode 100644 index 0000000000..98b1a76ea4 --- /dev/null +++ b/src/Catty/DataModel/Bricks/Motion/GlideToBrick.swift @@ -0,0 +1,102 @@ +/** + * 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(GlideToBrick) +@objcMembers class GlideToBrick: Brick, BrickVisualPlacementProtocol { + var durationInSeconds: Formula + var xPosition: Formula + var yPosition: Formula + + override required init() { + self.durationInSeconds = Formula(integer: 1) + self.xPosition = Formula(integer: 100) + self.yPosition = Formula(integer: 200) + super.init() + } + + func category() -> kBrickCategoryType { + kBrickCategoryType.motionBrick + } + + func formula(forLineNumber lineNumber: Int, andParameterNumber paramNumber: Int) -> Formula? { + if lineNumber == 0 && paramNumber == 0 { + return self.durationInSeconds + } else if lineNumber == 1 && paramNumber == 0 { + return self.xPosition + } else if lineNumber == 1 && paramNumber == 1 { + return self.yPosition + } + + return nil + } + + func setFormula(_ formula: Formula, forLineNumber lineNumber: Int, andParameterNumber paramNumber: Int) { + if lineNumber == 0 && paramNumber == 0 { + self.durationInSeconds = formula + } else if lineNumber == 1 && paramNumber == 0 { + self.xPosition = formula + } else if lineNumber == 1 && paramNumber == 1 { + self.yPosition = formula + } + } + + func getFormulas() -> [Formula] { + [self.durationInSeconds, self.xPosition, self.yPosition] + } + + func allowsStringFormula() -> Bool { + false + } + + override func setDefaultValuesFor(_ spriteObject: SpriteObject!) { + self.durationInSeconds = Formula(integer: 1) + self.xPosition = Formula(integer: 100) + self.yPosition = Formula(integer: 200) + } + + override func description() -> String! { + "GlideToBrick" + } + + override func isEqual(to brick: Brick!) -> Bool { + if brick is GlideToBrick { + let glideToBrick = brick as! GlideToBrick + return self.durationInSeconds.isEqual(to: glideToBrick.durationInSeconds) && + self.xPosition.isEqual(to: glideToBrick.xPosition) && + self.yPosition.isEqual(to: glideToBrick.yPosition) + } + return false + } + + func isVisualPlacementFormula(_ formula: Formula) -> Bool { + (formula.isEqual(to: xPosition) || formula.isEqual(to: yPosition)) && + doVisualPlacementBrickCellsContainOnlyValues() + } + + func doVisualPlacementBrickCellsContainOnlyValues() -> Bool { + xPosition.formulaTree.isSingleNumberFormula() && yPosition.formulaTree.isSingleNumberFormula() + } + + override func getRequiredResources() -> Int { + durationInSeconds.getRequiredResources() | xPosition.getRequiredResources() | yPosition.getRequiredResources() + } +} diff --git a/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick+CBXMLHandler.swift b/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick+CBXMLHandler.swift new file mode 100644 index 0000000000..f2631b8140 --- /dev/null +++ b/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick+CBXMLHandler.swift @@ -0,0 +1,54 @@ +/** + * 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 PlaceAtBrick: CBXMLNodeProtocol { + static func parse(from xmlElement: GDataXMLElement!, with context: CBXMLParserContext!) -> Self! { + + CBXMLParserHelper.validate(xmlElement, forNumberOfChildNodes: 1, andFormulaListWithTotalNumberOfFormulas: 2) + + let placeAtBrick = self.init() + if let formulaXPosition = CBXMLParserHelper.formula(in: xmlElement, forCategoryName: "X_POSITION", with: context) { + placeAtBrick.xPosition = formulaXPosition + } + if let formulaYPostion = CBXMLParserHelper.formula(in: xmlElement, forCategoryName: "Y_POSITION", with: context) { + placeAtBrick.yPosition = formulaYPostion + } + return placeAtBrick + } + + func xmlElement(with context: CBXMLSerializerContext) -> GDataXMLElement? { + let brick = super.xmlElement(for: "PlaceAtBrick", with: context) + let formulaList = GDataXMLElement(name: "formulaList", context: context) + + var formula = self.yPosition.xmlElement(with: context) + formula?.addAttribute(GDataXMLElement.attribute(withName: "category", escapedStringValue: "Y_POSITION") as? GDataXMLNode) + formulaList?.addChild(formula, context: context) + + formula = self.xPosition.xmlElement(with: context) + formula?.addAttribute(GDataXMLElement.attribute(withName: "category", escapedStringValue: "X_POSITION") as? GDataXMLNode) + formulaList?.addChild(formula, context: context) + + brick?.addChild(formulaList, context: context) + return brick + } + +} diff --git a/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick.h b/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick.h deleted file mode 100644 index 42e6b0edae..0000000000 --- a/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * 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 "Brick.h" -#import "BrickFormulaProtocol.h" - -@class Formula; - -@interface PlaceAtBrick : Brick - -@property (nonatomic, strong) Formula *xPosition; -@property (nonatomic, strong) Formula *yPosition; - -@end diff --git a/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick.m b/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick.m deleted file mode 100644 index acb611025a..0000000000 --- a/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick.m +++ /dev/null @@ -1,79 +0,0 @@ -/** - * 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 "PlaceAtBrick.h" -#import "Script.h" - -@implementation PlaceAtBrick - -- (Formula*)formulaForLineNumber:(NSInteger)lineNumber andParameterNumber:(NSInteger)paramNumber -{ - if(paramNumber == 0) - return self.xPosition; - else if(paramNumber == 1) - return self.yPosition; - - return nil; -} - -- (void)setFormula:(Formula*)formula forLineNumber:(NSInteger)lineNumber andParameterNumber:(NSInteger)paramNumber -{ - if(paramNumber == 0) - self.xPosition = formula; - else if(paramNumber == 1) - self.yPosition = formula; -} - -- (NSArray*)getFormulas -{ - return @[self.xPosition,self.yPosition]; -} - -- (BOOL)allowsStringFormula -{ - return NO; -} - -- (void)setDefaultValuesForObject:(SpriteObject*)spriteObject -{ - self.xPosition = [[Formula alloc] initWithInteger:100]; - self.yPosition = [[Formula alloc] initWithInteger:200]; -} - -- (kBrickCategoryType)category -{ - return kMotionBrick; -} - -#pragma mark - Description -- (NSString*)description -{ - return [NSString stringWithFormat:@"PlaceAtBrick"]; -} - -#pragma mark - Resources -- (NSInteger)getRequiredResources -{ - return [self.xPosition getRequiredResources]|[self.yPosition getRequiredResources]; -} - -@end diff --git a/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick.swift b/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick.swift new file mode 100644 index 0000000000..50bf7d853c --- /dev/null +++ b/src/Catty/DataModel/Bricks/Motion/PlaceAtBrick.swift @@ -0,0 +1,83 @@ +/** + * 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(PlaceAtBrick) +@objcMembers class PlaceAtBrick: Brick, BrickVisualPlacementProtocol { + var xPosition: Formula + var yPosition: Formula + + override required init () { + self.xPosition = Formula(integer: 100) + self.yPosition = Formula(integer: 200) + super.init() + } + + func formula(forLineNumber lineNumber: Int, andParameterNumber paramNumber: Int) -> Formula? { + if paramNumber == 0 { + return self.xPosition + } else if paramNumber == 1 { + return self.yPosition + } + return nil + } + + func setFormula(_ formula: Formula, forLineNumber lineNumber: Int, andParameterNumber paramNumber: Int) { + if paramNumber == 0 { + self.xPosition = formula + } else if paramNumber == 1 { + self.yPosition = formula + } + } + + func getFormulas() -> [Formula]! { + [self.xPosition, self.yPosition] + } + + func allowsStringFormula() -> Bool { + false + } + + override func setDefaultValuesFor(_ spriteObject: SpriteObject) { + self.xPosition = Formula(integer: 100) + self.yPosition = Formula(integer: 200) + } + + func category() -> kBrickCategoryType { + kBrickCategoryType.motionBrick + } + + override class func description() -> String { + "PlaceAtBrick" + } + + func isVisualPlacementFormula(_ formula: Formula) -> Bool { + doVisualPlacementBrickCellsContainOnlyValues() + } + + func doVisualPlacementBrickCellsContainOnlyValues() -> Bool { + xPosition.formulaTree.isSingleNumberFormula() && yPosition.formulaTree.isSingleNumberFormula() + } + + override func getRequiredResources() -> Int { + xPosition.getRequiredResources() | yPosition.getRequiredResources() + } +} diff --git a/src/Catty/DataModel/Formula/FormulaElement.h b/src/Catty/DataModel/Formula/FormulaElement.h index ffbd94623e..a031d96be0 100644 --- a/src/Catty/DataModel/Formula/FormulaElement.h +++ b/src/Catty/DataModel/Formula/FormulaElement.h @@ -128,6 +128,8 @@ additionalChildren:(NSArray*)additionalChildren - (BOOL)isSingleNumberFormula; +- (double)getSingleNumberFormulaValue; + - (NSInteger)getRequiredResources; @end diff --git a/src/Catty/DataModel/Formula/FormulaElement.m b/src/Catty/DataModel/Formula/FormulaElement.m index 9645b21164..42670645b0 100644 --- a/src/Catty/DataModel/Formula/FormulaElement.m +++ b/src/Catty/DataModel/Formula/FormulaElement.m @@ -321,6 +321,18 @@ - (BOOL)isSingleNumberFormula return false; } +- (double)getSingleNumberFormulaValue +{ + if (self.type == OPERATOR) { + if (self.value == MinusOperator.tag && self.leftChild == nil) { + return -[self.rightChild getSingleNumberFormulaValue]; + } + } else if(self.type == NUMBER) { + return [self.value doubleValue]; + } + return 0.0; +} + #pragma mark - Copy - (id)mutableCopyWithContext:(CBMutableCopyContext*)context { diff --git a/src/Catty/DataModel/SpriteObject/SpriteObject.m b/src/Catty/DataModel/SpriteObject/SpriteObject.m index 4cb0f01dd6..3efcdb63de 100644 --- a/src/Catty/DataModel/SpriteObject/SpriteObject.m +++ b/src/Catty/DataModel/SpriteObject/SpriteObject.m @@ -101,11 +101,15 @@ - (NSString*)projectPath - (NSString*)previewImagePath { - Look* look = [self.lookList objectAtIndex:0]; - if (! look) - return nil; - - return [look pathForScene:self.scene]; + if ([self numberOfLooks] > 0) + { + Look* look = [self.lookList objectAtIndex:0]; + if (! look) + return nil; + + return [look pathForScene:self.scene]; + } + return nil; } - (BOOL)isBackground diff --git a/src/Catty/Defines/LanguageTranslationDefines.h b/src/Catty/Defines/LanguageTranslationDefines.h index 690e00ac46..1c0dbcc3d3 100644 --- a/src/Catty/Defines/LanguageTranslationDefines.h +++ b/src/Catty/Defines/LanguageTranslationDefines.h @@ -167,6 +167,7 @@ #define kLocalizedDisableCondition NSLocalizedString(@"Disable condition", nil) #define kLocalizedEnableCondition NSLocalizedString(@"Enable condition", nil) #define kLocalizedEditFormula NSLocalizedString(@"Edit formula", nil) +#define kLocalizedPlaceVisually NSLocalizedString(@"Place visually", nil) #define kLocalizedMoveBrick NSLocalizedString(@"Move brick", nil) #define kLocalizedDeleteSounds NSLocalizedString(@"Delete sounds", nil) #define kLocalizedMoveSounds NSLocalizedString(@"Move sounds",nil) diff --git a/src/Catty/Defines/LanguageTranslationDefinesSwift.swift b/src/Catty/Defines/LanguageTranslationDefinesSwift.swift index 6c69231768..fa79b5b408 100644 --- a/src/Catty/Defines/LanguageTranslationDefinesSwift.swift +++ b/src/Catty/Defines/LanguageTranslationDefinesSwift.swift @@ -167,6 +167,7 @@ let kLocalizedEnableLoop = NSLocalizedString("Enable loop", comment: "") let kLocalizedDisableCondition = NSLocalizedString("Disable condition", comment: "") let kLocalizedEnableCondition = NSLocalizedString("Enable condition", comment: "") let kLocalizedEditFormula = NSLocalizedString("Edit formula", comment: "") +let kLocalizedPlaceVisually = NSLocalizedString("Place visually", comment: "") let kLocalizedMoveBrick = NSLocalizedString("Move brick", comment: "") let kLocalizedDeleteSounds = NSLocalizedString("Delete sounds", comment: "") let kLocalizedMoveSounds = NSLocalizedString("Move sounds", comment: "") diff --git a/src/Catty/Defines/ProjectDefines.h b/src/Catty/Defines/ProjectDefines.h index 095b754335..4f8e2c8b6f 100644 --- a/src/Catty/Defines/ProjectDefines.h +++ b/src/Catty/Defines/ProjectDefines.h @@ -114,6 +114,7 @@ typedef NS_ENUM(NSInteger, ResourceType) { #define kScreenshotFilename @"screenshot.png" #define kScreenshotManualFilename @"manual_screenshot.png" #define kScreenshotAutoFilename @"automatic_screenshot.png" +#define kScreenshotAutoFullScreenFilename @"automatic_full_screen_screenshot.png" #define kUserDefaultsBrickSelectionStatisticsMap @"BrickSelectionStatisticsMap" diff --git a/src/Catty/XML/XMLHandler/Bricks/Motion/GlideToBrick+CBXMLHandler.h b/src/Catty/Extension&Delegate&Protocol/Protocols/Bricks/BrickData/BrickVisualPlacementProtocol.swift similarity index 76% rename from src/Catty/XML/XMLHandler/Bricks/Motion/GlideToBrick+CBXMLHandler.h rename to src/Catty/Extension&Delegate&Protocol/Protocols/Bricks/BrickData/BrickVisualPlacementProtocol.swift index d6e2bd226e..2da6ccaa5a 100644 --- a/src/Catty/XML/XMLHandler/Bricks/Motion/GlideToBrick+CBXMLHandler.h +++ b/src/Catty/Extension&Delegate&Protocol/Protocols/Bricks/BrickData/BrickVisualPlacementProtocol.swift @@ -20,11 +20,12 @@ * along with this program. If not, see http://www.gnu.org/licenses/. */ -#import "GlideToBrick.h" -#import "CBXMLNodeProtocol.h" +import Foundation -@class CBXMLContext; +@objc protocol BrickVisualPlacementProtocol: BrickFormulaProtocol { + var xPosition: Formula { get set } + var yPosition: Formula { get set } -@interface GlideToBrick (CBXMLHandler) - -@end + func isVisualPlacementFormula(_ formula: Formula) -> Bool + func doVisualPlacementBrickCellsContainOnlyValues() -> Bool +} diff --git a/src/Catty/FormulaEditor/ViewController/FormulaEditorViewController.m b/src/Catty/FormulaEditor/ViewController/FormulaEditorViewController.m index 4e8a5f190f..ec8aa75ffe 100644 --- a/src/Catty/FormulaEditor/ViewController/FormulaEditorViewController.m +++ b/src/Catty/FormulaEditor/ViewController/FormulaEditorViewController.m @@ -43,7 +43,7 @@ kButtonIndexCancel = 4 }; -@interface FormulaEditorViewController () +@interface FormulaEditorViewController () @property (weak, nonatomic) Formula *formula; @@ -139,6 +139,58 @@ - (void)openFormulaEditor:(BrickCellFormulaData*)formulaData withEvent:(UIEvent* [self.brickCell setNeedsDisplay]; } +- (void)openFormulaAndVisualPlacementActionSheet:(BrickCellFormulaData *)formulaData withEvent:(UIEvent *)event +{ + [self openFormulaEditor:formulaData withEvent:event]; + + Brick* brick = formulaData.brickCell.scriptOrBrick; + Brick *visualPlacementBrick; + + if ([brick isVisualPlacementBrick]) { + visualPlacementBrick = (Brick *) brick; + if (!([visualPlacementBrick isVisualPlacementFormula:formulaData.formula])) { + return; + } + + [[[[[[AlertControllerBuilder actionSheetWithTitle:nil] + addCancelActionWithTitle:kLocalizedCancel handler:nil] + addDefaultActionWithTitle:kLocalizedEditFormula handler:^{ + [self openFormulaEditor:formulaData withEvent:event]; + }] + addDefaultActionWithTitle:kLocalizedPlaceVisually handler:^{ + [self openVisualPlacementEditor:visualPlacementBrick]; + }] + build] + showWithController:[Util topmostViewController]]; + } +} + +-(void)openVisualPlacementEditor:(Brick *)visualPlacementBrick +{ + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"iPhone" bundle: nil]; + VisualPlacementViewController *visualPlacementViewController = [storyboard instantiateViewControllerWithIdentifier:@"VisualPlacementViewController"]; + [visualPlacementViewController initWithBrick:visualPlacementBrick andObject:self.object]; + visualPlacementViewController.delegate = self; + + visualPlacementViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:visualPlacementViewController animated:YES completion:NULL]; +} + +- (void)doneVisualPlacement +{ + Brick *brick = (Brick *) self.brickCell.scriptOrBrick; + + self.internFormula = [[brick formulaForLineNumber:self.brickCellData.lineNumber andParameterNumber:self.brickCellData.parameterNumber] getInternFormula]; + + [self changeBrickCellFormulaData:self.brickCellData]; + [self update]; + [self showFormulaEditorTextView]; +} + +- (void)cancelVisualPlacement { + [self showFormulaEditorTextView]; +} + - (BOOL)changeBrickCellFormulaData:(BrickCellFormulaData *)brickCellData { InternFormulaParser *internFormulaParser = [[InternFormulaParser alloc] initWithTokens:[self.internFormula getInternTokenList] andFormulaManager:self.formulaManager]; diff --git a/src/Catty/FormulaEditor/ViewController/VisualPlacementViewController.swift b/src/Catty/FormulaEditor/ViewController/VisualPlacementViewController.swift new file mode 100644 index 0000000000..ea51138a95 --- /dev/null +++ b/src/Catty/FormulaEditor/ViewController/VisualPlacementViewController.swift @@ -0,0 +1,188 @@ +/** + * 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 +import UIKit + +@objc protocol VisualPlacementViewControllerDelegate { + func doneVisualPlacement() + func cancelVisualPlacement() +} + +@objcMembers class VisualPlacementViewController: UIViewController { + @IBOutlet private weak var objectImageView: UIImageView! + @IBOutlet private weak var oldPositionObjectImageView: UIImageView! + @IBOutlet private weak var backgroundImageView: UIImageView! + @IBOutlet private weak var cancelButton: UIButton! + @IBOutlet private weak var doneButton: UIButton! + @IBOutlet private weak var titleLabel: UILabel! + + weak var delegate: VisualPlacementViewControllerDelegate? + static var lookScalingDictionary = [String: Double] () + var objectImage: UIImage? + var backgroundImage: UIImage? + var isDragging = false + var imageWidth = 100.0 + var imageHeight = 100.0 + var scaleFactor = 1.0 + var oldPositionInView = CGPoint(x: 0.0, y: 0.0) + var centerPositionInView = CGPoint(x: 0.0, y: 0.0) + var centerPositionInStage = CGPoint(x: 0.0, y: 0.0) + var stageSize = CGSize(width: 0.0, height: 0.0) + var brick: BrickVisualPlacementProtocol! + var object: SpriteObject! + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + guard let navigationController = navigationController else { return } + navigationController.setNavigationBarHidden(true, animated: animated) + navigationController.setToolbarHidden(true, animated: animated) + + } + + override func viewDidLoad() { + super.viewDidLoad() + + self.edgesForExtendedLayout = [UIRectEdge.top, UIRectEdge.left, UIRectEdge.right, UIRectEdge.bottom] + self.extendedLayoutIncludesOpaqueBars = true + + backgroundImageView.alpha = 0.5 + oldPositionObjectImageView.alpha = 0.5 + + if let backgroundImage = backgroundImage { + backgroundImageView.image = backgroundImage + } + self.setupObjectImageView(self.objectImageView) + self.setupObjectImageView(self.oldPositionObjectImageView) + self.setupNavigationBar() + + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + guard let navigationController = navigationController else { return } + navigationController.setNavigationBarHidden(false, animated: animated) + navigationController.setToolbarHidden(false, animated: animated) + } + + func initWith(brick: BrickVisualPlacementProtocol, andObject object: SpriteObject) { + + let screenshotFileName = object.projectPath() + kScreenshotAutoFullScreenFilename + self.backgroundImage = UIImage.init(contentsOfFile: screenshotFileName) + if self.backgroundImage == nil, + let backgroundObject = object.scene.objects().first, + let backgroundImagePath = backgroundObject.previewImagePath() { + self.backgroundImage = UIImage.init(contentsOfFile: backgroundImagePath) + } + + self.brick = brick + self.centerPositionInStage.x = brick.xPosition.formulaTree.getSingleNumberFormulaValue() + self.centerPositionInStage.y = brick.yPosition.formulaTree.getSingleNumberFormulaValue() + self.object = object + + stageSize = CGSize(width: object.scene.project?.header.screenWidth.doubleValue ?? 0, height: object.scene.project?.header.screenHeight.doubleValue ?? 0) + centerPositionInView = CBSceneHelper.convertPointToTouchCoordinate(point: centerPositionInStage, stageSize: stageSize) + + let screenSize = Util.screenSize(false) + scaleFactor = (screenSize.width / stageSize.width) + + if let objectImagePath = object.previewImagePath() { + self.objectImage = UIImage.init(contentsOfFile: objectImagePath) + } + } + + func setupNavigationBar() { + cancelButton.setTitle(kLocalizedCancel, for: .normal) + doneButton.setTitle(kLocalizedDone, for: .normal) + titleLabel.text = kLocalizedPlaceVisually + } + + func setupObjectImageView(_ imageView: UIImageView) { + if let objectImage = objectImage { + var catrobatScaling = 1.0 + if let scaling = VisualPlacementViewController.lookScalingDictionary[object.name] { + catrobatScaling = scaling + } + catrobatScaling = catrobatScaling == 0 ? 1.0 : catrobatScaling + imageWidth = objectImage.size.width * self.scaleFactor * catrobatScaling + imageHeight = objectImage.size.height * self.scaleFactor * catrobatScaling + imageView.image = objectImage + } + imageView.frame.size.width = imageWidth + imageView.frame.size.height = imageHeight + imageView.frame.origin.x = centerPositionInView.x - imageWidth / 2 + imageView.frame.origin.y = centerPositionInView.y - imageHeight / 2 + } + + @IBAction private func cancelTapped(_ sender: Any) { + dismiss(animated: true) { + if let delegate = self.delegate { + delegate.cancelVisualPlacement() + } + } + } + + @IBAction private func doneTapped(_ sender: Any) { + let newPositionInStage = CBSceneHelper.convertTouchCoordinateToPoint(coordinate: self.centerPositionInView, stageSize: self.stageSize) + brick.xPosition = Formula(integer: Int32(newPositionInStage.x)) + brick.yPosition = Formula(integer: Int32(newPositionInStage.y)) + guard let project = object.scene.project else { return } + project.saveToDisk(withNotification: true) { + DispatchQueue.main.async { + self.dismiss(animated: true) { + if let delegate = self.delegate { + delegate.doneVisualPlacement() + } + + } + } + } + } +} + +extension VisualPlacementViewController { + + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + guard let touch = touches.first else { + return + } + let touchLocation = touch.location(in: objectImageView) + if objectImageView!.bounds.contains(touchLocation) { + isDragging = true + oldPositionInView = touchLocation + } + } + override func touchesMoved(_ touches: Set, with event: UIEvent?) { + guard isDragging, let touch = touches.first else { + return + } + + let touchLocation = touch.location(in: view) + objectImageView!.frame.origin.x = touchLocation.x - oldPositionInView.x + objectImageView!.frame.origin.y = touchLocation.y - oldPositionInView.y + centerPositionInView.x = objectImageView!.frame.origin.x + imageWidth / 2 + centerPositionInView.y = objectImageView!.frame.origin.y + imageHeight / 2 + } + override func touchesEnded(_ touches: Set, with event: UIEvent?) { + isDragging = false + } +} diff --git a/src/Catty/PlayerEngine/Helper/CBSceneHelper.swift b/src/Catty/PlayerEngine/Helper/CBSceneHelper.swift index 858ca2fee5..236cbb1ec3 100644 --- a/src/Catty/PlayerEngine/Helper/CBSceneHelper.swift +++ b/src/Catty/PlayerEngine/Helper/CBSceneHelper.swift @@ -25,10 +25,17 @@ // MARK: - Operations (Helpers) @objc class func convertTouchCoordinateToPoint(coordinate: CGPoint, stageSize: CGSize) -> CGPoint { let screenSize = Util.screenSize(false) - var x = (coordinate.x - screenSize.width / 2.0) - x = x * (stageSize.width / screenSize.width) - var y = (screenSize.height / 2.0 - coordinate.y) - y = y * (stageSize.height / screenSize.height) + let scaling = stageSize.width / screenSize.width + let x = (coordinate.x - screenSize.width / 2.0) * scaling + let y = (screenSize.height / 2.0 - coordinate.y) * scaling + return CGPoint(x: x, y: y) + } + + @objc class func convertPointToTouchCoordinate(point: CGPoint, stageSize: CGSize) -> CGPoint { + let screenSize = Util.screenSize(false) + let scaling = screenSize.width / stageSize.width + let x = point.x * scaling + screenSize.width / 2.0 + let y = screenSize.height / 2.0 - point.y * scaling return CGPoint(x: x, y: y) } } diff --git a/src/Catty/PlayerEngine/Instructions/Look/SetSizeToBrick+Instruction.swift b/src/Catty/PlayerEngine/Instructions/Look/SetSizeToBrick+Instruction.swift index 8a218acdb7..7a54555717 100644 --- a/src/Catty/PlayerEngine/Instructions/Look/SetSizeToBrick+Instruction.swift +++ b/src/Catty/PlayerEngine/Instructions/Look/SetSizeToBrick+Instruction.swift @@ -34,6 +34,11 @@ return { let sizeInPercent = formulaInterpreter.interpretDouble(self.size, for: object) spriteNode.catrobatSize = sizeInPercent + if let currentLook = spriteNode.currentLook, let firstLook = object.lookList.firstObject { + if currentLook.isEqual(firstLook) { + VisualPlacementViewController.lookScalingDictionary[object.name] = sizeInPercent / 100 + } + } } } } diff --git a/src/Catty/PlayerEngine/Instructions/Motion/GlideToBrick+Instruction.swift b/src/Catty/PlayerEngine/Instructions/Motion/GlideToBrick+Instruction.swift index bfa674c3b7..8b52871283 100644 --- a/src/Catty/PlayerEngine/Instructions/Motion/GlideToBrick+Instruction.swift +++ b/src/Catty/PlayerEngine/Instructions/Motion/GlideToBrick+Instruction.swift @@ -20,12 +20,10 @@ * along with this program. If not, see http://www.gnu.org/licenses/. */ -@objc extension GlideToBrick: CBInstructionProtocol { +extension GlideToBrick: CBInstructionProtocol { @nonobjc func instruction() -> CBInstruction { - guard let durationFormula = self.durationInSeconds else { fatalError("This should never happen!") } - - return .longDurationAction(duration: CBDuration.varTime(formula: durationFormula), closure: { duration, context -> SKAction in + CBInstruction.longDurationAction(duration: CBDuration.varTime(formula: self.durationInSeconds), closure: { duration, context -> SKAction in self.action(duration, context.formulaInterpreter) }) } @@ -35,8 +33,8 @@ let spriteNode = object.spriteNode else { fatalError("This should never happen!") } - let xDestination = formulaInterpreter.interpretFloat(self.xDestination, for: object) - let yDestination = formulaInterpreter.interpretFloat(self.yDestination, for: object) + let xDestination = formulaInterpreter.interpretFloat(self.xPosition, for: object) + let yDestination = formulaInterpreter.interpretFloat(self.yPosition, for: object) let duration = formulaInterpreter.interpretDouble(self.durationInSeconds, for: object) guard let scene = spriteNode.scene else { diff --git a/src/Catty/PlayerEngine/Instructions/Motion/PlaceAtBrick+Instruction.swift b/src/Catty/PlayerEngine/Instructions/Motion/PlaceAtBrick+Instruction.swift index ef8f01d50e..4bf8d298e3 100644 --- a/src/Catty/PlayerEngine/Instructions/Motion/PlaceAtBrick+Instruction.swift +++ b/src/Catty/PlayerEngine/Instructions/Motion/PlaceAtBrick+Instruction.swift @@ -20,7 +20,7 @@ * along with this program. If not, see http://www.gnu.org/licenses/. */ -@objc extension PlaceAtBrick: CBInstructionProtocol { +extension PlaceAtBrick: CBInstructionProtocol { @nonobjc func instruction() -> CBInstruction { .action { context in SKAction.run(self.actionBlock(context.formulaInterpreter)) } diff --git a/src/Catty/Resources/Localization/en.lproj/Localizable.strings b/src/Catty/Resources/Localization/en.lproj/Localizable.strings index 4034666ad9..168a7ff20f 100644 --- a/src/Catty/Resources/Localization/en.lproj/Localizable.strings +++ b/src/Catty/Resources/Localization/en.lproj/Localizable.strings @@ -1357,6 +1357,9 @@ /* No comment provided by engineer. */ "Place at " = "Place at "; +/* No comment provided by engineer. */ +"Place visually" = "Place visually"; + /* No comment provided by engineer. */ "Play" = "Play"; diff --git a/src/Catty/Storyboard+XIB/iPhone.storyboard b/src/Catty/Storyboard+XIB/iPhone.storyboard index 83ae7497f3..ef4d5e68f8 100644 --- a/src/Catty/Storyboard+XIB/iPhone.storyboard +++ b/src/Catty/Storyboard+XIB/iPhone.storyboard @@ -13,25 +13,25 @@ - + - + - + - + @@ -52,44 +52,44 @@ - + - + - +