mirror of
https://github.com/drewcassidy/KSP-Conformal-Decals.git
synced 2024-09-01 18:23:54 +00:00
146 lines
6.0 KiB
C#
146 lines
6.0 KiB
C#
using System;
|
|
using ConformalDecals.Util;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
|
|
namespace ConformalDecals {
|
|
public class TextRenderer {
|
|
private struct GlyphInfo {
|
|
public TMP_Glyph glyph;
|
|
public Vector2Int size;
|
|
public Vector2Int position;
|
|
public int fontIndex;
|
|
public bool needsResample;
|
|
}
|
|
|
|
private struct FontInfo {
|
|
public TMP_FontAsset font;
|
|
public Texture2D fontAtlas;
|
|
public Color32[] fontAtlasColors;
|
|
}
|
|
|
|
public static Texture2D RenderToTexture(TMP_FontAsset font, string text) {
|
|
Debug.Log($"Rendering text: {text}");
|
|
var charArray = text.ToCharArray();
|
|
var glyphInfoArray = new GlyphInfo[charArray.Length];
|
|
var fontInfoArray = new FontInfo[charArray.Length];
|
|
|
|
var baseScale = font.fontInfo.Scale;
|
|
|
|
var padding = (int) font.fontInfo.Padding;
|
|
var ascender = (int) font.fontInfo.Ascender;
|
|
var descender = (int) font.fontInfo.Descender;
|
|
var baseline = (int) baseScale * (descender + padding);
|
|
Debug.Log($"baseline: {baseline}");
|
|
Debug.Log($"ascender: {ascender}");
|
|
Debug.Log($"descender: {descender}");
|
|
Debug.Log($"baseScale: {baseScale}");
|
|
|
|
fontInfoArray[0].font = font;
|
|
|
|
int xAdvance = 0;
|
|
for (var i = 0; i < charArray.Length; i++) {
|
|
|
|
var glyphFont = TMP_FontUtilities.SearchForGlyph(font, charArray[i], out var glyph);
|
|
|
|
if (glyphFont == font) {
|
|
glyphInfoArray[i].fontIndex = 0;
|
|
}
|
|
else {
|
|
for (int f = 1; i < charArray.Length; i++) {
|
|
if (fontInfoArray[f].font == null) {
|
|
fontInfoArray[f].font = glyphFont;
|
|
glyphInfoArray[i].fontIndex = f;
|
|
break;
|
|
}
|
|
|
|
if (fontInfoArray[f].font == glyphFont) {
|
|
glyphInfoArray[i].fontIndex = f;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
Debug.Log($"getting font info for character: '{charArray[i]}'");
|
|
Debug.Log($"character font: {glyphFont.name}");
|
|
|
|
glyphInfoArray[i].glyph = glyph;
|
|
glyphInfoArray[i].needsResample = false;
|
|
|
|
float elementScale = glyph.scale;
|
|
|
|
if (glyphFont == font) {
|
|
if (!Mathf.Approximately(elementScale, 1)) {
|
|
glyphInfoArray[i].needsResample = true;
|
|
}
|
|
|
|
elementScale *= baseScale;
|
|
}
|
|
else {
|
|
var fontScale = glyphFont.fontInfo.Scale / glyphFont.fontInfo.PointSize;
|
|
if (!Mathf.Approximately(fontScale, baseScale)) {
|
|
glyphInfoArray[i].needsResample = true;
|
|
}
|
|
|
|
elementScale *= fontScale;
|
|
}
|
|
|
|
Debug.Log($"character scale: {glyphFont.fontInfo.Scale / glyphFont.fontInfo.PointSize}");
|
|
Debug.Log($"character needs resampling: {glyphInfoArray[i].needsResample}");
|
|
|
|
glyphInfoArray[i].size.x = (int) ((glyph.width + (padding * 2)) * elementScale);
|
|
glyphInfoArray[i].size.y = (int) ((glyph.height + (padding * 2)) * elementScale);
|
|
glyphInfoArray[i].position.x = (int) ((xAdvance + glyph.xOffset - padding) * elementScale);
|
|
glyphInfoArray[i].position.y = (int) ((baseline + glyph.yOffset - padding) * elementScale);
|
|
|
|
Debug.Log($"character size: {glyphInfoArray[i].size}");
|
|
Debug.Log($"character position: {glyphInfoArray[i].position}");
|
|
}
|
|
|
|
// calculate texture bounds
|
|
int xOffset = glyphInfoArray[0].position.x;
|
|
var textureWidth = (glyphInfoArray[charArray.Length - 1].position.x + glyphInfoArray[charArray.Length - 1].size.x) - xOffset;
|
|
var textureHeight = (int) baseScale * (ascender + descender + padding * 2);
|
|
|
|
// ensure texture sizes are powers of 2
|
|
textureWidth = Mathf.NextPowerOfTwo(textureWidth);
|
|
textureHeight = Mathf.NextPowerOfTwo(textureHeight);
|
|
Debug.Log($"texture is {textureWidth} x {textureHeight}");
|
|
|
|
var texture = new Texture2D(textureWidth, textureHeight, TextureFormat.Alpha8, true);
|
|
|
|
var colors = new Color32[textureWidth * textureHeight];
|
|
|
|
for (var i = 0; i < fontInfoArray.Length; i++) {
|
|
if (fontInfoArray[i].font == null) break;
|
|
fontInfoArray[i].fontAtlas = fontInfoArray[i].font.atlas;
|
|
fontInfoArray[i].fontAtlasColors = fontInfoArray[i].fontAtlas.GetPixels32();
|
|
}
|
|
|
|
for (int i = 0; i < charArray.Length; i++) {
|
|
var glyphInfo = glyphInfoArray[i];
|
|
var glyph = glyphInfo.glyph;
|
|
var fontInfo = fontInfoArray[glyphInfo.fontIndex];
|
|
|
|
var srcPos = new Vector2Int((int) glyph.x, (int) glyph.y);
|
|
var dstPos = glyphInfo.position;
|
|
dstPos.x += xOffset;
|
|
var dstSize = glyphInfo.size;
|
|
|
|
Debug.Log($"rendering character number {i}");
|
|
|
|
if (glyphInfo.needsResample) {
|
|
var srcSize = new Vector2(glyph.width, glyph.height);
|
|
TextureUtils.BlitRectBilinearAlpha(fontInfo.fontAtlas, srcPos, srcSize, texture, colors, dstPos, dstSize, TextureUtils.BlitMode.Add);
|
|
}
|
|
else {
|
|
TextureUtils.BlitRectAlpha(fontInfo.fontAtlas, fontInfo.fontAtlasColors, srcPos, texture, colors, dstPos, dstSize, TextureUtils.BlitMode.Add);
|
|
}
|
|
}
|
|
|
|
texture.Apply(true);
|
|
|
|
return texture;
|
|
}
|
|
}
|
|
} |