From 1859e51a2e2cd2999a2f5f04dd20f4767f37cbb1 Mon Sep 17 00:00:00 2001 From: drewcassidy Date: Sun, 27 Sep 2020 18:26:55 -0700 Subject: [PATCH] Documentation and cleanup pass --- .../Plugins/ConformalDecals.dll | Bin 86528 -> 82944 bytes Source/ConformalDecals/ConformalDecals.csproj | 1 - Source/ConformalDecals/Text/DecalFont.cs | 11 +- Source/ConformalDecals/Text/DecalText.cs | 4 + Source/ConformalDecals/Text/DecalTextStyle.cs | 11 +- Source/ConformalDecals/Text/FontLoader.cs | 1 + .../ConformalDecals/Text/TextRenderOutput.cs | 6 +- Source/ConformalDecals/Text/TextRenderer.cs | 33 ++- Source/ConformalDecals/Util/TextureUtils.cs | 263 ------------------ 9 files changed, 47 insertions(+), 283 deletions(-) delete mode 100644 Source/ConformalDecals/Util/TextureUtils.cs diff --git a/GameData/ConformalDecals/Plugins/ConformalDecals.dll b/GameData/ConformalDecals/Plugins/ConformalDecals.dll index e18268079aa3509cbb4110963de83da78939dc41..2db784f835ea130b107918d33e8a66e2576d1dd4 100644 GIT binary patch delta 35959 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 D9a+>c diff --git a/Source/ConformalDecals/ConformalDecals.csproj b/Source/ConformalDecals/ConformalDecals.csproj index 7def1b9..6d11eb6 100644 --- a/Source/ConformalDecals/ConformalDecals.csproj +++ b/Source/ConformalDecals/ConformalDecals.csproj @@ -100,7 +100,6 @@ - diff --git a/Source/ConformalDecals/Text/DecalFont.cs b/Source/ConformalDecals/Text/DecalFont.cs index 45ec8f7..efa0b6e 100644 --- a/Source/ConformalDecals/Text/DecalFont.cs +++ b/Source/ConformalDecals/Text/DecalFont.cs @@ -6,13 +6,17 @@ using UniLinq; namespace ConformalDecals.Text { public class DecalFont : IEquatable { + /// Human-readable name for the font public string Title { get; } - public TMP_FontAsset FontAsset { get; } - + /// Internal name for the font public string Name => FontAsset.name; + /// The font asset itself + public TMP_FontAsset FontAsset { get; } + /// Styles that are forced on for this font, + /// e.g. smallcaps for a font without lower case characters public FontStyles FontStyle { get; } public bool Bold => (FontStyle & FontStyles.Bold) != 0; @@ -23,7 +27,8 @@ namespace ConformalDecals.Text { public bool SmallCaps => (FontStyle & FontStyles.SmallCaps) != 0; - + /// Styles that are forced off for this font, + /// e.g. underline for a font with no underscore character public FontStyles FontStyleMask { get; } public bool BoldMask => (FontStyleMask & FontStyles.Bold) != 0; diff --git a/Source/ConformalDecals/Text/DecalText.cs b/Source/ConformalDecals/Text/DecalText.cs index 07ff603..c974292 100644 --- a/Source/ConformalDecals/Text/DecalText.cs +++ b/Source/ConformalDecals/Text/DecalText.cs @@ -3,12 +3,16 @@ using System.Text.RegularExpressions; namespace ConformalDecals.Text { public class DecalText : IEquatable { + /// Raw text contents public string Text { get; } + /// Font asset used by this text snippet public DecalFont Font { get; } + /// Style used by this text snippet public DecalTextStyle Style { get; } + /// The text formatted with newlines for vertical text public string FormattedText { get { if (Style.Vertical) { diff --git a/Source/ConformalDecals/Text/DecalTextStyle.cs b/Source/ConformalDecals/Text/DecalTextStyle.cs index 528c995..ac55fc3 100644 --- a/Source/ConformalDecals/Text/DecalTextStyle.cs +++ b/Source/ConformalDecals/Text/DecalTextStyle.cs @@ -1,14 +1,15 @@ using System; using TMPro; using UnityEngine; + // ReSharper disable NonReadonlyMemberInGetHashCode namespace ConformalDecals.Text { public struct DecalTextStyle : IEquatable { private FontStyles _fontStyle; - private bool _vertical; - private float _lineSpacing; - private float _charSpacing; + private bool _vertical; + private float _lineSpacing; + private float _charSpacing; public FontStyles FontStyle { get => _fontStyle; @@ -61,7 +62,7 @@ namespace ConformalDecals.Text { get => _charSpacing; set => _charSpacing = value; } - + public DecalTextStyle(FontStyles fontStyle, bool vertical, float lineSpacing, float charSpacing) { _fontStyle = fontStyle; _vertical = vertical; @@ -70,7 +71,7 @@ namespace ConformalDecals.Text { } public bool Equals(DecalTextStyle other) { - return FontStyle == other.FontStyle && Vertical == other.Vertical && + return FontStyle == other.FontStyle && Vertical == other.Vertical && Mathf.Approximately(LineSpacing, other.LineSpacing) && Mathf.Approximately(CharSpacing, other.CharSpacing); } diff --git a/Source/ConformalDecals/Text/FontLoader.cs b/Source/ConformalDecals/Text/FontLoader.cs index 76351cb..ddb13e5 100644 --- a/Source/ConformalDecals/Text/FontLoader.cs +++ b/Source/ConformalDecals/Text/FontLoader.cs @@ -6,6 +6,7 @@ using UniLinq; using UnityEngine; namespace ConformalDecals.Text { + /// KSP database loader for KSPFont files which contain TextMeshPro font assets [DatabaseLoaderAttrib(new[] {"kspfont"})] public class FontLoader : DatabaseLoader { private const string FallbackName = "NotoSans-Regular SDF"; diff --git a/Source/ConformalDecals/Text/TextRenderOutput.cs b/Source/ConformalDecals/Text/TextRenderOutput.cs index 035bda5..210e14a 100644 --- a/Source/ConformalDecals/Text/TextRenderOutput.cs +++ b/Source/ConformalDecals/Text/TextRenderOutput.cs @@ -1,11 +1,15 @@ using UnityEngine; namespace ConformalDecals.Text { + /// Texture render output, used for cacheing and is the datastructure returned to the ModuleConformalText class public class TextRenderOutput { + /// Texture with the rendered text public Texture2D Texture { get; private set; } + /// The rectangle that the rendered text takes up within the texture public Rect Window { get; private set; } - + + /// The number of users for this render output. If 0, it can be discarded from the cache and the texture reused public int UserCount { get; set; } public TextRenderOutput(Texture2D texture, Rect window) { diff --git a/Source/ConformalDecals/Text/TextRenderer.cs b/Source/ConformalDecals/Text/TextRenderer.cs index 44d1d62..f7eb319 100644 --- a/Source/ConformalDecals/Text/TextRenderer.cs +++ b/Source/ConformalDecals/Text/TextRenderer.cs @@ -5,11 +5,21 @@ using UnityEngine; using UnityEngine.Events; namespace ConformalDecals.Text { + // TODO: Testing shows the job system is unnecessary, so remove job system code. + + /// Class handing text rendering. + /// Is a singleton referencing a single gameobject in the scene which contains the TextMeshPro component [KSPAddon(KSPAddon.Startup.Instantly, true)] public class TextRenderer : MonoBehaviour { - public const TextureFormat TextTextureFormat = TextureFormat.RG16; + /// Texture format used for returned textures. + /// Unfortunately due to how Unity textures work, this cannot be R8 or Alpha8, + /// so theres always a superfluous green channel using memory + public const TextureFormat TextTextureFormat = TextureFormat.RG16; + + /// Render Texture format used when rendering public const RenderTextureFormat TextRenderTextureFormat = RenderTextureFormat.R8; + /// The text renderer object within the scene which contains the TextMeshPro component used for rendering. public static TextRenderer Instance { get { if (!_instance._isSetup) { @@ -20,6 +30,7 @@ namespace ConformalDecals.Text { } } + /// Text Render unityevent, used with the job system to signal render completion [Serializable] public class TextRenderEvent : UnityEvent { } @@ -37,7 +48,7 @@ namespace ConformalDecals.Text { private static readonly Dictionary RenderCache = new Dictionary(); private static readonly Queue RenderJobs = new Queue(); - // Update text using the job queue + /// Update text using the job queue public static TextRenderJob UpdateText(DecalText oldText, DecalText newText, UnityAction renderFinishedCallback) { if (newText == null) throw new ArgumentNullException(nameof(newText)); @@ -46,14 +57,14 @@ namespace ConformalDecals.Text { return job; } - // Update text immediately without using job queue + /// Update text immediately without using job queue public static TextRenderOutput UpdateTextNow(DecalText oldText, DecalText newText) { if (newText == null) throw new ArgumentNullException(nameof(newText)); return Instance.RunJob(new TextRenderJob(oldText, newText, null), out _); } - // Unregister a user of a piece of text + /// Unregister a user of a piece of text public static void UnregisterText(DecalText text) { Debug.Log($"[ConformalDecals] Unregistering text '{text.Text}'"); if (RenderCache.TryGetValue(text, out var renderedText)) { @@ -75,6 +86,7 @@ namespace ConformalDecals.Text { DontDestroyOnLoad(gameObject); } + /// Setup this text renderer instance for rendering private void Setup() { if (_isSetup) return; @@ -89,7 +101,7 @@ namespace ConformalDecals.Text { _isSetup = true; } - // Run a text render job + /// Run a text render job private TextRenderOutput RunJob(TextRenderJob job, out bool renderNeeded) { if (!job.Needed) { renderNeeded = false; @@ -100,6 +112,7 @@ namespace ConformalDecals.Text { foreach (var cacheitem in RenderCache) { Debug.Log($"[ConformalDecals] Cache item: '{cacheitem.Key.Text}' with {cacheitem.Value.UserCount} users"); } + job.Start(); Texture2D texture = null; @@ -134,16 +147,16 @@ namespace ConformalDecals.Text { } renderOutput.UserCount++; - + job.Finish(renderOutput); return renderOutput; } - // Render a piece of text to a given texture + /// Render a piece of text to a given texture public TextRenderOutput RenderText(DecalText text, Texture2D texture) { if (text == null) throw new ArgumentNullException(nameof(text)); if (_tmp == null) throw new InvalidOperationException("TextMeshPro object not yet created."); - + // SETUP TMP OBJECT FOR RENDERING _tmp.text = text.FormattedText; _tmp.font = text.Font.FontAsset; @@ -171,13 +184,13 @@ namespace ConformalDecals.Text { // SETUP MATERIALS AND BOUNDS for (int i = 0; i < meshFilters.Length; i++) { var renderer = meshFilters[i].gameObject.GetComponent(); - + meshes[i] = meshFilters[i].mesh; if (i == 0) meshes[i] = _tmp.mesh; materials[i] = Instantiate(renderer.material); materials[i].shader = _blitShader; - + if (renderer == null) throw new FormatException($"Object {meshFilters[i].gameObject.name} has filter but no renderer"); if (meshes[i] == null) throw new FormatException($"Object {meshFilters[i].gameObject.name} has a null mesh"); diff --git a/Source/ConformalDecals/Util/TextureUtils.cs b/Source/ConformalDecals/Util/TextureUtils.cs deleted file mode 100644 index f835afe..0000000 --- a/Source/ConformalDecals/Util/TextureUtils.cs +++ /dev/null @@ -1,263 +0,0 @@ -using UnityEngine; - -namespace ConformalDecals.Util { - public static class TextureUtils { - public enum BlitMode { - Set, - Add, - } - - public static Color32 AddColor32(Color32 color1, Color32 color2) { - return new Color32((byte) (color1.r + color2.r), (byte) (color1.g + color2.g), (byte) (color1.b + color2.b), (byte) (color1.a + color2.a)); - } - - public static Color32 AddColor32Clamped(Color32 color1, Color32 color2) { - var r = color1.r + color2.r; - var g = color1.g + color2.g; - var b = color1.b + color2.b; - var a = color1.a + color2.a; - if (r > byte.MaxValue) r = byte.MaxValue; - if (g > byte.MaxValue) g = byte.MaxValue; - if (b > byte.MaxValue) b = byte.MaxValue; - if (a > byte.MaxValue) a = byte.MaxValue; - - return new Color32((byte) r, (byte) g, (byte) b, (byte) a); - } - - public static void ClearTexture(Color32[] colors, Color32 clearColor = default) { - for (var i = 0; i < colors.Length; i++) { - colors[i] = clearColor; - } - } - - public static void BlitRectAlpha( - Texture2D src, Color32[] srcColors, Vector2Int srcPos, - Texture2D dst, Color32[] dstColors, Vector2Int dstPos, - Vector2Int size, BlitMode mode) { - - ClipRect(src, ref srcPos, dst, ref dstPos, ref size); - - if (size.x <= 0 || size.y <= 0) return; - - int srcIndex = srcPos.x + srcPos.y * src.width; - int dstIndex = dstPos.x + dstPos.y * dst.width; - - for (int dy = size.y - 1; dy >= 0; dy--) { - - for (int dx = size.x - 1; dx >= 0; dx--) { - switch (mode) { - case BlitMode.Set: - dstColors[dstIndex + dx].a = srcColors[srcIndex + dx].a; - break; - case BlitMode.Add: - var s = srcColors[srcIndex + dx].a; - var d = dstColors[dstIndex + dx].a; - var sum = s + d; - if (sum > byte.MaxValue) sum = byte.MaxValue; - dstColors[dstIndex + dx].a = (byte) sum; - break; - } - } - - srcIndex += src.width; - dstIndex += dst.width; - } - } - - public static void BlitRect( - Texture2D src, Color32[] srcColors, Vector2Int srcPos, - Texture2D dst, Color32[] dstColors, Vector2Int dstPos, - Vector2Int size, BlitMode mode) { - - ClipRect(src, ref srcPos, dst, ref dstPos, ref size); - - if (size.x <= 0 || size.y <= 0) return; - - int srcIndex = srcPos.x + srcPos.y * src.width; - int dstIndex = dstPos.x + dstPos.y * dst.width; - - for (int dy = 0; dy < size.y; dy++) { - - for (int dx = 0; dx < size.x; dx++) { - switch (mode) { - case BlitMode.Set: - dstColors[dstIndex + dx] = srcColors[srcIndex + dx]; - break; - case BlitMode.Add: - dstColors[dstIndex + dx] = AddColor32Clamped(srcColors[srcIndex + dx], dstColors[dstIndex + dx]); - break; - } - } - - srcIndex += src.width; - dstIndex += dst.width; - } - } - - public static void BlitRectBilinearAlpha( - Texture2D src, Vector2Int srcPos, Vector2 srcSize, - Texture2D dst, Color32[] dstColors, Vector2Int dstPos, Vector2Int dstSize, - BlitMode mode) { - - var sizeRatio = dstSize / srcSize; - - ClipRect(src, ref srcPos, dst, ref dstPos, ref srcSize, ref dstSize); - - if (dstSize.x <= 0 || dstSize.y <= 0) return; - - var srcPixel = new Vector2(1.0f / src.width, 1.0f / src.height); - var srcStart = (srcPos * srcPixel) + (srcPixel / 2); - var srcStep = sizeRatio * srcPixel; - var srcY = srcStart.y; - - int dstIndex = dstPos.x + dstPos.y * dst.width; - for (int dy = 0; - dy < dstSize.y; - dy++) { - var srcX = srcStart.x; - - for (int dx = 0; dx < dstSize.x; dx++) { - switch (mode) { - case BlitMode.Set: - dstColors[dstIndex + dx].a = (byte) (src.GetPixelBilinear(srcX, srcY).a * byte.MaxValue); - break; - case BlitMode.Add: - var s = (byte) (src.GetPixelBilinear(srcX, srcY).a * byte.MaxValue); - var d = dstColors[dstIndex + dx].a; - var sum = s + d; - if (sum > byte.MaxValue) sum = byte.MaxValue; - dstColors[dstIndex + dx].a = (byte) sum; - break; - } - - srcX += srcStep.x; - } - - srcY += srcStep.y; - dstIndex += dst.width; - } - } - - public static void BlitRectBilinear( - Texture2D src, Vector2Int srcPos, Vector2 srcSize, - Texture2D dst, Color32[] dstColors, Vector2Int dstPos, Vector2Int dstSize, - BlitMode mode) { - - var sizeRatio = dstSize / srcSize; - - ClipRect(src, ref srcPos, dst, ref dstPos, ref srcSize, ref dstSize); - - if (dstSize.x <= 0 || dstSize.y <= 0) return; - - var srcPixel = new Vector2(1.0f / src.width, 1.0f / src.height); - var srcStart = (srcPos * srcPixel) + (srcPixel / 2); - var srcStep = sizeRatio * srcPixel; - var srcY = srcStart.y; - - int dstIndex = dstPos.x + dstPos.y * dst.width; - for (int dy = 0; - dy < dstSize.y; - dy++) { - var srcX = srcStart.x; - - for (int dx = 0; dx < dstSize.x; dx++) { - switch (mode) { - case BlitMode.Set: - dstColors[dstIndex + dx] = src.GetPixelBilinear(srcX, srcY); - break; - case BlitMode.Add: - dstColors[dstIndex + dx] = AddColor32Clamped(src.GetPixelBilinear(srcX, srcY), dstColors[dstIndex + dx]); - break; - } - - srcX += srcStep.x; - } - - srcY += srcStep.y; - dstIndex += dst.width; - } - } - - private static void ClipRect(Texture2D src, ref Vector2Int srcPos, Texture2D dst, ref Vector2Int dstPos, ref Vector2Int size) { - if (srcPos.x < 0) { - size.x += srcPos.x; - dstPos.x -= srcPos.x; - srcPos.x = 0; - } - - if (srcPos.y < 0) { - size.y += srcPos.y; - dstPos.y -= srcPos.y; - srcPos.y = 0; - } - - if (dstPos.x < 0) { - size.x += dstPos.x; - srcPos.x -= dstPos.x; - dstPos.x = 0; - } - - if (dstPos.y < 0) { - size.y += dstPos.y; - srcPos.y -= dstPos.y; - dstPos.y = 0; - } - - if (srcPos.x + size.x > src.width) size.x = src.width - srcPos.x; - if (srcPos.y + size.y > src.height) size.y = src.height - srcPos.y; - if (dstPos.x + size.x > dst.width) size.x = dst.width - srcPos.x; - if (dstPos.y + size.y > dst.height) size.y = dst.height - srcPos.y; - } - - private static void ClipRect(Texture2D src, ref Vector2Int srcPos, Texture2D dst, ref Vector2Int dstPos, ref Vector2 srcSize, ref Vector2Int dstSize) { - var sizeRatio = dstSize / srcSize; - if (srcPos.x < 0) { - dstSize.x += (int) (srcPos.x * sizeRatio.x); - dstPos.x -= (int) (srcPos.x * sizeRatio.x); - srcSize.x += srcPos.x; - srcPos.x = 0; - } - - if (srcPos.y < 0) { - dstSize.y += (int) (srcPos.y * sizeRatio.y); - dstPos.y -= (int) (srcPos.y * sizeRatio.y); - srcSize.y += srcPos.y; - srcPos.y = 0; - } - - if (dstPos.x < 0) { - srcSize.x += dstPos.x / sizeRatio.x; - srcPos.x -= (int) (dstPos.x / sizeRatio.x); - dstSize.x += dstPos.x; - dstPos.x = 0; - } - - if (dstPos.y < 0) { - srcSize.y += dstPos.y / sizeRatio.y; - srcPos.y -= (int) (dstPos.y / sizeRatio.y); - dstSize.y += dstPos.y; - dstPos.y = 0; - } - - if (srcPos.x + srcSize.x > src.width) { - srcSize.x = src.width - srcPos.x; - dstSize.x = (int) (srcSize.x * sizeRatio.x); - } - - if (srcPos.y + srcSize.y > src.height) { - srcSize.y = src.height - srcPos.y; - dstSize.y = (int) (srcSize.y * sizeRatio.y); - } - - if (dstPos.x + dstSize.x > dst.width) { - dstSize.x = dst.width - srcPos.x; - srcSize.x = (int) (dstSize.x / sizeRatio.x); - } - - if (dstPos.y + dstSize.y > dst.height) { - dstSize.y = dst.height - srcPos.y; - srcSize.y = (int) (dstSize.y / sizeRatio.y); - } - } - } -} \ No newline at end of file