using System.Collections.Generic; using Godot; using Newlon.Components; using Newlon.Components.GUI.Seedpackets; using Newlon.Components.Plants; using Newlon.Systems.Effects; public partial class Previewport : SubViewport { private Node current_display; private Texture2D start_Field; [Export] private Label title; [Export] private RichTextLabel description; [Export] private Sprite2D _frameField; public override void _Ready() { GetParent().GetViewport().GuiFocusChanged += OnFocusChanged; start_Field = _frameField.Texture; } public void OnFocusChanged(Control node) { if (GetParent().IsVisibleInTree() == false) return; if (node is Seedpacket packet) { ChangeDisplay(packet.GetResource()); } } private void ChangeDisplay(EntityResource resource) { // Expand with updates if (current_display != null) { current_display.QueueFree(); } if (resource.CustomFrame != null && resource.CustomFrame.almanachField != null) { _frameField.Texture = resource.CustomFrame.almanachField; } else _frameField.Texture = start_Field; current_display = resource.Scene.Instantiate(); title.Text = Tr(resource.NameKey); AddChild(current_display); if (current_display is Entity entity) entity.DisableBrain(); string descriptionText; if (resource.isDescriptionParsed == false) { var unparsedDescription = Tr(resource.DescriptionKey); var keys = GetRequestedKeys(unparsedDescription); FillPlaceholders(keys, resource, current_display); descriptionText = ReplaceTextUsingDict(keys, unparsedDescription); resource.parsedDescription = descriptionText; resource.isDescriptionParsed = true; } else { descriptionText = resource.parsedDescription; } var rwd = Tr("rwd_" + resource.NameKey); if (rwd == "rwd_" + resource.NameKey) { rwd = ""; } else { rwd += "\n"; } description.Text = rwd + descriptionText; } private Dictionary GetRequestedKeys(string text) { var result = new Dictionary(); int start = -1; for (int i = 0; i < text.Length; i++) { if (text[i] == '{') { start = i; } if (text[i] == '}') { if (start == -1) continue; result.Add(text.Substr(start + 1, i - start - 1), 0); start = -1; } } return result; } private void FillPlaceholders(Dictionary placeholderDictionary, EntityResource resource, Node searchScene) { var searchList = new List() { resource, searchScene }; while (searchList.Count > 0) { var lookedObject = searchList[0]; searchList.RemoveAt(0); if (lookedObject is Node lookedNode) searchList.AddRange(lookedNode.GetChildren()); if (lookedObject is Shooter shooter) { var projectile = shooter._projectile.Instantiate(); searchList.Add(projectile); } foreach (var property in lookedObject.GetPropertyList()) { if ((Variant.Type)property["type"].AsInt32() == Variant.Type.Object) { if (lookedObject.Get(property["name"].AsString()).AsGodotObject() is Effect effect) { searchList.Add(effect); } } } foreach (var key in placeholderDictionary.Keys) { string request = key.Split('|')[0]; var namePropertyPair = request.Split('.'); Variant property; if (namePropertyPair.Length == 2) { if ((namePropertyPair[0] == "?" && lookedObject != searchScene) || (namePropertyPair[0] != "?" && lookedObject is Node node && node.Name != namePropertyPair[0])) { continue; } property = lookedObject.Get(namePropertyPair[1]); } else { property = lookedObject.Get(namePropertyPair[0]); } if (property.VariantType == Variant.Type.Nil) { continue; } float value = property.As(); placeholderDictionary[key] = value; } } // Apply any modifiers foreach (var key in placeholderDictionary.Keys) { if (key.Split('|').Length < 2) continue; string[] modifiers = key.Split('|')[1..]; float value = placeholderDictionary[key]; foreach (var mod in modifiers) { if (mod != "") { switch (mod[0]) { case '%': value *= 100; break; case '*': if (placeholderDictionary.ContainsKey(mod[1..])) { value *= placeholderDictionary[mod[1..]]; } else if (float.TryParse(mod[1..], out float result)) { value *= result; } break; case '/': if (placeholderDictionary.ContainsKey(mod[1..])) { value /= placeholderDictionary[mod[1..]]; } else if (float.TryParse(mod[1..], out float result)) { value /= result; } break; } } } placeholderDictionary[key] = value; } } private string ReplaceTextUsingDict(Dictionary dictionary, string text) { var resStr = text; foreach (var key in dictionary.Keys) { resStr = resStr.Replace('{' + key + '}', dictionary[key].ToString()); } return resStr; } }