2020-06-15 22:39:05 +00:00
|
|
|
using System;
|
2020-06-19 08:01:46 +00:00
|
|
|
using System.Collections;
|
2020-07-24 21:39:35 +00:00
|
|
|
using System.Collections.Generic;
|
2020-06-15 22:39:05 +00:00
|
|
|
using TMPro;
|
|
|
|
using UnityEngine;
|
2020-06-19 08:01:46 +00:00
|
|
|
using UnityEngine.Rendering;
|
|
|
|
|
|
|
|
namespace ConformalDecals.Text {
|
2020-07-24 21:39:35 +00:00
|
|
|
[KSPAddon(KSPAddon.Startup.Instantly, true)]
|
2020-06-19 08:01:46 +00:00
|
|
|
public class TextRenderer : MonoBehaviour {
|
|
|
|
public static TextRenderer Instance {
|
|
|
|
get {
|
|
|
|
if (!_instance._isSetup) {
|
|
|
|
_instance.Setup();
|
|
|
|
}
|
2020-06-15 22:39:05 +00:00
|
|
|
|
2020-06-19 08:01:46 +00:00
|
|
|
return _instance;
|
|
|
|
}
|
2020-06-15 22:39:05 +00:00
|
|
|
}
|
|
|
|
|
2020-07-24 21:39:35 +00:00
|
|
|
public const TextureFormat TextTextureFormat = TextureFormat.RG16;
|
2020-06-19 08:01:46 +00:00
|
|
|
public const RenderTextureFormat TextRenderTextureFormat = RenderTextureFormat.R8;
|
2020-06-15 22:39:05 +00:00
|
|
|
|
2020-07-24 21:39:35 +00:00
|
|
|
private const string BlitShader = "ConformalDecals/Text Blit";
|
2020-06-19 08:01:46 +00:00
|
|
|
private const int MaxTextureSize = 4096;
|
2020-07-24 21:39:35 +00:00
|
|
|
private const float FontSize = 100;
|
|
|
|
private const float PixelDensity = 5;
|
2020-06-15 22:39:05 +00:00
|
|
|
|
2020-06-19 08:01:46 +00:00
|
|
|
private static TextRenderer _instance;
|
2020-06-15 22:39:05 +00:00
|
|
|
|
2020-06-19 08:01:46 +00:00
|
|
|
private bool _isSetup;
|
|
|
|
private TextMeshPro _tmp;
|
|
|
|
private Material _blitMaterial;
|
2020-06-15 22:39:05 +00:00
|
|
|
|
2020-07-24 21:39:35 +00:00
|
|
|
private Dictionary<DecalText, RenderedText> _renderedTextures = new Dictionary<DecalText, RenderedText>();
|
|
|
|
private Texture2D _lastTexture; // to reduce the number of Texture2D objects created and destroyed, keep the last one on hand
|
|
|
|
|
2020-06-19 08:01:46 +00:00
|
|
|
private void Start() {
|
2020-07-24 21:39:35 +00:00
|
|
|
if (_instance != null) {
|
2020-06-19 08:01:46 +00:00
|
|
|
Debug.Log("[ConformalDecals] Duplicate TextRenderer created???");
|
|
|
|
}
|
2020-06-15 22:39:05 +00:00
|
|
|
|
2020-06-19 08:01:46 +00:00
|
|
|
Debug.Log("[ConformalDecals] Creating TextRenderer Object");
|
|
|
|
_instance = this;
|
|
|
|
DontDestroyOnLoad(gameObject);
|
|
|
|
}
|
2020-06-15 22:39:05 +00:00
|
|
|
|
2020-07-24 21:39:35 +00:00
|
|
|
private void Setup() {
|
2020-06-19 08:01:46 +00:00
|
|
|
if (_isSetup) return;
|
2020-06-15 22:39:05 +00:00
|
|
|
|
2020-06-19 08:01:46 +00:00
|
|
|
Debug.Log("[ConformalDecals] Setting Up TextRenderer Object");
|
2020-06-15 22:39:05 +00:00
|
|
|
|
2020-06-19 08:01:46 +00:00
|
|
|
_tmp = gameObject.AddComponent<TextMeshPro>();
|
|
|
|
_tmp.renderer.enabled = false; // dont automatically render
|
2020-06-15 22:39:05 +00:00
|
|
|
|
2020-07-24 21:39:35 +00:00
|
|
|
var shader = Shabby.Shabby.FindShader(BlitShader);
|
|
|
|
if (shader == null) Debug.LogError($"[ConformalDecals] could not find text blit shader named '{shader}'");
|
|
|
|
_blitMaterial = new Material(Shabby.Shabby.FindShader(BlitShader));
|
2020-06-15 22:39:05 +00:00
|
|
|
|
2020-06-19 08:01:46 +00:00
|
|
|
_isSetup = true;
|
2020-07-24 21:39:35 +00:00
|
|
|
}
|
2020-06-15 22:39:05 +00:00
|
|
|
|
2020-07-24 21:39:35 +00:00
|
|
|
public void RenderText(DecalText text, out Texture2D texture, out Rect window) {
|
2020-07-25 07:47:36 +00:00
|
|
|
// SETUP TMP OBJECT FOR RENDERING
|
2020-07-24 21:39:35 +00:00
|
|
|
_tmp.text = text.FormattedText;
|
|
|
|
_tmp.font = text.Font.fontAsset;
|
|
|
|
_tmp.fontStyle = text.Style.FontStyle | text.Font.fontStyle;
|
|
|
|
_tmp.lineSpacing = text.Style.LineSpacing;
|
|
|
|
_tmp.characterSpacing = text.Style.CharacterSpacing;
|
|
|
|
|
2020-07-25 07:47:36 +00:00
|
|
|
_tmp.extraPadding = true;
|
2020-07-24 21:39:35 +00:00
|
|
|
_tmp.enableKerning = true;
|
|
|
|
_tmp.enableWordWrapping = false;
|
|
|
|
_tmp.overflowMode = TextOverflowModes.Overflow;
|
|
|
|
_tmp.alignment = TextAlignmentOptions.Center | TextAlignmentOptions.Baseline;
|
|
|
|
_tmp.fontSize = FontSize;
|
|
|
|
|
2020-07-25 07:47:36 +00:00
|
|
|
// SETUP BLIT MATERIAL
|
2020-07-24 21:39:35 +00:00
|
|
|
_blitMaterial.SetTexture(PropertyIDs._MainTex, text.Font.fontAsset.atlas);
|
|
|
|
|
2020-07-25 07:47:36 +00:00
|
|
|
// GENERATE MESH
|
2020-07-24 21:39:35 +00:00
|
|
|
_tmp.ForceMeshUpdate();
|
|
|
|
var mesh = _tmp.mesh;
|
|
|
|
mesh.RecalculateBounds();
|
|
|
|
var bounds = mesh.bounds;
|
|
|
|
|
2020-07-25 07:47:36 +00:00
|
|
|
// CALCULATE SIZES
|
2020-07-24 21:39:35 +00:00
|
|
|
var size = bounds.size * PixelDensity;
|
|
|
|
|
|
|
|
var textureSize = new Vector2Int {
|
|
|
|
x = Mathf.NextPowerOfTwo((int) size.x),
|
|
|
|
y = Mathf.NextPowerOfTwo((int) size.y)
|
|
|
|
};
|
|
|
|
|
2020-07-25 07:47:36 +00:00
|
|
|
// make sure texture isnt too big, scale it down if it is
|
|
|
|
// this is just so you dont crash the game by pasting in the entire script of The Bee Movie
|
2020-07-24 21:39:35 +00:00
|
|
|
if (textureSize.x > MaxTextureSize) {
|
|
|
|
textureSize.y /= textureSize.x / MaxTextureSize;
|
2020-07-25 07:47:36 +00:00
|
|
|
textureSize.x = MaxTextureSize;
|
2020-07-24 21:39:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (textureSize.y > MaxTextureSize) {
|
|
|
|
textureSize.x /= textureSize.y / MaxTextureSize;
|
2020-07-25 07:47:36 +00:00
|
|
|
textureSize.y = MaxTextureSize;
|
2020-07-24 21:39:35 +00:00
|
|
|
}
|
|
|
|
|
2020-07-25 07:47:36 +00:00
|
|
|
// scale up everything to fit the texture for maximum usage
|
2020-07-24 21:39:35 +00:00
|
|
|
float sizeRatio = Mathf.Min(textureSize.x / size.x, textureSize.y, size.y);
|
|
|
|
|
2020-07-25 07:47:36 +00:00
|
|
|
// calculate where in the texture the used area actually is
|
2020-07-24 21:39:35 +00:00
|
|
|
window = new Rect {
|
|
|
|
size = size * sizeRatio,
|
|
|
|
center = (Vector2) textureSize / 2
|
|
|
|
};
|
|
|
|
|
2020-07-25 07:47:36 +00:00
|
|
|
// GET TEXTURE
|
2020-07-24 21:39:35 +00:00
|
|
|
if (_lastTexture != null) {
|
|
|
|
texture = _lastTexture;
|
|
|
|
texture.Resize(textureSize.x, textureSize.y, TextTextureFormat, false);
|
|
|
|
_lastTexture = null;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
texture = new Texture2D(textureSize.x, textureSize.y, TextTextureFormat, false);
|
|
|
|
}
|
|
|
|
|
2020-07-25 07:47:36 +00:00
|
|
|
// GENERATE PROJECTION MATRIX
|
|
|
|
var halfSize = (Vector2) textureSize / PixelDensity / 2 / sizeRatio;
|
2020-07-24 21:39:35 +00:00
|
|
|
var matrix = Matrix4x4.Ortho(bounds.center.x - halfSize.x, bounds.center.x + halfSize.x,
|
|
|
|
bounds.center.y - halfSize.y, bounds.center.y + halfSize.y, -1, 1);
|
|
|
|
|
2020-07-25 07:47:36 +00:00
|
|
|
// GET RENDERTEX
|
2020-07-24 21:39:35 +00:00
|
|
|
var renderTex = RenderTexture.GetTemporary(textureSize.x, textureSize.y, 0, TextRenderTextureFormat, RenderTextureReadWrite.Linear, 1);
|
|
|
|
renderTex.autoGenerateMips = false;
|
|
|
|
|
2020-07-25 07:47:36 +00:00
|
|
|
// RENDER
|
2020-07-24 21:39:35 +00:00
|
|
|
Graphics.SetRenderTarget(renderTex);
|
|
|
|
GL.PushMatrix();
|
|
|
|
GL.LoadProjectionMatrix(matrix);
|
|
|
|
_blitMaterial.SetPass(0);
|
|
|
|
Graphics.DrawMeshNow(mesh, Matrix4x4.identity);
|
|
|
|
GL.PopMatrix();
|
|
|
|
|
2020-07-25 07:47:36 +00:00
|
|
|
// COPY TEXTURE BACK INTO RAM
|
2020-07-24 21:39:35 +00:00
|
|
|
RenderTexture.active = renderTex;
|
|
|
|
texture.ReadPixels(new Rect(0, 0, textureSize.x, textureSize.y), 0, 0, false);
|
|
|
|
texture.Apply();
|
|
|
|
|
2020-07-25 07:47:36 +00:00
|
|
|
// RELEASE RENDERTEX
|
2020-07-24 21:39:35 +00:00
|
|
|
RenderTexture.ReleaseTemporary(renderTex);
|
2020-06-19 08:01:46 +00:00
|
|
|
}
|
2020-06-15 22:39:05 +00:00
|
|
|
}
|
|
|
|
}
|