namespace Mapbox.Editor { using System.Collections.Generic; using UnityEngine; using UnityEditor.SceneManagement; using UnityEditor; using System.IO; using System.Collections; using Mapbox.Unity; using Mapbox.Tokens; using Mapbox.Json; using Mapbox.Unity.Utilities; using Mapbox.Unity.Utilities.DebugTools; using UnityEditor.Callbacks; using System; public class MapboxConfigurationWindow : EditorWindow { public static MapboxConfigurationWindow instance; static MapboxConfiguration _mapboxConfig; static MapboxTokenStatus _currentTokenStatus = MapboxTokenStatus.StatusNotYetSet; static MapboxAccess _mapboxAccess; static bool _waitingToLoad = false; //default mapboxconfig static string _configurationFile; static string _accessToken = ""; [Range(0, 1000)] static int _memoryCacheSize = 500; [Range(0, 3000)] static int _fileCacheSize = 25000; static int _webRequestTimeout = 30; static bool _autoRefreshCache = false; //mapbox access callbacks static bool _listeningForTokenValidation = false; static bool _validating = false; static string _lastValidatedToken; //gui flags bool _showConfigurationFoldout; bool _showChangelogFoldout; Vector2 _scrollPosition; //samples static int _selectedSample; static ScenesList _sceneList; static GUIContent[] _sampleContent; string _sceneToOpen; //prefabs static int _selectedPrefab; static ScenesList _prefabList; static GUIContent[] _prefabContent; //styles GUISkin _skin; Color _defaultContentColor; Color _defaultBackgroundColor; GUIStyle _titleStyle; GUIStyle _bodyStyle; GUIStyle _linkStyle; GUIStyle _textFieldStyle; GUIStyle _submitButtonStyle; GUIStyle _validButtonStyle; Color _validContentColor; Color _validBackgroundColor; GUIStyle _invalidFieldStyle; GUIStyle _invalidButtonStyle; Color _invalidContentColor; Color _invalidBackgroundColor; GUIStyle _errorStyle; GUIStyle _verticalGroup; GUIStyle _horizontalGroup; GUIStyle _scrollViewStyle; GUIStyle _sampleButtonStyle; [DidReloadScripts] public static void ShowWindowOnImport() { if (ShouldShowConfigurationWindow()) { PlayerPrefs.SetInt(Constants.Path.DID_PROMPT_CONFIGURATION, 1); PlayerPrefs.Save(); InitWhenLoaded(); } } [MenuItem("Mapbox/Setup")] static void InitWhenLoaded() { if (EditorApplication.isCompiling && !_waitingToLoad) { //subscribe to updates _waitingToLoad = true; EditorApplication.update += InitWhenLoaded; return; } if (!EditorApplication.isCompiling) { //unsubscribe from updates if waiting if (_waitingToLoad) { EditorApplication.update -= InitWhenLoaded; _waitingToLoad = false; } Init(); } } static void Init() { Runnable.EnableRunnableInEditor(); //verify that the config file exists _configurationFile = Path.Combine(Unity.Constants.Path.MAPBOX_RESOURCES_ABSOLUTE, Unity.Constants.Path.CONFIG_FILE); if (!Directory.Exists(Unity.Constants.Path.MAPBOX_RESOURCES_ABSOLUTE)) { Directory.CreateDirectory(Unity.Constants.Path.MAPBOX_RESOURCES_ABSOLUTE); } if (!File.Exists(_configurationFile)) { _mapboxConfig = new MapboxConfiguration { AccessToken = _accessToken, MemoryCacheSize = (uint)_memoryCacheSize, FileCacheSize = (uint)_fileCacheSize, AutoRefreshCache = _autoRefreshCache, DefaultTimeout = _webRequestTimeout }; var json = JsonUtility.ToJson(_mapboxConfig); File.WriteAllText(_configurationFile, json); AssetDatabase.Refresh(); } //finish opening the window after the assetdatabase is refreshed. EditorApplication.delayCall += OpenWindow; } static void OpenWindow() { EditorApplication.delayCall -= OpenWindow; //setup mapboxaccess listener _mapboxAccess = MapboxAccess.Instance; if (!_listeningForTokenValidation) { _mapboxAccess.OnTokenValidation += HandleValidationResponse; _listeningForTokenValidation = true; } //setup local variables from mapbox config file _mapboxConfig = _mapboxAccess.Configuration; if (_mapboxConfig != null) { _accessToken = _mapboxConfig.AccessToken; _memoryCacheSize = (int)_mapboxConfig.MemoryCacheSize; _fileCacheSize = (int)_mapboxConfig.FileCacheSize; _autoRefreshCache = _mapboxConfig.AutoRefreshCache; _webRequestTimeout = (int)_mapboxConfig.DefaultTimeout; } //validate current config if (!string.IsNullOrEmpty(_accessToken)) { SubmitConfiguration(); } //cache sample scene gui content GetSceneList(); _selectedSample = -1; //instantiate the config window instance = GetWindow(typeof(MapboxConfigurationWindow)) as MapboxConfigurationWindow; instance.minSize = new Vector2(800, 350); instance.titleContent = new GUIContent("Mapbox Setup"); instance.Show(); } static void GetSceneList() { _prefabList = Resources.Load("Mapbox/PrefabList"); _sceneList = Resources.Load("Mapbox/ScenesList"); _prefabContent = LoadContent(_prefabList); _sampleContent = LoadContent(_sceneList); } static GUIContent[] LoadContent(ScenesList list) { //exclude scenes with no image data var content = new List(); if (list != null) { for (int i = 0; i < list.SceneList.Length; i++) { if (list.SceneList[i] != null) { if (File.Exists(list.SceneList[i].ScenePath)) { if (list.SceneList[i].Image != null) { content.Add(list.SceneList[i]); } } } } } var outputContent = new GUIContent[content.Count]; for (int i = 0; i < outputContent.Length; i++) { outputContent[i] = new GUIContent(content[i].Name, content[i].Image, content[i].ScenePath); } return outputContent; } /// /// Unity Events /// private void OnDisable() { AssetDatabase.Refresh(); } private void OnDestroy() { AssetDatabase.Refresh(); } private void OnLostFocus() { AssetDatabase.Refresh(); } /// /// Mapbox access /// private static void SubmitConfiguration() { var mapboxConfiguration = new MapboxConfiguration { AccessToken = _accessToken, MemoryCacheSize = (uint)_memoryCacheSize, FileCacheSize = (uint)_fileCacheSize, AutoRefreshCache = _autoRefreshCache, DefaultTimeout = _webRequestTimeout }; _mapboxAccess.SetConfiguration(mapboxConfiguration, false); _validating = true; } private static void HandleValidationResponse(MapboxTokenStatus status) { _currentTokenStatus = status; _validating = false; _lastValidatedToken = _accessToken; //save the config _configurationFile = Path.Combine(Unity.Constants.Path.MAPBOX_RESOURCES_ABSOLUTE, Unity.Constants.Path.CONFIG_FILE); var json = JsonUtility.ToJson(_mapboxAccess.Configuration); File.WriteAllText(_configurationFile, json); } void OnGUI() { //only run after init if (instance == null) { //TODO: loading message? InitWhenLoaded(); return; } InitStyles(); _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition, _scrollViewStyle); EditorGUILayout.BeginVertical(); // Access token link. DrawAccessTokenLink(); // Access token entry and validation. DrawAccessTokenField(); // Draw the validation error, if one exists DrawError(); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(_verticalGroup); // Configuration DrawConfigurationSettings(); GUILayout.Space(8); // Changelog DrawChangelog(); EditorGUILayout.EndVertical(); // Draw Prefab Examples if (_prefabContent.Length > 0) { EditorGUILayout.BeginVertical(_verticalGroup); DrawPrefabLinks(); EditorGUILayout.EndVertical(); } // Draw Example links if the scenelist asset is where it should be. if (_sampleContent.Length > 0) { EditorGUILayout.BeginVertical(_verticalGroup); DrawExampleLinks(); EditorGUILayout.EndVertical(); } EditorGUILayout.EndScrollView(); } void InitStyles() { _defaultContentColor = GUI.contentColor; _defaultBackgroundColor = GUI.backgroundColor; _titleStyle = new GUIStyle(GUI.skin.FindStyle("IN TitleText")); _titleStyle.padding.left = 3; _bodyStyle = new GUIStyle(GUI.skin.FindStyle("WordWrapLabel")); _linkStyle = new GUIStyle(GUI.skin.FindStyle("PR PrefabLabel")); _linkStyle.padding.left = 0; _linkStyle.padding.top = -1; _textFieldStyle = new GUIStyle(GUI.skin.FindStyle("TextField")); _textFieldStyle.margin.right = 0; _textFieldStyle.margin.top = 0; _submitButtonStyle = new GUIStyle(GUI.skin.FindStyle("ButtonRight")); _submitButtonStyle.padding.top = 0; _submitButtonStyle.margin.top = 0; _submitButtonStyle.fixedWidth = 200; _validButtonStyle = new GUIStyle(GUI.skin.FindStyle("LODSliderRange")); _validButtonStyle.alignment = TextAnchor.MiddleCenter; _validButtonStyle.padding = new RectOffset(0, 0, 0, 0); _validButtonStyle.border = new RectOffset(0, 0, 5, -2); _validButtonStyle.fixedWidth = 60; _validContentColor = new Color(1, 1, 1, .7f); _validBackgroundColor = new Color(.2f, .8f, .2f, 1); _invalidContentColor = new Color(1, 1, 1, .7f); _invalidBackgroundColor = new Color(.8f, .2f, .2f, 1); _errorStyle = new GUIStyle(GUI.skin.FindStyle("ErrorLabel")); _errorStyle.padding.left = 5; _verticalGroup = new GUIStyle(); _verticalGroup.margin = new RectOffset(0, 0, 0, 35); _horizontalGroup = new GUIStyle(); _horizontalGroup.padding = new RectOffset(0, 0, 4, 4); _scrollViewStyle = new GUIStyle(GUI.skin.FindStyle("scrollview")); _scrollViewStyle.padding = new RectOffset(20, 20, 40, 0); _sampleButtonStyle = new GUIStyle(GUI.skin.FindStyle("button")); _sampleButtonStyle.imagePosition = ImagePosition.ImageAbove; _sampleButtonStyle.padding = new RectOffset(0, 0, 5, 5); _sampleButtonStyle.fontStyle = FontStyle.Bold; } void DrawAccessTokenLink() { EditorGUILayout.LabelField("Access Token", _titleStyle); EditorGUILayout.BeginHorizontal(_horizontalGroup); if (string.IsNullOrEmpty(_accessToken)) { //fit box to text to create an 'inline link' GUIContent labelContent = new GUIContent("Copy your free token from"); GUIContent linkContent = new GUIContent("mapbox.com"); EditorGUILayout.LabelField(labelContent, _bodyStyle, GUILayout.Width(_bodyStyle.CalcSize(labelContent).x)); if (GUILayout.Button(linkContent, _linkStyle)) { Application.OpenURL("https://www.mapbox.com/studio/account/tokens/"); } //create link cursor var rect = GUILayoutUtility.GetLastRect(); rect.width = _linkStyle.CalcSize(new GUIContent(linkContent)).x; EditorGUIUtility.AddCursorRect(rect, MouseCursor.Link); GUILayout.FlexibleSpace(); } else { GUIContent labelContent = new GUIContent("Manage your tokens at"); GUIContent linkContent = new GUIContent("mapbox.com/studio/accounts/tokens/"); EditorGUILayout.LabelField(labelContent, _bodyStyle, GUILayout.Width(_bodyStyle.CalcSize(labelContent).x)); if (GUILayout.Button(linkContent, _linkStyle)) { Application.OpenURL("https://www.mapbox.com/studio/account/tokens/"); } //create link cursor var rect = GUILayoutUtility.GetLastRect(); rect.width = _linkStyle.CalcSize(new GUIContent(linkContent)).x; EditorGUIUtility.AddCursorRect(rect, MouseCursor.Link); GUILayout.FlexibleSpace(); } EditorGUILayout.EndHorizontal(); } void DrawAccessTokenField() { EditorGUILayout.BeginHorizontal(_horizontalGroup); //_accessToken is empty if (string.IsNullOrEmpty(_accessToken)) { _accessToken = EditorGUILayout.TextField("", _accessToken, _textFieldStyle); EditorGUI.BeginDisabledGroup(true); GUILayout.Button("Submit", _submitButtonStyle); EditorGUI.EndDisabledGroup(); } else { //_accessToken is being validated if (_validating) { EditorGUI.BeginDisabledGroup(true); _accessToken = EditorGUILayout.TextField("", _accessToken, _textFieldStyle); GUILayout.Button("Checking", _submitButtonStyle); EditorGUI.EndDisabledGroup(); } //_accessToken is the same as the already submitted token else if (string.Equals(_lastValidatedToken, _accessToken)) { //valid token if (_currentTokenStatus == MapboxTokenStatus.TokenValid) { GUI.backgroundColor = _validBackgroundColor; GUI.contentColor = _validContentColor; _accessToken = EditorGUILayout.TextField("", _accessToken, _textFieldStyle); GUILayout.Button("Valid", _validButtonStyle); GUI.contentColor = _defaultContentColor; GUI.backgroundColor = _defaultBackgroundColor; } //invalid token else { GUI.contentColor = _invalidContentColor; GUI.backgroundColor = _invalidBackgroundColor; _accessToken = EditorGUILayout.TextField("", _accessToken, _textFieldStyle); GUILayout.Button("Invalid", _validButtonStyle); GUI.contentColor = _defaultContentColor; GUI.backgroundColor = _defaultBackgroundColor; } //Submit button if (GUILayout.Button("Submit", _submitButtonStyle)) { SubmitConfiguration(); } } //_accessToken is a new, unsubmitted token. else { _accessToken = EditorGUILayout.TextField("", _accessToken, _textFieldStyle); if (GUILayout.Button("Submit", _submitButtonStyle)) { SubmitConfiguration(); } } } EditorGUILayout.EndHorizontal(); } void DrawError() { //draw the error message, if one exists EditorGUILayout.BeginHorizontal(_horizontalGroup); if (_currentTokenStatus != MapboxTokenStatus.TokenValid && _currentTokenStatus != MapboxTokenStatus.StatusNotYetSet && string.Equals(_lastValidatedToken, _accessToken) && !_validating) { EditorGUILayout.LabelField(_currentTokenStatus.ToString(), _errorStyle); } EditorGUILayout.EndHorizontal(); } void DrawChangelog() { EditorGUI.indentLevel = 2; GUIContent linkContent = new GUIContent("v" + Constants.SDK_VERSION + " changelog"); if (GUILayout.Button(linkContent, _linkStyle)) { Application.OpenURL("https://github.com/mapbox/mapbox-unity-sdk/blob/develop/documentation/docs/05-changelog.md"); } EditorGUI.indentLevel = 0; } void DrawConfigurationSettings() { _showConfigurationFoldout = EditorGUILayout.Foldout(_showConfigurationFoldout, "Configuration", true); if (_showConfigurationFoldout) { EditorGUIUtility.labelWidth = 240f; EditorGUI.indentLevel = 2; _memoryCacheSize = EditorGUILayout.IntSlider("Mem Cache Size (# of tiles)", _memoryCacheSize, 0, 1000); _fileCacheSize = EditorGUILayout.IntSlider("File Cache Size (# of tiles)", _fileCacheSize, 0, 3000); _autoRefreshCache = EditorGUILayout.Toggle(new GUIContent("Auto refresh cache", "Automatically update tiles in the local ambient cache if there is a newer version available online. ATTENTION: for every tile displayed (even a cached one) a webrequest needs to be made to check for updates."), _autoRefreshCache); _webRequestTimeout = EditorGUILayout.IntField("Default Web Request Timeout (s)", _webRequestTimeout); EditorGUILayout.BeginHorizontal(_horizontalGroup); GUILayout.Space(35f); if (GUILayout.Button("Save")) { SubmitConfiguration(); } EditorGUI.indentLevel = 0; EditorGUIUtility.labelWidth = 0f; EditorGUILayout.EndHorizontal(); } } void DrawPrefabLinks() { EditorGUI.BeginDisabledGroup(_currentTokenStatus != MapboxTokenStatus.TokenValid || _validating); if (_currentTokenStatus == MapboxTokenStatus.TokenValid) { EditorGUILayout.LabelField("Map Prefabs", _titleStyle); } else { EditorGUILayout.LabelField("Map Prefabs", "Paste your mapbox access token to get started", _titleStyle); } EditorGUILayout.BeginHorizontal(_horizontalGroup); EditorGUILayout.LabelField("Choose a starting scene to see each location-based prefab in action, or go to the prefabs folder and add them to your existing scene.", _bodyStyle); EditorGUILayout.EndHorizontal(); int rowCount = 4; EditorGUILayout.BeginHorizontal(); _selectedPrefab = GUILayout.SelectionGrid(-1, _prefabContent, rowCount, _sampleButtonStyle); if (_selectedPrefab != -1) { EditorApplication.isPaused = false; EditorApplication.isPlaying = false; _sceneToOpen = _prefabContent[_selectedPrefab].tooltip; EditorApplication.update += OpenAndPlayScene; } EditorGUILayout.EndHorizontal(); EditorGUI.EndDisabledGroup(); } void DrawExampleLinks() { EditorGUI.BeginDisabledGroup(_currentTokenStatus != MapboxTokenStatus.TokenValid || _validating); if (_currentTokenStatus == MapboxTokenStatus.TokenValid) { EditorGUILayout.LabelField("Example Scenes", _titleStyle); } else { EditorGUILayout.LabelField("Example Scenes", _titleStyle); } int rowCount = 4; EditorGUILayout.BeginHorizontal(_horizontalGroup); _selectedSample = GUILayout.SelectionGrid(-1, _sampleContent, rowCount, _sampleButtonStyle); if (_selectedSample != -1) { EditorApplication.isPaused = false; EditorApplication.isPlaying = false; _sceneToOpen = _sampleContent[_selectedSample].tooltip; EditorApplication.update += OpenAndPlayScene; } EditorGUILayout.EndHorizontal(); EditorGUI.EndDisabledGroup(); } private void OpenAndPlayScene() { if (EditorApplication.isPlaying) { return; } EditorApplication.update -= OpenAndPlayScene; if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) { EditorSceneManager.OpenScene(_sceneToOpen); EditorApplication.isPlaying = true; var editorWindow = GetWindow(typeof(MapboxConfigurationWindow)); editorWindow.Close(); } else { _sceneToOpen = null; _selectedPrefab = -1; _selectedSample = -1; } } static bool ShouldShowConfigurationWindow() { if (!PlayerPrefs.HasKey(Constants.Path.DID_PROMPT_CONFIGURATION)) { PlayerPrefs.SetInt(Constants.Path.DID_PROMPT_CONFIGURATION, 0); } return PlayerPrefs.GetInt(Constants.Path.DID_PROMPT_CONFIGURATION) == 0; } } }