diff --git a/iOS/.swiftlint.yml b/iOS/.swiftlint.yml new file mode 100644 index 0000000..48d625a --- /dev/null +++ b/iOS/.swiftlint.yml @@ -0,0 +1,3 @@ +line_length: 120 + + diff --git a/iOS/libraries/WWRobotAPI.framework/Versions/A/Headers/WWConstants.h b/iOS/libraries/WWRobotAPI.framework/Versions/A/Headers/WWConstants.h index 1f27547..3c56e40 100644 --- a/iOS/libraries/WWRobotAPI.framework/Versions/A/Headers/WWConstants.h +++ b/iOS/libraries/WWRobotAPI.framework/Versions/A/Headers/WWConstants.h @@ -28,9 +28,11 @@ #define WW_LAUNCHER_POWER_MIN 0.0 #define WW_LAUNCHER_POWER_MAX 1.0 -typedef unsigned int WWLauncherReloadDirection; -#define WW_LAUNCHER_RELOAD_LEFT 1 -#define WW_LAUNCHER_RELOAD_RIGHT 2 + +typedef NS_ENUM(NSUInteger, WWLauncherReloadDirection) { + WW_LAUNCHER_RELOAD_LEFT = 1, + WW_LAUNCHER_RELOAD_RIGHT = 2 +}; // on-robot file syntax definitions #define WW_ON_ROBOT_DIR_LENGTH 4 @@ -41,81 +43,85 @@ typedef unsigned int WWLauncherReloadDirection; // defines for componentIds (used for CommandSet and SensorSet) -typedef unsigned int WWComponentId; -#define WW_COMMAND_POWER 1 -#define WW_COMMAND_EYE_RING 100 -#define WW_COMMAND_LIGHT_RGB_EYE 101 -#define WW_COMMAND_LIGHT_RGB_LEFT_EAR 102 -#define WW_COMMAND_LIGHT_RGB_RIGHT_EAR 103 -#define WW_COMMAND_LIGHT_RGB_CHEST 104 -#define WW_COMMAND_LIGHT_MONO_TAIL 105 -#define WW_COMMAND_LIGHT_MONO_BUTTON_MAIN 106 -#define WW_COMMAND_HEAD_POSITION_TILT 202 -#define WW_COMMAND_HEAD_POSITION_PAN 203 -#define WW_COMMAND_BODY_LINEAR_ANGULAR 204 -#define WW_COMMAND_BODY_POSE 205 -#define WW_COMMAND_MOTOR_HEAD_BANG 210 -#define WW_COMMAND_BODY_WHEELS 211 -#define WW_COMMAND_BODY_COAST 212 -#define WW_COMMAND_SPEAKER 300 -#define WW_COMMAND_ON_ROBOT_ANIM 301 -#define WW_COMMAND_LAUNCHER_FLING 400 -#define WW_COMMAND_LAUNCHER_RELOAD 401 -#define WW_SENSOR_BUTTON_MAIN 1000 -#define WW_SENSOR_BUTTON_1 1001 -#define WW_SENSOR_BUTTON_2 1002 -#define WW_SENSOR_BUTTON_3 1003 -#define WW_SENSOR_HEAD_POSITION_PAN 2000 -#define WW_SENSOR_HEAD_POSITION_TILT 2001 -#define WW_SENSOR_BODY_POSE 2002 -#define WW_SENSOR_ACCELEROMETER 2003 -#define WW_SENSOR_GYROSCOPE 2004 -#define WW_SENSOR_DISTANCE_FRONT_LEFT_FACING 3000 -#define WW_SENSOR_DISTANCE_FRONT_RIGHT_FACING 3001 -#define WW_SENSOR_DISTANCE_BACK 3002 -#define WW_SENSOR_ENCODER_LEFT_WHEEL 3003 -#define WW_SENSOR_ENCODER_RIGHT_WHEEL 3004 -#define WW_SENSOR_MICROPHONE 3005 - - -typedef unsigned int WWRobotType; -#define WW_ROBOT_UNKNOWN 1000 -#define WW_ROBOT_DASH 1001 -#define WW_ROBOT_DOT 1002 - -typedef unsigned int WWPersonalityColorIndex; -#define WW_PERSONALITY_COLOR_NONE 0 // aka white -#define WW_PERSONALITY_COLOR_YELLOW 1 // do not renumber these! -#define WW_PERSONALITY_COLOR_GREEN 2 -#define WW_PERSONALITY_COLOR_ORANGE 3 -#define WW_PERSONALITY_COLOR_BLUE 4 -#define WW_PERSONALITY_COLOR_RED 5 -#define WW_PERSONALITY_COLOR_PURPLE 6 -#define WW_PERSONALITY_COLOR_INVALID 255 - -typedef unsigned int WWRobotColorIndex; // same as WWPersonalityColorIndex with additional values. -#define WW_ROBOT_COLOR_WHITE WW_PERSONALITY_COLOR_NONE -#define WW_ROBOT_COLOR_YELLOW WW_PERSONALITY_COLOR_YELLOW -#define WW_ROBOT_COLOR_GREEN WW_PERSONALITY_COLOR_GREEN -#define WW_ROBOT_COLOR_ORANGE WW_PERSONALITY_COLOR_ORANGE -#define WW_ROBOT_COLOR_BLUE WW_PERSONALITY_COLOR_BLUE -#define WW_ROBOT_COLOR_RED WW_PERSONALITY_COLOR_RED -#define WW_ROBOT_COLOR_PURPLE WW_PERSONALITY_COLOR_PURPLE -#define WW_ROBOT_COLOR_BLUE2 (WW_PERSONALITY_COLOR_PURPLE + 1) -#define WW_ROBOT_COLOR_OFF (WW_PERSONALITY_COLOR_PURPLE + 2) -#define WW_ROBOT_COLOR_INVALID WW_PERSONALITY_COLOR_INVALID - - -typedef unsigned int WWPersonalityAnimationIndex; -#define WW_PERSONALITY_ANIMATION_NONE 0 -#define WW_PERSONALITY_ANIMATION_1 1 -#define WW_PERSONALITY_ANIMATION_2 2 -#define WW_PERSONALITY_ANIMATION_3 3 -#define WW_PERSONALITY_ANIMATION_INVALID 255 - -typedef unsigned int WWBeaconDataType; -#define WW_BEACON_DATA_TYPE_COLOR 0 -#define WW_BEACON_DATA_TYPE_USER 1 +typedef NS_ENUM(unsigned int, WWComponentId) { + WW_COMMAND_POWER = 1, + WW_COMMAND_EYE_RING = 100, + WW_COMMAND_LIGHT_RGB_EYE = 101, + WW_COMMAND_LIGHT_RGB_LEFT_EAR = 102, + WW_COMMAND_LIGHT_RGB_RIGHT_EAR = 103, + WW_COMMAND_LIGHT_RGB_CHEST = 104, + WW_COMMAND_LIGHT_MONO_TAIL = 105, + WW_COMMAND_LIGHT_MONO_BUTTON_MAIN = 106, + WW_COMMAND_HEAD_POSITION_TILT = 202, + WW_COMMAND_HEAD_POSITION_PAN = 203, + WW_COMMAND_BODY_LINEAR_ANGULAR = 204, + WW_COMMAND_BODY_POSE = 205, + WW_COMMAND_MOTOR_HEAD_BANG = 210, + WW_COMMAND_BODY_WHEELS = 211, + WW_COMMAND_BODY_COAST = 212, + WW_COMMAND_SPEAKER = 300, + WW_COMMAND_ON_ROBOT_ANIM = 301, + WW_COMMAND_LAUNCHER_FLING = 400, + WW_COMMAND_LAUNCHER_RELOAD = 401, + WW_SENSOR_BUTTON_MAIN = 1000, + WW_SENSOR_BUTTON_1 = 1001, + WW_SENSOR_BUTTON_2 = 1002, + WW_SENSOR_BUTTON_3 = 1003, + WW_SENSOR_HEAD_POSITION_PAN = 2000, + WW_SENSOR_HEAD_POSITION_TILT = 2001, + WW_SENSOR_BODY_POSE = 2002, + WW_SENSOR_ACCELEROMETER = 2003, + WW_SENSOR_GYROSCOPE = 2004, + WW_SENSOR_DISTANCE_FRONT_LEFT_FACING = 3000, + WW_SENSOR_DISTANCE_FRONT_RIGHT_FACING = 3001, + WW_SENSOR_DISTANCE_BACK = 3002, + WW_SENSOR_ENCODER_LEFT_WHEEL = 3003, + WW_SENSOR_ENCODER_RIGHT_WHEEL = 3004, + WW_SENSOR_MICROPHONE = 3005, +}; + +typedef NS_ENUM(NSInteger, WWRobotType) { + WW_ROBOT_UNKNOWN = 1000, + WW_ROBOT_DASH = 1001, + WW_ROBOT_DOT = 1002, +}; + +typedef NS_ENUM(NSUInteger, WWPersonalityColorIndex) { + WW_PERSONALITY_COLOR_NONE = 0, // aka white + WW_PERSONALITY_COLOR_YELLOW = 1, // do not renumber these! + WW_PERSONALITY_COLOR_GREEN = 2, + WW_PERSONALITY_COLOR_ORANGE = 3, + WW_PERSONALITY_COLOR_BLUE = 4, + WW_PERSONALITY_COLOR_RED = 5, + WW_PERSONALITY_COLOR_PURPLE = 6, + WW_PERSONALITY_COLOR_INVALID = 255 +}; + +typedef NS_ENUM(NSUInteger, WWRobotColorIndex) { + WW_ROBOT_COLOR_WHITE = WW_PERSONALITY_COLOR_NONE, + WW_ROBOT_COLOR_YELLOW = WW_PERSONALITY_COLOR_YELLOW, + WW_ROBOT_COLOR_GREEN = WW_PERSONALITY_COLOR_GREEN, + WW_ROBOT_COLOR_ORANGE = WW_PERSONALITY_COLOR_ORANGE, + WW_ROBOT_COLOR_BLUE = WW_PERSONALITY_COLOR_BLUE, + WW_ROBOT_COLOR_RED = WW_PERSONALITY_COLOR_RED, + WW_ROBOT_COLOR_PURPLE = WW_PERSONALITY_COLOR_PURPLE, + WW_ROBOT_COLOR_BLUE2 = (WW_PERSONALITY_COLOR_PURPLE + 1), + WW_ROBOT_COLOR_OFF = (WW_PERSONALITY_COLOR_PURPLE + 2), + WW_ROBOT_COLOR_INVALID = WW_PERSONALITY_COLOR_INVALID +}; + +typedef NS_ENUM(NSUInteger, WWPersonalityAnimationIndex) { + WW_PERSONALITY_ANIMATION_NONE = 0, + WW_PERSONALITY_ANIMATION_1 = 1, + WW_PERSONALITY_ANIMATION_2 = 2, + WW_PERSONALITY_ANIMATION_3 = 3, + WW_PERSONALITY_ANIMATION_INVALID = 255, +}; + +typedef NS_ENUM(NSUInteger, WWBeaconDataType) { + WW_BEACON_DATA_TYPE_COLOR = 0, + WW_BEACON_DATA_TYPE_USER = 1 +}; #define WW_BEACON_RECEIVER_LEFT (1 << 0) #define WW_BEACON_RECEIVER_RIGHT (1 << 1) @@ -157,26 +163,26 @@ typedef unsigned int WWBeaconDataType; #define WW_COMMAND_VALUE_ORDER_INDEX __wwstr__"index" -typedef enum { +typedef NS_ENUM(NSUInteger, WWPoseMode) { WW_POSE_MODE_GLOBAL = 0, WW_POSE_MODE_RELATIVE_COMMAND, WW_POSE_MODE_RELATIVE_MEASURED, WW_POSE_MODE_SET_GLOBAL, WW_POSE_MODE_SET_TEMP_GLOBAL, WW_POSE_MODE_TEMP_GLOBAL -} WWPoseMode; +} ; -typedef enum { +typedef NS_ENUM(NSUInteger, WWPoseDirection) { WW_POSE_DIRECTION_FORWARD = 0, WW_POSE_DIRECTION_BACKWARD, WW_POSE_DIRECTION_INFERRED, -} WWPoseDirection; +} ; -typedef enum { +typedef NS_ENUM(NSUInteger, WWPoseWrap) { WW_POSE_WRAP_OFF = 0, WW_POSE_WRAP_ON, -} WWPoseWrap; +} ; #undef wwstr -#endif \ No newline at end of file +#endif diff --git a/iOS/libraries/WWRobotAPI.framework/Versions/A/Headers/WWRobotAPI.h b/iOS/libraries/WWRobotAPI.framework/Versions/A/Headers/WWRobotAPI.h index 2d83730..7deb340 100644 --- a/iOS/libraries/WWRobotAPI.framework/Versions/A/Headers/WWRobotAPI.h +++ b/iOS/libraries/WWRobotAPI.framework/Versions/A/Headers/WWRobotAPI.h @@ -6,6 +6,8 @@ // Copyright (c) 2014 Wonder Workshop inc. (https://www.makewonder.com/) All rights reserved. // +#import + // common #import #import diff --git a/iOS/playground.xcodeproj/project.pbxproj b/iOS/playground.xcodeproj/project.pbxproj index 5efb491..28c7c14 100644 --- a/iOS/playground.xcodeproj/project.pbxproj +++ b/iOS/playground.xcodeproj/project.pbxproj @@ -7,10 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - 0A304C021A1A6FEF001A67B7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A304C011A1A6FEF001A67B7 /* main.m */; }; - 0A304C051A1A6FEF001A67B7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A304C041A1A6FEF001A67B7 /* AppDelegate.m */; }; - 0A304C081A1A6FEF001A67B7 /* RobotListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A304C071A1A6FEF001A67B7 /* RobotListViewController.m */; }; - 0A304C0B1A1A6FEF001A67B7 /* RobotControlPanelViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A304C0A1A1A6FEF001A67B7 /* RobotControlPanelViewController.m */; }; + 0A304C081A1A6FEF001A67B7 /* RobotListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A304C071A1A6FEF001A67B7 /* RobotListViewController.swift */; }; 0A304C0E1A1A6FEF001A67B7 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0A304C0C1A1A6FEF001A67B7 /* Main.storyboard */; }; 0A304C101A1A6FEF001A67B7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0A304C0F1A1A6FEF001A67B7 /* Images.xcassets */; }; 0A304C131A1A6FEF001A67B7 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0A304C111A1A6FEF001A67B7 /* LaunchScreen.xib */; }; @@ -20,18 +17,23 @@ 0A304C2D1A1A70E7001A67B7 /* libc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A304C2C1A1A70E7001A67B7 /* libc++.dylib */; }; 0A304C321A1A8332001A67B7 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A304C311A1A8332001A67B7 /* UIKit.framework */; }; 0A304C341A1A833B001A67B7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A304C331A1A833B001A67B7 /* Foundation.framework */; }; - 0A304C3C1A1A8619001A67B7 /* RobotListTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A304C3A1A1A8619001A67B7 /* RobotListTableViewCell.m */; }; 0A304C3D1A1A8619001A67B7 /* RobotListTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0A304C3B1A1A8619001A67B7 /* RobotListTableViewCell.xib */; }; - 0A304C401A1AB963001A67B7 /* ControlLightsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A304C3F1A1AB963001A67B7 /* ControlLightsViewController.m */; }; - 0A304C431A1ABD6D001A67B7 /* RobotControlViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A304C421A1ABD6D001A67B7 /* RobotControlViewController.m */; }; - 0A304C481A1AD28A001A67B7 /* ControlEyeRingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A304C471A1AD28A001A67B7 /* ControlEyeRingViewController.m */; }; - 0A304C4B1A1AE50B001A67B7 /* JoystickView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A304C4A1A1AE50B001A67B7 /* JoystickView.m */; }; - 0A304C4E1A1AE8FC001A67B7 /* ControlDriveViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A304C4D1A1AE8FC001A67B7 /* ControlDriveViewController.m */; }; - 0A304C541A1BEBC9001A67B7 /* ControlSensorsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A304C531A1BEBC9001A67B7 /* ControlSensorsViewController.m */; }; - 0A304C581A1C0DA4001A67B7 /* ControlSoundViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A304C571A1C0DA4001A67B7 /* ControlSoundViewController.m */; }; 0A412C581A6468110045A7B0 /* wiggle.json in Resources */ = {isa = PBXBuildFile; fileRef = 0A412C571A6468110045A7B0 /* wiggle.json */; }; - 780D96501A1B844000B109CC /* CircleJoystickView.m in Sources */ = {isa = PBXBuildFile; fileRef = 780D964F1A1B844000B109CC /* CircleJoystickView.m */; }; - 780D96531A1B8F1800B109CC /* ControlHeadViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 780D96521A1B8F1800B109CC /* ControlHeadViewController.m */; }; + 6007A9051DD3C9EF005DF517 /* Bridging-Helper.m in Sources */ = {isa = PBXBuildFile; fileRef = 6007A9041DD3C9EF005DF517 /* Bridging-Helper.m */; }; + 604467961DDFAC5B00B4D2E8 /* CoordinatesHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 604467951DDFAC5B00B4D2E8 /* CoordinatesHelper.swift */; }; + 604F66F71DD4838800729682 /* RobotControlViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 604F66F61DD4838800729682 /* RobotControlViewController.swift */; }; + 604F66F91DD4885A00729682 /* ControlEyeRingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 604F66F81DD4885A00729682 /* ControlEyeRingViewController.swift */; }; + 604F66FB1DD494DA00729682 /* ControlDriveViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 604F66FA1DD494DA00729682 /* ControlDriveViewController.swift */; }; + 604F66FD1DD4A80600729682 /* ControlHeadViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 604F66FC1DD4A80600729682 /* ControlHeadViewController.swift */; }; + 604F66FF1DD4ACB700729682 /* ControlSensorsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 604F66FE1DD4ACB700729682 /* ControlSensorsViewController.swift */; }; + 604F67011DD4BAA900729682 /* ControlSoundViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 604F67001DD4BAA900729682 /* ControlSoundViewController.swift */; }; + 605653791DD47ED900354A88 /* ClassExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 605653781DD47ED900354A88 /* ClassExtensions.swift */; }; + 608033721DD5B28B0092A787 /* CircleJoystickView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608033711DD5B28B0092A787 /* CircleJoystickView.swift */; }; + 608033B01DD5C04E0092A787 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608033AF1DD5C04E0092A787 /* AppDelegate.swift */; }; + 608033B21DD5E6880092A787 /* JoystickView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608033B11DD5E6880092A787 /* JoystickView.swift */; }; + 608033B61DD67A730092A787 /* RobotListTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608033B51DD67A730092A787 /* RobotListTableViewCell.swift */; }; + 60E314E81DD46C1100EAF47A /* ControlLightsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E314E71DD46C1100EAF47A /* ControlLightsViewController.swift */; }; + 60EB766F1DD4F95B00071F47 /* RobotControlPanelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60EB766E1DD4F95B00071F47 /* RobotControlPanelViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -47,13 +49,7 @@ /* Begin PBXFileReference section */ 0A304BFC1A1A6FEF001A67B7 /* playground.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = playground.app; sourceTree = BUILT_PRODUCTS_DIR; }; 0A304C001A1A6FEF001A67B7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 0A304C011A1A6FEF001A67B7 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 0A304C031A1A6FEF001A67B7 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 0A304C041A1A6FEF001A67B7 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 0A304C061A1A6FEF001A67B7 /* RobotListViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RobotListViewController.h; sourceTree = ""; }; - 0A304C071A1A6FEF001A67B7 /* RobotListViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RobotListViewController.m; sourceTree = ""; }; - 0A304C091A1A6FEF001A67B7 /* RobotControlPanelViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RobotControlPanelViewController.h; sourceTree = ""; }; - 0A304C0A1A1A6FEF001A67B7 /* RobotControlPanelViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RobotControlPanelViewController.m; sourceTree = ""; }; + 0A304C071A1A6FEF001A67B7 /* RobotListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RobotListViewController.swift; sourceTree = ""; }; 0A304C0D1A1A6FEF001A67B7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 0A304C0F1A1A6FEF001A67B7 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 0A304C121A1A6FEF001A67B7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; @@ -66,28 +62,24 @@ 0A304C2F1A1A7E5D001A67B7 /* playground-prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "playground-prefix.pch"; sourceTree = ""; }; 0A304C311A1A8332001A67B7 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 0A304C331A1A833B001A67B7 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 0A304C391A1A8619001A67B7 /* RobotListTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RobotListTableViewCell.h; sourceTree = ""; }; - 0A304C3A1A1A8619001A67B7 /* RobotListTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RobotListTableViewCell.m; sourceTree = ""; }; 0A304C3B1A1A8619001A67B7 /* RobotListTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RobotListTableViewCell.xib; sourceTree = ""; }; - 0A304C3E1A1AB963001A67B7 /* ControlLightsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ControlLightsViewController.h; sourceTree = ""; }; - 0A304C3F1A1AB963001A67B7 /* ControlLightsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ControlLightsViewController.m; sourceTree = ""; }; - 0A304C411A1ABD6D001A67B7 /* RobotControlViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RobotControlViewController.h; sourceTree = ""; }; - 0A304C421A1ABD6D001A67B7 /* RobotControlViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RobotControlViewController.m; sourceTree = ""; }; - 0A304C461A1AD28A001A67B7 /* ControlEyeRingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ControlEyeRingViewController.h; sourceTree = ""; }; - 0A304C471A1AD28A001A67B7 /* ControlEyeRingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ControlEyeRingViewController.m; sourceTree = ""; }; - 0A304C491A1AE50B001A67B7 /* JoystickView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JoystickView.h; sourceTree = ""; }; - 0A304C4A1A1AE50B001A67B7 /* JoystickView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JoystickView.m; sourceTree = ""; }; - 0A304C4C1A1AE8FC001A67B7 /* ControlDriveViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ControlDriveViewController.h; sourceTree = ""; }; - 0A304C4D1A1AE8FC001A67B7 /* ControlDriveViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ControlDriveViewController.m; sourceTree = ""; }; - 0A304C521A1BEBC9001A67B7 /* ControlSensorsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ControlSensorsViewController.h; sourceTree = ""; }; - 0A304C531A1BEBC9001A67B7 /* ControlSensorsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ControlSensorsViewController.m; sourceTree = ""; }; - 0A304C561A1C0DA4001A67B7 /* ControlSoundViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ControlSoundViewController.h; sourceTree = ""; }; - 0A304C571A1C0DA4001A67B7 /* ControlSoundViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ControlSoundViewController.m; sourceTree = ""; }; 0A412C571A6468110045A7B0 /* wiggle.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = wiggle.json; sourceTree = ""; }; - 780D964E1A1B844000B109CC /* CircleJoystickView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CircleJoystickView.h; sourceTree = ""; }; - 780D964F1A1B844000B109CC /* CircleJoystickView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CircleJoystickView.m; sourceTree = ""; }; - 780D96511A1B8F1800B109CC /* ControlHeadViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ControlHeadViewController.h; sourceTree = ""; }; - 780D96521A1B8F1800B109CC /* ControlHeadViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ControlHeadViewController.m; sourceTree = ""; }; + 6007A9011DD3BF24005DF517 /* playground-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "playground-Bridging-Header.h"; sourceTree = ""; }; + 6007A9041DD3C9EF005DF517 /* Bridging-Helper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Bridging-Helper.m"; sourceTree = ""; }; + 604467951DDFAC5B00B4D2E8 /* CoordinatesHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoordinatesHelper.swift; sourceTree = ""; }; + 604F66F61DD4838800729682 /* RobotControlViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RobotControlViewController.swift; sourceTree = ""; }; + 604F66F81DD4885A00729682 /* ControlEyeRingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControlEyeRingViewController.swift; sourceTree = ""; }; + 604F66FA1DD494DA00729682 /* ControlDriveViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControlDriveViewController.swift; sourceTree = ""; }; + 604F66FC1DD4A80600729682 /* ControlHeadViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControlHeadViewController.swift; sourceTree = ""; }; + 604F66FE1DD4ACB700729682 /* ControlSensorsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControlSensorsViewController.swift; sourceTree = ""; }; + 604F67001DD4BAA900729682 /* ControlSoundViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControlSoundViewController.swift; sourceTree = ""; }; + 605653781DD47ED900354A88 /* ClassExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClassExtensions.swift; sourceTree = ""; }; + 608033711DD5B28B0092A787 /* CircleJoystickView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CircleJoystickView.swift; sourceTree = ""; }; + 608033AF1DD5C04E0092A787 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 608033B11DD5E6880092A787 /* JoystickView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JoystickView.swift; sourceTree = ""; }; + 608033B51DD67A730092A787 /* RobotListTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RobotListTableViewCell.swift; sourceTree = ""; }; + 60E314E71DD46C1100EAF47A /* ControlLightsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControlLightsViewController.swift; sourceTree = ""; }; + 60EB766E1DD4F95B00071F47 /* RobotControlPanelViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RobotControlPanelViewController.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -138,12 +130,15 @@ 0A412C561A6468060045A7B0 /* animations */, 0A304C361A1A85D2001A67B7 /* controllers */, 0A304C351A1A85CB001A67B7 /* views */, - 0A304C031A1A6FEF001A67B7 /* AppDelegate.h */, - 0A304C041A1A6FEF001A67B7 /* AppDelegate.m */, 0A304C0C1A1A6FEF001A67B7 /* Main.storyboard */, 0A304C0F1A1A6FEF001A67B7 /* Images.xcassets */, 0A304C111A1A6FEF001A67B7 /* LaunchScreen.xib */, 0A304BFF1A1A6FEF001A67B7 /* Supporting Files */, + 608033AF1DD5C04E0092A787 /* AppDelegate.swift */, + 604467951DDFAC5B00B4D2E8 /* CoordinatesHelper.swift */, + 6007A9011DD3BF24005DF517 /* playground-Bridging-Header.h */, + 6007A9041DD3C9EF005DF517 /* Bridging-Helper.m */, + 605653781DD47ED900354A88 /* ClassExtensions.swift */, ); path = playground; sourceTree = ""; @@ -153,7 +148,6 @@ children = ( 0A304C2F1A1A7E5D001A67B7 /* playground-prefix.pch */, 0A304C001A1A6FEF001A67B7 /* Info.plist */, - 0A304C011A1A6FEF001A67B7 /* main.m */, ); name = "Supporting Files"; sourceTree = ""; @@ -178,13 +172,10 @@ 0A304C351A1A85CB001A67B7 /* views */ = { isa = PBXGroup; children = ( - 780D964E1A1B844000B109CC /* CircleJoystickView.h */, - 780D964F1A1B844000B109CC /* CircleJoystickView.m */, - 0A304C391A1A8619001A67B7 /* RobotListTableViewCell.h */, - 0A304C3A1A1A8619001A67B7 /* RobotListTableViewCell.m */, + 608033711DD5B28B0092A787 /* CircleJoystickView.swift */, + 608033B51DD67A730092A787 /* RobotListTableViewCell.swift */, 0A304C3B1A1A8619001A67B7 /* RobotListTableViewCell.xib */, - 0A304C491A1AE50B001A67B7 /* JoystickView.h */, - 0A304C4A1A1AE50B001A67B7 /* JoystickView.m */, + 608033B11DD5E6880092A787 /* JoystickView.swift */, ); name = views; sourceTree = ""; @@ -192,24 +183,15 @@ 0A304C361A1A85D2001A67B7 /* controllers */ = { isa = PBXGroup; children = ( - 0A304C3E1A1AB963001A67B7 /* ControlLightsViewController.h */, - 0A304C3F1A1AB963001A67B7 /* ControlLightsViewController.m */, - 0A304C411A1ABD6D001A67B7 /* RobotControlViewController.h */, - 0A304C421A1ABD6D001A67B7 /* RobotControlViewController.m */, - 0A304C061A1A6FEF001A67B7 /* RobotListViewController.h */, - 0A304C071A1A6FEF001A67B7 /* RobotListViewController.m */, - 0A304C461A1AD28A001A67B7 /* ControlEyeRingViewController.h */, - 0A304C471A1AD28A001A67B7 /* ControlEyeRingViewController.m */, - 0A304C091A1A6FEF001A67B7 /* RobotControlPanelViewController.h */, - 0A304C0A1A1A6FEF001A67B7 /* RobotControlPanelViewController.m */, - 0A304C4C1A1AE8FC001A67B7 /* ControlDriveViewController.h */, - 0A304C4D1A1AE8FC001A67B7 /* ControlDriveViewController.m */, - 780D96511A1B8F1800B109CC /* ControlHeadViewController.h */, - 780D96521A1B8F1800B109CC /* ControlHeadViewController.m */, - 0A304C521A1BEBC9001A67B7 /* ControlSensorsViewController.h */, - 0A304C531A1BEBC9001A67B7 /* ControlSensorsViewController.m */, - 0A304C561A1C0DA4001A67B7 /* ControlSoundViewController.h */, - 0A304C571A1C0DA4001A67B7 /* ControlSoundViewController.m */, + 60E314E71DD46C1100EAF47A /* ControlLightsViewController.swift */, + 604F66F61DD4838800729682 /* RobotControlViewController.swift */, + 0A304C071A1A6FEF001A67B7 /* RobotListViewController.swift */, + 604F66F81DD4885A00729682 /* ControlEyeRingViewController.swift */, + 60EB766E1DD4F95B00071F47 /* RobotControlPanelViewController.swift */, + 604F66FA1DD494DA00729682 /* ControlDriveViewController.swift */, + 604F66FC1DD4A80600729682 /* ControlHeadViewController.swift */, + 604F66FE1DD4ACB700729682 /* ControlSensorsViewController.swift */, + 604F67001DD4BAA900729682 /* ControlSoundViewController.swift */, ); name = controllers; sourceTree = ""; @@ -283,7 +265,8 @@ TargetAttributes = { 0A304BFB1A1A6FEF001A67B7 = { CreatedOnToolsVersion = 6.1; - DevelopmentTeam = 6AS2VXQ4XQ; + DevelopmentTeam = XP2D8KRSZE; + LastSwiftMigration = 0810; }; 0A304C171A1A6FF0001A67B7 = { CreatedOnToolsVersion = 6.1; @@ -338,20 +321,22 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0A304C431A1ABD6D001A67B7 /* RobotControlViewController.m in Sources */, - 0A304C3C1A1A8619001A67B7 /* RobotListTableViewCell.m in Sources */, - 0A304C4B1A1AE50B001A67B7 /* JoystickView.m in Sources */, - 0A304C051A1A6FEF001A67B7 /* AppDelegate.m in Sources */, - 0A304C581A1C0DA4001A67B7 /* ControlSoundViewController.m in Sources */, - 780D96531A1B8F1800B109CC /* ControlHeadViewController.m in Sources */, - 0A304C081A1A6FEF001A67B7 /* RobotListViewController.m in Sources */, - 0A304C481A1AD28A001A67B7 /* ControlEyeRingViewController.m in Sources */, - 0A304C541A1BEBC9001A67B7 /* ControlSensorsViewController.m in Sources */, - 0A304C021A1A6FEF001A67B7 /* main.m in Sources */, - 0A304C4E1A1AE8FC001A67B7 /* ControlDriveViewController.m in Sources */, - 780D96501A1B844000B109CC /* CircleJoystickView.m in Sources */, - 0A304C0B1A1A6FEF001A67B7 /* RobotControlPanelViewController.m in Sources */, - 0A304C401A1AB963001A67B7 /* ControlLightsViewController.m in Sources */, + 60E314E81DD46C1100EAF47A /* ControlLightsViewController.swift in Sources */, + 604F66F71DD4838800729682 /* RobotControlViewController.swift in Sources */, + 608033721DD5B28B0092A787 /* CircleJoystickView.swift in Sources */, + 0A304C081A1A6FEF001A67B7 /* RobotListViewController.swift in Sources */, + 608033B21DD5E6880092A787 /* JoystickView.swift in Sources */, + 604F66F91DD4885A00729682 /* ControlEyeRingViewController.swift in Sources */, + 60EB766F1DD4F95B00071F47 /* RobotControlPanelViewController.swift in Sources */, + 604F66FB1DD494DA00729682 /* ControlDriveViewController.swift in Sources */, + 604F66FF1DD4ACB700729682 /* ControlSensorsViewController.swift in Sources */, + 608033B61DD67A730092A787 /* RobotListTableViewCell.swift in Sources */, + 604F66FD1DD4A80600729682 /* ControlHeadViewController.swift in Sources */, + 604F67011DD4BAA900729682 /* ControlSoundViewController.swift in Sources */, + 605653791DD47ED900354A88 /* ClassExtensions.swift in Sources */, + 604467961DDFAC5B00B4D2E8 /* CoordinatesHelper.swift in Sources */, + 608033B01DD5C04E0092A787 /* AppDelegate.swift in Sources */, + 6007A9051DD3C9EF005DF517 /* Bridging-Helper.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -475,8 +460,10 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEVELOPMENT_TEAM = XP2D8KRSZE; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -484,10 +471,13 @@ ); GCC_PREFIX_HEADER = "playground/playground-prefix.pch"; INFOPLIST_FILE = playground/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; + SWIFT_OBJC_BRIDGING_HEADER = "playground/playground-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -496,8 +486,10 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEVELOPMENT_TEAM = XP2D8KRSZE; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -505,10 +497,12 @@ ); GCC_PREFIX_HEADER = "playground/playground-prefix.pch"; INFOPLIST_FILE = playground/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; + SWIFT_OBJC_BRIDGING_HEADER = "playground/playground-Bridging-Header.h"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; @@ -516,6 +510,7 @@ 0A304C261A1A6FF0001A67B7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", @@ -535,6 +530,7 @@ 0A304C271A1A6FF0001A67B7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", diff --git a/iOS/playground/AppDelegate.h b/iOS/playground/AppDelegate.h deleted file mode 100644 index f6e3eaa..0000000 --- a/iOS/playground/AppDelegate.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// AppDelegate.h -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/iOS/playground/AppDelegate.m b/iOS/playground/AppDelegate.m deleted file mode 100644 index 6a4c5e5..0000000 --- a/iOS/playground/AppDelegate.m +++ /dev/null @@ -1,50 +0,0 @@ -// -// AppDelegate.m -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "AppDelegate.h" -#import "RobotControlPanelViewController.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController; - UINavigationController *navigationController = [splitViewController.viewControllers lastObject]; - //navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem; - splitViewController.delegate = self; - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/iOS/playground/AppDelegate.swift b/iOS/playground/AppDelegate.swift new file mode 100644 index 0000000..0e1f112 --- /dev/null +++ b/iOS/playground/AppDelegate.swift @@ -0,0 +1,26 @@ +// +// AppDelegate.swift +// something +// +// Created by Jelle Alten on 11-11-16. +// Copyright © 2016 Alt-N. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate { + + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions + launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + + if let splitViewController = window?.rootViewController as? UISplitViewController { + splitViewController.delegate = self + } + + return true + } + +} diff --git a/iOS/playground/Base.lproj/Main.storyboard b/iOS/playground/Base.lproj/Main.storyboard index 59d0a72..cea1cf1 100644 --- a/iOS/playground/Base.lproj/Main.storyboard +++ b/iOS/playground/Base.lproj/Main.storyboard @@ -1,8 +1,12 @@ - + + + + - + + @@ -10,6 +14,7 @@ + @@ -23,13 +28,13 @@ - + - + - + @@ -44,11 +49,11 @@ - + - + @@ -59,7 +64,7 @@ - + @@ -78,29 +83,29 @@ - + - + - + - + - + - + @@ -123,6 +128,7 @@ + @@ -136,9 +142,9 @@ - + - + @@ -148,6 +154,13 @@ + + + + + + + @@ -208,96 +221,88 @@ - + - - - - - - - - + - - - - - + + + + - - + + - - - - + + + + - + - + - + - + - + @@ -306,7 +311,7 @@ - + @@ -316,8 +321,8 @@ - - + + @@ -334,24 +339,23 @@ - + - + - @@ -365,9 +369,9 @@ - + - + @@ -458,14 +462,14 @@ - + - + - @@ -504,24 +507,24 @@ - + - + - + @@ -532,29 +535,28 @@ - + - + - - + @@ -564,28 +566,28 @@ - + - + - + - + - + - + @@ -598,11 +600,10 @@ - + - - + @@ -612,26 +613,26 @@ - + - + - + - + + + + + - + diff --git a/iOS/playground/Bridging-Helper.m b/iOS/playground/Bridging-Helper.m new file mode 100644 index 0000000..894092e --- /dev/null +++ b/iOS/playground/Bridging-Helper.m @@ -0,0 +1,15 @@ +// +// Bridging-Helper.m +// playground +// +// Created by Jelle Alten on 09-11-16. +// Copyright © 2016 Wonder Workshop. All rights reserved. +// + +#import + +@implementation WWRobotManager (shared) ++ (WWRobotManager*) sharedManager { + return [WWRobotManager manager]; +} +@end diff --git a/iOS/playground/CircleJoystickView.h b/iOS/playground/CircleJoystickView.h deleted file mode 100644 index 55eca68..0000000 --- a/iOS/playground/CircleJoystickView.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// CircleJoystickView.h -// WonderWorkshop -// -// Created by igor on 9/17/14. -// Copyright (c) 2014 play-i. All rights reserved. -// - -#import "JoystickView.h" - -@interface CircleJoystickView : JoystickView - -- (float) angle; /* get angle [0-360] */ -@property (nonatomic) float power; /* 0-1 multiplier, which is a relative joystick dot distance from the center */ - -@end diff --git a/iOS/playground/CircleJoystickView.m b/iOS/playground/CircleJoystickView.m deleted file mode 100644 index 7203ab8..0000000 --- a/iOS/playground/CircleJoystickView.m +++ /dev/null @@ -1,113 +0,0 @@ -// -// CircleJoystickView.m -// WonderWorkshop -// -// Created by igor on 9/17/14. -// Copyright (c) 2014 play-i. All rights reserved. -// - -#import "CircleJoystickView.h" - -#define STROKECOLOR CUSTOMBLUECOLOR -#define STROKEWIDTH 5.0f -#define CIRCLE_RECT_PADDING 10 -#define BACKCOLOR [UIColor whiteColor].CGColor - -float getDistance(CGPoint p1, CGPoint p2); - -@implementation CircleJoystickView -{ - float _circleRadius; -} - -- (float) angle -{ - CGPoint center = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2); - CGPoint p1 = self.dotPos; - CGPoint p0 = center; - - CGPoint vector = CGPointMake(p1.x - p0.x, p1.y - p0.y); - - float theta_rad = atan2(vector.y,vector.x); - - theta_rad += M_PI / 2.0; - - float theta_deg = (theta_rad / M_PI * 180); - - theta_deg += (theta_rad > 0 ? 0 : 360); - - - return theta_deg; -} - -// once upon a time we will get assets for joystick and remove this -- (void) drawRect:(CGRect)rect -{ - - - [super drawRect:rect]; -} - - -- (void) layoutSubviews -{ - [super layoutSubviews]; - - // get radius for circle drawing - _circleRadius = CGRectInset(self.bounds, CIRCLE_RECT_PADDING, CIRCLE_RECT_PADDING).size.width / 2; -} - -- (float) power -{ - return getDistance(self.dotPos, _center) / [self circleRadius]; -} - -- (float) circleRadius -{ - return _circleRadius - DOTSIZE / 2; -} - -- (void) enforceJoystickBound:(CGPoint *)point -{ - [super enforceJoystickBound:point]; - - float v1 = point->x - _center.x; - float v2 = point->y - _center.y; - - float lenght = sqrt( v1 * v1 + v2 * v2 ); - - float maxLength = [self circleRadius]; - - if (lenght >= maxLength) { - float phi = atan2(v2, v1); - - float x = _center.x + maxLength * cos(phi); - float y = _center.y + maxLength * sin(phi); - - // NSLog(@"new pos %@, corrected %.1f : %.1f", NSStringFromCGPoint(*p1), x, y); - - point->x = x; - point->y = y; - } - -} - -- (float) getX -{ - float src_min = _center.x - [self circleRadius]; - float src_max = _center.x + [self circleRadius]; - - return normalizeValueToNewRange(self.dotPos.x, src_min, src_max, 1, - 1); -} - -- (float) getY -{ - float src_min = _center.y - [self circleRadius]; - float src_max = _center.y + [self circleRadius]; - - return normalizeValueToNewRange(self.dotPos.y, src_min, src_max, 1, - 1); -} - - - -@end diff --git a/iOS/playground/CircleJoystickView.swift b/iOS/playground/CircleJoystickView.swift new file mode 100644 index 0000000..c91708b --- /dev/null +++ b/iOS/playground/CircleJoystickView.swift @@ -0,0 +1,67 @@ +// +// CircleJoystickView1.swift +// playground +// +// Created by Jelle Alten on 11-11-16. +// Copyright © 2016 Wonder Workshop. All rights reserved. +// + +import UIKit + +class CircleJoystickView: JoystickView { + + private var _circleRadius: Float = 0.0 + let circleRectPadding: CGFloat = 10 + + override func layoutSubviews() { + super.layoutSubviews() + + // get radius for circle drawing + let boundsInset = bounds.insetBy(dx: circleRectPadding, dy:circleRectPadding) + _circleRadius = Float( boundsInset.size.width / CGFloat(2.0)) + } + + var power: Float { + get { + return getDistance(point1: dotPos, point2: self.dragCenter) / circleRadius + } + } + + var circleRadius: Float { + return _circleRadius - Float(dotSize) / 2.0 + } + + override func enforceJoystickBound(_ point: CGPoint) -> CGPoint? { + let oldPoint = point + let v1 = oldPoint.x - dragCenter.x + let v2 = oldPoint.y - dragCenter.y + let length = sqrt( v1 * v1 + v2 * v2) + let maxLength = CGFloat(circleRadius) + if length > maxLength { + let phi = atan2(v2, v1) + let x = dragCenter.x + maxLength * cos(phi) + let y = dragCenter.y + maxLength * sin(phi) + return CGPoint(x: x, y: y) + } else { + return nil + } + } +} + +extension CircleJoystickView { + + override func getX() -> Float { + let src_min = Float(dragCenter.x) - circleRadius + let src_max = Float(dragCenter.x) + circleRadius + + return normalizeValueToNewRange(Float(dotPos.x), src_min, src_max, 1, -1) + } + + override func getY() -> Float { + let src_min = Float(dragCenter.y) - circleRadius + let src_max = Float(dragCenter.y) + circleRadius + + return normalizeValueToNewRange(Float(dotPos.y), src_min, src_max, 1, -1) + } + +} diff --git a/iOS/playground/ClassExtensions.swift b/iOS/playground/ClassExtensions.swift new file mode 100644 index 0000000..87f7027 --- /dev/null +++ b/iOS/playground/ClassExtensions.swift @@ -0,0 +1,15 @@ +// +// ClassExtensions.swift +// playground +// +// Created by Jelle Alten on 10-11-16. +// Copyright © 2016 Wonder Workshop. All rights reserved. +// + +import Foundation + +public extension NSObject { + public class var nameOfClass: String { + return String(describing: self) + } +} diff --git a/iOS/playground/ControlDriveViewController.h b/iOS/playground/ControlDriveViewController.h deleted file mode 100644 index 5c7a956..0000000 --- a/iOS/playground/ControlDriveViewController.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// ControlDriveViewController.h -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "RobotControlViewController.h" -#import "CircleJoystickView.h" - -@interface ControlDriveViewController : RobotControlViewController - -@property (nonatomic, weak) IBOutlet CircleJoystickView *joystick; -@property (weak, nonatomic) IBOutlet UIButton *toggleWiggleBtn; - -- (IBAction)toggleWiggle:(id)sender; -- (IBAction)executeNod:(id)sender; - -@end diff --git a/iOS/playground/ControlDriveViewController.m b/iOS/playground/ControlDriveViewController.m deleted file mode 100644 index 5c3ba04..0000000 --- a/iOS/playground/ControlDriveViewController.m +++ /dev/null @@ -1,155 +0,0 @@ -// -// ControlDriveViewController.m -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "ControlDriveViewController.h" - -#define ROBOT_SPEED 50 - -@interface ControlDriveViewController () - -@property (nonatomic) BOOL isWiggling; -@property (nonatomic) BOOL isNodding; -@property (nonatomic, strong) WWCommandSetSequence *wiggleAnimation; -@property (nonatomic, strong) WWCommandSetSequence *nodAnimation; -@property (weak, nonatomic) IBOutlet UILabel *poseLabel; - -@end - -@implementation ControlDriveViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.joystick.type = DRIVE_JOYSTICK; - [self.joystick updateDraggerImage]; - self.isWiggling = NO; - self.isNodding = NO; - - self.wiggleAnimation = [WWCommandSetSequence sequenceFromFileInBundle:@"wiggle" fileType:@"json"]; - self.nodAnimation = [WWCommandSetSequence new]; - WWCommandSet *lookup = [WWCommandSet new]; - [lookup setHeadPositionTilt:[[WWCommandHeadPosition alloc] initWithDegree:-20]]; - WWCommandSet *lookdown = [WWCommandSet new]; - [lookdown setHeadPositionTilt:[[WWCommandHeadPosition alloc] initWithDegree:7.5]]; - [self.nodAnimation addCommandSet:lookup withDuration:0.4]; - [self.nodAnimation addCommandSet:lookdown withDuration:0.4]; - [self.nodAnimation addCommandSet:lookup withDuration:0.4]; - [self.nodAnimation addCommandSet:lookdown withDuration:0.4]; -} - -- (WWCommandSet *) commandFromJoystick -{ - WWCommandSet *cmdToSend = [WWCommandSet new]; - - // use linear angular! - float joystickPower = self.joystick.power; - double lin = [self.joystick getY] * ROBOT_SPEED; - double ang = [self.joystick getX] * joystickPower * 3.14159 * 2.0; - - //NSLog(@"sending linear: %5.2f angular: %5.2f", lin, ang); - - // fudge factor to be tweaked - ang *= 0.5; - if (lin < 0) { - ang *= -1.0; - } - - WWCommandBodyLinearAngular *linAng = [[WWCommandBodyLinearAngular alloc] initWithLinear:lin - angular:ang]; - [cmdToSend setBodyLinearAngular:linAng]; - return cmdToSend; -} - -#pragma mark - Joystick delegates - -- (void) onJoystickMoved -{ - //self.directionalArrows.hidden = YES; - WWCommandSet *cmd = [self commandFromJoystick]; - [self sendCommandSetToRobots:cmd]; -} - -- (void) onJoystickReleased -{ - WWCommandSet *stopCommand = [WWCommandToolbelt moveStop]; - [self sendCommandSetToRobots:stopCommand]; -} - - -- (IBAction)toggleWiggle:(id)sender -{ - NSString *btnText; - for (WWRobot *robot in self.connectedRobots) { - if (self.isWiggling) { - [robot stopCommandSequence:self.wiggleAnimation]; - btnText = @"Start wiggle"; - } - else { - // always start from the beginning of animation - [robot executeCommandSequence:self.wiggleAnimation withOptions:nil]; - btnText = @"Stop wiggle"; - } - } - - [self.toggleWiggleBtn setTitle:btnText forState:UIControlStateNormal]; - self.isWiggling = !self.isWiggling; // toggle -} - -- (IBAction)executeNod:(id)sender -{ - if (!self.isNodding && !self.isWiggling) { - for (WWRobot *robot in self.connectedRobots) { - [robot executeCommandSequence:self.nodAnimation withOptions:nil]; - } - } -} - -- (void) robot:(WWRobot *)robot didFinishCommandSequence:(WWCommandSetSequence *)sequence -{ - if ([sequence isEqual:self.wiggleAnimation]) { - if (self.isWiggling) { - // continue to wiggle until user stops - for (WWRobot *robot in self.connectedRobots) { - [robot executeCommandSequence:self.wiggleAnimation withOptions:nil]; - } - } - } - else { - // this is a nod sequence - self.isNodding = NO; - } -} - -- (void) robot:(WWRobot *)robot didStopExecutingCommandSequence:(WWCommandSetSequence *)sequence withResults:(NSDictionary *)results -{ - NSLog(@"wiggle sequence terminated by user."); - for (WWRobot *robot in self.connectedRobots) { - [robot resetState]; - } -} - -#pragma mark pose slider methods -- (IBAction)didChangePoseDistanceValue:(id)sender { - self.poseLabel.text = [NSString stringWithFormat:@"%d", (int)((UISlider*)sender).value]; -} - -- (IBAction)MoveDashByFixedDistance:(id)sender { - - WWCommandSet *cmdToSend = [WWCommandSet new]; - - int distance = self.poseLabel.text.intValue; - - - WWCommandBodyPose *bodyPose = [[WWCommandBodyPose alloc] initWithRelativeMeasuredX:distance Y:0.0f Radians:0.0f Time:2.0f]; - - [cmdToSend setBodyPose:bodyPose]; - [self sendCommandSetToRobots:cmdToSend]; - -} - -@end diff --git a/iOS/playground/ControlDriveViewController.swift b/iOS/playground/ControlDriveViewController.swift new file mode 100644 index 0000000..46a19d6 --- /dev/null +++ b/iOS/playground/ControlDriveViewController.swift @@ -0,0 +1,148 @@ +// +// ControlDriveViewController.swift +// playground +// +// Created by Jelle Alten on 10-11-16. +// Copyright © 2016 Wonder Workshop. All rights reserved. +// + +import Foundation +import UIKit + +class ControlDriveViewController: RobotControlViewController { + + let robotSpeed: Float = 50 + + @IBOutlet weak var joystick: CircleJoystickView! + @IBOutlet weak var toggleWiggleBtn: UIButton! + + var isWiggling = false + var isNodding = false + var wiggleAnimation: WWCommandSetSequence + var nodAnimation: WWCommandSetSequence + + @IBOutlet weak var poseLabel: UILabel! + + required init?(coder aDecoder: NSCoder) { + wiggleAnimation = WWCommandSetSequence(fromFileInBundle: "wiggle", fileType: "json") + nodAnimation = WWCommandSetSequence() + let lookup = WWCommandSet() + lookup.setHeadPositionTilt(WWCommandHeadPosition(degree: -20)) + let lookdown = WWCommandSet() + lookdown.setHeadPositionTilt(WWCommandHeadPosition(degree: 7.5)) + nodAnimation.add(lookup, withDuration: 0.4) + nodAnimation.add(lookdown, withDuration: 0.4) + nodAnimation.add(lookup, withDuration: 0.4) + nodAnimation.add(lookdown, withDuration: 0.4) + + super.init(coder: aDecoder) + } + + override func viewDidLoad() { + super.viewDidLoad() + + joystick.type = .DRIVE_JOYSTICK + joystick.updateDraggerImage() + + } + + @IBAction func toggleWiggle(_ sender: Any) { + let btnText = isWiggling ? "Start wiggle": "Stop wiggle" + for robot in connectedRobots { + if isWiggling { + robot.stopCommand(wiggleAnimation) + } else { + // always start from the beginning of animation + robot.executeCommand(wiggleAnimation, withOptions: nil) + } + } + + toggleWiggleBtn.setTitle(btnText, for: .normal) + isWiggling = !isWiggling + } + + @IBAction func executeNod(_ sender: Any) { + if !isNodding && !isWiggling { + for robot in connectedRobots { + robot.executeCommand(nodAnimation, withOptions:nil) + } + } + } +} + +extension ControlDriveViewController: JoystickDelegate { + func onJoystickMoved() { + let cmd = commandFromJoystick() + sendCommandSet(toRobots: cmd) + } + + func onJoystickReleased() { + if let stopCmd = WWCommandToolbelt.moveStop() { + sendCommandSet(toRobots: stopCmd) + } + } + + private func commandFromJoystick() -> WWCommandSet { + let cmdToSend = WWCommandSet() + + // use linear angular! + let joystickPower = joystick.power + let lin = joystick.getY() * robotSpeed + var ang = joystick.getX() * joystickPower * 3.14159 * 2.0 + + //NSLog(@"sending linear: %5.2f angular: %5.2f", lin, ang) + + // fudge factor to be tweaked + ang *= 0.5 + if lin < 0 { + ang *= -1.0 + } + + let linAng = WWCommandBodyLinearAngular(linear: Double(lin), angular: Double(ang)) + cmdToSend.setBodyLinearAngular(linAng) + return cmdToSend + } + +} + +extension ControlDriveViewController { //: WWRobotObserver { + func robot(_ robot: WWRobot!, didFinishCommand sequence: WWCommandSetSequence!) { + if sequence == wiggleAnimation { + if isWiggling { + // continue to wiggle until user stops + for robot in connectedRobots { + robot.executeCommand(wiggleAnimation, withOptions: nil) + } + } else { + // this is a nod sequence + isNodding = false + } + } + } + + func robot(_ robot: WWRobot!, didStopExecutingCommand sequence: WWCommandSetSequence!, + withResults results: [AnyHashable: Any]!) { + print("wiggle sequence terminated by user.") + for robot in connectedRobots { + robot.resetState() + } + } +} + +extension ControlDriveViewController { + @IBAction func didChangePoseDistanceValue(_ sender: UISlider) { + + poseLabel.text = "\(Int(sender.value))" + } + + @IBAction func MoveDashByFixedDistance(_ sender: Any) { + + let cmdToSend = WWCommandSet() + let distance = Double(poseLabel.text ?? "0") ?? 0.0 + + let bodyPose = WWCommandBodyPose(relativeMeasuredX:distance, y:0.0, radians:0.0, time:2.0) + cmdToSend.setBodyPose(bodyPose) + sendCommandSet(toRobots: cmdToSend) + } + +} diff --git a/iOS/playground/ControlEyeRingViewController.h b/iOS/playground/ControlEyeRingViewController.h deleted file mode 100644 index 4ce881d..0000000 --- a/iOS/playground/ControlEyeRingViewController.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// ControlEyeRingViewController.h -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "RobotControlViewController.h" - -@interface ControlEyeRingViewController : RobotControlViewController - -@property (weak, nonatomic) IBOutlet UISwitch *eye0Switch; -@property (weak, nonatomic) IBOutlet UISwitch *eye1Switch; -@property (weak, nonatomic) IBOutlet UISwitch *eye2Switch; -@property (weak, nonatomic) IBOutlet UISwitch *eye3Switch; -@property (weak, nonatomic) IBOutlet UISwitch *eye4Switch; -@property (weak, nonatomic) IBOutlet UISwitch *eye5Switch; -@property (weak, nonatomic) IBOutlet UISwitch *eye6Switch; -@property (weak, nonatomic) IBOutlet UISwitch *eye7Switch; -@property (weak, nonatomic) IBOutlet UISwitch *eye8Switch; -@property (weak, nonatomic) IBOutlet UISwitch *eye9Switch; -@property (weak, nonatomic) IBOutlet UISwitch *eye10Switch; -@property (weak, nonatomic) IBOutlet UISwitch *eye11Switch; - -@property (weak, nonatomic) IBOutlet UISlider *eyeBrightnessSlider; -@property (weak, nonatomic) IBOutlet UIButton *eyeShowButton; - -- (IBAction)setEyeRing:(id)sender; -- (IBAction)toggleEyeShow:(id)sender; -- (IBAction)runEyeAnimation:(id)sender; - -@end diff --git a/iOS/playground/ControlEyeRingViewController.m b/iOS/playground/ControlEyeRingViewController.m deleted file mode 100644 index bd4477c..0000000 --- a/iOS/playground/ControlEyeRingViewController.m +++ /dev/null @@ -1,95 +0,0 @@ -// -// ControlEyeRingViewController.m -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "ControlEyeRingViewController.h" - -@interface ControlEyeRingViewController () - -@property (nonatomic) BOOL eyeShowInProgress; -@property (nonatomic, strong) NSTimer *eyeShowTimer; -@property (nonatomic) NSUInteger eyeShowValueState; - -- (void) eyeShowTimerValues:(NSTimer *)timer; - -@end - -@implementation ControlEyeRingViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - // Do any additional setup after loading the view. -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - -- (IBAction)setEyeRing:(id)sender { - NSArray *eyeBitmap = @[[NSNumber numberWithBool:self.eye0Switch.on], - [NSNumber numberWithBool:self.eye1Switch.on], - [NSNumber numberWithBool:self.eye2Switch.on], - [NSNumber numberWithBool:self.eye3Switch.on], - [NSNumber numberWithBool:self.eye4Switch.on], - [NSNumber numberWithBool:self.eye5Switch.on], - [NSNumber numberWithBool:self.eye6Switch.on], - [NSNumber numberWithBool:self.eye7Switch.on], - [NSNumber numberWithBool:self.eye8Switch.on], - [NSNumber numberWithBool:self.eye9Switch.on], - [NSNumber numberWithBool:self.eye10Switch.on], - [NSNumber numberWithBool:self.eye11Switch.on]]; - - WWCommandSet *cmd = [WWCommandSet new]; - WWCommandEyeRing *eyeRing = [[WWCommandEyeRing alloc] initWithBitmap:eyeBitmap]; - eyeRing.brightness = self.eyeBrightnessSlider.value; - [cmd setEyeRing:eyeRing]; - [self sendCommandSetToRobots:cmd]; -} - -- (IBAction)toggleEyeShow:(id)sender { - if (self.eyeShowInProgress) { - self.eyeShowInProgress = NO; - [self.eyeShowTimer invalidate]; - [self.eyeShowButton setTitle:@"Start eye show" forState:UIControlStateNormal]; - } - else { - self.eyeShowInProgress = YES; - self.eyeShowTimer = [NSTimer scheduledTimerWithTimeInterval:0.4 target:self selector:@selector(eyeShowTimerValues:) userInfo:nil repeats:YES]; - [self.eyeShowTimer fire]; - [self.eyeShowButton setTitle:@"Stop eye show" forState:UIControlStateNormal]; - } -} - -- (void) eyeShowTimerValues:(NSTimer *)timer { - self.eyeShowValueState = (self.eyeShowValueState+1) % 12; // rotate - - self.eye0Switch.on = ((0 + self.eyeShowValueState) % 2) == 0; - self.eye1Switch.on = ((1 + self.eyeShowValueState) % 2) == 0; - self.eye2Switch.on = ((2 + self.eyeShowValueState) % 2) == 0; - self.eye3Switch.on = ((3 + self.eyeShowValueState) % 2) == 0; - self.eye4Switch.on = ((4 + self.eyeShowValueState) % 2) == 0; - self.eye5Switch.on = ((5 + self.eyeShowValueState) % 2) == 0; - self.eye6Switch.on = ((6 + self.eyeShowValueState) % 2) == 0; - self.eye7Switch.on = ((7 + self.eyeShowValueState) % 2) == 0; - self.eye8Switch.on = ((8 + self.eyeShowValueState) % 2) == 0; - self.eye9Switch.on = ((9 + self.eyeShowValueState) % 2) == 0; - self.eye10Switch.on = ((10 + self.eyeShowValueState) % 2) == 0; - self.eye11Switch.on = ((11 + self.eyeShowValueState) % 2) == 0; - - self.eyeBrightnessSlider.value = (double)self.eyeShowValueState / 11.0f; - - [self setEyeRing:nil]; -} - -- (IBAction)runEyeAnimation:(id)sender { - WWCommandSet *cmd = [WWCommandSet new]; - WWCommandEyeRing* eye = [[WWCommandEyeRing alloc] initWithAnimation:WW_EYEANIM_FULL_BLINK]; - [cmd setEyeRing:eye]; - [self sendCommandSetToRobots:cmd]; -} -@end diff --git a/iOS/playground/ControlEyeRingViewController.swift b/iOS/playground/ControlEyeRingViewController.swift new file mode 100644 index 0000000..d478cb3 --- /dev/null +++ b/iOS/playground/ControlEyeRingViewController.swift @@ -0,0 +1,105 @@ +// +// ControlEyeRingViewController.swift +// playground +// +// Created by Jelle Alten on 10-11-16. +// Copyright © 2016 Wonder Workshop. All rights reserved. +// + +import Foundation +import UIKit + +class ControlEyeRingViewController: RobotControlViewController { + + @IBOutlet weak var eye0Switch: UISwitch! + @IBOutlet weak var eye1Switch: UISwitch! + @IBOutlet weak var eye2Switch: UISwitch! + @IBOutlet weak var eye3Switch: UISwitch! + @IBOutlet weak var eye4Switch: UISwitch! + @IBOutlet weak var eye5Switch: UISwitch! + @IBOutlet weak var eye6Switch: UISwitch! + @IBOutlet weak var eye7Switch: UISwitch! + @IBOutlet weak var eye8Switch: UISwitch! + @IBOutlet weak var eye9Switch: UISwitch! + @IBOutlet weak var eye10Switch: UISwitch! + @IBOutlet weak var eye11Switch: UISwitch! + + @IBOutlet weak var eyeBrightnessSlider: UISlider! + @IBOutlet weak var eyeShowButton: UIButton! + + private var eyeShowInProgress = false + private var eyeShowTimer = Timer() + private var eyeShowValueState: UInt = 0 + + @IBAction func setEyeRing(_ sender: Any) { + setEyeRing() + } + + @IBAction func setEyeRing() { + + let eyeBitmap = [eye0Switch.isOn, + eye1Switch.isOn, + eye2Switch.isOn, + eye3Switch.isOn, + eye4Switch.isOn, + eye5Switch.isOn, + eye6Switch.isOn, + eye7Switch.isOn, + eye8Switch.isOn, + eye9Switch.isOn, + eye10Switch.isOn, + eye11Switch.isOn] + let cmd = WWCommandSet() + let eyeRing = WWCommandEyeRing(bitmap: eyeBitmap) + eyeRing?.brightness = Double(eyeBrightnessSlider.value) + cmd.setEyeRing(eyeRing) + sendCommandSet(toRobots: cmd) + } + + @IBAction func toggleEyeShow(_ sender: UIButton) { + if eyeShowInProgress { + eyeShowInProgress = false + eyeShowTimer.invalidate() + eyeShowButton.setTitle("Start eye show", for:.normal) + } else { + eyeShowInProgress = true + eyeShowTimer = Timer.scheduledTimer(timeInterval: 0.4, target: self, + selector: #selector(eyeShowTimerValues(timer:)), + userInfo: nil, repeats: true) + eyeShowTimer.fire() + eyeShowButton.setTitle("Stop eye show", for:.normal) + } + + } + + @objc func eyeShowTimerValues(timer: Timer) { + + eyeShowValueState = (eyeShowValueState+1) % 12; // rotate + + eye0Switch.isOn = ((0 + eyeShowValueState) % 2) == 0 + eye1Switch.isOn = ((1 + eyeShowValueState) % 2) == 0 + eye2Switch.isOn = ((2 + eyeShowValueState) % 2) == 0 + eye3Switch.isOn = ((3 + eyeShowValueState) % 2) == 0 + eye4Switch.isOn = ((4 + eyeShowValueState) % 2) == 0 + eye5Switch.isOn = ((5 + eyeShowValueState) % 2) == 0 + eye6Switch.isOn = ((6 + eyeShowValueState) % 2) == 0 + eye7Switch.isOn = ((7 + eyeShowValueState) % 2) == 0 + eye8Switch.isOn = ((8 + eyeShowValueState) % 2) == 0 + eye9Switch.isOn = ((9 + eyeShowValueState) % 2) == 0 + eye10Switch.isOn = ((10 + eyeShowValueState) % 2) == 0 + eye11Switch.isOn = ((11 + eyeShowValueState) % 2) == 0 + + let newValue = Double(eyeShowValueState) / 11.0 + eyeBrightnessSlider.value = Float(newValue) + setEyeRing() + } + + @IBAction func runEyeAnimation(_ sender: Any) { + let cmd = WWCommandSet() + let eye = WWCommandEyeRing(animation: WW_EYEANIM_FULL_BLINK) + cmd.setEyeRing(eye) + sendCommandSet(toRobots: cmd) + + } + +} diff --git a/iOS/playground/ControlHeadViewController.h b/iOS/playground/ControlHeadViewController.h deleted file mode 100644 index 95ff14d..0000000 --- a/iOS/playground/ControlHeadViewController.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// ControlHeadViewController.h -// playground -// -// Created by igor on 11/18/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "RobotControlViewController.h" - -@interface ControlHeadViewController : RobotControlViewController - -- (IBAction) onMiddleBtnTouch:(id)sender; -- (IBAction) onTopBtnTouch:(id)sender; -- (IBAction) onBottomBtnTouch:(id)sender; -- (IBAction) onLeftBtnTouch:(id)sender; -- (IBAction) onRightBtnTouch:(id)sender; - -@end diff --git a/iOS/playground/ControlHeadViewController.m b/iOS/playground/ControlHeadViewController.m deleted file mode 100644 index 8d4c73d..0000000 --- a/iOS/playground/ControlHeadViewController.m +++ /dev/null @@ -1,53 +0,0 @@ -// -// ControlHeadViewController.m -// playground -// -// Created by igor on 11/18/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "ControlHeadViewController.h" - - -@interface ControlHeadViewController () - -@end - -@implementation ControlHeadViewController - -- (void)viewDidLoad { - [super viewDidLoad]; -} - -- (IBAction) onMiddleBtnTouch:(id)sender { - [self updateRobotHeadWithPan:0 andTilt:0]; -} - -- (IBAction) onTopBtnTouch:(id)sender { - [self updateRobotHeadWithPan:0 andTilt:-15]; -} - -- (IBAction) onBottomBtnTouch:(id)sender { - [self updateRobotHeadWithPan:0 andTilt:10]; -} - -- (IBAction) onLeftBtnTouch:(id)sender { - [self updateRobotHeadWithPan:-90 andTilt:0]; -} - -- (IBAction) onRightBtnTouch:(id)sender { - [self updateRobotHeadWithPan:90 andTilt:0]; -} - -- (void) updateRobotHeadWithPan:(float)panDegree andTilt:(float)tiltDegree -{ - WWCommandSet *command = [WWCommandSet new]; - WWCommandHeadPosition *tilt = [[WWCommandHeadPosition alloc] initWithDegree:tiltDegree]; - WWCommandHeadPosition *pan = [[WWCommandHeadPosition alloc] initWithDegree:panDegree]; - [command setHeadPositionTilt:tilt pan:pan]; - - [self sendCommandSetToRobots:command]; -} - - -@end diff --git a/iOS/playground/ControlHeadViewController.swift b/iOS/playground/ControlHeadViewController.swift new file mode 100644 index 0000000..59d52e5 --- /dev/null +++ b/iOS/playground/ControlHeadViewController.swift @@ -0,0 +1,36 @@ +// +// ControlHeadViewController.swift +// playground +// +// Created by Jelle Alten on 10-11-16. +// Copyright © 2016 Wonder Workshop. All rights reserved. +// + +import UIKit + +class ControlHeadViewController: RobotControlViewController { + + @IBAction func onMiddleBtnTouch(_ sender: Any) { + updateRobotHead(pan: 0, tilt: 0) + } + @IBAction func onTopBtnTouch(_ sender: Any) { + updateRobotHead(pan: 0, tilt: -15) + } + @IBAction func onButtomBtnTouch(_ sender: Any) { + updateRobotHead(pan: 0, tilt: 10) + } + @IBAction func onLeftBtnTouch(_ sender: Any) { + updateRobotHead(pan: 90, tilt: 0) + } + @IBAction func onRightBtnTouch(_ sender: Any) { + updateRobotHead(pan: -90, tilt: 0) + } + + private func updateRobotHead(pan panDegree: Float, tilt tiltDegree: Float) { + let command = WWCommandSet() + let tilt = WWCommandHeadPosition(degree: Double(tiltDegree)) + let pan = WWCommandHeadPosition(degree: Double(panDegree)) + command.setHeadPositionTilt(tilt, pan: pan) + sendCommandSet(toRobots: command) + } +} diff --git a/iOS/playground/ControlLightsViewController.h b/iOS/playground/ControlLightsViewController.h deleted file mode 100644 index 4be325b..0000000 --- a/iOS/playground/ControlLightsViewController.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// ControlLightsViewController.h -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "RobotControlViewController.h" - -@interface ControlLightsViewController : RobotControlViewController - -@property (weak, nonatomic) IBOutlet UISlider *leftEarRSlider; -@property (weak, nonatomic) IBOutlet UISlider *leftEarGSlider; -@property (weak, nonatomic) IBOutlet UISlider *leftEarBSlider; - -@property (weak, nonatomic) IBOutlet UISlider *chestRSlider; -@property (weak, nonatomic) IBOutlet UISlider *chestGSlider; -@property (weak, nonatomic) IBOutlet UISlider *chestBSlider; - -@property (weak, nonatomic) IBOutlet UISlider *rightEarRSlider; -@property (weak, nonatomic) IBOutlet UISlider *rightEarGSlider; -@property (weak, nonatomic) IBOutlet UISlider *rightEarBSlider; - -@property (weak, nonatomic) IBOutlet UISlider *mainButtonMonoSlider; - -@property (weak, nonatomic) IBOutlet UISlider *backMonoSlider; - -@property (weak, nonatomic) IBOutlet UIButton *lightShowButton; - -- (IBAction)setRGBLights:(id)sender; -- (IBAction)toggleLightShow:(id)sender; - -@end diff --git a/iOS/playground/ControlLightsViewController.m b/iOS/playground/ControlLightsViewController.m deleted file mode 100644 index 22d2ee8..0000000 --- a/iOS/playground/ControlLightsViewController.m +++ /dev/null @@ -1,100 +0,0 @@ -// -// ControlLightsViewController.m -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "ControlLightsViewController.h" - -@interface ControlLightsViewController () - -@property (nonatomic) BOOL lightShowInProgress; -@property (nonatomic, strong) NSTimer *lightShowTimer; -@property (nonatomic) NSUInteger lightShowValueState; - -- (void) lightShowTimerValues:(NSTimer *)timer; - -@end - -@implementation ControlLightsViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - // Do any additional setup after loading the view. -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - -- (IBAction)setRGBLights:(id)sender { - WWCommandSet *cmd = [WWCommandSet new]; - [cmd setLeftEarLight:[[WWCommandLightRGB alloc] initWithRed:self.leftEarRSlider.value green:self.leftEarGSlider.value blue:self.leftEarBSlider.value]]; - - [cmd setRightEarLight:[[WWCommandLightRGB alloc] initWithRed:self.rightEarRSlider.value green:self.rightEarGSlider.value blue:self.rightEarBSlider.value]]; - - [cmd setChestLight:[[WWCommandLightRGB alloc] initWithRed:self.chestRSlider.value green:self.chestGSlider.value blue:self.chestBSlider.value]]; - [cmd setEyeLight:[[WWCommandLightRGB alloc] initWithRed:self.chestRSlider.value green:self.chestGSlider.value blue:self.chestBSlider.value]]; - - [cmd setMainButtonLight:[[WWCommandLightMono alloc] initWithBrightness:self.mainButtonMonoSlider.value]]; - - [cmd setTailLight:[[WWCommandLightMono alloc] initWithBrightness:self.backMonoSlider.value]]; - - [self sendCommandSetToRobots:cmd]; -} - -- (IBAction)toggleLightShow:(id)sender { - if (self.lightShowInProgress) { - self.lightShowInProgress = NO; - [self.lightShowTimer invalidate]; - [self.lightShowButton setTitle:@"Start light show" forState:UIControlStateNormal]; - } - else { - self.lightShowInProgress = YES; - self.lightShowTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(lightShowTimerValues:) userInfo:nil repeats:YES]; - [self.lightShowTimer fire]; - [self.lightShowButton setTitle:@"Stop light show" forState:UIControlStateNormal]; - } -} - -- (void) lightShowTimerValues:(NSTimer *)timer { - double r, g, b, mono; - - self.lightShowValueState = (self.lightShowValueState+1) % 4; // rotate - switch (self.lightShowValueState) { - case 0: - r = 1.0; g = 0; b = 0; mono = 1.0; - break; - case 1: - r = 0; g = 1.0; b = 0; mono = 0.5; - break; - case 2: - r = 0; g = 0; b = 1.0; mono = 0; - break; - case 3: - r = 0.5; g = 0.5; b = 0.5; mono = 0.75; - break; - default: - r = 0; g = 0; b = 0; mono = 0; - break; - } - - self.leftEarRSlider.value = r; - self.leftEarGSlider.value = g; - self.leftEarBSlider.value = b; - self.rightEarRSlider.value = r; - self.rightEarGSlider.value = g; - self.rightEarBSlider.value = b; - self.chestRSlider.value = r; - self.chestGSlider.value = g; - self.chestBSlider.value = b; - self.mainButtonMonoSlider.value = mono; - self.backMonoSlider.value = mono; - - [self setRGBLights:nil]; -} - -@end diff --git a/iOS/playground/ControlLightsViewController.swift b/iOS/playground/ControlLightsViewController.swift new file mode 100644 index 0000000..5f322cc --- /dev/null +++ b/iOS/playground/ControlLightsViewController.swift @@ -0,0 +1,120 @@ +// +// ControlLightsViewController1.swift +// playground +// +// Created by Jelle Alten on 10-11-16. +// Copyright © 2016 Wonder Workshop. All rights reserved. +// + +import UIKit + +class ControlLightsViewController: RobotControlViewController { + + @IBOutlet weak var leftEarRSlider: UISlider! + @IBOutlet weak var leftEarGSlider: UISlider! + @IBOutlet weak var leftEarBSlider: UISlider! + + @IBOutlet weak var chestRSlider: UISlider! + @IBOutlet weak var chestGSlider: UISlider! + @IBOutlet weak var chestBSlider: UISlider! + + @IBOutlet weak var rightEarRSlider: UISlider! + @IBOutlet weak var rightEarGSlider: UISlider! + @IBOutlet weak var rightEarBSlider: UISlider! + + @IBOutlet weak var mainButtonMonoSlider: UISlider! + + @IBOutlet weak var backMonoSlider: UISlider! + + @IBOutlet weak var lightShowButton: UIButton! + + private var lightShowInProgress = false + private var lightShowTimer = Timer() + private var lightShowValueState: UInt = 0 + + @IBAction func setRGBLights(_ sender: UISlider) { + setRGBLights() + } + + @IBAction func setRGBLights() { + + let cmd = WWCommandSet() + cmd.setLeftEarLight(WWCommandLightRGB(red: Double(leftEarRSlider.value), + green: Double(leftEarGSlider.value), + blue: Double(leftEarBSlider.value))) + cmd.setRightEarLight(WWCommandLightRGB(red: Double(rightEarRSlider.value), + green: Double(rightEarGSlider.value), + blue: Double(rightEarBSlider.value))) + + cmd.setChestLight(WWCommandLightRGB(red: Double(chestRSlider.value), + green: Double(chestGSlider.value), + blue: Double(chestBSlider.value))) + + cmd.setChestLight(WWCommandLightRGB(red: Double(chestRSlider.value), + green: Double(chestGSlider.value), + blue: Double(chestBSlider.value))) + + cmd.setEyeLight(WWCommandLightRGB(red: Double(chestRSlider.value), + green: Double(chestGSlider.value), + blue: Double(chestBSlider.value))) + + cmd.setMainButtonLight(WWCommandLightMono(brightness: Double(mainButtonMonoSlider.value))) + + cmd.setTailLight(WWCommandLightMono(brightness: Double(backMonoSlider.value))) + sendCommandSet(toRobots:cmd) + } + @IBAction func toggleLightShow(_ sender: UIButton) { + if lightShowInProgress { + lightShowInProgress = false + lightShowTimer.invalidate() + lightShowButton.setTitle("Start light show", for:.normal) + } else { + lightShowInProgress = true + lightShowTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, + selector: #selector(self.lightShowTimerValues(timer:)), + userInfo: nil, repeats: true) + lightShowTimer.fire() + lightShowButton.setTitle("Stop light show", for:.normal) + } + + } + + @objc func lightShowTimerValues(timer: Timer) { + + var r, g, b, mono: Float + + lightShowValueState = (lightShowValueState+1) % 4; // rotate + switch lightShowValueState { + case 0: + r = 1.0; g = 0; b = 0; mono = 1.0 + break + case 1: + r = 0; g = 1.0; b = 0; mono = 0.5 + break + case 2: + r = 0; g = 0; b = 1.0; mono = 0 + break + case 3: + r = 0.5; g = 0.5; b = 0.5; mono = 0.75 + break + default: + r = 0; g = 0; b = 0; mono = 0 + break + } + + leftEarRSlider.value = r + leftEarGSlider.value = g + leftEarBSlider.value = b + rightEarRSlider.value = r + rightEarGSlider.value = g + rightEarBSlider.value = b + chestRSlider.value = r + chestGSlider.value = g + chestBSlider.value = b + mainButtonMonoSlider.value = mono + backMonoSlider.value = mono + + setRGBLights() + } + +} diff --git a/iOS/playground/ControlSensorsViewController.h b/iOS/playground/ControlSensorsViewController.h deleted file mode 100644 index 6dd8d72..0000000 --- a/iOS/playground/ControlSensorsViewController.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// ControlSensorsViewController.h -// playground -// -// Created by Kevin Liang on 11/18/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "RobotControlViewController.h" - -@interface ControlSensorsViewController : RobotControlViewController - -@property (weak, nonatomic) IBOutlet UITableView *dataTableView; - -@end diff --git a/iOS/playground/ControlSensorsViewController.m b/iOS/playground/ControlSensorsViewController.m deleted file mode 100644 index f0f1bc7..0000000 --- a/iOS/playground/ControlSensorsViewController.m +++ /dev/null @@ -1,136 +0,0 @@ -// -// ControlSensorsViewController.m -// playground -// -// Created by Kevin Liang on 11/18/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "ControlSensorsViewController.h" - -@interface ControlSensorsViewController () - -@property (nonatomic, strong) NSTimer *refreshDataTimer; - -- (void) refreshSensorData:(NSTimer *)timer; - -@end - -#define RADIANS_TO_DEGREES(radians) ((radians) * (180.0 / M_PI)) - -@implementation ControlSensorsViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - // Do any additional setup after loading the view. - - self.dataTableView.rowHeight = 200; -} - -- (void) viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - self.refreshDataTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(refreshSensorData:) userInfo:nil repeats:YES]; -} - -- (void) viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; - - [self.refreshDataTimer invalidate]; -} - -- (void) refreshSensorData:(NSTimer *)timer { - [self.dataTableView reloadData]; -} - -# pragma mark - table view -- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { - return 1; -} - -- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.connectedRobots.count; -} - -- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"DataCell" forIndexPath:indexPath]; - - WWRobot *robot = (WWRobot *)self.connectedRobots[indexPath.row]; - WWSensorSet *sensorData = robot.history.currentState; - - NSMutableString *detail = [NSMutableString stringWithCapacity:2000]; - [detail appendFormat:@"Name: %@\n", robot.name]; - - //buttons - WWSensorButton *SButtonMain = (WWSensorButton *)[sensorData sensorForIndex:WW_SENSOR_BUTTON_MAIN]; - WWSensorButton *SButtonOne = (WWSensorButton *)[sensorData sensorForIndex:WW_SENSOR_BUTTON_1]; - WWSensorButton *SButtonTwo = (WWSensorButton *)[sensorData sensorForIndex:WW_SENSOR_BUTTON_2]; - WWSensorButton *SButtonThree = (WWSensorButton *)[sensorData sensorForIndex:WW_SENSOR_BUTTON_3]; - [detail appendFormat:@"Btn Main: %@, ", SButtonMain.isPressed? @"true": @"false"]; - [detail appendFormat:@"Btn 1: %@, ", SButtonOne.isPressed? @"true": @"false"]; - [detail appendFormat:@"Btn 2: %@, ", SButtonTwo.isPressed? @"true": @"false"]; - [detail appendFormat:@"Btn 3: %@", SButtonThree.isPressed? @"true": @"false"]; - [detail appendFormat:@"\n"]; - - //accelerometer - WWSensorAccelerometer *SAcc = (WWSensorAccelerometer *)[sensorData sensorForIndex:WW_SENSOR_ACCELEROMETER]; - [detail appendString:@"Accel: "]; - [detail appendFormat:@"X: %3.2f, ", SAcc ? SAcc.x : NAN]; - [detail appendFormat:@"Y: %3.2f, ", SAcc ? SAcc.y : NAN]; - [detail appendFormat:@"Z: %3.2f", SAcc ? SAcc.z : NAN]; - [detail appendFormat:@"\n"]; - - WWSensorMicrophone *SMic = (WWSensorMicrophone *)[sensorData sensorForIndex:WW_SENSOR_MICROPHONE]; - [detail appendFormat:@"Microphone: "]; - [detail appendFormat:@"Amplitude: %03f, ", SMic ? SMic.amplitude : NAN]; - [detail appendFormat:@"Angle: %3.2f degrees", RADIANS_TO_DEGREES(SMic ? SMic.triangulationAngle : NAN)]; - [detail appendFormat:@"\n"]; - - if (robot.robotType == WW_ROBOT_DASH) { - //distance sensors - WWSensorDistance *SDistFLF = (WWSensorDistance *)[sensorData sensorForIndex:WW_SENSOR_DISTANCE_FRONT_RIGHT_FACING]; - WWSensorDistance *SDistFRF = (WWSensorDistance *)[sensorData sensorForIndex:WW_SENSOR_DISTANCE_FRONT_LEFT_FACING]; - WWSensorDistance *SDistRRF = (WWSensorDistance *)[sensorData sensorForIndex:WW_SENSOR_DISTANCE_BACK]; - [detail appendFormat:@"Distance: "]; - [detail appendFormat:@"Left-Facing: %2.2f, ", SDistFLF ? SDistFLF.reflectance : NAN]; - [detail appendFormat:@"Dist Right-Facing: %2.2f, ", SDistFRF ? SDistFRF.reflectance : NAN]; - [detail appendFormat:@"Dist Tail: %2.2f", SDistRRF ? SDistRRF.reflectance : NAN]; - [detail appendFormat:@"\n"]; - - //gyro - WWSensorGyroscope *SGyro = (WWSensorGyroscope *)[sensorData sensorForIndex:WW_SENSOR_GYROSCOPE]; - [detail appendString:@"Gyro: "]; - [detail appendFormat:@"yaw: %3.2f, ", SGyro ? SGyro.yaw : NAN]; - [detail appendFormat:@"pitch: %3.2f, ", SGyro ? SGyro.pitch : NAN]; - [detail appendFormat:@"roll: %3.2f", SGyro ? SGyro.roll : NAN]; - [detail appendFormat:@"\n"]; - - //head - WWSensorHeadPosition *SMotorServoHeadPan = (WWSensorHeadPosition *)[sensorData sensorForIndex:WW_SENSOR_HEAD_POSITION_PAN]; - WWSensorHeadPosition *SMotorServoHeadTilt = (WWSensorHeadPosition *)[sensorData sensorForIndex:WW_SENSOR_HEAD_POSITION_TILT]; - [detail appendString:@"Head: "]; - [detail appendFormat:@"Pan: %3.2f degrees, ", RADIANS_TO_DEGREES(SMotorServoHeadPan ? SMotorServoHeadPan.radians : NAN)]; - [detail appendFormat:@"Tilt: %3.2f degrees", RADIANS_TO_DEGREES(SMotorServoHeadTilt ? SMotorServoHeadTilt.radians : NAN)]; - [detail appendFormat:@"\n"]; - - //encoder - WWSensorEncoder *SEncoderLW = (WWSensorEncoder *)[sensorData sensorForIndex:WW_SENSOR_ENCODER_LEFT_WHEEL]; - WWSensorEncoder *SEncoderRW = (WWSensorEncoder *)[sensorData sensorForIndex:WW_SENSOR_ENCODER_RIGHT_WHEEL]; - [detail appendString:@"Encoder: "]; - [detail appendFormat:@"Left: %4.2f cm, ", SEncoderLW? SEncoderLW.distance: NAN]; - [detail appendFormat:@"Right: %4.2f cm", SEncoderLW? SEncoderRW.distance: NAN]; - [detail appendFormat:@"\n"]; - } - - cell.textLabel.text = detail; - //[cell.textLabel sizeToFit]; - return cell; -} - - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - -@end diff --git a/iOS/playground/ControlSensorsViewController.swift b/iOS/playground/ControlSensorsViewController.swift new file mode 100644 index 0000000..5a71242 --- /dev/null +++ b/iOS/playground/ControlSensorsViewController.swift @@ -0,0 +1,154 @@ +// +// ControlSensorsViewController.swift +// playground +// +// Created by Jelle Alten on 10-11-16. +// Copyright © 2016 Wonder Workshop. All rights reserved. +// + +import UIKit + +// Declare radiansToDegrees function +func radiansToDegrees (radians: Double) -> Double { + return radians * 180 / M_PI +} + +class ControlSensorsViewController: RobotControlViewController { + + private var refreshDataTimer = Timer() + + @IBOutlet weak var dataTableView: UITableView! + + override func viewDidLoad() { + super.viewDidLoad() + dataTableView.rowHeight = 200 + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + refreshDataTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, + selector: #selector(self.refreshSensorData(timer:)), + userInfo: nil, repeats: true) + + } + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + refreshDataTimer.invalidate() + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + func refreshSensorData(timer: Timer) { + dataTableView.reloadData() + } + +} + +extension ControlSensorsViewController: UITableViewDataSource { + + func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return connectedRobots.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "DataCell", for: indexPath) + let robot = connectedRobots[indexPath.row] + let sensorData = robot.history.currentState() as WWSensorSet + + var detail = String() + detail.append("Name: \(robot.name)\n") + + if let button = sensorData.sensor(forIndex: .SENSOR_BUTTON_MAIN) as? WWSensorButton { + detail.append("Btn Main: \(button.isPressed ? "true": "false"), ") + } + if let button = sensorData.sensor(forIndex: .SENSOR_BUTTON_1) as? WWSensorButton { + detail.append("Btn 1: \(button.isPressed ? "true": "false"), ") + } + if let button = sensorData.sensor(forIndex: .SENSOR_BUTTON_2) as? WWSensorButton { + detail.append("Btn 2: \(button.isPressed ? "true": "false"), ") + } + if let button = sensorData.sensor(forIndex: .SENSOR_BUTTON_3) as? WWSensorButton { + detail.append("Btn 3: \(button.isPressed ? "true": "false")") + } + detail.append("\n") + + let sAcc = sensorData.sensor(forIndex: .SENSOR_ACCELEROMETER) as? WWSensorAccelerometer + //accelerometer + detail.append("Accel: ") + if let sAcc = sAcc { + detail = detail.appendingFormat("X: %3.2f, ", sAcc.x) + detail = detail.appendingFormat("Y: %3.2f, ", sAcc.y) + detail = detail.appendingFormat("Z: %3.2f", sAcc.z) + } + detail.append("\n") + + let sMic = sensorData.sensor(forIndex: .SENSOR_MICROPHONE) as? WWSensorMicrophone + detail.append("Microphone: ") + if let sMic = sMic { + detail = detail.appendingFormat("Amplitude: %03f, ", sMic.amplitude) + let degrees = radiansToDegrees(radians: sMic.triangulationAngle) + detail = detail.appendingFormat("Angle: %3.2f degrees", degrees) + } + detail.append("\n") + + if robot.robotType == .ROBOT_DASH { + detail.append(getDashDetail(sensorData:sensorData)) + } + + cell.textLabel?.text = detail + //[cell.textLabel sizeToFit) + return cell + } + + func getDashDetail(sensorData: WWSensorSet) -> String { + var detail = "" + + //distance sensors + let sDistFLF = sensorData.sensor(forIndex: .SENSOR_DISTANCE_FRONT_RIGHT_FACING) as? WWSensorDistance + let sDistFRF = sensorData.sensor(forIndex: .SENSOR_DISTANCE_FRONT_LEFT_FACING) as? WWSensorDistance + let sDistRRF = sensorData.sensor(forIndex: .SENSOR_DISTANCE_BACK) as? WWSensorDistance + detail.append("Distance: ") + if let sDistFLF = sDistFLF, let sDistFRF = sDistFRF, let sDistRRF = sDistRRF { + detail = detail.appendingFormat("Left-Facing: %2.2f, ", sDistFLF.reflectance) + detail = detail.appendingFormat("Dist Right-Facing: %2.2f, ", sDistFRF.reflectance) + detail = detail.appendingFormat("Dist Tail: %2.2f", sDistRRF.reflectance) + } + detail.append("\n") + + //gyro + detail.append("Gyro: ") + if let sGyro = sensorData.sensor(forIndex: .SENSOR_GYROSCOPE) as? WWSensorGyroscope { + detail = detail.appendingFormat("yaw: %3.2f, ", sGyro.yaw) + detail = detail.appendingFormat("pitch: %3.2f, ", sGyro.pitch) + detail = detail.appendingFormat("roll: %3.2f", sGyro.roll) + } + detail.append("\n") + + //head + detail.append("Head: ") + if let sMotorServoHeadPan = sensorData.sensor(forIndex: .SENSOR_HEAD_POSITION_PAN) as? WWSensorHeadPosition, + let sMotorServoHeadTilt = sensorData.sensor(forIndex: .SENSOR_HEAD_POSITION_TILT) as? WWSensorHeadPosition { + detail = detail.appendingFormat("Pan: %3.2f degrees, ", sMotorServoHeadPan.degrees) + detail = detail.appendingFormat("Tilt: %3.2f degrees", sMotorServoHeadTilt.degrees) + } + detail.append("\n") + + //encoder + detail.append("Encoder: ") + if let sEncoderLW = sensorData.sensor(forIndex: .SENSOR_ENCODER_LEFT_WHEEL) as? WWSensorEncoder, + let sEncoderRW = sensorData.sensor(forIndex: .SENSOR_ENCODER_RIGHT_WHEEL) as? WWSensorEncoder { + + detail = detail.appendingFormat("Left: %4.2f cm, ", sEncoderLW.distance) + detail = detail.appendingFormat("Right: %4.2f cm", sEncoderRW.distance) + } + detail.append("\n") + return detail + } + +} diff --git a/iOS/playground/ControlSoundViewController.h b/iOS/playground/ControlSoundViewController.h deleted file mode 100644 index fddeb5e..0000000 --- a/iOS/playground/ControlSoundViewController.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// ControlSoundViewController.h -// playground -// -// Created by Kevin Liang on 11/18/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "RobotControlViewController.h" - -@interface ControlSoundViewController : RobotControlViewController - -@property (weak, nonatomic) IBOutlet UISlider *volumeSlider; - -- (IBAction)playSoundPressed:(id)sender; - -@end diff --git a/iOS/playground/ControlSoundViewController.m b/iOS/playground/ControlSoundViewController.m deleted file mode 100644 index 09c2f3c..0000000 --- a/iOS/playground/ControlSoundViewController.m +++ /dev/null @@ -1,88 +0,0 @@ -// -// ControlSoundViewController.m -// playground -// -// Created by Kevin Liang on 11/18/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "ControlSoundViewController.h" - -@interface ControlSoundViewController () - -@property (nonatomic) float volume; -@property (nonatomic, strong) WWEvent *mainButtonTouchUp; -@property (nonatomic, strong) WWEvent *headPanPositionChanged; - -@end - -@implementation ControlSoundViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - // Do any additional setup after loading the view. - - self.volume = (WW_VOLUME_MAX - WW_VOLUME_MUTE) / 2.0; - self.mainButtonTouchUp = [WWEventToolbelt buttonOnUp:[NSNumber numberWithUnsignedInteger:WW_SENSOR_BUTTON_MAIN]]; - - self.headPanPositionChanged = [[WWEvent alloc] initWithShouldAlertBlock:^BOOL(WWEvent *event, WWSensorHistory *history) { - WWSensorHeadPosition *currHeadPan = (WWSensorHeadPosition *)[history.currentState sensorForIndex:WW_SENSOR_HEAD_POSITION_PAN]; - WWSensorHeadPosition *prevHeadPan300ms = (WWSensorHeadPosition *)[[history pastStateAtTimeAgo:0.3] sensorForIndex:WW_SENSOR_HEAD_POSITION_PAN]; - - return fabsf(currHeadPan.radians - prevHeadPan300ms.radians) > 0.05; // allow for some errors - } identifier:@"head"]; -} - -- (void) setVolume:(float)volume { - _volume = volume; - self.volumeSlider.value = _volume; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - self.volumeSlider.value = self.volume; - - for (WWRobot *robot in self.connectedRobots) { - [robot addEvent:self.mainButtonTouchUp]; - [robot addEvent:self.headPanPositionChanged]; - } -} - -- (void)viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; - - for (WWRobot *robot in self.connectedRobots) { - [robot removeAllEvents]; - } -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - -- (IBAction)playSoundPressed:(id)sender { - WWCommandSet *speakerCommand = [WWCommandSet new]; - WWCommandSpeaker *speaker = [[WWCommandSpeaker alloc] initWithDefaultSound:WW_SOUNDFILE_HI]; - speaker.volume = self.volume; - [speakerCommand setSound:speaker]; - - [self sendCommandSetToRobots:speakerCommand]; -} - -#pragma mark - WWRobotDelegate -- (void) robot:(WWRobot *)robot eventsTriggered:(NSArray *)events { - - for (WWEvent *event in events) { - if ([self.mainButtonTouchUp isEqual:event]) { - self.volume = (self.volume == WW_VOLUME_MUTE) ? WW_VOLUME_MAX : WW_VOLUME_MUTE; - } - else if ([event hasIdentifier:@"head"]) { - WWSensorHeadPosition *headPan = (WWSensorHeadPosition *)[robot.history.currentState sensorForIndex:WW_SENSOR_HEAD_POSITION_PAN]; - self.volume = headPan.radians / -2.0f; - } - } -} - -@end diff --git a/iOS/playground/ControlSoundViewController.swift b/iOS/playground/ControlSoundViewController.swift new file mode 100644 index 0000000..604b85d --- /dev/null +++ b/iOS/playground/ControlSoundViewController.swift @@ -0,0 +1,91 @@ +// +// ControlSoundViewController.swift +// playground +// +// Created by Jelle Alten on 10-11-16. +// Copyright © 2016 Wonder Workshop. All rights reserved. +// + +import UIKit + +class ControlSoundViewController: RobotControlViewController { + + private var _volume: Double = (WW_VOLUME_MAX - WW_VOLUME_MUTE) / 2.0 + var volume: Double { + set { + _volume = newValue + volumeSlider.value = Float(newValue) + } + get { + return _volume + } + } + var mainButtonTouchUp: WWEvent + var headPanPositionChanged: WWEvent + + @IBOutlet weak var volumeSlider: UISlider! + + required init?(coder aDecoder: NSCoder) { + + let buttonNumber = NSNumber(value:1000) + mainButtonTouchUp = WWEventToolbelt.button(onUp: buttonNumber) + headPanPositionChanged = WWEvent(shouldAlert: { (event, history) -> Bool in + guard let history = history, let state = history.currentState(), + let currHeadPan = state.sensor(forIndex:.SENSOR_HEAD_POSITION_PAN) as? WWSensorHeadPosition, + let pastHeadPanSensor = history.pastState(atTimeAgo:0.3).sensor(forIndex:.SENSOR_HEAD_POSITION_PAN), + let prevHeadPan300ms = pastHeadPanSensor as? WWSensorHeadPosition else { + return false + } + let diff = currHeadPan.radians - prevHeadPan300ms.radians + return fabs(diff) > 0.05 // allow for some errors + + }, identifier: "head") + + super.init(coder: aDecoder) + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + volumeSlider.value = Float(volume) + + for robot in connectedRobots { + robot.add(mainButtonTouchUp) + robot.add(headPanPositionChanged) + } + } + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + for robot in connectedRobots { + robot.removeAllEvents() + } + } + + @IBAction func playSoundPressed(_ sender: Any) { + let speakerCommand = WWCommandSet() + if let speaker = WWCommandSpeaker(defaultSound:WW_SOUNDFILE_HI) { + speaker.volume = Float(volume) + speakerCommand.setSound(speaker) + sendCommandSet(toRobots: speakerCommand) + } + } +} + +// MARK: WWRobotObserver +extension ControlSoundViewController { + func robot(_ robot: WWRobot!, eventsTriggered events: [Any]!) { + guard let wwEvents = events as? [WWEvent] else { + return + } + for event in wwEvents as [WWEvent] { + if mainButtonTouchUp == event { + self.volume = (volume == WW_VOLUME_MUTE) ? WW_VOLUME_MAX: WW_VOLUME_MUTE + } else if event.hasIdentifier("head") { + if let sensor = robot.history.currentState().sensor(forIndex:.SENSOR_HEAD_POSITION_PAN), + let headPan = sensor as? WWSensorHeadPosition { + volume = headPan.radians / -2.0 + } + } + } + } +} diff --git a/iOS/playground/CoordinatesHelper.swift b/iOS/playground/CoordinatesHelper.swift new file mode 100644 index 0000000..3c6835c --- /dev/null +++ b/iOS/playground/CoordinatesHelper.swift @@ -0,0 +1,36 @@ +// +// helper.swift +// playground +// +// Created by Jelle Alten on 11-11-16. +// Copyright © 2016 Wonder Workshop. All rights reserved. +// + +import Foundation +import UIKit + +func clamp(_ input: CGFloat, _ min: CGFloat, _ max: CGFloat) -> CGFloat { + let t = input < min ? min: input + return t > max ? max: t +} + +func lerp(_ min: CGFloat, _ max: CGFloat, _ dist: CGFloat) -> CGFloat { + return min + (max - min) * dist +} + +func getDistance(point1: CGPoint, point2: CGPoint) -> Float { + return hypotf(Float(point1.x - point2.x), Float(point1.y - point2.y)) +} + +// translate from old coordinate system into new one +func normalizeValueToNewRange(_ value: Float, + _ srcMin: Float, _ srcMax: Float, + _ dstMin: Float, _ dstMax: Float) -> Float { + return ( value - srcMin ) / ( srcMax - srcMin ) * ( dstMax - dstMin ) + dstMin +} + +func lerpPoints(min: CGPoint, max: CGPoint, dist: Double) -> CGPoint { + let result = CGPoint(x: lerp(min.x, max.x, CGFloat(dist)), + y: lerp(min.y, max.y, CGFloat(dist)) ) + return result +} diff --git a/iOS/playground/Images.xcassets/AppIcon.appiconset/Contents.json b/iOS/playground/Images.xcassets/AppIcon.appiconset/Contents.json index 36d2c80..1d060ed 100644 --- a/iOS/playground/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/iOS/playground/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,5 +1,15 @@ { "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "29x29", @@ -30,6 +40,16 @@ "size" : "60x60", "scale" : "3x" }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, { "idiom" : "ipad", "size" : "29x29", @@ -59,6 +79,11 @@ "idiom" : "ipad", "size" : "76x76", "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" } ], "info" : { diff --git a/iOS/playground/JoystickView.h b/iOS/playground/JoystickView.h deleted file mode 100755 index 152b38c..0000000 --- a/iOS/playground/JoystickView.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// JoystickView.h -// RobotControl -// -// Created by igor on 2/24/14. -// Copyright (c) 2014 igor. All rights reserved. -// - -#import - -// joystick dot -#define DOTSIZE 90 -#define DOTSIZE_HALF (DOTSIZE / 2) - -typedef enum { - DRIVE_JOYSTICK, - HEAD_JOYSTICK -} JoystickType; - - -@protocol JoystickDelegate -@optional -- (void) onJoystickMoved; -- (void) onJoystickSoftReleased; -- (void) onJoystickReleased; -- (CGRect) joystickBounds; -- (float) joystickSoftReturnDuration; // max time for "return center" method which is called after user releases joystick -@end - -@interface JoystickView : UIView -{ - CGPoint _center; -} - -@property (nonatomic, weak) IBOutlet id joystickDelegate; -@property (nonatomic) CGPoint dotPos; -@property (nonatomic, strong) UIImageView *draggerImgView; -@property (nonatomic, assign) JoystickType type; -- (float) getX; /* returns relative position [-1 : 1] */ -- (float) getY; - -- (void) enforceJoystickBound:(CGPoint *)point; -- (void) updateDraggerImage; -- (void) returnNow; - -@end - - -// help methods - -static inline double clamp(double d, double min, double max) { - const double t = d < min ? min : d; - return t > max ? max : t; -} - -static inline double lerp(double min, double max, double T) -{ - return min + (max - min) * T; -} - -static inline float getDistance(CGPoint p1, CGPoint p2) -{ - return hypotf(p1.x - p2.x, p1.y - p2.y); -} - -// translate from old coordinate system into new one -static inline float normalizeValueToNewRange(float value, float src_min, float src_max, float dst_min, float dst_max) -{ - return ( value - src_min ) / ( src_max - src_min ) * ( dst_max - dst_min ) + dst_min; -} - -static inline CGPoint lerpPoints(CGPoint min, CGPoint max, double T) -{ - CGPoint result; - result.x = lerp(min.x, max.x, T); - result.y = lerp(min.y, max.y, T); - return result; -} - diff --git a/iOS/playground/JoystickView.m b/iOS/playground/JoystickView.m deleted file mode 100755 index 716b70e..0000000 --- a/iOS/playground/JoystickView.m +++ /dev/null @@ -1,205 +0,0 @@ -// -// JoystickView.m -// RobotControl -// -// Created by igor on 2/24/14. -// Copyright (c) 2014 igor. All rights reserved. -// - -#import "JoystickView.h" - -#define TIMER_RETURN_UPDATE_RATE 30.0 // delegates calls update rate ( affects robot update state ) - - -@interface JoystickView () - -@property (nonatomic, strong) NSTimer *returnTimer; -@property (nonatomic) float currentReturnRatio; -@property (nonatomic) float returnTime; - -@end - -@implementation JoystickView -#define DRIVE_DRAGGER_IMAGE @"RC_drive_joystick" -#define HEAD_DRAGGER_IMAGE @"RC_head_joystick" - -- (id) initWithCoder:(NSCoder *)aDecoder -{ - self = [super initWithCoder:aDecoder]; - if(self) { - [self commonInit]; - } - return self; -} - -- (id) initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - if (self) { - [self commonInit]; - } - return self; -} - -- (void) commonInit -{ - self.contentMode = UIViewContentModeScaleAspectFit; - self.autoresizingMask = 0; - self.userInteractionEnabled = YES; -} - -- (void) layoutSubviews -{ - [super layoutSubviews]; - - _center = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2); - _dotPos = _center; - [self updateDraggerPosition]; -} - -#pragma mark Joystick Layout -- (void) updateDraggerImage -{ - NSString *imgName; - if (self.type == DRIVE_JOYSTICK) { - imgName = DRIVE_DRAGGER_IMAGE; - } else { - imgName = HEAD_DRAGGER_IMAGE; - } - - UIImage *img = [UIImage imageNamed:imgName]; - self.draggerImgView = [[UIImageView alloc] initWithImage:img]; - self.draggerImgView.frame = CGRectMake(0, 0, DOTSIZE, DOTSIZE); - self.draggerImgView.center = self.dotPos; - - [self addSubview:self.draggerImgView]; -} - -// forbid the joystick dot going out of circle -- (void) enforceJoystickBound:(CGPoint *)point -{ - // clamp - if ([_joystickDelegate respondsToSelector:@selector(joystickBounds)]) { - CGRect bounds = [_joystickDelegate joystickBounds]; - point->x = clamp(point->x, bounds.origin.x, bounds.size.width); - point->y = clamp(point->y, bounds.origin.y, bounds.size.height); - } - return; -} - -#pragma mark Handle touches - -- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event -{ - [self.returnTimer invalidate]; - self.currentReturnRatio = 0; - [self.draggerImgView.layer removeAllAnimations]; -} - -- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event -{ - BOOL shouldReturnSoflty = [self.joystickDelegate respondsToSelector:@selector(joystickSoftReturnDuration)]; - - if (shouldReturnSoflty) { - if ([self.joystickDelegate respondsToSelector:@selector(onJoystickSoftReleased)]) { - [self.joystickDelegate onJoystickSoftReleased]; - } - [self returnJoystickToCenter]; - } else { - [self returnNow]; - [self.joystickDelegate onJoystickReleased]; - } -} - -- (void) returnNow -{ - if (self.returnTimer) { - [self.returnTimer invalidate]; - self.returnTimer = nil; - } - - self.dotPos = _center; - [self updateDraggerPosition]; -} - -- (void) returnJoystickToCenter -{ - float dist = getDistance(_center, _dotPos); - if (dist < 0.1) { - [self returnNow]; - return; - } - - self.returnTime = [self.joystickDelegate joystickSoftReturnDuration]; - self.returnTime *= dist / CGRectGetWidth(self.bounds); - - // timer will update robot with new joystick values while is being animated - self.returnTimer = [NSTimer scheduledTimerWithTimeInterval:(self.returnTime / TIMER_RETURN_UPDATE_RATE) target:self selector:@selector(updateReturnJoystick) userInfo:nil repeats:YES]; - - // animate soft return - [UIView animateWithDuration:self.returnTime animations:^{ - self.draggerImgView.center = _center; - }]; -} - -- (void) updateReturnJoystick -{ - if (_currentReturnRatio >= 1) { - self.dotPos = _center; - - // means we have returned it to the center - if ([_joystickDelegate respondsToSelector:@selector(onJoystickReleased)]) { - [_joystickDelegate onJoystickReleased]; - } - // clean - [self.returnTimer invalidate]; - self.returnTimer = nil; - _currentReturnRatio = 0; - } else { - _currentReturnRatio += (self.returnTime / TIMER_RETURN_UPDATE_RATE); - - if ([_joystickDelegate respondsToSelector:@selector(onJoystickMoved)]) { - [_joystickDelegate onJoystickMoved]; - } - - self.dotPos = lerpPoints(_dotPos, _center, _currentReturnRatio * 0.4); - } -} - -- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event -{ - CGPoint newPos = [[touches anyObject] locationInView: self]; - [self enforceJoystickBound:&newPos]; - - self.dotPos = newPos; - [self updateDraggerPosition]; -} - -- (void) setDotPos:(CGPoint)dotPos -{ - _dotPos = dotPos; - if ([_joystickDelegate respondsToSelector:@selector(onJoystickMoved)]) { - [_joystickDelegate onJoystickMoved]; - } -} - --(void) updateDraggerPosition -{ - self.draggerImgView.center = _dotPos; -} - -#pragma mark Joystick getters and setters - -// methods to be over-written -- (float) getX -{ - return 0; -} - -- (float) getY -{ - return 0; -} - - -@end diff --git a/iOS/playground/JoystickView.swift b/iOS/playground/JoystickView.swift new file mode 100644 index 0000000..16f728a --- /dev/null +++ b/iOS/playground/JoystickView.swift @@ -0,0 +1,197 @@ +// +// JoystickView.swift +// playground +// +// Created by Jelle Alten on 11-11-16. +// Copyright © 2016 Wonder Workshop. All rights reserved. +// + +import UIKit + +@objc protocol JoystickDelegate { + @objc optional func onJoystickMoved() + @objc optional func onJoystickSoftReleased() + @objc optional func onJoystickReleased() + @objc optional func joystickSoftReturnDuration() -> Float // max time for return center after user releases joystick + @objc optional func joystickBounds() -> CGRect +} + +class JoystickView: UIView { + + enum JoystickType: UInt { + case DRIVE_JOYSTICK + case HEAD_JOYSTICK + } + + let driveDraggerImage = "RC_drive_joystick" + let headDraggerImage = "RC_head_joystick" + let dotSize: CGFloat = 90 + let timerReturnUpdateRate: Float = 30.0 // delegates calls update rate ( affects robot update state ) + + var type: JoystickType = .DRIVE_JOYSTICK + var draggerImgView: UIImageView = UIImageView() + + @IBOutlet weak var joystickDelegate: JoystickDelegate! + + var returnTimer: Timer? + var currentReturnRatio: Float = 0.0 + var returnTime: Float = 0.0 + + var dragCenter: CGPoint = CGPoint() + private var _dotPos = CGPoint() + var dotPos: CGPoint { + set { + self._dotPos = newValue + joystickDelegate.onJoystickMoved?() + } + get { + return self._dotPos + } + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + commonInit() + } + + override init(frame: CGRect) { + super.init(frame: frame) + commonInit() + } + + func commonInit() { + contentMode = .scaleAspectFit + autoresizingMask = UIViewAutoresizing(rawValue: 0) + self.isUserInteractionEnabled = true + } + + override func layoutSubviews() { + super.layoutSubviews() + dragCenter = CGPoint(x:bounds.width / 2.0, y: bounds.height / 2.0) + dotPos = dragCenter + self.updateDraggerPosition() + } + + func updateDraggerImage() { + let imgName: String + switch type { + case .DRIVE_JOYSTICK: + imgName = driveDraggerImage + case .HEAD_JOYSTICK: + imgName = headDraggerImage + } + let img = UIImage(named: imgName) + draggerImgView = UIImageView(image: img) + draggerImgView.frame = CGRect(x: 0.0, y: 0.0, width: dotSize, height: dotSize) + draggerImgView.center = dotPos + print("adding the dragger") + addSubview(draggerImgView) + } + + func enforceJoystickBound(_ point: CGPoint) -> CGPoint? { + guard let bounds = joystickDelegate.joystickBounds?() else { + return nil + } + + return CGPoint(x: clamp(point.x, bounds.origin.x, bounds.width), + y: clamp(point.y, bounds.origin.y, bounds.height) ) + } + +} + +// MARK: - +// MARK: handle touches +extension JoystickView { + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + returnTimer?.invalidate() + currentReturnRatio = 0 + draggerImgView.layer.removeAllAnimations() + } + + override func touchesEnded(_ touches: Set, with event: UIEvent?) { + + if (joystickDelegate.joystickSoftReturnDuration?()) != nil { + joystickDelegate.onJoystickSoftReleased?() + returnJoystickToCenter() + } else { + returnNow() + joystickDelegate?.onJoystickReleased?() + } + } + + func returnNow() { + if let timer = returnTimer { + timer.invalidate() + returnTimer = nil + } + dotPos = dragCenter + updateDraggerPosition() + } + + func returnJoystickToCenter() { + let dist = getDistance(point1: dragCenter, point2: dotPos) + if dist < 0.1 { + returnNow() + } else if let returnDuration = joystickDelegate.joystickSoftReturnDuration?() { + returnTime = returnDuration * Float(dist) / Float(bounds.width) + // timer will update robot with new joystick values while is being animated + returnTimer = Timer.scheduledTimer(timeInterval: TimeInterval(returnTime / timerReturnUpdateRate), + target:self, + selector:#selector(self.updateReturnJoystick), + userInfo:nil, repeats:true) + + // animate soft return + UIView.animate(withDuration: TimeInterval(returnTime), animations: { + self.draggerImgView.center = self.dragCenter + }) + + } + } + + func updateReturnJoystick() { + if currentReturnRatio > 1 { + dotPos = dragCenter + // means we have returned it to the center + joystickDelegate.onJoystickReleased?() + + // clean + returnTimer?.invalidate() + returnTimer = nil + currentReturnRatio = 0 + } else { + currentReturnRatio += (returnTime / timerReturnUpdateRate) + joystickDelegate.onJoystickMoved?() + + dotPos = lerpPoints(min: dotPos, max: dragCenter, dist: Double(currentReturnRatio * 0.4)) + } + } + + override func touchesMoved(_ touches: Set, with event: UIEvent?) { + + if let originalPos = touches.first?.location(in: self) { + if let newPos = enforceJoystickBound(originalPos) { + dotPos = newPos + } else { + dotPos = originalPos + } + } + + updateDraggerPosition() + } + +} + +extension JoystickView { + + func updateDraggerPosition() { + draggerImgView.center = dotPos + } + + func getX() -> Float { + return 0 + } + func getY() -> Float { + return 0 + } + +} diff --git a/iOS/playground/RobotControlPanelViewController.h b/iOS/playground/RobotControlPanelViewController.h deleted file mode 100644 index 31fd48e..0000000 --- a/iOS/playground/RobotControlPanelViewController.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// RobotControlPanelViewController.h -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -@class RobotControlViewController; - -@interface RobotControlPanelViewController : UIViewController - -@property (weak, nonatomic) IBOutlet UISegmentedControl *controlsSelector; -@property (weak, nonatomic) IBOutlet UIView *controlsView; -@property (nonatomic, strong) RobotControlViewController *activeControlVC; - -- (IBAction)switchControls:(id)sender; - -@end - diff --git a/iOS/playground/RobotControlPanelViewController.m b/iOS/playground/RobotControlPanelViewController.m deleted file mode 100644 index 39b5875..0000000 --- a/iOS/playground/RobotControlPanelViewController.m +++ /dev/null @@ -1,78 +0,0 @@ -// -// RobotControlPanelViewController.m -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "RobotControlPanelViewController.h" -#import "ControlLightsViewController.h" -#import "ControlEyeRingViewController.h" -#import "ControlDriveViewController.h" -#import "ControlHeadViewController.h" -#import "ControlSoundViewController.h" -#import "ControlSensorsViewController.h" - -@interface RobotControlPanelViewController () - -@property (nonatomic, strong) NSArray *controlsVC; - -- (void) presentRobotControlsVC:(RobotControlViewController *)vc; - -@end - -@implementation RobotControlPanelViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - - UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; - ControlLightsViewController *lights = [sb instantiateViewControllerWithIdentifier:NSStringFromClass([ControlLightsViewController class])]; - ControlEyeRingViewController *eyeRing = [sb instantiateViewControllerWithIdentifier:NSStringFromClass([ControlEyeRingViewController class])]; - ControlDriveViewController *drive = [sb instantiateViewControllerWithIdentifier:NSStringFromClass([ControlDriveViewController class])]; - ControlHeadViewController *head = [sb instantiateViewControllerWithIdentifier:NSStringFromClass([ControlHeadViewController class])]; - ControlSoundViewController *sound = [sb instantiateViewControllerWithIdentifier:NSStringFromClass([ControlSoundViewController class])]; - ControlSensorsViewController *sensor = [sb instantiateViewControllerWithIdentifier:NSStringFromClass([ControlSensorsViewController class])]; - - self.controlsVC = @[lights, eyeRing, drive, head, sound, sensor]; - - [self presentRobotControlsVC:[self.controlsVC firstObject]]; -} - -- (IBAction)switchControls:(id)sender { - UISegmentedControl *control = sender; - - RobotControlViewController *newVC = (RobotControlViewController *)[self.controlsVC objectAtIndex:control.selectedSegmentIndex]; - [self presentRobotControlsVC:newVC]; -} - -- (void) presentRobotControlsVC:(RobotControlViewController *)vc -{ - if (![self.activeControlVC isEqual:vc]) { - [self.activeControlVC.view removeFromSuperview]; - [self.activeControlVC removeFromParentViewController]; - - self.activeControlVC = vc; - [self addChildViewController:self.activeControlVC]; - [self.controlsView addSubview:self.activeControlVC.view]; - [self.activeControlVC didMoveToParentViewController:self]; - } -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - -#pragma mark - WWRobotDelegate -- (void) robot:(WWRobot *)robot didReceiveRobotState:(WWSensorSet *)state { - -} - -- (void) robot:(WWRobot *)robot eventsTriggered:(NSArray *)events { - for (WWEvent *event in events) { - } -} - -@end diff --git a/iOS/playground/RobotControlPanelViewController.swift b/iOS/playground/RobotControlPanelViewController.swift new file mode 100644 index 0000000..0bca4ad --- /dev/null +++ b/iOS/playground/RobotControlPanelViewController.swift @@ -0,0 +1,61 @@ +// +// RobotControlPanelViewController.swift +// playground +// +// Created by Jelle Alten on 10-11-16. +// Copyright © 2016 Wonder Workshop. All rights reserved. +// + +import UIKit + +class RobotControlPanelViewController: UIViewController { + + @IBOutlet weak var controlsSelector: UISegmentedControl! + @IBOutlet weak var controlsView: UIView! + var activeControlVC: RobotControlViewController? + + var controlsVC = [RobotControlViewController]() + + override func viewDidLoad() { + super.viewDidLoad() + + let sb = UIStoryboard(name: "Main", bundle: nil) + let lights = sb.instantiateViewController(withIdentifier: ControlLightsViewController.nameOfClass) + let eyeRing = sb.instantiateViewController(withIdentifier: ControlEyeRingViewController.nameOfClass) + let drive = sb.instantiateViewController(withIdentifier: ControlDriveViewController.nameOfClass) + let head = sb.instantiateViewController(withIdentifier: ControlHeadViewController.nameOfClass) + let sound = sb.instantiateViewController(withIdentifier: ControlSoundViewController.nameOfClass) + let sensor = sb.instantiateViewController(withIdentifier: ControlSensorsViewController.nameOfClass) + + if let lights = lights as? RobotControlViewController, + let eyeRing = eyeRing as? RobotControlViewController, + let drive = drive as? RobotControlViewController, + let head = head as? RobotControlViewController, + let sound = sound as? RobotControlViewController, + let sensor = sensor as? RobotControlViewController { + + controlsVC = [lights, eyeRing, drive, head, sound, sensor] + presentRobotControlsVC(vc: controlsVC.first!) + } + } + + @IBAction func switchControls(_ control: UISegmentedControl) { + let newVC = controlsVC[control.selectedSegmentIndex] + presentRobotControlsVC(vc: newVC) + } + + private func presentRobotControlsVC(vc newVC: RobotControlViewController) { + if activeControlVC != newVC { + if let previousVC = activeControlVC { + previousVC.view.removeFromSuperview() + previousVC.removeFromParentViewController() + } + + activeControlVC = newVC + addChildViewController(newVC) + controlsView.addSubview(newVC.view) + newVC.didMove(toParentViewController: self) + } + } + +} diff --git a/iOS/playground/RobotControlViewController.h b/iOS/playground/RobotControlViewController.h deleted file mode 100644 index f0ec008..0000000 --- a/iOS/playground/RobotControlViewController.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// RobotControlViewController.h -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -@interface RobotControlViewController : UIViewController - -@property (nonatomic, strong) NSArray *connectedRobots; - -- (void) refreshConnectedRobots; -- (void) sendCommandSetToRobots:(WWCommandSet *)cmd; - -@end diff --git a/iOS/playground/RobotControlViewController.m b/iOS/playground/RobotControlViewController.m deleted file mode 100644 index 48e0112..0000000 --- a/iOS/playground/RobotControlViewController.m +++ /dev/null @@ -1,48 +0,0 @@ -// -// RobotControlViewController.m -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "RobotControlViewController.h" - -@interface RobotControlViewController () - -@end - -@implementation RobotControlViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - // Do any additional setup after loading the view. -} - -- (void) viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - [self refreshConnectedRobots]; -} - -- (void) refreshConnectedRobots -{ - self.connectedRobots = [[WWRobotManager manager] allConnectedRobots]; - for (WWRobot *robot in self.connectedRobots) { - [robot addRobotObserver:self]; - } -} - -- (void) sendCommandSetToRobots:(WWCommandSet *)cmd -{ - for (WWRobot *robot in self.connectedRobots) { - [robot sendRobotCommandSet:cmd]; - } -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - -@end diff --git a/iOS/playground/RobotControlViewController.swift b/iOS/playground/RobotControlViewController.swift new file mode 100644 index 0000000..256feb5 --- /dev/null +++ b/iOS/playground/RobotControlViewController.swift @@ -0,0 +1,32 @@ +// +// RobotControlViewController.swift +// playground +// +// +import UIKit + +class RobotControlViewController: UIViewController { + var connectedRobots = [WWRobot]() + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + refreshConnectedRobots() + } + + func refreshConnectedRobots() { + if let robots = WWRobotManager.shared().allConnectedRobots as? [WWRobot] { + connectedRobots = robots + for robot in connectedRobots { + robot.add(self) + } + } + } + + func sendCommandSet(toRobots cmd: WWCommandSet) { + for robot in connectedRobots { + robot.send(cmd) + } + } +} + +extension RobotControlViewController: WWRobotObserver { +} diff --git a/iOS/playground/RobotListTableViewCell.h b/iOS/playground/RobotListTableViewCell.h deleted file mode 100644 index d47fb24..0000000 --- a/iOS/playground/RobotListTableViewCell.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// RobotListTableViewCell.h -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import - -@interface RobotListTableViewCell : UITableViewCell - -@property (weak, nonatomic) IBOutlet UIView *statusColorView; -@property (weak, nonatomic) IBOutlet UIImageView *robotImageView; -@property (weak, nonatomic) IBOutlet UILabel *nameLabel; -@property (weak, nonatomic) IBOutlet UILabel *infoLabel; - -@end diff --git a/iOS/playground/RobotListTableViewCell.m b/iOS/playground/RobotListTableViewCell.m deleted file mode 100644 index 5e0e2ed..0000000 --- a/iOS/playground/RobotListTableViewCell.m +++ /dev/null @@ -1,23 +0,0 @@ -// -// RobotListTableViewCell.m -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "RobotListTableViewCell.h" - -@implementation RobotListTableViewCell - -- (void)awakeFromNib { - // Initialization code -} - -- (void)setSelected:(BOOL)selected animated:(BOOL)animated { - [super setSelected:selected animated:animated]; - - // Configure the view for the selected state -} - -@end diff --git a/iOS/playground/RobotListTableViewCell.swift b/iOS/playground/RobotListTableViewCell.swift new file mode 100644 index 0000000..cd1d0d7 --- /dev/null +++ b/iOS/playground/RobotListTableViewCell.swift @@ -0,0 +1,16 @@ +// +// RobotListTableViewCell.swift +// playground +// +// Created by Jelle Alten on 11-11-16. +// Copyright © 2016 Wonder Workshop. All rights reserved. +// + +import UIKit + +class RobotListTableViewCell: UITableViewCell { + @IBOutlet var statusColorView: UIView! + @IBOutlet var robotImageView: UIImageView! + @IBOutlet var nameLabel: UILabel! + @IBOutlet var infoLabel: UILabel! +} diff --git a/iOS/playground/RobotListTableViewCell.xib b/iOS/playground/RobotListTableViewCell.xib index 6ee3c16..adf0854 100644 --- a/iOS/playground/RobotListTableViewCell.xib +++ b/iOS/playground/RobotListTableViewCell.xib @@ -1,17 +1,21 @@ - + + + + - + + - + - + @@ -34,7 +38,7 @@ - + @@ -46,6 +50,6 @@ - + diff --git a/iOS/playground/RobotListViewController.h b/iOS/playground/RobotListViewController.h deleted file mode 100644 index 924c99f..0000000 --- a/iOS/playground/RobotListViewController.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// RobotListViewController.h -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import - -@class RobotControlPanelViewController; - -@interface RobotListViewController : UITableViewController - -@property (strong, nonatomic) RobotControlPanelViewController *controlPanelViewController; -@property (nonatomic, strong) WWRobotManager *manager; - -@end - diff --git a/iOS/playground/RobotListViewController.m b/iOS/playground/RobotListViewController.m deleted file mode 100644 index b62465a..0000000 --- a/iOS/playground/RobotListViewController.m +++ /dev/null @@ -1,182 +0,0 @@ -// -// RobotListViewController.m -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import "RobotListViewController.h" -#import "RobotControlPanelViewController.h" -#import "RobotControlViewController.h" -#import "RobotListTableViewCell.h" - -@interface RobotListViewController () - -@property NSMutableArray *robots; - -@end - - -@implementation RobotListViewController - -- (void)awakeFromNib { - [super awakeFromNib]; - if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { - self.clearsSelectionOnViewWillAppear = NO; - self.preferredContentSize = CGSizeMake(320.0, 600.0); - } -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.controlPanelViewController = (RobotControlPanelViewController *)[[self.splitViewController.viewControllers lastObject] topViewController]; - self.robots = [NSMutableArray new]; - - // load custom nib - [self.tableView registerNib:[UINib nibWithNibName:@"RobotListTableViewCell" bundle:nil] forCellReuseIdentifier:@"RobotListTableViewCell"]; - - // setup robot manager - self.manager = [WWRobotManager manager]; - NSAssert(self.manager, @"unable to instantiate robot manager"); - [self.manager addManagerObserver:self]; - [self.manager startScanningForRobots:2.0f]; - - self.tableView.rowHeight = 130; - UIColor *start = [UIColor colorWithRed:58/255.0 green:108/255.0 blue:183/255.0 alpha:0.15]; - UIColor *stop = [UIColor colorWithRed:58/255.0 green:108/255.0 blue:183/255.0 alpha:0.45]; - - CAGradientLayer *gradient = [CAGradientLayer layer]; - gradient.frame = [self.view bounds]; - gradient.colors = [NSArray arrayWithObjects:(id)start.CGColor, (id)stop.CGColor, nil]; - [self.tableView.layer insertSublayer:gradient atIndex:0]; -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - -- (void)insertNewObject:(id)sender { -// if (!self.objects) { -// self.objects = [[NSMutableArray alloc] init]; -// } -// [self.objects insertObject:[NSDate date] atIndex:0]; -// NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; -// [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; -} - -#pragma mark - Segues - -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - if ([[segue identifier] isEqualToString:@"showDetail"]) { - NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; - RobotControlPanelViewController *controller = (RobotControlPanelViewController *)[[segue destinationViewController] topViewController]; - controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem; - controller.navigationItem.leftItemsSupplementBackButton = YES; - } -} - -#pragma mark - Table View - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.robots.count; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - RobotListTableViewCell *cell = (RobotListTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"RobotListTableViewCell" forIndexPath:indexPath]; - - // status - WWRobot *robot = (WWRobot *)self.robots[indexPath.row]; - if (robot.isConnected) { - cell.contentView.backgroundColor = [UIColor colorWithRed:50/255.0 green:200/255.0 blue:50/255.0 alpha:0.6]; - } - else { - cell.contentView.backgroundColor = [UIColor colorWithRed:250/255.0 green:250/255.0 blue:250/255.0 alpha:0.6]; - } - - // robot info - NSMutableString *detail = [NSMutableString stringWithCapacity:200]; - [detail appendFormat:@"uuId: %@\n", robot.uuId]; - [detail appendFormat:@"Firmware %@\n", robot.firmwareVersion]; - [detail appendFormat:@"Serial: %@\n", robot.serialNumber]; - [detail appendFormat:@"RSSI %d dB\n", robot.signalStrength.intValue]; - [detail appendFormat:@"Personality color: %d\n", robot.personalityColorIndex]; - cell.infoLabel.text = detail; - - // robot name - cell.nameLabel.text = robot.name; - - // image - switch (robot.robotType) { - case WW_ROBOT_DOT: - cell.robotImageView.image = [UIImage imageNamed:@"dot.png"]; - break; - case WW_ROBOT_DASH: - cell.robotImageView.image = [UIImage imageNamed:@"dash.png"]; - - default: - break; - } - - return cell; -} - -- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - WWRobot *robot = self.robots[indexPath.row]; - if (robot.isConnected) { - [self.manager disconnectFromRobot:robot]; - } - else { - [self.manager connectToRobot:robot]; - } -} - -- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { - // Return NO if you do not want the specified item to be editable. - return NO; -} - -#pragma mark - RobotManagerDelegate - -- (void) manager:(WWRobotManager *)manager didDiscoverRobot:(WWRobot *)robot { - if (![self.robots containsObject:robot]) { - // found new robots, refresh list - [self.robots addObject:robot]; - [self.tableView reloadData]; - } -} - -- (void) manager:(WWRobotManager *)manager didUpdateDiscoveredRobots:(WWRobot *)robot { - // existing robots have new data, refresh - [self.tableView reloadData]; -} - -- (void) manager:(WWRobotManager *)manager didLoseRobot:(WWRobot *)robot { - // lost connectivity with existing robot, refresh list - [self.robots removeObject:robot]; - [self.tableView reloadData]; -} - -- (void) manager:(WWRobotManager *)manager didConnectRobot:(WWRobot *)robot { - // connected with robot, refresh - [self.tableView reloadData]; - [self.controlPanelViewController.activeControlVC refreshConnectedRobots]; -} - -- (void) manager:(WWRobotManager *)manager didFailToConnectRobot:(WWRobot *)robot error:(WWError *)error { - NSLog(@"failed to connect to robot: %@, with error: %@", robot.name, error); - [NSNumber numberWithUnsignedInteger:WW_SENSOR_BUTTON_MAIN]; -} - -- (void) manager:(WWRobotManager *)manager didDisconnectRobot:(WWRobot *)robot { - // disconnected with robot, refresh - [self.tableView reloadData]; -} - -@end diff --git a/iOS/playground/RobotListViewController.swift b/iOS/playground/RobotListViewController.swift new file mode 100644 index 0000000..83e0eb7 --- /dev/null +++ b/iOS/playground/RobotListViewController.swift @@ -0,0 +1,161 @@ +// +// RobotListViewController.m +// playground +// +// + +import UIKit + +class RobotListViewController: UITableViewController { + + var controlPanelViewController: RobotControlPanelViewController? + var manager: WWRobotManager? + var robots = [WWRobot]() + + override func awakeFromNib() { + super.awakeFromNib() + if UIDevice.current.userInterfaceIdiom == .pad { + clearsSelectionOnViewWillAppear = false + preferredContentSize = CGSize(width:320.0, height:600.0) + } + } + override func viewDidLoad() { + super.viewDidLoad() + if let panelViewController = splitViewController?.viewControllers.last as? RobotControlPanelViewController { + controlPanelViewController = panelViewController + } + + let nib = UINib(nibName: "RobotListTableViewCell", bundle: nil) + tableView.register(nib, forCellReuseIdentifier: "RobotListTableViewCell") + + // setup robot manager + let manager: WWRobotManager = WWRobotManager.shared() + manager.add(self) + + self.manager = manager + manager.startScanning(forRobots:2.0) + + tableView.rowHeight = 130 + let start = UIColor(red:58/255.0, green:108/255.0, blue:183/255.0, alpha:0.15) + let stop = UIColor(red: 58/255.0, green:108/255.0, blue:183/255.0, alpha:0.45) + + let gradient = CAGradientLayer() + gradient.frame = view.bounds + gradient.colors = [start.cgColor, stop.cgColor] + tableView.layer.insertSublayer(gradient, at:0) + } + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + if segue.identifier == "showDetail" { + if let controller = segue.destination as? RobotControlPanelViewController, + let splitViewController = splitViewController { + controller.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem + controller.navigationItem.leftItemsSupplementBackButton = true + } + } + } +} + +// mark: - +// mark: Table View methods +extension RobotListViewController { + + override func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return robots.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let tableViewCell = tableView.dequeueReusableCell(withIdentifier: "RobotListTableViewCell", for: indexPath) + guard let cell = tableViewCell as? RobotListTableViewCell else { + return UITableViewCell() + } + + let robot = robots[indexPath.row] + if robot.isConnected() { + cell.contentView.backgroundColor = UIColor(red:50/255.0, green:200/255.0, blue:50/255.0, alpha:0.6) + } else { + cell.contentView.backgroundColor = UIColor(red:250/255.0, green:250/255.0, blue:250/255.0, alpha:0.6) + } + + // robot info + var detail = String() + detail.append("uuId: \(robot.uuId)\n") + detail.append("Firmware \(robot.firmwareVersion)\n") + detail.append("Serial: \(robot.serialNumber)\n") + detail.append("RSSI \(robot.signalStrength.intValue) dB\n") + detail.append("Personality color: \(robot.personalityColorIndex)\n") + cell.infoLabel.text = detail + + // robot name + cell.nameLabel.text = robot.name + + // image + switch robot.robotType { + case .ROBOT_DOT: + cell.robotImageView.image = UIImage(named:"dot.png") + break + case .ROBOT_DASH: + cell.robotImageView.image = UIImage(named:"dash.png") + + default: + break + } + + return cell + } + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let robot = robots[indexPath.row] + if robot.isConnected() { + manager?.disconnect(from: robot) + } else { + manager?.connect(to: robot) + } + } + + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + return false + } + +} + +// mark: - +extension RobotListViewController: WWRobotManagerObserver { + func manager(_ manager: WWRobotManager!, didDiscover robot: WWRobot!) { + if !robots.contains(robot) { + robots.append(robot) + tableView.reloadData() + } + } + + func manager(_ manager: WWRobotManager!, didUpdateDiscoveredRobots robot: WWRobot!) { + tableView.reloadData() + } + + func manager(_ manager: WWRobotManager!, didLose robot: WWRobot!) { + if let index = robots.index(of: robot) { + robots.remove(at: index) + } + tableView.reloadData() + } + + func manager(_ manager: WWRobotManager!, didConnect robot: WWRobot!) { + tableView.reloadData() + controlPanelViewController?.activeControlVC?.refreshConnectedRobots() + } + + func manager(_ manager: WWRobotManager!, didFailToConnect robot: WWRobot!, error: WWError!) { + print("failed to connect to robot: \(robot.name), with error: \(error)") + print() + + } + + func manager(_ manager: WWRobotManager!, didDisconnectRobot robot: WWRobot!) { + tableView.reloadData() + } +} diff --git a/iOS/playground/main.m b/iOS/playground/main.m deleted file mode 100644 index 3c26fde..0000000 --- a/iOS/playground/main.m +++ /dev/null @@ -1,16 +0,0 @@ -// -// main.m -// playground -// -// Created by Kevin Liang on 11/17/14. -// Copyright (c) 2014 Wonder Workshop. All rights reserved. -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/iOS/playground/playground-Bridging-Header.h b/iOS/playground/playground-Bridging-Header.h new file mode 100644 index 0000000..e46dade --- /dev/null +++ b/iOS/playground/playground-Bridging-Header.h @@ -0,0 +1,10 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import +#import + +@interface WWRobotManager (shared) ++ (WWRobotManager*) sharedManager; +@end