Files
Cielonos/Assets/OtherPlugins/HUD-Navigation-System/Scripts/Utilities/HNSTextureCreator.cs
2026-04-18 13:57:19 -04:00

347 lines
10 KiB
C#

using System.IO;
using System.Collections;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace SickscoreGames.HUDNavigationSystem
{
#if (UNITY_EDITOR)
[ExecuteInEditMode]
public class HNSTextureCreator : MonoBehaviour
{
#region Variables
public string MapName = "New_Map";
public _TextureSize TextureSize = _TextureSize._2048;
public Color Background = Color.black;
public GameObject FitToObject;
public float ObjectBoundsMultiplier = 1f;
public bool PreviewShowBounds = true;
public Color PreviewBoundsColor = new Color (0f, 0f, 1f, .3f);
[HideInInspector]
public Bounds MapBounds = new Bounds (Vector3.zero, new Vector3 (500f, 100f, 500f));
[HideInInspector]
public Camera RenderCamera;
[HideInInspector]
public RenderTexture CameraRenderTexture;
public bool _isBusy = false;
#endregion
#region Main Methods
[MenuItem("Window/" + HNS.PublisherName + "/" + HNS.Name + "/Map Texture Creator", false, 11)]
public static void InitTextureCreator ()
{
// find / instantiate TextureCreator
HNSTextureCreator textureCreator = HUDNavigationExtensions.FindFirst<HNSTextureCreator> ();
if (textureCreator == null)
textureCreator = new GameObject ("HNS MapTextureCreator").AddComponent<HNSTextureCreator> ();
// set TextureCreator as active gameobject
Selection.activeGameObject = textureCreator.gameObject;
}
protected virtual void OnEnable ()
{
// prevent issues in play mode
if (Application.isPlaying)
DestroyImmediate (this.gameObject);
}
protected virtual void OnDisable ()
{
// destroy preview camera
if (RenderCamera != null)
DestroyImmediate (RenderCamera.gameObject);
// destroy render texture
if (CameraRenderTexture != null)
DestroyImmediate (CameraRenderTexture);
}
public virtual void FitToBounds (GameObject boundsObj)
{
if (boundsObj == null)
return;
// store object's position / scale
Vector3 objPosition = boundsObj.transform.position;
Vector3 objScale = boundsObj.transform.localScale;
// get bounds from object
Terrain terrain = boundsObj.GetComponent<Terrain> ();
if (terrain != null) {
// use terrain size
objPosition += terrain.terrainData.size / 2f;
objScale = terrain.terrainData.size;
} else {
// get mesh renderer
MeshRenderer meshRenderer = boundsObj.GetComponent<MeshRenderer> ();
if (meshRenderer != null) {
// use mesh renderer bounds
objPosition = meshRenderer.bounds.center;
objScale = meshRenderer.bounds.size;
} else {
// throw error if object has no mesh renderer
Debug.LogErrorFormat ("No MeshRenderer found on object '{0}'", boundsObj.name);
return;
}
}
// multiply bounds scale
if (ObjectBoundsMultiplier != 0f)
objScale = new Vector3 (objScale.x * ObjectBoundsMultiplier, objScale.y, objScale.z * ObjectBoundsMultiplier);
// update bounds center/size
MapBounds.center = objPosition;
MapBounds.size = objScale;
}
public virtual void CreateRenderCamera ()
{
// create render camera
if (RenderCamera == null) {
// create camera gameobject
GameObject cameraGO = new GameObject ("HNS MapTextureCreator Camera", typeof(Camera));
cameraGO.transform.rotation = Quaternion.Euler (90f, 0f, 0f);
cameraGO.transform.SetParent (this.transform);
RenderCamera = cameraGO.GetComponent<Camera> ();
}
// setup render camera
RenderCamera.clearFlags = CameraClearFlags.SolidColor;
RenderCamera.backgroundColor = Background;
RenderCamera.orthographic = true;
RenderCamera.depth = -100f;
// update orthographic size
RenderCamera.orthographicSize = Mathf.Min (MapBounds.size.x, MapBounds.size.z) / 2f;
if (MapBounds.size.x < MapBounds.size.z)
RenderCamera.orthographicSize = Mathf.Max (MapBounds.size.x, MapBounds.size.z) / 2f;
// update camera position
RenderCamera.transform.position = new Vector3 (MapBounds.center.x, MapBounds.max.y + .1f, MapBounds.center.z);
// update clipping planes
RenderCamera.nearClipPlane = .1f;
RenderCamera.farClipPlane = RenderCamera.transform.position.y - MapBounds.min.y + .1f;
// update camera background
RenderCamera.backgroundColor = Background;
// make sure it always has a target texture
if (RenderCamera.targetTexture == null && CameraRenderTexture != null)
RenderCamera.targetTexture = CameraRenderTexture;
}
public virtual void DestroyRenderCamera ()
{
if (RenderCamera == null)
return;
DestroyImmediate (RenderCamera.gameObject);
}
public virtual void UpdateRenderTexture ()
{
// check if we need to update the render texture
Vector2 renderSize = GetTotalTextureSize ();
if (CameraRenderTexture == null || CameraRenderTexture.width != renderSize.x || CameraRenderTexture.height != renderSize.y) {
// release render texture from camera
if (RenderCamera != null && RenderCamera.targetTexture != null)
RenderCamera.targetTexture.Release ();
// create render texture with new dimensions
CameraRenderTexture = new RenderTexture ((int)renderSize.x, (int)renderSize.y, 24, RenderTextureFormat.ARGB32);
// assign new render texture to camera
if (RenderCamera != null)
RenderCamera.targetTexture = CameraRenderTexture;
}
}
public void CreateMapTexture ()
{
_isBusy = true;
StartCoroutine (CreateMapTextureRoutine ());
}
public Vector2 GetTotalTextureSize ()
{
Vector3 intMapBounds = new Vector3 ((int)MapBounds.size.x, (int)MapBounds.size.y, (int)MapBounds.size.z);
int min = Mathf.Min ((int)intMapBounds.x, (int)intMapBounds.z);
int max = Mathf.Max ((int)intMapBounds.x, (int)intMapBounds.z);
int textureSize = (int)TextureSize;
int smallSide = Mathf.RoundToInt (textureSize / ((float)max / (float)min));
Vector2 finalSize = new Vector2 (textureSize, smallSide);
if (intMapBounds.x < intMapBounds.z)
finalSize = new Vector2 (smallSide, textureSize);
return finalSize;
}
public void FixPotDimensions ()
{
if (MapBounds.size.x < MapBounds.size.z)
MapBounds.size = new Vector3 (MapBounds.size.z, MapBounds.size.y, MapBounds.size.z);
else
MapBounds.size = new Vector3 (MapBounds.size.x, MapBounds.size.y, MapBounds.size.x);
}
#endregion
#region Utility Methods
IEnumerator CreateMapTextureRoutine ()
{
// create render camera
CreateRenderCamera ();
// update render texture
UpdateRenderTexture ();
// create map texture
string mapTexturePath = GetTexturePath ();
Vector2 mapTextureSize = GetTotalTextureSize ();
Texture2D mapTexture = new Texture2D ((int)mapTextureSize.x, (int)mapTextureSize.y, TextureFormat.RGB24, false);
// TextureCreator
try {
while (_isBusy) {
// manually render camera view
RenderCamera.Render ();
// set active render texture
RenderTexture.active = CameraRenderTexture;
// read pixels from current tile
mapTexture.ReadPixels (new Rect (Vector2.zero, mapTextureSize), 0, 0);
// apply changes to final texture
mapTexture.Apply ();
// unset active render texture
RenderTexture.active = null;
// write final map texture
byte[] bytes = mapTexture.EncodeToPNG ();
using (Stream stream = File.Create (mapTexturePath))
stream.Write (bytes, 0, bytes.Length);
_isBusy = false;
}
} catch (System.Exception ex) {
Debug.LogException (ex);
yield break;
} finally {
RenderTexture.active = null;
DestroyRenderCamera ();
_isBusy = false;
}
// refresh asset database
AssetDatabase.Refresh ();
string relativeTexturePath = mapTexturePath.Substring (mapTexturePath.IndexOf ("Assets"));
TextureImporter textureImporter = AssetImporter.GetAtPath (relativeTexturePath) as TextureImporter;
if (textureImporter != null) {
// set texture as UI sprite
if (textureImporter.textureType != TextureImporterType.Sprite)
textureImporter.textureType = TextureImporterType.Sprite;
// set sprite mode to single
if (textureImporter.spriteImportMode != SpriteImportMode.Single)
textureImporter.spriteImportMode = SpriteImportMode.Single;
// update texture size
if (textureImporter.maxTextureSize != (int)TextureSize)
textureImporter.maxTextureSize = (int)TextureSize;
// clamp texture
if (textureImporter.wrapMode != TextureWrapMode.Clamp)
textureImporter.wrapMode = TextureWrapMode.Clamp;
// disable POT scaling
if (mapTextureSize.x != mapTextureSize.y && textureImporter.npotScale != TextureImporterNPOTScale.None)
textureImporter.npotScale = TextureImporterNPOTScale.None;
// save changes
textureImporter.SaveAndReimport ();
// create map profile
HNSMapProfileUtilities.CreateProfile (relativeTexturePath, mapTextureSize, Background, MapBounds);
// refresh asset database
AssetDatabase.Refresh ();
} else {
Debug.LogError ("MapTextureCreator couldn't update the texture import settings. Please adjust the texture size manually within the texture import settings.");
}
// finish operation
EditorUtility.DisplayDialog ("HNS MapTextureCreator", string.Format ("Successfully created profile '{0}':\n\n{1}", MapName, mapTexturePath), "OK");
// destroy render camera
DestroyRenderCamera ();
yield return null;
}
string GetTexturePath ()
{
// check for empty filename
if (MapName.Length <= 0)
MapName = "Unnamed";
// check path and create directory
string path = Path.Combine (Application.dataPath, "HNS MapTextureCreator/" + MapName).Replace ('\\', '/');
if (!System.IO.Directory.Exists (path)) {
System.IO.Directory.CreateDirectory (path);
AssetDatabase.Refresh ();
}
// return final path and filename
return string.Format ("{0}/{1}_{2}_Map.png", path, MapName, System.DateTime.Now.ToString ("yyyyMMddHHmmss"));
}
void OnDrawGizmos ()
{
if (Selection.activeGameObject != this.gameObject)
return;
// draw map bounds
if (PreviewShowBounds) {
Gizmos.color = PreviewBoundsColor;
Gizmos.DrawCube (MapBounds.center, MapBounds.size);
}
}
#endregion
#region Subclasses
[System.Serializable]
public enum _TextureSize { _512 = 512, _1024 = 1024, _2048 = 2048, _4096 = 4096, _8192 = 8192 };
#endregion
}
#endif
}