From 370083630a5421be1dd8fb347756577dffb761f8 Mon Sep 17 00:00:00 2001 From: Harold Iedema Date: Sun, 1 Sep 2024 23:12:28 +0200 Subject: [PATCH] Removed WidgetConfigWindow in favor of VariablesWindow & Introduced an Icon Picker --- Umbra/i18n/de.json | 62 +++-- Umbra/i18n/en.json | 66 +++-- Umbra/i18n/fr.json | 44 ++-- Umbra/i18n/ja.json | 42 ++-- Umbra/i18n/zh.json | 42 ++-- .../CustomButton/CustomButtonWidget.Config.cs | 6 +- .../CustomButton/CustomButtonWidget.cs | 4 +- .../CustomMenu/CustomMenuWidget.Config.cs | 8 +- .../Library/CustomMenu/CustomMenuWidget.cs | 6 +- .../DynamicMenuPopup.CustomItemEditor.cs | 8 +- .../DynamicMenu/DynamicMenuWidget.Config.cs | 5 +- .../Library/DynamicMenu/DynamicMenuWidget.cs | 2 +- .../EmoteList/EmoteListWidget.Config.cs | 5 +- .../Library/EmoteList/EmoteListWidget.cs | 2 +- .../Library/MainMenu/MainMenuWidget.cs | 13 +- .../ShortcutPanelWidget.Config.cs | 3 +- .../ShortcutPanel/ShortcutPanelWidget.cs | 2 +- .../Societies/SocietiesWidget.Config.cs | 5 +- .../Library/Societies/SocietiesWidget.cs | 2 +- .../UnifiedMainMenu/UnifiedMainMenu.Config.cs | 10 +- .../UnifiedMainMenu/UnifiedMainMenu.cs | 4 +- .../Config/IconIdWidgetConfigVariable.cs | 19 ++ .../System/Editor/WidgetInstanceEditor.cs | 169 +++++++++++++ .../Widgets/System/Types/ToolbarWidget.cs | 2 +- .../Toolbar/Widgets/System/WidgetManager.cs | 23 +- .../src/Windows/Components/IconIdInputNode.cs | 213 +++++++++++++++++ .../Library/IconPicker/IconGridNode.cs | 102 ++++++++ .../IconPicker/IconPickerWindow.Nodes.cs | 106 +++++++++ .../IconPicker/IconPickerWindow.Stylesheet.cs | 81 +++++++ .../Library/IconPicker/IconPickerWindow.cs | 125 ++++++++++ .../Modules/AuxWidgetsModule.Nodes.cs | 12 +- .../Settings/Modules/WidgetsModule.Nodes.cs | 14 +- .../Variable/BooleanVariable.cs | 30 ++- .../VariablesWindow/Variable/ColorVariable.cs | 30 ++- .../VariablesWindow/Variable/FloatVariable.cs | 30 ++- .../Variable/IconIdVariable.cs | 30 +++ .../Variable/IntegerVariable.cs | 30 ++- .../Variable/StringSelectVariable.cs | 30 ++- .../Variable/StringVariable.cs | 31 ++- .../VariablesWindow/Variable/Variable.cs | 2 + .../VariablesWindow/VariablesWindow.Nodes.cs | 20 +- .../VariablesWindow/VariablesWindow.cs | 3 +- .../WidgetConfigWindow.Controls.cs | 225 ------------------ .../WidgetConfig/WidgetConfigWindow.Nodes.cs | 94 -------- .../WidgetConfig/WidgetConfigWindow.cs | 150 ------------ 45 files changed, 1233 insertions(+), 679 deletions(-) create mode 100644 Umbra/src/Toolbar/Widgets/System/Config/IconIdWidgetConfigVariable.cs create mode 100644 Umbra/src/Toolbar/Widgets/System/Editor/WidgetInstanceEditor.cs create mode 100644 Umbra/src/Windows/Components/IconIdInputNode.cs create mode 100644 Umbra/src/Windows/Library/IconPicker/IconGridNode.cs create mode 100644 Umbra/src/Windows/Library/IconPicker/IconPickerWindow.Nodes.cs create mode 100644 Umbra/src/Windows/Library/IconPicker/IconPickerWindow.Stylesheet.cs create mode 100644 Umbra/src/Windows/Library/IconPicker/IconPickerWindow.cs create mode 100644 Umbra/src/Windows/Library/VariablesWindow/Variable/IconIdVariable.cs delete mode 100644 Umbra/src/Windows/Library/WidgetConfig/WidgetConfigWindow.Controls.cs delete mode 100644 Umbra/src/Windows/Library/WidgetConfig/WidgetConfigWindow.Nodes.cs delete mode 100644 Umbra/src/Windows/Library/WidgetConfig/WidgetConfigWindow.cs diff --git a/Umbra/i18n/de.json b/Umbra/i18n/de.json index 928c0faa..f8b94709 100644 --- a/Umbra/i18n/de.json +++ b/Umbra/i18n/de.json @@ -10,6 +10,7 @@ "Apply": "Anwenden", "Copy": "Kopieren", "Paste": "Einfügen", + "Undo": "Rückgängig", "Experience": "EP", "Rested": "Erholt", "Revert": "Auf Standardwert zurücksetzen", @@ -624,8 +625,8 @@ "Widget.MainMenu.Description": "Zeigt eine Schaltfläche an, die das konfigurierte Hauptmenü öffnet.", "Widget.MainMenu.Config.Category.Name": "Menükategorie", "Widget.MainMenu.Config.Category.Description": "Die Kategorie des Hauptmenüs, das geöffnet werden soll, wenn die Schaltfläche angeklickt wird.", - "Widget.MainMenu.Config.CustomIconId.Name": "Benutzerdefinierte Symbol-ID", - "Widget.MainMenu.Config.CustomIconId.Description": "Die benutzerdefinierte Symbol-ID, die für die Hauptmenüschaltfläche verwendet werden soll. Dies kann verwendet werden, um das Standard-Symbol zu überschreiben. Verwende den Befehl \"/xldata icons\", um verfügbare Symbole zu durchsuchen und die richtige ID zu erhalten. Verwende ID 0, um das Standard-Symbol zu verwenden.", + "Widget.MainMenu.Config.CustomIconId.Name": "Benutzerdefinierte Symbol", + "Widget.MainMenu.Config.CustomIconId.Description": "Die benutzerdefinierte Symbol, die für die Hauptmenüschaltfläche verwendet werden soll. Dies kann verwendet werden, um das Standard-Symbol zu überschreiben.", "Widget.MainMenu.Config.ShowItemIcons.Name": "Symbole für Elemente im Menü anzeigen", "Widget.MainMenu.Config.ShowItemIcons.Description": "Ob Symbole im Popup-Menü für Elemente angezeigt werden sollen, die mit Symbolen verbunden sind.", "Widget.MainMenu.Config.GrayscaleIcons.Name": "Menüsymbole entsättigen", @@ -666,7 +667,7 @@ "Widget.DynamicMenu.Config.ButtonTooltip.Name": "Schaltflächen-Tooltip", "Widget.DynamicMenu.Config.ButtonTooltip.Description": "Der Tooltip, der angezeigt wird, wenn du mit der Maus über die Schaltfläche fährst, die das dynamische Menü öffnet.", "Widget.DynamicMenu.Config.ButtonIcon.Name": "Schaltflächensymbol", - "Widget.DynamicMenu.Config.ButtonIcon.Description": "Das Symbol, das auf der Schaltfläche angezeigt wird. Verwende den Befehl \"/xldata icons\", um die verfügbaren Symbole zu durchsuchen und die richtige ID zu erhalten.", + "Widget.DynamicMenu.Config.ButtonIcon.Description": "Das Symbol, das auf der Schaltfläche angezeigt wird.", "Widget.DynamicMenu.Config.EditModeEnabled.Name": "Bearbeitungsmodus aktivieren", "Widget.DynamicMenu.Config.EditModeEnabled.Description": "Aktiviert ein Platzhalter-Element am unteren Rand des Menüs, das ein Kontextmenü öffnet, um neue Elemente zum Menü hinzuzufügen.", "Widget.DynamicMenu.Config.MenuEntryHeight.Name": "Menüeintrag Höhe", @@ -689,8 +690,8 @@ "Widget.DynamicMenu.CustomItemEditor.Title": "Eigenes Element bearbeiten", "Widget.DynamicMenu.CustomItemEditor.Label.Name": "Name", "Widget.DynamicMenu.CustomItemEditor.Label.Description": "Der Name des eigenen Elements, der im dynamischen Menü angezeigt wird.", - "Widget.DynamicMenu.CustomItemEditor.Icon.Name": "Icon-ID", - "Widget.DynamicMenu.CustomItemEditor.Icon.Description": "Die Icon-ID, die neben dem eigenen Element im dynamischen Menü angezeigt wird. Benutze den Befehl \"/xldata icons\", um verfügbare Icons anzusehen und die richtige ID zu finden.", + "Widget.DynamicMenu.CustomItemEditor.Icon.Name": "Icon", + "Widget.DynamicMenu.CustomItemEditor.Icon.Description": "Die Icon, die neben dem eigenen Element im dynamischen Menü angezeigt wird.", "Widget.DynamicMenu.CustomItemEditor.Type.Name": "Aufruf-Typ", "Widget.DynamicMenu.CustomItemEditor.Type.Description": "Der Aufruf-Typ, der verwendet wird, wenn das eigene Element angeklickt wird.", "Widget.DynamicMenu.CustomItemEditor.Type.Option.ChatCommand": "Chat-Befehl", @@ -817,7 +818,7 @@ "Widget.Societies.Config.ButtonLabel.Name": "Schaltflächenbeschriftung (wenn nicht verfolgt)", "Widget.Societies.Config.ButtonLabel.Description": "Die Beschriftung, die auf der Schaltfläche des Widgets angezeigt werden soll, wenn keine Verbundenheit verfolgt wird.", "Widget.Societies.Config.ButtonIconId.Name": "Schaltflächensymboltyp (wenn nicht verfolgt)", - "Widget.Societies.Config.ButtonIconId.Description": "Die Symbol-ID, die auf der Schaltfläche angezeigt werden soll, wenn keine Verbundenheit verfolgt wird. Verwende den Befehl \"/xldata icons\", um verfügbare Symbole zu durchsuchen und die richtige ID zu erhalten. Verwende ID 0, um das Symbol auszublenden.", + "Widget.Societies.Config.ButtonIconId.Description": "Die Symbol, die auf der Schaltfläche angezeigt werden soll, wenn keine Verbundenheit verfolgt wird.", "Widget.Societies.Config.MinItemsBeforeHorizontalView.Name": "Mindestanzahl von Freundesvölkern vor dem Umschalten auf die horizontale Ansicht", "Widget.Societies.Config.MinItemsBeforeHorizontalView.Description": "Das Popup-Menü kann in einer horizontalen oder vertikalen Layout angezeigt werden. Diese Einstellung bestimmt, wann das Layout auf ein horizontales Layout umschalten soll, um vertikalen Bildschirmplatz zu sparen.", "Widget.Societies.Config.PrimaryAction.Name": "Primäre Aktion", @@ -913,10 +914,10 @@ "Widget.CustomButton.Config.AltMode.Description": "Was soll passieren, wenn du diesen Button rechtsklickst? Ein Befehl steht für einen einzelnen Chatbefehl, während eine URL eine Webseite in deinem Standardbrowser öffnet.", "Widget.CustomButton.Config.AltCommand.Name": "Rechtsklick-Befehl oder Website-URL", "Widget.CustomButton.Config.AltCommand.Description": "Je nach ausgewähltem Modus wird der angegebene Befehl ausgeführt, wenn der Button rechtsgeklickt wird, z.B. /tanzen., oder eine Webseite in deinem Standardbrowser geöffnet, wenn der URL-Modus ausgewählt ist.", - "Widget.CustomButton.Config.LeftIconId.Name": "Linke Symbol-ID", - "Widget.CustomButton.Config.LeftIconId.Description": "Die Symbol-ID, die auf der linken Seite der Schaltfläche angezeigt werden soll. Verwende den Befehl \"/xldata icons\", um verfügbare Symbole zu durchsuchen und die korrekte ID zu erhalten. Verwende die ID 0, um das Symbol zu verbergen.", - "Widget.CustomButton.Config.RightIconId.Name": "Rechte Symbol-ID", - "Widget.CustomButton.Config.RightIconId.Description": "Die Symbol-ID, die auf der rechten Seite der Schaltfläche angezeigt werden soll. Verwende den Befehl \"/xldata icons\", um verfügbare Symbole zu durchsuchen und die korrekte ID zu erhalten. Verwende die ID 0, um das Symbol zu verbergen.", + "Widget.CustomButton.Config.LeftIconId.Name": "Linke Symbol", + "Widget.CustomButton.Config.LeftIconId.Description": "Die Symbol, die auf der linken Seite der Schaltfläche angezeigt werden soll.", + "Widget.CustomButton.Config.RightIconId.Name": "Rechte Symbol", + "Widget.CustomButton.Config.RightIconId.Description": "Die Symbol, die auf der rechten Seite der Schaltfläche angezeigt werden soll.", "Widget.CustomDeliveries.Name": "Wunschlieferungen", "Widget.CustomDeliveries.Description": "Zeigt den aktuellen Status der Wunschlieferungen an.", "Widget.CustomDeliveries.AllowanceStatus": "Wöchentliche Lieferungen: {0}", @@ -927,7 +928,7 @@ "Widget.CustomDeliveries.Config.ButtonLabel.Name": "Schaltflächenbeschriftung", "Widget.CustomDeliveries.Config.ButtonLabel.Description": "Der Text, der auf der Schaltfläche angezeigt wird.", "Widget.CustomDeliveries.Config.ButtonIcon.Name": "Schaltflächensymbol-ID", - "Widget.CustomDeliveries.Config.ButtonIcon.Description": "Die Symbol-ID, die auf der Schaltfläche angezeigt werden soll. Verwende den Befehl \"/xldata icons\", um verfügbare Symbole zu durchsuchen und die richtige ID zu erhalten. Verwende die ID 0, um das Symbol auszublenden.", + "Widget.CustomDeliveries.Config.ButtonIcon.Description": "Die Symbol, die auf der Schaltfläche angezeigt werden soll.", "Widget.CustomDeliveries.Config.PrimaryAction.Name": "Primäre Aktion", "Widget.CustomDeliveries.Config.PrimaryAction.Description": "Die Aktion, die beim Klicken auf einen Kunden im Popup-Menü ausgeführt werden soll.", "Widget.CustomDeliveries.Config.PrimaryAction.Option.Track": "Verfolgen / Nicht verfolgen", @@ -950,18 +951,18 @@ "Widget.CustomMenu.Config.IconYOffset.Description": "Der vertikale Versatz des Symbols vom Zentrum des Widgets in Pixeln. Positive Werte bewegen das Symbol nach unten, negative Werte bewegen das Symbol nach oben.", "Widget.CustomMenu.Config.TextYOffset.Name": "Vertikaler Textversatz", "Widget.CustomMenu.Config.TextYOffset.Description": "Der vertikale Versatz des Textes vom Zentrum des Widgets in Pixeln. Positive Werte bewegen den Text nach unten, negative Werte bewegen den Text nach oben.", - "Widget.CustomMenu.Config.LeftIconId.Name": "Linke Symbol-ID", - "Widget.CustomMenu.Config.LeftIconId.Description": "Die Symbol-ID, die auf der linken Seite der Schaltfläche angezeigt werden soll. Verwende den Befehl \"/xldata icons\", um verfügbare Symbole zu durchsuchen und die richtige ID zu erhalten. Verwende die ID 0, um das Symbol auszublenden.", - "Widget.CustomMenu.Config.RightIconId.Name": "Rechte Symbol-ID", - "Widget.CustomMenu.Config.RightIconId.Description": "Die Symbol-ID, die auf der rechten Seite der Schaltfläche angezeigt werden soll. Verwende den Befehl \"/xldata icons\", um verfügbare Symbole zu durchsuchen und die richtige ID zu erhalten. Verwende die ID 0, um das Symbol auszublenden.", + "Widget.CustomMenu.Config.LeftIconId.Name": "Linke Symbol", + "Widget.CustomMenu.Config.LeftIconId.Description": "Die Symbol, die auf der linken Seite der Schaltfläche angezeigt werden soll.", + "Widget.CustomMenu.Config.RightIconId.Name": "Rechte Symbol", + "Widget.CustomMenu.Config.RightIconId.Description": "Die Symbol, die auf der rechten Seite der Schaltfläche angezeigt werden soll.", "Widget.CustomMenu.Config.DesaturateMenuIcons.Name": "Menüelement-Symbole entsättigen", "Widget.CustomMenu.Config.DesaturateMenuIcons.Description": "Entsättigt die Symbole im Menü, sodass sie in Graustufen erscheinen.", "Widget.CustomMenu.Config.ButtonLabel.Name": "Schaltflächenbeschriftung", "Widget.CustomMenu.Config.ButtonLabel.Description": "Der Text, der auf der Schaltfläche angezeigt wird. Diese Option wird ignoriert, wenn der Item-Modus ausgewählt ist und eine gültige Gegenstands-ID im Befehlsfeld angegeben wird.", "Widget.CustomMenu.Config.ButtonAltLabel.Name": "Schaltflächensub-Beschriftung", "Widget.CustomMenu.Config.ButtonAltLabel.Description": "Eine Sub-Beschriftung, die auf der rechten Seite des Menüpunkts angezeigt wird, typischerweise für Gegenstandsanzahlen, Verknüpfungen usw. Diese Option wird ignoriert, wenn der Item-Modus ausgewählt ist und eine gültige Gegenstands-ID im Befehlsfeld angegeben wird.", - "Widget.CustomMenu.Config.ButtonIconId.Name": "Symbol-ID", - "Widget.CustomMenu.Config.ButtonIconId.Description": "Die Symbol-ID, die auf der Schaltfläche angezeigt werden soll. Verwende den Befehl \"/xldata icons\", um verfügbare Symbole zu durchsuchen und die richtige ID zu erhalten. Verwende die ID 0, um das Symbol auszublenden. Diese Option wird ignoriert, wenn der Item-Modus ausgewählt ist und eine gültige Item-ID im Befehlsfeld angegeben wird.", + "Widget.CustomMenu.Config.ButtonIconId.Name": "Symbol", + "Widget.CustomMenu.Config.ButtonIconId.Description": "Die Symbol, die auf der Schaltfläche angezeigt werden soll.", "Widget.CustomMenu.Config.ButtonIconColor.Name": "Symbolfarbe", "Widget.CustomMenu.Config.ButtonIconColor.Description": "Eine benutzerdefinierte Farbmaske, die auf das Symbol dieses Menüpunkts angewendet wird. Verwende reines Weiß (#FFFFFF), um die Farbmaske effektiv zu deaktivieren und die Originalfarben des Symbols zu verwenden.", "Widget.CustomMenu.Config.ButtonCommand.Name": "Befehl, URL oder Item-ID", @@ -992,8 +993,8 @@ "Widget.EmoteList.Config.Label.Name": "Schaltflächenbeschriftung", "Widget.EmoteList.Config.Label.Description": "Der Text, der auf der Schaltfläche angezeigt wird.", "Widget.EmoteList.Config.Label.Default": "Emotes", - "Widget.EmoteList.Config.IconId.Name": "Icon-ID", - "Widget.EmoteList.Config.IconId.Description": "Die Icon-ID, die auf der Schaltfläche angezeigt werden soll. Verwende den Befehl \"/xldata icons\", um verfügbare Icons zu durchsuchen und die korrekte ID zu erhalten. Verwende die ID 0, um das Icon auszublenden.", + "Widget.EmoteList.Config.IconId.Name": "Icon", + "Widget.EmoteList.Config.IconId.Description": "Die Icon, die auf der Schaltfläche angezeigt werden soll.", "Widget.EmoteList.Config.CategoryName.Name": "Kategorie #{0} Name", "Widget.EmoteList.Config.CategoryName.Description": "Der Name der Kategorie. Wenn dieses Feld leer gelassen wird, wird die Kategorie im Popup deaktiviert (versteckt).", "Widget.EmoteList.PickerWindow.Title": "Emote-Auswahl", @@ -1042,7 +1043,7 @@ "Widget.ShortcutPanel.Config.ButtonLabel.Name": "Beschriftung der Schaltfläche", "Widget.ShortcutPanel.Config.ButtonLabel.Description": "Der Text, der auf der Toolbar-Schaltfläche angezeigt wird.", "Widget.ShortcutPanel.Config.ButtonIconId.Name": "Schaltflächensymbol-ID", - "Widget.ShortcutPanel.Config.ButtonIconId.Description": "Die ID des Symbols, das auf der Schaltfläche angezeigt werden soll. Verwende den Befehl \"/xldata icons\", um verfügbare Symbole zu durchsuchen und die richtige ID zu erhalten.", + "Widget.ShortcutPanel.Config.ButtonIconId.Description": "Die ID des Symbols, das auf der Schaltfläche angezeigt werden soll.", "Widget.ShortcutPanel.Config.CategoryName.Name": "Kategorie #{0} Name", "Widget.ShortcutPanel.Config.CategoryName.Description": "Der Name der Kategorie. Wenn dieses Feld leer bleibt, wird die Kategorie im Panel deaktiviert (ausgeblendet).", "Widget.ShortcutPanel.Config.NumRows.Name": "Anzahl der Zeilen", @@ -1088,10 +1089,10 @@ "Widget.UnifiedMainMenu.ContextMenu.Unpin": "Von Hauptmenü lösen", "Widget.UnifiedMainMenu.Config.Label.Name": "Schaltflächenbeschriftung", "Widget.UnifiedMainMenu.Config.Label.Description": "Der Text, der auf der Schaltfläche angezeigt wird.", - "Widget.UnifiedMainMenu.Config.IconId.Name": "Symbol-ID", - "Widget.UnifiedMainMenu.Config.IconId.Description": "Die Symbol-ID, die auf der Schaltfläche angezeigt werden soll. Verwende den Befehl \"/xldata icons\", um verfügbare Symbole zu durchsuchen und die richtige ID zu erhalten.", - "Widget.UnifiedMainMenu.Config.AvatarIconId.Name": "Avatar-Symbol-ID", - "Widget.UnifiedMainMenu.Config.AvatarIconId.Description": "Die Symbol-ID, die im Kopf des Menüs angezeigt werden soll. Verwende den Befehl \"/xldata icons\", um verfügbare Symbole zu durchsuchen und die richtige ID zu erhalten.", + "Widget.UnifiedMainMenu.Config.IconId.Name": "Symbol", + "Widget.UnifiedMainMenu.Config.IconId.Description": "Die Symbol, die auf der Schaltfläche angezeigt werden soll.", + "Widget.UnifiedMainMenu.Config.AvatarIconId.Name": "Avatar-Symbol", + "Widget.UnifiedMainMenu.Config.AvatarIconId.Description": "Die Symbol, die im Kopf des Menüs angezeigt werden soll.", "Widget.UnifiedMainMenu.Config.FixedMenuHeight.Name": "Feste Menühöhe", "Widget.UnifiedMainMenu.Config.FixedMenuHeight.Description": "Stellt die Höhe des Popup-Menüs auf den angegebenen Wert ein. Wenn das Menü mehr Elemente enthält, als in die angegebene Höhe passen, wird das Menü scrollbar.", "Widget.UnifiedMainMenu.Config.MainMenuWidth.Name": "Hauptmenübreite", @@ -1123,6 +1124,19 @@ "Widget.WalkingIndicator.Description": "Zeigt einen Indikator an, der erscheint, wenn dein Charakter geht statt rennt.", "Widget.WalkingIndicator.Config.OnlyShowWhenWalking.Name": "Nur anzeigen, wenn zu Fuß", "Widget.WalkingIndicator.Config.OnlyShowWhenWalking.Description": "Zeigt den Gehindikator nur an, wenn dein Charakter zu Fuß geht, und verbirgt ihn, wenn er rennt.", + "Window.IconPicker.Title": "Icon-Auswahl", + "Window.IconPicker.IconId": "Icon", + "Window.IconPicker.Category": "Kategorie", + "Window.IconPicker.Category.General": "Allgemein", + "Window.IconPicker.Category.Jobs": "Klasse/Job", + "Window.IconPicker.Category.Quests": "Quests", + "Window.IconPicker.Category.Avatars": "Avatare & Gesichter", + "Window.IconPicker.Category.Rewards": "Währungen & Belohnungen", + "Window.IconPicker.Category.MapMarkers": "Kartenmarkierungen & Symbole", + "Window.IconPicker.Category.Shapes": "Formen & Effekte", + "Window.IconPicker.Category.Mounts": "Reittiere", + "Window.IconPicker.Category.Minions": "Begleiter", + "Window.IconPicker.Category.Emotes": "Emotes", "ColorGroup.Window.Name": "Fensterfarben", "ColorGroup.Window.Description": "Farben, die für die Fensterdekoration verwendet werden.", "ColorGroup.Input.Name": "Eingabesteuerungen-Farben", diff --git a/Umbra/i18n/en.json b/Umbra/i18n/en.json index 6153792d..379d6dc3 100644 --- a/Umbra/i18n/en.json +++ b/Umbra/i18n/en.json @@ -10,6 +10,7 @@ "Apply": "Apply", "Copy": "Copy", "Paste": "Paste", + "Undo": "Undo", "Experience": "EXP", "Rested": "Rested", "Revert": "Revert to default value", @@ -624,8 +625,8 @@ "Widget.MainMenu.Description": "Shows a button that opens the configured main menu.", "Widget.MainMenu.Config.Category.Name": "Menu category", "Widget.MainMenu.Config.Category.Description": "The category of the main menu that should be opened when the button is clicked.", - "Widget.MainMenu.Config.CustomIconId.Name": "Custom icon ID", - "Widget.MainMenu.Config.CustomIconId.Description": "The custom icon ID that should be used for the main menu button. This can be used to override the default icon. Use the command \"/xldata icons\" to browse available icons to get the correct ID. Use ID 0 to use the default icon.", + "Widget.MainMenu.Config.CustomIconId.Name": "Custom icon", + "Widget.MainMenu.Config.CustomIconId.Description": "The custom icon that should be used for the main menu button. This can be used to override the default icon.", "Widget.MainMenu.Config.ShowItemIcons.Name": "Show item icons in the menu", "Widget.MainMenu.Config.ShowItemIcons.Description": "Whether to show icons in the popup menu for items that have icons associated with them.", "Widget.MainMenu.Config.GrayscaleIcons.Name": "Desaturate menu icons", @@ -666,7 +667,7 @@ "Widget.DynamicMenu.Config.ButtonTooltip.Name": "Button tooltip", "Widget.DynamicMenu.Config.ButtonTooltip.Description": "The tooltip that is displayed when hovering over the button that opens the dynamic menu.", "Widget.DynamicMenu.Config.ButtonIcon.Name": "Button icon", - "Widget.DynamicMenu.Config.ButtonIcon.Description": "The icon that is displayed on the button. Use the command \"/xldata icons\" to browse available icons to get the correct ID.", + "Widget.DynamicMenu.Config.ButtonIcon.Description": "The icon that is displayed on the button.", "Widget.DynamicMenu.Config.EditModeEnabled.Name": "Enable edit mode", "Widget.DynamicMenu.Config.EditModeEnabled.Description": "Enables a placeholder item at the bottom of the menu which opens a context menu to add new items to the menu.", "Widget.DynamicMenu.Config.MenuEntryHeight.Name": "Menu entry height", @@ -689,8 +690,8 @@ "Widget.DynamicMenu.CustomItemEditor.Title": "Edit Custom Item", "Widget.DynamicMenu.CustomItemEditor.Label.Name": "Name", "Widget.DynamicMenu.CustomItemEditor.Label.Description": "The name of the custom item that is displayed in the dynamic menu.", - "Widget.DynamicMenu.CustomItemEditor.Icon.Name": "Icon ID", - "Widget.DynamicMenu.CustomItemEditor.Icon.Description": "The icon ID that is displayed next to the custom item in the dynamic menu. Use the command \"/xldata icons\" to browse available icons to get the correct ID.", + "Widget.DynamicMenu.CustomItemEditor.Icon.Name": "Icon", + "Widget.DynamicMenu.CustomItemEditor.Icon.Description": "The icon that is displayed next to the custom item in the dynamic menu.", "Widget.DynamicMenu.CustomItemEditor.Type.Name": "Invocation Type", "Widget.DynamicMenu.CustomItemEditor.Type.Description": "The type of invocation that is used when the custom item is clicked.", "Widget.DynamicMenu.CustomItemEditor.Type.Option.ChatCommand": "Chat Command", @@ -817,7 +818,7 @@ "Widget.Societies.Config.ButtonLabel.Name": "Button label (if not tracking)", "Widget.Societies.Config.ButtonLabel.Description": "The label that should be displayed on the widget button when no Societal Relations are being tracked.", "Widget.Societies.Config.ButtonIconId.Name": "Button icon type (if not tracking)", - "Widget.Societies.Config.ButtonIconId.Description": "The icon ID that should be displayed on the button when no Societal Relations are being tracked. Use the command \"/xldata icons\" to browse available icons to get the correct ID. Use ID 0 to hide the icon.", + "Widget.Societies.Config.ButtonIconId.Description": "The icon that should be displayed on the button when no Societal Relations are being tracked.", "Widget.Societies.Config.MinItemsBeforeHorizontalView.Name": "Minimum amount of unlocked societies before switching to horizontal view", "Widget.Societies.Config.MinItemsBeforeHorizontalView.Description": "The popup menu can be displayed in a horizontal or vertical layout. This setting determines when the layout should switch to a horizontal layout to preserve vertical screen space.", "Widget.Societies.Config.PrimaryAction.Name": "Primary action", @@ -913,10 +914,10 @@ "Widget.CustomButton.Config.AltMode.Description": "What to do when right-clicking this button. A command represents a single chat command, while a URL will open a website in your default browser.", "Widget.CustomButton.Config.AltCommand.Name": "Right-click command or website URL", "Widget.CustomButton.Config.AltCommand.Description": "Depending on the selected mode, invokes the given command that is executed when the button is right-clicked. For example: /dance., or opens a website in your default browser if the URL mode is selected.", - "Widget.CustomButton.Config.LeftIconId.Name": "Left icon ID", - "Widget.CustomButton.Config.LeftIconId.Description": "The icon ID that should be displayed on the left side of the button. Use the command \"/xldata icons\" to browse available icons to get the correct ID. Use ID 0 to hide the icon.", - "Widget.CustomButton.Config.RightIconId.Name": "Right icon ID", - "Widget.CustomButton.Config.RightIconId.Description": "The icon ID that should be displayed on the right side of the button. Use the command \"/xldata icons\" to browse available icons to get the correct ID. Use ID 0 to hide the icon.", + "Widget.CustomButton.Config.LeftIconId.Name": "Left icon", + "Widget.CustomButton.Config.LeftIconId.Description": "The icon that should be displayed on the left side of the button.", + "Widget.CustomButton.Config.RightIconId.Name": "Right icon", + "Widget.CustomButton.Config.RightIconId.Description": "The icon that should be displayed on the right side of the button.", "Widget.CustomDeliveries.Name": "Custom Deliveries", "Widget.CustomDeliveries.Description": "Shows the current status of your custom deliveries.", "Widget.CustomDeliveries.AllowanceStatus": "Weekly allowance remaining: {0}", @@ -926,8 +927,8 @@ "Widget.CustomDeliveries.ContextMenu.Teleport": "Teleport to a nearby Aetheryte", "Widget.CustomDeliveries.Config.ButtonLabel.Name": "Button label", "Widget.CustomDeliveries.Config.ButtonLabel.Description": "The text that is displayed on the button.", - "Widget.CustomDeliveries.Config.ButtonIcon.Name": "Button icon ID", - "Widget.CustomDeliveries.Config.ButtonIcon.Description": "The icon ID that should be displayed on the button. Use the command \"/xldata icons\" to browse available icons to get the correct ID. Use ID 0 to hide the icon.", + "Widget.CustomDeliveries.Config.ButtonIcon.Name": "Button icon", + "Widget.CustomDeliveries.Config.ButtonIcon.Description": "The icon that should be displayed on the button.", "Widget.CustomDeliveries.Config.PrimaryAction.Name": "Primary action", "Widget.CustomDeliveries.Config.PrimaryAction.Description": "The action that should be executed when clicking an NPC in the popup menu.", "Widget.CustomDeliveries.Config.PrimaryAction.Option.Track": "Track / Untrack", @@ -950,18 +951,18 @@ "Widget.CustomMenu.Config.IconYOffset.Description": "The vertical offset of the icon from the center of the widget in pixels. Positive values move the icon down, negative values move the icon up.", "Widget.CustomMenu.Config.TextYOffset.Name": "Text vertical offset", "Widget.CustomMenu.Config.TextYOffset.Description": "The vertical offset of the text from the center of the widget in pixels. Positive values move the text down, negative values move the text up.", - "Widget.CustomMenu.Config.LeftIconId.Name": "Left icon ID", - "Widget.CustomMenu.Config.LeftIconId.Description": "The icon ID that should be displayed on the left side of the button. Use the command \"/xldata icons\" to browse available icons to get the correct ID. Use ID 0 to hide the icon.", - "Widget.CustomMenu.Config.RightIconId.Name": "Right icon ID", - "Widget.CustomMenu.Config.RightIconId.Description": "The icon ID that should be displayed on the right side of the button. Use the command \"/xldata icons\" to browse available icons to get the correct ID. Use ID 0 to hide the icon.", + "Widget.CustomMenu.Config.LeftIconId.Name": "Left icon", + "Widget.CustomMenu.Config.LeftIconId.Description": "The icon that should be displayed on the left side of the button.", + "Widget.CustomMenu.Config.RightIconId.Name": "Right icon", + "Widget.CustomMenu.Config.RightIconId.Description": "The icon that should be displayed on the right side of the button.", "Widget.CustomMenu.Config.DesaturateMenuIcons.Name": "Desaturate menu item icons", "Widget.CustomMenu.Config.DesaturateMenuIcons.Description": "Desaturates the icons in the menu to make it appear in grayscale.", "Widget.CustomMenu.Config.ButtonLabel.Name": "Button label", "Widget.CustomMenu.Config.ButtonLabel.Description": "The text that is displayed on the button. This option is ignored when the Item-mode is selected and a valid item ID is given in the command field.", "Widget.CustomMenu.Config.ButtonAltLabel.Name": "Button sub-label", "Widget.CustomMenu.Config.ButtonAltLabel.Description": "A sub-label that is displayed on the right side on the menu item, typically used for item counts, shortcuts, etc. This option is ignored when the Item-mode is selected and a valid item ID is given in the command field.", - "Widget.CustomMenu.Config.ButtonIconId.Name": "Icon ID", - "Widget.CustomMenu.Config.ButtonIconId.Description": "The icon ID that should be displayed on the button. Use the command \"/xldata icons\" to browse available icons to get the correct ID. Use ID 0 to hide the icon. This option is ignored when the Item-mode is selected and a valid item ID is given in the command field.", + "Widget.CustomMenu.Config.ButtonIconId.Name": "Icon", + "Widget.CustomMenu.Config.ButtonIconId.Description": "The icon that should be displayed on the button. This option is ignored when the Item-mode is selected and a valid item ID is given in the command field.", "Widget.CustomMenu.Config.ButtonIconColor.Name": "Icon color", "Widget.CustomMenu.Config.ButtonIconColor.Description": "A custom color mask to apply to the icon of this menu item. Use solid white (#FFFFFF) to effectively disable the color mask and use the icon's original colors.", "Widget.CustomMenu.Config.ButtonCommand.Name": "Command, URL or Item ID", @@ -992,8 +993,8 @@ "Widget.EmoteList.Config.Label.Name": "Button label", "Widget.EmoteList.Config.Label.Description": "The text that is displayed on the button.", "Widget.EmoteList.Config.Label.Default": "Emotes", - "Widget.EmoteList.Config.IconId.Name": "Icon ID", - "Widget.EmoteList.Config.IconId.Description": "The icon ID that should be displayed on the button. Use the command \"/xldata icons\" to browse available icons to get the correct ID. Use ID 0 to hide the icon.", + "Widget.EmoteList.Config.IconId.Name": "Icon", + "Widget.EmoteList.Config.IconId.Description": "The icon that should be displayed on the button.", "Widget.EmoteList.Config.CategoryName.Name": "Category #{0} name", "Widget.EmoteList.Config.CategoryName.Description": "The name of the category. Leaving this field empty will disable (hide) the category from the popup.", "Widget.EmoteList.PickerWindow.Title": "Emote Picker", @@ -1041,8 +1042,8 @@ "Widget.ShortcutPanel.Description": "Shows a customizable panel with a grid of slots that can be assigned to items, mounts, minions and more. The grid is resizable in the settings and can hold up to 4 configurable categories.", "Widget.ShortcutPanel.Config.ButtonLabel.Name": "Button label", "Widget.ShortcutPanel.Config.ButtonLabel.Description": "The text that is displayed on the toolbar button.", - "Widget.ShortcutPanel.Config.ButtonIconId.Name": "Button icon ID", - "Widget.ShortcutPanel.Config.ButtonIconId.Description": "The icon ID that should be displayed on the button. Use the command \"/xldata icons\" to browse available icons to get the correct ID.", + "Widget.ShortcutPanel.Config.ButtonIconId.Name": "Button icon", + "Widget.ShortcutPanel.Config.ButtonIconId.Description": "The icon that should be displayed on the button.", "Widget.ShortcutPanel.Config.CategoryName.Name": "Category #{0} name", "Widget.ShortcutPanel.Config.CategoryName.Description": "The name of the category. Leaving this field empty will disable (hide) the category from the panel.", "Widget.ShortcutPanel.Config.NumRows.Name": "Number of rows", @@ -1088,10 +1089,10 @@ "Widget.UnifiedMainMenu.ContextMenu.Unpin": "Unpin from main menu", "Widget.UnifiedMainMenu.Config.Label.Name": "Button label", "Widget.UnifiedMainMenu.Config.Label.Description": "The text that is displayed on the button.", - "Widget.UnifiedMainMenu.Config.IconId.Name": "Icon ID", - "Widget.UnifiedMainMenu.Config.IconId.Description": "The icon ID that should be displayed on the button. Use the command \"/xldata icons\" to browse available icons to get the correct ID.", - "Widget.UnifiedMainMenu.Config.AvatarIconId.Name": "Avatar icon ID", - "Widget.UnifiedMainMenu.Config.AvatarIconId.Description": "The icon ID that should be displayed in the header of the menu. Use the command \"/xldata icons\" to browse available icons to get the correct ID.", + "Widget.UnifiedMainMenu.Config.IconId.Name": "Icon", + "Widget.UnifiedMainMenu.Config.IconId.Description": "The icon that should be displayed on the button.", + "Widget.UnifiedMainMenu.Config.AvatarIconId.Name": "Avatar icon", + "Widget.UnifiedMainMenu.Config.AvatarIconId.Description": "The icon that should be displayed in the header of the menu.", "Widget.UnifiedMainMenu.Config.FixedMenuHeight.Name": "Fixed menu height", "Widget.UnifiedMainMenu.Config.FixedMenuHeight.Description": "Sets the height of the popup menu to the given value. If the menu has more items than can fit in the given height, the menu will become scrollable.", "Widget.UnifiedMainMenu.Config.MainMenuWidth.Name": "Main menu width", @@ -1123,6 +1124,19 @@ "Widget.WalkingIndicator.Description": "Shows an indicator that appears when you are walking instead of running. Click the widget to toggle between walking and running.", "Widget.WalkingIndicator.Config.OnlyShowWhenWalking.Name": "Only show when walking", "Widget.WalkingIndicator.Config.OnlyShowWhenWalking.Description": "Only shows the walking indicator when you are walking, and hides it when you are running.", + "Window.IconPicker.Title": "Icon Picker", + "Window.IconPicker.IconId": "Icon Id", + "Window.IconPicker.Category": "Category", + "Window.IconPicker.Category.General": "General", + "Window.IconPicker.Category.Jobs": "Class/Job", + "Window.IconPicker.Category.Quests": "Quests", + "Window.IconPicker.Category.Avatars": "Avatars & Faces", + "Window.IconPicker.Category.Rewards": "Currencies & Rewards", + "Window.IconPicker.Category.MapMarkers": "Map Markers & Symbols", + "Window.IconPicker.Category.Shapes": "Shapes & Effects", + "Window.IconPicker.Category.Mounts": "Mounts", + "Window.IconPicker.Category.Minions": "Minions", + "Window.IconPicker.Category.Emotes": "Emotes", "ColorGroup.Window.Name": "Window Colors", "ColorGroup.Window.Description": "Colors that are used for the window decorations.", "ColorGroup.Input.Name": "Input Controls Colors", diff --git a/Umbra/i18n/fr.json b/Umbra/i18n/fr.json index 4c9115e8..e9659de4 100644 --- a/Umbra/i18n/fr.json +++ b/Umbra/i18n/fr.json @@ -10,6 +10,7 @@ "Apply": "Appliquer", "Copy": "Copier", "Paste": "Coller", + "Undo": "Annuler", "Experience": "EXP", "Rested": "Reposé", "Revert": "Revenir à la valeur par défaut", @@ -625,7 +626,7 @@ "Widget.MainMenu.Config.Category.Name": "Catégorie de menu", "Widget.MainMenu.Config.Category.Description": "La catégorie du menu principal qui doit être ouverte lorsque le bouton est cliqué.", "Widget.MainMenu.Config.CustomIconId.Name": "Identifiant d'icône personnalisé", - "Widget.MainMenu.Config.CustomIconId.Description": "L'identifiant d'icône personnalisé qui doit être utilisé pour le bouton du menu principal. Cela peut être utilisé pour remplacer l'icône par défaut. Utilisez la commande \"/xldata icons\" pour parcourir les icônes disponibles et obtenir l'identifiant correct. Utilisez l'identifiant 0 pour utiliser l'icône par défaut.", + "Widget.MainMenu.Config.CustomIconId.Description": "L'identifiant d'icône personnalisé qui doit être utilisé pour le bouton du menu principal. Cela peut être utilisé pour remplacer l'icône par défaut.", "Widget.MainMenu.Config.ShowItemIcons.Name": "Afficher les icônes d'élément dans le menu", "Widget.MainMenu.Config.ShowItemIcons.Description": "Indique s'il faut afficher des icônes dans le menu contextuel pour les éléments qui leur sont associés.", "Widget.MainMenu.Config.GrayscaleIcons.Name": "Icônes de menu en niveaux de gris", @@ -666,7 +667,7 @@ "Widget.DynamicMenu.Config.ButtonTooltip.Name": "Infobulle du bouton", "Widget.DynamicMenu.Config.ButtonTooltip.Description": "L'infobulle qui s'affiche lorsque tu survoles le bouton qui ouvre le menu dynamique.", "Widget.DynamicMenu.Config.ButtonIcon.Name": "Icône du bouton", - "Widget.DynamicMenu.Config.ButtonIcon.Description": "L'icône qui s'affiche sur le bouton. Utilise la commande \"/xldata icons\" pour parcourir les icônes disponibles et obtenir l'ID correct.", + "Widget.DynamicMenu.Config.ButtonIcon.Description": "L'icône qui s'affiche sur le bouton.", "Widget.DynamicMenu.Config.EditModeEnabled.Name": "Activer le mode édition", "Widget.DynamicMenu.Config.EditModeEnabled.Description": "Active un élément de substitution en bas du menu, qui ouvre un menu contextuel pour ajouter de nouveaux éléments au menu.", "Widget.DynamicMenu.Config.MenuEntryHeight.Name": "Hauteur de l'entrée de menu", @@ -689,8 +690,8 @@ "Widget.DynamicMenu.CustomItemEditor.Title": "Modifier l'élément personnalisé", "Widget.DynamicMenu.CustomItemEditor.Label.Name": "Nom", "Widget.DynamicMenu.CustomItemEditor.Label.Description": "Le nom de l'élément personnalisé qui est affiché dans le menu dynamique.", - "Widget.DynamicMenu.CustomItemEditor.Icon.Name": "ID d'icône", - "Widget.DynamicMenu.CustomItemEditor.Icon.Description": "L'ID de l'icône affichée à côté de l'élément personnalisé dans le menu dynamique. Utilise la commande \"/xldata icons\" pour parcourir les icônes disponibles et obtenir le bon ID.", + "Widget.DynamicMenu.CustomItemEditor.Icon.Name": "l'Icône", + "Widget.DynamicMenu.CustomItemEditor.Icon.Description": "L'icône affichée à côté de l'élément personnalisé dans le menu dynamique.", "Widget.DynamicMenu.CustomItemEditor.Type.Name": "Type d'invocation", "Widget.DynamicMenu.CustomItemEditor.Type.Description": "Le type d'invocation utilisé lorsque l'élément personnalisé est cliqué.", "Widget.DynamicMenu.CustomItemEditor.Type.Option.ChatCommand": "Commande de chat", @@ -817,7 +818,7 @@ "Widget.Societies.Config.ButtonLabel.Name": "Libellé du bouton (si non suivi)", "Widget.Societies.Config.ButtonLabel.Description": "Le libellé qui doit être affiché sur le bouton du widget lorsqu'aucune relation sociétale n'est suivie.", "Widget.Societies.Config.ButtonIconId.Name": "Type d'icône du bouton (si non suivi)", - "Widget.Societies.Config.ButtonIconId.Description": "L'ID de l'icône qui doit être affichée sur le bouton lorsqu'aucune relation sociétale n'est suivie. Utilisez la commande \"/xldata icons\" pour parcourir les icônes disponibles afin d'obtenir l'ID correcte. Utilisez l'ID 0 pour masquer l'icône.", + "Widget.Societies.Config.ButtonIconId.Description": "L'icône qui doit être affichée sur le bouton lorsqu'aucune relation sociétale n'est suivie.", "Widget.Societies.Config.MinItemsBeforeHorizontalView.Name": "Nombre minimum de sociétés débloquées avant de passer à la vue horizontale", "Widget.Societies.Config.MinItemsBeforeHorizontalView.Description": "Le menu contextuel peut être affiché dans une disposition horizontale ou verticale. Ce paramètre détermine quand la disposition doit passer à une disposition horizontale pour préserver l'espace vertical de l'écran.", "Widget.Societies.Config.PrimaryAction.Name": "Action principale", @@ -914,9 +915,9 @@ "Widget.CustomButton.Config.AltCommand.Name": "Commande clic droit ou URL de site web", "Widget.CustomButton.Config.AltCommand.Description": "Selon le mode sélectionné, exécute la commande donnée lorsque le bouton est cliqué avec le bouton droit, par exemple : /danser., ou ouvre un site web dans ton navigateur par défaut si le mode URL est sélectionné.", "Widget.CustomButton.Config.LeftIconId.Name": "ID de l'icône de gauche", - "Widget.CustomButton.Config.LeftIconId.Description": "L'ID de l'icône qui doit être affichée sur le côté gauche du bouton. Utilisez la commande \"/xldata icons\" pour parcourir les icônes disponibles et obtenir le bon ID. Utilisez l'ID 0 pour masquer l'icône.", + "Widget.CustomButton.Config.LeftIconId.Description": "L'icône qui doit être affichée sur le côté gauche du bouton.", "Widget.CustomButton.Config.RightIconId.Name": "ID de l'icône de droite", - "Widget.CustomButton.Config.RightIconId.Description": "L'ID de l'icône qui doit être affichée sur le côté droit du bouton. Utilisez la commande \"/xldata icons\" pour parcourir les icônes disponibles et obtenir le bon ID. Utilisez l'ID 0 pour masquer l'icône.", + "Widget.CustomButton.Config.RightIconId.Description": "L'icône qui doit être affichée sur le côté droit du bouton.", "Widget.CustomDeliveries.Name": "Livraisons personnalisées", "Widget.CustomDeliveries.Description": "Affiche le statut actuel de vos livraisons personnalisées.", "Widget.CustomDeliveries.AllowanceStatus": "Allocation hebdomadaire restante : {0}", @@ -927,7 +928,7 @@ "Widget.CustomDeliveries.Config.ButtonLabel.Name": "Étiquette du bouton", "Widget.CustomDeliveries.Config.ButtonLabel.Description": "Le texte qui est affiché sur le bouton.", "Widget.CustomDeliveries.Config.ButtonIcon.Name": "ID de l'icône du bouton", - "Widget.CustomDeliveries.Config.ButtonIcon.Description": "L'ID de l'icône qui doit être affichée sur le bouton. Utilisez la commande \"/xldata icons\" pour parcourir les icônes disponibles et obtenir l'ID correcte. Utilisez l'ID 0 pour masquer l'icône.", + "Widget.CustomDeliveries.Config.ButtonIcon.Description": "L'icône qui doit être affichée sur le bouton.", "Widget.CustomDeliveries.Config.PrimaryAction.Name": "Action principale", "Widget.CustomDeliveries.Config.PrimaryAction.Description": "L'action qui doit être exécutée en cliquant sur un PNJ dans le menu contextuel.", "Widget.CustomDeliveries.Config.PrimaryAction.Option.Track": "Suivre / Ne pas suivre", @@ -951,9 +952,9 @@ "Widget.CustomMenu.Config.TextYOffset.Name": "Décalage vertical du texte", "Widget.CustomMenu.Config.TextYOffset.Description": "Le décalage vertical du texte par rapport au centre du widget en pixels. Les valeurs positives déplacent le texte vers le bas, les valeurs négatives déplacent le texte vers le haut.", "Widget.CustomMenu.Config.LeftIconId.Name": "ID de l'icône gauche", - "Widget.CustomMenu.Config.LeftIconId.Description": "L'ID de l'icône qui doit être affichée sur le côté gauche du bouton. Utilisez la commande \"/xldata icons\" pour parcourir les icônes disponibles et obtenir l'ID correcte. Utilisez l'ID 0 pour masquer l'icône.", + "Widget.CustomMenu.Config.LeftIconId.Description": "L'icône qui doit être affichée sur le côté gauche du bouton.", "Widget.CustomMenu.Config.RightIconId.Name": "ID de l'icône droite", - "Widget.CustomMenu.Config.RightIconId.Description": "L'ID de l'icône qui doit être affichée sur le côté droit du bouton. Utilisez la commande \"/xldata icons\" pour parcourir les icônes disponibles et obtenir l'ID correcte. Utilisez l'ID 0 pour masquer l'icône.", + "Widget.CustomMenu.Config.RightIconId.Description": "L'icône qui doit être affichée sur le côté droit du bouton.", "Widget.CustomMenu.Config.DesaturateMenuIcons.Name": "Désaturer les icônes des éléments de menu", "Widget.CustomMenu.Config.DesaturateMenuIcons.Description": "Désature les icônes du menu pour les rendre en niveaux de gris.", "Widget.CustomMenu.Config.ButtonLabel.Name": "Étiquette du bouton", @@ -961,7 +962,7 @@ "Widget.CustomMenu.Config.ButtonAltLabel.Name": "Sous-étiquette du bouton", "Widget.CustomMenu.Config.ButtonAltLabel.Description": "Une sous-étiquette affichée sur le côté droit de l'élément de menu, généralement utilisée pour les comptes d'articles, les raccourcis, etc. Cette option est ignorée lorsque le mode Article est sélectionné et qu'un ID d'article valide est donné dans le champ de commande.", "Widget.CustomMenu.Config.ButtonIconId.Name": "ID de l'icône", - "Widget.CustomMenu.Config.ButtonIconId.Description": "L'ID de l'icône qui doit être affichée sur le bouton. Utilisez la commande \"/xldata icons\" pour parcourir les icônes disponibles et obtenir l'ID correcte. Utilisez l'ID 0 pour masquer l'icône. Cette option est ignorée lorsque le mode Article est sélectionné et qu'un ID d'article valide est donné dans le champ de commande.", + "Widget.CustomMenu.Config.ButtonIconId.Description": "L'icône qui doit être affichée sur le bouton. Cette option est ignorée lorsque le mode Article est sélectionné et qu'un ID d'article valide est donné dans le champ de commande.", "Widget.CustomMenu.Config.ButtonIconColor.Name": "Couleur de l'icône", "Widget.CustomMenu.Config.ButtonIconColor.Description": "Un masque de couleur personnalisé à appliquer à l'icône de cet élément de menu. Utilisez du blanc pur (#FFFFFF) pour désactiver efficacement le masque de couleur et utiliser les couleurs originales de l'icône.", "Widget.CustomMenu.Config.ButtonCommand.Name": "Commande, URL ou ID d'article", @@ -993,7 +994,7 @@ "Widget.EmoteList.Config.Label.Description": "Le texte affiché sur le bouton.", "Widget.EmoteList.Config.Label.Default": "Emotes", "Widget.EmoteList.Config.IconId.Name": "ID de l'icône", - "Widget.EmoteList.Config.IconId.Description": "L'ID de l'icône qui doit être affichée sur le bouton. Utilisez la commande \"/xldata icons\" pour parcourir les icônes disponibles et obtenir l'ID correcte. Utilisez l'ID 0 pour masquer l'icône.", + "Widget.EmoteList.Config.IconId.Description": "L'icône qui doit être affichée sur le bouton.", "Widget.EmoteList.Config.CategoryName.Name": "Nom de la catégorie #{0}", "Widget.EmoteList.Config.CategoryName.Description": "Le nom de la catégorie. Laisser ce champ vide désactivera (masquera) la catégorie dans le popup.", "Widget.EmoteList.PickerWindow.Title": "Sélecteur d'emotes", @@ -1042,7 +1043,7 @@ "Widget.ShortcutPanel.Config.ButtonLabel.Name": "Étiquette du bouton", "Widget.ShortcutPanel.Config.ButtonLabel.Description": "Le texte affiché sur le bouton de la barre d'outils.", "Widget.ShortcutPanel.Config.ButtonIconId.Name": "ID de l'icône du bouton", - "Widget.ShortcutPanel.Config.ButtonIconId.Description": "L'ID de l'icône qui doit être affichée sur le bouton. Utilisez la commande \"/xldata icons\" pour parcourir les icônes disponibles afin d'obtenir l'ID correcte.", + "Widget.ShortcutPanel.Config.ButtonIconId.Description": "L'icône qui doit être affichée sur le bouton.", "Widget.ShortcutPanel.Config.CategoryName.Name": "Nom de la catégorie #{0}", "Widget.ShortcutPanel.Config.CategoryName.Description": "Le nom de la catégorie. Laisser ce champ vide désactivera (masquera) la catégorie du panneau.", "Widget.ShortcutPanel.Config.NumRows.Name": "Nombre de lignes", @@ -1089,9 +1090,9 @@ "Widget.UnifiedMainMenu.Config.Label.Name": "Étiquette du bouton", "Widget.UnifiedMainMenu.Config.Label.Description": "Le texte affiché sur le bouton.", "Widget.UnifiedMainMenu.Config.IconId.Name": "ID de l'icône", - "Widget.UnifiedMainMenu.Config.IconId.Description": "L'ID de l'icône qui doit être affichée sur le bouton. Utilisez la commande \"/xldata icons\" pour parcourir les icônes disponibles et obtenir l'ID correcte.", + "Widget.UnifiedMainMenu.Config.IconId.Description": "L'icône qui doit être affichée sur le bouton.", "Widget.UnifiedMainMenu.Config.AvatarIconId.Name": "ID de l'icône d'avatar", - "Widget.UnifiedMainMenu.Config.AvatarIconId.Description": "L'ID de l'icône qui doit être affichée dans l'en-tête du menu. Utilisez la commande \"/xldata icons\" pour parcourir les icônes disponibles et obtenir l'ID correcte.", + "Widget.UnifiedMainMenu.Config.AvatarIconId.Description": "L'icône qui doit être affichée dans l'en-tête du menu.", "Widget.UnifiedMainMenu.Config.FixedMenuHeight.Name": "Hauteur fixe du menu", "Widget.UnifiedMainMenu.Config.FixedMenuHeight.Description": "Définit la hauteur du menu popup à la valeur donnée. Si le menu contient plus d'éléments que la hauteur donnée, le menu deviendra déroulant.", "Widget.UnifiedMainMenu.Config.MainMenuWidth.Name": "Largeur du menu principal", @@ -1123,6 +1124,19 @@ "Widget.WalkingIndicator.Description": "Affiche un indicateur qui apparaît lorsque vous marchez au lieu de courir.", "Widget.WalkingIndicator.Config.OnlyShowWhenWalking.Name": "Afficher uniquement en marchant", "Widget.WalkingIndicator.Config.OnlyShowWhenWalking.Description": "Affiche l'indicateur de marche uniquement lorsque vous marchez et le masque lorsque vous courez.", + "Window.IconPicker.Title": "Sélecteur d'icône", + "Window.IconPicker.IconId": "ID de l'icône", + "Window.IconPicker.Category": "Catégorie", + "Window.IconPicker.Category.General": "Général", + "Window.IconPicker.Category.Jobs": "Classe/Job", + "Window.IconPicker.Category.Quests": "Quêtes", + "Window.IconPicker.Category.Avatars": "Avatars & Visages", + "Window.IconPicker.Category.Rewards": "Devises & Récompenses", + "Window.IconPicker.Category.MapMarkers": "Marqueurs & Symboles", + "Window.IconPicker.Category.Shapes": "Formes & Effets", + "Window.IconPicker.Category.Mounts": "Montures", + "Window.IconPicker.Category.Minions": "Familiers", + "Window.IconPicker.Category.Emotes": "Emotes", "ColorGroup.Window.Name": "Couleurs de fenêtre", "ColorGroup.Window.Description": "Couleurs utilisées pour les décorations de fenêtre.", "ColorGroup.Input.Name": "Couleurs des contrôles de saisie", diff --git a/Umbra/i18n/ja.json b/Umbra/i18n/ja.json index 6dccc550..3441d36c 100644 --- a/Umbra/i18n/ja.json +++ b/Umbra/i18n/ja.json @@ -10,6 +10,7 @@ "Apply": "適用", "Copy": "コピー", "Paste": "貼り付け", + "Undo": "元に戻す", "Experience": "経験", "Rested": "休息", "Revert": "デフォルト値に戻す", @@ -625,7 +626,7 @@ "Widget.MainMenu.Config.Category.Name": "メニューカテゴリ", "Widget.MainMenu.Config.Category.Description": "ボタンをクリックしたときに開かれるメインメニューのカテゴリ。", "Widget.MainMenu.Config.CustomIconId.Name": "カスタムアイコンID", - "Widget.MainMenu.Config.CustomIconId.Description": "メインメニューボタンに使用するカスタムアイコンID。デフォルトのアイコンを上書きするために使用できます。利用可能なアイコンを参照するには「/xldata icons」コマンドを使用して正しいIDを取得してください。デフォルトのアイコンを使用するにはID 0を使用してください。", + "Widget.MainMenu.Config.CustomIconId.Description": "メインメニューボタンに使用するカスタムアイコンID。デフォルトのアイコンを上書きするために使用できます。", "Widget.MainMenu.Config.ShowItemIcons.Name": "メニュー内のアイコンを表示する", "Widget.MainMenu.Config.ShowItemIcons.Description": "アイテムに関連付けられたアイコンを持つアイテムのポップアップメニューにアイコンを表示するかどうか。", "Widget.MainMenu.Config.GrayscaleIcons.Name": "メニューアイコンを白黒にする", @@ -666,7 +667,7 @@ "Widget.DynamicMenu.Config.ButtonTooltip.Name": "ボタンのツールチップ", "Widget.DynamicMenu.Config.ButtonTooltip.Description": "ダイナミックメニューを開くボタンにカーソルを合わせた時に表示されるツールチップ。", "Widget.DynamicMenu.Config.ButtonIcon.Name": "ボタンのアイコン", - "Widget.DynamicMenu.Config.ButtonIcon.Description": "ボタンに表示されるアイコン。利用可能なアイコンを閲覧して正しいIDを取得するには、コマンド「/xldata icons」を使用してね。", + "Widget.DynamicMenu.Config.ButtonIcon.Description": "ボタンに表示されるアイコン。", "Widget.DynamicMenu.Config.EditModeEnabled.Name": "編集モードを有効にする", "Widget.DynamicMenu.Config.EditModeEnabled.Description": "メニューの下部にプレースホルダーアイテムを表示し、新しいアイテムをメニューに追加するためのコンテキストメニューを開きます。", "Widget.DynamicMenu.Config.MenuEntryHeight.Name": "メニューエントリの高さ", @@ -690,7 +691,7 @@ "Widget.DynamicMenu.CustomItemEditor.Label.Name": "名前", "Widget.DynamicMenu.CustomItemEditor.Label.Description": "ダイナミックメニューに表示されるカスタムアイテムの名前。", "Widget.DynamicMenu.CustomItemEditor.Icon.Name": "アイコンID", - "Widget.DynamicMenu.CustomItemEditor.Icon.Description": "ダイナミックメニュー内のカスタムアイテムの横に表示されるアイコンIDです。正しいIDを取得するには、コマンド「/xldata icons」を使用して利用可能なアイコンを参照してください。", + "Widget.DynamicMenu.CustomItemEditor.Icon.Description": "ダイナミックメニュー内のカスタムアイテムの横に表示されるアイコンIDです。", "Widget.DynamicMenu.CustomItemEditor.Type.Name": "呼び出しタイプ", "Widget.DynamicMenu.CustomItemEditor.Type.Description": "カスタムアイテムがクリックされたときに使用される呼び出しタイプ。", "Widget.DynamicMenu.CustomItemEditor.Type.Option.ChatCommand": "チャットコマンド", @@ -817,7 +818,7 @@ "Widget.Societies.Config.ButtonLabel.Name": "ボタンラベル(追跡していない場合)", "Widget.Societies.Config.ButtonLabel.Description": "社会関係が追跡されていない場合にウィジェットボタンに表示されるラベル。", "Widget.Societies.Config.ButtonIconId.Name": "ボタンアイコンの種類(追跡していない場合)", - "Widget.Societies.Config.ButtonIconId.Description": "社会関係が追跡されていない場合にボタンに表示されるアイコンID。正しいIDを取得するには、コマンド「/xldata icons」を使用して利用可能なアイコンを参照してください。アイコンを非表示にするには、ID 0を使用します。", + "Widget.Societies.Config.ButtonIconId.Description": "社会関係が追跡されていない場合にボタンに表示されるアイコンID。", "Widget.Societies.Config.MinItemsBeforeHorizontalView.Name": "水平表示に切り替える前のアンロックされた社会の最小数", "Widget.Societies.Config.MinItemsBeforeHorizontalView.Description": "ポップアップメニューは、水平または垂直のレイアウトで表示できます。この設定は、垂直方向の画面スペースを確保するために、レイアウトを水平レイアウトに切り替えるタイミングを決定します。", "Widget.Societies.Config.PrimaryAction.Name": "主な行動", @@ -914,9 +915,9 @@ "Widget.CustomButton.Config.AltCommand.Name": "右クリックコマンドまたはウェブサイトURL", "Widget.CustomButton.Config.AltCommand.Description": "選択したモードに応じて、右クリックしたときに実行されるコマンドを呼び出します。例えば、/dance.、またはURLモードが選択されている場合、デフォルトのブラウザでウェブサイトを開きます。", "Widget.CustomButton.Config.LeftIconId.Name": "左側のアイコンID", - "Widget.CustomButton.Config.LeftIconId.Description": "ボタンの左側に表示するアイコンのID。使用可能なアイコンを参照するには「/xldata icons」というコマンドを使用してください。正しいIDを取得するために。アイコンを非表示にするにはID 0を使用してください。", + "Widget.CustomButton.Config.LeftIconId.Description": "ボタンの左側に表示するアイコンのID。", "Widget.CustomButton.Config.RightIconId.Name": "右側のアイコンID", - "Widget.CustomButton.Config.RightIconId.Description": "ボタンの右側に表示するアイコンのID。使用可能なアイコンを参照するには「/xldata icons」というコマンドを使用してください。正しいIDを取得するために。アイコンを非表示にするにはID 0を使用してください。", + "Widget.CustomButton.Config.RightIconId.Description": "ボタンの右側に表示するアイコンのID。", "Widget.CustomDeliveries.Name": "カスタムデリバリー", "Widget.CustomDeliveries.Description": "カスタムデリバリーの現在の状況を表示します。", "Widget.CustomDeliveries.AllowanceStatus": "残りの週割り当て: {0}", @@ -927,7 +928,7 @@ "Widget.CustomDeliveries.Config.ButtonLabel.Name": "ボタンラベル", "Widget.CustomDeliveries.Config.ButtonLabel.Description": "ボタンに表示されるテキスト。", "Widget.CustomDeliveries.Config.ButtonIcon.Name": "ボタンアイコンID", - "Widget.CustomDeliveries.Config.ButtonIcon.Description": "ボタンに表示するアイコンのIDです。利用可能なアイコンを閲覧して正しいIDを取得するには、コマンド「/xldata icons」を使用します。アイコンを非表示にするにはID 0を使用します。", + "Widget.CustomDeliveries.Config.ButtonIcon.Description": "ボタンに表示するアイコンのIDです。", "Widget.CustomDeliveries.Config.PrimaryAction.Name": "主要アクション", "Widget.CustomDeliveries.Config.PrimaryAction.Description": "ポップアップメニューでNPCをクリックしたときに実行されるアクション。", "Widget.CustomDeliveries.Config.PrimaryAction.Option.Track": "追跡/追跡解除", @@ -951,9 +952,9 @@ "Widget.CustomMenu.Config.TextYOffset.Name": "テキストの垂直オフセット", "Widget.CustomMenu.Config.TextYOffset.Description": "ウィジェットの中心からテキストの垂直オフセットをピクセル単位で指定します。正の値はテキストを下に移動し、負の値はテキストを上に移動します。", "Widget.CustomMenu.Config.LeftIconId.Name": "左アイコンID", - "Widget.CustomMenu.Config.LeftIconId.Description": "ボタンの左側に表示するアイコンID。正しいIDを取得するには、コマンド「/xldata icons」を使用して利用可能なアイコンを閲覧します。アイコンを非表示にするにはID 0を使用します。", + "Widget.CustomMenu.Config.LeftIconId.Description": "ボタンの左側に表示するアイコンID。", "Widget.CustomMenu.Config.RightIconId.Name": "右アイコンID", - "Widget.CustomMenu.Config.RightIconId.Description": "ボタンの右側に表示するアイコンID。正しいIDを取得するには、コマンド「/xldata icons」を使用して利用可能なアイコンを閲覧します。アイコンを非表示にするにはID 0を使用します。", + "Widget.CustomMenu.Config.RightIconId.Description": "ボタンの右側に表示するアイコンID。", "Widget.CustomMenu.Config.DesaturateMenuIcons.Name": "メニューアイテムアイコンの色を薄くする", "Widget.CustomMenu.Config.DesaturateMenuIcons.Description": "メニューのアイコンを薄くしてグレースケールで表示します。", "Widget.CustomMenu.Config.ButtonLabel.Name": "ボタンラベル", @@ -961,7 +962,7 @@ "Widget.CustomMenu.Config.ButtonAltLabel.Name": "ボタンのサブラベル", "Widget.CustomMenu.Config.ButtonAltLabel.Description": "メニュー項目の右側に表示されるサブラベルで、通常はアイテム数、ショートカットなどに使用されます。このオプションは、アイテムモードが選択され、コマンドフィールドに有効なアイテムIDが入力された場合は無視されます。", "Widget.CustomMenu.Config.ButtonIconId.Name": "アイコンID", - "Widget.CustomMenu.Config.ButtonIconId.Description": "ボタンに表示するアイコンID。正しいIDを取得するには、コマンド「/xldata icons」を使用して利用可能なアイコンを閲覧します。アイコンを非表示にするにはID 0を使用します。アイテムモードが選択され、コマンドフィールドに有効なアイテムIDが指定されている場合、このオプションは無視されます。", + "Widget.CustomMenu.Config.ButtonIconId.Description": "ボタンに表示するアイコンID。アイテムモードが選択され、コマンドフィールドに有効なアイテムIDが指定されている場合、このオプションは無視されます。", "Widget.CustomMenu.Config.ButtonIconColor.Name": "アイコンの色", "Widget.CustomMenu.Config.ButtonIconColor.Description": "このメニューアイテムのアイコンに適用するカスタムカラーマスクです。色マスクを効果的に無効にし、アイコンの元の色を使用するには、純白(#FFFFFF)を使用してください。", "Widget.CustomMenu.Config.ButtonCommand.Name": "コマンド、URL、またはアイテムID", @@ -993,7 +994,7 @@ "Widget.EmoteList.Config.Label.Description": "ボタンに表示されるテキスト。", "Widget.EmoteList.Config.Label.Default": "エモート", "Widget.EmoteList.Config.IconId.Name": "アイコンID", - "Widget.EmoteList.Config.IconId.Description": "ボタンに表示されるアイコンID。正しいIDを取得するには、コマンド「/xldata icons」を使用して利用可能なアイコンを閲覧します。アイコンを非表示にするにはID 0を使用します。", + "Widget.EmoteList.Config.IconId.Description": "ボタンに表示されるアイコンID。", "Widget.EmoteList.Config.CategoryName.Name": "カテゴリー #{0} 名", "Widget.EmoteList.Config.CategoryName.Description": "カテゴリーの名前。このフィールドを空白にすると、ポップアップからカテゴリーが無効(非表示)になります。", "Widget.EmoteList.PickerWindow.Title": "エモートピッカー", @@ -1042,7 +1043,7 @@ "Widget.ShortcutPanel.Config.ButtonLabel.Name": "ボタンラベル", "Widget.ShortcutPanel.Config.ButtonLabel.Description": "ツールバーボタンに表示されるテキスト。", "Widget.ShortcutPanel.Config.ButtonIconId.Name": "ボタンアイコンID", - "Widget.ShortcutPanel.Config.ButtonIconId.Description": "ボタンに表示されるアイコンID。正しいIDを取得するには、コマンド「/xldata icons」を使用して利用可能なアイコンを参照してください。", + "Widget.ShortcutPanel.Config.ButtonIconId.Description": "ボタンに表示されるアイコンID。", "Widget.ShortcutPanel.Config.CategoryName.Name": "カテゴリ #{0} 名称", "Widget.ShortcutPanel.Config.CategoryName.Description": "カテゴリの名称。このフィールドを空白にすると、パネルからカテゴリが無効(非表示)になります。", "Widget.ShortcutPanel.Config.NumRows.Name": "行数", @@ -1089,9 +1090,9 @@ "Widget.UnifiedMainMenu.Config.Label.Name": "ボタンラベル", "Widget.UnifiedMainMenu.Config.Label.Description": "ボタンに表示されるテキスト。", "Widget.UnifiedMainMenu.Config.IconId.Name": "アイコンID", - "Widget.UnifiedMainMenu.Config.IconId.Description": "ボタンに表示されるアイコンID。「/xldata icons」コマンドを使用して利用可能なアイコンを閲覧し、正しいIDを取得します。", + "Widget.UnifiedMainMenu.Config.IconId.Description": "ボタンに表示されるアイコンID。", "Widget.UnifiedMainMenu.Config.AvatarIconId.Name": "アバターアイコンID", - "Widget.UnifiedMainMenu.Config.AvatarIconId.Description": "メニューのヘッダーに表示されるアイコンID。「/xldata icons」コマンドを使用して利用可能なアイコンを閲覧し、正しいIDを取得します。", + "Widget.UnifiedMainMenu.Config.AvatarIconId.Description": "メニューのヘッダーに表示されるアイコンID。", "Widget.UnifiedMainMenu.Config.FixedMenuHeight.Name": "固定メニューの高さ", "Widget.UnifiedMainMenu.Config.FixedMenuHeight.Description": "ポップアップメニューの高さを指定された値に設定します。メニューに指定された高さに収まらない項目がある場合、メニューはスクロール可能になります。", "Widget.UnifiedMainMenu.Config.MainMenuWidth.Name": "メインメニューの幅", @@ -1123,6 +1124,19 @@ "Widget.WalkingIndicator.Description": "走る代わりに歩いているときに表示されるインジケーターを表示します。", "Widget.WalkingIndicator.Config.OnlyShowWhenWalking.Name": "歩行中のみ表示", "Widget.WalkingIndicator.Config.OnlyShowWhenWalking.Description": "歩行中のみ歩行インジケータを表示し、走っているときは非表示にします。", + "Window.IconPicker.Title": "アイコン選択", + "Window.IconPicker.IconId": "アイコンID", + "Window.IconPicker.Category": "カテゴリ", + "Window.IconPicker.Category.General": "一般", + "Window.IconPicker.Category.Jobs": "クラス/ジョブ", + "Window.IconPicker.Category.Quests": "クエスト", + "Window.IconPicker.Category.Avatars": "アバター & 顔", + "Window.IconPicker.Category.Rewards": "通貨 & 報酬", + "Window.IconPicker.Category.MapMarkers": "地図マーカー & シンボル", + "Window.IconPicker.Category.Shapes": "形状 & エフェクト", + "Window.IconPicker.Category.Mounts": "マウント", + "Window.IconPicker.Category.Minions": "ミニオン", + "Window.IconPicker.Category.Emotes": "エモート", "ColorGroup.Window.Name": "ウィンドウの色", "ColorGroup.Window.Description": "ウィンドウの装飾に使用される色。", "ColorGroup.Input.Name": "入力コントロールの色", diff --git a/Umbra/i18n/zh.json b/Umbra/i18n/zh.json index 86f23f54..f0a64793 100644 --- a/Umbra/i18n/zh.json +++ b/Umbra/i18n/zh.json @@ -10,6 +10,7 @@ "Apply": "应用", "Copy": "复制", "Paste": "粘贴", + "Undo": "撤销", "Experience": "经验", "Rested": "休息", "Revert": "恢复默认值", @@ -625,7 +626,7 @@ "Widget.MainMenu.Config.Category.Name": "菜单类别", "Widget.MainMenu.Config.Category.Description": "单击按钮时应打开的主菜单类别。", "Widget.MainMenu.Config.CustomIconId.Name": "自定义图标编号", - "Widget.MainMenu.Config.CustomIconId.Description": "主菜单按钮应使用的自定义图标ID,用来覆盖默认图标。使用命令“/xldata icons”浏览可用图标以获取正确的ID。使用ID 0以使用默认图标。", + "Widget.MainMenu.Config.CustomIconId.Description": "主菜单按钮应使用的自定义图标ID,用来覆盖默认图标。", "Widget.MainMenu.Config.ShowItemIcons.Name": "在菜单中显示项目图标", "Widget.MainMenu.Config.ShowItemIcons.Description": "是否在弹出菜单中显示带有图标的项目的图标。", "Widget.MainMenu.Config.GrayscaleIcons.Name": "使菜单图标变灰显示。", @@ -666,7 +667,7 @@ "Widget.DynamicMenu.Config.ButtonTooltip.Name": "按钮提示", "Widget.DynamicMenu.Config.ButtonTooltip.Description": "当鼠标悬停在打开动态菜单的按钮上时显示的提示。", "Widget.DynamicMenu.Config.ButtonIcon.Name": "按钮图标", - "Widget.DynamicMenu.Config.ButtonIcon.Description": "显示在按钮上的图标。使用命令 \"/xldata icons\" 浏览可用图标并获取正确的ID。", + "Widget.DynamicMenu.Config.ButtonIcon.Description": "显示在按钮上的图标。", "Widget.DynamicMenu.Config.EditModeEnabled.Name": "启用编辑模式", "Widget.DynamicMenu.Config.EditModeEnabled.Description": "在菜单底部启用一个占位符项目,打开上下文菜单以添加新项目到菜单中。", "Widget.DynamicMenu.Config.MenuEntryHeight.Name": "菜单项高度", @@ -690,7 +691,7 @@ "Widget.DynamicMenu.CustomItemEditor.Label.Name": "名称", "Widget.DynamicMenu.CustomItemEditor.Label.Description": "显示在动态菜单中的自定义项目的名称。", "Widget.DynamicMenu.CustomItemEditor.Icon.Name": "图标ID", - "Widget.DynamicMenu.CustomItemEditor.Icon.Description": "显示在动态菜单中自定义项目旁边的图标ID。使用命令“/xldata icons”浏览可用图标以获取正确的ID。", + "Widget.DynamicMenu.CustomItemEditor.Icon.Description": "显示在动态菜单中自定义项目旁边的图标ID。", "Widget.DynamicMenu.CustomItemEditor.Type.Name": "调用类型", "Widget.DynamicMenu.CustomItemEditor.Type.Description": "点击自定义项目时使用的调用类型。", "Widget.DynamicMenu.CustomItemEditor.Type.Option.ChatCommand": "聊天命令", @@ -817,7 +818,7 @@ "Widget.Societies.Config.ButtonLabel.Name": "按钮标签(未跟踪时)", "Widget.Societies.Config.ButtonLabel.Description": "当没有社会关系被跟踪时,应该显示在小部件按钮上的标签。", "Widget.Societies.Config.ButtonIconId.Name": "按钮图标类型(未跟踪时)", - "Widget.Societies.Config.ButtonIconId.Description": "当没有社会关系被跟踪时,应该显示在按钮上的图标ID。使用命令“/xldata icons”浏览可用图标以获取正确的ID。使用ID 0隐藏图标。", + "Widget.Societies.Config.ButtonIconId.Description": "当没有社会关系被跟踪时,应该显示在按钮上的图标ID。", "Widget.Societies.Config.MinItemsBeforeHorizontalView.Name": "切换到水平视图之前解锁的最小社会数量", "Widget.Societies.Config.MinItemsBeforeHorizontalView.Description": "弹出菜单可以显示为水平或垂直布局。此设置确定何时应切换到水平布局以节省垂直屏幕空间。", "Widget.Societies.Config.PrimaryAction.Name": "主要操作", @@ -914,9 +915,9 @@ "Widget.CustomButton.Config.AltCommand.Name": "右键命令或网站URL", "Widget.CustomButton.Config.AltCommand.Description": "根据选择的模式,执行右键点击按钮时的命令。例如:/dance.,或者在选择URL模式时,在默认浏览器中打开网站。", "Widget.CustomButton.Config.LeftIconId.Name": "左图标ID", - "Widget.CustomButton.Config.LeftIconId.Description": "显示在按钮左侧的图标的ID。使用命令“/xldata icons”浏览可用图标以获取正确的ID。使用ID 0以使用默认图标。", + "Widget.CustomButton.Config.LeftIconId.Description": "显示在按钮左侧的图标的ID。", "Widget.CustomButton.Config.RightIconId.Name": "右图标ID", - "Widget.CustomButton.Config.RightIconId.Description": "显示在按钮右侧的图标的ID。使用命令“/xldata icons”浏览可用图标以获取正确的ID。使用ID 0以使用默认图标。", + "Widget.CustomButton.Config.RightIconId.Description": "显示在按钮右侧的图标的ID。", "Widget.CustomDeliveries.Name": "定制交付", "Widget.CustomDeliveries.Description": "显示您当前的定制交付状态。", "Widget.CustomDeliveries.AllowanceStatus": "每周剩余额度:{0}", @@ -927,7 +928,7 @@ "Widget.CustomDeliveries.Config.ButtonLabel.Name": "按钮标签", "Widget.CustomDeliveries.Config.ButtonLabel.Description": "按钮上显示的文字。", "Widget.CustomDeliveries.Config.ButtonIcon.Name": "按钮图标ID", - "Widget.CustomDeliveries.Config.ButtonIcon.Description": "应显示在按钮上的图标ID。使用命令“/xldata icons”浏览可用图标以获取正确的ID。使用ID 0隐藏图标。", + "Widget.CustomDeliveries.Config.ButtonIcon.Description": "应显示在按钮上的图标ID。", "Widget.CustomDeliveries.Config.PrimaryAction.Name": "主要操作", "Widget.CustomDeliveries.Config.PrimaryAction.Description": "单击弹出菜单中的NPC时应执行的操作。", "Widget.CustomDeliveries.Config.PrimaryAction.Option.Track": "跟踪 / 取消跟踪", @@ -951,9 +952,9 @@ "Widget.CustomMenu.Config.TextYOffset.Name": "文本垂直偏移", "Widget.CustomMenu.Config.TextYOffset.Description": "文本相对于小部件中心的垂直偏移,以像素为单位。正值向下移动文本,负值向上移动文本。", "Widget.CustomMenu.Config.LeftIconId.Name": "左图标ID", - "Widget.CustomMenu.Config.LeftIconId.Description": "应显示在按钮左侧的图标ID。使用命令“/xldata icons”浏览可用图标以获取正确的ID。使用ID 0隐藏图标。", + "Widget.CustomMenu.Config.LeftIconId.Description": "应显示在按钮左侧的图标ID。", "Widget.CustomMenu.Config.RightIconId.Name": "右图标ID", - "Widget.CustomMenu.Config.RightIconId.Description": "应显示在按钮右侧的图标ID。使用命令“/xldata icons”浏览可用图标以获取正确的ID。使用ID 0隐藏图标。", + "Widget.CustomMenu.Config.RightIconId.Description": "应显示在按钮右侧的图标ID。", "Widget.CustomMenu.Config.DesaturateMenuIcons.Name": "去色菜单项图标", "Widget.CustomMenu.Config.DesaturateMenuIcons.Description": "去色菜单中的图标,使其以灰度显示。", "Widget.CustomMenu.Config.ButtonLabel.Name": "按钮标签", @@ -961,7 +962,7 @@ "Widget.CustomMenu.Config.ButtonAltLabel.Name": "按钮子标签", "Widget.CustomMenu.Config.ButtonAltLabel.Description": "显示在菜单项右侧的子标签,通常用于项目计数、快捷方式等。当选择了项目模式并在命令字段中提供了有效的项目ID时,此选项将被忽略。", "Widget.CustomMenu.Config.ButtonIconId.Name": "图标ID", - "Widget.CustomMenu.Config.ButtonIconId.Description": "应显示在按钮上的图标ID。使用命令“/xldata icons”浏览可用图标以获取正确的ID。使用ID 0隐藏图标。当选择了物品模式并在命令字段中给出有效的物品ID时,此选项将被忽略。", + "Widget.CustomMenu.Config.ButtonIconId.Description": "应显示在按钮上的图标ID。当选择了物品模式并在命令字段中给出有效的物品ID时,此选项将被忽略。", "Widget.CustomMenu.Config.ButtonIconColor.Name": "图标颜色", "Widget.CustomMenu.Config.ButtonIconColor.Description": "自定义颜色掩码以应用于此菜单项的图标。使用纯白色(#FFFFFF)可以有效禁用颜色掩码并使用图标的原始颜色。", "Widget.CustomMenu.Config.ButtonCommand.Name": "命令、URL或物品ID", @@ -993,7 +994,7 @@ "Widget.EmoteList.Config.Label.Description": "按钮上显示的文本。", "Widget.EmoteList.Config.Label.Default": "表情", "Widget.EmoteList.Config.IconId.Name": "图标ID", - "Widget.EmoteList.Config.IconId.Description": "应显示在按钮上的图标ID。使用命令“/xldata icons”浏览可用的图标以获取正确的ID。使用ID 0来隐藏图标。", + "Widget.EmoteList.Config.IconId.Description": "应显示在按钮上的图标ID。", "Widget.EmoteList.Config.CategoryName.Name": "类别 #{0} 名称", "Widget.EmoteList.Config.CategoryName.Description": "类别的名称。将此字段留空将禁用(隐藏)弹出窗口中的类别。", "Widget.EmoteList.PickerWindow.Title": "表情选择器", @@ -1042,7 +1043,7 @@ "Widget.ShortcutPanel.Config.ButtonLabel.Name": "按钮标签", "Widget.ShortcutPanel.Config.ButtonLabel.Description": "显示在工具栏按钮上的文本。", "Widget.ShortcutPanel.Config.ButtonIconId.Name": "按钮图标ID", - "Widget.ShortcutPanel.Config.ButtonIconId.Description": "要显示在按钮上的图标ID。使用命令“/xldata icons”浏览可用图标以获取正确的ID。", + "Widget.ShortcutPanel.Config.ButtonIconId.Description": "要显示在按钮上的图标ID。", "Widget.ShortcutPanel.Config.CategoryName.Name": "类别 #{0} 名称", "Widget.ShortcutPanel.Config.CategoryName.Description": "类别名称。将此字段留空将禁用(隐藏)面板中的类别。", "Widget.ShortcutPanel.Config.NumRows.Name": "行数", @@ -1089,9 +1090,9 @@ "Widget.UnifiedMainMenu.Config.Label.Name": "按钮标签", "Widget.UnifiedMainMenu.Config.Label.Description": "显示在按钮上的文本。", "Widget.UnifiedMainMenu.Config.IconId.Name": "图标ID", - "Widget.UnifiedMainMenu.Config.IconId.Description": "应显示在按钮上的图标ID。使用命令 \"/xldata icons\" 浏览可用图标以获取正确的ID。", + "Widget.UnifiedMainMenu.Config.IconId.Description": "应显示在按钮上的图标ID。", "Widget.UnifiedMainMenu.Config.AvatarIconId.Name": "头像图标ID", - "Widget.UnifiedMainMenu.Config.AvatarIconId.Description": "应显示在菜单标题中的图标ID。使用命令 \"/xldata icons\" 浏览可用图标以获取正确的ID。", + "Widget.UnifiedMainMenu.Config.AvatarIconId.Description": "应显示在菜单标题中的图标ID。", "Widget.UnifiedMainMenu.Config.FixedMenuHeight.Name": "固定菜单高度", "Widget.UnifiedMainMenu.Config.FixedMenuHeight.Description": "将弹出菜单的高度设置为给定值。如果菜单的项目超过给定高度,菜单将变得可滚动。", "Widget.UnifiedMainMenu.Config.MainMenuWidth.Name": "主菜单宽度", @@ -1123,6 +1124,19 @@ "Widget.WalkingIndicator.Description": "角色处于步行模式时显示步行图标", "Widget.WalkingIndicator.Config.OnlyShowWhenWalking.Name": "仅在步行时显示", "Widget.WalkingIndicator.Config.OnlyShowWhenWalking.Description": "仅在您步行时显示步行指示器,跑步时隐藏它。", + "Window.IconPicker.Title": "图标选择器", + "Window.IconPicker.IconId": "图标ID", + "Window.IconPicker.Category": "类别", + "Window.IconPicker.Category.General": "通用", + "Window.IconPicker.Category.Jobs": "职业", + "Window.IconPicker.Category.Quests": "任务", + "Window.IconPicker.Category.Avatars": "头像 & 面孔", + "Window.IconPicker.Category.Rewards": "货币 & 奖励", + "Window.IconPicker.Category.MapMarkers": "地图标记 & 符号", + "Window.IconPicker.Category.Shapes": "形状 & 效果", + "Window.IconPicker.Category.Mounts": "坐骑", + "Window.IconPicker.Category.Minions": "宠物", + "Window.IconPicker.Category.Emotes": "表情动作", "ColorGroup.Window.Name": "Window Colors", "ColorGroup.Window.Description": "Colors that are used for the window decorations.", "ColorGroup.Input.Name": "输入控件颜色", diff --git a/Umbra/src/Toolbar/Widgets/Library/CustomButton/CustomButtonWidget.Config.cs b/Umbra/src/Toolbar/Widgets/Library/CustomButton/CustomButtonWidget.Config.cs index d121ce5e..832f07b1 100644 --- a/Umbra/src/Toolbar/Widgets/Library/CustomButton/CustomButtonWidget.Config.cs +++ b/Umbra/src/Toolbar/Widgets/Library/CustomButton/CustomButtonWidget.Config.cs @@ -77,18 +77,16 @@ protected override IEnumerable GetConfigVariables() I18N.Translate("Widget.CustomButton.Config.HideLabel.Description"), false ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, - new IntegerWidgetConfigVariable( + new IconIdWidgetConfigVariable( "LeftIconId", I18N.Translate("Widget.CustomButton.Config.LeftIconId.Name"), I18N.Translate("Widget.CustomButton.Config.LeftIconId.Description"), - 0, 0 ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, - new IntegerWidgetConfigVariable( + new IconIdWidgetConfigVariable( "RightIconId", I18N.Translate("Widget.CustomButton.Config.RightIconId.Name"), I18N.Translate("Widget.CustomButton.Config.RightIconId.Description"), - 0, 0 ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, ..DefaultToolbarWidgetConfigVariables, diff --git a/Umbra/src/Toolbar/Widgets/Library/CustomButton/CustomButtonWidget.cs b/Umbra/src/Toolbar/Widgets/Library/CustomButton/CustomButtonWidget.cs index ff730ce8..e34314aa 100644 --- a/Umbra/src/Toolbar/Widgets/Library/CustomButton/CustomButtonWidget.cs +++ b/Umbra/src/Toolbar/Widgets/Library/CustomButton/CustomButtonWidget.cs @@ -80,8 +80,8 @@ private void InvokeAltCommand(Node _) private void UpdateIcons() { - var leftIconId = (uint)GetConfigValue("LeftIconId"); - var rightIconId = (uint)GetConfigValue("RightIconId"); + var leftIconId = GetConfigValue("LeftIconId"); + var rightIconId = GetConfigValue("RightIconId"); if (leftIconId != LeftIconId) { LeftIconId = leftIconId; diff --git a/Umbra/src/Toolbar/Widgets/Library/CustomMenu/CustomMenuWidget.Config.cs b/Umbra/src/Toolbar/Widgets/Library/CustomMenu/CustomMenuWidget.Config.cs index bfc64e5a..a9ea4d9d 100644 --- a/Umbra/src/Toolbar/Widgets/Library/CustomMenu/CustomMenuWidget.Config.cs +++ b/Umbra/src/Toolbar/Widgets/Library/CustomMenu/CustomMenuWidget.Config.cs @@ -60,18 +60,16 @@ protected override IEnumerable GetConfigVariables() I18N.Translate("Widget.CustomMenu.Config.HideLabel.Description"), false ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, - new IntegerWidgetConfigVariable( + new IconIdWidgetConfigVariable( "LeftIconId", I18N.Translate("Widget.CustomMenu.Config.LeftIconId.Name"), I18N.Translate("Widget.CustomMenu.Config.LeftIconId.Description"), - 0, 0 ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, - new IntegerWidgetConfigVariable( + new IconIdWidgetConfigVariable( "RightIconId", I18N.Translate("Widget.CustomMenu.Config.RightIconId.Name"), I18N.Translate("Widget.CustomMenu.Config.RightIconId.Description"), - 0, 0 ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, new BooleanWidgetConfigVariable( @@ -123,7 +121,7 @@ private static IEnumerable CreateButtonVariables(int butt "", 32 ) { Category = I18N.Translate("Widget.CustomMenu.Config.ButtonId", buttonIndex + 1) }, - new IntegerWidgetConfigVariable( + new IconIdWidgetConfigVariable( $"ButtonIconId_{buttonIndex}", I18N.Translate("Widget.CustomMenu.Config.ButtonIconId.Name"), I18N.Translate("Widget.CustomMenu.Config.ButtonIconId.Description"), diff --git a/Umbra/src/Toolbar/Widgets/Library/CustomMenu/CustomMenuWidget.cs b/Umbra/src/Toolbar/Widgets/Library/CustomMenu/CustomMenuWidget.cs index da388421..813640b4 100644 --- a/Umbra/src/Toolbar/Widgets/Library/CustomMenu/CustomMenuWidget.cs +++ b/Umbra/src/Toolbar/Widgets/Library/CustomMenu/CustomMenuWidget.cs @@ -79,8 +79,8 @@ private void UpdateIcons() return; } - var leftIconId = (uint)GetConfigValue("LeftIconId"); - var rightIconId = (uint)GetConfigValue("RightIconId"); + var leftIconId = GetConfigValue("LeftIconId"); + var rightIconId = GetConfigValue("RightIconId"); if (leftIconId != LeftIconId) { LeftIconId = leftIconId; @@ -112,7 +112,7 @@ private void UpdateItemList() string altLabel = GetConfigValue($"ButtonAltLabel_{i}").Trim(); string command = GetConfigValue($"ButtonCommand_{i}").Trim(); string mode = GetConfigValue($"ButtonMode_{i}").Trim(); - uint iconId = (uint)GetConfigValue($"ButtonIconId_{i}"); + uint iconId = GetConfigValue($"ButtonIconId_{i}"); uint iconColor = GetConfigValue($"ButtonIconColor_{i}"); ItemUsage usage = ParseItemUsageString(GetConfigValue($"ButtonItemUsage_{i}")); diff --git a/Umbra/src/Toolbar/Widgets/Library/DynamicMenu/DynamicMenuPopup.CustomItemEditor.cs b/Umbra/src/Toolbar/Widgets/Library/DynamicMenu/DynamicMenuPopup.CustomItemEditor.cs index 8c837ca7..87945d4a 100644 --- a/Umbra/src/Toolbar/Widgets/Library/DynamicMenu/DynamicMenuPopup.CustomItemEditor.cs +++ b/Umbra/src/Toolbar/Widgets/Library/DynamicMenu/DynamicMenuPopup.CustomItemEditor.cs @@ -23,11 +23,10 @@ private void OpenCustomItemEditor() MaxLength = 100, }; - IntegerVariable iconVar = new("Icon") { + IconIdVariable iconVar = new("Icon") { Name = I18N.Translate("Widget.DynamicMenu.CustomItemEditor.Icon.Name"), Description = I18N.Translate("Widget.DynamicMenu.CustomItemEditor.Icon.Description"), - Value = (int)(entry.Ci ?? 0), - Min = 0, + Value = (entry.Ci ?? 0), }; StringSelectVariable typeVar = new("Type") { @@ -57,9 +56,8 @@ private void OpenCustomItemEditor() "CustomItemEditor", window, _ => { - Logger.Info("Window closed."); entry.Cl = labelVar.Value; - entry.Ci = (uint)iconVar.Value; + entry.Ci = iconVar.Value; entry.Ct = typeVar.Value; entry.Cc = commandVar.Value; diff --git a/Umbra/src/Toolbar/Widgets/Library/DynamicMenu/DynamicMenuWidget.Config.cs b/Umbra/src/Toolbar/Widgets/Library/DynamicMenu/DynamicMenuWidget.Config.cs index 7b1e5138..09791a4e 100644 --- a/Umbra/src/Toolbar/Widgets/Library/DynamicMenu/DynamicMenuWidget.Config.cs +++ b/Umbra/src/Toolbar/Widgets/Library/DynamicMenu/DynamicMenuWidget.Config.cs @@ -27,12 +27,11 @@ protected override IEnumerable GetConfigVariables() I18N.Translate("Widget.DynamicMenu.Config.ButtonTooltip.Description"), "" ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, - new IntegerWidgetConfigVariable( + new IconIdWidgetConfigVariable( "ButtonIcon", I18N.Translate("Widget.DynamicMenu.Config.ButtonIcon.Name"), I18N.Translate("Widget.DynamicMenu.Config.ButtonIcon.Description"), - 14, - 0 + 14 ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, ..DefaultToolbarWidgetConfigVariables, ..SingleLabelTextOffsetVariables, diff --git a/Umbra/src/Toolbar/Widgets/Library/DynamicMenu/DynamicMenuWidget.cs b/Umbra/src/Toolbar/Widgets/Library/DynamicMenu/DynamicMenuWidget.cs index d28ad32b..aa673300 100644 --- a/Umbra/src/Toolbar/Widgets/Library/DynamicMenu/DynamicMenuWidget.cs +++ b/Umbra/src/Toolbar/Widgets/Library/DynamicMenu/DynamicMenuWidget.cs @@ -52,7 +52,7 @@ protected override void OnUpdate() Popup.ShowItemCount = GetConfigValue("ShowItemCount"); SetLabel(GetConfigValue("ButtonLabel")); - SetIcon((uint)GetConfigValue("ButtonIcon")); + SetIcon(GetConfigValue("ButtonIcon")); base.OnUpdate(); diff --git a/Umbra/src/Toolbar/Widgets/Library/EmoteList/EmoteListWidget.Config.cs b/Umbra/src/Toolbar/Widgets/Library/EmoteList/EmoteListWidget.Config.cs index 915ef61b..e0d7fc51 100644 --- a/Umbra/src/Toolbar/Widgets/Library/EmoteList/EmoteListWidget.Config.cs +++ b/Umbra/src/Toolbar/Widgets/Library/EmoteList/EmoteListWidget.Config.cs @@ -14,12 +14,11 @@ protected override IEnumerable GetConfigVariables() I18N.Translate("Widget.EmoteList.Config.Label.Description"), I18N.Translate("Widget.EmoteList.Config.Label.Default") ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, - new IntegerWidgetConfigVariable( + new IconIdWidgetConfigVariable( "IconId", I18N.Translate("Widget.EmoteList.Config.IconId.Name"), I18N.Translate("Widget.EmoteList.Config.IconId.Description"), - 14, - 0 + 14 ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, ..DefaultToolbarWidgetConfigVariables, ..SingleLabelTextOffsetVariables, diff --git a/Umbra/src/Toolbar/Widgets/Library/EmoteList/EmoteListWidget.cs b/Umbra/src/Toolbar/Widgets/Library/EmoteList/EmoteListWidget.cs index 39b68784..bfefdb11 100644 --- a/Umbra/src/Toolbar/Widgets/Library/EmoteList/EmoteListWidget.cs +++ b/Umbra/src/Toolbar/Widgets/Library/EmoteList/EmoteListWidget.cs @@ -53,7 +53,7 @@ protected override void OnDisposed() protected override void OnUpdate() { SetLabel(GetConfigValue("Label")); - SetIcon((uint)GetConfigValue("IconId")); + SetIcon(GetConfigValue("IconId")); Popup.KeepOpenAfterUse = GetConfigValue("KeepOpenAfterUse"); Popup.LastSelectedCategory = (byte)GetConfigValue("LastSelectedCategory"); diff --git a/Umbra/src/Toolbar/Widgets/Library/MainMenu/MainMenuWidget.cs b/Umbra/src/Toolbar/Widgets/Library/MainMenu/MainMenuWidget.cs index 9dbf7e7f..49564e66 100644 --- a/Umbra/src/Toolbar/Widgets/Library/MainMenu/MainMenuWidget.cs +++ b/Umbra/src/Toolbar/Widgets/Library/MainMenu/MainMenuWidget.cs @@ -40,7 +40,7 @@ internal sealed class MainMenuWidget( private string? _selectedCategory; private string? _displayMode; private string? _iconLocation; - private int? _customIconId; + private uint? _customIconId; public override string GetInstanceName() { @@ -73,7 +73,7 @@ protected override void OnUpdate() var displayMode = GetConfigValue("DisplayMode"); var iconLocation = GetConfigValue("IconLocation"); - var customIconId = GetConfigValue("CustomIconId"); + var customIconId = GetConfigValue("CustomIconId"); var showItemIcons = GetConfigValue("ShowItemIcons"); if (displayMode != _displayMode || iconLocation != _iconLocation || customIconId != _customIconId) { @@ -81,12 +81,12 @@ protected override void OnUpdate() _iconLocation = iconLocation; _customIconId = customIconId; - int existingCustomIconId = customIconId; + uint existingCustomIconId = customIconId; if (existingCustomIconId > 0) { // Make sure the icon exists. try { - Framework.Service().GetIconPath((uint)customIconId); + Framework.Service().GetIconPath(customIconId); } catch (FileNotFoundException) { existingCustomIconId = 0; } @@ -95,7 +95,7 @@ protected override void OnUpdate() bool hasIcon = displayMode is "IconOnly" or "TextAndIcon"; if (hasIcon) { - SetIcon((existingCustomIconId == 0 ? _category.GetIconId() : (uint)existingCustomIconId)); + SetIcon((existingCustomIconId == 0 ? _category.GetIconId() : existingCustomIconId)); } else { SetIcon(null); } @@ -131,11 +131,10 @@ protected override IEnumerable GetConfigVariables() MenuCategory.Character.ToString(), repository.GetCategories().ToDictionary(c => c.Category.ToString(), c => c.Name) ), - new IntegerWidgetConfigVariable( + new IconIdWidgetConfigVariable( "CustomIconId", I18N.Translate("Widget.MainMenu.Config.CustomIconId.Name"), I18N.Translate("Widget.MainMenu.Config.CustomIconId.Description"), - 0, 0 ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, ..DefaultToolbarWidgetConfigVariables, diff --git a/Umbra/src/Toolbar/Widgets/Library/ShortcutPanel/ShortcutPanelWidget.Config.cs b/Umbra/src/Toolbar/Widgets/Library/ShortcutPanel/ShortcutPanelWidget.Config.cs index e6c55386..bec4aa6d 100644 --- a/Umbra/src/Toolbar/Widgets/Library/ShortcutPanel/ShortcutPanelWidget.Config.cs +++ b/Umbra/src/Toolbar/Widgets/Library/ShortcutPanel/ShortcutPanelWidget.Config.cs @@ -29,11 +29,10 @@ protected override IEnumerable GetConfigVariables() Info.Name, 32 ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, - new IntegerWidgetConfigVariable( + new IconIdWidgetConfigVariable( "ButtonIconId", I18N.Translate("Widget.ShortcutPanel.Config.ButtonIconId.Name"), I18N.Translate("Widget.ShortcutPanel.Config.ButtonIconId.Description"), - 0, 0 ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, ..DefaultToolbarWidgetConfigVariables, diff --git a/Umbra/src/Toolbar/Widgets/Library/ShortcutPanel/ShortcutPanelWidget.cs b/Umbra/src/Toolbar/Widgets/Library/ShortcutPanel/ShortcutPanelWidget.cs index cf4a6a6d..c3b9f73a 100644 --- a/Umbra/src/Toolbar/Widgets/Library/ShortcutPanel/ShortcutPanelWidget.cs +++ b/Umbra/src/Toolbar/Widgets/Library/ShortcutPanel/ShortcutPanelWidget.cs @@ -47,7 +47,7 @@ protected override void OnUpdate() } SetLabel(GetConfigValue("ButtonLabel")); - SetIcon((uint)GetConfigValue("ButtonIconId")); + SetIcon(GetConfigValue("ButtonIconId")); base.OnUpdate(); } diff --git a/Umbra/src/Toolbar/Widgets/Library/Societies/SocietiesWidget.Config.cs b/Umbra/src/Toolbar/Widgets/Library/Societies/SocietiesWidget.Config.cs index 59427bf5..1e45acff 100644 --- a/Umbra/src/Toolbar/Widgets/Library/Societies/SocietiesWidget.Config.cs +++ b/Umbra/src/Toolbar/Widgets/Library/Societies/SocietiesWidget.Config.cs @@ -14,12 +14,11 @@ protected override IEnumerable GetConfigVariables() I18N.Translate("Widget.Societies.Config.ButtonLabel.Description"), Info.Name ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, - new IntegerWidgetConfigVariable( + new IconIdWidgetConfigVariable( "ButtonIconId", I18N.Translate("Widget.Societies.Config.ButtonIconId.Name"), I18N.Translate("Widget.Societies.Config.ButtonIconId.Description"), - 65042, - 0 + 65042 ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, ..DefaultToolbarWidgetConfigVariables, ..SingleLabelTextOffsetVariables, diff --git a/Umbra/src/Toolbar/Widgets/Library/Societies/SocietiesWidget.cs b/Umbra/src/Toolbar/Widgets/Library/Societies/SocietiesWidget.cs index 9b654250..36314365 100644 --- a/Umbra/src/Toolbar/Widgets/Library/Societies/SocietiesWidget.cs +++ b/Umbra/src/Toolbar/Widgets/Library/Societies/SocietiesWidget.cs @@ -45,7 +45,7 @@ protected override void OnUpdate() if (0 == trackedTribeId || !society.HasValue) { SetLabel(GetConfigValue("ButtonLabel")); - SetIcon((uint)GetConfigValue("ButtonIconId")); + SetIcon(GetConfigValue("ButtonIconId")); tooltip = null; } else { int pct = society.Value.RequiredRep > 0 diff --git a/Umbra/src/Toolbar/Widgets/Library/UnifiedMainMenu/UnifiedMainMenu.Config.cs b/Umbra/src/Toolbar/Widgets/Library/UnifiedMainMenu/UnifiedMainMenu.Config.cs index 06bd94fb..364e6bf6 100644 --- a/Umbra/src/Toolbar/Widgets/Library/UnifiedMainMenu/UnifiedMainMenu.Config.cs +++ b/Umbra/src/Toolbar/Widgets/Library/UnifiedMainMenu/UnifiedMainMenu.Config.cs @@ -14,12 +14,11 @@ protected override IEnumerable GetConfigVariables() I18N.Translate("Widget.UnifiedMainMenu.Config.Label.Description"), "Start" ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, - new IntegerWidgetConfigVariable( + new IconIdWidgetConfigVariable( "IconId", I18N.Translate("Widget.UnifiedMainMenu.Config.IconId.Name"), I18N.Translate("Widget.UnifiedMainMenu.Config.IconId.Description"), - 14, - 0 + 14 ) { Category = I18N.Translate("Widget.ConfigCategory.WidgetAppearance") }, ..DefaultToolbarWidgetConfigVariables, ..SingleLabelTextOffsetVariables, @@ -35,12 +34,11 @@ protected override IEnumerable GetConfigVariables() I18N.Translate("Widget.UnifiedMainMenu.Config.DesaturateIcons.Description"), false ) { Category = I18N.Translate("Widget.ConfigCategory.MenuAppearance") }, - new IntegerWidgetConfigVariable( + new IconIdWidgetConfigVariable( "AvatarIconId", I18N.Translate("Widget.UnifiedMainMenu.Config.AvatarIconId.Name"), I18N.Translate("Widget.UnifiedMainMenu.Config.AvatarIconId.Description"), - 76985, - 0 + 76985 ) { Category = I18N.Translate("Widget.ConfigCategory.MenuAppearance") }, new IntegerWidgetConfigVariable( "FixedMenuHeight", diff --git a/Umbra/src/Toolbar/Widgets/Library/UnifiedMainMenu/UnifiedMainMenu.cs b/Umbra/src/Toolbar/Widgets/Library/UnifiedMainMenu/UnifiedMainMenu.cs index 7149342a..36ce67fa 100644 --- a/Umbra/src/Toolbar/Widgets/Library/UnifiedMainMenu/UnifiedMainMenu.cs +++ b/Umbra/src/Toolbar/Widgets/Library/UnifiedMainMenu/UnifiedMainMenu.cs @@ -27,7 +27,7 @@ protected override void OnDisposed() protected override void OnUpdate() { - Popup.AvatarIconId = (uint)GetConfigValue("AvatarIconId"); + Popup.AvatarIconId = GetConfigValue("AvatarIconId"); Popup.MenuHeight = GetConfigValue("FixedMenuHeight"); Popup.CategoriesWidth = GetConfigValue("CategoriesWidth"); Popup.EntriesWidth = GetConfigValue("EntriesWidth"); @@ -38,7 +38,7 @@ protected override void OnUpdate() Popup.OpenSubMenusOnHover = GetConfigValue("OpenSubMenusOnHover"); SetLabel(GetConfigValue("Label")); - SetIcon((uint)GetConfigValue("IconId")); + SetIcon(GetConfigValue("IconId")); base.OnUpdate(); } diff --git a/Umbra/src/Toolbar/Widgets/System/Config/IconIdWidgetConfigVariable.cs b/Umbra/src/Toolbar/Widgets/System/Config/IconIdWidgetConfigVariable.cs new file mode 100644 index 00000000..f1665781 --- /dev/null +++ b/Umbra/src/Toolbar/Widgets/System/Config/IconIdWidgetConfigVariable.cs @@ -0,0 +1,19 @@ +using System; + +namespace Umbra.Widgets; + +public class IconIdWidgetConfigVariable(string id, string name, string? description, uint defaultValue) + : WidgetConfigVariable(id, name, description, defaultValue) +{ + /// + protected override uint Sanitize(object? value) + { + if (value is null) return 0; + + try { + return Convert.ToUInt32(value); + } catch { + return 0; + } + } +} diff --git a/Umbra/src/Toolbar/Widgets/System/Editor/WidgetInstanceEditor.cs b/Umbra/src/Toolbar/Widgets/System/Editor/WidgetInstanceEditor.cs new file mode 100644 index 00000000..f7542068 --- /dev/null +++ b/Umbra/src/Toolbar/Widgets/System/Editor/WidgetInstanceEditor.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Umbra.Common; +using Umbra.Windows; +using Umbra.Windows.Library.VariablesWindow; + +namespace Umbra.Widgets; + +[Service] +internal sealed class WidgetInstanceEditor(WindowManager windowManager) : IDisposable +{ + private WindowManager WindowManager { get; } = windowManager; + + private InstanceEditor? _editor; + + public void OpenEditor(ToolbarWidget widget) + { + _editor?.Dispose(); + _editor = new(widget, WindowManager); + Logger.Info($"Open settings for widget {widget.Id} (Type={widget.Info.Id})"); + + _editor.OnDisposed += () => _editor = null; + } + + public void Dispose() + { + _editor?.Dispose(); + } + + private sealed class InstanceEditor : IDisposable + { + public event Action? OnDisposed; + + private readonly Dictionary _variables = new(); + + public InstanceEditor(ToolbarWidget widget, WindowManager windowManager) + { + foreach (IWidgetConfigVariable wVar in widget.GetConfigVariableList()) { + if (wVar.IsHidden) continue; + + Variable? variable = ConvertWidgetVariable(widget, wVar); + if (variable == null) continue; + + _variables.Add(variable, wVar); + } + + windowManager.Present( + "WidgetInstanceEditor", + new VariablesWindow(widget.GetInstanceName(), _variables.Keys.ToList()), + _ => { + Dispose(); + } + ); + } + + public void Dispose() + { + foreach (Variable variable in _variables.Keys) variable.Dispose(); + _variables.Clear(); + + OnDisposed?.Invoke(); + + foreach (Delegate handler in OnDisposed?.GetInvocationList() ?? []) { + OnDisposed -= (Action)handler; + } + + OnDisposed = null; + } + + private static Variable? ConvertWidgetVariable(ToolbarWidget widget, IWidgetConfigVariable var) + { + switch (var) { + case IntegerWidgetConfigVariable i: { + IntegerVariable intVar = new(i.Id) { + Category = i.Category, + Name = i.Name, + Description = i.Description, + Value = i.Value, + Min = i.MinValue, + Max = i.MaxValue, + }; + + intVar.ValueChanged += v => widget.SetConfigValue(i.Id, v); + + return intVar; + } + case IconIdWidgetConfigVariable i: { + IconIdVariable iconVar = new(i.Id) { + Category = i.Category, + Name = i.Name, + Description = i.Description, + Value = i.Value, + }; + + iconVar.ValueChanged += v => widget.SetConfigValue(i.Id, v); + + return iconVar; + } + case FloatWidgetConfigVariable f: { + FloatVariable floatVar = new(f.Id) { + Category = f.Category, + Name = f.Name, + Description = f.Description, + Value = f.Value, + Min = f.MinValue, + Max = f.MaxValue, + }; + + floatVar.ValueChanged += v => widget.SetConfigValue(f.Id, v); + + return floatVar; + } + case BooleanWidgetConfigVariable b: { + BooleanVariable boolVar = new(b.Id) { + Category = b.Category, + Name = b.Name, + Description = b.Description, + Value = b.Value, + }; + + boolVar.ValueChanged += v => widget.SetConfigValue(b.Id, v); + + return boolVar; + } + case StringWidgetConfigVariable s: { + StringVariable stringVar = new(s.Id) { + Category = s.Category, + Name = s.Name, + Description = s.Description, + Value = s.Value, + }; + + stringVar.ValueChanged += v => widget.SetConfigValue(s.Id, v); + + return stringVar; + } + case SelectWidgetConfigVariable select: { + StringSelectVariable selectVar = new(select.Id) { + Category = select.Category, + Name = select.Name, + Description = select.Description, + Value = select.Value, + Choices = select.Options, + }; + + selectVar.ValueChanged += v => widget.SetConfigValue(select.Id, v); + + return selectVar; + } + case ColorWidgetConfigVariable c: { + ColorVariable colorVar = new(c.Id) { + Category = c.Category, + Name = c.Name, + Description = c.Description, + Value = c.Value, + }; + + colorVar.ValueChanged += v => widget.SetConfigValue(c.Id, v); + + return colorVar; + } + default: + Logger.Warning($"No conversion for {var.GetType().Name}."); + return null; + } + } + } +} diff --git a/Umbra/src/Toolbar/Widgets/System/Types/ToolbarWidget.cs b/Umbra/src/Toolbar/Widgets/System/Types/ToolbarWidget.cs index b03cabda..28261653 100644 --- a/Umbra/src/Toolbar/Widgets/System/Types/ToolbarWidget.cs +++ b/Umbra/src/Toolbar/Widgets/System/Types/ToolbarWidget.cs @@ -345,7 +345,7 @@ protected static Dictionary GetColorSelectOptions() /// protected void OpenSettingsWindow() { - Framework.Service().OpenWidgetSettingsWindow(this); + Framework.Service().OpenEditor(this); } private IEnumerable GetConfigVariablesInternal() diff --git a/Umbra/src/Toolbar/Widgets/System/WidgetManager.cs b/Umbra/src/Toolbar/Widgets/System/WidgetManager.cs index 9b0d4ebd..c4d7dcc6 100644 --- a/Umbra/src/Toolbar/Widgets/System/WidgetManager.cs +++ b/Umbra/src/Toolbar/Widgets/System/WidgetManager.cs @@ -325,27 +325,6 @@ public uint GetWidgetInstanceCount(string widgetId) return (uint)_instances.Values.Count(w => w.Info.Id == widgetId); } - /// - /// Opens the settings window for the given widget instance. - /// - public void OpenWidgetSettingsWindow(ToolbarWidget widget) - { - if (_currentActivator is not null) { - ClosePopup(); - } - - Framework - .Service() - .Present( - "WidgetInstanceConfig", - new WidgetConfigWindow(widget.Id), - _ => { - SaveWidgetState(widget.Id); - SaveState(); - } - ); - } - /// /// Updates the sort indices of all widgets to ensure there are no gaps. /// @@ -432,7 +411,7 @@ private void InvokeInstanceQuickSettings(Node node) foreach (ToolbarWidget widget in _instances.Values) { if (widget.Node == node) { node.CancelEvent = true; - OpenWidgetSettingsWindow(widget); + Framework.Service().OpenEditor(widget); break; } } diff --git a/Umbra/src/Windows/Components/IconIdInputNode.cs b/Umbra/src/Windows/Components/IconIdInputNode.cs new file mode 100644 index 00000000..f1cab9da --- /dev/null +++ b/Umbra/src/Windows/Components/IconIdInputNode.cs @@ -0,0 +1,213 @@ +/* Umbra | (c) 2024 by Una ____ ___ ___. + * Licensed under the terms of AGPL-3 | | \ _____ \_ |__ _______ _____ + * | | // \ | __ \\_ __ \\__ \ + * https://github.com/una-xiv/umbra | | /| Y Y \| \_\ \| | \/ / __ \_ + * |______//__|_| /____ /|__| (____ / + * Umbra is free software: you can redistribute \/ \/ \/ + * it and/or modify it under the terms of the GNU Affero General Public + * License as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Umbra UI is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + */ + +using System; +using System.Numerics; +using ImGuiNET; +using Lumina.Excel.GeneratedSheets; +using Umbra.Common; +using Umbra.Windows.Library.IconPicker; +using Una.Drawing; + +namespace Umbra.Windows.Components; + +public class IconIdInputNode : Node +{ + public event Action? OnValueChanged; + + public uint Value { + get => _value; + set + { + if (_value == value) return; + _value = value; + OnValueChanged?.Invoke(value); + } + } + + public string Label { + get => (string)(LabelNode.NodeValue ?? ""); + set => LabelNode.NodeValue = value; + } + + public string? Description { + get => (string?)DescriptionNode.NodeValue; + set => DescriptionNode.NodeValue = value; + } + + private uint _value; + + public IconIdInputNode(string id, uint value, string label, string? description = null) + { + _value = value; + + Id = id; + ClassList = ["input"]; + Stylesheet = ColorInputStylesheet; + + ChildNodes = [ + new() { + Id = "IconBox", + ClassList = ["input--box"], + InheritTags = true, + }, + new() { + Id = "Text", + ClassList = ["input--text"], + InheritTags = true, + ChildNodes = [ + new() { + Id = "Label", + ClassList = ["input--text--label"], + InheritTags = true, + NodeValue = label, + }, + new() { + Id = "Description", + ClassList = ["input--text--description"], + InheritTags = true, + NodeValue = description, + }, + ], + }, + ]; + + Label = label; + Description = description; + + BeforeReflow += _ => { + int maxWidth = ParentNode!.Bounds.ContentSize.Width - ParentNode!.ComputedStyle.Padding.HorizontalSize; + int padding = ComputedStyle.Gap + BoxNode.OuterWidth; + int width = (int)((maxWidth - padding) / ScaleFactor); + int labelHeight; + + if (LabelNode.Style.Size?.Width == width && DescriptionNode.Style.Size?.Width == width) { + return false; + } + + if (string.IsNullOrEmpty((string?)DescriptionNode.NodeValue)) { + DescriptionNode.Style.IsVisible = false; + labelHeight = 24; + } else { + DescriptionNode.Style.IsVisible = true; + labelHeight = 0; + } + + LabelNode.Style.Size = new(width, labelHeight); + DescriptionNode.Style.Size = new(width, 0); + + return true; + }; + + OnMouseUp += _ => { + Framework.Service().Present( + "IconPicker", + new IconPickerWindow(Value), + window => { + Value = window.IconId; + } + ); + }; + } + + protected override void OnDisposed() + { + foreach (var handler in OnValueChanged?.GetInvocationList() ?? []) OnValueChanged -= (Action)handler; + + OnValueChanged = null; + + base.OnDisposed(); + } + + protected override void OnDraw(ImDrawListPtr drawList) + { + BoxNode.Style.IconId = Value; + } + + private Node BoxNode => QuerySelector(".input--box")!; + private Node LabelNode => QuerySelector(".input--text--label")!; + private Node DescriptionNode => QuerySelector(".input--text--description")!; + + private static Stylesheet ColorInputStylesheet { get; } = new( + [ + new( + ".input", + new() { + Flow = Flow.Horizontal, + Gap = 8, + } + ), + new( + ".input--box", + new() { + Flow = Flow.Horizontal, + Anchor = Anchor.TopLeft, + Size = new(28, 28), + BorderRadius = 5, + StrokeWidth = 3, + StrokeInset = -1, + BackgroundColor = new(0), + StrokeColor = new("Input.Background"), + Color = new("Input.Text"), + IsAntialiased = false, + } + ), + new( + ".input--box:hover", + new() { + StrokeColor = new("Input.BorderHover"), + Color = new("Input.TextHover"), + } + ), + new( + ".input--text", + new() { + Flow = Flow.Vertical, + Anchor = Anchor.TopLeft, + Gap = 4, + } + ), + new( + ".input--text--label", + new() { + Anchor = Anchor.TopLeft, + TextAlign = Anchor.MiddleLeft, + TextOverflow = false, + FontSize = 14, + Color = new("Input.Text"), + WordWrap = false, + } + ), + new( + ".input--text--label:hover", + new() { + Color = new("Input.TextHover"), + } + ), + new( + ".input--text--description", + new() { + Anchor = Anchor.TopLeft, + FontSize = 11, + Color = new("Input.TextMuted"), + TextOverflow = false, + WordWrap = true, + LineHeight = 1.5f, + } + ), + ] + ); +} diff --git a/Umbra/src/Windows/Library/IconPicker/IconGridNode.cs b/Umbra/src/Windows/Library/IconPicker/IconGridNode.cs new file mode 100644 index 00000000..df179ff2 --- /dev/null +++ b/Umbra/src/Windows/Library/IconPicker/IconGridNode.cs @@ -0,0 +1,102 @@ +using Dalamud.Interface; +using Dalamud.Interface.Colors; +using Dalamud.Interface.Textures.TextureWraps; +using Dalamud.Interface.Utility; +using Dalamud.Plugin.Services; +using ImGuiNET; +using System; +using System.Collections.Generic; +using System.Numerics; +using Umbra.Common; +using Una.Drawing; + +namespace Umbra.Windows.Library.IconPicker; + +public class IconGridNode : Node +{ + public uint SelectedId { get; set; } + + private ITextureProvider TextureProvider { get; } = Framework.Service(); + + private Vector2 IconSize { get; set; } = new(48, 48); + + private List IconIds { get; } + + public IconGridNode(List iconIds, uint selectedId) + { + IconIds = iconIds; + SelectedId = selectedId; + NodeValue = " "; + } + + protected override void OnDraw(ImDrawListPtr drawList) + { + if (ParentNode == null || ParentNode.Bounds.ContentSize.IsZero) return; + + IconSize = new(48 * ScaleFactor); + + Size size = ParentNode.Bounds.ContentSize - new Size((int)(8 * ScaleFactor), (int)(16 * ScaleFactor)); + Vector2 pos = ParentNode.Bounds.ContentRect.TopLeft + new Vector2(8 * ScaleFactor); + int rowHeight = (int)(IconSize.Y + (8 * ScaleFactor)); + int iconsPerRow = (int)MathF.Floor(size.Width / (IconSize.X + (8 * ScaleFactor))); + + ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, new Vector2(0, 0)); + ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(0, 0)); + ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(8 * ScaleFactor)); + ImGui.SetCursorScreenPos(pos); + + if (ImGui.BeginChild("IconPickerIconGrid", size.ToVector2(), false, ImGuiWindowFlags.NoMove)) { + ImGuiClip.ClippedDraw(IconIds, this.DrawIcon, iconsPerRow, rowHeight); + } + + ImGui.EndChild(); + ImGui.PopStyleVar(3); + } + + private void DrawIcon(uint iconId) + { + Vector2 pos = ImGui.GetCursorScreenPos(); + + if (!TextureProvider.TryGetFromGameIcon(new(iconId), out var texture)) { + return; + } + + if (!texture.TryGetWrap(out IDalamudTextureWrap? wrap, out Exception? e)) { + return; + } + + ImDrawListPtr drawList = ImGui.GetWindowDrawList(); + + Vector2 p1 = pos; + Vector2 p2 = pos + IconSize; + Vector2 p3 = p1 + new Vector2(2); + Vector2 p4 = p2 - new Vector2(2); + + ImGui.Dummy(IconSize); + + drawList.AddRectFilled(p1, p2, new Color("Input.Background").ToUInt(), 6, ImDrawFlags.RoundCornersAll); + drawList.AddRect(p1, p2, new Color("Input.Border").ToUInt(), 6, ImDrawFlags.RoundCornersAll, 1); + drawList.AddImageRounded( + wrap.ImGuiHandle, + p3, + p4, + Vector2.Zero, + Vector2.One, + 0xFFFFFFFF, + 6, + ImDrawFlags.RoundCornersAll + ); + + if (iconId == SelectedId) { + drawList.AddRect(p1, p2, 0xFFFFFFFF, 6, ImDrawFlags.RoundCornersAll, 2); + } + + if (ImGui.IsItemHovered()) { + drawList.AddRect(p1, p2, 0xFF00FFFF, 6, ImDrawFlags.RoundCornersAll, 1); + } + + if (ImGui.IsItemClicked(ImGuiMouseButton.Left)) { + SelectedId = iconId; + } + } +} diff --git a/Umbra/src/Windows/Library/IconPicker/IconPickerWindow.Nodes.cs b/Umbra/src/Windows/Library/IconPicker/IconPickerWindow.Nodes.cs new file mode 100644 index 00000000..c3a2fc38 --- /dev/null +++ b/Umbra/src/Windows/Library/IconPicker/IconPickerWindow.Nodes.cs @@ -0,0 +1,106 @@ +using System.Linq; +using System.Numerics; +using Umbra.Common; +using Umbra.Windows.Components; +using Una.Drawing; + +namespace Umbra.Windows.Library.IconPicker; + +public sealed partial class IconPickerWindow +{ + protected override Node Node { get; } = new() { + Id = "IconPickerWindow", + Stylesheet = Stylesheet, + ChildNodes = [ + new() { + Id = "Header", + ChildNodes = [ + new() { + Id = "IconPreview", + }, + new() { + Id = "HeaderContent", + ChildNodes = [ + new() { + Id = "CategoryWrapper", + ChildNodes = [ + new SelectNode( + "CategoryId", + "General", + CategoryLabels.Keys.ToList(), + I18N.Translate("Window.IconPicker.Category") + ) + ] + }, + new() { + Id = "IconIdWrapper", + ChildNodes = [ + new IntegerInputNode( + "IconId", + 0, + 0, + int.MaxValue, + I18N.Translate("Window.IconPicker.IconId") + ) + ] + }, + ] + } + ] + }, + new() { + Id = "Body", + }, + new() { + Id = "Footer", + ChildNodes = [ + new() { + Id = "FooterButtons", + ChildNodes = [ + new ButtonNode("Undo", I18N.Translate("Undo")), + new ButtonNode("CloseButton", I18N.Translate("Close")), + ] + }, + ] + } + ] + }; + + private Node IconPreviewNode => Node.QuerySelector("#IconPreview")!; + private Node HeaderNode => Node.QuerySelector("#Header")!; + private Node HeaderContentNode => Node.QuerySelector("#HeaderContent")!; + private Node CategoryWrapper => Node.QuerySelector("#CategoryWrapper")!; + private Node IconIdWrapper => Node.QuerySelector("#IconIdWrapper")!; + private SelectNode CategorySelectNode => CategoryWrapper.QuerySelector("#CategoryId")!; + private IntegerInputNode IconIdInputNode => Node.QuerySelector("#IconId")!; + private Node BodyNode => Node.QuerySelector("#Body")!; + private Node FooterNode => Node.QuerySelector("#Footer")!; + private ButtonNode CloseButtonNode => FooterNode.QuerySelector("#CloseButton")!; + private ButtonNode UndoButtonNode => FooterNode.QuerySelector("#Undo")!; + + private void UpdateNodeSizes() + { + int headerWidth = ContentSize.Width - 48; + + Node.Style.Size = ContentSize; + IconPreviewNode.Style.IconId = IconId; + HeaderNode.Style.Size = new(ContentSize.Width, 64); + FooterNode.Style.Size = new(ContentSize.Width, 50); + HeaderContentNode.Style.Size = new(headerWidth, 48); + IconIdWrapper.Style.Size = new((headerWidth / 2) - 4, 48); + CategoryWrapper.Style.Size = new((headerWidth / 2) - 4, 48); + BodyNode.Style.Size = new(ContentSize.Width, ContentSize.Height - 114); + IconIdInputNode.Style.Padding = new(0); + IconIdInputNode.Style.Gap = 0; + CategorySelectNode.Style.Padding = new(0); + CategorySelectNode.Style.Gap = 0; + UndoButtonNode.Style.IsVisible = IconId != LastIconId; + + IconGridNode? gridNode = BodyNode.QuerySelector("IconGrid"); + + if (gridNode is not null && gridNode.SelectedId != IconId) { + IconId = gridNode.SelectedId; + IconIdInputNode.Value = (int)IconId; + } + } +} diff --git a/Umbra/src/Windows/Library/IconPicker/IconPickerWindow.Stylesheet.cs b/Umbra/src/Windows/Library/IconPicker/IconPickerWindow.Stylesheet.cs new file mode 100644 index 00000000..e4fa2345 --- /dev/null +++ b/Umbra/src/Windows/Library/IconPicker/IconPickerWindow.Stylesheet.cs @@ -0,0 +1,81 @@ +using System.Numerics; +using Umbra.Common; +using Una.Drawing; + +namespace Umbra.Windows.Library.IconPicker; + +public sealed partial class IconPickerWindow : Window +{ + private static Stylesheet Stylesheet { get; } = new( + [ + new( + "#IconPickerWindow", + new() { + Flow = Flow.Vertical, + } + ), + new( + "#Header", + new() { + BackgroundColor = new("Window.BackgroundLight"), + BorderColor = new() { Bottom = new("Window.Border") }, + BorderWidth = new() { Bottom = 1 }, + IsAntialiased = false, + Gap = 8, + Size = new(64, 0), + Padding = new(6), + } + ), + new( + "#IconPreview", + new() { + Size = new(52, 52), + BackgroundColor = new("Input.Background"), + StrokeColor = new("Input.Border"), + StrokeWidth = 1, + BorderRadius = 6, + IsAntialiased = false, + } + ), + new( + "#HeaderContent", + new() { + Flow = Flow.Horizontal, + Gap = 8, + } + ), + new( + "#Body", + new() { + Flow = Flow.Vertical, + } + ), + new( + "#Content", + new() { + Flow = Flow.Vertical, + Padding = new(8), + } + ), + new( + "#Footer", + new() { + Flow = Flow.Horizontal, + Gap = 15, + Padding = new(0, 15), + BackgroundColor = new("Window.BackgroundLight"), + BorderWidth = new() { Top = 1 }, + BorderColor = new() { Top = new("Window.Border") }, + IsAntialiased = false, + } + ), + new( + "#FooterButtons", + new() { + Anchor = Anchor.MiddleRight, + Gap = 15, + } + ), + ] + ); +} diff --git a/Umbra/src/Windows/Library/IconPicker/IconPickerWindow.cs b/Umbra/src/Windows/Library/IconPicker/IconPickerWindow.cs new file mode 100644 index 00000000..ffa100b2 --- /dev/null +++ b/Umbra/src/Windows/Library/IconPicker/IconPickerWindow.cs @@ -0,0 +1,125 @@ +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using Umbra.Common; + +namespace Umbra.Windows.Library.IconPicker; + +public sealed partial class IconPickerWindow(uint iconId) : Window +{ + public uint LastIconId { get; private set; } = iconId; + public uint IconId { get; set; } = iconId; + + protected override Vector2 MinSize { get; } = new(752, 600); + protected override Vector2 MaxSize { get; } = new(1200, 900); + protected override Vector2 DefaultSize { get; } = new(752, 600); + protected override string Title { get; } = I18N.Translate("Window.IconPicker.Title"); + + private static Dictionary> Categories { get; } = new() { + { + "General", + [ + (0, 94), (76216, 76216), (101, 125), (651, 652), (66001, 66001), (66021, 66023), (66031, 66033), + (66041, 66043), (66051, 66053), (66061, 66063), (66071, 66073), (66081, 66083), (66101, 66105), + (66121, 66125), (66141, 66145), (66161, 66171), (66181, 66191), (66301, 66341), (66401, 66423), + (66452, 66473), (60001, 6004), (60011, 60013), (60026, 60048), (60071, 60074), (61471, 61489), + (61501, 61548), (61551, 61598), (61751, 61768), (61801, 61880) + ] + }, + { "Jobs", [(62001, 62042), (62801, 62842), (62226, 62267), (62101, 62142), (62301, 62320), (62401, 62422)] }, { + "Quests", + [ + (71001, 71006), (71021, 71025), (71041, 71045), (71061, 70165), (71081, 70185), (71101, 71102), + (71121, 71125), (71141, 71145), (71201, 71205), (71221, 71225), (61721, 61723), (61731, 61733) + ] + }, + { "Avatars", [(76951, 76994), (62145, 62146), (72001, 72059), (72556, 72607)] }, + { "Emotes", [(64001, 64099), (64101, 64133), (64151, 64154), (64326, 64452)] }, + { "Rewards", [(65001, 65110)] }, { + "MapMarkers", + [ + (60401, 60408), (60412, 60482), (60501, 60508), (60511, 60515), (60550, 60565), (60567, 60583), + (60585, 60611), (60640, 60649), (60651, 60662), (60751, 60792), (60901, 60999) + ] + }, { + "Shapes", + [ + (76401, 76415), (76451, 76467), (76171, 76174), (76176, 76186), (76531, 76535), (76539, 76549), + (76556, 76588), (82091, 82093), (90001, 90004), (90200, 90263), (90401, 90463), (61901, 61917) + ] + }, + { "Minions", [(4401, 4926), (59401, 59926)] }, + { "Mounts", [(4001, 4098), (4101, 4293)] }, + }; + + private static Dictionary CategoryLabels { get; } = new() { + { I18N.Translate("Window.IconPicker.Category.General"), "General" }, + { I18N.Translate("Window.IconPicker.Category.Jobs"), "Jobs" }, + { I18N.Translate("Window.IconPicker.Category.Quests"), "Quests" }, + { I18N.Translate("Window.IconPicker.Category.Avatars"), "Avatars" }, + { I18N.Translate("Window.IconPicker.Category.Emotes"), "Emotes" }, + { I18N.Translate("Window.IconPicker.Category.Rewards"), "Rewards" }, + { I18N.Translate("Window.IconPicker.Category.MapMarkers"), "MapMarkers" }, + { I18N.Translate("Window.IconPicker.Category.Shapes"), "Shapes" }, + { I18N.Translate("Window.IconPicker.Category.Minions"), "Minions" }, + { I18N.Translate("Window.IconPicker.Category.Mounts"), "Mounts" }, + }; + + protected override void OnOpen() + { + IconIdInputNode.Value = (int)IconId; + IconIdInputNode.OnValueChanged += OnIconIdInputChanged; + CategorySelectNode.OnValueChanged += OnCategorySelectChanged; + + CloseButtonNode.OnMouseUp += _ => Close(); + + UndoButtonNode.OnMouseUp += _ => { + IconId = LastIconId; + IconIdInputNode.Value = (int)IconId; + IconGridNode? node = BodyNode.QuerySelector("IconGrid"); + if (node != null) node.SelectedId = IconId; + }; + + OnCategorySelectChanged(CategoryLabels.Keys.First()); + } + + protected override void OnClose() + { + IconIdInputNode.OnValueChanged -= OnIconIdInputChanged; + CategorySelectNode.OnValueChanged -= OnCategorySelectChanged; + } + + protected override void OnUpdate(int instanceId) + { + UpdateNodeSizes(); + } + + private void OnIconIdInputChanged(int value) + { + IconId = (uint)value; + + IconGridNode? node = BodyNode.QuerySelector("IconGrid"); + if (node != null) node.SelectedId = IconId; + } + + private void OnCategorySelectChanged(string value) + { + List ids = GetIconIds(Categories[CategoryLabels[value]]); + + BodyNode.QuerySelector("IconGrid")?.Dispose(); + BodyNode.AppendChild(new IconGridNode(ids, IconId) { Id = "IconGrid" }); + } + + private static List GetIconIds(List<(uint, uint)> idRanges) + { + List ids = []; + + foreach (var range in idRanges) { + for (uint i = range.Item1; i <= range.Item2; i++) { + ids.Add(i); + } + } + + return ids; + } +} diff --git a/Umbra/src/Windows/Library/Settings/Modules/AuxWidgetsModule.Nodes.cs b/Umbra/src/Windows/Library/Settings/Modules/AuxWidgetsModule.Nodes.cs index 7528e76d..0748e139 100644 --- a/Umbra/src/Windows/Library/Settings/Modules/AuxWidgetsModule.Nodes.cs +++ b/Umbra/src/Windows/Library/Settings/Modules/AuxWidgetsModule.Nodes.cs @@ -5,7 +5,6 @@ using Umbra.Widgets; using Umbra.Widgets.System; using Umbra.Windows.Components; -using Umbra.Windows.Library.WidgetConfig; using Una.Drawing; namespace Umbra.Windows.Settings.Modules; @@ -280,16 +279,7 @@ private Node CreateWidgetInstanceNode(ToolbarWidget widget) } }; - settingsButton.OnMouseUp += _ => Framework - .Service() - .Present( - "WidgetInstanceConfig", - new WidgetConfigWindow(widget.Id), - _ => { - wm.SaveWidgetState(widget.Id); - wm.SaveState(); - } - ); + settingsButton.OnMouseUp += _ => Framework.Service().OpenEditor(widget); nameNode.OnMouseUp += _ => { _selectedInstanceId = _selectedInstanceId == widget.Id ? "" : widget.Id; diff --git a/Umbra/src/Windows/Library/Settings/Modules/WidgetsModule.Nodes.cs b/Umbra/src/Windows/Library/Settings/Modules/WidgetsModule.Nodes.cs index a3f255b3..116cfc7e 100644 --- a/Umbra/src/Windows/Library/Settings/Modules/WidgetsModule.Nodes.cs +++ b/Umbra/src/Windows/Library/Settings/Modules/WidgetsModule.Nodes.cs @@ -14,16 +14,15 @@ * GNU Affero General Public License for more details. */ -using System; using Dalamud.Game.Text; using Dalamud.Interface; using ImGuiNET; +using System; using Umbra.Common; using Umbra.Widgets; using Umbra.Widgets.System; using Umbra.Windows.Components; using Umbra.Windows.Library.AddWidget; -using Umbra.Windows.Library.WidgetConfig; using Una.Drawing; namespace Umbra.Windows.Settings.Modules; @@ -237,16 +236,7 @@ private Node CreateWidgetInstanceNode(ToolbarWidget widget) } }; - settingsButton.OnMouseUp += _ => Framework - .Service() - .Present( - "WidgetInstanceConfig", - new WidgetConfigWindow(widget.Id), - _ => { - wm.SaveWidgetState(widget.Id); - wm.SaveState(); - } - ); + settingsButton.OnMouseUp += _ => Framework.Service().OpenEditor(widget); nameNode.OnMouseUp += _ => { _selectedInstanceId = _selectedInstanceId == widget.Id ? "" : widget.Id; diff --git a/Umbra/src/Windows/Library/VariablesWindow/Variable/BooleanVariable.cs b/Umbra/src/Windows/Library/VariablesWindow/Variable/BooleanVariable.cs index 1da541cb..5430b0bb 100644 --- a/Umbra/src/Windows/Library/VariablesWindow/Variable/BooleanVariable.cs +++ b/Umbra/src/Windows/Library/VariablesWindow/Variable/BooleanVariable.cs @@ -1,6 +1,30 @@ -namespace Umbra.Windows.Library.VariablesWindow; +using System; -public class BooleanVariable(string id) : Variable(id) +namespace Umbra.Windows.Library.VariablesWindow; + +public sealed class BooleanVariable(string id) : Variable(id), IDisposable { - public bool Value { get; set; } = false; + public bool Value { + get => _value; + set + { + if (_value == value) return; + + _value = value; + ValueChanged?.Invoke(value); + } + } + + private bool _value = false; + + public event Action? ValueChanged; + + public override void Dispose() + { + foreach (Delegate handler in ValueChanged?.GetInvocationList() ?? []) { + ValueChanged -= (Action)handler; + } + + ValueChanged = null; + } } diff --git a/Umbra/src/Windows/Library/VariablesWindow/Variable/ColorVariable.cs b/Umbra/src/Windows/Library/VariablesWindow/Variable/ColorVariable.cs index 708b0cb4..5300d3be 100644 --- a/Umbra/src/Windows/Library/VariablesWindow/Variable/ColorVariable.cs +++ b/Umbra/src/Windows/Library/VariablesWindow/Variable/ColorVariable.cs @@ -1,8 +1,32 @@ -namespace Umbra.Windows.Library.VariablesWindow; +using System; -public class ColorVariable(string id) : Variable(id) +namespace Umbra.Windows.Library.VariablesWindow; + +public sealed class ColorVariable(string id) : Variable(id), IDisposable { - public uint Value { get; set; } = 0; public uint Min { get; set; } = 0; public uint Max { get; set; } = 0xFFFFFFFF; + public uint Value { + get => _value; + set + { + if (_value == value) return; + + _value = value; + ValueChanged?.Invoke(value); + } + } + + private uint _value; + + public event Action? ValueChanged; + + public override void Dispose() + { + foreach (Delegate handler in ValueChanged?.GetInvocationList() ?? []) { + ValueChanged -= (Action)handler; + } + + ValueChanged = null; + } } diff --git a/Umbra/src/Windows/Library/VariablesWindow/Variable/FloatVariable.cs b/Umbra/src/Windows/Library/VariablesWindow/Variable/FloatVariable.cs index 7634ddef..e43da2e4 100644 --- a/Umbra/src/Windows/Library/VariablesWindow/Variable/FloatVariable.cs +++ b/Umbra/src/Windows/Library/VariablesWindow/Variable/FloatVariable.cs @@ -1,8 +1,32 @@ -namespace Umbra.Windows.Library.VariablesWindow; +using System; -public class FloatVariable(string id) : Variable(id) +namespace Umbra.Windows.Library.VariablesWindow; + +public sealed class FloatVariable(string id) : Variable(id), IDisposable { - public float Value { get; set; } = 0; public float Min { get; set; } = float.MinValue; public float Max { get; set; } = float.MaxValue; + public float Value { + get => _value; + set + { + if (_value == value) return; + + _value = value; + ValueChanged?.Invoke(value); + } + } + + private float _value; + + public event Action? ValueChanged; + + public override void Dispose() + { + foreach (Delegate handler in ValueChanged?.GetInvocationList() ?? []) { + ValueChanged -= (Action)handler; + } + + ValueChanged = null; + } } diff --git a/Umbra/src/Windows/Library/VariablesWindow/Variable/IconIdVariable.cs b/Umbra/src/Windows/Library/VariablesWindow/Variable/IconIdVariable.cs new file mode 100644 index 00000000..636dd197 --- /dev/null +++ b/Umbra/src/Windows/Library/VariablesWindow/Variable/IconIdVariable.cs @@ -0,0 +1,30 @@ +using System; + +namespace Umbra.Windows.Library.VariablesWindow; + +public sealed class IconIdVariable(string id) : Variable(id), IDisposable +{ + public uint Value { + get => _value; + set + { + if (_value == value) return; + + _value = value; + ValueChanged?.Invoke(value); + } + } + + private uint _value; + + public event Action? ValueChanged; + + public override void Dispose() + { + foreach (Delegate handler in ValueChanged?.GetInvocationList() ?? []) { + ValueChanged -= (Action)handler; + } + + ValueChanged = null; + } +} diff --git a/Umbra/src/Windows/Library/VariablesWindow/Variable/IntegerVariable.cs b/Umbra/src/Windows/Library/VariablesWindow/Variable/IntegerVariable.cs index bc0c870f..1437b8a4 100644 --- a/Umbra/src/Windows/Library/VariablesWindow/Variable/IntegerVariable.cs +++ b/Umbra/src/Windows/Library/VariablesWindow/Variable/IntegerVariable.cs @@ -1,8 +1,32 @@ -namespace Umbra.Windows.Library.VariablesWindow; +using System; -public class IntegerVariable(string id) : Variable(id) +namespace Umbra.Windows.Library.VariablesWindow; + +public sealed class IntegerVariable(string id) : Variable(id), IDisposable { - public int Value { get; set; } = 0; public int Min { get; set; } = int.MinValue; public int Max { get; set; } = int.MaxValue; + public int Value { + get => _value; + set + { + if (_value == value) return; + + _value = value; + ValueChanged?.Invoke(value); + } + } + + private int _value; + + public event Action? ValueChanged; + + public override void Dispose() + { + foreach (Delegate handler in ValueChanged?.GetInvocationList() ?? []) { + ValueChanged -= (Action)handler; + } + + ValueChanged = null; + } } diff --git a/Umbra/src/Windows/Library/VariablesWindow/Variable/StringSelectVariable.cs b/Umbra/src/Windows/Library/VariablesWindow/Variable/StringSelectVariable.cs index e21132ff..c4485037 100644 --- a/Umbra/src/Windows/Library/VariablesWindow/Variable/StringSelectVariable.cs +++ b/Umbra/src/Windows/Library/VariablesWindow/Variable/StringSelectVariable.cs @@ -1,9 +1,33 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace Umbra.Windows.Library.VariablesWindow; -public class StringSelectVariable(string id) : Variable(id) +public sealed class StringSelectVariable(string id) : Variable(id), IDisposable { - public string Value { get; set; } = string.Empty; public Dictionary Choices { get; set; } = []; + + public string Value { + get => _value; + set + { + if (_value == value) return; + + _value = value; + ValueChanged?.Invoke(value); + } + } + + private string _value = string.Empty; + + public event Action? ValueChanged; + + public override void Dispose() + { + foreach (Delegate handler in ValueChanged?.GetInvocationList() ?? []) { + ValueChanged -= (Action)handler; + } + + ValueChanged = null; + } } diff --git a/Umbra/src/Windows/Library/VariablesWindow/Variable/StringVariable.cs b/Umbra/src/Windows/Library/VariablesWindow/Variable/StringVariable.cs index 7d16bcce..874865ce 100644 --- a/Umbra/src/Windows/Library/VariablesWindow/Variable/StringVariable.cs +++ b/Umbra/src/Windows/Library/VariablesWindow/Variable/StringVariable.cs @@ -1,8 +1,31 @@ -namespace Umbra.Windows.Library.VariablesWindow; +using System; -public class StringVariable(string id) : Variable(id) -{ - public string Value { get; set; } = string.Empty; +namespace Umbra.Windows.Library.VariablesWindow; +public sealed class StringVariable(string id) : Variable(id), IDisposable +{ public uint MaxLength { get; set; } = 255; + public string Value { + get => _value; + set + { + if (_value == value) return; + + _value = value; + ValueChanged?.Invoke(value); + } + } + + private string _value = string.Empty; + + public event Action? ValueChanged; + + public override void Dispose() + { + foreach (Delegate handler in ValueChanged?.GetInvocationList() ?? []) { + ValueChanged -= (Action)handler; + } + + ValueChanged = null; + } } diff --git a/Umbra/src/Windows/Library/VariablesWindow/Variable/Variable.cs b/Umbra/src/Windows/Library/VariablesWindow/Variable/Variable.cs index f8d0df6a..fdee0dd6 100644 --- a/Umbra/src/Windows/Library/VariablesWindow/Variable/Variable.cs +++ b/Umbra/src/Windows/Library/VariablesWindow/Variable/Variable.cs @@ -6,4 +6,6 @@ public abstract class Variable(string id) public string Name { get; set; } = "Unnamed Variable"; public string? Description { get; set; } public string? Category { get; set; } + + public abstract void Dispose(); } diff --git a/Umbra/src/Windows/Library/VariablesWindow/VariablesWindow.Nodes.cs b/Umbra/src/Windows/Library/VariablesWindow/VariablesWindow.Nodes.cs index f174784c..6f3bb19a 100644 --- a/Umbra/src/Windows/Library/VariablesWindow/VariablesWindow.Nodes.cs +++ b/Umbra/src/Windows/Library/VariablesWindow/VariablesWindow.Nodes.cs @@ -127,7 +127,8 @@ private Node CreateCategoryNode(string name) BooleanVariable boolVar => CreateBooleanControl(boolVar), ColorVariable colorVar => CreateColorControl(colorVar), IntegerVariable intVar => CreateIntegerControl(intVar), - FloatVariable floatVar => RenderFloatControl(floatVar), + FloatVariable floatVar => CreateFloatControl(floatVar), + IconIdVariable iconVar => CreateIconIdControl(iconVar), _ => null }; } @@ -223,7 +224,7 @@ private IntegerInputNode CreateIntegerControl(IntegerVariable variable) return node; } - private FloatInputNode RenderFloatControl(FloatVariable variable) + private FloatInputNode CreateFloatControl(FloatVariable variable) { var node = new FloatInputNode( GetNextControlId(variable), @@ -240,6 +241,21 @@ private FloatInputNode RenderFloatControl(FloatVariable variable) return node; } + private IconIdInputNode CreateIconIdControl(IconIdVariable variable) + { + var node = new IconIdInputNode( + GetNextControlId(variable), + variable.Value, + variable.Name, + variable.Description + ); + + node.ClassList.Add("widget-config-control"); + node.OnValueChanged += v => variable.Value = v; + + return node; + } + /// /// Returns a new ID for the control node. /// diff --git a/Umbra/src/Windows/Library/VariablesWindow/VariablesWindow.cs b/Umbra/src/Windows/Library/VariablesWindow/VariablesWindow.cs index c385440e..09e53a14 100644 --- a/Umbra/src/Windows/Library/VariablesWindow/VariablesWindow.cs +++ b/Umbra/src/Windows/Library/VariablesWindow/VariablesWindow.cs @@ -22,10 +22,11 @@ protected override void OnOpen() Node rootCategory = new() { ClassList = ["widget-config-list"], + SortIndex = int.MinValue, }; foreach (var variable in variables) { - if (variable.Category == null) { + if (string.IsNullOrEmpty(variable.Category)) { Node? rootCtrl = CreateControlNode(variable); if (rootCtrl != null) rootCategory.AppendChild(rootCtrl); continue; diff --git a/Umbra/src/Windows/Library/WidgetConfig/WidgetConfigWindow.Controls.cs b/Umbra/src/Windows/Library/WidgetConfig/WidgetConfigWindow.Controls.cs deleted file mode 100644 index b202cccb..00000000 --- a/Umbra/src/Windows/Library/WidgetConfig/WidgetConfigWindow.Controls.cs +++ /dev/null @@ -1,225 +0,0 @@ -/* Umbra | (c) 2024 by Una ____ ___ ___. - * Licensed under the terms of AGPL-3 | | \ _____ \_ |__ _______ _____ - * | | // \ | __ \\_ __ \\__ \ - * https://github.com/una-xiv/umbra | | /| Y Y \| \_\ \| | \/ / __ \_ - * |______//__|_| /____ /|__| (____ / - * Umbra is free software: you can redistribute \/ \/ \/ - * it and/or modify it under the terms of the GNU Affero General Public - * License as published by the Free Software Foundation, either version 3 - * of the License, or (at your option) any later version. - * - * Umbra UI is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - */ - -using System; -using System.Linq; -using Dalamud.Interface; -using Lumina.Misc; -using Umbra.Common; -using Umbra.Widgets; -using Umbra.Windows.Components; -using Una.Drawing; - -namespace Umbra.Windows.Library.WidgetConfig; - -internal partial class WidgetConfigWindow -{ - private void RenderControl(IWidgetConfigVariable cvar, Node targetNode) - { - if (cvar.IsHidden) return; - - Node? node = null; - - switch (cvar) { - case SelectWidgetConfigVariable s: - node = RenderSelectControl(s); - break; - case BooleanWidgetConfigVariable b: - node = RenderBooleanControl(b); - break; - case ColorWidgetConfigVariable b: - node = RenderColorControl(b); - break; - case IntegerWidgetConfigVariable i: - node = RenderIntegerControl(i); - break; - case FloatWidgetConfigVariable f: - node = RenderFloatControl(f); - break; - case StringWidgetConfigVariable s: - node = RenderStringControl(s); - break; - default: - Logger.Warning($"Cannot render widget control for {cvar.Id} ({cvar.GetType().Name})"); - break; - } - - if (node is not null) { - node.ClassList.Add("control"); - targetNode.AppendChild(node); - } - } - - private Node RenderCategory(string name) - { - Node contentNode = new() { - ClassList = ["widget-config-category--content"], - }; - - Node headerNode = new() { - ClassList = ["widget-config-category-header"], - ChildNodes = [ - new() { - ClassList = ["widget-config-category--chevron"], - NodeValue = FontAwesomeIcon.ChevronCircleUp.ToIconString(), - InheritTags = true, - }, - new() { - ClassList = ["widget-config-category--label"], - NodeValue = name, - InheritTags = true, - } - ] - }; - - Node node = new() { - ClassList = ["widget-config-category"], - ChildNodes = { - headerNode, - contentNode, - }, - }; - - ControlsListNode.AppendChild(node); - - contentNode.Style.IsVisible = true; - - headerNode.OnClick += _ => { - contentNode.Style.IsVisible = !contentNode.Style.IsVisible; - - headerNode.QuerySelector(".widget-config-category--chevron")!.NodeValue = contentNode.Style.IsVisible.Value - ? FontAwesomeIcon.ChevronCircleUp.ToIconString() - : FontAwesomeIcon.ChevronCircleDown.ToIconString(); - }; - - return contentNode; - } - - private SelectNode RenderSelectControl(SelectWidgetConfigVariable cvar) - { - if (cvar.Options.Count == 0) - throw new InvalidOperationException("A select control must have at least one option."); - - if (!cvar.Options.TryGetValue(Instance.GetConfigValue(cvar.Id), out string? selectedValue)) { - selectedValue = cvar.Options.First().Value; - } - - var node = new SelectNode( - GetNextControlId(cvar), - selectedValue, - cvar.Options.Values.ToList(), - cvar.Name, - cvar.Description - ); - - node.ClassList.Add("widget-config-control"); - node.OnValueChanged += newValue => { - if (cvar.Options.ContainsValue(newValue)) { - cvar.SetValue(cvar.Options.First(x => x.Value == newValue).Key); - } - }; - - return node; - } - - private CheckboxNode RenderBooleanControl(BooleanWidgetConfigVariable cvar) - { - CheckboxNode node = new( - GetNextControlId(cvar), - Instance.GetConfigValue(cvar.Id), - cvar.Name, - cvar.Description - ); - - node.ClassList.Add("widget-config-control"); - node.OnValueChanged += newValue => cvar.SetValue(newValue); - - return node; - } - - private ColorInputNode RenderColorControl(ColorWidgetConfigVariable cvar) - { - var node = new ColorInputNode( - GetNextControlId(cvar), - Instance.GetConfigValue(cvar.Id), - cvar.Name, - cvar.Description - ); - - node.ClassList.Add("widget-config-control"); - node.OnValueChanged += newValue => cvar.SetValue(newValue); - - return node; - } - - private IntegerInputNode RenderIntegerControl(IntegerWidgetConfigVariable cvar) - { - var node = new IntegerInputNode( - GetNextControlId(cvar), - Instance.GetConfigValue(cvar.Id), - cvar.MinValue, - cvar.MaxValue, - cvar.Name, - cvar.Description - ); - - node.ClassList.Add("widget-config-control"); - node.OnValueChanged += newValue => cvar.SetValue(newValue); - - return node; - } - - private FloatInputNode RenderFloatControl(FloatWidgetConfigVariable cvar) - { - var node = new FloatInputNode( - GetNextControlId(cvar), - Instance.GetConfigValue(cvar.Id), - cvar.MinValue, - cvar.MaxValue, - cvar.Name, - cvar.Description - ); - - node.ClassList.Add("widget-config-control"); - node.OnValueChanged += newValue => cvar.SetValue(newValue); - - return node; - } - - private StringInputNode RenderStringControl(StringWidgetConfigVariable cvar) - { - var node = new StringInputNode( - GetNextControlId(cvar), - Instance.GetConfigValue(cvar.Id), - (uint)cvar.MaxLength, - cvar.Name, - cvar.Description - ); - - node.ClassList.Add("widget-config-control"); - node.OnValueChanged += cvar.SetValue; - - return node; - } - - /// - /// Returns a new ID for the control node. - /// - private string GetNextControlId(IWidgetConfigVariable cvar) - { - return $"control-{Crc32.Get(cvar.Id)}"; - } -} diff --git a/Umbra/src/Windows/Library/WidgetConfig/WidgetConfigWindow.Nodes.cs b/Umbra/src/Windows/Library/WidgetConfig/WidgetConfigWindow.Nodes.cs deleted file mode 100644 index 7d3c7db9..00000000 --- a/Umbra/src/Windows/Library/WidgetConfig/WidgetConfigWindow.Nodes.cs +++ /dev/null @@ -1,94 +0,0 @@ -/* Umbra | (c) 2024 by Una ____ ___ ___. - * Licensed under the terms of AGPL-3 | | \ _____ \_ |__ _______ _____ - * | | // \ | __ \\_ __ \\__ \ - * https://github.com/una-xiv/umbra | | /| Y Y \| \_\ \| | \/ / __ \_ - * |______//__|_| /____ /|__| (____ / - * Umbra is free software: you can redistribute \/ \/ \/ - * it and/or modify it under the terms of the GNU Affero General Public - * License as published by the Free Software Foundation, either version 3 - * of the License, or (at your option) any later version. - * - * Umbra UI is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - */ - -using Dalamud.Interface; -using Umbra.Common; -using Umbra.Windows.Components; -using Una.Drawing; - -namespace Umbra.Windows.Library.WidgetConfig; - -internal partial class WidgetConfigWindow -{ - protected sealed override Node Node { get; } = new() { - Stylesheet = WindowStyles.WidgetConfigWindowStylesheet, - ClassList = ["widget-config-window"], - ChildNodes = [ - new() { - Id = "SearchPanel", - ChildNodes = [ - new() { - Id = "SearchIcon", - NodeValue = FontAwesomeIcon.Search.ToIconString(), - }, - new() { - Id = "SearchInputWrapper", - ChildNodes = [new StringInputNode("Search", "", 128, null, null, 0, true)] - } - ] - }, - new() { - ClassList = ["widget-config-list--wrapper"], - Overflow = false, - ChildNodes = [ - new() { - ClassList = ["widget-config-list"], - } - ] - }, - new() { - ClassList = ["widget-config-footer"], - ChildNodes = [ - new() { - ClassList = ["widget-config-footer--buttons", "left-side"], - ChildNodes = [ - new ButtonNode("CopyToClipboard", I18N.Translate("Copy")), - new ButtonNode("PasteFromClipboard", I18N.Translate("Paste")), - ] - }, - new() { - ClassList = ["widget-config-footer--buttons"], - ChildNodes = [ - new ButtonNode("CloseButton", I18N.Translate("Close")), - ] - }, - ] - } - ] - }; - - private void UpdateNodeSizes() - { - Node.Style.Size = ContentSize; - - Node.QuerySelector(".widget-config-list--wrapper")!.Style.Size = - new(ContentSize.Width, ContentSize.Height - 95); - - Node.QuerySelector("#SearchPanel")!.Style.Size = new(ContentSize.Width, 0); - Node.QuerySelector("#SearchInputWrapper")!.Style.Size = new(ContentSize.Width - 55, 0); - Node.QuerySelector(".widget-config-footer")!.Style.Size = new(ContentSize.Width, 50); - - foreach (var categoryNode in Node.QuerySelectorAll(".widget-config-category")) { - categoryNode.Style.Size = new(ContentSize.Width - 30, 0); - } - - foreach (var widgetNode in Node.QuerySelectorAll(".widget-config-control")) { - widgetNode.Style.Size = new(ContentSize.Width - 30, 0); - } - } - - private Node ControlsListNode => Node.QuerySelector(".widget-config-list")!; -} diff --git a/Umbra/src/Windows/Library/WidgetConfig/WidgetConfigWindow.cs b/Umbra/src/Windows/Library/WidgetConfig/WidgetConfigWindow.cs deleted file mode 100644 index 04800794..00000000 --- a/Umbra/src/Windows/Library/WidgetConfig/WidgetConfigWindow.cs +++ /dev/null @@ -1,150 +0,0 @@ -/* Umbra | (c) 2024 by Una ____ ___ ___. - * Licensed under the terms of AGPL-3 | | \ _____ \_ |__ _______ _____ - * | | // \ | __ \\_ __ \\__ \ - * https://github.com/una-xiv/umbra | | /| Y Y \| \_\ \| | \/ / __ \_ - * |______//__|_| /____ /|__| (____ / - * Umbra is free software: you can redistribute \/ \/ \/ - * it and/or modify it under the terms of the GNU Affero General Public - * License as published by the Free Software Foundation, either version 3 - * of the License, or (at your option) any later version. - * - * Umbra UI is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - */ - -using Lumina.Misc; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; -using Umbra.Common; -using Umbra.Widgets; -using Umbra.Widgets.System; -using Umbra.Windows.Components; -using Una.Drawing; - -namespace Umbra.Windows.Library.WidgetConfig; - -internal partial class WidgetConfigWindow : Window -{ - protected override string Title { get; } - protected override Vector2 MinSize { get; } = new(512, 300); - protected override Vector2 MaxSize { get; } = new(720, 1200); - protected override Vector2 DefaultSize { get; } = new(512, 300); - - private WidgetManager Manager { get; } - private ToolbarWidget Instance { get; } - - public WidgetConfigWindow(string guid) - { - Manager = Framework.Service(); - Instance = Manager.GetInstance(guid); - Title = Instance.Info.Name; - } - - protected override void OnOpen() - { - Manager.OnWidgetRemoved += OnWidgetRemoved; - Instance.OnConfigValueChanged += OnConfigValueChanged; - - Node.QuerySelector("#CloseButton")!.OnMouseUp += CloseWindow; - Node.QuerySelector("#CopyToClipboard")!.OnMouseUp += CopyToClipboard; - Node.QuerySelector("#PasteFromClipboard")!.OnMouseUp += PasteFromClipboard; - Node.QuerySelector("#Search")!.OnValueChanged += OnSearchValueChanged; - - Node.QuerySelector("#PasteFromClipboard")!.IsDisabled = !Manager.HasInstanceClipboardData(Instance); - - Dictionary groups = new(); - - foreach (var opt in Instance.GetConfigVariableList()) { - if (string.IsNullOrEmpty(opt.Category)) { - RenderControl(opt, ControlsListNode); - continue; - } - - if (!groups.TryGetValue(opt.Category, out Node? categoryNode)) { - categoryNode = RenderCategory(opt.Category); - groups[opt.Category] = categoryNode; - } - - RenderControl(opt, categoryNode); - } - } - - protected override void OnClose() - { - Manager.OnWidgetRemoved -= OnWidgetRemoved; - - Node.QuerySelector("#CloseButton")!.OnMouseUp -= CloseWindow; - Node.QuerySelector("#CopyToClipboard")!.OnMouseUp -= CopyToClipboard; - Node.QuerySelector("#PasteFromClipboard")!.OnMouseUp -= PasteFromClipboard; - Node.QuerySelector("#Search")!.OnValueChanged -= OnSearchValueChanged; - } - - protected override void OnUpdate(int instanceId) - { - UpdateNodeSizes(); - } - - private void OnWidgetRemoved(ToolbarWidget widget) - { - if (widget == Instance) { - Close(); - } - } - - private void OnConfigValueChanged(IWidgetConfigVariable cvar) - { - var ctrl = Node.QuerySelector($"#control-{Crc32.Get(cvar.Id)}"); - if (ctrl == null) return; - - if (cvar is IntegerWidgetConfigVariable i) { - ((IntegerInputNode)ctrl).Value = Instance.GetConfigValue(i.Id); - } else if (cvar is FloatWidgetConfigVariable f) { - ((FloatInputNode)ctrl).Value = Instance.GetConfigValue(f.Id); - } else if (cvar is StringWidgetConfigVariable s) { - ((StringInputNode)ctrl).Value = Instance.GetConfigValue(s.Id); - } else if (cvar is SelectWidgetConfigVariable l - && l.Options.ContainsKey(Instance.GetConfigValue(l.Id))) { - ((SelectNode)ctrl).Value = l.Options[Instance.GetConfigValue(l.Id)]; - } else if (cvar is BooleanWidgetConfigVariable b) { - ((CheckboxNode)ctrl).Value = Instance.GetConfigValue(b.Id); - } - } - - private void CloseWindow(Node _) - { - Close(); - } - - private void CopyToClipboard(Node _) - { - Instance.CopyInstanceSettingsToClipboard(); - } - - private void PasteFromClipboard(Node _) - { - Instance.PasteInstanceSettingsFromClipboard(); - } - - private void OnSearchValueChanged(string search) - { - foreach (var control in Node.QuerySelectorAll(".widget-config-control")) { - if (string.IsNullOrEmpty(search)) { - control.Style.IsVisible = true; - continue; - } - - Node labelNode = control.QuerySelector("#Label")!; - string labelString = labelNode.NodeValue?.ToString() ?? string.Empty; - - control.Style.IsVisible = labelString.Contains(search, System.StringComparison.OrdinalIgnoreCase); - } - - // Hide empty categories. - foreach (var category in Node.QuerySelectorAll(".widget-config-category")) { - category.Style.IsVisible = category.QuerySelector(".widget-config-category--content")!.ChildNodes.Any(x => x.Style.IsVisible == true); - } - } -}