Fix text decal saving and loading

Closes #25
feature-saving
Andrew Cassidy 3 years ago
parent c6b9812fe3
commit dbbc621181

@ -90,7 +90,6 @@
<Compile Include="Text/FontLoader.cs" /> <Compile Include="Text/FontLoader.cs" />
<Compile Include="Text/TextRenderer.cs" /> <Compile Include="Text/TextRenderer.cs" />
<Compile Include="Text/DecalText.cs" /> <Compile Include="Text/DecalText.cs" />
<Compile Include="Text\DecalTextStyle.cs" />
<Compile Include="Text\TextRenderOutput.cs" /> <Compile Include="Text\TextRenderOutput.cs" />
<Compile Include="Text\TextRenderJob.cs" /> <Compile Include="Text\TextRenderJob.cs" />
<Compile Include="UI/ColorPickerController.cs" /> <Compile Include="UI/ColorPickerController.cs" />

@ -8,27 +8,26 @@ using TMPro;
using UnityEngine; using UnityEngine;
namespace ConformalDecals { namespace ConformalDecals {
public class ModuleConformalText : ModuleConformalDecal, ISerializationCallbackReceiver { public class ModuleConformalText : ModuleConformalDecal {
[KSPField(isPersistant = true)] public string text = "Text";
[KSPField] public Vector2 lineSpacingRange = new Vector2(-50, 50); [KSPField] public Vector2 lineSpacingRange = new Vector2(-50, 50);
[KSPField] public Vector2 charSpacingRange = new Vector2(-50, 50); [KSPField] public Vector2 charSpacingRange = new Vector2(-50, 50);
// serialization-only fields. do not use except in serialization functions [KSPField(isPersistant = true)] public bool vertical;
[KSPField(isPersistant = true)] public string fontName = "Calibri SDF"; [KSPField(isPersistant = true)] public float lineSpacing;
[KSPField(isPersistant = true)] public int style; [KSPField(isPersistant = true)] public float charSpacing;
[KSPField(isPersistant = true)] public bool vertical;
[KSPField(isPersistant = true)] public float lineSpacing; [KSPField] public string text;
[KSPField(isPersistant = true)] public float charSpacing; [KSPField] public DecalFont font;
[KSPField(isPersistant = true)] public string fillColor = "000000FF"; [KSPField] public FontStyles style;
[KSPField(isPersistant = true)] public string outlineColor = "FFFFFFFF"; [KSPField] public Color32 fillColor = Color.black;
[KSPField] public Color32 outlineColor = Color.white;
// KSP TWEAKABLES // KSP TWEAKABLES
[KSPEvent(guiName = "#LOC_ConformalDecals_gui-set-text", guiActive = false, guiActiveEditor = true)] [KSPEvent(guiName = "#LOC_ConformalDecals_gui-set-text", guiActive = false, guiActiveEditor = true)]
public void SetText() { public void SetText() {
if (_textEntryController == null) { if (_textEntryController == null) {
_textEntryController = TextEntryController.Create(_text, _font, _style, lineSpacingRange, charSpacingRange, OnTextUpdate); _textEntryController = TextEntryController.Create(text, font, style, vertical, lineSpacing, charSpacing, lineSpacingRange, charSpacingRange, OnTextUpdate);
} }
else { else {
_textEntryController.Close(); _textEntryController.Close();
@ -46,7 +45,7 @@ namespace ConformalDecals {
guiActive = false, guiActiveEditor = true)] guiActive = false, guiActiveEditor = true)]
public void SetFillColor() { public void SetFillColor() {
if (_fillColorPickerController == null) { if (_fillColorPickerController == null) {
_fillColorPickerController = ColorPickerController.Create(_fillColor, OnFillColorUpdate); _fillColorPickerController = ColorPickerController.Create(fillColor, OnFillColorUpdate);
} }
else { else {
_fillColorPickerController.Close(); _fillColorPickerController.Close();
@ -69,18 +68,13 @@ namespace ConformalDecals {
guiActive = false, guiActiveEditor = true)] guiActive = false, guiActiveEditor = true)]
public void SetOutlineColor() { public void SetOutlineColor() {
if (_outlineColorPickerController == null) { if (_outlineColorPickerController == null) {
_outlineColorPickerController = ColorPickerController.Create(_outlineColor, OnOutlineColorUpdate); _outlineColorPickerController = ColorPickerController.Create(outlineColor, OnOutlineColorUpdate);
} }
else { else {
_outlineColorPickerController.Close(); _outlineColorPickerController.Close();
} }
} }
private string _text;
private DecalTextStyle _style;
private DecalFont _font;
private Color32 _fillColor;
private Color32 _outlineColor;
private TextEntryController _textEntryController; private TextEntryController _textEntryController;
private ColorPickerController _fillColorPickerController; private ColorPickerController _fillColorPickerController;
@ -100,7 +94,12 @@ namespace ConformalDecals {
public override void OnLoad(ConfigNode node) { public override void OnLoad(ConfigNode node) {
base.OnLoad(node); base.OnLoad(node);
OnAfterDeserialize(); text = WebUtility.UrlDecode(ParseUtil.ParseString(node, "text"));
font = DecalConfig.GetFont(ParseUtil.ParseString(node, "font", true, "Calibri SDF"));
int styleInt = 0;
if (ParseUtil.ParseIntIndirect(ref styleInt, node, "style")) style = (FontStyles) styleInt;
if (!ParseUtil.ParseColor32Indirect(ref fillColor, node, "fillColor")) fillColor = Color.magenta;
if (!ParseUtil.ParseColor32Indirect(ref outlineColor, node, "outlineColor")) outlineColor = Color.magenta;
if (HighLogic.LoadedSceneIsGame) { if (HighLogic.LoadedSceneIsGame) {
// For some reason, rendering doesnt work right on the first frame a scene is loaded // For some reason, rendering doesnt work right on the first frame a scene is loaded
@ -114,7 +113,11 @@ namespace ConformalDecals {
} }
public override void OnSave(ConfigNode node) { public override void OnSave(ConfigNode node) {
OnBeforeSerialize(); node.AddValue("text", WebUtility.UrlEncode(text));
node.AddValue("fontName", font.Name);
node.AddValue("style", (int) style);
node.AddValue("fillColor", fillColor.ToHexString());
node.AddValue("outlineColor", outlineColor.ToHexString());
base.OnSave(node); base.OnSave(node);
} }
@ -131,31 +134,34 @@ namespace ConformalDecals {
_outlineWidthProperty = materialProperties.AddOrGetProperty<MaterialFloatProperty>("_OutlineWidth"); _outlineWidthProperty = materialProperties.AddOrGetProperty<MaterialFloatProperty>("_OutlineWidth");
} }
public void OnTextUpdate(string newText, DecalFont newFont, DecalTextStyle newStyle) { public void OnTextUpdate(string newText, DecalFont newFont, FontStyles newStyle, bool newVertical, float newLineSpacing, float newCharSpacing) {
_text = newText; this.text = newText;
_font = newFont; this.font = newFont;
_style = newStyle; this.style = newStyle;
this.vertical = newVertical;
this.lineSpacing = newLineSpacing;
this.charSpacing = newCharSpacing;
UpdateTextRecursive(); UpdateTextRecursive();
} }
public void OnFillColorUpdate(Color rgb, Util.ColorHSV hsv) { public void OnFillColorUpdate(Color rgb, Util.ColorHSV hsv) {
_fillColor = rgb; fillColor = rgb;
UpdateMaterials(); UpdateMaterials();
foreach (var counterpart in part.symmetryCounterparts) { foreach (var counterpart in part.symmetryCounterparts) {
var decal = counterpart.GetComponent<ModuleConformalText>(); var decal = counterpart.GetComponent<ModuleConformalText>();
decal._fillColor = _fillColor; decal.fillColor = fillColor;
decal.UpdateMaterials(); decal.UpdateMaterials();
} }
} }
public void OnOutlineColorUpdate(Color rgb, Util.ColorHSV hsv) { public void OnOutlineColorUpdate(Color rgb, Util.ColorHSV hsv) {
_outlineColor = rgb; outlineColor = rgb;
UpdateMaterials(); UpdateMaterials();
foreach (var counterpart in part.symmetryCounterparts) { foreach (var counterpart in part.symmetryCounterparts) {
var decal = counterpart.GetComponent<ModuleConformalText>(); var decal = counterpart.GetComponent<ModuleConformalText>();
decal._outlineColor = _outlineColor; decal.outlineColor = outlineColor;
decal.UpdateMaterials(); decal.UpdateMaterials();
} }
} }
@ -202,33 +208,6 @@ namespace ConformalDecals {
} }
} }
public void OnBeforeSerialize() {
text = WebUtility.UrlEncode(_text);
fontName = _font.Name;
style = (int) _style.FontStyle;
vertical = _style.Vertical;
lineSpacing = _style.LineSpacing;
charSpacing = _style.CharSpacing;
fillColor = _fillColor.ToHexString();
outlineColor = _outlineColor.ToHexString();
}
public void OnAfterDeserialize() {
_text = WebUtility.UrlDecode(text);
_font = DecalConfig.GetFont(fontName);
_style = new DecalTextStyle((FontStyles) style, vertical, lineSpacing, charSpacing);
if (!ParseUtil.TryParseColor32(fillColor, out _fillColor)) {
Logging.LogWarning($"Improperly formatted color value for fill: '{fillColor}'");
_fillColor = Color.magenta;
}
if (!ParseUtil.TryParseColor32(outlineColor, out _outlineColor)) {
Logging.LogWarning($"Improperly formatted color value for outline: '{outlineColor}'");
_outlineColor = Color.magenta;
}
}
public override void OnDestroy() { public override void OnDestroy() {
if (HighLogic.LoadedSceneIsGame && _currentText != null) TextRenderer.UnregisterText(_currentText); if (HighLogic.LoadedSceneIsGame && _currentText != null) TextRenderer.UnregisterText(_currentText);
@ -249,9 +228,9 @@ namespace ConformalDecals {
foreach (var counterpart in part.symmetryCounterparts) { foreach (var counterpart in part.symmetryCounterparts) {
var decal = counterpart.GetComponent<ModuleConformalText>(); var decal = counterpart.GetComponent<ModuleConformalText>();
decal._text = _text; decal.text = text;
decal._font = _font; decal.font = font;
decal._style = _style; decal.style = style;
decal._currentJob = _currentJob; decal._currentJob = _currentJob;
decal._currentText = _currentText; decal._currentText = _currentText;
@ -266,7 +245,7 @@ namespace ConformalDecals {
private void UpdateText() { private void UpdateText() {
// Render text // Render text
var newText = new DecalText(_text, _font, _style); var newText = new DecalText(text, font, style, vertical, lineSpacing, charSpacing);
var output = TextRenderer.UpdateTextNow(_currentText, newText); var output = TextRenderer.UpdateTextNow(_currentText, newText);
_currentText = newText; _currentText = newText;
@ -288,10 +267,10 @@ namespace ConformalDecals {
protected override void UpdateMaterials() { protected override void UpdateMaterials() {
_fillEnabledProperty.value = fillEnabled; _fillEnabledProperty.value = fillEnabled;
_fillColorProperty.color = _fillColor; _fillColorProperty.color = fillColor;
_outlineEnabledProperty.value = outlineEnabled; _outlineEnabledProperty.value = outlineEnabled;
_outlineColorProperty.color = _outlineColor; _outlineColorProperty.color = outlineColor;
_outlineWidthProperty.value = outlineWidth; _outlineWidthProperty.value = outlineWidth;
base.UpdateMaterials(); base.UpdateMaterials();

@ -3,41 +3,47 @@ using System.Collections.Generic;
using ConformalDecals.Util; using ConformalDecals.Util;
using TMPro; using TMPro;
using UniLinq; using UniLinq;
using UnityEngine;
namespace ConformalDecals.Text { namespace ConformalDecals.Text {
public class DecalFont : IEquatable<DecalFont> { public class DecalFont : ScriptableObject, ISerializationCallbackReceiver, IEquatable<DecalFont> {
[SerializeField] private string _title;
[SerializeField] private TMP_FontAsset _fontAsset;
[SerializeField] private FontStyles _fontStyle;
[SerializeField] private FontStyles _fontStyleMask;
/// Human-readable name for the font /// Human-readable name for the font
public string Title { get; } public string Title => _title;
/// Internal name for the font /// Internal name for the font
public string Name => FontAsset.name; public string Name => _fontAsset.name;
/// The font asset itself /// The font asset itself
public TMP_FontAsset FontAsset { get; } public TMP_FontAsset FontAsset => _fontAsset;
/// Styles that are forced on for this font, /// Styles that are forced on for this font,
/// e.g. smallcaps for a font without lower case characters /// e.g. smallcaps for a font without lower case characters
public FontStyles FontStyle { get; } public FontStyles FontStyle => _fontStyle;
public bool Bold => (FontStyle & FontStyles.Bold) != 0; public bool Bold => (_fontStyle & FontStyles.Bold) != 0;
public bool Italic => (FontStyle & FontStyles.Italic) != 0; public bool Italic => (_fontStyle & FontStyles.Italic) != 0;
public bool Underline => (FontStyle & FontStyles.Underline) != 0; public bool Underline => (_fontStyle & FontStyles.Underline) != 0;
public bool SmallCaps => (FontStyle & FontStyles.SmallCaps) != 0; public bool SmallCaps => (_fontStyle & FontStyles.SmallCaps) != 0;
/// Styles that are forced off for this font, /// Styles that are forced off for this font,
/// e.g. underline for a font with no underscore character /// e.g. underline for a font with no underscore character
public FontStyles FontStyleMask { get; } public FontStyles FontStyleMask => _fontStyleMask;
public bool BoldMask => (FontStyleMask & FontStyles.Bold) != 0; public bool BoldMask => (_fontStyleMask & FontStyles.Bold) != 0;
public bool ItalicMask => (FontStyleMask & FontStyles.Italic) != 0; public bool ItalicMask => (_fontStyleMask & FontStyles.Italic) != 0;
public bool UnderlineMask => (FontStyleMask & FontStyles.Underline) != 0; public bool UnderlineMask => (_fontStyleMask & FontStyles.Underline) != 0;
public bool SmallCapsMask => (FontStyleMask & FontStyles.SmallCaps) != 0; public bool SmallCapsMask => (_fontStyleMask & FontStyles.SmallCaps) != 0;
public DecalFont(ConfigNode node, IEnumerable<TMP_FontAsset> fontAssets) { public DecalFont(ConfigNode node, IEnumerable<TMP_FontAsset> fontAssets) {
@ -45,14 +51,14 @@ namespace ConformalDecals.Text {
if (fontAssets == null) throw new ArgumentNullException(nameof(fontAssets)); if (fontAssets == null) throw new ArgumentNullException(nameof(fontAssets));
var name = ParseUtil.ParseString(node, "name"); var name = ParseUtil.ParseString(node, "name");
FontAsset = fontAssets.First(o => o.name == name); _fontAsset = fontAssets.First(o => o.name == name);
if (FontAsset == null) { if (FontAsset == null) {
throw new FormatException($"Could not find font asset named {name}"); throw new FormatException($"Could not find font asset named {name}");
} }
Title = ParseUtil.ParseString(node, "title", true, name); _title = ParseUtil.ParseString(node, "title", true, name);
FontStyle = (FontStyles) ParseUtil.ParseInt(node, "style", true); _fontStyle = (FontStyles) ParseUtil.ParseInt(node, "style", true);
FontStyleMask = (FontStyles) ParseUtil.ParseInt(node, "styleMask", true); _fontStyleMask = (FontStyles) ParseUtil.ParseInt(node, "styleMask", true);
} }
@ -95,5 +101,9 @@ namespace ConformalDecals.Text {
public static bool operator !=(DecalFont left, DecalFont right) { public static bool operator !=(DecalFont left, DecalFont right) {
return !Equals(left, right); return !Equals(left, right);
} }
public void OnBeforeSerialize() { }
public void OnAfterDeserialize() { }
} }
} }

@ -1,21 +1,38 @@
using System; using System;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using TMPro;
namespace ConformalDecals.Text { namespace ConformalDecals.Text {
public class DecalText : IEquatable<DecalText> { public class DecalText : IEquatable<DecalText> {
private readonly string _text;
private readonly DecalFont _font;
private readonly FontStyles _style;
private readonly bool _vertical;
private readonly float _lineSpacing;
private readonly float _charSpacing;
/// Raw text contents /// Raw text contents
public string Text { get; } public string Text => _text;
/// Font asset used by this text snippet /// Font asset used by this text snippet
public DecalFont Font { get; } public DecalFont Font => _font;
/// Style used by this text snippet /// Style used by this text snippet
public DecalTextStyle Style { get; } public FontStyles Style => _style;
/// If this text snippet is vertical
public bool Vertical => _vertical;
/// The text snippet's line spacing
public float LineSpacing => _lineSpacing;
/// The text snippet's character spacing
public float CharSpacing => _charSpacing;
/// The text formatted with newlines for vertical text /// The text formatted with newlines for vertical text
public string FormattedText { public string FormattedText {
get { get {
if (Style.Vertical) { if (Vertical) {
return Regex.Replace(Text, @"(.)", "$1\n"); return Regex.Replace(Text, @"(.)", "$1\n");
} }
else { else {
@ -24,17 +41,22 @@ namespace ConformalDecals.Text {
} }
} }
public DecalText(string text, DecalFont font, DecalTextStyle style) {
public DecalText(string text, DecalFont font, FontStyles style, bool vertical, float linespacing, float charspacing) {
if (font == null) throw new ArgumentNullException(nameof(font)); if (font == null) throw new ArgumentNullException(nameof(font));
Text = text; _text = text;
Font = font; _font = font;
Style = style; _style = style;
_vertical = vertical;
_lineSpacing = linespacing;
_charSpacing = charspacing;
} }
public bool Equals(DecalText other) { public bool Equals(DecalText other) {
if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true; if (ReferenceEquals(this, other)) return true;
return Text == other.Text && Equals(Font, other.Font) && Style.Equals(other.Style); return _text == other._text && Equals(_font, other._font) && _style == other._style && _vertical == other._vertical && _lineSpacing.Equals(other._lineSpacing) &&
_charSpacing.Equals(other._charSpacing);
} }
public override bool Equals(object obj) { public override bool Equals(object obj) {
@ -46,9 +68,12 @@ namespace ConformalDecals.Text {
public override int GetHashCode() { public override int GetHashCode() {
unchecked { unchecked {
var hashCode = (Text != null ? Text.GetHashCode() : 0); var hashCode = (_text != null ? _text.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (Font != null ? Font.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (_font != null ? _font.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ Style.GetHashCode(); hashCode = (hashCode * 397) ^ (int) _style;
hashCode = (hashCode * 397) ^ _vertical.GetHashCode();
hashCode = (hashCode * 397) ^ _lineSpacing.GetHashCode();
hashCode = (hashCode * 397) ^ _charSpacing.GetHashCode();
return hashCode; return hashCode;
} }
} }

@ -1,101 +0,0 @@
using System;
using TMPro;
using UnityEngine;
// ReSharper disable NonReadonlyMemberInGetHashCode
namespace ConformalDecals.Text {
public struct DecalTextStyle : IEquatable<DecalTextStyle> {
private FontStyles _fontStyle;
private bool _vertical;
private float _lineSpacing;
private float _charSpacing;
public FontStyles FontStyle {
get => _fontStyle;
set => _fontStyle = value;
}
public bool Bold {
get => (FontStyle & FontStyles.Bold) != 0;
set {
if (value) FontStyle |= FontStyles.Bold;
else FontStyle &= ~FontStyles.Bold;
}
}
public bool Italic {
get => (FontStyle & FontStyles.Italic) != 0;
set {
if (value) FontStyle |= FontStyles.Italic;
else FontStyle &= ~FontStyles.Italic;
}
}
public bool Underline {
get => (FontStyle & FontStyles.Underline) != 0;
set {
if (value) FontStyle |= FontStyles.Underline;
else FontStyle &= ~FontStyles.Underline;
}
}
public bool SmallCaps {
get => (FontStyle & FontStyles.SmallCaps) != 0;
set {
if (value) FontStyle |= FontStyles.SmallCaps;
else FontStyle &= ~FontStyles.SmallCaps;
}
}
public bool Vertical {
get => _vertical;
set => _vertical = value;
}
public float LineSpacing {
get => _lineSpacing;
set => _lineSpacing = value;
}
public float CharSpacing {
get => _charSpacing;
set => _charSpacing = value;
}
public DecalTextStyle(FontStyles fontStyle, bool vertical, float lineSpacing, float charSpacing) {
_fontStyle = fontStyle;
_vertical = vertical;
_lineSpacing = lineSpacing;
_charSpacing = charSpacing;
}
public bool Equals(DecalTextStyle other) {
return FontStyle == other.FontStyle && Vertical == other.Vertical &&
Mathf.Approximately(LineSpacing, other.LineSpacing) &&
Mathf.Approximately(CharSpacing, other.CharSpacing);
}
public override bool Equals(object obj) {
return obj is DecalTextStyle other && Equals(other);
}
public override int GetHashCode() {
unchecked {
var hashCode = (int) FontStyle;
hashCode = (hashCode * 397) ^ Vertical.GetHashCode();
hashCode = (hashCode * 397) ^ LineSpacing.GetHashCode();
hashCode = (hashCode * 397) ^ CharSpacing.GetHashCode();
return hashCode;
}
}
public static bool operator ==(DecalTextStyle left, DecalTextStyle right) {
return left.Equals(right);
}
public static bool operator !=(DecalTextStyle left, DecalTextStyle right) {
return !left.Equals(right);
}
}
}

@ -163,9 +163,9 @@ namespace ConformalDecals.Text {
// 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.FontStyle | text.Font.FontStyle; _tmp.fontStyle = text.Style | text.Font.FontStyle;
_tmp.lineSpacing = text.Style.LineSpacing; _tmp.lineSpacing = text.LineSpacing;
_tmp.characterSpacing = text.Style.CharSpacing; _tmp.characterSpacing = text.CharSpacing;
_tmp.extraPadding = true; _tmp.extraPadding = true;
_tmp.enableKerning = true; _tmp.enableKerning = true;

@ -9,9 +9,8 @@ using UnityEngine.UI;
namespace ConformalDecals.UI { namespace ConformalDecals.UI {
public class TextEntryController : MonoBehaviour { public class TextEntryController : MonoBehaviour {
[Serializable] [Serializable]
public class TextUpdateEvent : UnityEvent<string, DecalFont, DecalTextStyle> { } public delegate void TextUpdateDelegate(string newText, DecalFont newFont, FontStyles style, bool vertical, float linespacing, float charspacing);
[SerializeField] public TextUpdateEvent onValueChanged = new TextUpdateEvent();
[SerializeField] private Selectable _textBox; [SerializeField] private Selectable _textBox;
[SerializeField] private Button _fontButton; [SerializeField] private Button _fontButton;
@ -28,21 +27,25 @@ namespace ConformalDecals.UI {
[SerializeField] private Toggle _smallCapsButton; [SerializeField] private Toggle _smallCapsButton;
[SerializeField] private Toggle _verticalButton; [SerializeField] private Toggle _verticalButton;
private string _text; private string _text;
private DecalFont _font; private DecalFont _font;
private DecalTextStyle _style; private FontStyles _style;
private Vector2 _lineSpacingRange; private bool _vertical;
private Vector2 _charSpacingRange; private float _lineSpacing;
private TMP_InputField _textBoxTMP; private float _charSpacing;
private Vector2 _lineSpacingRange;
private Vector2 _charSpacingRange;
private TMP_InputField _textBoxTMP;
private TextUpdateDelegate _onValueChanged;
private FontMenuController _fontMenu; private FontMenuController _fontMenu;
private bool _ignoreUpdates; private bool _ignoreUpdates;
public static TextEntryController Create( public static TextEntryController Create(
string text, DecalFont font, DecalTextStyle style, string text, DecalFont font, FontStyles style, bool vertical, float linespacing, float charspacing,
Vector2 lineSpacingRange, Vector2 charSpacingRange, Vector2 lineSpacingRange, Vector2 charSpacingRange,
UnityAction<string, DecalFont, DecalTextStyle> textUpdateCallback) { TextUpdateDelegate textUpdateCallback) {
var window = Instantiate(UILoader.TextEntryPrefab, MainCanvasUtil.MainCanvas.transform, true); var window = Instantiate(UILoader.TextEntryPrefab, MainCanvasUtil.MainCanvas.transform, true);
window.AddComponent<DragPanel>(); window.AddComponent<DragPanel>();
@ -52,9 +55,12 @@ namespace ConformalDecals.UI {
controller._text = text; controller._text = text;
controller._font = font; controller._font = font;
controller._style = style; controller._style = style;
controller._vertical = vertical;
controller._lineSpacing = linespacing;
controller._charSpacing = charspacing;
controller._lineSpacingRange = lineSpacingRange; controller._lineSpacingRange = lineSpacingRange;
controller._charSpacingRange = charSpacingRange; controller._charSpacingRange = charSpacingRange;
controller.onValueChanged.AddListener(textUpdateCallback); controller._onValueChanged = textUpdateCallback;
return controller; return controller;
} }
@ -81,7 +87,7 @@ namespace ConformalDecals.UI {
font.SetupSample(_fontButton.GetComponentInChildren<TextMeshProUGUI>()); font.SetupSample(_fontButton.GetComponentInChildren<TextMeshProUGUI>());
_textBoxTMP.text = _text; _textBoxTMP.text = _text;
_textBoxTMP.textComponent.fontStyle = _style.FontStyle | _font.FontStyle & ~_font.FontStyleMask; _textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask;
_textBoxTMP.fontAsset = _font.FontAsset; _textBoxTMP.fontAsset = _font.FontAsset;
UpdateStyleButtons(); UpdateStyleButtons();
@ -91,7 +97,7 @@ namespace ConformalDecals.UI {
public void OnLineSpacingUpdate(float value) { public void OnLineSpacingUpdate(float value) {
if (_ignoreUpdates) return; if (_ignoreUpdates) return;
_style.LineSpacing = Mathf.Lerp(_lineSpacingRange.x, _lineSpacingRange.y, value); _lineSpacing = Mathf.Lerp(_lineSpacingRange.x, _lineSpacingRange.y, value);
UpdateLineSpacing(); UpdateLineSpacing();
OnValueChanged(); OnValueChanged();
@ -101,7 +107,7 @@ namespace ConformalDecals.UI {
if (_ignoreUpdates) return; if (_ignoreUpdates) return;
if (float.TryParse(text, out var value)) { if (float.TryParse(text, out var value)) {
_style.LineSpacing = Mathf.Clamp(value, _lineSpacingRange.x, _lineSpacingRange.y); _lineSpacing = Mathf.Clamp(value, _lineSpacingRange.x, _lineSpacingRange.y);
} }
else { else {
Logging.LogWarning("Line spacing value '{text}' could not be parsed."); Logging.LogWarning("Line spacing value '{text}' could not be parsed.");
@ -114,7 +120,7 @@ namespace ConformalDecals.UI {
public void OnCharSpacingUpdate(float value) { public void OnCharSpacingUpdate(float value) {
if (_ignoreUpdates) return; if (_ignoreUpdates) return;
_style.CharSpacing = Mathf.Lerp(_charSpacingRange.x, _charSpacingRange.y, value); _charSpacing = Mathf.Lerp(_charSpacingRange.x, _charSpacingRange.y, value);
UpdateCharSpacing(); UpdateCharSpacing();
OnValueChanged(); OnValueChanged();
@ -124,7 +130,7 @@ namespace ConformalDecals.UI {
if (_ignoreUpdates) return; if (_ignoreUpdates) return;
if (float.TryParse(text, out var value)) { if (float.TryParse(text, out var value)) {
_style.CharSpacing = Mathf.Clamp(value, _charSpacingRange.x, _charSpacingRange.y); _charSpacing = Mathf.Clamp(value, _charSpacingRange.x, _charSpacingRange.y);
} }
else { else {
Logging.LogWarning("Char spacing value '{text}' could not be parsed."); Logging.LogWarning("Char spacing value '{text}' could not be parsed.");
@ -137,39 +143,55 @@ namespace ConformalDecals.UI {
public void OnBoldUpdate(bool state) { public void OnBoldUpdate(bool state) {
if (_ignoreUpdates) return; if (_ignoreUpdates) return;
_style.Bold = state; if (state)
_textBoxTMP.textComponent.fontStyle = _style.FontStyle | _font.FontStyle & ~_font.FontStyleMask; _style |= FontStyles.Bold;
else
_style &= ~FontStyles.Bold;
_textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask;
OnValueChanged(); OnValueChanged();
} }
public void OnItalicUpdate(bool state) { public void OnItalicUpdate(bool state) {
if (_ignoreUpdates) return; if (_ignoreUpdates) return;
_style.Italic = state; if (state)
_textBoxTMP.textComponent.fontStyle = _style.FontStyle | _font.FontStyle & ~_font.FontStyleMask; _style |= FontStyles.Italic;
else
_style &= ~FontStyles.Italic;
_textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask;
OnValueChanged(); OnValueChanged();
} }
public void OnUnderlineUpdate(bool state) { public void OnUnderlineUpdate(bool state) {
if (_ignoreUpdates) return; if (_ignoreUpdates) return;
_style.Underline = state; if (state)
_textBoxTMP.textComponent.fontStyle = _style.FontStyle | _font.FontStyle & ~_font.FontStyleMask; _style |= FontStyles.Underline;
else
_style &= ~FontStyles.Underline;
_textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask;
OnValueChanged(); OnValueChanged();
} }
public void OnSmallCapsUpdate(bool state) { public void OnSmallCapsUpdate(bool state) {
if (_ignoreUpdates) return; if (_ignoreUpdates) return;
_style.SmallCaps = state; if (state)
_textBoxTMP.textComponent.fontStyle = _style.FontStyle | _font.FontStyle & ~_font.FontStyleMask; _style |= FontStyles.SmallCaps;
else
_style &= ~FontStyles.SmallCaps;
_textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask;
OnValueChanged(); OnValueChanged();
} }
public void OnVerticalUpdate(bool state) { public void OnVerticalUpdate(bool state) {
if (_ignoreUpdates) return; if (_ignoreUpdates) return;
_style.Vertical = state; _vertical = state;
OnValueChanged(); OnValueChanged();
} }
@ -177,7 +199,7 @@ namespace ConformalDecals.UI {
private void Start() { private void Start() {
_textBoxTMP = ((TMP_InputField) _textBox); _textBoxTMP = ((TMP_InputField) _textBox);
_textBoxTMP.text = _text; _textBoxTMP.text = _text;
_textBoxTMP.textComponent.fontStyle = _style.FontStyle | _font.FontStyle & ~_font.FontStyleMask; _textBoxTMP.textComponent.fontStyle = _style | _font.FontStyle & ~_font.FontStyleMask;
_textBoxTMP.fontAsset = _font.FontAsset; _textBoxTMP.fontAsset = _font.FontAsset;
_font.SetupSample(_fontButton.GetComponentInChildren<TextMeshProUGUI>()); _font.SetupSample(_fontButton.GetComponentInChildren<TextMeshProUGUI>());
@ -188,7 +210,7 @@ namespace ConformalDecals.UI {
} }
private void OnValueChanged() { private void OnValueChanged() {
onValueChanged.Invoke(_text, _font, _style); _onValueChanged(_text, _font, _style, _vertical, _lineSpacing, _charSpacing);
} }
private void UpdateStyleButtons() { private void UpdateStyleButtons() {
@ -204,7 +226,7 @@ namespace ConformalDecals.UI {
} }
else { else {
_boldButton.interactable = true; _boldButton.interactable = true;
_boldButton.isOn = _style.Bold; _boldButton.isOn = (_style & FontStyles.Bold) != 0;
} }
if (_font.Italic) { if (_font.Italic) {
@ -217,7 +239,7 @@ namespace ConformalDecals.UI {
} }
else { else {
_italicButton.interactable = true; _italicButton.interactable = true;
_italicButton.isOn = _style.Italic; _italicButton.isOn = (_style & FontStyles.Italic) != 0;
} }
if (_font.Underline) { if (_font.Underline) {
@ -230,7 +252,7 @@ namespace ConformalDecals.UI {
} }
else { else {
_underlineButton.interactable = true; _underlineButton.interactable = true;
_underlineButton.isOn = _style.Underline; _underlineButton.isOn = (_style & FontStyles.Underline) != 0;
} }
if (_font.SmallCaps) { if (_font.SmallCaps) {
@ -243,10 +265,10 @@ namespace ConformalDecals.UI {
} }
else { else {
_smallCapsButton.interactable = true; _smallCapsButton.interactable = true;
_smallCapsButton.isOn = _style.SmallCaps; _smallCapsButton.isOn = (_style & FontStyles.SmallCaps) != 0;
} }
_verticalButton.isOn = _style.Vertical; _verticalButton.isOn = _vertical;
_ignoreUpdates = false; _ignoreUpdates = false;
} }
@ -254,8 +276,8 @@ namespace ConformalDecals.UI {
private void UpdateLineSpacing() { private void UpdateLineSpacing() {
_ignoreUpdates = true; _ignoreUpdates = true;
_lineSpacingSlider.value = Mathf.InverseLerp(_lineSpacingRange.x, _lineSpacingRange.y, _style.LineSpacing); _lineSpacingSlider.value = Mathf.InverseLerp(_lineSpacingRange.x, _lineSpacingRange.y, _lineSpacing);
((TMP_InputField) _lineSpacingTextBox).text = $"{_style.LineSpacing:F1}"; ((TMP_InputField) _lineSpacingTextBox).text = $"{_lineSpacing:F1}";
_ignoreUpdates = false; _ignoreUpdates = false;
} }
@ -263,8 +285,8 @@ namespace ConformalDecals.UI {
private void UpdateCharSpacing() { private void UpdateCharSpacing() {
_ignoreUpdates = true; _ignoreUpdates = true;
_charSpacingSlider.value = Mathf.InverseLerp(_charSpacingRange.x, _charSpacingRange.y, _style.CharSpacing); _charSpacingSlider.value = Mathf.InverseLerp(_charSpacingRange.x, _charSpacingRange.y, _charSpacing);
((TMP_InputField) _charSpacingTextBox).text = $"{_style.CharSpacing:F1}"; ((TMP_InputField) _charSpacingTextBox).text = $"{_charSpacing:F1}";
_ignoreUpdates = false; _ignoreUpdates = false;
} }

@ -30,9 +30,15 @@ namespace ConformalDecals.Util {
} }
public static string ParseString(ConfigNode node, string valueName, bool isOptional = false, string defaultValue = "") { public static string ParseString(ConfigNode node, string valueName, bool isOptional = false, string defaultValue = "") {
if (!node.HasValue(valueName)) throw new FormatException($"Missing value for {valueName}"); if (node.HasValue(valueName)) return node.GetValue(valueName);
if (isOptional) {
return defaultValue;
}
else {
throw new FormatException($"Missing value for {valueName}");
}
return node.GetValue(valueName);
} }
public static bool ParseStringIndirect(ref string value, ConfigNode node, string valueName) { public static bool ParseStringIndirect(ref string value, ConfigNode node, string valueName) {

Loading…
Cancel
Save