2026-01-06 04:07:34 +01:00
|
|
|
|
using BepInEx;
|
2026-01-06 05:22:10 +01:00
|
|
|
|
using HarmonyLib;
|
2026-01-06 04:07:34 +01:00
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
2026-01-06 05:22:10 +01:00
|
|
|
|
using System.Linq;
|
2026-01-06 04:07:34 +01:00
|
|
|
|
using UnityEngine;
|
2026-01-06 05:22:10 +01:00
|
|
|
|
using UnityEngine.UI;
|
2026-01-06 04:07:34 +01:00
|
|
|
|
using TMPro;
|
|
|
|
|
|
|
|
|
|
|
|
namespace StrategicMapPlus
|
|
|
|
|
|
{
|
2026-01-06 05:22:10 +01:00
|
|
|
|
[BepInPlugin("com.mod.strategicmapplus", "Strategic Map Plus", "28.0.0")]
|
2026-01-06 04:07:34 +01:00
|
|
|
|
public class StrategicMapMod : BaseUnityPlugin
|
|
|
|
|
|
{
|
2026-01-06 16:15:35 +01:00
|
|
|
|
public static bool GlobalShowToggle = false;
|
2026-01-06 04:07:34 +01:00
|
|
|
|
private float timer = 0f;
|
|
|
|
|
|
private float interval = 0.5f;
|
2026-01-06 05:22:10 +01:00
|
|
|
|
private bool texturesLoaded = false;
|
|
|
|
|
|
|
|
|
|
|
|
public static Dictionary<string, Sprite> SpriteCache = new Dictionary<string, Sprite>();
|
2026-01-06 16:15:35 +01:00
|
|
|
|
public static Dictionary<string, Texture2D> RawTextureCache = new Dictionary<string, Texture2D>();
|
2026-01-06 05:22:10 +01:00
|
|
|
|
private HashSet<string> reportedMissingKeys = new HashSet<string>();
|
2026-01-06 04:07:34 +01:00
|
|
|
|
|
|
|
|
|
|
void Awake()
|
|
|
|
|
|
{
|
2026-01-06 05:22:10 +01:00
|
|
|
|
Logger.LogInfo("Strategic Map Plus v28: Posición 0,0,0.");
|
2026-01-06 04:07:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Update()
|
|
|
|
|
|
{
|
2026-01-06 16:15:35 +01:00
|
|
|
|
// Toggle con Ctrl + V
|
|
|
|
|
|
if ((Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)) && Input.GetKeyDown(KeyCode.V))
|
|
|
|
|
|
{
|
|
|
|
|
|
GlobalShowToggle = !GlobalShowToggle;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-06 05:22:10 +01:00
|
|
|
|
if (!texturesLoaded && Time.time > 3f) LoadTextures();
|
|
|
|
|
|
|
2026-01-06 04:07:34 +01:00
|
|
|
|
timer += Time.deltaTime;
|
|
|
|
|
|
if (timer < interval) return;
|
|
|
|
|
|
timer = 0f;
|
|
|
|
|
|
|
2026-01-06 05:22:10 +01:00
|
|
|
|
if (texturesLoaded) ScanStrategicMap();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void LoadTextures()
|
|
|
|
|
|
{
|
|
|
|
|
|
Texture2D[] allTextures = Resources.FindObjectsOfTypeAll<Texture2D>();
|
|
|
|
|
|
Dictionary<string, Texture2D> textureLookup = new Dictionary<string, Texture2D>();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var tex in allTextures)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (tex != null && !string.IsNullOrEmpty(tex.name))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!textureLookup.ContainsKey(tex.name)) textureLookup.Add(tex.name, tex);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int loadedCount = 0;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var kvp in Textures.TextureMap)
|
|
|
|
|
|
{
|
|
|
|
|
|
string logicKey = kvp.Key;
|
|
|
|
|
|
string texName = kvp.Value;
|
|
|
|
|
|
|
|
|
|
|
|
if (textureLookup.ContainsKey(texName))
|
|
|
|
|
|
{
|
|
|
|
|
|
Texture2D tex = textureLookup[texName];
|
2026-01-06 16:15:35 +01:00
|
|
|
|
RawTextureCache[logicKey] = tex; // Guardamos la original para Debug
|
|
|
|
|
|
|
2026-01-06 15:29:51 +01:00
|
|
|
|
Textures.IconOffset offset = null;
|
|
|
|
|
|
if (Textures.IconsOffsets.ContainsKey(logicKey)) offset = Textures.IconsOffsets[logicKey];
|
|
|
|
|
|
|
|
|
|
|
|
Texture2D roundTex = MakeTextureTransparent(tex, offset);
|
2026-01-06 15:22:22 +01:00
|
|
|
|
Sprite s = Sprite.Create(roundTex, new Rect(0, 0, roundTex.width, roundTex.height), new Vector2(0.5f, 0.5f));
|
2026-01-06 05:22:10 +01:00
|
|
|
|
SpriteCache[logicKey] = s;
|
|
|
|
|
|
loadedCount++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (loadedCount > 0) texturesLoaded = true;
|
2026-01-06 04:07:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ScanStrategicMap()
|
|
|
|
|
|
{
|
|
|
|
|
|
GameObject regionsRoot = GameObject.Find("UI/2DRoot/Layout/Limit/FrontDialogs/StrategicView/Root/Regions");
|
|
|
|
|
|
if (regionsRoot == null || !regionsRoot.activeInHierarchy) return;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (Transform region in regionsRoot.transform)
|
|
|
|
|
|
{
|
|
|
|
|
|
Transform army = region.Find("Army");
|
|
|
|
|
|
if (army == null) continue;
|
|
|
|
|
|
|
|
|
|
|
|
Component defenseRenderer = army.GetComponent("iron.match.renderers.strategicview.DefenseCountRenderer");
|
|
|
|
|
|
Transform visualRoot = army.Find("Root");
|
|
|
|
|
|
Transform targetParent = (visualRoot != null) ? visualRoot : army;
|
|
|
|
|
|
|
|
|
|
|
|
if (defenseRenderer != null)
|
|
|
|
|
|
ProcessRegion((MonoBehaviour)defenseRenderer, targetParent);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ProcessRegion(MonoBehaviour renderer, Transform parentTransform)
|
|
|
|
|
|
{
|
2026-01-06 05:22:10 +01:00
|
|
|
|
var visualizer = parentTransform.GetComponent<StrategicDisplay>();
|
2026-01-06 04:07:34 +01:00
|
|
|
|
if (visualizer == null)
|
|
|
|
|
|
{
|
2026-01-06 05:22:10 +01:00
|
|
|
|
visualizer = parentTransform.gameObject.AddComponent<StrategicDisplay>();
|
2026-01-06 04:07:34 +01:00
|
|
|
|
visualizer.Initialize();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var traverse = Traverse.Create(renderer);
|
|
|
|
|
|
var model = traverse.Property("model").GetValue();
|
2026-01-06 05:22:10 +01:00
|
|
|
|
if (model == null) { visualizer.Hide(); return; }
|
2026-01-06 04:07:34 +01:00
|
|
|
|
|
|
|
|
|
|
var children = Traverse.Create(model).Field("Children").GetValue() as IEnumerable;
|
|
|
|
|
|
if (children == null) children = Traverse.Create(model).Field("children").GetValue() as IEnumerable;
|
|
|
|
|
|
|
2026-01-06 05:22:10 +01:00
|
|
|
|
string orderType = "";
|
|
|
|
|
|
bool isSpecial = false;
|
|
|
|
|
|
int strength = 0;
|
|
|
|
|
|
bool found = false;
|
2026-01-06 04:07:34 +01:00
|
|
|
|
|
|
|
|
|
|
if (children != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var child in children)
|
|
|
|
|
|
{
|
|
|
|
|
|
var childTrav = Traverse.Create(child);
|
|
|
|
|
|
var attributesObj = childTrav.Field("attributes").GetValue();
|
|
|
|
|
|
if (attributesObj != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var valuesDict = Traverse.Create(attributesObj).Field("data").GetValue() as IDictionary;
|
2026-01-06 05:22:10 +01:00
|
|
|
|
if (valuesDict != null && valuesDict.Contains(400003))
|
2026-01-06 04:07:34 +01:00
|
|
|
|
{
|
2026-01-06 05:22:10 +01:00
|
|
|
|
object typeCont = valuesDict[400003];
|
|
|
|
|
|
object typeVal = Traverse.Create(typeCont).Property("Value").GetValue();
|
2026-01-06 04:07:34 +01:00
|
|
|
|
|
2026-01-06 05:22:10 +01:00
|
|
|
|
if (typeVal?.ToString() == "Order")
|
|
|
|
|
|
{
|
|
|
|
|
|
if (valuesDict.Contains(400038)) // OrderType
|
|
|
|
|
|
{
|
|
|
|
|
|
object oCont = valuesDict[400038];
|
|
|
|
|
|
object oVal = Traverse.Create(oCont).Property("Value").GetValue();
|
|
|
|
|
|
var list = oVal as IList;
|
|
|
|
|
|
if (list != null && list.Count > 0) orderType = list[0].ToString();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (valuesDict.Contains(400039)) // HasStar
|
|
|
|
|
|
{
|
|
|
|
|
|
object sCont = valuesDict[400039];
|
|
|
|
|
|
object sVal = Traverse.Create(sCont).Property("Value").GetValue();
|
|
|
|
|
|
if (sVal != null && sVal.ToString().ToLower() == "true") isSpecial = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (valuesDict.Contains(400004)) // Strength
|
2026-01-06 04:07:34 +01:00
|
|
|
|
{
|
2026-01-06 05:22:10 +01:00
|
|
|
|
object strCont = valuesDict[400004];
|
|
|
|
|
|
object strVal = Traverse.Create(strCont).Property("Value").GetValue();
|
|
|
|
|
|
int.TryParse(strVal?.ToString(), out strength);
|
2026-01-06 04:07:34 +01:00
|
|
|
|
}
|
2026-01-06 05:22:10 +01:00
|
|
|
|
found = true;
|
|
|
|
|
|
break;
|
2026-01-06 04:07:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-06 05:22:10 +01:00
|
|
|
|
if (!found)
|
|
|
|
|
|
{
|
|
|
|
|
|
visualizer.Hide();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-01-06 04:07:34 +01:00
|
|
|
|
|
2026-01-06 05:22:10 +01:00
|
|
|
|
// Generar clave lógica
|
|
|
|
|
|
string generatedKey = $"{orderType}_{strength}";
|
|
|
|
|
|
if (isSpecial) generatedKey += "_Star";
|
2026-01-06 04:07:34 +01:00
|
|
|
|
|
2026-01-06 05:22:10 +01:00
|
|
|
|
if (SpriteCache.ContainsKey(generatedKey))
|
|
|
|
|
|
{
|
2026-01-06 16:15:35 +01:00
|
|
|
|
Texture2D raw = RawTextureCache.ContainsKey(generatedKey) ? RawTextureCache[generatedKey] : null;
|
|
|
|
|
|
visualizer.ShowIcon(SpriteCache[generatedKey], raw);
|
2026-01-06 05:22:10 +01:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!reportedMissingKeys.Contains(generatedKey))
|
|
|
|
|
|
{
|
|
|
|
|
|
Logger.LogWarning($"[FALTA MAPEO] El juego pide: '{generatedKey}'");
|
|
|
|
|
|
reportedMissingKeys.Add(generatedKey);
|
|
|
|
|
|
}
|
|
|
|
|
|
visualizer.ShowText(generatedKey);
|
|
|
|
|
|
}
|
2026-01-06 04:07:34 +01:00
|
|
|
|
}
|
2026-01-06 15:22:22 +01:00
|
|
|
|
|
|
|
|
|
|
// Función auxiliar que podrías llamar desde tu parche de Harmony
|
2026-01-06 15:29:51 +01:00
|
|
|
|
public static Texture2D MakeTextureTransparent(Texture originalTexture, Textures.IconOffset offset = null)
|
2026-01-06 15:22:22 +01:00
|
|
|
|
{
|
|
|
|
|
|
if (originalTexture == null) return null;
|
|
|
|
|
|
|
|
|
|
|
|
// 1. Crear una RenderTexture temporal para poder leer la textura original
|
|
|
|
|
|
RenderTexture tmp = RenderTexture.GetTemporary(
|
|
|
|
|
|
originalTexture.width,
|
|
|
|
|
|
originalTexture.height,
|
|
|
|
|
|
0,
|
|
|
|
|
|
RenderTextureFormat.Default,
|
|
|
|
|
|
RenderTextureReadWrite.Linear);
|
|
|
|
|
|
|
|
|
|
|
|
// 2. Copiar la textura original a la RenderTexture (esto "desbloquea" los píxeles)
|
|
|
|
|
|
Graphics.Blit(originalTexture, tmp);
|
|
|
|
|
|
|
|
|
|
|
|
// 3. Activar la RenderTexture para leerla
|
|
|
|
|
|
RenderTexture previous = RenderTexture.active;
|
|
|
|
|
|
RenderTexture.active = tmp;
|
|
|
|
|
|
|
|
|
|
|
|
// 4. Crear una nueva Texture2D leíble
|
|
|
|
|
|
Texture2D newTexture = new Texture2D(originalTexture.width, originalTexture.height);
|
|
|
|
|
|
newTexture.ReadPixels(new Rect(0, 0, tmp.width, tmp.height), 0, 0);
|
|
|
|
|
|
|
2026-01-06 16:15:35 +01:00
|
|
|
|
// 5. MODIFICAR LOS PÍXELES (Lógica de Re-muestreo / Resampling)
|
|
|
|
|
|
// En lugar de mover la máscara, dejamos la máscara fija en el centro y movemos la textura (Source).
|
|
|
|
|
|
// Esto permite hacer CLAMP (repetir bordes) para evitar cortes rectos.
|
|
|
|
|
|
|
|
|
|
|
|
Color[] sourcePixels = newTexture.GetPixels(); // Píxeles originales (Source)
|
|
|
|
|
|
Color[] finalPixels = new Color[sourcePixels.Length]; // Píxeles destino (Destination)
|
|
|
|
|
|
|
2026-01-06 15:22:22 +01:00
|
|
|
|
float width = newTexture.width;
|
|
|
|
|
|
float height = newTexture.height;
|
|
|
|
|
|
Vector2 center = new Vector2(width / 2f, height / 2f);
|
2026-01-06 16:15:35 +01:00
|
|
|
|
|
|
|
|
|
|
// Configuración por defecto
|
|
|
|
|
|
float maskRadius = (Mathf.Min(width, height) / 2f);
|
|
|
|
|
|
float shiftX = 0f;
|
|
|
|
|
|
float shiftY = 0f;
|
2026-01-06 15:22:22 +01:00
|
|
|
|
|
2026-01-06 15:29:51 +01:00
|
|
|
|
if (offset != null)
|
|
|
|
|
|
{
|
2026-01-06 16:15:35 +01:00
|
|
|
|
// Size: Escala de la máscara (1.0 = toca bordes)
|
|
|
|
|
|
if (offset.size > 0) maskRadius *= offset.size;
|
|
|
|
|
|
|
|
|
|
|
|
// Offset: Desplazamiento del CONTENIDO (UV Shift)
|
|
|
|
|
|
// Si Offset X > 0 (positivo), queremos ver lo que hay a la derecha,
|
|
|
|
|
|
// por tanto "desplazamos la textura hacia la izquierda" (sumamos al índice de lectura).
|
|
|
|
|
|
shiftX = offset.x * width;
|
|
|
|
|
|
shiftY = offset.y * height;
|
|
|
|
|
|
} else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Default
|
|
|
|
|
|
offset = new Textures.IconOffset(0.07f, 0, 0.9f);
|
|
|
|
|
|
|
|
|
|
|
|
if (offset.size > 0) maskRadius *= offset.size;
|
|
|
|
|
|
shiftX = offset.x * width;
|
|
|
|
|
|
shiftY = offset.y * height;
|
2026-01-06 15:29:51 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-06 16:15:35 +01:00
|
|
|
|
int w = (int)width;
|
|
|
|
|
|
int h = (int)height;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < finalPixels.Length; i++)
|
2026-01-06 15:22:22 +01:00
|
|
|
|
{
|
2026-01-06 16:15:35 +01:00
|
|
|
|
int x = i % w;
|
|
|
|
|
|
int y = i / w;
|
2026-01-06 15:22:22 +01:00
|
|
|
|
|
2026-01-06 16:15:35 +01:00
|
|
|
|
// 1. MÁSCARA (Siempre centrada en el output)
|
|
|
|
|
|
float dist = Vector2.Distance(new Vector2(x, y), center);
|
|
|
|
|
|
if (dist > maskRadius)
|
2026-01-06 15:22:22 +01:00
|
|
|
|
{
|
2026-01-06 16:15:35 +01:00
|
|
|
|
finalPixels[i] = Color.clear;
|
|
|
|
|
|
continue;
|
2026-01-06 15:22:22 +01:00
|
|
|
|
}
|
2026-01-06 16:15:35 +01:00
|
|
|
|
|
|
|
|
|
|
// 2. MUESTREO (Sampling) con Offset
|
|
|
|
|
|
// Calculamos qué píxel de la textura original corresponde a esta posición (x,y)
|
|
|
|
|
|
int srcX = (int)(x + shiftX);
|
|
|
|
|
|
int srcY = (int)(y + shiftY);
|
|
|
|
|
|
|
|
|
|
|
|
// 3. CLAMP (Repetir bordes)
|
|
|
|
|
|
// Si nos salimos de la textura, repetimos el último píxel válido.
|
|
|
|
|
|
// Esto evita el "corte recto" transparente (siempre que el borde tenga color).
|
|
|
|
|
|
srcX = Mathf.Clamp(srcX, 0, w - 1);
|
|
|
|
|
|
srcY = Mathf.Clamp(srcY, 0, h - 1);
|
|
|
|
|
|
|
|
|
|
|
|
// Leemos del array original
|
|
|
|
|
|
int srcIndex = srcY * w + srcX;
|
|
|
|
|
|
finalPixels[i] = sourcePixels[srcIndex];
|
2026-01-06 15:22:22 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-06 16:15:35 +01:00
|
|
|
|
newTexture.SetPixels(finalPixels);
|
2026-01-06 15:22:22 +01:00
|
|
|
|
newTexture.Apply();
|
|
|
|
|
|
|
|
|
|
|
|
// 6. Limpieza
|
|
|
|
|
|
RenderTexture.active = previous;
|
|
|
|
|
|
RenderTexture.ReleaseTemporary(tmp);
|
|
|
|
|
|
|
|
|
|
|
|
return newTexture;
|
|
|
|
|
|
}
|
2026-01-06 04:07:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-06 05:22:10 +01:00
|
|
|
|
// --- VISUALIZADOR ---
|
|
|
|
|
|
public class StrategicDisplay : MonoBehaviour
|
2026-01-06 04:07:34 +01:00
|
|
|
|
{
|
|
|
|
|
|
private GameObject displayObj;
|
2026-01-06 05:22:10 +01:00
|
|
|
|
private Image iconImage;
|
|
|
|
|
|
private TextMeshProUGUI debugText;
|
|
|
|
|
|
private bool isInitialized = false;
|
2026-01-06 05:50:51 +01:00
|
|
|
|
private bool hasContent = false;
|
|
|
|
|
|
|
2026-01-06 16:15:35 +01:00
|
|
|
|
// --- ZONA DEBUG EN INSPECTOR ---
|
|
|
|
|
|
public bool DebugMode = false;
|
|
|
|
|
|
public float DebugOffsetX = 0f;
|
|
|
|
|
|
public float DebugOffsetY = 0f;
|
|
|
|
|
|
public float DebugSize = 1f;
|
|
|
|
|
|
|
|
|
|
|
|
private Texture2D _rawTexture; // La textura original sin recortar
|
|
|
|
|
|
private Texture2D _generatedDebugTex; // Para limpiar memoria
|
|
|
|
|
|
private Sprite _defaultSprite; // Sprite original para restaurar
|
|
|
|
|
|
private float _lastX, _lastY, _lastSize;
|
|
|
|
|
|
private bool _lastDebugMode;
|
|
|
|
|
|
|
2026-01-06 05:50:51 +01:00
|
|
|
|
void Update()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!isInitialized || displayObj == null) return;
|
|
|
|
|
|
|
2026-01-06 16:15:35 +01:00
|
|
|
|
// Lógica de visualización (V o Ctrl+V)
|
|
|
|
|
|
bool shouldShow = hasContent && (StrategicMapMod.GlobalShowToggle || Input.GetKey(KeyCode.V));
|
2026-01-06 05:50:51 +01:00
|
|
|
|
if (displayObj.activeSelf != shouldShow)
|
|
|
|
|
|
{
|
|
|
|
|
|
displayObj.SetActive(shouldShow);
|
|
|
|
|
|
}
|
2026-01-06 16:15:35 +01:00
|
|
|
|
|
|
|
|
|
|
// Lógica de DEBUG en tiempo real
|
|
|
|
|
|
if (_rawTexture != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Si activamos el modo debug, forzamos actualización
|
|
|
|
|
|
if (DebugMode && !_lastDebugMode)
|
|
|
|
|
|
{
|
|
|
|
|
|
_lastDebugMode = true;
|
|
|
|
|
|
UpdateDebugTexture();
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (!DebugMode && _lastDebugMode)
|
|
|
|
|
|
{
|
|
|
|
|
|
_lastDebugMode = false;
|
|
|
|
|
|
// AL SALIR DEL DEBUG: Restaurar el sprite original
|
|
|
|
|
|
if (iconImage != null && _defaultSprite != null) iconImage.sprite = _defaultSprite;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (DebugMode)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_lastX != DebugOffsetX || _lastY != DebugOffsetY || _lastSize != DebugSize)
|
|
|
|
|
|
{
|
|
|
|
|
|
UpdateDebugTexture();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void UpdateDebugTexture()
|
|
|
|
|
|
{
|
|
|
|
|
|
_lastX = DebugOffsetX;
|
|
|
|
|
|
_lastY = DebugOffsetY;
|
|
|
|
|
|
_lastSize = DebugSize;
|
|
|
|
|
|
|
|
|
|
|
|
if (_generatedDebugTex != null) Destroy(_generatedDebugTex);
|
|
|
|
|
|
|
|
|
|
|
|
var debugOffset = new Textures.IconOffset(DebugOffsetX, DebugOffsetY, DebugSize);
|
|
|
|
|
|
_generatedDebugTex = StrategicMapMod.MakeTextureTransparent(_rawTexture, debugOffset);
|
|
|
|
|
|
|
|
|
|
|
|
if (_generatedDebugTex != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Sprite debugSprite = Sprite.Create(_generatedDebugTex, new Rect(0, 0, _generatedDebugTex.width, _generatedDebugTex.height), new Vector2(0.5f, 0.5f));
|
|
|
|
|
|
if (iconImage != null) iconImage.sprite = debugSprite;
|
|
|
|
|
|
}
|
2026-01-06 05:50:51 +01:00
|
|
|
|
}
|
2026-01-06 04:07:34 +01:00
|
|
|
|
|
|
|
|
|
|
public void Initialize()
|
|
|
|
|
|
{
|
2026-01-06 05:22:10 +01:00
|
|
|
|
if (isInitialized && displayObj != null) return;
|
|
|
|
|
|
if (displayObj != null) Destroy(displayObj);
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
displayObj = new GameObject("OrderIcon_Mod");
|
|
|
|
|
|
displayObj.transform.SetParent(this.transform, false);
|
|
|
|
|
|
|
|
|
|
|
|
// POSICIÓN EXACTA 0,0,0
|
|
|
|
|
|
displayObj.transform.localPosition = Vector3.zero;
|
|
|
|
|
|
|
|
|
|
|
|
// Aseguramos capa correcta
|
|
|
|
|
|
displayObj.layer = this.gameObject.layer;
|
|
|
|
|
|
|
|
|
|
|
|
RectTransform rt = displayObj.AddComponent<RectTransform>();
|
|
|
|
|
|
rt.sizeDelta = new Vector2(45, 45); // Tamaño del icono
|
|
|
|
|
|
|
|
|
|
|
|
iconImage = displayObj.AddComponent<Image>();
|
|
|
|
|
|
iconImage.raycastTarget = false;
|
|
|
|
|
|
iconImage.color = Color.white;
|
|
|
|
|
|
|
|
|
|
|
|
// Backup Text
|
|
|
|
|
|
GameObject textObj = new GameObject("BackupText");
|
|
|
|
|
|
textObj.transform.SetParent(displayObj.transform, false);
|
|
|
|
|
|
textObj.layer = this.gameObject.layer;
|
|
|
|
|
|
|
|
|
|
|
|
RectTransform textRt = textObj.AddComponent<RectTransform>();
|
|
|
|
|
|
textRt.anchoredPosition = Vector2.zero;
|
|
|
|
|
|
|
|
|
|
|
|
debugText = textObj.AddComponent<TextMeshProUGUI>();
|
|
|
|
|
|
debugText.alignment = TextAlignmentOptions.Center;
|
|
|
|
|
|
debugText.fontSize = 14;
|
|
|
|
|
|
debugText.fontStyle = FontStyles.Bold;
|
|
|
|
|
|
debugText.color = Color.magenta;
|
|
|
|
|
|
|
|
|
|
|
|
// CRUCIAL: Ponemos el icono al final de la lista de hijos para que se pinte ENCIMA
|
|
|
|
|
|
displayObj.transform.SetAsLastSibling();
|
|
|
|
|
|
|
2026-01-06 05:50:51 +01:00
|
|
|
|
// Inicialmente oculto
|
|
|
|
|
|
displayObj.SetActive(false);
|
|
|
|
|
|
|
2026-01-06 05:22:10 +01:00
|
|
|
|
isInitialized = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (System.Exception e)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning("Error UI: " + e.Message);
|
|
|
|
|
|
if (displayObj != null) Destroy(displayObj);
|
|
|
|
|
|
isInitialized = false;
|
|
|
|
|
|
}
|
2026-01-06 04:07:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-06 05:22:10 +01:00
|
|
|
|
public void Hide()
|
2026-01-06 04:07:34 +01:00
|
|
|
|
{
|
2026-01-06 05:50:51 +01:00
|
|
|
|
hasContent = false;
|
2026-01-06 05:22:10 +01:00
|
|
|
|
if (displayObj != null && displayObj.activeSelf) displayObj.SetActive(false);
|
|
|
|
|
|
}
|
2026-01-06 04:07:34 +01:00
|
|
|
|
|
2026-01-06 16:15:35 +01:00
|
|
|
|
public void ShowIcon(Sprite s, Texture2D raw = null)
|
2026-01-06 05:22:10 +01:00
|
|
|
|
{
|
|
|
|
|
|
if (!isInitialized) Initialize();
|
|
|
|
|
|
if (!isInitialized) return;
|
2026-01-06 04:07:34 +01:00
|
|
|
|
|
2026-01-06 16:15:35 +01:00
|
|
|
|
// Guardamos la referencia raw para el debug
|
|
|
|
|
|
_rawTexture = raw;
|
|
|
|
|
|
_defaultSprite = s; // Guardamos el sprite base
|
|
|
|
|
|
|
2026-01-06 05:22:10 +01:00
|
|
|
|
// Aseguramos orden de dibujado (Encima de todo)
|
|
|
|
|
|
displayObj.transform.SetAsLastSibling();
|
|
|
|
|
|
|
|
|
|
|
|
if (s != null)
|
2026-01-06 04:07:34 +01:00
|
|
|
|
{
|
2026-01-06 16:15:35 +01:00
|
|
|
|
// Solo sobreescribimos visualmente si NO estamos en modo debug
|
|
|
|
|
|
if (!DebugMode)
|
|
|
|
|
|
{
|
|
|
|
|
|
iconImage.sprite = s;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-06 05:22:10 +01:00
|
|
|
|
iconImage.enabled = true;
|
|
|
|
|
|
if (debugText != null) debugText.text = "";
|
2026-01-06 05:50:51 +01:00
|
|
|
|
hasContent = true;
|
2026-01-06 04:07:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-06 05:22:10 +01:00
|
|
|
|
|
|
|
|
|
|
public void ShowText(string t)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!isInitialized) Initialize();
|
|
|
|
|
|
if (!isInitialized) return;
|
|
|
|
|
|
|
|
|
|
|
|
displayObj.transform.SetAsLastSibling();
|
|
|
|
|
|
|
|
|
|
|
|
if (iconImage != null) iconImage.enabled = false;
|
|
|
|
|
|
if (debugText != null) debugText.text = t;
|
2026-01-06 05:50:51 +01:00
|
|
|
|
hasContent = true;
|
2026-01-06 05:22:10 +01:00
|
|
|
|
}
|
2026-01-06 04:07:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|