using System.Collections.Generic; using JetBrains.Annotations; using UnityEngine.Scripting; using UnityEngine; using System.Linq; using System.IO; using System; using Random = UnityEngine.Random; #if UNITY_EDITOR using UnityEditor; using UnityEngine.UI; #endif // UNITY_EDITOR namespace Fruitomation.Game { public class BuildingManager : MonoBehaviour { [Header("References")] [SerializeField] private BuildingRegistry Registry; [SerializeField] private GameObject HeatGrid; [Header("Colors")] [SerializeField] private Color FreezingColor; [SerializeField] private Color ColdColor; [SerializeField] private Color RoomColor; [SerializeField] private Color WarmColor; [SerializeField] private Color BoilingColor; private enum HeatingLevel { Freezing, Cold, Room, Warm, Boiling } private class BuildingInfo { public BuildingInfo(Building b, RectTransform rt) { Building = b; Rect = rt; } public Building Building { get; } public RectTransform Rect { get; } } [Serializable] private class SerializedBuilding { [SerializeField, Preserve, UsedImplicitly] public Vector2Int GridPosition; [SerializeField, Preserve, UsedImplicitly] public Vector2Int Position; [SerializeField, Preserve, UsedImplicitly] public string PrefabName; [SerializeField, Preserve, UsedImplicitly] public bool IsFlipped; public SerializedBuilding(Vector2Int gridPosition, Vector2Int pos, string name, bool flipped) { GridPosition = gridPosition; IsFlipped = flipped; PrefabName = name; Position = pos; } } [Serializable] private class SerializedBuildings { [SerializeField, Preserve, UsedImplicitly] private SerializedBuilding[] Buildings; public SerializedBuilding[] Get() => Buildings; public SerializedBuildings(List buildings) => Buildings = buildings.ToArray(); } private static string Filepath => Path.Combine(Application.persistentDataPath, "buildings.json"); private (HeatingLevel, Image)[,] HeatingLevels { get; } = new (HeatingLevel, Image)[96, 49]; private bool[,] InhabitedCells { get; } = new bool[96, 49]; private List Buildings { get; } = new(); #if UNITY_EDITOR private static BuildingManager Instance; public void ToggleGrid() => HeatGrid.SetActive(!HeatGrid.activeSelf); private Color LevelToColor(HeatingLevel level) { return level switch { HeatingLevel.Room => RoomColor, HeatingLevel.Boiling => BoilingColor, HeatingLevel.Cold => ColdColor, HeatingLevel.Freezing => FreezingColor, HeatingLevel.Warm => WarmColor, var _ => new Color() }; } private void Awake() { HeatGrid.SetActive(false); Instance = this; for (int x = 0; x < HeatingLevels.GetLength(0); x++) { for (int y = 0; y < HeatingLevels.GetLength(1); y++) { GameObject go = new($"Grid_{x}_{y}"); go.transform.SetParent(HeatGrid.transform); RectTransform rt = go.AddComponent(); Image img = go.AddComponent(); HeatingLevels[x, y].Item1 = (HeatingLevel)Random.Range(0, 5); HeatingLevels[x, y].Item2 = img; img.color = LevelToColor(HeatingLevels[x, y].Item1); rt.localScale = Vector3.one; img.raycastTarget = false; } } } [MenuItem("Fruitomation/Clear Buildings")] public static void ClearBuildings() { foreach (Building b in Instance.Buildings) { Destroy(b.gameObject); } Instance.Buildings.Clear(); } #endif // UNITY_EDITOR private void Start() { if (!File.Exists(Filepath)) { return; } string json = File.ReadAllText(Filepath); SerializedBuilding[] buildings = JsonUtility.FromJson(json).Get(); foreach (SerializedBuilding building in buildings) { GameObject prefab = Registry.GetBuildingOf(building.PrefabName); GameObject go = Instantiate(prefab, transform); BuildingInfo info = new ( go.GetComponent(), go.GetComponent() ); info.Rect.transform.localScale = new Vector3(building.IsFlipped ? -1f : 1f, 1f, 1f); info.Rect.sizeDelta = info.Building.SizeOnGrid * 40; info.Rect.anchoredPosition = building.Position; go.name = $"{building.PrefabName}"; info.Building.Init(this, building.GridPosition, building.Position, building.IsFlipped); Buildings.Add(info.Building); for (int x = building.GridPosition.x; x < building.GridPosition.x + info.Building.SizeOnGrid.x; x++) for (int y = building.GridPosition.y; y < building.GridPosition.y + info.Building.SizeOnGrid.y; y++) { InhabitedCells[x, y] = true; } } } private void OnDestroy() { Debug.Log($"Buildings: [{Buildings.Count}]"); List serialized = Buildings.Select(building => new SerializedBuilding ( building.GridPosition, building.Position, building.name, building.IsFlipped ) ).ToList(); string json = JsonUtility.ToJson(new SerializedBuildings(serialized), true); File.WriteAllText(Filepath, json); } public void RemoveBuilding(Building building) { Buildings.Remove(building); for (int x = building.GridPosition.x; x < building.GridPosition.x + building.SizeOnGrid.x; x++) for (int y = building.GridPosition.y; y < building.GridPosition.y + building.SizeOnGrid.y; y++) { InhabitedCells[x, y] = false; } } public bool AddBuildingAt(Vector2Int position, BuildingRegistry.BuildingInfo building, bool isFlipped) { // GameObject go = Instantiate(building.Prefab, transform); BuildingInfo info = new ( go.GetComponent(), go.GetComponent() ); go.name = $"{building.Name}"; Vector2Int p0 = position * 40; Vector2Int p1 = p0 + new Vector2Int(20, 100); Vector2Int g0 = position + new Vector2Int(48, 24); Vector2Int off0 = info.Building.SizeOnGrid - Vector2Int.one; Vector2Int off1 = off0 * 20; Vector2Int p2 = p1 + off1; info.Rect.sizeDelta = info.Building.SizeOnGrid * 40; info.Rect.anchoredPosition = p2; info.Rect.transform.localScale = new Vector3(isFlipped ? -1f : 1f, 1f, 1f); // for (int x = g0.x; x < g0.x + info.Building.SizeOnGrid.x; x++) for (int y = g0.y; y < g0.y + info.Building.SizeOnGrid.y; y++) { if (InhabitedCells[x, y]) { DestroyImmediate(go); return false; } } // for (int x = g0.x; x < g0.x + info.Building.SizeOnGrid.x; x++) for (int y = g0.y; y < g0.y + info.Building.SizeOnGrid.y; y++) { InhabitedCells[x, y] = true; } info.Building.Init(this, g0, p2, isFlipped); Buildings.Add(info.Building); return true; } } }