DynamicTileManager.cs 3.82 KB
Newer Older
Rory's avatar
Rory committed
1
2
3
4
5
using System;
using System.Collections.Generic;
using System.Linq;
using MapzenGo.Helpers;
using UnityEngine;
6
using MapzenGo.Helpers.VectorD;
Rory's avatar
Rory committed
7
8
9
10
11
12
13
14
15

namespace MapzenGo.Models
{
    public class DynamicTileManager : TileManager
    {
        [SerializeField] private Rect _centerCollider;
        [SerializeField] private int _removeAfter;
        [SerializeField] private bool _keepCentralized;

16
17
18
19
20
21
		private Vector2d offset;
		private RectD centerRect;
		private Vector2d centerTileCornerPos;
		private float scaleMultiplier;

		public override void Start()
Rory's avatar
Rory committed
22
23
24
25
26
        {
            base.Start();
            _removeAfter = Math.Max(_removeAfter, Range * 2 + 1);
            var rect = new Vector2(TileSize, TileSize);
            _centerCollider = new Rect(Vector2.zero - rect / 2 , rect);
27
28
29
30
31
			offset = Vector2d.zero;

			// Set initial position
			Centralize(GM.LatLonToMeters(Latitude, Longitude));
			scaleMultiplier = (float)(TileSize / centerRect.Width);
Rory's avatar
Rory committed
32
33
34
35
36
37
38
		}

        public override void Update()
        {
            base.Update();
            UpdateTiles();
        }
39
		
Rory's avatar
Rory committed
40
41
42
43
        private void UpdateTiles()
        {
			var meters = GM.LatLonToMeters(Latitude, Longitude);
			offset = meters - centerTileCornerPos;
44
45
46
47
48
49
50

			_centerCollider.position = (-offset).ToVector2() * scaleMultiplier;

			if (!_centerCollider.Contains(Vector2.zero, true))
			{
				Centralize(meters);
			}
Rory's avatar
Rory committed
51
52
53
54
55
			foreach (var tile in Tiles.Values)
			{
				tile.transform.position = ((tile.Rect.Min - centerTileCornerPos - offset + centerRect.Size / 2).ToVector3()) * scaleMultiplier;
			}

56
			/*
Rory's avatar
Rory committed
57
58
59
60
61
62
63
64
65
66
67
68
69
			// ========================= DEBUGGING =========================
			var tileTest = GM.MetersToTile(meters, Zoom);
			DebugText.Log("tms " + CenterTms + " | offset " + offset +
						"\ntile " + tileTest + " | meters " + meters +
						"\n " + centerTileCornerPos);
			// Debug.Log("tms " + CenterTms + " | offset " + offset);
			// ======================= END DEBUGGING =======================

			if (Math.Abs(_centerCollider.center.x) > 10f || Math.Abs(_centerCollider.center.y) > 10f)
			{
				Debug.Break();
				throw new System.Exception("Offset is too large, the map should stay closer to the center: " + Math.Abs(_centerCollider.center.x) + ", " + Math.Abs(_centerCollider.center.y));
			}
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
			*/
		}

		private void Centralize(Vector2d meters)
		{
			centerRect = GM.TileBounds(CenterTms, Zoom);
			centerTileCornerPos = new Vector2d(centerRect.Min.x, centerRect.Min.y + centerRect.Size.y);

			//player movement in TMS tiles
			var tileDif = GetMovementVector();

			//move locals
			CenterTms = GM.MetersToTile(meters, Zoom);
			CenterInMercator = GM.TileBounds(CenterTms, Zoom).Center;
			// Debug.Log(CenterTms + " ||| " + _centerCollider.center);

			//create new tiles
			LoadTiles(CenterTms, CenterInMercator);
			UnloadTiles(CenterTms);
Rory's avatar
Rory committed
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
		}

        private void UnloadTiles(Vector2d currentTms)
        {
            var rem = new List<Vector2d>();
            foreach (var key in Tiles.Keys.Where(x => x.ManhattanTo(currentTms) > _removeAfter))
            {
                rem.Add(key);
                Destroy(Tiles[key].gameObject);
            }
            foreach (var v in rem)
            {
                Tiles.Remove(v);
            }
		}

		private Vector2 GetMovementVector()
		{
			var tileDif = Vector2.zero;
			if (0 < Math.Min(_centerCollider.xMin, _centerCollider.xMax))
				tileDif.x = -1;
			else if (0 > Math.Max(_centerCollider.xMin, _centerCollider.xMax))
				tileDif.x = 1;

			if (0 < Math.Min(_centerCollider.yMin, _centerCollider.yMax))
				tileDif.y = 1;
			else if (0 > Math.Max(_centerCollider.yMin, _centerCollider.yMax))
				tileDif.y = -1; //invert axis  TMS vs unity
			return tileDif;
		}
		
		void OnDrawGizmos()
		{
            Gizmos.color = Color.magenta;
			Gizmos.DrawWireCube(_centerCollider.center.ToVector3xz() + Vector3.up * 0.01f, _centerCollider.size.ToVector3xz());
		}
    }
}