using GeoSus.Client; using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using UnityEditor; using UnityEngine; using UnityEngine.UI; namespace Subsystems{ [System.Serializable] public class BuildingSettings { public Material ResidentalBuildingsMat; public float ResidentalBuildingHeight; public Material CommercialBuildingsMat; public float CommercialBuildingHeight; public Material IndustrialBuildingsMat; public float IndustrialBuildingHeight; public Material DefaultBuildingMat; public float DefaultBuildingHeight; } [System.Serializable] public class PathwaySettings { public Material FootwayMat; public float FootwayWidth; public Material PathMat; public float PathWidth; public Material StepsMat; public float StepsWidth; public Material CyclewayMat; public float CyclewayWidth; public Material PedestrianMat; public float PedestrianWidth; public Material RoadMat; public float RoadWidth; public Material ServiceMat; public float ServiceWidth; public Material ResidentialMat; public float ResidentialWidth; public Material TrackMat; public float TrackWidth; public Material DefaultMat; public float DefaultWidth; } [System.Serializable] public class AreaSettings { public Material ParkMat; public Material GardenMat; public Material PlaygroundMat; public Material ForestMat; public Material GrassMat; public Material WaterMat; public Material DefaultMat; } public class GameManager_Map { private GameClient _gameClient; private GameObject _mapCenterPoint; private Position _centerPosition; private BuildingSettings _buildingSettings; private PathwaySettings _pathwaySettings; private AreaSettings _areaSettings; private const float _metersPerUnit = 1f; public GameManager_Map(GameClient gameClient, GameObject mapCenterPoint, BuildingSettings buildingSettings, PathwaySettings pathwaySettings, AreaSettings areaSettings) { _gameClient = gameClient; _mapCenterPoint = mapCenterPoint; _buildingSettings = buildingSettings; _pathwaySettings = pathwaySettings; _areaSettings = areaSettings; } public void BuildMap() { ClearChildren(); _centerPosition = _gameClient.CurrentLobbyState.MapData.Center; GameObject buildingsRoot = new GameObject("Buildings"); buildingsRoot.transform.parent = _mapCenterPoint.transform; GameObject pathRoot = new GameObject("Pathways"); pathRoot.transform.parent = _mapCenterPoint.transform; GameObject areaRoot = new GameObject("Areas"); areaRoot.transform.parent = _mapCenterPoint.transform; foreach (var building in _gameClient.CurrentLobbyState.MapData.GetBuildings()) { string buildingType = "Unknown"; try { buildingType = _gameClient.CurrentLobbyState.MapData.BuildingTypes[_gameClient.CurrentLobbyState.MapData.GetBuildings().IndexOf(building)]; } catch (Exception ex) { Debug.Log($"Error: {ex.Message}"); } building.Name = buildingType; GameObject b = BuildBuildingMesh(building); b.transform.parent = buildingsRoot.transform; } foreach (var path in _gameClient.CurrentLobbyState.MapData.GetPathways()) { GameObject p = BuildPathwayMesh(path); p.transform.parent = pathRoot.transform; } foreach (var area in _gameClient.CurrentLobbyState.MapData.GetAreas()) { GameObject a = BuildAreaMesh(area); a.transform.parent = areaRoot.transform; } //TODO: POIs } void ClearChildren() { List toDestroy = new List(); foreach (Transform t in _mapCenterPoint.transform) toDestroy.Add(t.gameObject); foreach (var g in toDestroy) { UnityEngine.Object.DestroyImmediate(g); } } #region Mesh Building GameObject BuildBuildingMesh(MapBuilding b) { var building = new GameObject($"Building_{b.Name ?? "Unknown"}"); // Výpočet středu budovy Vector3 center = CalculatePolygonCenter(b.Outline); building.transform.position = center; // Vytvoření mesh pro budovu MeshFilter meshFilter = building.AddComponent(); MeshRenderer meshRenderer = building.AddComponent(); float height; Material mat; switch (b.BuildingType.ToLower()) { case "residential": mat = _buildingSettings.ResidentalBuildingsMat; height = _buildingSettings.ResidentalBuildingHeight; break; case "commercial": mat = _buildingSettings.CommercialBuildingsMat; height = _buildingSettings.CommercialBuildingHeight; break; case "industrial": mat = _buildingSettings.IndustrialBuildingsMat; height = _buildingSettings.IndustrialBuildingHeight; break; default: mat = _buildingSettings.DefaultBuildingMat; height = _buildingSettings.DefaultBuildingHeight; break; } Mesh mesh = CreateExtrudedPolygonMesh(b.Outline, height); meshFilter.mesh = mesh; //TODO: material by type // Použijeme barvu podle typu budovy meshRenderer.material = mat; // Přidání collideru pro interakci building.AddComponent(); return building; } GameObject BuildPathwayMesh(MapPathway w) { var path = new GameObject($"Path_{w.Name ?? "Unknown"}"); // Použijeme LineRenderer pro jednoduchost LineRenderer line = path.AddComponent(); float width; Material mat; switch (w.PathType) { case PathType.Footway: mat = _pathwaySettings.FootwayMat; width = _pathwaySettings.FootwayWidth; break; case PathType.Path: mat = _pathwaySettings.PathMat; width = _pathwaySettings.PathWidth; break; case PathType.Steps: mat = _pathwaySettings.StepsMat; width = _pathwaySettings.PathWidth; break; case PathType.Cycleway: mat = _pathwaySettings.CyclewayMat; width = _pathwaySettings.CyclewayWidth; break; case PathType.Pedestrian: mat = _pathwaySettings.PedestrianMat; width = _pathwaySettings.PedestrianWidth; break; case PathType.Road: mat = _pathwaySettings.RoadMat; width = _pathwaySettings.RoadWidth; break; case PathType.Service: mat = _pathwaySettings.ServiceMat; width = _pathwaySettings.ServiceWidth; break; case PathType.Residential: mat = _pathwaySettings.ResidentialMat; width = _pathwaySettings.ResidentialWidth; break; case PathType.Track: mat = _pathwaySettings.TrackMat; width = _pathwaySettings.TrackWidth; break; default: mat = _pathwaySettings.DefaultMat; width = _pathwaySettings.DefaultWidth; break; } line.material = mat; line.widthMultiplier = width; // Nastavení bodů cesty line.positionCount = w.Points.Count; for (int i = 0; i < w.Points.Count; i++) { Vector3 pos = w.Points[i].ToLocalVector3(_gameClient.CurrentLobbyState.MapData.Center); pos.y = 0.1f; // Mírně nad zemí line.SetPosition(i, pos); } return path; } GameObject BuildAreaMesh(MapArea a) { var area = new GameObject($"Area_{a.Name ?? "Unknown"}"); MeshFilter meshFilter = area.AddComponent(); MeshRenderer meshRenderer = area.AddComponent(); // Vytvoření plochého mesh Mesh mesh = CreateFlatPolygonMesh(a.Outline); meshFilter.mesh = mesh; Material mat; switch (a.AreaType) { case MapAreaType.Park: mat = _areaSettings.ParkMat; break; case MapAreaType.Garden: mat = _areaSettings.GardenMat; break; case MapAreaType.Playground: mat = _areaSettings.PlaygroundMat; break; case MapAreaType.Forest: mat = _areaSettings.ForestMat; break; case MapAreaType.Grass: mat = _areaSettings.GrassMat; break; case MapAreaType.Water: mat = _areaSettings.WaterMat; break; default: mat = _areaSettings.DefaultMat; break; } meshRenderer.material = mat; area.transform.position = new Vector3(0, 0.05f, 0); // Těsně nad zemí return area; } //TODO: POIs #endregion #region Polygon Utils private Vector3 CalculatePolygonCenter(List points) { Vector3 center = Vector3.zero; foreach (var point in points) { center += point.ToLocalVector3(_gameClient.CurrentLobbyState.MapData.Center); } return center / points.Count; } private Mesh CreateExtrudedPolygonMesh(List outline, float height) { Mesh mesh = new Mesh(); int vertexCount = outline.Count; // Vertices - spodní a horní podstava Vector3[] vertices = new Vector3[vertexCount * 2]; Vector3 center = CalculatePolygonCenter(outline); for (int i = 0; i < vertexCount; i++) { Vector3 pos = outline[i].ToLocalVector3(_gameClient.CurrentLobbyState.MapData.Center) - center; vertices[i] = pos; // Spodní vertices[i + vertexCount] = pos + Vector3.up * height; // Horní } // Triangles - jen boční stěny pro jednoduchost List triangles = new List(); for (int i = 0; i < vertexCount; i++) { int next = (i + 1) % vertexCount; // Boční stěna - dva trojúhelníky triangles.Add(i); triangles.Add(i + vertexCount); triangles.Add(next); triangles.Add(next); triangles.Add(i + vertexCount); triangles.Add(next + vertexCount); } // Horní podstava - zjednodušená triangulace (fan) if (vertexCount >= 3) { for (int i = 1; i < vertexCount - 1; i++) { triangles.Add(vertexCount); // Střed (první bod horní) triangles.Add(vertexCount + i); triangles.Add(vertexCount + i + 1); } } mesh.vertices = vertices; mesh.triangles = triangles.ToArray(); mesh.RecalculateNormals(); mesh.RecalculateBounds(); return mesh; } private Mesh CreateFlatPolygonMesh(List outline) { Mesh mesh = new Mesh(); int vertexCount = outline.Count; Vector3[] vertices = new Vector3[vertexCount]; Vector3 center = CalculatePolygonCenter(outline); for (int i = 0; i < vertexCount; i++) { vertices[i] = outline[i].ToLocalVector3(_gameClient.CurrentLobbyState.MapData.Center) - center; } // Triangulace - fan pattern List triangles = new List(); if (vertexCount >= 3) { for (int i = 1; i < vertexCount - 1; i++) { triangles.Add(0); triangles.Add(i); triangles.Add(i + 1); } } mesh.vertices = vertices; mesh.triangles = triangles.ToArray(); mesh.RecalculateNormals(); return mesh; } #endregion } }