Exemplo n.º 1
0
    private void Start()
    {
        if (instance != null)
        {
            Destroy(gameObject);
            return;
        }

        DontDestroyOnLoad(this);
        instance    = this;
        unityThread = Thread.CurrentThread.ManagedThreadId;
        service     = new ClientSettingsService();
        ClientSettings settings = service.GetOrMake();

        if (string.IsNullOrEmpty(Config.CloudProxy))
        {
            API = new CloudAPI(new Uri(Config.CloudUrl), Config.SimID);
        }
        else
        {
            API = new CloudAPI(new Uri(Config.CloudUrl), Config.SimID, new Uri(Config.CloudProxy));
        }

#if UNITY_EDITOR
        EditorApplication.playModeStateChanged += HandlePlayMode;
#endif

        if (settings.onlineStatus)
        {
            ConnectionStatusEvent();
        }
    }
Exemplo n.º 2
0
 public SearchPage()
 {
     this.InitializeComponent();
     if (cloudAPI == null)
     {
         cloudAPI = new CloudAPI();
     }
 }
Exemplo n.º 3
0
        public void Login_Valid()
        {
            // arrange
            CloudAPI api = new CloudAPI(getKey());

            // act
            api.Login("*****@*****.**", "Lascarseddi12");

            // assert handled through exception
        }
Exemplo n.º 4
0
        public MyMusicPage()
        {
            this.InitializeComponent();
            localStorage = new LocalStorage();

            if (cloudAPI == null)
            {
                cloudAPI = new CloudAPI();
            }
        }
Exemplo n.º 5
0
        public void GetStatus_Test()
        {
            // arrange
            CloudAPI api = new CloudAPI(getKey());

            // act
            string status = api.GetStatus();

            // assert
            Assert.IsNotNull(status);
        }
Exemplo n.º 6
0
        public HomePage()
        {
            this.InitializeComponent();

            if (cloudAPI == null)
            {
                cloudAPI = new CloudAPI();
            }

            #pragma warning disable CS4014 // Force compiler to stop whining about my lack of await keyword
            FetchDataFromApi();
            #pragma warning restore CS4014
        }
Exemplo n.º 7
0
        private async void button_TestAPI_Click(object sender, RoutedEventArgs e)
        {
            if (cloudAPI == null)
            {
                cloudAPI = new CloudAPI();
            }

            Task <string> result      = cloudAPI.ProbeAsync();
            ContentDialog probeDialog = new ContentDialog {
                Title           = "Testing API connection",
                Content         = await result,
                CloseButtonText = "Ok"
            };

            await probeDialog.ShowAsync();
        }
Exemplo n.º 8
0
        public void Login_Invalid()
        {
            // Arrange
            CloudAPI api = new CloudAPI(getKey());

            // act
            try
            {
                api.Login("*****@*****.**", "fake");
            } catch (Exception e)
            {
                Assert.IsTrue(e.GetType() == typeof(CloudAPI.CloudException));
            }

            // assert
            //Assert.Fail("Expected CloudException");
        }
Exemplo n.º 9
0
        private static void Initialize()
        {
            Root = Path.Combine(Application.dataPath, "..");
            PersistentDataPath  = Application.persistentDataPath;
            PersistentDataPath += "-" + CloudAPI.GetInfo().version;

            AssetService = new AssetService();

            ParseConfigFile();
            if (!Application.isEditor)
            {
                ParseCommandLine();
            }

            CreatePersistentPath();

            if (!Application.isEditor)
            {
                CreateLockFile();
            }

            AssetBundle.UnloadAllAssetBundles(false);
            Sensors       = new List <SensorConfig>();
            SensorPrefabs = new List <SensorBase>();

            BridgePlugins.Load();
            LoadBuiltinAssets();
            LoadExternalAssets();
            Sensors = SensorTypes.ListSensorFields(SensorPrefabs);

            DatabaseManager.Init();

            ClientSettingsService csservice = new ClientSettingsService();

            if (string.IsNullOrEmpty(SimID))
            {
                SimID = csservice.GetOrMake().simid;
            }

            csservice.SetSimID(SimID);
            AssetBundle.UnloadAllAssetBundles(false);
        }
Exemplo n.º 10
0
        public void Awake()
        {
            if (instance != null)
            {
                Destroy(gameObject);
                return;
            }

            SimulatorVersionText.text = $"Simulator Version: {CloudAPI.GetInfo().version}";
            UnityVersionText.text     = $"Unity Version: {Application.unityVersion}";
            ColorUtility.TryParseHtmlString("#1F2940", out offlineColor);
            ColorUtility.TryParseHtmlString("#FFFFFF", out onlineColor);
            statusButtonIcon.material.color = Color.white;
            instance = this;
            statusButton.onClick.AddListener(OnStatusButtonClicked);
            statusMenuButton.onClick.AddListener(OnStatusMenuButtonClicked);
            linkButton.onClick.AddListener(OnLinkButtonClicked);
            offlineStartButton.onClick.AddListener(OnOfflineStartButtonClicked);
            offlineStopButton.onClick.AddListener(OnOfflineStopButtonClicked);
            clearAssetCacheButton.onClick.AddListener(() =>
            {
                CacheControlWindow.gameObject.SetActive(true);
            });
            LoadedAssetsButton.onClick.AddListener(() =>
            {
                LoadedAssetsWindow.SetActive(true);
            });
            unlinkButton.onClick.AddListener(OnUnlinkButtonClicked);
            quitButton.onClick.AddListener(OnQuitButtonClicked);
            SettingsButton.onClick.AddListener(OnSettingsButtonClicked);
            UpdateDropdown();
            offlineDropdown.onValueChanged.AddListener(OnDropdownValueChanged);
            UpdateStatus(ConnectionManager.Status, "");
            TaskProgressManager.Instance.OnUpdate += UpdateDownloadProgress;
            ConnectionManager.OnStatusChanged     += UpdateStatus;
        }
Exemplo n.º 11
0
        void OnGUI()
        {
            EditorGUILayout.HelpBox("Cloud URL: " + Config.CloudUrl, MessageType.Info);
            EditorGUILayout.HelpBox(new GUIContent("SimID: " + Config.SimID, "Identifies this instance"));

            if (!string.IsNullOrEmpty(ErrorMessage))
            {
                EditorGUILayout.HelpBox(ErrorMessage, MessageType.Warning);
            }

            if (EditorApplication.isPlayingOrWillChangePlaymode)
            {
                EditorGUILayout.HelpBox("Disabled during play mode", MessageType.Info);
                return;
            }

            if (updating)
            {
                EditorGUILayout.HelpBox("Updating...", MessageType.Info);
                return;
            }

            EditorGUI.BeginChangeCheck();

            EditorGUILayout.BeginHorizontal();
            if (!linked && GUILayout.Button(new GUIContent("Link", "Add this instance to a cluster or create a cluster.")))
            {
                var simInfo = CloudAPI.GetInfo();
                LinkTask(simInfo);
            }
            if (GUILayout.Button(new GUIContent("Refresh", "Refresh displayed local and cloud asset data in this window.")))
            {
                Refresh();
            }
            if (GUILayout.Button(new GUIContent("Manage clusters", "Visit cluster page on " + Config.CloudUrl)))
            {
                Application.OpenURL(Config.CloudUrl + "/clusters");
            }

            EditorGUILayout.EndHorizontal();

            ScrollPos = EditorGUILayout.BeginScrollView(ScrollPos);

            if (SimulatorVersions != null && SimulatorVersions.Count > 0)
            {
                if (versionIndex < 0 || versionIndex >= SimulatorVersions.Count)
                {
                    versionIndex = SimulatorVersions.FindIndex(e => e.version == Settings.VersionOverride);
                    if (versionIndex < 0)
                    {
                        versionIndex = 0;
                    }
                }

                versionIndex = EditorGUILayout.Popup(new GUIContent("Version", "Influences which compatible asset which will be downloaded from wise"), versionIndex, SimulatorVersions.Select(v => v.display).ToArray());
                if (versionIndex < 0 || versionIndex >= SimulatorVersions.Count)
                {
                    versionIndex = SimulatorVersions.Count - 1;
                }

                if (versionIndex == 0)
                {
                    Settings.VersionOverride = EditorGUILayout.TextField(new GUIContent("Version", "Influences which compatible asset which will be downloaded from wise"), Settings.VersionOverride);
                }
                else
                {
                    Settings.VersionOverride = SimulatorVersions[versionIndex].version;
                }
            }

            foreach (PropertyInfo prop in typeof(SimulationData).GetProperties())
            {
                if (prop.Name == "Id" || prop.Name == "UpdatedAt" || prop.Name == "CreatedAt" || prop.Name == "OwnerId" || prop.Name == "TestReportId" || prop.Name == "Version")
                {
                    continue;
                }

                object value = prop.GetValue(DeveloperSimulation);
                if (prop.PropertyType == typeof(bool))
                {
                    prop.SetValue(DeveloperSimulation, EditorGUILayout.ToggleLeft(prop.Name, ((bool?)value).Value));
                }
                else if (prop.PropertyType == typeof(int))
                {
                    prop.SetValue(DeveloperSimulation, EditorGUILayout.IntField(prop.Name, ((int?)value).Value));
                }
                else if (prop.PropertyType == typeof(float))
                {
                    prop.SetValue(DeveloperSimulation, EditorGUILayout.FloatField(prop.Name, ((float?)value).Value));
                }
                else if (prop.PropertyType == typeof(string))
                {
                    prop.SetValue(DeveloperSimulation, EditorGUILayout.TextField(prop.Name, (string)value));
                }
                else if (prop.PropertyType == typeof(DateTime))
                {
                    var userValue = EditorGUILayout.TextField(prop.Name, ((DateTime)value).ToString());
                    if (DateTime.TryParse(userValue, out DateTime dt))
                    {
                        prop.SetValue(DeveloperSimulation, dt);
                    }
                }
                else if (prop.PropertyType == typeof(int?))
                {
                    int?val = (int?)value;
                    EditorGUILayout.BeginHorizontal();
                    bool doSet = EditorGUILayout.ToggleLeft("enable " + prop.Name, val.HasValue);
                    EditorGUI.BeginDisabledGroup(!doSet);
                    int?newValue = EditorGUILayout.IntField(prop.Name, val.HasValue ? val.Value : 0, GUILayout.ExpandWidth(true));
                    prop.SetValue(DeveloperSimulation, doSet ? newValue : null);
                    EditorGUI.EndDisabledGroup();
                    GUILayout.EndHorizontal();
                }
                else if (prop.PropertyType == typeof(VehicleData[]))
                {
                    VehicleSetup = EditorGUILayout.Foldout(VehicleSetup, "EGO Vehicle Setup");
                    if (VehicleSetup)
                    {
                        if (VehicleChoices.Count > 0)
                        {
                            EditorGUI.indentLevel++;
                            var newIndex = EditorGUILayout.Popup(CurrentVehicleIndex, VehicleChoices.Select(v => v.display).ToArray());
                            var vehicle  = SetVehicleFromSelectionIndex(newIndex);

                            if (vehicle.Id.EndsWith(".prefab"))
                            {
                                if (Bridges.Length == 0)
                                {
                                    EditorGUILayout.LabelField("no local bridges available");
                                    vehicle.Bridge = null;
                                }
                                else
                                {
                                    var wantBridge = EditorGUILayout.ToggleLeft("Enable Bridge", vehicle.Bridge != null);
                                    if (!wantBridge)
                                    {
                                        vehicle.Bridge = null;
                                    }
                                    else if (vehicle.Bridge == null)
                                    {
                                        vehicle.Bridge = new BridgeData {
                                        };
                                    }

                                    if (vehicle.Bridge != null)
                                    {
                                        var bridgeIndex = Array.IndexOf(Bridges, vehicle.Bridge.Type);
                                        if (bridgeIndex < 0)
                                        {
                                            bridgeIndex = 0;
                                        }

                                        bridgeIndex                     = EditorGUILayout.Popup("Bridge Type", bridgeIndex, Bridges);
                                        vehicle.Bridge.Type             = Bridges[bridgeIndex];
                                        vehicle.Bridge.ConnectionString = EditorGUILayout.TextField("Bridge Connection", vehicle.Bridge.ConnectionString);
                                    }
                                }
                                EditorGUILayout.LabelField("json sensor config");
                                SensorScratchPad = EditorGUILayout.TextArea(SensorScratchPad, GUILayout.ExpandHeight(true));

                                try
                                {
                                    vehicle.Sensors = JsonConvert.DeserializeObject <SensorData[]>(SensorScratchPad);
                                    if (vehicle.Sensors == null)
                                    {
                                        vehicle.Sensors = new SensorData[0];
                                    }
                                }
                                catch (Exception e)
                                {
                                    EditorGUILayout.HelpBox(e.Message, MessageType.Error);
                                }
                            }
                            else
                            {
                                if (vehicle.Bridge != null)
                                {
                                    vehicle.Bridge.ConnectionString = EditorGUILayout.TextField("Bridge Connection", vehicle.Bridge.ConnectionString);
                                    EditorGUILayout.TextField("Bridge Type", vehicle.Bridge.Type);
                                    EditorGUILayout.TextField("Bridge Name", vehicle.Bridge.Name);
                                    EditorGUILayout.TextField("Bridge Id", vehicle.Bridge.Id);
                                }
                                EditorGUILayout.LabelField("json sensor config");
                                EditorGUILayout.TextArea(JsonConvert.SerializeObject(vehicle.Sensors, JsonSettings.camelCasePretty), GUILayout.ExpandHeight(true));
                            }
                            EditorGUI.indentLevel--;
                        }
                        else
                        {
                            EditorGUILayout.HelpBox("no Vehicles in Cloud Library or Assets/External/Vehicles", MessageType.Info);
                        }
                    }
                }
            }

            NPCSelectEnable = EditorGUILayout.BeginToggleGroup("NPC Select", NPCSelectEnable);
            if (NPCSelectEnable)
            {
                EditorGUI.indentLevel++;
                EditorGUILayout.BeginHorizontal(GUILayout.ExpandHeight(false));
                if (GUILayout.Button("Select All", GUILayout.ExpandWidth(false)))
                {
                    foreach (var npc in DeveloperSimulation.NPCs)
                    {
                        npc.Enabled = true;
                    }
                }
                if (GUILayout.Button("Select None", GUILayout.ExpandWidth(false)))
                {
                    foreach (var npc in DeveloperSimulation.NPCs)
                    {
                        npc.Enabled = false;
                    }
                }
                EditorGUILayout.EndHorizontal();
                foreach (var npc in DeveloperSimulation.NPCs)
                {
                    npc.Enabled = EditorGUILayout.Toggle($"{npc.Name}", npc.Enabled);
                }
                EditorGUI.indentLevel--;
            }
            EditorGUILayout.EndToggleGroup();
            EditorGUILayout.EndScrollView();

            if (EditorGUI.EndChangeCheck())
            {
                SaveAssetTime = Time.realtimeSinceStartup;
            }
        }
Exemplo n.º 12
0
        async void Refresh()
        {
            if (EditorApplication.isPlayingOrWillChangePlaymode)
            {
                return;
            }

            try
            {
                updating     = true;
                ErrorMessage = "";
                Simulator.Web.Config.ParseConfigFile();

                await UpdateVersions();

                try
                {
                    // FIXME also list and find bundles and cloud bridges?
                    var bridgesAssembly = Assembly.Load("Simulator.Bridges");
                    Bridges = bridgesAssembly.GetTypes()
                              .Where(ty => typeof(IBridgeFactory).IsAssignableFrom(ty) && !ty.IsAbstract)
                              .Select(ty => BridgePlugins.GetNameFromFactory(ty)).ToArray();
                }
                catch { }

                if (DeveloperSimulation.Cluster == null)
                {
                    DeveloperSimulation.Cluster = new ClusterData()
                    {
                        Name      = "DeveloperSettingsDummy",
                        Instances = new[]
                        {
                            new InstanceData
                            {
                                HostName   = "dummy.developer.settings",
                                Ip         = new [] { "127.0.0.1" },
                                MacAddress = "00:00:00:00:00:00"
                            }
                        }
                    };
                }

                if (string.IsNullOrEmpty(Config.CloudProxy))
                {
                    API = new CloudAPI(new Uri(Config.CloudUrl), Config.SimID);
                }
                else
                {
                    API = new CloudAPI(new Uri(Config.CloudUrl), Config.SimID, new Uri(Config.CloudProxy));
                }

                DatabaseManager.Init();
                var            csservice = new Simulator.Database.Services.ClientSettingsService();
                ClientSettings cls       = csservice.GetOrMake();
                Config.SimID = cls.simid;
                if (string.IsNullOrEmpty(Config.CloudUrl))
                {
                    ErrorMessage = "Cloud URL not set";
                    return;
                }
                if (string.IsNullOrEmpty(Config.SimID))
                {
                    linked       = false;
                    ErrorMessage = "Simulator not linked";
                    return;
                }

                var ret = await API.GetLibrary <VehicleDetailData>();

                CloudVehicles = ret.ToList();

                string[] guids = AssetDatabase.FindAssets("t:Prefab", new[] { "Assets/External/Vehicles" });
                LocalVehicles = guids.Select(g => AssetDatabase.GUIDToAssetPath(g)).ToList();

                string idOrPath = null;
                if (DeveloperSimulation.Vehicles != null) // get previously selected thing
                {
                    // we abuse VehicleData.Id to store the prefab path
                    idOrPath = EgoVehicle.Id;
                }

                if (idOrPath != null)
                {
                    // find index of previously selected thing in new dataset
                    var foundIndex = VehicleChoices.FindIndex(v => v.cloudIdOrPrefabPath == idOrPath && (v.IsLocal || v.configId == Settings.VehicleConfigId));
                    SetVehicleFromSelectionIndex(foundIndex);
                    updateVehicleDetails = true;
                    await UpdateCloudVehicleDetails();
                }

                DeveloperSimulation.NPCs = Config.NPCVehicles.Values.ToArray(); // TODO get from cloud and refresh config.cs LoadExternalAssets()
            }
            catch (CloudAPI.NoSuccessException ex)
            {
                if (ex.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                {
                    ErrorMessage = "This instance requires linking to a cluster on " + Config.CloudUrl;
                    linked       = false;
                }
                else
                {
                    Debug.LogException(ex);
                }
            }
            catch (Exception ex)
            {
                Debug.LogException(ex);
                ErrorMessage = ex.Message;
                if (ex.InnerException != null)
                {
                    ErrorMessage += "\n" + ex.InnerException.Message;
                }
            }
            finally
            {
                updating = false;
                Repaint();
            }
        }
Exemplo n.º 13
0
    async Task Connect()
    {
        try
        {
            simInfo          = CloudAPI.GetInfo();
            Status           = ConnectionStatus.Connecting;
            DisconnectReason = null;
            RunOnUnityThread(() =>
            {
                ConnectionUI.instance.UpdateStatus();
            });

            foreach (var timeOut in timeOutSequence)
            {
                try
                {
                    var reader = await API.Connect(simInfo);
                    await ReadResponse(reader);

                    break;
                }
                catch (HttpRequestException ex)
                {
                    // temporary network issue, we'll retry
                    Debug.Log(ex.Message + ", reconnecting after " + timeOut + " seconds");
                    await Task.Delay(1000 *timeOut);
                }
                if (Status == ConnectionStatus.Offline)
                {
                    Debug.Log("User cancelled connection.");
                    break;
                }
            }

            if (Config.RetryForever)
            {
                while (true)
                {
                    try
                    {
                        var reader = await API.Connect(simInfo);
                        await ReadResponse(reader);

                        break;
                    }
                    catch (CloudAPI.NoSuccessException ex)
                    {
                        Debug.Log(ex.Message + ", reconnecting after " + timeOutSequence[timeOutSequence.Length - 1] + " seconds");
                        DisconnectReason = ex.Message;
                        await Task.Delay(1000 *timeOutSequence[timeOutSequence.Length - 1]);
                    }
                }
            }
        }
        catch (CloudAPI.NoSuccessException ex)
        {
            // WISE told us it does not like us, so stop reconnecting
            DisconnectReason = ex.Message;
            Debug.Log($"WISE backend reported error: {ex.Message}, will not reconnect");
        }
        catch (TaskCanceledException)
        {
            Debug.Log("Linking task canceled.");
            DisconnectReason = "Linking task canceled.";
        }
        catch (System.Net.Sockets.SocketException se)
        {
            Debug.Log($"Could not reach WISE SSE at {Config.CloudUrl}: {se.Message}");
            DisconnectReason = $"Could not reach WISE SSE at {Config.CloudUrl}: {se.Message}";
        }
        catch (Exception ex)
        {
            Debug.LogException(ex);
        }

        Debug.Log("Giving up reconnecting.");
        Disconnect();
    }
        async void Refresh()
        {
            if (EditorApplication.isPlayingOrWillChangePlaymode)
            {
                return;
            }

            try
            {
                updating     = true;
                ErrorMessage = "";
                Simulator.Web.Config.ParseConfigFile();

                DatabaseManager.Init();
                var            csservice = new Simulator.Database.Services.ClientSettingsService();
                ClientSettings cls       = csservice.GetOrMake();
                Config.SimID = cls.simid;
                if (String.IsNullOrEmpty(Config.CloudUrl))
                {
                    ErrorMessage = "Cloud URL not set";
                    return;
                }
                if (String.IsNullOrEmpty(Config.SimID))
                {
                    ErrorMessage = "Simulator not linked";
                    return;
                }

                if (API != null)
                {
                    API.Disconnect();
                }

                API = new CloudAPI(new Uri(Config.CloudUrl), Config.SimID);
                var simInfo = CloudAPI.GetInfo();

                var reader = await API.Connect(simInfo);

                await API.EnsureConnectSuccess();

                var ret = await API.GetLibrary <VehicleDetailData>();

                CloudVehicles = ret.ToList();

                string[] guids = AssetDatabase.FindAssets("t:Prefab", new[] { "Assets/External/Vehicles" });
                LocalVehicles = guids.Select(g => AssetDatabase.GUIDToAssetPath(g)).ToList();

                string idOrPath = null;
                if (DeveloperSimulation.Vehicles != null) // get previously selected thing
                {
                    // we abuse VehicleData.Id to store the prefab path
                    idOrPath = DeveloperSimulation.Vehicles[0].Id;
                }

                if (idOrPath != null)
                {
                    // find index of previously selected thing in new dataset
                    var vehicleChoices = VehicleChoices;
                    var selected       = vehicleChoices.FindIndex(v => v.idOrPath == idOrPath);
                    SetVehicleFromSelectionIndex(vehicleChoices, selected);

                    await UpdateCloudVehicleDetails();
                }

                DeveloperSimulation.NPCs = Config.NPCVehicles.Values.ToArray(); // TODO get from cloud and refresh config.cs LoadExternalAssets()
            }
            catch (Exception ex)
            {
                Debug.LogException(ex);
                ErrorMessage = ex.Message;
                if (ex.InnerException != null)
                {
                    ErrorMessage += "\n" + ex.InnerException.Message;
                }
                API.Disconnect();
            }
            finally
            {
                updating = false;
                Repaint();
            }
        }
        async void Refresh()
        {
            if (EditorApplication.isPlayingOrWillChangePlaymode)
            {
                return;
            }

            try
            {
                updating     = true;
                ErrorMessage = "";
                Simulator.Web.Config.ParseConfigFile();

                if (DeveloperSimulation.Cluster == null)
                {
                    DeveloperSimulation.Cluster = new ClusterData()
                    {
                        Name      = "DeveloperSettingsDummy",
                        Instances = new[]
                        {
                            new InstanceData
                            {
                                HostName   = "dummy.developer.settings",
                                Ip         = new [] { "127.0.0.1" },
                                MacAddress = "00:00:00:00:00:00"
                            }
                        }
                    };
                }

                if (string.IsNullOrEmpty(Config.CloudProxy))
                {
                    API = new CloudAPI(new Uri(Config.CloudUrl), cookieContainer);
                }
                else
                {
                    API = new CloudAPI(new Uri(Config.CloudUrl), cookieContainer, new Uri(Config.CloudProxy));
                }

                DatabaseManager.Init();
                var            csservice = new Simulator.Database.Services.ClientSettingsService();
                ClientSettings cls       = csservice.GetOrMake();
                Config.SimID = cls.simid;
                if (String.IsNullOrEmpty(Config.CloudUrl))
                {
                    ErrorMessage = "Cloud URL not set";
                    return;
                }
                if (String.IsNullOrEmpty(Config.SimID))
                {
                    ErrorMessage = "Simulator not linked";
                    return;
                }

                if (cookieContainer.GetCookies(new Uri(Config.CloudUrl)).Count == 0)
                {
                    authenticated = false;
                }

                if (authenticated)
                {
                    var ret = await API.GetLibrary <VehicleDetailData>();

                    CloudVehicles = ret.ToList();
                }
                else
                {
                    CloudVehicles = new List <VehicleDetailData>();
                }

                string[] guids = AssetDatabase.FindAssets("t:Prefab", new[] { "Assets/External/Vehicles" });
                LocalVehicles = guids.Select(g => AssetDatabase.GUIDToAssetPath(g)).ToList();

                string idOrPath = null;
                if (DeveloperSimulation.Vehicles != null) // get previously selected thing
                {
                    // we abuse VehicleData.Id to store the prefab path
                    idOrPath = DeveloperSimulation.Vehicles[0].Id;
                }

                if (idOrPath != null)
                {
                    // find index of previously selected thing in new dataset
                    var foundIndex = VehicleChoices.FindIndex(v => v.cloudIdOrPrefabPath == idOrPath && (v.IsLocal || v.configId == Settings.VehicleConfigId));
                    SetVehicleFromSelectionIndex(foundIndex);

                    await UpdateCloudVehicleDetails();
                }

                DeveloperSimulation.NPCs = Config.NPCVehicles.Values.ToArray(); // TODO get from cloud and refresh config.cs LoadExternalAssets()
            }
            catch (CloudAPI.NoSuccessException ex)
            {
                if (ex.StatusCode == System.Net.HttpStatusCode.BadRequest)
                {
                    authenticated = false;
                    ClearCookie();
                }
            }
            catch (Exception ex)
            {
                Debug.LogException(ex);
                ErrorMessage = ex.Message;
                if (ex.InnerException != null)
                {
                    ErrorMessage += "\n" + ex.InnerException.Message;
                }
            }
            finally
            {
                updating = false;
                Repaint();
            }
        }