Merge branch 'main' into release

hotfix 0.2.7
Andrew Cassidy 3 years ago
commit 938babb41b

@ -30,6 +30,8 @@ public class TextRenderTest : MonoBehaviour {
Debug.Log("starting..."); Debug.Log("starting...");
StartCoroutine(OnRender()); StartCoroutine(OnRender());
var thing = new GameObject();
thing.AddComponent<TextMeshPro>();
} }
// Update is called once per frame // Update is called once per frame

@ -6,14 +6,14 @@
{ {
"MAJOR":0, "MAJOR":0,
"MINOR":2, "MINOR":2,
"PATCH":6, "PATCH":7,
"BUILD":1 "BUILD":0
}, },
"KSP_VERSION": "KSP_VERSION":
{ {
"MAJOR":1, "MAJOR":1,
"MINOR":10, "MINOR":11,
"PATCH":1 "PATCH":0
}, },
"KSP_VERSION_MIN":{ "KSP_VERSION_MIN":{
"MAJOR":1, "MAJOR":1,
@ -22,7 +22,7 @@
}, },
"KSP_VERSION_MAX":{ "KSP_VERSION_MAX":{
"MAJOR":1, "MAJOR":1,
"MINOR":10, "MINOR":11,
"PATCH":99 "PATCH":99
} }
} }

@ -1,5 +1,5 @@
# Conformal Decals v0.2.6 # Conformal Decals v0.2.7
[![Build Status](https://travis-ci.org/drewcassidy/KSP-Conformal-Decals.svg?branch=release)](https://travis-ci.org/drewcassidy/KSP-Conformal-Decals) [![Art: CC BY-SA 4.0](https://img.shields.io/badge/Art%20License-CC%20BY--SA%204.0-orange.svg)](https://creativecommons.org/licenses/by-sa/4.0/) [![Code: GPL v3](https://img.shields.io/badge/Code%20License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![Build Status](https://travis-ci.com/drewcassidy/KSP-Conformal-Decals.svg?branch=release)](https://travis-ci.com/drewcassidy/KSP-Conformal-Decals) [![Art: CC BY-SA 4.0](https://img.shields.io/badge/Art%20License-CC%20BY--SA%204.0-orange.svg)](https://creativecommons.org/licenses/by-sa/4.0/) [![Code: GPL v3](https://img.shields.io/badge/Code%20License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
![Screenshot](http://pileof.rocks/KSP/images/ConformalDecalsHeader.png) ![Screenshot](http://pileof.rocks/KSP/images/ConformalDecalsHeader.png)

@ -5,6 +5,7 @@
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<PlatformTarget>x64</PlatformTarget> <PlatformTarget>x64</PlatformTarget>
<NoWarn>1701;1702;CS0649;CS1591</NoWarn> <NoWarn>1701;1702;CS0649;CS1591</NoWarn>
<AssemblyVersion>0.2.7</AssemblyVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -35,19 +36,19 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="dlls\**"/> <Compile Remove="dlls\**" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Remove="dlls\**"/> <EmbeddedResource Remove="dlls\**" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove="dlls\**"/> <None Remove="dlls\**" />
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="/bin/cp -v '$(OutDir)ConformalDecals.dll' '$(SolutionDir)../GameData/ConformalDecals/Plugins'" IgnoreExitCode="true"/> <Exec Command="/bin/cp -v '$(OutDir)ConformalDecals.dll' '$(SolutionDir)../GameData/ConformalDecals/Plugins'" IgnoreExitCode="true" />
<!--Fuck you MSBuild stop trying to run CMD.exe on macOS--> <!--Fuck you MSBuild stop trying to run CMD.exe on macOS-->
</Target> </Target>

@ -89,7 +89,6 @@ namespace ConformalDecals {
private MaterialColorProperty _outlineColorProperty; private MaterialColorProperty _outlineColorProperty;
private MaterialFloatProperty _outlineWidthProperty; private MaterialFloatProperty _outlineWidthProperty;
private TextRenderJob _currentJob;
private DecalText _currentText; private DecalText _currentText;
public override void OnLoad(ConfigNode node) { public override void OnLoad(ConfigNode node) {
@ -253,7 +252,6 @@ namespace ConformalDecals {
decal.charSpacing = charSpacing; decal.charSpacing = charSpacing;
decal.lineSpacing = lineSpacing; decal.lineSpacing = lineSpacing;
decal._currentJob = _currentJob;
decal._currentText = _currentText; decal._currentText = _currentText;
decal.UpdateText(); decal.UpdateText();
} }
@ -267,7 +265,7 @@ namespace ConformalDecals {
private void UpdateText() { private void UpdateText() {
// Render text // Render text
var newText = new DecalText(text, font, style, vertical, lineSpacing, charSpacing); var newText = new DecalText(text, font, style, vertical, lineSpacing, charSpacing);
var output = TextRenderer.UpdateTextNow(_currentText, newText); var output = TextRenderer.UpdateText(_currentText, newText);
_currentText = newText; _currentText = newText;
UpdateTexture(output); UpdateTexture(output);

@ -1 +1 @@
[assembly: KSPAssembly("ConformalDecals", 0, 2, 6)] [assembly: KSPAssembly("ConformalDecals", 0, 2)]

@ -105,5 +105,9 @@ namespace ConformalDecals.Text {
public void OnBeforeSerialize() { } public void OnBeforeSerialize() { }
public void OnAfterDeserialize() { } public void OnAfterDeserialize() { }
public override string ToString() {
return _title;
}
} }
} }

@ -86,5 +86,9 @@ namespace ConformalDecals.Text {
public static bool operator !=(DecalText left, DecalText right) { public static bool operator !=(DecalText left, DecalText right) {
return !Equals(left, right); return !Equals(left, right);
} }
public override string ToString() {
return $"{nameof(_text)}: {_text}, {nameof(_font)}: {_font}, {nameof(_style)}: {_style}, {nameof(_vertical)}: {_vertical}, {nameof(_lineSpacing)}: {_lineSpacing}, {nameof(_charSpacing)}: {_charSpacing}";
}
} }
} }

@ -1,35 +0,0 @@
using System;
using UnityEngine.Events;
namespace ConformalDecals.Text {
public class TextRenderJob {
public DecalText OldText { get; }
public DecalText NewText { get; }
public bool Needed { get; private set; }
public bool IsStarted { get; private set; }
public bool IsDone { get; private set; }
public readonly TextRenderer.TextRenderEvent onRenderFinished = new TextRenderer.TextRenderEvent();
public TextRenderJob(DecalText oldText, DecalText newText, UnityAction<TextRenderOutput> renderFinishedCallback) {
OldText = oldText;
NewText = newText ?? throw new ArgumentNullException(nameof(newText));
Needed = true;
if (renderFinishedCallback != null) onRenderFinished.AddListener(renderFinishedCallback);
}
public void Cancel() {
Needed = false;
}
public void Start() {
IsStarted = true;
}
public void Finish(TextRenderOutput output) {
IsDone = true;
onRenderFinished.Invoke(output);
}
}
}

@ -9,7 +9,7 @@ namespace ConformalDecals.Text {
/// The rectangle that the rendered text takes up within the texture /// The rectangle that the rendered text takes up within the texture
public Rect Window { get; private set; } 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 /// The number of users for this render output. If 0, it can be discarded from the cache
public int UserCount { get; set; } public int UserCount { get; set; }
public TextRenderOutput(Texture2D texture, Rect window) { public TextRenderOutput(Texture2D texture, Rect window) {

@ -3,16 +3,12 @@ using System.Collections.Generic;
using ConformalDecals.Util; using ConformalDecals.Util;
using TMPro; using TMPro;
using UnityEngine; using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering; using UnityEngine.Rendering;
using Object = UnityEngine.Object;
namespace ConformalDecals.Text { namespace ConformalDecals.Text {
// TODO: Testing shows the job system is unnecessary, so remove job system code.
/// Class handing text rendering. /// Class handing text rendering.
/// Is a singleton referencing a single gameobject in the scene which contains the TextMeshPro component public static class TextRenderer {
[KSPAddon(KSPAddon.Startup.Instantly, true)]
public class TextRenderer : MonoBehaviour {
/// Texture format used for returned textures. /// Texture format used for returned textures.
/// Unfortunately due to how Unity textures work, this cannot be R8 or Alpha8, /// Unfortunately due to how Unity textures work, this cannot be R8 or Alpha8,
/// so theres always a superfluous green channel using memory /// so theres always a superfluous green channel using memory
@ -22,163 +18,73 @@ namespace ConformalDecals.Text {
/// Overriden below to be ARGB32 on DirectX because DirectX is dumb /// Overriden below to be ARGB32 on DirectX because DirectX is dumb
public static RenderTextureFormat textRenderTextureFormat = RenderTextureFormat.R8; public static 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) {
_instance.Setup();
}
return _instance;
}
}
/// Text Render unityevent, used with the job system to signal render completion
[Serializable]
public class TextRenderEvent : UnityEvent<TextRenderOutput> { }
private const string ShaderName = "ConformalDecals/Text Blit"; private const string ShaderName = "ConformalDecals/Text Blit";
private const int MaxTextureSize = 4096; private const int MaxTextureSize = 4096;
private const float FontSize = 100; private const float FontSize = 100;
private const float PixelDensity = 5; private const float PixelDensity = 5;
private static TextRenderer _instance; private static Shader _blitShader;
private static Texture2D _blankTexture;
private bool _isSetup;
private TextMeshPro _tmp;
private Shader _blitShader;
private static readonly Dictionary<DecalText, TextRenderOutput> RenderCache = new Dictionary<DecalText, TextRenderOutput>(); private static readonly Dictionary<DecalText, TextRenderOutput> RenderCache = new Dictionary<DecalText, TextRenderOutput>();
private static readonly Queue<TextRenderJob> RenderJobs = new Queue<TextRenderJob>();
/// Update text using the job queue /// Update text immediately without using job queue
public static TextRenderJob UpdateText(DecalText oldText, DecalText newText, UnityAction<TextRenderOutput> renderFinishedCallback) { public static TextRenderOutput UpdateText(DecalText oldText, DecalText newText) {
if (newText == null) throw new ArgumentNullException(nameof(newText)); if (newText == null) throw new ArgumentNullException(nameof(newText));
var job = new TextRenderJob(oldText, newText, renderFinishedCallback); if (!(oldText is null)) UnregisterText(oldText);
RenderJobs.Enqueue(job);
return job;
}
/// Update text immediately without using job queue // now that all old references are handled, begin rendering the new output
public static TextRenderOutput UpdateTextNow(DecalText oldText, DecalText newText) { if (!RenderCache.TryGetValue(newText, out var renderOutput)) {
if (newText == null) throw new ArgumentNullException(nameof(newText)); renderOutput = RenderText(newText);
RenderCache.Add(newText, renderOutput);
}
return Instance.RunJob(new TextRenderJob(oldText, newText, null), out _); renderOutput.UserCount++;
return renderOutput;
} }
/// Unregister a user of a piece of text /// Unregister a user of a piece of text
public static void UnregisterText(DecalText text) { public static void UnregisterText(DecalText text) {
if (text == null) throw new ArgumentNullException(nameof(text));
if (RenderCache.TryGetValue(text, out var renderedText)) { if (RenderCache.TryGetValue(text, out var renderedText)) {
renderedText.UserCount--; renderedText.UserCount--;
if (renderedText.UserCount <= 0) { if (renderedText.UserCount <= 0) {
RenderCache.Remove(text); RenderCache.Remove(text);
Destroy(renderedText.Texture); var texture = renderedText.Texture;
if (texture != _blankTexture) Object.Destroy(texture);
} }
} }
} }
private void Start() {
if (_instance != null) {
Logging.LogError("Duplicate TextRenderer created???");
}
Logging.Log("Creating TextRenderer Object");
_instance = this;
DontDestroyOnLoad(gameObject);
if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D11 || SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D12) {
textRenderTextureFormat = RenderTextureFormat.ARGB32; // DirectX is dumb
}
if (!SystemInfo.SupportsTextureFormat(textTextureFormat)) {
Logging.LogError($"Text texture format {textTextureFormat} not supported on this platform.");
}
if (!SystemInfo.SupportsRenderTextureFormat(textRenderTextureFormat)) {
Logging.LogError($"Text texture format {textRenderTextureFormat} not supported on this platform.");
}
}
/// Setup this text renderer instance for rendering
private void Setup() {
if (_isSetup) return;
Logging.Log("Setting Up TextRenderer Object");
_tmp = gameObject.AddComponent<TextMeshPro>();
_tmp.renderer.enabled = false; // dont automatically render
_blitShader = Shabby.Shabby.FindShader(ShaderName);
if (_blitShader == null) Logging.LogError($"Could not find text blit shader named '{ShaderName}'");
_isSetup = true;
}
/// Run a text render job
private TextRenderOutput RunJob(TextRenderJob job, out bool renderNeeded) {
if (!job.Needed) {
renderNeeded = false;
return null;
}
job.Start();
Texture2D texture = null;
if (job.OldText != null && RenderCache.TryGetValue(job.OldText, out var oldRender)) {
// old output still exists
oldRender.UserCount--;
if (oldRender.UserCount <= 0) {
// this is the only usage of this output, so we are free to re-render into the texture
texture = oldRender.Texture;
RenderCache.Remove(job.OldText);
}
}
// now that all old references are handled, begin rendering the new output
if (RenderCache.TryGetValue(job.NewText, out var renderOutput)) {
renderNeeded = false;
}
else {
renderNeeded = true;
renderOutput = RenderText(job.NewText, texture);
RenderCache.Add(job.NewText, renderOutput);
}
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) { public static TextRenderOutput RenderText(DecalText text) {
if (text == null) throw new ArgumentNullException(nameof(text)); if (text == null) throw new ArgumentNullException(nameof(text));
if (_tmp == null) throw new InvalidOperationException("TextMeshPro object not yet created.");
var tmpObject = new GameObject("Text Mesh Pro renderer");
var tmp = tmpObject.AddComponent<TextMeshPro>();
// SETUP TMP OBJECT FOR RENDERING // SETUP TMP OBJECT FOR RENDERING
_tmp.text = text.FormattedText; tmp.text = text.FormattedText;
_tmp.font = text.Font.FontAsset; tmp.font = text.Font.FontAsset;
_tmp.fontStyle = text.Style | text.Font.FontStyle; tmp.fontStyle = text.Style | text.Font.FontStyle;
_tmp.lineSpacing = text.LineSpacing; tmp.lineSpacing = text.LineSpacing;
_tmp.characterSpacing = text.CharSpacing; tmp.characterSpacing = text.CharSpacing;
_tmp.extraPadding = true; tmp.extraPadding = true;
_tmp.enableKerning = true; tmp.enableKerning = true;
_tmp.enableWordWrapping = false; tmp.enableWordWrapping = false;
_tmp.overflowMode = TextOverflowModes.Overflow; tmp.overflowMode = TextOverflowModes.Overflow;
_tmp.alignment = TextAlignmentOptions.Center; tmp.alignment = TextAlignmentOptions.Center;
_tmp.fontSize = FontSize; tmp.fontSize = FontSize;
// GENERATE MESH // GENERATE MESH
_tmp.ClearMesh(false); tmp.ClearMesh(false);
_tmp.ForceMeshUpdate(); tmp.ForceMeshUpdate();
var meshFilters = gameObject.GetComponentsInChildren<MeshFilter>(); var meshFilters = tmpObject.GetComponentsInChildren<MeshFilter>();
var meshes = new Mesh[meshFilters.Length]; var meshes = new Mesh[meshFilters.Length];
var materials = new Material[meshFilters.Length]; var materials = new Material[meshFilters.Length];
@ -189,9 +95,9 @@ namespace ConformalDecals.Text {
var renderer = meshFilters[i].gameObject.GetComponent<MeshRenderer>(); var renderer = meshFilters[i].gameObject.GetComponent<MeshRenderer>();
meshes[i] = meshFilters[i].mesh; meshes[i] = meshFilters[i].mesh;
if (i == 0) meshes[i] = _tmp.mesh; if (i == 0) meshes[i] = tmp.mesh;
materials[i] = Instantiate(renderer.material); materials[i] = Object.Instantiate(renderer.material);
materials[i].shader = _blitShader; materials[i].shader = _blitShader;
if (renderer == null) throw new FormatException($"Object {meshFilters[i].gameObject.name} has filter but no renderer"); if (renderer == null) throw new FormatException($"Object {meshFilters[i].gameObject.name} has filter but no renderer");
@ -209,15 +115,16 @@ namespace ConformalDecals.Text {
var size = bounds.size * PixelDensity; var size = bounds.size * PixelDensity;
size.x = Mathf.Max(size.x, 0.1f); size.x = Mathf.Max(size.x, 0.1f);
size.y = Mathf.Max(size.y, 0.1f); size.y = Mathf.Max(size.y, 0.1f);
var textureSize = new Vector2Int { var textureSize = new Vector2Int {
x = Mathf.NextPowerOfTwo((int) size.x), x = Mathf.NextPowerOfTwo((int) size.x),
y = Mathf.NextPowerOfTwo((int) size.y) y = Mathf.NextPowerOfTwo((int) size.y)
}; };
if (textureSize.x == 0 || textureSize.y == 0) { if (textureSize.x == 0 || textureSize.y == 0) {
Logging.LogWarning("No text present or error in texture size calculation. Aborting."); Logging.LogError("No text present or error in texture size calculation. Aborting.");
return new TextRenderOutput(Texture2D.blackTexture, Rect.zero); Object.Destroy(tmpObject);
return new TextRenderOutput(_blankTexture, Rect.zero);
} }
// make sure texture isnt too big, scale it down if it is // make sure texture isnt too big, scale it down if it is
@ -242,12 +149,7 @@ namespace ConformalDecals.Text {
}; };
// SETUP TEXTURE // SETUP TEXTURE
if (texture == null) { var texture = new Texture2D(textureSize.x, textureSize.y, textTextureFormat, false);
texture = new Texture2D(textureSize.x, textureSize.y, textTextureFormat, true);
}
else if (texture.width != textureSize.x || texture.height != textureSize.y || texture.format != textTextureFormat) {
texture.Resize(textureSize.x, textureSize.y, textTextureFormat, true);
}
// GENERATE PROJECTION MATRIX // GENERATE PROJECTION MATRIX
var halfSize = (Vector2) textureSize / PixelDensity / 2 / sizeRatio; var halfSize = (Vector2) textureSize / PixelDensity / 2 / sizeRatio;
@ -255,7 +157,7 @@ namespace ConformalDecals.Text {
bounds.center.y - halfSize.y, bounds.center.y + halfSize.y, -1, 1); bounds.center.y - halfSize.y, bounds.center.y + halfSize.y, -1, 1);
// GET RENDERTEX // GET RENDERTEX
var renderTex = new RenderTexture(textureSize.x, textureSize.y, 0, textRenderTextureFormat, RenderTextureReadWrite.Linear) {autoGenerateMips = false}; var renderTex = RenderTexture.GetTemporary(textureSize.x, textureSize.y, 0, textRenderTextureFormat, RenderTextureReadWrite.Linear);
// RENDER // RENDER
Graphics.SetRenderTarget(renderTex); Graphics.SetRenderTarget(renderTex);
@ -271,28 +173,42 @@ namespace ConformalDecals.Text {
} }
} }
// COPY TEXTURE BACK INTO RAM // COPY RENDERTEX INTO TEXTURE
var prevRT = RenderTexture.active; var prevRT = RenderTexture.active;
RenderTexture.active = renderTex; RenderTexture.active = renderTex;
texture.ReadPixels(new Rect(0, 0, textureSize.x, textureSize.y), 0, 0, true); texture.ReadPixels(new Rect(0, 0, textureSize.x, textureSize.y), 0, 0, false);
texture.Apply(); texture.Apply(false, true);
RenderTexture.active = prevRT; RenderTexture.active = prevRT;
GL.PopMatrix(); GL.PopMatrix();
// RELEASE RENDERTEX // RELEASE RENDERTEX
renderTex.Release(); RenderTexture.ReleaseTemporary(renderTex);
RenderTexture.Destroy(renderTex);
// CLEAR SUBMESHES // DESTROY THE RENDERER OBJECT
_tmp.text = ""; Object.Destroy(tmpObject);
for (int i = 0; i < transform.childCount; i++) { return new TextRenderOutput(texture, window);
var child = transform.GetChild(i); }
Destroy(child.gameObject);
/// Setup shader and texture
public static void ModuleManagerPostLoad() {
if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D11 || SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D12) {
textRenderTextureFormat = RenderTextureFormat.ARGB32; // DirectX is dumb
} }
return new TextRenderOutput(texture, window); if (!SystemInfo.SupportsTextureFormat(textTextureFormat)) {
Logging.LogError($"Text texture format {textTextureFormat} not supported on this platform.");
}
if (!SystemInfo.SupportsRenderTextureFormat(textRenderTextureFormat)) {
Logging.LogError($"Text texture format {textRenderTextureFormat} not supported on this platform.");
}
_blankTexture = Texture2D.blackTexture;
_blitShader = Shabby.Shabby.FindShader(ShaderName);
if (_blitShader == null) Logging.LogError($"Could not find text blit shader named '{ShaderName}'");
} }
} }
} }

@ -3,7 +3,6 @@ using ConformalDecals.Text;
using ConformalDecals.Util; using ConformalDecals.Util;
using TMPro; using TMPro;
using UnityEngine; using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI; using UnityEngine.UI;
namespace ConformalDecals.UI { namespace ConformalDecals.UI {
@ -35,14 +34,15 @@ namespace ConformalDecals.UI {
private Vector2 _lineSpacingRange; private Vector2 _lineSpacingRange;
private Vector2 _charSpacingRange; private Vector2 _charSpacingRange;
private TMP_InputField _textBoxTMP; private TMP_InputField _textBoxTMP;
private FontMenuController _fontMenu;
private TextUpdateDelegate _onValueChanged; private TextUpdateDelegate _onValueChanged;
private FontMenuController _fontMenu; private static int _lockCounter;
private bool _ignoreUpdates;
private bool _isLocked; private bool _isLocked;
private string _lockString; private string _lockString;
private static int _lockCounter; private bool _ignoreUpdates;
private bool _textUpdated;
public static TextEntryController Create( public static TextEntryController Create(
string text, DecalFont font, FontStyles style, bool vertical, float linespacing, float charspacing, string text, DecalFont font, FontStyles style, bool vertical, float linespacing, float charspacing,
@ -74,7 +74,7 @@ namespace ConformalDecals.UI {
public void SetControlLock(string value = null) { public void SetControlLock(string value = null) {
if (_isLocked) return; if (_isLocked) return;
InputLockManager.SetControlLock(_lockString); InputLockManager.SetControlLock(ControlTypes.EDITOR_UI, _lockString);
_isLocked = true; _isLocked = true;
} }
@ -86,8 +86,7 @@ namespace ConformalDecals.UI {
public void OnTextUpdate(string newText) { public void OnTextUpdate(string newText) {
this._text = newText; this._text = newText;
_textUpdated = true;
OnValueChanged();
} }
public void OnFontMenu() { public void OnFontMenu() {
@ -105,7 +104,7 @@ namespace ConformalDecals.UI {
_textBoxTMP.fontAsset = _font.FontAsset; _textBoxTMP.fontAsset = _font.FontAsset;
UpdateStyleButtons(); UpdateStyleButtons();
OnValueChanged(); _textUpdated = true;
} }
public void OnLineSpacingUpdate(float value) { public void OnLineSpacingUpdate(float value) {
@ -114,7 +113,7 @@ namespace ConformalDecals.UI {
_lineSpacing = Mathf.Lerp(_lineSpacingRange.x, _lineSpacingRange.y, value); _lineSpacing = Mathf.Lerp(_lineSpacingRange.x, _lineSpacingRange.y, value);
UpdateLineSpacing(); UpdateLineSpacing();
OnValueChanged(); _textUpdated = true;
} }
public void OnLineSpacingUpdate(string text) { public void OnLineSpacingUpdate(string text) {
@ -128,7 +127,7 @@ namespace ConformalDecals.UI {
} }
UpdateLineSpacing(); UpdateLineSpacing();
OnValueChanged(); _textUpdated = true;
} }
public void OnCharSpacingUpdate(float value) { public void OnCharSpacingUpdate(float value) {
@ -137,7 +136,7 @@ namespace ConformalDecals.UI {
_charSpacing = Mathf.Lerp(_charSpacingRange.x, _charSpacingRange.y, value); _charSpacing = Mathf.Lerp(_charSpacingRange.x, _charSpacingRange.y, value);
UpdateCharSpacing(); UpdateCharSpacing();
OnValueChanged(); _textUpdated = true;
} }
public void OnCharSpacingUpdate(string text) { public void OnCharSpacingUpdate(string text) {
@ -151,7 +150,7 @@ namespace ConformalDecals.UI {
} }
UpdateCharSpacing(); UpdateCharSpacing();
OnValueChanged(); _textUpdated = true;
} }
public void OnBoldUpdate(bool state) { public void OnBoldUpdate(bool state) {
@ -163,7 +162,7 @@ namespace ConformalDecals.UI {
_style &= ~FontStyles.Bold; _style &= ~FontStyles.Bold;
_textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask; _textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask;
OnValueChanged(); _textUpdated = true;
} }
public void OnItalicUpdate(bool state) { public void OnItalicUpdate(bool state) {
@ -175,7 +174,7 @@ namespace ConformalDecals.UI {
_style &= ~FontStyles.Italic; _style &= ~FontStyles.Italic;
_textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask; _textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask;
OnValueChanged(); _textUpdated = true;
} }
public void OnUnderlineUpdate(bool state) { public void OnUnderlineUpdate(bool state) {
@ -187,7 +186,7 @@ namespace ConformalDecals.UI {
_style &= ~FontStyles.Underline; _style &= ~FontStyles.Underline;
_textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask; _textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask;
OnValueChanged(); _textUpdated = true;
} }
public void OnSmallCapsUpdate(bool state) { public void OnSmallCapsUpdate(bool state) {
@ -199,19 +198,19 @@ namespace ConformalDecals.UI {
_style &= ~FontStyles.SmallCaps; _style &= ~FontStyles.SmallCaps;
_textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask; _textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask;
OnValueChanged(); _textUpdated = true;
} }
public void OnVerticalUpdate(bool state) { public void OnVerticalUpdate(bool state) {
if (_ignoreUpdates) return; if (_ignoreUpdates) return;
_vertical = state; _vertical = state;
OnValueChanged(); _textUpdated = true;
} }
private void Start() { private void Start() {
_lockString = $"ConformalDecals_TextEditor_{_lockCounter++}"; _lockString = $"ConformalDecals_TextEditor_{_lockCounter++}";
_textBoxTMP = ((TMP_InputField) _textBox); _textBoxTMP = ((TMP_InputField) _textBox);
_textBoxTMP.text = _text; _textBoxTMP.text = _text;
_textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask; _textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask;
@ -229,9 +228,12 @@ namespace ConformalDecals.UI {
private void OnDestroy() { private void OnDestroy() {
RemoveControlLock(); RemoveControlLock();
} }
private void OnValueChanged() { private void LateUpdate() {
_onValueChanged(_text, _font, _style, _vertical, _lineSpacing, _charSpacing); if (_textUpdated) {
_onValueChanged(_text, _font, _style, _vertical, _lineSpacing, _charSpacing);
_textUpdated = false;
}
} }
private void UpdateStyleButtons() { private void UpdateStyleButtons() {

@ -1,3 +1,12 @@
v0.2.7
------
- Supported KSP versions: 1.8.x to 1.11.x
- Notes:
- Attaching decal parts in flight using engineer kerbals is not supported.
- Fixes:
- Fixed certain non-ascii strings not rendering correctly under certain circumstances.
- Yet another attempted fix for the planet text glitch.
v0.2.6 v0.2.6
------ ------
- Fixes: - Fixes:

Loading…
Cancel
Save