SanAndreasUnity/Assets/Scripts/Behaviours/MiniMap.cs

324 lines
10 KiB
C#
Raw Normal View History

2020-05-31 17:07:22 +00:00
using SanAndreasUnity.Behaviours.Vehicles;
using SanAndreasUnity.Importing.Conversion;
using SanAndreasUnity.Utilities;
using System;
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
using Object = UnityEngine.Object;
namespace SanAndreasUnity.Behaviours
{
public class MiniMap : MonoBehaviour
{
public const int tileEdge = 12; // width/height of map in tiles
public const int tileCount = tileEdge * tileEdge; // number of tiles
public const int mapEdge = 6000; // width/height of map in world coordinates
public const int texSize = 128; // width/height of single tile in px
public const int mapSize = tileEdge * texSize; // width/height of whole map in px
public const int uiSize = 256, uiOffset = 10;
public static bool toggleMap;
public Image northImage,
outlineImage,
maskImage,
mapImage;
2020-04-28 21:55:02 +00:00
public RawImage playerImage;
2020-05-31 17:07:22 +00:00
public RectTransform mapTransform,
maskTransform,
mapContainer;
2020-04-28 23:08:38 +00:00
public Text zoneNameLabel;
private Canvas _canvas;
2020-05-31 17:07:22 +00:00
public float zoom = 1.3f;
private const float scaleConst = 1f;
public const float maxVelocity = 300f;
public static float[] zooms = new float[10] { .5f, .75f, 1f, 1.2f, 1.4f, 1.6f, 2f, 2.5f, 3f, 5f };
// Why?
[HideInInspector] [Obsolete] public float calibrator = 2.34f;
public float zoomDuration = 1,
mapZoomScaler = 1,
mapMovement = 5;
2020-05-01 16:21:22 +00:00
public Vector3 FocusPos { get; set; } = Vector3.zero;
public bool IsMinimapVisible => _canvas.enabled && this.gameObject.activeInHierarchy;
2020-05-31 17:07:22 +00:00
public bool debugActive = true;
public static MiniMap Instance { get; private set; }
private float realZoom
{
get
{
return zoom * scaleConst;
}
set
{
zoom = value / scaleConst;
}
}
2020-05-01 16:35:43 +00:00
private float _timeWhenRetrievedZoneName = 0f;
2020-05-31 17:07:22 +00:00
2020-05-01 16:26:45 +00:00
private string _lastZoneName = "";
2020-05-31 17:07:22 +00:00
private string ZoneName
{
get
{
2020-05-01 16:35:43 +00:00
if (Time.time - _timeWhenRetrievedZoneName > 2f)
2020-05-31 17:07:22 +00:00
{
2020-05-01 16:35:43 +00:00
_timeWhenRetrievedZoneName = Time.time;
2020-05-01 16:26:45 +00:00
_lastZoneName = Zone.GetZoneName(this.FocusPos);
2020-05-31 17:07:22 +00:00
}
2020-05-01 16:26:45 +00:00
return _lastZoneName;
2020-05-31 17:07:22 +00:00
}
}
public Texture2D NorthBlip { get { return this.northBlip; } }
public Texture2D PlayerBlip { get { return this.playerBlip; } }
public Texture2D WaypointTexture { get { return this.waypointTexture; } }
2019-07-13 18:35:24 +00:00
public Texture2D VehicleTexture => this.vehicleTexture;
2019-10-27 01:07:08 +00:00
public Texture2D GreenHouseTexture { get; private set; }
2020-05-31 17:07:22 +00:00
public Texture2D MapTexture { get { return this.mapTexture; } }
public Texture2D BlackPixel { get { return this.blackPixel; } }
public Texture2D SeaPixel { get { return this.seaPixel; } }
2020-05-01 17:28:01 +00:00
private Ped m_ped => Ped.Instance;
2020-05-31 17:07:22 +00:00
private PlayerController m_playerController => PlayerController.Instance;
2020-05-31 17:07:22 +00:00
private TextureDictionary huds;
2019-07-13 18:35:24 +00:00
private Texture2D northBlip, playerBlip, waypointTexture, vehicleTexture, mapTexture;
2020-05-01 17:28:01 +00:00
private Sprite mapSprite;
2020-05-31 17:07:22 +00:00
2020-04-28 21:39:30 +00:00
public RectTransform northPivot;
2020-05-31 17:07:22 +00:00
// Zoom vars
public float curZoomPercentage;
2020-04-28 21:39:30 +00:00
private float lastZoom;
2020-05-31 17:07:22 +00:00
private int zoomSelector = 2;
private Coroutine zoomCoroutine;
// GUI Elements
private Texture2D blackPixel, seaPixel;
private float fAlpha = 1;
private bool showZoomPanel;
private float curZoom = 1;
2020-05-01 17:28:01 +00:00
public void Load()
2020-05-31 17:07:22 +00:00
{
2020-05-01 17:28:01 +00:00
LoadGameTextures();
2020-05-31 17:07:22 +00:00
blackPixel = new Texture2D(1, 1);
blackPixel.SetPixel(0, 0, new Color(0, 0, 0, .5f));
blackPixel.Apply();
seaPixel = new Texture2D(1, 1);
seaPixel.SetPixel(0, 0, new Color(.45f, .54f, .678f));
seaPixel.Apply();
}
2020-05-01 17:39:40 +00:00
private void LoadGameTextures()
{
mapTexture = new Texture2D(mapSize, mapSize, TextureFormat.ARGB32, false, true);
TextureLoadParams textureLoadParams = new TextureLoadParams() { makeNoLongerReadable = false };
for (int i = 0; i < tileCount; i++)
{
// Offset
int y = ((i / tileEdge) + 1) * texSize,
x = (i % tileEdge) * texSize;
string name = "radar" + ((i < 10) ? "0" : "") + i;
var texDict = TextureDictionary.Load(name);
Texture2D tex = texDict.GetDiffuse(name, textureLoadParams).Texture;
for (int ii = 0; ii < texSize; ++ii)
for (int jj = 0; jj < texSize; ++jj)
mapTexture.SetPixel(x + ii, texSize - (y + jj) - 1, tex.GetPixel(ii, jj));
// unload the texture (don't destroy it, because it can be a dummy texture)
}
mapTexture.Apply(false, true);
huds = TextureDictionary.Load("hud");
northBlip = huds.GetDiffuse("radar_north").Texture;
playerBlip = huds.GetDiffuse("radar_centre").Texture;
waypointTexture = huds.GetDiffuse("radar_waypoint").Texture;
vehicleTexture = huds.GetDiffuse("radar_impound").Texture;
GreenHouseTexture = huds.GetDiffuse("radar_propertyG").Texture;
northImage.sprite = Sprite.Create(northBlip, new Rect(0, 0, northBlip.width, northBlip.height), new Vector2(northBlip.width, northBlip.height) / 2);
playerImage.texture = this.PlayerBlip;
mapSprite = Sprite.Create(mapTexture, new Rect(0, 0, mapTexture.width, mapTexture.height), new Vector2(mapTexture.width, mapTexture.height) / 2);
mapImage.sprite = mapSprite;
}
2020-05-31 17:07:22 +00:00
private void Awake()
{
Instance = this;
_canvas = this.GetComponentInParent<Canvas>();
2020-05-01 17:28:01 +00:00
curZoomPercentage = zooms[zoomSelector];
2020-05-31 17:07:22 +00:00
}
2020-05-01 17:03:23 +00:00
private void ReadInput()
{
2020-05-01 17:48:24 +00:00
bool zoomIn = Input.GetKeyDown(KeyCode.N);
bool zoomOut = Input.GetKeyDown(KeyCode.B);
2020-05-01 17:03:23 +00:00
2020-05-01 17:48:24 +00:00
if (zoomIn)
2020-05-31 17:07:22 +00:00
++zoomSelector;
2020-05-01 17:48:24 +00:00
else if (zoomOut)
2020-05-31 17:07:22 +00:00
--zoomSelector;
2020-05-01 17:48:24 +00:00
if (zoomIn || zoomOut)
2020-05-31 17:07:22 +00:00
{
2020-05-01 17:03:23 +00:00
if (zoomCoroutine != null)
StopCoroutine(zoomCoroutine);
2020-05-01 17:48:24 +00:00
zoomCoroutine = StartCoroutine(ChangeZoom(zoomIn));
2020-05-31 17:07:22 +00:00
}
}
public static Vector2 WorldPosToMapPos(Vector3 worldPos)
{
// map center is at (0,0) world coordinates
// this, for example, means that the left edge of the world is at: -mapEdge / 2.0f
// adjust world position, so that (0,0) world coordinates are mapped to (0,0) map coordinates
worldPos += new Vector3(mapEdge / 2.0f, 0, mapEdge / 2.0f);
float mul = mapSize / (float)mapEdge;
return new Vector2(worldPos.x * mul, worldPos.z * mul);
}
public static Vector3 MapPosToWorldPos(Vector2 mapPos)
{
// adjust map position, so that (0,0) map coordinated are mapped to (0,0) world coordinates
mapPos -= Vector2.one * (mapSize * 0.5f);
float mul = mapEdge / (float)mapSize;
return new Vector3(mapPos.x * mul, 0.0f, mapPos.y * mul);
}
private void LateUpdate()
{
if (!this.IsMinimapVisible)
return;
2020-05-31 17:07:22 +00:00
2020-05-01 16:21:22 +00:00
// update focus position
var ped = m_ped;
if (ped != null)
this.FocusPos = ped.transform.position;
else if (Camera.main != null)
this.FocusPos = Camera.main.transform.position;
// update zoom based on ped's velocity
var playerController = m_playerController;
if (playerController != null)
realZoom = Mathf.Lerp(.9f * scaleConst, 1.3f * scaleConst, 1 - Mathf.Clamp(playerController.CurVelocity, 0, maxVelocity) / maxVelocity) * curZoomPercentage;
2020-05-01 16:21:22 +00:00
// read input
if (GameManager.CanPlayerReadInput())
{
this.ReadInput();
}
// update position of UI
2020-05-01 16:21:22 +00:00
2020-04-28 21:39:30 +00:00
int worldSize = mapSize * 4;
2020-05-01 16:21:22 +00:00
Vector3 mapPos = - new Vector3(this.FocusPos.x, this.FocusPos.z, 0f) * mapSize / (float)worldSize;
2020-04-28 21:39:30 +00:00
mapImage.rectTransform.localPosition = mapPos;
2020-05-31 17:07:22 +00:00
// update rotation of UI
2020-05-01 16:21:22 +00:00
2020-04-28 21:39:30 +00:00
float relAngle = Camera.main != null ? Camera.main.transform.eulerAngles.y : 0f;
//mapContainer.pivot = new Vector2(mapPos.x, mapPos.y);
mapContainer.localRotation = Quaternion.Euler(0, 0, relAngle);
2020-04-28 21:47:45 +00:00
mapContainer.localScale = new Vector3(realZoom, realZoom, 1);
lastZoom = realZoom;
2020-05-31 17:07:22 +00:00
if (northPivot != null)
northPivot.localRotation = Quaternion.Euler(0, 0, relAngle);
if (playerImage != null && m_ped != null)
playerImage.rectTransform.localRotation = Quaternion.Euler(0, 0, relAngle - (m_ped.transform.eulerAngles.y + 180));
2020-04-28 21:47:45 +00:00
2020-04-28 23:08:38 +00:00
// update zone name label
string currentZoneName = this.ZoneName;
if (currentZoneName != this.zoneNameLabel.text)
this.zoneNameLabel.text = currentZoneName;
2020-05-31 17:07:22 +00:00
}
private IEnumerator ChangeZoom(bool isIncreasing)
{
showZoomPanel = true;
fAlpha = 1;
zoomSelector = GetClampedZoomSelector(zoomSelector);
float curZoom = zooms[zoomSelector % zooms.Length],
lastZoom = zooms[GetClampedZoomSelector(zoomSelector - 1 * (isIncreasing ? 1 : -1)) % zooms.Length];
float t = 0;
while (t < zoomDuration)
{
curZoomPercentage = Mathf.Lerp(lastZoom, curZoom, t / zoomDuration);
yield return new WaitForFixedUpdate();
t += Time.fixedDeltaTime;
fAlpha -= Time.fixedDeltaTime / zoomDuration;
}
showZoomPanel = false;
zoomCoroutine = null;
}
private int GetClampedZoomSelector(int? val = null)
{
int zoomVal = val == null ? zoomSelector : val.Value;
if (zoomVal < 0)
zoomVal = zooms.Length - 1;
return zoomVal;
}
}
}