From ece9d959fded1d432696d454ecb362ec4eed7c1a Mon Sep 17 00:00:00 2001 From: Andrew Cassidy Date: Sun, 30 Oct 2022 23:58:55 -0700 Subject: [PATCH] flag aspect ratio overrides are now configurable no longer hard coded to Squad/Flags --- CHANGELOG.md | 2 + .../Resources/ConformalDecals.cfg | 305 ++++++++++++++++++ Source/ConformalDecals/DecalConfig.cs | 18 +- .../MaterialPropertyCollection.cs | 19 +- .../MaterialTextureProperty.cs | 8 +- .../ConformalDecals/ModuleConformalDecal.cs | 44 ++- Source/ConformalDecals/ModuleConformalFlag.cs | 18 +- Source/ConformalDecals/ModuleConformalText.cs | 2 +- 8 files changed, 379 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f140b24..964c1ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ All notable changes to this project will be documented in this file ### Changed - Updated bundled Shabby to 0.3.0. Does not affect CKAN users +- Made flag aspect ratio overrides configurable with `ASPECTRATIO` nodes in the config. User flags added to Squad/Flags should now be the correct aspect ratio +- All decal aspect ratios can now be overriden with the `aspectRatio` field ### Fixed diff --git a/GameData/ConformalDecals/Resources/ConformalDecals.cfg b/GameData/ConformalDecals/Resources/ConformalDecals.cfg index e868a65..62482a1 100644 --- a/GameData/ConformalDecals/Resources/ConformalDecals.cfg +++ b/GameData/ConformalDecals/Resources/ConformalDecals.cfg @@ -49,4 +49,309 @@ CONFORMALDECALS { style = 32 styleMask = 4 } + + ASPECTRATIO { + path = Squad/Flags/09 + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/Sentinel_Flag + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/blorbs + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/bullseye + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/capsule + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/circles + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/default + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/hexagon + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/hexagonCircles + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/kerbal1 + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/kerbal2 + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/kerbin + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/kerbinmunflag + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/line + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/minimalistic + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/orbit + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/orbs + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/retro + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/rings + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/rocketScience + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/satellite + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/spheres + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/squadLogo + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/squadLogo2 + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/stripes + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/trees + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Flags/trippy + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/FlagsAgency/NASA + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/FlagsAgency/esa_dark_blue + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/FlagsAgency/uk_space_agency + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/FlagsOrganization/B612_Foundation_flag + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/FlagsOrganization/ESA_Arianespace + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/FlagsOrganization/electron + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/FlagsOrganization/rocketlab + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/C7AerospaceDivision + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/DinkelsteinKermansConstructionEmporium + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/ExperimentalEngineering + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/FlooydResearchLab + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/GoliathNationalProducts + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/IntegratedIntegrals + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/IonicSymphonicProtonicElectronics + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/JebsJunkyard + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/KerbalMotion + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/KerbinWorldFirstRecordKeepingSociety + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/Kerbodyne + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/Kerlington + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/MaxoConstructionToys + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/MovingPartsExpertsGroup + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/OMBDemolition + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/PeriapsisCo + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/Probodobodyne + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/R&D + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/ReactionSystemsLtd + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/Rockomax + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/Rokea + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/SeansCannery + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/SteadlerEngineeringCorps + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/StrutCo + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/Vac-Co + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/WinterOwl + aspectRatio = 0.625 + } + + ASPECTRATIO { + path = Squad/Agencies/ZaltonicElectronics + aspectRatio = 0.625 + } } \ No newline at end of file diff --git a/Source/ConformalDecals/DecalConfig.cs b/Source/ConformalDecals/DecalConfig.cs index a29e78a..a9fe8eb 100644 --- a/Source/ConformalDecals/DecalConfig.cs +++ b/Source/ConformalDecals/DecalConfig.cs @@ -15,6 +15,7 @@ namespace ConformalDecals { private static Dictionary _fontList; private static int _decalLayer = 31; private static bool _selectableInFlight; + private static Dictionary _aspectRatios; private struct LegacyShaderEntry { public string name; @@ -53,6 +54,8 @@ namespace ConformalDecals { public static IEnumerable Fonts => _fontList.Values; + public static Dictionary AspectRatios => _aspectRatios; + public static bool IsBlacklisted(Shader shader) { return IsBlacklisted(shader.name); } @@ -86,8 +89,7 @@ namespace ConformalDecals { public static DecalFont GetFont(string name) { if (_fontList.TryGetValue(name, out var font)) { return font; - } - else { + } else { throw new KeyNotFoundException($"Font {name} not found"); } } @@ -113,8 +115,17 @@ namespace ConformalDecals { try { var font = new DecalFont(fontNode, allFonts); _fontList.Add(font.Name, font); + } catch (Exception e) { + Debug.LogException(e); } - catch (Exception e) { + } + + foreach (var ratioNode in node.GetNodes("ASPECTRATIO")) { + try { + var path = ParseUtil.ParseString(ratioNode, "path"); + var ratio = ParseUtil.ParseFloat(ratioNode, "aspectRatio"); + _aspectRatios[path] = ratio; + } catch (Exception e) { Debug.LogException(e); } } @@ -144,6 +155,7 @@ namespace ConformalDecals { _shaderBlacklist = new List(); _shaderRegexBlacklist = new List(); _fontList = new Dictionary(); + _aspectRatios = new Dictionary(); var configs = GameDatabase.Instance.GetConfigs("CONFORMALDECALS"); diff --git a/Source/ConformalDecals/MaterialProperties/MaterialPropertyCollection.cs b/Source/ConformalDecals/MaterialProperties/MaterialPropertyCollection.cs index 579ff23..72a7bc3 100644 --- a/Source/ConformalDecals/MaterialProperties/MaterialPropertyCollection.cs +++ b/Source/ConformalDecals/MaterialProperties/MaterialPropertyCollection.cs @@ -75,7 +75,12 @@ namespace ConformalDecals.MaterialProperties { } } - public float AspectRatio => MainTexture == null ? 1 : MainTexture.AspectRatio; + public float AspectRatio { + get => MainTexture == null ? 1 : MainTexture.AspectRatio; + set { + if (MainTexture != null) MainTexture.AspectRatio = value; + } + } public void OnBeforeSerialize() { if (_materialProperties == null) throw new SerializationException("Tried to serialize an uninitialized MaterialPropertyCollection"); @@ -136,8 +141,7 @@ namespace ConformalDecals.MaterialProperties { public T GetProperty(string propertyName) where T : MaterialProperty { if (_materialProperties.ContainsKey(propertyName) && _materialProperties[propertyName] is T property) { return property; - } - else { + } else { return null; } } @@ -145,8 +149,7 @@ namespace ConformalDecals.MaterialProperties { public T AddOrGetProperty(string propertyName) where T : MaterialProperty { if (_materialProperties.ContainsKey(propertyName) && _materialProperties[propertyName] is T property) { return property; - } - else { + } else { return AddProperty(propertyName); } } @@ -156,9 +159,10 @@ namespace ConformalDecals.MaterialProperties { foreach (var material in Materials) { property.Remove(material); } + _materialProperties.Remove(propertyName); Destroy(property); - + return true; } @@ -204,8 +208,7 @@ namespace ConformalDecals.MaterialProperties { if (_shader == null) { Logging.Log("Using default decal shader"); shaderName = "ConformalDecals/Decal/Standard"; - } - else { + } else { return; } } diff --git a/Source/ConformalDecals/MaterialProperties/MaterialTextureProperty.cs b/Source/ConformalDecals/MaterialProperties/MaterialTextureProperty.cs index 9a096aa..7632e20 100644 --- a/Source/ConformalDecals/MaterialProperties/MaterialTextureProperty.cs +++ b/Source/ConformalDecals/MaterialProperties/MaterialTextureProperty.cs @@ -19,6 +19,8 @@ namespace ConformalDecals.MaterialProperties { [SerializeField] private Vector2 _textureOffset; [SerializeField] private Vector2 _textureScale = Vector2.one; + [SerializeField] private float _aspectRatioOverride = -1.0f; + public Texture2D Texture { get => _texture; set => _texture = value; @@ -43,10 +45,12 @@ namespace ConformalDecals.MaterialProperties { public float AspectRatio { get { + if (_aspectRatioOverride > 0) return _aspectRatioOverride; if (_texture == null) return 1; - if (_textureUrl?.Contains("Squad/Flags") == true) return 0.625f; return MaskedHeight / (float) MaskedWidth; } + + set => _aspectRatioOverride = value; } public override void ParseNode(ConfigNode node) { @@ -64,7 +68,7 @@ namespace ConformalDecals.MaterialProperties { if (ParseUtil.ParseStringIndirect(ref _textureUrl, node, "textureUrl")) { _texture = LoadTexture(_textureUrl, isNormal); } - + if (_texture == null) { _texture = isNormal ? DecalConfig.BlankNormal : Texture2D.whiteTexture; } diff --git a/Source/ConformalDecals/ModuleConformalDecal.cs b/Source/ConformalDecals/ModuleConformalDecal.cs index 0d281ec..5d4ce25 100644 --- a/Source/ConformalDecals/ModuleConformalDecal.cs +++ b/Source/ConformalDecals/ModuleConformalDecal.cs @@ -35,6 +35,8 @@ namespace ConformalDecals { [KSPField] public DecalScaleMode scaleMode = DecalScaleMode.HEIGHT; + [KSPField] public float aspectRatio = -1.0f; // < 0 = use texture + [KSPField] public bool depthAdjustable = true; [KSPField] public float defaultDepth = 0.1f; [KSPField] public Vector2 depthRange = new Vector2(0, 2); @@ -201,6 +203,10 @@ namespace ConformalDecals { } else if (tileIndex >= 0) { materialProperties.UpdateTile(tileIndex, tileSize); } + + // handle aspect ratio overrides + materialProperties.AspectRatio = aspectRatio; + } catch (Exception e) { this.LogException("Exception parsing partmodule", e); } @@ -393,30 +399,32 @@ namespace ConformalDecals { protected void UpdateScale() { scale = Mathf.Max(0.01f, scale); depth = Mathf.Max(0.01f, depth); - var aspectRatio = Mathf.Max(0.01f, materialProperties.AspectRatio); + + var sizeRatio = Mathf.Max(0.01f, materialProperties.AspectRatio); + Vector2 size; switch (scaleMode) { default: case DecalScaleMode.HEIGHT: - size = new Vector2(scale / aspectRatio, scale); + size = new Vector2(scale / sizeRatio, scale); break; case DecalScaleMode.WIDTH: - size = new Vector2(scale, scale * aspectRatio); + size = new Vector2(scale, scale * sizeRatio); break; case DecalScaleMode.AVERAGE: - var width1 = 2 * scale / (1 + aspectRatio); - size = new Vector2(width1, width1 * aspectRatio); + var width1 = 2 * scale / (1 + sizeRatio); + size = new Vector2(width1, width1 * sizeRatio); break; case DecalScaleMode.AREA: - var width2 = Mathf.Sqrt(scale / aspectRatio); - size = new Vector2(width2, width2 * aspectRatio); + var width2 = Mathf.Sqrt(scale / sizeRatio); + size = new Vector2(width2, width2 * sizeRatio); break; case DecalScaleMode.MINIMUM: - if (aspectRatio > 1) goto case DecalScaleMode.WIDTH; + if (sizeRatio > 1) goto case DecalScaleMode.WIDTH; else goto case DecalScaleMode.HEIGHT; case DecalScaleMode.MAXIMUM: - if (aspectRatio > 1) goto case DecalScaleMode.HEIGHT; + if (sizeRatio > 1) goto case DecalScaleMode.HEIGHT; else goto case DecalScaleMode.WIDTH; } @@ -433,7 +441,7 @@ namespace ConformalDecals { // update projection foreach (var target in _targets) { - if (target == null) { + if (target.target == null) { _targets.Remove(target); } else { target.Project(_orthoMatrix, decalProjectorTransform, _boundsRenderer.bounds, useBaseNormal); @@ -570,13 +578,19 @@ namespace ConformalDecals { public void Render(Camera camera) { if (!_isAttached) return; - // render on each target object - foreach (var target in _targets) { - if (target == null) { - _targets.Remove(target); - } else { + try { + // render on each target object + foreach (var target in _targets) { target.Render(_decalMaterial, part.mpb, camera); } + } catch (NullReferenceException) { + // catch any NREs and purge null transforms from the target list + // comparing Transform to null is expensive, but a try-catch block is much cheaper + foreach (var target in _targets) { + if (target.target == null) { + _targets.Remove(target); + } + } } } } diff --git a/Source/ConformalDecals/ModuleConformalFlag.cs b/Source/ConformalDecals/ModuleConformalFlag.cs index ffde2bc..d466b9d 100644 --- a/Source/ConformalDecals/ModuleConformalFlag.cs +++ b/Source/ConformalDecals/ModuleConformalFlag.cs @@ -1,3 +1,4 @@ +using ConformalDecals.Util; using UnityEngine; namespace ConformalDecals { @@ -48,12 +49,12 @@ namespace ConformalDecals { UpdateFlag(); } - public virtual void OnDestroy() { + public override void OnDestroy() { if (HighLogic.LoadedSceneIsEditor) { // Unregister flag change event GameEvents.onMissionFlagSelect.Remove(OnEditorFlagSelected); } - + base.OnDestroy(); } @@ -106,12 +107,13 @@ namespace ConformalDecals { // get the decal material property for the decal texture var textureProperty = materialProperties.AddOrGetTextureProperty("_Decal", true); - if (useCustomFlag) { - // set the texture to the custom flag - textureProperty.TextureUrl = flagUrl; - } else { - // set the texture to the mission flag - textureProperty.TextureUrl = MissionFlagUrl; + string textureURL = useCustomFlag ? flagUrl : MissionFlagUrl; + textureProperty.TextureUrl = textureURL; + + if (DecalConfig.AspectRatios.ContainsKey(textureURL)) { + var ratio = DecalConfig.AspectRatios[textureURL]; + this.Log($"Overriding aspect ratio for {textureURL} with {ratio}"); + textureProperty.AspectRatio = ratio; } UpdateMaterials(); diff --git a/Source/ConformalDecals/ModuleConformalText.cs b/Source/ConformalDecals/ModuleConformalText.cs index a974cfb..3e0bb7d 100644 --- a/Source/ConformalDecals/ModuleConformalText.cs +++ b/Source/ConformalDecals/ModuleConformalText.cs @@ -220,7 +220,7 @@ namespace ConformalDecals { } } - public void OnDestroy() { + public override void OnDestroy() { if (HighLogic.LoadedSceneIsGame && _currentText != null) TextRenderer.UnregisterText(_currentText); // close all UIs