Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #if UNITY_EDITOR
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using CityGen3D;
- using UnityEditor;
- using UnityEngine;
- /*
- NOTE: When using Data on a CityGen3D object in the scene hierarchy that links back to a prefab,
- for some reason, the types/tags lists in the various Data categories seem to get refreshed from the prefab when
- you reload Unity, which overwrites any changes made in the hierarchy copy. This happens even if not using this tool
- and just adding/deleting types or tags using the CityGen3D Data interface - either the prefab instance needs to be unpacked,
- or you need to remember to clear the data and then apply overrides back to the prefab after making edits
- */
- namespace Tesseraction.CityGenExtensions
- {
- public class BrowseOsmTagsWindow : EditorWindow
- {
- private const float FixedWindowWidth = 500f;
- private const float DefaultWindowHeight = 800f;
- private const float MinWindowHeight = 500f;
- private const float MaxWindowHeight = 4000f;
- private const string IsTagKnownColor = "<color=lime>";
- private const string TagFilterColor = "<color=yellow><b>";
- private const string TagKnownFilterColor = "<color=olive><b>";
- private Vector2 _overallScrollPos;
- private Dictionary<Database, bool> _foldoutNodes = new ();
- private Dictionary<Database, bool> _foldoutRelations = new ();
- private Dictionary<Database, bool> _foldoutWays = new ();
- private readonly Dictionary<string, Database> _databases = new ();
- private Dictionary<Database, Dictionary<string, TagCounts>> _tagCountsNodes = new ();
- private Dictionary<Database, Dictionary<string, TagCounts>> _tagCountsRelations = new ();
- private Dictionary<Database, Dictionary<string, TagCounts>> _tagCountsWays = new ();
- private readonly Dictionary<string, TagCounts> _tagDropdowns = new ();
- private Dictionary<string, HashSet<string>> _knownTags = new ();
- private Dictionary<string, HashSet<string>> _knownSurfaceTags = new ();
- private Dictionary<string, HashSet<string>> _knownRoadTags = new ();
- private Dictionary<string, HashSet<string>> _knownBuildingTags = new ();
- private Dictionary<string, HashSet<string>> _knownEntityTags = new ();
- private Dictionary<string, HashSet<string>> _knownFeatureTags = new ();
- private Dictionary<string, HashSet<string>> _knownTreeTags = new ();
- private bool _isInitialized;
- private string _searchField = "";
- private bool _searchFilterTag;
- private bool _searchFilterValue;
- [MenuItem ("Tools/CityGen3D/Browse OSM Tags", priority = 12)]
- private static void InitializeFromMenuOption ()
- {
- BrowseOsmTagsWindow window = (BrowseOsmTagsWindow) GetWindow (typeof (BrowseOsmTagsWindow));
- window.Initialize (FixedWindowWidth, DefaultWindowHeight);
- }
- public void Reset ()
- {
- BrowseOsmTagsWindow window = (BrowseOsmTagsWindow) GetWindow (typeof (BrowseOsmTagsWindow));
- window.titleContent = new GUIContent ("Browse OSM Tags");
- Initialize (window.position.width, window.position.height);
- }
- private void Initialize (float windowWidth, float windowHeight)
- {
- Map map = Map.Instance;
- {
- if (map == null)
- {
- Debug.LogError ("No CityGen3D Map object in scene");
- return;
- }
- }
- _searchField = string.Empty;
- _searchFilterTag = false;
- _searchFilterValue = false;
- _foldoutNodes.Clear ();
- _foldoutRelations.Clear ();
- _foldoutWays.Clear ();
- _databases.Clear ();
- _tagCountsNodes.Clear ();
- _tagCountsRelations.Clear ();
- _tagCountsWays.Clear ();
- _tagDropdowns.Clear ();
- _knownTags.Clear ();
- _knownSurfaceTags.Clear ();
- _knownRoadTags.Clear ();
- _knownBuildingTags.Clear ();
- _knownEntityTags.Clear ();
- _knownFeatureTags.Clear ();
- _knownTreeTags.Clear ();
- if (Map.Instance.mapSurfaces != null)
- {
- foreach (ObjectTag tags in Map.Instance.mapSurfaces.surfaceTags)
- {
- AddKnownTag (ref _knownTags, tags);
- AddKnownTag (ref _knownSurfaceTags, tags);
- }
- }
- if (Map.Instance.mapRoads != null)
- {
- foreach (ObjectTag tags in Map.Instance.mapRoads.roadTags)
- {
- AddKnownTag (ref _knownTags, tags);
- AddKnownTag (ref _knownRoadTags, tags);
- }
- }
- if (Map.Instance.mapBuildings != null)
- {
- foreach (ObjectTag tags in Map.Instance.mapBuildings.buildingTags)
- {
- AddKnownTag (ref _knownTags, tags);
- AddKnownTag (ref _knownBuildingTags, tags);
- }
- }
- if (Map.Instance.mapEntities != null)
- {
- foreach (ObjectTag tags in Map.Instance.mapEntities.entityTags)
- {
- AddKnownTag (ref _knownTags, tags);
- AddKnownTag (ref _knownEntityTags, tags);
- }
- }
- if (Map.Instance.mapFeatures != null)
- {
- foreach (ObjectTag tags in Map.Instance.mapFeatures.featureTags)
- {
- AddKnownTag (ref _knownTags, tags);
- AddKnownTag (ref _knownFeatureTags, tags);
- }
- }
- if (Map.Instance.mapTrees != null)
- {
- foreach (ObjectTag tags in Map.Instance.mapTrees.treeTags)
- {
- AddKnownTag (ref _knownTags, tags);
- AddKnownTag (ref _knownTreeTags, tags);
- }
- }
- SetInitialWindowRectSize (windowWidth, windowHeight);
- SetFlexibleWindowRectSize ();
- string databasePath = Path.Combine (Application.dataPath, "Database");
- string [] databaseFiles = Directory.GetFiles (databasePath);
- if (databaseFiles.Length == 0)
- {
- return;
- }
- _foldoutNodes = new Dictionary<Database, bool> ();
- _foldoutRelations = new Dictionary<Database, bool> ();
- _foldoutWays = new Dictionary<Database, bool> ();
- string filePath = string.Empty;
- foreach (string databaseFile in databaseFiles)
- {
- if (databaseFile.EndsWith (".meta"))
- {
- continue;
- }
- string fileName = Path.GetFileName (databaseFile);
- filePath = Path.Combine ("Assets", "Database", fileName);
- _databases.Add (filePath, null);
- }
- if (_databases.Count == 1)
- {
- LoadDatabase (filePath);
- }
- _isInitialized = true;
- }
- private static void AddKnownTag (ref Dictionary<string, HashSet<string>> tagSet, ObjectTag tags)
- {
- if (!tagSet.ContainsKey (tags.tag.key))
- {
- tagSet.Add (tags.tag.key, new HashSet<string> ());
- }
- if (!tagSet [tags.tag.key].Contains (tags.tag.value))
- {
- tagSet [tags.tag.key].Add (tags.tag.value);
- }
- }
- private void LoadDatabase (string filePath)
- {
- Database db = AssetDatabase.LoadAssetAtPath<Database> (filePath);
- if (db == null)
- {
- throw new MissingComponentException ();
- }
- _foldoutNodes.Add (db, false);
- _foldoutRelations.Add (db, false);
- _foldoutWays.Add (db, false);
- List<List<OSM_Tag>> allNodeTags = db.mapNodes.Select (x => x.tags).ToList ();
- LoadTagsAndCounts (ref _tagCountsNodes, allNodeTags, db);
- List<List<OSM_Tag>> allRelationTags = db.mapRelations.Select (x => x.tags).ToList ();
- LoadTagsAndCounts (ref _tagCountsRelations, allRelationTags, db);
- List<List<OSM_Tag>> allWayTags = db.mapWays.Select (x => x.tags).ToList ();
- LoadTagsAndCounts (ref _tagCountsWays, allWayTags, db);
- _databases [filePath] = db;
- }
- private void LoadTagsAndCounts (
- ref Dictionary<Database, Dictionary<string, TagCounts>> tagCountSet,
- List<List<OSM_Tag>> allTags,
- Database db)
- {
- HashSet<string> uniqueTags = new ();
- Dictionary<string, TagCounts> tagCounts = new ();
- foreach (List<OSM_Tag> tagSet in allTags)
- {
- uniqueTags.UnionWith (tagSet.Select (x => x.key));
- }
- List<string> sortedTags = new (uniqueTags);
- sortedTags.Sort ();
- foreach (string tag in sortedTags)
- {
- tagCounts.Add (tag, new TagCounts (0, new Dictionary<string, int> ()));
- }
- foreach (List<OSM_Tag> tagSet in allTags)
- {
- foreach (OSM_Tag osmTag in tagSet)
- {
- tagCounts [osmTag.key].count++;
- if (!tagCounts [osmTag.key].valueCounts.ContainsKey (osmTag.value))
- {
- tagCounts [osmTag.key].valueCounts.Add (osmTag.value, 0);
- }
- tagCounts [osmTag.key].valueCounts [osmTag.value]++;
- }
- }
- tagCountSet.Add (db, tagCounts);
- foreach (KeyValuePair<string, TagCounts> pair in tagCounts)
- {
- if (!_tagDropdowns.ContainsKey (pair.Key))
- {
- _tagDropdowns.Add (pair.Key, new TagCounts (pair.Value.count, new Dictionary<string, int> ()));
- }
- foreach (KeyValuePair<string, int> valuePair in pair.Value.valueCounts)
- {
- if (!_tagDropdowns [pair.Key].valueCounts.ContainsKey (valuePair.Key))
- {
- _tagDropdowns [pair.Key].valueCounts.Add (valuePair.Key, 0);
- }
- }
- }
- }
- private static BrowseOsmTagsWindow GetWindowReference ()
- {
- // Get the window without changing the focus away from the current window
- return (BrowseOsmTagsWindow) GetWindow (typeof (BrowseOsmTagsWindow), false, "Find OSM Tags", false);
- }
- private static void SetInitialWindowRectSize (float windowWidth, float windowHeight)
- {
- BrowseOsmTagsWindow window = GetWindowReference ();
- window.minSize = new Vector2 (windowWidth, windowHeight);
- window.maxSize = new Vector2 (windowWidth, windowHeight);
- }
- private static void SetFlexibleWindowRectSize ()
- {
- BrowseOsmTagsWindow window = GetWindowReference ();
- window.minSize = new Vector2 (FixedWindowWidth, MinWindowHeight);
- window.maxSize = new Vector2 (FixedWindowWidth, MaxWindowHeight);
- }
- private void OnGUI ()
- {
- BrowseOsmTagsWindow window = GetWindowReference ();
- float windowWidth = window.position.width;
- float windowHeight = window.position.height;
- GUIStyle labelStyle = new (EditorStyles.label) { richText = true };
- GUILayoutOption loadButtonWidth = GUILayout.Width (90f);
- GUILayoutOption exportButtonWidth = GUILayout.Width (90f);
- GUILayoutOption resetButtonWidth = GUILayout.Width (90f);
- GUILayoutOption searchFieldWidth = GUILayout.Width (windowWidth * 0.8f);
- GUILayoutOption searchToggleWidth = GUILayout.Width (windowWidth * 0.025f);
- GUILayoutOption searchIconWidth = GUILayout.Width (windowWidth * 0.05f);
- GUILayoutOption headerWidth = GUILayout.Width (windowWidth * 0.75f);
- GUILayoutOption databaseWidth = GUILayout.Width (windowWidth * 0.75f);
- const float iconSize = 16f;
- if (!_isInitialized)
- {
- EditorGUILayout.BeginHorizontal ();
- GUILayout.Label ("<color=red>Editor window not yet initialized</color>", labelStyle, headerWidth);
- if (GUILayout.Button ("Reset", resetButtonWidth))
- {
- Reset ();
- }
- EditorGUILayout.EndHorizontal ();
- return;
- }
- // Assumes at least nodes always present in each database
- if (_databases.Keys.Count == 0)
- {
- string databasePath = Path.Combine (Application.dataPath, "Database");
- string [] databaseFiles = Directory.GetFiles (databasePath);
- if (databaseFiles.Length == 0)
- {
- EditorGUILayout.BeginHorizontal ();
- GUILayout.Label ("<color=red>No OSM databases found</color>", labelStyle, headerWidth);
- if (GUILayout.Button ("Reset", resetButtonWidth))
- {
- Reset ();
- }
- EditorGUILayout.EndHorizontal ();
- return;
- }
- Reset ();
- }
- _overallScrollPos = EditorGUILayout.BeginScrollView (_overallScrollPos,
- GUILayout.Width (windowWidth), GUILayout.Height (windowHeight));
- EditorGUILayout.BeginHorizontal ();
- GUILayout.Label ("<color=green>" + _databases.Keys.Count + " OSM database" +
- (_databases.Keys.Count == 1 ? " " : "s ") + "found</color>", labelStyle, headerWidth);
- if (GUILayout.Button ("Reset", resetButtonWidth))
- {
- Reset ();
- }
- EditorGUILayout.EndHorizontal ();
- GUILayout.Space (10);
- Vector2 oldIconSize = EditorGUIUtility.GetIconSize ();
- EditorGUIUtility.SetIconSize (new Vector2 (iconSize, iconSize));
- EditorGUILayout.BeginHorizontal ();
- _searchField = GUILayout.TextField (_searchField, searchFieldWidth);
- GUIContent icon = EditorGUIUtility.IconContent ("d_Search Icon");
- EditorGUILayout.LabelField (icon, searchIconWidth);
- _searchFilterTag = GUILayout.Toggle (_searchFilterTag, new GUIContent ("", "Filter tags"), searchToggleWidth);
- _searchFilterValue = GUILayout.Toggle (_searchFilterValue, new GUIContent ("", "Filter values"), searchToggleWidth);
- EditorGUILayout.EndHorizontal ();
- EditorGUIUtility.SetIconSize (oldIconSize);
- bool hasSearch = !string.IsNullOrEmpty (_searchField);
- foreach (string filePath in _databases.Keys.ToArray ())
- {
- Database database = _databases [filePath];
- GUILayout.Space (10);
- if (database == null)
- {
- EditorGUILayout.BeginHorizontal ();
- GUILayout.Label ("<color=lightblue>Database at path " +
- Path.GetFileNameWithoutExtension (filePath) + "</color>", labelStyle, databaseWidth);
- if (GUILayout.Button ("Load", loadButtonWidth))
- {
- EditorUtility.ClearProgressBar ();
- EditorUtility.DisplayProgressBar ("Loading data", "Loading OSM data from " +
- Path.GetFileNameWithoutExtension (filePath), 0.5f);
- LoadDatabase (filePath);
- EditorUtility.ClearProgressBar ();
- }
- EditorGUILayout.EndHorizontal ();
- continue;
- }
- EditorGUILayout.BeginHorizontal ();
- GUILayout.Label ("<color=cyan>Database " + database.name + "</color>", labelStyle, databaseWidth);
- if (GUILayout.Button ("Export", exportButtonWidth))
- {
- ExportCsvDataToClipboard (database);
- }
- EditorGUILayout.EndHorizontal ();
- string searchTagReplacement = TagFilterColor + _searchField + "</b></color>";
- string searchKnownTagReplacement = TagKnownFilterColor + _searchField + "</b></color>";
- GUILayout.Space (6);
- ProcessTags (
- database,
- ref _tagCountsNodes,
- ref _foldoutNodes,
- hasSearch,
- searchTagReplacement,
- searchKnownTagReplacement,
- "Nodes",
- windowWidth);
- GUILayout.Space (6);
- ProcessTags (
- database,
- ref _tagCountsRelations,
- ref _foldoutRelations,
- hasSearch,
- searchTagReplacement,
- searchKnownTagReplacement,
- "Relations",
- windowWidth);
- GUILayout.Space (6);
- ProcessTags (
- database,
- ref _tagCountsWays,
- ref _foldoutWays,
- hasSearch,
- searchTagReplacement,
- searchKnownTagReplacement,
- "Ways",
- windowWidth);
- }
- EditorGUILayout.EndScrollView ();
- }
- private void ProcessTags (
- Database database,
- ref Dictionary<Database, Dictionary<string, TagCounts>> tagCountSet,
- ref Dictionary<Database, bool> foldoutSet,
- bool hasSearch,
- string searchTagReplacement,
- string searchKnownTagReplacement,
- string setType,
- float windowWidth)
- {
- GUIStyle labelStyle = new (EditorStyles.label) { richText = true };
- GUIStyle rightJustifiedLabelStyle = new (EditorStyles.label) { richText = true, alignment = TextAnchor.MiddleRight };
- GUILayoutOption addButtonWidth = GUILayout.Width (40f);
- GUILayoutOption deleteButtonWidth = GUILayout.Width (40f);
- GUILayoutOption tagWidth = GUILayout.Width (windowWidth * 0.4f);
- GUILayoutOption countWidth = GUILayout.Width (windowWidth * 0.15f);
- GUILayoutOption indentedToggleWidth = GUILayout.Width (windowWidth * 0.14f);
- GUILayoutOption indentedWidth = GUILayout.Width (windowWidth * 0.05f);
- int countTags = tagCountSet [database].Keys.Count;
- int countValues = 0;
- foreach (TagCounts tagCounts in tagCountSet [database].Values)
- {
- countValues += tagCounts.count;
- }
- string setTitle = setType + " -- " + countTags.ToString ("N0") + " keys, " + countValues.ToString ("N0") + " values";
- foldoutSet [database] = EditorGUILayout.Foldout (foldoutSet [database], setTitle);
- if (!foldoutSet [database])
- {
- return;
- }
- EditorGUILayout.BeginVertical ();
- foreach (string tag in tagCountSet [database].Keys)
- {
- Dictionary<string, int> sortedValues = tagCountSet [database] [tag].valueCounts;
- if (hasSearch && !tag.Contains (_searchField))
- {
- if (_searchFilterTag && !sortedValues.Any (x => x.Key.Contains (_searchField)))
- {
- continue;
- }
- }
- string tagDisplay = tag;
- string knownTagDisplay = tag;
- if (hasSearch && tag.Contains (_searchField))
- {
- tagDisplay = tagDisplay.Replace (_searchField, searchTagReplacement);
- knownTagDisplay = knownTagDisplay.Replace (_searchField, searchKnownTagReplacement);
- }
- EditorGUILayout.BeginHorizontal ();
- bool isTagKnown = _knownTags.ContainsKey (tag);
- if (isTagKnown)
- {
- GUILayout.Label (IsTagKnownColor + knownTagDisplay + "</color>", labelStyle, tagWidth);
- }
- else
- {
- GUILayout.Label ("<color=white>" + tagDisplay + "</color>", labelStyle, tagWidth);
- }
- GUILayout.Label (tagCountSet [database] [tag].count.ToString ("N0"), rightJustifiedLabelStyle, countWidth);
- GUILayout.Label ("", labelStyle, indentedToggleWidth);
- tagCountSet [database] [tag].showToggle = GUILayout.Toggle (
- tagCountSet [database] [tag].showToggle, " " + sortedValues.Count.ToString ("N0"), indentedToggleWidth);
- if (tagCountSet [database] [tag].showToggle)
- {
- EditorGUILayout.EndHorizontal ();
- EditorGUILayout.BeginVertical ();
- foreach (string sortedValue in sortedValues.Keys)
- {
- if (hasSearch && !sortedValue.Contains (_searchField))
- {
- if (_searchFilterValue)
- {
- continue;
- }
- }
- string sortedDisplay = sortedValue;
- string sortedKnownDisplay = sortedValue;
- if (hasSearch && sortedValue.Contains (_searchField))
- {
- sortedDisplay = sortedDisplay.Replace (_searchField, searchTagReplacement);
- sortedKnownDisplay = sortedKnownDisplay.Replace (_searchField, searchKnownTagReplacement);
- }
- EditorGUILayout.BeginHorizontal ();
- GUILayout.Label ("", labelStyle, indentedWidth);
- if (!isTagKnown)
- {
- GUILayout.Label ("<color=white>" + sortedDisplay + "</color>", labelStyle, tagWidth);
- }
- else
- {
- bool isKnown = _knownTags.ContainsKey (tag) && _knownTags [tag].Contains (sortedValue);
- if (isKnown)
- {
- GUILayout.Label (IsTagKnownColor + sortedKnownDisplay + "</color>", labelStyle, tagWidth);
- }
- else
- {
- GUILayout.Label ("<color=white>" + sortedDisplay + "</color>", labelStyle, tagWidth);
- }
- }
- int count = tagCountSet [database] [tag].valueCounts [sortedValue];
- GUILayout.Label (count.ToString ("N0"), rightJustifiedLabelStyle, countWidth);
- string alreadyTagged = string.Empty;
- ObjectTag selected = null;
- string [] options =
- {
- "None", "Surfaces", "Roads", "Buildings", "Entities", "Features", "Trees"
- };
- if (_knownSurfaceTags.ContainsKey (tag) && _knownSurfaceTags [tag].Contains (sortedValue))
- {
- alreadyTagged = "Surfaces";
- options = Map.Instance.mapSurfaces.surfaces.Select (x => x.name).ToArray ();
- selected = Map.Instance.mapSurfaces.surfaceTags
- .FirstOrDefault (x => x.tag.key == tag && x.tag.value == sortedValue);
- }
- if (_knownRoadTags.ContainsKey (tag) && _knownRoadTags [tag].Contains (sortedValue))
- {
- alreadyTagged = "Roads";
- options = Map.Instance.mapRoads.roads.Select (x => x.name).ToArray ();
- selected = Map.Instance.mapRoads.roadTags
- .FirstOrDefault (x => x.tag.key == tag && x.tag.value == sortedValue);
- }
- if (_knownBuildingTags.ContainsKey (tag) && _knownBuildingTags [tag].Contains (sortedValue))
- {
- alreadyTagged = "Buildings";
- options = Map.Instance.mapBuildings.buildings.Select (x => x.name).ToArray ();
- selected = Map.Instance.mapBuildings.buildingTags
- .FirstOrDefault (x => x.tag.key == tag && x.tag.value == sortedValue);
- }
- if (_knownEntityTags.ContainsKey (tag) && _knownEntityTags [tag].Contains (sortedValue))
- {
- alreadyTagged = "Entities";
- options = Map.Instance.mapEntities.entities.Select (x => x.name).ToArray ();
- selected = Map.Instance.mapEntities.entityTags
- .FirstOrDefault (x => x.tag.key == tag && x.tag.value == sortedValue);
- }
- if (_knownFeatureTags.ContainsKey (tag) && _knownFeatureTags [tag].Contains (sortedValue))
- {
- alreadyTagged = "Features";
- options = Map.Instance.mapFeatures.features.Select (x => x.name).ToArray ();
- selected = Map.Instance.mapFeatures.featureTags
- .FirstOrDefault (x => x.tag.key == tag && x.tag.value == sortedValue);
- }
- if (_knownTreeTags.ContainsKey (tag) && _knownTreeTags [tag].Contains (sortedValue))
- {
- alreadyTagged = "Trees";
- options = Map.Instance.mapTrees.trees.Select (x => x.name).ToArray ();
- selected = Map.Instance.mapTrees.treeTags
- .FirstOrDefault (x => x.tag.key == tag && x.tag.value == sortedValue);
- }
- if (!string.IsNullOrEmpty (alreadyTagged))
- {
- if (selected == null)
- {
- ClearKnownTags (tag, sortedValue, alreadyTagged);
- }
- else
- {
- _tagDropdowns [tag].valueCounts [sortedValue] = selected.index;
- _tagDropdowns [tag].valueCounts [sortedValue] =
- EditorGUILayout.Popup (_tagDropdowns [tag].valueCounts [sortedValue], options);
- if (_tagDropdowns [tag].valueCounts [sortedValue] != selected.index)
- {
- switch (alreadyTagged)
- {
- case "Surfaces":
- Undo.RecordObject (Map.Instance.mapSurfaces, "Change surface dropdown type");
- selected.index = _tagDropdowns [tag].valueCounts [sortedValue];
- EditorUtility.SetDirty (Map.Instance.mapSurfaces);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapSurfaces);
- break;
- case "Roads":
- Undo.RecordObject (Map.Instance.mapRoads, "Change road dropdown type");
- selected.index = _tagDropdowns [tag].valueCounts [sortedValue];
- EditorUtility.SetDirty (Map.Instance.mapRoads);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapRoads);
- break;
- case "Buildings":
- Undo.RecordObject (Map.Instance.mapBuildings, "Change building dropdown type");
- selected.index = _tagDropdowns [tag].valueCounts [sortedValue];
- EditorUtility.SetDirty (Map.Instance.mapBuildings);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapBuildings);
- break;
- case "Entities":
- Undo.RecordObject (Map.Instance.mapEntities, "Change entity dropdown type");
- selected.index = _tagDropdowns [tag].valueCounts [sortedValue];
- EditorUtility.SetDirty (Map.Instance.mapEntities);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapEntities);
- break;
- case "Features":
- Undo.RecordObject (Map.Instance.mapFeatures, "Change feature dropdown type");
- selected.index = _tagDropdowns [tag].valueCounts [sortedValue];
- EditorUtility.SetDirty (Map.Instance.mapFeatures);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapFeatures);
- break;
- case "Trees":
- Undo.RecordObject (Map.Instance.mapTrees, "Change tree dropdown type");
- selected.index = _tagDropdowns [tag].valueCounts [sortedValue];
- EditorUtility.SetDirty (Map.Instance.mapTrees);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapTrees);
- break;
- }
- }
- if (GUILayout.Button ("Del", deleteButtonWidth))
- {
- ClearKnownTags (tag, sortedValue, alreadyTagged);
- switch (alreadyTagged)
- {
- case "Surfaces":
- Undo.RecordObject (Map.Instance.mapSurfaces, "Delete surface entry");
- Map.Instance.mapSurfaces.surfaceTags.Remove (selected);
- EditorUtility.SetDirty (Map.Instance.mapSurfaces);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapSurfaces);
- break;
- case "Roads":
- Undo.RecordObject (Map.Instance.mapRoads, "Delete road entry");
- Map.Instance.mapRoads.roadTags.Remove (selected);
- EditorUtility.SetDirty (Map.Instance.mapRoads);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapRoads);
- break;
- case "Buildings":
- Undo.RecordObject (Map.Instance.mapBuildings, "Delete building entry");
- Map.Instance.mapBuildings.buildingTags.Remove (selected);
- EditorUtility.SetDirty (Map.Instance.mapBuildings);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapBuildings);
- break;
- case "Entities":
- Undo.RecordObject (Map.Instance.mapEntities, "Delete entity entry");
- Map.Instance.mapEntities.entityTags.Remove (selected);
- EditorUtility.SetDirty (Map.Instance.mapEntities);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapEntities);
- break;
- case "Features":
- Undo.RecordObject (Map.Instance.mapFeatures, "Delete feature entry");
- Map.Instance.mapFeatures.featureTags.Remove (selected);
- EditorUtility.SetDirty (Map.Instance.mapFeatures);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapFeatures);
- break;
- case "Trees":
- Undo.RecordObject (Map.Instance.mapTrees, "Delete tree entry");
- Map.Instance.mapTrees.treeTags.Remove (selected);
- EditorUtility.SetDirty (Map.Instance.mapTrees);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapTrees);
- break;
- }
- }
- }
- }
- else
- {
- // Note: if you delete the tag from the Data window directly instead of using the delete button here,
- // it can give a control position error - this is because the component has changed in between Layout
- // and Repaint events in the GUI and caused a mismatch. This apparently happens due to the GUI
- // running multiple times a frame and as such is not aligned with editor input very well
- // It's not a fatal problem, as this code will recover as well as it cvan, but the error is hard to hide
- _tagDropdowns [tag].valueCounts [sortedValue] =
- EditorGUILayout.Popup (_tagDropdowns [tag].valueCounts [sortedValue], options);
- if (_tagDropdowns [tag].valueCounts [sortedValue] != 0)
- {
- if (GUILayout.Button ("Add", addButtonWidth))
- {
- switch (_tagDropdowns [tag].valueCounts [sortedValue])
- {
- case 0:
- break;
- case 1:
- Undo.RecordObject (Map.Instance.mapSurfaces, "Add surface entry");
- int lastSurfaceID = Map.Instance.mapSurfaces.surfaces.Max (x => x.unique_id);
- ObjectTag surfaceTag = new ()
- {
- index = lastSurfaceID,
- tag = new OSM_Tag (tag, sortedValue)
- };
- AddKnownTag (ref _knownTags, surfaceTag);
- AddKnownTag (ref _knownSurfaceTags, surfaceTag);
- Map.Instance.mapSurfaces.surfaceTags.Add (surfaceTag);
- EditorUtility.SetDirty (Map.Instance.mapSurfaces);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapSurfaces);
- break;
- case 2:
- Undo.RecordObject (Map.Instance.mapRoads, "Add road entry");
- int lastRoadID = Map.Instance.mapRoads.roads.Max (x => x.unique_id);
- ObjectTag roadTag = new ()
- {
- index = lastRoadID,
- tag = new OSM_Tag (tag, sortedValue)
- };
- AddKnownTag (ref _knownTags, roadTag);
- AddKnownTag (ref _knownRoadTags, roadTag);
- Map.Instance.mapRoads.roadTags.Add (roadTag);
- EditorUtility.SetDirty (Map.Instance.mapRoads);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapRoads);
- break;
- case 3:
- Undo.RecordObject (Map.Instance.mapBuildings, "Add building entry");
- int lastBuildingID = Map.Instance.mapBuildings.buildings.Max (x => x.unique_id);
- ObjectTag buildingTag = new ()
- {
- index = lastBuildingID,
- tag = new OSM_Tag (tag, sortedValue)
- };
- AddKnownTag (ref _knownTags, buildingTag);
- AddKnownTag (ref _knownBuildingTags, buildingTag);
- Map.Instance.mapBuildings.buildingTags.Add (buildingTag);
- EditorUtility.SetDirty (Map.Instance.mapBuildings);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapBuildings);
- break;
- case 4:
- Undo.RecordObject (Map.Instance.mapEntities, "Add entity entry");
- int lastEntityID = Map.Instance.mapEntities.entities.Max (x => x.unique_id);
- ObjectTag entityTag = new ()
- {
- index = lastEntityID,
- tag = new OSM_Tag (tag, sortedValue)
- };
- AddKnownTag (ref _knownTags, entityTag);
- AddKnownTag (ref _knownEntityTags, entityTag);
- Map.Instance.mapEntities.entityTags.Add (entityTag);
- EditorUtility.SetDirty (Map.Instance.mapEntities);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapEntities);
- break;
- case 5:
- Undo.RecordObject (Map.Instance.mapFeatures, "Add feature entry");
- int lastFeatureID = Map.Instance.mapFeatures.features.Max (x => x.unique_id);
- ObjectTag featureTag = new ()
- {
- index = lastFeatureID,
- tag = new OSM_Tag (tag, sortedValue)
- };
- AddKnownTag (ref _knownTags, featureTag);
- AddKnownTag (ref _knownFeatureTags, featureTag);
- Map.Instance.mapFeatures.featureTags.Add (featureTag);
- EditorUtility.SetDirty (Map.Instance.mapFeatures);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapFeatures);
- break;
- case 6:
- Undo.RecordObject (Map.Instance.mapTrees, "Add tree entry");
- int lastTreeID = Map.Instance.mapTrees.trees.Max (x => x.unique_id);
- ObjectTag treeTag = new ()
- {
- index = lastTreeID,
- tag = new OSM_Tag (tag, sortedValue)
- };
- AddKnownTag (ref _knownTags, treeTag);
- AddKnownTag (ref _knownTreeTags, treeTag);
- Map.Instance.mapTrees.treeTags.Add (treeTag);
- EditorUtility.SetDirty (Map.Instance.mapTrees);
- PrefabUtility.RecordPrefabInstancePropertyModifications (Map.Instance.mapTrees);
- break;
- }
- }
- }
- }
- EditorGUILayout.EndHorizontal ();
- }
- EditorGUILayout.EndVertical ();
- }
- else
- {
- EditorGUILayout.EndHorizontal ();
- }
- }
- EditorGUILayout.EndVertical ();
- }
- private void ClearKnownTags (string tag, string sortedValue, string alreadyTagged)
- {
- _tagDropdowns [tag].valueCounts [sortedValue] = 0;
- _knownTags [tag].Remove (sortedValue);
- if (_knownTags [tag].Count == 0)
- {
- _knownTags.Remove (tag);
- }
- switch (alreadyTagged)
- {
- case "Surfaces":
- _knownSurfaceTags [tag].Remove (sortedValue);
- if (_knownSurfaceTags [tag].Count == 0)
- {
- _knownSurfaceTags.Remove (tag);
- }
- break;
- case "Roads":
- _knownRoadTags [tag].Remove (sortedValue);
- if (_knownRoadTags [tag].Count == 0)
- {
- _knownRoadTags.Remove (tag);
- }
- break;
- case "Buildings":
- _knownBuildingTags [tag].Remove (sortedValue);
- if (_knownBuildingTags [tag].Count == 0)
- {
- _knownBuildingTags.Remove (tag);
- }
- break;
- case "Entities":
- _knownEntityTags [tag].Remove (sortedValue);
- if (_knownEntityTags [tag].Count == 0)
- {
- _knownEntityTags.Remove (tag);
- }
- break;
- case "Features":
- _knownFeatureTags [tag].Remove (sortedValue);
- if (_knownFeatureTags [tag].Count == 0)
- {
- _knownFeatureTags.Remove (tag);
- }
- break;
- case "Trees":
- _knownTreeTags [tag].Remove (sortedValue);
- if (_knownTreeTags [tag].Count == 0)
- {
- _knownTreeTags.Remove (tag);
- }
- break;
- }
- }
- private void ExportCsvDataToClipboard (Database database)
- {
- StringBuilder sb = new ();
- sb.AppendLine ("Type,Key,Value,Count");
- foreach (KeyValuePair<string, TagCounts> node in _tagCountsNodes [database])
- {
- foreach (KeyValuePair<string, int> value in node.Value.valueCounts)
- {
- sb.Append ("Node,");
- sb.Append (CleanText (node.Key));
- sb.Append (",");
- sb.Append (CleanText (value.Key));
- sb.Append (",");
- sb.AppendLine (value.Value.ToString ());
- }
- }
- foreach (KeyValuePair<string, TagCounts> relation in _tagCountsRelations [database])
- {
- foreach (KeyValuePair<string, int> value in relation.Value.valueCounts)
- {
- sb.Append ("Relation,");
- sb.Append (CleanText (relation.Key));
- sb.Append (",");
- sb.Append (CleanText (value.Key));
- sb.Append (",");
- sb.AppendLine (value.Value.ToString ());
- }
- }
- foreach (KeyValuePair<string, TagCounts> way in _tagCountsWays [database])
- {
- foreach (KeyValuePair<string, int> value in way.Value.valueCounts)
- {
- sb.Append ("Way,");
- sb.Append (CleanText (way.Key));
- sb.Append (",");
- sb.Append (CleanText (value.Key));
- sb.Append (",");
- sb.AppendLine (value.Value.ToString ());
- }
- }
- GUIUtility.systemCopyBuffer = sb.ToString ();
- }
- private void OnInspectorUpdate ()
- {
- Repaint ();
- }
- private static string CleanText (string input)
- {
- const string doubleQuotes = "\"";
- const string doubleQuotesForExcel = "\"\"";
- bool hasComma = input.IndexOf (',') >= 0;
- bool hasDoubleQuotes = input.IndexOf ('"') >= 0;
- string result = input.Replace ("\n", " ").Replace ("\r", " ").Trim ();
- if (hasDoubleQuotes)
- {
- result = result.Replace ("\"", doubleQuotesForExcel);
- return doubleQuotes + result + doubleQuotes;
- }
- if (hasComma)
- {
- return doubleQuotes + result + doubleQuotes;
- }
- return result;
- }
- private class TagCounts
- {
- public int count;
- public bool showToggle;
- public readonly Dictionary<string, int> valueCounts;
- public TagCounts (int count, Dictionary<string, int> valueCounts)
- {
- this.count = count;
- showToggle = false;
- this.valueCounts = valueCounts;
- }
- }
- }
- }
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement