From 81ff0b772fa4c80630967730c06bd865e1f96f72 Mon Sep 17 00:00:00 2001 From: krzychu124 Date: Mon, 20 Mar 2023 23:07:03 +0100 Subject: [PATCH] Improved search for disconnected buildings and building selection tool --- .../BndResultHighlightManager.cs | 6 +- BrokenNodeDetector/BrokenNodeDetector.csproj | 2 +- .../DisconnectedBuildings.cs | 122 ++++++++++-------- 3 files changed, 75 insertions(+), 55 deletions(-) diff --git a/BrokenNodeDetector/BndResultHighlightManager.cs b/BrokenNodeDetector/BndResultHighlightManager.cs index f80bb9d..7b522d1 100644 --- a/BrokenNodeDetector/BndResultHighlightManager.cs +++ b/BrokenNodeDetector/BndResultHighlightManager.cs @@ -99,8 +99,10 @@ private bool RayCast(ToolBase.RaycastInput input, out ToolBase.RaycastOutput out Vector3 hit; bool found = false; if (input.m_ignoreBuildingFlags != Building.Flags.All && - Singleton.instance.RayCast(ray, input.m_buildingService.m_service, input.m_buildingService.m_subService, input.m_buildingService.m_itemLayers, input.m_ignoreBuildingFlags, out hit, out output.m_building)) - { + Singleton.instance.RayCast(ray, input.m_buildingService.m_service, input.m_buildingService.m_subService, input.m_buildingService.m_itemLayers, input.m_ignoreBuildingFlags, out hit, out ushort buildingId)) { + + ushort parentBuilding = Building.FindParentBuilding(buildingId); + output.m_building = parentBuilding != 0 ? parentBuilding : buildingId; float distance = Vector3.Distance(hit, origin); if (distance < (double) len) { diff --git a/BrokenNodeDetector/BrokenNodeDetector.csproj b/BrokenNodeDetector/BrokenNodeDetector.csproj index fc9e034..28e1cb1 100644 --- a/BrokenNodeDetector/BrokenNodeDetector.csproj +++ b/BrokenNodeDetector/BrokenNodeDetector.csproj @@ -91,7 +91,7 @@ ..\Dependencies\EManagersLib.API.dll - + ..\Dependencies\ICities.dll diff --git a/BrokenNodeDetector/UI/Tools/DisconnectedBuildingsTool/DisconnectedBuildings.cs b/BrokenNodeDetector/UI/Tools/DisconnectedBuildingsTool/DisconnectedBuildings.cs index 1ac8d7e..e55231e 100644 --- a/BrokenNodeDetector/UI/Tools/DisconnectedBuildingsTool/DisconnectedBuildings.cs +++ b/BrokenNodeDetector/UI/Tools/DisconnectedBuildingsTool/DisconnectedBuildings.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using System.Reflection; using System.Text; using System.Threading; using ColossalFramework.UI; @@ -29,13 +28,19 @@ public override IEnumerable Process() { ResetState(); _progress = 0f; - AsyncTask asyncTask = SimulationManager.instance.AddAction(ProcessInternal()); + AsyncTask asyncTask = SimulationManager.instance.AddAction(CheckRoadAccess()); while (!asyncTask.completed) { yield return _progress; } + + _progress = 0f; + AsyncTask asyncTask2 = SimulationManager.instance.AddAction(CollectDisconnectedBuildings()); + while (!asyncTask2.completed) { + yield return _progress; + } yield return 1.0f; - IsProcessing = true; + IsProcessing = false; } public override void InitResultsView(UIComponent component) { @@ -63,65 +68,75 @@ private void AttachCallbacks(UIComponent templateInstance) { templateInstance.Find("MoveNext").eventClick += MoveNextBuildingButtonClick; } - private IEnumerator ProcessInternal() { + private IEnumerator CheckRoadAccess() { BuildingManager bm = BuildingManager.instance; float searchStep = 1.0f / bm.m_buildings.m_size; + + ProgressMessage = $"Processing...0% Pass 1/2"; + Building[] mBuffer = bm.m_buildings.m_buffer; + for (int i = 1; i < mBuffer.Length; i++) { + + if ((mBuffer[i].m_flags & (Building.Flags.Created | Building.Flags.Deleted)) == Building.Flags.Created && + mBuffer[i].Info + ) { + mBuffer[i].Info.m_buildingAI.CheckRoadAccess((ushort)i, ref mBuffer[i]); + } + + float searchProgress = searchStep * i; + if (i % 64 == 0) { + ProgressMessage = $"Processing...{searchProgress * 100:F0}% Pass 1/2"; + Thread.Sleep(1); + _progress = searchProgress; + } + } + ProgressMessage = $"Processing...100% Pass 1/2"; + + yield return 1.0f; + } + + private IEnumerator CollectDisconnectedBuildings() { StringBuilder sb = new StringBuilder(); sb.AppendLine("[BND] Scanning for disconnected buildings"); sb.AppendLine("[BND] "); sb.AppendLine("[BND] =( Building ID )===( Location )="); sb.AppendLine(); - ProgressMessage = $"Processing...0%"; + BuildingManager bm = BuildingManager.instance; Building[] mBuffer = bm.m_buildings.m_buffer; + float searchStep = 1.0f / bm.m_buildings.m_size; + + ProgressMessage = "Processing...0% Pass 2/2"; + _progress = 0f; + int counter = 0; - MethodInfo findRoadAccess = typeof(PlayerBuildingAI).GetMethod("FindRoadAccess", BindingFlags.Instance | BindingFlags.NonPublic); - for (int i = 0; i < mBuffer.Length; i++) { - Building building = mBuffer[i]; + for (int i = 1; i < mBuffer.Length; i++) { + + if ((mBuffer[i].m_flags & (Building.Flags.Created | Building.Flags.Deleted)) == Building.Flags.Created && + mBuffer[i].Info + ) { + bool notConnected = ((mBuffer[i].m_flags & Building.Flags.RoadAccessFailed) != Building.Flags.None && + ((mBuffer[i].m_problems.m_Problems1 & (Notification.Problem1.RoadNotConnected | Notification.Problem1.PathNotConnected)) != Notification.Problem1.None || + (mBuffer[i].m_problems.m_Problems2 & (Notification.Problem2.NotInPedestrianZone | Notification.Problem2.CannotBeReached)) != Notification.Problem2.None)); - if ((building.m_flags & Building.Flags.Created) != 0 && building.Info) { - if (building.Info.m_buildingAI is PlayerBuildingAI) { + if (notConnected) { counter++; - PlayerBuildingAI buildingAI = building.Info.m_buildingAI as PlayerBuildingAI; - bool connected = true; - if ((building.m_flags & Building.Flags.Collapsed) == Building.Flags.None && buildingAI.RequireRoadAccess()) { - Vector3 position = buildingAI.m_info.m_zoningMode != BuildingInfo.ZoningMode.CornerLeft - ? (buildingAI.m_info.m_zoningMode != BuildingInfo.ZoningMode.CornerRight - ? building.CalculateSidewalkPosition(0.0f, 4f) - : building.CalculateSidewalkPosition(building.Width * -4f, 4f)) - : building.CalculateSidewalkPosition(building.Width * 4f, 4f); - object[] args = { (ushort)i, building, position, null, true, false }; - if (!(bool)findRoadAccess.Invoke(buildingAI, args)) - connected = false; - } - - if (!connected) { - _disconnectedBuildings.Add((ushort)i, building.m_position); - sb.AppendLine("==(" + i + ")===(" + building.m_position + ")="); - sb.Append("building ") - .Append(" " + (building.Info ? building.Info.m_class.name : "") + " ") - .Append(building.m_flags.ToString()) - .Append(" [name: ").Append(building.Info.name).Append("]"); - sb.AppendLine("---------------------------------------"); - } - } else if ((building.m_flags & Building.Flags.RoadAccessFailed) != 0 || (building.m_problems.m_Problems1 & Notification.Problem1.RoadNotConnected) != 0) { - _disconnectedBuildings.Add((ushort)i, building.m_position); - sb.AppendLine("==(" + i + ")===(" + building.m_position + ")="); - sb.Append("building ") - .Append(" " + (building.Info ? building.Info.m_class.name : "") + " ") - .Append(building.m_flags.ToString()) - .Append(" [name: ").Append(building.Info.name).Append("]"); + _disconnectedBuildings.Add((ushort)i, mBuffer[i].m_position); + sb.AppendLine("==(" + i + ")===" + mBuffer[i].m_position + "=="); + sb.Append("Building [ItemClass: ") + .Append((mBuffer[i].Info ? mBuffer[i].Info.m_class.name : "") + "] [Flags: ") + .Append(mBuffer[i].m_flags.ToString()).Append("] [Problems: ").Append(mBuffer[i].m_problems.ToString()) + .Append("] [Name: ").Append(mBuffer[i].Info.name).Append("]"); sb.AppendLine("---------------------------------------"); } } float searchProgress = searchStep * i; - if (i % 32 == 0) { - ProgressMessage = $"Processing...{searchProgress * 100:F0}%"; + if (i % 128 == 0) { + ProgressMessage = $"Processing...{searchProgress * 100:F0}% Pass 2/2"; Thread.Sleep(1); _progress = searchProgress; } } - ProgressMessage = $"Processing...100%"; + ProgressMessage = $"Processing...100% Pass 2/2"; Debug.Log("[BND] Disconnected building instances count: " + counter); Debug.Log("[BND] Scan report\n" + sb + "\n\n======================================================="); @@ -151,20 +166,22 @@ private void BuildTemplate() { UIPanel buildingPanel = _template.AddUIComponent(); buildingPanel.width = 400; buildingPanel.height = 40; - buildingPanel.relativePosition = new Vector2(10, 45); + buildingPanel.relativePosition = new Vector2(15, 45); buildingPanel.name = "BuildingPanel"; UILabel buildingId = buildingPanel.AddUIComponent(); + buildingId.processMarkup = true; buildingId.prefix = "Building ID: "; - buildingId.relativePosition = new Vector2(20, 10); + buildingId.relativePosition = new Vector2(0, 10); buildingId.name = "BuildingID"; - buildingId.textScale = 0.9f; + buildingId.textScale = 0.8f; UILabel buildingPos = buildingPanel.AddUIComponent(); + buildingPos.processMarkup = true; buildingPos.prefix = "Position: "; - buildingPos.relativePosition = new Vector2(200, 10); + buildingPos.relativePosition = new Vector2(150, 10); buildingPos.name = "BuildingPosition"; - buildingPos.textScale = 0.9f; + buildingPos.textScale = 0.8f; buildingPanel.Hide(); } @@ -216,6 +233,7 @@ private void UpdateBuildingsPanel(UIPanel buildingPanel, UILabel label) { if (_disconnectedBuildings.Count == 0) { ResetState(); label.text = "Great! Nothing found :-)"; + label.textColor = new Color(0f, 0.81f, 0.05f); label.parent.height = 50; label.relativePosition = Vector3.zero; label.color = Color.white; @@ -227,16 +245,16 @@ private void UpdateBuildingsPanel(UIPanel buildingPanel, UILabel label) { UILabel buildingId = buildingPanel.Find("BuildingID"); UILabel buildingPos = buildingPanel.Find("BuildingPosition"); if (_currentBuilding != 0 && _disconnectedBuildings.TryGetValue(_currentBuilding, out Vector3 position)) { - buildingId.text = _currentBuilding.ToString(); - buildingPos.text = position.ToString(); + buildingId.text = $"{_currentBuilding.ToString()}"; + buildingPos.text = $"{position.ToString()}"; } else { buildingId.text = " "; buildingPos.text = " "; } - label.relativePosition = new Vector3(20, 0); - label.text = $"{_disconnectedBuildings.Count} possibly disconnected building(s)"; - label.color = Color.yellow; + label.relativePosition = new Vector3(15, 0); + label.processMarkup = true; + label.text = $"{_disconnectedBuildings.Count} possibly disconnected building(s)"; } private void UpdateBuildingButtons(UIComponent moveNextButton) {