diff --git a/.gitignore b/.gitignore index 5e2bf9b..65b3d63 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,4 @@ Source/ConformalDecals/bin .idea obj *.swp +@thumbs diff --git a/Source/ConformalDecals/ModuleConformalDecal.cs b/Source/ConformalDecals/ModuleConformalDecal.cs index 64bc2a8..064c81d 100644 --- a/Source/ConformalDecals/ModuleConformalDecal.cs +++ b/Source/ConformalDecals/ModuleConformalDecal.cs @@ -481,6 +481,9 @@ namespace ConformalDecals { foreach (var renderer in renderers) { // skip disabled renderers if (renderer.gameObject.activeInHierarchy == false) continue; + + // skip transparentFX layer, which causes issues with Waterfall + if (renderer.gameObject.layer == 1) continue; // skip blacklisted shaders if (DecalConfig.IsBlacklisted(renderer.material.shader)) continue; diff --git a/Source/ConformalDecals/ModuleConformalFlag.cs b/Source/ConformalDecals/ModuleConformalFlag.cs index 4ce228b..ca249f3 100644 --- a/Source/ConformalDecals/ModuleConformalFlag.cs +++ b/Source/ConformalDecals/ModuleConformalFlag.cs @@ -1,4 +1,3 @@ -using ConformalDecals.Util; using UnityEngine; namespace ConformalDecals { @@ -9,6 +8,7 @@ namespace ConformalDecals { [KSPField(isPersistant = true)] public bool useCustomFlag; + // The URL of the flag for the current mission or agency public string MissionFlagUrl { get { if (HighLogic.LoadedSceneIsEditor) { @@ -19,6 +19,7 @@ namespace ConformalDecals { return string.IsNullOrEmpty(part.flagURL) ? HighLogic.CurrentGame.flagURL : part.flagURL; } + // If we are not in game, use the default flag (for icon rendering) return DefaultFlag; } } @@ -26,84 +27,106 @@ namespace ConformalDecals { public override void OnLoad(ConfigNode node) { base.OnLoad(node); - if (useCustomFlag) { - SetFlag(flagUrl); - } - else { - SetFlag(MissionFlagUrl); - } + // Since OnLoad is called for all modules, we only need to update this module + // Updating symmetry counterparts would be redundent + UpdateFlag(); } public override void OnStart(StartState state) { base.OnStart(state); - if (HighLogic.LoadedSceneIsGame) { - GameEvents.onMissionFlagSelect.Add(OnEditorFlagSelected); - } - if (HighLogic.LoadedSceneIsEditor) { + // Register flag change event + GameEvents.onMissionFlagSelect.Add(OnEditorFlagSelected); + + // Register reset button event Events[nameof(ResetFlag)].guiActiveEditor = useCustomFlag; } - if (useCustomFlag) { - SetFlag(flagUrl); - } - else { - SetFlag(MissionFlagUrl); - } + // Since OnStart is called for all modules, we only need to update this module + // Updating symmetry counterparts would be redundent + UpdateFlag(); } public override void OnDestroy() { - GameEvents.onMissionFlagSelect.Remove(SetFlag); + if (HighLogic.LoadedSceneIsEditor) { + // Unregister flag change event + GameEvents.onMissionFlagSelect.Remove(OnEditorFlagSelected); + } + base.OnDestroy(); } [KSPEvent(guiActive = false, guiActiveEditor = true, guiName = "#LOC_ConformalDecals_gui-select-flag")] public void SelectFlag() { + // Button for selecting a flag + // This is a bit of a hack to bring up the stock flag selection menu + // When its done, it calls OnCustomFlagSelected() + + // ReSharper disable once PossibleNullReferenceException var flagBrowser = (Instantiate((Object) (new FlagBrowserGUIButton(null, null, null, null)).FlagBrowserPrefab) as GameObject).GetComponent(); flagBrowser.OnFlagSelected = OnCustomFlagSelected; } [KSPEvent(guiActive = false, guiActiveEditor = true, guiName = "#LOC_ConformalDecals_gui-reset-flag")] public void ResetFlag() { - SetFlag(MissionFlagUrl); - SetFlagSymmetryCounterparts(MissionFlagUrl); - + + // we are no longer using a custom flag, so instead use the mission or agency flag useCustomFlag = false; + flagUrl = "Mission"; + UpdateFlag(true); + + // disable the reset button, since it no longer makes sense Events[nameof(ResetFlag)].guiActiveEditor = false; } private void OnCustomFlagSelected(FlagBrowser.FlagEntry newFlagEntry) { - SetFlag(newFlagEntry.textureInfo.name); - SetFlagSymmetryCounterparts(newFlagEntry.textureInfo.name); - + // Callback for when a flag is selected in the menu spawned by SelectFlag() + + // we are now using a custom flag with the URL of the new flag entry useCustomFlag = true; + flagUrl = newFlagEntry.textureInfo.name; + UpdateFlag(true); + + // make sure the reset button is now available Events[nameof(ResetFlag)].guiActiveEditor = true; } private void OnEditorFlagSelected(string newFlagUrl) { if (!useCustomFlag) { - SetFlag(newFlagUrl); - SetFlagSymmetryCounterparts(newFlagUrl); + flagUrl = newFlagUrl; + // Since this callback is called for all modules, we only need to update this module + // Updating symmetry counterparts would be redundent + UpdateFlag(); } } - private void SetFlag(string newFlagUrl) { - this.Log($"Loading flag texture '{newFlagUrl}'."); - - flagUrl = newFlagUrl; - materialProperties.AddOrGetTextureProperty("_Decal", true).TextureUrl = newFlagUrl; - + // Update the displayed flag texture for this decal or optionally any symmetry counterparts + private void UpdateFlag(bool recursive = false) { + // 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; + } + UpdateMaterials(); UpdateScale(); - } - private void SetFlagSymmetryCounterparts(string newFlagUrl) { - foreach (var counterpart in part.symmetryCounterparts) { - var decal = counterpart.GetComponent(); - - decal.SetFlag(newFlagUrl); - decal.useCustomFlag = useCustomFlag; + if (recursive) { + // for each symmetry counterpart, copy this part's properties and update it in turn + foreach (var counterpart in part.symmetryCounterparts) { + var decal = counterpart.GetComponent(); + + decal.useCustomFlag = useCustomFlag; + decal.flagUrl = flagUrl; + decal.UpdateFlag(); + } } } } diff --git a/Source/ConformalDecals/ModuleConformalText.cs b/Source/ConformalDecals/ModuleConformalText.cs index c5db737..b3948d8 100644 --- a/Source/ConformalDecals/ModuleConformalText.cs +++ b/Source/ConformalDecals/ModuleConformalText.cs @@ -153,7 +153,7 @@ namespace ConformalDecals { this.vertical = newVertical; this.lineSpacing = newLineSpacing; this.charSpacing = newCharSpacing; - UpdateTextRecursive(); + UpdateText(true); } public void OnFillColorUpdate(Color rgb, Util.ColorHSV hsv) { @@ -240,40 +240,37 @@ namespace ConformalDecals { base.OnDetach(); } - private void UpdateTextRecursive() { - UpdateText(); - - foreach (var counterpart in part.symmetryCounterparts) { - var decal = counterpart.GetComponent(); - decal.text = text; - decal.font = font; - decal.style = style; - decal.vertical = vertical; - decal.charSpacing = charSpacing; - decal.lineSpacing = lineSpacing; - - decal._currentText = _currentText; - decal.UpdateText(); - } - } - private IEnumerator UpdateTextLate() { yield return null; UpdateText(); } - private void UpdateText() { + private void UpdateText(bool recursive = false) { // Render text var newText = new DecalText(text, font, style, vertical, lineSpacing, charSpacing); var output = TextRenderer.UpdateText(_currentText, newText); + + // update the _currentText state variable + // this is the ONLY place this variable should be set! otherwise the current state is lost _currentText = newText; + // Update the texture with the new rendered output UpdateTexture(output); - // TODO: ASYNC RENDERING - // var newText = new DecalText(text, _font, _style); - // _currentJob = TextRenderer.UpdateText(_currentText, newText, UpdateTexture); - // _currentText = newText; + // If recursive, copy parameters to other parts and perform the same operation + if (recursive) { + foreach (var counterpart in part.symmetryCounterparts) { + var decal = counterpart.GetComponent(); + decal.text = text; + decal.font = font; + decal.style = style; + decal.vertical = vertical; + decal.charSpacing = charSpacing; + decal.lineSpacing = lineSpacing; + + decal.UpdateText(); + } + } } public void UpdateTexture(TextRenderOutput output) {