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; } }; // 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 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 m_vecMark = new(); private List m_vecNPCMark = new(); private Dictionary m_TexMap = new(); private float m_fZoom = 1.0f; private bool m_bShowMark = true; private bool m_bShowTargetArrow = true; // map state private bool isShowMiniMap = true; CECHostPlayer m_pHostPlayer; 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; //*/ char[] szIndex = new char[20]; string strIndex = string.Empty; bool bLoadNewMap = false; 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)) { Texture2D pA3DTex = m_TexRadarBack; 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(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++ ) { sprintf(szIndex, "%02d%02d", idxCorner[i].y, idxCorner[i].x); strIndex = $"{idxCorner[i].y:D2}{idxCorner[i].x:D2}"; if( strIndex == it.Key ) { bNoUse = false; break; } } if( bNoUse ) { A3DRELEASE(it->second); it = m_TexMap.erase(it); } else ++it; } } } private CECHostPlayer GetHostPlayer() { return CECGameRun.Instance.GetHostPlayer(); } } }