391 lines
14 KiB
C#
391 lines
14 KiB
C#
using GeoSus.Client;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.Localization.Pseudo;
|
|
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())
|
|
{
|
|
var buildingType = _gameClient.CurrentLobbyState.MapData.BuildingTypes[_gameClient.CurrentLobbyState.MapData.GetBuildings().IndexOf(building)];
|
|
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
|
|
}
|
|
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<MeshFilter>();
|
|
MeshRenderer meshRenderer = building.AddComponent<MeshRenderer>();
|
|
|
|
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<MeshCollider>();
|
|
return building;
|
|
}
|
|
GameObject BuildPathwayMesh(MapPathway w)
|
|
{
|
|
var path = new GameObject($"Path_{w.Name ?? "Unknown"}");
|
|
|
|
// Použijeme LineRenderer pro jednoduchost
|
|
LineRenderer line = path.AddComponent<LineRenderer>();
|
|
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 = LatLonToLocal(w.Points[i]);
|
|
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<MeshFilter>();
|
|
MeshRenderer meshRenderer = area.AddComponent<MeshRenderer>();
|
|
|
|
// 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
|
|
void ClearChildren()
|
|
{
|
|
List<GameObject> toDestroy = new List<GameObject>();
|
|
foreach (Transform t in _mapCenterPoint.transform)
|
|
toDestroy.Add(t.gameObject);
|
|
foreach (var g in toDestroy)
|
|
{
|
|
UnityEngine.Object.DestroyImmediate(g);
|
|
}
|
|
}
|
|
Vector3 LatLonToLocal(Position position)
|
|
{
|
|
if (_gameClient.CurrentLobbyState.MapData == null) return Vector3.zero;
|
|
|
|
// Výpočet vzdálenosti a směru od středu
|
|
// Zjednodušená verze - pro malé vzdálenosti je dost přesná
|
|
|
|
double latDiff = position.Lat - _gameClient.CurrentLobbyState.MapData.Center.Lat;
|
|
double lonDiff = position.Lon - _gameClient.CurrentLobbyState.MapData.Center.Lon;
|
|
|
|
// Převod stupňů na metry
|
|
// 1 stupeň latitude ≈ 111320 metrů
|
|
// 1 stupeň longitude závisí na latitude: 111320 * cos(latitude)
|
|
double metersPerDegreeLat = 111320.0;
|
|
double metersPerDegreeLon = 111320.0 * Math.Cos(_gameClient.CurrentLobbyState.MapData.Center.Lat * Math.PI / 180.0);
|
|
|
|
float x = (float)(lonDiff * metersPerDegreeLon);
|
|
float z = (float)(latDiff * metersPerDegreeLat);
|
|
|
|
return new Vector3(x, 0, z);
|
|
}
|
|
#region Polygon Utils
|
|
private Vector3 CalculatePolygonCenter(List<Position> points)
|
|
{
|
|
Vector3 center = Vector3.zero;
|
|
foreach (var point in points)
|
|
{
|
|
center += LatLonToLocal(point);
|
|
}
|
|
return center / points.Count;
|
|
}
|
|
private Mesh CreateExtrudedPolygonMesh(List<Position> 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 = LatLonToLocal(outline[i]) - center;
|
|
vertices[i] = pos; // Spodní
|
|
vertices[i + vertexCount] = pos + Vector3.up * height; // Horní
|
|
}
|
|
|
|
// Triangles - jen boční stěny pro jednoduchost
|
|
List<int> triangles = new List<int>();
|
|
|
|
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<Position> 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] = LatLonToLocal(outline[i]) - center;
|
|
}
|
|
|
|
// Triangulace - fan pattern
|
|
List<int> triangles = new List<int>();
|
|
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
|
|
}
|
|
}
|