using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using TMPro; // Panneau MODIFPNL : liste des modifications proposees pour la categorie choisie dans // VIEWER/MODIFYER. Les boutons de ListBTNS sont renommes avec le nom anglais de l'option // (c'est lui qui part dans la sauvegarde) et leur Label affiche la traduction. public static class ModifPanel { // Categorie = nom du bouton de MODIFYER. Options = noms anglais, dans l'ordre d'affichage. static readonly Dictionary Options = new() { { "Cabinet", new[] { "Add more drawers", "Add glass doors", "Reduce pantry" } }, { "Countertop", new[] { "White quartz", "Black quartz", "Wood" } }, { "BackSplash", new[] { "Subway tile", "Large format tile" } }, { "Floor", new[] { "Hardwood", "Vinyl", "Tile" } }, { "Wall", new[] { "White paint", "Grey paint" } }, { "Lamp", new[] { "Pendant lights", "Recessed lights" } }, { "Faucet", new[] { "Matte black", "Chrome" } }, { "Hood", new[] { "Chimney hood", "Built-in hood" } }, { "Appliances", new[] { "Stainless steel", "Black" } }, { "Stools", new[] { "Wood", "Metal" } }, { "Deco Items", new[] { "Add plants", "Add wall art" } }, }; // Modifications cochees, par categorie. Conservees d'une ouverture a l'autre et lues // par le Prompt, la sauvegarde et l'envoi. public static readonly Dictionary> Chosen = new(); // Vrai pendant Fill() : les OnValueChanged declenches par le remplissage sont ignores. static bool Filling; // Categories qui proposent un nuancier de couleurs, et celles qui proposent les finis // metalliques. Les autres (Cabinet, Deco Items) n'affichent ni l'un ni l'autre. static readonly string[] WithColors = { "Countertop", "BackSplash", "Floor", "Wall", "Lamp", "Hood", "Stools" }; static readonly string[] WithMetal = { "Appliances", "Faucet", "Knobs" }; // Pose le libelle traduit de chaque bouton de VIEWER/MODIFYER, d'apres son nom. // Les textes de la scene etaient desynchronises (deux "Cabinet", pas de "Stool", // "Others" au lieu de "Knobs") : c'est le nom de l'objet qui fait foi. public static void LabelCategories() { GameObject Modifyer = Get.o2("Canvas/VIEWER", "MODIFYER"); if (Modifyer == null) return; foreach (Transform Btn in Modifyer.transform) SetLabel(Btn, TRANS.Safe("T_Cat" + Btn.name.Replace(" ", ""))); } // Remplit ListBTNS pour la categorie et met le titre a jour. public static void Fill(string Category, string Title) { GameObject Pnl = Get.o2("Canvas", "MODIFPNL"); if (Pnl == null) { Debug.LogError("[ModifPanel] Canvas/MODIFPNL introuvable."); return; } SetTitle(Pnl, Title); Transform List = Pnl.transform.Find("ListBTNS"); if (List == null) { Debug.LogError("[ModifPanel] MODIFPNL/ListBTNS introuvable."); return; } if (!Options.TryGetValue(Category, out string[] Names)) Names = new string[0]; if (Names.Length > List.childCount) Debug.LogWarning("[ModifPanel] " + Category + " a " + Names.Length + " options mais ListBTNS n'a que " + List.childCount + " boutons."); Chosen.TryGetValue(Category, out List Already); // Poser les toggles declenche leur OnValueChanged : sans ce drapeau, l'etat laisse par // la categorie precedente serait enregistre sous la nouvelle pendant le remplissage. Filling = true; for (int i = 0; i < List.childCount; i++) { Transform Btn = List.GetChild(i); bool Used = i < Names.Length; Btn.gameObject.SetActive(Used); if (!Used) continue; Btn.name = Names[i];// nom anglais : c'est la valeur retenue SetLabel(Btn, TRANS.Safe(Key(Names[i]))); // On restitue les choix deja faits pour cette categorie. if (Btn.TryGetComponent(out Toggle Tog)) Tog.isOn = Already != null && Already.Contains(Names[i]); } Filling = false; ShowSwatches(Pnl, Category); UpdatePrompt();// le Prompt reste celui de toutes les categories } // Un seul des deux nuanciers a la fois, selon la categorie ouverte. static void ShowSwatches(GameObject Pnl, string Category) { SetActive(Pnl, "COLORS", System.Array.IndexOf(WithColors, Category) >= 0); SetActive(Pnl, "METAL COLOR", System.Array.IndexOf(WithMetal, Category) >= 0); } static void SetActive(GameObject Pnl, string Child, bool On) { Transform T = Pnl.transform.Find(Child); if (T != null) T.gameObject.SetActive(On); } // Enregistre les cases cochees de la categorie affichee. A appeler depuis "Button Save". public static void Save(string Category) { Remember(Category); Debug.Log("[ModifPanel] " + Category + " : " + string.Join(", ", Chosen[Category])); } // A brancher sur le OnValueChanged des toggles de ListBTNS : cocher ajoute la modification // au Prompt, decocher la retire. Le choix est retenu immediatement, sans attendre "Save" : // le Prompt doit conserver les selections d'une ouverture a l'autre. public static void OptionChanged() { if (Filling) return; Remember(CurrentCategory()); UpdatePrompt(); } static void Remember(string Category) { List Picked = CheckedOptions(); if (Category == "" || Picked == null) return; if (Picked.Count > 0) Chosen[Category] = Picked; else Chosen.Remove(Category);// plus rien de coche : la categorie sort du Prompt } // Options cochees actuellement affichees, null si le panneau est introuvable. static List CheckedOptions() { GameObject Pnl = Get.o2("Canvas", "MODIFPNL"); Transform List = Pnl != null ? Pnl.transform.Find("ListBTNS") : null; if (List == null) return null; List Picked = new(); for (int i = 0; i < List.childCount; i++) { Transform Btn = List.GetChild(i); if (Btn.gameObject.activeSelf && Btn.TryGetComponent(out Toggle Tog) && Tog.isOn) Picked.Add(Btn.name); } return Picked; } // Categorie affichee = bouton coche dans VIEWER/MODIFYER. static string CurrentCategory() { Transform Sel = Get.TogSelected(Get.o2("Canvas/VIEWER", "MODIFYER")); return Sel != null ? Sel.name : ""; } // Le Prompt cumule toutes les modifications retenues : celles deja enregistrees pour les // autres categories, plus la selection en cours dans le panneau ouvert. // Ce sont les noms anglais, c'est cette formulation qui part au rendu. public static void UpdatePrompt() { GameObject Pnl = Get.o2("Canvas", "MODIFPNL"); if (Pnl == null) return; // Le texte vit dans le cadre "BG Prompt" ; on prend le premier TMP_Text qu'il contient // plutot qu'un chemin fige : l'objet s'appelle "'Prompt:'" et pourrait etre renomme. Transform Holder = Pnl.transform.Find("BG Prompt"); if (Holder == null) { Debug.LogWarning("[ModifPanel] MODIFPNL/BG Prompt introuvable."); return; } TMP_Text Label = Holder.GetComponentInChildren(true); if (Label == null) { Debug.LogWarning("[ModifPanel] Aucun TMP_Text sous BG Prompt."); return; } // Chosen est deja tenu a jour a chaque clic : il contient toutes les categories, // y compris celle affichee. Rien a recalculer depuis les toggles. List All = new(); foreach (KeyValuePair> Kv in Chosen) All.AddRange(Kv.Value); Label.text = string.Join(", ", All); } // "Add more drawers" -> "T_ModAddMoreDrawers", "Built-in hood" -> "T_ModBuiltInHood". // Chaque mot prend une majuscule : un simple Replace(" ","") aurait donne // "T_ModAddmoredrawers", introuvable dans _T, et le label affichait la cle brute. static string Key(string Name) { string Out = "T_Mod"; foreach (string Word in Name.Split(' ', '-')) { if (Word.Length == 0) continue; Out += char.ToUpperInvariant(Word[0]) + Word[1..]; } return Out; } static void SetTitle(GameObject Pnl, string Title) { if (Title == "") return; Transform T = Pnl.transform.Find("BG/Tittle/T_Yourdesign"); if (T != null && T.TryGetComponent(out TMP_Text Label)) Label.text = Title; } // Le Label d'un bouton n'a pas toujours le meme nom d'objet ("Label", "Wall", "Hood"...) : // on prend le premier Text trouve dans ses enfants. static void SetLabel(Transform Btn, string Value) { Text Label = Btn.GetComponentInChildren(true); if (Label != null) Label.text = Value; } // Idem en lecture : sert a reprendre le libelle du bouton de MODIFYER pour le titre. public static string LabelOf(Transform Btn) { if (Btn == null) return ""; Text Label = Btn.GetComponentInChildren(true); if (Label != null) return Label.text; TMP_Text Tmp = Btn.GetComponentInChildren(true); return Tmp != null ? Tmp.text : Btn.name; } }