mirror of
https://github.com/GTA-ASM/SanAndreasUnity
synced 2024-11-27 06:20:17 +00:00
270 lines
No EOL
9 KiB
C#
270 lines
No EOL
9 KiB
C#
using SanAndreasUnity.Importing.Conversion;
|
|
using SanAndreasUnity.Utilities;
|
|
using System.Collections;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
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 MiniMap Instance { get; private set; }
|
|
|
|
public Image northImage,
|
|
outlineImage,
|
|
maskImage;
|
|
|
|
public RawImage mapImage, playerImage;
|
|
|
|
public RectTransform mapTransform,
|
|
maskTransform,
|
|
mapContainer,
|
|
northPivot;
|
|
|
|
public Text zoneNameLabel;
|
|
|
|
private Canvas _canvas;
|
|
|
|
private const float maxVelocityForZooming = 300f;
|
|
public static readonly float[] availableZooms = new float[] { .5f, .75f, 1f, 1.2f, 1.4f, 1.6f, 2f, 2.5f, 3f, 5f };
|
|
|
|
public float zoom = 1.3f;
|
|
public float zoomDuration = 1;
|
|
private float curZoomPercentage;
|
|
public int zoomSelector = 2;
|
|
private Coroutine zoomCoroutine;
|
|
|
|
public Vector3 FocusPos { get; set; } = Vector3.zero;
|
|
|
|
public bool IsMinimapVisible => _canvas.enabled && this.gameObject.activeInHierarchy;
|
|
|
|
private float _timeWhenRetrievedZoneName = 0f;
|
|
|
|
private string _lastZoneName = "";
|
|
|
|
private string ZoneName
|
|
{
|
|
get
|
|
{
|
|
if (Time.time - _timeWhenRetrievedZoneName > 2f)
|
|
{
|
|
_timeWhenRetrievedZoneName = Time.time;
|
|
_lastZoneName = Zone.GetZoneName(this.FocusPos);
|
|
}
|
|
|
|
return _lastZoneName;
|
|
}
|
|
}
|
|
|
|
public Texture2D NorthBlip { get; private set; }
|
|
public Texture2D PlayerBlip { get; private set; }
|
|
public Texture2D WaypointTexture { get; private set; }
|
|
public Texture2D VehicleTexture { get; private set; }
|
|
public Texture2D GreenHouseTexture { get; private set; }
|
|
public Texture2D MapTexture { get; private set; }
|
|
|
|
public Texture2D BlackPixel { get; private set; }
|
|
public Texture2D SeaPixel { get; private set; }
|
|
|
|
|
|
|
|
public void Load()
|
|
{
|
|
|
|
LoadGameTextures();
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
var 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;
|
|
mapImage.texture = MapTexture;
|
|
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
Instance = this;
|
|
|
|
_canvas = this.GetComponentInParent<Canvas>();
|
|
|
|
curZoomPercentage = availableZooms[zoomSelector];
|
|
|
|
}
|
|
|
|
private void ReadInput()
|
|
{
|
|
bool zoomIn = Input.GetKeyDown(KeyCode.N);
|
|
bool zoomOut = Input.GetKeyDown(KeyCode.B);
|
|
|
|
if (zoomIn)
|
|
++zoomSelector;
|
|
else if (zoomOut)
|
|
--zoomSelector;
|
|
|
|
if (zoomIn || zoomOut)
|
|
{
|
|
if (zoomCoroutine != null)
|
|
StopCoroutine(zoomCoroutine);
|
|
zoomCoroutine = StartCoroutine(ChangeZoom(zoomIn));
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
|
|
// update focus position
|
|
|
|
var ped = Ped.Instance;
|
|
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 = PlayerController.Instance;
|
|
if (playerController != null)
|
|
zoom = Mathf.Lerp(.9f, 1.3f, 1 - Mathf.Clamp(playerController.CurVelocity, 0, maxVelocityForZooming) / maxVelocityForZooming) * curZoomPercentage;
|
|
|
|
// read input
|
|
|
|
if (GameManager.CanPlayerReadInput())
|
|
{
|
|
this.ReadInput();
|
|
}
|
|
|
|
// update position of UI
|
|
|
|
Vector3 mapPos = - new Vector3(this.FocusPos.x, this.FocusPos.z, 0f) * (mapSize / (float)mapEdge);
|
|
mapImage.rectTransform.localPosition = mapPos;
|
|
|
|
// update rotation of UI
|
|
|
|
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);
|
|
|
|
mapContainer.localScale = new Vector3(zoom, zoom, 1);
|
|
|
|
if (northPivot != null)
|
|
northPivot.localRotation = Quaternion.Euler(0, 0, relAngle);
|
|
|
|
if (playerImage != null && ped != null)
|
|
playerImage.rectTransform.localRotation = Quaternion.Euler(0, 0, relAngle - (ped.transform.eulerAngles.y + 180));
|
|
|
|
// update zone name label
|
|
|
|
string currentZoneName = this.ZoneName;
|
|
if (currentZoneName != this.zoneNameLabel.text)
|
|
this.zoneNameLabel.text = currentZoneName;
|
|
|
|
}
|
|
|
|
private IEnumerator ChangeZoom(bool isIncreasing)
|
|
{
|
|
float fAlpha = 1;
|
|
|
|
zoomSelector = GetClampedZoomSelector(zoomSelector);
|
|
float curZoom = availableZooms[zoomSelector % availableZooms.Length],
|
|
lastZoom = availableZooms[GetClampedZoomSelector(zoomSelector - 1 * (isIncreasing ? 1 : -1)) % availableZooms.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;
|
|
}
|
|
|
|
zoomCoroutine = null;
|
|
}
|
|
|
|
private int GetClampedZoomSelector(int? val = null)
|
|
{
|
|
int zoomVal = val == null ? zoomSelector : val.Value;
|
|
|
|
if (zoomVal < 0)
|
|
zoomVal = availableZooms.Length - 1;
|
|
|
|
return zoomVal;
|
|
}
|
|
|
|
}
|
|
} |