Files
test/Assets/PerfectWorld/Scripts/UI/MiniMap/MiniMapUI.cs
T
2026-01-22 16:44:50 +07:00

352 lines
15 KiB
C#

using System.Collections.Generic;
using BrewMonster;
using BrewMonster.Scripts;
using BrewMonster.Scripts.Extensions;
using CSNetwork.GPDataType;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace PerfectWorld.UI.MiniMap
{
public class MiniMapUI : MonoBehaviour
{
public struct MARK
{
public int nNPC;
public string strName;
public A3DVECTOR3 vecPos;
int mapID;
public MARK(int nNPC, string strName, A3DVECTOR3 vecPos, int mapID)
{
this.nNPC = nNPC;
this.strName = strName;
this.vecPos = vecPos;
this.mapID = mapID;
}
}
public struct MAPTLVERTEX
{
public float x, y, z, rhw;
public uint diffuse;
public uint specular;
public float tu, tv, tu2, tv2;
}
// constants
private const int MINIMAP_UL = 0;
private const int MINIMAP_UR = 1;
private const int MINIMAP_LL = 2;
private const int MINIMAP_LR = 3;
private const int MINIMAP_MAX = 4;
[SerializeField] private Texture2D m_pA3DRadarBack;
[SerializeField] private Texture2D m_TexRadarBack;
[SerializeField] private byte nRow, nCol; // number of rows and cols in the current map instances.txt
[SerializeField] private string strSubPath; // path to the minimap textures folder "surfaces/minimaps/"
[SerializeField] private RectTransform pObjMiniMap;
[SerializeField] private TMP_Text txtHostPos;
private List<MARK> m_vecMark = new();
private List<MARK> m_vecNPCMark = new();
private Dictionary<string, Texture2D> m_TexMap = new();
private List<string> _texToDelete = new(); // list of texture to delete from m_TexMap, use in update functions.
private float m_fZoom = 1.0f;
private bool m_bShowMark = true;
private bool m_bShowTargetArrow = true;
private MAPTLVERTEX[][] m_vertexMiniMap = new MAPTLVERTEX[MINIMAP_MAX][];
// map state
private bool isShowMiniMap = true;
CECHostPlayer m_pHostPlayer;
private void Awake()
{
// initialize m_vertexMiniMap
for(int i = 0; i < MINIMAP_MAX; i++)
{
m_vertexMiniMap[i] = new MAPTLVERTEX[4];
}
}
void Update()
{
UpdateMiniMap();
}
private void UpdateMiniMap()
{
m_pHostPlayer = GetHostPlayer();
if (m_pHostPlayer == null) return;
Vector3 vecPosHost = m_pHostPlayer.transform.position;
txtHostPos.text = $"{Mathf.RoundToInt(vecPosHost.x) / 10 + 400}, {Mathf.RoundToInt(vecPosHost.z)}";
float fRatio = 512.0f / 1024.0f / m_fZoom;
float fNormal = fRatio;
if( m_fZoom < 1.0f )
fNormal = fRatio * m_fZoom;
vecPosHost.x = Mathf.Floor(vecPosHost.x * fNormal) / fNormal;
vecPosHost.z = Mathf.Floor(vecPosHost.z * fNormal) / fNormal;
Rect rcMiniMap = pObjMiniMap.rect;
//ASSERT(rcMiniMap.Width() == rcMiniMap.Height());
int W = (int)rcMiniMap.width;
int H = (int)rcMiniMap.height;
Vector2 C = rcMiniMap.center;
Vector2 ptHost = new Vector2();
Vector2 idxHost = new Vector2();
Vector2 ptThisCenter = new Vector2();
Vector2[] idxCorner = new Vector2[MINIMAP_MAX];
Rect rcHost = new Rect();
Rect rcThis = new Rect();
Rect[] rcCell = new Rect[MINIMAP_MAX];
Rect[] rcInter = new Rect[MINIMAP_MAX];
int nSide = 256;
float fCell = 1024.0f;
float fSide = nSide;
float fOffsetX = nCol * fCell / 2.0f;
float fOffsetY = nRow * fCell / 2.0f;
ptHost.x = Mathf.FloorToInt((vecPosHost.x + fOffsetX) * 512.0f / 1024.0f);
ptHost.y = Mathf.FloorToInt((fOffsetY - vecPosHost.z) * 512.0f / 1024.0f);
idxHost.x = ptHost.x / nSide;
idxHost.y = ptHost.y / nSide;
rcThis.x = idxHost.x * nSide;
rcThis.y = idxHost.y * nSide;
rcThis.width = nSide;
rcThis.height = nSide;
ptThisCenter = rcThis.center;
if( ptHost.y <= ptThisCenter.y )
{
if( ptHost.x <= ptThisCenter.x ) // Upper left.
{
idxCorner[MINIMAP_UL].x = idxHost.x - 1;
idxCorner[MINIMAP_UL].y = idxHost.y - 1;
idxCorner[MINIMAP_UR].x = idxHost.x;
idxCorner[MINIMAP_UR].y = idxHost.y - 1;
idxCorner[MINIMAP_LL].x = idxHost.x - 1;
idxCorner[MINIMAP_LL].y = idxHost.y;
idxCorner[MINIMAP_LR].x = idxHost.x;
idxCorner[MINIMAP_LR].y = idxHost.y;
}
else // Upper right.
{
idxCorner[MINIMAP_UL].x = idxHost.x;
idxCorner[MINIMAP_UL].y = idxHost.y - 1;
idxCorner[MINIMAP_UR].x = idxHost.x + 1;
idxCorner[MINIMAP_UR].y = idxHost.y - 1;
idxCorner[MINIMAP_LL].x = idxHost.x;
idxCorner[MINIMAP_LL].y = idxHost.y;
idxCorner[MINIMAP_LR].x = idxHost.x + 1;
idxCorner[MINIMAP_LR].y = idxHost.y;
}
}
else
{
if( ptHost.x <= ptThisCenter.x ) // Lower left.
{
idxCorner[MINIMAP_UL].x = idxHost.x - 1;
idxCorner[MINIMAP_UL].y = idxHost.y;
idxCorner[MINIMAP_UR].x = idxHost.x;
idxCorner[MINIMAP_UR].y = idxHost.y;
idxCorner[MINIMAP_LL].x = idxHost.x - 1;
idxCorner[MINIMAP_LL].y = idxHost.y + 1;
idxCorner[MINIMAP_LR].x = idxHost.x;
idxCorner[MINIMAP_LR].y = idxHost.y + 1;
}
else // Lower right.
{
idxCorner[MINIMAP_UL].x = idxHost.x;
idxCorner[MINIMAP_UL].y = idxHost.y;
idxCorner[MINIMAP_UR].x = idxHost.x + 1;
idxCorner[MINIMAP_UR].y = idxHost.y;
idxCorner[MINIMAP_LL].x = idxHost.x;
idxCorner[MINIMAP_LL].y = idxHost.y + 1;
idxCorner[MINIMAP_LR].x = idxHost.x + 1;
idxCorner[MINIMAP_LR].y = idxHost.y + 1;
}
}
rcHost.x = ptHost.x - Mathf.FloorToInt(W * m_fZoom) / 2;
rcHost.y = ptHost.y - Mathf.FloorToInt(H * m_fZoom) / 2;
rcHost.width = Mathf.FloorToInt(W * m_fZoom);
rcHost.height = Mathf.FloorToInt(H * m_fZoom);
int i, j;
bool bval;
//*/
string strIndex = string.Empty;
bool bLoadNewMap = false;
Texture2D pA3DTex = m_TexRadarBack;
for( i = MINIMAP_UL; i < MINIMAP_MAX; i++ )
{
rcCell[i].xMin = idxCorner[i].x * nSide;
rcCell[i].yMin = idxCorner[i].y * nSide;
rcCell[i].width = rcCell[i].x + nSide;
rcCell[i].height = rcCell[i].y + nSide;
rcInter[i] = rcCell[i].Intersect(rcHost);
if( rcInter[i].width == 0 && rcInter[i].height == 0 )
rcInter[i].Offset(rcCell[i].x, rcCell[i].y);
strIndex = $"{idxCorner[i].y:D2}{idxCorner[i].x:D2}";
if(!m_TexMap.ContainsKey(strIndex))
{
if( idxCorner[i].x >= 0 && idxCorner[i].x < nCol * 2 &&
idxCorner[i].y >= 0 && idxCorner[i].y < nRow * 2 )
{
string strFile;
// if(GetWorld()->IsRandomMap())
// {
// strFile = "temp\\Surfaces\\MiniMaps\\" + GetGameRun()->GetRandomMapProc()->GetMapName() + "\\" + strIndex + ".dds";
// pA3DTex->SetNoDownSample(true);
// unsigned char* pData = NULL;
// int iLen = 0;
// if(GetGameRun()->GetRandomMapProc()->EncodeMap(strFile,pData,iLen))
// {
// bool bval = pA3DTex->LoadFromMemory(m_pA3DDevice,pData,iLen,256,256,A3DFMT_UNKNOWN);
// ASSERT(bval);
// delete [] pData;
// }
// }
// else
// {
strFile = string.Format(strSubPath, strIndex, ".dds"); //"Surfaces\\MiniMaps\\" + strSubPath + "\\" + strIndex + ".dds";
pA3DTex = Resources.Load<Texture2D>(strFile);
// }
}
m_TexMap[strIndex] = pA3DTex;
bLoadNewMap = true;
}
}
//*/
if( bLoadNewMap )
{
bool bNoUse;
foreach(var it in m_TexMap)
{
if(it.Value == m_pA3DRadarBack)
{
continue;
}
bNoUse = true;
for( i = MINIMAP_UL; i < MINIMAP_MAX; i++ )
{
strIndex = $"{idxCorner[i].y:D2}{idxCorner[i].x:D2}";
if( strIndex == it.Key )
{
bNoUse = false;
break;
}
}
if( bNoUse )
{
_texToDelete.Add(it.Key);
}
}
}
// delete textures from m_TexMap if needed
foreach(var tex in _texToDelete)
{
m_TexMap.Remove(tex);
}
_texToDelete.Clear();
m_vertexMiniMap[0][0].x = -W / 2.0f;
m_vertexMiniMap[0][0].y = -H / 2.0f;
m_vertexMiniMap[0][1].x = -W / 2.0f + rcInter[MINIMAP_UL].width / m_fZoom;
m_vertexMiniMap[0][1].y = -H / 2.0f;
m_vertexMiniMap[0][2].x = -W / 2.0f;
m_vertexMiniMap[0][2].y = -H / 2.0f + rcInter[MINIMAP_UL].height / m_fZoom;
m_vertexMiniMap[0][3].x = -W / 2.0f + rcInter[MINIMAP_UL].width / m_fZoom;
m_vertexMiniMap[0][3].y = -H / 2.0f + rcInter[MINIMAP_UL].height / m_fZoom;
m_vertexMiniMap[1][0].x = +W / 2.0f - rcInter[MINIMAP_UR].width / m_fZoom;
m_vertexMiniMap[1][0].y = -H / 2.0f;
m_vertexMiniMap[1][1].x = +W / 2.0f;
m_vertexMiniMap[1][1].y = -H / 2.0f;
m_vertexMiniMap[1][2].x = +W / 2.0f - rcInter[MINIMAP_UR].width / m_fZoom;
m_vertexMiniMap[1][2].y = -H / 2.0f + rcInter[MINIMAP_UR].height / m_fZoom;
m_vertexMiniMap[1][3].x = +W / 2.0f;
m_vertexMiniMap[1][3].y = -H / 2.0f + rcInter[MINIMAP_UR].height / m_fZoom;
m_vertexMiniMap[2][0].x = -W / 2.0f;
m_vertexMiniMap[2][0].y = +H / 2.0f - rcInter[MINIMAP_LL].height / m_fZoom;
m_vertexMiniMap[2][1].x = -W / 2.0f + rcInter[MINIMAP_LL].width / m_fZoom;
m_vertexMiniMap[2][1].y = +H / 2.0f - rcInter[MINIMAP_LL].height / m_fZoom;
m_vertexMiniMap[2][2].x = -W / 2.0f;
m_vertexMiniMap[2][2].y = +H / 2.0f;
m_vertexMiniMap[2][3].x = -W / 2.0f + rcInter[MINIMAP_LL].width / m_fZoom;
m_vertexMiniMap[2][3].y = +H / 2.0f;
m_vertexMiniMap[3][0].x = +W / 2.0f - rcInter[MINIMAP_LR].width / m_fZoom;
m_vertexMiniMap[3][0].y = +H / 2.0f - rcInter[MINIMAP_LR].height / m_fZoom;
m_vertexMiniMap[3][1].x = +W / 2.0f;
m_vertexMiniMap[3][1].y = +H / 2.0f - rcInter[MINIMAP_LR].height / m_fZoom;
m_vertexMiniMap[3][2].x = +W / 2.0f - rcInter[MINIMAP_LR].width / m_fZoom;
m_vertexMiniMap[3][2].y = +H / 2.0f;
m_vertexMiniMap[3][3].x = +W / 2.0f;
m_vertexMiniMap[3][3].y = +H / 2.0f;
pA3DTex = m_TexRadarBack;
ushort[] a_wIndex = new ushort[6] { 0, 1, 2, 2, 1, 3 };
A3DVECTOR3 vecPos = new A3DVECTOR3(0);
for (i = 0; i < MINIMAP_MAX; i++)
{
strIndex = string.Format("{0:D2}{1:D2}", idxCorner[i].y, idxCorner[i].x);
pA3DTex = m_TexMap[strIndex];
m_vertexMiniMap[i][0].tu = (float)(rcInter[i].xMin - rcCell[i].xMin) / fSide;
m_vertexMiniMap[i][0].tv = (float)(rcInter[i].yMin - rcCell[i].yMin) / fSide;
m_vertexMiniMap[i][1].tu = (float)(rcInter[i].xMax - rcCell[i].xMin) / fSide;
m_vertexMiniMap[i][1].tv = (float)(rcInter[i].yMin - rcCell[i].yMin) / fSide;
m_vertexMiniMap[i][2].tu = (float)(rcInter[i].xMin - rcCell[i].xMin) / fSide;
m_vertexMiniMap[i][2].tv = (float)(rcInter[i].yMax - rcCell[i].yMin) / fSide;
m_vertexMiniMap[i][3].tu = (float)(rcInter[i].xMax - rcCell[i].xMin) / fSide;
m_vertexMiniMap[i][3].tv = (float)(rcInter[i].yMax - rcCell[i].yMin) / fSide;
for( j = 0; j < 4; j++ )
{
m_vertexMiniMap[i][j].tu2 = (m_vertexMiniMap[i][j].x
+ C.x - rcMiniMap.xMin) / (float)(W);
m_vertexMiniMap[i][j].tv2 = (m_vertexMiniMap[i][j].y
+ C.y - rcMiniMap.yMin) / (float)(H);
// if( MODE_A == m_nMode )
// {
vecPos.x = m_vertexMiniMap[i][j].x;
vecPos.y = m_vertexMiniMap[i][j].y;
// vecPos = vecPos * m;
// m_vertexMiniMap[i][j].x = vecPos.x + p->X;
// m_vertexMiniMap[i][j].y = vecPos.y + p->Y;
// }
// else
// {
// m_vertexMiniMap[i][j].x += C.x + p->X;
// m_vertexMiniMap[i][j].y += C.y + p->Y;
// }
m_vertexMiniMap[i][j].x -= 0.5f;
m_vertexMiniMap[i][j].y -= 0.5f;
}
}
}
private CECHostPlayer GetHostPlayer()
{
return CECGameRun.Instance.GetHostPlayer();
}
}
}