public void Reload() { this.CreateSettingsFile(); SerializedSettings example = new SerializedSettings(TestDirectory); example.Settings.IntegerValue = Int32.MaxValue; example.Settings.StringValue = Int32.MaxValue.ToString(); example.Settings.ComplexValue.Items.Clear(); // Reload the file. It should not contain any of the data we set // above (since we didn't save). // example.Reload(); Debug.Assert(example.Settings.StringValue == "Test"); Debug.Assert(example.Settings.IntegerValue == 42); Debug.Assert(example.Settings.ComplexValue.Items[0] == "Item 1"); Debug.Assert(example.Settings.ComplexValue.Items[1] == "Item 2"); Debug.Assert(example.Settings.DictionaryValue["A"] == 0); Debug.Assert(example.Settings.DictionaryValue["B"] == 1); Debug.Assert(example.Settings.DictionaryValue["C"] == 2); }
/// <summary> /// Serializes the current settings /// </summary> public string Serialize() { var s = new SerializedSettings(); // Save the settings foreach (var item in Settings) { s.Settings.Add(item.Key, new SerializedValue { TypeName = item.Value.GetType().AssemblyQualifiedName, Value = Json.Serialize(item.Value) }); } // Save the settings that couldn't be opened foreach (var item in UnloadableSettings) { // Make sure there isn't a duplicate // Cases there could be a duplicate: // 1. A setting with the same name was set without a successful load beforehand // 2. A setting was loaded properly, but not removed from UnloadableSettings due to threading if (!s.Settings.ContainsKey(item.Key)) { // This isn't a duplicate s.Settings.Add(item.Key, item.Value); } } return(Json.Serialize(s)); }
/// <summary> /// Checks if a specific key exists in the settings /// </summary> /// <param name="key">Key to check</param> /// <returns>true if existing</returns> public bool CheckSettingsExist(string key) { lock (Lock) { return(SerializedSettings.ContainsKey(key)); } }
public void Reload() { try { using (FileStream stream = File.OpenRead(settingsLocation)) { DataContractJsonSerializer ser = new DataContractJsonSerializer( typeof(SerializedSettings)); serializedSettings = ser.ReadObject(stream) as SerializedSettings; } } catch (Exception e) { API.Instance.Log( "Could not find/load browser settings at location {0}", settingsLocation); API.Instance.Log("Exception: {0}", e); } if (serializedSettings == null) { // initialize with default serializedSettings = new SerializedSettings(); } if (serializedSettings.SourceSettings == null) { serializedSettings.SourceSettings = new BrowserSourceSettings(); } if (serializedSettings.InstanceSettings == null) { serializedSettings.InstanceSettings = new BrowserInstanceSettings(); } if (serializedSettings.RuntimeSettings == null) { serializedSettings.RuntimeSettings = new BrowserRuntimeSettings(); } if (serializedSettings.RuntimeSettings.Plugins == null) { serializedSettings.RuntimeSettings.Plugins = new List <BrowserPlugin>(); } if (serializedSettings.PluginSettings == null) { serializedSettings.PluginSettings = new BrowserPluginSettings(); } if (serializedSettings.PluginSettings.CustomPluginDirectories == null) { serializedSettings.PluginSettings.CustomPluginDirectories = new List <String>(); } if (serializedSettings.PluginSettings.CustomPluginPaths == null) { serializedSettings.PluginSettings.CustomPluginPaths = new List <String>(); } if (serializedSettings.PluginSettings.DisabledPlugins == null) { serializedSettings.PluginSettings.DisabledPlugins = new List <String>(); } }
public void Reset() { // initialize with default serializedSettings = new SerializedSettings(); serializedSettings.SourceSettings = new BrowserSourceSettings(); serializedSettings.InstanceSettings = new BrowserInstanceSettings(); serializedSettings.RuntimeSettings = new BrowserRuntimeSettings(); }
void Notarize() { try { var prop = SerializedSettings.FindProperty("file"); NotarizationProcessor.Notarize(prop.stringValue); } catch (Exception e) { EditorUtility.DisplayDialog("Notarize error", e.Message, "Close"); } }
public void Reload() { JavaScriptSerializer serializer = new JavaScriptSerializer(); try { using (var reader = new StreamReader(settingsLocation)) { serializedSettings = serializer.Deserialize <SerializedSettings>(reader.ReadToEnd()); }; } catch (Exception) { API.Instance.Log("Could not find/load browser settings at location {0}", settingsLocation); } if (serializedSettings == null) { // initialize with default serializedSettings = new SerializedSettings(); } if (serializedSettings.SourceSettings == null) { serializedSettings.SourceSettings = new BrowserSourceSettings(); } if (serializedSettings.InstanceSettings == null) { serializedSettings.InstanceSettings = new BrowserInstanceSettings(); } if (serializedSettings.RuntimeSettings == null) { serializedSettings.RuntimeSettings = new BrowserRuntimeSettings(); } if (serializedSettings.RuntimeSettings.Plugins == null) { serializedSettings.RuntimeSettings.Plugins = new List <BrowserPlugin>(); } if (serializedSettings.PluginSettings == null) { serializedSettings.PluginSettings = new BrowserPluginSettings(); } if (serializedSettings.PluginSettings.CustomPluginDirectories == null) { serializedSettings.PluginSettings.CustomPluginDirectories = new List <String>(); } if (serializedSettings.PluginSettings.CustomPluginPaths == null) { serializedSettings.PluginSettings.CustomPluginPaths = new List <String>(); } if (serializedSettings.PluginSettings.DisabledPlugins == null) { serializedSettings.PluginSettings.DisabledPlugins = new List <String>(); } }
public void DoesNotExist() { SerializedSettings example = new SerializedSettings(TestDirectory); Debug.Assert(File.Exists(this.GetFileName()), "Settings File does not exist"); Debug.Assert(String.IsNullOrWhiteSpace(example.Settings.StringValue)); Debug.Assert(example.Settings.IntegerValue == 0); Debug.Assert(example.Settings.ComplexValue.Items.Count == 0); Debug.Assert(example.Settings.DictionaryValue.Count == 0); }
/// <summary> /// Fetches settings for a given key, returning null if no setting was found /// </summary> /// <typeparam name="T_Item">The type to cast the result to</typeparam> /// <param name="key">The key to fetch the settings for</param> /// <returns>null if not found, the object otherwise</returns> public T_Item FetchSettings <T_Item>(string key) { lock (Lock) { if (!SerializedSettings.ContainsKey(key)) { return(default(T_Item)); } return((T_Item)SerializedSettings[key]); } }
void ValidateFile() { try { var prop = SerializedSettings.FindProperty("file"); NotarizationProcessor.ValidateFile(prop.stringValue); EditorUtility.DisplayDialog("Validation successful", "File successfully notarized", "Close"); } catch (Exception e) { EditorUtility.DisplayDialog("Validation failed", e.Message, "Close"); } }
void Staple() { try { var prop = SerializedSettings.FindProperty("file"); NotarizationProcessor.Staple(prop.stringValue); EditorUtility.DisplayDialog("Stapling successful", "Notarization process complete, you can now distribute the app", "Close"); } catch (Exception e) { EditorUtility.DisplayDialog("Stapling failed", e.Message, "Close"); } }
///-------------------------------------------------------------------- /// <summary> /// Create a dummy file of expected settings. /// </summary> ///-------------------------------------------------------------------- private void CreateSettingsFile() { SerializedSettings example = new SerializedSettings(TestDirectory); example.Settings.StringValue = "Test"; example.Settings.IntegerValue = 42; example.Settings.ComplexValue.Items.Add("Item 1"); example.Settings.ComplexValue.Items.Add("Item 2"); example.Settings.DictionaryValue.Add("A", 0); example.Settings.DictionaryValue.Add("B", 1); example.Settings.DictionaryValue.Add("C", 2); example.Save(); }
internal void UpdateSetting(Setting setting) { var serializedSetting = SerializedSettings.FirstOrDefault(x => x.Name == setting.Name); if (serializedSetting != null) { var newSetting = m_settings.FirstOrDefault(x => x.Name == serializedSetting.Name); serializedSetting.StkSetting = newSetting; } else { SerializedSettings.Add(new SerializedSetting(setting)); } }
public void AlreadyExists() { // Create a settings file that is populated with data we should // expect during this test. // this.CreateSettingsFile(); // Create a new instance. This will load from the file and as // such should contain the settings we persisted. // SerializedSettings example = new SerializedSettings(TestDirectory); Debug.Assert(example.Settings.StringValue == "Test"); Debug.Assert(example.Settings.IntegerValue == 42); Debug.Assert(example.Settings.ComplexValue.Items[0] == "Item 1"); Debug.Assert(example.Settings.ComplexValue.Items[1] == "Item 2"); Debug.Assert(example.Settings.DictionaryValue["A"] == 0); Debug.Assert(example.Settings.DictionaryValue["B"] == 1); Debug.Assert(example.Settings.DictionaryValue["C"] == 2); }
/// <summary> /// Fetches settings for a given key, returning null if no setting was found /// </summary> /// <typeparam name="T_Item">The type to cast the result to</typeparam> /// <param name="key">The key to fetch the settings for</param> /// <returns>null if not found, the object otherwise</returns> public T_Item FetchSettings <T_Item>(string key) { lock (Lock) { try { if (SerializedSettings == null || !SerializedSettings.ContainsKey(key)) { SimpleLogger.Log(SimpleLogLevel.Info, "Settings use default of: " + key); var res = default(T_Item); SerializedSettings.Add(key, res); return(res); } return((T_Item)SerializedSettings[key]); } catch (Exception ex) { SimpleLogger.Log(SimpleLogLevel.Warn, "Fail to fetch settings for: '" + key + "' " + ex.Message); return(default(T_Item)); } } }
/// <summary> /// Deserializes the given data into a settings provider /// </summary> /// <param name="data">Data to deserialize. If null, a new provider will be created.</param> /// <param name="manager">Instance of the current plugin manager</param> /// <returns>A settings provider corresponding to the given data</returns> /// <exception cref="ArgumentNullException">Thrown if <paramref name="manager"/> is null</exception> public static SettingsProvider Deserialize(string data, PluginManager manager) { if (manager == null) { throw new ArgumentNullException(nameof(manager)); } var provider = new SettingsProvider(manager); SerializedSettings s; if (string.IsNullOrEmpty(data)) { s = new SerializedSettings(); } else { s = Json.Deserialize <SerializedSettings>(data); } foreach (var item in s.Settings) { var valueType = ReflectionHelpers.GetTypeByName(item.Value.TypeName, manager); if (valueType == null) { // If the type cannot be loaded, then it's possible that the PluginManager hasn't fully loaded everything yet. // Store the serialized value and try this part again if anyone requests the property. provider.UnloadableSettings[item.Key] = item.Value; } else { provider.Settings[item.Key] = Json.Deserialize(valueType.AsType(), item.Value.Value); } } return(provider); }
void OnGUI() { SerializedSettings.Update(); GUILayout.Label("OSX Build Notarization Settings", EditorStyles.boldLabel); EditorGUILayout.PropertyField(SerializedSettings.FindProperty("user")); EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Password"); string pass = EditorGUILayout.PasswordField(password); if (!string.IsNullOrEmpty(pass)) { password = pass; } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); EditorGUILayout.PropertyField(SerializedSettings.FindProperty("certId")); EditorGUILayout.Space(); EditorGUILayout.PropertyField(SerializedSettings.FindProperty("bundleId")); EditorGUILayout.Space(); EditorGUILayout.Space(); GUILayout.Label("Entitlement options", EditorStyles.boldLabel); EditorGUILayout.PropertyField(SerializedSettings.FindProperty("mono")); EditorGUILayout.PropertyField(SerializedSettings.FindProperty("steamOverlay")); EditorGUILayout.Space(); GuiLine(); GUILayout.Label("Auto notarize options", EditorStyles.boldLabel); EditorGUILayout.PropertyField(SerializedSettings.FindProperty("autoNotarizeOnOSXBuild")); EditorGUILayout.Space(); EditorGUILayout.PropertyField(SerializedSettings.FindProperty("blockUntilFinished")); EditorGUILayout.Space(); GuiLine(); GUILayout.Label("Manual notarization", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(GUILayout.MaxHeight(GUI.skin.button.CalcHeight(new GUIContent("..."), 30))); EditorGUILayout.BeginVertical(LabelMarginStyle); GUILayout.FlexibleSpace(); EditorGUILayout.PropertyField(SerializedSettings.FindProperty("file")); GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(false)); GUILayout.FlexibleSpace(); if (GUILayout.Button("...", GUILayout.ExpandWidth(false))) { var prop = SerializedSettings.FindProperty("file"); string directory = prop.stringValue; if (string.IsNullOrEmpty(prop.stringValue) && !string.IsNullOrEmpty(NotarizationProcessor.lastBuildFile)) { directory = NotarizationProcessor.lastBuildFile; } var fld = EditorUtility.OpenFilePanel("Pick file to notorize and press button", directory, "app"); if (!string.IsNullOrEmpty(fld)) { prop.stringValue = fld; } } GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); GUI.backgroundColor = new Color(0, 0.6f, 0, 1); if (GUILayout.Button("Notarize file", ActionButtonStyle, GUILayout.MinHeight(30))) { Notarize(); } EditorGUILayout.Space(); GUILayout.Label("After successful notarization (email)", EditorStyles.boldLabel); if (GUILayout.Button("Staple ticket to file", ActionButtonStyle, GUILayout.MinHeight(30))) { Staple(); } EditorGUILayout.Space(); GUILayout.Label("Notarization status", EditorStyles.boldLabel); if (GUILayout.Button("Get last status", ActionButtonStyle, GUILayout.MinHeight(30))) { NotarizationStatus(); } if (status != null) { EditorGUILayout.Space(); GUILayout.Label("Last Request: " + status.id, EditorStyles.label); GUILayout.Label("Date: " + status.dateTime, EditorStyles.label); GUILayout.Label("Status: " + (status.success ? "Successful" : "Failed"), EditorStyles.label); GUILayout.TextArea(status.url, EditorStyles.label); } EditorGUILayout.Space(); GUILayout.Label("Notarized file valid", EditorStyles.boldLabel); if (GUILayout.Button("Validate notarized file", ActionButtonStyle, GUILayout.MinHeight(30))) { ValidateFile(); } // GUIContent label = GUI.Label(yourLabelRect, status.url, EditorStyles.linkLabel); // Rect yourLabelRect = GUILayoutUtility.GetRect(status.url, EditorStyles.linkLabel); // if (Event.current.type == EventType.MouseUp && yourLabelRect.Contains(Event.current.mousePosition)) // Application.OpenURL(status.url); // This applies any changes to the underlying asset and marks dirty if needed // this is what ensures the asset gets saved SerializedSettings.ApplyModifiedProperties(); }
/// <summary> /// Save passed settings to settings file /// </summary> /// <param name="view">Main Window reference</param> /// <param name="connectionData"></param> /// <param name="streamData"></param> public void SaveSettings(MainWindow view, SettingsTab.ConnectionSettingsStruct connectionData, RVClient.StreamDataV1[] streamData) { FileStream stream = this.GetSettingsFileStream(view, true); if (stream != null) { SerializedSettings settings = new SerializedSettings(); settings.connectionData = connectionData; settings.streamData = streamData; XmlSerializer serializer = new XmlSerializer(typeof(SerializedSettings)); try { serializer.Serialize(stream, settings); } catch { view.WriteLog("Error: Could not save new settings"); stream.Close(); return; } stream.Close(); view.WriteLog("New settings saved successfully"); } }
/// <summary> /// Initializes the settings file with default data /// </summary> /// <param name="stream">Settings file opened stream</param> /// <remarks>This method is used as WinAppStock initializer</remarks> private void InitializeSettingsFile(FileStream stream) { SettingsTab.ConnectionSettingsStruct connectionData = new SettingsTab.ConnectionSettingsStruct() { host = "127.0.0.1", port = 27960, period = 5, username = "******", password = "******" }; RVClient.StreamDataV1[] streamData = new RVClient.StreamDataV1[1]; streamData[0].streamName = "my_local_stream_name"; streamData[0].port = 554; streamData[0].proxiedName = "my_stream_name"; SerializedSettings settings = new SerializedSettings(); settings.connectionData = connectionData; settings.streamData = streamData; XmlSerializer serializer = new XmlSerializer(typeof(SerializedSettings)); serializer.Serialize(stream, settings); }
void OnGUI() { // Use SerializedObject as a proxy to get dirty flags, undo & asset save GUILayout.Label("Output Settings", EditorStyles.boldLabel); // Need to use nested verticals and flexible space to align text & button vertically EditorGUILayout.BeginHorizontal(GUILayout.MaxHeight(GUI.skin.button.CalcHeight(new GUIContent("..."), 30))); // Also need a style on label to make it line up on the left edge EditorGUILayout.BeginVertical(LabelMarginStyle); GUILayout.FlexibleSpace(); EditorGUILayout.PropertyField(SerializedSettings.FindProperty("outputFolder")); GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(false)); GUILayout.FlexibleSpace(); if (GUILayout.Button("...", GUILayout.ExpandWidth(false))) { var prop = SerializedSettings.FindProperty("outputFolder"); var fld = EditorUtility.OpenFolderPanel("Pick build folder", prop.stringValue, PlayerSettings.productName); if (!string.IsNullOrEmpty(fld)) { prop.stringValue = fld; } } GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); EditorGUILayout.PropertyField(SerializedSettings.FindProperty("useProductName")); if (!Settings.useProductName) { EditorGUILayout.PropertyField(SerializedSettings.FindProperty("overrideName")); } EditorGUILayout.Space(); GUILayout.Label("Platforms To Build", EditorStyles.boldLabel); bool removeTargetAtEnd = false; BuildTarget targetToRemove = BuildTarget.iOS; foreach (var target in Settings.targets) { EditorGUILayout.BeginHorizontal(RemoveButtonContainerStyle, GUILayout.MaxHeight(23)); EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(false), GUILayout.MinWidth(30)); GUILayout.FlexibleSpace(); GUI.backgroundColor = new Color(0.6f, 0, 0, 1); if (GUILayout.Button(" X ", ActionButtonStyle)) { // Don't do this now, breaks iteration targetToRemove = target; removeTargetAtEnd = true; } GUI.backgroundColor = Color.white; GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(); GUILayout.FlexibleSpace(); EditorGUILayout.LabelField(target.ToString()); GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); } if (Settings.targets.Count == 0) { GUILayout.Label("No platforms selected! Add one below.", EditorStyles.centeredGreyMiniLabel); } EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(GUILayout.MaxHeight(GUI.skin.button.CalcHeight(new GUIContent("..."), 30))); EditorGUILayout.BeginVertical(LabelMarginStyle); GUILayout.FlexibleSpace(); GUILayout.Label("Add platform"); GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(); GUILayout.FlexibleSpace(); BuildTarget[] targets = (BuildTarget[])Enum.GetValues(typeof(BuildTarget)); string[] values = new string[targets.Length]; for (int i = 0; i < targets.Length; i++) { values[i] = targets[i].ToString(); } _targetToAddIndex = EditorGUILayout.Popup(_targetToAddIndex, values); GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(false)); GUILayout.FlexibleSpace(); if (GUILayout.Button("Add")) { var proplist = SerializedSettings.FindProperty("targets"); proplist.arraySize++; SerializedProperty targetEnum = proplist.GetArrayElementAtIndex(proplist.arraySize - 1); int index = 0; foreach (string name in targetEnum.enumNames) { if (name.ToLower().Equals(targets[_targetToAddIndex].ToString().ToLower())) { break; } index++; } proplist.GetArrayElementAtIndex(proplist.arraySize - 1).enumValueIndex = index; _targetsDirty = true; } GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); GUILayout.Label("Additional options", EditorStyles.boldLabel); EditorGUILayout.PropertyField(SerializedSettings.FindProperty("developmentBuild")); EditorGUILayout.PropertyField(SerializedSettings.FindProperty("compress")); if (removeTargetAtEnd) { int index = Settings.targets.IndexOf(targetToRemove); var proplist = SerializedSettings.FindProperty("targets"); proplist.DeleteArrayElementAtIndex(index); _targetsDirty = true; } // This applies any changes to the underlying asset and marks dirty if needed // this is what ensures the asset gets saved SerializedSettings.ApplyModifiedProperties(); if (_targetsDirty) { Repaint(); } EditorGUILayout.Space(); EditorGUILayout.Space(); GUI.backgroundColor = new Color(0, 0.6f, 0, 1); if (GUILayout.Button("Build Selected Platforms", ActionButtonStyle, GUILayout.MinHeight(30))) { // do eet Build(); } }
void OnGUI() { if (_targetsDirty) { UpdateTargetsNotAdded(); } // Use SerializedObject as a proxy to get dirty flags, undo & asset save GUILayout.Label("Output Settings", EditorStyles.boldLabel); // Need to use nested verticals and flexible space to align text & button vertically EditorGUILayout.BeginHorizontal(GUILayout.MaxHeight(GUI.skin.button.CalcHeight(new GUIContent("..."), 30))); // Also need a style on label to make it line up on the left edge EditorGUILayout.BeginVertical(LabelMarginStyle); GUILayout.FlexibleSpace(); EditorGUILayout.PropertyField(SerializedSettings.FindProperty("outputFolder")); GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(false)); GUILayout.FlexibleSpace(); if (GUILayout.Button("...", GUILayout.ExpandWidth(false))) { var prop = SerializedSettings.FindProperty("outputFolder"); var fld = EditorUtility.OpenFolderPanel("Pick build folder", prop.stringValue, PlayerSettings.productName); if (!string.IsNullOrEmpty(fld)) { prop.stringValue = fld; } } GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); EditorGUILayout.PropertyField(SerializedSettings.FindProperty("useProductName")); if (!Settings.useProductName) { EditorGUILayout.PropertyField(SerializedSettings.FindProperty("overrideName")); } EditorGUILayout.Space(); GUILayout.Label("Platforms To Build", EditorStyles.boldLabel); bool removeTargetAtEnd = false; Target targetToRemove = Target.iOS; foreach (var target in Settings.targets) { EditorGUILayout.BeginHorizontal(RemoveButtonContainerStyle, GUILayout.MaxHeight(23)); EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(false), GUILayout.MinWidth(30)); GUILayout.FlexibleSpace(); GUI.backgroundColor = new Color(0.6f, 0, 0, 1); if (GUILayout.Button(" X ", ActionButtonStyle)) { // Don't do this now, breaks iteration targetToRemove = target; removeTargetAtEnd = true; } GUI.backgroundColor = Color.white; GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(); GUILayout.FlexibleSpace(); EditorGUILayout.LabelField(TargetNames[target]); GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); } if (Settings.targets.Count == 0) { GUILayout.Label("No platforms selected! Add one below.", EditorStyles.centeredGreyMiniLabel); } EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(GUILayout.MaxHeight(GUI.skin.button.CalcHeight(new GUIContent("..."), 30))); EditorGUILayout.BeginVertical(LabelMarginStyle); GUILayout.FlexibleSpace(); GUILayout.Label("Add platform"); GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(); GUILayout.FlexibleSpace(); _targetToAddIndex = EditorGUILayout.Popup(_targetToAddIndex, _targetNamesNotAdded.ToArray()); GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(false)); GUILayout.FlexibleSpace(); if (GUILayout.Button("Add")) { // Ugh dealing with arrays in SerializedObject is awful string newTargetName = _targetNamesNotAdded[_targetToAddIndex]; Target newTarget = TargetNameToValue[newTargetName]; // Insert in order var proplist = SerializedSettings.FindProperty("targets"); int insertIndex; for (insertIndex = 0; insertIndex < proplist.arraySize; ++insertIndex) { string name = TargetNames[(Target)proplist.GetArrayElementAtIndex(insertIndex).enumValueIndex]; if (string.Compare(newTargetName, name, true) < 0) { break; } } proplist.arraySize++; // Move all existing items forward to make room for insert in order for (int i = proplist.arraySize - 1; i > insertIndex; --i) { proplist.GetArrayElementAtIndex(i).enumValueIndex = proplist.GetArrayElementAtIndex(i - 1).enumValueIndex; } proplist.GetArrayElementAtIndex(insertIndex).enumValueIndex = (int)newTarget; _targetsDirty = true; } GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); GUILayout.Label("Additional options", EditorStyles.boldLabel); EditorGUILayout.PropertyField(SerializedSettings.FindProperty("developmentBuild")); if (removeTargetAtEnd) { int index = Settings.targets.IndexOf(targetToRemove); var proplist = SerializedSettings.FindProperty("targets"); proplist.DeleteArrayElementAtIndex(index); _targetsDirty = true; } // This applies any changes to the underlying asset and marks dirty if needed // this is what ensures the asset gets saved SerializedSettings.ApplyModifiedProperties(); if (_targetsDirty) { Repaint(); } EditorGUILayout.Space(); EditorGUILayout.Space(); GUI.backgroundColor = new Color(0, 0.6f, 0, 1); if (GUILayout.Button("Build Selected Platforms", ActionButtonStyle, GUILayout.MinHeight(30))) { // do eet Build(); } }